Skip to content

Commit aa359fb

Browse files
benvinegaryannickcr
authored andcommitted
Add no-comment-textnodes rule
1 parent 55d0c9d commit aa359fb

File tree

4 files changed

+311
-0
lines changed

4 files changed

+311
-0
lines changed

docs/rules/no-comment-textnodes.md

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Prevent comments from being inserted as text nodes (no-comment-textnodes)
2+
3+
This rule prevents comment strings (e.g. beginning with `//` or `/*`) from being accidentally
4+
injected as a text node in JSX statements.
5+
6+
## Rule Details
7+
8+
The following patterns are considered warnings:
9+
10+
```js
11+
var Hello = React.createClass({
12+
render: function() {
13+
return (
14+
<div>// empty div</div>
15+
);
16+
}
17+
});
18+
19+
var Hello = React.createClass({
20+
render: function() {
21+
return (
22+
<div>
23+
/* empty div */
24+
</div>
25+
);
26+
}
27+
});
28+
```
29+
30+
The following patterns are not considered warnings:
31+
32+
```js
33+
var Hello = React.createClass({
34+
displayName: 'Hello',
35+
render: function() {
36+
return <div>{/* empty div */}</div>;
37+
}
38+
});
39+
40+
var Hello = React.createClass({
41+
displayName: 'Hello',
42+
render: function() {
43+
return <div /* empty div */></div>;
44+
}
45+
});
46+
47+
var Hello = React.createClass({
48+
displayName: 'Hello',
49+
render: function() {
50+
return <div className={'foo' /* temp class */}</div>;
51+
}
52+
});
53+
```
54+
55+
## Legitimate uses
56+
57+
It's possible you may want to legitimately output comment start characters (`//` or `/*`)
58+
in a JSX text node. In which case, you can do the following:
59+
60+
```js
61+
var Hello = React.createClass({
62+
render: function() {
63+
return (
64+
<div>{'/* This will be output as a text node */'}</div>
65+
);
66+
}
67+
});
68+
```

