@homebound/truss 2.0.0-next.11 → 2.0.0-next.13

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.
@@ -5,7 +5,7 @@ import { resolve, dirname, isAbsolute } from "path";
5
5
  // src/plugin/transform.ts
6
6
  import { parse } from "@babel/parser";
7
7
  import _traverse2 from "@babel/traverse";
8
- import _generate from "@babel/generator";
8
+ import _generate2 from "@babel/generator";
9
9
  import * as t4 from "@babel/types";
10
10
 
11
11
  // src/plugin/resolve-chain.ts
@@ -397,6 +397,7 @@ function resolveDelegateCall(abbr, entry, node, mapping, mediaQuery, pseudoClass
397
397
  pseudoElement,
398
398
  dynamicProps: targetEntry.props,
399
399
  incremented: false,
400
+ appendPx: true,
400
401
  dynamicExtraDefs: targetEntry.extraDefs,
401
402
  argNode: argAst
402
403
  };
@@ -882,6 +883,39 @@ function insertStylexNamespaceImport(ast, localName) {
882
883
  const idx = findLastImportIndex(ast);
883
884
  ast.program.body.splice(idx + 1, 0, stylexImport);
884
885
  }
886
+ function findNamedImportBinding(ast, source, importedName) {
887
+ for (const node of ast.program.body) {
888
+ if (!t.isImportDeclaration(node) || node.source.value !== source) continue;
889
+ for (const spec of node.specifiers) {
890
+ if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported, { name: importedName })) {
891
+ return spec.local.name;
892
+ }
893
+ }
894
+ }
895
+ return null;
896
+ }
897
+ function upsertNamedImports(ast, source, imports) {
898
+ if (imports.length === 0) return;
899
+ for (const node of ast.program.body) {
900
+ if (!t.isImportDeclaration(node) || node.source.value !== source) continue;
901
+ for (const entry of imports) {
902
+ const exists = node.specifiers.some(function(spec) {
903
+ return t.isImportSpecifier(spec) && t.isIdentifier(spec.imported, { name: entry.importedName });
904
+ });
905
+ if (exists) continue;
906
+ node.specifiers.push(t.importSpecifier(t.identifier(entry.localName), t.identifier(entry.importedName)));
907
+ }
908
+ return;
909
+ }
910
+ const importDecl = t.importDeclaration(
911
+ imports.map(function(entry) {
912
+ return t.importSpecifier(t.identifier(entry.localName), t.identifier(entry.importedName));
913
+ }),
914
+ t.stringLiteral(source)
915
+ );
916
+ const idx = findLastImportIndex(ast);
917
+ ast.program.body.splice(idx + 1, 0, importDecl);
918
+ }
885
919
  function extractChain(node, cssBinding) {
886
920
  const chain = [];
887
921
  let current = node;
@@ -1130,44 +1164,6 @@ function buildMaybeIncDeclaration(helperName, increment) {
1130
1164
  t2.variableDeclarator(t2.identifier(helperName), t2.arrowFunctionExpression([incParam], body))
1131
1165
  ]);
1132
1166
  }
