@d-zero/a11y-check-scenarios 0.2.0 → 0.3.1

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/dist/scenario.js CHANGED
@@ -133,6 +133,7 @@ export default createScenario((options) => {
133
133
  },
134
134
  ];
135
135
  return {
136
+ modulePath: import.meta.url,
136
137
  id: scenarioId,
137
138
  async exec(page, sizeName, logger) {
138
139
  // Wait Scroll End
@@ -154,7 +155,6 @@ export default createScenario((options) => {
154
155
  logger(`${test.name}: Screenshot`);
155
156
  let bin;
156
157
  let retry = 0;
157
- // eslint-disable-next-line no-constant-condition
158
158
  while (true) {
159
159
  bin = await page.screenshot({
160
160
  type: 'png',
@@ -185,7 +185,7 @@ export default createScenario((options) => {
185
185
  scenarioId,
186
186
  subKey: test.name,
187
187
  id: '',
188
- url: await page.url(),
188
+ url: page.url(),
189
189
  tool: `a11y-check-scenario01: ${test.name}`,
190
190
  timestamp: new Date(),
191
191
  component: null,
package/dist/scenario2.js CHANGED
@@ -5,6 +5,7 @@ const scenarioId = 'a11y-check/scenario02';
5
5
  export default createScenario((options) => {
6
6
  const cache = new Cache(scenarioId, options?.cacheDir);
7
7
  return {
8
+ modulePath: import.meta.url,
8
9
  id: scenarioId,
9
10
  async exec(page, sizeName, logger) {
10
11
  if (options?.cache === false) {
@@ -52,7 +53,7 @@ export default createScenario((options) => {
52
53
  needAnalysis.push({
53
54
  scenarioId,
54
55
  id: '',
55
- url: await page.url(),
56
+ url: page.url(),
56
57
  tool: 'a11y-check-scenario02',
57
58
  timestamp: new Date(),
58
59
  component: selector,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@d-zero/a11y-check-scenarios",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Accessibility Checker Scenario Collection",
5
5
  "author": "D-ZERO",
6
6
  "license": "MIT",
@@ -24,12 +24,15 @@
24
24
  "clean": "tsc --build --clean"
25
25
  },
26
26
  "dependencies": {
27
- "@d-zero/a11y-check-core": "0.2.0",
28
- "@d-zero/shared": "0.6.0",
27
+ "@d-zero/a11y-check-core": "0.4.0",
28
+ "@d-zero/shared": "0.8.0",
29
29
  "ansi-colors": "4.1.3"
30
30
  },
31
31
  "devDependencies": {
32
- "@d-zero/puppeteer-page": "0.2.0"
32
+ "puppeteer": "24.9.0"
33
33
  },
34
- "gitHead": "1eb1c03400580040119121e11ffb33acd876fe1b"
34
+ "peerDependencies": {
35
+ "puppeteer": "24.8.2"
36
+ },
37
+ "gitHead": "4e9cc7b87e0fef91b6f2d4edfb66ca9134b2491b"
35
38
  }
@@ -1,3 +0,0 @@
1
- import type { AxeResults } from 'axe-core';
2
- import type { Page } from 'puppeteer';
3
- export declare function runAxePuppeteer(page: Page, lang: string, log: (log: string) => void): Promise<AxeResults>;
@@ -1,17 +0,0 @@
1
- import { AxePuppeteer } from '@axe-core/puppeteer';
2
- import { delay } from '@d-zero/shared/delay';
3
- export async function runAxePuppeteer(page, lang, log) {
4
- const mod = await import(`axe-core/locales/${lang}.json`, {
5
- with: { type: 'json' },
6
- });
7
- const locale = mod.default;
8
- log(`Analyze%dots%`);
9
- const axeResults = await new AxePuppeteer(page)
10
- .configure({
11
- locale,
12
- })
13
- .analyze();
14
- log(`Found ${axeResults.violations.length} violations, ${axeResults.incomplete.length} incomplete issues`);
15
- await delay(600);
16
- return axeResults;
17
- }
package/dist/axe.d.ts DELETED
@@ -1,3 +0,0 @@
1
- import type { A11yCheckAxeOptions } from './types.js';
2
- declare const _default: import("@d-zero/a11y-check-core").A11yCheckScenario<A11yCheckAxeOptions>;
3
- export default _default;
package/dist/axe.js DELETED
@@ -1,25 +0,0 @@
1
- import { createScenario } from '@d-zero/a11y-check-core';
2
- import { Cache } from '@d-zero/shared/cache';
3
- import { runAxePuppeteer } from './axe-puppeteer.js';
4
- import { convertResultsFromViolations } from './convert-results-from-violations.js';
5
- const cache = new Cache('a11y-check/axe', '.cache');
6
- export default createScenario((options) => {
7
- return async (page, sizeName, log) => {
8
- if (options?.cache === false) {
9
- await cache.clear();
10
- }
11
- const axeLog = (message) => log(`🪓 ${message}`);
12
- const key = page.url() + '#' + sizeName;
13
- const cached = await cache.load(key, (key, value) => {
14
- if (key === 'timestamp') {
15
- return new Date(Date.parse(value));
16
- }
17
- return value;
18
- });
19
- if (cached) {
20
- return convertResultsFromViolations(page, cached, sizeName, options?.screenshot ?? false, axeLog);
21
- }
22
- const axeResults = await runAxePuppeteer(page, options?.lang ?? 'ja', axeLog);
23
- return convertResultsFromViolations(page, axeResults, sizeName, options?.screenshot ?? false, axeLog);
24
- };
25
- });
@@ -1,8 +0,0 @@
1
- import type { Style } from '@d-zero/a11y-check-core';
2
- import type { NodeResult } from 'axe-core';
3
- import type { Page } from 'puppeteer';
4
- export declare function convertResultsFromNode(page: Page, node: NodeResult, screenshot: boolean, log: (log: string) => void): Promise<{
5
- screenshot: string | null;
6
- style: Style | null;
7
- landmark: string | null;
8
- } | null>;
@@ -1,89 +0,0 @@
1
- import path from 'node:path';
2
- import { hash } from '@d-zero/shared/hash';
3
- export async function convertResultsFromNode(page, node, screenshot, log) {
4
- const target = node.target[0] && typeof node.target[0] === 'string' ? node.target[0] : null;
5
- if (!target) {
6
- return null;
7
- }
8
- log(`Node: ${target}`);
9
- let screenshotName = null;
10
- if (screenshot && target) {
11
- log(`Screenshot: ${target}`);
12
- const fileElement = await page.waitForSelector(target);
13
- if (fileElement) {
14
- const url = page.url();
15
- const ssName = hash(url + target) + '.png';
16
- const el = await fileElement
17
- .screenshot({
18
- path: path.resolve(process.cwd(), '.cache', ssName),
19
- })
20
- .catch(() => null);
21
- if (el) {
22
- screenshotName = ssName;
23
- }
24
- }
25
- }
26
- log(`Get style: ${target}`);
27
- const style = await page.evaluate((selector) => {
28
- const el = document.querySelector(selector);
29
- if (!el) {
30
- return null;
31
- }
32
- const style = globalThis.getComputedStyle(el);
33
- const closest = {
34
- closestBackgroundColor: null,
35
- closestBackgroundImage: null,
36
- };
37
- let current = el.parentElement;
38
- while (current) {
39
- const currentStyle = globalThis.getComputedStyle(current);
40
- if (currentStyle.backgroundColor !== 'rgba(0, 0, 0, 0)') {
41
- closest.closestBackgroundColor = currentStyle.backgroundColor;
42
- }
43
- if (currentStyle.backgroundImage !== 'none') {
44
- closest.closestBackgroundImage = currentStyle.backgroundImage;
45
- }
46
- if (closest.closestBackgroundColor || closest.closestBackgroundImage) {
47
- break;
48
- }
49
- current = current.parentElement;
50
- }
51
- return {
52
- color: style.color,
53
- backgroundColor: style.backgroundColor,
54
- backgroundImage: style.backgroundImage,
55
- ...closest,
56
- };
57
- }, target);
58
- const landmark = await page.evaluate((selector) => {
59
- const el = document.querySelector(selector);
60
- if (!el) {
61
- return null;
62
- }
63
- if (el.closest('header, [role="banner"]')) {
64
- return 'header';
65
- }
66
- if (el.closest('footer, [role="contentinfo"]')) {
67
- return 'footer';
68
- }
69
- if (el.closest('nav, [role="navigation"]')) {
70
- return 'nav';
71
- }
72
- if (el.closest('main, [role="main"]')) {
73
- return 'main';
74
- }
75
- if (el.closest('aside, [role="complementary"]')) {
76
- return 'aside';
77
- }
78
- const identicalComponent = el.closest('[id]');
79
- if (identicalComponent) {
80
- return `#${identicalComponent.id}`;
81
- }
82
- return null;
83
- }, target);
84
- return {
85
- screenshot: screenshotName,
86
- style,
87
- landmark,
88
- };
89
- }
@@ -1,4 +0,0 @@
1
- import type { A11yCheckResult } from '@d-zero/a11y-check-core';
2
- import type { AxeResults } from 'axe-core';
3
- import type { Page } from 'puppeteer';
4
- export declare function convertResultsFromViolations(page: Page, axeResults: AxeResults, sizeName: string, screenshot: boolean, log: (log: string) => void): Promise<A11yCheckResult[]>;
@@ -1,41 +0,0 @@
1
- import { convertResultsFromNode } from './convert-results-from-node.js';
2
- import { detectLevel } from './detect-level.js';
3
- import { inferExplanation } from './infer-explanation.js';
4
- import { p } from './pargraph.js';
5
- import { tagsToSCs } from './tags-to-scs.js';
6
- export async function convertResultsFromViolations(page, axeResults, sizeName, screenshot, log) {
7
- const results = [];
8
- const violations = [...axeResults.incomplete, ...axeResults.violations];
9
- for (const violation of violations) {
10
- const nodeResults = violation.nodes;
11
- for (const node of nodeResults) {
12
- const nodeResult = await convertResultsFromNode(page, node, screenshot, log);
13
- const explanation = inferExplanation(violation.id, node, nodeResult?.style ?? null);
14
- results.push({
15
- id: '',
16
- url: page.url(),
17
- tool: `${axeResults.testEngine.name} (v${axeResults.testEngine.version})`,
18
- timestamp: new Date(axeResults.timestamp),
19
- component: nodeResult?.landmark ?? null,
20
- environment: sizeName,
21
- targetNode: {
22
- value: node.html,
23
- },
24
- asIs: {
25
- value: p(`${violation.help}\n(${violation.helpUrl})`, violation.description, node.failureSummary),
26
- },
27
- toBe: {
28
- value: p(explanation?.main),
29
- },
30
- explanation: {
31
- value: p(explanation?.help),
32
- },
33
- wcagVersion: violation.tags.includes('wcag2a') ? 'WCAG2.0' : 'WCAG2.1',
34
- scNumber: tagsToSCs(violation.tags),
35
- level: detectLevel(violation.tags),
36
- screenshot: nodeResult?.screenshot ?? null,
37
- });
38
- }
39
- }
40
- return results;
41
- }
@@ -1 +0,0 @@
1
- export declare function detectLevel(tags: readonly string[]): "A" | "AA" | "AAA" | null;
@@ -1,9 +0,0 @@
1
- export function detectLevel(tags) {
2
- return tags.includes('wcag2a')
3
- ? 'A'
4
- : tags.includes('wcag2aa')
5
- ? 'AA'
6
- : tags.includes('wcag2aaa')
7
- ? 'AAA'
8
- : null;
9
- }
@@ -1 +0,0 @@
1
- export declare function detectLevel(tags: readonly string[]): "A" | "AA" | "AAA" | null;
@@ -1,9 +0,0 @@
1
- export function detectLevel(tags) {
2
- return tags.includes('wcag2')
3
- ? 'A'
4
- : tags.includes('wcag21')
5
- ? 'AA'
6
- : tags.includes('wcag2aaa')
7
- ? 'AAA'
8
- : null;
9
- }
@@ -1,4 +0,0 @@
1
- import type { AxeRuleId, Explanation } from './types.js';
2
- import type { NodeResult } from 'axe-core';
3
- import { type Style } from '@d-zero/a11y-check-core';
4
- export declare function inferExplanation(id: AxeRuleId, node: NodeResult, style: Style | null): Explanation | null;
@@ -1,390 +0,0 @@
1
- import { colorContrastCheck, ColorContrastError, } from '@d-zero/a11y-check-core';
2
- import { br, p } from './pargraph.js';
3
- export function inferExplanation(id, node, style) {
4
- switch (id) {
5
- case 'accesskeys': {
6
- return null;
7
- }
8
- case 'area-alt': {
9
- return {
10
- main: 'alt属性に「______」を設定してください。',
11
- help: '',
12
- };
13
- }
14
- case 'aria-allowed-attr': {
15
- return {
16
- main: 'aria属性に「______」を設定してください。',
17
- help: '',
18
- };
19
- }
20
- case 'aria-allowed-role': {
21
- return null;
22
- }
23
- case 'aria-braille-equivalent': {
24
- return null;
25
- }
26
- case 'aria-command-name': {
27
- return null;
28
- }
29
- case 'aria-conditional-attr': {
30
- return null;
31
- }
32
- case 'aria-deprecated-role': {
33
- return null;
34
- }
35
- case 'aria-dialog-name': {
36
- return null;
37
- }
38
- case 'aria-hidden-body': {
39
- return null;
40
- }
41
- case 'aria-hidden-focus': {
42
- return null;
43
- }
44
- case 'aria-input-field-name': {
45
- return null;
46
- }
47
- case 'aria-meter-name': {
48
- return null;
49
- }
50
- case 'aria-progressbar-name': {
51
- return null;
52
- }
53
- case 'aria-prohibited-attr': {
54
- return null;
55
- }
56
- case 'aria-required-attr': {
57
- return null;
58
- }
59
- case 'aria-required-children': {
60
- return null;
61
- }
62
- case 'aria-required-parent': {
63
- return null;
64
- }
65
- case 'aria-roledescription': {
66
- return null;
67
- }
68
- case 'aria-roles': {
69
- return null;
70
- }
71
- case 'aria-text': {
72
- return null;
73
- }
74
- case 'aria-toggle-field-name': {
75
- return null;
76
- }
77
- case 'aria-tooltip-name': {
78
- return null;
79
- }
80
- case 'aria-treeitem-name': {
81
- return null;
82
- }
83
- case 'aria-valid-attr-value': {
84
- return null;
85
- }
86
- case 'aria-valid-attr': {
87
- return null;
88
- }
89
- case 'audio-caption': {
90
- return null;
91
- }
92
- case 'autocomplete-valid': {
93
- return null;
94
- }
95
- case 'avoid-inline-spacing': {
96
- return null;
97
- }
98
- case 'blink': {
99
- return null;
100
- }
101
- case 'button-name': {
102
- return null;
103
- }
104
- case 'bypass': {
105
- return null;
106
- }
107
- case 'color-contrast-enhanced': {
108
- return null;
109
- }
110
- case 'color-contrast': {
111
- if (node.any?.[0]) {
112
- let main = '';
113
- let contrastResult = style ? colorContrastCheck(style) : null;
114
- let needCheck = null;
115
- let message = null;
116
- switch (contrastResult) {
117
- case null: {
118
- needCheck = 'N/A';
119
- message = '要素のスタイル取得に失敗しました。';
120
- break;
121
- }
122
- case ColorContrastError.DOES_NOT_DETERMINE_FOREGROUND: {
123
- needCheck = 'N/A';
124
- message = 'フォントの色が判定できません。';
125
- break;
126
- }
127
- case ColorContrastError.DOES_NOT_DETERMINE_BACKGROUND: {
128
- needCheck = 'WARNING';
129
- message = '背景色が判定できないかったので#FFFFFFとして判定しています。';
130
- contrastResult = style
131
- ? colorContrastCheck({
132
- ...style,
133
- backgroundColor: 'rgb(255, 255, 255)',
134
- })
135
- : null;
136
- break;
137
- }
138
- case ColorContrastError.FOREGROUND_COLOR_HAS_ALPHA: {
139
- needCheck = 'N/A';
140
- message = 'フォントの色に透明度が設定されています。';
141
- break;
142
- }
143
- case ColorContrastError.BACKGROUND_COLOR_HAS_ALPHA: {
144
- needCheck = 'N/A';
145
- message = '背景色に透明度が設定されています。';
146
- break;
147
- }
148
- default: {
149
- if (node.any[0].message.includes('判定できません')) {
150
- needCheck = 'WARNING';
151
- }
152
- if (contrastResult.AA === false) {
153
- main = p('AAのコントラスト比を満たしていません。', br(`前景色: ${contrastResult.foreground.hex}`, `背景色: ${contrastResult.background.hex}`, `コントラスト比: ${contrastResult.ratioText}`), 'コントラスト比は4.5:1を満たすようにしてください。');
154
- }
155
- }
156
- }
157
- return {
158
- main,
159
- help: p(needCheck ? `${needCheck} 目視で確認してください。` : null, node.any[0].message, message, typeof contrastResult === 'number'
160
- ? null
161
- : br(`前景色: ${contrastResult?.foreground.hex ?? '判定不可'}`, `背景色: ${contrastResult?.background.hex ?? '判定不可'}`, `コントラスト比: ${contrastResult?.ratioText ?? '判定不可'}`, `AA: ${contrastResult?.AA ? '適合' : '不適合'}`, `AAA: ${contrastResult?.AAA ? '適合' : '不適合'}`), br(`font-size: ${node.any[0].data.fontSize}`, `font-weight: ${node.any[0].data.fontWeight}`, `color: ${style?.color ?? null}`, `background-color: ${style?.backgroundColor ?? null}`, `background-image: ${style?.backgroundImage ?? null}`, `先祖要素 background-color: ${style?.closestBackgroundColor ?? null}`, `先祖要素 background-image: ${style?.closestBackgroundImage ?? null}`)),
162
- };
163
- }
164
- return null;
165
- }
166
- case 'css-orientation-lock': {
167
- return null;
168
- }
169
- case 'definition-list': {
170
- return null;
171
- }
172
- // cspell:disable-next-line
173
- case 'dlitem': {
174
- return null;
175
- }
176
- case 'document-title': {
177
- return null;
178
- }
179
- case 'duplicate-id-active': {
180
- return null;
181
- }
182
- case 'duplicate-id-aria': {
183
- return null;
184
- }
185
- case 'duplicate-id': {
186
- return null;
187
- }
188
- case 'empty-heading': {
189
- return null;
190
- }
191
- case 'empty-table-header': {
192
- // td要素に変更してください。
193
- return null;
194
- }
195
- case 'focus-order-semantics': {
196
- return null;
197
- }
198
- case 'form-field-multiple-labels': {
199
- // 「性別」のラベルはfieldset/legend要素をつかって複数のラジオボタンをグルーピングするように修正してください。
200
- return null;
201
- }
202
- case 'frame-focusable-content': {
203
- return null;
204
- }
205
- case 'frame-tested': {
206
- return null;
207
- }
208
- case 'frame-title-unique': {
209
- return null;
210
- }
211
- case 'frame-title': {
212
- return null;
213
- }
214
- case 'heading-order': {
215
- return null;
216
- }
217
- case 'hidden-content': {
218
- return null;
219
- }
220
- case 'html-has-lang': {
221
- return {
222
- main: 'html要素にlang属性を設定してください。日本語の場合は「ja」、英語の場合は「en」を設定してください。',
223
- help: '',
224
- };
225
- }
226
- case 'html-lang-valid': {
227
- return null;
228
- }
229
- case 'html-xml-lang-mismatch': {
230
- return null;
231
- }
232
- case 'identical-links-same-purpose': {
233
- return null;
234
- }
235
- case 'image-alt': {
236
- return null;
237
- }
238
- case 'image-redundant-alt': {
239
- return null;
240
- }
241
- case 'input-button-name': {
242
- return null;
243
- }
244
- case 'input-image-alt': {
245
- return null;
246
- }
247
- case 'label-content-name-mismatch': {
248
- return null;
249
- }
250
- case 'label-title-only': {
251
- return null;
252
- }
253
- case 'label': {
254
- return null;
255
- }
256
- case 'landmark-banner-is-top-level': {
257
- return null;
258
- }
259
- case 'landmark-complementary-is-top-level': {
260
- return null;
261
- }
262
- case 'landmark-contentinfo-is-top-level': {
263
- return null;
264
- }
265
- case 'landmark-main-is-top-level': {
266
- return null;
267
- }
268
- case 'landmark-no-duplicate-banner': {
269
- return null;
270
- }
271
- case 'landmark-no-duplicate-contentinfo': {
272
- return null;
273
- }
274
- case 'landmark-no-duplicate-main': {
275
- return null;
276
- }
277
- case 'landmark-one-main': {
278
- return {
279
- main: 'ページのメインコンテンツをmain要素で囲んでください。header要素やfooter要素とは別の領域が望ましいです。',
280
- help: '',
281
- };
282
- }
283
- case 'landmark-unique': {
284
- return null;
285
- }
286
- case 'link-in-text-block': {
287
- return null;
288
- }
289
- case 'link-name': {
290
- return null;
291
- }
292
- case 'list': {
293
- return null;
294
- }
295
- case 'listitem': {
296
- return null;
297
- }
298
- case 'marquee': {
299
- return null;
300
- }
301
- case 'meta-refresh-no-exceptions': {
302
- return null;
303
- }
304
- case 'meta-refresh': {
305
- return null;
306
- }
307
- case 'meta-viewport-large': {
308
- return null;
309
- }
310
- case 'meta-viewport': {
311
- return null;
312
- }
313
- case 'nested-interactive': {
314
- return null;
315
- }
316
- case 'no-autoplay-audio': {
317
- return null;
318
- }
319
- case 'object-alt': {
320
- return null;
321
- }
322
- case 'p-as-heading': {
323
- return null;
324
- }
325
- case 'page-has-heading-one': {
326
- return null;
327
- }
328
- case 'presentation-role-conflict': {
329
- return null;
330
- }
331
- case 'region': {
332
- return {
333
- main: 'main要素、header要素、footer要素などのランドマーク要素のいずれかの中にあるようにしてください。',
334
- help: '',
335
- };
336
- }
337
- case 'role-img-alt': {
338
- return null;
339
- }
340
- case 'scope-attr-valid': {
341
- return null;
342
- }
343
- case 'scrollable-region-focusable': {
344
- // tabindex="0"を設定してください。
345
- return null;
346
- }
347
- case 'select-name': {
348
- return null;
349
- }
350
- case 'server-side-image-map': {
351
- return null;
352
- }
353
- case 'skip-link': {
354
- return null;
355
- }
356
- case 'summary-name': {
357
- return null;
358
- }
359
- case 'svg-img-alt': {
360
- return null;
361
- }
362
- case 'tabindex': {
363
- return null;
364
- }
365
- case 'table-duplicate-name': {
366
- return null;
367
- }
368
- case 'table-fake-caption': {
369
- return null;
370
- }
371
- case 'target-size': {
372
- return null;
373
- }
374
- case 'td-has-header': {
375
- return null;
376
- }
377
- case 'td-headers-attr': {
378
- return null;
379
- }
380
- case 'th-has-data-cells': {
381
- return null;
382
- }
383
- case 'valid-lang': {
384
- return null;
385
- }
386
- case 'video-caption': {
387
- return null;
388
- }
389
- }
390
- }
@@ -1,2 +0,0 @@
1
- export declare function p(...texts: (string | null | undefined)[]): string;
2
- export declare function br(...texts: (string | null | undefined)[]): string;
package/dist/pargraph.js DELETED
@@ -1,6 +0,0 @@
1
- export function p(...texts) {
2
- return texts.filter(Boolean).join('\n\n');
3
- }
4
- export function br(...texts) {
5
- return texts.filter(Boolean).join('\n');
6
- }
package/dist/sc.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare function sc(tags: string[]): string;
package/dist/sc.js DELETED
@@ -1,23 +0,0 @@
1
- import { wcag } from '@d-zero/db-wcag';
2
- const scVersions = new Set(
3
- // @ts-ignore
4
- Object.keys(wcag.successCriterions['wcag_2.2'].en));
5
- export function sc(tags) {
6
- return tags.map(_sc).filter(Boolean).join('\n');
7
- }
8
- function _sc(tag) {
9
- if (!tag.startsWith('wcag') || tag.endsWith('a')) {
10
- return null;
11
- }
12
- const num = /\d+/.exec(tag)?.[0];
13
- if (!num) {
14
- return null;
15
- }
16
- for (const version of scVersions) {
17
- const crushedNum = version.replaceAll('.', '');
18
- if (tag === crushedNum) {
19
- return version;
20
- }
21
- }
22
- return null;
23
- }
@@ -1,2 +0,0 @@
1
- export declare function tagsToSCs(tags: string[]): string;
2
- export declare function tagToSC(tag: string): "1.1.1" | "1.2.1" | "1.2.2" | "1.2.3" | "1.2.4" | "1.2.5" | "1.2.6" | "1.2.7" | "1.2.8" | "1.2.9" | "1.3.1" | "1.3.2" | "1.3.3" | "1.3.4" | "1.3.5" | "1.3.6" | "1.4.1" | "1.4.2" | "1.4.3" | "1.4.4" | "1.4.5" | "1.4.6" | "1.4.7" | "1.4.8" | "1.4.9" | "1.4.10" | "1.4.11" | "1.4.12" | "1.4.13" | "2.1.1" | "2.1.2" | "2.1.3" | "2.1.4" | "2.2.1" | "2.2.2" | "2.2.3" | "2.2.4" | "2.2.5" | "2.2.6" | "2.3.1" | "2.3.2" | "2.3.3" | "2.4.1" | "2.4.2" | "2.4.3" | "2.4.4" | "2.4.5" | "2.4.6" | "2.4.7" | "2.4.8" | "2.4.9" | "2.4.10" | "2.4.11" | "2.4.12" | "2.4.13" | "2.5.1" | "2.5.2" | "2.5.3" | "2.5.4" | "2.5.5" | "2.5.6" | "2.5.7" | "2.5.8" | "3.1.1" | "3.1.2" | "3.1.3" | "3.1.4" | "3.1.5" | "3.1.6" | "3.2.1" | "3.2.2" | "3.2.3" | "3.2.4" | "3.2.5" | "3.2.6" | "3.3.1" | "3.3.2" | "3.3.3" | "3.3.4" | "3.3.5" | "3.3.6" | "3.3.7" | "3.3.8" | "3.3.9" | "4.1.2" | "4.1.3" | null;
@@ -1,23 +0,0 @@
1
- import { wcag } from '@d-zero/db-wcag';
2
- const scVersions = new Set(
3
- // @ts-ignore
4
- Object.keys(wcag.successCriterions['wcag_2.2'].en));
5
- export function tagsToSCs(tags) {
6
- return tags.map(tagToSC).filter(Boolean).join('\n');
7
- }
8
- export function tagToSC(tag) {
9
- if (!tag.startsWith('wcag') || tag.endsWith('a')) {
10
- return null;
11
- }
12
- const num = /\d+/.exec(tag)?.[0];
13
- if (!num) {
14
- return null;
15
- }
16
- for (const version of scVersions) {
17
- const crushedNum = version.replaceAll('.', '');
18
- if (num === crushedNum) {
19
- return version;
20
- }
21
- }
22
- return null;
23
- }