styled-components-to-stylex-codemod 0.0.48 → 0.0.49

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.
@@ -102,6 +102,7 @@ function readReactComponentFromFunction(node, checker, exportedNames, defaultExp
102
102
  parameters: readParameters(node.parameters, checker),
103
103
  restProps: readRestProps(node.parameters[0], node.body),
104
104
  bodySupportsSxProp: readsSxProp(node.parameters[0], node.body),
105
+ bodySxTarget: detectSxTarget(node.parameters[0], node.body),
105
106
  checker,
106
107
  location: node
107
108
  });
@@ -117,6 +118,7 @@ function readReactComponentFromVariable(name, node, propTypeNode, statement, che
117
118
  parameters: readParameters(node.parameters, checker),
118
119
  restProps: readRestProps(node.parameters[0], node.body),
119
120
  bodySupportsSxProp: readsSxProp(node.parameters[0], node.body),
121
+ bodySxTarget: detectSxTarget(node.parameters[0], node.body),
120
122
  checker,
121
123
  location: node
122
124
  });
@@ -141,6 +143,7 @@ function buildComponentMetadata(args) {
141
143
  restProps: args.restProps,
142
144
  hasIndexSignature: propType ? hasIndexSignature(propType, args.checker) : false,
143
145
  supportsSxProp: explicitPropNames.includes("sx") || supportsResolvedSxProp || args.bodySupportsSxProp === true,
146
+ ...args.bodySxTarget ? { sxTarget: args.bodySxTarget } : {},
144
147
  sxExcludedProperties,
145
148
  ...sxAllowedProperties !== void 0 ? { sxAllowedProperties } : {}
146
149
  };
@@ -591,6 +594,120 @@ function readsSxProp(parameter, body) {
591
594
  ts.forEachChild(body, visit);
592
595
  return found;
593
596
  }
