prop-name-casing.js 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /**
  2. * @fileoverview Requires specific casing for the Prop name in Vue components
  3. * @author Yu Kimura
  4. */
  5. 'use strict'
  6. const utils = require('../utils')
  7. const casing = require('../utils/casing')
  8. const { toRegExp } = require('../utils/regexp')
  9. const allowedCaseOptions = ['camelCase', 'snake_case']
  10. /**
  11. * @typedef {import('../utils').ComponentProp} ComponentProp
  12. */
  13. /** @param {RuleContext} context */
  14. function create(context) {
  15. const options = context.options[0]
  16. /** @type {RegExp[]} */
  17. const ignoreProps = (context.options[1]?.ignoreProps || []).map(toRegExp)
  18. const caseType = allowedCaseOptions.includes(options) ? options : 'camelCase'
  19. const checker = casing.getChecker(caseType)
  20. /**
  21. * @param {ComponentProp[]} props
  22. */
  23. function processProps(props) {
  24. for (const item of props) {
  25. const propName = item.propName
  26. if (propName == null) {
  27. continue
  28. }
  29. if (!checker(propName) && !ignoreProps.some((re) => re.test(propName))) {
  30. context.report({
  31. node: item.node,
  32. messageId: 'invalidCase',
  33. data: {
  34. name: propName,
  35. caseType
  36. }
  37. })
  38. }
  39. }
  40. }
  41. return utils.compositingVisitors(
  42. utils.defineScriptSetupVisitor(context, {
  43. onDefinePropsEnter(_node, props) {
  44. processProps(props)
  45. }
  46. }),
  47. utils.executeOnVue(context, (obj) => {
  48. processProps(utils.getComponentPropsFromOptions(obj))
  49. })
  50. )
  51. }
  52. module.exports = {
  53. meta: {
  54. type: 'suggestion',
  55. docs: {
  56. description:
  57. 'enforce specific casing for the Prop name in Vue components',
  58. categories: ['vue3-strongly-recommended', 'vue2-strongly-recommended'],
  59. url: 'https://eslint.vuejs.org/rules/prop-name-casing.html'
  60. },
  61. fixable: null, // null or "code" or "whitespace"
  62. schema: [
  63. {
  64. enum: allowedCaseOptions
  65. },
  66. {
  67. type: 'object',
  68. properties: {
  69. ignoreProps: {
  70. type: 'array',
  71. items: { type: 'string' },
  72. uniqueItems: true
  73. }
  74. },
  75. additionalProperties: false
  76. }
  77. ],
  78. messages: {
  79. invalidCase: 'Prop "{{name}}" is not in {{caseType}}.'
  80. }
  81. },
  82. create
  83. }