@accesslint/core 0.1.2 → 0.2.0

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