597
+ function detectSxTarget(parameter, body) {
598
+ if (!body) return;
599
+ const sxNames = collectSxBindingNames(parameter, body);
600
+ if (sxNames.size === 0) return;
601
+ const sxPropContainerNames = collectSxPropContainerNames(parameter);
602
+ const sxPropsNames = collectStylexPropsBindingNames(body, sxNames, sxPropContainerNames);
603
+ const root = returnedJsxRoot(body);
604
+ if (!root) return;
605
+ if (jsxOpeningUsesSx(jsxRootOpening(root), sxNames, sxPropsNames, sxPropContainerNames)) return "root";
606
+ return jsxChildrenUseSx(root, sxNames, sxPropsNames, sxPropContainerNames) ? "inner" : void 0;
607
+ }
608
+ function collectSxBindingNames(parameter, body) {
609
+ const names = /* @__PURE__ */ new Set();
610
+ if (parameter?.name && ts.isObjectBindingPattern(parameter.name)) collectBindingElementLocalNames(parameter.name, "sx", names);
611
+ else names.add("sx");
612
+ if (parameter?.name && ts.isIdentifier(parameter.name)) {
613
+ const propsName = parameter.name.text;
614
+ const visit = (node) => {
615
+ if (ts.isVariableDeclaration(node) && ts.isObjectBindingPattern(node.name) && node.initializer && isIdentifierNamed(unwrapExpression(node.initializer), propsName)) collectBindingElementLocalNames(node.name, "sx", names);
616
+ ts.forEachChild(node, visit);
617
+ };
618
+ ts.forEachChild(body, visit);
619
+ }
620
+ return names;
621
+ }
622
+ function collectBindingElementLocalNames(pattern, propertyName, names) {
623
+ for (const element of pattern.elements) if (bindingElementPropertyNameText(element) === propertyName && ts.isIdentifier(element.name)) names.add(element.name.text);
624
+ }
625
+ function collectSxPropContainerNames(parameter) {
626
+ const names = /* @__PURE__ */ new Set();
627
+ if (parameter?.name && ts.isIdentifier(parameter.name)) names.add(parameter.name.text);
628
+ return names;
629
+ }
630
+ function bindingElementPropertyNameText(element) {
631
+ if (element.propertyName) return ts.isIdentifier(element.propertyName) || ts.isStringLiteral(element.propertyName) ? element.propertyName.text : null;
632
+ return ts.isIdentifier(element.name) ? element.name.text : null;
633
+ }
634
+ function collectStylexPropsBindingNames(body, sxNames, sxPropContainerNames) {
635
+ const names = /* @__PURE__ */ new Set();
636
+ const visit = (node) => {
637
+ if (ts.isVariableDeclaration(node) && node.initializer && isStylexPropsCallWithSx(node.initializer, sxNames, sxPropContainerNames)) {
638
+ if (ts.isIdentifier(node.name)) names.add(node.name.text);
639
+ else if (ts.isObjectBindingPattern(node.name)) collectBindingPatternIdentifierNames(node.name, names);
640
+ }
641
+ ts.forEachChild(node, visit);
642
+ };
643
+ ts.forEachChild(body, visit);
644
+ return names;
645
+ }
646
+ function collectBindingPatternIdentifierNames(pattern, names) {
647
+ for (const element of pattern.elements) if (ts.isIdentifier(element.name)) names.add(element.name.text);
648
+ }
649
+ function isStylexPropsCallWithSx(expr, sxNames, sxPropContainerNames) {
650
+ const unwrapped = unwrapExpression(expr);
651
+ const noSxPropsNames = /* @__PURE__ */ new Set();
652
+ return ts.isCallExpression(unwrapped) && isStylexPropsCallee(unwrapped.expression) && unwrapped.arguments.some((arg) => expressionReferencesNames(arg, sxNames, noSxPropsNames, sxPropContainerNames));
653
+ }
654
+ function isStylexPropsCallee(expr) {
655
+ return ts.isPropertyAccessExpression(expr) && expr.name.text === "props" && ts.isIdentifier(expr.expression) && expr.expression.text === "stylex";
656
+ }
657
+ function returnedJsxRoot(body) {
658
+ if (ts.isJsxElement(body) || ts.isJsxSelfClosingElement(body)) return body;
659
+ if (!ts.isBlock(body)) return null;
660
+ for (const statement of body.statements) {
661
+ if (!ts.isReturnStatement(statement) || !statement.expression) continue;
662
+ const expr = unwrapExpression(statement.expression);
663
+ if (ts.isJsxElement(expr) || ts.isJsxSelfClosingElement(expr)) return expr;
664
+ }
665
+ return null;
666
+ }
667
+ function jsxChildrenUseSx(root, sxNames, sxPropsNames, sxPropContainerNames) {
668
+ if (!ts.isJsxElement(root)) return false;
669
+ let found = false;
670
+ const visit = (node) => {
671
+ if (found) return;
672
+ if (functionShadowsSxReference(node, sxNames, sxPropContainerNames)) return;
673
+ if (ts.isJsxElement(node) && jsxOpeningUsesSx(node.openingElement, sxNames, sxPropsNames, sxPropContainerNames) || ts.isJsxSelfClosingElement(node) && jsxOpeningUsesSx(node, sxNames, sxPropsNames, sxPropContainerNames)) {
674
+ found = true;
675
+ return;
676
+ }
677
+ ts.forEachChild(node, visit);
678
+ };
679
+ for (const child of root.children) visit(child);
680
+ return found;
681
+ }
682
+ function jsxRootOpening(root) {
683
+ return ts.isJsxElement(root) ? root.openingElement : root;
684
+ }
685
+ function jsxOpeningUsesSx(opening, sxNames, sxPropsNames, sxPropContainerNames) {
686
+ return opening.attributes.properties.some((attribute) => {
687
+ if (ts.isJsxSpreadAttribute(attribute)) return expressionReferencesNames(attribute.expression, sxNames, sxPropsNames, sxPropContainerNames);
688
+ if (!ts.isIdentifier(attribute.name) || !attribute.initializer) return false;
689
+ if (!ts.isJsxExpression(attribute.initializer) || !attribute.initializer.expression) return false;
690
+ if (attribute.name.text === "className" || attribute.name.text === "style") return expressionReferencesStylexPropsBinding(attribute.initializer.expression, sxPropsNames);
691
+ if (attribute.name.text !== "sx") return false;
692
+ return expressionReferencesNames(attribute.initializer.expression, sxNames, sxPropsNames, sxPropContainerNames);
693
+ });
694
+ }
695
+ function expressionReferencesStylexPropsBinding(expr, sxPropsNames) {
696
+ const unwrapped = unwrapExpression(expr);
697
+ return ts.isIdentifier(unwrapped) && sxPropsNames.has(unwrapped.text);
698
+ }
699
+ function expressionReferencesNames(expr, sxNames, sxPropsNames, sxPropContainerNames) {
700
+ const unwrapped = unwrapExpression(expr);
701
+ if (ts.isIdentifier(unwrapped)) return sxNames.has(unwrapped.text) || sxPropsNames.has(unwrapped.text);
702
+ if (ts.isPropertyAccessExpression(unwrapped) && unwrapped.name.text === "sx" && ts.isIdentifier(unwrapped.expression)) return sxPropContainerNames.has(unwrapped.expression.text);
703
+ return isStylexPropsCallWithSx(unwrapped, sxNames, sxPropContainerNames);
704
+ }
705
+ function functionShadowsSxReference(node, sxNames, sxPropContainerNames) {
706
+ if (!isFunctionWithParameters(node)) return false;
707
+ for (const name of sxPropContainerNames) if (node.parameters.some((parameter) => isBindingNameNamed(parameter.name, name))) return true;
708
+ for (const name of sxNames) if (node.parameters.some((parameter) => isBindingNameNamed(parameter.name, name))) return true;
709
+ return node.parameters.some((parameter) => ts.isObjectBindingPattern(parameter.name) && bindingPatternHasName(parameter.name, "sx"));
710
+ }
594
711
  function isFunctionWithParameterNamed(node, name) {
595
712
  return isFunctionWithParameters(node) ? node.parameters.some((parameter) => isBindingNameNamed(parameter.name, name)) : false;
596
713
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "styled-components-to-stylex-codemod",
3
- "version": "0.0.48",
3
+ "version": "0.0.49",
4
4
  "description": "Codemod to transform styled-components to StyleX",
5
5
  "keywords": [
6
6
  "codemod",