make page templates granularly overridable

This commit is contained in:
Valentin Gagarin 2024-11-13 15:24:41 +01:00
parent 648227d1b6
commit 4762618956
8 changed files with 49 additions and 51 deletions

View file

@ -1,13 +1,14 @@
{ config, lib, ... }: { config, lib, ... }:
let let
inherit (config) pages; inherit (config) pages;
cfg = config;
in in
{ {
imports = lib.nixFiles ./.; imports = lib.nixFiles ./.;
collections.news.type = config.content-types.article; collections.news.type = cfg.content-types.article;
pages.index = { link, ... }: { pages.index = { config, link, ... }: {
title = "Fediversity"; title = "Fediversity";
description = "Fediversity web site"; description = "Fediversity web site";
summary = '' summary = ''
@ -52,12 +53,19 @@ in
${ ${
let let
sorted = with lib; reverseList (sortOn (entry: entry.date) config.collections.news.entry); sorted = with lib; reverseList (sortOn (entry: entry.date) cfg.collections.news.entry);
in in
lib.join "\n" (map (article: '' lib.join "\n" (map (article: ''
- ${article.date} [${article.title}](${link article}) - ${article.date} [${article.title}](${link article})
'') sorted) '') sorted)
} }
''; '';
outputs.html = (cfg.templates.html.page config).override {
html.body.content = lib.mkForce [
# don't show the page title as a heading
(cfg.menus.main.outputs.html config)
(cfg.templates.html.markdown { inherit (config) name body; })
];
};
}; };
} }

View file

@ -1,5 +1,8 @@
{ lib }: { lib }:
rec { rec {
template = g: f: x:
(g (f x)) // { override = o: g (lib.recursiveUpdate (f x) o); };
/** /**
Recursively replace occurrences of `from` with `to` within `string` Recursively replace occurrences of `from` with `to` within `string`

View file

@ -21,7 +21,7 @@ in
description = '' description = ''
Collection of named helper functions for conversion different structured representations which can be rendered to a string Collection of named helper functions for conversion different structured representations which can be rendered to a string
''; '';
type = recursiveAttrs (with types; functionTo (coercedTo attrs toString str)); type = recursiveAttrs (with types; functionTo (either str attrs));
}; };
options.files = mkOption { options.files = mkOption {

View file

@ -4,19 +4,21 @@ let
mkOption mkOption
types types
; ;
# TODO: optionally run the whole thing through the validator
# https://github.com/validator/validator
render-html = document:
let
eval = lib.evalModules {
class = "DOM";
modules = [ document (import ./dom.nix) ];
};
in
toString eval.config;
in in
{ {
config.templates.html = { config.templates.html = {
dom = document:
let
eval = lib.evalModules {
class = "DOM";
modules = [ document (import ./dom.nix) ];
};
in
{
__toString = _: toString eval.config;
value = eval.config;
};
markdown = { name, body }: markdown = { name, body }:
let let
commonmark = pkgs.runCommand "${name}.html" commonmark = pkgs.runCommand "${name}.html"

View file

@ -5,14 +5,6 @@ let
types types
; ;
cfg = config; cfg = config;
render-html = document:
let
eval = lib.evalModules {
class = "DOM";
modules = [ document (import ../presentation/dom.nix) ];
};
in
toString eval.config;
in in
{ {
content-types.article = { config, collection, ... }: { content-types.article = { config, collection, ... }: {
@ -35,7 +27,7 @@ in
}; };
}; };
config.name = lib.slug config.title; config.name = lib.slug config.title;
config.outputs.html = lib.mkForce (render-html { config.outputs.html = lib.mkForce (cfg.templates.html.dom {
html = { html = {
head = { head = {
title.text = config.title; title.text = config.title;

View file

@ -68,7 +68,7 @@ in
in in
with lib; foldl with lib; foldl
(acc: elem: acc // { (acc: elem: acc // {
"${head elem.locations}.html" = builtins.toFile "${elem.name}.html" elem.outputs.html; "${head elem.locations}.html" = builtins.toFile "${elem.name}.html" "${elem.outputs.html}";
}) })
{ } { }
collections; collections;

View file

@ -53,13 +53,11 @@ in
# names is soft. # names is soft.
default = target: with lib; "${relativePath (head config.locations) (head target.locations)}.html"; default = target: with lib; "${relativePath (head config.locations) (head target.locations)}.html";
}; };
outputs.html = mkOption { outputs = mkOption {
# TODO: make this of type DOM and convert to string at the output.
# the output aggregator then only needs something string-coercible
description = '' description = ''
Representations of the document in different formats Representations of the document in different formats
''; '';
type = with types; str; type = with types; attrsOf (either str attrs);
}; };
}; };
}; };

View file

@ -5,14 +5,6 @@ let
types types
; ;
cfg = config; cfg = config;
render-html = document:
let
eval = lib.evalModules {
class = "DOM";
modules = [ document (import ../presentation/dom.nix) ];
};
in
toString eval.config;
in in
{ {
# TODO: enable i18n, e.g. via a nested attribute for language-specific content # TODO: enable i18n, e.g. via a nested attribute for language-specific content
@ -27,7 +19,7 @@ in
(acc: elem: acc // { (acc: elem: acc // {
# TODO: create static redirects from `tail page.locations` # TODO: create static redirects from `tail page.locations`
# TODO: the file name could correspond to the canonical location in the HTML representation # TODO: the file name could correspond to the canonical location in the HTML representation
"${head elem.locations}.html" = builtins.toFile "${elem.name}.html" elem.outputs.html; "${head elem.locations}.html" = builtins.toFile "${elem.name}.html" "${elem.outputs.html}";
}) })
{ } { }
(attrValues config.pages); (attrValues config.pages);
@ -59,19 +51,22 @@ in
type = types.str; type = types.str;
}; };
}; };
config.outputs.html = render-html {
html = { config.outputs.html = cfg.templates.html.page config;
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 { inherit (config) name body; })
];
};
};
}; };
config.templates.html.page = lib.template cfg.templates.html.dom (page: {
html = {
head = {
title.text = page.title;
meta.description = page.description;
link.canonical = lib.head page.locations;
};
body.content = [
(cfg.menus.main.outputs.html page)
{ section.heading.content = page.title; }
(cfg.templates.html.markdown { inherit (page) name body; })
];
};
});
} }