Skip to content

Commit 5890533

Browse files
authored
Merge pull request jsx-eslint#1735 from ThiefMaster/forbid-component-props
forbid-component-props: add component whitelist
2 parents dc2cd4c + 805c8ea commit 5890533

File tree

3 files changed

+66
-10
lines changed

3 files changed

+66
-10
lines changed

docs/rules/forbid-component-props.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,21 @@ The following patterns are **not** considered warnings:
3535

3636
```js
3737
...
38-
"react/forbid-component-props": [<enabled>, { "forbid": [<string>] }]
38+
"react/forbid-component-props": [<enabled>, { "forbid": [<string>|<object>] }]
3939
...
4040
```
4141

4242
### `forbid`
4343

44-
An array of strings, with the names of props that are forbidden. The default value of this option is `['className', 'style']`.
44+
An array specifying the names of props that are forbidden. The default value of this option is `['className', 'style']`.
45+
Each array element can either be a string with the property name or object specifying the property name and a component whitelist:
46+
47+
```js
48+
{
49+
"propName": "someProp",
50+
"allowedFor": [SomeComponent, AnotherComponent]
51+
}
52+
```
4553

4654

4755
### Related rules

lib/rules/forbid-component-props.js

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,41 @@ module.exports = {
3131
forbid: {
3232
type: 'array',
3333
items: {
34-
type: 'string'
34+
oneOf: [{
35+
type: 'string'
36+
}, {
37+
type: 'object',
38+
properties: {
39+
propName: {
40+
type: 'string'
41+
},
42+
allowedFor: {
43+
type: 'array',
44+
uniqueItems: true,
45+
items: {
46+
type: 'string'
47+
}
48+
}
49+
}
50+
}]
3551
}
3652
}
37-
},
38-
additionalProperties: true
53+
}
3954
}]
4055
},
4156

4257
create: function(context) {
43-
function isForbidden(prop) {
44-
const configuration = context.options[0] || {};
58+
const configuration = context.options[0] || {};
59+
const forbid = new Map((configuration.forbid || DEFAULTS).map(value => {
60+
const propName = typeof value === 'string' ? value : value.propName;
61+
const whitelist = typeof value === 'string' ? [] : (value.allowedFor || []);
62+
return [propName, whitelist];
63+
}));
4564

46-
const forbid = configuration.forbid || DEFAULTS;
47-
return forbid.indexOf(prop) >= 0;
65+
function isForbidden(prop, tagName) {
66+
const whitelist = forbid.get(prop);
67+
// if the tagName is undefined (`<this.something>`), we assume it's a forbidden element
68+
return typeof whitelist !== 'undefined' && (typeof tagName === 'undefined' || whitelist.indexOf(tagName) === -1);
4869
}
4970

5071
return {
@@ -57,7 +78,7 @@ module.exports = {
5778

5879
const prop = node.name.name;
5980

60-
if (!isForbidden(prop)) {
81+
if (!isForbidden(prop, tag)) {
6182
return;
6283
}
6384

tests/lib/rules/forbid-component-props.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ ruleTester.run('forbid-component-props', rule, {
101101
' <this.Foo {...props} />',
102102
');'
103103
].join('\n')
104+
}, {
105+
code: 'const item = (<ReactModal className="foo" />);',
106+
options: [{
107+
forbid: [{propName: 'className', allowedFor: ['ReactModal']}]
108+
}]
104109
}],
105110

106111
invalid: [{
@@ -165,5 +170,27 @@ ruleTester.run('forbid-component-props', rule, {
165170
column: 17,
166171
type: 'JSXAttribute'
167172
}]
173+
}, {
174+
code: 'const item = (<Foo className="foo" />);',
175+
options: [{
176+
forbid: [{propName: 'className', allowedFor: ['ReactModal']}]
177+
}],
178+
errors: [{
179+
message: CLASSNAME_ERROR_MESSAGE,
180+
line: 1,
181+
column: 20,
182+
type: 'JSXAttribute'
183+
}]
184+
}, {
185+
code: 'const item = (<this.ReactModal className="foo" />);',
186+
options: [{
187+
forbid: [{propName: 'className', allowedFor: ['ReactModal']}]
188+
}],
189+
errors: [{
190+
message: CLASSNAME_ERROR_MESSAGE,
191+
line: 1,
192+
column: 32,
193+
type: 'JSXAttribute'
194+
}]
168195
}]
169196
});

0 commit comments

Comments
 (0)