@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 +11 -1
- package/dist/{chunk-GKQRHFIT.mjs → chunk-WZSPSYDS.mjs} +3 -1
- package/dist/cli/index.js +31 -3
- package/dist/cli/index.mjs +29 -3
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
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
|
|
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
|
+

|
|
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 ``;
|
|
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 })));
|
package/dist/cli/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
PseudoAutomationEngine,
|
|
4
4
|
RegulatoryScanner
|
|
5
|
-
} from "../chunk-
|
|
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 ``;
|
|
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
package/dist/index.d.ts
CHANGED
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