nixite/nixite/site.nix
2024-01-02 10:53:45 +00:00

170 lines
4 KiB
Nix

let
html = import ./html.nix;
elems = import ./elems.nix;
style = import ./style.nix;
in rec {
prepare = {
favicon ? null,
styles ? {},
}: site: let
nullFn = p: p;
allStyles = styles // getStyles site;
doFavicon =
if favicon != null
then (applyFavicon favicon)
else nullFn;
in (extractPaths (extractLinks (applyStyle allStyles (doFavicon site))));
getStyles = site:
builtins.zipAttrsWith (name: value: builtins.elemAt value 0)
(map style.getStyles (flatten site));
flatten = site:
map (page:
if builtins.isAttrs page && page ? "__toString"
then page
else if builtins.isAttrs page
then flatten page
else page) (builtins.attrValues site);
applyStyle = style: site: ((linkStyle site) // {"style.css" = style;});
linkStyle = site:
eachPage site
(content: html.addToHead content [(elems.Stylesheet "/style.css")]);
eachPage = site: callback: (builtins.mapAttrs (name: content:
if builtins.isAttrs content && content ? "__toString"
then callback content
else if builtins.isAttrs content
then eachPage content callback
else content)
site);
applyFavicon = icon: site:
eachPage site (content:
html.addToHead content [
(elems.link {
rel = "shortcut icon";
href = icon;
})
]);
extractPaths = content:
switchPaths content
// {
static = (content.static or {}) // getPaths content;
};
extractLinks = content:
switchLinks content
// {
static = (content.static or {}) // getLinks content;
};
isLink = value:
builtins.isAttrs value && value ? type && value.type == "link";
switchLinks = runDeep isLink (value: "/static/" + value.name);
getLinks = content: (builtins.listToAttrs (getLinksKV content));
getLinksKV = getAllKV {
when = isLink;
key = l: l.name or null;
value = l: l.content or null;
};
runLink = f:
if !builtins.isFunction f
then null
else
(let
res = f {};
in (
if !builtins.isAttrs res
then null
else res
));
runDeep = when: do: set: (
if builtins.isAttrs set
then
builtins.mapAttrs
(key: value:
if when value
then do value
else runDeep when do value)
set
else if builtins.isList set
then (map (runDeep when do) set)
else set
);
switchPaths = runDeep builtins.isPath (value: "/static/" + baseNameOf value);
getPaths = content: (builtins.listToAttrs (getPathsKV content));
getPathsKV = getAllKV {
when = builtins.isPath;
key = baseNameOf;
value = v: v;
};
getAllKV = {
when,
key,
value,
} @ params: path: (
if when path
then [
{
name = key path;
value = value path;
}
]
else if builtins.isAttrs path
then
builtins.concatMap (getAllKV params) (builtins.attrValues
(builtins.mapAttrs
(n: v:
if (builtins.substring 0 2 n == "__")
then null
else v)
path))
else if builtins.isList path
then builtins.concatMap (getAllKV params) path
else []
);
link = {
name,
content,
} @ page:
page // {type = "link";};
copyTo = prefix: site:
builtins.toString (builtins.attrValues (builtins.mapAttrs (name: content:
if builtins.isString content
then ''
cp ${builtins.toFile name content} ${prefix}/${name}
''
else if builtins.isPath content
then ''
cp -r ${content} ${prefix}/${name}
''
else if builtins.isAttrs content && content ? "__toString"
then ''
cp ${builtins.toFile name (toString content)} ${prefix}/${name}
''
else if builtins.isAttrs content
then ''
mkdir -p ${prefix}/${name}
${copyTo "${prefix}/${name}" content}
''
else
throw "Site page must be string, path or attrset, but got ${
builtins.typeOf content
}: [${toString content}]")
site));
}