Skip to content

Commit abdfda9

Browse files
committed
Add always/never options to jsx-space-before-closing
1 parent d0a6b58 commit abdfda9

File tree

4 files changed

+118
-20
lines changed

4 files changed

+118
-20
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ Finally, enable all of the rules that you would like to use.
9292
"react/jsx-quotes": 1,
9393
"react/jsx-sort-prop-types": 1,
9494
"react/jsx-sort-props": 1,
95+
"react/jsx-space-before-closing": 1,
9596
"react/jsx-uses-react": 1,
9697
"react/jsx-uses-vars": 1,
9798
"react/no-danger": 1,
@@ -121,7 +122,6 @@ Finally, enable all of the rules that you would like to use.
121122
* [forbid-prop-types](docs/rules/forbid-prop-types.md): Forbid certain propTypes
122123
* [jsx-boolean-value](docs/rules/jsx-boolean-value.md): Enforce boolean attributes notation in JSX (fixable)
123124
* [jsx-closing-bracket-location](docs/rules/jsx-closing-bracket-location.md): Validate closing bracket location in JSX
124-
* [jsx-space-before-closing](docs/rules/jsx-space-before-closing.md): Validate spacing before closing bracket in JSX (fixable)
125125
* [jsx-curly-spacing](docs/rules/jsx-curly-spacing.md): Enforce or disallow spaces inside of curly braces in JSX attributes (fixable)
126126
* [jsx-equals-spacing](docs/rules/jsx-equals-spacing.md): Enforce or disallow spaces around equal signs in JSX attributes
127127
* [jsx-handler-names](docs/rules/jsx-handler-names.md): Enforce event handler naming conventions in JSX
@@ -137,6 +137,7 @@ Finally, enable all of the rules that you would like to use.
137137
* [jsx-quotes](docs/rules/jsx-quotes.md): Enforce quote style for JSX attributes
138138
* [jsx-sort-prop-types](docs/rules/jsx-sort-prop-types.md): Enforce propTypes declarations alphabetical sorting
139139
* [jsx-sort-props](docs/rules/jsx-sort-props.md): Enforce props alphabetical sorting
140+
* [jsx-space-before-closing](docs/rules/jsx-space-before-closing.md): Validate spacing before closing bracket in JSX (fixable)
140141
* [jsx-uses-react](docs/rules/jsx-uses-react.md): Prevent React to be incorrectly marked as unused
141142
* [jsx-uses-vars](docs/rules/jsx-uses-vars.md): Prevent variables used in JSX to be incorrectly marked as unused
142143
* [no-danger](docs/rules/no-danger.md): Prevent usage of dangerous JSX properties
Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
# Validate spacing before closing bracket in JSX (jsx-space-before-closing)
22

3-
Enforce a space before the closing bracket of self-closing JSX elements.
3+
Enforce or forbid spaces before the closing bracket of self-closing JSX elements.
44

55
## Rule Details
66

77
This rule checks if there is one or more spaces before the closing bracket of self-closing JSX elements.
88

9-
The following patterns are considered warnings:
9+
This rule takes one argument. If it is `"always"` then it warns whenever a space is missing before the closing bracket. If `"never"` then it warns if a space is present before the closing bracket. The default value of this option is `"always"`.
10+
11+
The following patterns are considered warnings when configured `"always"`:
1012

1113
```js
1214
<Hello/>
1315
<Hello firstname="John"/>
1416
```
1517

16-
The following patterns are not considered warnings:
18+
The following patterns are not considered warnings when configured `"always"`:
1719

1820
```js
1921
<Hello />
@@ -24,6 +26,24 @@ The following patterns are not considered warnings:
2426
/>
2527
```
2628

29+
The following patterns are considered warnings when configured `"never"`:
30+
31+
```js
32+
<Hello />
33+
<Hello firstName="John" />
34+
```
35+
36+
The following patterns are not considered warnings when configured `"never"`:
37+
38+
```js
39+
<Hello/>
40+
<Hello firstname="John"/>
41+
<Hello
42+
firstName="John"
43+
lastName="Smith"
44+
/>
45+
```
46+
2747
## When Not To Use It
2848

2949
You can turn this rule off if you are not concerned with the consistency of spacing before closing brackets.

lib/rules/jsx-space-before-closing.js

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @fileoverview Enforce a space before closing bracket of self-closing JSX elements.
2+
* @fileoverview Validate spacing before closing bracket in JSX.
33
* @author ryym
44
*/
55
'use strict';
@@ -9,8 +9,13 @@
99
// ------------------------------------------------------------------------------
1010

