nfunc-mcp 0.4.0 → 0.5.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/README.md +38 -4
- package/dist/mappers/a11yDedupe.js +38 -7
- package/dist/mappers/a11yDedupe.js.map +1 -1
- package/dist/mappers/defectFormatter.d.ts +9 -1
- package/dist/mappers/defectFormatter.js +53 -13
- package/dist/mappers/defectFormatter.js.map +1 -1
- package/dist/mappers/priorityMapper.d.ts +42 -0
- package/dist/mappers/priorityMapper.js +58 -0
- package/dist/mappers/priorityMapper.js.map +1 -1
- package/dist/mappers/runComparator.d.ts +85 -0
- package/dist/mappers/runComparator.js +165 -0
- package/dist/mappers/runComparator.js.map +1 -0
- package/dist/mappers/wcagLevels.d.ts +73 -0
- package/dist/mappers/wcagLevels.js +320 -0
- package/dist/mappers/wcagLevels.js.map +1 -0
- package/dist/tools/accessibility.d.ts +1 -0
- package/dist/tools/accessibility.js +488 -63
- package/dist/tools/accessibility.js.map +1 -1
- package/dist/tools/lighthouse.js +370 -102
- package/dist/tools/lighthouse.js.map +1 -1
- package/dist/utils/batchState.d.ts +75 -0
- package/dist/utils/batchState.js +128 -0
- package/dist/utils/batchState.js.map +1 -0
- package/dist/utils/outputParsers.js +26 -30
- package/dist/utils/outputParsers.js.map +1 -1
- package/dist/utils/psiParser.d.ts +11 -0
- package/dist/utils/psiParser.js +2 -2
- package/dist/utils/psiParser.js.map +1 -1
- package/dist/utils/urlInput.d.ts +30 -0
- package/dist/utils/urlInput.js +130 -0
- package/dist/utils/urlInput.js.map +1 -0
- package/docs/manual.md +218 -7
- package/package.json +1 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Before-and-after comparison of two runs.
|
|
3
|
+
*
|
|
4
|
+
* A snapshot answers "what is wrong with this page". A developer about to open
|
|
5
|
+
* a PR has a different question: "did my fix work, and did I break anything?"
|
|
6
|
+
* Those are not the same question, and a count cannot distinguish them.
|
|
7
|
+
*
|
|
8
|
+
* Measured case, from a page where an `alt` attribute and an `aria-label` were
|
|
9
|
+
* added to fix a missing-alt-text blocker:
|
|
10
|
+
*
|
|
11
|
+
* before: 2 violations — image-alt (P1), color-contrast (P3)
|
|
12
|
+
* after: 2 violations — aria-valid-attr-value (P2), color-contrast (P3)
|
|
13
|
+
*
|
|
14
|
+
* Identical totals. The P1 was genuinely fixed, and the fix introduced a new
|
|
15
|
+
* defect, because the aria-labelledby it added pointed at an id that did not
|
|
16
|
+
* exist. Anyone reading "2 before, 2 after" concludes the change did nothing.
|
|
17
|
+
* `newly_introduced` is the half of this module that earns its keep.
|
|
18
|
+
*/
|
|
19
|
+
const key = (d) => `${d.url}|${d.variant}|${d.id}`;
|
|
20
|
+
const runKey = (d) => `${d.url}|${d.variant}`;
|
|
21
|
+
const RANK = { P1: 0, P2: 1, P3: 2 };
|
|
22
|
+
function worst(items) {
|
|
23
|
+
if (items.length === 0)
|
|
24
|
+
return null;
|
|
25
|
+
return items.reduce((acc, i) => (RANK[i.priority] < RANK[acc] ? i.priority : acc), "P3");
|
|
26
|
+
}
|
|
27
|
+
function describe(verdict, fixed, broke, remaining, worstNew) {
|
|
28
|
+
// The "totals hid it" warning only belongs where the totals actually hid it.
|
|
29
|
+
// Claiming a count looked unchanged when it went 6 to 2 is the same kind of
|
|
30
|
+
// imprecision this module exists to remove.
|
|
31
|
+
const before = fixed + remaining;
|
|
32
|
+
const after = remaining + broke;
|
|
33
|
+
const totalsMask = before === after;
|
|
34
|
+
switch (verdict) {
|
|
35
|
+
case "clean":
|
|
36
|
+
return fixed > 0
|
|
37
|
+
? `All clear — ${fixed} defect(s) fixed and nothing failing now.`
|
|
38
|
+
: "All clear — nothing failing in either run.";
|
|
39
|
+
case "improved":
|
|
40
|
+
return `${fixed} defect(s) fixed, none introduced. ${remaining} still failing.`;
|
|
41
|
+
case "mixed":
|
|
42
|
+
return (`${fixed} defect(s) fixed, but ${broke} newly introduced` +
|
|
43
|
+
`${worstNew ? ` (worst: ${worstNew})` : ""}. ` +
|
|
44
|
+
(totalsMask
|
|
45
|
+
? `The total is unchanged at ${after}, so the count alone would suggest nothing happened — ` +
|
|
46
|
+
`check newly_introduced before treating this as a clean fix.`
|
|
47
|
+
: `Total went ${before} to ${after}; the drop is real but incomplete — ` +
|
|
48
|
+
`check newly_introduced before treating this as a clean fix.`));
|
|
49
|
+
case "regression":
|
|
50
|
+
return (`${broke} defect(s) newly introduced` +
|
|
51
|
+
`${worstNew ? ` (worst: ${worstNew})` : ""} and none fixed. This change made things worse.`);
|
|
52
|
+
case "unchanged":
|
|
53
|
+
return `No change — ${remaining} defect(s) failing in both runs.`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Compare two defect sets.
|
|
58
|
+
*
|
|
59
|
+
* Comparison is per (url, variant, defect id). A defect that moved priority
|
|
60
|
+
* between runs counts as still failing rather than as fixed-and-reintroduced,
|
|
61
|
+
* since it is the same defect on the same element — the priority shift shows up
|
|
62
|
+
* in `still_failing`.
|
|
63
|
+
*/
|
|
64
|
+
export function compareRuns(baselineDir, baseline, current, options = {}) {
|
|
65
|
+
const warnings = [];
|
|
66
|
+
const baseByKey = new Map(baseline.map((d) => [key(d), d]));
|
|
67
|
+
const curByKey = new Map(current.map((d) => [key(d), d]));
|
|
68
|
+
// Only compare runs both sides actually covered; anything else would report
|
|
69
|
+
// a "fix" that is really an absence of measurement.
|
|
70
|
+
const baseRuns = new Set(baseline.map(runKey));
|
|
71
|
+
const curRuns = new Set(current.map(runKey));
|
|
72
|
+
const comparableRuns = new Set([...curRuns].filter((r) => baseRuns.has(r)));
|
|
73
|
+
const notInBaseline = [...curRuns].filter((r) => !baseRuns.has(r));
|
|
74
|
+
const notInCurrent = [...baseRuns].filter((r) => !curRuns.has(r));
|
|
75
|
+
const fixed = [];
|
|
76
|
+
const stillFailing = [];
|
|
77
|
+
const newlyIntroduced = [];
|
|
78
|
+
for (const [k, d] of baseByKey) {
|
|
79
|
+
if (!comparableRuns.has(runKey(d)))
|
|
80
|
+
continue;
|
|
81
|
+
if (curByKey.has(k)) {
|
|
82
|
+
const now = curByKey.get(k);
|
|
83
|
+
stillFailing.push({ url: d.url, variant: d.variant, id: d.id, priority: now.priority, title: now.title });
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
fixed.push({ url: d.url, variant: d.variant, id: d.id, was: d.priority, title: d.title });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (const [k, d] of curByKey) {
|
|
90
|
+
if (!comparableRuns.has(runKey(d)))
|
|
91
|
+
continue;
|
|
92
|
+
if (!baseByKey.has(k)) {
|
|
93
|
+
newlyIntroduced.push({ url: d.url, variant: d.variant, id: d.id, priority: d.priority, title: d.title });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const sortByPriority = (items) => items.sort((a, b) => RANK[(a.priority ?? a.was)] - RANK[(b.priority ?? b.was)]);
|
|
97
|
+
sortByPriority(fixed);
|
|
98
|
+
sortByPriority(stillFailing);
|
|
99
|
+
sortByPriority(newlyIntroduced);
|
|
100
|
+
let verdict;
|
|
101
|
+
if (newlyIntroduced.length > 0 && fixed.length > 0)
|
|
102
|
+
verdict = "mixed";
|
|
103
|
+
else if (newlyIntroduced.length > 0)
|
|
104
|
+
verdict = "regression";
|
|
105
|
+
else if (fixed.length > 0)
|
|
106
|
+
verdict = stillFailing.length === 0 ? "clean" : "improved";
|
|
107
|
+
else
|
|
108
|
+
verdict = stillFailing.length === 0 ? "clean" : "unchanged";
|
|
109
|
+
if (notInBaseline.length > 0) {
|
|
110
|
+
warnings.push(`${notInBaseline.length} run(s) have no baseline to compare against and were excluded. ` +
|
|
111
|
+
"Their findings are in the report but not in this comparison.");
|
|
112
|
+
}
|
|
113
|
+
if (notInCurrent.length > 0) {
|
|
114
|
+
warnings.push(`${notInCurrent.length} run(s) in the baseline were not re-tested. A defect can only be ` +
|
|
115
|
+
"counted as fixed if the page was measured again.");
|
|
116
|
+
}
|
|
117
|
+
if (comparableRuns.size === 0) {
|
|
118
|
+
warnings.push("No run appears in both the baseline and this run, so nothing could be compared. " +
|
|
119
|
+
"Check that baseline_dir points at an index for the same URLs.");
|
|
120
|
+
}
|
|
121
|
+
// Score deltas, where the tool supplies them. Only for comparable runs, and
|
|
122
|
+
// only where both sides scored the category.
|
|
123
|
+
let scoreChanges;
|
|
124
|
+
if (options.baselineScores && options.currentScores) {
|
|
125
|
+
scoreChanges = [];
|
|
126
|
+
for (const runId of comparableRuns) {
|
|
127
|
+
const before = options.baselineScores.get(runId);
|
|
128
|
+
const after = options.currentScores.get(runId);
|
|
129
|
+
if (!before || !after)
|
|
130
|
+
continue;
|
|
131
|
+
const [url, variant] = runId.split("|");
|
|
132
|
+
for (const [category, afterScore] of Object.entries(after)) {
|
|
133
|
+
const beforeScore = before[category];
|
|
134
|
+
if (typeof beforeScore !== "number" || beforeScore === afterScore)
|
|
135
|
+
continue;
|
|
136
|
+
scoreChanges.push({
|
|
137
|
+
url,
|
|
138
|
+
variant,
|
|
139
|
+
category,
|
|
140
|
+
before: beforeScore,
|
|
141
|
+
after: afterScore,
|
|
142
|
+
delta: afterScore - beforeScore,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
scoreChanges.sort((a, b) => a.delta - b.delta);
|
|
147
|
+
if (scoreChanges.length === 0)
|
|
148
|
+
scoreChanges = undefined;
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
baseline_dir: baselineDir,
|
|
152
|
+
baseline_runs: baseRuns.size,
|
|
153
|
+
current_runs: curRuns.size,
|
|
154
|
+
verdict,
|
|
155
|
+
summary: describe(verdict, fixed.length, newlyIntroduced.length, stillFailing.length, worst(newlyIntroduced)),
|
|
156
|
+
fixed,
|
|
157
|
+
still_failing: stillFailing,
|
|
158
|
+
newly_introduced: newlyIntroduced,
|
|
159
|
+
...(scoreChanges ? { score_changes: scoreChanges } : {}),
|
|
160
|
+
not_in_baseline: notInBaseline,
|
|
161
|
+
not_in_current: notInCurrent,
|
|
162
|
+
warnings,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=runComparator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runComparator.js","sourceRoot":"","sources":["../../src/mappers/runComparator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WCAG 2.1 success criteria, their conformance levels, and how to get from a
|
|
3
|
+
* pa11y finding back to one.
|
|
4
|
+
*
|
|
5
|
+
* Levels are transcribed from the specification (https://www.w3.org/TR/WCAG21/)
|
|
6
|
+
* rather than inferred, because the whole priority scheme now rests on them: a
|
|
7
|
+
* criterion placed at the wrong level moves a finding between "blocks
|
|
8
|
+
* conformance" and "enhancement beyond the committed target", which is the
|
|
9
|
+
* difference between a release blocker and a backlog item.
|
|
10
|
+
*
|
|
11
|
+
* Levels are cumulative. AA conformance requires every Level A criterion *and*
|
|
12
|
+
* every Level AA one, so a single Level A failure makes AA conformance
|
|
13
|
+
* impossible no matter how clean the AA-specific criteria are. That is why a
|
|
14
|
+
* Level A failure outranks everything else here.
|
|
15
|
+
*/
|
|
16
|
+
export type WcagConformanceLevel = "A" | "AA" | "AAA";
|
|
17
|
+
export type TargetLevel = WcagConformanceLevel;
|
|
18
|
+
export interface Criterion {
|
|
19
|
+
number: string;
|
|
20
|
+
name: string;
|
|
21
|
+
level: WcagConformanceLevel;
|
|
22
|
+
}
|
|
23
|
+
/** All 78 WCAG 2.1 success criteria. */
|
|
24
|
+
declare const CRITERIA: Criterion[];
|
|
25
|
+
export declare function criterionByNumber(number: string): Criterion | null;
|
|
26
|
+
/**
|
|
27
|
+
* Pull the criterion out of an HTML_CodeSniffer code.
|
|
28
|
+
*
|
|
29
|
+
* htmlcs encodes it directly: "WCAG2AA.Principle1.Guideline1_1.1_1_1.H37"
|
|
30
|
+
* carries "1_1_1", which is criterion 1.1.1. Note the "WCAG2AA" prefix names
|
|
31
|
+
* the *standard being tested against*, not the criterion's level — reading it
|
|
32
|
+
* as a level is a mistake that would mark every finding AA.
|
|
33
|
+
*/
|
|
34
|
+
export declare function criterionFromHtmlcsCode(code: string): Criterion | null;
|
|
35
|
+
export declare function criterionFromAxeRule(ruleId: string): Criterion | null;
|
|
36
|
+
/** Resolve whichever engine produced the finding to a criterion. */
|
|
37
|
+
export declare function criterionFor(code: string, runner: "htmlcs" | "axe"): Criterion | null;
|
|
38
|
+
/** True when the criterion must be met to claim conformance at `target`. */
|
|
39
|
+
export declare function isRequiredFor(level: WcagConformanceLevel, target: TargetLevel): boolean;
|
|
40
|
+
export declare function levelRank(level: WcagConformanceLevel): number;
|
|
41
|
+
export { CRITERIA };
|
|
42
|
+
export interface FailedCriterion {
|
|
43
|
+
criterion: string;
|
|
44
|
+
name: string;
|
|
45
|
+
level: WcagConformanceLevel;
|
|
46
|
+
findings: number;
|
|
47
|
+
blocks_target: boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface ConformanceSummary {
|
|
50
|
+
target_level: TargetLevel;
|
|
51
|
+
conformant: boolean;
|
|
52
|
+
/** Distinct criteria failing, by level. Findings can be many per criterion. */
|
|
53
|
+
failing_criteria: Record<WcagConformanceLevel, number>;
|
|
54
|
+
/** Criteria above the committed target — enhancements, not gaps. */
|
|
55
|
+
beyond_target: number;
|
|
56
|
+
/** Findings that map to no success criterion at all. */
|
|
57
|
+
best_practice_only: number;
|
|
58
|
+
failed_criteria: FailedCriterion[];
|
|
59
|
+
summary: string;
|
|
60
|
+
}
|
|
61
|
+
interface FindingLike {
|
|
62
|
+
evidence: Record<string, unknown>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Roll findings up into a conformance verdict.
|
|
66
|
+
*
|
|
67
|
+
* The unit is the **criterion**, not the finding. Twelve findings against one
|
|
68
|
+
* criterion is one thing to fix and one line in a conformance statement; the
|
|
69
|
+
* finding count answers "how much work", the criterion count answers "are we
|
|
70
|
+
* conformant". Reporting only the former is how a report ends up saying a page
|
|
71
|
+
* has 22 accessibility issues when it fails five criteria.
|
|
72
|
+
*/
|
|
73
|
+
export declare function summariseConformance(findings: FindingLike[], target: TargetLevel): ConformanceSummary;
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WCAG 2.1 success criteria, their conformance levels, and how to get from a
|
|
3
|
+
* pa11y finding back to one.
|
|
4
|
+
*
|
|
5
|
+
* Levels are transcribed from the specification (https://www.w3.org/TR/WCAG21/)
|
|
6
|
+
* rather than inferred, because the whole priority scheme now rests on them: a
|
|
7
|
+
* criterion placed at the wrong level moves a finding between "blocks
|
|
8
|
+
* conformance" and "enhancement beyond the committed target", which is the
|
|
9
|
+
* difference between a release blocker and a backlog item.
|
|
10
|
+
*
|
|
11
|
+
* Levels are cumulative. AA conformance requires every Level A criterion *and*
|
|
12
|
+
* every Level AA one, so a single Level A failure makes AA conformance
|
|
13
|
+
* impossible no matter how clean the AA-specific criteria are. That is why a
|
|
14
|
+
* Level A failure outranks everything else here.
|
|
15
|
+
*/
|
|
16
|
+
/** All 78 WCAG 2.1 success criteria. */
|
|
17
|
+
const CRITERIA = [
|
|
18
|
+
{ number: "1.1.1", name: "Non-text Content", level: "A" },
|
|
19
|
+
{ number: "1.2.1", name: "Audio-only and Video-only (Prerecorded)", level: "A" },
|
|
20
|
+
{ number: "1.2.2", name: "Captions (Prerecorded)", level: "A" },
|
|
21
|
+
{ number: "1.2.3", name: "Audio Description or Media Alternative (Prerecorded)", level: "A" },
|
|
22
|
+
{ number: "1.2.4", name: "Captions (Live)", level: "AA" },
|
|
23
|
+
{ number: "1.2.5", name: "Audio Description (Prerecorded)", level: "AA" },
|
|
24
|
+
{ number: "1.2.6", name: "Sign Language (Prerecorded)", level: "AAA" },
|
|
25
|
+
{ number: "1.2.7", name: "Extended Audio Description (Prerecorded)", level: "AAA" },
|
|
26
|
+
{ number: "1.2.8", name: "Media Alternative (Prerecorded)", level: "AAA" },
|
|
27
|
+
{ number: "1.2.9", name: "Audio-only (Live)", level: "AAA" },
|
|
28
|
+
{ number: "1.3.1", name: "Info and Relationships", level: "A" },
|
|
29
|
+
{ number: "1.3.2", name: "Meaningful Sequence", level: "A" },
|
|
30
|
+
{ number: "1.3.3", name: "Sensory Characteristics", level: "A" },
|
|
31
|
+
{ number: "1.3.4", name: "Orientation", level: "AA" },
|
|
32
|
+
{ number: "1.3.5", name: "Identify Input Purpose", level: "AA" },
|
|
33
|
+
{ number: "1.3.6", name: "Identify Purpose", level: "AAA" },
|
|
34
|
+
{ number: "1.4.1", name: "Use of Color", level: "A" },
|
|
35
|
+
{ number: "1.4.2", name: "Audio Control", level: "A" },
|
|
36
|
+
{ number: "1.4.3", name: "Contrast (Minimum)", level: "AA" },
|
|
37
|
+
{ number: "1.4.4", name: "Resize Text", level: "AA" },
|
|
38
|
+
{ number: "1.4.5", name: "Images of Text", level: "AA" },
|
|
39
|
+
{ number: "1.4.6", name: "Contrast (Enhanced)", level: "AAA" },
|
|
40
|
+
{ number: "1.4.7", name: "Low or No Background Audio", level: "AAA" },
|
|
41
|
+
{ number: "1.4.8", name: "Visual Presentation", level: "AAA" },
|
|
42
|
+
{ number: "1.4.9", name: "Images of Text (No Exception)", level: "AAA" },
|
|
43
|
+
{ number: "1.4.10", name: "Reflow", level: "AA" },
|
|
44
|
+
{ number: "1.4.11", name: "Non-text Contrast", level: "AA" },
|
|
45
|
+
{ number: "1.4.12", name: "Text Spacing", level: "AA" },
|
|
46
|
+
{ number: "1.4.13", name: "Content on Hover or Focus", level: "AA" },
|
|
47
|
+
{ number: "2.1.1", name: "Keyboard", level: "A" },
|
|
48
|
+
{ number: "2.1.2", name: "No Keyboard Trap", level: "A" },
|
|
49
|
+
{ number: "2.1.3", name: "Keyboard (No Exception)", level: "AAA" },
|
|
50
|
+
{ number: "2.1.4", name: "Character Key Shortcuts", level: "A" },
|
|
51
|
+
{ number: "2.2.1", name: "Timing Adjustable", level: "A" },
|
|
52
|
+
{ number: "2.2.2", name: "Pause, Stop, Hide", level: "A" },
|
|
53
|
+
{ number: "2.2.3", name: "No Timing", level: "AAA" },
|
|
54
|
+
{ number: "2.2.4", name: "Interruptions", level: "AAA" },
|
|
55
|
+
{ number: "2.2.5", name: "Re-authenticating", level: "AAA" },
|
|
56
|
+
{ number: "2.2.6", name: "Timeouts", level: "AAA" },
|
|
57
|
+
{ number: "2.3.1", name: "Three Flashes or Below Threshold", level: "A" },
|
|
58
|
+
{ number: "2.3.2", name: "Three Flashes", level: "AAA" },
|
|
59
|
+
{ number: "2.3.3", name: "Animation from Interactions", level: "AAA" },
|
|
60
|
+
{ number: "2.4.1", name: "Bypass Blocks", level: "A" },
|
|
61
|
+
{ number: "2.4.2", name: "Page Titled", level: "A" },
|
|
62
|
+
{ number: "2.4.3", name: "Focus Order", level: "A" },
|
|
63
|
+
{ number: "2.4.4", name: "Link Purpose (In Context)", level: "A" },
|
|
64
|
+
{ number: "2.4.5", name: "Multiple Ways", level: "AA" },
|
|
65
|
+
{ number: "2.4.6", name: "Headings and Labels", level: "AA" },
|
|
66
|
+
{ number: "2.4.7", name: "Focus Visible", level: "AA" },
|
|
67
|
+
{ number: "2.4.8", name: "Location", level: "AAA" },
|
|
68
|
+
{ number: "2.4.9", name: "Link Purpose (Link Only)", level: "AAA" },
|
|
69
|
+
{ number: "2.4.10", name: "Section Headings", level: "AAA" },
|
|
70
|
+
{ number: "2.5.1", name: "Pointer Gestures", level: "A" },
|
|
71
|
+
{ number: "2.5.2", name: "Pointer Cancellation", level: "A" },
|
|
72
|
+
{ number: "2.5.3", name: "Label in Name", level: "A" },
|
|
73
|
+
{ number: "2.5.4", name: "Motion Actuation", level: "A" },
|
|
74
|
+
{ number: "2.5.5", name: "Target Size", level: "AAA" },
|
|
75
|
+
{ number: "2.5.6", name: "Concurrent Input Mechanisms", level: "AAA" },
|
|
76
|
+
{ number: "3.1.1", name: "Language of Page", level: "A" },
|
|
77
|
+
{ number: "3.1.2", name: "Language of Parts", level: "AA" },
|
|
78
|
+
{ number: "3.1.3", name: "Unusual Words", level: "AAA" },
|
|
79
|
+
{ number: "3.1.4", name: "Abbreviations", level: "AAA" },
|
|
80
|
+
{ number: "3.2.1", name: "On Focus", level: "A" },
|
|
81
|
+
{ number: "3.2.2", name: "On Input", level: "A" },
|
|
82
|
+
{ number: "3.2.3", name: "Consistent Navigation", level: "AA" },
|
|
83
|
+
{ number: "3.2.4", name: "Consistent Identification", level: "AA" },
|
|
84
|
+
{ number: "3.2.5", name: "Change on Request", level: "AAA" },
|
|
85
|
+
{ number: "3.3.1", name: "Error Identification", level: "A" },
|
|
86
|
+
{ number: "3.3.2", name: "Labels or Instructions", level: "A" },
|
|
87
|
+
{ number: "3.3.3", name: "Error Suggestion", level: "AA" },
|
|
88
|
+
{ number: "3.3.4", name: "Error Prevention (Legal, Financial, Data)", level: "AA" },
|
|
89
|
+
{ number: "3.3.5", name: "Help", level: "AAA" },
|
|
90
|
+
{ number: "3.3.6", name: "Error Prevention (All)", level: "AAA" },
|
|
91
|
+
{ number: "4.1.1", name: "Parsing", level: "A" },
|
|
92
|
+
{ number: "4.1.2", name: "Name, Role, Value", level: "A" },
|
|
93
|
+
{ number: "4.1.3", name: "Status Messages", level: "AA" },
|
|
94
|
+
];
|
|
95
|
+
const BY_NUMBER = new Map(CRITERIA.map((c) => [c.number, c]));
|
|
96
|
+
export function criterionByNumber(number) {
|
|
97
|
+
return BY_NUMBER.get(number) ?? null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* axe rule id → the success criterion it tests.
|
|
101
|
+
*
|
|
102
|
+
* pa11y's axe output carries `impact` and `needsFurtherReview` but **not** the
|
|
103
|
+
* WCAG tags axe itself attaches, so the mapping has to live here. Rules axe
|
|
104
|
+
* classifies as best-practice rather than as a WCAG criterion are mapped to
|
|
105
|
+
* null deliberately: reporting a best-practice rule as a conformance failure
|
|
106
|
+
* would overstate the legal position, which is the one thing a compliance
|
|
107
|
+
* report must not do.
|
|
108
|
+
*
|
|
109
|
+
* axe rule ids are identical to Lighthouse's accessibility audit ids, because
|
|
110
|
+
* Lighthouse runs axe internally — so this table serves both engines.
|
|
111
|
+
*/
|
|
112
|
+
const AXE_RULE_TO_CRITERION = {
|
|
113
|
+
// 1.1.1 Non-text Content
|
|
114
|
+
"image-alt": "1.1.1",
|
|
115
|
+
"input-image-alt": "1.1.1",
|
|
116
|
+
"area-alt": "1.1.1",
|
|
117
|
+
"object-alt": "1.1.1",
|
|
118
|
+
"svg-img-alt": "1.1.1",
|
|
119
|
+
"role-img-alt": "1.1.1",
|
|
120
|
+
"image-redundant-alt": null, // best practice
|
|
121
|
+
// 1.2.x media
|
|
122
|
+
"video-caption": "1.2.2",
|
|
123
|
+
"audio-caption": "1.2.1",
|
|
124
|
+
// 1.3.1 Info and Relationships
|
|
125
|
+
"aria-required-children": "1.3.1",
|
|
126
|
+
"aria-required-parent": "1.3.1",
|
|
127
|
+
list: "1.3.1",
|
|
128
|
+
listitem: "1.3.1",
|
|
129
|
+
"definition-list": "1.3.1",
|
|
130
|
+
dlitem: "1.3.1",
|
|
131
|
+
"td-headers-attr": "1.3.1",
|
|
132
|
+
"th-has-data-cells": "1.3.1",
|
|
133
|
+
"table-fake-caption": "1.3.1",
|
|
134
|
+
"td-has-header": "1.3.1",
|
|
135
|
+
// 1.3.4 / 1.3.5
|
|
136
|
+
"css-orientation-lock": "1.3.4",
|
|
137
|
+
"autocomplete-valid": "1.3.5",
|
|
138
|
+
// 1.4.x contrast and text
|
|
139
|
+
"link-in-text-block": "1.4.1",
|
|
140
|
+
"color-contrast": "1.4.3",
|
|
141
|
+
"color-contrast-enhanced": "1.4.6",
|
|
142
|
+
"meta-viewport": "1.4.4",
|
|
143
|
+
"meta-viewport-large": null, // best practice
|
|
144
|
+
"avoid-inline-spacing": "1.4.12",
|
|
145
|
+
// 2.1.x keyboard
|
|
146
|
+
accesskeys: null, // best practice
|
|
147
|
+
"scrollable-region-focusable": "2.1.1",
|
|
148
|
+
"frame-focusable-content": "2.1.1",
|
|
149
|
+
"server-side-image-map": "2.1.1",
|
|
150
|
+
// 2.2.x timing
|
|
151
|
+
"meta-refresh": "2.2.1",
|
|
152
|
+
"meta-refresh-no-exceptions": "2.2.4",
|
|
153
|
+
marquee: "2.2.2",
|
|
154
|
+
blink: "2.2.2",
|
|
155
|
+
// 2.4.x navigation
|
|
156
|
+
bypass: "2.4.1",
|
|
157
|
+
"document-title": "2.4.2",
|
|
158
|
+
"link-name": "2.4.4",
|
|
159
|
+
"frame-title": "4.1.2",
|
|
160
|
+
"frame-title-unique": "4.1.2",
|
|
161
|
+
"landmark-one-main": null, // best practice
|
|
162
|
+
region: null, // best practice
|
|
163
|
+
"page-has-heading-one": null, // best practice
|
|
164
|
+
"heading-order": null, // best practice
|
|
165
|
+
"empty-heading": null, // best practice
|
|
166
|
+
"identical-links-same-purpose": "2.4.9",
|
|
167
|
+
// 2.5.x input modality
|
|
168
|
+
"label-content-name-mismatch": "2.5.3",
|
|
169
|
+
"target-size": "2.5.5", // AAA in WCAG 2.1 — see note in levelForAxeRule
|
|
170
|
+
// 3.1.x language
|
|
171
|
+
"html-has-lang": "3.1.1",
|
|
172
|
+
"html-lang-valid": "3.1.1",
|
|
173
|
+
"html-xml-lang-mismatch": "3.1.1",
|
|
174
|
+
"valid-lang": "3.1.2",
|
|
175
|
+
// 3.3.x forms
|
|
176
|
+
"form-field-multiple-labels": "3.3.2",
|
|
177
|
+
label: "4.1.2",
|
|
178
|
+
"label-title-only": null, // best practice
|
|
179
|
+
// 4.1.x robust
|
|
180
|
+
"duplicate-id": "4.1.1",
|
|
181
|
+
"duplicate-id-active": "4.1.1",
|
|
182
|
+
"duplicate-id-aria": "4.1.1",
|
|
183
|
+
"aria-allowed-attr": "4.1.2",
|
|
184
|
+
"aria-allowed-role": null, // best practice
|
|
185
|
+
"aria-prohibited-attr": "4.1.2",
|
|
186
|
+
"aria-required-attr": "4.1.2",
|
|
187
|
+
"aria-roles": "4.1.2",
|
|
188
|
+
"aria-valid-attr": "4.1.2",
|
|
189
|
+
"aria-valid-attr-value": "4.1.2",
|
|
190
|
+
"aria-hidden-body": "4.1.2",
|
|
191
|
+
"aria-hidden-focus": "4.1.2",
|
|
192
|
+
"aria-input-field-name": "4.1.2",
|
|
193
|
+
"aria-toggle-field-name": "4.1.2",
|
|
194
|
+
"aria-command-name": "4.1.2",
|
|
195
|
+
"aria-meter-name": "4.1.2",
|
|
196
|
+
"aria-progressbar-name": "4.1.2",
|
|
197
|
+
"aria-tooltip-name": "4.1.2",
|
|
198
|
+
"aria-dialog-name": "4.1.2",
|
|
199
|
+
"aria-text": "4.1.2",
|
|
200
|
+
"aria-treeitem-name": "4.1.2",
|
|
201
|
+
"button-name": "4.1.2",
|
|
202
|
+
"select-name": "4.1.2",
|
|
203
|
+
"input-button-name": "4.1.2",
|
|
204
|
+
"nested-interactive": "4.1.2",
|
|
205
|
+
"presentation-role-conflict": null, // best practice
|
|
206
|
+
"aria-braille-equivalent": null, // best practice
|
|
207
|
+
"empty-table-header": null, // best practice
|
|
208
|
+
"frame-tested": null, // not a criterion
|
|
209
|
+
"aria-status": "4.1.3",
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* Pull the criterion out of an HTML_CodeSniffer code.
|
|
213
|
+
*
|
|
214
|
+
* htmlcs encodes it directly: "WCAG2AA.Principle1.Guideline1_1.1_1_1.H37"
|
|
215
|
+
* carries "1_1_1", which is criterion 1.1.1. Note the "WCAG2AA" prefix names
|
|
216
|
+
* the *standard being tested against*, not the criterion's level — reading it
|
|
217
|
+
* as a level is a mistake that would mark every finding AA.
|
|
218
|
+
*/
|
|
219
|
+
export function criterionFromHtmlcsCode(code) {
|
|
220
|
+
const match = /Guideline\d+_\d+\.(\d+)_(\d+)_(\d+)/.exec(code);
|
|
221
|
+
if (!match)
|
|
222
|
+
return null;
|
|
223
|
+
return criterionByNumber(`${match[1]}.${match[2]}.${match[3]}`);
|
|
224
|
+
}
|
|
225
|
+
export function criterionFromAxeRule(ruleId) {
|
|
226
|
+
const number = AXE_RULE_TO_CRITERION[ruleId];
|
|
227
|
+
if (!number)
|
|
228
|
+
return null;
|
|
229
|
+
return criterionByNumber(number);
|
|
230
|
+
}
|
|
231
|
+
/** Resolve whichever engine produced the finding to a criterion. */
|
|
232
|
+
export function criterionFor(code, runner) {
|
|
233
|
+
return runner === "axe" ? criterionFromAxeRule(code) : criterionFromHtmlcsCode(code);
|
|
234
|
+
}
|
|
235
|
+
const ORDER = { A: 0, AA: 1, AAA: 2 };
|
|
236
|
+
/** True when the criterion must be met to claim conformance at `target`. */
|
|
237
|
+
export function isRequiredFor(level, target) {
|
|
238
|
+
return ORDER[level] <= ORDER[target];
|
|
239
|
+
}
|
|
240
|
+
export function levelRank(level) {
|
|
241
|
+
return ORDER[level];
|
|
242
|
+
}
|
|
243
|
+
export { CRITERIA };
|
|
244
|
+
/**
|
|
245
|
+
* Roll findings up into a conformance verdict.
|
|
246
|
+
*
|
|
247
|
+
* The unit is the **criterion**, not the finding. Twelve findings against one
|
|
248
|
+
* criterion is one thing to fix and one line in a conformance statement; the
|
|
249
|
+
* finding count answers "how much work", the criterion count answers "are we
|
|
250
|
+
* conformant". Reporting only the former is how a report ends up saying a page
|
|
251
|
+
* has 22 accessibility issues when it fails five criteria.
|
|
252
|
+
*/
|
|
253
|
+
export function summariseConformance(findings, target) {
|
|
254
|
+
const byCriterion = new Map();
|
|
255
|
+
let bestPracticeOnly = 0;
|
|
256
|
+
for (const finding of findings) {
|
|
257
|
+
const number = finding.evidence["wcag_criterion"];
|
|
258
|
+
if (typeof number !== "string") {
|
|
259
|
+
bestPracticeOnly++;
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
const criterion = criterionByNumber(number);
|
|
263
|
+
if (!criterion) {
|
|
264
|
+
bestPracticeOnly++;
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const existing = byCriterion.get(number);
|
|
268
|
+
if (existing)
|
|
269
|
+
existing.findings++;
|
|
270
|
+
else
|
|
271
|
+
byCriterion.set(number, {
|
|
272
|
+
criterion: number,
|
|
273
|
+
name: criterion.name,
|
|
274
|
+
level: criterion.level,
|
|
275
|
+
findings: 1,
|
|
276
|
+
blocks_target: isRequiredFor(criterion.level, target),
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
const failed = [...byCriterion.values()].sort((a, b) => ORDER[a.level] - ORDER[b.level] || a.criterion.localeCompare(b.criterion));
|
|
280
|
+
const blocking = failed.filter((f) => f.blocks_target);
|
|
281
|
+
const failing = { A: 0, AA: 0, AAA: 0 };
|
|
282
|
+
for (const f of blocking)
|
|
283
|
+
failing[f.level]++;
|
|
284
|
+
const beyond = failed.length - blocking.length;
|
|
285
|
+
const conformant = blocking.length === 0;
|
|
286
|
+
const criteria = (n) => (n === 1 ? "criterion" : "criteria");
|
|
287
|
+
let summary;
|
|
288
|
+
if (conformant) {
|
|
289
|
+
summary =
|
|
290
|
+
`No Level ${target} conformance failures detected by automated testing. ` +
|
|
291
|
+
`This is not the same as being conformant — automated tools cover roughly a third of ` +
|
|
292
|
+
`WCAG criteria, and the rest need manual verification.`;
|
|
293
|
+
}
|
|
294
|
+
else if (failing.A > 0) {
|
|
295
|
+
summary =
|
|
296
|
+
`Not Level ${target} conformant. ${failing.A} Level A ${criteria(failing.A)} ` +
|
|
297
|
+
`${failing.A === 1 ? "fails" : "fail"}` +
|
|
298
|
+
(failing.AA > 0 ? `, plus ${failing.AA} at Level AA` : "") +
|
|
299
|
+
`. Level A is the floor — while any Level A criterion fails, Level ${target} conformance is ` +
|
|
300
|
+
`unreachable no matter how the remaining criteria score, so fix those first.`;
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
summary =
|
|
304
|
+
`Not Level ${target} conformant. Level A is fully met, but ${failing.AA} Level AA ` +
|
|
305
|
+
`${criteria(failing.AA)} ${failing.AA === 1 ? "fails" : "fail"}.`;
|
|
306
|
+
}
|
|
307
|
+
if (beyond > 0) {
|
|
308
|
+
summary += ` ${beyond} ${criteria(beyond)} above Level ${target} also failed; those are enhancements, not gaps.`;
|
|
309
|
+
}
|
|
310
|
+
return {
|
|
311
|
+
target_level: target,
|
|
312
|
+
conformant,
|
|
313
|
+
failing_criteria: failing,
|
|
314
|
+
beyond_target: beyond,
|
|
315
|
+
best_practice_only: bestPracticeOnly,
|
|
316
|
+
failed_criteria: failed,
|
|
317
|
+
summary,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
//# sourceMappingURL=wcagLevels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wcagLevels.js","sourceRoot":"","sources":["../../src/mappers/wcagLevels.ts"],"names":[],"mappings":"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"}
|