Skip to content

Commit 345aaac

Browse files
mysticateamichalsnik
authored andcommitted
Fix: html-indent about binary expressions (fixes #264) (#281)
* Fix: html-indent about binary expressions (fixes #264) * update logic
1 parent e6593a5 commit 345aaac

File tree

2 files changed

+189
-14
lines changed

2 files changed

+189
-14
lines changed

lib/rules/html-indent.js

+56-1
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,55 @@ function create (context) {
407407
return template.getFirstToken(node)
408408
}
409409

410+
/**
411+
* Check whether a given token is the first token of:
412+
*
413+
* - ExpressionStatement
414+
* - VExpressionContainer
415+
* - A parameter of CallExpression/NewExpression
416+
* - An element of ArrayExpression
417+
* - An expression of SequenceExpression
418+
*
419+
* @param {Token} token The token to check.
420+
* @param {Node} belongingNode The node that the token is belonging to.
421+
* @returns {boolean} `true` if the token is the first token of an element.
422+
*/
423+
function isBeginningOfElement (token, belongingNode) {
424+
let node = belongingNode
425+
426+
while (node != null) {
427+
const parent = node.parent
428+
const t = parent && parent.type
429+
if (t != null && (t.endsWith('Statement') || t.endsWith('Declaration'))) {
430+
return parent.range[0] === token.range[0]
431+
}
432+
if (t === 'VExpressionContainer') {
433+
return node.range[0] === token.range[0]
434+
}
435+
if (t === 'CallExpression' || t === 'NewExpression') {
436+
const openParen = template.getTokenAfter(parent.callee, isNotRightParen)
437+
return parent.arguments.some(param =>
438+
getFirstAndLastTokens(param, openParen.range[1]).firstToken.range[0] === token.range[0]
439+
)
440+
}
441+
if (t === 'ArrayExpression') {
442+
return parent.elements.some(element =>
443+
element != null &&
444+
getFirstAndLastTokens(element).firstToken.range[0] === token.range[0]
445+
)
446+
}
447+
if (t === 'SequenceExpression') {
448+
return parent.expressions.some(expr =>
449+
getFirstAndLastTokens(expr).firstToken.range[0] === token.range[0]
450+
)
451+
}
452+
453+
node = parent
454+
}
455+
456+
return false
457+
}
458+
410459
/**
411460
* Ignore all tokens of the given node.
412461
* @param {Node} node The node to ignore.
@@ -752,8 +801,14 @@ function create (context) {
752801
const leftToken = getChainHeadToken(node)
753802
const opToken = template.getTokenAfter(node.left, isNotRightParen)
754803
const rightToken = template.getTokenAfter(opToken)
804+
const prevToken = template.getTokenBefore(leftToken)
805+
const shouldIndent = (
806+
prevToken == null ||
807+
prevToken.loc.end.line === leftToken.loc.start.line ||
808+
isBeginningOfElement(leftToken, node)
809+
)
755810

756-
setOffset([opToken, rightToken], 1, leftToken)
811+
setOffset([opToken, rightToken], shouldIndent ? 1 : 0, leftToken)
757812
},
758813

759814
'AwaitExpression, RestElement, SpreadElement, UnaryExpression' (node) {

tests/lib/rules/html-indent.js

+133-13
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,10 @@ tester.run('html-indent', rule, {
255255
a
256256
=
257257
b
258-
+
259-
c
260-
+
261-
d
258+
+
259+
c
260+
+
261+
d
262262
"
263263
></div>
264264
</template>
@@ -1347,7 +1347,127 @@ tester.run('html-indent', rule, {
13471347
// Ignore all :D
13481348
ignores: ['*']
13491349
}]
1350-
}
1350+
},
1351+
1352+
// https://github.com/vuejs/eslint-plugin-vue/issues/264
1353+
unIndent`
1354+
<template>
1355+
<div
1356+
:class="{
1357+
foo: (
1358+
a === b &&
1359+
c === d
1360+
)
1361+
}"
1362+
/>
1363+
</template>
1364+
`,
1365+
unIndent`
1366+
<template>
1367+
<div
1368+
:class="{
1369+
foo:
1370+
a === b &&
1371+
c === d
1372+
}"
1373+
/>
1374+
</template>
1375+
`,
1376+
unIndent`
1377+
<template>
1378+
<div
1379+
:class="{
1380+
foo: a === b &&
1381+
c === d
1382+
}"
1383+
/>
1384+
</template>
1385+
`,
1386+
unIndent`
1387+
<template>
1388+
<div
1389+
:class="
1390+
[
1391+
a
1392+
+
1393+
b,
1394+
c
1395+
+
1396+
d
1397+
]
1398+
"
1399+
/>
1400+
</template>
1401+
`,
1402+
unIndent`
1403+
<template>
1404+
<div
1405+
:class="
1406+
foo(
1407+
a
1408+
+
1409+
b,
1410+
c
1411+
+
1412+
d
1413+
)
1414+
"
1415+
/>
1416+
<div
1417+
:class="
1418+
new Foo(
1419+
a
1420+
+
1421+
b,
1422+
c
1423+
+
1424+
d
1425+
)
1426+
"
1427+
/>
1428+
</template>
1429+
`,
1430+
unIndent`
1431+
<template>
1432+
<div
1433+
:class="
1434+
a
1435+
+
1436+
b,
1437+
c
1438+
+
1439+
d
1440+
"
1441+
/>
1442+
</template>
1443+
`,
1444+
unIndent`
1445+
<template>
1446+
<div
1447+
:class="
1448+
foo(
1449+
a
1450+
+
1451+
b
1452+
)
1453+
"
1454+
/>
1455+
<div
1456+
:class="
1457+
foo(
1458+
(
1459+
a +
1460+
b
1461+
),
1462+
(
1463+
c +
1464+
d
1465+
)
1466+
)
1467+
"
1468+
/>
1469+
</template>
1470+
`
13511471
],
13521472

13531473
invalid: [
@@ -1819,10 +1939,10 @@ tester.run('html-indent', rule, {
18191939
a
18201940
=
18211941
b
1822-
+
1823-
c
1824-
+
1825-
d
1942+
+
1943+
c
1944+
+
1945+
d
18261946
"
18271947
></div>
18281948
</template>
@@ -1840,10 +1960,10 @@ tester.run('html-indent', rule, {
18401960
{ message: 'Expected indentation of 12 spaces but found 10 spaces.', line: 16 },
18411961
{ message: 'Expected indentation of 16 spaces but found 10 spaces.', line: 17 },
18421962
{ message: 'Expected indentation of 16 spaces but found 10 spaces.', line: 18 },
1843-
{ message: 'Expected indentation of 20 spaces but found 10 spaces.', line: 19 },
1844-
{ message: 'Expected indentation of 20 spaces but found 10 spaces.', line: 20 },
1845-
{ message: 'Expected indentation of 20 spaces but found 10 spaces.', line: 21 },
1846-
{ message: 'Expected indentation of 20 spaces but found 10 spaces.', line: 22 }
1963+
{ message: 'Expected indentation of 16 spaces but found 10 spaces.', line: 19 },
1964+
{ message: 'Expected indentation of 16 spaces but found 10 spaces.', line: 20 },
1965+
{ message: 'Expected indentation of 16 spaces but found 10 spaces.', line: 21 },
1966+
{ message: 'Expected indentation of 16 spaces but found 10 spaces.', line: 22 }
18471967
]
18481968
},
18491969

0 commit comments

Comments
 (0)