Skip to content

Commit a87690d

Browse files
pkuczynskioliviertassinari
authored andcommitted
Add support for defining additionalLibraries as a regexp expression (#174)
* Add support for defining additionalLibraries as a regexp expression * Link to Babel docs * Add some tests * Add .idea to .gitignore * Updated example
1 parent 6e7d892 commit a87690d

File tree

10 files changed

+132
-6
lines changed

10 files changed

+132
-6
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313
# No npm lockfiles
1414
npm-shrinkwrap.json
1515
package-lock.json
16+
17+
# JetBrains IDE
18+
.idea

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,35 @@ additionalLibraries: ['react-immutable-proptypes'],
180180
```
181181
both will be removed.
182182

183+
#### Regular expressions
184+
185+
If you are using Babel 7 or newer and your config is stored in [`babel.config.js`](https://babeljs.io/docs/en/configuration#babelconfigjs), you can also use a regular expression to describe modules, which should be removed.
186+
187+
This would be particularly useful when using custom prop types validators, implemented as part of your own source code. For example
188+
189+
```js
190+
import CustomPropTypes from '../../prop-types/my-own-validator'
191+
import OtherCustomPropTypes from '../../prop-types/my-other-validator'
192+
```
193+
194+
would be removed with the following setting
195+
196+
```js
197+
additionalLibraries: [/\/prop-types\/.*$/]
198+
```
199+
200+
If you use an index file
201+
202+
```js
203+
import CustomPropTypes from '../../prop-types'
204+
```
205+
206+
you could set it up as
207+
208+
```js
209+
additionalLibraries: [/\/prop-types$/]
210+
```
211+
183212
### `classNameMatchers`
184213

185214
Use this option to enable this plugin to run on components that extend a class different than `React.Component` or `React.PureComponent`.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@
5252
"eslint-plugin-mocha": "^4.11.0",
5353
"eslint-plugin-prettier": "^2.3.1",
5454
"eslint-plugin-react": "^7.4.0",
55+
"globby": "^8.0.1",
5556
"mocha": "^4.0.1",
56-
"path-exists": "^3.0.0",
5757
"pkgfiles": "^2.3.2",
5858
"prettier": "^1.14.3"
5959
}

src/index.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,19 @@ export default function(api) {
361361
programPath.traverse({
362362
ImportDeclaration(path) {
363363
const { source, specifiers } = path.node
364-
if (globalOptions.libraries.indexOf(source.value) === -1) {
364+
365+
const found = globalOptions.libraries.some(library => {
366+
if (library instanceof RegExp) {
367+
return library.test(source.value)
368+
}
369+
370+
return source.value === library
371+
})
372+
373+
if (!found) {
365374
return
366375
}
376+
367377
const haveUsedSpecifiers = specifiers.some(specifier => {
368378
const importedIdentifierName = specifier.local.name
369379
const { referencePaths } = path.scope.getBinding(importedIdentifierName)

test/fixtures.test.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
import path from 'path'
55
import fs from 'fs'
6+
import globby from 'globby'
67
import { assert } from 'chai'
7-
import pathExists from 'path-exists'
88
import { transformFileSync } from '@babel/core'
99
import babelPluginSyntaxJsx from '@babel/plugin-syntax-jsx'
1010
import babelPluginExternalHelpers from '@babel/plugin-external-helpers'
@@ -31,10 +31,11 @@ describe('fixtures', () => {
3131
let expected
3232
let options = {}
3333

34-
const optionsPath = path.join(fixtureDir, 'options.json')
35-
if (pathExists.sync(optionsPath)) {
34+
const optionsPaths = globby.sync(path.join(fixtureDir, 'options.{js,json}'))
35+
36+
optionsPaths.forEach(optionsPath => {
3637
options = require(optionsPath) // eslint-disable-line global-require, import/no-dynamic-require
37-
}
38+
})
3839

3940
const filename = mode === 'options' ? 'expected.js' : `expected-${mode}.js`
4041

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React, { Component } from 'react'
2+
import PropTypes from 'prop-types'
3+
import CustomPropTypes from './custom-prop-types'
4+
5+
export default class Greeting extends Component {
6+
constructor (props, context) {
7+
super(props, context)
8+
const appName = context.store.getState().appName
9+
this.state = {
10+
appName: appName
11+
}
12+
}
13+
14+
render () {
15+
return <h1>Welcome {this.props.name} and {this.props.friends.join(', ')} to {this.state.appName}</h1>;
16+
}
17+
}
18+
19+
Greeting.propTypes = {
20+
name: PropTypes.string.isRequired,
21+
friends: CustomPropTypes.customValidator
22+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const customValidator = (props, propName, componentName) => {
2+
}
3+
4+
export default {
5+
customValidator
6+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"use strict";
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
exports.default = void 0;
7+
8+
var _react = babelHelpers.interopRequireWildcard(require("react"));
9+
10+
var Greeting =
11+
/*#__PURE__*/
12+
function (_Component) {
13+
babelHelpers.inherits(Greeting, _Component);
14+
15+
function Greeting(props, context) {
16+
var _this;
17+
18+
babelHelpers.classCallCheck(this, Greeting);
19+
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Greeting).call(this, props, context));
20+
var appName = context.store.getState().appName;
21+
_this.state = {
22+
appName: appName
23+
};
24+
return _this;
25+
}
26+
27+
babelHelpers.createClass(Greeting, [{
28+
key: "render",
29+
value: function render() {
30+
return _react.default.createElement("h1", null, "Welcome ", this.props.name, " and ", this.props.friends.join(', '), " to ", this.state.appName);
31+
}
32+
}]);
33+
return Greeting;
34+
}(_react.Component);
35+
36+
exports.default = Greeting;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React, { Component } from 'react';
2+
export default class Greeting extends Component {
3+
constructor(props, context) {
4+
super(props, context);
5+
const appName = context.store.getState().appName;
6+
this.state = {
7+
appName: appName
8+
};
9+
}
10+
11+
render() {
12+
return <h1>Welcome {this.props.name} and {this.props.friends.join(', ')} to {this.state.appName}</h1>;
13+
}
14+
15+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
additionalLibraries: [/\/custom-prop-types$/],
3+
removeImport: true
4+
}

0 commit comments

Comments
 (0)