Skip to content

Commit b779adf

Browse files
committed
Added allowMultiline property to the jsx-curly-spacing rule.
1 parent 9773cfc commit b779adf

File tree

3 files changed

+161
-12
lines changed

3 files changed

+161
-12
lines changed

docs/rules/jsx-curly-spacing.md

+48-3
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@ When `"never"` is set, the following patterns are considered warnings:
2929
<Hello name={ firstname } />;
3030
<Hello name={ firstname} />;
3131
<Hello name={firstname } />;
32-
<Hello name={
33-
firstname
34-
} />;
3532
```
3633

3734
The following patterns are not warnings:
3835

3936
```js
4037
<Hello name={firstname} />;
4138
<Hello name={{ firstname: 'John', lastname: 'Doe' }} />;
39+
<Hello name={
40+
firstname
41+
} />;
4242
```
4343

4444
#### always
@@ -61,6 +61,51 @@ The following patterns are not warnings:
6161
} />;
6262
```
6363

64+
#### Braces spanning multiple lines
65+
66+
By default, braces spanning multiple lines are allowed with either setting. If you want to disallow them you can specify an additional `allowMultiline` property with the value `false`:
67+
68+
```json
69+
"jsx-curly-spacing": [2, "never", {"allowMultiline": false}]
70+
```
71+
72+
When `"never"` is used and `allowMultiline` is `false`, the following patterns are considered warnings:
73+
74+
```js
75+
<Hello name={ firstname } />;
76+
<Hello name={ firstname} />;
77+
<Hello name={firstname } />;
78+
<Hello name={
79+
firstname
80+
} />;
81+
```
82+
83+
The following patterns are not warnings:
84+
85+
```js
86+
<Hello name={firstname} />;
87+
<Hello name={{ firstname: 'John', lastname: 'Doe' }} />;
88+
```
89+
90+
When `"always"` is used and `allowMultiline` is `false`, the following patterns are considered warnings:
91+
92+
```js
93+
<Hello name={firstname} />;
94+
<Hello name={ firstname} />;
95+
<Hello name={firstname } />;
96+
<Hello name={
97+
firstname
98+
} />;
99+
```
100+
101+
The following patterns are not warnings:
102+
103+
```js
104+
<Hello name={ firstname } />;
105+
<Hello name={ {firstname: 'John', lastname: 'Doe'} } />;
106+
```
107+
108+
64109
## When Not To Use It
65110

66111
You can turn this rule off if you are not concerned with the consistency around the spacing inside of JSX attributes.

lib/rules/jsx-curly-spacing.js

+61-8
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,24 @@
1010

