@csszyx/compiler 0.8.0 → 0.9.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/README.md +12 -8
- package/dist/color-var.cjs +1 -0
- package/dist/color-var.mjs +1 -0
- package/dist/index.cjs +1109 -44
- package/dist/index.d.cts +184 -38
- package/dist/index.d.mts +184 -38
- package/dist/index.mjs +1107 -47
- package/dist/shared/{compiler.BIUVmI0H.mjs → compiler.CIBwOKUt.mjs} +70 -15
- package/dist/shared/{compiler.C6jT0mcT.cjs → compiler.DItEsgH4.cjs} +70 -15
- package/dist/transform-core.cjs +1 -1
- package/dist/transform-core.mjs +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { init, version, transform_sz } from '@csszyx/core';
|
|
2
|
-
import { t as transform, C as COLOR_PROPERTIES, P as PROPERTY_MAP, g as getCSSVariableName, a as PropertyCategory, K as KNOWN_VARIANTS, b as getVariantPrefix, c as getPropertyCategory, s as stripInvalidColorStrings } from './shared/compiler.
|
|
3
|
-
export { B as BOOLEAN_SHORTHANDS, d as PROPERTY_CATEGORY_MAP, S as SUGGESTION_MAP, i as isValidSzProp, n as normalizeClassName } from './shared/compiler.
|
|
1
|
+
import { init, version, transform_sz, encode } from '@csszyx/core';
|
|
2
|
+
import { t as transform, C as COLOR_PROPERTIES, P as PROPERTY_MAP, g as getCSSVariableName, a as PropertyCategory, K as KNOWN_VARIANTS, b as getVariantPrefix, c as getPropertyCategory, s as stripInvalidColorStrings } from './shared/compiler.CIBwOKUt.mjs';
|
|
3
|
+
export { B as BOOLEAN_SHORTHANDS, d as PROPERTY_CATEGORY_MAP, S as SUGGESTION_MAP, i as isValidSzProp, n as normalizeClassName } from './shared/compiler.CIBwOKUt.mjs';
|
|
4
|
+
import { parseSync } from 'oxc-parser';
|
|
4
5
|
import * as t from '@babel/types';
|
|
5
6
|
import { createHash } from 'node:crypto';
|
|
6
7
|
import * as babel from '@babel/core';
|
|
7
8
|
import MagicString from 'magic-string';
|
|
8
|
-
import {
|
|
9
|
+
import { transformBatch, CsszyxNativeUnavailableError } from '@csszyx/core/native';
|
|
9
10
|
|
|
10
11
|
const AST_BUDGET = 5e4;
|
|
11
12
|
class ASTBudgetExceededError extends Error {
|
|
@@ -64,6 +65,7 @@ function transformSourceCode(source, filename, options) {
|
|
|
64
65
|
const rawClassNames = /* @__PURE__ */ new Set();
|
|
65
66
|
const diagnostics = [];
|
|
66
67
|
const recoveryTokens = /* @__PURE__ */ new Map();
|
|
68
|
+
const cssVariableMap = /* @__PURE__ */ new Map();
|
|
67
69
|
if (!source.includes("sz")) {
|
|
68
70
|
return {
|
|
69
71
|
code: source,
|
|
@@ -74,7 +76,8 @@ function transformSourceCode(source, filename, options) {
|
|
|
74
76
|
classes: collectedClasses,
|
|
75
77
|
rawClassNames,
|
|
76
78
|
diagnostics,
|
|
77
|
-
recoveryTokens
|
|
79
|
+
recoveryTokens,
|
|
80
|
+
cssVariableMap
|
|
78
81
|
};
|
|
79
82
|
}
|
|
80
83
|
try {
|
|
@@ -736,7 +739,8 @@ function transformSourceCode(source, filename, options) {
|
|
|
736
739
|
classes: collectedClasses,
|
|
737
740
|
rawClassNames,
|
|
738
741
|
diagnostics,
|
|
739
|
-
recoveryTokens
|
|
742
|
+
recoveryTokens,
|
|
743
|
+
cssVariableMap
|
|
740
744
|
};
|
|
741
745
|
} catch (e) {
|
|
742
746
|
if (e instanceof ASTBudgetExceededError) {
|
|
@@ -752,7 +756,8 @@ function transformSourceCode(source, filename, options) {
|
|
|
752
756
|
classes: collectedClasses,
|
|
753
757
|
rawClassNames,
|
|
754
758
|
diagnostics,
|
|
755
|
-
recoveryTokens
|
|
759
|
+
recoveryTokens,
|
|
760
|
+
cssVariableMap
|
|
756
761
|
};
|
|
757
762
|
}
|
|
758
763
|
}
|
|
@@ -1304,6 +1309,271 @@ class CsszyxCompiler {
|
|
|
1304
1309
|
}
|
|
1305
1310
|
}
|
|
1306
1311
|
|
|
1312
|
+
const CSS_VAR_REFERENCE_RE = /var\(\s*(--[\w-]+)/g;
|
|
1313
|
+
function scanGlobalVarUsages(source, filename = "file.tsx", options = {}) {
|
|
1314
|
+
if (!source.includes("--") && !source.includes("var(")) {
|
|
1315
|
+
return [];
|
|
1316
|
+
}
|
|
1317
|
+
const parsed = parseSync(filename, source);
|
|
1318
|
+
if (parsed.errors.length > 0) {
|
|
1319
|
+
throw new Error(
|
|
1320
|
+
`oxc-parser errors in ${filename}: ${parsed.errors.map((error) => error.message).join("; ")}`
|
|
1321
|
+
);
|
|
1322
|
+
}
|
|
1323
|
+
const tokenFilter = options.tokens ? new Set(options.tokens) : null;
|
|
1324
|
+
const constantStrings = collectStringConstants(parsed.program);
|
|
1325
|
+
const diagnostics = [];
|
|
1326
|
+
walk$1(parsed.program, (node, ancestors) => {
|
|
1327
|
+
if (node.type === "CallExpression") {
|
|
1328
|
+
collectStyleMethodDiagnostic(
|
|
1329
|
+
node,
|
|
1330
|
+
source,
|
|
1331
|
+
filename,
|
|
1332
|
+
constantStrings,
|
|
1333
|
+
tokenFilter,
|
|
1334
|
+
diagnostics
|
|
1335
|
+
);
|
|
1336
|
+
return;
|
|
1337
|
+
}
|
|
1338
|
+
if (node.type !== "JSXAttribute") {
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1341
|
+
const attrName = jsxAttributeName(node);
|
|
1342
|
+
if (attrName === "style") {
|
|
1343
|
+
collectJsxStyleDiagnostics(
|
|
1344
|
+
node,
|
|
1345
|
+
source,
|
|
1346
|
+
filename,
|
|
1347
|
+
constantStrings,
|
|
1348
|
+
tokenFilter,
|
|
1349
|
+
diagnostics
|
|
1350
|
+
);
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
if (attrName === "className") {
|
|
1354
|
+
collectClassNameDiagnostics(node, source, filename, tokenFilter, diagnostics);
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
if (attrName === "sz" && ancestors.some((parent) => parent.type === "JSXAttribute")) {
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
});
|
|
1361
|
+
return diagnostics;
|
|
1362
|
+
}
|
|
1363
|
+
function collectStringConstants(root) {
|
|
1364
|
+
const constants = /* @__PURE__ */ new Map();
|
|
1365
|
+
walk$1(root, (node) => {
|
|
1366
|
+
if (node.type !== "VariableDeclarator") {
|
|
1367
|
+
return;
|
|
1368
|
+
}
|
|
1369
|
+
const id = node.id;
|
|
1370
|
+
const init = node.init;
|
|
1371
|
+
if (id?.type !== "Identifier" || !init) {
|
|
1372
|
+
return;
|
|
1373
|
+
}
|
|
1374
|
+
const name = id.name;
|
|
1375
|
+
const value = literalStringValue$1(init);
|
|
1376
|
+
if (typeof name === "string" && value !== null) {
|
|
1377
|
+
constants.set(name, value);
|
|
1378
|
+
}
|
|
1379
|
+
});
|
|
1380
|
+
return constants;
|
|
1381
|
+
}
|
|
1382
|
+
function collectStyleMethodDiagnostic(node, source, filename, constants, tokenFilter, diagnostics) {
|
|
1383
|
+
const method = memberMethodName(node.callee);
|
|
1384
|
+
if (!method || !["setProperty", "getPropertyValue", "removeProperty"].includes(method)) {
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
const firstArg = node.arguments?.[0];
|
|
1388
|
+
const name = firstArg ? resolveString(firstArg, constants) : null;
|
|
1389
|
+
if (!name?.startsWith("--") || !shouldReportToken(name, tokenFilter)) {
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
const kind = method === "setProperty" ? "style-set-property" : method === "getPropertyValue" ? "style-get-property" : "style-remove-property";
|
|
1393
|
+
diagnostics.push(createDiagnostic(kind, name, node, source, filename));
|
|
1394
|
+
}
|
|
1395
|
+
function collectJsxStyleDiagnostics(attr, source, filename, constants, tokenFilter, diagnostics) {
|
|
1396
|
+
const expression = jsxExpression(attr);
|
|
1397
|
+
if (expression?.type !== "ObjectExpression") {
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1400
|
+
for (const prop of expression.properties ?? []) {
|
|
1401
|
+
if (prop.type !== "Property") {
|
|
1402
|
+
continue;
|
|
1403
|
+
}
|
|
1404
|
+
const name = propertyKeyString(prop, constants);
|
|
1405
|
+
if (name?.startsWith("--") && shouldReportToken(name, tokenFilter)) {
|
|
1406
|
+
diagnostics.push(createDiagnostic("jsx-style-key", name, prop, source, filename));
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
function collectClassNameDiagnostics(attr, source, filename, tokenFilter, diagnostics) {
|
|
1411
|
+
for (const value of jsxAttributeStringValues(attr)) {
|
|
1412
|
+
for (const name of extractVarReferences(value)) {
|
|
1413
|
+
if (shouldReportToken(name, tokenFilter)) {
|
|
1414
|
+
diagnostics.push(
|
|
1415
|
+
createDiagnostic("class-string-var-reference", name, attr, source, filename)
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
function jsxAttributeName(attr) {
|
|
1422
|
+
const name = attr.name;
|
|
1423
|
+
return name?.type === "JSXIdentifier" ? name.name ?? null : null;
|
|
1424
|
+
}
|
|
1425
|
+
function jsxExpression(attr) {
|
|
1426
|
+
const value = attr.value;
|
|
1427
|
+
if (value?.type !== "JSXExpressionContainer") {
|
|
1428
|
+
return null;
|
|
1429
|
+
}
|
|
1430
|
+
return value.expression ?? null;
|
|
1431
|
+
}
|
|
1432
|
+
function jsxAttributeStringValues(attr) {
|
|
1433
|
+
const value = attr.value;
|
|
1434
|
+
if (!value) {
|
|
1435
|
+
return [];
|
|
1436
|
+
}
|
|
1437
|
+
const direct = literalStringValue$1(value);
|
|
1438
|
+
if (direct !== null) {
|
|
1439
|
+
return [direct];
|
|
1440
|
+
}
|
|
1441
|
+
const expression = jsxExpression(attr);
|
|
1442
|
+
if (!expression) {
|
|
1443
|
+
return [];
|
|
1444
|
+
}
|
|
1445
|
+
const exprValue = literalStringValue$1(expression);
|
|
1446
|
+
if (exprValue !== null) {
|
|
1447
|
+
return [exprValue];
|
|
1448
|
+
}
|
|
1449
|
+
if (expression.type === "TemplateLiteral") {
|
|
1450
|
+
return templateStaticParts(expression);
|
|
1451
|
+
}
|
|
1452
|
+
return [];
|
|
1453
|
+
}
|
|
1454
|
+
function resolveString(node, constants) {
|
|
1455
|
+
const literal = literalStringValue$1(node);
|
|
1456
|
+
if (literal !== null) {
|
|
1457
|
+
return literal;
|
|
1458
|
+
}
|
|
1459
|
+
if (node.type === "Identifier") {
|
|
1460
|
+
const name = node.name;
|
|
1461
|
+
return typeof name === "string" ? constants.get(name) ?? null : null;
|
|
1462
|
+
}
|
|
1463
|
+
return null;
|
|
1464
|
+
}
|
|
1465
|
+
function literalStringValue$1(node) {
|
|
1466
|
+
if (node.type !== "Literal") {
|
|
1467
|
+
return null;
|
|
1468
|
+
}
|
|
1469
|
+
const value = node.value;
|
|
1470
|
+
return typeof value === "string" ? value : null;
|
|
1471
|
+
}
|
|
1472
|
+
function propertyKeyString(property, constants) {
|
|
1473
|
+
const key = property.key;
|
|
1474
|
+
const computed = property.computed === true;
|
|
1475
|
+
if (!key) {
|
|
1476
|
+
return null;
|
|
1477
|
+
}
|
|
1478
|
+
if (computed) {
|
|
1479
|
+
return resolveString(key, constants);
|
|
1480
|
+
}
|
|
1481
|
+
if (key.type === "Identifier") {
|
|
1482
|
+
const name = key.name;
|
|
1483
|
+
return typeof name === "string" ? name : null;
|
|
1484
|
+
}
|
|
1485
|
+
return literalStringValue$1(key);
|
|
1486
|
+
}
|
|
1487
|
+
function memberMethodName(callee) {
|
|
1488
|
+
if (callee?.type !== "MemberExpression") {
|
|
1489
|
+
return null;
|
|
1490
|
+
}
|
|
1491
|
+
const property = callee.property;
|
|
1492
|
+
if (!property) {
|
|
1493
|
+
return null;
|
|
1494
|
+
}
|
|
1495
|
+
if (property.type === "Identifier") {
|
|
1496
|
+
const name = property.name;
|
|
1497
|
+
return typeof name === "string" ? name : null;
|
|
1498
|
+
}
|
|
1499
|
+
return literalStringValue$1(property);
|
|
1500
|
+
}
|
|
1501
|
+
function templateStaticParts(node) {
|
|
1502
|
+
const quasis = node.quasis ?? [];
|
|
1503
|
+
const parts = [];
|
|
1504
|
+
for (const quasi of quasis) {
|
|
1505
|
+
const value = quasi.value;
|
|
1506
|
+
const cooked = value?.cooked;
|
|
1507
|
+
const raw = value?.raw;
|
|
1508
|
+
if (typeof cooked === "string") {
|
|
1509
|
+
parts.push(cooked);
|
|
1510
|
+
} else if (typeof raw === "string") {
|
|
1511
|
+
parts.push(raw);
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
return parts;
|
|
1515
|
+
}
|
|
1516
|
+
function extractVarReferences(value) {
|
|
1517
|
+
const refs = /* @__PURE__ */ new Set();
|
|
1518
|
+
for (const match of value.matchAll(CSS_VAR_REFERENCE_RE)) {
|
|
1519
|
+
refs.add(match[1]);
|
|
1520
|
+
}
|
|
1521
|
+
return [...refs].sort();
|
|
1522
|
+
}
|
|
1523
|
+
function shouldReportToken(name, tokenFilter) {
|
|
1524
|
+
return tokenFilter === null || tokenFilter.has(name);
|
|
1525
|
+
}
|
|
1526
|
+
function createDiagnostic(kind, name, node, source, filename) {
|
|
1527
|
+
return {
|
|
1528
|
+
kind,
|
|
1529
|
+
name,
|
|
1530
|
+
location: offsetToLocation(source, node.start, filename),
|
|
1531
|
+
message: `${name} is used outside csszyx-owned global variable alias rewrites (${kind}).`
|
|
1532
|
+
};
|
|
1533
|
+
}
|
|
1534
|
+
function offsetToLocation(source, offset, filename) {
|
|
1535
|
+
let line = 1;
|
|
1536
|
+
let column = 1;
|
|
1537
|
+
for (let index = 0; index < offset; index++) {
|
|
1538
|
+
if (source.charCodeAt(index) === 10) {
|
|
1539
|
+
line++;
|
|
1540
|
+
column = 1;
|
|
1541
|
+
} else {
|
|
1542
|
+
column++;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
return { filePath: filename, line, column };
|
|
1546
|
+
}
|
|
1547
|
+
function walk$1(node, visit, ancestors = []) {
|
|
1548
|
+
if (!isOxcNode$1(node)) {
|
|
1549
|
+
return;
|
|
1550
|
+
}
|
|
1551
|
+
visit(node, ancestors);
|
|
1552
|
+
ancestors.push(node);
|
|
1553
|
+
for (const key of Object.keys(node)) {
|
|
1554
|
+
if (isAstMetadataKey$1(key)) {
|
|
1555
|
+
continue;
|
|
1556
|
+
}
|
|
1557
|
+
const child = node[key];
|
|
1558
|
+
if (Array.isArray(child)) {
|
|
1559
|
+
for (const item of child) {
|
|
1560
|
+
walk$1(item, visit, ancestors);
|
|
1561
|
+
}
|
|
1562
|
+
} else if (child && typeof child === "object") {
|
|
1563
|
+
walk$1(child, visit, ancestors);
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
ancestors.pop();
|
|
1567
|
+
}
|
|
1568
|
+
function isOxcNode$1(value) {
|
|
1569
|
+
return Boolean(
|
|
1570
|
+
value && typeof value === "object" && typeof value.type === "string"
|
|
1571
|
+
);
|
|
1572
|
+
}
|
|
1573
|
+
function isAstMetadataKey$1(key) {
|
|
1574
|
+
return key === "loc" || key === "range" || key === "start" || key === "end" || key === "type";
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1307
1577
|
function findLCA(nodeA, nodeB, parentMap) {
|
|
1308
1578
|
const ancestorsA = /* @__PURE__ */ new Set();
|
|
1309
1579
|
let current = nodeA;
|
|
@@ -1637,6 +1907,155 @@ function injectRecoveryToken(attributes, token) {
|
|
|
1637
1907
|
};
|
|
1638
1908
|
}
|
|
1639
1909
|
|
|
1910
|
+
const DEFAULT_MAX_DEPTH = 5;
|
|
1911
|
+
function planComponentVariableHoistsWithDiagnostics(nodes, usages, options = {}) {
|
|
1912
|
+
const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
1913
|
+
const nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
1914
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1915
|
+
for (const usage of usages) {
|
|
1916
|
+
const groupKey = `${usage.name}\0${usage.valueKey}`;
|
|
1917
|
+
const group = groups.get(groupKey);
|
|
1918
|
+
if (group) {
|
|
1919
|
+
group.push(usage);
|
|
1920
|
+
} else {
|
|
1921
|
+
groups.set(groupKey, [usage]);
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
const plans = [];
|
|
1925
|
+
const diagnostics = [];
|
|
1926
|
+
for (const group of groups.values()) {
|
|
1927
|
+
if (group.length < 2) {
|
|
1928
|
+
continue;
|
|
1929
|
+
}
|
|
1930
|
+
const targetElementId = findLowestCommonAncestor(
|
|
1931
|
+
group.map((usage) => usage.elementId),
|
|
1932
|
+
nodeById
|
|
1933
|
+
);
|
|
1934
|
+
if (!targetElementId) {
|
|
1935
|
+
diagnostics.push(buildHoistDiagnostic(group, "no-lca"));
|
|
1936
|
+
continue;
|
|
1937
|
+
}
|
|
1938
|
+
const target = nodeById.get(targetElementId);
|
|
1939
|
+
if (!target || target.canHost === false) {
|
|
1940
|
+
diagnostics.push(buildHoistDiagnostic(group, "non-host-ancestor"));
|
|
1941
|
+
continue;
|
|
1942
|
+
}
|
|
1943
|
+
if (group.some(
|
|
1944
|
+
(usage) => distanceToAncestor(usage.elementId, targetElementId, nodeById) > maxDepth
|
|
1945
|
+
)) {
|
|
1946
|
+
diagnostics.push(buildHoistDiagnostic(group, "max-depth", maxDepth));
|
|
1947
|
+
continue;
|
|
1948
|
+
}
|
|
1949
|
+
plans.push({
|
|
1950
|
+
name: group[0].name,
|
|
1951
|
+
valueKey: group[0].valueKey,
|
|
1952
|
+
targetElementId,
|
|
1953
|
+
usageIds: group.map((usage) => usage.id)
|
|
1954
|
+
});
|
|
1955
|
+
}
|
|
1956
|
+
return { plans, diagnostics };
|
|
1957
|
+
}
|
|
1958
|
+
function buildHoistDiagnostic(group, reason, maxDepth) {
|
|
1959
|
+
return {
|
|
1960
|
+
name: group[0]?.name ?? "",
|
|
1961
|
+
reason,
|
|
1962
|
+
usageCount: group.length,
|
|
1963
|
+
...maxDepth === void 0 ? {} : { maxDepth }
|
|
1964
|
+
};
|
|
1965
|
+
}
|
|
1966
|
+
function findLowestCommonAncestor(elementIds, nodeById) {
|
|
1967
|
+
const [first, ...rest] = elementIds;
|
|
1968
|
+
if (!first) {
|
|
1969
|
+
return null;
|
|
1970
|
+
}
|
|
1971
|
+
let currentAncestors = ancestorChain(first, nodeById);
|
|
1972
|
+
for (const elementId of rest) {
|
|
1973
|
+
const nextAncestors = new Set(ancestorChain(elementId, nodeById));
|
|
1974
|
+
currentAncestors = currentAncestors.filter((id) => nextAncestors.has(id));
|
|
1975
|
+
if (currentAncestors.length === 0) {
|
|
1976
|
+
return null;
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
return currentAncestors[0] ?? null;
|
|
1980
|
+
}
|
|
1981
|
+
function ancestorChain(elementId, nodeById) {
|
|
1982
|
+
const chain = [];
|
|
1983
|
+
let current = elementId;
|
|
1984
|
+
while (current) {
|
|
1985
|
+
const node = nodeById.get(current);
|
|
1986
|
+
if (!node) {
|
|
1987
|
+
break;
|
|
1988
|
+
}
|
|
1989
|
+
chain.push(current);
|
|
1990
|
+
current = node.parentId;
|
|
1991
|
+
}
|
|
1992
|
+
return chain;
|
|
1993
|
+
}
|
|
1994
|
+
function distanceToAncestor(elementId, ancestorId, nodeById) {
|
|
1995
|
+
let distance = 0;
|
|
1996
|
+
let current = elementId;
|
|
1997
|
+
while (current) {
|
|
1998
|
+
if (current === ancestorId) {
|
|
1999
|
+
return distance;
|
|
2000
|
+
}
|
|
2001
|
+
const node = nodeById.get(current);
|
|
2002
|
+
if (!node) {
|
|
2003
|
+
break;
|
|
2004
|
+
}
|
|
2005
|
+
current = node.parentId;
|
|
2006
|
+
distance++;
|
|
2007
|
+
}
|
|
2008
|
+
return Number.POSITIVE_INFINITY;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
function planCSSVariableNames(usages, options = {}) {
|
|
2012
|
+
const componentNames = /* @__PURE__ */ new Map();
|
|
2013
|
+
const scopedNamesByElement = /* @__PURE__ */ new Map();
|
|
2014
|
+
const reservedNames = options.reservedNames ?? /* @__PURE__ */ new Set();
|
|
2015
|
+
return usages.map((usage) => {
|
|
2016
|
+
if (usage.tier === "component") {
|
|
2017
|
+
const key2 = canonicalUsageKey(usage);
|
|
2018
|
+
let name2 = componentNames.get(key2);
|
|
2019
|
+
if (!name2) {
|
|
2020
|
+
name2 = allocateVariableName("--c", componentNames.size, reservedNames);
|
|
2021
|
+
componentNames.set(key2, name2);
|
|
2022
|
+
}
|
|
2023
|
+
return { ...usage, name: name2 };
|
|
2024
|
+
}
|
|
2025
|
+
const elementId = usage.elementId ?? "";
|
|
2026
|
+
const elementNames = getOrCreate(scopedNamesByElement, elementId, () => /* @__PURE__ */ new Map());
|
|
2027
|
+
const key = canonicalUsageKey(usage);
|
|
2028
|
+
let name = elementNames.get(key);
|
|
2029
|
+
if (!name) {
|
|
2030
|
+
name = allocateVariableName("--s", elementNames.size, reservedNames);
|
|
2031
|
+
elementNames.set(key, name);
|
|
2032
|
+
}
|
|
2033
|
+
return { ...usage, name };
|
|
2034
|
+
});
|
|
2035
|
+
}
|
|
2036
|
+
function allocateVariableName(prefix, startIndex, reservedNames) {
|
|
2037
|
+
let index = startIndex;
|
|
2038
|
+
while (true) {
|
|
2039
|
+
const name = `${prefix}${encode(index)}`;
|
|
2040
|
+
if (!reservedNames.has(name)) {
|
|
2041
|
+
return name;
|
|
2042
|
+
}
|
|
2043
|
+
index++;
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
function canonicalUsageKey(usage) {
|
|
2047
|
+
return `${usage.variantChain ?? ""}\0${usage.propertyKey}`;
|
|
2048
|
+
}
|
|
2049
|
+
function getOrCreate(map, key, create) {
|
|
2050
|
+
const existing = map.get(key);
|
|
2051
|
+
if (existing) {
|
|
2052
|
+
return existing;
|
|
2053
|
+
}
|
|
2054
|
+
const value = create();
|
|
2055
|
+
map.set(key, value);
|
|
2056
|
+
return value;
|
|
2057
|
+
}
|
|
2058
|
+
|
|
1640
2059
|
class OxcNotImplementedError extends Error {
|
|
1641
2060
|
/**
|
|
1642
2061
|
* @param slice The Phase D slice expected to implement this path.
|
|
@@ -1652,6 +2071,8 @@ function transformOxc(source, filename, options) {
|
|
|
1652
2071
|
const rawClassNames = /* @__PURE__ */ new Set();
|
|
1653
2072
|
const diagnostics = [];
|
|
1654
2073
|
const recoveryTokens = /* @__PURE__ */ new Map();
|
|
2074
|
+
const cssVariableMap = /* @__PURE__ */ new Map();
|
|
2075
|
+
const globalVarAliases = normalizeGlobalVarAliases$1(options?.globalVarAliases);
|
|
1655
2076
|
if (!source.includes("sz")) {
|
|
1656
2077
|
return {
|
|
1657
2078
|
code: source,
|
|
@@ -1662,7 +2083,8 @@ function transformOxc(source, filename, options) {
|
|
|
1662
2083
|
classes,
|
|
1663
2084
|
rawClassNames,
|
|
1664
2085
|
diagnostics,
|
|
1665
|
-
recoveryTokens
|
|
2086
|
+
recoveryTokens,
|
|
2087
|
+
cssVariableMap
|
|
1666
2088
|
};
|
|
1667
2089
|
}
|
|
1668
2090
|
const effectiveFilename = filename ?? "file.tsx";
|
|
@@ -1677,6 +2099,18 @@ function transformOxc(source, filename, options) {
|
|
|
1677
2099
|
const edits = new MagicString(source);
|
|
1678
2100
|
const objectBindings = collectObjectBindings(parsed.program);
|
|
1679
2101
|
const conditionalBindings = collectConditionalBindings(parsed.program);
|
|
2102
|
+
const reservedCSSVariableNames = options?.mangleVars ? collectStaticStyleCustomPropertyNames(parsed.program) : void 0;
|
|
2103
|
+
const componentHoists = options?.mangleVars ? planOxcComponentVariableHoists(
|
|
2104
|
+
parsed.program,
|
|
2105
|
+
effectiveFilename,
|
|
2106
|
+
objectBindings,
|
|
2107
|
+
source,
|
|
2108
|
+
options.mangleVarHoistMaxDepth,
|
|
2109
|
+
reservedCSSVariableNames
|
|
2110
|
+
) : null;
|
|
2111
|
+
if (componentHoists) {
|
|
2112
|
+
diagnostics.push(...componentHoists.diagnostics);
|
|
2113
|
+
}
|
|
1680
2114
|
let transformed = false;
|
|
1681
2115
|
let usesRuntime = false;
|
|
1682
2116
|
let usesMerge = false;
|
|
@@ -1702,6 +2136,24 @@ function transformOxc(source, filename, options) {
|
|
|
1702
2136
|
let szRecoverAttr = null;
|
|
1703
2137
|
let alreadyTagged = false;
|
|
1704
2138
|
let lastAttr = null;
|
|
2139
|
+
let appliedHoistedStyleProps = false;
|
|
2140
|
+
const elementId = elementIdForOpening(openingNode);
|
|
2141
|
+
const hoistedStyleProps = componentHoists?.stylePropsByTarget.get(elementId) ?? [];
|
|
2142
|
+
const applyHoistedStyleProps = () => {
|
|
2143
|
+
if (appliedHoistedStyleProps || hoistedStyleProps.length === 0) {
|
|
2144
|
+
return;
|
|
2145
|
+
}
|
|
2146
|
+
applyStyleProps(
|
|
2147
|
+
edits,
|
|
2148
|
+
source,
|
|
2149
|
+
styleAttr,
|
|
2150
|
+
lastAttr,
|
|
2151
|
+
hoistedStyleProps,
|
|
2152
|
+
openingNode.name.end
|
|
2153
|
+
);
|
|
2154
|
+
appliedHoistedStyleProps = true;
|
|
2155
|
+
transformed = true;
|
|
2156
|
+
};
|
|
1705
2157
|
for (const attrRaw of attrs) {
|
|
1706
2158
|
if (attrRaw.type !== "JSXAttribute") {
|
|
1707
2159
|
continue;
|
|
@@ -1762,6 +2214,7 @@ function transformOxc(source, filename, options) {
|
|
|
1762
2214
|
}
|
|
1763
2215
|
}
|
|
1764
2216
|
if (szAttrs.length === 0) {
|
|
2217
|
+
applyHoistedStyleProps();
|
|
1765
2218
|
return;
|
|
1766
2219
|
}
|
|
1767
2220
|
const szDerived = [];
|
|
@@ -1798,7 +2251,9 @@ function transformOxc(source, filename, options) {
|
|
|
1798
2251
|
effectiveFilename,
|
|
1799
2252
|
objectBindings,
|
|
1800
2253
|
source,
|
|
1801
|
-
classes
|
|
2254
|
+
classes,
|
|
2255
|
+
globalVarAliases,
|
|
2256
|
+
cssVariableMap
|
|
1802
2257
|
);
|
|
1803
2258
|
if (conditionalClassExpr) {
|
|
1804
2259
|
if (classNameAttr || szAttrs.length > 1) {
|
|
@@ -1820,7 +2275,11 @@ function transformOxc(source, filename, options) {
|
|
|
1820
2275
|
const bound = objectBindings.get(identifierName);
|
|
1821
2276
|
if (bound) {
|
|
1822
2277
|
const result2 = transform(
|
|
1823
|
-
|
|
2278
|
+
applyGlobalVarAliasesToSzObject(
|
|
2279
|
+
astObjectToSzObject(bound, effectiveFilename, objectBindings),
|
|
2280
|
+
globalVarAliases,
|
|
2281
|
+
cssVariableMap
|
|
2282
|
+
)
|
|
1824
2283
|
);
|
|
1825
2284
|
for (const c of result2.className.split(/\s+/)) {
|
|
1826
2285
|
if (c) {
|
|
@@ -1837,7 +2296,9 @@ function transformOxc(source, filename, options) {
|
|
|
1837
2296
|
effectiveFilename,
|
|
1838
2297
|
objectBindings,
|
|
1839
2298
|
source,
|
|
1840
|
-
classes
|
|
2299
|
+
classes,
|
|
2300
|
+
globalVarAliases,
|
|
2301
|
+
cssVariableMap
|
|
1841
2302
|
);
|
|
1842
2303
|
if (conditionalClassExpr) {
|
|
1843
2304
|
if (classNameAttr || szAttrs.length > 1) {
|
|
@@ -1859,7 +2320,9 @@ function transformOxc(source, filename, options) {
|
|
|
1859
2320
|
const arrayClasses = astArrayToStaticClasses(
|
|
1860
2321
|
expression,
|
|
1861
2322
|
effectiveFilename,
|
|
1862
|
-
objectBindings
|
|
2323
|
+
objectBindings,
|
|
2324
|
+
globalVarAliases,
|
|
2325
|
+
cssVariableMap
|
|
1863
2326
|
);
|
|
1864
2327
|
if (arrayClasses === null) {
|
|
1865
2328
|
collectArrayCandidateClasses(
|
|
@@ -1897,7 +2360,9 @@ function transformOxc(source, filename, options) {
|
|
|
1897
2360
|
effectiveFilename,
|
|
1898
2361
|
objectBindings,
|
|
1899
2362
|
source,
|
|
1900
|
-
classes
|
|
2363
|
+
classes,
|
|
2364
|
+
globalVarAliases,
|
|
2365
|
+
cssVariableMap
|
|
1901
2366
|
);
|
|
1902
2367
|
if (conditionalSpreadClassExpr) {
|
|
1903
2368
|
if (classNameAttr || szAttrs.length > 1) {
|
|
@@ -1917,9 +2382,15 @@ function transformOxc(source, filename, options) {
|
|
|
1917
2382
|
expression,
|
|
1918
2383
|
effectiveFilename,
|
|
1919
2384
|
objectBindings,
|
|
1920
|
-
source
|
|
2385
|
+
source,
|
|
2386
|
+
options,
|
|
2387
|
+
componentHoists?.usageNamesByElement.get(elementId),
|
|
2388
|
+
cssVariableMap,
|
|
2389
|
+
reservedCSSVariableNames,
|
|
2390
|
+
globalVarAliases
|
|
1921
2391
|
);
|
|
1922
2392
|
if (partial && szAttrs.length === 1) {
|
|
2393
|
+
const mergedStyleProps = hoistedStyleProps.length > 0 ? [...hoistedStyleProps, ...partial.styleProps] : partial.styleProps;
|
|
1923
2394
|
if (classNameAttr?.value?.type === "JSXExpressionContainer") {
|
|
1924
2395
|
const classExpression = classNameAttr.value.expression;
|
|
1925
2396
|
const classExpressionSource = source.slice(
|
|
@@ -1932,7 +2403,15 @@ function transformOxc(source, filename, options) {
|
|
|
1932
2403
|
`className={_szMerge(${classExpressionSource}, ${JSON.stringify(partial.className)})}`
|
|
1933
2404
|
);
|
|
1934
2405
|
edits.remove(whitespaceStart(source, szAttr.start), szAttr.end);
|
|
1935
|
-
applyStyleProps(
|
|
2406
|
+
applyStyleProps(
|
|
2407
|
+
edits,
|
|
2408
|
+
source,
|
|
2409
|
+
styleAttr,
|
|
2410
|
+
lastAttr,
|
|
2411
|
+
mergedStyleProps,
|
|
2412
|
+
openingNode.name.end
|
|
2413
|
+
);
|
|
2414
|
+
appliedHoistedStyleProps = true;
|
|
1936
2415
|
for (const c of partial.className.split(/\s+/)) {
|
|
1937
2416
|
if (c) {
|
|
1938
2417
|
classes.add(c);
|
|
@@ -1956,7 +2435,15 @@ function transformOxc(source, filename, options) {
|
|
|
1956
2435
|
} else {
|
|
1957
2436
|
edits.overwrite(szAttr.start, szAttr.end, partial.classNameAttr);
|
|
1958
2437
|
}
|
|
1959
|
-
applyStyleProps(
|
|
2438
|
+
applyStyleProps(
|
|
2439
|
+
edits,
|
|
2440
|
+
source,
|
|
2441
|
+
styleAttr,
|
|
2442
|
+
lastAttr,
|
|
2443
|
+
mergedStyleProps,
|
|
2444
|
+
openingNode.name.end
|
|
2445
|
+
);
|
|
2446
|
+
appliedHoistedStyleProps = true;
|
|
1960
2447
|
for (const c of partial.className.split(/\s+/)) {
|
|
1961
2448
|
if (c) {
|
|
1962
2449
|
classes.add(c);
|
|
@@ -1972,7 +2459,9 @@ function transformOxc(source, filename, options) {
|
|
|
1972
2459
|
}
|
|
1973
2460
|
throw err;
|
|
1974
2461
|
}
|
|
1975
|
-
const result = transform(
|
|
2462
|
+
const result = transform(
|
|
2463
|
+
applyGlobalVarAliasesToSzObject(szObj, globalVarAliases, cssVariableMap)
|
|
2464
|
+
);
|
|
1976
2465
|
for (const c of result.className.split(/\s+/)) {
|
|
1977
2466
|
if (c) {
|
|
1978
2467
|
szDerived.push(c);
|
|
@@ -2005,6 +2494,7 @@ function transformOxc(source, filename, options) {
|
|
|
2005
2494
|
transformed = true;
|
|
2006
2495
|
return;
|
|
2007
2496
|
}
|
|
2497
|
+
applyHoistedStyleProps();
|
|
2008
2498
|
const existingRaw = classNameAttr ? stringLiteralValue(classNameAttr.value) : null;
|
|
2009
2499
|
const mergedClasses = [
|
|
2010
2500
|
...existingRaw ? existingRaw.split(/\s+/).filter(Boolean) : [],
|
|
@@ -2039,7 +2529,8 @@ function transformOxc(source, filename, options) {
|
|
|
2039
2529
|
classes,
|
|
2040
2530
|
rawClassNames,
|
|
2041
2531
|
diagnostics,
|
|
2042
|
-
recoveryTokens
|
|
2532
|
+
recoveryTokens,
|
|
2533
|
+
cssVariableMap
|
|
2043
2534
|
};
|
|
2044
2535
|
}
|
|
2045
2536
|
function stringLiteralValue(value) {
|
|
@@ -2148,7 +2639,7 @@ function astObjectToSzObject(node, filename, bindings) {
|
|
|
2148
2639
|
}
|
|
2149
2640
|
return result;
|
|
2150
2641
|
}
|
|
2151
|
-
function astArrayToStaticClasses(node, filename, bindings) {
|
|
2642
|
+
function astArrayToStaticClasses(node, filename, bindings, globalVarAliases, cssVariableMap) {
|
|
2152
2643
|
const out = [];
|
|
2153
2644
|
for (const element of node.elements) {
|
|
2154
2645
|
if (!element || isFalsyLiteral(element)) {
|
|
@@ -2165,7 +2656,13 @@ function astArrayToStaticClasses(node, filename, bindings) {
|
|
|
2165
2656
|
}
|
|
2166
2657
|
let result;
|
|
2167
2658
|
try {
|
|
2168
|
-
result = transform(
|
|
2659
|
+
result = transform(
|
|
2660
|
+
applyGlobalVarAliasesToSzObject(
|
|
2661
|
+
astObjectToSzObject(objectNode, filename, bindings),
|
|
2662
|
+
globalVarAliases,
|
|
2663
|
+
cssVariableMap
|
|
2664
|
+
)
|
|
2665
|
+
);
|
|
2169
2666
|
} catch (err) {
|
|
2170
2667
|
if (err instanceof OxcNotImplementedError) {
|
|
2171
2668
|
return null;
|
|
@@ -2262,7 +2759,7 @@ function resolveObjectExpression(node, bindings) {
|
|
|
2262
2759
|
}
|
|
2263
2760
|
return null;
|
|
2264
2761
|
}
|
|
2265
|
-
function buildConditionalSpreadClassExpression(node, filename, bindings, source, classes) {
|
|
2762
|
+
function buildConditionalSpreadClassExpression(node, filename, bindings, source, classes, globalVarAliases, cssVariableMap) {
|
|
2266
2763
|
let conditionalSpread = null;
|
|
2267
2764
|
const otherProps = [];
|
|
2268
2765
|
for (const prop of node.properties) {
|
|
@@ -2285,14 +2782,18 @@ function buildConditionalSpreadClassExpression(node, filename, bindings, source,
|
|
|
2285
2782
|
otherProps,
|
|
2286
2783
|
node,
|
|
2287
2784
|
filename,
|
|
2288
|
-
bindings
|
|
2785
|
+
bindings,
|
|
2786
|
+
globalVarAliases,
|
|
2787
|
+
cssVariableMap
|
|
2289
2788
|
);
|
|
2290
2789
|
const alternate = compileConditionalSpreadBranch(
|
|
2291
2790
|
conditionalSpread.alternate,
|
|
2292
2791
|
otherProps,
|
|
2293
2792
|
node,
|
|
2294
2793
|
filename,
|
|
2295
|
-
bindings
|
|
2794
|
+
bindings,
|
|
2795
|
+
globalVarAliases,
|
|
2796
|
+
cssVariableMap
|
|
2296
2797
|
);
|
|
2297
2798
|
if (consequent === null || alternate === null) {
|
|
2298
2799
|
return null;
|
|
@@ -2305,7 +2806,7 @@ function buildConditionalSpreadClassExpression(node, filename, bindings, source,
|
|
|
2305
2806
|
const testSource = source.slice(conditionalSpread.test.start, conditionalSpread.test.end);
|
|
2306
2807
|
return `${testSource} ? ${JSON.stringify(consequent)} : ${JSON.stringify(alternate)}`;
|
|
2307
2808
|
}
|
|
2308
|
-
function compileConditionalSpreadBranch(branch, otherProps, sourceNode, filename, bindings) {
|
|
2809
|
+
function compileConditionalSpreadBranch(branch, otherProps, sourceNode, filename, bindings, globalVarAliases, cssVariableMap) {
|
|
2309
2810
|
const branchObject = resolveObjectExpression(branch, bindings);
|
|
2310
2811
|
if (!branchObject) {
|
|
2311
2812
|
return null;
|
|
@@ -2317,7 +2818,13 @@ function compileConditionalSpreadBranch(branch, otherProps, sourceNode, filename
|
|
|
2317
2818
|
filename,
|
|
2318
2819
|
bindings
|
|
2319
2820
|
);
|
|
2320
|
-
return transform(
|
|
2821
|
+
return transform(
|
|
2822
|
+
applyGlobalVarAliasesToSzObject(
|
|
2823
|
+
{ ...branchValue, ...overrides },
|
|
2824
|
+
globalVarAliases,
|
|
2825
|
+
cssVariableMap
|
|
2826
|
+
)
|
|
2827
|
+
).className;
|
|
2321
2828
|
} catch (err) {
|
|
2322
2829
|
if (err instanceof OxcNotImplementedError) {
|
|
2323
2830
|
return null;
|
|
@@ -2325,8 +2832,15 @@ function compileConditionalSpreadBranch(branch, otherProps, sourceNode, filename
|
|
|
2325
2832
|
throw err;
|
|
2326
2833
|
}
|
|
2327
2834
|
}
|
|
2328
|
-
function buildPartialObjectTransform(node, filename, bindings, source) {
|
|
2329
|
-
const partial = evaluatePartialObject(
|
|
2835
|
+
function buildPartialObjectTransform(node, filename, bindings, source, options, hoistedNames, cssVariableMap, reservedNames, globalVarAliases = /* @__PURE__ */ new Map()) {
|
|
2836
|
+
const partial = evaluatePartialObject(
|
|
2837
|
+
node,
|
|
2838
|
+
filename,
|
|
2839
|
+
bindings,
|
|
2840
|
+
source,
|
|
2841
|
+
globalVarAliases,
|
|
2842
|
+
cssVariableMap
|
|
2843
|
+
);
|
|
2330
2844
|
if (!partial || partial.dynamicProps.size === 0 && partial.conditionalClasses.length === 0) {
|
|
2331
2845
|
return null;
|
|
2332
2846
|
}
|
|
@@ -2335,11 +2849,17 @@ function buildPartialObjectTransform(node, filename, bindings, source) {
|
|
|
2335
2849
|
}
|
|
2336
2850
|
const classParts = [];
|
|
2337
2851
|
if (Object.keys(partial.staticProps).length > 0) {
|
|
2338
|
-
const { className: className2 } = transform(
|
|
2852
|
+
const { className: className2 } = transform(
|
|
2853
|
+
applyGlobalVarAliasesToSzObject(partial.staticProps, globalVarAliases, cssVariableMap)
|
|
2854
|
+
);
|
|
2339
2855
|
if (className2) {
|
|
2340
2856
|
classParts.push(className2);
|
|
2341
2857
|
}
|
|
2342
2858
|
}
|
|
2859
|
+
if (options?.mangleVars) {
|
|
2860
|
+
applyHoistedVariableNames(partial, hoistedNames, cssVariableMap);
|
|
2861
|
+
applyScopedVariablePlan(partial, hoistedNames, cssVariableMap, reservedNames);
|
|
2862
|
+
}
|
|
2343
2863
|
for (const [, info] of partial.dynamicProps) {
|
|
2344
2864
|
classParts.push(buildCSSVarClassName(info));
|
|
2345
2865
|
}
|
|
@@ -2348,12 +2868,351 @@ function buildPartialObjectTransform(node, filename, bindings, source) {
|
|
|
2348
2868
|
}
|
|
2349
2869
|
const className = classParts.filter(Boolean).join(" ");
|
|
2350
2870
|
const classNameAttr = partial.conditionalClasses.length > 0 ? `className={${buildConditionalClassSource(classParts, partial.conditionalClasses, source)}}` : `className="${className}"`;
|
|
2351
|
-
const styleProps = [...partial.dynamicProps.
|
|
2352
|
-
(info) => `${JSON.stringify(info.varName)}: ${generateStyleValueSource(info, source)}`
|
|
2871
|
+
const styleProps = [...partial.dynamicProps.entries()].filter(([id]) => !hoistedNames?.has(id)).map(
|
|
2872
|
+
([, info]) => `${JSON.stringify(info.varName)}: ${generateStyleValueSource(info, source)}`
|
|
2353
2873
|
);
|
|
2354
2874
|
return { className, classNameAttr, styleProps, usesColorVar: partial.usesColorVar };
|
|
2355
2875
|
}
|
|
2356
|
-
function
|
|
2876
|
+
function applyHoistedVariableNames(partial, hoistedNames, cssVariableMap) {
|
|
2877
|
+
if (!hoistedNames) {
|
|
2878
|
+
return;
|
|
2879
|
+
}
|
|
2880
|
+
for (const [id, name] of hoistedNames) {
|
|
2881
|
+
const info = partial.dynamicProps.get(id);
|
|
2882
|
+
if (info) {
|
|
2883
|
+
addCssVariableMapping(cssVariableMap, info.varName, name);
|
|
2884
|
+
info.varName = name;
|
|
2885
|
+
}
|
|
2886
|
+
}
|
|
2887
|
+
}
|
|
2888
|
+
function applyScopedVariablePlan(partial, hoistedNames, cssVariableMap, reservedNames) {
|
|
2889
|
+
const entries = [...partial.dynamicProps.entries()].filter(([id]) => !hoistedNames?.has(id));
|
|
2890
|
+
const plan = planCSSVariableNames(
|
|
2891
|
+
entries.map(([id]) => ({
|
|
2892
|
+
id,
|
|
2893
|
+
tier: "scoped",
|
|
2894
|
+
elementId: "self",
|
|
2895
|
+
propertyKey: id
|
|
2896
|
+
})),
|
|
2897
|
+
{ reservedNames }
|
|
2898
|
+
);
|
|
2899
|
+
for (const planned of plan) {
|
|
2900
|
+
const info = partial.dynamicProps.get(planned.id);
|
|
2901
|
+
if (info) {
|
|
2902
|
+
addCssVariableMapping(cssVariableMap, info.varName, planned.name);
|
|
2903
|
+
info.varName = planned.name;
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2907
|
+
function addCssVariableMapping(cssVariableMap, original, mangled) {
|
|
2908
|
+
if (!cssVariableMap) {
|
|
2909
|
+
return;
|
|
2910
|
+
}
|
|
2911
|
+
const existing = cssVariableMap.get(original);
|
|
2912
|
+
if (!existing) {
|
|
2913
|
+
cssVariableMap.set(original, mangled);
|
|
2914
|
+
return;
|
|
2915
|
+
}
|
|
2916
|
+
const values = Array.isArray(existing) ? existing : [existing];
|
|
2917
|
+
if (!values.includes(mangled)) {
|
|
2918
|
+
cssVariableMap.set(original, [...values, mangled]);
|
|
2919
|
+
}
|
|
2920
|
+
}
|
|
2921
|
+
function normalizeGlobalVarAliases$1(input) {
|
|
2922
|
+
if (!input) {
|
|
2923
|
+
return /* @__PURE__ */ new Map();
|
|
2924
|
+
}
|
|
2925
|
+
const entries = input instanceof Map ? input.entries() : Array.isArray(input) ? input : Object.entries(input);
|
|
2926
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
2927
|
+
for (const [original, alias] of entries) {
|
|
2928
|
+
if (original.startsWith("--") && alias.startsWith("--")) {
|
|
2929
|
+
aliases.set(original, alias);
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
return aliases;
|
|
2933
|
+
}
|
|
2934
|
+
function applyGlobalVarAliasesToSzObject(object, globalVarAliases, cssVariableMap) {
|
|
2935
|
+
if (globalVarAliases.size === 0) {
|
|
2936
|
+
return object;
|
|
2937
|
+
}
|
|
2938
|
+
const rewritten = {};
|
|
2939
|
+
for (const [key, value] of Object.entries(object)) {
|
|
2940
|
+
rewritten[key] = applyGlobalVarAliasesToSzValue(value, globalVarAliases, cssVariableMap);
|
|
2941
|
+
}
|
|
2942
|
+
return rewritten;
|
|
2943
|
+
}
|
|
2944
|
+
function applyGlobalVarAliasesToSzValue(value, globalVarAliases, cssVariableMap) {
|
|
2945
|
+
if (typeof value === "string") {
|
|
2946
|
+
const alias = globalVarAliases.get(value);
|
|
2947
|
+
if (alias) {
|
|
2948
|
+
addCssVariableMapping(cssVariableMap, value, alias);
|
|
2949
|
+
return alias;
|
|
2950
|
+
}
|
|
2951
|
+
return value;
|
|
2952
|
+
}
|
|
2953
|
+
if (typeof value === "object") {
|
|
2954
|
+
return applyGlobalVarAliasesToSzObject(value, globalVarAliases, cssVariableMap);
|
|
2955
|
+
}
|
|
2956
|
+
return value;
|
|
2957
|
+
}
|
|
2958
|
+
function planOxcComponentVariableHoists(root, filename, bindings, source, maxDepth, reservedNames) {
|
|
2959
|
+
const nodes = [];
|
|
2960
|
+
const candidates = [];
|
|
2961
|
+
collectOxcHoistCandidates(root, null, nodes, candidates, filename, bindings, source);
|
|
2962
|
+
if (candidates.length < 2) {
|
|
2963
|
+
return {
|
|
2964
|
+
stylePropsByTarget: /* @__PURE__ */ new Map(),
|
|
2965
|
+
usageNamesByElement: /* @__PURE__ */ new Map(),
|
|
2966
|
+
diagnostics: []
|
|
2967
|
+
};
|
|
2968
|
+
}
|
|
2969
|
+
const plannedNames = planCSSVariableNames(
|
|
2970
|
+
candidates.map((candidate) => ({
|
|
2971
|
+
id: candidate.id,
|
|
2972
|
+
tier: "component",
|
|
2973
|
+
elementId: candidate.elementId,
|
|
2974
|
+
propertyKey: candidate.propertyKey,
|
|
2975
|
+
variantChain: candidate.variantChain || void 0
|
|
2976
|
+
})),
|
|
2977
|
+
{ reservedNames }
|
|
2978
|
+
);
|
|
2979
|
+
const nameByUsage = new Map(plannedNames.map((entry) => [entry.id, entry.name]));
|
|
2980
|
+
const candidateById = new Map(candidates.map((candidate) => [candidate.id, candidate]));
|
|
2981
|
+
const hoistUsages = candidates.map((candidate) => ({
|
|
2982
|
+
id: candidate.id,
|
|
2983
|
+
elementId: candidate.elementId,
|
|
2984
|
+
name: nameByUsage.get(candidate.id) ?? candidate.info.varName,
|
|
2985
|
+
valueKey: candidate.valueKey
|
|
2986
|
+
}));
|
|
2987
|
+
const analysis = planComponentVariableHoistsWithDiagnostics(nodes, hoistUsages, {
|
|
2988
|
+
maxDepth
|
|
2989
|
+
});
|
|
2990
|
+
const plans = analysis.plans;
|
|
2991
|
+
const stylePropsByTarget = /* @__PURE__ */ new Map();
|
|
2992
|
+
const usageNamesByElement = /* @__PURE__ */ new Map();
|
|
2993
|
+
for (const plan of plans) {
|
|
2994
|
+
const [firstUsageId] = plan.usageIds;
|
|
2995
|
+
const firstCandidate = firstUsageId ? candidateById.get(firstUsageId) : void 0;
|
|
2996
|
+
if (!firstCandidate) {
|
|
2997
|
+
continue;
|
|
2998
|
+
}
|
|
2999
|
+
appendMapArray(
|
|
3000
|
+
stylePropsByTarget,
|
|
3001
|
+
plan.targetElementId,
|
|
3002
|
+
`${JSON.stringify(plan.name)}: ${firstCandidate.valueSource}`
|
|
3003
|
+
);
|
|
3004
|
+
for (const usageId of plan.usageIds) {
|
|
3005
|
+
const candidate = candidateById.get(usageId);
|
|
3006
|
+
if (!candidate) {
|
|
3007
|
+
continue;
|
|
3008
|
+
}
|
|
3009
|
+
getOrCreateMap(usageNamesByElement, candidate.elementId).set(
|
|
3010
|
+
candidate.dynamicKey,
|
|
3011
|
+
plan.name
|
|
3012
|
+
);
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
3015
|
+
return {
|
|
3016
|
+
stylePropsByTarget,
|
|
3017
|
+
usageNamesByElement,
|
|
3018
|
+
diagnostics: analysis.diagnostics.map(formatHoistSkipDiagnostic)
|
|
3019
|
+
};
|
|
3020
|
+
}
|
|
3021
|
+
function formatHoistSkipDiagnostic(diagnostic) {
|
|
3022
|
+
const suffix = diagnostic.reason === "max-depth" && diagnostic.maxDepth !== void 0 ? ` (maxDepth ${diagnostic.maxDepth})` : "";
|
|
3023
|
+
return `[csszyx] mangleVars skipped component CSS variable hoist for ${diagnostic.name} across ${diagnostic.usageCount} usages: ${diagnostic.reason}${suffix}`;
|
|
3024
|
+
}
|
|
3025
|
+
function collectOxcHoistCandidates(node, parentElementId, nodes, candidates, filename, bindings, source) {
|
|
3026
|
+
if (node.type === "JSXElement") {
|
|
3027
|
+
const element = node;
|
|
3028
|
+
const opening = element.openingElement;
|
|
3029
|
+
const elementId = elementIdForOpening(opening);
|
|
3030
|
+
nodes.push({
|
|
3031
|
+
id: elementId,
|
|
3032
|
+
parentId: parentElementId,
|
|
3033
|
+
canHost: canHostHoistedStyleProps(opening)
|
|
3034
|
+
});
|
|
3035
|
+
collectOpeningHoistCandidates(opening, elementId, candidates, filename, bindings, source);
|
|
3036
|
+
for (const child of element.children) {
|
|
3037
|
+
collectOxcHoistCandidates(
|
|
3038
|
+
child,
|
|
3039
|
+
elementId,
|
|
3040
|
+
nodes,
|
|
3041
|
+
candidates,
|
|
3042
|
+
filename,
|
|
3043
|
+
bindings,
|
|
3044
|
+
source
|
|
3045
|
+
);
|
|
3046
|
+
}
|
|
3047
|
+
return;
|
|
3048
|
+
}
|
|
3049
|
+
if (node.type === "JSXFragment") {
|
|
3050
|
+
const fragment = node;
|
|
3051
|
+
const elementId = `f${node.start}`;
|
|
3052
|
+
nodes.push({ id: elementId, parentId: parentElementId, canHost: false });
|
|
3053
|
+
for (const child of fragment.children) {
|
|
3054
|
+
collectOxcHoistCandidates(
|
|
3055
|
+
child,
|
|
3056
|
+
elementId,
|
|
3057
|
+
nodes,
|
|
3058
|
+
candidates,
|
|
3059
|
+
filename,
|
|
3060
|
+
bindings,
|
|
3061
|
+
source
|
|
3062
|
+
);
|
|
3063
|
+
}
|
|
3064
|
+
return;
|
|
3065
|
+
}
|
|
3066
|
+
for (const key of Object.keys(node)) {
|
|
3067
|
+
if (isAstMetadataKey(key)) {
|
|
3068
|
+
continue;
|
|
3069
|
+
}
|
|
3070
|
+
const child = node[key];
|
|
3071
|
+
if (Array.isArray(child)) {
|
|
3072
|
+
for (const item of child) {
|
|
3073
|
+
if (isOxcNode(item)) {
|
|
3074
|
+
collectOxcHoistCandidates(
|
|
3075
|
+
item,
|
|
3076
|
+
parentElementId,
|
|
3077
|
+
nodes,
|
|
3078
|
+
candidates,
|
|
3079
|
+
filename,
|
|
3080
|
+
bindings,
|
|
3081
|
+
source
|
|
3082
|
+
);
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
} else if (isOxcNode(child)) {
|
|
3086
|
+
collectOxcHoistCandidates(
|
|
3087
|
+
child,
|
|
3088
|
+
parentElementId,
|
|
3089
|
+
nodes,
|
|
3090
|
+
candidates,
|
|
3091
|
+
filename,
|
|
3092
|
+
bindings,
|
|
3093
|
+
source
|
|
3094
|
+
);
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
function collectOpeningHoistCandidates(opening, elementId, candidates, filename, bindings, source) {
|
|
3099
|
+
for (const attrRaw of opening.attributes ?? []) {
|
|
3100
|
+
if (attrRaw.type !== "JSXAttribute") {
|
|
3101
|
+
continue;
|
|
3102
|
+
}
|
|
3103
|
+
const attr = attrRaw;
|
|
3104
|
+
if (attr.name?.name !== "sz" || attr.value?.type !== "JSXExpressionContainer") {
|
|
3105
|
+
continue;
|
|
3106
|
+
}
|
|
3107
|
+
const expression = attr.value.expression;
|
|
3108
|
+
if (expression.type !== "ObjectExpression") {
|
|
3109
|
+
continue;
|
|
3110
|
+
}
|
|
3111
|
+
const partial = evaluatePartialObject(
|
|
3112
|
+
expression,
|
|
3113
|
+
filename,
|
|
3114
|
+
bindings,
|
|
3115
|
+
source,
|
|
3116
|
+
/* @__PURE__ */ new Map(),
|
|
3117
|
+
void 0
|
|
3118
|
+
);
|
|
3119
|
+
if (!partial || partial.conditionalClasses.length > 0) {
|
|
3120
|
+
continue;
|
|
3121
|
+
}
|
|
3122
|
+
for (const [dynamicKey, info] of partial.dynamicProps) {
|
|
3123
|
+
candidates.push({
|
|
3124
|
+
id: `${elementId}:${dynamicKey}`,
|
|
3125
|
+
elementId,
|
|
3126
|
+
dynamicKey,
|
|
3127
|
+
propertyKey: dynamicKey,
|
|
3128
|
+
variantChain: info.variantChain,
|
|
3129
|
+
valueSource: generateStyleValueSource(info, source),
|
|
3130
|
+
valueKey: buildDynamicValueKey(info, source),
|
|
3131
|
+
info
|
|
3132
|
+
});
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
}
|
|
3136
|
+
function elementIdForOpening(opening) {
|
|
3137
|
+
return `e${opening.start}`;
|
|
3138
|
+
}
|
|
3139
|
+
function canHostHoistedStyleProps(opening) {
|
|
3140
|
+
if (!isDomJsxOpening(opening)) {
|
|
3141
|
+
return false;
|
|
3142
|
+
}
|
|
3143
|
+
const styleAttr = findJsxAttribute(opening, "style");
|
|
3144
|
+
return !styleAttr || styleAttr.value?.type === "JSXExpressionContainer";
|
|
3145
|
+
}
|
|
3146
|
+
function isDomJsxOpening(opening) {
|
|
3147
|
+
if (opening.name.type !== "JSXIdentifier") {
|
|
3148
|
+
return false;
|
|
3149
|
+
}
|
|
3150
|
+
const name = String(opening.name.name);
|
|
3151
|
+
return name.length > 0 && name.charAt(0) === name.charAt(0).toLowerCase();
|
|
3152
|
+
}
|
|
3153
|
+
function findJsxAttribute(opening, name) {
|
|
3154
|
+
for (const attrRaw of opening.attributes ?? []) {
|
|
3155
|
+
if (attrRaw.type === "JSXAttribute") {
|
|
3156
|
+
const attr = attrRaw;
|
|
3157
|
+
if (attr.name?.name === name) {
|
|
3158
|
+
return attr;
|
|
3159
|
+
}
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
return null;
|
|
3163
|
+
}
|
|
3164
|
+
function collectStaticStyleCustomPropertyNames(node) {
|
|
3165
|
+
const names = /* @__PURE__ */ new Set();
|
|
3166
|
+
walk(node, (child) => {
|
|
3167
|
+
if (child.type !== "JSXOpeningElement") {
|
|
3168
|
+
return;
|
|
3169
|
+
}
|
|
3170
|
+
const styleAttr = findJsxAttribute(child, "style");
|
|
3171
|
+
if (styleAttr?.value?.type !== "JSXExpressionContainer") {
|
|
3172
|
+
return;
|
|
3173
|
+
}
|
|
3174
|
+
const expression = styleAttr.value.expression;
|
|
3175
|
+
if (expression.type !== "ObjectExpression") {
|
|
3176
|
+
return;
|
|
3177
|
+
}
|
|
3178
|
+
for (const propRaw of expression.properties ?? []) {
|
|
3179
|
+
if (propRaw.type !== "Property") {
|
|
3180
|
+
continue;
|
|
3181
|
+
}
|
|
3182
|
+
const key = propRaw.key;
|
|
3183
|
+
const name = literalStringValue(key);
|
|
3184
|
+
if (name?.startsWith("--")) {
|
|
3185
|
+
names.add(name);
|
|
3186
|
+
}
|
|
3187
|
+
}
|
|
3188
|
+
});
|
|
3189
|
+
return names;
|
|
3190
|
+
}
|
|
3191
|
+
function literalStringValue(node) {
|
|
3192
|
+
if (node.type !== "Literal") {
|
|
3193
|
+
return null;
|
|
3194
|
+
}
|
|
3195
|
+
const value = node.value;
|
|
3196
|
+
return typeof value === "string" ? value : null;
|
|
3197
|
+
}
|
|
3198
|
+
function appendMapArray(map, key, value) {
|
|
3199
|
+
const existing = map.get(key);
|
|
3200
|
+
if (existing) {
|
|
3201
|
+
existing.push(value);
|
|
3202
|
+
} else {
|
|
3203
|
+
map.set(key, [value]);
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
function getOrCreateMap(map, key) {
|
|
3207
|
+
const existing = map.get(key);
|
|
3208
|
+
if (existing) {
|
|
3209
|
+
return existing;
|
|
3210
|
+
}
|
|
3211
|
+
const value = /* @__PURE__ */ new Map();
|
|
3212
|
+
map.set(key, value);
|
|
3213
|
+
return value;
|
|
3214
|
+
}
|
|
3215
|
+
function evaluatePartialObject(node, filename, bindings, source, globalVarAliases, cssVariableMap, variantChain = "") {
|
|
2357
3216
|
const staticProps = {};
|
|
2358
3217
|
const dynamicProps = /* @__PURE__ */ new Map();
|
|
2359
3218
|
const conditionalClasses = [];
|
|
@@ -2410,6 +3269,8 @@ function evaluatePartialObject(node, filename, bindings, source, variantChain =
|
|
|
2410
3269
|
filename,
|
|
2411
3270
|
bindings,
|
|
2412
3271
|
source,
|
|
3272
|
+
globalVarAliases,
|
|
3273
|
+
cssVariableMap,
|
|
2413
3274
|
nestedVariant
|
|
2414
3275
|
);
|
|
2415
3276
|
if (!nested) {
|
|
@@ -2430,8 +3291,20 @@ function evaluatePartialObject(node, filename, bindings, source, variantChain =
|
|
|
2430
3291
|
const consequent = extractStaticLiteralValue(conditional.consequent);
|
|
2431
3292
|
const alternate = extractStaticLiteralValue(conditional.alternate);
|
|
2432
3293
|
if (consequent !== null && alternate !== null) {
|
|
2433
|
-
const { className: consequentClasses } = transform(
|
|
2434
|
-
|
|
3294
|
+
const { className: consequentClasses } = transform(
|
|
3295
|
+
applyGlobalVarAliasesToSzObject(
|
|
3296
|
+
{ [key]: consequent },
|
|
3297
|
+
globalVarAliases,
|
|
3298
|
+
cssVariableMap
|
|
3299
|
+
)
|
|
3300
|
+
);
|
|
3301
|
+
const { className: alternateClasses } = transform(
|
|
3302
|
+
applyGlobalVarAliasesToSzObject(
|
|
3303
|
+
{ [key]: alternate },
|
|
3304
|
+
globalVarAliases,
|
|
3305
|
+
cssVariableMap
|
|
3306
|
+
)
|
|
3307
|
+
);
|
|
2435
3308
|
conditionalClasses.push({
|
|
2436
3309
|
test: conditional.test,
|
|
2437
3310
|
consequent: prefixVariantClasses(consequentClasses, variantChain),
|
|
@@ -2460,14 +3333,15 @@ function evaluatePartialObject(node, filename, bindings, source, variantChain =
|
|
|
2460
3333
|
}
|
|
2461
3334
|
return { staticProps, dynamicProps, conditionalClasses, usesColorVar };
|
|
2462
3335
|
}
|
|
2463
|
-
function applyStyleProps(edits, source, styleAttr, lastAttr, styleProps) {
|
|
3336
|
+
function applyStyleProps(edits, source, styleAttr, lastAttr, styleProps, fallbackInsertOffset) {
|
|
2464
3337
|
if (styleProps.length === 0) {
|
|
2465
3338
|
return;
|
|
2466
3339
|
}
|
|
2467
3340
|
const propsSource = styleProps.join(", ");
|
|
2468
3341
|
if (!styleAttr) {
|
|
2469
|
-
|
|
2470
|
-
|
|
3342
|
+
const insertOffset = lastAttr?.end ?? fallbackInsertOffset;
|
|
3343
|
+
if (insertOffset !== void 0) {
|
|
3344
|
+
edits.appendRight(insertOffset, ` style={{${propsSource}}}`);
|
|
2471
3345
|
}
|
|
2472
3346
|
return;
|
|
2473
3347
|
}
|
|
@@ -2493,6 +3367,67 @@ function generateStyleValueSource(info, source) {
|
|
|
2493
3367
|
return `\`\${${expressionSource}}\``;
|
|
2494
3368
|
}
|
|
2495
3369
|
}
|
|
3370
|
+
function buildDynamicValueKey(info, source) {
|
|
3371
|
+
const expressionSource = normalizeDynamicExpressionKey(
|
|
3372
|
+
source.slice(info.expression.start, info.expression.end)
|
|
3373
|
+
);
|
|
3374
|
+
switch (info.category) {
|
|
3375
|
+
case PropertyCategory.SPACING:
|
|
3376
|
+
return `spacing:${expressionSource}`;
|
|
3377
|
+
case PropertyCategory.COLOR:
|
|
3378
|
+
return `color:${expressionSource}`;
|
|
3379
|
+
case PropertyCategory.ANGLE:
|
|
3380
|
+
return `angle:${expressionSource}`;
|
|
3381
|
+
case PropertyCategory.DURATION:
|
|
3382
|
+
return `duration:${expressionSource}`;
|
|
3383
|
+
default:
|
|
3384
|
+
return `pass:${expressionSource}`;
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
function normalizeDynamicExpressionKey(expressionSource) {
|
|
3388
|
+
let normalized = expressionSource.trim();
|
|
3389
|
+
while (hasRedundantOuterParens(normalized)) {
|
|
3390
|
+
normalized = normalized.slice(1, -1).trim();
|
|
3391
|
+
}
|
|
3392
|
+
return normalized;
|
|
3393
|
+
}
|
|
3394
|
+
function hasRedundantOuterParens(expressionSource) {
|
|
3395
|
+
if (!expressionSource.startsWith("(") || !expressionSource.endsWith(")")) {
|
|
3396
|
+
return false;
|
|
3397
|
+
}
|
|
3398
|
+
let depth = 0;
|
|
3399
|
+
let quote = null;
|
|
3400
|
+
let escaped = false;
|
|
3401
|
+
for (let index = 0; index < expressionSource.length; index++) {
|
|
3402
|
+
const char = expressionSource[index];
|
|
3403
|
+
if (quote) {
|
|
3404
|
+
if (escaped) {
|
|
3405
|
+
escaped = false;
|
|
3406
|
+
} else if (char === "\\") {
|
|
3407
|
+
escaped = true;
|
|
3408
|
+
} else if (char === quote) {
|
|
3409
|
+
quote = null;
|
|
3410
|
+
}
|
|
3411
|
+
continue;
|
|
3412
|
+
}
|
|
3413
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
3414
|
+
quote = char;
|
|
3415
|
+
continue;
|
|
3416
|
+
}
|
|
3417
|
+
if (char === "(") {
|
|
3418
|
+
depth++;
|
|
3419
|
+
} else if (char === ")") {
|
|
3420
|
+
depth--;
|
|
3421
|
+
if (depth === 0 && index !== expressionSource.length - 1) {
|
|
3422
|
+
return false;
|
|
3423
|
+
}
|
|
3424
|
+
}
|
|
3425
|
+
if (depth < 0) {
|
|
3426
|
+
return false;
|
|
3427
|
+
}
|
|
3428
|
+
}
|
|
3429
|
+
return depth === 0;
|
|
3430
|
+
}
|
|
2496
3431
|
function buildCSSVarClassName(info) {
|
|
2497
3432
|
const variantPrefix = info.variantChain ? `${getVariantPrefix(info.variantChain)}:` : "";
|
|
2498
3433
|
return `${variantPrefix}${info.twPrefix}-(${info.varName})`;
|
|
@@ -2525,9 +3460,21 @@ function prefixVariantClasses(className, variantChain) {
|
|
|
2525
3460
|
function isRuntimeExpression(node) {
|
|
2526
3461
|
return node.type === "Identifier" || node.type === "MemberExpression" || node.type === "CallExpression" || node.type === "ConditionalExpression" || node.type === "TemplateLiteral" || node.type === "BinaryExpression" || node.type === "LogicalExpression";
|
|
2527
3462
|
}
|
|
2528
|
-
function buildStaticConditionalClassExpression(node, filename, bindings, source, classes) {
|
|
2529
|
-
const consequent = resolveStaticClassString(
|
|
2530
|
-
|
|
3463
|
+
function buildStaticConditionalClassExpression(node, filename, bindings, source, classes, globalVarAliases, cssVariableMap) {
|
|
3464
|
+
const consequent = resolveStaticClassString(
|
|
3465
|
+
node.consequent,
|
|
3466
|
+
filename,
|
|
3467
|
+
bindings,
|
|
3468
|
+
globalVarAliases,
|
|
3469
|
+
cssVariableMap
|
|
3470
|
+
);
|
|
3471
|
+
const alternate = resolveStaticClassString(
|
|
3472
|
+
node.alternate,
|
|
3473
|
+
filename,
|
|
3474
|
+
bindings,
|
|
3475
|
+
globalVarAliases,
|
|
3476
|
+
cssVariableMap
|
|
3477
|
+
);
|
|
2531
3478
|
if (consequent === null || alternate === null) {
|
|
2532
3479
|
return null;
|
|
2533
3480
|
}
|
|
@@ -2539,7 +3486,7 @@ function buildStaticConditionalClassExpression(node, filename, bindings, source,
|
|
|
2539
3486
|
const testSource = source.slice(node.test.start, node.test.end);
|
|
2540
3487
|
return `${testSource} ? ${JSON.stringify(consequent)} : ${JSON.stringify(alternate)}`;
|
|
2541
3488
|
}
|
|
2542
|
-
function resolveStaticClassString(node, filename, bindings) {
|
|
3489
|
+
function resolveStaticClassString(node, filename, bindings, globalVarAliases, cssVariableMap) {
|
|
2543
3490
|
const unwrapped = unwrapExpression(node);
|
|
2544
3491
|
let objectNode = null;
|
|
2545
3492
|
if (unwrapped.type === "ObjectExpression") {
|
|
@@ -2551,7 +3498,13 @@ function resolveStaticClassString(node, filename, bindings) {
|
|
|
2551
3498
|
return null;
|
|
2552
3499
|
}
|
|
2553
3500
|
try {
|
|
2554
|
-
return transform(
|
|
3501
|
+
return transform(
|
|
3502
|
+
applyGlobalVarAliasesToSzObject(
|
|
3503
|
+
astObjectToSzObject(objectNode, filename, bindings),
|
|
3504
|
+
globalVarAliases,
|
|
3505
|
+
cssVariableMap
|
|
3506
|
+
)
|
|
3507
|
+
).className;
|
|
2555
3508
|
} catch (err) {
|
|
2556
3509
|
if (err instanceof OxcNotImplementedError) {
|
|
2557
3510
|
return null;
|
|
@@ -2666,17 +3619,22 @@ function unwrapExpression(node) {
|
|
|
2666
3619
|
}
|
|
2667
3620
|
return current;
|
|
2668
3621
|
}
|
|
3622
|
+
function isOxcNode(value) {
|
|
3623
|
+
return Boolean(
|
|
3624
|
+
value && typeof value === "object" && typeof value.type === "string"
|
|
3625
|
+
);
|
|
3626
|
+
}
|
|
3627
|
+
function isAstMetadataKey(key) {
|
|
3628
|
+
return key === "loc" || key === "range" || key === "start" || key === "end" || key === "type";
|
|
3629
|
+
}
|
|
2669
3630
|
function walk(node, visit) {
|
|
2670
|
-
if (!node
|
|
3631
|
+
if (!isOxcNode(node)) {
|
|
2671
3632
|
return;
|
|
2672
3633
|
}
|
|
2673
3634
|
const typed = node;
|
|
2674
|
-
if (typeof typed.type !== "string") {
|
|
2675
|
-
return;
|
|
2676
|
-
}
|
|
2677
3635
|
visit(typed);
|
|
2678
3636
|
for (const key of Object.keys(typed)) {
|
|
2679
|
-
if (key
|
|
3637
|
+
if (isAstMetadataKey(key)) {
|
|
2680
3638
|
continue;
|
|
2681
3639
|
}
|
|
2682
3640
|
const child = typed[key];
|
|
@@ -2690,6 +3648,108 @@ function walk(node, visit) {
|
|
|
2690
3648
|
}
|
|
2691
3649
|
}
|
|
2692
3650
|
|
|
3651
|
+
class OxcRustNotImplementedError extends Error {
|
|
3652
|
+
/**
|
|
3653
|
+
* @param detail Native loader or transform failure detail.
|
|
3654
|
+
*/
|
|
3655
|
+
constructor(detail) {
|
|
3656
|
+
super(`transformRust: native engine unavailable - ${detail}`);
|
|
3657
|
+
this.name = "OxcRustNotImplementedError";
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3660
|
+
function transformRust(source, filename, options) {
|
|
3661
|
+
const [result] = transformRustBatch([{ filename, source }], options);
|
|
3662
|
+
if (!result) {
|
|
3663
|
+
throw new OxcRustNotImplementedError("native transform returned no result");
|
|
3664
|
+
}
|
|
3665
|
+
return result;
|
|
3666
|
+
}
|
|
3667
|
+
function ensureRustTransformAvailable() {
|
|
3668
|
+
try {
|
|
3669
|
+
transformBatch([]);
|
|
3670
|
+
} catch (err) {
|
|
3671
|
+
if (err instanceof OxcRustNotImplementedError) {
|
|
3672
|
+
throw err;
|
|
3673
|
+
}
|
|
3674
|
+
if (err instanceof CsszyxNativeUnavailableError) {
|
|
3675
|
+
throw new OxcRustNotImplementedError(
|
|
3676
|
+
`${err.message}; native package: ${err.packageName ?? "unsupported platform"}`
|
|
3677
|
+
);
|
|
3678
|
+
}
|
|
3679
|
+
throw err;
|
|
3680
|
+
}
|
|
3681
|
+
}
|
|
3682
|
+
function transformRustBatch(files, options) {
|
|
3683
|
+
try {
|
|
3684
|
+
return transformBatch(
|
|
3685
|
+
files.map((file, index) => ({
|
|
3686
|
+
filename: file.filename ?? `file-${index}.tsx`,
|
|
3687
|
+
source: file.source
|
|
3688
|
+
})),
|
|
3689
|
+
{
|
|
3690
|
+
mangleVars: options?.mangleVars === true,
|
|
3691
|
+
mangleVarHoistMaxDepth: options?.mangleVarHoistMaxDepth,
|
|
3692
|
+
globalVarAliases: normalizeGlobalVarAliases(options?.globalVarAliases)
|
|
3693
|
+
}
|
|
3694
|
+
).map(fromNativeResult);
|
|
3695
|
+
} catch (err) {
|
|
3696
|
+
if (err instanceof OxcRustNotImplementedError) {
|
|
3697
|
+
throw err;
|
|
3698
|
+
}
|
|
3699
|
+
if (err instanceof CsszyxNativeUnavailableError) {
|
|
3700
|
+
throw new OxcRustNotImplementedError(
|
|
3701
|
+
`${err.message}; native package: ${err.packageName ?? "unsupported platform"}`
|
|
3702
|
+
);
|
|
3703
|
+
}
|
|
3704
|
+
throw err;
|
|
3705
|
+
}
|
|
3706
|
+
}
|
|
3707
|
+
function normalizeGlobalVarAliases(input) {
|
|
3708
|
+
if (!input) {
|
|
3709
|
+
return [];
|
|
3710
|
+
}
|
|
3711
|
+
const entries = input instanceof Map ? input.entries() : Array.isArray(input) ? input : Object.entries(input);
|
|
3712
|
+
return [...entries].filter(([original, alias]) => original.startsWith("--") && alias.startsWith("--")).map(([original, alias]) => ({ original, alias }));
|
|
3713
|
+
}
|
|
3714
|
+
function fromNativeResult(result) {
|
|
3715
|
+
return {
|
|
3716
|
+
code: result.code,
|
|
3717
|
+
transformed: result.metadata.transformed,
|
|
3718
|
+
usesRuntime: result.metadata.usesRuntime,
|
|
3719
|
+
usesMerge: result.metadata.usesMerge,
|
|
3720
|
+
usesColorVar: result.metadata.usesColorVar,
|
|
3721
|
+
classes: new Set(result.classes),
|
|
3722
|
+
rawClassNames: new Set(result.rawClassNames),
|
|
3723
|
+
diagnostics: result.diagnostics,
|
|
3724
|
+
recoveryTokens: new Map(
|
|
3725
|
+
result.recoveryTokens.map(({ token, ...data }) => [
|
|
3726
|
+
token,
|
|
3727
|
+
{
|
|
3728
|
+
mode: data.mode,
|
|
3729
|
+
component: data.component,
|
|
3730
|
+
path: data.path
|
|
3731
|
+
}
|
|
3732
|
+
])
|
|
3733
|
+
),
|
|
3734
|
+
cssVariableMap: aggregateCssVariableMap(result.cssVariableMap ?? [])
|
|
3735
|
+
};
|
|
3736
|
+
}
|
|
3737
|
+
function aggregateCssVariableMap(entries) {
|
|
3738
|
+
const map = /* @__PURE__ */ new Map();
|
|
3739
|
+
for (const entry of entries) {
|
|
3740
|
+
const existing = map.get(entry.original);
|
|
3741
|
+
if (!existing) {
|
|
3742
|
+
map.set(entry.original, entry.mangled);
|
|
3743
|
+
continue;
|
|
3744
|
+
}
|
|
3745
|
+
const values = Array.isArray(existing) ? existing : [existing];
|
|
3746
|
+
if (!values.includes(entry.mangled)) {
|
|
3747
|
+
map.set(entry.original, [...values, entry.mangled]);
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
return map;
|
|
3751
|
+
}
|
|
3752
|
+
|
|
2693
3753
|
const VERSION = "0.0.0";
|
|
2694
3754
|
const DEFAULT_COMPILER_OPTIONS = {
|
|
2695
3755
|
buildId: Date.now().toString(),
|
|
@@ -2703,4 +3763,4 @@ function mergeOptions(options = {}) {
|
|
|
2703
3763
|
};
|
|
2704
3764
|
}
|
|
2705
3765
|
|
|
2706
|
-
export { COLOR_PROPERTIES, CsszyxCompiler, DEFAULT_COMPILER_OPTIONS, KNOWN_VARIANTS, ManifestBuilder, OxcNotImplementedError, PROPERTY_MAP, PropertyCategory, VERSION, buildParentMap, createRecoveryToken, generateRecoveryToken, getCSSVariableName, getPropertyCategory, hoistCSSVariables, injectRecoveryToken, isValidRecoveryMode, mergeOptions, parseManifest, serializeManifest, transform, transformOxc, transformSourceCode, validateManifest, validateSzRecover };
|
|
3766
|
+
export { COLOR_PROPERTIES, CsszyxCompiler, DEFAULT_COMPILER_OPTIONS, KNOWN_VARIANTS, ManifestBuilder, OxcNotImplementedError, OxcRustNotImplementedError, PROPERTY_MAP, PropertyCategory, VERSION, buildParentMap, createRecoveryToken, ensureRustTransformAvailable, generateRecoveryToken, getCSSVariableName, getPropertyCategory, hoistCSSVariables, injectRecoveryToken, isValidRecoveryMode, mergeOptions, parseManifest, scanGlobalVarUsages, serializeManifest, transform, transformOxc, transformRust, transformRustBatch, transformSourceCode, validateManifest, validateSzRecover };
|