From 4160b6e97629b064b89238785520be92d3ee1362 Mon Sep 17 00:00:00 2001 From: valentin gagarin Date: Wed, 13 Nov 2024 15:24:41 +0100 Subject: [PATCH] separate DOM mapping and generic templating the templates collection will soon only be there for reusable snippets, while the HTML representation of document types will be attached to those types directly. --- presentation/default.nix | 73 +++++++++++++++++--------------------- presentation/templates.nix | 22 ------------ structure/article.nix | 24 ++++++++++++- structure/document.nix | 8 ++--- structure/navigation.nix | 2 +- structure/page.nix | 23 +++++++++++- 6 files changed, 83 insertions(+), 69 deletions(-) delete mode 100644 presentation/templates.nix diff --git a/presentation/default.nix b/presentation/default.nix index 7410f3ca..a3435028 100644 --- a/presentation/default.nix +++ b/presentation/default.nix @@ -37,47 +37,38 @@ in type = recursiveAttrs (with types; functionTo (functionTo str)); }; - config.templates.html = - let - commonmark = name: markdown: pkgs.runCommand "${name}.html" - { - buildInputs = [ pkgs.cmark ]; - } '' - cmark ${builtins.toFile "${name}.md" markdown} > $out + config.templates.html = { + markdown = name: text: + let + commonmark = pkgs.runCommand "${name}.html" + { + buildInputs = [ pkgs.cmark ]; + } '' + cmark ${builtins.toFile "${name}.md" text} > $out + ''; + in + builtins.readFile commonmark; + nav = menu: page: + let + render-item = item: + if item ? menu then '' +
  • ${item.menu.label} + ${lib.indent " " (item.menu.outputs.html page)} +
  • + '' + else if item ? page then ''
  • ${item.page.title}
  • '' + else ''
  • ${item.link.label}
  • '' + ; + in + '' + ''; - in - { - nav = lib.mkDefault templates.nav; - page = lib.mkDefault (config: page: render-html { - html = { - head = { - title.text = page.title; - meta.description = page.description; - link.canonical = lib.head page.locations; - }; - body.content = [ - (config.menus.main.outputs.html page) - { section.heading.content = page.title; } - (builtins.readFile (commonmark page.name page.body)) - ]; - }; - }); - article = lib.mkDefault (config: page: render-html { - html = { - head = { - title.text = page.title; - meta.description = page.description; - meta.authors = if lib.isList page.author then page.author else [ page.author ]; - link.canonical = lib.head page.locations; - }; - body.content = [ - (config.menus.main.outputs.html page) - { section.heading.content = page.title; } - (builtins.readFile (commonmark page.name page.body)) - ]; - }; - }); - }; + + }; options.files = mkOption { description = '' @@ -86,6 +77,8 @@ in By default, all elements in `option`{pages} are converted to files using their template or the default template. Add more files to the output by assigning to this attribute set. ''; + # TODO: this should be attrsOf string-coercible instead. + # we can convert this to file at the very end. type = with types; attrsOf path; }; diff --git a/presentation/templates.nix b/presentation/templates.nix deleted file mode 100644 index c0d7f652..00000000 --- a/presentation/templates.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ lib }: -rec { - nav = menu: page: - let - render-item = item: - if item ? menu then '' -
  • ${item.menu.label} - ${lib.indent " " (item.menu.outputs.html page)} -
  • - '' - else if item ? page then ''
  • ${item.page.title}
  • '' - else ''
  • ${item.link.label}
  • '' - ; - in - '' - - ''; -} diff --git a/structure/article.nix b/structure/article.nix index ca7495df..aac3a398 100644 --- a/structure/article.nix +++ b/structure/article.nix @@ -5,6 +5,14 @@ let types ; cfg = config; + render-html = document: + let + eval = lib.evalModules { + class = "DOM"; + modules = [ document (import ../presentation/dom.nix) ]; + }; + in + toString eval.config; in { content-types.article = { config, collection, ... }: { @@ -27,6 +35,20 @@ in }; }; config.name = lib.slug config.title; - config.outputs.html = lib.mkForce (cfg.templates.html.article cfg config); + config.outputs.html = lib.mkForce (render-html { + html = { + head = { + title.text = config.title; + meta.description = config.description; + meta.authors = if lib.isList config.author then config.author else [ config.author ]; + link.canonical = lib.head config.locations; + }; + body.content = [ + (cfg.menus.main.outputs.html config) + { section.heading.content = config.title; } + (cfg.templates.html.markdown config.name config.body) + ]; + }; + }); }; } diff --git a/structure/document.nix b/structure/document.nix index 8af04c36..dd3718d5 100644 --- a/structure/document.nix +++ b/structure/document.nix @@ -45,13 +45,13 @@ in # names is soft. default = target: with lib; "${relativePath (head config.locations) (head target.locations)}.html"; }; - outputs = mkOption { - # TODO: figure out how to make this overridable at any granularity. - # it should be possible with the DOM module now. + outputs.html = mkOption { + # TODO: make this of type DOM and convert to string at the output. + # the output aggregator then only needs something string-coercible description = '' Representations of the document in different formats ''; - type = with types; attrsOf str; + type = with types; str; }; }; }; diff --git a/structure/navigation.nix b/structure/navigation.nix index a3d78360..97ae9480 100644 --- a/structure/navigation.nix +++ b/structure/navigation.nix @@ -56,7 +56,7 @@ in It must be a function that takes the page on which the navigation is to be shown, such that relative links get computed correctly. ''; type = with types; attrsOf (functionTo str); - default.html = cfg.templates.html.nav { menu = config; }; + default.html = cfg.templates.html.nav config; }; }; }; diff --git a/structure/page.nix b/structure/page.nix index d76954e1..a4352f12 100644 --- a/structure/page.nix +++ b/structure/page.nix @@ -5,6 +5,14 @@ let types ; cfg = config; + render-html = document: + let + eval = lib.evalModules { + class = "DOM"; + modules = [ document (import ../presentation/dom.nix) ]; + }; + in + toString eval.config; in { content-types.page = { name, config, ... }: { @@ -34,6 +42,19 @@ in type = types.str; }; }; - config.outputs.html = cfg.templates.html.page cfg config; + config.outputs.html = render-html { + html = { + head = { + title.text = config.title; + meta.description = config.description; + link.canonical = lib.head config.locations; + }; + body.content = [ + (cfg.menus.main.outputs.html config) + { section.heading.content = config.title; } + (cfg.templates.html.markdown config.name config.body) + ]; + }; + }; }; }