]> git.ipfire.org Git - thirdparty/vuejs/create-vue.git/commitdiff
feat: move all eslint-related stuff to main repo (#875)
authorHaoqun Jiang <github@haoqun.me>
Thu, 25 Dec 2025 06:20:21 +0000 (15:20 +0900)
committerGitHub <noreply@github.com>
Thu, 25 Dec 2025 06:20:21 +0000 (15:20 +0900)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Haoqun Jiang <haoqunjiang@gmail.com>
Co-authored-by: Zhousg <zhoushugang@itcast.cn>
Co-authored-by: Thorsten Lünborg <t.luenborg@googlemail.com>
Co-authored-by: Cédric Exbrayat <cexbrayat@users.noreply.github.com>
Co-authored-by: Anton Lilleby <antonlilleby@Anton-sin-MacBook-Pro.local>
Co-authored-by: Dmytro Tsysar <1106994+idmytro@users.noreply.github.com>
Co-authored-by: btea <2356281422@qq.com>
It's becoming harder and harder to maintain `@vue/create-eslint-config` separately as the tooling space evolves. So I decided to merge it back to the main repo.

The functionality remains mostly the same, except that we now explicitly generate an oxlint config file instead of passing options via CLI args.
Previously, I was adding `--ignore-path .gitignore` to oxlint commands, but it turns out `.gitignore` is automatically respected inside a git repo[^1]. So I skipped that part.

The general idea of this refactoring is that each general feature should be self-contained inside its own template folder (`linting` and `formatting` in this PR, in parallel with `tsconfig` and other stuff), so that in the future we can test them independently or even publish them as separate packages again. Still a lot of work to do in that direction, but this is a start.

[^1]: https://oxc.rs/docs/guide/usage/linter/cli.html#ignore-files

43 files changed:
.editorconfig [new file with mode: 0644]
LICENSE
__test__/renderEslint.spec.ts [deleted file]
index.ts
package.json
pnpm-lock.yaml
rolldown.config.ts
template/config/typescript/package.json
template/eslint/package.json [deleted file]
template/formatting/oxfmt/.vscode/extensions.json [moved from template/config/oxlint/.vscode/extensions.json with 100% similarity]
template/formatting/oxfmt/.vscode/settings.json [new file with mode: 0644]
template/formatting/oxfmt/_oxfmtrc.jsonc [new file with mode: 0644]
template/formatting/oxfmt/_prettierrc.json [new file with mode: 0644]
template/formatting/oxfmt/package.json [new file with mode: 0644]
template/formatting/prettier/.vscode/extensions.json [moved from template/config/prettier/.vscode/extensions.json with 100% similarity]
template/formatting/prettier/.vscode/settings.json [moved from template/config/prettier/.vscode/settings.json with 100% similarity]
template/formatting/prettier/_prettierrc.json [moved from template/config/prettier/_prettierrc.json with 100% similarity]
template/formatting/prettier/package.json [moved from template/config/prettier/package.json with 100% similarity]
template/linting/base/.vscode/extensions.json [moved from template/config/eslint/.vscode/extensions.json with 100% similarity]
template/linting/base/.vscode/settings.json [moved from template/config/eslint/.vscode/settings.json with 100% similarity]
template/linting/base/_editorconfig [new file with mode: 0644]
template/linting/base/_gitattributes [moved from template/config/prettier/_gitattributes with 100% similarity]
template/linting/base/package.json [new file with mode: 0644]
template/linting/core/js/eslint.config.js.data.mjs [new file with mode: 0644]
template/linting/core/js/eslint.config.js.ejs [new file with mode: 0644]
template/linting/core/js/package.json [new file with mode: 0644]
template/linting/core/ts/eslint.config.js.data.mjs [new file with mode: 0644]
template/linting/core/ts/eslint.config.js.ejs [new file with mode: 0644]
template/linting/core/ts/package.json [new file with mode: 0644]
template/linting/cypress-ct/eslint.config.js.data.mjs [new file with mode: 0644]
template/linting/cypress/eslint.config.js.data.mjs [new file with mode: 0644]
template/linting/cypress/package.json [new file with mode: 0644]
template/linting/oxlint/.vscode/extensions.json [new file with mode: 0644]
template/linting/oxlint/_ oxlintrc.json [new file with mode: 0644]
template/linting/oxlint/eslint.config.js.data.mjs [new file with mode: 0644]
template/linting/oxlint/package.json [new file with mode: 0644]
template/linting/playwright/eslint.config.js.data.mjs [new file with mode: 0644]
template/linting/playwright/package.json [new file with mode: 0644]
template/linting/prettier/eslint.config.js.data.mjs [new file with mode: 0644]
template/linting/prettier/package.json [new file with mode: 0644]
template/linting/vitest/eslint.config.js.data.mjs [new file with mode: 0644]
template/linting/vitest/package.json [new file with mode: 0644]
utils/renderEslint.ts [deleted file]

diff --git a/.editorconfig b/.editorconfig
new file mode 100644 (file)
index 0000000..ecea360
--- /dev/null
@@ -0,0 +1,6 @@
+[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue}]
+charset = utf-8
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
diff --git a/LICENSE b/LICENSE
index b5a7c2b0f13e725f8c13bf5b642419758e86b8a3..fea80e3de99585a28a41322ebbd85358e7e04f21 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -447,33 +447,4 @@ Repository: git://github.com/mde/ejs.git
 >    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 >    See the License for the specific language governing permissions and
 >    limitations under the License.
->
-
-## @vue/create-eslint-config
-
-License: MIT
-By: Haoqun Jiang
-Repository: git+https://github.com/vuejs/create-eslint-config.git
-
-> MIT License
->
-> Copyright (c) 2022 vuejs
->
-> Permission is hereby granted, free of charge, to any person obtaining a copy
-> of this software and associated documentation files (the "Software"), to deal
-> in the Software without restriction, including without limitation the rights
-> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-> copies of the Software, and to permit persons to whom the Software is
-> furnished to do so, subject to the following conditions:
->
-> The above copyright notice and this permission notice shall be included in all
-> copies or substantial portions of the Software.
->
-> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-> SOFTWARE.
 >
