@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.cjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const core = require('@csszyx/core');
|
|
4
|
-
const transformCore = require('./shared/compiler.
|
|
4
|
+
const transformCore = require('./shared/compiler.DItEsgH4.cjs');
|
|
5
|
+
const oxcParser = require('oxc-parser');
|
|
5
6
|
const t = require('@babel/types');
|
|
6
7
|
const node_crypto = require('node:crypto');
|
|
7
8
|
const babel = require('@babel/core');
|
|
8
9
|
const MagicString = require('magic-string');
|
|
9
|
-
const
|
|
10
|
+
const native = require('@csszyx/core/native');
|
|
10
11
|
|
|
11
12
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
12
13
|
|
|
@@ -83,6 +84,7 @@ function transformSourceCode(source, filename, options) {
|
|
|
83
84
|
const rawClassNames = /* @__PURE__ */ new Set();
|
|
84
85
|
const diagnostics = [];
|
|
85
86
|
const recoveryTokens = /* @__PURE__ */ new Map();
|
|
87
|
+
const cssVariableMap = /* @__PURE__ */ new Map();
|
|
86
88
|
if (!source.includes("sz")) {
|
|
87
89
|
return {
|
|
88
90
|
code: source,
|
|
@@ -93,7 +95,8 @@ function transformSourceCode(source, filename, options) {
|
|
|
93
95
|
classes: collectedClasses,
|
|
94
96
|
rawClassNames,
|
|
95
97
|
diagnostics,
|
|
96
|
-
recoveryTokens
|
|
98
|
+
recoveryTokens,
|
|
99
|
+
cssVariableMap
|
|
97
100
|
};
|
|
98
101
|
}
|
|
99
102
|
try {
|
|
@@ -755,7 +758,8 @@ function transformSourceCode(source, filename, options) {
|
|
|
755
758
|
classes: collectedClasses,
|
|
756
759
|
rawClassNames,
|
|
757
760
|
diagnostics,
|
|
758
|
-
recoveryTokens
|
|
761
|
+
recoveryTokens,
|
|
762
|
+
cssVariableMap
|
|
759
763
|
};
|
|
760
764
|
} catch (e) {
|
|
761
765
|
if (e instanceof ASTBudgetExceededError) {
|
|
@@ -771,7 +775,8 @@ function transformSourceCode(source, filename, options) {
|
|
|
771
775
|
classes: collectedClasses,
|
|
772
776
|
rawClassNames,
|
|
773
777
|
diagnostics,
|
|
774
|
-
recoveryTokens
|
|
778
|
+
recoveryTokens,
|
|
779
|
+
cssVariableMap
|
|
775
780
|
};
|
|
776
781
|
}
|
|
777
782
|
}
|
|
@@ -1323,6 +1328,271 @@ class CsszyxCompiler {
|
|
|
1323
1328
|
}
|
|
1324
1329
|
}
|
|
1325
1330
|
|
|
1331
|
+
const CSS_VAR_REFERENCE_RE = /var\(\s*(--[\w-]+)/g;
|
|
1332
|
+
function scanGlobalVarUsages(source, filename = "file.tsx", options = {}) {
|
|
1333
|
+
if (!source.includes("--") && !source.includes("var(")) {
|
|
1334
|
+
return [];
|
|
1335
|
+
}
|
|
1336
|
+
const parsed = oxcParser.parseSync(filename, source);
|
|
1337
|
+
if (parsed.errors.length > 0) {
|
|
1338
|
+
throw new Error(
|
|
1339
|
+
`oxc-parser errors in ${filename}: ${parsed.errors.map((error) => error.message).join("; ")}`
|
|
1340
|
+
);
|
|
1341
|
+
}
|
|
1342
|
+
const tokenFilter = options.tokens ? new Set(options.tokens) : null;
|
|
1343
|
+
const constantStrings = collectStringConstants(parsed.program);
|
|
1344
|
+
const diagnostics = [];
|
|
1345
|
+
walk$1(parsed.program, (node, ancestors) => {
|
|
1346
|
+
if (node.type === "CallExpression") {
|
|
1347
|
+
collectStyleMethodDiagnostic(
|
|
1348
|
+
node,
|
|
1349
|
+
source,
|
|
1350
|
+
filename,
|
|
1351
|
+
constantStrings,
|
|
1352
|
+
tokenFilter,
|
|
1353
|
+
diagnostics
|
|
1354
|
+
);
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
if (node.type !== "JSXAttribute") {
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
const attrName = jsxAttributeName(node);
|
|
1361
|
+
if (attrName === "style") {
|
|
1362
|
+
collectJsxStyleDiagnostics(
|
|
1363
|
+
node,
|
|
1364
|
+
source,
|
|
1365
|
+
filename,
|
|
1366
|
+
constantStrings,
|
|
1367
|
+
tokenFilter,
|
|
1368
|
+
diagnostics
|
|
1369
|
+
);
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
if (attrName === "className") {
|
|
1373
|
+
collectClassNameDiagnostics(node, source, filename, tokenFilter, diagnostics);
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
if (attrName === "sz" && ancestors.some((parent) => parent.type === "JSXAttribute")) {
|
|
1377
|
+
return;
|
|
1378
|
+
}
|
|
1379
|
+
});
|
|
1380
|
+
return diagnostics;
|
|
1381
|
+
}
|
|
1382
|
+
function collectStringConstants(root) {
|
|
1383
|
+
const constants = /* @__PURE__ */ new Map();
|
|
1384
|
+
walk$1(root, (node) => {
|
|
1385
|
+
if (node.type !== "VariableDeclarator") {
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
const id = node.id;
|
|
1389
|
+
const init = node.init;
|
|
1390
|
+
if (id?.type !== "Identifier" || !init) {
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
const name = id.name;
|
|
1394
|
+
const value = literalStringValue$1(init);
|
|
1395
|
+
if (typeof name === "string" && value !== null) {
|
|
1396
|
+
constants.set(name, value);
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1399
|
+
return constants;
|
|
1400
|
+
}
|
|
1401
|
+
function collectStyleMethodDiagnostic(node, source, filename, constants, tokenFilter, diagnostics) {
|
|
1402
|
+
const method = memberMethodName(node.callee);
|
|
1403
|
+
if (!method || !["setProperty", "getPropertyValue", "removeProperty"].includes(method)) {
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
const firstArg = node.arguments?.[0];
|
|
1407
|
+
const name = firstArg ? resolveString(firstArg, constants) : null;
|
|
1408
|
+
if (!name?.startsWith("--") || !shouldReportToken(name, tokenFilter)) {
|
|
1409
|
+
return;
|
|
1410
|
+
}
|
|
1411
|
+
const kind = method === "setProperty" ? "style-set-property" : method === "getPropertyValue" ? "style-get-property" : "style-remove-property";
|
|
1412
|
+
diagnostics.push(createDiagnostic(kind, name, node, source, filename));
|
|
1413
|
+
}
|
|
1414
|
+
function collectJsxStyleDiagnostics(attr, source, filename, constants, tokenFilter, diagnostics) {
|
|
1415
|
+
const expression = jsxExpression(attr);
|
|
1416
|
+
if (expression?.type !== "ObjectExpression") {
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
for (const prop of expression.properties ?? []) {
|
|
1420
|
+
if (prop.type !== "Property") {
|
|
1421
|
+
continue;
|
|
1422
|
+
}
|
|
1423
|
+
const name = propertyKeyString(prop, constants);
|
|
1424
|
+
if (name?.startsWith("--") && shouldReportToken(name, tokenFilter)) {
|
|
1425
|
+
diagnostics.push(createDiagnostic("jsx-style-key", name, prop, source, filename));
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
function collectClassNameDiagnostics(attr, source, filename, tokenFilter, diagnostics) {
|
|
1430
|
+
for (const value of jsxAttributeStringValues(attr)) {
|
|
1431
|
+
for (const name of extractVarReferences(value)) {
|
|
1432
|
+
if (shouldReportToken(name, tokenFilter)) {
|
|
1433
|
+
diagnostics.push(
|
|
1434
|
+
createDiagnostic("class-string-var-reference", name, attr, source, filename)
|
|
1435
|
+
);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
function jsxAttributeName(attr) {
|
|
1441
|
+
const name = attr.name;
|
|
1442
|
+
return name?.type === "JSXIdentifier" ? name.name ?? null : null;
|
|
1443
|
+
}
|
|
1444
|
+
function jsxExpression(attr) {
|
|
1445
|
+
const value = attr.value;
|
|
1446
|
+
if (value?.type !== "JSXExpressionContainer") {
|
|
1447
|
+
return null;
|
|
1448
|
+
}
|
|
1449
|
+
return value.expression ?? null;
|
|
1450
|
+
}
|
|
1451
|
+
function jsxAttributeStringValues(attr) {
|
|
1452
|
+
const value = attr.value;
|
|
1453
|
+
if (!value) {
|
|
1454
|
+
return [];
|
|
1455
|
+
}
|
|
1456
|
+
const direct = literalStringValue$1(value);
|
|
1457
|
+
if (direct !== null) {
|
|
1458
|
+
return [direct];
|
|
1459
|
+
}
|
|
1460
|
+
const expression = jsxExpression(attr);
|
|
1461
|
+
if (!expression) {
|
|
1462
|
+
return [];
|
|
1463
|
+
}
|
|
1464
|
+
const exprValue = literalStringValue$1(expression);
|
|
1465
|
+
if (exprValue !== null) {
|
|
1466
|
+
return [exprValue];
|
|
1467
|
+
}
|
|
1468
|
+
if (expression.type === "TemplateLiteral") {
|
|
1469
|
+
return templateStaticParts(expression);
|
|
1470
|
+
}
|
|
1471
|
+
return [];
|
|
1472
|
+
}
|
|
1473
|
+
function resolveString(node, constants) {
|
|
1474
|
+
const literal = literalStringValue$1(node);
|
|
1475
|
+
if (literal !== null) {
|
|
1476
|
+
return literal;
|
|
1477
|
+
}
|
|
1478
|
+
if (node.type === "Identifier") {
|
|
1479
|
+
const name = node.name;
|
|
1480
|
+
return typeof name === "string" ? constants.get(name) ?? null : null;
|
|
1481
|
+
}
|
|
1482
|
+
return null;
|
|
1483
|
+
}
|
|
1484
|
+
function literalStringValue$1(node) {
|
|
1485
|
+
if (node.type !== "Literal") {
|
|
1486
|
+
return null;
|
|
1487
|
+
}
|
|
1488
|
+
const value = node.value;
|
|
1489
|
+
return typeof value === "string" ? value : null;
|
|
1490
|
+
}
|
|
1491
|
+
function propertyKeyString(property, constants) {
|
|
1492
|
+
const key = property.key;
|
|
1493
|
+
const computed = property.computed === true;
|
|
1494
|
+
if (!key) {
|
|
1495
|
+
return null;
|
|
1496
|
+
}
|
|
1497
|
+
if (computed) {
|
|
1498
|
+
return resolveString(key, constants);
|
|
1499
|
+
}
|
|
1500
|
+
if (key.type === "Identifier") {
|
|
1501
|
+
const name = key.name;
|
|
1502
|
+
return typeof name === "string" ? name : null;
|
|
1503
|
+
}
|
|
1504
|
+
return literalStringValue$1(key);
|
|
1505
|
+
}
|
|
1506
|
+
function memberMethodName(callee) {
|
|
1507
|
+
if (callee?.type !== "MemberExpression") {
|
|
1508
|
+
return null;
|
|
1509
|
+
}
|
|
1510
|
+
const property = callee.property;
|
|
1511
|
+
if (!property) {
|
|
1512
|
+
return null;
|
|
1513
|
+
}
|
|
1514
|
+
if (property.type === "Identifier") {
|
|
1515
|
+
const name = property.name;
|
|
1516
|
+
return typeof name === "string" ? name : null;
|
|
1517
|
+
}
|
|
1518
|
+
return literalStringValue$1(property);
|
|
1519
|
+
}
|
|
1520
|
+
function templateStaticParts(node) {
|
|
1521
|
+
const quasis = node.quasis ?? [];
|
|
1522
|
+
const parts = [];
|
|
1523
|
+
for (const quasi of quasis) {
|
|
1524
|
+
const value = quasi.value;
|
|
1525
|
+
const cooked = value?.cooked;
|
|
1526
|
+
const raw = value?.raw;
|
|
1527
|
+
if (typeof cooked === "string") {
|
|
1528
|
+
parts.push(cooked);
|
|
1529
|
+
} else if (typeof raw === "string") {
|
|
1530
|
+
parts.push(raw);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
return parts;
|
|
1534
|
+
}
|
|
1535
|
+
function extractVarReferences(value) {
|
|
1536
|
+
const refs = /* @__PURE__ */ new Set();
|
|
1537
|
+
for (const match of value.matchAll(CSS_VAR_REFERENCE_RE)) {
|
|
1538
|
+
refs.add(match[1]);
|
|
1539
|
+
}
|
|
1540
|
+
return [...refs].sort();
|
|
1541
|
+
}
|
|
1542
|
+
function shouldReportToken(name, tokenFilter) {
|
|
1543
|
+
return tokenFilter === null || tokenFilter.has(name);
|
|
1544
|
+
}
|
|
1545
|
+
function createDiagnostic(kind, name, node, source, filename) {
|
|
1546
|
+
return {
|
|
1547
|
+
kind,
|
|
1548
|
+
name,
|
|
1549
|
+
location: offsetToLocation(source, node.start, filename),
|
|
1550
|
+
message: `${name} is used outside csszyx-owned global variable alias rewrites (${kind}).`
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1553
|
+
function offsetToLocation(source, offset, filename) {
|
|
1554
|
+
let line = 1;
|
|
1555
|
+
let column = 1;
|
|
1556
|
+
for (let index = 0; index < offset; index++) {
|
|
1557
|
+
if (source.charCodeAt(index) === 10) {
|
|
1558
|
+
line++;
|
|
1559
|
+
column = 1;
|
|
1560
|
+
} else {
|
|
1561
|
+
column++;
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
return { filePath: filename, line, column };
|
|
1565
|
+
}
|
|
1566
|
+
function walk$1(node, visit, ancestors = []) {
|
|
1567
|
+
if (!isOxcNode$1(node)) {
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
visit(node, ancestors);
|
|
1571
|
+
ancestors.push(node);
|
|
1572
|
+
for (const key of Object.keys(node)) {
|
|
1573
|
+
if (isAstMetadataKey$1(key)) {
|
|
1574
|
+
continue;
|
|
1575
|
+
}
|
|
1576
|
+
const child = node[key];
|
|
1577
|
+
if (Array.isArray(child)) {
|
|
1578
|
+
for (const item of child) {
|
|
1579
|
+
walk$1(item, visit, ancestors);
|
|
1580
|
+
}
|
|
1581
|
+
} else if (child && typeof child === "object") {
|
|
1582
|
+
walk$1(child, visit, ancestors);
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
ancestors.pop();
|
|
1586
|
+
}
|
|
1587
|
+
function isOxcNode$1(value) {
|
|
1588
|
+
return Boolean(
|
|
1589
|
+
value && typeof value === "object" && typeof value.type === "string"
|
|
1590
|
+
);
|
|
1591
|
+
}
|
|
1592
|
+
function isAstMetadataKey$1(key) {
|
|
1593
|
+
return key === "loc" || key === "range" || key === "start" || key === "end" || key === "type";
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1326
1596
|
function findLCA(nodeA, nodeB, parentMap) {
|
|
1327
1597
|
const ancestorsA = /* @__PURE__ */ new Set();
|
|
1328
1598
|
let current = nodeA;
|
|
@@ -1656,6 +1926,155 @@ function injectRecoveryToken(attributes, token) {
|
|
|
1656
1926
|
};
|
|
1657
1927
|
}
|
|
1658
1928
|
|
|
1929
|
+
const DEFAULT_MAX_DEPTH = 5;
|
|
1930
|
+
function planComponentVariableHoistsWithDiagnostics(nodes, usages, options = {}) {
|
|
1931
|
+
const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
1932
|
+
const nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
1933
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1934
|
+
for (const usage of usages) {
|
|
1935
|
+
const groupKey = `${usage.name}\0${usage.valueKey}`;
|
|
1936
|
+
const group = groups.get(groupKey);
|
|
1937
|
+
if (group) {
|
|
1938
|
+
group.push(usage);
|
|
1939
|
+
} else {
|
|
1940
|
+
groups.set(groupKey, [usage]);
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
const plans = [];
|
|
1944
|
+
const diagnostics = [];
|
|
1945
|
+
for (const group of groups.values()) {
|
|
1946
|
+
if (group.length < 2) {
|
|
1947
|
+
continue;
|
|
1948
|
+
}
|
|
1949
|
+
const targetElementId = findLowestCommonAncestor(
|
|
1950
|
+
group.map((usage) => usage.elementId),
|
|
1951
|
+
nodeById
|
|
1952
|
+
);
|
|
1953
|
+
if (!targetElementId) {
|
|
1954
|
+
diagnostics.push(buildHoistDiagnostic(group, "no-lca"));
|
|
1955
|
+
continue;
|
|
1956
|
+
}
|
|
1957
|
+
const target = nodeById.get(targetElementId);
|
|
1958
|
+
if (!target || target.canHost === false) {
|
|
1959
|
+
diagnostics.push(buildHoistDiagnostic(group, "non-host-ancestor"));
|
|
1960
|
+
continue;
|
|
1961
|
+
}
|
|
1962
|
+
if (group.some(
|
|
1963
|
+
(usage) => distanceToAncestor(usage.elementId, targetElementId, nodeById) > maxDepth
|
|
1964
|
+
)) {
|
|
1965
|
+
diagnostics.push(buildHoistDiagnostic(group, "max-depth", maxDepth));
|
|
1966
|
+
continue;
|
|
1967
|
+
}
|
|
1968
|
+
plans.push({
|
|
1969
|
+
name: group[0].name,
|
|
1970
|
+
valueKey: group[0].valueKey,
|
|
1971
|
+
targetElementId,
|
|
1972
|
+
usageIds: group.map((usage) => usage.id)
|
|
1973
|
+
});
|
|
1974
|
+
}
|
|
1975
|
+
return { plans, diagnostics };
|
|
1976
|
+
}
|
|
1977
|
+
function buildHoistDiagnostic(group, reason, maxDepth) {
|
|
1978
|
+
return {
|
|
1979
|
+
name: group[0]?.name ?? "",
|
|
1980
|
+
reason,
|
|
1981
|
+
usageCount: group.length,
|
|
1982
|
+
...maxDepth === void 0 ? {} : { maxDepth }
|
|
1983
|
+
};
|
|
1984
|
+
}
|
|
1985
|
+
function findLowestCommonAncestor(elementIds, nodeById) {
|
|
1986
|
+
const [first, ...rest] = elementIds;
|
|
1987
|
+
if (!first) {
|
|
1988
|
+
return null;
|
|
1989
|
+
}
|
|
1990
|
+
let currentAncestors = ancestorChain(first, nodeById);
|
|
1991
|
+
for (const elementId of rest) {
|
|
1992
|
+
const nextAncestors = new Set(ancestorChain(elementId, nodeById));
|
|
1993
|
+
currentAncestors = currentAncestors.filter((id) => nextAncestors.has(id));
|
|
1994
|
+
if (currentAncestors.length === 0) {
|
|
1995
|
+
return null;
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
return currentAncestors[0] ?? null;
|
|
1999
|
+
}
|
|
2000
|
+
function ancestorChain(elementId, nodeById) {
|
|
2001
|
+
const chain = [];
|
|
2002
|
+
let current = elementId;
|
|
2003
|
+
while (current) {
|
|
2004
|
+
const node = nodeById.get(current);
|
|
2005
|
+
if (!node) {
|
|
2006
|
+
break;
|
|
2007
|
+
}
|
|
2008
|
+
chain.push(current);
|
|
2009
|
+
current = node.parentId;
|
|
2010
|
+
}
|
|
2011
|
+
return chain;
|
|
2012
|
+
}
|
|
2013
|
+
function distanceToAncestor(elementId, ancestorId, nodeById) {
|
|
2014
|
+
let distance = 0;
|
|
2015
|
+
let current = elementId;
|
|
2016
|
+
while (current) {
|
|
2017
|
+
if (current === ancestorId) {
|
|
2018
|
+
return distance;
|
|
2019
|
+
}
|
|
2020
|
+
const node = nodeById.get(current);
|
|
2021
|
+
if (!node) {
|
|
2022
|
+
break;
|
|
2023
|
+
}
|
|
2024
|
+
current = node.parentId;
|
|
2025
|
+
distance++;
|
|
2026
|
+
}
|
|
2027
|
+
return Number.POSITIVE_INFINITY;
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
function planCSSVariableNames(usages, options = {}) {
|
|
2031
|
+
const componentNames = /* @__PURE__ */ new Map();
|
|
2032
|
+
const scopedNamesByElement = /* @__PURE__ */ new Map();
|
|
2033
|
+
const reservedNames = options.reservedNames ?? /* @__PURE__ */ new Set();
|
|
2034
|
+
return usages.map((usage) => {
|
|
2035
|
+
if (usage.tier === "component") {
|
|
2036
|
+
const key2 = canonicalUsageKey(usage);
|
|
2037
|
+
let name2 = componentNames.get(key2);
|
|
2038
|
+
if (!name2) {
|
|
2039
|
+
name2 = allocateVariableName("--c", componentNames.size, reservedNames);
|
|
2040
|
+
componentNames.set(key2, name2);
|
|
2041
|
+
}
|
|
2042
|
+
return { ...usage, name: name2 };
|
|
2043
|
+
}
|
|
2044
|
+
const elementId = usage.elementId ?? "";
|
|
2045
|
+
const elementNames = getOrCreate(scopedNamesByElement, elementId, () => /* @__PURE__ */ new Map());
|
|
2046
|
+
const key = canonicalUsageKey(usage);
|
|
2047
|
+
let name = elementNames.get(key);
|
|
2048
|
+
if (!name) {
|
|
2049
|
+
name = allocateVariableName("--s", elementNames.size, reservedNames);
|
|
2050
|
+
elementNames.set(key, name);
|
|
2051
|
+
}
|
|
2052
|
+
return { ...usage, name };
|
|
2053
|
+
});
|
|
2054
|
+
}
|
|
2055
|
+
function allocateVariableName(prefix, startIndex, reservedNames) {
|
|
2056
|
+
let index = startIndex;
|
|
2057
|
+
while (true) {
|
|
2058
|
+
const name = `${prefix}${core.encode(index)}`;
|
|
2059
|
+
if (!reservedNames.has(name)) {
|
|
2060
|
+
return name;
|
|
2061
|
+
}
|
|
2062
|
+
index++;
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
function canonicalUsageKey(usage) {
|
|
2066
|
+
return `${usage.variantChain ?? ""}\0${usage.propertyKey}`;
|
|
2067
|
+
}
|
|
2068
|
+
function getOrCreate(map, key, create) {
|
|
2069
|
+
const existing = map.get(key);
|
|
2070
|
+
if (existing) {
|
|
2071
|
+
return existing;
|
|
2072
|
+
}
|
|
2073
|
+
const value = create();
|
|
2074
|
+
map.set(key, value);
|
|
2075
|
+
return value;
|
|
2076
|
+
}
|
|
2077
|
+
|
|
1659
2078
|
class OxcNotImplementedError extends Error {
|
|
1660
2079
|
/**
|
|
1661
2080
|
* @param slice The Phase D slice expected to implement this path.
|
|
@@ -1671,6 +2090,8 @@ function transformOxc(source, filename, options) {
|
|
|
1671
2090
|
const rawClassNames = /* @__PURE__ */ new Set();
|
|
1672
2091
|
const diagnostics = [];
|
|
1673
2092
|
const recoveryTokens = /* @__PURE__ */ new Map();
|
|
2093
|
+
const cssVariableMap = /* @__PURE__ */ new Map();
|
|
2094
|
+
const globalVarAliases = normalizeGlobalVarAliases$1(options?.globalVarAliases);
|
|
1674
2095
|
if (!source.includes("sz")) {
|
|
1675
2096
|
return {
|
|
1676
2097
|
code: source,
|
|
@@ -1681,7 +2102,8 @@ function transformOxc(source, filename, options) {
|
|
|
1681
2102
|
classes,
|
|
1682
2103
|
rawClassNames,
|
|
1683
2104
|
diagnostics,
|
|
1684
|
-
recoveryTokens
|
|
2105
|
+
recoveryTokens,
|
|
2106
|
+
cssVariableMap
|
|
1685
2107
|
};
|
|
1686
2108
|
}
|
|
1687
2109
|
const effectiveFilename = filename ?? "file.tsx";
|
|
@@ -1696,6 +2118,18 @@ function transformOxc(source, filename, options) {
|
|
|
1696
2118
|
const edits = new MagicString__default(source);
|
|
1697
2119
|
const objectBindings = collectObjectBindings(parsed.program);
|
|
1698
2120
|
const conditionalBindings = collectConditionalBindings(parsed.program);
|
|
2121
|
+
const reservedCSSVariableNames = options?.mangleVars ? collectStaticStyleCustomPropertyNames(parsed.program) : void 0;
|
|
2122
|
+
const componentHoists = options?.mangleVars ? planOxcComponentVariableHoists(
|
|
2123
|
+
parsed.program,
|
|
2124
|
+
effectiveFilename,
|
|
2125
|
+
objectBindings,
|
|
2126
|
+
source,
|
|
2127
|
+
options.mangleVarHoistMaxDepth,
|
|
2128
|
+
reservedCSSVariableNames
|
|
2129
|
+
) : null;
|
|
2130
|
+
if (componentHoists) {
|
|
2131
|
+
diagnostics.push(...componentHoists.diagnostics);
|
|
2132
|
+
}
|
|
1699
2133
|
let transformed = false;
|
|
1700
2134
|
let usesRuntime = false;
|
|
1701
2135
|
let usesMerge = false;
|
|
@@ -1721,6 +2155,24 @@ function transformOxc(source, filename, options) {
|
|
|
1721
2155
|
let szRecoverAttr = null;
|
|
1722
2156
|
let alreadyTagged = false;
|
|
1723
2157
|
let lastAttr = null;
|
|
2158
|
+
let appliedHoistedStyleProps = false;
|
|
2159
|
+
const elementId = elementIdForOpening(openingNode);
|
|
2160
|
+
const hoistedStyleProps = componentHoists?.stylePropsByTarget.get(elementId) ?? [];
|
|
2161
|
+
const applyHoistedStyleProps = () => {
|
|
2162
|
+
if (appliedHoistedStyleProps || hoistedStyleProps.length === 0) {
|
|
2163
|
+
return;
|
|
2164
|
+
}
|
|
2165
|
+
applyStyleProps(
|
|
2166
|
+
edits,
|
|
2167
|
+
source,
|
|
2168
|
+
styleAttr,
|
|
2169
|
+
lastAttr,
|
|
2170
|
+
hoistedStyleProps,
|
|
2171
|
+
openingNode.name.end
|
|
2172
|
+
);
|
|
2173
|
+
appliedHoistedStyleProps = true;
|
|
2174
|
+
transformed = true;
|
|
2175
|
+
};
|
|
1724
2176
|
for (const attrRaw of attrs) {
|
|
1725
2177
|
if (attrRaw.type !== "JSXAttribute") {
|
|
1726
2178
|
continue;
|
|
@@ -1781,6 +2233,7 @@ function transformOxc(source, filename, options) {
|
|
|
1781
2233
|
}
|
|
1782
2234
|
}
|
|
1783
2235
|
if (szAttrs.length === 0) {
|
|
2236
|
+
applyHoistedStyleProps();
|
|
1784
2237
|
return;
|
|
1785
2238
|
}
|
|
1786
2239
|
const szDerived = [];
|
|
@@ -1817,7 +2270,9 @@ function transformOxc(source, filename, options) {
|
|
|
1817
2270
|
effectiveFilename,
|
|
1818
2271
|
objectBindings,
|
|
1819
2272
|
source,
|
|
1820
|
-
classes
|
|
2273
|
+
classes,
|
|
2274
|
+
globalVarAliases,
|
|
2275
|
+
cssVariableMap
|
|
1821
2276
|
);
|
|
1822
2277
|
if (conditionalClassExpr) {
|
|
1823
2278
|
if (classNameAttr || szAttrs.length > 1) {
|
|
@@ -1839,7 +2294,11 @@ function transformOxc(source, filename, options) {
|
|
|
1839
2294
|
const bound = objectBindings.get(identifierName);
|
|
1840
2295
|
if (bound) {
|
|
1841
2296
|
const result2 = transformCore.transform(
|
|
1842
|
-
|
|
2297
|
+
applyGlobalVarAliasesToSzObject(
|
|
2298
|
+
astObjectToSzObject(bound, effectiveFilename, objectBindings),
|
|
2299
|
+
globalVarAliases,
|
|
2300
|
+
cssVariableMap
|
|
2301
|
+
)
|
|
1843
2302
|
);
|
|
1844
2303
|
for (const c of result2.className.split(/\s+/)) {
|
|
1845
2304
|
if (c) {
|
|
@@ -1856,7 +2315,9 @@ function transformOxc(source, filename, options) {
|
|
|
1856
2315
|
effectiveFilename,
|
|
1857
2316
|
objectBindings,
|
|
1858
2317
|
source,
|
|
1859
|
-
classes
|
|
2318
|
+
classes,
|
|
2319
|
+
globalVarAliases,
|
|
2320
|
+
cssVariableMap
|
|
1860
2321
|
);
|
|
1861
2322
|
if (conditionalClassExpr) {
|
|
1862
2323
|
if (classNameAttr || szAttrs.length > 1) {
|
|
@@ -1878,7 +2339,9 @@ function transformOxc(source, filename, options) {
|
|
|
1878
2339
|
const arrayClasses = astArrayToStaticClasses(
|
|
1879
2340
|
expression,
|
|
1880
2341
|
effectiveFilename,
|
|
1881
|
-
objectBindings
|
|
2342
|
+
objectBindings,
|
|
2343
|
+
globalVarAliases,
|
|
2344
|
+
cssVariableMap
|
|
1882
2345
|
);
|
|
1883
2346
|
if (arrayClasses === null) {
|
|
1884
2347
|
collectArrayCandidateClasses(
|
|
@@ -1916,7 +2379,9 @@ function transformOxc(source, filename, options) {
|
|
|
1916
2379
|
effectiveFilename,
|
|
1917
2380
|
objectBindings,
|
|
1918
2381
|
source,
|
|
1919
|
-
classes
|
|
2382
|
+
classes,
|
|
2383
|
+
globalVarAliases,
|
|
2384
|
+
cssVariableMap
|
|
1920
2385
|
);
|
|
1921
2386
|
if (conditionalSpreadClassExpr) {
|
|
1922
2387
|
if (classNameAttr || szAttrs.length > 1) {
|
|
@@ -1936,9 +2401,15 @@ function transformOxc(source, filename, options) {
|
|
|
1936
2401
|
expression,
|
|
1937
2402
|
effectiveFilename,
|
|
1938
2403
|
objectBindings,
|
|
1939
|
-
source
|
|
2404
|
+
source,
|
|
2405
|
+
options,
|
|
2406
|
+
componentHoists?.usageNamesByElement.get(elementId),
|
|
2407
|
+
cssVariableMap,
|
|
2408
|
+
reservedCSSVariableNames,
|
|
2409
|
+
globalVarAliases
|
|
1940
2410
|
);
|
|
1941
2411
|
if (partial && szAttrs.length === 1) {
|
|
2412
|
+
const mergedStyleProps = hoistedStyleProps.length > 0 ? [...hoistedStyleProps, ...partial.styleProps] : partial.styleProps;
|
|
1942
2413
|
if (classNameAttr?.value?.type === "JSXExpressionContainer") {
|
|
1943
2414
|
const classExpression = classNameAttr.value.expression;
|
|
1944
2415
|
const classExpressionSource = source.slice(
|
|
@@ -1951,7 +2422,15 @@ function transformOxc(source, filename, options) {
|
|
|
1951
2422
|
`className={_szMerge(${classExpressionSource}, ${JSON.stringify(partial.className)})}`
|
|
1952
2423
|
);
|
|
1953
2424
|
edits.remove(whitespaceStart(source, szAttr.start), szAttr.end);
|
|
1954
|
-
applyStyleProps(
|
|
2425
|
+
applyStyleProps(
|
|
2426
|
+
edits,
|
|
2427
|
+
source,
|
|
2428
|
+
styleAttr,
|
|
2429
|
+
lastAttr,
|
|
2430
|
+
mergedStyleProps,
|
|
2431
|
+
openingNode.name.end
|
|
2432
|
+
);
|
|
2433
|
+
appliedHoistedStyleProps = true;
|
|
1955
2434
|
for (const c of partial.className.split(/\s+/)) {
|
|
1956
2435
|
if (c) {
|
|
1957
2436
|
classes.add(c);
|
|
@@ -1975,7 +2454,15 @@ function transformOxc(source, filename, options) {
|
|
|
1975
2454
|
} else {
|
|
1976
2455
|
edits.overwrite(szAttr.start, szAttr.end, partial.classNameAttr);
|
|
1977
2456
|
}
|
|
1978
|
-
applyStyleProps(
|
|
2457
|
+
applyStyleProps(
|
|
2458
|
+
edits,
|
|
2459
|
+
source,
|
|
2460
|
+
styleAttr,
|
|
2461
|
+
lastAttr,
|
|
2462
|
+
mergedStyleProps,
|
|
2463
|
+
openingNode.name.end
|
|
2464
|
+
);
|
|
2465
|
+
appliedHoistedStyleProps = true;
|
|
1979
2466
|
for (const c of partial.className.split(/\s+/)) {
|
|
1980
2467
|
if (c) {
|
|
1981
2468
|
classes.add(c);
|
|
@@ -1991,7 +2478,9 @@ function transformOxc(source, filename, options) {
|
|
|
1991
2478
|
}
|
|
1992
2479
|
throw err;
|
|
1993
2480
|
}
|
|
1994
|
-
const result = transformCore.transform(
|
|
2481
|
+
const result = transformCore.transform(
|
|
2482
|
+
applyGlobalVarAliasesToSzObject(szObj, globalVarAliases, cssVariableMap)
|
|
2483
|
+
);
|
|
1995
2484
|
for (const c of result.className.split(/\s+/)) {
|
|
1996
2485
|
if (c) {
|
|
1997
2486
|
szDerived.push(c);
|
|
@@ -2024,6 +2513,7 @@ function transformOxc(source, filename, options) {
|
|
|
2024
2513
|
transformed = true;
|
|
2025
2514
|
return;
|
|
2026
2515
|
}
|
|
2516
|
+
applyHoistedStyleProps();
|
|
2027
2517
|
const existingRaw = classNameAttr ? stringLiteralValue(classNameAttr.value) : null;
|
|
2028
2518
|
const mergedClasses = [
|
|
2029
2519
|
...existingRaw ? existingRaw.split(/\s+/).filter(Boolean) : [],
|
|
@@ -2058,7 +2548,8 @@ function transformOxc(source, filename, options) {
|
|
|
2058
2548
|
classes,
|
|
2059
2549
|
rawClassNames,
|
|
2060
2550
|
diagnostics,
|
|
2061
|
-
recoveryTokens
|
|
2551
|
+
recoveryTokens,
|
|
2552
|
+
cssVariableMap
|
|
2062
2553
|
};
|
|
2063
2554
|
}
|
|
2064
2555
|
function stringLiteralValue(value) {
|
|
@@ -2167,7 +2658,7 @@ function astObjectToSzObject(node, filename, bindings) {
|
|
|
2167
2658
|
}
|
|
2168
2659
|
return result;
|
|
2169
2660
|
}
|
|
2170
|
-
function astArrayToStaticClasses(node, filename, bindings) {
|
|
2661
|
+
function astArrayToStaticClasses(node, filename, bindings, globalVarAliases, cssVariableMap) {
|
|
2171
2662
|
const out = [];
|
|
2172
2663
|
for (const element of node.elements) {
|
|
2173
2664
|
if (!element || isFalsyLiteral(element)) {
|
|
@@ -2184,7 +2675,13 @@ function astArrayToStaticClasses(node, filename, bindings) {
|
|
|
2184
2675
|
}
|
|
2185
2676
|
let result;
|
|
2186
2677
|
try {
|
|
2187
|
-
result = transformCore.transform(
|
|
2678
|
+
result = transformCore.transform(
|
|
2679
|
+
applyGlobalVarAliasesToSzObject(
|
|
2680
|
+
astObjectToSzObject(objectNode, filename, bindings),
|
|
2681
|
+
globalVarAliases,
|
|
2682
|
+
cssVariableMap
|
|
2683
|
+
)
|
|
2684
|
+
);
|
|
2188
2685
|
} catch (err) {
|
|
2189
2686
|
if (err instanceof OxcNotImplementedError) {
|
|
2190
2687
|
return null;
|
|
@@ -2281,7 +2778,7 @@ function resolveObjectExpression(node, bindings) {
|
|
|
2281
2778
|
}
|
|
2282
2779
|
return null;
|
|
2283
2780
|
}
|
|
2284
|
-
function buildConditionalSpreadClassExpression(node, filename, bindings, source, classes) {
|
|
2781
|
+
function buildConditionalSpreadClassExpression(node, filename, bindings, source, classes, globalVarAliases, cssVariableMap) {
|
|
2285
2782
|
let conditionalSpread = null;
|
|
2286
2783
|
const otherProps = [];
|
|
2287
2784
|
for (const prop of node.properties) {
|
|
@@ -2304,14 +2801,18 @@ function buildConditionalSpreadClassExpression(node, filename, bindings, source,
|
|
|
2304
2801
|
otherProps,
|
|
2305
2802
|
node,
|
|
2306
2803
|
filename,
|
|
2307
|
-
bindings
|
|
2804
|
+
bindings,
|
|
2805
|
+
globalVarAliases,
|
|
2806
|
+
cssVariableMap
|
|
2308
2807
|
);
|
|
2309
2808
|
const alternate = compileConditionalSpreadBranch(
|
|
2310
2809
|
conditionalSpread.alternate,
|
|
2311
2810
|
otherProps,
|
|
2312
2811
|
node,
|
|
2313
2812
|
filename,
|
|
2314
|
-
bindings
|
|
2813
|
+
bindings,
|
|
2814
|
+
globalVarAliases,
|
|
2815
|
+
cssVariableMap
|
|
2315
2816
|
);
|
|
2316
2817
|
if (consequent === null || alternate === null) {
|
|
2317
2818
|
return null;
|
|
@@ -2324,7 +2825,7 @@ function buildConditionalSpreadClassExpression(node, filename, bindings, source,
|
|
|
2324
2825
|
const testSource = source.slice(conditionalSpread.test.start, conditionalSpread.test.end);
|
|
2325
2826
|
return `${testSource} ? ${JSON.stringify(consequent)} : ${JSON.stringify(alternate)}`;
|
|
2326
2827
|
}
|
|
2327
|
-
function compileConditionalSpreadBranch(branch, otherProps, sourceNode, filename, bindings) {
|
|
2828
|
+
function compileConditionalSpreadBranch(branch, otherProps, sourceNode, filename, bindings, globalVarAliases, cssVariableMap) {
|
|
2328
2829
|
const branchObject = resolveObjectExpression(branch, bindings);
|
|
2329
2830
|
if (!branchObject) {
|
|
2330
2831
|
return null;
|
|
@@ -2336,7 +2837,13 @@ function compileConditionalSpreadBranch(branch, otherProps, sourceNode, filename
|
|
|
2336
2837
|
filename,
|
|
2337
2838
|
bindings
|
|
2338
2839
|
);
|
|
2339
|
-
return transformCore.transform(
|
|
2840
|
+
return transformCore.transform(
|
|
2841
|
+
applyGlobalVarAliasesToSzObject(
|
|
2842
|
+
{ ...branchValue, ...overrides },
|
|
2843
|
+
globalVarAliases,
|
|
2844
|
+
cssVariableMap
|
|
2845
|
+
)
|
|
2846
|
+
).className;
|
|
2340
2847
|
} catch (err) {
|
|
2341
2848
|
if (err instanceof OxcNotImplementedError) {
|
|
2342
2849
|
return null;
|
|
@@ -2344,8 +2851,15 @@ function compileConditionalSpreadBranch(branch, otherProps, sourceNode, filename
|
|
|
2344
2851
|
throw err;
|
|
2345
2852
|
}
|
|
2346
2853
|
}
|
|
2347
|
-
function buildPartialObjectTransform(node, filename, bindings, source) {
|
|
2348
|
-
const partial = evaluatePartialObject(
|
|
2854
|
+
function buildPartialObjectTransform(node, filename, bindings, source, options, hoistedNames, cssVariableMap, reservedNames, globalVarAliases = /* @__PURE__ */ new Map()) {
|
|
2855
|
+
const partial = evaluatePartialObject(
|
|
2856
|
+
node,
|
|
2857
|
+
filename,
|
|
2858
|
+
bindings,
|
|
2859
|
+
source,
|
|
2860
|
+
globalVarAliases,
|
|
2861
|
+
cssVariableMap
|
|
2862
|
+
);
|
|
2349
2863
|
if (!partial || partial.dynamicProps.size === 0 && partial.conditionalClasses.length === 0) {
|
|
2350
2864
|
return null;
|
|
2351
2865
|
}
|
|
@@ -2354,11 +2868,17 @@ function buildPartialObjectTransform(node, filename, bindings, source) {
|
|
|
2354
2868
|
}
|
|
2355
2869
|
const classParts = [];
|
|
2356
2870
|
if (Object.keys(partial.staticProps).length > 0) {
|
|
2357
|
-
const { className: className2 } = transformCore.transform(
|
|
2871
|
+
const { className: className2 } = transformCore.transform(
|
|
2872
|
+
applyGlobalVarAliasesToSzObject(partial.staticProps, globalVarAliases, cssVariableMap)
|
|
2873
|
+
);
|
|
2358
2874
|
if (className2) {
|
|
2359
2875
|
classParts.push(className2);
|
|
2360
2876
|
}
|
|
2361
2877
|
}
|
|
2878
|
+
if (options?.mangleVars) {
|
|
2879
|
+
applyHoistedVariableNames(partial, hoistedNames, cssVariableMap);
|
|
2880
|
+
applyScopedVariablePlan(partial, hoistedNames, cssVariableMap, reservedNames);
|
|
2881
|
+
}
|
|
2362
2882
|
for (const [, info] of partial.dynamicProps) {
|
|
2363
2883
|
classParts.push(buildCSSVarClassName(info));
|
|
2364
2884
|
}
|
|
@@ -2367,12 +2887,351 @@ function buildPartialObjectTransform(node, filename, bindings, source) {
|
|
|
2367
2887
|
}
|
|
2368
2888
|
const className = classParts.filter(Boolean).join(" ");
|
|
2369
2889
|
const classNameAttr = partial.conditionalClasses.length > 0 ? `className={${buildConditionalClassSource(classParts, partial.conditionalClasses, source)}}` : `className="${className}"`;
|
|
2370
|
-
const styleProps = [...partial.dynamicProps.
|
|
2371
|
-
(info) => `${JSON.stringify(info.varName)}: ${generateStyleValueSource(info, source)}`
|
|
2890
|
+
const styleProps = [...partial.dynamicProps.entries()].filter(([id]) => !hoistedNames?.has(id)).map(
|
|
2891
|
+
([, info]) => `${JSON.stringify(info.varName)}: ${generateStyleValueSource(info, source)}`
|
|
2372
2892
|
);
|
|
2373
2893
|
return { className, classNameAttr, styleProps, usesColorVar: partial.usesColorVar };
|
|
2374
2894
|
}
|
|
2375
|
-
function
|
|
2895
|
+
function applyHoistedVariableNames(partial, hoistedNames, cssVariableMap) {
|
|
2896
|
+
if (!hoistedNames) {
|
|
2897
|
+
return;
|
|
2898
|
+
}
|
|
2899
|
+
for (const [id, name] of hoistedNames) {
|
|
2900
|
+
const info = partial.dynamicProps.get(id);
|
|
2901
|
+
if (info) {
|
|
2902
|
+
addCssVariableMapping(cssVariableMap, info.varName, name);
|
|
2903
|
+
info.varName = name;
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2907
|
+
function applyScopedVariablePlan(partial, hoistedNames, cssVariableMap, reservedNames) {
|
|
2908
|
+
const entries = [...partial.dynamicProps.entries()].filter(([id]) => !hoistedNames?.has(id));
|
|
2909
|
+
const plan = planCSSVariableNames(
|
|
2910
|
+
entries.map(([id]) => ({
|
|
2911
|
+
id,
|
|
2912
|
+
tier: "scoped",
|
|
2913
|
+
elementId: "self",
|
|
2914
|
+
propertyKey: id
|
|
2915
|
+
})),
|
|
2916
|
+
{ reservedNames }
|
|
2917
|
+
);
|
|
2918
|
+
for (const planned of plan) {
|
|
2919
|
+
const info = partial.dynamicProps.get(planned.id);
|
|
2920
|
+
if (info) {
|
|
2921
|
+
addCssVariableMapping(cssVariableMap, info.varName, planned.name);
|
|
2922
|
+
info.varName = planned.name;
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
function addCssVariableMapping(cssVariableMap, original, mangled) {
|
|
2927
|
+
if (!cssVariableMap) {
|
|
2928
|
+
return;
|
|
2929
|
+
}
|
|
2930
|
+
const existing = cssVariableMap.get(original);
|
|
2931
|
+
if (!existing) {
|
|
2932
|
+
cssVariableMap.set(original, mangled);
|
|
2933
|
+
return;
|
|
2934
|
+
}
|
|
2935
|
+
const values = Array.isArray(existing) ? existing : [existing];
|
|
2936
|
+
if (!values.includes(mangled)) {
|
|
2937
|
+
cssVariableMap.set(original, [...values, mangled]);
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
function normalizeGlobalVarAliases$1(input) {
|
|
2941
|
+
if (!input) {
|
|
2942
|
+
return /* @__PURE__ */ new Map();
|
|
2943
|
+
}
|
|
2944
|
+
const entries = input instanceof Map ? input.entries() : Array.isArray(input) ? input : Object.entries(input);
|
|
2945
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
2946
|
+
for (const [original, alias] of entries) {
|
|
2947
|
+
if (original.startsWith("--") && alias.startsWith("--")) {
|
|
2948
|
+
aliases.set(original, alias);
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
return aliases;
|
|
2952
|
+
}
|
|
2953
|
+
function applyGlobalVarAliasesToSzObject(object, globalVarAliases, cssVariableMap) {
|
|
2954
|
+
if (globalVarAliases.size === 0) {
|
|
2955
|
+
return object;
|
|
2956
|
+
}
|
|
2957
|
+
const rewritten = {};
|
|
2958
|
+
for (const [key, value] of Object.entries(object)) {
|
|
2959
|
+
rewritten[key] = applyGlobalVarAliasesToSzValue(value, globalVarAliases, cssVariableMap);
|
|
2960
|
+
}
|
|
2961
|
+
return rewritten;
|
|
2962
|
+
}
|
|
2963
|
+
function applyGlobalVarAliasesToSzValue(value, globalVarAliases, cssVariableMap) {
|
|
2964
|
+
if (typeof value === "string") {
|
|
2965
|
+
const alias = globalVarAliases.get(value);
|
|
2966
|
+
if (alias) {
|
|
2967
|
+
addCssVariableMapping(cssVariableMap, value, alias);
|
|
2968
|
+
return alias;
|
|
2969
|
+
}
|
|
2970
|
+
return value;
|
|
2971
|
+
}
|
|
2972
|
+
if (typeof value === "object") {
|
|
2973
|
+
return applyGlobalVarAliasesToSzObject(value, globalVarAliases, cssVariableMap);
|
|
2974
|
+
}
|
|
2975
|
+
return value;
|
|
2976
|
+
}
|
|
2977
|
+
function planOxcComponentVariableHoists(root, filename, bindings, source, maxDepth, reservedNames) {
|
|
2978
|
+
const nodes = [];
|
|
2979
|
+
const candidates = [];
|
|
2980
|
+
collectOxcHoistCandidates(root, null, nodes, candidates, filename, bindings, source);
|
|
2981
|
+
if (candidates.length < 2) {
|
|
2982
|
+
return {
|
|
2983
|
+
stylePropsByTarget: /* @__PURE__ */ new Map(),
|
|
2984
|
+
usageNamesByElement: /* @__PURE__ */ new Map(),
|
|
2985
|
+
diagnostics: []
|
|
2986
|
+
};
|
|
2987
|
+
}
|
|
2988
|
+
const plannedNames = planCSSVariableNames(
|
|
2989
|
+
candidates.map((candidate) => ({
|
|
2990
|
+
id: candidate.id,
|
|
2991
|
+
tier: "component",
|
|
2992
|
+
elementId: candidate.elementId,
|
|
2993
|
+
propertyKey: candidate.propertyKey,
|
|
2994
|
+
variantChain: candidate.variantChain || void 0
|
|
2995
|
+
})),
|
|
2996
|
+
{ reservedNames }
|
|
2997
|
+
);
|
|
2998
|
+
const nameByUsage = new Map(plannedNames.map((entry) => [entry.id, entry.name]));
|
|
2999
|
+
const candidateById = new Map(candidates.map((candidate) => [candidate.id, candidate]));
|
|
3000
|
+
const hoistUsages = candidates.map((candidate) => ({
|
|
3001
|
+
id: candidate.id,
|
|
3002
|
+
elementId: candidate.elementId,
|
|
3003
|
+
name: nameByUsage.get(candidate.id) ?? candidate.info.varName,
|
|
3004
|
+
valueKey: candidate.valueKey
|
|
3005
|
+
}));
|
|
3006
|
+
const analysis = planComponentVariableHoistsWithDiagnostics(nodes, hoistUsages, {
|
|
3007
|
+
maxDepth
|
|
3008
|
+
});
|
|
3009
|
+
const plans = analysis.plans;
|
|
3010
|
+
const stylePropsByTarget = /* @__PURE__ */ new Map();
|
|
3011
|
+
const usageNamesByElement = /* @__PURE__ */ new Map();
|
|
3012
|
+
for (const plan of plans) {
|
|
3013
|
+
const [firstUsageId] = plan.usageIds;
|
|
3014
|
+
const firstCandidate = firstUsageId ? candidateById.get(firstUsageId) : void 0;
|
|
3015
|
+
if (!firstCandidate) {
|
|
3016
|
+
continue;
|
|
3017
|
+
}
|
|
3018
|
+
appendMapArray(
|
|
3019
|
+
stylePropsByTarget,
|
|
3020
|
+
plan.targetElementId,
|
|
3021
|
+
`${JSON.stringify(plan.name)}: ${firstCandidate.valueSource}`
|
|
3022
|
+
);
|
|
3023
|
+
for (const usageId of plan.usageIds) {
|
|
3024
|
+
const candidate = candidateById.get(usageId);
|
|
3025
|
+
if (!candidate) {
|
|
3026
|
+
continue;
|
|
3027
|
+
}
|
|
3028
|
+
getOrCreateMap(usageNamesByElement, candidate.elementId).set(
|
|
3029
|
+
candidate.dynamicKey,
|
|
3030
|
+
plan.name
|
|
3031
|
+
);
|
|
3032
|
+
}
|
|
3033
|
+
}
|
|
3034
|
+
return {
|
|
3035
|
+
stylePropsByTarget,
|
|
3036
|
+
usageNamesByElement,
|
|
3037
|
+
diagnostics: analysis.diagnostics.map(formatHoistSkipDiagnostic)
|
|
3038
|
+
};
|
|
3039
|
+
}
|
|
3040
|
+
function formatHoistSkipDiagnostic(diagnostic) {
|
|
3041
|
+
const suffix = diagnostic.reason === "max-depth" && diagnostic.maxDepth !== void 0 ? ` (maxDepth ${diagnostic.maxDepth})` : "";
|
|
3042
|
+
return `[csszyx] mangleVars skipped component CSS variable hoist for ${diagnostic.name} across ${diagnostic.usageCount} usages: ${diagnostic.reason}${suffix}`;
|
|
3043
|
+
}
|
|
3044
|
+
function collectOxcHoistCandidates(node, parentElementId, nodes, candidates, filename, bindings, source) {
|
|
3045
|
+
if (node.type === "JSXElement") {
|
|
3046
|
+
const element = node;
|
|
3047
|
+
const opening = element.openingElement;
|
|
3048
|
+
const elementId = elementIdForOpening(opening);
|
|
3049
|
+
nodes.push({
|
|
3050
|
+
id: elementId,
|
|
3051
|
+
parentId: parentElementId,
|
|
3052
|
+
canHost: canHostHoistedStyleProps(opening)
|
|
3053
|
+
});
|
|
3054
|
+
collectOpeningHoistCandidates(opening, elementId, candidates, filename, bindings, source);
|
|
3055
|
+
for (const child of element.children) {
|
|
3056
|
+
collectOxcHoistCandidates(
|
|
3057
|
+
child,
|
|
3058
|
+
elementId,
|
|
3059
|
+
nodes,
|
|
3060
|
+
candidates,
|
|
3061
|
+
filename,
|
|
3062
|
+
bindings,
|
|
3063
|
+
source
|
|
3064
|
+
);
|
|
3065
|
+
}
|
|
3066
|
+
return;
|
|
3067
|
+
}
|
|
3068
|
+
if (node.type === "JSXFragment") {
|
|
3069
|
+
const fragment = node;
|
|
3070
|
+
const elementId = `f${node.start}`;
|
|
3071
|
+
nodes.push({ id: elementId, parentId: parentElementId, canHost: false });
|
|
3072
|
+
for (const child of fragment.children) {
|
|
3073
|
+
collectOxcHoistCandidates(
|
|
3074
|
+
child,
|
|
3075
|
+
elementId,
|
|
3076
|
+
nodes,
|
|
3077
|
+
candidates,
|
|
3078
|
+
filename,
|
|
3079
|
+
bindings,
|
|
3080
|
+
source
|
|
3081
|
+
);
|
|
3082
|
+
}
|
|
3083
|
+
return;
|
|
3084
|
+
}
|
|
3085
|
+
for (const key of Object.keys(node)) {
|
|
3086
|
+
if (isAstMetadataKey(key)) {
|
|
3087
|
+
continue;
|
|
3088
|
+
}
|
|
3089
|
+
const child = node[key];
|
|
3090
|
+
if (Array.isArray(child)) {
|
|
3091
|
+
for (const item of child) {
|
|
3092
|
+
if (isOxcNode(item)) {
|
|
3093
|
+
collectOxcHoistCandidates(
|
|
3094
|
+
item,
|
|
3095
|
+
parentElementId,
|
|
3096
|
+
nodes,
|
|
3097
|
+
candidates,
|
|
3098
|
+
filename,
|
|
3099
|
+
bindings,
|
|
3100
|
+
source
|
|
3101
|
+
);
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
} else if (isOxcNode(child)) {
|
|
3105
|
+
collectOxcHoistCandidates(
|
|
3106
|
+
child,
|
|
3107
|
+
parentElementId,
|
|
3108
|
+
nodes,
|
|
3109
|
+
candidates,
|
|
3110
|
+
filename,
|
|
3111
|
+
bindings,
|
|
3112
|
+
source
|
|
3113
|
+
);
|
|
3114
|
+
}
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
function collectOpeningHoistCandidates(opening, elementId, candidates, filename, bindings, source) {
|
|
3118
|
+
for (const attrRaw of opening.attributes ?? []) {
|
|
3119
|
+
if (attrRaw.type !== "JSXAttribute") {
|
|
3120
|
+
continue;
|
|
3121
|
+
}
|
|
3122
|
+
const attr = attrRaw;
|
|
3123
|
+
if (attr.name?.name !== "sz" || attr.value?.type !== "JSXExpressionContainer") {
|
|
3124
|
+
continue;
|
|
3125
|
+
}
|
|
3126
|
+
const expression = attr.value.expression;
|
|
3127
|
+
if (expression.type !== "ObjectExpression") {
|
|
3128
|
+
continue;
|
|
3129
|
+
}
|
|
3130
|
+
const partial = evaluatePartialObject(
|
|
3131
|
+
expression,
|
|
3132
|
+
filename,
|
|
3133
|
+
bindings,
|
|
3134
|
+
source,
|
|
3135
|
+
/* @__PURE__ */ new Map(),
|
|
3136
|
+
void 0
|
|
3137
|
+
);
|
|
3138
|
+
if (!partial || partial.conditionalClasses.length > 0) {
|
|
3139
|
+
continue;
|
|
3140
|
+
}
|
|
3141
|
+
for (const [dynamicKey, info] of partial.dynamicProps) {
|
|
3142
|
+
candidates.push({
|
|
3143
|
+
id: `${elementId}:${dynamicKey}`,
|
|
3144
|
+
elementId,
|
|
3145
|
+
dynamicKey,
|
|
3146
|
+
propertyKey: dynamicKey,
|
|
3147
|
+
variantChain: info.variantChain,
|
|
3148
|
+
valueSource: generateStyleValueSource(info, source),
|
|
3149
|
+
valueKey: buildDynamicValueKey(info, source),
|
|
3150
|
+
info
|
|
3151
|
+
});
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
function elementIdForOpening(opening) {
|
|
3156
|
+
return `e${opening.start}`;
|
|
3157
|
+
}
|
|
3158
|
+
function canHostHoistedStyleProps(opening) {
|
|
3159
|
+
if (!isDomJsxOpening(opening)) {
|
|
3160
|
+
return false;
|
|
3161
|
+
}
|
|
3162
|
+
const styleAttr = findJsxAttribute(opening, "style");
|
|
3163
|
+
return !styleAttr || styleAttr.value?.type === "JSXExpressionContainer";
|
|
3164
|
+
}
|
|
3165
|
+
function isDomJsxOpening(opening) {
|
|
3166
|
+
if (opening.name.type !== "JSXIdentifier") {
|
|
3167
|
+
return false;
|
|
3168
|
+
}
|
|
3169
|
+
const name = String(opening.name.name);
|
|
3170
|
+
return name.length > 0 && name.charAt(0) === name.charAt(0).toLowerCase();
|
|
3171
|
+
}
|
|
3172
|
+
function findJsxAttribute(opening, name) {
|
|
3173
|
+
for (const attrRaw of opening.attributes ?? []) {
|
|
3174
|
+
if (attrRaw.type === "JSXAttribute") {
|
|
3175
|
+
const attr = attrRaw;
|
|
3176
|
+
if (attr.name?.name === name) {
|
|
3177
|
+
return attr;
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
return null;
|
|
3182
|
+
}
|
|
3183
|
+
function collectStaticStyleCustomPropertyNames(node) {
|
|
3184
|
+
const names = /* @__PURE__ */ new Set();
|
|
3185
|
+
walk(node, (child) => {
|
|
3186
|
+
if (child.type !== "JSXOpeningElement") {
|
|
3187
|
+
return;
|
|
3188
|
+
}
|
|
3189
|
+
const styleAttr = findJsxAttribute(child, "style");
|
|
3190
|
+
if (styleAttr?.value?.type !== "JSXExpressionContainer") {
|
|
3191
|
+
return;
|
|
3192
|
+
}
|
|
3193
|
+
const expression = styleAttr.value.expression;
|
|
3194
|
+
if (expression.type !== "ObjectExpression") {
|
|
3195
|
+
return;
|
|
3196
|
+
}
|
|
3197
|
+
for (const propRaw of expression.properties ?? []) {
|
|
3198
|
+
if (propRaw.type !== "Property") {
|
|
3199
|
+
continue;
|
|
3200
|
+
}
|
|
3201
|
+
const key = propRaw.key;
|
|
3202
|
+
const name = literalStringValue(key);
|
|
3203
|
+
if (name?.startsWith("--")) {
|
|
3204
|
+
names.add(name);
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
});
|
|
3208
|
+
return names;
|
|
3209
|
+
}
|
|
3210
|
+
function literalStringValue(node) {
|
|
3211
|
+
if (node.type !== "Literal") {
|
|
3212
|
+
return null;
|
|
3213
|
+
}
|
|
3214
|
+
const value = node.value;
|
|
3215
|
+
return typeof value === "string" ? value : null;
|
|
3216
|
+
}
|
|
3217
|
+
function appendMapArray(map, key, value) {
|
|
3218
|
+
const existing = map.get(key);
|
|
3219
|
+
if (existing) {
|
|
3220
|
+
existing.push(value);
|
|
3221
|
+
} else {
|
|
3222
|
+
map.set(key, [value]);
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
function getOrCreateMap(map, key) {
|
|
3226
|
+
const existing = map.get(key);
|
|
3227
|
+
if (existing) {
|
|
3228
|
+
return existing;
|
|
3229
|
+
}
|
|
3230
|
+
const value = /* @__PURE__ */ new Map();
|
|
3231
|
+
map.set(key, value);
|
|
3232
|
+
return value;
|
|
3233
|
+
}
|
|
3234
|
+
function evaluatePartialObject(node, filename, bindings, source, globalVarAliases, cssVariableMap, variantChain = "") {
|
|
2376
3235
|
const staticProps = {};
|
|
2377
3236
|
const dynamicProps = /* @__PURE__ */ new Map();
|
|
2378
3237
|
const conditionalClasses = [];
|
|
@@ -2429,6 +3288,8 @@ function evaluatePartialObject(node, filename, bindings, source, variantChain =
|
|
|
2429
3288
|
filename,
|
|
2430
3289
|
bindings,
|
|
2431
3290
|
source,
|
|
3291
|
+
globalVarAliases,
|
|
3292
|
+
cssVariableMap,
|
|
2432
3293
|
nestedVariant
|
|
2433
3294
|
);
|
|
2434
3295
|
if (!nested) {
|
|
@@ -2449,8 +3310,20 @@ function evaluatePartialObject(node, filename, bindings, source, variantChain =
|
|
|
2449
3310
|
const consequent = extractStaticLiteralValue(conditional.consequent);
|
|
2450
3311
|
const alternate = extractStaticLiteralValue(conditional.alternate);
|
|
2451
3312
|
if (consequent !== null && alternate !== null) {
|
|
2452
|
-
const { className: consequentClasses } = transformCore.transform(
|
|
2453
|
-
|
|
3313
|
+
const { className: consequentClasses } = transformCore.transform(
|
|
3314
|
+
applyGlobalVarAliasesToSzObject(
|
|
3315
|
+
{ [key]: consequent },
|
|
3316
|
+
globalVarAliases,
|
|
3317
|
+
cssVariableMap
|
|
3318
|
+
)
|
|
3319
|
+
);
|
|
3320
|
+
const { className: alternateClasses } = transformCore.transform(
|
|
3321
|
+
applyGlobalVarAliasesToSzObject(
|
|
3322
|
+
{ [key]: alternate },
|
|
3323
|
+
globalVarAliases,
|
|
3324
|
+
cssVariableMap
|
|
3325
|
+
)
|
|
3326
|
+
);
|
|
2454
3327
|
conditionalClasses.push({
|
|
2455
3328
|
test: conditional.test,
|
|
2456
3329
|
consequent: prefixVariantClasses(consequentClasses, variantChain),
|
|
@@ -2479,14 +3352,15 @@ function evaluatePartialObject(node, filename, bindings, source, variantChain =
|
|
|
2479
3352
|
}
|
|
2480
3353
|
return { staticProps, dynamicProps, conditionalClasses, usesColorVar };
|
|
2481
3354
|
}
|
|
2482
|
-
function applyStyleProps(edits, source, styleAttr, lastAttr, styleProps) {
|
|
3355
|
+
function applyStyleProps(edits, source, styleAttr, lastAttr, styleProps, fallbackInsertOffset) {
|
|
2483
3356
|
if (styleProps.length === 0) {
|
|
2484
3357
|
return;
|
|
2485
3358
|
}
|
|
2486
3359
|
const propsSource = styleProps.join(", ");
|
|
2487
3360
|
if (!styleAttr) {
|
|
2488
|
-
|
|
2489
|
-
|
|
3361
|
+
const insertOffset = lastAttr?.end ?? fallbackInsertOffset;
|
|
3362
|
+
if (insertOffset !== void 0) {
|
|
3363
|
+
edits.appendRight(insertOffset, ` style={{${propsSource}}}`);
|
|
2490
3364
|
}
|
|
2491
3365
|
return;
|
|
2492
3366
|
}
|
|
@@ -2512,6 +3386,67 @@ function generateStyleValueSource(info, source) {
|
|
|
2512
3386
|
return `\`\${${expressionSource}}\``;
|
|
2513
3387
|
}
|
|
2514
3388
|
}
|
|
3389
|
+
function buildDynamicValueKey(info, source) {
|
|
3390
|
+
const expressionSource = normalizeDynamicExpressionKey(
|
|
3391
|
+
source.slice(info.expression.start, info.expression.end)
|
|
3392
|
+
);
|
|
3393
|
+
switch (info.category) {
|
|
3394
|
+
case transformCore.PropertyCategory.SPACING:
|
|
3395
|
+
return `spacing:${expressionSource}`;
|
|
3396
|
+
case transformCore.PropertyCategory.COLOR:
|
|
3397
|
+
return `color:${expressionSource}`;
|
|
3398
|
+
case transformCore.PropertyCategory.ANGLE:
|
|
3399
|
+
return `angle:${expressionSource}`;
|
|
3400
|
+
case transformCore.PropertyCategory.DURATION:
|
|
3401
|
+
return `duration:${expressionSource}`;
|
|
3402
|
+
default:
|
|
3403
|
+
return `pass:${expressionSource}`;
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
function normalizeDynamicExpressionKey(expressionSource) {
|
|
3407
|
+
let normalized = expressionSource.trim();
|
|
3408
|
+
while (hasRedundantOuterParens(normalized)) {
|
|
3409
|
+
normalized = normalized.slice(1, -1).trim();
|
|
3410
|
+
}
|
|
3411
|
+
return normalized;
|
|
3412
|
+
}
|
|
3413
|
+
function hasRedundantOuterParens(expressionSource) {
|
|
3414
|
+
if (!expressionSource.startsWith("(") || !expressionSource.endsWith(")")) {
|
|
3415
|
+
return false;
|
|
3416
|
+
}
|
|
3417
|
+
let depth = 0;
|
|
3418
|
+
let quote = null;
|
|
3419
|
+
let escaped = false;
|
|
3420
|
+
for (let index = 0; index < expressionSource.length; index++) {
|
|
3421
|
+
const char = expressionSource[index];
|
|
3422
|
+
if (quote) {
|
|
3423
|
+
if (escaped) {
|
|
3424
|
+
escaped = false;
|
|
3425
|
+
} else if (char === "\\") {
|
|
3426
|
+
escaped = true;
|
|
3427
|
+
} else if (char === quote) {
|
|
3428
|
+
quote = null;
|
|
3429
|
+
}
|
|
3430
|
+
continue;
|
|
3431
|
+
}
|
|
3432
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
3433
|
+
quote = char;
|
|
3434
|
+
continue;
|
|
3435
|
+
}
|
|
3436
|
+
if (char === "(") {
|
|
3437
|
+
depth++;
|
|
3438
|
+
} else if (char === ")") {
|
|
3439
|
+
depth--;
|
|
3440
|
+
if (depth === 0 && index !== expressionSource.length - 1) {
|
|
3441
|
+
return false;
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
if (depth < 0) {
|
|
3445
|
+
return false;
|
|
3446
|
+
}
|
|
3447
|
+
}
|
|
3448
|
+
return depth === 0;
|
|
3449
|
+
}
|
|
2515
3450
|
function buildCSSVarClassName(info) {
|
|
2516
3451
|
const variantPrefix = info.variantChain ? `${transformCore.getVariantPrefix(info.variantChain)}:` : "";
|
|
2517
3452
|
return `${variantPrefix}${info.twPrefix}-(${info.varName})`;
|
|
@@ -2544,9 +3479,21 @@ function prefixVariantClasses(className, variantChain) {
|
|
|
2544
3479
|
function isRuntimeExpression(node) {
|
|
2545
3480
|
return node.type === "Identifier" || node.type === "MemberExpression" || node.type === "CallExpression" || node.type === "ConditionalExpression" || node.type === "TemplateLiteral" || node.type === "BinaryExpression" || node.type === "LogicalExpression";
|
|
2546
3481
|
}
|
|
2547
|
-
function buildStaticConditionalClassExpression(node, filename, bindings, source, classes) {
|
|
2548
|
-
const consequent = resolveStaticClassString(
|
|
2549
|
-
|
|
3482
|
+
function buildStaticConditionalClassExpression(node, filename, bindings, source, classes, globalVarAliases, cssVariableMap) {
|
|
3483
|
+
const consequent = resolveStaticClassString(
|
|
3484
|
+
node.consequent,
|
|
3485
|
+
filename,
|
|
3486
|
+
bindings,
|
|
3487
|
+
globalVarAliases,
|
|
3488
|
+
cssVariableMap
|
|
3489
|
+
);
|
|
3490
|
+
const alternate = resolveStaticClassString(
|
|
3491
|
+
node.alternate,
|
|
3492
|
+
filename,
|
|
3493
|
+
bindings,
|
|
3494
|
+
globalVarAliases,
|
|
3495
|
+
cssVariableMap
|
|
3496
|
+
);
|
|
2550
3497
|
if (consequent === null || alternate === null) {
|
|
2551
3498
|
return null;
|
|
2552
3499
|
}
|
|
@@ -2558,7 +3505,7 @@ function buildStaticConditionalClassExpression(node, filename, bindings, source,
|
|
|
2558
3505
|
const testSource = source.slice(node.test.start, node.test.end);
|
|
2559
3506
|
return `${testSource} ? ${JSON.stringify(consequent)} : ${JSON.stringify(alternate)}`;
|
|
2560
3507
|
}
|
|
2561
|
-
function resolveStaticClassString(node, filename, bindings) {
|
|
3508
|
+
function resolveStaticClassString(node, filename, bindings, globalVarAliases, cssVariableMap) {
|
|
2562
3509
|
const unwrapped = unwrapExpression(node);
|
|
2563
3510
|
let objectNode = null;
|
|
2564
3511
|
if (unwrapped.type === "ObjectExpression") {
|
|
@@ -2570,7 +3517,13 @@ function resolveStaticClassString(node, filename, bindings) {
|
|
|
2570
3517
|
return null;
|
|
2571
3518
|
}
|
|
2572
3519
|
try {
|
|
2573
|
-
return transformCore.transform(
|
|
3520
|
+
return transformCore.transform(
|
|
3521
|
+
applyGlobalVarAliasesToSzObject(
|
|
3522
|
+
astObjectToSzObject(objectNode, filename, bindings),
|
|
3523
|
+
globalVarAliases,
|
|
3524
|
+
cssVariableMap
|
|
3525
|
+
)
|
|
3526
|
+
).className;
|
|
2574
3527
|
} catch (err) {
|
|
2575
3528
|
if (err instanceof OxcNotImplementedError) {
|
|
2576
3529
|
return null;
|
|
@@ -2685,17 +3638,22 @@ function unwrapExpression(node) {
|
|
|
2685
3638
|
}
|
|
2686
3639
|
return current;
|
|
2687
3640
|
}
|
|
3641
|
+
function isOxcNode(value) {
|
|
3642
|
+
return Boolean(
|
|
3643
|
+
value && typeof value === "object" && typeof value.type === "string"
|
|
3644
|
+
);
|
|
3645
|
+
}
|
|
3646
|
+
function isAstMetadataKey(key) {
|
|
3647
|
+
return key === "loc" || key === "range" || key === "start" || key === "end" || key === "type";
|
|
3648
|
+
}
|
|
2688
3649
|
function walk(node, visit) {
|
|
2689
|
-
if (!node
|
|
3650
|
+
if (!isOxcNode(node)) {
|
|
2690
3651
|
return;
|
|
2691
3652
|
}
|
|
2692
3653
|
const typed = node;
|
|
2693
|
-
if (typeof typed.type !== "string") {
|
|
2694
|
-
return;
|
|
2695
|
-
}
|
|
2696
3654
|
visit(typed);
|
|
2697
3655
|
for (const key of Object.keys(typed)) {
|
|
2698
|
-
if (key
|
|
3656
|
+
if (isAstMetadataKey(key)) {
|
|
2699
3657
|
continue;
|
|
2700
3658
|
}
|
|
2701
3659
|
const child = typed[key];
|
|
@@ -2709,6 +3667,108 @@ function walk(node, visit) {
|
|
|
2709
3667
|
}
|
|
2710
3668
|
}
|
|
2711
3669
|
|
|
3670
|
+
class OxcRustNotImplementedError extends Error {
|
|
3671
|
+
/**
|
|
3672
|
+
* @param detail Native loader or transform failure detail.
|
|
3673
|
+
*/
|
|
3674
|
+
constructor(detail) {
|
|
3675
|
+
super(`transformRust: native engine unavailable - ${detail}`);
|
|
3676
|
+
this.name = "OxcRustNotImplementedError";
|
|
3677
|
+
}
|
|
3678
|
+
}
|
|
3679
|
+
function transformRust(source, filename, options) {
|
|
3680
|
+
const [result] = transformRustBatch([{ filename, source }], options);
|
|
3681
|
+
if (!result) {
|
|
3682
|
+
throw new OxcRustNotImplementedError("native transform returned no result");
|
|
3683
|
+
}
|
|
3684
|
+
return result;
|
|
3685
|
+
}
|
|
3686
|
+
function ensureRustTransformAvailable() {
|
|
3687
|
+
try {
|
|
3688
|
+
native.transformBatch([]);
|
|
3689
|
+
} catch (err) {
|
|
3690
|
+
if (err instanceof OxcRustNotImplementedError) {
|
|
3691
|
+
throw err;
|
|
3692
|
+
}
|
|
3693
|
+
if (err instanceof native.CsszyxNativeUnavailableError) {
|
|
3694
|
+
throw new OxcRustNotImplementedError(
|
|
3695
|
+
`${err.message}; native package: ${err.packageName ?? "unsupported platform"}`
|
|
3696
|
+
);
|
|
3697
|
+
}
|
|
3698
|
+
throw err;
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
function transformRustBatch(files, options) {
|
|
3702
|
+
try {
|
|
3703
|
+
return native.transformBatch(
|
|
3704
|
+
files.map((file, index) => ({
|
|
3705
|
+
filename: file.filename ?? `file-${index}.tsx`,
|
|
3706
|
+
source: file.source
|
|
3707
|
+
})),
|
|
3708
|
+
{
|
|
3709
|
+
mangleVars: options?.mangleVars === true,
|
|
3710
|
+
mangleVarHoistMaxDepth: options?.mangleVarHoistMaxDepth,
|
|
3711
|
+
globalVarAliases: normalizeGlobalVarAliases(options?.globalVarAliases)
|
|
3712
|
+
}
|
|
3713
|
+
).map(fromNativeResult);
|
|
3714
|
+
} catch (err) {
|
|
3715
|
+
if (err instanceof OxcRustNotImplementedError) {
|
|
3716
|
+
throw err;
|
|
3717
|
+
}
|
|
3718
|
+
if (err instanceof native.CsszyxNativeUnavailableError) {
|
|
3719
|
+
throw new OxcRustNotImplementedError(
|
|
3720
|
+
`${err.message}; native package: ${err.packageName ?? "unsupported platform"}`
|
|
3721
|
+
);
|
|
3722
|
+
}
|
|
3723
|
+
throw err;
|
|
3724
|
+
}
|
|
3725
|
+
}
|
|
3726
|
+
function normalizeGlobalVarAliases(input) {
|
|
3727
|
+
if (!input) {
|
|
3728
|
+
return [];
|
|
3729
|
+
}
|
|
3730
|
+
const entries = input instanceof Map ? input.entries() : Array.isArray(input) ? input : Object.entries(input);
|
|
3731
|
+
return [...entries].filter(([original, alias]) => original.startsWith("--") && alias.startsWith("--")).map(([original, alias]) => ({ original, alias }));
|
|
3732
|
+
}
|
|
3733
|
+
function fromNativeResult(result) {
|
|
3734
|
+
return {
|
|
3735
|
+
code: result.code,
|
|
3736
|
+
transformed: result.metadata.transformed,
|
|
3737
|
+
usesRuntime: result.metadata.usesRuntime,
|
|
3738
|
+
usesMerge: result.metadata.usesMerge,
|
|
3739
|
+
usesColorVar: result.metadata.usesColorVar,
|
|
3740
|
+
classes: new Set(result.classes),
|
|
3741
|
+
rawClassNames: new Set(result.rawClassNames),
|
|
3742
|
+
diagnostics: result.diagnostics,
|
|
3743
|
+
recoveryTokens: new Map(
|
|
3744
|
+
result.recoveryTokens.map(({ token, ...data }) => [
|
|
3745
|
+
token,
|
|
3746
|
+
{
|
|
3747
|
+
mode: data.mode,
|
|
3748
|
+
component: data.component,
|
|
3749
|
+
path: data.path
|
|
3750
|
+
}
|
|
3751
|
+
])
|
|
3752
|
+
),
|
|
3753
|
+
cssVariableMap: aggregateCssVariableMap(result.cssVariableMap ?? [])
|
|
3754
|
+
};
|
|
3755
|
+
}
|
|
3756
|
+
function aggregateCssVariableMap(entries) {
|
|
3757
|
+
const map = /* @__PURE__ */ new Map();
|
|
3758
|
+
for (const entry of entries) {
|
|
3759
|
+
const existing = map.get(entry.original);
|
|
3760
|
+
if (!existing) {
|
|
3761
|
+
map.set(entry.original, entry.mangled);
|
|
3762
|
+
continue;
|
|
3763
|
+
}
|
|
3764
|
+
const values = Array.isArray(existing) ? existing : [existing];
|
|
3765
|
+
if (!values.includes(entry.mangled)) {
|
|
3766
|
+
map.set(entry.original, [...values, entry.mangled]);
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
return map;
|
|
3770
|
+
}
|
|
3771
|
+
|
|
2712
3772
|
const VERSION = "0.0.0";
|
|
2713
3773
|
const DEFAULT_COMPILER_OPTIONS = {
|
|
2714
3774
|
buildId: Date.now().toString(),
|
|
@@ -2738,17 +3798,22 @@ exports.CsszyxCompiler = CsszyxCompiler;
|
|
|
2738
3798
|
exports.DEFAULT_COMPILER_OPTIONS = DEFAULT_COMPILER_OPTIONS;
|
|
2739
3799
|
exports.ManifestBuilder = ManifestBuilder;
|
|
2740
3800
|
exports.OxcNotImplementedError = OxcNotImplementedError;
|
|
3801
|
+
exports.OxcRustNotImplementedError = OxcRustNotImplementedError;
|
|
2741
3802
|
exports.VERSION = VERSION;
|
|
2742
3803
|
exports.buildParentMap = buildParentMap;
|
|
2743
3804
|
exports.createRecoveryToken = createRecoveryToken;
|
|
3805
|
+
exports.ensureRustTransformAvailable = ensureRustTransformAvailable;
|
|
2744
3806
|
exports.generateRecoveryToken = generateRecoveryToken;
|
|
2745
3807
|
exports.hoistCSSVariables = hoistCSSVariables;
|
|
2746
3808
|
exports.injectRecoveryToken = injectRecoveryToken;
|
|
2747
3809
|
exports.isValidRecoveryMode = isValidRecoveryMode;
|
|
2748
3810
|
exports.mergeOptions = mergeOptions;
|
|
2749
3811
|
exports.parseManifest = parseManifest;
|
|
3812
|
+
exports.scanGlobalVarUsages = scanGlobalVarUsages;
|
|
2750
3813
|
exports.serializeManifest = serializeManifest;
|
|
2751
3814
|
exports.transformOxc = transformOxc;
|
|
3815
|
+
exports.transformRust = transformRust;
|
|
3816
|
+
exports.transformRustBatch = transformRustBatch;
|
|
2752
3817
|
exports.transformSourceCode = transformSourceCode;
|
|
2753
3818
|
exports.validateManifest = validateManifest;
|
|
2754
3819
|
exports.validateSzRecover = validateSzRecover;
|