ultra11y 5.24.0 → 5.26.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/.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/dist/playwright.mjs +1 -1
- package/package.json +1 -1
- package/scripts/build-pack-rgaa.mjs +41 -1
- package/scripts/ultra11y.mjs +704 -48
- package/scripts/vendor/rgaa/SOURCE.json +4 -3
- package/scripts/vendor/rgaa/methodologies.json +260 -0
- package/scripts/verify-rgaa-source.mjs +23 -6
- package/skills/review-a11y/SKILL.md +1 -1
- package/skills/review-a11y/scripts/ultra11y.mjs +704 -48
- package/skills/ultra11y/SKILL.md +10 -1
- package/skills/ultra11y/references/judgment.md +27 -1
- package/skills/ultra11y/references/orchestration.md +5 -0
- package/skills/ultra11y/scripts/ultra11y.mjs +704 -48
- package/src/adjudicate-subjects.ts +73 -1
- package/src/adjudicate.ts +206 -23
- package/src/adjudication-data.ts +31 -0
- package/src/audit.ts +1 -1
- package/src/cli.ts +51 -2
- package/src/criteria-view.ts +18 -8
- package/src/criteria.ts +17 -1
- package/src/data/standards/rgaa.json +471 -0
- package/src/dev.ts +1 -1
- package/src/glob.ts +2 -2
- package/src/graph/imports.ts +1 -1
- package/src/integrations/cypress-plugin.ts +1 -1
- package/src/integrations/cypress.ts +2 -2
- package/src/integrations/playwright.ts +5 -5
- package/src/mcp/handlers.ts +1 -1
- package/src/orchestrate-templates.ts +9 -5
- package/src/orchestrate.ts +1 -1
- package/src/rules/images.ts +1 -1
- package/src/rules/tables.ts +2 -2
- package/src/scan.ts +1 -1
- package/src/standards/pack-rules.ts +1 -1
- package/src/standards/pack.ts +6 -0
- package/src/standards/types.ts +17 -0
- package/src/standards/validate.ts +30 -0
- 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.
|
|
13
|
+
"version": "5.26.0",
|
|
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.
|
|
4
|
+
"version": "5.26.0",
|
|
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.
|
|
4
|
+
"version": "5.26.0",
|
|
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.
|
|
30
|
+
const ULTRA11Y_PLUGIN_VERSION = "5.26.0";
|
|
31
31
|
|
|
32
32
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
33
33
|
|
package/dist/playwright.mjs
CHANGED
|
@@ -720,7 +720,7 @@ var test = (() => {
|
|
|
720
720
|
const base = load(from).test;
|
|
721
721
|
if (!base?.extend) continue;
|
|
722
722
|
return base.extend({
|
|
723
|
-
//
|
|
723
|
+
// `any` for the same reason.
|
|
724
724
|
ultra11y: async ({ page }, use) => {
|
|
725
725
|
await use((opts) => checkA11y(page, opts));
|
|
726
726
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ultra11y",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.26.0",
|
|
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,8 @@
|
|
|
6
6
|
// of its criteria onto WCAG success criteria (bare SC ids). The WCAG↔rule coverage
|
|
7
7
|
// lives in the core (scripts/build-standards.mjs). The RGAA content is Licence
|
|
8
8
|
// Ouverte / Etalab 2.0 — see NOTICE. The official source is vendored under
|
|
9
|
-
// scripts/vendor/rgaa/
|
|
9
|
+
// scripts/vendor/rgaa/ (criteres.json, glossaire.json, methodologies.json) so the
|
|
10
|
+
// build is reproducible offline.
|
|
10
11
|
// node scripts/build-pack-rgaa.mjs # build from the vendored source
|
|
11
12
|
// node scripts/build-pack-rgaa.mjs --offline # alias (the source is always local)
|
|
12
13
|
// node scripts/build-pack-rgaa.mjs --fetch # refresh the vendored source from DINUM, then build
|
|
@@ -76,6 +77,22 @@ const flattenNode = (v) => {
|
|
|
76
77
|
};
|
|
77
78
|
const toArr = (v) => flattenNode(v);
|
|
78
79
|
|
|
80
|
+
// The official méthodologie de test for one criterion, keyed by the criterion's OWN test
|
|
81
|
+
// numbers so it renders directly under the test it explains: `{ "1": "1. Retrouver…", … }`.
|
|
82
|
+
// DINUM's file is flat and keyed by full test id ("11.2.1"), so this is the re-key.
|
|
83
|
+
//
|
|
84
|
+
// Returns undefined when the criterion has none, and the field is then absent from the pack
|
|
85
|
+
// rather than present-and-empty: `methodology` is optional on PackCriterion, and an empty
|
|
86
|
+
// object would make every consumer test for two shapes instead of one.
|
|
87
|
+
function methodologyOf(methodologies, id, tests) {
|
|
88
|
+
const out = {};
|
|
89
|
+
for (const k of Object.keys(tests || {})) {
|
|
90
|
+
const text = methodologies[`${id}.${k}`];
|
|
91
|
+
if (typeof text === "string" && text.trim()) out[k] = text.trim();
|
|
92
|
+
}
|
|
93
|
+
return Object.keys(out).length ? { methodology: out } : undefined;
|
|
94
|
+
}
|
|
95
|
+
|
|
79
96
|
// crude HTML -> plaintext for glossary bodies
|
|
80
97
|
const deHtml = (s) =>
|
|
81
98
|
s
|
|
@@ -245,6 +262,12 @@ const RULE_TO_CRITERIA = {
|
|
|
245
262
|
async function main() {
|
|
246
263
|
const criteres = await source("criteres.json");
|
|
247
264
|
const glossaire = await source("glossaire.json");
|
|
265
|
+
// THE OFFICIAL TEST METHODOLOGY — the third file DINUM publishes beside the other two,
|
|
266
|
+
// keyed by TEST id ("11.2.1"), and the one thing an adjudicator was never given. The
|
|
267
|
+
// criterion's wording says WHAT is required; this says HOW it is tested, step by step, in
|
|
268
|
+
// the referential's own words. Vendored like the rest so it reaches CI, an offline run and
|
|
269
|
+
// a model prompt without a network call — see `methodology` in src/standards/types.ts.
|
|
270
|
+
const methodologies = await source("methodologies.json");
|
|
248
271
|
|
|
249
272
|
const glossary = {};
|
|
250
273
|
for (const e of glossaire.glossary) glossary[slug(e.title)] = { title: e.title, body: deHtml(e.body) };
|
|
@@ -267,6 +290,7 @@ async function main() {
|
|
|
267
290
|
title: { fr: criterium.title },
|
|
268
291
|
titlePlain: { fr: plain(criterium.title) },
|
|
269
292
|
tests: criterium.tests || {},
|
|
293
|
+
...(methodologyOf(methodologies, id, criterium.tests) ?? {}),
|
|
270
294
|
techniques: [...techniques],
|
|
271
295
|
...(criterium.technicalNote ? { technicalNote: toArr(criterium.technicalNote) } : {}),
|
|
272
296
|
...(criterium.particularCases ? { particularCases: toArr(criterium.particularCases) } : {}),
|
|
@@ -462,6 +486,9 @@ const DOWNLOAD_EXT = "pdf|docx?|pptx?|xlsx?|odt|ods|odp|rtf|csv|zip|rar|7z|gz|ep
|
|
|
462
486
|
source: "https://github.com/DISIC/accessibilite.numerique.gouv.fr",
|
|
463
487
|
attribution: "RGAA 4.1.2 © DINUM (Direction interministérielle du numérique) — Licence Ouverte / Etalab 2.0",
|
|
464
488
|
idPattern: "^\\d+\\.\\d+$",
|
|
489
|
+
// Where DINUM publishes each criterion. Cited by the adjudication brief so a reader can
|
|
490
|
+
// reach the normative page — the vendored text above stays the authority either way.
|
|
491
|
+
criterionUrl: "https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#{id}",
|
|
465
492
|
// Auditor-display vocabulary (FR): the nouns an RGAA auditor reads. Rendered by the
|
|
466
493
|
// `prd` auditor block + GitHub issues; see src/standards/vocabulary.ts.
|
|
467
494
|
vocabulary: {
|
|
@@ -572,9 +599,22 @@ const DOWNLOAD_EXT = "pdf|docx?|pptx?|xlsx?|odt|ods|odp|rtf|csv|zip|rar|7z|gz|ep
|
|
|
572
599
|
throw new Error(`build-pack-rgaa: ${stringified.length} normative text(s) stringified to "[object Object]" — extend flattenNode: ${stringified.join(", ")}`);
|
|
573
600
|
}
|
|
574
601
|
|
|
602
|
+
// THE METHODOLOGY TABLE MUST NOT GO STALE EITHER. A methodology whose test id does not
|
|
603
|
+
// exist in the referential is a curation mistake upstream OR a re-key bug here, and it
|
|
604
|
+
// would ship as dead weight in every bundle. A test with no methodology is legitimate
|
|
605
|
+
// (DINUM does not document every one), so that is counted, not refused.
|
|
606
|
+
const testIds = new Set();
|
|
607
|
+
for (const c of criteria) for (const k of Object.keys(c.tests ?? {})) testIds.add(`${c.id}.${k}`);
|
|
608
|
+
const orphans = Object.keys(methodologies).filter((k) => !testIds.has(k));
|
|
609
|
+
if (orphans.length) {
|
|
610
|
+
throw new Error(`build-pack-rgaa: ${orphans.length} methodology(ies) name a test the referential does not have: ${orphans.join(", ")}`);
|
|
611
|
+
}
|
|
612
|
+
const documented = criteria.reduce((n, c) => n + Object.keys(c.methodology ?? {}).length, 0);
|
|
613
|
+
|
|
575
614
|
const noWcag = criteria.filter((c) => c.wcag.length === 0).map((c) => c.id);
|
|
576
615
|
console.log(`build-pack-rgaa: ${themes.length} themes, ${criteria.length} criteria → src/data/standards/rgaa.json`);
|
|
577
616
|
console.log(`build-pack-rgaa: glossary ${Object.keys(glossary).length} entries → src/data/standards/rgaa.glossary.json`);
|
|
617
|
+
console.log(`build-pack-rgaa: official test methodology on ${documented}/${testIds.size} tests`);
|
|
578
618
|
console.log(`build-pack-rgaa: criteria with no WCAG mapping (pack-local): ${noWcag.length ? noWcag.join(", ") : "none"} (${noWcag.length})`);
|
|
579
619
|
}
|
|
580
620
|
|