1111
module.exports = function(context) {
12+
13+
var configuration = context.options[0] || 'always';
1214
var sourceCode = context.getSourceCode();
1315

16+
var NEVER_MESSAGE = 'A space is forbidden before closing bracket';
17+
var ALWAYS_MESSAGE = 'A space is required before closing bracket';
18+
1419
/**
1520
* Find the token before the closing bracket.
1621
* @param {ASTNode} node - The JSX element node.
@@ -37,20 +42,33 @@ module.exports = function(context) {
3742
var leftToken = getTokenBeforeClosingBracket(node);
3843
var closingSlash = sourceCode.getTokenAfter(leftToken);
3944

40-
if (sourceCode.isSpaceBetweenTokens(leftToken, closingSlash)) {
45+
if (leftToken.loc.end.line !== closingSlash.loc.start.line) {
4146
return;
4247
}
4348

44-
context.report({
45-
loc: closingSlash.loc.start,
46-
message: 'A space is required before \'/>\'',
47-
fix: function(fixer) {
48-
return fixer.insertTextBefore(closingSlash, ' ');
49-
}
50-
});
49+
if (configuration === 'always' && !sourceCode.isSpaceBetweenTokens(leftToken, closingSlash)) {
50+
context.report({
51+
loc: closingSlash.loc.start,
52+
message: ALWAYS_MESSAGE,
53+
fix: function(fixer) {
54+
return fixer.insertTextBefore(closingSlash, ' ');
55+
}
56+
});
57+
} else if (configuration === 'never' && sourceCode.isSpaceBetweenTokens(leftToken, closingSlash)) {
58+
context.report({
59+
loc: closingSlash.loc.start,
60+
message: NEVER_MESSAGE,
61+
fix: function(fixer) {
62+
var previousToken = sourceCode.getTokenBefore(closingSlash);
63+
return fixer.removeRange([previousToken.range[1], closingSlash.range[0]]);
64+
}
65+
});
66+
}
5167
}
5268
};
5369

5470
};
5571

56-
module.exports.schema = [];
72+
module.exports.schema = [{
73+
enum: ['always', 'never']
74+
}];

tests/lib/rules/jsx-space-before-closing.js

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @fileoverview Enforce a space before closing bracket of self-closing JSX elements.
2+
* @fileoverview Validate spacing before closing bracket in JSX.
33
* @author ryym
44
*/
55
'use strict';
@@ -46,36 +46,95 @@ ruleTester.run('jsx-space-before-closing', rule, {
4646
'/>'
4747
].join('\n'),
4848
parserOptions: parserOptions
49+
}, {
50+
code: '<App/>',
51+
options: ['never'],
52+
parserOptions: parserOptions
53+
}, {
54+
code: '<App foo/>',
55+
options: ['never'],
56+
parserOptions: parserOptions
57+
}, {
58+
code: '<App foo={bar}/>',
59+
options: ['never'],
60+
parserOptions: parserOptions
61+
}, {
62+
code: '<App {...props}/>',
63+
options: ['never'],
64+
parserOptions: parserOptions
65+
}, {
66+
code: '<App></App>',
67+
options: ['never'],
68+
parserOptions: parserOptions
69+
}, {
70+
code: [
71+
'<App',
72+
' foo={bar}',
73+
'/>'
74+
].join('\n'),
75+
options: ['never'],
76+
parserOptions: parserOptions
4977
}],
5078

5179
invalid: [{
5280
code: '<App/>',
5381
output: '<App />',
5482
parserOptions: parserOptions,
5583
errors: [
56-
{message: 'A space is required before \'/>\''}
84+
{message: 'A space is required before closing bracket'}
5785
]
5886
}, {
5987
code: '<App foo/>',
6088
output: '<App foo />',
6189
parserOptions: parserOptions,
6290
errors: [
63-
{message: 'A space is required before \'/>\''}
91+
{message: 'A space is required before closing bracket'}
6492
]
6593
}, {
6694
code: '<App foo={bar}/>',
6795
output: '<App foo={bar} />',
6896
parserOptions: parserOptions,
6997
errors: [
70-
{message: 'A space is required before \'/>\''}
98+
{message: 'A space is required before closing bracket'}
7199
]
72100
}, {
73101
code: '<App {...props}/>',
74102
output: '<App {...props} />',
75103
parserOptions: parserOptions,
76104
errors: [
77-
{message: 'A space is required before \'/>\''}
105+
{message: 'A space is required before closing bracket'}
106+
]
107+
}, {
108+
code: '<App />',
109+
output: '<App/>',
110+
options: ['never'],
111+
parserOptions: parserOptions,
112+
errors: [
113+
{message: 'A space is forbidden before closing bracket'}
114+
]
115+
}, {
116+
code: '<App foo />',
117+
output: '<App foo/>',
118+
options: ['never'],
119+
parserOptions: parserOptions,
120+
errors: [
121+
{message: 'A space is forbidden before closing bracket'}
122+
]
123+
}, {
124+
code: '<App foo={bar} />',
125+
output: '<App foo={bar}/>',
126+
options: ['never'],
127+
parserOptions: parserOptions,
128+
errors: [
129+
{message: 'A space is forbidden before closing bracket'}
130+
]
131+
}, {
132+
code: '<App {...props} />',
133+
output: '<App {...props}/>',
134+
options: ['never'],
135+
parserOptions: parserOptions,
136+
errors: [
137+
{message: 'A space is forbidden before closing bracket'}
78138
]
79139
}]
80140
});
81-

0 commit comments

Comments
 (0)