Skip to content

Commit abcb642

Browse files
authored
Add globals option to component-name-in-template-casing (#1989)
1 parent 4d79ceb commit abcb642

File tree

3 files changed

+111
-10
lines changed

3 files changed

+111
-10
lines changed

docs/rules/component-name-in-template-casing.md

+17
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ This rule aims to warn the tag names other than the configured casing in Vue.js
3333
- `registeredComponentsOnly` ... If `true`, only registered components (in PascalCase) are checked. If `false`, check all.
3434
default `true`
3535
- `ignores` (`string[]`) ... The element names to ignore. Sets the element name to allow. For example, custom elements or Vue components with special name. You can set the regexp by writing it like `"/^name/"`.
36+
- `globals` (`string[]`) ... Globally registered component names to check. For example, `RouterView` and `RouterLink` are globally registered by `vue-router` and can't be detected as registered in a SFC file.
3637

3738
### `"PascalCase", { registeredComponentsOnly: true }` (default)
3839

@@ -141,6 +142,22 @@ export default {
141142

142143
</eslint-code-block>
143144

145+
### `"PascalCase", { globals: ["RouterView"] }`
146+
147+
<eslint-code-block fix :rules="{'vue/component-name-in-template-casing': ['error', 'PascalCase', {globals: ['RouterView']}]}">
148+
149+
```vue
150+
<template>
151+
<!-- ✓ GOOD -->
152+
<RouterView></RouterView>
153+
154+
<!-- ✗ BAD -->
155+
<router-view></router-view>
156+
</template>
157+
```
158+
159+
</eslint-code-block>
160+
144161
## :books: Further Reading
145162

146163
- [Style guide - Component name casing in templates](https://vuejs.org/style-guide/rules-strongly-recommended.html#component-name-casing-in-templates)

lib/rules/component-name-in-template-casing.js

+10-10
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ module.exports = {
4040
{
4141
type: 'object',
4242
properties: {
43+
globals: {
44+
type: 'array',
45+
items: { type: 'string' },
46+
uniqueItems: true
47+
},
4348
ignores: {
4449
type: 'array',
4550
items: { type: 'string' },
@@ -63,13 +68,15 @@ module.exports = {
6368
: defaultCase
6469
/** @type {RegExp[]} */
6570
const ignores = (options.ignores || []).map(toRegExp)
71+
/** @type {string[]} */
72+
const globals = (options.globals || []).map(casing.pascalCase)
6673
const registeredComponentsOnly = options.registeredComponentsOnly !== false
6774
const tokens =
6875
context.parserServices.getTemplateBodyTokenStore &&
6976
context.parserServices.getTemplateBodyTokenStore()
7077

7178
/** @type { Set<string> } */
72-
const registeredComponents = new Set()
79+
const registeredComponents = new Set(globals)
7380

7481
if (utils.isScriptSetup(context)) {
7582
// For <script setup>
@@ -106,15 +113,8 @@ module.exports = {
106113
}
107114
return true
108115
}
109-
// We only verify the components registered in the component.
110-
if (
111-
[...registeredComponents]
112-
.filter((name) => casing.isPascalCase(name)) // When defining a component with PascalCase, you can use either case
113-
.some(
114-
(name) =>
115-
node.rawName === name || casing.pascalCase(node.rawName) === name
116-
)
117-
) {
116+
// We only verify the registered components.
117+
if (registeredComponents.has(casing.pascalCase(node.rawName))) {
118118
return true
119119
}
120120

tests/lib/rules/component-name-in-template-casing.js

+84
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,30 @@ tester.run('component-name-in-template-casing', rule, {
168168
<keep-alive />
169169
</template>
170170
`
171+
},
172+
173+
// globals
174+
{
175+
code: `
176+
<template>
177+
<div>
178+
<RouterView />
179+
<RouterLink />
180+
</div>
181+
</template>
182+
`,
183+
options: ['PascalCase', { globals: ['RouterView', 'router-link'] }]
184+
},
185+
{
186+
code: `
187+
<template>
188+
<div>
189+
<router-view />
190+
<router-link />
191+
</div>
192+
</template>
193+
`,
194+
options: ['kebab-case', { globals: ['RouterView', 'router-link'] }]
171195
}
172196
],
173197
invalid: [
@@ -854,6 +878,66 @@ tester.run('component-name-in-template-casing', rule, {
854878
</script>
855879
`,
856880
errors: ['Component name "TheComponent" is not kebab-case.']
881+
},
882+
{
883+
code: `
884+
<template>
885+
<router-view />
886+
</template>
887+
`,
888+
options: ['PascalCase', { globals: ['RouterView'] }],
889+
output: `
890+
<template>
891+
<RouterView />
892+
</template>
893+
`,
894+
errors: [
895+
{
896+
message: 'Component name "router-view" is not PascalCase.',
897+
line: 3,
898+
column: 11
899+
}
900+
]
901+
},
902+
{
903+
code: `
904+
<template>
905+
<RouterView />
906+
</template>
907+
`,
908+
options: ['kebab-case', { globals: ['RouterView'] }],
909+
output: `
910+
<template>
911+
<router-view />
912+
</template>
913+
`,
914+
errors: [
915+
{
916+
message: 'Component name "RouterView" is not kebab-case.',
917+
line: 3,
918+
column: 11
919+
}
920+
]
921+
},
922+
{
923+
code: `
924+
<template>
925+
<RouterView />
926+
</template>
927+
`,
928+
options: ['kebab-case', { globals: ['router-view'] }],
929+
output: `
930+
<template>
931+
<router-view />
932+
</template>
933+
`,
934+
errors: [
935+
{
936+
message: 'Component name "RouterView" is not kebab-case.',
937+
line: 3,
938+
column: 11
939+
}
940+
]
857941
}
858942
]
859943
})

0 commit comments

Comments
 (0)