Skip to content

Commit d48f644

Browse files
committed
feat: Add prefer option to prefer-class-directive
This the prefer option can be 'empty' or 'always' with 'empty' being the default. 'always' matches the current behaviour, always insisting on directives 'empty' only prefers directives when one class is empty.
1 parent 0e9ba36 commit d48f644

File tree

6 files changed

+52
-3
lines changed

6 files changed

+52
-3
lines changed

docs/rules/prefer-class-directive.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ This rule aims to replace a class with ternary operator with the class directive
2222

2323
```svelte
2424
<script>
25-
/* eslint svelte/prefer-class-directive: "error" */
25+
/* eslint svelte/prefer-class-directive: "empty" */
26+
const selected = true;
2627
</script>
2728
2829
<!-- ✓ GOOD -->
30+
<button class:selected={selected}>foo</button>
2931
<button class:selected={current === 'foo'}>foo</button>
3032
3133
<!-- ✗ BAD -->
34+
<button class={selected ? 'selected' : ''}>foo</button>
3235
<button class={current === 'foo' ? 'selected' : ''}>foo</button>
3336
```
3437

@@ -40,7 +43,20 @@ You cannot enforce this style by using [prettier-plugin-svelte]. That is, this r
4043

4144
## :wrench: Options
4245

43-
Nothing.
46+
```json
47+
{
48+
"svelte/html-quotes": [
49+
"error",
50+
{
51+
"prefer": "empty" // or "always"
52+
}
53+
]
54+
}
55+
```
56+
57+
- `prefer` ... Whether to apply this rule always or just when there's an empty string. Default is `"empty"`.
58+
- `"empty"` ... Requires class directives only if one of the strings is empty.
59+
- `"always"` ... Requires class directives always rather than interpolation.
4460

4561
## :couple: Related Rules
4662

src/rules/prefer-class-directive.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,23 @@ export default createRule('prefer-class-directive', {
1414
conflictWithPrettier: false
1515
},
1616
fixable: 'code',
17-
schema: [],
17+
schema: [
18+
{
19+
type: 'object',
20+
properties: {
21+
prefer: { enum: ['always', 'empty'] }
22+
},
23+
additionalProperties: false
24+
}
25+
],
1826
messages: {
1927
unexpected: 'Unexpected class using the ternary operator.'
2028
},
2129
type: 'suggestion'
2230
},
2331
create(context) {
2432
const sourceCode = getSourceCode(context);
33+
const preferEmpty = context.options[0]?.prefer !== 'always';
2534

2635
type Expr = {
2736
not?: true;
@@ -301,6 +310,7 @@ export default createRule('prefer-class-directive', {
301310
const prevIsWord = !startsWithNonWord(attr, index + 1);
302311
const nextIsWord = !endsWithNonWord(attr, index - 1);
303312
let canTransform = true;
313+
let foundEmpty = false;
304314
for (const className of map.values()) {
305315
if (className) {
306316
if (!/^[\w-]*$/u.test(className.trim())) {
@@ -317,13 +327,17 @@ export default createRule('prefer-class-directive', {
317327
break;
318328
}
319329
} else {
330+
foundEmpty = true;
320331
if (prevIsWord && nextIsWord) {
321332
// The previous and next may be connected.
322333
canTransform = false;
323334
break;
324335
}
325336
}
326337
}
338+
if (preferEmpty && !foundEmpty) {
339+
return;
340+
}
327341
if (!canTransform) {
328342
return;
329343
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"options": [{ "prefer": "always" }]
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"options": [{ "prefer": "always" }]
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"options": [{ "prefer": "empty" }]
3+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script>
2+
let a = true;
3+
let a7 = 7;
4+
let danger = false;
5+
</script>
6+
7+
<button class="{a ? 'a' : 'b'}">foo</button>
8+
<button class="{!a ? 'b' : 'a'}">foo</button>
9+
<button class="{a7 === 7 ? 'a' : 'b'}">foo</button>
10+
<button class="btn {danger ? 'btn-danger' : 'btn-primary'}">foo</button>

0 commit comments

Comments
 (0)