merge styles with attrs in styled components

This commit is contained in:
tristan 2023-12-31 17:51:21 +00:00
parent 234c629e66
commit a7c1a1c7de
7 changed files with 68 additions and 39 deletions

View file

@ -35,7 +35,7 @@
}) })
); );
serve = self.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;

View file

@ -2,20 +2,20 @@ let
html = import ./html.nix; html = import ./html.nix;
s = import ./style.nix; s = import ./style.nix;
in in
(s.styled "p" "p" {} {}) (s.styled "p" "p" {})
(s.styled "div" "div" {} {}) (s.styled "div" "div" {})
(s.styled "section" "section" {} {}) (s.styled "section" "section" {})
(s.styled "span" "span" {} {}) (s.styled "span" "span" {})
(s.styled "main" "main" {} {}) (s.styled "main" "main" {})
(s.styled "article" "article" {} {}) (s.styled "article" "article" {})
(s.styled "title" "title" {class = [];} {}) (s.styled "title" "title" {class = [];})
(s.styled "h1" "h1" {} {}) (s.styled "h1" "h1" {})
(s.styled "h2" "h2" {} {}) (s.styled "h2" "h2" {})
(s.styled "h3" "h3" {} {}) (s.styled "h3" "h3" {})
(s.styled "list" "ul" { (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;
@ -26,7 +26,7 @@ in
]; ];
lang = "en"; lang = "en";
class = []; class = [];
} {}) })
// { // {
h = v: child: h = v: child:
html.tag "h${toString v}" {} child; html.tag "h${toString v}" {} child;

View file