index.js

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module.exports = {
88
'display-name': require('./lib/rules/display-name'),
99
'wrap-multilines': require('./lib/rules/wrap-multilines'),
1010
'self-closing-comp': require('./lib/rules/self-closing-comp'),
11+
'no-comment-textnodes': require('./lib/rules/no-comment-textnodes'),
1112
'no-danger': require('./lib/rules/no-danger'),
1213
'no-set-state': require('./lib/rules/no-set-state'),
1314
'no-is-mounted': require('./lib/rules/no-is-mounted'),

lib/rules/no-comment-textnodes.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* @fileoverview Comments inside children section of tag should be placed inside braces.
3+
* @author Ben Vinegar
4+
*/
5+
'use strict';
6+
7+
// ------------------------------------------------------------------------------
8+
// Rule Definition
9+
// ------------------------------------------------------------------------------
10+
11+
module.exports = function(context) {
12+
function reportLiteralNode(node) {
13+
context.report(node, 'Comments inside children section of tag should be placed inside braces');
14+
}
15+
16+
// --------------------------------------------------------------------------
17+
// Public
18+
// --------------------------------------------------------------------------
19+
20+
return {
21+
Literal: function(node) {
22+
if (/\s*\/(\/|\*)/.test(node.value)) {
23+
// inside component, e.g. <div>literal</div>
24+
if (node.parent.type !== 'JSXAttribute' &&
25+
node.parent.type !== 'JSXExpressionContainer' &&
26+
node.parent.type.indexOf('JSX') !== -1) {
27+
reportLiteralNode(node);
28+
}
29+
}
30+
}
31+
};
32+
};
33+
34+
module.exports.schema = [{
35+
type: 'object',
36+
properties: {},
37+
additionalProperties: false
38+
}];
+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/**
2+
* @fileoverview Tests for no-comment-textnodes
3+
* @author Ben Vinegar
4+
*/
5+
'use strict';
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
var rule = require('../../../lib/rules/no-comment-textnodes');
12+
var RuleTester = require('eslint').RuleTester;
13+
14+
// ------------------------------------------------------------------------------
15+
// Tests
16+
// ------------------------------------------------------------------------------
17+
18+
var ruleTester = new RuleTester();
19+
ruleTester.run('jsx-needs-i18n', rule, {
20+
21+
valid: [
22+
{
23+
code: [
24+
'class Comp1 extends Component {',
25+
' render() {',
26+
' return (',
27+
' <div>',
28+
' {/* valid */}',
29+
' </div>',
30+
' );',
31+
' }',
32+
'}'
33+
].join('\n'),
34+
args: [1],
35+
parser: 'babel-eslint'
36+
}, {
37+
code: [
38+
'class Comp1 extends Component {',
39+
' render() {',
40+
' return (<div>{/* valid */}</div>);',
41+
' }',
42+
'}'
43+
].join('\n'),
44+
args: [1],
45+
parser: 'babel-eslint'
46+
}, {
47+
code: [
48+
'class Comp1 extends Component {',
49+
' render() {',
50+
' const bar = (<div>{/* valid */}</div>);',
51+
' return bar;',
52+
' }',
53+
'}'
54+
].join('\n'),
55+
args: [1],
56+
parser: 'babel-eslint'
57+
}, {
58+
code: [
59+
'var Hello = React.createClass({',
60+
' foo: (<div>{/* valid */}</div>),',
61+
' render() {',
62+
' return this.foo;',
63+
' },',
64+
'});'
65+
].join('\n'),
66+
args: [1],
67+
parser: 'babel-eslint'
68+
}, {
69+
code: [
70+
'class Comp1 extends Component {',
71+
' render() {',
72+
' return (',
73+
' <div>',
74+
' {/* valid */}',
75+
' {/* valid 2 */}',
76+
' {/* valid 3 */}',
77+
' </div>',
78+
' );',
79+
' }',
80+
'}'
81+
].join('\n'),
82+
args: [1],
83+
parser: 'babel-eslint'
84+
}, {
85+
code: [
86+
'class Comp1 extends Component {',
87+
' render() {',
88+
' return (',
89+
' <div>',
90+
' </div>',
91+
' );',
92+
' }',
93+
'}'
94+
].join('\n'),
95+
args: [1],
96+
parser: 'babel-eslint'
97+
}, {
98+
code: [
99+
'var foo = require(\'foo\');'
100+
].join('\n'),
101+
args: [1],
102+
parser: 'babel-eslint'
103+
}, {
104+
code: [
105+
'<Foo bar=\'test\'>',
106+
' {/* valid */}',
107+
'</Foo>'
108+
].join('\n'),
109+
args: [1],
110+
parser: 'babel-eslint'
111+
},
112+
113+
// inside element declarations
114+
{
115+
code: [
116+
'<Foo /* valid */ placeholder={\'foo\'}/>'
117+
].join('\n'),
118+
args: [1],
119+
parser: 'babel-eslint'
120+
},
121+
{
122+
code: [
123+
'<Foo title={\'foo\' /* valid */}/>'
124+
].join('\n'),
125+
args: [1],
126+
parser: 'babel-eslint'
127+
}
128+
],
129+
130+
invalid: [
131+
{
132+
code: [
133+
'class Comp1 extends Component {',
134+
' render() {',
135+
' return (<div>// invalid</div>);',
136+
' }',
137+
'}'
138+
].join('\n'),
139+
args: [1],
140+
parser: 'babel-eslint',
141+
errors: [{message: 'Comments inside children section of tag should be placed inside braces'}]
142+
}, {
143+
code: [
144+
'class Comp1 extends Component {',
145+
' render() {',
146+
' return (<div>/* invalid */</div>);',
147+
' }',
148+
'}'
149+
].join('\n'),
150+
args: [1],
151+
parser: 'babel-eslint',
152+
errors: [{message: 'Comments inside children section of tag should be placed inside braces'}]
153+
}, {
154+
code: [
155+
'class Comp1 extends Component {',
156+
' render() {',
157+
' return (',
158+
' <div>',
159+
' // invalid',
160+
' </div>',
161+
' );',
162+
' }',
163+
'}'
164+
].join('\n'),
165+
args: [1],
166+
parser: 'babel-eslint',
167+
errors: [{message: 'Comments inside children section of tag should be placed inside braces'}]
168+
}, {
169+
code: [
170+
'class Comp1 extends Component {',
171+
' render() {',
172+
' return (',
173+
' <div>',
174+
' asdjfl',
175+
' /* invalid */',
176+
' foo',
177+
' </div>',
178+
' );',
179+
' }',
180+
'}'
181+
].join('\n'),
182+
args: [1],
183+
parser: 'babel-eslint',
184+
errors: [{message: 'Comments inside children section of tag should be placed inside braces'}]
185+
}, {
186+
code: [
187+
'class Comp1 extends Component {',
188+
' render() {',
189+
' return (',
190+
' <div>',
191+
' {\'asdjfl\'}',
192+
' // invalid',
193+
' {\'foo\'}',
194+
' </div>',
195+
' );',
196+
' }',
197+
'}'
198+
].join('\n'),
199+
args: [1],
200+
parser: 'babel-eslint',
201+
errors: [{message: 'Comments inside children section of tag should be placed inside braces'}]
202+
}
203+
]
204+
});

0 commit comments

Comments
 (0)