Skip to content

Commit

Permalink
change in schema
Browse files Browse the repository at this point in the history
  • Loading branch information
ashbhir committed Mar 10, 2019
1 parent f480201 commit 6d21f56
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 50 deletions.
62 changes: 42 additions & 20 deletions docs/rules/jsx-props-no-spreading.md
Expand Up @@ -8,65 +8,69 @@ The following patterns are considered warnings:

```jsx
<App {...props} />
<App {...props} some_other_prop={some_other_prop} />
<div {...props}><App /></div>
<MyCustomComponent {...props} some_other_prop={some_other_prop} />
<img {...props} />
```

The following patterns are **not** considered warnings:

```jsx
const {one_prop, two_prop} = props;
<App one_prop={one_prop} two_prop={two_prop} />
const {src, alt} = props;
const {one_prop, two_prop} = otherProps;
<MyCustomComponent one_prop={one_prop} two_prop={two_prop} />
<img src={src} alt={alt} />
```


## Rule Options

```js
...
"react/jsx-props-no-spreading": [<enabled>, { "allowedFor": ["HTMLElements", "Components", {"custom": <string>}] }]
"react/jsx-props-no-spreading": [{
"html": "ignore" / "enforce",
"custom": "ignore" / "enforce",
"exceptions": [<string>]
}]
...
```

### `allowedFor`
### html

An array specifying specifying the exceptions to which this rule should not apply for and hence props spreading should be allowed. The default is none.
`html` set to `ignore` will ignore all html jsx tags like `div`, `img` etc. Default is set to `enforce`.

### allowedFor: HTMLTags

The following patterns are **not** considered warnings:
The following patterns are **not** considered warnings when `html` is set to `ignore`:

```jsx
const {one_prop, two_prop} = props;
<img {...props} />
<MyCustomComponent {...props} />
```

The following patterns are considered warnings:
The following patterns are still considered warnings:

```jsx
<MyCustomComponent {...props} />
```

### allowedFor: Components
### custom

The following patterns are **not** considered warnings:
`custom` set to `ignore` will ignore all custom jsx tags like `App`, `MyCustomComponent` etc. Default is set to `enforce`.

The following patterns are **not** considered warnings when `custom` is set to `ignore`:

```jsx
const {src, alt} = props;
<MyCustomComponent {...props} />
<img src={src} alt={alt} />
```

The following patterns are considered warnings:
The following patterns are still considered warnings:
```jsx
<img {...props} />
```

### custom Mode
### exceptions

An "exception" will always flip the resulting html or custom setting for that component - ie, html set to `ignore`, with an exception of `div` will enforce on an `div`; custom set to `enforce` with an exception of `Foo` will ignore `Foo`.

```js
{ "custom": ["Image", "img"] }
{ "exceptions": ["Image", "img"] }
```

