component-definition-name-casing.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /**
  2. * @fileoverview enforce specific casing for component definition name
  3. * @author Armano
  4. */
  5. 'use strict'
  6. const utils = require('../utils')
  7. const casing = require('../utils/casing')
  8. const allowedCaseOptions = ['PascalCase', 'kebab-case']
  9. // ------------------------------------------------------------------------------
  10. // Rule Definition
  11. // ------------------------------------------------------------------------------
  12. module.exports = {
  13. meta: {
  14. type: 'suggestion',
  15. docs: {
  16. description: 'enforce specific casing for component definition name',
  17. category: undefined,
  18. // TODO Change with major version.
  19. // category: 'strongly-recommended',
  20. url: 'https://eslint.vuejs.org/rules/component-definition-name-casing.html'
  21. },
  22. fixable: 'code', // or "code" or "whitespace"
  23. schema: [
  24. {
  25. enum: allowedCaseOptions
  26. }
  27. ]
  28. },
  29. create (context) {
  30. const options = context.options[0]
  31. const caseType = allowedCaseOptions.indexOf(options) !== -1 ? options : 'PascalCase'
  32. // ----------------------------------------------------------------------
  33. // Public
  34. // ----------------------------------------------------------------------
  35. function convertName (node) {
  36. let nodeValue
  37. let range
  38. if (node.type === 'TemplateLiteral') {
  39. const quasis = node.quasis[0]
  40. nodeValue = quasis.value.cooked
  41. range = quasis.range
  42. } else {
  43. nodeValue = node.value
  44. range = node.range
  45. }
  46. const value = casing.getConverter(caseType)(nodeValue)
  47. if (value !== nodeValue) {
  48. context.report({
  49. node: node,
  50. message: 'Property name "{{value}}" is not {{caseType}}.',
  51. data: {
  52. value: nodeValue,
  53. caseType: caseType
  54. },
  55. fix: fixer => fixer.replaceTextRange([range[0] + 1, range[1] - 1], value)
  56. })
  57. }
  58. }
  59. function canConvert (node) {
  60. return node.type === 'Literal' || (
  61. node.type === 'TemplateLiteral' &&
  62. node.expressions.length === 0 &&
  63. node.quasis.length === 1
  64. )
  65. }
  66. return Object.assign({},
  67. utils.executeOnCallVueComponent(context, (node) => {
  68. if (node.arguments.length === 2) {
  69. const argument = node.arguments[0]
  70. if (canConvert(argument)) {
  71. convertName(argument)
  72. }
  73. }
  74. }),
  75. utils.executeOnVue(context, (obj) => {
  76. const node = obj.properties
  77. .find(item => (
  78. item.type === 'Property' &&
  79. item.key.name === 'name' &&
  80. canConvert(item.value)
  81. ))
  82. if (!node) return
  83. convertName(node.value)
  84. })
  85. )
  86. }
  87. }