WCAG 2.1 Coverage Gap Analysis
This document maps every WCAG 2.1 success criterion against what the Accessible PDF Converter currently tests, and explains what is missing, why, and what would be needed to close each gap.
Last updated: 2026-03-07 (updated to reflect Phase 1–4 implementation and 7 new Tier 1 auto-fixes)
Background
The pipeline has three validation layers:
- Custom static validator (
wcag-validator.ts) — regex/DOM analysis of HTML strings. Currently implements 38 rules spanning Level A, AA, and AAA. 20 of these rules are auto-fixable — violations are corrected before the HTML is saved. - Browser custom checkers (
wcag-resize-checker.ts,wcag-text-spacing-checker.ts,wcag-focus-order-checker.ts) — Puppeteer-based checks for criteria that require a rendered DOM. - axe-core auditor (
axe-validator.ts) — full browser audit covering ~90+ WCAG 2.0–2.2 rules.
WCAG 2.1 contains 78 success criteria across four principles (Perceivable, Operable, Understandable, Robust). This document answers the question: which of those 78 criteria are we checking, which are we missing but could check, and which are fundamentally impossible to test without a browser?
What We Currently Check
The table below lists the rules currently implemented across all three layers and the WCAG 2.1 success criterion each maps to. For the full rule reference see docs/WCAG-VALIDATION-RULES.md.
Custom static validator (38 rules, 20 auto-fixable):
| Rule ID | WCAG SC | Level | Layer |
|---|---|---|---|
image-alt | 1.1.1 Non-text Content | A | Static |
image-alt-meaningful | 1.1.1 Non-text Content | A | Static |
sensory-characteristics | 1.3.3 Sensory Characteristics | A | Static |
heading-order | 1.3.1 Info & Relationships | A | Static |
list-structure | 1.3.1 Info & Relationships | A | Static |
definition-list | 1.3.1 Info & Relationships | A | Static |
empty-heading | 1.3.1 Info & Relationships | A | Static |
empty-table-header | 1.3.1 Info & Relationships | A | Static |
table-has-header | 1.3.1 Info & Relationships | A | Static |
scope-attr-valid | 1.3.1 Info & Relationships | A | Static |
th-has-scope | 1.3.1 Info & Relationships | A | Static |
layout-table | 1.3.2 Meaningful Sequence | A | Static |
use-of-color | 1.4.1 Use of Color | A | Static |
color-contrast | 1.4.3 Contrast Minimum | AA | Static |
images-of-text | 1.4.5 Images of Text | AA | Static |
meta-viewport | 1.4.4 / 1.4.10 | AA | Static |
document-title | 2.4.2 Page Titled | A | Static |
skip-link | 2.4.1 Bypass Blocks | A | Static |
landmark-one-main | 2.4.1 Bypass Blocks | A | Static |
link-name | 2.4.4 Link Purpose | A | Static |
heading-descriptive | 2.4.6 Headings and Labels | AA | Static |
button-name | 4.1.2 Name, Role, Value | A | Static |
label | 3.3.2 Labels or Instructions | A | Static |
html-has-lang | 3.1.1 Language of Page | A | Static |
document-lang-valid | 3.1.1 Language of Page | AA | Static |
lang-of-parts | 3.1.2 Language of Parts | AA | Static |
consistent-identification | 3.2.4 Consistent Identification | AA | Static |
duplicate-id | 4.1.1 Parsing | A | Static |
invalid-nesting | 4.1.1 Parsing | A | Static |
aria-role-valid | 4.1.2 Name, Role, Value | A | Static |
aria-allowed-attr | 4.1.2 Name, Role, Value | A | Static |
status-messages | 4.1.3 Status Messages | AA | Static |
color-contrast-enhanced | 1.4.6 Contrast Enhanced | AAA | Static |
visual-presentation | 1.4.8 Visual Presentation | AAA | Static |
images-of-text-no-exception | 1.4.9 Images of Text (No Exception) | AAA | Static |
link-purpose-sole | 2.4.9 Link Purpose (Link Only) | AAA | Static |
section-headings | 2.4.10 Section Headings | AAA | Static |
abbreviation-expansion | 3.1.4 Abbreviations | AAA | Static |
Browser custom checkers (3 checks):
| Check | WCAG SC | Level | Layer |
|---|---|---|---|
checkResizeText | 1.4.4 Resize Text | AA | Browser |
checkTextSpacing | 1.4.12 Text Spacing | AA | Browser |
checkFocusOrder | 2.4.3 Focus Order | A | Browser |
axe-core covers ~90+ additional rules across WCAG 2.0–2.2 at all levels plus best practices. See docs/WCAG-VALIDATION-RULES.md Part 3 for the full list.
Gaps: Statically Testable — All Now Implemented ✓
All 11 criteria previously identified as statically testable have been implemented (Phases 1–3). No remaining static gaps exist.
| WCAG SC | Level | Rule ID |
|---|---|---|
| 1.1.1 Non-text Content (meaningful alt) | A | image-alt-meaningful |
| 1.3.2 Meaningful Sequence (layout tables) | A | layout-table |
| 1.3.3 Sensory Characteristics | A | sensory-characteristics |
| 1.4.1 Use of Color | A | use-of-color |
| 1.4.5 Images of Text (AA) | AA | images-of-text |
| 2.4.6 Headings and Labels | AA | heading-descriptive |
| 3.1.2 Language of Parts | AA | lang-of-parts |
| 3.2.4 Consistent Identification | AA | consistent-identification |
| 4.1.1 Parsing (invalid nesting) | A | invalid-nesting |
| 4.1.2 Name, Role, Value (ARIA roles) | A | aria-role-valid + aria-allowed-attr |
| 4.1.3 Status Messages | AA | status-messages |
Browser-Required Criteria — Checked or Covered
These criteria require a rendered browser. They are addressed by the browser custom checkers (Phase 4) or by axe-core.
| WCAG SC | Level | Status | How |
|---|---|---|---|
| 1.4.4 Resize Text | AA | ✓ Checked | checkResizeText() — applies 200% zoom, measures overflow |
| 1.4.11 Non-text Contrast | AA | ✓ Covered | axe-core non-text-contrast rule |
| 1.4.12 Text Spacing | AA | ✓ Checked | checkTextSpacing() — injects WCAG spacing overrides, detects clipping |
| 2.4.3 Focus Order | A | ✓ Checked | checkFocusOrder() — computes theoretical tab sequence vs. DOM order |
| 2.4.7 Focus Visible | AA | ✓ Covered | axe-core focus-visible rule |
| 2.5.3 Label in Name | A | ✓ Covered | axe-core label-content-name-mismatch rule |
| 2.1.1 Keyboard (partial) | A | ✓ Covered | axe-core scrollable-region-focusable, tabindex rules |
Browser-Required Criteria — Not Checked
These criteria cannot be verified by this pipeline. No violation is reported, no fix is applied, and no audit entry is produced. Documents that may involve these criteria must be verified manually by the document author.
These criteria still require live user interaction, media playback, or device capabilities that cannot be automated in a static document conversion pipeline.
| WCAG SC | Level | Why not checked |
|---|---|---|
| 1.2.1 Audio-only / Video-only (Prerecorded) | A | Requires inspecting or playing actual media files |
| 1.2.2 Captions (Prerecorded) | A | Requires reading caption tracks from media |
| 1.2.3 Audio Description or Media Alternative | A | Requires media playback |
| 1.2.4 Captions (Live) | AA | Requires live media stream |
| 1.2.5 Audio Description (Prerecorded) | AA | Requires media playback |
| 1.4.13 Content on Hover or Focus | AA | Requires triggering hover/focus states — not present in static PDF output |
| 2.1.2 No Keyboard Trap | A | Requires entering every widget via keyboard and confirming focus can exit |
| 2.3.1 Three Flashes or Below Threshold | A | Requires measuring frame-by-frame animation rates |
| 2.5.1 Pointer Gestures | A | Not applicable — no multi-touch gestures in static PDF output |
| 2.5.2 Pointer Cancellation | A | Not applicable — no interaction flows in static output |
| 2.5.4 Motion Actuation | A | Not applicable — static document output |
| 3.2.1 On Focus | A | Requires triggering focus events and observing context changes |
| 3.2.2 On Input | A | Requires triggering input events |
| 3.3.1 Error Identification | A | Requires form submission with invalid data — not in static PDF output |
| 3.3.3 Error Suggestion | AA | Same as above |
| 3.3.4 Error Prevention | AA | Requires form submission with reversibility verification |
Not Applicable to PDF-to-HTML Output
These criteria are structurally irrelevant to this product. They govern dynamic web application behaviors — session management, multi-page navigation, pointer gestures, orientation locking — that are absent from a static converted document. No testing is needed and no report entry is produced.
These criteria address behaviors that do not arise in static document conversion output. They apply to web applications or sites with navigation, accounts, or dynamic interaction — not to a single converted HTML document.
| WCAG SC | Level | Reason not applicable |
|---|---|---|
| 1.3.4 Orientation | AA | Converted documents do not lock screen orientation via CSS or JS |
| 1.3.5 Identify Input Purpose | AA | The autocomplete attribute is relevant for account/login forms, not for tables or text from a PDF |
| 2.1.4 Character Key Shortcuts | AA | No single-character keyboard shortcuts are added to converted output |
| 2.2.1 Timing Adjustable | A | No time limits are imposed on static documents |
| 2.2.2 Pause, Stop, Hide | A | No auto-updating or moving content in static output |
| 2.2.6 Timeouts | AAA | No session timeouts in a static document |
| 2.4.5 Multiple Ways | AA | A single converted document has no site-level navigation to audit |
| 3.2.3 Consistent Navigation | AA | No multi-page navigation structure |
| 3.2.5 Change on Request | AAA | No dynamic context changes in static output |
| 3.3.5 Help | AAA | Context-sensitive help is a web-app concept |
| 3.3.6 Error Prevention (All) | AAA | No user data submission in static output |
Summary
| Category | Count | Notes |
|---|---|---|
| Static validator rules | 38 rules | 20 auto-fixable; 19 flagged-only (reported, not fixed) |
| Browser custom checkers | 3 checks (1.4.4, 1.4.12, 2.4.3) | Detect only — fixes require CSS/markup restructuring |
| axe-core rules (browser) | ~90+ rules | 20 auto-fixable; 30+ reported only |
| Statically testable — not yet implemented | 0 (all closed) | |
| Browser-required — now checked | 7 criteria | 1.4.4, 1.4.11, 1.4.12, 2.4.3, 2.4.7, 2.5.3, 2.1.1 (partial) |
| Browser-required — NOT checked | 16 criteria | No detection, no report, no fix — manual verification required |
| Not applicable to this product | 14 criteria | N/A — no testing needed |
All previously identified static gaps have been closed. The remaining unchecked criteria either require live user interaction (form submission, real keypress sequences), media playback, or are not applicable to static PDF-to-HTML output.