@diegovelasquezweb/a11y-engine 0.3.1 → 0.4.0

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.
Files changed (44) hide show
  1. package/package.json +12 -9
  2. package/scripts/sync-assets.mjs +67 -0
  3. package/{scripts → src/cli}/audit.mjs +10 -10
  4. package/{scripts → src}/core/asset-loader.mjs +12 -12
  5. package/{scripts → src}/index.mjs +4 -4
  6. /package/assets/{discovery → generated/discovery}/crawler-config.mjs +0 -0
  7. /package/assets/{discovery → generated/discovery}/stack-detection.mjs +0 -0
  8. /package/assets/{engine → generated/engine}/cdp-checks.mjs +0 -0
  9. /package/assets/{engine → generated/engine}/pa11y-config.mjs +0 -0
  10. /package/assets/{remediation → generated/remediation}/axe-check-maps.mjs +0 -0
  11. /package/assets/{remediation → generated/remediation}/code-patterns.mjs +0 -0
  12. /package/assets/{remediation → generated/remediation}/guardrails.mjs +0 -0
  13. /package/assets/{remediation → generated/remediation}/intelligence.mjs +0 -0
  14. /package/assets/{remediation → generated/remediation}/source-boundaries.mjs +0 -0
  15. /package/assets/{reporting → generated/reporting}/compliance-config.mjs +0 -0
  16. /package/assets/{reporting → generated/reporting}/manual-checks.mjs +0 -0
  17. /package/assets/{reporting → generated/reporting}/wcag-reference.mjs +0 -0
  18. /package/assets/{discovery → source/discovery}/crawler-config.json +0 -0
  19. /package/assets/{discovery → source/discovery}/stack-detection.json +0 -0
  20. /package/assets/{engine → source/engine}/cdp-checks.json +0 -0
  21. /package/assets/{engine → source/engine}/pa11y-config.json +0 -0
  22. /package/assets/{remediation → source/remediation}/axe-check-maps.json +0 -0
  23. /package/assets/{remediation → source/remediation}/code-patterns.json +0 -0
  24. /package/assets/{remediation → source/remediation}/guardrails.json +0 -0
  25. /package/assets/{remediation → source/remediation}/intelligence.json +0 -0
  26. /package/assets/{remediation → source/remediation}/source-boundaries.json +0 -0
  27. /package/assets/{reporting → source/reporting}/compliance-config.json +0 -0
  28. /package/assets/{reporting → source/reporting}/manual-checks.json +0 -0
  29. /package/assets/{reporting → source/reporting}/wcag-reference.json +0 -0
  30. /package/{scripts → src}/core/toolchain.mjs +0 -0
  31. /package/{scripts → src}/core/utils.mjs +0 -0
  32. /package/{scripts/engine → src/enrichment}/analyzer.mjs +0 -0
  33. /package/{scripts → src}/index.d.mts +0 -0
  34. /package/{scripts/engine → src/pipeline}/dom-scanner.mjs +0 -0
  35. /package/{scripts/reports/builders → src/reports}/checklist.mjs +0 -0
  36. /package/{scripts/reports/builders → src/reports}/html.mjs +0 -0
  37. /package/{scripts/reports/builders → src/reports}/md.mjs +0 -0
  38. /package/{scripts/reports/builders → src/reports}/pdf.mjs +0 -0
  39. /package/{scripts → src}/reports/renderers/findings.mjs +0 -0
  40. /package/{scripts → src}/reports/renderers/html.mjs +0 -0
  41. /package/{scripts → src}/reports/renderers/md.mjs +0 -0
  42. /package/{scripts → src}/reports/renderers/pdf.mjs +0 -0
  43. /package/{scripts → src}/reports/renderers/utils.mjs +0 -0
  44. /package/{scripts/engine → src/source-patterns}/source-scanner.mjs +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegovelasquezweb/a11y-engine",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "WCAG 2.2 AA accessibility audit engine — scanner, analyzer, and report builders",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -14,27 +14,30 @@
