ultra11y 5.38.3 → 5.38.5
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.opencode/plugins/ultra11y.js +1 -1
- package/package.json +1 -1
- package/scripts/ultra11y.mjs +34 -2
- package/scripts/vendor/wcag-2.2-fr.json +1 -1
- package/scripts/vendor/wcag-2.2-sc-universe.json +1 -1
- package/scripts/vendor/wcag-2.2-techniques.json +1 -1
- package/scripts/vendor/wcag-2.2-text.json +1 -1
- package/skills/review-a11y/SKILL.md +1 -1
- package/skills/review-a11y/scripts/ultra11y.mjs +34 -2
- package/skills/ultra11y/SKILL.md +1 -1
- package/skills/ultra11y/scripts/ultra11y.mjs +34 -2
- package/skills/ultra11y/templates/gitlab-ci.yml +1 -1
- package/src/adjudicate-subjects.ts +36 -0
- package/src/data/wcag-universe.json +1 -1
- package/src/types.ts +1 -1
|
@@ -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.38.
|
|
13
|
+
"version": "5.38.5",
|
|
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.38.
|
|
4
|
+
"version": "5.38.5",
|
|
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.38.
|
|
4
|
+
"version": "5.38.5",
|
|
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.38.
|
|
30
|
+
const ULTRA11Y_PLUGIN_VERSION = "5.38.5";
|
|
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.38.
|
|
3
|
+
"version": "5.38.5",
|
|
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",
|
package/scripts/ultra11y.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { join as join53, relative as relative6, 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.38.
|
|
9
|
+
var VERSION = "5.38.5";
|
|
10
10
|
var SCHEMA_VERSION = 2;
|
|
11
11
|
var INAPPLICABLE_STATUS = "C";
|
|
12
12
|
|
|
@@ -2300,7 +2300,7 @@ var wcag_universe_default = {
|
|
|
2300
2300
|
wcagVersion: "2.2",
|
|
2301
2301
|
source: "https://www.w3.org/TR/WCAG22/",
|
|
2302
2302
|
criteriaSource: "https://github.com/w3c/wcag",
|
|
2303
|
-
provenance: "Full WCAG 2.x SC universe (all levels incl. AAA, and the removed 4.1.1 Parsing) fetched from raw.githubusercontent.com/w3c/wcag@main on 2026-08-
|
|
2303
|
+
provenance: "Full WCAG 2.x SC universe (all levels incl. AAA, and the removed 4.1.1 Parsing) fetched from raw.githubusercontent.com/w3c/wcag@main on 2026-08-28 via `node scripts/build-standards.mjs --refresh-universe`. Classification: core-AA = ships in src/data/wcag.json (the shipped WCAG 2.2 AA core); out-of-core = WCAG AAA; removed = obsolete (4.1.1).",
|
|
2304
2304
|
criteria: [
|
|
2305
2305
|
{
|
|
2306
2306
|
id: "1.1.1",
|
|
@@ -47196,6 +47196,36 @@ var SUBJECTS = {
|
|
|
47196
47196
|
),
|
|
47197
47197
|
...linesOf(d, /\b(?:flash|flashing|strobe|setInterval|requestAnimationFrame|classList\.(?:add|remove|replace|toggle))\b|animation(?:-name)?\s*:/i).filter((l) => !/^\s*(?:<!--|\/\/|\/\*)/.test(l.text)).map((l) => hAt(d, l.line, "flash-code", `possible scripted/CSS flash mechanism: ${l.text}`, `flash-code|${l.text}`))
|
|
47198
47198
|
]),
|
|
47199
|
+
// RGAA 7.2 — the script AND the alternative whose relevance must be judged. Inheriting
|
|
47200
|
+
// WCAG 4.1.2 used to hand this criterion every ARIA-bearing element in the repository while
|
|
47201
|
+
// omitting inline handlers entirely. On the realworld fixture that meant 33 unrelated
|
|
47202
|
+
// anchors and none of its three scripts; Haiku correctly refused to invent an association.
|
|
47203
|
+
// Keep the population narrow: scripts/handlers establish applicability, while noscript and
|
|
47204
|
+
// non-text fallbacks are the concrete alternatives covered by tests 7.2.1 and 7.2.2.
|
|
47205
|
+
scriptAlternatives: (docs) => docs.flatMap((d) => [
|
|
47206
|
+
...elementsByTag(d, "script").map(
|
|
47207
|
+
(e) => h(
|
|
47208
|
+
d,
|
|
47209
|
+
e,
|
|
47210
|
+
`<script${attr(e, "src") ? ` src="${attr(e, "src")}"` : ""}> \u2014 identify its alternative and compare the information or function`,
|
|
47211
|
+
`script|${attr(e, "src") ?? t(e, 100)}`
|
|
47212
|
+
)
|
|
47213
|
+
),
|
|
47214
|
+
...linesOf(d, /\bon[A-Z][A-Za-z]*\s*=|\son[a-z]+\s*=\s*["']/).map(
|
|
47215
|
+
(l) => hAt(d, l.line, "handler", `script handler \u2014 identify any alternative offering the same information or function: ${l.text}`, `handler|${l.text}`)
|
|
47216
|
+
),
|
|
47217
|
+
...elementsByTag(d, "noscript").map(
|
|
47218
|
+
(e) => h(d, e, `<noscript> alternative \u2014 does it provide content and functions similar to the associated script?`, `noscript|${t(e, 120)}`)
|
|
47219
|
+
),
|
|
47220
|
+
...d.elements.filter((e) => ["canvas", "object", "embed"].includes(e.tag) && (t(e, 120) !== "" || e.children.some((child) => child.type === "element"))).map(
|
|
47221
|
+
(e) => h(
|
|
47222
|
+
d,
|
|
47223
|
+
e,
|
|
47224
|
+
`<${e.tag}> fallback \u2014 if a script updates this non-text element, is its alternative updated and relevant?`,
|
|
47225
|
+
`script-fallback|${e.tag}|${t(e, 120)}`
|
|
47226
|
+
)
|
|
47227
|
+
)
|
|
47228
|
+
]),
|
|
47199
47229
|
// A change of context initiated by a script. RGAA 7.4 / WCAG 3.2.1-3.2.2.
|
|
47200
47230
|
//
|
|
47201
47231
|
// THE SUBJECT IS THE SCRIPT, and getting that wrong cost a release. This used to be a list of
|
|
@@ -47559,6 +47589,7 @@ var PACK_SUBJECTS = {
|
|
|
47559
47589
|
// Theme 7 — scripts. "Is each script operable by keyboard AND pointer?" is about the
|
|
47560
47590
|
// handlers and the focusable surface, never about the page's headings and lists.
|
|
47561
47591
|
"7.1": ["aria", "pointerHandlers"],
|
|
47592
|
+
"7.2": ["scriptAlternatives"],
|
|
47562
47593
|
"7.3": ["pointerHandlers", "focusables"],
|
|
47563
47594
|
"7.4": ["contextChange"],
|
|
47564
47595
|
"7.5": ["liveRegions"],
|
|
@@ -47607,6 +47638,7 @@ var EXISTENCE_SUBJECTS = /* @__PURE__ */ new Set([
|
|
|
47607
47638
|
"downloadDocs",
|
|
47608
47639
|
"newWindow",
|
|
47609
47640
|
"contextChange",
|
|
47641
|
+
"scriptAlternatives",
|
|
47610
47642
|
// A page that declares no default language has no language code for 8.4 to be about. The
|
|
47611
47643
|
// `<html>` element is always there; the attribute is what this subject looks for.
|
|
47612
47644
|
"declaredLang"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"wcagVersion": "2.2",
|
|
3
3
|
"source": "https://www.w3.org/TR/WCAG22/",
|
|
4
4
|
"criteriaSource": "https://github.com/w3c/wcag",
|
|
5
|
-
"provenance": "Full WCAG 2.x SC universe (all levels incl. AAA, and the removed 4.1.1 Parsing) fetched from raw.githubusercontent.com/w3c/wcag@main on 2026-08-
|
|
5
|
+
"provenance": "Full WCAG 2.x SC universe (all levels incl. AAA, and the removed 4.1.1 Parsing) fetched from raw.githubusercontent.com/w3c/wcag@main on 2026-08-28 via `node scripts/build-standards.mjs --refresh-universe`. Classification: core-AA = ships in src/data/wcag.json (the shipped WCAG 2.2 AA core); out-of-core = WCAG AAA; removed = obsolete (4.1.1).",
|
|
6
6
|
"principles": [
|
|
7
7
|
{
|
|
8
8
|
"number": 1,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"source": "https://github.com/w3c/wcag",
|
|
3
3
|
"understanding": "https://www.w3.org/WAI/WCAG22/Understanding/",
|
|
4
4
|
"license": "W3C Document License (code samples: W3C Software License)",
|
|
5
|
-
"fetchedAt": "2026-08-
|
|
5
|
+
"fetchedAt": "2026-08-28",
|
|
6
6
|
"criteria": {
|
|
7
7
|
"1.1.1": {
|
|
8
8
|
"slug": "non-text-content",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": "https://github.com/w3c/wcag",
|
|
3
3
|
"license": "W3C Document License",
|
|
4
|
-
"fetchedAt": "2026-08-
|
|
4
|
+
"fetchedAt": "2026-08-28",
|
|
5
5
|
"criteria": {
|
|
6
6
|
"1.1.1": "All non-text content that is presented to the user has a text alternative that serves the equivalent purpose, except for the situations listed below.\nControls, Input:\nIf non-text content is a control or accepts user input, then it has a name that describes its purpose. (Refer to Success Criterion 4.1.2 Name, Role, Value for additional requirements for controls and content that accepts user input.)\nTime-Based Media:\nIf non-text content is time-based media, then text alternatives at least provide descriptive identification of the non-text content. (Refer to Guideline 1.2 for additional requirements for media.)\nTest:\nIf non-text content is a test or exercise that would be invalid if presented in text, then text alternatives at least provide descriptive identification of the non-text content.\nSensory:\nIf non-text content is primarily intended to create a specific sensory experience, then text alternatives at least provide descriptive identification of the non-text content.\nCAPTCHA:\nIf the purpose of non-text content is to confirm that content is being accessed by a person rather than a computer, then text alternatives that identify and describe the purpose of the non-text content are provided, and alternative forms of CAPTCHA using output modes for different types of sensory perception are provided to accommodate different disabilities.\nDecoration, Formatting, Invisible:\nIf non-text content is pure decoration, is used only for visual formatting, or is not presented to users, then it is implemented in a way that it can be ignored by assistive technology.",
|
|
7
7
|
"1.2.1": "For prerecorded audio-only and prerecorded video-only media, the following are true, except when the audio or video is a media alternative for text and is clearly labeled as such:\nPrerecorded Audio-only:\nAn alternative for time-based media is provided that presents equivalent information for prerecorded audio-only content.\nPrerecorded Video-only:\nEither an alternative for time-based media or an audio track is provided that presents equivalent information for prerecorded video-only content.",
|
|
@@ -3,7 +3,7 @@ name: review-a11y
|
|
|
3
3
|
description: "Use to REVIEW changed frontend code for accessibility: staged files, a working diff, branch, or PR; prompts such as 'review a11y', 'is this accessible?', or 'anything to fix before merge?'; and hook or CI findings on a change. Run the bundled install-free engine with cross-file JSX/TSX analysis, then adjudicate candidates and return a severity-ranked WCAG 2.2 AA review with file:line fixes, residual rendering risks, and a verdict. Use `ultra11y` instead for whole-repo audits, dated conformance reports, country standards, PRD backlogs, or authoring accessible markup."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: 5.38.
|
|
6
|
+
version: 5.38.5
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# review-a11y — accessibility review of changed code
|
|
@@ -6,7 +6,7 @@ import { join as join53, relative as relative6, 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.38.
|
|
9
|
+
var VERSION = "5.38.5";
|
|
10
10
|
var SCHEMA_VERSION = 2;
|
|
11
11
|
var INAPPLICABLE_STATUS = "C";
|
|
12
12
|
|
|
@@ -2300,7 +2300,7 @@ var wcag_universe_default = {
|
|
|
2300
2300
|
wcagVersion: "2.2",
|
|
2301
2301
|
source: "https://www.w3.org/TR/WCAG22/",
|
|
2302
2302
|
criteriaSource: "https://github.com/w3c/wcag",
|
|
2303
|
-
provenance: "Full WCAG 2.x SC universe (all levels incl. AAA, and the removed 4.1.1 Parsing) fetched from raw.githubusercontent.com/w3c/wcag@main on 2026-08-
|
|
2303
|
+
provenance: "Full WCAG 2.x SC universe (all levels incl. AAA, and the removed 4.1.1 Parsing) fetched from raw.githubusercontent.com/w3c/wcag@main on 2026-08-28 via `node scripts/build-standards.mjs --refresh-universe`. Classification: core-AA = ships in src/data/wcag.json (the shipped WCAG 2.2 AA core); out-of-core = WCAG AAA; removed = obsolete (4.1.1).",
|
|
2304
2304
|
criteria: [
|
|
2305
2305
|
{
|
|
2306
2306
|
id: "1.1.1",
|
|
@@ -47196,6 +47196,36 @@ var SUBJECTS = {
|
|
|
47196
47196
|
),
|
|
47197
47197
|
...linesOf(d, /\b(?:flash|flashing|strobe|setInterval|requestAnimationFrame|classList\.(?:add|remove|replace|toggle))\b|animation(?:-name)?\s*:/i).filter((l) => !/^\s*(?:<!--|\/\/|\/\*)/.test(l.text)).map((l) => hAt(d, l.line, "flash-code", `possible scripted/CSS flash mechanism: ${l.text}`, `flash-code|${l.text}`))
|
|
47198
47198
|
]),
|
|
47199
|
+
// RGAA 7.2 — the script AND the alternative whose relevance must be judged. Inheriting
|
|
47200
|
+
// WCAG 4.1.2 used to hand this criterion every ARIA-bearing element in the repository while
|
|
47201
|
+
// omitting inline handlers entirely. On the realworld fixture that meant 33 unrelated
|
|
47202
|
+
// anchors and none of its three scripts; Haiku correctly refused to invent an association.
|
|
47203
|
+
// Keep the population narrow: scripts/handlers establish applicability, while noscript and
|
|
47204
|
+
// non-text fallbacks are the concrete alternatives covered by tests 7.2.1 and 7.2.2.
|
|
47205
|
+
scriptAlternatives: (docs) => docs.flatMap((d) => [
|
|
47206
|
+
...elementsByTag(d, "script").map(
|
|
47207
|
+
(e) => h(
|
|
47208
|
+
d,
|
|
47209
|
+
e,
|
|
47210
|
+
`<script${attr(e, "src") ? ` src="${attr(e, "src")}"` : ""}> \u2014 identify its alternative and compare the information or function`,
|
|
47211
|
+
`script|${attr(e, "src") ?? t(e, 100)}`
|
|
47212
|
+
)
|
|
47213
|
+
),
|
|
47214
|
+
...linesOf(d, /\bon[A-Z][A-Za-z]*\s*=|\son[a-z]+\s*=\s*["']/).map(
|
|
47215
|
+
(l) => hAt(d, l.line, "handler", `script handler \u2014 identify any alternative offering the same information or function: ${l.text}`, `handler|${l.text}`)
|
|
47216
|
+
),
|
|
47217
|
+
...elementsByTag(d, "noscript").map(
|
|
47218
|
+
(e) => h(d, e, `<noscript> alternative \u2014 does it provide content and functions similar to the associated script?`, `noscript|${t(e, 120)}`)
|
|
47219
|
+
),
|
|
47220
|
+
...d.elements.filter((e) => ["canvas", "object", "embed"].includes(e.tag) && (t(e, 120) !== "" || e.children.some((child) => child.type === "element"))).map(
|
|
47221
|
+
(e) => h(
|
|
47222
|
+
d,
|
|
47223
|
+
e,
|
|
47224
|
+
`<${e.tag}> fallback \u2014 if a script updates this non-text element, is its alternative updated and relevant?`,
|
|
47225
|
+
`script-fallback|${e.tag}|${t(e, 120)}`
|
|
47226
|
+
)
|
|
47227
|
+
)
|
|
47228
|
+
]),
|
|
47199
47229
|
// A change of context initiated by a script. RGAA 7.4 / WCAG 3.2.1-3.2.2.
|
|
47200
47230
|
//
|
|
47201
47231
|
// THE SUBJECT IS THE SCRIPT, and getting that wrong cost a release. This used to be a list of
|
|
@@ -47559,6 +47589,7 @@ var PACK_SUBJECTS = {
|
|
|
47559
47589
|
// Theme 7 — scripts. "Is each script operable by keyboard AND pointer?" is about the
|
|
47560
47590
|
// handlers and the focusable surface, never about the page's headings and lists.
|
|
47561
47591
|
"7.1": ["aria", "pointerHandlers"],
|
|
47592
|
+
"7.2": ["scriptAlternatives"],
|
|
47562
47593
|
"7.3": ["pointerHandlers", "focusables"],
|
|
47563
47594
|
"7.4": ["contextChange"],
|
|
47564
47595
|
"7.5": ["liveRegions"],
|
|
@@ -47607,6 +47638,7 @@ var EXISTENCE_SUBJECTS = /* @__PURE__ */ new Set([
|
|
|
47607
47638
|
"downloadDocs",
|
|
47608
47639
|
"newWindow",
|
|
47609
47640
|
"contextChange",
|
|
47641
|
+
"scriptAlternatives",
|
|
47610
47642
|
// A page that declares no default language has no language code for 8.4 to be about. The
|
|
47611
47643
|
// `<html>` element is always there; the attribute is what this subject looks for.
|
|
47612
47644
|
"declaredLang"
|
package/skills/ultra11y/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: ultra11y
|
|
|
3
3
|
description: "Use to AUDIT a repository, site, or page against WCAG 2.2 AA or a country standard such as RGAA; produce a dated conformance report, criterion grid, PRD backlog, or tickets; AUTHOR accessible markup; fix accessibility; or wire a repo gate and rendered-DOM capture pipeline. The bundled install-free engine runs 93 static checks tied to success criteria, while the agent adjudicates judgment criteria and routes rendering criteria to browser scans; check/verify reject invented non-conformities. Use `review-a11y` instead for a review scoped only to a diff, branch, or PR."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: 5.38.
|
|
6
|
+
version: 5.38.5
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# ultra11y — audit WCAG 2.2 AA and write accessible markup
|
|
@@ -6,7 +6,7 @@ import { join as join53, relative as relative6, 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.38.
|
|
9
|
+
var VERSION = "5.38.5";
|
|
10
10
|
var SCHEMA_VERSION = 2;
|
|
11
11
|
var INAPPLICABLE_STATUS = "C";
|
|
12
12
|
|
|
@@ -2300,7 +2300,7 @@ var wcag_universe_default = {
|
|
|
2300
2300
|
wcagVersion: "2.2",
|
|
2301
2301
|
source: "https://www.w3.org/TR/WCAG22/",
|
|
2302
2302
|
criteriaSource: "https://github.com/w3c/wcag",
|
|
2303
|
-
provenance: "Full WCAG 2.x SC universe (all levels incl. AAA, and the removed 4.1.1 Parsing) fetched from raw.githubusercontent.com/w3c/wcag@main on 2026-08-
|
|
2303
|
+
provenance: "Full WCAG 2.x SC universe (all levels incl. AAA, and the removed 4.1.1 Parsing) fetched from raw.githubusercontent.com/w3c/wcag@main on 2026-08-28 via `node scripts/build-standards.mjs --refresh-universe`. Classification: core-AA = ships in src/data/wcag.json (the shipped WCAG 2.2 AA core); out-of-core = WCAG AAA; removed = obsolete (4.1.1).",
|
|
2304
2304
|
criteria: [
|
|
2305
2305
|
{
|
|
2306
2306
|
id: "1.1.1",
|
|
@@ -47196,6 +47196,36 @@ var SUBJECTS = {
|
|
|
47196
47196
|
),
|
|
47197
47197
|
...linesOf(d, /\b(?:flash|flashing|strobe|setInterval|requestAnimationFrame|classList\.(?:add|remove|replace|toggle))\b|animation(?:-name)?\s*:/i).filter((l) => !/^\s*(?:<!--|\/\/|\/\*)/.test(l.text)).map((l) => hAt(d, l.line, "flash-code", `possible scripted/CSS flash mechanism: ${l.text}`, `flash-code|${l.text}`))
|
|
47198
47198
|
]),
|
|
47199
|
+
// RGAA 7.2 — the script AND the alternative whose relevance must be judged. Inheriting
|
|
47200
|
+
// WCAG 4.1.2 used to hand this criterion every ARIA-bearing element in the repository while
|
|
47201
|
+
// omitting inline handlers entirely. On the realworld fixture that meant 33 unrelated
|
|
47202
|
+
// anchors and none of its three scripts; Haiku correctly refused to invent an association.
|
|
47203
|
+
// Keep the population narrow: scripts/handlers establish applicability, while noscript and
|
|
47204
|
+
// non-text fallbacks are the concrete alternatives covered by tests 7.2.1 and 7.2.2.
|
|
47205
|
+
scriptAlternatives: (docs) => docs.flatMap((d) => [
|
|
47206
|
+
...elementsByTag(d, "script").map(
|
|
47207
|
+
(e) => h(
|
|
47208
|
+
d,
|
|
47209
|
+
e,
|
|
47210
|
+
`<script${attr(e, "src") ? ` src="${attr(e, "src")}"` : ""}> \u2014 identify its alternative and compare the information or function`,
|
|
47211
|
+
`script|${attr(e, "src") ?? t(e, 100)}`
|
|
47212
|
+
)
|
|
47213
|
+
),
|
|
47214
|
+
...linesOf(d, /\bon[A-Z][A-Za-z]*\s*=|\son[a-z]+\s*=\s*["']/).map(
|
|
47215
|
+
(l) => hAt(d, l.line, "handler", `script handler \u2014 identify any alternative offering the same information or function: ${l.text}`, `handler|${l.text}`)
|
|
47216
|
+
),
|
|
47217
|
+
...elementsByTag(d, "noscript").map(
|
|
47218
|
+
(e) => h(d, e, `<noscript> alternative \u2014 does it provide content and functions similar to the associated script?`, `noscript|${t(e, 120)}`)
|
|
47219
|
+
),
|
|
47220
|
+
...d.elements.filter((e) => ["canvas", "object", "embed"].includes(e.tag) && (t(e, 120) !== "" || e.children.some((child) => child.type === "element"))).map(
|
|
47221
|
+
(e) => h(
|
|
47222
|
+
d,
|
|
47223
|
+
e,
|
|
47224
|
+
`<${e.tag}> fallback \u2014 if a script updates this non-text element, is its alternative updated and relevant?`,
|
|
47225
|
+
`script-fallback|${e.tag}|${t(e, 120)}`
|
|
47226
|
+
)
|
|
47227
|
+
)
|
|
47228
|
+
]),
|
|
47199
47229
|
// A change of context initiated by a script. RGAA 7.4 / WCAG 3.2.1-3.2.2.
|
|
47200
47230
|
//
|
|
47201
47231
|
// THE SUBJECT IS THE SCRIPT, and getting that wrong cost a release. This used to be a list of
|
|
@@ -47559,6 +47589,7 @@ var PACK_SUBJECTS = {
|
|
|
47559
47589
|
// Theme 7 — scripts. "Is each script operable by keyboard AND pointer?" is about the
|
|
47560
47590
|
// handlers and the focusable surface, never about the page's headings and lists.
|
|
47561
47591
|
"7.1": ["aria", "pointerHandlers"],
|
|
47592
|
+
"7.2": ["scriptAlternatives"],
|
|
47562
47593
|
"7.3": ["pointerHandlers", "focusables"],
|
|
47563
47594
|
"7.4": ["contextChange"],
|
|
47564
47595
|
"7.5": ["liveRegions"],
|
|
@@ -47607,6 +47638,7 @@ var EXISTENCE_SUBJECTS = /* @__PURE__ */ new Set([
|
|
|
47607
47638
|
"downloadDocs",
|
|
47608
47639
|
"newWindow",
|
|
47609
47640
|
"contextChange",
|
|
47641
|
+
"scriptAlternatives",
|
|
47610
47642
|
// A page that declares no default language has no language code for 8.4 to be about. The
|
|
47611
47643
|
// `<html>` element is always there; the attribute is what this subject looks for.
|
|
47612
47644
|
"declaredLang"
|
|
@@ -27,7 +27,7 @@ variables:
|
|
|
27
27
|
ULTRA11Y_LANG: en
|
|
28
28
|
# Exact by default: a CI report must say which engine produced it. The release script keeps
|
|
29
29
|
# this pin aligned with the package version; override only for a deliberate upgrade test.
|
|
30
|
-
ULTRA11Y_VERSION: '5.38.
|
|
30
|
+
ULTRA11Y_VERSION: '5.38.5'
|
|
31
31
|
# Batches of 8 amortise the prompt; each accepted verdict is checkpointed before the next
|
|
32
32
|
# batch, and later passes receive only the residue.
|
|
33
33
|
ULTRA11Y_GRAIN: batch
|
|
@@ -826,6 +826,40 @@ export const SUBJECTS: Record<string, Subject> = {
|
|
|
826
826
|
.map((l) => hAt(d, l.line, "flash-code", `possible scripted/CSS flash mechanism: ${l.text}`, `flash-code|${l.text}`)),
|
|
827
827
|
]),
|
|
828
828
|
|
|
829
|
+
// RGAA 7.2 — the script AND the alternative whose relevance must be judged. Inheriting
|
|
830
|
+
// WCAG 4.1.2 used to hand this criterion every ARIA-bearing element in the repository while
|
|
831
|
+
// omitting inline handlers entirely. On the realworld fixture that meant 33 unrelated
|
|
832
|
+
// anchors and none of its three scripts; Haiku correctly refused to invent an association.
|
|
833
|
+
// Keep the population narrow: scripts/handlers establish applicability, while noscript and
|
|
834
|
+
// non-text fallbacks are the concrete alternatives covered by tests 7.2.1 and 7.2.2.
|
|
835
|
+
scriptAlternatives: (docs) =>
|
|
836
|
+
docs.flatMap((d) => [
|
|
837
|
+
...elementsByTag(d, "script").map((e) =>
|
|
838
|
+
h(
|
|
839
|
+
d,
|
|
840
|
+
e,
|
|
841
|
+
`<script${attr(e, "src") ? ` src="${attr(e, "src")}"` : ""}> — identify its alternative and compare the information or function`,
|
|
842
|
+
`script|${attr(e, "src") ?? t(e, 100)}`,
|
|
843
|
+
),
|
|
844
|
+
),
|
|
845
|
+
...linesOf(d, /\bon[A-Z][A-Za-z]*\s*=|\son[a-z]+\s*=\s*["']/).map((l) =>
|
|
846
|
+
hAt(d, l.line, "handler", `script handler — identify any alternative offering the same information or function: ${l.text}`, `handler|${l.text}`),
|
|
847
|
+
),
|
|
848
|
+
...elementsByTag(d, "noscript").map((e) =>
|
|
849
|
+
h(d, e, `<noscript> alternative — does it provide content and functions similar to the associated script?`, `noscript|${t(e, 120)}`),
|
|
850
|
+
),
|
|
851
|
+
...d.elements
|
|
852
|
+
.filter((e) => ["canvas", "object", "embed"].includes(e.tag) && (t(e, 120) !== "" || e.children.some((child) => child.type === "element")))
|
|
853
|
+
.map((e) =>
|
|
854
|
+
h(
|
|
855
|
+
d,
|
|
856
|
+
e,
|
|
857
|
+
`<${e.tag}> fallback — if a script updates this non-text element, is its alternative updated and relevant?`,
|
|
858
|
+
`script-fallback|${e.tag}|${t(e, 120)}`,
|
|
859
|
+
),
|
|
860
|
+
),
|
|
861
|
+
]),
|
|
862
|
+
|
|
829
863
|
// A change of context initiated by a script. RGAA 7.4 / WCAG 3.2.1-3.2.2.
|
|
830
864
|
//
|
|
831
865
|
// THE SUBJECT IS THE SCRIPT, and getting that wrong cost a release. This used to be a list of
|
|
@@ -1257,6 +1291,7 @@ export const PACK_SUBJECTS: Record<string, Record<string, string[]>> = {
|
|
|
1257
1291
|
// Theme 7 — scripts. "Is each script operable by keyboard AND pointer?" is about the
|
|
1258
1292
|
// handlers and the focusable surface, never about the page's headings and lists.
|
|
1259
1293
|
"7.1": ["aria", "pointerHandlers"],
|
|
1294
|
+
"7.2": ["scriptAlternatives"],
|
|
1260
1295
|
"7.3": ["pointerHandlers", "focusables"],
|
|
1261
1296
|
"7.4": ["contextChange"],
|
|
1262
1297
|
"7.5": ["liveRegions"],
|
|
@@ -1381,6 +1416,7 @@ export const EXISTENCE_SUBJECTS: ReadonlySet<string> = new Set([
|
|
|
1381
1416
|
"downloadDocs",
|
|
1382
1417
|
"newWindow",
|
|
1383
1418
|
"contextChange",
|
|
1419
|
+
"scriptAlternatives",
|
|
1384
1420
|
// A page that declares no default language has no language code for 8.4 to be about. The
|
|
1385
1421
|
// `<html>` element is always there; the attribute is what this subject looks for.
|
|
1386
1422
|
"declaredLang",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"wcagVersion": "2.2",
|
|
3
3
|
"source": "https://www.w3.org/TR/WCAG22/",
|
|
4
4
|
"criteriaSource": "https://github.com/w3c/wcag",
|
|
5
|
-
"provenance": "Full WCAG 2.x SC universe (all levels incl. AAA, and the removed 4.1.1 Parsing) fetched from raw.githubusercontent.com/w3c/wcag@main on 2026-08-
|
|
5
|
+
"provenance": "Full WCAG 2.x SC universe (all levels incl. AAA, and the removed 4.1.1 Parsing) fetched from raw.githubusercontent.com/w3c/wcag@main on 2026-08-28 via `node scripts/build-standards.mjs --refresh-universe`. Classification: core-AA = ships in src/data/wcag.json (the shipped WCAG 2.2 AA core); out-of-core = WCAG AAA; removed = obsolete (4.1.1).",
|
|
6
6
|
"criteria": [
|
|
7
7
|
{
|
|
8
8
|
"id": "1.1.1",
|
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.38.
|
|
3
|
+
export const VERSION = "5.38.5";
|
|
4
4
|
export const SCHEMA_VERSION = 2;
|
|
5
5
|
|
|
6
6
|
// Lang = the UI FRAME's language — the `L` localization tables each module (report,
|