v-slot.js 2.4 KB

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