Regulatory accessibility test engine with Virtual DOM and Shadow DOM support
npm install @holmdigital/engine

!TypeScript

> Regulatory accessibility test engine with Virtual DOM, Shadow DOM support, and built-in legal compliance reporting.
Most accessibility tools give you technical errors (e.g., "Color contrast must be 4.5:1"). This engine bridges the gap between technical code validation (using axe-core) and legal compliance (EN 301 549, Section 508, DOS-lagen).
It handles the heavy lifting of:
1. Mapping technical failures to specific legal clauses.
2. Validating HTML structure to ensure test accuracy.
3. Reporting in multiple languages (EN, SV, NL, DE, FR, ES) for non-technical stakeholders.
4. CI/CD Pipeline Integration with automatic enforcement.
For a comprehensive guide on CLI flags, CI/CD integration, and configuration files, see the Engine Library Catalog.
- Regulatory Mapping: Maps technical failures to EU laws (EN 301 549, EAA).
- HTML Structure Validation: Built-in html-validate checks to prevent false positives/negatives.
- Internationalization (i18n): Comprehensive support for 9 languages: English (en), Swedish (sv), Norwegian (no), Finnish (fi), Danish (da), German (de), French (fr), Spanish (es), and Dutch (nl).
- Template-Driven Accessibility Statements: Generates modern, glassmorphism-styled statements using externalized JSON templates for each language, allowing for professional legal phrasing and deep customization.
- Multi-Company Metadata: Easily customize statements via CLI flags or .a11yrc for scalable client generation.
- Enriched JUnit XML: Professional CI/CD reports including scan duration, page title, engine metadata, and detailed failing node snippets (Target + HTML).
- Configurable Severity Threshold: Fail CI only on critical/high issues (configurable).
- Pseudo-Automation: Automatically generates Playwright/Puppeteer test scripts for manual verification steps.
- PDF Reporting: Generates beautiful, compliant PDF reports with severity-sorted violations, HTML error counts, and @HolmDigital/engine branding.
- TypeScript: Written in TypeScript with full type definitions included.
``bash`
npm install @holmdigital/engine
`bash`
npx hd-a11y-scan
Options:
| Option | Description |
|--------|-------------|
| --lang | Language code (en, sv, de, fr, es, nl, no, fi, da, en-gb, en-us, en-ca) |--threshold
| | Severity threshold for compliance (critical, high, medium, low). Default: high |--ci
| | Run in CI mode (exit code 1 on failure) |--json
| | Output results as JSON |--pdf
| | Generate a PDF report |--statement
| | Generate a Premium V2 accessibility statement (HTML) |--org
| | Organization name for the statement metadata |--email
| | Contact email for the statement metadata |--phone
| | Contact phone for the statement metadata |--response-time
| | Response time for the statement metadata |--publish-date
| | Publish date for the website (YYYY-MM-DD) |--viewport
| | Set viewport size (mobile, tablet, desktop, or custom 1024x768) |--generate-tests
| | Generate Pseudo-Automation tests |--invalid-https-cert
| | Allow scanning sites with invalid/self-signed HTTPS certificates ⚠️ |--api-key
| | API Key for HolmDigital Cloud |--cloud-url
| | Custom Cloud API Endpoint (default: cloud.holmdigital.se) |
!Accessibility Status: 100% Compliant
The badge uses accessible colors (AAA compliant contrast) and is included in both the CLI output and the HTML report.
> ⚠️ Security Note: The --invalid-https-cert flag should only be used in trusted environments (local dev, staging). It disables certificate validation and is not recommended for production. (Contributed by @FerdiStro)
Example:
`bashFail only on critical issues in CI
npx hd-a11y-scan https://example.com --ci --threshold critical
JSON Output
`json
{
"url": "https://example.com",
"timestamp": "2026-01-13T17:05:11.749Z",
"metadata": {
"engineVersion": "1.4.12",
"axeCoreVersion": "4.10.2",
"standardsVersion": "1.2.3",
"scanDuration": 2891,
"pageTitle": "Example Domain",
"pageLanguage": "en"
},
"stats": {
"passed": 13,
"critical": 0,
"high": 0,
"medium": 2,
"low": 0,
"total": 2
},
"legalSummary": {
"wadApplicable": 2,
"eaaApplicable": 2,
"eaaDeadlineViolations": 2
},
"score": 90,
"complianceStatus": "PASS"
}
`EU Legal Framework
The engine maps violations to EU legal frameworks:
| Framework | Description | Deadline |
|-----------|-------------|----------|
| WAD | Web Accessibility Directive 2016/2102 (Public Sector) | Already in force |
| EAA | European Accessibility Act 2019/882 (Private Sector) | June 28, 2025 |
$3
| Field | Description |
|-------|-------------|
|
wadApplicable | Violations that affect WAD compliance (public sector) |
| eaaApplicable | Violations that affect EAA compliance (private sector) |
| eaaDeadlineViolations | Issues that must be fixed before EAA 2025 deadline |$3
The HTML/PDF report now includes:
- EU Legal Framework Impact summary section
- WAD/EAA badges on each violation card
- EAA deadline warnings for issues requiring immediate attention
Severity Threshold
The
--threshold flag controls when complianceStatus becomes FAIL:| Threshold | Fails on |
|-----------|----------|
|
critical | Only critical violations |
| high (default) | Critical + high violations |
| medium | Critical + high + medium violations |
| low | Any violation |Why this matters for CI/CD:
`bash
Strict: Block deployment on any serious issue
npx hd-a11y-scan https://staging.example.com --ci --threshold highLenient: Only block on critical issues (like missing alt text)
npx hd-a11y-scan https://staging.example.com --ci --threshold critical
`Medium violations (like missing
landmark) won't fail your CI by default, but are still reported for awareness.Metadata Fields
| Field | Description |
|-------|-------------|
|
engineVersion | Version of @holmdigital/engine |
| axeCoreVersion | Version of axe-core used |
| standardsVersion | Version of @holmdigital/standards database |
| scanDuration | Scan time in milliseconds |
| pageTitle | HTML of scanned page |
| pageLanguage | lang attribute of |
| stats.passed | Number of accessibility checks that passed |
Programmatic Usage
`typescript
import { RegulatoryScanner, setLanguage } from '@holmdigital/engine';const scanner = new RegulatoryScanner({
url: 'https://example.com',
severityThreshold: 'high' // critical, high, medium, low
});
setLanguage('sv');
const result = await scanner.scan();
console.log(
Score: ${result.score});
console.log(Duration: ${result.metadata.scanDuration}ms);
console.log(Passed: ${result.stats.passed}, Failed: ${result.stats.total});
``MIT © Holm Digital AB