Skip to content

Commit

Permalink
Add always/never options to jsx-space-before-closing
Browse files Browse the repository at this point in the history
  • Loading branch information
yannickcr authored and lencioni committed Feb 13, 2016
1 parent 895c03b commit 229bb1b
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 20 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ Finally, enable all of the rules that you would like to use.
"react/jsx-quotes": 1,
"react/jsx-sort-prop-types": 1,
"react/jsx-sort-props": 1,
"react/jsx-space-before-closing": 1,
"react/jsx-uses-react": 1,
"react/jsx-uses-vars": 1,
"react/no-danger": 1,
Expand Down Expand Up @@ -121,7 +122,6 @@ Finally, enable all of the rules that you would like to use.
* [forbid-prop-types](docs/rules/forbid-prop-types.md): Forbid certain propTypes
* [jsx-boolean-value](docs/rules/jsx-boolean-value.md): Enforce boolean attributes notation in JSX (fixable)
* [jsx-closing-bracket-location](docs/rules/jsx-closing-bracket-location.md): Validate closing bracket location in JSX
* [jsx-space-before-closing](docs/rules/jsx-space-before-closing.md): Validate spacing before closing bracket in JSX (fixable)
* [jsx-curly-spacing](docs/rules/jsx-curly-spacing.md): Enforce or disallow spaces inside of curly braces in JSX attributes (fixable)
* [jsx-equals-spacing](docs/rules/jsx-equals-spacing.md): Enforce or disallow spaces around equal signs in JSX attributes
* [jsx-handler-names](docs/rules/jsx-handler-names.md): Enforce event handler naming conventions in JSX
Expand All @@ -137,6 +137,7 @@ Finally, enable all of the rules that you would like to use.
* [jsx-quotes](docs/rules/jsx-quotes.md): Enforce quote style for JSX attributes
* [jsx-sort-prop-types](docs/rules/jsx-sort-prop-types.md): Enforce propTypes declarations alphabetical sorting
* [jsx-sort-props](docs/rules/jsx-sort-props.md): Enforce props alphabetical sorting
* [jsx-space-before-closing](docs/rules/jsx-space-before-closing.md): Validate spacing before closing bracket in JSX (fixable)
* [jsx-uses-react](docs/rules/jsx-uses-react.md): Prevent React to be incorrectly marked as unused
* [jsx-uses-vars](docs/rules/jsx-uses-vars.md): Prevent variables used in JSX to be incorrectly marked as unused
* [no-danger](docs/rules/no-danger.md): Prevent usage of dangerous JSX properties
Expand Down
26 changes: 23 additions & 3 deletions docs/rules/jsx-space-before-closing.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
# Validate spacing before closing bracket in JSX (jsx-space-before-closing)

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

## Rule Details

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

The following patterns are considered warnings:
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"`.

The following patterns are considered warnings when configured `"always"`:

```js
<Hello/>
<Hello firstname="John"/>
```

The following patterns are not considered warnings:
The following patterns are not considered warnings when configured `"always"`:

```js
<Hello />
Expand All @@ -24,6 +26,24 @@ The following patterns are not considered warnings:
/>
```

The following patterns are considered warnings when configured `"never"`:

```js
<Hello />
<Hello firstName="John" />
```

The following patterns are not considered warnings when configured `"never"`:

```js
<Hello/>
<Hello firstname="John"/>
<Hello
firstName="John"
lastName="Smith"
/>
```

## When Not To Use It

You can turn this rule off if you are not concerned with the consistency of spacing before closing brackets.
38 changes: 28 additions & 10 deletions lib/rules/jsx-space-before-closing.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @fileoverview Enforce a space before closing bracket of self-closing JSX elements.
* @fileoverview Validate spacing before closing bracket in JSX.
* @author ryym
*/
'use strict';
Expand All @@ -9,8 +9,13 @@
// ------------------------------------------------------------------------------

