Skip to content

Commit 29c659e

Browse files
author
Ross Solomon
committed
* Remove ecmaScript rule
* Remove rest/spread on import * Add fixer
1 parent b863f9f commit 29c659e

File tree

2 files changed

+60
-6
lines changed

2 files changed

+60
-6
lines changed

lib/rules/jsx-closing-tag-location.js

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,39 @@
1010
module.exports = {
1111
meta: {
1212
docs: {
13-
description: 'Validate closing tag location in JSX',
13+
description: 'Validate closing tag location for multiline JSX',
1414
category: 'Stylistic Issues',
1515
recommended: false
16-
}
16+
},
17+
fixable: 'whitespace'
1718
},
1819

1920
create: function(context) {
21+
var sourceCode = context.getSourceCode();
22+
23+
/**
24+
* Checks if the node is the first in its line, excluding whitespace.
25+
* @param {ASTNode} node The node to check
26+
* @return {Boolean} true if its the first node in its line
27+
*/
28+
function isNodeFirstInLine(node) {
29+
let token = node;
30+
let lines;
31+
do {
32+
token = sourceCode.getTokenBefore(token);
33+
lines = token.type === 'JSXText'
34+
? token.value.split('\n')
35+
: null;
36+
} while (
37+
token.type === 'JSXText' &&
38+
/^\s*$/.test(lines[lines.length - 1])
39+
);
40+
41+
var startLine = node.loc.start.line;
42+
var endLine = token ? token.loc.end.line : -1;
43+
return startLine !== endLine;
44+
}
45+
2046
return {
2147
JSXClosingElement: function(node) {
2248
if (!node.parent) {
@@ -32,10 +58,28 @@ module.exports = {
3258
return;
3359
}
3460

61+
let message;
62+
if (!isNodeFirstInLine(node)) {
63+
message = 'Closing tag of a multiline JSX expression must be on its own line.';
64+
} else {
65+
message = 'Expected closing tag to match indentation of opening.';
66+
}
67+
3568
context.report({
3669
node: node,
3770
loc: node.loc,
38-
message: 'Expected closing tag to match indentation of opening.'
71+
message,
72+
fix: function(fixer) {
73+
const indent = Array(opening.loc.start.column + 1).join(' ');
74+
if (isNodeFirstInLine(node)) {
75+
return fixer.replaceTextRange(
76+
[node.start - node.loc.start.column, node.start],
77+
indent
78+
);
79+
}
80+
81+
return fixer.insertTextBefore(node, `\n${indent}`);
82+
}
3983
});
4084
}
4185
};

tests/lib/rules/jsx-closing-tag-location.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@
99
// ------------------------------------------------------------------------------
1010

1111
const rule = require('../../../lib/rules/jsx-closing-tag-location');
12-
const {RuleTester} = require('eslint');
12+
const RuleTester = require('eslint').RuleTester;
1313
const parserOptions = {
14-
ecmaVersion: 8,
1514
sourceType: 'module',
1615
ecmaFeatures: {
1716
experimentalObjectRestSpread: true,
@@ -20,6 +19,7 @@ const parserOptions = {
2019
};
2120

2221
const MESSAGE_MATCH_INDENTATION = [{message: 'Expected closing tag to match indentation of opening.'}];
22+
const MESSAGE_OWN_LINE = [{message: 'Closing tag of a multiline JSX expression must be on its own line.'}];
2323

2424
// ------------------------------------------------------------------------------
2525
// Tests
@@ -45,12 +45,22 @@ ruleTester.run('jsx-closing-tag-location', rule, {
4545
' foo',
4646
' </App>'
4747
].join('\n'),
48+
output: [
49+
'<App>',
50+
' foo',
51+
'</App>'
52+
].join('\n'),
4853
errors: MESSAGE_MATCH_INDENTATION
4954
}, {
5055
code: [
5156
'<App>',
5257
' foo</App>'
5358
].join('\n'),
54-
errors: MESSAGE_MATCH_INDENTATION
59+
output: [
60+
'<App>',
61+
' foo',
62+
'</App>'
63+
].join('\n'),
64+
errors: MESSAGE_OWN_LINE
5565
}]
5666
});

0 commit comments

Comments
 (0)