no-parsing-error.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /**
  2. * @author Toru Nagashima
  3. * @copyright 2017 Toru Nagashima. All rights reserved.
  4. * See LICENSE file in root directory for full license.
  5. */
  6. 'use strict'
  7. // ------------------------------------------------------------------------------
  8. // Helpers
  9. // ------------------------------------------------------------------------------
  10. // https://html.spec.whatwg.org/multipage/parsing.html#parse-errors
  11. const DEFAULT_OPTIONS = Object.freeze(
  12. Object.assign(Object.create(null), {
  13. 'abrupt-closing-of-empty-comment': true,
  14. 'absence-of-digits-in-numeric-character-reference': true,
  15. 'cdata-in-html-content': true,
  16. 'character-reference-outside-unicode-range': true,
  17. 'control-character-in-input-stream': true,
  18. 'control-character-reference': true,
  19. 'eof-before-tag-name': true,
  20. 'eof-in-cdata': true,
  21. 'eof-in-comment': true,
  22. 'eof-in-tag': true,
  23. 'incorrectly-closed-comment': true,
  24. 'incorrectly-opened-comment': true,
  25. 'invalid-first-character-of-tag-name': true,
  26. 'missing-attribute-value': true,
  27. 'missing-end-tag-name': true,
  28. 'missing-semicolon-after-character-reference': true,
  29. 'missing-whitespace-between-attributes': true,
  30. 'nested-comment': true,
  31. 'noncharacter-character-reference': true,
  32. 'noncharacter-in-input-stream': true,
  33. 'null-character-reference': true,
  34. 'surrogate-character-reference': true,
  35. 'surrogate-in-input-stream': true,
  36. 'unexpected-character-in-attribute-name': true,
  37. 'unexpected-character-in-unquoted-attribute-value': true,
  38. 'unexpected-equals-sign-before-attribute-name': true,
  39. 'unexpected-null-character': true,
  40. 'unexpected-question-mark-instead-of-tag-name': true,
  41. 'unexpected-solidus-in-tag': true,
  42. 'unknown-named-character-reference': true,
  43. 'end-tag-with-attributes': true,
  44. 'duplicate-attribute': true,
  45. 'end-tag-with-trailing-solidus': true,
  46. 'non-void-html-element-start-tag-with-trailing-solidus': false,
  47. 'x-invalid-end-tag': true,
  48. 'x-invalid-namespace': true
  49. })
  50. )
  51. // ------------------------------------------------------------------------------
  52. // Rule Definition
  53. // ------------------------------------------------------------------------------
  54. module.exports = {
  55. meta: {
  56. type: 'problem',
  57. docs: {
  58. description: 'disallow parsing errors in `<template>`',
  59. categories: ['vue3-essential', 'essential'],
  60. url: 'https://eslint.vuejs.org/rules/no-parsing-error.html'
  61. },
  62. fixable: null,
  63. schema: [
  64. {
  65. type: 'object',
  66. properties: Object.keys(DEFAULT_OPTIONS).reduce((ret, code) => {
  67. ret[code] = { type: 'boolean' }
  68. return ret
  69. }, /** @type { { [key: string]: { type: 'boolean' } } } */ ({})),
  70. additionalProperties: false
  71. }
  72. ]
  73. },
  74. /**
  75. * @param {RuleContext} context - The rule context.
  76. * @returns {RuleListener} AST event handlers.
  77. */
  78. create(context) {
  79. const options = Object.assign({}, DEFAULT_OPTIONS, context.options[0] || {})
  80. return {
  81. Program(program) {
  82. const node = program.templateBody
  83. if (node == null || node.errors == null) {
  84. return
  85. }
  86. for (const error of node.errors) {
  87. if (error.code && !options[error.code]) {
  88. continue
  89. }
  90. context.report({
  91. node,
  92. loc: { line: error.lineNumber, column: error.column },
  93. message: 'Parsing error: {{message}}.',
  94. data: {
  95. message: error.message.endsWith('.')
  96. ? error.message.slice(0, -1)
  97. : error.message
  98. }
  99. })
  100. }
  101. }
  102. }
  103. }
  104. }