Skip to content

Commit 5de3e7b

Browse files
committed
refactor(ui-codemods): update codemod dacumentation and usage, delete old codemods
1 parent 40ca6bb commit 5de3e7b

40 files changed

+1181
-3409
lines changed

docs/contributor-docs/codemods.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
title: Writing codemods
3+
category: Contributor Guides
4+
order: 11
5+
---
6+
7+
## Codemods
8+
9+
Codemods are small scripts that can automate tedious code refactorings. It's like Search & replace, just on steroids, InstUI uses them so breaking changes during major version upgrades are easier for users. Common use cases are renaming imports or props of components.
10+
11+
To accomplish this our codemods use [jsCodeshift](https://github.com/facebook/jscodeshift). This tool parses source files to an Abstract Syntax Tree (AST) and gives us an API that can modify it.
12+
13+
### Codemod development
14+
15+
Our codemods live in the `ui-codemods` package. Each codemod is an ES module with a default export and is executed by jscodeshift. it should have the following code:
16+
17+
```ts
18+
---
19+
type: code
20+
---
21+
import type { Transform } from 'jscodeshift'
22+
/**
23+
* @param file the file to transform
24+
* @param api jscodeshift instance
25+
* @param options
26+
* @param options.filename if `filename` is specified then emitted warnings are
27+
* written to this file.
28+
* @param options.usePrettier if `true` the transformed code will be run through
29+
* [Prettier](https://prettier.io/). You can customize this through a [Prettier
30+
* config file](https://prettier.io/docs/configuration.html)
31+
* @returns the modified file as `string` or `null`
32+
*/
33+
const myCodemod: Transform = (file, api,
34+
options?: { fileName?: string; usePrettier?: boolean }) => {
35+
return instUICodemodExecutor([my, cool, scripts], file, api, options)
36+
}
37+
export default myCodemod
38+
```
39+
40+
> You can find lots of useful helper functions in `packages/ui-codemods/lib/utils/codemodhelpers.ts` and `packages/ui-codemods/lib/utils/codemodTypeCheckers.ts`
41+
42+
#### Testing codemods
43+
44+
You should write unit tests for your codemods. They are tested via test fixtures (sample before transform, sample after transform). To create a unit test for say `sampleCodemod` the following steps are needed:
45+
46+
1. create a new test in `packages/ui-codemods/lib/__node_tests__/codemod.tests.ts`:
47+
```ts
48+
---
49+
type: code
50+
---
51+
it('tests the cool sampleCodemod', () => {
52+
runTest(sampleCodemod)
53+
})
54+
```
55+
2. create a folder named `sampleCodemod` in `packages/ui-codemods/lib/__node_tests__/__testfixtures__`
56+
3. Here create sample input-output file pairs whose filename follows the following naming convention: `[fixtureName].input.[js/ts/tsx]`, `[fixtureName].output.[js/ts/tsx]`. These should be your test cases that ensure that the codemod does the transformation correctly.
57+
58+
Done! Run `npm run test:vitest ui-codemods` to run your test.
59+
60+
Finally, you should try to run your codemod as users will do:
61+
62+
```sh
63+
---
64+
type: code
65+
---
66+
npx [email protected] -t /path/to/sampleCodemod.ts /path/to/code/to/rewrite --usePrettier=false
67+
```

packages/ui-codemods/README.md

Lines changed: 5 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ category: packages
44

55
## ui-codemods
66

7-
The ui-codemods package should make it easier to deal with API changes when upgrading Instructure UI libraries.
7+
The `ui-codemods` package should make it easier to deal with API changes when upgrading Instructure UI libraries.
88

99
[![npm][npm]][npm-url]
1010
[![MIT License][license-badge]][license]
@@ -18,102 +18,20 @@ The codemod scripts can be installed via the following command:
1818
---
1919
type: code
2020
---
21-
npm install @instructure/ui-codemods
21+
# use here the InstUI version number you are upgrading to
22+
npm install @instructure/ui-codemods@10
2223
```
2324

24-
The configuration files are located in the [instui-config](#instui-config) package.
25-
This can be installed via the following command:
26-
27-
```sh
28-
---
29-
type: code
30-
---
31-
npm install @instructure/instui-config
32-
```
33-
34-
### Updating Deprecated Props
35-
36-
This codemod helps you update your project by renaming `props` that have had names changed (e.g., `onReady` => `onOpen`).
37-
38-
```sh
39-
---
40-
type: code
41-
---
42-
jscodeshift -t node_modules/@instructure/ui-codemods/lib/updatePropNames.ts <path> --config=node_modules/@instructure/instui-config/codemod-configs/v<version number ex. 5 or 6>/propNames.config.json
43-
```
44-
45-
### Updating Package Imports
46-
47-
This codemod helps you update your project by renaming `imports` that have changed (e.g., `instructure-ui` => `@instructure/<package name>`).
48-
49-
```sh
50-
---
51-
type: code
52-
---
53-
jscodeshift -t node_modules/@instructure/ui-codemods/lib/updateImports.ts <path> --config=node_modules/@instructure/instui-config/codemod-configs/v<version number ex. 5 or 6>/imports.config.js
54-
```
55-
56-
### Updating more complex props to the InstUI v8 syntax
57-
58-
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.
59-
60-
```sh
61-
---
62-
type: code
63-
---
64-
jscodeshift -t node_modules/@instructure/ui-codemods/lib/updateV7Props.ts <path> -fileName updateV7PropsWarnings.txt
65-
```
66-
67-
### Codemod for breaking changes after updating the dependencies to V8
68-
69-
```sh
70-
---
71-
type: code
72-
---
73-
jscodeshift -t node_modules/@instructure/ui-codemods/lib/updateV8Breaking.ts <path>
74-
```
75-
76-
This codemod updates breaking changes after a v8 upgrade. Run this in a project after you have upgraded your dependencies to InstUI v8.
77-
78-
### Codemod for breaking changes after updating the dependencies to V9
79-
80-
```sh
81-
---
82-
type: code
83-
---
84-
jscodeshift -t node_modules/@instructure/ui-codemods/lib/updateV9Breaking.ts <path> --parser=tsx --usePrettier=false
85-
```
86-
87-
This codemod addresses breaking changes following a v9 upgrade. Notably, it updates `EmotionThemeProvider` to `InstUISettingsProvider`. Execute this in your project post-upgrade to InstUI v9. Prettier is turned on by default for output formatting, and you can also use the `usePrettier` flag. Additionally, the parser flag can specify the parser for jsx and tsx files.
88-
8925
### Codemod for changing the color palette to the v10 color palette
9026

9127
```sh
9228
---
9329
type: code
9430
---
95-
jscodeshift -t node_modules/@instructure/ui-codemods/lib/updateV10Breaking.ts <path> --parser=tsx --usePrettier=false
96-
```
97-
98-
This codemod updates the `canvas` and `canvas-high-contrast` color palettes. Execute this in your project post-upgrade to InstUI v10. Prettier is turned on by default for output formatting, and you can also use the `usePrettier` flag. Additionally, the parser flag can specify the parser for jsx and tsx files.
99-
100-
### Codemod for adding a wrapper to ReactDOM.render()
101-
102-
```sh
103-
---
104-
type: code
105-
---
106-
jscodeshift -t node_modules/@instructure/ui-codemods/lib/updateV8ReactDOM.ts <path> -fileName updateV8ReactDOM.txt
31+
npx [email protected] -t node_modules/@instructure/ui-codemods/lib/updateV10Breaking.ts <path> --usePrettier=false
10732
```
10833

109-
This codemod updates ReactDOM.render calls with a given wrapper, for example:
110-
ReactDOM.render(<div />) -> ReactDOM.render(<Root><div /></Root>).
111-
Parameters (all optional):
112-
113-
- `fileName`: supplying this will append to the given file the warnings.
114-
- `wrapperPath`: The import path for the wrapper, default value is '@canvas/react-root'.
115-
- `wrapperTag`: The tag to wrap render calls in, default is 'Root'.
116-
- `isDefaultImport`: Is the given tag a default import? Default value is `true`.
34+
This codemod updates the `canvas` and `canvas-high-contrast` color palettes. Execute this in your project post-upgrade to InstUI v10. Prettier is turned on by default for output formatting, and you can also use the `usePrettier` flag.
11735

11836
[npm]: https://img.shields.io/npm/v/@instructure/ui-codemods.svg
11937
[npm-url]: https://npmjs.com/package/@instructure/ui-codemods
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* eslint-disable */
2+
// @ts-nocheck
3+
import { canvas, canvasHighContrast } from '@instructure/ui'
4+
5+
export const generateStyle = () => {
6+
return {
7+
logoSubtitle: {
8+
label: 'logoSubtitle',
9+
marginTop: '-3px'
10+
},
11+
optionWrapper: {
12+
label: 'optionWrapper',
13+
margin: '-0.5rem -0.75rem',
14+
padding: '0.5rem 0.75rem',
15+
border: '0 solid ' + canvas.colors.tiara,
16+
borderBottomWidth: '1px',
17+
display: 'flex',
18+
maxWidth: '100%',
19+
overflow: 'hidden',
20+
alignItems: 'center'
21+
},
22+
optionIcon: {
23+
label: 'optionIcon',
24+
width: '36px',
25+
height: '36px',
26+
backgroundColor: canvasHighContrast.colors.oxford,
27+
borderRadius: 100,
28+
flexShrink: 0,
29+
display: 'flex',
30+
justifyContent: 'center',
31+
alignItems: 'center'
32+
},
33+
truncateSingleLine: {
34+
overflow: 'hidden',
35+
whiteSpace: 'nowrap',
36+
textOverflow: 'ellipsis'
37+
}
38+
}
39+
}
40+
41+
export const generateComponentTheme = () => ({})
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* eslint-disable */
2+
// @ts-nocheck
3+
import { canvas, canvasHighContrast } from '@instructure/ui'
4+
5+
export const generateStyle = () => {
6+
return {
7+
logoSubtitle: {
8+
label: 'logoSubtitle',
9+
marginTop: '-3px'
10+
},
11+
optionWrapper: {
12+
label: 'optionWrapper',
13+
margin: '-0.5rem -0.75rem',
14+
padding: '0.5rem 0.75rem',
15+
border: '0 solid ' + canvas.colors?.contrasts?.grey1214,
16+
borderBottomWidth: '1px',
17+
display: 'flex',
18+
maxWidth: '100%',
19+
overflow: 'hidden',
20+
alignItems: 'center'
21+
},
22+
optionIcon: {
23+
label: 'optionIcon',
24+
width: '36px',
25+
height: '36px',
26+
backgroundColor: canvasHighContrast.colors?.contrasts?.grey100100,
27+
borderRadius: 100,
28+
flexShrink: 0,
29+
display: 'flex',
30+
justifyContent: 'center',
31+
alignItems: 'center'
32+
},
33+
truncateSingleLine: {
34+
overflow: 'hidden',
35+
whiteSpace: 'nowrap',
36+
textOverflow: 'ellipsis'
37+
}
38+
}
39+
}
40+
41+
export const generateComponentTheme = () => ({})
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// this is the same as the other colors test, it just makes sure that
2+
// codemods work on plain `.js` files too
3+
/* eslint-disable */
4+
// @ts-nocheck
5+
import { canvas, canvasHighContrast } from '@instructure/ui'
6+
7+
export const generateStyle = () => {
8+
return {
9+
logoSubtitle: {
10+
label: 'logoSubtitle',
11+
marginTop: '-3px'
12+
},
13+
optionWrapper: {
14+
label: 'optionWrapper',
15+
margin: '-0.5rem -0.75rem',
16+
padding: '0.5rem 0.75rem',
17+
border: '0 solid ' + canvas.colors.tiara,
18+
borderBottomWidth: '1px',
19+
display: 'flex',
20+
maxWidth: '100%',
21+
overflow: 'hidden',
22+
alignItems: 'center'
23+
},
24+
optionIcon: {
25+
label: 'optionIcon',
26+
width: '36px',
27+
height: '36px',
28+
backgroundColor: canvasHighContrast.colors.oxford,
29+
borderRadius: 100,
30+
flexShrink: 0,
31+
display: 'flex',
32+
justifyContent: 'center',
33+
alignItems: 'center'
34+
},
35+
truncateSingleLine: {
36+
overflow: 'hidden',
37+
whiteSpace: 'nowrap',
38+
textOverflow: 'ellipsis'
39+
}
40+
}
41+
}
42+
43+
export const generateComponentTheme = () => ({})
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// this is the same as the other colors test, it just makes sure that
2+
// codemods work on plain `.js` files too
3+
/* eslint-disable */
4+
// @ts-nocheck
5+
import { canvas, canvasHighContrast } from '@instructure/ui'
6+
7+
export const generateStyle = () => {
8+
return {
9+
logoSubtitle: {
10+
label: 'logoSubtitle',
11+
marginTop: '-3px'
12+
},
13+
optionWrapper: {
14+
label: 'optionWrapper',
15+
margin: '-0.5rem -0.75rem',
16+
padding: '0.5rem 0.75rem',
17+
border: '0 solid ' + canvas.colors?.contrasts?.grey1214,
18+
borderBottomWidth: '1px',
19+
display: 'flex',
20+
maxWidth: '100%',
21+
overflow: 'hidden',
22+
alignItems: 'center'
23+
},
24+
optionIcon: {
25+
label: 'optionIcon',
26+
width: '36px',
27+
height: '36px',
28+
backgroundColor: canvasHighContrast.colors?.contrasts?.grey100100,
29+
borderRadius: 100,
30+
flexShrink: 0,
31+
display: 'flex',
32+
justifyContent: 'center',
33+
alignItems: 'center'
34+
},
35+
truncateSingleLine: {
36+
overflow: 'hidden',
37+
whiteSpace: 'nowrap',
38+
textOverflow: 'ellipsis'
39+
}
40+
}
41+
}
42+
43+
export const generateComponentTheme = () => ({})

0 commit comments

Comments
 (0)