diff --git a/website/presentation/templates.nix b/website/presentation/templates.nix index 7a688f7..d23ee1f 100644 --- a/website/presentation/templates.nix +++ b/website/presentation/templates.nix @@ -49,4 +49,17 @@ in ''; }; + + config.templates.files = fs: with lib; + foldl' + # TODO: create static redirects from `tail .locations` + (acc: elem: acc // (mapAttrs' (type: value: { + name = head elem.locations + optionalString (type != "") ".${type}"; + value = builtins.toFile + (elem.name + optionalString (type != "") ".${type}") + (toString value); + })) + elem.outputs) + { } + fs; } diff --git a/website/structure/assets.nix b/website/structure/assets.nix new file mode 100644 index 0000000..ff53428 --- /dev/null +++ b/website/structure/assets.nix @@ -0,0 +1,35 @@ +{ config, lib, ... }: +let + inherit (lib) + mkOption + types + ; + cfg = config; +in +{ + options.assets = mkOption { + description = '' + Collection of assets, i.e. static files that can be linked to from within documents + ''; + type = with types; attrsOf (submodule ({ config, ... }: { + imports = [ cfg.content-types.document ]; + options.path = mkOption { + type = types.path; + }; + config.name = builtins.baseNameOf config.path; + config.outputs."" = builtins.readFile config.path; + })); + default = { }; + }; + + config.files = with lib; + let + flatten = attrs: mapAttrsToList + (name: value: + # HACK: we somehow have to distinguish a module value from regular attributes. + # arbitrary choice: the outputs attribute + if value ? outputs then value else mapAttrsToList value) + attrs; + in + cfg.templates.files (flatten cfg.assets); +} diff --git a/website/structure/collections.nix b/website/structure/collections.nix index 7dd1261..a4f4fa6 100644 --- a/website/structure/collections.nix +++ b/website/structure/collections.nix @@ -61,15 +61,11 @@ in }; })); }; + config.files = - # TODO: create static redirects from `tail .locations` + with lib; let - collections = with lib; concatMap (collection: collection.entry) (attrValues config.collections); + collections = concatMap (collection: collection.entry) (attrValues config.collections); in - with lib; foldl - (acc: elem: acc // { - "${head elem.locations}.html" = builtins.toFile "${elem.name}.html" "${elem.outputs.html}"; - }) - { } - collections; + cfg.templates.files collections; } diff --git a/website/structure/default.nix b/website/structure/default.nix index 6210292..a13bb95 100644 --- a/website/structure/default.nix +++ b/website/structure/default.nix @@ -47,11 +47,28 @@ in }; link = mkOption { description = "Helper function for transparent linking to other pages"; - type = with types; functionTo str; + type = with types; functionTo attrs; # TODO: we may want links to other representations, # and currently the mapping of output types to output file # names is soft. - default = target: with lib; "${relativePath (head config.locations) (head target.locations)}.html"; + default = with lib; target: + let + path = relativePath (head config.locations) (head target.locations); + links = mapAttrs + (type: output: + path + optionalString (type != "") ".${type}" + # ^^^^^^^^^^^^ + # convention for raw files + ) + target.outputs; + in + if length (attrValues links) == 0 + then throw "no output to link to for '${target.name}'" + else if length (attrValues links) == 1 + then links // { + __toString = _: head (attrValues links); + } + else links; }; outputs = mkOption { description = '' diff --git a/website/structure/page.nix b/website/structure/page.nix index 6c20719..3578385 100644 --- a/website/structure/page.nix +++ b/website/structure/page.nix @@ -14,15 +14,8 @@ in ''; type = with types; attrsOf (submodule config.content-types.page); }; - config.files = with lib; - foldl' - (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}"; - }) - { } - (attrValues config.pages); + + config.files = with lib; cfg.templates.files (attrValues config.pages); config.content-types.page = { name, config, ... }: { imports = [ cfg.content-types.document ];