v-for-delimiter-style.js 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  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. url: 'https://eslint.vuejs.org/rules/v-for-delimiter-style.html'
  16. },
  17. fixable: 'code',
  18. schema: [{ enum: ['in', 'of'] }],
  19. messages: {
  20. expected:
  21. "Expected '{{preferredDelimiter}}' instead of '{{usedDelimiter}}' in 'v-for'."
  22. }
  23. },
  24. /** @param {RuleContext} context */
  25. create(context) {
  26. const preferredDelimiter =
  27. /** @type {string|undefined} */ (context.options[0]) || 'in'
  28. return utils.defineTemplateBodyVisitor(context, {
  29. /** @param {VForExpression} node */
  30. VForExpression(node) {
  31. const sourceCode = context.getSourceCode()
  32. const tokenStore =
  33. sourceCode.parserServices.getTemplateBodyTokenStore &&
  34. sourceCode.parserServices.getTemplateBodyTokenStore()
  35. const delimiterToken = /** @type {Token} */ (
  36. tokenStore.getTokenAfter(
  37. node.left.length > 0
  38. ? node.left[node.left.length - 1]
  39. : tokenStore.getFirstToken(node),
  40. (token) => token.type !== 'Punctuator'
  41. )
  42. )
  43. if (delimiterToken.value === preferredDelimiter) {
  44. return
  45. }
  46. context.report({
  47. node,
  48. loc: node.loc,
  49. messageId: 'expected',
  50. data: {
  51. preferredDelimiter,
  52. usedDelimiter: delimiterToken.value
  53. },
  54. *fix(fixer) {
  55. yield fixer.replaceText(delimiterToken, preferredDelimiter)
  56. }
  57. })
  58. }
  59. })
  60. }
  61. }