Skip to content

Instantly share code, notes, and snippets.

@ptbrowne
Created March 14, 2018 08:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ptbrowne/4fab98301c8bcffeaf3af215025d5b2c to your computer and use it in GitHub Desktop.
Save ptbrowne/4fab98301c8bcffeaf3af215025d5b2c to your computer and use it in GitHub Desktop.
JSCodeshift Remark
<!DOCTYPE html>
<html>
<head>
<title>JSCodeshift</title>
<meta charset="utf-8">
<style>
@import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz);
@import url(https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic);
@import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700,400italic);
body { font-family: 'Droid Serif'; }
h1, h2, h3 {
font-family: 'Yanone Kaffeesatz';
font-weight: normal;
}
.remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
</style>
</head>
<body>
<textarea id="source">
# jscodeshift
## How to efficiently convert a codebase from one to another ?
---
## API 1
```js
<Button theme='danger'>
<Icon icon='delete'/>
Delete
</Button>
```
## API 2
```js
<Button icon='delete' label='Delete' theme='danger' />
```
---
class: center, middle
<img src='http://i.imgur.com/acEGnCV.gif' />
---
## [AST] : abstract syntax tree
`<Button type="reset" />`
```yaml
---
expression:
type: JSXElement
openingElement:
attributes:
- type: JSXAttribute
value:
type: Literal
value: reset
name:
type: JSXIdentifier
name: type
selfClosing: false
type: JSXOpeningElement
name:
type: JSXIdentifier
name: Button
closingElement:
type: JSXClosingElement
name:
type: JSXIdentifier
name: Button
type: ExpressionStatement
```
---
## [recast]
recAST
> to give (a metal object) a different form by melting it down and reshaping it.
- 1. Parse
- 2. Transform
- 3. Print
- Tries to preserve the style of original code as much as possible
---
```yaml
---
type: ExpressionStatement
expression:
type: JSXElement
openingElement:
type: JSXOpeningElement
name:
type: JSXIdentifier
name: Button
range:
- 1
- 7
loc:
start:
line: 1
column: 1
end:
line: 1
column: 7
lines:
length: 1
name:
indent: 0
```
---
## [jscodeshift]
- Wrapper on recast
- Runner
---
### Finding elements
```jsx
const buttons = root.find(j.JSXElement, {
openingElement: { name: { name: "Button" } }
})`
```
### Creating new elements
```jsx
new j.literal('Hello') // "Hello"
new j.jsxAttribute(
new j.jsxIdentifier('icon')
new j.jsxExpressionContainer(
new j.jsxIdentifier('myIcon')
)
) -> icon={myIcon}
...
```
### Updating elements
const update = path => {
path.node.openingElement.name.name = "Button 2"
}
// find and update all merge calls
const buttons = root.find(j.JSXElement, { openingElement: {name: {name: 'Button'}}})
buttons.forEach(update);
---
### [AST Explorer]
---
### CLI
```bash
$ find . | grep '.jsx$' | xargs jscodeshift --parser babel -t ~/code/codeshifts/button-api.js
Processing 52 files...
Spawning 3 workers...
Sending 18 files to free worker...
Sending 18 files to free worker...
Sending 16 files to free worker...
Not a simple button, cannot automatically migrate <Button className={styles['save-button']} disabled={saving} theme='regular' onClick={this.rename}>
{t('Groups.save')} {saving && <Spinner />}
</Button>
All done.
Results:
0 errors
44 unmodified
0 skipped
8 ok
Time elapsed: 1.864seconds
```
[jscodeshift]: https://github.com/facebook/jscodeshift
[recast]: https://github.com/benjamn/recast
[AST]: https://fr.wikipedia.org/wiki/Arbre_syntaxique_abstrait
[AST Explorer]: http://astexplorer.net/#/hb6iLO9hTe
</textarea>
<script src="https://remarkjs.com/downloads/remark-latest.min.js">
</script>
<script>
var slideshow = remark.create();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment