Skip to content

Commit 4b49bd0

Browse files
author
Yannick Croissant
committed
Add wrap-multilines rule
1 parent 00ca2e6 commit 4b49bd0

File tree

6 files changed

+180
-3
lines changed

6 files changed

+180
-3
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ Finally, enable all of the rules that you would like to use.
4545
"rules": {
4646
"react/no-multi-comp": 1,
4747
"react/prop-types": 1,
48-
"react/display-name": 1
48+
"react/display-name": 1,
49+
"react/wrap-multilines": 1
4950
}
5051
}
5152
```
@@ -55,6 +56,7 @@ Finally, enable all of the rules that you would like to use.
5556
* [no-multi-comp](docs/rules/no-multi-comp.md): Prevent multiple component definition per file
5657
* [prop-types](docs/rules/prop-types.md): Prevent missing propTypes in a React component definition
5758
* [display-name](docs/rules/display-name.md): Prevent missing displayName in a React component definition
59+
* [wrap-multilines](docs/rules/wrap-multilines.md): Prevent missing parentheses around multilines JSX
5860

5961
## To Do
6062

docs/rules/wrap-multilines.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Prevent missing parentheses around multilines JSX (wrap-multilines)
2+
3+
Wrapping multilines JSX in parentheses can improve readability and/or convenience.
4+
5+
## Rule Details
6+
7+
The following patterns are considered warnings:
8+
9+
```js
10+
var Hello = React.createClass({
11+
render: function() {
12+
return <div>
13+
<p>Hello {this.props.name}</p>
14+
</div>;
15+
}
16+
});
17+
```
18+
19+
The following patterns are not warnings:
20+
21+
```js
22+
var singleLineJSX = <p>Hello</p>
23+
24+
var Hello = React.createClass({
25+
render: function() {
26+
return (
27+
<div>
28+
<p>Hello {this.props.name}</p>
29+
</div>
30+
);
31+
}
32+
});
33+
```

index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ module.exports = {
44
rules: {
55
'no-multi-comp': require('./lib/rules/no-multi-comp'),
66
'prop-types': require('./lib/rules/prop-types'),
7-
'display-name': require('./lib/rules/display-name')
7+
'display-name': require('./lib/rules/display-name'),
8+
'wrap-multilines': require('./lib/rules/wrap-multilines')
89
},
910
rulesConfig: {
1011
'no-multi-comp': 0,
1112
'prop-types': 0,
12-
'display-name': 0
13+
'display-name': 0,
14+
'wrap-multilines': 0
1315
}
1416
};

lib/rules/self-closing.js

Whitespace-only changes.

lib/rules/wrap-multilines.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* @fileoverview Prevent missing parentheses around multilines JSX
3+
* @author Yannick Croissant
4+
*/
5+
'use strict';
6+
7+
// ------------------------------------------------------------------------------
8+
// Rule Definition
9+
// ------------------------------------------------------------------------------
10+
11+
module.exports = function(context) {
12+
13+
function isParenthesised(node) {
14+
var previousToken = context.getTokenBefore(node);
15+
var nextToken = context.getTokenAfter(node);
16+
17+
return previousToken && nextToken &&
18+
previousToken.value === '(' && previousToken.range[1] <= node.range[0] &&
19+
nextToken.value === ')' && nextToken.range[0] >= node.range[1];
20+
}
21+
22+
function isMultilines(node) {
23+
return node.loc.start.line !== node.loc.end.line;
24+
}
25+
26+
function check(node) {
27+
if (!node || node.type !== 'XJSElement') {
28+
return;
29+
}
30+
31+
if (!isParenthesised(node) && isMultilines(node)) {
32+
context.report(node, 'Missing parentheses around multilines JSX');
33+
}
34+
}
35+
36+
// --------------------------------------------------------------------------
37+
// Public
38+
// --------------------------------------------------------------------------
39+
40+
return {
41+
42+
'VariableDeclarator': function(node) {
43+
check(node.init);
44+
},
45+
46+
'AssignmentExpression': function(node) {
47+
check(node.right);
48+
},
49+
50+
'ReturnStatement': function(node) {
51+
check(node.argument);
52+
}
53+
};
54+
55+
};

tests/lib/rules/wrap-multilines.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* @fileoverview Prevent missing parentheses around multilines JSX
3+
* @author Yannick Croissant
4+
*/
5+
'use strict';
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
var eslint = require('eslint').linter;
12+
var ESLintTester = require('eslint-tester');
13+
14+
// ------------------------------------------------------------------------------
15+
// Tests
16+
// ------------------------------------------------------------------------------
17+
18+
var eslintTester = new ESLintTester(eslint);
19+
eslintTester.addRuleTest('lib/rules/wrap-multilines', {
20+
21+
valid: [
22+
{
23+
code: 'var Hello = React.createClass({render: function() {return <p>Hello {this.props.name}</p>;}});',
24+
settings: {
25+
ecmascript: 6,
26+
jsx: true
27+
}
28+
}, {
29+
code: 'var Hello = React.createClass({render: function() {return (\n<div>\n<p>Hello {this.props.name}</p>\n</div>\n);}});',
30+
settings: {
31+
ecmascript: 6,
32+
jsx: true
33+
}
34+
}, {
35+
code: 'var hello = <p>Hello</p>;',
36+
settings: {
37+
ecmascript: 6,
38+
jsx: true
39+
}
40+
}, {
41+
code: 'var hello = (\n<div>\n<p>Hello</p>\n</div>\n);',
42+
settings: {
43+
ecmascript: 6,
44+
jsx: true
45+
}
46+
}, {
47+
code: 'var hello; hello = (\n<div>\n<p>Hello</p>\n</div>\n);',
48+
settings: {
49+
ecmascript: 6,
50+
jsx: true
51+
}
52+
}
53+
],
54+
55+
invalid: [
56+
{
57+
code: 'var Hello = React.createClass({render: function() {return <div>\n<p>Hello {this.props.name}</p>\n</div>;}});',
58+
settings: {
59+
ecmascript: 6,
60+
jsx: true
61+
},
62+
errors: [{
63+
message: 'Missing parentheses around multilines JSX'
64+
}]
65+
}, {
66+
code: 'var hello = <div>\n<p>Hello</p>\n</div>;',
67+
settings: {
68+
ecmascript: 6,
69+
jsx: true
70+
},
71+
errors: [{
72+
message: 'Missing parentheses around multilines JSX'
73+
}]
74+
}, {
75+
code: 'var hello; hello = <div>\n<p>Hello</p>\n</div>;',
76+
settings: {
77+
ecmascript: 6,
78+
jsx: true
79+
},
80+
errors: [{
81+
message: 'Missing parentheses around multilines JSX'
82+
}]
83+
}
84+
]
85+
});

0 commit comments

Comments
 (0)