1133
- function buildMergePropsDeclaration(helperName, stylexNamespaceName) {
1134
- const explicitClassNameParam = t2.identifier("explicitClassName");
1135
- const stylesRestParam = t2.restElement(t2.identifier("styles"));
1136
- const sxId = t2.identifier("sx");
1137
- return t2.functionDeclaration(
1138
- t2.identifier(helperName),
1139
- [explicitClassNameParam, stylesRestParam],
1140
- t2.blockStatement([
1141
- t2.variableDeclaration("const", [
1142
- t2.variableDeclarator(
1143
- sxId,
1144
- t2.callExpression(t2.memberExpression(t2.identifier(stylexNamespaceName), t2.identifier("props")), [
1145
- t2.spreadElement(t2.identifier("styles"))
1146
- ])
1147
- )
1148
- ]),
1149
- t2.returnStatement(
1150
- t2.objectExpression([
1151
- t2.spreadElement(sxId),
1152
- t2.objectProperty(
1153
- t2.identifier("className"),
1154
- t2.callExpression(
1155
- t2.memberExpression(
1156
- t2.binaryExpression(
1157
- "+",
1158
- t2.binaryExpression("+", explicitClassNameParam, t2.stringLiteral(" ")),
1159
- t2.logicalExpression("||", t2.memberExpression(sxId, t2.identifier("className")), t2.stringLiteral(""))
1160
- ),
1161
- t2.identifier("trim")
1162
- ),
1163
- []
1164
- )
1165
- )
1166
- ])
1167
- )
1168
- ])
1169
- );
1170
- }
1171
1167
  function buildCreateDeclaration(createVarName, stylexNamespaceName, createProperties) {
1172
1168
  const createCall = t2.callExpression(t2.memberExpression(t2.identifier(stylexNamespaceName), t2.identifier("create")), [
1173
1169
  t2.objectExpression(createProperties)
@@ -1218,7 +1214,9 @@ function isValidIdentifier(s) {
1218
1214
 
1219
1215
  // src/plugin/rewrite-sites.ts
1220
1216
  import _traverse from "@babel/traverse";
1217
+ import _generate from "@babel/generator";
1221
1218
  import * as t3 from "@babel/types";
1219
+ var generate = _generate.default ?? _generate;
1222
1220
  var traverse = _traverse.default ?? _traverse;
1223
1221
  function rewriteExpressionSites(options) {
1224
1222
  for (const site of options.sites) {
@@ -1231,7 +1229,13 @@ function rewriteExpressionSites(options) {
1231
1229
  );
1232
1230
  cssAttrPath.replaceWith(
1233
1231
  t3.jsxSpreadAttribute(
1234
- buildCssSpreadExpression(cssAttrPath, propsCall, options.mergePropsHelperName, options.needsMergePropsHelper)
1232
+ buildCssSpreadExpression(
1233
+ cssAttrPath,
1234
+ propsCall,
1235
+ options.mergePropsHelperName,
1236
+ options.needsMergePropsHelper,
1237
+ options.stylexNamespaceName
1238
+ )
1235
1239
  )
1236
1240
  );
1237
1241
  continue;
@@ -1243,7 +1247,10 @@ function rewriteExpressionSites(options) {
1243
1247
  options.ast,
1244
1248
  options.stylexNamespaceName,
1245
1249
  options.mergePropsHelperName,
1246
- options.needsMergePropsHelper
1250
+ options.needsMergePropsHelper,
1251
+ options.asStyleArrayHelperName,
1252
+ options.needsAsStyleArrayHelper,
1253
+ options.skippedCssPropMessages
1247
1254
  );
1248
1255
  }
1249
1256
  function getCssAttributePath(path) {
@@ -1311,6 +1318,12 @@ function buildPropsArgs(segments, options) {
1311
1318
  argExpr = t3.callExpression(t3.identifier(options.maybeIncHelperName), [seg.argNode]);
1312
1319
  } else if (seg.incremented) {
1313
1320
  argExpr = seg.argNode;
1321
+ } else if (seg.appendPx) {
1322
+ argExpr = t3.binaryExpression(
1323
+ "+",
1324
+ t3.callExpression(t3.identifier("String"), [seg.argNode]),
1325
+ t3.stringLiteral("px")
1326
+ );
1314
1327
  } else {
1315
1328
  argExpr = t3.callExpression(t3.identifier("String"), [seg.argNode]);
1316
1329
  }
@@ -1321,30 +1334,78 @@ function buildPropsArgs(segments, options) {
1321
1334
  }
1322
1335
  return args;
1323
1336
  }
1324
- function rewriteCssAttributeExpressions(ast, stylexNamespaceName, mergePropsHelperName, needsMergePropsHelper) {
1337
+ function rewriteCssAttributeExpressions(ast, stylexNamespaceName, mergePropsHelperName, needsMergePropsHelper, asStyleArrayHelperName, needsAsStyleArrayHelper, skippedCssPropMessages) {
1325
1338
  traverse(ast, {
1326
1339
  JSXAttribute(path) {
1327
1340
  if (!t3.isJSXIdentifier(path.node.name, { name: "css" })) return;
1328
1341
  const value = path.node.value;
1329
1342
  if (!t3.isJSXExpressionContainer(value)) return;
1330
1343
  if (!t3.isExpression(value.expression)) return;
1331
- const propsArgs = buildStyleObjectPropsArgs(value.expression, path) ?? buildStyleArrayLikePropsArgsFromExpression(value.expression, path);
1332
- if (!propsArgs) return;
1344
+ if (!isCssRewriteableExpression(value.expression, path)) {
1345
+ skippedCssPropMessages.push({
1346
+ message: explainSkippedCssRewrite(value.expression, path),
1347
+ line: path.node.loc?.start.line ?? null
1348
+ });
1349
+ return;
1350
+ }
1351
+ const propsArgs = lowerCssExpressionToPropsArgs(
1352
+ value.expression,
1353
+ path,
1354
+ asStyleArrayHelperName,
1355
+ needsAsStyleArrayHelper
1356
+ );
1357
+ if (!propsArgs) {
1358
+ skippedCssPropMessages.push({
1359
+ message: explainSkippedCssRewrite(value.expression, path),
1360
+ line: path.node.loc?.start.line ?? null
1361
+ });
1362
+ return;
1363
+ }
1333
1364
  const propsCall = t3.callExpression(
1334
1365
  t3.memberExpression(t3.identifier(stylexNamespaceName), t3.identifier("props")),
1335
1366
  propsArgs
1336
1367
  );
1337
1368
  path.replaceWith(
1338
- t3.jsxSpreadAttribute(buildCssSpreadExpression(path, propsCall, mergePropsHelperName, needsMergePropsHelper))
1369
+ t3.jsxSpreadAttribute(
1370
+ buildCssSpreadExpression(path, propsCall, mergePropsHelperName, needsMergePropsHelper, stylexNamespaceName)
1371
+ )
1339
1372
  );
1340
1373
  }
1341
1374
  });
1342
1375
  }
1343
- function buildCssSpreadExpression(path, propsCall, mergePropsHelperName, needsMergePropsHelper) {
1376
+ function isCssRewriteableExpression(expr, path) {
1377
+ return !!lowerCssExpressionToPropsArgs(expr, path, "asStyleArray", { current: false });
1378
+ }
1379
+ function lowerCssExpressionToPropsArgs(expr, path, asStyleArrayHelperName, needsAsStyleArrayHelper) {
1380
+ return buildStyleObjectPropsArgs(expr, path, asStyleArrayHelperName, needsAsStyleArrayHelper) ?? buildStyleArrayLikePropsArgsFromExpression(expr, path, asStyleArrayHelperName, needsAsStyleArrayHelper) ?? buildUnknownCssValuePropsArgs(expr, asStyleArrayHelperName, needsAsStyleArrayHelper);
1381
+ }
1382
+ function explainSkippedCssRewrite(expr, path) {
1383
+ if (t3.isObjectExpression(expr)) {
1384
+ for (const prop of expr.properties) {
1385
+ if (!t3.isSpreadElement(prop)) {
1386
+ return `[truss] Unsupported pattern: Could not rewrite css prop: object contains a non-spread property (${formatNodeSnippet(expr)})`;
1387
+ }
1388
+ const normalizedArg = normalizeStyleArrayLikeExpression(prop.argument, path, /* @__PURE__ */ new Set());
1389
+ if (!normalizedArg) {
1390
+ return `[truss] Unsupported pattern: Could not rewrite css prop: spread argument is not style-array-like (${formatNodeSnippet(prop.argument)})`;
1391
+ }
1392
+ }
1393
+ return `[truss] Unsupported pattern: Could not rewrite css prop: object spread composition was not recognized (${formatNodeSnippet(expr)})`;
1394
+ }
1395
+ return `[truss] Unsupported pattern: Could not rewrite css prop: expression is not style-array-like (${formatNodeSnippet(expr)})`;
1396
+ }
1397
+ function formatNodeSnippet(node) {
1398
+ return generate(node, { compact: true, comments: true }).code;
1399
+ }
1400
+ function buildCssSpreadExpression(path, propsCall, mergePropsHelperName, needsMergePropsHelper, stylexNamespaceName) {
1344
1401
  const existingClassNameExpr = removeExistingClassNameAttribute(path);
1345
1402
  if (!existingClassNameExpr) return propsCall;
1346
1403
  needsMergePropsHelper.current = true;
1347
- return t3.callExpression(t3.identifier(mergePropsHelperName), [existingClassNameExpr, ...propsCall.arguments]);
1404
+ return t3.callExpression(t3.identifier(mergePropsHelperName), [
1405
+ t3.identifier(stylexNamespaceName),
1406
+ existingClassNameExpr,
1407
+ ...propsCall.arguments
1408
+ ]);
1348
1409
  }
1349
1410
  function removeExistingClassNameAttribute(path) {
1350
1411
  const openingElement = path.parentPath;
@@ -1364,30 +1425,30 @@ function removeExistingClassNameAttribute(path) {
1364
1425
  }
1365
1426
  return null;
1366
1427
  }
1367
- function buildStyleObjectPropsArgs(expr, path) {
1428
+ function buildStyleObjectPropsArgs(expr, path, asStyleArrayHelperName, needsAsStyleArrayHelper) {
1368
1429
  if (!t3.isObjectExpression(expr) || expr.properties.length === 0) return null;
1369
- let sawStyleArray = false;
1370
1430
  const propsArgs = [];
1371
1431
  for (const prop of expr.properties) {
1372
1432
  if (!t3.isSpreadElement(prop)) return null;
1373
1433
  const normalizedArg = normalizeStyleArrayLikeExpression(prop.argument, path, /* @__PURE__ */ new Set());
1374
1434
  if (!normalizedArg) {
1375
- propsArgs.push(t3.spreadElement(prop.argument));
1435
+ propsArgs.push(
1436
+ t3.spreadElement(
1437
+ buildUnknownObjectSpreadFallback(prop.argument, asStyleArrayHelperName, needsAsStyleArrayHelper)
1438
+ )
1439
+ );
1376
1440
  continue;
1377
1441
  }
1378
- if (isStyleArrayLike(normalizedArg, path, /* @__PURE__ */ new Set())) {
1379
- sawStyleArray = true;
1380
- }
1381
1442
  const nestedArgs = buildStyleArrayLikePropsArgs(normalizedArg, path, /* @__PURE__ */ new Set());
1382
1443
  if (nestedArgs && t3.isArrayExpression(normalizedArg)) {
1383
1444
  propsArgs.push(...nestedArgs);
1384
1445
  } else {
1385
- propsArgs.push(t3.spreadElement(normalizedArg));
1446
+ propsArgs.push(t3.spreadElement(buildSafeSpreadArgument(normalizedArg)));
1386
1447
  }
1387
1448
  }
1388
- return sawStyleArray ? propsArgs : null;
1449
+ return propsArgs.length > 0 ? propsArgs : null;
1389
1450
  }
1390
- function buildStyleArrayLikePropsArgsFromExpression(expr, path) {
1451
+ function buildStyleArrayLikePropsArgsFromExpression(expr, path, asStyleArrayHelperName, needsAsStyleArrayHelper) {
1391
1452
  const normalizedExpr = normalizeStyleArrayLikeExpression(expr, path, /* @__PURE__ */ new Set());
1392
1453
  if (!normalizedExpr) return null;
1393
1454
  return buildStyleArrayLikePropsArgs(normalizedExpr, path, /* @__PURE__ */ new Set());
@@ -1409,7 +1470,7 @@ function buildStyleArrayLikePropsArgs(expr, path, seen) {
1409
1470
  if (nestedArgs && t3.isArrayExpression(normalizedArg)) {
1410
1471
  propsArgs.push(...nestedArgs);
1411
1472
  } else {
1412
- propsArgs.push(t3.spreadElement(normalizedArg));
1473
+ propsArgs.push(t3.spreadElement(buildSafeSpreadArgument(normalizedArg)));
1413
1474
  }
1414
1475
  continue;
1415
1476
  }
@@ -1418,10 +1479,14 @@ function buildStyleArrayLikePropsArgs(expr, path, seen) {
1418
1479
  return propsArgs;
1419
1480
  }
1420
1481
  if (t3.isIdentifier(expr) || t3.isMemberExpression(expr) || t3.isConditionalExpression(expr) || t3.isLogicalExpression(expr) || t3.isCallExpression(expr)) {
1421
- return [t3.spreadElement(expr)];
1482
+ return [t3.spreadElement(buildSafeSpreadArgument(expr))];
1422
1483
  }
1423
1484
  return null;
1424
1485
  }
1486
+ function buildUnknownCssValuePropsArgs(expr, asStyleArrayHelperName, needsAsStyleArrayHelper) {
1487
+ if (!(t3.isIdentifier(expr) || t3.isMemberExpression(expr) || t3.isCallExpression(expr))) return null;
1488
+ return [t3.spreadElement(buildUnknownObjectSpreadFallback(expr, asStyleArrayHelperName, needsAsStyleArrayHelper))];
1489
+ }
1425
1490
  function rewriteStyleObjectExpressions(ast) {
1426
1491
  traverse(ast, {
1427
1492
  ObjectExpression(path) {
@@ -1446,16 +1511,17 @@ function tryBuildStyleArrayFromObject(path) {
1446
1511
  // I.e. `...Css.df.$`, `...(cond ? Css.df.$ : {})`, or `...styles.wrapper`
1447
1512
  );
1448
1513
  if (!normalizedArg) {
1449
- return null;
1514
+ elements.push(t3.spreadElement(buildInlineAsStyleArrayExpression(prop.argument)));
1515
+ continue;
1450
1516
  }
1451
- if (isStyleArrayLike(normalizedArg, path, /* @__PURE__ */ new Set())) {
1517
+ if (isKnownStyleArrayLike(normalizedArg, path, /* @__PURE__ */ new Set())) {
1452
1518
  sawStyleArray = true;
1453
1519
  }
1454
1520
  if (t3.isArrayExpression(normalizedArg)) {
1455
1521
  elements.push(...normalizedArg.elements);
1456
1522
  continue;
1457
1523
  }
1458
- elements.push(t3.spreadElement(normalizedArg));
1524
+ elements.push(t3.spreadElement(buildSafeSpreadArgument(normalizedArg)));
1459
1525
  }
1460
1526
  if (!sawStyleArray) return null;
1461
1527
  return t3.arrayExpression(elements);
@@ -1515,8 +1581,8 @@ function isStyleArrayLike(expr, path, seen) {
1515
1581
  return !!(init && isStyleArrayLike(init, bindingPath, seen));
1516
1582
  }
1517
1583
  if (t3.isCallExpression(expr)) {
1518
- const returnExpr = getLocalFunctionReturnExpression(expr, path);
1519
- return !!(returnExpr && isStyleArrayLike(returnExpr, path, seen));
1584
+ const returnExpr = getCallStyleArrayLikeExpression(expr, path);
1585
+ return returnExpr ? isStyleArrayLike(returnExpr, path, seen) : true;
1520
1586
  }
1521
1587
  if (t3.isMemberExpression(expr)) {
1522
1588
  const object = expr.object;
@@ -1537,6 +1603,49 @@ function isStyleArrayLike(expr, path, seen) {
1537
1603
  }
1538
1604
  return false;
1539
1605
  }
1606
+ function isKnownStyleArrayLike(expr, path, seen) {
1607
+ if (seen.has(expr)) return false;
1608
+ seen.add(expr);
1609
+ if (t3.isArrayExpression(expr)) return true;
1610
+ if (t3.isLogicalExpression(expr) && expr.operator === "&&") {
1611
+ return isKnownStyleArrayLike(expr.right, path, seen);
1612
+ }
1613
+ if (t3.isLogicalExpression(expr) && (expr.operator === "||" || expr.operator === "??")) {
1614
+ return isKnownStyleArrayLike(expr.left, path, seen) && isStyleArrayLikeBranch(expr.right, path, seen);
1615
+ }
1616
+ if (t3.isConditionalExpression(expr)) {
1617
+ return isStyleArrayLikeBranch(expr.consequent, path, seen) && isStyleArrayLikeBranch(expr.alternate, path, seen);
1618
+ }
1619
+ if (t3.isIdentifier(expr)) {
1620
+ const binding = path.scope.getBinding(expr.name);
1621
+ const bindingPath = binding?.path;
1622
+ if (!bindingPath || !bindingPath.isVariableDeclarator()) return false;
1623
+ const init = bindingPath.node.init;
1624
+ return !!(init && isKnownStyleArrayLike(init, bindingPath, seen));
1625
+ }
1626
+ if (t3.isCallExpression(expr)) {
1627
+ const returnExpr = getCallStyleArrayLikeExpression(expr, path);
1628
+ return !!(returnExpr && isKnownStyleArrayLike(returnExpr, path, seen));
1629
+ }
1630
+ if (t3.isMemberExpression(expr)) {
1631
+ const object = expr.object;
1632
+ if (!t3.isIdentifier(object)) return false;
1633
+ const binding = path.scope.getBinding(object.name);
1634
+ const bindingPath = binding?.path;
1635
+ if (!bindingPath || !bindingPath.isVariableDeclarator()) return false;
1636
+ const init = bindingPath.node.init;
1637
+ if (!init || !t3.isObjectExpression(init)) return false;
1638
+ const propertyName = getStaticMemberPropertyName(expr, path);
1639
+ if (!propertyName) return false;
1640
+ for (const prop of init.properties) {
1641
+ if (!t3.isObjectProperty(prop) || prop.computed) continue;
1642
+ if (!isMatchingPropertyName(prop.key, propertyName)) continue;
1643
+ const value = prop.value;
1644
+ return t3.isExpression(value) && isKnownStyleArrayLike(value, bindingPath, seen);
1645
+ }
1646
+ }
1647
+ return false;
1648
+ }
1540
1649
  function isStyleArrayLikeBranch(expr, path, seen) {
1541
1650
  return isEmptyObjectExpression(expr) || isStyleArrayLike(expr, path, seen);
1542
1651
  }
@@ -1546,6 +1655,20 @@ function isMatchingPropertyName(key, name) {
1546
1655
  function isEmptyObjectExpression(expr) {
1547
1656
  return t3.isObjectExpression(expr) && expr.properties.length === 0;
1548
1657
  }
1658
+ function buildUnknownObjectSpreadFallback(expr, asStyleArrayHelperName, needsAsStyleArrayHelper) {
1659
+ needsAsStyleArrayHelper.current = true;
1660
+ return t3.callExpression(t3.identifier(asStyleArrayHelperName), [expr]);
1661
+ }
1662
+ function buildInlineAsStyleArrayExpression(expr) {
1663
+ return t3.conditionalExpression(
1664
+ t3.callExpression(t3.memberExpression(t3.identifier("Array"), t3.identifier("isArray")), [expr]),
1665
+ expr,
1666
+ t3.conditionalExpression(expr, t3.arrayExpression([expr]), t3.arrayExpression([]))
1667
+ );
1668
+ }
1669
+ function buildSafeSpreadArgument(expr) {
1670
+ return t3.isConditionalExpression(expr) || t3.isLogicalExpression(expr) ? t3.parenthesizedExpression(expr) : expr;
1671
+ }
1549
1672
  function getStaticMemberPropertyName(expr, path) {
1550
1673
  if (!expr.computed && t3.isIdentifier(expr.property)) {
1551
1674
  return expr.property.name;
@@ -1562,6 +1685,15 @@ function getStaticMemberPropertyName(expr, path) {
1562
1685
  }
1563
1686
  return null;
1564
1687
  }
1688
+ function getCallStyleArrayLikeExpression(expr, path) {
1689
+ const localReturnExpr = getLocalFunctionReturnExpression(expr, path);
1690
+ if (localReturnExpr) return localReturnExpr;
1691
+ const firstArg = expr.arguments[0];
1692
+ if (firstArg && !t3.isSpreadElement(firstArg) && (t3.isArrowFunctionExpression(firstArg) || t3.isFunctionExpression(firstArg))) {
1693
+ return getFunctionLikeReturnExpression(firstArg);
1694
+ }
1695
+ return null;
1696
+ }
1565
1697
  function getLocalFunctionReturnExpression(expr, path) {
1566
1698
  if (!t3.isIdentifier(expr.callee)) return null;
1567
1699
  const binding = path.scope.getBinding(expr.callee.name);
@@ -1589,7 +1721,7 @@ function getFunctionLikeReturnExpression(fn) {
1589
1721
 
1590
1722
  // src/plugin/transform.ts
1591
1723
  var traverse2 = _traverse2.default ?? _traverse2;
1592
- var generate = _generate.default ?? _generate;
1724
+ var generate2 = _generate2.default ?? _generate2;
1593
1725
  function transformTruss(code, filename, mapping) {
1594
1726
  if (!code.includes("Css")) return null;
1595
1727
  const ast = parse(code, {
@@ -1626,8 +1758,12 @@ function transformTruss(code, filename, mapping) {
1626
1758
  const stylexNamespaceName = existingStylexNamespace ?? reservePreferredName(usedTopLevelNames, "stylex");
1627
1759
  const createVarName = reservePreferredName(usedTopLevelNames, "css", "css_");
1628
1760
  const maybeIncHelperName = needsMaybeInc ? reservePreferredName(usedTopLevelNames, "__maybeInc") : null;
1629
- const mergePropsHelperName = reservePreferredName(usedTopLevelNames, "__mergeProps");
1761
+ const existingMergePropsHelperName = findNamedImportBinding(ast, "@homebound/truss/runtime", "mergeProps");
1762
+ const mergePropsHelperName = existingMergePropsHelperName ?? reservePreferredName(usedTopLevelNames, "mergeProps");
1630
1763
  const needsMergePropsHelper = { current: false };
1764
+ const existingAsStyleArrayHelperName = findNamedImportBinding(ast, "@homebound/truss/runtime", "asStyleArray");
1765
+ const asStyleArrayHelperName = existingAsStyleArrayHelperName ?? reservePreferredName(usedTopLevelNames, "asStyleArray");
1766
+ const needsAsStyleArrayHelper = { current: false };
1631
1767
  const runtimeLookupNames = /* @__PURE__ */ new Map();
1632
1768
  for (const [lookupKey] of runtimeLookups) {
1633
1769
  runtimeLookupNames.set(lookupKey, reservePreferredName(usedTopLevelNames, `__${lookupKey}`));
@@ -1641,21 +1777,31 @@ function transformTruss(code, filename, mapping) {
1641
1777
  maybeIncHelperName,
1642
1778
  mergePropsHelperName,
1643
1779
  needsMergePropsHelper,
1780
+ asStyleArrayHelperName,
1781
+ needsAsStyleArrayHelper,
1782
+ skippedCssPropMessages: errorMessages,
1644
1783
  runtimeLookupNames
1645
1784
  });
1646
1785
  removeCssImport(ast, cssBindingName);
1647
1786
  if (!findStylexNamespaceImport(ast)) {
1648
1787
  insertStylexNamespaceImport(ast, stylexNamespaceName);
1649
1788
  }
1789
+ if (needsMergePropsHelper.current || needsAsStyleArrayHelper.current) {
1790
+ const runtimeImports = [];
1791
+ if (needsMergePropsHelper.current) {
1792
+ runtimeImports.push({ importedName: "mergeProps", localName: mergePropsHelperName });
1793
+ }
1794
+ if (needsAsStyleArrayHelper.current) {
1795
+ runtimeImports.push({ importedName: "asStyleArray", localName: asStyleArrayHelperName });
1796
+ }
1797
+ upsertNamedImports(ast, "@homebound/truss/runtime", runtimeImports);
1798
+ }
1650
1799
  const markerVarNames = collectReferencedMarkerNames(createEntries);
1651
1800
  const hoistedMarkerDecls = hoistMarkerDeclarations(ast, markerVarNames);
1652
1801
  const declarationsToInsert = [];
1653
1802
  if (maybeIncHelperName) {
1654
1803
  declarationsToInsert.push(buildMaybeIncDeclaration(maybeIncHelperName, mapping.increment));
1655
1804
  }
1656
- if (needsMergePropsHelper.current) {
1657
- declarationsToInsert.push(buildMergePropsDeclaration(mergePropsHelperName, stylexNamespaceName));
1658
- }
1659
1805
  declarationsToInsert.push(...hoistedMarkerDecls);
1660
1806
  if (createProperties.length > 0) {
1661
1807
  declarationsToInsert.push(buildCreateDeclaration(createVarName, stylexNamespaceName, createProperties));
@@ -1676,10 +1822,12 @@ function transformTruss(code, filename, mapping) {
1676
1822
  declarationsToInsert.push(consoleError);
1677
1823
  }
1678
1824
  if (declarationsToInsert.length > 0) {
1679
- const insertIndex = findLastImportIndex(ast) + 1;
1680
- ast.program.body.splice(insertIndex, 0, ...declarationsToInsert);
1825
+ const insertIndex = ast.program.body.findIndex(function(node) {
1826
+ return !t4.isImportDeclaration(node);
1827
+ });
1828
+ ast.program.body.splice(insertIndex === -1 ? ast.program.body.length : insertIndex, 0, ...declarationsToInsert);
1681
1829
  }
1682
- const output = generate(ast, {
1830
+ const output = generate2(ast, {
1683
1831
  sourceFileName: filename,
1684
1832
  retainLines: false
1685
1833
  });
@@ -1935,9 +2083,9 @@ ${body}
1935
2083
 
1936
2084
  // src/plugin/rewrite-css-ts-imports.ts
1937
2085
  import { parse as parse3 } from "@babel/parser";
1938
- import _generate2 from "@babel/generator";
2086
+ import _generate3 from "@babel/generator";
1939
2087
  import * as t7 from "@babel/types";
1940
- var generate2 = _generate2.default ?? _generate2;
2088
+ var generate3 = _generate3.default ?? _generate3;
1941
2089
  function rewriteCssTsImports(code, filename) {
1942
2090
  if (!code.includes(".css.ts")) {
1943
2091
  return { code, changed: false };
@@ -1975,7 +2123,7 @@ function rewriteCssTsImports(code, filename) {
1975
2123
  const insertIndex = findLastImportIndex(ast) + 1;
1976
2124
  ast.program.body.splice(insertIndex, 0, ...sideEffectImports);
1977
2125
  }
1978
- const output = generate2(ast, {
2126
+ const output = generate3(ast, {
1979
2127
  sourceFileName: filename,
1980
2128
  retainLines: false
1981
2129
  });