paintoliver 0.1.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.
- package/LICENSE +21 -0
- package/README.md +207 -0
- package/dist/analyzer/index.d.ts +20 -0
- package/dist/analyzer/index.d.ts.map +1 -0
- package/dist/analyzer/index.js +387 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/cli.d.ts +26 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +436 -0
- package/dist/cli.js.map +1 -0
- package/dist/contrast/index.d.ts +88 -0
- package/dist/contrast/index.d.ts.map +1 -0
- package/dist/contrast/index.js +314 -0
- package/dist/contrast/index.js.map +1 -0
- package/dist/paintoliver.bundle.js +14530 -0
- package/dist/reporter/index.d.ts +43 -0
- package/dist/reporter/index.d.ts.map +1 -0
- package/dist/reporter/index.js +235 -0
- package/dist/reporter/index.js.map +1 -0
- package/dist/transformer/css-var-transformer.d.ts +46 -0
- package/dist/transformer/css-var-transformer.d.ts.map +1 -0
- package/dist/transformer/css-var-transformer.js +422 -0
- package/dist/transformer/css-var-transformer.js.map +1 -0
- package/dist/transformer/index.d.ts +17 -0
- package/dist/transformer/index.d.ts.map +1 -0
- package/dist/transformer/index.js +213 -0
- package/dist/transformer/index.js.map +1 -0
- package/dist/transformer/tailwind-transformer.d.ts +47 -0
- package/dist/transformer/tailwind-transformer.d.ts.map +1 -0
- package/dist/transformer/tailwind-transformer.js +402 -0
- package/dist/transformer/tailwind-transformer.js.map +1 -0
- package/dist/utils/backup.d.ts +41 -0
- package/dist/utils/backup.d.ts.map +1 -0
- package/dist/utils/backup.js +125 -0
- package/dist/utils/backup.js.map +1 -0
- package/dist/vibes/definitions/brutalist.d.ts +11 -0
- package/dist/vibes/definitions/brutalist.d.ts.map +1 -0
- package/dist/vibes/definitions/brutalist.js +203 -0
- package/dist/vibes/definitions/brutalist.js.map +1 -0
- package/dist/vibes/definitions/corporate.d.ts +12 -0
- package/dist/vibes/definitions/corporate.d.ts.map +1 -0
- package/dist/vibes/definitions/corporate.js +212 -0
- package/dist/vibes/definitions/corporate.js.map +1 -0
- package/dist/vibes/definitions/glassmorphism.d.ts +20 -0
- package/dist/vibes/definitions/glassmorphism.d.ts.map +1 -0
- package/dist/vibes/definitions/glassmorphism.js +217 -0
- package/dist/vibes/definitions/glassmorphism.js.map +1 -0
- package/dist/vibes/definitions/kinetic-terminal.d.ts +20 -0
- package/dist/vibes/definitions/kinetic-terminal.d.ts.map +1 -0
- package/dist/vibes/definitions/kinetic-terminal.js +242 -0
- package/dist/vibes/definitions/kinetic-terminal.js.map +1 -0
- package/dist/vibes/definitions/minimal.d.ts +11 -0
- package/dist/vibes/definitions/minimal.d.ts.map +1 -0
- package/dist/vibes/definitions/minimal.js +167 -0
- package/dist/vibes/definitions/minimal.js.map +1 -0
- package/dist/vibes/definitions/windows-xp.d.ts +12 -0
- package/dist/vibes/definitions/windows-xp.d.ts.map +1 -0
- package/dist/vibes/definitions/windows-xp.js +229 -0
- package/dist/vibes/definitions/windows-xp.js.map +1 -0
- package/dist/vibes/registry.d.ts +25 -0
- package/dist/vibes/registry.d.ts.map +1 -0
- package/dist/vibes/registry.js +52 -0
- package/dist/vibes/registry.js.map +1 -0
- package/dist/vibes/types.d.ts +428 -0
- package/dist/vibes/types.d.ts.map +1 -0
- package/dist/vibes/types.js +12 -0
- package/dist/vibes/types.js.map +1 -0
- package/package.json +41 -0
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* FrontEnd Agent CLI
|
|
4
|
+
*
|
|
5
|
+
* Commands:
|
|
6
|
+
* apply [vibe] [path] Apply a vibe to a project
|
|
7
|
+
* analyze [path] Analyze a project without modifying it
|
|
8
|
+
* list List all available vibes
|
|
9
|
+
* restore [path] Restore files from the most recent backup
|
|
10
|
+
* list-backups [path] Show all available backups with age info
|
|
11
|
+
* clear-overrides [path] Remove saved contrast overrides from config
|
|
12
|
+
*
|
|
13
|
+
* Examples:
|
|
14
|
+
* paintoliver apply minimal ./my-app
|
|
15
|
+
* paintoliver apply . --dry-run # reads vibe from .paintoliver.json
|
|
16
|
+
* paintoliver apply glassmorphism ./ui --backup --verbose
|
|
17
|
+
* paintoliver apply brutalist . --watch
|
|
18
|
+
* paintoliver apply corporate . --fix-contrast
|
|
19
|
+
* paintoliver analyze ./my-app
|
|
20
|
+
* paintoliver list
|
|
21
|
+
* paintoliver list-backups ./my-app
|
|
22
|
+
* paintoliver restore ./my-app
|
|
23
|
+
* paintoliver clear-overrides ./my-app
|
|
24
|
+
*/
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;GAsBG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* FrontEnd Agent CLI
|
|
4
|
+
*
|
|
5
|
+
* Commands:
|
|
6
|
+
* apply [vibe] [path] Apply a vibe to a project
|
|
7
|
+
* analyze [path] Analyze a project without modifying it
|
|
8
|
+
* list List all available vibes
|
|
9
|
+
* restore [path] Restore files from the most recent backup
|
|
10
|
+
* list-backups [path] Show all available backups with age info
|
|
11
|
+
* clear-overrides [path] Remove saved contrast overrides from config
|
|
12
|
+
*
|
|
13
|
+
* Examples:
|
|
14
|
+
* paintoliver apply minimal ./my-app
|
|
15
|
+
* paintoliver apply . --dry-run # reads vibe from .paintoliver.json
|
|
16
|
+
* paintoliver apply glassmorphism ./ui --backup --verbose
|
|
17
|
+
* paintoliver apply brutalist . --watch
|
|
18
|
+
* paintoliver apply corporate . --fix-contrast
|
|
19
|
+
* paintoliver analyze ./my-app
|
|
20
|
+
* paintoliver list
|
|
21
|
+
* paintoliver list-backups ./my-app
|
|
22
|
+
* paintoliver restore ./my-app
|
|
23
|
+
* paintoliver clear-overrides ./my-app
|
|
24
|
+
*/
|
|
25
|
+
import { Command } from "commander";
|
|
26
|
+
import * as readline from "readline";
|
|
27
|
+
import * as fs from "fs";
|
|
28
|
+
import * as path from "path";
|
|
29
|
+
import { watch } from "chokidar";
|
|
30
|
+
import { analyzeProject } from "./analyzer/index.js";
|
|
31
|
+
import { applyVibe as applyVibeTransform } from "./transformer/index.js";
|
|
32
|
+
import { getVibe, listVibes, isValidVibeId } from "./vibes/registry.js";
|
|
33
|
+
import { printAnalysisReport, printTransformationReport, printVibeList, validateTransformation, writeJSONReport, } from "./reporter/index.js";
|
|
34
|
+
import { listBackups, restoreBackup, readBackupManifest, formatAge, } from "./utils/backup.js";
|
|
35
|
+
import { checkContrast, computeContrastFixes, writeContrastOverrides, clearContrastOverrides, loadContrastOverrides, isCheckableColor, } from "./contrast/index.js";
|
|
36
|
+
// ─── ANSI helpers ─────────────────────────────────────────────────────────────
|
|
37
|
+
const RESET = "\x1b[0m";
|
|
38
|
+
const BOLD = "\x1b[1m";
|
|
39
|
+
const DIM = "\x1b[2m";
|
|
40
|
+
const GREEN = "\x1b[32m";
|
|
41
|
+
const YELLOW = "\x1b[33m";
|
|
42
|
+
const RED = "\x1b[31m";
|
|
43
|
+
const CYAN = "\x1b[36m";
|
|
44
|
+
const b = (s) => `${BOLD}${s}${RESET}`;
|
|
45
|
+
const d = (s) => `${DIM}${s}${RESET}`;
|
|
46
|
+
const g = (s) => `${GREEN}${s}${RESET}`;
|
|
47
|
+
const y = (s) => `${YELLOW}${s}${RESET}`;
|
|
48
|
+
const r = (s) => `${RED}${s}${RESET}`;
|
|
49
|
+
const c = (s) => `${CYAN}${s}${RESET}`;
|
|
50
|
+
function loadProjectConfig(projectPath) {
|
|
51
|
+
const configPath = path.join(path.resolve(projectPath), ".paintoliver.json");
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return {};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// ─── Interactive prompt ───────────────────────────────────────────────────────
|
|
60
|
+
function promptLine(question) {
|
|
61
|
+
return new Promise((resolve) => {
|
|
62
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
63
|
+
rl.question(question, (answer) => {
|
|
64
|
+
rl.close();
|
|
65
|
+
resolve(answer.trim().toLowerCase());
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
// ─── Contrast flow ────────────────────────────────────────────────────────────
|
|
70
|
+
function printContrastFailures(failures) {
|
|
71
|
+
console.log(`\n ${y(b("WCAG 2.2 AA — Contrast check:"))} ${r(failures.length + " failing pair(s)")}\n`);
|
|
72
|
+
for (const f of failures) {
|
|
73
|
+
const type = f.required === 4.5 ? d("4.5:1 text") : d("3.0:1 UI");
|
|
74
|
+
console.log(` ${y("·")} ${b(f.fgRole.padEnd(22))} on ${b(f.bgRole)}`);
|
|
75
|
+
console.log(` ${d(f.fgHex)} on ${d(f.bgHex)} ${r(f.ratio + ":1")} → needs ${c(f.required + ":1")} ${type} ${d(f.label)}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function printContrastOverrideResult(configPath, fixDetails, projectRoot) {
|
|
79
|
+
const relPath = path.relative(process.cwd(), configPath);
|
|
80
|
+
console.log(`\n ${g("✓")} WCAG 2.2 AA — ${fixDetails.length} override(s) applied\n`);
|
|
81
|
+
for (const fix of fixDetails) {
|
|
82
|
+
console.log(` ${g("·")} ${b(fix.role.padEnd(22))} ${d(fix.original)} → ${g(fix.fixed)} ` +
|
|
83
|
+
`${d(fix.ratioWas + ":1")} → ${g(fix.ratioNow + ":1")} ${d(fix.label)}`);
|
|
84
|
+
}
|
|
85
|
+
console.log(`\n ${b("Overrides saved to:")} ${c(relPath)} → ${c('"contrastOverrides"')}`);
|
|
86
|
+
console.log(` ${d("To revert: paintoliver clear-overrides " + path.relative(process.cwd(), projectRoot))}`);
|
|
87
|
+
console.log("");
|
|
88
|
+
}
|
|
89
|
+
async function runApply(vibeId, projectRoot, options, isReapply = false) {
|
|
90
|
+
const vibe = getVibe(vibeId);
|
|
91
|
+
const exclude = options.exclude
|
|
92
|
+
? options.exclude.split(",").map((p) => p.trim())
|
|
93
|
+
: [];
|
|
94
|
+
// Load contrast overrides persisted in .paintoliver.json
|
|
95
|
+
const contrastOverrides = loadContrastOverrides(projectRoot);
|
|
96
|
+
// Announce active overrides
|
|
97
|
+
if (!isReapply && Object.keys(contrastOverrides).length > 0) {
|
|
98
|
+
const n = Object.keys(contrastOverrides).length;
|
|
99
|
+
console.log(`\n ${c("⚡")} Contrast overrides active (${b(String(n))} token${n === 1 ? "" : "s"}) — ` +
|
|
100
|
+
`loaded from ${c(".paintoliver.json")}\n`);
|
|
101
|
+
}
|
|
102
|
+
const config = {
|
|
103
|
+
projectRoot,
|
|
104
|
+
vibeId,
|
|
105
|
+
dryRun: options.dryRun,
|
|
106
|
+
backup: options.backup && !isReapply, // no backup on watch re-applies
|
|
107
|
+
verbose: options.verbose,
|
|
108
|
+
injectFonts: options.fonts !== false,
|
|
109
|
+
exclude,
|
|
110
|
+
contrastOverrides,
|
|
111
|
+
watchMode: options.watch,
|
|
112
|
+
skipContrast: options.noContrast,
|
|
113
|
+
};
|
|
114
|
+
// Analyze
|
|
115
|
+
let analysis;
|
|
116
|
+
try {
|
|
117
|
+
analysis = await analyzeProject(projectRoot, exclude);
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
console.error(`\n ${r("Error")} during analysis: ${String(err)}\n`);
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
if (!isReapply) {
|
|
124
|
+
printAnalysisReport(analysis, vibe);
|
|
125
|
+
}
|
|
126
|
+
// Validate
|
|
127
|
+
const issues = validateTransformation(analysis, vibe);
|
|
128
|
+
const fatalIssues = issues.filter((i) => i.level === "error");
|
|
129
|
+
const warnings = issues.filter((i) => i.level === "warning");
|
|
130
|
+
if (warnings.length > 0) {
|
|
131
|
+
for (const w of warnings) {
|
|
132
|
+
console.log(` ${y("⚠")} ${w}`);
|
|
133
|
+
}
|
|
134
|
+
console.log("");
|
|
135
|
+
}
|
|
136
|
+
if (fatalIssues.length > 0) {
|
|
137
|
+
console.error(" Fatal issues prevent transformation from running:\n");
|
|
138
|
+
for (const e of fatalIssues) {
|
|
139
|
+
console.error(` ${r("✗")} ${e.message}`);
|
|
140
|
+
}
|
|
141
|
+
console.error("");
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
// Transform
|
|
145
|
+
let result;
|
|
146
|
+
try {
|
|
147
|
+
result = await applyVibeTransform(analysis, vibe, config);
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
console.error(`\n ${r("Error")} during transformation: ${String(err)}\n`);
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
printTransformationReport(result, options.verbose, options.dryRun);
|
|
154
|
+
// JSON report
|
|
155
|
+
if (options.report) {
|
|
156
|
+
const reportPath = path.resolve(options.report);
|
|
157
|
+
writeJSONReport(result, reportPath);
|
|
158
|
+
console.log(` Report written to: ${reportPath}\n`);
|
|
159
|
+
}
|
|
160
|
+
// ── WCAG Contrast Check ──────────────────────────────────────────────────────
|
|
161
|
+
if (!config.skipContrast && result.resolvedColors) {
|
|
162
|
+
const checkableColors = Object.fromEntries(Object.entries(result.resolvedColors).filter(([, v]) => isCheckableColor(v)));
|
|
163
|
+
const failures = checkContrast(checkableColors);
|
|
164
|
+
if (failures.length > 0) {
|
|
165
|
+
printContrastFailures(failures);
|
|
166
|
+
if (options.dryRun) {
|
|
167
|
+
// In dry-run: show what would be fixed, write nothing
|
|
168
|
+
const { fixDetails } = computeContrastFixes(failures, checkableColors);
|
|
169
|
+
console.log(`\n ${d("[DRY RUN]")} ${fixDetails.length} override(s) would be applied. ` +
|
|
170
|
+
`Run without ${d("--dry-run")} to apply.\n`);
|
|
171
|
+
}
|
|
172
|
+
else if (options.watch) {
|
|
173
|
+
// In watch mode: can't prompt interactively
|
|
174
|
+
console.log(`\n ${y("⚠")} Contrast failures detected. Run ${c("paintoliver apply " + vibeId + " . --fix-contrast")} ` +
|
|
175
|
+
`to auto-fix and save overrides.\n`);
|
|
176
|
+
}
|
|
177
|
+
else if (options.fixContrast) {
|
|
178
|
+
// --fix-contrast flag: auto-fix without prompting
|
|
179
|
+
const { overrides, fixDetails } = computeContrastFixes(failures, checkableColors);
|
|
180
|
+
const configPath = writeContrastOverrides(projectRoot, {
|
|
181
|
+
...contrastOverrides,
|
|
182
|
+
...overrides,
|
|
183
|
+
});
|
|
184
|
+
printContrastOverrideResult(configPath, fixDetails, projectRoot);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
// Interactive: prompt the developer
|
|
188
|
+
const answer = await promptLine(`\n ${b("Fix these contrast issues?")} The agent will pick the least-disruptive ` +
|
|
189
|
+
`adjustment and save it to ${c(".paintoliver.json")}.\n ${b("[y/N]")} `);
|
|
190
|
+
if (answer === "y" || answer === "yes") {
|
|
191
|
+
const { overrides, fixDetails } = computeContrastFixes(failures, checkableColors);
|
|
192
|
+
const configPath = writeContrastOverrides(projectRoot, {
|
|
193
|
+
...contrastOverrides,
|
|
194
|
+
...overrides,
|
|
195
|
+
});
|
|
196
|
+
printContrastOverrideResult(configPath, fixDetails, projectRoot);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
console.log(`\n ${d("Skipped. Run with --fix-contrast to apply automatically.")}\n`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
else if (!isReapply) {
|
|
204
|
+
console.log(` ${g("✓")} WCAG 2.2 AA — all contrast pairs pass.\n`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return result.success;
|
|
208
|
+
}
|
|
209
|
+
// ─── Watch mode ───────────────────────────────────────────────────────────────
|
|
210
|
+
async function watchProject(vibeId, projectRoot, options) {
|
|
211
|
+
const globs = [
|
|
212
|
+
path.join(projectRoot, "**/*.css"),
|
|
213
|
+
path.join(projectRoot, "**/*.scss"),
|
|
214
|
+
path.join(projectRoot, "**/*.sass"),
|
|
215
|
+
path.join(projectRoot, "tailwind.config.*"),
|
|
216
|
+
path.join(projectRoot, ".paintoliver.json"),
|
|
217
|
+
];
|
|
218
|
+
const ignored = [
|
|
219
|
+
/node_modules/,
|
|
220
|
+
/\.git/,
|
|
221
|
+
/dist\//,
|
|
222
|
+
/build\//,
|
|
223
|
+
/\.next\//,
|
|
224
|
+
/\.paintoliver-backup/,
|
|
225
|
+
];
|
|
226
|
+
console.log(`\n ${c("◉")} Watching ${b(path.relative(process.cwd(), projectRoot) || ".")} ` +
|
|
227
|
+
`for changes (${b(vibeId)} vibe)...\n`);
|
|
228
|
+
// Initial apply
|
|
229
|
+
await runApply(vibeId, projectRoot, { ...options, watch: true }, false);
|
|
230
|
+
let debounce = null;
|
|
231
|
+
const watcher = watch(globs, { ignored, ignoreInitial: true });
|
|
232
|
+
watcher.on("change", (changedPath) => {
|
|
233
|
+
console.log(`\n ${d("→")} Changed: ${path.relative(projectRoot, changedPath)}`);
|
|
234
|
+
if (debounce)
|
|
235
|
+
clearTimeout(debounce);
|
|
236
|
+
debounce = setTimeout(() => {
|
|
237
|
+
void runApply(vibeId, projectRoot, { ...options, watch: true }, true);
|
|
238
|
+
}, 350);
|
|
239
|
+
});
|
|
240
|
+
// Keep process alive
|
|
241
|
+
await new Promise((resolve) => {
|
|
242
|
+
process.on("SIGINT", () => {
|
|
243
|
+
watcher.close().finally(() => {
|
|
244
|
+
console.log(`\n ${d("Watch stopped.")}\n`);
|
|
245
|
+
resolve();
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
// ─── CLI Setup ────────────────────────────────────────────────────────────────
|
|
251
|
+
const program = new Command();
|
|
252
|
+
program
|
|
253
|
+
.name("paintoliver")
|
|
254
|
+
.description("Apply consistent visual vibes to front-end codebases — safely, predictably, and at scale.")
|
|
255
|
+
.version("0.1.0");
|
|
256
|
+
// ─── apply command ────────────────────────────────────────────────────────────
|
|
257
|
+
program
|
|
258
|
+
.command("apply [vibe-or-path] [project-path]")
|
|
259
|
+
.description("Apply a visual vibe to a project")
|
|
260
|
+
.option("--dry-run", "Preview changes without writing any files", false)
|
|
261
|
+
.option("--backup", "Create a backup before modifying files (default: on)", true)
|
|
262
|
+
.option("--no-backup", "Skip backup creation")
|
|
263
|
+
.option("--verbose", "Show detailed change information", false)
|
|
264
|
+
.option("--no-fonts", "Skip Google Fonts import injection")
|
|
265
|
+
.option("--watch", "Watch for file changes and re-apply automatically", false)
|
|
266
|
+
.option("--fix-contrast", "Automatically fix WCAG contrast failures without prompting", false)
|
|
267
|
+
.option("--no-contrast", "Skip the WCAG 2.2 AA contrast check")
|
|
268
|
+
.option("--report <path>", "Write a JSON transformation report to the given path")
|
|
269
|
+
.option("--exclude <patterns>", "Comma-separated glob patterns to exclude")
|
|
270
|
+
.action(async (firstArg, secondArg, options) => {
|
|
271
|
+
// Smart arg parsing: first arg may be a vibe ID or a project path
|
|
272
|
+
const isVibeArg = firstArg !== undefined && isValidVibeId(firstArg);
|
|
273
|
+
const vibeArg = isVibeArg ? firstArg : undefined;
|
|
274
|
+
const rawPath = isVibeArg ? (secondArg ?? ".") : (firstArg ?? ".");
|
|
275
|
+
const projectRoot = path.resolve(rawPath);
|
|
276
|
+
if (!fs.existsSync(projectRoot)) {
|
|
277
|
+
console.error(`\n ${r("Error:")} Project path does not exist: ${projectRoot}\n`);
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
// Load project config to resolve vibe from config file if not provided on CLI
|
|
281
|
+
const cfg = loadProjectConfig(projectRoot);
|
|
282
|
+
const resolvedVibeId = (vibeArg ?? cfg.vibe);
|
|
283
|
+
if (!resolvedVibeId || !isValidVibeId(resolvedVibeId)) {
|
|
284
|
+
console.error(`\n ${r("Error:")} No vibe specified. Pass a vibe ID or set "vibe" in .paintoliver.json\n`);
|
|
285
|
+
console.error(` Available vibes: ${listVibes().map((v) => v.meta.id).join(", ")}\n`);
|
|
286
|
+
process.exit(1);
|
|
287
|
+
}
|
|
288
|
+
const opts = {
|
|
289
|
+
dryRun: options.dryRun,
|
|
290
|
+
backup: options.backup,
|
|
291
|
+
verbose: options.verbose,
|
|
292
|
+
fonts: options.fonts,
|
|
293
|
+
report: options.report,
|
|
294
|
+
exclude: options.exclude,
|
|
295
|
+
watch: options.watch,
|
|
296
|
+
fixContrast: options.fixContrast,
|
|
297
|
+
noContrast: options.contrast === false, // --no-contrast sets contrast=false
|
|
298
|
+
};
|
|
299
|
+
if (opts.watch) {
|
|
300
|
+
await watchProject(resolvedVibeId, projectRoot, opts);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
const success = await runApply(resolvedVibeId, projectRoot, opts);
|
|
304
|
+
process.exit(success ? 0 : 1);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
// ─── analyze command ──────────────────────────────────────────────────────────
|
|
308
|
+
program
|
|
309
|
+
.command("analyze [project-path]")
|
|
310
|
+
.description("Analyze a project's styling without making any changes")
|
|
311
|
+
.option("--json", "Output analysis as JSON", false)
|
|
312
|
+
.option("--exclude <patterns>", "Comma-separated glob patterns to exclude")
|
|
313
|
+
.action(async (projectPathArg, options) => {
|
|
314
|
+
const rawPath = projectPathArg ?? ".";
|
|
315
|
+
const projectRoot = path.resolve(rawPath);
|
|
316
|
+
if (!fs.existsSync(projectRoot)) {
|
|
317
|
+
console.error(`\n ${r("Error:")} Path does not exist: ${projectRoot}\n`);
|
|
318
|
+
process.exit(1);
|
|
319
|
+
}
|
|
320
|
+
const exclude = options.exclude
|
|
321
|
+
? options.exclude.split(",").map((p) => p.trim())
|
|
322
|
+
: [];
|
|
323
|
+
let analysis;
|
|
324
|
+
try {
|
|
325
|
+
analysis = await analyzeProject(projectRoot, exclude);
|
|
326
|
+
}
|
|
327
|
+
catch (err) {
|
|
328
|
+
console.error(`\n ${r("Error:")} ${String(err)}\n`);
|
|
329
|
+
process.exit(1);
|
|
330
|
+
}
|
|
331
|
+
if (options.json) {
|
|
332
|
+
console.log(JSON.stringify(analysis, null, 2));
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const { framework, stylingSystem, relevantFiles, detectedCSSVars, warnings } = analysis;
|
|
336
|
+
console.log("");
|
|
337
|
+
console.log(` ${b("Project Analysis")}`);
|
|
338
|
+
console.log(" ─────────────────────────────────────────");
|
|
339
|
+
console.log(` ${d("Path:")} ${projectRoot}`);
|
|
340
|
+
console.log(` ${d("Framework:")} ${framework}`);
|
|
341
|
+
console.log(` ${d("Styling system:")} ${stylingSystem}`);
|
|
342
|
+
console.log(` ${d("CSS entry points:")} ${analysis.cssEntryPoints.length}`);
|
|
343
|
+
console.log(` ${d("CSS variables:")} ${detectedCSSVars.length}`);
|
|
344
|
+
console.log(` ${d("Relevant files:")} ${relevantFiles.length}`);
|
|
345
|
+
console.log(` ${d("Theme mode:")} ${analysis.themeMode}`);
|
|
346
|
+
console.log(` ${d("Has token file:")} ${analysis.hasTokenFile}`);
|
|
347
|
+
if (detectedCSSVars.length > 0) {
|
|
348
|
+
console.log("");
|
|
349
|
+
console.log(` ${b("Detected CSS variables:")}`);
|
|
350
|
+
for (const v of detectedCSSVars.slice(0, 20)) {
|
|
351
|
+
console.log(` ${d(v)}`);
|
|
352
|
+
}
|
|
353
|
+
if (detectedCSSVars.length > 20) {
|
|
354
|
+
console.log(` ${d("... and " + (detectedCSSVars.length - 20) + " more")}`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (warnings.length > 0) {
|
|
358
|
+
console.log("");
|
|
359
|
+
console.log(` ${y(b("Warnings:"))}`);
|
|
360
|
+
for (const w of warnings) {
|
|
361
|
+
console.log(` ${y("⚠")} ${w}`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
console.log("");
|
|
365
|
+
});
|
|
366
|
+
// ─── list command ─────────────────────────────────────────────────────────────
|
|
367
|
+
program
|
|
368
|
+
.command("list")
|
|
369
|
+
.description("List all available vibes")
|
|
370
|
+
.action(() => {
|
|
371
|
+
printVibeList(listVibes());
|
|
372
|
+
});
|
|
373
|
+
// ─── list-backups command ─────────────────────────────────────────────────────
|
|
374
|
+
program
|
|
375
|
+
.command("list-backups [project-path]")
|
|
376
|
+
.description("Show all available backups for a project")
|
|
377
|
+
.action((projectPathArg) => {
|
|
378
|
+
const rawPath = projectPathArg ?? ".";
|
|
379
|
+
const projectRoot = path.resolve(rawPath);
|
|
380
|
+
const backups = listBackups(projectRoot);
|
|
381
|
+
if (backups.length === 0) {
|
|
382
|
+
console.log(`\n ${d("No backups found for:")} ${projectRoot}\n`);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
console.log(`\n ${b("Backups for")} ${c(path.relative(process.cwd(), projectRoot) || ".")}\n`);
|
|
386
|
+
for (const id of backups) {
|
|
387
|
+
const manifest = readBackupManifest(projectRoot, id);
|
|
388
|
+
const age = formatAge(id);
|
|
389
|
+
const fileCount = manifest?.files.length ?? "?";
|
|
390
|
+
console.log(` ${d("·")} ${b(id.padEnd(25))} ${y(age.padEnd(10))} ${d(fileCount + " file(s)")}`);
|
|
391
|
+
}
|
|
392
|
+
console.log(`\n ${d("To restore:")} ${c("paintoliver restore [path] --backup-id <id>")}\n`);
|
|
393
|
+
});
|
|
394
|
+
// ─── restore command ──────────────────────────────────────────────────────────
|
|
395
|
+
program
|
|
396
|
+
.command("restore [project-path]")
|
|
397
|
+
.description("Restore files from the most recent backup")
|
|
398
|
+
.option("--backup-id <id>", "Specific backup timestamp to restore (default: most recent)")
|
|
399
|
+
.action(async (projectPathArg, options) => {
|
|
400
|
+
const rawPath = projectPathArg ?? ".";
|
|
401
|
+
const projectRoot = path.resolve(rawPath);
|
|
402
|
+
const backups = listBackups(projectRoot);
|
|
403
|
+
if (backups.length === 0) {
|
|
404
|
+
console.error(`\n ${r("No backups found for:")} ${projectRoot}\n`);
|
|
405
|
+
process.exit(1);
|
|
406
|
+
}
|
|
407
|
+
const targetBackup = options.backupId ?? backups[0]; // newest first
|
|
408
|
+
try {
|
|
409
|
+
restoreBackup(projectRoot, targetBackup);
|
|
410
|
+
console.log(`\n ${g("✓")} Restored from backup: ${b(targetBackup)}\n`);
|
|
411
|
+
}
|
|
412
|
+
catch (err) {
|
|
413
|
+
console.error(`\n ${r("✗")} Restore failed: ${String(err)}\n`);
|
|
414
|
+
process.exit(1);
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
// ─── clear-overrides command ──────────────────────────────────────────────────
|
|
418
|
+
program
|
|
419
|
+
.command("clear-overrides [project-path]")
|
|
420
|
+
.description("Remove saved WCAG contrast overrides from .paintoliver.json")
|
|
421
|
+
.action((projectPathArg) => {
|
|
422
|
+
const rawPath = projectPathArg ?? ".";
|
|
423
|
+
const projectRoot = path.resolve(rawPath);
|
|
424
|
+
const result = clearContrastOverrides(projectRoot);
|
|
425
|
+
if (result === null) {
|
|
426
|
+
console.log(`\n ${d("No contrast overrides found in")} ${c(".paintoliver.json")}\n`);
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
const relPath = path.relative(process.cwd(), result);
|
|
430
|
+
console.log(`\n ${g("✓")} Contrast overrides removed from ${c(relPath)}. ` +
|
|
431
|
+
`The vibe's original colors will be used on the next run.\n`);
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
// ─── Parse ────────────────────────────────────────────────────────────────────
|
|
435
|
+
program.parse(process.argv);
|
|
436
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WCAG 2.2 Contrast Engine
|
|
3
|
+
*
|
|
4
|
+
* Checks semantic color pairs against WCAG 2.2 AA thresholds:
|
|
5
|
+
* - 4.5:1 for normal text
|
|
6
|
+
* - 3.0:1 for UI components and large text
|
|
7
|
+
*
|
|
8
|
+
* When failures are found, the engine computes the least-disruptive fix —
|
|
9
|
+
* adjusting lightness (binary search, 24 iterations) on whichever side of
|
|
10
|
+
* the pair requires the smallest change.
|
|
11
|
+
*
|
|
12
|
+
* Surface roles (background, card, muted, etc.) get a 0.15 lightness bias
|
|
13
|
+
* against being modified, to avoid ripple effects across multiple pairs.
|
|
14
|
+
*
|
|
15
|
+
* Fixes are persisted in .paintoliver.json under `contrastOverrides`
|
|
16
|
+
* and merged at the start of every subsequent run.
|
|
17
|
+
*/
|
|
18
|
+
import type { SemanticColors } from "../vibes/types.js";
|
|
19
|
+
export interface ContrastFailure {
|
|
20
|
+
fgRole: string;
|
|
21
|
+
bgRole: string;
|
|
22
|
+
fgHex: string;
|
|
23
|
+
bgHex: string;
|
|
24
|
+
ratio: number;
|
|
25
|
+
required: number;
|
|
26
|
+
label: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ContrastFix {
|
|
29
|
+
role: string;
|
|
30
|
+
original: string;
|
|
31
|
+
fixed: string;
|
|
32
|
+
fgRole: string;
|
|
33
|
+
bgRole: string;
|
|
34
|
+
ratioWas: number;
|
|
35
|
+
ratioNow: number;
|
|
36
|
+
label: string;
|
|
37
|
+
}
|
|
38
|
+
/** Only hex colors (#rrggbb, #rgb) can be checked — skip rgba/hsl/etc. */
|
|
39
|
+
export declare function isCheckableColor(str: string): boolean;
|
|
40
|
+
export declare function contrastRatio(hex1: string, hex2: string): number;
|
|
41
|
+
/**
|
|
42
|
+
* Binary-search the minimum lightness adjustment needed to make colorHex
|
|
43
|
+
* contrast against bgHex at targetRatio.
|
|
44
|
+
* Returns adjusted hex, or null if the ratio is impossible to achieve.
|
|
45
|
+
*/
|
|
46
|
+
export declare function nudgeToContrast(colorHex: string, bgHex: string, targetRatio: number): string | null;
|
|
47
|
+
/**
|
|
48
|
+
* For a failing contrast pair, find which side (fg or bg) needs the least
|
|
49
|
+
* lightness change, biasing against modifying surface roles.
|
|
50
|
+
*/
|
|
51
|
+
export declare function leastDisruptiveFix(fgRole: string, fgHex: string, bgRole: string, bgHex: string, targetRatio: number): {
|
|
52
|
+
role: string;
|
|
53
|
+
original: string;
|
|
54
|
+
fixed: string;
|
|
55
|
+
} | null;
|
|
56
|
+
/**
|
|
57
|
+
* Check a resolved color set against all WCAG 2.2 AA contrast pairs.
|
|
58
|
+
* Returns an array of failures (empty = all pass).
|
|
59
|
+
*/
|
|
60
|
+
export declare function checkContrast(colors: Record<string, string>): ContrastFailure[];
|
|
61
|
+
/**
|
|
62
|
+
* Compute the minimum color fixes needed to make all failures pass.
|
|
63
|
+
* Returns overrides (role → fixedHex) and per-fix details for reporting.
|
|
64
|
+
*/
|
|
65
|
+
export declare function computeContrastFixes(failures: ContrastFailure[], colors: Record<string, string>): {
|
|
66
|
+
overrides: Record<string, string>;
|
|
67
|
+
fixDetails: ContrastFix[];
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Write (or merge) contrastOverrides into the project's .paintoliver.json.
|
|
71
|
+
* Returns the path that was written.
|
|
72
|
+
*/
|
|
73
|
+
export declare function writeContrastOverrides(projectPath: string, overrides: Record<string, string>): string;
|
|
74
|
+
/**
|
|
75
|
+
* Remove the contrastOverrides block from .paintoliver.json.
|
|
76
|
+
* Returns the config path, or null if there was nothing to clear.
|
|
77
|
+
*/
|
|
78
|
+
export declare function clearContrastOverrides(projectPath: string): string | null;
|
|
79
|
+
/**
|
|
80
|
+
* Load contrastOverrides from the project's .paintoliver.json.
|
|
81
|
+
* Returns empty object if no config or no overrides block.
|
|
82
|
+
*/
|
|
83
|
+
export declare function loadContrastOverrides(projectPath: string): Record<string, string>;
|
|
84
|
+
/**
|
|
85
|
+
* Resolve the final color map by merging base vibe colors with contrastOverrides.
|
|
86
|
+
*/
|
|
87
|
+
export declare function resolveColors(baseColors: SemanticColors, contrastOverrides: Record<string, string>): Record<string, string>;
|
|
88
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contrast/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAIxD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAOD,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAIrD;AA8BD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIhE;AA0CD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CA6Bf;AAqBD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAkB1D;AA4BD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,eAAe,EAAE,CAoB/E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,eAAe,EAAE,EAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B;IAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,UAAU,EAAE,WAAW,EAAE,CAAA;CAAE,CA4BlE;AAID;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,CAcR;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYzE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWjF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,cAAc,EAC1B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACxC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAExB"}
|