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.
@@ -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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"}
@@ -1,2 +1,3 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export type A11yFormFactor = "desktop" | "mobile";
2
3
  export declare function registerAccessibilityTool(server: McpServer): void;