@a11y-skills/audit 0.3.1 → 0.4.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 CHANGED
@@ -3,6 +3,19 @@
3
3
  All notable changes to `@a11y-skills/audit` are documented here. This project
4
4
  adheres to [Semantic Versioning](https://semver.org/).
5
5
 
6
+ ## 0.4.0 — 2026-06-12
7
+
8
+ ### Added
9
+
10
+ - `bin` CLI (`a11y-audit`): run all ten WCAG checks against a URL without a
11
+ Playwright test runner — `npx -y @a11y-skills/audit --url <url>`. Flags:
12
+ `--checks <list>`, `--output-dir`, `--screenshot`, `--list-checks`,
13
+ `--version`, `--help`. Exit codes: `0` = no violations, `1` = violations
14
+ found, `2` = runtime error. JSON output uses the same envelope as the
15
+ function API regardless of exit code.
16
+ - `test/fixtures/cli-smoke.html`: network-independent smoke fixture (a page
17
+ with intentional axe violations) for the CI CLI smoke test.
18
+
6
19
  ## 0.3.1
7
20
 
8
21
  ### Fixed
package/README.ja.md CHANGED
@@ -50,6 +50,70 @@ npm install -D pixelmatch pngjs # runAutoPlayDetection を使う場合のみ
50
50
  > ESM 専用です。CommonJS ビルドは同梱しません。ESM(または ESM 出力の TypeScript)から
51
51
  > import してください。
52
52
 
53
+ ## CLI
54
+
55
+ テストランナー不要で、コマンド 1 本で 10 検査すべてを実行できます。
56
+
57
+ ```sh
58
+ npx -y @a11y-skills/audit --url https://example.com
59
+ ```
60
+
61
+ npm 7 以降では peer dependencies(`@playwright/test`、`@axe-core/playwright`)が
62
+ 自動でインストールされます。初回は Chromium のインストールが必要です:
63
+
64
+ ```sh
65
+ npx playwright install chromium
66
+ ```
67
+
68
+ ### フラグ
69
+
70
+ | フラグ | デフォルト | 説明 |
71
+ | --- | --- | --- |
72
+ | `--url <url>` | `TEST_PAGE` 環境変数 | 対象 URL。`--url` が環境変数より優先されます。どちらも未設定の場合は usage を表示して exit 2。 |
73
+ | `--checks <list>` | `all` | カンマ区切りのチェック名(下記一覧参照)。 |
74
+ | `--output-dir <dir>` | `./a11y-audit-results` | 結果 JSON の出力ディレクトリ。 |
75
+ | `--screenshot` | off | focus-indicator のスクリーンショットを有効化。 |
76
+ | `--list-checks` | — | チェック名一覧を出力して exit 0。 |
77
+ | `--version` | — | バージョンを出力して exit 0。 |
78
+ | `--help` | — | usage を出力して exit 0。 |
79
+
80
+ ### チェック名一覧
81
+
82
+ ```
83
+ axe-audit
84
+ focus-indicator-check
85
+ reflow-check
86
+ text-spacing-check
87
+ zoom-200-check
88
+ orientation-check
89
+ autocomplete-audit
90
+ time-limit-detector
91
+ auto-play-detection
92
+ target-size-check
93
+ ```
94
+
95
+ ### 終了コード
96
+
97
+ | コード | 意味 |
98
+ | --- | --- |
99
+ | `0` | すべてのチェックが完了し、違反なし。 |
100
+ | `1` | すべてのチェックが完了し、1 件以上の違反あり。 |
101
+ | `2` | 実行時エラー — 引数不正・peer 欠落・ナビゲーション失敗・チェックのクラッシュ。 |
102
+
103
+ exit コードが非 0 でも、完了したチェックの JSON は必ず書き出されます。
104
+
105
+ ### peer 要件
106
+
107
+ `@playwright/test >=1.50.0` および `@axe-core/playwright >=4.10.0` が必要です。
108
+ 見つからない場合は exit 2 でインストール手順を案内します。
109
+ `--list-checks`、`--help`、`--version` は peer なしでも動作します。
110
+
111
+ ### `auto-play-detection` と optional deps
112
+
113
+ `auto-play-detection` は `pixelmatch` と `pngjs` が必要です。
114
+ 未インストールの場合はそのチェックだけ `SKIPPED` となり、終了コードには影響しません。
115
+ 他の 9 検査は通常通り実行されます。
116
+
53
117
  ## 使い方 — 関数 API(推奨)
54
118
 
55
119
  ページの遷移は呼び出し側で行い、関数は検査の実行・結果 JSON の書き出し・結果オブジェクトの
package/README.md CHANGED
@@ -52,6 +52,70 @@ npm install -D pixelmatch pngjs # only if you use runAutoPlayDetection
52
52
  > ESM only. This package does not ship a CommonJS build; import it from ESM
53
53
  > (or a TypeScript project compiled to ESM).
54
54
 
55
+ ## CLI
56
+
57
+ Run all ten checks against a URL with a single command — no test runner needed.
58
+
59
+ ```sh
60
+ npx -y @a11y-skills/audit --url https://example.com
61
+ ```
62
+
63
+ Peer dependencies (`@playwright/test`, `@axe-core/playwright`) are pulled in
64
+ automatically by npm 7+. Install Chromium on first use:
65
+
66
+ ```sh
67
+ npx playwright install chromium
68
+ ```
69
+
70
+ ### Flags
71
+
72
+ | Flag | Default | Description |
73
+ | --- | --- | --- |
74
+ | `--url <url>` | `TEST_PAGE` env | Target URL. `--url` takes priority over the env var. If neither is set, usage is printed and the process exits 2. |
75
+ | `--checks <list>` | `all` | Comma-separated check names (see list below). |
76
+ | `--output-dir <dir>` | `./a11y-audit-results` | Directory for result JSON files. |
77
+ | `--screenshot` | off | Enable focus-indicator screenshot. |
78
+ | `--list-checks` | — | Print check names and exit 0. |
79
+ | `--version` | — | Print version and exit 0. |
80
+ | `--help` | — | Print usage and exit 0. |
81
+
82
+ ### Available check names
83
+
84
+ ```
85
+ axe-audit
86
+ focus-indicator-check
87
+ reflow-check
88
+ text-spacing-check
89
+ zoom-200-check
90
+ orientation-check
91
+ autocomplete-audit
92
+ time-limit-detector
93
+ auto-play-detection
94
+ target-size-check
95
+ ```
96
+
97
+ ### Exit codes
98
+
99
+ | Code | Meaning |
100
+ | --- | --- |
101
+ | `0` | All checks completed, no violations found. |
102
+ | `1` | All checks completed, at least one violation found. |
103
+ | `2` | Runtime error — bad arguments, missing peers, navigation failure, or check crash. |
104
+
105
+ Completed-check JSON is always written even when the exit code is non-zero.
106
+
107
+ ### Peer requirements
108
+
109
+ `@playwright/test >=1.50.0` and `@axe-core/playwright >=4.10.0` must be
110
+ resolvable. If they are not found, the CLI exits 2 with an install hint.
111
+ `--list-checks`, `--help`, and `--version` work without peers.
112
+
113
+ ### `auto-play-detection` and optional deps
114
+
115
+ `auto-play-detection` needs `pixelmatch` and `pngjs`. If they are absent, that
116
+ check is skipped with a `SKIPPED` message and does not affect the exit code.
117
+ The other nine checks continue normally.
118
+
55
119
  ## Usage — function API (recommended)
56
120
 
57
121
  You navigate the page; the function runs the check, writes a result JSON, and
package/dist/cli.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @a11y-skills/audit CLI
4
+ *
5
+ * Runs WCAG 2.2 accessibility checks against a URL without needing a
6
+ * Playwright test runner. All 10 checks are available via --checks.
7
+ *
8
+ * Exit codes:
9
+ * 0 — completed, no violations found across all checks
10
+ * 1 — completed, at least one violation found
11
+ * 2 — runtime error (bad args, missing peers, navigation failure, check crash)
12
+ */
13
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,407 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @a11y-skills/audit CLI
4
+ *
5
+ * Runs WCAG 2.2 accessibility checks against a URL without needing a
6
+ * Playwright test runner. All 10 checks are available via --checks.
7
+ *
8
+ * Exit codes:
9
+ * 0 — completed, no violations found across all checks
10
+ * 1 — completed, at least one violation found
11
+ * 2 — runtime error (bad args, missing peers, navigation failure, check crash)
12
+ */
13
+ import * as fs from 'node:fs';
14
+ import * as path from 'node:path';
15
+ import { parseArgs } from 'node:util';
16
+ // ---------------------------------------------------------------------------
17
+ // Check registry
18
+ // ---------------------------------------------------------------------------
19
+ // Checks are registered with lazy imports to avoid top-level peer resolution.
20
+ const CHECK_REGISTRY = [
21
+ {
22
+ name: 'axe-audit',
23
+ kind: 'page',
24
+ async run({ page, outputDir }) {
25
+ const { runAxeAudit } = await import('./playwright/runAxeAudit.js');
26
+ return (await runAxeAudit({ page, outputDir }));
27
+ },
28
+ },
29
+ {
30
+ name: 'focus-indicator-check',
31
+ kind: 'browser',
32
+ async run({ browser, outputDir, screenshot, url }) {
33
+ const { runFocusIndicatorCheck } = await import('./playwright/runFocusIndicatorCheck.js');
34
+ return (await runFocusIndicatorCheck({
35
+ browser,
36
+ targetUrl: url,
37
+ outputDir,
38
+ screenshot,
39
+ }));
40
+ },
41
+ },
42
+ {
43
+ name: 'reflow-check',
44
+ kind: 'page',
45
+ async run({ page, outputDir }) {
46
+ const { runReflowCheck } = await import('./playwright/runReflowCheck.js');
47
+ return (await runReflowCheck({ page, outputDir }));
48
+ },
49
+ },
50
+ {
51
+ name: 'text-spacing-check',
52
+ kind: 'page',
53
+ async run({ page, outputDir }) {
54
+ const { runTextSpacingCheck } = await import('./playwright/runTextSpacingCheck.js');
55
+ return (await runTextSpacingCheck({
56
+ page,
57
+ outputDir,
58
+ }));
59
+ },
60
+ },
61
+ {
62
+ name: 'zoom-200-check',
63
+ kind: 'page',
64
+ async run({ page, outputDir }) {
65
+ const { runZoomCheck } = await import('./playwright/runZoomCheck.js');
66
+ return (await runZoomCheck({ page, outputDir }));
67
+ },
68
+ },
69
+ {
70
+ name: 'orientation-check',
71
+ kind: 'page',
72
+ async run({ page, outputDir }) {
73
+ const { runOrientationCheck } = await import('./playwright/runOrientationCheck.js');
74
+ return (await runOrientationCheck({
75
+ page,
76
+ outputDir,
77
+ }));
78
+ },
79
+ },
80
+ {
81
+ name: 'autocomplete-audit',
82
+ kind: 'page',
83
+ async run({ page, outputDir }) {
84
+ const { runAutocompleteAudit } = await import('./playwright/runAutocompleteAudit.js');
85
+ return (await runAutocompleteAudit({
86
+ page,
87
+ outputDir,
88
+ }));
89
+ },
90
+ },
91
+ {
92
+ name: 'time-limit-detector',
93
+ kind: 'page',
94
+ async run({ page, outputDir }) {
95
+ const { runTimeLimitDetector } = await import('./playwright/runTimeLimitDetector.js');
96
+ return (await runTimeLimitDetector({
97
+ page,
98
+ outputDir,
99
+ }));
100
+ },
101
+ },
102
+ {
103
+ name: 'auto-play-detection',
104
+ kind: 'page',
105
+ async run({ page, outputDir }) {
106
+ const { runAutoPlayDetection } = await import('./playwright/runAutoPlayDetection.js');
107
+ return (await runAutoPlayDetection({
108
+ page,
109
+ outputDir: path.join(outputDir, 'auto-play-screenshots'),
110
+ }));
111
+ },
112
+ },
113
+ {
114
+ name: 'target-size-check',
115
+ kind: 'page',
116
+ async run({ page, outputDir }) {
117
+ const { runTargetSizeCheck } = await import('./playwright/runTargetSizeCheck.js');
118
+ return (await runTargetSizeCheck({
119
+ page,
120
+ outputDir,
121
+ }));
122
+ },
123
+ },
124
+ ];
125
+ // ---------------------------------------------------------------------------
126
+ // Helpers
127
+ // ---------------------------------------------------------------------------
128
+ function printUsage() {
129
+ process.stdout.write(`
130
+ Usage: a11y-audit --url <url> [options]
131
+
132
+ Options:
133
+ --url <url> Target URL to audit. Overrides TEST_PAGE env var.
134
+ --checks <list> Comma-separated check names (default: all).
135
+ Use --list-checks to see available names.
136
+ --output-dir <dir> Directory for result JSON files (default: ./a11y-audit-results).
137
+ --screenshot Enable focus-indicator screenshot (default: off).
138
+ --list-checks Print available check names and exit.
139
+ --version Print version and exit.
140
+ --help Print this message and exit.
141
+
142
+ Exit codes:
143
+ 0 No violations found.
144
+ 1 One or more violations found.
145
+ 2 Runtime error (bad arguments, missing peers, navigation failure).
146
+
147
+ Peer requirements:
148
+ @playwright/test >=1.50.0
149
+ @axe-core/playwright >=4.10.0
150
+
151
+ Install if missing: npm i -D @playwright/test @axe-core/playwright
152
+ Install browsers: npx playwright install chromium
153
+
154
+ auto-play-detection requires optional deps (pixelmatch, pngjs). If they are
155
+ missing, that check is skipped with a SKIPPED notice.
156
+ `);
157
+ }
158
+ /** Verify required peers are resolvable. Returns an error string or null. */
159
+ async function checkPeers() {
160
+ const missing = [];
161
+ for (const pkg of ['@playwright/test', '@axe-core/playwright']) {
162
+ try {
163
+ await import(pkg);
164
+ }
165
+ catch {
166
+ missing.push(pkg);
167
+ }
168
+ }
169
+ if (missing.length > 0) {
170
+ return (`Missing required peer dependencies: ${missing.join(', ')}\n` +
171
+ `Install them with: npm i -D @playwright/test @axe-core/playwright`);
172
+ }
173
+ return null;
174
+ }
175
+ function formatDuration(ms) {
176
+ return `${(ms / 1000).toFixed(1)}s`;
177
+ }
178
+ // ---------------------------------------------------------------------------
179
+ // Main
180
+ // ---------------------------------------------------------------------------
181
+ async function main() {
182
+ // Read package version from package.json
183
+ let pkgVersion = 'unknown';
184
+ try {
185
+ const pkgPath = new URL('../package.json', import.meta.url);
186
+ const pkgJson = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
187
+ pkgVersion = pkgJson.version;
188
+ }
189
+ catch {
190
+ // ignore
191
+ }
192
+ let values;
193
+ try {
194
+ const result = parseArgs({
195
+ args: process.argv.slice(2),
196
+ options: {
197
+ url: { type: 'string' },
198
+ checks: { type: 'string' },
199
+ 'output-dir': { type: 'string' },
200
+ screenshot: { type: 'boolean', default: false },
201
+ 'list-checks': { type: 'boolean', default: false },
202
+ version: { type: 'boolean', default: false },
203
+ help: { type: 'boolean', default: false },
204
+ },
205
+ strict: true,
206
+ });
207
+ values = result.values;
208
+ }
209
+ catch (err) {
210
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\n`);
211
+ printUsage();
212
+ process.exit(2);
213
+ }
214
+ if (values.help) {
215
+ printUsage();
216
+ process.exit(0);
217
+ }
218
+ if (values.version) {
219
+ process.stdout.write(`${pkgVersion}\n`);
220
+ process.exit(0);
221
+ }
222
+ if (values['list-checks']) {
223
+ process.stdout.write(CHECK_REGISTRY.map((c) => c.name).join('\n') + '\n');
224
+ process.exit(0);
225
+ }
226
+ // --- Resolve URL ---
227
+ const url = values.url ?? process.env.TEST_PAGE;
228
+ if (!url) {
229
+ process.stderr.write('Error: --url is required (or set the TEST_PAGE environment variable).\n');
230
+ printUsage();
231
+ process.exit(2);
232
+ }
233
+ // --- Resolve checks ---
234
+ const checksArg = values.checks;
235
+ let selectedChecks;
236
+ if (!checksArg || checksArg === 'all') {
237
+ selectedChecks = CHECK_REGISTRY;
238
+ }
239
+ else {
240
+ const names = checksArg.split(',').map((n) => n.trim());
241
+ const unknown = names.filter((n) => !CHECK_REGISTRY.some((c) => c.name === n));
242
+ if (unknown.length > 0) {
243
+ process.stderr.write(`Error: unknown check(s): ${unknown.join(', ')}\n` +
244
+ `Run --list-checks to see available names.\n`);
245
+ process.exit(2);
246
+ }
247
+ selectedChecks = names
248
+ .map((n) => CHECK_REGISTRY.find((c) => c.name === n))
249
+ .filter((c) => c !== undefined);
250
+ }
251
+ const outputDir = path.resolve(values['output-dir'] ?? './a11y-audit-results');
252
+ const screenshot = values.screenshot === true;
253
+ // --- Peer check (only before running checks) ---
254
+ const peerError = await checkPeers();
255
+ if (peerError) {
256
+ process.stderr.write(`Error: ${peerError}\n`);
257
+ process.exit(2);
258
+ }
259
+ // --- Launch browser ---
260
+ let browser;
261
+ try {
262
+ const { chromium } = await import('@playwright/test');
263
+ browser = await chromium.launch();
264
+ }
265
+ catch (err) {
266
+ process.stderr.write(`Error launching browser: ${err instanceof Error ? err.message : String(err)}\n`);
267
+ process.exit(2);
268
+ }
269
+ // Ensure output directory exists
270
+ fs.mkdirSync(outputDir, { recursive: true });
271
+ process.stdout.write(`a11y-audit v${pkgVersion}\n`);
272
+ process.stdout.write(`URL: ${url}\n`);
273
+ process.stdout.write(`Checks: ${selectedChecks.map((c) => c.name).join(', ')}\n`);
274
+ process.stdout.write(`Output dir: ${outputDir}\n`);
275
+ process.stdout.write(`\n`);
276
+ const summaries = [];
277
+ let hasViolations = false;
278
+ let hasErrors = false;
279
+ for (const check of selectedChecks) {
280
+ const start = Date.now();
281
+ // page-based checks get a fresh context + navigated page
282
+ let context = null;
283
+ let page = null;
284
+ try {
285
+ if (check.kind === 'page') {
286
+ context = await browser.newContext();
287
+ page = await context.newPage();
288
+ // Use 'load' for file: URLs to avoid networkidle hanging
289
+ const waitUntil = url.startsWith('file:') ? 'load' : 'networkidle';
290
+ try {
291
+ await page.goto(url, { waitUntil });
292
+ }
293
+ catch (navErr) {
294
+ const msg = navErr instanceof Error ? navErr.message : String(navErr);
295
+ process.stderr.write(`[${check.name}] Navigation failed: ${msg}\n`);
296
+ summaries.push({
297
+ name: check.name,
298
+ status: 'ERROR',
299
+ durationMs: Date.now() - start,
300
+ error: msg,
301
+ });
302
+ hasErrors = true;
303
+ continue;
304
+ }
305
+ }
306
+ const result = await check.run({
307
+ // page is null only for browser-kind checks, which do not use it
308
+ page: page,
309
+ browser,
310
+ outputDir,
311
+ screenshot,
312
+ url,
313
+ });
314
+ const durationMs = Date.now() - start;
315
+ const summary = result.summary;
316
+ const violationCount = summary?.violationCount ?? 0;
317
+ const incompleteCount = summary?.incompleteCount ?? 0;
318
+ const passCount = summary?.passCount ?? 0;
319
+ if (violationCount > 0) {
320
+ hasViolations = true;
321
+ }
322
+ process.stdout.write(`[${check.name}] DONE in ${formatDuration(durationMs)} — ` +
323
+ `violations: ${violationCount}, passes: ${passCount}, incomplete: ${incompleteCount}\n`);
324
+ summaries.push({
325
+ name: check.name,
326
+ status: 'DONE',
327
+ durationMs,
328
+ violationCount,
329
+ incompleteCount,
330
+ passCount,
331
+ });
332
+ }
333
+ catch (err) {
334
+ const durationMs = Date.now() - start;
335
+ const msg = err instanceof Error ? err.message : String(err);
336
+ // auto-play-detection: optional dep missing → SKIPPED, not ERROR
337
+ const isOptionalDepMissing = check.name === 'auto-play-detection' &&
338
+ (msg.includes('pixelmatch') ||
339
+ msg.includes('pngjs') ||
340
+ msg.includes('Cannot find module') ||
341
+ msg.includes('ERR_MODULE_NOT_FOUND'));
342
+ if (isOptionalDepMissing) {
343
+ process.stdout.write(`[${check.name}] SKIPPED — optional deps missing (pixelmatch, pngjs). ` +
344
+ `Install with: npm i pixelmatch pngjs\n`);
345
+ summaries.push({
346
+ name: check.name,
347
+ status: 'SKIPPED',
348
+ durationMs,
349
+ skipReason: 'optional deps missing (pixelmatch, pngjs)',
350
+ });
351
+ }
352
+ else {
353
+ process.stderr.write(`[${check.name}] ERROR: ${msg}\n`);
354
+ summaries.push({
355
+ name: check.name,
356
+ status: 'ERROR',
357
+ durationMs,
358
+ error: msg,
359
+ });
360
+ hasErrors = true;
361
+ }
362
+ }
363
+ finally {
364
+ if (context !== null) {
365
+ try {
366
+ await context.close();
367
+ }
368
+ catch {
369
+ // ignore cleanup errors
370
+ }
371
+ }
372
+ }
373
+ }
374
+ // --- Close browser ---
375
+ try {
376
+ await browser.close();
377
+ }
378
+ catch {
379
+ // ignore
380
+ }
381
+ // --- Summary ---
382
+ const totalMs = summaries.reduce((acc, s) => acc + s.durationMs, 0);
383
+ const doneCount = summaries.filter((s) => s.status === 'DONE').length;
384
+ const skippedCount = summaries.filter((s) => s.status === 'SKIPPED').length;
385
+ const errorCount = summaries.filter((s) => s.status === 'ERROR').length;
386
+ const totalViolations = summaries.reduce((acc, s) => acc + (s.violationCount ?? 0), 0);
387
+ process.stdout.write(`\n`);
388
+ process.stdout.write(`--- Summary (${formatDuration(totalMs)}) ---\n` +
389
+ ` Checks run: ${doneCount}\n` +
390
+ ` Skipped: ${skippedCount}\n` +
391
+ ` Errors: ${errorCount}\n` +
392
+ ` Total violations: ${totalViolations}\n` +
393
+ ` Results written to: ${outputDir}\n`);
394
+ if (hasErrors) {
395
+ process.exit(2);
396
+ }
397
+ else if (hasViolations) {
398
+ process.exit(1);
399
+ }
400
+ else {
401
+ process.exit(0);
402
+ }
403
+ }
404
+ main().catch((err) => {
405
+ process.stderr.write(`Fatal error: ${err instanceof Error ? err.message : String(err)}\n`);
406
+ process.exit(2);
407
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a11y-skills/audit",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Playwright + axe-core based WCAG 2.2 accessibility audit functions (axe, focus indicator, reflow, target size, text spacing, zoom, orientation, autocomplete, time limit, auto-play).",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "https://github.com/masuP9/a11y-specialist-skills",
13
+ "url": "git+https://github.com/masuP9/a11y-specialist-skills.git",
14
14
  "directory": "packages/a11y-audit"
15
15
  },
16
16
  "homepage": "https://github.com/masuP9/a11y-specialist-skills/tree/main/packages/a11y-audit",
@@ -29,6 +29,9 @@
29
29
  "reflow",
30
30
  "target-size"
31
31
  ],
32
+ "bin": {
33
+ "a11y-audit": "dist/cli.js"
34
+ },
32
35
  "exports": {
33
36
  ".": {
34
37
  "types": "./dist/index.d.ts",