@typestyles/migrate 0.5.2 → 0.5.4

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.
@@ -0,0 +1,728 @@
1
+ #!/usr/bin/env node
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let _babel_parser = require("@babel/parser");
25
+ let _babel_generator = require("@babel/generator");
26
+ _babel_generator = __toESM(_babel_generator, 1);
27
+ let _babel_traverse = require("@babel/traverse");
28
+ _babel_traverse = __toESM(_babel_traverse, 1);
29
+ let _babel_types = require("@babel/types");
30
+ _babel_types = __toESM(_babel_types, 1);
31
+ let postcss = require("postcss");
32
+ postcss = __toESM(postcss, 1);
33
+ let node_fs_promises = require("node:fs/promises");
34
+ let node_path = require("node:path");
35
+ let diff = require("diff");
36
+ let fast_glob = require("fast-glob");
37
+ fast_glob = __toESM(fast_glob, 1);
38
+ let picomatch = require("picomatch");
39
+ picomatch = __toESM(picomatch, 1);
40
+ //#region src/css.ts
41
+ function camelCaseProperty$1(property) {
42
+ return property.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
43
+ }
44
+ function numberNode(n) {
45
+ return n < 0 ? _babel_types.unaryExpression("-", _babel_types.numericLiteral(-n)) : _babel_types.numericLiteral(n);
46
+ }
47
+ function toValueNode(value, varReplacements) {
48
+ const trimmed = value.trim();
49
+ if (varReplacements?.has(trimmed)) return varReplacements.get(trimmed);
50
+ if (/^-?\d+(\.\d+)?$/.test(trimmed)) return numberNode(Number(trimmed));
51
+ return _babel_types.stringLiteral(trimmed);
52
+ }
53
+ function toKeyNode$1(key) {
54
+ if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) return _babel_types.identifier(key);
55
+ return _babel_types.stringLiteral(key);
56
+ }
57
+ function nodesToObject(nodes, warnings, varReplacements) {
58
+ const properties = [];
59
+ for (const node of nodes ?? []) {
60
+ if (node.type === "decl") {
61
+ const normalized = node.prop.startsWith("--") ? node.prop : camelCaseProperty$1(node.prop);
62
+ properties.push(_babel_types.objectProperty(toKeyNode$1(normalized), toValueNode(node.value, varReplacements)));
63
+ continue;
64
+ }
65
+ if (node.type === "rule") {
66
+ const nested = nodesToObject(node.nodes, warnings, varReplacements);
67
+ properties.push(_babel_types.objectProperty(_babel_types.stringLiteral(node.selector.trim()), nested));
68
+ continue;
69
+ }
70
+ if (node.type === "atrule") {
71
+ const nested = nodesToObject(node.nodes, warnings, varReplacements);
72
+ const atRuleKey = `@${node.name}${node.params ? ` ${node.params}` : ""}`;
73
+ properties.push(_babel_types.objectProperty(_babel_types.stringLiteral(atRuleKey), nested));
74
+ continue;
75
+ }
76
+ warnings.push({ message: `Unsupported CSS node "${node.type}" skipped.` });
77
+ }
78
+ return _babel_types.objectExpression(properties);
79
+ }
80
+ function cssToObjectExpression(cssText, warnings, varReplacements) {
81
+ try {
82
+ return nodesToObject(postcss.default.parse(cssText).nodes, warnings, varReplacements);
83
+ } catch (error) {
84
+ warnings.push({ message: `Could not parse CSS template literal: ${error.message}` });
85
+ return null;
86
+ }
87
+ }
88
+ //#endregion
89
+ //#region src/interpolations.ts
90
+ const PLACEHOLDER_PREFIX = "__ts_migrate_var_";
91
+ function camelCaseProperty(property) {
92
+ return property.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
93
+ }
94
+ function placeholderToken(index) {
95
+ return `${PLACEHOLDER_PREFIX}${index}__`;
96
+ }
97
+ function extractSuffixFromQuasi(quasiText) {
98
+ return quasiText.match(/^([^;\n]*)/)?.[1] ?? "";
99
+ }
100
+ function literalToCssValue(node) {
101
+ if (_babel_types.isStringLiteral(node)) return node.value;
102
+ if (_babel_types.isNumericLiteral(node)) return String(node.value);
103
+ return null;
104
+ }
105
+ function unwrapExpression(expression) {
106
+ if (_babel_types.isParenthesizedExpression(expression)) return unwrapExpression(expression.expression);
107
+ return expression;
108
+ }
109
+ function extractCssPropertyBeforeInterpolation(quasiText) {
110
+ return quasiText.match(/([a-zA-Z-]+)\s*:\s*$/)?.[1] ?? null;
111
+ }
112
+ function stripTrailingPropertyDeclaration(quasiText) {
113
+ return quasiText.replace(/[a-zA-Z-]+\s*:\s*$/, "");
114
+ }
115
+ function stripLeadingDeclarationRemainder(quasiText) {
116
+ const semiIdx = quasiText.indexOf(";");
117
+ if (semiIdx === -1) return quasiText;
118
+ return quasiText.slice(semiIdx + 1).trimStart();
119
+ }
120
+ function parsePropInterpolation(expression) {
121
+ if (!_babel_types.isArrowFunctionExpression(expression)) return null;
122
+ const param = expression.params[0];
123
+ if (!param) return null;
124
+ const body = unwrapExpression(expression.body);
125
+ if (!_babel_types.isExpression(body)) return null;
126
+ if (_babel_types.isIdentifier(param)) {
127
+ if (_babel_types.isMemberExpression(body) && !body.computed && _babel_types.isIdentifier(body.object, { name: param.name }) && _babel_types.isIdentifier(body.property)) return { propName: body.property.name };
128
+ return null;
129
+ }
130
+ if (_babel_types.isObjectPattern(param) && _babel_types.isIdentifier(body)) {
131
+ const propName = body.name;
132
+ if (!param.properties.some((property) => {
133
+ if (!_babel_types.isObjectProperty(property)) return false;
134
+ return (_babel_types.isIdentifier(property.key) ? property.key.name : _babel_types.isStringLiteral(property.key) ? property.key.value : null) === propName;
135
+ })) return null;
136
+ return { propName };
137
+ }
138
+ return null;
139
+ }
140
+ function parseBooleanTernaryInterpolation(expression) {
141
+ if (!_babel_types.isArrowFunctionExpression(expression)) return null;
142
+ const param = expression.params[0];
143
+ if (!_babel_types.isIdentifier(param)) return null;
144
+ const body = unwrapExpression(expression.body);
145
+ if (!_babel_types.isConditionalExpression(body)) return null;
146
+ if (!_babel_types.isMemberExpression(body.test) || body.test.computed || !_babel_types.isIdentifier(body.test.object, { name: param.name }) || !_babel_types.isIdentifier(body.test.property)) return null;
147
+ const trueValue = literalToCssValue(body.consequent);
148
+ const falseValue = literalToCssValue(body.alternate);
149
+ if (trueValue === null || falseValue === null) return null;
150
+ return {
151
+ propName: body.test.property.name,
152
+ trueValue,
153
+ falseValue
154
+ };
155
+ }
156
+ function parseTemplateInterpolations(template) {
157
+ const interpolations = [];
158
+ for (let i = 0; i < template.expressions.length; i++) {
159
+ const expression = template.expressions[i];
160
+ if (!_babel_types.isExpression(expression)) return null;
161
+ const parsed = parsePropInterpolation(expression);
162
+ if (!parsed) return null;
163
+ const followingQuasi = template.quasis[i + 1]?.value.cooked ?? "";
164
+ interpolations.push({
165
+ index: i,
166
+ propName: parsed.propName,
167
+ suffix: extractSuffixFromQuasi(followingQuasi)
168
+ });
169
+ }
170
+ return interpolations;
171
+ }
172
+ function parseBooleanTemplateInterpolations(template) {
173
+ const interpolations = [];
174
+ for (let i = 0; i < template.expressions.length; i++) {
175
+ const expression = template.expressions[i];
176
+ if (!_babel_types.isExpression(expression)) return null;
177
+ const parsed = parseBooleanTernaryInterpolation(expression);
178
+ if (!parsed) return null;
179
+ const cssProperty = extractCssPropertyBeforeInterpolation(template.quasis[i]?.value.cooked ?? "");
180
+ if (!cssProperty) return null;
181
+ interpolations.push({
182
+ index: i,
183
+ propName: parsed.propName,
184
+ trueValue: parsed.trueValue,
185
+ falseValue: parsed.falseValue,
186
+ cssProperty: camelCaseProperty(cssProperty)
187
+ });
188
+ }
189
+ return interpolations;
190
+ }
191
+ function reconstructInterpolatedCss(template, interpolations) {
192
+ let result = "";
193
+ for (let i = 0; i < template.quasis.length; i++) {
194
+ let quasiText = template.quasis[i].value.cooked ?? "";
195
+ if (i > 0) {
196
+ const interpolation = interpolations[i - 1];
197
+ if (interpolation?.suffix && quasiText.startsWith(interpolation.suffix)) quasiText = quasiText.slice(interpolation.suffix.length);
198
+ }
199
+ result += quasiText;
200
+ if (i < interpolations.length) result += placeholderToken(interpolations[i].index);
201
+ }
202
+ return result;
203
+ }
204
+ function reconstructStaticCssWithoutVariants(template, booleanInterpolations) {
205
+ const skipIndices = new Set(booleanInterpolations.map((interpolation) => interpolation.index));
206
+ let result = "";
207
+ for (let i = 0; i < template.quasis.length; i++) {
208
+ let quasiText = template.quasis[i].value.cooked ?? "";
209
+ if (skipIndices.has(i)) quasiText = stripTrailingPropertyDeclaration(quasiText);
210
+ if (i > 0 && skipIndices.has(i - 1)) quasiText = stripLeadingDeclarationRemainder(quasiText);
211
+ result += quasiText;
212
+ }
213
+ return result.trim();
214
+ }
215
+ function toVarDebugName(componentName, propName) {
216
+ return `${componentName}${propName.charAt(0).toUpperCase()}${propName.slice(1)}`;
217
+ }
218
+ function toComponentConstName(componentName) {
219
+ if (!componentName) return componentName;
220
+ return componentName.charAt(0).toLowerCase() + componentName.slice(1);
221
+ }
222
+ //#endregion
223
+ //#region src/variants.ts
224
+ function toCssValueNode(value) {
225
+ if (/^-?\d+(\.\d+)?$/.test(value.trim())) return numberNode(Number(value));
226
+ return _babel_types.stringLiteral(value);
227
+ }
228
+ function toKeyNode(key) {
229
+ if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) return _babel_types.identifier(key);
230
+ return _babel_types.stringLiteral(key);
231
+ }
232
+ function buildVariantStyles(properties) {
233
+ return _babel_types.objectExpression(Object.entries(properties).map(([key, value]) => _babel_types.objectProperty(toKeyNode(key), toCssValueNode(value))));
234
+ }
235
+ function buildVariantRecipeInput(name, baseObject, booleanInterpolations) {
236
+ const variantGroups = new Map();
237
+ for (const interpolation of booleanInterpolations) {
238
+ const group = variantGroups.get(interpolation.propName) ?? {
239
+ true: {},
240
+ false: {}
241
+ };
242
+ group.true[interpolation.cssProperty] = interpolation.trueValue;
243
+ group.false[interpolation.cssProperty] = interpolation.falseValue;
244
+ variantGroups.set(interpolation.propName, group);
245
+ }
246
+ const variantsProperties = [...variantGroups.entries()].map(([propName, values]) => _babel_types.objectProperty(_babel_types.identifier(propName), _babel_types.objectExpression([_babel_types.objectProperty(_babel_types.identifier("true"), buildVariantStyles(values.true)), _babel_types.objectProperty(_babel_types.identifier("false"), buildVariantStyles(values.false))])));
247
+ const axisProperties = [...variantGroups.keys()].map((propName) => _babel_types.objectProperty(_babel_types.identifier(propName), _babel_types.callExpression(_babel_types.memberExpression(_babel_types.identifier("variant"), _babel_types.identifier("boolean")), [_babel_types.objectExpression([_babel_types.objectProperty(_babel_types.identifier("default"), _babel_types.booleanLiteral(false))])])));
248
+ return _babel_types.objectExpression([
249
+ _babel_types.objectProperty(_babel_types.identifier("name"), _babel_types.stringLiteral(name)),
250
+ _babel_types.objectProperty(_babel_types.identifier("variants"), _babel_types.objectExpression(axisProperties)),
251
+ _babel_types.objectProperty(_babel_types.identifier("styles"), _babel_types.objectExpression([_babel_types.objectProperty(_babel_types.identifier("base"), baseObject), _babel_types.objectProperty(_babel_types.identifier("variants"), _babel_types.objectExpression(variantsProperties))]))
252
+ ]);
253
+ }
254
+ //#endregion
255
+ //#region src/transform.ts
256
+ function toKebabCase(input) {
257
+ return input.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[_\s]+/g, "-").toLowerCase();
258
+ }
259
+ function memberExpressionToJsxName(expression) {
260
+ if (_babel_types.isIdentifier(expression)) return _babel_types.jsxIdentifier(expression.name);
261
+ if (_babel_types.isMemberExpression(expression) && !expression.computed) {
262
+ const left = memberExpressionToJsxName(expression.object);
263
+ const right = _babel_types.isIdentifier(expression.property) ? _babel_types.jsxIdentifier(expression.property.name) : null;
264
+ if (!left || !right) return null;
265
+ return _babel_types.jsxMemberExpression(left, right);
266
+ }
267
+ return null;
268
+ }
269
+ function parseStyledTarget(tag, styledNames) {
270
+ if (_babel_types.isMemberExpression(tag) && _babel_types.isIdentifier(tag.object) && styledNames.has(tag.object.name) && _babel_types.isIdentifier(tag.property)) return {
271
+ kind: "intrinsic",
272
+ jsxName: _babel_types.jsxIdentifier(tag.property.name)
273
+ };
274
+ if (_babel_types.isCallExpression(tag) && _babel_types.isIdentifier(tag.callee) && styledNames.has(tag.callee.name)) {
275
+ const firstArg = tag.arguments[0];
276
+ if (!firstArg || !_babel_types.isExpression(firstArg)) return null;
277
+ const jsxName = memberExpressionToJsxName(firstArg);
278
+ if (!jsxName) return null;
279
+ return {
280
+ kind: "component",
281
+ jsxName
282
+ };
283
+ }
284
+ return null;
285
+ }
286
+ function addWarning(warnings, message, nodeName) {
287
+ warnings.push({
288
+ message,
289
+ nodeName
290
+ });
291
+ }
292
+ function createMergedClassExpression(existing, classNameExpression) {
293
+ return _babel_types.callExpression(_babel_types.memberExpression(_babel_types.callExpression(_babel_types.memberExpression(_babel_types.arrayExpression([existing, classNameExpression]), _babel_types.identifier("filter")), [_babel_types.identifier("Boolean")]), _babel_types.identifier("join")), [_babel_types.stringLiteral(" ")]);
294
+ }
295
+ function updateClassNameAttribute(openingElement, classNameExpression) {
296
+ const existingAttr = openingElement.attributes.find((attribute) => _babel_types.isJSXAttribute(attribute) && _babel_types.isJSXIdentifier(attribute.name, { name: "className" }));
297
+ if (!existingAttr) {
298
+ openingElement.attributes.push(_babel_types.jsxAttribute(_babel_types.jsxIdentifier("className"), _babel_types.jsxExpressionContainer(classNameExpression)));
299
+ return;
300
+ }
301
+ if (!existingAttr.value) {
302
+ existingAttr.value = _babel_types.jsxExpressionContainer(classNameExpression);
303
+ return;
304
+ }
305
+ if (_babel_types.isStringLiteral(existingAttr.value)) {
306
+ existingAttr.value = _babel_types.jsxExpressionContainer(createMergedClassExpression(_babel_types.stringLiteral(existingAttr.value.value), classNameExpression));
307
+ return;
308
+ }
309
+ if (_babel_types.isJSXExpressionContainer(existingAttr.value)) existingAttr.value = _babel_types.jsxExpressionContainer(createMergedClassExpression(existingAttr.value.expression, classNameExpression));
310
+ }
311
+ function hasLocalBinding(ast, name) {
312
+ for (const statement of ast.program.body) {
313
+ if (!_babel_types.isVariableDeclaration(statement)) continue;
314
+ for (const declarator of statement.declarations) {
315
+ if (_babel_types.isIdentifier(declarator.id) && declarator.id.name === name) return true;
316
+ if (_babel_types.isObjectPattern(declarator.id)) {
317
+ for (const prop of declarator.id.properties) if (_babel_types.isObjectProperty(prop) && _babel_types.isIdentifier(prop.value) && prop.value.name === name) return true;
318
+ }
319
+ }
320
+ }
321
+ return false;
322
+ }
323
+ function ensureTypestylesRuntime(ast, needs) {
324
+ const requiredSpecifiers = new Set(["createTypeStyles"]);
325
+ if (needs.recipe) requiredSpecifiers.add("variant");
326
+ if (needs.vars) {
327
+ requiredSpecifiers.add("createVar");
328
+ requiredSpecifiers.add("assignVars");
329
+ }
330
+ let typestylesImport = null;
331
+ let lastImportIndex = -1;
332
+ for (let i = 0; i < ast.program.body.length; i++) {
333
+ const statement = ast.program.body[i];
334
+ if (_babel_types.isImportDeclaration(statement)) {
335
+ lastImportIndex = i;
336
+ if (statement.source.value === "typestyles" && typestylesImport == null) typestylesImport = statement;
337
+ }
338
+ }
339
+ const buildSpecifiers = (names) => [...names].map((name) => _babel_types.importSpecifier(_babel_types.identifier(name), _babel_types.identifier(name)));
340
+ if (!typestylesImport) {
341
+ ast.program.body.unshift(_babel_types.importDeclaration(buildSpecifiers(requiredSpecifiers), _babel_types.stringLiteral("typestyles")));
342
+ lastImportIndex = 0;
343
+ } else for (const name of requiredSpecifiers) if (!typestylesImport.specifiers.some((specifier) => _babel_types.isImportSpecifier(specifier) && _babel_types.isIdentifier(specifier.imported, { name }) && _babel_types.isIdentifier(specifier.local, { name }))) typestylesImport.specifiers.push(_babel_types.importSpecifier(_babel_types.identifier(name), _babel_types.identifier(name)));
344
+ const destructureProps = [];
345
+ if (needs.style && !hasLocalBinding(ast, "style")) destructureProps.push(_babel_types.objectProperty(_babel_types.identifier("style"), _babel_types.identifier("style"), false, true));
346
+ if (needs.recipe && !hasLocalBinding(ast, "recipe")) destructureProps.push(_babel_types.objectProperty(_babel_types.identifier("recipe"), _babel_types.identifier("recipe"), false, true));
347
+ if (destructureProps.length === 0) return;
348
+ const factoryDecl = _babel_types.variableDeclaration("const", [_babel_types.variableDeclarator(_babel_types.objectPattern(destructureProps), _babel_types.callExpression(_babel_types.identifier("createTypeStyles"), []))]);
349
+ ast.program.body.splice(lastImportIndex + 1, 0, factoryDecl);
350
+ }
351
+ function cleanupUnusedImports(ast) {
352
+ (0, _babel_traverse.default)(ast, {
353
+ Program(path) {
354
+ path.scope.crawl();
355
+ },
356
+ ImportDeclaration(path) {
357
+ const unusedLocals = path.node.specifiers.filter((specifier) => {
358
+ if (path.node.source.value === "typestyles" && _babel_types.isImportSpecifier(specifier) && (specifier.local.name === "createTypeStyles" || specifier.local.name === "createVar" || specifier.local.name === "assignVars")) return false;
359
+ const local = specifier.local.name;
360
+ const binding = path.scope.getBinding(local);
361
+ return !binding || binding.referencePaths.length === 0;
362
+ });
363
+ if (unusedLocals.length === 0) return;
364
+ path.node.specifiers = path.node.specifiers.filter((specifier) => !unusedLocals.includes(specifier));
365
+ if (path.node.specifiers.length === 0) path.remove();
366
+ }
367
+ });
368
+ }
369
+ function createAssignVarValue(propExpression, suffix) {
370
+ if (!suffix) return propExpression;
371
+ if (_babel_types.isStringLiteral(propExpression)) return _babel_types.stringLiteral(`${propExpression.value}${suffix}`);
372
+ return _babel_types.binaryExpression("+", propExpression, _babel_types.stringLiteral(suffix));
373
+ }
374
+ function buildAssignVarsCall(propVars, propValues) {
375
+ const properties = propVars.filter((binding) => propValues.has(binding.propName)).map((binding) => {
376
+ const propExpression = propValues.get(binding.propName);
377
+ return _babel_types.objectProperty(_babel_types.identifier(binding.varConstName), createAssignVarValue(propExpression, binding.suffix), true);
378
+ });
379
+ return _babel_types.callExpression(_babel_types.identifier("assignVars"), [_babel_types.objectExpression(properties)]);
380
+ }
381
+ function mergeStyleExpressions(existing, assignVarsCall) {
382
+ return _babel_types.objectExpression([_babel_types.spreadElement(existing), _babel_types.spreadElement(assignVarsCall)]);
383
+ }
384
+ function updateStyleAttribute(openingElement, assignVarsCall) {
385
+ const existingAttr = openingElement.attributes.find((attribute) => _babel_types.isJSXAttribute(attribute) && _babel_types.isJSXIdentifier(attribute.name, { name: "style" }));
386
+ if (!existingAttr) {
387
+ openingElement.attributes.push(_babel_types.jsxAttribute(_babel_types.jsxIdentifier("style"), _babel_types.jsxExpressionContainer(assignVarsCall)));
388
+ return;
389
+ }
390
+ if (!existingAttr.value) {
391
+ existingAttr.value = _babel_types.jsxExpressionContainer(assignVarsCall);
392
+ return;
393
+ }
394
+ if (_babel_types.isJSXExpressionContainer(existingAttr.value)) existingAttr.value = _babel_types.jsxExpressionContainer(mergeStyleExpressions(existingAttr.value.expression, assignVarsCall));
395
+ }
396
+ function collectPropValuesFromJsx(openingElement, propNames) {
397
+ const values = new Map();
398
+ for (const attribute of openingElement.attributes) {
399
+ if (!_babel_types.isJSXAttribute(attribute) || !_babel_types.isJSXIdentifier(attribute.name)) continue;
400
+ if (!propNames.has(attribute.name.name)) continue;
401
+ if (!attribute.value) {
402
+ values.set(attribute.name.name, _babel_types.booleanLiteral(true));
403
+ continue;
404
+ }
405
+ if (_babel_types.isStringLiteral(attribute.value)) {
406
+ values.set(attribute.name.name, _babel_types.stringLiteral(attribute.value.value));
407
+ continue;
408
+ }
409
+ if (_babel_types.isJSXExpressionContainer(attribute.value)) values.set(attribute.name.name, attribute.value.expression);
410
+ }
411
+ return values;
412
+ }
413
+ function removeStyledProps(openingElement, propNames) {
414
+ openingElement.attributes = openingElement.attributes.filter((attribute) => {
415
+ if (!_babel_types.isJSXAttribute(attribute) || !_babel_types.isJSXIdentifier(attribute.name)) return true;
416
+ return !propNames.has(attribute.name.name);
417
+ });
418
+ }
419
+ function buildComponentClassNameExpression(componentConstName, variantProps, propValues) {
420
+ const properties = variantProps.filter((propName) => propValues.has(propName)).map((propName) => _babel_types.objectProperty(_babel_types.identifier(propName), propValues.get(propName)));
421
+ const call = properties.length === 0 ? _babel_types.callExpression(_babel_types.identifier(componentConstName), []) : _babel_types.callExpression(_babel_types.identifier(componentConstName), [_babel_types.objectExpression(properties)]);
422
+ return _babel_types.memberExpression(call, _babel_types.identifier("className"));
423
+ }
424
+ function migrateBooleanVariantTemplate(path, variableName, template, styledTarget, warnings, styledTransforms) {
425
+ const booleanInterpolations = parseBooleanTemplateInterpolations(template);
426
+ if (!booleanInterpolations) return false;
427
+ const baseObject = cssToObjectExpression(reconstructStaticCssWithoutVariants(template, booleanInterpolations), warnings);
428
+ if (!baseObject) {
429
+ addWarning(warnings, "Skipped because CSS could not be parsed.", variableName);
430
+ return false;
431
+ }
432
+ const componentConstName = path.scope.generateUidIdentifier(toComponentConstName(variableName)).name;
433
+ const recipeInput = buildVariantRecipeInput(toKebabCase(variableName), baseObject, booleanInterpolations);
434
+ const variantProps = [...new Set(booleanInterpolations.map((interpolation) => interpolation.propName))];
435
+ const declaration = path.parentPath;
436
+ if (!declaration.isVariableDeclaration()) return false;
437
+ declaration.node.declarations = [_babel_types.variableDeclarator(_babel_types.identifier(componentConstName), _babel_types.callExpression(_babel_types.identifier("recipe"), [recipeInput]))];
438
+ styledTransforms.set(variableName, {
439
+ originalName: variableName,
440
+ mode: "component",
441
+ classConstName: componentConstName,
442
+ target: styledTarget,
443
+ propVars: [],
444
+ variantProps
445
+ });
446
+ return true;
447
+ }
448
+ function migrateInterpolatedTemplate(path, variableName, template, styledTarget, warnings, styledTransforms) {
449
+ const interpolations = parseTemplateInterpolations(template);
450
+ if (!interpolations) {
451
+ addWarning(warnings, "Skipped template literal with unsupported interpolations. Only prop-based patterns like `${props => props.color}` are migrated.", variableName);
452
+ return false;
453
+ }
454
+ const cssText = reconstructInterpolatedCss(template, interpolations);
455
+ const propVars = interpolations.map((interpolation) => ({
456
+ propName: interpolation.propName,
457
+ varConstName: path.scope.generateUidIdentifier(`${variableName}${interpolation.propName.charAt(0).toUpperCase()}${interpolation.propName.slice(1)}Var`).name,
458
+ suffix: interpolation.suffix
459
+ }));
460
+ const varReplacements = new Map();
461
+ for (let i = 0; i < interpolations.length; i++) varReplacements.set(placeholderToken(interpolations[i].index), _babel_types.identifier(propVars[i].varConstName));
462
+ const objectExpression = cssToObjectExpression(cssText, warnings, varReplacements);
463
+ if (!objectExpression) {
464
+ addWarning(warnings, "Skipped because CSS could not be parsed.", variableName);
465
+ return false;
466
+ }
467
+ const classConstName = path.scope.generateUidIdentifier(`${variableName}Class`).name;
468
+ const varDeclarators = propVars.map((propVar) => _babel_types.variableDeclarator(_babel_types.identifier(propVar.varConstName), _babel_types.callExpression(_babel_types.identifier("createVar"), [_babel_types.stringLiteral(toVarDebugName(variableName, propVar.propName))])));
469
+ const declaration = path.parentPath;
470
+ if (!declaration.isVariableDeclaration()) return false;
471
+ declaration.node.declarations = [...varDeclarators, _babel_types.variableDeclarator(_babel_types.identifier(classConstName), _babel_types.callExpression(_babel_types.identifier("style"), [_babel_types.stringLiteral(toKebabCase(variableName)), objectExpression]))];
472
+ styledTransforms.set(variableName, {
473
+ originalName: variableName,
474
+ mode: "class",
475
+ classConstName,
476
+ target: styledTarget,
477
+ propVars,
478
+ variantProps: []
479
+ });
480
+ return true;
481
+ }
482
+ function isOnlyJsxReferences(binding) {
483
+ return binding.referencePaths.every((referencePath) => {
484
+ const parent = referencePath.parentPath;
485
+ if (!parent) return false;
486
+ return parent.isJSXOpeningElement() && parent.get("name") === referencePath || parent.isJSXClosingElement() && parent.get("name") === referencePath;
487
+ });
488
+ }
489
+ function migrateSource(filePath, source) {
490
+ const warnings = [];
491
+ let changed = false;
492
+ const ast = (0, _babel_parser.parse)(source, {
493
+ sourceType: "module",
494
+ plugins: ["typescript", "jsx"]
495
+ });
496
+ const styledNames = new Set();
497
+ const cssTagNames = new Set();
498
+ const styledTransforms = new Map();
499
+ let needsVars = false;
500
+ let needsStyle = false;
501
+ let needsRecipe = false;
502
+ (0, _babel_traverse.default)(ast, { ImportDeclaration(path) {
503
+ if (path.node.source.value === "styled-components" || path.node.source.value === "@emotion/styled") for (const specifier of path.node.specifiers) {
504
+ if (_babel_types.isImportDefaultSpecifier(specifier)) styledNames.add(specifier.local.name);
505
+ if (_babel_types.isImportSpecifier(specifier) && _babel_types.isIdentifier(specifier.imported, { name: "css" })) cssTagNames.add(specifier.local.name);
506
+ }
507
+ if (path.node.source.value === "@emotion/react" || path.node.source.value === "@emotion/css") {
508
+ for (const specifier of path.node.specifiers) if (_babel_types.isImportSpecifier(specifier) && _babel_types.isIdentifier(specifier.imported, { name: "css" })) cssTagNames.add(specifier.local.name);
509
+ }
510
+ } });
511
+ (0, _babel_traverse.default)(ast, { VariableDeclarator(path) {
512
+ if (!_babel_types.isIdentifier(path.node.id)) return;
513
+ if (!_babel_types.isTaggedTemplateExpression(path.node.init)) return;
514
+ const variableName = path.node.id.name;
515
+ const binding = path.scope.getBinding(variableName);
516
+ if (!binding) return;
517
+ const template = path.node.init.quasi;
518
+ const hasInterpolations = template.expressions.length > 0;
519
+ const styledTarget = parseStyledTarget(path.node.init.tag, styledNames);
520
+ if (hasInterpolations) {
521
+ if (!styledTarget) {
522
+ addWarning(warnings, "Skipped template literal with interpolations. Only styled-components prop patterns are migrated.", variableName);
523
+ return;
524
+ }
525
+ const declaration = path.parentPath;
526
+ if (declaration.parentPath?.isExportNamedDeclaration() || declaration.parentPath?.isExportDefaultDeclaration()) {
527
+ addWarning(warnings, "Skipped exported styled component to avoid changing external API shape.", variableName);
528
+ return;
529
+ }
530
+ if (!isOnlyJsxReferences(binding)) {
531
+ addWarning(warnings, "Skipped styled component with non-JSX references.", variableName);
532
+ return;
533
+ }
534
+ if (migrateBooleanVariantTemplate(path, variableName, template, styledTarget, warnings, styledTransforms)) {
535
+ needsRecipe = true;
536
+ changed = true;
537
+ return;
538
+ }
539
+ if (migrateInterpolatedTemplate(path, variableName, template, styledTarget, warnings, styledTransforms)) {
540
+ needsVars = true;
541
+ needsStyle = true;
542
+ changed = true;
543
+ }
544
+ return;
545
+ }
546
+ const objectExpression = cssToObjectExpression(template.quasis.map((quasi) => quasi.value.cooked ?? "").join(""), warnings);
547
+ if (!objectExpression) {
548
+ addWarning(warnings, "Skipped because CSS could not be parsed.", variableName);
549
+ return;
550
+ }
551
+ if (styledTarget) {
552
+ const declaration = path.parentPath;
553
+ if (declaration.parentPath?.isExportNamedDeclaration() || declaration.parentPath?.isExportDefaultDeclaration()) {
554
+ addWarning(warnings, "Skipped exported styled component to avoid changing external API shape.", variableName);
555
+ return;
556
+ }
557
+ if (!isOnlyJsxReferences(binding)) {
558
+ addWarning(warnings, "Skipped styled component with non-JSX references.", variableName);
559
+ return;
560
+ }
561
+ const classConstName = path.scope.generateUidIdentifier(`${variableName}Class`).name;
562
+ path.node.id = _babel_types.identifier(classConstName);
563
+ path.node.init = _babel_types.callExpression(_babel_types.identifier("style"), [_babel_types.stringLiteral(toKebabCase(variableName)), objectExpression]);
564
+ styledTransforms.set(variableName, {
565
+ originalName: variableName,
566
+ mode: "class",
567
+ classConstName,
568
+ target: styledTarget,
569
+ propVars: [],
570
+ variantProps: []
571
+ });
572
+ needsStyle = true;
573
+ changed = true;
574
+ return;
575
+ }
576
+ if (_babel_types.isIdentifier(path.node.init.tag) && cssTagNames.has(path.node.init.tag.name)) {
577
+ path.node.init = _babel_types.callExpression(_babel_types.identifier("style"), [_babel_types.stringLiteral(toKebabCase(variableName)), objectExpression]);
578
+ needsStyle = true;
579
+ changed = true;
580
+ }
581
+ } });
582
+ if (styledTransforms.size > 0) (0, _babel_traverse.default)(ast, { JSXElement(path) {
583
+ const openingName = path.node.openingElement.name;
584
+ if (!_babel_types.isJSXIdentifier(openingName)) return;
585
+ const transform = styledTransforms.get(openingName.name);
586
+ if (!transform) return;
587
+ path.node.openingElement.name = transform.target.jsxName;
588
+ if (path.node.closingElement) path.node.closingElement.name = transform.target.jsxName;
589
+ const classNameExpression = transform.mode === "component" ? buildComponentClassNameExpression(transform.classConstName, transform.variantProps, collectPropValuesFromJsx(path.node.openingElement, new Set(transform.variantProps))) : _babel_types.identifier(transform.classConstName);
590
+ updateClassNameAttribute(path.node.openingElement, classNameExpression);
591
+ if (transform.propVars.length > 0) {
592
+ const propNames = new Set(transform.propVars.map((propVar) => propVar.propName));
593
+ const propValues = collectPropValuesFromJsx(path.node.openingElement, propNames);
594
+ if (propValues.size > 0) {
595
+ const assignVarsCall = buildAssignVarsCall(transform.propVars, propValues);
596
+ updateStyleAttribute(path.node.openingElement, assignVarsCall);
597
+ removeStyledProps(path.node.openingElement, propNames);
598
+ }
599
+ }
600
+ if (transform.variantProps.length > 0) removeStyledProps(path.node.openingElement, new Set(transform.variantProps));
601
+ } });
602
+ if (changed) {
603
+ ensureTypestylesRuntime(ast, {
604
+ style: needsStyle,
605
+ recipe: needsRecipe,
606
+ vars: needsVars
607
+ });
608
+ cleanupUnusedImports(ast);
609
+ }
610
+ const output = (0, _babel_generator.default)(ast, {
611
+ retainLines: false,
612
+ comments: true,
613
+ concise: false
614
+ }, source);
615
+ return {
616
+ filePath,
617
+ changed: changed && output.code !== source,
618
+ code: output.code,
619
+ warnings
620
+ };
621
+ }
622
+ //#endregion
623
+ //#region src/files.ts
624
+ const DEFAULT_EXCLUDES = [
625
+ "**/node_modules/**",
626
+ "**/dist/**",
627
+ "**/.next/**",
628
+ "**/.turbo/**"
629
+ ];
630
+ function normalizeExtension(extension) {
631
+ return extension.startsWith(".") ? extension : `.${extension}`;
632
+ }
633
+ async function collectTargetFiles(cwd, targets, extensions, include, exclude) {
634
+ const normalizedTargets = targets.length > 0 ? targets : ["."];
635
+ const literalFiles = [];
636
+ const dynamicPatterns = [];
637
+ for (const target of normalizedTargets) {
638
+ const absolute = (0, node_path.resolve)(cwd, target);
639
+ try {
640
+ const targetStat = await (0, node_fs_promises.stat)(absolute);
641
+ if (targetStat.isFile()) literalFiles.push(absolute);
642
+ else if (targetStat.isDirectory()) dynamicPatterns.push(`${absolute.split("\\").join("/")}/**/*`);
643
+ } catch {
644
+ dynamicPatterns.push(target);
645
+ }
646
+ }
647
+ const globbed = await (0, fast_glob.default)(dynamicPatterns, {
648
+ cwd,
649
+ absolute: true,
650
+ onlyFiles: true,
651
+ ignore: [...DEFAULT_EXCLUDES, ...exclude]
652
+ });
653
+ const extensionSet = new Set(extensions.map(normalizeExtension));
654
+ const includeMatchers = include.length > 0 ? include.map((pattern) => (0, picomatch.default)(pattern)) : null;
655
+ const unique = new Set([...literalFiles, ...globbed]);
656
+ return Array.from(unique).filter((filePath) => extensionSet.has((0, node_path.extname)(filePath))).filter((filePath) => {
657
+ if (!includeMatchers) return true;
658
+ const rel = (0, node_path.relative)(cwd, filePath).split("\\").join("/");
659
+ return includeMatchers.some((matcher) => matcher(rel));
660
+ }).sort();
661
+ }
662
+ //#endregion
663
+ //#region src/migrate.ts
664
+ function renderPatch(filePath, before, after) {
665
+ return (0, diff.createPatch)(filePath, before, after, "before", "after").split("\n").slice(2).join("\n");
666
+ }
667
+ async function runMigration(cwd, options) {
668
+ const files = await collectTargetFiles(cwd, options.targets, options.extensions, options.include, options.exclude);
669
+ const reportEntries = [];
670
+ let changedCount = 0;
671
+ let warningCount = 0;
672
+ for (const filePath of files) {
673
+ const before = await (0, node_fs_promises.readFile)(filePath, "utf8");
674
+ const result = migrateSource(filePath, before);
675
+ const relativePath = (0, node_path.relative)(cwd, filePath);
676
+ warningCount += result.warnings.length;
677
+ if (result.changed) {
678
+ changedCount += 1;
679
+ if (options.write) {
680
+ await (0, node_fs_promises.writeFile)(filePath, result.code, "utf8");
681
+ process.stdout.write(`updated ${relativePath}\n`);
682
+ } else {
683
+ process.stdout.write(`\n--- ${relativePath} (dry-run) ---\n`);
684
+ process.stdout.write(`${renderPatch(relativePath, before, result.code)}\n`);
685
+ }
686
+ }
687
+ for (const warning of result.warnings) {
688
+ const nodeLabel = warning.nodeName ? ` (${warning.nodeName})` : "";
689
+ process.stdout.write(`warning ${relativePath}${nodeLabel}: ${warning.message}\n`);
690
+ }
691
+ reportEntries.push({
692
+ filePath: relativePath,
693
+ changed: result.changed,
694
+ warnings: result.warnings
695
+ });
696
+ }
697
+ const summary = {
698
+ filesScanned: files.length,
699
+ filesChanged: changedCount,
700
+ warnings: warningCount
701
+ };
702
+ process.stdout.write(`\nScanned ${summary.filesScanned} files, changed ${summary.filesChanged}, warnings ${summary.warnings}.\n`);
703
+ const report = {
704
+ summary,
705
+ files: reportEntries
706
+ };
707
+ if (options.reportPath) {
708
+ await (0, node_fs_promises.mkdir)((0, node_path.dirname)(options.reportPath), { recursive: true });
709
+ await (0, node_fs_promises.writeFile)(options.reportPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
710
+ process.stdout.write(`Report written to ${options.reportPath}\n`);
711
+ }
712
+ return report;
713
+ }
714
+ //#endregion
715
+ Object.defineProperty(exports, "migrateSource", {
716
+ enumerable: true,
717
+ get: function() {
718
+ return migrateSource;
719
+ }
720
+ });
721
+ Object.defineProperty(exports, "runMigration", {
722
+ enumerable: true,
723
+ get: function() {
724
+ return runMigration;
725
+ }
726
+ });
727
+
728
+ //# sourceMappingURL=migrate-B3MfAQI5.cjs.map