@ -1,5 +1,8 @@
let let
keyvalue = key: value: ''${key}="${toString value}"''; keyvalue = key: value:
assert builtins.isString key;
if value == "" || value == [] || value == {} then "" else
''${key}="${toString value}"'';
in rec { in rec {
toHTML = elem: toHTML = elem:
if builtins.typeOf elem == "string" if builtins.typeOf elem == "string"
@ -9,15 +12,16 @@ in rec {
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.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 keyvalue key (baseNameOf value) then keyvalue key (baseNameOf value)
else if (builtins.substring 0 2 key) == "__" else
if (builtins.substring 0 2 key) == "__"
then "" then ""
else keyvalue key value) else keyvalue key value)
attrs attrs
)); )));
tag = tag: attrs: child: { tag = tag: attrs: child: {
inherit tag attrs child; inherit tag attrs child;

View file

@ -36,18 +36,18 @@ let
) )
+ id; + id;
in { in {
styled = name: tag: cprops: styles: let styled = name: tag: cprops: let
custom = cprops.__child or (child: child); custom = cprops.__child or (child: child);
in in
{ {
${name} = props: ${name} = props:
if builtins.isAttrs props if builtins.isAttrs props
then (child: (html.tag tag (props // {class = [name];} // cprops) (custom child))) then (child: (html.tag tag (props // {class = [name];} // cprops // {style = "";}) (custom child)))
else if builtins.isString props || builtins.isList props else if builtins.isString props || builtins.isList props
then (html.tag tag ({class = [name];} // cprops) (custom props)) then (html.tag tag ({class = [name];} // cprops // {style = "";}) (custom props))
else throw "Call element with attributes and child."; else throw "Call element with attributes and child.";
style = mkStyle (mkIdentifier name tag cprops) styles; style = mkStyle (mkIdentifier name tag cprops) ( cprops.style or {} );
} }
// join; // join;

View file

@ -7,38 +7,47 @@ in
(it "makes a p tag" { (it "makes a p tag" {
expected = html.tag "p" {class = ["p"];} "foobar"; expected = html.tag "p" {class = ["p"];} "foobar";
actual = p {} "foobar"; actual = p {} "foobar";
asString = true;
}) })
(it "makes a div tag" { (it "makes a div tag" {
expected = html.tag "div" {class = ["div"];} "foobar"; expected = html.tag "div" {class = ["div"];} "foobar";
actual = div {} "foobar"; actual = div {} "foobar";
asString = true;
}) })
(it "makes a section tag" { (it "makes a section tag" {
expected = html.tag "section" {class = ["section"];} "foobar"; expected = html.tag "section" {class = ["section"];} "foobar";
actual = section {} "foobar"; actual = section {} "foobar";
asString = true;
}) })
(it "makes a span tag" { (it "makes a span tag" {
expected = html.tag "span" {class = ["span"];} "foobar"; expected = html.tag "span" {class = ["span"];} "foobar";
actual = span {} "foobar"; actual = span {} "foobar";
asString = true;
}) })
(it "makes a main tag" { (it "makes a main tag" {
expected = html.tag "main" {class = ["main"];} ["yeet"]; expected = html.tag "main" {class = ["main"];} ["yeet"];
actual = main {} ["yeet"]; actual = main {} ["yeet"];
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;
}) })
(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;
}) })
(it "makes a title tag" { (it "makes a title tag" {
expected = html.tag "title" {class = [];} "foobar"; expected = html.tag "title" {class = [];} "foobar";
actual = title {} "foobar"; actual = title {} "foobar";
asString = true;
}) })
(it "makes an a tag" { (it "makes an a tag" {
expected = html.tag "a" {href = "https://example.com";} "example"; expected = html.tag "a" {href = "https://example.com";} "example";
actual = link "https://example.com" "example"; actual = link "https://example.com" "example";
asString = true;
}) })
(it "makes a stylesheet link" { (it "makes a stylesheet link" {
expected = html.tag "link" { expected = html.tag "link" {
@ -46,9 +55,10 @@ in
rel = "stylesheet"; rel = "stylesheet";
} ""; } "";
actual = stylesheet "/style"; actual = stylesheet "/style";
asString = true;
}) })
(it "makes a list" { (it "makes a list" {
expected = toString (html.tag "ul" { expected = (html.tag "ul" {
__ = ""; __ = "";
class = ["list"]; class = ["list"];
} [ } [
@ -56,10 +66,11 @@ in
(html.tag "li" {} "bar") (html.tag "li" {} "bar")
(html.tag "li" {} "baz") (html.tag "li" {} "baz")
]); ]);
actual = toString (list {} ["foo" "bar" "baz"]); actual = (list {} ["foo" "bar" "baz"]);
asString = true;
}) })
(it "makes an html doc" { (it "makes an html doc" {
expected = toString (html.tag "html" { expected = (html.tag "html" {
__child = ""; __child = "";
class = []; class = [];
lang = "en"; lang = "en";
@ -67,6 +78,7 @@ in
(html.tag "head" {} ["foo"]) (html.tag "head" {} ["foo"])
(html.tag "body" {} "bar") (html.tag "body" {} "bar")
]); ]);
actual = toString (doc {} [["foo"] "bar"]); actual = (doc {} [["foo"] "bar"]);
asString = true;
}) })
] ]

View file

@ -1,8 +1,11 @@
msg: { msg: {
actual, actual,
expected, expected,
asString ? false,
}: }:
if actual == expected if (
if asString then toString actual == toString expected
else actual == expected )
then '' then ''
echo 'it ${msg}' echo 'it ${msg}'
'' ''

View file

@ -4,40 +4,46 @@ let
it = import ./it.nix; it = import ./it.nix;
my = my =
(style.styled "p" "p" {} { (style.styled "p" "p" {style = {
some-style = "some value"; some-style = "some value";
}) };})
(style.styled "div" "div" {class = ["something"];} { (style.styled "div" "div" {class = ["something"]; style = {
this = "that"; this = "that";
}) };})
(style.styled "s" "div" { (style.styled "s" "div" {
id = "s"; id = "s";
class = ["something"]; class = ["something"];
} { style = {
s = "yes"; s = "yes";
}) };})
(style.styled "foobar" "div" {class = ["foo" "bar"];} { (style.styled "foobar" "div" {
class = ["foo" "bar"];
style = {
something = "something"; something = "something";
}) };
} )
(style.style "body" { (style.style "body" {
foo = "bar"; 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 "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 "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;
}) })
(it "makes a component" { (it "makes a component" {
expected = html.tag "div" {class = ["something"];} "foobar"; expected = html.tag "div" {class = ["something"];} "foobar";
actual = my.div {} "foobar"; actual = my.div {} "foobar";
asString = true;
}) })
(it "makes special components" { (it "makes special components" {
expected = html.tag "div" { expected = html.tag "div" {
@ -45,20 +51,23 @@ in [
class = ["something"]; class = ["something"];
} "foobar"; } "foobar";
actual = my.s {} "foobar"; actual = my.s {} "foobar";
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 = ["foo" "bar"];} "foobar";
actual = my.foobar {} "foobar"; actual = my.foobar {} "foobar";
asString = true;
}) })
(it "does custom behavour" { (it "does custom behavour" {
expected = toString (html.tag "ul" { expected = (html.tag "ul" {
__ = ""; __ = "";
class = ["list"]; class = ["list"];
} [ } [
(html.tag "li" {} "1") (html.tag "li" {} "1")
(html.tag "li" {} "2") (html.tag "li" {} "2")
]); ]);
actual = toString (my.list {} ["1" "2"]); actual = (my.list {} ["1" "2"]);
asString = true;
}) })
(it "combines attrs" { (it "combines attrs" {
expected = html.tag "div" { expected = html.tag "div" {
@ -66,6 +75,7 @@ in [
class = ["something"]; class = ["something"];
} "foobar"; } "foobar";
actual = my.div {id = "foo";} "foobar"; actual = my.div {id = "foo";} "foobar";
asString = true;
}) })
(it "makes a style" { (it "makes a style" {
expected = '' expected = ''