forked from Fediversity/Fediversity
allow prefixing output paths of collection items
This commit is contained in:
parent
3505539499
commit
7efd5b8317
|
@ -5,7 +5,10 @@ in
|
||||||
{
|
{
|
||||||
imports = lib.nixFiles ./.;
|
imports = lib.nixFiles ./.;
|
||||||
|
|
||||||
collections.news.type = config.content-types.article;
|
collections.news = {
|
||||||
|
type = config.content-types.article;
|
||||||
|
prefixes = [ "news" ];
|
||||||
|
};
|
||||||
|
|
||||||
pages.index = { link, ... }: {
|
pages.index = { link, ... }: {
|
||||||
title = "Fediversity";
|
title = "Fediversity";
|
||||||
|
|
|
@ -18,9 +18,7 @@ in
|
||||||
in
|
in
|
||||||
map
|
map
|
||||||
(page: {
|
(page: {
|
||||||
page = lib.recursiveUpdate page {
|
page = lib.recursiveUpdate page { title = "${page.date}: ${page.title}"; };
|
||||||
title = "${page.date}: ${page.title}";
|
|
||||||
};
|
|
||||||
})
|
})
|
||||||
(lib.take 3 sorted);
|
(lib.take 3 sorted);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{ ... }:
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
collections.news.entry = {
|
collections.news.entry = { link, ... }: {
|
||||||
title = "Fediversity project publicly announced";
|
title = "Fediversity project publicly announced";
|
||||||
description = "The Fediversity project has officially been announced";
|
description = "The Fediversity project has officially been announced";
|
||||||
date = "2024-01-01";
|
date = "2024-01-01";
|
||||||
|
|
|
@ -52,16 +52,17 @@ rec {
|
||||||
inherit (lib) lists;
|
inherit (lib) lists;
|
||||||
|
|
||||||
path1 = subpath.components path1';
|
path1 = subpath.components path1';
|
||||||
|
prefix1 = with lib; take (length path1 - 1) path1;
|
||||||
path2 = subpath.components path2';
|
path2 = subpath.components path2';
|
||||||
|
prefix2 = with lib; take (length path1 - 1) path2;
|
||||||
|
|
||||||
commonPrefixLength = with lists;
|
commonPrefixLength = with lists;
|
||||||
findFirstIndex (i: i.fst != i.snd)
|
findFirstIndex (i: i.fst != i.snd)
|
||||||
{ fst = null; snd = null; }
|
(length prefix1)
|
||||||
(zipLists path1 path2);
|
(zipLists prefix1 prefix2);
|
||||||
|
|
||||||
relativeComponents = with lists;
|
relativeComponents = with lists;
|
||||||
[ "." ] ++ (replicate (length path1 - commonPrefixLength - 1) "..") ++
|
[ "." ] ++ (replicate (length prefix1 - commonPrefixLength) "..") ++ (drop commonPrefixLength path2);
|
||||||
(drop commonPrefixLength path2);
|
|
||||||
in
|
in
|
||||||
join "/" relativeComponents;
|
join "/" relativeComponents;
|
||||||
|
|
||||||
|
@ -98,13 +99,7 @@ rec {
|
||||||
merge = loc: defs:
|
merge = loc: defs:
|
||||||
map
|
map
|
||||||
(def:
|
(def:
|
||||||
let
|
elemType.merge (loc ++ [ "[definition ${toString def.file}]" ]) [{ inherit (def) file; value = def.value; }]
|
||||||
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
|
|
||||||
)
|
)
|
||||||
defs;
|
defs;
|
||||||
check = elemType.check;
|
check = elemType.check;
|
||||||
|
|
|
@ -41,7 +41,7 @@ in
|
||||||
<link rel="canonical" href="${page.outPath}" />
|
<link rel="canonical" href="${page.outPath}" />
|
||||||
'';
|
'';
|
||||||
body = ''
|
body = ''
|
||||||
${templates.nav { menu = { menu = config.menus.main; }; }}
|
${templates.nav { inherit page; menu = { menu = config.menus.main; }; }}
|
||||||
${builtins.readFile (commonmark page.name page.body)}
|
${builtins.readFile (commonmark page.name page.body)}
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
|
@ -55,7 +55,7 @@ in
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
body = ''
|
body = ''
|
||||||
${templates.nav { menu = { menu = config.menus.main; }; }}
|
${templates.nav { inherit page; menu = { menu = config.menus.main; }; }}
|
||||||
${builtins.readFile (commonmark page.name page.body)}
|
${builtins.readFile (commonmark page.name page.body)}
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
|
@ -76,20 +76,13 @@ in
|
||||||
let
|
let
|
||||||
pages = lib.attrValues config.pages;
|
pages = lib.attrValues config.pages;
|
||||||
collections = with lib; concatMap (collection: collection.entry) (attrValues config.collections);
|
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
|
in
|
||||||
with lib; foldl
|
with lib; foldl
|
||||||
(acc: elem: acc // {
|
(acc: elem: acc // {
|
||||||
"${head elem.locations}" = builtins.toFile "${elem.name}.html" elem.outputs.html;
|
"${head elem.locations}" = builtins.toFile "${elem.name}.html" elem.outputs.html;
|
||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
(pages ++ collections');
|
(pages ++ collections);
|
||||||
|
|
||||||
options.build = mkOption {
|
options.build = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
|
|
|
@ -14,16 +14,16 @@ rec {
|
||||||
<body>
|
<body>
|
||||||
</html>
|
</html>
|
||||||
'';
|
'';
|
||||||
nav = { menu }:
|
nav = { page, menu }:
|
||||||
let
|
let
|
||||||
render-item = item:
|
render-item = item:
|
||||||
if item ? menu then
|
if item ? menu then
|
||||||
''
|
''
|
||||||
<li>${item.menu.label}
|
<li>${item.menu.label}
|
||||||
${lib.indent " " (nav { menu = item; })}
|
${lib.indent " " (nav { inherit page; menu = item; })}
|
||||||
''
|
''
|
||||||
else
|
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>''
|
else ''<li><a href="${item.link.url}">${item.link.label}</a></li>''
|
||||||
;
|
;
|
||||||
in
|
in
|
||||||
|
|
|
@ -7,7 +7,7 @@ let
|
||||||
cfg = config;
|
cfg = config;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
content-types. article = { config, collection, ... }: {
|
content-types.article = { config, collection, ... }: {
|
||||||
imports = [ cfg.content-types.page ];
|
imports = [ cfg.content-types.page ];
|
||||||
options = {
|
options = {
|
||||||
collection = mkOption {
|
collection = mkOption {
|
||||||
|
@ -27,9 +27,6 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
config.name = lib.slug config.title;
|
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);
|
config.outputs.html = lib.mkForce (cfg.templates.html.article cfg config);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,11 +52,23 @@ in
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = name;
|
default = name;
|
||||||
};
|
};
|
||||||
entry = mkOption {
|
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";
|
description = "An entry in the collection";
|
||||||
type = types.collection (types.submodule ({
|
type = types.collection (types.submodule ({
|
||||||
_module.args.collection = config;
|
|
||||||
imports = [ config.type ];
|
imports = [ config.type ];
|
||||||
|
_module.args.collection = config;
|
||||||
|
process-locations = ls: with lib; concatMap (l: map (p: "${p}/${l}") config.prefixes) ls;
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,7 @@ let
|
||||||
;
|
;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
content-types.document = { name, config, link, ... }: {
|
content-types.document = { name, config, options, link, ... }: {
|
||||||
config._module.args.link = config.link;
|
config._module.args.link = config.link;
|
||||||
options = {
|
options = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
|
@ -17,7 +17,6 @@ in
|
||||||
# TODO: reconsider using `page.outPath` and what to put into `locations`.
|
# TODO: reconsider using `page.outPath` and what to put into `locations`.
|
||||||
# maybe we can avoid having ".html" suffixes there.
|
# maybe we can avoid having ".html" suffixes there.
|
||||||
# since templates can output multiple files, `html` is merely one of many things we *could* produce.
|
# 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 {
|
locations = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
List of historic output locations for the resulting file
|
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.
|
All other elements are used to create redirects to the canonical location.
|
||||||
'';
|
'';
|
||||||
type = with types; nonEmptyListOf str;
|
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 {
|
link = mkOption {
|
||||||
description = "Helper function for transparent linking to other pages";
|
description = "Helper function for transparent linking to other pages";
|
||||||
type = with types; functionTo str;
|
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
|
# TODO: may not need it when using `link`; could repurpose it to render the default template
|
||||||
outPath = mkOption {
|
outPath = mkOption {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, lib, ... }:
|
{ config, options, lib, ... }:
|
||||||
let
|
let
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
mkOption
|
mkOption
|
||||||
|
@ -7,7 +7,12 @@ let
|
||||||
cfg = config;
|
cfg = config;
|
||||||
subtype = baseModule: types.submodule [
|
subtype = baseModule: types.submodule [
|
||||||
baseModule
|
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
|
in
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue