no-empty-component-block.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. const sourceCode = context.getSourceCode()
  54. if (!sourceCode.parserServices.getDocumentFragment) {
  55. return {}
  56. }
  57. const documentFragment = sourceCode.parserServices.getDocumentFragment()
  58. if (!documentFragment) {
  59. return {}
  60. }
  61. const componentBlocks = documentFragment.children.filter(isVElement)
  62. return {
  63. Program() {
  64. for (const componentBlock of componentBlocks) {
  65. if (
  66. componentBlock.name !== 'template' &&
  67. componentBlock.name !== 'script' &&
  68. componentBlock.name !== 'style'
  69. )
  70. continue
  71. // https://vue-loader.vuejs.org/spec.html#src-imports
  72. if (hasAttributeSrc(componentBlock)) continue
  73. if (
  74. isValueOnlyWhiteSpacesOrLineBreaks(componentBlock) ||
  75. componentBlock.children.length === 0
  76. ) {
  77. context.report({
  78. node: componentBlock,
  79. loc: componentBlock.loc,
  80. messageId: 'unexpected',
  81. data: {
  82. blockName: componentBlock.name
  83. }
  84. })
  85. }
  86. }
  87. }
  88. }
  89. }
  90. }