@csszyx/compiler 0.10.8 → 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/index.cjs +222 -6
- package/dist/index.d.cts +23 -1
- package/dist/index.d.mts +23 -1
- package/dist/index.mjs +222 -7
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -390,6 +390,17 @@ function transformSourceCode(source, filename, options) {
|
|
|
390
390
|
transformed = true;
|
|
391
391
|
return;
|
|
392
392
|
}
|
|
393
|
+
const hoistedNested = tryHoistNestedConditional(
|
|
394
|
+
flatExpression,
|
|
395
|
+
getBinding
|
|
396
|
+
);
|
|
397
|
+
if (hoistedNested !== null) {
|
|
398
|
+
path.node.name.name = "className";
|
|
399
|
+
path.node.value = createMergedClassNameValue(hoistedNested);
|
|
400
|
+
collectFromExpr(hoistedNested, collectedClasses);
|
|
401
|
+
transformed = true;
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
393
404
|
const partial = evaluatePartialObject$1(flatExpression);
|
|
394
405
|
if (partial !== null && !partial.hasSpread && (partial.dynamicProps.size > 0 || partial.conditionalClasses.length > 0)) {
|
|
395
406
|
const staticClasses = [];
|
|
@@ -878,6 +889,101 @@ function tryStaticTransformNode(node, getBinding) {
|
|
|
878
889
|
}
|
|
879
890
|
return null;
|
|
880
891
|
}
|
|
892
|
+
function scanNestedConditionals(node) {
|
|
893
|
+
let topLevel = 0;
|
|
894
|
+
let nested = 0;
|
|
895
|
+
let test = null;
|
|
896
|
+
for (const prop of node.properties) {
|
|
897
|
+
if (!t__namespace.isObjectProperty(prop)) {
|
|
898
|
+
continue;
|
|
899
|
+
}
|
|
900
|
+
const value = prop.value;
|
|
901
|
+
if (t__namespace.isConditionalExpression(value)) {
|
|
902
|
+
topLevel++;
|
|
903
|
+
} else if (t__namespace.isObjectExpression(value)) {
|
|
904
|
+
nested += countAllConditionals(value);
|
|
905
|
+
test ??= firstConditionalTest(value);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
return { topLevel, nested, test };
|
|
909
|
+
}
|
|
910
|
+
function countAllConditionals(node) {
|
|
911
|
+
let count = 0;
|
|
912
|
+
for (const prop of node.properties) {
|
|
913
|
+
if (!t__namespace.isObjectProperty(prop)) {
|
|
914
|
+
continue;
|
|
915
|
+
}
|
|
916
|
+
const value = prop.value;
|
|
917
|
+
if (t__namespace.isConditionalExpression(value)) {
|
|
918
|
+
count++;
|
|
919
|
+
} else if (t__namespace.isObjectExpression(value)) {
|
|
920
|
+
count += countAllConditionals(value);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
return count;
|
|
924
|
+
}
|
|
925
|
+
function firstConditionalTest(node) {
|
|
926
|
+
for (const prop of node.properties) {
|
|
927
|
+
if (!t__namespace.isObjectProperty(prop)) {
|
|
928
|
+
continue;
|
|
929
|
+
}
|
|
930
|
+
const value = prop.value;
|
|
931
|
+
if (t__namespace.isConditionalExpression(value)) {
|
|
932
|
+
return value.test;
|
|
933
|
+
}
|
|
934
|
+
if (t__namespace.isObjectExpression(value)) {
|
|
935
|
+
const inner = firstConditionalTest(value);
|
|
936
|
+
if (inner) {
|
|
937
|
+
return inner;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
return null;
|
|
942
|
+
}
|
|
943
|
+
function cloneObjectPickingBranch(node, pick) {
|
|
944
|
+
return t__namespace.objectExpression(
|
|
945
|
+
node.properties.map((prop) => {
|
|
946
|
+
if (!t__namespace.isObjectProperty(prop)) {
|
|
947
|
+
return t__namespace.cloneNode(prop);
|
|
948
|
+
}
|
|
949
|
+
const value = prop.value;
|
|
950
|
+
let nextValue = t__namespace.cloneNode(value);
|
|
951
|
+
if (t__namespace.isConditionalExpression(value)) {
|
|
952
|
+
nextValue = t__namespace.cloneNode(value[pick]);
|
|
953
|
+
} else if (t__namespace.isObjectExpression(value)) {
|
|
954
|
+
nextValue = cloneObjectPickingBranch(value, pick);
|
|
955
|
+
}
|
|
956
|
+
return t__namespace.objectProperty(
|
|
957
|
+
t__namespace.cloneNode(prop.key),
|
|
958
|
+
nextValue,
|
|
959
|
+
prop.computed,
|
|
960
|
+
prop.shorthand
|
|
961
|
+
);
|
|
962
|
+
})
|
|
963
|
+
);
|
|
964
|
+
}
|
|
965
|
+
function tryHoistNestedConditional(node, getBinding) {
|
|
966
|
+
const { topLevel, nested, test } = scanNestedConditionals(node);
|
|
967
|
+
if (topLevel !== 0 || nested !== 1 || test === null) {
|
|
968
|
+
return null;
|
|
969
|
+
}
|
|
970
|
+
const consequent = tryStaticTransformNode(
|
|
971
|
+
cloneObjectPickingBranch(node, "consequent"),
|
|
972
|
+
getBinding
|
|
973
|
+
);
|
|
974
|
+
const alternate = tryStaticTransformNode(
|
|
975
|
+
cloneObjectPickingBranch(node, "alternate"),
|
|
976
|
+
getBinding
|
|
977
|
+
);
|
|
978
|
+
if (!consequent || !alternate || !t__namespace.isStringLiteral(consequent) || !t__namespace.isStringLiteral(alternate)) {
|
|
979
|
+
return null;
|
|
980
|
+
}
|
|
981
|
+
return t__namespace.conditionalExpression(
|
|
982
|
+
test,
|
|
983
|
+
emptyClassToUndefined(consequent),
|
|
984
|
+
emptyClassToUndefined(alternate)
|
|
985
|
+
);
|
|
986
|
+
}
|
|
881
987
|
function tryHoistConditionalSpread(node, getBinding) {
|
|
882
988
|
let conditionalSpreadIdx = -1;
|
|
883
989
|
let conditionalExpr = null;
|
|
@@ -1536,6 +1642,10 @@ class CsszyxCompiler {
|
|
|
1536
1642
|
}
|
|
1537
1643
|
}
|
|
1538
1644
|
|
|
1645
|
+
function sortStrings(values) {
|
|
1646
|
+
return [...values].sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1539
1649
|
const CSS_VAR_REFERENCE_RE = /var\(\s*(--[\w-]+)/g;
|
|
1540
1650
|
function scanGlobalVarUsages(source, filename = "file.tsx", options = {}) {
|
|
1541
1651
|
if (!source.includes("--") && !source.includes("var(")) {
|
|
@@ -1745,7 +1855,7 @@ function extractVarReferences(value) {
|
|
|
1745
1855
|
for (const match of value.matchAll(CSS_VAR_REFERENCE_RE)) {
|
|
1746
1856
|
refs.add(match[1]);
|
|
1747
1857
|
}
|
|
1748
|
-
return
|
|
1858
|
+
return sortStrings(refs);
|
|
1749
1859
|
}
|
|
1750
1860
|
function shouldReportToken(name, tokenFilter) {
|
|
1751
1861
|
return tokenFilter === null || tokenFilter.has(name);
|
|
@@ -2019,7 +2129,7 @@ class ManifestBuilder {
|
|
|
2019
2129
|
* @returns {string} SHA-256 checksum
|
|
2020
2130
|
*/
|
|
2021
2131
|
computeChecksum(tokens) {
|
|
2022
|
-
const sortedKeys = Object.keys(tokens)
|
|
2132
|
+
const sortedKeys = sortStrings(Object.keys(tokens));
|
|
2023
2133
|
const sortedTokens = {};
|
|
2024
2134
|
for (const key of sortedKeys) {
|
|
2025
2135
|
sortedTokens[key] = tokens[key];
|
|
@@ -2645,6 +2755,29 @@ function transformOxc(source, filename, options) {
|
|
|
2645
2755
|
transformed = true;
|
|
2646
2756
|
return;
|
|
2647
2757
|
}
|
|
2758
|
+
const nestedConditionalClassExpr = buildNestedConditionalClassExpression(
|
|
2759
|
+
expression,
|
|
2760
|
+
effectiveFilename,
|
|
2761
|
+
objectBindings,
|
|
2762
|
+
source,
|
|
2763
|
+
classes,
|
|
2764
|
+
globalVarAliases,
|
|
2765
|
+
cssVariableMap
|
|
2766
|
+
);
|
|
2767
|
+
if (nestedConditionalClassExpr) {
|
|
2768
|
+
if (classNameAttr || szAttrs.length > 1) {
|
|
2769
|
+
runtimeFallbackExpr = expression;
|
|
2770
|
+
runtimeFallbackAttr = szAttr;
|
|
2771
|
+
break;
|
|
2772
|
+
}
|
|
2773
|
+
edits.overwrite(
|
|
2774
|
+
szAttr.start,
|
|
2775
|
+
szAttr.end,
|
|
2776
|
+
`className={${nestedConditionalClassExpr}}`
|
|
2777
|
+
);
|
|
2778
|
+
transformed = true;
|
|
2779
|
+
return;
|
|
2780
|
+
}
|
|
2648
2781
|
const partial = buildPartialObjectTransform(
|
|
2649
2782
|
expression,
|
|
2650
2783
|
effectiveFilename,
|
|
@@ -2881,7 +3014,7 @@ function extractElementName(nameNode) {
|
|
|
2881
3014
|
}
|
|
2882
3015
|
return "<unknown>";
|
|
2883
3016
|
}
|
|
2884
|
-
function astObjectToSzObject(node, filename, bindings) {
|
|
3017
|
+
function astObjectToSzObject(node, filename, bindings, branchPick) {
|
|
2885
3018
|
const result = {};
|
|
2886
3019
|
for (const propRaw of node.properties) {
|
|
2887
3020
|
if (propRaw.type === "SpreadElement") {
|
|
@@ -2918,7 +3051,7 @@ function astObjectToSzObject(node, filename, bindings) {
|
|
|
2918
3051
|
`unsupported key shape ${prop.key.type} at ${filename}:${prop.key.start}`
|
|
2919
3052
|
);
|
|
2920
3053
|
}
|
|
2921
|
-
result[key] = astValueToSzValue(prop.value, filename, bindings);
|
|
3054
|
+
result[key] = astValueToSzValue(prop.value, filename, bindings, branchPick);
|
|
2922
3055
|
}
|
|
2923
3056
|
return result;
|
|
2924
3057
|
}
|
|
@@ -3350,6 +3483,80 @@ function resolveObjectExpression(node, bindings) {
|
|
|
3350
3483
|
}
|
|
3351
3484
|
return null;
|
|
3352
3485
|
}
|
|
3486
|
+
function countOxcConditionals(node) {
|
|
3487
|
+
let count = 0;
|
|
3488
|
+
for (const propRaw of node.properties) {
|
|
3489
|
+
if (propRaw.type !== "Property") {
|
|
3490
|
+
continue;
|
|
3491
|
+
}
|
|
3492
|
+
const value = propRaw.value;
|
|
3493
|
+
if (value.type === "ConditionalExpression") {
|
|
3494
|
+
count++;
|
|
3495
|
+
} else if (value.type === "ObjectExpression") {
|
|
3496
|
+
count += countOxcConditionals(value);
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
return count;
|
|
3500
|
+
}
|
|
3501
|
+
function firstOxcConditional(node) {
|
|
3502
|
+
for (const propRaw of node.properties) {
|
|
3503
|
+
if (propRaw.type !== "Property") {
|
|
3504
|
+
continue;
|
|
3505
|
+
}
|
|
3506
|
+
const value = propRaw.value;
|
|
3507
|
+
if (value.type === "ConditionalExpression") {
|
|
3508
|
+
return value;
|
|
3509
|
+
}
|
|
3510
|
+
if (value.type === "ObjectExpression") {
|
|
3511
|
+
const found = firstOxcConditional(value);
|
|
3512
|
+
if (found) {
|
|
3513
|
+
return found;
|
|
3514
|
+
}
|
|
3515
|
+
}
|
|
3516
|
+
}
|
|
3517
|
+
return null;
|
|
3518
|
+
}
|
|
3519
|
+
function buildNestedConditionalClassExpression(node, filename, bindings, source, classes, globalVarAliases, cssVariableMap) {
|
|
3520
|
+
let topLevel = 0;
|
|
3521
|
+
for (const propRaw of node.properties) {
|
|
3522
|
+
if (propRaw.type === "Property" && propRaw.value.type === "ConditionalExpression") {
|
|
3523
|
+
topLevel++;
|
|
3524
|
+
}
|
|
3525
|
+
}
|
|
3526
|
+
const first = firstOxcConditional(node);
|
|
3527
|
+
if (topLevel !== 0 || countOxcConditionals(node) !== 1 || !first) {
|
|
3528
|
+
return null;
|
|
3529
|
+
}
|
|
3530
|
+
const compileBranch = (pick) => {
|
|
3531
|
+
try {
|
|
3532
|
+
return transformCore.transform(
|
|
3533
|
+
applyGlobalVarAliasesToSzObject(
|
|
3534
|
+
astObjectToSzObject(node, filename, bindings, pick),
|
|
3535
|
+
globalVarAliases,
|
|
3536
|
+
cssVariableMap
|
|
3537
|
+
)
|
|
3538
|
+
).className;
|
|
3539
|
+
} catch (err) {
|
|
3540
|
+
if (err instanceof OxcNotImplementedError) {
|
|
3541
|
+
return null;
|
|
3542
|
+
}
|
|
3543
|
+
throw err;
|
|
3544
|
+
}
|
|
3545
|
+
};
|
|
3546
|
+
const consequent = compileBranch("consequent");
|
|
3547
|
+
const alternate = compileBranch("alternate");
|
|
3548
|
+
if (consequent === null || alternate === null) {
|
|
3549
|
+
return null;
|
|
3550
|
+
}
|
|
3551
|
+
for (const cls of `${consequent} ${alternate}`.split(/\s+/)) {
|
|
3552
|
+
if (cls) {
|
|
3553
|
+
classes.add(cls);
|
|
3554
|
+
}
|
|
3555
|
+
}
|
|
3556
|
+
const testSource = source.slice(first.test.start, first.test.end);
|
|
3557
|
+
const branch = (cls) => cls === "" ? "undefined" : JSON.stringify(cls);
|
|
3558
|
+
return `${testSource} ? ${branch(consequent)} : ${branch(alternate)}`;
|
|
3559
|
+
}
|
|
3353
3560
|
function buildConditionalSpreadClassExpression(node, filename, bindings, source, classes, globalVarAliases, cssVariableMap) {
|
|
3354
3561
|
let conditionalSpread = null;
|
|
3355
3562
|
const otherProps = [];
|
|
@@ -4134,7 +4341,15 @@ function extractKeyName(key) {
|
|
|
4134
4341
|
}
|
|
4135
4342
|
return null;
|
|
4136
4343
|
}
|
|
4137
|
-
function astValueToSzValue(node, filename, bindings) {
|
|
4344
|
+
function astValueToSzValue(node, filename, bindings, branchPick) {
|
|
4345
|
+
if (branchPick && node.type === "ConditionalExpression") {
|
|
4346
|
+
return astValueToSzValue(
|
|
4347
|
+
node[branchPick],
|
|
4348
|
+
filename,
|
|
4349
|
+
bindings,
|
|
4350
|
+
branchPick
|
|
4351
|
+
);
|
|
4352
|
+
}
|
|
4138
4353
|
if (node.type === "Literal") {
|
|
4139
4354
|
const value = node.value;
|
|
4140
4355
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
@@ -4160,7 +4375,7 @@ function astValueToSzValue(node, filename, bindings) {
|
|
|
4160
4375
|
);
|
|
4161
4376
|
}
|
|
4162
4377
|
if (node.type === "ObjectExpression") {
|
|
4163
|
-
return astObjectToSzObject(node, filename, bindings);
|
|
4378
|
+
return astObjectToSzObject(node, filename, bindings, branchPick);
|
|
4164
4379
|
}
|
|
4165
4380
|
if (node.type === "Identifier" || node.type === "MemberExpression") {
|
|
4166
4381
|
throw new OxcNotImplementedError(
|
|
@@ -4431,6 +4646,7 @@ exports.mergeOptions = mergeOptions;
|
|
|
4431
4646
|
exports.parseManifest = parseManifest;
|
|
4432
4647
|
exports.scanGlobalVarUsages = scanGlobalVarUsages;
|
|
4433
4648
|
exports.serializeManifest = serializeManifest;
|
|
4649
|
+
exports.sortStrings = sortStrings;
|
|
4434
4650
|
exports.transformOxc = transformOxc;
|
|
4435
4651
|
exports.transformRust = transformRust;
|
|
4436
4652
|
exports.transformRustBatch = transformRustBatch;
|
package/dist/index.d.cts
CHANGED
|
@@ -581,6 +581,28 @@ declare const COLOR_PROPERTIES: Set<string>;
|
|
|
581
581
|
*/
|
|
582
582
|
declare function getCSSVariableName(property: string, variantPrefix?: string): string;
|
|
583
583
|
|
|
584
|
+
/**
|
|
585
|
+
* Deterministic, locale-independent ascending sort for string collections.
|
|
586
|
+
*
|
|
587
|
+
* A bare `Array.prototype.sort()` coerces elements to strings, so it silently
|
|
588
|
+
* mis-orders numbers (`[10, 9]` → `[10, 9]`). Every ordered collection in this
|
|
589
|
+
* codebase is a set of identifiers — class names, mangle tokens, filenames,
|
|
590
|
+
* variant names, CSS-variable references — so the correct sort is lexicographic
|
|
591
|
+
* AND locale-independent (a locale-aware `localeCompare` would make build output
|
|
592
|
+
* order depend on the runner's locale and break reproducibility).
|
|
593
|
+
*
|
|
594
|
+
* This helper encodes exactly that, and its `T extends string` bound makes the
|
|
595
|
+
* intent compiler-checked: passing a `number[]` (or a `(string | number)[]`) is a
|
|
596
|
+
* type error, so a future numeric sort cannot slip through as a bare `.sort()`.
|
|
597
|
+
* The `no-restricted-syntax` lint rule forbids bare `.sort()` to route every sort
|
|
598
|
+
* through here or an explicit comparator.
|
|
599
|
+
*
|
|
600
|
+
* @template T - the (string) element type.
|
|
601
|
+
* @param values - the strings to sort (any iterable; not mutated).
|
|
602
|
+
* @returns a new array sorted ascending by UTF-16 code unit.
|
|
603
|
+
*/
|
|
604
|
+
declare function sortStrings<T extends string>(values: Iterable<T>): T[];
|
|
605
|
+
|
|
584
606
|
/**
|
|
585
607
|
* Phase D production transform — `transformOxc()` is the oxc-parser +
|
|
586
608
|
* magic-string replacement for `transformSourceCode()` (Babel). The
|
|
@@ -13639,5 +13661,5 @@ declare const DEFAULT_COMPILER_OPTIONS: Required<CompilerOptions>;
|
|
|
13639
13661
|
*/
|
|
13640
13662
|
declare function mergeOptions(options?: Partial<CompilerOptions>): Required<CompilerOptions>;
|
|
13641
13663
|
|
|
13642
|
-
export { COLOR_PROPERTIES, CsszyxCompiler, DEFAULT_COMPILER_OPTIONS, ManifestBuilder, OxcNotImplementedError, OxcRustNotImplementedError, PROPERTY_CATEGORY_MAP, PropertyCategory, SzObject, VERSION, buildParentMap, createRecoveryToken, ensureRustTransformAvailable, generateRecoveryToken, getCSSVariableName, getPropertyCategory, hoistCSSVariables, injectRecoveryToken, isRustTransformAvailable, isValidRecoveryMode, mergeOptions, parseManifest, scanGlobalVarUsages, serializeManifest, transformOxc, transformRust, transformRustBatch, transformSourceCode, validateManifest, validateSzRecover };
|
|
13664
|
+
export { COLOR_PROPERTIES, CsszyxCompiler, DEFAULT_COMPILER_OPTIONS, ManifestBuilder, OxcNotImplementedError, OxcRustNotImplementedError, PROPERTY_CATEGORY_MAP, PropertyCategory, SzObject, VERSION, buildParentMap, createRecoveryToken, ensureRustTransformAvailable, generateRecoveryToken, getCSSVariableName, getPropertyCategory, hoistCSSVariables, injectRecoveryToken, isRustTransformAvailable, isValidRecoveryMode, mergeOptions, parseManifest, scanGlobalVarUsages, serializeManifest, sortStrings, transformOxc, transformRust, transformRustBatch, transformSourceCode, validateManifest, validateSzRecover };
|
|
13643
13665
|
export type { BackgroundProps, BorderProps, BorderRadiusValue, CSSVarUsage, ColorName, ColorObjectValue, ColorPropValue, ColorShade, ColorValue, CompilerOptions, ContainerSize, CssVariableMangleValue, CustomTheme, EffectsProps, FilterProps, FlexboxGridProps, FractionValue, GlobalVarAliasTableInput, GlobalVarUsageDiagnostic, GlobalVarUsageKind, GlobalVarUsageLocation, InteractivityProps, LayoutProps, NegativeSpacingValue, RecoveryManifest, RecoveryMode, RecoveryToken, ScanGlobalVarUsagesOptions, ShadowValue, SizingProps, SourceTransformResult, SpacingProps, SpacingScale, SpacingValue, SvgProps, SzPropValue, SzProps, SzPropsBase, TableProps, TokenData, TokenMetadata, TransformOxcResult, TransformProps, TransformRustFile, TransformSourceCodeOptions, TransitionAnimationProps, TypographyProps, VariantModifiers };
|
package/dist/index.d.mts
CHANGED
|
@@ -581,6 +581,28 @@ declare const COLOR_PROPERTIES: Set<string>;
|
|
|
581
581
|
*/
|
|
582
582
|
declare function getCSSVariableName(property: string, variantPrefix?: string): string;
|
|
583
583
|
|
|
584
|
+
/**
|
|
585
|
+
* Deterministic, locale-independent ascending sort for string collections.
|
|
586
|
+
*
|
|
587
|
+
* A bare `Array.prototype.sort()` coerces elements to strings, so it silently
|
|
588
|
+
* mis-orders numbers (`[10, 9]` → `[10, 9]`). Every ordered collection in this
|
|
589
|
+
* codebase is a set of identifiers — class names, mangle tokens, filenames,
|
|
590
|
+
* variant names, CSS-variable references — so the correct sort is lexicographic
|
|
591
|
+
* AND locale-independent (a locale-aware `localeCompare` would make build output
|
|
592
|
+
* order depend on the runner's locale and break reproducibility).
|
|
593
|
+
*
|
|
594
|
+
* This helper encodes exactly that, and its `T extends string` bound makes the
|
|
595
|
+
* intent compiler-checked: passing a `number[]` (or a `(string | number)[]`) is a
|
|
596
|
+
* type error, so a future numeric sort cannot slip through as a bare `.sort()`.
|
|
597
|
+
* The `no-restricted-syntax` lint rule forbids bare `.sort()` to route every sort
|
|
598
|
+
* through here or an explicit comparator.
|
|
599
|
+
*
|
|
600
|
+
* @template T - the (string) element type.
|
|
601
|
+
* @param values - the strings to sort (any iterable; not mutated).
|
|
602
|
+
* @returns a new array sorted ascending by UTF-16 code unit.
|
|
603
|
+
*/
|
|
604
|
+
declare function sortStrings<T extends string>(values: Iterable<T>): T[];
|
|
605
|
+
|
|
584
606
|
/**
|
|
585
607
|
* Phase D production transform — `transformOxc()` is the oxc-parser +
|
|
586
608
|
* magic-string replacement for `transformSourceCode()` (Babel). The
|
|
@@ -13639,5 +13661,5 @@ declare const DEFAULT_COMPILER_OPTIONS: Required<CompilerOptions>;
|
|
|
13639
13661
|
*/
|
|
13640
13662
|
declare function mergeOptions(options?: Partial<CompilerOptions>): Required<CompilerOptions>;
|
|
13641
13663
|
|
|
13642
|
-
export { COLOR_PROPERTIES, CsszyxCompiler, DEFAULT_COMPILER_OPTIONS, ManifestBuilder, OxcNotImplementedError, OxcRustNotImplementedError, PROPERTY_CATEGORY_MAP, PropertyCategory, SzObject, VERSION, buildParentMap, createRecoveryToken, ensureRustTransformAvailable, generateRecoveryToken, getCSSVariableName, getPropertyCategory, hoistCSSVariables, injectRecoveryToken, isRustTransformAvailable, isValidRecoveryMode, mergeOptions, parseManifest, scanGlobalVarUsages, serializeManifest, transformOxc, transformRust, transformRustBatch, transformSourceCode, validateManifest, validateSzRecover };
|
|
13664
|
+
export { COLOR_PROPERTIES, CsszyxCompiler, DEFAULT_COMPILER_OPTIONS, ManifestBuilder, OxcNotImplementedError, OxcRustNotImplementedError, PROPERTY_CATEGORY_MAP, PropertyCategory, SzObject, VERSION, buildParentMap, createRecoveryToken, ensureRustTransformAvailable, generateRecoveryToken, getCSSVariableName, getPropertyCategory, hoistCSSVariables, injectRecoveryToken, isRustTransformAvailable, isValidRecoveryMode, mergeOptions, parseManifest, scanGlobalVarUsages, serializeManifest, sortStrings, transformOxc, transformRust, transformRustBatch, transformSourceCode, validateManifest, validateSzRecover };
|
|
13643
13665
|
export type { BackgroundProps, BorderProps, BorderRadiusValue, CSSVarUsage, ColorName, ColorObjectValue, ColorPropValue, ColorShade, ColorValue, CompilerOptions, ContainerSize, CssVariableMangleValue, CustomTheme, EffectsProps, FilterProps, FlexboxGridProps, FractionValue, GlobalVarAliasTableInput, GlobalVarUsageDiagnostic, GlobalVarUsageKind, GlobalVarUsageLocation, InteractivityProps, LayoutProps, NegativeSpacingValue, RecoveryManifest, RecoveryMode, RecoveryToken, ScanGlobalVarUsagesOptions, ShadowValue, SizingProps, SourceTransformResult, SpacingProps, SpacingScale, SpacingValue, SvgProps, SzPropValue, SzProps, SzPropsBase, TableProps, TokenData, TokenMetadata, TransformOxcResult, TransformProps, TransformRustFile, TransformSourceCodeOptions, TransitionAnimationProps, TypographyProps, VariantModifiers };
|
package/dist/index.mjs
CHANGED
|
@@ -371,6 +371,17 @@ function transformSourceCode(source, filename, options) {
|
|
|
371
371
|
transformed = true;
|
|
372
372
|
return;
|
|
373
373
|
}
|
|
374
|
+
const hoistedNested = tryHoistNestedConditional(
|
|
375
|
+
flatExpression,
|
|
376
|
+
getBinding
|
|
377
|
+
);
|
|
378
|
+
if (hoistedNested !== null) {
|
|
379
|
+
path.node.name.name = "className";
|
|
380
|
+
path.node.value = createMergedClassNameValue(hoistedNested);
|
|
381
|
+
collectFromExpr(hoistedNested, collectedClasses);
|
|
382
|
+
transformed = true;
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
374
385
|
const partial = evaluatePartialObject$1(flatExpression);
|
|
375
386
|
if (partial !== null && !partial.hasSpread && (partial.dynamicProps.size > 0 || partial.conditionalClasses.length > 0)) {
|
|
376
387
|
const staticClasses = [];
|
|
@@ -859,6 +870,101 @@ function tryStaticTransformNode(node, getBinding) {
|
|
|
859
870
|
}
|
|
860
871
|
return null;
|
|
861
872
|
}
|
|
873
|
+
function scanNestedConditionals(node) {
|
|
874
|
+
let topLevel = 0;
|
|
875
|
+
let nested = 0;
|
|
876
|
+
let test = null;
|
|
877
|
+
for (const prop of node.properties) {
|
|
878
|
+
if (!t.isObjectProperty(prop)) {
|
|
879
|
+
continue;
|
|
880
|
+
}
|
|
881
|
+
const value = prop.value;
|
|
882
|
+
if (t.isConditionalExpression(value)) {
|
|
883
|
+
topLevel++;
|
|
884
|
+
} else if (t.isObjectExpression(value)) {
|
|
885
|
+
nested += countAllConditionals(value);
|
|
886
|
+
test ??= firstConditionalTest(value);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
return { topLevel, nested, test };
|
|
890
|
+
}
|
|
891
|
+
function countAllConditionals(node) {
|
|
892
|
+
let count = 0;
|
|
893
|
+
for (const prop of node.properties) {
|
|
894
|
+
if (!t.isObjectProperty(prop)) {
|
|
895
|
+
continue;
|
|
896
|
+
}
|
|
897
|
+
const value = prop.value;
|
|
898
|
+
if (t.isConditionalExpression(value)) {
|
|
899
|
+
count++;
|
|
900
|
+
} else if (t.isObjectExpression(value)) {
|
|
901
|
+
count += countAllConditionals(value);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
return count;
|
|
905
|
+
}
|
|
906
|
+
function firstConditionalTest(node) {
|
|
907
|
+
for (const prop of node.properties) {
|
|
908
|
+
if (!t.isObjectProperty(prop)) {
|
|
909
|
+
continue;
|
|
910
|
+
}
|
|
911
|
+
const value = prop.value;
|
|
912
|
+
if (t.isConditionalExpression(value)) {
|
|
913
|
+
return value.test;
|
|
914
|
+
}
|
|
915
|
+
if (t.isObjectExpression(value)) {
|
|
916
|
+
const inner = firstConditionalTest(value);
|
|
917
|
+
if (inner) {
|
|
918
|
+
return inner;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
return null;
|
|
923
|
+
}
|
|
924
|
+
function cloneObjectPickingBranch(node, pick) {
|
|
925
|
+
return t.objectExpression(
|
|
926
|
+
node.properties.map((prop) => {
|
|
927
|
+
if (!t.isObjectProperty(prop)) {
|
|
928
|
+
return t.cloneNode(prop);
|
|
929
|
+
}
|
|
930
|
+
const value = prop.value;
|
|
931
|
+
let nextValue = t.cloneNode(value);
|
|
932
|
+
if (t.isConditionalExpression(value)) {
|
|
933
|
+
nextValue = t.cloneNode(value[pick]);
|
|
934
|
+
} else if (t.isObjectExpression(value)) {
|
|
935
|
+
nextValue = cloneObjectPickingBranch(value, pick);
|
|
936
|
+
}
|
|
937
|
+
return t.objectProperty(
|
|
938
|
+
t.cloneNode(prop.key),
|
|
939
|
+
nextValue,
|
|
940
|
+
prop.computed,
|
|
941
|
+
prop.shorthand
|
|
942
|
+
);
|
|
943
|
+
})
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
function tryHoistNestedConditional(node, getBinding) {
|
|
947
|
+
const { topLevel, nested, test } = scanNestedConditionals(node);
|
|
948
|
+
if (topLevel !== 0 || nested !== 1 || test === null) {
|
|
949
|
+
return null;
|
|
950
|
+
}
|
|
951
|
+
const consequent = tryStaticTransformNode(
|
|
952
|
+
cloneObjectPickingBranch(node, "consequent"),
|
|
953
|
+
getBinding
|
|
954
|
+
);
|
|
955
|
+
const alternate = tryStaticTransformNode(
|
|
956
|
+
cloneObjectPickingBranch(node, "alternate"),
|
|
957
|
+
getBinding
|
|
958
|
+
);
|
|
959
|
+
if (!consequent || !alternate || !t.isStringLiteral(consequent) || !t.isStringLiteral(alternate)) {
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
return t.conditionalExpression(
|
|
963
|
+
test,
|
|
964
|
+
emptyClassToUndefined(consequent),
|
|
965
|
+
emptyClassToUndefined(alternate)
|
|
966
|
+
);
|
|
967
|
+
}
|
|
862
968
|
function tryHoistConditionalSpread(node, getBinding) {
|
|
863
969
|
let conditionalSpreadIdx = -1;
|
|
864
970
|
let conditionalExpr = null;
|
|
@@ -1517,6 +1623,10 @@ class CsszyxCompiler {
|
|
|
1517
1623
|
}
|
|
1518
1624
|
}
|
|
1519
1625
|
|
|
1626
|
+
function sortStrings(values) {
|
|
1627
|
+
return [...values].sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1520
1630
|
const CSS_VAR_REFERENCE_RE = /var\(\s*(--[\w-]+)/g;
|
|
1521
1631
|
function scanGlobalVarUsages(source, filename = "file.tsx", options = {}) {
|
|
1522
1632
|
if (!source.includes("--") && !source.includes("var(")) {
|
|
@@ -1726,7 +1836,7 @@ function extractVarReferences(value) {
|
|
|
1726
1836
|
for (const match of value.matchAll(CSS_VAR_REFERENCE_RE)) {
|
|
1727
1837
|
refs.add(match[1]);
|
|
1728
1838
|
}
|
|
1729
|
-
return
|
|
1839
|
+
return sortStrings(refs);
|
|
1730
1840
|
}
|
|
1731
1841
|
function shouldReportToken(name, tokenFilter) {
|
|
1732
1842
|
return tokenFilter === null || tokenFilter.has(name);
|
|
@@ -2000,7 +2110,7 @@ class ManifestBuilder {
|
|
|
2000
2110
|
* @returns {string} SHA-256 checksum
|
|
2001
2111
|
*/
|
|
2002
2112
|
computeChecksum(tokens) {
|
|
2003
|
-
const sortedKeys = Object.keys(tokens)
|
|
2113
|
+
const sortedKeys = sortStrings(Object.keys(tokens));
|
|
2004
2114
|
const sortedTokens = {};
|
|
2005
2115
|
for (const key of sortedKeys) {
|
|
2006
2116
|
sortedTokens[key] = tokens[key];
|
|
@@ -2626,6 +2736,29 @@ function transformOxc(source, filename, options) {
|
|
|
2626
2736
|
transformed = true;
|
|
2627
2737
|
return;
|
|
2628
2738
|
}
|
|
2739
|
+
const nestedConditionalClassExpr = buildNestedConditionalClassExpression(
|
|
2740
|
+
expression,
|
|
2741
|
+
effectiveFilename,
|
|
2742
|
+
objectBindings,
|
|
2743
|
+
source,
|
|
2744
|
+
classes,
|
|
2745
|
+
globalVarAliases,
|
|
2746
|
+
cssVariableMap
|
|
2747
|
+
);
|
|
2748
|
+
if (nestedConditionalClassExpr) {
|
|
2749
|
+
if (classNameAttr || szAttrs.length > 1) {
|
|
2750
|
+
runtimeFallbackExpr = expression;
|
|
2751
|
+
runtimeFallbackAttr = szAttr;
|
|
2752
|
+
break;
|
|
2753
|
+
}
|
|
2754
|
+
edits.overwrite(
|
|
2755
|
+
szAttr.start,
|
|
2756
|
+
szAttr.end,
|
|
2757
|
+
`className={${nestedConditionalClassExpr}}`
|
|
2758
|
+
);
|
|
2759
|
+
transformed = true;
|
|
2760
|
+
return;
|
|
2761
|
+
}
|
|
2629
2762
|
const partial = buildPartialObjectTransform(
|
|
2630
2763
|
expression,
|
|
2631
2764
|
effectiveFilename,
|
|
@@ -2862,7 +2995,7 @@ function extractElementName(nameNode) {
|
|
|
2862
2995
|
}
|
|
2863
2996
|
return "<unknown>";
|
|
2864
2997
|
}
|
|
2865
|
-
function astObjectToSzObject(node, filename, bindings) {
|
|
2998
|
+
function astObjectToSzObject(node, filename, bindings, branchPick) {
|
|
2866
2999
|
const result = {};
|
|
2867
3000
|
for (const propRaw of node.properties) {
|
|
2868
3001
|
if (propRaw.type === "SpreadElement") {
|
|
@@ -2899,7 +3032,7 @@ function astObjectToSzObject(node, filename, bindings) {
|
|
|
2899
3032
|
`unsupported key shape ${prop.key.type} at ${filename}:${prop.key.start}`
|
|
2900
3033
|
);
|
|
2901
3034
|
}
|
|
2902
|
-
result[key] = astValueToSzValue(prop.value, filename, bindings);
|
|
3035
|
+
result[key] = astValueToSzValue(prop.value, filename, bindings, branchPick);
|
|
2903
3036
|
}
|
|
2904
3037
|
return result;
|
|
2905
3038
|
}
|
|
@@ -3331,6 +3464,80 @@ function resolveObjectExpression(node, bindings) {
|
|
|
3331
3464
|
}
|
|
3332
3465
|
return null;
|
|
3333
3466
|
}
|
|
3467
|
+
function countOxcConditionals(node) {
|
|
3468
|
+
let count = 0;
|
|
3469
|
+
for (const propRaw of node.properties) {
|
|
3470
|
+
if (propRaw.type !== "Property") {
|
|
3471
|
+
continue;
|
|
3472
|
+
}
|
|
3473
|
+
const value = propRaw.value;
|
|
3474
|
+
if (value.type === "ConditionalExpression") {
|
|
3475
|
+
count++;
|
|
3476
|
+
} else if (value.type === "ObjectExpression") {
|
|
3477
|
+
count += countOxcConditionals(value);
|
|
3478
|
+
}
|
|
3479
|
+
}
|
|
3480
|
+
return count;
|
|
3481
|
+
}
|
|
3482
|
+
function firstOxcConditional(node) {
|
|
3483
|
+
for (const propRaw of node.properties) {
|
|
3484
|
+
if (propRaw.type !== "Property") {
|
|
3485
|
+
continue;
|
|
3486
|
+
}
|
|
3487
|
+
const value = propRaw.value;
|
|
3488
|
+
if (value.type === "ConditionalExpression") {
|
|
3489
|
+
return value;
|
|
3490
|
+
}
|
|
3491
|
+
if (value.type === "ObjectExpression") {
|
|
3492
|
+
const found = firstOxcConditional(value);
|
|
3493
|
+
if (found) {
|
|
3494
|
+
return found;
|
|
3495
|
+
}
|
|
3496
|
+
}
|
|
3497
|
+
}
|
|
3498
|
+
return null;
|
|
3499
|
+
}
|
|
3500
|
+
function buildNestedConditionalClassExpression(node, filename, bindings, source, classes, globalVarAliases, cssVariableMap) {
|
|
3501
|
+
let topLevel = 0;
|
|
3502
|
+
for (const propRaw of node.properties) {
|
|
3503
|
+
if (propRaw.type === "Property" && propRaw.value.type === "ConditionalExpression") {
|
|
3504
|
+
topLevel++;
|
|
3505
|
+
}
|
|
3506
|
+
}
|
|
3507
|
+
const first = firstOxcConditional(node);
|
|
3508
|
+
if (topLevel !== 0 || countOxcConditionals(node) !== 1 || !first) {
|
|
3509
|
+
return null;
|
|
3510
|
+
}
|
|
3511
|
+
const compileBranch = (pick) => {
|
|
3512
|
+
try {
|
|
3513
|
+
return transform(
|
|
3514
|
+
applyGlobalVarAliasesToSzObject(
|
|
3515
|
+
astObjectToSzObject(node, filename, bindings, pick),
|
|
3516
|
+
globalVarAliases,
|
|
3517
|
+
cssVariableMap
|
|
3518
|
+
)
|
|
3519
|
+
).className;
|
|
3520
|
+
} catch (err) {
|
|
3521
|
+
if (err instanceof OxcNotImplementedError) {
|
|
3522
|
+
return null;
|
|
3523
|
+
}
|
|
3524
|
+
throw err;
|
|
3525
|
+
}
|
|
3526
|
+
};
|
|
3527
|
+
const consequent = compileBranch("consequent");
|
|
3528
|
+
const alternate = compileBranch("alternate");
|
|
3529
|
+
if (consequent === null || alternate === null) {
|
|
3530
|
+
return null;
|
|
3531
|
+
}
|
|
3532
|
+
for (const cls of `${consequent} ${alternate}`.split(/\s+/)) {
|
|
3533
|
+
if (cls) {
|
|
3534
|
+
classes.add(cls);
|
|
3535
|
+
}
|
|
3536
|
+
}
|
|
3537
|
+
const testSource = source.slice(first.test.start, first.test.end);
|
|
3538
|
+
const branch = (cls) => cls === "" ? "undefined" : JSON.stringify(cls);
|
|
3539
|
+
return `${testSource} ? ${branch(consequent)} : ${branch(alternate)}`;
|
|
3540
|
+
}
|
|
3334
3541
|
function buildConditionalSpreadClassExpression(node, filename, bindings, source, classes, globalVarAliases, cssVariableMap) {
|
|
3335
3542
|
let conditionalSpread = null;
|
|
3336
3543
|
const otherProps = [];
|
|
@@ -4115,7 +4322,15 @@ function extractKeyName(key) {
|
|
|
4115
4322
|
}
|
|
4116
4323
|
return null;
|
|
4117
4324
|
}
|
|
4118
|
-
function astValueToSzValue(node, filename, bindings) {
|
|
4325
|
+
function astValueToSzValue(node, filename, bindings, branchPick) {
|
|
4326
|
+
if (branchPick && node.type === "ConditionalExpression") {
|
|
4327
|
+
return astValueToSzValue(
|
|
4328
|
+
node[branchPick],
|
|
4329
|
+
filename,
|
|
4330
|
+
bindings,
|
|
4331
|
+
branchPick
|
|
4332
|
+
);
|
|
4333
|
+
}
|
|
4119
4334
|
if (node.type === "Literal") {
|
|
4120
4335
|
const value = node.value;
|
|
4121
4336
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
@@ -4141,7 +4356,7 @@ function astValueToSzValue(node, filename, bindings) {
|
|
|
4141
4356
|
);
|
|
4142
4357
|
}
|
|
4143
4358
|
if (node.type === "ObjectExpression") {
|
|
4144
|
-
return astObjectToSzObject(node, filename, bindings);
|
|
4359
|
+
return astObjectToSzObject(node, filename, bindings, branchPick);
|
|
4145
4360
|
}
|
|
4146
4361
|
if (node.type === "Identifier" || node.type === "MemberExpression") {
|
|
4147
4362
|
throw new OxcNotImplementedError(
|
|
@@ -4380,4 +4595,4 @@ function mergeOptions(options = {}) {
|
|
|
4380
4595
|
};
|
|
4381
4596
|
}
|
|
4382
4597
|
|
|
4383
|
-
export { COLOR_PROPERTIES, CsszyxCompiler, DEFAULT_COMPILER_OPTIONS, KNOWN_VARIANTS, ManifestBuilder, OxcNotImplementedError, OxcRustNotImplementedError, PROPERTY_MAP, PropertyCategory, VERSION, buildParentMap, createRecoveryToken, ensureRustTransformAvailable, generateRecoveryToken, getCSSVariableName, getPropertyCategory, hoistCSSVariables, injectRecoveryToken, isRustTransformAvailable, isValidRecoveryMode, mergeOptions, parseManifest, scanGlobalVarUsages, serializeManifest, transform, transformOxc, transformRust, transformRustBatch, transformSourceCode, validateManifest, validateSzRecover };
|
|
4598
|
+
export { COLOR_PROPERTIES, CsszyxCompiler, DEFAULT_COMPILER_OPTIONS, KNOWN_VARIANTS, ManifestBuilder, OxcNotImplementedError, OxcRustNotImplementedError, PROPERTY_MAP, PropertyCategory, VERSION, buildParentMap, createRecoveryToken, ensureRustTransformAvailable, generateRecoveryToken, getCSSVariableName, getPropertyCategory, hoistCSSVariables, injectRecoveryToken, isRustTransformAvailable, isValidRecoveryMode, mergeOptions, parseManifest, scanGlobalVarUsages, serializeManifest, sortStrings, transform, transformOxc, transformRust, transformRustBatch, transformSourceCode, validateManifest, validateSzRecover };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@csszyx/compiler",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.9",
|
|
4
4
|
"description": "Core compiler and transformation logic for csszyx",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"csszyx",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"@babel/types": "^7.23.6",
|
|
66
66
|
"magic-string": "0.30.21",
|
|
67
67
|
"oxc-parser": "0.131.0",
|
|
68
|
-
"@csszyx/core": "0.10.
|
|
68
|
+
"@csszyx/core": "0.10.9"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/babel__core": "^7.20.5",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"csstype": "^3.0.0",
|
|
75
75
|
"typescript": "^6.0.3",
|
|
76
76
|
"unbuild": "^3.6.1",
|
|
77
|
-
"vitest": "^4.1.
|
|
77
|
+
"vitest": "^4.1.9"
|
|
78
78
|
},
|
|
79
79
|
"sideEffects": false,
|
|
80
80
|
"engines": {
|