@diegovelasquezweb/a11y-engine 0.6.1 → 0.6.2

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.
@@ -9,18 +9,24 @@ export default {
9
9
  id: "axe",
10
10
  label: "axe-core",
11
11
  description: "Primary WCAG rule engine for rendered DOM violations.",
12
+ coverage: "Broadest WCAG rule coverage with over 90 checks across all four principles. Catches missing labels, contrast failures, landmark structure, and ARIA misuse.",
13
+ speed: "Fast",
12
14
  defaultEnabled: true,
13
15
  },
14
16
  {
15
17
  id: "cdp",
16
18
  label: "CDP",
17
19
  description: "Chrome accessibility tree checks for name/role/focus gaps.",
20
+ coverage: "Inspects the browser accessibility tree directly via Chrome DevTools Protocol. Catches name and role issues that axe misses at the DOM level.",
21
+ speed: "Medium",
18
22
  defaultEnabled: true,
19
23
  },
20
24
  {
21
25
  id: "pa11y",
22
26
  label: "pa11y",
23
27
  description: "HTML CodeSniffer checks to complement axe coverage.",
28
+ coverage: "Runs HTML CodeSniffer against the rendered page. Complements axe with additional HTML-level checks and alternative rule interpretations.",
29
+ speed: "Medium",
24
30
  defaultEnabled: true,
25
31
  },
26
32
  ],
@@ -36,7 +42,7 @@ export default {
36
42
  id: "crawlDepth",
37
43
  label: "Crawl depth",
38
44
  description: "Controls how many link levels are explored from the start page.",
39
- defaultValue: 2,
45
+ defaultValue: 1,
40
46
  type: "number",
41
47
  },
42
48
  {
@@ -45,29 +51,48 @@ export default {
45
51
  description: "Navigation readiness event before scanning each page.",
46
52
  defaultValue: "domcontentloaded",
47
53
  type: "enum",
48
- allowedValues: ["domcontentloaded", "load", "networkidle"],
54
+ allowedValues: [
55
+ {
56
+ value: "domcontentloaded",
57
+ label: "DOM Ready",
58
+ description: "Fires when the initial HTML is parsed. Fastest — use for server-rendered pages.",
59
+ },
60
+ {
61
+ value: "load",
62
+ label: "Page Load",
63
+ description: "Waits for all resources (images, scripts) to finish loading. Good for pages with critical above-the-fold assets.",
64
+ },
65
+ {
66
+ value: "networkidle",
67
+ label: "Network Idle",
68
+ description: "Waits until no network requests for 500ms. Best for SPAs and pages with deferred content loading.",
69
+ },
70
+ ],
49
71
  },
50
72
  {
51
73
  id: "timeoutMs",
52
74
  label: "Timeout",
53
- description: "Maximum navigation wait time per route in milliseconds.",
75
+ description: "Maximum time to wait for each page to load before aborting.",
54
76
  defaultValue: 30000,
55
77
  type: "number",
56
78
  },
57
79
  {
58
80
  id: "viewport",
59
81
  label: "Viewport",
60
- description: "Browser viewport used during scan emulation.",
82
+ description: "Browser window size used during the audit.",
61
83
  defaultValue: "1280x800",
62
84
  type: "text",
63
85
  },
64
86
  {
65
87
  id: "colorScheme",
66
88
  label: "Color scheme",
67
- description: "Emulated light or dark color-scheme preference.",
89
+ description: "Emulates light or dark mode during the scan.",
68
90
  defaultValue: "light",
69
91
  type: "enum",
70
- allowedValues: ["light", "dark"],
92
+ allowedValues: [
93
+ { value: "light", label: "Light" },
94
+ { value: "dark", label: "Dark" },
95
+ ],
71
96
  },
72
97
  {
73
98
  id: "axeTags",
@@ -78,6 +103,95 @@ export default {
78
103
  },
79
104
  ],
80
105
  },
