Skip to content

Commit 6d21f56

Browse files
committed
change in schema
1 parent f480201 commit 6d21f56

File tree

3 files changed

+107
-50
lines changed

3 files changed

+107
-50
lines changed

docs/rules/jsx-props-no-spreading.md

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,65 +8,69 @@ The following patterns are considered warnings:
88

99
```jsx
1010
<App {...props} />
11-
<App {...props} some_other_prop={some_other_prop} />
12-
<div {...props}><App /></div>
11+
<MyCustomComponent {...props} some_other_prop={some_other_prop} />
12+
<img {...props} />
1313
```
1414

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

1717
```jsx
18-
const {one_prop, two_prop} = props;
19-
<App one_prop={one_prop} two_prop={two_prop} />
18+
const {src, alt} = props;
19+
const {one_prop, two_prop} = otherProps;
20+
<MyCustomComponent one_prop={one_prop} two_prop={two_prop} />
21+
<img src={src} alt={alt} />
2022
```
2123

2224

2325
## Rule Options
2426

2527
```js
2628
...
27-
"react/jsx-props-no-spreading": [<enabled>, { "allowedFor": ["HTMLElements", "Components", {"custom": <string>}] }]
29+
"react/jsx-props-no-spreading": [{
30+
"html": "ignore" / "enforce",
31+
"custom": "ignore" / "enforce",
32+
"exceptions": [<string>]
33+
}]
2834
...
2935
```
3036

31-
### `allowedFor`
37+
### html
3238

33-
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.
39+
`html` set to `ignore` will ignore all html jsx tags like `div`, `img` etc. Default is set to `enforce`.
3440

35-
### allowedFor: HTMLTags
36-
37-
The following patterns are **not** considered warnings:
41+
The following patterns are **not** considered warnings when `html` is set to `ignore`:
3842

3943
```jsx
40-
const {one_prop, two_prop} = props;
4144
<img {...props} />
42-
<MyCustomComponent {...props} />
4345
```
4446

45-
The following patterns are considered warnings:
47+
The following patterns are still considered warnings:
4648

4749
```jsx
4850
<MyCustomComponent {...props} />
4951
```
5052

51-
### allowedFor: Components
53+
### custom
5254

53-
The following patterns are **not** considered warnings:
55+
`custom` set to `ignore` will ignore all custom jsx tags like `App`, `MyCustomComponent` etc. Default is set to `enforce`.
56+
57+
The following patterns are **not** considered warnings when `custom` is set to `ignore`:
5458

5559
```jsx
56-
const {src, alt} = props;
5760
<MyCustomComponent {...props} />
58-
<img src={src} alt={alt} />
5961
```
6062

61-
The following patterns are considered warnings:
63+
The following patterns are still considered warnings:
6264
```jsx
6365
<img {...props} />
6466
```
6567

