@versini/ui-styles 8.5.0 → 9.0.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.
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const DEFAULT_EXTENSIONS = ["js", "jsx", "ts", "tsx"];
|
|
4
|
+
const DEFAULT_IGNORE = [
|
|
5
|
+
"node_modules",
|
|
6
|
+
"dist",
|
|
7
|
+
"build",
|
|
8
|
+
".git",
|
|
9
|
+
"coverage",
|
|
10
|
+
".next",
|
|
11
|
+
".rslib",
|
|
12
|
+
"tmp",
|
|
13
|
+
"__tests__"
|
|
14
|
+
];
|
|
15
|
+
const EXCLUDED_FILE_PATTERNS = [
|
|
16
|
+
/\.stories\.[jt]sx?$/,
|
|
17
|
+
/\.test\.[jt]sx?$/,
|
|
18
|
+
/\.spec\.[jt]sx?$/
|
|
19
|
+
];
|
|
20
|
+
function shouldIgnore(filePath, ignorePatterns) {
|
|
21
|
+
const parts = filePath.split(path.sep);
|
|
22
|
+
return parts.some((part) => ignorePatterns.includes(part));
|
|
23
|
+
}
|
|
24
|
+
function hasAllowedExtension(filePath, extensions) {
|
|
25
|
+
const ext = path.extname(filePath).slice(1).toLowerCase();
|
|
26
|
+
return extensions.includes(ext);
|
|
27
|
+
}
|
|
28
|
+
function isExcludedFile(fileName) {
|
|
29
|
+
return EXCLUDED_FILE_PATTERNS.some((pattern) => pattern.test(fileName));
|
|
30
|
+
}
|
|
31
|
+
function scanDirectory(dirPath, rootPath, options, results) {
|
|
32
|
+
let entries;
|
|
33
|
+
try {
|
|
34
|
+
entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
35
|
+
} catch {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
40
|
+
const relativePath = path.relative(rootPath, fullPath);
|
|
41
|
+
if (shouldIgnore(relativePath, options.ignore)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (entry.isDirectory()) {
|
|
45
|
+
scanDirectory(fullPath, rootPath, options, results);
|
|
46
|
+
} else if (entry.isFile() && hasAllowedExtension(entry.name, options.extensions) && !isExcludedFile(entry.name)) {
|
|
47
|
+
try {
|
|
48
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
49
|
+
results.push({
|
|
50
|
+
absolutePath: fullPath,
|
|
51
|
+
relativePath,
|
|
52
|
+
content
|
|
53
|
+
});
|
|
54
|
+
} catch {
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function scanFiles(targetPath, options) {
|
|
60
|
+
const resolvedPath = path.resolve(targetPath);
|
|
61
|
+
const fullOptions = {
|
|
62
|
+
extensions: options?.extensions || DEFAULT_EXTENSIONS,
|
|
63
|
+
ignore: options?.ignore || DEFAULT_IGNORE
|
|
64
|
+
};
|
|
65
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
66
|
+
throw new Error(`Path does not exist: ${resolvedPath}`);
|
|
67
|
+
}
|
|
68
|
+
const stats = fs.statSync(resolvedPath);
|
|
69
|
+
const results = [];
|
|
70
|
+
if (stats.isFile()) {
|
|
71
|
+
if (hasAllowedExtension(resolvedPath, fullOptions.extensions)) {
|
|
72
|
+
const content = fs.readFileSync(resolvedPath, "utf-8");
|
|
73
|
+
results.push({
|
|
74
|
+
absolutePath: resolvedPath,
|
|
75
|
+
relativePath: path.basename(resolvedPath),
|
|
76
|
+
content
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
} else if (stats.isDirectory()) {
|
|
80
|
+
scanDirectory(resolvedPath, resolvedPath, fullOptions, results);
|
|
81
|
+
}
|
|
82
|
+
return results;
|
|
83
|
+
}
|
|
84
|
+
function getDefaultScanOptions() {
|
|
85
|
+
return {
|
|
86
|
+
extensions: [...DEFAULT_EXTENSIONS],
|
|
87
|
+
ignore: [...DEFAULT_IGNORE]
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export {
|
|
91
|
+
getDefaultScanOptions as g,
|
|
92
|
+
scanFiles as s
|
|
93
|
+
};
|
package/dist/cli/ui-doctor.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import { s as scanFiles, g as getDefaultScanOptions } from "./assets/fileScanner-Cis4RFj5.js";
|
|
3
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
4
|
+
import { dirname, resolve } from "node:path";
|
|
4
5
|
import { fileURLToPath } from "node:url";
|
|
5
6
|
const TAILWIND_COLOR_PALETTES = [
|
|
6
7
|
"red",
|
|
@@ -106,93 +107,6 @@ function findColorClasses(content) {
|
|
|
106
107
|
}
|
|
107
108
|
return allMatches;
|
|
108
109
|
}
|
|
109
|
-
const DEFAULT_EXTENSIONS = ["js", "jsx", "ts", "tsx"];
|
|
110
|
-
const DEFAULT_IGNORE = [
|
|
111
|
-
"node_modules",
|
|
112
|
-
"dist",
|
|
113
|
-
"build",
|
|
114
|
-
".git",
|
|
115
|
-
"coverage",
|
|
116
|
-
".next",
|
|
117
|
-
".rslib",
|
|
118
|
-
"tmp",
|
|
119
|
-
"__tests__"
|
|
120
|
-
];
|
|
121
|
-
const EXCLUDED_FILE_PATTERNS = [
|
|
122
|
-
/\.stories\.[jt]sx?$/,
|
|
123
|
-
/\.test\.[jt]sx?$/,
|
|
124
|
-
/\.spec\.[jt]sx?$/
|
|
125
|
-
];
|
|
126
|
-
function shouldIgnore(filePath, ignorePatterns) {
|
|
127
|
-
const parts = filePath.split(path.sep);
|
|
128
|
-
return parts.some((part) => ignorePatterns.includes(part));
|
|
129
|
-
}
|
|
130
|
-
function hasAllowedExtension(filePath, extensions) {
|
|
131
|
-
const ext = path.extname(filePath).slice(1).toLowerCase();
|
|
132
|
-
return extensions.includes(ext);
|
|
133
|
-
}
|
|
134
|
-
function isExcludedFile(fileName) {
|
|
135
|
-
return EXCLUDED_FILE_PATTERNS.some((pattern) => pattern.test(fileName));
|
|
136
|
-
}
|
|
137
|
-
function scanDirectory(dirPath, rootPath, options, results) {
|
|
138
|
-
let entries;
|
|
139
|
-
try {
|
|
140
|
-
entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
141
|
-
} catch {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
for (const entry of entries) {
|
|
145
|
-
const fullPath = path.join(dirPath, entry.name);
|
|
146
|
-
const relativePath = path.relative(rootPath, fullPath);
|
|
147
|
-
if (shouldIgnore(relativePath, options.ignore)) {
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
if (entry.isDirectory()) {
|
|
151
|
-
scanDirectory(fullPath, rootPath, options, results);
|
|
152
|
-
} else if (entry.isFile() && hasAllowedExtension(entry.name, options.extensions) && !isExcludedFile(entry.name)) {
|
|
153
|
-
try {
|
|
154
|
-
const content = fs.readFileSync(fullPath, "utf-8");
|
|
155
|
-
results.push({
|
|
156
|
-
absolutePath: fullPath,
|
|
157
|
-
relativePath,
|
|
158
|
-
content
|
|
159
|
-
});
|
|
160
|
-
} catch {
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
function scanFiles(targetPath, options) {
|
|
166
|
-
const resolvedPath = path.resolve(targetPath);
|
|
167
|
-
const fullOptions = {
|
|
168
|
-
extensions: options?.extensions || DEFAULT_EXTENSIONS,
|
|
169
|
-
ignore: options?.ignore || DEFAULT_IGNORE
|
|
170
|
-
};
|
|
171
|
-
if (!fs.existsSync(resolvedPath)) {
|
|
172
|
-
throw new Error(`Path does not exist: ${resolvedPath}`);
|
|
173
|
-
}
|
|
174
|
-
const stats = fs.statSync(resolvedPath);
|
|
175
|
-
const results = [];
|
|
176
|
-
if (stats.isFile()) {
|
|
177
|
-
if (hasAllowedExtension(resolvedPath, fullOptions.extensions)) {
|
|
178
|
-
const content = fs.readFileSync(resolvedPath, "utf-8");
|
|
179
|
-
results.push({
|
|
180
|
-
absolutePath: resolvedPath,
|
|
181
|
-
relativePath: path.basename(resolvedPath),
|
|
182
|
-
content
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
} else if (stats.isDirectory()) {
|
|
186
|
-
scanDirectory(resolvedPath, resolvedPath, fullOptions, results);
|
|
187
|
-
}
|
|
188
|
-
return results;
|
|
189
|
-
}
|
|
190
|
-
function getDefaultScanOptions() {
|
|
191
|
-
return {
|
|
192
|
-
extensions: [...DEFAULT_EXTENSIONS],
|
|
193
|
-
ignore: [...DEFAULT_IGNORE]
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
110
|
const colors = {
|
|
197
111
|
reset: "\x1B[0m",
|
|
198
112
|
bright: "\x1B[1m",
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { s as scanFiles, g as getDefaultScanOptions } from "./assets/fileScanner-Cis4RFj5.js";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import "node:path";
|
|
5
|
+
const PROSE_ELEMENT_MODIFIERS = [
|
|
6
|
+
"headings",
|
|
7
|
+
"h1",
|
|
8
|
+
"h2",
|
|
9
|
+
"h3",
|
|
10
|
+
"h4",
|
|
11
|
+
"h5",
|
|
12
|
+
"h6",
|
|
13
|
+
"p",
|
|
14
|
+
"a",
|
|
15
|
+
"blockquote",
|
|
16
|
+
"figure",
|
|
17
|
+
"figcaption",
|
|
18
|
+
"strong",
|
|
19
|
+
"em",
|
|
20
|
+
"kbd",
|
|
21
|
+
"code",
|
|
22
|
+
"pre",
|
|
23
|
+
"ol",
|
|
24
|
+
"ul",
|
|
25
|
+
"li",
|
|
26
|
+
"table",
|
|
27
|
+
"thead",
|
|
28
|
+
"tr",
|
|
29
|
+
"th",
|
|
30
|
+
"td",
|
|
31
|
+
"img",
|
|
32
|
+
"video",
|
|
33
|
+
"hr",
|
|
34
|
+
"lead"
|
|
35
|
+
];
|
|
36
|
+
function migrateContent(content) {
|
|
37
|
+
const matches = [];
|
|
38
|
+
let migratedContent = content;
|
|
39
|
+
const lines = content.split("\n");
|
|
40
|
+
const processedLines = [];
|
|
41
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
42
|
+
let line = lines[lineIndex];
|
|
43
|
+
const lineNumber = lineIndex + 1;
|
|
44
|
+
line = replaceWithTracking(
|
|
45
|
+
line,
|
|
46
|
+
/--tw-prose-/g,
|
|
47
|
+
"--tw-plume-",
|
|
48
|
+
lineNumber,
|
|
49
|
+
matches
|
|
50
|
+
);
|
|
51
|
+
line = replaceWithTracking(
|
|
52
|
+
line,
|
|
53
|
+
/\bnot-prose\b/g,
|
|
54
|
+
"not-plume",
|
|
55
|
+
lineNumber,
|
|
56
|
+
matches
|
|
57
|
+
);
|
|
58
|
+
for (const modifier of PROSE_ELEMENT_MODIFIERS) {
|
|
59
|
+
const pattern = new RegExp(`\\bprose-${modifier}:`, "g");
|
|
60
|
+
line = replaceWithTracking(
|
|
61
|
+
line,
|
|
62
|
+
pattern,
|
|
63
|
+
`plume-${modifier}:`,
|
|
64
|
+
lineNumber,
|
|
65
|
+
matches
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
line = replaceWithTracking(
|
|
69
|
+
line,
|
|
70
|
+
/\bprose-dark\b/g,
|
|
71
|
+
"plume-dark",
|
|
72
|
+
lineNumber,
|
|
73
|
+
matches
|
|
74
|
+
);
|
|
75
|
+
line = replaceWithTracking(
|
|
76
|
+
line,
|
|
77
|
+
/\bprose-lighter\b/g,
|
|
78
|
+
"plume-lighter",
|
|
79
|
+
lineNumber,
|
|
80
|
+
matches
|
|
81
|
+
);
|
|
82
|
+
line = replaceWithTracking(
|
|
83
|
+
line,
|
|
84
|
+
/\bprose-light\b/g,
|
|
85
|
+
"plume-light",
|
|
86
|
+
lineNumber,
|
|
87
|
+
matches
|
|
88
|
+
);
|
|
89
|
+
line = replaceWithTracking(
|
|
90
|
+
line,
|
|
91
|
+
/(?<![-\w])prose(?!-\w)/g,
|
|
92
|
+
"plume",
|
|
93
|
+
lineNumber,
|
|
94
|
+
matches
|
|
95
|
+
);
|
|
96
|
+
processedLines.push(line);
|
|
97
|
+
}
|
|
98
|
+
migratedContent = processedLines.join("\n");
|
|
99
|
+
return {
|
|
100
|
+
originalContent: content,
|
|
101
|
+
migratedContent,
|
|
102
|
+
matches,
|
|
103
|
+
hasChanges: matches.length > 0
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function replaceWithTracking(line, pattern, replacement, lineNumber, matches) {
|
|
107
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
108
|
+
let match = regex.exec(line);
|
|
109
|
+
while (match !== null) {
|
|
110
|
+
matches.push({
|
|
111
|
+
original: match[0],
|
|
112
|
+
replacement,
|
|
113
|
+
line: lineNumber,
|
|
114
|
+
column: match.index + 1
|
|
115
|
+
});
|
|
116
|
+
match = regex.exec(line);
|
|
117
|
+
}
|
|
118
|
+
const result = line.replace(pattern, replacement);
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
function migrateFile(filePath) {
|
|
122
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
123
|
+
const result = migrateContent(content);
|
|
124
|
+
return {
|
|
125
|
+
...result,
|
|
126
|
+
filePath
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function migrateFileInPlace(filePath) {
|
|
130
|
+
const result = migrateFile(filePath);
|
|
131
|
+
if (result.hasChanges) {
|
|
132
|
+
fs.writeFileSync(filePath, result.migratedContent, "utf-8");
|
|
133
|
+
}
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
function needsMigration(content) {
|
|
137
|
+
const patterns = [
|
|
138
|
+
/--tw-prose-/,
|
|
139
|
+
/\bnot-prose\b/,
|
|
140
|
+
/\bprose-dark\b/,
|
|
141
|
+
/\bprose-light\b/,
|
|
142
|
+
/\bprose-lighter\b/,
|
|
143
|
+
/(?<![-\w])prose(?!-\w)/
|
|
144
|
+
];
|
|
145
|
+
for (const modifier of PROSE_ELEMENT_MODIFIERS) {
|
|
146
|
+
patterns.push(new RegExp(`\\bprose-${modifier}:`));
|
|
147
|
+
}
|
|
148
|
+
return patterns.some((pattern) => pattern.test(content));
|
|
149
|
+
}
|
|
150
|
+
const VERSION = "1.0.0";
|
|
151
|
+
const colors = {
|
|
152
|
+
reset: "\x1B[0m",
|
|
153
|
+
bright: "\x1B[1m",
|
|
154
|
+
dim: "\x1B[2m",
|
|
155
|
+
red: "\x1B[31m",
|
|
156
|
+
green: "\x1B[32m",
|
|
157
|
+
yellow: "\x1B[33m",
|
|
158
|
+
cyan: "\x1B[36m"
|
|
159
|
+
};
|
|
160
|
+
function parseArgs(args) {
|
|
161
|
+
const defaults = getDefaultScanOptions();
|
|
162
|
+
const options = {
|
|
163
|
+
path: ".",
|
|
164
|
+
extensions: [...defaults.extensions, "mdx", "md", "jsx"],
|
|
165
|
+
ignore: defaults.ignore,
|
|
166
|
+
dryRun: false,
|
|
167
|
+
help: false,
|
|
168
|
+
version: false
|
|
169
|
+
};
|
|
170
|
+
let i = 0;
|
|
171
|
+
while (i < args.length) {
|
|
172
|
+
const arg = args[i];
|
|
173
|
+
switch (arg) {
|
|
174
|
+
case "-h":
|
|
175
|
+
case "--help":
|
|
176
|
+
options.help = true;
|
|
177
|
+
break;
|
|
178
|
+
case "-v":
|
|
179
|
+
case "--version":
|
|
180
|
+
options.version = true;
|
|
181
|
+
break;
|
|
182
|
+
case "--dry-run":
|
|
183
|
+
options.dryRun = true;
|
|
184
|
+
break;
|
|
185
|
+
case "-p":
|
|
186
|
+
case "--path":
|
|
187
|
+
i++;
|
|
188
|
+
if (i < args.length) {
|
|
189
|
+
options.path = args[i];
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
case "-e":
|
|
193
|
+
case "--extensions":
|
|
194
|
+
i++;
|
|
195
|
+
if (i < args.length) {
|
|
196
|
+
options.extensions = args[i].split(",").map((e) => e.trim());
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
case "-i":
|
|
200
|
+
case "--ignore":
|
|
201
|
+
i++;
|
|
202
|
+
if (i < args.length) {
|
|
203
|
+
options.ignore = args[i].split(",").map((p) => p.trim());
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
206
|
+
default:
|
|
207
|
+
if (!arg.startsWith("-")) {
|
|
208
|
+
options.path = arg;
|
|
209
|
+
}
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
i++;
|
|
213
|
+
}
|
|
214
|
+
return options;
|
|
215
|
+
}
|
|
216
|
+
function printHelp() {
|
|
217
|
+
console.log(`
|
|
218
|
+
${colors.cyan}${colors.bright}ui-plume-migrate${colors.reset} v${VERSION}
|
|
219
|
+
|
|
220
|
+
A CLI tool to migrate from "prose" to "plume" typography prefix.
|
|
221
|
+
|
|
222
|
+
This tool automatically replaces all prose patterns with plume patterns:
|
|
223
|
+
- CSS variables: --tw-prose-* → --tw-plume-*
|
|
224
|
+
- Base class: prose → plume
|
|
225
|
+
- Color variants: prose-dark, prose-light, prose-lighter → plume-*
|
|
226
|
+
- Not-prose: not-prose → not-plume
|
|
227
|
+
- Element variants: prose-h1:, prose-p:, etc. → plume-*:
|
|
228
|
+
|
|
229
|
+
${colors.bright}Usage:${colors.reset}
|
|
230
|
+
ui-plume-migrate [path] [options]
|
|
231
|
+
|
|
232
|
+
${colors.bright}Arguments:${colors.reset}
|
|
233
|
+
path Path to scan (default: current directory)
|
|
234
|
+
|
|
235
|
+
${colors.bright}Options:${colors.reset}
|
|
236
|
+
-p, --path <path> Path to scan (alternative to positional argument)
|
|
237
|
+
-e, --extensions <ext> Comma-separated file extensions
|
|
238
|
+
(default: js,jsx,ts,tsx,mdx,md)
|
|
239
|
+
-i, --ignore <patterns> Comma-separated patterns to ignore
|
|
240
|
+
(default: node_modules,dist,build,.git)
|
|
241
|
+
--dry-run Show what would change without making modifications
|
|
242
|
+
-h, --help Show this help message
|
|
243
|
+
-v, --version Show version number
|
|
244
|
+
|
|
245
|
+
${colors.bright}Examples:${colors.reset}
|
|
246
|
+
ui-plume-migrate Migrate current directory
|
|
247
|
+
ui-plume-migrate ./src Migrate the src directory
|
|
248
|
+
ui-plume-migrate ./src --dry-run Preview changes without modifying files
|
|
249
|
+
ui-plume-migrate -e tsx,ts Only process TypeScript files
|
|
250
|
+
`);
|
|
251
|
+
}
|
|
252
|
+
function printVersion() {
|
|
253
|
+
console.log(`ui-plume-migrate v${VERSION}`);
|
|
254
|
+
}
|
|
255
|
+
function printResults(results, dryRun, duration) {
|
|
256
|
+
const filesWithChanges = results.filter((r) => r.hasChanges);
|
|
257
|
+
const totalMatches = filesWithChanges.reduce(
|
|
258
|
+
(sum, r) => sum + r.matches.length,
|
|
259
|
+
0
|
|
260
|
+
);
|
|
261
|
+
console.log("");
|
|
262
|
+
if (filesWithChanges.length === 0) {
|
|
263
|
+
console.log(
|
|
264
|
+
`${colors.green}✓${colors.reset} No prose patterns found that need migration!`
|
|
265
|
+
);
|
|
266
|
+
console.log(
|
|
267
|
+
`${colors.dim} Scanned ${results.length} files in ${duration}ms${colors.reset}`
|
|
268
|
+
);
|
|
269
|
+
console.log("");
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const actionWord = dryRun ? "Would migrate" : "Migrated";
|
|
273
|
+
for (const result of filesWithChanges) {
|
|
274
|
+
console.log(
|
|
275
|
+
`${colors.cyan}${result.filePath}${colors.reset} (${result.matches.length} changes)`
|
|
276
|
+
);
|
|
277
|
+
const matchesByType = /* @__PURE__ */ new Map();
|
|
278
|
+
for (const match of result.matches) {
|
|
279
|
+
const key = `${match.original} → ${match.replacement}`;
|
|
280
|
+
matchesByType.set(key, (matchesByType.get(key) || 0) + 1);
|
|
281
|
+
}
|
|
282
|
+
for (const [change, count] of matchesByType) {
|
|
283
|
+
console.log(
|
|
284
|
+
` ${colors.dim}${change}${colors.reset} ${colors.yellow}(${count}x)${colors.reset}`
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
console.log("");
|
|
288
|
+
}
|
|
289
|
+
console.log(`${colors.dim}${"─".repeat(50)}${colors.reset}`);
|
|
290
|
+
const fileWord = filesWithChanges.length === 1 ? "file" : "files";
|
|
291
|
+
const changeWord = totalMatches === 1 ? "change" : "changes";
|
|
292
|
+
if (dryRun) {
|
|
293
|
+
console.log(
|
|
294
|
+
`${colors.yellow}${colors.bright}Dry run:${colors.reset} ${totalMatches} ${changeWord} in ${filesWithChanges.length} ${fileWord} would be made`
|
|
295
|
+
);
|
|
296
|
+
console.log(
|
|
297
|
+
`${colors.dim}Run without --dry-run to apply changes${colors.reset}`
|
|
298
|
+
);
|
|
299
|
+
} else {
|
|
300
|
+
console.log(
|
|
301
|
+
`${colors.green}${colors.bright}${actionWord}:${colors.reset} ${totalMatches} ${changeWord} in ${filesWithChanges.length} ${fileWord}`
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
console.log(
|
|
305
|
+
`${colors.dim}Scanned ${results.length} files in ${duration}ms${colors.reset}`
|
|
306
|
+
);
|
|
307
|
+
console.log("");
|
|
308
|
+
}
|
|
309
|
+
function main() {
|
|
310
|
+
const args = process.argv.slice(2);
|
|
311
|
+
const options = parseArgs(args);
|
|
312
|
+
if (options.help) {
|
|
313
|
+
printHelp();
|
|
314
|
+
process.exit(0);
|
|
315
|
+
}
|
|
316
|
+
if (options.version) {
|
|
317
|
+
printVersion();
|
|
318
|
+
process.exit(0);
|
|
319
|
+
}
|
|
320
|
+
console.log("");
|
|
321
|
+
console.log(
|
|
322
|
+
`${colors.cyan}${colors.bright}ui-plume-migrate${colors.reset} - Migrating prose → plume...`
|
|
323
|
+
);
|
|
324
|
+
if (options.dryRun) {
|
|
325
|
+
console.log(
|
|
326
|
+
`${colors.yellow}(dry run - no files will be modified)${colors.reset}`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
const startTime = Date.now();
|
|
330
|
+
let files;
|
|
331
|
+
try {
|
|
332
|
+
files = scanFiles(options.path, {
|
|
333
|
+
extensions: options.extensions,
|
|
334
|
+
ignore: options.ignore
|
|
335
|
+
});
|
|
336
|
+
} catch (error) {
|
|
337
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
338
|
+
console.error(`${colors.red}Error:${colors.reset} ${message}`);
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
341
|
+
const results = [];
|
|
342
|
+
for (const file of files) {
|
|
343
|
+
if (!needsMigration(file.content)) {
|
|
344
|
+
results.push({
|
|
345
|
+
filePath: file.relativePath,
|
|
346
|
+
originalContent: file.content,
|
|
347
|
+
migratedContent: file.content,
|
|
348
|
+
matches: [],
|
|
349
|
+
hasChanges: false
|
|
350
|
+
});
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
if (options.dryRun) {
|
|
354
|
+
const { migrateContent: migrateContent2 } = require("./proseMigrator");
|
|
355
|
+
const migrationResult = migrateContent2(file.content);
|
|
356
|
+
results.push({
|
|
357
|
+
...migrationResult,
|
|
358
|
+
filePath: file.relativePath
|
|
359
|
+
});
|
|
360
|
+
} else {
|
|
361
|
+
const result = migrateFileInPlace(file.absolutePath);
|
|
362
|
+
results.push({
|
|
363
|
+
...result,
|
|
364
|
+
filePath: file.relativePath
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
const duration = Date.now() - startTime;
|
|
369
|
+
printResults(results, options.dryRun, duration);
|
|
370
|
+
const hasChanges = results.some((r) => r.hasChanges);
|
|
371
|
+
if (options.dryRun && hasChanges) {
|
|
372
|
+
process.exit(1);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
main();
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@versini/ui-styles",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Arno Versini",
|
|
6
6
|
"publishConfig": {
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"main": "dist/index.js",
|
|
16
16
|
"types": "dist/index.d.ts",
|
|
17
17
|
"bin": {
|
|
18
|
-
"ui-doctor": "dist/cli/ui-doctor.js"
|
|
18
|
+
"ui-doctor": "dist/cli/ui-doctor.js",
|
|
19
|
+
"ui-plume-migrate": "dist/cli/ui-plume-migrate.js"
|
|
19
20
|
},
|
|
20
21
|
"files": [
|
|
21
22
|
"dist",
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
},
|
|
42
43
|
"dependencies": {
|
|
43
44
|
"@tailwindcss/container-queries": "0.1.1",
|
|
44
|
-
"@versini/ui-typography": "
|
|
45
|
+
"@versini/ui-typography": "2.0.0",
|
|
45
46
|
"culori": "4.0.2",
|
|
46
47
|
"fs-extra": "11.3.3",
|
|
47
48
|
"tailwindcss": "4.1.18"
|
|
@@ -49,5 +50,5 @@
|
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"rollup-plugin-copy": "3.5.0"
|
|
51
52
|
},
|
|
52
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "ace8376be408d1f21ced7ba7a3259891476690e4"
|
|
53
54
|
}
|