@holmdigital/engine 1.4.8 → 1.4.11

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
@@ -49,8 +49,18 @@ npx hd-a11y-scan <url> [options]
49
49
  | `--pdf <path>` | Generate a PDF report |
50
50
  | `--viewport <size>` | Set viewport size (`mobile`, `tablet`, `desktop`, or custom `1024x768`) |
51
51
  | `--generate-tests` | Generate Pseudo-Automation tests |
52
+ | `--invalid-https-cert` | Allow scanning sites with invalid/self-signed HTTPS certificates ⚠️ |
52
53
  | `--api-key <key>` | API Key for HolmDigital Cloud |
53
- | `--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.
62
+
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))*
54
64
 
55
65
  **Example:**
56
66
  ```bash
@@ -144,6 +144,7 @@ var RegulatoryScanner = class {
144
144
  standard: "dos-lagen",
145
145
  // Default till striktaste
146
146
  silent: false,
147
+ invalidHttpsCert: false,
147
148
  ...options
148
149
  };
149
150
  this.htmlValidator = new HtmlValidator();
@@ -236,8 +237,9 @@ var RegulatoryScanner = class {
236
237
  args: [
237
238
  "--no-sandbox",
238
239
  "--disable-setuid-sandbox",
239
- "--disable-blink-features=AutomationControlled"
240
+ "--disable-blink-features=AutomationControlled",
240
241
  // Gömmer att det är en robot
242
+ ...this.options.invalidHttpsCert ? ["--ignore-certificate-errors", "--allow-insecure-localhost"] : []
241
243
  ]
242
244
  });
243
245
  }
package/dist/cli/index.js CHANGED
@@ -499,6 +499,7 @@ var RegulatoryScanner = class {
499
499
  standard: "dos-lagen",
500
500
  // Default till striktaste
501
501
  silent: false,
502
+ invalidHttpsCert: false,
502
503
  ...options
503
504
  };
504
505
  this.htmlValidator = new HtmlValidator();
@@ -591,8 +592,9 @@ var RegulatoryScanner = class {
591
592
  args: [
592
593
  "--no-sandbox",
593
594
  "--disable-setuid-sandbox",
594
- "--disable-blink-features=AutomationControlled"
595
+ "--disable-blink-features=AutomationControlled",
595
596
  // Gömmer att det är en robot
597
+ ...this.options.invalidHttpsCert ? ["--ignore-certificate-errors", "--allow-insecure-localhost"] : []
596
598
  ]
597
599
  });
598
600
  }
@@ -793,6 +795,23 @@ test('${testName}', async ({ page }) => {
793
795
  }
794
796
  };
795
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
+
796
815
  // src/reporting/html-template.ts
797
816
  init_i18n();
