@siteimprove/alfa-dom 0.92.0 → 0.93.1

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,23 @@
1
1
  # @siteimprove/alfa-dom
2
2
 
3
+ ## 0.93.1
4
+
5
+ ## 0.93.0
6
+
7
+ ### Minor Changes
8
+
9
+ - **Breaking:** `Element.hasDisplaySize()` now builds a `Predicate<Element<"select">>` instead of a `Predicate<Element>`. ([#1683](https://github.com/Siteimprove/alfa/pull/1683))
10
+
11
+ That is, it can only be applied to elements that have been typed as `<select>` elements, where it makes sense. If the type of element cannot be narrowed in TypeScript (e.g. because it is the result of a direct test on `Element#name`), a type assertion is needed; in general, using the `Element.hasName` refinement is recommended over testing `Element#name`.
12
+
13
+ - **Added:** A method `Element<"select">#displaySize()` is now available. ([#1683](https://github.com/Siteimprove/alfa/pull/1683))
14
+
15
+ - **Breaking:** The helper `Element.inputType(element)` has been replaced by a method `element.inputType()`. ([#1683](https://github.com/Siteimprove/alfa/pull/1683))
16
+
17
+ It can still only be called if `element` has been typed as `Element<"input">`, i.e. is an `<input>` HTML element.
18
+
19
+ - **Added:** An `Element<"select">#optionsList()` helper is now available. ([#1683](https://github.com/Siteimprove/alfa/pull/1683))
20
+
3
21
  ## 0.92.0
4
22
 
5
23
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -22,6 +22,7 @@ export * from "./node/attribute.js";
22
22
  export * from "./node/comment.js";
23
23
  export * from "./node/document.js";
24
24
  export * from "./node/element.js";
25
+ import "./node/element/augment.js";
25
26
  export * from "./node/fragment.js";
26
27
  export * from "./node/shadow.js";
27
28
  export * from "./node/text.js";
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ export * from "./node/attribute.js";
22
22
  export * from "./node/comment.js";
23
23
  export * from "./node/document.js";
24
24
  export * from "./node/element.js";
25
+ import "./node/element/augment.js";
25
26
  export * from "./node/fragment.js";
26
27
  export * from "./node/shadow.js";
27
28
  export * from "./node/text.js";
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "./jsx.js";
2
2
  import type { Element } from "./index.js";
3
3
  export declare namespace JSX {
4
- type Element = _jsx.JSX.Element;
4
+ type Element<N extends string = string> = _jsx.JSX.Element<N>;
5
5
  interface IntrinsicElements extends _jsx.JSX.IntrinsicElements {
6
6
  }
7
7
  }
@@ -0,0 +1,26 @@
1
+ import { Sequence } from "@siteimprove/alfa-sequence";
2
+ import type { InputType } from "./input-type.js";
3
+ declare module "../element.js" {
4
+ interface Element<N extends string> {
5
+ /**
6
+ * {@link https://html.spec.whatwg.org/#attr-input-type}
7
+ */
8
+ inputType(this: Element<"input">): InputType;
9
+ /**
10
+ * {@link https://html.spec.whatwg.org/multipage/form-elements.html#concept-select-size}
11
+ *
12
+ * @remarks
13
+ * The size IDL attribute should have a value of 0, not 1 or 4, when the
14
+ * size content attribute is undefined. This is for historical reasons. In
15
+ * our case, this is not affecting the results, and it is easier to treat it
16
+ * as the actual displayed size.
17
+ * {@link https://html.spec.whatwg.org/multipage/form-elements.html#dom-select-size}
18
+ */
19
+ displaySize(this: Element<"select">): number;
20
+ /**
21
+ * {@link https://html.spec.whatwg.org/multipage/form-elements.html#concept-select-option-list}
22
+ */
23
+ optionsList(this: Element<"select">): Sequence<Element<"option">>;
24
+ }
25
+ }
26
+ //# sourceMappingURL=augment.d.ts.map
@@ -0,0 +1,56 @@
1
+ /*
2
+ * Augment the Element class with some methods that are specific to a given
3
+ * element. These are grouped here to de-clutter the main class declaration
4
+ * which thus only contains generic methods.
5
+ *
6
+ * {@link https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
7
+ */
8
+ import { None, Some } from "@siteimprove/alfa-option";
9
+ import { Sequence } from "@siteimprove/alfa-sequence";
10
+ import { Element } from "../element.js";
11
+ Element.prototype.inputType = function () {
12
+ if (this._inputType === undefined) {
13
+ this._inputType = this.attribute("type")
14
+ .flatMap((attribute) => attribute.enumerate("hidden", "search", "tel", "url", "email", "password", "date", "month", "week", "time", "datetime-local", "number", "range", "color", "checkbox", "radio", "file", "submit", "image", "reset", "button", "text"))
15
+ .getOr("text");
16
+ }
17
+ return this._inputType;
18
+ };
19
+ Element.prototype.displaySize = function () {
20
+ if (this._displaySize === undefined) {
21
+ this._displaySize = this.attribute("size")
22
+ .flatMap((attribute) => {
23
+ const size = parseInt(attribute.value, 10);
24
+ if (size === size && size === (size | 0)) {
25
+ return Some.of(size);
26
+ }
27
+ return None;
28
+ })
29
+ .getOrElse(() => (this.attribute("multiple").isSome() ? 4 : 1));
30
+ }
31
+ return this._displaySize;
32
+ };
33
+ Element.prototype.optionsList = function () {
34
+ if (this._optionsList === undefined) {
35
+ this._optionsList = this.children()
36
+ .filter(Element.isElement)
37
+ .flatMap((child) => {
38
+ switch (child.name) {
39
+ case "option":
40
+ return Sequence.from([child]);
41
+ case "optgroup":
42
+ return child
43
+ .children()
44
+ .filter(Element.isElement)
45
+ .filter(
46
+ // We cannot really use `Element.hasName` here as it would
47
+ // create a circular dependency.
48
+ (grandchild) => grandchild.name === "option");
49
+ default:
50
+ return Sequence.empty();
51
+ }
52
+ });
53
+ }
54
+ return this._optionsList;
55
+ };
56
+ //# sourceMappingURL=augment.js.map
@@ -1,12 +1,7 @@
1
- import type { Element } from "../element.js";
2
1
  /**
3
2
  * {@link https://html.spec.whatwg.org/#attr-input-type}
4
3
  *
5
4
  * @internal
6
5
  */
7
6
  export type InputType = "hidden" | "search" | "tel" | "url" | "email" | "password" | "date" | "month" | "week" | "time" | "datetime-local" | "number" | "range" | "color" | "checkbox" | "radio" | "file" | "submit" | "image" | "reset" | "button" | "text";
8
- /**
9
- * @public
10
- */
11
- export declare function inputType(element: Element<"input">): InputType;
12
7
  //# sourceMappingURL=input-type.d.ts.map
@@ -1,10 +1,2 @@
1
- /**
2
- * @public
3
- */
4
- export function inputType(element) {
5
- return element
6
- .attribute("type")
7
- .flatMap((attribute) => attribute.enumerate("hidden", "search", "tel", "url", "email", "password", "date", "month", "week", "time", "datetime-local", "number", "range", "color", "checkbox", "radio", "file", "submit", "image", "reset", "button", "text"))
8
- .getOr("text");
9
- }
1
+ export {};
10
2
  //# sourceMappingURL=input-type.js.map
@@ -3,5 +3,5 @@ import type { Element } from "../../element.js";
3
3
  /**
4
4
  * @public
5
5
  */
6
- export declare function hasDisplaySize(valueOrPredicate: number | Predicate<number>): Predicate<Element>;
6
+ export declare function hasDisplaySize(valueOrPredicate: number | Predicate<number>): Predicate<Element<"select">>;
7
7
  //# sourceMappingURL=has-display-size.d.ts.map
@@ -1,4 +1,3 @@
1
- import { None, Option } from "@siteimprove/alfa-option";
2
1
  /**
3
2
  * @public
4
3
  */
@@ -7,22 +6,7 @@ export function hasDisplaySize(valueOrPredicate) {
7
6
  ? valueOrPredicate
8
7
  : (size) => valueOrPredicate === size;
9
8
  return (element) => {
10
- const displaySize = element
11
- .attribute("size")
12
- .flatMap((size) => {
13
- const sizeValue = parseInt(size.value, 10);
14
- if (sizeValue === sizeValue && sizeValue === (sizeValue | 0)) {
15
- return Option.of(sizeValue);
16
- }
17
- else {
18
- return None;
19
- }
20
- })
21
- .getOrElse(() => element
22
- .attribute("multiple")
23
- .map(() => 4)
24
- .getOr(1));
25
- return predicate(displaySize);
9
+ return predicate(element.displaySize());
26
10
  };
27
11
  }
28
12
  //# sourceMappingURL=has-display-size.js.map
@@ -1,6 +1,6 @@
1
1
  import { Predicate } from "@siteimprove/alfa-predicate";
2
2
  import { Refinement } from "@siteimprove/alfa-refinement";
3
- import { inputType } from "../input-type.js";
3
+ import {} from "../input-type.js";
4
4
  import { hasName } from "./has-name.js";
5
5
  const { equals, test } = Predicate;
6
6
  const { and } = Refinement;
@@ -12,6 +12,6 @@ export function hasInputType(inputTypeOrPredicate, ...inputTypes) {
12
12
  else {
13
13
  predicate = equals(inputTypeOrPredicate, ...inputTypes);
14
14
  }
15
- return and(hasName("input"), (element) => test(predicate, inputType(element)));
15
+ return and(hasName("input"), (element) => test(predicate, element.inputType()));
16
16
  }
17
17
  //# sourceMappingURL=has-input-type.js.map
@@ -14,7 +14,7 @@ import { Document } from "./document.js";
14
14
  import { Shadow } from "./shadow.js";
15
15
  import { Slot } from "./slot.js";
16
16
  import { Slotable } from "./slotable.js";
17
- import * as helpers from "./element/input-type.js";
17
+ import type * as helpers from "./element/input-type.js";
18
18
  import * as predicate from "./element/predicate.js";
19
19
  /**
20
20
  * @public
@@ -60,6 +60,9 @@ 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
+ protected _inputType: helpers.InputType | undefined;
64
+ protected _displaySize: number | undefined;
65
+ protected _optionsList: Sequence<Element<"option">> | undefined;
63
66
  /**
64
67
  * {@link https://dom.spec.whatwg.org/#dom-slotable-assignedslot}
65
68
  */
@@ -117,6 +120,6 @@ export declare namespace Element {
117
120
  */
118
121
  function cloneElement(options: Node.ElementReplacementOptions, device?: Device): (element: Element) => Trampoline<Element>;
119
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;
120
- const inputType: typeof helpers.inputType;
123
+ type InputType = helpers.InputType;
121
124
  }
122
125
  //# sourceMappingURL=element.d.ts.map
@@ -15,7 +15,6 @@ import { Document } from "./document.js";
15
15
  import { Shadow } from "./shadow.js";
16
16
  import { Slot } from "./slot.js";
17
17
  import { Slotable } from "./slotable.js";
18
- import * as helpers from "./element/input-type.js";
19
18
  import * as predicate from "./element/predicate.js";
20
19
  const { isEmpty } = Iterable;
21
20
  const { not } = Predicate;
@@ -172,6 +171,19 @@ export class Element extends Node {
172
171
  }
173
172
  return None;
174
173
  }
174
+ /*
175
+ * This collects caches for methods that are specific to some kind of elements.
176
+ * The actual methods are declared in element/augment.ts to de-clutter this
177
+ * class. However, we need to declare the variables here as they would
178
+ * otherwise be public which exposes too much. And they must be `protected`
179
+ * to be accessible by the augments.
180
+ */
181
+ _inputType;
182
+ _displaySize;
183
+ _optionsList;
184
+ /*
185
+ * End of caches for methods specific to some kind of elements.
186
+ */
175
187
  /**
176
188
  * {@link https://dom.spec.whatwg.org/#dom-slotable-assignedslot}
177
189
  */
@@ -325,6 +337,5 @@ export class Element extends Node {
325
337
  }
326
338
  Element.cloneElement = cloneElement;
327
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;
328
- Element.inputType = helpers.inputType;
329
340
  })(Element || (Element = {}));
330
341
  //# sourceMappingURL=element.js.map
@@ -1,6 +1,6 @@
1
1
  import type { Sequence } from "@siteimprove/alfa-sequence";
2
2
  import { Node } from "../../node.js";
3
- import { Element } from "../element.js";
3
+ import type { Element } from "../element.js";
4
4
  /**
5
5
  * @public
6
6
  */
@@ -1,5 +1,4 @@
1
1
  import { Node } from "../../node.js";
2
- import { Element } from "../element.js";
3
2
  import { getElementDescendants } from "./element-descendants.js";
4
3
  /**
5
4
  * @public
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.92.0",
5
+ "version": "0.93.1",
6
6
  "license": "MIT",
7
7
  "description": "Implementations of the core DOM and CSSOM node types",
8
8
  "repository": {
@@ -33,32 +33,32 @@
33
33
  "dist/**/*.d.ts"
34
34
  ],
35
35
  "dependencies": {
36
- "@siteimprove/alfa-array": "^0.92.0",
37
- "@siteimprove/alfa-cache": "^0.92.0",
38
- "@siteimprove/alfa-comparable": "^0.92.0",
39
- "@siteimprove/alfa-css": "^0.92.0",
40
- "@siteimprove/alfa-css-feature": "^0.92.0",
41
- "@siteimprove/alfa-device": "^0.92.0",
42
- "@siteimprove/alfa-earl": "^0.92.0",
43
- "@siteimprove/alfa-equatable": "^0.92.0",
44
- "@siteimprove/alfa-flags": "^0.92.0",
45
- "@siteimprove/alfa-iterable": "^0.92.0",
46
- "@siteimprove/alfa-json": "^0.92.0",
47
- "@siteimprove/alfa-lazy": "^0.92.0",
48
- "@siteimprove/alfa-map": "^0.92.0",
49
- "@siteimprove/alfa-option": "^0.92.0",
50
- "@siteimprove/alfa-predicate": "^0.92.0",
51
- "@siteimprove/alfa-rectangle": "^0.92.0",
52
- "@siteimprove/alfa-refinement": "^0.92.0",
53
- "@siteimprove/alfa-sarif": "^0.92.0",
54
- "@siteimprove/alfa-selective": "^0.92.0",
55
- "@siteimprove/alfa-sequence": "^0.92.0",
56
- "@siteimprove/alfa-string": "^0.92.0",
57
- "@siteimprove/alfa-trampoline": "^0.92.0",
58
- "@siteimprove/alfa-tree": "^0.92.0"
36
+ "@siteimprove/alfa-array": "^0.93.1",
37
+ "@siteimprove/alfa-cache": "^0.93.1",
38
+ "@siteimprove/alfa-comparable": "^0.93.1",
39
+ "@siteimprove/alfa-css": "^0.93.1",
40
+ "@siteimprove/alfa-css-feature": "^0.93.1",
41
+ "@siteimprove/alfa-device": "^0.93.1",
42
+ "@siteimprove/alfa-earl": "^0.93.1",
43
+ "@siteimprove/alfa-equatable": "^0.93.1",
44
+ "@siteimprove/alfa-flags": "^0.93.1",
45
+ "@siteimprove/alfa-iterable": "^0.93.1",
46
+ "@siteimprove/alfa-json": "^0.93.1",
47
+ "@siteimprove/alfa-lazy": "^0.93.1",
48
+ "@siteimprove/alfa-map": "^0.93.1",
49
+ "@siteimprove/alfa-option": "^0.93.1",
50
+ "@siteimprove/alfa-predicate": "^0.93.1",
51
+ "@siteimprove/alfa-rectangle": "^0.93.1",
52
+ "@siteimprove/alfa-refinement": "^0.93.1",
53
+ "@siteimprove/alfa-sarif": "^0.93.1",
54
+ "@siteimprove/alfa-selective": "^0.93.1",
55
+ "@siteimprove/alfa-sequence": "^0.93.1",
56
+ "@siteimprove/alfa-string": "^0.93.1",
57
+ "@siteimprove/alfa-trampoline": "^0.93.1",
58
+ "@siteimprove/alfa-tree": "^0.93.1"
59
59
  },
60
60
  "devDependencies": {
61
- "@siteimprove/alfa-test": "^0.92.0",
61
+ "@siteimprove/alfa-test": "^0.93.1",
62
62
  "@types/jsdom": "^21.1.6",
63
63
  "jsdom": "^25.0.0"
64
64
  },