You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
3.5 KiB
115 lines
3.5 KiB
/** |
|
* @author Pig Fang |
|
* See LICENSE file in root directory for full license. |
|
*/ |
|
'use strict' |
|
|
|
// ------------------------------------------------------------------------------ |
|
// Requirements |
|
// ------------------------------------------------------------------------------ |
|
|
|
const utils = require('../utils') |
|
const casing = require('../utils/casing') |
|
|
|
// ------------------------------------------------------------------------------ |
|
// Helpers |
|
// ------------------------------------------------------------------------------ |
|
|
|
/** |
|
* @param {import('../../typings/eslint-plugin-vue/util-types/ast').Expression} node |
|
* @returns {string | null} |
|
*/ |
|
function getOptionsComponentName(node) { |
|
if (node.type === 'Identifier') { |
|
return node.name |
|
} |
|
if (node.type === 'Literal') { |
|
return typeof node.value === 'string' ? node.value : null |
|
} |
|
return null |
|
} |
|
|
|
// ------------------------------------------------------------------------------ |
|
// Rule Definition |
|
// ------------------------------------------------------------------------------ |
|
|
|
module.exports = { |
|
meta: { |
|
type: 'suggestion', |
|
docs: { |
|
description: |
|
'enforce the casing of component name in `components` options', |
|
categories: undefined, |
|
url: 'https://eslint.vuejs.org/rules/component-options-name-casing.html' |
|
}, |
|
fixable: 'code', |
|
hasSuggestions: true, |
|
schema: [{ enum: casing.allowedCaseOptions }], |
|
messages: { |
|
caseNotMatched: 'Component name "{{component}}" is not {{caseType}}.', |
|
possibleRenaming: 'Rename component name to be in {{caseType}}.' |
|
} |
|
}, |
|
/** @param {RuleContext} context */ |
|
create(context) { |
|
const caseType = context.options[0] || 'PascalCase' |
|
|
|
const canAutoFix = caseType === 'PascalCase' |
|
const checkCase = casing.getChecker(caseType) |
|
const convert = casing.getConverter(caseType) |
|
|
|
return utils.executeOnVue(context, (obj) => { |
|
const node = utils.findProperty(obj, 'components') |
|
if (!node || node.value.type !== 'ObjectExpression') { |
|
return |
|
} |
|
|
|
node.value.properties.forEach((property) => { |
|
if (property.type !== 'Property') { |
|
return |
|
} |
|
|
|
const name = getOptionsComponentName(property.key) |
|
if (!name || checkCase(name)) { |
|
return |
|
} |
|
|
|
context.report({ |
|
node: property.key, |
|
messageId: 'caseNotMatched', |
|
data: { |
|
component: name, |
|
caseType |
|
}, |
|
fix: canAutoFix |
|
? (fixer) => { |
|
const converted = convert(name) |
|
return property.shorthand |
|
? fixer.replaceText(property, `${converted}: ${name}`) |
|
: fixer.replaceText(property.key, converted) |
|
} |
|
: undefined, |
|
suggest: canAutoFix |
|
? undefined |
|
: [ |
|
{ |
|
messageId: 'possibleRenaming', |
|
data: { caseType }, |
|
fix: (fixer) => { |
|
const converted = convert(name) |
|
if (caseType === 'kebab-case') { |
|
return property.shorthand |
|
? fixer.replaceText(property, `'${converted}': ${name}`) |
|
: fixer.replaceText(property.key, `'${converted}'`) |
|
} |
|
return property.shorthand |
|
? fixer.replaceText(property, `${converted}: ${name}`) |
|
: fixer.replaceText(property.key, converted) |
|
} |
|
} |
|
] |
|
}) |
|
}) |
|
}) |
|
} |
|
}
|
|
|