UNPKG

eslint-plugin-vue

Version:

Official ESLint plugin for Vue.js

158 lines (156 loc) 6.12 kB
const require_runtime = require('../_virtual/_rolldown/runtime.js'); const require_index = require('../utils/index.js'); const require_casing = require('../utils/casing.js'); const require_regexp = require('../utils/regexp.js'); let _eslint_community_eslint_utils = require("@eslint-community/eslint-utils"); //#region lib/rules/custom-event-name-casing.ts var import_utils = /* @__PURE__ */ require_runtime.__toESM(require_index.default); const ALLOWED_CASE_OPTIONS = ["kebab-case", "camelCase"]; const DEFAULT_CASE = "camelCase"; /** * Get the name param node from the given CallExpression */ function getNameParamNode(node) { const nameLiteralNode = node.arguments[0]; if (nameLiteralNode && import_utils.default.isStringLiteral(nameLiteralNode)) { const name = import_utils.default.getStringLiteralValue(nameLiteralNode); if (name != null) return { name, loc: nameLiteralNode.loc }; } return null; } /** * Get the callee member node from the given CallExpression */ function getCalleeMemberNode(node) { const callee = import_utils.default.skipChainExpression(node.callee); if (callee.type === "MemberExpression") { const name = import_utils.default.getStaticPropertyName(callee); if (name) return { name, member: callee }; } return null; } var custom_event_name_casing_default = { meta: { type: "suggestion", docs: { description: "enforce specific casing for custom event name", categories: void 0, url: "https://eslint.vuejs.org/rules/custom-event-name-casing.html" }, fixable: null, schema: [{ enum: ALLOWED_CASE_OPTIONS }, { type: "object", properties: { ignores: { type: "array", items: { type: "string" }, uniqueItems: true, additionalItems: false } }, additionalProperties: false }], messages: { unexpected: "Custom event name '{{name}}' must be {{caseType}}." } }, create(context) { const setupContexts = /* @__PURE__ */ new Map(); let emitParamName = ""; const caseType = context.options[0] || DEFAULT_CASE; const objectOption = context.options[1] || {}; const caseChecker = require_casing.getChecker(caseType); const isIgnored = require_regexp.toRegExpGroupMatcher(objectOption.ignores); /** * Check whether the given event name is valid. */ function isValidEventName(name) { return caseChecker(name) || name.startsWith("update:"); } function verify(nameWithLoc) { const name = nameWithLoc.name; if (isValidEventName(name) || isIgnored(name)) return; context.report({ loc: nameWithLoc.loc, messageId: "unexpected", data: { name, caseType } }); } const programNode = context.sourceCode.ast; const callVisitor = { CallExpression(node, info) { const nameWithLoc = getNameParamNode(node); if (!nameWithLoc) return; const setupContext = setupContexts.get(info ? info.node : programNode); if (setupContext) { const { contextReferenceIds, emitReferenceIds } = setupContext; if (node.callee.type === "Identifier" && emitReferenceIds.has(node.callee)) verify(nameWithLoc); else { const emit = getCalleeMemberNode(node); if (emit && emit.name === "emit" && emit.member.object.type === "Identifier" && contextReferenceIds.has(emit.member.object)) verify(nameWithLoc); } } } }; return import_utils.default.defineTemplateBodyVisitor(context, { CallExpression(node) { const callee = node.callee; const nameWithLoc = getNameParamNode(node); if (!nameWithLoc) return; if (callee.type === "Identifier" && (callee.name === "$emit" || callee.name === emitParamName)) verify(nameWithLoc); } }, import_utils.default.compositingVisitors(import_utils.default.defineScriptSetupVisitor(context, { onDefineEmitsEnter(node) { if (!node.parent || node.parent.type !== "VariableDeclarator" || node.parent.init !== node) return; const emitParam = node.parent.id; if (emitParam.type !== "Identifier") return; emitParamName = emitParam.name; const variable = (0, _eslint_community_eslint_utils.findVariable)(import_utils.default.getScope(context, emitParam), emitParam); if (!variable) return; const emitReferenceIds = /* @__PURE__ */ new Set(); for (const reference of variable.references) emitReferenceIds.add(reference.identifier); setupContexts.set(programNode, { contextReferenceIds: /* @__PURE__ */ new Set(), emitReferenceIds }); }, ...callVisitor }), import_utils.default.defineVueVisitor(context, { onSetupFunctionEnter(node, { node: vueNode }) { const contextParam = import_utils.default.skipDefaultParamValue(node.params[1]); if (!contextParam) return; if (contextParam.type === "RestElement" || contextParam.type === "ArrayPattern") return; const contextReferenceIds = /* @__PURE__ */ new Set(); const emitReferenceIds = /* @__PURE__ */ new Set(); if (contextParam.type === "ObjectPattern") { const emitProperty = import_utils.default.findAssignmentProperty(contextParam, "emit"); if (!emitProperty || emitProperty.value.type !== "Identifier") return; const emitParam = emitProperty.value; const variable = (0, _eslint_community_eslint_utils.findVariable)(import_utils.default.getScope(context, emitParam), emitParam); if (!variable) return; for (const reference of variable.references) emitReferenceIds.add(reference.identifier); } else { const variable = (0, _eslint_community_eslint_utils.findVariable)(import_utils.default.getScope(context, contextParam), contextParam); if (!variable) return; for (const reference of variable.references) contextReferenceIds.add(reference.identifier); } setupContexts.set(vueNode, { contextReferenceIds, emitReferenceIds }); }, ...callVisitor, onVueObjectExit(node) { setupContexts.delete(node); } }), { CallExpression(node) { const nameLiteralNode = getNameParamNode(node); if (!nameLiteralNode) return; const emit = getCalleeMemberNode(node); if (emit && emit.name === "$emit") verify(nameLiteralNode); } })); } }; //#endregion exports.default = custom_event_name_casing_default;