@d-zero/a11y-check-axe-scenario 0.5.6 → 0.5.8
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 +348 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1 +1,348 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @d-zero/a11y-check-axe-scenario
|
|
2
|
+
|
|
3
|
+
axe-core を使用したアクセシビリティチェック用のシナリオパッケージです。
|
|
4
|
+
|
|
5
|
+
## インストール
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @d-zero/a11y-check-axe-scenario
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Peer Dependencies
|
|
12
|
+
|
|
13
|
+
このパッケージを使用するには、以下のピア依存関係をインストールする必要があります。
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install axe-core puppeteer
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
または、yarn を使用する場合:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
yarn add axe-core puppeteer
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 概要
|
|
26
|
+
|
|
27
|
+
`@d-zero/a11y-check-axe-scenario` は、[axe-core](https://github.com/dequelabs/axe-core) と Puppeteer を統合したアクセシビリティチェックシナリオを提供します。axe-core は、Deque Systems が開発したアクセシビリティテストエンジンで、WCAG(Web Content Accessibility Guidelines)に準拠したアクセシビリティ検証を自動的に実行します。
|
|
28
|
+
|
|
29
|
+
このパッケージは、`@d-zero/a11y-check-core` のシナリオシステムに統合されており、以下の機能を提供します:
|
|
30
|
+
|
|
31
|
+
- **axe-core による自動アクセシビリティチェック**: WCAG 2.0/2.1 の達成基準に基づいた検証
|
|
32
|
+
- **キャッシュ機構**: 検証結果のキャッシュによる高速化
|
|
33
|
+
- **多言語対応**: axe-core のロケール設定をサポート(デフォルト: 日本語)
|
|
34
|
+
- **スクリーンショット機能**: 違反箇所のスクリーンショット取得
|
|
35
|
+
- **WCAG 準拠レポート**: 達成基準番号、レベル(A/AA/AAA)、重要度を含む詳細レポート
|
|
36
|
+
|
|
37
|
+
## scenarioAxe の使い方
|
|
38
|
+
|
|
39
|
+
`scenarioAxe` は、`@d-zero/a11y-check-core` の `createScenario` を使用して作成されたシナリオ関数です。
|
|
40
|
+
|
|
41
|
+
### 基本的な使用方法
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { scenarioAxe } from '@d-zero/a11y-check-axe-scenario';
|
|
45
|
+
|
|
46
|
+
// オプションなしで使用
|
|
47
|
+
const scenario = scenarioAxe();
|
|
48
|
+
|
|
49
|
+
// オプションを指定して使用
|
|
50
|
+
const scenario = scenarioAxe({
|
|
51
|
+
screenshot: true,
|
|
52
|
+
cache: true,
|
|
53
|
+
cacheDir: './cache',
|
|
54
|
+
lang: 'ja',
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### シナリオの実行
|
|
59
|
+
|
|
60
|
+
シナリオは `@d-zero/a11y-check-core` の `scenarioRunner` を通じて実行されます:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { scenarioAxe } from '@d-zero/a11y-check-axe-scenario';
|
|
64
|
+
import { scenarioRunner } from '@d-zero/a11y-check-core';
|
|
65
|
+
|
|
66
|
+
const results = await scenarioRunner(['https://example.com'], [scenarioAxe()], {
|
|
67
|
+
cache: true,
|
|
68
|
+
screenshot: true,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
console.log(`${results.violations.length} 件の違反が検出されました`);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## A11yCheckAxeOptions の説明
|
|
75
|
+
|
|
76
|
+
`A11yCheckAxeOptions` は、axe シナリオの動作を制御するオプションです。`CoreOptions` を拡張しており、以下のプロパティが利用可能です。
|
|
77
|
+
|
|
78
|
+
### プロパティ
|
|
79
|
+
|
|
80
|
+
#### `screenshot` (boolean, オプション)
|
|
81
|
+
|
|
82
|
+
違反が検出された要素のスクリーンショットを取得するかどうかを指定します。
|
|
83
|
+
|
|
84
|
+
- デフォルト: `false`
|
|
85
|
+
- `true` に設定すると、各違反箇所の視覚的なスクリーンショットが Base64 エンコードされて結果に含まれます
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
const scenario = scenarioAxe({
|
|
89
|
+
screenshot: true,
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### `cache` (boolean, オプション)
|
|
94
|
+
|
|
95
|
+
axe-core の実行結果をキャッシュするかどうかを指定します。
|
|
96
|
+
|
|
97
|
+
- デフォルト: `true`
|
|
98
|
+
- `false` に設定すると、キャッシュがクリアされ、常に新しいチェックが実行されます
|
|
99
|
+
- キャッシュキーは `URL + '#' + サイズ名` で生成されます
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
const scenario = scenarioAxe({
|
|
103
|
+
cache: false, // キャッシュを無効化
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### `cacheDir` (string, オプション)
|
|
108
|
+
|
|
109
|
+
キャッシュファイルを保存するディレクトリのパスを指定します。
|
|
110
|
+
|
|
111
|
+
- デフォルト: `.cache/a11y-check/axe`(相対パス)
|
|
112
|
+
- 指定したディレクトリが存在しない場合は自動的に作成されます
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const scenario = scenarioAxe({
|
|
116
|
+
cacheDir: './my-cache/axe-results',
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### `lang` (string, オプション)
|
|
121
|
+
|
|
122
|
+
axe-core のロケール設定を指定します。エラーメッセージやヘルプテキストの言語が変わります。
|
|
123
|
+
|
|
124
|
+
- デフォルト: `'ja'`(日本語)
|
|
125
|
+
- axe-core がサポートする任意のロケールコードを指定可能(例: `'en'`, `'fr'`, `'de'` など)
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
const scenario = scenarioAxe({
|
|
129
|
+
lang: 'en', // 英語のメッセージを使用
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## 使用例
|
|
134
|
+
|
|
135
|
+
### 例 1: 基本的なチェック
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import { scenarioAxe } from '@d-zero/a11y-check-axe-scenario';
|
|
139
|
+
import puppeteer from 'puppeteer';
|
|
140
|
+
|
|
141
|
+
const browser = await puppeteer.launch();
|
|
142
|
+
const page = await browser.newPage();
|
|
143
|
+
await page.goto('https://example.com');
|
|
144
|
+
|
|
145
|
+
const scenario = scenarioAxe();
|
|
146
|
+
const result = await scenario.exec(page, 'desktop', (message) => console.log(message));
|
|
147
|
+
|
|
148
|
+
console.log(`${result.violations.length} 件の違反が検出されました`);
|
|
149
|
+
|
|
150
|
+
await browser.close();
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 例 2: スクリーンショット付きチェック
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { scenarioAxe } from '@d-zero/a11y-check-axe-scenario';
|
|
157
|
+
import puppeteer from 'puppeteer';
|
|
158
|
+
import fs from 'fs/promises';
|
|
159
|
+
|
|
160
|
+
const browser = await puppeteer.launch();
|
|
161
|
+
const page = await browser.newPage();
|
|
162
|
+
await page.goto('https://example.com');
|
|
163
|
+
|
|
164
|
+
const scenario = scenarioAxe({
|
|
165
|
+
screenshot: true,
|
|
166
|
+
lang: 'ja',
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const result = await scenario.exec(page, 'desktop', (message) => console.log(message));
|
|
170
|
+
|
|
171
|
+
// スクリーンショットを保存
|
|
172
|
+
for (const [index, violation] of result.violations.entries()) {
|
|
173
|
+
if (violation.screenshot) {
|
|
174
|
+
const base64Data = violation.screenshot.replace(/^data:image\/png;base64,/, '');
|
|
175
|
+
await fs.writeFile(`violation-${index}.png`, Buffer.from(base64Data, 'base64'));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
await browser.close();
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### 例 3: キャッシュを無効化して毎回チェック
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import { scenarioAxe } from '@d-zero/a11y-check-axe-scenario';
|
|
186
|
+
import puppeteer from 'puppeteer';
|
|
187
|
+
|
|
188
|
+
const browser = await puppeteer.launch();
|
|
189
|
+
const page = await browser.newPage();
|
|
190
|
+
await page.goto('https://example.com');
|
|
191
|
+
|
|
192
|
+
const scenario = scenarioAxe({
|
|
193
|
+
cache: false, // 毎回新しいチェックを実行
|
|
194
|
+
lang: 'ja',
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
const result = await scenario.exec(page, 'desktop', (message) => console.log(message));
|
|
198
|
+
|
|
199
|
+
await browser.close();
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### 例 4: カスタムキャッシュディレクトリと英語メッセージ
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
import { scenarioAxe } from '@d-zero/a11y-check-axe-scenario';
|
|
206
|
+
import puppeteer from 'puppeteer';
|
|
207
|
+
|
|
208
|
+
const browser = await puppeteer.launch();
|
|
209
|
+
const page = await browser.newPage();
|
|
210
|
+
await page.goto('https://example.com');
|
|
211
|
+
|
|
212
|
+
const scenario = scenarioAxe({
|
|
213
|
+
cacheDir: './test-cache/a11y',
|
|
214
|
+
lang: 'en',
|
|
215
|
+
screenshot: true,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
const result = await scenario.exec(page, 'mobile', (message) => console.log(message));
|
|
219
|
+
|
|
220
|
+
// 違反の詳細を出力
|
|
221
|
+
for (const violation of result.violations) {
|
|
222
|
+
console.log('URL:', violation.url);
|
|
223
|
+
console.log('WCAG:', violation.wcagVersion, violation.scNumber);
|
|
224
|
+
console.log('レベル:', violation.level);
|
|
225
|
+
console.log('重要度:', violation.severity);
|
|
226
|
+
console.log('対象ノード:', violation.targetNode.value);
|
|
227
|
+
console.log('現状:', violation.asIs.value);
|
|
228
|
+
console.log('あるべき姿:', violation.toBe.value);
|
|
229
|
+
console.log('説明:', violation.explanation.value);
|
|
230
|
+
console.log('---');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
await browser.close();
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### 例 5: 複数ページのチェック
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import { scenarioAxe } from '@d-zero/a11y-check-axe-scenario';
|
|
240
|
+
import puppeteer from 'puppeteer';
|
|
241
|
+
|
|
242
|
+
const urls = [
|
|
243
|
+
'https://example.com',
|
|
244
|
+
'https://example.com/about',
|
|
245
|
+
'https://example.com/contact',
|
|
246
|
+
];
|
|
247
|
+
|
|
248
|
+
const browser = await puppeteer.launch();
|
|
249
|
+
const scenario = scenarioAxe({
|
|
250
|
+
screenshot: true,
|
|
251
|
+
cache: true,
|
|
252
|
+
cacheDir: './cache/multi-page-check',
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
for (const url of urls) {
|
|
256
|
+
const page = await browser.newPage();
|
|
257
|
+
await page.goto(url);
|
|
258
|
+
|
|
259
|
+
const result = await scenario.exec(page, 'desktop', (message) =>
|
|
260
|
+
console.log(`[${url}] ${message}`),
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
console.log(`${url}: ${result.violations.length} 件の違反`);
|
|
264
|
+
|
|
265
|
+
await page.close();
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
await browser.close();
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## 返却される違反データの構造
|
|
272
|
+
|
|
273
|
+
`scenario.exec()` が返す `violations` 配列の各要素は、以下の構造を持ちます:
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
{
|
|
277
|
+
id: string; // 違反ID(空文字列)
|
|
278
|
+
url: string; // チェック対象のURL
|
|
279
|
+
tool: string; // 使用したツール名とバージョン(例: "axe-core (vX.Y.Z)")
|
|
280
|
+
timestamp: Date; // チェック実行日時
|
|
281
|
+
component: string | null; // ランドマーク情報
|
|
282
|
+
environment: string; // 環境名(サイズ名、例: "desktop", "mobile")
|
|
283
|
+
targetNode: {
|
|
284
|
+
// 違反している要素
|
|
285
|
+
value: string; // 要素のHTML
|
|
286
|
+
}
|
|
287
|
+
asIs: {
|
|
288
|
+
// 現在の状態
|
|
289
|
+
value: string; // axe-core からの説明
|
|
290
|
+
}
|
|
291
|
+
toBe: {
|
|
292
|
+
// あるべき姿
|
|
293
|
+
value: string; // 修正方法の説明
|
|
294
|
+
}
|
|
295
|
+
explanation: {
|
|
296
|
+
// 詳細な説明
|
|
297
|
+
value: string; // 追加の説明情報
|
|
298
|
+
}
|
|
299
|
+
wcagVersion: string | null; // WCAG バージョン("WCAG2.0" または "WCAG2.1")
|
|
300
|
+
scNumber: string | null; // 達成基準番号(例: "1.1.1")
|
|
301
|
+
level: 'A' | 'AA' | 'AAA' | null; // 適合レベル
|
|
302
|
+
severity: 'high' | 'medium' | 'low' | null; // 重要度
|
|
303
|
+
screenshot: string | null; // Base64 エンコードされたスクリーンショット
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## 対応する axe-core ルール
|
|
308
|
+
|
|
309
|
+
このパッケージは、axe-core の全ルールをサポートしています。主なルールには以下が含まれます:
|
|
310
|
+
|
|
311
|
+
- **ARIA 関連**: `aria-allowed-attr`, `aria-hidden-focus`, `aria-required-attr`, など
|
|
312
|
+
- **フォーム**: `label`, `button-name`, `input-button-name`, など
|
|
313
|
+
- **画像**: `image-alt`, `object-alt`, `svg-img-alt`, など
|
|
314
|
+
- **構造**: `heading-order`, `landmark-one-main`, `list`, など
|
|
315
|
+
- **色とコントラスト**: `color-contrast`, `color-contrast-enhanced`
|
|
316
|
+
- **キーボード操作**: `tabindex`, `accesskeys`, `bypass`
|
|
317
|
+
- **多言語**: `html-has-lang`, `html-lang-valid`, `valid-lang`
|
|
318
|
+
|
|
319
|
+
詳細なルールリストは `types.ts` の `AxeRuleId` 型を参照してください。
|
|
320
|
+
|
|
321
|
+
## 型のエクスポート
|
|
322
|
+
|
|
323
|
+
### `A11yCheckAxeOptions`
|
|
324
|
+
|
|
325
|
+
`scenarioAxe`関数のオプション型です。
|
|
326
|
+
|
|
327
|
+
### `Explanation`
|
|
328
|
+
|
|
329
|
+
違反の説明情報を表す型です。
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
type Explanation = {
|
|
333
|
+
main: string; // メインの説明テキスト
|
|
334
|
+
help: string; // ヘルプテキスト
|
|
335
|
+
};
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### `AxeRuleId`
|
|
339
|
+
|
|
340
|
+
axe-coreのルールIDのユニオン型です。サポートされるすべてのルールIDが定義されています。
|
|
341
|
+
|
|
342
|
+
## ライセンス
|
|
343
|
+
|
|
344
|
+
MIT
|
|
345
|
+
|
|
346
|
+
## 作者
|
|
347
|
+
|
|
348
|
+
D-ZERO
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@d-zero/a11y-check-axe-scenario",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.8",
|
|
4
4
|
"description": "Accessibility Checker Axe Scenario",
|
|
5
5
|
"author": "D-ZERO",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,17 +24,17 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@axe-core/puppeteer": "4.11.0",
|
|
27
|
-
"@d-zero/a11y-check-core": "0.6.
|
|
27
|
+
"@d-zero/a11y-check-core": "0.6.8",
|
|
28
28
|
"@d-zero/db-wcag": "1.0.0-alpha.1",
|
|
29
|
-
"@d-zero/shared": "0.
|
|
29
|
+
"@d-zero/shared": "0.18.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"axe-core": "4.11.1",
|
|
33
|
-
"puppeteer": "24.
|
|
33
|
+
"puppeteer": "24.37.2"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"axe-core": "4.11.1",
|
|
37
|
-
"puppeteer": "24.
|
|
37
|
+
"puppeteer": "24.37.2"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "a6d7b36c485bbc0782375c6e1ad0d0606f423e97"
|
|
40
40
|
}
|