From f302f05e940fbd21fddfdabd09c903b1cbb20d2b Mon Sep 17 00:00:00 2001 From: Joshua Stiefer Date: Wed, 12 Dec 2018 21:31:16 -0700 Subject: [PATCH 1/4] Handle JSX attribute indentation in jsx-indent --- lib/rules/jsx-indent.js | 12 ++++++++ lib/util/ast.js | 18 +++++++++-- tests/lib/rules/jsx-indent.js | 58 +++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/lib/rules/jsx-indent.js b/lib/rules/jsx-indent.js index 1ba0d75cdc..adcdaf910d 100644 --- a/lib/rules/jsx-indent.js +++ b/lib/rules/jsx-indent.js @@ -242,11 +242,23 @@ module.exports = { checkNodesIndent(node, peerElementIndent); } + function handleAttribute(node) { + if (node.value.type !== 'JSXExpressionContainer') { + return; + } + const nameIndent = getNodeIndent(node.name); + const lastToken = sourceCode.getLastToken(node.value); + const firstInLine = astUtil.getFirstNodeInLine(context, lastToken); + const indent = node.name.loc.start.line === firstInLine.loc.start.line ? 0 : nameIndent; + checkNodesIndent(firstInLine, indent); + } + return { JSXOpeningElement: handleOpeningElement, JSXOpeningFragment: handleOpeningElement, JSXClosingElement: handleClosingElement, JSXClosingFragment: handleClosingElement, + JSXAttribute: handleAttribute, JSXExpressionContainer: function(node) { if (!node.parent) { return; diff --git a/lib/util/ast.js b/lib/util/ast.js index 9af7e0c5ce..90d41a2d5b 100644 --- a/lib/util/ast.js +++ b/lib/util/ast.js @@ -68,13 +68,14 @@ function getComponentProperties(node) { } } + /** - * Checks if the node is the first in its line, excluding whitespace. + * Gets the first node in a line from the initial node, excluding whitespace. * @param {Object} context The node to check * @param {ASTNode} node The node to check - * @return {Boolean} true if it's the first node in its line + * @return {ASTNode} the first node in the line */ -function isNodeFirstInLine(context, node) { +function getFirstNodeInLine(context, node) { const sourceCode = context.getSourceCode(); let token = node; let lines; @@ -87,7 +88,17 @@ function isNodeFirstInLine(context, node) { token.type === 'JSXText' && /^\s*$/.test(lines[lines.length - 1]) ); + return token; +} +/** + * Checks if the node is the first in its line, excluding whitespace. + * @param {Object} context The node to check + * @param {ASTNode} node The node to check + * @return {Boolean} true if it's the first node in its line + */ +function isNodeFirstInLine(context, node) { + const token = getFirstNodeInLine(context, node); const startLine = node.loc.start.line; const endLine = token ? token.loc.end.line : -1; return startLine !== endLine; @@ -131,6 +142,7 @@ function isClass(node) { module.exports = { findReturnStatement: findReturnStatement, + getFirstNodeInLine: getFirstNodeInLine, getPropertyName: getPropertyName, getPropertyNameNode: getPropertyNameNode, getComponentProperties: getComponentProperties, diff --git a/tests/lib/rules/jsx-indent.js b/tests/lib/rules/jsx-indent.js index fc44dd4a5a..f66f3c668c 100644 --- a/tests/lib/rules/jsx-indent.js +++ b/tests/lib/rules/jsx-indent.js @@ -1478,5 +1478,63 @@ ruleTester.run('jsx-indent', rule, { errors: [ {message: 'Expected indentation of 4 space characters but found 2.'} ] + }, { + code: ` + const Component = () => ( + + )} + /> + ); + `, + output: ` + const Component = () => ( + + )} + /> + ); + `, + options: [2], + errors: [ + {message: 'Expected indentation of 8 space characters but found 4.'} + ] + }, { + code: ` +const Component = () => ( +\t +)} +\t/> +); + `, + output: ` +const Component = () => ( +\t +\t\t)} +\t/> +); + `, + options: ['tab'], + errors: [ + {message: 'Expected indentation of 2 tab characters but found 0.'} + ] }] }); From 9d74b8905b0bae1f23e061fcc6850705d5afa7fa Mon Sep 17 00:00:00 2001 From: Joshua Stiefer Date: Sat, 15 Dec 2018 14:15:07 -0700 Subject: [PATCH 2/4] Put jsx-indent attribute check behind an option --- lib/rules/jsx-indent.js | 11 +++- tests/lib/rules/jsx-indent.js | 108 +++++++++++++++++++++++++++++++++- 2 files changed, 116 insertions(+), 3 deletions(-) diff --git a/lib/rules/jsx-indent.js b/lib/rules/jsx-indent.js index adcdaf910d..87e4a86203 100644 --- a/lib/rules/jsx-indent.js +++ b/lib/rules/jsx-indent.js @@ -50,6 +50,14 @@ module.exports = { }, { type: 'integer' }] + }, { + type: 'object', + properties: { + checkAttributes: { + type: 'boolean' + } + }, + additionalProperties: false }] }, @@ -73,6 +81,7 @@ module.exports = { } const indentChar = indentType === 'space' ? ' ' : '\t'; + const checkAttributes = context.options[1] && context.options[1].checkAttributes || false; /** * Responsible for fixing the indentation issue fix @@ -243,7 +252,7 @@ module.exports = { } function handleAttribute(node) { - if (node.value.type !== 'JSXExpressionContainer') { + if (!checkAttributes || node.value.type !== 'JSXExpressionContainer') { return; } const nameIndent = getNodeIndent(node.name); diff --git a/tests/lib/rules/jsx-indent.js b/tests/lib/rules/jsx-indent.js index f66f3c668c..75584a32bf 100644 --- a/tests/lib/rules/jsx-indent.js +++ b/tests/lib/rules/jsx-indent.js @@ -716,6 +716,110 @@ ruleTester.run('jsx-indent', rule, { `, parser: 'babel-eslint', options: [2] + }, { + code: ` + const Component = () => ( + + )} + /> + ); + `, + output: ` + const Component = () => ( + + )} + /> + ); + `, + options: [2] + }, { + code: ` +const Component = () => ( +\t +)} +\t/> +); + `, + output: ` +const Component = () => ( +\t +\t\t)} +\t/> +); + `, + options: ['tab'] + }, { + code: ` + const Component = () => ( + + )} + /> + ); + `, + output: ` + const Component = () => ( + + )} + /> + ); + `, + options: [2, {checkAttributes: false}] + }, { + code: ` +const Component = () => ( +\t +)} +\t/> +); + `, + output: ` +const Component = () => ( +\t +\t\t)} +\t/> +); + `, + options: ['tab', {checkAttributes: false}] }], invalid: [{ @@ -1503,7 +1607,7 @@ ruleTester.run('jsx-indent', rule, { /> ); `, - options: [2], + options: [2, {checkAttributes: true}], errors: [ {message: 'Expected indentation of 8 space characters but found 4.'} ] @@ -1532,7 +1636,7 @@ const Component = () => ( \t/> ); `, - options: ['tab'], + options: ['tab', {checkAttributes: true}], errors: [ {message: 'Expected indentation of 2 tab characters but found 0.'} ] From 35025de4c44af85dd1adff44a1eddaa5e756dc73 Mon Sep 17 00:00:00 2001 From: Joshua Stiefer Date: Sat, 15 Dec 2018 14:23:43 -0700 Subject: [PATCH 3/4] Update jsx-indent documentation --- docs/rules/jsx-indent.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/rules/jsx-indent.md b/docs/rules/jsx-indent.md index 6f8b73df53..44bebb1fb7 100644 --- a/docs/rules/jsx-indent.md +++ b/docs/rules/jsx-indent.md @@ -31,10 +31,11 @@ The following patterns are considered warnings: ## Rule Options It takes an option as the second parameter which can be `"tab"` for tab-based indentation or a positive number for space indentations. +To enable checking the indentation of attributes, use the third parameter to turn on the `checkAttributes` option (default is false). ```js ... -"react/jsx-indent": [, 'tab'|] +"react/jsx-indent": [, 'tab'|, {checkAttributes: }] ... ``` @@ -52,6 +53,14 @@ The following patterns are considered warnings: + +// [2, 2, {checkAttributes: true}] +
hi
+} + /> +
``` The following patterns are **not** warnings: @@ -75,6 +84,14 @@ The following patterns are **not** warnings: + +// [2, 2, {checkAttributes: false}] +
hi
+} + /> +
``` ## When not to use From 6ddc708402fcd0c1c9e2a11c2872dc6d7f516ddb Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 15 Dec 2018 14:39:42 -0700 Subject: [PATCH 4/4] Update lib/rules/jsx-indent.js Co-Authored-By: jomasti --- lib/rules/jsx-indent.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/rules/jsx-indent.js b/lib/rules/jsx-indent.js index 87e4a86203..b79f724cba 100644 --- a/lib/rules/jsx-indent.js +++ b/lib/rules/jsx-indent.js @@ -81,7 +81,8 @@ module.exports = { } const indentChar = indentType === 'space' ? ' ' : '\t'; - const checkAttributes = context.options[1] && context.options[1].checkAttributes || false; + const options = context.options[1] || {}; + const checkAttributes = options.checkAttributes || false; /** * Responsible for fixing the indentation issue fix