Skip to content

Commit

Permalink
Allow separate messages for each forbid value
Browse files Browse the repository at this point in the history
  • Loading branch information
geshwho committed Apr 14, 2020
1 parent 6ba4150 commit 4ac531f
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 30 deletions.
12 changes: 5 additions & 7 deletions docs/rules/forbid-component-props.md
Expand Up @@ -35,26 +35,24 @@ The following patterns are **not** considered warnings:

```js
...
"react/forbid-component-props": [<enabled>, { "forbid": [<string>|<object>], "message": <string> }]
"react/forbid-component-props": [<enabled>, { "forbid": [<string>|<object>] }]
...
```

### `forbid`

An array specifying the names of props that are forbidden. The default value of this option is `['className', 'style']`.
Each array element can either be a string with the property name or object specifying the property name and a component whitelist:
Each array element can either be a string with the property name or object specifying the property name, an optional
custom message, and a component whitelist:

```js
{
"propName": "someProp",
"allowedFor": [SomeComponent, AnotherComponent]
"allowedFor": [SomeComponent, AnotherComponent],
"message": "Avoid using someProp"
}
```

### `message`

A custom message to provide with the error. The default message is ``Prop `${prop}` is forbidden on Components``

### Related rules

- [forbid-dom-props](./forbid-dom-props.md)
13 changes: 9 additions & 4 deletions docs/rules/forbid-dom-props.md
Expand Up @@ -36,17 +36,22 @@ The following patterns are **not** considered warnings:

```js
...
"react/forbid-dom-props": [<enabled>, { "forbid": [<string>], "message": <string> }]
"react/forbid-dom-props": [<enabled>, { "forbid": [<string>|<object>] }]
...
```

### `forbid`

An array of strings, with the names of props that are forbidden. The default value of this option `[]`.
Each array element can either be a string with the property name or object specifying the property name and an optional
custom message:

### `message`

A custom message to provide with the error. The default message is ``Prop `${prop}` is forbidden on DOM Nodes``
```js
{
"propName": "someProp",
"message": "Avoid using someProp"
}
```

### Related rules