66-
### custom Mode
68+
### exceptions
69+
70+
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`.
6771

6872
```js
69-
{ "custom": ["Image", "img"] }
73+
{ "exceptions": ["Image", "img"] }
7074
```
7175

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

89+
```js
90+
{ "html": "ignore", "exceptions": ["MyCustomComponent", "img"] }
91+
```
92+
93+
The following patterns are **not** considered warnings:
94+
95+
```jsx
96+
const {src, alt} = props;
97+
const {one_prop, two_prop} = otherProps;
98+
<img src={src} alt={alt} />
99+
<MyCustomComponent {...otherProps} />
100+
```
101+
102+
The following patterns are considered warnings:
103+
```jsx
104+
<img {...props} />
105+
```
106+
85107
## When Not To Use It
86108

87109
If you are not using JSX or have lots of props to be passed or the props spreading is used inside HOC.

lib/rules/jsx-props-no-spreading.js

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

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

9+
// ------------------------------------------------------------------------------
10+
// Constants
11+
// ------------------------------------------------------------------------------
12+
13+
const DEFAULTS = {html: 'enforce', custom: 'enforce', exceptions: []};
14+
915
// ------------------------------------------------------------------------------
1016
// Rule Definition
1117
// ------------------------------------------------------------------------------
@@ -21,23 +27,17 @@ module.exports = {
2127
schema: [{
2228
type: 'object',
2329
properties: {
24-
allowedFor: {
30+
html: {
31+
enum: ['enforce', 'ignore']
32+
},
33+
custom: {
34+
enum: ['enforce', 'ignore']
35+
},
36+
exceptions: {
2537
type: 'array',
2638
items: {
27-
oneOf: [{
28-
enum: ['HTMLTags', 'Components']
29-
}, {
30-
type: 'object',
31-
properties: {
32-
custom: {
33-
type: 'array',
34-
uniqueItems: true,
35-
items: {
36-
type: 'string'
37-
}
38-
}
39-
}
40-
}]
39+
type: 'string',
40+
uniqueItems: true
4141
}
4242
}
4343
}
@@ -46,20 +46,23 @@ module.exports = {
4646

4747
create: function (context) {
4848
const configuration = context.options[0] || {};
49-
const allowedFor = configuration.allowedFor || [];
49+
const ignoreHtmlTags = (configuration.html || DEFAULTS.html) === 'ignore';
50+
const ignoreCustomTags = (configuration.custom || DEFAULTS.custom) === 'ignore';
51+
const exceptions = configuration.exceptions || DEFAULTS.exceptions;
52+
const isException = (tag, allExceptions) => allExceptions.indexOf(tag) !== -1;
5053
return {
5154
JSXSpreadAttribute: function (node) {
5255
const tagName = node.parent.name.name;
5356
const isHTMLTag = tagName && tagName[0] !== tagName[0].toUpperCase();
54-
if (isHTMLTag && allowedFor.indexOf('HTMLTags') !== -1) {
55-
return;
56-
}
57-
if (!isHTMLTag && allowedFor.indexOf('Components') !== -1) {
57+
const isCustomTag = tagName && tagName[0] === tagName[0].toUpperCase();
58+
if (isHTMLTag &&
59+
((ignoreHtmlTags && !isException(tagName, exceptions)) ||
60+
(!ignoreHtmlTags && isException(tagName, exceptions)))) {
5861
return;
5962
}
60-
// Still if any option remains they have to be for custom tags
61-
const customTags = allowedFor.length > 0 ? (allowedFor[0].custom || []) : [];
62-
if (customTags.indexOf(tagName) !== -1) {
63+
if (isCustomTag &&
64+
((ignoreCustomTags && !isException(tagName, exceptions)) ||
65+
(!ignoreCustomTags && isException(tagName, exceptions)))) {
6366
return;
6467
}
6568
context.report({

tests/lib/rules/jsx-props-no-spreading.js

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ ruleTester.run('jsx-props-no-spreading', rule, {
4949
' <img {...props}/>',
5050
'</App>'
5151
].join('\n'),
52-
options: [{allowedFor: [{custom: ['Image', 'img']}]}]
52+
options: [{exceptions: ['Image', 'img']}]
5353
}, {
5454
code: [
5555
'const props = {src: "dummy.jpg", alt: "dummy"};',
@@ -59,7 +59,17 @@ ruleTester.run('jsx-props-no-spreading', rule, {
5959
' <img src={src} alt={alt}/>',
6060
'</App>'
6161
].join('\n'),
62-
options: [{allowedFor: ['Components']}]
62+
options: [{custom: 'ignore'}]
63+
}, {
64+
code: [
65+
'const props = {src: "dummy.jpg", alt: "dummy"};',
66+
'const { src, alt } = props;',
67+
'<App>',
68+
' <Image {...props}/>',
69+
' <img {...props}/>',
70+
'</App>'
71+
].join('\n'),
72+
options: [{custom: 'enforce', html: 'ignore', exceptions: ['Image']}]
6373
}, {
6474
code: [
6575
'const props = {src: "dummy.jpg", alt: "dummy"};',
@@ -70,7 +80,7 @@ ruleTester.run('jsx-props-no-spreading', rule, {
7080
' <div {...someOtherProps}/>',
7181
'</App>'
7282
].join('\n'),
73-
options: [{allowedFor: ['HTMLTags']}]
83+
options: [{html: 'ignore'}]
7484
}, {
7585
code: [
7686
'const props = {src: "dummy.jpg", alt: "dummy"};',
@@ -80,7 +90,7 @@ ruleTester.run('jsx-props-no-spreading', rule, {
8090
' <Image {...props}/>',
8191
'</App>'
8292
].join('\n'),
83-
options: [{allowedFor: ['HTMLTags', 'Components']}]
93+
options: [{html: 'ignore', custom: 'ignore'}]
8494
}],
8595

8696
invalid: [{
@@ -106,7 +116,18 @@ ruleTester.run('jsx-props-no-spreading', rule, {
106116
' <span {...props}/>',
107117
'</App>'
108118
].join('\n'),
109-
options: [{allowedFor: [{custom: ['Image', 'img']}]}],
119+
options: [{exceptions: ['Image', 'img']}],
120+
errors: [expectedError]
121+
}, {
122+
code: [
123+
'const props = {src: "dummy.jpg", alt: "dummy"};',
124+
'const { src, alt } = props;',
125+
'<App>',
126+
' <Image {...props}/>',
127+
' <img {...props}/>',
128+
'</App>'
129+
].join('\n'),
130+
options: [{custom: 'ignore'}],
110131
errors: [expectedError]
111132
}, {
112133
code: [
@@ -117,8 +138,19 @@ ruleTester.run('jsx-props-no-spreading', rule, {
117138
' <img {...props}/>',
118139
'</App>'
119140
].join('\n'),
120-
options: [{allowedFor: ['Components']}],
141+
options: [{html: 'ignore', exceptions: ['Image', 'img']}],
121142
errors: [expectedError]
143+
}, {
144+
code: [
145+
'const props = {src: "dummy.jpg", alt: "dummy"};',
146+
'const { src, alt } = props;',
147+
'<App>',
148+
' <Image {...props}/>',
149+
' <img {...props}/>',
150+
'</App>'
151+
].join('\n'),
152+
options: [{custom: 'ignore', html: 'ignore', exceptions: ['Image', 'img']}],
153+
errors: [expectedError, expectedError]
122154
}, {
123155
code: [
124156
'const props = {src: "dummy.jpg", alt: "dummy"};',
@@ -128,7 +160,7 @@ ruleTester.run('jsx-props-no-spreading', rule, {
128160
' <Image {...props}/>',
129161
'</App>'
130162
].join('\n'),
131-
options: [{allowedFor: ['HTMLTags']}],
163+
options: [{html: 'ignore'}],
132164
errors: [expectedError]
133165
}]
134166
});

0 commit comments

Comments
 (0)