forked from Fediversity/fediversity.eu
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.
This commit is contained in:
parent
2eeb7e5bcc
commit
4160b6e976
|
@ -37,46 +37,37 @@ in
|
||||||
type = recursiveAttrs (with types; functionTo (functionTo str));
|
type = recursiveAttrs (with types; functionTo (functionTo str));
|
||||||
};
|
};
|
||||||
|
|
||||||
config.templates.html =
|
config.templates.html = {
|
||||||
|
markdown = name: text:
|
||||||
let
|
let
|
||||||
commonmark = name: markdown: pkgs.runCommand "${name}.html"
|
commonmark = pkgs.runCommand "${name}.html"
|
||||||
{
|
{
|
||||||
buildInputs = [ pkgs.cmark ];
|
buildInputs = [ pkgs.cmark ];
|
||||||
} ''
|
} ''
|
||||||
cmark ${builtins.toFile "${name}.md" markdown} > $out
|
cmark ${builtins.toFile "${name}.md" text} > $out
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
{
|
builtins.readFile commonmark;
|
||||||
nav = lib.mkDefault templates.nav;
|
nav = menu: page:
|
||||||
page = lib.mkDefault (config: page: render-html {
|
let
|
||||||
html = {
|
render-item = item:
|
||||||
head = {
|
if item ? menu then ''
|
||||||
title.text = page.title;
|
<li>${item.menu.label}
|
||||||
meta.description = page.description;
|
${lib.indent " " (item.menu.outputs.html page)}
|
||||||
link.canonical = lib.head page.locations;
|
</li>
|
||||||
};
|
''
|
||||||
body.content = [
|
else if item ? page then ''<li><a href="${page.link item.page}">${item.page.title}</a></li>''
|
||||||
(config.menus.main.outputs.html page)
|
else ''<li><a href="${item.link.url}">${item.link.label}</a></li>''
|
||||||
{ section.heading.content = page.title; }
|
;
|
||||||
(builtins.readFile (commonmark page.name page.body))
|
in
|
||||||
];
|
''
|
||||||
};
|
<nav>
|
||||||
});
|
<ul>
|
||||||
article = lib.mkDefault (config: page: render-html {
|
${with lib; indent " " (join "\n" (map render-item menu.items))}
|
||||||
html = {
|
</ul>
|
||||||
head = {
|
</nav>
|
||||||
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 {
|
options.files = mkOption {
|
||||||
|
@ -86,6 +77,8 @@ in
|
||||||
By default, all elements in `option`{pages} are converted to files using their template or the default template.
|
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.
|
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;
|
type = with types; attrsOf path;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
{ lib }:
|
|
||||||
rec {
|
|
||||||
nav = menu: page:
|
|
||||||
let
|
|
||||||
render-item = item:
|
|
||||||
if item ? menu then ''
|
|
||||||
<li>${item.menu.label}
|
|
||||||
${lib.indent " " (item.menu.outputs.html page)}
|
|
||||||
</li>
|
|
||||||
''
|
|
||||||
else if item ? page then ''<li><a href="${page.link item.page}">${item.page.title}</a></li>''
|
|
||||||
else ''<li><a href="${item.link.url}">${item.link.label}</a></li>''
|
|
||||||
;
|
|
||||||
in
|
|
||||||
''
|
|
||||||
<nav>
|
|
||||||
<ul>
|
|
||||||
${with lib; indent " " (join "\n" (map render-item menu.menu.items))}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -5,6 +5,14 @@ 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, ... }: {
|
||||||
|
@ -27,6 +35,20 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
config.name = lib.slug config.title;
|
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)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,13 +45,13 @@ 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 = mkOption {
|
outputs.html = mkOption {
|
||||||
# TODO: figure out how to make this overridable at any granularity.
|
# TODO: make this of type DOM and convert to string at the output.
|
||||||
# it should be possible with the DOM module now.
|
# 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; attrsOf str;
|
type = with types; str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -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.
|
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);
|
type = with types; attrsOf (functionTo str);
|
||||||
default.html = cfg.templates.html.nav { menu = config; };
|
default.html = cfg.templates.html.nav config;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,14 @@ 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.page = { name, config, ... }: {
|
content-types.page = { name, config, ... }: {
|
||||||
|
@ -34,6 +42,19 @@ in
|
||||||
type = types.str;
|
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)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue