WIP inheritance
This commit is contained in:
parent
b734310051
commit
35b8cf7472
16
flake.nix
16
flake.nix
|
@ -32,14 +32,14 @@
|
||||||
|
|
||||||
default = nixite.serve self.packages.${system}.raw;
|
default = nixite.serve self.packages.${system}.raw;
|
||||||
|
|
||||||
test = let test = import ./testing/import.nix;
|
test = let run = import ./testing/run.nix pkgs;
|
||||||
in pkgs.writeShellScriptBin "test" ''
|
in run [
|
||||||
${test ./testing/md.test.nix}
|
#./testing/md.test.nix
|
||||||
${test ./testing/html.test.nix}
|
./testing/html.test.nix
|
||||||
${test ./testing/elems.test.nix}
|
#./testing/elems.test.nix
|
||||||
${test ./testing/site.test.nix}
|
#./testing/site.test.nix
|
||||||
${test ./testing/style.test.nix}
|
./testing/style.test.nix
|
||||||
'';
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
let
|
let
|
||||||
keyvalue = key: value:
|
keyvalue = key: value:
|
||||||
assert builtins.isString key;
|
assert builtins.isString key;
|
||||||
if value == "" || value == [ ] || value == { } then
|
if builtins.isAttrs value then
|
||||||
|
builtins.trace "Skipping ${key} as it is a set" "" else
|
||||||
|
if value == "" || value == [ ] then
|
||||||
""
|
""
|
||||||
else
|
else
|
||||||
''${key}="${toString value}"'';
|
''${key}="${toString value}"'';
|
||||||
|
@ -26,11 +28,27 @@ in rec {
|
||||||
else
|
else
|
||||||
keyvalue key value) attrs)));
|
keyvalue key value) attrs)));
|
||||||
|
|
||||||
tag = tag: attrs: child: {
|
tag = tag: {
|
||||||
inherit tag attrs child;
|
inherit tag;
|
||||||
__toString = toHTML;
|
__functor = self: attrs:
|
||||||
|
if !(builtins.isAttrs attrs) then
|
||||||
|
throw "HTML tag requires attribute set"
|
||||||
|
else {
|
||||||
|
inherit attrs;
|
||||||
|
__functor = self: child:
|
||||||
|
if !(isTag child) then
|
||||||
|
throw "tag child must be tag, list, or string"
|
||||||
|
else {
|
||||||
|
inherit tag attrs child;
|
||||||
|
__toString = toHTML;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
isTag = tag:
|
||||||
|
(builtins.isString tag || builtins.isList tag
|
||||||
|
|| (tag ? toString && builtins.isFunction tag.toString));
|
||||||
|
|
||||||
addToHead = page: heads:
|
addToHead = page: heads:
|
||||||
page // {
|
page // {
|
||||||
child = map
|
child = map
|
||||||
|
|
|
@ -2,25 +2,40 @@ let
|
||||||
html = import ./html.nix;
|
html = import ./html.nix;
|
||||||
|
|
||||||
join = {
|
join = {
|
||||||
__functor = self: new: self // new // { style = self.style + new.style; };
|
__functor = self: new: self // new // { style = self.style // new.style; };
|
||||||
};
|
};
|
||||||
|
|
||||||
mkStyle = identifier: styles:
|
mkStyle = identifier: styles: {
|
||||||
if styles == { } then
|
${identifier} = styles;
|
||||||
|
__toString = self:
|
||||||
|
toString (builtins.attrValues (builtins.mapAttrs styleToString self));
|
||||||
|
};
|
||||||
|
|
||||||
|
styleToString = identifier: styles:
|
||||||
|
if !builtins.isAttrs styles then
|
||||||
""
|
""
|
||||||
else ''
|
else if styles == { } then
|
||||||
${identifier} {
|
""
|
||||||
${
|
else
|
||||||
toString (builtins.attrValues
|
assert builtins.isString identifier; ''
|
||||||
(builtins.mapAttrs (key: value: "${key}: ${value};") styles))
|
${identifier} {
|
||||||
|
${
|
||||||
|
toString (builtins.attrValues
|
||||||
|
(builtins.mapAttrs (key: value: "${key}: ${value};") styles))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
'';
|
||||||
'';
|
|
||||||
|
|
||||||
mkIdentifier = name: tag:
|
mkIdentifier = name: tag:
|
||||||
{ class ? [ name ], id ? "", ... }:
|
assert builtins.isString name;
|
||||||
"${tag}" + builtins.concatStringsSep "" (map (c: "." + c) class)
|
let
|
||||||
|
elem = if builtins.isString tag then tag else tag.tag or "";
|
||||||
|
inheritClass =
|
||||||
|
if builtins.isString tag then [ ] else tag.attrs.class or [ ];
|
||||||
|
in { class ? [ name ] ++ inheritClass, id ? "", ... }:
|
||||||
|
"${elem}" + builtins.concatStringsSep "" (map (c: "." + c) class)
|
||||||
+ (if id != "" then "#" else "") + id;
|
+ (if id != "" then "#" else "") + id;
|
||||||
|
|
||||||
in {
|
in {
|
||||||
styled = name: tag: cprops:
|
styled = name: tag: cprops:
|
||||||
assert builtins.isString name;
|
assert builtins.isString name;
|
||||||
|
@ -36,9 +51,9 @@ in {
|
||||||
if cprops.class == [ ] then [ ] else [ name ] ++ cprops.class
|
if cprops.class == [ ] then [ ] else [ name ] ++ cprops.class
|
||||||
else
|
else
|
||||||
[ name ];
|
[ name ];
|
||||||
}) { style = ""; };
|
});
|
||||||
|
|
||||||
self = if builtins.isFunction tag then
|
self = if tag ? __functor && builtins.isFunction tag.__functor then
|
||||||
props: tag (joinProps props)
|
props: tag (joinProps props)
|
||||||
else if builtins.isString tag then
|
else if builtins.isString tag then
|
||||||
props: html.tag tag (joinProps props)
|
props: html.tag tag (joinProps props)
|
||||||
|
@ -54,8 +69,14 @@ in {
|
||||||
(self { } (__child props))
|
(self { } (__child props))
|
||||||
else
|
else
|
||||||
throw "Call element with attributes and child.")) self;
|
throw "Call element with attributes and child.")) self;
|
||||||
|
|
||||||
in {
|
in {
|
||||||
${name} = __self;
|
${name} = {
|
||||||
|
tag = (if builtins.isString tag then tag else tag.tag);
|
||||||
|
attrs =
|
||||||
|
joinProps (if builtins.isString tag then { } else tag.attrs or { });
|
||||||
|
__functor = self: __self;
|
||||||
|
};
|
||||||
|
|
||||||
style = mkStyle (mkIdentifier name tag cprops) (cprops.style or { });
|
style = mkStyle (mkIdentifier name tag cprops) (cprops.style or { });
|
||||||
} // join;
|
} // join;
|
||||||
|
|
|
@ -2,6 +2,19 @@ let
|
||||||
html = import ../nixite/html.nix;
|
html = import ../nixite/html.nix;
|
||||||
it = import ./it.nix;
|
it = import ./it.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 attr info in the tag" (let p = tag "p" { class = ""; };
|
||||||
|
in {
|
||||||
|
actual = p.attrs;
|
||||||
|
expected = { class = ""; };
|
||||||
|
}))
|
||||||
|
|
||||||
(it "makes a p tag" {
|
(it "makes a p tag" {
|
||||||
actual = tag "p" { } "Hello";
|
actual = tag "p" { } "Hello";
|
||||||
expected = {
|
expected = {
|
||||||
|
|
5
testing/run.nix
Normal file
5
testing/run.nix
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
pkgs:
|
||||||
|
let test = import ./import.nix;
|
||||||
|
in files:
|
||||||
|
(pkgs.writeShellScriptBin "test"
|
||||||
|
(builtins.concatStringsSep "\n" (map test files)))
|
|
@ -3,55 +3,61 @@ let
|
||||||
html = import ../nixite/html.nix;
|
html = import ../nixite/html.nix;
|
||||||
it = import ./it.nix;
|
it = import ./it.nix;
|
||||||
|
|
||||||
p = style.styled "generic" "p" {
|
my = (style.styled "div" "div" {
|
||||||
foo = "bar";
|
class = [ "something" ];
|
||||||
forgetme = "nothing";
|
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:
|
||||||
|
assert builtins.isList child;
|
||||||
|
(map (html.tag "li" { }) child);
|
||||||
|
});
|
||||||
|
in [
|
||||||
|
|
||||||
my = (style.styled "p" "p" { style = { some-style = "some value"; }; })
|
(it "makes a p component" (let
|
||||||
(style.styled "classless" "div" { class = [ ]; })
|
my = (style.styled "para" "p" { style = { some-style = "some value"; }; });
|
||||||
(style.styled "quote" p.generic {
|
in {
|
||||||
|
expected = html.tag "p" { class = [ "para" ]; } "yes";
|
||||||
|
actual = my.para { } "yes";
|
||||||
|
asString = true;
|
||||||
|
}))
|
||||||
|
|
||||||
|
(it "extends existing components" (let
|
||||||
|
my = (style.styled "generic" "p" {
|
||||||
|
foo = "bar";
|
||||||
|
forgetme = "nothing";
|
||||||
|
});
|
||||||
|
this = (style.styled "quote" my.generic {
|
||||||
baz = "baz";
|
baz = "baz";
|
||||||
forgetme = "forgotten";
|
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:
|
|
||||||
assert builtins.isList child;
|
|
||||||
(map (html.tag "li" { }) child);
|
|
||||||
});
|
});
|
||||||
in [
|
in {
|
||||||
(it "extends existing components" {
|
|
||||||
expected = html.tag "p" {
|
expected = html.tag "p" {
|
||||||
forgetme = "forgotten";
|
forgetme = "forgotten";
|
||||||
baz = "baz";
|
baz = "baz";
|
||||||
foo = "bar";
|
foo = "bar";
|
||||||
class = [ "generic" "quote" ];
|
class = [ "generic" "quote" ];
|
||||||
} "yes";
|
} "yes";
|
||||||
actual = my.quote { } "yes";
|
actual = this.quote { } "yes";
|
||||||
asString = true;
|
asString = true;
|
||||||
})
|
}))
|
||||||
(it "makes a p component" {
|
|
||||||
expected = html.tag "p" { class = [ "p" ]; } "yes";
|
(it "makes a component with no class"
|
||||||
actual = my.p { } "yes";
|
(let my = (style.styled "classless" "div" { class = [ ]; });
|
||||||
asString = true;
|
in {
|
||||||
})
|
expected = html.tag "div" { class = [ ]; } "yes";
|
||||||
(it "makes a component with no class" {
|
actual = my.classless { } "yes";
|
||||||
expected = html.tag "div" { class = [ ]; } "yes";
|
asString = true;
|
||||||
actual = my.classless { } "yes";
|
}))
|
||||||
asString = true;
|
|
||||||
})
|
|
||||||
(it "does not error without attrs" {
|
(it "does not error without attrs" {
|
||||||
expected = html.tag "p" { class = [ "p" ]; } "yes";
|
expected = html.tag "div" { class = [ "div" "something" ]; } "yes";
|
||||||
actual = my.p "yes";
|
actual = my.div "yes";
|
||||||
asString = true;
|
asString = true;
|
||||||
})
|
})
|
||||||
(it "makes a component" {
|
(it "makes a component" {
|
||||||
|
@ -88,24 +94,46 @@ in [
|
||||||
actual = my.div { id = "foo"; } "foobar";
|
actual = my.div { id = "foo"; } "foobar";
|
||||||
asString = true;
|
asString = true;
|
||||||
})
|
})
|
||||||
(it "makes a style" {
|
(it "makes a style"
|
||||||
expected = ''
|
(let my = (style.styled "para" "p" { style = { foo = "bar"; }; });
|
||||||
p.p {
|
in {
|
||||||
some-style: some value;
|
expected = { "p.para" = { foo = "bar"; }; };
|
||||||
}
|
actual = removeAttrs my.style [ "__toString" ];
|
||||||
div.something {
|
}))
|
||||||
this: that;
|
|
||||||
}
|
(it "retains tag"
|
||||||
div.something#s {
|
(let p = (style.styled "para" "p" { style = { foo = "bar"; }; });
|
||||||
s: yes;
|
in {
|
||||||
}
|
expected = "p";
|
||||||
div.foo.bar {
|
actual = p.para.tag;
|
||||||
something: something;
|
}))
|
||||||
}
|
|
||||||
body {
|
(it "retains attrs"
|
||||||
foo: bar;
|
(let p = (style.styled "para" "p" { style = { foo = "bar"; }; });
|
||||||
}
|
in {
|
||||||
'';
|
expected = { foo = "bar"; };
|
||||||
actual = my.style;
|
actual = p.para.attrs.style;
|
||||||
})
|
}))
|
||||||
|
|
||||||
|
(it "retains class" (let p = (style.styled "para" "p" { });
|
||||||
|
in {
|
||||||
|
expected = [ "para" ];
|
||||||
|
actual = p.para.attrs.class;
|
||||||
|
}))
|
||||||
|
|
||||||
|
(it "merges styles" (let
|
||||||
|
p = (style.styled "para" "p" { style = { foo = "bar"; }; });
|
||||||
|
d = (style.styled "para2" p.para { style = { baz = "bar"; }; });
|
||||||
|
my = p d;
|
||||||
|
in {
|
||||||
|
expected = {
|
||||||
|
"p.para" = { foo = "bar"; };
|
||||||
|
"p.para2.para" = {
|
||||||
|
foo = "bar";
|
||||||
|
baz = "bar";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
actual = removeAttrs my.style [ "__toString" ];
|
||||||
|
}))
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in a new issue