equall-cli 0.1.4 → 0.1.5
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 +12 -3
- package/dist/{chunk-CMP4ST3J.js → chunk-OQXPOPP6.js} +15 -14
- package/dist/cli.js +137 -4
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,12 +23,18 @@ equall scan .
|
|
|
23
23
|
33 files scanned · 15 WCAG violations · 19 best-practice issues
|
|
24
24
|
2 critical 11 serious 19 moderate 0 minor
|
|
25
25
|
2 issues ignored via equall-ignore
|
|
26
|
-
Score 56/100 · 18/
|
|
27
|
-
29/
|
|
26
|
+
Score 56/100 · 18/32 Level A criteria checked (56%) · 5 failed
|
|
27
|
+
29/56 Level AA criteria checked (52%) · 6 failed
|
|
28
28
|
|
|
29
29
|
ⓘ You're failing 5 Level A criteria (1.3.1, 2.1.1, 2.4.2, 2.4.4, 4.1.2).
|
|
30
30
|
Level A is the legal minimum — fix these first.
|
|
31
31
|
|
|
32
|
+
Best Practices
|
|
33
|
+
● region — 26 issues Landmarks help screen reader users navigate page sections
|
|
34
|
+
src/app/layout.tsx
|
|
35
|
+
src/components/Navigation.tsx
|
|
36
|
+
... and 24 more (use --verbose to see all)
|
|
37
|
+
|
|
32
38
|
Scanners: axe-core@4.11.1 (23 issues), eslint-jsx-a11y@6.10.2 (13 issues)
|
|
33
39
|
Completed in 0.8s
|
|
34
40
|
```
|
|
@@ -75,11 +81,14 @@ equall scan . --json # pipe to other tools
|
|
|
75
81
|
equall scan . --json > report.json
|
|
76
82
|
```
|
|
77
83
|
|
|
78
|
-
###
|
|
84
|
+
### Options
|
|
79
85
|
|
|
80
86
|
```bash
|
|
81
87
|
equall scan . --include "src/**/*.tsx"
|
|
82
88
|
equall scan . --exclude "**/*.stories.*"
|
|
89
|
+
equall scan . --verbose # show all files per best-practice rule
|
|
90
|
+
equall scan . --show-ignored # show ignored issues
|
|
91
|
+
equall scan . --show-manual # list untested criteria needing manual review
|
|
83
92
|
equall scan . --no-color # disable colored output
|
|
84
93
|
```
|
|
85
94
|
|
|
@@ -68717,7 +68717,7 @@ var MAX_PENALTY_PER_CRITERION = 15;
|
|
|
68717
68717
|
function computeScanResult(issues, filesScanned, scannersUsed, durationMs, targetLevel = "AA", criteriaCovered = [], criteriaTotal = 0) {
|
|
68718
68718
|
const summary = computeSummary(issues, filesScanned);
|
|
68719
68719
|
const score = computeScore(issues, filesScanned);
|
|
68720
|
-
const pourScores = computePourScores(issues, filesScanned);
|
|
68720
|
+
const pourScores = computePourScores(issues, filesScanned, criteriaCovered);
|
|
68721
68721
|
const conformanceLevel = computeConformanceLevel(issues, summary, targetLevel);
|
|
68722
68722
|
return {
|
|
68723
68723
|
score,
|
|
@@ -68782,32 +68782,33 @@ function computeScore(issues, filesScanned) {
|
|
|
68782
68782
|
const score = 100 * Math.exp(-k * scaledPenalty);
|
|
68783
68783
|
return Math.max(0, Math.round(score));
|
|
68784
68784
|
}
|
|
68785
|
-
function computePourScores(issues, filesScanned) {
|
|
68785
|
+
function computePourScores(issues, filesScanned, criteriaCovered = []) {
|
|
68786
68786
|
const pourIssues = {
|
|
68787
68787
|
perceivable: [],
|
|
68788
68788
|
operable: [],
|
|
68789
68789
|
understandable: [],
|
|
68790
68790
|
robust: []
|
|
68791
68791
|
};
|
|
68792
|
-
const
|
|
68793
|
-
|
|
68794
|
-
|
|
68795
|
-
|
|
68796
|
-
|
|
68792
|
+
const POUR_BY_PREFIX = { "1": "perceivable", "2": "operable", "3": "understandable", "4": "robust" };
|
|
68793
|
+
const pourCovered = {
|
|
68794
|
+
perceivable: false,
|
|
68795
|
+
operable: false,
|
|
68796
|
+
understandable: false,
|
|
68797
|
+
robust: false
|
|
68797
68798
|
};
|
|
68799
|
+
for (const c of criteriaCovered) {
|
|
68800
|
+
const principle = POUR_BY_PREFIX[c[0]];
|
|
68801
|
+
if (principle) pourCovered[principle] = true;
|
|
68802
|
+
}
|
|
68798
68803
|
for (const issue of issues) {
|
|
68799
68804
|
if (!issue.pour) continue;
|
|
68800
68805
|
pourIssues[issue.pour].push(issue);
|
|
68801
|
-
for (const c of issue.wcag_criteria) {
|
|
68802
|
-
pourCriteria[issue.pour].add(c);
|
|
68803
|
-
}
|
|
68804
68806
|
}
|
|
68805
68807
|
const scaleFactor = 1 / (1 + Math.log10(Math.max(1, filesScanned)));
|
|
68806
68808
|
const k = 0.02;
|
|
68807
68809
|
function pourScore(principle) {
|
|
68808
68810
|
const principleIssues = pourIssues[principle];
|
|
68809
|
-
|
|
68810
|
-
if (criteriaCount === 0 && principleIssues.length === 0) return null;
|
|
68811
|
+
if (!pourCovered[principle] && principleIssues.length === 0) return null;
|
|
68811
68812
|
if (principleIssues.length === 0) return 100;
|
|
68812
68813
|
const penaltyByCriterion = /* @__PURE__ */ new Map();
|
|
68813
68814
|
for (const issue of principleIssues) {
|
|
@@ -88388,8 +88389,8 @@ async function runScan(options = {}) {
|
|
|
88388
88389
|
const deduped = deduplicateIssues(allIssues);
|
|
88389
88390
|
const { active, ignored } = applyIgnoreComments(deduped, files);
|
|
88390
88391
|
const criteriaCovered = [...new Set(scanners.flatMap((s) => s.coveredCriteria))].sort();
|
|
88391
|
-
const WCAG_TOTAL = { A:
|
|
88392
|
-
const criteriaTotal = WCAG_TOTAL[scanOptions.wcag_level] ??
|
|
88392
|
+
const WCAG_TOTAL = { A: 32, AA: 56, AAA: 86 };
|
|
88393
|
+
const criteriaTotal = WCAG_TOTAL[scanOptions.wcag_level] ?? 56;
|
|
88393
88394
|
const durationMs = Date.now() - startTime;
|
|
88394
88395
|
const result = computeScanResult(active, files.length, scannersUsed, durationMs, scanOptions.wcag_level, criteriaCovered, criteriaTotal);
|
|
88395
88396
|
result.issues = [...active, ...ignored];
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
__toESM,
|
|
8
8
|
globby,
|
|
9
9
|
runScan
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-OQXPOPP6.js";
|
|
11
11
|
|
|
12
12
|
// node_modules/commander/lib/error.js
|
|
13
13
|
var require_error = __commonJS({
|
|
@@ -6412,6 +6412,107 @@ function ora(options) {
|
|
|
6412
6412
|
return new Ora(options);
|
|
6413
6413
|
}
|
|
6414
6414
|
|
|
6415
|
+
// src/wcag-catalog.ts
|
|
6416
|
+
var WCAG_CATALOG = [
|
|
6417
|
+
// Principle 1 — Perceivable
|
|
6418
|
+
{ id: "1.1.1", name: "Non-text Content", level: "A", pour: "perceivable" },
|
|
6419
|
+
{ id: "1.2.1", name: "Audio-only and Video-only (Prerecorded)", level: "A", pour: "perceivable" },
|
|
6420
|
+
{ id: "1.2.2", name: "Captions (Prerecorded)", level: "A", pour: "perceivable" },
|
|
6421
|
+
{ id: "1.2.3", name: "Audio Description or Media Alternative", level: "A", pour: "perceivable" },
|
|
6422
|
+
{ id: "1.2.4", name: "Captions (Live)", level: "AA", pour: "perceivable" },
|
|
6423
|
+
{ id: "1.2.5", name: "Audio Description (Prerecorded)", level: "AA", pour: "perceivable" },
|
|
6424
|
+
{ id: "1.2.6", name: "Sign Language (Prerecorded)", level: "AAA", pour: "perceivable" },
|
|
6425
|
+
{ id: "1.2.7", name: "Extended Audio Description (Prerecorded)", level: "AAA", pour: "perceivable" },
|
|
6426
|
+
{ id: "1.2.8", name: "Media Alternative (Prerecorded)", level: "AAA", pour: "perceivable" },
|
|
6427
|
+
{ id: "1.2.9", name: "Audio-only (Live)", level: "AAA", pour: "perceivable" },
|
|
6428
|
+
{ id: "1.3.1", name: "Info and Relationships", level: "A", pour: "perceivable" },
|
|
6429
|
+
{ id: "1.3.2", name: "Meaningful Sequence", level: "A", pour: "perceivable" },
|
|
6430
|
+
{ id: "1.3.3", name: "Sensory Characteristics", level: "A", pour: "perceivable" },
|
|
6431
|
+
{ id: "1.3.4", name: "Orientation", level: "AA", pour: "perceivable" },
|
|
6432
|
+
{ id: "1.3.5", name: "Identify Input Purpose", level: "AA", pour: "perceivable" },
|
|
6433
|
+
{ id: "1.3.6", name: "Identify Purpose", level: "AAA", pour: "perceivable" },
|
|
6434
|
+
{ id: "1.4.1", name: "Use of Color", level: "A", pour: "perceivable" },
|
|
6435
|
+
{ id: "1.4.2", name: "Audio Control", level: "A", pour: "perceivable" },
|
|
6436
|
+
{ id: "1.4.3", name: "Contrast (Minimum)", level: "AA", pour: "perceivable" },
|
|
6437
|
+
{ id: "1.4.4", name: "Resize Text", level: "AA", pour: "perceivable" },
|
|
6438
|
+
{ id: "1.4.5", name: "Images of Text", level: "AA", pour: "perceivable" },
|
|
6439
|
+
{ id: "1.4.6", name: "Contrast (Enhanced)", level: "AAA", pour: "perceivable" },
|
|
6440
|
+
{ id: "1.4.7", name: "Low or No Background Audio", level: "AAA", pour: "perceivable" },
|
|
6441
|
+
{ id: "1.4.8", name: "Visual Presentation", level: "AAA", pour: "perceivable" },
|
|
6442
|
+
{ id: "1.4.9", name: "Images of Text (No Exception)", level: "AAA", pour: "perceivable" },
|
|
6443
|
+
{ id: "1.4.10", name: "Reflow", level: "AA", pour: "perceivable" },
|
|
6444
|
+
{ id: "1.4.11", name: "Non-text Contrast", level: "AA", pour: "perceivable" },
|
|
6445
|
+
{ id: "1.4.12", name: "Text Spacing", level: "AA", pour: "perceivable" },
|
|
6446
|
+
{ id: "1.4.13", name: "Content on Hover or Focus", level: "AA", pour: "perceivable" },
|
|
6447
|
+
// Principle 2 — Operable
|
|
6448
|
+
{ id: "2.1.1", name: "Keyboard", level: "A", pour: "operable" },
|
|
6449
|
+
{ id: "2.1.2", name: "No Keyboard Trap", level: "A", pour: "operable" },
|
|
6450
|
+
{ id: "2.1.3", name: "Keyboard (No Exception)", level: "AAA", pour: "operable" },
|
|
6451
|
+
{ id: "2.1.4", name: "Character Key Shortcuts", level: "A", pour: "operable" },
|
|
6452
|
+
{ id: "2.2.1", name: "Timing Adjustable", level: "A", pour: "operable" },
|
|
6453
|
+
{ id: "2.2.2", name: "Pause, Stop, Hide", level: "A", pour: "operable" },
|
|
6454
|
+
{ id: "2.2.3", name: "No Timing", level: "AAA", pour: "operable" },
|
|
6455
|
+
{ id: "2.2.4", name: "Interruptions", level: "AAA", pour: "operable" },
|
|
6456
|
+
{ id: "2.2.5", name: "Re-authenticating", level: "AAA", pour: "operable" },
|
|
6457
|
+
{ id: "2.2.6", name: "Timeouts", level: "AAA", pour: "operable" },
|
|
6458
|
+
{ id: "2.3.1", name: "Three Flashes or Below Threshold", level: "A", pour: "operable" },
|
|
6459
|
+
{ id: "2.3.2", name: "Three Flashes", level: "AAA", pour: "operable" },
|
|
6460
|
+
{ id: "2.3.3", name: "Animation from Interactions", level: "AAA", pour: "operable" },
|
|
6461
|
+
{ id: "2.4.1", name: "Bypass Blocks", level: "A", pour: "operable" },
|
|
6462
|
+
{ id: "2.4.2", name: "Page Titled", level: "A", pour: "operable" },
|
|
6463
|
+
{ id: "2.4.3", name: "Focus Order", level: "A", pour: "operable" },
|
|
6464
|
+
{ id: "2.4.4", name: "Link Purpose (In Context)", level: "A", pour: "operable" },
|
|
6465
|
+
{ id: "2.4.5", name: "Multiple Ways", level: "AA", pour: "operable" },
|
|
6466
|
+
{ id: "2.4.6", name: "Headings and Labels", level: "AA", pour: "operable" },
|
|
6467
|
+
{ id: "2.4.7", name: "Focus Visible", level: "AA", pour: "operable" },
|
|
6468
|
+
{ id: "2.4.8", name: "Location", level: "AAA", pour: "operable" },
|
|
6469
|
+
{ id: "2.4.9", name: "Link Purpose (Link Only)", level: "AAA", pour: "operable" },
|
|
6470
|
+
{ id: "2.4.10", name: "Section Headings", level: "AAA", pour: "operable" },
|
|
6471
|
+
{ id: "2.4.11", name: "Focus Not Obscured (Minimum)", level: "AA", pour: "operable" },
|
|
6472
|
+
{ id: "2.4.12", name: "Focus Not Obscured (Enhanced)", level: "AAA", pour: "operable" },
|
|
6473
|
+
{ id: "2.4.13", name: "Focus Appearance", level: "AAA", pour: "operable" },
|
|
6474
|
+
{ id: "2.5.1", name: "Pointer Gestures", level: "A", pour: "operable" },
|
|
6475
|
+
{ id: "2.5.2", name: "Pointer Cancellation", level: "A", pour: "operable" },
|
|
6476
|
+
{ id: "2.5.3", name: "Label in Name", level: "A", pour: "operable" },
|
|
6477
|
+
{ id: "2.5.4", name: "Motion Actuation", level: "A", pour: "operable" },
|
|
6478
|
+
{ id: "2.5.5", name: "Target Size (Enhanced)", level: "AAA", pour: "operable" },
|
|
6479
|
+
{ id: "2.5.6", name: "Concurrent Input Mechanisms", level: "A", pour: "operable" },
|
|
6480
|
+
{ id: "2.5.7", name: "Dragging Movements", level: "AA", pour: "operable" },
|
|
6481
|
+
{ id: "2.5.8", name: "Target Size (Minimum)", level: "AA", pour: "operable" },
|
|
6482
|
+
// Principle 3 — Understandable
|
|
6483
|
+
{ id: "3.1.1", name: "Language of Page", level: "A", pour: "understandable" },
|
|
6484
|
+
{ id: "3.1.2", name: "Language of Parts", level: "AA", pour: "understandable" },
|
|
6485
|
+
{ id: "3.1.3", name: "Unusual Words", level: "AAA", pour: "understandable" },
|
|
6486
|
+
{ id: "3.1.4", name: "Abbreviations", level: "AAA", pour: "understandable" },
|
|
6487
|
+
{ id: "3.1.5", name: "Reading Level", level: "AAA", pour: "understandable" },
|
|
6488
|
+
{ id: "3.1.6", name: "Pronunciation", level: "AAA", pour: "understandable" },
|
|
6489
|
+
{ id: "3.2.1", name: "On Focus", level: "A", pour: "understandable" },
|
|
6490
|
+
{ id: "3.2.2", name: "On Input", level: "A", pour: "understandable" },
|
|
6491
|
+
{ id: "3.2.3", name: "Consistent Navigation", level: "AA", pour: "understandable" },
|
|
6492
|
+
{ id: "3.2.4", name: "Consistent Identification", level: "AA", pour: "understandable" },
|
|
6493
|
+
{ id: "3.2.5", name: "Change on Request", level: "AAA", pour: "understandable" },
|
|
6494
|
+
{ id: "3.2.6", name: "Consistent Help", level: "A", pour: "understandable" },
|
|
6495
|
+
{ id: "3.3.1", name: "Error Identification", level: "A", pour: "understandable" },
|
|
6496
|
+
{ id: "3.3.2", name: "Labels or Instructions", level: "A", pour: "understandable" },
|
|
6497
|
+
{ id: "3.3.3", name: "Error Suggestion", level: "AA", pour: "understandable" },
|
|
6498
|
+
{ id: "3.3.4", name: "Error Prevention (Legal, Financial, Data)", level: "AA", pour: "understandable" },
|
|
6499
|
+
{ id: "3.3.5", name: "Help", level: "AAA", pour: "understandable" },
|
|
6500
|
+
{ id: "3.3.6", name: "Error Prevention (All)", level: "AAA", pour: "understandable" },
|
|
6501
|
+
{ id: "3.3.7", name: "Redundant Entry", level: "A", pour: "understandable" },
|
|
6502
|
+
{ id: "3.3.8", name: "Accessible Authentication (Minimum)", level: "AA", pour: "understandable" },
|
|
6503
|
+
{ id: "3.3.9", name: "Accessible Authentication (Enhanced)", level: "AAA", pour: "understandable" },
|
|
6504
|
+
// Principle 4 — Robust
|
|
6505
|
+
{ id: "4.1.2", name: "Name, Role, Value", level: "A", pour: "robust" },
|
|
6506
|
+
{ id: "4.1.3", name: "Status Messages", level: "AA", pour: "robust" }
|
|
6507
|
+
];
|
|
6508
|
+
var LEVEL_RANK = { A: 1, AA: 2, AAA: 3 };
|
|
6509
|
+
var catalogMap = /* @__PURE__ */ new Map();
|
|
6510
|
+
for (const c of WCAG_CATALOG) catalogMap.set(c.id, c);
|
|
6511
|
+
function getCriteriaForLevel(level) {
|
|
6512
|
+
const maxRank = LEVEL_RANK[level];
|
|
6513
|
+
return WCAG_CATALOG.filter((c) => LEVEL_RANK[c.level] <= maxRank);
|
|
6514
|
+
}
|
|
6515
|
+
|
|
6415
6516
|
// src/output/terminal.ts
|
|
6416
6517
|
var WCAG_A_CRITERIA = /* @__PURE__ */ new Set([
|
|
6417
6518
|
"1.1.1",
|
|
@@ -6437,15 +6538,17 @@ var WCAG_A_CRITERIA = /* @__PURE__ */ new Set([
|
|
|
6437
6538
|
"2.5.2",
|
|
6438
6539
|
"2.5.3",
|
|
6439
6540
|
"2.5.4",
|
|
6541
|
+
"2.5.6",
|
|
6440
6542
|
"3.1.1",
|
|
6441
6543
|
"3.2.1",
|
|
6442
6544
|
"3.2.2",
|
|
6443
6545
|
"3.2.6",
|
|
6444
6546
|
"3.3.1",
|
|
6547
|
+
"3.3.2",
|
|
6445
6548
|
"3.3.7",
|
|
6446
6549
|
"4.1.2"
|
|
6447
6550
|
]);
|
|
6448
|
-
var WCAG_A_TOTAL =
|
|
6551
|
+
var WCAG_A_TOTAL = 32;
|
|
6449
6552
|
var BP_HINTS = {
|
|
6450
6553
|
"region": "Landmarks help screen reader users navigate page sections",
|
|
6451
6554
|
"landmark-main-is-top-level": "Nested landmarks confuse assistive technology",
|
|
@@ -6601,6 +6704,22 @@ function printResult(result, options = {}) {
|
|
|
6601
6704
|
const hint = BP_HINTS[criterion];
|
|
6602
6705
|
const hintSuffix = hint ? ` ${DIM}${hint}${RESET}` : "";
|
|
6603
6706
|
console.log(` ${severityIcon(topSeverity)} ${BOLD}${criterion}${RESET} ${DIM}\u2014 ${group.issues.length} issue${group.issues.length > 1 ? "s" : ""}${RESET}${hintSuffix}`);
|
|
6707
|
+
const maxFiles = options.verbose ? group.issues.length : 2;
|
|
6708
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6709
|
+
const uniqueIssues = [];
|
|
6710
|
+
for (const issue of group.issues) {
|
|
6711
|
+
if (!seen.has(issue.file_path)) {
|
|
6712
|
+
seen.add(issue.file_path);
|
|
6713
|
+
uniqueIssues.push(issue);
|
|
6714
|
+
}
|
|
6715
|
+
}
|
|
6716
|
+
for (const issue of uniqueIssues.slice(0, maxFiles)) {
|
|
6717
|
+
const location = issue.line ? `:${issue.line}` : "";
|
|
6718
|
+
console.log(` ${DIM}${issue.file_path}${location}${RESET}`);
|
|
6719
|
+
}
|
|
6720
|
+
if (!options.verbose && uniqueIssues.length > 2) {
|
|
6721
|
+
console.log(` ${DIM}... and ${uniqueIssues.length - 2} more (use --verbose to see all)${RESET}`);
|
|
6722
|
+
}
|
|
6604
6723
|
}
|
|
6605
6724
|
console.log();
|
|
6606
6725
|
}
|
|
@@ -6615,6 +6734,20 @@ function printResult(result, options = {}) {
|
|
|
6615
6734
|
console.log();
|
|
6616
6735
|
}
|
|
6617
6736
|
}
|
|
6737
|
+
if (options.showManual) {
|
|
6738
|
+
const level = options.targetLevel ?? "AA";
|
|
6739
|
+
const allForLevel = getCriteriaForLevel(level);
|
|
6740
|
+
const coveredSet = new Set(result.criteria_covered);
|
|
6741
|
+
const untested = allForLevel.filter((c) => !coveredSet.has(c.id));
|
|
6742
|
+
if (untested.length > 0) {
|
|
6743
|
+
console.log(` ${BOLD}Manual review needed${RESET} ${DIM}(${untested.length} criteria)${RESET}`);
|
|
6744
|
+
for (const c of untested) {
|
|
6745
|
+
const principle = c.pour.charAt(0).toUpperCase() + c.pour.slice(1);
|
|
6746
|
+
console.log(` ${DIM}${c.id}${RESET} ${c.name} ${DIM}\u2014 ${principle}${RESET}`);
|
|
6747
|
+
}
|
|
6748
|
+
console.log();
|
|
6749
|
+
}
|
|
6750
|
+
}
|
|
6618
6751
|
console.log(` ${DIM}Scanners: ${scanners_used.map((s) => `${s.name}@${s.version} (${s.issues_found} issues)`).join(", ")}${RESET}`);
|
|
6619
6752
|
console.log(` ${DIM}Completed in ${(duration_ms / 1e3).toFixed(1)}s${RESET}`);
|
|
6620
6753
|
console.log();
|
|
@@ -6837,7 +6970,7 @@ var __dir = resolve2(fileURLToPath(import.meta.url), "..");
|
|
|
6837
6970
|
var pkg = JSON.parse(readFileSync(resolve2(__dir, "..", "package.json"), "utf-8"));
|
|
6838
6971
|
var program2 = new Command();
|
|
6839
6972
|
program2.name("equall").description("Open-source accessibility scoring \u2014 aggregates axe-core, eslint-plugin-jsx-a11y, and more.").version(pkg.version);
|
|
6840
|
-
program2.command("scan").description("Scan a project for accessibility issues").argument("[path]", "Path to project root", ".").option("-l, --level <level>", "WCAG conformance target: A, AA, or AAA", "AA").option("--include <patterns...>", "Glob patterns to include").option("--exclude <patterns...>", "Glob patterns to exclude").option("--json", "Output results as JSON").option("-i, --show-ignored", "Show ignored issues in output").option("--no-color", "Disable colored output").action(async (path, opts) => {
|
|
6973
|
+
program2.command("scan").description("Scan a project for accessibility issues").argument("[path]", "Path to project root", ".").option("-l, --level <level>", "WCAG conformance target: A, AA, or AAA", "AA").option("--include <patterns...>", "Glob patterns to include").option("--exclude <patterns...>", "Glob patterns to exclude").option("--json", "Output results as JSON").option("-i, --show-ignored", "Show ignored issues in output").option("-v, --verbose", "Show all occurrences for best-practice issues").option("-m, --show-manual", "List WCAG criteria that require manual review").option("--no-color", "Disable colored output").action(async (path, opts) => {
|
|
6841
6974
|
const level = opts.level.toUpperCase();
|
|
6842
6975
|
if (!["A", "AA", "AAA"].includes(level)) {
|
|
6843
6976
|
console.error(`Invalid level "${opts.level}". Use A, AA, or AAA.`);
|
|
@@ -6865,7 +6998,7 @@ program2.command("scan").description("Scan a project for accessibility issues").
|
|
|
6865
6998
|
if (opts.json) {
|
|
6866
6999
|
printJson(result);
|
|
6867
7000
|
} else {
|
|
6868
|
-
printResult(result, { showIgnored: opts.showIgnored });
|
|
7001
|
+
printResult(result, { showIgnored: opts.showIgnored, verbose: opts.verbose, showManual: opts.showManual, targetLevel: level });
|
|
6869
7002
|
}
|
|
6870
7003
|
if (result.score < 50) process.exit(1);
|
|
6871
7004
|
} catch (error2) {
|
package/dist/index.js
CHANGED
package/package.json
CHANGED