@siteimprove/alfa-dom 0.99.0 → 0.100.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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # @siteimprove/alfa-dom
2
2
 
3
+ ## 0.100.0
4
+
5
+ ### Minor Changes
6
+
7
+ - **Breaking:** The `hasBox` predicate has been moved from `Element` to `Node`. ([#1768](https://github.com/Siteimprove/alfa/pull/1768))
8
+
9
+ To migrate, replace `Element.hasBox` with `Node.hasBox`.
10
+ If `Node` is not imported, add it to the import statement:
11
+
12
+ ```
13
+ import { Element, Node } from "@siteimprove/alfa-dom";
14
+ ```
15
+
16
+ - **Added:** `Text.of` now accepts `Option<Rectangle>` and `Option<Device>`. A rectangle can also be passed through the `box` JSON property when using `Text.fromText`. ([#1768](https://github.com/Siteimprove/alfa/pull/1768))
17
+
18
+ The rectangle represents the layout of the text node. If a rectangle is passed in, a device must be be supplied, otherwise the rectangle won't be set.
19
+
3
20
  ## 0.99.0
4
21
 
5
22
  ### Minor Changes
package/dist/h.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Device } from "@siteimprove/alfa-device";
2
2
  import type { Rectangle } from "@siteimprove/alfa-rectangle";
3
3
  import type { Node, Rule } from "./index.js";
4
- import { Attribute, Block, Declaration, Document, Element, FontFaceRule, Fragment, ImportRule, Layer, KeyframeRule, KeyframesRule, MediaRule, Namespace, NamespaceRule, PageRule, Shadow, Sheet, StyleRule, SupportsRule, Text, Type } from "./index.js";
4
+ import { Attribute, Block, Declaration, Document, Element, FontFaceRule, Fragment, ImportRule, KeyframeRule, KeyframesRule, Layer, MediaRule, Namespace, NamespaceRule, PageRule, Shadow, Sheet, StyleRule, SupportsRule, Text, Type } from "./index.js";
5
5
  /**
6
6
  * @public
7
7
  */
@@ -12,7 +12,7 @@ export declare function h<N extends string = string>(name: N, attributes?: Array
12
12
  export declare namespace h {
13
13
  function element<N extends string = string>(name: N, attributes?: Array<Attribute> | Record<string, string | boolean>, children?: Array<Node | string>, style?: Array<Declaration> | Record<string, string>, namespace?: Namespace, box?: Rectangle, device?: Device, externalId?: string, internalId?: string, extraData?: any): Element<N>;
14
14
  function attribute<N extends string = string>(name: N, value: string, externalId?: string, internalId?: string, extraData?: any): Attribute<N>;
15
- function text(data: string, externalId?: string, internalId?: string, extraData?: any): Text;
15
+ function text(data: string, box?: Rectangle, device?: Device, externalId?: string, internalId?: string, extraData?: any): Text;
16
16
  function document(children: Array<Node | string>, style?: Array<Sheet>, externalId?: string, internalId?: string, extraData?: any): Document;
17
17
  function shadow(children: Array<Node | string>, style?: Array<Sheet>, mode?: Shadow.Mode, externalId?: string, internalId?: string, extraData?: any): Shadow;
18
18
  function type<N extends string = string>(name: N, publicId?: string, systemId?: string, externalId?: string, internalId?: string, extraData?: any): Type<N>;
package/dist/h.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { None, Option } from "@siteimprove/alfa-option";
2
2
  import { Predicate } from "@siteimprove/alfa-predicate";
3
3
  import { Device } from "@siteimprove/alfa-device";
4
- import { Attribute, Block, Declaration, Document, Element, FontFaceRule, Fragment, ImportRule, Layer, KeyframeRule, KeyframesRule, MediaRule, Namespace, NamespaceRule, PageRule, Shadow, Sheet, StyleRule, SupportsRule, Text, Type, } from "./index.js";
4
+ import { Attribute, Block, Declaration, Document, Element, FontFaceRule, Fragment, ImportRule, KeyframeRule, KeyframesRule, Layer, MediaRule, Namespace, NamespaceRule, PageRule, Shadow, Sheet, StyleRule, SupportsRule, Text, Type, } from "./index.js";
5
5
  const { entries } = Object;
6
6
  const { nor } = Predicate;
7
7
  /**
@@ -57,8 +57,8 @@ export function h(name, attributes, children, style, box, device = Device.standa
57
57
  return Attribute.of(None, None, name, value, externalId, internalId, extraData);
58
58
  }
59
59
  h.attribute = attribute;
60
- function text(data, externalId, internalId, extraData) {
61
- return Text.of(data, externalId, internalId, extraData);
60
+ function text(data, box, device, externalId, internalId, extraData) {
61
+ return Text.of(data, Option.from(box), Option.from(device), externalId, internalId, extraData);
62
62
  }
63
63
  h.text = text;
64
64
  function document(children, style, externalId, internalId, extraData) {
package/dist/native.js CHANGED
@@ -6,6 +6,7 @@ export var Native;
6
6
  (function (Native) {
7
7
  async function fromNode(node = globalThis.window.document, options) {
8
8
  const { withCrossOrigin = false } = options ?? {};
9
+ const range = globalThis.document.createRange(); // Used by toText - the same instance can be reused for each text node.
9
10
  return toNode(node);
10
11
  async function toNode(node) {
11
12
  switch (node.nodeType) {
@@ -52,9 +53,16 @@ export var Native;
52
53
  };
53
54
  }
54
55
  function toText(text) {
56
+ range.selectNode(text);
55
57
  return {
56
58
  type: "text",
57
59
  data: text.data,
60
+ box:
61
+ // Not all execution environments have layout, e.g. JSDOM:
62
+ // https://github.com/jsdom/jsdom/pull/2719#issuecomment-590145974
63
+ range.getBoundingClientRect !== undefined
64
+ ? toRectangle(range.getBoundingClientRect())
65
+ : null,
58
66
  };
59
67
  }
60
68
  function toComment(comment) {
@@ -1,5 +1,4 @@
1
1
  export * from "./predicate/has-attribute.js";
2
- export * from "./predicate/has-box.js";
3
2
  export * from "./predicate/has-display-size.js";
4
3
  export * from "./predicate/has-id.js";
5
4
  export * from "./predicate/has-input-type.js";
@@ -7,14 +6,14 @@ export * from "./predicate/has-name.js";
7
6
  export * from "./predicate/has-namespace.js";
8
7
  export * from "./predicate/has-tab-index.js";
9
8
  export * from "./predicate/has-unique-id.js";
9
+ export * from "./predicate/is-actually-disabled.js";
10
10
  export * from "./predicate/is-browsing-context-container.js";
11
11
  export * from "./predicate/is-content.js";
12
- export * from "./predicate/is-actually-disabled.js";
13
12
  export * from "./predicate/is-document-element.js";
14
13
  export * from "./predicate/is-draggable.js";
15
14
  export * from "./predicate/is-editing-host.js";
16
15
  export * from "./predicate/is-fallback.js";
16
+ export * from "./predicate/is-replaced.js";
17
17
  export * from "./predicate/is-scoped-to.js";
18
18
  export * from "./predicate/is-suggested-focusable.js";
19
- export * from "./predicate/is-replaced.js";
20
19
  //# sourceMappingURL=predicate.d.ts.map
@@ -1,5 +1,4 @@
1
1
  export * from "./predicate/has-attribute.js";
2
- export * from "./predicate/has-box.js";
3
2
  export * from "./predicate/has-display-size.js";
4
3
  export * from "./predicate/has-id.js";
5
4
  export * from "./predicate/has-input-type.js";
@@ -7,14 +6,14 @@ export * from "./predicate/has-name.js";
7
6
  export * from "./predicate/has-namespace.js";
8
7
  export * from "./predicate/has-tab-index.js";
9
8
  export * from "./predicate/has-unique-id.js";
9
+ export * from "./predicate/is-actually-disabled.js";
10
10
  export * from "./predicate/is-browsing-context-container.js";
11
11
  export * from "./predicate/is-content.js";
12
- export * from "./predicate/is-actually-disabled.js";
13
12
  export * from "./predicate/is-document-element.js";
14
13
  export * from "./predicate/is-draggable.js";
15
14
  export * from "./predicate/is-editing-host.js";
16
15
  export * from "./predicate/is-fallback.js";
16
+ export * from "./predicate/is-replaced.js";
17
17
  export * from "./predicate/is-scoped-to.js";
18
18
  export * from "./predicate/is-suggested-focusable.js";
19
- export * from "./predicate/is-replaced.js";
20
19
  //# sourceMappingURL=predicate.js.map
@@ -119,7 +119,7 @@ export declare namespace Element {
119
119
  * @internal
120
120
  */
121
121
  function cloneElement(options: Node.ElementReplacementOptions, device?: Device): (element: Element) => Trampoline<Element>;
122
- const hasAttribute: typeof predicate.hasAttribute, hasBox: typeof predicate.hasBox, hasDisplaySize: typeof predicate.hasDisplaySize, hasId: typeof predicate.hasId, hasInputType: typeof predicate.hasInputType, hasName: typeof predicate.hasName, hasNamespace: typeof predicate.hasNamespace, hasTabIndex: typeof predicate.hasTabIndex, hasUniqueId: Predicate<Element<string>>, isBrowsingContextContainer: typeof predicate.isBrowsingContextContainer, isContent: typeof predicate.isContent, isActuallyDisabled: typeof predicate.isActuallyDisabled, isDocumentElement: typeof predicate.isDocumentElement, isDraggable: typeof predicate.isDraggable, isEditingHost: typeof predicate.isEditingHost, isFallback: typeof predicate.isFallback, isScopedTo: typeof predicate.isScopedTo, isSuggestedFocusable: typeof predicate.isSuggestedFocusable, isReplaced: typeof predicate.isReplaced;
122
+ const hasAttribute: typeof predicate.hasAttribute, hasDisplaySize: typeof predicate.hasDisplaySize, hasId: typeof predicate.hasId, hasInputType: typeof predicate.hasInputType, hasName: typeof predicate.hasName, hasNamespace: typeof predicate.hasNamespace, hasTabIndex: typeof predicate.hasTabIndex, hasUniqueId: Predicate<Element<string>>, isBrowsingContextContainer: typeof predicate.isBrowsingContextContainer, isContent: typeof predicate.isContent, isActuallyDisabled: typeof predicate.isActuallyDisabled, isDocumentElement: typeof predicate.isDocumentElement, isDraggable: typeof predicate.isDraggable, isEditingHost: typeof predicate.isEditingHost, isFallback: typeof predicate.isFallback, isScopedTo: typeof predicate.isScopedTo, isSuggestedFocusable: typeof predicate.isSuggestedFocusable, isReplaced: typeof predicate.isReplaced;
123
123
  type InputType = helpers.InputType;
124
124
  }
125
125
  //# sourceMappingURL=element.d.ts.map
@@ -336,6 +336,6 @@ export class Element extends Node {
336
336
  });
337
337
  }
338
338
  Element.cloneElement = cloneElement;
339
- Element.hasAttribute = predicate.hasAttribute, Element.hasBox = predicate.hasBox, Element.hasDisplaySize = predicate.hasDisplaySize, Element.hasId = predicate.hasId, Element.hasInputType = predicate.hasInputType, Element.hasName = predicate.hasName, Element.hasNamespace = predicate.hasNamespace, Element.hasTabIndex = predicate.hasTabIndex, Element.hasUniqueId = predicate.hasUniqueId, Element.isBrowsingContextContainer = predicate.isBrowsingContextContainer, Element.isContent = predicate.isContent, Element.isActuallyDisabled = predicate.isActuallyDisabled, Element.isDocumentElement = predicate.isDocumentElement, Element.isDraggable = predicate.isDraggable, Element.isEditingHost = predicate.isEditingHost, Element.isFallback = predicate.isFallback, Element.isScopedTo = predicate.isScopedTo, Element.isSuggestedFocusable = predicate.isSuggestedFocusable, Element.isReplaced = predicate.isReplaced;
339
+ Element.hasAttribute = predicate.hasAttribute, Element.hasDisplaySize = predicate.hasDisplaySize, Element.hasId = predicate.hasId, Element.hasInputType = predicate.hasInputType, Element.hasName = predicate.hasName, Element.hasNamespace = predicate.hasNamespace, Element.hasTabIndex = predicate.hasTabIndex, Element.hasUniqueId = predicate.hasUniqueId, Element.isBrowsingContextContainer = predicate.isBrowsingContextContainer, Element.isContent = predicate.isContent, Element.isActuallyDisabled = predicate.isActuallyDisabled, Element.isDocumentElement = predicate.isDocumentElement, Element.isDraggable = predicate.isDraggable, Element.isEditingHost = predicate.isEditingHost, Element.isFallback = predicate.isFallback, Element.isScopedTo = predicate.isScopedTo, Element.isSuggestedFocusable = predicate.isSuggestedFocusable, Element.isReplaced = predicate.isReplaced;
340
340
  })(Element || (Element = {}));
