ultra11y 5.42.0 → 5.42.1

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.
@@ -10,7 +10,7 @@
10
10
  "name": "ultra11y",
11
11
  "source": "./",
12
12
  "description": "Automatic accessibility review before commit, push and pull request, plus detailed evidenced Markdown, HTML and per-page WCAG 2.2 AA / RGAA reports in Claude Code.",
13
- "version": "5.42.0",
13
+ "version": "5.42.1",
14
14
  "author": { "name": "maxgfr" },
15
15
  "homepage": "https://github.com/maxgfr/ultra11y",
16
16
  "repository": "https://github.com/maxgfr/ultra11y",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ultra11y",
3
3
  "description": "Accessibility for WCAG 2.2 AA and country standards (RGAA…): automatic review before commit, push and pull request, plus detailed evidenced Markdown, HTML and per-page conformance reports in interactive agent sessions.",
4
- "version": "5.42.0",
4
+ "version": "5.42.1",
5
5
  "author": { "name": "maxgfr" },
6
6
  "homepage": "https://github.com/maxgfr/ultra11y",
7
7
  "repository": "https://github.com/maxgfr/ultra11y",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ultra11y",
3
3
  "description": "Accessibility for WCAG 2.2 AA and country standards (RGAA…): automatic review before commit, push and pull request, plus detailed evidenced Markdown, HTML and per-page conformance reports in interactive agent sessions.",
4
- "version": "5.42.0",
4
+ "version": "5.42.1",
5
5
  "author": { "name": "maxgfr", "url": "https://github.com/maxgfr" },
6
6
  "homepage": "https://github.com/maxgfr/ultra11y",
7
7
  "repository": "https://github.com/maxgfr/ultra11y",
@@ -27,7 +27,7 @@ import { fileURLToPath } from "node:url";
27
27
  // Ownership marker: `ultra11y install --opencode` refuses to overwrite a plugin file that
28
28
  // does not carry it, so a user's own ultra11y.js is never clobbered.
29
29
  const ULTRA11Y_OPENCODE_PLUGIN = "ULTRA11Y_OPENCODE_PLUGIN";
30
- const ULTRA11Y_PLUGIN_VERSION = "5.42.0";
30
+ const ULTRA11Y_PLUGIN_VERSION = "5.42.1";
31
31
 
32
32
  const here = dirname(fileURLToPath(import.meta.url));
33
33
 
@@ -1,4 +1,4 @@
1
- import { S as SnapshotPayload, F as FindingLike } from './payload-Bb1uQH1q.js';
1
+ import { S as SnapshotPayload, F as FindingLike } from './payload-BMFQTm5s.js';
2
2
 
3
3
  type On = (event: string, handler: any) => void;
4
4
  interface TaskPayload extends SnapshotPayload {
package/dist/cypress.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CheckOptions } from './payload-Bb1uQH1q.js';
2
- export { s as slugify } from './payload-Bb1uQH1q.js';
1
+ import { C as CheckOptions } from './payload-BMFQTm5s.js';
2
+ export { s as slugify } from './payload-BMFQTm5s.js';
3
3
 
