no-empty-component-block.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /**
  2. * @author tyankatsu <https://github.com/tyankatsu0105>
  3. * See LICENSE file in root directory for full license.
  4. */
  5. 'use strict'
  6. const { isVElement } = require('../utils')
  7. /**
  8. * check whether has attribute `src`
  9. * @param {VElement} componentBlock
  10. */
  11. function hasAttributeSrc(componentBlock) {
  12. const hasAttribute = componentBlock.startTag.attributes.length > 0
  13. const hasSrc = componentBlock.startTag.attributes.some(
  14. (attribute) =>
  15. !attribute.directive &&
  16. attribute.key.name === 'src' &&
  17. attribute.value &&
  18. attribute.value.value !== ''
  19. )
  20. return hasAttribute && hasSrc
  21. }
  22. /**
  23. * check whether value under the component block is only whitespaces or break lines
  24. * @param {VElement} componentBlock
  25. */
  26. function isValueOnlyWhiteSpacesOrLineBreaks(componentBlock) {
  27. return (
  28. componentBlock.children.length === 1 &&
  29. componentBlock.children[0].type === 'VText' &&
  30. !componentBlock.children[0].value.trim()
  31. )
  32. }
  33. module.exports = {
  34. meta: {
  35. type: 'suggestion',
  36. docs: {
  37. description:
  38. 'disallow the `<template>` `<script>` `<style>` block to be empty',
  39. categories: undefined,
  40. url: 'https://eslint.vuejs.org/rules/no-empty-component-block.html'
  41. },
  42. fixable: null,
  43. schema: [],
  44. messages: {
  45. unexpected: '`<{{ blockName }}>` is empty. Empty block is not allowed.'
  46. }
  47. },
  48. /**
  49. * @param {RuleContext} context - The rule context.
  50. * @returns {RuleListener} AST event handlers.
  51. */
  52. create(context) {
  53. if (!context.parserServices.getDocumentFragment) {
  54. return {}
  55. }
  56. const documentFragment = context.parserServices.getDocumentFragment()
  57. if (!documentFragment) {
  58. return {}
  59. }
  60. const componentBlocks = documentFragment.children.filter(isVElement)
  61. return {
  62. Program() {
  63. for (const componentBlock of componentBlocks) {
  64. if (
  65. componentBlock.name !== 'template' &&
  66. componentBlock.name !== 'script' &&
  67. componentBlock.name !== 'style'
  68. )
  69. continue
  70. // https://vue-loader.vuejs.org/spec.html#src-imports
  71. if (hasAttributeSrc(componentBlock)) continue
  72. if (
  73. isValueOnlyWhiteSpacesOrLineBreaks(componentBlock) ||
  74. componentBlock.children.length === 0
  75. ) {
  76. context.report({
  77. node: componentBlock,
  78. loc: componentBlock.loc,
  79. messageId: 'unexpected',
  80. data: {
  81. blockName: componentBlock.name
  82. }
  83. })
  84. }
  85. }
  86. }
  87. }
  88. }
  89. }