alejandra
This commit is contained in:
parent
b1426fb1ca
commit
dc33fdf093
|
@ -37,11 +37,11 @@
|
||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1704187012,
|
"lastModified": 1704192724,
|
||||||
"narHash": "sha256-td0PQa1cTvjurjBmLpCynAgDV425Mh8sRObRtbTGxiQ=",
|
"narHash": "sha256-Cx9os5FQU4UTjxt/uE1trPHxegXyhvV/wSiIiBWTDt0=",
|
||||||
"ref": "refs/heads/master",
|
"ref": "refs/heads/master",
|
||||||
"rev": "249bd9cda4fe9b02f3c85b22179109794eb57256",
|
"rev": "b800bb46955d69cf7693d7c788a4d624eff2717f",
|
||||||
"revCount": 2,
|
"revCount": 3,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.tristans.cloud/tristan/tix"
|
"url": "https://git.tristans.cloud/tristan/tix"
|
||||||
},
|
},
|
||||||
|
|
70
flake.nix
70
flake.nix
|
@ -1,14 +1,19 @@
|
||||||
{
|
{
|
||||||
description = "A site in nix?";
|
description = "A site in nix?";
|
||||||
|
|
||||||
inputs = { tix.url = "git+https://git.tristans.cloud/tristan/tix"; };
|
inputs = {tix.url = "git+https://git.tristans.cloud/tristan/tix";};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, tix }:
|
outputs = {
|
||||||
let
|
self,
|
||||||
system = "x86_64-linux";
|
nixpkgs,
|
||||||
pkgs = import nixpkgs { inherit system; };
|
tix,
|
||||||
nixite = import ./nixite/. { inherit pkgs; };
|
}: let
|
||||||
in nixite // {
|
system = "x86_64-linux";
|
||||||
|
pkgs = import nixpkgs {inherit system;};
|
||||||
|
nixite = import ./nixite/. {inherit pkgs;};
|
||||||
|
in
|
||||||
|
nixite
|
||||||
|
// {
|
||||||
packages.${system} = {
|
packages.${system} = {
|
||||||
raw = nixite.mkSite (let
|
raw = nixite.mkSite (let
|
||||||
readme = {
|
readme = {
|
||||||
|
@ -16,33 +21,34 @@
|
||||||
content = nixite.md.mdToPage ./README.md;
|
content = nixite.md.mdToPage ./README.md;
|
||||||
};
|
};
|
||||||
markup = {
|
markup = {
|
||||||
"index.html" = with nixite.elems;
|
"index.html" = with nixite.elems; let
|
||||||
let
|
blue = nixite.style.component span "blue" {
|
||||||
blue = nixite.style.component span "blue" {
|
style = {color = "blue";};
|
||||||
style = { color = "blue"; };
|
};
|
||||||
};
|
underblue = nixite.style.component blue "under" {
|
||||||
underblue = nixite.style.component blue "under" {
|
style = {text-decoration = "underline";};
|
||||||
style = { text-decoration = "underline"; };
|
};
|
||||||
};
|
in (Doc {} [
|
||||||
in (Doc { } [
|
[(title "Nixite")]
|
||||||
[ (title "Nixite") ]
|
(main [
|
||||||
(main [
|
(a {href = nixite.site.link readme;} "Readme")
|
||||||
(a { href = nixite.site.link readme; } "Readme")
|
(a "/blog" "blog")
|
||||||
(a "/blog" "blog")
|
(List {} ["item 1" "item 2" "item 3"])
|
||||||
(List { } [ "item 1" "item 2" "item 3" ])
|
(p [
|
||||||
(p [
|
"check out my"
|
||||||
"check out my"
|
(blue "blue span")
|
||||||
(blue "blue span")
|
"isn't it"
|
||||||
"isn't it"
|
(underblue {onclick = "alert(1)";} "great!")
|
||||||
(underblue { onclick = "alert(1)"; } "great!")
|
|
||||||
])
|
|
||||||
])
|
])
|
||||||
]);
|
])
|
||||||
|
]);
|
||||||
blog = nixite.md.readDir ./testing/blog;
|
blog = nixite.md.readDir ./testing/blog;
|
||||||
};
|
};
|
||||||
site = (nixite.site.prepare { favicon = ./testing/src/favicon.png; }
|
site =
|
||||||
markup);
|
nixite.site.prepare {favicon = ./testing/src/favicon.png;}
|
||||||
in site);
|
markup;
|
||||||
|
in
|
||||||
|
site);
|
||||||
|
|
||||||
default = nixite.serve self.packages.${system}.raw;
|
default = nixite.serve self.packages.${system}.raw;
|
||||||
|
|
||||||
|
@ -54,7 +60,7 @@
|
||||||
./testing/style.test.nix
|
./testing/style.test.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
watch = tix.watch "nix run .#test --show-trace" "fx";
|
watch = tix.watch "nix run .#test | ${pkgs.fx}/bin/fx" "fx";
|
||||||
|
|
||||||
dev = tix.watch "nix run .# --show-trace" "caddy";
|
dev = tix.watch "nix run .# --show-trace" "caddy";
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
{ pkgs, ... }: {
|
{pkgs, ...}: {
|
||||||
mkSite = import ./make-site.nix pkgs;
|
mkSite = import ./make-site.nix pkgs;
|
||||||
serve = site:
|
serve = site: (pkgs.writeShellScriptBin "serve" ''
|
||||||
(pkgs.writeShellScriptBin "serve" ''
|
${pkgs.caddy}/bin/caddy file-server --root ${site}
|
||||||
${pkgs.caddy}/bin/caddy file-server --root ${site}
|
'');
|
||||||
'');
|
|
||||||
md = import ./md.nix;
|
md = import ./md.nix;
|
||||||
html = import ./html.nix;
|
html = import ./html.nix;
|
||||||
elems = import ./elems.nix;
|
elems = import ./elems.nix;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
let html = import ./html.nix;
|
let
|
||||||
|
html = import ./html.nix;
|
||||||
in {
|
in {
|
||||||
html = html.tag "html";
|
html = html.tag "html";
|
||||||
# Document metadata
|
# Document metadata
|
||||||
|
@ -41,13 +42,15 @@ in {
|
||||||
main = html.tag "main";
|
main = html.tag "main";
|
||||||
div = html.tag "div";
|
div = html.tag "div";
|
||||||
# Text-level semantics
|
# Text-level semantics
|
||||||
a = html.tag "a" // {
|
a =
|
||||||
__functor = self: href:
|
html.tag "a"
|
||||||
(if builtins.isString href then
|
// {
|
||||||
(self // html.baseTag) { inherit href; }
|
__functor = self: href: (
|
||||||
else
|
if builtins.isString href
|
||||||
(self // html.baseTag) href);
|
then (self // html.baseTag) {inherit href;}
|
||||||
};
|
else (self // html.baseTag) href
|
||||||
|
);
|
||||||
|
};
|
||||||
em = html.tag "em";
|
em = html.tag "em";
|
||||||
strong = html.tag "strong";
|
strong = html.tag "strong";
|
||||||
small = html.tag "small";
|
small = html.tag "small";
|
||||||
|
@ -130,24 +133,31 @@ in {
|
||||||
canvas = html.tag "canvas";
|
canvas = html.tag "canvas";
|
||||||
|
|
||||||
# custom
|
# custom
|
||||||
List = html.tag "ul" // {
|
List =
|
||||||
__functor = self: children:
|
html.tag "ul"
|
||||||
(if builtins.isList children then
|
// {
|
||||||
(self // html.baseTag) (map (html.tag "li") children)
|
__functor = self: children: (
|
||||||
else
|
if builtins.isList children
|
||||||
html.incorporateAttrs self children);
|
then (self // html.baseTag) (map (html.tag "li") children)
|
||||||
};
|
else html.incorporateAttrs self children
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
Doc = params: child:
|
Doc = params: child:
|
||||||
assert builtins.isList child;
|
assert builtins.isList child;
|
||||||
assert builtins.length child == 2;
|
assert builtins.length child == 2;
|
||||||
assert builtins.isList (builtins.elemAt child 0);
|
assert builtins.isList (builtins.elemAt child 0);
|
||||||
html.tag "html" ({ lang = "en"; } // params) [
|
html.tag "html" ({lang = "en";} // params) [
|
||||||
(html.tag "head" { } (builtins.elemAt child 0))
|
(html.tag "head" {} (builtins.elemAt child 0))
|
||||||
(html.tag "body" { } (builtins.elemAt child 1))
|
(html.tag "body" {} (builtins.elemAt child 1))
|
||||||
];
|
];
|
||||||
Stylesheet = params:
|
Stylesheet = params:
|
||||||
html.tag "link" ({
|
html.tag "link" ({
|
||||||
rel = "stylesheet";
|
rel = "stylesheet";
|
||||||
} // (if builtins.isString params then { href = params; } else params)) "";
|
}
|
||||||
|
// (
|
||||||
|
if builtins.isString params
|
||||||
|
then {href = params;}
|
||||||
|
else params
|
||||||
|
)) "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,70 +1,78 @@
|
||||||
let
|
let
|
||||||
keyvalue = key: value:
|
keyvalue = key: value:
|
||||||
assert builtins.isString key;
|
assert builtins.isString key;
|
||||||
if builtins.isAttrs value then
|
if builtins.isAttrs value
|
||||||
builtins.trace "Skipping ${key} as it is a set" ""
|
then builtins.trace "Skipping ${key} as it is a set" ""
|
||||||
else if value == "" || value == [ ] || value == false then
|
else if value == "" || value == [] || value == false
|
||||||
""
|
then ""
|
||||||
else if value == true then
|
else if value == true
|
||||||
key
|
then key
|
||||||
else
|
else ''${key}="${toString value}"'';
|
||||||
''${key}="${toString value}"'';
|
|
||||||
in rec {
|
in rec {
|
||||||
toHTML = elem:
|
toHTML = elem:
|
||||||
if builtins.isString elem then
|
if builtins.isString elem
|
||||||
elem
|
then elem
|
||||||
else if builtins.isList elem then
|
else if builtins.isList elem
|
||||||
builtins.toString (map toHTML elem)
|
then builtins.toString (map toHTML elem)
|
||||||
else
|
else "<${elem.tag} ${writeAttrs elem.attrs or {}}>${
|
||||||
"<${elem.tag} ${writeAttrs elem.attrs or { }}>${
|
toHTML elem.child or ""
|
||||||
toHTML elem.child or ""
|
}</${elem.tag}>";
|
||||||
}</${elem.tag}>";
|
|
||||||
|
|
||||||
writeAttrs = attrs:
|
writeAttrs = attrs:
|
||||||
toString (builtins.filter (value: value != "") (builtins.attrValues
|
toString (builtins.filter (value: value != "") (builtins.attrValues
|
||||||
(builtins.mapAttrs (key: value:
|
(builtins.mapAttrs (key: value:
|
||||||
if (builtins.isPath value) then
|
if (builtins.isPath value)
|
||||||
keyvalue key (baseNameOf value)
|
then keyvalue key (baseNameOf value)
|
||||||
else if (builtins.substring 0 2 key) == "__" then
|
else if (builtins.substring 0 2 key) == "__"
|
||||||
""
|
then ""
|
||||||
else
|
else keyvalue key value)
|
||||||
keyvalue key value) attrs)));
|
attrs)));
|
||||||
|
|
||||||
tag = t:
|
tag = t: ({
|
||||||
({
|
|
||||||
tag = t;
|
tag = t;
|
||||||
attrs = { };
|
attrs = {};
|
||||||
} // baseTag);
|
}
|
||||||
|
// baseTag);
|
||||||
|
|
||||||
baseTag = {
|
baseTag = {
|
||||||
__toString = self: toString (self "");
|
__toString = self: toString (self "");
|
||||||
__functor = self: child:
|
__functor = self: child: (
|
||||||
(if !(isTag child) then
|
if !(isTag child)
|
||||||
(if isSet child then
|
then
|
||||||
incorporateAttrs self child
|
(
|
||||||
else
|
if isSet child
|
||||||
throw "tag child must be tag, list, or string, got ${
|
then incorporateAttrs self child
|
||||||
builtins.typeOf child
|
else
|
||||||
}")
|
throw "tag child must be tag, list, or string, got ${
|
||||||
|
builtins.typeOf child
|
||||||
|
}"
|
||||||
|
)
|
||||||
else
|
else
|
||||||
self // {
|
self
|
||||||
|
// {
|
||||||
inherit child;
|
inherit child;
|
||||||
__toString = toHTML;
|
__toString = toHTML;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
incorporateAttrs = self: attrs: self // ({ attrs = self.attrs // attrs; });
|
incorporateAttrs = self: attrs: self // {attrs = self.attrs // attrs;};
|
||||||
|
|
||||||
isSet = a: builtins.isAttrs a && !a ? __toString;
|
isSet = a: builtins.isAttrs a && !a ? __toString;
|
||||||
|
|
||||||
isTag = tag:
|
isTag = tag: (builtins.isString tag
|
||||||
(builtins.isString tag || builtins.isList tag
|
|| builtins.isList tag
|
||||||
|| (tag ? __toString && builtins.isFunction tag.__toString));
|
|| (tag ? __toString && builtins.isFunction tag.__toString));
|
||||||
|
|
||||||
addToHead = page: heads:
|
addToHead = page: heads:
|
||||||
page // {
|
page
|
||||||
child = map
|
// {
|
||||||
(e: if e.tag == "head" then e // { child = e.child ++ heads; } else e)
|
child =
|
||||||
|
map
|
||||||
|
(e:
|
||||||
|
if e.tag == "head"
|
||||||
|
then e // {child = e.child ++ heads;}
|
||||||
|
else e)
|
||||||
page.child;
|
page.child;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
{ stdenv, ... }:
|
{stdenv, ...}: raw: let
|
||||||
raw:
|
site = import ./site.nix;
|
||||||
let site = import ./site.nix;
|
in
|
||||||
in stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "site";
|
name = "site";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
mkdir dist
|
mkdir dist
|
||||||
|
|
||||||
${site.copyTo "dist" raw}
|
${site.copyTo "dist" raw}
|
||||||
|
|
||||||
'';
|
'';
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
cp -r dist $out
|
cp -r dist $out
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
200
nixite/md.nix
200
nixite/md.nix
|
@ -1,57 +1,55 @@
|
||||||
let elems = import ./elems.nix;
|
let
|
||||||
|
elems = import ./elems.nix;
|
||||||
in rec {
|
in rec {
|
||||||
readMd = md:
|
readMd = md:
|
||||||
if builtins.isPath md then
|
if builtins.isPath md
|
||||||
processMd (builtins.readFile md)
|
then processMd (builtins.readFile md)
|
||||||
else
|
else processMd md;
|
||||||
processMd md;
|
|
||||||
|
|
||||||
processMd = processStr;
|
processMd = processStr;
|
||||||
|
|
||||||
recReadMd = root:
|
recReadMd = root:
|
||||||
assert builtins.isPath root;
|
assert builtins.isPath root;
|
||||||
builtins.mapAttrs (path: type:
|
builtins.mapAttrs (path: type:
|
||||||
if type == "directory" then
|
if type == "directory"
|
||||||
recReadMd (root + (/. + path))
|
then recReadMd (root + (/. + path))
|
||||||
else if type == "regular" then
|
else if type == "regular"
|
||||||
mdToPage (root + (/. + path))
|
then mdToPage (root + (/. + path))
|
||||||
else
|
else throw "Cannot read ${path}, file type ${type}") (builtins.readDir root);
|
||||||
throw "Cannot read ${path}, file type ${type}") (builtins.readDir root);
|
|
||||||
|
|
||||||
recFixAppendix = site:
|
recFixAppendix = site:
|
||||||
builtins.listToAttrs (builtins.attrValues (builtins.mapAttrs (name: value: {
|
builtins.listToAttrs (builtins.attrValues (builtins.mapAttrs (name: value: {
|
||||||
name = fixAppendix name;
|
name = fixAppendix name;
|
||||||
value = if builtins.isAttrs value then recFixAppendix value else value;
|
value =
|
||||||
}) site));
|
if builtins.isAttrs value
|
||||||
|
then recFixAppendix value
|
||||||
|
else value;
|
||||||
|
})
|
||||||
|
site));
|
||||||
|
|
||||||
fixAppendix = builtins.replaceStrings [ ".md" ] [ ".html" ];
|
fixAppendix = builtins.replaceStrings [".md"] [".html"];
|
||||||
|
|
||||||
readDir = root: recFixAppendix (recReadMd root);
|
readDir = root: recFixAppendix (recReadMd root);
|
||||||
|
|
||||||
mdToPage = md:
|
mdToPage = md:
|
||||||
elems.Doc { } [ [ (elems.title { } "markdown file") ] (readMd md) ];
|
elems.Doc {} [[(elems.title {} "markdown file")] (readMd md)];
|
||||||
|
|
||||||
code = block:
|
|
||||||
matchThen "(```)(.*)(```)" block (m: elems.code (builtins.elemAt m 1));
|
|
||||||
|
|
||||||
list = block:
|
list = block:
|
||||||
matchThen (''
|
matchThen "(- .+\n)*(- .+\n?)"
|
||||||
(- .+
|
block (m: elems.List (splitList block));
|
||||||
)*(- .+
|
|
||||||
?)'') block (m: elems.List (splitList block));
|
|
||||||
|
|
||||||
splitList = block:
|
splitList = block:
|
||||||
map (listItem) (builtins.filter (s: builtins.isString s && s != "")
|
map listItem (builtins.filter (s: builtins.isString s && s != "")
|
||||||
(builtins.split "\n" block));
|
(builtins.split "\n" block));
|
||||||
|
|
||||||
listItem = str:
|
listItem = str: let
|
||||||
let
|
li = builtins.match "- (.*)" str;
|
||||||
li = builtins.match "- (.*)" str;
|
checkbox = builtins.match "- \\[(.)] (.*)" str;
|
||||||
checkbox = builtins.match "- \\[(.)] (.*)" str;
|
checked = builtins.elemAt checkbox 0;
|
||||||
checked = builtins.elemAt checkbox 0;
|
content = builtins.elemAt checkbox 1;
|
||||||
content = builtins.elemAt checkbox 1;
|
in
|
||||||
in if checkbox == null then
|
if checkbox == null
|
||||||
li
|
then li
|
||||||
else [
|
else [
|
||||||
(elems.input {
|
(elems.input {
|
||||||
type = "checkbox";
|
type = "checkbox";
|
||||||
|
@ -61,28 +59,41 @@ in rec {
|
||||||
content
|
content
|
||||||
];
|
];
|
||||||
|
|
||||||
replace = regex: apply: block:
|
replace = regex: apply: block: (let
|
||||||
(let
|
m = builtins.match regex block;
|
||||||
m = builtins.match regex block;
|
before = let
|
||||||
before = let v = builtins.elemAt m 0; in if v == null then "" else v;
|
v = builtins.elemAt m 0;
|
||||||
after = toString (builtins.elemAt m (matchCount - 1));
|
in
|
||||||
matchCount = builtins.length m;
|
if v == null
|
||||||
in if m == null then
|
then ""
|
||||||
block
|
else v;
|
||||||
else
|
after = toString (builtins.elemAt m (matchCount - 1));
|
||||||
(replace regex apply before) + (apply m) + after);
|
matchCount = builtins.length m;
|
||||||
|
in
|
||||||
|
if m == null
|
||||||
|
then block
|
||||||
|
else (replace regex apply before) + (apply m) + after);
|
||||||
|
|
||||||
rule = matcher: apply: blocks:
|
rule = matcher: apply: blocks:
|
||||||
map (b: if builtins.isString b then replace matcher apply b else b) blocks;
|
map (b:
|
||||||
|
if builtins.isString b
|
||||||
|
then replace matcher apply b
|
||||||
|
else b)
|
||||||
|
blocks;
|
||||||
|
|
||||||
applyRules = i: rules: input:
|
applyRules = i: rules: input: let
|
||||||
let
|
group =
|
||||||
group = if builtins.isString input then [ input ] else input;
|
if builtins.isString input
|
||||||
len = builtins.length rules;
|
then [input]
|
||||||
rule = builtins.elemAt rules i;
|
else input;
|
||||||
next = i + 1;
|
len = builtins.length rules;
|
||||||
in assert i < len;
|
rule = builtins.elemAt rules i;
|
||||||
if next < len then rule (applyRules next rules group) else rule group;
|
next = i + 1;
|
||||||
|
in
|
||||||
|
assert i < len;
|
||||||
|
if next < len
|
||||||
|
then rule (applyRules next rules group)
|
||||||
|
else rule group;
|
||||||
|
|
||||||
basicRule = matcher: elem: rule matcher (m: elem (builtins.elemAt m 1));
|
basicRule = matcher: elem: rule matcher (m: elem (builtins.elemAt m 1));
|
||||||
|
|
||||||
|
@ -96,60 +107,27 @@ in rec {
|
||||||
(basicRule (wrap "~~") elems.del)
|
(basicRule (wrap "~~") elems.del)
|
||||||
(basicRule (wrap "\\*\\*") elems.strong)
|
(basicRule (wrap "\\*\\*") elems.strong)
|
||||||
(basicRule (wrapBreak "__") elems.strong)
|
(basicRule (wrapBreak "__") elems.strong)
|
||||||
(rule (contains "\\[(.*)]\\((.*)\\)") (m:
|
(rule (contains "\\[(.*)]\\((.*)\\)") (m: let
|
||||||
let
|
href = builtins.elemAt m 2;
|
||||||
href = builtins.elemAt m 2;
|
text = builtins.elemAt m 1;
|
||||||
text = builtins.elemAt m 1;
|
in (elems.a href text)))
|
||||||
in (elems.a href text)))
|
(rule "(.*\n)([^-][^\n]+\n)((- [^\n]+\n)+)(.*)" (
|
||||||
(rule (''
|
l: (elems.ul (basicRule "(.*\n)?- ([^\n]+)\n(.*)" (m:
|
||||||
(.*
|
elems.li (basicRule "()\\[(.)](.*)" (check:
|
||||||
)([^-][^
|
elems.input {
|
||||||
]+
|
type = "checkbox";
|
||||||
)((- [^
|
checked = check != " ";
|
||||||
]+
|
disabled = true;
|
||||||
)+)(.*)'') (
|
}) [m])) [(builtins.elemAt l 2)]))
|
||||||
|
))
|
||||||
l:
|
(basicRule "(.*\n\n)?(.+)\n(.*)?" elems.p)
|
||||||
(elems.ul (basicRule (''
|
(basicRule "(.*\n\n)?```(.*)```(.*)?" (elems.textarea {readonly = true;}))
|
||||||
(.*
|
(basicRule (containsBreak "###### ([^\n]+)") (elems.h6))
|
||||||
)?- ([^
|
(basicRule (containsBreak "##### ([^\n]+)") (elems.h5))
|
||||||
]+)
|
(basicRule (containsBreak "#### ([^\n]+)") (elems.h4))
|
||||||
(.*)'') (m:
|
(basicRule (containsBreak "### ([^\n]+)") (elems.h3))
|
||||||
elems.li (basicRule ("()\\[(.)](.*)") (check:
|
(basicRule (containsBreak "## ([^\n]+)") (elems.h2))
|
||||||
elems.input {
|
(basicRule (containsBreak "# ([^\n]+)") (elems.h1))
|
||||||
type = "checkbox";
|
|
||||||
checked = check != " ";
|
|
||||||
disabled = true;
|
|
||||||
}) [ m ])) [ (builtins.elemAt l 2) ]))
|
|
||||||
|
|
||||||
))
|
|
||||||
(basicRule (''
|
|
||||||
(.*
|
|
||||||
|
|
||||||
)?(.+)
|
|
||||||
(.*)?'') elems.p)
|
|
||||||
(basicRule (''
|
|
||||||
(.*
|
|
||||||
|
|
||||||
)?```(.*)```(.*)?'') (elems.textarea { readonly = true; }))
|
|
||||||
(basicRule (containsBreak ''
|
|
||||||
###### ([^
|
|
||||||
]+)'') (elems.h6))
|
|
||||||
(basicRule (containsBreak ''
|
|
||||||
##### ([^
|
|
||||||
]+)'') (elems.h5))
|
|
||||||
(basicRule (containsBreak ''
|
|
||||||
#### ([^
|
|
||||||
]+)'') (elems.h4))
|
|
||||||
(basicRule (containsBreak ''
|
|
||||||
### ([^
|
|
||||||
]+)'') (elems.h3))
|
|
||||||
(basicRule (containsBreak ''
|
|
||||||
## ([^
|
|
||||||
]+)'') (elems.h2))
|
|
||||||
(basicRule (containsBreak ''
|
|
||||||
# ([^
|
|
||||||
]+)'') (elems.h1))
|
|
||||||
(basicRule (containsBreak "<(${linkmatcher})>") (m: elems.a m m))
|
(basicRule (containsBreak "<(${linkmatcher})>") (m: elems.a m m))
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -160,10 +138,11 @@ in rec {
|
||||||
containsBreak = matcher: "(.*[[:space:]])?${matcher}(.*)";
|
containsBreak = matcher: "(.*[[:space:]])?${matcher}(.*)";
|
||||||
wrapBreak = matcher: containsBreak "${matcher}([^${matcher}]+)${matcher}";
|
wrapBreak = matcher: containsBreak "${matcher}([^${matcher}]+)${matcher}";
|
||||||
|
|
||||||
matchThen = matcher: block: func:
|
matchThen = matcher: block: func: let
|
||||||
let m = builtins.match matcher block;
|
m = builtins.match matcher block;
|
||||||
in if m == null then
|
in
|
||||||
dontMatch block
|
if m == null
|
||||||
|
then dontMatch block
|
||||||
else {
|
else {
|
||||||
matched = true;
|
matched = true;
|
||||||
block = func m;
|
block = func m;
|
||||||
|
@ -173,5 +152,4 @@ in rec {
|
||||||
matched = false;
|
matched = false;
|
||||||
inherit block;
|
inherit block;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
152
nixite/site.nix
152
nixite/site.nix
|
@ -3,13 +3,17 @@ let
|
||||||
elems = import ./elems.nix;
|
elems = import ./elems.nix;
|
||||||
style = import ./style.nix;
|
style = import ./style.nix;
|
||||||
in rec {
|
in rec {
|
||||||
prepare = { favicon ? null, styles ? { }, }:
|
prepare = {
|
||||||
site:
|
favicon ? null,
|
||||||
let
|
styles ? {},
|
||||||
nullFn = p: p;
|
}: site: let
|
||||||
allStyles = styles // getStyles site;
|
nullFn = p: p;
|
||||||
doFavicon = if favicon != null then (applyFavicon favicon) else nullFn;
|
allStyles = styles // getStyles site;
|
||||||
in (extractPaths (extractLinks (applyStyle allStyles (doFavicon site))));
|
doFavicon =
|
||||||
|
if favicon != null
|
||||||
|
then (applyFavicon favicon)
|
||||||
|
else nullFn;
|
||||||
|
in (extractPaths (extractLinks (applyStyle allStyles (doFavicon site))));
|
||||||
|
|
||||||
getStyles = site:
|
getStyles = site:
|
||||||
builtins.zipAttrsWith (name: value: builtins.elemAt value 0)
|
builtins.zipAttrsWith (name: value: builtins.elemAt value 0)
|
||||||
|
@ -17,27 +21,25 @@ in rec {
|
||||||
|
|
||||||
flatten = site:
|
flatten = site:
|
||||||
map (page:
|
map (page:
|
||||||
if builtins.isAttrs page && page ? "__toString" then
|
if builtins.isAttrs page && page ? "__toString"
|
||||||
page
|
then page
|
||||||
else if builtins.isAttrs page then
|
else if builtins.isAttrs page
|
||||||
flatten page
|
then flatten page
|
||||||
else
|
else page) (builtins.attrValues site);
|
||||||
page) (builtins.attrValues site);
|
|
||||||
|
|
||||||
applyStyle = style: site: ((linkStyle site) // { "style.css" = style; });
|
applyStyle = style: site: ((linkStyle site) // {"style.css" = style;});
|
||||||
|
|
||||||
linkStyle = site:
|
linkStyle = site:
|
||||||
eachPage site
|
eachPage site
|
||||||
(content: html.addToHead content [ (elems.Stylesheet "/style.css") ]);
|
(content: html.addToHead content [(elems.Stylesheet "/style.css")]);
|
||||||
|
|
||||||
eachPage = site: callback:
|
eachPage = site: callback: (builtins.mapAttrs (name: content:
|
||||||
(builtins.mapAttrs (name: content:
|
if builtins.isAttrs content && content ? "__toString"
|
||||||
if builtins.isAttrs content && content ? "__toString" then
|
then callback content
|
||||||
callback content
|
else if builtins.isAttrs content
|
||||||
else if builtins.isAttrs content then
|
then eachPage content callback
|
||||||
eachPage content callback
|
else content)
|
||||||
else
|
site);
|
||||||
content) site);
|
|
||||||
|
|
||||||
applyFavicon = icon: site:
|
applyFavicon = icon: site:
|
||||||
eachPage site (content:
|
eachPage site (content:
|
||||||
|
@ -49,19 +51,21 @@ in rec {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
extractPaths = content:
|
extractPaths = content:
|
||||||
switchPaths content // {
|
switchPaths content
|
||||||
static = (content.static or { }) // getPaths content;
|
// {
|
||||||
|
static = (content.static or {}) // getPaths content;
|
||||||
};
|
};
|
||||||
|
|
||||||
extractLinks = content:
|
extractLinks = content:
|
||||||
switchLinks content // {
|
switchLinks content
|
||||||
static = (content.static or { }) // getLinks content;
|
// {
|
||||||
|
static = (content.static or {}) // getLinks content;
|
||||||
};
|
};
|
||||||
|
|
||||||
isLink = value:
|
isLink = value:
|
||||||
builtins.isAttrs value && value ? type && value.type == "link";
|
builtins.isAttrs value && value ? type && value.type == "link";
|
||||||
|
|
||||||
switchLinks = runDeep (isLink) (value: "/static/" + value.name);
|
switchLinks = runDeep isLink (value: "/static/" + value.name);
|
||||||
|
|
||||||
getLinks = content: (builtins.listToAttrs (getLinksKV content));
|
getLinks = content: (builtins.listToAttrs (getLinksKV content));
|
||||||
|
|
||||||
|
@ -72,19 +76,30 @@ in rec {
|
||||||
};
|
};
|
||||||
|
|
||||||
runLink = f:
|
runLink = f:
|
||||||
if !builtins.isFunction f then
|
if !builtins.isFunction f
|
||||||
null
|
then null
|
||||||
else
|
else
|
||||||
(let res = f { }; in (if !builtins.isAttrs res then null else res));
|
(let
|
||||||
|
res = f {};
|
||||||
|
in (
|
||||||
|
if !builtins.isAttrs res
|
||||||
|
then null
|
||||||
|
else res
|
||||||
|
));
|
||||||
|
|
||||||
runDeep = when: do: set:
|
runDeep = when: do: set: (
|
||||||
(if builtins.isAttrs set then
|
if builtins.isAttrs set
|
||||||
|
then
|
||||||
builtins.mapAttrs
|
builtins.mapAttrs
|
||||||
(key: value: if when value then do value else runDeep when do value) set
|
(key: value:
|
||||||
else if builtins.isList set then
|
if when value
|
||||||
(map (runDeep when do) set)
|
then do value
|
||||||
else
|
else runDeep when do value)
|
||||||
set);
|
set
|
||||||
|
else if builtins.isList set
|
||||||
|
then (map (runDeep when do) set)
|
||||||
|
else set
|
||||||
|
);
|
||||||
|
|
||||||
switchPaths = runDeep builtins.isPath (value: "/static/" + baseNameOf value);
|
switchPaths = runDeep builtins.isPath (value: "/static/" + baseNameOf value);
|
||||||
|
|
||||||
|
@ -96,35 +111,60 @@ in rec {
|
||||||
value = v: v;
|
value = v: v;
|
||||||
};
|
};
|
||||||
|
|
||||||
getAllKV = { when, key, value }@params:
|
getAllKV = {
|
||||||
path:
|
when,
|
||||||
(if when path then [{
|
key,
|
||||||
name = key path;
|
value,
|
||||||
value = value path;
|
} @ params: path: (
|
||||||
}] else if builtins.isAttrs path then
|
if when path
|
||||||
|
then [
|
||||||
|
{
|
||||||
|
name = key path;
|
||||||
|
value = value path;
|
||||||
|
}
|
||||||
|
]
|
||||||
|
else if builtins.isAttrs path
|
||||||
|
then
|
||||||
builtins.concatMap (getAllKV params) (builtins.attrValues
|
builtins.concatMap (getAllKV params) (builtins.attrValues
|
||||||
(builtins.mapAttrs
|
(builtins.mapAttrs
|
||||||
(n: v: if (builtins.substring 0 2 n == "__") then null else v) path))
|
(n: v:
|
||||||
else if builtins.isList path then
|
if (builtins.substring 0 2 n == "__")
|
||||||
builtins.concatMap (getAllKV params) path
|
then null
|
||||||
else
|
else v)
|
||||||
[ ]);
|
path))
|
||||||
|
else if builtins.isList path
|
||||||
|
then builtins.concatMap (getAllKV params) path
|
||||||
|
else []
|
||||||
|
);
|
||||||
|
|
||||||
link = { name, content }@page: page // { type = "link"; };
|
link = {
|
||||||
|
name,
|
||||||
|
content,
|
||||||
|
} @ page:
|
||||||
|
page // {type = "link";};
|
||||||
|
|
||||||
copyTo = prefix: site:
|
copyTo = prefix: site:
|
||||||
builtins.toString (builtins.attrValues (builtins.mapAttrs (name: content:
|
builtins.toString (builtins.attrValues (builtins.mapAttrs (name: content:
|
||||||
if builtins.isString content then ''
|
if builtins.isString content
|
||||||
|
then ''
|
||||||
cp ${builtins.toFile name content} ${prefix}/${name}
|
cp ${builtins.toFile name content} ${prefix}/${name}
|
||||||
'' else if builtins.isPath content then ''
|
''
|
||||||
|
else if builtins.isPath content
|
||||||
|
then ''
|
||||||
cp -r ${content} ${prefix}/${name}
|
cp -r ${content} ${prefix}/${name}
|
||||||
'' else if builtins.isAttrs content && content ? "__toString" then ''
|
''
|
||||||
|
else if builtins.isAttrs content && content ? "__toString"
|
||||||
|
then ''
|
||||||
cp ${builtins.toFile name (toString content)} ${prefix}/${name}
|
cp ${builtins.toFile name (toString content)} ${prefix}/${name}
|
||||||
'' else if builtins.isAttrs content then ''
|
''
|
||||||
|
else if builtins.isAttrs content
|
||||||
|
then ''
|
||||||
mkdir -p ${prefix}/${name}
|
mkdir -p ${prefix}/${name}
|
||||||
${copyTo "${prefix}/${name}" content}
|
${copyTo "${prefix}/${name}" content}
|
||||||
'' else
|
''
|
||||||
|
else
|
||||||
throw "Site page must be string, path or attrset, but got ${
|
throw "Site page must be string, path or attrset, but got ${
|
||||||
builtins.typeOf content
|
builtins.typeOf content
|
||||||
}: [${toString content}]") site));
|
}: [${toString content}]")
|
||||||
|
site));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +1,63 @@
|
||||||
let
|
let
|
||||||
|
|
||||||
styleToString = identifier: styles:
|
styleToString = identifier: styles:
|
||||||
if !builtins.isAttrs styles then
|
if !builtins.isAttrs styles
|
||||||
""
|
then ""
|
||||||
else if styles == { } then
|
else if styles == {}
|
||||||
""
|
then ""
|
||||||
else
|
else
|
||||||
assert builtins.isString identifier; ''
|
assert builtins.isString identifier; ''
|
||||||
${identifier} {
|
${identifier} {
|
||||||
${
|
${
|
||||||
toString (builtins.attrValues
|
toString (builtins.attrValues
|
||||||
(builtins.mapAttrs (key: value: "${key}: ${value};") styles))
|
(builtins.mapAttrs (key: value: "${key}: ${value};") styles))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
getStyle = element:
|
getStyle = element:
|
||||||
if builtins.isAttrs element && element.attrs ? __id then
|
if builtins.isAttrs element && element.attrs ? __id
|
||||||
|
then
|
||||||
({
|
({
|
||||||
${element.attrs.__id} = element.attrs.style or { };
|
${element.attrs.__id} = element.attrs.style or {};
|
||||||
} // (if element.attrs ? __extends then {
|
}
|
||||||
${element.attrs.__extends.attrs.__id or element.attrs.__extends.tag} =
|
// (
|
||||||
element.attrs.__extends.attrs.style or { };
|
if element.attrs ? __extends
|
||||||
} else
|
then {
|
||||||
{ }))
|
${element.attrs.__extends.attrs.__id or element.attrs.__extends.tag} =
|
||||||
else
|
element.attrs.__extends.attrs.style or {};
|
||||||
{ };
|
}
|
||||||
|
else {}
|
||||||
|
))
|
||||||
|
else {};
|
||||||
|
|
||||||
getStyles = element:
|
getStyles = element:
|
||||||
(getStyle element) // (if builtins.isList element then
|
(getStyle element)
|
||||||
getStylesFromList element
|
// (
|
||||||
else if element ? child then
|
if builtins.isList element
|
||||||
getStyles element.child
|
then getStylesFromList element
|
||||||
else
|
else if element ? child
|
||||||
{ }) // {
|
then getStyles element.child
|
||||||
__toString = stylesToString;
|
else {}
|
||||||
};
|
)
|
||||||
|
// {
|
||||||
|
__toString = stylesToString;
|
||||||
|
};
|
||||||
|
|
||||||
getStylesFromList = elements:
|
getStylesFromList = elements:
|
||||||
builtins.zipAttrsWith (name: value: builtins.elemAt value 0)
|
builtins.zipAttrsWith (name: value: builtins.elemAt value 0)
|
||||||
(map getStyles elements);
|
(map getStyles elements);
|
||||||
|
|
||||||
mkProps = tag: class: props:
|
mkProps = tag: class: props:
|
||||||
props // {
|
props
|
||||||
|
// {
|
||||||
__id = "${tag.tag}.${class}";
|
__id = "${tag.tag}.${class}";
|
||||||
__extends = tag;
|
__extends = tag;
|
||||||
class = (tag.attrs.class or [ ]) ++ [ class ] ++ (props.class or [ ]);
|
class = (tag.attrs.class or []) ++ [class] ++ (props.class or []);
|
||||||
};
|
};
|
||||||
|
|
||||||
stylesToString = styles:
|
stylesToString = styles:
|
||||||
builtins.concatStringsSep ""
|
builtins.concatStringsSep ""
|
||||||
(builtins.attrValues (builtins.mapAttrs (styleToString) styles));
|
(builtins.attrValues (builtins.mapAttrs styleToString styles));
|
||||||
|
|
||||||
in {
|
in {
|
||||||
inherit getStyle getStyles stylesToString;
|
inherit getStyle getStyles stylesToString;
|
||||||
|
|
||||||
|
|
|
@ -1,83 +1,86 @@
|
||||||
{ it, ... }:
|
{it, ...}: let
|
||||||
let
|
|
||||||
elems = import ../nixite/elems.nix;
|
elems = import ../nixite/elems.nix;
|
||||||
style = import ../nixite/style.nix;
|
style = import ../nixite/style.nix;
|
||||||
html = import ../nixite/html.nix;
|
html = import ../nixite/html.nix;
|
||||||
in with elems; [
|
in
|
||||||
(it "makes a p tag" {
|
with elems; [
|
||||||
expected = html.tag "p" { } "foobar";
|
(it "makes a p tag" {
|
||||||
actual = p { } "foobar";
|
expected = html.tag "p" {} "foobar";
|
||||||
asString = true;
|
actual = p {} "foobar";
|
||||||
})
|
asString = true;
|
||||||
(it "makes a div tag" {
|
})
|
||||||
expected = html.tag "div" { } "foobar";
|
(it "makes a div tag" {
|
||||||
actual = div { } "foobar";
|
expected = html.tag "div" {} "foobar";
|
||||||
asString = true;
|
actual = div {} "foobar";
|
||||||
})
|
asString = true;
|
||||||
(it "makes a section tag" {
|
})
|
||||||
expected = html.tag "section" { } "foobar";
|
(it "makes a section tag" {
|
||||||
actual = section { } "foobar";
|
expected = html.tag "section" {} "foobar";
|
||||||
asString = true;
|
actual = section {} "foobar";
|
||||||
})
|
asString = true;
|
||||||
(it "makes a span tag" {
|
})
|
||||||
expected = html.tag "span" { } "foobar";
|
(it "makes a span tag" {
|
||||||
actual = span { } "foobar";
|
expected = html.tag "span" {} "foobar";
|
||||||
asString = true;
|
actual = span {} "foobar";
|
||||||
})
|
asString = true;
|
||||||
(it "makes a main tag" {
|
})
|
||||||
expected = html.tag "main" { } [ "yeet" ];
|
(it "makes a main tag" {
|
||||||
actual = main { } [ "yeet" ];
|
expected = html.tag "main" {} ["yeet"];
|
||||||
asString = true;
|
actual = main {} ["yeet"];
|
||||||
})
|
asString = true;
|
||||||
(it "makes a title tag" {
|
})
|
||||||
expected = html.tag "title" { } "foobar";
|
(it "makes a title tag" {
|
||||||
actual = title { } "foobar";
|
expected = html.tag "title" {} "foobar";
|
||||||
asString = true;
|
actual = title {} "foobar";
|
||||||
})
|
asString = true;
|
||||||
|
})
|
||||||
|
|
||||||
(it "makes an a tag" {
|
(it "makes an a tag" {
|
||||||
expected = html.tag "a" { href = "https://example.com"; } "example";
|
expected = html.tag "a" {href = "https://example.com";} "example";
|
||||||
actual = a { href = "https://example.com"; } "example";
|
actual = a {href = "https://example.com";} "example";
|
||||||
asString = true;
|
asString = true;
|
||||||
})
|
})
|
||||||
|
|
||||||
(it "lets the a tag drop the props" {
|
(it "lets the a tag drop the props" {
|
||||||
expected = html.tag "a" { href = "https://example.com"; } "example";
|
expected = html.tag "a" {href = "https://example.com";} "example";
|
||||||
actual = a "https://example.com" "example";
|
actual = a "https://example.com" "example";
|
||||||
asString = true;
|
asString = true;
|
||||||
})
|
})
|
||||||
|
|
||||||
(it "lets you extend the a tag" {
|
(it "lets you extend the a tag" {
|
||||||
expected = [ "linky" ];
|
expected = ["linky"];
|
||||||
actual = ((style.component a "linky" { }) "https://example.com"
|
actual =
|
||||||
"example").attrs.class;
|
((style.component a "linky" {}) "https://example.com"
|
||||||
asString = true;
|
"example")
|
||||||
})
|
.attrs
|
||||||
|
.class;
|
||||||
|
asString = true;
|
||||||
|
})
|
||||||
|
|
||||||
(it "makes a stylesheet link" {
|
(it "makes a stylesheet link" {
|
||||||
expected = html.tag "link" {
|
expected = html.tag "link" {
|
||||||
href = "/style";
|
href = "/style";
|
||||||
rel = "stylesheet";
|
rel = "stylesheet";
|
||||||
} "";
|
} "";
|
||||||
actual = Stylesheet { href = "/style"; };
|
actual = Stylesheet {href = "/style";};
|
||||||
asString = true;
|
asString = true;
|
||||||
})
|
})
|
||||||
(it "makes a list" {
|
(it "makes a list" {
|
||||||
expected = html.tag "ul" { __ = ""; } [
|
expected = html.tag "ul" {__ = "";} [
|
||||||
(html.tag "li" { } "foo")
|
(html.tag "li" {} "foo")
|
||||||
(html.tag "li" { } "bar")
|
(html.tag "li" {} "bar")
|
||||||
(html.tag "li" { } "baz")
|
(html.tag "li" {} "baz")
|
||||||
];
|
];
|
||||||
actual = List { } [ "foo" "bar" "baz" ];
|
actual = List {} ["foo" "bar" "baz"];
|
||||||
asString = true;
|
asString = true;
|
||||||
})
|
})
|
||||||
(it "makes an html doc" {
|
(it "makes an html doc" {
|
||||||
expected = html.tag "html" {
|
expected = html.tag "html" {
|
||||||
__child = "";
|
__child = "";
|
||||||
class = [ ];
|
class = [];
|
||||||
lang = "en";
|
lang = "en";
|
||||||
} [ (html.tag "head" { } [ "foo" ]) (html.tag "body" { } "bar") ];
|
} [(html.tag "head" {} ["foo"]) (html.tag "body" {} "bar")];
|
||||||
actual = Doc { } [ [ "foo" ] "bar" ];
|
actual = Doc {} [["foo"] "bar"];
|
||||||
asString = true;
|
asString = true;
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,142 +1,149 @@
|
||||||
{ it, ... }:
|
{it, ...}: let
|
||||||
let html = import ../nixite/html.nix;
|
html = import ../nixite/html.nix;
|
||||||
in with html; [
|
in
|
||||||
|
with html; [
|
||||||
|
(it "keeps info in the tag" (let
|
||||||
|
p = tag "p";
|
||||||
|
in {
|
||||||
|
actual = p.tag;
|
||||||
|
expected = "p";
|
||||||
|
}))
|
||||||
|
|
||||||
(it "keeps info in the tag" (let p = tag "p";
|
(it "keeps attr info in the tag" (let
|
||||||
in {
|
p = tag "p" {class = "";};
|
||||||
actual = p.tag;
|
in {
|
||||||
expected = "p";
|
actual = p.attrs;
|
||||||
}))
|
expected = {class = "";};
|
||||||
|
}))
|
||||||
|
|
||||||
(it "keeps attr info in the tag" (let p = tag "p" { class = ""; };
|
(it "keeps tag after setting attrs" (let
|
||||||
in {
|
p = tag "p" {class = "";};
|
||||||
actual = p.attrs;
|
in {
|
||||||
expected = { class = ""; };
|
actual = p.tag;
|
||||||
}))
|
expected = "p";
|
||||||
|
}))
|
||||||
|
|
||||||
(it "keeps tag after setting attrs" (let p = tag "p" { class = ""; };
|
(it "makes a p tag" {
|
||||||
in {
|
actual = tag "p" {} "Hello";
|
||||||
actual = p.tag;
|
expected = {
|
||||||
expected = "p";
|
tag = "p";
|
||||||
}))
|
attrs = {};
|
||||||
|
child = "Hello";
|
||||||
|
};
|
||||||
|
removeDunders = true;
|
||||||
|
})
|
||||||
|
|
||||||
(it "makes a p tag" {
|
(it "makes element" (let
|
||||||
actual = tag "p" { } "Hello";
|
para = tag "p" {};
|
||||||
expected = {
|
in {
|
||||||
tag = "p";
|
expected = "p";
|
||||||
attrs = { };
|
actual = para.tag;
|
||||||
child = "Hello";
|
}))
|
||||||
};
|
|
||||||
removeDunders = true;
|
|
||||||
})
|
|
||||||
|
|
||||||
(it "makes element" (let para = (tag "p" { });
|
(it "keeps attrs on element" (let
|
||||||
in {
|
attrs = {style = {foo = "bar";};};
|
||||||
expected = "p";
|
para = tag "p" attrs;
|
||||||
actual = para.tag;
|
in {
|
||||||
}))
|
expected = attrs;
|
||||||
|
actual = para.attrs;
|
||||||
|
}))
|
||||||
|
|
||||||
(it "keeps attrs on element" (let
|
(it "makes renderable element" (let
|
||||||
attrs = { style = { foo = "bar"; }; };
|
attrs = {style = {foo = "bar";};};
|
||||||
para = (tag "p" attrs);
|
para = tag "p" attrs;
|
||||||
in {
|
in {
|
||||||
expected = attrs;
|
expected = "<p ></p>";
|
||||||
actual = para.attrs;
|
actual = toString (para "");
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "makes renderable element" (let
|
(it "keeps tag" (let
|
||||||
attrs = { style = { foo = "bar"; }; };
|
attrs = {style = {foo = "bar";};};
|
||||||
para = (tag "p" attrs);
|
para = tag "p" attrs;
|
||||||
in {
|
in {
|
||||||
expected = "<p ></p>";
|
expected = "p";
|
||||||
actual = toString (para "");
|
actual = (para "").tag;
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "keeps tag" (let
|
(it "keeps style" (let
|
||||||
attrs = { style = { foo = "bar"; }; };
|
attrs = {style = {foo = "bar";};};
|
||||||
para = (tag "p" attrs);
|
para = tag "p" attrs;
|
||||||
in {
|
in {
|
||||||
expected = "p";
|
expected = {foo = "bar";};
|
||||||
actual = (para "").tag;
|
actual = (para "").attrs.style;
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "keeps style" (let
|
(it "needs no args to make string" (let
|
||||||
attrs = { style = { foo = "bar"; }; };
|
p = tag "p";
|
||||||
para = (tag "p" attrs);
|
in {
|
||||||
in {
|
actual = toString p;
|
||||||
expected = { foo = "bar"; };
|
expected = "<p ></p>";
|
||||||
actual = (para "").attrs.style;
|
}))
|
||||||
}))
|
|
||||||
|
|
||||||
(it "needs no args to make string" (let p = tag "p";
|
(it "needs no content to make string" (let
|
||||||
in {
|
p = tag "p";
|
||||||
actual = toString p;
|
in {
|
||||||
expected = "<p ></p>";
|
actual = toString (p {class = "foobar";});
|
||||||
}))
|
expected = ''<p class="foobar"></p>'';
|
||||||
|
}))
|
||||||
|
|
||||||
(it "needs no content to make string" (let p = tag "p";
|
(it "can take many sets of props" (let
|
||||||
in {
|
p = tag "p";
|
||||||
actual = toString (p { class = "foobar"; });
|
in {
|
||||||
expected = ''<p class="foobar"></p>'';
|
actual = toString (p {class = "foobar";} {style = "a style";});
|
||||||
}))
|
expected = ''<p class="foobar" style="a style"></p>'';
|
||||||
|
}))
|
||||||
|
|
||||||
(it "can take many sets of props" (let p = tag "p";
|
(it "works recursively" (let
|
||||||
in {
|
attrs = {style = {foo = "bar";};};
|
||||||
actual = toString (p { class = "foobar"; } { style = "a style"; });
|
para = tag "p" attrs;
|
||||||
expected = ''<p class="foobar" style="a style"></p>'';
|
a = tag "a" {};
|
||||||
}))
|
in {
|
||||||
|
expected = "<p ><a >hello</a></p>";
|
||||||
|
actual = toString (para (a "hello"));
|
||||||
|
}))
|
||||||
|
|
||||||
(it "works recursively" (let
|
(it "throws with function child" {
|
||||||
attrs = { style = { foo = "bar"; }; };
|
actual = toString (tag "p" (i: ""));
|
||||||
para = (tag "p" attrs);
|
throws = true;
|
||||||
a = (tag "a" { });
|
})
|
||||||
in {
|
|
||||||
expected = "<p ><a >hello</a></p>";
|
|
||||||
actual = toString (para (a "hello"));
|
|
||||||
}))
|
|
||||||
|
|
||||||
(it "throws with function child" ({
|
(it "throws with a number" {
|
||||||
actual = toString (tag "p" (i: ""));
|
actual = toString (tag "p" 5);
|
||||||
throws = true;
|
throws = true;
|
||||||
}))
|
})
|
||||||
|
|
||||||
(it "throws with a number" ({
|
(it "throws with a bool" {
|
||||||
actual = toString (tag "p" 5);
|
actual = toString (tag "p" true);
|
||||||
throws = true;
|
throws = true;
|
||||||
}))
|
})
|
||||||
|
|
||||||
(it "throws with a bool" ({
|
(it "throws with a null" {
|
||||||
actual = toString (tag "p" true);
|
actual = toString (tag "p" null);
|
||||||
throws = true;
|
throws = true;
|
||||||
}))
|
})
|
||||||
|
|
||||||
(it "throws with a null" ({
|
(it "concatinates classes" {
|
||||||
actual = toString (tag "p" null);
|
actual = toString (tag "p" {class = ["class1" "class2"];} "Hello");
|
||||||
throws = true;
|
expected = ''<p class="class1 class2">Hello</p>'';
|
||||||
}))
|
})
|
||||||
|
|
||||||
(it "concatinates classes" {
|
(it "applies style" (let
|
||||||
actual = toString (tag "p" { class = [ "class1" "class2" ]; } "Hello");
|
page = tag "html" {} [(tag "head" {} ["foo"])];
|
||||||
expected = ''<p class="class1 class2">Hello</p>'';
|
in {
|
||||||
})
|
actual = addToHead page ["bar"];
|
||||||
|
expected = {
|
||||||
|
tag = "html";
|
||||||
|
attrs = {};
|
||||||
|
child = [(tag "head" {} ["foo" "bar"])];
|
||||||
|
};
|
||||||
|
removeDunders = true;
|
||||||
|
}))
|
||||||
|
|
||||||
(it "applies style" (let page = tag "html" { } [ (tag "head" { } [ "foo" ]) ];
|
(it "renders on / off attrs" {
|
||||||
in {
|
actual = toString (tag "p" {
|
||||||
actual = addToHead page [ "bar" ];
|
on = true;
|
||||||
expected = {
|
off = false;
|
||||||
tag = "html";
|
});
|
||||||
attrs = { };
|
expected = "<p on></p>";
|
||||||
child = [ (tag "head" { } [ "foo" "bar" ]) ];
|
})
|
||||||
};
|
]
|
||||||
removeDunders = true;
|
|
||||||
}))
|
|
||||||
|
|
||||||
(it "renders on / off attrs" ({
|
|
||||||
actual = toString (tag "p" {
|
|
||||||
on = true;
|
|
||||||
off = false;
|
|
||||||
});
|
|
||||||
expected = "<p on></p>";
|
|
||||||
}))
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
|
@ -1,148 +1,148 @@
|
||||||
{ it, ... }:
|
{it, ...}: let
|
||||||
let
|
|
||||||
md = import ../nixite/md.nix;
|
md = import ../nixite/md.nix;
|
||||||
elems = import ../nixite/elems.nix;
|
elems = import ../nixite/elems.nix;
|
||||||
in with md; [
|
in
|
||||||
|
with md; [
|
||||||
|
(it "matches a list of one element" {
|
||||||
|
actual = list ''
|
||||||
|
- something
|
||||||
|
'';
|
||||||
|
expected = {
|
||||||
|
matched = true;
|
||||||
|
block = elems.List ["something"];
|
||||||
|
};
|
||||||
|
asJSON = true;
|
||||||
|
})
|
||||||
|
|
||||||
(it "matches a list of one element" ({
|
(it "makes a list of many elements" {
|
||||||
actual = list ''
|
actual = list ''
|
||||||
- something
|
- something
|
||||||
'';
|
- something else
|
||||||
expected = {
|
'';
|
||||||
matched = true;
|
expected = {
|
||||||
block = elems.List [ "something" ];
|
matched = true;
|
||||||
};
|
block = elems.List ["something" "something else"];
|
||||||
asJSON = true;
|
};
|
||||||
}))
|
asJSON = true;
|
||||||
|
})
|
||||||
|
|
||||||
(it "makes a list of many elements" ({
|
(it "makes a list of many checkboxes" {
|
||||||
actual = list ''
|
actual = list ''
|
||||||
- something
|
- [ ] something
|
||||||
- something else
|
- [X] something else
|
||||||
'';
|
'';
|
||||||
expected = {
|
expected = {
|
||||||
matched = true;
|
matched = true;
|
||||||
block = elems.List [ "something" "something else" ];
|
block = elems.List [
|
||||||
};
|
[
|
||||||
asJSON = true;
|
(elems.input {
|
||||||
}))
|
type = "checkbox";
|
||||||
|
disabled = true;
|
||||||
|
checked = false;
|
||||||
|
} "")
|
||||||
|
"something"
|
||||||
|
]
|
||||||
|
[
|
||||||
|
(elems.input {
|
||||||
|
type = "checkbox";
|
||||||
|
disabled = true;
|
||||||
|
checked = true;
|
||||||
|
} "")
|
||||||
|
"something else"
|
||||||
|
]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
asJSON = true;
|
||||||
|
})
|
||||||
|
|
||||||
(it "makes a list of many checkboxes" ({
|
(it "matches a list with no whitespace around" {
|
||||||
actual = list ''
|
actual = list ''
|
||||||
- [ ] something
|
- something
|
||||||
- [X] something else
|
- something else'';
|
||||||
'';
|
expected = {
|
||||||
expected = {
|
matched = true;
|
||||||
matched = true;
|
block = elems.List ["something" "something else"];
|
||||||
block = elems.List [
|
};
|
||||||
[
|
asJSON = true;
|
||||||
(elems.input {
|
})
|
||||||
type = "checkbox";
|
|
||||||
disabled = true;
|
(it "doesnt match not a list" (let
|
||||||
checked = false;
|
str = "blah blah";
|
||||||
} "")
|
in {
|
||||||
"something"
|
actual = list str;
|
||||||
]
|
expected = {
|
||||||
[
|
matched = false;
|
||||||
(elems.input {
|
block = str;
|
||||||
type = "checkbox";
|
};
|
||||||
disabled = true;
|
}))
|
||||||
checked = true;
|
|
||||||
} "")
|
(it "processes whole string with all rules" {
|
||||||
"something else"
|
actual = processStr ''
|
||||||
]
|
this text **may** *or may not* contain **bold** words *inside* it.
|
||||||
|
'';
|
||||||
|
expected = elems.p [
|
||||||
|
"this text"
|
||||||
|
(elems.strong "may")
|
||||||
|
(elems.em "or may not")
|
||||||
|
"contain"
|
||||||
|
(elems.strong "bold")
|
||||||
|
"words"
|
||||||
|
(elems.em "inside")
|
||||||
|
"it."
|
||||||
];
|
];
|
||||||
};
|
asString = true;
|
||||||
asJSON = true;
|
})
|
||||||
}))
|
|
||||||
|
|
||||||
(it "matches a list with no whitespace around" ({
|
(it "makes paragraphs" {
|
||||||
actual = list ''
|
actual = readMd ''
|
||||||
- something
|
lorem ipsum
|
||||||
- something else'';
|
dolor sit
|
||||||
expected = {
|
|
||||||
matched = true;
|
|
||||||
block = elems.List [ "something" "something else" ];
|
|
||||||
};
|
|
||||||
asJSON = true;
|
|
||||||
}))
|
|
||||||
|
|
||||||
(it "doesnt match not a list" (let str = "blah blah";
|
foo bar
|
||||||
in {
|
'';
|
||||||
actual = list str;
|
expected = ''
|
||||||
expected = {
|
<p >lorem ipsum
|
||||||
matched = false;
|
dolor sit
|
||||||
block = str;
|
</p><p >foo bar</p>'';
|
||||||
};
|
asString = true;
|
||||||
}))
|
})
|
||||||
|
|
||||||
(it "processes whole string with all rules" ({
|
(it "can fix file appendixes" {
|
||||||
actual = processStr ''
|
actual = fixAppendix "index.md";
|
||||||
this text **may** *or may not* contain **bold** words *inside* it.
|
expected = "index.html";
|
||||||
'';
|
})
|
||||||
expected = (elems.p [
|
|
||||||
"this text"
|
|
||||||
(elems.strong "may")
|
|
||||||
(elems.em "or may not")
|
|
||||||
"contain"
|
|
||||||
(elems.strong "bold")
|
|
||||||
"words"
|
|
||||||
(elems.em "inside")
|
|
||||||
"it."
|
|
||||||
]);
|
|
||||||
asString = true;
|
|
||||||
}))
|
|
||||||
|
|
||||||
(it "makes paragraphs" {
|
(it "converts markdown to a page" {
|
||||||
actual = readMd ''
|
actual = toString (mdToPage ./blog/index.md) + "\n";
|
||||||
lorem ipsum
|
expected = builtins.readFile ./out/index.html;
|
||||||
dolor sit
|
asString = true;
|
||||||
|
})
|
||||||
|
|
||||||
foo bar
|
(it "recursively reads dir" {
|
||||||
'';
|
actual = recReadMd ./blog;
|
||||||
expected = ''
|
expected = {
|
||||||
<p >lorem ipsum
|
"index.md" = mdToPage ./blog/index.md;
|
||||||
dolor sit
|
"dir" = {"index.md" = mdToPage ./blog/dir/index.md;};
|
||||||
</p><p >foo bar</p>'';
|
};
|
||||||
asString = true;
|
asJSON = true;
|
||||||
})
|
})
|
||||||
|
|
||||||
(it "can fix file appendixes" {
|
(it "recursively fixes filename" {
|
||||||
actual = fixAppendix "index.md";
|
actual = recFixAppendix {
|
||||||
expected = "index.html";
|
"index.md" = "something";
|
||||||
})
|
dir = {"index.md" = "something else";};
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
"index.html" = "something";
|
||||||
|
dir = {"index.html" = "something else";};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
(it "converts markdown to a page" {
|
(it "recursively translates md to html" {
|
||||||
actual = toString (mdToPage ./blog/index.md) + "\n";
|
actual = builtins.toJSON (readDir ./blog);
|
||||||
expected = builtins.readFile ./out/index.html;
|
expected = builtins.toJSON {
|
||||||
asString = true;
|
"index.html" = mdToPage ./blog/index.md;
|
||||||
})
|
"dir" = {"index.html" = mdToPage ./blog/dir/index.md;};
|
||||||
|
};
|
||||||
(it "recursively reads dir" {
|
})
|
||||||
actual = recReadMd ./blog;
|
]
|
||||||
expected = {
|
|
||||||
"index.md" = mdToPage ./blog/index.md;
|
|
||||||
"dir" = { "index.md" = mdToPage ./blog/dir/index.md; };
|
|
||||||
};
|
|
||||||
asJSON = true;
|
|
||||||
})
|
|
||||||
|
|
||||||
(it "recursively fixes filename" {
|
|
||||||
actual = recFixAppendix {
|
|
||||||
"index.md" = "something";
|
|
||||||
dir = { "index.md" = "something else"; };
|
|
||||||
};
|
|
||||||
expected = {
|
|
||||||
"index.html" = "something";
|
|
||||||
dir = { "index.html" = "something else"; };
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
(it "recursively translates md to html" {
|
|
||||||
actual = builtins.toJSON (readDir ./blog);
|
|
||||||
expected = builtins.toJSON {
|
|
||||||
"index.html" = mdToPage ./blog/index.md;
|
|
||||||
"dir" = { "index.html" = mdToPage ./blog/dir/index.md; };
|
|
||||||
};
|
|
||||||
})
|
|
||||||
]
|
|
||||||
|
|
|
@ -1,315 +1,313 @@
|
||||||
{ it, ... }:
|
{it, ...}: let
|
||||||
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;
|
style = import ../nixite/style.nix;
|
||||||
in with site; [
|
in
|
||||||
(it "applies a style" {
|
with site; [
|
||||||
expected = {
|
(it "applies a style" {
|
||||||
"index.html" = html.tag "html" { } [
|
expected = {
|
||||||
(html.tag "head" { } [
|
"index.html" = html.tag "html" {} [
|
||||||
(elems.title { } "foobar")
|
(html.tag "head" {} [
|
||||||
(elems.Stylesheet "/style.css")
|
(elems.title {} "foobar")
|
||||||
])
|
|
||||||
(elems.main { } "something")
|
|
||||||
];
|
|
||||||
blog = {
|
|
||||||
"index.html" = html.tag "html" { } [
|
|
||||||
(html.tag "head" { } [
|
|
||||||
(elems.title { } "foobar")
|
|
||||||
(elems.Stylesheet "/style.css")
|
(elems.Stylesheet "/style.css")
|
||||||
])
|
])
|
||||||
(elems.main { } "blogy blog")
|
(elems.main {} "something")
|
||||||
];
|
];
|
||||||
|
blog = {
|
||||||
|
"index.html" = html.tag "html" {} [
|
||||||
|
(html.tag "head" {} [
|
||||||
|
(elems.title {} "foobar")
|
||||||
|
(elems.Stylesheet "/style.css")
|
||||||
|
])
|
||||||
|
(elems.main {} "blogy blog")
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"style.css" = ''
|
||||||
|
this is a stylesheet
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
"style.css" = ''
|
actual =
|
||||||
this is a stylesheet
|
applyStyle ''
|
||||||
'';
|
this is a stylesheet
|
||||||
};
|
'' {
|
||||||
actual = applyStyle ''
|
"index.html" = html.tag "html" {} [
|
||||||
this is a stylesheet
|
(html.tag "head" {} [(elems.title {} "foobar")])
|
||||||
'' {
|
(elems.main {} "something")
|
||||||
"index.html" = html.tag "html" { } [
|
];
|
||||||
(html.tag "head" { } [ (elems.title { } "foobar") ])
|
blog = {
|
||||||
(elems.main { } "something")
|
"index.html" = html.tag "html" {} [
|
||||||
];
|
(html.tag "head" {} [(elems.title {} "foobar")])
|
||||||
blog = {
|
(elems.main {} "blogy blog")
|
||||||
"index.html" = html.tag "html" { } [
|
];
|
||||||
(html.tag "head" { } [ (elems.title { } "foobar") ])
|
};
|
||||||
(elems.main { } "blogy blog")
|
};
|
||||||
];
|
asJSON = true;
|
||||||
};
|
})
|
||||||
};
|
|
||||||
asJSON = true;
|
|
||||||
})
|
|
||||||
|
|
||||||
(it "applies a favicon" {
|
(it "applies a favicon" {
|
||||||
expected = {
|
expected = {
|
||||||
"index.html" = elems.html { } [
|
"index.html" = elems.html {} [
|
||||||
(elems.head { } [
|
(elems.head {} [
|
||||||
(elems.title { } "foobar")
|
(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 {
|
(elems.link {
|
||||||
rel = "shortcut icon";
|
rel = "shortcut icon";
|
||||||
href = ./src/favicon.png;
|
href = ./src/favicon.png;
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
(elems.main { } "something")
|
(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 {
|
||||||
actual = applyFavicon ./src/favicon.png {
|
"index.html" = elems.html {} [
|
||||||
"index.html" = elems.html { } [
|
(elems.head {} [(elems.title {} "foobar")])
|
||||||
(elems.head { } [ (elems.title { } "foobar") ])
|
(elems.main {} "something")
|
||||||
(elems.main { } "something")
|
|
||||||
];
|
|
||||||
blog = {
|
|
||||||
"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;
|
||||||
asJSON = true;
|
})
|
||||||
})
|
|
||||||
|
|
||||||
(it "gets all styles" {
|
(it "gets all styles" {
|
||||||
expected = {
|
expected = {
|
||||||
"p" = { };
|
"p" = {};
|
||||||
"div" = { };
|
"div" = {};
|
||||||
"p.class" = { color = "blue"; };
|
"p.class" = {color = "blue";};
|
||||||
"div.class2" = { color = "green"; };
|
"div.class2" = {color = "green";};
|
||||||
};
|
};
|
||||||
actual = getStyles (let
|
actual = getStyles (let
|
||||||
p = style.component elems.p "class" { style = { color = "blue"; }; };
|
p = style.component elems.p "class" {style = {color = "blue";};};
|
||||||
g = style.component elems.div "class2" { style = { color = "green"; }; };
|
g = style.component elems.div "class2" {style = {color = "green";};};
|
||||||
|
in {
|
||||||
|
"index.html" = p "";
|
||||||
|
blog = {"index.html" = g "";};
|
||||||
|
});
|
||||||
|
removeDunders = true;
|
||||||
|
})
|
||||||
|
|
||||||
|
(it "gets top level paths" {
|
||||||
|
actual = getPaths {
|
||||||
|
something = "";
|
||||||
|
src = ./src/index.md;
|
||||||
|
};
|
||||||
|
expected = {"index.md" = ./src/index.md;};
|
||||||
|
})
|
||||||
|
(it "gets lower level paths" {
|
||||||
|
actual = getPaths {
|
||||||
|
something = "yes";
|
||||||
|
a-list = [
|
||||||
|
{thingy = ./src/index.md;}
|
||||||
|
[(html.tag "img" {src = ./src/favicon.png;} "")]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
"index.md" = ./src/index.md;
|
||||||
|
"favicon.png" = ./src/favicon.png;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
(it "switches paths" {
|
||||||
|
actual = switchPaths {
|
||||||
|
something = "";
|
||||||
|
a-thing = {src = ./src/index.md;};
|
||||||
|
a-list = [{thingy = ./src/index.md;}];
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
something = "";
|
||||||
|
a-thing = {src = "/static/index.md";};
|
||||||
|
a-list = [{thingy = "/static/index.md";}];
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
(it "extracts paths" {
|
||||||
|
actual = extractPaths {
|
||||||
|
something = "";
|
||||||
|
a-thing = {src = ./src/index.md;};
|
||||||
|
a-list = [{thingy = ./src/index.md;}];
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
something = "";
|
||||||
|
a-thing = {src = "/static/index.md";};
|
||||||
|
a-list = [{thingy = "/static/index.md";}];
|
||||||
|
static = {"index.md" = ./src/index.md;};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
(it "switches links" (let
|
||||||
|
coolPage = {
|
||||||
|
type = "link";
|
||||||
|
name = "cool-page";
|
||||||
|
content = "";
|
||||||
|
};
|
||||||
in {
|
in {
|
||||||
"index.html" = p "";
|
actual = switchLinks {
|
||||||
blog = { "index.html" = g ""; };
|
something = "";
|
||||||
});
|
a-thing = {src = coolPage;};
|
||||||
removeDunders = true;
|
a-list = [{thingy = coolPage;}];
|
||||||
})
|
};
|
||||||
|
expected = {
|
||||||
|
something = "";
|
||||||
|
a-thing = {src = "/static/cool-page";};
|
||||||
|
a-list = [{thingy = "/static/cool-page";}];
|
||||||
|
};
|
||||||
|
}))
|
||||||
|
|
||||||
(it "gets top level paths" {
|
(it "gets links" (let
|
||||||
actual = getPaths {
|
coolPage = {
|
||||||
something = "";
|
type = "link";
|
||||||
src = ./src/index.md;
|
name = "cool-page";
|
||||||
};
|
content = "cool content";
|
||||||
expected = { "index.md" = ./src/index.md; };
|
};
|
||||||
})
|
otherPage = {
|
||||||
(it "gets lower level paths" {
|
type = "link";
|
||||||
actual = getPaths {
|
name = "page2";
|
||||||
something = "yes";
|
content = "stuff";
|
||||||
a-list = [
|
};
|
||||||
{ thingy = ./src/index.md; }
|
in {
|
||||||
[ (html.tag "img" { src = ./src/favicon.png; } "") ]
|
actual = getLinks {
|
||||||
];
|
something = "yes";
|
||||||
};
|
a-list = [{thingy = coolPage;} [(elems.img {src = otherPage;} "")]];
|
||||||
expected = {
|
};
|
||||||
"index.md" = ./src/index.md;
|
expected = {
|
||||||
"favicon.png" = ./src/favicon.png;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
(it "switches paths" {
|
|
||||||
actual = switchPaths {
|
|
||||||
something = "";
|
|
||||||
a-thing = { src = ./src/index.md; };
|
|
||||||
a-list = [{ thingy = ./src/index.md; }];
|
|
||||||
};
|
|
||||||
expected = {
|
|
||||||
something = "";
|
|
||||||
a-thing = { src = "/static/index.md"; };
|
|
||||||
a-list = [{ thingy = "/static/index.md"; }];
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
(it "extracts paths" {
|
|
||||||
actual = extractPaths {
|
|
||||||
something = "";
|
|
||||||
a-thing = { src = ./src/index.md; };
|
|
||||||
a-list = [{ thingy = ./src/index.md; }];
|
|
||||||
};
|
|
||||||
expected = {
|
|
||||||
something = "";
|
|
||||||
a-thing = { src = "/static/index.md"; };
|
|
||||||
a-list = [{ thingy = "/static/index.md"; }];
|
|
||||||
static = { "index.md" = ./src/index.md; };
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
(it "switches links" (let
|
|
||||||
coolPage = {
|
|
||||||
type = "link";
|
|
||||||
name = "cool-page";
|
|
||||||
content = "";
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
actual = switchLinks {
|
|
||||||
something = "";
|
|
||||||
a-thing = { src = coolPage; };
|
|
||||||
a-list = [{ thingy = coolPage; }];
|
|
||||||
};
|
|
||||||
expected = {
|
|
||||||
something = "";
|
|
||||||
a-thing = { src = "/static/cool-page"; };
|
|
||||||
a-list = [{ thingy = "/static/cool-page"; }];
|
|
||||||
};
|
|
||||||
}))
|
|
||||||
|
|
||||||
(it "gets links" (let
|
|
||||||
coolPage = {
|
|
||||||
type = "link";
|
|
||||||
name = "cool-page";
|
|
||||||
content = "cool content";
|
|
||||||
};
|
|
||||||
otherPage = {
|
|
||||||
type = "link";
|
|
||||||
name = "page2";
|
|
||||||
content = "stuff";
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
actual = getLinks {
|
|
||||||
something = "yes";
|
|
||||||
a-list =
|
|
||||||
[ { thingy = coolPage; } [ (elems.img { src = otherPage; } "") ] ];
|
|
||||||
};
|
|
||||||
expected = {
|
|
||||||
"cool-page" = "cool content";
|
|
||||||
"page2" = "stuff";
|
|
||||||
};
|
|
||||||
}))
|
|
||||||
|
|
||||||
(it "extracts links" (let
|
|
||||||
coolPage = {
|
|
||||||
type = "link";
|
|
||||||
name = "cool-page";
|
|
||||||
content = "cool content";
|
|
||||||
};
|
|
||||||
otherPage = {
|
|
||||||
type = "link";
|
|
||||||
name = "page2";
|
|
||||||
content = "stuff";
|
|
||||||
};
|
|
||||||
|
|
||||||
in {
|
|
||||||
actual = extractLinks {
|
|
||||||
something = "";
|
|
||||||
a-thing = { src = coolPage; };
|
|
||||||
a-list = [{ thingy = otherPage; }];
|
|
||||||
};
|
|
||||||
expected = {
|
|
||||||
something = "";
|
|
||||||
a-thing = { src = "/static/cool-page"; };
|
|
||||||
a-list = [{ thingy = "/static/page2"; }];
|
|
||||||
static = {
|
|
||||||
"cool-page" = "cool content";
|
"cool-page" = "cool content";
|
||||||
"page2" = "stuff";
|
"page2" = "stuff";
|
||||||
};
|
};
|
||||||
};
|
}))
|
||||||
}))
|
|
||||||
|
|
||||||
(it "copies all the files" ({
|
(it "extracts links" (let
|
||||||
actual = copyTo "." {
|
coolPage = {
|
||||||
page = "this is a page";
|
type = "link";
|
||||||
subdir = {
|
name = "cool-page";
|
||||||
page = "this page is in a subdir";
|
content = "cool content";
|
||||||
link = ./src;
|
|
||||||
};
|
};
|
||||||
};
|
otherPage = {
|
||||||
expected = ''
|
type = "link";
|
||||||
cp /nix/store/crirfz0n6f8dgl1si3x7pwyw7fqm0r8l-page ./page
|
name = "page2";
|
||||||
mkdir -p ./subdir
|
content = "stuff";
|
||||||
cp -r /nix/store/q95cn7ccixzi9w22aic4bl0ykk40ka7v-src ./subdir/link
|
};
|
||||||
cp /nix/store/ic6fyy8wg8r4338a3m5kinmg11igxsyj-page ./subdir/page
|
in {
|
||||||
|
actual = extractLinks {
|
||||||
|
something = "";
|
||||||
|
a-thing = {src = coolPage;};
|
||||||
|
a-list = [{thingy = otherPage;}];
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
something = "";
|
||||||
|
a-thing = {src = "/static/cool-page";};
|
||||||
|
a-list = [{thingy = "/static/page2";}];
|
||||||
|
static = {
|
||||||
|
"cool-page" = "cool content";
|
||||||
|
"page2" = "stuff";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}))
|
||||||
|
|
||||||
'';
|
(it "copies all the files" {
|
||||||
}))
|
actual = copyTo "." {
|
||||||
|
page = "this is a page";
|
||||||
|
subdir = {
|
||||||
|
page = "this page is in a subdir";
|
||||||
|
link = ./src;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
expected = ''
|
||||||
|
cp /nix/store/crirfz0n6f8dgl1si3x7pwyw7fqm0r8l-page ./page
|
||||||
|
mkdir -p ./subdir
|
||||||
|
cp -r /nix/store/q95cn7ccixzi9w22aic4bl0ykk40ka7v-src ./subdir/link
|
||||||
|
cp /nix/store/ic6fyy8wg8r4338a3m5kinmg11igxsyj-page ./subdir/page
|
||||||
|
|
||||||
(it "throws with a list for a page" ({
|
'';
|
||||||
actual = copyTo "." { page = [ ]; };
|
})
|
||||||
throws = true;
|
|
||||||
}))
|
|
||||||
|
|
||||||
(it "throws with null for a page" ({
|
(it "throws with a list for a page" {
|
||||||
actual = copyTo "." { page = null; };
|
actual = copyTo "." {page = [];};
|
||||||
throws = true;
|
throws = true;
|
||||||
}))
|
})
|
||||||
|
|
||||||
(it "throws with a bool for a page" ({
|
(it "throws with null for a page" {
|
||||||
actual = copyTo "." { page = true; };
|
actual = copyTo "." {page = null;};
|
||||||
throws = true;
|
throws = true;
|
||||||
}))
|
})
|
||||||
|
|
||||||
(it "throws with a number for a page" ({
|
(it "throws with a bool for a page" {
|
||||||
actual = copyTo "." { page = 5; };
|
actual = copyTo "." {page = true;};
|
||||||
throws = true;
|
throws = true;
|
||||||
}))
|
})
|
||||||
|
|
||||||
(it "prepares the site" ({
|
(it "throws with a number for a page" {
|
||||||
actual = prepare { favicon = ./src/favicon.png; } {
|
actual = copyTo "." {page = 5;};
|
||||||
"index.html" = elems.html { } [
|
throws = true;
|
||||||
(elems.head { } [ (elems.title { } "foobar") ])
|
})
|
||||||
(elems.main { } [
|
|
||||||
(elems.a {
|
(it "prepares the site" {
|
||||||
href = {
|
actual = prepare {favicon = ./src/favicon.png;} {
|
||||||
type = "link";
|
"index.html" = elems.html {} [
|
||||||
name = "a-page";
|
(elems.head {} [(elems.title {} "foobar")])
|
||||||
content = "this is another page";
|
(elems.main {} [
|
||||||
};
|
(elems.a {
|
||||||
} "A Page")
|
href = {
|
||||||
])
|
type = "link";
|
||||||
];
|
name = "a-page";
|
||||||
blog = {
|
content = "this is another page";
|
||||||
"index.html" = elems.html { } [
|
};
|
||||||
(elems.head { } [ (elems.title { } "foobar") ])
|
} "A Page")
|
||||||
(elems.main { } "something")
|
])
|
||||||
];
|
];
|
||||||
|
blog = {
|
||||||
|
"index.html" = elems.html {} [
|
||||||
|
(elems.head {} [(elems.title {} "foobar")])
|
||||||
|
(elems.main {} "something")
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
expected = {
|
||||||
expected = {
|
"index.html" = elems.html {} [
|
||||||
"index.html" = elems.html { } [
|
(elems.head {} [
|
||||||
(elems.head { } [
|
(elems.title {} "foobar")
|
||||||
(elems.title { } "foobar")
|
|
||||||
(elems.link {
|
|
||||||
rel = "shortcut icon";
|
|
||||||
href = "/static/favicon.png";
|
|
||||||
})
|
|
||||||
(elems.Stylesheet "/style.css")
|
|
||||||
])
|
|
||||||
(elems.main { } [ (elems.a { href = "/static/a-page"; } "A Page") ])
|
|
||||||
];
|
|
||||||
blog = {
|
|
||||||
"index.html" = elems.html { } [
|
|
||||||
(elems.head { } [
|
|
||||||
(elems.title { } "foobar")
|
|
||||||
(elems.link {
|
(elems.link {
|
||||||
rel = "shortcut icon";
|
rel = "shortcut icon";
|
||||||
href = "/static/favicon.png";
|
href = "/static/favicon.png";
|
||||||
})
|
})
|
||||||
(elems.Stylesheet "/style.css")
|
(elems.Stylesheet "/style.css")
|
||||||
])
|
])
|
||||||
(elems.main { } "something")
|
(elems.main {} [(elems.a {href = "/static/a-page";} "A Page")])
|
||||||
];
|
];
|
||||||
|
blog = {
|
||||||
|
"index.html" = elems.html {} [
|
||||||
|
(elems.head {} [
|
||||||
|
(elems.title {} "foobar")
|
||||||
|
(elems.link {
|
||||||
|
rel = "shortcut icon";
|
||||||
|
href = "/static/favicon.png";
|
||||||
|
})
|
||||||
|
(elems.Stylesheet "/style.css")
|
||||||
|
])
|
||||||
|
(elems.main {} "something")
|
||||||
|
];
|
||||||
|
};
|
||||||
|
static = {
|
||||||
|
"favicon.png" = ./src/favicon.png;
|
||||||
|
"a-page" = "this is another page";
|
||||||
|
};
|
||||||
|
"style.css" = "";
|
||||||
};
|
};
|
||||||
static = {
|
asJSON = true;
|
||||||
"favicon.png" = ./src/favicon.png;
|
})
|
||||||
"a-page" = "this is another page";
|
]
|
||||||
};
|
|
||||||
"style.css" = "";
|
|
||||||
};
|
|
||||||
asJSON = true;
|
|
||||||
}))
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
|
@ -1,54 +1,53 @@
|
||||||
{ it, ... }:
|
{it, ...}: let
|
||||||
let
|
|
||||||
style = import ../nixite/style.nix;
|
style = import ../nixite/style.nix;
|
||||||
elems = import ../nixite/elems.nix;
|
elems = import ../nixite/elems.nix;
|
||||||
in [
|
in [
|
||||||
|
(it "fetches empty style" (let
|
||||||
(it "fetches empty style" (let para = (style.component elems.p "para" { });
|
para = style.component elems.p "para" {};
|
||||||
in {
|
in {
|
||||||
expected = {
|
expected = {
|
||||||
"p" = { };
|
"p" = {};
|
||||||
"p.para" = { };
|
"p.para" = {};
|
||||||
};
|
};
|
||||||
actual = style.getStyle (para "");
|
actual = style.getStyle (para "");
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "fetches style" (let
|
(it "fetches style" (let
|
||||||
attrs = { style = { foo = "bar"; }; };
|
attrs = {style = {foo = "bar";};};
|
||||||
para = (style.component elems.p "para" attrs);
|
para = style.component elems.p "para" attrs;
|
||||||
in {
|
in {
|
||||||
expected = {
|
expected = {
|
||||||
"p" = { };
|
"p" = {};
|
||||||
"p.para" = attrs.style;
|
"p.para" = attrs.style;
|
||||||
};
|
};
|
||||||
actual = style.getStyle (para "");
|
actual = style.getStyle (para "");
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "appliess class" (let
|
(it "appliess class" (let
|
||||||
attrs = { style = { foo = "bar"; }; };
|
attrs = {style = {foo = "bar";};};
|
||||||
para = (style.component elems.p "para" attrs);
|
para = style.component elems.p "para" attrs;
|
||||||
in {
|
in {
|
||||||
expected = [ "para" ];
|
expected = ["para"];
|
||||||
actual = (para "").attrs.class;
|
actual = (para "").attrs.class;
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "applies classes from props" (let
|
(it "applies classes from props" (let
|
||||||
attrs = {
|
attrs = {
|
||||||
style = { foo = "bar"; };
|
style = {foo = "bar";};
|
||||||
class = [ "other" "class" ];
|
class = ["other" "class"];
|
||||||
};
|
};
|
||||||
para = (style.component elems.p "para" attrs);
|
para = style.component elems.p "para" attrs;
|
||||||
in {
|
in {
|
||||||
expected = [ "para" "other" "class" ];
|
expected = ["para" "other" "class"];
|
||||||
actual = (para "").attrs.class;
|
actual = (para "").attrs.class;
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "fetches style for class" (let
|
(it "fetches style for class" (let
|
||||||
s = { foo = "bar"; };
|
s = {foo = "bar";};
|
||||||
para = (style.component elems.p "para" { style = s; });
|
para = style.component elems.p "para" {style = s;};
|
||||||
in {
|
in {
|
||||||
expected = {
|
expected = {
|
||||||
"p" = { };
|
"p" = {};
|
||||||
"p.para" = s;
|
"p.para" = s;
|
||||||
};
|
};
|
||||||
actual = style.getStyle (para "");
|
actual = style.getStyle (para "");
|
||||||
|
@ -56,13 +55,13 @@ in [
|
||||||
|
|
||||||
(it "fetches style recursively" (let
|
(it "fetches style recursively" (let
|
||||||
s = {
|
s = {
|
||||||
"p" = { };
|
"p" = {};
|
||||||
"div" = { };
|
"div" = {};
|
||||||
"p.para" = { foo = "bar"; };
|
"p.para" = {foo = "bar";};
|
||||||
"div.link" = { this = "that"; };
|
"div.link" = {this = "that";};
|
||||||
};
|
};
|
||||||
para = (style.component elems.p "para" { style = s."p.para"; });
|
para = style.component elems.p "para" {style = s."p.para";};
|
||||||
div = (style.component elems.div "link" { style = s."div.link"; });
|
div = style.component elems.div "link" {style = s."div.link";};
|
||||||
in {
|
in {
|
||||||
expected = s;
|
expected = s;
|
||||||
actual = style.getStyles (para (div "hello"));
|
actual = style.getStyles (para (div "hello"));
|
||||||
|
@ -71,39 +70,39 @@ in [
|
||||||
|
|
||||||
(it "fetches style recursively through lists" (let
|
(it "fetches style recursively through lists" (let
|
||||||
s = {
|
s = {
|
||||||
"p" = { };
|
"p" = {};
|
||||||
"div" = { };
|
"div" = {};
|
||||||
"p.para" = { foo = "bar"; };
|
"p.para" = {foo = "bar";};
|
||||||
"div.link" = { this = "that"; };
|
"div.link" = {this = "that";};
|
||||||
};
|
};
|
||||||
para = (style.component elems.p "para" { style = s."p.para"; });
|
para = style.component elems.p "para" {style = s."p.para";};
|
||||||
a = (style.component elems.div "link" { style = s."div.link"; });
|
a = style.component elems.div "link" {style = s."div.link";};
|
||||||
in {
|
in {
|
||||||
expected = s;
|
expected = s;
|
||||||
actual = style.getStyles (para [ (a "hello") ]);
|
actual = style.getStyles (para [(a "hello")]);
|
||||||
removeDunders = true;
|
removeDunders = true;
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "fetches style recursively with repeats" (let
|
(it "fetches style recursively with repeats" (let
|
||||||
s = {
|
s = {
|
||||||
"p" = { };
|
"p" = {};
|
||||||
"div" = { };
|
"div" = {};
|
||||||
"p.para" = { foo = "bar"; };
|
"p.para" = {foo = "bar";};
|
||||||
"div.link" = { this = "that"; };
|
"div.link" = {this = "that";};
|
||||||
};
|
};
|
||||||
para = (style.component elems.p "para" { style = s."p.para"; });
|
para = style.component elems.p "para" {style = s."p.para";};
|
||||||
a = (style.component elems.div "link" { style = s."div.link"; });
|
a = style.component elems.div "link" {style = s."div.link";};
|
||||||
in {
|
in {
|
||||||
expected = s;
|
expected = s;
|
||||||
actual = style.getStyles (para [ (a "hello") (a "hello") ]);
|
actual = style.getStyles (para [(a "hello") (a "hello")]);
|
||||||
removeDunders = true;
|
removeDunders = true;
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "converts styles to string" (let
|
(it "converts styles to string" (let
|
||||||
s = {
|
s = {
|
||||||
"p" = { };
|
"p" = {};
|
||||||
"p.para" = { foo = "bar"; };
|
"p.para" = {foo = "bar";};
|
||||||
"a.link" = { this = "that"; };
|
"a.link" = {this = "that";};
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
expected = ''
|
expected = ''
|
||||||
|
@ -119,11 +118,11 @@ in [
|
||||||
|
|
||||||
(it "extends styled tags" (let
|
(it "extends styled tags" (let
|
||||||
s = {
|
s = {
|
||||||
"p.para" = { foo = "bar"; };
|
"p.para" = {foo = "bar";};
|
||||||
"p.oof" = { oof = "yes"; };
|
"p.oof" = {oof = "yes";};
|
||||||
};
|
};
|
||||||
para = (style.component elems.p "para" { style = s."p.para"; });
|
para = style.component elems.p "para" {style = s."p.para";};
|
||||||
para2 = (style.component para "oof" { style = s."p.oof"; });
|
para2 = style.component para "oof" {style = s."p.oof";};
|
||||||
in {
|
in {
|
||||||
expected = s;
|
expected = s;
|
||||||
actual = style.getStyles (para2 "");
|
actual = style.getStyles (para2 "");
|
||||||
|
@ -132,16 +131,15 @@ in [
|
||||||
|
|
||||||
(it "extends styled tags classes" (let
|
(it "extends styled tags classes" (let
|
||||||
s = {
|
s = {
|
||||||
"p" = { };
|
"p" = {};
|
||||||
"div" = { };
|
"div" = {};
|
||||||
"p.para" = { foo = "bar"; };
|
"p.para" = {foo = "bar";};
|
||||||
"p.para.oof" = { oof = "yes"; };
|
"p.para.oof" = {oof = "yes";};
|
||||||
};
|
};
|
||||||
para = (style.component elems.p "para" { style = s."p.para"; });
|
para = style.component elems.p "para" {style = s."p.para";};
|
||||||
para2 = (style.component para "oof" { style = s."p.para.oof"; });
|
para2 = style.component para "oof" {style = s."p.para.oof";};
|
||||||
in {
|
in {
|
||||||
expected = [ "para" "oof" ];
|
expected = ["para" "oof"];
|
||||||
actual = (para2 "").attrs.class;
|
actual = (para2 "").attrs.class;
|
||||||
}))
|
}))
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in a new issue