babel-helper-decorate-react
Version:
Babel Helper for custom decorator for React Component
313 lines (218 loc) • 7.51 kB
Markdown
# babel-helper-decorate-react
[](https://travis-ci.org/imcuttle/babel-helper-decorate-react)
[](https://codecov.io/github/imcuttle/babel-helper-decorate-react?branch=master)
[](https://www.npmjs.com/package/babel-helper-decorate-react)
[](https://www.npmjs.com/package/babel-helper-decorate-react)
[](https://prettier.io/)
[](https://conventionalcommits.org)
> Babel Helper for custom decorator for React Component
### Input
```jsx
export const Button = () => {
return <button>button</button>
}
// decorate-enable-next-line { "argument": 123 }
export default class ButtonDefault extends React.Component {
// ...
}
// decorate-disable-next-line
export class Button2 extends React.Component {
// ...
}
```
### Output
```jsx
import hoc from '/your/hoc/path'
export const Button = hoc()(() => {
return <button>button</button>
})
// decorate-enable-next-line { "argument": 123 }
export default
@hoc({ argument: 123 })
class ButtonDefault extends React.Component {
// ...
}
// decorate-disable-next-line
export class Button2 extends React.Component {
// ...
}
```
## Why?
It's useful for decorate react component for react component, like use mobx-react `observer`.
### `babelConfig`
```diff
{
plugins: [
+ 'babel-helper-decorate-react/mobx'
]
}
```
### `babel-helper-decorate-react/mobx/decorate`
```js
const mobx = require('mobx-react')
module.exports = () => {
return (Component) => {
return mobx.observer(Component)
}
}
```
### `Input`
```jsx
export const Button = () => {
return <button>button</button>
}
/* mobx-observer-disable */
export const ButtonDisable = () => {
return <button>button</button>
}
/* mobx-observer-enable */
export default class ButtonDefault extends React.Component {
// ...
}
```
### Output
```jsx
import decorate from 'babel-helper-decorate-react/mobx/decorate'
// To be observer component
export const Button = decorate()(() => {
return <button>button</button>
})
export const ButtonDisable = () => {
return <button>button</button>
}
// To be observer component
export default
@decorate()
class ButtonDefault extends React.Component {
// ...
}
```
## Installation
```bash
npm install babel-helper-decorate-react
# or use yarn
yarn add babel-helper-decorate-react
```
## Usage
```javascript
import babel from '@babel/core'
import createDecorateReactVisitor from 'babel-helper-decorate-react'
babel.transform(code, {
plugins: [
{
visitor: createDecorateReactVisitor({
// ...opts
})
}
]
})
```
## API
### `createDecorateReactVisitor(options?)`
#### `Options`
extends [createDecorateVisitor#Options](#options-1)
##### `detectComponentName`
Should detect react component name?
`App` is valid, `app` is invalid.
- **Type:** `boolean`
- **Default:** `true`
##### `detectClassComponent`
Should detect react class component?
- **Type:** `boolean`
- **Default:** `true`
##### `detectFunctionComponent`
Should detect react function component?
- **Type:** `boolean`
- **Default:** `true`
##### `reactClassMemberTokens`
The MemberExpression or Identifier tokens for Detecting React class component
- **Type:** `string[]`
- **Default:** `['React.Profiler', 'React.Suspense', 'React.StrictMode', 'React.Fragment', 'Profiler', 'Suspense', 'StrictMode', 'Fragment']`
##### `reactClassSuperTokens`
The super class tokens for Detecting React class component
- **Type:** `string[]`
- **Default:** `['React.Component', 'React.PureComponent', 'Component', 'PureComponent']`
##### `reactClassCallTokens`
The CallExpression tokens for Detecting React class component
- **Type:** `string[]`
- **Default:** `['React.createRef', 'React.createFactory', 'React.createElement', 'React.cloneElement', 'createRef', 'createFactory', 'createElement', 'cloneElement']`
##### `reactClassMethodsTokens`
The ClassMethod tokens for Detecting React class component
- **Type:** `string[]`
- **Default:** `['componentDidUpdate', 'componentDidCatch', 'componentDidMount', 'componentWillMount', 'componentWillReceiveProps', 'componentWillUnmount', 'componentWillUpdate', 'UNSAFE_componentWillMount', 'UNSAFE_componentWillReceiveProps', 'UNSAFE_componentWillUpdate', 'getSnapshotBeforeUpdate', 'shouldComponentUpdate', 'render']`
##### `reactFunctionCallTokens`
The ClassMethod tokens for Detecting React function component
- **Type:** `string[]`
- **Default:** `['React.createRef', 'React.createFactory', 'React.createElement', 'React.cloneElement', 'createRef', 'createFactory', 'createElement', 'cloneElement', 'React.useCallback', 'React.useEffect', 'React.useMemo', 'React.useImperativeHandle', 'React.useLayoutEffect', 'React.useReducer', 'React.useContext', 'React.useState', 'React.useDebugValue', 'React.useRef', 'useCallback', 'useEffect', 'useMemo', 'useImperativeHandle', 'useLayoutEffect', 'useReducer', 'useContext', 'useState', 'useDebugValue', 'useRef']`
### createDecorateVisitor
#### Options
##### `prefix`
Comment prefix for enable or disable decoration like eslint comment
```js
/* decorate-disable */
/* decorate-enable */
// decorate-disable-next-line
// decorate-disable-line
// decorate-enable-next-line
// decorate-enable-line
```
- **Type:** `string`
- **Default:** `'decorate'`
##### `decorateLibPath`
The Path of decoration library.
- **Type:** `string`
- **Default:** `null`
##### `moduleInteropPath`
You may not use it.
- **Type:** `string | null`
- **Default:** `require.resolve('module-interop')`
##### `defaultEnable`
The decoration's status by default
you can use `// decorate-enable-next-line` to enable when is disabled by default
- **Type:** `boolean`
- **Default:** `true`
##### `detectScopeDepth`
The visitorType matched scope depth.
`-1` means allow any depth.
```jsx
const Button = () => {
// scope depth: 2
const Inner = () => <button>inner</button>
// scope depth: 1
return <button>123</button>
}
```
- **Type:** `number`
- **Default:** `-1`
##### `wrapFunctionComponentDecorateTokens`
should wrap function component decorator
```jsx
// Input
const Button = forwardRef(() => {
// scope depth: 1
return <button>123</button>
})
// Output
const Button = decorate()(
forwardRef(() => {
// scope depth: 1
return <button>123</button>
})
)
```
- **Type:** `string[]`
- **Default:** `['forwardRef', 'React.forwardRef']`
## Contributing
- Fork it!
- Create your new branch:
`git checkout -b feature-new` or `git checkout -b fix-which-bug`
- Start your magic work now
- Make sure npm test passes
- Commit your changes:
`git commit -am 'feat: some description (close #123)'` or `git commit -am 'fix: some description (fix #123)'`
- Push to the branch: `git push`
- Submit a pull request :)
## Authors
This library is written and maintained by imcuttle, <a href="mailto:imcuttle@163.com">imcuttle@163.com</a>.
## License
MIT - [imcuttle](https://github.com/imcuttle) 🐟