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.
		
		
		
		
		
			
		
			
				
					
					
						
							128 lines
						
					
					
						
							4.0 KiB
						
					
					
				
			
		
		
	
	
							128 lines
						
					
					
						
							4.0 KiB
						
					
					
				/** | 
						|
 * @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 | 
						|
    } | 
						|
  } | 
						|
}
 | 
						|
 |