-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add jsx-curly-spacing rule (fixes #142)
- Loading branch information
Yannick Croissant
committed
Jul 10, 2015
1 parent
81bde27
commit 250b9eb
Showing
5 changed files
with
294 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Enforce or disallow spaces inside of curly braces in JSX attributes. (jsx-curly-spacing) | ||
|
||
While formatting preferences are very personal, a number of style guides require or disallow spaces between curly braces. | ||
|
||
## Rule Details | ||
|
||
This rule aims to maintain consistency around the spacing inside of JSX attributes. | ||
|
||
It either requires or disallows spaces between those braces and the values inside of them. | ||
|
||
### Options | ||
|
||
There are two main options for the rule: | ||
|
||
* `"always"` enforces a space inside of curly braces | ||
* `"never"` disallows spaces inside of curly braces (default) | ||
|
||
Depending on your coding conventions, you can choose either option by specifying it in your configuration: | ||
|
||
```json | ||
"jsx-curly-spacing": [2, "always"] | ||
``` | ||
|
||
#### never | ||
|
||
When `"never"` is set, the following patterns are considered warnings: | ||
|
||
```js | ||
<Hello name={ firstname } />; | ||
<Hello name={ firstname} />; | ||
<Hello name={firstname } />; | ||
<Hello name={ | ||
firstname | ||
} />; | ||
``` | ||
|
||
The following patterns are not warnings: | ||
|
||
```js | ||
<Hello name={firstname} />; | ||
<Hello name={{ firstname: 'John', lastname: 'Doe' }} />; | ||
``` | ||
|
||
#### always | ||
|
||
When `"always"` is used, the following patterns are considered warnings: | ||
|
||
```js | ||
<Hello name={firstname} />; | ||
<Hello name={ firstname} />; | ||
<Hello name={firstname } />; | ||
``` | ||
|
||
The following patterns are not warnings: | ||
|
||
```js | ||
<Hello name={ firstname } />; | ||
<Hello name={ {firstname: 'John', lastname: 'Doe'} } />; | ||
<Hello name={ | ||
firstname | ||
} />; | ||
``` | ||
|
||
## When Not To Use It | ||
|
||
You can turn this rule off if you are not concerned with the consistency around the spacing inside of JSX attributes. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/** | ||
* @fileoverview Enforce or disallow spaces inside of curly braces in JSX attributes. | ||
* @author Jamund Ferguson, Brandyn Bennett, Michael Ficarra, Vignesh Anand, Jamund Ferguson, Yannick Croissant | ||
*/ | ||
'use strict'; | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Rule Definition | ||
// ------------------------------------------------------------------------------ | ||
|
||
module.exports = function(context) { | ||
var spaced = context.options[0] === 'always'; | ||
|
||
// -------------------------------------------------------------------------- | ||
// Helpers | ||
// -------------------------------------------------------------------------- | ||
|
||
/** | ||
* Determines whether two adjacent tokens are have whitespace between them. | ||
* @param {Object} left - The left token object. | ||
* @param {Object} right - The right token object. | ||
* @returns {boolean} Whether or not there is space between the tokens. | ||
*/ | ||
function isSpaced(left, right) { | ||
return left.range[1] < right.range[0]; | ||
} | ||
|
||
/** | ||
* Reports that there shouldn't be a space after the first token | ||
* @param {ASTNode} node - The node to report in the event of an error. | ||
* @param {Token} token - The token to use for the report. | ||
* @returns {void} | ||
*/ | ||
function reportNoBeginningSpace(node, token) { | ||
context.report(node, token.loc.start, | ||
'There should be no space after \'' + token.value + '\''); | ||
} | ||
|
||
/** | ||
* Reports that there shouldn't be a space before the last token | ||
* @param {ASTNode} node - The node to report in the event of an error. | ||
* @param {Token} token - The token to use for the report. | ||
* @returns {void} | ||
*/ | ||
function reportNoEndingSpace(node, token) { | ||
context.report(node, token.loc.start, | ||
'There should be no space before \'' + token.value + '\''); | ||
} | ||
|
||
/** | ||
* Reports that there should be a space after the first token | ||
* @param {ASTNode} node - The node to report in the event of an error. | ||
* @param {Token} token - The token to use for the report. | ||
* @returns {void} | ||
*/ | ||
function reportRequiredBeginningSpace(node, token) { | ||
context.report(node, token.loc.start, | ||
'A space is required after \'' + token.value + '\''); | ||
} | ||
|
||
/** | ||
* Reports that there should be a space before the last token | ||
* @param {ASTNode} node - The node to report in the event of an error. | ||
* @param {Token} token - The token to use for the report. | ||
* @returns {void} | ||
*/ | ||
function reportRequiredEndingSpace(node, token) { | ||
context.report(node, token.loc.start, | ||
'A space is required before \'' + token.value + '\''); | ||
} | ||
|
||
/** | ||
* Determines if spacing in curly braces is valid. | ||
* @param {ASTNode} node The AST node to check. | ||
* @param {Token} first The first token to check (should be the opening brace) | ||
* @param {Token} second The second token to check (should be first after the opening brace) | ||
* @param {Token} penultimate The penultimate token to check (should be last before closing brace) | ||
* @param {Token} last The last token to check (should be closing brace) | ||
* @returns {void} | ||
*/ | ||
function validateBraceSpacing(node, first, second, penultimate, last) { | ||
if (spaced && !isSpaced(first, second)) { | ||
reportRequiredBeginningSpace(node, first); | ||
} | ||
if (!spaced && isSpaced(first, second)) { | ||
reportNoBeginningSpace(node, first); | ||
} | ||
if (spaced && !isSpaced(penultimate, last)) { | ||
reportRequiredEndingSpace(node, last); | ||
} | ||
if (!spaced && isSpaced(penultimate, last)) { | ||
reportNoEndingSpace(node, last); | ||
} | ||
} | ||
|
||
// -------------------------------------------------------------------------- | ||
// Public | ||
// -------------------------------------------------------------------------- | ||
|
||
return { | ||
JSXExpressionContainer: function(node) { | ||
var first = context.getFirstToken(node); | ||
var second = context.getFirstToken(node, 1); | ||
var penultimate = context.getLastToken(node, 1); | ||
var last = context.getLastToken(node); | ||
|
||
validateBraceSpacing(node, first, second, penultimate, last); | ||
} | ||
}; | ||
}; | ||
|
||
module.exports.schema = [{ | ||
enum: ['always', 'never'] | ||
}]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/** | ||
* @fileoverview Enforce or disallow spaces inside of curly braces in JSX attributes. | ||
* @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/jsx-curly-spacing', { | ||
valid: [{ | ||
code: '<App foo={bar} />;', | ||
args: 1, | ||
ecmaFeatures: {jsx: true} | ||
}, { | ||
code: '<App foo={bar} />;', | ||
args: [1, 'never'], | ||
ecmaFeatures: {jsx: true} | ||
}, { | ||
code: '<App foo={ bar } />;', | ||
args: [1, 'always'], | ||
ecmaFeatures: {jsx: true} | ||
}, { | ||
code: '<App foo={{ bar:baz }} />;', | ||
args: [1, 'never'], | ||
ecmaFeatures: {jsx: true} | ||
}, { | ||
code: '<App foo={ {bar:baz} } />;', | ||
args: [1, 'always'], | ||
ecmaFeatures: {jsx: true} | ||
}, { | ||
code: [ | ||
'<App foo={', | ||
'bar', | ||
'} />;' | ||
].join('\n'), | ||
args: [1, 'always'], | ||
ecmaFeatures: {jsx: true} | ||
}], | ||
|
||
invalid: [{ | ||
code: '<App foo={ bar } />;', | ||
args: [1, 'never'], | ||
errors: [{ | ||
message: 'There should be no space after \'{\'' | ||
}, { | ||
message: 'There should be no space before \'}\'' | ||
}], | ||
ecmaFeatures: {jsx: true} | ||
}, { | ||
code: '<App foo={bar} />;', | ||
args: [1, 'always'], | ||
errors: [{ | ||
message: 'A space is required after \'{\'' | ||
}, { | ||
message: 'A space is required before \'}\'' | ||
}], | ||
ecmaFeatures: {jsx: true} | ||
}, { | ||
code: '<App foo={ bar} />;', | ||
args: [1, 'always'], | ||
errors: [{ | ||
message: 'A space is required before \'}\'' | ||
}], | ||
ecmaFeatures: {jsx: true} | ||
}, { | ||
code: '<App foo={bar } />;', | ||
args: [1, 'always'], | ||
errors: [{ | ||
message: 'A space is required after \'{\'' | ||
}], | ||
ecmaFeatures: {jsx: true} | ||
}, { | ||
code: '<App foo={ bar} />;', | ||
args: [1, 'never'], | ||
errors: [{ | ||
message: 'There should be no space after \'{\'' | ||
}], | ||
ecmaFeatures: {jsx: true} | ||
}, { | ||
code: '<App foo={bar } />;', | ||
args: [1, 'never'], | ||
errors: [{ | ||
message: 'There should be no space before \'}\'' | ||
}], | ||
ecmaFeatures: {jsx: true} | ||
}, { | ||
code: [ | ||
'<App foo={', | ||
'bar', | ||
'} />;' | ||
].join('\n'), | ||
args: [1, 'never'], | ||
errors: [{ | ||
message: 'There should be no space after \'{\'' | ||
}, { | ||
message: 'There should be no space before \'}\'' | ||
}], | ||
ecmaFeatures: {jsx: true} | ||
}] | ||
}); |