ultra11y 5.18.0 → 5.18.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 of the code under change before every commit, push and pull request, plus full WCAG 2.2 AA / RGAA audits and conformance deliverables on demand.",
13
- "version": "5.18.0",
13
+ "version": "5.18.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…): an automatic review of the code under change before every commit, push and pull request, plus full audits and conformance deliverables on demand.",
4
- "version": "5.18.0",
4
+ "version": "5.18.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…): an automatic review of the code under change before every commit, push and pull request, plus full audits and conformance deliverables on demand.",
4
- "version": "5.18.0",
4
+ "version": "5.18.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.18.0";
30
+ const ULTRA11Y_PLUGIN_VERSION = "5.18.1";
31
31
 
32
32
  const here = dirname(fileURLToPath(import.meta.url));
33
33
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultra11y",
3
- "version": "5.18.0",
3
+ "version": "5.18.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",
@@ -6,7 +6,7 @@ import { join as join51, relative as relative5, resolve as resolve16, sep as sep
6
6
  import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL3 } from "url";
7
7
 
8
8
  // src/types.ts
9
- var VERSION = "5.18.0";
9
+ var VERSION = "5.18.1";
10
10
  var SCHEMA_VERSION = 2;
11
11
  var INAPPLICABLE_STATUS = "C";
12
12
 
