123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- /**
- * @fileoverview Define a style for the props casing in templates.
- * @author Armano
- */
- 'use strict'
- const utils = require('../utils')
- const casing = require('../utils/casing')
- const svgAttributes = require('../utils/svg-attributes-weird-case.json')
- // ------------------------------------------------------------------------------
- // Rule Definition
- // ------------------------------------------------------------------------------
- module.exports = {
- meta: {
- type: 'suggestion',
- docs: {
- description:
- 'enforce attribute naming style on custom components in template',
- categories: ['vue3-strongly-recommended', 'strongly-recommended'],
- url: 'https://eslint.vuejs.org/rules/attribute-hyphenation.html'
- },
- fixable: 'code',
- schema: [
- {
- enum: ['always', 'never']
- },
- {
- type: 'object',
- properties: {
- ignore: {
- type: 'array',
- items: {
- allOf: [
- { type: 'string' },
- { not: { type: 'string', pattern: ':exit$' } },
- { not: { type: 'string', pattern: '^\\s*$' } }
- ]
- },
- uniqueItems: true,
- additionalItems: false
- }
- },
- additionalProperties: false
- }
- ]
- },
- /** @param {RuleContext} context */
- create(context) {
- const sourceCode = context.getSourceCode()
- const option = context.options[0]
- const optionsPayload = context.options[1]
- const useHyphenated = option !== 'never'
- let ignoredAttributes = ['data-', 'aria-', 'slot-scope'].concat(
- svgAttributes
- )
- if (optionsPayload && optionsPayload.ignore) {
- ignoredAttributes = ignoredAttributes.concat(optionsPayload.ignore)
- }
- const caseConverter = casing.getExactConverter(
- useHyphenated ? 'kebab-case' : 'camelCase'
- )
- /**
- * @param {VDirective | VAttribute} node
- * @param {string} name
- */
- function reportIssue(node, name) {
- const text = sourceCode.getText(node.key)
- context.report({
- node: node.key,
- loc: node.loc,
- message: useHyphenated
- ? "Attribute '{{text}}' must be hyphenated."
- : "Attribute '{{text}}' can't be hyphenated.",
- data: {
- text
- },
- fix: (fixer) =>
- fixer.replaceText(node.key, text.replace(name, caseConverter(name)))
- })
- }
- /**
- * @param {string} value
- */
- function isIgnoredAttribute(value) {
- const isIgnored = ignoredAttributes.some((attr) => {
- return value.includes(attr)
- })
- if (isIgnored) {
- return true
- }
- return useHyphenated ? value.toLowerCase() === value : !/-/.test(value)
- }
- // ----------------------------------------------------------------------
- // Public
- // ----------------------------------------------------------------------
- return utils.defineTemplateBodyVisitor(context, {
- VAttribute(node) {
- if (
- !utils.isCustomComponent(node.parent.parent) &&
- node.parent.parent.name !== 'slot'
- )
- return
- const name = !node.directive
- ? node.key.rawName
- : node.key.name.name === 'bind'
- ? node.key.argument &&
- node.key.argument.type === 'VIdentifier' &&
- node.key.argument.rawName
- : /* otherwise */ false
- if (!name || isIgnoredAttribute(name)) return
- reportIssue(node, name)
- }
- })
- }
- }
|