@siteimprove/alfa-dom 0.89.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +291 -0
- package/dist/h.d.ts +37 -0
- package/dist/h.js +214 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +32 -0
- package/dist/jsx-runtime.d.ts +26 -0
- package/dist/jsx-runtime.js +41 -0
- package/dist/jsx.d.ts +44 -0
- package/dist/jsx.js +45 -0
- package/dist/namespace.d.ts +43 -0
- package/dist/namespace.js +57 -0
- package/dist/native.d.ts +18 -0
- package/dist/native.js +449 -0
- package/dist/node/attribute/predicate/has-name.d.ts +11 -0
- package/dist/node/attribute/predicate/has-name.js +13 -0
- package/dist/node/attribute/predicate.d.ts +2 -0
- package/dist/node/attribute/predicate.js +2 -0
- package/dist/node/attribute.d.ts +90 -0
- package/dist/node/attribute.js +164 -0
- package/dist/node/comment.d.ts +42 -0
- package/dist/node/comment.js +74 -0
- package/dist/node/document.d.ts +59 -0
- package/dist/node/document.js +113 -0
- package/dist/node/element/input-type.d.ts +12 -0
- package/dist/node/element/input-type.js +10 -0
- package/dist/node/element/predicate/has-attribute.d.ts +12 -0
- package/dist/node/element/predicate/has-attribute.js +11 -0
- package/dist/node/element/predicate/has-box.d.ts +9 -0
- package/dist/node/element/predicate/has-box.js +7 -0
- package/dist/node/element/predicate/has-display-size.d.ts +7 -0
- package/dist/node/element/predicate/has-display-size.js +28 -0
- package/dist/node/element/predicate/has-id.d.ts +16 -0
- package/dist/node/element/predicate/has-id.js +17 -0
- package/dist/node/element/predicate/has-input-type.d.ts +12 -0
- package/dist/node/element/predicate/has-input-type.js +17 -0
- package/dist/node/element/predicate/has-name.d.ts +11 -0
- package/dist/node/element/predicate/has-name.js +13 -0
- package/dist/node/element/predicate/has-namespace.d.ts +12 -0
- package/dist/node/element/predicate/has-namespace.js +13 -0
- package/dist/node/element/predicate/has-tab-index.d.ts +12 -0
- package/dist/node/element/predicate/has-tab-index.js +11 -0
- package/dist/node/element/predicate/has-unique-id.d.ts +7 -0
- package/dist/node/element/predicate/has-unique-id.js +31 -0
- package/dist/node/element/predicate/is-actually-disabled.d.ts +8 -0
- package/dist/node/element/predicate/is-actually-disabled.js +47 -0
- package/dist/node/element/predicate/is-browsing-context-container.d.ts +8 -0
- package/dist/node/element/predicate/is-browsing-context-container.js +20 -0
- package/dist/node/element/predicate/is-content.d.ts +10 -0
- package/dist/node/element/predicate/is-content.js +17 -0
- package/dist/node/element/predicate/is-document-element.d.ts +6 -0
- package/dist/node/element/predicate/is-document-element.js +13 -0
- package/dist/node/element/predicate/is-draggable.d.ts +8 -0
- package/dist/node/element/predicate/is-draggable.js +28 -0
- package/dist/node/element/predicate/is-editing-host.d.ts +8 -0
- package/dist/node/element/predicate/is-editing-host.js +20 -0
- package/dist/node/element/predicate/is-fallback.d.ts +15 -0
- package/dist/node/element/predicate/is-fallback.js +28 -0
- package/dist/node/element/predicate/is-replaced.d.ts +8 -0
- package/dist/node/element/predicate/is-replaced.js +17 -0
- package/dist/node/element/predicate/is-scoped-to.d.ts +7 -0
- package/dist/node/element/predicate/is-scoped-to.js +11 -0
- package/dist/node/element/predicate/is-suggested-focusable.d.ts +14 -0
- package/dist/node/element/predicate/is-suggested-focusable.js +47 -0
- package/dist/node/element/predicate.d.ts +20 -0
- package/dist/node/element/predicate.js +20 -0
- package/dist/node/element.d.ts +122 -0
- package/dist/node/element.js +330 -0
- package/dist/node/fragment.d.ts +38 -0
- package/dist/node/fragment.js +68 -0
- package/dist/node/predicate/has-child.d.ts +7 -0
- package/dist/node/predicate/has-child.js +8 -0
- package/dist/node/predicate/has-descendant.d.ts +7 -0
- package/dist/node/predicate/has-descendant.js +8 -0
- package/dist/node/predicate/has-inclusive-descendant.d.ts +7 -0
- package/dist/node/predicate/has-inclusive-descendant.js +8 -0
- package/dist/node/predicate/has-text-content.d.ts +7 -0
- package/dist/node/predicate/has-text-content.js +12 -0
- package/dist/node/predicate/is-root.d.ts +7 -0
- package/dist/node/predicate/is-root.js +7 -0
- package/dist/node/predicate.d.ts +6 -0
- package/dist/node/predicate.js +6 -0
- package/dist/node/query/element-descendants.d.ts +8 -0
- package/dist/node/query/element-descendants.js +17 -0
- package/dist/node/query/element-id-map.d.ts +14 -0
- package/dist/node/query/element-id-map.js +30 -0
- package/dist/node/query/inclusive-element-descendants.d.ts +8 -0
- package/dist/node/query/inclusive-element-descendants.js +10 -0
- package/dist/node/query/index.d.ts +12 -0
- package/dist/node/query/index.js +13 -0
- package/dist/node/shadow.d.ts +66 -0
- package/dist/node/shadow.js +128 -0
- package/dist/node/slot.d.ts +29 -0
- package/dist/node/slot.js +41 -0
- package/dist/node/slotable.d.ts +29 -0
- package/dist/node/slotable.js +40 -0
- package/dist/node/text.d.ts +46 -0
- package/dist/node/text.js +83 -0
- package/dist/node/traversal/get-nodes-between.d.ts +24 -0
- package/dist/node/traversal/get-nodes-between.js +62 -0
- package/dist/node/traversal/lowest-common-ancestor.d.ts +13 -0
- package/dist/node/traversal/lowest-common-ancestor.js +19 -0
- package/dist/node/traversal.d.ts +2 -0
- package/dist/node/traversal.js +2 -0
- package/dist/node/type.d.ts +45 -0
- package/dist/node/type.js +74 -0
- package/dist/node.d.ts +263 -0
- package/dist/node.js +325 -0
- package/dist/style/block.d.ts +30 -0
- package/dist/style/block.js +63 -0
- package/dist/style/declaration.d.ts +65 -0
- package/dist/style/declaration.js +103 -0
- package/dist/style/rule/condition.d.ts +21 -0
- package/dist/style/rule/condition.js +30 -0
- package/dist/style/rule/font-face.d.ts +29 -0
- package/dist/style/rule/font-face.js +47 -0
- package/dist/style/rule/grouping.d.ts +22 -0
- package/dist/style/rule/grouping.js +34 -0
- package/dist/style/rule/import.d.ts +47 -0
- package/dist/style/rule/import.js +114 -0
- package/dist/style/rule/keyframe.d.ts +32 -0
- package/dist/style/rule/keyframe.js +53 -0
- package/dist/style/rule/keyframes.d.ts +28 -0
- package/dist/style/rule/keyframes.js +49 -0
- package/dist/style/rule/layer.d.ts +61 -0
- package/dist/style/rule/layer.js +106 -0
- package/dist/style/rule/media.d.ts +32 -0
- package/dist/style/rule/media.js +54 -0
- package/dist/style/rule/namespace.d.ts +31 -0
- package/dist/style/rule/namespace.js +52 -0
- package/dist/style/rule/page.d.ts +32 -0
- package/dist/style/rule/page.js +53 -0
- package/dist/style/rule/style.d.ts +35 -0
- package/dist/style/rule/style.js +62 -0
- package/dist/style/rule/supports.d.ts +32 -0
- package/dist/style/rule/supports.js +56 -0
- package/dist/style/rule.d.ts +60 -0
- package/dist/style/rule.js +109 -0
- package/dist/style/sheet.d.ts +37 -0
- package/dist/style/sheet.js +66 -0
- package/package.json +69 -0
package/dist/jsx.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Element, Node } from "./index.js";
|
|
2
|
+
import type * as dom from "./index.js";
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export declare function jsx<N extends string = string>(name: N, properties?: jsx.Properties | null, ...children: jsx.Children): Element<N>;
|
|
7
|
+
/**
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export declare namespace jsx {
|
|
11
|
+
type Child = Node | string;
|
|
12
|
+
/**
|
|
13
|
+
* @remarks
|
|
14
|
+
* This type is declared using the short array syntax (`[]`) to avoid issues
|
|
15
|
+
* with circular generic references.
|
|
16
|
+
*/
|
|
17
|
+
type Children = (Child | Children)[];
|
|
18
|
+
interface Properties {
|
|
19
|
+
[name: string]: unknown;
|
|
20
|
+
/**
|
|
21
|
+
* An optional record of CSS property names and their associated values.
|
|
22
|
+
* This works similarly to the `style` property in React.
|
|
23
|
+
*
|
|
24
|
+
* {@link https://reactjs.org/docs/dom-elements.html#style}
|
|
25
|
+
*/
|
|
26
|
+
style?: Record<string, string>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* {@link https://www.typescriptlang.org/docs/handbook/jsx.html}
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* This namespace is currently needed to let the TypeScript compiler know the
|
|
33
|
+
* shape of elements returned by `jsx()` and the properties that tags allow.
|
|
34
|
+
* We should keep an eye on https://github.com/microsoft/TypeScript/issues/14729
|
|
35
|
+
* as it might provide an opportunity to get rid of this namespace entirely.
|
|
36
|
+
*/
|
|
37
|
+
namespace JSX {
|
|
38
|
+
type Element<N extends string = string> = dom.Element<N>;
|
|
39
|
+
interface IntrinsicElements {
|
|
40
|
+
[tag: string]: Properties;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=jsx.d.ts.map
|
package/dist/jsx.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { h } from "./h.js";
|
|
2
|
+
import { Rectangle } from "@siteimprove/alfa-rectangle";
|
|
3
|
+
const { entries } = Object;
|
|
4
|
+
/**
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export function jsx(name, properties = null, ...children) {
|
|
8
|
+
const attributes = {};
|
|
9
|
+
const style = {};
|
|
10
|
+
let box = undefined;
|
|
11
|
+
let device = undefined;
|
|
12
|
+
let externalId = undefined;
|
|
13
|
+
let serializationId = undefined;
|
|
14
|
+
for (const [name, value] of entries(properties ?? {})) {
|
|
15
|
+
if (value === null || value === undefined) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
switch (name) {
|
|
19
|
+
case "style":
|
|
20
|
+
for (const [propName, propValue] of entries(value)) {
|
|
21
|
+
style[propName] = propValue;
|
|
22
|
+
}
|
|
23
|
+
continue;
|
|
24
|
+
case "box":
|
|
25
|
+
const deviceAndBox = value;
|
|
26
|
+
box = Rectangle.from(deviceAndBox);
|
|
27
|
+
device = deviceAndBox.device;
|
|
28
|
+
continue;
|
|
29
|
+
case "externalId":
|
|
30
|
+
if (typeof value === "string") {
|
|
31
|
+
externalId = value;
|
|
32
|
+
}
|
|
33
|
+
continue;
|
|
34
|
+
case "serializationId":
|
|
35
|
+
if (typeof value === "string") {
|
|
36
|
+
serializationId = value;
|
|
37
|
+
}
|
|
38
|
+
continue;
|
|
39
|
+
default:
|
|
40
|
+
attributes[name] = value === true ? value : `${value}`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return h(name, attributes, children.flat(Infinity), style, box, device, externalId, serializationId);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=jsx.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {@link https://infra.spec.whatwg.org/#namespaces}
|
|
3
|
+
*
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export declare enum Namespace {
|
|
7
|
+
/**
|
|
8
|
+
* {@link https://infra.spec.whatwg.org/#html-namespace}
|
|
9
|
+
*/
|
|
10
|
+
HTML = "http://www.w3.org/1999/xhtml",
|
|
11
|
+
/**
|
|
12
|
+
* {@link https://infra.spec.whatwg.org/#mathml-namespace}
|
|
13
|
+
*/
|
|
14
|
+
MathML = "http://www.w3.org/1998/Math/MathML",
|
|
15
|
+
/**
|
|
16
|
+
* {@link https://infra.spec.whatwg.org/#svg-namespace}
|
|
17
|
+
*/
|
|
18
|
+
SVG = "http://www.w3.org/2000/svg",
|
|
19
|
+
/**
|
|
20
|
+
* {@link https://infra.spec.whatwg.org/#xlink-namespace}
|
|
21
|
+
*/
|
|
22
|
+
XLink = "http://www.w3.org/1999/xlink",
|
|
23
|
+
/**
|
|
24
|
+
* {@link https://infra.spec.whatwg.org/#xml-namespace}
|
|
25
|
+
*/
|
|
26
|
+
XML = "http://www.w3.org/XML/1998/namespace",
|
|
27
|
+
/**
|
|
28
|
+
* @remarks
|
|
29
|
+
* The trailing slash is not a typo! For some reason it snuck its way into the
|
|
30
|
+
* specification and whether or not it is strictly required is an awfully good
|
|
31
|
+
* question.
|
|
32
|
+
*
|
|
33
|
+
* {@link https://infra.spec.whatwg.org/#xmlns-namespace}
|
|
34
|
+
*/
|
|
35
|
+
XMLNS = "http://www.w3.org/2000/xmlns/"
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export declare namespace Namespace {
|
|
41
|
+
function isNamespace(value: string): value is Namespace;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=namespace.d.ts.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {@link https://infra.spec.whatwg.org/#namespaces}
|
|
3
|
+
*
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export var Namespace;
|
|
7
|
+
(function (Namespace) {
|
|
8
|
+
/**
|
|
9
|
+
* {@link https://infra.spec.whatwg.org/#html-namespace}
|
|
10
|
+
*/
|
|
11
|
+
Namespace["HTML"] = "http://www.w3.org/1999/xhtml";
|
|
12
|
+
/**
|
|
13
|
+
* {@link https://infra.spec.whatwg.org/#mathml-namespace}
|
|
14
|
+
*/
|
|
15
|
+
Namespace["MathML"] = "http://www.w3.org/1998/Math/MathML";
|
|
16
|
+
/**
|
|
17
|
+
* {@link https://infra.spec.whatwg.org/#svg-namespace}
|
|
18
|
+
*/
|
|
19
|
+
Namespace["SVG"] = "http://www.w3.org/2000/svg";
|
|
20
|
+
/**
|
|
21
|
+
* {@link https://infra.spec.whatwg.org/#xlink-namespace}
|
|
22
|
+
*/
|
|
23
|
+
Namespace["XLink"] = "http://www.w3.org/1999/xlink";
|
|
24
|
+
/**
|
|
25
|
+
* {@link https://infra.spec.whatwg.org/#xml-namespace}
|
|
26
|
+
*/
|
|
27
|
+
Namespace["XML"] = "http://www.w3.org/XML/1998/namespace";
|
|
28
|
+
/**
|
|
29
|
+
* @remarks
|
|
30
|
+
* The trailing slash is not a typo! For some reason it snuck its way into the
|
|
31
|
+
* specification and whether or not it is strictly required is an awfully good
|
|
32
|
+
* question.
|
|
33
|
+
*
|
|
34
|
+
* {@link https://infra.spec.whatwg.org/#xmlns-namespace}
|
|
35
|
+
*/
|
|
36
|
+
Namespace["XMLNS"] = "http://www.w3.org/2000/xmlns/";
|
|
37
|
+
})(Namespace || (Namespace = {}));
|
|
38
|
+
/**
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
(function (Namespace) {
|
|
42
|
+
function isNamespace(value) {
|
|
43
|
+
switch (value) {
|
|
44
|
+
case Namespace.HTML:
|
|
45
|
+
case Namespace.MathML:
|
|
46
|
+
case Namespace.SVG:
|
|
47
|
+
case Namespace.XLink:
|
|
48
|
+
case Namespace.XML:
|
|
49
|
+
case Namespace.XMLNS:
|
|
50
|
+
return true;
|
|
51
|
+
default:
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
Namespace.isNamespace = isNamespace;
|
|
56
|
+
})(Namespace || (Namespace = {}));
|
|
57
|
+
//# sourceMappingURL=namespace.js.map
|
package/dist/native.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Attribute, Comment, Document, Element, Node, Text, Type } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
export declare namespace Native {
|
|
6
|
+
function fromNode(node: globalThis.Element, options?: Options): Promise<Element.JSON>;
|
|
7
|
+
function fromNode(node: globalThis.Attr, options?: Options): Promise<Attribute.JSON>;
|
|
8
|
+
function fromNode(node: globalThis.Text, options?: Options): Promise<Text.JSON>;
|
|
9
|
+
function fromNode(node: globalThis.Comment, options?: Options): Promise<Comment.JSON>;
|
|
10
|
+
function fromNode(node: globalThis.Document, options?: Options): Promise<Document.JSON>;
|
|
11
|
+
function fromNode(node: globalThis.DocumentType, options?: Options): Promise<Type.JSON>;
|
|
12
|
+
function fromNode(node: globalThis.Node, options?: Options): Promise<Node.JSON>;
|
|
13
|
+
interface Options {
|
|
14
|
+
/** Whether to enforce anonymous CORS on <link> missing one */
|
|
15
|
+
withCrossOrigin?: boolean;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=native.d.ts.map
|
package/dist/native.js
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
/**
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
export var Native;
|
|
6
|
+
(function (Native) {
|
|
7
|
+
async function fromNode(node, options) {
|
|
8
|
+
const { withCrossOrigin = false } = options ?? {};
|
|
9
|
+
return toNode(node);
|
|
10
|
+
async function toNode(node) {
|
|
11
|
+
switch (node.nodeType) {
|
|
12
|
+
case node.ELEMENT_NODE:
|
|
13
|
+
return toElement(node);
|
|
14
|
+
case node.ATTRIBUTE_NODE:
|
|
15
|
+
return toAttribute(node);
|
|
16
|
+
case node.TEXT_NODE:
|
|
17
|
+
return toText(node);
|
|
18
|
+
case node.COMMENT_NODE:
|
|
19
|
+
return toComment(node);
|
|
20
|
+
case node.DOCUMENT_NODE:
|
|
21
|
+
return toDocument(node);
|
|
22
|
+
case node.DOCUMENT_TYPE_NODE:
|
|
23
|
+
return toType(node);
|
|
24
|
+
}
|
|
25
|
+
throw new Error(`Unsupported node of type: ${node.nodeType}`);
|
|
26
|
+
}
|
|
27
|
+
async function toElement(element) {
|
|
28
|
+
return {
|
|
29
|
+
type: "element",
|
|
30
|
+
namespace: element.namespaceURI,
|
|
31
|
+
prefix: element.prefix,
|
|
32
|
+
name: element.localName,
|
|
33
|
+
attributes: map(element.attributes, toAttribute),
|
|
34
|
+
style: "style" in element ? toBlock(element.style) : null,
|
|
35
|
+
children: await mapAsync(element.childNodes, toNode),
|
|
36
|
+
shadow: element.shadowRoot !== null
|
|
37
|
+
? await toShadow(element.shadowRoot)
|
|
38
|
+
: null,
|
|
39
|
+
content: "contentDocument" in element && element.contentDocument !== null
|
|
40
|
+
? await toDocument(element.contentDocument)
|
|
41
|
+
: null,
|
|
42
|
+
box: toRectangle(element.getBoundingClientRect()),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function toAttribute(attribute) {
|
|
46
|
+
return {
|
|
47
|
+
type: "attribute",
|
|
48
|
+
namespace: attribute.namespaceURI,
|
|
49
|
+
prefix: attribute.prefix,
|
|
50
|
+
name: attribute.localName,
|
|
51
|
+
value: attribute.value,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function toText(text) {
|
|
55
|
+
return {
|
|
56
|
+
type: "text",
|
|
57
|
+
data: text.data,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function toComment(comment) {
|
|
61
|
+
return {
|
|
62
|
+
type: "comment",
|
|
63
|
+
data: comment.data,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
async function toDocument(document) {
|
|
67
|
+
if (withCrossOrigin) {
|
|
68
|
+
await ensureCrossOrigin(document);
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
type: "document",
|
|
72
|
+
children: await mapAsync(document.childNodes, toNode),
|
|
73
|
+
style: getStyleSheets(document),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function toType(type) {
|
|
77
|
+
return {
|
|
78
|
+
type: "type",
|
|
79
|
+
name: type.name,
|
|
80
|
+
publicId: type.publicId === "" ? null : type.publicId,
|
|
81
|
+
systemId: type.systemId === "" ? null : type.systemId,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async function toShadow(shadow) {
|
|
85
|
+
if (withCrossOrigin) {
|
|
86
|
+
await ensureCrossOrigin(document);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
type: "shadow",
|
|
90
|
+
mode: shadow.mode,
|
|
91
|
+
children: await mapAsync(shadow.childNodes, toNode),
|
|
92
|
+
style: getStyleSheets(shadow),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* @privateRemarks
|
|
97
|
+
* Adopted stylesheets are assumed to be ordered after document stylesheets.
|
|
98
|
+
*
|
|
99
|
+
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/adoptedStyleSheets}
|
|
100
|
+
*/
|
|
101
|
+
function getStyleSheets(docOrShadow) {
|
|
102
|
+
return [
|
|
103
|
+
...map(docOrShadow.styleSheets, toSheet),
|
|
104
|
+
// `adoptedStyleSheets` generated by JSDOM can be undefined despite it violating the type.
|
|
105
|
+
// It seems this part of the specification is still not fully implemented in JSDOM as of July 2024.
|
|
106
|
+
// https://github.com/jsdom/jsdom/issues/3444
|
|
107
|
+
...map(docOrShadow.adoptedStyleSheets ?? [], toSheet),
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
function toSheet(sheet) {
|
|
111
|
+
let rules;
|
|
112
|
+
try {
|
|
113
|
+
rules = map(sheet.cssRules, toRule);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
rules = [];
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
rules,
|
|
120
|
+
disabled: sheet.disabled,
|
|
121
|
+
condition:
|
|
122
|
+
// Sheets generated by pre-renderers like JSDOM do not contain media
|
|
123
|
+
// at all.
|
|
124
|
+
// OTOH, the MediaList.mediaText interface treat null as the empty
|
|
125
|
+
// string, so we must do the same here (in the other direction).
|
|
126
|
+
(sheet?.media?.mediaText ?? "") === "" ? null : sheet.media.mediaText,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function toRule(rule) {
|
|
130
|
+
// In the best case, rule.constructor.name works and everything is fine.
|
|
131
|
+
switch (rule.constructor.name) {
|
|
132
|
+
case "CSSFontFaceRule":
|
|
133
|
+
return toFontFaceRule(rule);
|
|
134
|
+
case "CSSImportRule":
|
|
135
|
+
return toImportRule(rule);
|
|
136
|
+
case "CSSKeyframeRule":
|
|
137
|
+
return toKeyframeRule(rule);
|
|
138
|
+
case "CSSKeyframesRule":
|
|
139
|
+
return toKeyframesRule(rule);
|
|
140
|
+
case "CSSLayerBlockRule":
|
|
141
|
+
return toLayerBlockRule(rule);
|
|
142
|
+
case "CSSLayerStatementRule":
|
|
143
|
+
return toLayerStatementRule(rule);
|
|
144
|
+
case "CSSMediaRule":
|
|
145
|
+
return toMediaRule(rule);
|
|
146
|
+
case "CSSNamespaceRule":
|
|
147
|
+
return toNamespaceRule(rule);
|
|
148
|
+
case "CSSPageRule":
|
|
149
|
+
return toPageRule(rule);
|
|
150
|
+
case "CSSStyleRule":
|
|
151
|
+
return toStyleRule(rule);
|
|
152
|
+
case "CSSSupportsRule":
|
|
153
|
+
return toSupportsRule(rule);
|
|
154
|
+
}
|
|
155
|
+
// In some case (June 2024: in Firefox), rule.constructor.name returns
|
|
156
|
+
// undefined when used from an extension's content script. This is likely
|
|
157
|
+
// due to the fact that the rule has been created in the "page" world,
|
|
158
|
+
// but this code is evaluated in a content script world which does not
|
|
159
|
+
// have access to the actual constructor.
|
|
160
|
+
// However, in that case, .toString() seems to work… Since it may have been
|
|
161
|
+
// redefined along the prototype chain, we make sure to use the basic one.
|
|
162
|
+
// see https://stackoverflow.com/questions/43616128/undefined-javascript-object-constructor
|
|
163
|
+
switch (Object.prototype.toString.apply(rule)) {
|
|
164
|
+
case "[object CSSFontFaceRule]":
|
|
165
|
+
return toFontFaceRule(rule);
|
|
166
|
+
case "[object CSSImportRule]":
|
|
167
|
+
return toImportRule(rule);
|
|
168
|
+
case "[object CSSKeyframeRule]":
|
|
169
|
+
return toKeyframeRule(rule);
|
|
170
|
+
case "[object CSSKeyframesRule]":
|
|
171
|
+
return toKeyframesRule(rule);
|
|
172
|
+
case "[object CSSLayerBlockRule]":
|
|
173
|
+
return toLayerBlockRule(rule);
|
|
174
|
+
case "[object CSSLayerStatementRule]":
|
|
175
|
+
return toLayerStatementRule(rule);
|
|
176
|
+
case "[object CSSMediaRule]":
|
|
177
|
+
return toMediaRule(rule);
|
|
178
|
+
case "[object CSSNamespaceRule]":
|
|
179
|
+
return toNamespaceRule(rule);
|
|
180
|
+
case "[object CSSPageRule]":
|
|
181
|
+
return toPageRule(rule);
|
|
182
|
+
case "[object CSSStyleRule]":
|
|
183
|
+
return toStyleRule(rule);
|
|
184
|
+
case "[object CSSSupportsRule]":
|
|
185
|
+
return toSupportsRule(rule);
|
|
186
|
+
}
|
|
187
|
+
// If everything else failed, we default to the deprecated `type`.
|
|
188
|
+
// This is clearly bad, notably because @layer rules where introduced
|
|
189
|
+
// after the deprecation and thus do not have a `type` property.
|
|
190
|
+
// But it might still save the show in some corner cases.
|
|
191
|
+
switch (rule.type) {
|
|
192
|
+
case CSSRule.FONT_FACE_RULE:
|
|
193
|
+
return toFontFaceRule(rule);
|
|
194
|
+
case CSSRule.IMPORT_RULE:
|
|
195
|
+
return toImportRule(rule);
|
|
196
|
+
case CSSRule.KEYFRAME_RULE:
|
|
197
|
+
return toKeyframeRule(rule);
|
|
198
|
+
case CSSRule.KEYFRAMES_RULE:
|
|
199
|
+
return toKeyframesRule(rule);
|
|
200
|
+
// case "CSSLayerBlockRule":
|
|
201
|
+
// return toLayerBlockRule(rule);
|
|
202
|
+
// case "CSSLayerStatementRule":
|
|
203
|
+
// return toLayerStatementRule(rule);
|
|
204
|
+
case CSSRule.MEDIA_RULE:
|
|
205
|
+
return toMediaRule(rule);
|
|
206
|
+
case CSSRule.NAMESPACE_RULE:
|
|
207
|
+
return toNamespaceRule(rule);
|
|
208
|
+
case CSSRule.PAGE_RULE:
|
|
209
|
+
return toPageRule(rule);
|
|
210
|
+
case CSSRule.STYLE_RULE:
|
|
211
|
+
return toStyleRule(rule);
|
|
212
|
+
case CSSRule.SUPPORTS_RULE:
|
|
213
|
+
return toSupportsRule(rule);
|
|
214
|
+
}
|
|
215
|
+
// If nothing worked, just crash.
|
|
216
|
+
throw new Error(`Unsupported rule of type: ${rule.constructor.name} / ${Object.prototype.toString.apply(rule)} / ${rule.type}`);
|
|
217
|
+
}
|
|
218
|
+
function toFontFaceRule(rule) {
|
|
219
|
+
return {
|
|
220
|
+
type: "font-face",
|
|
221
|
+
style: toBlock(rule.style),
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function toImportRule(rule) {
|
|
225
|
+
return {
|
|
226
|
+
type: "import",
|
|
227
|
+
rules: rule.styleSheet === null ? [] : toSheet(rule.styleSheet).rules,
|
|
228
|
+
condition: rule.media.mediaText === "" ? "all" : rule.media.mediaText,
|
|
229
|
+
href: rule.href,
|
|
230
|
+
supportText: rule.supportsText,
|
|
231
|
+
layer: rule.layerName,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function toKeyframeRule(rule) {
|
|
235
|
+
return {
|
|
236
|
+
type: "keyframe",
|
|
237
|
+
key: rule.keyText,
|
|
238
|
+
style: toBlock(rule.style),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function toKeyframesRule(rule) {
|
|
242
|
+
let rules;
|
|
243
|
+
try {
|
|
244
|
+
rules = map(rule.cssRules, toRule);
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
rules = [];
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
type: "keyframes",
|
|
251
|
+
rules,
|
|
252
|
+
name: rule.name,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function toLayerBlockRule(rule) {
|
|
256
|
+
return {
|
|
257
|
+
type: "layer-block",
|
|
258
|
+
layer: rule.name,
|
|
259
|
+
rules: map(rule.cssRules, toRule),
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function toLayerStatementRule(rule) {
|
|
263
|
+
return {
|
|
264
|
+
type: "layer-statement",
|
|
265
|
+
layers: [...rule.nameList],
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function toMediaRule(rule) {
|
|
269
|
+
let rules;
|
|
270
|
+
try {
|
|
271
|
+
rules = map(rule.cssRules, toRule);
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
rules = [];
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
type: "media",
|
|
278
|
+
condition: rule.conditionText,
|
|
279
|
+
rules,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function toNamespaceRule(rule) {
|
|
283
|
+
return {
|
|
284
|
+
type: "namespace",
|
|
285
|
+
namespace: rule.namespaceURI,
|
|
286
|
+
prefix: rule.prefix,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function toPageRule(rule) {
|
|
290
|
+
return {
|
|
291
|
+
type: "page",
|
|
292
|
+
selector: rule.selectorText,
|
|
293
|
+
style: toBlock(rule.style),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
function toStyleRule(styleRule) {
|
|
297
|
+
return {
|
|
298
|
+
type: "style",
|
|
299
|
+
selector: styleRule.selectorText,
|
|
300
|
+
style: toBlock(styleRule.style),
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function toSupportsRule(rule) {
|
|
304
|
+
let rules;
|
|
305
|
+
try {
|
|
306
|
+
rules = map(rule.cssRules, toRule);
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
rules = [];
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
312
|
+
type: "supports",
|
|
313
|
+
condition: rule.conditionText,
|
|
314
|
+
rules,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* @privateRemarks
|
|
319
|
+
* User Agents normally expose the pre-parsed declarations.
|
|
320
|
+
* However, there is a corner case of shorthands whose value is a `var()`
|
|
321
|
+
* where several UAs (as of April 2024: at least Chrome and Firefox) list
|
|
322
|
+
* the **longhands** in their CSSStyleDeclaration object (in the enumerable
|
|
323
|
+
* part), but associate no values to them, only to the corresponding
|
|
324
|
+
* shorthand (as expected and declared). This causes attempts to access
|
|
325
|
+
* the apparently declared properties through the `getPropertyValue()`
|
|
326
|
+
* method to return an empty string.
|
|
327
|
+
*
|
|
328
|
+
* {@link https://github.com/Siteimprove/alfa/issues/1563}
|
|
329
|
+
*
|
|
330
|
+
* To circumvent that, we simply return the raw CSS text; and delegate parsing
|
|
331
|
+
* to consumers, aka Block.from.
|
|
332
|
+
*
|
|
333
|
+
* Note that somehow JSDOM behaves differently and correctly associate the
|
|
334
|
+
* value with the shorthand. This means that the local tests using JSDOM
|
|
335
|
+
* are brittle and cannot detect a regression on this issue.
|
|
336
|
+
*/
|
|
337
|
+
function toBlock(block) {
|
|
338
|
+
return block.cssText;
|
|
339
|
+
}
|
|
340
|
+
function toRectangle(domRect) {
|
|
341
|
+
return {
|
|
342
|
+
type: "rectangle",
|
|
343
|
+
x: domRect.x,
|
|
344
|
+
y: domRect.y,
|
|
345
|
+
width: domRect.width,
|
|
346
|
+
height: domRect.height,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
function map(arrayLike, mapper) {
|
|
350
|
+
const result = new Array(arrayLike.length);
|
|
351
|
+
for (let i = 0, n = arrayLike.length; i < n; i++) {
|
|
352
|
+
result[i] = mapper(arrayLike[i]);
|
|
353
|
+
}
|
|
354
|
+
return result;
|
|
355
|
+
}
|
|
356
|
+
async function mapAsync(arrayLike, mapper) {
|
|
357
|
+
const result = new Array(arrayLike.length);
|
|
358
|
+
for (let i = 0, n = arrayLike.length; i < n; i++) {
|
|
359
|
+
result[i] = await mapper(arrayLike[i]);
|
|
360
|
+
}
|
|
361
|
+
return result;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Ensure that the needed resources for the document or shadow root, such as
|
|
365
|
+
* style sheets, adhere to CORS policy.
|
|
366
|
+
*/
|
|
367
|
+
async function ensureCrossOrigin(documentOrShadowRoot) {
|
|
368
|
+
/**
|
|
369
|
+
* Ensure that all `<link>` elements specify the `crossorigin` attribute.
|
|
370
|
+
* Even `<link>` elements that reference same-origin resources will need
|
|
371
|
+
* this attribute as they may contain nested resource imports that risk
|
|
372
|
+
* violating CORS policy.
|
|
373
|
+
*
|
|
374
|
+
* Do keep in mind that this will only work for resources that also set
|
|
375
|
+
* appropriate CORS request headers.
|
|
376
|
+
*/
|
|
377
|
+
const links = documentOrShadowRoot.querySelectorAll("link");
|
|
378
|
+
for (let i = 0; i < links.length; i++) {
|
|
379
|
+
const link = links[i];
|
|
380
|
+
/**
|
|
381
|
+
* Skip `<link>` elements for which the `crossorigin` attribute is already
|
|
382
|
+
* set to a valid value.
|
|
383
|
+
*/
|
|
384
|
+
if (link.crossOrigin !== null) {
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Simply setting the `crossorigin` attribute for the `<link>` element
|
|
389
|
+
* will not work as it must be reevaluated. We therefore create a clone,
|
|
390
|
+
* set the `crossorigin` attribute, and replace the original `<link>`
|
|
391
|
+
* element.
|
|
392
|
+
*/
|
|
393
|
+
const clone = link.cloneNode();
|
|
394
|
+
/**
|
|
395
|
+
* Set the `crossorigin` attribute to `anonymous`, ensuring that
|
|
396
|
+
* credentials are not sent as part of the cross-origin request. This is
|
|
397
|
+
* incredibly important as we don't want to risk leaking credentials!
|
|
398
|
+
*/
|
|
399
|
+
clone.crossOrigin = "anonymous";
|
|
400
|
+
/**
|
|
401
|
+
* Replace the original `<link>` element with its clone. For style sheets,
|
|
402
|
+
* this will unfortunately cause a FOUC while the browser recomputes
|
|
403
|
+
* styles.
|
|
404
|
+
*
|
|
405
|
+
* {@link https://en.wikipedia.org/wiki/Flash_of_unstyled_content}
|
|
406
|
+
*/
|
|
407
|
+
link.parentNode.replaceChild(clone, link);
|
|
408
|
+
/**
|
|
409
|
+
* While certain resources will load synchronously from cache, others will
|
|
410
|
+
* not and we therefore need to await these.
|
|
411
|
+
*/
|
|
412
|
+
if (shouldAwait(link)) {
|
|
413
|
+
/**
|
|
414
|
+
* Construct a promise that resolves once the `<link>` element either
|
|
415
|
+
* loads successfully or fails to load. If the `<link>` element fails to
|
|
416
|
+
* load, a request error will be logged to the console which should be
|
|
417
|
+
* enough indication that something didn't go quite as expected. Either
|
|
418
|
+
* way, we will deliver audit results even in the event of a missing
|
|
419
|
+
* resource.
|
|
420
|
+
*/
|
|
421
|
+
await new Promise((resolve) => ["load", "error"].forEach((event) => clone.addEventListener(event, () => resolve())));
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Check if the given `<link>` element should be awaited.
|
|
426
|
+
*/
|
|
427
|
+
function shouldAwait(link) {
|
|
428
|
+
/**
|
|
429
|
+
* A `<link>` element with an empty `href` will cause the fetch process to
|
|
430
|
+
* abort with no events to await.
|
|
431
|
+
*/
|
|
432
|
+
if (link.getAttribute("href")?.trim() === "") {
|
|
433
|
+
return false;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Style sheets should be awaited as these are loaded and applied
|
|
437
|
+
* asynchronously, often times causing additional resources to be loaded
|
|
438
|
+
* via `url()` references and `@import` rules.
|
|
439
|
+
*/
|
|
440
|
+
if (link.rel === "stylesheet") {
|
|
441
|
+
return true;
|
|
442
|
+
}
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
Native.fromNode = fromNode;
|
|
448
|
+
})(Native || (Native = {}));
|
|
449
|
+
//# sourceMappingURL=native.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Refinement } from "@siteimprove/alfa-refinement";
|
|
2
|
+
import { Attribute } from "../../attribute.js";
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export declare function hasName<N extends string = string>(predicate: Refinement<string, N>): Refinement<Attribute, Attribute<N>>;
|
|
7
|
+
/**
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export declare function hasName<N extends string = string>(name: N, ...rest: Array<N>): Refinement<Attribute, Attribute<N>>;
|
|
11
|
+
//# sourceMappingURL=has-name.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Attribute } from "../../attribute.js";
|
|
2
|
+
export function hasName(nameOrPredicate, ...names) {
|
|
3
|
+
let predicate;
|
|
4
|
+
if (typeof nameOrPredicate === "function") {
|
|
5
|
+
predicate = nameOrPredicate;
|
|
6
|
+
}
|
|
7
|
+
else {
|
|
8
|
+
names.unshift(nameOrPredicate);
|
|
9
|
+
predicate = (name, attribute) => names.some((candidate) => Attribute.foldCase(candidate, attribute.owner) === name);
|
|
10
|
+
}
|
|
11
|
+
return (attribute) => predicate(attribute.name, attribute);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=has-name.js.map
|