-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new no-children-prop rule (Fixes #720)
Prevents children being passed as props. Children should be actual children.
- Loading branch information
Showing
5 changed files
with
219 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Prevent passing of children as props (no-children-prop) | ||
|
||
Children should always be actual children, not passed in as a prop. | ||
|
||
## Rule Details | ||
|
||
The following patterns are considered warnings: | ||
|
||
```js | ||
<div children='Children' /> | ||
|
||
React.createElement("div", { children: 'Children' }) | ||
``` | ||
|
||
The following patterns are not considered warnings: | ||
|
||
```js | ||
<div>Children</div> | ||
|
||
React.createElement("div", {}, 'Children') | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/** | ||
* @fileoverview Prevent passing of children as props | ||
* @author Benjamin Stepp | ||
*/ | ||
'use strict'; | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Helpers | ||
// ------------------------------------------------------------------------------ | ||
|
||
/** | ||
* Checks if a node name match the JSX tag convention. | ||
* @param {String} name - Name of the node to check. | ||
* @returns {Boolean} Whether or not the node name match the JSX tag convention. | ||
*/ | ||
var tagConvention = /^[a-z]|\-/; | ||
function isTagName(name) { | ||
return tagConvention.test(name); | ||
} | ||
|
||
/** | ||
* Checks if the node is a createElement call with a props literal. | ||
* @param {ASTNode} node - The AST node being checked. | ||
* @returns {Boolean} - True if node is a createElement call with a props | ||
* object literal, False if not. | ||
*/ | ||
function isCreateElementWithProps(node) { | ||
return node.callee | ||
&& node.callee.type === 'MemberExpression' | ||
&& node.callee.property.name === 'createElement' | ||
&& node.arguments.length > 1 | ||
&& node.arguments[1].type === 'ObjectExpression'; | ||
} | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Rule Definition | ||
// ------------------------------------------------------------------------------ | ||
|
||
module.exports = { | ||
meta: { | ||
docs: {}, | ||
schema: [] | ||
}, | ||
create: function(context) { | ||
return { | ||
JSXAttribute: function(node) { | ||
if (isTagName(node.parent.name.name) && node.name.name === 'children') { | ||
context.report({ | ||
node: node, | ||
message: 'Do not pass children as props.' | ||
}); | ||
} | ||
}, | ||
CallExpression: function(node) { | ||
if (isCreateElementWithProps(node)) { | ||
var props = node.arguments[1].properties; | ||
var childrenProp = props.find(function(prop) { | ||
return prop.key.name === 'children'; | ||
}); | ||
|
||
if (childrenProp) { | ||
context.report({ | ||
node: node, | ||
message: 'Do not pass children as props.' | ||
}); | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/** | ||
* @fileoverview Tests for no-children-prop | ||
* @author Benjamin Stepp | ||
*/ | ||
|
||
'use strict'; | ||
|
||
// ----------------------------------------------------------------------------- | ||
// Requirements | ||
// ----------------------------------------------------------------------------- | ||
|
||
var rule = require('../../../lib/rules/no-children-prop'); | ||
var RuleTester = require('eslint').RuleTester; | ||
|
||
var parserOptions = { | ||
ecmaVersion: 6, | ||
ecmaFeatures: { | ||
jsx: true | ||
} | ||
}; | ||
|
||
// ----------------------------------------------------------------------------- | ||
// Tests | ||
// ----------------------------------------------------------------------------- | ||
|
||
var ruleTester = new RuleTester(); | ||
ruleTester.run('no-children-prop', rule, { | ||
valid: [ | ||
{ | ||
code: '<div />;', | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: '<div></div>;', | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: 'React.createElement("div", {});', | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: 'React.createElement("div", undefined);', | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: '<div>Children</div>;', | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: 'React.createElement("div", {}, "Children");', | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: 'React.createElement("div", undefined, "Children");', | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: '<div><div /></div>;', | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: 'React.createElement("div", {}, React.createElement("div"));', | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: 'React.createElement("div", undefined, React.createElement("div"));', | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: '<div><div /><div /></div>;', | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: 'React.createElement("div", {}, [React.createElement("div"), React.createElement("div")]);', | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: 'React.createElement("div", undefined, [React.createElement("div"), React.createElement("div")]);', | ||
parserOptions: parserOptions | ||
} | ||
], | ||
invalid: [ | ||
{ | ||
code: '<div children="Children" />;', | ||
errors: [{message: 'Do not pass children as props.'}], | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: '<div children={<div />} />;', | ||
errors: [{message: 'Do not pass children as props.'}], | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: '<div children={[<div />, <div />]} />;', | ||
errors: [{message: 'Do not pass children as props.'}], | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: '<div children="Children">Children</div>;', | ||
errors: [{message: 'Do not pass children as props.'}], | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: 'React.createElement("div", {children: "Children"});', | ||
errors: [{message: 'Do not pass children as props.'}], | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: 'React.createElement("div", {children: "Children"}, "Children");', | ||
errors: [{message: 'Do not pass children as props.'}], | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: 'React.createElement("div", {children: React.createElement("div")});', | ||
errors: [{message: 'Do not pass children as props.'}], | ||
parserOptions: parserOptions | ||
}, | ||
{ | ||
code: 'React.createElement("div", {children: [React.createElement("div"), React.createElement("div")]});', | ||
errors: [{message: 'Do not pass children as props.'}], | ||
parserOptions: parserOptions | ||
} | ||
] | ||
}); |