\ No newline at end of file
diff --git a/__test__/renderEslint.spec.ts b/__test__/renderEslint.spec.ts
deleted file mode 100644 (file)
index 4deaf6c..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-import { it, describe, expect } from 'vitest'
-import { getAdditionalConfigs } from '../utils/renderEslint'
-
-describe('renderEslint', () => {
-  it('should get additional dependencies and config with no test flags', () => {
-    const additionalConfigs = getAdditionalConfigs({
-      needsTypeScript: false,
-      needsVitest: false,
-      needsCypress: false,
-      needsCypressCT: false,
-      needsPlaywright: false,
-    })
-    expect(additionalConfigs).toStrictEqual([])
-  })
-
-  it('should get additional dependencies and config with for vitest', () => {
-    const additionalConfigs = getAdditionalConfigs({
-      needsTypeScript: false,
-      needsVitest: true,
-      needsCypress: false,
-      needsCypressCT: false,
-      needsPlaywright: false,
-    })
-    expect(additionalConfigs).toHaveLength(1)
-    const [additionalVitestConfig] = additionalConfigs
-    expect(additionalVitestConfig.devDependencies['@vitest/eslint-plugin']).not.toBeUndefined()
-    expect(additionalVitestConfig.afterVuePlugin).toHaveLength(1)
-    const [additionalVitestPlugin] = additionalVitestConfig.afterVuePlugin!
-    expect(additionalVitestPlugin.importer).toBe(`import pluginVitest from '@vitest/eslint-plugin'`)
-    expect(additionalVitestPlugin.content).toContain('...pluginVitest.configs.recommended')
-    expect(additionalVitestPlugin.content).toContain("files: ['src/**/__tests__/*']")
-  })
-
-  it('should get additional dependencies and config with for cypress', () => {
-    const additionalConfigs = getAdditionalConfigs({
-      needsTypeScript: false,
-      needsVitest: false,
-      needsCypress: true,
-      needsCypressCT: false,
-      needsPlaywright: false,
-    })
-    expect(additionalConfigs).toHaveLength(1)
-    const [additionalCypressConfig] = additionalConfigs
-    expect(additionalCypressConfig.devDependencies['eslint-plugin-cypress']).not.toBeUndefined()
-    expect(additionalCypressConfig.afterVuePlugin).toHaveLength(1)
-    const [additionalCypressPlugin] = additionalCypressConfig.afterVuePlugin!
-    expect(additionalCypressPlugin.importer).toBe(
-      "import pluginCypress from 'eslint-plugin-cypress'",
-    )
-    expect(additionalCypressPlugin.content).toContain('...pluginCypress.configs.recommended')
-    expect(additionalCypressPlugin.content).toContain(
-      "'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}'",
-    )
-    expect(additionalCypressPlugin.content).toContain("'cypress/support/**/*.{js,ts,jsx,tsx}'")
-  })
-
-  it('should get additional dependencies and config with for cypress with component testing', () => {
-    const additionalConfigs = getAdditionalConfigs({
-      needsTypeScript: false,
-      needsVitest: false,
-      needsCypress: true,
-      needsCypressCT: true,
-      needsPlaywright: false,
-    })
-    expect(additionalConfigs).toHaveLength(1)
-    const [additionalCypressConfig] = additionalConfigs
-    expect(additionalCypressConfig.devDependencies['eslint-plugin-cypress']).not.toBeUndefined()
-    expect(additionalCypressConfig.afterVuePlugin).toHaveLength(1)
-    const [additionalCypressPlugin] = additionalCypressConfig.afterVuePlugin!
-    expect(additionalCypressPlugin.importer).toBe(
-      "import pluginCypress from 'eslint-plugin-cypress'",
-    )
-    expect(additionalCypressPlugin.content).toContain('...pluginCypress.configs.recommended')
-    expect(additionalCypressPlugin.content).toContain("'**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}'")
-    expect(additionalCypressPlugin.content).toContain(
-      "'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}'",
-    )
-    expect(additionalCypressPlugin.content).toContain("'cypress/support/**/*.{js,ts,jsx,tsx}'")
-  })
-
-  it('should get additional dependencies and config with for playwright', () => {
-    const additionalConfigs = getAdditionalConfigs({
-      needsTypeScript: false,
-      needsVitest: false,
-      needsCypress: false,
-      needsCypressCT: false,
-      needsPlaywright: true,
-    })
-    expect(additionalConfigs).toHaveLength(1)
-    const [additionalPlaywrightConfig] = additionalConfigs
-    expect(
-      additionalPlaywrightConfig.devDependencies['eslint-plugin-playwright'],
-    ).not.toBeUndefined()
-    expect(additionalPlaywrightConfig.afterVuePlugin).toHaveLength(1)
-    const [additionalPlaywrightPlugin] = additionalPlaywrightConfig.afterVuePlugin!
-    expect(additionalPlaywrightPlugin.importer).toBe(
-      "import pluginPlaywright from 'eslint-plugin-playwright'",
-    )
-    expect(additionalPlaywrightPlugin.content).toContain(
-      "...pluginPlaywright.configs['flat/recommended']",
-    )
-    expect(additionalPlaywrightPlugin.content).toContain(
-      "files: ['e2e/**/*.{test,spec}.{js,ts,jsx,tsx}']",
-    )
-  })
-})
index 4d77d0904b01345db6f656adbf37cf48c2ebc62a..a006f966fc5385a9f1612a93453fea51bbb565b5 100755 (executable)
--- a/index.ts
+++ b/index.ts
@@ -20,7 +20,6 @@ import {
 import generateReadme from './utils/generateReadme'
 import getCommand from './utils/getCommand'
 import getLanguage from './utils/getLanguage'
-import renderEslint from './utils/renderEslint'
 import { trimBoilerplate, removeCSSImport, emptyRouterConfig } from './utils/trimBoilerplate'
 
 import cliPackageJson from './package.json' with { type: 'json' }
@@ -511,25 +510,40 @@ async function init() {
   }
 
   // Render ESLint config
-  if (needsEslint || needsOxlint) {
-    renderEslint(root, {
-      needsTypeScript,
-      needsOxlint,
-      needsVitest,
-      needsCypress,
-      needsCypressCT,
-      needsPrettier,
-      needsPlaywright,
-    })
-    render('config/eslint')
-  }
+  if (needsEslint) {
+    render('linting/base')
 
-  if (needsOxlint) {
-    render('config/oxlint')
+    if (needsTypeScript) {
+      render('linting/core/ts')
+    } else {
+      render('linting/core/js')
+    }
+
+    if (needsCypress) {
+      render('linting/cypress')
+    }
+    if (needsCypressCT) {
+      render('linting/cypress-ct')
+    }
+    if (needsPlaywright) {
+      render('linting/playwright')
+    }
+    if (needsVitest) {
+      render('linting/vitest')
+    }
+
+    // These configs only disable rules, so they should be applied last.
+    if (needsPrettier) {
+      render('linting/prettier')
+    }
+    if (needsOxlint) {
+      render('linting/oxlint')
+    }
   }
 
   if (needsPrettier) {
-    render('config/prettier')
+    render('formatting/prettier')
+    // TODO: add oxfmt option in the next PR
   }
 
   // use rolldown-vite if the feature is enabled
@@ -615,7 +629,7 @@ async function init() {
       root,
       () => {},
       (filepath) => {
-        if (filepath.endsWith('.js') && !filepath.endsWith('eslint.config.js')) {
+        if (filepath.endsWith('.js')) {
           const tsFilePath = filepath.replace(/\.js$/, '.ts')
           if (fs.existsSync(tsFilePath)) {
             fs.unlinkSync(filepath)
@@ -694,7 +708,7 @@ async function init() {
   if (!dotGitDirectoryState.hasDotGitDirectory) {
     outroMessage += `
 ${dim('|')} ${language.infos.optionalGitCommand}
-  
+
    ${bold(green('git init && git add -A && git commit -m "initial commit"'))}`
   }
 
index 9ada06738027792ff654aee94a005bcdc0fdead7..58cc1fc3cf11566617653e4c997e905de0f85e3d 100644 (file)
@@ -45,7 +45,6 @@
     "@types/eslint": "^9.6.1",
     "@types/node": "^24.10.4",
     "@types/prompts": "^2.4.9",
-    "@vue/create-eslint-config": "^0.14.2",
     "@vue/tsconfig": "^0.8.1",
     "ejs": "^3.1.10",
     "husky": "^9.1.7",
index 95b98d686ff205a1f48cc31687952e3c1c9ea3ec..a0f23041e515253b7406f5c8c237d817ea3c4c82 100644 (file)
@@ -23,12 +23,9 @@ importers:
       '@types/prompts':
         specifier: ^2.4.9
         version: 2.4.9
-      '@vue/create-eslint-config':
-        specifier: ^0.14.2
-        version: 0.14.2
       '@vue/tsconfig':
         specifier: ^0.8.1
-        version: 0.8.1(typescript@5.9.2)(vue@3.5.26(typescript@5.9.2))
+        version: 0.8.1(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3))
       ejs:
         specifier: ^3.1.10
         version: 3.1.10
@@ -61,17 +58,17 @@ importers:
     dependencies:
       vue:
         specifier: ^3.5.26
-        version: 3.5.26(typescript@5.9.2)
+        version: 3.5.26(typescript@5.9.3)
     devDependencies:
       '@vitejs/plugin-vue':
         specifier: ^6.0.3
-        version: 6.0.3(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.2))
+        version: 6.0.3(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.3))
       vite:
         specifier: ^7.3.0
         version: 7.3.0(@types/node@24.10.4)(yaml@2.8.1)
       vite-plugin-vue-devtools:
         specifier: ^8.0.5
-        version: 8.0.5(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.2))
+        version: 8.0.5(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.3))
 
   template/config/cypress:
     devDependencies:
@@ -86,7 +83,7 @@ importers:
     dependencies:
       vue:
         specifier: ^3.5.26
-        version: 3.5.26(typescript@5.9.2)
+        version: 3.5.26(typescript@5.9.3)
     devDependencies:
       cypress:
         specifier: ^15.8.1
@@ -96,11 +93,11 @@ importers:
     dependencies:
       vue:
         specifier: ^3.5.26
-        version: 3.5.26(typescript@5.9.2)
+        version: 3.5.26(typescript@5.9.3)
     devDependencies:
       '@vitejs/plugin-vue-jsx':
         specifier: ^5.1.2
-        version: 5.1.2(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.2))
+        version: 5.1.2(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.3))
       vite:
         specifier: ^7.3.0
         version: 7.3.0(@types/node@24.10.4)(yaml@2.8.1)
@@ -109,10 +106,10 @@ importers:
     devDependencies:
       '@nightwatch/vue':
         specifier: ^3.1.2
-        version: 3.1.2(@types/node@24.10.4)(vue@3.5.26(typescript@5.9.2))
+        version: 3.1.2(@types/node@24.10.4)(vue@3.5.26(typescript@5.9.3))
       '@vitejs/plugin-vue':
         specifier: ^6.0.3
-        version: 6.0.3(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.2))
+        version: 6.0.3(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.3))
       chromedriver:
         specifier: ^143.0.3
         version: 143.0.3
