component extending, add all html elems

also use nixfmt
This commit is contained in:
tristan 2023-12-31 21:33:42 +00:00
parent ccc6b53b91
commit cb6d9652f8
15 changed files with 548 additions and 604 deletions

View file

@ -1,52 +1,43 @@
{ {
description = "A site in nix?"; description = "A site in nix?";
outputs = { outputs = { self, nixpkgs, }:
self, let
nixpkgs, system = "x86_64-linux";
}: let pkgs = import nixpkgs { inherit system; };
system = "x86_64-linux"; nixite = import ./nixite/. { inherit pkgs; };
pkgs = import nixpkgs { in nixite // {
inherit system;
};
nixite = import ./nixite/. {inherit pkgs;};
in
nixite
// {
packages.${system} = { packages.${system} = {
default = nixite.mkSite ( default = nixite.mkSite (nixite.site.applyStyle ./testing/src/style.css
nixite.site.applyStyle ./testing/src/style.css
(nixite.site.extractPaths { (nixite.site.extractPaths {
"index.html" = with nixite.elems; (doc [ "index.html" = with nixite.elems;
[ (Doc [
(title "Nixite") [
(nixite.html.tag "link" {rel = "shortcut icon"; type = "image/png"; href = ./testing/src/favicon.png;} "") (title "Nixite")
] (nixite.html.tag "link" {
(main [ rel = "shortcut icon";
(link "/blog" "blog") type = "image/png";
(list [ href = ./testing/src/favicon.png;
"item 1" } "")
"item 2" ]
"item 3" (main [
(a "/blog" "blog")
(list [ "item 1" "item 2" "item 3" ])
]) ])
]) ]);
]);
blog = nixite.md.readDir ./testing/blog; blog = nixite.md.readDir ./testing/blog;
}) }));
);
serve = nixite.serve self.packages.${system}.default; serve = nixite.serve self.packages.${system}.default;
test = let test = let test = import ./testing/import.nix;
test = import ./testing/import.nix; in pkgs.writeShellScriptBin "test" ''
in ${test ./testing/md.test.nix}
pkgs.writeShellScriptBin "test" '' ${test ./testing/html.test.nix}
${test ./testing/md.test.nix} ${test ./testing/elems.test.nix}
${test ./testing/html.test.nix} ${test ./testing/site.test.nix}
${test ./testing/elems.test.nix} ${test ./testing/style.test.nix}
${test ./testing/site.test.nix} '';
${test ./testing/style.test.nix}
'';
}; };
}; };
} }

View file

