diff --git a/docs/rules/forbid-component-props.md b/docs/rules/forbid-component-props.md index e4b088e531..b44b36d929 100644 --- a/docs/rules/forbid-component-props.md +++ b/docs/rules/forbid-component-props.md @@ -35,26 +35,24 @@ The following patterns are **not** considered warnings: ```js ... -"react/forbid-component-props": [, { "forbid": [|], "message": }] +"react/forbid-component-props": [, { "forbid": [|] }] ... ``` ### `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) diff --git a/docs/rules/forbid-dom-props.md b/docs/rules/forbid-dom-props.md index ad7db3e191..600cd30b8c 100644 --- a/docs/rules/forbid-dom-props.md +++ b/docs/rules/forbid-dom-props.md @@ -36,17 +36,22 @@ The following patterns are **not** considered warnings: ```js ... -"react/forbid-dom-props": [, { "forbid": [], "message": }] +"react/forbid-dom-props": [, { "forbid": [|] }] ... ``` ### `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 diff --git a/lib/rules/forbid-component-props.js b/lib/rules/forbid-component-props.js index 05560a64e9..e5d8185961 100644 --- a/lib/rules/forbid-component-props.js +++ b/lib/rules/forbid-component-props.js @@ -46,13 +46,13 @@ module.exports = { items: { type: 'string' } + }, + message: { + type: 'string' } } }] } - }, - message: { - type: 'string' } } }] @@ -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 (``), 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 { @@ -87,6 +90,7 @@ module.exports = { return; } + const customMessage = forbid.get(prop).message; const errorMessage = customMessage || `Prop \`${prop}\` is forbidden on Components`; context.report({ diff --git a/lib/rules/forbid-dom-props.js b/lib/rules/forbid-dom-props.js index 40cf989bf2..197f73cee0 100644 --- a/lib/rules/forbid-dom-props.js +++ b/lib/rules/forbid-dom-props.js @@ -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 @@ -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 { @@ -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({ diff --git a/tests/lib/rules/forbid-component-props.js b/tests/lib/rules/forbid-component-props.js index f712c9fd59..910d2c240f 100644 --- a/tests/lib/rules/forbid-component-props.js +++ b/tests/lib/rules/forbid-component-props.js @@ -193,8 +193,7 @@ ruleTester.run('forbid-component-props', rule, { }, { code: 'const item = ();', 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', @@ -202,5 +201,55 @@ ruleTester.run('forbid-component-props', rule, { column: 20, type: 'JSXAttribute' }] + }, { + code: [ + 'const item = () => (', + '', + ' ', + '', + ');' + ].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 = () => (', + '', + ' ', + '', + ');' + ].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' + }] }] }); diff --git a/tests/lib/rules/forbid-dom-props.js b/tests/lib/rules/forbid-dom-props.js index 9863c5afa7..123c9e0e37 100644 --- a/tests/lib/rules/forbid-dom-props.js +++ b/tests/lib/rules/forbid-dom-props.js @@ -133,8 +133,7 @@ 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', @@ -142,5 +141,55 @@ ruleTester.run('forbid-element-props', rule, { column: 8, type: 'JSXAttribute' }] + }, { + code: [ + 'const First = (props) => (', + '
', + '
', + '
', + ');' + ].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) => (', + '
', + '
', + '
', + ');' + ].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' + }] }] });