vue.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import type { Linter } from 'eslint';
  2. import { interopDefault } from '../util';
  3. export async function vue(): Promise<Linter.Config[]> {
  4. const [pluginVue, parserVue, parserTs] = await Promise.all([
  5. interopDefault(import('eslint-plugin-vue')),
  6. interopDefault(import('vue-eslint-parser')),
  7. // @ts-expect-error missing types
  8. interopDefault(import('@typescript-eslint/parser')),
  9. ] as const);
  10. return [
  11. {
  12. files: ['**/*.vue'],
  13. languageOptions: {
  14. // globals: {
  15. // computed: 'readonly',
  16. // defineEmits: 'readonly',
  17. // defineExpose: 'readonly',
  18. // defineProps: 'readonly',
  19. // onMounted: 'readonly',
  20. // onUnmounted: 'readonly',
  21. // reactive: 'readonly',
  22. // ref: 'readonly',
  23. // shallowReactive: 'readonly',
  24. // shallowRef: 'readonly',
  25. // toRef: 'readonly',
  26. // toRefs: 'readonly',
  27. // watch: 'readonly',
  28. // watchEffect: 'readonly',
  29. // },
  30. parser: parserVue,
  31. parserOptions: {
  32. ecmaFeatures: {
  33. jsx: true,
  34. },
  35. extraFileExtensions: ['.vue'],
  36. parser: parserTs,
  37. sourceType: 'module',
  38. },
  39. },
  40. plugins: {
  41. vue: pluginVue,
  42. },
  43. processor: pluginVue.processors['.vue'],
  44. rules: {
  45. ...pluginVue.configs.base.rules,
  46. ...pluginVue.configs['vue3-essential'].rules,
  47. ...pluginVue.configs['vue3-strongly-recommended'].rules,
  48. ...pluginVue.configs['vue3-recommended'].rules,
  49. 'vue/attribute-hyphenation': [
  50. 'error',
  51. 'always',
  52. {
  53. ignore: [],
  54. },
  55. ],
  56. 'vue/attributes-order': 'off',
  57. 'vue/block-order': [
  58. 'error',
  59. {
  60. order: ['script', 'template', 'style'],
  61. },
  62. ],
  63. 'vue/component-name-in-template-casing': ['error', 'PascalCase'],
  64. 'vue/component-options-name-casing': ['error', 'PascalCase'],
  65. 'vue/custom-event-name-casing': ['error', 'camelCase'],
  66. 'vue/define-macros-order': [
  67. 'error',
  68. {
  69. order: [
  70. 'defineOptions',
  71. 'defineProps',
  72. 'defineEmits',
  73. 'defineSlots',
  74. ],
  75. },
  76. ],
  77. 'vue/dot-location': ['error', 'property'],
  78. 'vue/dot-notation': ['error', { allowKeywords: true }],
  79. 'vue/eqeqeq': ['error', 'smart'],
  80. 'vue/html-closing-bracket-newline': 'error',
  81. 'vue/html-indent': 'off',
  82. // 'vue/html-indent': ['error', 2],
  83. 'vue/html-quotes': ['error', 'double'],
  84. 'vue/html-self-closing': [
  85. 'error',
  86. {
  87. html: {
  88. component: 'always',
  89. normal: 'never',
  90. void: 'always',
  91. },
  92. math: 'always',
  93. svg: 'always',
  94. },
  95. ],
  96. 'vue/max-attributes-per-line': 'off',
  97. 'vue/multi-word-component-names': 'off',
  98. 'vue/multiline-html-element-content-newline': 'error',
  99. 'vue/no-empty-pattern': 'error',
  100. 'vue/no-extra-parens': ['error', 'functions'],
  101. 'vue/no-irregular-whitespace': 'error',
  102. 'vue/no-loss-of-precision': 'error',
  103. 'vue/no-reserved-component-names': 'off',
  104. 'vue/no-restricted-syntax': [
  105. 'error',
  106. 'DebuggerStatement',
  107. 'LabeledStatement',
  108. 'WithStatement',
  109. ],
  110. 'vue/no-restricted-v-bind': ['error', '/^v-/'],
  111. 'vue/no-sparse-arrays': 'error',
  112. 'vue/no-unused-refs': 'error',
  113. 'vue/no-useless-v-bind': 'error',
  114. 'vue/object-shorthand': [
  115. 'error',
  116. 'always',
  117. {
  118. avoidQuotes: true,
  119. ignoreConstructors: false,
  120. },
  121. ],
  122. 'vue/one-component-per-file': 'error',
  123. 'vue/prefer-import-from-vue': 'error',
  124. 'vue/prefer-separate-static-class': 'error',
  125. 'vue/prefer-template': 'error',
  126. 'vue/prop-name-casing': ['error', 'camelCase'],
  127. 'vue/require-default-prop': 'error',
  128. 'vue/require-explicit-emits': 'error',
  129. 'vue/require-prop-types': 'off',
  130. 'vue/script-setup-uses-vars': 'error',
  131. 'vue/singleline-html-element-content-newline': 'off',
  132. 'vue/space-infix-ops': 'error',
  133. 'vue/space-unary-ops': ['error', { nonwords: false, words: true }],
  134. 'vue/v-on-event-hyphenation': [
  135. 'error',
  136. 'always',
  137. {
  138. autofix: true,
  139. ignore: [],
  140. },
  141. ],
  142. },
  143. },
  144. ];
  145. }