2024-11-13 15:24:41 +01:00
|
|
|
{ config, lib, options, ... }:
|
|
|
|
let
|
|
|
|
inherit (lib)
|
|
|
|
mkOption
|
|
|
|
types
|
|
|
|
;
|
|
|
|
cfg = config;
|
|
|
|
in
|
|
|
|
{
|
|
|
|
options = {
|
|
|
|
content-types = mkOption {
|
|
|
|
description = "Content types";
|
|
|
|
type = with types; attrsOf deferredModule;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
config.content-types = {
|
2024-11-13 15:24:41 +01:00
|
|
|
document = { name, config, ... }: {
|
2024-11-13 15:24:41 +01:00
|
|
|
options = {
|
2024-11-13 15:24:41 +01:00
|
|
|
|
2024-11-13 15:24:41 +01:00
|
|
|
name = mkOption {
|
2024-11-13 15:24:41 +01:00
|
|
|
description = "Symbolic name, used as a human-readable identifier";
|
2024-11-13 15:24:41 +01:00
|
|
|
type = types.str;
|
|
|
|
default = name;
|
|
|
|
};
|
|
|
|
locations = mkOption {
|
|
|
|
description = ''
|
|
|
|
List of historic output locations for the resulting file
|
|
|
|
|
|
|
|
The first element is the canonical location.
|
|
|
|
All other elements are used to create redirects to the canonical location.
|
|
|
|
'';
|
|
|
|
type = with types; nonEmptyListOf str;
|
|
|
|
};
|
|
|
|
link = mkOption {
|
|
|
|
description = "Helper function for transparent linking to other pages";
|
|
|
|
type = with types; functionTo str;
|
|
|
|
default = target: "TODO: compute the relative path based on `locations`";
|
|
|
|
};
|
2024-11-13 15:24:41 +01:00
|
|
|
# TODO: may not need it when using `link`; could repurpose it to render the default template
|
2024-11-13 15:24:41 +01:00
|
|
|
outPath = mkOption {
|
|
|
|
description = ''
|
|
|
|
Location of the page, used for transparently creating links
|
|
|
|
'';
|
|
|
|
type = types.str;
|
|
|
|
default = lib.head config.locations;
|
|
|
|
};
|
2024-11-13 15:24:41 +01:00
|
|
|
# TODO: maybe it would even make sense to split routing and rendering altogether.
|
|
|
|
# in that case, templates would return strings, and a different
|
|
|
|
# piece of the machinery resolves rendering templates to files
|
|
|
|
# using `locations`.
|
|
|
|
# then we'd have e.g. `templates.html` and `templates.atom` for
|
|
|
|
# different output formats.
|
|
|
|
template = mkOption {
|
|
|
|
description = ''
|
|
|
|
Function that converts the page contents to files
|
|
|
|
'';
|
|
|
|
type = with types; functionTo (functionTo options.files.type);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
page = { name, config, ... }: {
|
|
|
|
imports = [ cfg.content-types.document ];
|
|
|
|
options = {
|
|
|
|
title = mkOption {
|
|
|
|
description = "Page title";
|
|
|
|
type = types.str;
|
|
|
|
default = name;
|
|
|
|
};
|
2024-11-13 15:24:41 +01:00
|
|
|
description = mkOption {
|
|
|
|
description = ''
|
|
|
|
One-sentence description of page contents
|
|
|
|
'';
|
|
|
|
type = types.str;
|
|
|
|
};
|
|
|
|
summary = mkOption {
|
|
|
|
description = ''
|
|
|
|
One-paragraph summary of page contents
|
|
|
|
'';
|
|
|
|
type = types.str;
|
|
|
|
};
|
|
|
|
body = mkOption {
|
|
|
|
description = ''
|
|
|
|
Page contents in CommonMark
|
|
|
|
'';
|
|
|
|
type = types.str;
|
|
|
|
};
|
|
|
|
};
|
2024-11-13 15:24:41 +01:00
|
|
|
config.template = cfg.templates.page;
|
2024-11-13 15:24:41 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
article = { config, collectionName, ... }: {
|
|
|
|
imports = [ cfg.content-types.page ];
|
|
|
|
options = {
|
|
|
|
date = mkOption {
|
|
|
|
description = "Publication date";
|
|
|
|
type = with types; nullOr str;
|
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
author = mkOption {
|
|
|
|
description = "Page author";
|
|
|
|
type = with types; nullOr (either str (listOf str));
|
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
config.name = lib.slug config.title;
|
|
|
|
config.outPath = "${collectionName}/${lib.head config.locations}";
|
2024-11-13 15:24:41 +01:00
|
|
|
config.template = lib.mkForce cfg.templates.article;
|
2024-11-13 15:24:41 +01:00
|
|
|
};
|
2024-11-13 15:24:41 +01:00
|
|
|
|
|
|
|
named-link = { ... }: {
|
|
|
|
options = {
|
|
|
|
label = mkOption {
|
|
|
|
description = "Link label";
|
|
|
|
type = types.str;
|
|
|
|
};
|
|
|
|
url = mkOption {
|
|
|
|
description = "Link URL";
|
|
|
|
type = types.str;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
navigation = { name, ... }: {
|
|
|
|
options = {
|
|
|
|
name = mkOption {
|
|
|
|
description = "Symbolic name, used as a human-readable identifier";
|
|
|
|
type = types.str;
|
|
|
|
default = name;
|
|
|
|
};
|
|
|
|
label = mkOption {
|
|
|
|
description = "Menu label";
|
|
|
|
type = types.str;
|
|
|
|
default = name;
|
|
|
|
};
|
|
|
|
items = mkOption {
|
|
|
|
description = "List of menu items";
|
|
|
|
type = with types; listOf (attrTag {
|
|
|
|
menu = mkOption { type = submodule cfg.content-types.navigation; };
|
|
|
|
page = mkOption { type = submodule cfg.content-types.page; };
|
|
|
|
link = mkOption { type = submodule cfg.content-types.named-link; };
|
|
|
|
});
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2024-11-13 15:24:41 +01:00
|
|
|
};
|
|
|
|
}
|