106
+ conformanceLevels: [
107
+ {
108
+ id: "A",
109
+ label: "Level A",
110
+ badge: "Minimum",
111
+ description: "The baseline: essential requirements that remove the most severe barriers.",
112
+ shortDescription: "Minimum baseline",
113
+ hint: "Failing Level A means some users cannot access the content at all.",
114
+ tags: ["wcag2a", "wcag21a", "wcag22a"],
115
+ },
116
+ {
117
+ id: "AA",
118
+ label: "Level AA",
119
+ badge: "Standard",
120
+ description: "The recommended target for most websites — required by most accessibility laws.",
121
+ shortDescription: "Recommended for most websites",
122
+ hint: "Referenced by ADA, Section 508, EN 301 549, and EAA.",
123
+ tags: ["wcag2a", "wcag21a", "wcag22a", "wcag2aa", "wcag21aa", "wcag22aa"],
124
+ },
125
+ {
126
+ id: "AAA",
127
+ label: "Level AAA",
128
+ badge: "Enhanced",
129
+ description: "The highest conformance level — not required but beneficial for specialized audiences.",
130
+ shortDescription: "Strictest — not required by most regulations",
131
+ hint: "Full AAA conformance is not recommended as a general policy for entire sites.",
132
+ tags: ["wcag2a", "wcag21a", "wcag22a", "wcag2aa", "wcag21aa", "wcag22aa", "wcag2aaa"],
133
+ },
134
+ ],
135
+ wcagPrinciples: [
136
+ {
137
+ id: "perceivable",
138
+ name: "Perceivable",
139
+ description: "Information and UI components must be presentable to users in ways they can perceive.",
140
+ criterionPrefix: " 1.",
141
+ number: 1,
142
+ },
143
+ {
144
+ id: "operable",
145
+ name: "Operable",
146
+ description: "UI components and navigation must be operable.",
147
+ criterionPrefix: " 2.",
148
+ number: 2,
149
+ },
150
+ {
151
+ id: "understandable",
152
+ name: "Understandable",
153
+ description: "Information and the operation of the UI must be understandable.",
154
+ criterionPrefix: " 3.",
155
+ number: 3,
156
+ },
157
+ {
158
+ id: "robust",
159
+ name: "Robust",
160
+ description: "Content must be robust enough to be interpreted by a wide variety of user agents.",
161
+ criterionPrefix: " 4.",
162
+ number: 4,
163
+ },
164
+ ],
165
+ severityLevels: [
166
+ {
167
+ id: "Critical",
168
+ label: "Critical",
169
+ shortDescription: "Functional blockers",
170
+ description: "Blocks key user tasks with no practical workaround.",
171
+ order: 1,
172
+ },
173
+ {
174
+ id: "Serious",
175
+ label: "Serious",
176
+ shortDescription: "Serious impediments",
177
+ description: "Major barrier with difficult workaround or significant friction.",
178
+ order: 2,
179
+ },
180
+ {
181
+ id: "Moderate",
182
+ label: "Moderate",
183
+ shortDescription: "Significant friction",
184
+ description: "Usability degradation that still allows task completion.",
185
+ order: 3,
186
+ },
187
+ {
188
+ id: "Minor",
189
+ label: "Minor",
190
+ shortDescription: "Minor violations",
191
+ description: "Lower-impact issue that still reduces quality and consistency.",
192
+ order: 4,
193
+ },
194
+ ],
81
195
  personas: {
82
196
  screenReader: {
83
197
  label: "Screen Reader Users",
@@ -96,16 +210,17 @@ export default {
96
210
  description: "People who benefit from predictable behavior and clear instructions.",
97
211
  },
98
212
  },
99
- tooltips: {
100
- scoreGauge: {
213
+ concepts: {
214
+ score: {
101
215
  title: "Compliance Score",
102
216
  body: "Weighted score from severity totals. It is a prioritization signal, not legal certification.",
217
+ context: "Based on automated accessibility technical checks.",
103
218
  },
104
219
  wcagStatus: {
105
220
  title: "WCAG Status",
106
221
  body: "Pass = no issues. Conditional Pass = only Moderate/Minor. Fail = any Critical/Serious remaining.",
107
222
  },
108
- severityCards: {
223
+ severityBreakdown: {
109
224
  title: "Severity Breakdown",
110
225
  body: "Issue counts grouped by user impact and task completion risk.",
111
226
  },
@@ -116,12 +231,35 @@ export default {
116
231
  quickWins: {
117
232
  title: "Quick Wins",
118
233
  body: "Top Critical/Serious findings that already include concrete fix code.",
234
+ context: "High-priority issues with ready-to-use code fixes for immediate remediation.",
119
235
  },
120
236
  findingsFilter: {
121
237
  title: "Findings Filter",
122
238
  body: "Filter findings by severity or WCAG principle to focus remediation.",
123
239
  },
124
240
  },
241
+ outputs: {
242
+ pdf: {
243
+ title: "Stakeholder Report",
244
+ description: "A formal PDF accessibility compliance report.",
245
+ detail: "Designed for clients, non-technical stakeholders, project managers, and auditors. Includes the compliance score, WCAG status, severity breakdown, and a prioritized list of findings with recommended fixes — formatted for sharing and sign-off.",
246
+ },
247
+ checklist: {
248
+ title: "Manual Checklist",
249
+ description: "An interactive WCAG 2.2 AA manual testing checklist.",
250
+ detail: "Automated scanners catch around 30–40% of accessibility issues. This checklist covers the remaining manual checks — keyboard navigation, screen reader behavior, focus management, motion, zoom, and cognitive accessibility. Use it alongside the automated findings for a complete audit.",
251
+ },
252
+ json: {
253
+ title: "JSON Export",
254
+ description: "Machine-readable snapshot of all findings, scores, and metadata.",
255
+ detail: "Useful for integrating with CI/CD pipelines, tracking compliance over time, importing into dashboards, or diffing two audits programmatically. Includes all enriched findings with WCAG mappings, fix code, severity, and page location.",
256
+ },
257
+ remediation: {
258
+ title: "Remediation Guide",
259
+ description: "A structured Markdown guide for AI agents and developers.",
260
+ detail: "Contains prioritized fixes with ready-to-use code snippets, framework-specific guardrails, WCAG mappings, selector context, and verification commands. Designed to be fed directly into an AI coding agent (Claude, Copilot, Cursor) or used by developers for systematic remediation.",
261
+ },
262
+ },
125
263
  docs: {
126
264
  sections: [
127
265
  {
@@ -135,24 +273,21 @@ export default {
135
273
  {
136
274
  id: "wcag-2-0",
137
275
  title: "WCAG 2.0",
138
- tag: "2008",
139
- tagVariant: "neutral",
276
+ badge: "2008",
140
277
  summary: "The original W3C recommendation that established the foundation for web accessibility.",
141
278
  body: "Introduced the four principles (Perceivable, Operable, Understandable, Robust) and three conformance levels (A, AA, AAA). Covers core requirements like text alternatives, keyboard access, color contrast, and form labels. Still widely referenced in legal frameworks worldwide.",
142
279
  },
143
280
  {
144
281
  id: "wcag-2-1",
145
282
  title: "WCAG 2.1",
146
- tag: "2018",
147
- tagVariant: "info",
283
+ badge: "2018",
148
284
  summary: "Extended 2.0 with 17 new success criteria for mobile, low vision, and cognitive disabilities.",
149
285
  body: "Added criteria for touch targets (2.5.5), text spacing (1.4.12), content reflow (1.4.10), orientation (1.3.4), and input purpose (1.3.5). Required by the European Accessibility Act (EAA) and referenced in updated ADA guidance. All 2.0 criteria remain \u2014 2.1 is a superset.",
150
286
  },
151
287
  {
152
288
  id: "wcag-2-2",
153
289
  title: "WCAG 2.2",
154
- tag: "2023",
155
- tagVariant: "violet",
290
+ badge: "2023",
156
291
  summary: "The latest version, adding 9 new criteria focused on cognitive accessibility and consistent help.",
157
292
  body: "Key additions include consistent help (3.2.6), accessible authentication (3.3.8), dragging movements (2.5.7), and focus appearance (2.4.11/2.4.12). Removed criterion 4.1.1 (Parsing) as it\u2019s now handled by modern browsers. Supersedes both 2.0 and 2.1 \u2014 all prior criteria are included.",
158
293
  },
@@ -165,24 +300,21 @@ export default {
165
300
  {
166
301
  id: "level-a",
167
302
  title: "Level A",
168
- tag: "Minimum",
169
- tagVariant: "warning",
303
+ badge: "Minimum",
170
304
  summary: "The baseline: essential requirements that remove the most severe barriers.",
171
305
  body: "Covers fundamentals like non-text content alternatives (1.1.1), keyboard operability (2.1.1), page titles (2.4.2), and language of the page (3.1.1). Failing Level A means some users cannot access the content at all. Every site should meet Level A at minimum.",
172
306
  },
173
307
  {
174
308
  id: "level-aa",
175
309
  title: "Level AA",
176
- tag: "Standard",
177
- tagVariant: "success",
310
+ badge: "Standard",
178
311
  summary: "The recommended target for most websites \u2014 required by most accessibility laws.",
179
312
  body: "Includes all Level A criteria plus requirements for color contrast (1.4.3 \u2014 4.5:1 ratio), resize text (1.4.4), focus visible (2.4.7), error suggestion (3.3.3), and consistent navigation (3.2.3). Referenced by ADA, Section 508, EN 301 549, and EAA. This is the standard the scanner defaults to.",
180
313
  },
181
314
  {
182
315
  id: "level-aaa",
183
316
  title: "Level AAA",
184
- tag: "Enhanced",
185
- tagVariant: "purple",
317
+ badge: "Enhanced",
186
318
  summary: "The highest conformance level \u2014 not required but beneficial for specialized audiences.",
187
319
  body: "Adds stricter contrast (1.4.6 \u2014 7:1 ratio), sign language for audio (1.2.6), extended audio description (1.2.7), and reading level (3.1.5). Full AAA conformance is not recommended as a general policy because some criteria cannot be satisfied for all content types. Useful for targeted sections like education or government services.",
188
320
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegovelasquezweb/a11y-engine",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "WCAG 2.2 AA accessibility audit engine — scanner, analyzer, and report builders",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/index.d.mts CHANGED
@@ -217,16 +217,87 @@ export interface ScannerEngineHelp {
217
217
  id: "axe" | "cdp" | "pa11y" | string;
218
218
  label: string;
219
219
  description: string;
220
+ coverage: string;
221
+ speed: "Fast" | "Medium" | "Slow" | string;
220
222
  defaultEnabled: boolean;
221
223
  }
222
224
 
225
+ export interface EnumOptionValue {
226
+ value: string;
227
+ label: string;
228
+ description?: string;
229
+ }
230
+
223
231
  export interface ScannerOptionHelp {
224
232
  id: string;
225
233
  label: string;
226
234
  description: string;
227
235
  defaultValue: unknown;
228
236
  type: string;
229
- allowedValues?: unknown[];
237
+ allowedValues?: unknown[] | EnumOptionValue[];
238
+ }
239
+
240
+ export interface ConformanceLevel {
241
+ id: "A" | "AA" | "AAA";
242
+ label: string;
243
+ badge: string;
244
+ description: string;
245
+ shortDescription: string;
246
+ hint: string;
247
+ tags: string[];
248
+ }
249
+
250
+ export interface WcagPrinciple {
251
+ id: string;
252
+ name: string;
253
+ description: string;
254
+ criterionPrefix: string;
255
+ number: number;
256
+ }
257
+
258
+ export interface SeverityLevel {
259
+ id: "Critical" | "Serious" | "Moderate" | "Minor";
260
+ label: string;
261
+ shortDescription: string;
262
+ description: string;
263
+ order: number;
264
+ }
265
+
266
+ export interface OutputFormatInfo {
267
+ title: string;
268
+ description: string;
269
+ detail: string;
270
+ }
271
+
272
+ export interface OutputsInfo {
273
+ pdf: OutputFormatInfo;
274
+ checklist: OutputFormatInfo;
275
+ json: OutputFormatInfo;
276
+ remediation: OutputFormatInfo;
277
+ }
278
+
279
+ export interface ConformanceLevelsResult {
280
+ locale: string;
281
+ version: string;
282
+ conformanceLevels: ConformanceLevel[];
283
+ }
284
+
285
+ export interface WcagPrinciplesResult {
286
+ locale: string;
287
+ version: string;
288
+ wcagPrinciples: WcagPrinciple[];
289
+ }
290
+
291
+ export interface SeverityLevelsResult {
292
+ locale: string;
293
+ version: string;
294
+ severityLevels: SeverityLevel[];
295
+ }
296
+
297
+ export interface OutputsInfoResult {
298
+ locale: string;
299
+ version: string;
300
+ outputs: OutputsInfo;
230
301
  }
231
302
 
232
303
  export interface ScannerHelp {
@@ -252,9 +323,10 @@ export interface PersonaReference {
252
323
  personas: PersonaReferenceItem[];
253
324
  }
254
325
 
255
- export interface UiTooltip {
326
+ export interface ConceptEntry {
256
327
  title: string;
257
328
  body: string;
329
+ context?: string;
258
330
  }
259
331
 
260
332
  export interface GlossaryEntry {
@@ -266,8 +338,7 @@ export interface DocArticle {
266
338
  id: string;
267
339
  title: string;
268
340
  icon?: string;
269
- tag?: string;
270
- tagVariant?: string;
341
+ badge?: string;
271
342
  summary: string;
272
343
  body: string;
273
344
  }
@@ -292,7 +363,7 @@ export interface KnowledgeDocs {
292
363
  export interface UiHelp {
293
364
  locale: string;
294
365
  version: string;
295
- tooltips: Record<string, UiTooltip>;
366
+ concepts: Record<string, ConceptEntry>;
296
367
  glossary: GlossaryEntry[];
297
368
  }
298
369
 
@@ -305,9 +376,13 @@ export interface EngineKnowledge {
305
376
  options: ScannerOptionHelp[];
306
377
  };
307
378
  personas: PersonaReferenceItem[];
308
- tooltips: Record<string, UiTooltip>;
379
+ concepts: Record<string, ConceptEntry>;
309
380
  glossary: GlossaryEntry[];
310
381
  docs: KnowledgeDocs;
382
+ conformanceLevels: ConformanceLevel[];
383
+ wcagPrinciples: WcagPrinciple[];
384
+ severityLevels: SeverityLevel[];
385
+ outputs: OutputsInfo;
311
386
  }
312
387
 
313
388
  export interface KnowledgeOptions {
@@ -405,4 +480,12 @@ export function getPersonaReference(options?: KnowledgeOptions): PersonaReferenc
405
480
 
406
481
  export function getUiHelp(options?: KnowledgeOptions): UiHelp;
407
482
 
483
+ export function getConformanceLevels(options?: KnowledgeOptions): ConformanceLevelsResult;
484
+
485
+ export function getWcagPrinciples(options?: KnowledgeOptions): WcagPrinciplesResult;
486
+
487
+ export function getSeverityLevels(options?: KnowledgeOptions): SeverityLevelsResult;
488
+
489
+ export function getOutputsInfo(options?: KnowledgeOptions): OutputsInfoResult;
490
+
408
491
  export function getKnowledge(options?: KnowledgeOptions): EngineKnowledge;
package/src/index.mjs CHANGED
@@ -515,7 +515,7 @@ export function getUiHelp(options = {}) {
515
515
  return {
516
516
  locale,
517
517
  version: payload.version || "1.0.0",
518
- tooltips: clone(localePayload.tooltips || {}),
518
+ concepts: clone(localePayload.concepts || {}),
519
519
  glossary: clone(localePayload.glossary || []),
520
520
  };
521
521
  }
@@ -527,10 +527,82 @@ export function getUiHelp(options = {}) {
527
527
  * @param {{ locale?: string }} [options={}]
528
528
  * @returns {{ locale: string, version: string, scanner: object, personas: object[], tooltips: Record<string, object>, glossary: object[] }}
529
529
  */
530
+ /**
531
+ * Returns conformance level definitions with WCAG axe-core tag mappings.
532
+ *
533
+ * @param {{ locale?: string }} [options={}]
534
+ * @returns {{ locale: string, version: string, conformanceLevels: object[] }}
535
+ */
536
+ export function getConformanceLevels(options = {}) {
537
+ const locale = resolveKnowledgeLocale(options.locale || "en");
538
+ const payload = getKnowledgeData();
539
+ const levels = payload.locales[locale]?.conformanceLevels || [];
540
+ return {
541
+ locale,
542
+ version: payload.version || "1.0.0",
543
+ conformanceLevels: clone(levels),
544
+ };
545
+ }
546
+
547
+ /**
548
+ * Returns the four WCAG principles with their criterion prefix patterns.
549
+ *
550
+ * @param {{ locale?: string }} [options={}]
551
+ * @returns {{ locale: string, version: string, wcagPrinciples: object[] }}
552
+ */
553
+ export function getWcagPrinciples(options = {}) {
554
+ const locale = resolveKnowledgeLocale(options.locale || "en");
555
+ const payload = getKnowledgeData();
556
+ const principles = payload.locales[locale]?.wcagPrinciples || [];
557
+ return {
558
+ locale,
559
+ version: payload.version || "1.0.0",
560
+ wcagPrinciples: clone(principles),
561
+ };
562
+ }
563
+
564
+ /**
565
+ * Returns severity level definitions with labels, descriptions, and ordering.
566
+ *
567
+ * @param {{ locale?: string }} [options={}]
568
+ * @returns {{ locale: string, version: string, severityLevels: object[] }}
569
+ */
570
+ export function getSeverityLevels(options = {}) {
571
+ const locale = resolveKnowledgeLocale(options.locale || "en");
572
+ const payload = getKnowledgeData();
573
+ const levels = payload.locales[locale]?.severityLevels || [];
574
+ return {
575
+ locale,
576
+ version: payload.version || "1.0.0",
577
+ severityLevels: clone(levels),
578
+ };
579
+ }
580
+
581
+ /**
582
+ * Returns output format descriptions for each report type the engine produces.
583
+ *
584
+ * @param {{ locale?: string }} [options={}]
585
+ * @returns {{ locale: string, version: string, outputs: object }}
586
+ */
587
+ export function getOutputsInfo(options = {}) {
588
+ const locale = resolveKnowledgeLocale(options.locale || "en");
589
+ const payload = getKnowledgeData();
590
+ const outputs = payload.locales[locale]?.outputs || {};
591
+ return {
592
+ locale,
593
+ version: payload.version || "1.0.0",
594
+ outputs: clone(outputs),
595
+ };
596
+ }
597
+
530
598
  export function getKnowledge(options = {}) {
531
599
  const scanner = getScannerHelp(options);
532
600
  const personas = getPersonaReference(options);
533
601
  const ui = getUiHelp(options);
602
+ const conformance = getConformanceLevels(options);
603
+ const principles = getWcagPrinciples(options);
604
+ const severity = getSeverityLevels(options);
605
+ const outputsInfo = getOutputsInfo(options);
534
606
 
535
607
  const payload = getKnowledgeData();
536
608
  const docs = clone(payload.locales[scanner.locale]?.docs ?? { sections: [] });
@@ -544,9 +616,13 @@ export function getKnowledge(options = {}) {
544
616
  options: scanner.options,
545
617
  },
546
618
  personas: personas.personas,
547
- tooltips: ui.tooltips,
619
+ concepts: ui.concepts,
548
620
  glossary: ui.glossary,
549
621
  docs,
622
+ conformanceLevels: conformance.conformanceLevels,
623
+ wcagPrinciples: principles.wcagPrinciples,
624
+ severityLevels: severity.severityLevels,
625
+ outputs: outputsInfo.outputs,
550
626
  };
551
627
  }
552
628