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,46 +1,37 @@
{ {
description = "A site in nix?"; description = "A site in nix?";
outputs = { outputs = { self, nixpkgs, }:
self, let
nixpkgs,
}: let
system = "x86_64-linux"; system = "x86_64-linux";
pkgs = import nixpkgs { pkgs = import nixpkgs { inherit system; };
inherit system; nixite = import ./nixite/. { inherit pkgs; };
}; in nixite // {
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") (title "Nixite")
(nixite.html.tag "link" {rel = "shortcut icon"; type = "image/png"; href = ./testing/src/favicon.png;} "") (nixite.html.tag "link" {
rel = "shortcut icon";
type = "image/png";
href = ./testing/src/favicon.png;
} "")
] ]
(main [ (main [
(link "/blog" "blog") (a "/blog" "blog")
(list [ (list [ "item 1" "item 2" "item 3" ])
"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
pkgs.writeShellScriptBin "test" ''
${test ./testing/md.test.nix} ${test ./testing/md.test.nix}
${test ./testing/html.test.nix} ${test ./testing/html.test.nix}
${test ./testing/elems.test.nix} ${test ./testing/elems.test.nix}

View file

@ -1,6 +1,7 @@
{pkgs, ...}: { { pkgs, ... }: {
mkSite = import ./make-site.nix pkgs; mkSite = import ./make-site.nix pkgs;
serve = site: (pkgs.writeShellScriptBin "serve" '' serve = site:
(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;

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")
(base "code") (base "var") (base "samp") (base "kbd") (base "sub") (base "sup")
(base "i") (base "b") (base "u") (base "mark") (base "bdi") (base "bdo")
(base "span") (base "br") (base "wbr") (base "ins") (base "del")
(base "picture") (base "source") (base "img") (base "iframe") (base "embed")
(base "object") (base "param") (base "video") (base "audio") (base "track")
(base "map") (base "area") (base "table") (base "caption") (base "colgroup")
(base "col") (base "tbody") (base "thead") (base "tfoot") (base "tr")
(base "td") (base "th") (base "form") (base "label") (base "input")
(base "button") (base "select") (base "datalist") (base "optgroup")
(base "option") (base "textarea") (base "output") (base "progress")
(base "meter") (base "fieldset") (base "legend") (base "details")
(base "summary") (base "dialog") (base "script") (base "noscript")
(base "template") (base "slot") (base "canvas")
(s.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);
(s.styled "doc" "html" { }) (s.styled "Doc" "html" {
__child = child: __child = 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 "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))
]; ];
lang = "en"; lang = "en";
class = []; class = [ ];
}) }) (s.styled "a" "a" {
(s.styled "link" "a" {
__self = self: attrs: child: __self = self: attrs: child:
if builtins.isString attrs then if builtins.isString attrs then
self {href = attrs;} child else self { href = attrs; } child
else
self attrs child; self attrs child;
}) }) (s.styled "Stylesheet" "link" {
(s.styled "stylesheet" "link" {
rel = "stylesheet"; rel = "stylesheet";
class = []; class = [ ];
__self = self: attrs: __self = self: attrs:
if builtins.isString attrs then if builtins.isString attrs then
self {href = attrs;} "" else self { href = attrs; } ""
else
self attrs ""; self attrs "";
}) }) // {
// { H = v: child: html.tag "h${toString v}" { } child;
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
""
else
''${key}="${toString value}"''; ''${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,7 +1,7 @@
{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 = ''
@ -13,4 +13,4 @@ in
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 (
builtins.mapAttrs (name: value: {
name = fixAppendix name; name = fixAppendix name;
value = value = if builtins.isAttrs value then recFixAppendix value else value;
if builtins.isAttrs value }) site));
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:
let
m = heading block; m = heading block;
h = h = if m == null then 0 else builtins.stringLength (builtins.elemAt m 0);
if m == null in if m == null then elems.p { } block else elems.H h (builtins.elemAt m 1);
then 0
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; name = baseNameOf path;
value = path; value = path;
} }] else if builtins.isAttrs path then
] builtins.concatLists (map getPathsKV (builtins.attrValues path))
else if builtins.isAttrs path else if builtins.isList path then
then builtins.concatLists (map getPathsKV (builtins.attrValues path)) builtins.concatLists (map getPathsKV path)
else if builtins.isList path else
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 (
name: content:
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 ${builtins.typeOf content}: [${toString content}]" throw "Site page must be string, path or attrset, but got ${
) builtins.typeOf content
site }: [${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:
assert builtins.isString name;
let
__child = cprops.__child or (child: child); __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 = if builtins.isFunction tag then
props: tag (joinProps props)
else if builtins.isString tag then
props: html.tag tag (joinProps props)
else
throw "You may only style a tag (string) or element, got ${
builtins.typeOf tag
}";
__self = (cprops.__self or (self: props: __self = (cprops.__self or (self: props:
if builtins.isAttrs props if builtins.isAttrs props then
then (child: ( self props (__child child) )) (child: (self props (__child child)))
else if builtins.isString props || builtins.isList props else if builtins.isString props || builtins.isList props then
then (self {} (__child props)) (self { } (__child props))
else throw "Call element with attributes and child." else
)) self; throw "Call element with attributes and child.")) self;
in {
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,51 +2,53 @@ 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" {class = ["p"];} "foobar"; expected = html.tag "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" {class = ["div"];} "foobar"; expected = html.tag "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" {class = ["section"];} "foobar"; expected = html.tag "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" {class = ["span"];} "foobar"; expected = html.tag "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" {class = ["main"];} ["yeet"]; expected = html.tag "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" {class = [];} "foobar"; expected = html.tag "title" { } "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" {class = ["link"]; href = "https://example.com";} "example"; expected = html.tag "a" {
actual = link "https://example.com" "example"; class = [ "a" ];
href = "https://example.com";
} "example";
actual = a "https://example.com" "example";
asString = true; asString = true;
}) })
(it "makes a stylesheet link" { (it "makes a stylesheet link" {
@ -54,31 +56,28 @@ in
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" {
__ = ""; __ = "";
class = ["list"]; class = [ "List" ];
} [ } [
(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"]) actual = Doc { } [ [ "foo" ] "bar" ];
(html.tag "body" {} "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 ''
else ''
echo 'FAILED: ${msg}' echo 'FAILED: ${msg}'
echo '${builtins.toJSON expected}' echo '${builtins.toJSON expected}'
echo '${builtins.toJSON actual}' echo '${builtins.toJSON actual}'
'' ''

View file

@ -2,15 +2,15 @@ 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 ''
@ -19,10 +19,13 @@ in
lorem ipsum lorem ipsum
''; '';
expected = [ expected = [
(elems.h 1 "foo bar") (elems.H 1 "foo bar")
"" ""
(elems.p {} "lorem ipsum\n") (elems.p { } ''
lorem ipsum
'')
]; ];
asString = true;
}) })
(it "can fix file appendixes" { (it "can fix file appendixes" {
@ -34,34 +37,27 @@ in
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 = { expected = {
"index.html" = "something"; "index.html" = "something";
dir = { dir = { "index.html" = "something else"; };
"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,55 +3,58 @@ 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" {} [(elems.title {} "foobar") (elems.stylesheet "/style.css")]) (html.tag "head" { } [
(elems.main {} "something") (elems.title { } "foobar")
(elems.Stylesheet "/style.css")
])
(elems.main { } "something")
]; ];
blog = { blog = {
"index.html" = html.tag "html" {} [ "index.html" = html.tag "html" { } [
(html.tag "head" {} [(elems.title {} "foobar") (elems.stylesheet "/style.css")]) (html.tag "head" { } [
(elems.main {} "blogy blog") (elems.title { } "foobar")
(elems.Stylesheet "/style.css")
])
(elems.main { } "blogy blog")
]; ];
}; };
"style.css" = '' "style.css" = ''
this is a stylesheet this is a stylesheet
''; '';
}; };
actual = actual = applyStyle ''
applyStyle ''
this is a stylesheet this is a stylesheet
'' { '' {
"index.html" = html.tag "html" {} [ "index.html" = html.tag "html" { } [
(html.tag "head" {} [(elems.title {} "foobar")]) (html.tag "head" { } [ (elems.title { } "foobar") ])
(elems.main {} "something") (elems.main { } "something")
]; ];
blog = { blog = {
"index.html" = html.tag "html" {} [ "index.html" = html.tag "html" { } [
(html.tag "head" {} [(elems.title {} "foobar")]) (html.tag "head" { } [ (elems.title { } "foobar") ])
(elems.main {} "blogy blog") (elems.main { } "blogy blog")
]; ];
}; };
}; };
asJSON = true;
}) })
(it "extracts top level paths" { (it "extracts top level paths" {
actual = getPaths { actual = getPaths {
something = ""; something = "";
src = ./src/index.md; src = ./src/index.md;
}; };
expected = { expected = { "index.md" = ./src/index.md; };
"index.md" = ./src/index.md;
};
}) })
(it "extracts lower level paths" { (it "extracts lower level paths" {
actual = getPaths { actual = getPaths {
something = "yes"; something = "yes";
a-list = [ a-list = [
{thingy = ./src/index.md;} { thingy = ./src/index.md; }
[(html.tag "img" {src = ./src/favicon.png;} "")] [ (html.tag "img" { src = ./src/favicon.png; } "") ]
]; ];
}; };
expected = { expected = {
@ -62,45 +65,27 @@ in
(it "switches paths" { (it "switches paths" {
actual = switchPaths { actual = switchPaths {
something = ""; something = "";
a-thing = { a-thing = { src = ./src/index.md; };
src = ./src/index.md; a-list = [{ thingy = ./src/index.md; }];
};
a-list = [
{thingy = ./src/index.md;}
];
}; };
expected = { expected = {
something = ""; something = "";
a-thing = { a-thing = { src = "/static/index.md"; };
src = "/static/index.md"; a-list = [{ thingy = "/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 = [
{thingy = ./src/index.md;}
];
}; };
expected = { expected = {
something = ""; something = "";
a-thing = { a-thing = { src = "/static/index.md"; };
src = "/static/index.md"; a-list = [{ thingy = "/static/index.md"; }];
}; static = { "index.md" = ./src/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 = {
some-style = "some value";
};})
(style.styled "div" "div" {class = ["something"]; style = {
this = "that";
};})
(style.styled "s" "div" {
id = "s";
class = ["something"];
style = {
s = "yes";
};})
(style.styled "foobar" "div" {
class = ["foo" "bar"];
style = {
something = "something";
};
} )
(style.style "body" {
foo = "bar"; foo = "bar";
}) forgetme = "nothing";
(style.styled "list" "ul" { };
my = (style.styled "p" "p" { style = { some-style = "some value"; }; })
(style.styled "classless" "div" { class = [ ]; })
(style.styled "quote" p.generic {
baz = "baz";
forgetme = "forgotten";
}) (style.styled "div" "div" {
class = [ "something" ];
style = { this = "that"; };
}) (style.styled "s" "div" {
id = "s";
class = [ "something" ];
style = { s = "yes"; };
}) (style.styled "foobar" "div" {
class = [ "foo" "bar" ];
style = { something = "something"; };
}) (style.style "body" { foo = "bar"; }) (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" {