@vertaaux/cli 0.4.0 → 0.5.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/CHANGELOG.md +116 -0
- package/MIGRATION.md +239 -0
- package/README.md +62 -17
- package/dist/app/interactive-app.d.ts +103 -0
- package/dist/app/interactive-app.d.ts.map +1 -0
- package/dist/app/interactive-app.js +328 -0
- package/dist/app/layout/canvas.d.ts +23 -0
- package/dist/app/layout/canvas.d.ts.map +1 -0
- package/dist/app/layout/canvas.js +36 -0
- package/dist/app/layout/footer.d.ts +31 -0
- package/dist/app/layout/footer.d.ts.map +1 -0
- package/dist/app/layout/footer.js +41 -0
- package/dist/app/layout/header.d.ts +20 -0
- package/dist/app/layout/header.d.ts.map +1 -0
- package/dist/app/layout/header.js +27 -0
- package/dist/app/menu/categories.d.ts +20 -0
- package/dist/app/menu/categories.d.ts.map +1 -0
- package/dist/app/menu/categories.js +166 -0
- package/dist/app/menu/filter.d.ts +17 -0
- package/dist/app/menu/filter.d.ts.map +1 -0
- package/dist/app/menu/filter.js +33 -0
- package/dist/app/menu/menu-view.d.ts +35 -0
- package/dist/app/menu/menu-view.d.ts.map +1 -0
- package/dist/app/menu/menu-view.js +230 -0
- package/dist/app/menu/recent.d.ts +24 -0
- package/dist/app/menu/recent.d.ts.map +1 -0
- package/dist/app/menu/recent.js +49 -0
- package/dist/app/types.d.ts +43 -0
- package/dist/app/types.d.ts.map +1 -0
- package/dist/app/types.js +7 -0
- package/dist/app/views/command-runner.d.ts +36 -0
- package/dist/app/views/command-runner.d.ts.map +1 -0
- package/dist/app/views/command-runner.js +415 -0
- package/dist/app/views/help-overlay.d.ts +21 -0
- package/dist/app/views/help-overlay.d.ts.map +1 -0
- package/dist/app/views/help-overlay.js +46 -0
- package/dist/auth/ci-token.d.ts +8 -2
- package/dist/auth/ci-token.d.ts.map +1 -1
- package/dist/auth/ci-token.js +15 -30
- package/dist/auth/device-flow.d.ts +2 -1
- package/dist/auth/device-flow.d.ts.map +1 -1
- package/dist/auth/device-flow.js +13 -10
- package/dist/auth/token-store.d.ts.map +1 -1
- package/dist/auth/token-store.js +12 -2
- package/dist/baseline/diff.d.ts +2 -2
- package/dist/baseline/diff.d.ts.map +1 -1
- package/dist/baseline/diff.js +15 -34
- package/dist/commands/a11y.d.ts +11 -0
- package/dist/commands/a11y.d.ts.map +1 -0
- package/dist/commands/a11y.js +149 -0
- package/dist/commands/audit/artifacts.d.ts +27 -0
- package/dist/commands/audit/artifacts.d.ts.map +1 -0
- package/dist/commands/audit/artifacts.js +158 -0
- package/dist/commands/audit/ci-detection.d.ts +18 -0
- package/dist/commands/audit/ci-detection.d.ts.map +1 -0
- package/dist/commands/audit/ci-detection.js +71 -0
- package/dist/commands/audit/explain.d.ts +11 -0
- package/dist/commands/audit/explain.d.ts.map +1 -0
- package/dist/commands/audit/explain.js +45 -0
- package/dist/commands/audit/filters.d.ts +17 -0
- package/dist/commands/audit/filters.d.ts.map +1 -0
- package/dist/commands/audit/filters.js +40 -0
- package/dist/commands/audit/index.d.ts +18 -0
- package/dist/commands/audit/index.d.ts.map +1 -0
- package/dist/commands/audit/index.js +589 -0
- package/dist/commands/audit/output.d.ts +32 -0
- package/dist/commands/audit/output.d.ts.map +1 -0
- package/dist/commands/audit/output.js +129 -0
- package/dist/commands/audit/policy.d.ts +27 -0
- package/dist/commands/audit/policy.d.ts.map +1 -0
- package/dist/commands/audit/policy.js +147 -0
- package/dist/commands/audit/scoring.d.ts +23 -0
- package/dist/commands/audit/scoring.d.ts.map +1 -0
- package/dist/commands/audit/scoring.js +70 -0
- package/dist/commands/audit/types.d.ts +89 -0
- package/dist/commands/audit/types.d.ts.map +1 -0
- package/dist/commands/audit/types.js +8 -0
- package/dist/commands/audit.d.ts +2 -60
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +2 -1097
- package/dist/commands/baseline.d.ts +2 -0
- package/dist/commands/baseline.d.ts.map +1 -1
- package/dist/commands/baseline.js +221 -123
- package/dist/commands/comment.d.ts +22 -0
- package/dist/commands/comment.d.ts.map +1 -1
- package/dist/commands/comment.js +127 -62
- package/dist/commands/compare.d.ts +17 -0
- package/dist/commands/compare.d.ts.map +1 -1
- package/dist/commands/compare.js +288 -181
- package/dist/commands/diff.d.ts +7 -0
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +181 -143
- package/dist/commands/doc.d.ts +10 -0
- package/dist/commands/doc.d.ts.map +1 -1
- package/dist/commands/doc.js +135 -77
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +166 -19
- package/dist/commands/download.d.ts +10 -0
- package/dist/commands/download.d.ts.map +1 -1
- package/dist/commands/download.js +169 -112
- package/dist/commands/explain.d.ts +5 -0
- package/dist/commands/explain.d.ts.map +1 -1
- package/dist/commands/explain.js +242 -156
- package/dist/commands/fix-all.d.ts +25 -0
- package/dist/commands/fix-all.d.ts.map +1 -0
- package/dist/commands/fix-all.js +206 -0
- package/dist/commands/fix-plan.d.ts +9 -0
- package/dist/commands/fix-plan.d.ts.map +1 -1
- package/dist/commands/fix-plan.js +154 -90
- package/dist/commands/fix.d.ts +17 -0
- package/dist/commands/fix.d.ts.map +1 -0
- package/dist/commands/fix.js +111 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +94 -42
- package/dist/commands/login.d.ts +18 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +263 -92
- package/dist/commands/patch-review.d.ts +11 -0
- package/dist/commands/patch-review.d.ts.map +1 -1
- package/dist/commands/patch-review.js +160 -98
- package/dist/commands/policy.d.ts +31 -0
- package/dist/commands/policy.d.ts.map +1 -1
- package/dist/commands/policy.js +270 -125
- package/dist/commands/release-notes.d.ts +10 -0
- package/dist/commands/release-notes.d.ts.map +1 -1
- package/dist/commands/release-notes.js +128 -74
- package/dist/commands/scan.d.ts +13 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +133 -0
- package/dist/commands/status.d.ts +9 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +81 -0
- package/dist/commands/suggest.d.ts +10 -0
- package/dist/commands/suggest.d.ts.map +1 -1
- package/dist/commands/suggest.js +180 -83
- package/dist/commands/triage.d.ts +35 -0
- package/dist/commands/triage.d.ts.map +1 -1
- package/dist/commands/triage.js +207 -82
- package/dist/commands/upload.d.ts +9 -0
- package/dist/commands/upload.d.ts.map +1 -1
- package/dist/commands/upload.js +140 -101
- package/dist/commands/verify.d.ts +13 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +118 -0
- package/dist/config/schema.d.ts +4 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +127 -991
- package/dist/interactive/fix-wizard.d.ts +3 -0
- package/dist/interactive/fix-wizard.d.ts.map +1 -1
- package/dist/interactive/fix-wizard.js +130 -112
- package/dist/interactive/init-wizard.d.ts +3 -1
- package/dist/interactive/init-wizard.d.ts.map +1 -1
- package/dist/interactive/init-wizard.js +207 -138
- package/dist/interactive/prompts.d.ts +7 -3
- package/dist/interactive/prompts.d.ts.map +1 -1
- package/dist/interactive/prompts.js +44 -23
- package/dist/output/envelope.d.ts +9 -0
- package/dist/output/envelope.d.ts.map +1 -1
- package/dist/output/envelope.js +37 -3
- package/dist/output/factory.d.ts +2 -1
- package/dist/output/factory.d.ts.map +1 -1
- package/dist/output/html.d.ts +2 -1
- package/dist/output/html.d.ts.map +1 -1
- package/dist/output/html.js +3 -2
- package/dist/output/human.d.ts +2 -1
- package/dist/output/human.d.ts.map +1 -1
- package/dist/output/human.js +3 -2
- package/dist/output/json.d.ts +2 -1
- package/dist/output/json.d.ts.map +1 -1
- package/dist/output/junit.d.ts +2 -1
- package/dist/output/junit.d.ts.map +1 -1
- package/dist/output/sarif.d.ts +2 -1
- package/dist/output/sarif.d.ts.map +1 -1
- package/dist/policy/schema.d.ts +137 -0
- package/dist/policy/schema.d.ts.map +1 -1
- package/dist/policy/schema.js +107 -0
- package/dist/prompts/command-catalog.js +9 -9
- package/dist/types.d.ts +74 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/ui/banner.d.ts +34 -0
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +97 -5
- package/dist/ui/diagnostics.d.ts +9 -4
- package/dist/ui/diagnostics.d.ts.map +1 -1
- package/dist/ui/diagnostics.js +32 -82
- package/dist/ui/strings.d.ts +373 -0
- package/dist/ui/strings.d.ts.map +1 -0
- package/dist/ui/strings.js +499 -0
- package/dist/ui/table.d.ts +0 -2
- package/dist/ui/table.d.ts.map +1 -1
- package/dist/ui/table.js +3 -4
- package/dist/utils/api-client.d.ts +46 -0
- package/dist/utils/api-client.d.ts.map +1 -0
- package/dist/utils/api-client.js +170 -0
- package/dist/utils/client.d.ts +29 -18
- package/dist/utils/client.d.ts.map +1 -1
- package/dist/utils/client.js +104 -12
- package/dist/utils/formatters.d.ts +38 -0
- package/dist/utils/formatters.d.ts.map +1 -0
- package/dist/utils/formatters.js +277 -0
- package/dist/utils/root-args.d.ts +12 -0
- package/dist/utils/root-args.d.ts.map +1 -0
- package/dist/utils/root-args.js +44 -0
- package/dist/utils/stdin.d.ts +7 -0
- package/dist/utils/stdin.d.ts.map +1 -1
- package/dist/utils/stdin.js +32 -2
- package/dist/utils/url-classify.d.ts.map +1 -1
- package/dist/utils/url-classify.js +24 -3
- package/node_modules/@vertaaux/tui/dist/index.cjs +1216 -27
- package/node_modules/@vertaaux/tui/dist/index.cjs.map +1 -1
- package/node_modules/@vertaaux/tui/dist/index.d.cts +361 -4
- package/node_modules/@vertaaux/tui/dist/index.d.ts +361 -4
- package/node_modules/@vertaaux/tui/dist/index.js +1189 -27
- package/node_modules/@vertaaux/tui/dist/index.js.map +1 -1
- package/node_modules/@vertaaux/tui/package.json +2 -3
- package/node_modules/chalk/license +9 -0
- package/node_modules/chalk/package.json +83 -0
- package/node_modules/chalk/readme.md +297 -0
- package/node_modules/chalk/source/index.d.ts +325 -0
- package/node_modules/chalk/source/index.js +225 -0
- package/node_modules/chalk/source/utilities.js +33 -0
- package/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +236 -0
- package/node_modules/chalk/source/vendor/ansi-styles/index.js +223 -0
- package/node_modules/chalk/source/vendor/supports-color/browser.d.ts +1 -0
- package/node_modules/chalk/source/vendor/supports-color/browser.js +34 -0
- package/node_modules/chalk/source/vendor/supports-color/index.d.ts +55 -0
- package/node_modules/chalk/source/vendor/supports-color/index.js +190 -0
- package/package.json +20 -5
- package/dist/commands/client.d.ts +0 -14
- package/dist/commands/client.d.ts.map +0 -1
- package/dist/commands/client.js +0 -362
- package/dist/commands/drift.d.ts +0 -15
- package/dist/commands/drift.d.ts.map +0 -1
- package/dist/commands/drift.js +0 -309
- package/dist/commands/protect.d.ts +0 -16
- package/dist/commands/protect.d.ts.map +0 -1
- package/dist/commands/protect.js +0 -323
- package/dist/commands/report.d.ts +0 -15
- package/dist/commands/report.d.ts.map +0 -1
- package/dist/commands/report.js +0 -214
- package/dist/policy/sync.d.ts +0 -67
- package/dist/policy/sync.d.ts.map +0 -1
- package/dist/policy/sync.js +0 -147
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output formatting utilities for the VertaaUX CLI legacy commands.
|
|
3
|
+
* Provides markdown and JSON formatting functions for audit/fix/verify results.
|
|
4
|
+
*/
|
|
5
|
+
import { scoreColor, boldColor } from "@vertaaux/tui";
|
|
6
|
+
import { writeOutput } from "../output/envelope.js";
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Data normalization
|
|
9
|
+
// ============================================================================
|
|
10
|
+
export function normalizeIssues(issues) {
|
|
11
|
+
if (Array.isArray(issues))
|
|
12
|
+
return issues;
|
|
13
|
+
if (issues && typeof issues === "object") {
|
|
14
|
+
const values = Object.values(issues);
|
|
15
|
+
return values.flatMap((value) => (Array.isArray(value) ? value : []));
|
|
16
|
+
}
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
export function toNumber(value) {
|
|
20
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
21
|
+
return value;
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
export function getOverallScore(scores) {
|
|
25
|
+
if (!scores)
|
|
26
|
+
return null;
|
|
27
|
+
const s = scores;
|
|
28
|
+
const direct = toNumber(s.overall ?? s.ux ?? s.total);
|
|
29
|
+
if (direct !== null)
|
|
30
|
+
return direct;
|
|
31
|
+
const numeric = Object.values(s)
|
|
32
|
+
.map((value) => toNumber(value))
|
|
33
|
+
.filter((value) => value !== null);
|
|
34
|
+
if (numeric.length === 0)
|
|
35
|
+
return null;
|
|
36
|
+
const avg = numeric.reduce((sum, value) => sum + value, 0) / numeric.length;
|
|
37
|
+
return Math.round(avg);
|
|
38
|
+
}
|
|
39
|
+
export function getCategoryScore(scores, key) {
|
|
40
|
+
if (!scores)
|
|
41
|
+
return null;
|
|
42
|
+
return toNumber(scores[key]);
|
|
43
|
+
}
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// Markdown formatters
|
|
46
|
+
// ============================================================================
|
|
47
|
+
export function formatScoresTable(scores) {
|
|
48
|
+
if (!scores)
|
|
49
|
+
return "No scores available.";
|
|
50
|
+
const entries = Object.entries(scores).filter(([, value]) => typeof value === "number");
|
|
51
|
+
if (entries.length === 0)
|
|
52
|
+
return "No scores available.";
|
|
53
|
+
const lines = ["| Category | Score |", "| --- | --- |"];
|
|
54
|
+
for (const [key, value] of entries) {
|
|
55
|
+
lines.push(`| ${key} | ${value} |`);
|
|
56
|
+
}
|
|
57
|
+
return lines.join("\n");
|
|
58
|
+
}
|
|
59
|
+
export function formatIssuesList(issues, limit = 5) {
|
|
60
|
+
if (!issues.length)
|
|
61
|
+
return "No issues.";
|
|
62
|
+
const lines = issues.slice(0, limit).map((issue, index) => {
|
|
63
|
+
const label = issue.title || issue.id || "Issue";
|
|
64
|
+
const severity = issue.severity ? issue.severity.toUpperCase() : "INFO";
|
|
65
|
+
return `${index + 1}. [${severity}] ${label}`;
|
|
66
|
+
});
|
|
67
|
+
if (issues.length > limit) {
|
|
68
|
+
lines.push(`...and ${issues.length - limit} more`);
|
|
69
|
+
}
|
|
70
|
+
return lines.join("\n");
|
|
71
|
+
}
|
|
72
|
+
export function formatAuditMarkdown(result) {
|
|
73
|
+
const status = result.status || "unknown";
|
|
74
|
+
const lines = [`## Audit Results`, `- Status: ${status}`];
|
|
75
|
+
if (result.job_id)
|
|
76
|
+
lines.push(`- Job ID: ${result.job_id}`);
|
|
77
|
+
if (result.url)
|
|
78
|
+
lines.push(`- URL: ${result.url}`);
|
|
79
|
+
if (result.mode)
|
|
80
|
+
lines.push(`- Mode: ${result.mode}`);
|
|
81
|
+
if (typeof result.progress === "number" && status !== "completed") {
|
|
82
|
+
lines.push(`- Progress: ${result.progress}%`);
|
|
83
|
+
}
|
|
84
|
+
if (status !== "completed")
|
|
85
|
+
return lines.join("\n");
|
|
86
|
+
const overall = getOverallScore(result.scores);
|
|
87
|
+
if (overall !== null)
|
|
88
|
+
lines.push(`- Overall score: ${boldColor(String(overall), scoreColor(overall))}`);
|
|
89
|
+
lines.push("\n### Scores");
|
|
90
|
+
lines.push(formatScoresTable(result.scores));
|
|
91
|
+
const issues = normalizeIssues(result.issues);
|
|
92
|
+
lines.push("\n### Issues");
|
|
93
|
+
lines.push(`Total issues: ${issues.length}`);
|
|
94
|
+
lines.push(formatIssuesList(issues));
|
|
95
|
+
return lines.join("\n");
|
|
96
|
+
}
|
|
97
|
+
export function formatA11yMarkdown(result) {
|
|
98
|
+
const lines = [`## Accessibility Audit`, `- Status: ${result.status || "unknown"}`];
|
|
99
|
+
if (result.url)
|
|
100
|
+
lines.push(`- URL: ${result.url}`);
|
|
101
|
+
if (result.mode)
|
|
102
|
+
lines.push(`- Mode: ${result.mode}`);
|
|
103
|
+
if (result.status !== "completed")
|
|
104
|
+
return lines.join("\n");
|
|
105
|
+
const a11yScore = getCategoryScore(result.scores, "accessibility");
|
|
106
|
+
if (a11yScore !== null)
|
|
107
|
+
lines.push(`- Accessibility score: ${boldColor(String(a11yScore), scoreColor(a11yScore))}`);
|
|
108
|
+
const issues = normalizeIssues(result.issues).filter((issue) => {
|
|
109
|
+
const category = (issue.category || "").toLowerCase();
|
|
110
|
+
return (category.includes("accessibility") ||
|
|
111
|
+
category.includes("a11y") ||
|
|
112
|
+
category.includes("wcag"));
|
|
113
|
+
});
|
|
114
|
+
lines.push("\n### Accessibility Issues");
|
|
115
|
+
lines.push(`Total accessibility issues: ${issues.length}`);
|
|
116
|
+
lines.push(formatIssuesList(issues));
|
|
117
|
+
return lines.join("\n");
|
|
118
|
+
}
|
|
119
|
+
export function formatCompareMarkdown(compare) {
|
|
120
|
+
const lines = ["## Audit Comparison"];
|
|
121
|
+
lines.push(`- URL A: ${compare.urlA}`);
|
|
122
|
+
lines.push(`- URL B: ${compare.urlB}`);
|
|
123
|
+
lines.push(`- Job A: ${compare.jobA}`);
|
|
124
|
+
lines.push(`- Job B: ${compare.jobB}`);
|
|
125
|
+
lines.push("\n### Overall Scores");
|
|
126
|
+
lines.push("| Site | Score | Delta |");
|
|
127
|
+
lines.push("| --- | --- | --- |");
|
|
128
|
+
lines.push(`| A | ${compare.overallA !== null ? boldColor(String(compare.overallA), scoreColor(compare.overallA)) : "n/a"} | ${compare.delta ?? "n/a"} |`);
|
|
129
|
+
lines.push(`| B | ${compare.overallB !== null ? boldColor(String(compare.overallB), scoreColor(compare.overallB)) : "n/a"} | ${compare.delta ?? "n/a"} |`);
|
|
130
|
+
lines.push("\n### Category Scores");
|
|
131
|
+
lines.push("| Category | A | B | Delta |");
|
|
132
|
+
lines.push("| --- | --- | --- | --- |");
|
|
133
|
+
for (const [key, values] of Object.entries(compare.categoryDeltas)) {
|
|
134
|
+
lines.push(`| ${key} | ${values.a ?? "n/a"} | ${values.b ?? "n/a"} | ${values.delta ?? "n/a"} |`);
|
|
135
|
+
}
|
|
136
|
+
lines.push("\n### Issue Counts");
|
|
137
|
+
lines.push(`- A: ${compare.issuesA}`);
|
|
138
|
+
lines.push(`- B: ${compare.issuesB}`);
|
|
139
|
+
return lines.join("\n");
|
|
140
|
+
}
|
|
141
|
+
export function formatExplainMarkdown(issue) {
|
|
142
|
+
const lines = ["## Issue Explanation"];
|
|
143
|
+
if (issue.id)
|
|
144
|
+
lines.push(`- ID: ${issue.id}`);
|
|
145
|
+
if (issue.severity)
|
|
146
|
+
lines.push(`- Severity: ${issue.severity}`);
|
|
147
|
+
if (issue.category)
|
|
148
|
+
lines.push(`- Category: ${issue.category}`);
|
|
149
|
+
if (issue.selector)
|
|
150
|
+
lines.push(`- Selector: ${issue.selector}`);
|
|
151
|
+
if (issue.description) {
|
|
152
|
+
lines.push("\n### Description");
|
|
153
|
+
lines.push(issue.description);
|
|
154
|
+
}
|
|
155
|
+
const recommendation = issue.recommendation || issue.recommended_fix;
|
|
156
|
+
if (recommendation) {
|
|
157
|
+
lines.push("\n### Recommendation");
|
|
158
|
+
lines.push(recommendation);
|
|
159
|
+
}
|
|
160
|
+
if (issue.wcag_reference) {
|
|
161
|
+
lines.push("\n### WCAG Reference");
|
|
162
|
+
lines.push(issue.wcag_reference);
|
|
163
|
+
}
|
|
164
|
+
return lines.join("\n");
|
|
165
|
+
}
|
|
166
|
+
export function formatPatchMarkdown(patch) {
|
|
167
|
+
if (!patch)
|
|
168
|
+
return "No patch generated.";
|
|
169
|
+
const lines = [
|
|
170
|
+
"## Patch Generated",
|
|
171
|
+
"",
|
|
172
|
+
`**Confidence:** ${patch.confidence.label} (${patch.confidence.percentage}%)`,
|
|
173
|
+
`**Classification:** ${patch.classification}`,
|
|
174
|
+
"",
|
|
175
|
+
"### Explanation",
|
|
176
|
+
patch.explanation,
|
|
177
|
+
"",
|
|
178
|
+
"### Search",
|
|
179
|
+
"```",
|
|
180
|
+
patch.search,
|
|
181
|
+
"```",
|
|
182
|
+
"",
|
|
183
|
+
"### Replace",
|
|
184
|
+
"```",
|
|
185
|
+
patch.replace,
|
|
186
|
+
"```",
|
|
187
|
+
];
|
|
188
|
+
return lines.join("\n");
|
|
189
|
+
}
|
|
190
|
+
export function formatVerifyMarkdown(result) {
|
|
191
|
+
if (!result.success || !result.verification) {
|
|
192
|
+
return `## Verification Failed\n\n${result.error?.message || "Unknown error"}`;
|
|
193
|
+
}
|
|
194
|
+
const v = result.verification;
|
|
195
|
+
const deltaSign = v.score_delta.delta >= 0 ? "+" : "";
|
|
196
|
+
const lines = [
|
|
197
|
+
"## Verification Result",
|
|
198
|
+
"",
|
|
199
|
+
`**Issue Fixed:** ${v.issue_fixed ? "Yes" : "No"}`,
|
|
200
|
+
`**Score Delta:** ${boldColor(String(v.score_delta.before), scoreColor(v.score_delta.before))} -> ${boldColor(String(v.score_delta.after), scoreColor(v.score_delta.after))} (${deltaSign}${v.score_delta.delta})`,
|
|
201
|
+
`**Component:** ${v.component_audited}`,
|
|
202
|
+
`**Duration:** ${v.duration_ms}ms`,
|
|
203
|
+
];
|
|
204
|
+
if (v.regressions.length > 0) {
|
|
205
|
+
lines.push("", "### Regressions");
|
|
206
|
+
for (const r of v.regressions) {
|
|
207
|
+
lines.push(`- [${r.impact.toUpperCase()}] ${r.rule_id}: ${r.description}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
lines.push("", "### Regressions", "None");
|
|
212
|
+
}
|
|
213
|
+
if (v.error) {
|
|
214
|
+
lines.push("", `**Warning:** ${v.error}`);
|
|
215
|
+
}
|
|
216
|
+
return lines.join("\n");
|
|
217
|
+
}
|
|
218
|
+
// Auto-fixable issue types (from lib/patch/classifier.ts)
|
|
219
|
+
const AUTO_FIXABLE_TYPES = new Set([
|
|
220
|
+
"label",
|
|
221
|
+
"input-missing-label",
|
|
222
|
+
"form-field-label",
|
|
223
|
+
"button-name",
|
|
224
|
+
"missing-button-name",
|
|
225
|
+
"link-name",
|
|
226
|
+
"html-has-lang",
|
|
227
|
+
"missing-lang-attribute",
|
|
228
|
+
"html-lang-valid",
|
|
229
|
+
"document-title",
|
|
230
|
+
"bypass",
|
|
231
|
+
"region",
|
|
232
|
+
"landmark-one-main",
|
|
233
|
+
"color-contrast",
|
|
234
|
+
"autocomplete-valid",
|
|
235
|
+
"aria-required-attr",
|
|
236
|
+
"aria-valid-attr",
|
|
237
|
+
"aria-valid-attr-value",
|
|
238
|
+
]);
|
|
239
|
+
export function isAutoFixable(issueType) {
|
|
240
|
+
const normalized = issueType.toLowerCase().replace(/^(axe|wcag)-/, "");
|
|
241
|
+
return AUTO_FIXABLE_TYPES.has(normalized);
|
|
242
|
+
}
|
|
243
|
+
export function formatBatchMarkdown(results) {
|
|
244
|
+
const lines = [
|
|
245
|
+
"## Batch Patch Results",
|
|
246
|
+
"",
|
|
247
|
+
`**Total Requested:** ${results.totalRequested}`,
|
|
248
|
+
`**Succeeded:** ${results.successes.length}`,
|
|
249
|
+
`**Failed:** ${results.failures.length}`,
|
|
250
|
+
`**Skipped:** ${results.totalSkipped}`,
|
|
251
|
+
];
|
|
252
|
+
if (results.successes.length > 0) {
|
|
253
|
+
lines.push("", "### Successful Patches");
|
|
254
|
+
for (const s of results.successes) {
|
|
255
|
+
const conf = s.patch?.confidence;
|
|
256
|
+
const cls = s.patch?.classification || "unknown";
|
|
257
|
+
const confStr = conf ? `${conf.label} (${conf.percentage}%)` : "n/a";
|
|
258
|
+
lines.push(`- ${s.issueId}: ${confStr} [${cls}]`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (results.failures.length > 0) {
|
|
262
|
+
lines.push("", "### Failed");
|
|
263
|
+
for (const f of results.failures) {
|
|
264
|
+
const details = f.details ? ` - ${f.details}` : "";
|
|
265
|
+
lines.push(`- ${f.issueId}: ${f.reason}${details}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return lines.join("\n");
|
|
269
|
+
}
|
|
270
|
+
export function printOutput(format, data, markdown) {
|
|
271
|
+
if (format === "json") {
|
|
272
|
+
process.stdout.write(JSON.stringify(data, null, 2) + "\n");
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
// Route through writeOutput so interactive mode can buffer the output
|
|
276
|
+
writeOutput(markdown || "");
|
|
277
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function hasHelpOrVersionFlag(args: string[]): boolean;
|
|
2
|
+
/**
|
|
3
|
+
* Return the first non-option token after skipping root global options.
|
|
4
|
+
*
|
|
5
|
+
* This keeps the "launch interactive app when no command is present" behavior
|
|
6
|
+
* while still allowing global flags to appear before the subcommand:
|
|
7
|
+
*
|
|
8
|
+
* vertaa --machine doctor
|
|
9
|
+
* vertaa --base https://api.example.test audit https://example.com
|
|
10
|
+
*/
|
|
11
|
+
export declare function getRootCommandToken(args: string[]): string | undefined;
|
|
12
|
+
//# sourceMappingURL=root-args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-args.d.ts","sourceRoot":"","sources":["../../src/utils/root-args.ts"],"names":[],"mappings":"AAcA,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAE5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAyBtE"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const ROOT_OPTIONS_WITH_VALUES = new Set([
|
|
2
|
+
"-b",
|
|
3
|
+
"--base",
|
|
4
|
+
"-c",
|
|
5
|
+
"--config",
|
|
6
|
+
]);
|
|
7
|
+
const HELP_OR_VERSION_FLAGS = new Set([
|
|
8
|
+
"-h",
|
|
9
|
+
"--help",
|
|
10
|
+
"-v",
|
|
11
|
+
"--version",
|
|
12
|
+
]);
|
|
13
|
+
export function hasHelpOrVersionFlag(args) {
|
|
14
|
+
return args.some((arg) => HELP_OR_VERSION_FLAGS.has(arg));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Return the first non-option token after skipping root global options.
|
|
18
|
+
*
|
|
19
|
+
* This keeps the "launch interactive app when no command is present" behavior
|
|
20
|
+
* while still allowing global flags to appear before the subcommand:
|
|
21
|
+
*
|
|
22
|
+
* vertaa --machine doctor
|
|
23
|
+
* vertaa --base https://api.example.test audit https://example.com
|
|
24
|
+
*/
|
|
25
|
+
export function getRootCommandToken(args) {
|
|
26
|
+
for (let i = 0; i < args.length; i++) {
|
|
27
|
+
const arg = args[i];
|
|
28
|
+
if (arg === "--") {
|
|
29
|
+
return args[i + 1];
|
|
30
|
+
}
|
|
31
|
+
if (ROOT_OPTIONS_WITH_VALUES.has(arg)) {
|
|
32
|
+
i++;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (arg.startsWith("--base=") || arg.startsWith("--config=")) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (arg.startsWith("-")) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
return arg;
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
package/dist/utils/stdin.d.ts
CHANGED
|
@@ -16,6 +16,13 @@ export interface StdinResult {
|
|
|
16
16
|
/** Whether the input was valid JSON */
|
|
17
17
|
isJson: boolean;
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Unwrap the standard CLI JSON envelope shape ({ meta, data }).
|
|
21
|
+
*
|
|
22
|
+
* Commands that consume the output of other VertaaUX commands usually want
|
|
23
|
+
* the payload under `data`, not the outer provenance metadata.
|
|
24
|
+
*/
|
|
25
|
+
export declare function unwrapJsonEnvelope<T = unknown>(input: unknown): T;
|
|
19
26
|
/**
|
|
20
27
|
* Check if stdin has piped data available.
|
|
21
28
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdin.d.ts","sourceRoot":"","sources":["../../src/utils/stdin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IACrB,uCAAuC;IACvC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA2B7D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CA+B9E;AAED;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAG5D"}
|
|
1
|
+
{"version":3,"file":"stdin.d.ts","sourceRoot":"","sources":["../../src/utils/stdin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IACrB,uCAAuC;IACvC,MAAM,EAAE,OAAO,CAAC;CACjB;AAqBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,CAKjE;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA2B7D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CA+B9E;AAED;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAG5D"}
|
package/dist/utils/stdin.js
CHANGED
|
@@ -5,6 +5,36 @@
|
|
|
5
5
|
* and provides a consistent interface for all commands that accept
|
|
6
6
|
* piped data (explain, triage, fix-plan, patch-review, etc.).
|
|
7
7
|
*/
|
|
8
|
+
/**
|
|
9
|
+
* Detect the standard CLI JSON envelope shape ({ meta, data }).
|
|
10
|
+
*
|
|
11
|
+
* Only matches when `meta` contains `command` and `version` — the fields
|
|
12
|
+
* that `createEnvelope()` always emits — so legitimate JSON payloads that
|
|
13
|
+
* happen to have a top-level `data` key are left untouched.
|
|
14
|
+
*/
|
|
15
|
+
function isVertaaEnvelope(input) {
|
|
16
|
+
if (!input || typeof input !== "object" || !("meta" in input) || !("data" in input)) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const meta = input.meta;
|
|
20
|
+
if (!meta || typeof meta !== "object") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const { command, version } = meta;
|
|
24
|
+
return command !== undefined && version !== undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Unwrap the standard CLI JSON envelope shape ({ meta, data }).
|
|
28
|
+
*
|
|
29
|
+
* Commands that consume the output of other VertaaUX commands usually want
|
|
30
|
+
* the payload under `data`, not the outer provenance metadata.
|
|
31
|
+
*/
|
|
32
|
+
export function unwrapJsonEnvelope(input) {
|
|
33
|
+
if (isVertaaEnvelope(input)) {
|
|
34
|
+
return input.data;
|
|
35
|
+
}
|
|
36
|
+
return input;
|
|
37
|
+
}
|
|
8
38
|
/**
|
|
9
39
|
* Check if stdin has piped data available.
|
|
10
40
|
*/
|
|
@@ -64,7 +94,7 @@ export async function readJsonInput(filePath) {
|
|
|
64
94
|
}
|
|
65
95
|
const content = fs.readFileSync(resolved, "utf-8");
|
|
66
96
|
try {
|
|
67
|
-
return JSON.parse(content);
|
|
97
|
+
return unwrapJsonEnvelope(JSON.parse(content));
|
|
68
98
|
}
|
|
69
99
|
catch {
|
|
70
100
|
throw new Error(`Invalid JSON in file: ${filePath}`);
|
|
@@ -77,7 +107,7 @@ export async function readJsonInput(filePath) {
|
|
|
77
107
|
throw new Error("Could not parse input as JSON. If piping from vertaa, use --json flag:\n" +
|
|
78
108
|
" vertaa audit https://example.com --json | vertaa explain");
|
|
79
109
|
}
|
|
80
|
-
return stdin.json;
|
|
110
|
+
return unwrapJsonEnvelope(stdin.json);
|
|
81
111
|
}
|
|
82
112
|
// No input found
|
|
83
113
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-classify.d.ts","sourceRoot":"","sources":["../../src/utils/url-classify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;AAEzD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"url-classify.d.ts","sourceRoot":"","sources":["../../src/utils/url-classify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;AAEzD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CA8BtD;AAgED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAGrD"}
|
|
@@ -25,9 +25,12 @@ export function classifyUrl(urlString) {
|
|
|
25
25
|
hostname.endsWith(".localhost")) {
|
|
26
26
|
return "localhost";
|
|
27
27
|
}
|
|
28
|
-
// IP literal check
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
// IP literal check — strip brackets from IPv6 literals
|
|
29
|
+
const ip = hostname.startsWith("[") && hostname.endsWith("]")
|
|
30
|
+
? hostname.slice(1, -1)
|
|
31
|
+
: hostname;
|
|
32
|
+
if (net.isIP(ip)) {
|
|
33
|
+
if (isPrivateIp(ip))
|
|
31
34
|
return "private";
|
|
32
35
|
return "public";
|
|
33
36
|
}
|
|
@@ -40,6 +43,24 @@ function isPrivateIp(address) {
|
|
|
40
43
|
const version = net.isIP(address);
|
|
41
44
|
if (version === 6) {
|
|
42
45
|
const lower = address.toLowerCase();
|
|
46
|
+
// IPv4-mapped IPv6 — extract and check as IPv4
|
|
47
|
+
// Handles both dotted form (::ffff:127.0.0.1) and hex form (::ffff:7f00:1)
|
|
48
|
+
if (lower.startsWith("::ffff:")) {
|
|
49
|
+
const mapped = lower.slice(7); // strip "::ffff:"
|
|
50
|
+
if (net.isIPv4(mapped)) {
|
|
51
|
+
return isPrivateIp(mapped);
|
|
52
|
+
}
|
|
53
|
+
// Hex form: two 16-bit groups (e.g. "7f00:1" = 127.0.0.1)
|
|
54
|
+
const hexParts = mapped.split(":");
|
|
55
|
+
if (hexParts.length === 2) {
|
|
56
|
+
const hi = parseInt(hexParts[0], 16);
|
|
57
|
+
const lo = parseInt(hexParts[1], 16);
|
|
58
|
+
if (!isNaN(hi) && !isNaN(lo) && hi <= 0xffff && lo <= 0xffff) {
|
|
59
|
+
const ipv4 = `${(hi >> 8) & 0xff}.${hi & 0xff}.${(lo >> 8) & 0xff}.${lo & 0xff}`;
|
|
60
|
+
return isPrivateIp(ipv4);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
43
64
|
return (lower === "::" ||
|
|
44
65
|
lower === "::1" ||
|
|
45
66
|
lower.startsWith("fc") ||
|