/** * @author Yosuke Ota * issue https://github.com/vuejs/eslint-plugin-vue/issues/250 */ 'use strict' // ------------------------------------------------------------------------------ // Requirements // ------------------------------------------------------------------------------ const utils = require('../utils') const casing = require('../utils/casing') const allowedCaseOptions = ['PascalCase', 'kebab-case'] const defaultCase = 'PascalCase' // ------------------------------------------------------------------------------ // Rule Definition // ------------------------------------------------------------------------------ module.exports = { meta: { type: 'suggestion', docs: { description: 'enforce specific casing for the component naming style in template', category: 'strongly-recommended', url: 'https://github.com/vuejs/eslint-plugin-vue/blob/v5.0.0/docs/rules/component-name-in-template-casing.md' }, fixable: 'code', schema: [ { enum: allowedCaseOptions }, { type: 'object', properties: { ignores: { type: 'array', items: { type: 'string' }, uniqueItems: true, additionalItems: false } }, additionalProperties: false } ] }, create (context) { const caseOption = context.options[0] const options = context.options[1] || {} const caseType = allowedCaseOptions.indexOf(caseOption) !== -1 ? caseOption : defaultCase const ignores = options.ignores || [] const tokens = context.parserServices.getTemplateBodyTokenStore && context.parserServices.getTemplateBodyTokenStore() let hasInvalidEOF = false return utils.defineTemplateBodyVisitor(context, { 'VElement' (node) { if (hasInvalidEOF) { return } if ( (!utils.isHtmlElementNode(node) && !utils.isSvgElementNode(node)) || utils.isHtmlWellKnownElementName(node.rawName) || utils.isSvgWellKnownElementName(node.rawName) ) { return } const name = node.rawName if (ignores.indexOf(name) >= 0) { return } const casingName = casing.getConverter(caseType)(name) if (casingName !== name) { const startTag = node.startTag const open = tokens.getFirstToken(startTag) context.report({ node: open, loc: open.loc, message: 'Component name "{{name}}" is not {{caseType}}.', data: { name, caseType }, fix: fixer => { const endTag = node.endTag if (!endTag) { return fixer.replaceText(open, `<${casingName}`) } const endTagOpen = tokens.getFirstToken(endTag) return [ fixer.replaceText(open, `<${casingName}`), fixer.replaceText(endTagOpen, `