v-for-delimiter-style.js 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. /**
  2. * @fileoverview enforce `v-for` directive's delimiter style
  3. * @author Flo Edelmann
  4. * @copyright 2020 Flo Edelmann. All rights reserved.
  5. * See LICENSE file in root directory for full license.
  6. */
  7. 'use strict'
  8. const utils = require('../utils')
  9. module.exports = {
  10. meta: {
  11. type: 'layout',
  12. docs: {
  13. description: "enforce `v-for` directive's delimiter style",
  14. categories: undefined,
  15. recommended: false,
  16. url: 'https://eslint.vuejs.org/rules/v-for-delimiter-style.html'
  17. },
  18. fixable: 'code',
  19. schema: [{ enum: ['in', 'of'] }]
  20. },
  21. /** @param {RuleContext} context */
  22. create(context) {
  23. const preferredDelimiter =
  24. /** @type {string|undefined} */ (context.options[0]) || 'in'
  25. return utils.defineTemplateBodyVisitor(context, {
  26. /** @param {VForExpression} node */
  27. VForExpression(node) {
  28. const tokenStore =
  29. context.parserServices.getTemplateBodyTokenStore &&
  30. context.parserServices.getTemplateBodyTokenStore()
  31. const delimiterToken = /** @type {Token} */ (
  32. tokenStore.getTokenAfter(
  33. node.left.length > 0
  34. ? node.left[node.left.length - 1]
  35. : tokenStore.getFirstToken(node),
  36. (token) => token.type !== 'Punctuator' || token.value !== ')'
  37. )
  38. )
  39. if (delimiterToken.value === preferredDelimiter) {
  40. return
  41. }
  42. context.report({
  43. node,
  44. loc: node.loc,
  45. message: `Expected '{{preferredDelimiter}}' instead of '{{usedDelimiter}}' in 'v-for'.`,
  46. data: {
  47. preferredDelimiter,
  48. usedDelimiter: delimiterToken.value
  49. },
  50. *fix(fixer) {
  51. yield fixer.replaceText(delimiterToken, preferredDelimiter)
  52. }
  53. })
  54. }
  55. })
  56. }
  57. }