Skip to content

Commit 6fe31ab

Browse files
authored
Improve autofix of prefer-class-directive (#101)
1 parent 9d922f3 commit 6fe31ab

File tree

10 files changed

+112
-6
lines changed

10 files changed

+112
-6
lines changed

docs-svelte-kit/src/lib/components/ESLintPlayground.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
5959
<button
6060
type=button
61-
class={current === 'foo' ? 'selected' : ''}
61+
class="{active ? 'active' : ''} {current === 'foo' ? 'selected' : ''}"
6262
on:click="{() => current = 'foo'}"
6363
>foo</button>
6464

src/rules/prefer-class-directive.ts

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { AST } from "svelte-eslint-parser"
22
import type * as ESTree from "estree"
33
import { createRule } from "../utils"
44
import { getStringIfConstant, needParentheses } from "../utils/ast-utils"
5+
import type { Rule } from "eslint"
56

67
export default createRule("prefer-class-directive", {
78
meta: {
@@ -217,7 +218,7 @@ export default createRule("prefer-class-directive", {
217218

218219
/** Report */
219220
function report(
220-
node: AST.SvelteMustacheTag,
221+
node: AST.SvelteMustacheTagText,
221222
map: Map<Expr, string>,
222223
attr: AST.SvelteAttribute,
223224
) {
@@ -237,10 +238,56 @@ export default createRule("prefer-class-directive", {
237238
space = className
238239
}
239240
}
240-
if (attr.value.length === 1) {
241+
242+
const fixesBuffer: Rule.Fix[] = []
243+
const index = attr.value.indexOf(node)
244+
const beforeAttrValues = attr.value.slice(0, index)
245+
const afterAttrValues = attr.value.slice(index + 1)
246+
let valueNode
247+
while ((valueNode = beforeAttrValues[beforeAttrValues.length - 1])) {
248+
if (valueNode.type === "SvelteLiteral") {
249+
if (!valueNode.value.trim()) {
250+
// Before spaces
251+
beforeAttrValues.pop()
252+
fixesBuffer.push(fixer.remove(valueNode))
253+
continue
254+
}
255+
if (valueNode.value.trimEnd() !== valueNode.value) {
256+
// Before spaces
257+
fixesBuffer.push(
258+
fixer.replaceText(valueNode, valueNode.value.trimEnd()),
259+
)
260+
}
261+
}
262+
break
263+
}
264+
while ((valueNode = afterAttrValues[0])) {
265+
if (valueNode.type === "SvelteLiteral") {
266+
if (!valueNode.value.trim()) {
267+
// After spaces
268+
afterAttrValues.shift()
269+
fixesBuffer.push(fixer.remove(valueNode))
270+
continue
271+
}
272+
if (valueNode.value.trimStart() !== valueNode.value) {
273+
// After spaces
274+
fixesBuffer.push(
275+
fixer.replaceText(valueNode, valueNode.value.trimStart()),
276+
)
277+
}
278+
}
279+
break
280+
}
281+
282+
if (!beforeAttrValues.length && !afterAttrValues.length) {
241283
yield fixer.replaceText(attr, classDirectives.join(" "))
242284
} else {
243-
yield fixer.replaceText(node, space)
285+
yield* fixesBuffer
286+
if (beforeAttrValues.length && afterAttrValues.length) {
287+
yield fixer.replaceText(node, space || " ")
288+
} else {
289+
yield fixer.remove(node)
290+
}
244291
yield fixer.insertTextAfterRange(
245292
[attr.range[1], attr.range[1]],
246293
` ${classDirectives.join(" ")}`,
@@ -252,7 +299,7 @@ export default createRule("prefer-class-directive", {
252299

253300
/** verify */
254301
function verify(
255-
node: AST.SvelteMustacheTag,
302+
node: AST.SvelteMustacheTagText,
256303
index: number,
257304
attr: AST.SvelteAttribute,
258305
) {

tests/fixtures/rules/prefer-class-directive/invalid/test01-input.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@
55
<button class={selected ? "selected" : ""}>foo</button>
66
<button class="a {selected ? 'selected' : ''} b">foo</button>
77
<button class="a{selected ? ' selected ' : ' '}b">foo</button>
8+
9+
<!-- test01-input.svelte -->

tests/fixtures/rules/prefer-class-directive/invalid/test01-output.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@
33
</script>
44

55
<button class:selected={selected}>foo</button>
6-
<button class="a b" class:selected={selected}>foo</button>
76
<button class="a b" class:selected={selected}>foo</button>
7+
<button class="a b" class:selected={selected}>foo</button>
8+
9+
<!-- test01-input.svelte -->
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[
2+
{
3+
"message": "Unexpected class using the ternary operator.",
4+
"line": 6,
5+
"column": 16
6+
},
7+
{
8+
"message": "Unexpected class using the ternary operator.",
9+
"line": 6,
10+
"column": 41
11+
}
12+
]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script>
2+
let current = "foo"
3+
let active = true
4+
</script>
5+
6+
<button class="{active ? 'active' : ''} {current === 'foo' ? 'selected' : ''}"
7+
>foo</button
8+
>
9+
10+
<!-- trim-test01-input.svelte -->
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script>
2+
let current = "foo"
3+
let active = true
4+
</script>
5+
6+
<button class="{current === 'foo' ? 'selected' : ''}" class:active={active}
7+
>foo</button
8+
>
9+
10+
<!-- trim-test01-input.svelte -->
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
{
3+
"message": "Unexpected class using the ternary operator.",
4+
"line": 6,
5+
"column": 15
6+
}
7+
]
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<script>
2+
let current = "foo"
3+
let active = true
4+
</script>
5+
6+
<button class={current === "foo" ? "selected" : ""} class:active>foo</button>
7+
8+
<!-- trim-test01.2-input.svelte -->
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<script>
2+
let current = "foo"
3+
let active = true
4+
</script>
5+
6+
<button class:selected={current === "foo"} class:active>foo</button>
7+
8+
<!-- trim-test01.2-input.svelte -->

0 commit comments

Comments
 (0)