@react-spectrum/codemods 0.1.0
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/LICENSE +201 -0
- package/dist/index.js +55 -0
- package/dist/s1-to-s2/src/codemods/button.js +52 -0
- package/dist/s1-to-s2/src/codemods/changes.js +1106 -0
- package/dist/s1-to-s2/src/codemods/codemod.js +214 -0
- package/dist/s1-to-s2/src/codemods/colors.js +309 -0
- package/dist/s1-to-s2/src/codemods/dialog.js +63 -0
- package/dist/s1-to-s2/src/codemods/dimensions.js +199 -0
- package/dist/s1-to-s2/src/codemods/styleProps.js +624 -0
- package/dist/s1-to-s2/src/codemods/transforms.js +685 -0
- package/dist/s1-to-s2/src/codemods/unsafeStyle.js +420 -0
- package/dist/s1-to-s2/src/codemods/utils.js +160 -0
- package/dist/s1-to-s2/src/getComponents.js +27 -0
- package/dist/s1-to-s2/src/index.js +57 -0
- package/dist/s1-to-s2/src/transform.js +13 -0
- package/dist/s1-to-s2/src/utils/addMacroSupport.js +20 -0
- package/dist/s1-to-s2/src/utils/installPackage.js +49 -0
- package/dist/s1-to-s2/src/utils/logger.js +24 -0
- package/dist/s1-to-s2/src/utils/waitForKeypress.js +10 -0
- package/dist/use-monopackages/src/codemod.js +146 -0
- package/dist/use-monopackages/src/index.js +13 -0
- package/package.json +51 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformUnsafeStyle = transformUnsafeStyle;
|
|
4
|
+
const styleProps_1 = require("./styleProps");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
const dimensions_1 = require("./dimensions");
|
|
7
|
+
const colors_1 = require("./colors");
|
|
8
|
+
function transformUnsafeStyle(value, element) {
|
|
9
|
+
let res = {
|
|
10
|
+
macroValues: [],
|
|
11
|
+
dynamicValues: [],
|
|
12
|
+
conditions: []
|
|
13
|
+
};
|
|
14
|
+
for (let property of value.properties) {
|
|
15
|
+
if (property.type === 'ObjectProperty' && property.key.type === 'Identifier') {
|
|
16
|
+
let prop = propertyMapping[property.key.name] || property.key.name;
|
|
17
|
+
if (property.value.type === 'ConditionalExpression') {
|
|
18
|
+
let consequent = handleProperty(element, property.key.name, property.value.consequent);
|
|
19
|
+
let alternate = handleProperty(element, property.key.name, property.value.alternate);
|
|
20
|
+
if (consequent && alternate) {
|
|
21
|
+
let test = property.value.test;
|
|
22
|
+
// eslint-disable-next-line max-depth
|
|
23
|
+
if (test.type === 'BinaryExpression' && test.operator === '===' && test.left.type === 'Identifier' && test.right.type === 'StringLiteral') {
|
|
24
|
+
res.macroValues.push({
|
|
25
|
+
key: prop,
|
|
26
|
+
value: { default: alternate, [test.left.name]: { [test.right.value]: consequent } }
|
|
27
|
+
});
|
|
28
|
+
res.conditions?.push({
|
|
29
|
+
key: test.left.name,
|
|
30
|
+
value: test.left
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
let condition = (0, utils_1.nameFromExpression)(test) || `isCondition${res.conditions.length}`;
|
|
35
|
+
// eslint-disable-next-line max-depth
|
|
36
|
+
if (!/^is[A-Z]/.test(condition)) {
|
|
37
|
+
condition = `is${(0, utils_1.capitalize)(condition)}`;
|
|
38
|
+
}
|
|
39
|
+
res.macroValues.push({
|
|
40
|
+
key: prop,
|
|
41
|
+
value: { default: alternate, [condition]: consequent }
|
|
42
|
+
});
|
|
43
|
+
res.conditions?.push({
|
|
44
|
+
key: condition,
|
|
45
|
+
value: test
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
let value = handleProperty(element, prop, property.value);
|
|
52
|
+
if (value != null) {
|
|
53
|
+
res.macroValues.push({ key: prop, value });
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
res.dynamicValues?.push({ key: prop, value: property.value });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Bail
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return res;
|
|
65
|
+
}
|
|
66
|
+
const propertyMapping = {
|
|
67
|
+
background: 'backgroundColor',
|
|
68
|
+
borderInlineStartWidth: 'borderStartWidth',
|
|
69
|
+
borderInlineEndWidth: 'borderEndWidth',
|
|
70
|
+
borderInlineWidth: 'borderXWidth',
|
|
71
|
+
borderBlockWidth: 'borderYWidth',
|
|
72
|
+
borderLeftWidth: 'borderStartWidth',
|
|
73
|
+
borderRightWidth: 'borderEndWidth',
|
|
74
|
+
marginInlineStart: 'marginStart',
|
|
75
|
+
marginInlineEnd: 'marginEnd',
|
|
76
|
+
marginInline: 'marginX',
|
|
77
|
+
marginBlock: 'marginY',
|
|
78
|
+
marginLeft: 'marginStart',
|
|
79
|
+
marginRight: 'marginEnd',
|
|
80
|
+
paddingInlineStart: 'paddingStart',
|
|
81
|
+
paddingInlineEnd: 'paddingEnd',
|
|
82
|
+
paddingInline: 'paddingX',
|
|
83
|
+
paddingBlock: 'paddingY',
|
|
84
|
+
paddingLeft: 'paddingStart',
|
|
85
|
+
paddingRight: 'paddingEnd',
|
|
86
|
+
insetInlineStart: 'insetStart',
|
|
87
|
+
insetInlineEnd: 'insetEnd',
|
|
88
|
+
borderStartStartRadius: 'borderTopStartRadius',
|
|
89
|
+
borderStartEndRadius: 'borderTopEndRadius',
|
|
90
|
+
borderEndStartRadius: 'borderBottomStartRadius',
|
|
91
|
+
borderEndEndRadius: 'borderBottomEndRadius'
|
|
92
|
+
};
|
|
93
|
+
function handleProperty(element, property, value) {
|
|
94
|
+
switch (property) {
|
|
95
|
+
case 'color':
|
|
96
|
+
case 'background':
|
|
97
|
+
case 'backgroundColor':
|
|
98
|
+
case 'borderColor':
|
|
99
|
+
case 'outlineColor':
|
|
100
|
+
case 'fill':
|
|
101
|
+
case 'stroke': {
|
|
102
|
+
if ((element === 'View' || element === 'Flex' || element === 'Grid') && value.type === 'StringLiteral') {
|
|
103
|
+
return (0, colors_1.convertUnsafeStyleColor)(property, value.value);
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
case 'borderWidth':
|
|
108
|
+
case 'borderInlineStartWidth':
|
|
109
|
+
case 'borderInlineEndWidth':
|
|
110
|
+
case 'borderInlineWidth':
|
|
111
|
+
case 'broderBlockWidth':
|
|
112
|
+
case 'borderLeftWidth':
|
|
113
|
+
case 'borderRightWidth':
|
|
114
|
+
case 'borderTopWidth':
|
|
115
|
+
case 'borderBottomWidth':
|
|
116
|
+
if (element === 'View' || element === 'Flex' || element === 'Grid') {
|
|
117
|
+
if (value.type === 'NumericLiteral' && value.value >= 0 && value.value <= 4) {
|
|
118
|
+
return value.value;
|
|
119
|
+
}
|
|
120
|
+
else if (value.type === 'StringLiteral') {
|
|
121
|
+
if (/^[0-4]px$/.test(value.value)) {
|
|
122
|
+
return parseInt(value.value, 10);
|
|
123
|
+
}
|
|
124
|
+
let m = value.value.match(/^var\(--spectrum-alias-border-size-(.+)\)$/);
|
|
125
|
+
if (m) {
|
|
126
|
+
return styleProps_1.borderWidths[m[1]];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
break;
|
|
131
|
+
case 'borderStartStartRadius':
|
|
132
|
+
case 'borderStartEndRadius':
|
|
133
|
+
case 'borderEndStartRadius':
|
|
134
|
+
case 'borderEndEndRadius':
|
|
135
|
+
case 'borderRadius':
|
|
136
|
+
if (element === 'View' || element === 'Flex' || element === 'Grid') {
|
|
137
|
+
if (value.type === 'StringLiteral' && /^[0-4]px$/.test(value.value)) {
|
|
138
|
+
value = { type: 'NumericLiteral', value: parseInt(value.value, 10) };
|
|
139
|
+
}
|
|
140
|
+
if (value.type === 'NumericLiteral') {
|
|
141
|
+
switch (value.value) {
|
|
142
|
+
case 0: return 'none';
|
|
143
|
+
case 2: return 'sm';
|
|
144
|
+
case 4: return 'default';
|
|
145
|
+
case 8: return 'lg';
|
|
146
|
+
case 16: return 'xl';
|
|
147
|
+
default: return `[${value.value}px]`;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else if (value.type === 'StringLiteral') {
|
|
151
|
+
let m = value.value.match(/^var\(--spectrum-alias-border-radius-(.+)\)$/);
|
|
152
|
+
if (m) {
|
|
153
|
+
return styleProps_1.borderRadius[m[1]];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
break;
|
|
158
|
+
case 'width':
|
|
159
|
+
case 'minWidth':
|
|
160
|
+
case 'maxWidth':
|
|
161
|
+
case 'height':
|
|
162
|
+
case 'minHeight':
|
|
163
|
+
case 'maxHeight':
|
|
164
|
+
case 'margin':
|
|
165
|
+
case 'marginInlineStart':
|
|
166
|
+
case 'marginInlineEnd':
|
|
167
|
+
case 'marginInline':
|
|
168
|
+
case 'marginBlock':
|
|
169
|
+
case 'marginLeft':
|
|
170
|
+
case 'marginRight':
|
|
171
|
+
case 'marginTop':
|
|
172
|
+
case 'marginBottom':
|
|
173
|
+
case 'top':
|
|
174
|
+
case 'bottom':
|
|
175
|
+
case 'left':
|
|
176
|
+
case 'right':
|
|
177
|
+
case 'insetInlineStart':
|
|
178
|
+
case 'insetInlineEnd':
|
|
179
|
+
case 'flexBasis': {
|
|
180
|
+
if (value.type === 'NumericLiteral' || value.type === 'StringLiteral') {
|
|
181
|
+
return (0, dimensions_1.convertUnsafeDimension)(value.value);
|
|
182
|
+
}
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
case 'padding':
|
|
186
|
+
case 'paddingInlineStart':
|
|
187
|
+
case 'paddingInlineEnd':
|
|
188
|
+
case 'paddingInline':
|
|
189
|
+
case 'paddingBlock':
|
|
190
|
+
case 'paddingLeft':
|
|
191
|
+
case 'paddingRight':
|
|
192
|
+
case 'paddingTop':
|
|
193
|
+
case 'paddingBottom':
|
|
194
|
+
case 'gap':
|
|
195
|
+
case 'rowGap':
|
|
196
|
+
case 'columnGap': {
|
|
197
|
+
if (element === 'View' || element === 'Flex' || element === 'Grid') {
|
|
198
|
+
if (value.type === 'NumericLiteral' || value.type === 'StringLiteral') {
|
|
199
|
+
return (0, dimensions_1.convertUnsafeDimension)(value.value);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
case 'fontSize': {
|
|
205
|
+
if (element === 'View' || element === 'Flex' || element === 'Grid') {
|
|
206
|
+
if (value.type === 'StringLiteral' && /^[0-4]px$/.test(value.value)) {
|
|
207
|
+
value = { type: 'NumericLiteral', value: parseInt(value.value, 10) };
|
|
208
|
+
}
|
|
209
|
+
if (value.type === 'NumericLiteral') {
|
|
210
|
+
switch (value.value) {
|
|
211
|
+
case 11: return 'ui-xs';
|
|
212
|
+
case 12: return 'ui-sm';
|
|
213
|
+
case 14: return 'ui';
|
|
214
|
+
case 16: return 'ui-lg';
|
|
215
|
+
case 18: return 'ui-xl';
|
|
216
|
+
case 20: return 'ui-2xl';
|
|
217
|
+
case 22: return 'ui-3xl';
|
|
218
|
+
default: return `[${value.value / 16}rem]`;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else if (value.type === 'StringLiteral') {
|
|
222
|
+
let m = value.value.match(/^var\(--spectrum-global-dimension-font-size-(.+)\)$/);
|
|
223
|
+
if (m) {
|
|
224
|
+
switch (m[1]) {
|
|
225
|
+
case '25': return `[${10 / 16}rem]`;
|
|
226
|
+
case '50': return 'xs';
|
|
227
|
+
case '75': return 'ui-sm';
|
|
228
|
+
case '100': return 'ui';
|
|
229
|
+
case '150': return `[${15 / 16}rem]`;
|
|
230
|
+
case '200': return 'ui-lg';
|
|
231
|
+
case '300': return 'ui-xl';
|
|
232
|
+
case '400': return 'body-xl';
|
|
233
|
+
case '500': return 'body-2xl';
|
|
234
|
+
case '600': return 'body-3xl';
|
|
235
|
+
case '700': return 'heading-lg';
|
|
236
|
+
case '800': return `[${32 / 16}rem]`;
|
|
237
|
+
case '900': return 'heading-xl';
|
|
238
|
+
case '1000': return `[${40 / 16}rem]`;
|
|
239
|
+
case '1100': return 'heading-2xl';
|
|
240
|
+
case '1200': return `[${50 / 16}rem]`;
|
|
241
|
+
case '1300': return 'heading-3xl';
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
case 'fontWeight':
|
|
249
|
+
if (element === 'View' || element === 'Flex' || element === 'Grid') {
|
|
250
|
+
if (value.type === 'StringLiteral') {
|
|
251
|
+
let m = value.value.match(/^var\(--spectrum-global-font-weight-(.+)\)$/);
|
|
252
|
+
if (m) {
|
|
253
|
+
switch (m[1]) {
|
|
254
|
+
case 'light':
|
|
255
|
+
case 'medium':
|
|
256
|
+
case 'bold':
|
|
257
|
+
case 'black':
|
|
258
|
+
case 'extra-bold':
|
|
259
|
+
return m[1];
|
|
260
|
+
case 'regular':
|
|
261
|
+
return 'normal';
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
switch (value.value) {
|
|
266
|
+
case 'normal':
|
|
267
|
+
case 'bold':
|
|
268
|
+
return value.value;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
break;
|
|
274
|
+
case 'alignSelf':
|
|
275
|
+
case 'justifySelf':
|
|
276
|
+
case 'position':
|
|
277
|
+
case 'zIndex':
|
|
278
|
+
case 'order':
|
|
279
|
+
case 'flexGrow':
|
|
280
|
+
case 'flexShrink':
|
|
281
|
+
case 'gridArea':
|
|
282
|
+
case 'gridColumn':
|
|
283
|
+
case 'gridRow':
|
|
284
|
+
case 'gridRowEnd':
|
|
285
|
+
case 'gridRowStart': {
|
|
286
|
+
if ((value.type === 'StringLiteral' && !/^(var|calc)\(/.test(value.value)) || value.type === 'NumericLiteral') {
|
|
287
|
+
return value.value;
|
|
288
|
+
}
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
case 'gridTemplateAreas': {
|
|
292
|
+
if (element === 'Flex' || element === 'Grid' || element === 'View') {
|
|
293
|
+
if (value.type === 'StringLiteral' && !value.value.startsWith('var(')) {
|
|
294
|
+
let rows = value.value.match(/"(.+?)"/g);
|
|
295
|
+
if (rows) {
|
|
296
|
+
return rows.map(r => r.slice(1, -1));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case 'display':
|
|
303
|
+
case 'justifyContent':
|
|
304
|
+
case 'alignContent':
|
|
305
|
+
case 'alignItems':
|
|
306
|
+
case 'justifyItems':
|
|
307
|
+
case 'placeItems':
|
|
308
|
+
case 'placeContent':
|
|
309
|
+
case 'placeSelf':
|
|
310
|
+
case 'flexDirection':
|
|
311
|
+
case 'flexWrap':
|
|
312
|
+
case 'flex':
|
|
313
|
+
case 'gridAutoFlow':
|
|
314
|
+
case 'gridAutoRows':
|
|
315
|
+
case 'gridAutoColumns':
|
|
316
|
+
case 'gridTemplateColumns':
|
|
317
|
+
case 'gridTemplateRows':
|
|
318
|
+
case 'float':
|
|
319
|
+
case 'clear':
|
|
320
|
+
case 'contain':
|
|
321
|
+
case 'boxSizing':
|
|
322
|
+
case 'tableLayout':
|
|
323
|
+
case 'captionSide':
|
|
324
|
+
case 'borderCollapse':
|
|
325
|
+
case 'overflow':
|
|
326
|
+
case 'overflowX':
|
|
327
|
+
case 'overflowY':
|
|
328
|
+
case 'overscrollBehavior':
|
|
329
|
+
case 'overscrollBehaviorX':
|
|
330
|
+
case 'overscrollBehaviorY':
|
|
331
|
+
case 'scrollBehavior':
|
|
332
|
+
case 'pointerEvents':
|
|
333
|
+
case 'touchAction':
|
|
334
|
+
case 'userSelect':
|
|
335
|
+
case 'visibility':
|
|
336
|
+
case 'isolation':
|
|
337
|
+
case 'transformOrigin':
|
|
338
|
+
case 'cursor':
|
|
339
|
+
case 'resize':
|
|
340
|
+
case 'scrollSnapType':
|
|
341
|
+
case 'scrollSnapAlign':
|
|
342
|
+
case 'scrollSnapStop':
|
|
343
|
+
case 'appearance':
|
|
344
|
+
case 'objectFit':
|
|
345
|
+
case 'objectPosition':
|
|
346
|
+
case 'willChange':
|
|
347
|
+
case 'rotate':
|
|
348
|
+
case 'scale':
|
|
349
|
+
case 'transform':
|
|
350
|
+
case 'borderStyle':
|
|
351
|
+
case 'fontStyle':
|
|
352
|
+
case 'listStyleType':
|
|
353
|
+
case 'listStylePosition':
|
|
354
|
+
case 'textTransform':
|
|
355
|
+
case 'textAlign':
|
|
356
|
+
case 'verticalAlign':
|
|
357
|
+
case 'textDecoration':
|
|
358
|
+
case 'textOverflow':
|
|
359
|
+
case 'hyphens':
|
|
360
|
+
case 'whiteSpace':
|
|
361
|
+
case 'textWrap':
|
|
362
|
+
case 'wordBreak':
|
|
363
|
+
case 'boxDecorationBreak':
|
|
364
|
+
case 'forcedColorAdjust':
|
|
365
|
+
case 'backgroundPosition':
|
|
366
|
+
case 'backgroundSize':
|
|
367
|
+
case 'backgroundAttachment':
|
|
368
|
+
case 'backgroundClip':
|
|
369
|
+
case 'backgroundRepeat':
|
|
370
|
+
case 'backgroundOrigin':
|
|
371
|
+
case 'backgroundBlendMode':
|
|
372
|
+
case 'mixBlendMode':
|
|
373
|
+
case 'opacity':
|
|
374
|
+
case 'outlineStyle':
|
|
375
|
+
case 'animationDirection':
|
|
376
|
+
case 'animationFillMode':
|
|
377
|
+
case 'animationTimingFunction':
|
|
378
|
+
case 'animationDelay':
|
|
379
|
+
case 'transitionTimingFunction':
|
|
380
|
+
case 'transitionDelay': {
|
|
381
|
+
if (element === 'Flex' || element === 'Grid' || element === 'View') {
|
|
382
|
+
if ((value.type === 'StringLiteral' && !/^(var|calc)\(/.test(value.value)) || value.type === 'NumericLiteral') {
|
|
383
|
+
return value.value;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
case 'animationDuration':
|
|
389
|
+
case 'transitionDuration': {
|
|
390
|
+
if (element === 'Flex' || element === 'Grid' || element === 'View') {
|
|
391
|
+
if (value.type === 'StringLiteral') {
|
|
392
|
+
let m = value.value.match(/^var\(--spectrum-global-animation-duration-(.+)\)$/);
|
|
393
|
+
if (m) {
|
|
394
|
+
switch (m[1]) {
|
|
395
|
+
case '0': return 0;
|
|
396
|
+
case '100': return 130;
|
|
397
|
+
case '200': return 160;
|
|
398
|
+
case '300': return 190;
|
|
399
|
+
case '400': return 220;
|
|
400
|
+
case '500': return 250;
|
|
401
|
+
case '600': return 300;
|
|
402
|
+
case '700': return 350;
|
|
403
|
+
case '800': return 400;
|
|
404
|
+
case '900': return 450;
|
|
405
|
+
case '1000': return 500;
|
|
406
|
+
case '2000': return 1000;
|
|
407
|
+
case '4000': return 2000;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
else if (/^\d+(s|ms)$/.test(value.value)) {
|
|
411
|
+
return value.value;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
else if (value.type === 'NumericLiteral') {
|
|
415
|
+
return value.value;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.getPropValue = getPropValue;
|
|
27
|
+
exports.nameFromExpression = nameFromExpression;
|
|
28
|
+
exports.capitalize = capitalize;
|
|
29
|
+
exports.addComment = addComment;
|
|
30
|
+
exports.addComponentImport = addComponentImport;
|
|
31
|
+
exports.removeComponentImport = removeComponentImport;
|
|
32
|
+
exports.getName = getName;
|
|
33
|
+
const t = __importStar(require("@babel/types"));
|
|
34
|
+
function getPropValue(node) {
|
|
35
|
+
if (node?.type === 'JSXExpressionContainer') {
|
|
36
|
+
if (node.expression.type === 'JSXEmptyExpression') {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return node.expression;
|
|
40
|
+
}
|
|
41
|
+
if (node?.type === 'RestElement' ||
|
|
42
|
+
node?.type === 'ObjectPattern' ||
|
|
43
|
+
node?.type === 'ArrayPattern' ||
|
|
44
|
+
node?.type === 'AssignmentPattern') {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return node;
|
|
48
|
+
}
|
|
49
|
+
function nameFromExpression(expr) {
|
|
50
|
+
switch (expr.type) {
|
|
51
|
+
case 'Identifier':
|
|
52
|
+
case 'JSXIdentifier':
|
|
53
|
+
return expr.name;
|
|
54
|
+
case 'CallExpression':
|
|
55
|
+
case 'NewExpression':
|
|
56
|
+
case 'OptionalCallExpression':
|
|
57
|
+
return nameFromExpression(expr.callee);
|
|
58
|
+
case 'MemberExpression':
|
|
59
|
+
case 'OptionalMemberExpression':
|
|
60
|
+
return nameFromExpression(expr.object) + capitalize(nameFromExpression(expr.property));
|
|
61
|
+
case 'FunctionExpression':
|
|
62
|
+
case 'ClassExpression':
|
|
63
|
+
return expr.id ? nameFromExpression(expr.id) : '';
|
|
64
|
+
case 'ConditionalExpression':
|
|
65
|
+
return nameFromExpression(expr.test);
|
|
66
|
+
case 'UnaryExpression':
|
|
67
|
+
return nameFromExpression(expr.argument);
|
|
68
|
+
case 'ParenthesizedExpression':
|
|
69
|
+
return nameFromExpression(expr.expression);
|
|
70
|
+
case 'JSXExpressionContainer':
|
|
71
|
+
return expr.expression.type !== 'JSXEmptyExpression' ? nameFromExpression(expr.expression) : '';
|
|
72
|
+
case 'BinaryExpression':
|
|
73
|
+
case 'LogicalExpression':
|
|
74
|
+
case 'AssignmentExpression':
|
|
75
|
+
return nameFromExpression(expr.left) + capitalize(nameFromExpression(expr.right));
|
|
76
|
+
case 'AwaitExpression':
|
|
77
|
+
return expr.argument ? nameFromExpression(expr.argument) : '';
|
|
78
|
+
case 'SequenceExpression':
|
|
79
|
+
return expr.expressions.reduce((p, e) => {
|
|
80
|
+
let v = nameFromExpression(e);
|
|
81
|
+
return p ? p + capitalize(v) : v;
|
|
82
|
+
}, '');
|
|
83
|
+
default:
|
|
84
|
+
return '';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function capitalize(string) {
|
|
88
|
+
return string[0].toUpperCase() + string.slice(1);
|
|
89
|
+
}
|
|
90
|
+
function addComment(node, comment) {
|
|
91
|
+
if (!node.comments) {
|
|
92
|
+
node.comments = [];
|
|
93
|
+
}
|
|
94
|
+
node.comments.push({
|
|
95
|
+
type: 'Line',
|
|
96
|
+
value: comment,
|
|
97
|
+
leading: true
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function addComponentImport(path, newComponent) {
|
|
101
|
+
// If newComponent variable already exists in scope, alias new import to avoid conflict.
|
|
102
|
+
let existingBinding = path.scope.getBinding(newComponent);
|
|
103
|
+
let localName = newComponent;
|
|
104
|
+
if (existingBinding) {
|
|
105
|
+
let newName = newComponent;
|
|
106
|
+
let i = 1;
|
|
107
|
+
while (path.scope.hasBinding(newName)) {
|
|
108
|
+
newName = newComponent + i;
|
|
109
|
+
i++;
|
|
110
|
+
}
|
|
111
|
+
localName = newName;
|
|
112
|
+
}
|
|
113
|
+
let existingImport = path.node.body.find((node) => t.isImportDeclaration(node) && node.source.value === '@react-spectrum/s2');
|
|
114
|
+
if (existingImport && t.isImportDeclaration(existingImport)) {
|
|
115
|
+
let specifier = existingImport.specifiers.find((specifier) => {
|
|
116
|
+
return (t.isImportSpecifier(specifier) &&
|
|
117
|
+
specifier.imported.type === 'Identifier' &&
|
|
118
|
+
specifier.imported.name === newComponent);
|
|
119
|
+
});
|
|
120
|
+
if (specifier) {
|
|
121
|
+
// Already imported
|
|
122
|
+
return localName;
|
|
123
|
+
}
|
|
124
|
+
existingImport.specifiers.push(t.importSpecifier(t.identifier(localName), t.identifier(newComponent)));
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
let importDeclaration = t.importDeclaration([
|
|
128
|
+
t.importSpecifier(t.identifier(localName), t.identifier(newComponent))
|
|
129
|
+
], t.stringLiteral('@react-spectrum/s2'));
|
|
130
|
+
path.node.body.unshift(importDeclaration);
|
|
131
|
+
}
|
|
132
|
+
return localName;
|
|
133
|
+
}
|
|
134
|
+
function removeComponentImport(path, component) {
|
|
135
|
+
let existingImport = path.node.body.find((node) => t.isImportDeclaration(node) && node.source.value === '@adobe/react-spectrum' || t.isImportDeclaration(node) && node.source.value.startsWith('@react-spectrum/'));
|
|
136
|
+
if (existingImport && t.isImportDeclaration(existingImport)) {
|
|
137
|
+
let specifier = existingImport.specifiers.find((specifier) => {
|
|
138
|
+
return (t.isImportSpecifier(specifier) &&
|
|
139
|
+
specifier.imported.type === 'Identifier' &&
|
|
140
|
+
specifier.imported.name === component);
|
|
141
|
+
});
|
|
142
|
+
if (specifier) {
|
|
143
|
+
existingImport.specifiers = existingImport.specifiers.filter((s) => s !== specifier);
|
|
144
|
+
if (existingImport.specifiers.length === 0) {
|
|
145
|
+
path.node.body = path.node.body.filter((node) => node !== existingImport);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Look up the name in path.scope and find the original binding.
|
|
152
|
+
* Returns the original name even if an alias is used.
|
|
153
|
+
*/
|
|
154
|
+
function getName(path, identifier) {
|
|
155
|
+
let binding = path.scope.getBinding(identifier.name);
|
|
156
|
+
if (binding && t.isImportSpecifier(binding.path.node) && t.isIdentifier(binding.path.node.imported)) {
|
|
157
|
+
return binding.path.node.imported.name;
|
|
158
|
+
}
|
|
159
|
+
return identifier.name;
|
|
160
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getComponents = getComponents;
|
|
7
|
+
const parser_1 = require("@babel/parser");
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs_1 = require("fs");
|
|
10
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
11
|
+
function getComponents() {
|
|
12
|
+
// Determine list of available components in S2 from index.ts
|
|
13
|
+
let availableComponents = new Set();
|
|
14
|
+
const packagePath = require.resolve('@react-spectrum/s2');
|
|
15
|
+
const indexPath = path.join(path.dirname(packagePath), process.env.NODE_ENV === 'test' ? 'src/index.ts' : '../src/index.ts');
|
|
16
|
+
let index = (0, parser_1.parse)((0, fs_1.readFileSync)(indexPath, 'utf8'), { sourceType: 'module', plugins: ['typescript'] });
|
|
17
|
+
(0, traverse_1.default)(index, {
|
|
18
|
+
ExportNamedDeclaration(path) {
|
|
19
|
+
if (path.node.exportKind === 'value') {
|
|
20
|
+
for (let specifier of path.node.specifiers) {
|
|
21
|
+
availableComponents.add(specifier.exported.type === 'Identifier' ? specifier.exported.name : specifier.exported.value);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
return availableComponents;
|
|
27
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.s1_to_s2 = s1_to_s2;
|
|
7
|
+
const addMacroSupport_js_1 = require("./utils/addMacroSupport.js");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const installPackage_js_1 = __importDefault(require("./utils/installPackage.js"));
|
|
10
|
+
const logger_js_1 = __importDefault(require("./utils/logger.js"));
|
|
11
|
+
const transform_js_1 = require("./transform.js");
|
|
12
|
+
const waitForKeypress_js_1 = require("./utils/waitForKeypress.js");
|
|
13
|
+
const boxen = require('boxen');
|
|
14
|
+
async function s1_to_s2(options) {
|
|
15
|
+
console.log(boxen('Welcome to the React Spectrum v3 to Spectrum 2 upgrade assistant!\n\n' +
|
|
16
|
+
'This tool will:\n\n' +
|
|
17
|
+
`1. Install the ${chalk_1.default.bold('@react-spectrum/s2')} package and setup your bundler to use the Spectrum 2 style macro.\n\n` +
|
|
18
|
+
'2. Upgrade the components in the current directory to use Spectrum 2.\n\n' +
|
|
19
|
+
'3. Provide next steps to complete your upgrade.', { borderStyle: 'round', padding: 1, borderColor: 'green' }), '\n\n');
|
|
20
|
+
console.log('Press Enter to get started...');
|
|
21
|
+
await (0, waitForKeypress_js_1.waitForKeypress)();
|
|
22
|
+
// Install S2 package
|
|
23
|
+
let isS2PackageInstalled = await (0, installPackage_js_1.default)('@react-spectrum/s2');
|
|
24
|
+
// Add support for macros
|
|
25
|
+
let { isMacroPluginInstalled, isMacroSupportEnabled } = await (0, addMacroSupport_js_1.addMacroSupport)();
|
|
26
|
+
console.log('Press Enter to upgrade components...');
|
|
27
|
+
await (0, waitForKeypress_js_1.waitForKeypress)();
|
|
28
|
+
logger_js_1.default.info('Upgrading components...');
|
|
29
|
+
await (0, transform_js_1.transform)(options);
|
|
30
|
+
logger_js_1.default.success('Upgrade complete!');
|
|
31
|
+
let nextSteps = [
|
|
32
|
+
'Add the following import to the entry component of your app: \n\n' +
|
|
33
|
+
`${chalk_1.default.bold('import \'@react-spectrum/s2/page.css\';')}\n\n` +
|
|
34
|
+
'Note that unlike React Spectrum v3, a Provider is not required.'
|
|
35
|
+
];
|
|
36
|
+
if (!isS2PackageInstalled) {
|
|
37
|
+
nextSteps.unshift(`Install the ${chalk_1.default.bold('@react-spectrum/s2')} package manually.`);
|
|
38
|
+
}
|
|
39
|
+
if (!isMacroSupportEnabled) {
|
|
40
|
+
nextSteps.push('Configure your bundler to support using the Spectrum 2 style macro.\n\n' +
|
|
41
|
+
`Macros are supported by default in Parcel v2.12.0 or later and can be used with other bundlers by${!isMacroPluginInstalled ? ` installing the ${chalk_1.default.bold('unplugin-parcel-macros')} package and` : ''} adding the plugin to your bundler config. See the examples for:\n\n` +
|
|
42
|
+
` - Webpack: ${chalk_1.default.underline('https://github.com/adobe/react-spectrum/tree/main/examples/s2-webpack-5-example')}\n` +
|
|
43
|
+
` - Next.js: ${chalk_1.default.underline('https://github.com/adobe/react-spectrum/tree/main/examples/s2-next-macros')}\n` +
|
|
44
|
+
` - Vite: ${chalk_1.default.underline('https://github.com/adobe/react-spectrum/tree/main/examples/s2-vite-project')}\n` +
|
|
45
|
+
` - Rollup: ${chalk_1.default.underline('https://github.com/adobe/react-spectrum/tree/main/examples/s2-rollup-starter-app')}\n` +
|
|
46
|
+
` - ESBuild: ${chalk_1.default.underline('https://github.com/adobe/react-spectrum/tree/main/examples/s2-esbuild-starter-app')}\n\n` +
|
|
47
|
+
`or view documentation for the plugin here: ${chalk_1.default.underline('https://jsr.io/@unplugin/macros')}`);
|
|
48
|
+
}
|
|
49
|
+
nextSteps.push('Handle remaining upgrades and run your project\'s linter or formatter.\n\n' +
|
|
50
|
+
'There may have been some upgrades that we couldn\'t handle automatically. We marked these with comments containing:\n\n' +
|
|
51
|
+
`${chalk_1.default.bold('TODO(S2-upgrade)')}\n\n` +
|
|
52
|
+
'You should be able to search your codebase and handle these manually. \n\n' +
|
|
53
|
+
'We also recommend running your project\'s code formatter (i.e. Prettier, ESLint) after the upgrade process to clean up any extraneous formatting from the codemod.\n\n' +
|
|
54
|
+
`For additional help, reference the Spectrum 2 Migration Guide: ${chalk_1.default.underline('https://github.com/adobe/react-spectrum/tree/main/packages/@react-spectrum/codemods/s1-to-s2/UPGRADE.md')}`);
|
|
55
|
+
console.log(boxen(`Next steps:\n\n ${nextSteps.map((step, i) => `${i + 1}. ${step}`).join('\n\n\n')}`, { borderStyle: 'round', padding: 1, borderColor: 'green' }));
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.transform = transform;
|
|
7
|
+
const Runner_js_1 = require("jscodeshift/src/Runner.js");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const transformPath = path_1.default.join(__dirname, 'codemods', 'codemod.js');
|
|
10
|
+
async function transform(options) {
|
|
11
|
+
let { path: filePath = '.', ...rest } = options;
|
|
12
|
+
return await (0, Runner_js_1.run)(transformPath, [filePath], rest);
|
|
13
|
+
}
|