@csszyx/cli 0.9.10 → 0.10.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/dist/bin.mjs +165 -15
- package/dist/index.d.mts +10 -0
- package/dist/index.mjs +2 -1
- package/dist/shared/{cli.dDkXlxD_.mjs → cli.C2lx9IpE.mjs} +334 -136
- package/package.json +4 -3
package/dist/bin.mjs
CHANGED
|
@@ -6,7 +6,9 @@ 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 {
|
|
9
|
+
import { parseExpression } from '@babel/parser';
|
|
10
|
+
import { transform } from '@csszyx/compiler';
|
|
11
|
+
import { i as transformHtmlSourceSimple, t as transformSource, h as generateTypes } from './shared/cli.C2lx9IpE.mjs';
|
|
10
12
|
import { execa } from 'execa';
|
|
11
13
|
import prompts from 'prompts';
|
|
12
14
|
import readline from 'node:readline';
|
|
@@ -18,7 +20,6 @@ import { Minimatch } from 'minimatch';
|
|
|
18
20
|
import 'node:fs/promises';
|
|
19
21
|
import 'node:url';
|
|
20
22
|
import 'tailwindcss/resolveConfig.js';
|
|
21
|
-
import '@babel/parser';
|
|
22
23
|
import '@babel/types';
|
|
23
24
|
|
|
24
25
|
const colors = {
|
|
@@ -329,6 +330,97 @@ async function doctor(options = {}) {
|
|
|
329
330
|
}
|
|
330
331
|
}
|
|
331
332
|
|
|
333
|
+
class ExplainParseError extends Error {
|
|
334
|
+
}
|
|
335
|
+
function literalToValue(node) {
|
|
336
|
+
switch (node.type) {
|
|
337
|
+
case "StringLiteral":
|
|
338
|
+
return node.value;
|
|
339
|
+
case "NumericLiteral":
|
|
340
|
+
return node.value;
|
|
341
|
+
case "BooleanLiteral":
|
|
342
|
+
return node.value;
|
|
343
|
+
case "NullLiteral":
|
|
344
|
+
return null;
|
|
345
|
+
case "UnaryExpression":
|
|
346
|
+
if (node.operator === "-" && node.argument.type === "NumericLiteral") {
|
|
347
|
+
return -node.argument.value;
|
|
348
|
+
}
|
|
349
|
+
throw new ExplainParseError(`unsupported unary expression "${node.operator}"`);
|
|
350
|
+
case "TemplateLiteral":
|
|
351
|
+
if (node.expressions.length === 0 && node.quasis.length === 1) {
|
|
352
|
+
return node.quasis[0]?.value.cooked ?? "";
|
|
353
|
+
}
|
|
354
|
+
throw new ExplainParseError("template literals with interpolation are dynamic");
|
|
355
|
+
case "ArrayExpression":
|
|
356
|
+
return arrayToValue(node);
|
|
357
|
+
case "ObjectExpression":
|
|
358
|
+
return objectToValue(node);
|
|
359
|
+
default:
|
|
360
|
+
throw new ExplainParseError(
|
|
361
|
+
`"${node.type}" is dynamic \u2014 explain only resolves static literals`
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
function arrayToValue(node) {
|
|
366
|
+
return node.elements.map((element) => {
|
|
367
|
+
if (element === null) {
|
|
368
|
+
throw new ExplainParseError("array holes are not supported");
|
|
369
|
+
}
|
|
370
|
+
if (element.type === "SpreadElement") {
|
|
371
|
+
throw new ExplainParseError("spreads are dynamic and cannot be explained");
|
|
372
|
+
}
|
|
373
|
+
return literalToValue(element);
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
function objectToValue(node) {
|
|
377
|
+
const result = {};
|
|
378
|
+
for (const property of node.properties) {
|
|
379
|
+
if (property.type !== "ObjectProperty") {
|
|
380
|
+
throw new ExplainParseError("object methods/spreads are dynamic");
|
|
381
|
+
}
|
|
382
|
+
if (property.computed) {
|
|
383
|
+
throw new ExplainParseError("computed keys are dynamic");
|
|
384
|
+
}
|
|
385
|
+
const { key } = property;
|
|
386
|
+
const name = key.type === "Identifier" ? key.name : key.type === "StringLiteral" ? key.value : null;
|
|
387
|
+
if (name === null) {
|
|
388
|
+
throw new ExplainParseError(`unsupported key type "${key.type}"`);
|
|
389
|
+
}
|
|
390
|
+
if (property.value.type === "AssignmentPattern" || property.value.type === "RestElement") {
|
|
391
|
+
throw new ExplainParseError("pattern values are not supported");
|
|
392
|
+
}
|
|
393
|
+
result[name] = literalToValue(property.value);
|
|
394
|
+
}
|
|
395
|
+
return result;
|
|
396
|
+
}
|
|
397
|
+
function explainSz(input) {
|
|
398
|
+
let expression;
|
|
399
|
+
try {
|
|
400
|
+
expression = parseExpression(input, { plugins: ["typescript"] });
|
|
401
|
+
} catch {
|
|
402
|
+
throw new ExplainParseError("could not parse the sz argument as a JS expression");
|
|
403
|
+
}
|
|
404
|
+
if (expression.type !== "ObjectExpression") {
|
|
405
|
+
throw new ExplainParseError('sz must be an object literal, e.g. "{ p: 4 }"');
|
|
406
|
+
}
|
|
407
|
+
const object = objectToValue(expression);
|
|
408
|
+
const result = transform(object);
|
|
409
|
+
return typeof result === "string" ? result : result.className;
|
|
410
|
+
}
|
|
411
|
+
function explain(sz) {
|
|
412
|
+
let className;
|
|
413
|
+
try {
|
|
414
|
+
className = explainSz(sz);
|
|
415
|
+
} catch (error) {
|
|
416
|
+
const reason = error instanceof ExplainParseError ? error.message : String(error);
|
|
417
|
+
printError(`Could not explain sz: ${reason}`);
|
|
418
|
+
process.exitCode = 1;
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
console.log(className === "" ? "(no classes)" : className);
|
|
422
|
+
}
|
|
423
|
+
|
|
332
424
|
const VITE_FRAMEWORKS = /* @__PURE__ */ new Set(["vite-react", "vite-vue", "vite-svelte"]);
|
|
333
425
|
async function readFileOrNull(filePath) {
|
|
334
426
|
try {
|
|
@@ -470,7 +562,40 @@ async function init(options = {}) {
|
|
|
470
562
|
}
|
|
471
563
|
console.log(" \u2022 Check the docs at https://csszyx.com");
|
|
472
564
|
}
|
|
565
|
+
async function isInsideWorkspace(cwd) {
|
|
566
|
+
let dir = path__default.dirname(path__default.resolve(cwd));
|
|
567
|
+
const { root } = path__default.parse(dir);
|
|
568
|
+
while (dir !== root) {
|
|
569
|
+
if (await fs.pathExists(path__default.join(dir, "pnpm-workspace.yaml")) || await fs.pathExists(path__default.join(dir, "nx.json")) || await fs.pathExists(path__default.join(dir, "lerna.json"))) {
|
|
570
|
+
return true;
|
|
571
|
+
}
|
|
572
|
+
const pkg = await readFileOrNull(path__default.join(dir, "package.json"));
|
|
573
|
+
if (pkg) {
|
|
574
|
+
try {
|
|
575
|
+
if ("workspaces" in JSON.parse(pkg)) return true;
|
|
576
|
+
} catch {
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
dir = path__default.dirname(dir);
|
|
580
|
+
}
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
function tailwindImportBlock(cssDir, cwd, monorepo) {
|
|
584
|
+
if (!monorepo) return '@import "tailwindcss";\n';
|
|
585
|
+
const rel = path__default.relative(path__default.resolve(cssDir), path__default.resolve(cwd)) || ".";
|
|
586
|
+
const src = rel.split(path__default.sep).join("/");
|
|
587
|
+
return `/* Monorepo: scope Tailwind's content detection to this package. Its
|
|
588
|
+
automatic detection otherwise climbs to the workspace root and scans
|
|
589
|
+
sibling packages + docs (.md/.mdx/.txt are NOT ignored), generating
|
|
590
|
+
phantom or broken url() classes. csszyx auto-injects @source for its
|
|
591
|
+
generated classes; this @source covers your own templates. See
|
|
592
|
+
https://csszyx.com/docs/monorepo-content-scope/ */
|
|
593
|
+
@import "tailwindcss" source(none);
|
|
594
|
+
@source "${src}";
|
|
595
|
+
`;
|
|
596
|
+
}
|
|
473
597
|
async function setupTailwindCss(cwd, framework) {
|
|
598
|
+
const monorepo = await isInsideWorkspace(cwd);
|
|
474
599
|
let cssPath;
|
|
475
600
|
let content = null;
|
|
476
601
|
for (const candidate of CSS_ENTRY_CANDIDATES) {
|
|
@@ -485,14 +610,16 @@ async function setupTailwindCss(cwd, framework) {
|
|
|
485
610
|
if (!cssPath || content === null) {
|
|
486
611
|
cssPath = path__default.join(cwd, "src/index.css");
|
|
487
612
|
await fs.ensureDir(path__default.dirname(cssPath));
|
|
488
|
-
await fs.writeFile(cssPath,
|
|
613
|
+
await fs.writeFile(cssPath, tailwindImportBlock(path__default.dirname(cssPath), cwd, monorepo));
|
|
489
614
|
printInfo(`Created ${path__default.relative(cwd, cssPath)} with Tailwind v4 import`);
|
|
490
615
|
return;
|
|
491
616
|
}
|
|
492
617
|
if (!content.includes('@import "tailwindcss"') && !content.includes("@import 'tailwindcss'")) {
|
|
493
|
-
await fs.writeFile(
|
|
494
|
-
|
|
495
|
-
|
|
618
|
+
await fs.writeFile(
|
|
619
|
+
cssPath,
|
|
620
|
+
`${tailwindImportBlock(path__default.dirname(cssPath), cwd, monorepo)}
|
|
621
|
+
${content}`
|
|
622
|
+
);
|
|
496
623
|
printInfo(`Added Tailwind v4 import to ${path__default.relative(cwd, cssPath)}`);
|
|
497
624
|
}
|
|
498
625
|
if (NEXTJS_FRAMEWORKS.has(framework)) {
|
|
@@ -841,6 +968,7 @@ async function migrate(options = {}) {
|
|
|
841
968
|
let totalTransformed = 0;
|
|
842
969
|
let totalSkipped = 0;
|
|
843
970
|
let totalSkippedComponent = 0;
|
|
971
|
+
let totalSzKeysNormalized = 0;
|
|
844
972
|
let totalFiles = 0;
|
|
845
973
|
const allUnrecognized = [];
|
|
846
974
|
const allWarnings = [];
|
|
@@ -849,7 +977,10 @@ async function migrate(options = {}) {
|
|
|
849
977
|
for (const filePath of files) {
|
|
850
978
|
const source = fs$1.readFileSync(filePath, "utf-8");
|
|
851
979
|
const isHtml = filePath.endsWith(".html");
|
|
852
|
-
|
|
980
|
+
if (options.keysOnly && isHtml) {
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
const hasRelevantAttr = isHtml ? source.includes("class=") : options.keysOnly ? source.includes("sz=") : source.includes("className=") || source.includes("sz=");
|
|
853
984
|
if (!hasRelevantAttr) {
|
|
854
985
|
continue;
|
|
855
986
|
}
|
|
@@ -866,13 +997,18 @@ async function migrate(options = {}) {
|
|
|
866
997
|
injectRuntime: options.injectRuntime,
|
|
867
998
|
cdnUrl: options.cdnUrl,
|
|
868
999
|
localPath: options.localPath
|
|
869
|
-
}) : transformSource(processSource, filePath, {
|
|
1000
|
+
}) : transformSource(processSource, filePath, {
|
|
1001
|
+
injectTodos,
|
|
1002
|
+
customMap,
|
|
1003
|
+
keysOnly: options.keysOnly
|
|
1004
|
+
});
|
|
870
1005
|
allWarnings.push(...result.warnings);
|
|
871
1006
|
if (result.changed) {
|
|
872
1007
|
totalFiles++;
|
|
873
1008
|
totalTransformed += result.stats.classNamesTransformed;
|
|
874
1009
|
totalSkipped += result.stats.classNamesSkipped;
|
|
875
1010
|
totalSkippedComponent += result.stats.classNamesSkippedComponent;
|
|
1011
|
+
totalSzKeysNormalized += result.stats.szKeysNormalized ?? 0;
|
|
876
1012
|
allUnrecognized.push(...result.stats.classesUnrecognized);
|
|
877
1013
|
if (result.potentiallyUnusedImports.length > 0) {
|
|
878
1014
|
const rel2 = path__default.relative(cwd, filePath);
|
|
@@ -891,20 +1027,25 @@ async function migrate(options = {}) {
|
|
|
891
1027
|
}
|
|
892
1028
|
}
|
|
893
1029
|
const rel = path__default.relative(cwd, filePath);
|
|
1030
|
+
const detail = options.keysOnly ? `${result.stats.szKeysNormalized ?? 0} sz key(s) normalized` : `${result.stats.classNamesTransformed} className(s) \u2192 sz`;
|
|
894
1031
|
if (dryRun) {
|
|
895
|
-
printInfo(` ${rel}: ${
|
|
896
|
-
log.writeLine(` ${rel}: ${result.stats.classNamesTransformed} className(s) \u2192 sz`);
|
|
897
|
-
} else {
|
|
898
|
-
log.writeLine(` ${rel}: ${result.stats.classNamesTransformed} className(s) \u2192 sz`);
|
|
1032
|
+
printInfo(` ${rel}: ${detail}`);
|
|
899
1033
|
}
|
|
1034
|
+
log.writeLine(` ${rel}: ${detail}`);
|
|
900
1035
|
}
|
|
901
1036
|
}
|
|
902
1037
|
s2.succeed("Migration complete");
|
|
903
1038
|
console.info();
|
|
904
1039
|
printSuccess(`Files modified: ${totalFiles}`);
|
|
905
|
-
|
|
1040
|
+
if (!options.keysOnly) {
|
|
1041
|
+
printSuccess(`classNames converted: ${totalTransformed}`);
|
|
1042
|
+
}
|
|
906
1043
|
log.writeLine(`Files modified: ${totalFiles}`);
|
|
907
1044
|
log.writeLine(`classNames converted: ${totalTransformed}`);
|
|
1045
|
+
if (totalSzKeysNormalized > 0) {
|
|
1046
|
+
printSuccess(`legacy sz keys normalized: ${totalSzKeysNormalized}`);
|
|
1047
|
+
log.writeLine(`legacy sz keys normalized: ${totalSzKeysNormalized}`);
|
|
1048
|
+
}
|
|
908
1049
|
if (totalSkipped > 0) {
|
|
909
1050
|
printWarn(`classNames skipped (dynamic): ${totalSkipped}`);
|
|
910
1051
|
log.writeLine(`classNames skipped (dynamic): ${totalSkipped}`);
|
|
@@ -1359,6 +1500,11 @@ cli.command("doctor", "Diagnose mangling issues").option("--verbose", "Show deta
|
|
|
1359
1500
|
cwd: options.cwd
|
|
1360
1501
|
});
|
|
1361
1502
|
});
|
|
1503
|
+
cli.command("explain <sz>", "Print the Tailwind className an sz object compiles to").action(
|
|
1504
|
+
(sz) => {
|
|
1505
|
+
explain(sz);
|
|
1506
|
+
}
|
|
1507
|
+
);
|
|
1362
1508
|
cli.command("audit", "Analyze mangling performance").option("--json", "Output as JSON").option("--watch", "Live updates").option("--compare <dir>", "Compare with previous build").option("--cwd <dir>", "Current working directory").action(async (options) => {
|
|
1363
1509
|
await audit({
|
|
1364
1510
|
json: options.json,
|
|
@@ -1378,7 +1524,10 @@ cli.command("generate-types", "Generate TypeScript declarations from tailwind.co
|
|
|
1378
1524
|
cli.command("migrate [dir]", "Convert Tailwind className to sz prop").option("--dry-run", "Show changes without modifying files").option("--ignore <patterns>", "Glob patterns to ignore (comma-separated)").option("--pattern <glob>", "Custom glob pattern for file discovery").option("--cwd <dir>", "Current working directory").option("--braces", "Wrap HTML sz values in outer { } braces (default: bare)").option("--no-fouc", "Skip FOUC-prevention CSS injection into HTML files").option("--inject-runtime <mode>", "Inject runtime script into HTML: local | cdn").option("--cdn-url <url>", "Custom CDN URL for --inject-runtime cdn").option(
|
|
1379
1525
|
"--local-path <path>",
|
|
1380
1526
|
"Local script path for --inject-runtime local (default: csszyx-runtime.js)"
|
|
1381
|
-
).option("--audit", "Scan without modifying files and output .csszyx-todo.json").option("--inject-todos", "Inject {/* @sz-todo */} comments above unrecognized classes").option("--resolve-todos <file>", "Path to a JSON file mapping custom classes to sz properties").
|
|
1527
|
+
).option("--audit", "Scan without modifying files and output .csszyx-todo.json").option("--inject-todos", "Inject {/* @sz-todo */} comments above unrecognized classes").option("--resolve-todos <file>", "Path to a JSON file mapping custom classes to sz properties").option(
|
|
1528
|
+
"--keys-only",
|
|
1529
|
+
"Only normalize legacy sz-prop keys to their canonical form; leave className untouched (0.9.10 \u2192 0.10.0 upgrade)"
|
|
1530
|
+
).action(async (dir, options) => {
|
|
1382
1531
|
await migrate({
|
|
1383
1532
|
dryRun: options.dryRun,
|
|
1384
1533
|
ignore: options.ignore ? options.ignore.split(",") : void 0,
|
|
@@ -1391,7 +1540,8 @@ cli.command("migrate [dir]", "Convert Tailwind className to sz prop").option("--
|
|
|
1391
1540
|
localPath: options.localPath,
|
|
1392
1541
|
audit: options.audit,
|
|
1393
1542
|
injectTodos: options.injectTodos,
|
|
1394
|
-
resolveTodos: options.resolveTodos
|
|
1543
|
+
resolveTodos: options.resolveTodos,
|
|
1544
|
+
keysOnly: options.keysOnly
|
|
1395
1545
|
});
|
|
1396
1546
|
});
|
|
1397
1547
|
cli.command(
|
package/dist/index.d.mts
CHANGED
|
@@ -212,6 +212,8 @@ interface TransformResult {
|
|
|
212
212
|
/** className kept on capitalized components (they do not accept sz). */
|
|
213
213
|
classNamesSkippedComponent: number;
|
|
214
214
|
classesUnrecognized: string[];
|
|
215
|
+
/** Legacy sz-prop keys rewritten to their single-way canonical (transitional). */
|
|
216
|
+
szKeysNormalized?: number;
|
|
215
217
|
};
|
|
216
218
|
/** Imports that may be unused after migration (e.g., clsx, cn). */
|
|
217
219
|
potentiallyUnusedImports: string[];
|
|
@@ -224,6 +226,14 @@ interface TransformOptions {
|
|
|
224
226
|
injectTodos?: boolean;
|
|
225
227
|
/** Map of custom classes to sz objects, used to override unrecognized classes */
|
|
226
228
|
customMap?: CsszyxTodoMap;
|
|
229
|
+
/**
|
|
230
|
+
* If true, ONLY normalize legacy sz-prop keys to their single-way canonical
|
|
231
|
+
* and leave every `className` attribute untouched. The sz-key-only upgrade
|
|
232
|
+
* path for 0.9.10 → 0.10.0.
|
|
233
|
+
*
|
|
234
|
+
* TRANSITIONAL: part of the same legacy-key normalizer; remove at v1.
|
|
235
|
+
*/
|
|
236
|
+
keysOnly?: boolean;
|
|
227
237
|
}
|
|
228
238
|
/**
|
|
229
239
|
* Transform a JSX/TSX source file, replacing className with sz props.
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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.C2lx9IpE.mjs';
|
|
2
2
|
import 'node:path';
|
|
3
3
|
import 'node:fs';
|
|
4
4
|
import 'node:fs/promises';
|
|
@@ -6,3 +6,4 @@ import 'node:url';
|
|
|
6
6
|
import 'tailwindcss/resolveConfig.js';
|
|
7
7
|
import '@babel/parser';
|
|
8
8
|
import '@babel/types';
|
|
9
|
+
import '@csszyx/compiler';
|
|
@@ -5,6 +5,7 @@ import { pathToFileURL } from 'node:url';
|
|
|
5
5
|
import resolveConfig from 'tailwindcss/resolveConfig.js';
|
|
6
6
|
import { parse } from '@babel/parser';
|
|
7
7
|
import * as t from '@babel/types';
|
|
8
|
+
import { REMOVED_BOOLEAN_SUGAR, SUGGESTION_MAP } from '@csszyx/compiler';
|
|
8
9
|
|
|
9
10
|
const CONFIG_FILES = [
|
|
10
11
|
"tailwind.config.ts",
|
|
@@ -147,12 +148,6 @@ const PROPERTY_MAPPINGS = [
|
|
|
147
148
|
valueType: "spacing",
|
|
148
149
|
description: "Gap between flex/grid items"
|
|
149
150
|
},
|
|
150
|
-
{
|
|
151
|
-
prop: "grid",
|
|
152
|
-
prefix: "grid",
|
|
153
|
-
valueType: "grid",
|
|
154
|
-
description: "Grid shorthand"
|
|
155
|
-
},
|
|
156
151
|
{
|
|
157
152
|
prop: "gridCols",
|
|
158
153
|
prefix: "grid-cols",
|
|
@@ -324,7 +319,7 @@ const PROPERTY_MAPPINGS = [
|
|
|
324
319
|
description: "Background color"
|
|
325
320
|
},
|
|
326
321
|
{
|
|
327
|
-
prop: "
|
|
322
|
+
prop: "color",
|
|
328
323
|
prefix: "text",
|
|
329
324
|
valueType: "colors",
|
|
330
325
|
stateful: true,
|
|
@@ -358,7 +353,7 @@ const PROPERTY_MAPPINGS = [
|
|
|
358
353
|
},
|
|
359
354
|
// Typography
|
|
360
355
|
{
|
|
361
|
-
prop: "
|
|
356
|
+
prop: "weight",
|
|
362
357
|
prefix: "font",
|
|
363
358
|
valueType: "fontWeight",
|
|
364
359
|
description: "Font weight"
|
|
@@ -370,7 +365,7 @@ const PROPERTY_MAPPINGS = [
|
|
|
370
365
|
description: "Font family"
|
|
371
366
|
},
|
|
372
367
|
{
|
|
373
|
-
prop: "
|
|
368
|
+
prop: "text",
|
|
374
369
|
prefix: "text",
|
|
375
370
|
valueType: "fontSize",
|
|
376
371
|
description: "Font size"
|
|
@@ -400,12 +395,6 @@ const PROPERTY_MAPPINGS = [
|
|
|
400
395
|
valueType: "borderRadius",
|
|
401
396
|
description: "Border radius"
|
|
402
397
|
},
|
|
403
|
-
{
|
|
404
|
-
prop: "borderW",
|
|
405
|
-
prefix: "border",
|
|
406
|
-
valueType: "borderWidth",
|
|
407
|
-
description: "Border width"
|
|
408
|
-
},
|
|
409
398
|
// Effects
|
|
410
399
|
{
|
|
411
400
|
prop: "shadow",
|
|
@@ -581,11 +570,14 @@ const STATIC_VALUE_TYPES = {
|
|
|
581
570
|
transition: ["none", "all", "colors", "opacity", "shadow", "transform"],
|
|
582
571
|
ease: ["linear", "in", "out", "in-out"]
|
|
583
572
|
};
|
|
573
|
+
function escapeTsString(value) {
|
|
574
|
+
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\r/g, "\\r").replace(/\n/g, "\\n");
|
|
575
|
+
}
|
|
584
576
|
function generateUnionType(values) {
|
|
585
577
|
if (values.length === 0) {
|
|
586
578
|
return "string";
|
|
587
579
|
}
|
|
588
|
-
return values.map((v) => `'${v}'`).join(" | ");
|
|
580
|
+
return values.map((v) => `'${escapeTsString(v)}'`).join(" | ");
|
|
589
581
|
}
|
|
590
582
|
function generateTypeDeclarations(theme, options = {}) {
|
|
591
583
|
const { includeComments = true } = options;
|
|
@@ -989,6 +981,7 @@ const REVERSE_PROPERTY_MAP = {
|
|
|
989
981
|
bg: "bg",
|
|
990
982
|
"bg-clip": "bgClip",
|
|
991
983
|
"bg-origin": "bgOrigin",
|
|
984
|
+
"bg-size": "bgSize",
|
|
992
985
|
// Border Radius
|
|
993
986
|
rounded: "rounded",
|
|
994
987
|
"rounded-t": "roundedT",
|
|
@@ -1048,6 +1041,11 @@ const REVERSE_PROPERTY_MAP = {
|
|
|
1048
1041
|
// Space between
|
|
1049
1042
|
"space-x": "spaceX",
|
|
1050
1043
|
"space-y": "spaceY",
|
|
1044
|
+
// Logical margin / padding (block-start / block-end)
|
|
1045
|
+
mbs: "mbs",
|
|
1046
|
+
mbe: "mbe",
|
|
1047
|
+
pbs: "pbs",
|
|
1048
|
+
pbe: "pbe",
|
|
1051
1049
|
// Sizing
|
|
1052
1050
|
w: "w",
|
|
1053
1051
|
"min-w": "minW",
|
|
@@ -1056,6 +1054,15 @@ const REVERSE_PROPERTY_MAP = {
|
|
|
1056
1054
|
"min-h": "minH",
|
|
1057
1055
|
"max-h": "maxH",
|
|
1058
1056
|
size: "size",
|
|
1057
|
+
// Logical sizing (block-size / inline-size). The bare `block`/`inline` classes
|
|
1058
|
+
// are display values (BOOLEAN_VALUE_MAP wins via exact match first); only the
|
|
1059
|
+
// `block-*` / `inline-*` value forms route here.
|
|
1060
|
+
block: "blockSize",
|
|
1061
|
+
inline: "inlineSize",
|
|
1062
|
+
"min-block": "minBlockSize",
|
|
1063
|
+
"max-block": "maxBlockSize",
|
|
1064
|
+
"min-inline": "minInlineSize",
|
|
1065
|
+
"max-inline": "maxInlineSize",
|
|
1059
1066
|
// Layout
|
|
1060
1067
|
aspect: "aspect",
|
|
1061
1068
|
columns: "columns",
|
|
@@ -1079,6 +1086,11 @@ const REVERSE_PROPERTY_MAP = {
|
|
|
1079
1086
|
inset: "inset",
|
|
1080
1087
|
"inset-x": "insetX",
|
|
1081
1088
|
"inset-y": "insetY",
|
|
1089
|
+
// Logical inset sides (inset-s/e + block-start/block-end)
|
|
1090
|
+
"inset-s": "insetS",
|
|
1091
|
+
"inset-e": "insetE",
|
|
1092
|
+
"inset-bs": "insetBs",
|
|
1093
|
+
"inset-be": "insetBe",
|
|
1082
1094
|
top: "top",
|
|
1083
1095
|
right: "right",
|
|
1084
1096
|
bottom: "bottom",
|
|
@@ -1089,7 +1101,7 @@ const REVERSE_PROPERTY_MAP = {
|
|
|
1089
1101
|
// Typography (ambiguous — text-*, font-* disambiguated)
|
|
1090
1102
|
text: "color",
|
|
1091
1103
|
// default for text- prefix
|
|
1092
|
-
font: "
|
|
1104
|
+
font: "weight",
|
|
1093
1105
|
// default for font- prefix
|
|
1094
1106
|
decoration: "decoration",
|
|
1095
1107
|
// ambiguous
|
|
@@ -1146,6 +1158,8 @@ const REVERSE_PROPERTY_MAP = {
|
|
|
1146
1158
|
"mix-blend": "mixBlend",
|
|
1147
1159
|
"bg-blend": "bgBlend",
|
|
1148
1160
|
// Filters
|
|
1161
|
+
filter: "filter",
|
|
1162
|
+
"backdrop-filter": "backdropFilter",
|
|
1149
1163
|
blur: "blur",
|
|
1150
1164
|
brightness: "brightness",
|
|
1151
1165
|
contrast: "contrast",
|
|
@@ -1168,9 +1182,12 @@ const REVERSE_PROPERTY_MAP = {
|
|
|
1168
1182
|
scale: "scale",
|
|
1169
1183
|
"scale-x": "scaleX",
|
|
1170
1184
|
"scale-y": "scaleY",
|
|
1185
|
+
"scale-z": "scaleZ",
|
|
1171
1186
|
rotate: "rotate",
|
|
1187
|
+
translate: "translate",
|
|
1172
1188
|
"translate-x": "translateX",
|
|
1173
1189
|
"translate-y": "translateY",
|
|
1190
|
+
"translate-z": "translateZ",
|
|
1174
1191
|
"skew-x": "skewX",
|
|
1175
1192
|
"skew-y": "skewY",
|
|
1176
1193
|
origin: "origin",
|
|
@@ -1184,6 +1201,11 @@ const REVERSE_PROPERTY_MAP = {
|
|
|
1184
1201
|
cursor: "cursor",
|
|
1185
1202
|
caret: "caret",
|
|
1186
1203
|
"pointer-events": "pointerEvents",
|
|
1204
|
+
scheme: "scheme",
|
|
1205
|
+
tab: "tabSize",
|
|
1206
|
+
zoom: "zoom",
|
|
1207
|
+
scrollbar: "scrollbar",
|
|
1208
|
+
"scrollbar-gutter": "scrollbarGutter",
|
|
1187
1209
|
resize: "resize",
|
|
1188
1210
|
scroll: "scroll",
|
|
1189
1211
|
"scroll-m": "scrollM",
|
|
@@ -1221,6 +1243,8 @@ const REVERSE_PROPERTY_MAP = {
|
|
|
1221
1243
|
// Line clamp
|
|
1222
1244
|
"line-clamp": "lineClamp",
|
|
1223
1245
|
wrap: "wrap",
|
|
1246
|
+
// Typography plugin (bare `prose` is boolean; `prose-gray`/`prose-lg` carry a value)
|
|
1247
|
+
prose: "prose",
|
|
1224
1248
|
// Text shadow
|
|
1225
1249
|
"text-shadow": "textShadow",
|
|
1226
1250
|
// Gradient stops
|
|
@@ -1237,47 +1261,13 @@ const REVERSE_PROPERTY_MAP = {
|
|
|
1237
1261
|
backface: "backface"
|
|
1238
1262
|
};
|
|
1239
1263
|
const REVERSE_BOOLEAN_MAP = {
|
|
1240
|
-
//
|
|
1241
|
-
block: "block",
|
|
1242
|
-
inline: "inline",
|
|
1243
|
-
"inline-block": "inlineBlock",
|
|
1244
|
-
flex: "flex",
|
|
1245
|
-
"inline-flex": "inlineFlex",
|
|
1246
|
-
grid: "grid",
|
|
1247
|
-
"inline-grid": "inlineGrid",
|
|
1248
|
-
hidden: "hidden",
|
|
1249
|
-
contents: "contents",
|
|
1250
|
-
table: "table",
|
|
1251
|
-
"table-row": "tableRow",
|
|
1252
|
-
"table-cell": "tableCell",
|
|
1253
|
-
"flow-root": "flowRoot",
|
|
1254
|
-
"list-item": "listItem",
|
|
1255
|
-
// Position
|
|
1256
|
-
static: "static",
|
|
1257
|
-
fixed: "fixed",
|
|
1258
|
-
absolute: "absolute",
|
|
1259
|
-
relative: "relative",
|
|
1260
|
-
sticky: "sticky",
|
|
1261
|
-
// Visibility
|
|
1262
|
-
visible: "visible",
|
|
1263
|
-
invisible: "invisible",
|
|
1264
|
-
collapse: "collapse",
|
|
1265
|
-
// Typography
|
|
1264
|
+
// Typography (composite)
|
|
1266
1265
|
truncate: "truncate",
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
overline: "overline",
|
|
1273
|
-
"line-through": "lineThrough",
|
|
1274
|
-
"no-underline": "noUnderline",
|
|
1275
|
-
italic: "italic",
|
|
1276
|
-
"not-italic": "notItalic",
|
|
1277
|
-
antialiased: "antialiased",
|
|
1278
|
-
"subpixel-antialiased": "subpixelAntialiased",
|
|
1279
|
-
// Flexbox
|
|
1280
|
-
// flexWrap is string-based, not boolean — removed from boolean map
|
|
1266
|
+
// Flexbox (default-or-value: bare `grow`/`shrink` mean grow/shrink: true,
|
|
1267
|
+
// while grow-0/shrink-0 carry a value via REVERSE_PROPERTY_MAP).
|
|
1268
|
+
// flexWrap is string-based, not boolean — kept out of this map.
|
|
1269
|
+
grow: "grow",
|
|
1270
|
+
shrink: "shrink",
|
|
1281
1271
|
// Filters (defaults)
|
|
1282
1272
|
blur: "blur",
|
|
1283
1273
|
grayscale: "grayscale",
|
|
@@ -1290,6 +1280,10 @@ const REVERSE_BOOLEAN_MAP = {
|
|
|
1290
1280
|
// Misc
|
|
1291
1281
|
container: "container",
|
|
1292
1282
|
prose: "prose",
|
|
1283
|
+
// Bare `resize` (resize: both) and bare `shadow` (default elevation) are
|
|
1284
|
+
// default-or-value toggles, like ring/outline below.
|
|
1285
|
+
resize: "resize",
|
|
1286
|
+
shadow: "shadow",
|
|
1293
1287
|
"sr-only": "srOnly",
|
|
1294
1288
|
"not-sr-only": "notSrOnly",
|
|
1295
1289
|
isolate: "isolate",
|
|
@@ -1310,10 +1304,8 @@ const REVERSE_BOOLEAN_MAP = {
|
|
|
1310
1304
|
"inset-ring": "insetRing",
|
|
1311
1305
|
outline: "outline",
|
|
1312
1306
|
rounded: "rounded",
|
|
1313
|
-
// Transforms
|
|
1314
|
-
|
|
1315
|
-
"translate-3d": "translate",
|
|
1316
|
-
// transform-gpu/cpu/none use BOOLEAN_VALUE_MAP → { transform: 'gpu'/'cpu'/'none' }
|
|
1307
|
+
// Transforms — scale-3d/translate-3d carry the literal '3d' value via
|
|
1308
|
+
// BOOLEAN_VALUE_MAP, and transform-gpu/cpu/none → { transform: 'gpu'/'cpu'/'none' }.
|
|
1317
1309
|
// Font numeric
|
|
1318
1310
|
"normal-nums": "fontVariant",
|
|
1319
1311
|
"lining-nums": "fontVariant",
|
|
@@ -1376,10 +1368,94 @@ const BOOLEAN_VALUE_MAP = {
|
|
|
1376
1368
|
// Appearance
|
|
1377
1369
|
"appearance-none": { prop: "appearance", value: "none" },
|
|
1378
1370
|
"appearance-auto": { prop: "appearance", value: "auto" },
|
|
1371
|
+
// Isolation (bare `isolate` is in REVERSE_BOOLEAN_MAP; `isolation-auto` carries a value)
|
|
1372
|
+
"isolation-auto": { prop: "isolation", value: "auto", cssProperty: "isolation" },
|
|
1373
|
+
// Field sizing
|
|
1374
|
+
"field-sizing-content": { prop: "fieldSizing", value: "content", cssProperty: "field-sizing" },
|
|
1375
|
+
"field-sizing-fixed": { prop: "fieldSizing", value: "fixed", cssProperty: "field-sizing" },
|
|
1379
1376
|
// Transform
|
|
1380
1377
|
"transform-none": { prop: "transform", value: "none" },
|
|
1381
1378
|
"transform-gpu": { prop: "transform", value: "gpu" },
|
|
1382
|
-
"transform-cpu": { prop: "transform", value: "cpu" }
|
|
1379
|
+
"transform-cpu": { prop: "transform", value: "cpu" },
|
|
1380
|
+
// transform-style (3d / flat) — single CSS property, so fail-closed on conflict.
|
|
1381
|
+
"transform-3d": { prop: "transformStyle", value: "3d", cssProperty: "transform-style" },
|
|
1382
|
+
"transform-flat": { prop: "transformStyle", value: "flat", cssProperty: "transform-style" },
|
|
1383
|
+
// 3D scale/translate keyword shorthands carry the literal '3d' value.
|
|
1384
|
+
"scale-3d": { prop: "scale", value: "3d" },
|
|
1385
|
+
"translate-3d": { prop: "translate", value: "3d" },
|
|
1386
|
+
// Single-property utilities — migrated to their canonical { key: value }
|
|
1387
|
+
// form. The boolean-sugar aliases (flex/absolute/italic/...) were removed,
|
|
1388
|
+
// so these never emit `{ flex: true }`; one key per CSS property.
|
|
1389
|
+
// display
|
|
1390
|
+
block: { prop: "display", value: "block", cssProperty: "display" },
|
|
1391
|
+
inline: { prop: "display", value: "inline", cssProperty: "display" },
|
|
1392
|
+
"inline-block": { prop: "display", value: "inline-block", cssProperty: "display" },
|
|
1393
|
+
flex: { prop: "display", value: "flex", cssProperty: "display" },
|
|
1394
|
+
"inline-flex": { prop: "display", value: "inline-flex", cssProperty: "display" },
|
|
1395
|
+
grid: { prop: "display", value: "grid", cssProperty: "display" },
|
|
1396
|
+
"inline-grid": { prop: "display", value: "inline-grid", cssProperty: "display" },
|
|
1397
|
+
hidden: { prop: "display", value: "none", cssProperty: "display" },
|
|
1398
|
+
contents: { prop: "display", value: "contents", cssProperty: "display" },
|
|
1399
|
+
table: { prop: "display", value: "table", cssProperty: "display" },
|
|
1400
|
+
"inline-table": { prop: "display", value: "inline-table", cssProperty: "display" },
|
|
1401
|
+
"table-row": { prop: "display", value: "table-row", cssProperty: "display" },
|
|
1402
|
+
"table-row-group": { prop: "display", value: "table-row-group", cssProperty: "display" },
|
|
1403
|
+
"table-cell": { prop: "display", value: "table-cell", cssProperty: "display" },
|
|
1404
|
+
"table-caption": { prop: "display", value: "table-caption", cssProperty: "display" },
|
|
1405
|
+
"table-column": { prop: "display", value: "table-column", cssProperty: "display" },
|
|
1406
|
+
"table-column-group": {
|
|
1407
|
+
prop: "display",
|
|
1408
|
+
value: "table-column-group",
|
|
1409
|
+
cssProperty: "display"
|
|
1410
|
+
},
|
|
1411
|
+
"table-footer-group": {
|
|
1412
|
+
prop: "display",
|
|
1413
|
+
value: "table-footer-group",
|
|
1414
|
+
cssProperty: "display"
|
|
1415
|
+
},
|
|
1416
|
+
"table-header-group": {
|
|
1417
|
+
prop: "display",
|
|
1418
|
+
value: "table-header-group",
|
|
1419
|
+
cssProperty: "display"
|
|
1420
|
+
},
|
|
1421
|
+
"flow-root": { prop: "display", value: "flow-root", cssProperty: "display" },
|
|
1422
|
+
"list-item": { prop: "display", value: "list-item", cssProperty: "display" },
|
|
1423
|
+
// position
|
|
1424
|
+
static: { prop: "position", value: "static", cssProperty: "position" },
|
|
1425
|
+
fixed: { prop: "position", value: "fixed", cssProperty: "position" },
|
|
1426
|
+
absolute: { prop: "position", value: "absolute", cssProperty: "position" },
|
|
1427
|
+
relative: { prop: "position", value: "relative", cssProperty: "position" },
|
|
1428
|
+
sticky: { prop: "position", value: "sticky", cssProperty: "position" },
|
|
1429
|
+
// visibility
|
|
1430
|
+
visible: { prop: "visibility", value: "visible", cssProperty: "visibility" },
|
|
1431
|
+
invisible: { prop: "visibility", value: "hidden", cssProperty: "visibility" },
|
|
1432
|
+
collapse: { prop: "visibility", value: "collapse", cssProperty: "visibility" },
|
|
1433
|
+
// isolation
|
|
1434
|
+
isolate: { prop: "isolation", value: "isolate", cssProperty: "isolation" },
|
|
1435
|
+
// text-transform
|
|
1436
|
+
uppercase: { prop: "textTransform", value: "uppercase", cssProperty: "text-transform" },
|
|
1437
|
+
lowercase: { prop: "textTransform", value: "lowercase", cssProperty: "text-transform" },
|
|
1438
|
+
capitalize: { prop: "textTransform", value: "capitalize", cssProperty: "text-transform" },
|
|
1439
|
+
"normal-case": { prop: "textTransform", value: "none", cssProperty: "text-transform" },
|
|
1440
|
+
// font-style
|
|
1441
|
+
italic: { prop: "fontStyle", value: "italic", cssProperty: "font-style" },
|
|
1442
|
+
"not-italic": { prop: "fontStyle", value: "normal", cssProperty: "font-style" },
|
|
1443
|
+
// text-decoration-line
|
|
1444
|
+
underline: { prop: "decoration", value: "underline", cssProperty: "text-decoration-line" },
|
|
1445
|
+
overline: { prop: "decoration", value: "overline", cssProperty: "text-decoration-line" },
|
|
1446
|
+
"line-through": {
|
|
1447
|
+
prop: "decoration",
|
|
1448
|
+
value: "line-through",
|
|
1449
|
+
cssProperty: "text-decoration-line"
|
|
1450
|
+
},
|
|
1451
|
+
"no-underline": { prop: "decoration", value: "none", cssProperty: "text-decoration-line" },
|
|
1452
|
+
// font-smoothing
|
|
1453
|
+
antialiased: { prop: "fontSmoothing", value: "grayscale", cssProperty: "font-smoothing" },
|
|
1454
|
+
"subpixel-antialiased": {
|
|
1455
|
+
prop: "fontSmoothing",
|
|
1456
|
+
value: "subpixel",
|
|
1457
|
+
cssProperty: "font-smoothing"
|
|
1458
|
+
}
|
|
1383
1459
|
};
|
|
1384
1460
|
const SORTED_PREFIXES = Object.keys(REVERSE_PROPERTY_MAP).sort((a, b) => {
|
|
1385
1461
|
if (b.length !== a.length) {
|
|
@@ -1406,6 +1482,13 @@ const NEGATIVE_ALLOWED = /* @__PURE__ */ new Set([
|
|
|
1406
1482
|
"inset-y",
|
|
1407
1483
|
"start",
|
|
1408
1484
|
"end",
|
|
1485
|
+
"inset-s",
|
|
1486
|
+
"inset-e",
|
|
1487
|
+
"inset-bs",
|
|
1488
|
+
"inset-be",
|
|
1489
|
+
"mbs",
|
|
1490
|
+
"mbe",
|
|
1491
|
+
"translate",
|
|
1409
1492
|
"z",
|
|
1410
1493
|
"order",
|
|
1411
1494
|
"col",
|
|
@@ -1431,7 +1514,10 @@ const NEGATIVE_ALLOWED = /* @__PURE__ */ new Set([
|
|
|
1431
1514
|
"scroll-mb",
|
|
1432
1515
|
"scroll-ml",
|
|
1433
1516
|
"hue-rotate",
|
|
1434
|
-
"backdrop-hue-rotate"
|
|
1517
|
+
"backdrop-hue-rotate",
|
|
1518
|
+
// mask gradient direction carries a leading `-` as part of the value
|
|
1519
|
+
// (e.g. -mask-linear-45 → { mask: '-linear-45' }), not a numeric negation.
|
|
1520
|
+
"mask"
|
|
1435
1521
|
]);
|
|
1436
1522
|
const FRACTION_SUPPORTED = /* @__PURE__ */ new Set([
|
|
1437
1523
|
"w",
|
|
@@ -1451,8 +1537,14 @@ const FRACTION_SUPPORTED = /* @__PURE__ */ new Set([
|
|
|
1451
1537
|
"left",
|
|
1452
1538
|
"start",
|
|
1453
1539
|
"end",
|
|
1540
|
+
"inset-s",
|
|
1541
|
+
"inset-e",
|
|
1542
|
+
"inset-bs",
|
|
1543
|
+
"inset-be",
|
|
1454
1544
|
"translate-x",
|
|
1455
|
-
"translate-y"
|
|
1545
|
+
"translate-y",
|
|
1546
|
+
"translate",
|
|
1547
|
+
"aspect"
|
|
1456
1548
|
]);
|
|
1457
1549
|
const SPACING_PROPS = /* @__PURE__ */ new Set([
|
|
1458
1550
|
"p",
|
|
@@ -1516,7 +1608,25 @@ const SPACING_PROPS = /* @__PURE__ */ new Set([
|
|
|
1516
1608
|
"scroll-pe",
|
|
1517
1609
|
"border-spacing",
|
|
1518
1610
|
"translate-x",
|
|
1519
|
-
"translate-y"
|
|
1611
|
+
"translate-y",
|
|
1612
|
+
"translate-z",
|
|
1613
|
+
"translate",
|
|
1614
|
+
// Logical sizing accepts the spacing/sizing scale (block-4, inline-full, …)
|
|
1615
|
+
"block",
|
|
1616
|
+
"inline",
|
|
1617
|
+
"min-block",
|
|
1618
|
+
"max-block",
|
|
1619
|
+
"min-inline",
|
|
1620
|
+
"max-inline",
|
|
1621
|
+
// Logical inset sides + block-axis margin/padding
|
|
1622
|
+
"inset-s",
|
|
1623
|
+
"inset-e",
|
|
1624
|
+
"inset-bs",
|
|
1625
|
+
"inset-be",
|
|
1626
|
+
"mbs",
|
|
1627
|
+
"mbe",
|
|
1628
|
+
"pbs",
|
|
1629
|
+
"pbe"
|
|
1520
1630
|
]);
|
|
1521
1631
|
const TEXT_SIZE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
1522
1632
|
"xs",
|
|
@@ -1600,7 +1710,28 @@ const OBJECT_POSITION_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
1600
1710
|
"right-top",
|
|
1601
1711
|
"right-bottom"
|
|
1602
1712
|
]);
|
|
1603
|
-
const SHADOW_SIZE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
1713
|
+
const SHADOW_SIZE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
1714
|
+
"2xs",
|
|
1715
|
+
"xs",
|
|
1716
|
+
"sm",
|
|
1717
|
+
"md",
|
|
1718
|
+
"lg",
|
|
1719
|
+
"xl",
|
|
1720
|
+
"2xl",
|
|
1721
|
+
"inner",
|
|
1722
|
+
"none"
|
|
1723
|
+
]);
|
|
1724
|
+
const ALIGN_CONTENT_KEYWORDS = /* @__PURE__ */ new Set([
|
|
1725
|
+
"normal",
|
|
1726
|
+
"center",
|
|
1727
|
+
"start",
|
|
1728
|
+
"end",
|
|
1729
|
+
"between",
|
|
1730
|
+
"around",
|
|
1731
|
+
"evenly",
|
|
1732
|
+
"baseline",
|
|
1733
|
+
"stretch"
|
|
1734
|
+
]);
|
|
1604
1735
|
const OUTLINE_STYLE_KEYWORDS = /* @__PURE__ */ new Set(["none", "dashed", "dotted", "double"]);
|
|
1605
1736
|
const DECORATION_STYLE_KEYWORDS = /* @__PURE__ */ new Set(["solid", "double", "dotted", "dashed", "wavy"]);
|
|
1606
1737
|
const DECORATION_THICKNESS_KEYWORDS = /* @__PURE__ */ new Set([
|
|
@@ -1730,7 +1861,13 @@ function parseClass(cls, options = {}) {
|
|
|
1730
1861
|
negative = true;
|
|
1731
1862
|
negInput = input.slice(1);
|
|
1732
1863
|
}
|
|
1733
|
-
|
|
1864
|
+
if (input === "@container") {
|
|
1865
|
+
return { prop: "@container", value: true };
|
|
1866
|
+
}
|
|
1867
|
+
if (input.startsWith("@container/")) {
|
|
1868
|
+
return { prop: "@container", value: input.slice("@container/".length) };
|
|
1869
|
+
}
|
|
1870
|
+
const boolResult = tryBooleanMatch(input);
|
|
1734
1871
|
if (boolResult) {
|
|
1735
1872
|
return applyImportant(boolResult, important);
|
|
1736
1873
|
}
|
|
@@ -1746,7 +1883,10 @@ function parseClass(cls, options = {}) {
|
|
|
1746
1883
|
continue;
|
|
1747
1884
|
}
|
|
1748
1885
|
if (REVERSE_BOOLEAN_MAP[source]) {
|
|
1749
|
-
return applyImportant(
|
|
1886
|
+
return applyImportant(
|
|
1887
|
+
{ prop: REVERSE_BOOLEAN_MAP[source], value: true },
|
|
1888
|
+
important
|
|
1889
|
+
);
|
|
1750
1890
|
}
|
|
1751
1891
|
if (prefix === "divide-x" || prefix === "divide-y") {
|
|
1752
1892
|
return applyImportant({ prop, value: true }, important);
|
|
@@ -1785,10 +1925,6 @@ function parseClass(cls, options = {}) {
|
|
|
1785
1925
|
}
|
|
1786
1926
|
}
|
|
1787
1927
|
}
|
|
1788
|
-
const displayResult = tryDisplay(input, options);
|
|
1789
|
-
if (displayResult) {
|
|
1790
|
-
return applyImportant(displayResult, important);
|
|
1791
|
-
}
|
|
1792
1928
|
if (input.startsWith("[") && input.endsWith("]") && input.includes(":")) {
|
|
1793
1929
|
const inner = input.slice(1, -1);
|
|
1794
1930
|
if (inner.startsWith("--")) {
|
|
@@ -1808,72 +1944,28 @@ function applyImportant(result, important) {
|
|
|
1808
1944
|
if (!important) {
|
|
1809
1945
|
return result;
|
|
1810
1946
|
}
|
|
1947
|
+
const base = result.cssProperty ? { cssProperty: result.cssProperty } : {};
|
|
1811
1948
|
if (typeof result.value === "string") {
|
|
1812
|
-
return { prop: result.prop, value: `${result.value}!` };
|
|
1949
|
+
return { ...base, prop: result.prop, value: `${result.value}!` };
|
|
1813
1950
|
}
|
|
1814
1951
|
if (typeof result.value === "boolean") {
|
|
1815
|
-
return { prop: result.prop, value: "!" };
|
|
1952
|
+
return { ...base, prop: result.prop, value: "!" };
|
|
1816
1953
|
}
|
|
1817
1954
|
if (typeof result.value === "number") {
|
|
1818
|
-
return { prop: result.prop, value: `${String(result.value)}!` };
|
|
1955
|
+
return { ...base, prop: result.prop, value: `${String(result.value)}!` };
|
|
1819
1956
|
}
|
|
1820
1957
|
return result;
|
|
1821
1958
|
}
|
|
1822
|
-
function tryBooleanMatch(cls
|
|
1959
|
+
function tryBooleanMatch(cls) {
|
|
1823
1960
|
if (BOOLEAN_VALUE_MAP[cls]) {
|
|
1824
|
-
const { prop, value } = BOOLEAN_VALUE_MAP[cls];
|
|
1825
|
-
return { prop, value };
|
|
1961
|
+
const { prop, value, cssProperty } = BOOLEAN_VALUE_MAP[cls];
|
|
1962
|
+
return cssProperty ? { prop, value, cssProperty } : { prop, value };
|
|
1826
1963
|
}
|
|
1827
1964
|
if (REVERSE_BOOLEAN_MAP[cls]) {
|
|
1828
|
-
return
|
|
1965
|
+
return { prop: REVERSE_BOOLEAN_MAP[cls], value: true };
|
|
1829
1966
|
}
|
|
1830
1967
|
return null;
|
|
1831
1968
|
}
|
|
1832
|
-
function tryDisplay(cls, options) {
|
|
1833
|
-
const displayValues = /* @__PURE__ */ new Set([
|
|
1834
|
-
"block",
|
|
1835
|
-
"inline",
|
|
1836
|
-
"inline-block",
|
|
1837
|
-
"flex",
|
|
1838
|
-
"inline-flex",
|
|
1839
|
-
"grid",
|
|
1840
|
-
"inline-grid",
|
|
1841
|
-
"hidden",
|
|
1842
|
-
"contents",
|
|
1843
|
-
"table",
|
|
1844
|
-
"table-row",
|
|
1845
|
-
"table-cell",
|
|
1846
|
-
"flow-root",
|
|
1847
|
-
"list-item"
|
|
1848
|
-
]);
|
|
1849
|
-
if (displayValues.has(cls)) {
|
|
1850
|
-
return REVERSE_BOOLEAN_MAP[cls] ? booleanClassToParsed(cls, options) : null;
|
|
1851
|
-
}
|
|
1852
|
-
return null;
|
|
1853
|
-
}
|
|
1854
|
-
function booleanClassToParsed(cls, options) {
|
|
1855
|
-
const displayValue = DISPLAY_CLASS_VALUES[cls];
|
|
1856
|
-
if (options.display === "canonical" && displayValue) {
|
|
1857
|
-
return { prop: "display", value: displayValue, cssProperty: "display" };
|
|
1858
|
-
}
|
|
1859
|
-
return { prop: REVERSE_BOOLEAN_MAP[cls], value: true };
|
|
1860
|
-
}
|
|
1861
|
-
const DISPLAY_CLASS_VALUES = {
|
|
1862
|
-
block: "block",
|
|
1863
|
-
inline: "inline",
|
|
1864
|
-
"inline-block": "inline-block",
|
|
1865
|
-
flex: "flex",
|
|
1866
|
-
"inline-flex": "inline-flex",
|
|
1867
|
-
grid: "grid",
|
|
1868
|
-
"inline-grid": "inline-grid",
|
|
1869
|
-
hidden: "none",
|
|
1870
|
-
contents: "contents",
|
|
1871
|
-
table: "table",
|
|
1872
|
-
"table-row": "table-row",
|
|
1873
|
-
"table-cell": "table-cell",
|
|
1874
|
-
"flow-root": "flow-root",
|
|
1875
|
-
"list-item": "list-item"
|
|
1876
|
-
};
|
|
1877
1969
|
function tryGradient(cls, negative) {
|
|
1878
1970
|
let input = cls;
|
|
1879
1971
|
let type = null;
|
|
@@ -1999,12 +2091,18 @@ function disambiguate(prefix, value, negative) {
|
|
|
1999
2091
|
return disambiguateInsetShadow(value);
|
|
2000
2092
|
case "stroke":
|
|
2001
2093
|
return disambiguateStroke(value);
|
|
2094
|
+
case "from":
|
|
2095
|
+
case "via":
|
|
2096
|
+
case "to":
|
|
2097
|
+
return disambiguateGradientStop(prefix, value);
|
|
2002
2098
|
case "list":
|
|
2003
2099
|
return disambiguateList(value);
|
|
2004
2100
|
case "ease":
|
|
2005
2101
|
return { prop: "ease", value: parseValue("ease", value, negative) };
|
|
2006
2102
|
case "snap":
|
|
2007
2103
|
return disambiguateSnap();
|
|
2104
|
+
case "content":
|
|
2105
|
+
return disambiguateContent(value);
|
|
2008
2106
|
case "flex":
|
|
2009
2107
|
return disambiguateFlex(value);
|
|
2010
2108
|
case "table":
|
|
@@ -2045,17 +2143,17 @@ function disambiguateText(value) {
|
|
|
2045
2143
|
}
|
|
2046
2144
|
function disambiguateFont(value) {
|
|
2047
2145
|
if (FONT_WEIGHT_KEYWORDS.has(value)) {
|
|
2048
|
-
return { prop: "
|
|
2146
|
+
return { prop: "weight", value };
|
|
2049
2147
|
}
|
|
2050
2148
|
if (/^\d{3}$/.test(value)) {
|
|
2051
|
-
return { prop: "
|
|
2149
|
+
return { prop: "weight", value: parseInt(value, 10) };
|
|
2052
2150
|
}
|
|
2053
2151
|
if (FONT_FAMILY_KEYWORDS.has(value)) {
|
|
2054
2152
|
return { prop: "fontFamily", value };
|
|
2055
2153
|
}
|
|
2056
2154
|
if (value.startsWith("stretch-")) {
|
|
2057
2155
|
const stretchVal = value.slice("stretch-".length);
|
|
2058
|
-
return { prop: "fontStretch", value: stretchVal };
|
|
2156
|
+
return { prop: "fontStretch", value: parseStringValue(stretchVal) };
|
|
2059
2157
|
}
|
|
2060
2158
|
if (FONT_STRETCH_KEYWORDS.has(value)) {
|
|
2061
2159
|
return { prop: "fontStretch", value };
|
|
@@ -2087,6 +2185,12 @@ function disambiguateBg(value) {
|
|
|
2087
2185
|
if (BG_ATTACHMENT_KEYWORDS.has(value)) {
|
|
2088
2186
|
return { prop: "bgAttach", value };
|
|
2089
2187
|
}
|
|
2188
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
2189
|
+
const inner = value.slice(1, -1).replace(/_/g, " ");
|
|
2190
|
+
if (inner.includes(" ") && BG_POSITION_KEYWORDS.has(inner.split(" ")[0])) {
|
|
2191
|
+
return { prop: "bgPos", value: inner };
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2090
2194
|
if (value === "none") {
|
|
2091
2195
|
return { prop: "bgImg", value: "none" };
|
|
2092
2196
|
}
|
|
@@ -2105,6 +2209,13 @@ function disambiguateShadow(value) {
|
|
|
2105
2209
|
if (SHADOW_SIZE_KEYWORDS.has(value)) {
|
|
2106
2210
|
return { prop: "shadow", value };
|
|
2107
2211
|
}
|
|
2212
|
+
if (value.startsWith("(") && value.endsWith(")")) {
|
|
2213
|
+
const inner = value.slice(1, -1);
|
|
2214
|
+
if (inner.startsWith("color:")) {
|
|
2215
|
+
return { prop: "shadowColor", value: inner.slice("color:".length) };
|
|
2216
|
+
}
|
|
2217
|
+
return { prop: "shadow", value: inner };
|
|
2218
|
+
}
|
|
2108
2219
|
return { prop: "shadowColor", value: parseStringValue(value) };
|
|
2109
2220
|
}
|
|
2110
2221
|
function disambiguateOutline(value) {
|
|
@@ -2125,12 +2236,11 @@ function disambiguateDecoration(value) {
|
|
|
2125
2236
|
return { prop: "decorationStyle", value };
|
|
2126
2237
|
}
|
|
2127
2238
|
if (DECORATION_THICKNESS_KEYWORDS.has(value)) {
|
|
2128
|
-
const num = Number(value);
|
|
2129
|
-
if (!Number.isNaN(num)) {
|
|
2130
|
-
return { prop: "decorationThickness", value };
|
|
2131
|
-
}
|
|
2132
2239
|
return { prop: "decorationThickness", value };
|
|
2133
2240
|
}
|
|
2241
|
+
if (isArbitraryDimension(value) || value.startsWith("(") && value.endsWith(")")) {
|
|
2242
|
+
return { prop: "decorationThickness", value: parseStringValue(value) };
|
|
2243
|
+
}
|
|
2134
2244
|
return { prop: "decorationColor", value: parseStringValue(value) };
|
|
2135
2245
|
}
|
|
2136
2246
|
function disambiguateRing(value, negative) {
|
|
@@ -2175,8 +2285,18 @@ function disambiguateStroke(value) {
|
|
|
2175
2285
|
if (!Number.isNaN(num) && Number.isInteger(num)) {
|
|
2176
2286
|
return { prop: "strokeWidth", value: num };
|
|
2177
2287
|
}
|
|
2288
|
+
if (isArbitraryDimension(value)) {
|
|
2289
|
+
return { prop: "strokeWidth", value: parseStringValue(value) };
|
|
2290
|
+
}
|
|
2178
2291
|
return { prop: "stroke", value: parseStringValue(value) };
|
|
2179
2292
|
}
|
|
2293
|
+
function disambiguateGradientStop(prefix, value) {
|
|
2294
|
+
const posKey = prefix === "from" ? "fromPos" : prefix === "via" ? "viaPos" : "toPos";
|
|
2295
|
+
if (/^\d+(\.\d+)?%$/.test(value) || /^\d+$/.test(value) || isArbitraryDimension(value)) {
|
|
2296
|
+
return { prop: posKey, value: parseStringValue(value) };
|
|
2297
|
+
}
|
|
2298
|
+
return { prop: prefix, value: parseStringValue(value) };
|
|
2299
|
+
}
|
|
2180
2300
|
function disambiguateTransition(value) {
|
|
2181
2301
|
if (TRANSITION_PROPERTY_KEYWORDS.has(value)) {
|
|
2182
2302
|
return { prop: "transition", value };
|
|
@@ -2192,6 +2312,12 @@ function disambiguateList(value) {
|
|
|
2192
2312
|
function disambiguateSnap(_value) {
|
|
2193
2313
|
return null;
|
|
2194
2314
|
}
|
|
2315
|
+
function disambiguateContent(value) {
|
|
2316
|
+
if (ALIGN_CONTENT_KEYWORDS.has(value)) {
|
|
2317
|
+
return { prop: "alignContent", value };
|
|
2318
|
+
}
|
|
2319
|
+
return { prop: "content", value: parseValue("content", value, false) };
|
|
2320
|
+
}
|
|
2195
2321
|
function disambiguateFlex(value) {
|
|
2196
2322
|
const dirValues = /* @__PURE__ */ new Set(["row", "col", "row-reverse", "col-reverse"]);
|
|
2197
2323
|
if (dirValues.has(value)) {
|
|
@@ -2251,6 +2377,8 @@ function isValidSpacingValue(value) {
|
|
|
2251
2377
|
"lvh",
|
|
2252
2378
|
"lvw",
|
|
2253
2379
|
// Max-width size keywords
|
|
2380
|
+
"3xs",
|
|
2381
|
+
"2xs",
|
|
2254
2382
|
"xs",
|
|
2255
2383
|
"sm",
|
|
2256
2384
|
"md",
|
|
@@ -2300,7 +2428,7 @@ function parseValue(prefix, value, negative) {
|
|
|
2300
2428
|
return inner;
|
|
2301
2429
|
}
|
|
2302
2430
|
if (FRACTION_SUPPORTED.has(prefix) && /^\d+\/\d+$/.test(value)) {
|
|
2303
|
-
return value;
|
|
2431
|
+
return negative ? `-${value}` : value;
|
|
2304
2432
|
}
|
|
2305
2433
|
if (value === "px") {
|
|
2306
2434
|
return negative ? "-px" : "px";
|
|
@@ -2309,7 +2437,7 @@ function parseValue(prefix, value, negative) {
|
|
|
2309
2437
|
return "auto";
|
|
2310
2438
|
}
|
|
2311
2439
|
if (value === "full") {
|
|
2312
|
-
return "full";
|
|
2440
|
+
return negative ? "-full" : "full";
|
|
2313
2441
|
}
|
|
2314
2442
|
if (value === "screen") {
|
|
2315
2443
|
return "screen";
|
|
@@ -2627,7 +2755,7 @@ function parseClassTokenCached(token) {
|
|
|
2627
2755
|
}
|
|
2628
2756
|
function parseClassToken(token) {
|
|
2629
2757
|
const { variantParts, baseClass } = extractVariants(token);
|
|
2630
|
-
const parsed = parseClass(baseClass, {
|
|
2758
|
+
const parsed = parseClass(baseClass, { });
|
|
2631
2759
|
if (!parsed) {
|
|
2632
2760
|
return null;
|
|
2633
2761
|
}
|
|
@@ -3087,18 +3215,77 @@ function isAstNode(value) {
|
|
|
3087
3215
|
function isClassNameJsxAttribute(node) {
|
|
3088
3216
|
return t.isJSXAttribute(node) && t.isJSXIdentifier(node.name) && node.name.name === "className";
|
|
3089
3217
|
}
|
|
3218
|
+
function isCleanCanonicalTarget(target) {
|
|
3219
|
+
return /^[a-z][a-z0-9]*$/i.test(target);
|
|
3220
|
+
}
|
|
3221
|
+
function normalizeSzObject(obj, replacements) {
|
|
3222
|
+
let count = 0;
|
|
3223
|
+
for (const prop of obj.properties) {
|
|
3224
|
+
if (!t.isObjectProperty(prop) || prop.computed) {
|
|
3225
|
+
continue;
|
|
3226
|
+
}
|
|
3227
|
+
const key = prop.key;
|
|
3228
|
+
let keyName = null;
|
|
3229
|
+
if (t.isIdentifier(key)) {
|
|
3230
|
+
keyName = key.name;
|
|
3231
|
+
} else if (t.isStringLiteral(key)) {
|
|
3232
|
+
keyName = key.value;
|
|
3233
|
+
}
|
|
3234
|
+
if (keyName === null) {
|
|
3235
|
+
continue;
|
|
3236
|
+
}
|
|
3237
|
+
const sugar = REMOVED_BOOLEAN_SUGAR[keyName];
|
|
3238
|
+
if (sugar && t.isBooleanLiteral(prop.value) && prop.value.value === true && prop.start != null && prop.end != null) {
|
|
3239
|
+
replacements.push({
|
|
3240
|
+
start: prop.start,
|
|
3241
|
+
end: prop.end,
|
|
3242
|
+
text: `${sugar.key}: '${sugar.value}'`
|
|
3243
|
+
});
|
|
3244
|
+
count++;
|
|
3245
|
+
continue;
|
|
3246
|
+
}
|
|
3247
|
+
const suggestion = SUGGESTION_MAP[keyName];
|
|
3248
|
+
if (suggestion && isCleanCanonicalTarget(suggestion) && suggestion !== keyName && key.start != null && key.end != null) {
|
|
3249
|
+
replacements.push({
|
|
3250
|
+
start: key.start,
|
|
3251
|
+
end: key.end,
|
|
3252
|
+
text: t.isStringLiteral(key) ? `'${suggestion}'` : suggestion
|
|
3253
|
+
});
|
|
3254
|
+
count++;
|
|
3255
|
+
}
|
|
3256
|
+
if (t.isObjectExpression(prop.value)) {
|
|
3257
|
+
count += normalizeSzObject(prop.value, replacements);
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
return count;
|
|
3261
|
+
}
|
|
3090
3262
|
function transformSource(source, filePath, options = {}) {
|
|
3091
3263
|
const warnings = [];
|
|
3092
3264
|
let classNamesTransformed = 0;
|
|
3093
3265
|
let classNamesSkipped = 0;
|
|
3094
3266
|
let classNamesSkippedComponent = 0;
|
|
3267
|
+
let szKeysNormalized = 0;
|
|
3095
3268
|
const classesUnrecognized = [];
|
|
3096
3269
|
const replacements = [];
|
|
3097
3270
|
const clsxImportNames = /* @__PURE__ */ new Set();
|
|
3098
3271
|
let clsxUsedOutsideClassName = false;
|
|
3099
3272
|
const clsxCallsitesMigrated = /* @__PURE__ */ new Set();
|
|
3100
3273
|
let hasCvaImport = false;
|
|
3101
|
-
if (
|
|
3274
|
+
if (options.keysOnly && source.indexOf("sz=") === -1) {
|
|
3275
|
+
return {
|
|
3276
|
+
code: source,
|
|
3277
|
+
changed: false,
|
|
3278
|
+
warnings: [],
|
|
3279
|
+
stats: {
|
|
3280
|
+
classNamesTransformed: 0,
|
|
3281
|
+
classNamesSkipped: 0,
|
|
3282
|
+
classNamesSkippedComponent: 0,
|
|
3283
|
+
classesUnrecognized: []
|
|
3284
|
+
},
|
|
3285
|
+
potentiallyUnusedImports: []
|
|
3286
|
+
};
|
|
3287
|
+
}
|
|
3288
|
+
if (source.indexOf("className") === -1 && source.indexOf("cva") === -1 && source.indexOf("sz=") === -1) {
|
|
3102
3289
|
return {
|
|
3103
3290
|
code: source,
|
|
3104
3291
|
changed: false,
|
|
@@ -3160,6 +3347,16 @@ function transformSource(source, filePath, options = {}) {
|
|
|
3160
3347
|
},
|
|
3161
3348
|
JSXAttribute(node, parent) {
|
|
3162
3349
|
const attrName = node.name;
|
|
3350
|
+
if (t.isJSXIdentifier(attrName) && attrName.name === "sz") {
|
|
3351
|
+
const szValue = node.value;
|
|
3352
|
+
if (t.isJSXExpressionContainer(szValue) && t.isObjectExpression(szValue.expression)) {
|
|
3353
|
+
szKeysNormalized += normalizeSzObject(szValue.expression, replacements);
|
|
3354
|
+
}
|
|
3355
|
+
return;
|
|
3356
|
+
}
|
|
3357
|
+
if (options.keysOnly) {
|
|
3358
|
+
return;
|
|
3359
|
+
}
|
|
3163
3360
|
if (!t.isJSXIdentifier(attrName) || attrName.name !== "className") {
|
|
3164
3361
|
return;
|
|
3165
3362
|
}
|
|
@@ -3324,7 +3521,8 @@ function transformSource(source, filePath, options = {}) {
|
|
|
3324
3521
|
classNamesTransformed,
|
|
3325
3522
|
classNamesSkipped,
|
|
3326
3523
|
classNamesSkippedComponent,
|
|
3327
|
-
classesUnrecognized
|
|
3524
|
+
classesUnrecognized,
|
|
3525
|
+
szKeysNormalized
|
|
3328
3526
|
},
|
|
3329
3527
|
potentiallyUnusedImports
|
|
3330
3528
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@csszyx/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Command-line tools for csszyx",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"csszyx",
|
|
@@ -49,8 +49,9 @@
|
|
|
49
49
|
"picocolors": "^1.0.0",
|
|
50
50
|
"prompts": "^2.4.2",
|
|
51
51
|
"tailwindcss": "^3.4.1",
|
|
52
|
-
"@csszyx/
|
|
53
|
-
"@csszyx/unplugin": "0.
|
|
52
|
+
"@csszyx/compiler": "0.10.1",
|
|
53
|
+
"@csszyx/unplugin": "0.10.1",
|
|
54
|
+
"@csszyx/types": "0.10.1"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
56
57
|
"@types/fs-extra": "^11.0.4",
|