798
817
  function generateReportHTML(result) {
@@ -956,6 +975,7 @@ function generateReportHTML(result) {
956
975
  <div class="meta">
957
976
  <div>${t("report.scan_target", { url: result.url })}</div>
958
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>` : ""}
959
979
  </div>
960
980
  </div>
961
981
 
@@ -1145,7 +1165,7 @@ function isValidUrl(urlString) {
1145
1165
  }
1146
1166
  var program = new import_commander.Command();
1147
1167
  program.name("hd-a11y-scan").description("HolmDigital Regulatory Scanner").version("0.1.0");
1148
- program.argument("<url>", "URL to scan").option("--lang <code>", "Language code (en, sv)", "en").option("--ci", "Run in CI/CD mode (exit code 1 on critical failures)").option("--generate-tests", "Generate Pseudo-Automation tests").option("--json", "Output as JSON").option("--pdf <path>", "Generate PDF report to path").option("--viewport <size>", 'Set viewport (e.g. "mobile", "desktop", "1024x768")').option("--threshold <level>", "Severity threshold for compliance (critical, high, medium, low)", "high").option("--api-key <key>", "API key for HolmDigital Cloud authentication").option("--cloud-url <url>", "Cloud API URL", "https://cloud.holmdigital.se").action(async (url, options) => {
1168
+ program.argument("<url>", "URL to scan").option("--lang <code>", "Language code (en, sv)", "en").option("--ci", "Run in CI/CD mode (exit code 1 on critical failures)").option("--generate-tests", "Generate Pseudo-Automation tests").option("--json", "Output as JSON").option("--pdf <path>", "Generate PDF report to path").option("--viewport <size>", 'Set viewport (e.g. "mobile", "desktop", "1024x768")').option("--threshold <level>", "Severity threshold for compliance (critical, high, medium, low)", "high").option("--api-key <key>", "API key for HolmDigital Cloud authentication").option("--cloud-url <url>", "Cloud API URL", "https://cloud.holmdigital.se").option("--invalid-https-cert", "Allow scanning on pages with invalid https certificate").action(async (url, options) => {
1149
1169
  setLanguage(options.lang);
1150
1170
  if (!isValidUrl(url)) {
1151
1171
  console.error(import_chalk.default.red(`Error: Invalid URL format '${url}'`));
@@ -1175,7 +1195,8 @@ program.argument("<url>", "URL to scan").option("--lang <code>", "Language code
1175
1195
  viewport,
1176
1196
  silent: options.json,
1177
1197
  // Suppress debug output for JSON mode
1178
- severityThreshold: options.threshold
1198
+ severityThreshold: options.threshold,
1199
+ invalidHttpsCert: options.invalidHttpsCert
1179
1200
  });
1180
1201
  if (spinner) spinner.text = t("cli.analyzing");
1181
1202
  const result = await scanner.scan();
@@ -1195,6 +1216,13 @@ program.argument("<url>", "URL to scan").option("--lang <code>", "Language code
1195
1216
  if (result.complianceStatus === "FAIL") {
1196
1217
  console.log(import_chalk.default.red(t("cli.not_compliant")));
1197
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
+ }
1198
1226
  console.log(import_chalk.default.gray("----------------------------------------"));
1199
1227
  if (options.viewport) {
1200
1228
  console.log(import_chalk.default.blue(t("cli.viewport", { width: viewport.width, height: viewport.height })));
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  PseudoAutomationEngine,
4
4
  RegulatoryScanner
5
- } from "../chunk-GKQRHFIT.mjs";
5
+ } from "../chunk-WZSPSYDS.mjs";
6
6
  import {
7
7
  getCurrentLang,
8
8
  setLanguage,
@@ -14,6 +14,23 @@ 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
 
@@ -362,7 +380,7 @@ function isValidUrl(urlString) {
362
380
  }
363
381
  var program = new Command();
364
382
  program.name("hd-a11y-scan").description("HolmDigital Regulatory Scanner").version("0.1.0");
365
- program.argument("<url>", "URL to scan").option("--lang <code>", "Language code (en, sv)", "en").option("--ci", "Run in CI/CD mode (exit code 1 on critical failures)").option("--generate-tests", "Generate Pseudo-Automation tests").option("--json", "Output as JSON").option("--pdf <path>", "Generate PDF report to path").option("--viewport <size>", 'Set viewport (e.g. "mobile", "desktop", "1024x768")').option("--threshold <level>", "Severity threshold for compliance (critical, high, medium, low)", "high").option("--api-key <key>", "API key for HolmDigital Cloud authentication").option("--cloud-url <url>", "Cloud API URL", "https://cloud.holmdigital.se").action(async (url, options) => {
383
+ program.argument("<url>", "URL to scan").option("--lang <code>", "Language code (en, sv)", "en").option("--ci", "Run in CI/CD mode (exit code 1 on critical failures)").option("--generate-tests", "Generate Pseudo-Automation tests").option("--json", "Output as JSON").option("--pdf <path>", "Generate PDF report to path").option("--viewport <size>", 'Set viewport (e.g. "mobile", "desktop", "1024x768")').option("--threshold <level>", "Severity threshold for compliance (critical, high, medium, low)", "high").option("--api-key <key>", "API key for HolmDigital Cloud authentication").option("--cloud-url <url>", "Cloud API URL", "https://cloud.holmdigital.se").option("--invalid-https-cert", "Allow scanning on pages with invalid https certificate").action(async (url, options) => {
366
384
  setLanguage(options.lang);
367
385
  if (!isValidUrl(url)) {
368
386
  console.error(chalk.red(`Error: Invalid URL format '${url}'`));
@@ -392,7 +410,8 @@ program.argument("<url>", "URL to scan").option("--lang <code>", "Language code
392
410
  viewport,
393
411
  silent: options.json,
394
412
  // Suppress debug output for JSON mode
395
- severityThreshold: options.threshold
413
+ severityThreshold: options.threshold,
414
+ invalidHttpsCert: options.invalidHttpsCert
396
415
  });
397
416
  if (spinner) spinner.text = t("cli.analyzing");
398
417
  const result = await scanner.scan();
@@ -412,6 +431,13 @@ program.argument("<url>", "URL to scan").option("--lang <code>", "Language code
412
431
  if (result.complianceStatus === "FAIL") {
413
432
  console.log(chalk.red(t("cli.not_compliant")));
414
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
+ }
415
441
  console.log(chalk.gray("----------------------------------------"));
416
442
  if (options.viewport) {
417
443
  console.log(chalk.blue(t("cli.viewport", { width: viewport.width, height: viewport.height })));
package/dist/index.d.mts CHANGED
@@ -23,6 +23,7 @@ interface ScannerOptions {
23
23
  };
24
24
  silent?: boolean;
25
25
  severityThreshold?: 'critical' | 'high' | 'medium' | 'low';
26
+ invalidHttpsCert?: boolean;
26
27
  }
27
28
  interface ScanMetadata {
28
29
  engineVersion: string;
package/dist/index.d.ts CHANGED
@@ -23,6 +23,7 @@ interface ScannerOptions {
23
23
  };
24
24
  silent?: boolean;
25
25
  severityThreshold?: 'critical' | 'high' | 'medium' | 'low';
26
+ invalidHttpsCert?: boolean;
26
27
  }
27
28
  interface ScanMetadata {
28
29
  engineVersion: string;
package/dist/index.js CHANGED
@@ -506,6 +506,7 @@ var RegulatoryScanner = class {
506
506
  standard: "dos-lagen",
507
507
  // Default till striktaste
508
508
  silent: false,
509
+ invalidHttpsCert: false,
509
510
  ...options
510
511
  };
511
512
  this.htmlValidator = new HtmlValidator();
@@ -598,8 +599,9 @@ var RegulatoryScanner = class {
598
599
  args: [
599
600
  "--no-sandbox",
600
601
  "--disable-setuid-sandbox",
601
- "--disable-blink-features=AutomationControlled"
602
+ "--disable-blink-features=AutomationControlled",
602
603
  // Gömmer att det är en robot
604
+ ...this.options.invalidHttpsCert ? ["--ignore-certificate-errors", "--allow-insecure-localhost"] : []
603
605
  ]
604
606
  });
605
607
  }
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  PseudoAutomationEngine,
3
3
  RegulatoryScanner,
4
4
  VirtualDOMBuilder
5
- } from "./chunk-GKQRHFIT.mjs";
5
+ } from "./chunk-WZSPSYDS.mjs";
6
6
  import {
7
7
  getCurrentLang,
8
8
  setLanguage,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holmdigital/engine",
3
- "version": "1.4.8",
3
+ "version": "1.4.11",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -76,4 +76,4 @@
76
76
  "typescript": "^5.7.2",
77
77
  "vitest": "^4.0.16"
78
78
  }
79
- }
79
+ }