no-parsing-error.js 3.3 KB

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