Skip to content

Commit

Permalink
Add option "disallowedFor" for dom element prop
Browse files Browse the repository at this point in the history
  • Loading branch information
TildaDares committed Jul 15, 2022
1 parent bdbd2a4 commit 94e98f5
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -6,6 +6,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
## Unreleased

### Added
* [`forbid-dom-props`]: add `disallowedFor` option ([#3338][] @TildaDares)
* [`jsx-newline`]: add `allowMultiline` option when prevent option is true ([#3311][] @TildaDares)

### Fixed
Expand All @@ -21,6 +22,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [Tests] [`jsx-indent`], [`jsx-one-expression-per-line`]: add passing test cases ([#3314][] @ROSSROSALES)
* [Refactor] `boolean-prop-naming`, `jsx-indent`: avoid assigning to arguments ([#3316][] @caroline223)

[#3338]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3338
[#3331]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3331
[#3328]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3328
[#3327]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3327
Expand Down
5 changes: 3 additions & 2 deletions docs/rules/forbid-dom-props.md
Expand Up @@ -43,12 +43,13 @@ Examples of **correct** code for this rule:
### `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:
Each array element can either be a string with the property name or object specifying the property name, an optional
custom message, and a DOM nodes blacklist(e.g. `<div />`):

```js
{
"propName": "someProp",
"disallowedFor": [DOMNode, AnotherDOMNode],
"message": "Avoid using someProp"
}
```
Expand Down
20 changes: 17 additions & 3 deletions lib/rules/forbid-dom-props.js
Expand Up @@ -47,6 +47,13 @@ module.exports = {
propName: {
type: 'string',
},
disallowedFor: {
type: 'array',
uniqueItems: true,
items: {
type: 'string',
},
},
message: {
type: 'string',
},
Expand All @@ -66,13 +73,20 @@ module.exports = {
const forbid = new Map((configuration.forbid || DEFAULTS).map((value) => {
const propName = typeof value === 'string' ? value : value.propName;
const options = {
disallowList: typeof value === 'string' ? [] : (value.disallowedFor || []),
message: typeof value === 'string' ? null : value.message,
};
return [propName, options];
}));

function isForbidden(prop) {
return forbid.has(prop);
function isForbidden(prop, tagName) {
const options = forbid.get(prop);
const disallowList = options ? options.disallowList : undefined;
return typeof disallowList !== 'undefined'
&& (typeof tagName === 'undefined'
|| disallowList.length === 0
|| (disallowList.length > 0
&& disallowList.indexOf(tagName) !== -1));
}

return {
Expand All @@ -85,7 +99,7 @@ module.exports = {

const prop = node.name.name;

if (!isForbidden(prop)) {
if (!isForbidden(prop, tag)) {
return;
}

Expand Down
87 changes: 87 additions & 0 deletions tests/lib/rules/forbid-dom-props.js
Expand Up @@ -95,6 +95,23 @@ ruleTester.run('forbid-dom-props', rule, {
`,
options: [{ forbid: ['id'] }],
},
{
code: `
const First = (props) => (
<div otherProp="bar" />
);
`,
options: [
{
forbid: [
{
propName: 'otherProp',
disallowedFor: ['span'],
},
],
},
],
},
]),

invalid: parsers.all([
Expand Down Expand Up @@ -237,5 +254,75 @@ ruleTester.run('forbid-dom-props', rule, {
},
],
},
{
code: `
const First = (props) => (
<form accept='file'>
<input type="file" id="videoFile" accept="video/*" />
<input type="hidden" name="fullname" />
</form>
);
`,
options: [
{
forbid: [{
propName: 'accept',
disallowedFor: ['form'],
message: 'Avoid using the accept attribute on <form>',
}],
},
],
errors: [
{
message: 'Avoid using the accept attribute on <form>',
line: 3,
column: 17,
type: 'JSXAttribute',
},
],
},
{
code: `
const First = (props) => (
<div className="foo">
<input className="boo" />
<span className="foobar">Foobar</span>
<div otherProp="bar" />
</div>
);
`,
options: [
{
forbid: [
{
propName: 'className',
disallowedFor: ['div', 'span'],
message: 'Please use class instead of ClassName',
},
{ propName: 'otherProp', message: 'Avoid using otherProp' },
],
},
],
errors: [
{
message: 'Please use class instead of ClassName',
line: 3,
column: 16,
type: 'JSXAttribute',
},
{
message: 'Please use class instead of ClassName',
line: 5,
column: 19,
type: 'JSXAttribute',
},
{
message: 'Avoid using otherProp',
line: 6,
column: 18,
type: 'JSXAttribute',
},
],
},
]),
});

0 comments on commit 94e98f5

Please sign in to comment.