next-a11y 0.1.7 → 0.1.9
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 +113 -27
- package/dist/{chunk-A4KDGFRG.mjs → chunk-7JAVB7EY.mjs} +5 -3
- package/dist/cli/index.js +1214 -583
- package/dist/cli/index.mjs +1208 -579
- package/dist/index.d.mts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.mjs +1 -1
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ next-a11y writes the fix.
|
|
|
13
13
|
|
|
14
14
|
95% of websites fail WCAG 2.2 AA. The same 6 error types. Every year. For 5 years straight. ([WebAIM Million 2025](https://webaim.org/projects/million/))
|
|
15
15
|
|
|
16
|
-
next-a11y fixes
|
|
16
|
+
next-a11y fixes 5 of those 6 automatically: **missing alt text**, **missing form labels**, **empty links**, **empty buttons**, **missing lang**. The 6th — low contrast — requires runtime color analysis and isn't detectable from source. We also catch the rest (heading order, skip nav, etc.).
|
|
17
17
|
|
|
18
18
|
## Quick start
|
|
19
19
|
|
|
@@ -23,33 +23,68 @@ npx next-a11y scan ./src # see what's broken
|
|
|
23
23
|
npx next-a11y scan ./src --fix # fix it
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
### Before
|
|
26
|
+
### Before (report only)
|
|
27
27
|
|
|
28
28
|
```
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
29
|
+
next-a11y v0.1.9
|
|
30
|
+
Scanned 13 files
|
|
31
|
+
|
|
32
|
+
Heuristic score: 34 / 100 Poor
|
|
33
|
+
|
|
34
|
+
[AI] fixes available:
|
|
35
|
+
[img] 12 images missing alt text -24 pts
|
|
36
|
+
src/components/Hero.tsx:7 — Image is missing alt text
|
|
37
|
+
src/components/ProductCard.tsx:8 — Image has meaningless alt text: "IMG_123.jpg"
|
|
38
|
+
[btn] 4 buttons without accessible name -8 pts
|
|
39
|
+
src/components/Navbar.tsx:12 — Button has no accessible name
|
|
40
|
+
[lnk] 2 links without accessible name -4 pts
|
|
41
|
+
[inp] 3 inputs without label -9 pts
|
|
42
|
+
Auto fixes available:
|
|
43
|
+
[lng] 1 missing lang on <html> -5 pts
|
|
44
|
+
Warnings (manual review needed):
|
|
45
|
+
[img] 2 next/image without sizes -2 pts
|
|
46
|
+
[nav] 1 missing skip navigation link -3 pts
|
|
47
|
+
[hdg] 1 heading hierarchy violations -1 pts
|
|
48
|
+
[div] 1 div used as interactive element -1 pts
|
|
49
|
+
|
|
50
|
+
----------------------------------------
|
|
40
51
|
38 fixable · 4 warnings · Run --fix to apply
|
|
41
52
|
```
|
|
42
53
|
|
|
43
|
-
### After
|
|
54
|
+
### After (with --fix)
|
|
44
55
|
|
|
45
56
|
```
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
57
|
+
Generating text using openai/gpt-4o-mini
|
|
58
|
+
|
|
59
|
+
[AI] resolved 1/18 → "Hero image with welcome message"
|
|
60
|
+
[AI] resolved 2/18 → "Add to cart"
|
|
61
|
+
[AI] resolved 3/18 → "Visit Twitter"
|
|
62
|
+
...
|
|
63
|
+
Total tokens used: 2,450
|
|
64
|
+
|
|
65
|
+
Fixes applied:
|
|
49
66
|
|
|
50
|
-
|
|
67
|
+
[FIXED] src/components/Hero.tsx:7 added alt text "Hero image with welcome message"
|
|
68
|
+
[FIXED] src/components/Navbar.tsx:12 added aria-label "Add to cart"
|
|
69
|
+
[FIXED] src/components/Footer.tsx:7 added rel="noopener noreferrer"
|
|
70
|
+
[FIXED] src/app/layout.tsx:11 added lang "en"
|
|
71
|
+
[FIXED] src/app/page.tsx:1 added metadata.title "Home"
|
|
72
|
+
...
|
|
51
73
|
|
|
52
|
-
|
|
74
|
+
next-a11y v0.1.9
|
|
75
|
+
Scanned 13 files
|
|
76
|
+
|
|
77
|
+
Heuristic score: 97 / 100 Good
|
|
78
|
+
|
|
79
|
+
Warnings (manual review needed):
|
|
80
|
+
[img] 2 next/image without sizes -2 pts
|
|
81
|
+
[nav] 1 missing skip navigation link -3 pts
|
|
82
|
+
[hdg] 1 heading hierarchy violations -1 pts
|
|
83
|
+
[div] 1 div used as interactive element -1 pts
|
|
84
|
+
|
|
85
|
+
----------------------------------------
|
|
86
|
+
[FIXED] 31 · 4 warnings
|
|
87
|
+
Score: 34 -> 97 (+63 pts)
|
|
53
88
|
```
|
|
54
89
|
|
|
55
90
|
## What it fixes
|
|
@@ -86,29 +121,41 @@ npx next-a11y scan ./src --fix # fix it
|
|
|
86
121
|
|
|
87
122
|
| Rule | What it does |
|
|
88
123
|
| -------------------- | -------------------------------------------------------- |
|
|
89
|
-
| `heading-order` | Flags `h1` → `h3` skips
|
|
124
|
+
| `heading-order` | Flags `h1` → `h3` skips (shows heading text in message) |
|
|
90
125
|
| `no-div-interactive` | Flags `<div onClick>` without `role` or keyboard handler |
|
|
91
126
|
|
|
127
|
+
## Locale support
|
|
128
|
+
|
|
129
|
+
Generated labels (aria-labels, alt text, page titles) follow the target locale:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npx next-a11y scan ./src --fix --locale pl
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Supported: `en`, `pl`, `de`, `es`, `fr`. Known icons (Twitter, GitHub, Cart, etc.) use locale-aware heuristics; others are generated by AI in the requested language.
|
|
136
|
+
|
|
92
137
|
## No AI? No problem.
|
|
93
138
|
|
|
94
139
|
```bash
|
|
95
|
-
npx next-a11y scan ./src --fix --no-ai
|
|
140
|
+
npx next-a11y scan ./src --fix --no-ai # not recommended for best results
|
|
96
141
|
```
|
|
97
142
|
|
|
98
|
-
9 deterministic rules work without any API key or AI setup.
|
|
143
|
+
9 deterministic rules work without any API key or AI setup. Not recommended for best results — AI fixes handle alt text, labels, and page titles more accurately.
|
|
99
144
|
|
|
100
145
|
## AI providers
|
|
101
146
|
|
|
102
147
|
Works with any major provider through [Vercel AI SDK](https://sdk.vercel.ai/):
|
|
103
148
|
|
|
104
149
|
```bash
|
|
105
|
-
npm install @ai-sdk/google # free tier: 1500 req/day
|
|
150
|
+
npm install -D @ai-sdk/google # free tier: 1500 req/day
|
|
151
|
+
# or
|
|
152
|
+
npm install -D @ai-sdk/openai # gpt-4o-mini ~$0.001/fix
|
|
106
153
|
# or
|
|
107
|
-
npm install @ai-sdk/
|
|
154
|
+
npm install -D @ai-sdk/anthropic # claude-haiku ~$0.001/fix
|
|
108
155
|
# or
|
|
109
|
-
npm install @ai-sdk
|
|
156
|
+
npm install -D @openrouter/ai-sdk-provider # 200+ models via one API
|
|
110
157
|
# or
|
|
111
|
-
npm install ollama-ai-provider # local, $0
|
|
158
|
+
npm install -D ollama-ai-provider # local, $0
|
|
112
159
|
```
|
|
113
160
|
|
|
114
161
|
## Config
|
|
@@ -135,6 +182,45 @@ export default defineConfig({
|
|
|
135
182
|
});
|
|
136
183
|
```
|
|
137
184
|
|
|
185
|
+
## CLI reference
|
|
186
|
+
|
|
187
|
+
### scan
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
npx next-a11y scan <path> [options]
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
| Option | Description |
|
|
194
|
+
| --------------------- | -------------------------------------------------------------------- |
|
|
195
|
+
| `--fix` | Auto-fix issues |
|
|
196
|
+
| `-i, --interactive` | Review each fix interactively |
|
|
197
|
+
| `--no-ai` | Skip AI-powered fixes (deterministic only, not recommended) |
|
|
198
|
+
| `--provider <name>` | Override AI provider (openai, anthropic, google, ollama, openrouter) |
|
|
199
|
+
| `--model <name>` | Override AI model |
|
|
200
|
+
| `--fill-alt` | Replace empty `alt=""` with AI-generated text |
|
|
201
|
+
| `--locale <locale>` | Locale for generated content (e.g. en, pl, de) |
|
|
202
|
+
| `--min-score <score>` | Exit code 1 if heuristic score below threshold |
|
|
203
|
+
| `-q, --quiet` | Minimal output (no progress, one-line report) |
|
|
204
|
+
|
|
205
|
+
### init
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
npx next-a11y init
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Creates `a11y.config.ts`, optionally installs AI SDK package, adds `.a11y-cache` to `.gitignore`.
|
|
212
|
+
|
|
213
|
+
### cache
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
npx next-a11y cache stats # Show cache statistics
|
|
217
|
+
npx next-a11y cache clear # Clear the cache
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Scoring
|
|
221
|
+
|
|
222
|
+
The 0–100 score is a **heuristic** — it does not certify WCAG compliance. It's a weighted count of detected violations (e.g. missing alt −2 pts, missing lang −5 pts). Use it to track progress and gate CI; don't treat 97/100 as "WCAG AA compliant."
|
|
223
|
+
|
|
138
224
|
## CI
|
|
139
225
|
|
|
140
226
|
```yaml
|
|
@@ -157,7 +243,7 @@ npx next-a11y scan . --fix
|
|
|
157
243
|
|
|
158
244
|
## How it works
|
|
159
245
|
|
|
160
|
-
Static analysis codemod. Parses your source with [ts-morph](https://github.com/dsherret/ts-morph), runs 15 rules against the AST, generates fixes (AI or pattern-based), writes them back to your files. No browser. No runtime. Ships zero code to production.
|
|
246
|
+
Static analysis codemod. Parses your source with [ts-morph](https://github.com/dsherret/ts-morph), runs 15 rules against the AST, generates fixes (AI or pattern-based), writes them back to your files. Fixes are applied concurrently per file. Cache keys include locale so `--locale pl` and `--locale en` don't overwrite each other. Use `--quiet` / `-q` for minimal output (CI-friendly). No browser. No runtime. Ships zero code to production.
|
|
161
247
|
|
|
162
248
|
## License
|
|
163
249
|
|
|
@@ -7,16 +7,18 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
|
|
8
8
|
// src/config/schema.ts
|
|
9
9
|
var PROVIDER_DEFAULTS = {
|
|
10
|
-
openai: "gpt-
|
|
10
|
+
openai: "gpt-4o-mini",
|
|
11
11
|
anthropic: "claude-haiku-4-5-20251001",
|
|
12
12
|
google: "gemini-2.0-flash-lite",
|
|
13
|
-
ollama: "llava"
|
|
13
|
+
ollama: "llava",
|
|
14
|
+
openrouter: "openai/gpt-4o-mini"
|
|
14
15
|
};
|
|
15
16
|
var PROVIDER_ENV = {
|
|
16
17
|
openai: "OPENAI_API_KEY",
|
|
17
18
|
anthropic: "ANTHROPIC_API_KEY",
|
|
18
19
|
google: "GOOGLE_GENERATIVE_AI_API_KEY",
|
|
19
|
-
ollama: null
|
|
20
|
+
ollama: null,
|
|
21
|
+
openrouter: "OPENROUTER_API_KEY"
|
|
20
22
|
};
|
|
21
23
|
var DEFAULT_RULES = {
|
|
22
24
|
"img-alt": "fix",
|