mustache-interpolation-spacing.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /**
  2. * @fileoverview enforce unified spacing in mustache interpolations.
  3. * @author Armano
  4. */
  5. 'use strict'
  6. // ------------------------------------------------------------------------------
  7. // Requirements
  8. // ------------------------------------------------------------------------------
  9. const utils = require('../utils')
  10. // ------------------------------------------------------------------------------
  11. // Rule Definition
  12. // ------------------------------------------------------------------------------
  13. module.exports = {
  14. meta: {
  15. docs: {
  16. description: 'enforce unified spacing in mustache interpolations',
  17. category: 'strongly-recommended',
  18. url: 'https://github.com/vuejs/eslint-plugin-vue/blob/v4.7.1/docs/rules/mustache-interpolation-spacing.md'
  19. },
  20. fixable: 'whitespace',
  21. schema: [
  22. {
  23. enum: ['always', 'never']
  24. }
  25. ]
  26. },
  27. create (context) {
  28. const options = context.options[0] || 'always'
  29. const template =
  30. context.parserServices.getTemplateBodyTokenStore &&
  31. context.parserServices.getTemplateBodyTokenStore()
  32. // ----------------------------------------------------------------------
  33. // Public
  34. // ----------------------------------------------------------------------
  35. return utils.defineTemplateBodyVisitor(context, {
  36. 'VExpressionContainer[expression!=null]' (node) {
  37. const openBrace = template.getFirstToken(node)
  38. const closeBrace = template.getLastToken(node)
  39. if (
  40. !openBrace ||
  41. !closeBrace ||
  42. openBrace.type !== 'VExpressionStart' ||
  43. closeBrace.type !== 'VExpressionEnd'
  44. ) {
  45. return
  46. }
  47. const firstToken = template.getTokenAfter(openBrace, { includeComments: true })
  48. const lastToken = template.getTokenBefore(closeBrace, { includeComments: true })
  49. if (options === 'always') {
  50. if (openBrace.range[1] === firstToken.range[0]) {
  51. context.report({
  52. node: openBrace,
  53. message: "Expected 1 space after '{{', but not found.",
  54. fix: (fixer) => fixer.insertTextAfter(openBrace, ' ')
  55. })
  56. }
  57. if (closeBrace.range[0] === lastToken.range[1]) {
  58. context.report({
  59. node: closeBrace,
  60. message: "Expected 1 space before '}}', but not found.",
  61. fix: (fixer) => fixer.insertTextBefore(closeBrace, ' ')
  62. })
  63. }
  64. } else {
  65. if (openBrace.range[1] !== firstToken.range[0]) {
  66. context.report({
  67. loc: {
  68. start: openBrace.loc.start,
  69. end: firstToken.loc.start
  70. },
  71. message: "Expected no space after '{{', but found.",
  72. fix: (fixer) => fixer.removeRange([openBrace.range[1], firstToken.range[0]])
  73. })
  74. }
  75. if (closeBrace.range[0] !== lastToken.range[1]) {
  76. context.report({
  77. loc: {
  78. start: lastToken.loc.end,
  79. end: closeBrace.loc.end
  80. },
  81. message: "Expected no space before '}}', but found.",
  82. fix: (fixer) => fixer.removeRange([lastToken.range[1], closeBrace.range[0]])
  83. })
  84. }
  85. }
  86. }
  87. })
  88. }
  89. }