The following patterns are **not** considered warnings:
Expand All @@ -82,6 +86,24 @@ The following patterns are considered warnings:
<MyCustomComponent {...props} />
```

```js
{ "html": "ignore", "exceptions": ["MyCustomComponent", "img"] }
```

The following patterns are **not** considered warnings:

```jsx
const {src, alt} = props;
const {one_prop, two_prop} = otherProps;
<img src={src} alt={alt} />
<MyCustomComponent {...otherProps} />
```

The following patterns are considered warnings:
```jsx
<img {...props} />
```

## When Not To Use It

If you are not using JSX or have lots of props to be passed or the props spreading is used inside HOC.
49 changes: 26 additions & 23 deletions lib/rules/jsx-props-no-spreading.js
Expand Up @@ -6,6 +6,12 @@

const docsUrl = require('../util/docsUrl');

// ------------------------------------------------------------------------------
// Constants
// ------------------------------------------------------------------------------

const DEFAULTS = {html: 'enforce', custom: 'enforce', exceptions: []};

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
Expand All @@ -21,23 +27,17 @@ module.exports = {
schema: [{
type: 'object',
properties: {
allowedFor: {
html: {
enum: ['enforce', 'ignore']
},
custom: {
enum: ['enforce', 'ignore']
},
exceptions: {
type: 'array',
items: {
oneOf: [{
enum: ['HTMLTags', 'Components']
}, {
type: 'object',
properties: {
custom: {
type: 'array',
uniqueItems: true,
items: {
type: 'string'
}
}
}
}]
type: 'string',
uniqueItems: true
}
}
}
Expand All @@ -46,20 +46,23 @@ module.exports = {

create: function (context) {
const configuration = context.options[0] || {};
const allowedFor = configuration.allowedFor || [];
const ignoreHtmlTags = (configuration.html || DEFAULTS.html) === 'ignore';
const ignoreCustomTags = (configuration.custom || DEFAULTS.custom) === 'ignore';
const exceptions = configuration.exceptions || DEFAULTS.exceptions;
const isException = (tag, allExceptions) => allExceptions.indexOf(tag) !== -1;
return {
JSXSpreadAttribute: function (node) {
const tagName = node.parent.name.name;
const isHTMLTag = tagName && tagName[0] !== tagName[0].toUpperCase();
if (isHTMLTag && allowedFor.indexOf('HTMLTags') !== -1) {
return;
}
if (!isHTMLTag && allowedFor.indexOf('Components') !== -1) {
const isCustomTag = tagName && tagName[0] === tagName[0].toUpperCase();
if (isHTMLTag &&
((ignoreHtmlTags && !isException(tagName, exceptions)) ||
(!ignoreHtmlTags && isException(tagName, exceptions)))) {
return;
}
// Still if any option remains they have to be for custom tags
const customTags = allowedFor.length > 0 ? (allowedFor[0].custom || []) : [];
if (customTags.indexOf(tagName) !== -1) {
if (isCustomTag &&
((ignoreCustomTags && !isException(tagName, exceptions)) ||
(!ignoreCustomTags && isException(tagName, exceptions)))) {
return;
}
context.report({
Expand Down
46 changes: 39 additions & 7 deletions tests/lib/rules/jsx-props-no-spreading.js
Expand Up @@ -49,7 +49,7 @@ ruleTester.run('jsx-props-no-spreading', rule, {
' <img {...props}/>',
'</App>'
].join('\n'),
options: [{allowedFor: [{custom: ['Image', 'img']}]}]
options: [{exceptions: ['Image', 'img']}]
}, {
code: [
'const props = {src: "dummy.jpg", alt: "dummy"};',
Expand All @@ -59,7 +59,17 @@ ruleTester.run('jsx-props-no-spreading', rule, {
' <img src={src} alt={alt}/>',
'</App>'
].join('\n'),
options: [{allowedFor: ['Components']}]
options: [{custom: 'ignore'}]
}, {
code: [
'const props = {src: "dummy.jpg", alt: "dummy"};',
'const { src, alt } = props;',
'<App>',
' <Image {...props}/>',
' <img {...props}/>',
'</App>'
].join('\n'),
options: [{custom: 'enforce', html: 'ignore', exceptions: ['Image']}]
}, {
code: [
'const props = {src: "dummy.jpg", alt: "dummy"};',
Expand All @@ -70,7 +80,7 @@ ruleTester.run('jsx-props-no-spreading', rule, {
' <div {...someOtherProps}/>',
'</App>'
].join('\n'),
options: [{allowedFor: ['HTMLTags']}]
options: [{html: 'ignore'}]
}, {
code: [
'const props = {src: "dummy.jpg", alt: "dummy"};',
Expand All @@ -80,7 +90,7 @@ ruleTester.run('jsx-props-no-spreading', rule, {
' <Image {...props}/>',
'</App>'
].join('\n'),
options: [{allowedFor: ['HTMLTags', 'Components']}]
options: [{html: 'ignore', custom: 'ignore'}]
}],

invalid: [{
Expand All @@ -106,7 +116,18 @@ ruleTester.run('jsx-props-no-spreading', rule, {
' <span {...props}/>',
'</App>'
].join('\n'),
options: [{allowedFor: [{custom: ['Image', 'img']}]}],
options: [{exceptions: ['Image', 'img']}],
errors: [expectedError]
}, {
code: [
'const props = {src: "dummy.jpg", alt: "dummy"};',
'const { src, alt } = props;',
'<App>',
' <Image {...props}/>',
' <img {...props}/>',
'</App>'
].join('\n'),
options: [{custom: 'ignore'}],
errors: [expectedError]
}, {
code: [
Expand All @@ -117,8 +138,19 @@ ruleTester.run('jsx-props-no-spreading', rule, {
' <img {...props}/>',
'</App>'
].join('\n'),
options: [{allowedFor: ['Components']}],
options: [{html: 'ignore', exceptions: ['Image', 'img']}],
errors: [expectedError]
}, {
code: [
'const props = {src: "dummy.jpg", alt: "dummy"};',
'const { src, alt } = props;',
'<App>',
' <Image {...props}/>',
' <img {...props}/>',
'</App>'
].join('\n'),
options: [{custom: 'ignore', html: 'ignore', exceptions: ['Image', 'img']}],
errors: [expectedError, expectedError]
}, {
code: [
'const props = {src: "dummy.jpg", alt: "dummy"};',
Expand All @@ -128,7 +160,7 @@ ruleTester.run('jsx-props-no-spreading', rule, {
' <Image {...props}/>',
'</App>'
].join('\n'),
options: [{allowedFor: ['HTMLTags']}],
options: [{html: 'ignore'}],
errors: [expectedError]
}]
});

0 comments on commit 6d21f56

Please sign in to comment.