no-multi-spaces.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /**
  2. * @fileoverview This rule warns about the usage of extra whitespaces between attributes
  3. * @author Armano
  4. */
  5. 'use strict'
  6. // ------------------------------------------------------------------------------
  7. // Rule Definition
  8. // ------------------------------------------------------------------------------
  9. const isProperty = (context, node) => {
  10. const sourceCode = context.getSourceCode()
  11. return node.type === 'Punctuator' && sourceCode.getText(node) === ':'
  12. }
  13. module.exports = {
  14. meta: {
  15. type: 'layout',
  16. docs: {
  17. description: 'disallow multiple spaces',
  18. category: 'strongly-recommended',
  19. url: 'https://eslint.vuejs.org/rules/no-multi-spaces.html'
  20. },
  21. fixable: 'whitespace', // or "code" or "whitespace"
  22. schema: [{
  23. type: 'object',
  24. properties: {
  25. ignoreProperties: {
  26. type: 'boolean'
  27. }
  28. },
  29. additionalProperties: false
  30. }]
  31. },
  32. /**
  33. * @param {RuleContext} context - The rule context.
  34. * @returns {Object} AST event handlers.
  35. */
  36. create (context) {
  37. const options = context.options[0] || {}
  38. const ignoreProperties = options.ignoreProperties === true
  39. return {
  40. Program (node) {
  41. if (context.parserServices.getTemplateBodyTokenStore == null) {
  42. context.report({
  43. loc: { line: 1, column: 0 },
  44. message: 'Use the latest vue-eslint-parser. See also https://vuejs.github.io/eslint-plugin-vue/user-guide/#what-is-the-use-the-latest-vue-eslint-parser-error.'
  45. })
  46. return
  47. }
  48. if (!node.templateBody) {
  49. return
  50. }
  51. const sourceCode = context.getSourceCode()
  52. const tokenStore = context.parserServices.getTemplateBodyTokenStore()
  53. const tokens = tokenStore.getTokens(node.templateBody, { includeComments: true })
  54. let prevToken = tokens.shift()
  55. for (const token of tokens) {
  56. const spaces = token.range[0] - prevToken.range[1]
  57. const shouldIgnore = ignoreProperties && (
  58. isProperty(context, token) || isProperty(context, prevToken)
  59. )
  60. if (spaces > 1 && token.loc.start.line === prevToken.loc.start.line && !shouldIgnore) {
  61. context.report({
  62. node: token,
  63. loc: {
  64. start: prevToken.loc.end,
  65. end: token.loc.start
  66. },
  67. message: "Multiple spaces found before '{{displayValue}}'.",
  68. fix: (fixer) => fixer.replaceTextRange([prevToken.range[1], token.range[0]], ' '),
  69. data: {
  70. displayValue: sourceCode.getText(token)
  71. }
  72. })
  73. }
  74. prevToken = token
  75. }
  76. }
  77. }
  78. }
  79. }