@mikey-pro/eslint-config-vue 7.5.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +284 -31
  2. package/package.json +31 -5
package/index.js CHANGED
@@ -1,17 +1,21 @@
1
- const baseConfig = require('@mikey-pro/eslint-config');
1
+ import baseConfig from '@mikey-pro/eslint-config';
2
+ import vuePlugin from 'eslint-plugin-vue';
3
+ import vueRecommended from 'eslint-plugin-vue/lib/configs/vue3-recommended.js';
2
4
 
3
- module.exports = {
5
+ const vueConfig = [
4
6
  ...baseConfig,
5
- overrides: [
6
- ...baseConfig.overrides,
7
- {
8
- extends: ['plugin:vue/vue3-recommended'],
9
- files: ['*.vue'],
7
+ {
8
+ files: ['*.vue'],
9
+ languageOptions: {
10
10
  parser: 'vue-eslint-parser',
11
11
  parserOptions: {
12
+ parser: {
13
+ js: '@babel/eslint-parser',
14
+ ts: '@typescript-eslint/parser',
15
+ '<template>': 'espree'
16
+ },
12
17
  babelOptions: {
13
18
  plugins: [
14
- 'eslint-plugin-vue',
15
19
  [
16
20
  '@babel/plugin-transform-react-jsx',
17
21
  {
@@ -35,29 +39,278 @@ module.exports = {
35
39
  ecmaVersion: 'latest',
36
40
  requireConfigFile: false,
37
41
  sourceType: 'module',
42
+ extraFileExtensions: ['.vue'],
43
+ vueFeatures: {
44
+ filter: true,
45
+ interpolationAsNonHTML: false,
46
+ styleCSSVariableInjection: true
47
+ }
38
48
  },
39
- rules: {
40
- 'vue/component-tags-order': [
41
- 'warn',
42
- {
43
- order: [['script', 'template'], 'style'],
44
- },
45
- ],
46
- 'vue/html-self-closing': [
47
- 'warn',
48
- {
49
- html: {
50
- component: 'always',
51
- normal: 'always',
52
- void: 'always',
53
- },
54
- math: 'always',
55
- svg: 'always',
49
+ },
50
+ plugins: {
51
+ vue: vuePlugin,
52
+ },
53
+ rules: {
54
+ ...vueRecommended.rules,
55
+
56
+ // Vue 3 Composition API
57
+ 'vue/define-macros-order': ['warn', {
58
+ order: ['defineProps', 'defineEmits']
59
+ }],
60
+ 'vue/define-props-declaration': ['error', 'type-based'],
61
+ 'vue/component-api-style': ['error', ['script-setup', 'composition']],
62
+ 'vue/no-ref-object-destructure': 'error',
63
+ 'vue/no-setup-props-destructure': 'error',
64
+
65
+ // Best Practices
66
+ 'vue/block-order': ['error', {
67
+ order: ['script', 'template', 'style']
68
+ }],
69
+ 'vue/component-name-in-template-casing': ['error', 'PascalCase'],
70
+ 'vue/no-duplicate-attr-inheritance': 'error',
71
+ 'vue/no-useless-v-bind': 'error',
72
+ 'vue/prefer-separate-static-class': 'error',
73
+
74
+ // Performance
75
+ 'vue/no-async-in-computed-properties': 'error',
76
+ 'vue/no-side-effects-in-computed-properties': 'error',
77
+ 'vue/no-static-inline-styles': 'warn',
78
+
79
+ // Type Safety
80
+ 'vue/component-definition-name-casing': ['error', 'PascalCase'],
81
+ 'vue/match-component-file-name': ['error', {
82
+ extensions: ['vue'],
83
+ shouldMatchCase: true
84
+ }],
85
+ 'vue/component-options-name-casing': ['error', 'PascalCase'],
86
+
87
+ // Best Practices
88
+ 'vue/prefer-import-from-vue': 'error',
89
+ 'vue/no-unused-refs': 'warn',
90
+ 'vue/no-required-prop-with-default': 'error',
91
+ 'vue/require-typed-ref': 'error',
92
+ 'vue/valid-define-props': 'error',
93
+
94
+ // Existing rules...
95
+ 'vue/component-tags-order': [
96
+ 'warn',
97
+ {
98
+ order: [['script', 'template'], 'style'],
99
+ },
100
+ ],
101
+ 'vue/html-self-closing': [
102
+ 'warn',
103
+ {
104
+ html: {
105
+ component: 'always',
106
+ normal: 'always',
107
+ void: 'always',
56
108
  },
57
- ],
58
- 'vue/singleline-html-element-content-newline': 'off',
59
- 'prettier/prettier': ['warn', { parser: 'vue' }],
60
- },
109
+ math: 'always',
110
+ svg: 'always',
111
+ },
112
+ ],
113
+ 'vue/singleline-html-element-content-newline': 'off',
114
+ 'prettier/prettier': ['warn', { parser: 'vue' }],
115
+
116
+ // Enhanced Type Safety
117
+ 'vue/define-emits-declaration': ['error', 'type-based'],
118
+ 'vue/no-export-in-script-setup': 'error',
119
+
120
+ // Script Setup
121
+ 'vue/script-setup-uses-vars': 'error',
122
+ 'vue/no-undef-components': ['error', {
123
+ ignorePatterns: ['router-view', 'router-link'],
124
+ }],
125
+
126
+ // Performance
127
+ 'vue/no-unused-properties': ['warn', {
128
+ groups: ['props', 'data', 'computed', 'methods', 'setup'],
129
+ }],
130
+
131
+ // Composables
132
+ 'vue/define-macros-order': ['error', {
133
+ order: [
134
+ 'defineOptions',
135
+ 'defineProps',
136
+ 'defineEmits',
137
+ 'defineSlots',
138
+ 'withDefaults'
139
+ ]
140
+ }],
141
+ 'vue/custom-event-name-casing': ['error', 'camelCase', {
142
+ ignore: []
143
+ }],
144
+
145
+ // Security
146
+ 'vue/no-unescaped-html': 'error',
147
+ 'vue/no-potential-component-option-typo': 'error',
148
+ 'vue/no-restricted-component-options': ['error', {
149
+ name: 'data',
150
+ message: 'Use setup() instead'
151
+ }],
152
+ 'vue/no-restricted-v-bind': ['error', '/^v-/'],
153
+ 'vue/no-restricted-html-elements': [
154
+ 'error',
155
+ 'iframe',
156
+ 'object',
157
+ 'embed'
158
+ ],
159
+ 'vue/no-use-v-if-with-v-for': ['error', {
160
+ allowUsingIterationVar: false
161
+ }],
162
+
163
+ // Optimization
164
+ 'vue/no-unused-properties': ['error', {
165
+ groups: ['props', 'data', 'computed', 'methods', 'setup'],
166
+ deepData: true
167
+ }],
168
+ 'vue/no-unused-refs': 'error',
169
+ 'vue/valid-next-tick': 'error',
170
+
171
+ // Performance
172
+ 'vue/no-parsing-error': ['error', {
173
+ 'invalid-first-character-of-tag-name': false
174
+ }],
175
+ 'vue/no-unused-components': ['error', {
176
+ ignoreWhenBindingPresent: true
177
+ }],
178
+ 'vue/valid-v-slot': ['error', {
179
+ allowModifiers: true
180
+ }],
181
+
182
+ // Advanced Vue 3 Features
183
+ 'vue/prefer-true-attribute-shorthand': ['error', 'always'],
184
+ 'vue/v-on-function-call': ['error', 'never'],
185
+ 'vue/no-empty-component-block': 'error',
186
+ 'vue/multi-word-component-names': ['error', {
187
+ ignores: ['index', 'default']
188
+ }],
189
+
190
+ // Performance Optimizations
191
+ 'vue/no-deprecated-filter': 'error',
192
+ 'vue/prefer-template': 'error',
193
+ 'vue/no-useless-mustaches': 'error',
194
+ 'vue/no-empty-pattern': 'error',
195
+
196
+ // Type Safety
197
+ 'vue/block-tag-newline': ['error', {
198
+ singleline: 'always',
199
+ multiline: 'always',
200
+ maxEmptyLines: 1
201
+ }],
202
+
203
+ // Enhanced Performance
204
+ 'vue/no-child-content': ['error', {
205
+ 'ignoreSlots': ['default']
206
+ }],
207
+ 'vue/no-duplicate-attr-inheritance': ['error', {
208
+ 'ignoreKeys': ['class', 'style']
209
+ }],
210
+ 'vue/prefer-define-options': 'error',
211
+
212
+ // Better Type Safety
213
+ 'vue/define-props-declaration': ['error', {
214
+ 'type-based': true,
215
+ 'required': true
216
+ }],
217
+ 'vue/define-emits-declaration': ['error', {
218
+ 'type-based': true
219
+ }],
220
+
221
+ // Component Organization
222
+ 'vue/block-order': ['error', {
223
+ 'order': [
224
+ 'script:not([setup])',
225
+ 'script[setup]',
226
+ 'template',
227
+ 'style:not([scoped])',
228
+ 'style[scoped]'
229
+ ]
230
+ }],
231
+
232
+ // Vue 3.4+ Features
233
+ 'vue/next-tick-style': ['error', 'promise'],
234
+ 'vue/prefer-prop-type-inference': 'error',
235
+ 'vue/require-typed-object-prop': 'error',
236
+ 'vue/no-deprecated-model-definition': ['error', {
237
+ allowVue3Compat: false
238
+ }],
239
+
240
+ // Memory Optimization
241
+ 'vue/no-ref-as-operand': 'error',
242
+ 'vue/prefer-import-from-vue': ['error', {
243
+ disallowVuePath: true
244
+ }],
245
+ 'vue/no-side-effects-in-computed-properties': ['error', {
246
+ enforceForEventHandlers: true
247
+ }],
248
+
249
+ // Strict Mode Features
250
+ 'vue/component-name-in-template-casing': ['error', 'PascalCase', {
251
+ registeredComponentsOnly: true,
252
+ ignores: []
253
+ }],
254
+ 'vue/define-macros-order': ['error', {
255
+ order: [
256
+ 'defineOptions',
257
+ 'defineSlots',
258
+ 'defineEmits',
259
+ 'defineModel',
260
+ 'defineProps'
261
+ ]
262
+ }],
263
+
264
+ // Performance Optimizations
265
+ 'vue/no-static-style': 'error',
266
+ 'vue/no-undef-properties': ['error', {
267
+ ignores: ['/^\\$/']
268
+ }],
269
+ 'vue/valid-define-options': 'error',
270
+
271
+ // Script Setup Safety
272
+ 'vue/script-setup-uses-vars': ['error', {
273
+ checkTemplate: true
274
+ }],
275
+ 'vue/valid-define-options': ['error', {
276
+ presetName: 'script-setup'
277
+ }],
278
+
279
+ // Performance Optimizations
280
+ 'vue/prefer-define-options': ['error', {
281
+ presets: ['composition-api', 'script-setup']
282
+ }],
283
+ 'vue/no-duplicate-attr-inheritance': ['error', {
284
+ ignoreKeys: ['class', 'style', 'key', 'ref']
285
+ }],
286
+
287
+ // Type Safety
288
+ 'vue/no-setup-props-reactivity-loss': 'error',
289
+ 'vue/no-watch-after-await': 'error',
290
+ 'vue/prefer-prop-type-inference': ['error', {
291
+ allowAny: false
292
+ }]
61
293
  },
62
- ],
63
- };
294
+ settings: {
295
+ ...baseConfig.settings,
296
+ 'import/resolver': {
297
+ typescript: {
298
+ alwaysTryTypes: true,
299
+ project: ['./tsconfig.json', './tsconfig.*.json']
300
+ }
301
+ },
302
+ 'import/core-modules': ['vue', '@vue/composition-api', '@vue/runtime-core', '@vue/runtime-dom'],
303
+ 'import/parsers': {
304
+ '@typescript-eslint/parser': ['.ts', '.tsx', '.vue', '.d.ts'],
305
+ },
306
+ 'vue': {
307
+ version: '3.4'
308
+ }
309
+ }
310
+ },
311
+ ];
312
+
313
+ export default vueConfig;
314
+ if (typeof module !== 'undefined' && module.exports) {
315
+ module.exports = vueConfig;
316
+ }
package/package.json CHANGED
@@ -1,13 +1,35 @@
1
1
  {
2
2
  "name": "@mikey-pro/eslint-config-vue",
3
- "version": "7.5.0",
3
+ "version": "8.0.0",
4
4
  "description": "Mikey Pro ESLint Vue configuration",
5
+ "type": "module",
5
6
  "main": "index.js",
6
7
  "dependencies": {
8
+ "@babel/core": "^7.24.0",
9
+ "@babel/eslint-parser": "^7.24.0",
7
10
  "@babel/plugin-transform-react-jsx": "^7.23.4",
8
- "@vue/babel-plugin-jsx": "^1.2.2",
9
- "eslint-plugin-vue": "^9.25",
10
- "vue-eslint-parser": "^9.4"
11
+ "@babel/preset-env": "^7.24.0",
12
+ "@mikey-pro/eslint-config": "workspace:^",
13
+ "@typescript-eslint/parser": "^7.0.0",
14
+ "eslint-plugin-vue": "^9.22.0",
15
+ "vue-eslint-parser": "^9.4.2"
16
+ },
17
+ "peerDependencies": {
18
+ "@mikey-pro/eslint-config": "workspace:^",
19
+ "@types/node": ">=18.0.0",
20
+ "@vue/compiler-sfc": "^3.4.0",
21
+ "eslint": "^8.57.0",
22
+ "prettier": "^3.2.0",
23
+ "typescript": ">=5.0.0",
24
+ "vue": "^3.4.0"
25
+ },
26
+ "peerDependenciesMeta": {
27
+ "@types/node": {
28
+ "optional": true
29
+ },
30
+ "typescript": {
31
+ "optional": true
32
+ }
11
33
  },
12
34
  "files": [
13
35
  "index.js",
@@ -35,9 +57,13 @@
35
57
  "config",
36
58
  "style-guide",
37
59
  "style",
38
- "guide"
60
+ "guide",
61
+ "vue"
39
62
  ],
40
63
  "author": "Mikl Wolfe <wolfe@mikl.io> (https://mikl.io)",
64
+ "engines": {
65
+ "node": ">=18.0.0"
66
+ },
41
67
  "browserslist": [
42
68
  "defaults"
43
69
  ]