14
14
  },
15
15
  "exports": {
16
16
  ".": {
17
- "types": "./scripts/index.d.mts",
18
- "default": "./scripts/index.mjs"
17
+ "types": "./src/index.d.mts",
18
+ "default": "./src/index.mjs"
19
19
  },
20
20
  "./package.json": "./package.json"
21
21
  },
22
- "main": "scripts/index.mjs",
23
- "types": "scripts/index.d.mts",
22
+ "main": "src/index.mjs",
23
+ "types": "src/index.d.mts",
24
24
  "bin": {
25
- "a11y-audit": "scripts/audit.mjs"
25
+ "a11y-audit": "src/cli/audit.mjs"
26
26
  },
27
27
  "files": [
28
- "scripts/**",
29
- "assets/**",
28
+ "src/**",
29
+ "assets/source/**",
30
+ "assets/generated/**",
30
31
  "docs/**",
32
+ "scripts/sync-assets.mjs",
31
33
  "README.md",
32
34
  "CHANGELOG.md",
33
35
  "LICENSE"
34
36
  ],
35
37
  "scripts": {
38
+ "sync-assets": "node scripts/sync-assets.mjs",
36
39
  "test": "vitest run",
37
- "prepublishOnly": "node -e \"console.log('Publishing @diegovelasquezweb/a11y-engine...')\""
40
+ "prepublishOnly": "node scripts/sync-assets.mjs"
38
41
  },
39
42
  "dependencies": {
40
43
  "@axe-core/playwright": "^4.11.1",
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * sync-assets.mjs
4
+ * Generates assets/generated/**\/*.mjs from assets/source/**\/*.json.
5
+ * Run: node scripts/sync-assets.mjs
6
+ * Hooked automatically in prepublishOnly.
7
+ */
8
+
9
+ import fs from "node:fs";
10
+ import path from "node:path";
11
+ import { fileURLToPath } from "node:url";
12
+
13
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
+ const ROOT = path.resolve(__dirname, "..");
15
+ const SOURCE_DIR = path.join(ROOT, "assets", "source");
16
+ const GENERATED_DIR = path.join(ROOT, "assets", "generated");
17
+
18
+ let synced = 0;
19
+ let skipped = 0;
20
+
21
+ function syncDir(sourceDir, generatedDir) {
22
+ fs.mkdirSync(generatedDir, { recursive: true });
23
+
24
+ for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
25
+ const sourcePath = path.join(sourceDir, entry.name);
26
+ const generatedPath = path.join(generatedDir, entry.name);
27
+
28
+ if (entry.isDirectory()) {
29
+ syncDir(sourcePath, path.join(generatedDir, entry.name));
30
+ continue;
31
+ }
32
+
33
+ if (!entry.name.endsWith(".json")) {
34
+ skipped++;
35
+ continue;
36
+ }
37
+
38
+ const mjsName = entry.name.replace(/\.json$/, ".mjs");
39
+ const mjsPath = path.join(generatedDir, mjsName);
40
+
41
+ let data;
42
+ try {
43
+ data = JSON.parse(fs.readFileSync(sourcePath, "utf-8"));
44
+ } catch (err) {
45
+ console.error(` [ERROR] Failed to parse ${sourcePath}: ${err.message}`);
46
+ process.exit(1);
47
+ }
48
+
49
+ const content = `export default ${JSON.stringify(data)};\n`;
50
+
51
+ // Only write if content changed (avoid unnecessary fs writes)
52
+ let existing = null;
53
+ try { existing = fs.readFileSync(mjsPath, "utf-8"); } catch { /* new file */ }
54
+
55
+ if (existing !== content) {
56
+ fs.writeFileSync(mjsPath, content, "utf-8");
57
+ console.log(` synced: ${path.relative(ROOT, mjsPath)}`);
58
+ synced++;
59
+ } else {
60
+ skipped++;
61
+ }
62
+ }
63
+ }
64
+
65
+ console.log("Syncing assets/source/*.json → assets/generated/*.mjs");
66
+ syncDir(SOURCE_DIR, GENERATED_DIR);
67
+ console.log(`Done. ${synced} file(s) written, ${skipped} unchanged/skipped.`);
@@ -10,7 +10,7 @@ import { spawn, execSync } from "node:child_process";
10
10
  import path from "node:path";
