11import * as fs from 'node:fs'
22import * as path from 'node:path'
33
4- import type { Linter } from 'eslint'
5-
64import createESLintConfig from '@vue/create-eslint-config'
75
86import sortDependencies from './sortDependencies'
@@ -15,29 +13,23 @@ export default function renderEslint(
1513 rootDir ,
1614 { needsTypeScript, needsVitest, needsCypress, needsCypressCT, needsPrettier, needsPlaywright }
1715) {
18- const { additionalConfig , additionalDependencies } = getAdditionalConfigAndDependencies ( {
16+ const additionalConfigs = getAdditionalConfigs ( {
1917 needsVitest,
2018 needsCypress,
2119 needsCypressCT,
2220 needsPlaywright
2321 } )
2422
2523 const { pkg, files } = createESLintConfig ( {
26- vueVersion : '3.x' ,
27- // we currently don't support other style guides
2824 styleGuide : 'default' ,
2925 hasTypeScript : needsTypeScript ,
3026 needsPrettier,
3127
32- additionalConfig,
33- additionalDependencies
28+ additionalConfigs
3429 } )
3530
3631 const scripts : Record < string , string > = {
37- // Note that we reuse .gitignore here to avoid duplicating the configuration
38- lint : needsTypeScript
39- ? 'eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore'
40- : 'eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore'
32+ lint : 'eslint . --fix'
4133 }
4234
4335 // Theoretically, we could add Prettier without requring ESLint.
@@ -54,62 +46,90 @@ export default function renderEslint(
5446 const packageJsonPath = path . resolve ( rootDir , 'package.json' )
5547 const existingPkg = JSON . parse ( fs . readFileSync ( packageJsonPath , 'utf8' ) )
5648 const updatedPkg = sortDependencies ( deepMerge ( deepMerge ( existingPkg , pkg ) , { scripts } ) )
57- fs . writeFileSync ( packageJsonPath , JSON . stringify ( updatedPkg , null , 2 ) + '\n' , 'utf-8 ' )
49+ fs . writeFileSync ( packageJsonPath , JSON . stringify ( updatedPkg , null , 2 ) + '\n' , 'utf8 ' )
5850
59- // write to .eslintrc.cjs , .prettierrc.json, etc.
51+ // write to eslint.config.mjs , .prettierrc.json, .editorconfig , etc.
6052 for ( const [ fileName , content ] of Object . entries ( files ) ) {
6153 const fullPath = path . resolve ( rootDir , fileName )
62- fs . writeFileSync ( fullPath , content as string , 'utf-8 ' )
54+ fs . writeFileSync ( fullPath , content as string , 'utf8 ' )
6355 }
6456}
6557
58+ type ConfigItemInESLintTemplate = {
59+ importer : string
60+ content : string
61+ }
62+ type AdditionalConfig = {
63+ devDependencies : Record < string , string >
64+ beforeVuePlugin ?: Array < ConfigItemInESLintTemplate >
65+ afterVuePlugin ?: Array < ConfigItemInESLintTemplate >
66+ }
67+ type AdditionalConfigArray = Array < AdditionalConfig >
68+
6669// visible for testing
67- export function getAdditionalConfigAndDependencies ( {
70+ export function getAdditionalConfigs ( {
6871 needsVitest,
6972 needsCypress,
7073 needsCypressCT,
7174 needsPlaywright
7275} ) {
73- const additionalConfig : Linter . Config = { }
74- const additionalDependencies = { }
76+ const additionalConfigs : AdditionalConfigArray = [ ]
7577
7678 if ( needsVitest ) {
77- additionalConfig . overrides = [
78- {
79- files : [ 'src/**/*.{test,spec}.{js,ts,jsx,tsx}' ] ,
80- extends : [ 'plugin:@vitest/legacy-recommended' ]
81- }
82- ]
83-
84- additionalDependencies [ '@vitest/eslint-plugin' ] = eslintDeps [ '@vitest/eslint-plugin' ]
79+ additionalConfigs . push ( {
80+ devDependencies : { '@vitest/eslint-plugin' : eslintDeps [ '@vitest/eslint-plugin' ] } ,
81+ afterVuePlugin : [
82+ {
83+ importer : `import pluginVitest from '@vitest/eslint-plugin'` ,
84+ content : `
85+ {
86+ ...pluginVitest.configs['recommended'],
87+ files: ['src/**/__tests__/*'],
88+ },`
89+ }
90+ ]
91+ } )
8592 }
8693
8794 if ( needsCypress ) {
88- additionalConfig . overrides = [
89- {
90- files : needsCypressCT
91- ? [
92- '**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}' ,
93- 'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}' ,
94- 'cypress/support/**/*.{js,ts,jsx,tsx}'
95- ]
96- : [ 'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}' , 'cypress/support/**/*.{js,ts,jsx,tsx}' ] ,
97- extends : [ 'plugin:cypress/recommended' ]
98- }
99- ]
100-
101- additionalDependencies [ 'eslint-plugin-cypress' ] = eslintDeps [ 'eslint-plugin-cypress' ]
95+ additionalConfigs . push ( {
96+ devDependencies : { 'eslint-plugin-cypress' : eslintDeps [ 'eslint-plugin-cypress' ] } ,
97+ afterVuePlugin : [
98+ {
99+ importer : "import pluginCypress from 'eslint-plugin-cypress/flat'" ,
100+ content : `
101+ {
102+ ...pluginCypress.configs.recommended,
103+ files: [
104+ ${ [
105+ ...( needsCypressCT ? [ "'**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}'," ] : [ ] ) ,
106+ 'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}' ,
107+ 'cypress/support/**/*.{js,ts,jsx,tsx}'
108+ ]
109+ . map ( JSON . stringify . bind ( JSON ) )
110+ . join ( ',\n ' ) }
111+ ],
112+ },`
113+ }
114+ ]
115+ } )
102116 }
103117
104118 if ( needsPlaywright ) {
105- additionalConfig . overrides = [
106- {
107- files : [ 'e2e/**/*.{test,spec}.{js,ts,jsx,tsx}' ] ,
108- extends : [ 'plugin:playwright/recommended' ]
109- }
110- ]
111-
112- additionalDependencies [ 'eslint-plugin-playwright' ] = eslintDeps [ 'eslint-plugin-playwright' ]
119+ additionalConfigs . push ( {
120+ devDependencies : { 'eslint-plugin-playwright' : eslintDeps [ 'eslint-plugin-playwright' ] } ,
121+ afterVuePlugin : [
122+ {
123+ importer : "import pluginPlaywright from 'eslint-plugin-playwright'" ,
124+ content : `
125+ {
126+ ...pluginPlaywright.configs['flat/recommended'],
127+ files: ['e2e/**/*.{test,spec}.{js,ts,jsx,tsx}'],
128+ },`
129+ }
130+ ]
131+ } )
113132 }
114- return { additionalConfig, additionalDependencies }
133+
134+ return additionalConfigs
115135}
0 commit comments