diff --git a/lib/rules/html-indent.js b/lib/rules/html-indent.js
index b4a41d572..412d9779f 100644
--- a/lib/rules/html-indent.js
+++ b/lib/rules/html-indent.js
@@ -198,6 +198,26 @@ function isBeginningOfLine (node, index, nodes) {
return false
}
+/**
+ * Check whether a given token is a closing token which triggers unindent.
+ * @param {Token} token The token to check.
+ * @returns {boolean} `true` if the token is a closing token.
+ */
+function isClosingToken (token) {
+ return token != null && (
+ token.type === 'HTMLEndTagOpen' ||
+ token.type === 'VExpressionEnd' ||
+ (
+ token.type === 'Punctuator' &&
+ (
+ token.value === ')' ||
+ token.value === '}' ||
+ token.value === ']'
+ )
+ )
+ )
+}
+
/**
* Creates AST event handlers for html-indent.
*
@@ -504,9 +524,10 @@ function create (context) {
* Validate the given token with the pre-calculated expected indentation.
* @param {Token} token The token to validate.
* @param {number} expectedIndent The expected indentation.
+ * @param {number|undefined} optionalExpectedIndent The optional expected indentation.
* @returns {void}
*/
- function validateCore (token, expectedIndent) {
+ function validateCore (token, expectedIndent, optionalExpectedIndent) {
const line = token.loc.start.line
const actualIndent = token.loc.start.column
const indentText = getIndentText(token)
@@ -530,7 +551,7 @@ function create (context) {
}
}
- if (actualIndent !== expectedIndent) {
+ if (actualIndent !== expectedIndent && (optionalExpectedIndent === undefined || actualIndent !== optionalExpectedIndent)) {
context.report({
loc: {
start: { line, column: 0 },
@@ -553,9 +574,10 @@ function create (context) {
* Validate indentation of the line that the given tokens are on.
* @param {Token[]} tokens The tokens on the same line to validate.
* @param {Token[]} comments The comments which are on the immediately previous lines of the tokens.
+ * @param {Token|null} lastToken The last validated token. Comments can adjust to the token.
* @returns {void}
*/
- function validate (tokens, comments) {
+ function validate (tokens, comments, lastToken) {
// Calculate and save expected indentation.
const firstToken = tokens[0]
const actualIndent = firstToken.loc.start.column
@@ -604,9 +626,17 @@ function create (context) {
}
}
+ // Calculate the expected indents for comments.
+ // It allows the same indent level with the previous line.
+ const lastOffsetInfo = offsets.get(lastToken)
+ const lastExpectedIndent = lastOffsetInfo && lastOffsetInfo.expectedIndent
+ const commentExpectedIndents = (typeof lastExpectedIndent === 'number' && isClosingToken(firstToken))
+ ? { primary: lastExpectedIndent, secondary: expectedIndent }
+ : { primary: expectedIndent, secondary: undefined }
+
// Validate.
for (const comment of comments) {
- validateCore(comment, expectedIndent)
+ validateCore(comment, commentExpectedIndents.primary, commentExpectedIndents.secondary)
}
validateCore(firstToken, expectedIndent)
}
@@ -1142,6 +1172,7 @@ function create (context) {
let tokensOnSameLine = []
let isBesideMultilineToken = false
let first = true
+ let lastValidatedToken = null
// Validate indentation of tokens.
for (const token of template.getTokens(node, { includeComments: true, filter: isNotWhitespace })) {
@@ -1168,7 +1199,8 @@ function create (context) {
}
}
- validate(tokensOnSameLine, comments)
+ validate(tokensOnSameLine, comments, lastValidatedToken)
+ lastValidatedToken = tokensOnSameLine[0]
}
isBesideMultilineToken = last(tokensOnSameLine).loc.end.line === token.loc.start.line
tokensOnSameLine = [token]
@@ -1176,7 +1208,7 @@ function create (context) {
}
}
if (tokensOnSameLine.length >= 1 && tokensOnSameLine.some(isNotComment)) {
- validate(tokensOnSameLine, comments)
+ validate(tokensOnSameLine, comments, lastValidatedToken)
}
}
}))
diff --git a/tests/lib/rules/html-indent.js b/tests/lib/rules/html-indent.js
index a426dbf97..4998eb1d6 100644
--- a/tests/lib/rules/html-indent.js
+++ b/tests/lib/rules/html-indent.js
@@ -1290,6 +1290,46 @@ tester.run('html-indent', rule, {
}}
`,
+ unIndent`
+
+ {{
+ message
+ // comment
+ // comment
+ }}
+
+
+ `,
+ unIndent`
+
+ {{
+ message
+ /*
+ * comment
+ */
+ }}
+
+ `,
+ unIndent`
+
+ {{
+ message
+ // comment
+ // comment
+ }}
+
+
+ `,
+ unIndent`
+
+ {{
+ message
+ /*
+ * comment
+ */
+ }}
+
+ `,
// Ignores
{
@@ -4246,6 +4286,63 @@ tester.run('html-indent', rule, {
{ message: 'Expected indentation of 4 spaces but found 2 spaces.', line: 6 }
]
},
+ {
+ code: unIndent`
+
+ {{
+ message
+ // comment
+ // comment
+ }}
+
+
+ `,
+ output: unIndent`
+
+ {{
+ message
+ // comment
+ // comment
+ }}
+
+
+ `,
+ errors: [
+ { message: 'Expected indentation of 2 spaces but found 0 spaces.', line: 2 },
+ { message: 'Expected indentation of 4 spaces but found 0 spaces.', line: 3 },
+ { message: 'Expected indentation of 4 spaces but found 0 spaces.', line: 4 },
+ { message: 'Expected indentation of 4 spaces but found 0 spaces.', line: 5 },
+ { message: 'Expected indentation of 2 spaces but found 0 spaces.', line: 6 }
+ ]
+ },
+ {
+ code: unIndent`
+
+ {{
+ message
+ /*
+ * comment
+ */
+ }}
+
+ `,
+ output: unIndent`
+
+ {{
+ message
+ /*
+ * comment
+ */
+ }}
+
+ `,
+ errors: [
+ { message: 'Expected indentation of 2 spaces but found 0 spaces.', line: 2 },
+ { message: 'Expected indentation of 4 spaces but found 0 spaces.', line: 3 },
+ { message: 'Expected indentation of 4 spaces but found 0 spaces.', line: 4 },
+ { message: 'Expected indentation of 2 spaces but found 0 spaces.', line: 7 }
+ ]
+ },
// Ignores
{