v-slot.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /**
  2. * @author Yosuke Ota
  3. * See LICENSE file in root directory for full license.
  4. */
  5. 'use strict'
  6. module.exports = {
  7. supported: '2.6.0',
  8. createTemplateBodyVisitor (context) {
  9. const sourceCode = context.getSourceCode()
  10. /**
  11. * Checks whether the given node can convert to the `slot`.
  12. * @param {VAttribute} vSlotAttr node of `v-slot`
  13. * @returns {boolean} `true` if the given node can convert to the `slot`
  14. */
  15. function canConvertToSlot (vSlotAttr) {
  16. if (vSlotAttr.parent.parent.name !== 'template') {
  17. return false
  18. }
  19. return true
  20. }
  21. /**
  22. * Convert to `slot` and `slot-scope`.
  23. * @param {object} fixer fixer
  24. * @param {VAttribute} vSlotAttr node of `v-slot`
  25. * @returns {*} fix data
  26. */
  27. function fixVSlotToSlot (fixer, vSlotAttr) {
  28. const key = vSlotAttr.key
  29. if (key.modifiers.length) {
  30. // unknown modifiers
  31. return null
  32. }
  33. const attrs = []
  34. const argument = key.argument
  35. if (argument) {
  36. if (argument.type === 'VIdentifier') {
  37. const name = argument.rawName
  38. attrs.push(`slot="${name}"`)
  39. } else if (argument.type === 'VExpressionContainer' && argument.expression) {
  40. const expression = sourceCode.getText(argument.expression)
  41. attrs.push(`:slot="${expression}"`)
  42. } else {
  43. // unknown or syntax error
  44. return null
  45. }
  46. }
  47. const scopedValueNode = vSlotAttr.value
  48. if (scopedValueNode) {
  49. attrs.push(
  50. `slot-scope=${sourceCode.getText(scopedValueNode)}`
  51. )
  52. }
  53. if (!attrs.length) {
  54. attrs.push('slot') // useless
  55. }
  56. return fixer.replaceText(vSlotAttr, attrs.join(' '))
  57. }
  58. /**
  59. * Reports `v-slot` node
  60. * @param {VAttribute} vSlotAttr node of `v-slot`
  61. * @returns {void}
  62. */
  63. function reportVSlot (vSlotAttr) {
  64. context.report({
  65. node: vSlotAttr.key,
  66. messageId: 'forbiddenVSlot',
  67. // fix to use `slot` (downgrade)
  68. fix: fixer => {
  69. if (!canConvertToSlot(vSlotAttr)) {
  70. return null
  71. }
  72. return fixVSlotToSlot(fixer, vSlotAttr)
  73. }
  74. })
  75. }
  76. return {
  77. "VAttribute[directive=true][key.name.name='slot']": reportVSlot
  78. }
  79. }
  80. }