341
341
  //# sourceMappingURL=element.js.map
@@ -1,9 +1,10 @@
1
1
  import type { Device } from "@siteimprove/alfa-device";
2
2
  import type { Predicate } from "@siteimprove/alfa-predicate";
3
3
  import type { Rectangle } from "@siteimprove/alfa-rectangle";
4
- import type { Element } from "../../element.js";
4
+ import type { Element } from "../element.js";
5
+ import type { Text } from "../text.js";
5
6
  /**
6
7
  * @public
7
8
  */
8
- export declare function hasBox(predicate: Predicate<Rectangle> | undefined, device: Device): Predicate<Element>;
9
+ export declare function hasBox(predicate: Predicate<Rectangle> | undefined, device: Device): Predicate<Element | Text>;
9
10
  //# sourceMappingURL=has-box.d.ts.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @public
3
+ */
4
+ export function hasBox(predicate = () => true, device) {
5
+ return (node) => node.getBoundingBox(device).some(predicate);
6
+ }
7
+ //# sourceMappingURL=has-box.js.map
@@ -1,3 +1,4 @@
1
+ export * from "./predicate/has-box.js";
1
2
  export * from "./predicate/has-child.js";
2
3
  export * from "./predicate/has-descendant.js";
3
4
  export * from "./predicate/has-inclusive-descendant.js";
