diff --git a/lib/rules/component-name-in-template-casing.js b/lib/rules/component-name-in-template-casing.js
index df06a0b1c..b457ffa61 100644
--- a/lib/rules/component-name-in-template-casing.js
+++ b/lib/rules/component-name-in-template-casing.js
@@ -11,6 +11,30 @@ const { toRegExp } = require('../utils/regexp')
const allowedCaseOptions = ['PascalCase', 'kebab-case']
const defaultCase = 'PascalCase'
+/**
+ * Checks whether the given variable is the type-only import object.
+ * @param {Variable} variable
+ * @returns {boolean} `true` if the given variable is the type-only import.
+ */
+function isTypeOnlyImport(variable) {
+ if (variable.defs.length === 0) return false
+
+ return variable.defs.every((def) => {
+ if (def.type !== 'ImportBinding') {
+ return false
+ }
+ if (def.parent.importKind === 'type') {
+ // check for `import type Foo from './xxx'`
+ return true
+ }
+ if (def.node.type === 'ImportSpecifier' && def.node.importKind === 'type') {
+ // check for `import { type Foo } from './xxx'`
+ return true
+ }
+ return false
+ })
+}
+
module.exports = {
meta: {
type: 'suggestion',
@@ -75,10 +99,13 @@ module.exports = {
(scope) => scope.type === 'module'
)
for (const variable of (moduleScope && moduleScope.variables) || []) {
- registeredComponents.add(variable.name)
+ if (!isTypeOnlyImport(variable)) {
+ registeredComponents.add(variable.name)
+ }
}
}
}
+
/**
* Checks whether the given node is the verification target node.
* @param {VElement} node element node
diff --git a/tests/lib/rules/component-name-in-template-casing.js b/tests/lib/rules/component-name-in-template-casing.js
index d57a5ffbf..7b3f012c8 100644
--- a/tests/lib/rules/component-name-in-template-casing.js
+++ b/tests/lib/rules/component-name-in-template-casing.js
@@ -4,6 +4,7 @@
'use strict'
const rule = require('../../../lib/rules/component-name-in-template-casing')
+const semver = require('semver')
const RuleTester = require('eslint').RuleTester
const tester = new RuleTester({
@@ -193,7 +194,43 @@ tester.run('component-name-in-template-casing', rule, {
`,
options: ['kebab-case', { globals: ['RouterView', 'router-link'] }]
- }
+ },
+
+ // type-only imports
+ ...(semver.gte(
+ require('@typescript-eslint/parser/package.json').version,
+ '5.0.0'
+ )
+ ? [
+ {
+ code: `
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ options: ['PascalCase', { registeredComponentsOnly: true }],
+ parserOptions: {
+ parser: require.resolve('@typescript-eslint/parser')
+ }
+ }
+ ]
+ : [])
],
invalid: [
{
@@ -939,6 +976,99 @@ tester.run('component-name-in-template-casing', rule, {
column: 11
}
]
- }
+ },
+ // type-only imports
+ ...(semver.gte(
+ require('@typescript-eslint/parser/package.json').version,
+ '5.0.0'
+ )
+ ? [
+ {
+ code: `
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ options: ['PascalCase', { registeredComponentsOnly: false }],
+ parserOptions: {
+ parser: require.resolve('@typescript-eslint/parser')
+ },
+ output: `
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ errors: [
+ {
+ message: 'Component name "foo" is not PascalCase.',
+ line: 13,
+ column: 17
+ },
+ {
+ message: 'Component name "hello-world1" is not PascalCase.',
+ line: 14,
+ column: 17
+ },
+ {
+ message: 'Component name "hello-world2" is not PascalCase.',
+ line: 15,
+ column: 17
+ },
+ {
+ message: 'Component name "hello-world3" is not PascalCase.',
+ line: 16,
+ column: 17
+ },
+ {
+ message: 'Component name "hello-world4" is not PascalCase.',
+ line: 17,
+ column: 17
+ },
+ {
+ message: 'Component name "hello-world5" is not PascalCase.',
+ line: 18,
+ column: 17
+ },
+ {
+ message: 'Component name "component" is not PascalCase.',
+ line: 19,
+ column: 17
+ }
+ ]
+ }
+ ]
+ : [])
]
})