no-empty-component-block.js 2.9 KB

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