@@ -124,7 +121,7 @@ importers:
         version: 3.13.0(chromedriver@143.0.3)(geckodriver@6.1.0)
       ts-node:
         specifier: ^10.9.2
-        version: 10.9.2(@types/node@24.10.4)(typescript@5.9.2)
+        version: 10.9.2(@types/node@24.10.4)(typescript@5.9.3)
       vite:
         specifier: ^7.3.0
         version: 7.3.0(@types/node@24.10.4)(yaml@2.8.1)
@@ -136,7 +133,7 @@ importers:
     dependencies:
       vue:
         specifier: ^3.5.26
-        version: 3.5.26(typescript@5.9.2)
+        version: 3.5.26(typescript@5.9.3)
     devDependencies:
       '@vue/test-utils':
         specifier: ^2.4.6
@@ -146,10 +143,10 @@ importers:
     dependencies:
       pinia:
         specifier: ^3.0.4
-        version: 3.0.4(typescript@5.9.2)(vue@3.5.26(typescript@5.9.2))
+        version: 3.0.4(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3))
       vue:
         specifier: ^3.5.26
-        version: 3.5.26(typescript@5.9.2)
+        version: 3.5.26(typescript@5.9.3)
 
   template/config/playwright:
     devDependencies:
@@ -157,20 +154,14 @@ importers:
         specifier: ^1.57.0
         version: 1.57.0
 
