From 02970ac88d74e66f82194d7e38c9c2e973e0ba5d Mon Sep 17 00:00:00 2001 From: Toru Nagashima Date: Mon, 4 Dec 2017 20:04:59 +0900 Subject: [PATCH 1/2] Fix: html-indent about binary expressions (fixes #264) --- lib/rules/html-indent.js | 35 +++++++++++++++++-- tests/lib/rules/html-indent.js | 61 ++++++++++++++++++++++++++-------- 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/lib/rules/html-indent.js b/lib/rules/html-indent.js index b4a41d572..63ab8d038 100644 --- a/lib/rules/html-indent.js +++ b/lib/rules/html-indent.js @@ -387,6 +387,31 @@ function create (context) { return template.getFirstToken(node) } + /** + * Check whether a given token is the first token of a statement. + * @param {Token} token The token to check. + * @param {Node} belongingNode The node that the token is belonging to. + * @returns {boolean} `true` if the token is the first token of a statement. + */ + function isFirstOfStatement (token, belongingNode) { + let node = belongingNode + + while (node != null) { + const parent = node.parent + const t = parent && parent.type + if (t != null && (t.endsWith('Statement') || t.endsWith('Declaration'))) { + return parent.range[0] === token.range[0] + } + if (t === 'VExpressionContainer') { + return node.range[0] === token.range[0] + } + + node = parent + } + + return false + } + /** * Ignore all tokens of the given node. * @param {Node} node The node to ignore. @@ -722,8 +747,14 @@ function create (context) { const leftToken = getChainHeadToken(node) const opToken = template.getTokenAfter(node.left, isNotRightParen) const rightToken = template.getTokenAfter(opToken) - - setOffset([opToken, rightToken], 1, leftToken) + const prevToken = template.getTokenBefore(leftToken) + const shouldIndent = ( + prevToken == null || + prevToken.loc.end.line === leftToken.loc.start.line || + isFirstOfStatement(leftToken, node) + ) + + setOffset([opToken, rightToken], shouldIndent ? 1 : 0, leftToken) }, 'AwaitExpression, RestElement, SpreadElement, UnaryExpression' (node) { diff --git a/tests/lib/rules/html-indent.js b/tests/lib/rules/html-indent.js index a426dbf97..dee4511e4 100644 --- a/tests/lib/rules/html-indent.js +++ b/tests/lib/rules/html-indent.js @@ -255,10 +255,10 @@ tester.run('html-indent', rule, { a = b - + - c - + - d + + + c + + + d " > @@ -1307,7 +1307,42 @@ tester.run('html-indent', rule, { // Ignore all :D ignores: ['*'] }] - } + }, + + // https://github.com/vuejs/eslint-plugin-vue/issues/264 + unIndent` + + `, + unIndent` + + `, + unIndent` + + ` ], invalid: [ @@ -1779,10 +1814,10 @@ tester.run('html-indent', rule, { a = b - + - c - + - d + + + c + + + d " > @@ -1800,10 +1835,10 @@ tester.run('html-indent', rule, { { message: 'Expected indentation of 12 spaces but found 10 spaces.', line: 16 }, { message: 'Expected indentation of 16 spaces but found 10 spaces.', line: 17 }, { message: 'Expected indentation of 16 spaces but found 10 spaces.', line: 18 }, - { message: 'Expected indentation of 20 spaces but found 10 spaces.', line: 19 }, - { message: 'Expected indentation of 20 spaces but found 10 spaces.', line: 20 }, - { message: 'Expected indentation of 20 spaces but found 10 spaces.', line: 21 }, - { message: 'Expected indentation of 20 spaces but found 10 spaces.', line: 22 } + { message: 'Expected indentation of 16 spaces but found 10 spaces.', line: 19 }, + { message: 'Expected indentation of 16 spaces but found 10 spaces.', line: 20 }, + { message: 'Expected indentation of 16 spaces but found 10 spaces.', line: 21 }, + { message: 'Expected indentation of 16 spaces but found 10 spaces.', line: 22 } ] }, From b67c107aaa0b7732edbaf16842e17b0cd786fd4f Mon Sep 17 00:00:00 2001 From: Toru Nagashima Date: Thu, 7 Dec 2017 21:23:21 +0900 Subject: [PATCH 2/2] update logic --- lib/rules/html-indent.js | 32 +++++++++++-- tests/lib/rules/html-indent.js | 85 ++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 4 deletions(-) diff --git a/lib/rules/html-indent.js b/lib/rules/html-indent.js index 63ab8d038..f0fdd2491 100644 --- a/lib/rules/html-indent.js +++ b/lib/rules/html-indent.js @@ -388,12 +388,19 @@ function create (context) { } /** - * Check whether a given token is the first token of a statement. + * Check whether a given token is the first token of: + * + * - ExpressionStatement + * - VExpressionContainer + * - A parameter of CallExpression/NewExpression + * - An element of ArrayExpression + * - An expression of SequenceExpression + * * @param {Token} token The token to check. * @param {Node} belongingNode The node that the token is belonging to. - * @returns {boolean} `true` if the token is the first token of a statement. + * @returns {boolean} `true` if the token is the first token of an element. */ - function isFirstOfStatement (token, belongingNode) { + function isBeginningOfElement (token, belongingNode) { let node = belongingNode while (node != null) { @@ -405,6 +412,23 @@ function create (context) { if (t === 'VExpressionContainer') { return node.range[0] === token.range[0] } + if (t === 'CallExpression' || t === 'NewExpression') { + const openParen = template.getTokenAfter(parent.callee, isNotRightParen) + return parent.arguments.some(param => + getFirstAndLastTokens(param, openParen.range[1]).firstToken.range[0] === token.range[0] + ) + } + if (t === 'ArrayExpression') { + return parent.elements.some(element => + element != null && + getFirstAndLastTokens(element).firstToken.range[0] === token.range[0] + ) + } + if (t === 'SequenceExpression') { + return parent.expressions.some(expr => + getFirstAndLastTokens(expr).firstToken.range[0] === token.range[0] + ) + } node = parent } @@ -751,7 +775,7 @@ function create (context) { const shouldIndent = ( prevToken == null || prevToken.loc.end.line === leftToken.loc.start.line || - isFirstOfStatement(leftToken, node) + isBeginningOfElement(leftToken, node) ) setOffset([opToken, rightToken], shouldIndent ? 1 : 0, leftToken) diff --git a/tests/lib/rules/html-indent.js b/tests/lib/rules/html-indent.js index dee4511e4..40c30ee59 100644 --- a/tests/lib/rules/html-indent.js +++ b/tests/lib/rules/html-indent.js @@ -1342,6 +1342,91 @@ tester.run('html-indent', rule, { }" /> + `, + unIndent` + + `, + unIndent` + + `, + unIndent` + + `, + unIndent` + ` ],