module.exports = function(context) {

var configuration = context.options[0] || 'always';
var sourceCode = context.getSourceCode();

var NEVER_MESSAGE = 'A space is forbidden before closing bracket';
var ALWAYS_MESSAGE = 'A space is required before closing bracket';

/**
* Find the token before the closing bracket.
* @param {ASTNode} node - The JSX element node.
Expand All @@ -37,20 +42,33 @@ module.exports = function(context) {
var leftToken = getTokenBeforeClosingBracket(node);
var closingSlash = sourceCode.getTokenAfter(leftToken);

if (sourceCode.isSpaceBetweenTokens(leftToken, closingSlash)) {
if (leftToken.loc.end.line !== closingSlash.loc.start.line) {
return;
}

context.report({
loc: closingSlash.loc.start,
message: 'A space is required before \'/>\'',
fix: function(fixer) {
return fixer.insertTextBefore(closingSlash, ' ');
}
});
if (configuration === 'always' && !sourceCode.isSpaceBetweenTokens(leftToken, closingSlash)) {
context.report({
loc: closingSlash.loc.start,
message: ALWAYS_MESSAGE,
fix: function(fixer) {
return fixer.insertTextBefore(closingSlash, ' ');
}
});
} else if (configuration === 'never' && sourceCode.isSpaceBetweenTokens(leftToken, closingSlash)) {
context.report({
loc: closingSlash.loc.start,
message: NEVER_MESSAGE,
fix: function(fixer) {
var previousToken = sourceCode.getTokenBefore(closingSlash);
return fixer.removeRange([previousToken.range[1], closingSlash.range[0]]);
}
});
}
}
};

};

module.exports.schema = [];
module.exports.schema = [{
enum: ['always', 'never']
}];
71 changes: 65 additions & 6 deletions tests/lib/rules/jsx-space-before-closing.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @fileoverview Enforce a space before closing bracket of self-closing JSX elements.
* @fileoverview Validate spacing before closing bracket in JSX.
* @author ryym
*/
'use strict';
Expand Down Expand Up @@ -46,36 +46,95 @@ ruleTester.run('jsx-space-before-closing', rule, {
'/>'
].join('\n'),
parserOptions: parserOptions
}, {
code: '<App/>',
options: ['never'],
parserOptions: parserOptions
}, {
code: '<App foo/>',
options: ['never'],
parserOptions: parserOptions
}, {
code: '<App foo={bar}/>',
options: ['never'],
parserOptions: parserOptions
}, {
code: '<App {...props}/>',
options: ['never'],
parserOptions: parserOptions
}, {
code: '<App></App>',
options: ['never'],
parserOptions: parserOptions
}, {
code: [
'<App',
' foo={bar}',
'/>'
].join('\n'),
options: ['never'],
parserOptions: parserOptions
}],

invalid: [{
code: '<App/>',
output: '<App />',
parserOptions: parserOptions,
errors: [
{message: 'A space is required before \'/>\''}
{message: 'A space is required before closing bracket'}
]
}, {
code: '<App foo/>',
output: '<App foo />',
parserOptions: parserOptions,
errors: [
{message: 'A space is required before \'/>\''}
{message: 'A space is required before closing bracket'}
]
}, {
code: '<App foo={bar}/>',
output: '<App foo={bar} />',
parserOptions: parserOptions,
errors: [
{message: 'A space is required before \'/>\''}
{message: 'A space is required before closing bracket'}
]
}, {
code: '<App {...props}/>',
output: '<App {...props} />',
parserOptions: parserOptions,
errors: [
{message: 'A space is required before \'/>\''}
{message: 'A space is required before closing bracket'}
]
}, {
code: '<App />',
output: '<App/>',
options: ['never'],
parserOptions: parserOptions,
errors: [
{message: 'A space is forbidden before closing bracket'}
]
}, {
code: '<App foo />',
output: '<App foo/>',
options: ['never'],
parserOptions: parserOptions,
errors: [
{message: 'A space is forbidden before closing bracket'}
]
}, {
code: '<App foo={bar} />',
output: '<App foo={bar}/>',
options: ['never'],
parserOptions: parserOptions,
errors: [
{message: 'A space is forbidden before closing bracket'}
]
}, {
code: '<App {...props} />',
output: '<App {...props}/>',
options: ['never'],
parserOptions: parserOptions,
errors: [
{message: 'A space is forbidden before closing bracket'}
]
}]
});

0 comments on commit 229bb1b

Please sign in to comment.