An open API service indexing awesome lists of open source software.

https://github.com/imcuttle/babel-helper-decorate-react

Babel Helper for custom decorator for React Component
https://github.com/imcuttle/babel-helper-decorate-react

Last synced: 8 months ago
JSON representation

Babel Helper for custom decorator for React Component

Awesome Lists containing this project

README

          

# babel-helper-decorate-react

[![Build status](https://img.shields.io/travis/imcuttle/babel-helper-decorate-react/master.svg?style=flat-square)](https://travis-ci.org/imcuttle/babel-helper-decorate-react)
[![Test coverage](https://img.shields.io/codecov/c/github/imcuttle/babel-helper-decorate-react.svg?style=flat-square)](https://codecov.io/github/imcuttle/babel-helper-decorate-react?branch=master)
[![NPM version](https://img.shields.io/npm/v/babel-helper-decorate-react.svg?style=flat-square)](https://www.npmjs.com/package/babel-helper-decorate-react)
[![NPM Downloads](https://img.shields.io/npm/dm/babel-helper-decorate-react.svg?style=flat-square&maxAge=43200)](https://www.npmjs.com/package/babel-helper-decorate-react)
[![Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://prettier.io/)
[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg?style=flat-square)](https://conventionalcommits.org)

> Babel Helper for custom decorator for React Component

### Input

```jsx
export const Button = () => {
return 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
})

// 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
}

/* mobx-observer-disable */
export const ButtonDisable = () => {
return 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
})

export const ButtonDisable = () => {
return 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 = () => inner

// scope depth: 1
return 123
}
```

- **Type:** `number`
- **Default:** `-1`

##### `wrapFunctionComponentDecorateTokens`

should wrap function component decorator

```jsx
// Input
const Button = forwardRef(() => {
// scope depth: 1
return 123
})

// Output
const Button = decorate()(
forwardRef(() => {
// scope depth: 1
return 123
})
)
```

- **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, imcuttle@163.com.

## License

MIT - [imcuttle](https://github.com/imcuttle) 🐟