4
4
  interface CypressCheckOptions extends CheckOptions {
5
5
  /** Capture a viewport screenshot so the pixel tier can run. On by default — the plugin
@@ -80,7 +80,10 @@ interface CheckOptions {
80
80
  * for nothing but recording the sample and asserts nothing afterwards. `{ clicks: true }`
81
81
  * additionally presses `button[type=button]` (destructive-sounding names skipped, navigation
82
82
  * aborts the pass) — never the default on an authenticated session, where a server mutation
83
- * is invisible to any check this side of the network. */
83
+ * is invisible to any check this side of the network.
84
+ *
85
+ * PLAYWRIGHT ONLY, like `probes` beside it: the Cypress integration records a page and runs
86
+ * no live probe at all, so both are inert there. Stated rather than left to be discovered. */
84
87
  liveRegion?: boolean | {
85
88
  clicks?: boolean;
86
89
  };
@@ -1,4 +1,4 @@
1
- import { C as CheckOptions, A as AuditLike } from './payload-Bb1uQH1q.js';
1
+ import { C as CheckOptions, A as AuditLike } from './payload-BMFQTm5s.js';
2
2
 
3
3
  interface PlaywrightPage {
4
4
  evaluate(script: string): Promise<unknown>;
@@ -133,6 +133,7 @@ var COLLECT_SNAPSHOT = `(() => {
133
133
  })()`;
134
134
 
135
135
  // src/probes.ts
136
+ var PROBES_VERSION = 2;
136
137
  var PRELUDE = `
137
138
  const __sel = (e) => {
138
139
  if (!e || !e.tagName) return '\u2014';
@@ -240,8 +241,18 @@ function focusSetupExpr(scope = "", maxFocusables = PROBE_DEFAULTS.maxFocusables
240
241
  // from it is not merely unmeasured -- it is silently cleared. A page whose only control is a
241
242
  // <summary> tagged nothing at all, so the count was zero, so the ring was "vacuously whole",
242
243
  // so 2.4.7 and 2.4.11 closed without a single Tab press.
244
+ //
245
+ // AND NOT iframe / audio[controls] / video[controls], which were here for one release and
246
+ // had to come back out. They are genuinely focusable, but their focus lives in another
247
+ // document: everything below reads the PARENT'S activeElement, which stays the host element
248
+ // press after press while the user tabs through the controls inside. The trap walk reads
249
+ // exactly that as a cage, so an ordinary page with a video player, a payment frame, a map or
250
+ // a support widget was reported as a bloquant 2.1.2 -- a blocker manufactured out of our own
251
+ // blindness, able to fail somebody else's gate. The measurement we cannot make is not a
252
+ // finding; Tab still crosses them, the walk still records that it crossed something it never
253
+ // measured, and the page is not cleared either.
243
254
  // (No backticks in this comment: it lives inside a template literal.)
244
- const sel = 'a[href],area[href],button:not([disabled]),input:not([type=hidden]):not([disabled]),select:not([disabled]),textarea:not([disabled]),summary,iframe,audio[controls],video[controls],[contenteditable]:not([contenteditable="false"]),[tabindex]:not([tabindex="-1"]),[role=button]:not([disabled])';
255
+ const sel = 'a[href],area[href],button:not([disabled]),input:not([type=hidden]):not([disabled]),select:not([disabled]),textarea:not([disabled]),summary,[contenteditable]:not([contenteditable="false"]),[tabindex]:not([tabindex="-1"]),[role=button]:not([disabled])';
245
256
  // A BOX THAT IS ANIMATING CANNOT BE COMPARED ACROSS TIME, so it contributes a constant.
246
257
  //
247
258
  // The snapshot is taken before Tab and re-read after it, and the properties compared include
@@ -587,6 +598,7 @@ async function runLiveProbes(page, opts = {}) {
587
598
  const size = canResize ? page.viewportSize() ?? null : null;
588
599
  const restore = size ?? { width: 1280, height: 900 };
589
600
  const out = {
601
+ v: PROBES_VERSION,
590
602
  focusVisible: [],
591
603
  hover: [],
592
604
  keyboardTrap: [],
@@ -703,6 +715,12 @@ async function runLiveProbes(page, opts = {}) {
703
715
  else skip("4.1.3", r.why ?? "the live-region pass did not exercise the whole page");
704
716
  }
705
717
  }
718
+ for (const [bucket, sc] of UNREADABLE_BY_OLDER) {
719
+ if (out[bucket]?.length) {
720
+ const at = out.probed.indexOf(sc);
721
+ if (at >= 0) out.probed.splice(at, 1);
722
+ }
723
+ }
706
724
  return out;
707
725
  }
708
726
  var DESTRUCTIVE_NAME_RE = "\\b(supprim|retir|effac|envoy|valid|confirm|pay|achet|command|delete|remove|eras|clear|send|submit|buy|order)";
@@ -856,6 +874,11 @@ var REMOVE_TEXT_SPACING_STEP = `(() => {
856
874
  }
857
875
  return true;
858
876
  })()`;
877
+ var UNREADABLE_BY_OLDER = [
878
+ ["focusObscured", "2.4.11"],
879
+ ["keyboardTrap", "2.1.2"],
880
+ ["liveRegion", "4.1.3"]
881
+ ];
859
882
 
860
883
  // src/integrations/core.ts
861
884
  import { spawnSync } from "child_process";
@@ -1055,9 +1078,13 @@ async function checkA11y(page, opts = {}) {
1055
1078
  );
1056
1079
  }
1057
1080
  let probes;
1058
- if (opts.probes) {
1081
+ if (opts.probes || opts.liveRegion) {
1059
1082
  try {
1060
- probes = await runLiveProbes(page, { ...probeOptions(opts.probes), ...opts.liveRegion ? { liveRegion: opts.liveRegion } : {} });
1083
+ probes = await runLiveProbes(page, {
1084
+ ...probeOptions(opts.probes),
1085
+ ...opts.probes ? {} : { only: ["4.1.3"] },
1086
+ ...opts.liveRegion ? { liveRegion: opts.liveRegion } : {}
1087
+ });
1061
1088
  } catch (e) {
1062
1089
  console.warn(
1063
1090
  `ultra11y: the live probes failed on this page \u2014 ${e instanceof Error ? e.message : String(e)}. The snapshot was still recorded; the criteria they decide stay to assess.`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultra11y",
3
- "version": "5.42.0",
3
+ "version": "5.42.1",
4
4
  "description": "Audit HTML/CSS/JSX against WCAG 2.2 AA and produce a dated compliance report, or author/review accessible markup (native-HTML-first). A skills.sh agent skill: an install-free static engine (bundled, no npm install) plus the agent's judgment, with check/verify gates against hallucinated non-conformities, and pluggable in-repo standards packs (RGAA France first; Section 508 & EN 301 549 next).",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.33.0",