@holmdigital/engine 1.4.9 → 1.4.12

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/README.md CHANGED
@@ -51,7 +51,14 @@ npx hd-a11y-scan <url> [options]
51
51
  | `--generate-tests` | Generate Pseudo-Automation tests |
52
52
  | `--invalid-https-cert` | Allow scanning sites with invalid/self-signed HTTPS certificates ⚠️ |
53
53
  | `--api-key <key>` | API Key for HolmDigital Cloud |
54
- | `--cloud-url <url>` | Custom URL for HolmDigital Cloud API |
54
+ | `--cloud-url <url>` | Custom Cloud API Endpoint (default: cloud.holmdigital.se) |
55
+
56
+ ### 🏆 Accessibility Badge
57
+ If your site achieves a **100% score**, the CLI will generate a [Shields.io](https://shields.io/) badge that you can add to your project's README:
58
+
59
+ ![Accessibility Status: 100% Compliant](https://img.shields.io/badge/HolmDigital_Engine-100%25-00703C?style=flat-square)
60
+
61
+ The badge uses accessible colors (AAA compliant contrast) and is included in both the CLI output and the HTML report.
55
62
 
56
63
  > **⚠️ 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](https://github.com/FerdiStro))*
57
64
 
@@ -71,9 +78,9 @@ npx hd-a11y-scan https://example.com --json
71
78
  "url": "https://example.com",
72
79
  "timestamp": "2026-01-13T17:05:11.749Z",
73
80
  "metadata": {
74
- "engineVersion": "1.4.6",
81
+ "engineVersion": "1.4.12",
75
82
  "axeCoreVersion": "4.10.2",
76
- "standardsVersion": "1.2.2",
83
+ "standardsVersion": "1.2.3",
77
84
  "scanDuration": 2891,
78
85
  "pageTitle": "Example Domain",
79
86
  "pageLanguage": "en"
@@ -1,7 +1,3 @@
1
- import {
2
- __require
3
- } from "./chunk-BKI2FFUX.mjs";
4
-
5
1
  // src/core/virtual-dom.ts
6
2
  var VirtualDOMBuilder = class {
7
3
  page;
@@ -93,6 +89,7 @@ var VirtualDOMBuilder = class {
93
89
  };
94
90
 
95
91
  // src/core/regulatory-scanner.ts
92
+ import axeCore from "axe-core";
96
93
  import puppeteer from "puppeteer";
97
94
 
98
95
  // src/core/html-validator.ts
@@ -250,13 +247,13 @@ var RegulatoryScanner = class {
250
247
  return page;
251
248
  }
252
249
  async injectAxe(page) {
253
- const axeSource = __require("axe-core").source;
250
+ const axeSource = axeCore.source;
254
251
  await page.evaluate(axeSource);
255
252
  }
256
253
  async enrichResults(axeResults) {
257
254
  const reports = [];
258
255
  const { searchRulesByTags, generateRegulatoryReport } = await import("@holmdigital/standards");
259
- const { getCurrentLang } = await import("./i18n-M6ATDHUS.mjs");
256
+ const { getCurrentLang } = await import("./i18n-WJLEZT5A.mjs");
260
257
  const lang = getCurrentLang();
261
258
  for (const violation of axeResults.violations) {
262
259
  let report = generateRegulatoryReport(violation.id, lang);
@@ -342,7 +339,6 @@ var RegulatoryScanner = class {
342
339
  complianceStatus = stats.total > 0 ? "FAIL" : "PASS";
343
340
  break;
344
341
  }
345
- const axeCore = __require("axe-core");
346
342
  const metadata = {
347
343
  engineVersion: "1.4.7",
348
344
  axeCoreVersion: axeCore.version || "4.10.2",
@@ -1,10 +1,3 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
1
  // src/locales/en.json
9
2
  var en_default = {
10
3
  cli: {
@@ -280,7 +273,6 @@ function getCurrentLang() {
280
273
  }
281
274
 
282
275
  export {
283
- __require,
284
276
  setLanguage,
285
277
  t,
286
278
  getCurrentLang
package/dist/cli/index.js CHANGED
@@ -358,6 +358,7 @@ var import_chalk = __toESM(require("chalk"));
358
358
  var import_ora = __toESM(require("ora"));
359
359
 
360
360
  // src/core/regulatory-scanner.ts
361
+ var import_axe_core = __toESM(require("axe-core"));
361
362
  var import_puppeteer = __toESM(require("puppeteer"));
362
363
 
363
364
  // src/core/virtual-dom.ts
@@ -605,7 +606,7 @@ var RegulatoryScanner = class {
605
606
  return page;
606
607
  }
607
608
  async injectAxe(page) {
608
- const axeSource = require("axe-core").source;
609
+ const axeSource = import_axe_core.default.source;
609
610
  await page.evaluate(axeSource);
610
611
  }
611
612
  async enrichResults(axeResults) {
@@ -697,10 +698,9 @@ var RegulatoryScanner = class {
697
698
  complianceStatus = stats.total > 0 ? "FAIL" : "PASS";
698
699
  break;
699
700
  }
700
- const axeCore = require("axe-core");
701
701
  const metadata = {
702
702
  engineVersion: "1.4.7",
703
- axeCoreVersion: axeCore.version || "4.10.2",
703
+ axeCoreVersion: import_axe_core.default.version || "4.10.2",
704
704
  standardsVersion: "1.2.2",
705
705
  scanDuration,
706
706
  pageTitle,
@@ -795,6 +795,23 @@ test('${testName}', async ({ page }) => {
795
795
  }
796
796
  };
797
797
 
798
+ // src/reporting/badge-generator.ts
799
+ var BADGE_COLOR = "00703C";
800
+ var BADGE_BASE_URL = "https://img.shields.io/badge/HolmDigital_Engine";
801
+ function generateBadgeUrl(score) {
802
+ if (score !== 100) {
803
+ return null;
804
+ }
805
+ return `${BADGE_BASE_URL}-100%25-${BADGE_COLOR}?style=flat-square`;
806
+ }
807
+ function generateBadgeMarkdown(score) {
808
+ const url = generateBadgeUrl(score);
809
+ if (!url) {
810
+ return null;
811
+ }
812
+ return `![Accessibility Status: 100% Compliant](${url})`;
813
+ }
814
+
798
815
  // src/reporting/html-template.ts
799
816
  init_i18n();
800
817
  function generateReportHTML(result) {
@@ -958,6 +975,7 @@ function generateReportHTML(result) {
958
975
  <div class="meta">
959
976
  <div>${t("report.scan_target", { url: result.url })}</div>
960
977
  <div>${t("report.generated", { date: formatDate(result.timestamp) })}</div>
978
+ ${generateBadgeUrl(result.score) ? `<div style="margin-top: 0.5rem;"><img src="${generateBadgeUrl(result.score)}" alt="Accessibility Status: 100% Compliant" /></div>` : ""}
961
979
  </div>
962
980
  </div>
963
981
 
@@ -1198,6 +1216,13 @@ program.argument("<url>", "URL to scan").option("--lang <code>", "Language code
1198
1216
  if (result.complianceStatus === "FAIL") {
1199
1217
  console.log(import_chalk.default.red(t("cli.not_compliant")));
1200
1218
  }
1219
+ if (result.score === 100) {
1220
+ const badge = generateBadgeMarkdown(result.score);
1221
+ if (badge) {
1222
+ console.log(import_chalk.default.green.bold("\n\u{1F3C6} Perfect Score! Here is your accessibility badge:"));
1223
+ console.log(import_chalk.default.white(badge));
1224
+ }
1225
+ }
1201
1226
  console.log(import_chalk.default.gray("----------------------------------------"));
1202
1227
  if (options.viewport) {
1203
1228
  console.log(import_chalk.default.blue(t("cli.viewport", { width: viewport.width, height: viewport.height })));
@@ -2,18 +2,35 @@
2
2
  import {
3
3
  PseudoAutomationEngine,
4
4
  RegulatoryScanner
5
- } from "../chunk-WZSPSYDS.mjs";
5
+ } from "../chunk-FFTRXRZU.mjs";
6
6
  import {
7
7
  getCurrentLang,
8
8
  setLanguage,
9
9
  t
10
- } from "../chunk-BKI2FFUX.mjs";
10
+ } from "../chunk-YWRTSIUX.mjs";
11
11
 
12
12
  // src/cli/index.ts
13
13
  import { Command } from "commander";
14
14
  import chalk from "chalk";
15
15
  import ora from "ora";
16
16
 
17
+ // src/reporting/badge-generator.ts
18
+ var BADGE_COLOR = "00703C";
19
+ var BADGE_BASE_URL = "https://img.shields.io/badge/HolmDigital_Engine";
20
+ function generateBadgeUrl(score) {
21
+ if (score !== 100) {
22
+ return null;
23
+ }
24
+ return `${BADGE_BASE_URL}-100%25-${BADGE_COLOR}?style=flat-square`;
25
+ }
26
+ function generateBadgeMarkdown(score) {
27
+ const url = generateBadgeUrl(score);
28
+ if (!url) {
29
+ return null;
30
+ }
31
+ return `![Accessibility Status: 100% Compliant](${url})`;
32
+ }
33
+
17
34
  // src/reporting/html-template.ts
18
35
  function generateReportHTML(result) {
19
36
  const criticalCount = result.stats.critical;
@@ -176,6 +193,7 @@ function generateReportHTML(result) {
176
193
  <div class="meta">
177
194
  <div>${t("report.scan_target", { url: result.url })}</div>
178
195
  <div>${t("report.generated", { date: formatDate(result.timestamp) })}</div>
196
+ ${generateBadgeUrl(result.score) ? `<div style="margin-top: 0.5rem;"><img src="${generateBadgeUrl(result.score)}" alt="Accessibility Status: 100% Compliant" /></div>` : ""}
179
197
  </div>
180
198
  </div>
181
199
 
@@ -413,6 +431,13 @@ program.argument("<url>", "URL to scan").option("--lang <code>", "Language code
413
431
  if (result.complianceStatus === "FAIL") {
414
432
  console.log(chalk.red(t("cli.not_compliant")));
415
433
  }
434
+ if (result.score === 100) {
435
+ const badge = generateBadgeMarkdown(result.score);
436
+ if (badge) {
437
+ console.log(chalk.green.bold("\n\u{1F3C6} Perfect Score! Here is your accessibility badge:"));
438
+ console.log(chalk.white(badge));
439
+ }
440
+ }
416
441
  console.log(chalk.gray("----------------------------------------"));
417
442
  if (options.viewport) {
418
443
  console.log(chalk.blue(t("cli.viewport", { width: viewport.width, height: viewport.height })));
@@ -2,7 +2,7 @@ import {
2
2
  getCurrentLang,
3
3
  setLanguage,
4
4
  t
5
- } from "./chunk-BKI2FFUX.mjs";
5
+ } from "./chunk-YWRTSIUX.mjs";
6
6
  export {
7
7
  getCurrentLang,
8
8
  setLanguage,
package/dist/index.js CHANGED
@@ -365,6 +365,7 @@ __export(index_exports, {
365
365
  module.exports = __toCommonJS(index_exports);
366
366
 
367
367
  // src/core/regulatory-scanner.ts
368
+ var import_axe_core = __toESM(require("axe-core"));
368
369
  var import_puppeteer = __toESM(require("puppeteer"));
369
370
 
370
371
  // src/core/virtual-dom.ts
@@ -612,7 +613,7 @@ var RegulatoryScanner = class {
612
613
  return page;
613
614
  }
614
615
  async injectAxe(page) {
615
- const axeSource = require("axe-core").source;
616
+ const axeSource = import_axe_core.default.source;
616
617
  await page.evaluate(axeSource);
617
618
  }
618
619
  async enrichResults(axeResults) {
@@ -704,10 +705,9 @@ var RegulatoryScanner = class {
704
705
  complianceStatus = stats.total > 0 ? "FAIL" : "PASS";
705
706
  break;
706
707
  }
707
- const axeCore = require("axe-core");
708
708
  const metadata = {
709
709
  engineVersion: "1.4.7",
710
- axeCoreVersion: axeCore.version || "4.10.2",
710
+ axeCoreVersion: import_axe_core.default.version || "4.10.2",
711
711
  standardsVersion: "1.2.2",
712
712
  scanDuration,
713
713
  pageTitle,
package/dist/index.mjs CHANGED
@@ -2,12 +2,12 @@ import {
2
2
  PseudoAutomationEngine,
3
3
  RegulatoryScanner,
4
4
  VirtualDOMBuilder
5
- } from "./chunk-WZSPSYDS.mjs";
5
+ } from "./chunk-FFTRXRZU.mjs";
6
6
  import {
7
7
  getCurrentLang,
8
8
  setLanguage,
9
9
  t
10
- } from "./chunk-BKI2FFUX.mjs";
10
+ } from "./chunk-YWRTSIUX.mjs";
11
11
  export {
12
12
  PseudoAutomationEngine,
13
13
  RegulatoryScanner,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holmdigital/engine",
3
- "version": "1.4.9",
3
+ "version": "1.4.12",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -34,8 +34,9 @@
34
34
  "build": "tsup src/index.ts src/cli/index.ts --format cjs,esm --dts --clean",
35
35
  "dev": "tsup src/index.ts src/cli/index.ts --format cjs,esm --dts --watch",
36
36
  "test": "vitest",
37
+ "test:ci": "vitest run",
37
38
  "test:integration": "vitest run --config vitest.integration.config.ts",
38
- "lint": "eslint src --ext .ts",
39
+ "lint": "eslint src",
39
40
  "prepublishOnly": "npm run build"
40
41
  },
41
42
  "keywords": [