add favicons to every page

This commit is contained in:
tristan 2024-01-01 08:10:32 +00:00
parent 30ffa6c9b3
commit d723140f84
6 changed files with 129 additions and 32 deletions

View file

@ -9,7 +9,7 @@
in nixite // { in nixite // {
packages.${system} = { packages.${system} = {
raw = nixite.mkSite (let raw = nixite.mkSite (let
site = (nixite.site.extractPaths { markup = {
"test" = with nixite.elems; "test" = with nixite.elems;
let let
blue = nixite.style.tag "span" "blue" { blue = nixite.style.tag "span" "blue" {
@ -19,14 +19,7 @@
style = { text-decoration = "underline"; }; style = { text-decoration = "underline"; };
}; };
in (Doc { } [ in (Doc { } [
[ [ (title { } "Nixite") ]
(title { } "Nixite")
(link {
rel = "shortcut icon";
type = "image/png";
href = ./testing/src/favicon.png;
} "")
]
(main { } [ (main { } [
(a "/readme" "Readme") (a "/readme" "Readme")
(a "/blog" "blog") (a "/blog" "blog")
@ -41,10 +34,11 @@
]); ]);
blog = nixite.md.readDir ./testing/blog; blog = nixite.md.readDir ./testing/blog;
"index.html" = nixite.md.mdToPage ./README.md; "index.html" = nixite.md.mdToPage ./README.md;
}); };
styles = # nixite.site.getStyles site; styles = nixite.site.getStyles markup;
nixite.style.getStyles site.test; site = (nixite.site.extractPaths (nixite.site.applyStyle styles
in nixite.site.applyStyle styles site); (nixite.site.applyFavicon ./testing/src/favicon.png markup)));
in site);
default = nixite.serve self.packages.${system}.raw; default = nixite.serve self.packages.${system}.raw;

View file

@ -14,8 +14,8 @@ in rec {
else if builtins.isList elem then else if builtins.isList elem then
builtins.toString (map toHTML elem) builtins.toString (map toHTML elem)
else else
"<${elem.tag} ${writeAttrs elem.attrs}>${ "<${elem.tag} ${writeAttrs elem.attrs or { }}>${
toHTML elem.child toHTML elem.child or ""
}</${elem.tag}>"; }</${elem.tag}>";
writeAttrs = attrs: writeAttrs = attrs:
@ -30,11 +30,13 @@ in rec {
tag = tag: { tag = tag: {
inherit tag; inherit tag;
__toString = self: toString (self { } "");
__functor = self: attrs: __functor = self: attrs:
if !(builtins.isAttrs attrs) then if !(builtins.isAttrs attrs) then
throw "HTML tag requires attribute set" throw "HTML tag requires attribute set"
else { else {
inherit tag attrs; inherit tag attrs;
__toString = self: toString (self "");
__functor = self: child: __functor = self: child:
if !(isTag child) then if !(isTag child) then
throw "tag child must be tag, list, or string, got ${ throw "tag child must be tag, list, or string, got ${

View file

@ -1,24 +1,45 @@
let let
html = import ./html.nix; html = import ./html.nix;
elems = import ./elems.nix; elems = import ./elems.nix;
style = import ./style.nix;
in rec { in rec {
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; }; applyStyle = style: site: (linkStyle site) // { "style.css" = style; };
getStyles = site: ''
.blue {
color: blue;
}
'';
linkStyle = site: linkStyle = site:
eachPage site
(content: html.addToHead content [ (elems.Stylesheet "/style.css") ]);
eachPage = site: callback:
(builtins.mapAttrs (name: content: (builtins.mapAttrs (name: content:
if builtins.isAttrs content && content ? "__toString" then if builtins.isAttrs content && content ? "__toString" then
html.addToHead content [ (elems.Stylesheet "/style.css") ] callback content
else if builtins.isAttrs content then else if builtins.isAttrs content then
linkStyle content eachPage content callback
else else
content) site); content) site);
applyFavicon = icon: site:
eachPage site (content:
html.addToHead content [
(elems.link {
rel = "shortcut icon";
href = icon;
})
]);
extractPaths = content: switchPaths content // { static = getPaths content; }; extractPaths = content: switchPaths content // { static = getPaths content; };
switchPaths = content: switchPaths = content:

View file

@ -69,6 +69,18 @@ in with html; [
actual = (para "").attrs.style; actual = (para "").attrs.style;
})) }))
(it "needs no args to make string" (let p = tag "p";
in {
actual = toString p;
expected = "<p ></p>";
}))
(it "needs no content to make string" (let p = tag "p";
in {
actual = toString (p { class = "foobar"; });
expected = ''<p class="foobar"></p>'';
}))
(it "works recursively" (let (it "works recursively" (let
attrs = { style = { foo = "bar"; }; }; attrs = { style = { foo = "bar"; }; };
para = (tag "p" attrs); para = (tag "p" attrs);

View file

@ -1,15 +1,24 @@
msg: msg:
{ actual, expected, asString ? false, asJSON ? false, removeDunders ? false, }: { actual, expected, asString ? false, asJSON ? false, removeDunders ? false, }:
if (if asString then let
toString actual == toString expected preProcess = v:
if removeDunders then
builtins.removeAttrs v [ "__toString" "__functor" ]
else if asString then
toString v
else if asJSON then else if asJSON then
builtins.toJSON actual == builtins.toJSON expected builtins.toJSON v
else if removeDunders then else v;
builtins.removeAttrs actual [ "__toString" "__functor" ] == expected
else a = preProcess actual;
actual == expected) then '' e = preProcess expected;
in
if (a == e) then ''
echo 'it ${msg}' echo 'it ${msg}'
'' else '' ''
else
''
echo 'FAILED: ${msg}' echo 'FAILED: ${msg}'
echo '${builtins.toJSON expected}' echo '${builtins.toJSON expected}'
echo '${builtins.toJSON actual}' echo '${builtins.toJSON actual}'

View file

@ -2,6 +2,7 @@ let
html = import ../nixite/html.nix; html = import ../nixite/html.nix;
elems = import ../nixite/elems.nix; elems = import ../nixite/elems.nix;
site = import ../nixite/site.nix; site = import ../nixite/site.nix;
style = import ../nixite/style.nix;
it = import ./it.nix; it = import ./it.nix;
in with site; [ in with site; [
(it "applies a style" { (it "applies a style" {
@ -42,6 +43,64 @@ in with site; [
}; };
asJSON = true; asJSON = true;
}) })
(it "applies a favicon" {
expected = {
"index.html" = elems.html { } [
(elems.head { } [
(elems.title { } "foobar")
(elems.link {
rel = "shortcut icon";
href = ./src/favicon.png;
})
])
(elems.main { } "something")
];
blog = {
"index.html" = elems.html { } [
(elems.head { } [
(elems.title { } "foobar")
(elems.link {
rel = "shortcut icon";
href = ./src/favicon.png;
})
])
(elems.main { } "something")
];
};
};
actual = applyFavicon ./src/favicon.png {
"index.html" = elems.html { } [
(elems.head { } [ (elems.title { } "foobar") ])
(elems.main { } "something")
];
blog = {
"index.html" = elems.html { } [
(elems.head { } [ (elems.title { } "foobar") ])
(elems.main { } "something")
];
};
};
asJSON = true;
})
(it "extracts all styles" {
expected = {
"p.class" = {color = "blue";};
"a.class2" = {color = "green";};
};
actual = getStyles (let
p = style.tag "p" "class" {style = {color = "blue";};};
g = style.tag "a" "class2" {style = {color = "green";};};
in {
"index.html" = p "";
blog = {
"index.html" = g "";
};
});
removeDunders = true;
})
(it "extracts top level paths" { (it "extracts top level paths" {
actual = getPaths { actual = getPaths {
something = ""; something = "";