reusable, extendable tags
This commit is contained in:
parent
8e97ebe2ce
commit
e76305f71a
17
flake.nix
17
flake.nix
|
@ -10,30 +10,29 @@
|
||||||
packages.${system} = {
|
packages.${system} = {
|
||||||
raw = nixite.mkSite (let
|
raw = nixite.mkSite (let
|
||||||
readme = {
|
readme = {
|
||||||
type = "link";
|
|
||||||
name = "readme";
|
name = "readme";
|
||||||
content = nixite.md.mdToPage ./README.md;
|
content = nixite.md.mdToPage ./README.md;
|
||||||
};
|
};
|
||||||
markup = {
|
markup = {
|
||||||
"test" = with nixite.elems;
|
"index.html" = with nixite.elems;
|
||||||
let
|
let
|
||||||
blue = nixite.style.tag "span" "blue" {
|
blue = nixite.style.component span "blue" {
|
||||||
style = { color = "blue"; };
|
style = { color = "blue"; };
|
||||||
};
|
};
|
||||||
underblue = nixite.style.extend 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 = 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 "great!")
|
(underblue { onclick = "alert(1)"; } "great!")
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -28,26 +28,28 @@ in rec {
|
||||||
else
|
else
|
||||||
keyvalue key value) attrs)));
|
keyvalue key value) attrs)));
|
||||||
|
|
||||||
tag = tag: {
|
tag = t: {
|
||||||
inherit tag;
|
tag = t;
|
||||||
__toString = self: toString (self { } "");
|
attrs = {};
|
||||||
__functor = self: attrs:
|
|
||||||
if !(builtins.isAttrs attrs) then
|
|
||||||
throw "HTML tag requires attribute set"
|
|
||||||
else {
|
|
||||||
inherit tag attrs;
|
|
||||||
__toString = self: toString (self "");
|
__toString = self: toString (self "");
|
||||||
__functor = self: child:
|
__functor = self: child:
|
||||||
if !(isTag child) then
|
(if !(isTag child) then
|
||||||
|
(if isSet child then
|
||||||
|
self // ({attrs = self.attrs // child;})
|
||||||
|
else
|
||||||
throw "tag child must be tag, list, or string, got ${
|
throw "tag child must be tag, list, or string, got ${
|
||||||
builtins.typeOf child
|
builtins.typeOf child
|
||||||
}"
|
}"
|
||||||
|
)
|
||||||
else {
|
else {
|
||||||
inherit tag attrs child;
|
tag = t;
|
||||||
|
attrs = self.attrs;
|
||||||
|
inherit child;
|
||||||
__toString = toHTML;
|
__toString = toHTML;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
};
|
|
||||||
};
|
isSet = a: builtins.isAttrs a && !a ? __toString;
|
||||||
|
|
||||||
isTag = tag:
|
isTag = tag:
|
||||||
(builtins.isString tag || builtins.isList tag
|
(builtins.isString tag || builtins.isList tag
|
||||||
|
|
|
@ -112,6 +112,8 @@ in rec {
|
||||||
else
|
else
|
||||||
[ ]);
|
[ ]);
|
||||||
|
|
||||||
|
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 ''
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
let
|
let
|
||||||
html = import ./html.nix;
|
|
||||||
|
|
||||||
styleToString = identifier: styles:
|
styleToString = identifier: styles:
|
||||||
if !builtins.isAttrs styles then
|
if !builtins.isAttrs styles then
|
||||||
|
@ -21,7 +20,7 @@ let
|
||||||
({
|
({
|
||||||
${element.attrs.__id} = element.attrs.style or { };
|
${element.attrs.__id} = element.attrs.style or { };
|
||||||
} // (if element.attrs ? __extends then {
|
} // (if element.attrs ? __extends then {
|
||||||
${element.attrs.__extends.attrs.__id} =
|
${element.attrs.__extends.attrs.__id or element.attrs.__extends.tag} =
|
||||||
element.attrs.__extends.attrs.style or { };
|
element.attrs.__extends.attrs.style or { };
|
||||||
} else
|
} else
|
||||||
{ }))
|
{ }))
|
||||||
|
@ -42,10 +41,11 @@ let
|
||||||
builtins.zipAttrsWith (name: value: builtins.elemAt value 0)
|
builtins.zipAttrsWith (name: value: builtins.elemAt value 0)
|
||||||
(map getStyles elements);
|
(map getStyles elements);
|
||||||
|
|
||||||
mkProps = props: tag: class:
|
mkProps = tag: class: props:
|
||||||
props // {
|
props // {
|
||||||
__id = "${tag}.${builtins.concatStringsSep "." class}";
|
__id = "${tag.tag}.${class}";
|
||||||
class = class ++ (props.class or [ ]);
|
__extends = tag;
|
||||||
|
class = ( tag.attrs.class or [] ) ++ [ class ] ++ (props.class or [ ]);
|
||||||
};
|
};
|
||||||
|
|
||||||
stylesToString = styles:
|
stylesToString = styles:
|
||||||
|
@ -55,11 +55,6 @@ let
|
||||||
in {
|
in {
|
||||||
inherit getStyle getStyles stylesToString;
|
inherit getStyle getStyles stylesToString;
|
||||||
|
|
||||||
extend = tag: class: props:
|
component = tag: class: props:
|
||||||
(html.tag tag.tag ((mkProps props tag.tag (tag.attrs.class ++ [ class ]))
|
tag ( mkProps tag class props );
|
||||||
// {
|
|
||||||
__extends = tag;
|
|
||||||
}));
|
|
||||||
|
|
||||||
tag = tag: class: props: (html.tag tag (mkProps props tag [ class ]));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,12 @@ in with html; [
|
||||||
expected = ''<p class="foobar"></p>'';
|
expected = ''<p class="foobar"></p>'';
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
(it "can take many sets of props" (let p = tag "p";
|
||||||
|
in {
|
||||||
|
actual = toString (p { class = "foobar"; } { style = "a style"; });
|
||||||
|
expected = ''<p class="foobar" style="a style"></p>'';
|
||||||
|
}))
|
||||||
|
|
||||||
(it "works recursively" (let
|
(it "works recursively" (let
|
||||||
attrs = { style = { foo = "bar"; }; };
|
attrs = { style = { foo = "bar"; }; };
|
||||||
para = (tag "p" attrs);
|
para = (tag "p" attrs);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
path:
|
path:
|
||||||
|
builtins.trace ( "testing " + builtins.baseNameOf path )
|
||||||
''
|
''
|
||||||
echo
|
echo
|
||||||
echo 'TEST: ${builtins.baseNameOf path}'
|
echo 'TEST: ${builtins.baseNameOf path}'
|
||||||
|
|
|
@ -4,7 +4,7 @@ msg:
|
||||||
let
|
let
|
||||||
preProcess = v:
|
preProcess = v:
|
||||||
if removeDunders then
|
if removeDunders then
|
||||||
builtins.removeAttrs v [ "__toString" "__functor" ]
|
undunder v
|
||||||
else if asString then
|
else if asString then
|
||||||
toString v
|
toString v
|
||||||
else if asJSON then
|
else if asJSON then
|
||||||
|
@ -15,11 +15,14 @@ let
|
||||||
a = preProcess actual;
|
a = preProcess actual;
|
||||||
e = preProcess expected;
|
e = preProcess expected;
|
||||||
|
|
||||||
|
undunder = v: if builtins.isAttrs v then builtins.removeAttrs v [ "__toString" "__functor" ] else v;
|
||||||
|
|
||||||
|
out = (if safeToPrint then builtins.toJSON (undunder actual) else ''{"msg": "refusing to print"}'');
|
||||||
|
|
||||||
in if (a == e) then ''
|
in if (a == e) then ''
|
||||||
echo 'it ${msg}'
|
echo 'it ${msg}'
|
||||||
'' else
|
'' else
|
||||||
builtins.trace "FAILED ${msg}" builtins.trace
|
builtins.trace "FAILED ${msg}" ''
|
||||||
(if safeToPrint then builtins.toJSON actual else actual) builtins.trace
|
|
||||||
(if safeToPrint then builtins.toJSON expected else expected) ''
|
|
||||||
echo FAILED ${msg}
|
echo FAILED ${msg}
|
||||||
|
echo '${out}' | jq '.'
|
||||||
''
|
''
|
||||||
|
|
|
@ -85,13 +85,13 @@ in with site; [
|
||||||
})
|
})
|
||||||
|
|
||||||
(it "gets all styles" {
|
(it "gets all styles" {
|
||||||
expected = {
|
expected = {"p"={};"div"={};
|
||||||
"p.class" = { color = "blue"; };
|
"p.class" = { color = "blue"; };
|
||||||
"a.class2" = { color = "green"; };
|
"div.class2" = { color = "green"; };
|
||||||
};
|
};
|
||||||
actual = getStyles (let
|
actual = getStyles (let
|
||||||
p = style.tag "p" "class" { style = { color = "blue"; }; };
|
p = style.component elems.p "class" { style = { color = "blue"; }; };
|
||||||
g = style.tag "a" "class2" { style = { color = "green"; }; };
|
g = style.component elems.div "class2" { style = { color = "green"; }; };
|
||||||
in {
|
in {
|
||||||
"index.html" = p "";
|
"index.html" = p "";
|
||||||
blog = { "index.html" = g ""; };
|
blog = { "index.html" = g ""; };
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
let
|
let
|
||||||
style = import ../nixite/style.nix;
|
style = import ../nixite/style.nix;
|
||||||
|
elems = import ../nixite/elems.nix;
|
||||||
it = import ./it.nix;
|
it = import ./it.nix;
|
||||||
|
|
||||||
in [
|
in [
|
||||||
|
|
||||||
(it "fetches empty style" (let para = (style.tag "p" "para" { });
|
(it "fetches empty style" (let para = (style.component elems.p "para" { });
|
||||||
in {
|
in {
|
||||||
expected = { "p.para" = { }; };
|
expected = { "p" = {}; "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.tag "p" "para" attrs);
|
para = (style.component elems.p "para" attrs);
|
||||||
in {
|
in {
|
||||||
expected = { "p.para" = attrs.style; };
|
expected = {"p" = {}; "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.tag "p" "para" attrs);
|
para = (style.component elems.p "para" attrs);
|
||||||
in {
|
in {
|
||||||
expected = [ "para" ];
|
expected = [ "para" ];
|
||||||
actual = (para "").attrs.class;
|
actual = (para "").attrs.class;
|
||||||
|
@ -31,7 +32,7 @@ in [
|
||||||
style = { foo = "bar"; };
|
style = { foo = "bar"; };
|
||||||
class = [ "other" "class" ];
|
class = [ "other" "class" ];
|
||||||
};
|
};
|
||||||
para = (style.tag "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;
|
||||||
|
@ -39,32 +40,32 @@ in [
|
||||||
|
|
||||||
(it "fetches style for class" (let
|
(it "fetches style for class" (let
|
||||||
s = { foo = "bar"; };
|
s = { foo = "bar"; };
|
||||||
para = (style.tag "p" "para" { style = s; });
|
para = (style.component elems.p "para" { style = s; });
|
||||||
in {
|
in {
|
||||||
expected = { "p.para" = s; };
|
expected = { "p" = {}; "p.para" = s; };
|
||||||
actual = style.getStyle (para "");
|
actual = style.getStyle (para "");
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "fetches style recursively" (let
|
(it "fetches style recursively" (let
|
||||||
s = {
|
s = {"p" = {};"div" = {};
|
||||||
"p.para" = { foo = "bar"; };
|
"p.para" = { foo = "bar"; };
|
||||||
"a.link" = { this = "that"; };
|
"div.link" = { this = "that"; };
|
||||||
};
|
};
|
||||||
para = (style.tag "p" "para" { style = s."p.para"; });
|
para = (style.component elems.p "para" { style = s."p.para"; });
|
||||||
a = (style.tag "a" "link" { style = s."a.link"; });
|
div = (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 (div "hello"));
|
||||||
removeDunders = true;
|
removeDunders = true;
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "fetches style recursively through lists" (let
|
(it "fetches style recursively through lists" (let
|
||||||
s = {
|
s = {"p" = {};"div" = {};
|
||||||
"p.para" = { foo = "bar"; };
|
"p.para" = { foo = "bar"; };
|
||||||
"a.link" = { this = "that"; };
|
"div.link" = { this = "that"; };
|
||||||
};
|
};
|
||||||
para = (style.tag "p" "para" { style = s."p.para"; });
|
para = (style.component elems.p "para" { style = s."p.para"; });
|
||||||
a = (style.tag "a" "link" { style = s."a.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") ]);
|
||||||
|
@ -72,12 +73,12 @@ in [
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "fetches style recursively with repeats" (let
|
(it "fetches style recursively with repeats" (let
|
||||||
s = {
|
s = {"p" = {};"div" = {};
|
||||||
"p.para" = { foo = "bar"; };
|
"p.para" = { foo = "bar"; };
|
||||||
"a.link" = { this = "that"; };
|
"div.link" = { this = "that"; };
|
||||||
};
|
};
|
||||||
para = (style.tag "p" "para" { style = s."p.para"; });
|
para = (style.component elems.p "para" { style = s."p.para"; });
|
||||||
a = (style.tag "a" "link" { style = s."a.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") ]);
|
||||||
|
@ -85,7 +86,7 @@ in [
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "converts styles to string" (let
|
(it "converts styles to string" (let
|
||||||
s = {
|
s = {"p" = {};
|
||||||
"p.para" = { foo = "bar"; };
|
"p.para" = { foo = "bar"; };
|
||||||
"a.link" = { this = "that"; };
|
"a.link" = { this = "that"; };
|
||||||
};
|
};
|
||||||
|
@ -104,10 +105,10 @@ in [
|
||||||
(it "extends styled tags" (let
|
(it "extends styled tags" (let
|
||||||
s = {
|
s = {
|
||||||
"p.para" = { foo = "bar"; };
|
"p.para" = { foo = "bar"; };
|
||||||
"p.para.oof" = { oof = "yes"; };
|
"p.oof" = { oof = "yes"; };
|
||||||
};
|
};
|
||||||
para = (style.tag "p" "para" { style = s."p.para"; });
|
para = (style.component elems.p "para" { style = s."p.para"; });
|
||||||
para2 = (style.extend para "oof" { style = s."p.para.oof"; });
|
para2 = (style.component para "oof" { style = s."p.oof"; });
|
||||||
in {
|
in {
|
||||||
expected = s;
|
expected = s;
|
||||||
actual = style.getStyles (para2 "");
|
actual = style.getStyles (para2 "");
|
||||||
|
@ -115,12 +116,12 @@ in [
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(it "extends styled tags classes" (let
|
(it "extends styled tags classes" (let
|
||||||
s = {
|
s = {"p" = {}; "div" = {};
|
||||||
"p.para" = { foo = "bar"; };
|
"p.para" = { foo = "bar"; };
|
||||||
"p.para.oof" = { oof = "yes"; };
|
"p.para.oof" = { oof = "yes"; };
|
||||||
};
|
};
|
||||||
para = (style.tag "p" "para" { style = s."p.para"; });
|
para = (style.component elems.p "para" { style = s."p.para"; });
|
||||||
para2 = (style.extend 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