Package Exports
- @holmdigital/engine
- @holmdigital/engine/cli
Readme
@holmdigital/engine
Regulatory accessibility test engine with Virtual DOM, Shadow DOM support, and built-in legal compliance reporting.
Why this package?
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:
- Mapping technical failures to specific legal clauses.
- Validating HTML structure to ensure test accuracy.
- Reporting in multiple languages (EN, SV, NO, FI, DA, NL, DE, FR, ES) for non-technical stakeholders.
- 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.
Features
- Regulatory Mapping: Maps technical failures to EU laws (EN 301 549, EAA).
- HTML Structure Validation: Built-in
html-validatechecks 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
.a11yrcfor 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/enginebranding. - Type-Safe Results: Scan results return fully typed
EnrichedReport[]withfailingNodesandlegalContext— zeroas anycasts in the pipeline. - Build-Time Version Injection: Engine version derived from
package.jsonat build time via tsupdefine— CLI, cloud client, and reports always report the correct version. - TypeScript: Written in TypeScript with full type definitions included.
Installation
npm install @holmdigital/engineCLI Usage
npx hd-a11y-scan <url> [options]Options:
| Option | Description |
|---|---|
--lang <code> |
Language code (en, sv, de, fr, es, nl, no, fi, da, en-gb, en-us, en-ca) |
--threshold <level> |
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 <path> |
Generate a PDF report |
--statement <path> |
Generate a Premium V2 accessibility statement (HTML) |
--org <name> |
Organization name for the statement metadata |
--email <email> |
Contact email for the statement metadata |
--phone <number> |
Contact phone for the statement metadata |
--response-time <val> |
Response time for the statement metadata |
--publish-date <date> |
Publish date for the website (YYYY-MM-DD) |
--viewport <size> |
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 <key> |
API Key for HolmDigital Cloud |
--cloud-url <url> |
Custom Cloud API Endpoint (default: cloud.holmdigital.se) |
🏆 Accessibility Badge
If your site achieves a 100% score, the CLI will generate a Shields.io badge that you can add to your project's README:
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-certflag should only be used in trusted environments (local dev, staging). It disables certificate validation and is not recommended for production. (Contributed by @FerdiStro)
Example:
# Fail only on critical issues in CI
npx hd-a11y-scan https://example.com --ci --threshold critical
# Full JSON output with metadata
npx hd-a11y-scan https://example.com --jsonJSON Output
{
"url": "https://example.com",
"timestamp": "2026-01-13T17:05:11.749Z",
"metadata": {
"engineVersion": "2.1.5",
"axeCoreVersion": "4.11.1",
"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 |
legalSummary Fields
| 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 |
HTML Report Enhancements
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:
# Strict: Block deployment on any serious issue
npx hd-a11y-scan https://staging.example.com --ci --threshold high
# Lenient: Only block on critical issues (like missing alt text)
npx hd-a11y-scan https://staging.example.com --ci --threshold criticalMedium violations (like missing <main> 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 <title> of scanned page |
pageLanguage |
lang attribute of <html> |
stats.passed |
Number of accessibility checks that passed |
Programmatic Usage
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}`);License
MIT © Holm Digital AB