Skip to content

Commit 3fe9713

Browse files
authored
Add vue-scoped-css/require-v-global-argument rule (#43)
1 parent a90c6b5 commit 3fe9713

File tree

6 files changed

+174
-0
lines changed

6 files changed

+174
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ Enforce all the rules in this category with:
104104
| [vue-scoped-css/no-unused-selector](https://future-architect.github.io/eslint-plugin-vue-scoped-css/rules/no-unused-selector.html) | Reports selectors defined in Scoped CSS not used in `<template>`. | |
105105
| [vue-scoped-css/require-scoped](https://future-architect.github.io/eslint-plugin-vue-scoped-css/rules/require-scoped.html) | Enforce the `<style>` tags to has the `scoped` attribute. | |
106106
| [vue-scoped-css/require-v-deep-argument](https://future-architect.github.io/eslint-plugin-vue-scoped-css/rules/require-v-deep-argument.html) | require selector argument to be passed to `::v-deep()`. | :wrench: |
107+
| [vue-scoped-css/require-v-global-argument](https://future-architect.github.io/eslint-plugin-vue-scoped-css/rules/require-v-global-argument.html) | require selector argument to be passed to `::v-global()`. | |
107108
| [vue-scoped-css/require-v-slotted-argument](https://future-architect.github.io/eslint-plugin-vue-scoped-css/rules/require-v-slotted-argument.html) | require selector argument to be passed to `::v-slotted()`. | |
108109

109110
## Recommended for Vue.js 2.x

docs/rules/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Enforce all the rules in this category with:
2424
| [vue-scoped-css/no-unused-selector](./no-unused-selector.md) | Reports selectors defined in Scoped CSS not used in `<template>`. | |
2525
| [vue-scoped-css/require-scoped](./require-scoped.md) | Enforce the `<style>` tags to has the `scoped` attribute. | |
2626
| [vue-scoped-css/require-v-deep-argument](./require-v-deep-argument.md) | require selector argument to be passed to `::v-deep()`. | :wrench: |
27+
| [vue-scoped-css/require-v-global-argument](./require-v-global-argument.md) | require selector argument to be passed to `::v-global()`. | |
2728
| [vue-scoped-css/require-v-slotted-argument](./require-v-slotted-argument.md) | require selector argument to be passed to `::v-slotted()`. | |
2829

2930
## Recommended for Vue.js 2.x
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
pageClass: "rule-details"
3+
sidebarDepth: 0
4+
title: "vue-scoped-css/require-v-global-argument"
5+
description: "require selector argument to be passed to `::v-global()`."
6+
---
7+
# vue-scoped-css/require-v-global-argument
8+
9+
> require selector argument to be passed to `::v-global()`.
10+
11+
- :gear: This rule is included in `"plugin:vue-scoped-css/vue3-recommended"` and `"plugin:vue-scoped-css/all"`.
12+
13+
## :book: Rule Details
14+
15+
This rule reports `::v-global` pseudo-element with no selector argument passed.
16+
17+
<eslint-code-block :rules="{'vue-scoped-css/require-v-global-argument': ['error']}">
18+
19+
```vue
20+
<style scoped>
21+
/* ✗ BAD */
22+
::v-global() {}
23+
::v-global {}
24+
25+
/* ✓ GOOD */
26+
::v-global(.foo .bar) {}
27+
</style>
28+
```
29+
30+
</eslint-code-block>
31+
32+
## :wrench: Options
33+
34+
Nothing.
35+
36+
## Implementation
37+
38+
- [Rule source](https://github.com/future-architect/eslint-plugin-vue-scoped-css/blob/master/lib/rules/require-v-global-argument.ts)
39+
- [Test source](https://github.com/future-architect/eslint-plugin-vue-scoped-css/blob/master/tests/lib/rules/require-v-global-argument.js)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import {
2+
getStyleContexts,
3+
getCommentDirectivesReporter,
4+
StyleContext,
5+
ValidStyleContext,
6+
} from "../styles/context"
7+
import type { RuleContext, Rule } from "../types"
8+
import {
9+
isPseudoEmptyArguments,
10+
VGlobalPseudo,
11+
isVGlobalPseudo,
12+
} from "../styles/utils/selectors"
13+
14+
declare const module: {
15+
exports: Rule
16+
}
17+
18+
module.exports = {
19+
meta: {
20+
docs: {
21+
description:
22+
"require selector argument to be passed to `::v-global()`.",
23+
categories: ["vue3-recommended"],
24+
default: "warn",
25+
url:
26+
"https://future-architect.github.io/eslint-plugin-vue-scoped-css/rules/require-v-global-argument.html",
27+
},
28+
fixable: null,
29+
messages: {
30+
missingArguments:
31+
"Need to pass argument to the `::v-global` pseudo-element.",
32+
},
33+
schema: [],
34+
type: "suggestion", // "problem",
35+
},
36+
create(context: RuleContext) {
37+
const styles = getStyleContexts(context)
38+
.filter(StyleContext.isValid)
39+
.filter((style) => style.scoped)
40+
if (!styles.length) {
41+
return {}
42+
}
43+
const reporter = getCommentDirectivesReporter(context)
44+
45+
/**
46+
* Reports the given node
47+
* @param {ASTNode} node node to report
48+
*/
49+
function report(node: VGlobalPseudo) {
50+
reporter.report({
51+
node,
52+
loc: node.loc,
53+
messageId: "missingArguments",
54+
})
55+
}
56+
57+
/**
58+
* Verify the style
59+
*/
60+
function verify(style: ValidStyleContext) {
61+
style.traverseSelectorNodes({
62+
enterNode(node) {
63+
if (isVGlobalPseudo(node) && isPseudoEmptyArguments(node)) {
64+
report(node)
65+
}
66+
},
67+
})
68+
}
69+
70+
return {
71+
"Program:exit"() {
72+
for (const style of styles) {
73+
verify(style)
74+
}
75+
},
76+
}
77+
},
78+
}

lib/utils/rules.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ const baseRules = [
3636
ruleName: "require-v-deep-argument",
3737
ruleId: "vue-scoped-css/require-v-deep-argument",
3838
},
39+
{
40+
rule: require("../rules/require-v-global-argument"),
41+
ruleName: "require-v-global-argument",
42+
ruleId: "vue-scoped-css/require-v-global-argument",
43+
},
3944
{
4045
rule: require("../rules/require-v-slotted-argument"),
4146
ruleName: "require-v-slotted-argument",
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { RuleTester } from "eslint"
2+
const rule = require("../../../lib/rules/require-v-global-argument")
3+
4+
const tester = new RuleTester({
5+
parser: require.resolve("vue-eslint-parser"),
6+
parserOptions: {
7+
ecmaVersion: 2019,
8+
sourceType: "module",
9+
},
10+
})
11+
12+
tester.run("require-v-global-argument", rule, {
13+
valid: [
14+
`
15+
<template><div class="item">sample</div></template>
16+
<style scoped>
17+
::v-global(.foo .bar) {}
18+
</style>
19+
`,
20+
],
21+
invalid: [
22+
{
23+
code: `
24+
<template><div class="item">sample</div></template>
25+
<style scoped>
26+
::v-global {}
27+
::v-global() {}
28+
</style>
29+
`,
30+
errors: [
31+
{
32+
message:
33+
"Need to pass argument to the `::v-global` pseudo-element.",
34+
line: 4,
35+
column: 13,
36+
endLine: 4,
37+
endColumn: 23,
38+
},
39+
{
40+
message:
41+
"Need to pass argument to the `::v-global` pseudo-element.",
42+
line: 5,
43+
column: 13,
44+
endLine: 5,
45+
endColumn: 25,
46+
},
47+
],
48+
},
49+
],
50+
})

0 commit comments

Comments
 (0)