Expand Down
20 changes: 12 additions & 8 deletions lib/rules/forbid-component-props.js
Expand Up @@ -46,13 +46,13 @@ module.exports = {
items: {
type: 'string'
}
},
message: {
type: 'string'
}
}
}]
}
},
message: {
type: 'string'
}
}
}]
Expand All @@ -62,15 +62,18 @@ module.exports = {
const configuration = context.options[0] || {};
const forbid = new Map((configuration.forbid || DEFAULTS).map((value) => {
const propName = typeof value === 'string' ? value : value.propName;
const whitelist = typeof value === 'string' ? [] : (value.allowedFor || []);
return [propName, whitelist];
const options = {
allowList: typeof value === 'string' ? [] : (value.allowedFor || []),
message: typeof value === 'string' ? null : value.message
};
return [propName, options];
}));
const customMessage = configuration.message;

function isForbidden(prop, tagName) {
const whitelist = forbid.get(prop);
const options = forbid.get(prop);
const allowList = options ? options.allowList : undefined;
// if the tagName is undefined (`<this.something>`), we assume it's a forbidden element
return typeof whitelist !== 'undefined' && (typeof tagName === 'undefined' || whitelist.indexOf(tagName) === -1);
return typeof allowList !== 'undefined' && (typeof tagName === 'undefined' || allowList.indexOf(tagName) === -1);
}

return {
Expand All @@ -87,6 +90,7 @@ module.exports = {
return;
}

const customMessage = forbid.get(prop).message;
const errorMessage = customMessage || `Prop \`${prop}\` is forbidden on Components`;

context.report({
Expand Down
29 changes: 22 additions & 7 deletions lib/rules/forbid-dom-props.js
Expand Up @@ -32,13 +32,22 @@ module.exports = {
forbid: {
type: 'array',
items: {
type: 'string',
onfOf: [{
type: 'string'
}, {
type: 'object',
properties: {
propName: {
type: 'string'
},
message: {
type: 'string'
}
}
}],
minLength: 1
},
uniqueItems: true
},
message: {
type: 'string'
}
},
additionalProperties: false
Expand All @@ -47,11 +56,16 @@ module.exports = {

create(context) {
const configuration = context.options[0] || {};
const customMessage = configuration.message;
const forbid = new Map((configuration.forbid || DEFAULTS).map((value) => {
const propName = typeof value === 'string' ? value : value.propName;
const options = {
message: typeof value === 'string' ? null : value.message
};
return [propName, options];
}));

function isForbidden(prop) {
const forbid = configuration.forbid || DEFAULTS;
return forbid.indexOf(prop) >= 0;
return forbid.get(prop) !== undefined;
}

return {
Expand All @@ -68,6 +82,7 @@ module.exports = {
return;
}

const customMessage = forbid.get(prop).message;
const errorMessage = customMessage || `Prop \`${prop}\` is forbidden on DOM Nodes`;

context.report({
Expand Down
53 changes: 51 additions & 2 deletions tests/lib/rules/forbid-component-props.js
Expand Up @@ -193,14 +193,63 @@ ruleTester.run('forbid-component-props', rule, {
}, {
code: 'const item = (<Foo className="foo" />);',
options: [{
forbid: [{propName: 'className'}],
message: 'Please use ourCoolClassName instead of ClassName'
forbid: [{propName: 'className', message: 'Please use ourCoolClassName instead of ClassName'}]
}],
errors: [{
message: 'Please use ourCoolClassName instead of ClassName',
line: 1,
column: 20,
type: 'JSXAttribute'
}]
}, {
code: [
'const item = () => (',
'<Foo className="foo">',
' <Bar option="high" />',
'</Foo>',
');'
].join('\n'),
options: [{
forbid: [
{propName: 'className', message: 'Please use ourCoolClassName instead of ClassName'},
{propName: 'option', message: 'Avoid using option'}
]
}],
errors: [{
message: 'Please use ourCoolClassName instead of ClassName',
line: 2,
column: 6,
type: 'JSXAttribute'
}, {
message: 'Avoid using option',
line: 3,
column: 8,
type: 'JSXAttribute'
}]
}, {
code: [
'const item = () => (',
'<Foo className="foo">',
' <Bar option="high" />',
'</Foo>',
');'
].join('\n'),
options: [{
forbid: [
{propName: 'className'},
{propName: 'option', message: 'Avoid using option'}
]
}],
errors: [{
message: 'Prop `className` is forbidden on Components',
line: 2,
column: 6,
type: 'JSXAttribute'
}, {
message: 'Avoid using option',
line: 3,
column: 8,
type: 'JSXAttribute'
}]
}]
});
53 changes: 51 additions & 2 deletions tests/lib/rules/forbid-dom-props.js
Expand Up @@ -133,14 +133,63 @@ ruleTester.run('forbid-element-props', rule, {
');'
].join('\n'),
options: [{
forbid: ['className'],
message: 'Please use class instead of ClassName'
forbid: [{propName: 'className', message: 'Please use class instead of ClassName'}]
}],
errors: [{
message: 'Please use class instead of ClassName',
line: 2,
column: 8,
type: 'JSXAttribute'
}]
}, {
code: [
'const First = (props) => (',
' <div className="foo">',
' <div otherProp="bar" />',
' </div>',
');'
].join('\n'),
options: [{
forbid: [
{propName: 'className', message: 'Please use class instead of ClassName'},
{propName: 'otherProp', message: 'Avoid using otherProp'}
]
}],
errors: [{
message: 'Please use class instead of ClassName',
line: 2,
column: 8,
type: 'JSXAttribute'
}, {
message: 'Avoid using otherProp',
line: 3,
column: 10,
type: 'JSXAttribute'
}]
}, {
code: [
'const First = (props) => (',
' <div className="foo">',
' <div otherProp="bar" />',
' </div>',
');'
].join('\n'),
options: [{
forbid: [
{propName: 'className'},
{propName: 'otherProp', message: 'Avoid using otherProp'}
]
}],
errors: [{
message: 'Prop `className` is forbidden on DOM Nodes',
line: 2,
column: 8,
type: 'JSXAttribute'
}, {
message: 'Avoid using otherProp',
line: 3,
column: 10,
type: 'JSXAttribute'
}]
}]
});

0 comments on commit 4ac531f

Please sign in to comment.