allow prefixing output paths of collection items

This commit is contained in:
Valentin Gagarin 2024-11-13 15:24:41 +01:00
parent c3774eb1f6
commit c2fe5da469
10 changed files with 54 additions and 46 deletions

View file

@ -5,7 +5,10 @@ in
{
imports = lib.nixFiles ./.;
collections.news.type = config.content-types.article;
collections.news = {
type = config.content-types.article;
prefixes = [ "news" ];
};
pages.index = { link, ... }: {
title = "Fediversity";

View file

@ -18,9 +18,7 @@ in
in
map
(page: {
page = lib.recursiveUpdate page {
title = "${page.date}: ${page.title}";
};
page = lib.recursiveUpdate page { title = "${page.date}: ${page.title}"; };
})
(lib.take 3 sorted);
}

View file

@ -1,6 +1,6 @@
{ ... }:
{ config, lib, ... }:
{
collections.news.entry = {
collections.news.entry = { link, ... }: {
title = "Fediversity project publicly announced";
description = "The Fediversity project has officially been announced";
date = "2024-01-01";

17
lib.nix
View file

@ -52,16 +52,17 @@ rec {
inherit (lib) lists;
path1 = subpath.components path1';
prefix1 = with lib; take (length path1 - 1) path1;
path2 = subpath.components path2';
prefix2 = with lib; take (length path1 - 1) path2;
commonPrefixLength = with lists;
findFirstIndex (i: i.fst != i.snd)
{ fst = null; snd = null; }
(zipLists path1 path2);
(length prefix1)
(zipLists prefix1 prefix2);
relativeComponents = with lists;
[ "." ] ++ (replicate (length path1 - commonPrefixLength - 1) "..") ++
(drop commonPrefixLength path2);
[ "." ] ++ (replicate (length prefix1 - commonPrefixLength) "..") ++ (drop commonPrefixLength path2);
in
join "/" relativeComponents;
@ -98,13 +99,7 @@ rec {
merge = loc: defs:
map
(def:
let
merged = lib.mergeDefinitions
(loc ++ [ "[definition ${toString def.file}]" ])
elemType
[{ inherit (def) file; value = def.value; }];
in
if merged ? mergedValue then merged.mergedValue else merged.value
elemType.merge (loc ++ [ "[definition ${toString def.file}]" ]) [{ inherit (def) file; value = def.value; }]
)
defs;
check = elemType.check;

View file

@ -41,7 +41,7 @@ in
<link rel="canonical" href="${page.outPath}" />
'';
body = ''
${templates.nav { menu = { menu = config.menus.main; }; }}
${templates.nav { inherit page; menu = { menu = config.menus.main; }; }}
${builtins.readFile (commonmark page.name page.body)}
'';
});
@ -55,7 +55,7 @@ in
}
'';
body = ''
${templates.nav { menu = { menu = config.menus.main; }; }}
${templates.nav { inherit page; menu = { menu = config.menus.main; }; }}
${builtins.readFile (commonmark page.name page.body)}
'';
});
@ -76,20 +76,13 @@ in
let
pages = lib.attrValues config.pages;
collections = with lib; concatMap (collection: collection.entry) (attrValues config.collections);
collections' = with lib; map
(
entry: recursiveUpdate entry {
locations = map (l: "${entry.collection.name}/${l}") entry.locations;
}
)
collections;
in
with lib; foldl
(acc: elem: acc // {
"${head elem.locations}" = builtins.toFile "${elem.name}.html" elem.outputs.html;
})
{ }
(pages ++ collections');
(pages ++ collections);
options.build = mkOption {
description = ''

View file

@ -14,23 +14,23 @@ rec {
<body>
</html>
'';
nav = { menu }:
nav = { page, menu }:
let
render-item = item:
if item ? menu then
''
<li>${item.menu.label}
${lib.indent " " (nav { menu = item; })}
${lib.indent " " (nav { inherit page; menu = item; })}
''
else
if item ? page then ''<li><a href="${item.page}">${item.page.title}</a></li>''
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))}
${with lib; indent " " (join "\n" (map render-item menu.menu.items))}
</ul>
</nav>
'';

View file

@ -7,7 +7,7 @@ let
cfg = config;
in
{
content-types. article = { config, collection, ... }: {
content-types.article = { config, collection, ... }: {
imports = [ cfg.content-types.page ];
options = {
collection = mkOption {
@ -27,9 +27,6 @@ in
};
};
config.name = lib.slug config.title;
# TODO: this should be covered by the TBD `link` function instead,
# taking a historical list of collection names into account
config.outPath = "${collection.name}/${lib.head config.locations}";
config.outputs.html = lib.mkForce (cfg.templates.html.article cfg config);
};
}

View file

@ -52,13 +52,25 @@ in
type = types.str;
default = name;
};
entry = mkOption {
description = "An entry in the collection";
type = types.collection (types.submodule ({
_module.args.collection = config;
imports = [ config.type ];
}));
prefixes = mkOption {
description = ''
List of historic output locations for files in the collection
The first element is the canonical location.
All other elements are used to create redirects to the canonical location.
'';
type = with types; nonEmptyListOf str;
example = [ "." ];
};
entry = mkOption
{
description = "An entry in the collection";
type = types.collection (types.submodule ({
imports = [ config.type ];
_module.args.collection = config;
process-locations = ls: with lib; concatMap (l: map (p: "${p}/${l}") config.prefixes) ls;
}));
};
};
}));
};

View file

@ -6,7 +6,7 @@ let
;
in
{
content-types.document = { name, config, link, ... }: {
content-types.document = { name, config, options, link, ... }: {
config._module.args.link = config.link;
options = {
name = mkOption {
@ -17,7 +17,6 @@ in
# TODO: reconsider using `page.outPath` and what to put into `locations`.
# maybe we can avoid having ".html" suffixes there.
# since templates can output multiple files, `html` is merely one of many things we *could* produce.
# TODO: make `apply` configurable so one can programmatically modify locations
locations = mkOption {
description = ''
List of historic output locations for the resulting file
@ -26,11 +25,17 @@ in
All other elements are used to create redirects to the canonical location.
'';
type = with types; nonEmptyListOf str;
apply = config.process-locations;
};
process-locations = mkOption {
description = "Function to post-process the output locations of contained document";
type = types.functionTo options.locations.type;
default = lib.id;
};
link = mkOption {
description = "Helper function for transparent linking to other pages";
type = with types; functionTo str;
default = target: with lib; relativePath (head config.locations) (head target.locations);
default = target: with lib; relativePath config.outPath target.outPath;
};
# TODO: may not need it when using `link`; could repurpose it to render the default template
outPath = mkOption {

View file

@ -1,4 +1,4 @@
{ config, lib, ... }:
{ config, options, lib, ... }:
let
inherit (lib)
mkOption
@ -7,7 +7,12 @@ let
cfg = config;
subtype = baseModule: types.submodule [
baseModule
{ _module.freeformType = types.attrs; }
{
_module.freeformType = types.attrs;
# XXX: this is supposed to be used with a finished value,
# and we don't want to process locations again.
process-locations = lib.mkForce lib.id;
}
];
in
{