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, ... }:
let
inherit (config) pages;
cfg = config;
in
{
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";
description = "Fediversity web site";
summary = ''
@ -52,12 +53,19 @@ in
${
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
lib.join "\n" (map (article: ''
- ${article.date} [${article.title}](${link article})
'') 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 }:
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`

View file

@ -21,7 +21,7 @@ in
description = ''
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 {

View file

@ -4,19 +4,21 @@ let
mkOption
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
{
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 }:
let
commonmark = pkgs.runCommand "${name}.html"

View file

@ -5,14 +5,6 @@ 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, ... }: {
@ -35,7 +27,7 @@ in
};
};
config.name = lib.slug config.title;
config.outputs.html = lib.mkForce (render-html {
config.outputs.html = lib.mkForce (cfg.templates.html.dom {
html = {
head = {
title.text = config.title;

View file

@ -68,7 +68,7 @@ in
in
with lib; foldl
(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;

View file

@ -53,13 +53,11 @@ in
# names is soft.
default = target: with lib; "${relativePath (head config.locations) (head target.locations)}.html";
};
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
outputs = mkOption {
description = ''
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
;
cfg = config;
render-html = document:
let
eval = lib.evalModules {
class = "DOM";
modules = [ document (import ../presentation/dom.nix) ];
};
in
toString eval.config;
in
{
# TODO: enable i18n, e.g. via a nested attribute for language-specific content
@ -27,7 +19,7 @@ in
(acc: elem: acc // {
# TODO: create static redirects from `tail page.locations`
# 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);
@ -59,19 +51,22 @@ in
type = types.str;
};
};
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 { inherit (config) name body; })
];
};
};
config.outputs.html = cfg.templates.html.page config;
};
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; })
];
};
});
}