forked from Fediversity/fediversity.eu
implement stylesheet links
This commit is contained in:
parent
1934b90686
commit
955409b71d
|
@ -69,6 +69,7 @@ let
|
||||||
default = false;
|
default = false;
|
||||||
};
|
};
|
||||||
id = {
|
id = {
|
||||||
|
# TODO: would be cool if we could enforce unique IDs per document
|
||||||
type = with types; nullOr nonEmptyStr;
|
type = with types; nullOr nonEmptyStr;
|
||||||
default = null;
|
default = null;
|
||||||
};
|
};
|
||||||
|
@ -92,7 +93,35 @@ let
|
||||||
# https://html.spec.whatwg.org/multipage/microdata.html#encoding-microdata
|
# https://html.spec.whatwg.org/multipage/microdata.html#encoding-microdata
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# all possible attributes to `<link>` elements.
|
||||||
|
# since not all of them apply to each `rel=` type, the separate implementations can pick from this collection
|
||||||
|
link-attrs = lib.mapAttrs (name: value: mkOption value) {
|
||||||
|
href = {
|
||||||
|
# TODO: implement https://html.spec.whatwg.org/multipage/semantics.html#the-link-element:attr-link-href-3
|
||||||
|
# TODO: https://url.spec.whatwg.org/#valid-url-string
|
||||||
|
type = types.nonEmptyStr;
|
||||||
|
};
|
||||||
|
media = {
|
||||||
|
# TODO: https://drafts.csswg.org/mediaqueries/#media
|
||||||
|
# it's awsome we have that standard, but ugh so much work
|
||||||
|
# ;..S
|
||||||
|
# Clay seems to do it right: https://github.com/sebastiaanvisser/clay
|
||||||
|
type = with types; nullOr str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
integrity = {
|
||||||
|
# TODO: implement https://w3c.github.io/webappsec-subresource-integrity/
|
||||||
|
type = with types; nullOr str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
# TODO: more attributes
|
||||||
|
# https://html.spec.whatwg.org/multipage/semantics.html#the-link-element:concept-element-attributes
|
||||||
|
};
|
||||||
|
|
||||||
|
# TODO: not sure where to put these, since so far they apply to multiple elements,
|
||||||
|
# but have the same properties for all of them
|
||||||
attrs = lib.mapAttrs (name: value: mkOption value) {
|
attrs = lib.mapAttrs (name: value: mkOption value) {
|
||||||
|
# TODO: investigate: `href` may be coupled with other attributes such as `target` or `hreflang`, this could simplify things
|
||||||
href = {
|
href = {
|
||||||
# TODO: https://url.spec.whatwg.org/#valid-url-string
|
# TODO: https://url.spec.whatwg.org/#valid-url-string
|
||||||
# ;..O
|
# ;..O
|
||||||
|
@ -156,6 +185,8 @@ let
|
||||||
</${name}>
|
</${name}>
|
||||||
'');
|
'');
|
||||||
|
|
||||||
|
print-element' = name: attrs: "<${name}${print-attrs attrs}>";
|
||||||
|
|
||||||
toString-unwrap = e:
|
toString-unwrap = e:
|
||||||
with lib;
|
with lib;
|
||||||
if isAttrs e
|
if isAttrs e
|
||||||
|
@ -270,10 +301,16 @@ let
|
||||||
type = with types; nullOr str;
|
type = with types; nullOr str;
|
||||||
default = null;
|
default = null;
|
||||||
};
|
};
|
||||||
|
# TODO: this one has more internal structure, e.g with hreflang
|
||||||
|
# TODO: print in output
|
||||||
link.canonical = mkOption {
|
link.canonical = mkOption {
|
||||||
type = with types; nullOr str;
|
type = with types; nullOr str;
|
||||||
default = null;
|
default = null;
|
||||||
};
|
};
|
||||||
|
link.stylesheets = mkOption {
|
||||||
|
type = types.listOf (submodule stylesheet);
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
|
||||||
# TODO: figure out `meta` elements
|
# TODO: figure out `meta` elements
|
||||||
# https://html.spec.whatwg.org/multipage/semantics.html#the-meta-element:concept-element-attributes
|
# https://html.spec.whatwg.org/multipage/semantics.html#the-meta-element:concept-element-attributes
|
||||||
|
@ -291,14 +328,23 @@ let
|
||||||
${/* https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-x-ua-compatible */
|
${/* https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-x-ua-compatible */
|
||||||
""}<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
""}<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
|
||||||
<meta name="viewport" content="${join ", " (mapAttrsToList
|
${print-element' "meta" {
|
||||||
(name: value: "${name}=${toString value}") self.meta.viewport)
|
name = "viewport";
|
||||||
}" />
|
content = "${join ", " (mapAttrsToList (name: value: "${name}=${toString value}") self.meta.viewport) }";
|
||||||
|
}}
|
||||||
|
|
||||||
${join "\n" (map
|
${join "\n" (map
|
||||||
(author: ''<meta name="author" content="${author}" />'')
|
(author: print-element' "meta" {
|
||||||
|
name = "author";
|
||||||
|
content = "${author}";
|
||||||
|
})
|
||||||
self.meta.authors)
|
self.meta.authors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
${join "\n" (map
|
||||||
|
(stylesheet: print-element' "link" ({ rel = "stylesheet"; } // (removeAttrs stylesheet [ "categories" "__toString" ])))
|
||||||
|
self.link.stylesheets)
|
||||||
|
}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -350,7 +396,6 @@ let
|
||||||
"prev"
|
"prev"
|
||||||
"privacy-policy"
|
"privacy-policy"
|
||||||
"search"
|
"search"
|
||||||
"stylesheet"
|
|
||||||
"terms-of-service"
|
"terms-of-service"
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -362,6 +407,37 @@ let
|
||||||
config.__toString = self: "<link${print-attrs self}>";
|
config.__toString = self: "<link${print-attrs self}>";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# <link rel="stylesheet"> is implemented separately because it can be used both in `<head>` and `<body>`
|
||||||
|
# semantically it's a standalone thing but syntactically happens to be subsumed under `<link>`
|
||||||
|
stylesheet = { config, name, ... }: {
|
||||||
|
imports = [ element ];
|
||||||
|
options = global-attrs // {
|
||||||
|
type = mkOption {
|
||||||
|
# TODO: this must be a valid MIME type string, which is a bit involved.
|
||||||
|
# the syntax is explicated here: https://mimesniff.spec.whatwg.org/#mime-type-writing
|
||||||
|
# but the spec refers to RFC9110: https://www.rfc-editor.org/rfc/rfc9110#name-media-type
|
||||||
|
# all registered MIME types: https://www.iana.org/assignments/top-level-media-types/top-level-media-types.xhtml
|
||||||
|
# XXX: if nothing is specified, "text/css" is assumed.
|
||||||
|
# https://html.spec.whatwg.org/multipage/links.html#link-type-stylesheet:link-type-stylesheet-2
|
||||||
|
# there's no specification on what else could be there, and it's questionable whether setting anything else even makes sense.
|
||||||
|
# in practice, browsers seem to ignore anything but "text/css", so we may as well not care at all.
|
||||||
|
type = with types; nullOr str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
# https://html.spec.whatwg.org/multipage/semantics.html#attr-link-disabled
|
||||||
|
disabled = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
# TODO: implement the rest of the stylesheet attributes
|
||||||
|
# https://html.spec.whatwg.org/#link-type-stylesheet
|
||||||
|
inherit (link-attrs) href media integrity;
|
||||||
|
};
|
||||||
|
# https://html.spec.whatwg.org/multipage/links.html#link-type-stylesheet:body-ok
|
||||||
|
config.categories = [ "metadata" "phrasing" ];
|
||||||
|
config.__toString = self: print-attrs (removeAttrs self [ "categories" "__toString" ]);
|
||||||
|
};
|
||||||
|
|
||||||
body = { config, name, ... }: {
|
body = { config, name, ... }: {
|
||||||
imports = [ element ];
|
imports = [ element ];
|
||||||
options = {
|
options = {
|
||||||
|
|
Reference in a new issue