Fediversity/website/presentation/default.nix

110 lines
3.4 KiB
Nix
Raw Normal View History

2024-11-13 15:24:41 +01:00
{ config, options, lib, pkgs, ... }:
let
inherit (lib)
mkOption
types
;
2024-11-13 15:24:41 +01:00
templates = import ./templates.nix { inherit lib; };
2024-11-13 15:24:41 +01:00
in
{
options.templates =
let
# arbitrarily nested attribute set where the leaves are of type `type`
# NOTE: due to how `either` works, the first match is significant,
# so if `type` happens to be an attrset, the typecheck will consider
# `type`, not `attrsOf`
recursiveAttrs = type: with types; attrsOf (either type (recursiveAttrs type));
in
mkOption {
description = ''
Collection of named functions to convert document contents to a string representation
2024-11-13 15:24:41 +01:00
Each template function takes the complete site `config` and the document's data structure.
'';
type = recursiveAttrs (with types; functionTo (functionTo str));
};
2024-11-13 15:24:41 +01:00
config.templates.html =
2024-11-13 15:24:41 +01:00
let
commonmark = name: markdown: pkgs.runCommand "${name}.html"
{
buildInputs = [ pkgs.cmark ];
} ''
cmark ${builtins.toFile "${name}.md" markdown} > $out
'';
in
{
page = lib.mkDefault (config: page: templates.html {
head = ''
<title>${page.title}</title>
<meta name="description" content="${page.description}" />
<link rel="canonical" href="${page.outPath}" />
'';
body = ''
${templates.nav { inherit page; menu = { menu = config.menus.main; }; }}
${builtins.readFile (commonmark page.name page.body)}
'';
2024-11-13 15:24:41 +01:00
});
article = lib.mkDefault (config: page: templates.html {
head = ''
<title>${page.title}</title>
<meta name="description" content="${page.description}" />
2024-11-13 15:24:41 +01:00
${with lib; join "\n" (map
(author: ''<meta name="author" content="${author}" />'')
(if isList page.author then page.author else [page.author]))
}
'';
body = ''
${templates.nav { inherit page; menu = { menu = config.menus.main; }; }}
${builtins.readFile (commonmark page.name page.body)}
'';
2024-11-13 15:24:41 +01:00
});
};
options.files = mkOption {
description = ''
Files that make up the site, mapping from output path to contents
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.
'';
type = with types; attrsOf path;
};
config.files =
# TODO: create static redirects from `tail page.locations`
2024-11-13 15:24:41 +01:00
let
pages = lib.attrValues config.pages;
collections = with lib; concatMap (collection: collection.entry) (attrValues config.collections);
2024-11-13 15:24:41 +01:00
in
with lib; foldl
(acc: elem: acc // {
# TODO: we may or may not want to enforce the mapping of file types to output file name suffixes
"${head elem.locations}.html" = builtins.toFile "${elem.name}.html" elem.outputs.html;
})
{ }
(pages ++ collections);
2024-11-13 15:24:41 +01:00
options.build = mkOption {
description = ''
The final output of the web site
'';
type = types.package;
default =
let
script = ''
mkdir $out
'' + lib.join "\n" copy;
copy = lib.mapAttrsToList
(
path: file: ''
mkdir -p $out/$(dirname ${path})
cp -r ${file} $out/${path}
''
)
config.files;
in
pkgs.runCommand "source" { } script;
};
}