Skip to content

Commit

Permalink
Add wrap-multilines rule
Browse files Browse the repository at this point in the history
  • Loading branch information
Yannick Croissant committed Dec 28, 2014
1 parent 00ca2e6 commit 4b49bd0
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 3 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ Finally, enable all of the rules that you would like to use.
"rules": {
"react/no-multi-comp": 1,
"react/prop-types": 1,
"react/display-name": 1
"react/display-name": 1,
"react/wrap-multilines": 1
}
}
```
Expand All @@ -55,6 +56,7 @@ Finally, enable all of the rules that you would like to use.
* [no-multi-comp](docs/rules/no-multi-comp.md): Prevent multiple component definition per file
* [prop-types](docs/rules/prop-types.md): Prevent missing propTypes in a React component definition
* [display-name](docs/rules/display-name.md): Prevent missing displayName in a React component definition
* [wrap-multilines](docs/rules/wrap-multilines.md): Prevent missing parentheses around multilines JSX

## To Do

Expand Down
33 changes: 33 additions & 0 deletions docs/rules/wrap-multilines.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Prevent missing parentheses around multilines JSX (wrap-multilines)

Wrapping multilines JSX in parentheses can improve readability and/or convenience.

## Rule Details

The following patterns are considered warnings:

```js
var Hello = React.createClass({
render: function() {
return <div>
<p>Hello {this.props.name}</p>
</div>;
}
});
```

The following patterns are not warnings:

```js
var singleLineJSX = <p>Hello</p>

var Hello = React.createClass({
render: function() {
return (
<div>
<p>Hello {this.props.name}</p>
</div>
);
}
});
```
6 changes: 4 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ module.exports = {
rules: {
'no-multi-comp': require('./lib/rules/no-multi-comp'),
'prop-types': require('./lib/rules/prop-types'),
'display-name': require('./lib/rules/display-name')
'display-name': require('./lib/rules/display-name'),
'wrap-multilines': require('./lib/rules/wrap-multilines')
},
rulesConfig: {
'no-multi-comp': 0,
'prop-types': 0,
'display-name': 0
'display-name': 0,
'wrap-multilines': 0
}
};
Empty file added lib/rules/self-closing.js
Empty file.
55 changes: 55 additions & 0 deletions lib/rules/wrap-multilines.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* @fileoverview Prevent missing parentheses around multilines JSX
* @author Yannick Croissant
*/
'use strict';

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

module.exports = function(context) {

function isParenthesised(node) {
var previousToken = context.getTokenBefore(node);
var nextToken = context.getTokenAfter(node);

return previousToken && nextToken &&
previousToken.value === '(' && previousToken.range[1] <= node.range[0] &&
nextToken.value === ')' && nextToken.range[0] >= node.range[1];
}

function isMultilines(node) {
return node.loc.start.line !== node.loc.end.line;
}

function check(node) {
if (!node || node.type !== 'XJSElement') {
return;
}

if (!isParenthesised(node) && isMultilines(node)) {
context.report(node, 'Missing parentheses around multilines JSX');
}
}

// --------------------------------------------------------------------------
// Public
// --------------------------------------------------------------------------

return {

'VariableDeclarator': function(node) {
check(node.init);
},

'AssignmentExpression': function(node) {
check(node.right);
},

'ReturnStatement': function(node) {
check(node.argument);
}
};

};
85 changes: 85 additions & 0 deletions tests/lib/rules/wrap-multilines.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* @fileoverview Prevent missing parentheses around multilines JSX
* @author Yannick Croissant
*/
'use strict';

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

var eslint = require('eslint').linter;
var ESLintTester = require('eslint-tester');

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

var eslintTester = new ESLintTester(eslint);
eslintTester.addRuleTest('lib/rules/wrap-multilines', {

valid: [
{
code: 'var Hello = React.createClass({render: function() {return <p>Hello {this.props.name}</p>;}});',
settings: {
ecmascript: 6,
jsx: true
}
}, {
code: 'var Hello = React.createClass({render: function() {return (\n<div>\n<p>Hello {this.props.name}</p>\n</div>\n);}});',
settings: {
ecmascript: 6,
jsx: true
}
}, {
code: 'var hello = <p>Hello</p>;',
settings: {
ecmascript: 6,
jsx: true
}
}, {
code: 'var hello = (\n<div>\n<p>Hello</p>\n</div>\n);',
settings: {
ecmascript: 6,
jsx: true
}
}, {
code: 'var hello; hello = (\n<div>\n<p>Hello</p>\n</div>\n);',
settings: {
ecmascript: 6,
jsx: true
}
}
],

invalid: [
{
code: 'var Hello = React.createClass({render: function() {return <div>\n<p>Hello {this.props.name}</p>\n</div>;}});',
settings: {
ecmascript: 6,
jsx: true
},
errors: [{
message: 'Missing parentheses around multilines JSX'
}]
}, {
code: 'var hello = <div>\n<p>Hello</p>\n</div>;',
settings: {
ecmascript: 6,
jsx: true
},
errors: [{
message: 'Missing parentheses around multilines JSX'
}]
}, {
code: 'var hello; hello = <div>\n<p>Hello</p>\n</div>;',
settings: {
ecmascript: 6,
jsx: true
},
errors: [{
message: 'Missing parentheses around multilines JSX'
}]
}
]
});

0 comments on commit 4b49bd0

Please sign in to comment.