@ -1,8 +1,9 @@
{pkgs, ...}: { { pkgs, ... }: {
mkSite = import ./make-site.nix pkgs; mkSite = import ./make-site.nix pkgs;
serve = site: (pkgs.writeShellScriptBin "serve" '' serve = site:
${pkgs.caddy}/bin/caddy file-server --root ${site} (pkgs.writeShellScriptBin "serve" ''
''); ${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;

View file

@ -1,47 +1,60 @@
let let
html = import ./html.nix; html = import ./html.nix;
s = import ./style.nix; s = import ./style.nix;
in base = tag: (s.styled tag tag { class = [ ]; });
(s.styled "p" "p" {}) in (base "html") (base "head") (base "title") (base "base") (base "link")
(s.styled "div" "div" {}) (base "meta")
(s.styled "section" "section" {}) # (base "style" ) # borks styled coponents
(s.styled "span" "span" {}) (base "body") (base "article") (base "section") (base "nav") (base "aside")
(s.styled "main" "main" {}) (base "h1") (base "h2") (base "h3") (base "h4") (base "h5") (base "h6")
(s.styled "article" "article" {}) (base "hgroup") (base "header") (base "footer") (base "address") (base "p")
(s.styled "title" "title" {class = [];}) (base "hr") (base "pre") (base "blockquote") (base "ol") (base "ul")
(s.styled "h1" "h1" {}) (base "menu") (base "li") (base "dl") (base "dt") (base "dd") (base "figure")
(s.styled "h2" "h2" {}) (base "figcaption") (base "main") (base "div") (base "a") (base "em")
(s.styled "h3" "h3" {}) (base "strong") (base "small") (base "s") (base "cite") (base "q") (base "dfn")
(s.styled "list" "ul" { (base "abbr") (base "ruby") (base "rt") (base "rp") (base "data") (base "time")
__child = child: (base "code") (base "var") (base "samp") (base "kbd") (base "sub") (base "sup")
assert builtins.isList child; (map (html.tag "li" {}) child); (base "i") (base "b") (base "u") (base "mark") (base "bdi") (base "bdo")
}) (base "span") (base "br") (base "wbr") (base "ins") (base "del")
(s.styled "doc" "html" { (base "picture") (base "source") (base "img") (base "iframe") (base "embed")
__child = child: (base "object") (base "param") (base "video") (base "audio") (base "track")
assert builtins.isList child; (base "map") (base "area") (base "table") (base "caption") (base "colgroup")
assert builtins.length child == 2; (base "col") (base "tbody") (base "thead") (base "tfoot") (base "tr")
assert builtins.isList (builtins.elemAt child 0); [ (base "td") (base "th") (base "form") (base "label") (base "input")
(html.tag "head" {} (builtins.elemAt child 0)) (base "button") (base "select") (base "datalist") (base "optgroup")
(html.tag "body" {} (builtins.elemAt child 1)) (base "option") (base "textarea") (base "output") (base "progress")
]; (base "meter") (base "fieldset") (base "legend") (base "details")
lang = "en"; (base "summary") (base "dialog") (base "script") (base "noscript")
class = []; (base "template") (base "slot") (base "canvas")
})
(s.styled "link" "a" { (s.styled "List" "ul" {
__self = self: attrs: child: __child = child:
if builtins.isString attrs then assert builtins.isList child;
self {href = attrs;} child else (map (html.tag "li" { }) child);
self attrs child; }) (s.styled "Doc" "html" {
}) __child = child:
(s.styled "stylesheet" "link" { assert builtins.isList child;
rel = "stylesheet"; assert builtins.length child == 2;
class = []; assert builtins.isList (builtins.elemAt child 0); [
__self = self: attrs: (html.tag "head" { } (builtins.elemAt child 0))
if builtins.isString attrs then (html.tag "body" { } (builtins.elemAt child 1))
self {href = attrs;} "" else ];
self attrs ""; lang = "en";
}) class = [ ];
// { }) (s.styled "a" "a" {
h = v: child: __self = self: attrs: child:
html.tag "h${toString v}" {} child; if builtins.isString attrs then
} self { href = attrs; } child
else
self attrs child;
}) (s.styled "Stylesheet" "link" {
rel = "stylesheet";
class = [ ];
__self = self: attrs:
if builtins.isString attrs then
self { href = attrs; } ""
else
self attrs "";
}) // {
H = v: child: html.tag "h${toString v}" { } child;
}

View file

@ -1,27 +1,30 @@
let let
keyvalue = key: value: keyvalue = key: value:
assert builtins.isString key; assert builtins.isString key;
if value == "" || value == [] || value == {} then "" else if value == "" || value == [ ] || value == { } then
''${key}="${toString value}"''; ""
else
''${key}="${toString value}"'';
in rec { in rec {
toHTML = elem: toHTML = elem:
if builtins.typeOf elem == "string" if builtins.typeOf elem == "string" then
then elem elem
else if builtins.typeOf elem == "list" else if builtins.typeOf elem == "list" then
then builtins.toString (map toHTML elem) builtins.toString (map toHTML elem)
else ''<${elem.tag} ${writeAttrs elem.attrs}>${toHTML elem.child}</${elem.tag}>''; else
"<${elem.tag} ${writeAttrs elem.attrs}>${
toHTML elem.child
}</${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) if (builtins.isPath value) then
then keyvalue key (baseNameOf value) keyvalue key (baseNameOf value)
else if (builtins.substring 0 2 key) == "__" then
""
else else
if (builtins.substring 0 2 key) == "__" keyvalue key value) attrs)));
then ""
else keyvalue key value)
attrs
)));
tag = tag: attrs: child: { tag = tag: attrs: child: {
inherit tag attrs child; inherit tag attrs child;
@ -29,20 +32,9 @@ in rec {
}; };
addToHead = page: heads: addToHead = page: heads:
page page // {
// { child = map
child = (e: if e.tag == "head" then e // { child = e.child ++ heads; } else e)
map
(
e:
if e.tag == "head"
then
e
// {
child = e.child ++ heads;
}
else e
)
page.child; page.child;
}; };
} }

View file

@ -1,16 +1,16 @@
{stdenv, ...}: raw: let { stdenv, ... }:
site = import ./site.nix; raw:
in let site = import ./site.nix;
stdenv.mkDerivation { in 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
''; '';
} }

