@accesslint/core 0.1.2 → 0.2.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 +64 -33
- package/dist/index.cjs +5 -5
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.iife.js +5 -5
- package/dist/index.js +1080 -981
- package/dist/rules/aria/aria-hidden-rules.d.ts.map +1 -1
- package/dist/rules/color/color-contrast.d.ts +3 -0
- package/dist/rules/color/color-contrast.d.ts.map +1 -0
- package/dist/rules/images/server-side-image-map.d.ts +1 -2
- package/dist/rules/images/server-side-image-map.d.ts.map +1 -1
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/keyboard/tabindex.d.ts +1 -2
- package/dist/rules/keyboard/tabindex.d.ts.map +1 -1
- package/dist/rules/structure/deprecated-elements.d.ts +2 -3
- package/dist/rules/structure/deprecated-elements.d.ts.map +1 -1
- package/dist/rules/structure/list-rules.d.ts.map +1 -1
- package/dist/rules/types.d.ts +0 -14
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/utils/color.d.ts +8 -0
- package/dist/rules/utils/color.d.ts.map +1 -0
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
let
|
|
2
|
-
function
|
|
3
|
-
|
|
1
|
+
let $ = /* @__PURE__ */ new WeakMap();
|
|
2
|
+
function K() {
|
|
3
|
+
$ = /* @__PURE__ */ new WeakMap();
|
|
4
4
|
}
|
|
5
|
-
function
|
|
5
|
+
function Y(t) {
|
|
6
6
|
var i;
|
|
7
7
|
const a = t.tagName.toLowerCase(), e = (i = t.getAttribute("type")) == null ? void 0 : i.toLowerCase();
|
|
8
8
|
switch (a) {
|
|
@@ -117,28 +117,28 @@ function U(t) {
|
|
|
117
117
|
return null;
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
|
-
function
|
|
121
|
-
var
|
|
122
|
-
const a =
|
|
120
|
+
function T(t) {
|
|
121
|
+
var n;
|
|
122
|
+
const a = $.get(t);
|
|
123
123
|
if (a !== void 0) return a;
|
|
124
|
-
const i = ((
|
|
125
|
-
return
|
|
124
|
+
const i = ((n = t.getAttribute("role")) == null ? void 0 : n.trim().toLowerCase()) || null || Y(t);
|
|
125
|
+
return $.set(t, i), i;
|
|
126
126
|
}
|
|
127
|
-
function
|
|
128
|
-
var
|
|
127
|
+
function b(t) {
|
|
128
|
+
var r, o, s, u, h;
|
|
129
129
|
const a = t.getAttribute("aria-labelledby");
|
|
130
130
|
if (a) {
|
|
131
131
|
const d = a.split(/\s+/).map((p) => {
|
|
132
|
-
const
|
|
133
|
-
return
|
|
132
|
+
const g = t.ownerDocument.getElementById(p);
|
|
133
|
+
return g ? w(g).trim() : "";
|
|
134
134
|
}).filter(Boolean);
|
|
135
135
|
if (d.length) return d.join(" ");
|
|
136
136
|
}
|
|
137
|
-
const e = (
|
|
137
|
+
const e = (r = t.getAttribute("aria-label")) == null ? void 0 : r.trim();
|
|
138
138
|
if (e) return e;
|
|
139
139
|
if (t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement || t instanceof HTMLSelectElement) {
|
|
140
140
|
if (t.id) {
|
|
141
|
-
const
|
|
141
|
+
const g = t.ownerDocument.querySelector(`label[for="${CSS.escape(t.id)}"]`), f = g ? w(g).trim() : "";
|
|
142
142
|
if (f) return f;
|
|
143
143
|
}
|
|
144
144
|
const d = t.closest("label"), p = d ? w(d).trim() : "";
|
|
@@ -150,15 +150,15 @@ function g(t) {
|
|
|
150
150
|
const d = (s = t.getAttribute("placeholder")) == null ? void 0 : s.trim();
|
|
151
151
|
if (d) return d;
|
|
152
152
|
}
|
|
153
|
-
const
|
|
154
|
-
if (
|
|
153
|
+
const n = t.tagName.toLowerCase();
|
|
154
|
+
if (n === "fieldset") {
|
|
155
155
|
const d = t.querySelector(":scope > legend");
|
|
156
156
|
if (d) {
|
|
157
157
|
const p = w(d).trim();
|
|
158
158
|
if (p) return p;
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
|
-
if (
|
|
161
|
+
if (n === "table") {
|
|
162
162
|
const d = t.querySelector(":scope > caption");
|
|
163
163
|
if (d) {
|
|
164
164
|
const p = w(d).trim();
|
|
@@ -169,9 +169,9 @@ function g(t) {
|
|
|
169
169
|
const d = w(t).trim();
|
|
170
170
|
if (d) return d;
|
|
171
171
|
}
|
|
172
|
-
return t instanceof HTMLImageElement || t instanceof HTMLAreaElement ? ((
|
|
172
|
+
return t instanceof HTMLImageElement || t instanceof HTMLAreaElement ? ((u = t.alt) == null ? void 0 : u.trim()) ?? "" : t instanceof HTMLInputElement && t.type === "image" ? ((h = t.alt) == null ? void 0 : h.trim()) ?? "" : "";
|
|
173
173
|
}
|
|
174
|
-
const
|
|
174
|
+
const oe = /* @__PURE__ */ new Set([
|
|
175
175
|
"alert",
|
|
176
176
|
"alertdialog",
|
|
177
177
|
"application",
|
|
@@ -255,52 +255,52 @@ const J = /* @__PURE__ */ new Set([
|
|
|
255
255
|
"treegrid",
|
|
256
256
|
"treeitem"
|
|
257
257
|
]);
|
|
258
|
-
function
|
|
258
|
+
function se(t) {
|
|
259
259
|
const a = t.trim().toLowerCase().replace(/[\u201C\u201D\u2018\u2019\u00AB\u00BB]/g, "");
|
|
260
|
-
return
|
|
260
|
+
return oe.has(a);
|
|
261
261
|
}
|
|
262
|
-
let
|
|
263
|
-
function
|
|
264
|
-
|
|
262
|
+
let M = /* @__PURE__ */ new WeakMap();
|
|
263
|
+
function Q() {
|
|
264
|
+
M = /* @__PURE__ */ new WeakMap();
|
|
265
265
|
}
|
|
266
|
-
function
|
|
267
|
-
const a =
|
|
266
|
+
function m(t) {
|
|
267
|
+
const a = M.get(t);
|
|
268
268
|
if (a !== void 0) return a;
|
|
269
269
|
let e;
|
|
270
|
-
return t.getAttribute("aria-hidden") === "true" || t instanceof HTMLElement && (t.hidden || t.style.display === "none") ? e = !0 : t.parentElement ? e =
|
|
270
|
+
return t.getAttribute("aria-hidden") === "true" || t instanceof HTMLElement && (t.hidden || t.style.display === "none") ? e = !0 : t.parentElement ? e = m(t.parentElement) : e = !1, M.set(t, e), e;
|
|
271
271
|
}
|
|
272
|
-
function
|
|
272
|
+
function le(t) {
|
|
273
273
|
return !!(t.getAttribute("aria-hidden") === "true" || t instanceof HTMLElement && (t.hidden || t.style.display === "none"));
|
|
274
274
|
}
|
|
275
275
|
function w(t) {
|
|
276
|
-
var e, i,
|
|
276
|
+
var e, i, n, r;
|
|
277
277
|
let a = "";
|
|
278
278
|
for (const o of t.childNodes)
|
|
279
279
|
if (o.nodeType === 3)
|
|
280
280
|
a += o.textContent ?? "";
|
|
281
281
|
else if (o.nodeType === 1) {
|
|
282
282
|
const s = o;
|
|
283
|
-
if (!
|
|
284
|
-
const
|
|
285
|
-
if (
|
|
283
|
+
if (!le(s)) {
|
|
284
|
+
const u = (e = s.tagName) == null ? void 0 : e.toLowerCase();
|
|
285
|
+
if (u === "img" || u === "area")
|
|
286
286
|
a += ((i = s.getAttribute("aria-label")) == null ? void 0 : i.trim()) ?? s.getAttribute("alt") ?? "";
|
|
287
|
-
else if (
|
|
288
|
-
const h = (
|
|
287
|
+
else if (u === "svg") {
|
|
288
|
+
const h = (n = s.getAttribute("aria-label")) == null ? void 0 : n.trim();
|
|
289
289
|
if (h)
|
|
290
290
|
a += h;
|
|
291
291
|
else {
|
|
292
292
|
const d = s.querySelector("title");
|
|
293
293
|
d && (a += d.textContent ?? "");
|
|
294
294
|
}
|
|
295
|
-
} else (
|
|
295
|
+
} else (r = s.getAttribute("aria-label")) != null && r.trim() ? a += s.getAttribute("aria-label").trim() : a += w(s);
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
298
|
return a;
|
|
299
299
|
}
|
|
300
|
-
function
|
|
300
|
+
function ce(t) {
|
|
301
301
|
return t.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
302
302
|
}
|
|
303
|
-
const
|
|
303
|
+
const de = [
|
|
304
304
|
"data-testid",
|
|
305
305
|
"data-test-id",
|
|
306
306
|
"data-cy",
|
|
@@ -310,41 +310,41 @@ const ae = [
|
|
|
310
310
|
"for",
|
|
311
311
|
"aria-label"
|
|
312
312
|
];
|
|
313
|
-
function
|
|
313
|
+
function ue(t) {
|
|
314
314
|
const a = t.tagName.toLowerCase();
|
|
315
|
-
for (const i of
|
|
316
|
-
const
|
|
317
|
-
if (
|
|
318
|
-
return `${a}[${i}="${
|
|
315
|
+
for (const i of de) {
|
|
316
|
+
const n = t.getAttribute(i);
|
|
317
|
+
if (n != null && n.length > 0 && n.length < 100)
|
|
318
|
+
return `${a}[${i}="${ce(n)}"]`;
|
|
319
319
|
}
|
|
320
320
|
const e = t.parentElement;
|
|
321
321
|
if (e) {
|
|
322
322
|
const i = Array.from(e.children).filter(
|
|
323
|
-
(
|
|
323
|
+
(n) => n.tagName === t.tagName
|
|
324
324
|
);
|
|
325
325
|
if (i.length > 1)
|
|
326
326
|
return `${a}:nth-of-type(${i.indexOf(t) + 1})`;
|
|
327
327
|
}
|
|
328
328
|
return a;
|
|
329
329
|
}
|
|
330
|
-
function
|
|
330
|
+
function R(t) {
|
|
331
331
|
if (t.id) return `#${CSS.escape(t.id)}`;
|
|
332
332
|
const a = t.getRootNode(), e = a instanceof ShadowRoot ? null : a.documentElement, i = [];
|
|
333
|
-
let
|
|
334
|
-
for (;
|
|
335
|
-
if (
|
|
336
|
-
i.unshift(`#${CSS.escape(
|
|
333
|
+
let n = t;
|
|
334
|
+
for (; n && n !== e; ) {
|
|
335
|
+
if (n !== t && n.id) {
|
|
336
|
+
i.unshift(`#${CSS.escape(n.id)}`);
|
|
337
337
|
break;
|
|
338
338
|
}
|
|
339
|
-
if (i.unshift(
|
|
340
|
-
const
|
|
339
|
+
if (i.unshift(ue(n)), i.length >= 2) {
|
|
340
|
+
const r = i.join(" > ");
|
|
341
341
|
try {
|
|
342
|
-
const o = a.querySelectorAll(
|
|
343
|
-
if (o.length === 1 && o[0] === t) return
|
|
342
|
+
const o = a.querySelectorAll(r);
|
|
343
|
+
if (o.length === 1 && o[0] === t) return r;
|
|
344
344
|
} catch {
|
|
345
345
|
}
|
|
346
346
|
}
|
|
347
|
-
|
|
347
|
+
n = n.parentElement;
|
|
348
348
|
}
|
|
349
349
|
return i.join(" > ");
|
|
350
350
|
}
|
|
@@ -353,26 +353,59 @@ function c(t) {
|
|
|
353
353
|
const a = [];
|
|
354
354
|
let e = t;
|
|
355
355
|
for (; e; ) {
|
|
356
|
-
const
|
|
357
|
-
if (
|
|
358
|
-
a.unshift({ selector:
|
|
356
|
+
const n = e.getRootNode();
|
|
357
|
+
if (n instanceof ShadowRoot)
|
|
358
|
+
a.unshift({ selector: R(e), delimiter: " >>> " }), e = n.host;
|
|
359
359
|
else {
|
|
360
|
-
const
|
|
361
|
-
if (
|
|
362
|
-
a.unshift({ selector:
|
|
360
|
+
const r = (i = n.defaultView) == null ? void 0 : i.frameElement;
|
|
361
|
+
if (r)
|
|
362
|
+
a.unshift({ selector: R(e), delimiter: " >>>iframe> " }), e = r;
|
|
363
363
|
else {
|
|
364
|
-
a.unshift({ selector:
|
|
364
|
+
a.unshift({ selector: R(e), delimiter: "" });
|
|
365
365
|
break;
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
|
-
return a.map((
|
|
369
|
+
return a.map((n, r) => (r === 0 ? "" : n.delimiter) + n.selector).join("");
|
|
370
|
+
}
|
|
371
|
+
function Ma(t) {
|
|
372
|
+
const a = [], e = [];
|
|
373
|
+
let i = t;
|
|
374
|
+
for (; i; ) {
|
|
375
|
+
const r = i.indexOf(" >>>iframe> "), o = i.indexOf(" >>> ");
|
|
376
|
+
if (r !== -1 && (o === -1 || r <= o))
|
|
377
|
+
a.push(i.slice(0, r).trim()), e.push("iframe"), i = i.slice(r + 12);
|
|
378
|
+
else if (o !== -1)
|
|
379
|
+
a.push(i.slice(0, o).trim()), e.push("shadow"), i = i.slice(o + 5);
|
|
380
|
+
else {
|
|
381
|
+
a.push(i.trim());
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
let n = document;
|
|
386
|
+
for (let r = 0; r < a.length; r++) {
|
|
387
|
+
const o = n.querySelector(a[r]);
|
|
388
|
+
if (!o) return null;
|
|
389
|
+
if (r < a.length - 1)
|
|
390
|
+
if (e[r] === "iframe") {
|
|
391
|
+
const s = o.contentDocument;
|
|
392
|
+
if (!s) return null;
|
|
393
|
+
n = s;
|
|
394
|
+
} else {
|
|
395
|
+
const s = o.shadowRoot;
|
|
396
|
+
if (!s) return null;
|
|
397
|
+
n = s;
|
|
398
|
+
}
|
|
399
|
+
else
|
|
400
|
+
return o;
|
|
401
|
+
}
|
|
402
|
+
return null;
|
|
370
403
|
}
|
|
371
404
|
function l(t) {
|
|
372
405
|
const a = t.outerHTML;
|
|
373
406
|
return a.length > 200 ? a.slice(0, 200) + "..." : a;
|
|
374
407
|
}
|
|
375
|
-
const
|
|
408
|
+
const me = /* @__PURE__ */ new Set([
|
|
376
409
|
"aria-activedescendant",
|
|
377
410
|
"aria-atomic",
|
|
378
411
|
"aria-autocomplete",
|
|
@@ -426,7 +459,7 @@ const re = /* @__PURE__ */ new Set([
|
|
|
426
459
|
"aria-valuemin",
|
|
427
460
|
"aria-valuenow",
|
|
428
461
|
"aria-valuetext"
|
|
429
|
-
]),
|
|
462
|
+
]), pe = /* @__PURE__ */ new Set([
|
|
430
463
|
"aria-atomic",
|
|
431
464
|
"aria-busy",
|
|
432
465
|
"aria-disabled",
|
|
@@ -437,7 +470,7 @@ const re = /* @__PURE__ */ new Set([
|
|
|
437
470
|
"aria-multiselectable",
|
|
438
471
|
"aria-readonly",
|
|
439
472
|
"aria-required"
|
|
440
|
-
]),
|
|
473
|
+
]), he = /* @__PURE__ */ new Set(["aria-checked", "aria-pressed"]), ge = /* @__PURE__ */ new Set([
|
|
441
474
|
"aria-colcount",
|
|
442
475
|
"aria-colindex",
|
|
443
476
|
"aria-colspan",
|
|
@@ -447,11 +480,11 @@ const re = /* @__PURE__ */ new Set([
|
|
|
447
480
|
"aria-rowindex",
|
|
448
481
|
"aria-rowspan",
|
|
449
482
|
"aria-setsize"
|
|
450
|
-
]),
|
|
483
|
+
]), be = /* @__PURE__ */ new Set([
|
|
451
484
|
"aria-valuemax",
|
|
452
485
|
"aria-valuemin",
|
|
453
486
|
"aria-valuenow"
|
|
454
|
-
]),
|
|
487
|
+
]), F = {
|
|
455
488
|
"aria-autocomplete": /* @__PURE__ */ new Set(["inline", "list", "both", "none"]),
|
|
456
489
|
"aria-current": /* @__PURE__ */ new Set(["page", "step", "location", "date", "time", "true", "false"]),
|
|
457
490
|
"aria-dropeffect": /* @__PURE__ */ new Set(["copy", "execute", "link", "move", "none", "popup"]),
|
|
@@ -461,7 +494,7 @@ const re = /* @__PURE__ */ new Set([
|
|
|
461
494
|
"aria-orientation": /* @__PURE__ */ new Set(["horizontal", "vertical", "undefined"]),
|
|
462
495
|
"aria-relevant": /* @__PURE__ */ new Set(["additions", "all", "removals", "text"]),
|
|
463
496
|
"aria-sort": /* @__PURE__ */ new Set(["ascending", "descending", "none", "other"])
|
|
464
|
-
},
|
|
497
|
+
}, _ = /* @__PURE__ */ new Set([
|
|
465
498
|
"caption",
|
|
466
499
|
"code",
|
|
467
500
|
"deletion",
|
|
@@ -478,7 +511,7 @@ const re = /* @__PURE__ */ new Set([
|
|
|
478
511
|
"suggestion",
|
|
479
512
|
"term",
|
|
480
513
|
"time"
|
|
481
|
-
]),
|
|
514
|
+
]), fe = {
|
|
482
515
|
abbr: !0,
|
|
483
516
|
bdi: !0,
|
|
484
517
|
bdo: !0,
|
|
@@ -506,7 +539,7 @@ const re = /* @__PURE__ */ new Set([
|
|
|
506
539
|
u: !0,
|
|
507
540
|
var: !0,
|
|
508
541
|
wbr: !0
|
|
509
|
-
},
|
|
542
|
+
}, ve = {
|
|
510
543
|
alert: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"]),
|
|
511
544
|
article: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"]),
|
|
512
545
|
banner: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"]),
|
|
@@ -539,77 +572,77 @@ const re = /* @__PURE__ */ new Set([
|
|
|
539
572
|
time: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"]),
|
|
540
573
|
tooltip: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"])
|
|
541
574
|
};
|
|
542
|
-
let
|
|
543
|
-
function
|
|
544
|
-
|
|
575
|
+
let I = null, q = null;
|
|
576
|
+
function J() {
|
|
577
|
+
I = null, q = null;
|
|
545
578
|
}
|
|
546
|
-
function
|
|
547
|
-
var
|
|
548
|
-
if (
|
|
579
|
+
function O(t) {
|
|
580
|
+
var n;
|
|
581
|
+
if (q && (I == null ? void 0 : I.deref()) === t) return q;
|
|
549
582
|
const a = [], e = [], i = [];
|
|
550
|
-
for (const
|
|
583
|
+
for (const r of t.querySelectorAll("*")) {
|
|
551
584
|
let o = !1;
|
|
552
|
-
for (const d of
|
|
585
|
+
for (const d of r.attributes)
|
|
553
586
|
if (d.name.startsWith("aria-")) {
|
|
554
587
|
o = !0;
|
|
555
588
|
break;
|
|
556
589
|
}
|
|
557
590
|
if (!o) continue;
|
|
558
|
-
const s = c(
|
|
559
|
-
for (const d of
|
|
560
|
-
if (d.name.startsWith("aria-") && !
|
|
591
|
+
const s = c(r), u = l(r), h = m(r);
|
|
592
|
+
for (const d of r.attributes)
|
|
593
|
+
if (d.name.startsWith("aria-") && !me.has(d.name)) {
|
|
561
594
|
a.push({
|
|
562
595
|
ruleId: "aria-valid-attr",
|
|
563
596
|
selector: s,
|
|
564
|
-
html:
|
|
597
|
+
html: u,
|
|
565
598
|
impact: "critical",
|
|
566
599
|
message: `Invalid ARIA attribute "${d.name}".`
|
|
567
600
|
});
|
|
568
601
|
break;
|
|
569
602
|
}
|
|
570
|
-
for (const d of
|
|
603
|
+
for (const d of r.attributes) {
|
|
571
604
|
if (!d.name.startsWith("aria-")) continue;
|
|
572
605
|
const p = d.value.trim();
|
|
573
|
-
if (
|
|
606
|
+
if (pe.has(d.name))
|
|
574
607
|
p !== "true" && p !== "false" && e.push({
|
|
575
608
|
ruleId: "aria-valid-attr-value",
|
|
576
609
|
selector: s,
|
|
577
|
-
html:
|
|
610
|
+
html: u,
|
|
578
611
|
impact: "critical",
|
|
579
612
|
message: `${d.name} must be "true" or "false", got "${p}".`
|
|
580
613
|
});
|
|
581
|
-
else if (
|
|
614
|
+
else if (he.has(d.name))
|
|
582
615
|
p !== "true" && p !== "false" && p !== "mixed" && e.push({
|
|
583
616
|
ruleId: "aria-valid-attr-value",
|
|
584
617
|
selector: s,
|
|
585
|
-
html:
|
|
618
|
+
html: u,
|
|
586
619
|
impact: "critical",
|
|
587
620
|
message: `${d.name} must be "true", "false", or "mixed", got "${p}".`
|
|
588
621
|
});
|
|
589
|
-
else if (
|
|
622
|
+
else if (ge.has(d.name))
|
|
590
623
|
(p === "" || !/^-?\d+$/.test(p)) && e.push({
|
|
591
624
|
ruleId: "aria-valid-attr-value",
|
|
592
625
|
selector: s,
|
|
593
|
-
html:
|
|
626
|
+
html: u,
|
|
594
627
|
impact: "critical",
|
|
595
628
|
message: `${d.name} must be an integer, got "${p}".`
|
|
596
629
|
});
|
|
597
|
-
else if (
|
|
630
|
+
else if (be.has(d.name))
|
|
598
631
|
(p === "" || isNaN(Number(p))) && e.push({
|
|
599
632
|
ruleId: "aria-valid-attr-value",
|
|
600
633
|
selector: s,
|
|
601
|
-
html:
|
|
634
|
+
html: u,
|
|
602
635
|
impact: "critical",
|
|
603
636
|
message: `${d.name} must be a number, got "${p}".`
|
|
604
637
|
});
|
|
605
|
-
else if (
|
|
606
|
-
const
|
|
607
|
-
for (const f of
|
|
608
|
-
if (!
|
|
638
|
+
else if (F[d.name]) {
|
|
639
|
+
const g = p.split(/\s+/);
|
|
640
|
+
for (const f of g)
|
|
641
|
+
if (!F[d.name].has(f)) {
|
|
609
642
|
e.push({
|
|
610
643
|
ruleId: "aria-valid-attr-value",
|
|
611
644
|
selector: s,
|
|
612
|
-
html:
|
|
645
|
+
html: u,
|
|
613
646
|
impact: "critical",
|
|
614
647
|
message: `Invalid value "${p}" for ${d.name}.`
|
|
615
648
|
});
|
|
@@ -618,37 +651,37 @@ function $(t) {
|
|
|
618
651
|
}
|
|
619
652
|
}
|
|
620
653
|
if (!h) {
|
|
621
|
-
const d = (
|
|
622
|
-
if (!d &&
|
|
623
|
-
const
|
|
624
|
-
(
|
|
654
|
+
const d = (n = r.getAttribute("role")) == null ? void 0 : n.trim().toLowerCase(), p = r.tagName.toLowerCase();
|
|
655
|
+
if (!d && fe[p]) {
|
|
656
|
+
const g = r.hasAttribute("aria-label"), f = r.hasAttribute("aria-labelledby");
|
|
657
|
+
(g || f) && i.push({
|
|
625
658
|
ruleId: "aria-prohibited-attr",
|
|
626
659
|
selector: s,
|
|
627
|
-
html:
|
|
660
|
+
html: u,
|
|
628
661
|
impact: "serious",
|
|
629
662
|
message: `aria-label and aria-labelledby are prohibited on <${p}> elements.`
|
|
630
663
|
});
|
|
631
664
|
} else if (d) {
|
|
632
|
-
if (
|
|
633
|
-
const f =
|
|
665
|
+
if (_.has(d)) {
|
|
666
|
+
const f = r.hasAttribute("aria-label"), v = r.hasAttribute("aria-labelledby");
|
|
634
667
|
(f || v) && i.push({
|
|
635
668
|
ruleId: "aria-prohibited-attr",
|
|
636
669
|
selector: s,
|
|
637
|
-
html:
|
|
670
|
+
html: u,
|
|
638
671
|
impact: "serious",
|
|
639
672
|
message: `aria-label and aria-labelledby are prohibited on role "${d}".`
|
|
640
673
|
});
|
|
641
674
|
}
|
|
642
|
-
const
|
|
643
|
-
if (
|
|
644
|
-
for (const f of
|
|
645
|
-
if (f.name.startsWith("aria-") &&
|
|
646
|
-
if ((f.name === "aria-label" || f.name === "aria-labelledby") &&
|
|
675
|
+
const g = ve[d];
|
|
676
|
+
if (g) {
|
|
677
|
+
for (const f of r.attributes)
|
|
678
|
+
if (f.name.startsWith("aria-") && g.has(f.name)) {
|
|
679
|
+
if ((f.name === "aria-label" || f.name === "aria-labelledby") && _.has(d))
|
|
647
680
|
continue;
|
|
648
681
|
i.push({
|
|
649
682
|
ruleId: "aria-prohibited-attr",
|
|
650
683
|
selector: s,
|
|
651
|
-
html:
|
|
684
|
+
html: u,
|
|
652
685
|
impact: "serious",
|
|
653
686
|
message: `Attribute "${f.name}" is prohibited on role "${d}".`
|
|
654
687
|
});
|
|
@@ -657,10 +690,62 @@ function $(t) {
|
|
|
657
690
|
}
|
|
658
691
|
}
|
|
659
692
|
}
|
|
660
|
-
return
|
|
693
|
+
return I = new WeakRef(t), q = { validAttr: a, validAttrValue: e, prohibitedAttr: i }, q;
|
|
661
694
|
}
|
|
662
|
-
|
|
663
|
-
|
|
695
|
+
let H = /* @__PURE__ */ new WeakMap(), D = /* @__PURE__ */ new WeakMap();
|
|
696
|
+
function Z() {
|
|
697
|
+
H = /* @__PURE__ */ new WeakMap(), D = /* @__PURE__ */ new WeakMap();
|
|
698
|
+
}
|
|
699
|
+
function E(t) {
|
|
700
|
+
let a = H.get(t);
|
|
701
|
+
return a || (a = getComputedStyle(t), H.set(t, a), a);
|
|
702
|
+
}
|
|
703
|
+
function P(t, a, e) {
|
|
704
|
+
const [i, n, r] = [t, a, e].map((o) => {
|
|
705
|
+
const s = o / 255;
|
|
706
|
+
return s <= 0.04045 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
|
|
707
|
+
});
|
|
708
|
+
return 0.2126 * i + 0.7152 * n + 0.0722 * r;
|
|
709
|
+
}
|
|
710
|
+
function ye(t, a) {
|
|
711
|
+
const e = Math.max(t, a), i = Math.min(t, a);
|
|
712
|
+
return (e + 0.05) / (i + 0.05);
|
|
713
|
+
}
|
|
714
|
+
function ee(t) {
|
|
715
|
+
const a = t.match(
|
|
716
|
+
/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*[\d.]+)?\s*\)/
|
|
717
|
+
);
|
|
718
|
+
return a ? [parseInt(a[1]), parseInt(a[2]), parseInt(a[3])] : null;
|
|
719
|
+
}
|
|
720
|
+
function we(t) {
|
|
721
|
+
const a = D.get(t);
|
|
722
|
+
if (a !== void 0) return a;
|
|
723
|
+
const e = Ae(t);
|
|
724
|
+
return D.set(t, e), e;
|
|
725
|
+
}
|
|
726
|
+
function Ae(t) {
|
|
727
|
+
let a = t;
|
|
728
|
+
for (; a; ) {
|
|
729
|
+
const e = E(a), i = e.backgroundColor;
|
|
730
|
+
if (i === "transparent" || i === "rgba(0, 0, 0, 0)") {
|
|
731
|
+
a = a.parentElement;
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
const n = i.match(/rgba\(.+?,\s*([\d.]+)\s*\)/);
|
|
735
|
+
if (n && parseFloat(n[1]) < 0.1) {
|
|
736
|
+
a = a.parentElement;
|
|
737
|
+
continue;
|
|
738
|
+
}
|
|
739
|
+
return e.backgroundImage && e.backgroundImage !== "none" ? null : ee(i);
|
|
740
|
+
}
|
|
741
|
+
return [255, 255, 255];
|
|
742
|
+
}
|
|
743
|
+
function Se(t) {
|
|
744
|
+
const a = E(t), e = parseFloat(a.fontSize), i = parseInt(a.fontWeight) || (a.fontWeight === "bold" ? 700 : 400);
|
|
745
|
+
return e >= 24 || e >= 18.66 && i >= 700;
|
|
746
|
+
}
|
|
747
|
+
function xe(t) {
|
|
748
|
+
var r, o;
|
|
664
749
|
const a = [], e = t.closest("a");
|
|
665
750
|
if (e) {
|
|
666
751
|
const s = e.getAttribute("href");
|
|
@@ -669,17 +754,17 @@ function ue(t) {
|
|
|
669
754
|
const i = t.closest("figure");
|
|
670
755
|
if (i) {
|
|
671
756
|
const s = i.querySelector("figcaption");
|
|
672
|
-
(
|
|
757
|
+
(r = s == null ? void 0 : s.textContent) != null && r.trim() && a.push(`Figcaption: ${s.textContent.trim().slice(0, 100)}`);
|
|
673
758
|
}
|
|
674
|
-
const
|
|
675
|
-
if (
|
|
676
|
-
const s = (o =
|
|
759
|
+
const n = t.parentElement;
|
|
760
|
+
if (n && n !== e) {
|
|
761
|
+
const s = (o = n.textContent) == null ? void 0 : o.replace(t.alt || "", "").trim().slice(0, 100);
|
|
677
762
|
s && a.push(`Adjacent text: ${s}`);
|
|
678
763
|
}
|
|
679
764
|
return a.length > 0 ? a.join(`
|
|
680
765
|
`) : void 0;
|
|
681
766
|
}
|
|
682
|
-
const
|
|
767
|
+
const ke = {
|
|
683
768
|
id: "img-alt",
|
|
684
769
|
wcag: ["1.1.1"],
|
|
685
770
|
level: "A",
|
|
@@ -689,17 +774,17 @@ const me = {
|
|
|
689
774
|
run(t) {
|
|
690
775
|
const a = [];
|
|
691
776
|
for (const e of t.querySelectorAll("img"))
|
|
692
|
-
|
|
777
|
+
m(e) || e.getAttribute("role") === "presentation" || e.getAttribute("role") === "none" || !e.hasAttribute("alt") && !b(e) && a.push({
|
|
693
778
|
ruleId: "img-alt",
|
|
694
779
|
selector: c(e),
|
|
695
780
|
html: l(e),
|
|
696
781
|
impact: "critical",
|
|
697
782
|
message: "Image element missing alt attribute.",
|
|
698
|
-
context:
|
|
783
|
+
context: xe(e)
|
|
699
784
|
});
|
|
700
785
|
return a;
|
|
701
786
|
}
|
|
702
|
-
},
|
|
787
|
+
}, Ie = {
|
|
703
788
|
id: "svg-img-alt",
|
|
704
789
|
wcag: ["1.1.1"],
|
|
705
790
|
level: "A",
|
|
@@ -709,8 +794,8 @@ const me = {
|
|
|
709
794
|
run(t) {
|
|
710
795
|
const a = [];
|
|
711
796
|
for (const e of t.querySelectorAll('svg[role="img"]')) {
|
|
712
|
-
if (
|
|
713
|
-
|
|
797
|
+
if (m(e)) continue;
|
|
798
|
+
b(e) || a.push({
|
|
714
799
|
ruleId: "svg-img-alt",
|
|
715
800
|
selector: c(e),
|
|
716
801
|
html: l(e),
|
|
@@ -720,7 +805,7 @@ const me = {
|
|
|
720
805
|
}
|
|
721
806
|
return a;
|
|
722
807
|
}
|
|
723
|
-
},
|
|
808
|
+
}, qe = {
|
|
724
809
|
id: "input-image-alt",
|
|
725
810
|
wcag: ["1.1.1", "4.1.2"],
|
|
726
811
|
level: "A",
|
|
@@ -730,7 +815,7 @@ const me = {
|
|
|
730
815
|
run(t) {
|
|
731
816
|
const a = [];
|
|
732
817
|
for (const e of t.querySelectorAll('input[type="image"]'))
|
|
733
|
-
|
|
818
|
+
m(e) || b(e) || a.push({
|
|
734
819
|
ruleId: "input-image-alt",
|
|
735
820
|
selector: c(e),
|
|
736
821
|
html: l(e),
|
|
@@ -739,7 +824,7 @@ const me = {
|
|
|
739
824
|
});
|
|
740
825
|
return a;
|
|
741
826
|
}
|
|
742
|
-
},
|
|
827
|
+
}, Ce = {
|
|
743
828
|
id: "image-redundant-alt",
|
|
744
829
|
wcag: [],
|
|
745
830
|
level: "A",
|
|
@@ -751,23 +836,23 @@ const me = {
|
|
|
751
836
|
var e;
|
|
752
837
|
const a = [];
|
|
753
838
|
for (const i of t.querySelectorAll("img[alt]")) {
|
|
754
|
-
const
|
|
755
|
-
if (!
|
|
756
|
-
const
|
|
757
|
-
if (
|
|
758
|
-
const o = ((e =
|
|
759
|
-
o && o ===
|
|
839
|
+
const n = i.getAttribute("alt").trim().toLowerCase();
|
|
840
|
+
if (!n) continue;
|
|
841
|
+
const r = i.closest("a, button");
|
|
842
|
+
if (r) {
|
|
843
|
+
const o = ((e = r.textContent) == null ? void 0 : e.trim().toLowerCase()) || "";
|
|
844
|
+
o && o === n && a.push({
|
|
760
845
|
ruleId: "image-redundant-alt",
|
|
761
846
|
selector: c(i),
|
|
762
847
|
html: l(i),
|
|
763
848
|
impact: "minor",
|
|
764
|
-
message: `Alt text "${i.getAttribute("alt")}" duplicates surrounding ${
|
|
849
|
+
message: `Alt text "${i.getAttribute("alt")}" duplicates surrounding ${r.tagName.toLowerCase()} text.`
|
|
765
850
|
});
|
|
766
851
|
}
|
|
767
852
|
}
|
|
768
853
|
return a;
|
|
769
854
|
}
|
|
770
|
-
},
|
|
855
|
+
}, Te = ["image", "picture", "photo", "graphic", "icon", "img"], Ee = {
|
|
771
856
|
id: "image-alt-redundant-words",
|
|
772
857
|
wcag: [],
|
|
773
858
|
level: "A",
|
|
@@ -779,7 +864,7 @@ const me = {
|
|
|
779
864
|
const a = [];
|
|
780
865
|
for (const e of t.querySelectorAll("img[alt]")) {
|
|
781
866
|
const i = e.getAttribute("alt").toLowerCase();
|
|
782
|
-
i &&
|
|
867
|
+
i && Te.some((n) => i.split(/\s+/).includes(n)) && a.push({
|
|
783
868
|
ruleId: "image-alt-redundant-words",
|
|
784
869
|
selector: c(e),
|
|
785
870
|
html: l(e),
|
|
@@ -789,7 +874,7 @@ const me = {
|
|
|
789
874
|
}
|
|
790
875
|
return a;
|
|
791
876
|
}
|
|
792
|
-
},
|
|
877
|
+
}, Le = {
|
|
793
878
|
id: "area-alt",
|
|
794
879
|
wcag: ["1.1.1", "4.1.2"],
|
|
795
880
|
level: "A",
|
|
@@ -799,8 +884,8 @@ const me = {
|
|
|
799
884
|
run(t) {
|
|
800
885
|
const a = [];
|
|
801
886
|
for (const e of t.querySelectorAll("area[href]")) {
|
|
802
|
-
if (
|
|
803
|
-
|
|
887
|
+
if (m(e)) continue;
|
|
888
|
+
b(e) || a.push({
|
|
804
889
|
ruleId: "area-alt",
|
|
805
890
|
selector: c(e),
|
|
806
891
|
html: l(e),
|
|
@@ -810,7 +895,7 @@ const me = {
|
|
|
810
895
|
}
|
|
811
896
|
return a;
|
|
812
897
|
}
|
|
813
|
-
},
|
|
898
|
+
}, Re = {
|
|
814
899
|
id: "object-alt",
|
|
815
900
|
wcag: ["1.1.1"],
|
|
816
901
|
level: "A",
|
|
@@ -820,7 +905,7 @@ const me = {
|
|
|
820
905
|
run(t) {
|
|
821
906
|
const a = [];
|
|
822
907
|
for (const e of t.querySelectorAll("object"))
|
|
823
|
-
|
|
908
|
+
m(e) || e.getAttribute("role") === "presentation" || e.getAttribute("role") === "none" || b(e) || a.push({
|
|
824
909
|
ruleId: "object-alt",
|
|
825
910
|
selector: c(e),
|
|
826
911
|
html: l(e),
|
|
@@ -829,7 +914,7 @@ const me = {
|
|
|
829
914
|
});
|
|
830
915
|
return a;
|
|
831
916
|
}
|
|
832
|
-
},
|
|
917
|
+
}, Ne = {
|
|
833
918
|
id: "role-img-alt",
|
|
834
919
|
wcag: ["1.1.1"],
|
|
835
920
|
level: "A",
|
|
@@ -839,8 +924,8 @@ const me = {
|
|
|
839
924
|
run(t) {
|
|
840
925
|
const a = [];
|
|
841
926
|
for (const e of t.querySelectorAll('[role="img"]')) {
|
|
842
|
-
if (
|
|
843
|
-
|
|
927
|
+
if (m(e) || e.tagName.toLowerCase() === "svg" || e.tagName.toLowerCase() === "img") continue;
|
|
928
|
+
b(e) || a.push({
|
|
844
929
|
ruleId: "role-img-alt",
|
|
845
930
|
selector: c(e),
|
|
846
931
|
html: l(e),
|
|
@@ -850,26 +935,220 @@ const me = {
|
|
|
850
935
|
}
|
|
851
936
|
return a;
|
|
852
937
|
}
|
|
853
|
-
}
|
|
938
|
+
};
|
|
939
|
+
function Ha(t) {
|
|
940
|
+
if (typeof t != "object" || t === null)
|
|
941
|
+
return "Rule spec must be an object";
|
|
942
|
+
const a = t;
|
|
943
|
+
if (typeof a.id != "string" || a.id.length === 0)
|
|
944
|
+
return "Rule must have a non-empty string id";
|
|
945
|
+
if (typeof a.selector != "string" || a.selector.length === 0)
|
|
946
|
+
return "Rule must have a non-empty string selector";
|
|
947
|
+
if (typeof a.check != "object" || a.check === null)
|
|
948
|
+
return "Rule must have a check object";
|
|
949
|
+
const e = a.check;
|
|
950
|
+
if (![
|
|
951
|
+
"selector-exists",
|
|
952
|
+
"attribute-value",
|
|
953
|
+
"attribute-missing",
|
|
954
|
+
"attribute-regex",
|
|
955
|
+
"child-required",
|
|
956
|
+
"child-invalid"
|
|
957
|
+
].includes(e.type))
|
|
958
|
+
return `Invalid check type: ${String(e.type)}`;
|
|
959
|
+
if (typeof a.impact != "string" || !["critical", "serious", "moderate", "minor"].includes(a.impact))
|
|
960
|
+
return "Rule must have a valid impact (critical|serious|moderate|minor)";
|
|
961
|
+
if (typeof a.message != "string" || a.message.length === 0)
|
|
962
|
+
return "Rule must have a non-empty message";
|
|
963
|
+
if (typeof a.description != "string")
|
|
964
|
+
return "Rule must have a description string";
|
|
965
|
+
if (!Array.isArray(a.wcag))
|
|
966
|
+
return "Rule must have a wcag array";
|
|
967
|
+
if (typeof a.level != "string" || !["A", "AA"].includes(a.level))
|
|
968
|
+
return "Rule must have level A or AA";
|
|
969
|
+
const n = $e(e);
|
|
970
|
+
return n || null;
|
|
971
|
+
}
|
|
972
|
+
function $e(t) {
|
|
973
|
+
switch (t.type) {
|
|
974
|
+
case "selector-exists":
|
|
975
|
+
return null;
|
|
976
|
+
case "attribute-value":
|
|
977
|
+
return typeof t.attribute != "string" ? "attribute-value check requires attribute string" : [">", "<", "=", "!=", "in", "not-in"].includes(t.operator) ? t.value === void 0 ? "attribute-value check requires value" : null : "attribute-value check requires valid operator";
|
|
978
|
+
case "attribute-missing":
|
|
979
|
+
return typeof t.attribute != "string" ? "attribute-missing check requires attribute string" : null;
|
|
980
|
+
case "attribute-regex":
|
|
981
|
+
return typeof t.attribute != "string" ? "attribute-regex check requires attribute string" : typeof t.pattern != "string" ? "attribute-regex check requires pattern string" : typeof t.shouldMatch != "boolean" ? "attribute-regex check requires shouldMatch boolean" : null;
|
|
982
|
+
case "child-required":
|
|
983
|
+
return typeof t.childSelector != "string" ? "child-required check requires childSelector string" : null;
|
|
984
|
+
case "child-invalid":
|
|
985
|
+
return Array.isArray(t.allowedChildren) ? null : "child-invalid check requires allowedChildren array";
|
|
986
|
+
default:
|
|
987
|
+
return `Unknown check type: ${String(t.type)}`;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
function S(t, a, e) {
|
|
991
|
+
let i = t;
|
|
992
|
+
if (i.includes("{{tag}}") && (i = i.replace(/\{\{tag\}\}/g, a.tagName.toLowerCase())), i.includes("{{value}}")) {
|
|
993
|
+
let n = "";
|
|
994
|
+
"attribute" in e && e.attribute && (n = a.getAttribute(e.attribute) ?? ""), i = i.replace(/\{\{value\}\}/g, n);
|
|
995
|
+
}
|
|
996
|
+
return i;
|
|
997
|
+
}
|
|
998
|
+
function x(t) {
|
|
999
|
+
const a = t.skipAriaHidden !== !1;
|
|
1000
|
+
return {
|
|
1001
|
+
id: t.id,
|
|
1002
|
+
wcag: t.wcag,
|
|
1003
|
+
level: t.level,
|
|
1004
|
+
tags: t.tags,
|
|
1005
|
+
description: t.description,
|
|
1006
|
+
guidance: t.guidance,
|
|
1007
|
+
prompt: t.prompt,
|
|
1008
|
+
run(e) {
|
|
1009
|
+
const i = [];
|
|
1010
|
+
switch (t.check.type) {
|
|
1011
|
+
case "selector-exists": {
|
|
1012
|
+
for (const n of e.querySelectorAll(t.selector))
|
|
1013
|
+
a && m(n) || i.push({
|
|
1014
|
+
ruleId: t.id,
|
|
1015
|
+
selector: c(n),
|
|
1016
|
+
html: l(n),
|
|
1017
|
+
impact: t.impact,
|
|
1018
|
+
message: S(t.message, n, t.check),
|
|
1019
|
+
element: n
|
|
1020
|
+
});
|
|
1021
|
+
break;
|
|
1022
|
+
}
|
|
1023
|
+
case "attribute-value": {
|
|
1024
|
+
const { attribute: n, operator: r, value: o } = t.check;
|
|
1025
|
+
for (const s of e.querySelectorAll(t.selector)) {
|
|
1026
|
+
if (a && m(s)) continue;
|
|
1027
|
+
const u = s.getAttribute(n);
|
|
1028
|
+
u !== null && Me(u, r, o) && i.push({
|
|
1029
|
+
ruleId: t.id,
|
|
1030
|
+
selector: c(s),
|
|
1031
|
+
html: l(s),
|
|
1032
|
+
impact: t.impact,
|
|
1033
|
+
message: S(t.message, s, t.check),
|
|
1034
|
+
element: s
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
break;
|
|
1038
|
+
}
|
|
1039
|
+
case "attribute-missing": {
|
|
1040
|
+
const { attribute: n } = t.check;
|
|
1041
|
+
for (const r of e.querySelectorAll(t.selector))
|
|
1042
|
+
a && m(r) || r.hasAttribute(n) || i.push({
|
|
1043
|
+
ruleId: t.id,
|
|
1044
|
+
selector: c(r),
|
|
1045
|
+
html: l(r),
|
|
1046
|
+
impact: t.impact,
|
|
1047
|
+
message: S(t.message, r, t.check),
|
|
1048
|
+
element: r
|
|
1049
|
+
});
|
|
1050
|
+
break;
|
|
1051
|
+
}
|
|
1052
|
+
case "attribute-regex": {
|
|
1053
|
+
const { attribute: n, pattern: r, flags: o, shouldMatch: s } = t.check;
|
|
1054
|
+
let u;
|
|
1055
|
+
try {
|
|
1056
|
+
u = new RegExp(r, o);
|
|
1057
|
+
} catch {
|
|
1058
|
+
break;
|
|
1059
|
+
}
|
|
1060
|
+
for (const h of e.querySelectorAll(t.selector)) {
|
|
1061
|
+
if (a && m(h)) continue;
|
|
1062
|
+
const d = h.getAttribute(n);
|
|
1063
|
+
if (d === null) continue;
|
|
1064
|
+
const p = u.test(d);
|
|
1065
|
+
s && !p ? i.push({
|
|
1066
|
+
ruleId: t.id,
|
|
1067
|
+
selector: c(h),
|
|
1068
|
+
html: l(h),
|
|
1069
|
+
impact: t.impact,
|
|
1070
|
+
message: S(t.message, h, t.check),
|
|
1071
|
+
element: h
|
|
1072
|
+
}) : !s && p && i.push({
|
|
1073
|
+
ruleId: t.id,
|
|
1074
|
+
selector: c(h),
|
|
1075
|
+
html: l(h),
|
|
1076
|
+
impact: t.impact,
|
|
1077
|
+
message: S(t.message, h, t.check),
|
|
1078
|
+
element: h
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
break;
|
|
1082
|
+
}
|
|
1083
|
+
case "child-required": {
|
|
1084
|
+
const { childSelector: n } = t.check;
|
|
1085
|
+
for (const r of e.querySelectorAll(t.selector))
|
|
1086
|
+
a && m(r) || r.querySelector(n) || i.push({
|
|
1087
|
+
ruleId: t.id,
|
|
1088
|
+
selector: c(r),
|
|
1089
|
+
html: l(r),
|
|
1090
|
+
impact: t.impact,
|
|
1091
|
+
message: S(t.message, r, t.check),
|
|
1092
|
+
element: r
|
|
1093
|
+
});
|
|
1094
|
+
break;
|
|
1095
|
+
}
|
|
1096
|
+
case "child-invalid": {
|
|
1097
|
+
const n = new Set(
|
|
1098
|
+
t.check.allowedChildren.map((r) => r.toLowerCase())
|
|
1099
|
+
);
|
|
1100
|
+
for (const r of e.querySelectorAll(t.selector))
|
|
1101
|
+
if (!(a && m(r))) {
|
|
1102
|
+
for (const o of r.children)
|
|
1103
|
+
if (!n.has(o.tagName.toLowerCase())) {
|
|
1104
|
+
i.push({
|
|
1105
|
+
ruleId: t.id,
|
|
1106
|
+
selector: c(o),
|
|
1107
|
+
html: l(o),
|
|
1108
|
+
impact: t.impact,
|
|
1109
|
+
message: S(t.message, o, t.check),
|
|
1110
|
+
element: o
|
|
1111
|
+
});
|
|
1112
|
+
break;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
break;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
return i;
|
|
1119
|
+
}
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
function Me(t, a, e) {
|
|
1123
|
+
switch (a) {
|
|
1124
|
+
case ">":
|
|
1125
|
+
return parseFloat(t) > e;
|
|
1126
|
+
case "<":
|
|
1127
|
+
return parseFloat(t) < e;
|
|
1128
|
+
case "=":
|
|
1129
|
+
return t === String(e);
|
|
1130
|
+
case "!=":
|
|
1131
|
+
return t !== String(e);
|
|
1132
|
+
case "in":
|
|
1133
|
+
return Array.isArray(e) && e.includes(t);
|
|
1134
|
+
case "not-in":
|
|
1135
|
+
return Array.isArray(e) && !e.includes(t);
|
|
1136
|
+
default:
|
|
1137
|
+
return !1;
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
const He = {
|
|
854
1141
|
id: "server-side-image-map",
|
|
1142
|
+
selector: "img[ismap], input[type='image'][ismap]",
|
|
1143
|
+
check: { type: "selector-exists" },
|
|
1144
|
+
impact: "minor",
|
|
1145
|
+
message: "Server-side image map detected. Use client-side image map with <map> and <area> elements instead.",
|
|
1146
|
+
description: "Server-side image maps must not be used.",
|
|
855
1147
|
wcag: ["2.1.1"],
|
|
856
1148
|
level: "A",
|
|
857
|
-
description: "Server-side image maps must not be used.",
|
|
858
1149
|
guidance: "Server-side image maps (using ismap attribute) send click coordinates to the server, which is inaccessible to keyboard users and screen readers who can't precisely click specific regions. Replace with client-side image maps (<map> with <area> elements) that provide keyboard access and accessible names, or use linked images/buttons instead.",
|
|
859
|
-
prompt: "Explain that the ismap attribute should be removed and the functionality replaced with a client-side <map> element with <area> children, or separate linked images/buttons."
|
|
860
|
-
|
|
861
|
-
const a = [];
|
|
862
|
-
for (const e of t.querySelectorAll("img[ismap], input[type='image'][ismap]"))
|
|
863
|
-
u(e) || a.push({
|
|
864
|
-
ruleId: "server-side-image-map",
|
|
865
|
-
selector: c(e),
|
|
866
|
-
html: l(e),
|
|
867
|
-
impact: "minor",
|
|
868
|
-
message: "Server-side image map detected. Use client-side image map with <map> and <area> elements instead."
|
|
869
|
-
});
|
|
870
|
-
return a;
|
|
871
|
-
}
|
|
872
|
-
}, Se = {
|
|
1150
|
+
prompt: "Explain that the ismap attribute should be removed and the functionality replaced with a client-side <map> element with <area> children, or separate linked images/buttons."
|
|
1151
|
+
}, De = x(He), Be = {
|
|
873
1152
|
id: "label",
|
|
874
1153
|
wcag: ["4.1.2"],
|
|
875
1154
|
level: "A",
|
|
@@ -881,8 +1160,8 @@ const me = {
|
|
|
881
1160
|
'input:not([type="hidden"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="image"]), textarea, select'
|
|
882
1161
|
);
|
|
883
1162
|
for (const i of e) {
|
|
884
|
-
if (
|
|
885
|
-
|
|
1163
|
+
if (m(i)) continue;
|
|
1164
|
+
b(i) || a.push({
|
|
886
1165
|
ruleId: "label",
|
|
887
1166
|
selector: c(i),
|
|
888
1167
|
html: l(i),
|
|
@@ -892,7 +1171,7 @@ const me = {
|
|
|
892
1171
|
}
|
|
893
1172
|
return a;
|
|
894
1173
|
}
|
|
895
|
-
},
|
|
1174
|
+
}, Oe = {
|
|
896
1175
|
id: "form-field-multiple-labels",
|
|
897
1176
|
wcag: [],
|
|
898
1177
|
level: "A",
|
|
@@ -903,17 +1182,17 @@ const me = {
|
|
|
903
1182
|
run(t) {
|
|
904
1183
|
const a = [], e = t.querySelectorAll('input:not([type="hidden"]), textarea, select');
|
|
905
1184
|
for (const i of e) {
|
|
906
|
-
if (
|
|
907
|
-
const
|
|
908
|
-
let
|
|
1185
|
+
if (m(i) || !i.id) continue;
|
|
1186
|
+
const n = t.querySelectorAll(`label[for="${CSS.escape(i.id)}"]`);
|
|
1187
|
+
let r = 0, o = i.parentElement;
|
|
909
1188
|
for (; o; ) {
|
|
910
1189
|
if (o.tagName.toLowerCase() === "label" && !o.hasAttribute("for")) {
|
|
911
|
-
|
|
1190
|
+
r++;
|
|
912
1191
|
break;
|
|
913
1192
|
}
|
|
914
1193
|
o = o.parentElement;
|
|
915
1194
|
}
|
|
916
|
-
const s =
|
|
1195
|
+
const s = n.length + r;
|
|
917
1196
|
s > 1 && a.push({
|
|
918
1197
|
ruleId: "form-field-multiple-labels",
|
|
919
1198
|
selector: c(i),
|
|
@@ -924,7 +1203,7 @@ const me = {
|
|
|
924
1203
|
}
|
|
925
1204
|
return a;
|
|
926
1205
|
}
|
|
927
|
-
},
|
|
1206
|
+
}, We = {
|
|
928
1207
|
id: "select-name",
|
|
929
1208
|
wcag: ["4.1.2"],
|
|
930
1209
|
level: "A",
|
|
@@ -934,7 +1213,7 @@ const me = {
|
|
|
934
1213
|
run(t) {
|
|
935
1214
|
const a = [];
|
|
936
1215
|
for (const e of t.querySelectorAll("select"))
|
|
937
|
-
|
|
1216
|
+
m(e) || b(e) || a.push({
|
|
938
1217
|
ruleId: "select-name",
|
|
939
1218
|
selector: c(e),
|
|
940
1219
|
html: l(e),
|
|
@@ -943,7 +1222,7 @@ const me = {
|
|
|
943
1222
|
});
|
|
944
1223
|
return a;
|
|
945
1224
|
}
|
|
946
|
-
},
|
|
1225
|
+
}, Fe = {
|
|
947
1226
|
id: "input-button-name",
|
|
948
1227
|
wcag: ["4.1.2"],
|
|
949
1228
|
level: "A",
|
|
@@ -953,22 +1232,22 @@ const me = {
|
|
|
953
1232
|
run(t) {
|
|
954
1233
|
var e, i;
|
|
955
1234
|
const a = [];
|
|
956
|
-
for (const
|
|
1235
|
+
for (const n of t.querySelectorAll(
|
|
957
1236
|
'input[type="submit"], input[type="button"], input[type="reset"]'
|
|
958
1237
|
)) {
|
|
959
|
-
if (
|
|
960
|
-
const
|
|
961
|
-
!
|
|
1238
|
+
if (m(n)) continue;
|
|
1239
|
+
const r = (e = n.getAttribute("value")) == null ? void 0 : e.trim(), o = (i = n.getAttribute("type")) == null ? void 0 : i.toLowerCase(), s = (o === "submit" || o === "reset") && !n.hasAttribute("value");
|
|
1240
|
+
!r && !s && !b(n) && a.push({
|
|
962
1241
|
ruleId: "input-button-name",
|
|
963
|
-
selector: c(
|
|
964
|
-
html: l(
|
|
1242
|
+
selector: c(n),
|
|
1243
|
+
html: l(n),
|
|
965
1244
|
impact: "critical",
|
|
966
1245
|
message: "Input button has no discernible text."
|
|
967
1246
|
});
|
|
968
1247
|
}
|
|
969
1248
|
return a;
|
|
970
1249
|
}
|
|
971
|
-
},
|
|
1250
|
+
}, _e = /* @__PURE__ */ new Set([
|
|
972
1251
|
"off",
|
|
973
1252
|
"on",
|
|
974
1253
|
"name",
|
|
@@ -1023,7 +1302,7 @@ const me = {
|
|
|
1023
1302
|
"impp",
|
|
1024
1303
|
"url",
|
|
1025
1304
|
"photo"
|
|
1026
|
-
]),
|
|
1305
|
+
]), Pe = {
|
|
1027
1306
|
id: "autocomplete-valid",
|
|
1028
1307
|
wcag: ["1.3.5"],
|
|
1029
1308
|
level: "AA",
|
|
@@ -1035,8 +1314,8 @@ const me = {
|
|
|
1035
1314
|
for (const e of t.querySelectorAll("[autocomplete]")) {
|
|
1036
1315
|
const i = e.getAttribute("autocomplete").trim();
|
|
1037
1316
|
if (!i) continue;
|
|
1038
|
-
const
|
|
1039
|
-
|
|
1317
|
+
const n = i.split(/\s+/), r = n[n.length - 1];
|
|
1318
|
+
_e.has(r) || a.push({
|
|
1040
1319
|
ruleId: "autocomplete-valid",
|
|
1041
1320
|
selector: c(e),
|
|
1042
1321
|
html: l(e),
|
|
@@ -1047,30 +1326,30 @@ const me = {
|
|
|
1047
1326
|
return a;
|
|
1048
1327
|
}
|
|
1049
1328
|
};
|
|
1050
|
-
function
|
|
1329
|
+
function V(t) {
|
|
1051
1330
|
return t.toLowerCase().replace(/\s+/g, " ").trim();
|
|
1052
1331
|
}
|
|
1053
|
-
function
|
|
1054
|
-
const e =
|
|
1332
|
+
function U(t, a) {
|
|
1333
|
+
const e = V(t), i = V(a);
|
|
1055
1334
|
if (!e || !i || e.includes(i) || i.includes(e)) return !0;
|
|
1056
|
-
const
|
|
1057
|
-
return
|
|
1335
|
+
const n = i.split(/\s+/).map((r) => r.replace(/[.,;:!?\u2026]+$/g, "")).filter((r) => r.length > 2);
|
|
1336
|
+
return n.length >= 2 && n.filter((o) => e.includes(o)).length / n.length > 0.5;
|
|
1058
1337
|
}
|
|
1059
|
-
function
|
|
1338
|
+
function B(t) {
|
|
1060
1339
|
let a = "";
|
|
1061
1340
|
for (const e of t.childNodes)
|
|
1062
1341
|
if (e.nodeType === 3)
|
|
1063
1342
|
a += e.textContent ?? "";
|
|
1064
1343
|
else if (e.nodeType === 1) {
|
|
1065
|
-
const i = e;
|
|
1066
|
-
if (
|
|
1067
|
-
const
|
|
1068
|
-
if (
|
|
1069
|
-
a +=
|
|
1344
|
+
const i = e, n = i.tagName.toLowerCase();
|
|
1345
|
+
if (n === "style" || n === "script" || n === "svg" || i.getAttribute("aria-hidden") === "true" || i instanceof HTMLElement && i.style.display === "none") continue;
|
|
1346
|
+
const r = i.getAttribute("role");
|
|
1347
|
+
if (r === "img" || r === "presentation" || r === "none") continue;
|
|
1348
|
+
a += B(i);
|
|
1070
1349
|
}
|
|
1071
1350
|
return a;
|
|
1072
1351
|
}
|
|
1073
|
-
const
|
|
1352
|
+
const Ve = {
|
|
1074
1353
|
id: "label-content-name-mismatch",
|
|
1075
1354
|
wcag: ["2.5.3"],
|
|
1076
1355
|
level: "A",
|
|
@@ -1080,33 +1359,33 @@ const Te = {
|
|
|
1080
1359
|
run(t) {
|
|
1081
1360
|
const a = [];
|
|
1082
1361
|
for (const e of t.querySelectorAll('button, [role="button"], a[href], input[type="submit"], input[type="button"]')) {
|
|
1083
|
-
if (
|
|
1084
|
-
const i =
|
|
1362
|
+
if (m(e)) continue;
|
|
1363
|
+
const i = b(e);
|
|
1085
1364
|
if (!i) continue;
|
|
1086
|
-
let
|
|
1087
|
-
e instanceof HTMLInputElement ?
|
|
1088
|
-
const
|
|
1089
|
-
if (!
|
|
1365
|
+
let n = "";
|
|
1366
|
+
e instanceof HTMLInputElement ? n = e.value || "" : n = B(e);
|
|
1367
|
+
const r = n.trim();
|
|
1368
|
+
if (!r || r.length <= 2) continue;
|
|
1090
1369
|
const o = e.hasAttribute("aria-label"), s = e.hasAttribute("aria-labelledby");
|
|
1091
|
-
!o && !s ||
|
|
1370
|
+
!o && !s || U(i, n) || a.push({
|
|
1092
1371
|
ruleId: "label-content-name-mismatch",
|
|
1093
1372
|
selector: c(e),
|
|
1094
1373
|
html: l(e),
|
|
1095
1374
|
impact: "serious",
|
|
1096
|
-
message: `Accessible name "${i}" does not contain visible text "${
|
|
1375
|
+
message: `Accessible name "${i}" does not contain visible text "${n.trim()}".`
|
|
1097
1376
|
});
|
|
1098
1377
|
}
|
|
1099
1378
|
for (const e of t.querySelectorAll("input, select, textarea")) {
|
|
1100
|
-
if (
|
|
1101
|
-
const i =
|
|
1379
|
+
if (m(e) || e instanceof HTMLInputElement && ["hidden", "submit", "button", "image"].includes(e.type)) continue;
|
|
1380
|
+
const i = b(e);
|
|
1102
1381
|
if (!i || !e.hasAttribute("aria-label")) continue;
|
|
1103
|
-
const
|
|
1382
|
+
const r = e.id;
|
|
1104
1383
|
let o = "";
|
|
1105
|
-
if (
|
|
1106
|
-
const s = t.querySelector(`label[for="${CSS.escape(
|
|
1107
|
-
s && (o =
|
|
1384
|
+
if (r) {
|
|
1385
|
+
const s = t.querySelector(`label[for="${CSS.escape(r)}"]`);
|
|
1386
|
+
s && (o = B(s));
|
|
1108
1387
|
}
|
|
1109
|
-
o.trim() && (
|
|
1388
|
+
o.trim() && (U(i, o) || a.push({
|
|
1110
1389
|
ruleId: "label-content-name-mismatch",
|
|
1111
1390
|
selector: c(e),
|
|
1112
1391
|
html: l(e),
|
|
@@ -1116,7 +1395,7 @@ const Te = {
|
|
|
1116
1395
|
}
|
|
1117
1396
|
return a;
|
|
1118
1397
|
}
|
|
1119
|
-
},
|
|
1398
|
+
}, Ue = {
|
|
1120
1399
|
id: "label-title-only",
|
|
1121
1400
|
wcag: [],
|
|
1122
1401
|
level: "A",
|
|
@@ -1125,21 +1404,21 @@ const Te = {
|
|
|
1125
1404
|
guidance: "The title attribute is unreliable as a label because it only appears on hover/focus (not visible to touch users) and is often ignored by assistive technologies. Use a visible <label> element, aria-label, or aria-labelledby instead. Title can supplement a label but should not replace it.",
|
|
1126
1405
|
prompt: "The title attribute text should be moved to a visible <label> element or aria-label. Show what text to use based on the current title.",
|
|
1127
1406
|
run(t) {
|
|
1128
|
-
var i,
|
|
1407
|
+
var i, n, r, o;
|
|
1129
1408
|
const a = [], e = t.querySelectorAll(
|
|
1130
1409
|
'input:not([type="hidden"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="image"]), textarea, select'
|
|
1131
1410
|
);
|
|
1132
1411
|
for (const s of e) {
|
|
1133
|
-
if (
|
|
1134
|
-
const
|
|
1412
|
+
if (m(s)) continue;
|
|
1413
|
+
const u = s.hasAttribute("title") && ((i = s.getAttribute("title")) == null ? void 0 : i.trim()), h = s.hasAttribute("aria-label") && ((n = s.getAttribute("aria-label")) == null ? void 0 : n.trim()), d = s.hasAttribute("aria-labelledby");
|
|
1135
1414
|
let p = !1;
|
|
1136
|
-
const
|
|
1137
|
-
if (
|
|
1138
|
-
const v = s.ownerDocument.querySelector(`label[for="${CSS.escape(
|
|
1139
|
-
(
|
|
1415
|
+
const g = s.id;
|
|
1416
|
+
if (g) {
|
|
1417
|
+
const v = s.ownerDocument.querySelector(`label[for="${CSS.escape(g)}"]`);
|
|
1418
|
+
(r = v == null ? void 0 : v.textContent) != null && r.trim() && (p = !0);
|
|
1140
1419
|
}
|
|
1141
1420
|
const f = s.closest("label");
|
|
1142
|
-
(o = f == null ? void 0 : f.textContent) != null && o.trim() && (p = !0),
|
|
1421
|
+
(o = f == null ? void 0 : f.textContent) != null && o.trim() && (p = !0), u && !h && !d && !p && a.push({
|
|
1143
1422
|
ruleId: "label-title-only",
|
|
1144
1423
|
selector: c(s),
|
|
1145
1424
|
html: l(s),
|
|
@@ -1149,29 +1428,19 @@ const Te = {
|
|
|
1149
1428
|
}
|
|
1150
1429
|
return a;
|
|
1151
1430
|
}
|
|
1152
|
-
},
|
|
1431
|
+
}, je = {
|
|
1153
1432
|
id: "tabindex",
|
|
1433
|
+
selector: "[tabindex]",
|
|
1434
|
+
check: { type: "attribute-value", attribute: "tabindex", operator: ">", value: 0 },
|
|
1435
|
+
impact: "serious",
|
|
1436
|
+
message: 'Element has tabindex="{{value}}" which disrupts tab order.',
|
|
1437
|
+
description: "Elements should not have tabindex greater than 0, which disrupts natural tab order.",
|
|
1154
1438
|
wcag: [],
|
|
1155
|
-
tags: ["best-practice"],
|
|
1156
1439
|
level: "A",
|
|
1157
|
-
|
|
1440
|
+
tags: ["best-practice"],
|
|
1158
1441
|
guidance: "Positive tabindex values force elements to the front of the tab order regardless of DOM position, creating unpredictable navigation for keyboard users. Use tabindex='0' to add elements to the natural tab order, or tabindex='-1' to make elements programmatically focusable but not in tab order. Rely on DOM order for tab sequence.",
|
|
1159
|
-
prompt: "Change the positive tabindex value to tabindex='0' and rely on DOM order for tab sequence instead."
|
|
1160
|
-
|
|
1161
|
-
const a = [];
|
|
1162
|
-
for (const e of t.querySelectorAll("[tabindex]")) {
|
|
1163
|
-
const i = parseInt(e.getAttribute("tabindex"), 10);
|
|
1164
|
-
i > 0 && a.push({
|
|
1165
|
-
ruleId: "tabindex",
|
|
1166
|
-
selector: c(e),
|
|
1167
|
-
html: l(e),
|
|
1168
|
-
impact: "serious",
|
|
1169
|
-
message: `Element has tabindex="${i}" which disrupts tab order.`
|
|
1170
|
-
});
|
|
1171
|
-
}
|
|
1172
|
-
return a;
|
|
1173
|
-
}
|
|
1174
|
-
}, Re = /* @__PURE__ */ new Set([
|
|
1442
|
+
prompt: "Change the positive tabindex value to tabindex='0' and rely on DOM order for tab sequence instead."
|
|
1443
|
+
}, ze = x(je), Ge = /* @__PURE__ */ new Set([
|
|
1175
1444
|
"div",
|
|
1176
1445
|
"span",
|
|
1177
1446
|
"p",
|
|
@@ -1198,7 +1467,7 @@ const Te = {
|
|
|
1198
1467
|
"tr",
|
|
1199
1468
|
"td",
|
|
1200
1469
|
"th"
|
|
1201
|
-
]),
|
|
1470
|
+
]), Xe = {
|
|
1202
1471
|
id: "focus-order-semantics",
|
|
1203
1472
|
wcag: [],
|
|
1204
1473
|
tags: ["best-practice"],
|
|
@@ -1210,7 +1479,7 @@ const Te = {
|
|
|
1210
1479
|
const a = [];
|
|
1211
1480
|
for (const e of t.querySelectorAll('[tabindex="0"]')) {
|
|
1212
1481
|
const i = e.tagName.toLowerCase();
|
|
1213
|
-
if (!
|
|
1482
|
+
if (!Ge.has(i)) continue;
|
|
1214
1483
|
e.getAttribute("role") || a.push({
|
|
1215
1484
|
ruleId: "focus-order-semantics",
|
|
1216
1485
|
selector: c(e),
|
|
@@ -1221,7 +1490,7 @@ const Te = {
|
|
|
1221
1490
|
}
|
|
1222
1491
|
return a;
|
|
1223
1492
|
}
|
|
1224
|
-
},
|
|
1493
|
+
}, Ke = /* @__PURE__ */ new Set([
|
|
1225
1494
|
"a",
|
|
1226
1495
|
"audio",
|
|
1227
1496
|
"button",
|
|
@@ -1230,7 +1499,7 @@ const Te = {
|
|
|
1230
1499
|
"select",
|
|
1231
1500
|
"textarea",
|
|
1232
1501
|
"video"
|
|
1233
|
-
]),
|
|
1502
|
+
]), Ye = /* @__PURE__ */ new Set([
|
|
1234
1503
|
"button",
|
|
1235
1504
|
"checkbox",
|
|
1236
1505
|
"combobox",
|
|
@@ -1254,7 +1523,7 @@ const Te = {
|
|
|
1254
1523
|
"tabpanel",
|
|
1255
1524
|
"textbox",
|
|
1256
1525
|
"treeitem"
|
|
1257
|
-
]),
|
|
1526
|
+
]), Qe = {
|
|
1258
1527
|
grid: /* @__PURE__ */ new Set(["gridcell", "row", "columnheader", "rowheader"]),
|
|
1259
1528
|
listbox: /* @__PURE__ */ new Set(["option"]),
|
|
1260
1529
|
menu: /* @__PURE__ */ new Set(["menuitem", "menuitemcheckbox", "menuitemradio"]),
|
|
@@ -1264,26 +1533,26 @@ const Te = {
|
|
|
1264
1533
|
tree: /* @__PURE__ */ new Set(["treeitem"]),
|
|
1265
1534
|
treegrid: /* @__PURE__ */ new Set(["gridcell", "row", "columnheader", "rowheader", "treeitem"])
|
|
1266
1535
|
};
|
|
1267
|
-
function
|
|
1268
|
-
var
|
|
1269
|
-
const e = (
|
|
1270
|
-
return !e || !i ? !1 : ((o =
|
|
1536
|
+
function Je(t, a) {
|
|
1537
|
+
var n, r, o;
|
|
1538
|
+
const e = (n = t.getAttribute("role")) == null ? void 0 : n.toLowerCase(), i = (r = a.getAttribute("role")) == null ? void 0 : r.toLowerCase();
|
|
1539
|
+
return !e || !i ? !1 : ((o = Qe[e]) == null ? void 0 : o.has(i)) ?? !1;
|
|
1271
1540
|
}
|
|
1272
|
-
function
|
|
1273
|
-
var
|
|
1541
|
+
function Ze(t) {
|
|
1542
|
+
var n;
|
|
1274
1543
|
const a = t.tagName.toLowerCase();
|
|
1275
|
-
if (
|
|
1544
|
+
if (Ke.has(a))
|
|
1276
1545
|
return a === "a" && !t.hasAttribute("href") ? !1 : a === "audio" || a === "video" ? t.hasAttribute("controls") : !(a === "img" && !t.hasAttribute("usemap") || a === "input" && t.type === "hidden" || t.disabled);
|
|
1277
|
-
const e = (
|
|
1278
|
-
if (e &&
|
|
1546
|
+
const e = (n = t.getAttribute("role")) == null ? void 0 : n.toLowerCase();
|
|
1547
|
+
if (e && Ye.has(e)) return !0;
|
|
1279
1548
|
const i = t.getAttribute("tabindex");
|
|
1280
1549
|
return i !== null && i !== "-1" || t.getAttribute("contenteditable") === "true";
|
|
1281
1550
|
}
|
|
1282
|
-
function
|
|
1551
|
+
function et(t) {
|
|
1283
1552
|
const a = t.tagName.toLowerCase();
|
|
1284
1553
|
return !!(a === "a" && t.hasAttribute("href") || a === "button" && !t.disabled);
|
|
1285
1554
|
}
|
|
1286
|
-
const
|
|
1555
|
+
const tt = {
|
|
1287
1556
|
id: "nested-interactive",
|
|
1288
1557
|
wcag: ["4.1.2"],
|
|
1289
1558
|
level: "A",
|
|
@@ -1293,15 +1562,15 @@ const We = {
|
|
|
1293
1562
|
run(t) {
|
|
1294
1563
|
const a = [], e = t.body ?? t;
|
|
1295
1564
|
if (!e) return a;
|
|
1296
|
-
const
|
|
1297
|
-
let o =
|
|
1565
|
+
const n = (t.body ? t : t.ownerDocument).createTreeWalker(e, NodeFilter.SHOW_ELEMENT), r = [];
|
|
1566
|
+
let o = n.currentNode;
|
|
1298
1567
|
for (; o; ) {
|
|
1299
|
-
for (;
|
|
1300
|
-
|
|
1301
|
-
if (!
|
|
1302
|
-
if (
|
|
1303
|
-
const s =
|
|
1304
|
-
|
|
1568
|
+
for (; r.length > 0 && !r[r.length - 1].contains(o); )
|
|
1569
|
+
r.pop();
|
|
1570
|
+
if (!m(o) && Ze(o)) {
|
|
1571
|
+
if (r.length > 0) {
|
|
1572
|
+
const s = r[r.length - 1];
|
|
1573
|
+
Je(s, o) || a.push({
|
|
1305
1574
|
ruleId: "nested-interactive",
|
|
1306
1575
|
selector: c(o),
|
|
1307
1576
|
html: l(o),
|
|
@@ -1309,13 +1578,13 @@ const We = {
|
|
|
1309
1578
|
message: `Interactive element <${o.tagName.toLowerCase()}> is nested inside <${s.tagName.toLowerCase()}>.`
|
|
1310
1579
|
});
|
|
1311
1580
|
}
|
|
1312
|
-
|
|
1581
|
+
et(o) && r.push(o);
|
|
1313
1582
|
}
|
|
1314
|
-
o =
|
|
1583
|
+
o = n.nextNode();
|
|
1315
1584
|
}
|
|
1316
1585
|
return a;
|
|
1317
1586
|
}
|
|
1318
|
-
},
|
|
1587
|
+
}, at = {
|
|
1319
1588
|
id: "scrollable-region-focusable",
|
|
1320
1589
|
wcag: ["2.1.1"],
|
|
1321
1590
|
level: "A",
|
|
@@ -1325,11 +1594,11 @@ const We = {
|
|
|
1325
1594
|
run(t) {
|
|
1326
1595
|
const a = [];
|
|
1327
1596
|
for (const e of t.querySelectorAll("*")) {
|
|
1328
|
-
if (
|
|
1329
|
-
const i = t.defaultView ?? t.ownerDocument.defaultView,
|
|
1330
|
-
if (!
|
|
1331
|
-
const
|
|
1332
|
-
if (!(
|
|
1597
|
+
if (m(e) || !(e instanceof HTMLElement)) continue;
|
|
1598
|
+
const i = t.defaultView ?? t.ownerDocument.defaultView, n = i == null ? void 0 : i.getComputedStyle(e);
|
|
1599
|
+
if (!n) continue;
|
|
1600
|
+
const r = n.overflowX, o = n.overflowY;
|
|
1601
|
+
if (!(r === "scroll" || r === "auto" || o === "scroll" || o === "auto") || !(e.scrollHeight > e.clientHeight || e.scrollWidth > e.clientWidth)) continue;
|
|
1333
1602
|
const h = e.getAttribute("tabindex");
|
|
1334
1603
|
h !== null && h !== "-1" || e.querySelector(
|
|
1335
1604
|
'a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
@@ -1343,7 +1612,7 @@ const We = {
|
|
|
1343
1612
|
}
|
|
1344
1613
|
return a;
|
|
1345
1614
|
}
|
|
1346
|
-
},
|
|
1615
|
+
}, it = {
|
|
1347
1616
|
id: "accesskeys",
|
|
1348
1617
|
wcag: [],
|
|
1349
1618
|
level: "A",
|
|
@@ -1354,26 +1623,26 @@ const We = {
|
|
|
1354
1623
|
run(t) {
|
|
1355
1624
|
var i;
|
|
1356
1625
|
const a = [], e = /* @__PURE__ */ new Map();
|
|
1357
|
-
for (const
|
|
1358
|
-
if (
|
|
1359
|
-
const
|
|
1360
|
-
if (!
|
|
1361
|
-
const o = e.get(
|
|
1362
|
-
o.push(
|
|
1626
|
+
for (const n of t.querySelectorAll("[accesskey]")) {
|
|
1627
|
+
if (m(n)) continue;
|
|
1628
|
+
const r = (i = n.getAttribute("accesskey")) == null ? void 0 : i.trim().toLowerCase();
|
|
1629
|
+
if (!r) continue;
|
|
1630
|
+
const o = e.get(r) || [];
|
|
1631
|
+
o.push(n), e.set(r, o);
|
|
1363
1632
|
}
|
|
1364
|
-
for (const [
|
|
1365
|
-
if (
|
|
1366
|
-
for (const o of
|
|
1633
|
+
for (const [n, r] of e)
|
|
1634
|
+
if (r.length > 1)
|
|
1635
|
+
for (const o of r.slice(1))
|
|
1367
1636
|
a.push({
|
|
1368
1637
|
ruleId: "accesskeys",
|
|
1369
1638
|
selector: c(o),
|
|
1370
1639
|
html: l(o),
|
|
1371
1640
|
impact: "serious",
|
|
1372
|
-
message: `Duplicate accesskey "${
|
|
1641
|
+
message: `Duplicate accesskey "${n}". Each accesskey must be unique.`
|
|
1373
1642
|
});
|
|
1374
1643
|
return a;
|
|
1375
1644
|
}
|
|
1376
|
-
},
|
|
1645
|
+
}, nt = {
|
|
1377
1646
|
id: "heading-order",
|
|
1378
1647
|
wcag: [],
|
|
1379
1648
|
level: "A",
|
|
@@ -1383,22 +1652,22 @@ const We = {
|
|
|
1383
1652
|
prompt: "State which heading level was expected and suggest changing this heading to the appropriate level.",
|
|
1384
1653
|
run(t) {
|
|
1385
1654
|
const a = [], e = t.querySelectorAll("h1, h2, h3, h4, h5, h6, [role='heading']");
|
|
1386
|
-
let i = 0,
|
|
1387
|
-
for (const
|
|
1388
|
-
if (
|
|
1655
|
+
let i = 0, n = null;
|
|
1656
|
+
for (const r of e) {
|
|
1657
|
+
if (m(r)) continue;
|
|
1389
1658
|
let o;
|
|
1390
|
-
|
|
1659
|
+
r.hasAttribute("aria-level") ? o = parseInt(r.getAttribute("aria-level"), 10) : o = parseInt(r.tagName[1], 10), i > 0 && o > i + 1 && a.push({
|
|
1391
1660
|
ruleId: "heading-order",
|
|
1392
|
-
selector: c(
|
|
1393
|
-
html: l(
|
|
1661
|
+
selector: c(r),
|
|
1662
|
+
html: l(r),
|
|
1394
1663
|
impact: "moderate",
|
|
1395
1664
|
message: `Heading level ${o} skipped from level ${i}.`,
|
|
1396
|
-
context:
|
|
1397
|
-
}), i = o,
|
|
1665
|
+
context: n ? `Previous heading: ${l(n)}` : void 0
|
|
1666
|
+
}), i = o, n = r;
|
|
1398
1667
|
}
|
|
1399
1668
|
return a;
|
|
1400
1669
|
}
|
|
1401
|
-
},
|
|
1670
|
+
}, L = 'article, aside, main, nav, section, [role="article"], [role="complementary"], [role="main"], [role="navigation"], [role="region"]', j = 'main, [role="main"], header, [role="banner"], footer, [role="contentinfo"], nav, [role="navigation"], aside, [role="complementary"], section[aria-label], section[aria-labelledby], [role="region"][aria-label], [role="region"][aria-labelledby], form[aria-label], form[aria-labelledby], [role="form"][aria-label], [role="form"][aria-labelledby], [role="search"]', rt = {
|
|
1402
1671
|
id: "landmark-one-main",
|
|
1403
1672
|
wcag: [],
|
|
1404
1673
|
level: "A",
|
|
@@ -1422,7 +1691,7 @@ const We = {
|
|
|
1422
1691
|
message: "Page has multiple main landmarks."
|
|
1423
1692
|
})) : [];
|
|
1424
1693
|
}
|
|
1425
|
-
},
|
|
1694
|
+
}, ot = {
|
|
1426
1695
|
id: "landmark-no-duplicate-banner",
|
|
1427
1696
|
wcag: [],
|
|
1428
1697
|
level: "A",
|
|
@@ -1431,18 +1700,18 @@ const We = {
|
|
|
1431
1700
|
guidance: "The banner landmark (typically <header>) identifies site-oriented content like logos and search. Only one top-level banner is allowed per page. If you need multiple headers, nest them inside sectioning elements (article, section, aside) where they become scoped headers rather than page-level banners.",
|
|
1432
1701
|
prompt: "Explain whether to remove this duplicate banner or nest it inside a sectioning element.",
|
|
1433
1702
|
run(t) {
|
|
1434
|
-
const a = [], e = t.querySelectorAll('header, [role="banner"]'), i = Array.from(e).filter((
|
|
1703
|
+
const a = [], e = t.querySelectorAll('header, [role="banner"]'), i = Array.from(e).filter((n) => !n.closest(L));
|
|
1435
1704
|
return i.length > 1 && i.slice(1).forEach(
|
|
1436
|
-
(
|
|
1705
|
+
(n) => a.push({
|
|
1437
1706
|
ruleId: "landmark-no-duplicate-banner",
|
|
1438
|
-
selector: c(
|
|
1439
|
-
html: l(
|
|
1707
|
+
selector: c(n),
|
|
1708
|
+
html: l(n),
|
|
1440
1709
|
impact: "moderate",
|
|
1441
1710
|
message: "Page has multiple banner landmarks."
|
|
1442
1711
|
})
|
|
1443
1712
|
), a;
|
|
1444
1713
|
}
|
|
1445
|
-
},
|
|
1714
|
+
}, st = {
|
|
1446
1715
|
id: "landmark-no-duplicate-contentinfo",
|
|
1447
1716
|
wcag: [],
|
|
1448
1717
|
level: "A",
|
|
@@ -1451,18 +1720,18 @@ const We = {
|
|
|
1451
1720
|
guidance: "The contentinfo landmark (typically <footer>) contains information about the page like copyright and contact info. Only one top-level contentinfo is allowed per page. Nest additional footers inside sectioning elements to scope them.",
|
|
1452
1721
|
prompt: "Explain whether to remove this duplicate footer or nest it inside a sectioning element.",
|
|
1453
1722
|
run(t) {
|
|
1454
|
-
const a = [], e = t.querySelectorAll('footer, [role="contentinfo"]'), i = Array.from(e).filter((
|
|
1723
|
+
const a = [], e = t.querySelectorAll('footer, [role="contentinfo"]'), i = Array.from(e).filter((n) => !n.closest(L));
|
|
1455
1724
|
return i.length > 1 && i.slice(1).forEach(
|
|
1456
|
-
(
|
|
1725
|
+
(n) => a.push({
|
|
1457
1726
|
ruleId: "landmark-no-duplicate-contentinfo",
|
|
1458
|
-
selector: c(
|
|
1459
|
-
html: l(
|
|
1727
|
+
selector: c(n),
|
|
1728
|
+
html: l(n),
|
|
1460
1729
|
impact: "moderate",
|
|
1461
1730
|
message: "Page has multiple contentinfo landmarks."
|
|
1462
1731
|
})
|
|
1463
1732
|
), a;
|
|
1464
1733
|
}
|
|
1465
|
-
},
|
|
1734
|
+
}, lt = {
|
|
1466
1735
|
id: "landmark-no-duplicate-main",
|
|
1467
1736
|
wcag: [],
|
|
1468
1737
|
level: "A",
|
|
@@ -1482,7 +1751,7 @@ const We = {
|
|
|
1482
1751
|
})
|
|
1483
1752
|
), a;
|
|
1484
1753
|
}
|
|
1485
|
-
},
|
|
1754
|
+
}, ct = {
|
|
1486
1755
|
id: "landmark-banner-is-top-level",
|
|
1487
1756
|
wcag: [],
|
|
1488
1757
|
level: "A",
|
|
@@ -1493,7 +1762,7 @@ const We = {
|
|
|
1493
1762
|
run(t) {
|
|
1494
1763
|
const a = [], e = t.querySelectorAll('[role="banner"]');
|
|
1495
1764
|
for (const i of e)
|
|
1496
|
-
i.closest(
|
|
1765
|
+
i.closest(L) && a.push({
|
|
1497
1766
|
ruleId: "landmark-banner-is-top-level",
|
|
1498
1767
|
selector: c(i),
|
|
1499
1768
|
html: l(i),
|
|
@@ -1502,7 +1771,7 @@ const We = {
|
|
|
1502
1771
|
});
|
|
1503
1772
|
return a;
|
|
1504
1773
|
}
|
|
1505
|
-
},
|
|
1774
|
+
}, dt = {
|
|
1506
1775
|
id: "landmark-contentinfo-is-top-level",
|
|
1507
1776
|
wcag: [],
|
|
1508
1777
|
level: "A",
|
|
@@ -1513,7 +1782,7 @@ const We = {
|
|
|
1513
1782
|
run(t) {
|
|
1514
1783
|
const a = [], e = t.querySelectorAll('[role="contentinfo"]');
|
|
1515
1784
|
for (const i of e)
|
|
1516
|
-
i.closest(
|
|
1785
|
+
i.closest(L) && a.push({
|
|
1517
1786
|
ruleId: "landmark-contentinfo-is-top-level",
|
|
1518
1787
|
selector: c(i),
|
|
1519
1788
|
html: l(i),
|
|
@@ -1522,7 +1791,7 @@ const We = {
|
|
|
1522
1791
|
});
|
|
1523
1792
|
return a;
|
|
1524
1793
|
}
|
|
1525
|
-
},
|
|
1794
|
+
}, ut = {
|
|
1526
1795
|
id: "landmark-main-is-top-level",
|
|
1527
1796
|
wcag: [],
|
|
1528
1797
|
level: "A",
|
|
@@ -1533,8 +1802,8 @@ const We = {
|
|
|
1533
1802
|
run(t) {
|
|
1534
1803
|
const a = [], e = t.querySelectorAll('main, [role="main"]');
|
|
1535
1804
|
for (const i of e) {
|
|
1536
|
-
const
|
|
1537
|
-
|
|
1805
|
+
const n = i.parentElement;
|
|
1806
|
+
n != null && n.closest('article, aside, nav, section, [role="article"], [role="complementary"], [role="navigation"], [role="region"]') && a.push({
|
|
1538
1807
|
ruleId: "landmark-main-is-top-level",
|
|
1539
1808
|
selector: c(i),
|
|
1540
1809
|
html: l(i),
|
|
@@ -1544,7 +1813,7 @@ const We = {
|
|
|
1544
1813
|
}
|
|
1545
1814
|
return a;
|
|
1546
1815
|
}
|
|
1547
|
-
},
|
|
1816
|
+
}, mt = {
|
|
1548
1817
|
id: "landmark-complementary-is-top-level",
|
|
1549
1818
|
wcag: [],
|
|
1550
1819
|
level: "A",
|
|
@@ -1555,8 +1824,8 @@ const We = {
|
|
|
1555
1824
|
run(t) {
|
|
1556
1825
|
const a = [], e = t.querySelectorAll('aside, [role="complementary"]');
|
|
1557
1826
|
for (const i of e) {
|
|
1558
|
-
const
|
|
1559
|
-
|
|
1827
|
+
const n = i.parentElement;
|
|
1828
|
+
n && !n.matches('body, main, [role="main"]') && i.closest('article, nav, section, [role="article"], [role="navigation"], [role="region"]') && a.push({
|
|
1560
1829
|
ruleId: "landmark-complementary-is-top-level",
|
|
1561
1830
|
selector: c(i),
|
|
1562
1831
|
html: l(i),
|
|
@@ -1566,7 +1835,7 @@ const We = {
|
|
|
1566
1835
|
}
|
|
1567
1836
|
return a;
|
|
1568
1837
|
}
|
|
1569
|
-
},
|
|
1838
|
+
}, pt = {
|
|
1570
1839
|
id: "landmark-unique",
|
|
1571
1840
|
wcag: [],
|
|
1572
1841
|
level: "A",
|
|
@@ -1581,28 +1850,28 @@ const We = {
|
|
|
1581
1850
|
{ selector: 'section[aria-label], section[aria-labelledby], [role="region"]', type: "region" },
|
|
1582
1851
|
{ selector: 'form[aria-label], form[aria-labelledby], [role="form"], [role="search"]', type: "form" }
|
|
1583
1852
|
];
|
|
1584
|
-
for (const { selector: i, type:
|
|
1585
|
-
const
|
|
1586
|
-
if (
|
|
1853
|
+
for (const { selector: i, type: n } of e) {
|
|
1854
|
+
const r = Array.from(t.querySelectorAll(i)).filter((s) => !m(s));
|
|
1855
|
+
if (r.length <= 1) continue;
|
|
1587
1856
|
const o = /* @__PURE__ */ new Map();
|
|
1588
|
-
for (const s of
|
|
1589
|
-
const
|
|
1590
|
-
h.push(s), o.set(
|
|
1857
|
+
for (const s of r) {
|
|
1858
|
+
const u = b(s).toLowerCase() || "", h = o.get(u) || [];
|
|
1859
|
+
h.push(s), o.set(u, h);
|
|
1591
1860
|
}
|
|
1592
|
-
for (const [s,
|
|
1593
|
-
if (
|
|
1594
|
-
for (const h of
|
|
1861
|
+
for (const [s, u] of o)
|
|
1862
|
+
if (u.length > 1)
|
|
1863
|
+
for (const h of u.slice(1))
|
|
1595
1864
|
a.push({
|
|
1596
1865
|
ruleId: "landmark-unique",
|
|
1597
1866
|
selector: c(h),
|
|
1598
1867
|
html: l(h),
|
|
1599
1868
|
impact: "moderate",
|
|
1600
|
-
message: s ? `Multiple ${
|
|
1869
|
+
message: s ? `Multiple ${n} landmarks have the same label "${s}".` : `Multiple ${n} landmarks have no label. Add unique aria-label attributes.`
|
|
1601
1870
|
});
|
|
1602
1871
|
}
|
|
1603
1872
|
return a;
|
|
1604
1873
|
}
|
|
1605
|
-
},
|
|
1874
|
+
}, ht = {
|
|
1606
1875
|
id: "region",
|
|
1607
1876
|
wcag: [],
|
|
1608
1877
|
level: "A",
|
|
@@ -1614,45 +1883,31 @@ const We = {
|
|
|
1614
1883
|
var i;
|
|
1615
1884
|
const a = [], e = t.body;
|
|
1616
1885
|
if (!e) return [];
|
|
1617
|
-
for (const
|
|
1618
|
-
if (
|
|
1619
|
-
const
|
|
1620
|
-
!
|
|
1886
|
+
for (const n of e.children) {
|
|
1887
|
+
if (m(n) || n instanceof HTMLScriptElement || n instanceof HTMLStyleElement || n.tagName === "NOSCRIPT" || n instanceof HTMLElement && n.hidden || n.matches('a[href^="#"]')) continue;
|
|
1888
|
+
const r = n.matches(j), o = (i = n.textContent) == null ? void 0 : i.trim();
|
|
1889
|
+
!r && o && (n.querySelector(j) || a.push({
|
|
1621
1890
|
ruleId: "region",
|
|
1622
|
-
selector: c(
|
|
1623
|
-
html: l(
|
|
1891
|
+
selector: c(n),
|
|
1892
|
+
html: l(n),
|
|
1624
1893
|
impact: "moderate",
|
|
1625
1894
|
message: "Content is not contained within a landmark region."
|
|
1626
1895
|
}));
|
|
1627
1896
|
}
|
|
1628
1897
|
return a;
|
|
1629
1898
|
}
|
|
1630
|
-
},
|
|
1899
|
+
}, gt = {
|
|
1631
1900
|
id: "list",
|
|
1901
|
+
selector: "ul, ol",
|
|
1902
|
+
check: { type: "child-invalid", allowedChildren: ["li", "script", "template"] },
|
|
1903
|
+
impact: "serious",
|
|
1904
|
+
message: "List contains non-<li> child <{{tag}}>.",
|
|
1905
|
+
description: "<ul> and <ol> must only contain <li>, <script>, or <template> as direct children.",
|
|
1632
1906
|
wcag: ["1.3.1"],
|
|
1633
1907
|
level: "A",
|
|
1634
|
-
description: "<ul> and <ol> must only contain <li>, <script>, or <template> as direct children.",
|
|
1635
1908
|
guidance: "Screen readers announce list structure ('list with 5 items') based on proper markup. Placing non-<li> elements directly inside <ul> or <ol> breaks this structure. Wrap content in <li> elements, or if you need wrapper divs for styling, restructure your CSS to style the <li> elements directly.",
|
|
1636
|
-
prompt: "Explain how to restructure this element within the list properly."
|
|
1637
|
-
|
|
1638
|
-
const a = [];
|
|
1639
|
-
for (const e of t.querySelectorAll("ul, ol"))
|
|
1640
|
-
for (const i of e.children) {
|
|
1641
|
-
const r = i.tagName.toLowerCase();
|
|
1642
|
-
if (r !== "li" && r !== "script" && r !== "template") {
|
|
1643
|
-
a.push({
|
|
1644
|
-
ruleId: "list",
|
|
1645
|
-
selector: c(i),
|
|
1646
|
-
html: l(i),
|
|
1647
|
-
impact: "serious",
|
|
1648
|
-
message: `<${e.tagName.toLowerCase()}> contains non-<li> child <${r}>.`
|
|
1649
|
-
});
|
|
1650
|
-
break;
|
|
1651
|
-
}
|
|
1652
|
-
}
|
|
1653
|
-
return a;
|
|
1654
|
-
}
|
|
1655
|
-
}, et = {
|
|
1909
|
+
prompt: "Explain how to restructure this element within the list properly."
|
|
1910
|
+
}, bt = x(gt), ft = {
|
|
1656
1911
|
id: "dlitem",
|
|
1657
1912
|
wcag: ["1.3.1"],
|
|
1658
1913
|
level: "A",
|
|
@@ -1671,30 +1926,18 @@ const We = {
|
|
|
1671
1926
|
});
|
|
1672
1927
|
return a;
|
|
1673
1928
|
}
|
|
1674
|
-
},
|
|
1929
|
+
}, vt = {
|
|
1675
1930
|
id: "definition-list",
|
|
1931
|
+
selector: "dl",
|
|
1932
|
+
check: { type: "child-invalid", allowedChildren: ["dt", "dd", "div", "script", "template"] },
|
|
1933
|
+
impact: "serious",
|
|
1934
|
+
message: "<dl> contains invalid child <{{tag}}>.",
|
|
1935
|
+
description: "<dl> elements must only contain <dt>, <dd>, <div>, <script>, or <template>.",
|
|
1676
1936
|
wcag: ["1.3.1"],
|
|
1677
1937
|
level: "A",
|
|
1678
|
-
description: "<dl> elements must only contain <dt>, <dd>, <div>, <script>, or <template>.",
|
|
1679
1938
|
guidance: "Definition lists have strict content requirements. Only <dt> (terms), <dd> (definitions), and <div> (for grouping dt/dd pairs) are valid children. Other elements break the list structure for screen readers. Move invalid elements outside the <dl>, or restructure using proper definition list markup.",
|
|
1680
|
-
prompt: "Explain whether to move this element outside the <dl> or convert it to dt/dd."
|
|
1681
|
-
|
|
1682
|
-
const a = [], e = /* @__PURE__ */ new Set(["dt", "dd", "div", "script", "template"]);
|
|
1683
|
-
for (const i of t.querySelectorAll("dl"))
|
|
1684
|
-
for (const r of i.children)
|
|
1685
|
-
if (!e.has(r.tagName.toLowerCase())) {
|
|
1686
|
-
a.push({
|
|
1687
|
-
ruleId: "definition-list",
|
|
1688
|
-
selector: c(r),
|
|
1689
|
-
html: l(r),
|
|
1690
|
-
impact: "serious",
|
|
1691
|
-
message: `<dl> contains invalid child <${r.tagName.toLowerCase()}>.`
|
|
1692
|
-
});
|
|
1693
|
-
break;
|
|
1694
|
-
}
|
|
1695
|
-
return a;
|
|
1696
|
-
}
|
|
1697
|
-
}, at = {
|
|
1939
|
+
prompt: "Explain whether to move this element outside the <dl> or convert it to dt/dd."
|
|
1940
|
+
}, yt = x(vt), wt = {
|
|
1698
1941
|
id: "document-title",
|
|
1699
1942
|
wcag: ["2.4.2"],
|
|
1700
1943
|
level: "A",
|
|
@@ -1712,7 +1955,7 @@ const We = {
|
|
|
1712
1955
|
message: a ? "Document <title> element is empty." : "Document is missing a <title> element."
|
|
1713
1956
|
}] : [];
|
|
1714
1957
|
}
|
|
1715
|
-
},
|
|
1958
|
+
}, At = {
|
|
1716
1959
|
id: "bypass",
|
|
1717
1960
|
wcag: ["2.4.1"],
|
|
1718
1961
|
level: "A",
|
|
@@ -1725,10 +1968,10 @@ const We = {
|
|
|
1725
1968
|
)) return [];
|
|
1726
1969
|
const e = t.querySelector('a[href^="#"]');
|
|
1727
1970
|
if (e) {
|
|
1728
|
-
const
|
|
1729
|
-
if (
|
|
1730
|
-
const
|
|
1731
|
-
if (t.getElementById(
|
|
1971
|
+
const n = e.getAttribute("href");
|
|
1972
|
+
if (n && n.length > 1) {
|
|
1973
|
+
const r = n.slice(1);
|
|
1974
|
+
if (t.getElementById(r)) return [];
|
|
1732
1975
|
}
|
|
1733
1976
|
}
|
|
1734
1977
|
return t.querySelector("h1, h2, h3, [role='heading']") ? [] : [{
|
|
@@ -1739,7 +1982,7 @@ const We = {
|
|
|
1739
1982
|
message: "Page has no mechanism to bypass repeated content. Add a <main> landmark or skip link."
|
|
1740
1983
|
}];
|
|
1741
1984
|
}
|
|
1742
|
-
},
|
|
1985
|
+
}, St = {
|
|
1743
1986
|
id: "page-has-heading-one",
|
|
1744
1987
|
wcag: [],
|
|
1745
1988
|
level: "A",
|
|
@@ -1749,10 +1992,10 @@ const We = {
|
|
|
1749
1992
|
prompt: "Suggest appropriate h1 text based on the page's visible content.",
|
|
1750
1993
|
run(t) {
|
|
1751
1994
|
const a = t.querySelector("h1");
|
|
1752
|
-
if (a &&
|
|
1995
|
+
if (a && b(a)) return [];
|
|
1753
1996
|
const e = t.querySelectorAll('[role="heading"][aria-level="1"]');
|
|
1754
1997
|
for (const i of e)
|
|
1755
|
-
if (
|
|
1998
|
+
if (b(i)) return [];
|
|
1756
1999
|
return [{
|
|
1757
2000
|
ruleId: "page-has-heading-one",
|
|
1758
2001
|
selector: "html",
|
|
@@ -1761,7 +2004,7 @@ const We = {
|
|
|
1761
2004
|
message: "Page does not contain a level-one heading."
|
|
1762
2005
|
}];
|
|
1763
2006
|
}
|
|
1764
|
-
},
|
|
2007
|
+
}, xt = {
|
|
1765
2008
|
id: "frame-title",
|
|
1766
2009
|
wcag: ["4.1.2"],
|
|
1767
2010
|
level: "A",
|
|
@@ -1771,8 +2014,8 @@ const We = {
|
|
|
1771
2014
|
run(t) {
|
|
1772
2015
|
const a = [];
|
|
1773
2016
|
for (const e of t.querySelectorAll("iframe, frame")) {
|
|
1774
|
-
if (
|
|
1775
|
-
|
|
2017
|
+
if (m(e)) continue;
|
|
2018
|
+
b(e) || a.push({
|
|
1776
2019
|
ruleId: "frame-title",
|
|
1777
2020
|
selector: c(e),
|
|
1778
2021
|
html: l(e),
|
|
@@ -1782,7 +2025,7 @@ const We = {
|
|
|
1782
2025
|
}
|
|
1783
2026
|
return a;
|
|
1784
2027
|
}
|
|
1785
|
-
},
|
|
2028
|
+
}, kt = {
|
|
1786
2029
|
id: "frame-title-unique",
|
|
1787
2030
|
wcag: ["4.1.2"],
|
|
1788
2031
|
level: "A",
|
|
@@ -1791,21 +2034,21 @@ const We = {
|
|
|
1791
2034
|
guidance: "When multiple frames have identical titles, screen reader users cannot distinguish between them. Give each frame a unique, descriptive title that explains its specific purpose or content.",
|
|
1792
2035
|
prompt: "Suggest a more specific title to distinguish this frame from others.",
|
|
1793
2036
|
run(t) {
|
|
1794
|
-
var
|
|
2037
|
+
var n;
|
|
1795
2038
|
const a = [], e = Array.from(t.querySelectorAll("iframe[title], frame[title]")), i = /* @__PURE__ */ new Map();
|
|
1796
|
-
for (const
|
|
1797
|
-
if (
|
|
1798
|
-
const o =
|
|
1799
|
-
if (o === "0" || s === "0" ||
|
|
1800
|
-
const
|
|
1801
|
-
if (
|
|
1802
|
-
const h = i.get(
|
|
1803
|
-
h.push(
|
|
2039
|
+
for (const r of e) {
|
|
2040
|
+
if (m(r)) continue;
|
|
2041
|
+
const o = r.getAttribute("width"), s = r.getAttribute("height");
|
|
2042
|
+
if (o === "0" || s === "0" || r instanceof HTMLElement && r.style.display === "none" || r instanceof HTMLElement && r.style.visibility === "hidden") continue;
|
|
2043
|
+
const u = (n = r.getAttribute("title")) == null ? void 0 : n.trim().toLowerCase();
|
|
2044
|
+
if (u) {
|
|
2045
|
+
const h = i.get(u) || [];
|
|
2046
|
+
h.push(r), i.set(u, h);
|
|
1804
2047
|
}
|
|
1805
2048
|
}
|
|
1806
|
-
for (const [,
|
|
1807
|
-
if (
|
|
1808
|
-
for (const o of
|
|
2049
|
+
for (const [, r] of i)
|
|
2050
|
+
if (r.length > 1)
|
|
2051
|
+
for (const o of r.slice(1))
|
|
1809
2052
|
a.push({
|
|
1810
2053
|
ruleId: "frame-title-unique",
|
|
1811
2054
|
selector: c(o),
|
|
@@ -1815,7 +2058,7 @@ const We = {
|
|
|
1815
2058
|
});
|
|
1816
2059
|
return a;
|
|
1817
2060
|
}
|
|
1818
|
-
},
|
|
2061
|
+
}, It = {
|
|
1819
2062
|
id: "empty-heading",
|
|
1820
2063
|
wcag: [],
|
|
1821
2064
|
level: "A",
|
|
@@ -1826,7 +2069,7 @@ const We = {
|
|
|
1826
2069
|
run(t) {
|
|
1827
2070
|
const a = [], e = t.querySelectorAll('h1, h2, h3, h4, h5, h6, [role="heading"]');
|
|
1828
2071
|
for (const i of e)
|
|
1829
|
-
|
|
2072
|
+
m(i) || b(i) || a.push({
|
|
1830
2073
|
ruleId: "empty-heading",
|
|
1831
2074
|
selector: c(i),
|
|
1832
2075
|
html: l(i),
|
|
@@ -1835,7 +2078,7 @@ const We = {
|
|
|
1835
2078
|
});
|
|
1836
2079
|
return a;
|
|
1837
2080
|
}
|
|
1838
|
-
},
|
|
2081
|
+
}, qt = {
|
|
1839
2082
|
id: "meta-viewport",
|
|
1840
2083
|
wcag: ["1.4.4"],
|
|
1841
2084
|
level: "AA",
|
|
@@ -1843,10 +2086,10 @@ const We = {
|
|
|
1843
2086
|
guidance: "Users with low vision need to zoom content up to 200% or more. Setting user-scalable=no or maximum-scale=1 prevents zooming and fails WCAG. Remove these restrictions. If your layout breaks at high zoom, fix the responsive design rather than preventing zoom.",
|
|
1844
2087
|
prompt: "Explain which viewport restrictions to remove and show the corrected meta tag.",
|
|
1845
2088
|
run(t) {
|
|
1846
|
-
var
|
|
2089
|
+
var r;
|
|
1847
2090
|
const a = [], e = t.querySelector('meta[name="viewport"]');
|
|
1848
2091
|
if (!e) return [];
|
|
1849
|
-
const i = ((
|
|
2092
|
+
const i = ((r = e.getAttribute("content")) == null ? void 0 : r.toLowerCase()) || "";
|
|
1850
2093
|
(/user-scalable\s*=\s*no/i.test(i) || /user-scalable\s*=\s*0/i.test(i)) && a.push({
|
|
1851
2094
|
ruleId: "meta-viewport",
|
|
1852
2095
|
selector: c(e),
|
|
@@ -1854,9 +2097,9 @@ const We = {
|
|
|
1854
2097
|
impact: "critical",
|
|
1855
2098
|
message: "Viewport disables user scaling. Remove user-scalable=no."
|
|
1856
2099
|
});
|
|
1857
|
-
const
|
|
1858
|
-
if (
|
|
1859
|
-
const o = parseFloat(
|
|
2100
|
+
const n = i.match(/maximum-scale\s*=\s*([\d.]+)/i);
|
|
2101
|
+
if (n) {
|
|
2102
|
+
const o = parseFloat(n[1]);
|
|
1860
2103
|
o < 2 && a.push({
|
|
1861
2104
|
ruleId: "meta-viewport",
|
|
1862
2105
|
selector: c(e),
|
|
@@ -1867,7 +2110,7 @@ const We = {
|
|
|
1867
2110
|
}
|
|
1868
2111
|
return a;
|
|
1869
2112
|
}
|
|
1870
|
-
},
|
|
2113
|
+
}, Ct = {
|
|
1871
2114
|
id: "meta-refresh",
|
|
1872
2115
|
wcag: ["2.2.1", "2.2.4", "3.2.5"],
|
|
1873
2116
|
level: "A",
|
|
@@ -1877,10 +2120,10 @@ const We = {
|
|
|
1877
2120
|
run(t) {
|
|
1878
2121
|
const a = [], e = t.querySelector('meta[http-equiv="refresh"]');
|
|
1879
2122
|
if (!e) return [];
|
|
1880
|
-
const i = e.getAttribute("content") || "",
|
|
1881
|
-
if (
|
|
1882
|
-
const
|
|
1883
|
-
i.includes("url=") ?
|
|
2123
|
+
const i = e.getAttribute("content") || "", n = i.match(/^(\d+)/);
|
|
2124
|
+
if (n) {
|
|
2125
|
+
const r = parseInt(n[1], 10);
|
|
2126
|
+
i.includes("url=") ? r <= 0 ? a.push({
|
|
1884
2127
|
ruleId: "meta-refresh",
|
|
1885
2128
|
selector: c(e),
|
|
1886
2129
|
html: l(e),
|
|
@@ -1891,56 +2134,40 @@ const We = {
|
|
|
1891
2134
|
selector: c(e),
|
|
1892
2135
|
html: l(e),
|
|
1893
2136
|
impact: "critical",
|
|
1894
|
-
message: `Page redirects after ${
|
|
1895
|
-
}) :
|
|
2137
|
+
message: `Page redirects after ${r} seconds without warning. Use server-side redirect.`
|
|
2138
|
+
}) : r > 0 && r <= 72e3 && a.push({
|
|
1896
2139
|
ruleId: "meta-refresh",
|
|
1897
2140
|
selector: c(e),
|
|
1898
2141
|
html: l(e),
|
|
1899
2142
|
impact: "critical",
|
|
1900
|
-
message: `Page auto-refreshes after ${
|
|
2143
|
+
message: `Page auto-refreshes after ${r} seconds. Provide user control over refresh.`
|
|
1901
2144
|
});
|
|
1902
2145
|
}
|
|
1903
2146
|
return a;
|
|
1904
2147
|
}
|
|
1905
|
-
},
|
|
2148
|
+
}, Tt = {
|
|
1906
2149
|
id: "blink",
|
|
2150
|
+
selector: "blink",
|
|
2151
|
+
check: { type: "selector-exists" },
|
|
2152
|
+
impact: "serious",
|
|
2153
|
+
message: "The <blink> element causes accessibility issues. Remove it entirely.",
|
|
2154
|
+
description: "The <blink> element must not be used.",
|
|
1907
2155
|
wcag: ["2.2.2"],
|
|
1908
2156
|
level: "A",
|
|
1909
|
-
description: "The <blink> element must not be used.",
|
|
1910
2157
|
guidance: "Blinking content can cause seizures in users with photosensitive epilepsy and is distracting for users with attention disorders. The <blink> element is deprecated and should never be used. If you need to draw attention to content, use less intrusive methods like color, borders, or icons.",
|
|
1911
|
-
prompt: "Suggest static alternatives to the blinking effect."
|
|
1912
|
-
|
|
1913
|
-
const a = [];
|
|
1914
|
-
for (const e of t.querySelectorAll("blink"))
|
|
1915
|
-
u(e) || a.push({
|
|
1916
|
-
ruleId: "blink",
|
|
1917
|
-
selector: c(e),
|
|
1918
|
-
html: l(e),
|
|
1919
|
-
impact: "serious",
|
|
1920
|
-
message: "The <blink> element causes accessibility issues. Remove it entirely."
|
|
1921
|
-
});
|
|
1922
|
-
return a;
|
|
1923
|
-
}
|
|
1924
|
-
}, ut = {
|
|
2158
|
+
prompt: "Suggest static alternatives to the blinking effect."
|
|
2159
|
+
}, Et = x(Tt), Lt = {
|
|
1925
2160
|
id: "marquee",
|
|
2161
|
+
selector: "marquee",
|
|
2162
|
+
check: { type: "selector-exists" },
|
|
2163
|
+
impact: "serious",
|
|
2164
|
+
message: "The <marquee> element causes accessibility issues. Replace with static content.",
|
|
2165
|
+
description: "The <marquee> element must not be used.",
|
|
1926
2166
|
wcag: ["2.2.2"],
|
|
1927
2167
|
level: "A",
|
|
1928
|
-
description: "The <marquee> element must not be used.",
|
|
1929
2168
|
guidance: "Scrolling or moving content is difficult for many users to read, especially those with cognitive or visual disabilities. The <marquee> element is deprecated. Replace scrolling text with static content. If content must scroll, provide pause/stop controls and ensure it stops after 5 seconds.",
|
|
1930
|
-
prompt: "Suggest static alternatives or accessible carousel patterns."
|
|
1931
|
-
|
|
1932
|
-
const a = [];
|
|
1933
|
-
for (const e of t.querySelectorAll("marquee"))
|
|
1934
|
-
u(e) || a.push({
|
|
1935
|
-
ruleId: "marquee",
|
|
1936
|
-
selector: c(e),
|
|
1937
|
-
html: l(e),
|
|
1938
|
-
impact: "serious",
|
|
1939
|
-
message: "The <marquee> element causes accessibility issues. Replace with static content."
|
|
1940
|
-
});
|
|
1941
|
-
return a;
|
|
1942
|
-
}
|
|
1943
|
-
}, mt = {
|
|
2169
|
+
prompt: "Suggest static alternatives or accessible carousel patterns."
|
|
2170
|
+
}, Rt = x(Lt), Nt = {
|
|
1944
2171
|
id: "p-as-heading",
|
|
1945
2172
|
wcag: [],
|
|
1946
2173
|
level: "A",
|
|
@@ -1951,15 +2178,15 @@ const We = {
|
|
|
1951
2178
|
run(t) {
|
|
1952
2179
|
var e, i;
|
|
1953
2180
|
const a = [];
|
|
1954
|
-
for (const
|
|
1955
|
-
if (
|
|
1956
|
-
const
|
|
1957
|
-
if ((o && s || o && h) && p &&
|
|
1958
|
-
const y =
|
|
2181
|
+
for (const n of t.querySelectorAll("p")) {
|
|
2182
|
+
if (m(n)) continue;
|
|
2183
|
+
const r = n.getAttribute("style") || "", o = /font-weight\s*:\s*(bold|[6-9]00)/i.test(r), s = /font-size\s*:\s*(\d+)\s*(px|em|rem)/i.test(r), u = ((e = n.className) == null ? void 0 : e.toLowerCase()) || "", h = /\bh[1-6]\b|\bheading\b/.test(u), d = ((i = n.textContent) == null ? void 0 : i.trim()) || "", p = d.length > 0 && d.length < 50, g = !d.match(/[.!?,;:]$/);
|
|
2184
|
+
if ((o && s || o && h) && p && g) {
|
|
2185
|
+
const y = n.nextElementSibling;
|
|
1959
2186
|
y && (y.tagName === "P" || y.tagName === "DIV" || y.tagName === "UL") && a.push({
|
|
1960
2187
|
ruleId: "p-as-heading",
|
|
1961
|
-
selector: c(
|
|
1962
|
-
html: l(
|
|
2188
|
+
selector: c(n),
|
|
2189
|
+
html: l(n),
|
|
1963
2190
|
impact: "serious",
|
|
1964
2191
|
message: "Paragraph appears to be styled as a heading. Use an h1-h6 element instead."
|
|
1965
2192
|
});
|
|
@@ -1967,7 +2194,7 @@ const We = {
|
|
|
1967
2194
|
}
|
|
1968
2195
|
return a;
|
|
1969
2196
|
}
|
|
1970
|
-
},
|
|
2197
|
+
}, $t = {
|
|
1971
2198
|
id: "aria-roles",
|
|
1972
2199
|
wcag: ["4.1.2"],
|
|
1973
2200
|
level: "A",
|
|
@@ -1977,9 +2204,9 @@ const We = {
|
|
|
1977
2204
|
run(t) {
|
|
1978
2205
|
const a = [];
|
|
1979
2206
|
for (const e of t.querySelectorAll("[role]")) {
|
|
1980
|
-
const
|
|
1981
|
-
for (const o of
|
|
1982
|
-
if (o && !
|
|
2207
|
+
const r = e.getAttribute("role").replace(/[\u201C\u201D\u2018\u2019\u00AB\u00BB]/g, "").split(/\s+/);
|
|
2208
|
+
for (const o of r)
|
|
2209
|
+
if (o && !se(o)) {
|
|
1983
2210
|
a.push({
|
|
1984
2211
|
ruleId: "aria-roles",
|
|
1985
2212
|
selector: c(e),
|
|
@@ -1992,7 +2219,7 @@ const We = {
|
|
|
1992
2219
|
}
|
|
1993
2220
|
return a;
|
|
1994
2221
|
}
|
|
1995
|
-
},
|
|
2222
|
+
}, Mt = {
|
|
1996
2223
|
id: "aria-valid-attr",
|
|
1997
2224
|
wcag: ["4.1.2"],
|
|
1998
2225
|
level: "A",
|
|
@@ -2000,9 +2227,9 @@ const We = {
|
|
|
2000
2227
|
guidance: "Misspelled ARIA attributes are ignored by assistive technologies. Check the spelling against the WAI-ARIA specification. Common mistakes: aria-labeledby (should be aria-labelledby), aria-role (should be role), aria-description (valid in ARIA 1.3+).",
|
|
2001
2228
|
prompt: "Identify the misspelled attribute and provide the correct spelling.",
|
|
2002
2229
|
run(t) {
|
|
2003
|
-
return
|
|
2230
|
+
return O(t).validAttr;
|
|
2004
2231
|
}
|
|
2005
|
-
},
|
|
2232
|
+
}, Ht = {
|
|
2006
2233
|
id: "aria-valid-attr-value",
|
|
2007
2234
|
wcag: ["4.1.2"],
|
|
2008
2235
|
level: "A",
|
|
@@ -2010,9 +2237,9 @@ const We = {
|
|
|
2010
2237
|
guidance: "Each ARIA attribute accepts specific value types. Boolean attributes (aria-hidden, aria-disabled) accept only 'true' or 'false'. Tristate attributes (aria-checked, aria-pressed) also accept 'mixed'. Token attributes (aria-live, aria-autocomplete) accept predefined values. ID reference attributes (aria-labelledby, aria-describedby) must reference existing element IDs.",
|
|
2011
2238
|
prompt: "Show the invalid value and list the valid values for this specific attribute.",
|
|
2012
2239
|
run(t) {
|
|
2013
|
-
return
|
|
2240
|
+
return O(t).validAttrValue;
|
|
2014
2241
|
}
|
|
2015
|
-
},
|
|
2242
|
+
}, Dt = {
|
|
2016
2243
|
checkbox: ["aria-checked"],
|
|
2017
2244
|
combobox: ["aria-expanded"],
|
|
2018
2245
|
heading: ["aria-level"],
|
|
@@ -2027,7 +2254,7 @@ const We = {
|
|
|
2027
2254
|
slider: ["aria-valuenow"],
|
|
2028
2255
|
spinbutton: ["aria-valuenow"],
|
|
2029
2256
|
switch: ["aria-checked"]
|
|
2030
|
-
},
|
|
2257
|
+
}, Bt = {
|
|
2031
2258
|
id: "aria-required-attr",
|
|
2032
2259
|
wcag: ["4.1.2"],
|
|
2033
2260
|
level: "A",
|
|
@@ -2037,21 +2264,21 @@ const We = {
|
|
|
2037
2264
|
run(t) {
|
|
2038
2265
|
const a = [];
|
|
2039
2266
|
for (const e of t.querySelectorAll("[role]")) {
|
|
2040
|
-
const i = e.getAttribute("role").trim().toLowerCase(),
|
|
2041
|
-
if (
|
|
2267
|
+
const i = e.getAttribute("role").trim().toLowerCase(), n = Dt[i];
|
|
2268
|
+
if (n && !(i === "checkbox" && e instanceof HTMLInputElement && e.type === "checkbox") && !(i === "radio" && e instanceof HTMLInputElement && e.type === "radio") && !(i === "option" && e instanceof HTMLOptionElement) && !(i === "heading" && /^h[1-6]$/i.test(e.tagName))) {
|
|
2042
2269
|
if (i === "separator") {
|
|
2043
|
-
const
|
|
2044
|
-
if (!
|
|
2270
|
+
const r = e.getAttribute("tabindex");
|
|
2271
|
+
if (!r || r === "-1") continue;
|
|
2045
2272
|
}
|
|
2046
2273
|
if (!(e.tagName.toLowerCase() === "hr" && !e.hasAttribute("role"))) {
|
|
2047
|
-
for (const
|
|
2048
|
-
if (!e.hasAttribute(
|
|
2274
|
+
for (const r of n)
|
|
2275
|
+
if (!e.hasAttribute(r)) {
|
|
2049
2276
|
a.push({
|
|
2050
2277
|
ruleId: "aria-required-attr",
|
|
2051
2278
|
selector: c(e),
|
|
2052
2279
|
html: l(e),
|
|
2053
2280
|
impact: "critical",
|
|
2054
|
-
message: `Role "${i}" requires attribute "${
|
|
2281
|
+
message: `Role "${i}" requires attribute "${r}".`
|
|
2055
2282
|
});
|
|
2056
2283
|
break;
|
|
2057
2284
|
}
|
|
@@ -2061,24 +2288,24 @@ const We = {
|
|
|
2061
2288
|
return a;
|
|
2062
2289
|
}
|
|
2063
2290
|
};
|
|
2064
|
-
function
|
|
2065
|
-
var
|
|
2291
|
+
function Ot(t) {
|
|
2292
|
+
var r, o, s;
|
|
2066
2293
|
const a = [], e = t.className;
|
|
2067
2294
|
e && typeof e == "string" && e.trim() && a.push(`Classes: ${e.trim().slice(0, 100)}`);
|
|
2068
2295
|
const i = t.closest("form");
|
|
2069
2296
|
if (i) {
|
|
2070
|
-
const
|
|
2071
|
-
|
|
2297
|
+
const u = i.getAttribute("aria-label") || ((o = (r = i.querySelector("legend")) == null ? void 0 : r.textContent) == null ? void 0 : o.trim());
|
|
2298
|
+
u && a.push(`Form: ${u.slice(0, 60)}`);
|
|
2072
2299
|
}
|
|
2073
|
-
const
|
|
2074
|
-
if (
|
|
2075
|
-
const
|
|
2076
|
-
(s =
|
|
2300
|
+
const n = t.parentElement;
|
|
2301
|
+
if (n) {
|
|
2302
|
+
const u = n.closest("h1, h2, h3, h4, h5, h6") || n.querySelector("h1, h2, h3, h4, h5, h6");
|
|
2303
|
+
(s = u == null ? void 0 : u.textContent) != null && s.trim() && a.push(`Nearby heading: ${u.textContent.trim().slice(0, 60)}`);
|
|
2077
2304
|
}
|
|
2078
2305
|
return a.length > 0 ? a.join(`
|
|
2079
2306
|
`) : void 0;
|
|
2080
2307
|
}
|
|
2081
|
-
const
|
|
2308
|
+
const Wt = {
|
|
2082
2309
|
id: "button-name",
|
|
2083
2310
|
wcag: ["4.1.2"],
|
|
2084
2311
|
level: "A",
|
|
@@ -2088,19 +2315,19 @@ const yt = {
|
|
|
2088
2315
|
run(t) {
|
|
2089
2316
|
const a = [];
|
|
2090
2317
|
for (const e of t.querySelectorAll('button, [role="button"]')) {
|
|
2091
|
-
if (
|
|
2092
|
-
|
|
2318
|
+
if (m(e) || e.getRootNode() instanceof ShadowRoot) continue;
|
|
2319
|
+
b(e) || a.push({
|
|
2093
2320
|
ruleId: "button-name",
|
|
2094
2321
|
selector: c(e),
|
|
2095
2322
|
html: l(e),
|
|
2096
2323
|
impact: "critical",
|
|
2097
2324
|
message: "Button has no discernible text.",
|
|
2098
|
-
context:
|
|
2325
|
+
context: Ot(e)
|
|
2099
2326
|
});
|
|
2100
2327
|
}
|
|
2101
2328
|
return a;
|
|
2102
2329
|
}
|
|
2103
|
-
},
|
|
2330
|
+
}, Ft = {
|
|
2104
2331
|
alert: /* @__PURE__ */ new Set(["aria-atomic", "aria-busy", "aria-live", "aria-relevant"]),
|
|
2105
2332
|
alertdialog: /* @__PURE__ */ new Set(["aria-describedby", "aria-modal"]),
|
|
2106
2333
|
application: /* @__PURE__ */ new Set(["aria-activedescendant", "aria-disabled", "aria-errormessage", "aria-expanded", "aria-haspopup", "aria-invalid"]),
|
|
@@ -2172,7 +2399,7 @@ const yt = {
|
|
|
2172
2399
|
tree: /* @__PURE__ */ new Set(["aria-activedescendant", "aria-disabled", "aria-errormessage", "aria-invalid", "aria-multiselectable", "aria-orientation", "aria-required"]),
|
|
2173
2400
|
treegrid: /* @__PURE__ */ new Set(["aria-activedescendant", "aria-colcount", "aria-disabled", "aria-errormessage", "aria-invalid", "aria-multiselectable", "aria-orientation", "aria-readonly", "aria-required", "aria-rowcount"]),
|
|
2174
2401
|
treeitem: /* @__PURE__ */ new Set(["aria-checked", "aria-disabled", "aria-expanded", "aria-haspopup", "aria-level", "aria-posinset", "aria-selected", "aria-setsize"])
|
|
2175
|
-
},
|
|
2402
|
+
}, _t = /* @__PURE__ */ new Set([
|
|
2176
2403
|
"aria-atomic",
|
|
2177
2404
|
"aria-busy",
|
|
2178
2405
|
"aria-controls",
|
|
@@ -2196,7 +2423,7 @@ const yt = {
|
|
|
2196
2423
|
"aria-roledescription",
|
|
2197
2424
|
"aria-braillelabel",
|
|
2198
2425
|
"aria-brailleroledescription"
|
|
2199
|
-
]),
|
|
2426
|
+
]), Pt = {
|
|
2200
2427
|
id: "aria-allowed-attr",
|
|
2201
2428
|
wcag: ["4.1.2"],
|
|
2202
2429
|
level: "A",
|
|
@@ -2206,23 +2433,23 @@ const yt = {
|
|
|
2206
2433
|
run(t) {
|
|
2207
2434
|
const a = [];
|
|
2208
2435
|
for (const e of t.querySelectorAll("[role], [aria-*]")) {
|
|
2209
|
-
if (
|
|
2210
|
-
const i =
|
|
2436
|
+
if (m(e)) continue;
|
|
2437
|
+
const i = T(e);
|
|
2211
2438
|
if (!i) continue;
|
|
2212
|
-
const
|
|
2213
|
-
if (
|
|
2214
|
-
for (const
|
|
2215
|
-
|
|
2439
|
+
const n = Ft[i];
|
|
2440
|
+
if (n)
|
|
2441
|
+
for (const r of e.attributes)
|
|
2442
|
+
r.name.startsWith("aria-") && (_t.has(r.name) || n.has(r.name) || a.push({
|
|
2216
2443
|
ruleId: "aria-allowed-attr",
|
|
2217
2444
|
selector: c(e),
|
|
2218
2445
|
html: l(e),
|
|
2219
2446
|
impact: "critical",
|
|
2220
|
-
message: `ARIA attribute "${
|
|
2447
|
+
message: `ARIA attribute "${r.name}" is not allowed on role "${i}".`
|
|
2221
2448
|
}));
|
|
2222
2449
|
}
|
|
2223
2450
|
return a;
|
|
2224
2451
|
}
|
|
2225
|
-
},
|
|
2452
|
+
}, Vt = /* @__PURE__ */ new Set([
|
|
2226
2453
|
"base",
|
|
2227
2454
|
"col",
|
|
2228
2455
|
"colgroup",
|
|
@@ -2237,7 +2464,7 @@ const yt = {
|
|
|
2237
2464
|
"template",
|
|
2238
2465
|
"title",
|
|
2239
2466
|
"track"
|
|
2240
|
-
]),
|
|
2467
|
+
]), k = {
|
|
2241
2468
|
a: /* @__PURE__ */ new Set(["button", "checkbox", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "switch", "tab", "treeitem", "link"]),
|
|
2242
2469
|
"a[href]": /* @__PURE__ */ new Set(["button", "checkbox", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "switch", "tab", "treeitem"]),
|
|
2243
2470
|
abbr: "any",
|
|
@@ -2344,22 +2571,22 @@ const yt = {
|
|
|
2344
2571
|
video: /* @__PURE__ */ new Set(["application"]),
|
|
2345
2572
|
wbr: /* @__PURE__ */ new Set(["none", "presentation"])
|
|
2346
2573
|
};
|
|
2347
|
-
function
|
|
2574
|
+
function Ut(t) {
|
|
2348
2575
|
var e;
|
|
2349
2576
|
const a = t.tagName.toLowerCase();
|
|
2350
|
-
if (
|
|
2577
|
+
if (Vt.has(a))
|
|
2351
2578
|
return "none";
|
|
2352
2579
|
if (a === "a" && t.hasAttribute("href"))
|
|
2353
|
-
return
|
|
2580
|
+
return k["a[href]"];
|
|
2354
2581
|
if (a === "img" && t.getAttribute("alt") === "")
|
|
2355
|
-
return
|
|
2582
|
+
return k["img[alt='']"];
|
|
2356
2583
|
if (a === "input") {
|
|
2357
|
-
const
|
|
2358
|
-
return
|
|
2584
|
+
const n = `input[type=${((e = t.getAttribute("type")) == null ? void 0 : e.toLowerCase()) || "text"}]`;
|
|
2585
|
+
return n in k ? k[n] : "none";
|
|
2359
2586
|
}
|
|
2360
|
-
return
|
|
2587
|
+
return k[a] || "any";
|
|
2361
2588
|
}
|
|
2362
|
-
const
|
|
2589
|
+
const jt = {
|
|
2363
2590
|
id: "aria-allowed-role",
|
|
2364
2591
|
wcag: ["4.1.2"],
|
|
2365
2592
|
level: "A",
|
|
@@ -2370,29 +2597,29 @@ const It = {
|
|
|
2370
2597
|
var e;
|
|
2371
2598
|
const a = [];
|
|
2372
2599
|
for (const i of t.querySelectorAll("[role]")) {
|
|
2373
|
-
if (
|
|
2374
|
-
const
|
|
2375
|
-
if (!
|
|
2376
|
-
const
|
|
2377
|
-
if (
|
|
2378
|
-
const o =
|
|
2600
|
+
if (m(i)) continue;
|
|
2601
|
+
const n = (e = i.getAttribute("role")) == null ? void 0 : e.trim().toLowerCase();
|
|
2602
|
+
if (!n) continue;
|
|
2603
|
+
const r = Y(i);
|
|
2604
|
+
if (r && n === r) continue;
|
|
2605
|
+
const o = Ut(i);
|
|
2379
2606
|
o === "none" ? a.push({
|
|
2380
2607
|
ruleId: "aria-allowed-role",
|
|
2381
2608
|
selector: c(i),
|
|
2382
2609
|
html: l(i),
|
|
2383
2610
|
impact: "minor",
|
|
2384
2611
|
message: `Element <${i.tagName.toLowerCase()}> should not have an explicit role.`
|
|
2385
|
-
}) : o !== "any" && !o.has(
|
|
2612
|
+
}) : o !== "any" && !o.has(n) && a.push({
|
|
2386
2613
|
ruleId: "aria-allowed-role",
|
|
2387
2614
|
selector: c(i),
|
|
2388
2615
|
html: l(i),
|
|
2389
2616
|
impact: "minor",
|
|
2390
|
-
message: `Role "${
|
|
2617
|
+
message: `Role "${n}" is not allowed on element <${i.tagName.toLowerCase()}>.`
|
|
2391
2618
|
});
|
|
2392
2619
|
}
|
|
2393
2620
|
return a;
|
|
2394
2621
|
}
|
|
2395
|
-
},
|
|
2622
|
+
}, z = {
|
|
2396
2623
|
// Each array is an OR group - at least one of each inner array must be present
|
|
2397
2624
|
combobox: [["listbox", "tree", "grid", "dialog", "textbox"]],
|
|
2398
2625
|
// Must own/contain one of these
|
|
@@ -2409,7 +2636,7 @@ const It = {
|
|
|
2409
2636
|
tablist: [["tab"]],
|
|
2410
2637
|
tree: [["treeitem", "group"]],
|
|
2411
2638
|
treegrid: [["row", "rowgroup"]]
|
|
2412
|
-
},
|
|
2639
|
+
}, G = {
|
|
2413
2640
|
caption: ["figure", "table", "grid", "treegrid"],
|
|
2414
2641
|
// cell/gridcell/columnheader/rowheader must be in a row
|
|
2415
2642
|
// but we skip checking native td/th since they're handled by HTML semantics
|
|
@@ -2423,25 +2650,25 @@ const It = {
|
|
|
2423
2650
|
tab: ["tablist"],
|
|
2424
2651
|
treeitem: ["tree", "group"]
|
|
2425
2652
|
};
|
|
2426
|
-
function
|
|
2427
|
-
var
|
|
2428
|
-
const e = ((
|
|
2653
|
+
function zt(t, a) {
|
|
2654
|
+
var r;
|
|
2655
|
+
const e = ((r = t.getAttribute("aria-owns")) == null ? void 0 : r.split(/\s+/)) || [], i = t.ownerDocument, n = /* @__PURE__ */ new Set();
|
|
2429
2656
|
for (const o of t.querySelectorAll("*")) {
|
|
2430
|
-
const s =
|
|
2431
|
-
s && !
|
|
2657
|
+
const s = T(o);
|
|
2658
|
+
s && !m(o) && n.add(s);
|
|
2432
2659
|
}
|
|
2433
2660
|
for (const o of e) {
|
|
2434
2661
|
const s = i.getElementById(o);
|
|
2435
2662
|
if (s) {
|
|
2436
|
-
const
|
|
2437
|
-
|
|
2663
|
+
const u = T(s);
|
|
2664
|
+
u && !m(s) && n.add(u);
|
|
2438
2665
|
}
|
|
2439
2666
|
}
|
|
2440
2667
|
for (const o of a)
|
|
2441
|
-
if (!o.some((
|
|
2668
|
+
if (!o.some((u) => n.has(u))) return !1;
|
|
2442
2669
|
return !0;
|
|
2443
2670
|
}
|
|
2444
|
-
const
|
|
2671
|
+
const Gt = {
|
|
2445
2672
|
id: "aria-required-children",
|
|
2446
2673
|
wcag: ["4.1.2"],
|
|
2447
2674
|
level: "A",
|
|
@@ -2452,24 +2679,24 @@ const Ct = {
|
|
|
2452
2679
|
var e;
|
|
2453
2680
|
const a = [];
|
|
2454
2681
|
for (const i of t.querySelectorAll("[role]")) {
|
|
2455
|
-
if (
|
|
2456
|
-
const
|
|
2457
|
-
if (!
|
|
2458
|
-
const
|
|
2459
|
-
if (!
|
|
2460
|
-
const o =
|
|
2682
|
+
if (m(i)) continue;
|
|
2683
|
+
const n = (e = i.getAttribute("role")) == null ? void 0 : e.trim().toLowerCase();
|
|
2684
|
+
if (!n || !(n in z)) continue;
|
|
2685
|
+
const r = z[n];
|
|
2686
|
+
if (!zt(i, r)) {
|
|
2687
|
+
const o = r.map((s) => s.join(" or ")).join(", ");
|
|
2461
2688
|
a.push({
|
|
2462
2689
|
ruleId: "aria-required-children",
|
|
2463
2690
|
selector: c(i),
|
|
2464
2691
|
html: l(i),
|
|
2465
2692
|
impact: "critical",
|
|
2466
|
-
message: `Role "${
|
|
2693
|
+
message: `Role "${n}" requires children with role: ${o}.`
|
|
2467
2694
|
});
|
|
2468
2695
|
}
|
|
2469
2696
|
}
|
|
2470
2697
|
return a;
|
|
2471
2698
|
}
|
|
2472
|
-
},
|
|
2699
|
+
}, Xt = {
|
|
2473
2700
|
id: "aria-required-parent",
|
|
2474
2701
|
wcag: ["4.1.2"],
|
|
2475
2702
|
level: "A",
|
|
@@ -2480,14 +2707,14 @@ const Ct = {
|
|
|
2480
2707
|
var e;
|
|
2481
2708
|
const a = [];
|
|
2482
2709
|
for (const i of t.querySelectorAll("[role]")) {
|
|
2483
|
-
if (
|
|
2484
|
-
const
|
|
2485
|
-
if (!
|
|
2486
|
-
const
|
|
2710
|
+
if (m(i)) continue;
|
|
2711
|
+
const n = (e = i.getAttribute("role")) == null ? void 0 : e.trim().toLowerCase();
|
|
2712
|
+
if (!n || !(n in G)) continue;
|
|
2713
|
+
const r = G[n];
|
|
2487
2714
|
let o = i.parentElement, s = !1;
|
|
2488
2715
|
for (; o && o !== t.documentElement; ) {
|
|
2489
|
-
const
|
|
2490
|
-
if (
|
|
2716
|
+
const u = T(o);
|
|
2717
|
+
if (u && r.includes(u)) {
|
|
2491
2718
|
s = !0;
|
|
2492
2719
|
break;
|
|
2493
2720
|
}
|
|
@@ -2498,12 +2725,12 @@ const Ct = {
|
|
|
2498
2725
|
selector: c(i),
|
|
2499
2726
|
html: l(i),
|
|
2500
2727
|
impact: "critical",
|
|
2501
|
-
message: `Role "${
|
|
2728
|
+
message: `Role "${n}" must be contained within: ${r.join(", ")}.`
|
|
2502
2729
|
});
|
|
2503
2730
|
}
|
|
2504
2731
|
return a;
|
|
2505
2732
|
}
|
|
2506
|
-
},
|
|
2733
|
+
}, Kt = [
|
|
2507
2734
|
"a[href]",
|
|
2508
2735
|
"button:not([disabled])",
|
|
2509
2736
|
'input:not([disabled]):not([type="hidden"])',
|
|
@@ -2519,37 +2746,32 @@ const Ct = {
|
|
|
2519
2746
|
"embed",
|
|
2520
2747
|
"area[href]"
|
|
2521
2748
|
].join(", ");
|
|
2522
|
-
function
|
|
2749
|
+
function Yt(t) {
|
|
2523
2750
|
let a = t;
|
|
2524
2751
|
const e = t.ownerDocument, i = e.defaultView;
|
|
2525
2752
|
for (; a && a !== e.body; ) {
|
|
2526
2753
|
if (a.style.display === "none" || a.style.visibility === "hidden") return !1;
|
|
2527
2754
|
if (i) {
|
|
2528
|
-
const
|
|
2529
|
-
if (
|
|
2755
|
+
const n = i.getComputedStyle(a);
|
|
2756
|
+
if (n.display === "none" || n.visibility === "hidden") return !1;
|
|
2530
2757
|
}
|
|
2531
2758
|
a = a.parentElement;
|
|
2532
2759
|
}
|
|
2533
2760
|
return !0;
|
|
2534
2761
|
}
|
|
2535
|
-
const
|
|
2762
|
+
const Qt = {
|
|
2536
2763
|
id: "aria-hidden-body",
|
|
2764
|
+
selector: 'body[aria-hidden="true"]',
|
|
2765
|
+
check: { type: "selector-exists" },
|
|
2766
|
+
impact: "critical",
|
|
2767
|
+
message: "aria-hidden='true' on body hides all content from assistive technologies.",
|
|
2768
|
+
description: "aria-hidden='true' must not be present on the document body.",
|
|
2537
2769
|
wcag: ["4.1.2"],
|
|
2538
2770
|
level: "A",
|
|
2539
|
-
description: "aria-hidden='true' must not be present on the document body.",
|
|
2540
2771
|
guidance: "Setting aria-hidden='true' on the body element hides all page content from assistive technologies, making the page completely inaccessible to screen reader users. Remove aria-hidden from the body element. If you need to hide content temporarily (e.g., behind a modal), use aria-hidden on specific sections instead.",
|
|
2541
2772
|
prompt: "Instruct to remove aria-hidden='true' from the body element.",
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
return (a == null ? void 0 : a.getAttribute("aria-hidden")) === "true" ? [{
|
|
2545
|
-
ruleId: "aria-hidden-body",
|
|
2546
|
-
selector: "body",
|
|
2547
|
-
html: l(a),
|
|
2548
|
-
impact: "critical",
|
|
2549
|
-
message: "aria-hidden='true' on body hides all content from assistive technologies."
|
|
2550
|
-
}] : [];
|
|
2551
|
-
}
|
|
2552
|
-
}, Nt = {
|
|
2773
|
+
skipAriaHidden: !1
|
|
2774
|
+
}, Jt = x(Qt), Zt = {
|
|
2553
2775
|
id: "aria-hidden-focus",
|
|
2554
2776
|
wcag: ["4.1.2"],
|
|
2555
2777
|
level: "A",
|
|
@@ -2560,14 +2782,14 @@ const Rt = {
|
|
|
2560
2782
|
const a = [];
|
|
2561
2783
|
for (const e of t.querySelectorAll('[aria-hidden="true"]')) {
|
|
2562
2784
|
if (e === t.body) continue;
|
|
2563
|
-
const i = e.querySelectorAll(
|
|
2564
|
-
for (const
|
|
2565
|
-
if (
|
|
2566
|
-
if (
|
|
2785
|
+
const i = e.querySelectorAll(Kt);
|
|
2786
|
+
for (const n of i)
|
|
2787
|
+
if (n instanceof HTMLElement) {
|
|
2788
|
+
if (n.getAttribute("tabindex") === "-1" || n.disabled || n instanceof HTMLInputElement && n.type === "hidden" || !Yt(n)) continue;
|
|
2567
2789
|
a.push({
|
|
2568
2790
|
ruleId: "aria-hidden-focus",
|
|
2569
|
-
selector: c(
|
|
2570
|
-
html: l(
|
|
2791
|
+
selector: c(n),
|
|
2792
|
+
html: l(n),
|
|
2571
2793
|
impact: "serious",
|
|
2572
2794
|
message: "Focusable element is inside an aria-hidden region."
|
|
2573
2795
|
});
|
|
@@ -2575,7 +2797,7 @@ const Rt = {
|
|
|
2575
2797
|
}
|
|
2576
2798
|
return a;
|
|
2577
2799
|
}
|
|
2578
|
-
},
|
|
2800
|
+
}, ea = {
|
|
2579
2801
|
id: "aria-command-name",
|
|
2580
2802
|
wcag: ["4.1.2"],
|
|
2581
2803
|
level: "A",
|
|
@@ -2586,10 +2808,10 @@ const Rt = {
|
|
|
2586
2808
|
var e;
|
|
2587
2809
|
const a = [];
|
|
2588
2810
|
for (const i of t.querySelectorAll('[role="button"], [role="link"], [role="menuitem"]')) {
|
|
2589
|
-
if (
|
|
2590
|
-
if (!
|
|
2591
|
-
const
|
|
2592
|
-
if ((e =
|
|
2811
|
+
if (m(i) || i.tagName.toLowerCase() === "button" || i.tagName.toLowerCase() === "a") continue;
|
|
2812
|
+
if (!b(i)) {
|
|
2813
|
+
const r = i.querySelector("img[alt]");
|
|
2814
|
+
if ((e = r == null ? void 0 : r.getAttribute("alt")) != null && e.trim()) continue;
|
|
2593
2815
|
a.push({
|
|
2594
2816
|
ruleId: "aria-command-name",
|
|
2595
2817
|
selector: c(i),
|
|
@@ -2601,7 +2823,7 @@ const Rt = {
|
|
|
2601
2823
|
}
|
|
2602
2824
|
return a;
|
|
2603
2825
|
}
|
|
2604
|
-
},
|
|
2826
|
+
}, ta = {
|
|
2605
2827
|
id: "aria-input-field-name",
|
|
2606
2828
|
wcag: ["4.1.2"],
|
|
2607
2829
|
level: "A",
|
|
@@ -2611,8 +2833,8 @@ const Rt = {
|
|
|
2611
2833
|
run(t) {
|
|
2612
2834
|
const a = [], e = '[role="combobox"], [role="listbox"], [role="searchbox"], [role="slider"], [role="spinbutton"], [role="textbox"]';
|
|
2613
2835
|
for (const i of t.querySelectorAll(e)) {
|
|
2614
|
-
if (
|
|
2615
|
-
|
|
2836
|
+
if (m(i) || i.matches("input, select, textarea")) continue;
|
|
2837
|
+
b(i) || a.push({
|
|
2616
2838
|
ruleId: "aria-input-field-name",
|
|
2617
2839
|
selector: c(i),
|
|
2618
2840
|
html: l(i),
|
|
@@ -2622,7 +2844,7 @@ const Rt = {
|
|
|
2622
2844
|
}
|
|
2623
2845
|
return a;
|
|
2624
2846
|
}
|
|
2625
|
-
},
|
|
2847
|
+
}, aa = {
|
|
2626
2848
|
id: "aria-toggle-field-name",
|
|
2627
2849
|
wcag: ["4.1.2"],
|
|
2628
2850
|
level: "A",
|
|
@@ -2632,8 +2854,8 @@ const Rt = {
|
|
|
2632
2854
|
run(t) {
|
|
2633
2855
|
const a = [], e = '[role="checkbox"], [role="switch"], [role="radio"], [role="menuitemcheckbox"], [role="menuitemradio"]';
|
|
2634
2856
|
for (const i of t.querySelectorAll(e)) {
|
|
2635
|
-
if (
|
|
2636
|
-
|
|
2857
|
+
if (m(i) || i.matches('input[type="checkbox"], input[type="radio"]')) continue;
|
|
2858
|
+
b(i) || a.push({
|
|
2637
2859
|
ruleId: "aria-toggle-field-name",
|
|
2638
2860
|
selector: c(i),
|
|
2639
2861
|
html: l(i),
|
|
@@ -2643,7 +2865,7 @@ const Rt = {
|
|
|
2643
2865
|
}
|
|
2644
2866
|
return a;
|
|
2645
2867
|
}
|
|
2646
|
-
},
|
|
2868
|
+
}, ia = {
|
|
2647
2869
|
id: "aria-meter-name",
|
|
2648
2870
|
wcag: ["4.1.2"],
|
|
2649
2871
|
level: "A",
|
|
@@ -2653,8 +2875,8 @@ const Rt = {
|
|
|
2653
2875
|
run(t) {
|
|
2654
2876
|
const a = [];
|
|
2655
2877
|
for (const e of t.querySelectorAll('[role="meter"], meter')) {
|
|
2656
|
-
if (
|
|
2657
|
-
|
|
2878
|
+
if (m(e)) continue;
|
|
2879
|
+
b(e) || a.push({
|
|
2658
2880
|
ruleId: "aria-meter-name",
|
|
2659
2881
|
selector: c(e),
|
|
2660
2882
|
html: l(e),
|
|
@@ -2664,7 +2886,7 @@ const Rt = {
|
|
|
2664
2886
|
}
|
|
2665
2887
|
return a;
|
|
2666
2888
|
}
|
|
2667
|
-
},
|
|
2889
|
+
}, na = {
|
|
2668
2890
|
id: "aria-progressbar-name",
|
|
2669
2891
|
wcag: ["4.1.2"],
|
|
2670
2892
|
level: "A",
|
|
@@ -2674,8 +2896,8 @@ const Rt = {
|
|
|
2674
2896
|
run(t) {
|
|
2675
2897
|
const a = [];
|
|
2676
2898
|
for (const e of t.querySelectorAll('[role="progressbar"], progress')) {
|
|
2677
|
-
if (
|
|
2678
|
-
|
|
2899
|
+
if (m(e)) continue;
|
|
2900
|
+
b(e) || a.push({
|
|
2679
2901
|
ruleId: "aria-progressbar-name",
|
|
2680
2902
|
selector: c(e),
|
|
2681
2903
|
html: l(e),
|
|
@@ -2685,7 +2907,7 @@ const Rt = {
|
|
|
2685
2907
|
}
|
|
2686
2908
|
return a;
|
|
2687
2909
|
}
|
|
2688
|
-
},
|
|
2910
|
+
}, ra = {
|
|
2689
2911
|
id: "aria-dialog-name",
|
|
2690
2912
|
wcag: ["4.1.2"],
|
|
2691
2913
|
level: "A",
|
|
@@ -2695,8 +2917,8 @@ const Rt = {
|
|
|
2695
2917
|
run(t) {
|
|
2696
2918
|
const a = [];
|
|
2697
2919
|
for (const e of t.querySelectorAll('[role="dialog"], [role="alertdialog"], dialog')) {
|
|
2698
|
-
if (
|
|
2699
|
-
|
|
2920
|
+
if (m(e)) continue;
|
|
2921
|
+
b(e) || a.push({
|
|
2700
2922
|
ruleId: "aria-dialog-name",
|
|
2701
2923
|
selector: c(e),
|
|
2702
2924
|
html: l(e),
|
|
@@ -2706,7 +2928,7 @@ const Rt = {
|
|
|
2706
2928
|
}
|
|
2707
2929
|
return a;
|
|
2708
2930
|
}
|
|
2709
|
-
},
|
|
2931
|
+
}, oa = {
|
|
2710
2932
|
id: "aria-tooltip-name",
|
|
2711
2933
|
wcag: ["4.1.2"],
|
|
2712
2934
|
level: "A",
|
|
@@ -2716,8 +2938,8 @@ const Rt = {
|
|
|
2716
2938
|
run(t) {
|
|
2717
2939
|
const a = [];
|
|
2718
2940
|
for (const e of t.querySelectorAll('[role="tooltip"]')) {
|
|
2719
|
-
if (
|
|
2720
|
-
|
|
2941
|
+
if (m(e)) continue;
|
|
2942
|
+
b(e) || a.push({
|
|
2721
2943
|
ruleId: "aria-tooltip-name",
|
|
2722
2944
|
selector: c(e),
|
|
2723
2945
|
html: l(e),
|
|
@@ -2727,7 +2949,7 @@ const Rt = {
|
|
|
2727
2949
|
}
|
|
2728
2950
|
return a;
|
|
2729
2951
|
}
|
|
2730
|
-
},
|
|
2952
|
+
}, sa = {
|
|
2731
2953
|
id: "aria-treeitem-name",
|
|
2732
2954
|
wcag: ["4.1.2"],
|
|
2733
2955
|
level: "A",
|
|
@@ -2737,8 +2959,8 @@ const Rt = {
|
|
|
2737
2959
|
run(t) {
|
|
2738
2960
|
const a = [];
|
|
2739
2961
|
for (const e of t.querySelectorAll('[role="treeitem"]')) {
|
|
2740
|
-
if (
|
|
2741
|
-
|
|
2962
|
+
if (m(e)) continue;
|
|
2963
|
+
b(e) || a.push({
|
|
2742
2964
|
ruleId: "aria-treeitem-name",
|
|
2743
2965
|
selector: c(e),
|
|
2744
2966
|
html: l(e),
|
|
@@ -2748,7 +2970,7 @@ const Rt = {
|
|
|
2748
2970
|
}
|
|
2749
2971
|
return a;
|
|
2750
2972
|
}
|
|
2751
|
-
},
|
|
2973
|
+
}, la = {
|
|
2752
2974
|
id: "aria-prohibited-attr",
|
|
2753
2975
|
wcag: ["4.1.2"],
|
|
2754
2976
|
level: "A",
|
|
@@ -2756,16 +2978,16 @@ const Rt = {
|
|
|
2756
2978
|
guidance: "Some ARIA roles prohibit certain attributes. For example, roles like 'none', 'presentation', 'generic', and text-level roles (code, emphasis, strong) prohibit aria-label and aria-labelledby because naming is not supported for these roles. Remove the prohibited attributes or change the role.",
|
|
2757
2979
|
prompt: "Identify the prohibited attribute and recommend removing it from this element.",
|
|
2758
2980
|
run(t) {
|
|
2759
|
-
return
|
|
2981
|
+
return O(t).prohibitedAttr;
|
|
2760
2982
|
}
|
|
2761
|
-
},
|
|
2983
|
+
}, ca = [
|
|
2762
2984
|
"a[href]",
|
|
2763
2985
|
"button:not([disabled])",
|
|
2764
2986
|
'input:not([disabled]):not([type="hidden"])',
|
|
2765
2987
|
"select:not([disabled])",
|
|
2766
2988
|
"textarea:not([disabled])",
|
|
2767
2989
|
'[tabindex]:not([tabindex="-1"])'
|
|
2768
|
-
].join(", "),
|
|
2990
|
+
].join(", "), da = [
|
|
2769
2991
|
"aria-atomic",
|
|
2770
2992
|
"aria-busy",
|
|
2771
2993
|
"aria-controls",
|
|
@@ -2779,7 +3001,7 @@ const Rt = {
|
|
|
2779
3001
|
"aria-live",
|
|
2780
3002
|
"aria-owns",
|
|
2781
3003
|
"aria-relevant"
|
|
2782
|
-
],
|
|
3004
|
+
], ua = {
|
|
2783
3005
|
id: "presentation-role-conflict",
|
|
2784
3006
|
wcag: ["4.1.2"],
|
|
2785
3007
|
level: "A",
|
|
@@ -2789,12 +3011,12 @@ const Rt = {
|
|
|
2789
3011
|
run(t) {
|
|
2790
3012
|
const a = [];
|
|
2791
3013
|
for (const e of t.querySelectorAll('[role="presentation"], [role="none"]')) {
|
|
2792
|
-
if (
|
|
3014
|
+
if (m(e)) continue;
|
|
2793
3015
|
const i = [];
|
|
2794
|
-
e.matches(
|
|
2795
|
-
for (const
|
|
2796
|
-
if (e.hasAttribute(
|
|
2797
|
-
i.push(`has ${
|
|
3016
|
+
e.matches(ca) && i.push("element is focusable");
|
|
3017
|
+
for (const n of da)
|
|
3018
|
+
if (e.hasAttribute(n)) {
|
|
3019
|
+
i.push(`has ${n}`);
|
|
2798
3020
|
break;
|
|
2799
3021
|
}
|
|
2800
3022
|
(e.hasAttribute("aria-label") || e.hasAttribute("aria-labelledby")) && i.push("has accessible name"), i.length > 0 && a.push({
|
|
@@ -2807,7 +3029,7 @@ const Rt = {
|
|
|
2807
3029
|
}
|
|
2808
3030
|
return a;
|
|
2809
3031
|
}
|
|
2810
|
-
},
|
|
3032
|
+
}, ma = {
|
|
2811
3033
|
id: "summary-name",
|
|
2812
3034
|
wcag: ["4.1.2"],
|
|
2813
3035
|
level: "A",
|
|
@@ -2817,8 +3039,8 @@ const Rt = {
|
|
|
2817
3039
|
run(t) {
|
|
2818
3040
|
const a = [];
|
|
2819
3041
|
for (const e of t.querySelectorAll("summary")) {
|
|
2820
|
-
if (
|
|
2821
|
-
|
|
3042
|
+
if (m(e)) continue;
|
|
3043
|
+
b(e) || a.push({
|
|
2822
3044
|
ruleId: "summary-name",
|
|
2823
3045
|
selector: c(e),
|
|
2824
3046
|
html: l(e),
|
|
@@ -2829,24 +3051,24 @@ const Rt = {
|
|
|
2829
3051
|
return a;
|
|
2830
3052
|
}
|
|
2831
3053
|
};
|
|
2832
|
-
function
|
|
2833
|
-
var
|
|
3054
|
+
function pa(t) {
|
|
3055
|
+
var n, r;
|
|
2834
3056
|
const a = [], e = t.getAttribute("href");
|
|
2835
3057
|
e && a.push(`href: ${e}`);
|
|
2836
3058
|
const i = t.parentElement;
|
|
2837
3059
|
if (i) {
|
|
2838
3060
|
const o = i.closest("h1, h2, h3, h4, h5, h6");
|
|
2839
|
-
if ((
|
|
3061
|
+
if ((n = o == null ? void 0 : o.textContent) != null && n.trim())
|
|
2840
3062
|
a.push(`Nearby heading: ${o.textContent.trim().slice(0, 80)}`);
|
|
2841
3063
|
else {
|
|
2842
|
-
const s = (
|
|
3064
|
+
const s = (r = i.textContent) == null ? void 0 : r.trim().slice(0, 100);
|
|
2843
3065
|
s && a.push(`Parent text: ${s}`);
|
|
2844
3066
|
}
|
|
2845
3067
|
}
|
|
2846
3068
|
return a.length > 0 ? a.join(`
|
|
2847
3069
|
`) : void 0;
|
|
2848
3070
|
}
|
|
2849
|
-
const
|
|
3071
|
+
const ha = {
|
|
2850
3072
|
id: "link-name",
|
|
2851
3073
|
wcag: ["2.4.4", "4.1.2"],
|
|
2852
3074
|
level: "A",
|
|
@@ -2856,19 +3078,19 @@ const Gt = {
|
|
|
2856
3078
|
run(t) {
|
|
2857
3079
|
const a = [];
|
|
2858
3080
|
for (const e of t.querySelectorAll('a[href], [role="link"]')) {
|
|
2859
|
-
if (
|
|
2860
|
-
|
|
3081
|
+
if (m(e)) continue;
|
|
3082
|
+
b(e) || a.push({
|
|
2861
3083
|
ruleId: "link-name",
|
|
2862
3084
|
selector: c(e),
|
|
2863
3085
|
html: l(e),
|
|
2864
3086
|
impact: "serious",
|
|
2865
3087
|
message: "Link has no discernible text.",
|
|
2866
|
-
context:
|
|
3088
|
+
context: pa(e)
|
|
2867
3089
|
});
|
|
2868
3090
|
}
|
|
2869
3091
|
return a;
|
|
2870
3092
|
}
|
|
2871
|
-
},
|
|
3093
|
+
}, ga = {
|
|
2872
3094
|
id: "skip-link",
|
|
2873
3095
|
wcag: ["2.4.1"],
|
|
2874
3096
|
level: "A",
|
|
@@ -2879,11 +3101,11 @@ const Gt = {
|
|
|
2879
3101
|
run(t) {
|
|
2880
3102
|
const a = [], e = t.querySelectorAll('a[href^="#"]');
|
|
2881
3103
|
for (const i of e) {
|
|
2882
|
-
const
|
|
2883
|
-
if (!
|
|
2884
|
-
const
|
|
2885
|
-
if (!(
|
|
2886
|
-
const s =
|
|
3104
|
+
const n = i.getAttribute("href");
|
|
3105
|
+
if (!n || n === "#") continue;
|
|
3106
|
+
const r = w(i).toLowerCase();
|
|
3107
|
+
if (!(r.includes("skip") || r.includes("jump") || r.includes("main content") || r.includes("navigation"))) continue;
|
|
3108
|
+
const s = n.slice(1);
|
|
2887
3109
|
t.getElementById(s) || a.push({
|
|
2888
3110
|
ruleId: "skip-link",
|
|
2889
3111
|
selector: c(i),
|
|
@@ -2894,7 +3116,7 @@ const Gt = {
|
|
|
2894
3116
|
}
|
|
2895
3117
|
return a;
|
|
2896
3118
|
}
|
|
2897
|
-
},
|
|
3119
|
+
}, ba = {
|
|
2898
3120
|
id: "link-in-text-block",
|
|
2899
3121
|
wcag: ["1.4.1"],
|
|
2900
3122
|
level: "A",
|
|
@@ -2904,11 +3126,11 @@ const Gt = {
|
|
|
2904
3126
|
run(t) {
|
|
2905
3127
|
const a = [];
|
|
2906
3128
|
for (const e of t.querySelectorAll("a[href]")) {
|
|
2907
|
-
if (
|
|
3129
|
+
if (m(e)) continue;
|
|
2908
3130
|
const i = e.parentElement;
|
|
2909
3131
|
if (!i) continue;
|
|
2910
|
-
const
|
|
2911
|
-
if (
|
|
3132
|
+
const n = i.textContent || "", r = e.textContent || "";
|
|
3133
|
+
if (n.length > r.length + 20) {
|
|
2912
3134
|
const o = e.getAttribute("style") || "";
|
|
2913
3135
|
o.includes("text-decoration") && o.includes("none") && a.push({
|
|
2914
3136
|
ruleId: "link-in-text-block",
|
|
@@ -2921,7 +3143,7 @@ const Gt = {
|
|
|
2921
3143
|
}
|
|
2922
3144
|
return a;
|
|
2923
3145
|
}
|
|
2924
|
-
},
|
|
3146
|
+
}, fa = {
|
|
2925
3147
|
id: "html-has-lang",
|
|
2926
3148
|
wcag: ["3.1.1"],
|
|
2927
3149
|
level: "A",
|
|
@@ -2939,7 +3161,7 @@ const Gt = {
|
|
|
2939
3161
|
message: "<html> element missing lang attribute."
|
|
2940
3162
|
}];
|
|
2941
3163
|
}
|
|
2942
|
-
},
|
|
3164
|
+
}, te = /^[a-z]{2,3}(-[a-z0-9]{2,8})*$/i, va = {
|
|
2943
3165
|
id: "html-lang-valid",
|
|
2944
3166
|
wcag: ["3.1.1"],
|
|
2945
3167
|
level: "A",
|
|
@@ -2949,7 +3171,7 @@ const Gt = {
|
|
|
2949
3171
|
run(t) {
|
|
2950
3172
|
var e;
|
|
2951
3173
|
const a = (e = t.documentElement.getAttribute("lang")) == null ? void 0 : e.trim();
|
|
2952
|
-
return a && !
|
|
3174
|
+
return a && !te.test(a) ? [{
|
|
2953
3175
|
ruleId: "html-lang-valid",
|
|
2954
3176
|
selector: "html",
|
|
2955
3177
|
html: l(t.documentElement),
|
|
@@ -2957,7 +3179,7 @@ const Gt = {
|
|
|
2957
3179
|
message: `Invalid lang attribute value "${a}".`
|
|
2958
3180
|
}] : [];
|
|
2959
3181
|
}
|
|
2960
|
-
},
|
|
3182
|
+
}, ya = {
|
|
2961
3183
|
id: "valid-lang",
|
|
2962
3184
|
wcag: ["3.1.2"],
|
|
2963
3185
|
level: "AA",
|
|
@@ -2968,19 +3190,19 @@ const Gt = {
|
|
|
2968
3190
|
var e;
|
|
2969
3191
|
const a = [];
|
|
2970
3192
|
for (const i of t.querySelectorAll("[lang]")) {
|
|
2971
|
-
if (
|
|
2972
|
-
const
|
|
2973
|
-
|
|
3193
|
+
if (m(i) || i === t.documentElement) continue;
|
|
3194
|
+
const n = (e = i.getAttribute("lang")) == null ? void 0 : e.trim();
|
|
3195
|
+
n && !te.test(n) && a.push({
|
|
2974
3196
|
ruleId: "valid-lang",
|
|
2975
3197
|
selector: c(i),
|
|
2976
3198
|
html: l(i),
|
|
2977
3199
|
impact: "serious",
|
|
2978
|
-
message: `Invalid lang attribute value "${
|
|
3200
|
+
message: `Invalid lang attribute value "${n}".`
|
|
2979
3201
|
});
|
|
2980
3202
|
}
|
|
2981
3203
|
return a;
|
|
2982
3204
|
}
|
|
2983
|
-
},
|
|
3205
|
+
}, wa = {
|
|
2984
3206
|
id: "html-xml-lang-mismatch",
|
|
2985
3207
|
wcag: ["3.1.1"],
|
|
2986
3208
|
level: "A",
|
|
@@ -2988,8 +3210,8 @@ const Gt = {
|
|
|
2988
3210
|
guidance: "In XHTML documents, if both lang and xml:lang are present, they must specify the same base language. Mismatched values confuse assistive technologies. Either remove xml:lang (preferred for HTML5) or ensure both attributes have identical values.",
|
|
2989
3211
|
prompt: "Explain whether to remove xml:lang or align it with the lang value.",
|
|
2990
3212
|
run(t) {
|
|
2991
|
-
var
|
|
2992
|
-
const a = t.documentElement, e = (
|
|
3213
|
+
var n, r;
|
|
3214
|
+
const a = t.documentElement, e = (n = a.getAttribute("lang")) == null ? void 0 : n.trim().toLowerCase(), i = (r = a.getAttribute("xml:lang")) == null ? void 0 : r.trim().toLowerCase();
|
|
2993
3215
|
if (e && i) {
|
|
2994
3216
|
const o = e.split("-")[0], s = i.split("-")[0];
|
|
2995
3217
|
if (o !== s)
|
|
@@ -3003,7 +3225,7 @@ const Gt = {
|
|
|
3003
3225
|
}
|
|
3004
3226
|
return [];
|
|
3005
3227
|
}
|
|
3006
|
-
},
|
|
3228
|
+
}, Aa = {
|
|
3007
3229
|
id: "td-headers-attr",
|
|
3008
3230
|
wcag: ["1.3.1"],
|
|
3009
3231
|
level: "A",
|
|
@@ -3013,25 +3235,25 @@ const Gt = {
|
|
|
3013
3235
|
run(t) {
|
|
3014
3236
|
const a = [];
|
|
3015
3237
|
for (const e of t.querySelectorAll("td[headers]")) {
|
|
3016
|
-
if (
|
|
3238
|
+
if (m(e)) continue;
|
|
3017
3239
|
const i = e.closest("table");
|
|
3018
3240
|
if (!i) continue;
|
|
3019
|
-
const
|
|
3020
|
-
for (const
|
|
3021
|
-
if (!i.querySelector(`th#${CSS.escape(
|
|
3241
|
+
const n = e.getAttribute("headers").split(/\s+/);
|
|
3242
|
+
for (const r of n)
|
|
3243
|
+
if (!i.querySelector(`th#${CSS.escape(r)}, td#${CSS.escape(r)}`)) {
|
|
3022
3244
|
a.push({
|
|
3023
3245
|
ruleId: "td-headers-attr",
|
|
3024
3246
|
selector: c(e),
|
|
3025
3247
|
html: l(e),
|
|
3026
3248
|
impact: "serious",
|
|
3027
|
-
message: `Headers attribute references non-existent ID "${
|
|
3249
|
+
message: `Headers attribute references non-existent ID "${r}".`
|
|
3028
3250
|
});
|
|
3029
3251
|
break;
|
|
3030
3252
|
}
|
|
3031
3253
|
}
|
|
3032
3254
|
return a;
|
|
3033
3255
|
}
|
|
3034
|
-
},
|
|
3256
|
+
}, Sa = {
|
|
3035
3257
|
id: "th-has-data-cells",
|
|
3036
3258
|
wcag: ["1.3.1"],
|
|
3037
3259
|
level: "A",
|
|
@@ -3041,9 +3263,9 @@ const Gt = {
|
|
|
3041
3263
|
run(t) {
|
|
3042
3264
|
const a = [];
|
|
3043
3265
|
for (const e of t.querySelectorAll("table")) {
|
|
3044
|
-
if (
|
|
3045
|
-
const i = e.querySelectorAll("th"),
|
|
3046
|
-
i.length > 0 &&
|
|
3266
|
+
if (m(e) || e.getAttribute("role") === "presentation" || e.getAttribute("role") === "none") continue;
|
|
3267
|
+
const i = e.querySelectorAll("th"), n = e.querySelectorAll("td");
|
|
3268
|
+
i.length > 0 && n.length === 0 && a.push({
|
|
3047
3269
|
ruleId: "th-has-data-cells",
|
|
3048
3270
|
selector: c(e),
|
|
3049
3271
|
html: l(e),
|
|
@@ -3053,7 +3275,7 @@ const Gt = {
|
|
|
3053
3275
|
}
|
|
3054
3276
|
return a;
|
|
3055
3277
|
}
|
|
3056
|
-
},
|
|
3278
|
+
}, xa = {
|
|
3057
3279
|
id: "td-has-header",
|
|
3058
3280
|
wcag: ["1.3.1"],
|
|
3059
3281
|
level: "A",
|
|
@@ -3063,34 +3285,34 @@ const Gt = {
|
|
|
3063
3285
|
run(t) {
|
|
3064
3286
|
var e, i;
|
|
3065
3287
|
const a = [];
|
|
3066
|
-
for (const
|
|
3067
|
-
if (
|
|
3068
|
-
const
|
|
3288
|
+
for (const n of t.querySelectorAll("table")) {
|
|
3289
|
+
if (m(n) || n.getAttribute("role") === "presentation" || n.getAttribute("role") === "none") continue;
|
|
3290
|
+
const r = n.querySelectorAll("tr"), o = r.length;
|
|
3069
3291
|
let s = 0;
|
|
3070
|
-
for (const p of
|
|
3071
|
-
const
|
|
3292
|
+
for (const p of r) {
|
|
3293
|
+
const g = p.querySelectorAll("td, th");
|
|
3072
3294
|
let f = 0;
|
|
3073
|
-
for (const v of
|
|
3295
|
+
for (const v of g)
|
|
3074
3296
|
f += parseInt(v.getAttribute("colspan") || "1", 10);
|
|
3075
3297
|
s = Math.max(s, f);
|
|
3076
3298
|
}
|
|
3077
3299
|
if (o <= 3 && s <= 3) continue;
|
|
3078
|
-
const
|
|
3079
|
-
if (
|
|
3080
|
-
for (const p of
|
|
3081
|
-
if (
|
|
3082
|
-
const
|
|
3083
|
-
if (!
|
|
3084
|
-
const f =
|
|
3300
|
+
const u = n.querySelector("th") !== null, h = n.querySelector("th[scope]") !== null, d = n.querySelector("td[headers]") !== null;
|
|
3301
|
+
if (u)
|
|
3302
|
+
for (const p of n.querySelectorAll("td")) {
|
|
3303
|
+
if (m(p) || p.hasAttribute("headers")) continue;
|
|
3304
|
+
const g = p.closest("tr");
|
|
3305
|
+
if (!g) continue;
|
|
3306
|
+
const f = g.querySelector("th") !== null, v = Array.from(g.children).indexOf(p);
|
|
3085
3307
|
let y = !1;
|
|
3086
|
-
const
|
|
3087
|
-
if (
|
|
3088
|
-
const
|
|
3089
|
-
|
|
3308
|
+
const C = n.querySelector("thead");
|
|
3309
|
+
if (C) {
|
|
3310
|
+
const A = C.querySelector("tr");
|
|
3311
|
+
A && ((e = A.querySelectorAll("th, td")[v]) == null ? void 0 : e.tagName.toLowerCase()) === "th" && (y = !0);
|
|
3090
3312
|
}
|
|
3091
3313
|
if (!y) {
|
|
3092
|
-
const
|
|
3093
|
-
|
|
3314
|
+
const A = n.querySelector("tbody > tr, tr");
|
|
3315
|
+
A && ((i = A.querySelectorAll("th, td")[v]) == null ? void 0 : i.tagName.toLowerCase()) === "th" && (y = !0);
|
|
3094
3316
|
}
|
|
3095
3317
|
if (!f && !y && !h && !d) {
|
|
3096
3318
|
a.push({
|
|
@@ -3106,7 +3328,7 @@ const Gt = {
|
|
|
3106
3328
|
}
|
|
3107
3329
|
return a;
|
|
3108
3330
|
}
|
|
3109
|
-
},
|
|
3331
|
+
}, ka = {
|
|
3110
3332
|
id: "scope-attr-valid",
|
|
3111
3333
|
wcag: ["1.3.1"],
|
|
3112
3334
|
level: "A",
|
|
@@ -3116,20 +3338,20 @@ const Gt = {
|
|
|
3116
3338
|
run(t) {
|
|
3117
3339
|
var i;
|
|
3118
3340
|
const a = [], e = /* @__PURE__ */ new Set(["row", "col", "rowgroup", "colgroup"]);
|
|
3119
|
-
for (const
|
|
3120
|
-
if (
|
|
3121
|
-
const
|
|
3122
|
-
|
|
3341
|
+
for (const n of t.querySelectorAll("th[scope]")) {
|
|
3342
|
+
if (m(n)) continue;
|
|
3343
|
+
const r = (i = n.getAttribute("scope")) == null ? void 0 : i.toLowerCase();
|
|
3344
|
+
r && !e.has(r) && a.push({
|
|
3123
3345
|
ruleId: "scope-attr-valid",
|
|
3124
|
-
selector: c(
|
|
3125
|
-
html: l(
|
|
3346
|
+
selector: c(n),
|
|
3347
|
+
html: l(n),
|
|
3126
3348
|
impact: "moderate",
|
|
3127
|
-
message: `Invalid scope value "${
|
|
3349
|
+
message: `Invalid scope value "${r}". Use row, col, rowgroup, or colgroup.`
|
|
3128
3350
|
});
|
|
3129
3351
|
}
|
|
3130
3352
|
return a;
|
|
3131
3353
|
}
|
|
3132
|
-
},
|
|
3354
|
+
}, Ia = {
|
|
3133
3355
|
id: "empty-table-header",
|
|
3134
3356
|
wcag: [],
|
|
3135
3357
|
level: "A",
|
|
@@ -3140,9 +3362,9 @@ const Gt = {
|
|
|
3140
3362
|
run(t) {
|
|
3141
3363
|
const a = [];
|
|
3142
3364
|
for (const e of t.querySelectorAll("th")) {
|
|
3143
|
-
if (
|
|
3365
|
+
if (m(e)) continue;
|
|
3144
3366
|
const i = e.closest("table");
|
|
3145
|
-
(i == null ? void 0 : i.getAttribute("role")) === "presentation" || (i == null ? void 0 : i.getAttribute("role")) === "none" ||
|
|
3367
|
+
(i == null ? void 0 : i.getAttribute("role")) === "presentation" || (i == null ? void 0 : i.getAttribute("role")) === "none" || b(e) || a.push({
|
|
3146
3368
|
ruleId: "empty-table-header",
|
|
3147
3369
|
selector: c(e),
|
|
3148
3370
|
html: l(e),
|
|
@@ -3152,7 +3374,7 @@ const Gt = {
|
|
|
3152
3374
|
}
|
|
3153
3375
|
return a;
|
|
3154
3376
|
}
|
|
3155
|
-
},
|
|
3377
|
+
}, N = ["aria-labelledby", "aria-describedby", "aria-controls", "aria-owns", "aria-flowto"], qa = {
|
|
3156
3378
|
id: "duplicate-id-aria",
|
|
3157
3379
|
wcag: ["4.1.2"],
|
|
3158
3380
|
level: "A",
|
|
@@ -3161,46 +3383,46 @@ const Gt = {
|
|
|
3161
3383
|
prompt: "Identify which attribute references this ID and suggest a unique replacement.",
|
|
3162
3384
|
run(t) {
|
|
3163
3385
|
const a = [], e = /* @__PURE__ */ new Set();
|
|
3164
|
-
for (const
|
|
3165
|
-
for (const
|
|
3166
|
-
const o =
|
|
3386
|
+
for (const n of t.querySelectorAll("[aria-labelledby], [aria-describedby], [aria-controls], [aria-owns], [aria-flowto]"))
|
|
3387
|
+
for (const r of N) {
|
|
3388
|
+
const o = n.getAttribute(r);
|
|
3167
3389
|
o && o.split(/\s+/).forEach((s) => e.add(s));
|
|
3168
3390
|
}
|
|
3169
|
-
for (const
|
|
3170
|
-
const
|
|
3171
|
-
|
|
3391
|
+
for (const n of t.querySelectorAll("label[for]")) {
|
|
3392
|
+
const r = n.getAttribute("for");
|
|
3393
|
+
r && e.add(r);
|
|
3172
3394
|
}
|
|
3173
3395
|
const i = /* @__PURE__ */ new Map();
|
|
3174
|
-
for (const
|
|
3175
|
-
e.has(
|
|
3176
|
-
for (const [
|
|
3177
|
-
if (
|
|
3178
|
-
const o = t.querySelectorAll(`#${CSS.escape(
|
|
3179
|
-
|
|
3180
|
-
),
|
|
3396
|
+
for (const n of t.querySelectorAll("[id]"))
|
|
3397
|
+
e.has(n.id) && (n instanceof HTMLElement && (n.style.display === "none" || n.style.visibility === "hidden" || n.hidden) || i.set(n.id, (i.get(n.id) ?? 0) + 1));
|
|
3398
|
+
for (const [n, r] of i) {
|
|
3399
|
+
if (r <= 1) continue;
|
|
3400
|
+
const o = t.querySelectorAll(`#${CSS.escape(n)}`), s = t.querySelector(
|
|
3401
|
+
N.map((d) => `[${d}~="${CSS.escape(n)}"]`).join(", ")
|
|
3402
|
+
), u = t.querySelector(`label[for="${CSS.escape(n)}"]`);
|
|
3181
3403
|
let h;
|
|
3182
3404
|
if (s) {
|
|
3183
|
-
const d =
|
|
3405
|
+
const d = N.find(
|
|
3184
3406
|
(p) => {
|
|
3185
|
-
var
|
|
3186
|
-
return (
|
|
3407
|
+
var g;
|
|
3408
|
+
return (g = s.getAttribute(p)) == null ? void 0 : g.split(/\s+/).includes(n);
|
|
3187
3409
|
}
|
|
3188
3410
|
);
|
|
3189
3411
|
d && (h = d);
|
|
3190
|
-
} else
|
|
3412
|
+
} else u && (h = "label[for]");
|
|
3191
3413
|
a.push({
|
|
3192
3414
|
ruleId: "duplicate-id-aria",
|
|
3193
3415
|
selector: c(o[1]),
|
|
3194
3416
|
html: l(o[1]),
|
|
3195
3417
|
impact: "critical",
|
|
3196
|
-
message: `Duplicate ID "${
|
|
3418
|
+
message: `Duplicate ID "${n}" referenced by ${h ?? "an accessibility attribute"}.`,
|
|
3197
3419
|
context: `First element: ${l(o[0])}${h ? `
|
|
3198
3420
|
Referenced by: ${h}` : ""}`
|
|
3199
3421
|
});
|
|
3200
3422
|
}
|
|
3201
3423
|
return a;
|
|
3202
3424
|
}
|
|
3203
|
-
},
|
|
3425
|
+
}, Ca = {
|
|
3204
3426
|
id: "video-caption",
|
|
3205
3427
|
wcag: ["1.2.2"],
|
|
3206
3428
|
level: "A",
|
|
@@ -3210,7 +3432,7 @@ Referenced by: ${h}` : ""}`
|
|
|
3210
3432
|
run(t) {
|
|
3211
3433
|
const a = [];
|
|
3212
3434
|
for (const e of t.querySelectorAll("video")) {
|
|
3213
|
-
if (
|
|
3435
|
+
if (m(e) || e.hasAttribute("muted") || e.hasAttribute("autoplay")) continue;
|
|
3214
3436
|
e.querySelector('track[kind="captions"], track[kind="subtitles"]') || a.push({
|
|
3215
3437
|
ruleId: "video-caption",
|
|
3216
3438
|
selector: c(e),
|
|
@@ -3221,7 +3443,7 @@ Referenced by: ${h}` : ""}`
|
|
|
3221
3443
|
}
|
|
3222
3444
|
return a;
|
|
3223
3445
|
}
|
|
3224
|
-
},
|
|
3446
|
+
}, Ta = {
|
|
3225
3447
|
id: "audio-caption",
|
|
3226
3448
|
wcag: ["1.2.1"],
|
|
3227
3449
|
level: "A",
|
|
@@ -3231,9 +3453,9 @@ Referenced by: ${h}` : ""}`
|
|
|
3231
3453
|
run(t) {
|
|
3232
3454
|
const a = [];
|
|
3233
3455
|
for (const e of t.querySelectorAll("audio")) {
|
|
3234
|
-
if (
|
|
3235
|
-
const
|
|
3236
|
-
|
|
3456
|
+
if (m(e) || e.querySelector('track[kind="captions"], track[kind="descriptions"]') || e.hasAttribute("aria-describedby")) continue;
|
|
3457
|
+
const n = e.parentElement;
|
|
3458
|
+
n && n.querySelector('a[href*="transcript"], a[href*="text"]') || a.push({
|
|
3237
3459
|
ruleId: "audio-caption",
|
|
3238
3460
|
selector: c(e),
|
|
3239
3461
|
html: l(e),
|
|
@@ -3243,122 +3465,195 @@ Referenced by: ${h}` : ""}`
|
|
|
3243
3465
|
}
|
|
3244
3466
|
return a;
|
|
3245
3467
|
}
|
|
3246
|
-
},
|
|
3468
|
+
}, Ea = /* @__PURE__ */ new Set([
|
|
3469
|
+
"SCRIPT",
|
|
3470
|
+
"STYLE",
|
|
3471
|
+
"NOSCRIPT",
|
|
3472
|
+
"TEMPLATE",
|
|
3473
|
+
"IFRAME",
|
|
3474
|
+
"OBJECT",
|
|
3475
|
+
"EMBED",
|
|
3476
|
+
"SVG",
|
|
3477
|
+
"CANVAS",
|
|
3478
|
+
"VIDEO",
|
|
3479
|
+
"AUDIO",
|
|
3480
|
+
"IMG",
|
|
3481
|
+
"BR",
|
|
3482
|
+
"HR"
|
|
3483
|
+
]);
|
|
3484
|
+
function X([t, a, e]) {
|
|
3485
|
+
return "#" + [t, a, e].map((i) => i.toString(16).padStart(2, "0")).join("");
|
|
3486
|
+
}
|
|
3487
|
+
function La(t) {
|
|
3488
|
+
return t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement || t instanceof HTMLSelectElement || t instanceof HTMLButtonElement ? t.disabled : !!t.closest("fieldset[disabled]");
|
|
3489
|
+
}
|
|
3490
|
+
function Ra(t) {
|
|
3491
|
+
let a = t;
|
|
3492
|
+
for (; a; ) {
|
|
3493
|
+
if (a.getAttribute("aria-hidden") === "true") return !0;
|
|
3494
|
+
const e = E(a);
|
|
3495
|
+
if (e.display === "none" || e.visibility === "hidden") return !0;
|
|
3496
|
+
a = a.parentElement;
|
|
3497
|
+
}
|
|
3498
|
+
return !1;
|
|
3499
|
+
}
|
|
3500
|
+
const Na = {
|
|
3501
|
+
id: "color-contrast",
|
|
3502
|
+
wcag: ["1.4.3"],
|
|
3503
|
+
level: "AA",
|
|
3504
|
+
description: "Text elements must have sufficient color contrast against the background.",
|
|
3505
|
+
guidance: "WCAG SC 1.4.3 requires a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text (>=24px or >=18.66px bold). Increase the contrast by darkening the text or lightening the background, or vice versa.",
|
|
3506
|
+
prompt: "Suggest changing the text or background color to meet the minimum contrast ratio.",
|
|
3507
|
+
run(t) {
|
|
3508
|
+
const a = [], e = t.body;
|
|
3509
|
+
if (!e) return [];
|
|
3510
|
+
const i = t.createTreeWalker(e, NodeFilter.SHOW_TEXT), n = /* @__PURE__ */ new Set();
|
|
3511
|
+
let r;
|
|
3512
|
+
for (; r = i.nextNode(); ) {
|
|
3513
|
+
if (!r.textContent || !r.textContent.trim()) continue;
|
|
3514
|
+
const o = r.parentElement;
|
|
3515
|
+
if (!o || n.has(o) || (n.add(o), Ea.has(o.tagName)) || La(o) || Ra(o)) continue;
|
|
3516
|
+
const s = E(o);
|
|
3517
|
+
if (parseFloat(s.opacity) === 0) continue;
|
|
3518
|
+
const u = ee(s.color);
|
|
3519
|
+
if (!u) continue;
|
|
3520
|
+
const h = s.color.match(/rgba\(.+?,\s*([\d.]+)\s*\)/);
|
|
3521
|
+
if (h && parseFloat(h[1]) === 0) continue;
|
|
3522
|
+
const d = we(o);
|
|
3523
|
+
if (!d) continue;
|
|
3524
|
+
const p = P(u[0], u[1], u[2]), g = P(d[0], d[1], d[2]), f = ye(p, g), v = Se(o) ? 3 : 4.5;
|
|
3525
|
+
if (f < v) {
|
|
3526
|
+
const y = Math.round(f * 100) / 100, C = X(u), A = X(d);
|
|
3527
|
+
a.push({
|
|
3528
|
+
ruleId: "color-contrast",
|
|
3529
|
+
selector: c(o),
|
|
3530
|
+
html: l(o),
|
|
3531
|
+
impact: "serious",
|
|
3532
|
+
message: `Insufficient color contrast ratio of ${y}:1 (required ${v}:1).`,
|
|
3533
|
+
context: `foreground: ${C} rgb(${u.join(", ")}), background: ${A} rgb(${d.join(", ")}), ratio: ${y}:1, required: ${v}:1`
|
|
3534
|
+
});
|
|
3535
|
+
}
|
|
3536
|
+
}
|
|
3537
|
+
return a;
|
|
3538
|
+
}
|
|
3539
|
+
}, ae = [
|
|
3247
3540
|
// Document Structure
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3541
|
+
wt,
|
|
3542
|
+
At,
|
|
3543
|
+
St,
|
|
3544
|
+
xt,
|
|
3545
|
+
kt,
|
|
3546
|
+
qt,
|
|
3547
|
+
Ct,
|
|
3548
|
+
Et,
|
|
3549
|
+
Rt,
|
|
3257
3550
|
// Images
|
|
3258
|
-
me,
|
|
3259
|
-
pe,
|
|
3260
|
-
he,
|
|
3261
|
-
ge,
|
|
3262
|
-
fe,
|
|
3263
|
-
ve,
|
|
3264
|
-
ye,
|
|
3265
|
-
we,
|
|
3266
|
-
Ae,
|
|
3267
|
-
// Forms
|
|
3268
|
-
Se,
|
|
3269
|
-
xe,
|
|
3270
3551
|
ke,
|
|
3271
3552
|
Ie,
|
|
3553
|
+
qe,
|
|
3272
3554
|
Ce,
|
|
3273
|
-
Te,
|
|
3274
|
-
Le,
|
|
3275
|
-
// Keyboard
|
|
3276
3555
|
Ee,
|
|
3556
|
+
Le,
|
|
3557
|
+
Re,
|
|
3277
3558
|
Ne,
|
|
3559
|
+
De,
|
|
3560
|
+
// Forms
|
|
3561
|
+
Be,
|
|
3562
|
+
Oe,
|
|
3278
3563
|
We,
|
|
3279
3564
|
Fe,
|
|
3280
3565
|
Pe,
|
|
3281
|
-
// Structure
|
|
3282
|
-
_e,
|
|
3283
|
-
st,
|
|
3284
|
-
mt,
|
|
3285
3566
|
Ve,
|
|
3286
3567
|
Ue,
|
|
3287
|
-
|
|
3568
|
+
// Keyboard
|
|
3288
3569
|
ze,
|
|
3289
|
-
Ge,
|
|
3290
|
-
Ke,
|
|
3291
3570
|
Xe,
|
|
3292
|
-
Qe,
|
|
3293
|
-
Ye,
|
|
3294
|
-
Je,
|
|
3295
|
-
Ze,
|
|
3296
|
-
et,
|
|
3297
3571
|
tt,
|
|
3298
|
-
|
|
3572
|
+
at,
|
|
3573
|
+
it,
|
|
3574
|
+
// Structure
|
|
3575
|
+
nt,
|
|
3576
|
+
It,
|
|
3577
|
+
Nt,
|
|
3578
|
+
rt,
|
|
3579
|
+
ot,
|
|
3580
|
+
st,
|
|
3581
|
+
lt,
|
|
3582
|
+
ct,
|
|
3583
|
+
dt,
|
|
3584
|
+
ut,
|
|
3585
|
+
mt,
|
|
3299
3586
|
pt,
|
|
3300
3587
|
ht,
|
|
3301
|
-
|
|
3588
|
+
bt,
|
|
3302
3589
|
ft,
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
Ct,
|
|
3306
|
-
Tt,
|
|
3307
|
-
Rt,
|
|
3308
|
-
Nt,
|
|
3590
|
+
yt,
|
|
3591
|
+
// ARIA
|
|
3309
3592
|
$t,
|
|
3310
3593
|
Mt,
|
|
3311
3594
|
Ht,
|
|
3312
|
-
Dt,
|
|
3313
3595
|
Bt,
|
|
3314
|
-
Ot,
|
|
3315
|
-
Wt,
|
|
3316
|
-
Ft,
|
|
3317
3596
|
Pt,
|
|
3318
|
-
Ut,
|
|
3319
|
-
yt,
|
|
3320
3597
|
jt,
|
|
3321
|
-
// Links
|
|
3322
3598
|
Gt,
|
|
3323
|
-
Kt,
|
|
3324
3599
|
Xt,
|
|
3325
|
-
// Language
|
|
3326
|
-
Qt,
|
|
3327
|
-
Yt,
|
|
3328
3600
|
Jt,
|
|
3329
3601
|
Zt,
|
|
3330
|
-
// Tables
|
|
3331
3602
|
ea,
|
|
3332
3603
|
ta,
|
|
3333
3604
|
aa,
|
|
3334
3605
|
ia,
|
|
3606
|
+
na,
|
|
3335
3607
|
ra,
|
|
3608
|
+
oa,
|
|
3609
|
+
sa,
|
|
3610
|
+
la,
|
|
3611
|
+
ua,
|
|
3612
|
+
Wt,
|
|
3613
|
+
ma,
|
|
3614
|
+
// Links
|
|
3615
|
+
ha,
|
|
3616
|
+
ga,
|
|
3617
|
+
ba,
|
|
3618
|
+
// Language
|
|
3619
|
+
fa,
|
|
3620
|
+
va,
|
|
3621
|
+
ya,
|
|
3622
|
+
wa,
|
|
3623
|
+
// Tables
|
|
3624
|
+
Aa,
|
|
3625
|
+
Sa,
|
|
3626
|
+
xa,
|
|
3627
|
+
ka,
|
|
3628
|
+
Ia,
|
|
3336
3629
|
// Parsing
|
|
3337
|
-
|
|
3630
|
+
qa,
|
|
3338
3631
|
// Media
|
|
3339
|
-
|
|
3340
|
-
|
|
3632
|
+
Ca,
|
|
3633
|
+
Ta,
|
|
3634
|
+
// Color
|
|
3635
|
+
Na
|
|
3341
3636
|
];
|
|
3342
|
-
let
|
|
3343
|
-
function
|
|
3344
|
-
t.additionalRules && (
|
|
3637
|
+
let W = [], ie = /* @__PURE__ */ new Set();
|
|
3638
|
+
function Da(t) {
|
|
3639
|
+
t.additionalRules && (W = t.additionalRules), t.disabledRules && (ie = new Set(t.disabledRules));
|
|
3345
3640
|
}
|
|
3346
|
-
function
|
|
3347
|
-
return
|
|
3641
|
+
function ne() {
|
|
3642
|
+
return ae.filter((a) => !ie.has(a.id)).concat(W);
|
|
3348
3643
|
}
|
|
3349
|
-
function
|
|
3350
|
-
|
|
3351
|
-
const a =
|
|
3644
|
+
function Ba(t) {
|
|
3645
|
+
Q(), K(), Z(), J();
|
|
3646
|
+
const a = ne(), e = [];
|
|
3352
3647
|
let i = 0;
|
|
3353
3648
|
return {
|
|
3354
|
-
processChunk(
|
|
3355
|
-
const
|
|
3649
|
+
processChunk(n) {
|
|
3650
|
+
const r = performance.now();
|
|
3356
3651
|
for (; i < a.length; ) {
|
|
3357
3652
|
try {
|
|
3358
3653
|
e.push(...a[i].run(t));
|
|
3359
3654
|
} catch {
|
|
3360
3655
|
}
|
|
3361
|
-
if (i++, performance.now() -
|
|
3656
|
+
if (i++, performance.now() - r >= n) break;
|
|
3362
3657
|
}
|
|
3363
3658
|
return i < a.length;
|
|
3364
3659
|
},
|
|
@@ -3367,13 +3662,13 @@ function ma(t) {
|
|
|
3367
3662
|
}
|
|
3368
3663
|
};
|
|
3369
3664
|
}
|
|
3370
|
-
function
|
|
3665
|
+
function Oa(t) {
|
|
3371
3666
|
var i;
|
|
3372
|
-
|
|
3373
|
-
const a =
|
|
3374
|
-
for (const
|
|
3667
|
+
Q(), K(), Z(), J();
|
|
3668
|
+
const a = ne(), e = [];
|
|
3669
|
+
for (const n of a)
|
|
3375
3670
|
try {
|
|
3376
|
-
e.push(...
|
|
3671
|
+
e.push(...n.run(t));
|
|
3377
3672
|
} catch {
|
|
3378
3673
|
}
|
|
3379
3674
|
return {
|
|
@@ -3383,227 +3678,31 @@ function pa(t) {
|
|
|
3383
3678
|
ruleCount: a.length
|
|
3384
3679
|
};
|
|
3385
3680
|
}
|
|
3386
|
-
const
|
|
3387
|
-
function
|
|
3388
|
-
const a =
|
|
3389
|
-
return a ||
|
|
3390
|
-
}
|
|
3391
|
-
function ga(t) {
|
|
3392
|
-
if (typeof t != "object" || t === null)
|
|
3393
|
-
return "Rule spec must be an object";
|
|
3394
|
-
const a = t;
|
|
3395
|
-
if (typeof a.id != "string" || a.id.length === 0)
|
|
3396
|
-
return "Rule must have a non-empty string id";
|
|
3397
|
-
if (typeof a.selector != "string" || a.selector.length === 0)
|
|
3398
|
-
return "Rule must have a non-empty string selector";
|
|
3399
|
-
if (typeof a.check != "object" || a.check === null)
|
|
3400
|
-
return "Rule must have a check object";
|
|
3401
|
-
const e = a.check;
|
|
3402
|
-
if (![
|
|
3403
|
-
"selector-exists",
|
|
3404
|
-
"attribute-value",
|
|
3405
|
-
"attribute-missing",
|
|
3406
|
-
"attribute-regex",
|
|
3407
|
-
"child-required",
|
|
3408
|
-
"child-invalid"
|
|
3409
|
-
].includes(e.type))
|
|
3410
|
-
return `Invalid check type: ${String(e.type)}`;
|
|
3411
|
-
if (typeof a.impact != "string" || !["critical", "serious", "moderate", "minor"].includes(a.impact))
|
|
3412
|
-
return "Rule must have a valid impact (critical|serious|moderate|minor)";
|
|
3413
|
-
if (typeof a.message != "string" || a.message.length === 0)
|
|
3414
|
-
return "Rule must have a non-empty message";
|
|
3415
|
-
if (typeof a.description != "string")
|
|
3416
|
-
return "Rule must have a description string";
|
|
3417
|
-
if (!Array.isArray(a.wcag))
|
|
3418
|
-
return "Rule must have a wcag array";
|
|
3419
|
-
if (typeof a.level != "string" || !["A", "AA"].includes(a.level))
|
|
3420
|
-
return "Rule must have level A or AA";
|
|
3421
|
-
const r = ca(e);
|
|
3422
|
-
return r || null;
|
|
3423
|
-
}
|
|
3424
|
-
function ca(t) {
|
|
3425
|
-
switch (t.type) {
|
|
3426
|
-
case "selector-exists":
|
|
3427
|
-
return null;
|
|
3428
|
-
case "attribute-value":
|
|
3429
|
-
return typeof t.attribute != "string" ? "attribute-value check requires attribute string" : [">", "<", "=", "!=", "in", "not-in"].includes(t.operator) ? t.value === void 0 ? "attribute-value check requires value" : null : "attribute-value check requires valid operator";
|
|
3430
|
-
case "attribute-missing":
|
|
3431
|
-
return typeof t.attribute != "string" ? "attribute-missing check requires attribute string" : null;
|
|
3432
|
-
case "attribute-regex":
|
|
3433
|
-
return typeof t.attribute != "string" ? "attribute-regex check requires attribute string" : typeof t.pattern != "string" ? "attribute-regex check requires pattern string" : typeof t.shouldMatch != "boolean" ? "attribute-regex check requires shouldMatch boolean" : null;
|
|
3434
|
-
case "child-required":
|
|
3435
|
-
return typeof t.childSelector != "string" ? "child-required check requires childSelector string" : null;
|
|
3436
|
-
case "child-invalid":
|
|
3437
|
-
return Array.isArray(t.allowedChildren) ? null : "child-invalid check requires allowedChildren array";
|
|
3438
|
-
default:
|
|
3439
|
-
return `Unknown check type: ${String(t.type)}`;
|
|
3440
|
-
}
|
|
3441
|
-
}
|
|
3442
|
-
function A(t, a, e) {
|
|
3443
|
-
let i = t;
|
|
3444
|
-
if (i.includes("{{tag}}") && (i = i.replace(/\{\{tag\}\}/g, a.tagName.toLowerCase())), i.includes("{{value}}")) {
|
|
3445
|
-
let r = "";
|
|
3446
|
-
"attribute" in e && e.attribute && (r = a.getAttribute(e.attribute) ?? ""), i = i.replace(/\{\{value\}\}/g, r);
|
|
3447
|
-
}
|
|
3448
|
-
return i;
|
|
3449
|
-
}
|
|
3450
|
-
function ba(t) {
|
|
3451
|
-
const a = t.skipAriaHidden !== !1;
|
|
3452
|
-
return {
|
|
3453
|
-
id: t.id,
|
|
3454
|
-
wcag: t.wcag,
|
|
3455
|
-
level: t.level,
|
|
3456
|
-
tags: t.tags,
|
|
3457
|
-
description: t.description,
|
|
3458
|
-
guidance: t.guidance,
|
|
3459
|
-
prompt: t.prompt,
|
|
3460
|
-
run(e) {
|
|
3461
|
-
const i = [];
|
|
3462
|
-
switch (t.check.type) {
|
|
3463
|
-
case "selector-exists": {
|
|
3464
|
-
for (const r of e.querySelectorAll(t.selector))
|
|
3465
|
-
a && u(r) || i.push({
|
|
3466
|
-
ruleId: t.id,
|
|
3467
|
-
selector: c(r),
|
|
3468
|
-
html: l(r),
|
|
3469
|
-
impact: t.impact,
|
|
3470
|
-
message: A(t.message, r, t.check),
|
|
3471
|
-
element: r
|
|
3472
|
-
});
|
|
3473
|
-
break;
|
|
3474
|
-
}
|
|
3475
|
-
case "attribute-value": {
|
|
3476
|
-
const { attribute: r, operator: n, value: o } = t.check;
|
|
3477
|
-
for (const s of e.querySelectorAll(t.selector)) {
|
|
3478
|
-
if (a && u(s)) continue;
|
|
3479
|
-
const m = s.getAttribute(r);
|
|
3480
|
-
m !== null && da(m, n, o) && i.push({
|
|
3481
|
-
ruleId: t.id,
|
|
3482
|
-
selector: c(s),
|
|
3483
|
-
html: l(s),
|
|
3484
|
-
impact: t.impact,
|
|
3485
|
-
message: A(t.message, s, t.check),
|
|
3486
|
-
element: s
|
|
3487
|
-
});
|
|
3488
|
-
}
|
|
3489
|
-
break;
|
|
3490
|
-
}
|
|
3491
|
-
case "attribute-missing": {
|
|
3492
|
-
const { attribute: r } = t.check;
|
|
3493
|
-
for (const n of e.querySelectorAll(t.selector))
|
|
3494
|
-
a && u(n) || n.hasAttribute(r) || i.push({
|
|
3495
|
-
ruleId: t.id,
|
|
3496
|
-
selector: c(n),
|
|
3497
|
-
html: l(n),
|
|
3498
|
-
impact: t.impact,
|
|
3499
|
-
message: A(t.message, n, t.check),
|
|
3500
|
-
element: n
|
|
3501
|
-
});
|
|
3502
|
-
break;
|
|
3503
|
-
}
|
|
3504
|
-
case "attribute-regex": {
|
|
3505
|
-
const { attribute: r, pattern: n, flags: o, shouldMatch: s } = t.check;
|
|
3506
|
-
let m;
|
|
3507
|
-
try {
|
|
3508
|
-
m = new RegExp(n, o);
|
|
3509
|
-
} catch {
|
|
3510
|
-
break;
|
|
3511
|
-
}
|
|
3512
|
-
for (const h of e.querySelectorAll(t.selector)) {
|
|
3513
|
-
if (a && u(h)) continue;
|
|
3514
|
-
const d = h.getAttribute(r);
|
|
3515
|
-
if (d === null) continue;
|
|
3516
|
-
const p = m.test(d);
|
|
3517
|
-
s && !p ? i.push({
|
|
3518
|
-
ruleId: t.id,
|
|
3519
|
-
selector: c(h),
|
|
3520
|
-
html: l(h),
|
|
3521
|
-
impact: t.impact,
|
|
3522
|
-
message: A(t.message, h, t.check),
|
|
3523
|
-
element: h
|
|
3524
|
-
}) : !s && p && i.push({
|
|
3525
|
-
ruleId: t.id,
|
|
3526
|
-
selector: c(h),
|
|
3527
|
-
html: l(h),
|
|
3528
|
-
impact: t.impact,
|
|
3529
|
-
message: A(t.message, h, t.check),
|
|
3530
|
-
element: h
|
|
3531
|
-
});
|
|
3532
|
-
}
|
|
3533
|
-
break;
|
|
3534
|
-
}
|
|
3535
|
-
case "child-required": {
|
|
3536
|
-
const { childSelector: r } = t.check;
|
|
3537
|
-
for (const n of e.querySelectorAll(t.selector))
|
|
3538
|
-
a && u(n) || n.querySelector(r) || i.push({
|
|
3539
|
-
ruleId: t.id,
|
|
3540
|
-
selector: c(n),
|
|
3541
|
-
html: l(n),
|
|
3542
|
-
impact: t.impact,
|
|
3543
|
-
message: A(t.message, n, t.check),
|
|
3544
|
-
element: n
|
|
3545
|
-
});
|
|
3546
|
-
break;
|
|
3547
|
-
}
|
|
3548
|
-
case "child-invalid": {
|
|
3549
|
-
const r = new Set(
|
|
3550
|
-
t.check.allowedChildren.map((n) => n.toLowerCase())
|
|
3551
|
-
);
|
|
3552
|
-
for (const n of e.querySelectorAll(t.selector))
|
|
3553
|
-
if (!(a && u(n))) {
|
|
3554
|
-
for (const o of n.children)
|
|
3555
|
-
if (!r.has(o.tagName.toLowerCase())) {
|
|
3556
|
-
i.push({
|
|
3557
|
-
ruleId: t.id,
|
|
3558
|
-
selector: c(o),
|
|
3559
|
-
html: l(o),
|
|
3560
|
-
impact: t.impact,
|
|
3561
|
-
message: A(t.message, o, t.check),
|
|
3562
|
-
element: o
|
|
3563
|
-
});
|
|
3564
|
-
break;
|
|
3565
|
-
}
|
|
3566
|
-
}
|
|
3567
|
-
break;
|
|
3568
|
-
}
|
|
3569
|
-
}
|
|
3570
|
-
return i;
|
|
3571
|
-
}
|
|
3572
|
-
};
|
|
3573
|
-
}
|
|
3574
|
-
function da(t, a, e) {
|
|
3575
|
-
switch (a) {
|
|
3576
|
-
case ">":
|
|
3577
|
-
return parseFloat(t) > e;
|
|
3578
|
-
case "<":
|
|
3579
|
-
return parseFloat(t) < e;
|
|
3580
|
-
case "=":
|
|
3581
|
-
return t === String(e);
|
|
3582
|
-
case "!=":
|
|
3583
|
-
return t !== String(e);
|
|
3584
|
-
case "in":
|
|
3585
|
-
return Array.isArray(e) && e.includes(t);
|
|
3586
|
-
case "not-in":
|
|
3587
|
-
return Array.isArray(e) && !e.includes(t);
|
|
3588
|
-
default:
|
|
3589
|
-
return !1;
|
|
3590
|
-
}
|
|
3681
|
+
const $a = new Map(ae.map((t) => [t.id, t]));
|
|
3682
|
+
function Wa(t) {
|
|
3683
|
+
const a = $a.get(t);
|
|
3684
|
+
return a || W.find((e) => e.id === t);
|
|
3591
3685
|
}
|
|
3592
3686
|
export {
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3687
|
+
J as clearAriaAttrAuditCache,
|
|
3688
|
+
Q as clearAriaHiddenCache,
|
|
3689
|
+
Z as clearColorCaches,
|
|
3690
|
+
K as clearComputedRoleCache,
|
|
3691
|
+
x as compileDeclarativeRule,
|
|
3692
|
+
Da as configureRules,
|
|
3693
|
+
Ba as createChunkedAudit,
|
|
3694
|
+
b as getAccessibleName,
|
|
3597
3695
|
w as getAccessibleTextContent,
|
|
3598
|
-
|
|
3599
|
-
|
|
3696
|
+
ne as getActiveRules,
|
|
3697
|
+
T as getComputedRole,
|
|
3600
3698
|
l as getHtmlSnippet,
|
|
3601
|
-
|
|
3602
|
-
|
|
3699
|
+
Y as getImplicitRole,
|
|
3700
|
+
Wa as getRuleById,
|
|
3603
3701
|
c as getSelector,
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3702
|
+
m as isAriaHidden,
|
|
3703
|
+
se as isValidRole,
|
|
3704
|
+
Ma as querySelectorShadowAware,
|
|
3705
|
+
ae as rules,
|
|
3706
|
+
Oa as runAudit,
|
|
3707
|
+
Ha as validateDeclarativeRule
|
|
3609
3708
|
};
|