@cronn/element-snapshot 0.9.0 → 0.11.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/README.md +8 -3
- package/dist/browser-lib.iife.js +707 -0
- package/dist/{index.d.ts → index.d.mts} +104 -88
- package/dist/index.mjs +166 -0
- package/package.json +22 -13
- package/dist/browser-lib.d.ts +0 -128
- package/dist/browser-lib.global.js +0 -766
- package/dist/index.js +0 -158
|
@@ -1,766 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
(() => {
|
|
3
|
-
// src/browser/attribute.ts
|
|
4
|
-
function stringAttribute(value) {
|
|
5
|
-
return value !== null && value !== "" ? value : void 0;
|
|
6
|
-
}
|
|
7
|
-
function booleanAttribute(value) {
|
|
8
|
-
return value === true || value === "true" ? true : void 0;
|
|
9
|
-
}
|
|
10
|
-
function numericAttribute(value) {
|
|
11
|
-
if (value === null) {
|
|
12
|
-
return void 0;
|
|
13
|
-
}
|
|
14
|
-
try {
|
|
15
|
-
return parseInt(value);
|
|
16
|
-
} catch {
|
|
17
|
-
return void 0;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
function enumAttribute(value, supportedValues) {
|
|
21
|
-
if (value === null || !supportedValues.has(value)) {
|
|
22
|
-
return void 0;
|
|
23
|
-
}
|
|
24
|
-
return value;
|
|
25
|
-
}
|
|
26
|
-
function resolveElementReference(element, attributeName) {
|
|
27
|
-
const referenceId = element.getAttribute(attributeName);
|
|
28
|
-
if (referenceId === null) {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
return element.ownerDocument.getElementById(referenceId);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// src/browser/children.ts
|
|
35
|
-
function snapshotChildren(element) {
|
|
36
|
-
const children = Array.from(element.childNodes).map(snapshotNodeRecursive).filter((childSnapshot) => childSnapshot !== null).flat();
|
|
37
|
-
return children.length > 0 ? children : void 0;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// src/browser/text.ts
|
|
41
|
-
function snapshotTextNode(textNode) {
|
|
42
|
-
const textContent = snapshotTextContent(textNode);
|
|
43
|
-
if (textContent === void 0) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
return {
|
|
47
|
-
role: "text",
|
|
48
|
-
name: textContent
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
function snapshotTextContent(element) {
|
|
52
|
-
if (element.textContent === null) {
|
|
53
|
-
return void 0;
|
|
54
|
-
}
|
|
55
|
-
const normalizedText = element.textContent.replaceAll(/\s+/g, " ").trim();
|
|
56
|
-
return normalizedText !== "" ? normalizedText : void 0;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// src/browser/name.ts
|
|
60
|
-
function resolveAccessibleName(element, includeTextContent = true) {
|
|
61
|
-
const labelledByElement = resolveElementReference(element, "aria-labelledby");
|
|
62
|
-
if (labelledByElement !== null) {
|
|
63
|
-
return snapshotTextContent(labelledByElement);
|
|
64
|
-
}
|
|
65
|
-
if (element.ariaLabel !== null) {
|
|
66
|
-
return element.ariaLabel;
|
|
67
|
-
}
|
|
68
|
-
if (includeTextContent) {
|
|
69
|
-
return snapshotTextContent(element);
|
|
70
|
-
}
|
|
71
|
-
return void 0;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// src/browser/state.ts
|
|
75
|
-
function disableableAttributes(element) {
|
|
76
|
-
const supportsHtmlAttribute = isNativeInputElement(element) || element instanceof HTMLButtonElement;
|
|
77
|
-
const disabled = booleanAttribute(
|
|
78
|
-
supportsHtmlAttribute ? element.hasAttribute("disabled") : false
|
|
79
|
-
);
|
|
80
|
-
return {
|
|
81
|
-
disabled: disabled ?? booleanAttribute(element.ariaDisabled)
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function selectableAttributes(element) {
|
|
85
|
-
return { selected: booleanAttribute(element.ariaSelected) };
|
|
86
|
-
}
|
|
87
|
-
function inputStateAttributes(element) {
|
|
88
|
-
const supportsHtmlAttributes = isNativeInputElement(element);
|
|
89
|
-
const readonly = booleanAttribute(
|
|
90
|
-
supportsHtmlAttributes ? element.hasAttribute("readonly") : false
|
|
91
|
-
);
|
|
92
|
-
const required = booleanAttribute(
|
|
93
|
-
supportsHtmlAttributes ? element.hasAttribute("required") : false
|
|
94
|
-
);
|
|
95
|
-
return {
|
|
96
|
-
readonly: readonly ?? booleanAttribute(element.ariaReadOnly),
|
|
97
|
-
...disableableAttributes(element),
|
|
98
|
-
required: required ?? booleanAttribute(element.ariaRequired),
|
|
99
|
-
invalid: booleanAttribute(element.ariaInvalid)
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
function isNativeInputElement(element) {
|
|
103
|
-
return element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// src/browser/button.ts
|
|
107
|
-
var PRESSED_VALUES = /* @__PURE__ */ new Set(["true", "mixed", "false"]);
|
|
108
|
-
function snapshotButton(element) {
|
|
109
|
-
return {
|
|
110
|
-
role: "button",
|
|
111
|
-
name: resolveAccessibleName(element),
|
|
112
|
-
attributes: {
|
|
113
|
-
...disableableAttributes(element),
|
|
114
|
-
expanded: booleanAttribute(element.ariaExpanded),
|
|
115
|
-
pressed: resolvePressedAttribute(element)
|
|
116
|
-
},
|
|
117
|
-
children: snapshotChildren(element)
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
function resolvePressedAttribute(element) {
|
|
121
|
-
const pressed = enumAttribute(element.ariaPressed, PRESSED_VALUES);
|
|
122
|
-
if (pressed === "mixed") {
|
|
123
|
-
return pressed;
|
|
124
|
-
}
|
|
125
|
-
return booleanAttribute(pressed === "true");
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// src/browser/description.ts
|
|
129
|
-
function discribableAttributes(element) {
|
|
130
|
-
return {
|
|
131
|
-
description: resolveDescription(element)
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
function resolveDescription(element) {
|
|
135
|
-
const describedByElement = resolveElementReference(
|
|
136
|
-
element,
|
|
137
|
-
"aria-describedby"
|
|
138
|
-
);
|
|
139
|
-
if (describedByElement !== null) {
|
|
140
|
-
return snapshotTextContent(describedByElement);
|
|
141
|
-
}
|
|
142
|
-
if (element.ariaDescription !== null) {
|
|
143
|
-
return element.ariaDescription;
|
|
144
|
-
}
|
|
145
|
-
return void 0;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// src/browser/container.ts
|
|
149
|
-
var CONTAINER_ROLES = /* @__PURE__ */ new Set([
|
|
150
|
-
"paragraph",
|
|
151
|
-
"list",
|
|
152
|
-
"listitem",
|
|
153
|
-
"listbox",
|
|
154
|
-
"article",
|
|
155
|
-
"banner",
|
|
156
|
-
"complementary",
|
|
157
|
-
"contentinfo",
|
|
158
|
-
"form",
|
|
159
|
-
"main",
|
|
160
|
-
"navigation",
|
|
161
|
-
"region",
|
|
162
|
-
"search",
|
|
163
|
-
"term",
|
|
164
|
-
"definition",
|
|
165
|
-
"table",
|
|
166
|
-
"grid",
|
|
167
|
-
"rowgroup",
|
|
168
|
-
"row",
|
|
169
|
-
"rowheader",
|
|
170
|
-
"cell",
|
|
171
|
-
"gridcell",
|
|
172
|
-
"alert",
|
|
173
|
-
"menu",
|
|
174
|
-
"tablist",
|
|
175
|
-
"tabpanel"
|
|
176
|
-
]);
|
|
177
|
-
function snapshotContainer(role, element) {
|
|
178
|
-
const children = snapshotChildren(element);
|
|
179
|
-
return {
|
|
180
|
-
role,
|
|
181
|
-
name: resolveAccessibleName(element, false),
|
|
182
|
-
children
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
function isContainerRole(role) {
|
|
186
|
-
return CONTAINER_ROLES.has(role);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// src/browser/selector.ts
|
|
190
|
-
function selectorList(...selectors) {
|
|
191
|
-
return selectors.join(",");
|
|
192
|
-
}
|
|
193
|
-
function roleSelector(roleName) {
|
|
194
|
-
return attributeSelector("role", roleName);
|
|
195
|
-
}
|
|
196
|
-
function attributeSelector(name, value) {
|
|
197
|
-
return `[${name}='${value}']`;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// src/browser/utils.ts
|
|
201
|
-
function getElementTagName(element) {
|
|
202
|
-
return element.tagName.toLowerCase();
|
|
203
|
-
}
|
|
204
|
-
function isWithinElement(element, containerSelector) {
|
|
205
|
-
return element.closest(containerSelector) !== null;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// src/browser/role.ts
|
|
209
|
-
var ELEMENT_ROLES = {
|
|
210
|
-
main: "main",
|
|
211
|
-
nav: "navigation",
|
|
212
|
-
form: "form",
|
|
213
|
-
header: "banner",
|
|
214
|
-
section: "region",
|
|
215
|
-
article: "article",
|
|
216
|
-
aside: "complementary",
|
|
217
|
-
search: "search",
|
|
218
|
-
footer: "contentinfo",
|
|
219
|
-
p: "paragraph",
|
|
220
|
-
h1: "heading",
|
|
221
|
-
h2: "heading",
|
|
222
|
-
h3: "heading",
|
|
223
|
-
h4: "heading",
|
|
224
|
-
h5: "heading",
|
|
225
|
-
h6: "heading",
|
|
226
|
-
ul: "list",
|
|
227
|
-
ol: "list",
|
|
228
|
-
li: "listitem",
|
|
229
|
-
a: "link",
|
|
230
|
-
button: "button",
|
|
231
|
-
input: resolveInputRole,
|
|
232
|
-
textarea: "textbox",
|
|
233
|
-
select: "combobox",
|
|
234
|
-
option: "option",
|
|
235
|
-
dt: "term",
|
|
236
|
-
dd: "definition",
|
|
237
|
-
table: "table",
|
|
238
|
-
thead: "rowgroup",
|
|
239
|
-
tbody: "rowgroup",
|
|
240
|
-
tfoot: "rowgroup",
|
|
241
|
-
tr: "row",
|
|
242
|
-
th: resolveTableHeaderCellRole,
|
|
243
|
-
td: "cell",
|
|
244
|
-
fieldset: "group",
|
|
245
|
-
progress: "progressbar"
|
|
246
|
-
};
|
|
247
|
-
var CONTEXT_DEPENDENT_ROLES = {
|
|
248
|
-
banner: isTopLevelBanner,
|
|
249
|
-
region: hasAccessibleName,
|
|
250
|
-
term: isWithinDescriptionList,
|
|
251
|
-
definition: isWithinDescriptionList,
|
|
252
|
-
listitem: isWithinList,
|
|
253
|
-
menuitem: isWithinMenu,
|
|
254
|
-
rowgroup: isWithinTableOrGrid,
|
|
255
|
-
row: isWithinTableOrGrid,
|
|
256
|
-
columnheader: isWithinTableRowOrGridRow,
|
|
257
|
-
rowheader: isWithinTableRowOrGridRow,
|
|
258
|
-
cell: isWithinTableRow,
|
|
259
|
-
gridcell: isWithinGridRow,
|
|
260
|
-
tab: isWithinTablist
|
|
261
|
-
};
|
|
262
|
-
var INPUT_ROLES = {
|
|
263
|
-
button: "button",
|
|
264
|
-
checkbox: "checkbox",
|
|
265
|
-
email: "textbox",
|
|
266
|
-
image: "button",
|
|
267
|
-
number: "spinbutton",
|
|
268
|
-
radio: "radio",
|
|
269
|
-
range: "slider",
|
|
270
|
-
reset: "button",
|
|
271
|
-
search: "searchbox",
|
|
272
|
-
submit: "button",
|
|
273
|
-
tel: "searchbox",
|
|
274
|
-
text: "textbox",
|
|
275
|
-
url: "textbox"
|
|
276
|
-
};
|
|
277
|
-
function parseElementRole(element) {
|
|
278
|
-
const resolvedElementRole = resolveElementRole(element);
|
|
279
|
-
if (resolvedElementRole === void 0) {
|
|
280
|
-
return void 0;
|
|
281
|
-
}
|
|
282
|
-
const isValidInContext = CONTEXT_DEPENDENT_ROLES[resolvedElementRole];
|
|
283
|
-
if (isValidInContext !== void 0 && !isValidInContext(element)) {
|
|
284
|
-
return void 0;
|
|
285
|
-
}
|
|
286
|
-
return resolvedElementRole;
|
|
287
|
-
}
|
|
288
|
-
function resolveElementRole(element) {
|
|
289
|
-
const explicitRole = element.role;
|
|
290
|
-
if (isIgnoredRole(explicitRole)) {
|
|
291
|
-
return void 0;
|
|
292
|
-
}
|
|
293
|
-
if (explicitRole !== null && (hasRoleSpecificSnapshot(explicitRole) || isContainerRole(explicitRole))) {
|
|
294
|
-
return explicitRole;
|
|
295
|
-
}
|
|
296
|
-
const tagName = getElementTagName(element);
|
|
297
|
-
const roleResolver = ELEMENT_ROLES[tagName];
|
|
298
|
-
if (roleResolver === void 0) {
|
|
299
|
-
return void 0;
|
|
300
|
-
}
|
|
301
|
-
if (typeof roleResolver === "string") {
|
|
302
|
-
return roleResolver;
|
|
303
|
-
}
|
|
304
|
-
return roleResolver(element);
|
|
305
|
-
}
|
|
306
|
-
function isIgnoredRole(role) {
|
|
307
|
-
return role === "presentation" || role === "none";
|
|
308
|
-
}
|
|
309
|
-
function resolveInputRole(element) {
|
|
310
|
-
if (!(element instanceof HTMLInputElement)) {
|
|
311
|
-
return void 0;
|
|
312
|
-
}
|
|
313
|
-
const roleResolver = INPUT_ROLES[element.type];
|
|
314
|
-
if (roleResolver === void 0) {
|
|
315
|
-
return "textbox";
|
|
316
|
-
}
|
|
317
|
-
if (typeof roleResolver === "string") {
|
|
318
|
-
return roleResolver;
|
|
319
|
-
}
|
|
320
|
-
return roleResolver(element);
|
|
321
|
-
}
|
|
322
|
-
var DISALLOWED_BANNER_CONTAINER_ELEMENTS = [
|
|
323
|
-
"article",
|
|
324
|
-
"aside",
|
|
325
|
-
"main",
|
|
326
|
-
"nav",
|
|
327
|
-
"section"
|
|
328
|
-
];
|
|
329
|
-
var DISALLOWED_BANNER_CONTAINER_ROLES = [
|
|
330
|
-
"article",
|
|
331
|
-
"complementary",
|
|
332
|
-
"main",
|
|
333
|
-
"navigation",
|
|
334
|
-
"region"
|
|
335
|
-
];
|
|
336
|
-
function isTopLevelBanner(element) {
|
|
337
|
-
const disallowedContainerSelector = selectorList(
|
|
338
|
-
...DISALLOWED_BANNER_CONTAINER_ELEMENTS,
|
|
339
|
-
...DISALLOWED_BANNER_CONTAINER_ROLES.map(roleSelector)
|
|
340
|
-
);
|
|
341
|
-
return !isWithinElement(element, disallowedContainerSelector);
|
|
342
|
-
}
|
|
343
|
-
function hasAccessibleName(element) {
|
|
344
|
-
const accessibleName = resolveAccessibleName(element, false);
|
|
345
|
-
return accessibleName !== void 0;
|
|
346
|
-
}
|
|
347
|
-
function isWithinDescriptionList(element) {
|
|
348
|
-
return isWithinElement(element, "dl");
|
|
349
|
-
}
|
|
350
|
-
function resolveTableHeaderCellRole(element) {
|
|
351
|
-
if (!(element instanceof HTMLTableCellElement)) {
|
|
352
|
-
return void 0;
|
|
353
|
-
}
|
|
354
|
-
const scope = element.scope;
|
|
355
|
-
switch (scope) {
|
|
356
|
-
case "col":
|
|
357
|
-
return "columnheader";
|
|
358
|
-
case "row":
|
|
359
|
-
return "rowheader";
|
|
360
|
-
default:
|
|
361
|
-
return void 0;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
function isWithinTableOrGrid(element) {
|
|
365
|
-
return isWithinTable(element) || isWithinGrid(element);
|
|
366
|
-
}
|
|
367
|
-
function isWithinTable(element) {
|
|
368
|
-
return isWithinElement(element, selectorList("table", roleSelector("table")));
|
|
369
|
-
}
|
|
370
|
-
function isWithinGrid(element) {
|
|
371
|
-
return isWithinElement(element, roleSelector("grid"));
|
|
372
|
-
}
|
|
373
|
-
function isWithinTableRowOrGridRow(element) {
|
|
374
|
-
return isWithinTableRow(element) || isWithinGridRow(element);
|
|
375
|
-
}
|
|
376
|
-
function isWithinTableRow(element) {
|
|
377
|
-
const closestRow = element.closest(selectorList("tr", roleSelector("row")));
|
|
378
|
-
return closestRow !== null && isWithinTable(closestRow);
|
|
379
|
-
}
|
|
380
|
-
function isWithinGridRow(element) {
|
|
381
|
-
const closestRow = element.closest(selectorList("tr", roleSelector("row")));
|
|
382
|
-
return closestRow !== null && isWithinGrid(closestRow);
|
|
383
|
-
}
|
|
384
|
-
function isWithinList(element) {
|
|
385
|
-
return isWithinElement(
|
|
386
|
-
element,
|
|
387
|
-
selectorList("ul", "ol", roleSelector("list"))
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
function isWithinMenu(element) {
|
|
391
|
-
return isWithinElement(element, roleSelector("menu"));
|
|
392
|
-
}
|
|
393
|
-
function isWithinTablist(element) {
|
|
394
|
-
return isWithinElement(element, roleSelector("tablist"));
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// src/browser/input.ts
|
|
398
|
-
function snapshotInput(element) {
|
|
399
|
-
if (element instanceof HTMLInputElement) {
|
|
400
|
-
return snapshotInputElement(element);
|
|
401
|
-
}
|
|
402
|
-
if (element instanceof HTMLTextAreaElement) {
|
|
403
|
-
return snapshotTextareaElement(element);
|
|
404
|
-
}
|
|
405
|
-
return null;
|
|
406
|
-
}
|
|
407
|
-
function snapshotInputElement(element) {
|
|
408
|
-
const inputRole = resolveInputRole(element);
|
|
409
|
-
if (inputRole === void 0 || inputRole === "button" || inputRole === "combobox") {
|
|
410
|
-
return null;
|
|
411
|
-
}
|
|
412
|
-
const value = resolveInputValue(element);
|
|
413
|
-
return {
|
|
414
|
-
role: inputRole,
|
|
415
|
-
name: resolveInputLabel(element),
|
|
416
|
-
attributes: {
|
|
417
|
-
value,
|
|
418
|
-
checked: resolveChecked(element),
|
|
419
|
-
...snapshotCommonInputAttributes(element, value === void 0)
|
|
420
|
-
}
|
|
421
|
-
};
|
|
422
|
-
}
|
|
423
|
-
function snapshotTextareaElement(element) {
|
|
424
|
-
const value = resolveInputValue(element);
|
|
425
|
-
return {
|
|
426
|
-
role: "textbox",
|
|
427
|
-
name: resolveInputLabel(element),
|
|
428
|
-
attributes: {
|
|
429
|
-
value,
|
|
430
|
-
...snapshotCommonInputAttributes(element, value === void 0)
|
|
431
|
-
}
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
function snapshotCommonInputAttributes(element, isEmpty) {
|
|
435
|
-
return {
|
|
436
|
-
...discribableAttributes(element),
|
|
437
|
-
placeholder: isEmpty ? resolvePlaceholder(element) : void 0,
|
|
438
|
-
...inputStateAttributes(element)
|
|
439
|
-
};
|
|
440
|
-
}
|
|
441
|
-
var CHECKED_INPUT_TYPES = /* @__PURE__ */ new Set(["checkbox", "radio"]);
|
|
442
|
-
function resolveInputValue(element) {
|
|
443
|
-
if (element instanceof HTMLInputElement && CHECKED_INPUT_TYPES.has(element.type)) {
|
|
444
|
-
return void 0;
|
|
445
|
-
}
|
|
446
|
-
return stringAttribute(element.value);
|
|
447
|
-
}
|
|
448
|
-
function resolveChecked(element) {
|
|
449
|
-
if (!(element instanceof HTMLInputElement)) {
|
|
450
|
-
return void 0;
|
|
451
|
-
}
|
|
452
|
-
return element.checked ? true : void 0;
|
|
453
|
-
}
|
|
454
|
-
function resolveInputLabel(element) {
|
|
455
|
-
const accessibleName = resolveAccessibleName(element, false);
|
|
456
|
-
if (accessibleName !== void 0) {
|
|
457
|
-
return accessibleName;
|
|
458
|
-
}
|
|
459
|
-
if (element.id !== null) {
|
|
460
|
-
const referencedElement = element.ownerDocument.querySelector(
|
|
461
|
-
`[for='${element.id}']`
|
|
462
|
-
);
|
|
463
|
-
if (referencedElement !== null) {
|
|
464
|
-
return snapshotTextContent(referencedElement);
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
const closestLabel = element.closest("label");
|
|
468
|
-
if (closestLabel !== null) {
|
|
469
|
-
return snapshotTextContent(closestLabel);
|
|
470
|
-
}
|
|
471
|
-
return void 0;
|
|
472
|
-
}
|
|
473
|
-
function resolvePlaceholder(element) {
|
|
474
|
-
if (element instanceof HTMLSelectElement || element instanceof HTMLButtonElement) {
|
|
475
|
-
return void 0;
|
|
476
|
-
}
|
|
477
|
-
return stringAttribute(element.placeholder);
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// src/browser/combobox.ts
|
|
481
|
-
function snapshotCombobox(element) {
|
|
482
|
-
if (!isCombobox(element)) {
|
|
483
|
-
return null;
|
|
484
|
-
}
|
|
485
|
-
const options = snapshotOptions(element);
|
|
486
|
-
const value = resolveValue(element);
|
|
487
|
-
return {
|
|
488
|
-
role: "combobox",
|
|
489
|
-
name: resolveInputLabel(element),
|
|
490
|
-
attributes: {
|
|
491
|
-
value,
|
|
492
|
-
...snapshotCommonInputAttributes(element, value === void 0)
|
|
493
|
-
},
|
|
494
|
-
options
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
function isCombobox(element) {
|
|
498
|
-
if (element instanceof HTMLSelectElement) {
|
|
499
|
-
return element.role === null || element.role === "combobox";
|
|
500
|
-
}
|
|
501
|
-
if (element instanceof HTMLInputElement || element instanceof HTMLButtonElement) {
|
|
502
|
-
return element.role === "combobox";
|
|
503
|
-
}
|
|
504
|
-
return false;
|
|
505
|
-
}
|
|
506
|
-
function resolveValue(element) {
|
|
507
|
-
if (element instanceof HTMLButtonElement) {
|
|
508
|
-
return snapshotTextContent(element);
|
|
509
|
-
}
|
|
510
|
-
if (element instanceof HTMLInputElement) {
|
|
511
|
-
return resolveInputValue(element);
|
|
512
|
-
}
|
|
513
|
-
const selectedLabels = Array.from(element.selectedOptions).map(
|
|
514
|
-
(option) => option.label
|
|
515
|
-
);
|
|
516
|
-
if (selectedLabels.length === 0) {
|
|
517
|
-
return void 0;
|
|
518
|
-
}
|
|
519
|
-
if (selectedLabels.length === 1) {
|
|
520
|
-
return selectedLabels.at(0);
|
|
521
|
-
}
|
|
522
|
-
return selectedLabels;
|
|
523
|
-
}
|
|
524
|
-
function snapshotOptions(element) {
|
|
525
|
-
return resolveOptions(element).map(snapshotOption).filter((childSnapshot) => childSnapshot !== null);
|
|
526
|
-
}
|
|
527
|
-
function resolveOptions(element) {
|
|
528
|
-
if (element instanceof HTMLSelectElement) {
|
|
529
|
-
return Array.from(element.options);
|
|
530
|
-
}
|
|
531
|
-
const controlledElement = resolveElementReference(element, "aria-controls");
|
|
532
|
-
if (controlledElement === null) {
|
|
533
|
-
return [];
|
|
534
|
-
}
|
|
535
|
-
const optionSelector = selectorList("option", roleSelector("option"));
|
|
536
|
-
return Array.from(controlledElement.querySelectorAll(optionSelector));
|
|
537
|
-
}
|
|
538
|
-
function snapshotOption(element) {
|
|
539
|
-
return {
|
|
540
|
-
role: "option",
|
|
541
|
-
name: resolveAccessibleName(element),
|
|
542
|
-
attributes: {
|
|
543
|
-
selected: element instanceof HTMLOptionElement ? booleanAttribute(element.selected) : booleanAttribute(element.ariaSelected)
|
|
544
|
-
},
|
|
545
|
-
children: snapshotChildren(element)
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// src/browser/dialog.ts
|
|
550
|
-
function snapshotDialogWithRole(role) {
|
|
551
|
-
return (element) => snapshotDialog(role, element);
|
|
552
|
-
}
|
|
553
|
-
function snapshotDialog(role, element) {
|
|
554
|
-
return {
|
|
555
|
-
role,
|
|
556
|
-
name: resolveAccessibleName(element, false),
|
|
557
|
-
attributes: {
|
|
558
|
-
...discribableAttributes(element),
|
|
559
|
-
modal: booleanAttribute(element.ariaModal)
|
|
560
|
-
},
|
|
561
|
-
children: snapshotChildren(element)
|
|
562
|
-
};
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
// src/browser/group.ts
|
|
566
|
-
function snapshotGroup(element) {
|
|
567
|
-
return {
|
|
568
|
-
role: "group",
|
|
569
|
-
name: resolveGroupName(element),
|
|
570
|
-
children: snapshotChildren(element)
|
|
571
|
-
};
|
|
572
|
-
}
|
|
573
|
-
function resolveGroupName(element) {
|
|
574
|
-
const legendElement = element instanceof HTMLFieldSetElement ? element.querySelector("legend") : null;
|
|
575
|
-
if (legendElement !== null) {
|
|
576
|
-
return snapshotTextContent(legendElement);
|
|
577
|
-
}
|
|
578
|
-
return resolveAccessibleName(element, false);
|
|
579
|
-
}
|
|
580
|
-
function snapshotRadiogroup(element) {
|
|
581
|
-
return {
|
|
582
|
-
role: "radiogroup",
|
|
583
|
-
name: resolveAccessibleName(element, false),
|
|
584
|
-
attributes: discribableAttributes(element),
|
|
585
|
-
children: snapshotChildren(element)
|
|
586
|
-
};
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
// src/browser/heading.ts
|
|
590
|
-
var LEVEL_REGEXP = /^H([1-6])$/;
|
|
591
|
-
function snapshotHeading(element) {
|
|
592
|
-
if (!(element instanceof HTMLHeadingElement)) {
|
|
593
|
-
return null;
|
|
594
|
-
}
|
|
595
|
-
return {
|
|
596
|
-
role: "heading",
|
|
597
|
-
name: resolveAccessibleName(element),
|
|
598
|
-
attributes: {
|
|
599
|
-
level: resolveLevel(element)
|
|
600
|
-
},
|
|
601
|
-
children: snapshotChildren(element)
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
|
-
function resolveLevel(element) {
|
|
605
|
-
const levelAsString = LEVEL_REGEXP.exec(element.nodeName)?.at(1) ?? null;
|
|
606
|
-
return numericAttribute(levelAsString);
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
// src/browser/link.ts
|
|
610
|
-
function snapshotLink(element) {
|
|
611
|
-
return {
|
|
612
|
-
role: "link",
|
|
613
|
-
name: resolveAccessibleName(element),
|
|
614
|
-
attributes: linkAttributes(element),
|
|
615
|
-
children: snapshotChildren(element)
|
|
616
|
-
};
|
|
617
|
-
}
|
|
618
|
-
function linkAttributes(element) {
|
|
619
|
-
return { url: stringAttribute(element.getAttribute("href")) };
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
// src/browser/list.ts
|
|
623
|
-
function snapshotMenuitem(element) {
|
|
624
|
-
return {
|
|
625
|
-
role: "menuitem",
|
|
626
|
-
name: resolveAccessibleName(element),
|
|
627
|
-
attributes: {
|
|
628
|
-
...linkAttributes(element),
|
|
629
|
-
...disableableAttributes(element)
|
|
630
|
-
},
|
|
631
|
-
children: snapshotChildren(element)
|
|
632
|
-
};
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
// src/browser/progressbar.ts
|
|
636
|
-
function snapshotProgressbar(element) {
|
|
637
|
-
return {
|
|
638
|
-
role: "progressbar",
|
|
639
|
-
name: resolveAccessibleName(element, false),
|
|
640
|
-
attributes: {
|
|
641
|
-
value: resolveValue2(element)
|
|
642
|
-
},
|
|
643
|
-
children: snapshotChildren(element)
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
function resolveValue2(element) {
|
|
647
|
-
if (element instanceof HTMLProgressElement) {
|
|
648
|
-
return element.value;
|
|
649
|
-
}
|
|
650
|
-
return numericAttribute(element.ariaValueNow);
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
// src/browser/tab.ts
|
|
654
|
-
function snapshotTab(element) {
|
|
655
|
-
return {
|
|
656
|
-
role: "tab",
|
|
657
|
-
name: resolveAccessibleName(element),
|
|
658
|
-
attributes: {
|
|
659
|
-
...disableableAttributes(element),
|
|
660
|
-
...selectableAttributes(element)
|
|
661
|
-
},
|
|
662
|
-
children: snapshotChildren(element)
|
|
663
|
-
};
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
// src/browser/table.ts
|
|
667
|
-
var SORT_ATTRIBUTES = /* @__PURE__ */ new Set(["ascending", "descending", "other"]);
|
|
668
|
-
function snapshotColumnheader(element) {
|
|
669
|
-
return {
|
|
670
|
-
role: "columnheader",
|
|
671
|
-
name: resolveAccessibleName(element),
|
|
672
|
-
attributes: {
|
|
673
|
-
sort: enumAttribute(element.ariaSort, SORT_ATTRIBUTES)
|
|
674
|
-
},
|
|
675
|
-
children: snapshotChildren(element)
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
// src/browser/element.ts
|
|
680
|
-
var ROLE_SNAPSHOTS = {
|
|
681
|
-
button: snapshotButton,
|
|
682
|
-
checkbox: snapshotInput,
|
|
683
|
-
combobox: snapshotCombobox,
|
|
684
|
-
option: snapshotOption,
|
|
685
|
-
heading: snapshotHeading,
|
|
686
|
-
link: snapshotLink,
|
|
687
|
-
radio: snapshotInput,
|
|
688
|
-
searchbox: snapshotInput,
|
|
689
|
-
slider: snapshotInput,
|
|
690
|
-
spinbutton: snapshotInput,
|
|
691
|
-
textbox: snapshotInput,
|
|
692
|
-
dialog: snapshotDialogWithRole("dialog"),
|
|
693
|
-
alertdialog: snapshotDialogWithRole("alertdialog"),
|
|
694
|
-
tab: snapshotTab,
|
|
695
|
-
menuitem: snapshotMenuitem,
|
|
696
|
-
columnheader: snapshotColumnheader,
|
|
697
|
-
group: snapshotGroup,
|
|
698
|
-
radiogroup: snapshotRadiogroup,
|
|
699
|
-
progressbar: snapshotProgressbar
|
|
700
|
-
};
|
|
701
|
-
function snapshotElement(element) {
|
|
702
|
-
return snapshotNodeRecursive(element);
|
|
703
|
-
}
|
|
704
|
-
function snapshotNodeRecursive(node) {
|
|
705
|
-
const snapshot = snapshotNodeByType(node);
|
|
706
|
-
if (snapshot === null) {
|
|
707
|
-
return [];
|
|
708
|
-
}
|
|
709
|
-
if (Array.isArray(snapshot)) {
|
|
710
|
-
return snapshot;
|
|
711
|
-
}
|
|
712
|
-
return [snapshot];
|
|
713
|
-
}
|
|
714
|
-
function snapshotNodeByType(node) {
|
|
715
|
-
if (node.nodeType === Node.TEXT_NODE) {
|
|
716
|
-
return snapshotTextNode(node);
|
|
717
|
-
}
|
|
718
|
-
if (!isSupportedElement(node) || isHiddenElement(node)) {
|
|
719
|
-
return null;
|
|
720
|
-
}
|
|
721
|
-
const elementRole = parseElementRole(node);
|
|
722
|
-
if (elementRole === void 0) {
|
|
723
|
-
return snapshotChildren(node) ?? null;
|
|
724
|
-
}
|
|
725
|
-
if (hasRoleSpecificSnapshot(elementRole)) {
|
|
726
|
-
const snapshotByRole = ROLE_SNAPSHOTS[elementRole];
|
|
727
|
-
return snapshotByRole(node);
|
|
728
|
-
}
|
|
729
|
-
return snapshotContainer(elementRole, node);
|
|
730
|
-
}
|
|
731
|
-
var UNSUPPORTED_ELEMENTS = /* @__PURE__ */ new Set([
|
|
732
|
-
"style",
|
|
733
|
-
"script",
|
|
734
|
-
"noscript",
|
|
735
|
-
"img",
|
|
736
|
-
"picture",
|
|
737
|
-
"audio",
|
|
738
|
-
"video",
|
|
739
|
-
"figure",
|
|
740
|
-
"template"
|
|
741
|
-
]);
|
|
742
|
-
function isSupportedElement(node) {
|
|
743
|
-
if (!(node instanceof HTMLElement)) {
|
|
744
|
-
return false;
|
|
745
|
-
}
|
|
746
|
-
const tagName = getElementTagName(node);
|
|
747
|
-
return !UNSUPPORTED_ELEMENTS.has(tagName);
|
|
748
|
-
}
|
|
749
|
-
function hasRoleSpecificSnapshot(role) {
|
|
750
|
-
return role in ROLE_SNAPSHOTS;
|
|
751
|
-
}
|
|
752
|
-
function isHiddenElement(element) {
|
|
753
|
-
if (element.hasAttribute("hidden")) {
|
|
754
|
-
return true;
|
|
755
|
-
}
|
|
756
|
-
const ariaHidden = booleanAttribute(element.ariaHidden);
|
|
757
|
-
if (ariaHidden === true) {
|
|
758
|
-
return true;
|
|
759
|
-
}
|
|
760
|
-
const cssStyles = window.getComputedStyle(element);
|
|
761
|
-
return cssStyles.display === "none" || cssStyles.visibility === "hidden" || cssStyles.visibility === "collapse";
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
// src/browser-lib.ts
|
|
765
|
-
window.snapshotElement = snapshotElement;
|
|
766
|
-
})();
|