1111
module.exports = function(context) {
1212
var spaced = context.options[0] === 'always';
13+
var multiline = context.options[1] ? context.options[1].allowMultiline : true;
1314

1415
// --------------------------------------------------------------------------
1516
// Helpers
1617
// --------------------------------------------------------------------------
1718

1819
/**
19-
* Determines whether two adjacent tokens are have whitespace between them.
20+
* Determines whether two adjacent tokens have a newline between them.
21+
* @param {Object} left - The left token object.
22+
* @param {Object} right - The right token object.
23+
* @returns {boolean} Whether or not there is a newline between the tokens.
24+
*/
25+
function isMultiline(left, right) {
26+
return left.loc.start.line !== right.loc.start.line;
27+
}
28+
29+
/**
30+
* Determines whether two adjacent tokens have whitespace between them.
2031
* @param {Object} left - The left token object.
2132
* @param {Object} right - The right token object.
2233
* @returns {boolean} Whether or not there is space between the tokens.
@@ -25,6 +36,28 @@ module.exports = function(context) {
2536
return left.range[1] < right.range[0];
2637
}
2738

39+
/**
40+
* Reports that there shouldn't be a newline after the first token
41+
* @param {ASTNode} node - The node to report in the event of an error.
42+
* @param {Token} token - The token to use for the report.
43+
* @returns {void}
44+
*/
45+
function reportNoBeginningNewline(node, token) {
46+
context.report(node, token.loc.start,
47+
'There should be no newline after \'' + token.value + '\'');
48+
}
49+
50+
/**
51+
* Reports that there shouldn't be a newline before the last token
52+
* @param {ASTNode} node - The node to report in the event of an error.
53+
* @param {Token} token - The token to use for the report.
54+
* @returns {void}
55+
*/
56+
function reportNoEndingNewline(node, token) {
57+
context.report(node, token.loc.start,
58+
'There should be no newline before \'' + token.value + '\'');
59+
}
60+
2861
/**
2962
* Reports that there shouldn't be a space after the first token
3063
* @param {ASTNode} node - The node to report in the event of an error.
@@ -79,16 +112,28 @@ module.exports = function(context) {
79112
* @returns {void}
80113
*/
81114
function validateBraceSpacing(node, first, second, penultimate, last) {
82-
if (spaced && !isSpaced(first, second)) {
83-
reportRequiredBeginningSpace(node, first);
115+
if (spaced) {
116+
if (!isSpaced(first, second)) {
117+
reportRequiredBeginningSpace(node, first);
118+
} else if (!multiline && isMultiline(first, second)) {
119+
reportNoBeginningNewline(node, first);
120+
}
121+
122+
if (!isSpaced(penultimate, last)) {
123+
reportRequiredEndingSpace(node, last);
124+
} else if (!multiline && isMultiline(penultimate, last)) {
125+
reportNoEndingNewline(node, last);
126+
}
127+
128+
return;
84129
}
85-
if (!spaced && isSpaced(first, second)) {
130+
131+
// "never" setting if we get here.
132+
if (isSpaced(first, second) && !(multiline && isMultiline(first, second))) {
86133
reportNoBeginningSpace(node, first);
87134
}
88-
if (spaced && !isSpaced(penultimate, last)) {
89-
reportRequiredEndingSpace(node, last);
90-
}
91-
if (!spaced && isSpaced(penultimate, last)) {
135+
136+
if (isSpaced(penultimate, last) && !(multiline && isMultiline(penultimate, last))) {
92137
reportNoEndingSpace(node, last);
93138
}
94139
}
@@ -111,4 +156,12 @@ module.exports = function(context) {
111156

112157
module.exports.schema = [{
113158
enum: ['always', 'never']
159+
}, {
160+
type: 'object',
161+
properties: {
162+
allowMultiline: {
163+
type: 'boolean'
164+
}
165+
},
166+
additionalProperties: false
114167
}];

tests/lib/rules/jsx-curly-spacing.js

+52-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ eslintTester.addRuleTest('lib/rules/jsx-curly-spacing', {
2929
code: '<App foo={ bar } />;',
3030
args: [1, 'always'],
3131
ecmaFeatures: {jsx: true}
32+
}, {
33+
code: '<App foo={ bar } />;',
34+
args: [1, 'always', {allowMultiline: false}],
35+
ecmaFeatures: {jsx: true}
3236
}, {
3337
code: '<App foo={{ bar:baz }} />;',
3438
args: [1, 'never'],
@@ -45,6 +49,22 @@ eslintTester.addRuleTest('lib/rules/jsx-curly-spacing', {
4549
].join('\n'),
4650
args: [1, 'always'],
4751
ecmaFeatures: {jsx: true}
52+
}, {
53+
code: [
54+
'<App foo={',
55+
'bar',
56+
'} />;'
57+
].join('\n'),
58+
args: [1, 'always'],
59+
ecmaFeatures: {jsx: true}
60+
}, {
61+
code: [
62+
'<App foo={',
63+
'bar',
64+
'} />;'
65+
].join('\n'),
66+
args: [1, 'never'],
67+
ecmaFeatures: {jsx: true}
4868
}],
4969

5070
invalid: [{
@@ -56,6 +76,15 @@ eslintTester.addRuleTest('lib/rules/jsx-curly-spacing', {
5676
message: 'There should be no space before \'}\''
5777
}],
5878
ecmaFeatures: {jsx: true}
79+
}, {
80+
code: '<App foo={ bar } />;',
81+
args: [1, 'never', {allowMultiline: false}],
82+
errors: [{
83+
message: 'There should be no space after \'{\''
84+
}, {
85+
message: 'There should be no space before \'}\''
86+
}],
87+
ecmaFeatures: {jsx: true}
5988
}, {
6089
code: '<App foo={bar} />;',
6190
args: [1, 'always'],
@@ -65,6 +94,15 @@ eslintTester.addRuleTest('lib/rules/jsx-curly-spacing', {
6594
message: 'A space is required before \'}\''
6695
}],
6796
ecmaFeatures: {jsx: true}
97+
}, {
98+
code: '<App foo={bar} />;',
99+
args: [1, 'always', {allowMultiline: false}],
100+
errors: [{
101+
message: 'A space is required after \'{\''
102+
}, {
103+
message: 'A space is required before \'}\''
104+
}],
105+
ecmaFeatures: {jsx: true}
68106
}, {
69107
code: '<App foo={ bar} />;',
70108
args: [1, 'always'],
@@ -99,12 +137,25 @@ eslintTester.addRuleTest('lib/rules/jsx-curly-spacing', {
99137
'bar',
100138
'} />;'
101139
].join('\n'),
102-
args: [1, 'never'],
140+
args: [1, 'never', {allowMultiline: false}],
103141
errors: [{
104142
message: 'There should be no space after \'{\''
105143
}, {
106144
message: 'There should be no space before \'}\''
107145
}],
108146
ecmaFeatures: {jsx: true}
147+
}, {
148+
code: [
149+
'<App foo={',
150+
'bar',
151+
'} />;'
152+
].join('\n'),
153+
args: [1, 'always', {allowMultiline: false}],
154+
errors: [{
155+
message: 'There should be no newline after \'{\''
156+
}, {
157+
message: 'There should be no newline before \'}\''
158+
}],
159+
ecmaFeatures: {jsx: true}
109160
}]
110161
});

0 commit comments

Comments
 (0)