styled-components-to-stylex-codemod 0.0.3 → 0.0.6
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 +3 -1
- package/dist/index.d.mts +1 -6
- package/dist/index.mjs +11 -12
- package/dist/{transform-types-t2Vk9Bka.d.mts → logger-BS4Evg0n.d.mts} +8 -26
- package/dist/{logger-Dhb8r1Ry.mjs → logger-Dlnt1fYP.mjs} +75 -35
- package/dist/transform.d.mts +23 -3
- package/dist/transform.mjs +451 -117
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -230,10 +230,12 @@ When the codemod encounters an interpolation inside a styled template literal, i
|
|
|
230
230
|
- theme access (`props.theme...`) via `resolveValue({ kind: "theme", path })`
|
|
231
231
|
- prop access (`props.foo`) and conditionals (`props.foo ? "a" : "b"`, `props.foo && "color: red;"`)
|
|
232
232
|
- simple helper calls (`transitionSpeed("slowTransition")`) via `resolveValue({ kind: "call", calleeImportedName, calleeSource, args, ... })`
|
|
233
|
+
- helper calls applied to prop values (e.g. `shadow(props.shadow)`) by emitting a StyleX style function that calls the helper at runtime
|
|
234
|
+
- conditional CSS blocks via ternary (e.g. `props.$dim ? "opacity: 0.5;" : ""`)
|
|
233
235
|
|
|
234
236
|
If the pipeline can’t resolve an interpolation:
|
|
235
237
|
|
|
236
|
-
- for
|
|
238
|
+
- for some dynamic value cases, the transform preserves the value as a wrapper inline style so output keeps visual parity (at the cost of using `style={...}` for that prop)
|
|
237
239
|
- otherwise, the declaration containing that interpolation is **dropped** and a warning is produced (manual follow-up required)
|
|
238
240
|
|
|
239
241
|
### Limitations
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as defineAdapter, r as Adapter, t as CollectedWarning } from "./logger-BS4Evg0n.mjs";
|
|
2
2
|
|
|
3
|
-
//#region src/internal/logger.d.ts
|
|
4
|
-
interface CollectedWarning extends TransformWarning {
|
|
5
|
-
filePath: string;
|
|
6
|
-
}
|
|
7
|
-
//#endregion
|
|
8
3
|
//#region src/run.d.ts
|
|
9
4
|
interface RunTransformOptions {
|
|
10
5
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as assertValidAdapter, r as describeValue, t as Logger } from "./logger-Dlnt1fYP.mjs";
|
|
2
2
|
import { run } from "jscodeshift/src/Runner.js";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
@@ -69,7 +69,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
69
69
|
*/
|
|
70
70
|
async function runTransform(options) {
|
|
71
71
|
if (!options || typeof options !== "object") throw new Error([
|
|
72
|
-
"
|
|
72
|
+
"runTransform(options) was called with an invalid argument.",
|
|
73
73
|
"Expected: runTransform({ files: string | string[], adapter: Adapter, ... })",
|
|
74
74
|
`Received: ${describeValue(options)}`,
|
|
75
75
|
"",
|
|
@@ -80,14 +80,14 @@ async function runTransform(options) {
|
|
|
80
80
|
].join("\n"));
|
|
81
81
|
const filesValue = options.files;
|
|
82
82
|
if (typeof filesValue !== "string" && !Array.isArray(filesValue)) throw new Error([
|
|
83
|
-
"
|
|
83
|
+
"runTransform(options): `files` is required.",
|
|
84
84
|
"Expected: files: string | string[]",
|
|
85
85
|
`Received: files=${describeValue(filesValue)}`
|
|
86
86
|
].join("\n"));
|
|
87
|
-
if (typeof filesValue === "string" && filesValue.trim() === "") throw new Error(["
|
|
87
|
+
if (typeof filesValue === "string" && filesValue.trim() === "") throw new Error(["runTransform(options): `files` must be a non-empty string.", "Example: files: \"src/**/*.tsx\""].join("\n"));
|
|
88
88
|
if (Array.isArray(filesValue)) {
|
|
89
|
-
if (filesValue.length === 0) throw new Error(["
|
|
90
|
-
if (filesValue.find((p) => typeof p !== "string" || p.trim() === "") !== void 0) throw new Error(["
|
|
89
|
+
if (filesValue.length === 0) throw new Error(["runTransform(options): `files` must not be an empty array.", "Example: files: [\"src/**/*.ts\", \"src/**/*.tsx\"]"].join("\n"));
|
|
90
|
+
if (filesValue.find((p) => typeof p !== "string" || p.trim() === "") !== void 0) throw new Error(["runTransform(options): `files` array must contain non-empty strings.", `Received: files=${describeValue(filesValue)}`].join("\n"));
|
|
91
91
|
}
|
|
92
92
|
const { files, dryRun = false, print = false, parser = "tsx", formatterCommand } = options;
|
|
93
93
|
const adapter = options.adapter;
|
|
@@ -101,9 +101,8 @@ async function runTransform(options) {
|
|
|
101
101
|
try {
|
|
102
102
|
return adapter.resolveValue(ctx);
|
|
103
103
|
} catch (e) {
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
logWarning(`[styled-components-to-stylex] adapter.resolveValue threw${kind ? ` (kind=${kind}${details ? ` ${details}` : ""})` : ""}: ${e?.stack ?? String(e)}\n`);
|
|
104
|
+
const msg = `adapter.resolveValue threw an error: ${e instanceof Error ? e.message : String(e)}`;
|
|
105
|
+
Logger.error(msg, ctx);
|
|
107
106
|
throw e;
|
|
108
107
|
}
|
|
109
108
|
}
|
|
@@ -113,7 +112,7 @@ async function runTransform(options) {
|
|
|
113
112
|
const cwd = process.cwd();
|
|
114
113
|
for (const pattern of patterns) for await (const file of glob(pattern, { cwd })) filePaths.push(file);
|
|
115
114
|
if (filePaths.length === 0) {
|
|
116
|
-
|
|
115
|
+
Logger.warn("No files matched the provided glob pattern(s)");
|
|
117
116
|
return {
|
|
118
117
|
errors: 0,
|
|
119
118
|
unchanged: 0,
|
|
@@ -156,7 +155,7 @@ async function runTransform(options) {
|
|
|
156
155
|
proc.on("error", reject);
|
|
157
156
|
});
|
|
158
157
|
} catch (e) {
|
|
159
|
-
|
|
158
|
+
Logger.warn(`Formatter command failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
160
159
|
}
|
|
161
160
|
}
|
|
162
161
|
return {
|
|
@@ -165,7 +164,7 @@ async function runTransform(options) {
|
|
|
165
164
|
skipped: result.skip,
|
|
166
165
|
transformed: result.ok,
|
|
167
166
|
timeElapsed: parseFloat(result.timeElapsed) || 0,
|
|
168
|
-
warnings: flushWarnings()
|
|
167
|
+
warnings: Logger.flushWarnings()
|
|
169
168
|
};
|
|
170
169
|
}
|
|
171
170
|
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import "stylis";
|
|
2
|
-
import { Options } from "jscodeshift";
|
|
3
|
-
|
|
4
1
|
//#region src/adapter.d.ts
|
|
5
2
|
/**
|
|
6
3
|
* Adapter - Single user entry point for customizing the codemod.
|
|
@@ -159,35 +156,20 @@ interface Adapter {
|
|
|
159
156
|
*/
|
|
160
157
|
declare function defineAdapter(adapter: Adapter): Adapter;
|
|
161
158
|
//#endregion
|
|
162
|
-
//#region src/internal/
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
interface TransformWarning {
|
|
159
|
+
//#region src/internal/logger.d.ts
|
|
160
|
+
type Severity = "info" | "warning" | "error";
|
|
161
|
+
interface WarningLog {
|
|
162
|
+
severity: Severity;
|
|
167
163
|
type: "unsupported-feature" | "dynamic-node";
|
|
168
|
-
feature: string;
|
|
169
164
|
message: string;
|
|
170
165
|
loc?: {
|
|
171
166
|
line: number;
|
|
172
167
|
column: number;
|
|
173
168
|
};
|
|
169
|
+
context?: unknown;
|
|
174
170
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
*/
|
|
178
|
-
interface TransformResult {
|
|
179
|
-
code: string | null;
|
|
180
|
-
warnings: TransformWarning[];
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Options for the transform
|
|
184
|
-
*/
|
|
185
|
-
interface TransformOptions extends Options {
|
|
186
|
-
/**
|
|
187
|
-
* Adapter for customizing the transform.
|
|
188
|
-
* Controls value resolution and resolver-provided imports.
|
|
189
|
-
*/
|
|
190
|
-
adapter: Adapter;
|
|
171
|
+
interface CollectedWarning extends WarningLog {
|
|
172
|
+
filePath: string;
|
|
191
173
|
}
|
|
192
174
|
//#endregion
|
|
193
|
-
export { defineAdapter as
|
|
175
|
+
export { defineAdapter as i, WarningLog as n, Adapter as r, CollectedWarning as t };
|
|
@@ -25,7 +25,7 @@ function assertValidAdapter(candidate, where) {
|
|
|
25
25
|
const resolveValue = obj?.resolveValue;
|
|
26
26
|
const shouldSupportExternalStyling = obj?.shouldSupportExternalStyling;
|
|
27
27
|
if (!candidate || typeof candidate !== "object") throw new Error([
|
|
28
|
-
|
|
28
|
+
`${where}: expected an adapter object.`,
|
|
29
29
|
`Received: ${describeValue(candidate)}`,
|
|
30
30
|
"",
|
|
31
31
|
"Adapter requirements:",
|
|
@@ -40,7 +40,7 @@ function assertValidAdapter(candidate, where) {
|
|
|
40
40
|
`Docs/examples: ${ADAPTER_DOCS_URL}`
|
|
41
41
|
].join("\n"));
|
|
42
42
|
if (typeof resolveValue !== "function") throw new Error([
|
|
43
|
-
|
|
43
|
+
`${where}: adapter.resolveValue must be a function.`,
|
|
44
44
|
`Received: resolveValue=${describeValue(resolveValue)}`,
|
|
45
45
|
"",
|
|
46
46
|
"Adapter shape:",
|
|
@@ -50,11 +50,11 @@ function assertValidAdapter(candidate, where) {
|
|
|
50
50
|
"",
|
|
51
51
|
`Docs/examples: ${ADAPTER_DOCS_URL}`
|
|
52
52
|
].join("\n"));
|
|
53
|
-
if (typeof shouldSupportExternalStyling !== "function") throw new Error([
|
|
53
|
+
if (typeof shouldSupportExternalStyling !== "function") throw new Error([`${where}: adapter.shouldSupportExternalStyling must be a function.`, `Received: shouldSupportExternalStyling=${describeValue(shouldSupportExternalStyling)}`].join("\n"));
|
|
54
54
|
const styleMerger = obj?.styleMerger;
|
|
55
55
|
if (styleMerger !== null && styleMerger !== void 0) {
|
|
56
56
|
if (typeof styleMerger !== "object") throw new Error([
|
|
57
|
-
|
|
57
|
+
`${where}: adapter.styleMerger must be null or an object.`,
|
|
58
58
|
`Received: styleMerger=${describeValue(styleMerger)}`,
|
|
59
59
|
"",
|
|
60
60
|
"Expected shape:",
|
|
@@ -64,9 +64,9 @@ function assertValidAdapter(candidate, where) {
|
|
|
64
64
|
" }"
|
|
65
65
|
].join("\n"));
|
|
66
66
|
const { functionName, importSource } = styleMerger;
|
|
67
|
-
if (typeof functionName !== "string" || !functionName.trim()) throw new Error([
|
|
67
|
+
if (typeof functionName !== "string" || !functionName.trim()) throw new Error([`${where}: adapter.styleMerger.functionName must be a non-empty string.`, `Received: functionName=${describeValue(functionName)}`].join("\n"));
|
|
68
68
|
if (!importSource || typeof importSource !== "object") throw new Error([
|
|
69
|
-
|
|
69
|
+
`${where}: adapter.styleMerger.importSource must be an object.`,
|
|
70
70
|
`Received: importSource=${describeValue(importSource)}`,
|
|
71
71
|
"",
|
|
72
72
|
"Expected shape:",
|
|
@@ -75,42 +75,82 @@ function assertValidAdapter(candidate, where) {
|
|
|
75
75
|
" { kind: \"absolutePath\", value: \"/path/to/module.ts\" }"
|
|
76
76
|
].join("\n"));
|
|
77
77
|
const { kind, value } = importSource;
|
|
78
|
-
if (kind !== "specifier" && kind !== "absolutePath") throw new Error([
|
|
79
|
-
if (typeof value !== "string" || !value.trim()) throw new Error([
|
|
78
|
+
if (kind !== "specifier" && kind !== "absolutePath") throw new Error([`${where}: adapter.styleMerger.importSource.kind must be "specifier" or "absolutePath".`, `Received: kind=${describeValue(kind)}`].join("\n"));
|
|
79
|
+
if (typeof value !== "string" || !value.trim()) throw new Error([`${where}: adapter.styleMerger.importSource.value must be a non-empty string.`, `Received: value=${describeValue(value)}`].join("\n"));
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
const ADAPTER_DOCS_URL = `https://github.com/skovhus/styled-components-to-stylex-codemod#adapter`;
|
|
83
83
|
|
|
84
84
|
//#endregion
|
|
85
85
|
//#region src/internal/logger.ts
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
collected = [];
|
|
92
|
-
return result;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Log a warning message to stderr.
|
|
96
|
-
* All codemod warnings go through this so tests can mock it.
|
|
97
|
-
*/
|
|
98
|
-
function logWarning(message) {
|
|
99
|
-
process.stderr.write(message);
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Log transform warnings to stderr and collect them.
|
|
103
|
-
*/
|
|
104
|
-
function logWarnings(warnings, filePath) {
|
|
105
|
-
for (const warning of warnings) {
|
|
106
|
-
collected.push({
|
|
107
|
-
...warning,
|
|
108
|
-
filePath
|
|
109
|
-
});
|
|
110
|
-
logWarning(`[styled-components-to-stylex] Warning${warning.loc ? ` (${filePath}:${warning.loc.line}:${warning.loc.column})` : ` (${filePath})`}: ${warning.message}\n`);
|
|
86
|
+
var Logger = class Logger {
|
|
87
|
+
static flushWarnings() {
|
|
88
|
+
const result = collected;
|
|
89
|
+
collected = [];
|
|
90
|
+
return result;
|
|
111
91
|
}
|
|
112
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Log a warning message to stderr.
|
|
94
|
+
* All codemod warnings go through this so tests can mock it.
|
|
95
|
+
*/
|
|
96
|
+
static warn(message, context) {
|
|
97
|
+
Logger.writeWithSpacing(message, context);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Log an error message to stderr.
|
|
101
|
+
*/
|
|
102
|
+
static error(message, context) {
|
|
103
|
+
Logger.writeWithSpacing(`${Logger.colorizeErrorLabel("Error")} ${message}`, context);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Log transform warnings to stderr and collect them.
|
|
107
|
+
*/
|
|
108
|
+
static logWarnings(warnings, filePath) {
|
|
109
|
+
for (const warning of warnings) {
|
|
110
|
+
collected.push({
|
|
111
|
+
...warning,
|
|
112
|
+
filePath
|
|
113
|
+
});
|
|
114
|
+
const location = warning.loc ? `${filePath}:${warning.loc.line}:${warning.loc.column}` : `${filePath}`;
|
|
115
|
+
const label = Logger.colorizeSeverityLabel(warning.severity);
|
|
116
|
+
Logger.writeWithSpacing(`${label} ${location}\n${warning.message}`, warning.context);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
static writeWithSpacing(message, context) {
|
|
120
|
+
const trimmed = message.replace(/\s+$/u, "");
|
|
121
|
+
const serialized = Logger.formatContext(context);
|
|
122
|
+
process.stderr.write(`${trimmed}${serialized ? `\n${serialized}` : ""}\n\n`);
|
|
123
|
+
}
|
|
124
|
+
static colorizeSeverityLabel(severity) {
|
|
125
|
+
if (severity === "error") return Logger.colorizeErrorLabel("Error");
|
|
126
|
+
if (severity === "info") return Logger.colorizeInfoLabel("Info");
|
|
127
|
+
return Logger.colorizeWarnLabel("Warning");
|
|
128
|
+
}
|
|
129
|
+
static colorizeWarnLabel(label) {
|
|
130
|
+
if (!process.stderr.isTTY) return label;
|
|
131
|
+
return `${WARN_BG_COLOR}${WARN_TEXT_COLOR}${label}${RESET_COLOR}`;
|
|
132
|
+
}
|
|
133
|
+
static colorizeErrorLabel(label) {
|
|
134
|
+
if (!process.stderr.isTTY) return label;
|
|
135
|
+
return `${ERROR_BG_COLOR}${ERROR_TEXT_COLOR}${label}${RESET_COLOR}`;
|
|
136
|
+
}
|
|
137
|
+
static colorizeInfoLabel(label) {
|
|
138
|
+
if (!process.stderr.isTTY) return label;
|
|
139
|
+
return `${INFO_BG_COLOR}${INFO_TEXT_COLOR}${label}${RESET_COLOR}`;
|
|
140
|
+
}
|
|
141
|
+
static formatContext(context) {
|
|
142
|
+
if (typeof context === "undefined") return null;
|
|
143
|
+
return JSON.stringify(context, null, 2);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
113
146
|
let collected = [];
|
|
147
|
+
const WARN_BG_COLOR = "\x1B[43m";
|
|
148
|
+
const WARN_TEXT_COLOR = "\x1B[30m";
|
|
149
|
+
const ERROR_BG_COLOR = "\x1B[41m";
|
|
150
|
+
const ERROR_TEXT_COLOR = "\x1B[37m";
|
|
151
|
+
const INFO_BG_COLOR = "\x1B[44m";
|
|
152
|
+
const INFO_TEXT_COLOR = "\x1B[37m";
|
|
153
|
+
const RESET_COLOR = "\x1B[0m";
|
|
114
154
|
|
|
115
155
|
//#endregion
|
|
116
|
-
export {
|
|
156
|
+
export { assertValidAdapter as n, describeValue as r, Logger as t };
|
package/dist/transform.d.mts
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
|
-
import { n as
|
|
1
|
+
import { n as WarningLog, r as Adapter } from "./logger-BS4Evg0n.mjs";
|
|
2
|
+
import "stylis";
|
|
2
3
|
import { API, FileInfo, Options } from "jscodeshift";
|
|
3
4
|
|
|
4
|
-
//#region src/transform.d.ts
|
|
5
|
+
//#region src/internal/transform-types.d.ts
|
|
5
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Result of the transform including any log entries
|
|
9
|
+
*/
|
|
10
|
+
interface TransformResult {
|
|
11
|
+
code: string | null;
|
|
12
|
+
warnings: WarningLog[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Options for the transform
|
|
16
|
+
*/
|
|
17
|
+
interface TransformOptions extends Options {
|
|
18
|
+
/**
|
|
19
|
+
* Adapter for customizing the transform.
|
|
20
|
+
* Controls value resolution and resolver-provided imports.
|
|
21
|
+
*/
|
|
22
|
+
adapter: Adapter;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/transform.d.ts
|
|
6
26
|
/**
|
|
7
27
|
* Transform styled-components to StyleX
|
|
8
28
|
*
|
|
@@ -15,4 +35,4 @@ declare function transform(file: FileInfo, api: API, options: Options): string |
|
|
|
15
35
|
*/
|
|
16
36
|
declare function transformWithWarnings(file: FileInfo, api: API, options: TransformOptions): TransformResult;
|
|
17
37
|
//#endregion
|
|
18
|
-
export { type TransformOptions, type TransformResult,
|
|
38
|
+
export { type TransformOptions, type TransformResult, transform as default, transformWithWarnings };
|
package/dist/transform.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as assertValidAdapter, t as Logger } from "./logger-Dlnt1fYP.mjs";
|
|
2
2
|
import path, { dirname, resolve } from "node:path";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { compile } from "stylis";
|
|
@@ -427,6 +427,14 @@ function collectStyledDeclsImpl(args) {
|
|
|
427
427
|
}
|
|
428
428
|
return out;
|
|
429
429
|
};
|
|
430
|
+
const shouldForceWrapperForAttrs = (attrsInfo) => {
|
|
431
|
+
if (!attrsInfo) return false;
|
|
432
|
+
const props = /* @__PURE__ */ new Set();
|
|
433
|
+
for (const c of attrsInfo.conditionalAttrs ?? []) if (typeof c?.jsxProp === "string") props.add(c.jsxProp);
|
|
434
|
+
for (const a of attrsInfo.defaultAttrs ?? []) if (typeof a?.jsxProp === "string") props.add(a.jsxProp);
|
|
435
|
+
for (const inv of attrsInfo.invertedBoolAttrs ?? []) if (typeof inv?.jsxProp === "string") props.add(inv.jsxProp);
|
|
436
|
+
return [...props].some((p) => p.startsWith("$"));
|
|
437
|
+
};
|
|
430
438
|
const parseShouldForwardProp = (arg0) => {
|
|
431
439
|
if (!arg0 || arg0.type !== "ObjectExpression") return;
|
|
432
440
|
const prop = (arg0.properties ?? []).find((p) => {
|
|
@@ -661,6 +669,7 @@ function collectStyledDeclsImpl(args) {
|
|
|
661
669
|
templateExpressions: parsed.slots.map((s) => s.expression),
|
|
662
670
|
rawCss: parsed.rawCss,
|
|
663
671
|
...attrsInfo ? { attrsInfo } : {},
|
|
672
|
+
...shouldForceWrapperForAttrs(attrsInfo) ? { needsWrapperComponent: true } : {},
|
|
664
673
|
...shouldForwardProp ? { shouldForwardProp } : {},
|
|
665
674
|
...shouldForwardProp ? { shouldForwardPropFromWithConfig: true } : {},
|
|
666
675
|
...withConfigMeta ? { withConfig: withConfigMeta } : {},
|
|
@@ -690,6 +699,7 @@ function collectStyledDeclsImpl(args) {
|
|
|
690
699
|
templateExpressions: parsed.slots.map((s) => s.expression),
|
|
691
700
|
rawCss: parsed.rawCss,
|
|
692
701
|
...attrsInfo ? { attrsInfo } : {},
|
|
702
|
+
...shouldForceWrapperForAttrs(attrsInfo) ? { needsWrapperComponent: true } : {},
|
|
693
703
|
...propsType ? { propsType } : {},
|
|
694
704
|
...leadingComments ? { leadingComments } : {}
|
|
695
705
|
});
|
|
@@ -716,6 +726,7 @@ function collectStyledDeclsImpl(args) {
|
|
|
716
726
|
templateExpressions: parsed.slots.map((s) => s.expression),
|
|
717
727
|
rawCss: parsed.rawCss,
|
|
718
728
|
...attrsInfo ? { attrsInfo } : {},
|
|
729
|
+
...shouldForceWrapperForAttrs(attrsInfo) ? { needsWrapperComponent: true } : {},
|
|
719
730
|
...propsType ? { propsType } : {},
|
|
720
731
|
...leadingComments ? { leadingComments } : {}
|
|
721
732
|
});
|
|
@@ -1479,6 +1490,84 @@ function tryResolveConditionalCssBlock(node) {
|
|
|
1479
1490
|
}
|
|
1480
1491
|
return null;
|
|
1481
1492
|
}
|
|
1493
|
+
function tryResolveConditionalCssBlockTernary(node) {
|
|
1494
|
+
const expr = node.expr;
|
|
1495
|
+
if (!isArrowFunctionExpression(expr)) return null;
|
|
1496
|
+
const paramName = getArrowFnSingleParamName(expr);
|
|
1497
|
+
if (!paramName) return null;
|
|
1498
|
+
if (expr.body.type !== "ConditionalExpression") return null;
|
|
1499
|
+
const test = expr.body.test;
|
|
1500
|
+
if (!test || test.type !== "MemberExpression") return null;
|
|
1501
|
+
const testPath = getMemberPathFromIdentifier(test, paramName);
|
|
1502
|
+
if (!testPath || testPath.length !== 1) return null;
|
|
1503
|
+
const when = testPath[0];
|
|
1504
|
+
const consText = literalToString(expr.body.consequent);
|
|
1505
|
+
const altText = literalToString(expr.body.alternate);
|
|
1506
|
+
if (consText === null || altText === null) return null;
|
|
1507
|
+
const consStyle = consText.trim() ? parseCssDeclarationBlock(consText) : null;
|
|
1508
|
+
const altStyle = altText.trim() ? parseCssDeclarationBlock(altText) : null;
|
|
1509
|
+
if (!consStyle && !altStyle) return null;
|
|
1510
|
+
const variants = [];
|
|
1511
|
+
if (altStyle) variants.push({
|
|
1512
|
+
nameHint: "falsy",
|
|
1513
|
+
when: `!${when}`,
|
|
1514
|
+
style: altStyle
|
|
1515
|
+
});
|
|
1516
|
+
if (consStyle) variants.push({
|
|
1517
|
+
nameHint: "truthy",
|
|
1518
|
+
when,
|
|
1519
|
+
style: consStyle
|
|
1520
|
+
});
|
|
1521
|
+
return {
|
|
1522
|
+
type: "splitVariants",
|
|
1523
|
+
variants
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
1526
|
+
function tryResolveArrowFnCallWithSinglePropArg(node) {
|
|
1527
|
+
if (!node.css.property) return null;
|
|
1528
|
+
const expr = node.expr;
|
|
1529
|
+
if (!isArrowFunctionExpression(expr)) return null;
|
|
1530
|
+
const paramName = getArrowFnSingleParamName(expr);
|
|
1531
|
+
if (!paramName) return null;
|
|
1532
|
+
const body = expr.body;
|
|
1533
|
+
if (!body || body.type !== "CallExpression") return null;
|
|
1534
|
+
if (body.callee?.type !== "Identifier" || typeof body.callee.name !== "string") return null;
|
|
1535
|
+
const calleeIdent = body.callee.name;
|
|
1536
|
+
const args = body.arguments ?? [];
|
|
1537
|
+
if (args.length !== 1) return null;
|
|
1538
|
+
const arg0 = args[0];
|
|
1539
|
+
if (!arg0 || arg0.type !== "MemberExpression") return null;
|
|
1540
|
+
const path$1 = getMemberPathFromIdentifier(arg0, paramName);
|
|
1541
|
+
if (!path$1 || path$1.length !== 1) return null;
|
|
1542
|
+
const propName = path$1[0];
|
|
1543
|
+
return {
|
|
1544
|
+
type: "emitStyleFunction",
|
|
1545
|
+
nameHint: `${sanitizeIdentifier(node.css.property)}FromProp`,
|
|
1546
|
+
params: "value: any",
|
|
1547
|
+
body: `{ ${Object.keys(styleFromSingleDeclaration(node.css.property, "value"))[0]}: value }`,
|
|
1548
|
+
call: propName,
|
|
1549
|
+
valueTransform: {
|
|
1550
|
+
kind: "call",
|
|
1551
|
+
calleeIdent
|
|
1552
|
+
}
|
|
1553
|
+
};
|
|
1554
|
+
}
|
|
1555
|
+
function tryResolveInlineStyleValueForConditionalExpression(node) {
|
|
1556
|
+
if (!node.css.property) return null;
|
|
1557
|
+
const expr = node.expr;
|
|
1558
|
+
if (!isArrowFunctionExpression(expr)) return null;
|
|
1559
|
+
if (expr.body?.type !== "ConditionalExpression") return null;
|
|
1560
|
+
{
|
|
1561
|
+
const paramName = getArrowFnSingleParamName(expr);
|
|
1562
|
+
const test = expr.body.test;
|
|
1563
|
+
const testPath = paramName && test?.type === "MemberExpression" ? getMemberPathFromIdentifier(test, paramName) : null;
|
|
1564
|
+
if (testPath && testPath[0] === "theme") return {
|
|
1565
|
+
type: "keepOriginal",
|
|
1566
|
+
reason: "Theme-dependent conditional values require a project-specific theme source (e.g. useTheme()); cannot safely preserve."
|
|
1567
|
+
};
|
|
1568
|
+
}
|
|
1569
|
+
return { type: "emitInlineStyleValueFromProps" };
|
|
1570
|
+
}
|
|
1482
1571
|
function tryResolvePropAccess(node) {
|
|
1483
1572
|
if (!node.css.property) return null;
|
|
1484
1573
|
const expr = node.expr;
|
|
@@ -1503,7 +1592,7 @@ function tryResolvePropAccess(node) {
|
|
|
1503
1592
|
* Order matters: more-specific transforms first, then fall back to prop-access emission.
|
|
1504
1593
|
*/
|
|
1505
1594
|
function resolveDynamicNode(node, ctx) {
|
|
1506
|
-
return tryResolveThemeAccess(node, ctx) ?? tryResolveCallExpression(node, ctx) ?? tryResolveConditionalValue(node, ctx) ?? tryResolveConditionalCssBlock(node) ?? tryResolvePropAccess(node);
|
|
1595
|
+
return tryResolveThemeAccess(node, ctx) ?? tryResolveCallExpression(node, ctx) ?? tryResolveConditionalValue(node, ctx) ?? tryResolveConditionalCssBlockTernary(node) ?? tryResolveConditionalCssBlock(node) ?? tryResolveArrowFnCallWithSinglePropArg(node) ?? tryResolvePropAccess(node) ?? tryResolveInlineStyleValueForConditionalExpression(node);
|
|
1507
1596
|
}
|
|
1508
1597
|
function literalToStaticValue$1(node) {
|
|
1509
1598
|
if (!node || typeof node !== "object") return null;
|
|
@@ -1815,8 +1904,8 @@ function tryHandleInterpolatedBorder(args) {
|
|
|
1815
1904
|
},
|
|
1816
1905
|
warn: (w) => {
|
|
1817
1906
|
warnings.push({
|
|
1907
|
+
severity: "warning",
|
|
1818
1908
|
type: "dynamic-node",
|
|
1819
|
-
feature: w.feature,
|
|
1820
1909
|
message: w.message,
|
|
1821
1910
|
...w.loc ? { loc: w.loc } : {}
|
|
1822
1911
|
});
|
|
@@ -2162,6 +2251,90 @@ function lowerRules(args) {
|
|
|
2162
2251
|
target[key] = map;
|
|
2163
2252
|
};
|
|
2164
2253
|
const toKebab = (s) => s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9-]/g, "-").toLowerCase();
|
|
2254
|
+
const isAstNode$1 = (v) => !!v && typeof v === "object" && !Array.isArray(v) && typeof v.type === "string";
|
|
2255
|
+
const mergeStyleObjects = (target, source) => {
|
|
2256
|
+
for (const [key, value] of Object.entries(source)) {
|
|
2257
|
+
const existing = target[key];
|
|
2258
|
+
if (existing && value && typeof existing === "object" && typeof value === "object" && !Array.isArray(existing) && !Array.isArray(value) && !isAstNode$1(existing) && !isAstNode$1(value)) mergeStyleObjects(existing, value);
|
|
2259
|
+
else target[key] = value;
|
|
2260
|
+
}
|
|
2261
|
+
};
|
|
2262
|
+
const isCssHelperTaggedTemplate = (expr) => {
|
|
2263
|
+
if (!expr || expr.type !== "TaggedTemplateExpression") return false;
|
|
2264
|
+
if (expr.tag?.type !== "Identifier") return false;
|
|
2265
|
+
const localName = expr.tag.name;
|
|
2266
|
+
const imp = importMap.get(localName);
|
|
2267
|
+
return !!imp && imp.importedName === "css" && imp.source?.kind === "specifier" && imp.source.value === "styled-components";
|
|
2268
|
+
};
|
|
2269
|
+
const resolveHelperExprToAst = (expr, paramName) => {
|
|
2270
|
+
if (!expr || typeof expr !== "object") return null;
|
|
2271
|
+
if (expr.type === "StringLiteral" || expr.type === "NumericLiteral" || expr.type === "Literal") return expr;
|
|
2272
|
+
const path$1 = paramName && (expr.type === "MemberExpression" || expr.type === "OptionalMemberExpression") ? getMemberPathFromIdentifier(expr, paramName) : null;
|
|
2273
|
+
if (!path$1 || path$1[0] !== "theme") return null;
|
|
2274
|
+
const res = resolveValue({
|
|
2275
|
+
kind: "theme",
|
|
2276
|
+
path: path$1.slice(1).join(".")
|
|
2277
|
+
});
|
|
2278
|
+
if (!res) return null;
|
|
2279
|
+
for (const imp of res.imports ?? []) resolverImports.set(JSON.stringify(imp), imp);
|
|
2280
|
+
return parseExpr$1(res.expr) ?? null;
|
|
2281
|
+
};
|
|
2282
|
+
const resolveCssHelperTemplate = (template, paramName) => {
|
|
2283
|
+
const parsed = parseStyledTemplateLiteral(template);
|
|
2284
|
+
const wrappedRawCss = `& { ${parsed.rawCss} }`;
|
|
2285
|
+
const rules = normalizeStylisAstToIR(compile(wrappedRawCss), parsed.slots, { rawCss: wrappedRawCss });
|
|
2286
|
+
const slotExprById = new Map(parsed.slots.map((s) => [s.index, s.expression]));
|
|
2287
|
+
const out = {};
|
|
2288
|
+
const normalizePseudoElement = (pseudo) => {
|
|
2289
|
+
if (!pseudo) return null;
|
|
2290
|
+
if (pseudo === ":before" || pseudo === ":after") return `::${pseudo.slice(1)}`;
|
|
2291
|
+
return pseudo.startsWith("::") ? pseudo : null;
|
|
2292
|
+
};
|
|
2293
|
+
for (const rule of rules) {
|
|
2294
|
+
if (rule.atRuleStack.length > 0) return null;
|
|
2295
|
+
const selector = (rule.selector ?? "").trim();
|
|
2296
|
+
let target = out;
|
|
2297
|
+
if (selector !== "&") {
|
|
2298
|
+
const pseudoElement = parsePseudoElement(selector);
|
|
2299
|
+
const simplePseudo = parseSimplePseudo(selector);
|
|
2300
|
+
const normalizedPseudoElement = normalizePseudoElement(pseudoElement ?? (simplePseudo === ":before" || simplePseudo === ":after" ? simplePseudo : null));
|
|
2301
|
+
if (normalizedPseudoElement) {
|
|
2302
|
+
const nested = out[normalizedPseudoElement] ?? {};
|
|
2303
|
+
out[normalizedPseudoElement] = nested;
|
|
2304
|
+
target = nested;
|
|
2305
|
+
} else if (simplePseudo) {
|
|
2306
|
+
const nested = out[simplePseudo] ?? {};
|
|
2307
|
+
out[simplePseudo] = nested;
|
|
2308
|
+
target = nested;
|
|
2309
|
+
} else return null;
|
|
2310
|
+
}
|
|
2311
|
+
for (const d of rule.declarations) {
|
|
2312
|
+
if (!d.property) return null;
|
|
2313
|
+
if (d.value.kind === "static") {
|
|
2314
|
+
for (const mapped of cssDeclarationToStylexDeclarations(d)) {
|
|
2315
|
+
let value = cssValueToJs$1(mapped.value, d.important);
|
|
2316
|
+
if (mapped.prop === "content" && typeof value === "string") {
|
|
2317
|
+
const m = value.match(/^['"]([\s\S]*)['"]$/);
|
|
2318
|
+
if (m) value = `"${m[1]}"`;
|
|
2319
|
+
else if (!value.startsWith("\"") && !value.endsWith("\"")) value = `"${value}"`;
|
|
2320
|
+
}
|
|
2321
|
+
target[mapped.prop] = value;
|
|
2322
|
+
}
|
|
2323
|
+
continue;
|
|
2324
|
+
}
|
|
2325
|
+
if (d.important) return null;
|
|
2326
|
+
const parts = d.value.parts ?? [];
|
|
2327
|
+
if (parts.length !== 1 || parts[0]?.kind !== "slot") return null;
|
|
2328
|
+
const slotId = parts[0].slotId;
|
|
2329
|
+
const expr = slotExprById.get(slotId);
|
|
2330
|
+
if (!expr) return null;
|
|
2331
|
+
const exprAst = resolveHelperExprToAst(expr, paramName);
|
|
2332
|
+
if (!exprAst) return null;
|
|
2333
|
+
for (const mapped of cssDeclarationToStylexDeclarations(d)) target[mapped.prop] = exprAst;
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
return out;
|
|
2337
|
+
};
|
|
2165
2338
|
const tryHandleMappedFunctionColor = (d) => {
|
|
2166
2339
|
if ((d.property ?? "").trim() !== "background") return false;
|
|
2167
2340
|
if (d.value.kind !== "interpolated") return false;
|
|
@@ -2238,6 +2411,68 @@ function lowerRules(args) {
|
|
|
2238
2411
|
}
|
|
2239
2412
|
return true;
|
|
2240
2413
|
};
|
|
2414
|
+
const tryHandleCssHelperConditionalBlock = (d) => {
|
|
2415
|
+
if (d.value.kind !== "interpolated") return false;
|
|
2416
|
+
if (d.property) return false;
|
|
2417
|
+
const parts = d.value.parts ?? [];
|
|
2418
|
+
if (parts.length !== 1 || parts[0]?.kind !== "slot") return false;
|
|
2419
|
+
const slotId = parts[0].slotId;
|
|
2420
|
+
const expr = decl.templateExpressions[slotId];
|
|
2421
|
+
if (!expr || expr.type !== "ArrowFunctionExpression") return false;
|
|
2422
|
+
const paramName = expr.params?.[0]?.type === "Identifier" ? expr.params[0].name : null;
|
|
2423
|
+
if (!paramName) return false;
|
|
2424
|
+
if (expr.body?.type !== "ConditionalExpression") return false;
|
|
2425
|
+
const readPropName = (node) => {
|
|
2426
|
+
const path$1 = getMemberPathFromIdentifier(node, paramName);
|
|
2427
|
+
if (!path$1 || path$1.length !== 1) return null;
|
|
2428
|
+
return path$1[0];
|
|
2429
|
+
};
|
|
2430
|
+
const testInfo = (() => {
|
|
2431
|
+
const test = expr.body.test;
|
|
2432
|
+
if (!test || typeof test !== "object") return null;
|
|
2433
|
+
if (test.type === "MemberExpression" || test.type === "OptionalMemberExpression") {
|
|
2434
|
+
const propName = readPropName(test);
|
|
2435
|
+
return propName ? {
|
|
2436
|
+
when: propName,
|
|
2437
|
+
propName
|
|
2438
|
+
} : null;
|
|
2439
|
+
}
|
|
2440
|
+
if (test.type === "UnaryExpression" && test.operator === "!") {
|
|
2441
|
+
const propName = readPropName(test.argument);
|
|
2442
|
+
return propName ? {
|
|
2443
|
+
when: `!${propName}`,
|
|
2444
|
+
propName
|
|
2445
|
+
} : null;
|
|
2446
|
+
}
|
|
2447
|
+
if (test.type === "BinaryExpression" && (test.operator === "===" || test.operator === "!==") && (test.left?.type === "MemberExpression" || test.left?.type === "OptionalMemberExpression")) {
|
|
2448
|
+
const propName = readPropName(test.left);
|
|
2449
|
+
const rhs = literalToStaticValue(test.right);
|
|
2450
|
+
if (!propName || rhs === null) return null;
|
|
2451
|
+
const rhsValue = JSON.stringify(rhs);
|
|
2452
|
+
return {
|
|
2453
|
+
when: `${propName} ${test.operator} ${rhsValue}`,
|
|
2454
|
+
propName
|
|
2455
|
+
};
|
|
2456
|
+
}
|
|
2457
|
+
return null;
|
|
2458
|
+
})();
|
|
2459
|
+
if (!testInfo) return false;
|
|
2460
|
+
const cons = expr.body.consequent;
|
|
2461
|
+
const alt = expr.body.alternate;
|
|
2462
|
+
if (!isCssHelperTaggedTemplate(cons) || !isCssHelperTaggedTemplate(alt)) return false;
|
|
2463
|
+
const consStyle = resolveCssHelperTemplate(cons.quasi, paramName);
|
|
2464
|
+
const altStyle = resolveCssHelperTemplate(alt.quasi, paramName);
|
|
2465
|
+
if (!consStyle || !altStyle) return false;
|
|
2466
|
+
mergeStyleObjects(styleObj, altStyle);
|
|
2467
|
+
const when = testInfo.when;
|
|
2468
|
+
const existingBucket = variantBuckets.get(when);
|
|
2469
|
+
const nextBucket = existingBucket ? { ...existingBucket } : {};
|
|
2470
|
+
mergeStyleObjects(nextBucket, consStyle);
|
|
2471
|
+
variantBuckets.set(when, nextBucket);
|
|
2472
|
+
variantStyleKeys[when] ??= `${decl.styleKey}${toSuffixFromProp$1(when)}`;
|
|
2473
|
+
if (testInfo.propName && !testInfo.propName.startsWith("$")) ensureShouldForwardPropDrop(decl, testInfo.propName);
|
|
2474
|
+
return true;
|
|
2475
|
+
};
|
|
2241
2476
|
for (const rule of decl.rules) {
|
|
2242
2477
|
const selTrim = rule.selector.trim();
|
|
2243
2478
|
if (selTrim === "& + &" || /^&\s*\+\s*&$/.test(selTrim)) {
|
|
@@ -2301,9 +2536,9 @@ function lowerRules(args) {
|
|
|
2301
2536
|
else if (!hasExprPlaceholder && /\s+[a-zA-Z]/.test(s)) bail = true;
|
|
2302
2537
|
if (bail) {
|
|
2303
2538
|
warnings.push({
|
|
2539
|
+
severity: "warning",
|
|
2304
2540
|
type: "unsupported-feature",
|
|
2305
|
-
|
|
2306
|
-
message: "Complex selectors (grouped selectors, descendant element selectors, class-conditioned selectors, or :not() chains) are not currently supported; skipping this file."
|
|
2541
|
+
message: "Complex selectors (grouped selectors, descendant element selectors, class-conditioned selectors, or :not() chains) are not currently supported"
|
|
2307
2542
|
});
|
|
2308
2543
|
break;
|
|
2309
2544
|
}
|
|
@@ -2433,6 +2668,7 @@ function lowerRules(args) {
|
|
|
2433
2668
|
}
|
|
2434
2669
|
}
|
|
2435
2670
|
}
|
|
2671
|
+
if (tryHandleCssHelperConditionalBlock(d)) continue;
|
|
2436
2672
|
if (tryHandleLogicalOrDefault(d)) continue;
|
|
2437
2673
|
{
|
|
2438
2674
|
const tryHandleEnumIfChainValue = () => {
|
|
@@ -2617,10 +2853,11 @@ function lowerRules(args) {
|
|
|
2617
2853
|
})();
|
|
2618
2854
|
if (!indexedExprAst) {
|
|
2619
2855
|
warnings.push({
|
|
2856
|
+
severity: "error",
|
|
2620
2857
|
type: "dynamic-node",
|
|
2621
|
-
feature: "adapter-resolveValue",
|
|
2622
2858
|
message: `Adapter returned an unparseable expression for ${decl.localName}; dropping this declaration.`
|
|
2623
2859
|
});
|
|
2860
|
+
bail = true;
|
|
2624
2861
|
continue;
|
|
2625
2862
|
}
|
|
2626
2863
|
const param = j.identifier(indexPropName);
|
|
@@ -2677,8 +2914,8 @@ function lowerRules(args) {
|
|
|
2677
2914
|
warn: (w) => {
|
|
2678
2915
|
const loc$1 = w.loc;
|
|
2679
2916
|
warnings.push({
|
|
2917
|
+
severity: "warning",
|
|
2680
2918
|
type: "dynamic-node",
|
|
2681
|
-
feature: w.feature,
|
|
2682
2919
|
message: w.message,
|
|
2683
2920
|
...loc$1 ? { loc: loc$1 } : {}
|
|
2684
2921
|
});
|
|
@@ -2694,8 +2931,8 @@ function lowerRules(args) {
|
|
|
2694
2931
|
const exprAst = parseExpr$1(wrapExprWithStaticParts(res.expr, prefix, suffix));
|
|
2695
2932
|
if (!exprAst) {
|
|
2696
2933
|
warnings.push({
|
|
2934
|
+
severity: "error",
|
|
2697
2935
|
type: "dynamic-node",
|
|
2698
|
-
feature: "adapter-resolveValue",
|
|
2699
2936
|
message: `Adapter returned an unparseable expression for ${decl.localName}; dropping this declaration.`,
|
|
2700
2937
|
...loc ? { loc } : {}
|
|
2701
2938
|
});
|
|
@@ -2738,8 +2975,8 @@ function lowerRules(args) {
|
|
|
2738
2975
|
const exprAst = parseExpr$1(wrapExprWithStaticParts(expr, staticPrefix, staticSuffix));
|
|
2739
2976
|
if (!exprAst) {
|
|
2740
2977
|
warnings.push({
|
|
2978
|
+
severity: "error",
|
|
2741
2979
|
type: "dynamic-node",
|
|
2742
|
-
feature: "adapter-resolveValue",
|
|
2743
2980
|
message: `Adapter returned an unparseable expression for ${decl.localName}; dropping this declaration.`,
|
|
2744
2981
|
...loc ? { loc } : {}
|
|
2745
2982
|
});
|
|
@@ -2787,8 +3024,8 @@ function lowerRules(args) {
|
|
|
2787
3024
|
if (cssProp === "border" && expandBorderShorthand(target, parsed.exprAst)) return;
|
|
2788
3025
|
if (pseudos?.length) {
|
|
2789
3026
|
const existing = target[stylexProp];
|
|
2790
|
-
const isAstNode$
|
|
2791
|
-
const map = existing && typeof existing === "object" && !Array.isArray(existing) && !isAstNode$
|
|
3027
|
+
const isAstNode$2 = !!existing && typeof existing === "object" && !Array.isArray(existing) && "type" in existing && typeof existing.type === "string";
|
|
3028
|
+
const map = existing && typeof existing === "object" && !Array.isArray(existing) && !isAstNode$2 ? existing : {};
|
|
2792
3029
|
if (!("default" in map)) map.default = existing ?? null;
|
|
2793
3030
|
for (const ps of pseudos) map[ps] = parsed.exprAst;
|
|
2794
3031
|
target[stylexProp] = map;
|
|
@@ -2830,6 +3067,21 @@ function lowerRules(args) {
|
|
|
2830
3067
|
}
|
|
2831
3068
|
continue;
|
|
2832
3069
|
}
|
|
3070
|
+
if (res && res.type === "emitInlineStyleValueFromProps") if (!d.property) {} else {
|
|
3071
|
+
const e = decl.templateExpressions[slotId];
|
|
3072
|
+
if (e?.type === "ArrowFunctionExpression") {
|
|
3073
|
+
decl.needsWrapperComponent = true;
|
|
3074
|
+
const valueExpr = j.callExpression(e, [j.identifier("props")]);
|
|
3075
|
+
for (const out of cssDeclarationToStylexDeclarations(d)) {
|
|
3076
|
+
if (!out.prop) continue;
|
|
3077
|
+
inlineStyleProps.push({
|
|
3078
|
+
prop: out.prop,
|
|
3079
|
+
expr: valueExpr
|
|
3080
|
+
});
|
|
3081
|
+
}
|
|
3082
|
+
continue;
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
2833
3085
|
if (res && res.type === "emitStyleFunction") {
|
|
2834
3086
|
const jsxProp = res.call;
|
|
2835
3087
|
{
|
|
@@ -2845,14 +3097,20 @@ function lowerRules(args) {
|
|
|
2845
3097
|
const param = j.identifier(out.prop);
|
|
2846
3098
|
const valueId = j.identifier(out.prop);
|
|
2847
3099
|
annotateParamFromJsxProp(param, jsxProp);
|
|
3100
|
+
if (jsxProp?.startsWith?.("$")) ensureShouldForwardPropDrop(decl, jsxProp);
|
|
2848
3101
|
const buildValueExpr = () => {
|
|
3102
|
+
const transformed = (() => {
|
|
3103
|
+
const vt = res.valueTransform;
|
|
3104
|
+
if (vt?.kind === "call" && typeof vt.calleeIdent === "string") return j.callExpression(j.identifier(vt.calleeIdent), [valueId]);
|
|
3105
|
+
return valueId;
|
|
3106
|
+
})();
|
|
2849
3107
|
const v = d.value;
|
|
2850
|
-
if (!v || v.kind !== "interpolated") return
|
|
3108
|
+
if (!v || v.kind !== "interpolated") return transformed;
|
|
2851
3109
|
const parts = v.parts ?? [];
|
|
2852
3110
|
const slotParts = parts.filter((p$1) => p$1?.kind === "slot");
|
|
2853
|
-
if (slotParts.length !== 1) return
|
|
2854
|
-
if (slotParts[0].slotId !== slotId) return
|
|
2855
|
-
if (!parts.some((p$1) => p$1?.kind === "static" && p$1.value !== "")) return
|
|
3111
|
+
if (slotParts.length !== 1) return transformed;
|
|
3112
|
+
if (slotParts[0].slotId !== slotId) return transformed;
|
|
3113
|
+
if (!parts.some((p$1) => p$1?.kind === "static" && p$1.value !== "")) return transformed;
|
|
2856
3114
|
const quasis = [];
|
|
2857
3115
|
const exprs = [];
|
|
2858
3116
|
let q = "";
|
|
@@ -2867,7 +3125,7 @@ function lowerRules(args) {
|
|
|
2867
3125
|
cooked: q
|
|
2868
3126
|
}, false));
|
|
2869
3127
|
q = "";
|
|
2870
|
-
exprs.push(
|
|
3128
|
+
exprs.push(transformed);
|
|
2871
3129
|
continue;
|
|
2872
3130
|
}
|
|
2873
3131
|
}
|
|
@@ -2890,8 +3148,8 @@ function lowerRules(args) {
|
|
|
2890
3148
|
}
|
|
2891
3149
|
if (res && res.type === "keepOriginal") {
|
|
2892
3150
|
warnings.push({
|
|
3151
|
+
severity: "warning",
|
|
2893
3152
|
type: "dynamic-node",
|
|
2894
|
-
feature: "dynamic-call",
|
|
2895
3153
|
message: res.reason,
|
|
2896
3154
|
...loc ? { loc } : {}
|
|
2897
3155
|
});
|
|
@@ -2910,9 +3168,9 @@ function lowerRules(args) {
|
|
|
2910
3168
|
continue;
|
|
2911
3169
|
}
|
|
2912
3170
|
warnings.push({
|
|
3171
|
+
severity: "warning",
|
|
2913
3172
|
type: "dynamic-node",
|
|
2914
|
-
|
|
2915
|
-
message: `Unresolved interpolation for ${decl.localName}; skipping file (manual follow-up required).`,
|
|
3173
|
+
message: `Unsupported interpolation for ${decl.localName}.`,
|
|
2916
3174
|
...loc ? { loc } : {}
|
|
2917
3175
|
});
|
|
2918
3176
|
bail = true;
|
|
@@ -3056,9 +3314,9 @@ function lowerRules(args) {
|
|
|
3056
3314
|
decl.needsWrapperComponent = true;
|
|
3057
3315
|
} else resolvedStyleObjects.set(decl.styleKey, styleObj);
|
|
3058
3316
|
{
|
|
3059
|
-
const isAstNode$
|
|
3317
|
+
const isAstNode$2 = (v) => !!v && typeof v === "object" && !Array.isArray(v) && "type" in v && typeof v.type === "string";
|
|
3060
3318
|
const isPseudoOrMediaMap = (v) => {
|
|
3061
|
-
if (!v || typeof v !== "object" || Array.isArray(v) || isAstNode$
|
|
3319
|
+
if (!v || typeof v !== "object" || Array.isArray(v) || isAstNode$2(v)) return false;
|
|
3062
3320
|
const keys = Object.keys(v);
|
|
3063
3321
|
if (keys.length === 0) return false;
|
|
3064
3322
|
return keys.includes("default") || keys.some((k) => k.startsWith(":") || k.startsWith("@media") || k.startsWith("::"));
|
|
@@ -3325,11 +3583,11 @@ function emitStylesAndImports(args) {
|
|
|
3325
3583
|
{
|
|
3326
3584
|
const toModuleSpecifier = (from) => {
|
|
3327
3585
|
if (from.kind === "specifier") {
|
|
3328
|
-
if (typeof from.value !== "string" || from.value.trim() === "") throw new Error(`
|
|
3586
|
+
if (typeof from.value !== "string" || from.value.trim() === "") throw new Error(`Invalid import specifier: expected non-empty string, got ${JSON.stringify(from.value)}`);
|
|
3329
3587
|
return from.value;
|
|
3330
3588
|
}
|
|
3331
|
-
if (typeof from.value !== "string" || from.value.trim() === "") throw new Error(`
|
|
3332
|
-
if (!path.isAbsolute(from.value)) throw new Error(`
|
|
3589
|
+
if (typeof from.value !== "string" || from.value.trim() === "") throw new Error(`Invalid import absolutePath: expected non-empty string, got ${JSON.stringify(from.value)}`);
|
|
3590
|
+
if (!path.isAbsolute(from.value)) throw new Error(`Invalid import absolutePath: expected absolute path, got ${JSON.stringify(from.value)}`);
|
|
3333
3591
|
const baseDir = path.dirname(String(filePath));
|
|
3334
3592
|
let rel = path.relative(baseDir, from.value);
|
|
3335
3593
|
rel = rel.split(path.sep).join("/");
|
|
@@ -4066,6 +4324,9 @@ function emitIntrinsicWrappers(ctx) {
|
|
|
4066
4324
|
for (const p of props) if (p) extraProps.add(p);
|
|
4067
4325
|
}
|
|
4068
4326
|
for (const p of d.styleFnFromProps ?? []) if (p?.jsxProp) extraProps.add(p.jsxProp);
|
|
4327
|
+
for (const a of d.attrsInfo?.defaultAttrs ?? []) if (a?.jsxProp) extraProps.add(a.jsxProp);
|
|
4328
|
+
for (const c of d.attrsInfo?.conditionalAttrs ?? []) if (c?.jsxProp) extraProps.add(c.jsxProp);
|
|
4329
|
+
for (const inv of d.attrsInfo?.invertedBoolAttrs ?? []) if (inv?.jsxProp) extraProps.add(inv.jsxProp);
|
|
4069
4330
|
const dropPrefixFromFilter = d.shouldForwardProp?.dropPrefix;
|
|
4070
4331
|
const usedAttrs = getUsedAttrs(d.localName);
|
|
4071
4332
|
const shouldAllowAnyPrefixProps = !!dropPrefixFromFilter && (usedAttrs.has("*") || [...usedAttrs].some((n) => n.startsWith(dropPrefixFromFilter) && !extraProps.has(n)));
|
|
@@ -4091,12 +4352,6 @@ function emitIntrinsicWrappers(ctx) {
|
|
|
4091
4352
|
if (!allowStyleProp) omitted$1.push("\"style\"");
|
|
4092
4353
|
return joinIntersection(omitted$1.length ? `Omit<${base$1}, ${omitted$1.join(" | ")}>` : base$1, extrasTypeText);
|
|
4093
4354
|
}
|
|
4094
|
-
if (!d.shouldForwardPropFromWithConfig) {
|
|
4095
|
-
const supplementalLines = [];
|
|
4096
|
-
if (allowClassNameProp) supplementalLines.push(` className?: string;`);
|
|
4097
|
-
if (allowStyleProp) supplementalLines.push(` style?: React.CSSProperties;`);
|
|
4098
|
-
return withChildren(joinIntersection(extrasTypeText, supplementalLines.length > 0 ? `{\n${supplementalLines.join("\n")}\n}` : "{}"));
|
|
4099
|
-
}
|
|
4100
4355
|
const base = `React.ComponentProps<"${tagName}">`;
|
|
4101
4356
|
const omitted = [];
|
|
4102
4357
|
if (!allowClassNameProp) omitted.push("\"className\"");
|
|
@@ -4142,6 +4397,9 @@ function emitIntrinsicWrappers(ctx) {
|
|
|
4142
4397
|
const destructureParts = [];
|
|
4143
4398
|
for (const p of dropProps) destructureParts.push(p);
|
|
4144
4399
|
for (const p of knownPrefixProps) if (!destructureParts.includes(p)) destructureParts.push(p);
|
|
4400
|
+
for (const a of d.attrsInfo?.defaultAttrs ?? []) if (a?.jsxProp && !destructureParts.includes(a.jsxProp)) destructureParts.push(a.jsxProp);
|
|
4401
|
+
for (const c of d.attrsInfo?.conditionalAttrs ?? []) if (c?.jsxProp && !destructureParts.includes(c.jsxProp)) destructureParts.push(c.jsxProp);
|
|
4402
|
+
for (const inv of d.attrsInfo?.invertedBoolAttrs ?? []) if (inv?.jsxProp && !destructureParts.includes(inv.jsxProp)) destructureParts.push(inv.jsxProp);
|
|
4145
4403
|
const propsParamId = j.identifier("props");
|
|
4146
4404
|
annotatePropsParam(propsParamId, d.localName);
|
|
4147
4405
|
const propsId = j.identifier("props");
|
|
@@ -4166,7 +4424,19 @@ function emitIntrinsicWrappers(ctx) {
|
|
|
4166
4424
|
const declStmt$1 = j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps$1), propsId)]);
|
|
4167
4425
|
const cleanupPrefixStmt$1 = dropPrefix && shouldAllowAnyPrefixProps && includeRest ? j.forOfStatement(j.variableDeclaration("const", [j.variableDeclarator(j.identifier("k"), null)]), j.callExpression(j.memberExpression(j.identifier("Object"), j.identifier("keys")), [restId]), j.blockStatement([j.ifStatement(j.callExpression(j.memberExpression(j.identifier("k"), j.identifier("startsWith")), [j.literal(dropPrefix)]), j.expressionStatement(j.unaryExpression("delete", j.memberExpression(restId, j.identifier("k"), true))))])) : null;
|
|
4168
4426
|
const sxDecl = j.variableDeclaration("const", [j.variableDeclarator(j.identifier("sx"), j.callExpression(j.memberExpression(j.identifier("stylex"), j.identifier("props")), styleArgs))]);
|
|
4169
|
-
const openingAttrs$1 = [
|
|
4427
|
+
const openingAttrs$1 = [];
|
|
4428
|
+
for (const a of d.attrsInfo?.defaultAttrs ?? []) {
|
|
4429
|
+
const propExpr = j.identifier(a.jsxProp);
|
|
4430
|
+
const fallback = typeof a.value === "string" ? j.literal(a.value) : typeof a.value === "number" ? j.literal(a.value) : typeof a.value === "boolean" ? j.booleanLiteral(a.value) : j.literal(String(a.value));
|
|
4431
|
+
openingAttrs$1.push(j.jsxAttribute(j.jsxIdentifier(a.attrName), j.jsxExpressionContainer(j.logicalExpression("??", propExpr, fallback))));
|
|
4432
|
+
}
|
|
4433
|
+
for (const cond of d.attrsInfo?.conditionalAttrs ?? []) openingAttrs$1.push(j.jsxAttribute(j.jsxIdentifier(cond.attrName), j.jsxExpressionContainer(j.conditionalExpression(j.identifier(cond.jsxProp), j.literal(cond.value), j.identifier("undefined")))));
|
|
4434
|
+
for (const inv of d.attrsInfo?.invertedBoolAttrs ?? []) openingAttrs$1.push(j.jsxAttribute(j.jsxIdentifier(inv.attrName), j.jsxExpressionContainer(j.binaryExpression("!==", j.identifier(inv.jsxProp), j.booleanLiteral(true)))));
|
|
4435
|
+
for (const [key, value] of Object.entries(d.attrsInfo?.staticAttrs ?? {})) if (typeof value === "string") openingAttrs$1.push(j.jsxAttribute(j.jsxIdentifier(key), j.literal(value)));
|
|
4436
|
+
else if (typeof value === "boolean") openingAttrs$1.push(j.jsxAttribute(j.jsxIdentifier(key), value ? null : j.jsxExpressionContainer(j.literal(false))));
|
|
4437
|
+
else if (typeof value === "number") openingAttrs$1.push(j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.literal(value))));
|
|
4438
|
+
if (includeRest) openingAttrs$1.push(j.jsxSpreadAttribute(restId));
|
|
4439
|
+
openingAttrs$1.push(j.jsxSpreadAttribute(j.identifier("sx")));
|
|
4170
4440
|
if (d.inlineStyleProps && d.inlineStyleProps.length) openingAttrs$1.push(j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(j.objectExpression([j.spreadElement(j.memberExpression(j.identifier("sx"), j.identifier("style"))), ...d.inlineStyleProps.map((p) => j.property("init", j.identifier(p.prop), p.expr))]))));
|
|
4171
4441
|
const openingEl$1 = j.jsxOpeningElement(j.jsxIdentifier(tagName), openingAttrs$1, false);
|
|
4172
4442
|
const jsx$1 = isVoid ? {
|
|
@@ -4272,6 +4542,7 @@ function emitIntrinsicWrappers(ctx) {
|
|
|
4272
4542
|
if (!allowClassNameProp && !allowStyleProp) {
|
|
4273
4543
|
const usedAttrs = getUsedAttrs(d.localName);
|
|
4274
4544
|
const includeRest = usedAttrs.has("*") || !!d.usedAsValue || usedAttrs.size > 0;
|
|
4545
|
+
const destructureProps = [...new Set([...(d.attrsInfo?.conditionalAttrs ?? []).map((c) => c.jsxProp).filter(Boolean), ...(d.attrsInfo?.invertedBoolAttrs ?? []).map((inv) => inv.jsxProp).filter(Boolean)])];
|
|
4275
4546
|
emitted.push(...withLeadingCommentsOnFirstFunction$1(emitMinimalWrapper$1({
|
|
4276
4547
|
j,
|
|
4277
4548
|
localName: d.localName,
|
|
@@ -4279,11 +4550,15 @@ function emitIntrinsicWrappers(ctx) {
|
|
|
4279
4550
|
propsTypeName: propsTypeNameFor(d.localName),
|
|
4280
4551
|
emitTypes,
|
|
4281
4552
|
styleArgs,
|
|
4282
|
-
destructureProps
|
|
4553
|
+
destructureProps,
|
|
4283
4554
|
allowClassNameProp: false,
|
|
4284
4555
|
allowStyleProp: false,
|
|
4285
4556
|
includeRest,
|
|
4286
4557
|
patternProp: patternProp$1,
|
|
4558
|
+
defaultAttrs: d.attrsInfo?.defaultAttrs ?? [],
|
|
4559
|
+
conditionalAttrs: d.attrsInfo?.conditionalAttrs ?? [],
|
|
4560
|
+
invertedBoolAttrs: d.attrsInfo?.invertedBoolAttrs ?? [],
|
|
4561
|
+
staticAttrs: d.attrsInfo?.staticAttrs ?? {},
|
|
4287
4562
|
inlineStyleProps: d.inlineStyleProps ?? [],
|
|
4288
4563
|
styleMerger
|
|
4289
4564
|
}), d));
|
|
@@ -4584,10 +4859,10 @@ function emitIntrinsicWrappers(ctx) {
|
|
|
4584
4859
|
allowStyleProp: false,
|
|
4585
4860
|
includeRest: shouldIncludeRest,
|
|
4586
4861
|
patternProp: patternProp$1,
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4862
|
+
defaultAttrs: d.attrsInfo?.defaultAttrs ?? [],
|
|
4863
|
+
conditionalAttrs: d.attrsInfo?.conditionalAttrs ?? [],
|
|
4864
|
+
invertedBoolAttrs: d.attrsInfo?.invertedBoolAttrs ?? [],
|
|
4865
|
+
staticAttrs: d.attrsInfo?.staticAttrs ?? {},
|
|
4591
4866
|
inlineStyleProps: d.inlineStyleProps ?? [],
|
|
4592
4867
|
styleMerger
|
|
4593
4868
|
}), d));
|
|
@@ -5286,7 +5561,7 @@ function emitWrappersImpl(args) {
|
|
|
5286
5561
|
case "a": return "React.AnchorHTMLAttributes<HTMLAnchorElement>";
|
|
5287
5562
|
case "button": return "React.ButtonHTMLAttributes<HTMLButtonElement>";
|
|
5288
5563
|
case "div": return "React.HTMLAttributes<HTMLDivElement>";
|
|
5289
|
-
case "input": return "React.
|
|
5564
|
+
case "input": return "React.ComponentProps<\"input\">";
|
|
5290
5565
|
case "img": return "React.ImgHTMLAttributes<HTMLImageElement>";
|
|
5291
5566
|
case "label": return "React.LabelHTMLAttributes<HTMLLabelElement>";
|
|
5292
5567
|
case "select": return "React.SelectHTMLAttributes<HTMLSelectElement>";
|
|
@@ -5618,25 +5893,6 @@ function shouldSkipForThemeProvider(args) {
|
|
|
5618
5893
|
if (!themeProviderLocalForSkip) return false;
|
|
5619
5894
|
return root.find(j.JSXIdentifier, { name: themeProviderLocalForSkip }).size() > 0;
|
|
5620
5895
|
}
|
|
5621
|
-
function shouldSkipForCssHelper(args) {
|
|
5622
|
-
const { root, j, styledImports } = args;
|
|
5623
|
-
const cssImportForSkip = findStyledComponentsNamedImport({
|
|
5624
|
-
styledImports,
|
|
5625
|
-
j,
|
|
5626
|
-
importedName: "css"
|
|
5627
|
-
});
|
|
5628
|
-
const cssLocalForSkip = cssImportForSkip?.local?.type === "Identifier" ? cssImportForSkip.local.name : cssImportForSkip?.imported?.type === "Identifier" ? cssImportForSkip.imported.name : void 0;
|
|
5629
|
-
if (!cssLocalForSkip) return false;
|
|
5630
|
-
const usedAsTaggedTemplate = root.find(j.TaggedTemplateExpression, { tag: {
|
|
5631
|
-
type: "Identifier",
|
|
5632
|
-
name: cssLocalForSkip
|
|
5633
|
-
} }).size() > 0;
|
|
5634
|
-
const usedAsCall = root.find(j.CallExpression, { callee: {
|
|
5635
|
-
type: "Identifier",
|
|
5636
|
-
name: cssLocalForSkip
|
|
5637
|
-
} }).size() > 0;
|
|
5638
|
-
return usedAsTaggedTemplate || usedAsCall;
|
|
5639
|
-
}
|
|
5640
5896
|
function collectThemeProviderSkipWarnings(args) {
|
|
5641
5897
|
const { root, j, styledImports } = args;
|
|
5642
5898
|
const warnings = [];
|
|
@@ -5649,9 +5905,9 @@ function collectThemeProviderSkipWarnings(args) {
|
|
|
5649
5905
|
if (!themeProviderLocalForSkip) return warnings;
|
|
5650
5906
|
if (!(root.find(j.JSXIdentifier, { name: themeProviderLocalForSkip }).size() > 0)) return warnings;
|
|
5651
5907
|
const warning = {
|
|
5908
|
+
severity: "warning",
|
|
5652
5909
|
type: "unsupported-feature",
|
|
5653
|
-
|
|
5654
|
-
message: "ThemeProvider usage is project-specific; skipping this file (manual follow-up required)."
|
|
5910
|
+
message: "ThemeProvider usage is project-specific"
|
|
5655
5911
|
};
|
|
5656
5912
|
if (themeProviderImportForSkip?.loc) warning.loc = {
|
|
5657
5913
|
line: themeProviderImportForSkip.loc.start.line,
|
|
@@ -5678,9 +5934,9 @@ function collectCssHelperSkipWarnings(args) {
|
|
|
5678
5934
|
name: cssLocalForSkip
|
|
5679
5935
|
} }).size() > 0)) return warnings;
|
|
5680
5936
|
const warning = {
|
|
5937
|
+
severity: "warning",
|
|
5681
5938
|
type: "unsupported-feature",
|
|
5682
|
-
|
|
5683
|
-
message: "`css` helper usage from styled-components is project-specific and not safely transformable; skipping this file (manual follow-up required)."
|
|
5939
|
+
message: "`css` helper usage from styled-components is not supported"
|
|
5684
5940
|
};
|
|
5685
5941
|
if (cssImportForSkip?.loc) warning.loc = {
|
|
5686
5942
|
line: cssImportForSkip.loc.start.line,
|
|
@@ -5695,8 +5951,8 @@ function collectCreateGlobalStyleWarnings(styledImports) {
|
|
|
5695
5951
|
const specifiers = importPath.node.specifiers ?? [];
|
|
5696
5952
|
for (const specifier of specifiers) if (specifier.type === "ImportSpecifier" && specifier.imported.type === "Identifier" && specifier.imported.name === "createGlobalStyle") {
|
|
5697
5953
|
const warning = {
|
|
5954
|
+
severity: "warning",
|
|
5698
5955
|
type: "unsupported-feature",
|
|
5699
|
-
feature: "createGlobalStyle",
|
|
5700
5956
|
message: "createGlobalStyle is not supported in StyleX. Global styles should be handled separately (e.g., in a CSS file or using CSS reset libraries)."
|
|
5701
5957
|
};
|
|
5702
5958
|
if (specifier.loc) warning.loc = {
|
|
@@ -5717,9 +5973,9 @@ function shouldSkipForCreateGlobalStyle(args) {
|
|
|
5717
5973
|
}
|
|
5718
5974
|
function universalSelectorUnsupportedWarning(loc) {
|
|
5719
5975
|
return {
|
|
5976
|
+
severity: "warning",
|
|
5720
5977
|
type: "unsupported-feature",
|
|
5721
|
-
|
|
5722
|
-
message: "Universal selectors (`*`) are currently unsupported; skipping this file (manual follow-up required).",
|
|
5978
|
+
message: "Universal selectors (`*`) are currently unsupported",
|
|
5723
5979
|
...loc ? { loc } : {}
|
|
5724
5980
|
};
|
|
5725
5981
|
}
|
|
@@ -5844,14 +6100,14 @@ function createResolveValueSafe(args) {
|
|
|
5844
6100
|
if (typeof res === "undefined") {
|
|
5845
6101
|
bailRef.value = true;
|
|
5846
6102
|
warnings.push({
|
|
6103
|
+
severity: "error",
|
|
5847
6104
|
type: "dynamic-node",
|
|
5848
|
-
feature: "adapter-resolveValue",
|
|
5849
6105
|
message: [
|
|
5850
6106
|
"Adapter.resolveValue returned undefined. This usually means your adapter forgot to return a value.",
|
|
5851
6107
|
"Return null to leave a value unresolved, or return { expr, imports } to resolve it.",
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
6108
|
+
"Skipping transformation for this file to avoid producing incorrect output."
|
|
6109
|
+
].join(" "),
|
|
6110
|
+
context: ctx
|
|
5855
6111
|
});
|
|
5856
6112
|
return null;
|
|
5857
6113
|
}
|
|
@@ -5862,32 +6118,6 @@ function createResolveValueSafe(args) {
|
|
|
5862
6118
|
bailRef
|
|
5863
6119
|
};
|
|
5864
6120
|
}
|
|
5865
|
-
function formatResolveValueContext(ctx) {
|
|
5866
|
-
const c = ctx;
|
|
5867
|
-
const kind = c?.kind;
|
|
5868
|
-
if (kind === "theme") return `kind=theme path=${JSON.stringify(String(c?.path ?? ""))}`;
|
|
5869
|
-
if (kind === "cssVariable") {
|
|
5870
|
-
const parts = [`kind=cssVariable name=${JSON.stringify(String(c?.name ?? ""))}`];
|
|
5871
|
-
if (typeof c?.fallback === "string") parts.push(`fallback=${JSON.stringify(c.fallback)}`);
|
|
5872
|
-
if (typeof c?.definedValue === "string") parts.push(`definedValue=${JSON.stringify(c.definedValue)}`);
|
|
5873
|
-
return parts.join(" ");
|
|
5874
|
-
}
|
|
5875
|
-
if (kind === "call") {
|
|
5876
|
-
const args = Array.isArray(c?.args) ? c.args : [];
|
|
5877
|
-
return [
|
|
5878
|
-
"kind=call",
|
|
5879
|
-
`calleeImportedName=${JSON.stringify(String(c?.calleeImportedName ?? ""))}`,
|
|
5880
|
-
`calleeSource=${JSON.stringify(c?.calleeSource ?? null)}`,
|
|
5881
|
-
`callSiteFilePath=${JSON.stringify(String(c?.callSiteFilePath ?? ""))}`,
|
|
5882
|
-
`args=${JSON.stringify(args)}`
|
|
5883
|
-
].join(" ");
|
|
5884
|
-
}
|
|
5885
|
-
try {
|
|
5886
|
-
return `ctx=${JSON.stringify(ctx)}`;
|
|
5887
|
-
} catch {
|
|
5888
|
-
return `ctx=${String(ctx)}`;
|
|
5889
|
-
}
|
|
5890
|
-
}
|
|
5891
6121
|
|
|
5892
6122
|
//#endregion
|
|
5893
6123
|
//#region src/internal/css-vars.ts
|
|
@@ -6106,7 +6336,7 @@ function getStaticPropertiesFromImport(args) {
|
|
|
6106
6336
|
*/
|
|
6107
6337
|
function transform(file, api, options) {
|
|
6108
6338
|
const result = transformWithWarnings(file, api, options);
|
|
6109
|
-
logWarnings(result.warnings, file.path);
|
|
6339
|
+
Logger.logWarnings(result.warnings, file.path);
|
|
6110
6340
|
return result.code;
|
|
6111
6341
|
}
|
|
6112
6342
|
/**
|
|
@@ -6154,18 +6384,6 @@ function transformWithWarnings(file, api, options) {
|
|
|
6154
6384
|
styledImports
|
|
6155
6385
|
})
|
|
6156
6386
|
};
|
|
6157
|
-
if (shouldSkipForCssHelper({
|
|
6158
|
-
root,
|
|
6159
|
-
j,
|
|
6160
|
-
styledImports
|
|
6161
|
-
})) return {
|
|
6162
|
-
code: null,
|
|
6163
|
-
warnings: collectCssHelperSkipWarnings({
|
|
6164
|
-
root,
|
|
6165
|
-
j,
|
|
6166
|
-
styledImports
|
|
6167
|
-
})
|
|
6168
|
-
};
|
|
6169
6387
|
warnings.push(...collectCreateGlobalStyleWarnings(styledImports));
|
|
6170
6388
|
const keyframesImport = styledImports.find(j.ImportSpecifier).nodes().find((s) => s.imported.type === "Identifier" && s.imported.name === "keyframes");
|
|
6171
6389
|
const keyframesLocal = keyframesImport?.local?.type === "Identifier" ? keyframesImport.local.name : keyframesImport?.imported?.type === "Identifier" ? keyframesImport.imported.name : void 0;
|
|
@@ -6199,17 +6417,90 @@ function transformWithWarnings(file, api, options) {
|
|
|
6199
6417
|
});
|
|
6200
6418
|
const cssImport = styledImports.find(j.ImportSpecifier).nodes().find((s) => s.imported.type === "Identifier" && s.imported.name === "css");
|
|
6201
6419
|
const cssLocal = cssImport?.local?.type === "Identifier" ? cssImport.local.name : cssImport?.imported?.type === "Identifier" ? cssImport.imported.name : void 0;
|
|
6420
|
+
const styledLocalNames = /* @__PURE__ */ new Set();
|
|
6421
|
+
styledImports.forEach((imp) => {
|
|
6422
|
+
const specs = imp.node.specifiers ?? [];
|
|
6423
|
+
for (const spec of specs) if (spec.type === "ImportDefaultSpecifier" && spec.local?.type === "Identifier") styledLocalNames.add(spec.local.name);
|
|
6424
|
+
});
|
|
6425
|
+
const isStyledTag = (tag) => {
|
|
6426
|
+
if (!tag || typeof tag !== "object") return false;
|
|
6427
|
+
if (tag.type === "Identifier") return styledLocalNames.has(tag.name);
|
|
6428
|
+
if (tag.type === "MemberExpression" || tag.type === "OptionalMemberExpression") return isStyledTag(tag.object);
|
|
6429
|
+
if (tag.type === "CallExpression") return isStyledTag(tag.callee);
|
|
6430
|
+
return false;
|
|
6431
|
+
};
|
|
6432
|
+
const hasUnsupportedCssHelperUsage = (() => {
|
|
6433
|
+
if (!cssLocal) return false;
|
|
6434
|
+
if (root.find(j.CallExpression, { callee: {
|
|
6435
|
+
type: "Identifier",
|
|
6436
|
+
name: cssLocal
|
|
6437
|
+
} }).size() > 0) return true;
|
|
6438
|
+
const cssTagged = root.find(j.TaggedTemplateExpression, { tag: {
|
|
6439
|
+
type: "Identifier",
|
|
6440
|
+
name: cssLocal
|
|
6441
|
+
} });
|
|
6442
|
+
let unsupported = false;
|
|
6443
|
+
cssTagged.forEach((p) => {
|
|
6444
|
+
if (unsupported) return;
|
|
6445
|
+
const cssNode = p.node;
|
|
6446
|
+
let cur = p;
|
|
6447
|
+
let arrow = null;
|
|
6448
|
+
while (cur && cur.parentPath) {
|
|
6449
|
+
cur = cur.parentPath;
|
|
6450
|
+
if (!cur?.node) break;
|
|
6451
|
+
if (cur.node.type === "ArrowFunctionExpression") {
|
|
6452
|
+
arrow = cur.node;
|
|
6453
|
+
break;
|
|
6454
|
+
}
|
|
6455
|
+
}
|
|
6456
|
+
if (!arrow) {
|
|
6457
|
+
unsupported = true;
|
|
6458
|
+
return;
|
|
6459
|
+
}
|
|
6460
|
+
if (arrow.body?.type !== "ConditionalExpression") {
|
|
6461
|
+
unsupported = true;
|
|
6462
|
+
return;
|
|
6463
|
+
}
|
|
6464
|
+
const cond = arrow.body;
|
|
6465
|
+
if (cond.consequent !== cssNode && cond.alternate !== cssNode) {
|
|
6466
|
+
unsupported = true;
|
|
6467
|
+
return;
|
|
6468
|
+
}
|
|
6469
|
+
let hasStyledAncestor = false;
|
|
6470
|
+
let anc = cur;
|
|
6471
|
+
while (anc && anc.parentPath) {
|
|
6472
|
+
anc = anc.parentPath;
|
|
6473
|
+
if (anc?.node?.type === "TaggedTemplateExpression" && isStyledTag(anc.node.tag)) {
|
|
6474
|
+
hasStyledAncestor = true;
|
|
6475
|
+
break;
|
|
6476
|
+
}
|
|
6477
|
+
}
|
|
6478
|
+
if (!hasStyledAncestor) {
|
|
6479
|
+
unsupported = true;
|
|
6480
|
+
return;
|
|
6481
|
+
}
|
|
6482
|
+
});
|
|
6483
|
+
return unsupported;
|
|
6484
|
+
})();
|
|
6485
|
+
const isIdentifierReference = (p) => {
|
|
6486
|
+
const parent = p?.parent?.node;
|
|
6487
|
+
if (!parent) return true;
|
|
6488
|
+
if (parent.type === "ImportSpecifier" || parent.type === "ImportDefaultSpecifier" || parent.type === "ImportNamespaceSpecifier") return false;
|
|
6489
|
+
if ((parent.type === "MemberExpression" || parent.type === "OptionalMemberExpression") && parent.property === p.node && parent.computed === false) return false;
|
|
6490
|
+
if ((parent.type === "Property" || parent.type === "ObjectProperty") && parent.key === p.node && parent.computed === false) return false;
|
|
6491
|
+
if (parent.type === "TSPropertySignature" && parent.key === p.node) return false;
|
|
6492
|
+
return true;
|
|
6493
|
+
};
|
|
6202
6494
|
const cssHelperNames = /* @__PURE__ */ new Set();
|
|
6495
|
+
if (hasUnsupportedCssHelperUsage) return {
|
|
6496
|
+
code: null,
|
|
6497
|
+
warnings: collectCssHelperSkipWarnings({
|
|
6498
|
+
root,
|
|
6499
|
+
j,
|
|
6500
|
+
styledImports
|
|
6501
|
+
})
|
|
6502
|
+
};
|
|
6203
6503
|
if (cssLocal) {
|
|
6204
|
-
const isIdentifierReference = (p) => {
|
|
6205
|
-
const parent = p?.parent?.node;
|
|
6206
|
-
if (!parent) return true;
|
|
6207
|
-
if (parent.type === "ImportSpecifier" || parent.type === "ImportDefaultSpecifier" || parent.type === "ImportNamespaceSpecifier") return false;
|
|
6208
|
-
if ((parent.type === "MemberExpression" || parent.type === "OptionalMemberExpression") && parent.property === p.node && parent.computed === false) return false;
|
|
6209
|
-
if ((parent.type === "Property" || parent.type === "ObjectProperty") && parent.key === p.node && parent.computed === false) return false;
|
|
6210
|
-
if (parent.type === "TSPropertySignature" && parent.key === p.node) return false;
|
|
6211
|
-
return true;
|
|
6212
|
-
};
|
|
6213
6504
|
const isStillReferenced = () => root.find(j.Identifier, { name: cssLocal }).filter((p) => isIdentifierReference(p)).size() > 0;
|
|
6214
6505
|
root.find(j.VariableDeclarator, { init: { type: "TaggedTemplateExpression" } }).forEach((p) => {
|
|
6215
6506
|
const init = p.node.init;
|
|
@@ -6308,8 +6599,8 @@ function transformWithWarnings(file, api, options) {
|
|
|
6308
6599
|
});
|
|
6309
6600
|
if (hasComponentSelector) {
|
|
6310
6601
|
const warning = {
|
|
6602
|
+
severity: "warning",
|
|
6311
6603
|
type: "unsupported-feature",
|
|
6312
|
-
feature: "component-selector",
|
|
6313
6604
|
message: "Component selectors like `${OtherComponent}:hover &` are not directly representable in StyleX. Manual refactor is required to preserve relationship/hover semantics."
|
|
6314
6605
|
};
|
|
6315
6606
|
if (componentSelectorLoc) warnings.push({
|
|
@@ -6324,8 +6615,8 @@ function transformWithWarnings(file, api, options) {
|
|
|
6324
6615
|
}
|
|
6325
6616
|
if (hasSpecificityHack) {
|
|
6326
6617
|
const warning = {
|
|
6618
|
+
severity: "warning",
|
|
6327
6619
|
type: "unsupported-feature",
|
|
6328
|
-
feature: "specificity",
|
|
6329
6620
|
message: "Styled-components specificity hacks like `&&` / `&&&` are not representable in StyleX. The output may not preserve selector specificity and may require manual adjustments."
|
|
6330
6621
|
};
|
|
6331
6622
|
if (specificityHackLoc) warnings.push({
|
|
@@ -6965,6 +7256,7 @@ function transformWithWarnings(file, api, options) {
|
|
|
6965
7256
|
}
|
|
6966
7257
|
continue;
|
|
6967
7258
|
}
|
|
7259
|
+
if (decl.needsWrapperComponent) continue;
|
|
6968
7260
|
root.find(j.JSXElement, { openingElement: { name: {
|
|
6969
7261
|
type: "JSXIdentifier",
|
|
6970
7262
|
name: decl.localName
|
|
@@ -7086,6 +7378,32 @@ function transformWithWarnings(file, api, options) {
|
|
|
7086
7378
|
stylesIdentifier,
|
|
7087
7379
|
styleMerger: adapter.styleMerger
|
|
7088
7380
|
});
|
|
7381
|
+
if (adapter.styleMerger?.functionName && adapter.styleMerger.importSource) {
|
|
7382
|
+
const mergerName = adapter.styleMerger.functionName;
|
|
7383
|
+
const hasMergerUsage = root.find(j.Identifier, { name: mergerName }).filter((p) => isIdentifierReference(p)).size() > 0;
|
|
7384
|
+
const hasMergerImport = root.find(j.ImportSpecifier, { imported: {
|
|
7385
|
+
type: "Identifier",
|
|
7386
|
+
name: mergerName
|
|
7387
|
+
} }).size() > 0;
|
|
7388
|
+
const hasLocalBinding = root.find(j.FunctionDeclaration, { id: { name: mergerName } }).size() > 0 || root.find(j.VariableDeclarator, { id: {
|
|
7389
|
+
type: "Identifier",
|
|
7390
|
+
name: mergerName
|
|
7391
|
+
} }).size() > 0;
|
|
7392
|
+
if (hasMergerUsage && !hasMergerImport && !hasLocalBinding) {
|
|
7393
|
+
const source = adapter.styleMerger.importSource;
|
|
7394
|
+
if (source.kind === "specifier") {
|
|
7395
|
+
const decl = j.importDeclaration([j.importSpecifier(j.identifier(mergerName))], j.literal(source.value));
|
|
7396
|
+
const stylexImport = root.find(j.ImportDeclaration, { source: { value: "@stylexjs/stylex" } });
|
|
7397
|
+
if (stylexImport.size() > 0) stylexImport.at(stylexImport.size() - 1).insertAfter(decl);
|
|
7398
|
+
else {
|
|
7399
|
+
const firstImport = root.find(j.ImportDeclaration).at(0);
|
|
7400
|
+
if (firstImport.size() > 0) firstImport.insertBefore(decl);
|
|
7401
|
+
else root.get().node.program.body.unshift(decl);
|
|
7402
|
+
}
|
|
7403
|
+
hasChanges = true;
|
|
7404
|
+
}
|
|
7405
|
+
}
|
|
7406
|
+
}
|
|
7089
7407
|
for (const [componentName, statements] of staticPropertyAssignments.entries()) {
|
|
7090
7408
|
if (statements.length === 0) continue;
|
|
7091
7409
|
const wrapperFn = root.find(j.FunctionDeclaration, { id: { name: componentName } }).at(0);
|
|
@@ -7103,6 +7421,22 @@ function transformWithWarnings(file, api, options) {
|
|
|
7103
7421
|
preserveReactImport
|
|
7104
7422
|
});
|
|
7105
7423
|
if (post.changed) hasChanges = true;
|
|
7424
|
+
if (cssLocal) {
|
|
7425
|
+
const isStillReferenced = () => root.find(j.Identifier, { name: cssLocal }).filter((p) => isIdentifierReference(p)).size() > 0;
|
|
7426
|
+
if (!isStillReferenced()) styledImports.forEach((imp) => {
|
|
7427
|
+
const specs = imp.node.specifiers ?? [];
|
|
7428
|
+
const next = specs.filter((s) => {
|
|
7429
|
+
if (s.type !== "ImportSpecifier") return true;
|
|
7430
|
+
if (s.imported.type !== "Identifier") return true;
|
|
7431
|
+
return s.imported.name !== "css";
|
|
7432
|
+
});
|
|
7433
|
+
if (next.length !== specs.length) {
|
|
7434
|
+
imp.node.specifiers = next;
|
|
7435
|
+
if (imp.node.specifiers.length === 0) j(imp).remove();
|
|
7436
|
+
hasChanges = true;
|
|
7437
|
+
}
|
|
7438
|
+
});
|
|
7439
|
+
}
|
|
7106
7440
|
if (post.needsReactImport) {
|
|
7107
7441
|
const firstImport = root.find(j.ImportDeclaration).at(0);
|
|
7108
7442
|
const reactImport = j.importDeclaration([j.importDefaultSpecifier(j.identifier("React"))], j.literal("react"));
|