mustache-interpolation-spacing.js 2.9 KB

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