aria-ease 2.1.1 → 2.2.1

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/bin/audit-cli.cjs CHANGED
@@ -5,6 +5,9 @@ function _array_like_to_array(arr, len) {
5
5
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
6
6
  return arr2;
7
7
  }
8
+ function _array_with_holes(arr) {
9
+ if (Array.isArray(arr)) return arr;
10
+ }
8
11
  function _array_without_holes(arr) {
9
12
  if (Array.isArray(arr)) return _array_like_to_array(arr);
10
13
  }
@@ -37,6 +40,13 @@ function _async_to_generator(fn) {
37
40
  });
38
41
  };
39
42
  }
43
+ function _instanceof(left, right) {
44
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
45
+ return !!right[Symbol.hasInstance](left);
46
+ } else {
47
+ return left instanceof right;
48
+ }
49
+ }
40
50
  function _getRequireWildcardCache(nodeInterop) {
41
51
  if (typeof WeakMap !== "function") return null;
42
52
  var cacheBabelInterop = new WeakMap();
@@ -81,9 +91,39 @@ function _interop_require_wildcard(obj, nodeInterop) {
81
91
  function _iterable_to_array(iter) {
82
92
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
83
93
  }
94
+ function _iterable_to_array_limit(arr, i) {
95
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
96
+ if (_i == null) return;
97
+ var _arr = [];
98
+ var _n = true;
99
+ var _d = false;
100
+ var _s, _e;
101
+ try {
102
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
103
+ _arr.push(_s.value);
104
+ if (i && _arr.length === i) break;
105
+ }
106
+ } catch (err) {
107
+ _d = true;
108
+ _e = err;
109
+ } finally{
110
+ try {
111
+ if (!_n && _i["return"] != null) _i["return"]();
112
+ } finally{
113
+ if (_d) throw _e;
114
+ }
115
+ }
116
+ return _arr;
117
+ }
118
+ function _non_iterable_rest() {
119
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
120
+ }
84
121
  function _non_iterable_spread() {
85
122
  throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
86
123
  }
124
+ function _sliced_to_array(arr, i) {
125
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
126
+ }
87
127
  function _to_consumable_array(arr) {
88
128
  return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
89
129
  }
@@ -274,6 +314,13 @@ function _async_to_generator1(fn) {
274
314
  });
275
315
  };
276
316
  }
