`
hgroup.attrs = mkOption {
type = with types; nullOr (submodule { options = global-attrs; });
default = with lib; mkIf (!isNull config.before || !isNull config.after) { };
};
# https://html.spec.whatwg.org/multipage/sections.html#the-hgroup-element
before = mkOption {
type = with types; listOf (attrTag ({ inherit (element-types) p; } // categories.scripting));
default = [ ];
};
content = mkOption {
# https://html.spec.whatwg.org/multipage/sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements
type = with types; either str (listOf (attrTag categories.phrasing));
};
after = mkOption {
type = with types;
listOf (attrTag ({ inherit (element-types) p; } // categories.scripting));
default = [ ];
};
};
});
};
# https://html.spec.whatwg.org/multipage/sections.html#headings-and-outlines
content = mkOption {
type = with types; listOf (either str (attrTag categories.flow));
default = [ ];
};
};
options.heading-level = mkOption {
# XXX: this will proudly fail if the invariant is violated,
# but the error message will be inscrutable
type = with types; ints.between 1 6;
internal = true;
};
config = {
categories = [ "flow" "sectioning" "palpable" ];
__toString = self: with lib;
let
n = toString config.heading-level;
heading = ''${self.heading.content}'';
hgroup = with lib; print-element "hgroup" self.heading.hgroup.attrs (squash ''
${optionalString (!isNull self.heading.before) (toString-unwrap self.heading.before)}
${heading}
${optionalString (!isNull self.heading.after) (toString-unwrap self.heading.after)}
'');
content = if isNull self.heading.hgroup.attrs then heading else hgroup
+ join "\n" (map toString-unwrap self.content);
in
if !isNull self.attrs
then print-element name self.attrs content
else content;
};
};
p = { name, ... }: {
imports = [ element ];
options = {
attrs = mkAttrs { };
content = mkOption {
type = with types; either str (listOf (attrTag categories.phrasing));
};
};
config.categories = [ "flow" "palpable" ];
config.__toString = self: print-element name self.attrs (toString self.content);
};
dl = { config, name, ... }: {
imports = [ element ];
options = {
attrs = mkAttrs { };
content = mkOption {
type = with types; listOf (submodule ({ ... }: {
options = {
# TODO: wrap in `` if set
div.attrs = mkOption {
type = with types; nullOr (submodule { options = global-attrs; });
default = null;
};
before = mkOption {
type = with types; listOf (attrTag categories.scripting);
default = [ ];
};
terms = mkOption {
type = with types; nonEmptyListOf (submodule dt);
};
between = mkOption {
type = with types; listOf (attrTag categories.scripting);
default = [ ];
};
descriptions = mkOption {
type = with types; nonEmptyListOf (submodule dd);
};
after = mkOption {
type = with types; listOf (attrTag categories.scripting);
default = [ ];
};
};
}));
};
};
config.categories = [ "flow" ] ++ [ "palpable" ];
config.__toString = self:
with lib;
let
content = map
(entry:
let
list = squash ''
${join "\n" entry.before}
${join "\n" entry.terms}
${join "\n" entry.between}
${join "\n" entry.descriptions}
${join "\n" entry.after}
'';
in
if !isNull entry.div.attrs
then print-element "div" entry.div.attrs list
else list
)
self.content;
in
print-element name self.attrs (join "\n" content);
};
dt = { config, ... }: {
imports = [ element ];
options = {
attrs = mkAttrs { };
dt = mkOption {
type = with types; either str (submodule (attrTag (
# TODO: test
with lib; removeAttrs
(filterAttrs
(name: value: ! any (c: elem c [ "sectioning" "heading" ]) value.categories)
categories.flow
)
[ "header" "footer" ]
)));
};
};
config.categories = [ ];
config.__toString = self: print-element "dt" self.attrs self.dt;
};
dd = { config, ... }: {
imports = [ element ];
options = {
attrs = mkAttrs { };
dd = mkOption {
type = with types; either str (submodule (attrTag categories.flow));
};
};
config.categories = [ ];
config.__toString = self: print-element "dd" self.attrs self.dd;
};
};
in
{
imports = [ element ];
options = {
inherit (element-types) html;
};
config.categories = [ ];
config.__toString = self: ''
${self.html}
'';
}