Skip to content

Commit 1c95b83

Browse files
authored
feat: add checkUnscoped option to no-unused-keyframes, no-unused-selector, and require-selector-used-inside rules (#255)
* feat: add `checkUnscoped` option to `no-unused-keyframes`, `no-unused-selector`, and `require-selector-used-inside` rules * Create thirty-experts-raise.md
1 parent eca95b4 commit 1c95b83

10 files changed

+111
-21
lines changed

.changeset/thirty-experts-raise.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"eslint-plugin-vue-scoped-css": minor
3+
---
4+
5+
feat: add `checkUnscoped` option to `no-unused-keyframes`, `no-unused-selector`, and `require-selector-used-inside` rules

docs/rules/no-unused-keyframes.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,15 @@ This rule reports `@keyframes` is not used in Scoped CSS.
3636

3737
## :wrench: Options
3838

39-
Nothing.
39+
```json
40+
{
41+
"vue-scoped-css/no-unused-keyframes": ["error", {
42+
"checkUnscoped": false
43+
}]
44+
}
45+
```
46+
47+
- `checkUnscoped` ... The rule only checks `<style scoped>` by default, but if set to `true` it will also check `<style>` without the scoped attribute. If you set it to `true`, be very careful that the warned CSS may actually be used outside the `.vue` file.
4048

4149
## Implementation
4250

docs/rules/no-unused-selector.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,15 @@ This is a limitation of this rule. Without this limitation, the root element can
8989
{
9090
"vue-scoped-css/no-unused-selector": ["error", {
9191
"ignoreBEMModifier": false,
92-
"captureClassesFromDoc": []
92+
"captureClassesFromDoc": [],
93+
"checkUnscoped": false,
9394
}]
9495
}
9596
```
9697

9798
- `ignoreBEMModifier` ... Set `true` if you want to ignore the `BEM` modifier. Default is false.
9899
- `captureClassesFromDoc` ... Specifies the regexp that extracts the class name from the documentation in the comments. Even if there is no matching element, no error is reported if the document of a class name exists in the comments.
100+
- `checkUnscoped` ... The rule only checks `<style scoped>` by default, but if set to `true` it will also check `<style>` without the scoped attribute. If you set it to `true`, be very careful that the warned CSS may actually be used outside the `.vue` file.
99101

100102
### `"ignoreBEMModifier": true`
101103

docs/rules/require-selector-used-inside.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,15 @@ div {}
5454
{
5555
"vue-scoped-css/require-selector-used-inside": ["error", {
5656
"ignoreBEMModifier": false,
57-
"captureClassesFromDoc": []
57+
"captureClassesFromDoc": [],
58+
"checkUnscoped": false
5859
}]
5960
}
6061
```
6162

6263
- `ignoreBEMModifier` ... Set `true` if you want to ignore the `BEM` modifier. Default is false.
6364
- `captureClassesFromDoc` ... Specifies the regexp that extracts the class name from the documentation in the comments. Even if there is no matching element, no error is reported if the document of a class name exists in the comments.
65+
- `checkUnscoped` ... The rule only checks `<style scoped>` by default, but if set to `true` it will also check `<style>` without the scoped attribute. If you set it to `true`, be very careful that the warned CSS may actually be used outside the `.vue` file.
6466

6567
### `"ignoreBEMModifier": true`
6668

lib/rules/no-unused-keyframes.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,24 @@ module.exports = {
2424
messages: {
2525
unused: "The @keyframes `{{params}}` is unused.",
2626
},
27-
schema: [],
27+
schema: [
28+
{
29+
type: "object",
30+
properties: {
31+
checkUnscoped: {
32+
type: "boolean",
33+
},
34+
},
35+
additionalProperties: false,
36+
},
37+
],
2838
type: "suggestion", // "problem",
2939
},
3040
create(context: RuleContext) {
41+
const checkUnscoped = Boolean(context.options[0]?.checkUnscoped);
3142
const styles = getStyleContexts(context)
3243
.filter(isValidStyleContext)
33-
.filter((style) => style.scoped);
44+
.filter((style) => style.scoped || checkUnscoped);
3445
if (!styles.length) {
3546
return {};
3647
}

lib/rules/no-unused-selector.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ module.exports = {
124124
minItems: 0,
125125
uniqueItems: true,
126126
},
127+
checkUnscoped: {
128+
type: "boolean",
129+
},
127130
},
128131
additionalProperties: false,
129132
},
@@ -134,9 +137,10 @@ module.exports = {
134137
if (!hasTemplateBlock(context)) {
135138
return {};
136139
}
140+
const checkUnscoped = Boolean(context.options[0]?.checkUnscoped);
137141
const styles = getStyleContexts(context)
138142
.filter(isValidStyleContext)
139-
.filter((style) => style.scoped);
143+
.filter((style) => style.scoped || checkUnscoped);
140144
if (!styles.length) {
141145
return {};
142146
}

lib/rules/require-selector-used-inside.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ module.exports = {
102102
minItems: 0,
103103
uniqueItems: true,
104104
},
105+
checkUnscoped: {
106+
type: "boolean",
107+
},
105108
},
106109
additionalProperties: false,
107110
},
@@ -112,9 +115,10 @@ module.exports = {
112115
if (!hasTemplateBlock(context)) {
113116
return {};
114117
}
118+
const checkUnscoped = Boolean(context.options[0]?.checkUnscoped);
115119
const styles = getStyleContexts(context)
116120
.filter(isValidStyleContext)
117-
.filter((style) => style.scoped);
121+
.filter((style) => style.scoped || checkUnscoped);
118122
if (!styles.length) {
119123
return {};
120124
}

tests/lib/rules/no-unused-keyframes.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,16 @@ tester.run("no-unused-keyframes", rule as any, {
109109
}
110110
</style>
111111
`,
112+
`
113+
<template><a/></template>
114+
<style>
115+
.item {
116+
animation-name: slidein;
117+
}
118+
@keyframes unused {
119+
}
120+
</style>
121+
`,
112122
],
113123
invalid: [
114124
{
@@ -177,5 +187,25 @@ tester.run("no-unused-keyframes", rule as any, {
177187
},
178188
],
179189
},
190+
{
191+
code: `
192+
<template><a/></template>
193+
<style>
194+
.item {
195+
animation-name: slidein;
196+
}
197+
@keyframes unused {
198+
}
199+
</style>
200+
`,
201+
options: [{ checkUnscoped: true }],
202+
errors: [
203+
{
204+
message: "The @keyframes `unused` is unused.",
205+
line: 7,
206+
column: 18,
207+
},
208+
],
209+
},
180210
],
181211
});

tests/lib/rules/no-unused-selector.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -385,13 +385,13 @@ tester.run("no-unused-selector", rule as any, {
385385
`,
386386
// not scoped
387387
`
388-
<template>
389-
<div></div>
390-
</template>
391-
<style>
392-
input {}
393-
</style>
394-
`,
388+
<template>
389+
<div></div>
390+
</template>
391+
<style>
392+
input {}
393+
</style>
394+
`,
395395

396396
// deep
397397
`
@@ -1111,5 +1111,17 @@ tester.run("no-unused-selector", rule as any, {
11111111
`,
11121112
errors: ["The selector `.bar` is unused."],
11131113
},
1114+
{
1115+
code: `
1116+
<template>
1117+
<div></div>
1118+
</template>
1119+
<style>
1120+
input {}
1121+
</style>
1122+
`,
1123+
options: [{ checkUnscoped: true }],
1124+
errors: ["The selector `input` is unused."],
1125+
},
11141126
],
11151127
});

tests/lib/rules/require-selector-used-inside.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -313,13 +313,13 @@ tester.run("require-selector-used-inside", rule as any, {
313313
`,
314314
// not scoped
315315
`
316-
<template>
317-
<div></div>
318-
</template>
319-
<style>
320-
input {}
321-
</style>
322-
`,
316+
<template>
317+
<div></div>
318+
</template>
319+
<style>
320+
input {}
321+
</style>
322+
`,
323323

324324
// deep
325325
`
@@ -909,5 +909,17 @@ tester.run("require-selector-used-inside", rule as any, {
909909
"The selector `div>h3>` is unused in the template.",
910910
],
911911
},
912+
{
913+
code: `
914+
<template>
915+
<div></div>
916+
</template>
917+
<style>
918+
input {}
919+
</style>
920+
`,
921+
options: [{ checkUnscoped: true }],
922+
errors: ["The selector `input` is unused in the template."],
923+
},
912924
],
913925
});

0 commit comments

Comments
 (0)