317
+ function _instanceof1(left, right) {
318
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
319
+ return !!right[Symbol.hasInstance](left);
320
+ } else {
321
+ return _instanceof(left, right);
322
+ }
323
+ }
277
324
  function _ts_generator1(thisArg, body) {
278
325
  var f, y, t, _ = {
279
326
  label: 0,
@@ -371,6 +418,12 @@ function runAudit(url) {
371
418
  return _ts_generator1(this, function(_state) {
372
419
  switch(_state.label){
373
420
  case 0:
421
+ _state.trys.push([
422
+ 0,
423
+ 6,
424
+ ,
425
+ 7
426
+ ]);
374
427
  return [
375
428
  4,
376
429
  import_playwright2.chromium.launch({
@@ -399,14 +452,6 @@ function runAudit(url) {
399
452
  ];
400
453
  case 4:
401
454
  _state.sent();
402
- _state.label = 5;
403
- case 5:
404
- _state.trys.push([
405
- 5,
406
- 7,
407
- ,
408
- 8
409
- ]);
410
455
  axe = new import_playwright.default({
411
456
  page: page
412
457
  });
@@ -414,26 +459,39 @@ function runAudit(url) {
414
459
  4,
415
460
  axe.analyze()
416
461
  ];
417
- case 6:
462
+ case 5:
418
463
  axeResults = _state.sent();
419
464
  return [
420
465
  2,
421
466
  axeResults
422
467
  ];
423
- case 7:
468
+ case 6:
424
469
  error = _state.sent();
425
- console.log(error);
470
+ if (_instanceof1(error, Error) && error.message.includes("Executable doesn't exist")) {
471
+ console.error("\n\u274C Playwright browsers not found!\n");
472
+ console.log("\uD83D\uDCE6 First-time setup required:");
473
+ console.log(" Run: npx playwright install chromium\n");
474
+ console.log("\uD83D\uDCA1 This downloads the browser needed for auditing (~200MB)");
475
+ console.log(" You only need to do this once.\n");
476
+ process.exit(1);
477
+ }
426
478
  return [
427
479
  3,
428
- 8
480
+ 7
481
+ ];
482
+ case 7:
483
+ if (!browser) return [
484
+ 3,
485
+ 9
429
486
  ];
430
- case 8:
431
487
  return [
432
488
  4,
433
489
  browser.close()
434
490
  ];
435
- case 9:
491
+ case 8:
436
492
  _state.sent();
493
+ _state.label = 9;
494
+ case 9:
437
495
  return [
438
496
  2
439
497
  ];
@@ -462,6 +520,8 @@ function formatResults(allResults, format) {
462
520
  }), null, 2);
463
521
  case "csv":
464
522
  return toCSV(allResults);
523
+ case "html":
524
+ return toHTML(allResults);
465
525
  default:
466
526
  return "";
467
527
  }
@@ -475,19 +535,116 @@ function toCSV(allResults) {
475
535
  if (result) {
476
536
  result.violations.forEach(function(v) {
477
537
  v.nodes.forEach(function(n) {
478
- rows.push('"'.concat(url, '","').concat(v.id, '","').concat(v.impact, '","').concat(v.description, '","').concat(n.target, '","').concat(n.failureSummary, '"'));
538
+ var _n_failureSummary;
539
+ rows.push(escapeCSV(url) + "," + escapeCSV(v.id) + "," + escapeCSV(v.impact) + "," + escapeCSV(v.description) + "," + escapeCSV(Array.isArray(n.target) ? n.target.join("; ") : String(n.target)) + "," + escapeCSV((_n_failureSummary = n.failureSummary) !== null && _n_failureSummary !== void 0 ? _n_failureSummary : ""));
479
540
  });
480
541
  });
481
542
  }
482
543
  });
483
544
  return rows.join("\n");
484
545
  }
546
+ function escapeCSV(value) {
547
+ var s = String(value !== null && value !== void 0 ? value : "");
548
+ return '"'.concat(s.replace(/"/g, '""'), '"');
549
+ }
550
+ function toHTML(allResults) {
551
+ var summary = {
552
+ pagesAudited: 0,
553
+ pagesWithViolations: 0,
554
+ totalViolations: 0,
555
+ distinctRules: /* @__PURE__ */ new Set(),
556
+ impactCounts: /* @__PURE__ */ new Map()
557
+ };
558
+ allResults.forEach(function(param) {
559
+ var result = param.result;
560
+ if (!result) return;
561
+ summary.pagesAudited++;
562
+ var pageViolations = result.violations.reduce(function(acc, v) {
563
+ var nodesCount = (v.nodes || []).length;
564
+ if (nodesCount > 0) {
565
+ summary.distinctRules.add(v.id);
566
+ summary.totalViolations += nodesCount;
567
+ acc += nodesCount;
568
+ var _v_impact;
569
+ var impact = String((_v_impact = v.impact) !== null && _v_impact !== void 0 ? _v_impact : "unknown");
570
+ summary.impactCounts.set(impact, (summary.impactCounts.get(impact) || 0) + nodesCount);
571
+ }
572
+ return acc;
573
+ }, 0);
574
+ if (pageViolations > 0) summary.pagesWithViolations++;
575
+ });
576
+ var rows = [];
577
+ allResults.forEach(function(param) {
578
+ var url = param.url, result = param.result;
579
+ if (!result) return;
580
+ result.violations.forEach(function(v) {
581
+ v.nodes.forEach(function(n) {
582
+ var target = Array.isArray(n.target) ? n.target.join("; ") : String(n.target);
583
+ var _v_impact, _v_impact1, _v_description, _n_failureSummary;
584
+ rows.push('\n <tr>\n <td class="nowrap">'.concat(escapeHTML(url), '</td>\n <td class="nowrap">').concat(escapeHTML(v.id), '</td>\n <td class="impact ').concat(escapeClass(String((_v_impact = v.impact) !== null && _v_impact !== void 0 ? _v_impact : "unknown")), '">').concat(escapeHTML(String((_v_impact1 = v.impact) !== null && _v_impact1 !== void 0 ? _v_impact1 : "")), '</td>\n <td class="desc">').concat(escapeHTML((_v_description = v.description) !== null && _v_description !== void 0 ? _v_description : ""), '</td>\n <td class="target"><code>').concat(escapeHTML(target), '</code></td>\n <td class="fail">').concat(escapeHTML((_n_failureSummary = n.failureSummary) !== null && _n_failureSummary !== void 0 ? _n_failureSummary : "").split(/\r?\n/).join("<br/>"), "</td>\n </tr>\n "));
585
+ });
586
+ });
587
+ });
588
+ var impactSummary = Array.from(summary.impactCounts.entries()).map(function(param) {
589
+ var _param = _sliced_to_array(param, 2), impact = _param[0], count = _param[1];
590
+ return '<li><strong class="impact '.concat(escapeClass(impact), '">').concat(escapeHTML(impact), "</strong>: ").concat(count, "</li>");
591
+ }).join("\n");
592
+ var d = /* @__PURE__ */ new Date();
593
+ var pad = function(n) {
594
+ return String(n).padStart(2, "0");
595
+ };
596
+ var reportDateTime = "".concat(pad(d.getDate()), "-").concat(pad(d.getMonth() + 1), "-").concat(d.getFullYear(), " ").concat(pad(d.getHours()), ":").concat(pad(d.getMinutes()), ":").concat(pad(d.getSeconds()));
597
+ var headerSummary = '\n <section class="summary">\n <h2>Report summary</h2>\n <ul>\n <li><strong>Date:</strong> '.concat(reportDateTime, "</li>\n <li><strong>Pages audited:</strong> ").concat(summary.pagesAudited, "</li>\n <li><strong>Pages with violations:</strong> ").concat(summary.pagesWithViolations, "</li>\n <li><strong>Total violations:</strong> ").concat(summary.totalViolations, "</li>\n <li><strong>Distinct rules:</strong> ").concat(summary.distinctRules.size, '</li>\n </ul>\n <div class="impact-summary">\n <h3>By impact</h3>\n <ul class="summary-list">\n ').concat(impactSummary || "<li>None</li>", "\n </ul>\n </div>\n </section>\n ").trim();
598
+ var html = '\n <!DOCTYPE html>\n <html lang="en">\n <head>\n <meta charset="utf-8"/>\n <title>Aria-Ease Accessibility Audit Report</title>\n <meta name="viewport" content="width=device-width, initial-scale=1"/>\n <style>\n :root{\n --bg:#ffffff; --muted:#6b7280; --border:#e6e9ee;\n --impact-critical: red; --impact-moderate:#fff4dd; --impact-serious:rgb(255, 123, 0);\n }\n body{font-family:Inter,ui-sans-serif,system-ui,Segoe UI,Roboto,Helvetica,Arial; background:var(--bg); color:#111827; padding:24px; line-height:1.4}\n h1{margin:0 0 8px}\n .summary{background:#f8fafc;border:1px solid var(--border);padding:12px 16px;border-radius:8px;margin-bottom:18px}\n .summary ul{margin:6px 0 0 0;padding:0 18px}\n .impact-summary h3{margin:12px 0 6px}\n table{width:100%; border-collapse:collapse; margin-top:12px}\n th,td{border:1px solid var(--border); padding:10px; text-align:left; vertical-align:top}\n th{background:#f3f4f6; font-weight:600; position:sticky; top:0; z-index:1}\n .nowrap{white-space:nowrap}\n .target code{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, "Roboto Mono", "Courier New", monospace; white-space:pre-wrap}\n .desc{max-width:380px}\n tr:nth-child(even){background:#fbfbfb}\n td.fail{color:#7b1e1e}\n .impact.critical{background:var(--impact-critical); font-weight:600}\n .impact.moderate{background:var(--impact-moderate); font-weight:600}\n .impact.serious{background:var(--impact-serious); font-weight:600}\n @media (max-width:900px){\n .desc{max-width:200px}\n table, thead, tbody, th, td, tr{display:block}\n thead{display:none}\n tr{margin-bottom:10px; border: 1px solid var(--border);}\n td{border:1px solid var(--border); padding:6px}\n td::before{font-weight:600; display:inline-block; width:120px}\n }\n .summary-list strong,\n .summary-list li {\n padding: 2px 4px;\n }\n </style>\n </head>\n <body>\n <h1>Aria-Ease Accessibility Audit Report</h1>\n '.concat(headerSummary, "\n <table>\n <thead>\n <tr>\n <th>URL</th><th>Rule</th><th>Impact</th><th>Description</th><th>Target</th><th>FailureSummary</th>\n </tr>\n </thead>\n <tbody>\n ").concat(rows.join("\n") || '<tr><td colspan="6"><em>No violations found.</em></td></tr>', "\n </tbody>\n </table>\n </body>\n </html>\n ").trim();
599
+ return html;
600
+ }
601
+ function escapeHTML(str) {
602
+ return String(str !== null && str !== void 0 ? str : "").replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
603
+ }
604
+ function escapeClass(s) {
605
+ return String(s !== null && s !== void 0 ? s : "").toLowerCase().replace(/[^a-z0-9]+/g, "-");
606
+ }
485
607
  // bin/audit-cli.ts
486
608
  var program = new import_commander.Command();
487
- program.name("aria-ease").description("Run accessibility audits").version("2.0.4");
488
- program.command("audit").description("Run accessibility audit").option("-u, --url <url>", "Single URL to audit").option("-f, --format <format>", "Output format for the audit report: json | csv", "csv").option("-o, --out <path>", "Directory to save the audit report", "./accessibility-reports").action(function(opts) {
609
+ program.name("aria-ease").description("Run accessibility tests and audits").version("2.1.1");
610
+ program.command("audit").description("Run axe-core powered accessibility audit on webpages").option("-u, --url <url>", "Single URL to audit").option("-f, --format <format>", "Output format for the audit report: json | csv | html", "all").option("-o, --out <path>", "Directory to save the audit report", "./accessibility-reports/audit").action(function(opts) {
489
611
  return _async_to_generator(function() {
490
- var _urls, configPath, config, _tmp, urls, format, allResults, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, url, result, err1, err, hasResults, formatted, out, timestamp, fileName, filePath;
612
+ var _urls, _opts_audit, _config_audit, _config_audit1, _opts_audit1, configPath, config, _tmp, urls, format, allResults, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, url, result, err1, err, hasResults;
613
+ function createReport(format2) {
614
+ return _async_to_generator(function() {
615
+ var _config_audit, formatted, out, d, pad, timestamp, fileName, filePath;
616
+ return _ts_generator(this, function(_state) {
617
+ switch(_state.label){
618
+ case 0:
619
+ formatted = formatResults(allResults, format2);
620
+ out = ((_config_audit = config.audit) === null || _config_audit === void 0 ? void 0 : _config_audit.output) && config.audit.output.out || opts.audit.out;
621
+ return [
622
+ 4,
623
+ import_fs_extra.default.ensureDir(out)
624
+ ];
625
+ case 1:
626
+ _state.sent();
627
+ d = /* @__PURE__ */ new Date();
628
+ pad = function(n) {
629
+ return String(n).padStart(2, "0");
630
+ };
631
+ timestamp = "".concat(pad(d.getDate()), "-").concat(pad(d.getMonth() + 1), "-").concat(d.getFullYear(), " ").concat(pad(d.getHours()), ":").concat(pad(d.getMinutes()), ":").concat(pad(d.getSeconds()));
632
+ fileName = "ariaease-report-".concat(timestamp, ".").concat(format2);
633
+ filePath = import_path.default.join(out, fileName);
634
+ return [
635
+ 4,
636
+ import_fs_extra.default.writeFile(filePath, formatted, "utf-8")
637
+ ];
638
+ case 2:
639
+ _state.sent();
640
+ console.log(import_chalk.default.magentaBright("\uD83D\uDCC1 Report saved to ".concat(filePath)));
641
+ return [
642
+ 2
643
+ ];
644
+ }
645
+ });
646
+ })();
647
+ }
491
648
  return _ts_generator(this, function(_state) {
492
649
  switch(_state.label){
493
650
  case 0:
@@ -532,18 +689,20 @@ program.command("audit").description("Run accessibility audit").option("-u, --ur
532
689
  6
533
690
  ];
534
691
  case 5:
535
- console.log(import_chalk.default.yellow("\u2139\uFE0F No ariaease.config.js found at project root, using default configurations."));
692
+ console.log(import_chalk.default.yellow("\u2139\uFE0F No ariaease.config.js found at project root, using CLI configurations."));
536
693
  _state.label = 6;
537
694
  case 6:
538
695
  urls = [];
539
- if (opts.url) urls.push(opts.url);
540
- if (config.urls && Array.isArray(config.urls)) (_urls = urls).push.apply(_urls, _to_consumable_array(config.urls));
541
- format = config.output && config.output.format || opts.format;
696
+ if ((_opts_audit = opts.audit) === null || _opts_audit === void 0 ? void 0 : _opts_audit.url) urls.push(opts.audit.url);
697
+ if (((_config_audit = config.audit) === null || _config_audit === void 0 ? void 0 : _config_audit.urls) && Array.isArray(config.audit.urls)) (_urls = urls).push.apply(_urls, _to_consumable_array(config.audit.urls));
698
+ format = ((_config_audit1 = config.audit) === null || _config_audit1 === void 0 ? void 0 : _config_audit1.output) && config.audit.output.format || ((_opts_audit1 = opts.audit) === null || _opts_audit1 === void 0 ? void 0 : _opts_audit1.format);
542
699
  if (![
543
700
  "json",
544
- "csv"
701
+ "csv",
702
+ "html",
703
+ "all"
545
704
  ].includes(format)) {
546
- console.log(import_chalk.default.red('\u274C Invalid format. Use "json" or "csv".'));
705
+ console.log(import_chalk.default.red('\u274C Invalid format. Use "json", "csv", "html" or "all".'));
547
706
  process.exit(1);
548
707
  }
549
708
  if (urls.length === 0) {
@@ -639,24 +798,21 @@ program.command("audit").description("Run accessibility audit").option("-u, --ur
639
798
  console.log(import_chalk.default.red("\u274C No audit report generated"));
640
799
  process.exit(1);
641
800
  }
642
- formatted = formatResults(allResults, format);
643
- out = config.output && config.output.out || opts.out;
644
- return [
645
- 4,
646
- import_fs_extra.default.ensureDir(out)
647
- ];
648
- case 17:
649
- _state.sent();
650
- timestamp = /* @__PURE__ */ new Date().toISOString().replace(/[:.]/g, "-");
651
- fileName = "ariaease-report-".concat(timestamp, ".").concat(format);
652
- filePath = import_path.default.join(out, fileName);
653
- return [
654
- 4,
655
- import_fs_extra.default.writeFile(filePath, formatted, "utf-8")
656
- ];
657
- case 18:
658
- _state.sent();
659
- console.log(import_chalk.default.magentaBright("\uD83D\uDCC1 Report saved to ".concat(filePath)));
801
+ if ([
802
+ "json",
803
+ "csv",
804
+ "html"
805
+ ].includes(format)) {
806
+ createReport(format);
807
+ } else if (format === "all") {
808
+ [
809
+ "json",
810
+ "csv",
811
+ "html"
812
+ ].map(function(format2) {
813
+ createReport(format2);
814
+ });
815
+ }
660
816
  console.log(import_chalk.default.green("\n\uD83C\uDF89 All audits completed."));
661
817
  return [
662
818
  2
@@ -665,6 +821,9 @@ program.command("audit").description("Run accessibility audit").option("-u, --ur
665
821
  });
666
822
  })();
667
823
  });
824
+ program.command("test").description("Run core a11y accessibility standard tests on UI components").option("-f, --format <format>", "Output format for the test report: json | csv | html", "html").option("-o, --out <path>", "Directory to save the test report", "./accessibility-reports/test").action(function() {
825
+ console.log("Coming soon");
826
+ });
668
827
  program.command("help").description("Display help information").action(function() {
669
828
  program.outputHelp();
670
829
  });