-  template/config/prettier:
-    devDependencies:
-      prettier:
-        specifier: 3.7.4
-        version: 3.7.4
-
   template/config/router:
     dependencies:
       vue:
         specifier: ^3.5.26
-        version: 3.5.26(typescript@5.9.2)
+        version: 3.5.26(typescript@5.9.3)
       vue-router:
         specifier: ^4.6.4
-        version: 4.6.4(vue@3.5.26(typescript@5.9.2))
+        version: 4.6.4(vue@3.5.26(typescript@5.9.3))
 
   template/config/typescript:
     devDependencies:
@@ -181,17 +172,17 @@ importers:
         specifier: ^8.0.4
         version: 8.0.4
       typescript:
-        specifier: ~5.9.0
-        version: 5.9.2
+        specifier: ~5.9.3
+        version: 5.9.3
       vue-tsc:
         specifier: ^3.2.1
-        version: 3.2.1(typescript@5.9.2)
+        version: 3.2.1(typescript@5.9.3)
 
   template/config/vitest:
     dependencies:
       vue:
         specifier: ^3.5.26
-        version: 3.5.26(typescript@5.9.2)
+        version: 3.5.26(typescript@5.9.3)
     devDependencies:
       '@vue/test-utils':
         specifier: ^2.4.6
@@ -210,7 +201,7 @@ importers:
         version: 24.0.3
       '@vue/tsconfig':
         specifier: ^0.8.1
-        version: 0.8.1(typescript@5.9.2)(vue@3.5.26(typescript@5.9.2))
+        version: 0.8.1(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3))
 
   template/tsconfig/vitest:
     devDependencies:
@@ -1379,11 +1370,6 @@ packages:
   '@vue/compiler-ssr@3.5.26':
     resolution: {integrity: sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==}
 
-  '@vue/create-eslint-config@0.14.2':
-    resolution: {integrity: sha512-Cut75X2zJzgYoI3l6yoQVLrYRTmuQMwW9lUtNlIbAFF+KweHb5txEQHMJMxNRCQXaURm8otVUQANhFoO/AvGGQ==}
-    engines: {node: ^16.14.0 || >= 18.0.0}
-    hasBin: true
-
   '@vue/devtools-api@6.6.4':
     resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==}
 
@@ -3805,8 +3791,8 @@ packages:
     resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==}
     engines: {node: '>=8'}
 
-  typescript@5.9.2:
-    resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==}
+  typescript@5.9.3:
+    resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
     engines: {node: '>=14.17'}
     hasBin: true
 
@@ -4901,10 +4887,10 @@ snapshots:
     dependencies:
       archiver: 5.3.2
 
-  '@nightwatch/vue@3.1.2(@types/node@24.10.4)(vue@3.5.26(typescript@5.9.2))':
+  '@nightwatch/vue@3.1.2(@types/node@24.10.4)(vue@3.5.26(typescript@5.9.3))':
     dependencies:
       '@nightwatch/esbuild-utils': 0.2.1
-      '@vitejs/plugin-vue': 4.6.2(vite@4.5.14(@types/node@24.10.4))(vue@3.5.26(typescript@5.9.2))
+      '@vitejs/plugin-vue': 4.6.2(vite@4.5.14(@types/node@24.10.4))(vue@3.5.26(typescript@5.9.3))
       get-port: 5.1.1
       vite: 4.5.14(@types/node@24.10.4)
       vite-plugin-nightwatch: 0.4.6
@@ -5145,7 +5131,7 @@ snapshots:
       '@types/node': 24.10.4
     optional: true
 
-  '@vitejs/plugin-vue-jsx@5.1.2(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.2))':
+  '@vitejs/plugin-vue-jsx@5.1.2(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.3))':
     dependencies:
       '@babel/core': 7.28.5
       '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5)
@@ -5153,20 +5139,20 @@ snapshots:
       '@rolldown/pluginutils': 1.0.0-beta.50
       '@vue/babel-plugin-jsx': 2.0.1(@babel/core@7.28.5)
       vite: 7.3.0(@types/node@24.10.4)(yaml@2.8.1)
-      vue: 3.5.26(typescript@5.9.2)
+      vue: 3.5.26(typescript@5.9.3)
     transitivePeerDependencies:
       - supports-color
 
-  '@vitejs/plugin-vue@4.6.2(vite@4.5.14(@types/node@24.10.4))(vue@3.5.26(typescript@5.9.2))':
+  '@vitejs/plugin-vue@4.6.2(vite@4.5.14(@types/node@24.10.4))(vue@3.5.26(typescript@5.9.3))':
     dependencies:
       vite: 4.5.14(@types/node@24.10.4)
-      vue: 3.5.26(typescript@5.9.2)
+      vue: 3.5.26(typescript@5.9.3)
 
-  '@vitejs/plugin-vue@6.0.3(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.2))':
+  '@vitejs/plugin-vue@6.0.3(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.3))':
     dependencies:
       '@rolldown/pluginutils': 1.0.0-beta.53
       vite: 7.3.0(@types/node@24.10.4)(yaml@2.8.1)
-      vue: 3.5.26(typescript@5.9.2)
+      vue: 3.5.26(typescript@5.9.3)
 
   '@vitest/expect@4.0.16':
     dependencies:
@@ -5350,19 +5336,13 @@ snapshots:
       '@vue/compiler-dom': 3.5.26
       '@vue/shared': 3.5.26
 
-  '@vue/create-eslint-config@0.14.2':
-    dependencies:
-      ejs: 3.1.10
-      enquirer: 2.4.1
-      kolorist: 1.8.0
-
   '@vue/devtools-api@6.6.4': {}
 
   '@vue/devtools-api@7.7.8':
     dependencies:
       '@vue/devtools-kit': 7.7.8
 
-  '@vue/devtools-core@8.0.5(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.2))':
+  '@vue/devtools-core@8.0.5(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.3))':
     dependencies:
       '@vue/devtools-kit': 8.0.5
       '@vue/devtools-shared': 8.0.5
