diff --git a/.changeset/rude-heads-serve.md b/.changeset/rude-heads-serve.md new file mode 100644 index 000000000..861605ed7 --- /dev/null +++ b/.changeset/rude-heads-serve.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-vue': minor +--- + +Changed `vue/component-name-in-template-casing` `globals` option to support regex patterns diff --git a/docs/rules/component-name-in-template-casing.md b/docs/rules/component-name-in-template-casing.md index dd59d40e4..cc5a4256a 100644 --- a/docs/rules/component-name-in-template-casing.md +++ b/docs/rules/component-name-in-template-casing.md @@ -34,7 +34,7 @@ This rule aims to warn the tag names other than the configured casing in Vue.js - `registeredComponentsOnly` ... If `true`, only registered components (in PascalCase) are checked. If `false`, check all. default `true` - `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/"`. -- `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. +- `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. You can set the regexp by writing it like `"/^c-/"` to match component names with patterns. ### `"PascalCase", { registeredComponentsOnly: true }` (default) @@ -143,17 +143,23 @@ export default { -### `"PascalCase", { globals: ["RouterView"] }` +### `"PascalCase", { globals: ["RouterView", "/^c-/"] }` - + ```vue ``` diff --git a/lib/rules/component-name-in-template-casing.js b/lib/rules/component-name-in-template-casing.js index c7267cd49..fe3fd5ff8 100644 --- a/lib/rules/component-name-in-template-casing.js +++ b/lib/rules/component-name-in-template-casing.js @@ -6,7 +6,7 @@ const utils = require('../utils') const casing = require('../utils/casing') -const { toRegExpGroupMatcher } = require('../utils/regexp') +const { toRegExpGroupMatcher, isRegExp } = require('../utils/regexp') const allowedCaseOptions = ['PascalCase', 'kebab-case'] const defaultCase = 'PascalCase' @@ -82,8 +82,18 @@ module.exports = { ? caseOption : defaultCase const isIgnored = toRegExpGroupMatcher(options.ignores) - /** @type {string[]} */ - const globals = (options.globals || []).map(casing.pascalCase) + + const globalStrings = [] + const globalPatterns = [] + for (const global of options.globals || []) { + if (isRegExp(global)) { + globalPatterns.push(global) + } else { + globalStrings.push(global) + } + } + + const isGlobalPattern = toRegExpGroupMatcher(globalPatterns) const registeredComponentsOnly = options.registeredComponentsOnly !== false const sourceCode = context.getSourceCode() const tokens = @@ -91,7 +101,7 @@ module.exports = { sourceCode.parserServices.getTemplateBodyTokenStore() /** @type { Set } */ - const registeredComponents = new Set(globals) + const registeredComponents = new Set(globalStrings.map(casing.pascalCase)) if (utils.isScriptSetup(context)) { // For setup> @@ -137,8 +147,10 @@ module.exports = { return true } - // We only verify the registered components. - return registeredComponents.has(casing.pascalCase(node.rawName)) + return ( + registeredComponents.has(casing.pascalCase(node.rawName)) || + isGlobalPattern(node.rawName) + ) } let hasInvalidEOF = false diff --git a/tests/lib/rules/component-name-in-template-casing.js b/tests/lib/rules/component-name-in-template-casing.js index 02ab287f6..34e3574fc 100644 --- a/tests/lib/rules/component-name-in-template-casing.js +++ b/tests/lib/rules/component-name-in-template-casing.js @@ -202,6 +202,21 @@ tester.run('component-name-in-template-casing', rule, { options: ['kebab-case', { globals: ['RouterView', 'router-link'] }] }, + // globals with regex patterns + { + code: ` + + `, + options: ['kebab-case', { globals: ['/^c-/', 'other-component'] }] + }, + // type-only imports ...(semver.gte( require('@typescript-eslint/parser/package.json').version, @@ -1223,6 +1238,72 @@ tester.run('component-name-in-template-casing', rule, { } ] }, + { + code: ` + + `, + output: ` + + `, + options: ['PascalCase', { globals: ['/^c-/'] }], + errors: [ + { + message: 'Component name "c-button" is not PascalCase.', + line: 3, + column: 11, + endLine: 3, + endColumn: 20 + }, + { + message: 'Component name "c-card" is not PascalCase.', + line: 4, + column: 11, + endLine: 4, + endColumn: 18 + } + ] + }, + { + code: ` + + `, + output: ` + + `, + options: ['kebab-case', { globals: ['/^C[A-Z]/', '/^c-/'] }], + errors: [ + { + message: 'Component name "CButton" is not kebab-case.', + line: 3, + column: 11, + endLine: 3, + endColumn: 19 + }, + { + message: 'Component name "CCard" is not kebab-case.', + line: 4, + column: 11, + endLine: 4, + endColumn: 17 + } + ] + }, // type-only imports ...(semver.gte( require('@typescript-eslint/parser/package.json').version,

AltStyle によって変換されたページ (->オリジナル) /