@csszyx/cli 0.10.7 → 0.10.9
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/dist/bin.mjs +161 -4
- package/dist/index.mjs +2 -2
- package/dist/shared/{cli.C2lx9IpE.mjs → cli.DXHBKEV9.mjs} +127 -109
- package/package.json +5 -5
package/dist/bin.mjs
CHANGED
|
@@ -6,18 +6,18 @@ import path__default from 'node:path';
|
|
|
6
6
|
import fs from 'fs-extra';
|
|
7
7
|
import ora from 'ora';
|
|
8
8
|
import pc from 'picocolors';
|
|
9
|
+
import { readFile } from 'node:fs/promises';
|
|
10
|
+
import { transformSourceCode, transform, sortStrings } from '@csszyx/compiler';
|
|
11
|
+
import fg from 'fast-glob';
|
|
9
12
|
import { parseExpression } from '@babel/parser';
|
|
10
|
-
import {
|
|
11
|
-
import { i as transformHtmlSourceSimple, t as transformSource, h as generateTypes } from './shared/cli.C2lx9IpE.mjs';
|
|
13
|
+
import { i as transformHtmlSourceSimple, t as transformSource, h as generateTypes } from './shared/cli.DXHBKEV9.mjs';
|
|
12
14
|
import { execa } from 'execa';
|
|
13
15
|
import prompts from 'prompts';
|
|
14
16
|
import readline from 'node:readline';
|
|
15
|
-
import fg from 'fast-glob';
|
|
16
17
|
import { runNextPrebuild } from '@csszyx/unplugin/next-prebuild';
|
|
17
18
|
import { NextSafelistWatcher } from '@csszyx/unplugin/next-watcher';
|
|
18
19
|
import { watch } from 'chokidar';
|
|
19
20
|
import { Minimatch } from 'minimatch';
|
|
20
|
-
import 'node:fs/promises';
|
|
21
21
|
import 'node:url';
|
|
22
22
|
import 'tailwindcss/resolveConfig.js';
|
|
23
23
|
import '@babel/types';
|
|
@@ -178,6 +178,81 @@ function formatBytes(bytes) {
|
|
|
178
178
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
+
const DEFAULT_IGNORE$1 = [
|
|
182
|
+
"**/node_modules/**",
|
|
183
|
+
"**/dist/**",
|
|
184
|
+
"**/build/**",
|
|
185
|
+
"**/.next/**",
|
|
186
|
+
"**/.nuxt/**",
|
|
187
|
+
"**/.astro/**"
|
|
188
|
+
];
|
|
189
|
+
async function check(options = {}) {
|
|
190
|
+
const cwd = options.cwd ?? process.cwd();
|
|
191
|
+
const patterns = options.pattern ? [options.pattern] : ["**/*.{jsx,tsx}"];
|
|
192
|
+
const ignore = [...DEFAULT_IGNORE$1, ...options.ignore ?? []];
|
|
193
|
+
process.env.CSSZYX_NO_PROJECT_SCAN_HINT = "1";
|
|
194
|
+
printHeader("csszyx check \u2014 static sz diagnostics");
|
|
195
|
+
const s = spinner.start("Scanning for files...");
|
|
196
|
+
let files;
|
|
197
|
+
try {
|
|
198
|
+
files = await fg(patterns, { cwd, ignore, absolute: true });
|
|
199
|
+
} catch (err) {
|
|
200
|
+
s.fail("File scan failed");
|
|
201
|
+
printWarn(`Could not scan files: ${err instanceof Error ? err.message : String(err)}`);
|
|
202
|
+
process.exitCode = 1;
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
s.succeed(`Found ${files.length} files`);
|
|
206
|
+
const issues = [];
|
|
207
|
+
let currentFile = "";
|
|
208
|
+
const originalWarn = console.warn;
|
|
209
|
+
console.warn = (...args) => {
|
|
210
|
+
const message = args.map(String).join(" ");
|
|
211
|
+
if (message.startsWith("[csszyx]")) {
|
|
212
|
+
issues.push({ file: currentFile, message: message.replace(/^\[csszyx\]\s*/, "") });
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
try {
|
|
216
|
+
for (const file of files) {
|
|
217
|
+
let source;
|
|
218
|
+
try {
|
|
219
|
+
source = await readFile(file, "utf8");
|
|
220
|
+
} catch {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (!source.includes("sz")) {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
currentFile = path__default.relative(cwd, file);
|
|
227
|
+
try {
|
|
228
|
+
transformSourceCode(source, file, { rootDir: cwd });
|
|
229
|
+
} catch {
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
} finally {
|
|
233
|
+
console.warn = originalWarn;
|
|
234
|
+
}
|
|
235
|
+
if (issues.length === 0) {
|
|
236
|
+
printSuccess(`No sz issues found across ${files.length} files.`);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
240
|
+
for (const { file, message } of issues) {
|
|
241
|
+
const list = byFile.get(file) ?? [];
|
|
242
|
+
list.push(message);
|
|
243
|
+
byFile.set(file, list);
|
|
244
|
+
}
|
|
245
|
+
for (const [file, messages] of byFile) {
|
|
246
|
+
printWarn(file);
|
|
247
|
+
for (const message of messages) {
|
|
248
|
+
printInfo(` ${message}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
printWarn(`
|
|
252
|
+
\u2716 ${issues.length} sz issue(s) in ${byFile.size} file(s).`);
|
|
253
|
+
process.exitCode = 1;
|
|
254
|
+
}
|
|
255
|
+
|
|
181
256
|
function detectFramework(cwd) {
|
|
182
257
|
try {
|
|
183
258
|
const pkgPath = path__default.join(cwd, "package.json");
|
|
@@ -1445,6 +1520,71 @@ function normalizeDebounceMs(debounceMs) {
|
|
|
1445
1520
|
return parsed;
|
|
1446
1521
|
}
|
|
1447
1522
|
|
|
1523
|
+
const DEFAULT_IGNORE = [
|
|
1524
|
+
"**/node_modules/**",
|
|
1525
|
+
"**/dist/**",
|
|
1526
|
+
"**/build/**",
|
|
1527
|
+
"**/.next/**",
|
|
1528
|
+
"**/.nuxt/**",
|
|
1529
|
+
"**/.astro/**"
|
|
1530
|
+
];
|
|
1531
|
+
const CLASS_SELECTOR_RE = /\.(-?[a-z_][\w-]*)/gi;
|
|
1532
|
+
function stripNonSelectorText(css) {
|
|
1533
|
+
return css.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/\/\/[^\n]*/g, " ").replace(/url\([^)]*\)/gi, " ").replace(/'[^']*'/g, " ").replace(/"[^"]*"/g, " ");
|
|
1534
|
+
}
|
|
1535
|
+
function looksLikeToken(name) {
|
|
1536
|
+
return /^[a-z][a-z0-9]{0,2}$/i.test(name);
|
|
1537
|
+
}
|
|
1538
|
+
async function scanCollisions(options = {}) {
|
|
1539
|
+
const cwd = options.cwd ?? process.cwd();
|
|
1540
|
+
const patterns = options.pattern ? [options.pattern] : ["**/*.{css,scss,sass,less}"];
|
|
1541
|
+
const ignore = [...DEFAULT_IGNORE, ...options.ignore ?? []];
|
|
1542
|
+
printHeader("csszyx scan-collisions \u2014 mangle token risks");
|
|
1543
|
+
const s = spinner.start("Scanning stylesheets...");
|
|
1544
|
+
let files;
|
|
1545
|
+
try {
|
|
1546
|
+
files = await fg(patterns, { cwd, ignore, absolute: true });
|
|
1547
|
+
} catch (err) {
|
|
1548
|
+
s.fail("Stylesheet scan failed");
|
|
1549
|
+
printWarn(`Could not scan files: ${err instanceof Error ? err.message : String(err)}`);
|
|
1550
|
+
process.exitCode = 1;
|
|
1551
|
+
return;
|
|
1552
|
+
}
|
|
1553
|
+
s.succeed(`Scanned ${files.length} stylesheet(s)`);
|
|
1554
|
+
const risky = /* @__PURE__ */ new Map();
|
|
1555
|
+
for (const file of files) {
|
|
1556
|
+
let css;
|
|
1557
|
+
try {
|
|
1558
|
+
css = await readFile(file, "utf8");
|
|
1559
|
+
} catch {
|
|
1560
|
+
continue;
|
|
1561
|
+
}
|
|
1562
|
+
const rel = path__default.relative(cwd, file);
|
|
1563
|
+
for (const match of stripNonSelectorText(css).matchAll(CLASS_SELECTOR_RE)) {
|
|
1564
|
+
const name = match[1];
|
|
1565
|
+
if (looksLikeToken(name)) {
|
|
1566
|
+
(risky.get(name) ?? risky.set(name, /* @__PURE__ */ new Set()).get(name))?.add(rel);
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
if (risky.size === 0) {
|
|
1571
|
+
printSuccess("No collision-prone class names found \u2014 mangling is safe to enable.");
|
|
1572
|
+
return;
|
|
1573
|
+
}
|
|
1574
|
+
const names = sortStrings(risky.keys());
|
|
1575
|
+
printWarn(`${names.length} class name(s) could collide with a mangled token:`);
|
|
1576
|
+
for (const name of names) {
|
|
1577
|
+
const where = [...risky.get(name) ?? []].slice(0, 3).join(", ");
|
|
1578
|
+
printInfo(` .${name} (in ${where})`);
|
|
1579
|
+
}
|
|
1580
|
+
printInfo("\nPreferred: rename these in your own CSS to something specific");
|
|
1581
|
+
printInfo(" (e.g. `.x` \u2192 `.resize-handle-x`) \u2014 short names also clash on");
|
|
1582
|
+
printInfo(" specificity with other libraries.");
|
|
1583
|
+
printInfo("\nFor names in a third-party stylesheet you cannot edit, reserve them:");
|
|
1584
|
+
printInfo(` production: { mangle: true, mangleExclude: ${JSON.stringify(names)} }`);
|
|
1585
|
+
process.exitCode = 1;
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1448
1588
|
const cli = cac("csszyx");
|
|
1449
1589
|
normalizeNextCommandAlias(process.argv);
|
|
1450
1590
|
function readCliVersion() {
|
|
@@ -1500,6 +1640,23 @@ cli.command("doctor", "Diagnose mangling issues").option("--verbose", "Show deta
|
|
|
1500
1640
|
cwd: options.cwd
|
|
1501
1641
|
});
|
|
1502
1642
|
});
|
|
1643
|
+
cli.command("check", "Scan the whole project for unknown/aliased sz keys (CI-friendly)").option("--pattern <glob>", "Glob of source files to scan").option("--ignore <glob>", "Extra ignore glob (repeatable)").option("--cwd <dir>", "Current working directory").action(async (options) => {
|
|
1644
|
+
await check({
|
|
1645
|
+
cwd: options.cwd,
|
|
1646
|
+
pattern: options.pattern,
|
|
1647
|
+
ignore: options.ignore ? Array.isArray(options.ignore) ? options.ignore : [options.ignore] : void 0
|
|
1648
|
+
});
|
|
1649
|
+
});
|
|
1650
|
+
cli.command(
|
|
1651
|
+
"scan-collisions",
|
|
1652
|
+
"Find class names that could collide with a mangled token (for production.mangleExclude)"
|
|
1653
|
+
).option("--pattern <glob>", "Glob of stylesheet files to scan").option("--ignore <glob>", "Extra ignore glob (repeatable)").option("--cwd <dir>", "Current working directory").action(async (options) => {
|
|
1654
|
+
await scanCollisions({
|
|
1655
|
+
cwd: options.cwd,
|
|
1656
|
+
pattern: options.pattern,
|
|
1657
|
+
ignore: options.ignore ? Array.isArray(options.ignore) ? options.ignore : [options.ignore] : void 0
|
|
1658
|
+
});
|
|
1659
|
+
});
|
|
1503
1660
|
cli.command("explain <sz>", "Print the Tailwind className an sz object compiles to").action(
|
|
1504
1661
|
(sz) => {
|
|
1505
1662
|
explain(sz);
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { c as classNameToSzObject, e as extractScreenKeys, a as extractSpacingKeys, f as findConfigFile, b as flattenColors, g as generateAndWriteTypes, d as generateTypeDeclarations, h as generateTypes, t as migrateSource, s as scanTailwindConfig, w as writeDeclarationFile } from './shared/cli.
|
|
1
|
+
export { c as classNameToSzObject, e as extractScreenKeys, a as extractSpacingKeys, f as findConfigFile, b as flattenColors, g as generateAndWriteTypes, d as generateTypeDeclarations, h as generateTypes, t as migrateSource, s as scanTailwindConfig, w as writeDeclarationFile } from './shared/cli.DXHBKEV9.mjs';
|
|
2
2
|
import 'node:path';
|
|
3
3
|
import 'node:fs';
|
|
4
4
|
import 'node:fs/promises';
|
|
5
5
|
import 'node:url';
|
|
6
|
+
import '@csszyx/compiler';
|
|
6
7
|
import 'tailwindcss/resolveConfig.js';
|
|
7
8
|
import '@babel/parser';
|
|
8
9
|
import '@babel/types';
|
|
9
|
-
import '@csszyx/compiler';
|
|
@@ -2,10 +2,10 @@ import { resolve, dirname } from 'node:path';
|
|
|
2
2
|
import { existsSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { mkdir } from 'node:fs/promises';
|
|
4
4
|
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import { sortStrings, REMOVED_BOOLEAN_SUGAR, SUGGESTION_MAP } from '@csszyx/compiler';
|
|
5
6
|
import resolveConfig from 'tailwindcss/resolveConfig.js';
|
|
6
7
|
import { parse } from '@babel/parser';
|
|
7
8
|
import * as t from '@babel/types';
|
|
8
|
-
import { REMOVED_BOOLEAN_SUGAR, SUGGESTION_MAP } from '@csszyx/compiler';
|
|
9
9
|
|
|
10
10
|
const CONFIG_FILES = [
|
|
11
11
|
"tailwind.config.ts",
|
|
@@ -69,7 +69,7 @@ function flattenColors(colors) {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
return result
|
|
72
|
+
return sortStrings(result);
|
|
73
73
|
}
|
|
74
74
|
function extractSpacingKeys(spacing) {
|
|
75
75
|
return Object.keys(spacing).sort((a, b) => {
|
|
@@ -869,113 +869,6 @@ async function generateTypes(options = {}) {
|
|
|
869
869
|
}
|
|
870
870
|
}
|
|
871
871
|
|
|
872
|
-
function generateSzExpression(obj) {
|
|
873
|
-
return `{${objectToString(obj)}}`;
|
|
874
|
-
}
|
|
875
|
-
function generateSzHtmlValue(obj, braces = false) {
|
|
876
|
-
const s = objectToString(obj);
|
|
877
|
-
if (braces) {
|
|
878
|
-
return s;
|
|
879
|
-
}
|
|
880
|
-
if (s.startsWith("{ ") && s.endsWith(" }")) {
|
|
881
|
-
return s.slice(2, -2);
|
|
882
|
-
}
|
|
883
|
-
if (s.startsWith("{") && s.endsWith("}")) {
|
|
884
|
-
return s.slice(1, -1).trim();
|
|
885
|
-
}
|
|
886
|
-
return s;
|
|
887
|
-
}
|
|
888
|
-
function generateSzObjectLiteral(obj) {
|
|
889
|
-
return objectToString(obj);
|
|
890
|
-
}
|
|
891
|
-
function objectToString(obj, indent = 0) {
|
|
892
|
-
const entries = Object.entries(obj);
|
|
893
|
-
if (entries.length === 0) {
|
|
894
|
-
return "{}";
|
|
895
|
-
}
|
|
896
|
-
const spaces = " ".repeat(indent);
|
|
897
|
-
const innerSpaces = " ".repeat(indent + 2);
|
|
898
|
-
if (entries.length <= 2 && !hasDeepNesting(obj)) {
|
|
899
|
-
const parts = entries.map(([k, v]) => `${formatKey(k)}: ${formatValue(v, indent)}`);
|
|
900
|
-
return `{ ${parts.join(", ")} }`;
|
|
901
|
-
}
|
|
902
|
-
const lines = entries.map(
|
|
903
|
-
([k, v]) => `${innerSpaces}${formatKey(k)}: ${formatValue(v, indent + 2)},`
|
|
904
|
-
);
|
|
905
|
-
return `{
|
|
906
|
-
${lines.join("\n")}
|
|
907
|
-
${spaces}}`;
|
|
908
|
-
}
|
|
909
|
-
function hasDeepNesting(obj) {
|
|
910
|
-
return Object.values(obj).some(
|
|
911
|
-
(v) => typeof v === "object" && v !== null && !isColorOpacityObj(v) && !isGradientObj(v)
|
|
912
|
-
);
|
|
913
|
-
}
|
|
914
|
-
function isColorOpacityObj(v) {
|
|
915
|
-
return typeof v === "object" && v !== null && "color" in v && "op" in v;
|
|
916
|
-
}
|
|
917
|
-
function isGradientObj(v) {
|
|
918
|
-
return typeof v === "object" && v !== null && "gradient" in v;
|
|
919
|
-
}
|
|
920
|
-
function formatKey(key) {
|
|
921
|
-
if (/^[a-z_$][\w$]*$/i.test(key)) {
|
|
922
|
-
return key;
|
|
923
|
-
}
|
|
924
|
-
return `'${key}'`;
|
|
925
|
-
}
|
|
926
|
-
function formatValue(value, indent) {
|
|
927
|
-
if (value === true) {
|
|
928
|
-
return "true";
|
|
929
|
-
}
|
|
930
|
-
if (value === false) {
|
|
931
|
-
return "false";
|
|
932
|
-
}
|
|
933
|
-
if (value === null) {
|
|
934
|
-
return "null";
|
|
935
|
-
}
|
|
936
|
-
if (typeof value === "number") {
|
|
937
|
-
return String(value);
|
|
938
|
-
}
|
|
939
|
-
if (typeof value === "string") {
|
|
940
|
-
return `'${escapeString(value)}'`;
|
|
941
|
-
}
|
|
942
|
-
if (Array.isArray(value)) {
|
|
943
|
-
const items = value.map((v) => formatValue(v, indent));
|
|
944
|
-
return `[${items.join(", ")}]`;
|
|
945
|
-
}
|
|
946
|
-
if (typeof value === "object") {
|
|
947
|
-
if (isColorOpacityObj(value)) {
|
|
948
|
-
const parts = [`color: '${escapeString(String(value.color))}'`];
|
|
949
|
-
if (typeof value.op === "number") {
|
|
950
|
-
parts.push(`op: ${value.op}`);
|
|
951
|
-
} else {
|
|
952
|
-
parts.push(`op: '${escapeString(String(value.op))}'`);
|
|
953
|
-
}
|
|
954
|
-
return `{ ${parts.join(", ")} }`;
|
|
955
|
-
}
|
|
956
|
-
if (isGradientObj(value)) {
|
|
957
|
-
const grad = value;
|
|
958
|
-
const parts = [`gradient: '${grad.gradient}'`];
|
|
959
|
-
if ("dir" in grad) {
|
|
960
|
-
if (typeof grad.dir === "number") {
|
|
961
|
-
parts.push(`dir: ${grad.dir}`);
|
|
962
|
-
} else {
|
|
963
|
-
parts.push(`dir: '${escapeString(String(grad.dir))}'`);
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
if ("in" in grad) {
|
|
967
|
-
parts.push(`in: '${escapeString(String(grad.in))}'`);
|
|
968
|
-
}
|
|
969
|
-
return `{ ${parts.join(", ")} }`;
|
|
970
|
-
}
|
|
971
|
-
return objectToString(value, indent);
|
|
972
|
-
}
|
|
973
|
-
return String(value);
|
|
974
|
-
}
|
|
975
|
-
function escapeString(s) {
|
|
976
|
-
return s.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
977
|
-
}
|
|
978
|
-
|
|
979
872
|
const REVERSE_PROPERTY_MAP = {
|
|
980
873
|
// Background (ambiguous — disambiguated in class-parser)
|
|
981
874
|
bg: "bg",
|
|
@@ -2474,6 +2367,113 @@ function parseStringValue(value) {
|
|
|
2474
2367
|
return value;
|
|
2475
2368
|
}
|
|
2476
2369
|
|
|
2370
|
+
function generateSzExpression(obj) {
|
|
2371
|
+
return `{${objectToString(obj)}}`;
|
|
2372
|
+
}
|
|
2373
|
+
function generateSzHtmlValue(obj, braces = false) {
|
|
2374
|
+
const s = objectToString(obj);
|
|
2375
|
+
if (braces) {
|
|
2376
|
+
return s;
|
|
2377
|
+
}
|
|
2378
|
+
if (s.startsWith("{ ") && s.endsWith(" }")) {
|
|
2379
|
+
return s.slice(2, -2);
|
|
2380
|
+
}
|
|
2381
|
+
if (s.startsWith("{") && s.endsWith("}")) {
|
|
2382
|
+
return s.slice(1, -1).trim();
|
|
2383
|
+
}
|
|
2384
|
+
return s;
|
|
2385
|
+
}
|
|
2386
|
+
function generateSzObjectLiteral(obj) {
|
|
2387
|
+
return objectToString(obj);
|
|
2388
|
+
}
|
|
2389
|
+
function objectToString(obj, indent = 0) {
|
|
2390
|
+
const entries = Object.entries(obj);
|
|
2391
|
+
if (entries.length === 0) {
|
|
2392
|
+
return "{}";
|
|
2393
|
+
}
|
|
2394
|
+
const spaces = " ".repeat(indent);
|
|
2395
|
+
const innerSpaces = " ".repeat(indent + 2);
|
|
2396
|
+
if (entries.length <= 2 && !hasDeepNesting(obj)) {
|
|
2397
|
+
const parts = entries.map(([k, v]) => `${formatKey(k)}: ${formatValue(v, indent)}`);
|
|
2398
|
+
return `{ ${parts.join(", ")} }`;
|
|
2399
|
+
}
|
|
2400
|
+
const lines = entries.map(
|
|
2401
|
+
([k, v]) => `${innerSpaces}${formatKey(k)}: ${formatValue(v, indent + 2)},`
|
|
2402
|
+
);
|
|
2403
|
+
return `{
|
|
2404
|
+
${lines.join("\n")}
|
|
2405
|
+
${spaces}}`;
|
|
2406
|
+
}
|
|
2407
|
+
function hasDeepNesting(obj) {
|
|
2408
|
+
return Object.values(obj).some(
|
|
2409
|
+
(v) => typeof v === "object" && v !== null && !isColorOpacityObj(v) && !isGradientObj(v)
|
|
2410
|
+
);
|
|
2411
|
+
}
|
|
2412
|
+
function isColorOpacityObj(v) {
|
|
2413
|
+
return typeof v === "object" && v !== null && "color" in v && "op" in v;
|
|
2414
|
+
}
|
|
2415
|
+
function isGradientObj(v) {
|
|
2416
|
+
return typeof v === "object" && v !== null && "gradient" in v;
|
|
2417
|
+
}
|
|
2418
|
+
function formatKey(key) {
|
|
2419
|
+
if (/^[a-z_$][\w$]*$/i.test(key)) {
|
|
2420
|
+
return key;
|
|
2421
|
+
}
|
|
2422
|
+
return `'${key}'`;
|
|
2423
|
+
}
|
|
2424
|
+
function formatValue(value, indent) {
|
|
2425
|
+
if (value === true) {
|
|
2426
|
+
return "true";
|
|
2427
|
+
}
|
|
2428
|
+
if (value === false) {
|
|
2429
|
+
return "false";
|
|
2430
|
+
}
|
|
2431
|
+
if (value === null) {
|
|
2432
|
+
return "null";
|
|
2433
|
+
}
|
|
2434
|
+
if (typeof value === "number") {
|
|
2435
|
+
return String(value);
|
|
2436
|
+
}
|
|
2437
|
+
if (typeof value === "string") {
|
|
2438
|
+
return `'${escapeString(value)}'`;
|
|
2439
|
+
}
|
|
2440
|
+
if (Array.isArray(value)) {
|
|
2441
|
+
const items = value.map((v) => formatValue(v, indent));
|
|
2442
|
+
return `[${items.join(", ")}]`;
|
|
2443
|
+
}
|
|
2444
|
+
if (typeof value === "object") {
|
|
2445
|
+
if (isColorOpacityObj(value)) {
|
|
2446
|
+
const parts = [`color: '${escapeString(String(value.color))}'`];
|
|
2447
|
+
if (typeof value.op === "number") {
|
|
2448
|
+
parts.push(`op: ${value.op}`);
|
|
2449
|
+
} else {
|
|
2450
|
+
parts.push(`op: '${escapeString(String(value.op))}'`);
|
|
2451
|
+
}
|
|
2452
|
+
return `{ ${parts.join(", ")} }`;
|
|
2453
|
+
}
|
|
2454
|
+
if (isGradientObj(value)) {
|
|
2455
|
+
const grad = value;
|
|
2456
|
+
const parts = [`gradient: '${grad.gradient}'`];
|
|
2457
|
+
if ("dir" in grad) {
|
|
2458
|
+
if (typeof grad.dir === "number") {
|
|
2459
|
+
parts.push(`dir: ${grad.dir}`);
|
|
2460
|
+
} else {
|
|
2461
|
+
parts.push(`dir: '${escapeString(String(grad.dir))}'`);
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
if ("in" in grad) {
|
|
2465
|
+
parts.push(`in: '${escapeString(String(grad.in))}'`);
|
|
2466
|
+
}
|
|
2467
|
+
return `{ ${parts.join(", ")} }`;
|
|
2468
|
+
}
|
|
2469
|
+
return objectToString(value, indent);
|
|
2470
|
+
}
|
|
2471
|
+
return String(value);
|
|
2472
|
+
}
|
|
2473
|
+
function escapeString(s) {
|
|
2474
|
+
return s.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
2477
|
function tokenize(className) {
|
|
2478
2478
|
return className.trim().split(/\s+/).filter(Boolean);
|
|
2479
2479
|
}
|
|
@@ -3244,6 +3244,24 @@ function normalizeSzObject(obj, replacements) {
|
|
|
3244
3244
|
count++;
|
|
3245
3245
|
continue;
|
|
3246
3246
|
}
|
|
3247
|
+
if (keyName === "font" && key.start != null && key.end != null) {
|
|
3248
|
+
let fontValue = null;
|
|
3249
|
+
if (t.isStringLiteral(prop.value)) {
|
|
3250
|
+
fontValue = prop.value.value;
|
|
3251
|
+
} else if (t.isNumericLiteral(prop.value)) {
|
|
3252
|
+
fontValue = String(prop.value.value);
|
|
3253
|
+
}
|
|
3254
|
+
const resolved = fontValue !== null ? disambiguateFont(fontValue)?.prop : void 0;
|
|
3255
|
+
if (resolved && resolved !== "font") {
|
|
3256
|
+
replacements.push({
|
|
3257
|
+
start: key.start,
|
|
3258
|
+
end: key.end,
|
|
3259
|
+
text: t.isStringLiteral(key) ? `'${resolved}'` : resolved
|
|
3260
|
+
});
|
|
3261
|
+
count++;
|
|
3262
|
+
continue;
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3247
3265
|
const suggestion = SUGGESTION_MAP[keyName];
|
|
3248
3266
|
if (suggestion && isCleanCanonicalTarget(suggestion) && suggestion !== keyName && key.start != null && key.end != null) {
|
|
3249
3267
|
replacements.push({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@csszyx/cli",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.9",
|
|
4
4
|
"description": "Command-line tools for csszyx",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"csszyx",
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
"picocolors": "^1.0.0",
|
|
50
50
|
"prompts": "^2.4.2",
|
|
51
51
|
"tailwindcss": "^3.4.1",
|
|
52
|
-
"@csszyx/compiler": "0.10.
|
|
53
|
-
"@csszyx/unplugin": "0.10.
|
|
54
|
-
"@csszyx/types": "0.10.
|
|
52
|
+
"@csszyx/compiler": "0.10.9",
|
|
53
|
+
"@csszyx/unplugin": "0.10.9",
|
|
54
|
+
"@csszyx/types": "0.10.9"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/fs-extra": "^11.0.4",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@types/prompts": "^2.4.9",
|
|
60
60
|
"typescript": "^6.0.3",
|
|
61
61
|
"unbuild": "^3.6.1",
|
|
62
|
-
"vitest": "^4.1.
|
|
62
|
+
"vitest": "^4.1.9"
|
|
63
63
|
},
|
|
64
64
|
"sideEffects": false,
|
|
65
65
|
"engines": {
|