Skip to content

Commit

Permalink
[Fix] jsx-indent: Does not check indents for JSXText
Browse files Browse the repository at this point in the history
Fixes #2467. Fixes #2484. Fixes #1136.
  • Loading branch information
toshi-toma authored and ljharb committed Jan 16, 2020
1 parent d1dc277 commit 0264f6a
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 6 deletions.
59 changes: 58 additions & 1 deletion lib/rules/jsx-indent.js
Expand Up @@ -97,6 +97,11 @@ module.exports = {
function getFixerFunction(node, needed) {
return function fix(fixer) {
const indent = Array(needed + 1).join(indentChar);
if (node.type === 'JSXText') {
const regExp = /\n[\t ]*(\S)/g;
const fixedText = node.raw.replace(regExp, (match, p1) => `\n${indent}${p1}`);
return fixer.replaceText(node, fixedText);
}
return fixer.replaceTextRange(
[node.range[0] - node.loc.start.column, node.range[0]],
indent
Expand All @@ -108,7 +113,7 @@ module.exports = {
* Reports a given indent violation and properly pluralizes the message
* @param {ASTNode} node Node violating the indent rule
* @param {Number} needed Expected indentation character count
* @param {Number} gotten Indentation character count in the actual node/code
* @param {Number|Array<number>} gotten Indentation character count in the actual node/code
* @param {Object} [loc] Error line and column location
*/
function report(node, needed, gotten, loc) {
Expand Down Expand Up @@ -290,6 +295,51 @@ module.exports = {
}
}

/**
* Instead String.prototype.mathAll
* @param {String} str
* @param {RegExp} regex
* @returns {Array}
*/
function matchAll(str, regex) {
const matches = [];
str.replace(regex, (...args) => {
/** @type {object} */
const match = Array.prototype.slice.call(args, 0, -2);
match.input = args[args.length - 1];
match.index = args[args.length - 2];
matches.push(match);
return '';
});
return matches;
}

/**
* Check indent for JSXText
* @param {ASTNode} node The node to check
* @param {Number} indent needed indent
*/
function checkJSXTextNodeIndent(node, indent) {
const value = node.value;
const regExp = indentType === 'space' ? /\n( *)[\t ]*\S/g : /\n(\t*)[\t ]*\S/g;
const nodeIndentsPerLine = [];
const matches = matchAll(value, regExp);
matches.forEach((match) => {
if (match[1]) {
nodeIndentsPerLine.push(match[1].length);
} else {
nodeIndentsPerLine.push(0);
}
});
const hasFirstInLineNode = nodeIndentsPerLine.length > 0;
if (
hasFirstInLineNode &&
!nodeIndentsPerLine.every(actualIndent => actualIndent === indent)
) {
report(node, indent, nodeIndentsPerLine);
}
}

function handleOpeningElement(node) {
const sourceCode = context.getSourceCode();
let prevToken = sourceCode.getTokenBefore(node);
Expand Down Expand Up @@ -352,6 +402,13 @@ module.exports = {
}
const parentNodeIndent = getNodeIndent(node.parent);
checkNodesIndent(node, parentNodeIndent + indentSize);
},
JSXText(node) {
if (!node.parent) {
return;
}
const parentNodeIndent = getNodeIndent(node.parent);
checkJSXTextNodeIndent(node, parentNodeIndent + indentSize);
}
};
}
Expand Down
69 changes: 64 additions & 5 deletions tests/lib/rules/jsx-indent.js
Expand Up @@ -300,13 +300,12 @@ ruleTester.run('jsx-indent', rule, {
].join('\n'),
parser: parsers.BABEL_ESLINT
}, {
// Literals indentation is not touched
code: [
'<div>',
'bar <div>',
' bar',
' bar {foo}',
'bar </div>',
' bar <div>',
' bar',
' bar {foo}',
' bar </div>',
'</div>'
].join('\n')
}, {
Expand Down Expand Up @@ -956,6 +955,27 @@ const Component = () => (
}
`,
options: [2, {indentLogicalExpressions: true}]
}, {
code: [
'<App>',
' text',
'</App>'
].join('\n')
}, {
code: [
'<App>',
' text',
' text',
' text',
'</App>'
].join('\n')
}, {
code: [
'<App>',
'\ttext',
'</App>'
].join('\n'),
options: ['tab']
}],

invalid: [{
Expand Down Expand Up @@ -1883,5 +1903,44 @@ const Component = () => (
errors: [
{message: 'Expected indentation of 8 space characters but found 4.'}
]
}, {
code: [
'<div>',
'text',
'</div>'
].join('\n'),
errors: [
{message: 'Expected indentation of 4 space characters but found 0.'}
]
}, {
code: [
'<div>',
' text',
'text',
'</div>'
].join('\n'),
errors: [
{message: 'Expected indentation of 4 space characters but found 2,0.'}
]
}, {
code: [
'<div>',
'\t text',
' \t text',
'</div>'
].join('\n'),
errors: [
{message: 'Expected indentation of 4 space characters but found 0,2.'}
]
}, {
code: [
'<div>',
'\t\ttext',
'</div>'
].join('\n'),
options: ['tab'],
errors: [
{message: 'Expected indentation of 1 tab character but found 2.'}
]
}]
});

0 comments on commit 0264f6a

Please sign in to comment.