@sanity/ui-codemod 1.0.0-alpha.4 → 1.0.0-alpha.5

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.
@@ -1,4 +1,151 @@
1
+ import { getComponentLocalNames, insertTodoWarning } from "./transformComponent.js";
2
+ import { readFileSync, existsSync } from "node:fs";
3
+ import { resolve, dirname, join } from "node:path";
1
4
  import { LAYOUT_MODS } from "./layout-mods.js";
5
+ const parseCache = /* @__PURE__ */ new Map();
6
+ function parseModule(j, filePath) {
7
+ const cached = parseCache.get(filePath);
8
+ if (cached)
9
+ return cached;
10
+ try {
11
+ const source = readFileSync(filePath, "utf8"), root = j(source);
12
+ return parseCache.set(filePath, root), root;
13
+ } catch {
14
+ return null;
15
+ }
16
+ }
17
+ const EXTENSIONS = [".tsx", ".ts", ".jsx", ".js"];
18
+ function resolveRelativeModulePath(fromFilePath, moduleSpecifier) {
19
+ if (!moduleSpecifier.startsWith("."))
20
+ return null;
21
+ const base = resolve(dirname(fromFilePath), moduleSpecifier);
22
+ for (const ext of EXTENSIONS) {
23
+ const filePath = `${base}${ext}`;
24
+ if (existsSync(filePath))
25
+ return filePath;
26
+ }
27
+ for (const ext of EXTENSIONS) {
28
+ const indexPath = join(base, `index${ext}`);
29
+ if (existsSync(indexPath))
30
+ return indexPath;
31
+ }
32
+ return existsSync(base) ? base : null;
33
+ }
34
+ function findVariableInit(j, root, name) {
35
+ let init = null;
36
+ return root.find(j.VariableDeclarator).forEach((path) => {
37
+ const { id } = path.node;
38
+ id.type === "Identifier" && id.name === name && path.node.init && (init = path.node.init);
39
+ }), init;
40
+ }
41
+ function getExportSpecifierName(exported) {
42
+ return exported.type === "Identifier" || exported.type === "JSXIdentifier" ? exported.name : null;
43
+ }
44
+ function getNamedExportInit(j, exportName, filePath, visited = /* @__PURE__ */ new Set()) {
45
+ if (visited.has(filePath))
46
+ return null;
47
+ visited.add(filePath);
48
+ const root = parseModule(j, filePath);
49
+ if (!root)
50
+ return null;
51
+ for (const path of root.find(j.ExportNamedDeclaration).paths()) {
52
+ const { declaration, specifiers, source } = path.node, reexportSource = typeof source?.value == "string" ? source.value : null;
53
+ if (declaration?.type === "VariableDeclaration") {
54
+ for (const declarator of declaration.declarations)
55
+ if (declarator.type === "VariableDeclarator" && declarator.id.type === "Identifier" && declarator.id.name === exportName && declarator.init)
56
+ return { init: declarator.init, modulePath: filePath };
57
+ }
58
+ for (const spec of specifiers ?? []) {
59
+ if (spec.type !== "ExportSpecifier")
60
+ continue;
61
+ const exported = getExportSpecifierName(spec.exported);
62
+ if (!exported || exported !== exportName)
63
+ continue;
64
+ const local = spec.local?.type === "Identifier" ? spec.local.name : exported;
65
+ if (reexportSource) {
66
+ const resolvedPath = resolveRelativeModulePath(filePath, reexportSource);
67
+ if (resolvedPath) {
68
+ const followed = getNamedExportInit(j, local, resolvedPath, visited);
69
+ if (followed)
70
+ return followed;
71
+ }
72
+ continue;
73
+ }
74
+ const init = findVariableInit(j, root, local);
75
+ if (init)
76
+ return { init, modulePath: filePath };
77
+ }
78
+ }
79
+ return null;
80
+ }
81
+ function getStyledComponentName(node) {
82
+ if (!node || typeof node != "object" || !("type" in node))
83
+ return null;
84
+ const current = node;
85
+ if (current.type === "TaggedTemplateExpression")
86
+ return getStyledComponentName(current.tag);
87
+ if (current.type === "CallExpression") {
88
+ const callee = current.callee;
89
+ if (callee && typeof callee == "object" && "type" in callee && callee.type === "Identifier" && "name" in callee && callee.name === "styled") {
90
+ const arg = current.arguments?.[0];
91
+ return arg && typeof arg == "object" && "type" in arg && arg.type === "Identifier" && "name" in arg ? arg.name : null;
92
+ }
93
+ return getStyledComponentName(callee);
94
+ }
95
+ return current.type === "MemberExpression" && current.object ? getStyledComponentName(current.object) : null;
96
+ }
97
+ function getSameFileStyledComponentAliases(j, root, localNames) {
98
+ const aliases = /* @__PURE__ */ new Set(), names = new Set(localNames);
99
+ return root.find(j.VariableDeclarator).forEach((path) => {
100
+ const { id, init } = path.node;
101
+ if (!init || id.type !== "Identifier")
102
+ return;
103
+ const baseComponent = getStyledComponentName(init);
104
+ baseComponent && names.has(baseComponent) && aliases.add(id.name);
105
+ }), aliases;
106
+ }
107
+ function getImportedStyledComponentAliases(j, root, componentName, filePath, options) {
108
+ const aliases = /* @__PURE__ */ new Set();
109
+ return filePath && root.find(j.ImportDeclaration).forEach((path) => {
110
+ const source = path.node.source.value;
111
+ if (typeof source != "string")
112
+ return;
113
+ const resolvedPath = resolveRelativeModulePath(filePath, source);
114
+ if (resolvedPath)
115
+ for (const spec of path.node.specifiers ?? []) {
116
+ if (spec.type !== "ImportSpecifier" || "importKind" in spec && spec.importKind === "type" || spec.imported.type !== "Identifier")
117
+ continue;
118
+ const exportName = spec.imported.name, localName = spec.local?.type === "Identifier" ? spec.local.name : exportName, namedExport = getNamedExportInit(j, exportName, resolvedPath);
119
+ if (!namedExport)
120
+ continue;
121
+ const sourceRoot = parseModule(j, namedExport.modulePath);
122
+ if (!sourceRoot)
123
+ continue;
124
+ const exportLocalNames = getComponentLocalNames(j, sourceRoot, componentName, options), baseComponent = getStyledComponentName(namedExport.init);
125
+ baseComponent && exportLocalNames.has(baseComponent) && aliases.add(localName);
126
+ }
127
+ }), aliases;
128
+ }
129
+ function getStyledComponentAliases(j, root, componentName, filePath, localNames, options) {
130
+ const sameFile = getSameFileStyledComponentAliases(j, root, localNames), imported = getImportedStyledComponentAliases(j, root, componentName, filePath, options);
131
+ return /* @__PURE__ */ new Set([...sameFile, ...imported]);
132
+ }
133
+ const DEFAULT_WARNING = "Please double check styled-component migration below";
134
+ function transformStyledComponents(j, root, aliases, filter, options = {}) {
135
+ const names = new Set(aliases), { callback, warning = DEFAULT_WARNING } = options;
136
+ let hasChanges = !1;
137
+ return root.find(j.JSXOpeningElement).forEach((path) => {
138
+ const name = path.node.name;
139
+ if (name.type !== "JSXIdentifier" || !names.has(name.name))
140
+ return;
141
+ const attrs = path.node.attributes ?? [];
142
+ if (!filter(attrs)) {
143
+ insertTodoWarning(j, path, warning) && (hasChanges = !0);
144
+ return;
145
+ }
146
+ callback?.(path) && (hasChanges = !0);
147
+ }), hasChanges;
148
+ }
2
149
  const FLEX_MODS = {
3
150
  ...LAYOUT_MODS,
4
151
  align: {
@@ -69,6 +216,8 @@ const FLEX_MODS = {
69
216
  }
70
217
  };
71
218
  export {
72
- FLEX_MODS
219
+ FLEX_MODS,
220
+ getStyledComponentAliases,
221
+ transformStyledComponents
73
222
  };
74
223
  //# sourceMappingURL=flex.mods.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"flex.mods.js","sources":["../../src/transforms/latest/flex/flex.mods.ts"],"sourcesContent":["import {LAYOUT_MODS} from '../../../constants/latest/layout-mods'\nimport type {AttributeMods} from '../../../types/AttributeMods'\n\n/** @internal */\nexport const FLEX_MODS: AttributeMods = {\n ...LAYOUT_MODS,\n align: {\n type: 'rename-only',\n name: 'alignItems',\n },\n direction: {\n type: 'rename-only',\n name: 'flexDirection',\n },\n gridAutoColumns: {\n type: 'style-only',\n style: 'gridAutoColumns',\n },\n gridAutoFlow: {\n type: 'style-only',\n style: 'gridAutoFlow',\n },\n gridAutoRows: {\n type: 'style-only',\n style: 'gridAutoRows',\n },\n gridTemplateColumns: {\n type: 'style-mapped',\n style: 'gridTemplateColumns',\n mapping: {\n 0: '0px',\n 1: 'repeat(1, 1fr)',\n 2: 'repeat(2, 1fr)',\n 3: 'repeat(3, 1fr)',\n 4: 'repeat(4, 1fr)',\n 5: 'repeat(5, 1fr)',\n 6: 'repeat(6, 1fr)',\n 7: 'repeat(7, 1fr)',\n 8: 'repeat(8, 1fr)',\n 9: 'repeat(9, 1fr)',\n 10: 'repeat(10, 1fr)',\n 11: 'repeat(11, 1fr)',\n 12: 'repeat(12, 1fr)',\n },\n },\n gridTemplateRows: {\n type: 'style-mapped',\n style: 'gridTemplateRows',\n mapping: {\n 0: '0px',\n 1: 'repeat(1, 1fr)',\n 2: 'repeat(2, 1fr)',\n 3: 'repeat(3, 1fr)',\n 4: 'repeat(4, 1fr)',\n 5: 'repeat(5, 1fr)',\n 6: 'repeat(6, 1fr)',\n 7: 'repeat(7, 1fr)',\n 8: 'repeat(8, 1fr)',\n 9: 'repeat(9, 1fr)',\n 10: 'repeat(10, 1fr)',\n 11: 'repeat(11, 1fr)',\n 12: 'repeat(12, 1fr)',\n },\n },\n wrap: {\n type: 'rename-only',\n name: 'flexWrap',\n },\n justify: {\n type: 'rename-only',\n name: 'justifyContent',\n },\n}\n"],"names":[],"mappings":";AAIO,MAAM,YAA2B;AAAA,EACtC,GAAG;AAAA,EACH,OAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAAA,EAER,WAAW;AAAA,IACT,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAAA,EAER,iBAAiB;AAAA,IACf,MAAM;AAAA,IACN,OAAO;AAAA,EAAA;AAAA,EAET,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,OAAO;AAAA,EAAA;AAAA,EAET,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,OAAO;AAAA,EAAA;AAAA,EAET,qBAAqB;AAAA,IACnB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,MACP,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IAAA;AAAA,EACN;AAAA,EAEF,kBAAkB;AAAA,IAChB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,MACP,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IAAA;AAAA,EACN;AAAA,EAEF,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAAA,EAER,SAAS;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAEV;"}
1
+ {"version":3,"file":"flex.mods.js","sources":["../../src/utils/parseModule.ts","../../src/utils/resolveRelativeModulePath.ts","../../src/utils/getNamedExportInit.ts","../../src/utils/getStyledComponentName.ts","../../src/utils/getStyledComponentAliases.ts","../../src/utils/transformStyledComponents.ts","../../src/transforms/latest/flex/flex.mods.ts"],"sourcesContent":["import {readFileSync} from 'node:fs'\n\nimport type {API, Collection} from 'jscodeshift'\n\nconst parseCache = new Map<string, Collection>()\n\nexport function parseModule(j: API['jscodeshift'], filePath: string): Collection | null {\n const cached = parseCache.get(filePath)\n\n if (cached) {\n return cached\n }\n\n try {\n const source = readFileSync(filePath, 'utf8')\n const root = j(source)\n\n parseCache.set(filePath, root)\n\n return root\n } catch {\n return null\n }\n}\n\n/** @internal */\nexport function clearModuleParseCache(): void {\n parseCache.clear()\n}\n","import {existsSync} from 'node:fs'\nimport {dirname, join, resolve} from 'node:path'\n\nconst EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js'] as const\n\nexport function resolveRelativeModulePath(\n fromFilePath: string,\n moduleSpecifier: string,\n): string | null {\n if (!moduleSpecifier.startsWith('.')) {\n return null\n }\n\n const base = resolve(dirname(fromFilePath), moduleSpecifier)\n\n for (const ext of EXTENSIONS) {\n const filePath = `${base}${ext}`\n\n if (existsSync(filePath)) {\n return filePath\n }\n }\n\n for (const ext of EXTENSIONS) {\n const indexPath = join(base, `index${ext}`)\n\n if (existsSync(indexPath)) {\n return indexPath\n }\n }\n\n if (existsSync(base)) {\n return base\n }\n\n return null\n}\n","import type {API, Expression, ExportSpecifier} from 'jscodeshift'\n\nimport {parseModule} from './parseModule'\nimport {resolveRelativeModulePath} from './resolveRelativeModulePath'\n\nexport type NamedExportInit = {\n init: Expression\n modulePath: string\n}\n\nfunction findVariableInit(\n j: API['jscodeshift'],\n root: ReturnType<API['jscodeshift']>,\n name: string,\n): Expression | null {\n let init: Expression | null = null\n\n root.find(j.VariableDeclarator).forEach((path) => {\n const {id} = path.node\n\n if (id.type === 'Identifier' && id.name === name && path.node.init) {\n init = path.node.init\n }\n })\n\n return init\n}\n\nfunction getExportSpecifierName(exported: ExportSpecifier['exported']): string | null {\n if (exported.type === 'Identifier' || exported.type === 'JSXIdentifier') {\n return exported.name\n }\n\n return null\n}\n\nexport function getNamedExportInit(\n j: API['jscodeshift'],\n exportName: string,\n filePath: string,\n visited: Set<string> = new Set(),\n): NamedExportInit | null {\n if (visited.has(filePath)) {\n return null\n }\n\n visited.add(filePath)\n\n const root = parseModule(j, filePath)\n\n if (!root) {\n return null\n }\n\n for (const path of root.find(j.ExportNamedDeclaration).paths()) {\n const {declaration, specifiers, source} = path.node\n const reexportSource = typeof source?.value === 'string' ? source.value : null\n\n if (declaration?.type === 'VariableDeclaration') {\n for (const declarator of declaration.declarations) {\n if (declarator.type !== 'VariableDeclarator') {\n continue\n }\n\n if (\n declarator.id.type === 'Identifier' &&\n declarator.id.name === exportName &&\n declarator.init\n ) {\n return {init: declarator.init, modulePath: filePath}\n }\n }\n }\n\n for (const spec of specifiers ?? []) {\n if (spec.type !== 'ExportSpecifier') {\n continue\n }\n\n const exported = getExportSpecifierName(spec.exported)\n\n if (!exported || exported !== exportName) {\n continue\n }\n\n const local = spec.local?.type === 'Identifier' ? spec.local.name : exported\n\n if (reexportSource) {\n const resolvedPath = resolveRelativeModulePath(filePath, reexportSource)\n\n if (resolvedPath) {\n const followed = getNamedExportInit(j, local, resolvedPath, visited)\n\n if (followed) {\n return followed\n }\n }\n\n continue\n }\n\n const init = findVariableInit(j, root, local)\n\n if (init) {\n return {init, modulePath: filePath}\n }\n }\n }\n\n return null\n}\n","export function getStyledComponentName(node: unknown): string | null {\n if (!node || typeof node !== 'object' || !('type' in node)) {\n return null\n }\n\n const current = node as {\n type: string\n callee?: unknown\n tag?: unknown\n object?: unknown\n arguments?: unknown[]\n }\n\n if (current.type === 'TaggedTemplateExpression') {\n return getStyledComponentName(current.tag)\n }\n\n if (current.type === 'CallExpression') {\n const callee = current.callee\n\n if (\n callee &&\n typeof callee === 'object' &&\n 'type' in callee &&\n callee.type === 'Identifier' &&\n 'name' in callee &&\n callee.name === 'styled'\n ) {\n const arg = current.arguments?.[0]\n\n if (\n arg &&\n typeof arg === 'object' &&\n 'type' in arg &&\n arg.type === 'Identifier' &&\n 'name' in arg\n ) {\n return arg.name as string\n }\n\n return null\n }\n\n return getStyledComponentName(callee)\n }\n\n if (current.type === 'MemberExpression' && current.object) {\n return getStyledComponentName(current.object)\n }\n\n return null\n}\n","import type {API, Collection} from 'jscodeshift'\n\nimport type {BaseOptions} from '../types/BaseOptions'\nimport {getComponentLocalNames} from './getComponentLocalNames'\nimport {getNamedExportInit} from './getNamedExportInit'\nimport {getStyledComponentName} from './getStyledComponentName'\nimport {parseModule} from './parseModule'\nimport {resolveRelativeModulePath} from './resolveRelativeModulePath'\n\nexport function getSameFileStyledComponentAliases(\n j: API['jscodeshift'],\n root: Collection,\n localNames: Iterable<string>,\n): Set<string> {\n const aliases = new Set<string>()\n const names = new Set(localNames)\n\n root.find(j.VariableDeclarator).forEach((path) => {\n const {id, init} = path.node\n\n if (!init || id.type !== 'Identifier') {\n return\n }\n\n const baseComponent = getStyledComponentName(init)\n\n if (baseComponent && names.has(baseComponent)) {\n aliases.add(id.name)\n }\n })\n\n return aliases\n}\n\nexport function getImportedStyledComponentAliases(\n j: API['jscodeshift'],\n root: Collection,\n componentName: string,\n filePath: string | undefined,\n options?: BaseOptions,\n): Set<string> {\n const aliases = new Set<string>()\n\n if (!filePath) {\n return aliases\n }\n\n root.find(j.ImportDeclaration).forEach((path) => {\n const source = path.node.source.value\n\n if (typeof source !== 'string') {\n return\n }\n\n const resolvedPath = resolveRelativeModulePath(filePath, source)\n\n if (!resolvedPath) {\n return\n }\n\n for (const spec of path.node.specifiers ?? []) {\n if (spec.type !== 'ImportSpecifier') {\n continue\n }\n\n if ('importKind' in spec && spec.importKind === 'type') {\n continue\n }\n\n if (spec.imported.type !== 'Identifier') {\n continue\n }\n\n const exportName = spec.imported.name\n const localName = spec.local?.type === 'Identifier' ? spec.local.name : exportName\n const namedExport = getNamedExportInit(j, exportName, resolvedPath)\n\n if (!namedExport) {\n continue\n }\n\n const sourceRoot = parseModule(j, namedExport.modulePath)\n\n if (!sourceRoot) {\n continue\n }\n\n const exportLocalNames = getComponentLocalNames(j, sourceRoot, componentName, options)\n const baseComponent = getStyledComponentName(namedExport.init)\n\n if (baseComponent && exportLocalNames.has(baseComponent)) {\n aliases.add(localName)\n }\n }\n })\n\n return aliases\n}\n\nexport function getStyledComponentAliases(\n j: API['jscodeshift'],\n root: Collection,\n componentName: string,\n filePath: string | undefined,\n localNames: Set<string>,\n options?: BaseOptions,\n): Set<string> {\n const sameFile = getSameFileStyledComponentAliases(j, root, localNames)\n const imported = getImportedStyledComponentAliases(j, root, componentName, filePath, options)\n\n return new Set([...sameFile, ...imported])\n}\n","import type {API, ASTPath, JSXAttribute, JSXOpeningElement, JSXSpreadAttribute} from 'jscodeshift'\n\nimport {insertTodoWarning} from './insertTodoWarning'\n\nconst DEFAULT_WARNING = 'Please double check styled-component migration below'\n\n/**\n * Runs callback on JSX styled-component if `filter` passes. Otherwise, adds\n * a TODO on the component JSX instance when manual review is needed.\n * Returns whether the AST was updated.\n */\nexport function transformStyledComponents(\n j: API['jscodeshift'],\n root: ReturnType<API['jscodeshift']>,\n aliases: Iterable<string>,\n filter: (attrs: (JSXAttribute | JSXSpreadAttribute)[]) => boolean,\n options: {\n callback?: (path: ASTPath<JSXOpeningElement>) => boolean | void\n warning?: string\n } = {},\n): boolean {\n const names = new Set(aliases)\n const {callback, warning = DEFAULT_WARNING} = options\n let hasChanges = false\n\n root.find(j.JSXOpeningElement).forEach((path) => {\n const name = path.node.name\n\n if (name.type !== 'JSXIdentifier' || !names.has(name.name)) {\n return\n }\n\n const attrs = path.node.attributes ?? []\n\n if (!filter(attrs)) {\n if (insertTodoWarning(j, path, warning)) {\n hasChanges = true\n }\n\n return\n }\n\n if (callback?.(path)) {\n hasChanges = true\n }\n })\n\n return hasChanges\n}\n","import {LAYOUT_MODS} from '../../../constants/latest/layout-mods'\nimport type {AttributeMods} from '../../../types/AttributeMods'\n\n/** @internal */\nexport const FLEX_MODS: AttributeMods = {\n ...LAYOUT_MODS,\n align: {\n type: 'rename-only',\n name: 'alignItems',\n },\n direction: {\n type: 'rename-only',\n name: 'flexDirection',\n },\n gridAutoColumns: {\n type: 'style-only',\n style: 'gridAutoColumns',\n },\n gridAutoFlow: {\n type: 'style-only',\n style: 'gridAutoFlow',\n },\n gridAutoRows: {\n type: 'style-only',\n style: 'gridAutoRows',\n },\n gridTemplateColumns: {\n type: 'style-mapped',\n style: 'gridTemplateColumns',\n mapping: {\n 0: '0px',\n 1: 'repeat(1, 1fr)',\n 2: 'repeat(2, 1fr)',\n 3: 'repeat(3, 1fr)',\n 4: 'repeat(4, 1fr)',\n 5: 'repeat(5, 1fr)',\n 6: 'repeat(6, 1fr)',\n 7: 'repeat(7, 1fr)',\n 8: 'repeat(8, 1fr)',\n 9: 'repeat(9, 1fr)',\n 10: 'repeat(10, 1fr)',\n 11: 'repeat(11, 1fr)',\n 12: 'repeat(12, 1fr)',\n },\n },\n gridTemplateRows: {\n type: 'style-mapped',\n style: 'gridTemplateRows',\n mapping: {\n 0: '0px',\n 1: 'repeat(1, 1fr)',\n 2: 'repeat(2, 1fr)',\n 3: 'repeat(3, 1fr)',\n 4: 'repeat(4, 1fr)',\n 5: 'repeat(5, 1fr)',\n 6: 'repeat(6, 1fr)',\n 7: 'repeat(7, 1fr)',\n 8: 'repeat(8, 1fr)',\n 9: 'repeat(9, 1fr)',\n 10: 'repeat(10, 1fr)',\n 11: 'repeat(11, 1fr)',\n 12: 'repeat(12, 1fr)',\n },\n },\n wrap: {\n type: 'rename-only',\n name: 'flexWrap',\n },\n justify: {\n type: 'rename-only',\n name: 'justifyContent',\n },\n}\n"],"names":[],"mappings":"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"}
@@ -1,154 +1,8 @@
1
1
  import "jscodeshift";
2
- import { getComponentLocalNames, insertTodoWarning, transformComponent, shouldTransformComponent, transformImport, transformAttributes, getStaticAttributeExpression } from "../../../_chunks-es/transformComponent.js";
3
- import { readFileSync, existsSync } from "node:fs";
4
- import { resolve, dirname, join } from "node:path";
2
+ import { transformComponent, getComponentLocalNames, shouldTransformComponent, transformImport, transformAttributes, getStaticAttributeExpression } from "../../../_chunks-es/transformComponent.js";
3
+ import { getStyledComponentAliases, FLEX_MODS, transformStyledComponents } from "../../../_chunks-es/flex.mods.js";
5
4
  import { replaceElement, BOX_MODS } from "../../../_chunks-es/box.mods.js";
6
- import { FLEX_MODS } from "../../../_chunks-es/flex.mods.js";
7
5
  import { GRID_MODS } from "../../../_chunks-es/grid.mods.js";
8
- const parseCache = /* @__PURE__ */ new Map();
9
- function parseModule(j, filePath) {
10
- const cached = parseCache.get(filePath);
11
- if (cached)
12
- return cached;
13
- try {
14
- const source = readFileSync(filePath, "utf8"), root = j(source);
15
- return parseCache.set(filePath, root), root;
16
- } catch {
17
- return null;
18
- }
19
- }
20
- const EXTENSIONS = [".tsx", ".ts", ".jsx", ".js"];
21
- function resolveRelativeModulePath(fromFilePath, moduleSpecifier) {
22
- if (!moduleSpecifier.startsWith("."))
23
- return null;
24
- const base = resolve(dirname(fromFilePath), moduleSpecifier);
25
- for (const ext of EXTENSIONS) {
26
- const filePath = `${base}${ext}`;
27
- if (existsSync(filePath))
28
- return filePath;
29
- }
30
- for (const ext of EXTENSIONS) {
31
- const indexPath = join(base, `index${ext}`);
32
- if (existsSync(indexPath))
33
- return indexPath;
34
- }
35
- return existsSync(base) ? base : null;
36
- }
37
- function findVariableInit(j, root, name) {
38
- let init = null;
39
- return root.find(j.VariableDeclarator).forEach((path) => {
40
- const { id } = path.node;
41
- id.type === "Identifier" && id.name === name && path.node.init && (init = path.node.init);
42
- }), init;
43
- }
44
- function getExportSpecifierName(exported) {
45
- return exported.type === "Identifier" || exported.type === "JSXIdentifier" ? exported.name : null;
46
- }
47
- function getNamedExportInit(j, exportName, filePath, visited = /* @__PURE__ */ new Set()) {
48
- if (visited.has(filePath))
49
- return null;
50
- visited.add(filePath);
51
- const root = parseModule(j, filePath);
52
- if (!root)
53
- return null;
54
- for (const path of root.find(j.ExportNamedDeclaration).paths()) {
55
- const { declaration, specifiers, source } = path.node, reexportSource = typeof source?.value == "string" ? source.value : null;
56
- if (declaration?.type === "VariableDeclaration") {
57
- for (const declarator of declaration.declarations)
58
- if (declarator.type === "VariableDeclarator" && declarator.id.type === "Identifier" && declarator.id.name === exportName && declarator.init)
59
- return { init: declarator.init, modulePath: filePath };
60
- }
61
- for (const spec of specifiers ?? []) {
62
- if (spec.type !== "ExportSpecifier")
63
- continue;
64
- const exported = getExportSpecifierName(spec.exported);
65
- if (!exported || exported !== exportName)
66
- continue;
67
- const local = spec.local?.type === "Identifier" ? spec.local.name : exported;
68
- if (reexportSource) {
69
- const resolvedPath = resolveRelativeModulePath(filePath, reexportSource);
70
- if (resolvedPath) {
71
- const followed = getNamedExportInit(j, local, resolvedPath, visited);
72
- if (followed)
73
- return followed;
74
- }
75
- continue;
76
- }
77
- const init = findVariableInit(j, root, local);
78
- if (init)
79
- return { init, modulePath: filePath };
80
- }
81
- }
82
- return null;
83
- }
84
- function getStyledComponentName(node) {
85
- if (!node || typeof node != "object" || !("type" in node))
86
- return null;
87
- const current = node;
88
- if (current.type === "TaggedTemplateExpression")
89
- return getStyledComponentName(current.tag);
90
- if (current.type === "CallExpression") {
91
- const callee = current.callee;
92
- if (callee && typeof callee == "object" && "type" in callee && callee.type === "Identifier" && "name" in callee && callee.name === "styled") {
93
- const arg = current.arguments?.[0];
94
- return arg && typeof arg == "object" && "type" in arg && arg.type === "Identifier" && "name" in arg ? arg.name : null;
95
- }
96
- return getStyledComponentName(callee);
97
- }
98
- return current.type === "MemberExpression" && current.object ? getStyledComponentName(current.object) : null;
99
- }
100
- function getSameFileStyledComponentAliases(j, root, localNames) {
101
- const aliases = /* @__PURE__ */ new Set(), names = new Set(localNames);
102
- return root.find(j.VariableDeclarator).forEach((path) => {
103
- const { id, init } = path.node;
104
- if (!init || id.type !== "Identifier")
105
- return;
106
- const baseComponent = getStyledComponentName(init);
107
- baseComponent && names.has(baseComponent) && aliases.add(id.name);
108
- }), aliases;
109
- }
110
- function getImportedStyledComponentAliases(j, root, componentName, filePath, options) {
111
- const aliases = /* @__PURE__ */ new Set();
112
- return filePath && root.find(j.ImportDeclaration).forEach((path) => {
113
- const source = path.node.source.value;
114
- if (typeof source != "string")
115
- return;
116
- const resolvedPath = resolveRelativeModulePath(filePath, source);
117
- if (resolvedPath)
118
- for (const spec of path.node.specifiers ?? []) {
119
- if (spec.type !== "ImportSpecifier" || "importKind" in spec && spec.importKind === "type" || spec.imported.type !== "Identifier")
120
- continue;
121
- const exportName = spec.imported.name, localName = spec.local?.type === "Identifier" ? spec.local.name : exportName, namedExport = getNamedExportInit(j, exportName, resolvedPath);
122
- if (!namedExport)
123
- continue;
124
- const sourceRoot = parseModule(j, namedExport.modulePath);
125
- if (!sourceRoot)
126
- continue;
127
- const exportLocalNames = getComponentLocalNames(j, sourceRoot, componentName, options), baseComponent = getStyledComponentName(namedExport.init);
128
- baseComponent && exportLocalNames.has(baseComponent) && aliases.add(localName);
129
- }
130
- }), aliases;
131
- }
132
- function getStyledComponentAliases(j, root, componentName, filePath, localNames, options) {
133
- const sameFile = getSameFileStyledComponentAliases(j, root, localNames), imported = getImportedStyledComponentAliases(j, root, componentName, filePath, options);
134
- return /* @__PURE__ */ new Set([...sameFile, ...imported]);
135
- }
136
- const DEFAULT_WARNING = "Please double check styled-component migration below";
137
- function transformStyledComponents(j, root, aliases, filter, options = {}) {
138
- const names = new Set(aliases), { callback, warning = DEFAULT_WARNING } = options;
139
- let hasChanges = !1;
140
- return root.find(j.JSXOpeningElement).forEach((path) => {
141
- const name = path.node.name;
142
- if (name.type !== "JSXIdentifier" || !names.has(name.name))
143
- return;
144
- const attrs = path.node.attributes ?? [];
145
- if (!filter(attrs)) {
146
- insertTodoWarning(j, path, warning) && (hasChanges = !0);
147
- return;
148
- }
149
- callback?.(path) && (hasChanges = !0);
150
- }), hasChanges;
151
- }
152
6
  const BOX_TODO_WARNING = "Please double check the Box migration below", FLEX_TODO_WARNING = "Please double check the Flex migration below", GRID_TODO_WARNING = "Please double check the Grid migration below", STYLED_TODO_WARNING = "Please double check styled(Box) migration below";
153
7
  function transform(fileInfo, api, options) {
154
8
  const { fromPackage, toPackage } = options || {};
@@ -1 +1 @@
1
- {"version":3,"file":"box.js","sources":["../../../../src/utils/parseModule.ts","../../../../src/utils/resolveRelativeModulePath.ts","../../../../src/utils/getNamedExportInit.ts","../../../../src/utils/getStyledComponentName.ts","../../../../src/utils/getStyledComponentAliases.ts","../../../../src/utils/transformStyledComponents.ts","../../../../src/transforms/latest/box/box.ts"],"sourcesContent":["import {readFileSync} from 'node:fs'\n\nimport type {API, Collection} from 'jscodeshift'\n\nconst parseCache = new Map<string, Collection>()\n\nexport function parseModule(j: API['jscodeshift'], filePath: string): Collection | null {\n const cached = parseCache.get(filePath)\n\n if (cached) {\n return cached\n }\n\n try {\n const source = readFileSync(filePath, 'utf8')\n const root = j(source)\n\n parseCache.set(filePath, root)\n\n return root\n } catch {\n return null\n }\n}\n\n/** @internal */\nexport function clearModuleParseCache(): void {\n parseCache.clear()\n}\n","import {existsSync} from 'node:fs'\nimport {dirname, join, resolve} from 'node:path'\n\nconst EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js'] as const\n\nexport function resolveRelativeModulePath(\n fromFilePath: string,\n moduleSpecifier: string,\n): string | null {\n if (!moduleSpecifier.startsWith('.')) {\n return null\n }\n\n const base = resolve(dirname(fromFilePath), moduleSpecifier)\n\n for (const ext of EXTENSIONS) {\n const filePath = `${base}${ext}`\n\n if (existsSync(filePath)) {\n return filePath\n }\n }\n\n for (const ext of EXTENSIONS) {\n const indexPath = join(base, `index${ext}`)\n\n if (existsSync(indexPath)) {\n return indexPath\n }\n }\n\n if (existsSync(base)) {\n return base\n }\n\n return null\n}\n","import type {API, Expression, ExportSpecifier} from 'jscodeshift'\n\nimport {parseModule} from './parseModule'\nimport {resolveRelativeModulePath} from './resolveRelativeModulePath'\n\nexport type NamedExportInit = {\n init: Expression\n modulePath: string\n}\n\nfunction findVariableInit(\n j: API['jscodeshift'],\n root: ReturnType<API['jscodeshift']>,\n name: string,\n): Expression | null {\n let init: Expression | null = null\n\n root.find(j.VariableDeclarator).forEach((path) => {\n const {id} = path.node\n\n if (id.type === 'Identifier' && id.name === name && path.node.init) {\n init = path.node.init\n }\n })\n\n return init\n}\n\nfunction getExportSpecifierName(exported: ExportSpecifier['exported']): string | null {\n if (exported.type === 'Identifier' || exported.type === 'JSXIdentifier') {\n return exported.name\n }\n\n return null\n}\n\nexport function getNamedExportInit(\n j: API['jscodeshift'],\n exportName: string,\n filePath: string,\n visited: Set<string> = new Set(),\n): NamedExportInit | null {\n if (visited.has(filePath)) {\n return null\n }\n\n visited.add(filePath)\n\n const root = parseModule(j, filePath)\n\n if (!root) {\n return null\n }\n\n for (const path of root.find(j.ExportNamedDeclaration).paths()) {\n const {declaration, specifiers, source} = path.node\n const reexportSource = typeof source?.value === 'string' ? source.value : null\n\n if (declaration?.type === 'VariableDeclaration') {\n for (const declarator of declaration.declarations) {\n if (declarator.type !== 'VariableDeclarator') {\n continue\n }\n\n if (\n declarator.id.type === 'Identifier' &&\n declarator.id.name === exportName &&\n declarator.init\n ) {\n return {init: declarator.init, modulePath: filePath}\n }\n }\n }\n\n for (const spec of specifiers ?? []) {\n if (spec.type !== 'ExportSpecifier') {\n continue\n }\n\n const exported = getExportSpecifierName(spec.exported)\n\n if (!exported || exported !== exportName) {\n continue\n }\n\n const local = spec.local?.type === 'Identifier' ? spec.local.name : exported\n\n if (reexportSource) {\n const resolvedPath = resolveRelativeModulePath(filePath, reexportSource)\n\n if (resolvedPath) {\n const followed = getNamedExportInit(j, local, resolvedPath, visited)\n\n if (followed) {\n return followed\n }\n }\n\n continue\n }\n\n const init = findVariableInit(j, root, local)\n\n if (init) {\n return {init, modulePath: filePath}\n }\n }\n }\n\n return null\n}\n","export function getStyledComponentName(node: unknown): string | null {\n if (!node || typeof node !== 'object' || !('type' in node)) {\n return null\n }\n\n const current = node as {\n type: string\n callee?: unknown\n tag?: unknown\n object?: unknown\n arguments?: unknown[]\n }\n\n if (current.type === 'TaggedTemplateExpression') {\n return getStyledComponentName(current.tag)\n }\n\n if (current.type === 'CallExpression') {\n const callee = current.callee\n\n if (\n callee &&\n typeof callee === 'object' &&\n 'type' in callee &&\n callee.type === 'Identifier' &&\n 'name' in callee &&\n callee.name === 'styled'\n ) {\n const arg = current.arguments?.[0]\n\n if (\n arg &&\n typeof arg === 'object' &&\n 'type' in arg &&\n arg.type === 'Identifier' &&\n 'name' in arg\n ) {\n return arg.name as string\n }\n\n return null\n }\n\n return getStyledComponentName(callee)\n }\n\n if (current.type === 'MemberExpression' && current.object) {\n return getStyledComponentName(current.object)\n }\n\n return null\n}\n","import type {API, Collection} from 'jscodeshift'\n\nimport type {BaseOptions} from '../types/BaseOptions'\nimport {getComponentLocalNames} from './getComponentLocalNames'\nimport {getNamedExportInit} from './getNamedExportInit'\nimport {getStyledComponentName} from './getStyledComponentName'\nimport {parseModule} from './parseModule'\nimport {resolveRelativeModulePath} from './resolveRelativeModulePath'\n\nexport function getSameFileStyledComponentAliases(\n j: API['jscodeshift'],\n root: Collection,\n localNames: Iterable<string>,\n): Set<string> {\n const aliases = new Set<string>()\n const names = new Set(localNames)\n\n root.find(j.VariableDeclarator).forEach((path) => {\n const {id, init} = path.node\n\n if (!init || id.type !== 'Identifier') {\n return\n }\n\n const baseComponent = getStyledComponentName(init)\n\n if (baseComponent && names.has(baseComponent)) {\n aliases.add(id.name)\n }\n })\n\n return aliases\n}\n\nexport function getImportedStyledComponentAliases(\n j: API['jscodeshift'],\n root: Collection,\n componentName: string,\n filePath: string | undefined,\n options?: BaseOptions,\n): Set<string> {\n const aliases = new Set<string>()\n\n if (!filePath) {\n return aliases\n }\n\n root.find(j.ImportDeclaration).forEach((path) => {\n const source = path.node.source.value\n\n if (typeof source !== 'string') {\n return\n }\n\n const resolvedPath = resolveRelativeModulePath(filePath, source)\n\n if (!resolvedPath) {\n return\n }\n\n for (const spec of path.node.specifiers ?? []) {\n if (spec.type !== 'ImportSpecifier') {\n continue\n }\n\n if ('importKind' in spec && spec.importKind === 'type') {\n continue\n }\n\n if (spec.imported.type !== 'Identifier') {\n continue\n }\n\n const exportName = spec.imported.name\n const localName = spec.local?.type === 'Identifier' ? spec.local.name : exportName\n const namedExport = getNamedExportInit(j, exportName, resolvedPath)\n\n if (!namedExport) {\n continue\n }\n\n const sourceRoot = parseModule(j, namedExport.modulePath)\n\n if (!sourceRoot) {\n continue\n }\n\n const exportLocalNames = getComponentLocalNames(j, sourceRoot, componentName, options)\n const baseComponent = getStyledComponentName(namedExport.init)\n\n if (baseComponent && exportLocalNames.has(baseComponent)) {\n aliases.add(localName)\n }\n }\n })\n\n return aliases\n}\n\nexport function getStyledComponentAliases(\n j: API['jscodeshift'],\n root: Collection,\n componentName: string,\n filePath: string | undefined,\n localNames: Set<string>,\n options?: BaseOptions,\n): Set<string> {\n const sameFile = getSameFileStyledComponentAliases(j, root, localNames)\n const imported = getImportedStyledComponentAliases(j, root, componentName, filePath, options)\n\n return new Set([...sameFile, ...imported])\n}\n","import type {API, ASTPath, JSXAttribute, JSXOpeningElement, JSXSpreadAttribute} from 'jscodeshift'\n\nimport {insertTodoWarning} from './insertTodoWarning'\n\nconst DEFAULT_WARNING = 'Please double check styled-component migration below'\n\n/**\n * Runs callback on JSX styled-component if `filter` passes. Otherwise, adds\n * a TODO on the component JSX instance when manual review is needed.\n * Returns whether the AST was updated.\n */\nexport function transformStyledComponents(\n j: API['jscodeshift'],\n root: ReturnType<API['jscodeshift']>,\n aliases: Iterable<string>,\n filter: (attrs: (JSXAttribute | JSXSpreadAttribute)[]) => boolean,\n options: {\n callback?: (path: ASTPath<JSXOpeningElement>) => boolean | void\n warning?: string\n } = {},\n): boolean {\n const names = new Set(aliases)\n const {callback, warning = DEFAULT_WARNING} = options\n let hasChanges = false\n\n root.find(j.JSXOpeningElement).forEach((path) => {\n const name = path.node.name\n\n if (name.type !== 'JSXIdentifier' || !names.has(name.name)) {\n return\n }\n\n const attrs = path.node.attributes ?? []\n\n if (!filter(attrs)) {\n if (insertTodoWarning(j, path, warning)) {\n hasChanges = true\n }\n\n return\n }\n\n if (callback?.(path)) {\n hasChanges = true\n }\n })\n\n return hasChanges\n}\n","import {type API, type FileInfo, type JSXSpreadAttribute, type JSXAttribute} from 'jscodeshift'\n\nimport type {BaseOptions} from '../../../types/BaseOptions'\nimport {getComponentLocalNames} from '../../../utils/getComponentLocalNames'\nimport {getStaticAttributeExpression} from '../../../utils/getStaticAttributeExpression'\nimport {getStyledComponentAliases} from '../../../utils/getStyledComponentAliases'\nimport {replaceElement} from '../../../utils/replaceElement'\nimport {shouldTransformComponent} from '../../../utils/shouldTransformComponent'\nimport {transformAttributes} from '../../../utils/transformAttributes'\nimport {transformComponent} from '../../../utils/transformComponent'\nimport {transformImport} from '../../../utils/transformImport'\nimport {transformStyledComponents} from '../../../utils/transformStyledComponents'\nimport {FLEX_MODS} from '../flex/flex.mods'\nimport {GRID_MODS} from '../grid/grid.mods'\nimport {BOX_MODS} from './box.mods'\n\nconst BOX_TODO_WARNING = 'Please double check the Box migration below'\nconst FLEX_TODO_WARNING = 'Please double check the Flex migration below'\nconst GRID_TODO_WARNING = 'Please double check the Grid migration below'\nconst STYLED_TODO_WARNING = 'Please double check styled(Box) migration below'\n\n/** @internal */\nexport default function transform(\n fileInfo: FileInfo,\n api: API,\n options?: BaseOptions,\n): string | undefined {\n const {fromPackage, toPackage} = options || {}\n\n return transformComponent(fileInfo, api, ({j, root, markChanged}) => {\n const localNames = getComponentLocalNames(j, root, 'Box', options)\n const styledAliases = getStyledComponentAliases(\n j,\n root,\n 'Box',\n fileInfo.path,\n localNames,\n options,\n )\n\n if (!shouldTransformComponent(j, root, 'Box', localNames, options, styledAliases)) {\n return\n }\n\n const matchesDisplayValue = (\n attrs: (JSXAttribute | JSXSpreadAttribute)[],\n suffix: string,\n exclude: string[],\n ) => {\n const display = getStaticAttributeExpression(j, attrs, 'display') || []\n const values = Array.isArray(display) ? display : [display]\n let matchesExclude\n\n for (const excluded of exclude) {\n if (values.some((value) => typeof value === 'string' && value.endsWith(excluded))) {\n matchesExclude = true\n break\n }\n }\n\n if (matchesExclude) {\n return false\n }\n\n return values.some((value) => typeof value === 'string' && value.endsWith(suffix))\n }\n\n const replaceWithFlex = (attrs: (JSXAttribute | JSXSpreadAttribute)[]) =>\n matchesDisplayValue(attrs, 'flex', ['block', 'inline', 'grid'])\n\n const replaceWithGrid = (attrs: (JSXAttribute | JSXSpreadAttribute)[]) =>\n matchesDisplayValue(attrs, 'grid', ['block', 'inline', 'flex'])\n\n if (transformImport(j, root, 'Box', fromPackage, toPackage)) {\n markChanged()\n }\n\n if (\n replaceElement(\n j,\n root,\n replaceWithFlex,\n {\n element: 'Box',\n localNames,\n },\n {\n element: 'Flex',\n callback: (path) => transformAttributes(j, path, FLEX_MODS, FLEX_TODO_WARNING),\n },\n )\n ) {\n markChanged()\n }\n\n if (\n replaceElement(\n j,\n root,\n replaceWithGrid,\n {\n element: 'Box',\n localNames,\n callback: (path) => transformAttributes(j, path, BOX_MODS, BOX_TODO_WARNING),\n },\n {\n element: 'Grid',\n callback: (path) => transformAttributes(j, path, GRID_MODS, GRID_TODO_WARNING),\n },\n )\n ) {\n markChanged()\n }\n\n if (\n transformStyledComponents(\n j,\n root,\n styledAliases,\n (attrs) => !replaceWithFlex(attrs) && !replaceWithGrid(attrs),\n {\n warning: STYLED_TODO_WARNING,\n callback: (path) => transformAttributes(j, path, BOX_MODS, BOX_TODO_WARNING),\n },\n )\n ) {\n markChanged()\n }\n })\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"box.js","sources":["../../../../src/transforms/latest/box/box.ts"],"sourcesContent":["import {type API, type FileInfo, type JSXSpreadAttribute, type JSXAttribute} from 'jscodeshift'\n\nimport type {BaseOptions} from '../../../types/BaseOptions'\nimport {getComponentLocalNames} from '../../../utils/getComponentLocalNames'\nimport {getStaticAttributeExpression} from '../../../utils/getStaticAttributeExpression'\nimport {getStyledComponentAliases} from '../../../utils/getStyledComponentAliases'\nimport {replaceElement} from '../../../utils/replaceElement'\nimport {shouldTransformComponent} from '../../../utils/shouldTransformComponent'\nimport {transformAttributes} from '../../../utils/transformAttributes'\nimport {transformComponent} from '../../../utils/transformComponent'\nimport {transformImport} from '../../../utils/transformImport'\nimport {transformStyledComponents} from '../../../utils/transformStyledComponents'\nimport {FLEX_MODS} from '../flex/flex.mods'\nimport {GRID_MODS} from '../grid/grid.mods'\nimport {BOX_MODS} from './box.mods'\n\nconst BOX_TODO_WARNING = 'Please double check the Box migration below'\nconst FLEX_TODO_WARNING = 'Please double check the Flex migration below'\nconst GRID_TODO_WARNING = 'Please double check the Grid migration below'\nconst STYLED_TODO_WARNING = 'Please double check styled(Box) migration below'\n\n/** @internal */\nexport default function transform(\n fileInfo: FileInfo,\n api: API,\n options?: BaseOptions,\n): string | undefined {\n const {fromPackage, toPackage} = options || {}\n\n return transformComponent(fileInfo, api, ({j, root, markChanged}) => {\n const localNames = getComponentLocalNames(j, root, 'Box', options)\n const styledAliases = getStyledComponentAliases(\n j,\n root,\n 'Box',\n fileInfo.path,\n localNames,\n options,\n )\n\n if (!shouldTransformComponent(j, root, 'Box', localNames, options, styledAliases)) {\n return\n }\n\n const matchesDisplayValue = (\n attrs: (JSXAttribute | JSXSpreadAttribute)[],\n suffix: string,\n exclude: string[],\n ) => {\n const display = getStaticAttributeExpression(j, attrs, 'display') || []\n const values = Array.isArray(display) ? display : [display]\n let matchesExclude\n\n for (const excluded of exclude) {\n if (values.some((value) => typeof value === 'string' && value.endsWith(excluded))) {\n matchesExclude = true\n break\n }\n }\n\n if (matchesExclude) {\n return false\n }\n\n return values.some((value) => typeof value === 'string' && value.endsWith(suffix))\n }\n\n const replaceWithFlex = (attrs: (JSXAttribute | JSXSpreadAttribute)[]) =>\n matchesDisplayValue(attrs, 'flex', ['block', 'inline', 'grid'])\n\n const replaceWithGrid = (attrs: (JSXAttribute | JSXSpreadAttribute)[]) =>\n matchesDisplayValue(attrs, 'grid', ['block', 'inline', 'flex'])\n\n if (transformImport(j, root, 'Box', fromPackage, toPackage)) {\n markChanged()\n }\n\n if (\n replaceElement(\n j,\n root,\n replaceWithFlex,\n {\n element: 'Box',\n localNames,\n },\n {\n element: 'Flex',\n callback: (path) => transformAttributes(j, path, FLEX_MODS, FLEX_TODO_WARNING),\n },\n )\n ) {\n markChanged()\n }\n\n if (\n replaceElement(\n j,\n root,\n replaceWithGrid,\n {\n element: 'Box',\n localNames,\n callback: (path) => transformAttributes(j, path, BOX_MODS, BOX_TODO_WARNING),\n },\n {\n element: 'Grid',\n callback: (path) => transformAttributes(j, path, GRID_MODS, GRID_TODO_WARNING),\n },\n )\n ) {\n markChanged()\n }\n\n if (\n transformStyledComponents(\n j,\n root,\n styledAliases,\n (attrs) => !replaceWithFlex(attrs) && !replaceWithGrid(attrs),\n {\n warning: STYLED_TODO_WARNING,\n callback: (path) => transformAttributes(j, path, BOX_MODS, BOX_TODO_WARNING),\n },\n )\n ) {\n markChanged()\n }\n })\n}\n"],"names":[],"mappings":";;;;;AAgBA,MAAM,mBAAmB,+CACnB,oBAAoB,gDACpB,oBAAoB,gDACpB,sBAAsB;AAG5B,SAAwB,UACtB,UACA,KACA,SACoB;AACpB,QAAM,EAAC,aAAa,UAAA,IAAa,WAAW,CAAA;AAE5C,SAAO,mBAAmB,UAAU,KAAK,CAAC,EAAC,GAAG,MAAM,kBAAiB;AACnE,UAAM,aAAa,uBAAuB,GAAG,MAAM,OAAO,OAAO,GAC3D,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IAAA;AAGF,QAAI,CAAC,yBAAyB,GAAG,MAAM,OAAO,YAAY,SAAS,aAAa;AAC9E;AAGF,UAAM,sBAAsB,CAC1B,OACA,QACA,YACG;AACH,YAAM,UAAU,6BAA6B,GAAG,OAAO,SAAS,KAAK,CAAA,GAC/D,SAAS,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;AAC1D,UAAI;AAEJ,iBAAW,YAAY;AACrB,YAAI,OAAO,KAAK,CAAC,UAAU,OAAO,SAAU,YAAY,MAAM,SAAS,QAAQ,CAAC,GAAG;AACjF,2BAAiB;AACjB;AAAA,QACF;AAGF,aAAI,iBACK,KAGF,OAAO,KAAK,CAAC,UAAU,OAAO,SAAU,YAAY,MAAM,SAAS,MAAM,CAAC;AAAA,IACnF,GAEM,kBAAkB,CAAC,UACvB,oBAAoB,OAAO,QAAQ,CAAC,SAAS,UAAU,MAAM,CAAC,GAE1D,kBAAkB,CAAC,UACvB,oBAAoB,OAAO,QAAQ,CAAC,SAAS,UAAU,MAAM,CAAC;AAE5D,oBAAgB,GAAG,MAAM,OAAO,aAAa,SAAS,KACxD,eAIA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE,SAAS;AAAA,QACT;AAAA,MAAA;AAAA,MAEF;AAAA,QACE,SAAS;AAAA,QACT,UAAU,CAAC,SAAS,oBAAoB,GAAG,MAAM,WAAW,iBAAiB;AAAA,MAAA;AAAA,IAC/E,KAGF,eAIA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE,SAAS;AAAA,QACT;AAAA,QACA,UAAU,CAAC,SAAS,oBAAoB,GAAG,MAAM,UAAU,gBAAgB;AAAA,MAAA;AAAA,MAE7E;AAAA,QACE,SAAS;AAAA,QACT,UAAU,CAAC,SAAS,oBAAoB,GAAG,MAAM,WAAW,iBAAiB;AAAA,MAAA;AAAA,IAC/E,KAGF,eAIA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAC,UAAU,CAAC,gBAAgB,KAAK,KAAK,CAAC,gBAAgB,KAAK;AAAA,MAC5D;AAAA,QACE,SAAS;AAAA,QACT,UAAU,CAAC,SAAS,oBAAoB,GAAG,MAAM,UAAU,gBAAgB;AAAA,MAAA;AAAA,IAC7E,KAGF,YAAA;AAAA,EAEJ,CAAC;AACH;"}
@@ -1,16 +1,24 @@
1
1
  import "jscodeshift";
2
2
  import { transformComponent, getComponentLocalNames, shouldTransformComponent, transformImport, transformAttributes } from "../../../_chunks-es/transformComponent.js";
3
- import { FLEX_MODS } from "../../../_chunks-es/flex.mods.js";
3
+ import { getStyledComponentAliases, transformStyledComponents, FLEX_MODS } from "../../../_chunks-es/flex.mods.js";
4
4
  const TODO_WARNING = "Please double check the Flex migration below";
5
5
  function transform(fileInfo, api, options) {
6
6
  const { fromPackage, toPackage } = options || {};
7
7
  return transformComponent(fileInfo, api, ({ j, root, markChanged }) => {
8
- const localNames = getComponentLocalNames(j, root, "Flex", options);
9
- shouldTransformComponent(j, root, "Flex", localNames, options) && (transformImport(j, root, "Flex", fromPackage, toPackage) && markChanged(), root.find(j.JSXOpeningElement, {
10
- name: { type: "JSXIdentifier", name: "Flex" }
11
- }).forEach((path) => {
12
- transformAttributes(j, path, FLEX_MODS, TODO_WARNING) && markChanged();
13
- }));
8
+ const localNames = getComponentLocalNames(j, root, "Flex", options), styledAliases = getStyledComponentAliases(
9
+ j,
10
+ root,
11
+ "Flex",
12
+ fileInfo.path,
13
+ localNames,
14
+ options
15
+ );
16
+ shouldTransformComponent(j, root, "Flex", localNames, options, styledAliases) && (transformImport(j, root, "Flex", fromPackage, toPackage) && markChanged(), root.find(j.JSXOpeningElement).forEach((path) => {
17
+ const name = path.node.name;
18
+ name.type !== "JSXIdentifier" || !localNames.has(name.name) || transformAttributes(j, path, FLEX_MODS, TODO_WARNING) && markChanged();
19
+ }), transformStyledComponents(j, root, styledAliases, () => !0, {
20
+ callback: (path) => transformAttributes(j, path, FLEX_MODS, TODO_WARNING)
21
+ }) && markChanged());
14
22
  });
15
23
  }
16
24
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"flex.js","sources":["../../../../src/transforms/latest/flex/flex.ts"],"sourcesContent":["import {type API, type FileInfo} from 'jscodeshift'\n\nimport type {BaseOptions} from '../../../types/BaseOptions'\nimport {getComponentLocalNames} from '../../../utils/getComponentLocalNames'\nimport {shouldTransformComponent} from '../../../utils/shouldTransformComponent'\nimport {transformAttributes} from '../../../utils/transformAttributes'\nimport {transformComponent} from '../../../utils/transformComponent'\nimport {transformImport} from '../../../utils/transformImport'\nimport {FLEX_MODS} from './flex.mods'\n\nconst TODO_WARNING = 'Please double check the Flex migration below'\n\n/** @internal */\nexport default function transform(\n fileInfo: FileInfo,\n api: API,\n options: BaseOptions,\n): string | undefined {\n const {fromPackage, toPackage} = options || {}\n\n return transformComponent(fileInfo, api, ({j, root, markChanged}) => {\n const localNames = getComponentLocalNames(j, root, 'Flex', options)\n\n if (!shouldTransformComponent(j, root, 'Flex', localNames, options)) {\n return\n }\n\n if (transformImport(j, root, 'Flex', fromPackage, toPackage)) {\n markChanged()\n }\n\n root\n .find(j.JSXOpeningElement, {\n name: {type: 'JSXIdentifier', name: 'Flex'},\n })\n .forEach((path) => {\n if (transformAttributes(j, path, FLEX_MODS, TODO_WARNING)) {\n markChanged()\n }\n })\n })\n}\n"],"names":[],"mappings":";;;AAUA,MAAM,eAAe;AAGrB,SAAwB,UACtB,UACA,KACA,SACoB;AACpB,QAAM,EAAC,aAAa,UAAA,IAAa,WAAW,CAAA;AAE5C,SAAO,mBAAmB,UAAU,KAAK,CAAC,EAAC,GAAG,MAAM,kBAAiB;AACnE,UAAM,aAAa,uBAAuB,GAAG,MAAM,QAAQ,OAAO;AAE7D,6BAAyB,GAAG,MAAM,QAAQ,YAAY,OAAO,MAI9D,gBAAgB,GAAG,MAAM,QAAQ,aAAa,SAAS,KACzD,YAAA,GAGF,KACG,KAAK,EAAE,mBAAmB;AAAA,MACzB,MAAM,EAAC,MAAM,iBAAiB,MAAM,OAAA;AAAA,IAAM,CAC3C,EACA,QAAQ,CAAC,SAAS;AACb,0BAAoB,GAAG,MAAM,WAAW,YAAY,KACtD,YAAA;AAAA,IAEJ,CAAC;AAAA,EACL,CAAC;AACH;"}
1
+ {"version":3,"file":"flex.js","sources":["../../../../src/transforms/latest/flex/flex.ts"],"sourcesContent":["import {type API, type FileInfo} from 'jscodeshift'\n\nimport type {BaseOptions} from '../../../types/BaseOptions'\nimport {getComponentLocalNames} from '../../../utils/getComponentLocalNames'\nimport {getStyledComponentAliases} from '../../../utils/getStyledComponentAliases'\nimport {shouldTransformComponent} from '../../../utils/shouldTransformComponent'\nimport {transformAttributes} from '../../../utils/transformAttributes'\nimport {transformComponent} from '../../../utils/transformComponent'\nimport {transformImport} from '../../../utils/transformImport'\nimport {transformStyledComponents} from '../../../utils/transformStyledComponents'\nimport {FLEX_MODS} from './flex.mods'\n\nconst TODO_WARNING = 'Please double check the Flex migration below'\n\n/** @internal */\nexport default function transform(\n fileInfo: FileInfo,\n api: API,\n options: BaseOptions,\n): string | undefined {\n const {fromPackage, toPackage} = options || {}\n\n return transformComponent(fileInfo, api, ({j, root, markChanged}) => {\n const localNames = getComponentLocalNames(j, root, 'Flex', options)\n const styledAliases = getStyledComponentAliases(\n j,\n root,\n 'Flex',\n fileInfo.path,\n localNames,\n options,\n )\n\n if (!shouldTransformComponent(j, root, 'Flex', localNames, options, styledAliases)) {\n return\n }\n\n if (transformImport(j, root, 'Flex', fromPackage, toPackage)) {\n markChanged()\n }\n\n root.find(j.JSXOpeningElement).forEach((path) => {\n const name = path.node.name\n\n if (name.type !== 'JSXIdentifier' || !localNames.has(name.name)) {\n return\n }\n\n if (transformAttributes(j, path, FLEX_MODS, TODO_WARNING)) {\n markChanged()\n }\n })\n\n if (\n transformStyledComponents(j, root, styledAliases, () => true, {\n callback: (path) => transformAttributes(j, path, FLEX_MODS, TODO_WARNING),\n })\n ) {\n markChanged()\n }\n })\n}\n"],"names":[],"mappings":";;;AAYA,MAAM,eAAe;AAGrB,SAAwB,UACtB,UACA,KACA,SACoB;AACpB,QAAM,EAAC,aAAa,UAAA,IAAa,WAAW,CAAA;AAE5C,SAAO,mBAAmB,UAAU,KAAK,CAAC,EAAC,GAAG,MAAM,kBAAiB;AACnE,UAAM,aAAa,uBAAuB,GAAG,MAAM,QAAQ,OAAO,GAC5D,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IAAA;AAGG,6BAAyB,GAAG,MAAM,QAAQ,YAAY,SAAS,aAAa,MAI7E,gBAAgB,GAAG,MAAM,QAAQ,aAAa,SAAS,KACzD,YAAA,GAGF,KAAK,KAAK,EAAE,iBAAiB,EAAE,QAAQ,CAAC,SAAS;AAC/C,YAAM,OAAO,KAAK,KAAK;AAEnB,WAAK,SAAS,mBAAmB,CAAC,WAAW,IAAI,KAAK,IAAI,KAI1D,oBAAoB,GAAG,MAAM,WAAW,YAAY,KACtD,YAAA;AAAA,IAEJ,CAAC,GAGC,0BAA0B,GAAG,MAAM,eAAe,MAAM,IAAM;AAAA,MAC5D,UAAU,CAAC,SAAS,oBAAoB,GAAG,MAAM,WAAW,YAAY;AAAA,IAAA,CACzE,KAED,YAAA;AAAA,EAEJ,CAAC;AACH;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/ui-codemod",
3
- "version": "1.0.0-alpha.4",
3
+ "version": "1.0.0-alpha.5",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "license": "ISC",
@@ -1,13 +1,6 @@
1
- import {mkdtempSync, readFileSync, rmSync, writeFileSync} from 'node:fs'
2
- import {tmpdir} from 'node:os'
3
- import {join} from 'node:path'
1
+ import {expect} from 'vitest'
4
2
 
5
- import {afterEach, describe, expect, it} from 'vitest'
6
-
7
- const applyTransform = require('jscodeshift/dist/testUtils').applyTransform
8
-
9
- import {clearModuleParseCache} from '../../../utils/parseModule'
10
- import {defineInlineTest} from '../../../utils/testUtils'
3
+ import {defineCrossFileTest, defineInlineTest} from '../../../utils/testUtils'
11
4
  import transform from './box'
12
5
 
13
6
  defineInlineTest(
@@ -246,157 +239,104 @@ defineInlineTest(
246
239
  'warns and does not transform attributes if styled Box should be replaced',
247
240
  )
248
241
 
249
- const tempDirs: string[] = []
250
-
251
- afterEach(() => {
252
- clearModuleParseCache()
253
-
254
- for (const dir of tempDirs.splice(0)) {
255
- rmSync(dir, {recursive: true, force: true})
256
- }
257
- })
258
-
259
- describe('cross-file styled aliases', () => {
260
- it('transforms attributes on imported styled Box wrappers', () => {
261
- const dir = mkdtempSync(join(tmpdir(), 'ui-codemod-box-crossfile-'))
262
-
263
- tempDirs.push(dir)
264
-
265
- writeFileSync(
266
- join(dir, 'Component.styled.tsx'),
267
- `
268
- import {Box} from '@sanity/ui'
269
-
270
- export const RootBox = styled(Box)(({theme}) => ({}))
271
- `,
272
- )
273
-
274
- writeFileSync(
275
- join(dir, 'Component.tsx'),
276
- `
277
- import {RootBox} from './Component.styled'
278
-
279
- export function Component() {
280
- return <RootBox alignItems="center" />
281
- }
282
- `,
283
- )
242
+ defineCrossFileTest(
243
+ transform,
244
+ {},
245
+ `
246
+ import {Box} from '@sanity/ui'
284
247
 
285
- const importerPath = join(dir, 'Component.tsx')
286
- const source = readFileSync(importerPath, 'utf8')
287
- const output = applyTransform(transform, {}, {source, path: importerPath}, {parser: 'tsx'})
248
+ export const RootBox = styled(Box)(({theme}) => ({}))
249
+ `,
250
+ `
251
+ import {RootBox} from './Component.styled'
288
252
 
253
+ export function Component() {
254
+ return <RootBox alignItems="center" />
255
+ }
256
+ `,
257
+ (output) => {
289
258
  expect(output).toContain('alignItems: "center"')
290
259
  expect(output).not.toContain('<RootBox alignItems="center" />')
291
- })
292
-
293
- it('adds todo warning when imported styled Box wrapper should be replaced', () => {
294
- const dir = mkdtempSync(join(tmpdir(), 'ui-codemod-box-crossfile-todo-'))
295
-
296
- tempDirs.push(dir)
297
-
298
- writeFileSync(
299
- join(dir, 'Component.styled.tsx'),
300
- `
301
- import {Box} from '@sanity/ui'
302
-
303
- export const RootBox = styled(Box)(({theme}) => ({}))
304
- `,
305
- )
306
-
307
- writeFileSync(
308
- join(dir, 'Component.tsx'),
309
- `
310
- import {RootBox} from './Component.styled'
260
+ },
261
+ 'transforms attributes on imported styled Box wrappers',
262
+ )
311
263
 
312
- export function Component() {
313
- return <RootBox display="flex" alignItems="center" />
314
- }
315
- `,
316
- )
264
+ defineCrossFileTest(
265
+ transform,
266
+ {},
267
+ `
268
+ import {Box} from '@sanity/ui'
317
269
 
318
- const importerPath = join(dir, 'Component.tsx')
319
- const source = readFileSync(importerPath, 'utf8')
320
- const output = applyTransform(transform, {}, {source, path: importerPath}, {parser: 'tsx'})
270
+ export const RootBox = styled(Box)(({theme}) => ({}))
271
+ `,
272
+ `
273
+ import {RootBox} from './Component.styled'
321
274
 
275
+ export function Component() {
276
+ return <RootBox display="flex" alignItems="center" />
277
+ }
278
+ `,
279
+ (output) => {
322
280
  expect(output).toContain('UI-CODEMOD TODO: Please double check styled(Box) migration below')
323
281
  expect(output).toContain('<RootBox display="flex" alignItems="center" />')
324
282
  expect(output).not.toContain('const RootBox = styled(Box)')
325
- })
326
-
327
- it('does not rewrite unrelated Box from another package', () => {
328
- const dir = mkdtempSync(join(tmpdir(), 'ui-codemod-box-crossfile-unrelated-'))
329
-
330
- tempDirs.push(dir)
331
-
332
- writeFileSync(
333
- join(dir, 'Component.styled.tsx'),
334
- `
335
- import {Box} from '@sanity/ui'
336
-
337
- export const RootBox = styled(Box)(({theme}) => ({}))
338
- `,
339
- )
340
-
341
- writeFileSync(
342
- join(dir, 'Component.tsx'),
343
- `
344
- import {Box} from 'another-package'
345
- import {RootBox} from './Component.styled'
346
-
347
- export function Component() {
348
- return (
349
- <>
350
- <RootBox alignItems="center" />
351
- <Box display="flex" />
352
- </>
353
- )
354
- }
355
- `,
356
- )
357
-
358
- const importerPath = join(dir, 'Component.tsx')
359
- const source = readFileSync(importerPath, 'utf8')
360
- const output = applyTransform(transform, {}, {source, path: importerPath}, {parser: 'tsx'})
283
+ },
284
+ 'adds todo warning when imported styled Box wrapper should be replaced',
285
+ )
361
286
 
287
+ defineCrossFileTest(
288
+ transform,
289
+ {},
290
+ `
291
+ import {Box} from '@sanity/ui'
292
+
293
+ export const RootBox = styled(Box)(({theme}) => ({}))
294
+ `,
295
+ `
296
+ import {Box} from 'another-package'
297
+ import {RootBox} from './Component.styled'
298
+
299
+ export function Component() {
300
+ return (
301
+ <>
302
+ <RootBox alignItems="center" />
303
+ <Box display="flex" />
304
+ </>
305
+ )
306
+ }
307
+ `,
308
+ (output) => {
362
309
  expect(output).toContain('alignItems: "center"')
363
310
  expect(output).not.toContain('<RootBox alignItems="center" />')
364
311
  expect(output).toContain('<Box display="flex" />')
365
312
  expect(output).not.toContain('<Flex')
366
- })
367
-
368
- it('transforms styled Box wrappers imported through barrel re-exports', () => {
369
- const dir = mkdtempSync(join(tmpdir(), 'ui-codemod-box-crossfile-barrel-'))
370
-
371
- tempDirs.push(dir)
372
-
373
- writeFileSync(
374
- join(dir, 'Component.styled.tsx'),
375
- `
376
- import {Box} from '@sanity/ui'
377
-
378
- export const RootBox = styled(Box)(({theme}) => ({}))
379
- `,
380
- )
381
-
382
- writeFileSync(join(dir, 'index.ts'), `export {RootBox} from './Component.styled'`)
383
-
384
- writeFileSync(
385
- join(dir, 'Component.tsx'),
386
- `
387
- import {RootBox} from './index'
313
+ },
314
+ 'does not rewrite unrelated Box from another package',
315
+ )
388
316
 
389
- export function Component() {
390
- return <RootBox alignItems="center" />
391
- }
392
- `,
393
- )
317
+ defineCrossFileTest(
318
+ transform,
319
+ {},
320
+ `
321
+ import {Box} from '@sanity/ui'
394
322
 
395
- const importerPath = join(dir, 'Component.tsx')
396
- const source = readFileSync(importerPath, 'utf8')
397
- const output = applyTransform(transform, {}, {source, path: importerPath}, {parser: 'tsx'})
323
+ export const RootBox = styled(Box)(({theme}) => ({}))
324
+ `,
325
+ `
326
+ import {RootBox} from './index'
398
327
 
328
+ export function Component() {
329
+ return <RootBox alignItems="center" />
330
+ }
331
+ `,
332
+ (output) => {
399
333
  expect(output).toContain('alignItems: "center"')
400
334
  expect(output).not.toContain('<RootBox alignItems="center" />')
401
- })
402
- })
335
+ },
336
+ 'transforms styled Box wrappers imported through barrel re-exports',
337
+ {
338
+ extraFiles: {
339
+ 'index.ts': `export {RootBox} from './Component.styled'`,
340
+ },
341
+ },
342
+ )
@@ -1,4 +1,6 @@
1
- import {defineInlineTest} from '../../../utils/testUtils'
1
+ import {expect} from 'vitest'
2
+
3
+ import {defineCrossFileTest, defineInlineTest} from '../../../utils/testUtils'
2
4
  import transform from './flex'
3
5
 
4
6
  defineInlineTest(
@@ -78,3 +80,78 @@ defineInlineTest(
78
80
  `,
79
81
  'moves grid props to style and updates mapped values',
80
82
  )
83
+
84
+ defineCrossFileTest(
85
+ transform,
86
+ {},
87
+ `
88
+ import {Flex} from '@sanity/ui'
89
+
90
+ export const RootFlex = styled(Flex)(({theme}) => ({}))
91
+ `,
92
+ `
93
+ import {RootFlex} from './Component.styled'
94
+
95
+ export function Component() {
96
+ return <RootFlex align="center" />
97
+ }
98
+ `,
99
+ (output) => {
100
+ expect(output).toContain('<RootFlex alignItems="center" />')
101
+ },
102
+ 'transforms attributes on imported styled Flex wrappers',
103
+ )
104
+
105
+ defineCrossFileTest(
106
+ transform,
107
+ {},
108
+ `
109
+ import {Flex} from '@sanity/ui'
110
+
111
+ export const RootFlex = styled(Flex)(({theme}) => ({}))
112
+ `,
113
+ `
114
+ import {Flex} from 'another-package'
115
+ import {RootFlex} from './Component.styled'
116
+
117
+ export function Component() {
118
+ return (
119
+ <>
120
+ <RootFlex align="center" />
121
+ <Flex direction="column" />
122
+ </>
123
+ )
124
+ }
125
+ `,
126
+ (output) => {
127
+ expect(output).toContain('<RootFlex alignItems="center" />')
128
+ expect(output).toContain('<Flex direction="column" />')
129
+ },
130
+ 'does not transform attributes on unrelated Flex from another package',
131
+ )
132
+
133
+ defineCrossFileTest(
134
+ transform,
135
+ {},
136
+ `
137
+ import {Flex} from '@sanity/ui'
138
+
139
+ export const RootFlex = styled(Flex)(({theme}) => ({}))
140
+ `,
141
+ `
142
+ import {RootFlex} from './index'
143
+
144
+ export function Component() {
145
+ return <RootFlex align="center" />
146
+ }
147
+ `,
148
+ (output) => {
149
+ expect(output).toContain('<RootFlex alignItems="center" />')
150
+ },
151
+ 'transforms styled Flex wrappers imported through barrel re-exports',
152
+ {
153
+ extraFiles: {
154
+ 'index.ts': `export {RootFlex} from './Component.styled'`,
155
+ },
156
+ },
157
+ )
@@ -2,10 +2,12 @@ import {type API, type FileInfo} from 'jscodeshift'
2
2
 
3
3
  import type {BaseOptions} from '../../../types/BaseOptions'
4
4
  import {getComponentLocalNames} from '../../../utils/getComponentLocalNames'
5
+ import {getStyledComponentAliases} from '../../../utils/getStyledComponentAliases'
5
6
  import {shouldTransformComponent} from '../../../utils/shouldTransformComponent'
6
7
  import {transformAttributes} from '../../../utils/transformAttributes'
7
8
  import {transformComponent} from '../../../utils/transformComponent'
8
9
  import {transformImport} from '../../../utils/transformImport'
10
+ import {transformStyledComponents} from '../../../utils/transformStyledComponents'
9
11
  import {FLEX_MODS} from './flex.mods'
10
12
 
11
13
  const TODO_WARNING = 'Please double check the Flex migration below'
@@ -20,8 +22,16 @@ export default function transform(
20
22
 
21
23
  return transformComponent(fileInfo, api, ({j, root, markChanged}) => {
22
24
  const localNames = getComponentLocalNames(j, root, 'Flex', options)
25
+ const styledAliases = getStyledComponentAliases(
26
+ j,
27
+ root,
28
+ 'Flex',
29
+ fileInfo.path,
30
+ localNames,
31
+ options,
32
+ )
23
33
 
24
- if (!shouldTransformComponent(j, root, 'Flex', localNames, options)) {
34
+ if (!shouldTransformComponent(j, root, 'Flex', localNames, options, styledAliases)) {
25
35
  return
26
36
  }
27
37
 
@@ -29,14 +39,24 @@ export default function transform(
29
39
  markChanged()
30
40
  }
31
41
 
32
- root
33
- .find(j.JSXOpeningElement, {
34
- name: {type: 'JSXIdentifier', name: 'Flex'},
35
- })
36
- .forEach((path) => {
37
- if (transformAttributes(j, path, FLEX_MODS, TODO_WARNING)) {
38
- markChanged()
39
- }
42
+ root.find(j.JSXOpeningElement).forEach((path) => {
43
+ const name = path.node.name
44
+
45
+ if (name.type !== 'JSXIdentifier' || !localNames.has(name.name)) {
46
+ return
47
+ }
48
+
49
+ if (transformAttributes(j, path, FLEX_MODS, TODO_WARNING)) {
50
+ markChanged()
51
+ }
52
+ })
53
+
54
+ if (
55
+ transformStyledComponents(j, root, styledAliases, () => true, {
56
+ callback: (path) => transformAttributes(j, path, FLEX_MODS, TODO_WARNING),
40
57
  })
58
+ ) {
59
+ markChanged()
60
+ }
41
61
  })
42
62
  }
@@ -1,6 +1,12 @@
1
+ import {mkdtempSync, readFileSync, rmSync, writeFileSync} from 'node:fs'
2
+ import {tmpdir} from 'node:os'
3
+ import {join} from 'node:path'
4
+
1
5
  import {type FileInfo, type Options, type Transform} from 'jscodeshift'
2
6
  import {expect, it} from 'vitest'
3
7
 
8
+ import {clearModuleParseCache} from './parseModule'
9
+
4
10
  const applyTransform = require('jscodeshift/dist/testUtils').applyTransform
5
11
 
6
12
  export function defineInlineTest(
@@ -52,3 +58,42 @@ function runInlineTest(
52
58
  expectation(output)
53
59
  return output
54
60
  }
61
+
62
+ export function defineCrossFileTest(
63
+ module: Transform,
64
+ options: Options,
65
+ styledInput: string,
66
+ importerInput: string,
67
+ assert: (output: string) => void,
68
+ testName?: string,
69
+ crossFileOptions?: {
70
+ extraFiles?: Record<string, string>
71
+ },
72
+ ) {
73
+ it(testName || 'transforms cross-file styled component correctly', async () => {
74
+ const dir = mkdtempSync(join(tmpdir(), 'ui-codemod-crossfile-'))
75
+
76
+ try {
77
+ writeFileSync(join(dir, 'Component.styled.tsx'), styledInput.trim())
78
+ writeFileSync(join(dir, 'Component.tsx'), importerInput.trim())
79
+
80
+ for (const [filePath, source] of Object.entries(crossFileOptions?.extraFiles ?? {})) {
81
+ writeFileSync(join(dir, filePath), source.trim())
82
+ }
83
+
84
+ const importerPath = join(dir, 'Component.tsx')
85
+ const source = readFileSync(importerPath, 'utf8')
86
+ const output = await applyTransform(
87
+ module,
88
+ options,
89
+ {source, path: importerPath},
90
+ {parser: 'tsx'},
91
+ )
92
+
93
+ assert(typeof output === 'string' ? output : '')
94
+ } finally {
95
+ clearModuleParseCache()
96
+ rmSync(dir, {recursive: true, force: true})
97
+ }
98
+ })
99
+ }