feat(sterni/nix/html): flatten lists enclosed by an element

Currently nix/html requires that the content of an element is either an
HTML string (which may or may not be generated by the library) or a flat
list of HTML strings (which may or may not be generated by the library).

I've found that this requirement makes authoring more complex pages that
have programmatically generated parts cumbersome since one needs to take
care that returned lists are appended, not included as an element. This
leads to confusing code and annoying errors. We don't really care about
the nesting of a content list as long as the order is clear, so we can
just flatten the list making life a little easier:

    (<main> { } [
      (<section> { } (<h2> { } "static section"))
      listOfGeneratedSections
      (<section> { } (<h2> { } "another section"))
    ])

Change-Id: I06016a8eff01d34d7eaea7798a00ed191115f9c8
Reviewed-on: https://cl.tvl.fyi/c/depot/+/12908
Reviewed-by: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
Autosubmit: sterni <sternenseemann@systemli.org>
This commit is contained in:
sterni 2024-12-25 01:07:14 +01:00 committed by clbot
parent 8b9e4badf0
commit 3bd43e39dd
2 changed files with 15 additions and 3 deletions

View file

@ -29,7 +29,7 @@ let
If the content argument is `null`, the tag will have no children nor a
closing element. If the content argument is a string it is used as the
content as is (unescaped). If the content argument is a list, its
elements are concatenated.
elements are concatenated (recursively if necessary).
`renderTag` is only an internal function which is reexposed as `__findFile`
to allow for much neater syntax than calling `renderTag` everywhere:
@ -95,7 +95,7 @@ let
);
content' =
if builtins.isList content
then builtins.concatStringsSep "" content
then builtins.concatStringsSep "" (flatten content)
else content;
in
if content == null
@ -113,6 +113,12 @@ let
*/
withDoctype = doc: "<!DOCTYPE html>" + doc;
/* Taken from <nixpkgs/lib/lists.nix>. */
flatten = x:
if builtins.isList x
then builtins.concatMap (y: flatten y) x
else [ x ];
in
{
inherit escapeMinimal renderTag withDoctype;

View file

@ -34,7 +34,13 @@ let
(<h1> { } (esc "html.nix"))
(<h2> { } [
(<em> { } "the")
(esc " most cursed HTML DSL ever!")
# test flattening
[
(esc " ")
(esc "most")
[ (esc " cursed ") ]
(esc "HTML DSL ever!")
]
])
])
(<dl> { } [