@instructure/ui-codemods 8.17.1-snapshot.35 → 8.17.1-snapshot.80
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 +8 -0
- package/lib/helpers/replaceDeprecatedImports.ts +144 -3
- package/lib/helpers/replaceDeprecatedProps.ts +75 -7
- package/lib/helpers/v7PropsUpdateHelpers.ts +551 -0
- package/lib/updateImports.ts +1 -1
- package/lib/updatePropNames.ts +7 -2
- package/lib/updateV7Props.ts +101 -0
- package/lib/updateV8Props.ts +74 -0
- package/lib/utils/UpdateV7ButtonsLink.ts +139 -0
- package/lib/utils/updateV7ButtonsClose.ts +104 -0
- package/lib/utils/updateV7ButtonsIconCircle.ts +240 -0
- package/lib/utils/updateV7ButtonsMisc.ts +137 -0
- package/lib/utils/updateV7ButtonsWithText.ts +111 -0
- package/lib/utils/updateV7FocusableView.ts +105 -0
- package/lib/utils/updateV7Heading.ts +145 -0
- package/lib/utils/updateV7Lists.ts +113 -0
- package/lib/utils/updateV7Pill.ts +83 -0
- package/lib/utils/updateV7Popover.ts +137 -0
- package/lib/utils/updateV7Tabs.ts +129 -0
- package/lib/utils/warnV7ComponentDeprecations.ts +96 -0
- package/package.json +3 -3
- package/tsconfig.build.tsbuildinfo +1 -1
- package/lib/utils/createLiteral.ts +0 -48
- package/lib/utils/findDeprecatedProp.ts +0 -59
- package/lib/utils/findImportDeclaration.ts +0 -51
- package/lib/utils/findTransform.ts +0 -97
- package/lib/utils/parseImport.ts +0 -78
package/README.md
CHANGED
|
@@ -45,6 +45,14 @@ This codemod helps you update your project by renaming `imports` that have chang
|
|
|
45
45
|
jscodeshift -t node_modules/@instructure/ui-codemods/lib/updateImports.js <path> --config=node_modules/@instructure/instui-config/codemod-configs/v<version number ex. 5 or 6>/imports.config.js
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
### Updating more complex props to the InstUI v8 syntax
|
|
49
|
+
|
|
50
|
+
This codemod upgrades more complex changes like Button, also outputs any manual changes needed to the console. Run this in a InstUI v7 codebase only. This command has an optional fileName parameter, supplying this will append to the given file the warnings.
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
jscodeshift -t node_modules/@instructure/ui-codemods/lib/updateV7Props.js <path> -fileName updateV7PropsWarnings.txt
|
|
54
|
+
```
|
|
55
|
+
|
|
48
56
|
[npm]: https://img.shields.io/npm/v/@instructure/ui-codemods.svg
|
|
49
57
|
[npm-url]: https://npmjs.com/package/@instructure/ui-codemods
|
|
50
58
|
[license-badge]: https://img.shields.io/npm/l/instructure-ui.svg?style=flat-square
|
|
@@ -22,9 +22,6 @@
|
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import parseImport, { ParsedImport } from '../utils/parseImport'
|
|
26
|
-
import findTransform from '../utils/findTransform'
|
|
27
|
-
import findImportDeclaration from '../utils/findImportDeclaration'
|
|
28
25
|
import {
|
|
29
26
|
API,
|
|
30
27
|
ASTPath,
|
|
@@ -35,6 +32,16 @@ import {
|
|
|
35
32
|
JSCodeshift
|
|
36
33
|
} from 'jscodeshift'
|
|
37
34
|
import type { ConfigObject, TransformObj } from '../updateImports'
|
|
35
|
+
import { Transform } from '../updateImports'
|
|
36
|
+
import path from 'path'
|
|
37
|
+
|
|
38
|
+
export type ParsedImport = {
|
|
39
|
+
scope?: string
|
|
40
|
+
name?: string
|
|
41
|
+
fullName?: string
|
|
42
|
+
moduleName?: string
|
|
43
|
+
sourcePath?: string
|
|
44
|
+
}
|
|
38
45
|
|
|
39
46
|
function transformImportPath(
|
|
40
47
|
importPath: string,
|
|
@@ -319,6 +326,140 @@ function updateImports(
|
|
|
319
326
|
return hasModifications
|
|
320
327
|
}
|
|
321
328
|
|
|
329
|
+
function findImportDeclaration(
|
|
330
|
+
j: JSCodeshift,
|
|
331
|
+
root: Collection,
|
|
332
|
+
importPath: string
|
|
333
|
+
) {
|
|
334
|
+
let importDeclaration
|
|
335
|
+
const declarationQueryResult = root.find(j.ImportDeclaration, {
|
|
336
|
+
source: {
|
|
337
|
+
type: 'StringLiteral',
|
|
338
|
+
value: importPath
|
|
339
|
+
}
|
|
340
|
+
})
|
|
341
|
+
if (declarationQueryResult.length > 0) {
|
|
342
|
+
importDeclaration = declarationQueryResult.get()
|
|
343
|
+
}
|
|
344
|
+
return importDeclaration
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function findTransform(
|
|
348
|
+
transforms: Transform[],
|
|
349
|
+
importPath: string,
|
|
350
|
+
parsedImport: ParsedImport,
|
|
351
|
+
moduleName?: string
|
|
352
|
+
) {
|
|
353
|
+
return (
|
|
354
|
+
transforms.find(({ where = {} }) => {
|
|
355
|
+
// If `where` has no entries, there are no matching transforms
|
|
356
|
+
if (Object.keys(where).length === 0) return false
|
|
357
|
+
|
|
358
|
+
let performedTest = false
|
|
359
|
+
let foundTransform = true
|
|
360
|
+
|
|
361
|
+
if (where.moduleName) {
|
|
362
|
+
performedTest = true
|
|
363
|
+
|
|
364
|
+
if (moduleName) {
|
|
365
|
+
// Give preference to the module name parsed from the AST vs. the import path string
|
|
366
|
+
foundTransform = foundTransform && where.moduleName === moduleName
|
|
367
|
+
} else {
|
|
368
|
+
foundTransform =
|
|
369
|
+
foundTransform && where.moduleName === parsedImport.moduleName
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (where.moduleNames) {
|
|
374
|
+
performedTest = true
|
|
375
|
+
|
|
376
|
+
if (moduleName) {
|
|
377
|
+
foundTransform =
|
|
378
|
+
foundTransform && where.moduleNames.includes(moduleName)
|
|
379
|
+
} else {
|
|
380
|
+
foundTransform =
|
|
381
|
+
foundTransform &&
|
|
382
|
+
where.moduleNames.includes(parsedImport.moduleName!)
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (where.packageName) {
|
|
387
|
+
performedTest = true
|
|
388
|
+
|
|
389
|
+
foundTransform =
|
|
390
|
+
foundTransform && where.packageName === parsedImport.fullName
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (where.packageNames) {
|
|
394
|
+
performedTest = true
|
|
395
|
+
|
|
396
|
+
foundTransform =
|
|
397
|
+
foundTransform && where.packageNames.includes(parsedImport.fullName!)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (where.importPath) {
|
|
401
|
+
performedTest = true
|
|
402
|
+
|
|
403
|
+
foundTransform = foundTransform && where.importPath === importPath
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (where.importPattern) {
|
|
407
|
+
performedTest = true
|
|
408
|
+
|
|
409
|
+
foundTransform =
|
|
410
|
+
foundTransform && new RegExp(where.importPattern).test(importPath)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return performedTest && foundTransform
|
|
414
|
+
}) || {}
|
|
415
|
+
).transform
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function parseImport(importPath: string): ParsedImport {
|
|
419
|
+
let parsedImport = {}
|
|
420
|
+
|
|
421
|
+
if (!importPath) return {}
|
|
422
|
+
|
|
423
|
+
const splitPath = importPath.split('/')
|
|
424
|
+
|
|
425
|
+
const parseSourceAndModule = (entries: string[] = []) => {
|
|
426
|
+
if (entries.length === 0) return {}
|
|
427
|
+
|
|
428
|
+
const lastEntry = entries[entries.length - 1]
|
|
429
|
+
|
|
430
|
+
const moduleOffset = path.parse(lastEntry).name === 'index' ? 2 : 1
|
|
431
|
+
|
|
432
|
+
const moduleName = entries[entries.length - moduleOffset]
|
|
433
|
+
|
|
434
|
+
return {
|
|
435
|
+
moduleName: moduleName ? path.parse(moduleName).name : undefined,
|
|
436
|
+
sourcePath: entries.slice(0, entries.length - moduleOffset).join('/')
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (importPath[0] === '@') {
|
|
441
|
+
const [scope, name, ...rest] = splitPath
|
|
442
|
+
|
|
443
|
+
parsedImport = {
|
|
444
|
+
scope,
|
|
445
|
+
name,
|
|
446
|
+
fullName: `${scope}/${name}`,
|
|
447
|
+
moduleName: `${scope}/${name}`,
|
|
448
|
+
...parseSourceAndModule(rest)
|
|
449
|
+
}
|
|
450
|
+
} else {
|
|
451
|
+
const [name, ...rest] = splitPath
|
|
452
|
+
|
|
453
|
+
parsedImport = {
|
|
454
|
+
name,
|
|
455
|
+
fullName: name,
|
|
456
|
+
moduleName: name,
|
|
457
|
+
...parseSourceAndModule(rest)
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return parsedImport
|
|
461
|
+
}
|
|
462
|
+
|
|
322
463
|
/**
|
|
323
464
|
* Find imports
|
|
324
465
|
*
|
|
@@ -22,8 +22,6 @@
|
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import findDeprecatedProp from '../utils/findDeprecatedProp'
|
|
26
|
-
import createLiteral from '../utils/createLiteral'
|
|
27
25
|
import {
|
|
28
26
|
ASTPath,
|
|
29
27
|
Collection,
|
|
@@ -36,14 +34,16 @@ import type {
|
|
|
36
34
|
ComponentUpdateData,
|
|
37
35
|
UpdatePropNamesOptions
|
|
38
36
|
} from '../updatePropNames'
|
|
37
|
+
import { printWarning } from './v7PropsUpdateHelpers'
|
|
39
38
|
|
|
40
39
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
40
|
+
* Replaces deprecated pros and their values based on the given config
|
|
41
|
+
* object
|
|
43
42
|
* Example:
|
|
44
|
-
* <
|
|
43
|
+
* <Flex wrapItems -> <Flex wrap="wrap"
|
|
45
44
|
*/
|
|
46
45
|
export default function replaceDeprecatedProps(
|
|
46
|
+
filePath: string,
|
|
47
47
|
j: JSCodeshift,
|
|
48
48
|
root: Collection,
|
|
49
49
|
config: UpdatePropNamesOptions
|
|
@@ -91,9 +91,11 @@ export default function replaceDeprecatedProps(
|
|
|
91
91
|
// This means the value is contained in a jsx expression container. For example,
|
|
92
92
|
// in the following jsx, `<div prop={someValue} />` we are looking at `{someValue}`
|
|
93
93
|
expressionContainers.forEach((expressionContainer) => {
|
|
94
|
-
const { type } = expressionContainer.value.expression
|
|
95
94
|
// Verify that the expression container contains a literal
|
|
96
|
-
if (
|
|
95
|
+
if (
|
|
96
|
+
expressionContainer.value.expression.type ===
|
|
97
|
+
'Literal'
|
|
98
|
+
) {
|
|
97
99
|
replaceValue(
|
|
98
100
|
j,
|
|
99
101
|
literals,
|
|
@@ -101,6 +103,15 @@ export default function replaceDeprecatedProps(
|
|
|
101
103
|
attr,
|
|
102
104
|
expressionContainer
|
|
103
105
|
)
|
|
106
|
+
} else {
|
|
107
|
+
printWarning(
|
|
108
|
+
filePath,
|
|
109
|
+
el.value.loc?.start.line,
|
|
110
|
+
"Could not rename the value of '" +
|
|
111
|
+
prop +
|
|
112
|
+
"' because its value is a function or a variable " +
|
|
113
|
+
'reference. Please update manually.'
|
|
114
|
+
)
|
|
104
115
|
}
|
|
105
116
|
})
|
|
106
117
|
} else if (literals && literals.length > 0) {
|
|
@@ -159,3 +170,60 @@ const replaceValue = (
|
|
|
159
170
|
}
|
|
160
171
|
})
|
|
161
172
|
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Find the deprecated prop for a component
|
|
176
|
+
*
|
|
177
|
+
* @param config Deprecated property configuration
|
|
178
|
+
* @param comp Component name
|
|
179
|
+
* @param prop Property name
|
|
180
|
+
* @return Object if a match is found, otherwise null
|
|
181
|
+
*/
|
|
182
|
+
const findDeprecatedProp = (
|
|
183
|
+
config: UpdatePropNamesOptions,
|
|
184
|
+
comp: string,
|
|
185
|
+
prop: string
|
|
186
|
+
) => {
|
|
187
|
+
if (config && comp && prop && config[comp]) {
|
|
188
|
+
const component = config[comp]
|
|
189
|
+
|
|
190
|
+
// Iterate versions
|
|
191
|
+
const versions = Object.keys(component)
|
|
192
|
+
for (let i = 0; i < versions.length; i++) {
|
|
193
|
+
const props = component[versions[i]]
|
|
194
|
+
|
|
195
|
+
// Iterate properties
|
|
196
|
+
for (let j = 0; j < props.length; j++) {
|
|
197
|
+
const match = props[j]
|
|
198
|
+
|
|
199
|
+
if (prop === match.old) {
|
|
200
|
+
return match
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return null
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const createLiteral = (
|
|
209
|
+
j: JSCodeshift,
|
|
210
|
+
value: string | boolean | number | null
|
|
211
|
+
) => {
|
|
212
|
+
if (typeof value === 'string') {
|
|
213
|
+
return j.stringLiteral(value)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (typeof value === 'number') {
|
|
217
|
+
return j.jsxExpressionContainer(j.numericLiteral(value))
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (typeof value === 'boolean') {
|
|
221
|
+
return j.jsxExpressionContainer(j.booleanLiteral(value))
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (value === null) {
|
|
225
|
+
return j.jsxExpressionContainer(j.nullLiteral())
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return null
|
|
229
|
+
}
|