@@ -5370,7 +5350,7 @@ snapshots:
       nanoid: 5.1.5
       pathe: 2.0.3
       vite-hot-client: 2.1.0(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))
-      vue: 3.5.26(typescript@5.9.2)
+      vue: 3.5.26(typescript@5.9.3)
     transitivePeerDependencies:
       - vite
 
@@ -5428,11 +5408,11 @@ snapshots:
       '@vue/shared': 3.5.26
       csstype: 3.2.3
 
-  '@vue/server-renderer@3.5.26(vue@3.5.26(typescript@5.9.2))':
+  '@vue/server-renderer@3.5.26(vue@3.5.26(typescript@5.9.3))':
     dependencies:
       '@vue/compiler-ssr': 3.5.26
       '@vue/shared': 3.5.26
-      vue: 3.5.26(typescript@5.9.2)
+      vue: 3.5.26(typescript@5.9.3)
 
   '@vue/shared@3.5.24': {}
 
@@ -5445,10 +5425,10 @@ snapshots:
       js-beautify: 1.15.1
       vue-component-type-helpers: 2.1.6
 
-  '@vue/tsconfig@0.8.1(typescript@5.9.2)(vue@3.5.26(typescript@5.9.2))':
+  '@vue/tsconfig@0.8.1(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3))':
     optionalDependencies:
-      typescript: 5.9.2
-      vue: 3.5.26(typescript@5.9.2)
+      typescript: 5.9.3
+      vue: 3.5.26(typescript@5.9.3)
 
   '@wdio/logger@9.18.0':
     dependencies:
@@ -7333,12 +7313,12 @@ snapshots:
 
   pify@2.3.0: {}
 
-  pinia@3.0.4(typescript@5.9.2)(vue@3.5.26(typescript@5.9.2)):
+  pinia@3.0.4(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3)):
     dependencies:
       '@vue/devtools-api': 7.7.8
-      vue: 3.5.26(typescript@5.9.2)
+      vue: 3.5.26(typescript@5.9.3)
     optionalDependencies:
-      typescript: 5.9.2
+      typescript: 5.9.3
 
   piscina@4.7.0:
     optionalDependencies:
@@ -7906,7 +7886,7 @@ snapshots:
 
   tree-kill@1.2.2: {}
 
-  ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.2):
+  ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3):
     dependencies:
       '@cspotcode/source-map-support': 0.8.1
       '@tsconfig/node10': 1.0.11
@@ -7920,7 +7900,7 @@ snapshots:
       create-require: 1.1.1
       diff: 4.0.2
       make-error: 1.3.6
-      typescript: 5.9.2
+      typescript: 5.9.3
       v8-compile-cache-lib: 3.0.1
       yn: 3.1.1
 
@@ -7944,7 +7924,7 @@ snapshots:
 
   type-fest@0.8.1: {}
 
-  typescript@5.9.2: {}
+  typescript@5.9.3: {}
 
   undici-types@7.16.0: {}
 
@@ -8021,9 +8001,9 @@ snapshots:
       - supports-color
       - utf-8-validate
 
-  vite-plugin-vue-devtools@8.0.5(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.2)):
+  vite-plugin-vue-devtools@8.0.5(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.3)):
     dependencies:
-      '@vue/devtools-core': 8.0.5(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.2))
+      '@vue/devtools-core': 8.0.5(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.1))(vue@3.5.26(typescript@5.9.3))
       '@vue/devtools-kit': 8.0.5
       '@vue/devtools-shared': 8.0.5
       sirv: 3.0.2
@@ -8114,26 +8094,26 @@ snapshots:
 
   vue-component-type-helpers@2.1.6: {}
 
-  vue-router@4.6.4(vue@3.5.26(typescript@5.9.2)):
+  vue-router@4.6.4(vue@3.5.26(typescript@5.9.3)):
     dependencies:
       '@vue/devtools-api': 6.6.4
-      vue: 3.5.26(typescript@5.9.2)
+      vue: 3.5.26(typescript@5.9.3)
 
-  vue-tsc@3.2.1(typescript@5.9.2):
+  vue-tsc@3.2.1(typescript@5.9.3):
     dependencies:
       '@volar/typescript': 2.4.27
       '@vue/language-core': 3.2.1
-      typescript: 5.9.2
+      typescript: 5.9.3
 
-  vue@3.5.26(typescript@5.9.2):
+  vue@3.5.26(typescript@5.9.3):
     dependencies:
       '@vue/compiler-dom': 3.5.26
       '@vue/compiler-sfc': 3.5.26
       '@vue/runtime-dom': 3.5.26
-      '@vue/server-renderer': 3.5.26(vue@3.5.26(typescript@5.9.2))
+      '@vue/server-renderer': 3.5.26(vue@3.5.26(typescript@5.9.3))
       '@vue/shared': 3.5.26
     optionalDependencies:
-      typescript: 5.9.2
+      typescript: 5.9.3
 
   w3c-xmlserializer@5.0.0:
     dependencies:
index 6ee4e497f6d066ede8dadaf31851b5780c2c523b..b1c17e20a6dbb318dbf96b77f2fd048599c481a0 100644 (file)
@@ -1,4 +1,3 @@
-import fs from 'node:fs'
 import path from 'node:path'
 import { defineConfig, RolldownPlugin } from 'rolldown'
 import license from 'rollup-plugin-license'
@@ -200,34 +199,5 @@ export default defineConfig({
         },
       },
     }) as RolldownPlugin,
-
-    {
-      name: '@vue/create-eslint-config fix',
-      transform: {
-        filter: {
-          id: /@vue.create-eslint-config.renderEjsFile\.js$/,
-        },
-        handler(_code, id) {
-          const pkgDir = path.dirname(id)
-          const templatesDir = path.resolve(pkgDir, './templates')
-
-          const allTemplateFileNames = fs.readdirSync(templatesDir)
-          const templateFiles = Object.fromEntries(
-            allTemplateFileNames.map((fileName) => {
-              const content = fs.readFileSync(path.resolve(templatesDir, fileName), 'utf8')
-              return [`./templates/${fileName}`, content]
-            }),
-          )
-
-          return `
-            import ejs from 'ejs'
-            const templates = ${JSON.stringify(templateFiles)}
-            export default function renderEjsFile(filePath, data) {
-              return ejs.render(templates[filePath], data, {})
-            }
-          `
-        },
-      },
-    },
   ],
 })
