styled-components-to-stylex-codemod 0.0.35 → 0.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +178 -56
- package/dist/{bridge-consumer-patcher-DbMPzKPE.mjs → bridge-consumer-patcher-CKOMofN8.mjs} +2 -2
- package/dist/{logger-fIHHMZYO.mjs → extract-external-interface-BgvS5GC0.mjs} +112 -1
- package/dist/{forwarded-as-consumer-patcher-CXfXrvkk.mjs → forwarded-as-consumer-patcher-CqxniQIc.mjs} +2 -2
- package/dist/index.d.mts +12 -1
- package/dist/index.mjs +171 -34
- package/dist/{merge-markers-Bp-ELxFV.mjs → merge-markers-CJ02ZuW0.mjs} +2 -5
- package/dist/{run-prepass-DUxB6hxo.mjs → run-prepass-5LTAQkG0.mjs} +304 -106
- package/dist/{string-utils-Bq7DbB2x.mjs → string-utils-ChXtospT.mjs} +21 -1
- package/dist/{logger-BoGU2nCP.d.mts → transform-types-CY57kiqK.d.mts} +119 -2
- package/dist/transform.d.mts +1 -83
- package/dist/transform.mjs +586 -128
- package/dist/{transient-prop-consumer-patcher-C5KQ2iFe.mjs → transient-prop-consumer-patcher-CKAzqPfK.mjs} +2 -2
- package/package.json +1 -1
- /package/dist/{path-utils-GG-vEb5-.mjs → path-utils-CMR9NmMm.mjs} +0 -0
- /package/dist/{styled-css-Bu2bjAUW.mjs → styled-css-DVtGPEUe.mjs} +0 -0
package/README.md
CHANGED
|
@@ -4,7 +4,153 @@ Transform styled-components to StyleX.
|
|
|
4
4
|
|
|
5
5
|
**[Try it in the online playground](https://skovhus.github.io/styled-components-to-stylex-codemod/)** — experiment with the transform in your browser.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Migration game plan
|
|
8
|
+
|
|
9
|
+
### 1. Define your theme and mixins as StyleX
|
|
10
|
+
|
|
11
|
+
Before running the codemod, convert your theme object and shared style helpers into StyleX equivalents:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// tokens.stylex.ts — theme variables
|
|
15
|
+
import * as stylex from "@stylexjs/stylex";
|
|
16
|
+
|
|
17
|
+
// Before: { colors: { primary: "#0066cc" }, spacing: { sm: "8px" } }
|
|
18
|
+
export const colors = stylex.defineVars({ primary: "#0066cc" });
|
|
19
|
+
export const spacing = stylex.defineVars({ sm: "8px" });
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
// helpers.stylex.ts — shared mixins
|
|
24
|
+
import * as stylex from "@stylexjs/stylex";
|
|
25
|
+
|
|
26
|
+
// Before: export const truncate = () => `white-space: nowrap; overflow: hidden; ...`
|
|
27
|
+
export const truncate = stylex.create({
|
|
28
|
+
base: { whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" },
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Write an adapter and run the codemod
|
|
33
|
+
|
|
34
|
+
The adapter maps your project's `props.theme.*` access, CSS variables, and helper calls to the StyleX equivalents from step 1. See [Basic usage](#basic-usage) for the full API.
|
|
35
|
+
|
|
36
|
+
### 3. Convert bottom-up (leaf components first)
|
|
37
|
+
|
|
38
|
+
When a component wraps another component that internally uses styled-components (e.g. `styled(GroupHeader)` where `GroupHeader` renders a `StyledHeader`), CSS cascade conflicts can arise after migration. Convert leaf files — the ones that don't wrap other styled-components — first, then work your way up. The codemod will bail with a warning if it detects this pattern.
|
|
39
|
+
|
|
40
|
+
### 4. Verify, iterate, clean up
|
|
41
|
+
|
|
42
|
+
Build and test your project. Review warnings — they tell you which files were skipped and why. Fix adapter gaps, re-run on remaining files, and repeat until done. [Report issues](https://github.com/skovhus/styled-components-to-stylex-codemod/issues) with input/output examples if the codemod produces incorrect results.
|
|
43
|
+
|
|
44
|
+
## Agent prompt for configuring a migration
|
|
45
|
+
|
|
46
|
+
Copy this into an agent working in the repository you want to migrate:
|
|
47
|
+
|
|
48
|
+
````prompt
|
|
49
|
+
You are helping migrate this repository from styled-components to StyleX with
|
|
50
|
+
`styled-components-to-stylex-codemod`.
|
|
51
|
+
|
|
52
|
+
Work in small, reviewable steps:
|
|
53
|
+
|
|
54
|
+
1. Inspect the project before changing files.
|
|
55
|
+
- Identify the package manager and install command.
|
|
56
|
+
- Find styled-components usage, theme access patterns, CSS variables, helper
|
|
57
|
+
functions used inside template interpolations, shared mixins, and existing
|
|
58
|
+
StyleX setup.
|
|
59
|
+
- Identify a leaf component/file glob to migrate first. Prefer components
|
|
60
|
+
that do not wrap other styled-components.
|
|
61
|
+
|
|
62
|
+
2. Install the codemod and any missing StyleX runtime/build dependencies the
|
|
63
|
+
project needs.
|
|
64
|
+
- Use the repository's package manager.
|
|
65
|
+
- Keep dependency changes separate and explain why each package is needed.
|
|
66
|
+
|
|
67
|
+
3. Create a local codemod runner, for example
|
|
68
|
+
`scripts/run-styled-components-to-stylex.mts`, using this shape:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { defineAdapter, runTransform } from "styled-components-to-stylex-codemod";
|
|
72
|
+
|
|
73
|
+
const adapter = defineAdapter({
|
|
74
|
+
resolveValue(ctx) {
|
|
75
|
+
// Map props.theme.*, CSS variables, and imported constants to StyleX
|
|
76
|
+
// variables or other static StyleX-compatible expressions.
|
|
77
|
+
return undefined;
|
|
78
|
+
},
|
|
79
|
+
resolveCall(ctx) {
|
|
80
|
+
// Map helper calls used in styled template interpolations to StyleX
|
|
81
|
+
// mixins/values, or return { preserveRuntimeCall: true } when safe.
|
|
82
|
+
return undefined;
|
|
83
|
+
},
|
|
84
|
+
resolveSelector(ctx) {
|
|
85
|
+
// Map imported selector helpers such as media query or pseudo aliases.
|
|
86
|
+
return undefined;
|
|
87
|
+
},
|
|
88
|
+
externalInterface(ctx) {
|
|
89
|
+
// Return { styles: true, as: true, ref: true } for exported components
|
|
90
|
+
// that must keep accepting className/style, polymorphic `as`, or refs.
|
|
91
|
+
return { styles: false, as: false, ref: false };
|
|
92
|
+
},
|
|
93
|
+
styleMerger: null,
|
|
94
|
+
useSxProp: false,
|
|
95
|
+
wrappedComponentInterface(ctx) {
|
|
96
|
+
return undefined;
|
|
97
|
+
},
|
|
98
|
+
themeHook: {
|
|
99
|
+
functionName: "useTheme",
|
|
100
|
+
importSource: { kind: "specifier", value: "styled-components" },
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
await runTransform({
|
|
105
|
+
files: "src/**/*.tsx",
|
|
106
|
+
consumerPaths: "src/**/*.tsx",
|
|
107
|
+
adapter,
|
|
108
|
+
dryRun: true,
|
|
109
|
+
parser: "tsx",
|
|
110
|
+
formatterCommands: ["pnpm prettier --write"],
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
4. Configure the adapter for this codebase.
|
|
115
|
+
- `resolveValue`: map theme paths (`props.theme.color.primary`), CSS
|
|
116
|
+
variables (`var(--token)`), and imported values to StyleX variables.
|
|
117
|
+
- `resolveCall`: map project style helpers to StyleX mixins or values.
|
|
118
|
+
- `resolveSelector`: map imported media-query or pseudo selector helpers.
|
|
119
|
+
- `externalInterface`: preserve `className`/`style`, `as`, and `ref` support
|
|
120
|
+
for public components. Use `externalInterface: "auto"` only when
|
|
121
|
+
`consumerPaths` covers the consumers and the prepass succeeds.
|
|
122
|
+
- `styleMerger`: provide the project's helper for combining StyleX styles
|
|
123
|
+
with external `className`/`style` when public components need it.
|
|
124
|
+
- `useSxProp` and `wrappedComponentInterface`: enable only if the project
|
|
125
|
+
uses StyleX `sx` props and the Babel plugin is configured for them.
|
|
126
|
+
- `themeHook`: point wrapper theme conditionals at the project's runtime
|
|
127
|
+
theme hook if it is not `useTheme` from styled-components.
|
|
128
|
+
- `resolveBaseComponent`: add this only for base UI primitives that can be
|
|
129
|
+
safely replaced with intrinsic elements and static StyleX styles.
|
|
130
|
+
|
|
131
|
+
5. Run a dry run first.
|
|
132
|
+
- Keep `dryRun: true`.
|
|
133
|
+
- Run the runner against the smallest useful file glob.
|
|
134
|
+
- Read every warning. Update the adapter instead of hand-editing output
|
|
135
|
+
when the warning describes a repeatable project pattern.
|
|
136
|
+
|
|
137
|
+
6. Run the real transform only after the dry run is clean enough to review.
|
|
138
|
+
- Set `dryRun: false`.
|
|
139
|
+
- Keep the migration scoped to the selected leaf files.
|
|
140
|
+
- Run the project's formatter, typecheck, lint, tests, and Storybook or
|
|
141
|
+
visual checks if available.
|
|
142
|
+
- Inspect the diff for dropped declarations, inline-style fallbacks, public
|
|
143
|
+
component API changes, and cross-file selector bridge/marker behavior.
|
|
144
|
+
|
|
145
|
+
7. Iterate bottom-up.
|
|
146
|
+
- Commit the runner/adapter and each migrated slice separately.
|
|
147
|
+
- Expand the `files` glob only after the previous slice is reviewed.
|
|
148
|
+
- Preserve warnings or TODOs for any file that needs manual follow-up.
|
|
149
|
+
````
|
|
150
|
+
|
|
151
|
+
## API and configuration reference
|
|
152
|
+
|
|
153
|
+
### Installation
|
|
8
154
|
|
|
9
155
|
```bash
|
|
10
156
|
npm install styled-components-to-stylex-codemod
|
|
@@ -12,7 +158,7 @@ npm install styled-components-to-stylex-codemod
|
|
|
12
158
|
pnpm add styled-components-to-stylex-codemod
|
|
13
159
|
```
|
|
14
160
|
|
|
15
|
-
|
|
161
|
+
### Basic usage
|
|
16
162
|
|
|
17
163
|
Use `runTransform` to transform files matching a glob pattern:
|
|
18
164
|
|
|
@@ -22,15 +168,19 @@ import { runTransform, defineAdapter } from "styled-components-to-stylex-codemod
|
|
|
22
168
|
const adapter = defineAdapter({
|
|
23
169
|
// Map theme paths and CSS variables to StyleX expressions
|
|
24
170
|
resolveValue(ctx) {
|
|
25
|
-
return
|
|
171
|
+
return undefined;
|
|
26
172
|
},
|
|
27
173
|
// Map helper function calls to StyleX expressions
|
|
28
174
|
resolveCall(ctx) {
|
|
29
|
-
return
|
|
175
|
+
return undefined;
|
|
176
|
+
},
|
|
177
|
+
// Map imported selector helpers such as media query or pseudo aliases
|
|
178
|
+
resolveSelector(ctx) {
|
|
179
|
+
return undefined;
|
|
30
180
|
},
|
|
31
|
-
// Control which components accept external className/style
|
|
181
|
+
// Control which components accept external className/style, polymorphic `as`, and refs
|
|
32
182
|
externalInterface(ctx) {
|
|
33
|
-
return {
|
|
183
|
+
return { styles: false, as: false, ref: false };
|
|
34
184
|
},
|
|
35
185
|
// Optional: use a helper for merging StyleX styles with external className/style
|
|
36
186
|
styleMerger: null,
|
|
@@ -71,7 +221,7 @@ const adapter = defineAdapter({
|
|
|
71
221
|
/**
|
|
72
222
|
* Resolve dynamic values in styled template literals to StyleX expressions.
|
|
73
223
|
* Called for theme access (`props.theme.x`), CSS variables (`var(--x)`),
|
|
74
|
-
* and imported values. Return `{ expr, imports }` or `
|
|
224
|
+
* and imported values. Return `{ expr, imports }` or `undefined` to skip.
|
|
75
225
|
*/
|
|
76
226
|
resolveValue(ctx) {
|
|
77
227
|
if (ctx.kind === "theme") {
|
|
@@ -102,19 +252,19 @@ const adapter = defineAdapter({
|
|
|
102
252
|
};
|
|
103
253
|
}
|
|
104
254
|
|
|
105
|
-
return
|
|
255
|
+
return undefined;
|
|
106
256
|
},
|
|
107
257
|
|
|
108
258
|
/**
|
|
109
259
|
* Resolve helper function calls in template interpolations.
|
|
110
260
|
* e.g. `${transitionSpeed("slow")}` → `transitionSpeedVars.slow`
|
|
111
|
-
* Return `{ expr, imports }` or `
|
|
261
|
+
* Return `{ expr, imports }` or `undefined` to bail the file with a warning.
|
|
112
262
|
*/
|
|
113
263
|
resolveCall(ctx) {
|
|
114
264
|
const arg0 = ctx.args[0];
|
|
115
265
|
const key = arg0?.kind === "literal" && typeof arg0.value === "string" ? arg0.value : null;
|
|
116
266
|
if (ctx.calleeImportedName !== "transitionSpeed" || !key) {
|
|
117
|
-
return
|
|
267
|
+
return undefined;
|
|
118
268
|
}
|
|
119
269
|
|
|
120
270
|
return {
|
|
@@ -128,6 +278,14 @@ const adapter = defineAdapter({
|
|
|
128
278
|
};
|
|
129
279
|
},
|
|
130
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Resolve imported values used in selector position, such as media query
|
|
283
|
+
* helpers or pseudo-class aliases. Return `undefined` to bail the file.
|
|
284
|
+
*/
|
|
285
|
+
resolveSelector(ctx) {
|
|
286
|
+
return undefined;
|
|
287
|
+
},
|
|
288
|
+
|
|
131
289
|
/**
|
|
132
290
|
* Optional: inline styled(ImportedComponent) into an intrinsic element.
|
|
133
291
|
* When the base component can be resolved statically, return the target
|
|
@@ -153,14 +311,14 @@ const adapter = defineAdapter({
|
|
|
153
311
|
},
|
|
154
312
|
|
|
155
313
|
/**
|
|
156
|
-
* Control which exported components accept external className/style
|
|
157
|
-
*
|
|
314
|
+
* Control which exported components accept external className/style,
|
|
315
|
+
* polymorphic `as`, and/or refs. Return `{ styles, as, ref }` flags.
|
|
158
316
|
*/
|
|
159
317
|
externalInterface(ctx) {
|
|
160
318
|
if (ctx.filePath.includes("/shared/components/")) {
|
|
161
|
-
return { styles: true, as: true };
|
|
319
|
+
return { styles: true, as: true, ref: true };
|
|
162
320
|
}
|
|
163
|
-
return { styles: false, as: false };
|
|
321
|
+
return { styles: false, as: false, ref: false };
|
|
164
322
|
},
|
|
165
323
|
|
|
166
324
|
/**
|
|
@@ -228,8 +386,9 @@ Adapters are the main extension point, see full example above. They let you cont
|
|
|
228
386
|
|
|
229
387
|
- how theme paths, CSS variables, and imported values are turned into StyleX-compatible JS values (`resolveValue`)
|
|
230
388
|
- what extra imports to inject into transformed files (returned from `resolveValue`)
|
|
231
|
-
- how helper calls are resolved (via `resolveCall({ ... })` returning `{ expr, imports }`, or `{ preserveRuntimeCall: true }` to keep only the original helper runtime call; `
|
|
232
|
-
-
|
|
389
|
+
- how helper calls are resolved (via `resolveCall({ ... })` returning `{ expr, imports }`, or `{ preserveRuntimeCall: true }` to keep only the original helper runtime call; `undefined` bails the file)
|
|
390
|
+
- how imported media-query or pseudo selector helpers are resolved (`resolveSelector`)
|
|
391
|
+
- which exported components should support external className/style extension, polymorphic `as`, and/or refs (`externalInterface`)
|
|
233
392
|
- how className/style merging is handled for components accepting external styling (`styleMerger`)
|
|
234
393
|
- which imported components already accept a StyleX `sx` prop (auto-detected from the imported component's prop type when `useSxProp: true`; can be overridden via `wrappedComponentInterface`). When detected, the codemod emits `sx={styles.x}` on the wrapped component instead of `{...stylex.props(styles.x)}`.
|
|
235
394
|
- which runtime theme hook import/call to use for emitted wrapper theme conditionals (`themeHook`)
|
|
@@ -254,7 +413,7 @@ await runTransform({
|
|
|
254
413
|
|
|
255
414
|
#### Auto-detecting external interface usage (experimental)
|
|
256
415
|
|
|
257
|
-
Instead of manually specifying which components need `styles` or `
|
|
416
|
+
Instead of manually specifying which components need `styles`, `as`, or `ref` support, set `externalInterface: "auto"` to auto-detect usage by scanning consumer code.
|
|
258
417
|
|
|
259
418
|
> [!NOTE]
|
|
260
419
|
> Experimental. Requires `consumerPaths` and a successful prepass scan.
|
|
@@ -275,7 +434,7 @@ await runTransform({
|
|
|
275
434
|
});
|
|
276
435
|
```
|
|
277
436
|
|
|
278
|
-
When `externalInterface: "auto"` is set, `runTransform()` scans `files` and `consumerPaths` for `styled(Component)` calls
|
|
437
|
+
When `externalInterface: "auto"` is set, `runTransform()` scans `files` and `consumerPaths` for `styled(Component)` calls plus JSX usage such as `<Component as={...}>`, `ref`, `className`, and `style`, resolves imports back to the component definition files, and returns the appropriate `{ styles, as, ref }` flags automatically.
|
|
279
438
|
|
|
280
439
|
If that prepass scan fails, `runTransform()` stops and throws an actionable error rather than silently falling back to non-auto behavior.
|
|
281
440
|
|
|
@@ -344,7 +503,7 @@ When the codemod encounters an interpolation inside a styled template literal, i
|
|
|
344
503
|
- Use the optional `usage: "create" | "props"` field to override the default inference
|
|
345
504
|
- Use `preserveRuntimeCall: true` to keep the original helper call as a runtime style-function
|
|
346
505
|
override (with or without a static fallback from `expr`)
|
|
347
|
-
- if `resolveCall` returns `
|
|
506
|
+
- if `resolveCall` returns `undefined`, the transform **bails the file** and logs a warning
|
|
348
507
|
- helper calls applied to prop values (e.g. `shadow(props.shadow)`) by emitting a StyleX style function that calls the helper at runtime
|
|
349
508
|
- conditional CSS blocks via ternary (e.g. `props.$dim ? "opacity: 0.5;" : ""`)
|
|
350
509
|
|
|
@@ -359,43 +518,6 @@ If the pipeline can't resolve an interpolation:
|
|
|
359
518
|
- **createGlobalStyle**: detected usage is reported as an **unsupported-feature** warning (StyleX does not support global styles in the same way).
|
|
360
519
|
- **Theme prop overrides**: passing a `theme` prop directly to styled components (e.g. `<Button theme={...} />`) is not supported and will bail with a warning.
|
|
361
520
|
|
|
362
|
-
## Migration game plan
|
|
363
|
-
|
|
364
|
-
### 1. Define your theme and mixins as StyleX
|
|
365
|
-
|
|
366
|
-
Before running the codemod, convert your theme object and shared style helpers into StyleX equivalents:
|
|
367
|
-
|
|
368
|
-
```ts
|
|
369
|
-
// tokens.stylex.ts — theme variables
|
|
370
|
-
import * as stylex from "@stylexjs/stylex";
|
|
371
|
-
|
|
372
|
-
// Before: { colors: { primary: "#0066cc" }, spacing: { sm: "8px" } }
|
|
373
|
-
export const colors = stylex.defineVars({ primary: "#0066cc" });
|
|
374
|
-
export const spacing = stylex.defineVars({ sm: "8px" });
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
```ts
|
|
378
|
-
// helpers.stylex.ts — shared mixins
|
|
379
|
-
import * as stylex from "@stylexjs/stylex";
|
|
380
|
-
|
|
381
|
-
// Before: export const truncate = () => `white-space: nowrap; overflow: hidden; ...`
|
|
382
|
-
export const truncate = stylex.create({
|
|
383
|
-
base: { whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" },
|
|
384
|
-
});
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
### 2. Write an adapter and run the codemod
|
|
388
|
-
|
|
389
|
-
The adapter maps your project's `props.theme.*` access, CSS variables, and helper calls to the StyleX equivalents from step 1. See [Usage](#usage) for the full API.
|
|
390
|
-
|
|
391
|
-
### 3. Convert bottom-up (leaf components first)
|
|
392
|
-
|
|
393
|
-
When a component wraps another component that internally uses styled-components (e.g. `styled(GroupHeader)` where `GroupHeader` renders a `StyledHeader`), CSS cascade conflicts can arise after migration. Convert leaf files — the ones that don't wrap other styled-components — first, then work your way up. The codemod will bail with a warning if it detects this pattern.
|
|
394
|
-
|
|
395
|
-
### 4. Verify, iterate, clean up
|
|
396
|
-
|
|
397
|
-
Build and test your project. Review warnings — they tell you which files were skipped and why. Fix adapter gaps, re-run on remaining files, and repeat until done. [Report issues](https://github.com/skovhus/styled-components-to-stylex-codemod/issues) with input/output examples if the codemod produces incorrect results.
|
|
398
|
-
|
|
399
521
|
## License
|
|
400
522
|
|
|
401
523
|
MIT
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { n as toRealPath } from "./path-utils-CMR9NmMm.mjs";
|
|
2
|
+
import { r as escapeRegex } from "./string-utils-ChXtospT.mjs";
|
|
3
3
|
import { t as isSelectorContext } from "./selector-context-heuristic-DE3JAmpc.mjs";
|
|
4
4
|
import { readFileSync } from "node:fs";
|
|
5
5
|
//#region src/internal/bridge-consumer-patcher.ts
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import path from "node:path";
|
|
1
2
|
import { readFileSync } from "node:fs";
|
|
2
3
|
//#region src/internal/logger.ts
|
|
3
4
|
/**
|
|
@@ -236,4 +237,114 @@ const INFO_TEXT_COLOR = "\x1B[37m";
|
|
|
236
237
|
const SECTION_COLOR = "\x1B[36m";
|
|
237
238
|
const RESET_COLOR = "\x1B[0m";
|
|
238
239
|
//#endregion
|
|
239
|
-
|
|
240
|
+
//#region src/internal/prepass/extract-external-interface.ts
|
|
241
|
+
function findImportSource(src, localName) {
|
|
242
|
+
const [aliasRe, namedRe, defaultRe] = getImportSourceRes(localName);
|
|
243
|
+
const aliasMatch = src.match(aliasRe);
|
|
244
|
+
if (aliasMatch?.[1] && aliasMatch[2]) {
|
|
245
|
+
if (aliasMatch[1] === "default") return {
|
|
246
|
+
source: aliasMatch[2],
|
|
247
|
+
exportedName: localName,
|
|
248
|
+
isDefault: true
|
|
249
|
+
};
|
|
250
|
+
return {
|
|
251
|
+
source: aliasMatch[2],
|
|
252
|
+
exportedName: aliasMatch[1],
|
|
253
|
+
isDefault: false
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
const namedMatch = src.match(namedRe);
|
|
257
|
+
if (namedMatch?.[1]) return {
|
|
258
|
+
source: namedMatch[1],
|
|
259
|
+
exportedName: localName,
|
|
260
|
+
isDefault: false
|
|
261
|
+
};
|
|
262
|
+
const defaultMatch = src.match(defaultRe);
|
|
263
|
+
if (defaultMatch?.[1]) return {
|
|
264
|
+
source: defaultMatch[1],
|
|
265
|
+
exportedName: localName,
|
|
266
|
+
isDefault: true
|
|
267
|
+
};
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
const importSourceReCache = /* @__PURE__ */ new Map();
|
|
271
|
+
function getImportSourceRes(localName) {
|
|
272
|
+
let cached = importSourceReCache.get(localName);
|
|
273
|
+
if (!cached) {
|
|
274
|
+
cached = [
|
|
275
|
+
new RegExp(String.raw`import\s+\{[^}]*\b(\w+)\s+as\s+${localName}\b[^}]*\}\s+from\s+["']([^"']+)["']`),
|
|
276
|
+
new RegExp(String.raw`import\s+\{[^}]*\b${localName}\b[^}]*\}\s+from\s+["']([^"']+)["']`),
|
|
277
|
+
new RegExp(String.raw`import\s+${localName}(?:\s*,\s*\{[^}]*\})?\s+from\s+["']([^"']+)["']`)
|
|
278
|
+
];
|
|
279
|
+
importSourceReCache.set(localName, cached);
|
|
280
|
+
}
|
|
281
|
+
return cached;
|
|
282
|
+
}
|
|
283
|
+
function resolveBarrelReExport(filePath, name, resolve, read) {
|
|
284
|
+
const basename = path.basename(filePath);
|
|
285
|
+
if (basename !== "index.ts" && basename !== "index.tsx") return null;
|
|
286
|
+
let src;
|
|
287
|
+
try {
|
|
288
|
+
src = read(filePath);
|
|
289
|
+
} catch {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
const namedMatch = src.match(getBarrelExportRe(name));
|
|
293
|
+
if (namedMatch?.[1]) return resolve(namedMatch[1], filePath);
|
|
294
|
+
for (const match of src.matchAll(/export\s*\*\s*from\s*["']([^"']+)["']/g)) {
|
|
295
|
+
const specifier = match[1];
|
|
296
|
+
if (!specifier) continue;
|
|
297
|
+
const resolved = resolve(specifier, filePath);
|
|
298
|
+
if (resolved) try {
|
|
299
|
+
if (fileExports(read(resolved), name)) return resolved;
|
|
300
|
+
} catch {}
|
|
301
|
+
}
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
function fileExports(src, name) {
|
|
305
|
+
return getFileExportsRe(name).test(src);
|
|
306
|
+
}
|
|
307
|
+
const fileExportsReCache = /* @__PURE__ */ new Map();
|
|
308
|
+
function getFileExportsRe(name) {
|
|
309
|
+
let re = fileExportsReCache.get(name);
|
|
310
|
+
if (!re) {
|
|
311
|
+
re = new RegExp(String.raw`export\s+(?:(?:const|function|class|let|var)\s+${name}\b|default\s+${name}\b)` + String.raw`|export\s*\{[^}]*\b${name}\b[^}]*\}`);
|
|
312
|
+
fileExportsReCache.set(name, re);
|
|
313
|
+
}
|
|
314
|
+
return re;
|
|
315
|
+
}
|
|
316
|
+
const barrelExportReCache = /* @__PURE__ */ new Map();
|
|
317
|
+
function getBarrelExportRe(name) {
|
|
318
|
+
let re = barrelExportReCache.get(name);
|
|
319
|
+
if (!re) {
|
|
320
|
+
re = new RegExp(String.raw`export\s*\{[^}]*\b${name}\b[^}]*\}\s*from\s*["']([^"']+)["']`);
|
|
321
|
+
barrelExportReCache.set(name, re);
|
|
322
|
+
}
|
|
323
|
+
return re;
|
|
324
|
+
}
|
|
325
|
+
function fileImportsFrom(usageSrc, usageFile, name, defFile, resolve) {
|
|
326
|
+
const [namedRe, defaultRe] = getFileImportsFromRes(name);
|
|
327
|
+
namedRe.lastIndex = 0;
|
|
328
|
+
defaultRe.lastIndex = 0;
|
|
329
|
+
const stem = path.parse(defFile).name;
|
|
330
|
+
const parent = path.basename(path.dirname(defFile));
|
|
331
|
+
for (const re of [namedRe, defaultRe]) for (const match of usageSrc.matchAll(re)) {
|
|
332
|
+
const specifier = match[1];
|
|
333
|
+
if (!specifier) continue;
|
|
334
|
+
const resolved = resolve(specifier, usageFile);
|
|
335
|
+
if (resolved && path.resolve(resolved) === path.resolve(defFile)) return true;
|
|
336
|
+
if (specifier.endsWith(stem) || specifier.endsWith(`${parent}/${stem}`) || specifier.endsWith(parent)) return true;
|
|
337
|
+
}
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
const fileImportsFromReCache = /* @__PURE__ */ new Map();
|
|
341
|
+
function getFileImportsFromRes(name) {
|
|
342
|
+
let cached = fileImportsFromReCache.get(name);
|
|
343
|
+
if (!cached) {
|
|
344
|
+
cached = [new RegExp(String.raw`import\s+\{[^}]*\b${name}\b[^}]*\}\s+from\s+["']([^"']+)["']`, "g"), new RegExp(String.raw`import\s+${name}(?:\s*,\s*\{[^}]*\})?\s+from\s+["']([^"']+)["']`, "g")];
|
|
345
|
+
fileImportsFromReCache.set(name, cached);
|
|
346
|
+
}
|
|
347
|
+
return cached;
|
|
348
|
+
}
|
|
349
|
+
//#endregion
|
|
350
|
+
export { Logger as a, resolveBarrelReExport as i, fileImportsFrom as n, findImportSource as r, fileExports as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { n as toRealPath } from "./path-utils-CMR9NmMm.mjs";
|
|
2
|
+
import { r as escapeRegex } from "./string-utils-ChXtospT.mjs";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
//#region src/internal/forwarded-as-consumer-patcher.ts
|
|
5
5
|
/**
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as CollectedWarning, c as MarkerFileContext, l as defineAdapter, n as TransformMode, o as AdapterInput, s as ImportSource } from "./transform-types-CY57kiqK.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/run.d.ts
|
|
4
4
|
interface RunTransformOptions {
|
|
@@ -64,6 +64,17 @@ interface RunTransformOptions {
|
|
|
64
64
|
* @default false
|
|
65
65
|
*/
|
|
66
66
|
silent?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Controls which styled declarations are eligible for conversion.
|
|
69
|
+
*
|
|
70
|
+
* - `"all"` converts every supported styled declaration.
|
|
71
|
+
* - `"leavesOnly"` only converts declarations whose render base is intrinsic
|
|
72
|
+
* after adapter resolution, or that wrap another leaf styled declaration in
|
|
73
|
+
* the transform run (including cross-file imports).
|
|
74
|
+
*
|
|
75
|
+
* @default "all"
|
|
76
|
+
*/
|
|
77
|
+
transformMode?: TransformMode;
|
|
67
78
|
/**
|
|
68
79
|
* When true, allow the codemod to leave individual styled declarations as-is when
|
|
69
80
|
* they hit an unsupported pattern while transforming the rest of the file. This
|