@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/node.js
ADDED
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import { Comparable, Comparison, } from "@siteimprove/alfa-comparable";
|
|
2
|
+
import { Flags } from "@siteimprove/alfa-flags";
|
|
3
|
+
import { Lazy } from "@siteimprove/alfa-lazy";
|
|
4
|
+
import { Option } from "@siteimprove/alfa-option";
|
|
5
|
+
import { Selective } from "@siteimprove/alfa-selective";
|
|
6
|
+
import { Sequence } from "@siteimprove/alfa-sequence";
|
|
7
|
+
import { String } from "@siteimprove/alfa-string";
|
|
8
|
+
import * as tree from "@siteimprove/alfa-tree";
|
|
9
|
+
import { Attribute, Comment, Document, Element, Fragment, Shadow, Slot, Slotable, Text, Type, } from "./index.js";
|
|
10
|
+
import * as predicate from "./node/predicate.js";
|
|
11
|
+
import * as traversal from "./node/traversal.js";
|
|
12
|
+
/**
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
export class Node extends tree.Node {
|
|
16
|
+
constructor(children, type, externalId, serializationId, extraData) {
|
|
17
|
+
super(children, type, externalId, serializationId, extraData);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* {@link https://dom.spec.whatwg.org/#concept-descendant-text-content}
|
|
21
|
+
*/
|
|
22
|
+
textContent(options = Node.Traversal.empty) {
|
|
23
|
+
return String.flatten(this.descendants(options).filter(Text.isText).join(""));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Construct a sequence of descendants of this node sorted by tab index. Only
|
|
27
|
+
* nodes with a non-negative tab index are included in the sequence.
|
|
28
|
+
*
|
|
29
|
+
* {@link https://html.spec.whatwg.org/multipage/#tabindex-value}
|
|
30
|
+
*/
|
|
31
|
+
tabOrder() {
|
|
32
|
+
/**
|
|
33
|
+
* Gather candidates for sequential focus navigation.
|
|
34
|
+
*
|
|
35
|
+
* @remarks
|
|
36
|
+
* These are all elements that are keyboard focusable (non-negative
|
|
37
|
+
* tabIndex), plus the shadow hosts and content elements that may contain
|
|
38
|
+
* focusable descendants.
|
|
39
|
+
*
|
|
40
|
+
* It is important that the traversal is done here on the DOM tree only.
|
|
41
|
+
* The shadow trees and content documents will be expanded later. Doing it
|
|
42
|
+
* too early potentially would mix their elements during sorting of the
|
|
43
|
+
* tabIndexes.
|
|
44
|
+
*/
|
|
45
|
+
function candidates(node) {
|
|
46
|
+
if (Element.isElement(node)) {
|
|
47
|
+
const element = node;
|
|
48
|
+
const tabIndex = element.tabIndex();
|
|
49
|
+
// If the element is a shadow host that doesn't block keyboard navigation
|
|
50
|
+
// we record it to later expand its shadow tree.
|
|
51
|
+
if (element.shadow.isSome()) {
|
|
52
|
+
// If the element has a negative tab index and is a shadow host then
|
|
53
|
+
// none of its descendants will be part of the tab order.
|
|
54
|
+
if (tabIndex.some((i) => i < 0)) {
|
|
55
|
+
return Sequence.empty();
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
return Sequence.of([element, tabIndex]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// If the element contains a content document, we record it to later
|
|
62
|
+
// expand its content.
|
|
63
|
+
if (element.content.isSome()) {
|
|
64
|
+
return Sequence.of([element, tabIndex]);
|
|
65
|
+
}
|
|
66
|
+
// If the element is a slot, we replace it by its assigned nodes.
|
|
67
|
+
if (Slot.isSlot(element)) {
|
|
68
|
+
return Sequence.from(element.assignedNodes())
|
|
69
|
+
.filter(Element.isElement)
|
|
70
|
+
.map((element) => [element, tabIndex]);
|
|
71
|
+
}
|
|
72
|
+
// If the element is keyboard focusable, record it and recurse.
|
|
73
|
+
if (tabIndex.some((i) => i >= 0)) {
|
|
74
|
+
return Sequence.of([element, tabIndex], Lazy.of(() => element.children().flatMap(candidates)));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Otherwise (not an element, or not keyboard focusable), recurse into the children.
|
|
78
|
+
return node.children().flatMap(candidates);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Compare two elements, with non-negative tabindexes, by tabindex.
|
|
82
|
+
*
|
|
83
|
+
* @remarks
|
|
84
|
+
* Due to non-focusable shadow hosts being candidates (for shadow DOM
|
|
85
|
+
* expansion), we may have some indexes being None. These must be treated
|
|
86
|
+
* as 0 (insert in DOM order), rather than smaller than actual indexes
|
|
87
|
+
* (insert at start). Therefore, we cannot use Option.compareWith.
|
|
88
|
+
*/
|
|
89
|
+
const comparer = ([, a], [, b]) => {
|
|
90
|
+
const aValue = a.getOr(0);
|
|
91
|
+
const bValue = b.getOr(0);
|
|
92
|
+
return aValue === 0
|
|
93
|
+
? // "normal order" must come after any "specific order",
|
|
94
|
+
// i.e., 0 is greater than any positive number.
|
|
95
|
+
bValue === 0
|
|
96
|
+
? Comparison.Equal
|
|
97
|
+
: Comparison.Greater
|
|
98
|
+
: bValue === 0
|
|
99
|
+
? // aValue cannot be 0 anymore.
|
|
100
|
+
Comparison.Less
|
|
101
|
+
: // If none are 0, simply compare the values.
|
|
102
|
+
Comparable.compare(aValue, bValue);
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Expand an element into the sequentially focusable elements in its
|
|
106
|
+
* shadow tree or content document.
|
|
107
|
+
*
|
|
108
|
+
* @remarks
|
|
109
|
+
* It is important that this expansion happens **after** sorting by tabindex
|
|
110
|
+
* since shadow DOM and content documents build their own sequential focus
|
|
111
|
+
* order that is inserted as-is in the light tree or parent browsing context.
|
|
112
|
+
* That is, a tabindex of 1 in a shadow tree or content document does
|
|
113
|
+
* **not** come before a tabindex of 2 in the main document.
|
|
114
|
+
*/
|
|
115
|
+
function expand([element, tabIndex]) {
|
|
116
|
+
// In case of shadow host, we include it if its sequentially focusable,
|
|
117
|
+
// and always recurse into the shadow tree.
|
|
118
|
+
for (const shadow of element.shadow) {
|
|
119
|
+
if (tabIndex.some((i) => i >= 0)) {
|
|
120
|
+
return Sequence.of(element, Lazy.of(() => shadow.tabOrder()));
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
return shadow.tabOrder();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// In case of content document, we always ignore the host (iframe) which
|
|
127
|
+
// usually redirects focus to the content.
|
|
128
|
+
for (const content of element.content) {
|
|
129
|
+
return content.tabOrder();
|
|
130
|
+
}
|
|
131
|
+
// If no shadow or content document, just keep the element.
|
|
132
|
+
return Sequence.of(element);
|
|
133
|
+
}
|
|
134
|
+
return candidates(this).sortWith(comparer).flatMap(expand);
|
|
135
|
+
}
|
|
136
|
+
parent(options = Node.Traversal.empty) {
|
|
137
|
+
const parent = this._parent;
|
|
138
|
+
// If we traverse the flat tree, we want to jump over shadow roots.
|
|
139
|
+
if (options.isSet(Node.Traversal.flattened)) {
|
|
140
|
+
return parent.flatMap((parent) => {
|
|
141
|
+
if (Shadow.isShadow(parent)) {
|
|
142
|
+
return parent.host;
|
|
143
|
+
}
|
|
144
|
+
// Additionally, if this is a slottable light child of a shadow host, we want
|
|
145
|
+
// to search for where it is slotted, and return that parent instead.
|
|
146
|
+
if (Element.isElement(parent) &&
|
|
147
|
+
parent.shadow.isSome() &&
|
|
148
|
+
Slotable.isSlotable(this)) {
|
|
149
|
+
return this.assignedSlot().flatMap((slot) => slot.parent(options));
|
|
150
|
+
}
|
|
151
|
+
return Option.of(parent);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return parent;
|
|
155
|
+
}
|
|
156
|
+
_path = [];
|
|
157
|
+
/**
|
|
158
|
+
* @internal
|
|
159
|
+
*/
|
|
160
|
+
_internalPath(options) {
|
|
161
|
+
let path = this.parent(options)
|
|
162
|
+
.map((parent) => parent.path(options))
|
|
163
|
+
.getOr("/");
|
|
164
|
+
path += path === "/" ? "" : "/";
|
|
165
|
+
path += "node()";
|
|
166
|
+
path += `[${this.index(options) + 1}]`;
|
|
167
|
+
return path;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get an XPath that uniquely identifies the node across descendants of its
|
|
171
|
+
* root.
|
|
172
|
+
*/
|
|
173
|
+
// path may change if the subtree is attached to a parent, so we shouldn't
|
|
174
|
+
// cache it.
|
|
175
|
+
// However, path is a fairly "final" serialisation operation that makes
|
|
176
|
+
// little sense in the context of an incomplete tree.
|
|
177
|
+
// For the sake of simplicity, and until we encounter errors due to this,
|
|
178
|
+
// we accept the risk of caching the value assuming that it will only be
|
|
179
|
+
// computed on fully frozen trees.
|
|
180
|
+
path(options = Node.Traversal.empty) {
|
|
181
|
+
if (this._path[options.value] !== undefined) {
|
|
182
|
+
return this._path[options.value];
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
this._path[options.value] = this._internalPath(options);
|
|
186
|
+
return this._internalPath(options);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
equals(value) {
|
|
190
|
+
return value === this;
|
|
191
|
+
}
|
|
192
|
+
toEARL() {
|
|
193
|
+
return {
|
|
194
|
+
"@context": {
|
|
195
|
+
ptr: "http://www.w3.org/2009/pointers#",
|
|
196
|
+
},
|
|
197
|
+
"@type": [
|
|
198
|
+
"ptr:Pointer",
|
|
199
|
+
"ptr:SinglePointer",
|
|
200
|
+
"ptr:ExpressionPointer",
|
|
201
|
+
"ptr:XPathPointer",
|
|
202
|
+
],
|
|
203
|
+
"ptr:expression": this.path(),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
toSARIF() {
|
|
207
|
+
return {
|
|
208
|
+
logicalLocations: [
|
|
209
|
+
{
|
|
210
|
+
fullyQualifiedName: this.path(),
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* @public
|
|
218
|
+
*/
|
|
219
|
+
(function (Node) {
|
|
220
|
+
function isNode(value) {
|
|
221
|
+
return value instanceof Node;
|
|
222
|
+
}
|
|
223
|
+
Node.isNode = isNode;
|
|
224
|
+
class Traversal extends Flags {
|
|
225
|
+
static of(...flags) {
|
|
226
|
+
return new Traversal(Flags._reduce(...flags));
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
Node.Traversal = Traversal;
|
|
230
|
+
(function (Traversal) {
|
|
231
|
+
Traversal.none = 0;
|
|
232
|
+
/**
|
|
233
|
+
* When set, traverse the node in shadow-including tree order.
|
|
234
|
+
*
|
|
235
|
+
* {@link https://dom.spec.whatwg.org/#concept-shadow-including-tree-order}
|
|
236
|
+
*/
|
|
237
|
+
Traversal.composed = (1 << 0);
|
|
238
|
+
/**
|
|
239
|
+
* When set, traverse the flattened element tree rooted at the node.
|
|
240
|
+
*
|
|
241
|
+
* {@link https://drafts.csswg.org/css-scoping/#flat-tree}
|
|
242
|
+
*/
|
|
243
|
+
Traversal.flattened = (1 << 1);
|
|
244
|
+
/**
|
|
245
|
+
* When set, traverse all nested browsing contexts encountered.
|
|
246
|
+
*
|
|
247
|
+
* {@link https://html.spec.whatwg.org/#nested-browsing-context}
|
|
248
|
+
*/
|
|
249
|
+
Traversal.nested = (1 << 2);
|
|
250
|
+
Traversal.empty = Traversal.of(Traversal.none);
|
|
251
|
+
})(Traversal = Node.Traversal || (Node.Traversal = {}));
|
|
252
|
+
/**
|
|
253
|
+
* Traversal options to traverse the flat tree.
|
|
254
|
+
*
|
|
255
|
+
* {@link https://drafts.csswg.org/css-scoping-1/#flattening}
|
|
256
|
+
*/
|
|
257
|
+
Node.flatTree = Traversal.of(Traversal.flattened);
|
|
258
|
+
/**
|
|
259
|
+
* Traversal options to traverse all relevant nodes (flat tree and inside
|
|
260
|
+
* nested browsing container), a very frequent use case.
|
|
261
|
+
*/
|
|
262
|
+
Node.fullTree = Traversal.of(Traversal.flattened, Traversal.nested);
|
|
263
|
+
/**
|
|
264
|
+
* Traversal options to traverse in shadow-including tree order and inside
|
|
265
|
+
* nested browsing context container, a common use case.
|
|
266
|
+
*/
|
|
267
|
+
Node.composedNested = Traversal.of(Traversal.composed, Traversal.nested);
|
|
268
|
+
function from(json, device) {
|
|
269
|
+
return fromNode(json, device).run();
|
|
270
|
+
}
|
|
271
|
+
Node.from = from;
|
|
272
|
+
/**
|
|
273
|
+
* @internal
|
|
274
|
+
*/
|
|
275
|
+
function fromNode(json, device) {
|
|
276
|
+
switch (json.type) {
|
|
277
|
+
case "element":
|
|
278
|
+
return Element.fromElement(json, device);
|
|
279
|
+
case "attribute":
|
|
280
|
+
return Attribute.fromAttribute(json);
|
|
281
|
+
case "text":
|
|
282
|
+
return Text.fromText(json);
|
|
283
|
+
case "comment":
|
|
284
|
+
return Comment.fromComment(json);
|
|
285
|
+
case "document":
|
|
286
|
+
return Document.fromDocument(json, device);
|
|
287
|
+
case "type":
|
|
288
|
+
return Type.fromType(json);
|
|
289
|
+
case "fragment":
|
|
290
|
+
return Fragment.fromFragment(json, device);
|
|
291
|
+
default:
|
|
292
|
+
throw new Error(`Unexpected node of type: ${json.type}`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
Node.fromNode = fromNode;
|
|
296
|
+
function clone(node, options, device) {
|
|
297
|
+
return cloneNode(node, options, device).run();
|
|
298
|
+
}
|
|
299
|
+
Node.clone = clone;
|
|
300
|
+
/**
|
|
301
|
+
* @internal
|
|
302
|
+
*/
|
|
303
|
+
function cloneNode(node, options = {
|
|
304
|
+
predicate: () => false,
|
|
305
|
+
newElements: [],
|
|
306
|
+
}, device) {
|
|
307
|
+
return Selective.of(node)
|
|
308
|
+
.if(Element.isElement, Element.cloneElement(options, device))
|
|
309
|
+
.if(Attribute.isAttribute, Attribute.cloneAttribute)
|
|
310
|
+
.if(Text.isText, Text.cloneText)
|
|
311
|
+
.if(Comment.isComment, Comment.cloneComment)
|
|
312
|
+
.if(Document.isDocument, Document.cloneDocument(options, device))
|
|
313
|
+
.if(Type.isType, Type.cloneType)
|
|
314
|
+
.if(Fragment.isFragment, Fragment.cloneFragment(options, device))
|
|
315
|
+
.if(Shadow.isShadow, Shadow.cloneShadow(options, device))
|
|
316
|
+
.else(() => {
|
|
317
|
+
throw new Error(`Unexpected node of type: ${node.type}`);
|
|
318
|
+
})
|
|
319
|
+
.get();
|
|
320
|
+
}
|
|
321
|
+
Node.cloneNode = cloneNode;
|
|
322
|
+
Node.getNodesBetween = traversal.getNodesBetween;
|
|
323
|
+
Node.hasChild = predicate.hasChild, Node.hasDescendant = predicate.hasDescendant, Node.hasInclusiveDescendant = predicate.hasInclusiveDescendant, Node.hasTextContent = predicate.hasTextContent, Node.isRoot = predicate.isRoot;
|
|
324
|
+
})(Node || (Node = {}));
|
|
325
|
+
//# sourceMappingURL=node.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Equatable } from "@siteimprove/alfa-equatable";
|
|
2
|
+
import { Iterable } from "@siteimprove/alfa-iterable";
|
|
3
|
+
import type { Serializable } from "@siteimprove/alfa-json";
|
|
4
|
+
import { Option } from "@siteimprove/alfa-option";
|
|
5
|
+
import type { Predicate } from "@siteimprove/alfa-predicate";
|
|
6
|
+
import { Declaration } from "./declaration.js";
|
|
7
|
+
/**
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export declare class Block implements Iterable<Declaration>, Equatable, Serializable {
|
|
11
|
+
static of(declarations: Iterable<Declaration>): Block;
|
|
12
|
+
private _declarations;
|
|
13
|
+
private constructor();
|
|
14
|
+
get declarations(): Iterable<Declaration>;
|
|
15
|
+
get size(): number;
|
|
16
|
+
isEmpty(): boolean;
|
|
17
|
+
declaration(predicate: string | Predicate<Declaration>): Option<Declaration>;
|
|
18
|
+
equals(value: unknown): value is this;
|
|
19
|
+
[Symbol.iterator](): Iterator<Declaration>;
|
|
20
|
+
toJSON(): Block.JSON;
|
|
21
|
+
toString(): string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
export declare namespace Block {
|
|
27
|
+
type JSON = Array<Declaration.JSON>;
|
|
28
|
+
function from(jsonOrText: JSON | string): Block;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=block.d.ts.map
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Declaration as CSSDeclaration, Lexer } from "@siteimprove/alfa-css";
|
|
2
|
+
import { Iterable } from "@siteimprove/alfa-iterable";
|
|
3
|
+
import { Option } from "@siteimprove/alfa-option";
|
|
4
|
+
import { Declaration } from "./declaration.js";
|
|
5
|
+
/**
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export class Block {
|
|
9
|
+
static of(declarations) {
|
|
10
|
+
return new Block(Array.from(declarations));
|
|
11
|
+
}
|
|
12
|
+
_declarations;
|
|
13
|
+
constructor(declarations) {
|
|
14
|
+
this._declarations = declarations;
|
|
15
|
+
}
|
|
16
|
+
get declarations() {
|
|
17
|
+
return this._declarations;
|
|
18
|
+
}
|
|
19
|
+
get size() {
|
|
20
|
+
return this._declarations.length;
|
|
21
|
+
}
|
|
22
|
+
isEmpty() {
|
|
23
|
+
return this._declarations.length === 0;
|
|
24
|
+
}
|
|
25
|
+
declaration(predicate) {
|
|
26
|
+
return Option.from(this._declarations.find(typeof predicate === "string"
|
|
27
|
+
? (declaration) => declaration.name === predicate
|
|
28
|
+
: predicate));
|
|
29
|
+
}
|
|
30
|
+
equals(value) {
|
|
31
|
+
return (value instanceof Block &&
|
|
32
|
+
value._declarations.length === this._declarations.length &&
|
|
33
|
+
value._declarations.every((declaration, i) => declaration.equals(this._declarations[i])));
|
|
34
|
+
}
|
|
35
|
+
*[Symbol.iterator]() {
|
|
36
|
+
yield* this._declarations;
|
|
37
|
+
}
|
|
38
|
+
toJSON() {
|
|
39
|
+
return this._declarations.map((declaration) => declaration.toJSON());
|
|
40
|
+
}
|
|
41
|
+
toString() {
|
|
42
|
+
return this._declarations.join(";\n");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* @public
|
|
47
|
+
*/
|
|
48
|
+
(function (Block) {
|
|
49
|
+
function from(jsonOrText) {
|
|
50
|
+
if (typeof jsonOrText === "string") {
|
|
51
|
+
return Block.of(Iterable.map(CSSDeclaration.parseList(Lexer.lex(jsonOrText)).getUnsafe(`Could not parse CSS declarations "${jsonOrText}"`)[1], (declaration) => Declaration.from({
|
|
52
|
+
name: declaration.name,
|
|
53
|
+
value: declaration.value.join(""),
|
|
54
|
+
important: declaration.important,
|
|
55
|
+
})));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
return Block.of(jsonOrText.map(Declaration.from));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
Block.from = from;
|
|
62
|
+
})(Block || (Block = {}));
|
|
63
|
+
//# sourceMappingURL=block.js.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Equatable } from "@siteimprove/alfa-equatable";
|
|
2
|
+
import type { Serializable } from "@siteimprove/alfa-json";
|
|
3
|
+
import { Option } from "@siteimprove/alfa-option";
|
|
4
|
+
import type * as json from "@siteimprove/alfa-json";
|
|
5
|
+
import type { Element } from "../node/element.js";
|
|
6
|
+
import type { Rule } from "./rule.js";
|
|
7
|
+
/**
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export declare class Declaration implements Equatable, Serializable {
|
|
11
|
+
static of(name: string, value: string, important?: boolean): Declaration;
|
|
12
|
+
private readonly _name;
|
|
13
|
+
private readonly _value;
|
|
14
|
+
private readonly _important;
|
|
15
|
+
/**
|
|
16
|
+
* @remarks
|
|
17
|
+
* If the declaration is in a style rule, point to it
|
|
18
|
+
*/
|
|
19
|
+
private _parent;
|
|
20
|
+
/**
|
|
21
|
+
* @remarks
|
|
22
|
+
* If the declaration is in a style attribute on an element, point to it
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* "owner" use the same vocabulary as attribute's owner
|
|
26
|
+
*
|
|
27
|
+
* @remarks
|
|
28
|
+
* Only one of _parent and _owner should be Some.
|
|
29
|
+
*/
|
|
30
|
+
private _owner;
|
|
31
|
+
private constructor();
|
|
32
|
+
get name(): string;
|
|
33
|
+
get value(): string;
|
|
34
|
+
get important(): boolean;
|
|
35
|
+
get parent(): Option<Rule>;
|
|
36
|
+
get owner(): Option<Element>;
|
|
37
|
+
ancestors(): Iterable<Rule>;
|
|
38
|
+
/**
|
|
39
|
+
* Parent rule or owner element are ignored for declaration equality.
|
|
40
|
+
*/
|
|
41
|
+
equals(value: unknown): value is this;
|
|
42
|
+
toJSON(): Declaration.JSON;
|
|
43
|
+
toString(): string;
|
|
44
|
+
/**
|
|
45
|
+
* @internal
|
|
46
|
+
*/
|
|
47
|
+
_attachParent(parent: Rule): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
_attachOwner(owner: Element): boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
export declare namespace Declaration {
|
|
57
|
+
interface JSON {
|
|
58
|
+
[key: string]: json.JSON;
|
|
59
|
+
name: string;
|
|
60
|
+
value: string;
|
|
61
|
+
important: boolean;
|
|
62
|
+
}
|
|
63
|
+
function from(json: JSON): Declaration;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=declaration.d.ts.map
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { None, Option } from "@siteimprove/alfa-option";
|
|
2
|
+
/**
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
export class Declaration {
|
|
6
|
+
static of(name, value, important = false) {
|
|
7
|
+
return new Declaration(name, value, important);
|
|
8
|
+
}
|
|
9
|
+
_name;
|
|
10
|
+
_value;
|
|
11
|
+
_important;
|
|
12
|
+
/**
|
|
13
|
+
* @remarks
|
|
14
|
+
* If the declaration is in a style rule, point to it
|
|
15
|
+
*/
|
|
16
|
+
_parent = None;
|
|
17
|
+
/**
|
|
18
|
+
* @remarks
|
|
19
|
+
* If the declaration is in a style attribute on an element, point to it
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* "owner" use the same vocabulary as attribute's owner
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* Only one of _parent and _owner should be Some.
|
|
26
|
+
*/
|
|
27
|
+
_owner = None;
|
|
28
|
+
constructor(name, value, important) {
|
|
29
|
+
this._name = name;
|
|
30
|
+
this._value = value;
|
|
31
|
+
this._important = important;
|
|
32
|
+
}
|
|
33
|
+
get name() {
|
|
34
|
+
return this._name;
|
|
35
|
+
}
|
|
36
|
+
get value() {
|
|
37
|
+
return this._value;
|
|
38
|
+
}
|
|
39
|
+
get important() {
|
|
40
|
+
return this._important;
|
|
41
|
+
}
|
|
42
|
+
get parent() {
|
|
43
|
+
return this._parent;
|
|
44
|
+
}
|
|
45
|
+
get owner() {
|
|
46
|
+
return this._owner;
|
|
47
|
+
}
|
|
48
|
+
*ancestors() {
|
|
49
|
+
for (const parent of this._parent) {
|
|
50
|
+
yield parent;
|
|
51
|
+
yield* parent.ancestors();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Parent rule or owner element are ignored for declaration equality.
|
|
56
|
+
*/
|
|
57
|
+
equals(value) {
|
|
58
|
+
return (value instanceof Declaration &&
|
|
59
|
+
value._name === this._name &&
|
|
60
|
+
value._value === this._value &&
|
|
61
|
+
value._important === this._important);
|
|
62
|
+
}
|
|
63
|
+
toJSON() {
|
|
64
|
+
return {
|
|
65
|
+
name: this._name,
|
|
66
|
+
value: this._value,
|
|
67
|
+
important: this._important,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
toString() {
|
|
71
|
+
return `${this._name}: ${this._value}${this._important ? " !important" : ""}`;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
_attachParent(parent) {
|
|
77
|
+
if (this._parent.isSome() || this._owner.isSome()) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
this._parent = Option.of(parent);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
_attachOwner(owner) {
|
|
87
|
+
if (this._parent.isSome() || this._owner.isSome()) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
this._owner = Option.of(owner);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* @public
|
|
96
|
+
*/
|
|
97
|
+
(function (Declaration) {
|
|
98
|
+
function from(json) {
|
|
99
|
+
return Declaration.of(json.name, json.value, json.important);
|
|
100
|
+
}
|
|
101
|
+
Declaration.from = from;
|
|
102
|
+
})(Declaration || (Declaration = {}));
|
|
103
|
+
//# sourceMappingURL=declaration.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Rule } from "../rule.js";
|
|
2
|
+
import { GroupingRule } from "./grouping.js";
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export declare abstract class ConditionRule<T extends string = string> extends GroupingRule<T> {
|
|
7
|
+
protected readonly _condition: string;
|
|
8
|
+
protected constructor(type: T, condition: string, rules: Array<Rule>);
|
|
9
|
+
get condition(): string;
|
|
10
|
+
toJSON(): ConditionRule.JSON<T>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
export declare namespace ConditionRule {
|
|
16
|
+
interface JSON<T extends string = string> extends GroupingRule.JSON<T> {
|
|
17
|
+
condition: string;
|
|
18
|
+
}
|
|
19
|
+
function isConditionRule(value: unknown): value is ConditionRule;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=condition.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { GroupingRule } from "./grouping.js";
|
|
2
|
+
/**
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
export class ConditionRule extends GroupingRule {
|
|
6
|
+
_condition;
|
|
7
|
+
constructor(type, condition, rules) {
|
|
8
|
+
super(type, rules);
|
|
9
|
+
this._condition = condition;
|
|
10
|
+
}
|
|
11
|
+
get condition() {
|
|
12
|
+
return this._condition;
|
|
13
|
+
}
|
|
14
|
+
toJSON() {
|
|
15
|
+
return {
|
|
16
|
+
...super.toJSON(),
|
|
17
|
+
condition: this._condition,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
(function (ConditionRule) {
|
|
25
|
+
function isConditionRule(value) {
|
|
26
|
+
return value instanceof ConditionRule;
|
|
27
|
+
}
|
|
28
|
+
ConditionRule.isConditionRule = isConditionRule;
|
|
29
|
+
})(ConditionRule || (ConditionRule = {}));
|
|
30
|
+
//# sourceMappingURL=condition.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Trampoline } from "@siteimprove/alfa-trampoline";
|
|
2
|
+
import { Block } from "../block.js";
|
|
3
|
+
import type { Declaration } from "../declaration.js";
|
|
4
|
+
import { Rule } from "../rule.js";
|
|
5
|
+
/**
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export declare class FontFaceRule extends Rule<"font-face"> {
|
|
9
|
+
static of(declarations: Iterable<Declaration>): FontFaceRule;
|
|
10
|
+
private readonly _style;
|
|
11
|
+
private constructor();
|
|
12
|
+
get style(): Block;
|
|
13
|
+
toJSON(): FontFaceRule.JSON;
|
|
14
|
+
toString(): string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
export declare namespace FontFaceRule {
|
|
20
|
+
interface JSON extends Rule.JSON<"font-face"> {
|
|
21
|
+
style: Block.JSON | string;
|
|
22
|
+
}
|
|
23
|
+
function isFontFaceRule(value: unknown): value is FontFaceRule;
|
|
24
|
+
/**
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
function fromFontFaceRule(json: JSON): Trampoline<FontFaceRule>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=font-face.d.ts.map
|