index 2c755e61f067d41b626591d0261e5f519d148a99..157bc3d7d09f105daa0e9501cfabd56bbfb8a322 100644 (file)
@@ -7,7 +7,7 @@
   "devDependencies": {
     "@types/node": "^24.10.4",
     "npm-run-all2": "^8.0.4",
-    "typescript": "~5.9.0",
+    "typescript": "~5.9.3",
     "vue-tsc": "^3.2.1"
   }
 }
diff --git a/template/eslint/package.json b/template/eslint/package.json
deleted file mode 100644 (file)
index 7ca2de3..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "devDependencies": {
-    "@vitest/eslint-plugin": "^1.5.4",
-    "eslint-plugin-cypress": "^5.2.0",
-    "eslint-plugin-playwright": "^2.4.0"
-  }
-}
diff --git a/template/formatting/oxfmt/.vscode/settings.json b/template/formatting/oxfmt/.vscode/settings.json
new file mode 100644 (file)
index 0000000..16f965c
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "[javascript]": {
+    "editor.defaultFormatter": "oxc.oxc-vscode"
+  },
+  "[javascriptreact]": {
+    "editor.defaultFormatter": "oxc.oxc-vscode"
+  },
+  "[typescript]": {
+    "editor.defaultFormatter": "oxc.oxc-vscode"
+  },
+  "[typescriptreact]": {
+    "editor.defaultFormatter": "oxc.oxc-vscode"
+  }
+}
diff --git a/template/formatting/oxfmt/_oxfmtrc.jsonc b/template/formatting/oxfmt/_oxfmtrc.jsonc
new file mode 100644 (file)
index 0000000..2de1f92
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "$schema": "./node_modules/oxfmt/configuration_schema.json",
+  "semi": false,
+  "singleQuote": true,
+}
diff --git a/template/formatting/oxfmt/_prettierrc.json b/template/formatting/oxfmt/_prettierrc.json
new file mode 100644 (file)
index 0000000..a84e0ed
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "$schema": "https://json.schemastore.org/prettierrc",
+  "semi": false,
+  "singleQuote": true,
+  "printWidth": 100,
+  "plugins": ["@prettier/plugin-oxc"]
+}
diff --git a/template/formatting/oxfmt/package.json b/template/formatting/oxfmt/package.json
new file mode 100644 (file)
index 0000000..49845de
--- /dev/null
@@ -0,0 +1,13 @@
+{
+  "scripts": {
+    "format:oxfmt": "oxfmt src/",
+    "format:prettier": "prettier --write --experimental-cli src/ '!**/*.{js,jsx,ts,tsx}'",
+    "format": "run-p format:oxfmt format:prettier"
+  },
+  "devDependencies": {
+    "@prettier/plugin-oxc": "^0.1.3",
+    "npm-run-all2": "^8.0.4",
+    "prettier": "3.7.4",
+    "oxfmt": "^0.18.0"
+  }
+}
diff --git a/template/linting/base/_editorconfig b/template/linting/base/_editorconfig
new file mode 100644 (file)
index 0000000..3b510aa
--- /dev/null
@@ -0,0 +1,8 @@
+[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}]
+charset = utf-8
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+end_of_line = lf
+max_line_length = 100
diff --git a/template/linting/base/package.json b/template/linting/base/package.json
new file mode 100644 (file)
index 0000000..9f1b863
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "scripts": {
+    "lint": "eslint . --fix --cache"
+  },
+  "devDependencies": {
+    "eslint-plugin-vue": "~10.6.2",
+    "eslint": "^9.39.2"
+  }
+}
diff --git a/template/linting/core/js/eslint.config.js.data.mjs b/template/linting/core/js/eslint.config.js.data.mjs
new file mode 100644 (file)
index 0000000..62e48a5
--- /dev/null
@@ -0,0 +1,15 @@
+export default function getData() {
+  return {
+    configs: [
+      {
+        importer: `import js from '@eslint/js'`,
+        content: `  js.configs.recommended,`,
+      },
+
+      {
+        importer: `import pluginVue from 'eslint-plugin-vue'`,
+        content: `  ...pluginVue.configs['flat/essential'],`,
+      },
+    ],
+  }
+}
diff --git a/template/linting/core/js/eslint.config.js.ejs b/template/linting/core/js/eslint.config.js.ejs
new file mode 100644 (file)
index 0000000..8d9971c
--- /dev/null
@@ -0,0 +1,27 @@
+import { defineConfig, globalIgnores } from 'eslint/config'
+import globals from 'globals'
+<%_ for (const { importer } of configs) { _%>
+<%_ if (importer) { _%><%- importer %>
+<%_ } _%>
+<%_ } _%>
+
+export default defineConfig([
+  {
+    name: 'app/files-to-lint',
+    files: ['**/*.{vue,js,mjs,jsx}'],
+  },
+
+  globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
+
+  {
+    languageOptions: {
+      globals: {
+        ...globals.browser,
+      },
+    },
+  },
+
+<%_ for (const { content } of configs) { _%>
+<%- content %>
+<%_ } _%>
+])
diff --git a/template/linting/core/js/package.json b/template/linting/core/js/package.json
new file mode 100644 (file)
index 0000000..1bdd664
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "devDependencies": {
+    "@eslint/js": "^9.39.2",
+    "eslint-plugin-vue": "~10.6.2",
+    "eslint": "^9.39.2",
+    "globals": "^16.5.0"
+  }
+}
diff --git a/template/linting/core/ts/eslint.config.js.data.mjs b/template/linting/core/ts/eslint.config.js.data.mjs
new file mode 100644 (file)
index 0000000..486b1c7
--- /dev/null
@@ -0,0 +1,15 @@
+export default function getData() {
+  return {
+    configs: [
+      {
+        importer: `import pluginVue from 'eslint-plugin-vue'`,
+        content: `  ...pluginVue.configs['flat/essential'],`,
+      },
+
+      {
+        // skipped importer for this one because it was already there
+        content: `  vueTsConfigs.recommended,`,
+      },
+    ],
+  }
+}
diff --git a/template/linting/core/ts/eslint.config.js.ejs b/template/linting/core/ts/eslint.config.js.ejs
new file mode 100644 (file)
index 0000000..9378b68
--- /dev/null
@@ -0,0 +1,24 @@
+import { globalIgnores } from 'eslint/config'
+import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'
+<%_ for (const { importer } of configs) { _%>
+<%_ if (importer) { _%><%- importer %>
+<%_ } _%>
+<%_ } _%>
+
+// To allow more languages other than `ts` in `.vue` files, uncomment the following lines:
+// import { configureVueProject } from '@vue/eslint-config-typescript'
+// configureVueProject({ scriptLangs: ['ts', 'tsx'] })
+// More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup
+
+export default defineConfigWithVueTs(
+  {
+    name: 'app/files-to-lint',
+    files: ['**/*.{vue,ts,mts,tsx}'],
+  },
+
+  globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
+
+<%_ for (const { content } of configs) { _%>
+<%- content %>
+<%_ } _%>
+)
diff --git a/template/linting/core/ts/package.json b/template/linting/core/ts/package.json
new file mode 100644 (file)
index 0000000..6dc0dfb
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "devDependencies": {
+    "@vue/eslint-config-typescript": "^14.6.0",
+    "eslint": "^9.39.2",
+    "eslint-plugin-vue": "~10.6.2",
+    "jiti": "^2.6.1",
+    "typescript": "~5.9.3"
+  }
+}
diff --git a/template/linting/cypress-ct/eslint.config.js.data.mjs b/template/linting/cypress-ct/eslint.config.js.data.mjs
new file mode 100644 (file)
index 0000000..2e4ccf2
--- /dev/null
@@ -0,0 +1,25 @@
+export default function getData({ oldData }) {
+  return {
+    ...oldData,
+    configs: oldData.configs.map((c) => {
+      if (!c.content.includes('pluginCypress')) {
+        return c
+      }
+
+      return {
+        ...c,
+
+        // modify the files pattern to include component testing files
+        content: `
+  {
+    ...pluginCypress.configs.recommended,
+    files: [
+      '**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}',
+      'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}',
+      'cypress/support/**/*.{js,ts,jsx,tsx}',
+    ],
+  },`,
+      }
+    }),
+  }
+}
diff --git a/template/linting/cypress/eslint.config.js.data.mjs b/template/linting/cypress/eslint.config.js.data.mjs
new file mode 100644 (file)
index 0000000..58b37de
--- /dev/null
@@ -0,0 +1,19 @@
+export default function getData({ oldData }) {
+  return {
+    ...oldData,
+    configs: [
+      ...oldData.configs,
+      {
+        importer: `import pluginCypress from 'eslint-plugin-cypress'`,
+        content: `
+  {
+    ...pluginCypress.configs.recommended,
+    files: [
+      'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}',
+      'cypress/support/**/*.{js,ts,jsx,tsx}',
+    ],
+  },`,
+      },
+    ],
+  }
+}
diff --git a/template/linting/cypress/package.json b/template/linting/cypress/package.json
new file mode 100644 (file)
index 0000000..f3638c9
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "devDependencies": {
+    "eslint-plugin-cypress": "^5.2.0"
+  }
+}
diff --git a/template/linting/oxlint/.vscode/extensions.json b/template/linting/oxlint/.vscode/extensions.json
new file mode 100644 (file)
index 0000000..99e2f7d
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "recommendations": ["oxc.oxc-vscode"]
+}
diff --git a/template/linting/oxlint/_ oxlintrc.json b/template/linting/oxlint/_ oxlintrc.json
new file mode 100644 (file)
index 0000000..d5648b9
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "$schema": "./node_modules/oxlint/configuration_schema.json",
+  "plugins": ["eslint", "typescript", "unicorn", "oxc", "vue"],
+  "env": {
+    "browser": true
+  },
+  "categories": {
+    "correctness": "error"
+  }
+}
diff --git a/template/linting/oxlint/eslint.config.js.data.mjs b/template/linting/oxlint/eslint.config.js.data.mjs
new file mode 100644 (file)
index 0000000..4601d74
--- /dev/null
@@ -0,0 +1,12 @@
+export default function getData({ oldData }) {
+  return {
+    ...oldData,
+    configs: [
+      ...oldData.configs,
+      {
+        importer: `import pluginOxlint from 'eslint-plugin-oxlint'`,
+        content: `\n  ...pluginOxlint.configs['flat/recommended'],`,
+      },
+    ],
+  }
+}
diff --git a/template/linting/oxlint/package.json b/template/linting/oxlint/package.json
new file mode 100644 (file)
index 0000000..07c9542
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "scripts": {
+    "lint:oxlint": "oxlint . --fix",
+    "lint:eslint": "eslint . --fix --cache",
+    "lint": "run-s lint:*"
+  },
+  "devDependencies": {
+    "eslint-plugin-oxlint": "~1.33.0",
+    "npm-run-all2": "^8.0.4",
+    "oxlint": "~1.33.0"
+  }
+}
diff --git a/template/linting/playwright/eslint.config.js.data.mjs b/template/linting/playwright/eslint.config.js.data.mjs
new file mode 100644 (file)
index 0000000..1900c75
--- /dev/null
@@ -0,0 +1,16 @@
+export default function getData({ oldData }) {
+  return {
+    ...oldData,
+    configs: [
+      ...oldData.configs,
+      {
+        importer: "import pluginPlaywright from 'eslint-plugin-playwright'",
+        content: `
+  {
+    ...pluginPlaywright.configs['flat/recommended'],
+    files: ['e2e/**/*.{test,spec}.{js,ts,jsx,tsx}'],
+  },`,
+      },
+    ],
+  }
+}
diff --git a/template/linting/playwright/package.json b/template/linting/playwright/package.json
new file mode 100644 (file)
index 0000000..6c3f127
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "devDependencies": {
+    "eslint-plugin-playwright": "^2.4.0"
+  }
+}
diff --git a/template/linting/prettier/eslint.config.js.data.mjs b/template/linting/prettier/eslint.config.js.data.mjs
new file mode 100644 (file)
index 0000000..81db21f
--- /dev/null
@@ -0,0 +1,12 @@
+export default function getData({ oldData }) {
+  return {
+    ...oldData,
+    configs: [
+      ...oldData.configs,
+      {
+        importer: `import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'`,
+        content: `\n  skipFormatting,`,
+      },
+    ],
+  }
+}
diff --git a/template/linting/prettier/package.json b/template/linting/prettier/package.json
new file mode 100644 (file)
index 0000000..16577b3
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "devDependencies": {
+    "@vue/eslint-config-prettier": "^10.2.0",
+    "prettier": "3.7.4"
+  }
+}
diff --git a/template/linting/vitest/eslint.config.js.data.mjs b/template/linting/vitest/eslint.config.js.data.mjs
new file mode 100644 (file)
index 0000000..9532176
--- /dev/null
@@ -0,0 +1,16 @@
+export default function getData({ oldData }) {
+  return {
+    ...oldData,
+    configs: [
+      ...oldData.configs,
+      {
+        importer: `import pluginVitest from '@vitest/eslint-plugin'`,
+        content: `
+  {
+    ...pluginVitest.configs.recommended,
+    files: ['src/**/__tests__/*'],
+  },`,
+      },
+    ],
+  }
+}
diff --git a/template/linting/vitest/package.json b/template/linting/vitest/package.json
new file mode 100644 (file)
index 0000000..9149757
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "devDependencies": {
+    "@vitest/eslint-plugin": "^1.5.2"
+  }
+}
diff --git a/utils/renderEslint.ts b/utils/renderEslint.ts
deleted file mode 100644 (file)
index 8235438..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-import * as fs from 'node:fs'
-import * as path from 'node:path'
-
-import createESLintConfig from '@vue/create-eslint-config'
-
-import sortDependencies from './sortDependencies'
-import deepMerge from './deepMerge'
-
-import eslintTemplatePackage from '../template/eslint/package.json' with { type: 'json' }
-const eslintDeps = eslintTemplatePackage.devDependencies
-
-export default function renderEslint(
-  rootDir,
-  {
-    needsTypeScript,
-    needsVitest,
-    needsCypress,
-    needsCypressCT,
-    needsOxlint,
-    needsPrettier,
-    needsPlaywright,
-  },
-) {
-  const additionalConfigs = getAdditionalConfigs({
-    needsTypeScript,
-    needsVitest,
-    needsCypress,
-    needsCypressCT,
-    needsPlaywright,
-  })
-
-  const { pkg, files } = createESLintConfig({
-    styleGuide: 'default',
-    hasTypeScript: needsTypeScript,
-    needsOxlint,
-    // Theoretically, we could add Prettier without requring ESLint.
-    // But it doesn't seem to be a good practice, so we just let createESLintConfig handle it.
-    needsPrettier,
-    additionalConfigs,
-  })
-
-  // update package.json
-  const packageJsonPath = path.resolve(rootDir, 'package.json')
-  const existingPkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
-  const updatedPkg = sortDependencies(deepMerge(existingPkg, pkg))
-  fs.writeFileSync(packageJsonPath, JSON.stringify(updatedPkg, null, 2) + '\n', 'utf8')
-
-  // write to eslint.config.js, .prettierrc.json, .editorconfig, etc.
-  for (const [fileName, content] of Object.entries(files)) {
-    const fullPath = path.resolve(rootDir, fileName)
-    fs.writeFileSync(fullPath, content as string, 'utf8')
-  }
-}
-
-type ConfigItemInESLintTemplate = {
-  importer: string
-  content: string
-}
-type AdditionalConfig = {
-  devDependencies: Record<string, string>
-  beforeVuePlugin?: Array<ConfigItemInESLintTemplate>
-  afterVuePlugin?: Array<ConfigItemInESLintTemplate>
-}
-type AdditionalConfigArray = Array<AdditionalConfig>
-
-// visible for testing
-export function getAdditionalConfigs({
-  needsTypeScript,
-  needsVitest,
-  needsCypress,
-  needsCypressCT,
-  needsPlaywright,
-}) {
-  const additionalConfigs: AdditionalConfigArray = []
-
-  if (needsVitest) {
-    additionalConfigs.push({
-      devDependencies: {
-        '@vitest/eslint-plugin': eslintDeps['@vitest/eslint-plugin'],
-      },
-      afterVuePlugin: [
-        {
-          importer: `import pluginVitest from '@vitest/eslint-plugin'`,
-          content: `
-  {
-    ...pluginVitest.configs.recommended,
-    files: ['src/**/__tests__/*'],
-  },`,
-        },
-      ],
-    })
-  }
-
-  if (needsCypress) {
-    additionalConfigs.push({
-      devDependencies: {
-        'eslint-plugin-cypress': eslintDeps['eslint-plugin-cypress'],
-      },
-      afterVuePlugin: [
-        {
-          importer:
-            (needsTypeScript
-              ? `// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n` +
-                `// @ts-ignore\n`
-              : '') + "import pluginCypress from 'eslint-plugin-cypress'",
-          content: `
-  {
-    ...pluginCypress.configs.recommended,
-    files: [
-      ${[
-        ...(needsCypressCT ? ['**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}'] : []),
-        'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}',
-        'cypress/support/**/*.{js,ts,jsx,tsx}',
-      ]
-        .map(JSON.stringify.bind(JSON))
-        .join(',\n      ')
-        .replace(/"/g, "'" /* use single quotes as in the other configs */)}
-    ],
-  },`,
-        },
-      ],
-    })
-  }
-
-  if (needsPlaywright) {
-    additionalConfigs.push({
-      devDependencies: {
-        'eslint-plugin-playwright': eslintDeps['eslint-plugin-playwright'],
-      },
-      afterVuePlugin: [
-        {
-          importer: "import pluginPlaywright from 'eslint-plugin-playwright'",
-          content: `
-  {
-    ...pluginPlaywright.configs['flat/recommended'],
-    files: ['e2e/**/*.{test,spec}.{js,ts,jsx,tsx}'],
-  },`,
-        },
-      ],
-    })
-  }
-
-  return additionalConfigs
-}