11
11
  import { fileURLToPath } from "node:url";
12
12
  import fs from "node:fs";
13
- import { log, DEFAULTS, SKILL_ROOT, getInternalPath } from "./core/utils.mjs";
13
+ import { log, DEFAULTS, SKILL_ROOT, getInternalPath } from "../core/utils.mjs";
14
14
 
15
15
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
16
16
 
@@ -205,7 +205,7 @@ async function main() {
205
205
  log.success("Dependencies ready.");
206
206
  }
207
207
 
208
- await runScript("core/toolchain.mjs");
208
+ await runScript("../core/toolchain.mjs");
209
209
 
210
210
  const screenshotsDir = getInternalPath("screenshots");
211
211
  fs.rmSync(screenshotsDir, { recursive: true, force: true });
@@ -258,12 +258,12 @@ async function main() {
258
258
  }
259
259
  if (axeTags) scanArgs.push("--axe-tags", axeTags);
260
260
 
261
- await runScript("engine/dom-scanner.mjs", scanArgs, childEnv);
261
+ await runScript("../pipeline/dom-scanner.mjs", scanArgs, childEnv);
262
262
 
263
263
  const analyzerArgs = [];
264
264
  if (ignoreFindings) analyzerArgs.push("--ignore-findings", ignoreFindings);
265
265
  if (framework) analyzerArgs.push("--framework", framework);
266
- await runScript("engine/analyzer.mjs", analyzerArgs);
266
+ await runScript("../enrichment/analyzer.mjs", analyzerArgs);
267
267
 
268
268
  if (projectDir && !skipPatterns) {
269
269
  const patternArgs = ["--project-dir", path.resolve(projectDir)];
@@ -275,7 +275,7 @@ async function main() {
275
275
  } catch { /* ignore */ }
276
276
  }
277
277
  if (resolvedFramework) patternArgs.push("--framework", resolvedFramework);
278
- await runScript("engine/source-scanner.mjs", patternArgs);
278
+ await runScript("../source-patterns/source-scanner.mjs", patternArgs);
279
279
  }
280
280
 
281
281
  const mdOutput = getInternalPath("remediation.md");