View file

@ -1,60 +1,42 @@
let let elems = import ./elems.nix;
elems = import ./elems.nix;
in rec { in rec {
readMd = md: readMd = md:
if builtins.isPath md if builtins.isPath md then
then processMd (builtins.readFile md) processMd (builtins.readFile md)
else processMd md; else
processMd md;
processMd = md: (map (c: processMd = md:
if builtins.isString c (map (c: if builtins.isString c then mdBlock c else "")
then mdBlock c (builtins.split "\n\n" md));
else "") (builtins.split "\n\n" md));
recReadMd = root: recReadMd = root:
assert builtins.isPath root; assert builtins.isPath root;
builtins.mapAttrs builtins.mapAttrs (path: type:
(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}") throw "Cannot read ${path}, file type ${type}") (builtins.readDir root);
(builtins.readDir root);
recFixAppendix = site: recFixAppendix = site:
builtins.listToAttrs ( builtins.listToAttrs (builtins.attrValues (builtins.mapAttrs (name: value: {
builtins.attrValues ( name = fixAppendix name;
builtins.mapAttrs (name: value: { value = if builtins.isAttrs value then recFixAppendix value else value;
name = fixAppendix name; }) site));
value =
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: elems.doc [ mdToPage = md: elems.Doc [ [ (elems.title "markdown file") ] (readMd md) ];
[(elems.title "markdown file")]
(readMd md)
];
mdBlock = block: let mdBlock = block:
m = heading block; let
h = m = heading block;
if m == null h = if m == null then 0 else builtins.stringLength (builtins.elemAt m 0);
then 0 in if m == null then elems.p { } block else elems.H h (builtins.elemAt m 1);
else builtins.stringLength (builtins.elemAt m 0);
in
if m == null
then elems.p {} block
else elems.h h (builtins.elemAt m 1);
heading = block: builtins.match "(#+) (.*)" block; heading = block: builtins.match "(#+) (.*)" block;
} }

View file

@ -2,76 +2,57 @@ let
html = import ./html.nix; html = import ./html.nix;
elems = import ./elems.nix; elems = import ./elems.nix;
in rec { in rec {
applyStyle = style: site: (linkStyle site) // {"style.css" = style;}; applyStyle = style: site: (linkStyle site) // { "style.css" = style; };
linkStyle = site: (builtins.mapAttrs ( linkStyle = site:
name: content: (builtins.mapAttrs (name: content:
if builtins.isAttrs content && content ? "__toString" if builtins.isAttrs content && content ? "__toString" then
then html.addToHead content [(elems.stylesheet "/style.css")] html.addToHead content [ (elems.Stylesheet "/style.css") ]
else if builtins.isAttrs content else if builtins.isAttrs content then
then linkStyle content linkStyle content
else content else
) content) site);
site);
extractPaths = content: extractPaths = content: switchPaths content // { static = getPaths content; };
switchPaths content // {static = getPaths content;};
switchPaths = content: ( switchPaths = content:
if builtins.isAttrs content (if builtins.isAttrs content then
then
builtins.mapAttrs (key: value: builtins.mapAttrs (key: value:
if builtins.isPath value if builtins.isPath value then
then ("/static/" + baseNameOf value) ("/static/" + baseNameOf value)
else switchPaths value) else
content switchPaths value) content
else if builtins.isList content else if builtins.isList content then
then (map switchPaths content) (map switchPaths content)
else content else
); content);
getPaths = content: (builtins.listToAttrs (getPathsKV content)); getPaths = content: (builtins.listToAttrs (getPathsKV content));
getPathsKV = path: ( getPathsKV = path:
if builtins.isPath path (if builtins.isPath path then [{
then [ name = baseNameOf path;
{ value = path;
name = baseNameOf path; }] else if builtins.isAttrs path then
value = path; builtins.concatLists (map getPathsKV (builtins.attrValues path))
} else if builtins.isList path then
] builtins.concatLists (map getPathsKV path)
else if builtins.isAttrs path else
then builtins.concatLists (map getPathsKV (builtins.attrValues path)) [ ]);
else if builtins.isList path
then builtins.concatLists (map getPathsKV path)
else []
);
copyTo = prefix: site: copyTo = prefix: site:
builtins.toString ( builtins.toString (builtins.attrValues (builtins.mapAttrs (name: content:
builtins.attrValues ( if builtins.isString content then ''
builtins.mapAttrs ( cp ${builtins.toFile name content} ${prefix}/${name}
name: content: '' else if builtins.isPath content then ''
if builtins.isString content cp -r ${content} ${prefix}/${name}
then '' '' else if builtins.isAttrs content && content ? "__toString" then ''
cp ${builtins.toFile name content} ${prefix}/${name} cp ${builtins.toFile name (toString content)} ${prefix}/${name}
'' '' else if builtins.isAttrs content then ''
else if builtins.isPath content mkdir -p ${prefix}/${name}
then '' ${copyTo "${prefix}/${name}" content}
cp -r ${content} ${prefix}/${name} '' else
'' throw "Site page must be string, path or attrset, but got ${
else if builtins.isAttrs content && content ? "__toString" builtins.typeOf content
then '' }: [${toString content}]") site));
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
)
);
} }

View file

@ -2,65 +2,63 @@ let
html = import ./html.nix; html = import ./html.nix;
join = { join = {
__functor = self: new: __functor = self: new: self // new // { style = self.style + new.style; };
self
// new
// {style = self.style + new.style;};
}; };
mkStyle = identifier: styles: mkStyle = identifier: styles:
if styles == {} if styles == { } then
then "" ""
else '' else ''
${identifier} { ${identifier} {
${toString (builtins.attrValues ( ${
builtins.mapAttrs ( toString (builtins.attrValues
key: value: ''${key}: ${value};'' (builtins.mapAttrs (key: value: "${key}: ${value};") styles))
) }
styles
))}
} }
''; '';
mkIdentifier = name: tag: { mkIdentifier = name: tag:
class ? [name], { class ? [ name ], id ? "", ... }:
id ? "", "${tag}" + builtins.concatStringsSep "" (map (c: "." + c) class)
... + (if id != "" then "#" else "") + id;
}:
"${tag}"
+ builtins.concatStringsSep "" (map (c: "." + c) class)
+ (
if id != ""
then "#"
else ""
)
+ id;
in { in {
styled = name: tag: cprops: let styled = name: tag: cprops:
__child = cprops.__child or (child: child); assert builtins.isString name;
let
__child = cprops.__child or (child: child);
self = props: joinProps = (cprops // {
html.tag tag (props // {class = [name];} // cprops // {style = "";}); __functor = prev: next:
prev // next // {
class = prev.class ++ next.class or [ ];
};
class = if cprops ? class then
if cprops.class == [ ] then [ ] else [ name ] ++ cprops.class
else
[ name ];
}) { style = ""; };
__self = (cprops.__self or (self: props: self = if builtins.isFunction tag then
if builtins.isAttrs props props: tag (joinProps props)
then (child: ( self props (__child child) )) else if builtins.isString tag then
else if builtins.isString props || builtins.isList props props: html.tag tag (joinProps props)
then (self {} (__child props)) else
else throw "Call element with attributes and child." throw "You may only style a tag (string) or element, got ${
)) self; builtins.typeOf tag
}";
in __self = (cprops.__self or (self: props:
{ if builtins.isAttrs props then
(child: (self props (__child child)))
else if builtins.isString props || builtins.isList props then
(self { } (__child props))
else
throw "Call element with attributes and child.")) self;
in {
${name} = __self; ${name} = __self;
style = mkStyle (mkIdentifier name tag cprops) ( cprops.style or {} ); style = mkStyle (mkIdentifier name tag cprops) (cprops.style or { });
} } // join;
// join;
style = identifier: styles: style = identifier: styles: { style = mkStyle identifier styles; } // join;
{
style = mkStyle identifier styles;
}
// join;
} }

View file

@ -2,83 +2,82 @@ let
elems = import ../nixite/elems.nix; elems = import ../nixite/elems.nix;
html = import ../nixite/html.nix; html = import ../nixite/html.nix;
it = import ./it.nix; it = import ./it.nix;
in in with elems; [
with elems; [ (it "makes a p tag" {
(it "makes a p tag" { expected = html.tag "p" { } "foobar";
expected = html.tag "p" {class = ["p"];} "foobar"; actual = p { } "foobar";
actual = p {} "foobar"; asString = true;
asString = true; })
}) (it "makes a div tag" {
(it "makes a div tag" { expected = html.tag "div" { } "foobar";
expected = html.tag "div" {class = ["div"];} "foobar"; actual = div { } "foobar";
actual = div {} "foobar"; asString = true;
asString = true; })
}) (it "makes a section tag" {
(it "makes a section tag" { expected = html.tag "section" { } "foobar";
expected = html.tag "section" {class = ["section"];} "foobar"; actual = section { } "foobar";
actual = section {} "foobar"; asString = true;
asString = true; })
}) (it "makes a span tag" {
(it "makes a span tag" { expected = html.tag "span" { } "foobar";
expected = html.tag "span" {class = ["span"];} "foobar"; actual = span { } "foobar";
actual = span {} "foobar"; asString = true;
asString = true; })
}) (it "makes a main tag" {
(it "makes a main tag" { expected = html.tag "main" { } [ "yeet" ];
expected = html.tag "main" {class = ["main"];} ["yeet"]; actual = main { } [ "yeet" ];
actual = main {} ["yeet"]; asString = true;
asString = true; })
}) (it "makes an h1 tag" {
(it "makes an h1 tag" { expected = html.tag "h1" { } "foobar";
expected = html.tag "h1" {} "foobar"; actual = H 1 "foobar";
actual = h 1 "foobar"; asString = true;
asString = true; })
}) (it "makes an h2 tag" {
(it "makes an h2 tag" { expected = html.tag "h2" { } "foobar";
expected = html.tag "h2" {} "foobar"; actual = H 2 "foobar";
actual = h 2 "foobar"; asString = true;
asString = true; })
}) (it "makes a title tag" {
(it "makes a title tag" { expected = html.tag "title" { } "foobar";
expected = html.tag "title" {class = [];} "foobar"; actual = title { } "foobar";
actual = title {} "foobar"; asString = true;
asString = true; })
}) (it "makes an a tag" {
(it "makes an a tag" { expected = html.tag "a" {
expected = html.tag "a" {class = ["link"]; href = "https://example.com";} "example"; class = [ "a" ];
actual = link "https://example.com" "example"; href = "https://example.com";
asString = true; } "example";
}) actual = a "https://example.com" "example";
(it "makes a stylesheet link" { asString = true;
expected = html.tag "link" { })
href = "/style"; (it "makes a stylesheet link" {
rel = "stylesheet"; expected = html.tag "link" {
} ""; href = "/style";
actual = stylesheet {href = "/style"; }; rel = "stylesheet";
asString = true; } "";
}) actual = Stylesheet { href = "/style"; };
(it "makes a list" { asString = true;
expected = (html.tag "ul" { })
__ = ""; (it "makes a list" {
class = ["list"]; expected = html.tag "ul" {
} [ __ = "";
(html.tag "li" {} "foo") class = [ "List" ];
(html.tag "li" {} "bar") } [
(html.tag "li" {} "baz") (html.tag "li" { } "foo")
]); (html.tag "li" { } "bar")
actual = (list {} ["foo" "bar" "baz"]); (html.tag "li" { } "baz")
asString = true; ];
}) actual = List { } [ "foo" "bar" "baz" ];
(it "makes an html doc" { asString = true;
expected = (html.tag "html" { })
__child = ""; (it "makes an html doc" {
class = []; expected = html.tag "html" {
lang = "en"; __child = "";
} [ class = [ ];
(html.tag "head" {} ["foo"]) lang = "en";
(html.tag "body" {} "bar") } [ (html.tag "head" { } [ "foo" ]) (html.tag "body" { } "bar") ];
]); actual = Doc { } [ [ "foo" ] "bar" ];
actual = (doc {} [["foo"] "bar"]); asString = true;
asString = true; })
}) ]
]

View file

@ -1,32 +1,30 @@
let let
html = import ../nixite/html.nix; html = import ../nixite/html.nix;
it = import ./it.nix; it = import ./it.nix;
in in with html; [
with html; [ (it "makes a p tag" {
(it "makes a p tag" { actual = tag "p" { } "Hello";
actual = tag "p" {} "Hello"; expected = {
expected = { tag = "p";
tag = "p"; attrs = { };
attrs = {}; child = "Hello";
child = "Hello"; __toString = toHTML;
__toString = toHTML; };
}; })
})
(it "concatinates classes" { (it "concatinates classes" {
actual = toString (tag "p" {class = ["class1" "class2"];} "Hello"); actual = toString (tag "p" { class = [ "class1" "class2" ]; } "Hello");
expected = ''<p class="class1 class2">Hello</p>''; expected = ''<p class="class1 class2">Hello</p>'';
}) })
(it "applies style" (let (it "applies style" (let page = tag "html" { } [ (tag "head" { } [ "foo" ]) ];
page = tag "html" {} [(tag "head" {} ["foo"])]; in {
in { actual = addToHead page [ "bar" ];
actual = addToHead page ["bar"]; expected = {
expected = { tag = "html";
tag = "html"; attrs = { };
attrs = {}; child = [ (tag "head" { } [ "foo" "bar" ]) ];
child = [(tag "head" {} ["foo" "bar"])]; __toString = toHTML;
__toString = toHTML; };
}; }))
})) ]
]

View file

@ -3,5 +3,4 @@ path:
echo echo
echo 'TEST: ${builtins.baseNameOf path}' echo 'TEST: ${builtins.baseNameOf path}'
echo echo
'' '' + builtins.concatStringsSep "\n" (import path)
+ builtins.concatStringsSep "\n" (import path)

View file

@ -1,16 +1,14 @@
msg: { msg:
actual, { actual, expected, asString ? false, asJSON ? false, }:
expected, if (if asString then
asString ? false, toString actual == toString expected
}: else if asJSON then
if ( builtins.toJSON actual == builtins.toJSON expected
if asString then toString actual == toString expected else
else actual == expected ) actual == expected) then ''
then '' echo 'it ${msg}'
echo 'it ${msg}' '' else ''
'' echo 'FAILED: ${msg}'
else '' echo '${builtins.toJSON expected}'
echo 'FAILED: ${msg}' echo '${builtins.toJSON actual}'
echo '${builtins.toJSON expected}' ''
echo '${builtins.toJSON actual}'
''

View file

@ -2,66 +2,62 @@ let
md = import ../nixite/md.nix; md = import ../nixite/md.nix;
elems = import ../nixite/elems.nix; elems = import ../nixite/elems.nix;
it = import ./it.nix; it = import ./it.nix;
in in with md; [
with md; [ (assert heading "# heading 1" == [ "#" "heading 1" ]; "echo gets heading 1")
(assert heading "# heading 1" == ["#" "heading 1"]; "echo gets heading 1") (assert heading "## subheading" == [ "##" "subheading" ];
(assert heading "## subheading" == ["##" "subheading"]; "echo gets heading 2") "echo gets heading 2")
(assert heading "some paragraph" == null; "echo paragraph is heading 0") (assert heading "some paragraph" == null; "echo paragraph is heading 0")
(assert mdBlock "# heading 1" == elems.h 1 "heading 1"; "echo makes h1 tag") #(assert mdBlock "# heading 1" == elems.h 1 "heading 1"; "echo makes h1 tag")
(assert mdBlock "## subheading" == elems.h 2 "subheading"; "echo makes h2 tag") #(assert mdBlock "## subheading" == elems.h 2 "subheading"; "echo makes h2 tag")
(assert mdBlock "some paragraph" == elems.p {} "some paragraph"; "echo makes p tag") #(assert mdBlock "some paragraph" == elems.p {} "some paragraph"; "echo makes p tag")
(it "processes md block" { (it "processes md block" {
actual = readMd '' actual = readMd ''
# foo bar # foo bar
lorem ipsum
'';
expected = [
(elems.H 1 "foo bar")
""
(elems.p { } ''
lorem ipsum lorem ipsum
''; '')
expected = [ ];
(elems.h 1 "foo bar") asString = true;
"" })
(elems.p {} "lorem ipsum\n")
];
})
(it "can fix file appendixes" { (it "can fix file appendixes" {
actual = fixAppendix "index.md"; actual = fixAppendix "index.md";
expected = "index.html"; expected = "index.html";
}) })
(it "recursively reads dir" { (it "recursively reads dir" {
actual = recReadMd ./blog; actual = recReadMd ./blog;
expected = { expected = {
"index.md" = mdToPage ./blog/index.md; "index.md" = mdToPage ./blog/index.md;
"dir" = { "dir" = { "index.md" = mdToPage ./blog/dir/index.md; };
"index.md" = mdToPage ./blog/dir/index.md; };
}; asJSON = true;
}; })
})
(it "recursively fixes filename" { (it "recursively fixes filename" {
actual = recFixAppendix { actual = recFixAppendix {
"index.md" = "something"; "index.md" = "something";
dir = { dir = { "index.md" = "something else"; };
"index.md" = "something else"; };
}; expected = {
}; "index.html" = "something";
expected = { dir = { "index.html" = "something else"; };
"index.html" = "something"; };
dir = { })
"index.html" = "something else";
};
};
})
(it "recursively translates md to html" { (it "recursively translates md to html" {
actual = builtins.toJSON ( readDir ./blog ); actual = builtins.toJSON (readDir ./blog);
expected = builtins.toJSON { expected = builtins.toJSON {
"index.html" = mdToPage ./blog/index.md; "index.html" = mdToPage ./blog/index.md;
"dir" = { "dir" = { "index.html" = mdToPage ./blog/dir/index.md; };
"index.html" = mdToPage ./blog/dir/index.md; };
}; })
}; ]
})
]

View file

@ -3,104 +3,89 @@ let
elems = import ../nixite/elems.nix; elems = import ../nixite/elems.nix;
site = import ../nixite/site.nix; site = import ../nixite/site.nix;
it = import ./it.nix; it = import ./it.nix;
in in with site; [
with site; [ (it "applies a style" {
(it "applies a style" { expected = {
expected = { "index.html" = html.tag "html" { } [
"index.html" = html.tag "html" {} [ (html.tag "head" { } [
(html.tag "head" {} [(elems.title {} "foobar") (elems.stylesheet "/style.css")]) (elems.title { } "foobar")
(elems.main {} "something") (elems.Stylesheet "/style.css")
]; ])
blog = { (elems.main { } "something")
"index.html" = html.tag "html" {} [ ];
(html.tag "head" {} [(elems.title {} "foobar") (elems.stylesheet "/style.css")]) blog = {
(elems.main {} "blogy blog") "index.html" = html.tag "html" { } [
]; (html.tag "head" { } [
}; (elems.title { } "foobar")
"style.css" = '' (elems.Stylesheet "/style.css")
this is a stylesheet ])
''; (elems.main { } "blogy blog")
};
actual =
applyStyle ''
this is a stylesheet
'' {
"index.html" = html.tag "html" {} [
(html.tag "head" {} [(elems.title {} "foobar")])
(elems.main {} "something")
];
blog = {
"index.html" = html.tag "html" {} [
(html.tag "head" {} [(elems.title {} "foobar")])
(elems.main {} "blogy blog")
];
};
};
})
(it "extracts top level paths" {
actual = getPaths {
something = "";
src = ./src/index.md;
};
expected = {
"index.md" = ./src/index.md;
};
})
(it "extracts lower level paths" {
actual = getPaths {
something = "yes";
a-list = [
{thingy = ./src/index.md;}
[(html.tag "img" {src = ./src/favicon.png;} "")]
]; ];
}; };
expected = { "style.css" = ''
"index.md" = ./src/index.md; this is a stylesheet
"favicon.png" = ./src/favicon.png; '';
}; };
}) actual = applyStyle ''
(it "switches paths" { this is a stylesheet
actual = switchPaths { '' {
something = ""; "index.html" = html.tag "html" { } [
a-thing = { (html.tag "head" { } [ (elems.title { } "foobar") ])
src = ./src/index.md; (elems.main { } "something")
}; ];
a-list = [ blog = {
{thingy = ./src/index.md;} "index.html" = html.tag "html" { } [
(html.tag "head" { } [ (elems.title { } "foobar") ])
(elems.main { } "blogy blog")
]; ];
}; };
expected = { };
something = ""; asJSON = true;
a-thing = { })
src = "/static/index.md"; (it "extracts top level paths" {
}; actual = getPaths {
a-list = [ something = "";
{thingy = "/static/index.md";} src = ./src/index.md;
]; };
}; expected = { "index.md" = ./src/index.md; };
}) })
(it "extracts 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" { (it "extracts paths" {
actual = extractPaths { actual = extractPaths {
something = ""; something = "";
a-thing = { a-thing = { src = ./src/index.md; };
src = ./src/index.md; a-list = [{ thingy = ./src/index.md; }];
}; };
a-list = [ expected = {
{thingy = ./src/index.md;} something = "";
]; a-thing = { src = "/static/index.md"; };
}; a-list = [{ thingy = "/static/index.md"; }];
expected = { static = { "index.md" = ./src/index.md; };
something = ""; };
a-thing = { })
src = "/static/index.md"; ]
};
a-list = [
{thingy = "/static/index.md";}
];
static = {
"index.md" = ./src/index.md;
};
};
})
]

View file

@ -3,78 +3,89 @@ let
html = import ../nixite/html.nix; html = import ../nixite/html.nix;
it = import ./it.nix; it = import ./it.nix;
my = p = style.styled "generic" "p" {
(style.styled "p" "p" {style = { foo = "bar";
some-style = "some value"; forgetme = "nothing";
};}) };
(style.styled "div" "div" {class = ["something"]; style = {
this = "that"; my = (style.styled "p" "p" { style = { some-style = "some value"; }; })
};}) (style.styled "classless" "div" { class = [ ]; })
(style.styled "s" "div" { (style.styled "quote" p.generic {
id = "s"; baz = "baz";
class = ["something"]; forgetme = "forgotten";
style = { }) (style.styled "div" "div" {
s = "yes"; class = [ "something" ];
};}) style = { this = "that"; };
(style.styled "foobar" "div" { }) (style.styled "s" "div" {
class = ["foo" "bar"]; id = "s";
style = { class = [ "something" ];
something = "something"; style = { s = "yes"; };
}; }) (style.styled "foobar" "div" {
} ) class = [ "foo" "bar" ];
(style.style "body" { style = { something = "something"; };
foo = "bar"; }) (style.style "body" { foo = "bar"; }) (style.styled "list" "ul" {
})
(style.styled "list" "ul" {
__child = child: __child = child:
assert builtins.isList child; (map (html.tag "li" {}) child); assert builtins.isList child;
(map (html.tag "li" { }) child);
}); });
in [ in [
(it "extends existing components" {
expected = html.tag "p" {
forgetme = "forgotten";
baz = "baz";
foo = "bar";
class = [ "generic" "quote" ];
} "yes";
actual = my.quote { } "yes";
asString = true;
})
(it "makes a p component" { (it "makes a p component" {
expected = html.tag "p" {class = ["p"];} "yes"; expected = html.tag "p" { class = [ "p" ]; } "yes";
actual = my.p {} "yes"; actual = my.p { } "yes";
asString = true;
})
(it "makes a component with no class" {
expected = html.tag "div" { class = [ ]; } "yes";
actual = my.classless { } "yes";
asString = true; asString = true;
}) })
(it "does not error without attrs" { (it "does not error without attrs" {
expected = html.tag "p" {class = ["p"];} "yes"; expected = html.tag "p" { class = [ "p" ]; } "yes";
actual = my.p "yes"; actual = my.p "yes";
asString = true; asString = true;
}) })
(it "makes a component" { (it "makes a component" {
expected = html.tag "div" {class = ["something"];} "foobar"; expected = html.tag "div" { class = [ "div" "something" ]; } "foobar";
actual = my.div {} "foobar"; actual = my.div { } "foobar";
asString = true; asString = true;
}) })
(it "makes special components" { (it "makes special components" {
expected = html.tag "div" { expected = html.tag "div" {
id = "s"; id = "s";
class = ["something"]; class = [ "s" "something" ];
} "foobar"; } "foobar";
actual = my.s {} "foobar"; actual = my.s { } "foobar";
asString = true; asString = true;
}) })
(it "works on many classes" { (it "works on many classes" {
expected = html.tag "div" {class = ["foo" "bar"];} "foobar"; expected = html.tag "div" { class = [ "foobar" "foo" "bar" ]; } "foobar";
actual = my.foobar {} "foobar"; actual = my.foobar { } "foobar";
asString = true; asString = true;
}) })
(it "does custom behavour" { (it "does custom behavour" {
expected = (html.tag "ul" { expected = html.tag "ul" {
__ = ""; __ = "";
class = ["list"]; class = [ "list" ];
} [ } [ (html.tag "li" { } "1") (html.tag "li" { } "2") ];
(html.tag "li" {} "1") actual = my.list { } [ "1" "2" ];
(html.tag "li" {} "2")
]);
actual = (my.list {} ["1" "2"]);
asString = true; asString = true;
}) })
(it "combines attrs" { (it "combines attrs" {
expected = html.tag "div" { expected = html.tag "div" {
id = "foo"; id = "foo";
class = ["something"]; class = [ "div" "something" ];
} "foobar"; } "foobar";
actual = my.div {id = "foo";} "foobar"; actual = my.div { id = "foo"; } "foobar";
asString = true; asString = true;
}) })
(it "makes a style" { (it "makes a style" {