diff --git a/css.nix b/css.nix index 1026ce3..c161ad8 100644 --- a/css.nix +++ b/css.nix @@ -1,19 +1,43 @@ -{utils}: let - inherit (utils) mapAttrsToList concatStringsSep isList toString map; +{lib, ...}: let + l = lib // builtins; + t = l.types; evalCssValue = value: - if isList value - then concatStringsSep ", " (map toString value) - else toString value; - evalInner = inner: concatStringsSep " " (mapAttrsToList (name: value: "${name}: ${evalCssValue value};") inner); - css = maybeAttrs: - if isList maybeAttrs - then concatStringsSep " " maybeAttrs - else concatStringsSep " " (mapAttrsToList (name: inner: "${name} { ${evalInner inner} }") maybeAttrs); + if l.isList value + then l.concatStringsSep ", " (l.map toString value) + else l.toString value; + evalInner = inner: + l.concatStringsSep + " " + ( + l.mapAttrsToList + (name: value: "${name}: ${evalCssValue value};") + inner + ); + eval = maybeAttrs: + if l.isList maybeAttrs + then l.concatStringsSep " " maybeAttrs + else + l.concatStringsSep + " " + ( + l.mapAttrsToList + (name: inner: "${name} { ${evalInner inner} }") + maybeAttrs + ); + css = { + __functor = self: arg: eval arg; + media = rule: inner: '' + @media (${rule}) { ${eval inner} } + ''; + }; in { - inherit css; - - media = rule: inner: '' - @media (${rule}) { ${css inner} } - ''; + options = { + html-nix.lib.css = l.mkOption { + type = t.functionTo t.str; + }; + }; + config = { + html-nix.lib.css = css; + }; } diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..71e44ce --- /dev/null +++ b/default.nix @@ -0,0 +1,8 @@ +{ + imports = [ + ./html.nix + ./css.nix + ./pkgs-lib.nix + ./templaters/default.nix + ]; +} diff --git a/examples/flake.nix b/examples/flake.nix new file mode 100644 index 0000000..91eed36 --- /dev/null +++ b/examples/flake.nix @@ -0,0 +1,15 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + parts.url = "github:hercules-ci/flake-parts"; + }; + + outputs = inp: + inp.parts.lib.mkFlake {inputs = inp;} { + systems = ["x86_64-linux"]; + imports = [ + ../default.nix + ./site.nix + ]; + }; +} diff --git a/examples/serve.nix b/examples/serve.nix deleted file mode 100644 index c04ff72..0000000 --- a/examples/serve.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ - tags, - pkgs, -}: -with pkgs.htmlNix; let - index = with tags; - html [ - (body [ - (p "Hello world!") - (mkLink "./ex.html" "say bye") - ]) - ]; - - ex = with tags; - html [ - (body [ - (p "Bye world!") - (mkLink "./index.html" "go back") - ]) - ]; - - site = { - "index.html" = index; - "ex.html" = ex; - }; -in - mkServeFromSite site diff --git a/examples/site.nix b/examples/site.nix index 332b0cd..671b62f 100644 --- a/examples/site.nix +++ b/examples/site.nix @@ -1,12 +1,12 @@ { - pkgs, - lib, -}: let - inherit (pkgs) htmlNix; - src = ./site; -in - htmlNix.mkServeFromSite (htmlNix.mkSiteFrom { - inherit src; - templater = lib.templaters.basic; - local = true; - }) + perSystem = {config, ...}: let + html-nix = config.html-nix; + siteServe = html-nix.mkServeFromSite (html-nix.mkSiteFrom { + src = ./site; + templater = html-nix.lib.templaters.basic; + local = true; + }); + in { + apps.site.program = "${siteServe}/bin/serve"; + }; +} diff --git a/examples/tags.nix b/examples/tags.nix deleted file mode 100644 index 2909c09..0000000 --- a/examples/tags.nix +++ /dev/null @@ -1,8 +0,0 @@ -tags: -with tags; - html [ - (body [ - (p "Hello,") - (p "world!") - ]) - ] diff --git a/flake.lock b/flake.lock index 22ac262..15d95dd 100644 --- a/flake.lock +++ b/flake.lock @@ -1,27 +1,28 @@ { "nodes": { - "flakeUtils": { + "examples": { + "inputs": { + "nixpkgs": "nixpkgs", + "parts": "parts" + }, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", - "type": "github" + "lastModified": 1, + "narHash": "sha256-agjsV0F6nVUimGUciKlOSF35XvTOQKKEez0xZ8X0JBI=", + "path": "./examples", + "type": "path" }, "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" + "path": "./examples", + "type": "path" } }, "nixpkgs": { "locked": { - "lastModified": 1644972330, - "narHash": "sha256-6V2JFpTUzB9G+KcqtUR1yl7f6rd9495YrFECslEmbGw=", + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "19574af0af3ffaf7c9e359744ed32556f34536bd", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", "type": "github" }, "original": { @@ -31,10 +32,99 @@ "type": "github" } }, + "nixpkgs-lib": { + "locked": { + "dir": "lib", + "lastModified": 1680213900, + "narHash": "sha256-cIDr5WZIj3EkKyCgj/6j3HBH4Jj1W296z7HTcWj1aMA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e3652e0735fbec227f342712f180f4f21f0594f2", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib_2": { + "locked": { + "dir": "lib", + "lastModified": 1680213900, + "narHash": "sha256-cIDr5WZIj3EkKyCgj/6j3HBH4Jj1W296z7HTcWj1aMA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e3652e0735fbec227f342712f180f4f21f0594f2", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1680392223, + "narHash": "sha256-n3g7QFr85lDODKt250rkZj2IFS3i4/8HBU2yKHO3tqw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "dcc36e45d054d7bb554c9cdab69093debd91a0b5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "parts_2": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_2" + }, + "locked": { + "lastModified": 1680392223, + "narHash": "sha256-n3g7QFr85lDODKt250rkZj2IFS3i4/8HBU2yKHO3tqw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "dcc36e45d054d7bb554c9cdab69093debd91a0b5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "root": { "inputs": { - "flakeUtils": "flakeUtils", - "nixpkgs": "nixpkgs" + "examples": "examples", + "nixpkgs": "nixpkgs_2", + "parts": "parts_2" } } }, diff --git a/flake.nix b/flake.nix index 6bf2787..a58a298 100644 --- a/flake.nix +++ b/flake.nix @@ -1,57 +1,17 @@ { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - flakeUtils.url = "github:numtide/flake-utils"; + parts.url = "github:hercules-ci/flake-parts"; + examples.url = "path:./examples"; }; - outputs = { - self, - flakeUtils, - nixpkgs, - }: let - utils = import ./utils.nix; - - lib = { - # Convert Nix expressions to HTML - tags = import ./tags.nix {inherit utils;}; - # Convert Nix expressions to CSS - css = import ./css.nix {inherit utils;}; - - # Various site templaters - templaters = { - # Basic templater with purecss, mobile responsive layout and supports posts - basic = import ./templaters/basic.nix; + outputs = inp: + inp.parts.lib.mkFlake {inputs = inp;} { + debug = true; + systems = ["x86_64-linux"]; + flake = { + flakeModule = ./default.nix; + inherit (inp.examples) apps; }; }; - - outputs = flakeUtils.lib.eachDefaultSystem (system: let - pkgs = nixpkgs.legacyPackages.${system}; - in { - lib = { - pkgsLib = import ./pkgs-lib.nix { - inherit pkgs; - utils = utils // {inherit (lib) tags css;}; - }; - }; - - apps = with flakeUtils.lib; { - site = mkApp { - drv = import ./examples/site.nix {inherit lib pkgs;}; - name = "serve"; - }; - basicServe = mkApp { - drv = import ./examples/serve.nix { - inherit (lib) tags; - inherit pkgs; - }; - name = "serve"; - }; - }; - - examples = { - tags = import ./examples/tags.nix lib.tags; - }; - }); - in - outputs // {lib = outputs.lib // lib;}; } diff --git a/html.nix b/html.nix new file mode 100644 index 0000000..6bb43d0 --- /dev/null +++ b/html.nix @@ -0,0 +1,49 @@ +{lib, ...}: let + l = lib // builtins; + + evalAttrs = attrs: + l.concatStrings + ( + l.mapAttrsToList + (name: value: " ${name}=\"${value}\"") + attrs + ); + evalChildren = children: + if l.isList children + then l.concatStrings children + else children; + tag = name: maybeAttrs: + if l.isAttrs maybeAttrs + then (children: "<${name}${evalAttrs maybeAttrs}>${evalChildren children}") + else tag name {} maybeAttrs; + noChildrenTag = name: attrs: "<${name} ${evalAttrs attrs}>"; + + tagsToGen = + (l.map (n: "h${toString n}") (l.range 1 6)) + ++ ["ul" "li" "html" "head" "body" "div" "p"] + ++ ["a" "title" "code" "pre" "nav" "article" "script"]; + tags = l.genAttrs tag tagsToGen; + + noChildrenTagsToGen = ["link" "meta"]; + noChildrenTags = l.genAttrs noChildrenTag noChildrenTagsToGen; +in { + options = { + html-nix.lib.html = l.mkOption { + type = l.types.raw; + }; + }; + config = { + html-nix.lib.html = + tags + // noChildrenTags + // { + inherit tag; + mkLink = url: tags.a {href = url;}; + mkStylesheet = url: + noChildrenTags.link { + rel = "stylesheet"; + href = url; + }; + }; + }; +} diff --git a/pkgs-lib.nix b/pkgs-lib.nix index 28489d7..3801eab 100644 --- a/pkgs-lib.nix +++ b/pkgs-lib.nix @@ -1,97 +1,117 @@ { - utils, - pkgs, + lib, + flake-parts-lib, + ... }: let - pkgBin = name: "${pkgs.${name}}/bin/${name}"; - - mkServePathScript = path: - pkgs.writeScriptBin "serve" '' - ${pkgs.nodePackages.http-server}/bin/http-server -c-1 ${path} - ''; - - mkSitePath = site: let - inherit (utils) recursiveAttrPaths concatStringsSep map; - inherit (pkgs.lib) mapAttrsRecursive init last getAttrFromPath; - - convertToPath = path: value: - if builtins.isPath value - then value - else pkgs.writeText (concatStringsSep "-" path) value; - fileAttrPaths = recursiveAttrPaths site; - texts = mapAttrsRecursive convertToPath site; - mkCreateFileCmd = path: value: let p = concatStringsSep "/" (init path); in "mkdir -p \"$out/${p}\" && ln -s \"${value}\" \"$out/${p}/${last path}\""; - createFileCmds = map (path: mkCreateFileCmd path (getAttrFromPath path texts)) fileAttrPaths; - in - pkgs.runCommandLocal "site-path" {} '' - mkdir -p $out - ${concatStringsSep "\n" createFileCmds} - ''; - - parseMarkdown = name: contents: - pkgs.runCommandLocal name {} '' - printf ${pkgs.lib.escapeShellArg contents} | ${pkgBin "pandoc"} -f gfm > $out - ''; + l = lib // builtins; in { - inherit mkServePathScript mkSitePath parseMarkdown; + options = { + perSystem = + flake-parts-lib.mkPerSystemOption + ({...}: { + html-nix.lib = { + mkServeFromSite = l.mkOption { + type = with l.types; functionTo package; + }; + mkSiteFrom = l.mkOption { + type = with l.types; functionTo attrs; + }; + }; + }); + }; + config = { + perSystem = {pkgs, ...}: let + pkgBin = name: "${pkgs.${name}}/bin/${name}"; - mkServeFromSite = site: mkServePathScript (mkSitePath site); - mkSiteFrom = { - src, - templater, - local ? false, - }: let - inherit (utils) readDir readFile fromTOML mapAttrsToList sort elemAt; - inherit (pkgs.lib) nameValuePair head splitString pipe removeSuffix mapAttrs'; - - postsRendered = let - path = src + "/posts"; - in - pipe (readDir path) [ - (mapAttrsToList ( - name: _: - nameValuePair - (head (splitString "." name)) - (readFile (parseMarkdown name (readFile (path + "/${name}")))) - )) - (sort ( - p: op: let - extractDate = name: splitString "-" (head (splitString "_" name)); - getPart = name: el: removeSuffix "0" (elemAt (extractDate name) el); - d = getPart p.name; - od = getPart op.name; - in - !(((d 0) > (od 0)) && ((d 1) > (od 1)) && ((d 2) > (od 2))) - )) - ]; - pagesRendered = let - path = src + "/pages"; - in - mapAttrs' - ( - name: _: - nameValuePair - (head (splitString "." name)) - (readFile (parseMarkdown name (readFile (path + "/${name}")))) - ) - (readDir path); - siteConfig = fromTOML (readFile (src + "/config.toml")); - baseurl = - if local - then "http://localhost:8080" - else siteConfig.baseurl or (throw "Need baseurl"); - - context = { - inherit utils pkgs baseurl; - config = siteConfig; - posts = postsRendered; - pages = pagesRendered; - site = { - "robots.txt" = '' - User-agent: * - Allow: / + mkServePathScript = path: + pkgs.writeScriptBin "serve" '' + ${pkgs.nodePackages.http-server}/bin/http-server -c-1 ${path} ''; + + mkSitePath = site: let + convertToPath = path: value: + if builtins.isPath value + then value + else pkgs.writeText (l.concatStringsSep "-" path) value; + fileAttrPaths = l.recursiveAttrPaths site; + texts = l.mapAttrsRecursive convertToPath site; + mkCreateFileCmd = path: value: let + p = l.concatStringsSep "/" (l.init path); + in "mkdir -p \"$out/${p}\" && ln -s \"${value}\" \"$out/${p}/${l.last path}\""; + createFileCmds = + l.map + (path: mkCreateFileCmd path (l.getAttrFromPath path texts)) + fileAttrPaths; + in + pkgs.runCommandLocal "site-path" {} '' + mkdir -p $out + ${l.concatStringsSep "\n" createFileCmds} + ''; + + parseMarkdown = name: contents: + pkgs.runCommandLocal name {} '' + printf ${l.escapeShellArg contents} | ${pkgBin "pandoc"} -f gfm > $out + ''; + in { + html-nix.lib = { + mkServeFromSite = site: mkServePathScript (mkSitePath site); + mkSiteFrom = { + src, + templater, + local ? false, + }: let + postsRendered = let + path = src + "/posts"; + in + l.pipe (l.readDir path) [ + (l.mapAttrsToList ( + name: _: + l.nameValuePair + (l.head (l.splitString "." name)) + (l.readFile (parseMarkdown name (l.readFile (path + "/${name}")))) + )) + (l.sort ( + p: op: let + extractDate = name: l.splitString "-" (l.head (l.splitString "_" name)); + getPart = name: el: l.removeSuffix "0" (l.elemAt (extractDate name) el); + d = getPart p.name; + od = getPart op.name; + in + !(((d 0) > (od 0)) && ((d 1) > (od 1)) && ((d 2) > (od 2))) + )) + ]; + pagesRendered = let + path = src + "/pages"; + in + l.mapAttrs' + ( + name: _: + l.nameValuePair + (l.head (l.splitString "." name)) + (l.readFile (parseMarkdown name (l.readFile (path + "/${name}")))) + ) + (l.readDir path); + siteConfig = l.fromTOML (l.readFile (src + "/config.toml")); + baseurl = + if local + then "http://localhost:8080" + else siteConfig.baseurl or (throw "Need baseurl"); + + context = { + inherit lib baseurl; + config = siteConfig; + posts = postsRendered; + pages = pagesRendered; + site = { + "robots.txt" = '' + User-agent: * + Allow: / + ''; + }; + }; + in + (templater context).site; }; }; - in - (templater context).site; + }; } diff --git a/tags.nix b/tags.nix deleted file mode 100644 index 1f4e425..0000000 --- a/tags.nix +++ /dev/null @@ -1,34 +0,0 @@ -{utils}: let - inherit (utils) concatStrings mapAttrsToList genAttrs isAttrs isList range toString; - - evalAttrs = attrs: concatStrings (mapAttrsToList (name: value: " ${name}=\"${value}\"") attrs); - evalChildren = children: - if isList children - then concatStrings children - else children; - tag = name: maybeAttrs: - if isAttrs maybeAttrs - then (children: "<${name}${evalAttrs maybeAttrs}>${evalChildren children}") - else tag name {} maybeAttrs; - noChildrenTag = name: attrs: "<${name} ${evalAttrs attrs}>"; - - tagsToGen = - (map (n: "h${toString n}") (range 1 6)) - ++ ["ul" "li" "html" "head" "body" "div" "p"] - ++ ["a" "title" "code" "pre" "nav" "article" "script"]; - tags = genAttrs tag tagsToGen; - - noChildrenTagsToGen = ["link" "meta"]; - noChildrenTags = genAttrs noChildrenTag noChildrenTagsToGen; -in - tags - // noChildrenTags - // { - inherit tag; - mkLink = url: tags.a {href = url;}; - mkStylesheet = url: - noChildrenTags.link { - rel = "stylesheet"; - href = url; - }; - } diff --git a/templaters/basic.nix b/templaters/basic.nix index d552463..d370919 100644 --- a/templaters/basic.nix +++ b/templaters/basic.nix @@ -1,207 +1,222 @@ { - utils, - posts, - pkgs, config, - pages, - site, - baseurl, + lib, ... -} @ context: let - inherit (utils) readFile mapAttrsToList mapAttrs tags fetchGit map elemAt foldl' concatStrings genAttrs toString; - inherit (pkgs.lib) optionalString optionalAttrs optional length splitString nameValuePair toInt range mapAttrs' singleton; - inherit (builtins) listToAttrs; +}: let + l = lib // builtins; + t = l.types; + inherit (config.html-nix.lib) html css; - stylesheets = map tags.mkStylesheet [ - "https://unpkg.com/purecss@2.0.6/build/pure-min.css" - "https://unpkg.com/purecss@2.0.6/build/grids-responsive-min.css" - "${baseurl}/site.css" - ]; + func = ctx: let + stylesheets = l.map html.mkStylesheet [ + "https://unpkg.com/purecss@3.0.0/build/pure-min.css" + "https://unpkg.com/purecss@3.0.0/build/grids-responsive-min.css" + "${ctx.baseurl}/site.css" + ]; - parsePostName = name: let - parts = splitString "_" name; - id = elemAt parts 1; - date = elemAt parts 0; - in { - inherit id date; - formatted = "${date} - ${id}"; - }; + parsePostName = name: let + parts = l.splitString "_" name; + id = l.elemAt parts 1; + date = l.elemAt parts 0; + in { + inherit id date; + formatted = "${date} - ${id}"; + }; - renderPost = { - name, - value, - }: let - parsed = parsePostName name; - inherit (parsed) id date; - in - with tags; - article [ - (a { - href = "#${id}"; - class = "postheader"; - } (h2 {inherit id;} id)) - (h3 ("date: " + date)) - value + renderPost = { + name, + value, + }: let + parsed = parsePostName name; + inherit (parsed) id date; + in + with html; + article [ + (a { + href = "#${id}"; + class = "postheader"; + } (h2 {inherit id;} id)) + (h3 ("date: " + date)) + value + ]; + + pagesSection = with html; + [ + (div {class = "pure-u-1";} (a { + href = "${ctx.baseurl}/"; + class = "pagelink"; + } "home")) + ] + ++ (l.map + (name: + div {class = "pure-u-1";} (a { + href = "${ctx.baseurl}/${name}/"; + class = "pagelink"; + } + name)) + (l.mapAttrsToList (name: _: name) pages)) + ++ [ + (div {class = "pure-u-1";} (a { + href = "${ctx.baseurl}/posts/"; + class = "pagelink"; + } "posts")) ]; - pagesSection = - [ - (tags.div {class = "pure-u-1";} (tags.a { - href = "${baseurl}/"; - class = "pagelink"; - } "home")) - ] - ++ (map - (name: - tags.div {class = "pure-u-1";} (tags.a { - href = "${baseurl}/${name}/"; - class = "pagelink"; - } - name)) - (mapAttrsToList (name: _: name) pages)) - ++ [ - (tags.div {class = "pure-u-1";} (tags.a { - href = "${baseurl}/posts/"; - class = "pagelink"; - } "posts")) - ]; + postsLinks = with html; + singleton + (ul ( + l.map + ( + post: + li ( + a {href = "${ctx.baseurl}/${post.name}";} + (parsePostName post.name).formatted + ) + ) + posts + )); - postsRendered = map renderPost posts; - - postsLinks = with tags; - singleton - (ul ( - map - ( - post: - li ( - a {href = "${baseurl}/${post.name}";} - (parsePostName post.name).formatted - ) - ) - posts - )); - - postsSectionContent = with tags; - [ - (a { - href = "#posts"; - class = "postheader"; - } (h1 "posts")) - ] - ++ postsLinks; - - sidebarSection = optionalString ((length pagesSection) > 0) ( - with tags; - nav {class = "sidebar";} [ - (div {class = "pure-g";} pagesSection) + postsSectionContent = with html; + [ + (a { + href = "#posts"; + class = "postheader"; + } (h1 "posts")) ] - ); + ++ postsLinks; - mkPage = content: - with tags; '' - - ${html [ - (head (stylesheets - ++ [ - (title config.title) - (meta { - name = "viewport"; - content = "width=device-width, initial-scale=1"; - }) - ])) - (body '' - ${script "0"} - ${sidebarSection} - ${div {class = "content";} content} - '') - ]} - ''; - - indexPage = mkPage (context.indexContent or postsSectionContent); - - pagesAndPosts = - pages - // listToAttrs ( - map (post: nameValuePair post.name (renderPost post)) posts + sidebarSection = l.optionalString ((l.length pagesSection) > 0) ( + with html; + nav {class = "sidebar";} [ + (div {class = "pure-g";} pagesSection) + ] ); - stylesheet = with utils.css; let - marginMobile = { - margin-left = "3%"; - margin-right = "3%"; - }; - in - css [ - (css ( - ( - mapAttrs' - (name: value: nameValuePair value {content = "\"${concatStrings (map (_: "#") (range 1 (toInt name)))} \"";}) - (genAttrs (n: "h${toString n}:before") (map toString (range 1 6))) - ) - // { - body = { - font-family = ["Raleway" "Helvetica" "Arial" "sans-serif"]; - background = "#111111"; - color = "#eeeeee"; - }; - pre = { - font-family = ["Iosevka Term" "Iosevka" "monospace"]; - background = "#171A21"; - color = "#eeeeee"; - }; - "a,a:hover" = { - color = "#ffd814"; - text-decoration = "none"; - }; - "a:hover" = { - text-decoration = "underline"; - }; - "a.postheader,a.postheader:hover" = { - color = "#fc6711"; - }; - "a.pagelink,a.pagelink:hover" = { - color = "#ffd814"; - }; - "div.content" = { - margin-top = "5%"; - margin-bottom = "5%"; - margin-left = "20%"; - margin-right = "25%"; - }; - "nav.sidebar" = { - position = "fixed"; - margin-left = "3%"; - padding-top = 0; - z-index = 1000; - }; - } - )) - (media "max-width: 48em" { - "nav.sidebar" = - { - position = "relative"; - margin-top = "5%"; - } - // marginMobile; - "div.content" = - { - margin-top = 0; - } - // marginMobile; - }) - ]; -in { - inherit stylesheets sidebarSection mkPage stylesheet; + mkPage = content: + with html; '' + + ${html [ + (head (stylesheets + ++ [ + (title ctx.config.title) + (meta { + name = "viewport"; + content = "width=device-width, initial-scale=1"; + }) + ])) + (body '' + ${script "0"} + ${sidebarSection} + ${div {class = "content";} content} + '') + ]} + ''; - site = - site - // { - "index.html" = indexPage; - "posts"."index.html" = mkPage postsSectionContent; - "404.html" = mkPage (tags.h1 "No such page"); - "site.css" = stylesheet; - } - // (mapAttrs (name: value: {"index.html" = mkPage value;}) pagesAndPosts) - // optionalAttrs (context ? resources) {inherit (context) resources;}; + indexPage = mkPage (ctx.indexContent or postsSectionContent); + + pagesAndPosts = + ctx.pages + // l.listToAttrs ( + map (post: l.nameValuePair post.name (renderPost post)) ctx.posts + ); + + stylesheet = let + marginMobile = { + margin-left = "3%"; + margin-right = "3%"; + }; + in + css [ + (css ( + ( + l.mapAttrs' + ( + name: value: + l.nameValuePair + value + { + content = "\"${l.concatStrings (l.map (_: "#") (l.range 1 (l.toInt name)))} \""; + } + ) + ( + l.genAttrs + (n: "h${l.toString n}:before") + (l.map l.toString (l.range 1 6)) + ) + ) + // { + body = { + font-family = ["Raleway" "Helvetica" "Arial" "sans-serif"]; + background = "#111111"; + color = "#eeeeee"; + }; + pre = { + font-family = ["Iosevka Term" "Iosevka" "monospace"]; + background = "#171A21"; + color = "#eeeeee"; + }; + "a,a:hover" = { + color = "#ffd814"; + text-decoration = "none"; + }; + "a:hover" = { + text-decoration = "underline"; + }; + "a.postheader,a.postheader:hover" = { + color = "#fc6711"; + }; + "a.pagelink,a.pagelink:hover" = { + color = "#ffd814"; + }; + "div.content" = { + margin-top = "5%"; + margin-bottom = "5%"; + margin-left = "20%"; + margin-right = "25%"; + }; + "nav.sidebar" = { + position = "fixed"; + margin-left = "3%"; + padding-top = 0; + z-index = 1000; + }; + } + )) + (css.media "max-width: 48em" { + "nav.sidebar" = + { + position = "relative"; + margin-top = "5%"; + } + // marginMobile; + "div.content" = + { + margin-top = 0; + } + // marginMobile; + }) + ]; + in { + inherit stylesheets sidebarSection mkPage stylesheet; + + site = + ctx.site + // { + "index.html" = indexPage; + "posts"."index.html" = mkPage postsSectionContent; + "404.html" = mkPage (html.h1 "No such page"); + "site.css" = stylesheet; + } + // (l.mapAttrs (name: value: {"index.html" = mkPage value;}) pagesAndPosts) + // l.optionalAttrs (ctx ? resources) {inherit (ctx) resources;}; + }; +in { + options = { + html-nix.lib.templaters.basic = l.mkOption { + type = t.functionTo t.attrs; + }; + }; + config = { + html-nix.lib.templaters.basic = func; + }; } diff --git a/templaters/default.nix b/templaters/default.nix new file mode 100644 index 0000000..f9bc9f7 --- /dev/null +++ b/templaters/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./basic.nix + ]; +} diff --git a/utils.nix b/utils.nix deleted file mode 100644 index 2b8af61..0000000 --- a/utils.nix +++ /dev/null @@ -1,38 +0,0 @@ -let - inherit (builtins) isAttrs isList map any concatMap concatStringsSep listToAttrs genList; - - mapAttrsToList = f: attrs: map (name: f name attrs.${name}) (builtins.attrNames attrs); -in - { - inherit mapAttrsToList; - - recursiveAttrPaths = set: let - flattenIfHasList = x: - if (isList x) && (any isList x) - then concatMap flattenIfHasList x - else [x]; - - recurse = path: set: let - g = name: value: - if isAttrs value - then recurse (path ++ [name]) value - else path ++ [name]; - in - mapAttrsToList g set; - in - flattenIfHasList (recurse [] set); - - concatStrings = concatStringsSep ""; - genAttrs = f: names: - listToAttrs (map (n: { - name = n; - value = f n; - }) - names); - - range = first: last: - if first > last - then [] - else genList (n: first + n) (last - first + 1); - } - // builtins