@diegovelasquezweb/a11y-engine 0.1.8 → 0.2.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/CHANGELOG.md +31 -0
- package/README.md +190 -152
- package/docs/architecture.md +22 -0
- package/docs/cli-handbook.md +4 -0
- package/docs/outputs.md +37 -23
- package/package.json +1 -1
- package/scripts/engine/analyzer.mjs +40 -14
- package/scripts/engine/dom-scanner.mjs +56 -3
- package/scripts/engine/source-scanner.mjs +1 -1
- package/scripts/index.d.mts +139 -3
- package/scripts/index.mjs +527 -79
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Programmatic API** — 7 exported functions accessible via `import { ... } from "@diegovelasquezweb/a11y-engine"`:
|
|
13
|
+
- `getEnrichedFindings(input, options?)` — normalizes raw findings, canonicalizes pa11y rules, enriches with fix intelligence, infers effort, sorts by severity. Accepts a full scan payload or a raw findings array. Supports `screenshotUrlBuilder` callback for consumer-specific screenshot URLs.
|
|
14
|
+
- `getAuditSummary(findings, payload?)` — computes severity totals, compliance score, grade label, WCAG pass/fail status, persona impact groups, quick wins, target URL, and detected stack from metadata.
|
|
15
|
+
- `getPDFReport(payload, options?)` — generates a formal A4 PDF compliance report via Playwright. Returns `{ buffer, contentType }`.
|
|
16
|
+
- `getChecklist(options?)` — generates a standalone manual accessibility testing checklist as HTML. Returns `{ html, contentType }`.
|
|
17
|
+
- `getHTMLReport(payload, options?)` — generates an interactive HTML audit dashboard with severity filters and fix guidance. Supports embedded base64 screenshots via `screenshotsDir`. Returns `{ html, contentType }`.
|
|
18
|
+
- `getRemediationGuide(payload, options?)` — generates a Markdown remediation guide optimized for AI agents. Supports optional `patternFindings` from source scanner. Returns `{ markdown, contentType }`.
|
|
19
|
+
- `getSourcePatterns(projectDir, options?)` — scans project source code for accessibility patterns not detectable by axe-core. Returns `{ findings, summary }`.
|
|
20
|
+
- **TypeScript type declarations** shipped with the package (`scripts/index.d.mts`):
|
|
21
|
+
- `Finding` — raw finding with all snake_case fields
|
|
22
|
+
- `EnrichedFinding` — extends Finding with camelCase aliases and enriched fields
|
|
23
|
+
- `AuditSummary` — full audit summary including totals, score, personas, quick wins, detected stack
|
|
24
|
+
- `SeverityTotals`, `PersonaGroup`, `DetectedStack`, `ComplianceScore`
|
|
25
|
+
- `ScanPayload`, `EnrichmentOptions`, `ReportOptions`
|
|
26
|
+
- `PDFReport`, `HTMLReport`, `ChecklistReport`, `RemediationGuide`
|
|
27
|
+
- `SourcePatternFinding`, `SourcePatternResult`, `SourcePatternOptions`
|
|
28
|
+
- `exports` and `main` fields in `package.json` pointing to `scripts/index.mjs`
|
|
29
|
+
- `--axe-tags` CLI flag passthrough from `audit.mjs` to `dom-scanner.mjs`
|
|
30
|
+
- `resolveScanDirs` exported from `source-scanner.mjs` for programmatic use
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- `getEnrichedFindings` always creates camelCase aliases (`fixDescription`, `fixCode`, `screenshotPath`, `wcagCriterionId`, `impactedUsers`, etc.) regardless of whether the finding already has fix data — fixes bug where camelCase fields were `undefined` when snake_case data existed
|
|
35
|
+
- `getEnrichedFindings` infers `effort` field after intelligence enrichment: findings with `fixCode` default to `"low"`, others to `"high"` — unless an explicit effort value already exists
|
|
36
|
+
- `getEnrichedFindings` normalizes raw findings internally — consumers no longer need to pre-process the findings array
|
|
37
|
+
- `getEnrichedFindings` sorts findings by severity (Critical > Serious > Moderate > Minor) then by ID
|
|
38
|
+
- `getAuditSummary` now includes `quickWins` (top 3 Critical/Serious findings with fix code), `targetUrl` (extracted from metadata with fallbacks), and `detectedStack` (framework/CMS/libraries from project context)
|
|
39
|
+
- CLI (`audit.mjs`) continues to work standalone — the programmatic API is additive
|
|
40
|
+
|
|
10
41
|
---
|
|
11
42
|
|
|
12
43
|
## [0.1.3] — 2026-03-14
|
package/README.md
CHANGED
|
@@ -1,176 +1,218 @@
|
|
|
1
1
|
# @diegovelasquezweb/a11y-engine
|
|
2
2
|
|
|
3
|
-
Multi-engine WCAG 2.2
|
|
3
|
+
Multi-engine WCAG 2.2 accessibility audit engine. Combines three scanning engines (axe-core, Chrome DevTools Protocol, and pa11y), merges and deduplicates their findings, enriches results with fix intelligence, and produces structured artifacts for developers, agents, and stakeholders.
|
|
4
4
|
|
|
5
5
|
## What it is
|
|
6
6
|
|
|
7
|
-
A Node.js
|
|
7
|
+
A Node.js package that works two ways:
|
|
8
8
|
|
|
9
|
-
1.
|
|
10
|
-
2.
|
|
11
|
-
- **axe-core** — industry-standard WCAG rule engine, injected into the live page via Playwright
|
|
12
|
-
- **CDP** (Chrome DevTools Protocol) — queries the browser's accessibility tree directly for issues axe may miss (missing accessible names, aria-hidden on focusable elements)
|
|
13
|
-
- **pa11y** (HTML CodeSniffer) — catches WCAG violations around heading hierarchy, link purpose, and form associations
|
|
14
|
-
3. Merges and deduplicates findings across all three engines
|
|
15
|
-
4. Optionally scans project source code for patterns no runtime engine can detect
|
|
16
|
-
5. Enriches each finding with stack-aware fix guidance, selectors, and verification commands
|
|
17
|
-
6. Produces a full artifact set: JSON data, Markdown remediation guide, HTML dashboard, PDF compliance report, and manual testing checklist
|
|
9
|
+
1. **CLI** — run `npx a11y-audit --base-url <url>` to scan a site and generate reports
|
|
10
|
+
2. **Programmatic API** — import functions directly to normalize findings, compute scores, and generate reports in your own application
|
|
18
11
|
|
|
19
|
-
##
|
|
12
|
+
## Programmatic API
|
|
20
13
|
|
|
21
|
-
|
|
14
|
+
```bash
|
|
15
|
+
npm install @diegovelasquezweb/a11y-engine
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import {
|
|
20
|
+
getEnrichedFindings,
|
|
21
|
+
getAuditSummary,
|
|
22
|
+
getPDFReport,
|
|
23
|
+
getChecklist,
|
|
24
|
+
getHTMLReport,
|
|
25
|
+
getRemediationGuide,
|
|
26
|
+
getSourcePatterns,
|
|
27
|
+
} from "@diegovelasquezweb/a11y-engine";
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### getEnrichedFindings
|
|
31
|
+
|
|
32
|
+
Normalizes raw scan findings, canonicalizes pa11y rules to axe equivalents, enriches with fix intelligence, infers effort, and sorts by severity.
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
const findings = getEnrichedFindings(scanPayload, {
|
|
36
|
+
screenshotUrlBuilder: (path) => `/api/screenshot?path=${encodeURIComponent(path)}`,
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
| Parameter | Type | Description |
|
|
22
41
|
| :--- | :--- | :--- |
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
| **Fix Intelligence** | Stack-aware patches with code snippets tailored to detected framework | Raw rule violations with no remediation context |
|
|
26
|
-
| **Structured Artifacts** | JSON + Markdown + HTML + PDF + Checklist — ready to consume or forward | Findings exist only in the terminal session |
|
|
27
|
-
| **CI/Agent Integration** | Deterministic exit codes, stdout-parseable output paths, JSON schema | Requires wrapper scripting |
|
|
42
|
+
| `input` | `ScanPayload \| Finding[] \| Record<string, unknown>[]` | Raw scan output or findings array |
|
|
43
|
+
| `options.screenshotUrlBuilder` | `(rawPath: string) => string` | Transforms screenshot file paths into consumer-specific URLs |
|
|
28
44
|
|
|
29
|
-
|
|
45
|
+
**Returns**: `EnrichedFinding[]` — normalized, enriched, sorted findings with both snake_case and camelCase fields.
|
|
46
|
+
|
|
47
|
+
### getAuditSummary
|
|
48
|
+
|
|
49
|
+
Computes a complete audit summary from enriched findings.
|
|
30
50
|
|
|
51
|
+
```ts
|
|
52
|
+
const summary = getAuditSummary(findings, scanPayload);
|
|
53
|
+
// summary.score → 72
|
|
54
|
+
// summary.label → "Good"
|
|
55
|
+
// summary.wcagStatus → "Fail"
|
|
56
|
+
// summary.totals → { Critical: 1, Serious: 3, Moderate: 5, Minor: 2 }
|
|
57
|
+
// summary.personaGroups → { screenReader: {...}, keyboard: {...}, ... }
|
|
58
|
+
// summary.quickWins → [top 3 fixable Critical/Serious findings]
|
|
59
|
+
// summary.targetUrl → "https://example.com"
|
|
60
|
+
// summary.detectedStack → { framework: "nextjs", cms: null, uiLibraries: [] }
|
|
31
61
|
```
|
|
32
|
-
|
|
33
|
-
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
v
|
|
50
|
-
[4. Analyze] Enriches with WCAG mapping, severity, fix code, framework hints
|
|
51
|
-
|
|
|
52
|
-
v
|
|
53
|
-
[5. Reports] HTML dashboard, PDF, checklist, Markdown remediation
|
|
62
|
+
|
|
63
|
+
| Parameter | Type | Description |
|
|
64
|
+
| :--- | :--- | :--- |
|
|
65
|
+
| `findings` | `EnrichedFinding[]` | Output from `getEnrichedFindings` |
|
|
66
|
+
| `payload` | `ScanPayload \| null` | Original scan payload for metadata extraction |
|
|
67
|
+
|
|
68
|
+
**Returns**: `AuditSummary`
|
|
69
|
+
|
|
70
|
+
### getPDFReport
|
|
71
|
+
|
|
72
|
+
Generates a formal A4 PDF compliance report using Playwright.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
const { buffer, contentType } = await getPDFReport(scanPayload, {
|
|
76
|
+
baseUrl: "https://example.com",
|
|
77
|
+
});
|
|
78
|
+
fs.writeFileSync("report.pdf", buffer);
|
|
54
79
|
```
|
|
55
80
|
|
|
56
|
-
|
|
81
|
+
**Returns**: `Promise<PDFReport>` — `{ buffer: Buffer, contentType: "application/pdf" }`
|
|
57
82
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
83
|
+
### getHTMLReport
|
|
84
|
+
|
|
85
|
+
Generates an interactive HTML audit dashboard with severity filters, persona impact, and fix guidance.
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
const { html, contentType } = await getHTMLReport(scanPayload, {
|
|
89
|
+
baseUrl: "https://example.com",
|
|
90
|
+
screenshotsDir: "/path/to/.audit/screenshots",
|
|
91
|
+
});
|
|
62
92
|
```
|
|
63
93
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
94
|
+
**Returns**: `Promise<HTMLReport>` — `{ html: string, contentType: "text/html" }`
|
|
95
|
+
|
|
96
|
+
### getChecklist
|
|
97
|
+
|
|
98
|
+
Generates a standalone manual accessibility testing checklist.
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
const { html, contentType } = await getChecklist({
|
|
102
|
+
baseUrl: "https://example.com",
|
|
103
|
+
});
|
|
68
104
|
```
|
|
69
105
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
106
|
+
**Returns**: `Promise<ChecklistReport>` — `{ html: string, contentType: "text/html" }`
|
|
107
|
+
|
|
108
|
+
### getRemediationGuide
|
|
109
|
+
|
|
110
|
+
Generates a Markdown remediation guide optimized for AI agents.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
const { markdown, contentType } = await getRemediationGuide(scanPayload, {
|
|
114
|
+
baseUrl: "https://example.com",
|
|
115
|
+
patternFindings: sourcePatternResult,
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Returns**: `Promise<RemediationGuide>` — `{ markdown: string, contentType: "text/markdown" }`
|
|
120
|
+
|
|
121
|
+
### getSourcePatterns
|
|
122
|
+
|
|
123
|
+
Scans project source code for accessibility patterns not detectable by axe-core at runtime.
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
const { findings, summary } = await getSourcePatterns("/path/to/project", {
|
|
127
|
+
framework: "nextjs",
|
|
128
|
+
});
|
|
129
|
+
// summary → { total: 12, confirmed: 10, potential: 2 }
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Returns**: `Promise<SourcePatternResult>` — `{ findings: SourcePatternFinding[], summary: { total, confirmed, potential } }`
|
|
133
|
+
|
|
134
|
+
## CLI usage
|
|
75
135
|
|
|
76
|
-
|
|
136
|
+
The CLI runs the full scan pipeline: crawl, scan with 3 engines, merge, analyze, and generate reports.
|
|
77
137
|
|
|
78
138
|
```bash
|
|
79
|
-
# Minimal scan
|
|
139
|
+
# Minimal scan
|
|
80
140
|
npx a11y-audit --base-url https://example.com
|
|
81
141
|
|
|
82
142
|
# Full audit with all reports
|
|
83
143
|
npx a11y-audit --base-url https://example.com --with-reports --output ./audit/report.html
|
|
84
144
|
|
|
85
|
-
# Scan with source code intelligence
|
|
145
|
+
# Scan with source code intelligence
|
|
86
146
|
npx a11y-audit --base-url http://localhost:3000 --project-dir . --with-reports --output ./audit/report.html
|
|
87
147
|
```
|
|
88
148
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
```
|
|
92
|
-
a11y-audit --base-url <url> [options]
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### Targeting & scope
|
|
149
|
+
### Targeting and scope
|
|
96
150
|
|
|
97
151
|
| Flag | Argument | Default | Description |
|
|
98
152
|
| :--- | :--- | :--- | :--- |
|
|
99
|
-
| `--base-url` | `<url>` | (Required) | Starting URL for the audit
|
|
100
|
-
| `--max-routes` | `<num>` | `10` | Max routes to discover and scan
|
|
101
|
-
| `--crawl-depth` | `<num>` | `2` | BFS link-follow depth during discovery (1-3)
|
|
102
|
-
| `--routes` | `<csv>` | — | Explicit path list, bypasses auto-discovery
|
|
103
|
-
| `--project-dir` | `<path>` | — | Path to project source
|
|
153
|
+
| `--base-url` | `<url>` | (Required) | Starting URL for the audit |
|
|
154
|
+
| `--max-routes` | `<num>` | `10` | Max routes to discover and scan |
|
|
155
|
+
| `--crawl-depth` | `<num>` | `2` | BFS link-follow depth during discovery (1-3) |
|
|
156
|
+
| `--routes` | `<csv>` | — | Explicit path list, bypasses auto-discovery |
|
|
157
|
+
| `--project-dir` | `<path>` | — | Path to project source for stack-aware fixes and source pattern scanning |
|
|
104
158
|
|
|
105
159
|
### Audit intelligence
|
|
106
160
|
|
|
107
161
|
| Flag | Argument | Default | Description |
|
|
108
162
|
| :--- | :--- | :--- | :--- |
|
|
109
|
-
| `--target` | `<text>` | `WCAG 2.2 AA` | Compliance target label in reports
|
|
110
|
-
| `--
|
|
111
|
-
| `--
|
|
112
|
-
| `--
|
|
113
|
-
| `--
|
|
114
|
-
| `--framework` | `<name>` | — | Override auto-detected stack
|
|
163
|
+
| `--target` | `<text>` | `WCAG 2.2 AA` | Compliance target label in reports |
|
|
164
|
+
| `--axe-tags` | `<csv>` | `wcag2a,wcag2aa,wcag21a,wcag21aa,wcag22a,wcag22aa` | axe-core WCAG tag filter |
|
|
165
|
+
| `--only-rule` | `<id>` | — | Run a single axe rule (e.g. `color-contrast`) |
|
|
166
|
+
| `--ignore-findings` | `<csv>` | — | Rule IDs to exclude from output |
|
|
167
|
+
| `--exclude-selectors` | `<csv>` | — | CSS selectors to skip during DOM scan |
|
|
168
|
+
| `--framework` | `<name>` | — | Override auto-detected stack (`nextjs`, `react`, `vue`, `angular`, `svelte`, `shopify`, `wordpress`, etc.) |
|
|
115
169
|
|
|
116
|
-
### Execution
|
|
170
|
+
### Execution and emulation
|
|
117
171
|
|
|
118
172
|
| Flag | Argument | Default | Description |
|
|
119
173
|
| :--- | :--- | :--- | :--- |
|
|
120
|
-
| `--color-scheme` | `light\|dark` | `light` | Emulate `prefers-color-scheme
|
|
121
|
-
| `--wait-until` | `domcontentloaded\|load\|networkidle` | `domcontentloaded` | Playwright page load strategy
|
|
122
|
-
| `--viewport` | `<WxH>` | — | Viewport size (e.g. `375x812
|
|
123
|
-
| `--wait-ms` | `<num>` | `2000` | Delay after page load before
|
|
124
|
-
| `--timeout-ms` | `<num>` | `30000` | Network timeout per page (ms)
|
|
125
|
-
| `--headed` | — | `false` | Run browser in visible mode
|
|
126
|
-
| `--affected-only` | — | `false` | Re-scan only routes with previous violations
|
|
174
|
+
| `--color-scheme` | `light\|dark` | `light` | Emulate `prefers-color-scheme` |
|
|
175
|
+
| `--wait-until` | `domcontentloaded\|load\|networkidle` | `domcontentloaded` | Playwright page load strategy |
|
|
176
|
+
| `--viewport` | `<WxH>` | — | Viewport size (e.g. `375x812`) |
|
|
177
|
+
| `--wait-ms` | `<num>` | `2000` | Delay after page load before scanning (ms) |
|
|
178
|
+
| `--timeout-ms` | `<num>` | `30000` | Network timeout per page (ms) |
|
|
179
|
+
| `--headed` | — | `false` | Run browser in visible mode |
|
|
180
|
+
| `--affected-only` | — | `false` | Re-scan only routes with previous violations |
|
|
127
181
|
|
|
128
182
|
### Output generation
|
|
129
183
|
|
|
130
184
|
| Flag | Argument | Default | Description |
|
|
131
185
|
| :--- | :--- | :--- | :--- |
|
|
132
|
-
| `--with-reports` | — | `false` | Generate HTML + PDF + Checklist reports
|
|
133
|
-
| `--
|
|
134
|
-
| `--
|
|
135
|
-
| `--skip-patterns` | — | `false` | Disable source code pattern scanner even when `--project-dir` is set. |
|
|
136
|
-
|
|
137
|
-
## Common command patterns
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
# Focused audit — one rule, one route
|
|
141
|
-
a11y-audit --base-url https://example.com --only-rule color-contrast --routes /checkout --max-routes 1
|
|
142
|
-
|
|
143
|
-
# Dark mode audit
|
|
144
|
-
a11y-audit --base-url https://example.com --color-scheme dark
|
|
186
|
+
| `--with-reports` | — | `false` | Generate HTML + PDF + Checklist reports |
|
|
187
|
+
| `--output` | `<path>` | — | Output path for `report.html` |
|
|
188
|
+
| `--skip-patterns` | — | `false` | Disable source code pattern scanner |
|
|
145
189
|
|
|
146
|
-
|
|
147
|
-
a11y-audit --base-url https://example.com --wait-until networkidle --wait-ms 3000
|
|
148
|
-
|
|
149
|
-
# Mobile viewport
|
|
150
|
-
a11y-audit --base-url https://example.com --viewport 375x812
|
|
151
|
-
|
|
152
|
-
# Fast re-audit after fixes (skips clean pages)
|
|
153
|
-
a11y-audit --base-url https://example.com --affected-only
|
|
190
|
+
## How the scan pipeline works
|
|
154
191
|
|
|
155
|
-
# Ignore known false positives
|
|
156
|
-
a11y-audit --base-url https://example.com --ignore-findings color-contrast,frame-title
|
|
157
192
|
```
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
193
|
+
URL
|
|
194
|
+
|
|
|
195
|
+
v
|
|
196
|
+
[1. Crawl & Discover] sitemap.xml / BFS link crawl / explicit --routes
|
|
197
|
+
|
|
|
198
|
+
v
|
|
199
|
+
[2. Navigate] Playwright opens each route in Chromium
|
|
200
|
+
|
|
|
201
|
+
+---> [axe-core] Injects axe into the page, runs WCAG tag checks
|
|
202
|
+
|
|
|
203
|
+
+---> [CDP] Opens a CDP session, reads the full accessibility tree
|
|
204
|
+
|
|
|
205
|
+
+---> [pa11y] Launches HTML CodeSniffer via Puppeteer Chrome
|
|
206
|
+
|
|
|
207
|
+
v
|
|
208
|
+
[3. Merge & Dedup] Combines findings, removes cross-engine duplicates
|
|
209
|
+
|
|
|
210
|
+
v
|
|
211
|
+
[4. Analyze] Enriches with WCAG mapping, severity, fix code, framework hints
|
|
212
|
+
|
|
|
213
|
+
v
|
|
214
|
+
[5. Reports] HTML dashboard, PDF, checklist, Markdown remediation
|
|
215
|
+
```
|
|
174
216
|
|
|
175
217
|
## Scan engines
|
|
176
218
|
|
|
@@ -181,52 +223,48 @@ The primary engine. Runs Deque's axe-core rule set against the live DOM inside P
|
|
|
181
223
|
### CDP (Chrome DevTools Protocol)
|
|
182
224
|
|
|
183
225
|
Queries the browser's full accessibility tree via a CDP session. Catches issues axe may miss:
|
|
184
|
-
- Interactive elements
|
|
226
|
+
- Interactive elements with no accessible name
|
|
185
227
|
- Focusable elements hidden with `aria-hidden`
|
|
186
228
|
|
|
187
229
|
### pa11y (HTML CodeSniffer)
|
|
188
230
|
|
|
189
|
-
Runs Squiz's HTML CodeSniffer via Puppeteer Chrome. Catches WCAG violations around
|
|
190
|
-
- Heading hierarchy
|
|
191
|
-
- Link purpose
|
|
192
|
-
- Form label associations
|
|
231
|
+
Runs Squiz's HTML CodeSniffer via Puppeteer Chrome. Catches WCAG violations around heading hierarchy, link purpose, and form label associations.
|
|
193
232
|
|
|
194
233
|
Requires a separate Chrome installation (`npx puppeteer browsers install chrome`). If Chrome is missing, pa11y fails silently and the scan continues with axe + CDP.
|
|
195
234
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
After all three engines run, findings are merged and deduplicated:
|
|
199
|
-
- axe findings are added first (baseline)
|
|
200
|
-
- CDP findings are checked against axe equivalents (e.g. `cdp-missing-accessible-name` vs `button-name`) to avoid duplicates
|
|
201
|
-
- pa11y findings are checked against existing selectors to avoid triple-reporting the same element
|
|
202
|
-
|
|
203
|
-
## Troubleshooting
|
|
204
|
-
|
|
205
|
-
**`Error: browserType.launch: Executable doesn't exist`**
|
|
206
|
-
Run `npx playwright install chromium` (or `pnpm exec playwright install chromium`).
|
|
235
|
+
## Output artifacts
|
|
207
236
|
|
|
208
|
-
|
|
209
|
-
pa11y requires Puppeteer's Chrome, which is separate from Playwright's Chromium. Install it with `npx puppeteer browsers install chrome`.
|
|
237
|
+
All artifacts are written to `.audit/` relative to the package root.
|
|
210
238
|
|
|
211
|
-
|
|
212
|
-
|
|
239
|
+
| File | Always generated | Description |
|
|
240
|
+
| :--- | :--- | :--- |
|
|
241
|
+
| `a11y-scan-results.json` | Yes | Raw merged results from axe + CDP + pa11y per route |
|
|
242
|
+
| `a11y-findings.json` | Yes | Enriched findings with fix intelligence |
|
|
243
|
+
| `progress.json` | Yes | Real-time scan progress with per-engine step status |
|
|
244
|
+
| `remediation.md` | Yes | AI-agent-optimized remediation roadmap |
|
|
245
|
+
| `report.html` | With `--with-reports` | Interactive HTML dashboard |
|
|
246
|
+
| `report.pdf` | With `--with-reports` | Formal compliance PDF |
|
|
247
|
+
| `checklist.html` | With `--with-reports` | Manual WCAG testing checklist |
|
|
213
248
|
|
|
214
|
-
|
|
215
|
-
Use `--wait-until networkidle --wait-ms 3000` to let async content render before the engines run.
|
|
249
|
+
## Installation
|
|
216
250
|
|
|
217
|
-
|
|
218
|
-
|
|
251
|
+
```bash
|
|
252
|
+
npm install @diegovelasquezweb/a11y-engine
|
|
253
|
+
npx playwright install chromium
|
|
254
|
+
npx puppeteer browsers install chrome
|
|
255
|
+
```
|
|
219
256
|
|
|
220
|
-
**
|
|
221
|
-
|
|
257
|
+
> **Two browsers are required:**
|
|
258
|
+
> - **Playwright Chromium** — used by axe-core and CDP checks
|
|
259
|
+
> - **Puppeteer Chrome** — used by pa11y (HTML CodeSniffer)
|
|
222
260
|
|
|
223
261
|
## Documentation
|
|
224
262
|
|
|
225
263
|
| Resource | Description |
|
|
226
264
|
| :--- | :--- |
|
|
227
|
-
| [Architecture](
|
|
228
|
-
| [CLI Handbook](
|
|
229
|
-
| [Output Artifacts](
|
|
265
|
+
| [Architecture](docs/architecture.md) | How the multi-engine scanner pipeline works |
|
|
266
|
+
| [CLI Handbook](docs/cli-handbook.md) | Full flag reference and usage patterns |
|
|
267
|
+
| [Output Artifacts](docs/outputs.md) | Schema and structure of every generated file |
|
|
230
268
|
|
|
231
269
|
## License
|
|
232
270
|
|
package/docs/architecture.md
CHANGED
|
@@ -205,6 +205,28 @@ Assets are static JSON files bundled with the package under `assets/`. They are
|
|
|
205
205
|
| `remediation/axe-check-maps.json` | axe check-to-rule mapping |
|
|
206
206
|
| `remediation/source-boundaries.json` | Framework-specific source file locations |
|
|
207
207
|
|
|
208
|
+
## Programmatic API
|
|
209
|
+
|
|
210
|
+
In addition to the CLI pipeline, the engine exports 7 functions via `scripts/index.mjs` for direct consumption by Node.js applications (e.g. `a11y-scanner`). These functions reuse the same internal renderers, assets, and enrichment logic as the CLI — no duplication.
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
scripts/index.mjs (public API)
|
|
214
|
+
├── getEnrichedFindings() ← uses asset-loader, intelligence.json, pa11y-config.json
|
|
215
|
+
├── getAuditSummary() ← uses compliance-config.json, wcag-reference.json
|
|
216
|
+
├── getPDFReport() ← uses reports/renderers/pdf.mjs + Playwright
|
|
217
|
+
├── getHTMLReport() ← uses reports/renderers/html.mjs + findings.mjs
|
|
218
|
+
├── getChecklist() ← uses reports/renderers/html.mjs (manual checks)
|
|
219
|
+
├── getRemediationGuide() ← uses reports/renderers/md.mjs
|
|
220
|
+
└── getSourcePatterns() ← uses engine/source-scanner.mjs
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Key design decisions
|
|
224
|
+
|
|
225
|
+
- **No filesystem output** — all API functions return data in memory (strings, Buffers, arrays). The consumer decides where to write.
|
|
226
|
+
- **Payload in, results out** — functions accept the raw `{ findings, metadata }` payload that `a11y-findings.json` contains. No need to resolve paths or read files.
|
|
227
|
+
- **`screenshotUrlBuilder` callback** — `getEnrichedFindings` accepts an optional function to transform raw screenshot paths (e.g. `screenshots/0-color-contrast.png`) into consumer-specific URLs (e.g. `/api/scan/{id}/screenshot?path=...`). This keeps URL construction out of the engine.
|
|
228
|
+
- **CLI unaffected** — the `audit.mjs` orchestrator and all CLI builders continue to work exactly as before. The API is additive.
|
|
229
|
+
|
|
208
230
|
## Execution model and timeouts
|
|
209
231
|
|
|
210
232
|
`audit.mjs` spawns each stage as a child process via `node:child_process`. All child processes:
|
package/docs/cli-handbook.md
CHANGED
|
@@ -235,3 +235,7 @@ The engine never exits `1` just because findings were found. Exit `1` only indic
|
|
|
235
235
|
REMEDIATION_PATH=<abs-path> # always printed on success
|
|
236
236
|
REPORT_PATH=<abs-path> # only printed when --with-reports is set
|
|
237
237
|
```
|
|
238
|
+
|
|
239
|
+
## Programmatic alternative
|
|
240
|
+
|
|
241
|
+
For applications that embed the engine as a dependency (e.g. web dashboards, CI pipelines), the engine also exports a programmatic API that processes scan data in memory without filesystem operations. See the [README](../README.md#programmatic-api) for full documentation.
|
package/docs/outputs.md
CHANGED
|
@@ -257,40 +257,54 @@ Written to the same directory as `--output` as `checklist.html`.
|
|
|
257
257
|
|
|
258
258
|
## Consuming outputs programmatically
|
|
259
259
|
|
|
260
|
-
###
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
import {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
260
|
+
### Using the programmatic API (recommended)
|
|
261
|
+
|
|
262
|
+
The engine exports functions that process scan data directly in memory — no filesystem path resolution needed:
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
import {
|
|
266
|
+
getEnrichedFindings,
|
|
267
|
+
getAuditSummary,
|
|
268
|
+
getPDFReport,
|
|
269
|
+
getHTMLReport,
|
|
270
|
+
getChecklist,
|
|
271
|
+
getRemediationGuide,
|
|
272
|
+
getSourcePatterns,
|
|
273
|
+
} from "@diegovelasquezweb/a11y-engine";
|
|
274
|
+
|
|
275
|
+
// After running audit.mjs via CLI, read the findings file
|
|
276
|
+
const payload = JSON.parse(fs.readFileSync(findingsPath, "utf-8"));
|
|
277
|
+
|
|
278
|
+
// Enrich findings with fix intelligence
|
|
279
|
+
const findings = getEnrichedFindings(payload, {
|
|
280
|
+
screenshotUrlBuilder: (path) => `/api/screenshot?path=${encodeURIComponent(path)}`,
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// Get full audit summary
|
|
284
|
+
const summary = getAuditSummary(findings, payload);
|
|
285
|
+
|
|
286
|
+
// Generate reports
|
|
287
|
+
const pdf = await getPDFReport(payload, { baseUrl: "https://example.com" });
|
|
288
|
+
const html = await getHTMLReport(payload, { baseUrl: "https://example.com" });
|
|
289
|
+
const checklist = await getChecklist({ baseUrl: "https://example.com" });
|
|
290
|
+
const guide = await getRemediationGuide(payload, { baseUrl: "https://example.com" });
|
|
291
|
+
|
|
292
|
+
// Scan source code patterns
|
|
293
|
+
const patterns = await getSourcePatterns("/path/to/project", { framework: "nextjs" });
|
|
274
294
|
```
|
|
275
295
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
```js
|
|
279
|
-
const symlinkBase = path.join(process.cwd(), "node_modules", "@diegovelasquezweb", "a11y-engine");
|
|
280
|
-
const engineRoot = fs.realpathSync(symlinkBase);
|
|
281
|
-
const findingsPath = path.join(engineRoot, ".audit", "a11y-findings.json");
|
|
282
|
-
```
|
|
296
|
+
See the [README](../README.md#programmatic-api) for full API documentation and type signatures.
|
|
283
297
|
|
|
284
298
|
### Reading `progress.json` for live UI updates
|
|
285
299
|
|
|
300
|
+
During CLI execution, `progress.json` is written to `.audit/` in real-time. This is relevant when using the CLI via `child_process` — the programmatic API does not write progress files.
|
|
301
|
+
|
|
286
302
|
```js
|
|
287
303
|
const progressPath = path.join(engineRoot, ".audit", "progress.json");
|
|
288
304
|
|
|
289
|
-
// Poll this file during scan execution
|
|
290
305
|
if (fs.existsSync(progressPath)) {
|
|
291
306
|
const progress = JSON.parse(fs.readFileSync(progressPath, "utf-8"));
|
|
292
307
|
console.log(`Current step: ${progress.currentStep}`);
|
|
293
|
-
console.log(`axe found: ${progress.steps?.axe?.found ?? "pending"}`);
|
|
294
308
|
}
|
|
295
309
|
```
|
|
296
310
|
|