@accesslint/core 0.8.3 → 0.8.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/README.md +3 -2
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/es.d.ts.map +1 -1
- package/dist/index.cjs +5 -5
- package/dist/index.iife.js +2 -2
- package/dist/index.js +705 -654
- package/dist/rules/aria/aria-allowed-role.d.ts.map +1 -1
- package/dist/rules/aria/presentational-children-focusable.d.ts.map +1 -1
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/input-assistance/accessible-authentication.d.ts +3 -0
- package/dist/rules/input-assistance/accessible-authentication.d.ts.map +1 -0
- package/dist/rules/text-alternatives/image-alt-words.d.ts +4 -4
- package/dist/rules/text-alternatives/image-alt-words.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const W = [
|
|
2
2
|
"a[href]",
|
|
3
3
|
"button:not([disabled])",
|
|
4
4
|
'input:not([disabled]):not([type="hidden"])',
|
|
@@ -15,7 +15,7 @@ const j = [
|
|
|
15
15
|
"area[href]"
|
|
16
16
|
].join(", ");
|
|
17
17
|
let K = /* @__PURE__ */ new WeakMap();
|
|
18
|
-
function
|
|
18
|
+
function rt() {
|
|
19
19
|
K = /* @__PURE__ */ new WeakMap();
|
|
20
20
|
}
|
|
21
21
|
function $e(e) {
|
|
@@ -133,7 +133,7 @@ function $e(e) {
|
|
|
133
133
|
return null;
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
|
-
function
|
|
136
|
+
function j(e) {
|
|
137
137
|
var n;
|
|
138
138
|
const a = K.get(e);
|
|
139
139
|
if (a !== void 0) return a;
|
|
@@ -144,14 +144,14 @@ let Q = /* @__PURE__ */ new WeakMap();
|
|
|
144
144
|
function st() {
|
|
145
145
|
Q = /* @__PURE__ */ new WeakMap();
|
|
146
146
|
}
|
|
147
|
-
function
|
|
147
|
+
function x(e) {
|
|
148
148
|
const a = Q.get(e);
|
|
149
149
|
if (a !== void 0) return a;
|
|
150
150
|
const t = lt(e);
|
|
151
151
|
return Q.set(e, t), t;
|
|
152
152
|
}
|
|
153
153
|
function lt(e) {
|
|
154
|
-
var
|
|
154
|
+
var o, r, s, l, d;
|
|
155
155
|
const a = e.getAttribute("aria-labelledby");
|
|
156
156
|
if (a) {
|
|
157
157
|
const c = a.split(/\s+/).map((u) => {
|
|
@@ -160,7 +160,7 @@ function lt(e) {
|
|
|
160
160
|
}).filter(Boolean);
|
|
161
161
|
if (c.length) return c.join(" ");
|
|
162
162
|
}
|
|
163
|
-
const t = (
|
|
163
|
+
const t = (o = e.getAttribute("aria-label")) == null ? void 0 : o.trim();
|
|
164
164
|
if (t) return t;
|
|
165
165
|
if (e instanceof HTMLInputElement || e instanceof HTMLTextAreaElement || e instanceof HTMLSelectElement) {
|
|
166
166
|
if (e.id) {
|
|
@@ -170,7 +170,7 @@ function lt(e) {
|
|
|
170
170
|
const c = e.closest("label"), u = c ? k(c).trim() : "";
|
|
171
171
|
if (u) return u;
|
|
172
172
|
}
|
|
173
|
-
const i = (
|
|
173
|
+
const i = (r = e.getAttribute("title")) == null ? void 0 : r.trim();
|
|
174
174
|
if (i) return i;
|
|
175
175
|
if (e instanceof HTMLInputElement || e instanceof HTMLTextAreaElement) {
|
|
176
176
|
const c = (s = e.getAttribute("placeholder")) == null ? void 0 : s.trim();
|
|
@@ -310,7 +310,7 @@ const ut = /* @__PURE__ */ new Set([
|
|
|
310
310
|
"aria-relevant",
|
|
311
311
|
"aria-roledescription"
|
|
312
312
|
]);
|
|
313
|
-
function
|
|
313
|
+
function I(e) {
|
|
314
314
|
let a = e;
|
|
315
315
|
for (; a; ) {
|
|
316
316
|
if (He(a)) return !0;
|
|
@@ -338,7 +338,7 @@ function He(e) {
|
|
|
338
338
|
return !1;
|
|
339
339
|
}
|
|
340
340
|
function k(e) {
|
|
341
|
-
var t, i, n,
|
|
341
|
+
var t, i, n, o, r;
|
|
342
342
|
let a = "";
|
|
343
343
|
for (const s of e.childNodes)
|
|
344
344
|
if (s.nodeType === 3)
|
|
@@ -361,14 +361,14 @@ function k(e) {
|
|
|
361
361
|
}
|
|
362
362
|
a += ((i = l.getAttribute("aria-label")) == null ? void 0 : i.trim()) ?? l.getAttribute("alt") ?? ((n = l.getAttribute("title")) == null ? void 0 : n.trim()) ?? "";
|
|
363
363
|
} else if (d === "svg") {
|
|
364
|
-
const c = (
|
|
364
|
+
const c = (o = l.getAttribute("aria-label")) == null ? void 0 : o.trim();
|
|
365
365
|
if (c)
|
|
366
366
|
a += c;
|
|
367
367
|
else {
|
|
368
368
|
const u = l.querySelector("title");
|
|
369
369
|
u && (a += u.textContent ?? "");
|
|
370
370
|
}
|
|
371
|
-
} else (
|
|
371
|
+
} else (r = l.getAttribute("aria-label")) != null && r.trim() ? a += l.getAttribute("aria-label").trim() : a += k(l);
|
|
372
372
|
}
|
|
373
373
|
}
|
|
374
374
|
return a;
|
|
@@ -381,13 +381,13 @@ function ee(e) {
|
|
|
381
381
|
else if (t.nodeType === 1) {
|
|
382
382
|
const i = t, n = i.tagName.toLowerCase();
|
|
383
383
|
if (n === "style" || n === "script" || n === "svg" || i.getAttribute("aria-hidden") === "true" || i instanceof HTMLElement && i.style.display === "none") continue;
|
|
384
|
-
const
|
|
385
|
-
if (
|
|
384
|
+
const o = i.getAttribute("role");
|
|
385
|
+
if (o === "img" || o === "presentation" || o === "none") continue;
|
|
386
386
|
a += ee(i);
|
|
387
387
|
}
|
|
388
388
|
return a;
|
|
389
389
|
}
|
|
390
|
-
function
|
|
390
|
+
function Pe(e) {
|
|
391
391
|
let a = e;
|
|
392
392
|
for (; a; ) {
|
|
393
393
|
if (a instanceof HTMLElement && a.style.visibility === "hidden") return !0;
|
|
@@ -395,19 +395,19 @@ function De(e) {
|
|
|
395
395
|
}
|
|
396
396
|
return !1;
|
|
397
397
|
}
|
|
398
|
-
function
|
|
399
|
-
var n,
|
|
398
|
+
function De(e) {
|
|
399
|
+
var n, o;
|
|
400
400
|
const a = e.getAttribute("aria-labelledby");
|
|
401
401
|
if (a) {
|
|
402
|
-
const
|
|
402
|
+
const r = a.split(/\s+/).map((s) => {
|
|
403
403
|
var l, d;
|
|
404
404
|
return ((d = (l = e.ownerDocument.getElementById(s)) == null ? void 0 : l.textContent) == null ? void 0 : d.trim()) ?? "";
|
|
405
405
|
}).filter(Boolean);
|
|
406
|
-
if (
|
|
406
|
+
if (r.length) return r.join(" ");
|
|
407
407
|
}
|
|
408
408
|
const t = (n = e.getAttribute("aria-label")) == null ? void 0 : n.trim();
|
|
409
409
|
if (t) return t;
|
|
410
|
-
const i = (
|
|
410
|
+
const i = (o = e.getAttribute("title")) == null ? void 0 : o.trim();
|
|
411
411
|
return i || "";
|
|
412
412
|
}
|
|
413
413
|
function se(e) {
|
|
@@ -440,8 +440,8 @@ function gt(e) {
|
|
|
440
440
|
const t = e.parentElement;
|
|
441
441
|
if (t) {
|
|
442
442
|
let i = 0, n = 0;
|
|
443
|
-
for (let
|
|
444
|
-
t.children[
|
|
443
|
+
for (let o = 0; o < t.children.length; o++)
|
|
444
|
+
t.children[o].tagName === e.tagName && (i++, t.children[o] === e && (n = i));
|
|
445
445
|
if (i > 1)
|
|
446
446
|
return `${a}:nth-of-type(${n})`;
|
|
447
447
|
}
|
|
@@ -459,10 +459,10 @@ function Y(e) {
|
|
|
459
459
|
break;
|
|
460
460
|
}
|
|
461
461
|
if (i.unshift(gt(n)), i.length >= 2) {
|
|
462
|
-
const
|
|
462
|
+
const o = i.join(" > ");
|
|
463
463
|
try {
|
|
464
|
-
const
|
|
465
|
-
if (
|
|
464
|
+
const r = a.querySelectorAll(o);
|
|
465
|
+
if (r.length === 1 && r[0] === e) return o;
|
|
466
466
|
} catch {
|
|
467
467
|
}
|
|
468
468
|
}
|
|
@@ -471,17 +471,17 @@ function Y(e) {
|
|
|
471
471
|
return i.join(" > ");
|
|
472
472
|
}
|
|
473
473
|
function p(e) {
|
|
474
|
-
var
|
|
474
|
+
var o;
|
|
475
475
|
const a = te.get(e);
|
|
476
476
|
if (a !== void 0) return a;
|
|
477
477
|
const t = [];
|
|
478
478
|
let i = e;
|
|
479
479
|
for (; i; ) {
|
|
480
|
-
const
|
|
481
|
-
if (
|
|
482
|
-
t.unshift({ selector: Y(i), delimiter: " >>> " }), i =
|
|
480
|
+
const r = i.getRootNode();
|
|
481
|
+
if (r instanceof ShadowRoot)
|
|
482
|
+
t.unshift({ selector: Y(i), delimiter: " >>> " }), i = r.host;
|
|
483
483
|
else {
|
|
484
|
-
const s = (
|
|
484
|
+
const s = (o = r.defaultView) == null ? void 0 : o.frameElement;
|
|
485
485
|
if (s)
|
|
486
486
|
t.unshift({ selector: Y(i), delimiter: " >>>iframe> " }), i = s;
|
|
487
487
|
else {
|
|
@@ -490,39 +490,39 @@ function p(e) {
|
|
|
490
490
|
}
|
|
491
491
|
}
|
|
492
492
|
}
|
|
493
|
-
const n = t.map((
|
|
493
|
+
const n = t.map((r, s) => (s === 0 ? "" : r.delimiter) + r.selector).join("");
|
|
494
494
|
return te.set(e, n), n;
|
|
495
495
|
}
|
|
496
|
-
function
|
|
496
|
+
function Un(e) {
|
|
497
497
|
const a = [], t = [];
|
|
498
498
|
let i = e;
|
|
499
499
|
for (; i; ) {
|
|
500
|
-
const
|
|
501
|
-
if (
|
|
502
|
-
a.push(i.slice(0,
|
|
503
|
-
else if (
|
|
504
|
-
a.push(i.slice(0,
|
|
500
|
+
const o = i.indexOf(" >>>iframe> "), r = i.indexOf(" >>> ");
|
|
501
|
+
if (o !== -1 && (r === -1 || o <= r))
|
|
502
|
+
a.push(i.slice(0, o).trim()), t.push("iframe"), i = i.slice(o + 12);
|
|
503
|
+
else if (r !== -1)
|
|
504
|
+
a.push(i.slice(0, r).trim()), t.push("shadow"), i = i.slice(r + 5);
|
|
505
505
|
else {
|
|
506
506
|
a.push(i.trim());
|
|
507
507
|
break;
|
|
508
508
|
}
|
|
509
509
|
}
|
|
510
510
|
let n = document;
|
|
511
|
-
for (let
|
|
512
|
-
const
|
|
513
|
-
if (!
|
|
514
|
-
if (
|
|
515
|
-
if (t[
|
|
516
|
-
const s =
|
|
511
|
+
for (let o = 0; o < a.length; o++) {
|
|
512
|
+
const r = n.querySelector(a[o]);
|
|
513
|
+
if (!r) return null;
|
|
514
|
+
if (o < a.length - 1)
|
|
515
|
+
if (t[o] === "iframe") {
|
|
516
|
+
const s = r.contentDocument;
|
|
517
517
|
if (!s) return null;
|
|
518
518
|
n = s;
|
|
519
519
|
} else {
|
|
520
|
-
const s =
|
|
520
|
+
const s = r.shadowRoot;
|
|
521
521
|
if (!s) return null;
|
|
522
522
|
n = s;
|
|
523
523
|
}
|
|
524
524
|
else
|
|
525
|
-
return
|
|
525
|
+
return r;
|
|
526
526
|
}
|
|
527
527
|
return null;
|
|
528
528
|
}
|
|
@@ -637,7 +637,7 @@ const ft = /* @__PURE__ */ new Set([
|
|
|
637
637
|
"suggestion",
|
|
638
638
|
"term",
|
|
639
639
|
"time"
|
|
640
|
-
]),
|
|
640
|
+
]), wt = {
|
|
641
641
|
abbr: !0,
|
|
642
642
|
bdi: !0,
|
|
643
643
|
bdo: !0,
|
|
@@ -665,7 +665,7 @@ const ft = /* @__PURE__ */ new Set([
|
|
|
665
665
|
u: !0,
|
|
666
666
|
var: !0,
|
|
667
667
|
wbr: !0
|
|
668
|
-
},
|
|
668
|
+
}, xt = {
|
|
669
669
|
alert: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"]),
|
|
670
670
|
article: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"]),
|
|
671
671
|
banner: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"]),
|
|
@@ -698,25 +698,25 @@ const ft = /* @__PURE__ */ new Set([
|
|
|
698
698
|
time: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"]),
|
|
699
699
|
tooltip: /* @__PURE__ */ new Set(["aria-disabled", "aria-errormessage", "aria-haspopup", "aria-invalid"])
|
|
700
700
|
};
|
|
701
|
-
let
|
|
701
|
+
let D = null, F = null;
|
|
702
702
|
function At() {
|
|
703
|
-
|
|
703
|
+
D = null, F = null;
|
|
704
704
|
}
|
|
705
705
|
function le(e) {
|
|
706
706
|
var n;
|
|
707
|
-
if (F && (
|
|
707
|
+
if (F && (D == null ? void 0 : D.deref()) === e) return F;
|
|
708
708
|
const a = [], t = [], i = [];
|
|
709
|
-
for (const
|
|
710
|
-
let
|
|
711
|
-
for (const c of
|
|
709
|
+
for (const o of e.querySelectorAll("*")) {
|
|
710
|
+
let r = !1;
|
|
711
|
+
for (const c of o.attributes)
|
|
712
712
|
if (c.name.startsWith("aria-")) {
|
|
713
|
-
|
|
713
|
+
r = !0;
|
|
714
714
|
break;
|
|
715
715
|
}
|
|
716
|
-
if (!
|
|
716
|
+
if (!r) continue;
|
|
717
717
|
let s, l;
|
|
718
|
-
const d = () => (s === void 0 && (s = p(
|
|
719
|
-
for (const c of
|
|
718
|
+
const d = () => (s === void 0 && (s = p(o), l = m(o)), { selector: s, html: l });
|
|
719
|
+
for (const c of o.attributes)
|
|
720
720
|
if (c.name.startsWith("aria-") && !ft.has(c.name)) {
|
|
721
721
|
const u = d();
|
|
722
722
|
a.push({
|
|
@@ -729,7 +729,7 @@ function le(e) {
|
|
|
729
729
|
});
|
|
730
730
|
break;
|
|
731
731
|
}
|
|
732
|
-
for (const c of
|
|
732
|
+
for (const c of o.attributes) {
|
|
733
733
|
if (!c.name.startsWith("aria-")) continue;
|
|
734
734
|
const u = c.value.trim();
|
|
735
735
|
if (!(u === "" && !he.has(c.name) && !ge.has(c.name))) {
|
|
@@ -799,10 +799,10 @@ function le(e) {
|
|
|
799
799
|
}
|
|
800
800
|
}
|
|
801
801
|
}
|
|
802
|
-
if (!h(
|
|
803
|
-
const c = (n =
|
|
804
|
-
if (!c &&
|
|
805
|
-
const b =
|
|
802
|
+
if (!h(o)) {
|
|
803
|
+
const c = (n = o.getAttribute("role")) == null ? void 0 : n.trim().toLowerCase(), u = o.tagName.toLowerCase();
|
|
804
|
+
if (!c && wt[u]) {
|
|
805
|
+
const b = o.hasAttribute("aria-label"), g = o.hasAttribute("aria-labelledby");
|
|
806
806
|
if (b || g) {
|
|
807
807
|
const f = d(), v = b ? "aria-label" : "aria-labelledby";
|
|
808
808
|
i.push({
|
|
@@ -816,7 +816,7 @@ function le(e) {
|
|
|
816
816
|
}
|
|
817
817
|
} else if (c) {
|
|
818
818
|
if (fe.has(c)) {
|
|
819
|
-
const g =
|
|
819
|
+
const g = o.hasAttribute("aria-label"), f = o.hasAttribute("aria-labelledby");
|
|
820
820
|
if (g || f) {
|
|
821
821
|
const v = d(), y = g ? "aria-label" : "aria-labelledby";
|
|
822
822
|
i.push({
|
|
@@ -829,9 +829,9 @@ function le(e) {
|
|
|
829
829
|
});
|
|
830
830
|
}
|
|
831
831
|
}
|
|
832
|
-
const b =
|
|
832
|
+
const b = xt[c];
|
|
833
833
|
if (b) {
|
|
834
|
-
for (const g of
|
|
834
|
+
for (const g of o.attributes)
|
|
835
835
|
if (g.name.startsWith("aria-") && b.has(g.name)) {
|
|
836
836
|
if ((g.name === "aria-label" || g.name === "aria-labelledby") && fe.has(c))
|
|
837
837
|
continue;
|
|
@@ -849,22 +849,22 @@ function le(e) {
|
|
|
849
849
|
}
|
|
850
850
|
}
|
|
851
851
|
}
|
|
852
|
-
return
|
|
852
|
+
return D = new WeakRef(e), F = { validAttr: a, validAttrValue: t, prohibitedAttr: i }, F;
|
|
853
853
|
}
|
|
854
854
|
let ae = /* @__PURE__ */ new WeakMap(), ie = /* @__PURE__ */ new WeakMap(), ne = /* @__PURE__ */ new WeakMap();
|
|
855
855
|
function kt() {
|
|
856
856
|
ae = /* @__PURE__ */ new WeakMap(), ie = /* @__PURE__ */ new WeakMap(), ne = /* @__PURE__ */ new WeakMap();
|
|
857
857
|
}
|
|
858
|
-
function
|
|
858
|
+
function w(e) {
|
|
859
859
|
let a = ae.get(e);
|
|
860
860
|
return a || (a = getComputedStyle(e), ae.set(e, a), a);
|
|
861
861
|
}
|
|
862
|
-
function
|
|
863
|
-
const [i, n,
|
|
864
|
-
const s =
|
|
862
|
+
function q(e, a, t) {
|
|
863
|
+
const [i, n, o] = [e, a, t].map((r) => {
|
|
864
|
+
const s = r / 255;
|
|
865
865
|
return s <= 0.04045 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
|
|
866
866
|
});
|
|
867
|
-
return 0.2126 * i + 0.7152 * n + 0.0722 *
|
|
867
|
+
return 0.2126 * i + 0.7152 * n + 0.0722 * o;
|
|
868
868
|
}
|
|
869
869
|
function $(e, a) {
|
|
870
870
|
const t = Math.max(e, a), i = Math.min(e, a);
|
|
@@ -904,10 +904,10 @@ function C(e) {
|
|
|
904
904
|
);
|
|
905
905
|
if (n)
|
|
906
906
|
return [parseInt(n[1]), parseInt(n[2]), parseInt(n[3])];
|
|
907
|
-
const
|
|
907
|
+
const o = e.match(
|
|
908
908
|
/rgba?\(\s*(\d+)\s+(\d+)\s+(\d+)\s*(?:\/\s*[\d.]+%?)?\s*\)/
|
|
909
909
|
);
|
|
910
|
-
return
|
|
910
|
+
return o ? [parseInt(o[1]), parseInt(o[2]), parseInt(o[3])] : null;
|
|
911
911
|
}
|
|
912
912
|
function U(e) {
|
|
913
913
|
const a = e.match(/rgba\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*([\d.]+)\s*\)/);
|
|
@@ -942,8 +942,8 @@ function St(e) {
|
|
|
942
942
|
const a = [];
|
|
943
943
|
let t = e;
|
|
944
944
|
for (; t; ) {
|
|
945
|
-
const n =
|
|
946
|
-
if (
|
|
945
|
+
const n = w(t), o = n.backgroundImage;
|
|
946
|
+
if (o && o !== "none" && o !== "initial") {
|
|
947
947
|
const d = n.backgroundColor;
|
|
948
948
|
if (d && d !== "transparent" && d !== "rgba(0, 0, 0, 0)" && d !== "rgba(0 0 0 / 0)") {
|
|
949
949
|
const c = C(d);
|
|
@@ -952,17 +952,17 @@ function St(e) {
|
|
|
952
952
|
}
|
|
953
953
|
return null;
|
|
954
954
|
}
|
|
955
|
-
const
|
|
956
|
-
if (
|
|
955
|
+
const r = n.backgroundColor;
|
|
956
|
+
if (r === "transparent" || r === "rgba(0, 0, 0, 0)" || r === "rgba(0 0 0 / 0)") {
|
|
957
957
|
t = t.parentElement;
|
|
958
958
|
continue;
|
|
959
959
|
}
|
|
960
|
-
const s = U(
|
|
960
|
+
const s = U(r);
|
|
961
961
|
if (s < 0.01) {
|
|
962
962
|
t = t.parentElement;
|
|
963
963
|
continue;
|
|
964
964
|
}
|
|
965
|
-
const l = C(
|
|
965
|
+
const l = C(r);
|
|
966
966
|
if (!l) {
|
|
967
967
|
t = t.parentElement;
|
|
968
968
|
continue;
|
|
@@ -986,10 +986,10 @@ function It(e, a = [255, 255, 255]) {
|
|
|
986
986
|
if (i === -1) return t;
|
|
987
987
|
const n = e.indexOf("(", i);
|
|
988
988
|
if (n === -1) return t;
|
|
989
|
-
let
|
|
990
|
-
for (;
|
|
991
|
-
e[
|
|
992
|
-
const s = e.slice(n + 1,
|
|
989
|
+
let o = 1, r = n + 1;
|
|
990
|
+
for (; r < e.length && o > 0; r++)
|
|
991
|
+
e[r] === "(" ? o++ : e[r] === ")" && o--;
|
|
992
|
+
const s = e.slice(n + 1, r - 1), l = Fe(s);
|
|
993
993
|
for (const d of l) {
|
|
994
994
|
const c = d.trim();
|
|
995
995
|
if (/^(to\s|[\d.]+deg|[\d.]+turn|[\d.]+rad)/i.test(c)) continue;
|
|
@@ -1002,32 +1002,32 @@ function It(e, a = [255, 255, 255]) {
|
|
|
1002
1002
|
}
|
|
1003
1003
|
return t;
|
|
1004
1004
|
}
|
|
1005
|
-
const
|
|
1006
|
-
function
|
|
1005
|
+
const qt = /* @__PURE__ */ new Set(["IMG", "PICTURE", "VIDEO", "SVG"]);
|
|
1006
|
+
function Et(e) {
|
|
1007
1007
|
const a = ne.get(e);
|
|
1008
1008
|
if (a !== void 0) return a;
|
|
1009
1009
|
const t = Rt(e);
|
|
1010
1010
|
return ne.set(e, t), t;
|
|
1011
1011
|
}
|
|
1012
1012
|
function Lt(e) {
|
|
1013
|
-
return
|
|
1013
|
+
return qt.has(e.tagName) ? !0 : !!e.querySelector("img, picture, video, svg");
|
|
1014
1014
|
}
|
|
1015
1015
|
function Rt(e) {
|
|
1016
1016
|
let a = e, t = !1;
|
|
1017
1017
|
for (; a; ) {
|
|
1018
|
-
const i =
|
|
1018
|
+
const i = w(a).position;
|
|
1019
1019
|
if ((i === "absolute" || i === "fixed") && (t = !0), a !== e && i !== "static") {
|
|
1020
1020
|
for (const n of a.children) {
|
|
1021
1021
|
if (n === e || n.contains(e)) continue;
|
|
1022
1022
|
if (Lt(n)) {
|
|
1023
1023
|
if (t) return !0;
|
|
1024
|
-
const
|
|
1025
|
-
if (
|
|
1024
|
+
const r = w(n).position;
|
|
1025
|
+
if (r === "absolute" || r === "fixed") return !0;
|
|
1026
1026
|
}
|
|
1027
|
-
const
|
|
1028
|
-
if (
|
|
1029
|
-
const
|
|
1030
|
-
if (
|
|
1027
|
+
const o = w(n);
|
|
1028
|
+
if (o.position === "absolute" || o.position === "fixed") {
|
|
1029
|
+
const r = o.backgroundImage;
|
|
1030
|
+
if (r && r !== "none" && r !== "initial") return !0;
|
|
1031
1031
|
}
|
|
1032
1032
|
}
|
|
1033
1033
|
if (t) break;
|
|
@@ -1040,8 +1040,8 @@ function Ct(e) {
|
|
|
1040
1040
|
const a = parseFloat(e);
|
|
1041
1041
|
return e.endsWith("pt") ? a * (4 / 3) : a;
|
|
1042
1042
|
}
|
|
1043
|
-
function
|
|
1044
|
-
const a =
|
|
1043
|
+
function we(e) {
|
|
1044
|
+
const a = w(e), t = Ct(a.fontSize), i = parseInt(a.fontWeight) || (a.fontWeight === "bold" ? 700 : 400);
|
|
1045
1045
|
return t >= 23.5 || t >= 18.5 && i >= 700;
|
|
1046
1046
|
}
|
|
1047
1047
|
function Tt(e) {
|
|
@@ -1049,32 +1049,32 @@ function Tt(e) {
|
|
|
1049
1049
|
for (const i of a) {
|
|
1050
1050
|
const n = i.trim();
|
|
1051
1051
|
if (!n) continue;
|
|
1052
|
-
const
|
|
1053
|
-
if (!
|
|
1052
|
+
const o = n.match(/rgba?\([^)]+\)/), r = o ? C(o[0]) : null;
|
|
1053
|
+
if (!r) return null;
|
|
1054
1054
|
const s = n.replace(/rgba?\([^)]+\)/, "").match(/[\d.]+px/g), l = s && s.length >= 3 ? parseFloat(s[2]) : 0;
|
|
1055
|
-
t.push({ color:
|
|
1055
|
+
t.push({ color: r, blur: l });
|
|
1056
1056
|
}
|
|
1057
1057
|
return t.length > 0 ? t : null;
|
|
1058
1058
|
}
|
|
1059
|
-
function
|
|
1059
|
+
function xe(e) {
|
|
1060
1060
|
return e === "transparent" || e === "rgba(0, 0, 0, 0)" || e === "rgba(0 0 0 / 0)";
|
|
1061
1061
|
}
|
|
1062
1062
|
function _([e, a, t]) {
|
|
1063
1063
|
return "#" + [e, a, t].map((i) => i.toString(16).padStart(2, "0")).join("");
|
|
1064
1064
|
}
|
|
1065
1065
|
function Nt(e, a, t) {
|
|
1066
|
-
const i =
|
|
1067
|
-
let
|
|
1068
|
-
for (const
|
|
1069
|
-
const s =
|
|
1070
|
-
|
|
1066
|
+
const i = q(e[0], e[1], e[2]), n = q(a[0], a[1], a[2]);
|
|
1067
|
+
let o = $(i, n);
|
|
1068
|
+
for (const r of t) {
|
|
1069
|
+
const s = q(r.color[0], r.color[1], r.color[2]);
|
|
1070
|
+
o = Math.max(o, $(i, s), $(s, n));
|
|
1071
1071
|
}
|
|
1072
|
-
return
|
|
1072
|
+
return o;
|
|
1073
1073
|
}
|
|
1074
1074
|
function Mt(e) {
|
|
1075
1075
|
let a = 1, t = e;
|
|
1076
1076
|
for (; t; ) {
|
|
1077
|
-
const i =
|
|
1077
|
+
const i = w(t), n = parseFloat(i.opacity);
|
|
1078
1078
|
isNaN(n) || (a *= n), t = t.parentElement;
|
|
1079
1079
|
}
|
|
1080
1080
|
return a;
|
|
@@ -1084,28 +1084,28 @@ function $t(e) {
|
|
|
1084
1084
|
for (; a; ) {
|
|
1085
1085
|
for (const n of ["::before", "::after"])
|
|
1086
1086
|
try {
|
|
1087
|
-
const
|
|
1088
|
-
if (!
|
|
1089
|
-
const s =
|
|
1090
|
-
if (s && !
|
|
1091
|
-
const l =
|
|
1087
|
+
const o = getComputedStyle(a, n), r = o.content;
|
|
1088
|
+
if (!r || r === "none" || r === "normal" || r === '""') continue;
|
|
1089
|
+
const s = o.backgroundColor;
|
|
1090
|
+
if (s && !xe(s) && U(s) >= 0.1) return !0;
|
|
1091
|
+
const l = o.backgroundImage;
|
|
1092
1092
|
if (l && l !== "none" && l !== "initial") return !0;
|
|
1093
|
-
const d =
|
|
1093
|
+
const d = o.position;
|
|
1094
1094
|
if (d === "absolute" || d === "fixed") {
|
|
1095
|
-
const c = parseFloat(
|
|
1095
|
+
const c = parseFloat(o.width), u = parseFloat(o.height);
|
|
1096
1096
|
if (c > 1 && u > 1) return !0;
|
|
1097
1097
|
}
|
|
1098
1098
|
} catch {
|
|
1099
1099
|
}
|
|
1100
|
-
const i =
|
|
1101
|
-
if (i && !
|
|
1100
|
+
const i = w(a).backgroundColor;
|
|
1101
|
+
if (i && !xe(i) && U(i) >= 1) break;
|
|
1102
1102
|
a = a.parentElement;
|
|
1103
1103
|
}
|
|
1104
1104
|
return !1;
|
|
1105
1105
|
}
|
|
1106
1106
|
const G = /* @__PURE__ */ new Map();
|
|
1107
|
-
function
|
|
1108
|
-
G.set(e, a),
|
|
1107
|
+
function On(e, a) {
|
|
1108
|
+
G.set(e, a), oe.delete(e);
|
|
1109
1109
|
}
|
|
1110
1110
|
function Ht(e, a) {
|
|
1111
1111
|
const t = G.get(a);
|
|
@@ -1118,42 +1118,42 @@ function Ht(e, a) {
|
|
|
1118
1118
|
} : i;
|
|
1119
1119
|
}) : e;
|
|
1120
1120
|
}
|
|
1121
|
-
const
|
|
1122
|
-
function
|
|
1121
|
+
const oe = /* @__PURE__ */ new Map();
|
|
1122
|
+
function Pt(e) {
|
|
1123
1123
|
return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1124
1124
|
}
|
|
1125
|
-
function
|
|
1125
|
+
function Dt(e) {
|
|
1126
1126
|
const a = e.split(/\{(\d+)\}/);
|
|
1127
1127
|
let t = "^";
|
|
1128
1128
|
for (let i = 0; i < a.length; i++)
|
|
1129
|
-
i % 2 === 0 ? t +=
|
|
1129
|
+
i % 2 === 0 ? t += Pt(a[i]) : t += "(.+?)";
|
|
1130
1130
|
return t += "$", new RegExp(t);
|
|
1131
1131
|
}
|
|
1132
1132
|
function Ft(e, a) {
|
|
1133
|
-
let t =
|
|
1134
|
-
if (t || (t = /* @__PURE__ */ new Map(),
|
|
1133
|
+
let t = oe.get(e);
|
|
1134
|
+
if (t || (t = /* @__PURE__ */ new Map(), oe.set(e, t)), t.has(a)) return t.get(a);
|
|
1135
1135
|
const i = G.get(e);
|
|
1136
1136
|
if (!i) return;
|
|
1137
1137
|
const n = i[a];
|
|
1138
1138
|
if (!(n != null && n.messages))
|
|
1139
1139
|
return t.set(a, []), [];
|
|
1140
|
-
const
|
|
1141
|
-
for (const [
|
|
1142
|
-
|
|
1143
|
-
regex:
|
|
1140
|
+
const o = [];
|
|
1141
|
+
for (const [r, s] of Object.entries(n.messages))
|
|
1142
|
+
o.push({
|
|
1143
|
+
regex: Dt(r),
|
|
1144
1144
|
translated: s
|
|
1145
1145
|
});
|
|
1146
|
-
return t.set(a,
|
|
1146
|
+
return t.set(a, o), o;
|
|
1147
1147
|
}
|
|
1148
1148
|
function zt(e, a, t) {
|
|
1149
1149
|
const i = Ft(t, e);
|
|
1150
1150
|
if (!i) return a;
|
|
1151
|
-
for (const { regex: n, translated:
|
|
1152
|
-
const
|
|
1153
|
-
if (
|
|
1154
|
-
return
|
|
1151
|
+
for (const { regex: n, translated: o } of i) {
|
|
1152
|
+
const r = a.match(n);
|
|
1153
|
+
if (r)
|
|
1154
|
+
return o.replace(/\{(\d+)\}/g, (s, l) => {
|
|
1155
1155
|
const d = parseInt(l, 10);
|
|
1156
|
-
return d + 1 <
|
|
1156
|
+
return d + 1 < r.length ? r[d + 1] : `{${l}}`;
|
|
1157
1157
|
});
|
|
1158
1158
|
}
|
|
1159
1159
|
return a;
|
|
@@ -1165,7 +1165,7 @@ function ze(e, a) {
|
|
|
1165
1165
|
}) : e;
|
|
1166
1166
|
}
|
|
1167
1167
|
function Ae(e) {
|
|
1168
|
-
var
|
|
1168
|
+
var o, r;
|
|
1169
1169
|
const a = [], t = e.closest("a");
|
|
1170
1170
|
if (t) {
|
|
1171
1171
|
const s = t.getAttribute("href");
|
|
@@ -1174,17 +1174,17 @@ function Ae(e) {
|
|
|
1174
1174
|
const i = e.closest("figure");
|
|
1175
1175
|
if (i) {
|
|
1176
1176
|
const s = i.querySelector("figcaption");
|
|
1177
|
-
(
|
|
1177
|
+
(o = s == null ? void 0 : s.textContent) != null && o.trim() && a.push(`Figcaption: ${s.textContent.trim().slice(0, 100)}`);
|
|
1178
1178
|
}
|
|
1179
1179
|
const n = e.parentElement;
|
|
1180
1180
|
if (n && n !== t) {
|
|
1181
|
-
const s = e instanceof HTMLImageElement && e.alt || "", l = (
|
|
1181
|
+
const s = e instanceof HTMLImageElement && e.alt || "", l = (r = n.textContent) == null ? void 0 : r.replace(s, "").trim().slice(0, 100);
|
|
1182
1182
|
l && a.push(`Adjacent text: ${l}`);
|
|
1183
1183
|
}
|
|
1184
1184
|
return a.length > 0 ? a.join(`
|
|
1185
1185
|
`) : void 0;
|
|
1186
1186
|
}
|
|
1187
|
-
const
|
|
1187
|
+
const Wt = {
|
|
1188
1188
|
id: "text-alternatives/img-alt",
|
|
1189
1189
|
category: "text-alternatives",
|
|
1190
1190
|
actRuleIds: ["23a2a8"],
|
|
@@ -1197,11 +1197,11 @@ const jt = {
|
|
|
1197
1197
|
run(e) {
|
|
1198
1198
|
const a = [];
|
|
1199
1199
|
for (const t of e.querySelectorAll("img")) {
|
|
1200
|
-
if (h(t) ||
|
|
1200
|
+
if (h(t) || Pe(t)) continue;
|
|
1201
1201
|
const i = t.getAttribute("role");
|
|
1202
1202
|
if (i === "presentation" || i === "none") {
|
|
1203
|
-
const
|
|
1204
|
-
if (!
|
|
1203
|
+
const o = t.getAttribute("tabindex");
|
|
1204
|
+
if (!o || o === "-1") continue;
|
|
1205
1205
|
}
|
|
1206
1206
|
const n = t.getAttribute("alt");
|
|
1207
1207
|
if (n !== null && n.trim() === "" && n !== "") {
|
|
@@ -1216,7 +1216,7 @@ const jt = {
|
|
|
1216
1216
|
});
|
|
1217
1217
|
continue;
|
|
1218
1218
|
}
|
|
1219
|
-
!t.hasAttribute("alt") && !
|
|
1219
|
+
!t.hasAttribute("alt") && !x(t) && a.push({
|
|
1220
1220
|
ruleId: "text-alternatives/img-alt",
|
|
1221
1221
|
selector: p(t),
|
|
1222
1222
|
html: m(t),
|
|
@@ -1229,9 +1229,9 @@ const jt = {
|
|
|
1229
1229
|
return a;
|
|
1230
1230
|
}
|
|
1231
1231
|
};
|
|
1232
|
-
function
|
|
1232
|
+
function jt(e) {
|
|
1233
1233
|
var i;
|
|
1234
|
-
const a =
|
|
1234
|
+
const a = De(e);
|
|
1235
1235
|
if (a) return a;
|
|
1236
1236
|
const t = e.querySelector("title");
|
|
1237
1237
|
return (i = t == null ? void 0 : t.textContent) != null && i.trim() ? t.textContent.trim() : "";
|
|
@@ -1250,14 +1250,14 @@ const Ut = {
|
|
|
1250
1250
|
const a = [], t = 'svg[role="img"], [role="graphics-document"], [role="graphics-symbol"]';
|
|
1251
1251
|
for (const i of e.querySelectorAll(t)) {
|
|
1252
1252
|
if (h(i)) continue;
|
|
1253
|
-
if (!
|
|
1254
|
-
const
|
|
1253
|
+
if (!jt(i)) {
|
|
1254
|
+
const o = i.getAttribute("role");
|
|
1255
1255
|
a.push({
|
|
1256
1256
|
ruleId: "text-alternatives/svg-img-alt",
|
|
1257
1257
|
selector: p(i),
|
|
1258
1258
|
html: m(i),
|
|
1259
1259
|
impact: "serious",
|
|
1260
|
-
message: `${i.tagName.toLowerCase()} with role='${
|
|
1260
|
+
message: `${i.tagName.toLowerCase()} with role='${o}' has no accessible name.`,
|
|
1261
1261
|
fix: { type: "add-attribute", attribute: "aria-label", value: "" }
|
|
1262
1262
|
});
|
|
1263
1263
|
}
|
|
@@ -1277,7 +1277,7 @@ const Ut = {
|
|
|
1277
1277
|
run(e) {
|
|
1278
1278
|
const a = [];
|
|
1279
1279
|
for (const t of e.querySelectorAll('input[type="image"]'))
|
|
1280
|
-
h(t) ||
|
|
1280
|
+
h(t) || x(t) || a.push({
|
|
1281
1281
|
ruleId: "text-alternatives/input-image-alt",
|
|
1282
1282
|
selector: p(t),
|
|
1283
1283
|
html: m(t),
|
|
@@ -1302,11 +1302,11 @@ const Ut = {
|
|
|
1302
1302
|
for (const i of e.querySelectorAll("img[alt]")) {
|
|
1303
1303
|
const n = i.getAttribute("alt").trim().toLowerCase();
|
|
1304
1304
|
if (!n) continue;
|
|
1305
|
-
const
|
|
1306
|
-
if (
|
|
1307
|
-
const
|
|
1308
|
-
if (
|
|
1309
|
-
const s =
|
|
1305
|
+
const o = i.closest("a, button");
|
|
1306
|
+
if (o) {
|
|
1307
|
+
const r = ((t = o.textContent) == null ? void 0 : t.trim().toLowerCase()) || "";
|
|
1308
|
+
if (r && r === n) {
|
|
1309
|
+
const s = o.tagName.toLowerCase(), l = o.getAttribute("href");
|
|
1310
1310
|
a.push({
|
|
1311
1311
|
ruleId: "text-alternatives/image-redundant-alt",
|
|
1312
1312
|
selector: p(i),
|
|
@@ -1321,7 +1321,7 @@ const Ut = {
|
|
|
1321
1321
|
}
|
|
1322
1322
|
return a;
|
|
1323
1323
|
}
|
|
1324
|
-
}, Bt =
|
|
1324
|
+
}, Bt = /^(image|picture|photo|graphic|icon|img)(\s+of\b|\s*[:\u2013\u2014-]|\s*$)/i, _t = {
|
|
1325
1325
|
id: "text-alternatives/image-alt-words",
|
|
1326
1326
|
category: "text-alternatives",
|
|
1327
1327
|
wcag: ["1.1.1"],
|
|
@@ -1329,23 +1329,26 @@ const Ut = {
|
|
|
1329
1329
|
tags: ["best-practice"],
|
|
1330
1330
|
fixability: "contextual",
|
|
1331
1331
|
browserHint: "Screenshot the image to verify the alt text accurately describes it without filler words like 'image of'.",
|
|
1332
|
-
description: "Image alt text should not
|
|
1332
|
+
description: "Image alt text should not start with words like 'image of', 'photo of', or 'picture of' — screen readers already announce the element type.",
|
|
1333
1333
|
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'.",
|
|
1334
1334
|
run(e) {
|
|
1335
1335
|
const a = [];
|
|
1336
1336
|
for (const t of e.querySelectorAll("img[alt]")) {
|
|
1337
|
-
const i = t.getAttribute("alt").
|
|
1337
|
+
const i = t.getAttribute("alt").trim();
|
|
1338
1338
|
if (!i) continue;
|
|
1339
|
-
const n =
|
|
1340
|
-
n
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1339
|
+
const n = i.match(Bt);
|
|
1340
|
+
if (n) {
|
|
1341
|
+
const o = n[1].toLowerCase();
|
|
1342
|
+
a.push({
|
|
1343
|
+
ruleId: "text-alternatives/image-alt-words",
|
|
1344
|
+
selector: p(t),
|
|
1345
|
+
html: m(t),
|
|
1346
|
+
impact: "minor",
|
|
1347
|
+
message: `Alt text "${i}" starts with redundant prefix "${o}".`,
|
|
1348
|
+
context: `Current alt: "${i}", redundant prefix: "${o}"`,
|
|
1349
|
+
fix: { type: "suggest", suggestion: "Remove the redundant prefix from the alt text; screen readers already announce the element as an image" }
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1349
1352
|
}
|
|
1350
1353
|
return a;
|
|
1351
1354
|
}
|
|
@@ -1361,7 +1364,7 @@ const Ut = {
|
|
|
1361
1364
|
const a = [];
|
|
1362
1365
|
for (const t of e.querySelectorAll("area[href]")) {
|
|
1363
1366
|
if (h(t)) continue;
|
|
1364
|
-
|
|
1367
|
+
x(t) || a.push({
|
|
1365
1368
|
ruleId: "text-alternatives/area-alt",
|
|
1366
1369
|
selector: p(t),
|
|
1367
1370
|
html: m(t),
|
|
@@ -1386,7 +1389,7 @@ const Ut = {
|
|
|
1386
1389
|
var t;
|
|
1387
1390
|
const a = [];
|
|
1388
1391
|
for (const i of e.querySelectorAll("object")) {
|
|
1389
|
-
if (h(i) ||
|
|
1392
|
+
if (h(i) || Pe(i) || i.getAttribute("role") === "presentation" || i.getAttribute("role") === "none" || De(i)) continue;
|
|
1390
1393
|
const n = i.getAttribute("data") || "";
|
|
1391
1394
|
if (!((i.getAttribute("type") || "").startsWith("image/") || /\.(png|jpg|jpeg|gif|svg|webp|bmp|ico)$/i.test(n))) {
|
|
1392
1395
|
const s = i.querySelector("img[alt]");
|
|
@@ -1417,7 +1420,7 @@ const Ut = {
|
|
|
1417
1420
|
const a = [];
|
|
1418
1421
|
for (const t of e.querySelectorAll('[role="img"]')) {
|
|
1419
1422
|
if (h(t) || t.tagName.toLowerCase() === "svg" || t.tagName.toLowerCase() === "img") continue;
|
|
1420
|
-
|
|
1423
|
+
x(t) || a.push({
|
|
1421
1424
|
ruleId: "text-alternatives/role-img-alt",
|
|
1422
1425
|
selector: p(t),
|
|
1423
1426
|
html: m(t),
|
|
@@ -1441,7 +1444,7 @@ const Ut = {
|
|
|
1441
1444
|
run(e) {
|
|
1442
1445
|
const a = [];
|
|
1443
1446
|
for (const t of e.querySelectorAll("video")) {
|
|
1444
|
-
if (h(t) ||
|
|
1447
|
+
if (h(t) || I(t) || t.hasAttribute("muted") || t.hasAttribute("autoplay")) continue;
|
|
1445
1448
|
t.querySelector('track[kind="captions"], track[kind="subtitles"]') || a.push({
|
|
1446
1449
|
ruleId: "time-based-media/video-captions",
|
|
1447
1450
|
selector: p(t),
|
|
@@ -1465,7 +1468,7 @@ const Ut = {
|
|
|
1465
1468
|
run(e) {
|
|
1466
1469
|
const a = [];
|
|
1467
1470
|
for (const t of e.querySelectorAll("audio")) {
|
|
1468
|
-
if (h(t) ||
|
|
1471
|
+
if (h(t) || I(t) || t.querySelector('track[kind="captions"], track[kind="descriptions"]') || t.hasAttribute("aria-describedby")) continue;
|
|
1469
1472
|
const n = t.parentElement;
|
|
1470
1473
|
n && n.querySelector('a[href*="transcript"], a[href*="text"]') || a.push({
|
|
1471
1474
|
ruleId: "time-based-media/audio-transcript",
|
|
@@ -1564,7 +1567,7 @@ const na = {
|
|
|
1564
1567
|
run(e) {
|
|
1565
1568
|
const a = [];
|
|
1566
1569
|
for (const t of e.querySelectorAll("[autocomplete]")) {
|
|
1567
|
-
if (h(t) ||
|
|
1570
|
+
if (h(t) || I(t) || t.disabled || t.getAttribute("aria-disabled") === "true") continue;
|
|
1568
1571
|
const i = t.getAttribute("autocomplete").trim();
|
|
1569
1572
|
i && (ia(i) || a.push({
|
|
1570
1573
|
ruleId: "adaptable/autocomplete-valid",
|
|
@@ -1577,7 +1580,7 @@ const na = {
|
|
|
1577
1580
|
return a;
|
|
1578
1581
|
}
|
|
1579
1582
|
};
|
|
1580
|
-
function
|
|
1583
|
+
function Vn(e) {
|
|
1581
1584
|
if (typeof e != "object" || e === null)
|
|
1582
1585
|
return "Rule spec must be an object";
|
|
1583
1586
|
const a = e;
|
|
@@ -1607,10 +1610,10 @@ function On(e) {
|
|
|
1607
1610
|
return "Rule must have a wcag array";
|
|
1608
1611
|
if (typeof a.level != "string" || !["A", "AA"].includes(a.level))
|
|
1609
1612
|
return "Rule must have level A or AA";
|
|
1610
|
-
const n =
|
|
1613
|
+
const n = oa(t);
|
|
1611
1614
|
return n || null;
|
|
1612
1615
|
}
|
|
1613
|
-
function
|
|
1616
|
+
function oa(e) {
|
|
1614
1617
|
switch (e.type) {
|
|
1615
1618
|
case "selector-exists":
|
|
1616
1619
|
return null;
|
|
@@ -1650,28 +1653,28 @@ function N(e) {
|
|
|
1650
1653
|
description: e.description,
|
|
1651
1654
|
guidance: e.guidance,
|
|
1652
1655
|
run(t) {
|
|
1653
|
-
var n,
|
|
1656
|
+
var n, o;
|
|
1654
1657
|
const i = [];
|
|
1655
1658
|
switch (e.check.type) {
|
|
1656
1659
|
case "selector-exists": {
|
|
1657
|
-
for (const
|
|
1658
|
-
a && h(
|
|
1660
|
+
for (const r of t.querySelectorAll(e.selector))
|
|
1661
|
+
a && h(r) || i.push({
|
|
1659
1662
|
ruleId: e.id,
|
|
1660
|
-
selector: p(
|
|
1661
|
-
html: m(
|
|
1663
|
+
selector: p(r),
|
|
1664
|
+
html: m(r),
|
|
1662
1665
|
impact: e.impact,
|
|
1663
|
-
message: L(e.message,
|
|
1666
|
+
message: L(e.message, r, e.check),
|
|
1664
1667
|
...e.fix ? { fix: e.fix } : {},
|
|
1665
|
-
element:
|
|
1668
|
+
element: r
|
|
1666
1669
|
});
|
|
1667
1670
|
break;
|
|
1668
1671
|
}
|
|
1669
1672
|
case "attribute-value": {
|
|
1670
|
-
const { attribute:
|
|
1673
|
+
const { attribute: r, operator: s, value: l } = e.check;
|
|
1671
1674
|
for (const d of t.querySelectorAll(e.selector)) {
|
|
1672
1675
|
if (a && h(d)) continue;
|
|
1673
|
-
const c = d.getAttribute(
|
|
1674
|
-
c !== null &&
|
|
1676
|
+
const c = d.getAttribute(r);
|
|
1677
|
+
c !== null && ra(c, s, l) && i.push({
|
|
1675
1678
|
ruleId: e.id,
|
|
1676
1679
|
selector: p(d),
|
|
1677
1680
|
html: m(d),
|
|
@@ -1684,9 +1687,9 @@ function N(e) {
|
|
|
1684
1687
|
break;
|
|
1685
1688
|
}
|
|
1686
1689
|
case "attribute-missing": {
|
|
1687
|
-
const { attribute:
|
|
1690
|
+
const { attribute: r } = e.check;
|
|
1688
1691
|
for (const s of t.querySelectorAll(e.selector))
|
|
1689
|
-
a && h(s) || s.hasAttribute(
|
|
1692
|
+
a && h(s) || s.hasAttribute(r) || i.push({
|
|
1690
1693
|
ruleId: e.id,
|
|
1691
1694
|
selector: p(s),
|
|
1692
1695
|
html: m(s),
|
|
@@ -1698,7 +1701,7 @@ function N(e) {
|
|
|
1698
1701
|
break;
|
|
1699
1702
|
}
|
|
1700
1703
|
case "attribute-regex": {
|
|
1701
|
-
const { attribute:
|
|
1704
|
+
const { attribute: r, pattern: s, flags: l, shouldMatch: d } = e.check;
|
|
1702
1705
|
let c;
|
|
1703
1706
|
try {
|
|
1704
1707
|
c = new RegExp(s, l);
|
|
@@ -1707,7 +1710,7 @@ function N(e) {
|
|
|
1707
1710
|
}
|
|
1708
1711
|
for (const u of t.querySelectorAll(e.selector)) {
|
|
1709
1712
|
if (a && h(u)) continue;
|
|
1710
|
-
const b = u.getAttribute(
|
|
1713
|
+
const b = u.getAttribute(r);
|
|
1711
1714
|
if (b === null) continue;
|
|
1712
1715
|
const g = c.test(b);
|
|
1713
1716
|
d && !g ? i.push({
|
|
@@ -1731,9 +1734,9 @@ function N(e) {
|
|
|
1731
1734
|
break;
|
|
1732
1735
|
}
|
|
1733
1736
|
case "child-required": {
|
|
1734
|
-
const { childSelector:
|
|
1737
|
+
const { childSelector: r } = e.check;
|
|
1735
1738
|
for (const s of t.querySelectorAll(e.selector))
|
|
1736
|
-
a && h(s) || s.querySelector(
|
|
1739
|
+
a && h(s) || s.querySelector(r) || i.push({
|
|
1737
1740
|
ruleId: e.id,
|
|
1738
1741
|
selector: p(s),
|
|
1739
1742
|
html: m(s),
|
|
@@ -1745,7 +1748,7 @@ function N(e) {
|
|
|
1745
1748
|
break;
|
|
1746
1749
|
}
|
|
1747
1750
|
case "child-invalid": {
|
|
1748
|
-
const
|
|
1751
|
+
const r = new Set(
|
|
1749
1752
|
e.check.allowedChildren.map((l) => l.toLowerCase())
|
|
1750
1753
|
), s = e.check.allowedChildRoles ? new Set(e.check.allowedChildRoles.map((l) => l.toLowerCase())) : null;
|
|
1751
1754
|
for (const l of t.querySelectorAll(e.selector)) {
|
|
@@ -1772,8 +1775,8 @@ function N(e) {
|
|
|
1772
1775
|
}
|
|
1773
1776
|
if (!c)
|
|
1774
1777
|
for (const b of l.children) {
|
|
1775
|
-
if (
|
|
1776
|
-
const g = (
|
|
1778
|
+
if (r.has(b.tagName.toLowerCase())) continue;
|
|
1779
|
+
const g = (o = b.getAttribute("role")) == null ? void 0 : o.trim().toLowerCase();
|
|
1777
1780
|
if (!(g && (s != null && s.has(g))) && !(g === "presentation" || g === "none")) {
|
|
1778
1781
|
i.push({
|
|
1779
1782
|
ruleId: e.id,
|
|
@@ -1795,7 +1798,7 @@ function N(e) {
|
|
|
1795
1798
|
}
|
|
1796
1799
|
};
|
|
1797
1800
|
}
|
|
1798
|
-
function
|
|
1801
|
+
function ra(e, a, t) {
|
|
1799
1802
|
switch (a) {
|
|
1800
1803
|
case ">":
|
|
1801
1804
|
return parseFloat(e) > t;
|
|
@@ -1839,8 +1842,8 @@ const sa = {
|
|
|
1839
1842
|
if (h(i)) continue;
|
|
1840
1843
|
const n = i.parentElement;
|
|
1841
1844
|
if (!n) continue;
|
|
1842
|
-
const
|
|
1843
|
-
|
|
1845
|
+
const o = n.tagName.toLowerCase();
|
|
1846
|
+
o === "ul" || o === "ol" || o === "menu" || ((t = n.getAttribute("role")) == null ? void 0 : t.trim().toLowerCase()) === "list" || a.push({
|
|
1844
1847
|
ruleId: "adaptable/listitem-parent",
|
|
1845
1848
|
selector: p(i),
|
|
1846
1849
|
html: m(i),
|
|
@@ -1862,8 +1865,8 @@ const sa = {
|
|
|
1862
1865
|
var t;
|
|
1863
1866
|
const a = [];
|
|
1864
1867
|
for (const i of e.querySelectorAll("dt, dd")) {
|
|
1865
|
-
const n = i.parentElement,
|
|
1866
|
-
(!n ||
|
|
1868
|
+
const n = i.parentElement, o = n == null ? void 0 : n.tagName.toLowerCase();
|
|
1869
|
+
(!n || o !== "dl" && !(o === "div" && ((t = n.parentElement) == null ? void 0 : t.tagName.toLowerCase()) === "dl")) && a.push({
|
|
1867
1870
|
ruleId: "adaptable/dl-children",
|
|
1868
1871
|
selector: p(i),
|
|
1869
1872
|
html: m(i),
|
|
@@ -1885,7 +1888,7 @@ const sa = {
|
|
|
1885
1888
|
fixability: "contextual",
|
|
1886
1889
|
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 if they represent a term change to <dt>, if a definition change to <dd>. Styling wrappers should be replaced with <div> elements containing <dt>/<dd> pairs."
|
|
1887
1890
|
}, ma = N(ua);
|
|
1888
|
-
function
|
|
1891
|
+
function We(e, a) {
|
|
1889
1892
|
switch (a.toLowerCase()) {
|
|
1890
1893
|
case "deg":
|
|
1891
1894
|
return e;
|
|
@@ -1907,29 +1910,29 @@ function pa(e) {
|
|
|
1907
1910
|
/rotate[Z]?\(\s*(-?[\d.]+)(deg|rad|turn|grad)\s*\)/i
|
|
1908
1911
|
);
|
|
1909
1912
|
if (a) {
|
|
1910
|
-
const n =
|
|
1913
|
+
const n = We(parseFloat(a[1]), a[2]);
|
|
1911
1914
|
if (B(n)) return !0;
|
|
1912
1915
|
}
|
|
1913
1916
|
const t = e.match(
|
|
1914
1917
|
/matrix\(\s*(-?[\d.e]+)\s*,\s*(-?[\d.e]+)\s*,\s*(-?[\d.e]+)\s*,\s*(-?[\d.e]+)/i
|
|
1915
1918
|
);
|
|
1916
1919
|
if (t) {
|
|
1917
|
-
const n = parseFloat(t[1]),
|
|
1918
|
-
if (B(
|
|
1920
|
+
const n = parseFloat(t[1]), o = parseFloat(t[2]), r = Math.atan2(o, n) * (180 / Math.PI);
|
|
1921
|
+
if (B(r)) return !0;
|
|
1919
1922
|
}
|
|
1920
1923
|
const i = e.match(
|
|
1921
1924
|
/matrix3d\(\s*(-?[\d.e]+)\s*,\s*(-?[\d.e]+)\s*,\s*(-?[\d.e]+)\s*,\s*(-?[\d.e]+)\s*,\s*(-?[\d.e]+)\s*,\s*(-?[\d.e]+)/i
|
|
1922
1925
|
);
|
|
1923
1926
|
if (i) {
|
|
1924
|
-
const n = parseFloat(i[1]),
|
|
1925
|
-
if (B(
|
|
1927
|
+
const n = parseFloat(i[1]), o = parseFloat(i[2]), r = Math.atan2(o, n) * (180 / Math.PI);
|
|
1928
|
+
if (B(r)) return !0;
|
|
1926
1929
|
}
|
|
1927
1930
|
return !1;
|
|
1928
1931
|
}
|
|
1929
1932
|
function ba(e) {
|
|
1930
1933
|
const a = e.match(/(-?[\d.]+)(deg|rad|turn|grad)/i);
|
|
1931
1934
|
if (!a) return !1;
|
|
1932
|
-
const t =
|
|
1935
|
+
const t = We(parseFloat(a[1]), a[2]);
|
|
1933
1936
|
return B(t);
|
|
1934
1937
|
}
|
|
1935
1938
|
const ha = {
|
|
@@ -1946,15 +1949,15 @@ const ha = {
|
|
|
1946
1949
|
const a = [];
|
|
1947
1950
|
for (const t of e.querySelectorAll("style")) {
|
|
1948
1951
|
const i = t.textContent || "", n = /@media[^{]*\b(orientation)\s*:\s*(portrait|landscape)\b[^{]*\{([^}]*\{[^}]*\}[^}]*)\}/gi;
|
|
1949
|
-
let
|
|
1950
|
-
for (;
|
|
1951
|
-
const
|
|
1952
|
+
let o;
|
|
1953
|
+
for (; o = n.exec(i); ) {
|
|
1954
|
+
const r = o[3];
|
|
1952
1955
|
let s = !1;
|
|
1953
|
-
const l =
|
|
1956
|
+
const l = r.match(
|
|
1954
1957
|
/transform\s*:\s*([^;]+)/i
|
|
1955
1958
|
);
|
|
1956
1959
|
if (l && pa(l[1]) && (s = !0), !s) {
|
|
1957
|
-
const d =
|
|
1960
|
+
const d = r.match(
|
|
1958
1961
|
/(?:^|[{;\s])rotate\s*:\s*([^;]+)/i
|
|
1959
1962
|
);
|
|
1960
1963
|
d && ba(d[1]) && (s = !0);
|
|
@@ -1964,7 +1967,7 @@ const ha = {
|
|
|
1964
1967
|
selector: p(t),
|
|
1965
1968
|
html: m(t),
|
|
1966
1969
|
impact: "serious",
|
|
1967
|
-
message: `CSS locks page orientation via @media (orientation: ${
|
|
1970
|
+
message: `CSS locks page orientation via @media (orientation: ${o[2]}) with a 90° transform.`
|
|
1968
1971
|
});
|
|
1969
1972
|
}
|
|
1970
1973
|
}
|
|
@@ -2001,24 +2004,24 @@ const ha = {
|
|
|
2001
2004
|
"treegrid"
|
|
2002
2005
|
]);
|
|
2003
2006
|
function fa(e, a) {
|
|
2004
|
-
var
|
|
2005
|
-
const t = ((
|
|
2006
|
-
let
|
|
2007
|
+
var r;
|
|
2008
|
+
const t = ((r = e.getAttribute("aria-owns")) == null ? void 0 : r.split(/\s+/)) || [], i = e.ownerDocument, n = /* @__PURE__ */ new Set();
|
|
2009
|
+
let o = !1;
|
|
2007
2010
|
for (const s of e.querySelectorAll("*")) {
|
|
2008
2011
|
if (h(s)) continue;
|
|
2009
|
-
|
|
2010
|
-
const l =
|
|
2012
|
+
o = !0;
|
|
2013
|
+
const l = j(s);
|
|
2011
2014
|
l && n.add(l);
|
|
2012
2015
|
}
|
|
2013
2016
|
for (const s of t) {
|
|
2014
2017
|
const l = i.getElementById(s);
|
|
2015
2018
|
if (l && !h(l)) {
|
|
2016
|
-
|
|
2017
|
-
const d =
|
|
2019
|
+
o = !0;
|
|
2020
|
+
const d = j(l);
|
|
2018
2021
|
d && n.add(d);
|
|
2019
2022
|
}
|
|
2020
2023
|
}
|
|
2021
|
-
if (!
|
|
2024
|
+
if (!o) return "empty";
|
|
2022
2025
|
for (const s of a)
|
|
2023
2026
|
if (!s.some((l) => n.has(l))) return "fail";
|
|
2024
2027
|
return "pass";
|
|
@@ -2044,9 +2047,9 @@ const va = {
|
|
|
2044
2047
|
const l = i.tagName.toLowerCase();
|
|
2045
2048
|
if (l === "input" || l === "textarea") continue;
|
|
2046
2049
|
}
|
|
2047
|
-
const
|
|
2048
|
-
if (
|
|
2049
|
-
const s =
|
|
2050
|
+
const o = ke[n], r = fa(i, o);
|
|
2051
|
+
if (r === "pass" || r === "empty" && ga.has(n)) continue;
|
|
2052
|
+
const s = o.map((l) => l.join(" or ")).join(", ");
|
|
2050
2053
|
a.push({
|
|
2051
2054
|
ruleId: "adaptable/aria-required-children",
|
|
2052
2055
|
selector: p(i),
|
|
@@ -2088,27 +2091,27 @@ const va = {
|
|
|
2088
2091
|
if (h(i)) continue;
|
|
2089
2092
|
const n = (t = i.getAttribute("role")) == null ? void 0 : t.trim().toLowerCase();
|
|
2090
2093
|
if (!n || !(n in Se)) continue;
|
|
2091
|
-
const
|
|
2092
|
-
let
|
|
2093
|
-
for (;
|
|
2094
|
-
const l =
|
|
2095
|
-
if (l &&
|
|
2094
|
+
const o = Se[n];
|
|
2095
|
+
let r = i.parentElement, s = !1;
|
|
2096
|
+
for (; r && r !== e.documentElement; ) {
|
|
2097
|
+
const l = j(r);
|
|
2098
|
+
if (l && o.includes(l)) {
|
|
2096
2099
|
s = !0;
|
|
2097
2100
|
break;
|
|
2098
2101
|
}
|
|
2099
|
-
|
|
2102
|
+
r = r.parentElement;
|
|
2100
2103
|
}
|
|
2101
2104
|
s || a.push({
|
|
2102
2105
|
ruleId: "adaptable/aria-required-parent",
|
|
2103
2106
|
selector: p(i),
|
|
2104
2107
|
html: m(i),
|
|
2105
2108
|
impact: "critical",
|
|
2106
|
-
message: `Role "${n}" must be contained within: ${
|
|
2109
|
+
message: `Role "${n}" must be contained within: ${o.join(", ")}.`
|
|
2107
2110
|
});
|
|
2108
2111
|
}
|
|
2109
2112
|
return a;
|
|
2110
2113
|
}
|
|
2111
|
-
},
|
|
2114
|
+
}, wa = {
|
|
2112
2115
|
id: "adaptable/td-headers-attr",
|
|
2113
2116
|
category: "adaptable",
|
|
2114
2117
|
actRuleIds: ["a25f45"],
|
|
@@ -2123,25 +2126,25 @@ const va = {
|
|
|
2123
2126
|
if (h(t)) continue;
|
|
2124
2127
|
const i = t.closest("table");
|
|
2125
2128
|
if (!i) continue;
|
|
2126
|
-
const n = t.getAttribute("id"),
|
|
2127
|
-
for (const
|
|
2128
|
-
if (
|
|
2129
|
+
const n = t.getAttribute("id"), o = t.getAttribute("headers").split(/\s+/);
|
|
2130
|
+
for (const r of o) {
|
|
2131
|
+
if (r === n) {
|
|
2129
2132
|
a.push({
|
|
2130
2133
|
ruleId: "adaptable/td-headers-attr",
|
|
2131
2134
|
selector: p(t),
|
|
2132
2135
|
html: m(t),
|
|
2133
2136
|
impact: "serious",
|
|
2134
|
-
message: `Headers attribute references the cell itself ("${
|
|
2137
|
+
message: `Headers attribute references the cell itself ("${r}").`
|
|
2135
2138
|
});
|
|
2136
2139
|
break;
|
|
2137
2140
|
}
|
|
2138
|
-
if (!i.querySelector(`th#${CSS.escape(
|
|
2141
|
+
if (!i.querySelector(`th#${CSS.escape(r)}, td#${CSS.escape(r)}`)) {
|
|
2139
2142
|
a.push({
|
|
2140
2143
|
ruleId: "adaptable/td-headers-attr",
|
|
2141
2144
|
selector: p(t),
|
|
2142
2145
|
html: m(t),
|
|
2143
2146
|
impact: "serious",
|
|
2144
|
-
message: `Headers attribute references non-existent ID "${
|
|
2147
|
+
message: `Headers attribute references non-existent ID "${r}".`
|
|
2145
2148
|
});
|
|
2146
2149
|
break;
|
|
2147
2150
|
}
|
|
@@ -2149,7 +2152,7 @@ const va = {
|
|
|
2149
2152
|
}
|
|
2150
2153
|
return a;
|
|
2151
2154
|
}
|
|
2152
|
-
},
|
|
2155
|
+
}, xa = {
|
|
2153
2156
|
id: "adaptable/th-has-data-cells",
|
|
2154
2157
|
category: "adaptable",
|
|
2155
2158
|
actRuleIds: ["d0f69e"],
|
|
@@ -2205,16 +2208,16 @@ const ka = {
|
|
|
2205
2208
|
const a = [];
|
|
2206
2209
|
for (const i of e.querySelectorAll("table")) {
|
|
2207
2210
|
if (h(i) || !Aa(i)) continue;
|
|
2208
|
-
const n = i.querySelectorAll("tr"),
|
|
2209
|
-
let
|
|
2211
|
+
const n = i.querySelectorAll("tr"), o = n.length;
|
|
2212
|
+
let r = 0;
|
|
2210
2213
|
for (const d of n) {
|
|
2211
2214
|
const c = d.querySelectorAll("td, th");
|
|
2212
2215
|
let u = 0;
|
|
2213
2216
|
for (const b of c)
|
|
2214
2217
|
u += parseInt(b.getAttribute("colspan") || "1", 10);
|
|
2215
|
-
|
|
2218
|
+
r = Math.max(r, u);
|
|
2216
2219
|
}
|
|
2217
|
-
if (
|
|
2220
|
+
if (o <= 3 && r <= 3) continue;
|
|
2218
2221
|
const s = i.querySelector("th[scope]") !== null, l = i.querySelector("td[headers]") !== null;
|
|
2219
2222
|
for (const d of i.querySelectorAll("td")) {
|
|
2220
2223
|
if (h(d) || !((t = d.textContent) != null && t.trim()) && !d.querySelector("img, svg, input, select, textarea") || d.hasAttribute("aria-label") || d.hasAttribute("aria-labelledby") || d.hasAttribute("headers")) continue;
|
|
@@ -2258,13 +2261,13 @@ const ka = {
|
|
|
2258
2261
|
const a = [], t = /* @__PURE__ */ new Set(["row", "col", "rowgroup", "colgroup"]);
|
|
2259
2262
|
for (const n of e.querySelectorAll("th[scope]")) {
|
|
2260
2263
|
if (h(n)) continue;
|
|
2261
|
-
const
|
|
2262
|
-
|
|
2264
|
+
const o = (i = n.getAttribute("scope")) == null ? void 0 : i.toLowerCase();
|
|
2265
|
+
o && !t.has(o) && a.push({
|
|
2263
2266
|
ruleId: "adaptable/scope-attr-valid",
|
|
2264
2267
|
selector: p(n),
|
|
2265
2268
|
html: m(n),
|
|
2266
2269
|
impact: "moderate",
|
|
2267
|
-
message: `Invalid scope value "${
|
|
2270
|
+
message: `Invalid scope value "${o}". Use row, col, rowgroup, or colgroup.`
|
|
2268
2271
|
});
|
|
2269
2272
|
}
|
|
2270
2273
|
return a;
|
|
@@ -2284,7 +2287,7 @@ const ka = {
|
|
|
2284
2287
|
for (const t of e.querySelectorAll("th")) {
|
|
2285
2288
|
if (h(t)) continue;
|
|
2286
2289
|
const i = t.closest("table");
|
|
2287
|
-
(i == null ? void 0 : i.getAttribute("role")) === "presentation" || (i == null ? void 0 : i.getAttribute("role")) === "none" ||
|
|
2290
|
+
(i == null ? void 0 : i.getAttribute("role")) === "presentation" || (i == null ? void 0 : i.getAttribute("role")) === "none" || x(t) || a.push({
|
|
2288
2291
|
ruleId: "adaptable/empty-table-header",
|
|
2289
2292
|
selector: p(t),
|
|
2290
2293
|
html: m(t),
|
|
@@ -2294,7 +2297,7 @@ const ka = {
|
|
|
2294
2297
|
}
|
|
2295
2298
|
return a;
|
|
2296
2299
|
}
|
|
2297
|
-
},
|
|
2300
|
+
}, qa = {
|
|
2298
2301
|
id: "distinguishable/meta-viewport",
|
|
2299
2302
|
category: "distinguishable",
|
|
2300
2303
|
actRuleIds: ["b4f0c3"],
|
|
@@ -2308,9 +2311,9 @@ const ka = {
|
|
|
2308
2311
|
run(e) {
|
|
2309
2312
|
const a = [], t = e.querySelector('meta[name="viewport"]');
|
|
2310
2313
|
if (!t) return [];
|
|
2311
|
-
const i = t.getAttribute("content") || "", n = i.toLowerCase(),
|
|
2312
|
-
if (
|
|
2313
|
-
const s =
|
|
2314
|
+
const i = t.getAttribute("content") || "", n = i.toLowerCase(), o = n.match(/user-scalable\s*=\s*([^\s,;]+)/i);
|
|
2315
|
+
if (o) {
|
|
2316
|
+
const s = o[1], l = parseFloat(s);
|
|
2314
2317
|
(s === "no" || !isNaN(l) && l > -1 && l < 1) && a.push({
|
|
2315
2318
|
ruleId: "distinguishable/meta-viewport",
|
|
2316
2319
|
selector: p(t),
|
|
@@ -2321,9 +2324,9 @@ const ka = {
|
|
|
2321
2324
|
fix: { type: "suggest", suggestion: "Remove user-scalable=no from the viewport meta content attribute" }
|
|
2322
2325
|
});
|
|
2323
2326
|
}
|
|
2324
|
-
const
|
|
2325
|
-
if (
|
|
2326
|
-
const s =
|
|
2327
|
+
const r = n.match(/maximum-scale\s*=\s*([\d.]+|yes)/i);
|
|
2328
|
+
if (r) {
|
|
2329
|
+
const s = r[1], l = s.toLowerCase() === "yes" ? 1 : parseFloat(s);
|
|
2327
2330
|
l < 2 && a.push({
|
|
2328
2331
|
ruleId: "distinguishable/meta-viewport",
|
|
2329
2332
|
selector: p(t),
|
|
@@ -2340,27 +2343,27 @@ const ka = {
|
|
|
2340
2343
|
function ce(e) {
|
|
2341
2344
|
return e.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
2342
2345
|
}
|
|
2343
|
-
function
|
|
2346
|
+
function je(e, a) {
|
|
2344
2347
|
const t = e.getAttribute("style");
|
|
2345
2348
|
if (!t) return null;
|
|
2346
2349
|
const i = new RegExp(
|
|
2347
2350
|
`${ce(a)}\\s*:\\s*([^;!]+)\\s*!\\s*important`,
|
|
2348
2351
|
"gi"
|
|
2349
2352
|
);
|
|
2350
|
-
let n = null,
|
|
2351
|
-
for (;
|
|
2352
|
-
n =
|
|
2353
|
+
let n = null, o;
|
|
2354
|
+
for (; o = i.exec(t); )
|
|
2355
|
+
n = o;
|
|
2353
2356
|
if (!n) return null;
|
|
2354
|
-
const
|
|
2355
|
-
if (/^(inherit|unset|revert)$/i.test(
|
|
2356
|
-
if (/^(normal|initial)$/i.test(
|
|
2357
|
-
const s =
|
|
2357
|
+
const r = n[1].trim();
|
|
2358
|
+
if (/^(inherit|unset|revert)$/i.test(r)) return null;
|
|
2359
|
+
if (/^(normal|initial)$/i.test(r)) return { em: 0, px: null };
|
|
2360
|
+
const s = r.match(/^(-?[\d.]+)\s*em$/i);
|
|
2358
2361
|
if (s) return { em: parseFloat(s[1]), px: null };
|
|
2359
|
-
const l =
|
|
2362
|
+
const l = r.match(/^(-?[\d.]+)$/);
|
|
2360
2363
|
if (l) return { em: parseFloat(l[1]), px: null };
|
|
2361
|
-
const d =
|
|
2364
|
+
const d = r.match(/^(-?[\d.]+)\s*%$/);
|
|
2362
2365
|
if (d) return { em: parseFloat(d[1]) / 100, px: null };
|
|
2363
|
-
const c =
|
|
2366
|
+
const c = r.match(/^(-?[\d.]+)\s*(px|pt|cm|mm|in)$/i);
|
|
2364
2367
|
if (c) {
|
|
2365
2368
|
const u = parseFloat(c[1]), b = c[2].toLowerCase();
|
|
2366
2369
|
let g;
|
|
@@ -2388,28 +2391,28 @@ function We(e, a) {
|
|
|
2388
2391
|
return null;
|
|
2389
2392
|
}
|
|
2390
2393
|
function Ue(e, a, t, i) {
|
|
2391
|
-
function n(
|
|
2392
|
-
var
|
|
2393
|
-
if (
|
|
2394
|
-
const s =
|
|
2394
|
+
function n(o) {
|
|
2395
|
+
var r;
|
|
2396
|
+
if (o !== e) {
|
|
2397
|
+
const s = o.getAttribute("style") || "";
|
|
2395
2398
|
if (new RegExp(
|
|
2396
2399
|
`${ce(a)}\\s*:\\s*[^;!]+\\s*!\\s*important`,
|
|
2397
2400
|
"i"
|
|
2398
2401
|
).test(s)) return !1;
|
|
2399
2402
|
}
|
|
2400
|
-
for (const s of
|
|
2401
|
-
if (s.nodeType === 3 && ((
|
|
2402
|
-
const l = parseFloat(
|
|
2403
|
+
for (const s of o.childNodes)
|
|
2404
|
+
if (s.nodeType === 3 && ((r = s.textContent) != null && r.trim())) {
|
|
2405
|
+
const l = parseFloat(w(o).fontSize);
|
|
2403
2406
|
if (l > 0 && t / l < i) return !0;
|
|
2404
2407
|
break;
|
|
2405
2408
|
}
|
|
2406
|
-
for (const s of
|
|
2409
|
+
for (const s of o.children)
|
|
2407
2410
|
if (n(s)) return !0;
|
|
2408
2411
|
return !1;
|
|
2409
2412
|
}
|
|
2410
2413
|
return n(e);
|
|
2411
2414
|
}
|
|
2412
|
-
function
|
|
2415
|
+
function Ea(e) {
|
|
2413
2416
|
var a;
|
|
2414
2417
|
for (const t of e.childNodes)
|
|
2415
2418
|
if (t.nodeType === 3 && ((a = t.textContent) != null && a.trim()))
|
|
@@ -2431,7 +2434,7 @@ function Ve(e) {
|
|
|
2431
2434
|
return !1;
|
|
2432
2435
|
}
|
|
2433
2436
|
function de(e, a) {
|
|
2434
|
-
if (
|
|
2437
|
+
if (Ea(e)) return !0;
|
|
2435
2438
|
for (const t of e.children) {
|
|
2436
2439
|
const i = t.getAttribute("style") || "";
|
|
2437
2440
|
if (!new RegExp(
|
|
@@ -2444,17 +2447,17 @@ function de(e, a) {
|
|
|
2444
2447
|
}
|
|
2445
2448
|
function Be(e, a, t, i) {
|
|
2446
2449
|
const n = [];
|
|
2447
|
-
for (const
|
|
2448
|
-
if (h(
|
|
2449
|
-
const
|
|
2450
|
-
if (!
|
|
2450
|
+
for (const o of e.querySelectorAll("[style]")) {
|
|
2451
|
+
if (h(o) || !Oe(o) || Ve(o) || !de(o, t)) continue;
|
|
2452
|
+
const r = je(o, t);
|
|
2453
|
+
if (!r) continue;
|
|
2451
2454
|
let s = !1;
|
|
2452
|
-
if (
|
|
2453
|
-
const l =
|
|
2455
|
+
if (r.em !== null ? s = r.em < i : r.px !== null && (s = Ue(o, t, r.px, i)), s) {
|
|
2456
|
+
const l = r.em !== null ? `${r.em}${t === "line-height" ? "" : "em"}` : `${r.px}px`;
|
|
2454
2457
|
n.push({
|
|
2455
2458
|
ruleId: a,
|
|
2456
|
-
selector: p(
|
|
2457
|
-
html: m(
|
|
2459
|
+
selector: p(o),
|
|
2460
|
+
html: m(o),
|
|
2458
2461
|
impact: "serious",
|
|
2459
2462
|
message: `${t} ${l} with !important is below the ${i}${t === "line-height" ? "" : "em"} minimum.`
|
|
2460
2463
|
});
|
|
@@ -2465,10 +2468,10 @@ function Be(e, a, t, i) {
|
|
|
2465
2468
|
function La(e) {
|
|
2466
2469
|
let a = e, t = !1;
|
|
2467
2470
|
for (; a; ) {
|
|
2468
|
-
const i =
|
|
2471
|
+
const i = w(a);
|
|
2469
2472
|
parseFloat(i.width) > 500 && (t = !0), (i.whiteSpace === "nowrap" || i.whiteSpace === "pre") && (t = !0);
|
|
2470
|
-
const
|
|
2471
|
-
if ((
|
|
2473
|
+
const o = i.overflowX, r = i.overflowY;
|
|
2474
|
+
if ((o === "scroll" || o === "auto") && r !== "scroll" && r !== "auto")
|
|
2472
2475
|
return t;
|
|
2473
2476
|
a = a.parentElement;
|
|
2474
2477
|
}
|
|
@@ -2500,20 +2503,20 @@ const Ra = {
|
|
|
2500
2503
|
for (const t of e.querySelectorAll("[style]")) {
|
|
2501
2504
|
if (h(t) || !Oe(t) || Ve(t) || !de(t, "line-height") || La(t)) continue;
|
|
2502
2505
|
if (t instanceof HTMLElement && t.scrollHeight > 0) {
|
|
2503
|
-
const
|
|
2504
|
-
if (
|
|
2506
|
+
const o = parseFloat(w(t).lineHeight);
|
|
2507
|
+
if (o > 0 && t.scrollHeight <= o * 1.5) continue;
|
|
2505
2508
|
}
|
|
2506
|
-
const i =
|
|
2509
|
+
const i = je(t, "line-height");
|
|
2507
2510
|
if (!i) continue;
|
|
2508
2511
|
let n = !1;
|
|
2509
2512
|
if (i.em !== null ? n = i.em < 1.5 : i.px !== null && (n = Ue(t, "line-height", i.px, 1.5)), n) {
|
|
2510
|
-
const
|
|
2513
|
+
const o = i.em !== null ? `${i.em}` : `${i.px}px`;
|
|
2511
2514
|
a.push({
|
|
2512
2515
|
ruleId: "distinguishable/line-height",
|
|
2513
2516
|
selector: p(t),
|
|
2514
2517
|
html: m(t),
|
|
2515
2518
|
impact: "serious",
|
|
2516
|
-
message: `Line height ${
|
|
2519
|
+
message: `Line height ${o} with !important is below the 1.5 minimum.`
|
|
2517
2520
|
});
|
|
2518
2521
|
}
|
|
2519
2522
|
}
|
|
@@ -2547,14 +2550,14 @@ const Ra = {
|
|
|
2547
2550
|
]);
|
|
2548
2551
|
function $a(e) {
|
|
2549
2552
|
let a = e.parentElement;
|
|
2550
|
-
for (; a && !Na.has(
|
|
2553
|
+
for (; a && !Na.has(w(a).display); )
|
|
2551
2554
|
a = a.parentElement;
|
|
2552
2555
|
if (!a) return null;
|
|
2553
2556
|
const t = a.ownerDocument.createTreeWalker(a, NodeFilter.SHOW_TEXT);
|
|
2554
|
-
let i = "", n = null,
|
|
2555
|
-
for (;
|
|
2556
|
-
if (!
|
|
2557
|
-
let s =
|
|
2557
|
+
let i = "", n = null, o;
|
|
2558
|
+
for (; o = t.nextNode(); ) {
|
|
2559
|
+
if (!o.data.trim()) continue;
|
|
2560
|
+
let s = o.parentElement, l = !1;
|
|
2558
2561
|
for (; s && s !== a; ) {
|
|
2559
2562
|
if (s.tagName === "A") {
|
|
2560
2563
|
l = !0;
|
|
@@ -2562,12 +2565,12 @@ function $a(e) {
|
|
|
2562
2565
|
}
|
|
2563
2566
|
s = s.parentElement;
|
|
2564
2567
|
}
|
|
2565
|
-
l || (i +=
|
|
2568
|
+
l || (i += o.data, !n && o.parentElement && (n = C(w(o.parentElement).color)));
|
|
2566
2569
|
}
|
|
2567
|
-
const
|
|
2568
|
-
return !n || !
|
|
2570
|
+
const r = i.match(new RegExp("\\p{L}{3,}", "gu"));
|
|
2571
|
+
return !n || !r || r.length < 2 ? null : { block: a, textColor: n };
|
|
2569
2572
|
}
|
|
2570
|
-
function
|
|
2573
|
+
function qe(e, a) {
|
|
2571
2574
|
const t = e.textDecorationLine || e.textDecoration || "";
|
|
2572
2575
|
return (t.includes("underline") || t.includes("line-through")) && t !== a;
|
|
2573
2576
|
}
|
|
@@ -2581,7 +2584,7 @@ function Ha(e) {
|
|
|
2581
2584
|
if (t.data.trim()) return !1;
|
|
2582
2585
|
return !0;
|
|
2583
2586
|
}
|
|
2584
|
-
const
|
|
2587
|
+
const Pa = {
|
|
2585
2588
|
id: "distinguishable/link-in-text-block",
|
|
2586
2589
|
category: "distinguishable",
|
|
2587
2590
|
wcag: ["1.4.1"],
|
|
@@ -2594,18 +2597,18 @@ const Da = {
|
|
|
2594
2597
|
const a = [];
|
|
2595
2598
|
for (const t of e.querySelectorAll("a[href]")) {
|
|
2596
2599
|
if (h(t) || !k(t).trim() || Ha(t) || t.closest('nav, header, footer, aside, [role="navigation"], [role="banner"], [role="contentinfo"], [role="complementary"]')) continue;
|
|
2597
|
-
const i =
|
|
2600
|
+
const i = w(t);
|
|
2598
2601
|
if (!Ma.has(i.display || "inline")) continue;
|
|
2599
2602
|
const n = $a(t);
|
|
2600
2603
|
if (!n) continue;
|
|
2601
|
-
const
|
|
2602
|
-
if (
|
|
2603
|
-
const l = parseFloat(i.fontSize) || 16, d = parseFloat(
|
|
2604
|
+
const o = w(n.block), r = o.textDecorationLine || o.textDecoration || "";
|
|
2605
|
+
if (qe(i, r) || (parseFloat(i.borderBottomWidth) || 0) > 0 && i.borderBottomStyle !== "none" && i.borderBottomStyle !== "hidden" || Math.abs(V(i.fontWeight) - V(o.fontWeight)) >= 300 || i.fontStyle !== o.fontStyle) continue;
|
|
2606
|
+
const l = parseFloat(i.fontSize) || 16, d = parseFloat(o.fontSize) || 16;
|
|
2604
2607
|
if (d > 0 && l / d >= 1.2) continue;
|
|
2605
2608
|
let c = !1;
|
|
2606
2609
|
for (const y of t.querySelectorAll("*")) {
|
|
2607
|
-
const A =
|
|
2608
|
-
if (
|
|
2610
|
+
const A = w(y);
|
|
2611
|
+
if (qe(A, r) || Math.abs(V(A.fontWeight) - V(o.fontWeight)) >= 300) {
|
|
2609
2612
|
c = !0;
|
|
2610
2613
|
break;
|
|
2611
2614
|
}
|
|
@@ -2613,7 +2616,7 @@ const Da = {
|
|
|
2613
2616
|
if (c) continue;
|
|
2614
2617
|
const u = C(i.color);
|
|
2615
2618
|
if (!u) continue;
|
|
2616
|
-
const b =
|
|
2619
|
+
const b = q(...u), g = q(...n.textColor), f = $(b, g);
|
|
2617
2620
|
if (f < 1.1 || f >= 3) continue;
|
|
2618
2621
|
const v = (y) => "#" + y.map((A) => A.toString(16).padStart(2, "0")).join("");
|
|
2619
2622
|
a.push({
|
|
@@ -2628,7 +2631,7 @@ const Da = {
|
|
|
2628
2631
|
}
|
|
2629
2632
|
return a;
|
|
2630
2633
|
}
|
|
2631
|
-
},
|
|
2634
|
+
}, Da = /* @__PURE__ */ new Set([
|
|
2632
2635
|
"SCRIPT",
|
|
2633
2636
|
"STYLE",
|
|
2634
2637
|
"NOSCRIPT",
|
|
@@ -2662,26 +2665,26 @@ function za(e) {
|
|
|
2662
2665
|
if (h(e)) return !0;
|
|
2663
2666
|
let a = e;
|
|
2664
2667
|
for (; a; ) {
|
|
2665
|
-
const t =
|
|
2668
|
+
const t = w(a);
|
|
2666
2669
|
if (t.display === "none" || t.visibility === "hidden" || Fa(t)) return !0;
|
|
2667
2670
|
a = a.parentElement;
|
|
2668
2671
|
}
|
|
2669
2672
|
return !1;
|
|
2670
2673
|
}
|
|
2671
|
-
function
|
|
2674
|
+
function Wa(e) {
|
|
2672
2675
|
return e instanceof HTMLInputElement || e instanceof HTMLTextAreaElement || e instanceof HTMLSelectElement || e instanceof HTMLButtonElement ? e.disabled : !!(e.closest("fieldset[disabled]") || e.getAttribute("aria-disabled") === "true");
|
|
2673
2676
|
}
|
|
2674
|
-
function
|
|
2677
|
+
function ja(e, a) {
|
|
2675
2678
|
if (e.tagName !== "LABEL") return !1;
|
|
2676
2679
|
const t = e, i = t.htmlFor;
|
|
2677
2680
|
if (i) {
|
|
2678
|
-
const
|
|
2679
|
-
if (
|
|
2681
|
+
const r = a.getElementById(i);
|
|
2682
|
+
if (r && (r.disabled || r.getAttribute("aria-disabled") === "true")) return !0;
|
|
2680
2683
|
}
|
|
2681
2684
|
const n = t.querySelector("input, select, textarea, button");
|
|
2682
2685
|
if (n && (n.disabled || n.getAttribute("aria-disabled") === "true")) return !0;
|
|
2683
|
-
const
|
|
2684
|
-
return !!(
|
|
2686
|
+
const o = t.id;
|
|
2687
|
+
return !!(o && a.querySelector(`[aria-labelledby~="${o}"][aria-disabled="true"]`));
|
|
2685
2688
|
}
|
|
2686
2689
|
function Ua(e) {
|
|
2687
2690
|
return e.closest("select") !== null;
|
|
@@ -2708,10 +2711,10 @@ function _a(e) {
|
|
|
2708
2711
|
const a = parseFloat(e);
|
|
2709
2712
|
return isNaN(a) ? NaN : e.trim().endsWith("%") ? a / 100 : a;
|
|
2710
2713
|
}
|
|
2711
|
-
const
|
|
2714
|
+
const Ee = /([a-z-]+)\(([^)]*)\)/g;
|
|
2712
2715
|
function Le(e) {
|
|
2713
2716
|
let a, t = !1;
|
|
2714
|
-
for (
|
|
2717
|
+
for (Ee.lastIndex = 0; a = Ee.exec(e); ) {
|
|
2715
2718
|
t = !0;
|
|
2716
2719
|
const i = Ba[a[1]];
|
|
2717
2720
|
if (i === void 0 || _a(a[2]) !== i) return !1;
|
|
@@ -2721,12 +2724,12 @@ function Le(e) {
|
|
|
2721
2724
|
function Ga(e) {
|
|
2722
2725
|
let a = e;
|
|
2723
2726
|
for (; a; ) {
|
|
2724
|
-
const t =
|
|
2727
|
+
const t = w(a), i = t.filter;
|
|
2725
2728
|
if (i && i !== "none" && i !== "initial" && !Le(i)) return !0;
|
|
2726
2729
|
const n = t.mixBlendMode;
|
|
2727
2730
|
if (n && n !== "normal" && n !== "initial") return !0;
|
|
2728
|
-
const
|
|
2729
|
-
if (
|
|
2731
|
+
const o = t.backdropFilter;
|
|
2732
|
+
if (o && o !== "none" && o !== "initial" && !Le(o)) return !0;
|
|
2730
2733
|
a = a.parentElement;
|
|
2731
2734
|
}
|
|
2732
2735
|
return !1;
|
|
@@ -2734,7 +2737,7 @@ function Ga(e) {
|
|
|
2734
2737
|
function Ya(e) {
|
|
2735
2738
|
let a = e;
|
|
2736
2739
|
for (; a; ) {
|
|
2737
|
-
const t =
|
|
2740
|
+
const t = w(a), i = t.backgroundImage;
|
|
2738
2741
|
if (i && i !== "none" && i !== "initial")
|
|
2739
2742
|
return i.includes("gradient(") ? { bgImage: i, gradientEl: a } : null;
|
|
2740
2743
|
const n = t.backgroundColor;
|
|
@@ -2750,7 +2753,7 @@ function Ya(e) {
|
|
|
2750
2753
|
}
|
|
2751
2754
|
return null;
|
|
2752
2755
|
}
|
|
2753
|
-
function Xa(e, a, t, i, n,
|
|
2756
|
+
function Xa(e, a, t, i, n, o, r, s, l) {
|
|
2754
2757
|
const d = It(s, l);
|
|
2755
2758
|
if (d.length === 0) return null;
|
|
2756
2759
|
let c = 0, u = d[0];
|
|
@@ -2758,8 +2761,8 @@ function Xa(e, a, t, i, n, r, o, s, l) {
|
|
|
2758
2761
|
let v = a;
|
|
2759
2762
|
t < 1 && (v = R(a, f, t)), i < 1 && (v = R(v, f, i));
|
|
2760
2763
|
const y = $(
|
|
2761
|
-
|
|
2762
|
-
|
|
2764
|
+
q(v[0], v[1], v[2]),
|
|
2765
|
+
q(f[0], f[1], f[2])
|
|
2763
2766
|
);
|
|
2764
2767
|
y > c && (c = y, u = f);
|
|
2765
2768
|
}
|
|
@@ -2768,11 +2771,11 @@ function Xa(e, a, t, i, n, r, o, s, l) {
|
|
|
2768
2771
|
t < 1 && (b = R(a, u, t)), i < 1 && (b = R(b, u, i));
|
|
2769
2772
|
const g = Math.round(c * 100) / 100;
|
|
2770
2773
|
return {
|
|
2771
|
-
ruleId:
|
|
2774
|
+
ruleId: o,
|
|
2772
2775
|
selector: p(e),
|
|
2773
2776
|
html: m(e),
|
|
2774
2777
|
impact: "serious",
|
|
2775
|
-
message: `Insufficient${
|
|
2778
|
+
message: `Insufficient${r === "AAA" ? " enhanced" : ""} color contrast ratio of ${g}:1 (required ${n}:1).`,
|
|
2776
2779
|
context: `foreground: ${_(b)} rgb(${b.join(", ")}), background: gradient, ratio: ${g}:1, required: ${n}:1`,
|
|
2777
2780
|
fix: { type: "suggest", suggestion: `Change the text color or gradient background so the contrast ratio meets ${n}:1. The current foreground is ${_(b)}.` }
|
|
2778
2781
|
};
|
|
@@ -2780,15 +2783,15 @@ function Xa(e, a, t, i, n, r, o, s, l) {
|
|
|
2780
2783
|
function _e(e, a, t) {
|
|
2781
2784
|
const i = [], n = e.body;
|
|
2782
2785
|
if (!n) return [];
|
|
2783
|
-
const
|
|
2786
|
+
const o = e.createTreeWalker(n, NodeFilter.SHOW_TEXT), r = /* @__PURE__ */ new Set();
|
|
2784
2787
|
let s;
|
|
2785
|
-
for (; s =
|
|
2788
|
+
for (; s = o.nextNode(); ) {
|
|
2786
2789
|
if (!s.textContent || !s.textContent.trim() || Oa(s.textContent)) continue;
|
|
2787
2790
|
const l = s.parentElement;
|
|
2788
|
-
if (!l ||
|
|
2791
|
+
if (!l || r.has(l) || (r.add(l), Da.has(l.tagName))) continue;
|
|
2789
2792
|
const d = l.tagName;
|
|
2790
|
-
if (d === "BODY" || d === "HTML" || Ua(l) ||
|
|
2791
|
-
const c =
|
|
2793
|
+
if (d === "BODY" || d === "HTML" || Ua(l) || Wa(l) || ja(l, e) || Va(l) || za(l)) continue;
|
|
2794
|
+
const c = w(l);
|
|
2792
2795
|
if (parseFloat(c.opacity) === 0) continue;
|
|
2793
2796
|
const u = Mt(l);
|
|
2794
2797
|
if (u < 0.1) continue;
|
|
@@ -2798,14 +2801,14 @@ function _e(e, a, t) {
|
|
|
2798
2801
|
const f = C(c.color);
|
|
2799
2802
|
if (!f) continue;
|
|
2800
2803
|
const v = U(c.color);
|
|
2801
|
-
if (v === 0 ||
|
|
2802
|
-
const y = t === "AAA" ?
|
|
2804
|
+
if (v === 0 || Et(l)) continue;
|
|
2805
|
+
const y = t === "AAA" ? we(l) ? 4.5 : 7 : we(l) ? 3 : 4.5;
|
|
2803
2806
|
let A = ye(l);
|
|
2804
2807
|
if (!A) {
|
|
2805
2808
|
if (g) continue;
|
|
2806
|
-
const
|
|
2807
|
-
if (
|
|
2808
|
-
const O =
|
|
2809
|
+
const E = Ya(l);
|
|
2810
|
+
if (E) {
|
|
2811
|
+
const O = E.gradientEl.parentElement ? ye(E.gradientEl.parentElement) : null, H = Xa(
|
|
2809
2812
|
l,
|
|
2810
2813
|
f,
|
|
2811
2814
|
v,
|
|
@@ -2813,7 +2816,7 @@ function _e(e, a, t) {
|
|
|
2813
2816
|
y,
|
|
2814
2817
|
a,
|
|
2815
2818
|
t,
|
|
2816
|
-
|
|
2819
|
+
E.bgImage,
|
|
2817
2820
|
O ?? [255, 255, 255]
|
|
2818
2821
|
);
|
|
2819
2822
|
H && i.push(H);
|
|
@@ -2822,16 +2825,16 @@ function _e(e, a, t) {
|
|
|
2822
2825
|
}
|
|
2823
2826
|
let S = f;
|
|
2824
2827
|
v < 1 && (S = R(f, A, v)), u < 1 && (S = R(S, A, u));
|
|
2825
|
-
const nt =
|
|
2828
|
+
const nt = q(S[0], S[1], S[2]), ot = q(A[0], A[1], A[2]), be = g ? Nt(S, A, g) : $(nt, ot);
|
|
2826
2829
|
if (be < y) {
|
|
2827
|
-
const
|
|
2830
|
+
const E = Math.round(be * 100) / 100, O = _(S), H = _(A);
|
|
2828
2831
|
i.push({
|
|
2829
2832
|
ruleId: a,
|
|
2830
2833
|
selector: p(l),
|
|
2831
2834
|
html: m(l),
|
|
2832
2835
|
impact: "serious",
|
|
2833
|
-
message: `Insufficient${t === "AAA" ? " enhanced" : ""} color contrast ratio of ${
|
|
2834
|
-
context: `foreground: ${O} rgb(${S.join(", ")}), background: ${H} rgb(${A.join(", ")}), ratio: ${
|
|
2836
|
+
message: `Insufficient${t === "AAA" ? " enhanced" : ""} color contrast ratio of ${E}:1 (required ${y}:1).`,
|
|
2837
|
+
context: `foreground: ${O} rgb(${S.join(", ")}), background: ${H} rgb(${A.join(", ")}), ratio: ${E}:1, required: ${y}:1`,
|
|
2835
2838
|
fix: { type: "suggest", suggestion: `Change the text color or background color so the contrast ratio meets ${y}:1. Current foreground is ${O}, background is ${H}.` }
|
|
2836
2839
|
});
|
|
2837
2840
|
}
|
|
@@ -2949,7 +2952,7 @@ const Ja = {
|
|
|
2949
2952
|
"select",
|
|
2950
2953
|
"textarea",
|
|
2951
2954
|
"video"
|
|
2952
|
-
]),
|
|
2955
|
+
]), oi = /* @__PURE__ */ new Set([
|
|
2953
2956
|
"button",
|
|
2954
2957
|
"checkbox",
|
|
2955
2958
|
"combobox",
|
|
@@ -2973,7 +2976,7 @@ const Ja = {
|
|
|
2973
2976
|
"tabpanel",
|
|
2974
2977
|
"textbox",
|
|
2975
2978
|
"treeitem"
|
|
2976
|
-
]),
|
|
2979
|
+
]), ri = {
|
|
2977
2980
|
grid: /* @__PURE__ */ new Set(["gridcell", "row", "columnheader", "rowheader"]),
|
|
2978
2981
|
listbox: /* @__PURE__ */ new Set(["option"]),
|
|
2979
2982
|
menu: /* @__PURE__ */ new Set(["menuitem", "menuitemcheckbox", "menuitemradio"]),
|
|
@@ -2984,9 +2987,9 @@ const Ja = {
|
|
|
2984
2987
|
treegrid: /* @__PURE__ */ new Set(["gridcell", "row", "columnheader", "rowheader", "treeitem"])
|
|
2985
2988
|
};
|
|
2986
2989
|
function si(e, a) {
|
|
2987
|
-
var n,
|
|
2988
|
-
const t = (n = e.getAttribute("role")) == null ? void 0 : n.toLowerCase(), i = (
|
|
2989
|
-
return !t || !i ? !1 : ((
|
|
2990
|
+
var n, o, r;
|
|
2991
|
+
const t = (n = e.getAttribute("role")) == null ? void 0 : n.toLowerCase(), i = (o = a.getAttribute("role")) == null ? void 0 : o.toLowerCase();
|
|
2992
|
+
return !t || !i ? !1 : ((r = ri[t]) == null ? void 0 : r.has(i)) ?? !1;
|
|
2990
2993
|
}
|
|
2991
2994
|
function li(e) {
|
|
2992
2995
|
var n;
|
|
@@ -2994,7 +2997,7 @@ function li(e) {
|
|
|
2994
2997
|
if (ni.has(a))
|
|
2995
2998
|
return a === "a" && !e.hasAttribute("href") ? !1 : a === "audio" || a === "video" ? e.hasAttribute("controls") : !(a === "img" && !e.hasAttribute("usemap") || a === "input" && e.type === "hidden" || e.disabled);
|
|
2996
2999
|
const t = (n = e.getAttribute("role")) == null ? void 0 : n.toLowerCase();
|
|
2997
|
-
if (t &&
|
|
3000
|
+
if (t && oi.has(t)) return !0;
|
|
2998
3001
|
const i = e.getAttribute("tabindex");
|
|
2999
3002
|
return i !== null && i !== "-1" || e.getAttribute("contenteditable") === "true";
|
|
3000
3003
|
}
|
|
@@ -3013,26 +3016,26 @@ const di = {
|
|
|
3013
3016
|
run(e) {
|
|
3014
3017
|
const a = [], t = e.body ?? e;
|
|
3015
3018
|
if (!t) return a;
|
|
3016
|
-
const n = (e.body ? e : e.ownerDocument).createTreeWalker(t, NodeFilter.SHOW_ELEMENT),
|
|
3017
|
-
let
|
|
3018
|
-
for (;
|
|
3019
|
-
for (;
|
|
3020
|
-
|
|
3021
|
-
if (!h(
|
|
3022
|
-
if (
|
|
3023
|
-
const s =
|
|
3024
|
-
si(s,
|
|
3019
|
+
const n = (e.body ? e : e.ownerDocument).createTreeWalker(t, NodeFilter.SHOW_ELEMENT), o = [];
|
|
3020
|
+
let r = n.currentNode;
|
|
3021
|
+
for (; r; ) {
|
|
3022
|
+
for (; o.length > 0 && !o[o.length - 1].contains(r); )
|
|
3023
|
+
o.pop();
|
|
3024
|
+
if (!h(r) && li(r)) {
|
|
3025
|
+
if (o.length > 0) {
|
|
3026
|
+
const s = o[o.length - 1];
|
|
3027
|
+
si(s, r) || a.push({
|
|
3025
3028
|
ruleId: "keyboard-accessible/nested-interactive",
|
|
3026
|
-
selector: p(
|
|
3027
|
-
html: m(
|
|
3029
|
+
selector: p(r),
|
|
3030
|
+
html: m(r),
|
|
3028
3031
|
impact: "serious",
|
|
3029
|
-
message: `Interactive element <${
|
|
3032
|
+
message: `Interactive element <${r.tagName.toLowerCase()}> is nested inside <${s.tagName.toLowerCase()}>.`,
|
|
3030
3033
|
fix: { type: "suggest", suggestion: "Move the nested interactive element outside its interactive parent so they are siblings instead of nested" }
|
|
3031
3034
|
});
|
|
3032
3035
|
}
|
|
3033
|
-
ci(
|
|
3036
|
+
ci(r) && o.push(r);
|
|
3034
3037
|
}
|
|
3035
|
-
|
|
3038
|
+
r = n.nextNode();
|
|
3036
3039
|
}
|
|
3037
3040
|
return a;
|
|
3038
3041
|
}
|
|
@@ -3053,9 +3056,9 @@ const di = {
|
|
|
3053
3056
|
if (h(i) || !(i instanceof HTMLElement)) continue;
|
|
3054
3057
|
const n = i.tagName.toLowerCase();
|
|
3055
3058
|
if (n === "body" || n === "html") continue;
|
|
3056
|
-
const
|
|
3057
|
-
if (
|
|
3058
|
-
const
|
|
3059
|
+
const o = i.getAttribute("role");
|
|
3060
|
+
if (o === "presentation" || o === "none" || o === "listbox" || o === "menu" || o === "tree" || o === "tabpanel") continue;
|
|
3061
|
+
const r = w(i), s = r.overflowX, l = r.overflowY;
|
|
3059
3062
|
if (!(s === "scroll" || s === "auto" || l === "scroll" || l === "auto")) continue;
|
|
3060
3063
|
if (i.scrollHeight > 0 || i.clientHeight > 0) {
|
|
3061
3064
|
const g = i.scrollHeight - i.clientHeight, f = i.scrollWidth - i.clientWidth;
|
|
@@ -3065,7 +3068,7 @@ const di = {
|
|
|
3065
3068
|
} else
|
|
3066
3069
|
continue;
|
|
3067
3070
|
const u = i.getAttribute("tabindex");
|
|
3068
|
-
u !== null && u !== "-1" || i.querySelector(
|
|
3071
|
+
u !== null && u !== "-1" || i.querySelector(W) || a.push({
|
|
3069
3072
|
ruleId: "keyboard-accessible/scrollable-region",
|
|
3070
3073
|
selector: p(i),
|
|
3071
3074
|
html: m(i),
|
|
@@ -3089,18 +3092,18 @@ const di = {
|
|
|
3089
3092
|
const a = [], t = /* @__PURE__ */ new Map();
|
|
3090
3093
|
for (const n of e.querySelectorAll("[accesskey]")) {
|
|
3091
3094
|
if (h(n)) continue;
|
|
3092
|
-
const
|
|
3093
|
-
if (!
|
|
3094
|
-
const
|
|
3095
|
-
|
|
3095
|
+
const o = (i = n.getAttribute("accesskey")) == null ? void 0 : i.trim().toLowerCase();
|
|
3096
|
+
if (!o) continue;
|
|
3097
|
+
const r = t.get(o) || [];
|
|
3098
|
+
r.push(n), t.set(o, r);
|
|
3096
3099
|
}
|
|
3097
|
-
for (const [n,
|
|
3098
|
-
if (
|
|
3099
|
-
for (const
|
|
3100
|
+
for (const [n, o] of t)
|
|
3101
|
+
if (o.length > 1)
|
|
3102
|
+
for (const r of o.slice(1))
|
|
3100
3103
|
a.push({
|
|
3101
3104
|
ruleId: "keyboard-accessible/accesskeys",
|
|
3102
|
-
selector: p(
|
|
3103
|
-
html: m(
|
|
3105
|
+
selector: p(r),
|
|
3106
|
+
html: m(r),
|
|
3104
3107
|
impact: "serious",
|
|
3105
3108
|
message: `Duplicate accesskey "${n}". Each accesskey must be unique.`
|
|
3106
3109
|
});
|
|
@@ -3118,12 +3121,12 @@ const di = {
|
|
|
3118
3121
|
guidance: "Keyboard users need to see which element has focus. Do not remove the default focus outline (outline: none) without providing an alternative visible indicator. Use :focus-visible or :focus styles to ensure focus is always perceivable.",
|
|
3119
3122
|
run(e) {
|
|
3120
3123
|
const a = [];
|
|
3121
|
-
for (const t of e.querySelectorAll(
|
|
3124
|
+
for (const t of e.querySelectorAll(W)) {
|
|
3122
3125
|
if (h(t) || !(t instanceof HTMLElement)) continue;
|
|
3123
3126
|
const i = t.getAttribute("style") || "";
|
|
3124
3127
|
if (/outline\s*:\s*(none|0)\s*(;|$|!)/i.test(i)) {
|
|
3125
|
-
const
|
|
3126
|
-
!
|
|
3128
|
+
const o = /border\s*:/i.test(i), r = /box-shadow\s*:/i.test(i);
|
|
3129
|
+
!o && !r && a.push({
|
|
3127
3130
|
ruleId: "keyboard-accessible/focus-visible",
|
|
3128
3131
|
selector: p(t),
|
|
3129
3132
|
html: m(t),
|
|
@@ -3183,12 +3186,12 @@ function ue(e) {
|
|
|
3183
3186
|
description: e.description,
|
|
3184
3187
|
guidance: e.guidance,
|
|
3185
3188
|
run(a) {
|
|
3186
|
-
const t = [], i = a.querySelectorAll(e.selector), n = e.filterTopLevel ? Array.from(i).filter((
|
|
3189
|
+
const t = [], i = a.querySelectorAll(e.selector), n = e.filterTopLevel ? Array.from(i).filter((o) => !o.closest(Xe)) : Array.from(i);
|
|
3187
3190
|
return n.length > 1 && n.slice(1).forEach(
|
|
3188
|
-
(
|
|
3191
|
+
(o) => t.push({
|
|
3189
3192
|
ruleId: e.id,
|
|
3190
|
-
selector: p(
|
|
3191
|
-
html: m(
|
|
3193
|
+
selector: p(o),
|
|
3194
|
+
html: m(o),
|
|
3192
3195
|
impact: "moderate",
|
|
3193
3196
|
message: `Page has multiple ${e.landmarkName} landmarks.`
|
|
3194
3197
|
})
|
|
@@ -3292,7 +3295,7 @@ const bi = {
|
|
|
3292
3295
|
fixability: "mechanical",
|
|
3293
3296
|
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.",
|
|
3294
3297
|
fix: { type: "remove-element" }
|
|
3295
|
-
}, yi = N(vi),
|
|
3298
|
+
}, yi = N(vi), wi = {
|
|
3296
3299
|
id: "navigable/document-title",
|
|
3297
3300
|
category: "navigable",
|
|
3298
3301
|
actRuleIds: ["2779a5"],
|
|
@@ -3306,13 +3309,13 @@ const bi = {
|
|
|
3306
3309
|
var t, i, n;
|
|
3307
3310
|
const a = e.querySelector("title");
|
|
3308
3311
|
if (!a || !((t = a.textContent) != null && t.trim())) {
|
|
3309
|
-
let
|
|
3310
|
-
const
|
|
3311
|
-
if ((i =
|
|
3312
|
-
|
|
3312
|
+
let o;
|
|
3313
|
+
const r = e.querySelector("h1");
|
|
3314
|
+
if ((i = r == null ? void 0 : r.textContent) != null && i.trim())
|
|
3315
|
+
o = `h1: "${r.textContent.trim().slice(0, 100)}"`;
|
|
3313
3316
|
else if (e.body) {
|
|
3314
3317
|
const s = ((n = e.body.textContent) == null ? void 0 : n.trim().replace(/\s+/g, " ")) || "";
|
|
3315
|
-
s && (
|
|
3318
|
+
s && (o = `Page text: "${s.slice(0, 150)}"`);
|
|
3316
3319
|
}
|
|
3317
3320
|
return [{
|
|
3318
3321
|
ruleId: "navigable/document-title",
|
|
@@ -3320,13 +3323,13 @@ const bi = {
|
|
|
3320
3323
|
html: "<html>",
|
|
3321
3324
|
impact: "serious",
|
|
3322
3325
|
message: a ? "Document <title> element is empty." : "Document is missing a <title> element.",
|
|
3323
|
-
context:
|
|
3326
|
+
context: o,
|
|
3324
3327
|
fix: { type: "add-element", tag: "title", parent: "head", textContent: "" }
|
|
3325
3328
|
}];
|
|
3326
3329
|
}
|
|
3327
3330
|
return [];
|
|
3328
3331
|
}
|
|
3329
|
-
},
|
|
3332
|
+
}, xi = {
|
|
3330
3333
|
id: "navigable/bypass",
|
|
3331
3334
|
category: "navigable",
|
|
3332
3335
|
actRuleIds: ["cf77f2"],
|
|
@@ -3342,10 +3345,10 @@ const bi = {
|
|
|
3342
3345
|
)) return [];
|
|
3343
3346
|
const t = e.querySelector('a[href^="#"]');
|
|
3344
3347
|
if (t) {
|
|
3345
|
-
const
|
|
3346
|
-
if (
|
|
3347
|
-
const
|
|
3348
|
-
if (e.getElementById(
|
|
3348
|
+
const o = t.getAttribute("href");
|
|
3349
|
+
if (o && o.length > 1) {
|
|
3350
|
+
const r = o.slice(1);
|
|
3351
|
+
if (e.getElementById(r)) return [];
|
|
3349
3352
|
}
|
|
3350
3353
|
}
|
|
3351
3354
|
if (e.querySelector("h1, h2, h3, [role='heading']")) return [];
|
|
@@ -3369,17 +3372,17 @@ const bi = {
|
|
|
3369
3372
|
description: "Page should contain a level-one heading.",
|
|
3370
3373
|
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 at least one level-one heading that describes the main content, typically matching or similar to the page title.",
|
|
3371
3374
|
run(e) {
|
|
3372
|
-
var
|
|
3375
|
+
var r, s, l;
|
|
3373
3376
|
const a = e.querySelector("h1");
|
|
3374
|
-
if (a &&
|
|
3377
|
+
if (a && x(a)) return [];
|
|
3375
3378
|
const t = e.querySelectorAll('[role="heading"][aria-level="1"]');
|
|
3376
3379
|
for (const d of t)
|
|
3377
|
-
if (
|
|
3378
|
-
const i = [], n = (s = (
|
|
3380
|
+
if (x(d)) return [];
|
|
3381
|
+
const i = [], n = (s = (r = e.querySelector("title")) == null ? void 0 : r.textContent) == null ? void 0 : s.trim();
|
|
3379
3382
|
n && i.push(`Page title: "${n}"`);
|
|
3380
|
-
const
|
|
3381
|
-
if (
|
|
3382
|
-
const d = ((l =
|
|
3383
|
+
const o = e.querySelector("main");
|
|
3384
|
+
if (o) {
|
|
3385
|
+
const d = ((l = o.textContent) == null ? void 0 : l.trim().replace(/\s+/g, " ")) || "";
|
|
3383
3386
|
d && i.push(`Main content: "${d.slice(0, 100)}"`);
|
|
3384
3387
|
}
|
|
3385
3388
|
return [{
|
|
@@ -3404,18 +3407,18 @@ const bi = {
|
|
|
3404
3407
|
run(e) {
|
|
3405
3408
|
const a = [], t = e.querySelectorAll("h1, h2, h3, h4, h5, h6, [role='heading']");
|
|
3406
3409
|
let i = 0, n = null;
|
|
3407
|
-
for (const
|
|
3408
|
-
if (h(
|
|
3409
|
-
let
|
|
3410
|
-
|
|
3410
|
+
for (const o of t) {
|
|
3411
|
+
if (h(o)) continue;
|
|
3412
|
+
let r;
|
|
3413
|
+
o.hasAttribute("aria-level") ? r = parseInt(o.getAttribute("aria-level"), 10) : r = parseInt(o.tagName[1], 10), i > 0 && r > i + 1 && a.push({
|
|
3411
3414
|
ruleId: "navigable/heading-order",
|
|
3412
|
-
selector: p(
|
|
3413
|
-
html: m(
|
|
3415
|
+
selector: p(o),
|
|
3416
|
+
html: m(o),
|
|
3414
3417
|
impact: "moderate",
|
|
3415
|
-
message: `Heading level ${
|
|
3418
|
+
message: `Heading level ${r} skipped from level ${i}. Use h${i + 1} instead.`,
|
|
3416
3419
|
context: n ? `Previous heading: ${m(n)}` : void 0,
|
|
3417
3420
|
fix: { type: "suggest", suggestion: `Change this heading to an h${i + 1} element to maintain proper heading hierarchy` }
|
|
3418
|
-
}), i =
|
|
3421
|
+
}), i = r, n = o;
|
|
3419
3422
|
}
|
|
3420
3423
|
return a;
|
|
3421
3424
|
}
|
|
@@ -3434,12 +3437,12 @@ const bi = {
|
|
|
3434
3437
|
var i;
|
|
3435
3438
|
const a = [], t = e.querySelectorAll('h1, h2, h3, h4, h5, h6, [role="heading"]');
|
|
3436
3439
|
for (const n of t)
|
|
3437
|
-
if (!h(n) && !
|
|
3438
|
-
let
|
|
3439
|
-
const
|
|
3440
|
-
if (
|
|
3441
|
-
const s = ((i =
|
|
3442
|
-
s && (
|
|
3440
|
+
if (!h(n) && !x(n)) {
|
|
3441
|
+
let o;
|
|
3442
|
+
const r = n.nextElementSibling;
|
|
3443
|
+
if (r) {
|
|
3444
|
+
const s = ((i = r.textContent) == null ? void 0 : i.trim().replace(/\s+/g, " ")) || "";
|
|
3445
|
+
s && (o = s.slice(0, 100));
|
|
3443
3446
|
}
|
|
3444
3447
|
a.push({
|
|
3445
3448
|
ruleId: "navigable/empty-heading",
|
|
@@ -3447,7 +3450,7 @@ const bi = {
|
|
|
3447
3450
|
html: m(n),
|
|
3448
3451
|
impact: "minor",
|
|
3449
3452
|
message: "Heading is empty. Add text content or remove the heading element.",
|
|
3450
|
-
context:
|
|
3453
|
+
context: o ? `Following content: "${o}"` : void 0,
|
|
3451
3454
|
fix: { type: "add-text-content" }
|
|
3452
3455
|
});
|
|
3453
3456
|
}
|
|
@@ -3468,8 +3471,8 @@ const bi = {
|
|
|
3468
3471
|
const a = [];
|
|
3469
3472
|
for (const n of e.querySelectorAll("p")) {
|
|
3470
3473
|
if (h(n)) continue;
|
|
3471
|
-
const
|
|
3472
|
-
if ((
|
|
3474
|
+
const o = n.getAttribute("style") || "", r = /font-weight\s*:\s*(bold|[6-9]00)/i.test(o), s = /font-size\s*:\s*(\d+)\s*(px|em|rem)/i.test(o), l = ((t = n.className) == null ? void 0 : t.toLowerCase()) || "", d = /\bh[1-6]\b|\bheading\b/.test(l), c = ((i = n.textContent) == null ? void 0 : i.trim()) || "", u = c.length > 0 && c.length < 50, b = !c.match(/[.!?,;:]$/);
|
|
3475
|
+
if ((r && s || r && d) && u && b) {
|
|
3473
3476
|
const v = n.nextElementSibling;
|
|
3474
3477
|
v && (v.tagName === "P" || v.tagName === "DIV" || v.tagName === "UL") && a.push({
|
|
3475
3478
|
ruleId: "navigable/p-as-heading",
|
|
@@ -3484,24 +3487,24 @@ const bi = {
|
|
|
3484
3487
|
return a;
|
|
3485
3488
|
}
|
|
3486
3489
|
};
|
|
3487
|
-
function
|
|
3488
|
-
var n,
|
|
3490
|
+
function qi(e) {
|
|
3491
|
+
var n, o;
|
|
3489
3492
|
const a = [], t = e.getAttribute("href");
|
|
3490
3493
|
t && a.push(`href: ${t}`);
|
|
3491
3494
|
const i = e.parentElement;
|
|
3492
3495
|
if (i) {
|
|
3493
|
-
const
|
|
3494
|
-
if ((n =
|
|
3495
|
-
a.push(`Nearby heading: ${
|
|
3496
|
+
const r = i.closest("h1, h2, h3, h4, h5, h6");
|
|
3497
|
+
if ((n = r == null ? void 0 : r.textContent) != null && n.trim())
|
|
3498
|
+
a.push(`Nearby heading: ${r.textContent.trim().slice(0, 80)}`);
|
|
3496
3499
|
else {
|
|
3497
|
-
const s = (
|
|
3500
|
+
const s = (o = i.textContent) == null ? void 0 : o.trim().slice(0, 100);
|
|
3498
3501
|
s && a.push(`Parent text: ${s}`);
|
|
3499
3502
|
}
|
|
3500
3503
|
}
|
|
3501
3504
|
return a.length > 0 ? a.join(`
|
|
3502
3505
|
`) : void 0;
|
|
3503
3506
|
}
|
|
3504
|
-
const
|
|
3507
|
+
const Ei = {
|
|
3505
3508
|
id: "navigable/link-name",
|
|
3506
3509
|
category: "navigable",
|
|
3507
3510
|
actRuleIds: ["c487ae"],
|
|
@@ -3514,14 +3517,14 @@ const qi = {
|
|
|
3514
3517
|
run(e) {
|
|
3515
3518
|
const a = [];
|
|
3516
3519
|
for (const t of e.querySelectorAll('a[href], area[href], [role="link"]')) {
|
|
3517
|
-
if (h(t) ||
|
|
3518
|
-
|
|
3520
|
+
if (h(t) || I(t) || t.getRootNode() instanceof ShadowRoot) continue;
|
|
3521
|
+
x(t) || a.push({
|
|
3519
3522
|
ruleId: "navigable/link-name",
|
|
3520
3523
|
selector: p(t),
|
|
3521
3524
|
html: m(t),
|
|
3522
3525
|
impact: "serious",
|
|
3523
3526
|
message: "Link has no discernible text.",
|
|
3524
|
-
context:
|
|
3527
|
+
context: qi(t),
|
|
3525
3528
|
fix: { type: "add-text-content" }
|
|
3526
3529
|
});
|
|
3527
3530
|
}
|
|
@@ -3541,8 +3544,8 @@ const qi = {
|
|
|
3541
3544
|
for (const i of t) {
|
|
3542
3545
|
const n = i.getAttribute("href");
|
|
3543
3546
|
if (!n || n === "#") continue;
|
|
3544
|
-
const
|
|
3545
|
-
if (!(
|
|
3547
|
+
const o = k(i).toLowerCase();
|
|
3548
|
+
if (!(o.includes("skip") || o.includes("jump") || o.includes("main content") || o.includes("navigation"))) continue;
|
|
3546
3549
|
const s = n.slice(1);
|
|
3547
3550
|
e.getElementById(s) || a.push({
|
|
3548
3551
|
ruleId: "navigable/skip-link",
|
|
@@ -3635,7 +3638,7 @@ const qi = {
|
|
|
3635
3638
|
}
|
|
3636
3639
|
return a;
|
|
3637
3640
|
}
|
|
3638
|
-
},
|
|
3641
|
+
}, Pi = {
|
|
3639
3642
|
id: "landmarks/complementary-is-top-level",
|
|
3640
3643
|
category: "landmarks",
|
|
3641
3644
|
wcag: [],
|
|
@@ -3658,7 +3661,7 @@ const qi = {
|
|
|
3658
3661
|
}
|
|
3659
3662
|
return a;
|
|
3660
3663
|
}
|
|
3661
|
-
},
|
|
3664
|
+
}, Di = {
|
|
3662
3665
|
id: "landmarks/landmark-unique",
|
|
3663
3666
|
category: "landmarks",
|
|
3664
3667
|
wcag: [],
|
|
@@ -3675,14 +3678,14 @@ const qi = {
|
|
|
3675
3678
|
{ selector: 'form[aria-label], form[aria-labelledby], [role="form"], [role="search"]', type: "form" }
|
|
3676
3679
|
];
|
|
3677
3680
|
for (const { selector: i, type: n } of t) {
|
|
3678
|
-
const
|
|
3679
|
-
if (
|
|
3680
|
-
const
|
|
3681
|
-
for (const s of
|
|
3682
|
-
const l =
|
|
3683
|
-
d.push(s),
|
|
3681
|
+
const o = Array.from(e.querySelectorAll(i)).filter((s) => !h(s));
|
|
3682
|
+
if (o.length <= 1) continue;
|
|
3683
|
+
const r = /* @__PURE__ */ new Map();
|
|
3684
|
+
for (const s of o) {
|
|
3685
|
+
const l = x(s).toLowerCase() || "", d = r.get(l) || [];
|
|
3686
|
+
d.push(s), r.set(l, d);
|
|
3684
3687
|
}
|
|
3685
|
-
for (const [s, l] of
|
|
3688
|
+
for (const [s, l] of r)
|
|
3686
3689
|
if (l.length > 1)
|
|
3687
3690
|
for (const d of l.slice(1))
|
|
3688
3691
|
a.push({
|
|
@@ -3710,8 +3713,8 @@ const qi = {
|
|
|
3710
3713
|
if (!t) return [];
|
|
3711
3714
|
for (const n of t.children) {
|
|
3712
3715
|
if (h(n) || n instanceof HTMLScriptElement || n instanceof HTMLStyleElement || n.tagName === "NOSCRIPT" || n instanceof HTMLElement && n.hidden || n.matches('a[href^="#"]')) continue;
|
|
3713
|
-
const
|
|
3714
|
-
!
|
|
3716
|
+
const o = n.matches(Re), r = (i = n.textContent) == null ? void 0 : i.trim();
|
|
3717
|
+
!o && r && (n.querySelector(Re) || a.push({
|
|
3715
3718
|
ruleId: "landmarks/region",
|
|
3716
3719
|
selector: p(n),
|
|
3717
3720
|
html: m(n),
|
|
@@ -3738,14 +3741,14 @@ const qi = {
|
|
|
3738
3741
|
if (!e.doctype && e.body) {
|
|
3739
3742
|
const n = e.body.children;
|
|
3740
3743
|
if (n.length > 0 && Array.from(n).every(
|
|
3741
|
-
(
|
|
3744
|
+
(o) => o.tagName.toLowerCase() === "svg" || o.tagName.toLowerCase() === "math"
|
|
3742
3745
|
)) return [];
|
|
3743
3746
|
}
|
|
3744
3747
|
if (!((t = a.getAttribute("lang")) != null && t.trim())) {
|
|
3745
3748
|
let n;
|
|
3746
3749
|
if (e.body) {
|
|
3747
|
-
const
|
|
3748
|
-
|
|
3750
|
+
const o = ((i = e.body.textContent) == null ? void 0 : i.trim().replace(/\s+/g, " ")) || "";
|
|
3751
|
+
o && (n = o.slice(0, 200));
|
|
3749
3752
|
}
|
|
3750
3753
|
return [{
|
|
3751
3754
|
ruleId: "readable/html-has-lang",
|
|
@@ -3759,15 +3762,15 @@ const qi = {
|
|
|
3759
3762
|
}
|
|
3760
3763
|
return [];
|
|
3761
3764
|
}
|
|
3762
|
-
},
|
|
3765
|
+
}, Wi = new Set(
|
|
3763
3766
|
"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(" ")
|
|
3764
|
-
),
|
|
3767
|
+
), ji = new Set(
|
|
3765
3768
|
"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(" ")
|
|
3766
3769
|
), Ui = /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i;
|
|
3767
3770
|
function Ke(e) {
|
|
3768
3771
|
if (!Ui.test(e)) return !1;
|
|
3769
3772
|
const a = e.split("-")[0].toLowerCase();
|
|
3770
|
-
return a.length === 2 ?
|
|
3773
|
+
return a.length === 2 ? Wi.has(a) : a.length === 3 ? !ji.has(a) : !1;
|
|
3771
3774
|
}
|
|
3772
3775
|
function Ce(e) {
|
|
3773
3776
|
var i;
|
|
@@ -3777,25 +3780,25 @@ function Ce(e) {
|
|
|
3777
3780
|
if (!t.data.trim()) continue;
|
|
3778
3781
|
const n = t.parentElement;
|
|
3779
3782
|
if (!n || n instanceof HTMLElement && (n.hidden || n.style.display === "none")) continue;
|
|
3780
|
-
let
|
|
3781
|
-
for (;
|
|
3782
|
-
if (
|
|
3783
|
-
|
|
3783
|
+
let o = n, r = !1;
|
|
3784
|
+
for (; o && o !== e; ) {
|
|
3785
|
+
if (o.hasAttribute("lang")) {
|
|
3786
|
+
r = !0;
|
|
3784
3787
|
break;
|
|
3785
3788
|
}
|
|
3786
|
-
|
|
3789
|
+
o = o.parentElement;
|
|
3787
3790
|
}
|
|
3788
|
-
if (!
|
|
3791
|
+
if (!r) return !0;
|
|
3789
3792
|
}
|
|
3790
3793
|
for (const n of e.querySelectorAll("img[alt]")) {
|
|
3791
3794
|
if (!((i = n.getAttribute("alt")) == null ? void 0 : i.trim())) continue;
|
|
3792
|
-
let
|
|
3793
|
-
for (;
|
|
3794
|
-
if (
|
|
3795
|
+
let r = n.parentElement, s = !1;
|
|
3796
|
+
for (; r && r !== e; ) {
|
|
3797
|
+
if (r.hasAttribute("lang")) {
|
|
3795
3798
|
s = !0;
|
|
3796
3799
|
break;
|
|
3797
3800
|
}
|
|
3798
|
-
|
|
3801
|
+
r = r.parentElement;
|
|
3799
3802
|
}
|
|
3800
3803
|
if (!s) return !0;
|
|
3801
3804
|
}
|
|
@@ -3867,11 +3870,11 @@ const Oi = {
|
|
|
3867
3870
|
description: "The lang and xml:lang attributes on <html> must match.",
|
|
3868
3871
|
guidance: "In XHTML documents, if both lang and xml:lang are present, they must specify the same base language. Mismatched values confuse assistive technologies. Either remove xml:lang (preferred for HTML5) or ensure both attributes have identical values.",
|
|
3869
3872
|
run(e) {
|
|
3870
|
-
var n,
|
|
3871
|
-
const a = e.documentElement, t = (n = a.getAttribute("lang")) == null ? void 0 : n.trim().toLowerCase(), i = (
|
|
3873
|
+
var n, o;
|
|
3874
|
+
const a = e.documentElement, t = (n = a.getAttribute("lang")) == null ? void 0 : n.trim().toLowerCase(), i = (o = a.getAttribute("xml:lang")) == null ? void 0 : o.trim().toLowerCase();
|
|
3872
3875
|
if (t && i) {
|
|
3873
|
-
const
|
|
3874
|
-
if (
|
|
3876
|
+
const r = t.split("-")[0], s = i.split("-")[0];
|
|
3877
|
+
if (r !== s)
|
|
3875
3878
|
return [{
|
|
3876
3879
|
ruleId: "readable/html-xml-lang-mismatch",
|
|
3877
3880
|
selector: "html",
|
|
@@ -3897,7 +3900,7 @@ const Oi = {
|
|
|
3897
3900
|
const a = [];
|
|
3898
3901
|
for (const t of e.querySelectorAll("iframe, frame")) {
|
|
3899
3902
|
if (h(t) || Ge(t)) continue;
|
|
3900
|
-
if (!
|
|
3903
|
+
if (!x(t)) {
|
|
3901
3904
|
const n = t.getAttribute("src");
|
|
3902
3905
|
a.push({
|
|
3903
3906
|
ruleId: "labels-and-names/frame-title",
|
|
@@ -3924,21 +3927,21 @@ const Oi = {
|
|
|
3924
3927
|
run(e) {
|
|
3925
3928
|
var n;
|
|
3926
3929
|
const a = [], t = Array.from(e.querySelectorAll("iframe[title], frame[title]")), i = /* @__PURE__ */ new Map();
|
|
3927
|
-
for (const
|
|
3928
|
-
if (h(
|
|
3929
|
-
const
|
|
3930
|
-
if (
|
|
3931
|
-
const s = i.get(
|
|
3932
|
-
s.push(
|
|
3930
|
+
for (const o of t) {
|
|
3931
|
+
if (h(o) || Ge(o)) continue;
|
|
3932
|
+
const r = (n = o.getAttribute("title")) == null ? void 0 : n.trim().toLowerCase();
|
|
3933
|
+
if (r) {
|
|
3934
|
+
const s = i.get(r) || [];
|
|
3935
|
+
s.push(o), i.set(r, s);
|
|
3933
3936
|
}
|
|
3934
3937
|
}
|
|
3935
|
-
for (const [,
|
|
3936
|
-
if (
|
|
3937
|
-
for (const
|
|
3938
|
+
for (const [, o] of i)
|
|
3939
|
+
if (o.length > 1)
|
|
3940
|
+
for (const r of o.slice(1))
|
|
3938
3941
|
a.push({
|
|
3939
3942
|
ruleId: "labels-and-names/frame-title-unique",
|
|
3940
|
-
selector: p(
|
|
3941
|
-
html: m(
|
|
3943
|
+
selector: p(r),
|
|
3944
|
+
html: m(r),
|
|
3942
3945
|
impact: "moderate",
|
|
3943
3946
|
message: "Frame title is not unique. Use a distinct title for each frame."
|
|
3944
3947
|
});
|
|
@@ -3994,10 +3997,10 @@ const Ji = [
|
|
|
3994
3997
|
"textbox"
|
|
3995
3998
|
]);
|
|
3996
3999
|
function Zi(e) {
|
|
3997
|
-
var
|
|
3998
|
-
const a = (
|
|
4000
|
+
var r, s, l, d;
|
|
4001
|
+
const a = (r = e.getAttribute("role")) == null ? void 0 : r.trim().toLowerCase();
|
|
3999
4002
|
if (a && Ki.has(a) || (e instanceof HTMLInputElement || e instanceof HTMLTextAreaElement) && !(a && Qi.has(a)))
|
|
4000
|
-
return
|
|
4003
|
+
return x(e);
|
|
4001
4004
|
const i = e.getAttribute("aria-labelledby");
|
|
4002
4005
|
if (i) {
|
|
4003
4006
|
const c = i.split(/\s+/).map((u) => {
|
|
@@ -4012,8 +4015,8 @@ function Zi(e) {
|
|
|
4012
4015
|
const c = Xi(e);
|
|
4013
4016
|
if (c) return c;
|
|
4014
4017
|
}
|
|
4015
|
-
const
|
|
4016
|
-
if (
|
|
4018
|
+
const o = (l = e.getAttribute("title")) == null ? void 0 : l.trim();
|
|
4019
|
+
if (o) return o;
|
|
4017
4020
|
if (e instanceof HTMLInputElement || e instanceof HTMLTextAreaElement) {
|
|
4018
4021
|
const c = (d = e.getAttribute("placeholder")) == null ? void 0 : d.trim();
|
|
4019
4022
|
if (c) return c;
|
|
@@ -4034,16 +4037,16 @@ const en = {
|
|
|
4034
4037
|
var i;
|
|
4035
4038
|
const a = [], t = e.querySelectorAll(`${Qe}, ${Ji}`);
|
|
4036
4039
|
for (const n of t) {
|
|
4037
|
-
if (h(n) ||
|
|
4038
|
-
const
|
|
4039
|
-
if (
|
|
4040
|
+
if (h(n) || I(n)) continue;
|
|
4041
|
+
const o = (i = n.getAttribute("role")) == null ? void 0 : i.trim().toLowerCase();
|
|
4042
|
+
if (o === "presentation" || o === "none") continue;
|
|
4040
4043
|
if (!Zi(n)) {
|
|
4041
4044
|
const s = [], l = n.tagName.toLowerCase(), d = n.getAttribute("type");
|
|
4042
4045
|
d && l === "input" && s.push(`type: ${d}`);
|
|
4043
4046
|
const c = n.getAttribute("name");
|
|
4044
4047
|
c && s.push(`name: "${c}"`);
|
|
4045
4048
|
const u = n.getAttribute("placeholder");
|
|
4046
|
-
u && s.push(`placeholder: "${u}"`),
|
|
4049
|
+
u && s.push(`placeholder: "${u}"`), o && s.push(`role: ${o}`);
|
|
4047
4050
|
const b = n.getAttribute("id");
|
|
4048
4051
|
b && s.push(`id: "${b}"`), a.push({
|
|
4049
4052
|
ruleId: "labels-and-names/form-label",
|
|
@@ -4072,15 +4075,15 @@ const en = {
|
|
|
4072
4075
|
for (const i of t) {
|
|
4073
4076
|
if (h(i) || !i.id) continue;
|
|
4074
4077
|
const n = e.querySelectorAll(`label[for="${CSS.escape(i.id)}"]`);
|
|
4075
|
-
let
|
|
4076
|
-
for (;
|
|
4077
|
-
if (
|
|
4078
|
-
|
|
4078
|
+
let o = 0, r = i.parentElement;
|
|
4079
|
+
for (; r; ) {
|
|
4080
|
+
if (r.tagName.toLowerCase() === "label" && !r.hasAttribute("for")) {
|
|
4081
|
+
o++;
|
|
4079
4082
|
break;
|
|
4080
4083
|
}
|
|
4081
|
-
|
|
4084
|
+
r = r.parentElement;
|
|
4082
4085
|
}
|
|
4083
|
-
const s = n.length +
|
|
4086
|
+
const s = n.length + o;
|
|
4084
4087
|
s > 1 && a.push({
|
|
4085
4088
|
ruleId: "labels-and-names/multiple-labels",
|
|
4086
4089
|
selector: p(i),
|
|
@@ -4107,9 +4110,9 @@ const en = {
|
|
|
4107
4110
|
for (const n of e.querySelectorAll(
|
|
4108
4111
|
'input[type="submit"], input[type="button"], input[type="reset"]'
|
|
4109
4112
|
)) {
|
|
4110
|
-
if (h(n) ||
|
|
4111
|
-
const
|
|
4112
|
-
!
|
|
4113
|
+
if (h(n) || I(n)) continue;
|
|
4114
|
+
const o = (t = n.getAttribute("value")) == null ? void 0 : t.trim(), r = (i = n.getAttribute("type")) == null ? void 0 : i.toLowerCase(), s = (r === "submit" || r === "reset") && !n.hasAttribute("value");
|
|
4115
|
+
!o && !s && !x(n) && a.push({
|
|
4113
4116
|
ruleId: "labels-and-names/input-button-name",
|
|
4114
4117
|
selector: p(n),
|
|
4115
4118
|
html: m(n),
|
|
@@ -4127,8 +4130,8 @@ function Te(e) {
|
|
|
4127
4130
|
function Ne(e, a) {
|
|
4128
4131
|
const t = Te(e), i = Te(a);
|
|
4129
4132
|
if (!t || !i || t.includes(i) || i.includes(t)) return !0;
|
|
4130
|
-
const n = i.split(/\s+/).map((
|
|
4131
|
-
return n.length >= 2 && n.filter((
|
|
4133
|
+
const n = i.split(/\s+/).map((o) => o.replace(/[.,;:!?\u2026]+$/g, "")).filter((o) => o.length > 2);
|
|
4134
|
+
return n.length >= 2 && n.filter((r) => t.includes(r)).length / n.length > 0.5;
|
|
4132
4135
|
}
|
|
4133
4136
|
const nn = {
|
|
4134
4137
|
id: "labels-and-names/label-content-mismatch",
|
|
@@ -4145,14 +4148,14 @@ const nn = {
|
|
|
4145
4148
|
const a = [];
|
|
4146
4149
|
for (const t of e.querySelectorAll('button, [role="button"], a[href], input[type="submit"], input[type="button"]')) {
|
|
4147
4150
|
if (h(t)) continue;
|
|
4148
|
-
const i =
|
|
4151
|
+
const i = x(t);
|
|
4149
4152
|
if (!i) continue;
|
|
4150
4153
|
let n = "";
|
|
4151
4154
|
t instanceof HTMLInputElement ? n = t.value || "" : n = ee(t);
|
|
4152
|
-
const
|
|
4153
|
-
if (!
|
|
4154
|
-
const
|
|
4155
|
-
!
|
|
4155
|
+
const o = n.trim();
|
|
4156
|
+
if (!o || o.length <= 2) continue;
|
|
4157
|
+
const r = t.hasAttribute("aria-label"), s = t.hasAttribute("aria-labelledby");
|
|
4158
|
+
!r && !s || Ne(i, n) || a.push({
|
|
4156
4159
|
ruleId: "labels-and-names/label-content-mismatch",
|
|
4157
4160
|
selector: p(t),
|
|
4158
4161
|
html: m(t),
|
|
@@ -4163,26 +4166,26 @@ const nn = {
|
|
|
4163
4166
|
}
|
|
4164
4167
|
for (const t of e.querySelectorAll("input, select, textarea")) {
|
|
4165
4168
|
if (h(t) || t instanceof HTMLInputElement && ["hidden", "submit", "button", "image"].includes(t.type)) continue;
|
|
4166
|
-
const i =
|
|
4169
|
+
const i = x(t);
|
|
4167
4170
|
if (!i || !t.hasAttribute("aria-label")) continue;
|
|
4168
|
-
const
|
|
4169
|
-
let
|
|
4170
|
-
if (
|
|
4171
|
-
const s = e.querySelector(`label[for="${CSS.escape(
|
|
4172
|
-
s && (
|
|
4171
|
+
const o = t.id;
|
|
4172
|
+
let r = "";
|
|
4173
|
+
if (o) {
|
|
4174
|
+
const s = e.querySelector(`label[for="${CSS.escape(o)}"]`);
|
|
4175
|
+
s && (r = ee(s));
|
|
4173
4176
|
}
|
|
4174
|
-
|
|
4177
|
+
r.trim() && (Ne(i, r) || a.push({
|
|
4175
4178
|
ruleId: "labels-and-names/label-content-mismatch",
|
|
4176
4179
|
selector: p(t),
|
|
4177
4180
|
html: m(t),
|
|
4178
4181
|
impact: "serious",
|
|
4179
|
-
message: `Accessible name "${i}" does not contain visible label "${
|
|
4182
|
+
message: `Accessible name "${i}" does not contain visible label "${r.trim()}".`,
|
|
4180
4183
|
fix: { type: "suggest", suggestion: "Update aria-label to include the visible label text so voice control users can activate this element by speaking its label" }
|
|
4181
4184
|
}));
|
|
4182
4185
|
}
|
|
4183
4186
|
return a;
|
|
4184
4187
|
}
|
|
4185
|
-
},
|
|
4188
|
+
}, on = {
|
|
4186
4189
|
id: "labels-and-names/label-title-only",
|
|
4187
4190
|
category: "labels-and-names",
|
|
4188
4191
|
wcag: ["4.1.2"],
|
|
@@ -4192,15 +4195,15 @@ const nn = {
|
|
|
4192
4195
|
description: "Form elements should not use title attribute as the only accessible name.",
|
|
4193
4196
|
guidance: "The title attribute is unreliable as a label because it only appears on hover/focus (not visible to touch users) and is often ignored by assistive technologies. Use a visible <label> element, aria-label, or aria-labelledby instead. Title can supplement a label but should not replace it.",
|
|
4194
4197
|
run(e) {
|
|
4195
|
-
var i, n,
|
|
4198
|
+
var i, n, o;
|
|
4196
4199
|
const a = [], t = e.querySelectorAll(Qe);
|
|
4197
|
-
for (const
|
|
4198
|
-
if (h(
|
|
4199
|
-
const s =
|
|
4200
|
+
for (const r of t) {
|
|
4201
|
+
if (h(r)) continue;
|
|
4202
|
+
const s = r.hasAttribute("title") && ((i = r.getAttribute("title")) == null ? void 0 : i.trim()), l = r.hasAttribute("aria-label") && ((n = r.getAttribute("aria-label")) == null ? void 0 : n.trim()), d = r.hasAttribute("aria-labelledby"), c = Yi(r), u = !!((o = c == null ? void 0 : c.textContent) != null && o.trim());
|
|
4200
4203
|
s && !l && !d && !u && a.push({
|
|
4201
4204
|
ruleId: "labels-and-names/label-title-only",
|
|
4202
|
-
selector: p(
|
|
4203
|
-
html: m(
|
|
4205
|
+
selector: p(r),
|
|
4206
|
+
html: m(r),
|
|
4204
4207
|
impact: "serious",
|
|
4205
4208
|
message: "Form element uses title attribute as only label. Use <label>, aria-label, or aria-labelledby instead.",
|
|
4206
4209
|
fix: { type: "suggest", suggestion: "Add a visible <label> element or aria-label attribute, and optionally keep the title as supplementary text" }
|
|
@@ -4208,7 +4211,7 @@ const nn = {
|
|
|
4208
4211
|
}
|
|
4209
4212
|
return a;
|
|
4210
4213
|
}
|
|
4211
|
-
},
|
|
4214
|
+
}, rn = {
|
|
4212
4215
|
id: "labels-and-names/aria-command-name",
|
|
4213
4216
|
category: "labels-and-names",
|
|
4214
4217
|
actRuleIds: ["m6b1q3"],
|
|
@@ -4221,12 +4224,12 @@ const nn = {
|
|
|
4221
4224
|
var t;
|
|
4222
4225
|
const a = [];
|
|
4223
4226
|
for (const i of e.querySelectorAll('[role="button"], [role="link"], [role="menuitem"]')) {
|
|
4224
|
-
if (h(i) ||
|
|
4227
|
+
if (h(i) || I(i) || se(i)) continue;
|
|
4225
4228
|
const n = i.getAttribute("role");
|
|
4226
4229
|
if ((i.tagName.toLowerCase() === "button" || i.tagName.toLowerCase() === "a") && n !== "menuitem") continue;
|
|
4227
|
-
if (!
|
|
4228
|
-
const
|
|
4229
|
-
if ((t =
|
|
4230
|
+
if (!x(i)) {
|
|
4231
|
+
const r = i.querySelector("img[alt]");
|
|
4232
|
+
if ((t = r == null ? void 0 : r.getAttribute("alt")) != null && t.trim()) continue;
|
|
4230
4233
|
a.push({
|
|
4231
4234
|
ruleId: "labels-and-names/aria-command-name",
|
|
4232
4235
|
selector: p(i),
|
|
@@ -4254,13 +4257,13 @@ function M(e) {
|
|
|
4254
4257
|
var i;
|
|
4255
4258
|
const t = [];
|
|
4256
4259
|
for (const n of a.querySelectorAll(e.selector)) {
|
|
4257
|
-
if (h(n) || e.checkComputedHidden &&
|
|
4260
|
+
if (h(n) || e.checkComputedHidden && I(n) || e.checkShadowDOM && se(n)) continue;
|
|
4258
4261
|
if (e.roleSet) {
|
|
4259
|
-
const
|
|
4260
|
-
if (!
|
|
4262
|
+
const r = (i = n.getAttribute("role")) == null ? void 0 : i.trim().toLowerCase();
|
|
4263
|
+
if (!r || !e.roleSet.has(r)) continue;
|
|
4261
4264
|
}
|
|
4262
4265
|
if (e.skipNative && n.matches(e.skipNative)) continue;
|
|
4263
|
-
|
|
4266
|
+
x(n) || t.push({
|
|
4264
4267
|
ruleId: e.id,
|
|
4265
4268
|
selector: p(n),
|
|
4266
4269
|
html: m(n),
|
|
@@ -4337,12 +4340,12 @@ const sn = M({
|
|
|
4337
4340
|
fix: { type: "add-text-content" }
|
|
4338
4341
|
});
|
|
4339
4342
|
function bn(e) {
|
|
4340
|
-
var
|
|
4343
|
+
var o, r, s;
|
|
4341
4344
|
const a = [], t = e.className;
|
|
4342
4345
|
t && typeof t == "string" && t.trim() && a.push(`Classes: ${t.trim().slice(0, 100)}`);
|
|
4343
4346
|
const i = e.closest("form");
|
|
4344
4347
|
if (i) {
|
|
4345
|
-
const l = i.getAttribute("aria-label") || ((
|
|
4348
|
+
const l = i.getAttribute("aria-label") || ((r = (o = i.querySelector("legend")) == null ? void 0 : o.textContent) == null ? void 0 : r.trim());
|
|
4346
4349
|
l && a.push(`Form: ${l.slice(0, 60)}`);
|
|
4347
4350
|
}
|
|
4348
4351
|
const n = e.parentElement;
|
|
@@ -4366,10 +4369,10 @@ const hn = {
|
|
|
4366
4369
|
run(e) {
|
|
4367
4370
|
const a = [];
|
|
4368
4371
|
for (const t of e.querySelectorAll('button, [role="button"]')) {
|
|
4369
|
-
if (h(t) ||
|
|
4372
|
+
if (h(t) || I(t)) continue;
|
|
4370
4373
|
const i = t.getAttribute("role");
|
|
4371
4374
|
if ((i === "none" || i === "presentation") && !(t.matches('button:not([disabled]), [tabindex]:not([tabindex="-1"])') || t.tagName.toLowerCase() === "button" && !t.disabled) || se(t)) continue;
|
|
4372
|
-
|
|
4375
|
+
x(t) || a.push({
|
|
4373
4376
|
ruleId: "labels-and-names/button-name",
|
|
4374
4377
|
selector: p(t),
|
|
4375
4378
|
html: m(t),
|
|
@@ -4394,7 +4397,7 @@ const hn = {
|
|
|
4394
4397
|
const a = [];
|
|
4395
4398
|
for (const t of e.querySelectorAll("details > summary:first-of-type")) {
|
|
4396
4399
|
if (h(t)) continue;
|
|
4397
|
-
|
|
4400
|
+
x(t) || a.push({
|
|
4398
4401
|
ruleId: "labels-and-names/summary-name",
|
|
4399
4402
|
selector: p(t),
|
|
4400
4403
|
html: m(t),
|
|
@@ -4405,14 +4408,14 @@ const hn = {
|
|
|
4405
4408
|
}
|
|
4406
4409
|
return a;
|
|
4407
4410
|
}
|
|
4408
|
-
},
|
|
4411
|
+
}, re = ["aria-labelledby", "aria-describedby", "aria-controls", "aria-owns", "aria-flowto"];
|
|
4409
4412
|
function fn(e) {
|
|
4410
4413
|
const a = /* @__PURE__ */ new Set();
|
|
4411
4414
|
for (const t of e.querySelectorAll("[aria-labelledby], [aria-describedby], [aria-controls], [aria-owns], [aria-flowto]"))
|
|
4412
|
-
for (const i of
|
|
4415
|
+
for (const i of re) {
|
|
4413
4416
|
const n = t.getAttribute(i);
|
|
4414
|
-
n && n.split(/\s+/).forEach((
|
|
4415
|
-
|
|
4417
|
+
n && n.split(/\s+/).forEach((o) => {
|
|
4418
|
+
o && a.add(o);
|
|
4416
4419
|
});
|
|
4417
4420
|
}
|
|
4418
4421
|
for (const t of e.querySelectorAll("label[for]")) {
|
|
@@ -4433,14 +4436,14 @@ const vn = {
|
|
|
4433
4436
|
const a = [], t = fn(e), i = /* @__PURE__ */ new Map();
|
|
4434
4437
|
for (const n of e.querySelectorAll("[id]"))
|
|
4435
4438
|
t.has(n.id) && (n instanceof HTMLElement && (n.style.display === "none" || n.style.visibility === "hidden" || n.hidden) || i.set(n.id, (i.get(n.id) ?? 0) + 1));
|
|
4436
|
-
for (const [n,
|
|
4437
|
-
if (
|
|
4438
|
-
const
|
|
4439
|
-
|
|
4439
|
+
for (const [n, o] of i) {
|
|
4440
|
+
if (o <= 1) continue;
|
|
4441
|
+
const r = e.querySelectorAll(`#${CSS.escape(n)}`), s = e.querySelector(
|
|
4442
|
+
re.map((c) => `[${c}~="${CSS.escape(n)}"]`).join(", ")
|
|
4440
4443
|
), l = e.querySelector(`label[for="${CSS.escape(n)}"]`);
|
|
4441
4444
|
let d;
|
|
4442
4445
|
if (s) {
|
|
4443
|
-
const c =
|
|
4446
|
+
const c = re.find(
|
|
4444
4447
|
(u) => {
|
|
4445
4448
|
var b;
|
|
4446
4449
|
return (b = s.getAttribute(u)) == null ? void 0 : b.split(/\s+/).includes(n);
|
|
@@ -4450,11 +4453,11 @@ const vn = {
|
|
|
4450
4453
|
} else l && (d = "label[for]");
|
|
4451
4454
|
a.push({
|
|
4452
4455
|
ruleId: "labels-and-names/duplicate-id-aria",
|
|
4453
|
-
selector: p(
|
|
4454
|
-
html: m(
|
|
4456
|
+
selector: p(r[1]),
|
|
4457
|
+
html: m(r[1]),
|
|
4455
4458
|
impact: "critical",
|
|
4456
4459
|
message: `Duplicate ID "${n}" referenced by ${d ?? "an accessibility attribute"}.`,
|
|
4457
|
-
context: `First element: ${m(
|
|
4460
|
+
context: `First element: ${m(r[0])}${d ? `
|
|
4458
4461
|
Referenced by: ${d}` : ""}`,
|
|
4459
4462
|
fix: { type: "suggest", suggestion: "Change the duplicate ID to a unique value so the ARIA or label reference points to the correct element" }
|
|
4460
4463
|
});
|
|
@@ -4462,6 +4465,49 @@ Referenced by: ${d}` : ""}`,
|
|
|
4462
4465
|
return a;
|
|
4463
4466
|
}
|
|
4464
4467
|
}, yn = {
|
|
4468
|
+
id: "input-assistance/accessible-authentication",
|
|
4469
|
+
category: "input-assistance",
|
|
4470
|
+
wcag: ["3.3.8"],
|
|
4471
|
+
level: "AA",
|
|
4472
|
+
fixability: "mechanical",
|
|
4473
|
+
description: 'Password inputs must not block password managers. Avoid autocomplete="off" and allow pasting.',
|
|
4474
|
+
guidance: 'WCAG 2.2 SC 3.3.8 requires that authentication steps either avoid cognitive function tests or provide a mechanism to assist users. Password managers are a key assistive mechanism. Setting autocomplete="off" on password fields prevents password managers from filling credentials. Blocking paste via onpaste attributes prevents users from pasting stored passwords. Set autocomplete to "current-password" for login forms or "new-password" for registration/change-password forms, and do not block paste on password fields.',
|
|
4475
|
+
run(e) {
|
|
4476
|
+
var t;
|
|
4477
|
+
const a = [];
|
|
4478
|
+
for (const i of e.querySelectorAll('input[type="password"]')) {
|
|
4479
|
+
if (h(i) || I(i) || i.disabled || i.getAttribute("aria-disabled") === "true") continue;
|
|
4480
|
+
if (((t = i.getAttribute("autocomplete")) == null ? void 0 : t.trim().toLowerCase()) === "off") {
|
|
4481
|
+
a.push({
|
|
4482
|
+
ruleId: "input-assistance/accessible-authentication",
|
|
4483
|
+
selector: p(i),
|
|
4484
|
+
html: m(i),
|
|
4485
|
+
impact: "critical",
|
|
4486
|
+
message: 'Password field has autocomplete="off" which blocks password managers.',
|
|
4487
|
+
fix: {
|
|
4488
|
+
type: "set-attribute",
|
|
4489
|
+
attribute: "autocomplete",
|
|
4490
|
+
value: "current-password"
|
|
4491
|
+
}
|
|
4492
|
+
});
|
|
4493
|
+
continue;
|
|
4494
|
+
}
|
|
4495
|
+
const o = i.getAttribute("onpaste");
|
|
4496
|
+
o && /return\s+false|preventDefault/.test(o) && a.push({
|
|
4497
|
+
ruleId: "input-assistance/accessible-authentication",
|
|
4498
|
+
selector: p(i),
|
|
4499
|
+
html: m(i),
|
|
4500
|
+
impact: "critical",
|
|
4501
|
+
message: "Password field blocks pasting, preventing password manager use.",
|
|
4502
|
+
fix: {
|
|
4503
|
+
type: "remove-attribute",
|
|
4504
|
+
attribute: "onpaste"
|
|
4505
|
+
}
|
|
4506
|
+
});
|
|
4507
|
+
}
|
|
4508
|
+
return a;
|
|
4509
|
+
}
|
|
4510
|
+
}, wn = {
|
|
4465
4511
|
id: "aria/aria-roles",
|
|
4466
4512
|
category: "aria",
|
|
4467
4513
|
actRuleIds: ["674b10"],
|
|
@@ -4473,13 +4519,13 @@ Referenced by: ${d}` : ""}`,
|
|
|
4473
4519
|
run(e) {
|
|
4474
4520
|
const a = [];
|
|
4475
4521
|
for (const t of e.querySelectorAll("[role]")) {
|
|
4476
|
-
const
|
|
4477
|
-
!
|
|
4522
|
+
const o = t.getAttribute("role").replace(/[\u201C\u201D\u2018\u2019\u00AB\u00BB]/g, "").split(/\s+/).filter(Boolean);
|
|
4523
|
+
!o.some((s) => dt(s)) && o.length > 0 && a.push({
|
|
4478
4524
|
ruleId: "aria/aria-roles",
|
|
4479
4525
|
selector: p(t),
|
|
4480
4526
|
html: m(t),
|
|
4481
4527
|
impact: "critical",
|
|
4482
|
-
message: `Invalid ARIA role "${
|
|
4528
|
+
message: `Invalid ARIA role "${o[0]}".`,
|
|
4483
4529
|
fix: { type: "remove-attribute", attribute: "role" }
|
|
4484
4530
|
});
|
|
4485
4531
|
}
|
|
@@ -4497,7 +4543,7 @@ Referenced by: ${d}` : ""}`,
|
|
|
4497
4543
|
run(e) {
|
|
4498
4544
|
return le(e).validAttr;
|
|
4499
4545
|
}
|
|
4500
|
-
},
|
|
4546
|
+
}, An = {
|
|
4501
4547
|
id: "aria/aria-valid-attr-value",
|
|
4502
4548
|
category: "aria",
|
|
4503
4549
|
actRuleIds: ["6a7281"],
|
|
@@ -4509,7 +4555,7 @@ Referenced by: ${d}` : ""}`,
|
|
|
4509
4555
|
run(e) {
|
|
4510
4556
|
return le(e).validAttrValue;
|
|
4511
4557
|
}
|
|
4512
|
-
},
|
|
4558
|
+
}, kn = {
|
|
4513
4559
|
checkbox: ["aria-checked"],
|
|
4514
4560
|
combobox: ["aria-expanded"],
|
|
4515
4561
|
heading: ["aria-level"],
|
|
@@ -4523,7 +4569,7 @@ Referenced by: ${d}` : ""}`,
|
|
|
4523
4569
|
slider: ["aria-valuenow"],
|
|
4524
4570
|
spinbutton: ["aria-valuenow"],
|
|
4525
4571
|
switch: ["aria-checked"]
|
|
4526
|
-
},
|
|
4572
|
+
}, Sn = {
|
|
4527
4573
|
id: "aria/aria-required-attr",
|
|
4528
4574
|
category: "aria",
|
|
4529
4575
|
actRuleIds: ["4e8ab6"],
|
|
@@ -4536,22 +4582,22 @@ Referenced by: ${d}` : ""}`,
|
|
|
4536
4582
|
const a = [];
|
|
4537
4583
|
for (const t of e.querySelectorAll("[role]")) {
|
|
4538
4584
|
if (h(t) || t instanceof HTMLElement && t.style.display === "none") continue;
|
|
4539
|
-
const i = t.getAttribute("role").trim().toLowerCase(), n =
|
|
4585
|
+
const i = t.getAttribute("role").trim().toLowerCase(), n = kn[i];
|
|
4540
4586
|
if (n && !(i === "checkbox" && t instanceof HTMLInputElement && t.type === "checkbox") && !(i === "radio" && t instanceof HTMLInputElement && t.type === "radio") && !(i === "option" && t instanceof HTMLOptionElement) && !(i === "heading" && /^h[1-6]$/i.test(t.tagName))) {
|
|
4541
4587
|
if (i === "separator") {
|
|
4542
|
-
const
|
|
4543
|
-
if (!
|
|
4588
|
+
const o = t.getAttribute("tabindex");
|
|
4589
|
+
if (!o || o === "-1") continue;
|
|
4544
4590
|
}
|
|
4545
4591
|
if (!(t.tagName.toLowerCase() === "hr" && !t.hasAttribute("role"))) {
|
|
4546
|
-
for (const
|
|
4547
|
-
if (!t.hasAttribute(
|
|
4592
|
+
for (const o of n)
|
|
4593
|
+
if (!t.hasAttribute(o)) {
|
|
4548
4594
|
a.push({
|
|
4549
4595
|
ruleId: "aria/aria-required-attr",
|
|
4550
4596
|
selector: p(t),
|
|
4551
4597
|
html: m(t),
|
|
4552
4598
|
impact: "critical",
|
|
4553
|
-
message: `Role "${i}" requires attribute "${
|
|
4554
|
-
fix: { type: "add-attribute", attribute:
|
|
4599
|
+
message: `Role "${i}" requires attribute "${o}".`,
|
|
4600
|
+
fix: { type: "add-attribute", attribute: o, value: "" }
|
|
4555
4601
|
});
|
|
4556
4602
|
break;
|
|
4557
4603
|
}
|
|
@@ -4560,7 +4606,7 @@ Referenced by: ${d}` : ""}`,
|
|
|
4560
4606
|
}
|
|
4561
4607
|
return a;
|
|
4562
4608
|
}
|
|
4563
|
-
},
|
|
4609
|
+
}, In = {
|
|
4564
4610
|
alert: /* @__PURE__ */ new Set(["aria-atomic", "aria-busy", "aria-live", "aria-relevant"]),
|
|
4565
4611
|
alertdialog: /* @__PURE__ */ new Set(["aria-describedby", "aria-modal"]),
|
|
4566
4612
|
application: /* @__PURE__ */ new Set(["aria-activedescendant", "aria-disabled", "aria-errormessage", "aria-expanded", "aria-haspopup", "aria-invalid"]),
|
|
@@ -4632,7 +4678,7 @@ Referenced by: ${d}` : ""}`,
|
|
|
4632
4678
|
tree: /* @__PURE__ */ new Set(["aria-activedescendant", "aria-disabled", "aria-errormessage", "aria-invalid", "aria-multiselectable", "aria-orientation", "aria-required"]),
|
|
4633
4679
|
treegrid: /* @__PURE__ */ new Set(["aria-activedescendant", "aria-colcount", "aria-disabled", "aria-errormessage", "aria-invalid", "aria-multiselectable", "aria-orientation", "aria-readonly", "aria-required", "aria-rowcount"]),
|
|
4634
4680
|
treeitem: /* @__PURE__ */ new Set(["aria-checked", "aria-disabled", "aria-expanded", "aria-haspopup", "aria-level", "aria-posinset", "aria-selected", "aria-setsize"])
|
|
4635
|
-
},
|
|
4681
|
+
}, qn = {
|
|
4636
4682
|
id: "aria/aria-allowed-attr",
|
|
4637
4683
|
category: "aria",
|
|
4638
4684
|
actRuleIds: ["5c01ea"],
|
|
@@ -4650,30 +4696,30 @@ Referenced by: ${d}` : ""}`,
|
|
|
4650
4696
|
let n = i.currentNode;
|
|
4651
4697
|
for (; n; ) {
|
|
4652
4698
|
if (n instanceof Element) {
|
|
4653
|
-
for (const
|
|
4654
|
-
if (
|
|
4699
|
+
for (const o of n.attributes)
|
|
4700
|
+
if (o.name.startsWith("aria-")) {
|
|
4655
4701
|
t.add(n);
|
|
4656
4702
|
break;
|
|
4657
4703
|
}
|
|
4658
4704
|
}
|
|
4659
4705
|
n = i.nextNode();
|
|
4660
4706
|
}
|
|
4661
|
-
for (const
|
|
4662
|
-
if (h(
|
|
4663
|
-
const
|
|
4664
|
-
if (!
|
|
4665
|
-
const s =
|
|
4707
|
+
for (const o of t) {
|
|
4708
|
+
if (h(o)) continue;
|
|
4709
|
+
const r = j(o);
|
|
4710
|
+
if (!r) continue;
|
|
4711
|
+
const s = In[r];
|
|
4666
4712
|
if (s)
|
|
4667
|
-
for (const l of
|
|
4713
|
+
for (const l of o.attributes) {
|
|
4668
4714
|
if (!l.name.startsWith("aria-") || ut.has(l.name) || s.has(l.name)) continue;
|
|
4669
4715
|
const d = s.size > 0 ? [...s].join(", ") : "none (only global ARIA attributes)";
|
|
4670
4716
|
a.push({
|
|
4671
4717
|
ruleId: "aria/aria-allowed-attr",
|
|
4672
|
-
selector: p(
|
|
4673
|
-
html: m(
|
|
4718
|
+
selector: p(o),
|
|
4719
|
+
html: m(o),
|
|
4674
4720
|
impact: "critical",
|
|
4675
|
-
message: `ARIA attribute "${l.name}" is not allowed on role "${
|
|
4676
|
-
context: `Attribute: ${l.name}="${l.value}", role: ${
|
|
4721
|
+
message: `ARIA attribute "${l.name}" is not allowed on role "${r}".`,
|
|
4722
|
+
context: `Attribute: ${l.name}="${l.value}", role: ${r}, allowed role-specific attributes: ${d}`,
|
|
4677
4723
|
fix: { type: "remove-attribute", attribute: l.name }
|
|
4678
4724
|
});
|
|
4679
4725
|
}
|
|
@@ -4695,7 +4741,7 @@ Referenced by: ${d}` : ""}`,
|
|
|
4695
4741
|
"template",
|
|
4696
4742
|
"title",
|
|
4697
4743
|
"track"
|
|
4698
|
-
]),
|
|
4744
|
+
]), P = {
|
|
4699
4745
|
a: /* @__PURE__ */ new Set(["button", "checkbox", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "switch", "tab", "treeitem", "link"]),
|
|
4700
4746
|
"a[href]": /* @__PURE__ */ new Set(["button", "checkbox", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "switch", "tab", "treeitem"]),
|
|
4701
4747
|
abbr: "any",
|
|
@@ -4751,6 +4797,7 @@ Referenced by: ${d}` : ""}`,
|
|
|
4751
4797
|
"input[type=checkbox]": /* @__PURE__ */ new Set(["button", "menuitemcheckbox", "option", "switch"]),
|
|
4752
4798
|
"input[type=image]": /* @__PURE__ */ new Set(["link", "menuitem", "menuitemcheckbox", "menuitemradio", "radio", "switch"]),
|
|
4753
4799
|
"input[type=radio]": /* @__PURE__ */ new Set(["menuitemradio"]),
|
|
4800
|
+
"input[type=search]": /* @__PURE__ */ new Set(["combobox", "searchbox"]),
|
|
4754
4801
|
"input[type=text]": /* @__PURE__ */ new Set(["combobox", "searchbox", "spinbutton"]),
|
|
4755
4802
|
ins: "any",
|
|
4756
4803
|
kbd: "any",
|
|
@@ -4802,22 +4849,22 @@ Referenced by: ${d}` : ""}`,
|
|
|
4802
4849
|
video: /* @__PURE__ */ new Set(["application"]),
|
|
4803
4850
|
wbr: /* @__PURE__ */ new Set(["none", "presentation"])
|
|
4804
4851
|
};
|
|
4805
|
-
function
|
|
4852
|
+
function Ln(e) {
|
|
4806
4853
|
var t;
|
|
4807
4854
|
const a = e.tagName.toLowerCase();
|
|
4808
4855
|
if (En.has(a))
|
|
4809
4856
|
return "none";
|
|
4810
4857
|
if (a === "a" && e.hasAttribute("href"))
|
|
4811
|
-
return
|
|
4858
|
+
return P["a[href]"];
|
|
4812
4859
|
if (a === "img" && e.getAttribute("alt") === "")
|
|
4813
|
-
return
|
|
4860
|
+
return P["img[alt='']"];
|
|
4814
4861
|
if (a === "input") {
|
|
4815
4862
|
const n = `input[type=${((t = e.getAttribute("type")) == null ? void 0 : t.toLowerCase()) || "text"}]`;
|
|
4816
|
-
return n in
|
|
4863
|
+
return n in P ? P[n] : "none";
|
|
4817
4864
|
}
|
|
4818
|
-
return
|
|
4865
|
+
return P[a] || "any";
|
|
4819
4866
|
}
|
|
4820
|
-
const
|
|
4867
|
+
const Rn = {
|
|
4821
4868
|
id: "aria/aria-allowed-role",
|
|
4822
4869
|
category: "aria",
|
|
4823
4870
|
wcag: ["4.1.2"],
|
|
@@ -4832,16 +4879,16 @@ const Ln = {
|
|
|
4832
4879
|
if (h(i)) continue;
|
|
4833
4880
|
const n = (t = i.getAttribute("role")) == null ? void 0 : t.trim().toLowerCase();
|
|
4834
4881
|
if (!n) continue;
|
|
4835
|
-
const
|
|
4836
|
-
if (
|
|
4837
|
-
const
|
|
4838
|
-
|
|
4882
|
+
const o = $e(i);
|
|
4883
|
+
if (o && n === o) continue;
|
|
4884
|
+
const r = Ln(i);
|
|
4885
|
+
r === "none" ? a.push({
|
|
4839
4886
|
ruleId: "aria/aria-allowed-role",
|
|
4840
4887
|
selector: p(i),
|
|
4841
4888
|
html: m(i),
|
|
4842
4889
|
impact: "minor",
|
|
4843
4890
|
message: `Element <${i.tagName.toLowerCase()}> should not have an explicit role.`
|
|
4844
|
-
}) :
|
|
4891
|
+
}) : r !== "any" && !r.has(n) && a.push({
|
|
4845
4892
|
ruleId: "aria/aria-allowed-role",
|
|
4846
4893
|
selector: p(i),
|
|
4847
4894
|
html: m(i),
|
|
@@ -4851,7 +4898,7 @@ const Ln = {
|
|
|
4851
4898
|
}
|
|
4852
4899
|
return a;
|
|
4853
4900
|
}
|
|
4854
|
-
},
|
|
4901
|
+
}, Cn = {
|
|
4855
4902
|
id: "aria/aria-hidden-body",
|
|
4856
4903
|
selector: 'body[aria-hidden="true"]',
|
|
4857
4904
|
check: { type: "selector-exists" },
|
|
@@ -4864,8 +4911,8 @@ const Ln = {
|
|
|
4864
4911
|
fixability: "mechanical",
|
|
4865
4912
|
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.",
|
|
4866
4913
|
skipAriaHidden: !1
|
|
4867
|
-
},
|
|
4868
|
-
function
|
|
4914
|
+
}, Tn = N(Cn);
|
|
4915
|
+
function Nn(e) {
|
|
4869
4916
|
let a = e;
|
|
4870
4917
|
const t = e.ownerDocument, i = t.defaultView;
|
|
4871
4918
|
for (; a && a !== t.body; ) {
|
|
@@ -4878,13 +4925,13 @@ function Tn(e) {
|
|
|
4878
4925
|
}
|
|
4879
4926
|
return !0;
|
|
4880
4927
|
}
|
|
4881
|
-
function
|
|
4928
|
+
function Mn(e) {
|
|
4882
4929
|
const a = e.ownerDocument.defaultView;
|
|
4883
4930
|
if (!a) return !1;
|
|
4884
4931
|
const t = a.getComputedStyle(e), i = t.position;
|
|
4885
4932
|
if (i !== "absolute" && i !== "fixed") return !1;
|
|
4886
|
-
const n = parseFloat(t.top),
|
|
4887
|
-
if (!(!isNaN(n) && n < -500 || !isNaN(
|
|
4933
|
+
const n = parseFloat(t.top), o = parseFloat(t.left);
|
|
4934
|
+
if (!(!isNaN(n) && n < -500 || !isNaN(o) && o < -500)) return !1;
|
|
4888
4935
|
const s = e.id;
|
|
4889
4936
|
if (!s) return !1;
|
|
4890
4937
|
const l = s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), d = new RegExp(
|
|
@@ -4896,7 +4943,7 @@ function Nn(e) {
|
|
|
4896
4943
|
}
|
|
4897
4944
|
return !1;
|
|
4898
4945
|
}
|
|
4899
|
-
const
|
|
4946
|
+
const $n = {
|
|
4900
4947
|
id: "aria/aria-hidden-focus",
|
|
4901
4948
|
category: "aria",
|
|
4902
4949
|
actRuleIds: ["6cfa84"],
|
|
@@ -4909,17 +4956,17 @@ const Mn = {
|
|
|
4909
4956
|
const a = [];
|
|
4910
4957
|
for (const t of e.querySelectorAll('[aria-hidden="true"]')) {
|
|
4911
4958
|
if (t === e.body) continue;
|
|
4912
|
-
const i = [...t.querySelectorAll(
|
|
4913
|
-
t.matches(
|
|
4959
|
+
const i = [...t.querySelectorAll(W)];
|
|
4960
|
+
t.matches(W) && i.push(t);
|
|
4914
4961
|
for (const n of i)
|
|
4915
4962
|
if (n instanceof HTMLElement) {
|
|
4916
|
-
const
|
|
4917
|
-
if (
|
|
4918
|
-
const
|
|
4919
|
-
if (/\.focus\s*\(/.test(
|
|
4963
|
+
const o = n.getAttribute("tabindex");
|
|
4964
|
+
if (o === "-1" || n.disabled || n instanceof HTMLInputElement && n.type === "hidden" || !Nn(n)) continue;
|
|
4965
|
+
const r = n.getAttribute("onfocus") || "";
|
|
4966
|
+
if (/\.focus\s*\(/.test(r) || Mn(n)) continue;
|
|
4920
4967
|
const s = n.tagName.toLowerCase();
|
|
4921
4968
|
let l;
|
|
4922
|
-
|
|
4969
|
+
o !== null ? l = `has tabindex="${o}"` : s === "a" && n.hasAttribute("href") ? l = "is a link with href" : s === "button" ? l = "is a <button>" : s === "input" ? l = `is an <input type="${n.type}">` : s === "select" ? l = "is a <select>" : s === "textarea" ? l = "is a <textarea>" : s === "iframe" ? l = "is an <iframe>" : l = `is a natively focusable <${s}>`;
|
|
4923
4970
|
const d = n === t ? n : n.closest('[aria-hidden="true"]');
|
|
4924
4971
|
a.push({
|
|
4925
4972
|
ruleId: "aria/aria-hidden-focus",
|
|
@@ -4934,7 +4981,7 @@ const Mn = {
|
|
|
4934
4981
|
}
|
|
4935
4982
|
return a;
|
|
4936
4983
|
}
|
|
4937
|
-
},
|
|
4984
|
+
}, Hn = {
|
|
4938
4985
|
id: "aria/aria-prohibited-attr",
|
|
4939
4986
|
category: "aria",
|
|
4940
4987
|
actRuleIds: ["kb1m8s"],
|
|
@@ -4946,7 +4993,7 @@ const Mn = {
|
|
|
4946
4993
|
run(e) {
|
|
4947
4994
|
return le(e).prohibitedAttr;
|
|
4948
4995
|
}
|
|
4949
|
-
},
|
|
4996
|
+
}, Pn = [
|
|
4950
4997
|
"a[href]",
|
|
4951
4998
|
"button:not([disabled])",
|
|
4952
4999
|
'input:not([disabled]):not([type="hidden"])',
|
|
@@ -4970,7 +5017,7 @@ const Mn = {
|
|
|
4970
5017
|
];
|
|
4971
5018
|
function Me(e) {
|
|
4972
5019
|
const a = [];
|
|
4973
|
-
e.matches(
|
|
5020
|
+
e.matches(Pn) && a.push("element is focusable");
|
|
4974
5021
|
for (const t of Dn)
|
|
4975
5022
|
if (e.hasAttribute(t)) {
|
|
4976
5023
|
a.push(`has ${t}`);
|
|
@@ -4978,7 +5025,7 @@ function Me(e) {
|
|
|
4978
5025
|
}
|
|
4979
5026
|
return (e.hasAttribute("aria-label") || e.hasAttribute("aria-labelledby")) && a.push("has accessible name"), a;
|
|
4980
5027
|
}
|
|
4981
|
-
const
|
|
5028
|
+
const Fn = {
|
|
4982
5029
|
id: "aria/presentation-role-conflict",
|
|
4983
5030
|
category: "aria",
|
|
4984
5031
|
actRuleIds: ["46ca7f"],
|
|
@@ -5015,7 +5062,7 @@ const Pn = {
|
|
|
5015
5062
|
}
|
|
5016
5063
|
return a;
|
|
5017
5064
|
}
|
|
5018
|
-
},
|
|
5065
|
+
}, zn = /* @__PURE__ */ new Set([
|
|
5019
5066
|
"button",
|
|
5020
5067
|
"checkbox",
|
|
5021
5068
|
"img",
|
|
@@ -5033,7 +5080,7 @@ const Pn = {
|
|
|
5033
5080
|
"spinbutton",
|
|
5034
5081
|
"switch",
|
|
5035
5082
|
"tab"
|
|
5036
|
-
]),
|
|
5083
|
+
]), Wn = {
|
|
5037
5084
|
id: "aria/presentational-children-focusable",
|
|
5038
5085
|
category: "aria",
|
|
5039
5086
|
actRuleIds: ["307n5z"],
|
|
@@ -5046,10 +5093,10 @@ const Pn = {
|
|
|
5046
5093
|
const a = [];
|
|
5047
5094
|
for (const t of e.querySelectorAll("*")) {
|
|
5048
5095
|
if (h(t)) continue;
|
|
5049
|
-
const i =
|
|
5050
|
-
if (!(!i || !
|
|
5051
|
-
for (const n of t.querySelectorAll(
|
|
5052
|
-
if (n !== t && !n.disabled) {
|
|
5096
|
+
const i = j(t);
|
|
5097
|
+
if (!(!i || !zn.has(i))) {
|
|
5098
|
+
for (const n of t.querySelectorAll(W))
|
|
5099
|
+
if (n !== t && !n.disabled && n.getAttribute("tabindex") !== "-1") {
|
|
5053
5100
|
a.push({
|
|
5054
5101
|
ruleId: "aria/presentational-children-focusable",
|
|
5055
5102
|
selector: p(n),
|
|
@@ -5065,7 +5112,7 @@ const Pn = {
|
|
|
5065
5112
|
}
|
|
5066
5113
|
}, Ze = [
|
|
5067
5114
|
// Text Alternatives
|
|
5068
|
-
|
|
5115
|
+
Wt,
|
|
5069
5116
|
Ut,
|
|
5070
5117
|
Ot,
|
|
5071
5118
|
Vt,
|
|
@@ -5085,17 +5132,17 @@ const Pn = {
|
|
|
5085
5132
|
ha,
|
|
5086
5133
|
va,
|
|
5087
5134
|
ya,
|
|
5088
|
-
xa,
|
|
5089
5135
|
wa,
|
|
5136
|
+
xa,
|
|
5090
5137
|
ka,
|
|
5091
5138
|
Sa,
|
|
5092
5139
|
Ia,
|
|
5093
5140
|
// Distinguishable
|
|
5094
|
-
|
|
5141
|
+
qa,
|
|
5095
5142
|
Ra,
|
|
5096
5143
|
Ca,
|
|
5097
5144
|
Ta,
|
|
5098
|
-
|
|
5145
|
+
Pa,
|
|
5099
5146
|
Ja,
|
|
5100
5147
|
Ka,
|
|
5101
5148
|
// Keyboard Accessible
|
|
@@ -5112,13 +5159,13 @@ const Pn = {
|
|
|
5112
5159
|
fi,
|
|
5113
5160
|
yi,
|
|
5114
5161
|
// Navigable
|
|
5115
|
-
xi,
|
|
5116
5162
|
wi,
|
|
5163
|
+
xi,
|
|
5117
5164
|
Ai,
|
|
5118
5165
|
ki,
|
|
5119
5166
|
Si,
|
|
5120
5167
|
Ii,
|
|
5121
|
-
|
|
5168
|
+
Ei,
|
|
5122
5169
|
Li,
|
|
5123
5170
|
// Landmarks
|
|
5124
5171
|
Ri,
|
|
@@ -5128,8 +5175,8 @@ const Pn = {
|
|
|
5128
5175
|
Mi,
|
|
5129
5176
|
$i,
|
|
5130
5177
|
Hi,
|
|
5131
|
-
Di,
|
|
5132
5178
|
Pi,
|
|
5179
|
+
Di,
|
|
5133
5180
|
Fi,
|
|
5134
5181
|
// Readable
|
|
5135
5182
|
zi,
|
|
@@ -5143,8 +5190,8 @@ const Pn = {
|
|
|
5143
5190
|
tn,
|
|
5144
5191
|
an,
|
|
5145
5192
|
nn,
|
|
5146
|
-
rn,
|
|
5147
5193
|
on,
|
|
5194
|
+
rn,
|
|
5148
5195
|
sn,
|
|
5149
5196
|
ln,
|
|
5150
5197
|
cn,
|
|
@@ -5155,21 +5202,23 @@ const Pn = {
|
|
|
5155
5202
|
hn,
|
|
5156
5203
|
gn,
|
|
5157
5204
|
vn,
|
|
5158
|
-
//
|
|
5205
|
+
// Input Assistance
|
|
5159
5206
|
yn,
|
|
5160
|
-
|
|
5207
|
+
// ARIA
|
|
5161
5208
|
wn,
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5209
|
+
xn,
|
|
5210
|
+
An,
|
|
5211
|
+
Sn,
|
|
5212
|
+
qn,
|
|
5213
|
+
Rn,
|
|
5214
|
+
Tn,
|
|
5167
5215
|
$n,
|
|
5168
|
-
|
|
5169
|
-
|
|
5216
|
+
Hn,
|
|
5217
|
+
Fn,
|
|
5218
|
+
Wn
|
|
5170
5219
|
];
|
|
5171
5220
|
let me = [], et = /* @__PURE__ */ new Set(), tt = !1, at = !1, T, z;
|
|
5172
|
-
function
|
|
5221
|
+
function Bn(e) {
|
|
5173
5222
|
e.additionalRules && (me = e.additionalRules), e.disabledRules && (et = new Set(e.disabledRules)), "includeAAA" in e && (tt = !!e.includeAAA), "componentMode" in e && (at = !!e.componentMode), "locale" in e && (T = e.locale || void 0), z = void 0;
|
|
5174
5223
|
}
|
|
5175
5224
|
function pe() {
|
|
@@ -5180,23 +5229,23 @@ function pe() {
|
|
|
5180
5229
|
}).concat(me);
|
|
5181
5230
|
return T ? (z = Ht(a, T), z) : a;
|
|
5182
5231
|
}
|
|
5183
|
-
function
|
|
5232
|
+
function _n(e) {
|
|
5184
5233
|
it();
|
|
5185
5234
|
const a = pe(), t = T, i = [], n = [];
|
|
5186
|
-
let
|
|
5235
|
+
let o = 0;
|
|
5187
5236
|
return {
|
|
5188
|
-
processChunk(
|
|
5237
|
+
processChunk(r) {
|
|
5189
5238
|
const s = performance.now();
|
|
5190
|
-
for (;
|
|
5191
|
-
const l = a[
|
|
5239
|
+
for (; o < a.length; ) {
|
|
5240
|
+
const l = a[o];
|
|
5192
5241
|
try {
|
|
5193
5242
|
i.push(...l.run(e));
|
|
5194
5243
|
} catch (d) {
|
|
5195
5244
|
n.push({ ruleId: l.id, error: d instanceof Error ? d.message : String(d) });
|
|
5196
5245
|
}
|
|
5197
|
-
if (
|
|
5246
|
+
if (o++, performance.now() - s >= r) break;
|
|
5198
5247
|
}
|
|
5199
|
-
return
|
|
5248
|
+
return o < a.length;
|
|
5200
5249
|
},
|
|
5201
5250
|
getViolations() {
|
|
5202
5251
|
return t ? ze(i, t) : i;
|
|
@@ -5207,17 +5256,17 @@ function Bn(e) {
|
|
|
5207
5256
|
};
|
|
5208
5257
|
}
|
|
5209
5258
|
function it() {
|
|
5210
|
-
mt(),
|
|
5259
|
+
mt(), rt(), st(), kt(), At(), pt();
|
|
5211
5260
|
}
|
|
5212
|
-
function
|
|
5261
|
+
function Gn(e) {
|
|
5213
5262
|
var n;
|
|
5214
5263
|
it();
|
|
5215
5264
|
const a = pe(), t = [], i = [];
|
|
5216
|
-
for (const
|
|
5265
|
+
for (const o of a)
|
|
5217
5266
|
try {
|
|
5218
|
-
t.push(...
|
|
5219
|
-
} catch (
|
|
5220
|
-
i.push({ ruleId:
|
|
5267
|
+
t.push(...o.run(e));
|
|
5268
|
+
} catch (r) {
|
|
5269
|
+
i.push({ ruleId: o.id, error: r instanceof Error ? r.message : String(r) });
|
|
5221
5270
|
}
|
|
5222
5271
|
return {
|
|
5223
5272
|
url: ((n = e.location) == null ? void 0 : n.href) ?? "",
|
|
@@ -5227,29 +5276,29 @@ function _n(e) {
|
|
|
5227
5276
|
skippedRules: i
|
|
5228
5277
|
};
|
|
5229
5278
|
}
|
|
5230
|
-
function
|
|
5279
|
+
function Yn(e, a) {
|
|
5231
5280
|
const t = (l) => `${l.ruleId}\0${l.selector}`, i = /* @__PURE__ */ new Map();
|
|
5232
5281
|
for (const l of e.violations)
|
|
5233
5282
|
i.set(t(l), l);
|
|
5234
5283
|
const n = /* @__PURE__ */ new Map();
|
|
5235
5284
|
for (const l of a.violations)
|
|
5236
5285
|
n.set(t(l), l);
|
|
5237
|
-
const
|
|
5286
|
+
const o = [], r = [];
|
|
5238
5287
|
for (const [l, d] of n)
|
|
5239
|
-
i.has(l) ?
|
|
5288
|
+
i.has(l) ? r.push(d) : o.push(d);
|
|
5240
5289
|
const s = [];
|
|
5241
5290
|
for (const [l, d] of i)
|
|
5242
5291
|
n.has(l) || s.push(d);
|
|
5243
|
-
return { added:
|
|
5292
|
+
return { added: o, fixed: s, unchanged: r };
|
|
5244
5293
|
}
|
|
5245
5294
|
const jn = new Map(Ze.map((e) => [e.id, e]));
|
|
5246
|
-
function
|
|
5295
|
+
function Xn(e) {
|
|
5247
5296
|
if (T)
|
|
5248
5297
|
return pe().find((i) => i.id === e);
|
|
5249
5298
|
const a = jn.get(e);
|
|
5250
5299
|
return a || me.find((t) => t.id === e);
|
|
5251
5300
|
}
|
|
5252
|
-
const
|
|
5301
|
+
const Jn = {
|
|
5253
5302
|
"navigable/document-title": { description: "Documents must have a <title> element to provide users with an overview of content.", 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').", messages: { "Document <title> element is empty.": "Document <title> element is empty.", "Document is missing a <title> element.": "Document is missing a <title> element." } },
|
|
5254
5303
|
"navigable/bypass": { description: "Page must have a mechanism to bypass repeated blocks of content.", 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.', messages: { "Page has no mechanism to bypass repeated content. Add a <main> landmark or skip link.": "Page has no mechanism to bypass repeated content. Add a <main> landmark or skip link." } },
|
|
5255
5304
|
"navigable/page-has-heading-one": { description: "Page should contain a level-one heading.", 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 at least one level-one heading that describes the main content, typically matching or similar to the page title.", messages: { "Page does not contain a level-one heading.": "Page does not contain a level-one heading." } },
|
|
@@ -5263,7 +5312,7 @@ const Xn = {
|
|
|
5263
5312
|
"text-alternatives/svg-img-alt": { description: "SVG elements with an img, graphics-document, or graphics-symbol role must have an accessible name via a <title> element, aria-label, or aria-labelledby.", guidance: "Inline SVGs with role='img' need accessible names. Add a <title> element as the first child of the SVG (screen readers will announce it), or use aria-label on the SVG element. For complex SVGs, use aria-labelledby referencing both a <title> and <desc> element. Decorative SVGs should use aria-hidden='true' instead.", messages: { "{0} with role='{1}' has no accessible name.": "{0} with role='{1}' has no accessible name." } },
|
|
5264
5313
|
"text-alternatives/input-image-alt": { description: 'Image inputs (<input type="image">) must have alternate text describing the button action.', guidance: "Image buttons (<input type='image'>) act as submit buttons with a custom image. Add alt text via alt, aria-label, or aria-labelledby that describes the action (e.g. alt='Search' or alt='Submit order'), not the image itself. Without it, screen readers announce only 'image' or the filename, giving no clue what the button does.", messages: { "Image input missing alt text.": "Image input missing alt text." } },
|
|
5265
5314
|
"text-alternatives/image-redundant-alt": { 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.", 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.", messages: { 'Alt text "{0}" duplicates surrounding {1} text.': 'Alt text "{0}" duplicates surrounding {1} text.' } },
|
|
5266
|
-
"text-alternatives/image-alt-words": { description: "Image alt text should not
|
|
5315
|
+
"text-alternatives/image-alt-words": { description: "Image alt text should not start with words like 'image of', 'photo of', or 'picture of' — screen readers already announce the element type.", 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'.", messages: { 'Alt text "{0}" contains redundant word(s): {1}.': 'Alt text "{0}" contains redundant word(s): {1}.' } },
|
|
5267
5316
|
"text-alternatives/area-alt": { description: "Image map <area> elements must have alternative text.", guidance: "Each clickable region in an image map needs alternative text so screen reader users know what the region represents. Add an alt attribute to every <area> element describing its purpose. For complex image maps, consider using alternative approaches like SVG with embedded links, or a list of text links.", messages: { "Image map <area> element is missing alternative text.": "Image map <area> element is missing alternative text." } },
|
|
5268
5317
|
"text-alternatives/object-alt": { description: "<object> elements must have alternative text.", guidance: "Object elements embed external content that may not be accessible to all users. Provide alternative text via aria-label, aria-labelledby, or a title attribute. The fallback content inside <object> is only shown when the object fails to load and does not serve as an accessible name.", messages: { "<object> element is missing alternative text. Add aria-label, aria-labelledby, or a title attribute.": "<object> element is missing alternative text. Add aria-label, aria-labelledby, or a title attribute." } },
|
|
5269
5318
|
"text-alternatives/role-img-alt": { description: "Elements with role='img' must have an accessible name.", guidance: "When you assign role='img' to an element (like a div containing icon fonts or CSS backgrounds), you must provide an accessible name via aria-label or aria-labelledby. Without this, screen reader users have no way to understand what the image represents. If the image is decorative, use role='presentation' or role='none' instead.", messages: { "Element with role='img' has no accessible name. Add aria-label or aria-labelledby.": "Element with role='img' has no accessible name. Add aria-label or aria-labelledby." } },
|
|
@@ -5341,8 +5390,9 @@ const Xn = {
|
|
|
5341
5390
|
"distinguishable/word-spacing": { description: "Word spacing set with !important in style attributes must be at least 0.16em.", guidance: "WCAG 1.4.12 requires users to be able to override text spacing. Using !important on word-spacing with a value below 0.16em prevents this. Either increase the value to at least 0.16em or remove !important.", messages: { "Word spacing {0}em with !important is below the 0.16em minimum.": "Word spacing {0}em with !important is below the 0.16em minimum." } },
|
|
5342
5391
|
"adaptable/orientation-lock": { description: "Page orientation must not be restricted using CSS transforms.", guidance: "Users with motor disabilities may mount their device in a fixed orientation. Using CSS transforms with @media (orientation: portrait/landscape) to rotate content 90° effectively locks the page to one orientation. Remove the orientation-dependent transform and use responsive design instead.", messages: { "CSS locks page orientation via @media (orientation: {0}) with a 90° transform.": "CSS locks page orientation via @media (orientation: {0}) with a 90° transform." } },
|
|
5343
5392
|
"aria/presentational-children-focusable": { description: "Elements with a role that makes children presentational must not contain focusable content.", guidance: "Roles like button, checkbox, img, tab, and others make their children presentational — hidden from assistive technologies. If those children are focusable, keyboard users can reach elements that screen reader users cannot perceive. Move focusable content outside the parent or remove the focusability.", messages: { 'Focusable element inside a "{0}" role whose children are presentational.': 'Focusable element inside a "{0}" role whose children are presentational.' } },
|
|
5344
|
-
"keyboard-accessible/focus-visible": { description: "Elements in sequential focus order must have a visible focus indicator.", guidance: "Keyboard users need to see which element has focus. Do not remove the default focus outline (outline: none) without providing an alternative visible indicator. Use :focus-visible or :focus styles to ensure focus is always perceivable.", messages: { "Focusable element has outline removed without a visible focus alternative.": "Focusable element has outline removed without a visible focus alternative." } }
|
|
5345
|
-
|
|
5393
|
+
"keyboard-accessible/focus-visible": { description: "Elements in sequential focus order must have a visible focus indicator.", guidance: "Keyboard users need to see which element has focus. Do not remove the default focus outline (outline: none) without providing an alternative visible indicator. Use :focus-visible or :focus styles to ensure focus is always perceivable.", messages: { "Focusable element has outline removed without a visible focus alternative.": "Focusable element has outline removed without a visible focus alternative." } },
|
|
5394
|
+
"input-assistance/accessible-authentication": { description: 'Password inputs must not block password managers. Avoid autocomplete="off" and allow pasting.', guidance: 'WCAG 2.2 SC 3.3.8 requires that authentication steps either avoid cognitive function tests or provide a mechanism to assist users. Password managers are a key assistive mechanism. Setting autocomplete="off" on password fields prevents password managers from filling credentials. Blocking paste via onpaste attributes prevents users from pasting stored passwords. Set autocomplete to "current-password" for login forms or "new-password" for registration/change-password forms, and do not block paste on password fields.', messages: { 'Password field has autocomplete="off" which blocks password managers.': 'Password field has autocomplete="off" which blocks password managers.', "Password field blocks pasting, preventing password manager use.": "Password field blocks pasting, preventing password manager use." } }
|
|
5395
|
+
}, Kn = {
|
|
5346
5396
|
"navigable/document-title": { description: "Los documentos deben tener un elemento <title> para proporcionar a los usuarios una vista general del contenido.", guidance: "Los usuarios de lectores de pantalla dependen de los títulos de página para identificar y navegar entre pestañas/ventanas. Agregue un elemento <title> descriptivo en <head> que resuma el propósito de la página. Mantenga los títulos únicos en todo el sitio, colocando el contenido específico antes del nombre del sitio (por ejemplo, 'Contáctenos - Acme Corp').", messages: { "Document <title> element is empty.": "El elemento <title> del documento está vacío.", "Document is missing a <title> element.": "Al documento le falta un elemento <title>." } },
|
|
5347
5397
|
"navigable/bypass": { description: "La página debe tener un mecanismo para omitir bloques de contenido repetidos.", guidance: 'Los usuarios de teclado deben poder omitir contenido repetitivo como la navegación. Proporcione un enlace de salto en la parte superior de la página que enlace al contenido principal (por ejemplo, <a href="#main">Saltar al contenido principal</a>), o use un landmark <main>. Los lectores de pantalla pueden saltar directamente a los landmarks, por lo que un elemento <main> correctamente marcado satisface este requisito.', messages: { "Page has no mechanism to bypass repeated content. Add a <main> landmark or skip link.": "La página no tiene un mecanismo para omitir contenido repetido. Agregue un landmark <main> o un enlace de salto." } },
|
|
5348
5398
|
"navigable/page-has-heading-one": { description: "La página debe contener un encabezado de nivel uno.", guidance: "Un encabezado de nivel uno (<h1> o role='heading' con aria-level='1') ayuda a los usuarios a comprender el tema de la página y proporciona un punto de referencia para la navegación con lector de pantalla. Cada página debe tener exactamente un h1 que describa el contenido principal, típicamente coincidiendo o similar al título de la página.", messages: { "Page does not contain a level-one heading.": "La página no contiene un encabezado de nivel uno." } },
|
|
@@ -5356,7 +5406,7 @@ const Xn = {
|
|
|
5356
5406
|
"text-alternatives/svg-img-alt": { description: "Los elementos SVG con rol img, graphics-document o graphics-symbol deben tener un nombre accesible mediante un elemento <title>, aria-label o aria-labelledby.", guidance: "Los SVG en línea con role='img' necesitan nombres accesibles. Agregue un elemento <title> como primer hijo del SVG (los lectores de pantalla lo anunciarán), o use aria-label en el elemento SVG. Para SVGs complejos, use aria-labelledby haciendo referencia tanto a un elemento <title> como a un elemento <desc>. Los SVGs decorativos deben usar aria-hidden='true' en su lugar.", messages: { "{0} with role='{1}' has no accessible name.": "{0} con role='{1}' no tiene nombre accesible." } },
|
|
5357
5407
|
"text-alternatives/input-image-alt": { description: 'Las entradas de imagen (<input type="image">) deben tener texto alternativo mediante alt, aria-label o aria-labelledby. El texto debe describir la acción del botón, no la imagen.', guidance: "Los botones de imagen (<input type='image'>) deben tener texto alternativo mediante alt, aria-label o aria-labelledby. El texto debe describir la acción del botón, no la imagen.", messages: { "Image input missing alt text.": "A la entrada de imagen le falta texto alt." } },
|
|
5358
5408
|
"text-alternatives/image-redundant-alt": { description: "El texto alternativo de la imagen no debe duplicar el texto del enlace o botón adyacente. Cuando el texto alt repite el texto circundante, los usuarios de lectores de pantalla escuchan la misma información dos veces.", guidance: "Cuando una imagen está dentro de un enlace o botón que también tiene texto, haga que el texto alt sea complementario en lugar de idéntico. Si la imagen es puramente decorativa en ese contexto, use alt='' para evitar la repetición.", messages: { 'Alt text "{0}" duplicates surrounding {1} text.': 'El texto alt "{0}" duplica el texto del {1} circundante.' } },
|
|
5359
|
-
"text-alternatives/image-alt-words": { description: "El texto alternativo de la imagen no debe
|
|
5409
|
+
"text-alternatives/image-alt-words": { description: "El texto alternativo de la imagen no debe comenzar con palabras como 'imagen de', 'foto de' o 'fotografía de': los lectores de pantalla ya anuncian el tipo de elemento.", guidance: "Los lectores de pantalla ya anuncian 'imagen' o 'gráfico' antes de leer el texto alt, por lo que frases como 'imagen de', 'foto de' o 'fotografía de' son redundantes. Elimine estas palabras y describa lo que muestra la imagen. Por ejemplo, cambie 'imagen de un perro' a 'golden retriever jugando a buscar'.", messages: { 'Alt text "{0}" contains redundant word(s): {1}.': 'El texto alt "{0}" contiene palabra(s) redundante(s): {1}.' } },
|
|
5360
5410
|
"text-alternatives/area-alt": { description: "Los elementos <area> del mapa de imagen deben tener texto alternativo.", guidance: "Cada región clicable en un mapa de imagen necesita texto alternativo para que los usuarios de lectores de pantalla sepan qué representa la región. Agregue un atributo alt a cada elemento <area> describiendo su propósito. Para mapas de imagen complejos, considere usar enfoques alternativos como SVG con enlaces incrustados, o una lista de enlaces de texto.", messages: { "Image map <area> element is missing alternative text.": "Al elemento <area> del mapa de imagen le falta texto alternativo." } },
|
|
5361
5411
|
"text-alternatives/object-alt": { description: "Los elementos <object> deben tener texto alternativo.", guidance: "Los elementos object incrustan contenido externo que puede no ser accesible para todos los usuarios. Proporcione texto alternativo mediante aria-label, aria-labelledby o un atributo title. El contenido de respaldo dentro de <object> solo se muestra cuando el objeto no se carga y no sirve como nombre accesible.", messages: { "<object> element is missing alternative text. Add aria-label, aria-labelledby, or a title attribute.": "Al elemento <object> le falta texto alternativo. Agregue aria-label, aria-labelledby o un atributo title." } },
|
|
5362
5412
|
"text-alternatives/role-img-alt": { description: "Los elementos con role='img' deben tener un nombre accesible.", guidance: "Cuando asigna role='img' a un elemento (como un div que contiene fuentes de iconos o fondos CSS), debe proporcionar un nombre accesible mediante aria-label o aria-labelledby. Sin esto, los usuarios de lectores de pantalla no tienen forma de entender lo que representa la imagen. Si la imagen es decorativa, use role='presentation' o role='none' en su lugar.", messages: { "Element with role='img' has no accessible name. Add aria-label or aria-labelledby.": "El elemento con role='img' no tiene nombre accesible. Agregue aria-label o aria-labelledby." } },
|
|
@@ -5434,34 +5484,35 @@ const Xn = {
|
|
|
5434
5484
|
"distinguishable/word-spacing": { description: "El espaciado de palabras establecido con !important en atributos de estilo debe ser al menos 0.16em.", guidance: "WCAG 1.4.12 requiere que los usuarios puedan anular el espaciado de texto. Usar !important en word-spacing con un valor inferior a 0.16em lo impide. Aumente el valor a al menos 0.16em o elimine !important.", messages: { "Word spacing {0}em with !important is below the 0.16em minimum.": "El espaciado de palabras {0}em con !important está por debajo del mínimo de 0.16em." } },
|
|
5435
5485
|
"adaptable/orientation-lock": { description: "La orientación de la página no debe restringirse usando transformaciones CSS.", guidance: "Los usuarios con discapacidades motoras pueden montar su dispositivo en una orientación fija. Usar transformaciones CSS con @media (orientation: portrait/landscape) para rotar el contenido 90° bloquea efectivamente la página a una orientación. Elimine la transformación dependiente de la orientación y use diseño responsivo en su lugar.", messages: { "CSS locks page orientation via @media (orientation: {0}) with a 90° transform.": "CSS bloquea la orientación de la página mediante @media (orientation: {0}) con una transformación de 90°." } },
|
|
5436
5486
|
"aria/presentational-children-focusable": { description: "Los elementos con un rol que hace a los hijos presentacionales no deben contener contenido enfocable.", guidance: "Roles como button, checkbox, img, tab y otros hacen que sus hijos sean presentacionales — ocultos de las tecnologías de asistencia. Si esos hijos son enfocables, los usuarios de teclado pueden alcanzar elementos que los usuarios de lectores de pantalla no pueden percibir. Mueva el contenido enfocable fuera del padre o elimine la enfocabilidad.", messages: { 'Focusable element inside a "{0}" role whose children are presentational.': 'Elemento enfocable dentro de un rol "{0}" cuyos hijos son presentacionales.' } },
|
|
5437
|
-
"keyboard-accessible/focus-visible": { description: "Los elementos en orden de foco secuencial deben tener un indicador de foco visible.", guidance: "Los usuarios de teclado necesitan ver qué elemento tiene el foco. No elimine el contorno de foco predeterminado (outline: none) sin proporcionar un indicador visible alternativo. Use estilos :focus-visible o :focus para asegurar que el foco siempre sea perceptible.", messages: { "Focusable element has outline removed without a visible focus alternative.": "El elemento enfocable tiene el contorno eliminado sin una alternativa de foco visible." } }
|
|
5487
|
+
"keyboard-accessible/focus-visible": { description: "Los elementos en orden de foco secuencial deben tener un indicador de foco visible.", guidance: "Los usuarios de teclado necesitan ver qué elemento tiene el foco. No elimine el contorno de foco predeterminado (outline: none) sin proporcionar un indicador visible alternativo. Use estilos :focus-visible o :focus para asegurar que el foco siempre sea perceptible.", messages: { "Focusable element has outline removed without a visible focus alternative.": "El elemento enfocable tiene el contorno eliminado sin una alternativa de foco visible." } },
|
|
5488
|
+
"input-assistance/accessible-authentication": { description: 'Los campos de contraseña no deben bloquear los administradores de contraseñas. Evite autocomplete="off" y permita pegar.', guidance: 'WCAG 2.2 SC 3.3.8 requiere que los pasos de autenticación eviten pruebas de función cognitiva o proporcionen un mecanismo para asistir a los usuarios. Los administradores de contraseñas son un mecanismo de asistencia clave. Establecer autocomplete="off" en campos de contraseña impide que los administradores de contraseñas completen las credenciales. Bloquear el pegado mediante atributos onpaste impide que los usuarios peguen contraseñas almacenadas. Establezca autocomplete en "current-password" para formularios de inicio de sesión o "new-password" para formularios de registro/cambio de contraseña, y no bloquee el pegado en campos de contraseña.', messages: { 'Password field has autocomplete="off" which blocks password managers.': 'El campo de contraseña tiene autocomplete="off" lo cual bloquea los administradores de contraseñas.', "Password field blocks pasting, preventing password manager use.": "El campo de contraseña bloquea el pegado, impidiendo el uso de administradores de contraseñas." } }
|
|
5438
5489
|
};
|
|
5439
5490
|
export {
|
|
5440
5491
|
it as clearAllCaches,
|
|
5441
5492
|
At as clearAriaAttrAuditCache,
|
|
5442
5493
|
mt as clearAriaHiddenCache,
|
|
5443
5494
|
kt as clearColorCaches,
|
|
5444
|
-
|
|
5495
|
+
rt as clearComputedRoleCache,
|
|
5445
5496
|
N as compileDeclarativeRule,
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5497
|
+
Bn as configureRules,
|
|
5498
|
+
_n as createChunkedAudit,
|
|
5499
|
+
Yn as diffAudit,
|
|
5500
|
+
x as getAccessibleName,
|
|
5450
5501
|
k as getAccessibleTextContent,
|
|
5451
5502
|
pe as getActiveRules,
|
|
5452
|
-
|
|
5503
|
+
j as getComputedRole,
|
|
5453
5504
|
m as getHtmlSnippet,
|
|
5454
5505
|
$e as getImplicitRole,
|
|
5455
|
-
|
|
5506
|
+
Xn as getRuleById,
|
|
5456
5507
|
p as getSelector,
|
|
5457
5508
|
h as isAriaHidden,
|
|
5458
5509
|
dt as isValidRole,
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5510
|
+
Jn as localeEn,
|
|
5511
|
+
Kn as localeEs,
|
|
5512
|
+
Un as querySelectorShadowAware,
|
|
5513
|
+
On as registerLocale,
|
|
5463
5514
|
Ze as rules,
|
|
5464
|
-
|
|
5515
|
+
Gn as runAudit,
|
|
5465
5516
|
ze as translateViolations,
|
|
5466
|
-
|
|
5517
|
+
Vn as validateDeclarativeRule
|
|
5467
5518
|
};
|