Skip to content

Commit d2b6de3

Browse files
committed
Add jsx-equals-spacing rule (fixes #394)
1 parent 5c1f029 commit d2b6de3

File tree

5 files changed

+288
-0
lines changed

5 files changed

+288
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ Finally, enable all of the rules that you would like to use.
7777
"react/jsx-boolean-value": 1,
7878
"react/jsx-closing-bracket-location": 1,
7979
"react/jsx-curly-spacing": 1,
80+
"react/jsx-equals-spacing": 1,
8081
"react/jsx-handler-names": 1,
8182
"react/jsx-indent-props": 1,
8283
"react/jsx-indent": 1,
@@ -120,6 +121,7 @@ Finally, enable all of the rules that you would like to use.
120121
* [jsx-boolean-value](docs/rules/jsx-boolean-value.md): Enforce boolean attributes notation in JSX (fixable)
121122
* [jsx-closing-bracket-location](docs/rules/jsx-closing-bracket-location.md): Validate closing bracket location in JSX
122123
* [jsx-curly-spacing](docs/rules/jsx-curly-spacing.md): Enforce or disallow spaces inside of curly braces in JSX attributes
124+
* [jsx-equals-spacing](docs/rules/jsx-equals-spacing.md): Enforce or disallow spaces around equal signs in JSX attributes
123125
* [jsx-handler-names](docs/rules/jsx-handler-names.md): Enforce event handler naming conventions in JSX
124126
* [jsx-indent-props](docs/rules/jsx-indent-props.md): Validate props indentation in JSX
125127
* [jsx-indent](docs/rules/jsx-indent.md): Validate JSX indentation

docs/rules/jsx-equals-spacing.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Enforce or disallow spaces around equal signs in JSX attributes. (jsx-equals-spacing)
2+
3+
Some style guides require or disallow spaces around equal signs.
4+
5+
## Rule Details
6+
7+
This rule will enforce consistency of spacing around equal signs in JSX attributes, by requiring or disallowing one or more spaces before and after `=`.
8+
9+
### Options
10+
11+
There are two options for the rule:
12+
13+
* `"always"` enforces spaces around the equal sign
14+
* `"never"` disallows spaces around the equal sign (default)
15+
16+
Depending on your coding conventions, you can choose either option by specifying it in your configuration:
17+
18+
```json
19+
"jsx-equals-spacing": [2, "always"]
20+
```
21+
22+
#### never
23+
24+
When `"never"` is set, the following patterns are considered warnings:
25+
26+
```js
27+
<Hello name = {firstname} />;
28+
<Hello name ={firstname} />;
29+
<Hello name= {firstname} />;
30+
```
31+
32+
The following patterns are not warnings:
33+
34+
```js
35+
<Hello name={firstname} />;
36+
<Hello name />;
37+
<Hello {...props} />;
38+
```
39+
40+
#### always
41+
42+
When `"always"` is used, the following patterns are considered warnings:
43+
44+
```js
45+
<Hello name={firstname} />;
46+
<Hello name ={firstname} />;
47+
<Hello name= {firstname} />;
48+
```
49+
50+
The following patterns are not warnings:
51+
52+
```js
53+
<Hello name = {firstname} />;
54+
<Hello name />;
55+
<Hello {...props} />;
56+
```
57+
58+
## When Not To Use It
59+
60+
You can turn this rule off if you are not concerned with the consistency of spacing around equal signs in JSX attributes.
61+

index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module.exports = {
2323
'jsx-quotes': require('./lib/rules/jsx-quotes'),
2424
'no-unknown-property': require('./lib/rules/no-unknown-property'),
2525
'jsx-curly-spacing': require('./lib/rules/jsx-curly-spacing'),
26+
'jsx-equals-spacing': require('./lib/rules/jsx-equals-spacing'),
2627
'jsx-sort-props': require('./lib/rules/jsx-sort-props'),
2728
'jsx-sort-prop-types': require('./lib/rules/jsx-sort-prop-types'),
2829
'jsx-boolean-value': require('./lib/rules/jsx-boolean-value'),
@@ -62,6 +63,7 @@ module.exports = {
6263
'jsx-quotes': 0,
6364
'no-unknown-property': 0,
6465
'jsx-curly-spacing': 0,
66+
'jsx-equals-spacing': 0,
6567
'jsx-sort-props': 0,
6668
'jsx-sort-prop-types': 0,
6769
'jsx-boolean-value': 0,

lib/rules/jsx-equals-spacing.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* @fileoverview Disallow or enforce spaces around equal signs in JSX attributes.
3+
* @author ryym
4+
*/
5+
'use strict';
6+
7+
// ------------------------------------------------------------------------------
8+
// Rule Definition
9+
// ------------------------------------------------------------------------------
10+
11+
module.exports = function(context) {
12+
var config = context.options[0];
13+
var sourceCode = context.getSourceCode();
14+
15+
/**
16+
* Determines a given attribute node has an equal sign.
17+
* @param {ASTNode} attrNode - The attribute node.
18+
* @returns {boolean} Whether or not the attriute node has an equal sign.
19+
*/
20+
function hasEqual(attrNode) {
21+
return attrNode.type !== 'JSXSpreadAttribute' && attrNode.value !== null;
22+
}
23+
24+
// --------------------------------------------------------------------------
25+
// Public
26+
// --------------------------------------------------------------------------
27+
28+
return {
29+
JSXOpeningElement: function(node) {
30+
node.attributes.forEach(function(attrNode) {
31+
if (!hasEqual(attrNode)) {
32+
return;
33+
}
34+
35+
var equalToken = sourceCode.getTokenAfter(attrNode.name);
36+
var spacedBefore = sourceCode.isSpaceBetweenTokens(attrNode.name, equalToken);
37+
var spacedAfter = sourceCode.isSpaceBetweenTokens(equalToken, attrNode.value);
38+
39+
switch (config) {
40+
default:
41+
case 'never':
42+
if (spacedBefore) {
43+
context.report(attrNode, equalToken.loc.start,
44+
'There should be no space before \'=\'');
45+
}
46+
if (spacedAfter) {
47+
context.report(attrNode, equalToken.loc.start,
48+
'There should be no space after \'=\'');
49+
}
50+
break;
51+
case 'always':
52+
if (!spacedBefore) {
53+
context.report(attrNode, equalToken.loc.start,
54+
'A space is required before \'=\'');
55+
}
56+
if (!spacedAfter) {
57+
context.report(attrNode, equalToken.loc.start,
58+
'A space is required after \'=\'');
59+
}
60+
break;
61+
}
62+
});
63+
}
64+
};
65+
};
66+
67+
module.exports.schema = [{
68+
enum: ['always', 'never']
69+
}];

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

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/**
2+
* @fileoverview Disallow or enforce spaces around equal signs in JSX attributes.
3+
* @author ryym
4+
*/
5+
'use strict';
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
var rule = require('../../../lib/rules/jsx-equals-spacing');
12+
var RuleTester = require('eslint').RuleTester;
13+
14+
var parserOptions = {
15+
ecmaVersion: 6,
16+
ecmaFeatures: {
17+
jsx: true
18+
}
19+
};
20+
21+
// ------------------------------------------------------------------------------
22+
// Tests
23+
// ------------------------------------------------------------------------------
24+
25+
var ruleTester = new RuleTester();
26+
ruleTester.run('jsx-equals-spacing', rule, {
27+
valid: [{
28+
code: '<App />',
29+
parserOptions: parserOptions
30+
}, {
31+
code: '<App foo />',
32+
parserOptions: parserOptions
33+
}, {
34+
code: '<App foo="bar" />',
35+
parserOptions: parserOptions
36+
}, {
37+
code: '<App foo={e => bar(e)} />',
38+
parserOptions: parserOptions
39+
}, {
40+
code: '<App {...props} />',
41+
parserOptions: parserOptions
42+
}, {
43+
code: '<App />',
44+
options: ['never'],
45+
parserOptions: parserOptions
46+
}, {
47+
code: '<App foo />',
48+
options: ['never'],
49+
parserOptions: parserOptions
50+
}, {
51+
code: '<App foo="bar" />',
52+
options: ['never'],
53+
parserOptions: parserOptions
54+
}, {
55+
code: '<App foo={e => bar(e)} />',
56+
options: ['never'],
57+
parserOptions: parserOptions
58+
}, {
59+
code: '<App {...props} />',
60+
options: ['never'],
61+
parserOptions: parserOptions
62+
}, {
63+
code: '<App />',
64+
options: ['always'],
65+
parserOptions: parserOptions
66+
}, {
67+
code: '<App foo />',
68+
options: ['always'],
69+
parserOptions: parserOptions
70+
}, {
71+
code: '<App foo = "bar" />',
72+
options: ['always'],
73+
parserOptions: parserOptions
74+
}, {
75+
code: '<App foo = {e => bar(e)} />',
76+
options: ['always'],
77+
parserOptions: parserOptions
78+
}, {
79+
code: '<App {...props} />',
80+
options: ['always'],
81+
parserOptions: parserOptions
82+
}],
83+
84+
invalid: [{
85+
code: '<App foo = {bar} />',
86+
parserOptions: parserOptions,
87+
errors: [
88+
{message: 'There should be no space before \'=\''},
89+
{message: 'There should be no space after \'=\''}
90+
]
91+
}, {
92+
code: '<App foo = {bar} />',
93+
options: ['never'],
94+
parserOptions: parserOptions,
95+
errors: [
96+
{message: 'There should be no space before \'=\''},
97+
{message: 'There should be no space after \'=\''}
98+
]
99+
}, {
100+
code: '<App foo ={bar} />',
101+
options: ['never'],
102+
parserOptions: parserOptions,
103+
errors: [
104+
{message: 'There should be no space before \'=\''}
105+
]
106+
}, {
107+
code: '<App foo= {bar} />',
108+
options: ['never'],
109+
parserOptions: parserOptions,
110+
errors: [
111+
{message: 'There should be no space after \'=\''}
112+
]
113+
}, {
114+
code: '<App foo= {bar} bar = {baz} />',
115+
options: ['never'],
116+
parserOptions: parserOptions,
117+
errors: [
118+
{message: 'There should be no space after \'=\''},
119+
{message: 'There should be no space before \'=\''},
120+
{message: 'There should be no space after \'=\''}
121+
]
122+
}, {
123+
code: '<App foo={bar} />',
124+
options: ['always'],
125+
parserOptions: parserOptions,
126+
errors: [
127+
{message: 'A space is required before \'=\''},
128+
{message: 'A space is required after \'=\''}
129+
]
130+
}, {
131+
code: '<App foo ={bar} />',
132+
options: ['always'],
133+
parserOptions: parserOptions,
134+
errors: [
135+
{message: 'A space is required after \'=\''}
136+
]
137+
}, {
138+
code: '<App foo= {bar} />',
139+
options: ['always'],
140+
parserOptions: parserOptions,
141+
errors: [
142+
{message: 'A space is required before \'=\''}
143+
]
144+
}, {
145+
code: '<App foo={bar} bar ={baz} />',
146+
options: ['always'],
147+
parserOptions: parserOptions,
148+
errors: [
149+
{message: 'A space is required before \'=\''},
150+
{message: 'A space is required after \'=\''},
151+
{message: 'A space is required after \'=\''}
152+
]
153+
}]
154+
});

0 commit comments

Comments
 (0)