@@ -283,7 +283,7 @@ async function main() {
283
283
  if (target) mdArgs.push("--target", target);
284
284
 
285
285
  if (skipReports) {
286
- await runScript("reports/builders/md.mjs", mdArgs);
286
+ await runScript("../reports/md.mjs", mdArgs);
287
287
  } else {
288
288
  const output = getArgValue("output");
289
289
  if (!output) {
@@ -307,10 +307,10 @@ async function main() {
307
307
  const checklistArgs = ["--output", checklistOutput, "--base-url", baseUrl];
308
308
 
309
309
  await Promise.all([
310
- runScript("reports/builders/html.mjs", buildArgs),
311
- runScript("reports/builders/checklist.mjs", checklistArgs),
312
- runScript("reports/builders/md.mjs", mdArgs),
313
- runScript("reports/builders/pdf.mjs", pdfArgs),
310
+ runScript("../reports/html.mjs", buildArgs),
311
+ runScript("../reports/checklist.mjs", checklistArgs),
312
+ runScript("../reports/md.mjs", mdArgs),
313
+ runScript("../reports/pdf.mjs", pdfArgs),
314
314
  ]);
315
315
 
316
316
  console.log(`REPORT_PATH=${absoluteOutputPath}`);
@@ -5,18 +5,18 @@
5
5
  * This ensures bundlers (Turbopack, Webpack) can trace them automatically.
6
6
  */
7
7
 
8
- import crawlerConfig from "../../assets/discovery/crawler-config.mjs";
9
- import stackDetection from "../../assets/discovery/stack-detection.mjs";
10
- import cdpChecks from "../../assets/engine/cdp-checks.mjs";
11
- import pa11yConfig from "../../assets/engine/pa11y-config.mjs";
12
- import axeCheckMaps from "../../assets/remediation/axe-check-maps.mjs";
13
- import codePatterns from "../../assets/remediation/code-patterns.mjs";
14
- import guardrails from "../../assets/remediation/guardrails.mjs";
15
- import intelligence from "../../assets/remediation/intelligence.mjs";
16
- import sourceBoundaries from "../../assets/remediation/source-boundaries.mjs";
17
- import complianceConfig from "../../assets/reporting/compliance-config.mjs";
18
- import manualChecks from "../../assets/reporting/manual-checks.mjs";
19
- import wcagReference from "../../assets/reporting/wcag-reference.mjs";
8
+ import crawlerConfig from "../../assets/generated/discovery/crawler-config.mjs";
9
+ import stackDetection from "../../assets/generated/discovery/stack-detection.mjs";
10
+ import cdpChecks from "../../assets/generated/engine/cdp-checks.mjs";
11
+ import pa11yConfig from "../../assets/generated/engine/pa11y-config.mjs";
12
+ import axeCheckMaps from "../../assets/generated/remediation/axe-check-maps.mjs";
13
+ import codePatterns from "../../assets/generated/remediation/code-patterns.mjs";
14
+ import guardrails from "../../assets/generated/remediation/guardrails.mjs";
15
+ import intelligence from "../../assets/generated/remediation/intelligence.mjs";
16
+ import sourceBoundaries from "../../assets/generated/remediation/source-boundaries.mjs";
17
+ import complianceConfig from "../../assets/generated/reporting/compliance-config.mjs";
18
+ import manualChecks from "../../assets/generated/reporting/manual-checks.mjs";
19
+ import wcagReference from "../../assets/generated/reporting/wcag-reference.mjs";
20
20
 
21
21
  /**
22
22
  * Pre-loaded asset map. Each value is the parsed JSON object, ready to use.
@@ -457,8 +457,8 @@ export function getAuditSummary(findings, payload = null) {
457
457
  export async function runAudit(options) {
458
458
  if (!options.baseUrl) throw new Error("runAudit requires baseUrl");
459
459
 
460
- const { runDomScanner } = await import("./engine/dom-scanner.mjs");
461
- const { runAnalyzer } = await import("./engine/analyzer.mjs");
460
+ const { runDomScanner } = await import("./pipeline/dom-scanner.mjs");
461
+ const { runAnalyzer } = await import("./enrichment/analyzer.mjs");
462
462
 
463
463
  const onProgress = options.onProgress || null;
464
464
 
@@ -497,7 +497,7 @@ export async function runAudit(options) {
497
497
  // Step 3: Source patterns (optional)
498
498
  if (options.projectDir && !options.skipPatterns) {
499
499
  try {
500
- const { resolveScanDirs, scanPattern } = await import("./engine/source-scanner.mjs");
500
+ const { resolveScanDirs, scanPattern } = await import("./source-patterns/source-scanner.mjs");
501
501
  const { patterns } = loadAssetJson(ASSET_PATHS.remediation.codePatterns, "code-patterns.json");
502
502
 
503
503
  let resolvedFramework = options.framework;
@@ -893,7 +893,7 @@ export async function getRemediationGuide(payload, options = {}) {
893
893
  * @returns {Promise<{ findings: object[], summary: { total: number, confirmed: number, potential: number } }>}
894
894
  */
895
895
  export async function getSourcePatterns(projectDir, options = {}) {
896
- const { scanPattern, resolveScanDirs } = await import("./engine/source-scanner.mjs");
896
+ const { scanPattern, resolveScanDirs } = await import("./source-patterns/source-scanner.mjs");
897
897
 
898
898
  const { patterns } = loadAssetJson(ASSET_PATHS.remediation.codePatterns, "code-patterns.json");
899
899
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes