123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- /**
- * @author Yosuke Ota
- * See LICENSE file in root directory for full license.
- */
- 'use strict'
- module.exports = {
- deprecated: '2.6.0',
- createTemplateBodyVisitor (context) {
- const sourceCode = context.getSourceCode()
- /**
- * 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 (slotAttr.parent.parent.name !== 'template') {
- return false
- }
- if (!slotAttr.value) {
- return true
- }
- const slotName = slotAttr.value.value
- // If non-Latin characters are included it can not be converted.
- return !/[^a-z]/i.test(slotName)
- }
- /**
- * Checks whether the given node can convert to the `v-slot`.
- * @param {VAttribute} slotAttr node of `v-bind:slot`
- * @returns {boolean} `true` if the given node can convert to the `v-slot`
- */
- function canConvertFromVBindSlotToVSlot (slotAttr) {
- if (slotAttr.parent.parent.name !== 'template') {
- return false
- }
- if (!slotAttr.value) {
- return true
- }
- if (!slotAttr.value.expression) {
- // parse error or empty expression
- return false
- }
- const slotName = sourceCode.getText(slotAttr.value.expression).trim()
- // If non-Latin characters are included it can not be converted.
- // It does not check the space only because `a>b?c:d` should be rejected.
- return !/[^a-z]/i.test(slotName)
- }
- /**
- * Convert to `v-slot`.
- * @param {object} fixer fixer
- * @param {VAttribute} slotAttr node of `slot`
- * @param {string | null} slotName name of `slot`
- * @param {boolean} vBind `true` if `slotAttr` is `v-bind:slot`
- * @returns {*} fix data
- */
- function fixSlotToVSlot (fixer, slotAttr, slotName, vBind) {
- const element = slotAttr.parent
- const scopeAttr = element.attributes
- .find(attr => attr.directive === true && attr.key.name && (
- attr.key.name.name === 'slot-scope' ||
- attr.key.name.name === 'scope'
- ))
- const nameArgument = slotName ? (vBind ? `:[${slotName}]` : `:${slotName}`) : ''
- const scopeValue = scopeAttr && scopeAttr.value
- ? `=${sourceCode.getText(scopeAttr.value)}`
- : ''
- const replaceText = `v-slot${nameArgument}${scopeValue}`
- const fixers = [
- fixer.replaceText(slotAttr || scopeAttr, replaceText)
- ]
- if (slotAttr && scopeAttr) {
- fixers.push(fixer.remove(scopeAttr))
- }
- return fixers
- }
- /**
- * Reports `slot` node
- * @param {VAttribute} slotAttr node of `slot`
- * @returns {void}
- */
- function reportSlot (slotAttr) {
- context.report({
- node: slotAttr.key,
- messageId: 'forbiddenSlotAttribute',
- // fix to use `v-slot`
- fix (fixer) {
- if (!canConvertFromSlotToVSlot(slotAttr)) {
- return null
- }
- const slotName = slotAttr.value &&
- slotAttr.value.value
- return fixSlotToVSlot(fixer, slotAttr, slotName, false)
- }
- })
- }
- /**
- * Reports `v-bind:slot` node
- * @param {VAttribute} slotAttr node of `v-bind:slot`
- * @returns {void}
- */
- function reportVBindSlot (slotAttr) {
- context.report({
- node: slotAttr.key,
- messageId: 'forbiddenSlotAttribute',
- // fix to use `v-slot`
- fix (fixer) {
- if (!canConvertFromVBindSlotToVSlot(slotAttr)) {
- return null
- }
- const slotName = slotAttr.value &&
- slotAttr.value.expression &&
- sourceCode.getText(slotAttr.value.expression).trim()
- return fixSlotToVSlot(fixer, slotAttr, slotName, true)
- }
- })
- }
- return {
- "VAttribute[directive=false][key.name='slot']": reportSlot,
- "VAttribute[directive=true][key.name.name='bind'][key.argument.name='slot']": reportVBindSlot
- }
- }
- }
|