accented 0.0.0-20250424114613 → 0.0.0-20250618181418

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.
Files changed (201) hide show
  1. package/README.md +0 -209
  2. package/dist/accented.d.ts +2 -2
  3. package/dist/accented.d.ts.map +1 -1
  4. package/dist/accented.js +24 -20
  5. package/dist/accented.js.map +1 -1
  6. package/dist/common/tokens.d.ts +2 -0
  7. package/dist/common/tokens.d.ts.map +1 -0
  8. package/dist/common/tokens.js +2 -0
  9. package/dist/common/tokens.js.map +1 -0
  10. package/dist/dom-updater.d.ts +1 -1
  11. package/dist/dom-updater.d.ts.map +1 -1
  12. package/dist/dom-updater.js +14 -13
  13. package/dist/dom-updater.js.map +1 -1
  14. package/dist/elements/accented-dialog.d.ts +2 -3
  15. package/dist/elements/accented-dialog.d.ts.map +1 -1
  16. package/dist/elements/accented-dialog.js +14 -8
  17. package/dist/elements/accented-dialog.js.map +1 -1
  18. package/dist/elements/accented-trigger.d.ts +3 -4
  19. package/dist/elements/accented-trigger.d.ts.map +1 -1
  20. package/dist/elements/accented-trigger.js +8 -10
  21. package/dist/elements/accented-trigger.js.map +1 -1
  22. package/dist/fullscreen-listener.d.ts +1 -1
  23. package/dist/fullscreen-listener.d.ts.map +1 -1
  24. package/dist/fullscreen-listener.js +3 -4
  25. package/dist/fullscreen-listener.js.map +1 -1
  26. package/dist/intersection-observer.d.ts +1 -1
  27. package/dist/intersection-observer.d.ts.map +1 -1
  28. package/dist/intersection-observer.js +12 -6
  29. package/dist/intersection-observer.js.map +1 -1
  30. package/dist/log-and-rethrow.d.ts +1 -1
  31. package/dist/log-and-rethrow.d.ts.map +1 -1
  32. package/dist/log-and-rethrow.js +2 -3
  33. package/dist/log-and-rethrow.js.map +1 -1
  34. package/dist/logger.d.ts +1 -1
  35. package/dist/logger.d.ts.map +1 -1
  36. package/dist/logger.js +2 -2
  37. package/dist/logger.js.map +1 -1
  38. package/dist/register-elements.d.ts +1 -1
  39. package/dist/register-elements.d.ts.map +1 -1
  40. package/dist/register-elements.js +6 -7
  41. package/dist/register-elements.js.map +1 -1
  42. package/dist/resize-listener.d.ts +1 -1
  43. package/dist/resize-listener.d.ts.map +1 -1
  44. package/dist/resize-listener.js +3 -4
  45. package/dist/resize-listener.js.map +1 -1
  46. package/dist/scanner.d.ts +2 -2
  47. package/dist/scanner.d.ts.map +1 -1
  48. package/dist/scanner.js +25 -27
  49. package/dist/scanner.js.map +1 -1
  50. package/dist/scroll-listeners.d.ts +1 -1
  51. package/dist/scroll-listeners.d.ts.map +1 -1
  52. package/dist/scroll-listeners.js +3 -4
  53. package/dist/scroll-listeners.js.map +1 -1
  54. package/dist/state.d.ts +1 -1
  55. package/dist/state.d.ts.map +1 -1
  56. package/dist/state.js +4 -5
  57. package/dist/state.js.map +1 -1
  58. package/dist/task-queue.d.ts +2 -2
  59. package/dist/task-queue.d.ts.map +1 -1
  60. package/dist/task-queue.js +1 -1
  61. package/dist/task-queue.js.map +1 -1
  62. package/dist/types.d.ts +3 -3
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/utils/are-elements-with-issues-equal.d.ts +2 -2
  65. package/dist/utils/are-elements-with-issues-equal.d.ts.map +1 -1
  66. package/dist/utils/are-elements-with-issues-equal.js +3 -3
  67. package/dist/utils/are-elements-with-issues-equal.js.map +1 -1
  68. package/dist/utils/are-issue-sets-equal.d.ts +2 -2
  69. package/dist/utils/are-issue-sets-equal.d.ts.map +1 -1
  70. package/dist/utils/are-issue-sets-equal.js +3 -3
  71. package/dist/utils/are-issue-sets-equal.js.map +1 -1
  72. package/dist/utils/containing-blocks.d.ts.map +1 -1
  73. package/dist/utils/containing-blocks.js +1 -1
  74. package/dist/utils/containing-blocks.js.map +1 -1
  75. package/dist/utils/contains.d.ts +1 -1
  76. package/dist/utils/contains.d.ts.map +1 -1
  77. package/dist/utils/contains.js +1 -1
  78. package/dist/utils/contains.js.map +1 -1
  79. package/dist/utils/deduplicate-nodes.js +0 -1
  80. package/dist/utils/deduplicate-nodes.js.map +1 -1
  81. package/dist/utils/deep-merge.d.ts +1 -1
  82. package/dist/utils/deep-merge.d.ts.map +1 -1
  83. package/dist/utils/deep-merge.js +6 -5
  84. package/dist/utils/deep-merge.js.map +1 -1
  85. package/dist/utils/dom-helpers.d.ts.map +1 -1
  86. package/dist/utils/dom-helpers.js +4 -2
  87. package/dist/utils/dom-helpers.js.map +1 -1
  88. package/dist/utils/ensure-non-empty.d.ts +1 -1
  89. package/dist/utils/ensure-non-empty.d.ts.map +1 -1
  90. package/dist/utils/ensure-non-empty.js +2 -2
  91. package/dist/utils/ensure-non-empty.js.map +1 -1
  92. package/dist/utils/get-element-html.d.ts +1 -1
  93. package/dist/utils/get-element-html.d.ts.map +1 -1
  94. package/dist/utils/get-element-html.js +4 -2
  95. package/dist/utils/get-element-html.js.map +1 -1
  96. package/dist/utils/get-element-position.d.ts +2 -2
  97. package/dist/utils/get-element-position.d.ts.map +1 -1
  98. package/dist/utils/get-element-position.js +21 -25
  99. package/dist/utils/get-element-position.js.map +1 -1
  100. package/dist/utils/get-parent.d.ts +1 -1
  101. package/dist/utils/get-parent.d.ts.map +1 -1
  102. package/dist/utils/get-parent.js +1 -1
  103. package/dist/utils/get-parent.js.map +1 -1
  104. package/dist/utils/get-scan-context.d.ts +2 -2
  105. package/dist/utils/get-scan-context.d.ts.map +1 -1
  106. package/dist/utils/get-scan-context.js +9 -9
  107. package/dist/utils/get-scan-context.js.map +1 -1
  108. package/dist/utils/get-scrollable-ancestors.d.ts +1 -1
  109. package/dist/utils/get-scrollable-ancestors.d.ts.map +1 -1
  110. package/dist/utils/get-scrollable-ancestors.js +5 -5
  111. package/dist/utils/get-scrollable-ancestors.js.map +1 -1
  112. package/dist/utils/is-node-in-scan-context.d.ts +2 -2
  113. package/dist/utils/is-node-in-scan-context.d.ts.map +1 -1
  114. package/dist/utils/is-node-in-scan-context.js +5 -5
  115. package/dist/utils/is-node-in-scan-context.js.map +1 -1
  116. package/dist/utils/is-non-empty.d.ts +2 -0
  117. package/dist/utils/is-non-empty.d.ts.map +1 -0
  118. package/dist/utils/is-non-empty.js +4 -0
  119. package/dist/utils/is-non-empty.js.map +1 -0
  120. package/dist/utils/normalize-context.d.ts +2 -2
  121. package/dist/utils/normalize-context.d.ts.map +1 -1
  122. package/dist/utils/normalize-context.js +10 -8
  123. package/dist/utils/normalize-context.js.map +1 -1
  124. package/dist/utils/recalculate-positions.d.ts +1 -1
  125. package/dist/utils/recalculate-positions.d.ts.map +1 -1
  126. package/dist/utils/recalculate-positions.js +5 -5
  127. package/dist/utils/recalculate-positions.js.map +1 -1
  128. package/dist/utils/recalculate-scrollable-ancestors.d.ts +1 -1
  129. package/dist/utils/recalculate-scrollable-ancestors.d.ts.map +1 -1
  130. package/dist/utils/recalculate-scrollable-ancestors.js +4 -4
  131. package/dist/utils/recalculate-scrollable-ancestors.js.map +1 -1
  132. package/dist/utils/shadow-dom-aware-mutation-observer.d.ts +1 -1
  133. package/dist/utils/shadow-dom-aware-mutation-observer.d.ts.map +1 -1
  134. package/dist/utils/shadow-dom-aware-mutation-observer.js +19 -22
  135. package/dist/utils/shadow-dom-aware-mutation-observer.js.map +1 -1
  136. package/dist/utils/supports-anchor-positioning.d.ts +1 -1
  137. package/dist/utils/supports-anchor-positioning.d.ts.map +1 -1
  138. package/dist/utils/supports-anchor-positioning.js +1 -1
  139. package/dist/utils/supports-anchor-positioning.js.map +1 -1
  140. package/dist/utils/transform-violations.d.ts +2 -2
  141. package/dist/utils/transform-violations.d.ts.map +1 -1
  142. package/dist/utils/transform-violations.js +9 -9
  143. package/dist/utils/transform-violations.js.map +1 -1
  144. package/dist/utils/update-elements-with-issues.d.ts +3 -3
  145. package/dist/utils/update-elements-with-issues.d.ts.map +1 -1
  146. package/dist/utils/update-elements-with-issues.js +34 -29
  147. package/dist/utils/update-elements-with-issues.js.map +1 -1
  148. package/dist/validate-options.d.ts +2 -2
  149. package/dist/validate-options.d.ts.map +1 -1
  150. package/dist/validate-options.js +24 -23
  151. package/dist/validate-options.js.map +1 -1
  152. package/package.json +5 -3
  153. package/src/accented.test.ts +2 -2
  154. package/src/accented.ts +34 -26
  155. package/src/common/tokens.ts +1 -0
  156. package/src/dom-updater.ts +26 -19
  157. package/src/elements/accented-dialog.ts +69 -43
  158. package/src/elements/accented-trigger.ts +52 -43
  159. package/src/fullscreen-listener.ts +15 -11
  160. package/src/intersection-observer.ts +27 -16
  161. package/src/log-and-rethrow.ts +2 -3
  162. package/src/logger.ts +8 -6
  163. package/src/register-elements.ts +7 -7
  164. package/src/resize-listener.ts +15 -11
  165. package/src/scanner.ts +55 -41
  166. package/src/scroll-listeners.ts +27 -19
  167. package/src/state.ts +24 -21
  168. package/src/task-queue.test.ts +5 -4
  169. package/src/task-queue.ts +2 -2
  170. package/src/types.ts +52 -53
  171. package/src/utils/are-elements-with-issues-equal.ts +7 -5
  172. package/src/utils/are-issue-sets-equal.test.ts +10 -6
  173. package/src/utils/are-issue-sets-equal.ts +8 -6
  174. package/src/utils/containing-blocks.ts +6 -3
  175. package/src/utils/contains.test.ts +2 -2
  176. package/src/utils/contains.ts +1 -1
  177. package/src/utils/deduplicate-nodes.ts +1 -1
  178. package/src/utils/deep-merge.test.ts +8 -1
  179. package/src/utils/deep-merge.ts +11 -8
  180. package/src/utils/dom-helpers.ts +6 -2
  181. package/src/utils/ensure-non-empty.ts +2 -2
  182. package/src/utils/get-element-html.ts +4 -2
  183. package/src/utils/get-element-position.ts +37 -24
  184. package/src/utils/get-parent.ts +1 -1
  185. package/src/utils/get-scan-context.test.ts +14 -8
  186. package/src/utils/get-scan-context.ts +12 -15
  187. package/src/utils/get-scrollable-ancestors.ts +8 -5
  188. package/src/utils/is-node-in-scan-context.test.ts +3 -3
  189. package/src/utils/is-node-in-scan-context.ts +6 -6
  190. package/src/utils/is-non-empty.ts +3 -0
  191. package/src/utils/normalize-context.test.ts +9 -9
  192. package/src/utils/normalize-context.ts +17 -10
  193. package/src/utils/recalculate-positions.ts +5 -5
  194. package/src/utils/recalculate-scrollable-ancestors.ts +4 -4
  195. package/src/utils/shadow-dom-aware-mutation-observer.ts +21 -24
  196. package/src/utils/supports-anchor-positioning.ts +3 -3
  197. package/src/utils/transform-violations.test.ts +22 -20
  198. package/src/utils/transform-violations.ts +14 -10
  199. package/src/utils/update-elements-with-issues.test.ts +49 -49
  200. package/src/utils/update-elements-with-issues.ts +96 -71
  201. package/src/validate-options.ts +91 -38
