@accesslint/core 0.3.4 → 0.3.6
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/dist/index.cjs +5 -5
- package/dist/index.iife.js +5 -5
- package/dist/index.js +812 -732
- package/dist/rules/aria/aria-allowed-attr.d.ts.map +1 -1
- package/dist/rules/aria/aria-hidden-rules.d.ts.map +1 -1
- package/dist/rules/forms/label.d.ts.map +1 -1
- package/dist/rules/images/image-redundant-alt.d.ts.map +1 -1
- package/dist/rules/language/html-has-lang.d.ts.map +1 -1
- package/dist/rules/links/link-rules.d.ts.map +1 -1
- package/dist/rules/structure/document-rules.d.ts.map +1 -1
- package/dist/rules/structure/frame-rules.d.ts.map +1 -1
- package/dist/rules/structure/heading-rules.d.ts.map +1 -1
- package/dist/rules/structure/meta-rules.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
let O = /* @__PURE__ */ new WeakMap();
|
|
2
|
-
function
|
|
2
|
+
function ve() {
|
|
3
3
|
O = /* @__PURE__ */ new WeakMap();
|
|
4
4
|
}
|
|
5
5
|
function ue(t) {
|
|
@@ -117,71 +117,71 @@ function ue(t) {
|
|
|
117
117
|
return null;
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
|
-
function
|
|
120
|
+
function L(t) {
|
|
121
121
|
var n;
|
|
122
122
|
const a = O.get(t);
|
|
123
123
|
if (a !== void 0) return a;
|
|
124
124
|
const i = ((n = t.getAttribute("role")) == null ? void 0 : n.trim().toLowerCase()) || null || ue(t);
|
|
125
125
|
return O.set(t, i), i;
|
|
126
126
|
}
|
|
127
|
-
let
|
|
128
|
-
function
|
|
129
|
-
|
|
127
|
+
let B = /* @__PURE__ */ new WeakMap();
|
|
128
|
+
function ye() {
|
|
129
|
+
B = /* @__PURE__ */ new WeakMap();
|
|
130
130
|
}
|
|
131
131
|
function v(t) {
|
|
132
|
-
const a =
|
|
132
|
+
const a = B.get(t);
|
|
133
133
|
if (a !== void 0) return a;
|
|
134
134
|
const e = we(t);
|
|
135
|
-
return
|
|
135
|
+
return B.set(t, e), e;
|
|
136
136
|
}
|
|
137
137
|
function we(t) {
|
|
138
|
-
var r, o, s,
|
|
138
|
+
var r, o, s, l, h;
|
|
139
139
|
const a = t.getAttribute("aria-labelledby");
|
|
140
140
|
if (a) {
|
|
141
|
-
const
|
|
142
|
-
const g = t.ownerDocument.getElementById(
|
|
143
|
-
return g ?
|
|
141
|
+
const c = a.split(/\s+/).map((d) => {
|
|
142
|
+
const g = t.ownerDocument.getElementById(d);
|
|
143
|
+
return g ? w(g).trim() : "";
|
|
144
144
|
}).filter(Boolean);
|
|
145
|
-
if (
|
|
145
|
+
if (c.length) return c.join(" ");
|
|
146
146
|
}
|
|
147
147
|
const e = (r = t.getAttribute("aria-label")) == null ? void 0 : r.trim();
|
|
148
148
|
if (e) return e;
|
|
149
149
|
if (t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement || t instanceof HTMLSelectElement) {
|
|
150
150
|
if (t.id) {
|
|
151
|
-
const g = t.ownerDocument.querySelector(`label[for="${CSS.escape(t.id)}"]`), b = g ?
|
|
151
|
+
const g = t.ownerDocument.querySelector(`label[for="${CSS.escape(t.id)}"]`), b = g ? w(g).trim() : "";
|
|
152
152
|
if (b) return b;
|
|
153
153
|
}
|
|
154
|
-
const
|
|
155
|
-
if (
|
|
154
|
+
const c = t.closest("label"), d = c ? w(c).trim() : "";
|
|
155
|
+
if (d) return d;
|
|
156
156
|
}
|
|
157
157
|
const i = (o = t.getAttribute("title")) == null ? void 0 : o.trim();
|
|
158
158
|
if (i) return i;
|
|
159
159
|
if (t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement) {
|
|
160
|
-
const
|
|
161
|
-
if (
|
|
160
|
+
const c = (s = t.getAttribute("placeholder")) == null ? void 0 : s.trim();
|
|
161
|
+
if (c) return c;
|
|
162
162
|
}
|
|
163
163
|
const n = t.tagName.toLowerCase();
|
|
164
164
|
if (n === "fieldset") {
|
|
165
|
-
const
|
|
166
|
-
if (
|
|
167
|
-
const
|
|
168
|
-
if (
|
|
165
|
+
const c = t.querySelector(":scope > legend");
|
|
166
|
+
if (c) {
|
|
167
|
+
const d = w(c).trim();
|
|
168
|
+
if (d) return d;
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
if (n === "table") {
|
|
172
|
-
const
|
|
173
|
-
if (
|
|
174
|
-
const
|
|
175
|
-
if (
|
|
172
|
+
const c = t.querySelector(":scope > caption");
|
|
173
|
+
if (c) {
|
|
174
|
+
const d = w(c).trim();
|
|
175
|
+
if (d) return d;
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
if (!(t instanceof HTMLInputElement)) {
|
|
179
|
-
const
|
|
180
|
-
if (
|
|
179
|
+
const c = w(t).trim();
|
|
180
|
+
if (c) return c;
|
|
181
181
|
}
|
|
182
|
-
return t instanceof HTMLImageElement || t instanceof HTMLAreaElement ? ((
|
|
182
|
+
return t instanceof HTMLImageElement || t instanceof HTMLAreaElement ? ((l = t.alt) == null ? void 0 : l.trim()) ?? "" : t instanceof HTMLInputElement && t.type === "image" ? ((h = t.alt) == null ? void 0 : h.trim()) ?? "" : "";
|
|
183
183
|
}
|
|
184
|
-
const
|
|
184
|
+
const Ae = /* @__PURE__ */ new Set([
|
|
185
185
|
"alert",
|
|
186
186
|
"alertdialog",
|
|
187
187
|
"application",
|
|
@@ -265,64 +265,64 @@ const ye = /* @__PURE__ */ new Set([
|
|
|
265
265
|
"treegrid",
|
|
266
266
|
"treeitem"
|
|
267
267
|
]);
|
|
268
|
-
function
|
|
268
|
+
function xe(t) {
|
|
269
269
|
const a = t.trim().toLowerCase().replace(/[\u201C\u201D\u2018\u2019\u00AB\u00BB]/g, "");
|
|
270
|
-
return
|
|
270
|
+
return Ae.has(a);
|
|
271
271
|
}
|
|
272
|
-
let
|
|
272
|
+
let F = /* @__PURE__ */ new WeakMap();
|
|
273
273
|
function Se() {
|
|
274
|
-
|
|
274
|
+
F = /* @__PURE__ */ new WeakMap();
|
|
275
275
|
}
|
|
276
276
|
function p(t) {
|
|
277
|
-
const a =
|
|
277
|
+
const a = F.get(t);
|
|
278
278
|
if (a !== void 0) return a;
|
|
279
279
|
let e;
|
|
280
|
-
return t.getAttribute("aria-hidden") === "true" || t instanceof HTMLElement && (t.hidden || t.style.display === "none") ? e = !0 : t.parentElement ? e = p(t.parentElement) : e = !1,
|
|
280
|
+
return t.getAttribute("aria-hidden") === "true" || t instanceof HTMLElement && (t.hidden || t.style.display === "none") ? e = !0 : t.parentElement ? e = p(t.parentElement) : e = !1, F.set(t, e), e;
|
|
281
281
|
}
|
|
282
|
-
function
|
|
282
|
+
function ke(t) {
|
|
283
283
|
return !!(t.getAttribute("aria-hidden") === "true" || t instanceof HTMLElement && (t.hidden || t.style.display === "none"));
|
|
284
284
|
}
|
|
285
|
-
function
|
|
285
|
+
function w(t) {
|
|
286
286
|
var e, i, n, r, o;
|
|
287
287
|
let a = "";
|
|
288
288
|
for (const s of t.childNodes)
|
|
289
289
|
if (s.nodeType === 3)
|
|
290
290
|
a += s.textContent ?? "";
|
|
291
291
|
else if (s.nodeType === 1) {
|
|
292
|
-
const
|
|
293
|
-
if (!
|
|
294
|
-
const h = (e =
|
|
292
|
+
const l = s;
|
|
293
|
+
if (!ke(l)) {
|
|
294
|
+
const h = (e = l.tagName) == null ? void 0 : e.toLowerCase();
|
|
295
295
|
if (h === "img" || h === "area") {
|
|
296
|
-
const
|
|
297
|
-
if (
|
|
298
|
-
const
|
|
296
|
+
const c = l.getAttribute("aria-labelledby");
|
|
297
|
+
if (c) {
|
|
298
|
+
const d = c.split(/\s+/).map((g) => {
|
|
299
299
|
var b, f;
|
|
300
|
-
return ((f = (b =
|
|
300
|
+
return ((f = (b = l.ownerDocument.getElementById(g)) == null ? void 0 : b.textContent) == null ? void 0 : f.trim()) ?? "";
|
|
301
301
|
}).filter(Boolean);
|
|
302
|
-
if (
|
|
303
|
-
a +=
|
|
302
|
+
if (d.length) {
|
|
303
|
+
a += d.join(" ");
|
|
304
304
|
continue;
|
|
305
305
|
}
|
|
306
306
|
}
|
|
307
|
-
a += ((i =
|
|
307
|
+
a += ((i = l.getAttribute("aria-label")) == null ? void 0 : i.trim()) ?? l.getAttribute("alt") ?? ((n = l.getAttribute("title")) == null ? void 0 : n.trim()) ?? "";
|
|
308
308
|
} else if (h === "svg") {
|
|
309
|
-
const
|
|
310
|
-
if (
|
|
311
|
-
a +=
|
|
309
|
+
const c = (r = l.getAttribute("aria-label")) == null ? void 0 : r.trim();
|
|
310
|
+
if (c)
|
|
311
|
+
a += c;
|
|
312
312
|
else {
|
|
313
|
-
const
|
|
314
|
-
|
|
313
|
+
const d = l.querySelector("title");
|
|
314
|
+
d && (a += d.textContent ?? "");
|
|
315
315
|
}
|
|
316
|
-
} else (o =
|
|
316
|
+
} else (o = l.getAttribute("aria-label")) != null && o.trim() ? a += l.getAttribute("aria-label").trim() : a += w(l);
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
319
|
return a;
|
|
320
320
|
}
|
|
321
|
-
let
|
|
322
|
-
function
|
|
323
|
-
|
|
321
|
+
let W = /* @__PURE__ */ new WeakMap();
|
|
322
|
+
function Ie() {
|
|
323
|
+
W = /* @__PURE__ */ new WeakMap();
|
|
324
324
|
}
|
|
325
|
-
function
|
|
325
|
+
function Te(t) {
|
|
326
326
|
return t.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
327
327
|
}
|
|
328
328
|
const Ee = [
|
|
@@ -335,12 +335,12 @@ const Ee = [
|
|
|
335
335
|
"for",
|
|
336
336
|
"aria-label"
|
|
337
337
|
];
|
|
338
|
-
function
|
|
338
|
+
function Ce(t) {
|
|
339
339
|
const a = t.tagName.toLowerCase();
|
|
340
340
|
for (const i of Ee) {
|
|
341
341
|
const n = t.getAttribute(i);
|
|
342
342
|
if (n != null && n.length > 0 && n.length < 100)
|
|
343
|
-
return `${a}[${i}="${
|
|
343
|
+
return `${a}[${i}="${Te(n)}"]`;
|
|
344
344
|
}
|
|
345
345
|
const e = t.parentElement;
|
|
346
346
|
if (e) {
|
|
@@ -352,7 +352,7 @@ function Te(t) {
|
|
|
352
352
|
}
|
|
353
353
|
return a;
|
|
354
354
|
}
|
|
355
|
-
function
|
|
355
|
+
function M(t) {
|
|
356
356
|
if (t.id) return `#${CSS.escape(t.id)}`;
|
|
357
357
|
const a = t.getRootNode(), e = a instanceof ShadowRoot ? null : a.documentElement, i = [];
|
|
358
358
|
let n = t;
|
|
@@ -361,7 +361,7 @@ function $(t) {
|
|
|
361
361
|
i.unshift(`#${CSS.escape(n.id)}`);
|
|
362
362
|
break;
|
|
363
363
|
}
|
|
364
|
-
if (i.unshift(
|
|
364
|
+
if (i.unshift(Ce(n)), i.length >= 2) {
|
|
365
365
|
const r = i.join(" > ");
|
|
366
366
|
try {
|
|
367
367
|
const o = a.querySelectorAll(r);
|
|
@@ -373,28 +373,28 @@ function $(t) {
|
|
|
373
373
|
}
|
|
374
374
|
return i.join(" > ");
|
|
375
375
|
}
|
|
376
|
-
function
|
|
376
|
+
function m(t) {
|
|
377
377
|
var r;
|
|
378
|
-
const a =
|
|
378
|
+
const a = W.get(t);
|
|
379
379
|
if (a !== void 0) return a;
|
|
380
380
|
const e = [];
|
|
381
381
|
let i = t;
|
|
382
382
|
for (; i; ) {
|
|
383
383
|
const o = i.getRootNode();
|
|
384
384
|
if (o instanceof ShadowRoot)
|
|
385
|
-
e.unshift({ selector:
|
|
385
|
+
e.unshift({ selector: M(i), delimiter: " >>> " }), i = o.host;
|
|
386
386
|
else {
|
|
387
387
|
const s = (r = o.defaultView) == null ? void 0 : r.frameElement;
|
|
388
388
|
if (s)
|
|
389
|
-
e.unshift({ selector:
|
|
389
|
+
e.unshift({ selector: M(i), delimiter: " >>>iframe> " }), i = s;
|
|
390
390
|
else {
|
|
391
|
-
e.unshift({ selector:
|
|
391
|
+
e.unshift({ selector: M(i), delimiter: "" });
|
|
392
392
|
break;
|
|
393
393
|
}
|
|
394
394
|
}
|
|
395
395
|
}
|
|
396
396
|
const n = e.map((o, s) => (s === 0 ? "" : o.delimiter) + o.selector).join("");
|
|
397
|
-
return
|
|
397
|
+
return W.set(t, n), n;
|
|
398
398
|
}
|
|
399
399
|
function wi(t) {
|
|
400
400
|
const a = [], e = [];
|
|
@@ -429,7 +429,7 @@ function wi(t) {
|
|
|
429
429
|
}
|
|
430
430
|
return null;
|
|
431
431
|
}
|
|
432
|
-
function
|
|
432
|
+
function u(t) {
|
|
433
433
|
const a = t.outerHTML;
|
|
434
434
|
return a.length > 200 ? a.slice(0, 200) + "..." : a;
|
|
435
435
|
}
|
|
@@ -498,7 +498,7 @@ const Le = /* @__PURE__ */ new Set([
|
|
|
498
498
|
"aria-multiselectable",
|
|
499
499
|
"aria-readonly",
|
|
500
500
|
"aria-required"
|
|
501
|
-
]), X = /* @__PURE__ */ new Set(["aria-checked", "aria-pressed"]),
|
|
501
|
+
]), X = /* @__PURE__ */ new Set(["aria-checked", "aria-pressed"]), qe = /* @__PURE__ */ new Set([
|
|
502
502
|
"aria-colcount",
|
|
503
503
|
"aria-colindex",
|
|
504
504
|
"aria-colspan",
|
|
@@ -508,7 +508,7 @@ const Le = /* @__PURE__ */ new Set([
|
|
|
508
508
|
"aria-rowindex",
|
|
509
509
|
"aria-rowspan",
|
|
510
510
|
"aria-setsize"
|
|
511
|
-
]),
|
|
511
|
+
]), Re = /* @__PURE__ */ new Set([
|
|
512
512
|
"aria-valuemax",
|
|
513
513
|
"aria-valuemin",
|
|
514
514
|
"aria-valuenow"
|
|
@@ -540,7 +540,7 @@ const Le = /* @__PURE__ */ new Set([
|
|
|
540
540
|
"suggestion",
|
|
541
541
|
"term",
|
|
542
542
|
"time"
|
|
543
|
-
]),
|
|
543
|
+
]), Ne = {
|
|
544
544
|
abbr: !0,
|
|
545
545
|
bdi: !0,
|
|
546
546
|
bdo: !0,
|
|
@@ -568,7 +568,7 @@ const Le = /* @__PURE__ */ new Set([
|
|
|
568
568
|
u: !0,
|
|
569
569
|
var: !0,
|
|
570
570
|
wbr: !0
|
|
571
|
-
},
|
|
571
|
+
}, $e = {
|
|
572
572
|
alert: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"]),
|
|
573
573
|
article: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"]),
|
|
574
574
|
banner: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"]),
|
|
@@ -601,95 +601,95 @@ const Le = /* @__PURE__ */ new Set([
|
|
|
601
601
|
time: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"]),
|
|
602
602
|
tooltip: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"])
|
|
603
603
|
};
|
|
604
|
-
let
|
|
604
|
+
let E = null, C = null;
|
|
605
605
|
function Me() {
|
|
606
|
-
|
|
606
|
+
E = null, C = null;
|
|
607
607
|
}
|
|
608
608
|
function z(t) {
|
|
609
609
|
var n;
|
|
610
|
-
if (
|
|
610
|
+
if (C && (E == null ? void 0 : E.deref()) === t) return C;
|
|
611
611
|
const a = [], e = [], i = [];
|
|
612
612
|
for (const r of t.querySelectorAll("*")) {
|
|
613
613
|
let o = !1;
|
|
614
|
-
for (const
|
|
615
|
-
if (
|
|
614
|
+
for (const c of r.attributes)
|
|
615
|
+
if (c.name.startsWith("aria-")) {
|
|
616
616
|
o = !0;
|
|
617
617
|
break;
|
|
618
618
|
}
|
|
619
619
|
if (!o) continue;
|
|
620
|
-
let s,
|
|
621
|
-
const h = () => (s === void 0 && (s =
|
|
622
|
-
for (const
|
|
623
|
-
if (
|
|
624
|
-
const
|
|
620
|
+
let s, l;
|
|
621
|
+
const h = () => (s === void 0 && (s = m(r), l = u(r)), { selector: s, html: l });
|
|
622
|
+
for (const c of r.attributes)
|
|
623
|
+
if (c.name.startsWith("aria-") && !Le.has(c.name)) {
|
|
624
|
+
const d = h();
|
|
625
625
|
a.push({
|
|
626
626
|
ruleId: "aria-valid-attr",
|
|
627
|
-
selector:
|
|
628
|
-
html:
|
|
627
|
+
selector: d.selector,
|
|
628
|
+
html: d.html,
|
|
629
629
|
impact: "critical",
|
|
630
|
-
message: `Invalid ARIA attribute "${
|
|
630
|
+
message: `Invalid ARIA attribute "${c.name}".`
|
|
631
631
|
});
|
|
632
632
|
break;
|
|
633
633
|
}
|
|
634
|
-
for (const
|
|
635
|
-
if (!
|
|
636
|
-
const
|
|
637
|
-
if (!(
|
|
638
|
-
if (G.has(
|
|
639
|
-
if (
|
|
634
|
+
for (const c of r.attributes) {
|
|
635
|
+
if (!c.name.startsWith("aria-")) continue;
|
|
636
|
+
const d = c.value.trim();
|
|
637
|
+
if (!(d === "" && !G.has(c.name) && !X.has(c.name))) {
|
|
638
|
+
if (G.has(c.name)) {
|
|
639
|
+
if (d !== "true" && d !== "false") {
|
|
640
640
|
const g = h();
|
|
641
641
|
e.push({
|
|
642
642
|
ruleId: "aria-valid-attr-value",
|
|
643
643
|
selector: g.selector,
|
|
644
644
|
html: g.html,
|
|
645
645
|
impact: "critical",
|
|
646
|
-
message: `${
|
|
646
|
+
message: `${c.name} must be "true" or "false", got "${d}".`
|
|
647
647
|
});
|
|
648
648
|
}
|
|
649
|
-
} else if (X.has(
|
|
650
|
-
if (
|
|
649
|
+
} else if (X.has(c.name)) {
|
|
650
|
+
if (d !== "true" && d !== "false" && d !== "mixed") {
|
|
651
651
|
const g = h();
|
|
652
652
|
e.push({
|
|
653
653
|
ruleId: "aria-valid-attr-value",
|
|
654
654
|
selector: g.selector,
|
|
655
655
|
html: g.html,
|
|
656
656
|
impact: "critical",
|
|
657
|
-
message: `${
|
|
657
|
+
message: `${c.name} must be "true", "false", or "mixed", got "${d}".`
|
|
658
658
|
});
|
|
659
659
|
}
|
|
660
|
-
} else if (
|
|
661
|
-
if (
|
|
660
|
+
} else if (qe.has(c.name)) {
|
|
661
|
+
if (d === "" || !/^-?\d+$/.test(d)) {
|
|
662
662
|
const g = h();
|
|
663
663
|
e.push({
|
|
664
664
|
ruleId: "aria-valid-attr-value",
|
|
665
665
|
selector: g.selector,
|
|
666
666
|
html: g.html,
|
|
667
667
|
impact: "critical",
|
|
668
|
-
message: `${
|
|
668
|
+
message: `${c.name} must be an integer, got "${d}".`
|
|
669
669
|
});
|
|
670
670
|
}
|
|
671
|
-
} else if (
|
|
672
|
-
if (
|
|
671
|
+
} else if (Re.has(c.name)) {
|
|
672
|
+
if (d === "" || isNaN(Number(d))) {
|
|
673
673
|
const g = h();
|
|
674
674
|
e.push({
|
|
675
675
|
ruleId: "aria-valid-attr-value",
|
|
676
676
|
selector: g.selector,
|
|
677
677
|
html: g.html,
|
|
678
678
|
impact: "critical",
|
|
679
|
-
message: `${
|
|
679
|
+
message: `${c.name} must be a number, got "${d}".`
|
|
680
680
|
});
|
|
681
681
|
}
|
|
682
|
-
} else if (Y[
|
|
683
|
-
const g =
|
|
682
|
+
} else if (Y[c.name]) {
|
|
683
|
+
const g = d.split(/\s+/);
|
|
684
684
|
for (const b of g)
|
|
685
|
-
if (!Y[
|
|
685
|
+
if (!Y[c.name].has(b)) {
|
|
686
686
|
const f = h();
|
|
687
687
|
e.push({
|
|
688
688
|
ruleId: "aria-valid-attr-value",
|
|
689
689
|
selector: f.selector,
|
|
690
690
|
html: f.html,
|
|
691
691
|
impact: "critical",
|
|
692
|
-
message: `Invalid value "${
|
|
692
|
+
message: `Invalid value "${d}" for ${c.name}.`
|
|
693
693
|
});
|
|
694
694
|
break;
|
|
695
695
|
}
|
|
@@ -697,8 +697,8 @@ function z(t) {
|
|
|
697
697
|
}
|
|
698
698
|
}
|
|
699
699
|
if (!p(r)) {
|
|
700
|
-
const
|
|
701
|
-
if (!
|
|
700
|
+
const c = (n = r.getAttribute("role")) == null ? void 0 : n.trim().toLowerCase(), d = r.tagName.toLowerCase();
|
|
701
|
+
if (!c && Ne[d]) {
|
|
702
702
|
const g = r.hasAttribute("aria-label"), b = r.hasAttribute("aria-labelledby");
|
|
703
703
|
if (g || b) {
|
|
704
704
|
const f = h();
|
|
@@ -707,28 +707,28 @@ function z(t) {
|
|
|
707
707
|
selector: f.selector,
|
|
708
708
|
html: f.html,
|
|
709
709
|
impact: "serious",
|
|
710
|
-
message: `aria-label and aria-labelledby are prohibited on <${
|
|
710
|
+
message: `aria-label and aria-labelledby are prohibited on <${d}> elements.`
|
|
711
711
|
});
|
|
712
712
|
}
|
|
713
|
-
} else if (
|
|
714
|
-
if (K.has(
|
|
713
|
+
} else if (c) {
|
|
714
|
+
if (K.has(c)) {
|
|
715
715
|
const b = r.hasAttribute("aria-label"), f = r.hasAttribute("aria-labelledby");
|
|
716
716
|
if (b || f) {
|
|
717
|
-
const
|
|
717
|
+
const y = h();
|
|
718
718
|
i.push({
|
|
719
719
|
ruleId: "aria-prohibited-attr",
|
|
720
|
-
selector:
|
|
721
|
-
html:
|
|
720
|
+
selector: y.selector,
|
|
721
|
+
html: y.html,
|
|
722
722
|
impact: "serious",
|
|
723
|
-
message: `aria-label and aria-labelledby are prohibited on role "${
|
|
723
|
+
message: `aria-label and aria-labelledby are prohibited on role "${c}".`
|
|
724
724
|
});
|
|
725
725
|
}
|
|
726
726
|
}
|
|
727
|
-
const g =
|
|
727
|
+
const g = $e[c];
|
|
728
728
|
if (g) {
|
|
729
729
|
for (const b of r.attributes)
|
|
730
730
|
if (b.name.startsWith("aria-") && g.has(b.name)) {
|
|
731
|
-
if ((b.name === "aria-label" || b.name === "aria-labelledby") && K.has(
|
|
731
|
+
if ((b.name === "aria-label" || b.name === "aria-labelledby") && K.has(c))
|
|
732
732
|
continue;
|
|
733
733
|
const f = h();
|
|
734
734
|
i.push({
|
|
@@ -736,22 +736,22 @@ function z(t) {
|
|
|
736
736
|
selector: f.selector,
|
|
737
737
|
html: f.html,
|
|
738
738
|
impact: "serious",
|
|
739
|
-
message: `Attribute "${b.name}" is prohibited on role "${
|
|
739
|
+
message: `Attribute "${b.name}" is prohibited on role "${c}".`
|
|
740
740
|
});
|
|
741
741
|
}
|
|
742
742
|
}
|
|
743
743
|
}
|
|
744
744
|
}
|
|
745
745
|
}
|
|
746
|
-
return
|
|
746
|
+
return E = new WeakRef(t), C = { validAttr: a, validAttrValue: e, prohibitedAttr: i }, C;
|
|
747
747
|
}
|
|
748
|
-
let
|
|
749
|
-
function
|
|
750
|
-
|
|
748
|
+
let _ = /* @__PURE__ */ new WeakMap(), P = /* @__PURE__ */ new WeakMap(), j = /* @__PURE__ */ new WeakMap();
|
|
749
|
+
function He() {
|
|
750
|
+
_ = /* @__PURE__ */ new WeakMap(), P = /* @__PURE__ */ new WeakMap(), j = /* @__PURE__ */ new WeakMap();
|
|
751
751
|
}
|
|
752
752
|
function A(t) {
|
|
753
|
-
let a =
|
|
754
|
-
return a || (a = getComputedStyle(t),
|
|
753
|
+
let a = _.get(t);
|
|
754
|
+
return a || (a = getComputedStyle(t), _.set(t, a), a);
|
|
755
755
|
}
|
|
756
756
|
function q(t, a, e) {
|
|
757
757
|
const [i, n, r] = [t, a, e].map((o) => {
|
|
@@ -764,7 +764,7 @@ function de(t, a) {
|
|
|
764
764
|
const e = Math.max(t, a), i = Math.min(t, a);
|
|
765
765
|
return (e + 0.05) / (i + 0.05);
|
|
766
766
|
}
|
|
767
|
-
const
|
|
767
|
+
const J = {
|
|
768
768
|
black: [0, 0, 0],
|
|
769
769
|
white: [255, 255, 255],
|
|
770
770
|
red: [255, 0, 0],
|
|
@@ -786,7 +786,7 @@ const Q = {
|
|
|
786
786
|
};
|
|
787
787
|
function R(t) {
|
|
788
788
|
const a = t.trim().toLowerCase();
|
|
789
|
-
if (
|
|
789
|
+
if (J[a]) return J[a];
|
|
790
790
|
const e = a.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])$/);
|
|
791
791
|
if (e)
|
|
792
792
|
return [parseInt(e[1] + e[1], 16), parseInt(e[2] + e[2], 16), parseInt(e[3] + e[3], 16)];
|
|
@@ -803,13 +803,13 @@ function R(t) {
|
|
|
803
803
|
);
|
|
804
804
|
return r ? [parseInt(r[1]), parseInt(r[2]), parseInt(r[3])] : null;
|
|
805
805
|
}
|
|
806
|
-
function
|
|
807
|
-
const a =
|
|
806
|
+
function De(t) {
|
|
807
|
+
const a = P.get(t);
|
|
808
808
|
if (a !== void 0) return a;
|
|
809
|
-
const e =
|
|
810
|
-
return
|
|
809
|
+
const e = Oe(t);
|
|
810
|
+
return P.set(t, e), e;
|
|
811
811
|
}
|
|
812
|
-
function
|
|
812
|
+
function Oe(t) {
|
|
813
813
|
let a = t;
|
|
814
814
|
for (; a; ) {
|
|
815
815
|
const e = A(a), i = e.backgroundImage;
|
|
@@ -828,20 +828,20 @@ function De(t) {
|
|
|
828
828
|
}
|
|
829
829
|
return [255, 255, 255];
|
|
830
830
|
}
|
|
831
|
-
const
|
|
832
|
-
function
|
|
833
|
-
const a =
|
|
831
|
+
const Be = /* @__PURE__ */ new Set(["IMG", "PICTURE", "VIDEO", "SVG"]);
|
|
832
|
+
function Fe(t) {
|
|
833
|
+
const a = j.get(t);
|
|
834
834
|
if (a !== void 0) return a;
|
|
835
|
-
const e =
|
|
836
|
-
return
|
|
835
|
+
const e = We(t);
|
|
836
|
+
return j.set(t, e), e;
|
|
837
837
|
}
|
|
838
|
-
function
|
|
838
|
+
function We(t) {
|
|
839
839
|
let a = t, e = !1;
|
|
840
840
|
for (; a; ) {
|
|
841
841
|
const i = A(a).position;
|
|
842
842
|
if ((i === "absolute" || i === "fixed") && (e = !0), a !== t && i !== "static") {
|
|
843
843
|
for (const n of a.children)
|
|
844
|
-
if (!(n === t || n.contains(t)) &&
|
|
844
|
+
if (!(n === t || n.contains(t)) && Be.has(n.tagName)) {
|
|
845
845
|
if (e) return !0;
|
|
846
846
|
const r = A(n).position;
|
|
847
847
|
if (r === "absolute" || r === "fixed") return !0;
|
|
@@ -856,7 +856,7 @@ function _e(t) {
|
|
|
856
856
|
const a = parseFloat(t);
|
|
857
857
|
return t.endsWith("pt") ? a * (4 / 3) : a;
|
|
858
858
|
}
|
|
859
|
-
function
|
|
859
|
+
function Pe(t) {
|
|
860
860
|
const a = A(t), e = _e(a.fontSize), i = parseInt(a.fontWeight) || (a.fontWeight === "bold" ? 700 : 400);
|
|
861
861
|
return e >= 23.5 || e >= 18.5 && i >= 700;
|
|
862
862
|
}
|
|
@@ -874,13 +874,13 @@ function H(t) {
|
|
|
874
874
|
}
|
|
875
875
|
const n = t.parentElement;
|
|
876
876
|
if (n && n !== e) {
|
|
877
|
-
const s = t instanceof HTMLImageElement && t.alt || "",
|
|
878
|
-
|
|
877
|
+
const s = t instanceof HTMLImageElement && t.alt || "", l = (o = n.textContent) == null ? void 0 : o.replace(s, "").trim().slice(0, 100);
|
|
878
|
+
l && a.push(`Adjacent text: ${l}`);
|
|
879
879
|
}
|
|
880
880
|
return a.length > 0 ? a.join(`
|
|
881
881
|
`) : void 0;
|
|
882
882
|
}
|
|
883
|
-
function
|
|
883
|
+
function Q(t) {
|
|
884
884
|
let a = t;
|
|
885
885
|
for (; a; ) {
|
|
886
886
|
if (a instanceof HTMLElement && a.style.visibility === "hidden") return !0;
|
|
@@ -898,7 +898,7 @@ const je = {
|
|
|
898
898
|
run(t) {
|
|
899
899
|
const a = [];
|
|
900
900
|
for (const e of t.querySelectorAll("img")) {
|
|
901
|
-
if (p(e) ||
|
|
901
|
+
if (p(e) || Q(e)) continue;
|
|
902
902
|
const i = e.getAttribute("role");
|
|
903
903
|
if (i === "presentation" || i === "none") {
|
|
904
904
|
const r = e.getAttribute("tabindex");
|
|
@@ -908,8 +908,8 @@ const je = {
|
|
|
908
908
|
if (n !== null && n.trim() === "" && n !== "") {
|
|
909
909
|
a.push({
|
|
910
910
|
ruleId: "img-alt",
|
|
911
|
-
selector:
|
|
912
|
-
html:
|
|
911
|
+
selector: m(e),
|
|
912
|
+
html: u(e),
|
|
913
913
|
impact: "critical",
|
|
914
914
|
message: 'Image has whitespace-only alt text. Use alt="" for decorative images or provide descriptive text.',
|
|
915
915
|
context: H(e)
|
|
@@ -918,18 +918,18 @@ const je = {
|
|
|
918
918
|
}
|
|
919
919
|
!e.hasAttribute("alt") && !v(e) && a.push({
|
|
920
920
|
ruleId: "img-alt",
|
|
921
|
-
selector:
|
|
922
|
-
html:
|
|
921
|
+
selector: m(e),
|
|
922
|
+
html: u(e),
|
|
923
923
|
impact: "critical",
|
|
924
924
|
message: "Image element missing alt attribute.",
|
|
925
925
|
context: H(e)
|
|
926
926
|
});
|
|
927
927
|
}
|
|
928
928
|
for (const e of t.querySelectorAll('[role="img"]:not(img):not(svg)'))
|
|
929
|
-
p(e) ||
|
|
929
|
+
p(e) || Q(e) || v(e) || a.push({
|
|
930
930
|
ruleId: "img-alt",
|
|
931
|
-
selector:
|
|
932
|
-
html:
|
|
931
|
+
selector: m(e),
|
|
932
|
+
html: u(e),
|
|
933
933
|
impact: "critical",
|
|
934
934
|
message: 'Element with role="img" has no accessible name. Add aria-label or aria-labelledby.',
|
|
935
935
|
context: H(e)
|
|
@@ -937,15 +937,15 @@ const je = {
|
|
|
937
937
|
return a;
|
|
938
938
|
}
|
|
939
939
|
};
|
|
940
|
-
function
|
|
940
|
+
function Ve(t) {
|
|
941
941
|
var r, o, s;
|
|
942
942
|
const a = t.getAttribute("aria-labelledby");
|
|
943
943
|
if (a) {
|
|
944
|
-
const
|
|
945
|
-
var
|
|
946
|
-
return ((
|
|
944
|
+
const l = a.split(/\s+/).map((h) => {
|
|
945
|
+
var c, d;
|
|
946
|
+
return ((d = (c = t.ownerDocument.getElementById(h)) == null ? void 0 : c.textContent) == null ? void 0 : d.trim()) ?? "";
|
|
947
947
|
}).filter(Boolean);
|
|
948
|
-
if (
|
|
948
|
+
if (l.length) return l.join(" ");
|
|
949
949
|
}
|
|
950
950
|
const e = (r = t.getAttribute("aria-label")) == null ? void 0 : r.trim();
|
|
951
951
|
if (e) return e;
|
|
@@ -954,7 +954,7 @@ function Pe(t) {
|
|
|
954
954
|
const n = (s = t.getAttribute("title")) == null ? void 0 : s.trim();
|
|
955
955
|
return n || "";
|
|
956
956
|
}
|
|
957
|
-
const
|
|
957
|
+
const ze = {
|
|
958
958
|
id: "svg-img-alt",
|
|
959
959
|
wcag: ["1.1.1"],
|
|
960
960
|
level: "A",
|
|
@@ -965,12 +965,12 @@ const Ve = {
|
|
|
965
965
|
const a = [], e = 'svg[role="img"], [role="graphics-document"], [role="graphics-symbol"]';
|
|
966
966
|
for (const i of t.querySelectorAll(e)) {
|
|
967
967
|
if (p(i)) continue;
|
|
968
|
-
if (!
|
|
968
|
+
if (!Ve(i)) {
|
|
969
969
|
const r = i.getAttribute("role");
|
|
970
970
|
a.push({
|
|
971
971
|
ruleId: "svg-img-alt",
|
|
972
|
-
selector:
|
|
973
|
-
html:
|
|
972
|
+
selector: m(i),
|
|
973
|
+
html: u(i),
|
|
974
974
|
impact: "serious",
|
|
975
975
|
message: `${i.tagName.toLowerCase()} with role='${r}' has no accessible name.`
|
|
976
976
|
});
|
|
@@ -978,7 +978,7 @@ const Ve = {
|
|
|
978
978
|
}
|
|
979
979
|
return a;
|
|
980
980
|
}
|
|
981
|
-
},
|
|
981
|
+
}, Ue = {
|
|
982
982
|
id: "input-image-alt",
|
|
983
983
|
wcag: ["1.1.1", "4.1.2"],
|
|
984
984
|
level: "A",
|
|
@@ -990,21 +990,21 @@ const Ve = {
|
|
|
990
990
|
for (const e of t.querySelectorAll('input[type="image"]'))
|
|
991
991
|
p(e) || v(e) || a.push({
|
|
992
992
|
ruleId: "input-image-alt",
|
|
993
|
-
selector:
|
|
994
|
-
html:
|
|
993
|
+
selector: m(e),
|
|
994
|
+
html: u(e),
|
|
995
995
|
impact: "critical",
|
|
996
996
|
message: "Image input missing alt text."
|
|
997
997
|
});
|
|
998
998
|
return a;
|
|
999
999
|
}
|
|
1000
|
-
},
|
|
1000
|
+
}, Ge = {
|
|
1001
1001
|
id: "image-redundant-alt",
|
|
1002
1002
|
wcag: [],
|
|
1003
1003
|
level: "A",
|
|
1004
1004
|
tags: ["best-practice"],
|
|
1005
1005
|
description: "Image alt text should not duplicate adjacent link or button text. When alt text repeats surrounding text, screen reader users hear the same information twice.",
|
|
1006
1006
|
guidance: "When an image is inside a link or button that also has text, make the alt text complementary rather than identical. If the image is purely decorative in that context, use alt='' to avoid repetition.",
|
|
1007
|
-
prompt: "
|
|
1007
|
+
prompt: "The image alt text is identical to the text already visible in the parent link or button. Screen reader users hear the same words twice. If the image is decorative in this context (e.g. an icon next to a label), recommend alt=''. Otherwise suggest brief complementary alt text that adds information the visible text doesn't convey — for example what the image depicts, not what the link says.",
|
|
1008
1008
|
run(t) {
|
|
1009
1009
|
var e;
|
|
1010
1010
|
const a = [];
|
|
@@ -1014,40 +1014,47 @@ const Ve = {
|
|
|
1014
1014
|
const r = i.closest("a, button");
|
|
1015
1015
|
if (r) {
|
|
1016
1016
|
const o = ((e = r.textContent) == null ? void 0 : e.trim().toLowerCase()) || "";
|
|
1017
|
-
o && o === n
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1017
|
+
if (o && o === n) {
|
|
1018
|
+
const s = r.tagName.toLowerCase(), l = r.getAttribute("href");
|
|
1019
|
+
a.push({
|
|
1020
|
+
ruleId: "image-redundant-alt",
|
|
1021
|
+
selector: m(i),
|
|
1022
|
+
html: u(i),
|
|
1023
|
+
impact: "minor",
|
|
1024
|
+
message: `Alt text "${i.getAttribute("alt")}" duplicates surrounding ${s} text.`,
|
|
1025
|
+
context: `Duplicated text: "${i.getAttribute("alt")}", parent element: <${s}>${l ? ` href="${l}"` : ""}`
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1024
1028
|
}
|
|
1025
1029
|
}
|
|
1026
1030
|
return a;
|
|
1027
1031
|
}
|
|
1028
|
-
},
|
|
1032
|
+
}, Xe = ["image", "picture", "photo", "graphic", "icon", "img"], Ye = {
|
|
1029
1033
|
id: "image-alt-redundant-words",
|
|
1030
1034
|
wcag: [],
|
|
1031
1035
|
level: "A",
|
|
1032
1036
|
tags: ["best-practice"],
|
|
1033
1037
|
description: "Image alt text should not contain words like 'image', 'photo', or 'picture' — screen readers already announce the element type.",
|
|
1034
1038
|
guidance: "Screen readers already announce 'image' or 'graphic' before reading alt text, so phrases like 'image of', 'photo of', or 'picture of' are redundant. Remove these words and describe what the image shows. For example, change 'image of a dog' to 'golden retriever playing fetch'.",
|
|
1035
|
-
prompt: "
|
|
1039
|
+
prompt: "The alt text contains a word like 'image', 'photo', or 'picture' that is already announced by the screen reader. Rewrite the alt text with the redundant word removed while keeping the description meaningful. For example: 'image of a sunset over the ocean' → 'sunset over the ocean'; 'photo of team members' → 'team members at the 2024 offsite'; 'icon for settings' → 'settings'.",
|
|
1036
1040
|
run(t) {
|
|
1037
1041
|
const a = [];
|
|
1038
1042
|
for (const e of t.querySelectorAll("img[alt]")) {
|
|
1039
1043
|
const i = e.getAttribute("alt").toLowerCase();
|
|
1040
|
-
|
|
1044
|
+
if (!i) continue;
|
|
1045
|
+
const n = Xe.filter((r) => i.split(/\s+/).includes(r));
|
|
1046
|
+
n.length > 0 && a.push({
|
|
1041
1047
|
ruleId: "image-alt-redundant-words",
|
|
1042
|
-
selector:
|
|
1043
|
-
html:
|
|
1048
|
+
selector: m(e),
|
|
1049
|
+
html: u(e),
|
|
1044
1050
|
impact: "minor",
|
|
1045
|
-
message: `Alt text "${e.getAttribute("alt")}" contains redundant word(s)
|
|
1051
|
+
message: `Alt text "${e.getAttribute("alt")}" contains redundant word(s): ${n.join(", ")}.`,
|
|
1052
|
+
context: `Current alt: "${e.getAttribute("alt")}", redundant word(s): ${n.join(", ")}`
|
|
1046
1053
|
});
|
|
1047
1054
|
}
|
|
1048
1055
|
return a;
|
|
1049
1056
|
}
|
|
1050
|
-
},
|
|
1057
|
+
}, Ke = {
|
|
1051
1058
|
id: "area-alt",
|
|
1052
1059
|
wcag: ["1.1.1", "4.1.2"],
|
|
1053
1060
|
level: "A",
|
|
@@ -1060,8 +1067,8 @@ const Ve = {
|
|
|
1060
1067
|
if (p(e)) continue;
|
|
1061
1068
|
v(e) || a.push({
|
|
1062
1069
|
ruleId: "area-alt",
|
|
1063
|
-
selector:
|
|
1064
|
-
html:
|
|
1070
|
+
selector: m(e),
|
|
1071
|
+
html: u(e),
|
|
1065
1072
|
impact: "critical",
|
|
1066
1073
|
message: "Image map <area> element is missing alternative text."
|
|
1067
1074
|
});
|
|
@@ -1069,13 +1076,13 @@ const Ve = {
|
|
|
1069
1076
|
return a;
|
|
1070
1077
|
}
|
|
1071
1078
|
};
|
|
1072
|
-
function
|
|
1079
|
+
function Je(t) {
|
|
1073
1080
|
var n, r;
|
|
1074
1081
|
const a = t.getAttribute("aria-labelledby");
|
|
1075
1082
|
if (a) {
|
|
1076
1083
|
const o = a.split(/\s+/).map((s) => {
|
|
1077
|
-
var
|
|
1078
|
-
return ((h = (
|
|
1084
|
+
var l, h;
|
|
1085
|
+
return ((h = (l = t.ownerDocument.getElementById(s)) == null ? void 0 : l.textContent) == null ? void 0 : h.trim()) ?? "";
|
|
1079
1086
|
}).filter(Boolean);
|
|
1080
1087
|
if (o.length) return o.join(" ");
|
|
1081
1088
|
}
|
|
@@ -1104,7 +1111,7 @@ const Qe = {
|
|
|
1104
1111
|
}
|
|
1105
1112
|
n = n.parentElement;
|
|
1106
1113
|
}
|
|
1107
|
-
if (r || i.getAttribute("role") === "presentation" || i.getAttribute("role") === "none" ||
|
|
1114
|
+
if (r || i.getAttribute("role") === "presentation" || i.getAttribute("role") === "none" || Je(i)) continue;
|
|
1108
1115
|
const o = i.getAttribute("data") || "";
|
|
1109
1116
|
if (!((i.getAttribute("type") || "").startsWith("image/") || /\.(png|jpg|jpeg|gif|svg|webp|bmp|ico)$/i.test(o))) {
|
|
1110
1117
|
const h = i.querySelector("img[alt]");
|
|
@@ -1112,15 +1119,15 @@ const Qe = {
|
|
|
1112
1119
|
}
|
|
1113
1120
|
a.push({
|
|
1114
1121
|
ruleId: "object-alt",
|
|
1115
|
-
selector:
|
|
1116
|
-
html:
|
|
1122
|
+
selector: m(i),
|
|
1123
|
+
html: u(i),
|
|
1117
1124
|
impact: "serious",
|
|
1118
1125
|
message: "<object> element is missing alternative text. Add aria-label, aria-labelledby, or a title attribute."
|
|
1119
1126
|
});
|
|
1120
1127
|
}
|
|
1121
1128
|
return a;
|
|
1122
1129
|
}
|
|
1123
|
-
},
|
|
1130
|
+
}, Ze = {
|
|
1124
1131
|
id: "role-img-alt",
|
|
1125
1132
|
wcag: ["1.1.1"],
|
|
1126
1133
|
level: "A",
|
|
@@ -1133,8 +1140,8 @@ const Qe = {
|
|
|
1133
1140
|
if (p(e) || e.tagName.toLowerCase() === "svg" || e.tagName.toLowerCase() === "img") continue;
|
|
1134
1141
|
v(e) || a.push({
|
|
1135
1142
|
ruleId: "role-img-alt",
|
|
1136
|
-
selector:
|
|
1137
|
-
html:
|
|
1143
|
+
selector: m(e),
|
|
1144
|
+
html: u(e),
|
|
1138
1145
|
impact: "serious",
|
|
1139
1146
|
message: "Element with role='img' has no accessible name. Add aria-label or aria-labelledby."
|
|
1140
1147
|
});
|
|
@@ -1142,7 +1149,7 @@ const Qe = {
|
|
|
1142
1149
|
return a;
|
|
1143
1150
|
}
|
|
1144
1151
|
};
|
|
1145
|
-
function
|
|
1152
|
+
function Ai(t) {
|
|
1146
1153
|
if (typeof t != "object" || t === null)
|
|
1147
1154
|
return "Rule spec must be an object";
|
|
1148
1155
|
const a = t;
|
|
@@ -1172,10 +1179,10 @@ function yi(t) {
|
|
|
1172
1179
|
return "Rule must have a wcag array";
|
|
1173
1180
|
if (typeof a.level != "string" || !["A", "AA"].includes(a.level))
|
|
1174
1181
|
return "Rule must have level A or AA";
|
|
1175
|
-
const n =
|
|
1182
|
+
const n = et(e);
|
|
1176
1183
|
return n || null;
|
|
1177
1184
|
}
|
|
1178
|
-
function
|
|
1185
|
+
function et(t) {
|
|
1179
1186
|
switch (t.type) {
|
|
1180
1187
|
case "selector-exists":
|
|
1181
1188
|
return null;
|
|
@@ -1193,7 +1200,7 @@ function Ze(t) {
|
|
|
1193
1200
|
return `Unknown check type: ${String(t.type)}`;
|
|
1194
1201
|
}
|
|
1195
1202
|
}
|
|
1196
|
-
function
|
|
1203
|
+
function S(t, a, e) {
|
|
1197
1204
|
let i = t;
|
|
1198
1205
|
if (i.includes("{{tag}}") && (i = i.replace(/\{\{tag\}\}/g, a.tagName.toLowerCase())), i.includes("{{value}}")) {
|
|
1199
1206
|
let n = "";
|
|
@@ -1218,10 +1225,10 @@ function k(t) {
|
|
|
1218
1225
|
for (const n of e.querySelectorAll(t.selector))
|
|
1219
1226
|
a && p(n) || i.push({
|
|
1220
1227
|
ruleId: t.id,
|
|
1221
|
-
selector:
|
|
1222
|
-
html:
|
|
1228
|
+
selector: m(n),
|
|
1229
|
+
html: u(n),
|
|
1223
1230
|
impact: t.impact,
|
|
1224
|
-
message:
|
|
1231
|
+
message: S(t.message, n, t.check),
|
|
1225
1232
|
element: n
|
|
1226
1233
|
});
|
|
1227
1234
|
break;
|
|
@@ -1230,13 +1237,13 @@ function k(t) {
|
|
|
1230
1237
|
const { attribute: n, operator: r, value: o } = t.check;
|
|
1231
1238
|
for (const s of e.querySelectorAll(t.selector)) {
|
|
1232
1239
|
if (a && p(s)) continue;
|
|
1233
|
-
const
|
|
1234
|
-
|
|
1240
|
+
const l = s.getAttribute(n);
|
|
1241
|
+
l !== null && tt(l, r, o) && i.push({
|
|
1235
1242
|
ruleId: t.id,
|
|
1236
|
-
selector:
|
|
1237
|
-
html:
|
|
1243
|
+
selector: m(s),
|
|
1244
|
+
html: u(s),
|
|
1238
1245
|
impact: t.impact,
|
|
1239
|
-
message:
|
|
1246
|
+
message: S(t.message, s, t.check),
|
|
1240
1247
|
element: s
|
|
1241
1248
|
});
|
|
1242
1249
|
}
|
|
@@ -1247,40 +1254,40 @@ function k(t) {
|
|
|
1247
1254
|
for (const r of e.querySelectorAll(t.selector))
|
|
1248
1255
|
a && p(r) || r.hasAttribute(n) || i.push({
|
|
1249
1256
|
ruleId: t.id,
|
|
1250
|
-
selector:
|
|
1251
|
-
html:
|
|
1257
|
+
selector: m(r),
|
|
1258
|
+
html: u(r),
|
|
1252
1259
|
impact: t.impact,
|
|
1253
|
-
message:
|
|
1260
|
+
message: S(t.message, r, t.check),
|
|
1254
1261
|
element: r
|
|
1255
1262
|
});
|
|
1256
1263
|
break;
|
|
1257
1264
|
}
|
|
1258
1265
|
case "attribute-regex": {
|
|
1259
1266
|
const { attribute: n, pattern: r, flags: o, shouldMatch: s } = t.check;
|
|
1260
|
-
let
|
|
1267
|
+
let l;
|
|
1261
1268
|
try {
|
|
1262
|
-
|
|
1269
|
+
l = new RegExp(r, o);
|
|
1263
1270
|
} catch {
|
|
1264
1271
|
break;
|
|
1265
1272
|
}
|
|
1266
1273
|
for (const h of e.querySelectorAll(t.selector)) {
|
|
1267
1274
|
if (a && p(h)) continue;
|
|
1268
|
-
const
|
|
1269
|
-
if (
|
|
1270
|
-
const
|
|
1271
|
-
s && !
|
|
1275
|
+
const c = h.getAttribute(n);
|
|
1276
|
+
if (c === null) continue;
|
|
1277
|
+
const d = l.test(c);
|
|
1278
|
+
s && !d ? i.push({
|
|
1272
1279
|
ruleId: t.id,
|
|
1273
|
-
selector:
|
|
1274
|
-
html:
|
|
1280
|
+
selector: m(h),
|
|
1281
|
+
html: u(h),
|
|
1275
1282
|
impact: t.impact,
|
|
1276
|
-
message:
|
|
1283
|
+
message: S(t.message, h, t.check),
|
|
1277
1284
|
element: h
|
|
1278
|
-
}) : !s &&
|
|
1285
|
+
}) : !s && d && i.push({
|
|
1279
1286
|
ruleId: t.id,
|
|
1280
|
-
selector:
|
|
1281
|
-
html:
|
|
1287
|
+
selector: m(h),
|
|
1288
|
+
html: u(h),
|
|
1282
1289
|
impact: t.impact,
|
|
1283
|
-
message:
|
|
1290
|
+
message: S(t.message, h, t.check),
|
|
1284
1291
|
element: h
|
|
1285
1292
|
});
|
|
1286
1293
|
}
|
|
@@ -1291,10 +1298,10 @@ function k(t) {
|
|
|
1291
1298
|
for (const r of e.querySelectorAll(t.selector))
|
|
1292
1299
|
a && p(r) || r.querySelector(n) || i.push({
|
|
1293
1300
|
ruleId: t.id,
|
|
1294
|
-
selector:
|
|
1295
|
-
html:
|
|
1301
|
+
selector: m(r),
|
|
1302
|
+
html: u(r),
|
|
1296
1303
|
impact: t.impact,
|
|
1297
|
-
message:
|
|
1304
|
+
message: S(t.message, r, t.check),
|
|
1298
1305
|
element: r
|
|
1299
1306
|
});
|
|
1300
1307
|
break;
|
|
@@ -1309,10 +1316,10 @@ function k(t) {
|
|
|
1309
1316
|
if (!n.has(o.tagName.toLowerCase())) {
|
|
1310
1317
|
i.push({
|
|
1311
1318
|
ruleId: t.id,
|
|
1312
|
-
selector:
|
|
1313
|
-
html:
|
|
1319
|
+
selector: m(o),
|
|
1320
|
+
html: u(o),
|
|
1314
1321
|
impact: t.impact,
|
|
1315
|
-
message:
|
|
1322
|
+
message: S(t.message, o, t.check),
|
|
1316
1323
|
element: o
|
|
1317
1324
|
});
|
|
1318
1325
|
break;
|
|
@@ -1325,7 +1332,7 @@ function k(t) {
|
|
|
1325
1332
|
}
|
|
1326
1333
|
};
|
|
1327
1334
|
}
|
|
1328
|
-
function
|
|
1335
|
+
function tt(t, a, e) {
|
|
1329
1336
|
switch (a) {
|
|
1330
1337
|
case ">":
|
|
1331
1338
|
return parseFloat(t) > e;
|
|
@@ -1343,7 +1350,7 @@ function et(t, a, e) {
|
|
|
1343
1350
|
return !1;
|
|
1344
1351
|
}
|
|
1345
1352
|
}
|
|
1346
|
-
const
|
|
1353
|
+
const at = {
|
|
1347
1354
|
id: "server-side-image-map",
|
|
1348
1355
|
selector: "img[ismap], input[type='image'][ismap]",
|
|
1349
1356
|
check: { type: "selector-exists" },
|
|
@@ -1354,7 +1361,7 @@ const tt = {
|
|
|
1354
1361
|
level: "A",
|
|
1355
1362
|
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.",
|
|
1356
1363
|
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."
|
|
1357
|
-
},
|
|
1364
|
+
}, it = k(at), nt = [
|
|
1358
1365
|
'[role="checkbox"]',
|
|
1359
1366
|
'[role="combobox"]',
|
|
1360
1367
|
'[role="listbox"]',
|
|
@@ -1366,13 +1373,13 @@ const tt = {
|
|
|
1366
1373
|
'[role="spinbutton"]',
|
|
1367
1374
|
'[role="switch"]',
|
|
1368
1375
|
'[role="textbox"]'
|
|
1369
|
-
].join(", "),
|
|
1376
|
+
].join(", "), rt = /* @__PURE__ */ new Set([
|
|
1370
1377
|
"checkbox",
|
|
1371
1378
|
"menuitemcheckbox",
|
|
1372
1379
|
"menuitemradio",
|
|
1373
1380
|
"radio",
|
|
1374
1381
|
"switch"
|
|
1375
|
-
]),
|
|
1382
|
+
]), ot = /* @__PURE__ */ new Set([
|
|
1376
1383
|
"combobox",
|
|
1377
1384
|
"listbox",
|
|
1378
1385
|
"searchbox",
|
|
@@ -1380,68 +1387,78 @@ const tt = {
|
|
|
1380
1387
|
"spinbutton",
|
|
1381
1388
|
"textbox"
|
|
1382
1389
|
]);
|
|
1383
|
-
function
|
|
1384
|
-
var o, s,
|
|
1390
|
+
function st(t) {
|
|
1391
|
+
var o, s, l, h;
|
|
1385
1392
|
const a = (o = t.getAttribute("role")) == null ? void 0 : o.trim().toLowerCase();
|
|
1386
|
-
if (a &&
|
|
1393
|
+
if (a && rt.has(a) || (t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement) && !(a && ot.has(a)))
|
|
1387
1394
|
return v(t);
|
|
1388
1395
|
const i = t.getAttribute("aria-labelledby");
|
|
1389
1396
|
if (i) {
|
|
1390
|
-
const
|
|
1391
|
-
const g = t.ownerDocument.getElementById(
|
|
1392
|
-
return g ?
|
|
1397
|
+
const c = i.split(/\s+/).map((d) => {
|
|
1398
|
+
const g = t.ownerDocument.getElementById(d);
|
|
1399
|
+
return g ? w(g).trim() : "";
|
|
1393
1400
|
}).filter(Boolean);
|
|
1394
|
-
if (
|
|
1401
|
+
if (c.length) return c.join(" ");
|
|
1395
1402
|
}
|
|
1396
1403
|
const n = (s = t.getAttribute("aria-label")) == null ? void 0 : s.trim();
|
|
1397
1404
|
if (n) return n;
|
|
1398
1405
|
if (t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement || t instanceof HTMLSelectElement) {
|
|
1399
1406
|
if (t.id) {
|
|
1400
|
-
const
|
|
1401
|
-
if (
|
|
1402
|
-
const g =
|
|
1407
|
+
const d = t.ownerDocument.querySelector(`label[for="${CSS.escape(t.id)}"]`);
|
|
1408
|
+
if (d) {
|
|
1409
|
+
const g = w(d).trim();
|
|
1403
1410
|
if (g) return g;
|
|
1404
1411
|
}
|
|
1405
1412
|
}
|
|
1406
|
-
const
|
|
1407
|
-
if (
|
|
1408
|
-
const
|
|
1409
|
-
if (
|
|
1413
|
+
const c = t.closest("label");
|
|
1414
|
+
if (c) {
|
|
1415
|
+
const d = w(c).trim();
|
|
1416
|
+
if (d) return d;
|
|
1410
1417
|
}
|
|
1411
1418
|
}
|
|
1412
|
-
const r = (
|
|
1419
|
+
const r = (l = t.getAttribute("title")) == null ? void 0 : l.trim();
|
|
1413
1420
|
if (r) return r;
|
|
1414
1421
|
if (t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement) {
|
|
1415
|
-
const
|
|
1416
|
-
if (
|
|
1422
|
+
const c = (h = t.getAttribute("placeholder")) == null ? void 0 : h.trim();
|
|
1423
|
+
if (c) return c;
|
|
1417
1424
|
}
|
|
1418
1425
|
return "";
|
|
1419
1426
|
}
|
|
1420
|
-
const
|
|
1427
|
+
const lt = {
|
|
1421
1428
|
id: "label",
|
|
1422
1429
|
wcag: ["4.1.2"],
|
|
1423
1430
|
level: "A",
|
|
1424
1431
|
description: "Form elements must have labels. Use <label>, aria-label, or aria-labelledby.",
|
|
1425
1432
|
guidance: "Every form input needs an accessible label so users understand what information to enter. Use a <label> element with a for attribute matching the input's id, wrap the input in a <label>, or use aria-label/aria-labelledby for custom components. Placeholders are not sufficient as labels since they disappear when typing.",
|
|
1426
|
-
prompt:
|
|
1433
|
+
prompt: `This form field has no accessible label. Based on the context (input type, name attribute, placeholder, or surrounding elements), suggest adding a <label for="id"> element with descriptive text, or an aria-label attribute. The label should describe what information the user should enter, not the field type. For example: 'Email address', 'Search', 'Phone number'.`,
|
|
1427
1434
|
run(t) {
|
|
1428
1435
|
var n;
|
|
1429
|
-
const a = [], i = t.querySelectorAll(`input:not([type="hidden"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="image"]), textarea, select, ${
|
|
1436
|
+
const a = [], i = t.querySelectorAll(`input:not([type="hidden"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="image"]), textarea, select, ${nt}`);
|
|
1430
1437
|
for (const r of i) {
|
|
1431
1438
|
if (p(r) || r instanceof HTMLElement && (r.hidden || r.style.display === "none")) continue;
|
|
1432
1439
|
const o = (n = r.getAttribute("role")) == null ? void 0 : n.trim().toLowerCase();
|
|
1433
1440
|
if (o === "presentation" || o === "none") continue;
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
+
if (!st(r)) {
|
|
1442
|
+
const l = [], h = r.tagName.toLowerCase(), c = r.getAttribute("type");
|
|
1443
|
+
c && h === "input" && l.push(`type: ${c}`);
|
|
1444
|
+
const d = r.getAttribute("name");
|
|
1445
|
+
d && l.push(`name: "${d}"`);
|
|
1446
|
+
const g = r.getAttribute("placeholder");
|
|
1447
|
+
g && l.push(`placeholder: "${g}"`), o && l.push(`role: ${o}`);
|
|
1448
|
+
const b = r.getAttribute("id");
|
|
1449
|
+
b && l.push(`id: "${b}"`), a.push({
|
|
1450
|
+
ruleId: "label",
|
|
1451
|
+
selector: m(r),
|
|
1452
|
+
html: u(r),
|
|
1453
|
+
impact: "critical",
|
|
1454
|
+
message: "Form element has no accessible label.",
|
|
1455
|
+
context: l.length > 0 ? l.join(", ") : void 0
|
|
1456
|
+
});
|
|
1457
|
+
}
|
|
1441
1458
|
}
|
|
1442
1459
|
return a;
|
|
1443
1460
|
}
|
|
1444
|
-
},
|
|
1461
|
+
}, ct = {
|
|
1445
1462
|
id: "form-field-multiple-labels",
|
|
1446
1463
|
wcag: [],
|
|
1447
1464
|
level: "A",
|
|
@@ -1465,15 +1482,15 @@ const st = {
|
|
|
1465
1482
|
const s = n.length + r;
|
|
1466
1483
|
s > 1 && a.push({
|
|
1467
1484
|
ruleId: "form-field-multiple-labels",
|
|
1468
|
-
selector:
|
|
1469
|
-
html:
|
|
1485
|
+
selector: m(i),
|
|
1486
|
+
html: u(i),
|
|
1470
1487
|
impact: "moderate",
|
|
1471
1488
|
message: `Form field has ${s} labels. Use a single label element.`
|
|
1472
1489
|
});
|
|
1473
1490
|
}
|
|
1474
1491
|
return a;
|
|
1475
1492
|
}
|
|
1476
|
-
},
|
|
1493
|
+
}, ut = {
|
|
1477
1494
|
id: "select-name",
|
|
1478
1495
|
wcag: ["4.1.2"],
|
|
1479
1496
|
level: "A",
|
|
@@ -1485,14 +1502,14 @@ const st = {
|
|
|
1485
1502
|
for (const e of t.querySelectorAll("select"))
|
|
1486
1503
|
p(e) || v(e) || a.push({
|
|
1487
1504
|
ruleId: "select-name",
|
|
1488
|
-
selector:
|
|
1489
|
-
html:
|
|
1505
|
+
selector: m(e),
|
|
1506
|
+
html: u(e),
|
|
1490
1507
|
impact: "critical",
|
|
1491
1508
|
message: "Select element has no accessible name."
|
|
1492
1509
|
});
|
|
1493
1510
|
return a;
|
|
1494
1511
|
}
|
|
1495
|
-
},
|
|
1512
|
+
}, dt = {
|
|
1496
1513
|
id: "input-button-name",
|
|
1497
1514
|
wcag: ["4.1.2"],
|
|
1498
1515
|
level: "A",
|
|
@@ -1509,15 +1526,15 @@ const st = {
|
|
|
1509
1526
|
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");
|
|
1510
1527
|
!r && !s && !v(n) && a.push({
|
|
1511
1528
|
ruleId: "input-button-name",
|
|
1512
|
-
selector:
|
|
1513
|
-
html:
|
|
1529
|
+
selector: m(n),
|
|
1530
|
+
html: u(n),
|
|
1514
1531
|
impact: "critical",
|
|
1515
1532
|
message: "Input button has no discernible text."
|
|
1516
1533
|
});
|
|
1517
1534
|
}
|
|
1518
1535
|
return a;
|
|
1519
1536
|
}
|
|
1520
|
-
},
|
|
1537
|
+
}, mt = /* @__PURE__ */ new Set([
|
|
1521
1538
|
"off",
|
|
1522
1539
|
"on",
|
|
1523
1540
|
"name",
|
|
@@ -1572,7 +1589,7 @@ const st = {
|
|
|
1572
1589
|
"impp",
|
|
1573
1590
|
"url",
|
|
1574
1591
|
"photo"
|
|
1575
|
-
]),
|
|
1592
|
+
]), ht = /* @__PURE__ */ new Set([
|
|
1576
1593
|
"tel",
|
|
1577
1594
|
"tel-country-code",
|
|
1578
1595
|
"tel-national",
|
|
@@ -1581,18 +1598,18 @@ const st = {
|
|
|
1581
1598
|
"tel-extension",
|
|
1582
1599
|
"email",
|
|
1583
1600
|
"impp"
|
|
1584
|
-
]),
|
|
1585
|
-
function
|
|
1601
|
+
]), pt = /* @__PURE__ */ new Set(["home", "work", "mobile", "fax", "pager"]), gt = /* @__PURE__ */ new Set(["shipping", "billing"]), bt = /* @__PURE__ */ new Set(["webauthn"]);
|
|
1602
|
+
function ft(t) {
|
|
1586
1603
|
const a = t.toLowerCase().split(/\s+/).filter(Boolean);
|
|
1587
1604
|
if (a.length === 0) return !0;
|
|
1588
1605
|
let e = 0;
|
|
1589
|
-
a[e].startsWith("section-") && e++, e < a.length &&
|
|
1606
|
+
a[e].startsWith("section-") && e++, e < a.length && gt.has(a[e]) && e++;
|
|
1590
1607
|
let i = !1;
|
|
1591
|
-
if (e < a.length &&
|
|
1608
|
+
if (e < a.length && pt.has(a[e]) && (i = !0, e++), e >= a.length) return !1;
|
|
1592
1609
|
const n = a[e];
|
|
1593
|
-
return !
|
|
1610
|
+
return !mt.has(n) || i && !ht.has(n) ? !1 : (e++, e < a.length && bt.has(a[e]) && e++, e === a.length);
|
|
1594
1611
|
}
|
|
1595
|
-
const
|
|
1612
|
+
const vt = {
|
|
1596
1613
|
id: "autocomplete-valid",
|
|
1597
1614
|
wcag: ["1.3.5"],
|
|
1598
1615
|
level: "AA",
|
|
@@ -1604,10 +1621,10 @@ const ft = {
|
|
|
1604
1621
|
for (const e of t.querySelectorAll("[autocomplete]")) {
|
|
1605
1622
|
if (p(e) || e instanceof HTMLElement && e.style.display === "none" || e.disabled || e.getAttribute("aria-disabled") === "true") continue;
|
|
1606
1623
|
const i = e.getAttribute("autocomplete").trim();
|
|
1607
|
-
i && (
|
|
1624
|
+
i && (ft(i) || a.push({
|
|
1608
1625
|
ruleId: "autocomplete-valid",
|
|
1609
|
-
selector:
|
|
1610
|
-
html:
|
|
1626
|
+
selector: m(e),
|
|
1627
|
+
html: u(e),
|
|
1611
1628
|
impact: "serious",
|
|
1612
1629
|
message: `Invalid autocomplete value "${i}".`
|
|
1613
1630
|
}));
|
|
@@ -1638,7 +1655,7 @@ function V(t) {
|
|
|
1638
1655
|
}
|
|
1639
1656
|
return a;
|
|
1640
1657
|
}
|
|
1641
|
-
const
|
|
1658
|
+
const yt = {
|
|
1642
1659
|
id: "label-content-name-mismatch",
|
|
1643
1660
|
wcag: ["2.5.3"],
|
|
1644
1661
|
level: "A",
|
|
@@ -1658,8 +1675,8 @@ const vt = {
|
|
|
1658
1675
|
const o = e.hasAttribute("aria-label"), s = e.hasAttribute("aria-labelledby");
|
|
1659
1676
|
!o && !s || ee(i, n) || a.push({
|
|
1660
1677
|
ruleId: "label-content-name-mismatch",
|
|
1661
|
-
selector:
|
|
1662
|
-
html:
|
|
1678
|
+
selector: m(e),
|
|
1679
|
+
html: u(e),
|
|
1663
1680
|
impact: "serious",
|
|
1664
1681
|
message: `Accessible name "${i}" does not contain visible text "${n.trim()}".`
|
|
1665
1682
|
});
|
|
@@ -1676,8 +1693,8 @@ const vt = {
|
|
|
1676
1693
|
}
|
|
1677
1694
|
o.trim() && (ee(i, o) || a.push({
|
|
1678
1695
|
ruleId: "label-content-name-mismatch",
|
|
1679
|
-
selector:
|
|
1680
|
-
html:
|
|
1696
|
+
selector: m(e),
|
|
1697
|
+
html: u(e),
|
|
1681
1698
|
impact: "serious",
|
|
1682
1699
|
message: `Accessible name "${i}" does not contain visible label "${o.trim()}".`
|
|
1683
1700
|
}));
|
|
@@ -1699,25 +1716,25 @@ const vt = {
|
|
|
1699
1716
|
);
|
|
1700
1717
|
for (const s of e) {
|
|
1701
1718
|
if (p(s)) continue;
|
|
1702
|
-
const
|
|
1703
|
-
let
|
|
1719
|
+
const l = 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()), c = s.hasAttribute("aria-labelledby");
|
|
1720
|
+
let d = !1;
|
|
1704
1721
|
const g = s.id;
|
|
1705
1722
|
if (g) {
|
|
1706
1723
|
const f = s.ownerDocument.querySelector(`label[for="${CSS.escape(g)}"]`);
|
|
1707
|
-
(r = f == null ? void 0 : f.textContent) != null && r.trim() && (
|
|
1724
|
+
(r = f == null ? void 0 : f.textContent) != null && r.trim() && (d = !0);
|
|
1708
1725
|
}
|
|
1709
1726
|
const b = s.closest("label");
|
|
1710
|
-
(o = b == null ? void 0 : b.textContent) != null && o.trim() && (
|
|
1727
|
+
(o = b == null ? void 0 : b.textContent) != null && o.trim() && (d = !0), l && !h && !c && !d && a.push({
|
|
1711
1728
|
ruleId: "label-title-only",
|
|
1712
|
-
selector:
|
|
1713
|
-
html:
|
|
1729
|
+
selector: m(s),
|
|
1730
|
+
html: u(s),
|
|
1714
1731
|
impact: "serious",
|
|
1715
1732
|
message: "Form element uses title attribute as only label. Use <label>, aria-label, or aria-labelledby instead."
|
|
1716
1733
|
});
|
|
1717
1734
|
}
|
|
1718
1735
|
return a;
|
|
1719
1736
|
}
|
|
1720
|
-
},
|
|
1737
|
+
}, At = {
|
|
1721
1738
|
id: "tabindex",
|
|
1722
1739
|
selector: "[tabindex]",
|
|
1723
1740
|
check: { type: "attribute-value", attribute: "tabindex", operator: ">", value: 0 },
|
|
@@ -1729,7 +1746,7 @@ const vt = {
|
|
|
1729
1746
|
tags: ["best-practice"],
|
|
1730
1747
|
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.",
|
|
1731
1748
|
prompt: "Change the positive tabindex value to tabindex='0' and rely on DOM order for tab sequence instead."
|
|
1732
|
-
},
|
|
1749
|
+
}, xt = k(At), St = /* @__PURE__ */ new Set([
|
|
1733
1750
|
"div",
|
|
1734
1751
|
"span",
|
|
1735
1752
|
"p",
|
|
@@ -1756,7 +1773,7 @@ const vt = {
|
|
|
1756
1773
|
"tr",
|
|
1757
1774
|
"td",
|
|
1758
1775
|
"th"
|
|
1759
|
-
]),
|
|
1776
|
+
]), kt = {
|
|
1760
1777
|
id: "focus-order-semantics",
|
|
1761
1778
|
wcag: [],
|
|
1762
1779
|
tags: ["best-practice"],
|
|
@@ -1771,15 +1788,15 @@ const vt = {
|
|
|
1771
1788
|
if (!St.has(i)) continue;
|
|
1772
1789
|
e.getAttribute("role") || a.push({
|
|
1773
1790
|
ruleId: "focus-order-semantics",
|
|
1774
|
-
selector:
|
|
1775
|
-
html:
|
|
1791
|
+
selector: m(e),
|
|
1792
|
+
html: u(e),
|
|
1776
1793
|
impact: "moderate",
|
|
1777
1794
|
message: `Non-interactive <${i}> with tabindex="0" has no interactive role.`
|
|
1778
1795
|
});
|
|
1779
1796
|
}
|
|
1780
1797
|
return a;
|
|
1781
1798
|
}
|
|
1782
|
-
},
|
|
1799
|
+
}, It = /* @__PURE__ */ new Set([
|
|
1783
1800
|
"a",
|
|
1784
1801
|
"audio",
|
|
1785
1802
|
"button",
|
|
@@ -1788,7 +1805,7 @@ const vt = {
|
|
|
1788
1805
|
"select",
|
|
1789
1806
|
"textarea",
|
|
1790
1807
|
"video"
|
|
1791
|
-
]),
|
|
1808
|
+
]), Tt = /* @__PURE__ */ new Set([
|
|
1792
1809
|
"button",
|
|
1793
1810
|
"checkbox",
|
|
1794
1811
|
"combobox",
|
|
@@ -1822,7 +1839,7 @@ const vt = {
|
|
|
1822
1839
|
tree: /* @__PURE__ */ new Set(["treeitem"]),
|
|
1823
1840
|
treegrid: /* @__PURE__ */ new Set(["gridcell", "row", "columnheader", "rowheader", "treeitem"])
|
|
1824
1841
|
};
|
|
1825
|
-
function
|
|
1842
|
+
function Ct(t, a) {
|
|
1826
1843
|
var n, r, o;
|
|
1827
1844
|
const e = (n = t.getAttribute("role")) == null ? void 0 : n.toLowerCase(), i = (r = a.getAttribute("role")) == null ? void 0 : r.toLowerCase();
|
|
1828
1845
|
return !e || !i ? !1 : ((o = Et[e]) == null ? void 0 : o.has(i)) ?? !1;
|
|
@@ -1830,18 +1847,18 @@ function Tt(t, a) {
|
|
|
1830
1847
|
function Lt(t) {
|
|
1831
1848
|
var n;
|
|
1832
1849
|
const a = t.tagName.toLowerCase();
|
|
1833
|
-
if (
|
|
1850
|
+
if (It.has(a))
|
|
1834
1851
|
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);
|
|
1835
1852
|
const e = (n = t.getAttribute("role")) == null ? void 0 : n.toLowerCase();
|
|
1836
|
-
if (e &&
|
|
1853
|
+
if (e && Tt.has(e)) return !0;
|
|
1837
1854
|
const i = t.getAttribute("tabindex");
|
|
1838
1855
|
return i !== null && i !== "-1" || t.getAttribute("contenteditable") === "true";
|
|
1839
1856
|
}
|
|
1840
|
-
function
|
|
1857
|
+
function qt(t) {
|
|
1841
1858
|
const a = t.tagName.toLowerCase();
|
|
1842
1859
|
return !!(a === "a" && t.hasAttribute("href") || a === "button" && !t.disabled);
|
|
1843
1860
|
}
|
|
1844
|
-
const
|
|
1861
|
+
const Rt = {
|
|
1845
1862
|
id: "nested-interactive",
|
|
1846
1863
|
wcag: ["4.1.2"],
|
|
1847
1864
|
level: "A",
|
|
@@ -1859,21 +1876,21 @@ const qt = {
|
|
|
1859
1876
|
if (!p(o) && Lt(o)) {
|
|
1860
1877
|
if (r.length > 0) {
|
|
1861
1878
|
const s = r[r.length - 1];
|
|
1862
|
-
|
|
1879
|
+
Ct(s, o) || a.push({
|
|
1863
1880
|
ruleId: "nested-interactive",
|
|
1864
|
-
selector:
|
|
1865
|
-
html:
|
|
1881
|
+
selector: m(o),
|
|
1882
|
+
html: u(o),
|
|
1866
1883
|
impact: "serious",
|
|
1867
1884
|
message: `Interactive element <${o.tagName.toLowerCase()}> is nested inside <${s.tagName.toLowerCase()}>.`
|
|
1868
1885
|
});
|
|
1869
1886
|
}
|
|
1870
|
-
|
|
1887
|
+
qt(o) && r.push(o);
|
|
1871
1888
|
}
|
|
1872
1889
|
o = n.nextNode();
|
|
1873
1890
|
}
|
|
1874
1891
|
return a;
|
|
1875
1892
|
}
|
|
1876
|
-
},
|
|
1893
|
+
}, Nt = {
|
|
1877
1894
|
id: "scrollable-region-focusable",
|
|
1878
1895
|
wcag: ["2.1.1"],
|
|
1879
1896
|
level: "A",
|
|
@@ -1889,23 +1906,23 @@ const qt = {
|
|
|
1889
1906
|
if (e.scrollHeight > 0 || e.clientHeight > 0) {
|
|
1890
1907
|
if (e.scrollHeight <= e.clientHeight && e.scrollWidth <= e.clientWidth) continue;
|
|
1891
1908
|
} else {
|
|
1892
|
-
const
|
|
1893
|
-
if (!
|
|
1909
|
+
const c = i.height !== "" || i.maxHeight !== "", d = e.textContent != null && e.textContent.trim().length > 0;
|
|
1910
|
+
if (!c || !d) continue;
|
|
1894
1911
|
}
|
|
1895
|
-
const
|
|
1896
|
-
|
|
1912
|
+
const l = e.getAttribute("tabindex");
|
|
1913
|
+
l !== null && l !== "-1" || e.querySelector(
|
|
1897
1914
|
'a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
1898
1915
|
) || a.push({
|
|
1899
1916
|
ruleId: "scrollable-region-focusable",
|
|
1900
|
-
selector:
|
|
1901
|
-
html:
|
|
1917
|
+
selector: m(e),
|
|
1918
|
+
html: u(e),
|
|
1902
1919
|
impact: "serious",
|
|
1903
1920
|
message: "Scrollable region is not keyboard accessible. Add tabindex='0' or include focusable elements."
|
|
1904
1921
|
});
|
|
1905
1922
|
}
|
|
1906
1923
|
return a;
|
|
1907
1924
|
}
|
|
1908
|
-
},
|
|
1925
|
+
}, $t = {
|
|
1909
1926
|
id: "accesskeys",
|
|
1910
1927
|
wcag: [],
|
|
1911
1928
|
level: "A",
|
|
@@ -1928,8 +1945,8 @@ const qt = {
|
|
|
1928
1945
|
for (const o of r.slice(1))
|
|
1929
1946
|
a.push({
|
|
1930
1947
|
ruleId: "accesskeys",
|
|
1931
|
-
selector:
|
|
1932
|
-
html:
|
|
1948
|
+
selector: m(o),
|
|
1949
|
+
html: u(o),
|
|
1933
1950
|
impact: "serious",
|
|
1934
1951
|
message: `Duplicate accesskey "${n}". Each accesskey must be unique.`
|
|
1935
1952
|
});
|
|
@@ -1951,16 +1968,16 @@ const qt = {
|
|
|
1951
1968
|
let o;
|
|
1952
1969
|
r.hasAttribute("aria-level") ? o = parseInt(r.getAttribute("aria-level"), 10) : o = parseInt(r.tagName[1], 10), i > 0 && o > i + 1 && a.push({
|
|
1953
1970
|
ruleId: "heading-order",
|
|
1954
|
-
selector:
|
|
1955
|
-
html:
|
|
1971
|
+
selector: m(r),
|
|
1972
|
+
html: u(r),
|
|
1956
1973
|
impact: "moderate",
|
|
1957
1974
|
message: `Heading level ${o} skipped from level ${i}.`,
|
|
1958
|
-
context: n ? `Previous heading: ${
|
|
1975
|
+
context: n ? `Previous heading: ${u(n)}` : void 0
|
|
1959
1976
|
}), i = o, n = r;
|
|
1960
1977
|
}
|
|
1961
1978
|
return a;
|
|
1962
1979
|
}
|
|
1963
|
-
}, N = 'article, aside, main, nav, section, [role="article"], [role="complementary"], [role="main"], [role="navigation"], [role="region"]', te = '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"]',
|
|
1980
|
+
}, N = 'article, aside, main, nav, section, [role="article"], [role="complementary"], [role="main"], [role="navigation"], [role="region"]', te = '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"]', Ht = {
|
|
1964
1981
|
id: "landmark-one-main",
|
|
1965
1982
|
wcag: [],
|
|
1966
1983
|
level: "A",
|
|
@@ -1978,13 +1995,13 @@ const qt = {
|
|
|
1978
1995
|
message: "Page has no main landmark."
|
|
1979
1996
|
}] : a.length > 1 ? Array.from(a).slice(1).map((e) => ({
|
|
1980
1997
|
ruleId: "landmark-one-main",
|
|
1981
|
-
selector:
|
|
1982
|
-
html:
|
|
1998
|
+
selector: m(e),
|
|
1999
|
+
html: u(e),
|
|
1983
2000
|
impact: "moderate",
|
|
1984
2001
|
message: "Page has multiple main landmarks."
|
|
1985
2002
|
})) : [];
|
|
1986
2003
|
}
|
|
1987
|
-
},
|
|
2004
|
+
}, Dt = {
|
|
1988
2005
|
id: "landmark-no-duplicate-banner",
|
|
1989
2006
|
wcag: [],
|
|
1990
2007
|
level: "A",
|
|
@@ -1997,14 +2014,14 @@ const qt = {
|
|
|
1997
2014
|
return i.length > 1 && i.slice(1).forEach(
|
|
1998
2015
|
(n) => a.push({
|
|
1999
2016
|
ruleId: "landmark-no-duplicate-banner",
|
|
2000
|
-
selector:
|
|
2001
|
-
html:
|
|
2017
|
+
selector: m(n),
|
|
2018
|
+
html: u(n),
|
|
2002
2019
|
impact: "moderate",
|
|
2003
2020
|
message: "Page has multiple banner landmarks."
|
|
2004
2021
|
})
|
|
2005
2022
|
), a;
|
|
2006
2023
|
}
|
|
2007
|
-
},
|
|
2024
|
+
}, Ot = {
|
|
2008
2025
|
id: "landmark-no-duplicate-contentinfo",
|
|
2009
2026
|
wcag: [],
|
|
2010
2027
|
level: "A",
|
|
@@ -2017,14 +2034,14 @@ const qt = {
|
|
|
2017
2034
|
return i.length > 1 && i.slice(1).forEach(
|
|
2018
2035
|
(n) => a.push({
|
|
2019
2036
|
ruleId: "landmark-no-duplicate-contentinfo",
|
|
2020
|
-
selector:
|
|
2021
|
-
html:
|
|
2037
|
+
selector: m(n),
|
|
2038
|
+
html: u(n),
|
|
2022
2039
|
impact: "moderate",
|
|
2023
2040
|
message: "Page has multiple contentinfo landmarks."
|
|
2024
2041
|
})
|
|
2025
2042
|
), a;
|
|
2026
2043
|
}
|
|
2027
|
-
},
|
|
2044
|
+
}, Bt = {
|
|
2028
2045
|
id: "landmark-no-duplicate-main",
|
|
2029
2046
|
wcag: [],
|
|
2030
2047
|
level: "A",
|
|
@@ -2037,14 +2054,14 @@ const qt = {
|
|
|
2037
2054
|
return e.length > 1 && Array.from(e).slice(1).forEach(
|
|
2038
2055
|
(i) => a.push({
|
|
2039
2056
|
ruleId: "landmark-no-duplicate-main",
|
|
2040
|
-
selector:
|
|
2041
|
-
html:
|
|
2057
|
+
selector: m(i),
|
|
2058
|
+
html: u(i),
|
|
2042
2059
|
impact: "moderate",
|
|
2043
2060
|
message: "Page has multiple main landmarks."
|
|
2044
2061
|
})
|
|
2045
2062
|
), a;
|
|
2046
2063
|
}
|
|
2047
|
-
},
|
|
2064
|
+
}, Ft = {
|
|
2048
2065
|
id: "landmark-banner-is-top-level",
|
|
2049
2066
|
wcag: [],
|
|
2050
2067
|
level: "A",
|
|
@@ -2057,14 +2074,14 @@ const qt = {
|
|
|
2057
2074
|
for (const i of e)
|
|
2058
2075
|
i.closest(N) && a.push({
|
|
2059
2076
|
ruleId: "landmark-banner-is-top-level",
|
|
2060
|
-
selector:
|
|
2061
|
-
html:
|
|
2077
|
+
selector: m(i),
|
|
2078
|
+
html: u(i),
|
|
2062
2079
|
impact: "moderate",
|
|
2063
2080
|
message: "Banner landmark is nested within another landmark."
|
|
2064
2081
|
});
|
|
2065
2082
|
return a;
|
|
2066
2083
|
}
|
|
2067
|
-
},
|
|
2084
|
+
}, Wt = {
|
|
2068
2085
|
id: "landmark-contentinfo-is-top-level",
|
|
2069
2086
|
wcag: [],
|
|
2070
2087
|
level: "A",
|
|
@@ -2077,8 +2094,8 @@ const qt = {
|
|
|
2077
2094
|
for (const i of e)
|
|
2078
2095
|
i.closest(N) && a.push({
|
|
2079
2096
|
ruleId: "landmark-contentinfo-is-top-level",
|
|
2080
|
-
selector:
|
|
2081
|
-
html:
|
|
2097
|
+
selector: m(i),
|
|
2098
|
+
html: u(i),
|
|
2082
2099
|
impact: "moderate",
|
|
2083
2100
|
message: "Contentinfo landmark is nested within another landmark."
|
|
2084
2101
|
});
|
|
@@ -2098,15 +2115,15 @@ const qt = {
|
|
|
2098
2115
|
const n = i.parentElement;
|
|
2099
2116
|
n != null && n.closest('article, aside, nav, section, [role="article"], [role="complementary"], [role="navigation"], [role="region"]') && a.push({
|
|
2100
2117
|
ruleId: "landmark-main-is-top-level",
|
|
2101
|
-
selector:
|
|
2102
|
-
html:
|
|
2118
|
+
selector: m(i),
|
|
2119
|
+
html: u(i),
|
|
2103
2120
|
impact: "moderate",
|
|
2104
2121
|
message: "Main landmark is nested within another landmark."
|
|
2105
2122
|
});
|
|
2106
2123
|
}
|
|
2107
2124
|
return a;
|
|
2108
2125
|
}
|
|
2109
|
-
},
|
|
2126
|
+
}, Pt = {
|
|
2110
2127
|
id: "landmark-complementary-is-top-level",
|
|
2111
2128
|
wcag: [],
|
|
2112
2129
|
level: "A",
|
|
@@ -2120,8 +2137,8 @@ const qt = {
|
|
|
2120
2137
|
const n = i.parentElement;
|
|
2121
2138
|
n && !n.matches('body, main, [role="main"]') && i.closest('article, nav, section, [role="article"], [role="navigation"], [role="region"]') && a.push({
|
|
2122
2139
|
ruleId: "landmark-complementary-is-top-level",
|
|
2123
|
-
selector:
|
|
2124
|
-
html:
|
|
2140
|
+
selector: m(i),
|
|
2141
|
+
html: u(i),
|
|
2125
2142
|
impact: "moderate",
|
|
2126
2143
|
message: "Complementary landmark should be top-level."
|
|
2127
2144
|
});
|
|
@@ -2148,23 +2165,23 @@ const qt = {
|
|
|
2148
2165
|
if (r.length <= 1) continue;
|
|
2149
2166
|
const o = /* @__PURE__ */ new Map();
|
|
2150
2167
|
for (const s of r) {
|
|
2151
|
-
const
|
|
2152
|
-
h.push(s), o.set(
|
|
2168
|
+
const l = v(s).toLowerCase() || "", h = o.get(l) || [];
|
|
2169
|
+
h.push(s), o.set(l, h);
|
|
2153
2170
|
}
|
|
2154
|
-
for (const [s,
|
|
2155
|
-
if (
|
|
2156
|
-
for (const h of
|
|
2171
|
+
for (const [s, l] of o)
|
|
2172
|
+
if (l.length > 1)
|
|
2173
|
+
for (const h of l.slice(1))
|
|
2157
2174
|
a.push({
|
|
2158
2175
|
ruleId: "landmark-unique",
|
|
2159
|
-
selector:
|
|
2160
|
-
html:
|
|
2176
|
+
selector: m(h),
|
|
2177
|
+
html: u(h),
|
|
2161
2178
|
impact: "moderate",
|
|
2162
2179
|
message: s ? `Multiple ${n} landmarks have the same label "${s}".` : `Multiple ${n} landmarks have no label. Add unique aria-label attributes.`
|
|
2163
2180
|
});
|
|
2164
2181
|
}
|
|
2165
2182
|
return a;
|
|
2166
2183
|
}
|
|
2167
|
-
},
|
|
2184
|
+
}, Vt = {
|
|
2168
2185
|
id: "region",
|
|
2169
2186
|
wcag: [],
|
|
2170
2187
|
level: "A",
|
|
@@ -2181,15 +2198,15 @@ const qt = {
|
|
|
2181
2198
|
const r = n.matches(te), o = (i = n.textContent) == null ? void 0 : i.trim();
|
|
2182
2199
|
!r && o && (n.querySelector(te) || a.push({
|
|
2183
2200
|
ruleId: "region",
|
|
2184
|
-
selector:
|
|
2185
|
-
html:
|
|
2201
|
+
selector: m(n),
|
|
2202
|
+
html: u(n),
|
|
2186
2203
|
impact: "moderate",
|
|
2187
2204
|
message: "Content is not contained within a landmark region."
|
|
2188
2205
|
}));
|
|
2189
2206
|
}
|
|
2190
2207
|
return a;
|
|
2191
2208
|
}
|
|
2192
|
-
},
|
|
2209
|
+
}, zt = {
|
|
2193
2210
|
id: "list",
|
|
2194
2211
|
selector: "ul, ol",
|
|
2195
2212
|
check: { type: "child-invalid", allowedChildren: ["li", "script", "template"] },
|
|
@@ -2200,7 +2217,7 @@ const qt = {
|
|
|
2200
2217
|
level: "A",
|
|
2201
2218
|
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.",
|
|
2202
2219
|
prompt: "Explain how to restructure this element within the list properly."
|
|
2203
|
-
},
|
|
2220
|
+
}, Ut = k(zt), Gt = {
|
|
2204
2221
|
id: "dlitem",
|
|
2205
2222
|
wcag: ["1.3.1"],
|
|
2206
2223
|
level: "A",
|
|
@@ -2212,14 +2229,14 @@ const qt = {
|
|
|
2212
2229
|
for (const e of t.querySelectorAll("dt, dd"))
|
|
2213
2230
|
(!e.parentElement || e.parentElement.tagName.toLowerCase() !== "dl") && a.push({
|
|
2214
2231
|
ruleId: "dlitem",
|
|
2215
|
-
selector:
|
|
2216
|
-
html:
|
|
2232
|
+
selector: m(e),
|
|
2233
|
+
html: u(e),
|
|
2217
2234
|
impact: "serious",
|
|
2218
2235
|
message: `<${e.tagName.toLowerCase()}> is not contained in a <dl>.`
|
|
2219
2236
|
});
|
|
2220
2237
|
return a;
|
|
2221
2238
|
}
|
|
2222
|
-
},
|
|
2239
|
+
}, Xt = {
|
|
2223
2240
|
id: "definition-list",
|
|
2224
2241
|
selector: "dl",
|
|
2225
2242
|
check: { type: "child-invalid", allowedChildren: ["dt", "dd", "div", "script", "template"] },
|
|
@@ -2230,49 +2247,64 @@ const qt = {
|
|
|
2230
2247
|
level: "A",
|
|
2231
2248
|
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.",
|
|
2232
2249
|
prompt: "Explain whether to move this element outside the <dl> or convert it to dt/dd."
|
|
2233
|
-
},
|
|
2250
|
+
}, Yt = k(Xt), Kt = {
|
|
2234
2251
|
id: "document-title",
|
|
2235
2252
|
wcag: ["2.4.2"],
|
|
2236
2253
|
level: "A",
|
|
2237
2254
|
description: "Documents must have a <title> element to provide users with an overview of content.",
|
|
2238
2255
|
guidance: "Screen reader users rely on page titles to identify and navigate between tabs/windows. Add a descriptive <title> element in <head> that summarizes the page purpose. Keep titles unique across the site, placing specific content before the site name (e.g., 'Contact Us - Acme Corp').",
|
|
2239
|
-
prompt: "Suggest a descriptive
|
|
2256
|
+
prompt: "The page has no title or an empty title. Suggest a concise, descriptive <title> based on the page content sample in context. Good titles are specific and front-load the unique part: 'Product Details - Store Name' rather than 'Store Name - Product Details'.",
|
|
2240
2257
|
run(t) {
|
|
2241
|
-
var e;
|
|
2258
|
+
var e, i, n;
|
|
2242
2259
|
const a = t.querySelector("title");
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2260
|
+
if (!a || !((e = a.textContent) != null && e.trim())) {
|
|
2261
|
+
let r;
|
|
2262
|
+
const o = t.querySelector("h1");
|
|
2263
|
+
if ((i = o == null ? void 0 : o.textContent) != null && i.trim())
|
|
2264
|
+
r = `h1: "${o.textContent.trim().slice(0, 100)}"`;
|
|
2265
|
+
else if (t.body) {
|
|
2266
|
+
const s = ((n = t.body.textContent) == null ? void 0 : n.trim().replace(/\s+/g, " ")) || "";
|
|
2267
|
+
s && (r = `Page text: "${s.slice(0, 150)}"`);
|
|
2268
|
+
}
|
|
2269
|
+
return [{
|
|
2270
|
+
ruleId: "document-title",
|
|
2271
|
+
selector: "html",
|
|
2272
|
+
html: "<html>",
|
|
2273
|
+
impact: "serious",
|
|
2274
|
+
message: a ? "Document <title> element is empty." : "Document is missing a <title> element.",
|
|
2275
|
+
context: r
|
|
2276
|
+
}];
|
|
2277
|
+
}
|
|
2278
|
+
return [];
|
|
2250
2279
|
}
|
|
2251
|
-
},
|
|
2280
|
+
}, Jt = {
|
|
2252
2281
|
id: "bypass",
|
|
2253
2282
|
wcag: ["2.4.1"],
|
|
2254
2283
|
level: "A",
|
|
2255
2284
|
description: "Page must have a mechanism to bypass repeated blocks of content.",
|
|
2256
2285
|
guidance: 'Keyboard users must be able to skip repetitive content like navigation. Provide a skip link at the top of the page that links to the main content (e.g., <a href="#main">Skip to main content</a>), or use a <main> landmark. Screen readers can jump directly to landmarks, so a properly marked-up <main> element satisfies this requirement.',
|
|
2257
|
-
prompt:
|
|
2286
|
+
prompt: 'The page has no mechanism for keyboard users to skip repeated content. The simplest fix is to wrap the primary content area in a <main> element — screen readers can jump directly to it. Alternatively, add a skip link as the first element in <body>: <a href="#main" class="skip-link">Skip to main content</a>, with a matching id on the target element. Use the context to understand what the page is missing.',
|
|
2258
2287
|
run(t) {
|
|
2259
2288
|
if (t.querySelector(
|
|
2260
2289
|
'main, [role="main"], nav, [role="navigation"], aside, [role="complementary"], header, [role="banner"], footer, [role="contentinfo"], [role="search"], [role="region"]'
|
|
2261
2290
|
)) return [];
|
|
2262
2291
|
const e = t.querySelector('a[href^="#"]');
|
|
2263
2292
|
if (e) {
|
|
2264
|
-
const
|
|
2265
|
-
if (
|
|
2266
|
-
const
|
|
2267
|
-
if (t.getElementById(
|
|
2293
|
+
const r = e.getAttribute("href");
|
|
2294
|
+
if (r && r.length > 1) {
|
|
2295
|
+
const o = r.slice(1);
|
|
2296
|
+
if (t.getElementById(o)) return [];
|
|
2268
2297
|
}
|
|
2269
2298
|
}
|
|
2270
|
-
|
|
2299
|
+
if (t.querySelector("h1, h2, h3, [role='heading']")) return [];
|
|
2300
|
+
const n = [];
|
|
2301
|
+
return n.push("no landmarks (<main>, <nav>, <header>, <footer>)"), n.push("no skip link"), n.push("no headings"), [{
|
|
2271
2302
|
ruleId: "bypass",
|
|
2272
2303
|
selector: "html",
|
|
2273
2304
|
html: "<html>",
|
|
2274
2305
|
impact: "serious",
|
|
2275
|
-
message: "Page has no mechanism to bypass repeated content. Add a <main> landmark or skip link."
|
|
2306
|
+
message: "Page has no mechanism to bypass repeated content. Add a <main> landmark or skip link.",
|
|
2307
|
+
context: `Missing: ${n.join(", ")}`
|
|
2276
2308
|
}];
|
|
2277
2309
|
}
|
|
2278
2310
|
}, Qt = {
|
|
@@ -2282,43 +2314,63 @@ const qt = {
|
|
|
2282
2314
|
tags: ["best-practice"],
|
|
2283
2315
|
description: "Page should contain a level-one heading.",
|
|
2284
2316
|
guidance: "A level-one heading (<h1> or role='heading' with aria-level='1') helps users understand the page topic and provides a landmark for screen reader navigation. Each page should have exactly one h1 that describes the main content, typically matching or similar to the page title.",
|
|
2285
|
-
prompt: "Suggest appropriate h1 text based on the page's
|
|
2317
|
+
prompt: "The page has no <h1> heading. Suggest appropriate h1 text based on the page title or content sample in context. The h1 should describe the page's main topic and typically be placed at the start of the main content area.",
|
|
2286
2318
|
run(t) {
|
|
2319
|
+
var o, s, l;
|
|
2287
2320
|
const a = t.querySelector("h1");
|
|
2288
2321
|
if (a && v(a)) return [];
|
|
2289
2322
|
const e = t.querySelectorAll('[role="heading"][aria-level="1"]');
|
|
2290
|
-
for (const
|
|
2291
|
-
if (v(
|
|
2323
|
+
for (const h of e)
|
|
2324
|
+
if (v(h)) return [];
|
|
2325
|
+
const i = [], n = (s = (o = t.querySelector("title")) == null ? void 0 : o.textContent) == null ? void 0 : s.trim();
|
|
2326
|
+
n && i.push(`Page title: "${n}"`);
|
|
2327
|
+
const r = t.querySelector("main");
|
|
2328
|
+
if (r) {
|
|
2329
|
+
const h = ((l = r.textContent) == null ? void 0 : l.trim().replace(/\s+/g, " ")) || "";
|
|
2330
|
+
h && i.push(`Main content: "${h.slice(0, 100)}"`);
|
|
2331
|
+
}
|
|
2292
2332
|
return [{
|
|
2293
2333
|
ruleId: "page-has-heading-one",
|
|
2294
2334
|
selector: "html",
|
|
2295
2335
|
html: "<html>",
|
|
2296
2336
|
impact: "moderate",
|
|
2297
|
-
message: "Page does not contain a level-one heading."
|
|
2337
|
+
message: "Page does not contain a level-one heading.",
|
|
2338
|
+
context: i.length > 0 ? i.join(", ") : void 0
|
|
2298
2339
|
}];
|
|
2299
2340
|
}
|
|
2300
|
-
}
|
|
2341
|
+
};
|
|
2342
|
+
function me(t) {
|
|
2343
|
+
if (!(t instanceof HTMLElement)) return !1;
|
|
2344
|
+
if (t.style.display === "none" || t.style.visibility === "hidden") return !0;
|
|
2345
|
+
const a = t.getAttribute("width"), e = t.getAttribute("height");
|
|
2346
|
+
return (a === "0" || a === "1") && (e === "0" || e === "1");
|
|
2347
|
+
}
|
|
2348
|
+
const Zt = {
|
|
2301
2349
|
id: "frame-title",
|
|
2302
2350
|
wcag: ["4.1.2"],
|
|
2303
2351
|
level: "A",
|
|
2304
2352
|
description: "Frames must have an accessible name.",
|
|
2305
2353
|
guidance: "Screen readers announce frame titles when users navigate frames. Add a title attribute to <iframe> and <frame> elements that describes the frame's purpose (e.g., <iframe title='Video player'>). Avoid generic titles like 'frame' or 'iframe'. If the frame is decorative, use aria-hidden='true'.",
|
|
2306
|
-
prompt: "
|
|
2354
|
+
prompt: "This iframe has no accessible name. Based on the src URL in context, suggest a descriptive title attribute that tells screen reader users what the frame contains. For example: 'YouTube video player', 'Google Map', 'Payment form', 'Chat widget'. If the frame appears decorative or non-essential, recommend adding aria-hidden='true' instead.",
|
|
2307
2355
|
run(t) {
|
|
2308
2356
|
const a = [];
|
|
2309
2357
|
for (const e of t.querySelectorAll("iframe, frame")) {
|
|
2310
|
-
if (p(e)) continue;
|
|
2311
|
-
v(e)
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2358
|
+
if (p(e) || me(e)) continue;
|
|
2359
|
+
if (!v(e)) {
|
|
2360
|
+
const n = e.getAttribute("src");
|
|
2361
|
+
a.push({
|
|
2362
|
+
ruleId: "frame-title",
|
|
2363
|
+
selector: m(e),
|
|
2364
|
+
html: u(e),
|
|
2365
|
+
impact: "serious",
|
|
2366
|
+
message: "Frame is missing an accessible name. Add a title attribute.",
|
|
2367
|
+
context: n ? `src: "${n}"` : void 0
|
|
2368
|
+
});
|
|
2369
|
+
}
|
|
2318
2370
|
}
|
|
2319
2371
|
return a;
|
|
2320
2372
|
}
|
|
2321
|
-
},
|
|
2373
|
+
}, ea = {
|
|
2322
2374
|
id: "frame-title-unique",
|
|
2323
2375
|
wcag: ["4.1.2"],
|
|
2324
2376
|
level: "A",
|
|
@@ -2330,13 +2382,11 @@ const qt = {
|
|
|
2330
2382
|
var n;
|
|
2331
2383
|
const a = [], e = Array.from(t.querySelectorAll("iframe[title], frame[title]")), i = /* @__PURE__ */ new Map();
|
|
2332
2384
|
for (const r of e) {
|
|
2333
|
-
if (p(r)) continue;
|
|
2334
|
-
const o = r.getAttribute("
|
|
2335
|
-
if (o
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
const h = i.get(u) || [];
|
|
2339
|
-
h.push(r), i.set(u, h);
|
|
2385
|
+
if (p(r) || me(r)) continue;
|
|
2386
|
+
const o = (n = r.getAttribute("title")) == null ? void 0 : n.trim().toLowerCase();
|
|
2387
|
+
if (o) {
|
|
2388
|
+
const s = i.get(o) || [];
|
|
2389
|
+
s.push(r), i.set(o, s);
|
|
2340
2390
|
}
|
|
2341
2391
|
}
|
|
2342
2392
|
for (const [, r] of i)
|
|
@@ -2344,66 +2394,77 @@ const qt = {
|
|
|
2344
2394
|
for (const o of r.slice(1))
|
|
2345
2395
|
a.push({
|
|
2346
2396
|
ruleId: "frame-title-unique",
|
|
2347
|
-
selector:
|
|
2348
|
-
html:
|
|
2397
|
+
selector: m(o),
|
|
2398
|
+
html: u(o),
|
|
2349
2399
|
impact: "moderate",
|
|
2350
2400
|
message: "Frame title is not unique. Use a distinct title for each frame."
|
|
2351
2401
|
});
|
|
2352
2402
|
return a;
|
|
2353
2403
|
}
|
|
2354
|
-
},
|
|
2404
|
+
}, ta = {
|
|
2355
2405
|
id: "empty-heading",
|
|
2356
2406
|
wcag: [],
|
|
2357
2407
|
level: "A",
|
|
2358
2408
|
tags: ["best-practice"],
|
|
2359
2409
|
description: "Headings must have discernible text.",
|
|
2360
2410
|
guidance: "Screen reader users navigate pages by headings, so empty headings create confusing navigation points. Ensure all headings contain visible text or accessible names. If a heading is used purely for visual styling, use CSS instead of heading elements.",
|
|
2361
|
-
prompt: "
|
|
2411
|
+
prompt: "This heading element has no text content, so screen reader users encounter a blank heading when navigating. Either add descriptive text that summarizes the following section, or if this element is used only for visual styling, replace it with a styled <p> or <div> and use CSS for appearance. The context includes nearby content to help suggest appropriate heading text.",
|
|
2362
2412
|
run(t) {
|
|
2413
|
+
var i;
|
|
2363
2414
|
const a = [], e = t.querySelectorAll('h1, h2, h3, h4, h5, h6, [role="heading"]');
|
|
2364
|
-
for (const
|
|
2365
|
-
p(
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2415
|
+
for (const n of e)
|
|
2416
|
+
if (!p(n) && !v(n)) {
|
|
2417
|
+
let r;
|
|
2418
|
+
const o = n.nextElementSibling;
|
|
2419
|
+
if (o) {
|
|
2420
|
+
const s = ((i = o.textContent) == null ? void 0 : i.trim().replace(/\s+/g, " ")) || "";
|
|
2421
|
+
s && (r = s.slice(0, 100));
|
|
2422
|
+
}
|
|
2423
|
+
a.push({
|
|
2424
|
+
ruleId: "empty-heading",
|
|
2425
|
+
selector: m(n),
|
|
2426
|
+
html: u(n),
|
|
2427
|
+
impact: "minor",
|
|
2428
|
+
message: "Heading is empty. Add text content or remove the heading element.",
|
|
2429
|
+
context: r ? `Following content: "${r}"` : void 0
|
|
2430
|
+
});
|
|
2431
|
+
}
|
|
2372
2432
|
return a;
|
|
2373
2433
|
}
|
|
2374
|
-
},
|
|
2434
|
+
}, aa = {
|
|
2375
2435
|
id: "meta-viewport",
|
|
2376
2436
|
wcag: ["1.4.4"],
|
|
2377
2437
|
level: "AA",
|
|
2378
2438
|
description: "Viewport meta tag must not disable user scaling.",
|
|
2379
2439
|
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.",
|
|
2380
|
-
prompt: "
|
|
2440
|
+
prompt: "The viewport meta tag restricts zooming, which prevents low-vision users from enlarging content. Show the current content attribute and a corrected version with the problematic properties removed. Keep other viewport properties (like width=device-width, initial-scale=1) intact — only remove user-scalable=no and maximum-scale restrictions.",
|
|
2381
2441
|
run(t) {
|
|
2382
|
-
var r;
|
|
2383
2442
|
const a = [], e = t.querySelector('meta[name="viewport"]');
|
|
2384
2443
|
if (!e) return [];
|
|
2385
|
-
const i =
|
|
2386
|
-
(/user-scalable\s*=\s*no/i.test(
|
|
2444
|
+
const i = e.getAttribute("content") || "", n = i.toLowerCase();
|
|
2445
|
+
(/user-scalable\s*=\s*no/i.test(n) || /user-scalable\s*=\s*0/i.test(n)) && a.push({
|
|
2387
2446
|
ruleId: "meta-viewport",
|
|
2388
|
-
selector:
|
|
2389
|
-
html:
|
|
2447
|
+
selector: m(e),
|
|
2448
|
+
html: u(e),
|
|
2390
2449
|
impact: "critical",
|
|
2391
|
-
message: "Viewport disables user scaling. Remove user-scalable=no."
|
|
2450
|
+
message: "Viewport disables user scaling. Remove user-scalable=no.",
|
|
2451
|
+
context: `content: "${i}"`
|
|
2392
2452
|
});
|
|
2393
|
-
const
|
|
2394
|
-
if (
|
|
2395
|
-
const o =
|
|
2453
|
+
const r = n.match(/maximum-scale\s*=\s*([\d.]+|yes)/i);
|
|
2454
|
+
if (r) {
|
|
2455
|
+
const o = r[1], s = o.toLowerCase() === "yes" ? 1 : parseFloat(o);
|
|
2396
2456
|
s < 2 && a.push({
|
|
2397
2457
|
ruleId: "meta-viewport",
|
|
2398
|
-
selector:
|
|
2399
|
-
html:
|
|
2458
|
+
selector: m(e),
|
|
2459
|
+
html: u(e),
|
|
2400
2460
|
impact: "critical",
|
|
2401
|
-
message: `Viewport maximum-scale=${s} restricts zooming. Set to at least 2 or remove
|
|
2461
|
+
message: `Viewport maximum-scale=${s} restricts zooming. Set to at least 2 or remove.`,
|
|
2462
|
+
context: `content: "${i}"`
|
|
2402
2463
|
});
|
|
2403
2464
|
}
|
|
2404
2465
|
return a;
|
|
2405
2466
|
}
|
|
2406
|
-
},
|
|
2467
|
+
}, ia = {
|
|
2407
2468
|
id: "meta-refresh",
|
|
2408
2469
|
wcag: ["2.2.1", "2.2.4", "3.2.5"],
|
|
2409
2470
|
level: "A",
|
|
@@ -2418,23 +2479,23 @@ const qt = {
|
|
|
2418
2479
|
if (/^\d+\s*[;,]\s*url\s*=/i.test(e) || /^\d+\s*[;,]\s*['"]?\s*https?:/i.test(e))
|
|
2419
2480
|
return n > 0 && n <= 72e3 ? [{
|
|
2420
2481
|
ruleId: "meta-refresh",
|
|
2421
|
-
selector:
|
|
2422
|
-
html:
|
|
2482
|
+
selector: m(a),
|
|
2483
|
+
html: u(a),
|
|
2423
2484
|
impact: "critical",
|
|
2424
2485
|
message: `Page redirects after ${n} seconds without warning. Use server-side redirect.`
|
|
2425
2486
|
}] : [];
|
|
2426
2487
|
if (n > 0 && n <= 72e3)
|
|
2427
2488
|
return [{
|
|
2428
2489
|
ruleId: "meta-refresh",
|
|
2429
|
-
selector:
|
|
2430
|
-
html:
|
|
2490
|
+
selector: m(a),
|
|
2491
|
+
html: u(a),
|
|
2431
2492
|
impact: "critical",
|
|
2432
2493
|
message: `Page auto-refreshes after ${n} seconds. Provide user control over refresh.`
|
|
2433
2494
|
}];
|
|
2434
2495
|
}
|
|
2435
2496
|
return [];
|
|
2436
2497
|
}
|
|
2437
|
-
},
|
|
2498
|
+
}, na = {
|
|
2438
2499
|
id: "blink",
|
|
2439
2500
|
selector: "blink",
|
|
2440
2501
|
check: { type: "selector-exists" },
|
|
@@ -2445,7 +2506,7 @@ const qt = {
|
|
|
2445
2506
|
level: "A",
|
|
2446
2507
|
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.",
|
|
2447
2508
|
prompt: "Suggest static alternatives to the blinking effect."
|
|
2448
|
-
},
|
|
2509
|
+
}, ra = k(na), oa = {
|
|
2449
2510
|
id: "marquee",
|
|
2450
2511
|
selector: "marquee",
|
|
2451
2512
|
check: { type: "selector-exists" },
|
|
@@ -2456,7 +2517,7 @@ const qt = {
|
|
|
2456
2517
|
level: "A",
|
|
2457
2518
|
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.",
|
|
2458
2519
|
prompt: "Suggest static alternatives or accessible carousel patterns."
|
|
2459
|
-
},
|
|
2520
|
+
}, sa = k(oa), la = {
|
|
2460
2521
|
id: "p-as-heading",
|
|
2461
2522
|
wcag: [],
|
|
2462
2523
|
level: "A",
|
|
@@ -2469,13 +2530,13 @@ const qt = {
|
|
|
2469
2530
|
const a = [];
|
|
2470
2531
|
for (const n of t.querySelectorAll("p")) {
|
|
2471
2532
|
if (p(n)) continue;
|
|
2472
|
-
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),
|
|
2473
|
-
if ((o && s || o && h) &&
|
|
2474
|
-
const
|
|
2475
|
-
|
|
2533
|
+
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), l = ((e = n.className) == null ? void 0 : e.toLowerCase()) || "", h = /\bh[1-6]\b|\bheading\b/.test(l), c = ((i = n.textContent) == null ? void 0 : i.trim()) || "", d = c.length > 0 && c.length < 50, g = !c.match(/[.!?,;:]$/);
|
|
2534
|
+
if ((o && s || o && h) && d && g) {
|
|
2535
|
+
const y = n.nextElementSibling;
|
|
2536
|
+
y && (y.tagName === "P" || y.tagName === "DIV" || y.tagName === "UL") && a.push({
|
|
2476
2537
|
ruleId: "p-as-heading",
|
|
2477
|
-
selector:
|
|
2478
|
-
html:
|
|
2538
|
+
selector: m(n),
|
|
2539
|
+
html: u(n),
|
|
2479
2540
|
impact: "serious",
|
|
2480
2541
|
message: "Paragraph appears to be styled as a heading. Use an h1-h6 element instead."
|
|
2481
2542
|
});
|
|
@@ -2483,7 +2544,7 @@ const qt = {
|
|
|
2483
2544
|
}
|
|
2484
2545
|
return a;
|
|
2485
2546
|
}
|
|
2486
|
-
},
|
|
2547
|
+
}, ca = {
|
|
2487
2548
|
id: "aria-roles",
|
|
2488
2549
|
wcag: ["4.1.2"],
|
|
2489
2550
|
level: "A",
|
|
@@ -2494,17 +2555,17 @@ const qt = {
|
|
|
2494
2555
|
const a = [];
|
|
2495
2556
|
for (const e of t.querySelectorAll("[role]")) {
|
|
2496
2557
|
const r = e.getAttribute("role").replace(/[\u201C\u201D\u2018\u2019\u00AB\u00BB]/g, "").split(/\s+/).filter(Boolean);
|
|
2497
|
-
!r.some((s) =>
|
|
2558
|
+
!r.some((s) => xe(s)) && r.length > 0 && a.push({
|
|
2498
2559
|
ruleId: "aria-roles",
|
|
2499
|
-
selector:
|
|
2500
|
-
html:
|
|
2560
|
+
selector: m(e),
|
|
2561
|
+
html: u(e),
|
|
2501
2562
|
impact: "critical",
|
|
2502
2563
|
message: `Invalid ARIA role "${r[0]}".`
|
|
2503
2564
|
});
|
|
2504
2565
|
}
|
|
2505
2566
|
return a;
|
|
2506
2567
|
}
|
|
2507
|
-
},
|
|
2568
|
+
}, ua = {
|
|
2508
2569
|
id: "aria-valid-attr",
|
|
2509
2570
|
wcag: ["4.1.2"],
|
|
2510
2571
|
level: "A",
|
|
@@ -2514,7 +2575,7 @@ const qt = {
|
|
|
2514
2575
|
run(t) {
|
|
2515
2576
|
return z(t).validAttr;
|
|
2516
2577
|
}
|
|
2517
|
-
},
|
|
2578
|
+
}, da = {
|
|
2518
2579
|
id: "aria-valid-attr-value",
|
|
2519
2580
|
wcag: ["4.1.2"],
|
|
2520
2581
|
level: "A",
|
|
@@ -2524,7 +2585,7 @@ const qt = {
|
|
|
2524
2585
|
run(t) {
|
|
2525
2586
|
return z(t).validAttrValue;
|
|
2526
2587
|
}
|
|
2527
|
-
},
|
|
2588
|
+
}, ma = {
|
|
2528
2589
|
checkbox: ["aria-checked"],
|
|
2529
2590
|
combobox: ["aria-expanded"],
|
|
2530
2591
|
heading: ["aria-level"],
|
|
@@ -2538,7 +2599,7 @@ const qt = {
|
|
|
2538
2599
|
slider: ["aria-valuenow"],
|
|
2539
2600
|
spinbutton: ["aria-valuenow"],
|
|
2540
2601
|
switch: ["aria-checked"]
|
|
2541
|
-
},
|
|
2602
|
+
}, ha = {
|
|
2542
2603
|
id: "aria-required-attr",
|
|
2543
2604
|
wcag: ["4.1.2"],
|
|
2544
2605
|
level: "A",
|
|
@@ -2549,7 +2610,7 @@ const qt = {
|
|
|
2549
2610
|
const a = [];
|
|
2550
2611
|
for (const e of t.querySelectorAll("[role]")) {
|
|
2551
2612
|
if (p(e) || e instanceof HTMLElement && e.style.display === "none") continue;
|
|
2552
|
-
const i = e.getAttribute("role").trim().toLowerCase(), n =
|
|
2613
|
+
const i = e.getAttribute("role").trim().toLowerCase(), n = ma[i];
|
|
2553
2614
|
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))) {
|
|
2554
2615
|
if (i === "separator") {
|
|
2555
2616
|
const r = e.getAttribute("tabindex");
|
|
@@ -2560,8 +2621,8 @@ const qt = {
|
|
|
2560
2621
|
if (!e.hasAttribute(r)) {
|
|
2561
2622
|
a.push({
|
|
2562
2623
|
ruleId: "aria-required-attr",
|
|
2563
|
-
selector:
|
|
2564
|
-
html:
|
|
2624
|
+
selector: m(e),
|
|
2625
|
+
html: u(e),
|
|
2565
2626
|
impact: "critical",
|
|
2566
2627
|
message: `Role "${i}" requires attribute "${r}".`
|
|
2567
2628
|
});
|
|
@@ -2573,24 +2634,24 @@ const qt = {
|
|
|
2573
2634
|
return a;
|
|
2574
2635
|
}
|
|
2575
2636
|
};
|
|
2576
|
-
function
|
|
2637
|
+
function pa(t) {
|
|
2577
2638
|
var r, o, s;
|
|
2578
2639
|
const a = [], e = t.className;
|
|
2579
2640
|
e && typeof e == "string" && e.trim() && a.push(`Classes: ${e.trim().slice(0, 100)}`);
|
|
2580
2641
|
const i = t.closest("form");
|
|
2581
2642
|
if (i) {
|
|
2582
|
-
const
|
|
2583
|
-
|
|
2643
|
+
const l = i.getAttribute("aria-label") || ((o = (r = i.querySelector("legend")) == null ? void 0 : r.textContent) == null ? void 0 : o.trim());
|
|
2644
|
+
l && a.push(`Form: ${l.slice(0, 60)}`);
|
|
2584
2645
|
}
|
|
2585
2646
|
const n = t.parentElement;
|
|
2586
2647
|
if (n) {
|
|
2587
|
-
const
|
|
2588
|
-
(s =
|
|
2648
|
+
const l = n.closest("h1, h2, h3, h4, h5, h6") || n.querySelector("h1, h2, h3, h4, h5, h6");
|
|
2649
|
+
(s = l == null ? void 0 : l.textContent) != null && s.trim() && a.push(`Nearby heading: ${l.textContent.trim().slice(0, 60)}`);
|
|
2589
2650
|
}
|
|
2590
2651
|
return a.length > 0 ? a.join(`
|
|
2591
2652
|
`) : void 0;
|
|
2592
2653
|
}
|
|
2593
|
-
const
|
|
2654
|
+
const ga = {
|
|
2594
2655
|
id: "button-name",
|
|
2595
2656
|
wcag: ["4.1.2"],
|
|
2596
2657
|
level: "A",
|
|
@@ -2605,16 +2666,16 @@ const pa = {
|
|
|
2605
2666
|
if ((i === "none" || i === "presentation") && !(e.matches('button:not([disabled]), [tabindex]:not([tabindex="-1"])') || e.tagName.toLowerCase() === "button" && !e.disabled) || e.getRootNode() instanceof ShadowRoot) continue;
|
|
2606
2667
|
v(e) || a.push({
|
|
2607
2668
|
ruleId: "button-name",
|
|
2608
|
-
selector:
|
|
2609
|
-
html:
|
|
2669
|
+
selector: m(e),
|
|
2670
|
+
html: u(e),
|
|
2610
2671
|
impact: "critical",
|
|
2611
2672
|
message: "Button has no discernible text.",
|
|
2612
|
-
context:
|
|
2673
|
+
context: pa(e)
|
|
2613
2674
|
});
|
|
2614
2675
|
}
|
|
2615
2676
|
return a;
|
|
2616
2677
|
}
|
|
2617
|
-
},
|
|
2678
|
+
}, ba = {
|
|
2618
2679
|
alert: /* @__PURE__ */ new Set(["aria-atomic", "aria-busy", "aria-live", "aria-relevant"]),
|
|
2619
2680
|
alertdialog: /* @__PURE__ */ new Set(["aria-describedby", "aria-modal"]),
|
|
2620
2681
|
application: /* @__PURE__ */ new Set(["aria-activedescendant", "aria-disabled", "aria-errormessage", "aria-expanded", "aria-haspopup", "aria-invalid"]),
|
|
@@ -2686,7 +2747,7 @@ const pa = {
|
|
|
2686
2747
|
tree: /* @__PURE__ */ new Set(["aria-activedescendant", "aria-disabled", "aria-errormessage", "aria-invalid", "aria-multiselectable", "aria-orientation", "aria-required"]),
|
|
2687
2748
|
treegrid: /* @__PURE__ */ new Set(["aria-activedescendant", "aria-colcount", "aria-disabled", "aria-errormessage", "aria-invalid", "aria-multiselectable", "aria-orientation", "aria-readonly", "aria-required", "aria-rowcount"]),
|
|
2688
2749
|
treeitem: /* @__PURE__ */ new Set(["aria-checked", "aria-disabled", "aria-expanded", "aria-haspopup", "aria-level", "aria-posinset", "aria-selected", "aria-setsize"])
|
|
2689
|
-
},
|
|
2750
|
+
}, fa = /* @__PURE__ */ new Set([
|
|
2690
2751
|
"aria-atomic",
|
|
2691
2752
|
"aria-busy",
|
|
2692
2753
|
"aria-controls",
|
|
@@ -2710,33 +2771,37 @@ const pa = {
|
|
|
2710
2771
|
"aria-roledescription",
|
|
2711
2772
|
"aria-braillelabel",
|
|
2712
2773
|
"aria-brailleroledescription"
|
|
2713
|
-
]),
|
|
2774
|
+
]), va = {
|
|
2714
2775
|
id: "aria-allowed-attr",
|
|
2715
2776
|
wcag: ["4.1.2"],
|
|
2716
2777
|
level: "A",
|
|
2717
2778
|
description: "ARIA attributes must be allowed for the element's role.",
|
|
2718
2779
|
guidance: "Each ARIA role supports specific attributes. Using unsupported attributes creates confusion for assistive technologies. Check the ARIA specification for which attributes are valid for each role, or remove the attribute if it's not needed.",
|
|
2719
|
-
prompt: "
|
|
2780
|
+
prompt: "The ARIA attribute listed in context is not supported on this element's role. Either remove the attribute (if the behavior it describes isn't needed), or change the element's role to one that supports it. The context lists which attributes ARE allowed on this role — use that to suggest alternatives if applicable.",
|
|
2720
2781
|
run(t) {
|
|
2721
2782
|
const a = [];
|
|
2722
2783
|
for (const e of t.querySelectorAll("[role], [aria-*]")) {
|
|
2723
2784
|
if (p(e)) continue;
|
|
2724
|
-
const i =
|
|
2785
|
+
const i = L(e);
|
|
2725
2786
|
if (!i) continue;
|
|
2726
|
-
const n =
|
|
2787
|
+
const n = ba[i];
|
|
2727
2788
|
if (n)
|
|
2728
|
-
for (const r of e.attributes)
|
|
2729
|
-
r.name.startsWith("aria-")
|
|
2789
|
+
for (const r of e.attributes) {
|
|
2790
|
+
if (!r.name.startsWith("aria-") || fa.has(r.name) || n.has(r.name)) continue;
|
|
2791
|
+
const o = n.size > 0 ? [...n].join(", ") : "none (only global ARIA attributes)";
|
|
2792
|
+
a.push({
|
|
2730
2793
|
ruleId: "aria-allowed-attr",
|
|
2731
|
-
selector:
|
|
2732
|
-
html:
|
|
2794
|
+
selector: m(e),
|
|
2795
|
+
html: u(e),
|
|
2733
2796
|
impact: "critical",
|
|
2734
|
-
message: `ARIA attribute "${r.name}" is not allowed on role "${i}"
|
|
2735
|
-
|
|
2797
|
+
message: `ARIA attribute "${r.name}" is not allowed on role "${i}".`,
|
|
2798
|
+
context: `Attribute: ${r.name}="${r.value}", role: ${i}, allowed role-specific attributes: ${o}`
|
|
2799
|
+
});
|
|
2800
|
+
}
|
|
2736
2801
|
}
|
|
2737
2802
|
return a;
|
|
2738
2803
|
}
|
|
2739
|
-
},
|
|
2804
|
+
}, ya = /* @__PURE__ */ new Set([
|
|
2740
2805
|
"base",
|
|
2741
2806
|
"col",
|
|
2742
2807
|
"colgroup",
|
|
@@ -2751,7 +2816,7 @@ const pa = {
|
|
|
2751
2816
|
"template",
|
|
2752
2817
|
"title",
|
|
2753
2818
|
"track"
|
|
2754
|
-
]),
|
|
2819
|
+
]), T = {
|
|
2755
2820
|
a: /* @__PURE__ */ new Set(["button", "checkbox", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "switch", "tab", "treeitem", "link"]),
|
|
2756
2821
|
"a[href]": /* @__PURE__ */ new Set(["button", "checkbox", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "switch", "tab", "treeitem"]),
|
|
2757
2822
|
abbr: "any",
|
|
@@ -2861,19 +2926,19 @@ const pa = {
|
|
|
2861
2926
|
function wa(t) {
|
|
2862
2927
|
var e;
|
|
2863
2928
|
const a = t.tagName.toLowerCase();
|
|
2864
|
-
if (
|
|
2929
|
+
if (ya.has(a))
|
|
2865
2930
|
return "none";
|
|
2866
2931
|
if (a === "a" && t.hasAttribute("href"))
|
|
2867
|
-
return
|
|
2932
|
+
return T["a[href]"];
|
|
2868
2933
|
if (a === "img" && t.getAttribute("alt") === "")
|
|
2869
|
-
return
|
|
2934
|
+
return T["img[alt='']"];
|
|
2870
2935
|
if (a === "input") {
|
|
2871
2936
|
const n = `input[type=${((e = t.getAttribute("type")) == null ? void 0 : e.toLowerCase()) || "text"}]`;
|
|
2872
|
-
return n in
|
|
2937
|
+
return n in T ? T[n] : "none";
|
|
2873
2938
|
}
|
|
2874
|
-
return
|
|
2939
|
+
return T[a] || "any";
|
|
2875
2940
|
}
|
|
2876
|
-
const
|
|
2941
|
+
const Aa = {
|
|
2877
2942
|
id: "aria-allowed-role",
|
|
2878
2943
|
wcag: ["4.1.2"],
|
|
2879
2944
|
level: "A",
|
|
@@ -2892,14 +2957,14 @@ const ya = {
|
|
|
2892
2957
|
const o = wa(i);
|
|
2893
2958
|
o === "none" ? a.push({
|
|
2894
2959
|
ruleId: "aria-allowed-role",
|
|
2895
|
-
selector:
|
|
2896
|
-
html:
|
|
2960
|
+
selector: m(i),
|
|
2961
|
+
html: u(i),
|
|
2897
2962
|
impact: "minor",
|
|
2898
2963
|
message: `Element <${i.tagName.toLowerCase()}> should not have an explicit role.`
|
|
2899
2964
|
}) : o !== "any" && !o.has(n) && a.push({
|
|
2900
2965
|
ruleId: "aria-allowed-role",
|
|
2901
|
-
selector:
|
|
2902
|
-
html:
|
|
2966
|
+
selector: m(i),
|
|
2967
|
+
html: u(i),
|
|
2903
2968
|
impact: "minor",
|
|
2904
2969
|
message: `Role "${n}" is not allowed on element <${i.tagName.toLowerCase()}>.`
|
|
2905
2970
|
});
|
|
@@ -2937,22 +3002,22 @@ const ya = {
|
|
|
2937
3002
|
tab: ["tablist"],
|
|
2938
3003
|
treeitem: ["tree", "group"]
|
|
2939
3004
|
};
|
|
2940
|
-
function
|
|
3005
|
+
function xa(t, a) {
|
|
2941
3006
|
var r;
|
|
2942
3007
|
const e = ((r = t.getAttribute("aria-owns")) == null ? void 0 : r.split(/\s+/)) || [], i = t.ownerDocument, n = /* @__PURE__ */ new Set();
|
|
2943
3008
|
for (const o of t.querySelectorAll("*")) {
|
|
2944
|
-
const s =
|
|
3009
|
+
const s = L(o);
|
|
2945
3010
|
s && !p(o) && n.add(s);
|
|
2946
3011
|
}
|
|
2947
3012
|
for (const o of e) {
|
|
2948
3013
|
const s = i.getElementById(o);
|
|
2949
3014
|
if (s) {
|
|
2950
|
-
const
|
|
2951
|
-
|
|
3015
|
+
const l = L(s);
|
|
3016
|
+
l && !p(s) && n.add(l);
|
|
2952
3017
|
}
|
|
2953
3018
|
}
|
|
2954
3019
|
for (const o of a)
|
|
2955
|
-
if (!o.some((
|
|
3020
|
+
if (!o.some((l) => n.has(l))) return !1;
|
|
2956
3021
|
return !0;
|
|
2957
3022
|
}
|
|
2958
3023
|
const Sa = {
|
|
@@ -2970,12 +3035,12 @@ const Sa = {
|
|
|
2970
3035
|
const n = (e = i.getAttribute("role")) == null ? void 0 : e.trim().toLowerCase();
|
|
2971
3036
|
if (!n || !(n in ae)) continue;
|
|
2972
3037
|
const r = ae[n];
|
|
2973
|
-
if (!
|
|
3038
|
+
if (!xa(i, r)) {
|
|
2974
3039
|
const o = r.map((s) => s.join(" or ")).join(", ");
|
|
2975
3040
|
a.push({
|
|
2976
3041
|
ruleId: "aria-required-children",
|
|
2977
|
-
selector:
|
|
2978
|
-
html:
|
|
3042
|
+
selector: m(i),
|
|
3043
|
+
html: u(i),
|
|
2979
3044
|
impact: "critical",
|
|
2980
3045
|
message: `Role "${n}" requires children with role: ${o}.`
|
|
2981
3046
|
});
|
|
@@ -2983,7 +3048,7 @@ const Sa = {
|
|
|
2983
3048
|
}
|
|
2984
3049
|
return a;
|
|
2985
3050
|
}
|
|
2986
|
-
},
|
|
3051
|
+
}, ka = {
|
|
2987
3052
|
id: "aria-required-parent",
|
|
2988
3053
|
wcag: ["4.1.2"],
|
|
2989
3054
|
level: "A",
|
|
@@ -3000,8 +3065,8 @@ const Sa = {
|
|
|
3000
3065
|
const r = ie[n];
|
|
3001
3066
|
let o = i.parentElement, s = !1;
|
|
3002
3067
|
for (; o && o !== t.documentElement; ) {
|
|
3003
|
-
const
|
|
3004
|
-
if (
|
|
3068
|
+
const l = L(o);
|
|
3069
|
+
if (l && r.includes(l)) {
|
|
3005
3070
|
s = !0;
|
|
3006
3071
|
break;
|
|
3007
3072
|
}
|
|
@@ -3009,8 +3074,8 @@ const Sa = {
|
|
|
3009
3074
|
}
|
|
3010
3075
|
s || a.push({
|
|
3011
3076
|
ruleId: "aria-required-parent",
|
|
3012
|
-
selector:
|
|
3013
|
-
html:
|
|
3077
|
+
selector: m(i),
|
|
3078
|
+
html: u(i),
|
|
3014
3079
|
impact: "critical",
|
|
3015
3080
|
message: `Role "${n}" must be contained within: ${r.join(", ")}.`
|
|
3016
3081
|
});
|
|
@@ -3033,7 +3098,7 @@ const Sa = {
|
|
|
3033
3098
|
"embed",
|
|
3034
3099
|
"area[href]"
|
|
3035
3100
|
].join(", ");
|
|
3036
|
-
function
|
|
3101
|
+
function Ia(t) {
|
|
3037
3102
|
let a = t;
|
|
3038
3103
|
const e = t.ownerDocument, i = e.defaultView;
|
|
3039
3104
|
for (; a && a !== e.body; ) {
|
|
@@ -3046,7 +3111,7 @@ function ka(t) {
|
|
|
3046
3111
|
}
|
|
3047
3112
|
return !0;
|
|
3048
3113
|
}
|
|
3049
|
-
const
|
|
3114
|
+
const Ta = {
|
|
3050
3115
|
id: "aria-hidden-body",
|
|
3051
3116
|
selector: 'body[aria-hidden="true"]',
|
|
3052
3117
|
check: { type: "selector-exists" },
|
|
@@ -3058,13 +3123,13 @@ const Ia = {
|
|
|
3058
3123
|
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.",
|
|
3059
3124
|
prompt: "Instruct to remove aria-hidden='true' from the body element.",
|
|
3060
3125
|
skipAriaHidden: !1
|
|
3061
|
-
}, Ea = k(
|
|
3126
|
+
}, Ea = k(Ta), Ca = {
|
|
3062
3127
|
id: "aria-hidden-focus",
|
|
3063
3128
|
wcag: ["4.1.2"],
|
|
3064
3129
|
level: "A",
|
|
3065
3130
|
description: "Elements with aria-hidden='true' must not contain focusable elements.",
|
|
3066
3131
|
guidance: "When aria-hidden='true' hides an element from assistive technologies but the element contains focusable children, keyboard users can focus those children but screen reader users won't know they exist. Either remove focusable elements from the hidden region, add tabindex='-1' to them, or remove aria-hidden.",
|
|
3067
|
-
prompt: "
|
|
3132
|
+
prompt: "This element can receive keyboard focus but is inside an aria-hidden region, making it invisible to screen readers. The context explains why it's focusable. Fix by either: (1) adding tabindex='-1' to remove it from tab order, (2) moving it outside the aria-hidden region, or (3) removing aria-hidden='true' from the ancestor if the content should be accessible.",
|
|
3068
3133
|
run(t) {
|
|
3069
3134
|
const a = [];
|
|
3070
3135
|
for (const e of t.querySelectorAll('[aria-hidden="true"]')) {
|
|
@@ -3073,13 +3138,19 @@ const Ia = {
|
|
|
3073
3138
|
e.matches(ne) && i.push(e);
|
|
3074
3139
|
for (const n of i)
|
|
3075
3140
|
if (n instanceof HTMLElement) {
|
|
3076
|
-
|
|
3141
|
+
const r = n.getAttribute("tabindex");
|
|
3142
|
+
if (r === "-1" || n.disabled || n instanceof HTMLInputElement && n.type === "hidden" || !Ia(n)) continue;
|
|
3143
|
+
const o = n.tagName.toLowerCase();
|
|
3144
|
+
let s;
|
|
3145
|
+
r !== null ? s = `has tabindex="${r}"` : o === "a" && n.hasAttribute("href") ? s = "is a link with href" : o === "button" ? s = "is a <button>" : o === "input" ? s = `is an <input type="${n.type}">` : o === "select" ? s = "is a <select>" : o === "textarea" ? s = "is a <textarea>" : o === "iframe" ? s = "is an <iframe>" : s = `is a natively focusable <${o}>`;
|
|
3146
|
+
const l = n === e ? n : n.closest('[aria-hidden="true"]');
|
|
3077
3147
|
a.push({
|
|
3078
3148
|
ruleId: "aria-hidden-focus",
|
|
3079
|
-
selector:
|
|
3080
|
-
html:
|
|
3149
|
+
selector: m(n),
|
|
3150
|
+
html: u(n),
|
|
3081
3151
|
impact: "serious",
|
|
3082
|
-
message: "Focusable element is inside an aria-hidden region."
|
|
3152
|
+
message: "Focusable element is inside an aria-hidden region.",
|
|
3153
|
+
context: `Focusable because: ${s}. aria-hidden ancestor: ${l ? u(l) : "unknown"}`
|
|
3083
3154
|
});
|
|
3084
3155
|
}
|
|
3085
3156
|
}
|
|
@@ -3102,8 +3173,8 @@ const Ia = {
|
|
|
3102
3173
|
if ((e = r == null ? void 0 : r.getAttribute("alt")) != null && e.trim()) continue;
|
|
3103
3174
|
a.push({
|
|
3104
3175
|
ruleId: "aria-command-name",
|
|
3105
|
-
selector:
|
|
3106
|
-
html:
|
|
3176
|
+
selector: m(i),
|
|
3177
|
+
html: u(i),
|
|
3107
3178
|
impact: "serious",
|
|
3108
3179
|
message: "ARIA command has no accessible name."
|
|
3109
3180
|
});
|
|
@@ -3111,7 +3182,7 @@ const Ia = {
|
|
|
3111
3182
|
}
|
|
3112
3183
|
return a;
|
|
3113
3184
|
}
|
|
3114
|
-
},
|
|
3185
|
+
}, qa = {
|
|
3115
3186
|
id: "aria-input-field-name",
|
|
3116
3187
|
wcag: ["4.1.2"],
|
|
3117
3188
|
level: "A",
|
|
@@ -3124,15 +3195,15 @@ const Ia = {
|
|
|
3124
3195
|
if (p(i) || i.matches("input, select, textarea")) continue;
|
|
3125
3196
|
v(i) || a.push({
|
|
3126
3197
|
ruleId: "aria-input-field-name",
|
|
3127
|
-
selector:
|
|
3128
|
-
html:
|
|
3198
|
+
selector: m(i),
|
|
3199
|
+
html: u(i),
|
|
3129
3200
|
impact: "serious",
|
|
3130
3201
|
message: "ARIA input field has no accessible name."
|
|
3131
3202
|
});
|
|
3132
3203
|
}
|
|
3133
3204
|
return a;
|
|
3134
3205
|
}
|
|
3135
|
-
},
|
|
3206
|
+
}, Ra = {
|
|
3136
3207
|
id: "aria-toggle-field-name",
|
|
3137
3208
|
wcag: ["4.1.2"],
|
|
3138
3209
|
level: "A",
|
|
@@ -3145,15 +3216,15 @@ const Ia = {
|
|
|
3145
3216
|
if (p(i) || i.matches('input[type="checkbox"], input[type="radio"]')) continue;
|
|
3146
3217
|
v(i) || a.push({
|
|
3147
3218
|
ruleId: "aria-toggle-field-name",
|
|
3148
|
-
selector:
|
|
3149
|
-
html:
|
|
3219
|
+
selector: m(i),
|
|
3220
|
+
html: u(i),
|
|
3150
3221
|
impact: "serious",
|
|
3151
3222
|
message: "ARIA toggle field has no accessible name."
|
|
3152
3223
|
});
|
|
3153
3224
|
}
|
|
3154
3225
|
return a;
|
|
3155
3226
|
}
|
|
3156
|
-
},
|
|
3227
|
+
}, Na = {
|
|
3157
3228
|
id: "aria-meter-name",
|
|
3158
3229
|
wcag: ["4.1.2"],
|
|
3159
3230
|
level: "A",
|
|
@@ -3166,15 +3237,15 @@ const Ia = {
|
|
|
3166
3237
|
if (p(e)) continue;
|
|
3167
3238
|
v(e) || a.push({
|
|
3168
3239
|
ruleId: "aria-meter-name",
|
|
3169
|
-
selector:
|
|
3170
|
-
html:
|
|
3240
|
+
selector: m(e),
|
|
3241
|
+
html: u(e),
|
|
3171
3242
|
impact: "serious",
|
|
3172
3243
|
message: "Meter has no accessible name."
|
|
3173
3244
|
});
|
|
3174
3245
|
}
|
|
3175
3246
|
return a;
|
|
3176
3247
|
}
|
|
3177
|
-
},
|
|
3248
|
+
}, $a = {
|
|
3178
3249
|
id: "aria-progressbar-name",
|
|
3179
3250
|
wcag: ["4.1.2"],
|
|
3180
3251
|
level: "A",
|
|
@@ -3187,8 +3258,8 @@ const Ia = {
|
|
|
3187
3258
|
if (p(e)) continue;
|
|
3188
3259
|
v(e) || a.push({
|
|
3189
3260
|
ruleId: "aria-progressbar-name",
|
|
3190
|
-
selector:
|
|
3191
|
-
html:
|
|
3261
|
+
selector: m(e),
|
|
3262
|
+
html: u(e),
|
|
3192
3263
|
impact: "serious",
|
|
3193
3264
|
message: "Progressbar has no accessible name."
|
|
3194
3265
|
});
|
|
@@ -3208,15 +3279,15 @@ const Ia = {
|
|
|
3208
3279
|
if (p(e)) continue;
|
|
3209
3280
|
v(e) || a.push({
|
|
3210
3281
|
ruleId: "aria-dialog-name",
|
|
3211
|
-
selector:
|
|
3212
|
-
html:
|
|
3282
|
+
selector: m(e),
|
|
3283
|
+
html: u(e),
|
|
3213
3284
|
impact: "serious",
|
|
3214
3285
|
message: "Dialog has no accessible name."
|
|
3215
3286
|
});
|
|
3216
3287
|
}
|
|
3217
3288
|
return a;
|
|
3218
3289
|
}
|
|
3219
|
-
},
|
|
3290
|
+
}, Ha = {
|
|
3220
3291
|
id: "aria-tooltip-name",
|
|
3221
3292
|
wcag: ["4.1.2"],
|
|
3222
3293
|
level: "A",
|
|
@@ -3229,15 +3300,15 @@ const Ia = {
|
|
|
3229
3300
|
if (p(e)) continue;
|
|
3230
3301
|
v(e) || a.push({
|
|
3231
3302
|
ruleId: "aria-tooltip-name",
|
|
3232
|
-
selector:
|
|
3233
|
-
html:
|
|
3303
|
+
selector: m(e),
|
|
3304
|
+
html: u(e),
|
|
3234
3305
|
impact: "serious",
|
|
3235
3306
|
message: "Tooltip has no accessible name."
|
|
3236
3307
|
});
|
|
3237
3308
|
}
|
|
3238
3309
|
return a;
|
|
3239
3310
|
}
|
|
3240
|
-
},
|
|
3311
|
+
}, Da = {
|
|
3241
3312
|
id: "aria-treeitem-name",
|
|
3242
3313
|
wcag: ["4.1.2"],
|
|
3243
3314
|
level: "A",
|
|
@@ -3250,15 +3321,15 @@ const Ia = {
|
|
|
3250
3321
|
if (p(e)) continue;
|
|
3251
3322
|
v(e) || a.push({
|
|
3252
3323
|
ruleId: "aria-treeitem-name",
|
|
3253
|
-
selector:
|
|
3254
|
-
html:
|
|
3324
|
+
selector: m(e),
|
|
3325
|
+
html: u(e),
|
|
3255
3326
|
impact: "serious",
|
|
3256
3327
|
message: "Treeitem has no accessible name."
|
|
3257
3328
|
});
|
|
3258
3329
|
}
|
|
3259
3330
|
return a;
|
|
3260
3331
|
}
|
|
3261
|
-
},
|
|
3332
|
+
}, Oa = {
|
|
3262
3333
|
id: "aria-prohibited-attr",
|
|
3263
3334
|
wcag: ["4.1.2"],
|
|
3264
3335
|
level: "A",
|
|
@@ -3268,14 +3339,14 @@ const Ia = {
|
|
|
3268
3339
|
run(t) {
|
|
3269
3340
|
return z(t).prohibitedAttr;
|
|
3270
3341
|
}
|
|
3271
|
-
},
|
|
3342
|
+
}, Ba = [
|
|
3272
3343
|
"a[href]",
|
|
3273
3344
|
"button:not([disabled])",
|
|
3274
3345
|
'input:not([disabled]):not([type="hidden"])',
|
|
3275
3346
|
"select:not([disabled])",
|
|
3276
3347
|
"textarea:not([disabled])",
|
|
3277
3348
|
'[tabindex]:not([tabindex="-1"])'
|
|
3278
|
-
].join(", "),
|
|
3349
|
+
].join(", "), Fa = [
|
|
3279
3350
|
"aria-atomic",
|
|
3280
3351
|
"aria-busy",
|
|
3281
3352
|
"aria-controls",
|
|
@@ -3292,15 +3363,15 @@ const Ia = {
|
|
|
3292
3363
|
];
|
|
3293
3364
|
function re(t) {
|
|
3294
3365
|
const a = [];
|
|
3295
|
-
t.matches(
|
|
3296
|
-
for (const e of
|
|
3366
|
+
t.matches(Ba) && a.push("element is focusable");
|
|
3367
|
+
for (const e of Fa)
|
|
3297
3368
|
if (t.hasAttribute(e)) {
|
|
3298
3369
|
a.push(`has ${e}`);
|
|
3299
3370
|
break;
|
|
3300
3371
|
}
|
|
3301
3372
|
return (t.hasAttribute("aria-label") || t.hasAttribute("aria-labelledby")) && a.push("has accessible name"), a;
|
|
3302
3373
|
}
|
|
3303
|
-
const
|
|
3374
|
+
const Wa = {
|
|
3304
3375
|
id: "presentation-role-conflict",
|
|
3305
3376
|
wcag: ["4.1.2"],
|
|
3306
3377
|
level: "A",
|
|
@@ -3314,8 +3385,8 @@ const Ba = {
|
|
|
3314
3385
|
const i = re(e);
|
|
3315
3386
|
i.length > 0 && a.push({
|
|
3316
3387
|
ruleId: "presentation-role-conflict",
|
|
3317
|
-
selector:
|
|
3318
|
-
html:
|
|
3388
|
+
selector: m(e),
|
|
3389
|
+
html: u(e),
|
|
3319
3390
|
impact: "serious",
|
|
3320
3391
|
message: `Presentation role conflicts with: ${i.join(", ")}. The role will be ignored.`
|
|
3321
3392
|
});
|
|
@@ -3325,8 +3396,8 @@ const Ba = {
|
|
|
3325
3396
|
const i = re(e);
|
|
3326
3397
|
i.length > 0 && a.push({
|
|
3327
3398
|
ruleId: "presentation-role-conflict",
|
|
3328
|
-
selector:
|
|
3329
|
-
html:
|
|
3399
|
+
selector: m(e),
|
|
3400
|
+
html: u(e),
|
|
3330
3401
|
impact: "serious",
|
|
3331
3402
|
message: `Element with implicit presentation role (alt="") conflicts with: ${i.join(", ")}. The decorative role will be ignored.`
|
|
3332
3403
|
});
|
|
@@ -3346,8 +3417,8 @@ const Ba = {
|
|
|
3346
3417
|
if (p(e)) continue;
|
|
3347
3418
|
v(e) || a.push({
|
|
3348
3419
|
ruleId: "summary-name",
|
|
3349
|
-
selector:
|
|
3350
|
-
html:
|
|
3420
|
+
selector: m(e),
|
|
3421
|
+
html: u(e),
|
|
3351
3422
|
impact: "serious",
|
|
3352
3423
|
message: "<summary> element has no accessible name. Add descriptive text."
|
|
3353
3424
|
});
|
|
@@ -3355,7 +3426,7 @@ const Ba = {
|
|
|
3355
3426
|
return a;
|
|
3356
3427
|
}
|
|
3357
3428
|
};
|
|
3358
|
-
function
|
|
3429
|
+
function Pa(t) {
|
|
3359
3430
|
var n, r;
|
|
3360
3431
|
const a = [], e = t.getAttribute("href");
|
|
3361
3432
|
e && a.push(`href: ${e}`);
|
|
@@ -3385,16 +3456,16 @@ const ja = {
|
|
|
3385
3456
|
if (p(e)) continue;
|
|
3386
3457
|
v(e) || a.push({
|
|
3387
3458
|
ruleId: "link-name",
|
|
3388
|
-
selector:
|
|
3389
|
-
html:
|
|
3459
|
+
selector: m(e),
|
|
3460
|
+
html: u(e),
|
|
3390
3461
|
impact: "serious",
|
|
3391
3462
|
message: "Link has no discernible text.",
|
|
3392
|
-
context:
|
|
3463
|
+
context: Pa(e)
|
|
3393
3464
|
});
|
|
3394
3465
|
}
|
|
3395
3466
|
return a;
|
|
3396
3467
|
}
|
|
3397
|
-
},
|
|
3468
|
+
}, Va = {
|
|
3398
3469
|
id: "skip-link",
|
|
3399
3470
|
wcag: ["2.4.1"],
|
|
3400
3471
|
level: "A",
|
|
@@ -3407,20 +3478,20 @@ const ja = {
|
|
|
3407
3478
|
for (const i of e) {
|
|
3408
3479
|
const n = i.getAttribute("href");
|
|
3409
3480
|
if (!n || n === "#") continue;
|
|
3410
|
-
const r =
|
|
3481
|
+
const r = w(i).toLowerCase();
|
|
3411
3482
|
if (!(r.includes("skip") || r.includes("jump") || r.includes("main content") || r.includes("navigation"))) continue;
|
|
3412
3483
|
const s = n.slice(1);
|
|
3413
3484
|
t.getElementById(s) || a.push({
|
|
3414
3485
|
ruleId: "skip-link",
|
|
3415
|
-
selector:
|
|
3416
|
-
html:
|
|
3486
|
+
selector: m(i),
|
|
3487
|
+
html: u(i),
|
|
3417
3488
|
impact: "moderate",
|
|
3418
3489
|
message: `Skip link points to "#${s}" which does not exist on the page.`
|
|
3419
3490
|
});
|
|
3420
3491
|
}
|
|
3421
3492
|
return a;
|
|
3422
3493
|
}
|
|
3423
|
-
},
|
|
3494
|
+
}, za = /* @__PURE__ */ new Set([
|
|
3424
3495
|
"block",
|
|
3425
3496
|
"flex",
|
|
3426
3497
|
"grid",
|
|
@@ -3428,23 +3499,23 @@ const ja = {
|
|
|
3428
3499
|
"table-cell",
|
|
3429
3500
|
"list-item",
|
|
3430
3501
|
"flow-root"
|
|
3431
|
-
]),
|
|
3502
|
+
]), Ua = /* @__PURE__ */ new Set([
|
|
3432
3503
|
"inline",
|
|
3433
3504
|
"inline-block",
|
|
3434
3505
|
"inline-flex",
|
|
3435
3506
|
"inline-grid"
|
|
3436
3507
|
]);
|
|
3437
|
-
function
|
|
3508
|
+
function Ga(t) {
|
|
3438
3509
|
let a = t.parentElement;
|
|
3439
3510
|
for (; a; ) {
|
|
3440
3511
|
const e = A(a).display;
|
|
3441
|
-
if (
|
|
3442
|
-
return a;
|
|
3512
|
+
if (za.has(e))
|
|
3513
|
+
return Xa(a) ? a : null;
|
|
3443
3514
|
a = a.parentElement;
|
|
3444
3515
|
}
|
|
3445
3516
|
return null;
|
|
3446
3517
|
}
|
|
3447
|
-
function
|
|
3518
|
+
function Xa(t) {
|
|
3448
3519
|
const a = t.ownerDocument.createTreeWalker(
|
|
3449
3520
|
t,
|
|
3450
3521
|
NodeFilter.SHOW_TEXT
|
|
@@ -3464,7 +3535,7 @@ function Ga(t) {
|
|
|
3464
3535
|
}
|
|
3465
3536
|
return !1;
|
|
3466
3537
|
}
|
|
3467
|
-
function
|
|
3538
|
+
function Ya(t, a) {
|
|
3468
3539
|
const e = t.ownerDocument.createTreeWalker(
|
|
3469
3540
|
t,
|
|
3470
3541
|
NodeFilter.SHOW_TEXT
|
|
@@ -3485,7 +3556,7 @@ function Xa(t, a) {
|
|
|
3485
3556
|
}
|
|
3486
3557
|
return null;
|
|
3487
3558
|
}
|
|
3488
|
-
function
|
|
3559
|
+
function Ka(t, a) {
|
|
3489
3560
|
const e = t.textDecorationLine || t.textDecoration || "", i = a.textDecorationLine || a.textDecoration || "";
|
|
3490
3561
|
if ((e.includes("underline") || e.includes("line-through")) && e !== i)
|
|
3491
3562
|
return !0;
|
|
@@ -3495,14 +3566,14 @@ function Ya(t, a) {
|
|
|
3495
3566
|
const o = parseFloat(t.outlineWidth) || 0, s = t.outlineStyle || "";
|
|
3496
3567
|
if (o > 0 && s !== "none")
|
|
3497
3568
|
return !0;
|
|
3498
|
-
const
|
|
3499
|
-
if (
|
|
3569
|
+
const l = t.backgroundImage || "";
|
|
3570
|
+
if (l && l !== "none" && l !== "initial")
|
|
3500
3571
|
return !0;
|
|
3501
|
-
const h = oe(t.fontWeight),
|
|
3502
|
-
if (Math.abs(h -
|
|
3572
|
+
const h = oe(t.fontWeight), c = oe(a.fontWeight);
|
|
3573
|
+
if (Math.abs(h - c) >= 300 || t.fontStyle !== a.fontStyle)
|
|
3503
3574
|
return !0;
|
|
3504
|
-
const
|
|
3505
|
-
return g > 0 &&
|
|
3575
|
+
const d = parseFloat(t.fontSize) || 16, g = parseFloat(a.fontSize) || 16;
|
|
3576
|
+
return g > 0 && d / g >= 1.2;
|
|
3506
3577
|
}
|
|
3507
3578
|
function oe(t) {
|
|
3508
3579
|
return t === "bold" ? 700 : t === "normal" ? 400 : parseInt(t) || 400;
|
|
@@ -3510,7 +3581,7 @@ function oe(t) {
|
|
|
3510
3581
|
function se(t, a, e) {
|
|
3511
3582
|
return "#" + [t, a, e].map((i) => i.toString(16).padStart(2, "0")).join("");
|
|
3512
3583
|
}
|
|
3513
|
-
const
|
|
3584
|
+
const Ja = {
|
|
3514
3585
|
id: "link-in-text-block",
|
|
3515
3586
|
wcag: ["1.4.1"],
|
|
3516
3587
|
level: "A",
|
|
@@ -3520,22 +3591,22 @@ const Ka = {
|
|
|
3520
3591
|
run(t) {
|
|
3521
3592
|
const a = [];
|
|
3522
3593
|
for (const e of t.querySelectorAll("a[href]")) {
|
|
3523
|
-
if (p(e) || !
|
|
3594
|
+
if (p(e) || !w(e).trim() || e.closest('nav, [role="navigation"], [role="banner"], [role="contentinfo"]')) continue;
|
|
3524
3595
|
const i = A(e), n = i.display || "inline";
|
|
3525
|
-
if (!
|
|
3526
|
-
const r =
|
|
3596
|
+
if (!Ua.has(n)) continue;
|
|
3597
|
+
const r = Ga(e);
|
|
3527
3598
|
if (!r) continue;
|
|
3528
3599
|
const o = A(r);
|
|
3529
|
-
if (
|
|
3530
|
-
const s = R(i.color),
|
|
3531
|
-
if (!s || !
|
|
3532
|
-
const h = q(...s),
|
|
3533
|
-
if (
|
|
3534
|
-
const g = se(...s), b = se(...
|
|
3600
|
+
if (Ka(i, o)) continue;
|
|
3601
|
+
const s = R(i.color), l = Ya(r);
|
|
3602
|
+
if (!s || !l) continue;
|
|
3603
|
+
const h = q(...s), c = q(...l), d = de(h, c);
|
|
3604
|
+
if (d >= 3) continue;
|
|
3605
|
+
const g = se(...s), b = se(...l), f = `link color: ${g} rgb(${s.join(", ")}), surrounding text: ${b} rgb(${l.join(", ")}), ratio: ${d.toFixed(2)}:1`;
|
|
3535
3606
|
a.push({
|
|
3536
3607
|
ruleId: "link-in-text-block",
|
|
3537
|
-
selector:
|
|
3538
|
-
html:
|
|
3608
|
+
selector: m(e),
|
|
3609
|
+
html: u(e),
|
|
3539
3610
|
impact: "serious",
|
|
3540
3611
|
message: "Link in text block is not visually distinguishable from surrounding text. Add an underline, border, or ensure 3:1 color contrast with surrounding text.",
|
|
3541
3612
|
context: f
|
|
@@ -3549,36 +3620,45 @@ const Ka = {
|
|
|
3549
3620
|
level: "A",
|
|
3550
3621
|
description: "The <html> element must have a lang attribute.",
|
|
3551
3622
|
guidance: "Screen readers use the lang attribute to determine which language rules and pronunciation to use. Without it, content may be mispronounced. Set lang to the primary language of the page (e.g., lang='en' for English, lang='es' for Spanish).",
|
|
3552
|
-
prompt:
|
|
3623
|
+
prompt: `The page is missing a lang attribute on <html>. Use the text sample in context to determine the primary language and suggest the correct BCP 47 code (e.g. 'en' for English, 'es' for Spanish, 'fr' for French, 'de' for German, 'ja' for Japanese, 'zh' for Chinese, 'pt' for Portuguese, 'ar' for Arabic). Add lang to the <html> element: <html lang="...">.`,
|
|
3553
3624
|
run(t) {
|
|
3554
|
-
var e;
|
|
3625
|
+
var e, i;
|
|
3555
3626
|
const a = t.documentElement;
|
|
3556
3627
|
if (a.tagName.toLowerCase() !== "html") return [];
|
|
3557
3628
|
if (!t.doctype && t.body) {
|
|
3558
|
-
const
|
|
3559
|
-
if (
|
|
3560
|
-
(
|
|
3629
|
+
const n = t.body.children;
|
|
3630
|
+
if (n.length > 0 && Array.from(n).every(
|
|
3631
|
+
(r) => r.tagName.toLowerCase() === "svg" || r.tagName.toLowerCase() === "math"
|
|
3561
3632
|
)) return [];
|
|
3562
3633
|
}
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3634
|
+
if (!((e = a.getAttribute("lang")) != null && e.trim())) {
|
|
3635
|
+
let n;
|
|
3636
|
+
if (t.body) {
|
|
3637
|
+
const r = ((i = t.body.textContent) == null ? void 0 : i.trim().replace(/\s+/g, " ")) || "";
|
|
3638
|
+
r && (n = r.slice(0, 200));
|
|
3639
|
+
}
|
|
3640
|
+
return [{
|
|
3641
|
+
ruleId: "html-has-lang",
|
|
3642
|
+
selector: m(a),
|
|
3643
|
+
html: u(a),
|
|
3644
|
+
impact: "serious",
|
|
3645
|
+
message: "<html> element missing lang attribute.",
|
|
3646
|
+
context: n ? `Page text sample: "${n}"` : void 0
|
|
3647
|
+
}];
|
|
3648
|
+
}
|
|
3649
|
+
return [];
|
|
3570
3650
|
}
|
|
3571
|
-
},
|
|
3651
|
+
}, Za = new Set(
|
|
3572
3652
|
"aa ab ae af ak am an ar as av ay az ba be bg bh bi bm bn bo br bs ca ce ch co cr cs cu cv cy da de dv dz ee el en eo es et eu fa ff fi fj fo fr fy ga gd gl gn gu gv ha he hi ho hr ht hu hy hz ia id ie ig ii ik io is it iu ja jv ka kg ki kj kk kl km kn ko kr ks ku kv kw ky la lb lg li ln lo lt lu lv mg mh mi mk ml mn mr ms mt my na nb nd ne ng nl nn no nr nv ny oc oj om or os pa pi pl ps pt qu rm rn ro ru rw sa sc sd se sg si sk sl sm sn so sq sr ss st su sv sw ta te tg th ti tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa wo xh yi yo za zh zu".split(" ")
|
|
3573
|
-
),
|
|
3653
|
+
), ei = new Set(
|
|
3574
3654
|
"aar abk afr aka amh ara arg asm ava ave aym aze bak bam bel ben bih bis bod bos bre bul cat ces cha che chu chv cor cos cre cym dan deu div dzo ell eng epo est eus ewe fao fas fij fin fra fry ful gla gle glg glv grn guj hat hau hbs heb her hin hmo hrv hun hye ibo iii iku ile ina ind ipk isl ita jav jpn kal kan kas kat kau kaz khm kik kin kir kom kon kor kua kur lao lat lav lim lin lit ltz lub lug mah mal mar mkd mlg mlt mon mri msa mya nau nav nbl nde ndo nep nld nno nob nor nya oci oji ori orm oss pan pli pol por pus que roh ron run rus sag san sin slk slv sme smo sna snd som sot spa sqi srd srp ssw sun swa swe tah tam tat tel tgk tgl tha tir ton tsn tso tuk tur twi uig ukr urd uzb ven vie vol wln wol xho yid yor zha zho zul".split(" ")
|
|
3575
|
-
),
|
|
3576
|
-
function
|
|
3577
|
-
if (!
|
|
3655
|
+
), ti = /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i;
|
|
3656
|
+
function he(t) {
|
|
3657
|
+
if (!ti.test(t)) return !1;
|
|
3578
3658
|
const a = t.split("-")[0].toLowerCase();
|
|
3579
|
-
return a.length === 2 ?
|
|
3659
|
+
return a.length === 2 ? Za.has(a) : a.length === 3 ? !ei.has(a) : !1;
|
|
3580
3660
|
}
|
|
3581
|
-
const
|
|
3661
|
+
const ai = {
|
|
3582
3662
|
id: "html-lang-valid",
|
|
3583
3663
|
wcag: ["3.1.1"],
|
|
3584
3664
|
level: "A",
|
|
@@ -3588,10 +3668,10 @@ const ti = {
|
|
|
3588
3668
|
run(t) {
|
|
3589
3669
|
var e;
|
|
3590
3670
|
const a = (e = t.documentElement.getAttribute("lang")) == null ? void 0 : e.trim();
|
|
3591
|
-
return a && !
|
|
3671
|
+
return a && !he(a) ? [{
|
|
3592
3672
|
ruleId: "html-lang-valid",
|
|
3593
3673
|
selector: "html",
|
|
3594
|
-
html:
|
|
3674
|
+
html: u(t.documentElement),
|
|
3595
3675
|
impact: "serious",
|
|
3596
3676
|
message: `Invalid lang attribute value "${a}".`
|
|
3597
3677
|
}] : [];
|
|
@@ -3629,7 +3709,7 @@ function le(t) {
|
|
|
3629
3709
|
}
|
|
3630
3710
|
return !1;
|
|
3631
3711
|
}
|
|
3632
|
-
const
|
|
3712
|
+
const ii = {
|
|
3633
3713
|
id: "valid-lang",
|
|
3634
3714
|
wcag: ["3.1.2"],
|
|
3635
3715
|
level: "AA",
|
|
@@ -3644,24 +3724,24 @@ const ai = {
|
|
|
3644
3724
|
if (i && !n) {
|
|
3645
3725
|
le(e) && a.push({
|
|
3646
3726
|
ruleId: "valid-lang",
|
|
3647
|
-
selector:
|
|
3648
|
-
html:
|
|
3727
|
+
selector: m(e),
|
|
3728
|
+
html: u(e),
|
|
3649
3729
|
impact: "serious",
|
|
3650
3730
|
message: "Empty lang attribute value."
|
|
3651
3731
|
});
|
|
3652
3732
|
continue;
|
|
3653
3733
|
}
|
|
3654
|
-
n && le(e) && (
|
|
3734
|
+
n && le(e) && (he(n) || a.push({
|
|
3655
3735
|
ruleId: "valid-lang",
|
|
3656
|
-
selector:
|
|
3657
|
-
html:
|
|
3736
|
+
selector: m(e),
|
|
3737
|
+
html: u(e),
|
|
3658
3738
|
impact: "serious",
|
|
3659
3739
|
message: `Invalid lang attribute value "${n}".`
|
|
3660
3740
|
}));
|
|
3661
3741
|
}
|
|
3662
3742
|
return a;
|
|
3663
3743
|
}
|
|
3664
|
-
},
|
|
3744
|
+
}, ni = {
|
|
3665
3745
|
id: "html-xml-lang-mismatch",
|
|
3666
3746
|
wcag: ["3.1.1"],
|
|
3667
3747
|
level: "A",
|
|
@@ -3677,14 +3757,14 @@ const ai = {
|
|
|
3677
3757
|
return [{
|
|
3678
3758
|
ruleId: "html-xml-lang-mismatch",
|
|
3679
3759
|
selector: "html",
|
|
3680
|
-
html:
|
|
3760
|
+
html: u(a),
|
|
3681
3761
|
impact: "moderate",
|
|
3682
3762
|
message: `lang="${e}" and xml:lang="${i}" do not match.`
|
|
3683
3763
|
}];
|
|
3684
3764
|
}
|
|
3685
3765
|
return [];
|
|
3686
3766
|
}
|
|
3687
|
-
},
|
|
3767
|
+
}, ri = {
|
|
3688
3768
|
id: "td-headers-attr",
|
|
3689
3769
|
wcag: ["1.3.1"],
|
|
3690
3770
|
level: "A",
|
|
@@ -3702,8 +3782,8 @@ const ai = {
|
|
|
3702
3782
|
if (o === n) {
|
|
3703
3783
|
a.push({
|
|
3704
3784
|
ruleId: "td-headers-attr",
|
|
3705
|
-
selector:
|
|
3706
|
-
html:
|
|
3785
|
+
selector: m(e),
|
|
3786
|
+
html: u(e),
|
|
3707
3787
|
impact: "serious",
|
|
3708
3788
|
message: `Headers attribute references the cell itself ("${o}").`
|
|
3709
3789
|
});
|
|
@@ -3712,8 +3792,8 @@ const ai = {
|
|
|
3712
3792
|
if (!i.querySelector(`th#${CSS.escape(o)}, td#${CSS.escape(o)}`)) {
|
|
3713
3793
|
a.push({
|
|
3714
3794
|
ruleId: "td-headers-attr",
|
|
3715
|
-
selector:
|
|
3716
|
-
html:
|
|
3795
|
+
selector: m(e),
|
|
3796
|
+
html: u(e),
|
|
3717
3797
|
impact: "serious",
|
|
3718
3798
|
message: `Headers attribute references non-existent ID "${o}".`
|
|
3719
3799
|
});
|
|
@@ -3723,7 +3803,7 @@ const ai = {
|
|
|
3723
3803
|
}
|
|
3724
3804
|
return a;
|
|
3725
3805
|
}
|
|
3726
|
-
},
|
|
3806
|
+
}, oi = {
|
|
3727
3807
|
id: "th-has-data-cells",
|
|
3728
3808
|
wcag: ["1.3.1"],
|
|
3729
3809
|
level: "A",
|
|
@@ -3737,15 +3817,15 @@ const ai = {
|
|
|
3737
3817
|
const i = e.querySelectorAll("th"), n = e.querySelectorAll("td");
|
|
3738
3818
|
i.length > 0 && n.length === 0 && a.push({
|
|
3739
3819
|
ruleId: "th-has-data-cells",
|
|
3740
|
-
selector:
|
|
3741
|
-
html:
|
|
3820
|
+
selector: m(e),
|
|
3821
|
+
html: u(e),
|
|
3742
3822
|
impact: "serious",
|
|
3743
3823
|
message: "Table has header cells but no data cells."
|
|
3744
3824
|
});
|
|
3745
3825
|
}
|
|
3746
3826
|
return a;
|
|
3747
3827
|
}
|
|
3748
|
-
},
|
|
3828
|
+
}, si = {
|
|
3749
3829
|
id: "td-has-header",
|
|
3750
3830
|
wcag: ["1.3.1"],
|
|
3751
3831
|
level: "A",
|
|
@@ -3759,36 +3839,36 @@ const ai = {
|
|
|
3759
3839
|
if (p(n) || n.getAttribute("role") === "presentation" || n.getAttribute("role") === "none") continue;
|
|
3760
3840
|
const r = n.querySelectorAll("tr"), o = r.length;
|
|
3761
3841
|
let s = 0;
|
|
3762
|
-
for (const
|
|
3763
|
-
const g =
|
|
3842
|
+
for (const d of r) {
|
|
3843
|
+
const g = d.querySelectorAll("td, th");
|
|
3764
3844
|
let b = 0;
|
|
3765
3845
|
for (const f of g)
|
|
3766
3846
|
b += parseInt(f.getAttribute("colspan") || "1", 10);
|
|
3767
3847
|
s = Math.max(s, b);
|
|
3768
3848
|
}
|
|
3769
3849
|
if (o <= 3 && s <= 3) continue;
|
|
3770
|
-
const
|
|
3771
|
-
if (
|
|
3772
|
-
for (const
|
|
3773
|
-
if (p(
|
|
3774
|
-
const g =
|
|
3850
|
+
const l = n.querySelector("th") !== null, h = n.querySelector("th[scope]") !== null, c = n.querySelector("td[headers]") !== null;
|
|
3851
|
+
if (l)
|
|
3852
|
+
for (const d of n.querySelectorAll("td")) {
|
|
3853
|
+
if (p(d) || d.hasAttribute("headers")) continue;
|
|
3854
|
+
const g = d.closest("tr");
|
|
3775
3855
|
if (!g) continue;
|
|
3776
|
-
const b = g.querySelector("th") !== null, f = Array.from(g.children).indexOf(
|
|
3777
|
-
let
|
|
3856
|
+
const b = g.querySelector("th") !== null, f = Array.from(g.children).indexOf(d);
|
|
3857
|
+
let y = !1;
|
|
3778
3858
|
const I = n.querySelector("thead");
|
|
3779
3859
|
if (I) {
|
|
3780
|
-
const
|
|
3781
|
-
|
|
3860
|
+
const x = I.querySelector("tr");
|
|
3861
|
+
x && ((e = x.querySelectorAll("th, td")[f]) == null ? void 0 : e.tagName.toLowerCase()) === "th" && (y = !0);
|
|
3782
3862
|
}
|
|
3783
|
-
if (!
|
|
3784
|
-
const
|
|
3785
|
-
|
|
3863
|
+
if (!y) {
|
|
3864
|
+
const x = n.querySelector("tbody > tr, tr");
|
|
3865
|
+
x && ((i = x.querySelectorAll("th, td")[f]) == null ? void 0 : i.tagName.toLowerCase()) === "th" && (y = !0);
|
|
3786
3866
|
}
|
|
3787
|
-
if (!b && !
|
|
3867
|
+
if (!b && !y && !h && !c) {
|
|
3788
3868
|
a.push({
|
|
3789
3869
|
ruleId: "td-has-header",
|
|
3790
|
-
selector: d
|
|
3791
|
-
html:
|
|
3870
|
+
selector: m(d),
|
|
3871
|
+
html: u(d),
|
|
3792
3872
|
impact: "serious",
|
|
3793
3873
|
message: "Data cell has no associated header. Add th elements with scope, or headers attribute."
|
|
3794
3874
|
});
|
|
@@ -3798,7 +3878,7 @@ const ai = {
|
|
|
3798
3878
|
}
|
|
3799
3879
|
return a;
|
|
3800
3880
|
}
|
|
3801
|
-
},
|
|
3881
|
+
}, li = {
|
|
3802
3882
|
id: "scope-attr-valid",
|
|
3803
3883
|
wcag: ["1.3.1"],
|
|
3804
3884
|
level: "A",
|
|
@@ -3813,15 +3893,15 @@ const ai = {
|
|
|
3813
3893
|
const r = (i = n.getAttribute("scope")) == null ? void 0 : i.toLowerCase();
|
|
3814
3894
|
r && !e.has(r) && a.push({
|
|
3815
3895
|
ruleId: "scope-attr-valid",
|
|
3816
|
-
selector:
|
|
3817
|
-
html:
|
|
3896
|
+
selector: m(n),
|
|
3897
|
+
html: u(n),
|
|
3818
3898
|
impact: "moderate",
|
|
3819
3899
|
message: `Invalid scope value "${r}". Use row, col, rowgroup, or colgroup.`
|
|
3820
3900
|
});
|
|
3821
3901
|
}
|
|
3822
3902
|
return a;
|
|
3823
3903
|
}
|
|
3824
|
-
},
|
|
3904
|
+
}, ci = {
|
|
3825
3905
|
id: "empty-table-header",
|
|
3826
3906
|
wcag: [],
|
|
3827
3907
|
level: "A",
|
|
@@ -3836,15 +3916,15 @@ const ai = {
|
|
|
3836
3916
|
const i = e.closest("table");
|
|
3837
3917
|
(i == null ? void 0 : i.getAttribute("role")) === "presentation" || (i == null ? void 0 : i.getAttribute("role")) === "none" || v(e) || a.push({
|
|
3838
3918
|
ruleId: "empty-table-header",
|
|
3839
|
-
selector:
|
|
3840
|
-
html:
|
|
3919
|
+
selector: m(e),
|
|
3920
|
+
html: u(e),
|
|
3841
3921
|
impact: "minor",
|
|
3842
3922
|
message: "Table header cell is empty. Add text or use aria-label."
|
|
3843
3923
|
});
|
|
3844
3924
|
}
|
|
3845
3925
|
return a;
|
|
3846
3926
|
}
|
|
3847
|
-
}, D = ["aria-labelledby", "aria-describedby", "aria-controls", "aria-owns", "aria-flowto"],
|
|
3927
|
+
}, D = ["aria-labelledby", "aria-describedby", "aria-controls", "aria-owns", "aria-flowto"], ui = {
|
|
3848
3928
|
id: "duplicate-id-aria",
|
|
3849
3929
|
wcag: ["4.1.2"],
|
|
3850
3930
|
level: "A",
|
|
@@ -3868,31 +3948,31 @@ const ai = {
|
|
|
3868
3948
|
for (const [n, r] of i) {
|
|
3869
3949
|
if (r <= 1) continue;
|
|
3870
3950
|
const o = t.querySelectorAll(`#${CSS.escape(n)}`), s = t.querySelector(
|
|
3871
|
-
D.map((
|
|
3872
|
-
),
|
|
3951
|
+
D.map((c) => `[${c}~="${CSS.escape(n)}"]`).join(", ")
|
|
3952
|
+
), l = t.querySelector(`label[for="${CSS.escape(n)}"]`);
|
|
3873
3953
|
let h;
|
|
3874
3954
|
if (s) {
|
|
3875
|
-
const
|
|
3876
|
-
(
|
|
3955
|
+
const c = D.find(
|
|
3956
|
+
(d) => {
|
|
3877
3957
|
var g;
|
|
3878
|
-
return (g = s.getAttribute(
|
|
3958
|
+
return (g = s.getAttribute(d)) == null ? void 0 : g.split(/\s+/).includes(n);
|
|
3879
3959
|
}
|
|
3880
3960
|
);
|
|
3881
|
-
|
|
3882
|
-
} else
|
|
3961
|
+
c && (h = c);
|
|
3962
|
+
} else l && (h = "label[for]");
|
|
3883
3963
|
a.push({
|
|
3884
3964
|
ruleId: "duplicate-id-aria",
|
|
3885
|
-
selector:
|
|
3886
|
-
html:
|
|
3965
|
+
selector: m(o[1]),
|
|
3966
|
+
html: u(o[1]),
|
|
3887
3967
|
impact: "critical",
|
|
3888
3968
|
message: `Duplicate ID "${n}" referenced by ${h ?? "an accessibility attribute"}.`,
|
|
3889
|
-
context: `First element: ${
|
|
3969
|
+
context: `First element: ${u(o[0])}${h ? `
|
|
3890
3970
|
Referenced by: ${h}` : ""}`
|
|
3891
3971
|
});
|
|
3892
3972
|
}
|
|
3893
3973
|
return a;
|
|
3894
3974
|
}
|
|
3895
|
-
},
|
|
3975
|
+
}, di = {
|
|
3896
3976
|
id: "video-caption",
|
|
3897
3977
|
wcag: ["1.2.2"],
|
|
3898
3978
|
level: "A",
|
|
@@ -3905,15 +3985,15 @@ Referenced by: ${h}` : ""}`
|
|
|
3905
3985
|
if (p(e) || e.hasAttribute("muted") || e.hasAttribute("autoplay")) continue;
|
|
3906
3986
|
e.querySelector('track[kind="captions"], track[kind="subtitles"]') || a.push({
|
|
3907
3987
|
ruleId: "video-caption",
|
|
3908
|
-
selector:
|
|
3909
|
-
html:
|
|
3988
|
+
selector: m(e),
|
|
3989
|
+
html: u(e),
|
|
3910
3990
|
impact: "critical",
|
|
3911
3991
|
message: "Video element has no captions track."
|
|
3912
3992
|
});
|
|
3913
3993
|
}
|
|
3914
3994
|
return a;
|
|
3915
3995
|
}
|
|
3916
|
-
},
|
|
3996
|
+
}, mi = {
|
|
3917
3997
|
id: "audio-caption",
|
|
3918
3998
|
wcag: ["1.2.1"],
|
|
3919
3999
|
level: "A",
|
|
@@ -3927,15 +4007,15 @@ Referenced by: ${h}` : ""}`
|
|
|
3927
4007
|
const n = e.parentElement;
|
|
3928
4008
|
n && n.querySelector('a[href*="transcript"], a[href*="text"]') || a.push({
|
|
3929
4009
|
ruleId: "audio-caption",
|
|
3930
|
-
selector:
|
|
3931
|
-
html:
|
|
4010
|
+
selector: m(e),
|
|
4011
|
+
html: u(e),
|
|
3932
4012
|
impact: "critical",
|
|
3933
4013
|
message: "Audio element has no transcript or text alternative. Add a transcript or track element."
|
|
3934
4014
|
});
|
|
3935
4015
|
}
|
|
3936
4016
|
return a;
|
|
3937
4017
|
}
|
|
3938
|
-
},
|
|
4018
|
+
}, hi = /* @__PURE__ */ new Set([
|
|
3939
4019
|
"SCRIPT",
|
|
3940
4020
|
"STYLE",
|
|
3941
4021
|
"NOSCRIPT",
|
|
@@ -3954,10 +4034,10 @@ Referenced by: ${h}` : ""}`
|
|
|
3954
4034
|
function ce([t, a, e]) {
|
|
3955
4035
|
return "#" + [t, a, e].map((i) => i.toString(16).padStart(2, "0")).join("");
|
|
3956
4036
|
}
|
|
3957
|
-
function
|
|
4037
|
+
function pi(t) {
|
|
3958
4038
|
return t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement || t instanceof HTMLSelectElement || t instanceof HTMLButtonElement ? t.disabled : !!(t.closest("fieldset[disabled]") || t.getAttribute("aria-disabled") === "true");
|
|
3959
4039
|
}
|
|
3960
|
-
function
|
|
4040
|
+
function gi(t, a) {
|
|
3961
4041
|
if (t.tagName !== "LABEL") return !1;
|
|
3962
4042
|
const e = t, i = e.htmlFor;
|
|
3963
4043
|
if (i) {
|
|
@@ -3969,7 +4049,7 @@ function pi(t, a) {
|
|
|
3969
4049
|
const r = e.id;
|
|
3970
4050
|
return !!(r && a.querySelector(`[aria-labelledby~="${r}"][aria-disabled="true"]`));
|
|
3971
4051
|
}
|
|
3972
|
-
function
|
|
4052
|
+
function bi(t) {
|
|
3973
4053
|
const a = t.clip;
|
|
3974
4054
|
if (a && a.startsWith("rect(")) {
|
|
3975
4055
|
const i = a.match(/[\d.]+/g);
|
|
@@ -3983,17 +4063,17 @@ function gi(t) {
|
|
|
3983
4063
|
}
|
|
3984
4064
|
return !1;
|
|
3985
4065
|
}
|
|
3986
|
-
function
|
|
4066
|
+
function fi(t) {
|
|
3987
4067
|
if (p(t)) return !0;
|
|
3988
4068
|
let a = t;
|
|
3989
4069
|
for (; a; ) {
|
|
3990
4070
|
const e = A(a);
|
|
3991
|
-
if (e.display === "none" || e.visibility === "hidden" ||
|
|
4071
|
+
if (e.display === "none" || e.visibility === "hidden" || bi(e)) return !0;
|
|
3992
4072
|
a = a.parentElement;
|
|
3993
4073
|
}
|
|
3994
4074
|
return !1;
|
|
3995
4075
|
}
|
|
3996
|
-
const
|
|
4076
|
+
const vi = {
|
|
3997
4077
|
id: "color-contrast",
|
|
3998
4078
|
wcag: ["1.4.3"],
|
|
3999
4079
|
level: "AA",
|
|
@@ -4008,140 +4088,140 @@ const fi = {
|
|
|
4008
4088
|
for (; r = i.nextNode(); ) {
|
|
4009
4089
|
if (!r.textContent || !r.textContent.trim()) continue;
|
|
4010
4090
|
const o = r.parentElement;
|
|
4011
|
-
if (!o || n.has(o) || (n.add(o),
|
|
4091
|
+
if (!o || n.has(o) || (n.add(o), hi.has(o.tagName)) || pi(o) || gi(o, t) || fi(o)) continue;
|
|
4012
4092
|
const s = A(o);
|
|
4013
4093
|
if (parseFloat(s.opacity) === 0) continue;
|
|
4014
|
-
const
|
|
4015
|
-
if (
|
|
4094
|
+
const l = s.textShadow;
|
|
4095
|
+
if (l && l !== "none" && l !== "initial") continue;
|
|
4016
4096
|
const h = R(s.color);
|
|
4017
4097
|
if (!h) continue;
|
|
4018
|
-
const
|
|
4019
|
-
if (
|
|
4020
|
-
const
|
|
4021
|
-
if (!
|
|
4022
|
-
const g = q(h[0], h[1], h[2]), b = q(
|
|
4023
|
-
if (f <
|
|
4024
|
-
const I = Math.round(f * 100) / 100,
|
|
4098
|
+
const c = s.color.match(/rgba\(.+?,\s*([\d.]+)\s*\)/) || s.color.match(/rgba?\(.+?\/\s*([\d.]+%?)\s*\)/);
|
|
4099
|
+
if (c && (c[1].endsWith("%") ? parseFloat(c[1]) / 100 : parseFloat(c[1])) === 0 || Fe(o)) continue;
|
|
4100
|
+
const d = De(o);
|
|
4101
|
+
if (!d) continue;
|
|
4102
|
+
const g = q(h[0], h[1], h[2]), b = q(d[0], d[1], d[2]), f = de(g, b), y = Pe(o) ? 3 : 4.5;
|
|
4103
|
+
if (f < y) {
|
|
4104
|
+
const I = Math.round(f * 100) / 100, x = ce(h), $ = ce(d);
|
|
4025
4105
|
a.push({
|
|
4026
4106
|
ruleId: "color-contrast",
|
|
4027
|
-
selector:
|
|
4028
|
-
html:
|
|
4107
|
+
selector: m(o),
|
|
4108
|
+
html: u(o),
|
|
4029
4109
|
impact: "serious",
|
|
4030
|
-
message: `Insufficient color contrast ratio of ${I}:1 (required ${
|
|
4031
|
-
context: `foreground: ${
|
|
4110
|
+
message: `Insufficient color contrast ratio of ${I}:1 (required ${y}:1).`,
|
|
4111
|
+
context: `foreground: ${x} rgb(${h.join(", ")}), background: ${$} rgb(${d.join(", ")}), ratio: ${I}:1, required: ${y}:1`
|
|
4032
4112
|
});
|
|
4033
4113
|
}
|
|
4034
4114
|
}
|
|
4035
4115
|
return a;
|
|
4036
4116
|
}
|
|
4037
|
-
},
|
|
4117
|
+
}, pe = [
|
|
4038
4118
|
// Document Structure
|
|
4039
|
-
Yt,
|
|
4040
4119
|
Kt,
|
|
4041
|
-
Qt,
|
|
4042
4120
|
Jt,
|
|
4121
|
+
Qt,
|
|
4043
4122
|
Zt,
|
|
4044
|
-
|
|
4123
|
+
ea,
|
|
4045
4124
|
aa,
|
|
4046
|
-
|
|
4047
|
-
|
|
4125
|
+
ia,
|
|
4126
|
+
ra,
|
|
4127
|
+
sa,
|
|
4048
4128
|
// Images
|
|
4049
4129
|
je,
|
|
4050
|
-
Ve,
|
|
4051
4130
|
ze,
|
|
4052
4131
|
Ue,
|
|
4053
|
-
|
|
4132
|
+
Ge,
|
|
4054
4133
|
Ye,
|
|
4134
|
+
Ke,
|
|
4055
4135
|
Qe,
|
|
4056
|
-
|
|
4057
|
-
|
|
4136
|
+
Ze,
|
|
4137
|
+
it,
|
|
4058
4138
|
// Forms
|
|
4059
|
-
st,
|
|
4060
4139
|
lt,
|
|
4061
4140
|
ct,
|
|
4062
4141
|
ut,
|
|
4063
|
-
|
|
4142
|
+
dt,
|
|
4064
4143
|
vt,
|
|
4144
|
+
yt,
|
|
4065
4145
|
wt,
|
|
4066
4146
|
// Keyboard
|
|
4067
|
-
At,
|
|
4068
4147
|
xt,
|
|
4069
|
-
|
|
4148
|
+
kt,
|
|
4070
4149
|
Rt,
|
|
4071
4150
|
Nt,
|
|
4151
|
+
$t,
|
|
4072
4152
|
// Structure
|
|
4073
4153
|
Mt,
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
$t,
|
|
4154
|
+
ta,
|
|
4155
|
+
la,
|
|
4077
4156
|
Ht,
|
|
4078
4157
|
Dt,
|
|
4079
4158
|
Ot,
|
|
4080
|
-
Wt,
|
|
4081
4159
|
Bt,
|
|
4082
|
-
_t,
|
|
4083
4160
|
Ft,
|
|
4084
|
-
|
|
4161
|
+
Wt,
|
|
4162
|
+
_t,
|
|
4085
4163
|
Pt,
|
|
4086
|
-
|
|
4164
|
+
jt,
|
|
4165
|
+
Vt,
|
|
4087
4166
|
Ut,
|
|
4088
|
-
|
|
4167
|
+
Gt,
|
|
4168
|
+
Yt,
|
|
4089
4169
|
// ARIA
|
|
4090
|
-
la,
|
|
4091
4170
|
ca,
|
|
4092
4171
|
ua,
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4172
|
+
da,
|
|
4173
|
+
ha,
|
|
4174
|
+
va,
|
|
4175
|
+
Aa,
|
|
4096
4176
|
Sa,
|
|
4097
|
-
|
|
4177
|
+
ka,
|
|
4098
4178
|
Ea,
|
|
4099
|
-
Ta,
|
|
4100
|
-
La,
|
|
4101
4179
|
Ca,
|
|
4180
|
+
La,
|
|
4102
4181
|
qa,
|
|
4103
4182
|
Ra,
|
|
4104
4183
|
Na,
|
|
4105
|
-
Ma,
|
|
4106
4184
|
$a,
|
|
4185
|
+
Ma,
|
|
4107
4186
|
Ha,
|
|
4108
4187
|
Da,
|
|
4109
|
-
|
|
4110
|
-
|
|
4188
|
+
Oa,
|
|
4189
|
+
Wa,
|
|
4190
|
+
ga,
|
|
4111
4191
|
_a,
|
|
4112
4192
|
// Links
|
|
4113
4193
|
ja,
|
|
4114
|
-
|
|
4115
|
-
|
|
4194
|
+
Va,
|
|
4195
|
+
Ja,
|
|
4116
4196
|
// Language
|
|
4117
4197
|
Qa,
|
|
4118
|
-
ti,
|
|
4119
4198
|
ai,
|
|
4120
4199
|
ii,
|
|
4121
|
-
// Tables
|
|
4122
4200
|
ni,
|
|
4201
|
+
// Tables
|
|
4123
4202
|
ri,
|
|
4124
4203
|
oi,
|
|
4125
4204
|
si,
|
|
4126
4205
|
li,
|
|
4127
|
-
// Parsing
|
|
4128
4206
|
ci,
|
|
4129
|
-
//
|
|
4207
|
+
// Parsing
|
|
4130
4208
|
ui,
|
|
4209
|
+
// Media
|
|
4131
4210
|
di,
|
|
4211
|
+
mi,
|
|
4132
4212
|
// Color
|
|
4133
|
-
|
|
4213
|
+
vi
|
|
4134
4214
|
];
|
|
4135
|
-
let U = [],
|
|
4136
|
-
function
|
|
4137
|
-
t.additionalRules && (U = t.additionalRules), t.disabledRules && (
|
|
4215
|
+
let U = [], ge = /* @__PURE__ */ new Set();
|
|
4216
|
+
function xi(t) {
|
|
4217
|
+
t.additionalRules && (U = t.additionalRules), t.disabledRules && (ge = new Set(t.disabledRules));
|
|
4138
4218
|
}
|
|
4139
|
-
function
|
|
4140
|
-
return
|
|
4219
|
+
function be() {
|
|
4220
|
+
return pe.filter((a) => !ge.has(a.id)).concat(U);
|
|
4141
4221
|
}
|
|
4142
4222
|
function Si(t) {
|
|
4143
|
-
|
|
4144
|
-
const a =
|
|
4223
|
+
fe();
|
|
4224
|
+
const a = be(), e = [];
|
|
4145
4225
|
let i = 0;
|
|
4146
4226
|
return {
|
|
4147
4227
|
processChunk(n) {
|
|
@@ -4160,13 +4240,13 @@ function Si(t) {
|
|
|
4160
4240
|
}
|
|
4161
4241
|
};
|
|
4162
4242
|
}
|
|
4163
|
-
function
|
|
4164
|
-
Se(),
|
|
4243
|
+
function fe() {
|
|
4244
|
+
Se(), ve(), ye(), He(), Me(), Ie();
|
|
4165
4245
|
}
|
|
4166
|
-
function
|
|
4246
|
+
function ki(t) {
|
|
4167
4247
|
var i;
|
|
4168
|
-
|
|
4169
|
-
const a =
|
|
4248
|
+
fe();
|
|
4249
|
+
const a = be(), e = [];
|
|
4170
4250
|
for (const n of a)
|
|
4171
4251
|
try {
|
|
4172
4252
|
e.push(...n.run(t));
|
|
@@ -4179,32 +4259,32 @@ function xi(t) {
|
|
|
4179
4259
|
ruleCount: a.length
|
|
4180
4260
|
};
|
|
4181
4261
|
}
|
|
4182
|
-
const
|
|
4183
|
-
function
|
|
4184
|
-
const a =
|
|
4262
|
+
const yi = new Map(pe.map((t) => [t.id, t]));
|
|
4263
|
+
function Ii(t) {
|
|
4264
|
+
const a = yi.get(t);
|
|
4185
4265
|
return a || U.find((e) => e.id === t);
|
|
4186
4266
|
}
|
|
4187
4267
|
export {
|
|
4188
|
-
|
|
4268
|
+
fe as clearAllCaches,
|
|
4189
4269
|
Me as clearAriaAttrAuditCache,
|
|
4190
4270
|
Se as clearAriaHiddenCache,
|
|
4191
|
-
|
|
4192
|
-
|
|
4271
|
+
He as clearColorCaches,
|
|
4272
|
+
ve as clearComputedRoleCache,
|
|
4193
4273
|
k as compileDeclarativeRule,
|
|
4194
|
-
|
|
4274
|
+
xi as configureRules,
|
|
4195
4275
|
Si as createChunkedAudit,
|
|
4196
4276
|
v as getAccessibleName,
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4277
|
+
w as getAccessibleTextContent,
|
|
4278
|
+
be as getActiveRules,
|
|
4279
|
+
L as getComputedRole,
|
|
4280
|
+
u as getHtmlSnippet,
|
|
4201
4281
|
ue as getImplicitRole,
|
|
4202
|
-
|
|
4203
|
-
|
|
4282
|
+
Ii as getRuleById,
|
|
4283
|
+
m as getSelector,
|
|
4204
4284
|
p as isAriaHidden,
|
|
4205
|
-
|
|
4285
|
+
xe as isValidRole,
|
|
4206
4286
|
wi as querySelectorShadowAware,
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4287
|
+
pe as rules,
|
|
4288
|
+
ki as runAudit,
|
|
4289
|
+
Ai as validateDeclarativeRule
|
|
4210
4290
|
};
|