@@ -52,9 +52,12 @@ export function deepMerge (target, obj) {
52
52
// This is also used in `create-vue`
53
53
export default function createConfig ( {
54
54
vueVersion = '3.x' , // '2.x' | '3.x' (TODO: 2.7 / vue-demi)
55
+ configFormat = 'eslintrc' , // eslintrc | flat
55
56
56
- styleGuide = 'default' , // default | airbnb | typescript
57
- hasTypeScript = false , // js | ts
57
+ filePatterns = [ ] , // flat format only - e.g. '**/*.vue', '**/*.js', etc.
58
+
59
+ styleGuide = 'default' , // default | airbnb | standard
60
+ hasTypeScript = false , // true | false
58
61
needsPrettier = false , // true | false
59
62
60
63
additionalConfig = { } , // e.g. Cypress, createAliasSetting for Airbnb, etc.
@@ -69,13 +72,18 @@ export default function createConfig ({
69
72
addDependency ( 'eslint' )
70
73
addDependency ( 'eslint-plugin-vue' )
71
74
72
- if ( styleGuide !== 'default' || hasTypeScript || needsPrettier ) {
75
+ if ( configFormat === 'flat' ) {
76
+ addDependency ( '@eslint/eslintrc' )
77
+ addDependency ( '@eslint/js' )
78
+ } else if ( styleGuide !== 'default' || hasTypeScript || needsPrettier ) {
73
79
addDependency ( '@rushstack/eslint-patch' )
74
80
}
75
81
76
82
const language = hasTypeScript ? 'typescript' : 'javascript'
77
83
78
- const eslintConfig = {
84
+ const flatConfigExtends = [ ]
85
+ const flatConfigImports = [ ]
86
+ const eslintrcConfig = {
79
87
root : true ,
80
88
extends : [
81
89
vueVersion . startsWith ( '2' )
@@ -85,49 +93,75 @@ export default function createConfig ({
85
93
}
86
94
const addDependencyAndExtend = ( name ) => {
87
95
addDependency ( name )
88
- eslintConfig . extends . push ( name )
96
+ eslintrcConfig . extends . push ( name )
89
97
}
90
98
91
99
switch ( `${ styleGuide } -${ language } ` ) {
92
100
case 'default-javascript' :
93
- eslintConfig . extends . push ( 'eslint:recommended' )
101
+ eslintrcConfig . extends . push ( 'eslint:recommended' )
102
+ flatConfigImports . push ( `import js from '@eslint/js'` )
103
+ flatConfigExtends . push ( 'js.configs.recommended' )
94
104
break
95
105
case 'default-typescript' :
96
- eslintConfig . extends . push ( 'eslint:recommended' )
106
+ eslintrcConfig . extends . push ( 'eslint:recommended' )
107
+ flatConfigImports . push ( `import js from '@eslint/js'` )
108
+ flatConfigExtends . push ( 'js.configs.recommended' )
97
109
addDependencyAndExtend ( '@vue/eslint-config-typescript' )
110
+ flatConfigExtends . push ( `...compat.extends('@vue/eslint-config-typescript')` )
98
111
break
99
112
case 'airbnb-javascript' :
100
113
case 'standard-javascript' :
101
114
addDependencyAndExtend ( `@vue/eslint-config-${ styleGuide } ` )
115
+ flatConfigExtends . push ( `...compat.extends('@vue/eslint-config-${ styleGuide } ')` )
102
116
break
103
117
case 'airbnb-typescript' :
104
118
case 'standard-typescript' :
105
119
addDependencyAndExtend ( `@vue/eslint-config-${ styleGuide } -with-typescript` )
120
+ flatConfigExtends . push ( `...compat.extends('@vue/eslint-config-${ styleGuide } -with-typescript')` )
106
121
break
107
122
default :
108
123
throw new Error ( `unexpected combination of styleGuide and language: ${ styleGuide } -${ language } ` )
109
124
}
110
125
126
+ flatConfigImports . push ( `import pluginVue from 'eslint-plugin-vue'` )
127
+ flatConfigExtends . push (
128
+ vueVersion . startsWith ( '2' )
129
+ ? `...pluginVue.configs['flat/vue2-essential']`
130
+ : `...pluginVue.configs['flat/essential']`
131
+ )
132
+
111
133
deepMerge ( pkg . devDependencies , additionalDependencies )
112
- deepMerge ( eslintConfig , additionalConfig )
134
+ deepMerge ( eslintrcConfig , additionalConfig )
135
+
136
+ const flatConfigEntry = {
137
+ files : filePatterns
138
+ }
139
+ deepMerge ( flatConfigEntry , additionalConfig )
113
140
114
141
if ( needsPrettier ) {
115
142
addDependency ( 'prettier' )
116
143
addDependency ( '@vue/eslint-config-prettier' )
117
- eslintConfig . extends . push ( '@vue/eslint-config-prettier/skip-formatting' )
144
+ eslintrcConfig . extends . push ( '@vue/eslint-config-prettier/skip-formatting' )
145
+ flatConfigExtends . push ( `...compat.extends('@vue/eslint-config-prettier/skip-formatting')` )
118
146
}
119
147
148
+ const configFilename = configFormat === 'flat'
149
+ ? 'eslint.config.js'
150
+ : '.eslintrc.cjs'
120
151
const files = {
121
- '.eslintrc.cjs' : ''
152
+ [ configFilename ] : ''
122
153
}
123
154
124
155
if ( styleGuide === 'default' ) {
125
156
// Both Airbnb & Standard have already set `env: node`
126
- files [ '.eslintrc.cjs' ] += '/* eslint-env node */\n'
157
+ files [ configFilename ] += '/* eslint-env node */\n'
127
158
128
159
// Both Airbnb & Standard have already set `ecmaVersion`
129
160
// The default in eslint-plugin-vue is 2020, which doesn't support top-level await
130
- eslintConfig . parserOptions = {
161
+ eslintrcConfig . parserOptions = {
162
+ ecmaVersion : 'latest'
163
+ }
164
+ flatConfigEntry . languageOptions = {
131
165
ecmaVersion : 'latest'
132
166
}
133
167
}
@@ -136,7 +170,33 @@ export default function createConfig ({
136
170
files [ '.eslintrc.cjs' ] += "require('@rushstack/eslint-patch/modern-module-resolution')\n\n"
137
171
}
138
172
139
- files [ '.eslintrc.cjs' ] += `module.exports = ${ stringifyJS ( eslintConfig , styleGuide ) } \n`
173
+ // eslint.config.js | .eslintrc.cjs
174
+ if ( configFormat === 'flat' ) {
175
+ files [ 'eslint.config.js' ] += "import path from 'node:path'\n"
176
+ files [ 'eslint.config.js' ] += "import { fileURLToPath } from 'node:url'\n\n"
177
+
178
+ flatConfigImports . forEach ( ( pkgImport ) => {
179
+ files [ 'eslint.config.js' ] += `${ pkgImport } \n`
180
+ } )
181
+ files [ 'eslint.config.js' ] += '\n'
182
+
183
+ // neccesary for compatibility until all packages support flat config
184
+ files [ 'eslint.config.js' ] += 'const __filename = fileURLToPath(import.meta.url)\n'
185
+ files [ 'eslint.config.js' ] += 'const __dirname = path.dirname(__filename)\n'
186
+ files [ 'eslint.config.js' ] += 'const compat = new FlatCompat({\n'
187
+ files [ 'eslint.config.js' ] += ' baseDirectory: __dirname\n'
188
+ files [ 'eslint.config.js' ] += '})\n\n'
189
+
190
+ files [ 'eslint.config.js' ] += 'export default [\n'
191
+ flatConfigExtends . forEach ( ( usage ) => {
192
+ files [ 'eslint.config.js' ] += ` ${ usage } ,\n`
193
+ } )
194
+
195
+ const [ , ...keep ] = stringifyJS ( [ flatConfigEntry ] , styleGuide ) . split ( '{' )
196
+ files [ 'eslint.config.js' ] += ` {${ keep . join ( '{' ) } \n`
197
+ } else {
198
+ files [ '.eslintrc.cjs' ] += `module.exports = ${ stringifyJS ( eslintrcConfig , styleGuide ) } \n`
199
+ }
140
200
141
201
// .editorconfig & .prettierrc.json
142
202
if ( editorconfigs [ styleGuide ] ) {
0 commit comments