170 lines
4 KiB
Nix
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));
|
|
}
|