@tamagui/codemod-flat-values 3.0.0-beta.807.1 → 3.0.0-beta.881.1
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 +13 -3
- package/dist/functionalVariants.mjs +469 -0
- package/dist/functionalVariants.mjs.map +1 -0
- package/dist/index.mjs +24 -18
- package/dist/index.mjs.map +1 -1
- package/dist/legacyConditions.mjs +0 -1
- package/dist/legacyConditions.mjs.map +1 -1
- package/dist/report.mjs +36 -6
- package/dist/report.mjs.map +1 -1
- package/package.json +6 -6
- package/src/functionalVariants.ts +642 -0
- package/src/index.ts +43 -28
- package/src/legacyConditions.ts +0 -1
- package/src/report.ts +70 -5
package/README.md
CHANGED
|
@@ -77,11 +77,16 @@ helper, a `react-native` component, and an intrinsic tag are all left alone —
|
|
|
77
77
|
literals is rewritten in place (`active ? '$red10' : '$blue10'`), and an expression
|
|
78
78
|
whose type the checker can prove interpolates into the program
|
|
79
79
|
(`` backgroundColor={`${GREEN} disabled:${GREY}`} ``).
|
|
80
|
-
- Variant
|
|
80
|
+
- Variant branches convert as their own style objects, so a
|
|
81
81
|
branch contributes at its own position in the forward pass. No base is invented for
|
|
82
82
|
a condition-only branch: with clause-level merge (decision 21)
|
|
83
83
|
`exitStyle={{ x: 10 }}` is exactly `x="exit:10px"`, which keeps whatever base the
|
|
84
84
|
styled component, variant, or call site defined — the same thing the v1 prop did.
|
|
85
|
+
- V2 spread variant keys become typed `styled.dynamic` callbacks for the size,
|
|
86
|
+
space, color, radius, font-size, and z-index token categories. Type keys become
|
|
87
|
+
one `number | string | boolean` dynamic, with `typeof` branches when each body
|
|
88
|
+
is one object-literal return. The report leaves catch-all keys, mixed exact and
|
|
89
|
+
function branches, and sibling-prop reads authored.
|
|
85
90
|
|
|
86
91
|
Every program the report suggests is parsed back with the real value parser and merged
|
|
87
92
|
with the real clause merge before it is printed. A program that does not read back
|
|
@@ -198,6 +203,11 @@ A flag means a human decides. Every code the tool can emit:
|
|
|
198
203
|
| `structured-<property>` | a condition needs an object or array with no verified CSS-shaped migration rule |
|
|
199
204
|
| `condition-order-not-preservable`, `base-order-not-preservable` | merging would move a value past something that can also set it |
|
|
200
205
|
| `computed-property` | a computed key hides the affected style property |
|
|
206
|
+
| `functional-variant-needs-resolve` | the callback reads `extras.props`; use the generated `.resolve` draft |
|
|
207
|
+
| `functional-variant-mixed` | exact branches and a function key share one variant |
|
|
208
|
+
| `functional-variant-catch-all` | `'...'` needs an explicit value type chosen by the app |
|
|
209
|
+
| `functional-variant-type-bodies` | different type-key bodies cannot be combined into safe `typeof` branches |
|
|
210
|
+
| `functional-variant-unsupported`, `functional-variant-unsupported-extras`, `functional-variant-styled-import` | the callback, env access, or `styled` import does not have a provable automatic rewrite |
|
|
201
211
|
| `emitted-program-mismatch`, `emitted-value-invalid` | the printer failed its own re-parse; this is a codemod bug |
|
|
202
212
|
| plus any code from the shared converter | `unsupported-legacy-value`, `legacy-condition-object`, `ambiguous-legacy-group`, `legacy-composite-shorthand` |
|
|
203
213
|
|
|
@@ -215,5 +225,5 @@ payloads go through the same shared converter, so they always agree on that.
|
|
|
215
225
|
## Remaining manual migration
|
|
216
226
|
|
|
217
227
|
The report counts the files whose sites all converted: those have no legacy condition
|
|
218
|
-
object left. V3 has no compatibility setting, so the
|
|
219
|
-
still needs a hand edit after `--write`.
|
|
228
|
+
object or flagged functional variant left. V3 has no compatibility setting, so the
|
|
229
|
+
report names every file that still needs a hand edit after `--write`.
|
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
import { Node, SyntaxKind } from "ts-morph";
|
|
2
|
+
import { unwrapExpression } from "./expressions.mjs";
|
|
3
|
+
|
|
4
|
+
const spreadTypes = /* @__PURE__ */ new Map([
|
|
5
|
+
["...size", "SizeTokens"],
|
|
6
|
+
["...space", "SpaceTokens"],
|
|
7
|
+
["...color", "ColorTokens"],
|
|
8
|
+
["...radius", "RadiusTokens"],
|
|
9
|
+
["...fontSize", "FontSizeTokens"],
|
|
10
|
+
["...zIndex", "ZIndexTokens"]
|
|
11
|
+
]);
|
|
12
|
+
const typeKeys = /* @__PURE__ */ new Map([
|
|
13
|
+
[":number", "number"],
|
|
14
|
+
[":string", "string"],
|
|
15
|
+
[":boolean", "boolean"]
|
|
16
|
+
]);
|
|
17
|
+
const typeOrder = [
|
|
18
|
+
"number",
|
|
19
|
+
"string",
|
|
20
|
+
"boolean"
|
|
21
|
+
];
|
|
22
|
+
const envMembers = /* @__PURE__ */ new Set([
|
|
23
|
+
"tokens",
|
|
24
|
+
"theme",
|
|
25
|
+
"fonts",
|
|
26
|
+
"font",
|
|
27
|
+
"fontFamily"
|
|
28
|
+
]);
|
|
29
|
+
function propertyName(node) {
|
|
30
|
+
if (Node.isIdentifier(node) || Node.isPrivateIdentifier(node)) return node.getText();
|
|
31
|
+
if (Node.isStringLiteral(node) || Node.isNumericLiteral(node)) {
|
|
32
|
+
return node.getLiteralText();
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function renderNode(node, replacements) {
|
|
37
|
+
const start = node.getStart();
|
|
38
|
+
const end = node.getEnd();
|
|
39
|
+
const selected = [];
|
|
40
|
+
for (const replacement of [...replacements].sort((left, right) => right.end - right.start - (left.end - left.start))) {
|
|
41
|
+
if (replacement.start < start || replacement.end > end) continue;
|
|
42
|
+
if (selected.some((current) => replacement.start < current.end && replacement.end > current.start)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
selected.push(replacement);
|
|
46
|
+
}
|
|
47
|
+
let text = node.getText();
|
|
48
|
+
for (const replacement of selected.sort((left, right) => right.start - left.start)) {
|
|
49
|
+
const relativeStart = replacement.start - start;
|
|
50
|
+
const relativeEnd = replacement.end - start;
|
|
51
|
+
text = `${text.slice(0, relativeStart)}${replacement.text}${text.slice(relativeEnd)}`;
|
|
52
|
+
}
|
|
53
|
+
return text;
|
|
54
|
+
}
|
|
55
|
+
function referencesWithin(node, definition) {
|
|
56
|
+
return definition.findReferencesAsNodes().filter((reference) => reference.getStart() >= node.getStart() && reference.getEnd() <= node.getEnd());
|
|
57
|
+
}
|
|
58
|
+
function renderObjectReturn(expression, replacements) {
|
|
59
|
+
let current = expression;
|
|
60
|
+
while (Node.isParenthesizedExpression(current)) current = current.getExpression();
|
|
61
|
+
return renderNode(Node.isAsExpression(current) || Node.isTypeAssertion(current) ? expression : unwrapExpression(expression), replacements);
|
|
62
|
+
}
|
|
63
|
+
function callbackAnalysis(callback) {
|
|
64
|
+
const body = callback.getBody();
|
|
65
|
+
const parameters = callback.getParameters();
|
|
66
|
+
const firstNameNode = parameters[0]?.getNameNode();
|
|
67
|
+
const firstName = Node.isIdentifier(firstNameNode) ? firstNameNode.getText() : null;
|
|
68
|
+
const secondNameNode = parameters[1]?.getNameNode();
|
|
69
|
+
const renderedReplacements = [];
|
|
70
|
+
const normalizedReplacements = [];
|
|
71
|
+
const draftReplacements = [];
|
|
72
|
+
const unsupportedExtras = /* @__PURE__ */ new Set();
|
|
73
|
+
let propsLine = null;
|
|
74
|
+
let usesEnv = false;
|
|
75
|
+
if (firstNameNode && Node.isIdentifier(firstNameNode)) {
|
|
76
|
+
for (const reference of referencesWithin(body, firstNameNode)) {
|
|
77
|
+
normalizedReplacements.push({
|
|
78
|
+
start: reference.getStart(),
|
|
79
|
+
end: reference.getEnd(),
|
|
80
|
+
text: "value"
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (secondNameNode && Node.isIdentifier(secondNameNode)) {
|
|
85
|
+
const references = referencesWithin(body, secondNameNode);
|
|
86
|
+
usesEnv = references.length > 0;
|
|
87
|
+
const otherSameName = body.getDescendantsOfKind(SyntaxKind.Identifier).some((identifier) => identifier.getText() === secondNameNode.getText() && !references.some((reference) => reference.getStart() === identifier.getStart() && reference.getEnd() === identifier.getEnd()));
|
|
88
|
+
const envNameExists = body.getDescendantsOfKind(SyntaxKind.Identifier).some((identifier) => identifier.getText() === "env");
|
|
89
|
+
if (secondNameNode.getText() !== "env" && !otherSameName && !envNameExists) {
|
|
90
|
+
renderedReplacements.push({
|
|
91
|
+
start: secondNameNode.getStart(),
|
|
92
|
+
end: secondNameNode.getEnd(),
|
|
93
|
+
text: "env"
|
|
94
|
+
});
|
|
95
|
+
for (const reference of references) {
|
|
96
|
+
renderedReplacements.push({
|
|
97
|
+
start: reference.getStart(),
|
|
98
|
+
end: reference.getEnd(),
|
|
99
|
+
text: "env"
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
for (const reference of references) {
|
|
104
|
+
normalizedReplacements.push({
|
|
105
|
+
start: reference.getStart(),
|
|
106
|
+
end: reference.getEnd(),
|
|
107
|
+
text: "env"
|
|
108
|
+
});
|
|
109
|
+
draftReplacements.push({
|
|
110
|
+
start: reference.getStart(),
|
|
111
|
+
end: reference.getEnd(),
|
|
112
|
+
text: "env"
|
|
113
|
+
});
|
|
114
|
+
const parent = reference.getParent();
|
|
115
|
+
if (Node.isPropertyAccessExpression(parent) && parent.getExpression().getStart() === reference.getStart()) {
|
|
116
|
+
const member = parent.getName();
|
|
117
|
+
if (member === "props") {
|
|
118
|
+
propsLine ??= callback.getSourceFile().getLineAndColumnAtPos(parent.getStart()).line;
|
|
119
|
+
draftReplacements.push({
|
|
120
|
+
start: parent.getStart(),
|
|
121
|
+
end: parent.getEnd(),
|
|
122
|
+
text: "props"
|
|
123
|
+
});
|
|
124
|
+
} else if (!envMembers.has(member)) {
|
|
125
|
+
unsupportedExtras.add(member);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (Node.isElementAccessExpression(parent) && parent.getExpression().getStart() === reference.getStart()) {
|
|
129
|
+
const argument = parent.getArgumentExpression();
|
|
130
|
+
const member = argument && Node.isStringLiteral(argument) ? argument.getLiteralValue() : null;
|
|
131
|
+
if (member === "props") {
|
|
132
|
+
propsLine ??= callback.getSourceFile().getLineAndColumnAtPos(parent.getStart()).line;
|
|
133
|
+
draftReplacements.push({
|
|
134
|
+
start: parent.getStart(),
|
|
135
|
+
end: parent.getEnd(),
|
|
136
|
+
text: "props"
|
|
137
|
+
});
|
|
138
|
+
} else if (member === null || !envMembers.has(member)) {
|
|
139
|
+
unsupportedExtras.add(member ?? parent.getText());
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
} else if (secondNameNode && Node.isObjectBindingPattern(secondNameNode)) {
|
|
144
|
+
for (const element of secondNameNode.getElements()) {
|
|
145
|
+
const bindingName = element.getNameNode();
|
|
146
|
+
const sourceName = propertyName(element.getPropertyNameNode() ?? bindingName);
|
|
147
|
+
if (!sourceName || !Node.isIdentifier(bindingName)) {
|
|
148
|
+
unsupportedExtras.add(element.getText());
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (element.getDotDotDotToken()) {
|
|
152
|
+
unsupportedExtras.add(element.getText());
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const references = referencesWithin(body, bindingName);
|
|
156
|
+
if (sourceName === "props") {
|
|
157
|
+
propsLine ??= callback.getSourceFile().getLineAndColumnAtPos(element.getStart()).line;
|
|
158
|
+
for (const reference of references) {
|
|
159
|
+
draftReplacements.push({
|
|
160
|
+
start: reference.getStart(),
|
|
161
|
+
end: reference.getEnd(),
|
|
162
|
+
text: "props"
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (!envMembers.has(sourceName)) {
|
|
168
|
+
unsupportedExtras.add(sourceName);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (references.length) usesEnv = true;
|
|
172
|
+
for (const reference of references) {
|
|
173
|
+
normalizedReplacements.push({
|
|
174
|
+
start: reference.getStart(),
|
|
175
|
+
end: reference.getEnd(),
|
|
176
|
+
text: `env.${sourceName}`
|
|
177
|
+
});
|
|
178
|
+
draftReplacements.push({
|
|
179
|
+
start: reference.getStart(),
|
|
180
|
+
end: reference.getEnd(),
|
|
181
|
+
text: `env.${sourceName}`
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
} else if (secondNameNode) {
|
|
186
|
+
unsupportedExtras.add(secondNameNode.getText());
|
|
187
|
+
}
|
|
188
|
+
const normalizedBody = firstNameNode && !Node.isIdentifier(firstNameNode) ? null : renderNode(body, normalizedReplacements);
|
|
189
|
+
const draftBody = firstNameNode && !Node.isIdentifier(firstNameNode) ? null : renderNode(body, draftReplacements);
|
|
190
|
+
let objectReturn = null;
|
|
191
|
+
const unwrappedBody = Node.isExpression(body) ? unwrapExpression(body) : body;
|
|
192
|
+
if (Node.isExpression(body) && Node.isObjectLiteralExpression(unwrappedBody)) {
|
|
193
|
+
objectReturn = renderObjectReturn(body, normalizedReplacements);
|
|
194
|
+
} else if (Node.isBlock(body)) {
|
|
195
|
+
const statements = body.getStatements();
|
|
196
|
+
if (statements.length === 1 && Node.isReturnStatement(statements[0])) {
|
|
197
|
+
const returned = statements[0].getExpression();
|
|
198
|
+
if (returned) {
|
|
199
|
+
const unwrapped = unwrapExpression(returned);
|
|
200
|
+
if (Node.isObjectLiteralExpression(unwrapped)) {
|
|
201
|
+
objectReturn = renderObjectReturn(returned, normalizedReplacements);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
callback,
|
|
208
|
+
firstName,
|
|
209
|
+
rendered: renderNode(callback, renderedReplacements),
|
|
210
|
+
normalizedBody,
|
|
211
|
+
objectReturn,
|
|
212
|
+
usesEnv,
|
|
213
|
+
propsLine,
|
|
214
|
+
draftBody,
|
|
215
|
+
unsupportedExtras: [...unsupportedExtras].sort()
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function styledImport(sourceFile) {
|
|
219
|
+
for (const declaration of sourceFile.getImportDeclarations()) {
|
|
220
|
+
const module = declaration.getModuleSpecifierValue();
|
|
221
|
+
if (module !== "tamagui" && module !== "@tamagui/core") continue;
|
|
222
|
+
if (declaration.getNamedImports().some((specifier) => {
|
|
223
|
+
const localName = specifier.getAliasNode()?.getText() ?? specifier.getName();
|
|
224
|
+
return specifier.getName() === "styled" && localName === "styled";
|
|
225
|
+
})) {
|
|
226
|
+
return declaration;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
function typeReference(sourceFile, declaration, typeName) {
|
|
232
|
+
const module = declaration.getModuleSpecifierValue();
|
|
233
|
+
for (const current of sourceFile.getImportDeclarations()) {
|
|
234
|
+
if (current.getModuleSpecifierValue() !== module) continue;
|
|
235
|
+
const existing = current.getNamedImports().find((specifier) => specifier.getName() === typeName);
|
|
236
|
+
if (existing) {
|
|
237
|
+
return {
|
|
238
|
+
localName: existing.getAliasNode()?.getText() ?? existing.getName(),
|
|
239
|
+
required: null
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
let localName = typeName;
|
|
244
|
+
if (sourceFile.getLocal(localName)) {
|
|
245
|
+
localName = `Tamagui${typeName}`;
|
|
246
|
+
let suffix = 2;
|
|
247
|
+
while (sourceFile.getLocal(localName)) localName = `Tamagui${typeName}${suffix++}`;
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
localName,
|
|
251
|
+
required: {
|
|
252
|
+
module,
|
|
253
|
+
name: typeName,
|
|
254
|
+
localName
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function callbackFromProperty(property) {
|
|
259
|
+
if (!Node.isPropertyAssignment(property)) return null;
|
|
260
|
+
const initializer = unwrapExpression(property.getInitializerOrThrow());
|
|
261
|
+
return Node.isArrowFunction(initializer) || Node.isFunctionExpression(initializer) ? initializer : null;
|
|
262
|
+
}
|
|
263
|
+
function commentsBefore(properties) {
|
|
264
|
+
const comments = /* @__PURE__ */ new Map();
|
|
265
|
+
for (const property of properties) {
|
|
266
|
+
for (const range of property.getLeadingCommentRanges()) {
|
|
267
|
+
comments.set(range.getPos(), range.getText());
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return [...comments.entries()].sort((left, right) => left[0] - right[0]).map((entry) => entry[1]).join("\n");
|
|
271
|
+
}
|
|
272
|
+
function convertFunctionalVariants(config, label, write) {
|
|
273
|
+
const sites = [];
|
|
274
|
+
const requiredTypeImports = [];
|
|
275
|
+
const variantsProperty = config.getProperty("variants");
|
|
276
|
+
if (!Node.isPropertyAssignment(variantsProperty)) {
|
|
277
|
+
return {
|
|
278
|
+
sites,
|
|
279
|
+
requiredTypeImports
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
const variants = unwrapExpression(variantsProperty.getInitializerOrThrow());
|
|
283
|
+
if (!Node.isObjectLiteralExpression(variants)) return {
|
|
284
|
+
sites,
|
|
285
|
+
requiredTypeImports
|
|
286
|
+
};
|
|
287
|
+
const sourceFile = config.getSourceFile();
|
|
288
|
+
const importDeclaration = styledImport(sourceFile);
|
|
289
|
+
for (const variant of variants.getProperties()) {
|
|
290
|
+
if (!Node.isPropertyAssignment(variant)) continue;
|
|
291
|
+
const variantName = propertyName(variant.getNameNode());
|
|
292
|
+
if (!variantName) continue;
|
|
293
|
+
const initializer = unwrapExpression(variant.getInitializerOrThrow());
|
|
294
|
+
if (!Node.isObjectLiteralExpression(initializer)) continue;
|
|
295
|
+
const functional = initializer.getProperties().flatMap((property) => {
|
|
296
|
+
if (!("getNameNode" in property)) return [];
|
|
297
|
+
const name = propertyName(property.getNameNode());
|
|
298
|
+
return name && (name === "..." || name.startsWith("...") || name.startsWith(":")) ? [{
|
|
299
|
+
name,
|
|
300
|
+
property
|
|
301
|
+
}] : [];
|
|
302
|
+
});
|
|
303
|
+
if (!functional.length) continue;
|
|
304
|
+
const flags = [];
|
|
305
|
+
const notes = [];
|
|
306
|
+
const line = sourceFile.getLineAndColumnAtPos(functional[0].property.getStart()).line;
|
|
307
|
+
const before = variant.getText();
|
|
308
|
+
const exact = initializer.getProperties().filter((property) => !functional.some((entry) => entry.property === property));
|
|
309
|
+
const callbacks = functional.map((entry) => callbackFromProperty(entry.property));
|
|
310
|
+
const analyses = callbacks.map((callback) => callback ? callbackAnalysis(callback) : null);
|
|
311
|
+
let after = before;
|
|
312
|
+
let draft = null;
|
|
313
|
+
let dynamicText = null;
|
|
314
|
+
let requiredImport = null;
|
|
315
|
+
if (exact.length) {
|
|
316
|
+
flags.push({
|
|
317
|
+
code: "functional-variant-mixed",
|
|
318
|
+
detail: `variant "${variantName}" combines exact branches with a function key; v3 has no mixed variant form`
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
if (functional.some((entry) => entry.name === "...")) {
|
|
322
|
+
flags.push({
|
|
323
|
+
code: "functional-variant-catch-all",
|
|
324
|
+
detail: `choose the value type and replace this catch-all with styled.dynamic<YourValue>(...); unknown would erase the prop contract`
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
if (callbacks.some((callback) => callback === null)) {
|
|
328
|
+
flags.push({
|
|
329
|
+
code: "functional-variant-unsupported",
|
|
330
|
+
detail: `variant "${variantName}" uses a function key whose value is not an inline arrow or function expression`
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
if (callbacks.some((callback) => callback && (callback.getParameters().length > 2 || callback.isAsync() || Node.isFunctionExpression(callback) && callback.isGenerator()))) {
|
|
334
|
+
flags.push({
|
|
335
|
+
code: "functional-variant-unsupported",
|
|
336
|
+
detail: `variant "${variantName}" uses an async, generator, or three-parameter callback`
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
if (analyses.some((analysis) => analysis?.firstName === null)) {
|
|
340
|
+
flags.push({
|
|
341
|
+
code: "functional-variant-unsupported",
|
|
342
|
+
detail: `variant "${variantName}" destructures its value parameter; migrate that callback by hand`
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
const unsupportedExtras = [...new Set(analyses.flatMap((analysis) => analysis?.unsupportedExtras ?? []))];
|
|
346
|
+
if (unsupportedExtras.length) {
|
|
347
|
+
flags.push({
|
|
348
|
+
code: "functional-variant-unsupported-extras",
|
|
349
|
+
detail: `v3 env has no ${unsupportedExtras.map((name) => `"${name}"`).join(", ")} member`
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
const propsAnalysis = analyses.find((analysis) => analysis?.propsLine != null);
|
|
353
|
+
if (propsAnalysis) {
|
|
354
|
+
const analysis = propsAnalysis;
|
|
355
|
+
const valueName = analysis.firstName ?? "value";
|
|
356
|
+
const propAccess = /^[A-Za-z_$][\w$]*$/.test(variantName) ? `props.${variantName}` : `props[${JSON.stringify(variantName)}]`;
|
|
357
|
+
const body = analysis.draftBody;
|
|
358
|
+
if (body) {
|
|
359
|
+
const statements = Node.isBlock(analysis.callback.getBody()) ? body.slice(1, -1).trim() : `return ${body}`;
|
|
360
|
+
draft = `${variantName}: styled.dynamic<${spreadTypes.get(functional[0].name) ?? typeKeys.get(functional[0].name) ?? "YourValue"}>()
|
|
361
|
+
|
|
362
|
+
.resolve((props, env) => {
|
|
363
|
+
const ${valueName} = ${propAccess}
|
|
364
|
+
${statements.split("\n").map((statement) => ` ${statement}`).join("\n")}
|
|
365
|
+
})`;
|
|
366
|
+
}
|
|
367
|
+
flags.push({
|
|
368
|
+
code: "functional-variant-needs-resolve",
|
|
369
|
+
detail: `line ${analysis.propsLine} reads sibling props; declare the consumed prop with styled.dynamic<T>() and adapt the generated .resolve draft`
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
const allTypeKeys = functional.every((entry) => typeKeys.has(entry.name));
|
|
373
|
+
const oneSpread = functional.length === 1 && spreadTypes.has(functional[0].name);
|
|
374
|
+
if (new Set(functional.map((entry) => entry.name)).size !== functional.length) {
|
|
375
|
+
flags.push({
|
|
376
|
+
code: "functional-variant-unsupported",
|
|
377
|
+
detail: `variant "${variantName}" repeats a function key`
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
if (!functional.some((entry) => entry.name === "...") && !allTypeKeys && !oneSpread) {
|
|
381
|
+
flags.push({
|
|
382
|
+
code: "functional-variant-unsupported",
|
|
383
|
+
detail: `variant "${variantName}" uses unsupported functional keys ${functional.map((entry) => `"${entry.name}"`).join(", ")}`
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
if (!flags.length && oneSpread) {
|
|
387
|
+
if (!importDeclaration) {
|
|
388
|
+
flags.push({
|
|
389
|
+
code: "functional-variant-styled-import",
|
|
390
|
+
detail: `the file does not import styled directly from "tamagui" or "@tamagui/core", so the token type source is not provable`
|
|
391
|
+
});
|
|
392
|
+
} else {
|
|
393
|
+
const typeName = spreadTypes.get(functional[0].name);
|
|
394
|
+
const reference = typeReference(sourceFile, importDeclaration, typeName);
|
|
395
|
+
requiredImport = reference.required;
|
|
396
|
+
dynamicText = `styled.dynamic<${reference.localName}>(${analyses[0].rendered})`;
|
|
397
|
+
notes.push(`uses ${reference.localName} from ${importDeclaration.getModuleSpecifierValue()}`);
|
|
398
|
+
}
|
|
399
|
+
} else if (!flags.length && allTypeKeys) {
|
|
400
|
+
const present = new Set(functional.map((entry) => typeKeys.get(entry.name)));
|
|
401
|
+
const union = typeOrder.filter((type) => present.has(type)).join(" | ");
|
|
402
|
+
if (functional.length === 1) {
|
|
403
|
+
dynamicText = `styled.dynamic<${union}>(${analyses[0].rendered})`;
|
|
404
|
+
} else {
|
|
405
|
+
const normalizedBodies = analyses.map((analysis) => analysis.normalizedBody);
|
|
406
|
+
const sameBody = normalizedBodies.every((body) => body === normalizedBodies[0]);
|
|
407
|
+
const envParameter = analyses.some((analysis) => analysis.usesEnv) ? ", env" : "";
|
|
408
|
+
if (sameBody) {
|
|
409
|
+
dynamicText = `styled.dynamic<${union}>((value${envParameter}) => ${normalizedBodies[0]})`;
|
|
410
|
+
} else if (analyses.every((analysis) => analysis.objectReturn !== null)) {
|
|
411
|
+
const byType = new Map(functional.map((entry, index) => [typeKeys.get(entry.name), analyses[index].objectReturn]));
|
|
412
|
+
const ordered = typeOrder.filter((type) => byType.has(type));
|
|
413
|
+
const branches = ordered.map((type, index) => index === ordered.length - 1 ? `return ${byType.get(type)}` : `if (typeof value === '${type}') return ${byType.get(type)}`);
|
|
414
|
+
dynamicText = `styled.dynamic<${union}>((value${envParameter}) => {
|
|
415
|
+
${branches.map((branch) => ` ${branch}`).join("\n")}
|
|
416
|
+
})`;
|
|
417
|
+
} else {
|
|
418
|
+
flags.push({
|
|
419
|
+
code: "functional-variant-type-bodies",
|
|
420
|
+
detail: `variant "${variantName}" has different type-key bodies; automatic typeof branches require each body to be one object-literal return`
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (dynamicText && !flags.length) {
|
|
426
|
+
const comments = commentsBefore(functional.map((entry) => entry.property));
|
|
427
|
+
const replacement = comments ? `${comments}
|
|
428
|
+
${dynamicText}` : dynamicText;
|
|
429
|
+
after = `${variant.getNameNode().getText()}: ${replacement}`;
|
|
430
|
+
if (requiredImport) requiredTypeImports.push(requiredImport);
|
|
431
|
+
if (write) variant.setInitializer(replacement);
|
|
432
|
+
}
|
|
433
|
+
sites.push({
|
|
434
|
+
label: `${label} variants.${variantName}`,
|
|
435
|
+
line,
|
|
436
|
+
before,
|
|
437
|
+
after,
|
|
438
|
+
converted: flags.length === 0,
|
|
439
|
+
flags,
|
|
440
|
+
draft,
|
|
441
|
+
notes
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
sites,
|
|
446
|
+
requiredTypeImports
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
function addFunctionalVariantTypeImports(sourceFile, imports) {
|
|
450
|
+
const seen = /* @__PURE__ */ new Set();
|
|
451
|
+
for (const required of imports) {
|
|
452
|
+
const key = `${required.module}:${required.name}:${required.localName}`;
|
|
453
|
+
if (seen.has(key)) continue;
|
|
454
|
+
seen.add(key);
|
|
455
|
+
const declaration = sourceFile.getImportDeclarations().find((current) => current.getModuleSpecifierValue() === required.module);
|
|
456
|
+
if (!declaration) continue;
|
|
457
|
+
if (sourceFile.getImportDeclarations().some((current) => current.getModuleSpecifierValue() === required.module && current.getNamedImports().some((specifier) => specifier.getName() === required.name))) {
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
declaration.addNamedImport({
|
|
461
|
+
name: required.name,
|
|
462
|
+
alias: required.localName === required.name ? void 0 : required.localName,
|
|
463
|
+
isTypeOnly: !declaration.isTypeOnly()
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export { addFunctionalVariantTypeImports, convertFunctionalVariants };
|
|
469
|
+
//# sourceMappingURL=functionalVariants.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functionalVariants.js","names":[],"sources":["functionalVariants.js"],"sourcesContent":["import {\n Node,\n SyntaxKind\n} from \"ts-morph\";\nimport { unwrapExpression } from \"./expressions\";\nconst spreadTypes = /* @__PURE__ */ new Map([\n [\"...size\", \"SizeTokens\"],\n [\"...space\", \"SpaceTokens\"],\n [\"...color\", \"ColorTokens\"],\n [\"...radius\", \"RadiusTokens\"],\n [\"...fontSize\", \"FontSizeTokens\"],\n [\"...zIndex\", \"ZIndexTokens\"]\n]);\nconst typeKeys = /* @__PURE__ */ new Map([\n [\":number\", \"number\"],\n [\":string\", \"string\"],\n [\":boolean\", \"boolean\"]\n]);\nconst typeOrder = [\"number\", \"string\", \"boolean\"];\nconst envMembers = /* @__PURE__ */ new Set([\"tokens\", \"theme\", \"fonts\", \"font\", \"fontFamily\"]);\nfunction propertyName(node) {\n if (Node.isIdentifier(node) || Node.isPrivateIdentifier(node)) return node.getText();\n if (Node.isStringLiteral(node) || Node.isNumericLiteral(node)) {\n return node.getLiteralText();\n }\n return null;\n}\nfunction renderNode(node, replacements) {\n const start = node.getStart();\n const end = node.getEnd();\n const selected = [];\n for (const replacement of [...replacements].sort(\n (left, right) => right.end - right.start - (left.end - left.start)\n )) {\n if (replacement.start < start || replacement.end > end) continue;\n if (selected.some(\n (current) => replacement.start < current.end && replacement.end > current.start\n )) {\n continue;\n }\n selected.push(replacement);\n }\n let text = node.getText();\n for (const replacement of selected.sort((left, right) => right.start - left.start)) {\n const relativeStart = replacement.start - start;\n const relativeEnd = replacement.end - start;\n text = `${text.slice(0, relativeStart)}${replacement.text}${text.slice(relativeEnd)}`;\n }\n return text;\n}\nfunction referencesWithin(node, definition) {\n return definition.findReferencesAsNodes().filter(\n (reference) => reference.getStart() >= node.getStart() && reference.getEnd() <= node.getEnd()\n );\n}\nfunction renderObjectReturn(expression, replacements) {\n let current = expression;\n while (Node.isParenthesizedExpression(current)) current = current.getExpression();\n return renderNode(\n Node.isAsExpression(current) || Node.isTypeAssertion(current) ? expression : unwrapExpression(expression),\n replacements\n );\n}\nfunction callbackAnalysis(callback) {\n const body = callback.getBody();\n const parameters = callback.getParameters();\n const firstNameNode = parameters[0]?.getNameNode();\n const firstName = Node.isIdentifier(firstNameNode) ? firstNameNode.getText() : null;\n const secondNameNode = parameters[1]?.getNameNode();\n const renderedReplacements = [];\n const normalizedReplacements = [];\n const draftReplacements = [];\n const unsupportedExtras = /* @__PURE__ */ new Set();\n let propsLine = null;\n let usesEnv = false;\n if (firstNameNode && Node.isIdentifier(firstNameNode)) {\n for (const reference of referencesWithin(body, firstNameNode)) {\n normalizedReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: \"value\"\n });\n }\n }\n if (secondNameNode && Node.isIdentifier(secondNameNode)) {\n const references = referencesWithin(body, secondNameNode);\n usesEnv = references.length > 0;\n const otherSameName = body.getDescendantsOfKind(SyntaxKind.Identifier).some(\n (identifier) => identifier.getText() === secondNameNode.getText() && !references.some(\n (reference) => reference.getStart() === identifier.getStart() && reference.getEnd() === identifier.getEnd()\n )\n );\n const envNameExists = body.getDescendantsOfKind(SyntaxKind.Identifier).some((identifier) => identifier.getText() === \"env\");\n if (secondNameNode.getText() !== \"env\" && !otherSameName && !envNameExists) {\n renderedReplacements.push({\n start: secondNameNode.getStart(),\n end: secondNameNode.getEnd(),\n text: \"env\"\n });\n for (const reference of references) {\n renderedReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: \"env\"\n });\n }\n }\n for (const reference of references) {\n normalizedReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: \"env\"\n });\n draftReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: \"env\"\n });\n const parent = reference.getParent();\n if (Node.isPropertyAccessExpression(parent) && parent.getExpression().getStart() === reference.getStart()) {\n const member = parent.getName();\n if (member === \"props\") {\n propsLine ??= callback.getSourceFile().getLineAndColumnAtPos(parent.getStart()).line;\n draftReplacements.push({\n start: parent.getStart(),\n end: parent.getEnd(),\n text: \"props\"\n });\n } else if (!envMembers.has(member)) {\n unsupportedExtras.add(member);\n }\n }\n if (Node.isElementAccessExpression(parent) && parent.getExpression().getStart() === reference.getStart()) {\n const argument = parent.getArgumentExpression();\n const member = argument && Node.isStringLiteral(argument) ? argument.getLiteralValue() : null;\n if (member === \"props\") {\n propsLine ??= callback.getSourceFile().getLineAndColumnAtPos(parent.getStart()).line;\n draftReplacements.push({\n start: parent.getStart(),\n end: parent.getEnd(),\n text: \"props\"\n });\n } else if (member === null || !envMembers.has(member)) {\n unsupportedExtras.add(member ?? parent.getText());\n }\n }\n }\n } else if (secondNameNode && Node.isObjectBindingPattern(secondNameNode)) {\n for (const element of secondNameNode.getElements()) {\n const bindingName = element.getNameNode();\n const sourceName = propertyName(element.getPropertyNameNode() ?? bindingName);\n if (!sourceName || !Node.isIdentifier(bindingName)) {\n unsupportedExtras.add(element.getText());\n continue;\n }\n if (element.getDotDotDotToken()) {\n unsupportedExtras.add(element.getText());\n continue;\n }\n const references = referencesWithin(body, bindingName);\n if (sourceName === \"props\") {\n propsLine ??= callback.getSourceFile().getLineAndColumnAtPos(element.getStart()).line;\n for (const reference of references) {\n draftReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: \"props\"\n });\n }\n continue;\n }\n if (!envMembers.has(sourceName)) {\n unsupportedExtras.add(sourceName);\n continue;\n }\n if (references.length) usesEnv = true;\n for (const reference of references) {\n normalizedReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: `env.${sourceName}`\n });\n draftReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: `env.${sourceName}`\n });\n }\n }\n } else if (secondNameNode) {\n unsupportedExtras.add(secondNameNode.getText());\n }\n const normalizedBody = firstNameNode && !Node.isIdentifier(firstNameNode) ? null : renderNode(body, normalizedReplacements);\n const draftBody = firstNameNode && !Node.isIdentifier(firstNameNode) ? null : renderNode(body, draftReplacements);\n let objectReturn = null;\n const unwrappedBody = Node.isExpression(body) ? unwrapExpression(body) : body;\n if (Node.isExpression(body) && Node.isObjectLiteralExpression(unwrappedBody)) {\n objectReturn = renderObjectReturn(body, normalizedReplacements);\n } else if (Node.isBlock(body)) {\n const statements = body.getStatements();\n if (statements.length === 1 && Node.isReturnStatement(statements[0])) {\n const returned = statements[0].getExpression();\n if (returned) {\n const unwrapped = unwrapExpression(returned);\n if (Node.isObjectLiteralExpression(unwrapped)) {\n objectReturn = renderObjectReturn(returned, normalizedReplacements);\n }\n }\n }\n }\n return {\n callback,\n firstName,\n rendered: renderNode(callback, renderedReplacements),\n normalizedBody,\n objectReturn,\n usesEnv,\n propsLine,\n draftBody,\n unsupportedExtras: [...unsupportedExtras].sort()\n };\n}\nfunction styledImport(sourceFile) {\n for (const declaration of sourceFile.getImportDeclarations()) {\n const module = declaration.getModuleSpecifierValue();\n if (module !== \"tamagui\" && module !== \"@tamagui/core\") continue;\n if (declaration.getNamedImports().some((specifier) => {\n const localName = specifier.getAliasNode()?.getText() ?? specifier.getName();\n return specifier.getName() === \"styled\" && localName === \"styled\";\n })) {\n return declaration;\n }\n }\n return null;\n}\nfunction typeReference(sourceFile, declaration, typeName) {\n const module = declaration.getModuleSpecifierValue();\n for (const current of sourceFile.getImportDeclarations()) {\n if (current.getModuleSpecifierValue() !== module) continue;\n const existing = current.getNamedImports().find((specifier) => specifier.getName() === typeName);\n if (existing) {\n return {\n localName: existing.getAliasNode()?.getText() ?? existing.getName(),\n required: null\n };\n }\n }\n let localName = typeName;\n if (sourceFile.getLocal(localName)) {\n localName = `Tamagui${typeName}`;\n let suffix = 2;\n while (sourceFile.getLocal(localName)) localName = `Tamagui${typeName}${suffix++}`;\n }\n return { localName, required: { module, name: typeName, localName } };\n}\nfunction callbackFromProperty(property) {\n if (!Node.isPropertyAssignment(property)) return null;\n const initializer = unwrapExpression(property.getInitializerOrThrow());\n return Node.isArrowFunction(initializer) || Node.isFunctionExpression(initializer) ? initializer : null;\n}\nfunction commentsBefore(properties) {\n const comments = /* @__PURE__ */ new Map();\n for (const property of properties) {\n for (const range of property.getLeadingCommentRanges()) {\n comments.set(range.getPos(), range.getText());\n }\n }\n return [...comments.entries()].sort((left, right) => left[0] - right[0]).map((entry) => entry[1]).join(\"\\n\");\n}\nfunction convertFunctionalVariants(config, label, write) {\n const sites = [];\n const requiredTypeImports = [];\n const variantsProperty = config.getProperty(\"variants\");\n if (!Node.isPropertyAssignment(variantsProperty)) {\n return { sites, requiredTypeImports };\n }\n const variants = unwrapExpression(variantsProperty.getInitializerOrThrow());\n if (!Node.isObjectLiteralExpression(variants)) return { sites, requiredTypeImports };\n const sourceFile = config.getSourceFile();\n const importDeclaration = styledImport(sourceFile);\n for (const variant of variants.getProperties()) {\n if (!Node.isPropertyAssignment(variant)) continue;\n const variantName = propertyName(variant.getNameNode());\n if (!variantName) continue;\n const initializer = unwrapExpression(variant.getInitializerOrThrow());\n if (!Node.isObjectLiteralExpression(initializer)) continue;\n const functional = initializer.getProperties().flatMap((property) => {\n if (!(\"getNameNode\" in property)) return [];\n const name = propertyName(property.getNameNode());\n return name && (name === \"...\" || name.startsWith(\"...\") || name.startsWith(\":\")) ? [{ name, property }] : [];\n });\n if (!functional.length) continue;\n const flags = [];\n const notes = [];\n const line = sourceFile.getLineAndColumnAtPos(functional[0].property.getStart()).line;\n const before = variant.getText();\n const exact = initializer.getProperties().filter((property) => !functional.some((entry) => entry.property === property));\n const callbacks = functional.map((entry) => callbackFromProperty(entry.property));\n const analyses = callbacks.map(\n (callback) => callback ? callbackAnalysis(callback) : null\n );\n let after = before;\n let draft = null;\n let dynamicText = null;\n let requiredImport = null;\n if (exact.length) {\n flags.push({\n code: \"functional-variant-mixed\",\n detail: `variant \"${variantName}\" combines exact branches with a function key; v3 has no mixed variant form`\n });\n }\n if (functional.some((entry) => entry.name === \"...\")) {\n flags.push({\n code: \"functional-variant-catch-all\",\n detail: `choose the value type and replace this catch-all with styled.dynamic<YourValue>(...); unknown would erase the prop contract`\n });\n }\n if (callbacks.some((callback) => callback === null)) {\n flags.push({\n code: \"functional-variant-unsupported\",\n detail: `variant \"${variantName}\" uses a function key whose value is not an inline arrow or function expression`\n });\n }\n if (callbacks.some(\n (callback) => callback && (callback.getParameters().length > 2 || callback.isAsync() || Node.isFunctionExpression(callback) && callback.isGenerator())\n )) {\n flags.push({\n code: \"functional-variant-unsupported\",\n detail: `variant \"${variantName}\" uses an async, generator, or three-parameter callback`\n });\n }\n if (analyses.some((analysis) => analysis?.firstName === null)) {\n flags.push({\n code: \"functional-variant-unsupported\",\n detail: `variant \"${variantName}\" destructures its value parameter; migrate that callback by hand`\n });\n }\n const unsupportedExtras = [\n ...new Set(analyses.flatMap((analysis) => analysis?.unsupportedExtras ?? []))\n ];\n if (unsupportedExtras.length) {\n flags.push({\n code: \"functional-variant-unsupported-extras\",\n detail: `v3 env has no ${unsupportedExtras.map((name) => `\"${name}\"`).join(\", \")} member`\n });\n }\n const propsAnalysis = analyses.find((analysis) => analysis?.propsLine != null);\n if (propsAnalysis) {\n const analysis = propsAnalysis;\n const valueName = analysis.firstName ?? \"value\";\n const propAccess = /^[A-Za-z_$][\\w$]*$/.test(variantName) ? `props.${variantName}` : `props[${JSON.stringify(variantName)}]`;\n const body = analysis.draftBody;\n if (body) {\n const statements = Node.isBlock(analysis.callback.getBody()) ? body.slice(1, -1).trim() : `return ${body}`;\n draft = `${variantName}: styled.dynamic<${spreadTypes.get(functional[0].name) ?? typeKeys.get(functional[0].name) ?? \"YourValue\"}>()\n\n.resolve((props, env) => {\n const ${valueName} = ${propAccess}\n${statements.split(\"\\n\").map((statement) => ` ${statement}`).join(\"\\n\")}\n})`;\n }\n flags.push({\n code: \"functional-variant-needs-resolve\",\n detail: `line ${analysis.propsLine} reads sibling props; declare the consumed prop with styled.dynamic<T>() and adapt the generated .resolve draft`\n });\n }\n const allTypeKeys = functional.every((entry) => typeKeys.has(entry.name));\n const oneSpread = functional.length === 1 && spreadTypes.has(functional[0].name);\n if (new Set(functional.map((entry) => entry.name)).size !== functional.length) {\n flags.push({\n code: \"functional-variant-unsupported\",\n detail: `variant \"${variantName}\" repeats a function key`\n });\n }\n if (!functional.some((entry) => entry.name === \"...\") && !allTypeKeys && !oneSpread) {\n flags.push({\n code: \"functional-variant-unsupported\",\n detail: `variant \"${variantName}\" uses unsupported functional keys ${functional.map((entry) => `\"${entry.name}\"`).join(\", \")}`\n });\n }\n if (!flags.length && oneSpread) {\n if (!importDeclaration) {\n flags.push({\n code: \"functional-variant-styled-import\",\n detail: `the file does not import styled directly from \"tamagui\" or \"@tamagui/core\", so the token type source is not provable`\n });\n } else {\n const typeName = spreadTypes.get(functional[0].name);\n const reference = typeReference(sourceFile, importDeclaration, typeName);\n requiredImport = reference.required;\n dynamicText = `styled.dynamic<${reference.localName}>(${analyses[0].rendered})`;\n notes.push(\n `uses ${reference.localName} from ${importDeclaration.getModuleSpecifierValue()}`\n );\n }\n } else if (!flags.length && allTypeKeys) {\n const present = new Set(functional.map((entry) => typeKeys.get(entry.name)));\n const union = typeOrder.filter((type) => present.has(type)).join(\" | \");\n if (functional.length === 1) {\n dynamicText = `styled.dynamic<${union}>(${analyses[0].rendered})`;\n } else {\n const normalizedBodies = analyses.map((analysis) => analysis.normalizedBody);\n const sameBody = normalizedBodies.every((body) => body === normalizedBodies[0]);\n const envParameter = analyses.some((analysis) => analysis.usesEnv) ? \", env\" : \"\";\n if (sameBody) {\n dynamicText = `styled.dynamic<${union}>((value${envParameter}) => ${normalizedBodies[0]})`;\n } else if (analyses.every((analysis) => analysis.objectReturn !== null)) {\n const byType = new Map(\n functional.map((entry, index) => [\n typeKeys.get(entry.name),\n analyses[index].objectReturn\n ])\n );\n const ordered = typeOrder.filter((type) => byType.has(type));\n const branches = ordered.map(\n (type, index) => index === ordered.length - 1 ? `return ${byType.get(type)}` : `if (typeof value === '${type}') return ${byType.get(type)}`\n );\n dynamicText = `styled.dynamic<${union}>((value${envParameter}) => {\n${branches.map((branch) => ` ${branch}`).join(\"\\n\")}\n})`;\n } else {\n flags.push({\n code: \"functional-variant-type-bodies\",\n detail: `variant \"${variantName}\" has different type-key bodies; automatic typeof branches require each body to be one object-literal return`\n });\n }\n }\n }\n if (dynamicText && !flags.length) {\n const comments = commentsBefore(functional.map((entry) => entry.property));\n const replacement = comments ? `${comments}\n${dynamicText}` : dynamicText;\n after = `${variant.getNameNode().getText()}: ${replacement}`;\n if (requiredImport) requiredTypeImports.push(requiredImport);\n if (write) variant.setInitializer(replacement);\n }\n sites.push({\n label: `${label} variants.${variantName}`,\n line,\n before,\n after,\n converted: flags.length === 0,\n flags,\n draft,\n notes\n });\n }\n return { sites, requiredTypeImports };\n}\nfunction addFunctionalVariantTypeImports(sourceFile, imports) {\n const seen = /* @__PURE__ */ new Set();\n for (const required of imports) {\n const key = `${required.module}:${required.name}:${required.localName}`;\n if (seen.has(key)) continue;\n seen.add(key);\n const declaration = sourceFile.getImportDeclarations().find((current) => current.getModuleSpecifierValue() === required.module);\n if (!declaration) continue;\n if (sourceFile.getImportDeclarations().some(\n (current) => current.getModuleSpecifierValue() === required.module && current.getNamedImports().some((specifier) => specifier.getName() === required.name)\n )) {\n continue;\n }\n declaration.addNamedImport({\n name: required.name,\n alias: required.localName === required.name ? void 0 : required.localName,\n isTypeOnly: !declaration.isTypeOnly()\n });\n }\n}\nexport {\n addFunctionalVariantTypeImports,\n convertFunctionalVariants\n};\n//# sourceMappingURL=functionalVariants.js.map\n"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import { ModuleKind, ModuleResolutionKind, Node, Project, ScriptTarget, SyntaxKi
|
|
|
7
7
|
import { planContainers } from "./containers.mjs";
|
|
8
8
|
import { convertJsxSite, convertStyleObject } from "./convert.mjs";
|
|
9
9
|
import { compact, unwrapExpression } from "./expressions.mjs";
|
|
10
|
+
import { addFunctionalVariantTypeImports, convertFunctionalVariants } from "./functionalVariants.mjs";
|
|
10
11
|
import { codemodMediaNames, createModifierRegistry, grammarPlatformNames } from "./grammar.mjs";
|
|
11
12
|
import { createProvenance } from "./provenance.mjs";
|
|
12
13
|
import { renderReport } from "./report.mjs";
|
|
@@ -151,6 +152,19 @@ function variantSites(config, label, registry, containers, targets, host, write2
|
|
|
151
152
|
if (!Node.isPropertyAssignment(variant)) continue;
|
|
152
153
|
const variantName = compact(variant.getNameNode().getText());
|
|
153
154
|
const branches = unwrapExpression(variant.getInitializerOrThrow());
|
|
155
|
+
if (Node.isCallExpression(branches)) {
|
|
156
|
+
const callee = branches.getExpression();
|
|
157
|
+
if (Node.isPropertyAccessExpression(callee) && callee.getName() === "dynamic") {
|
|
158
|
+
const body = branches.getArguments()[0];
|
|
159
|
+
if (body && Node.isExpression(body)) {
|
|
160
|
+
for (const style of variantStyleObjects(body)) {
|
|
161
|
+
const site = convertStyleObject(style, "styled", `${label} variants.${variantName}`, registry, containers, targets, host, write2);
|
|
162
|
+
if (site) sites.push(site);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
154
168
|
if (!Node.isObjectLiteralExpression(branches)) continue;
|
|
155
169
|
for (const branch of branches.getProperties()) {
|
|
156
170
|
if (!Node.isPropertyAssignment(branch)) continue;
|
|
@@ -163,22 +177,6 @@ function variantSites(config, label, registry, containers, targets, host, write2
|
|
|
163
177
|
}
|
|
164
178
|
}
|
|
165
179
|
}
|
|
166
|
-
const compound = config.getProperty("compoundVariants");
|
|
167
|
-
if (Node.isPropertyAssignment(compound)) {
|
|
168
|
-
const array = unwrapExpression(compound.getInitializerOrThrow());
|
|
169
|
-
if (Node.isArrayLiteralExpression(array)) {
|
|
170
|
-
for (const [index, element] of array.getElements().entries()) {
|
|
171
|
-
const entry = unwrapExpression(element);
|
|
172
|
-
if (!Node.isObjectLiteralExpression(entry)) continue;
|
|
173
|
-
const style = entry.getProperty("style");
|
|
174
|
-
if (!Node.isPropertyAssignment(style)) continue;
|
|
175
|
-
for (const object of variantStyleObjects(style.getInitializerOrThrow())) {
|
|
176
|
-
const site = convertStyleObject(object, "styled", `${label} compoundVariants[${index}]`, registry, containers, targets, host, write2);
|
|
177
|
-
if (site) sites.push(site);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
180
|
return sites;
|
|
183
181
|
}
|
|
184
182
|
function conversionTargets(filePath) {
|
|
@@ -199,6 +197,8 @@ function inspectFile(sourceFile, registry, provenance2, write2) {
|
|
|
199
197
|
const containers = planContainers(sourceFile, registry);
|
|
200
198
|
const targets = conversionTargets(sourceFile.getFilePath());
|
|
201
199
|
const sites = [];
|
|
200
|
+
const functionalVariants = [];
|
|
201
|
+
const requiredTypeImports = [];
|
|
202
202
|
const styledCalls = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).filter((call) => provenance2.isTamaguiStyledCall(call)).sort((left, right) => right.getStart() - left.getStart());
|
|
203
203
|
const jsxOpenings = [...sourceFile.getDescendantsOfKind(SyntaxKind.JsxOpeningElement), ...sourceFile.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement)].filter((opening) => provenance2.isTamaguiElement(opening)).sort((left, right) => right.getStart() - left.getStart());
|
|
204
204
|
for (const opening of jsxOpenings) {
|
|
@@ -212,13 +212,19 @@ function inspectFile(sourceFile, registry, provenance2, write2) {
|
|
|
212
212
|
if (!Node.isObjectLiteralExpression(config)) continue;
|
|
213
213
|
const label = `styled(${compact(call.getArguments()[0]?.getText() ?? "unknown")}, \u2026)`;
|
|
214
214
|
sites.push(...variantSites(config, label, registry, containers, targets, host, write2));
|
|
215
|
+
const functional = convertFunctionalVariants(config, label, write2);
|
|
216
|
+
functionalVariants.push(...functional.sites);
|
|
217
|
+
requiredTypeImports.push(...functional.requiredTypeImports);
|
|
215
218
|
const site = convertStyleObject(config, "styled", label, registry, containers, targets, host, write2);
|
|
216
219
|
if (site) sites.push(site);
|
|
217
220
|
}
|
|
218
221
|
sites.sort((left, right) => left.line - right.line || left.label.localeCompare(right.label));
|
|
222
|
+
functionalVariants.sort((left, right) => left.line - right.line || left.label.localeCompare(right.label));
|
|
223
|
+
if (write2) addFunctionalVariantTypeImports(sourceFile, requiredTypeImports);
|
|
219
224
|
return {
|
|
220
225
|
file: relative(projectRoot, sourceFile.getFilePath()),
|
|
221
|
-
sites
|
|
226
|
+
sites,
|
|
227
|
+
functionalVariants
|
|
222
228
|
};
|
|
223
229
|
}
|
|
224
230
|
const usage = `Converts Tamagui style syntax to V3 flat property values and reports what it cannot convert.
|
|
@@ -337,6 +343,6 @@ if (write) {
|
|
|
337
343
|
}
|
|
338
344
|
console.log(`wrote ${reportPath}`);
|
|
339
345
|
if (write) console.log(`rewrote ${written} source files`);
|
|
340
|
-
console.log(`${summary.sites} sites: ${summary.clean - summary.waiting} clean, ${summary.needsRelocation} need relocation, ${summary.unknownHost} unknown host, ${summary.ineligible} ineligible, ${summary.waiting} waiting on runtime support, ${summary.flagged} syntax-flagged; ${summary.ignoredFiles} source files ignored`);
|
|
346
|
+
console.log(`${summary.sites} style sites: ${summary.clean - summary.waiting} clean, ${summary.needsRelocation} need relocation, ${summary.unknownHost} unknown host, ${summary.ineligible} ineligible, ${summary.waiting} waiting on runtime support, ${summary.flagged} syntax-flagged; ${summary.functionalVariantSites} functional variants: ${summary.functionalVariantConverted} automatic, ${summary.functionalVariantFlagged} flagged; ${summary.ignoredFiles} source files ignored`);
|
|
341
347
|
|
|
342
348
|
//# sourceMappingURL=index.mjs.map
|