@@ -1,3 +1,4 @@
1
+ export * from "./predicate/has-box.js";
1
2
  export * from "./predicate/has-child.js";
2
3
  export * from "./predicate/has-descendant.js";
3
4
  export * from "./predicate/has-inclusive-descendant.js";
@@ -1,4 +1,6 @@
1
- import type { Option } from "@siteimprove/alfa-option";
1
+ import type { Device } from "@siteimprove/alfa-device";
2
+ import { Option } from "@siteimprove/alfa-option";
3
+ import { Rectangle } from "@siteimprove/alfa-rectangle";
2
4
  import { Trampoline } from "@siteimprove/alfa-trampoline";
3
5
  import * as json from "@siteimprove/alfa-json";
4
6
  import { Node } from "../node.js";
@@ -8,12 +10,14 @@ import { Slotable } from "./slotable.js";
8
10
  * @public
9
11
  */
10
12
  export declare class Text extends Node<"text"> implements Slotable {
11
- static of(data: string, externalId?: string, internalId?: string, extraData?: any): Text;
13
+ static of(data: string, box: Option<Rectangle>, device: Option<Device>, externalId?: string, internalId?: string, extraData?: any): Text;
12
14
  static empty(): Text;
13
15
  private readonly _data;
14
- protected constructor(data: string, externalId?: string, internalId?: string, extraData?: any);
16
+ private readonly _boxes;
17
+ protected constructor(data: string, box: Option<Rectangle>, device: Option<Device>, externalId?: string, internalId?: string, extraData?: any);
15
18
  get data(): string;
16
19
  assignedSlot(): Option<Slot>;
20
+ getBoundingBox(device: Device): Option<Rectangle>;
17
21
  /**
18
22
  * @internal
19
23
  **/
@@ -32,15 +36,16 @@ export declare namespace Text {
32
36
  }
33
37
  interface JSON extends Node.JSON<"text"> {
34
38
  data: string;
39
+ box: Rectangle.JSON | null;
35
40
  }
36
41
  function isText(value: unknown): value is Text;
37
42
  /**
38
43
  * @internal
39
44
  */
40
- function fromText(json: JSON): Trampoline<Text>;
45
+ function fromText(json: JSON, device?: Device): Trampoline<Text>;
41
46
  /**
42
47
  * @internal
43
48
  */
44
- function cloneText(text: Text): Trampoline<Text>;
49
+ function cloneText(device?: Device): (text: Text) => Trampoline<Text>;
45
50
  }
