UNPKG

eslint-plugin-vue

Version:

Official ESLint plugin for Vue.js

129 lines (126 loc) 5.41 kB
'use strict'; const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.js'); const require_index = require('../../utils/index.js'); const require_casing$1 = require('../../utils/casing.js'); const require_regexp$1 = require('../../utils/regexp.js'); const require_can_convert_to_v_slot$1 = require('./utils/can-convert-to-v-slot.js'); //#region lib/rules/syntaxes/slot-attribute.js /** * @author Yosuke Ota * See LICENSE file in root directory for full license. */ var require_slot_attribute = /* @__PURE__ */ require_rolldown_runtime.__commonJSMin(((exports, module) => { const canConvertToVSlot = require_can_convert_to_v_slot$1.default; const regexp = require_regexp$1.default; const casing = require_casing$1.default; const { isVElement } = require_index.default; module.exports = { deprecated: "2.6.0", supported: "<3.0.0", createTemplateBodyVisitor(context) { const { ignore = [], ignoreParents = [] } = context.options[0] || {}; const isAnyIgnored = regexp.toRegExpGroupMatcher(ignore); const isParentIgnored = regexp.toRegExpGroupMatcher(ignoreParents); const sourceCode = context.sourceCode; const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore && sourceCode.parserServices.getTemplateBodyTokenStore(); /** * Checks whether the given node can convert to the `v-slot`. * @param {VAttribute} slotAttr node of `slot` * @returns {boolean} `true` if the given node can convert to the `v-slot` */ function canConvertFromSlotToVSlot(slotAttr) { if (!canConvertToVSlot(slotAttr.parent.parent, sourceCode, tokenStore)) return false; if (!slotAttr.value) return true; const slotName = slotAttr.value.value; return !/[^\w\-]/u.test(slotName); } /** * Checks whether the given node can convert to the `v-slot`. * @param {VDirective} slotAttr node of `v-bind:slot` * @returns {boolean} `true` if the given node can convert to the `v-slot` */ function canConvertFromVBindSlotToVSlot(slotAttr) { if (!canConvertToVSlot(slotAttr.parent.parent, sourceCode, tokenStore)) return false; if (!slotAttr.value) return true; if (!slotAttr.value.expression) return false; return slotAttr.value.expression.type === "Identifier"; } /** * Convert to `v-slot`. * @param {RuleFixer} fixer fixer * @param {VAttribute|VDirective} slotAttr node of `slot` * @param {string | null} slotName name of `slot` * @param {boolean} vBind `true` if `slotAttr` is `v-bind:slot` * @returns {IterableIterator<Fix>} fix data */ function* fixSlotToVSlot(fixer, slotAttr, slotName, vBind) { const startTag = slotAttr.parent; const scopeAttr = startTag.attributes.find((attr) => attr.directive === true && attr.key.name && (attr.key.name.name === "slot-scope" || attr.key.name.name === "scope")); let nameArgument = ""; if (slotName) nameArgument = vBind ? `:[${slotName}]` : `:${slotName}`; const scopeValue = scopeAttr && scopeAttr.value ? `=${sourceCode.getText(scopeAttr.value)}` : ""; const replaceText = `v-slot${nameArgument}${scopeValue}`; const element = startTag.parent; if (element.name === "template") { yield fixer.replaceText(slotAttr || scopeAttr, replaceText); if (slotAttr && scopeAttr) yield fixer.remove(scopeAttr); } else { yield fixer.remove(slotAttr || scopeAttr); if (slotAttr && scopeAttr) yield fixer.remove(scopeAttr); const vFor = startTag.attributes.find((attr) => attr.directive && attr.key.name.name === "for"); const vForText = vFor ? `${sourceCode.getText(vFor)} ` : ""; if (vFor) yield fixer.remove(vFor); yield fixer.insertTextBefore(element, `<template ${vForText}${replaceText}>\n`); yield fixer.insertTextAfter(element, `\n</template>`); } } /** * Reports `slot` node * @param {VAttribute} slotAttr node of `slot` * @returns {void} */ function reportSlot(slotAttr) { const component = slotAttr.parent.parent; const componentName = component.rawName; if (isAnyIgnored(componentName, casing.pascalCase(componentName), casing.kebabCase(componentName))) return; const parent = component.parent; const parentName = isVElement(parent) ? parent.rawName : null; if (parentName && isParentIgnored(parentName)) return; context.report({ node: slotAttr.key, messageId: "forbiddenSlotAttribute", *fix(fixer) { if (!canConvertFromSlotToVSlot(slotAttr)) return; yield* fixSlotToVSlot(fixer, slotAttr, slotAttr.value && slotAttr.value.value, false); } }); } /** * Reports `v-bind:slot` node * @param {VDirective} slotAttr node of `v-bind:slot` * @returns {void} */ function reportVBindSlot(slotAttr) { context.report({ node: slotAttr.key, messageId: "forbiddenSlotAttribute", *fix(fixer) { if (!canConvertFromVBindSlotToVSlot(slotAttr)) return; yield* fixSlotToVSlot(fixer, slotAttr, slotAttr.value && slotAttr.value.expression && sourceCode.getText(slotAttr.value.expression).trim(), true); } }); } return { "VAttribute[directive=false][key.name='slot']": reportSlot, "VAttribute[directive=true][key.name.name='bind'][key.argument.name='slot']": reportVBindSlot }; } }; })); //#endregion Object.defineProperty(exports, 'default', { enumerable: true, get: function () { return require_slot_attribute(); } });