max-lines-per-block.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /**
  2. * @author lsdsjy
  3. * @fileoverview Rule for checking the maximum number of lines in Vue SFC blocks.
  4. */
  5. 'use strict'
  6. const { SourceCode } = require('eslint')
  7. const utils = require('../utils')
  8. /**
  9. * @param {string} text
  10. */
  11. function isEmptyLine(text) {
  12. return !text.trim()
  13. }
  14. module.exports = {
  15. meta: {
  16. type: 'problem',
  17. docs: {
  18. description: 'enforce maximum number of lines in Vue SFC blocks',
  19. categories: undefined,
  20. url: 'https://eslint.vuejs.org/rules/max-lines-per-block.html'
  21. },
  22. fixable: null,
  23. schema: [
  24. {
  25. type: 'object',
  26. properties: {
  27. style: {
  28. type: 'integer',
  29. minimum: 1
  30. },
  31. template: {
  32. type: 'integer',
  33. minimum: 1
  34. },
  35. script: {
  36. type: 'integer',
  37. minimum: 1
  38. },
  39. skipBlankLines: {
  40. type: 'boolean',
  41. minimum: 0
  42. }
  43. },
  44. additionalProperties: false
  45. }
  46. ],
  47. messages: {
  48. tooManyLines:
  49. 'Block has too many lines ({{lineCount}}). Maximum allowed is {{limit}}.'
  50. }
  51. },
  52. /** @param {RuleContext} context */
  53. create(context) {
  54. const option = context.options[0] || {}
  55. /**
  56. * @type {Record<string, number>}
  57. */
  58. const limits = {
  59. template: option.template,
  60. script: option.script,
  61. style: option.style
  62. }
  63. const code = context.getSourceCode()
  64. const documentFragment =
  65. context.parserServices.getDocumentFragment &&
  66. context.parserServices.getDocumentFragment()
  67. function getTopLevelHTMLElements() {
  68. if (documentFragment) {
  69. return documentFragment.children.filter(utils.isVElement)
  70. }
  71. return []
  72. }
  73. return {
  74. /** @param {Program} node */
  75. Program(node) {
  76. if (utils.hasInvalidEOF(node)) {
  77. return
  78. }
  79. for (const block of getTopLevelHTMLElements()) {
  80. if (limits[block.name]) {
  81. // We suppose the start tag and end tag occupy one single line respectively
  82. let lineCount = block.loc.end.line - block.loc.start.line - 1
  83. if (option.skipBlankLines) {
  84. const lines = SourceCode.splitLines(code.getText(block))
  85. lineCount -= lines.filter(isEmptyLine).length
  86. }
  87. if (lineCount > limits[block.name]) {
  88. context.report({
  89. node: block,
  90. messageId: 'tooManyLines',
  91. data: {
  92. limit: limits[block.name],
  93. lineCount
  94. }
  95. })
  96. }
  97. }
  98. }
  99. }
  100. }
  101. }
  102. }