@siteimprove/alfa-dom 0.108.2 → 0.110.0
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 +14 -0
- package/dist/node/comment.js +1 -1
- package/dist/node/element/predicate/is-suggested-focusable.js +3 -0
- package/dist/node/element.d.ts +11 -0
- package/dist/node/element.js +27 -4
- package/dist/node/query/descendants.d.ts +34 -1
- package/dist/node/query/descendants.js +49 -0
- package/dist/node/query/index.d.ts +6 -2
- package/dist/node/query/index.js +2 -1
- package/dist/node/text.js +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +2 -5
- package/package.json +29 -29
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @siteimprove/alfa-dom
|
|
2
2
|
|
|
3
|
+
## 0.110.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- **Added:** The `inert` attribute is now supported. ([#1964](https://github.com/Siteimprove/alfa/pull/1964))
|
|
8
|
+
|
|
9
|
+
## 0.109.0
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- **Added:** A new function `getTextDescendants` has been added to the `Query` namespace. It retrieves all text descendants of a node, with an option to group text under matching sub-trees into labeled `TextGroup` objects. ([#1972](https://github.com/Siteimprove/alfa/pull/1972))
|
|
14
|
+
|
|
15
|
+
- **Changed:** The `index()` method on nodes now accepts an optional predicate parameter to filter siblings when calculating the node's index position. ([#1980](https://github.com/Siteimprove/alfa/pull/1980))
|
|
16
|
+
|
|
3
17
|
## 0.108.2
|
|
4
18
|
|
|
5
19
|
## 0.108.1
|
package/dist/node/comment.js
CHANGED
|
@@ -28,7 +28,7 @@ export class Comment extends Node {
|
|
|
28
28
|
.getOr("/");
|
|
29
29
|
path += path === "/" ? "" : "/";
|
|
30
30
|
path += "comment()";
|
|
31
|
-
const index = this.
|
|
31
|
+
const index = this.index(options, Comment.isComment);
|
|
32
32
|
path += `[${index + 1}]`;
|
|
33
33
|
return path;
|
|
34
34
|
}
|
package/dist/node/element.d.ts
CHANGED
|
@@ -60,9 +60,20 @@ export declare class Element<N extends string = string> extends Node<"element">
|
|
|
60
60
|
* {@link https://html.spec.whatwg.org/#dom-tabindex}
|
|
61
61
|
*/
|
|
62
62
|
tabIndex(): Option<number>;
|
|
63
|
+
/**
|
|
64
|
+
* Computes inertness of an element based on the `inert` attribute.
|
|
65
|
+
*
|
|
66
|
+
* {@link https://html.spec.whatwg.org/#the-inert-attribute}
|
|
67
|
+
*
|
|
68
|
+
* @privateRemarks
|
|
69
|
+
* According to {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/inert}
|
|
70
|
+
* only open dialogs can escape inertness (except when they have the `inert` attribute).
|
|
71
|
+
*/
|
|
72
|
+
isInert(): boolean;
|
|
63
73
|
protected _inputType: helpers.InputType | undefined;
|
|
64
74
|
protected _displaySize: number | undefined;
|
|
65
75
|
protected _optionsList: Sequence<Element<"option">> | undefined;
|
|
76
|
+
private _isInert;
|
|
66
77
|
/**
|
|
67
78
|
* {@link https://dom.spec.whatwg.org/#dom-slotable-assignedslot}
|
|
68
79
|
*/
|
package/dist/node/element.js
CHANGED
|
@@ -17,7 +17,7 @@ import { Slot } from "./slot.js";
|
|
|
17
17
|
import { Slotable } from "./slotable.js";
|
|
18
18
|
import * as predicate from "./element/predicate.js";
|
|
19
19
|
const { isEmpty } = Iterable;
|
|
20
|
-
const { not } = Predicate;
|
|
20
|
+
const { and, not, or, test } = Predicate;
|
|
21
21
|
/**
|
|
22
22
|
* @public
|
|
23
23
|
*/
|
|
@@ -171,6 +171,30 @@ export class Element extends Node {
|
|
|
171
171
|
}
|
|
172
172
|
return None;
|
|
173
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Computes inertness of an element based on the `inert` attribute.
|
|
176
|
+
*
|
|
177
|
+
* {@link https://html.spec.whatwg.org/#the-inert-attribute}
|
|
178
|
+
*
|
|
179
|
+
* @privateRemarks
|
|
180
|
+
* According to {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/inert}
|
|
181
|
+
* only open dialogs can escape inertness (except when they have the `inert` attribute).
|
|
182
|
+
*/
|
|
183
|
+
isInert() {
|
|
184
|
+
if (this._isInert === undefined) {
|
|
185
|
+
this._isInert = test(or(
|
|
186
|
+
// Explicitly inert;
|
|
187
|
+
Element.hasAttribute("inert"), and(
|
|
188
|
+
// or not an open dialog,
|
|
189
|
+
not(and(Element.hasName("dialog"), Element.hasAttribute("open"))),
|
|
190
|
+
// and with an inert ancestor.
|
|
191
|
+
(element) => element
|
|
192
|
+
.parent(Node.flatTree)
|
|
193
|
+
.filter(Element.isElement)
|
|
194
|
+
.some((parent) => parent.isInert()))), this);
|
|
195
|
+
}
|
|
196
|
+
return this._isInert;
|
|
197
|
+
}
|
|
174
198
|
/*
|
|
175
199
|
* This collects caches for methods that are specific to some kind of elements.
|
|
176
200
|
* The actual methods are declared in element/augment.ts to de-clutter this
|
|
@@ -181,6 +205,7 @@ export class Element extends Node {
|
|
|
181
205
|
_inputType;
|
|
182
206
|
_displaySize;
|
|
183
207
|
_optionsList;
|
|
208
|
+
_isInert;
|
|
184
209
|
/*
|
|
185
210
|
* End of caches for methods specific to some kind of elements.
|
|
186
211
|
*/
|
|
@@ -205,9 +230,7 @@ export class Element extends Node {
|
|
|
205
230
|
.getOr("/");
|
|
206
231
|
path += path === "/" ? "" : "/";
|
|
207
232
|
path += this._name;
|
|
208
|
-
const index = this.
|
|
209
|
-
.filter(Element.isElement)
|
|
210
|
-
.count((element) => element._name === this._name);
|
|
233
|
+
const index = this.index(options, (node) => Element.isElement(node) && node._name === this._name);
|
|
211
234
|
path += `[${index + 1}]`;
|
|
212
235
|
return path;
|
|
213
236
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { Predicate } from "@siteimprove/alfa-predicate";
|
|
2
2
|
import type { Refinement } from "@siteimprove/alfa-refinement";
|
|
3
|
-
import
|
|
3
|
+
import { Sequence } from "@siteimprove/alfa-sequence";
|
|
4
4
|
import { Node } from "../../node.js";
|
|
5
5
|
import { Element } from "../element.js";
|
|
6
|
+
import { Text } from "../text.js";
|
|
6
7
|
/**
|
|
7
8
|
* Get all descendants of a node that satisfy a given refinement.
|
|
8
9
|
*
|
|
@@ -31,4 +32,36 @@ export declare const getElementDescendants: (node: Node, options?: Node.Traversa
|
|
|
31
32
|
* @public
|
|
32
33
|
*/
|
|
33
34
|
export declare function getInclusiveElementDescendants(node: Element, options?: Node.Traversal): Sequence<Element>;
|
|
35
|
+
/**
|
|
36
|
+
* A group of text nodes with an associated label.
|
|
37
|
+
*
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export interface TextGroup {
|
|
41
|
+
label: string;
|
|
42
|
+
text: Sequence<Text>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Options for grouping text descendants.
|
|
46
|
+
*
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
export interface TextGroupOptions<N extends Node = Node> {
|
|
50
|
+
startsGroup: Refinement<Node, N>;
|
|
51
|
+
getLabel: (node: N) => string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get all text descendants of a node, optionally grouping some into labeled groups.
|
|
55
|
+
*
|
|
56
|
+
* @remarks
|
|
57
|
+
* When a descendant matches `startsGroup`, all of its text descendants are collected
|
|
58
|
+
* into a {@link TextGroup} with a label from `getLabel`. Text nodes outside such
|
|
59
|
+
* sub-trees are returned as plain {@link Text} nodes.
|
|
60
|
+
*
|
|
61
|
+
* Groups are not nested: if a `startsGroup` node contains another `startsGroup` node,
|
|
62
|
+
* the inner node's text is included in the outer group, not as a separate group.
|
|
63
|
+
*
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
export declare function getTextDescendants<N extends Node = Node>(textOptions?: TextGroupOptions<N>): (node: Node, options?: Node.Traversal) => Sequence<Text | TextGroup>;
|
|
34
67
|
//# sourceMappingURL=descendants.d.ts.map
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Cache } from "@siteimprove/alfa-cache";
|
|
2
|
+
import { Sequence } from "@siteimprove/alfa-sequence";
|
|
2
3
|
import { Node } from "../../node.js";
|
|
3
4
|
import { Element } from "../element.js";
|
|
5
|
+
import { Text } from "../text.js";
|
|
4
6
|
const _descendantsCache = Cache.empty();
|
|
5
7
|
export function getDescendants(predicate) {
|
|
6
8
|
return (node, options = Node.Traversal.empty) => {
|
|
@@ -23,4 +25,51 @@ export const getElementDescendants = getDescendants(Element.isElement);
|
|
|
23
25
|
export function getInclusiveElementDescendants(node, options = Node.Traversal.empty) {
|
|
24
26
|
return getElementDescendants(node, options).prepend(node);
|
|
25
27
|
}
|
|
28
|
+
const _textCache = Cache.empty();
|
|
29
|
+
const defaultTextOptions = {
|
|
30
|
+
startsGroup: (node) => false,
|
|
31
|
+
getLabel: () => "",
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Get all text descendants of a node, optionally grouping some into labeled groups.
|
|
35
|
+
*
|
|
36
|
+
* @remarks
|
|
37
|
+
* When a descendant matches `startsGroup`, all of its text descendants are collected
|
|
38
|
+
* into a {@link TextGroup} with a label from `getLabel`. Text nodes outside such
|
|
39
|
+
* sub-trees are returned as plain {@link Text} nodes.
|
|
40
|
+
*
|
|
41
|
+
* Groups are not nested: if a `startsGroup` node contains another `startsGroup` node,
|
|
42
|
+
* the inner node's text is included in the outer group, not as a separate group.
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
export function getTextDescendants(textOptions = defaultTextOptions) {
|
|
47
|
+
return (node, options = Node.Traversal.empty) => {
|
|
48
|
+
const optionsMap = _textCache
|
|
49
|
+
.get(textOptions, Cache.empty)
|
|
50
|
+
.get(node, () => []);
|
|
51
|
+
if (optionsMap[options.value] === undefined) {
|
|
52
|
+
optionsMap[options.value] = Sequence.from(_getTextDescendants(node, textOptions, options));
|
|
53
|
+
}
|
|
54
|
+
return optionsMap[options.value];
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function* _getTextDescendants(node, textOptions, traversalOptions) {
|
|
58
|
+
const { startsGroup, getLabel } = textOptions;
|
|
59
|
+
for (const child of node.children(traversalOptions)) {
|
|
60
|
+
if (startsGroup(child)) {
|
|
61
|
+
const groupText = getDescendants(Text.isText)(child, traversalOptions);
|
|
62
|
+
yield {
|
|
63
|
+
label: getLabel(child),
|
|
64
|
+
text: groupText,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
else if (Text.isText(child)) {
|
|
68
|
+
yield child;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
yield* _getTextDescendants(child, textOptions, traversalOptions);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
26
75
|
//# sourceMappingURL=descendants.js.map
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import * as descendants from "./descendants.js";
|
|
2
2
|
import * as elementIdMap from "./element-id-map.js";
|
|
3
|
+
import type { Node } from "../../node.js";
|
|
3
4
|
/**
|
|
4
5
|
* @public
|
|
5
6
|
*/
|
|
6
7
|
export declare namespace Query {
|
|
7
8
|
const getDescendants: typeof descendants.getDescendants;
|
|
8
|
-
const getElementDescendants: (node:
|
|
9
|
-
const getElementIdMap: typeof elementIdMap.getElementIdMap;
|
|
9
|
+
const getElementDescendants: (node: Node, options?: Node.Traversal) => import("@siteimprove/alfa-sequence").Sequence<import("../element.js").Element<string>>;
|
|
10
10
|
const getInclusiveElementDescendants: typeof descendants.getInclusiveElementDescendants;
|
|
11
|
+
const getTextDescendants: typeof descendants.getTextDescendants;
|
|
12
|
+
const getElementIdMap: typeof elementIdMap.getElementIdMap;
|
|
13
|
+
type TextGroup = descendants.TextGroup;
|
|
14
|
+
type TextGroupOptions<N extends Node = Node> = descendants.TextGroupOptions<N>;
|
|
11
15
|
}
|
|
12
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/node/query/index.js
CHANGED
|
@@ -7,7 +7,8 @@ export var Query;
|
|
|
7
7
|
(function (Query) {
|
|
8
8
|
Query.getDescendants = descendants.getDescendants;
|
|
9
9
|
Query.getElementDescendants = descendants.getElementDescendants;
|
|
10
|
-
Query.getElementIdMap = elementIdMap.getElementIdMap;
|
|
11
10
|
Query.getInclusiveElementDescendants = descendants.getInclusiveElementDescendants;
|
|
11
|
+
Query.getTextDescendants = descendants.getTextDescendants;
|
|
12
|
+
Query.getElementIdMap = elementIdMap.getElementIdMap;
|
|
12
13
|
})(Query || (Query = {}));
|
|
13
14
|
//# sourceMappingURL=index.js.map
|
package/dist/node/text.js
CHANGED
|
@@ -44,7 +44,7 @@ export class Text extends Node {
|
|
|
44
44
|
.getOr("/");
|
|
45
45
|
path += path === "/" ? "" : "/";
|
|
46
46
|
path += "text()";
|
|
47
|
-
const index = this.
|
|
47
|
+
const index = this.index(options, Text.isText);
|
|
48
48
|
path += `[${index + 1}]`;
|
|
49
49
|
return path;
|
|
50
50
|
}
|
package/dist/node.d.ts
CHANGED
|
@@ -73,7 +73,7 @@ export interface Node {
|
|
|
73
73
|
last(options?: Node.Traversal): Option<Node>;
|
|
74
74
|
previous(options?: Node.Traversal): Option<Node>;
|
|
75
75
|
next(options?: Node.Traversal): Option<Node>;
|
|
76
|
-
index(options?: Node.Traversal): number;
|
|
76
|
+
index(options?: Node.Traversal, predicate?: Predicate<Node>): number;
|
|
77
77
|
closest<T extends Node>(refinement: Refinement<Node, T>, options?: Node.Traversal): Option<T>;
|
|
78
78
|
closest(predicate: Predicate<Node>, options?: Node.Traversal): Option<Node>;
|
|
79
79
|
}
|
package/dist/node.js
CHANGED
|
@@ -183,13 +183,10 @@ export class Node extends tree.Node {
|
|
|
183
183
|
// we accept the risk of caching the value assuming that it will only be
|
|
184
184
|
// computed on fully frozen trees.
|
|
185
185
|
path(options = Node.Traversal.empty) {
|
|
186
|
-
if (this._path[options.value]
|
|
187
|
-
return this._path[options.value];
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
186
|
+
if (this._path[options.value] == undefined) {
|
|
190
187
|
this._path[options.value] = this._internalPath(options);
|
|
191
|
-
return this._internalPath(options);
|
|
192
188
|
}
|
|
189
|
+
return this._path[options.value];
|
|
193
190
|
}
|
|
194
191
|
equals(value) {
|
|
195
192
|
return value === this;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "http://json.schemastore.org/package",
|
|
3
3
|
"name": "@siteimprove/alfa-dom",
|
|
4
4
|
"homepage": "https://alfa.siteimprove.com",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.110.0",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"description": "Implementations of the core DOM and CSSOM node types",
|
|
8
8
|
"repository": {
|
|
@@ -35,37 +35,37 @@
|
|
|
35
35
|
"dist/**/*.d.ts"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@siteimprove/alfa-array": "^0.
|
|
39
|
-
"@siteimprove/alfa-cache": "^0.
|
|
40
|
-
"@siteimprove/alfa-comparable": "^0.
|
|
41
|
-
"@siteimprove/alfa-css": "^0.
|
|
42
|
-
"@siteimprove/alfa-css-feature": "^0.
|
|
43
|
-
"@siteimprove/alfa-device": "^0.
|
|
44
|
-
"@siteimprove/alfa-earl": "^0.
|
|
45
|
-
"@siteimprove/alfa-equatable": "^0.
|
|
46
|
-
"@siteimprove/alfa-flags": "^0.
|
|
47
|
-
"@siteimprove/alfa-iterable": "^0.
|
|
48
|
-
"@siteimprove/alfa-json": "^0.
|
|
49
|
-
"@siteimprove/alfa-lazy": "^0.
|
|
50
|
-
"@siteimprove/alfa-map": "^0.
|
|
51
|
-
"@siteimprove/alfa-option": "^0.
|
|
52
|
-
"@siteimprove/alfa-parser": "^0.
|
|
53
|
-
"@siteimprove/alfa-predicate": "^0.
|
|
54
|
-
"@siteimprove/alfa-rectangle": "^0.
|
|
55
|
-
"@siteimprove/alfa-refinement": "^0.
|
|
56
|
-
"@siteimprove/alfa-result": "^0.
|
|
57
|
-
"@siteimprove/alfa-sarif": "^0.
|
|
58
|
-
"@siteimprove/alfa-selective": "^0.
|
|
59
|
-
"@siteimprove/alfa-sequence": "^0.
|
|
60
|
-
"@siteimprove/alfa-slice": "^0.
|
|
61
|
-
"@siteimprove/alfa-string": "^0.
|
|
62
|
-
"@siteimprove/alfa-trampoline": "^0.
|
|
63
|
-
"@siteimprove/alfa-tree": "^0.
|
|
38
|
+
"@siteimprove/alfa-array": "^0.110.0",
|
|
39
|
+
"@siteimprove/alfa-cache": "^0.110.0",
|
|
40
|
+
"@siteimprove/alfa-comparable": "^0.110.0",
|
|
41
|
+
"@siteimprove/alfa-css": "^0.110.0",
|
|
42
|
+
"@siteimprove/alfa-css-feature": "^0.110.0",
|
|
43
|
+
"@siteimprove/alfa-device": "^0.110.0",
|
|
44
|
+
"@siteimprove/alfa-earl": "^0.110.0",
|
|
45
|
+
"@siteimprove/alfa-equatable": "^0.110.0",
|
|
46
|
+
"@siteimprove/alfa-flags": "^0.110.0",
|
|
47
|
+
"@siteimprove/alfa-iterable": "^0.110.0",
|
|
48
|
+
"@siteimprove/alfa-json": "^0.110.0",
|
|
49
|
+
"@siteimprove/alfa-lazy": "^0.110.0",
|
|
50
|
+
"@siteimprove/alfa-map": "^0.110.0",
|
|
51
|
+
"@siteimprove/alfa-option": "^0.110.0",
|
|
52
|
+
"@siteimprove/alfa-parser": "^0.110.0",
|
|
53
|
+
"@siteimprove/alfa-predicate": "^0.110.0",
|
|
54
|
+
"@siteimprove/alfa-rectangle": "^0.110.0",
|
|
55
|
+
"@siteimprove/alfa-refinement": "^0.110.0",
|
|
56
|
+
"@siteimprove/alfa-result": "^0.110.0",
|
|
57
|
+
"@siteimprove/alfa-sarif": "^0.110.0",
|
|
58
|
+
"@siteimprove/alfa-selective": "^0.110.0",
|
|
59
|
+
"@siteimprove/alfa-sequence": "^0.110.0",
|
|
60
|
+
"@siteimprove/alfa-slice": "^0.110.0",
|
|
61
|
+
"@siteimprove/alfa-string": "^0.110.0",
|
|
62
|
+
"@siteimprove/alfa-trampoline": "^0.110.0",
|
|
63
|
+
"@siteimprove/alfa-tree": "^0.110.0"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@siteimprove/alfa-test": "^0.
|
|
66
|
+
"@siteimprove/alfa-test": "^0.110.0",
|
|
67
67
|
"@types/jsdom": "^27.0.0",
|
|
68
|
-
"jsdom": "^27.
|
|
68
|
+
"jsdom": "^27.4.0"
|
|
69
69
|
},
|
|
70
70
|
"publishConfig": {
|
|
71
71
|
"access": "public",
|