@@ -60370,6 +60370,7 @@ async function runScanManyLocal(urls, opts) {
60370
60370
  const browser = await launchChromium(chromium);
60371
60371
  const findings = [];
60372
60372
  const snapshots = [];
60373
+ const redirected = [];
60373
60374
  try {
60374
60375
  for (const url of urls) {
60375
60376
  const out2 = await runOnPage(browser, AxeBuilder, url, false, {
@@ -60379,6 +60380,17 @@ async function runScanManyLocal(urls, opts) {
60379
60380
  lang,
60380
60381
  snapshot: Boolean(opts.snapshotRoot)
60381
60382
  });
60383
+ if (out2.httpStatus !== void 0 && out2.httpStatus >= 400) {
60384
+ redirected.push({
60385
+ id: slugifyPageId(url),
60386
+ name: url,
60387
+ requested: url,
60388
+ landed: out2.landedUrl ?? out2.url,
60389
+ reason: "http-status",
60390
+ status: out2.httpStatus
60391
+ });
60392
+ continue;
60393
+ }
60382
60394
  findings.push(...toDynamicResult(out2, url, lang, LOCAL_ENGINE).findings);
60383
60395
  const id = opts.snapshotRoot ? writeRunnerSnapshot(opts.snapshotRoot, out2, url) : void 0;
60384
60396
  if (id) snapshots.push(id);
@@ -60393,7 +60405,8 @@ async function runScanManyLocal(urls, opts) {
60393
60405
  date: today(),
60394
60406
  findings,
60395
60407
  testedScs: localTestedScs(interact),
60396
- ...snapshots.length ? { snapshots } : {}
60408
+ ...snapshots.length ? { snapshots } : {},
60409
+ ...redirected.length ? { redirected } : {}
60397
60410
  };
60398
60411
  }
60399
60412
  async function runSampleScanLocal(pages, opts) {
@@ -5,7 +5,7 @@ when_to_use: "Invoke WITHOUT being asked whenever changed front-end code should
5
5
  allowed-tools: Bash(node ${CLAUDE_SKILL_DIR}/scripts/ultra11y.mjs *), Read, Grep, Glob
6
6
  license: MIT
7
7
  metadata:
8
- version: 5.18.0
8
+ version: 5.18.1
9
9
  ---
10
10
 
11
11
  # review-a11y — accessibility review of changed code
@@ -6,7 +6,7 @@ import { join as join51, relative as relative5, resolve as resolve16, sep as sep
6
6
  import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL3 } from "url";
7
7
 
8
8
  // src/types.ts
9
- var VERSION = "5.18.0";
9
+ var VERSION = "5.18.1";
10
10
  var SCHEMA_VERSION = 2;
11
11
  var INAPPLICABLE_STATUS = "C";
12
12
 
@@ -60370,6 +60370,7 @@ async function runScanManyLocal(urls, opts) {
60370
60370
  const browser = await launchChromium(chromium);
60371
60371
  const findings = [];
60372
60372
  const snapshots = [];
60373
+ const redirected = [];
60373
60374
  try {
60374
60375
  for (const url of urls) {
60375
60376
  const out2 = await runOnPage(browser, AxeBuilder, url, false, {
@@ -60379,6 +60380,17 @@ async function runScanManyLocal(urls, opts) {
60379
60380
  lang,
60380
60381
  snapshot: Boolean(opts.snapshotRoot)
60381
60382
  });
60383
+ if (out2.httpStatus !== void 0 && out2.httpStatus >= 400) {
60384
+ redirected.push({
60385
+ id: slugifyPageId(url),
60386
+ name: url,
60387
+ requested: url,
60388
+ landed: out2.landedUrl ?? out2.url,
60389
+ reason: "http-status",
60390
+ status: out2.httpStatus
60391
+ });
60392
+ continue;
60393
+ }
60382
60394
  findings.push(...toDynamicResult(out2, url, lang, LOCAL_ENGINE).findings);
60383
60395
  const id = opts.snapshotRoot ? writeRunnerSnapshot(opts.snapshotRoot, out2, url) : void 0;
60384
60396
  if (id) snapshots.push(id);
@@ -60393,7 +60405,8 @@ async function runScanManyLocal(urls, opts) {
60393
60405
  date: today(),
60394
60406
  findings,
60395
60407
  testedScs: localTestedScs(interact),
60396
- ...snapshots.length ? { snapshots } : {}
60408
+ ...snapshots.length ? { snapshots } : {},
60409
+ ...redirected.length ? { redirected } : {}
60397
60410
  };
60398
60411
  }
60399
60412
  async function runSampleScanLocal(pages, opts) {
@@ -4,7 +4,7 @@ description: "Use to AUDIT existing HTML/CSS/JSX against WCAG 2.2 AA accessibili
4
4
  when_to_use: "Invoke when the user asks for an accessibility AUDIT or a formal deliverable: audit a repo, site or page against WCAG 2.2 AA or a country standard (RGAA, Section 508, EN 301 549); produce a dated conformance report, a criterion grid, a PRD backlog, or tickets (GitHub/GitLab/Jira); author accessible markup from scratch; wire the repo gate (init --hook/--ci) or a rendered-DOM capture pipeline. For a review of the code UNDER CHANGE (diff, branch, PR), use the `review-a11y` skill instead."
5
5
  license: MIT
6
6
  metadata:
7
- version: 5.18.0
7
+ version: 5.18.1
8
8
  ---
9
9
 
10
10
  # ultra11y — audit WCAG 2.2 AA and write accessible markup
@@ -6,7 +6,7 @@ import { join as join51, relative as relative5, resolve as resolve16, sep as sep
6
6
  import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL3 } from "url";
7
7
 
8
8
  // src/types.ts
9
- var VERSION = "5.18.0";
9
+ var VERSION = "5.18.1";
10
10
  var SCHEMA_VERSION = 2;
11
11
  var INAPPLICABLE_STATUS = "C";
12
12
 
@@ -60370,6 +60370,7 @@ async function runScanManyLocal(urls, opts) {
60370
60370
  const browser = await launchChromium(chromium);
60371
60371
  const findings = [];
60372
60372
  const snapshots = [];
60373
+ const redirected = [];
60373
60374
  try {
60374
60375
  for (const url of urls) {
60375
60376
  const out2 = await runOnPage(browser, AxeBuilder, url, false, {
@@ -60379,6 +60380,17 @@ async function runScanManyLocal(urls, opts) {
60379
60380
  lang,
60380
60381
  snapshot: Boolean(opts.snapshotRoot)
60381
60382
  });
60383
+ if (out2.httpStatus !== void 0 && out2.httpStatus >= 400) {
60384
+ redirected.push({
60385
+ id: slugifyPageId(url),
60386
+ name: url,
60387
+ requested: url,
60388
+ landed: out2.landedUrl ?? out2.url,
60389
+ reason: "http-status",
60390
+ status: out2.httpStatus
60391
+ });
60392
+ continue;
60393
+ }
60382
60394
  findings.push(...toDynamicResult(out2, url, lang, LOCAL_ENGINE).findings);
60383
60395
  const id = opts.snapshotRoot ? writeRunnerSnapshot(opts.snapshotRoot, out2, url) : void 0;
60384
60396
  if (id) snapshots.push(id);
@@ -60393,7 +60405,8 @@ async function runScanManyLocal(urls, opts) {
60393
60405
  date: today(),
60394
60406
  findings,
60395
60407
  testedScs: localTestedScs(interact),
60396
- ...snapshots.length ? { snapshots } : {}
60408
+ ...snapshots.length ? { snapshots } : {},
60409
+ ...redirected.length ? { redirected } : {}
60397
60410
  };
60398
60411
  }
60399
60412
  async function runSampleScanLocal(pages, opts) {
package/src/scan-local.ts CHANGED
@@ -32,7 +32,7 @@ import {
32
32
  TEXT_SPACING_PROBE,
33
33
  } from "./probes.js";
34
34
  import { sampleScope } from "./sample.js";
35
- import { COLLECT_SNAPSHOT, type CollectedPage } from "./snapshot.js";
35
+ import { COLLECT_SNAPSHOT, type CollectedPage, slugifyPageId } from "./snapshot.js";
36
36
  import { today } from "./util.js";
37
37
 
38
38
  export const LOCAL_ENGINE = "axe-core@playwright (local)";
@@ -784,6 +784,7 @@ export async function runScanManyLocal(urls: string[], opts: LocalManyOpts): Pro
784
784
  const browser = await launchChromium(chromium);
785
785
  const findings: DynamicFinding[] = [];
786
786
  const snapshots: string[] = [];
787
+ const redirected: ScanRedirect[] = [];
787
788
  try {
788
789
  for (const url of urls) {
789
790
  const out = await runOnPage(browser, AxeBuilder, url, false, {
@@ -793,6 +794,29 @@ export async function runScanManyLocal(urls: string[], opts: LocalManyOpts): Pro
793
794
  lang,
794
795
  snapshot: Boolean(opts.snapshotRoot),
795
796
  });
797
+ // A CRAWLED URL THAT ANSWERED AN ERROR IS NOT A PAGE OF THE SITE.
798
+ //
799
+ // The sample scan has refused these since it existed, for the reason its own comment
800
+ // gives: a page filed under a name nobody looked at is a false conformance claim. The
801
+ // URL path never applied the same rule, so a crawl that followed a broken link audited
802
+ // the SERVER'S ERROR PAGE and scored it. Measured on a three-page test site with one
803
+ // dead link: the deliverable carried a fourth page called « Error response » at 97 %
804
+ // RGAA, and its criteria counted towards the run.
805
+ //
806
+ // Refused rather than merely skipped: `renderRedirected` states the drop — which URL,
807
+ // what it answered — because a report that is simply SHORTER reads exactly like a
808
+ // complete one, and a dead link is a fixable bug in the site rather than in the audit.
809
+ if (out.httpStatus !== undefined && out.httpStatus >= 400) {
810
+ redirected.push({
811
+ id: slugifyPageId(url),
812
+ name: url,
813
+ requested: url,
814
+ landed: out.landedUrl ?? out.url,
815
+ reason: "http-status",
816
+ status: out.httpStatus,
817
+ });
818
+ continue;
819
+ }
796
820
  findings.push(...toDynamicResult(out, url, lang, LOCAL_ENGINE).findings);
797
821
  const id = opts.snapshotRoot ? writeRunnerSnapshot(opts.snapshotRoot, out, url) : undefined;
798
822
  if (id) snapshots.push(id);
@@ -808,6 +832,7 @@ export async function runScanManyLocal(urls: string[], opts: LocalManyOpts): Pro
808
832
  findings,
809
833
  testedScs: localTestedScs(interact),
810
834
  ...(snapshots.length ? { snapshots } : {}),
835
+ ...(redirected.length ? { redirected } : {}),
811
836
  };
812
837
  }
813
838
 
package/src/types.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  // Single source of truth for shared types + the embedded version. sync-version.mjs
2
2
  // rewrites VERSION at release time (kept in lockstep with package.json + SKILL.md).
3
- export const VERSION = "5.18.0";
3
+ export const VERSION = "5.18.1";
4
4
  export const SCHEMA_VERSION = 2;
5
5
 
6
6
  // Lang = the UI FRAME's language — the `L` localization tables each module (report,