46
51
  //# sourceMappingURL=text.d.ts.map
package/dist/node/text.js CHANGED
@@ -1,3 +1,6 @@
1
+ import { Cache } from "@siteimprove/alfa-cache";
2
+ import { None, Option } from "@siteimprove/alfa-option";
3
+ import { Rectangle } from "@siteimprove/alfa-rectangle";
1
4
  import { Trampoline } from "@siteimprove/alfa-trampoline";
2
5
  import * as json from "@siteimprove/alfa-json";
3
6
  import { Node } from "../node.js";
@@ -6,16 +9,18 @@ import { Slotable } from "./slotable.js";
6
9
  * @public
7
10
  */
8
11
  export class Text extends Node {
9
- static of(data, externalId, internalId, extraData) {
10
- return new Text(data, externalId, internalId, extraData);
12
+ static of(data, box, device, externalId, internalId, extraData) {
13
+ return new Text(data, box, device, externalId, internalId, extraData);
11
14
  }
12
15
  static empty() {
13
- return new Text("");
16
+ return new Text("", None, None);
14
17
  }
15
18
  _data;
16
- constructor(data, externalId, internalId, extraData) {
19
+ _boxes;
20
+ constructor(data, box, device, externalId, internalId, extraData) {
17
21
  super([], "text", externalId, internalId, extraData);
18
22
  this._data = data;
23
+ this._boxes = Cache.from(device.isSome() && box.isSome() ? [[device.get(), box.get()]] : []);
19
24
  }
20
25
  get data() {
21
26
  return this._data;
@@ -23,6 +28,9 @@ export class Text extends Node {
23
28
  assignedSlot() {
24
29
  return Slotable.findSlot(this);
25
30
  }
31
+ getBoundingBox(device) {
32
+ return this._boxes.get(device);
33
+ }
26
34
  /**
27
35
  * @internal
28
36
  **/
@@ -46,6 +54,13 @@ export class Text extends Node {
46
54
  return result;
47
55
  }
48
56
  result.data = this.data;
57
+ result.box =
58
+ options?.device === undefined
59
+ ? null
60
+ : this._boxes
61
+ .get(options.device)
62
+ .map((box) => box.toJSON())
63
+ .getOr(null);
49
64
  return result;
50
65
  }
51
66
  toString() {
@@ -68,15 +83,15 @@ export class Text extends Node {
68
83
  /**
69
84
  * @internal
70
85
  */
71
- function fromText(json) {
72
- return Trampoline.done(Text.of(json.data, json.externalId, undefined, json.internalId));
86
+ function fromText(json, device) {
87
+ return Trampoline.done(Text.of(json.data, Option.from(json.box).map(Rectangle.from), Option.from(device), json.externalId, undefined, json.internalId));
73
88
  }
74
89
  Text.fromText = fromText;
75
90
  /**
76
91
  * @internal
77
92
  */
78
- function cloneText(text) {
79
- return Trampoline.done(Text.of(text.data, text.externalId, text.extraData, text.internalId));
93
+ function cloneText(device) {
94
+ return (text) => Trampoline.done(Text.of(text.data, Option.from(device).flatMap((d) => text.getBoundingBox(d)), Option.from(device), text.externalId, text.extraData, text.internalId));
80
95
  }
81
96
  Text.cloneText = cloneText;
82
97
  })(Text || (Text = {}));
package/dist/node.d.ts CHANGED
@@ -16,7 +16,7 @@ import * as traversal from "./node/traversal.js";
16
16
  /**
17
17
  * @public
18
18
  */
19
- export declare abstract class Node<T extends string = string> extends tree.Node<Node.Traversal.Flag, T> implements earl.Serializable<Node.EARL>, json.Serializable<tree.Node.JSON<T>>, sarif.Serializable<sarif.Location> {
19
+ export declare abstract class Node<T extends string = string> extends tree.Node<"DOM traversal", Node.TraversalFlags, T> implements earl.Serializable<Node.EARL>, json.Serializable<tree.Node.JSON<T>>, sarif.Serializable<sarif.Location> {
20
20
  protected constructor(children: Array<Node>, type: T, externalId?: string, internalId?: string, extraData?: any);
21
21
  /**
22
22
  * {@link https://dom.spec.whatwg.org/#concept-descendant-text-content}
@@ -103,48 +103,148 @@ export declare namespace Node {
103
103
  };
104
104
  }
105
105
  function isNode(value: unknown): value is Node;
106
- class Traversal extends Flags<Traversal.Flag> {
107
- static of(...flags: Array<Traversal.Flag>): Traversal;
108
- }
109
- namespace Traversal {
110
- type Flag = 0 | 1 | 2 | 4;
111
- const none: Flag;
112
- /**
113
- * When set, traverse the node in shadow-including tree order.
114
- *
115
- * {@link https://dom.spec.whatwg.org/#concept-shadow-including-tree-order}
116
- */
117
- const composed: Flag;
118
- /**
119
- * When set, traverse the flattened element tree rooted at the node.
120
- *
121
- * {@link https://drafts.csswg.org/css-scoping/#flat-tree}
122
- */
123
- const flattened: Flag;
124
- /**
125
- * When set, traverse all nested browsing contexts encountered.
126
- *
127
- * {@link https://html.spec.whatwg.org/#nested-browsing-context}
128
- */
129
- const nested: Flag;
130
- const empty: Traversal;
131
- }
106
+ const Traversal: {
107
+ of: (...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">) => {
108
+ has(flag: 0 | 1 | 2 | 4 | "composed" | "flattened" | "nested"): boolean;
109
+ isSet: (flag: 0 | 1 | 2 | 4 | "composed" | "flattened" | "nested") => boolean;
110
+ add(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): any;
111
+ set: (...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">) => any;
112
+ remove(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): any;
113
+ unset: (...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">) => any;
114
+ is(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): boolean;
115
+ equals(value: any): boolean;
116
+ equals(value: unknown): value is any;
117
+ toString(): string;
118
+ toJSON(): Flags.JSON<"DOM traversal"> & {
119
+ composed: boolean;
120
+ flattened: boolean;
121
+ nested: boolean;
122
+ };
123
+ readonly value: number;
124
+ readonly kind: "DOM traversal";
125
+ } & {
126
+ composed: boolean;
127
+ flattened: boolean;
128
+ nested: boolean;
129
+ };
130
+ readonly none: 0;
131
+ readonly empty: {
132
+ has(flag: 0 | 1 | 2 | 4 | "composed" | "flattened" | "nested"): boolean;
133
+ isSet: (flag: 0 | 1 | 2 | 4 | "composed" | "flattened" | "nested") => boolean;
134
+ add(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): any;
135
+ set: (...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">) => any;
136
+ remove(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): any;
137
+ unset: (...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">) => any;
138
+ is(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): boolean;
139
+ equals(value: any): boolean;
140
+ equals(value: unknown): value is any;
141
+ toString(): string;
142
+ toJSON(): Flags.JSON<"DOM traversal"> & {
143
+ composed: boolean;
144
+ flattened: boolean;
145
+ nested: boolean;
146
+ };
147
+ readonly value: number;
148
+ readonly kind: "DOM traversal";
149
+ } & {
150
+ composed: boolean;
151
+ flattened: boolean;
152
+ nested: boolean;
153
+ };
154
+ readonly allFlags: [1, 2, 4];
155
+ nameOf: (flag: 1 | 2 | 4) => "composed" | "flattened" | "nested";
156
+ reduce: (...flags: import("@siteimprove/alfa-array").Array<number>) => number;
157
+ named: <K extends string, A extends import("@siteimprove/alfa-array").Array<string>>(kind: K, ...flags: A) => {
158
+ [x: string]: any;
159
+ };
160
+ composed: 1 | 2 | 4;
161
+ flattened: 1 | 2 | 4;
162
+ nested: 1 | 2 | 4;
163
+ };
164
+ type Traversal = ReturnType<(typeof Traversal)["of"]>;
165
+ type TraversalFlags = (typeof Node.Traversal.allFlags)[number];
132
166
  /**
133
167
  * Traversal options to traverse the flat tree.
134
168
  *
135
169
  * {@link https://drafts.csswg.org/css-scoping-1/#flattening}
136
170
  */
137
- const flatTree: Traversal;
171
+ const flatTree: {
172
+ has(flag: 0 | 1 | 2 | 4 | "composed" | "flattened" | "nested"): boolean;
173
+ isSet: (flag: 0 | 1 | 2 | 4 | "composed" | "flattened" | "nested") => boolean;
174
+ add(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): any;
175
+ set: (...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">) => any;
176
+ remove(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): any;
177
+ unset: (...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">) => any;
178
+ is(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): boolean;
179
+ equals(value: any): boolean;
180
+ equals(value: unknown): value is any;
181
+ toString(): string;
182
+ toJSON(): Flags.JSON<"DOM traversal"> & {
183
+ composed: boolean;
184
+ flattened: boolean;
185
+ nested: boolean;
186
+ };
187
+ readonly value: number;
188
+ readonly kind: "DOM traversal";
189
+ } & {
190
+ composed: boolean;
191
+ flattened: boolean;
192
+ nested: boolean;
193
+ };
138
194
  /**
139
195
  * Traversal options to traverse all relevant nodes (flat tree and inside
140
196
  * nested browsing container), a very frequent use case.
141
197
  */
142
- const fullTree: Traversal;
198
+ const fullTree: {
199
+ has(flag: 0 | 1 | 2 | 4 | "composed" | "flattened" | "nested"): boolean;
200
+ isSet: (flag: 0 | 1 | 2 | 4 | "composed" | "flattened" | "nested") => boolean;
201
+ add(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): any;
202
+ set: (...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">) => any;
203
+ remove(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): any;
204
+ unset: (...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">) => any;
205
+ is(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): boolean;
206
+ equals(value: any): boolean;
207
+ equals(value: unknown): value is any;
208
+ toString(): string;
209
+ toJSON(): Flags.JSON<"DOM traversal"> & {
210
+ composed: boolean;
211
+ flattened: boolean;
212
+ nested: boolean;
213
+ };
214
+ readonly value: number;
215
+ readonly kind: "DOM traversal";
216
+ } & {
217
+ composed: boolean;
218
+ flattened: boolean;
219
+ nested: boolean;
220
+ };
143
221
  /**
144
222
  * Traversal options to traverse in shadow-including tree order and inside
145
223
  * nested browsing context container, a common use case.
146
224
  */
147
- const composedNested: Traversal;
225
+ const composedNested: {
226
+ has(flag: 0 | 1 | 2 | 4 | "composed" | "flattened" | "nested"): boolean;
227
+ isSet: (flag: 0 | 1 | 2 | 4 | "composed" | "flattened" | "nested") => boolean;
228
+ add(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): any;
229
+ set: (...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">) => any;
230
+ remove(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): any;
231
+ unset: (...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">) => any;
232
+ is(...flags: import("@siteimprove/alfa-array").Array<0 | 1 | 2 | 4 | "composed" | "flattened" | "nested">): boolean;
233
+ equals(value: any): boolean;
234
+ equals(value: unknown): value is any;
235
+ toString(): string;
236
+ toJSON(): Flags.JSON<"DOM traversal"> & {
237
+ composed: boolean;
238
+ flattened: boolean;
239
+ nested: boolean;
240
+ };
241
+ readonly value: number;
242
+ readonly kind: "DOM traversal";
243
+ } & {
244
+ composed: boolean;
245
+ flattened: boolean;
246
+ nested: boolean;
247
+ };
148
248
  function from(json: Element.JSON, device?: Device): Element;
149
249
  function from(json: Attribute.JSON, device?: Device): Attribute;
150
250
  function from(json: Text.JSON, device?: Device): Text;
@@ -261,6 +361,6 @@ export declare namespace Node {
261
361
  */
262
362
  function cloneNode(node: Node, options?: ElementReplacementOptions, device?: Device): Trampoline<Node>;
263
363
  const getNodesBetween: typeof traversal.getNodesBetween;
264
- const hasChild: typeof predicate.hasChild, hasDescendant: typeof predicate.hasDescendant, hasInclusiveDescendant: typeof predicate.hasInclusiveDescendant, hasTextContent: typeof predicate.hasTextContent, isRoot: typeof predicate.isRoot;
364
+ const hasBox: typeof predicate.hasBox, hasChild: typeof predicate.hasChild, hasDescendant: typeof predicate.hasDescendant, hasInclusiveDescendant: typeof predicate.hasInclusiveDescendant, hasTextContent: typeof predicate.hasTextContent, isRoot: typeof predicate.isRoot;
265
365
  }
266
366
  //# sourceMappingURL=node.d.ts.map
package/dist/node.js CHANGED
@@ -236,50 +236,23 @@ export class Node extends tree.Node {
236
236
  return value instanceof Node;
237
237
  }
238
238
  Node.isNode = isNode;
239
- class Traversal extends Flags {
240
- static of(...flags) {
241
- return new Traversal(Flags._reduce(...flags));
242
- }
243
- }
244
- Node.Traversal = Traversal;
245
- (function (Traversal) {
246
- Traversal.none = 0;
247
- /**
248
- * When set, traverse the node in shadow-including tree order.
249
- *
250
- * {@link https://dom.spec.whatwg.org/#concept-shadow-including-tree-order}
251
- */
252
- Traversal.composed = (1 << 0);
253
- /**
254
- * When set, traverse the flattened element tree rooted at the node.
255
- *
256
- * {@link https://drafts.csswg.org/css-scoping/#flat-tree}
257
- */
258
- Traversal.flattened = (1 << 1);
259
- /**
260
- * When set, traverse all nested browsing contexts encountered.
261
- *
262
- * {@link https://html.spec.whatwg.org/#nested-browsing-context}
263
- */
264
- Traversal.nested = (1 << 2);
265
- Traversal.empty = Traversal.of(Traversal.none);
266
- })(Traversal = Node.Traversal || (Node.Traversal = {}));
239
+ Node.Traversal = Flags.named("DOM traversal", "composed", "flattened", "nested");
267
240
  /**
268
241
  * Traversal options to traverse the flat tree.
269
242
  *
270
243
  * {@link https://drafts.csswg.org/css-scoping-1/#flattening}
271
244
  */
272
- Node.flatTree = Traversal.of(Traversal.flattened);
245
+ Node.flatTree = Node.Traversal.of("flattened");
273
246
  /**
274
247
  * Traversal options to traverse all relevant nodes (flat tree and inside
275
248
  * nested browsing container), a very frequent use case.
276
249
  */
277
- Node.fullTree = Traversal.of(Traversal.flattened, Traversal.nested);
250
+ Node.fullTree = Node.Traversal.of("flattened", "nested");
278
251
  /**
279
252
  * Traversal options to traverse in shadow-including tree order and inside
280
253
  * nested browsing context container, a common use case.
281
254
  */
282
- Node.composedNested = Traversal.of(Traversal.composed, Traversal.nested);
255
+ Node.composedNested = Node.Traversal.of("composed", "nested");
283
256
  const cacheWithDevice = Cache.empty();
284
257
  const cacheWithoutDevice = Cache.empty();
285
258
  function from(json, device) {
@@ -300,7 +273,7 @@ export class Node extends tree.Node {
300
273
  case "attribute":
301
274
  return Attribute.fromAttribute(json);
302
275
  case "text":
303
- return Text.fromText(json);
276
+ return Text.fromText(json, device);
304
277
  case "comment":
305
278
  return Comment.fromComment(json);
306
279
  case "document":
@@ -328,7 +301,7 @@ export class Node extends tree.Node {
328
301
  return Selective.of(node)
329
302
  .if(Element.isElement, Element.cloneElement(options, device))
330
303
  .if(Attribute.isAttribute, Attribute.cloneAttribute)
331
- .if(Text.isText, Text.cloneText)
304
+ .if(Text.isText, Text.cloneText(device))
332
305
  .if(Comment.isComment, Comment.cloneComment)
333
306
  .if(Document.isDocument, Document.cloneDocument(options, device))
334
307
  .if(Type.isType, Type.cloneType)
@@ -341,6 +314,6 @@ export class Node extends tree.Node {
341
314
  }
342
315
  Node.cloneNode = cloneNode;
343
316
  Node.getNodesBetween = traversal.getNodesBetween;
344
- Node.hasChild = predicate.hasChild, Node.hasDescendant = predicate.hasDescendant, Node.hasInclusiveDescendant = predicate.hasInclusiveDescendant, Node.hasTextContent = predicate.hasTextContent, Node.isRoot = predicate.isRoot;
317
+ Node.hasBox = predicate.hasBox, Node.hasChild = predicate.hasChild, Node.hasDescendant = predicate.hasDescendant, Node.hasInclusiveDescendant = predicate.hasInclusiveDescendant, Node.hasTextContent = predicate.hasTextContent, Node.isRoot = predicate.isRoot;
345
318
  })(Node || (Node = {}));
346
319
  //# sourceMappingURL=node.js.map
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.99.0",
5
+ "version": "0.100.0",
6
6
  "license": "MIT",
7
7
  "description": "Implementations of the core DOM and CSSOM node types",
8
8
  "repository": {
@@ -35,35 +35,35 @@
35
35
  "dist/**/*.d.ts"
36
36
  ],
37
37
  "dependencies": {
38
- "@siteimprove/alfa-array": "^0.99.0",
39
- "@siteimprove/alfa-cache": "^0.99.0",
40
- "@siteimprove/alfa-comparable": "^0.99.0",
41
- "@siteimprove/alfa-css": "^0.99.0",
42
- "@siteimprove/alfa-css-feature": "^0.99.0",
43
- "@siteimprove/alfa-device": "^0.99.0",
44
- "@siteimprove/alfa-earl": "^0.99.0",
45
- "@siteimprove/alfa-equatable": "^0.99.0",
46
- "@siteimprove/alfa-flags": "^0.99.0",
47
- "@siteimprove/alfa-iterable": "^0.99.0",
48
- "@siteimprove/alfa-json": "^0.99.0",
49
- "@siteimprove/alfa-lazy": "^0.99.0",
50
- "@siteimprove/alfa-map": "^0.99.0",
51
- "@siteimprove/alfa-option": "^0.99.0",
52
- "@siteimprove/alfa-parser": "^0.99.0",
53
- "@siteimprove/alfa-predicate": "^0.99.0",
54
- "@siteimprove/alfa-rectangle": "^0.99.0",
55
- "@siteimprove/alfa-refinement": "^0.99.0",
56
- "@siteimprove/alfa-result": "^0.99.0",
57
- "@siteimprove/alfa-sarif": "^0.99.0",
58
- "@siteimprove/alfa-selective": "^0.99.0",
59
- "@siteimprove/alfa-sequence": "^0.99.0",
60
- "@siteimprove/alfa-slice": "^0.99.0",
61
- "@siteimprove/alfa-string": "^0.99.0",
62
- "@siteimprove/alfa-trampoline": "^0.99.0",
63
- "@siteimprove/alfa-tree": "^0.99.0"
38
+ "@siteimprove/alfa-array": "^0.100.0",
39
+ "@siteimprove/alfa-cache": "^0.100.0",
40
+ "@siteimprove/alfa-comparable": "^0.100.0",
41
+ "@siteimprove/alfa-css": "^0.100.0",
42
+ "@siteimprove/alfa-css-feature": "^0.100.0",
43
+ "@siteimprove/alfa-device": "^0.100.0",
44
+ "@siteimprove/alfa-earl": "^0.100.0",
45
+ "@siteimprove/alfa-equatable": "^0.100.0",
46
+ "@siteimprove/alfa-flags": "^0.100.0",
47
+ "@siteimprove/alfa-iterable": "^0.100.0",
48
+ "@siteimprove/alfa-json": "^0.100.0",
49
+ "@siteimprove/alfa-lazy": "^0.100.0",
50
+ "@siteimprove/alfa-map": "^0.100.0",
51
+ "@siteimprove/alfa-option": "^0.100.0",
52
+ "@siteimprove/alfa-parser": "^0.100.0",
53
+ "@siteimprove/alfa-predicate": "^0.100.0",
54
+ "@siteimprove/alfa-rectangle": "^0.100.0",
55
+ "@siteimprove/alfa-refinement": "^0.100.0",
56
+ "@siteimprove/alfa-result": "^0.100.0",
57
+ "@siteimprove/alfa-sarif": "^0.100.0",
58
+ "@siteimprove/alfa-selective": "^0.100.0",
59
+ "@siteimprove/alfa-sequence": "^0.100.0",
60
+ "@siteimprove/alfa-slice": "^0.100.0",
61
+ "@siteimprove/alfa-string": "^0.100.0",
62
+ "@siteimprove/alfa-trampoline": "^0.100.0",
63
+ "@siteimprove/alfa-tree": "^0.100.0"
64
64
  },
65
65
  "devDependencies": {
66
- "@siteimprove/alfa-test": "^0.99.0",
66
+ "@siteimprove/alfa-test": "^0.100.0",
67
67
  "@types/jsdom": "^21.1.6",
68
68
  "jsdom": "^26.0.0"
69
69
  },
@@ -1,7 +0,0 @@
1
- /**
2
- * @public
3
- */
4
- export function hasBox(predicate = () => true, device) {
5
- return (element) => element.getBoundingBox(device).some(predicate);
6
- }
7
- //# sourceMappingURL=has-box.js.map