@@ -1,11 +1,12 @@
1
1
  import assert from 'node:assert/strict';
2
- import {mock, suite, test} from 'node:test';
2
+ import { mock, suite, test } from 'node:test';
3
3
 
4
- import TaskQueue from './task-queue.js';
4
+ import { TaskQueue } from './task-queue';
5
5
 
6
- const wait = (duration: number) => new Promise(resolve => setTimeout(resolve, duration));
6
+ const wait = (duration: number) => new Promise((resolve) => setTimeout(resolve, duration));
7
7
 
8
- const createAsyncCallback = (duration: number) => mock.fn(() => new Promise(resolve => setTimeout(resolve, duration)));
8
+ const createAsyncCallback = (duration: number) =>
9
+ mock.fn(() => new Promise((resolve) => setTimeout(resolve, duration)));
9
10
 
10
11
  suite('TaskQueue', () => {
11
12
  test('callback is not called after a TaskQueue is created, even after a timeout', async () => {
package/src/task-queue.ts CHANGED
@@ -1,8 +1,8 @@
1
- import type { Throttle } from './types';
1
+ import type { Throttle } from './types.ts';
2
2
 
3
3
  type TaskCallback<T> = (items: Array<T>) => void;
4
4
 
5
- export default class TaskQueue<T> {
5
+ export class TaskQueue<T> {
6
6
  #throttle: Throttle;
7
7
  #asyncCallback: TaskCallback<T> | null = null;
8
8
 
package/src/types.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type axe from 'axe-core';
2
1
  import type { Signal } from '@preact/signals-core';
3
- import type { AccentedTrigger } from './elements/accented-trigger';
2
+ import type axe from 'axe-core';
3
+ import type { AccentedTrigger } from './elements/accented-trigger.ts';
4
4
 
5
5
  export type Throttle = {
6
6
  /**
@@ -8,7 +8,7 @@ export type Throttle = {
8
8
  *
9
9
  * Default: `1000`.
10
10
  * */
11
- wait?: number,
11
+ wait?: number;
12
12
 
13
13
  /**
14
14
  * When to run the scan on Accented initialization or on a mutation.
@@ -17,8 +17,8 @@ export type Throttle = {
17
17
  *
18
18
  * Default: `true`.
19
19
  * */
20
- leading?: boolean
21
- }
20
+ leading?: boolean;
21
+ };
22
22
 
23
23
  export type Output = {
24
24
  /**
@@ -26,8 +26,8 @@ export type Output = {
26
26
  *
27
27
  * Default: `true`.
28
28
  * */
29
- console?: boolean
30
- }
29
+ console?: boolean;
30
+ };
31
31
 
32
32
  /**
33
33
  * Model context type based on axe.ElementContext,
@@ -43,27 +43,27 @@ export type SelectorList = Array<Selector> | NodeList;
43
43
  // The rest of the type is structured the same as in axe-core.
44
44
  export type ContextProp = Selector | SelectorList;
45
45
 
46
- export type ContextObject = {
47
- include: ContextProp;
48
- exclude?: ContextProp;
49
- } | {
50
- exclude: ContextProp;
51
- include?: ContextProp;
52
- };
46
+ export type ContextObject =
47
+ | {
48
+ include: ContextProp;
49
+ exclude?: ContextProp;
50
+ }
51
+ | {
52
+ exclude: ContextProp;
53
+ include?: ContextProp;
54
+ };
53
55
 
54
56
  export type Context = ContextProp | ContextObject;
55
57
 
56
-
57
-
58
58
  export const allowedAxeOptions = ['rules', 'runOnly'] as const;
59
59
 
60
- export type AxeOptions = Pick<axe.RunOptions, typeof allowedAxeOptions[number]>;
60
+ export type AxeOptions = Pick<axe.RunOptions, (typeof allowedAxeOptions)[number]>;
61
61
 
62
62
  type CallbackParams = {
63
63
  /**
64
64
  * The most current array of elements with issues.
65
65
  * */
66
- elementsWithIssues: Array<ElementWithIssues>,
66
+ elementsWithIssues: Array<ElementWithIssues>;
67
67
 
68
68
  /**
69
69
  * * `performance`: runtime performance of the last scan. An object:
@@ -75,17 +75,16 @@ type CallbackParams = {
75
75
  * or an object with `include` and `exclude` properties (if any nodes were excluded).
76
76
  * */
77
77
  performance: {
78
- totalBlockingTime: number,
79
- scan: number,
80
- domUpdate: number,
81
- scanContext: ScanContext | Array<Node>
82
- }
83
- }
78
+ totalBlockingTime: number;
79
+ scan: number;
80
+ domUpdate: number;
81
+ scanContext: ScanContext | Array<Node>;
82
+ };
83
+ };
84
84
 
85
85
  export type Callback = (params: CallbackParams) => void;
86
86
 
87
87
  export type AccentedOptions = {
88
-
89
88
  /**
90
89
  * The `context` parameter for `axe.run()`.
91
90
  *
@@ -102,7 +101,7 @@ export type AccentedOptions = {
102
101
  *
103
102
  * Default: `document`.
104
103
  */
105
- context?: Context,
104
+ context?: Context;
106
105
 
107
106
  /**
108
107
  * The `options` parameter for `axe.run()`.
@@ -118,7 +117,7 @@ export type AccentedOptions = {
118
117
  *
119
118
  * Default: `{}`.
120
119
  */
121
- axeOptions?: AxeOptions,
120
+ axeOptions?: AxeOptions;
122
121
 
123
122
  /**
124
123
  * The character sequence that’s used in various elements, attributes and stylesheets that Accented adds to the page.
@@ -135,24 +134,24 @@ export type AccentedOptions = {
135
134
  *
136
135
  * Default: `accented`.
137
136
  */
138
- name?: string,
137
+ name?: string;
139
138
 
140
139
  /**
141
140
  * Output options object.
142
141
  * */
143
- output?: Output,
142
+ output?: Output;
144
143
 
145
144
  /**
146
145
  * Scan throttling options object.
147
146
  * */
148
- throttle?: Throttle,
147
+ throttle?: Throttle;
149
148
 
150
149
  /**
151
150
  * A callback that will be called after each scan.
152
151
  *
153
152
  * Default: `() => {}`.
154
153
  * */
155
- callback?: Callback
154
+ callback?: Callback;
156
155
  };
157
156
 
158
157
  /**
@@ -162,41 +161,41 @@ export type AccentedOptions = {
162
161
  export type DisableAccented = () => void;
163
162
 
164
163
  export type Position = {
165
- left: number,
166
- top: number,
167
- width: number,
168
- height: number
164
+ left: number;
165
+ top: number;
166
+ width: number;
167
+ height: number;
169
168
  };
170
169
 
171
170
  export type Issue = {
172
- id: string,
173
- title: string,
174
- description: string,
175
- url: string,
176
- impact: axe.ImpactValue
171
+ id: string;
172
+ title: string;
173
+ description: string;
174
+ url: string;
175
+ impact: axe.ImpactValue;
177
176
  };
178
177
 
179
178
  export type BaseElementWithIssues = {
180
- element: HTMLElement | SVGElement,
181
- rootNode: Node
179
+ element: HTMLElement | SVGElement;
180
+ rootNode: Node;
182
181
  };
183
182
 
184
183
  export type ElementWithIssues = BaseElementWithIssues & {
185
- issues: Array<Issue>
184
+ issues: Array<Issue>;
186
185
  };
187
186
 
188
187
  export type ExtendedElementWithIssues = BaseElementWithIssues & {
189
- issues: Signal<ElementWithIssues['issues']>,
190
- visible: Signal<boolean>,
191
- trigger: AccentedTrigger,
192
- position: Signal<Position>,
193
- skipRender: boolean,
194
- anchorNameValue: string,
195
- scrollableAncestors: Signal<Set<Element>>
196
- id: number
188
+ issues: Signal<ElementWithIssues['issues']>;
189
+ visible: Signal<boolean>;
190
+ trigger: AccentedTrigger;
191
+ position: Signal<Position>;
192
+ skipRender: boolean;
193
+ anchorNameValue: string;
194
+ scrollableAncestors: Signal<Set<Element>>;
195
+ id: number;
197
196
  };
198
197
 
199
198
  export type ScanContext = {
200
- include: Array<Node>,
201
- exclude: Array<Node>
199
+ include: Array<Node>;
200
+ exclude: Array<Node>;
202
201
  };
@@ -1,9 +1,11 @@
1
- import type { BaseElementWithIssues } from "../types";
1
+ import type { BaseElementWithIssues } from '../types.ts';
2
2
 
3
- export default function areElementsWithIssuesEqual(
3
+ export function areElementsWithIssuesEqual(
4
4
  elementWithIssues1: BaseElementWithIssues,
5
- elementWithIssues2: BaseElementWithIssues
5
+ elementWithIssues2: BaseElementWithIssues,
6
6
  ) {
7
- return elementWithIssues1.element === elementWithIssues2.element
8
- && elementWithIssues1.rootNode === elementWithIssues2.rootNode;
7
+ return (
8
+ elementWithIssues1.element === elementWithIssues2.element &&
9
+ elementWithIssues1.rootNode === elementWithIssues2.rootNode
10
+ );
9
11
  }
@@ -1,14 +1,14 @@
1
1
  import assert from 'node:assert/strict';
2
- import {suite, test} from 'node:test';
3
- import areIssueSetsEqual from './are-issue-sets-equal.js';
2
+ import { suite, test } from 'node:test';
4
3
  import type { Issue } from '../types';
4
+ import { areIssueSetsEqual } from './are-issue-sets-equal';
5
5
 
6
6
  const issue1: Issue = {
7
7
  id: 'id1',
8
8
  title: 'title1',
9
9
  description: 'description1',
10
10
  url: 'http://example.com',
11
- impact: 'serious'
11
+ impact: 'serious',
12
12
  };
13
13
 
14
14
  const issue2: Issue = {
@@ -16,18 +16,22 @@ const issue2: Issue = {
16
16
  title: 'title2',
17
17
  description: 'description2',
18
18
  url: 'http://example.com',
19
- impact: 'serious'
19
+ impact: 'serious',
20
20
  };
21
21
 
22
22
  // @ts-expect-error
23
- const issue2Clone: Issue = Object.keys(issue2).reduce((obj, key) => { obj[key] = issue2[key]; return obj; }, {});
23
+ const issue2Clone: Issue = Object.keys(issue2).reduce((obj, key) => {
24
+ // @ts-expect-error
25
+ obj[key] = issue2[key];
26
+ return obj;
27
+ }, {});
24
28
 
25
29
  const issue3: Issue = {
26
30
  id: 'id3',
27
31
  title: 'title3',
28
32
  description: 'description3',
29
33
  url: 'http://example.com',
30
- impact: 'serious'
34
+ impact: 'serious',
31
35
  };
32
36
 
33
37
  suite('areIssueSetsEqual', () => {
@@ -1,10 +1,12 @@
1
- import type { Issue } from '../types';
1
+ import type { Issue } from '../types.ts';
2
2
 
3
3
  const issueProps: Array<keyof Issue> = ['id', 'title', 'description', 'url', 'impact'];
4
4
 
5
- export default function areIssueSetsEqual(issues1: Array<Issue>, issues2: Array<Issue>) {
6
- return issues1.length === issues2.length &&
7
- issues1.every(issue1 => Boolean(issues2.find(issue2 =>
8
- issueProps.every(prop => issue2[prop] === issue1[prop])
9
- )));
5
+ export function areIssueSetsEqual(issues1: Array<Issue>, issues2: Array<Issue>) {
6
+ return (
7
+ issues1.length === issues2.length &&
8
+ issues1.every((issue1) =>
9
+ Boolean(issues2.find((issue2) => issueProps.every((prop) => issue2[prop] === issue1[prop]))),
10
+ )
11
+ );
10
12
  }
@@ -7,7 +7,10 @@
7
7
  *
8
8
  * It's only meant to be used during initialization.
9
9
  */
10
- function testContainingBlockCreation<T extends keyof CSSStyleDeclaration>(prop: T, value: CSSStyleDeclaration[T]) {
10
+ function testContainingBlockCreation<T extends keyof CSSStyleDeclaration>(
11
+ prop: T,
12
+ value: CSSStyleDeclaration[T],
13
+ ) {
11
14
  const container = document.createElement('div');
12
15
  container.style[prop] = value;
13
16
  container.style.position = 'fixed';
@@ -40,13 +43,13 @@ export function createsContainingBlock(prop: keyof CSSStyleDeclaration) {
40
43
 
41
44
  export function initializeContainingBlockSupportSet() {
42
45
  type StyleEntry<T extends keyof CSSStyleDeclaration> = {
43
- [K in T]: { prop: K; value: CSSStyleDeclaration[K] }
46
+ [K in T]: { prop: K; value: CSSStyleDeclaration[K] };
44
47
  }[T];
45
48
 
46
49
  const propsToTest: Array<StyleEntry<'filter' | 'backdropFilter' | 'containerType'>> = [
47
50
  { prop: 'filter', value: 'blur(1px)' },
48
51
  { prop: 'backdropFilter', value: 'blur(1px)' },
49
- { prop: 'containerType', value: 'size' }
52
+ { prop: 'containerType', value: 'size' },
50
53
  ];
51
54
 
52
55
  for (const { prop, value } of propsToTest) {
@@ -1,7 +1,7 @@
1
- import { JSDOM } from 'jsdom';
2
1
  import assert from 'node:assert/strict';
3
2
  import { suite, test } from 'node:test';
4
- import contains from './contains';
3
+ import { JSDOM } from 'jsdom';
4
+ import { contains } from './contains';
5
5
 
6
6
  suite('contains', () => {
7
7
  test('an element contains itself', () => {
@@ -1,6 +1,6 @@
1
1
  import { isDocumentFragment, isShadowRoot } from './dom-helpers.js';
2
2
 
3
- export default function contains(ancestor: Node, descendant: Node): boolean {
3
+ export function contains(ancestor: Node, descendant: Node): boolean {
4
4
  if (ancestor.contains(descendant)) {
5
5
  return true;
6
6
  }
@@ -1,3 +1,3 @@
1
1
  export function deduplicateNodes(nodes: Array<Node>): Array<Node> {
2
- return [...new Set(nodes)];;
2
+ return [...new Set(nodes)];
3
3
  }
@@ -1,7 +1,7 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { suite, test } from 'node:test';
3
3
 
4
- import deepMerge from './deep-merge';
4
+ import { deepMerge } from './deep-merge';
5
5
 
6
6
  suite('deepMerge', () => {
7
7
  test('merges two objects with overlapping keys', () => {
@@ -31,4 +31,11 @@ suite('deepMerge', () => {
31
31
  const result = deepMerge(target, source);
32
32
  assert.deepEqual(result, { a: [4, 5] });
33
33
  });
34
+
35
+ test('handles merging an object into a string in a logical way', () => {
36
+ const target = { a: 'hello' };
37
+ const source = { a: { b: 'bye' } };
38
+ const result = deepMerge(target, source);
39
+ assert.deepEqual(result, { a: { b: 'bye' } });
40
+ });
34
41
  });
@@ -1,16 +1,19 @@
1
+ // biome-ignore lint/suspicious/noExplicitAny: I'm not sure how to type this properly
1
2
  type AnyObject = Record<string, any>;
2
3
 
3
- export default function deepMerge(target: AnyObject, source: AnyObject): AnyObject {
4
- const output = {...target};
4
+ const isObject = (obj: unknown): obj is AnyObject =>
5
+ typeof obj === 'object' && obj !== null && !Array.isArray(obj);
6
+
7
+ export function deepMerge(target: AnyObject, source: AnyObject): AnyObject {
8
+ const output = { ...target };
5
9
  for (const key of Object.keys(source)) {
6
- if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
7
- if (!(key in target)) {
8
- output[key] = source[key];
9
- } else {
10
+ if (isObject(source[key])) {
11
+ if (isObject(target[key])) {
10
12
  output[key] = deepMerge(target[key], source[key]);
13
+ } else {
14
+ output[key] = source[key];
11
15
  }
12
- }
13
- else {
16
+ } else {
14
17
  output[key] = source[key];
15
18
  }
16
19
  }
@@ -1,6 +1,10 @@
1
1
  export function isNode(obj: object): obj is Node {
2
- return 'nodeType' in obj && typeof obj.nodeType === 'number' &&
3
- 'nodeName' in obj && typeof obj.nodeName === 'string';
2
+ return (
3
+ 'nodeType' in obj &&
4
+ typeof obj.nodeType === 'number' &&
5
+ 'nodeName' in obj &&
6
+ typeof obj.nodeName === 'string'
7
+ );
4
8
  }
5
9
 
6
10
  export function isNodeList(obj: object): obj is NodeList {
@@ -1,6 +1,6 @@
1
- export default function ensureNonEmpty<T>(arr: T[]): [T, ...T[]] {
1
+ export function ensureNonEmpty<T>(arr: T[]): [T, ...T[]] {
2
2
  if (arr.length === 0) {
3
- throw new Error("Array must not be empty");
3
+ throw new Error('Array must not be empty');
4
4
  }
5
5
  return arr as [T, ...T[]];
6
6
  }
@@ -1,4 +1,4 @@
1
- export default function getElementHtml(element: Element) {
1
+ export function getElementHtml(element: Element) {
2
2
  const outerHtml = element.outerHTML;
3
3
  const innerHtml = element.innerHTML;
4
4
  if (!innerHtml) {
@@ -9,5 +9,7 @@ export default function getElementHtml(element: Element) {
9
9
  // This shouldn't be happening, but if it does, we can just return the outer HTML.
10
10
  return outerHtml;
11
11
  }
12
- return outerHtml.slice(0, index) + '…' + outerHtml.slice(index + innerHtml.length);
12
+ const openingTag = outerHtml.slice(0, index);
13
+ const closingTag = outerHtml.slice(index + innerHtml.length);
14
+ return `${openingTag}…${closingTag}`;
13
15
  }
@@ -1,23 +1,36 @@
1
- import type { Position } from '../types';
2
- import { isHtmlElement } from './dom-helpers.js';
3
- import getParent from './get-parent.js';
1
+ import type { Position } from '../types.ts';
4
2
  import { createsContainingBlock } from './containing-blocks.js';
3
+ import { isHtmlElement } from './dom-helpers.js';
4
+ import { getParent } from './get-parent.js';
5
5
 
6
6
  // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_display/Containing_block#identifying_the_containing_block
7
7
  function isContainingBlock(element: Element, win: Window): boolean {
8
8
  const style = win.getComputedStyle(element);
9
- const { transform, perspective, contain, contentVisibility, containerType, filter, backdropFilter, willChange } = style;
9
+ const {
10
+ transform,
11
+ perspective,
12
+ contain,
13
+ contentVisibility,
14
+ containerType,
15
+ filter,
16
+ backdropFilter,
17
+ willChange,
18
+ } = style;
10
19
  const containItems = contain.split(' ');
11
20
  const willChangeItems = willChange.split(/\s*,\s*/);
12
21
 
13
- return transform !== 'none'
14
- || perspective !== 'none'
15
- || containItems.some((item) => ['layout', 'paint', 'strict', 'content'].includes(item))
16
- || contentVisibility === 'auto'
17
- || (createsContainingBlock('containerType') && containerType !== 'normal')
18
- || (createsContainingBlock('filter') && filter !== 'none')
19
- || (createsContainingBlock('backdropFilter') && backdropFilter !== 'none')
20
- || willChangeItems.some((item) => ['transform', 'perspective', 'contain', 'filter', 'backdrop-filter'].includes(item));
22
+ return (
23
+ transform !== 'none' ||
24
+ perspective !== 'none' ||
25
+ containItems.some((item) => ['layout', 'paint', 'strict', 'content'].includes(item)) ||
26
+ contentVisibility === 'auto' ||
27
+ (createsContainingBlock('containerType') && containerType !== 'normal') ||
28
+ (createsContainingBlock('filter') && filter !== 'none') ||
29
+ (createsContainingBlock('backdropFilter') && backdropFilter !== 'none') ||
30
+ willChangeItems.some((item) =>
31
+ ['transform', 'perspective', 'contain', 'filter', 'backdrop-filter'].includes(item),
32
+ )
33
+ );
21
34
  }
22
35
 
23
36
  function getNonInitialContainingBlock(element: Element, win: Window): Element | null {
@@ -39,7 +52,7 @@ function getNonInitialContainingBlock(element: Element, win: Window): Element |
39
52
  * * The element itself, or one of the element's ancestors has a scale or rotate transform.
40
53
  * * The browser doesn't support anchor positioning.
41
54
  */
42
- export default function getElementPosition(element: Element, win: Window): Position {
55
+ export function getElementPosition(element: Element, win: Window): Position {
43
56
  const nonInitialContainingBlock = getNonInitialContainingBlock(element, win);
44
57
  // If an element has a containing block as an ancestor,
45
58
  // and that containing block is not the <html> element (the initial containing block),
@@ -60,17 +73,17 @@ export default function getElementPosition(element: Element, win: Window): Posit
60
73
  currentElement = currentElement.offsetParent as HTMLElement | null;
61
74
  }
62
75
  return { top, left, width, height };
63
- } else {
64
- const elementRect = element.getBoundingClientRect();
65
- const nonInitialContainingBlockRect = nonInitialContainingBlock.getBoundingClientRect();
66
- return {
67
- top: elementRect.top - nonInitialContainingBlockRect.top,
68
- height: elementRect.height,
69
- left: elementRect.left - nonInitialContainingBlockRect.left,
70
- width: elementRect.width
71
- };
72
76
  }
73
- } else {
74
- return element.getBoundingClientRect();
77
+
78
+ const elementRect = element.getBoundingClientRect();
79
+ const nonInitialContainingBlockRect = nonInitialContainingBlock.getBoundingClientRect();
80
+ return {
81
+ top: elementRect.top - nonInitialContainingBlockRect.top,
82
+ height: elementRect.height,
83
+ left: elementRect.left - nonInitialContainingBlockRect.left,
84
+ width: elementRect.width,
85
+ };
75
86
  }
87
+
88
+ return element.getBoundingClientRect();
76
89
  }
@@ -1,6 +1,6 @@
1
1
  import { isDocumentFragment, isShadowRoot } from './dom-helpers.js';
2
2
 
3
- export default function getParent (element: Element): Element | null {
3
+ export function getParent(element: Element): Element | null {
4
4
  if (element.parentElement) {
5
5
  return element.parentElement;
6
6
  }
@@ -1,7 +1,7 @@
1
- import { JSDOM } from 'jsdom';
2
1
  import assert from 'node:assert/strict';
3
2
  import { suite, test } from 'node:test';
4
- import getScanContext from './get-scan-context';
3
+ import { JSDOM } from 'jsdom';
4
+ import { getScanContext } from './get-scan-context';
5
5
 
6
6
  suite('getScanContext', () => {
7
7
  test('when context doesn’t overlap with nodes, the result is empty', () => {
@@ -13,7 +13,7 @@ suite('getScanContext', () => {
13
13
 
14
14
  assert.deepEqual(scanContext, {
15
15
  include: [],
16
- exclude: []
16
+ exclude: [],
17
17
  });
18
18
  });
19
19
 
@@ -27,7 +27,7 @@ suite('getScanContext', () => {
27
27
 
28
28
  assert.deepEqual(scanContext, {
29
29
  include: [contextNode],
30
- exclude: []
30
+ exclude: [],
31
31
  });
32
32
  });
33
33
 
@@ -44,13 +44,16 @@ suite('getScanContext', () => {
44
44
  const { document } = dom.window;
45
45
  global.document = document;
46
46
  const mutatedNode = document.querySelector('#mutated-node')!;
47
- const scanContext = getScanContext([mutatedNode], {include: ['.include'], exclude: ['.exclude']});
47
+ const scanContext = getScanContext([mutatedNode], {
48
+ include: ['.include'],
49
+ exclude: ['.exclude'],
50
+ });
48
51
  const innerExclude = document.querySelector('#inner-exclude')!;
49
52
  const innerInclude = document.querySelector('#inner-include')!;
50
53
 
51
54
  assert.deepEqual(scanContext, {
52
55
  include: [mutatedNode, innerInclude],
53
- exclude: [innerExclude]
56
+ exclude: [innerExclude],
54
57
  });
55
58
  });
56
59
 
@@ -67,13 +70,16 @@ suite('getScanContext', () => {
67
70
  const { document } = dom.window;
68
71
  global.document = document;
69
72
  const mutatedNode = document.querySelector('#mutated-node')!;
70
- const scanContext = getScanContext([mutatedNode], {include: ['.include'], exclude: ['.exclude']});
73
+ const scanContext = getScanContext([mutatedNode], {
74
+ include: ['.include'],
75
+ exclude: ['.exclude'],
76
+ });
71
77
  const innerExclude = document.querySelector('#inner-exclude')!;
72
78
  const innerInclude = document.querySelector('#inner-include')!;
73
79
 
74
80
  assert.deepEqual(scanContext, {
75
81
  include: [innerInclude],
76
- exclude: [innerExclude]
82
+ exclude: [innerExclude],
77
83
  });
78
84
  });
79
85
  });