From 353203880d5ac26d28980180f7f51b4ec802f33e Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Fri, 17 Jul 2026 08:41:28 +0000 Subject: [PATCH 01/19] feat(create): implement support for JetBrains editors --- .../cli/src/utils/__tests__/editor.spec.ts | 40 ++++++++++ packages/cli/src/utils/editor.ts | 80 +++++++++++++++++-- 2 files changed, 112 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/utils/__tests__/editor.spec.ts b/packages/cli/src/utils/__tests__/editor.spec.ts index 12eeabd64c..9a329ed433 100644 --- a/packages/cli/src/utils/__tests__/editor.spec.ts +++ b/packages/cli/src/utils/__tests__/editor.spec.ts @@ -91,6 +91,14 @@ describe('detectExistingEditors', () => { it('returns undefined when no editor config files exist', () => { expect(detectExistingEditors(createTempDir())).toBeUndefined(); }); + + it('detects existing jetbrains editor config files', () => { + const projectRoot = createTempDir(); + fs.mkdirSync(path.join(projectRoot, '.idea'), { recursive: true }); + fs.writeFileSync(path.join(projectRoot, '.idea', 'externalDependencies.xml'), ''); + + expect(detectExistingEditors(projectRoot)).toEqual(['jetbrains']); + }); }); describe('writeEditorConfigs', () => { @@ -539,4 +547,36 @@ describe('writeEditorConfigs', () => { expect(zedSettings['npm.scriptRunner']).toBeUndefined(); expect(zedSettings.lsp).toBeDefined(); }); + + it('writes jetbrains config as XML based on file extension', async () => { + const projectRoot = createTempDir(); + + await writeEditorConfigs({ + projectRoot, + editorId: 'jetbrains', + interactive: false, + silent: true, + }); + + const xml = fs.readFileSync(path.join(projectRoot, '.idea', 'externalDependencies.xml'), 'utf8'); + expect(xml).toContain(''); + expect(xml).toContain(''); + }); + + it('does not overwrite existing non-JSON editor config in non-interactive mode', async () => { + const projectRoot = createTempDir(); + const xmlPath = path.join(projectRoot, '.idea', 'externalDependencies.xml'); + fs.mkdirSync(path.dirname(xmlPath), { recursive: true }); + fs.writeFileSync(xmlPath, '', 'utf8'); + + await writeEditorConfigs({ + projectRoot, + editorId: 'jetbrains', + interactive: false, + silent: true, + }); + + const xml = fs.readFileSync(xmlPath, 'utf8'); + expect(xml).toBe(''); + }); }); diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index 9688b36397..e210841ed0 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -150,6 +150,17 @@ const ZED_SETTINGS = { }, } as const; +const JETBRAINS_EXTERNAL_DEPENDENCIES = ` + + + + + + +`; + +type EditorConfigValue = Record | string; + export const EDITORS = [ { id: 'vscode', @@ -168,6 +179,14 @@ export const EDITORS = [ 'settings.json': ZED_SETTINGS as Record, }, }, + { + id: 'jetbrains', + label: 'JetBrains (IntelliJ, WebStorm, etc)', + targetDir: '.idea', + files: { + 'externalDependencies.xml': JETBRAINS_EXTERNAL_DEPENDENCIES, + }, + }, ] as const; export type EditorId = (typeof EDITORS)[number]['id']; @@ -386,11 +405,12 @@ async function writeEditorConfig({ await fsPromises.mkdir(targetDir, { recursive: true }); for (const [fileName, baseIncoming] of Object.entries(editorConfig.files)) { - const incoming = + const incoming: EditorConfigValue = editorId === 'vscode' && fileName === 'settings.json' && extraVsCodeSettings ? { ...extraVsCodeSettings, ...baseIncoming } : baseIncoming; const filePath = path.join(targetDir, fileName); + const jsonFormat = isJsonLikeFile(fileName); if (fs.existsSync(filePath)) { const displayPath = `${editorConfig.targetDir}/${fileName}`; @@ -406,13 +426,17 @@ async function writeEditorConfig({ `${displayPath} already exists.\n ` + styleText( 'gray', - `Vite+ adds ${editorConfig.label} settings for the built-in linter and formatter. Merge adds new keys without overwriting existing ones.`, + jsonFormat + ? `Vite+ adds ${editorConfig.label} settings for the built-in linter and formatter. Merge adds new keys without overwriting existing ones.` + : `Vite+ adds ${editorConfig.label} settings for the built-in linter and formatter. Overwrite replaces the existing file with the generated config.`, ), options: [ { - label: 'Merge', + label: jsonFormat ? 'Merge' : 'Overwrite', value: 'merge', - hint: 'Merge new settings into existing file', + hint: jsonFormat + ? 'Merge new settings into existing file' + : 'Replace existing file with generated config', }, { label: 'Skip', @@ -424,12 +448,19 @@ async function writeEditorConfig({ }); conflictAction = prompts.isCancel(action) || action === 'skip' ? 'skip' : 'merge'; } else { - // Non-interactive: always merge (safe because existing keys are never overwritten) - conflictAction = 'merge'; + // Non-interactive: merge JSON safely, skip non-JSON to avoid destructive overwrite. + conflictAction = jsonFormat ? 'merge' : 'skip'; } if (conflictAction === 'merge') { - mergeAndWriteEditorConfig(filePath, incoming, fileName, displayPath, silent); + if (jsonFormat) { + if (!isPlainObject(incoming)) { + throw new Error(`Cannot merge editor config: ${displayPath} incoming value is not JSON`); + } + mergeAndWriteEditorConfig(filePath, incoming, fileName, displayPath, silent); + } else { + writeTextEditorConfig(filePath, incoming, displayPath, silent); + } } else { if (!silent) { prompts.log.info(`Skipped writing ${displayPath}`); @@ -438,13 +469,46 @@ async function writeEditorConfig({ continue; } - writeJsonFile(filePath, incoming); + if (jsonFormat) { + if (!isPlainObject(incoming)) { + throw new Error(`Cannot write editor config: ${editorConfig.targetDir}/${fileName} must be JSON`); + } + writeJsonFile(filePath, incoming); + } else { + writeTextEditorConfig(filePath, incoming, `${editorConfig.targetDir}/${fileName}`, silent); + } if (!silent) { prompts.log.success(`Wrote editor config to ${editorConfig.targetDir}/${fileName}`); } } } +function isJsonLikeFile(fileName: string): boolean { + const ext = path.extname(fileName).toLowerCase(); + return ext === '.json' || ext === '.jsonc'; +} + +function writeTextEditorConfig( + filePath: string, + incoming: EditorConfigValue, + displayPath: string, + silent = false, +) { + if (typeof incoming !== 'string') { + throw new Error(`Cannot write editor config: ${displayPath} must be text content`); + } + + const existingText = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf-8') : undefined; + if (existingText === incoming) { + if (!silent) { + prompts.log.info(`No changes needed for ${displayPath}`); + } + return; + } + + fs.writeFileSync(filePath, incoming, 'utf-8'); +} + function normalizeEditorSelection(editorId: EditorSelection): EditorId[] { if (!editorId) { return []; From c56386fa7c7c0125078790bc487ba2b672bab334 Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Sat, 25 Jul 2026 09:50:27 +0000 Subject: [PATCH 02/19] WIP docs on JetBrains --- docs/guide/ide-integration.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/guide/ide-integration.md b/docs/guide/ide-integration.md index 554da52e4f..0d8b23d8fd 100644 --- a/docs/guide/ide-integration.md +++ b/docs/guide/ide-integration.md @@ -99,3 +99,15 @@ You can also manually set up the Zed config: ``` Setting `oxfmt.fmt.configPath` to `./vite.config.ts` keeps editor format-on-save aligned with the `fmt` block in your Vite+ config. The full generated config covers additional languages (CSS, HTML, JSON, Markdown, etc.) — run `vp create` or `vp migrate` to get the complete file written automatically. + +## JetBrains (IntelliJ, WebStorm, etc...) + +For the best Vite+ experience with JetBrains IDEs such as IntelliJ & WebStorm, install the [Oxc](https://plugins.jetbrains.com/plugin/27061-oxc) plugin from the JetBrains marketplace. + +When you create or migrate a project, Vite+ prompts you to choose whether you want the editor config written for Zed. + +You can also manually set up the IDE configuration to utilise Oxc: + +```json + +``` From 07bdba133bae3a8a1a2c2efaaeef6bc25b176e7b Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Sun, 26 Jul 2026 05:55:30 +0000 Subject: [PATCH 03/19] some todos --- packages/cli/src/utils/editor.ts | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index 9ab3598e1b..c23b222518 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -150,6 +150,8 @@ const ZED_SETTINGS = { }, } as const; +// TODO Replace this raw XML template with a JSON-object definition +// once the XML parser/merge support below is in place. const JETBRAINS_EXTERNAL_DEPENDENCIES = ` @@ -159,6 +161,8 @@ const JETBRAINS_EXTERNAL_DEPENDENCIES = ` `; +// TODO: Extend this to allow XML files to be authored as JSON objects too +// e.g. `Record | string` -> add a dedicated XML-object type once an XML parser/differ is written type EditorConfigValue = Record | string; export const EDITORS = [ @@ -189,6 +193,15 @@ export const EDITORS = [ }, ] as const; +// Since some file types may not be obvious (e.g. `.editorconfig`), it may be beneficial to add a property for declaring file type overrides for both read and write +// The only problem is that now we have to maintain a list of file types and their extensions, which is not trivial. For now, we can just use the file extension to determine the file type and just deal with corner-case scenarios as we go. +// TODO: Replace values with custom parser classes/objects implemented specifically for each file type +export const FILE_TYPE_MAPPINGS = { + '.json': 'jsonc', + '.jsonc': 'jsonc', + '.xml': 'xml', +} + export type EditorId = (typeof EDITORS)[number]['id']; type EditorSelection = EditorId | readonly EditorId[] | undefined; @@ -451,7 +464,9 @@ async function writeEditorConfig({ if (conflictAction === 'merge') { if (jsonFormat) { if (!isPlainObject(incoming)) { - throw new Error(`Cannot merge editor config: ${displayPath} incoming value is not JSON`); + throw new Error( + `Cannot merge editor config: ${displayPath} incoming value is not JSON`, + ); } mergeAndWriteEditorConfig(filePath, incoming, fileName, displayPath, silent); } else { @@ -467,7 +482,9 @@ async function writeEditorConfig({ if (jsonFormat) { if (!isPlainObject(incoming)) { - throw new Error(`Cannot write editor config: ${editorConfig.targetDir}/${fileName} must be JSON`); + throw new Error( + `Cannot write editor config: ${editorConfig.targetDir}/${fileName} must be JSON`, + ); } writeJsonFile(filePath, incoming); } else { @@ -484,6 +501,9 @@ function isJsonLikeFile(fileName: string): boolean { return ext === '.json' || ext === '.jsonc'; } +// TODO: Add an `isXmlFile()` extension check (`.xml`) alongside `isJsonLikeFile()`, +// and dispatch `.xml` files to write/merge instead of write/skip-on-conflict +// See `writeEditorConfig()`'s `jsonFormat` branching for the call sites that need a parallel `xmlFormat` branch (conflict prompt copy, merge dispatch, initial write). function writeTextEditorConfig( filePath: string, incoming: EditorConfigValue, @@ -502,6 +522,8 @@ function writeTextEditorConfig( return; } + // TODO: Once XML merge support exists, this plain overwrite-or-skip behavior should be replaced with a merge that preserves comments and formatting, similar to `mergeAndWriteEditorConfig()`. + // Likely will need to be extended for other file types too, so consider a generic `mergeAndWriteFile()` that dispatches to JSON/XML/text merge strategies based on file extension. fs.writeFileSync(filePath, incoming, 'utf-8'); } From 8b9cc42c2ca6b38df3f6a8559db95fb9e2444702 Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Sun, 26 Jul 2026 06:34:38 +0000 Subject: [PATCH 04/19] Finish IDE integration docs page --- docs/guide/ide-integration.md | 49 ++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/docs/guide/ide-integration.md b/docs/guide/ide-integration.md index 0d8b23d8fd..0704db4266 100644 --- a/docs/guide/ide-integration.md +++ b/docs/guide/ide-integration.md @@ -104,10 +104,53 @@ Setting `oxfmt.fmt.configPath` to `./vite.config.ts` keeps editor format-on-save For the best Vite+ experience with JetBrains IDEs such as IntelliJ & WebStorm, install the [Oxc](https://plugins.jetbrains.com/plugin/27061-oxc) plugin from the JetBrains marketplace. -When you create or migrate a project, Vite+ prompts you to choose whether you want the editor config written for Zed. +When you create or migrate a project, Vite+ prompts you to choose whether you want the editor config written for JetBrains IDEs. + +::: tip Vite+ does not merge with existing config files +Due to some complexities with merging XML files, Vite+ currently does not merge your current files if the files already exist. +You'll be given the opportunity to replace your files, instead of merging. +::: + +You can also manually set up the IDE configuration to match your Vite+ setup: + +```xml [.idea/externalDependencies.xml] + + + + + + + +``` -You can also manually set up the IDE configuration to utilise Oxc: +```xml [.idea/workspace.xml] + + + + + + + +``` -```json +```xml [.idea/OxfmtSettings.xml] + + + + + +``` +```gitignore [.idea/.gitignore] +!externalDependencies.xml ``` From 81a098fcb57027f88de183c45301ceb04e04a3dc Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Sun, 26 Jul 2026 06:36:34 +0000 Subject: [PATCH 05/19] oops --- docs/guide/ide-integration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/ide-integration.md b/docs/guide/ide-integration.md index 0704db4266..71c92cab27 100644 --- a/docs/guide/ide-integration.md +++ b/docs/guide/ide-integration.md @@ -134,7 +134,7 @@ You can also manually set up the IDE configuration to match your Vite+ setup: "javascript.nodejs.core.library.configured.version": "24.18.0", // Replace with your selected Node.js version "javascript.nodejs.core.library.typings.version": "24.13.3", // Replace with the version of @types/node that corresponds to your runtime (or omit if you don't want it) "javascript.preferred.runtime.type.id": "node", - "nodejs_interpreter_path": "~/.vite-plus/bin/node", + "nodejs_interpreter_path": "~/.vite-plus/bin/node", // Replace ~ with the path to your home directory, IntelliJ/WebStorm don't understand ~ "nodejs_package_manager_path": "pnpm", // Replace with your package manager of choice } }]]> From 08155c8c5b32f17729486958cc941dc4c1a7dac6 Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Wed, 5 Aug 2026 06:16:56 +0000 Subject: [PATCH 06/19] Revert "some todos" This reverts commit 07bdba133bae3a8a1a2c2efaaeef6bc25b176e7b. --- packages/cli/src/utils/editor.ts | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index c23b222518..9ab3598e1b 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -150,8 +150,6 @@ const ZED_SETTINGS = { }, } as const; -// TODO Replace this raw XML template with a JSON-object definition -// once the XML parser/merge support below is in place. const JETBRAINS_EXTERNAL_DEPENDENCIES = ` @@ -161,8 +159,6 @@ const JETBRAINS_EXTERNAL_DEPENDENCIES = ` `; -// TODO: Extend this to allow XML files to be authored as JSON objects too -// e.g. `Record | string` -> add a dedicated XML-object type once an XML parser/differ is written type EditorConfigValue = Record | string; export const EDITORS = [ @@ -193,15 +189,6 @@ export const EDITORS = [ }, ] as const; -// Since some file types may not be obvious (e.g. `.editorconfig`), it may be beneficial to add a property for declaring file type overrides for both read and write -// The only problem is that now we have to maintain a list of file types and their extensions, which is not trivial. For now, we can just use the file extension to determine the file type and just deal with corner-case scenarios as we go. -// TODO: Replace values with custom parser classes/objects implemented specifically for each file type -export const FILE_TYPE_MAPPINGS = { - '.json': 'jsonc', - '.jsonc': 'jsonc', - '.xml': 'xml', -} - export type EditorId = (typeof EDITORS)[number]['id']; type EditorSelection = EditorId | readonly EditorId[] | undefined; @@ -464,9 +451,7 @@ async function writeEditorConfig({ if (conflictAction === 'merge') { if (jsonFormat) { if (!isPlainObject(incoming)) { - throw new Error( - `Cannot merge editor config: ${displayPath} incoming value is not JSON`, - ); + throw new Error(`Cannot merge editor config: ${displayPath} incoming value is not JSON`); } mergeAndWriteEditorConfig(filePath, incoming, fileName, displayPath, silent); } else { @@ -482,9 +467,7 @@ async function writeEditorConfig({ if (jsonFormat) { if (!isPlainObject(incoming)) { - throw new Error( - `Cannot write editor config: ${editorConfig.targetDir}/${fileName} must be JSON`, - ); + throw new Error(`Cannot write editor config: ${editorConfig.targetDir}/${fileName} must be JSON`); } writeJsonFile(filePath, incoming); } else { @@ -501,9 +484,6 @@ function isJsonLikeFile(fileName: string): boolean { return ext === '.json' || ext === '.jsonc'; } -// TODO: Add an `isXmlFile()` extension check (`.xml`) alongside `isJsonLikeFile()`, -// and dispatch `.xml` files to write/merge instead of write/skip-on-conflict -// See `writeEditorConfig()`'s `jsonFormat` branching for the call sites that need a parallel `xmlFormat` branch (conflict prompt copy, merge dispatch, initial write). function writeTextEditorConfig( filePath: string, incoming: EditorConfigValue, @@ -522,8 +502,6 @@ function writeTextEditorConfig( return; } - // TODO: Once XML merge support exists, this plain overwrite-or-skip behavior should be replaced with a merge that preserves comments and formatting, similar to `mergeAndWriteEditorConfig()`. - // Likely will need to be extended for other file types too, so consider a generic `mergeAndWriteFile()` that dispatches to JSON/XML/text merge strategies based on file extension. fs.writeFileSync(filePath, incoming, 'utf-8'); } From add16266fd49bf296c5a5d14e5dc104738ca38fe Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Wed, 5 Aug 2026 06:47:19 +0000 Subject: [PATCH 07/19] feat: auto-add other relevant files when selecting JetBrains --- docs/guide/ide-integration.md | 4 +- .../cli/src/utils/__tests__/editor.spec.ts | 51 ++++++++++++++++--- packages/cli/src/utils/editor.ts | 36 ++++++++++++- 3 files changed, 81 insertions(+), 10 deletions(-) diff --git a/docs/guide/ide-integration.md b/docs/guide/ide-integration.md index 71c92cab27..7786b7b886 100644 --- a/docs/guide/ide-integration.md +++ b/docs/guide/ide-integration.md @@ -108,7 +108,7 @@ When you create or migrate a project, Vite+ prompts you to choose whether you wa ::: tip Vite+ does not merge with existing config files Due to some complexities with merging XML files, Vite+ currently does not merge your current files if the files already exist. -You'll be given the opportunity to replace your files, instead of merging. +You'll be given the opportunity to replace any existing files, instead of merging. ::: You can also manually set up the IDE configuration to match your Vite+ setup: @@ -134,7 +134,7 @@ You can also manually set up the IDE configuration to match your Vite+ setup: "javascript.nodejs.core.library.configured.version": "24.18.0", // Replace with your selected Node.js version "javascript.nodejs.core.library.typings.version": "24.13.3", // Replace with the version of @types/node that corresponds to your runtime (or omit if you don't want it) "javascript.preferred.runtime.type.id": "node", - "nodejs_interpreter_path": "~/.vite-plus/bin/node", // Replace ~ with the path to your home directory, IntelliJ/WebStorm don't understand ~ + "nodejs_interpreter_path": "~/.vite-plus/bin/node", // Replace ~ with the path to your home directory, IntelliJ/WebStorm doesn't understand ~ "nodejs_package_manager_path": "pnpm", // Replace with your package manager of choice } }]]> diff --git a/packages/cli/src/utils/__tests__/editor.spec.ts b/packages/cli/src/utils/__tests__/editor.spec.ts index 9a329ed433..9fb46fa9a0 100644 --- a/packages/cli/src/utils/__tests__/editor.spec.ts +++ b/packages/cli/src/utils/__tests__/editor.spec.ts @@ -95,7 +95,7 @@ describe('detectExistingEditors', () => { it('detects existing jetbrains editor config files', () => { const projectRoot = createTempDir(); fs.mkdirSync(path.join(projectRoot, '.idea'), { recursive: true }); - fs.writeFileSync(path.join(projectRoot, '.idea', 'externalDependencies.xml'), ''); + fs.writeFileSync(path.join(projectRoot, '.idea', 'workspace.xml'), ''); expect(detectExistingEditors(projectRoot)).toEqual(['jetbrains']); }); @@ -548,7 +548,7 @@ describe('writeEditorConfigs', () => { expect(zedSettings.lsp).toBeDefined(); }); - it('writes jetbrains config as XML based on file extension', async () => { + it('writes all jetbrains editor config files', async () => { const projectRoot = createTempDir(); await writeEditorConfigs({ @@ -558,12 +558,39 @@ describe('writeEditorConfigs', () => { silent: true, }); - const xml = fs.readFileSync(path.join(projectRoot, '.idea', 'externalDependencies.xml'), 'utf8'); - expect(xml).toContain(''); - expect(xml).toContain(''); + const externalDependenciesXml = fs.readFileSync( + path.join(projectRoot, '.idea', 'externalDependencies.xml'), + 'utf8', + ); + expect(externalDependenciesXml).toContain(''); + expect(externalDependenciesXml).toContain( + '', + ); + expect(externalDependenciesXml).toContain(''); + + const workspaceXml = fs.readFileSync(path.join(projectRoot, '.idea', 'workspace.xml'), 'utf8'); + expect(workspaceXml).toContain(''); + expect(workspaceXml).toContain('"javascript.preferred.runtime.type.id": "node"'); + expect(workspaceXml).toContain( + `"nodejs_interpreter_path": "${os.homedir()}/.vite-plus/bin/node"`, + ); + expect(workspaceXml).toContain('"nodejs_package_manager_path": "pnpm"'); + + const oxfmtSettingsXml = fs.readFileSync( + path.join(projectRoot, '.idea', 'OxfmtSettings.xml'), + 'utf8', + ); + expect(oxfmtSettingsXml).toContain(''); + expect(oxfmtSettingsXml).toContain(''); + expect(oxfmtSettingsXml).toContain( + ' `; +const JETBRAINS_WORKSPACE_CONFIG = ` + + + + + +`; + +const JETBRAINS_OXFMT_SETTINGS = ` + + + + +`; + +const JETBRAINS_GITIGNORE_ADDITION = `!externalDependencies.xml` + type EditorConfigValue = Record | string; export const EDITORS = [ @@ -185,6 +210,9 @@ export const EDITORS = [ targetDir: '.idea', files: { 'externalDependencies.xml': JETBRAINS_EXTERNAL_DEPENDENCIES, + 'workspace.xml': JETBRAINS_WORKSPACE_CONFIG, + 'OxfmtSettings.xml': JETBRAINS_OXFMT_SETTINGS, + '.gitignore': JETBRAINS_GITIGNORE_ADDITION, }, }, ] as const; @@ -451,7 +479,9 @@ async function writeEditorConfig({ if (conflictAction === 'merge') { if (jsonFormat) { if (!isPlainObject(incoming)) { - throw new Error(`Cannot merge editor config: ${displayPath} incoming value is not JSON`); + throw new Error( + `Cannot merge editor config: ${displayPath} incoming value is not JSON`, + ); } mergeAndWriteEditorConfig(filePath, incoming, fileName, displayPath, silent); } else { @@ -467,7 +497,9 @@ async function writeEditorConfig({ if (jsonFormat) { if (!isPlainObject(incoming)) { - throw new Error(`Cannot write editor config: ${editorConfig.targetDir}/${fileName} must be JSON`); + throw new Error( + `Cannot write editor config: ${editorConfig.targetDir}/${fileName} must be JSON`, + ); } writeJsonFile(filePath, incoming); } else { From 823a04c4b6562d6204c1244800631a49ea3df8a1 Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Wed, 5 Aug 2026 06:51:51 +0000 Subject: [PATCH 08/19] feat: Remove intellij.vitejs from externalDependencies.xml file preset for now --- docs/guide/ide-integration.md | 1 - packages/cli/src/utils/__tests__/editor.spec.ts | 1 - packages/cli/src/utils/editor.ts | 1 - 3 files changed, 3 deletions(-) diff --git a/docs/guide/ide-integration.md b/docs/guide/ide-integration.md index 7786b7b886..e281633015 100644 --- a/docs/guide/ide-integration.md +++ b/docs/guide/ide-integration.md @@ -118,7 +118,6 @@ You can also manually set up the IDE configuration to match your Vite+ setup: - ``` diff --git a/packages/cli/src/utils/__tests__/editor.spec.ts b/packages/cli/src/utils/__tests__/editor.spec.ts index 9fb46fa9a0..b31330a087 100644 --- a/packages/cli/src/utils/__tests__/editor.spec.ts +++ b/packages/cli/src/utils/__tests__/editor.spec.ts @@ -566,7 +566,6 @@ describe('writeEditorConfigs', () => { expect(externalDependenciesXml).toContain( '', ); - expect(externalDependenciesXml).toContain(''); const workspaceXml = fs.readFileSync(path.join(projectRoot, '.idea', 'workspace.xml'), 'utf8'); expect(workspaceXml).toContain(''); diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index ff87ecdd91..69eb9447a6 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -155,7 +155,6 @@ const JETBRAINS_EXTERNAL_DEPENDENCIES = ` - `; From 6fdfb830ba371c36a00089e83298c32ee152f119 Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Wed, 5 Aug 2026 06:52:17 +0000 Subject: [PATCH 09/19] docs: add note about .idea folders in most projects --- docs/guide/ide-integration.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/guide/ide-integration.md b/docs/guide/ide-integration.md index e281633015..305f22c029 100644 --- a/docs/guide/ide-integration.md +++ b/docs/guide/ide-integration.md @@ -150,6 +150,8 @@ You can also manually set up the IDE configuration to match your Vite+ setup: ``` +Often, `.idea` folders are gitignored in a project, even the `externalDependencies.xml` file. Adding the `.idea/.gitignore` file with the following content will help ensure that it is present: + ```gitignore [.idea/.gitignore] !externalDependencies.xml ``` From 9c5664622eba8fcc97d2ebdec34cb2df6dfd81f3 Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Wed, 5 Aug 2026 10:54:18 +0000 Subject: [PATCH 10/19] do not override jetbrains configs in non-interactive vp migrate --- .../src/migration/__tests__/migrator.spec.ts | 38 +++++++++++++++++++ packages/cli/src/migration/setup-plan.ts | 13 ++++++- packages/cli/src/utils/editor.ts | 2 +- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/migration/__tests__/migrator.spec.ts b/packages/cli/src/migration/__tests__/migrator.spec.ts index bcefe8a9f5..005cef7171 100644 --- a/packages/cli/src/migration/__tests__/migrator.spec.ts +++ b/packages/cli/src/migration/__tests__/migrator.spec.ts @@ -8593,3 +8593,41 @@ describe('collectMigrationSetupPlan ESLint gating', () => { }, ); }); + +describe('collectMigrationSetupPlan non-interactive editor conflicts', () => { + let tmpDir: string; + + beforeEach(() => { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'vp-test-setup-plan-editor-')); + writePkgAt(tmpDir, { name: 'x' }); + }); + + afterEach(() => { + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + it('skips (never overwrites) existing non-JSON jetbrains files, only merges JSON-like ones', async () => { + fs.mkdirSync(path.join(tmpDir, '.idea'), { recursive: true }); + fs.writeFileSync( + path.join(tmpDir, '.idea', 'externalDependencies.xml'), + '', + ); + fs.writeFileSync(path.join(tmpDir, '.idea', 'workspace.xml'), ''); + + const plan = await collectMigrationSetupPlan( + tmpDir, + PackageManager.pnpm, + { + interactive: false, + hooks: false, + agent: false as const, + editor: 'jetbrains', + }, + undefined, + false, + ); + + expect(plan.editorConflictDecisions.get('externalDependencies.xml')).toBe('skip'); + expect(plan.editorConflictDecisions.get('workspace.xml')).toBe('skip'); + }); +}); diff --git a/packages/cli/src/migration/setup-plan.ts b/packages/cli/src/migration/setup-plan.ts index 660e46fdb0..d4728eac83 100644 --- a/packages/cli/src/migration/setup-plan.ts +++ b/packages/cli/src/migration/setup-plan.ts @@ -8,7 +8,12 @@ import { detectExistingAgentTargetPaths, selectAgentTargetPaths, } from '../utils/agent.ts'; -import { detectEditorConflicts, type EditorId, selectEditor } from '../utils/editor.ts'; +import { + detectEditorConflicts, + type EditorId, + isJsonLikeFile, + selectEditor, +} from '../utils/editor.ts'; import { cancelAndExit, promptGitHooks } from '../utils/prompts.ts'; import { confirmEslintMigration, @@ -141,7 +146,11 @@ async function collectEditorConfigPlan( } editorConflictDecisions.set(conflict.fileName, action); } else { - editorConflictDecisions.set(conflict.fileName, 'merge'); + // Non-JSON files (e.g. JetBrains XML) can't be merged, so only skip them here. + editorConflictDecisions.set( + conflict.fileName, + isJsonLikeFile(conflict.fileName) ? 'merge' : 'skip', + ); } } diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index 69eb9447a6..df3d769bea 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -510,7 +510,7 @@ async function writeEditorConfig({ } } -function isJsonLikeFile(fileName: string): boolean { +export function isJsonLikeFile(fileName: string): boolean { const ext = path.extname(fileName).toLowerCase(); return ext === '.json' || ext === '.jsonc'; } From 91eb277e3dcc90af55f925a740f7e4830f2909d4 Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Wed, 5 Aug 2026 11:11:52 +0000 Subject: [PATCH 11/19] adjust gitignore to ignore other files in .idea as well --- packages/cli/src/utils/editor.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index df3d769bea..bd4f36b135 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -181,7 +181,9 @@ const JETBRAINS_OXFMT_SETTINGS = ` `; -const JETBRAINS_GITIGNORE_ADDITION = `!externalDependencies.xml` +const JETBRAINS_GITIGNORE_ADDITION = `** +!externalDependencies.xml +`; type EditorConfigValue = Record | string; From 9c03b3078b5dfa5c4d0f8da45512b58938c99b69 Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Wed, 5 Aug 2026 11:33:56 +0000 Subject: [PATCH 12/19] resolve package manager correctly in the JetBrains config --- packages/cli/src/create/bin.ts | 2 ++ packages/cli/src/migration/bin.ts | 2 ++ .../cli/src/utils/__tests__/editor.spec.ts | 19 +++++++++++++++++-- packages/cli/src/utils/editor.ts | 19 +++++++++++++++---- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/create/bin.ts b/packages/cli/src/create/bin.ts index 0ef9c028e1..6e7cbe8e46 100644 --- a/packages/cli/src/create/bin.ts +++ b/packages/cli/src/create/bin.ts @@ -1101,6 +1101,7 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h interactive: options.interactive, silent: compactOutput, extraVsCodeSettings: { 'npm.scriptRunner': 'vp' }, + packageManager, }); if (selectedEditors?.includes('vscode')) { ensureGitignoreVsCodeEditorConfigs(fullPath); @@ -1269,6 +1270,7 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h interactive: options.interactive, silent: compactOutput, extraVsCodeSettings: { 'npm.scriptRunner': 'vp' }, + packageManager, }); if (selectedEditors?.includes('vscode')) { ensureGitignoreVsCodeEditorConfigs(fullPath); diff --git a/packages/cli/src/migration/bin.ts b/packages/cli/src/migration/bin.ts index 4065458314..1eb928f769 100644 --- a/packages/cli/src/migration/bin.ts +++ b/packages/cli/src/migration/bin.ts @@ -958,6 +958,7 @@ async function executeMigrationPlan( interactive, conflictDecisions: plan.editorConflictDecisions, silent: true, + packageManager: plan.packageManager, }); // 11. Add framework shims if requested @@ -1472,6 +1473,7 @@ async function main() { interactive: options.interactive, conflictDecisions: plan.editorConflictDecisions, silent: true, + packageManager, }); didMigrate = true; } diff --git a/packages/cli/src/utils/__tests__/editor.spec.ts b/packages/cli/src/utils/__tests__/editor.spec.ts index b31330a087..360f3c0ca2 100644 --- a/packages/cli/src/utils/__tests__/editor.spec.ts +++ b/packages/cli/src/utils/__tests__/editor.spec.ts @@ -586,7 +586,22 @@ describe('writeEditorConfigs', () => { ); const gitignore = fs.readFileSync(path.join(projectRoot, '.idea', '.gitignore'), 'utf8'); - expect(gitignore).toBe('!externalDependencies.xml'); + expect(gitignore).toBe('**\n!externalDependencies.xml\n'); + }); + + it('writes workspace.xml with the resolved package manager', async () => { + const projectRoot = createTempDir(); + + await writeEditorConfigs({ + projectRoot, + editorId: 'jetbrains', + interactive: false, + silent: true, + packageManager: 'yarn', + }); + + const workspaceXml = fs.readFileSync(path.join(projectRoot, '.idea', 'workspace.xml'), 'utf8'); + expect(workspaceXml).toContain('"nodejs_package_manager_path": "yarn"'); }); it('does not overwrite existing non-JSON jetbrains file in non-interactive mode', async () => { @@ -615,6 +630,6 @@ describe('writeEditorConfigs', () => { expect(oxfmtSettingsXml).toContain(''); const gitignore = fs.readFileSync(path.join(projectRoot, '.idea', '.gitignore'), 'utf8'); - expect(gitignore).toBe('!externalDependencies.xml'); + expect(gitignore).toBe('**\n!externalDependencies.xml\n'); }); }); diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index bd4f36b135..2019bde44e 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -14,6 +14,7 @@ import { parse as parseJsonc, } from 'jsonc-parser'; +import { PackageManager } from '../types/package.ts'; import { detectFormattingOptions, writeJsonFile } from './json.ts'; // Language-specific overrides because user-level [lang] settings beat the workspace default @@ -159,19 +160,21 @@ const JETBRAINS_EXTERNAL_DEPENDENCIES = ` `; -const JETBRAINS_WORKSPACE_CONFIG = ` +function jetbrainsWorkspaceConfig(packageManager: PackageManager): string { + return ` `; +} const JETBRAINS_OXFMT_SETTINGS = ` @@ -211,7 +214,8 @@ export const EDITORS = [ targetDir: '.idea', files: { 'externalDependencies.xml': JETBRAINS_EXTERNAL_DEPENDENCIES, - 'workspace.xml': JETBRAINS_WORKSPACE_CONFIG, + // Placeholder; writeEditorConfig() regenerates this with the resolved package manager. + 'workspace.xml': jetbrainsWorkspaceConfig(PackageManager.pnpm), 'OxfmtSettings.xml': JETBRAINS_OXFMT_SETTINGS, '.gitignore': JETBRAINS_GITIGNORE_ADDITION, }, @@ -381,6 +385,7 @@ export async function writeEditorConfigs({ conflictDecisions, silent = false, extraVsCodeSettings, + packageManager = PackageManager.pnpm, }: { projectRoot: string; editorId: EditorSelection; @@ -388,6 +393,7 @@ export async function writeEditorConfigs({ conflictDecisions?: Map; silent?: boolean; extraVsCodeSettings?: Record; + packageManager?: PackageManager; }) { const editorIds = normalizeEditorSelection(editorId); if (editorIds.length === 0) { @@ -402,6 +408,7 @@ export async function writeEditorConfigs({ conflictDecisions, silent, extraVsCodeSettings, + packageManager, }); } } @@ -413,6 +420,7 @@ async function writeEditorConfig({ conflictDecisions, silent, extraVsCodeSettings, + packageManager, }: { projectRoot: string; editorId: EditorId; @@ -420,6 +428,7 @@ async function writeEditorConfig({ conflictDecisions?: Map; silent: boolean; extraVsCodeSettings?: Record; + packageManager: PackageManager; }) { const editorConfig = EDITORS.find((e) => e.id === editorId); if (!editorConfig) { @@ -433,7 +442,9 @@ async function writeEditorConfig({ const incoming: EditorConfigValue = editorId === 'vscode' && fileName === 'settings.json' && extraVsCodeSettings ? { ...extraVsCodeSettings, ...baseIncoming } - : baseIncoming; + : editorId === 'jetbrains' && fileName === 'workspace.xml' + ? jetbrainsWorkspaceConfig(packageManager) + : baseIncoming; const filePath = path.join(targetDir, fileName); const jsonFormat = isJsonLikeFile(fileName); From 4e06aac54949f2b8e10582e3a2d6bf4dc4ca01eb Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Wed, 5 Aug 2026 11:39:04 +0000 Subject: [PATCH 13/19] use JSON.stringify for making the PropertiesComponent in JB config + normalize nodejs_interpreter_path --- packages/cli/src/utils/editor.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index 2019bde44e..23540bc098 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -164,13 +164,13 @@ function jetbrainsWorkspaceConfig(packageManager: PackageManager): string { return ` - + })}]]> `; From 0fc5db774c4da1d736386f5914f52284f92cea0b Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Fri, 7 Aug 2026 08:26:40 +0000 Subject: [PATCH 14/19] chore(cli): alias --editor intellij and --editor webstorm to --editor jetbrains also warns if it is passed --- .../cli/src/utils/__tests__/editor.spec.ts | 75 ++++++++++++++++++- packages/cli/src/utils/editor.ts | 30 ++++++-- 2 files changed, 98 insertions(+), 7 deletions(-) diff --git a/packages/cli/src/utils/__tests__/editor.spec.ts b/packages/cli/src/utils/__tests__/editor.spec.ts index 360f3c0ca2..28eb1bcc70 100644 --- a/packages/cli/src/utils/__tests__/editor.spec.ts +++ b/packages/cli/src/utils/__tests__/editor.spec.ts @@ -6,7 +6,12 @@ import * as prompts from '@voidzero-dev/vite-plus-prompts'; import { parse as parseJsonc } from 'jsonc-parser'; import { afterEach, describe, expect, it, vi } from 'vitest'; -import { detectExistingEditors, selectEditors, writeEditorConfigs } from '../editor.js'; +import { + detectExistingEditors, + selectEditor, + selectEditors, + writeEditorConfigs, +} from '../editor.js'; const tempDirs: string[] = []; @@ -75,6 +80,74 @@ describe('selectEditors', () => { }), ).resolves.toEqual(['zed']); }); + + it('resolves --editor intellij to jetbrains and warns about the non-canonical ID used', async () => { + const warnSpy = vi.spyOn(prompts.log, 'warn').mockImplementation(() => {}); + + await expect( + selectEditors({ + interactive: false, + editor: 'intellij', + onCancel: vi.fn(), + }), + ).resolves.toEqual(['jetbrains']); + + expect(warnSpy).toHaveBeenCalledWith( + expect.stringContaining('--editor intellij was passed; use --editor jetbrains instead, as it\'s the canonical ID for that editor.'), + ); + }); + + it('resolves --editor webstorm to jetbrains and warns about the non-canonical ID used', async () => { + const warnSpy = vi.spyOn(prompts.log, 'warn').mockImplementation(() => {}); + + await expect( + selectEditors({ + interactive: false, + editor: 'webstorm', + onCancel: vi.fn(), + }), + ).resolves.toEqual(['jetbrains']); + + expect(warnSpy).toHaveBeenCalledWith( + expect.stringContaining('--editor webstorm was passed; use --editor jetbrains instead, as it\'s the canonical ID for that editor.'), + ); + }); + + it('does not show intellij/webstorm aliases as interactive TUI options', async () => { + const multiselectSpy = vi.spyOn(prompts, 'multiselect').mockResolvedValue(['vscode']); + + await selectEditors({ + interactive: true, + onCancel: vi.fn(), + }); + + expect(multiselectSpy).toHaveBeenCalledWith( + expect.objectContaining({ + options: expect.not.arrayContaining([ + expect.objectContaining({ value: 'intellij' }), + expect.objectContaining({ value: 'webstorm' }), + ]), + }), + ); + }); +}); + +describe('selectEditor', () => { + it('resolves --editor intellij to jetbrains and warns about the non-canonical ID used', async () => { + const warnSpy = vi.spyOn(prompts.log, 'warn').mockImplementation(() => {}); + + await expect( + selectEditor({ + interactive: false, + editor: 'intellij', + onCancel: vi.fn(), + }), + ).resolves.toBe('jetbrains'); + + expect(warnSpy).toHaveBeenCalledWith( + expect.stringContaining('--editor intellij was passed; use --editor jetbrains instead, as it\'s the canonical ID for that editor.'), + ); + }); }); describe('detectExistingEditors', () => { diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index 23540bc098..85986539d3 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -165,11 +165,11 @@ function jetbrainsWorkspaceConfig(packageManager: PackageManager): string { @@ -222,6 +222,12 @@ export const EDITORS = [ }, ] as const; +// Deprecated aliases kept for backwards-compatible `--editor` values; not shown as TUI options. +const EDITOR_ALIASES = [ + { id: 'intellij', alias: 'jetbrains' }, + { id: 'webstorm', alias: 'jetbrains' }, +] as const; + export type EditorId = (typeof EDITORS)[number]['id']; type EditorSelection = EditorId | readonly EditorId[] | undefined; @@ -686,7 +692,19 @@ function resolveEditorId(editor: string): EditorId | undefined { const match = EDITORS.find( (option) => option.id === normalized || option.label.toLowerCase() === normalized, ); - return match?.id; + if (match) { + return match.id; + } + + const aliasMatch = EDITOR_ALIASES.find((option) => option.id === normalized); + if (aliasMatch) { + prompts.log.warn( + `--editor ${aliasMatch.id} was passed; use --editor ${aliasMatch.alias} instead, as it's the canonical ID for the editor.`, + ); + return aliasMatch.alias; + } + + return undefined; } function resolveEditorIds(editors: readonly string[]): EditorId[] | undefined { From a71e16f1a159140613cd27281a68ce54b2cca049 Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:53:03 +0000 Subject: [PATCH 15/19] fix(cli): remove the need for importing os module --- packages/cli/src/utils/editor.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index 78b65afa53..e91bc2e2cf 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -1,6 +1,5 @@ import fs from 'node:fs'; import fsPromises from 'node:fs/promises'; -import os from 'node:os'; import path from 'node:path'; import { styleText } from 'node:util'; @@ -110,7 +109,7 @@ function jetbrainsWorkspaceConfig(packageManager: PackageManager): string { From 9b5445709169551551947d2ebebb5b7fa328e45a Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:54:30 +0000 Subject: [PATCH 16/19] docs: use $USER_HOME$ on .idea/workspace.xml config --- docs/guide/ide-integration.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guide/ide-integration.md b/docs/guide/ide-integration.md index f477d95620..4aef237b1d 100644 --- a/docs/guide/ide-integration.md +++ b/docs/guide/ide-integration.md @@ -134,8 +134,8 @@ You can also manually set up the IDE configuration to match your Vite+ setup: "javascript.nodejs.core.library.configured.version": "24.18.0", // Replace with your selected Node.js version "javascript.nodejs.core.library.typings.version": "24.13.3", // Replace with the version of @types/node that corresponds to your runtime (or omit if you don't want it) "javascript.preferred.runtime.type.id": "node", - "nodejs_interpreter_path": "~/.vite-plus/bin/node", // Replace ~ with the path to your home directory, IntelliJ/WebStorm doesn't understand ~ - "nodejs_package_manager_path": "pnpm", // Replace with your package manager of choice + "nodejs_interpreter_path": "$USER_HOME$/.vite-plus/bin/node", + "nodejs_package_manager_path": "pnpm" // Replace with your package manager of choice } }]]> From c6a4aec02af0f61006008dc97f8947111355a3e2 Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Fri, 7 Aug 2026 12:39:51 +0000 Subject: [PATCH 17/19] fix: pretty-print JSON.striingify output for JetBrains config --- packages/cli/src/utils/editor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index e91bc2e2cf..cc0eee73e8 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -112,7 +112,7 @@ function jetbrainsWorkspaceConfig(packageManager: PackageManager): string { nodejs_interpreter_path: '$USER_HOME$/.vite-plus/bin/node.exe', nodejs_package_manager_path: packageManager, }, - })}]]> + }, null, 2)}]]> `; From 90ba55ff36d70bf50def25817f9469fcf5b70da5 Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Fri, 7 Aug 2026 12:41:48 +0000 Subject: [PATCH 18/19] chore: fmt --- packages/cli/src/utils/__tests__/editor.spec.ts | 12 +++++++++--- packages/cli/src/utils/editor.ts | 16 ++++++++++------ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/packages/cli/src/utils/__tests__/editor.spec.ts b/packages/cli/src/utils/__tests__/editor.spec.ts index e0e095af33..a6ad7fbac2 100644 --- a/packages/cli/src/utils/__tests__/editor.spec.ts +++ b/packages/cli/src/utils/__tests__/editor.spec.ts @@ -93,7 +93,9 @@ describe('selectEditors', () => { ).resolves.toEqual(['jetbrains']); expect(warnSpy).toHaveBeenCalledWith( - expect.stringContaining('--editor intellij was passed; use --editor jetbrains instead, as it\'s the canonical ID for that editor.'), + expect.stringContaining( + "--editor intellij was passed; use --editor jetbrains instead, as it's the canonical ID for that editor.", + ), ); }); @@ -109,7 +111,9 @@ describe('selectEditors', () => { ).resolves.toEqual(['jetbrains']); expect(warnSpy).toHaveBeenCalledWith( - expect.stringContaining('--editor webstorm was passed; use --editor jetbrains instead, as it\'s the canonical ID for that editor.'), + expect.stringContaining( + "--editor webstorm was passed; use --editor jetbrains instead, as it's the canonical ID for that editor.", + ), ); }); @@ -145,7 +149,9 @@ describe('selectEditor', () => { ).resolves.toBe('jetbrains'); expect(warnSpy).toHaveBeenCalledWith( - expect.stringContaining('--editor intellij was passed; use --editor jetbrains instead, as it\'s the canonical ID for that editor.'), + expect.stringContaining( + "--editor intellij was passed; use --editor jetbrains instead, as it's the canonical ID for that editor.", + ), ); }); }); diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index cc0eee73e8..267ed40cc7 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -106,13 +106,17 @@ function jetbrainsWorkspaceConfig(packageManager: PackageManager): string { return ` - + null, + 2, + )}]]> `; From 6b088768b6b5bd4940b09afb3a02bc70f52108fc Mon Sep 17 00:00:00 2001 From: KTrain <69028025+KTrain5169@users.noreply.github.com> Date: Fri, 7 Aug 2026 12:49:01 +0000 Subject: [PATCH 19/19] chore: fix tests --- packages/cli/src/utils/__tests__/editor.spec.ts | 2 +- packages/cli/src/utils/editor.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/utils/__tests__/editor.spec.ts b/packages/cli/src/utils/__tests__/editor.spec.ts index a6ad7fbac2..bf8746f06a 100644 --- a/packages/cli/src/utils/__tests__/editor.spec.ts +++ b/packages/cli/src/utils/__tests__/editor.spec.ts @@ -652,7 +652,7 @@ describe('writeEditorConfigs', () => { expect(workspaceXml).toContain(''); expect(workspaceXml).toContain('"javascript.preferred.runtime.type.id": "node"'); expect(workspaceXml).toContain( - `"nodejs_interpreter_path": "${os.homedir()}/.vite-plus/bin/node"`, + `"nodejs_interpreter_path": "$USER_HOME$/.vite-plus/bin/node.exe"`, ); expect(workspaceXml).toContain('"nodejs_package_manager_path": "pnpm"'); diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index 267ed40cc7..5de892ba43 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -645,7 +645,7 @@ function resolveEditorId(editor: string): EditorId | undefined { const aliasMatch = EDITOR_ALIASES.find((option) => option.id === normalized); if (aliasMatch) { prompts.log.warn( - `--editor ${aliasMatch.id} was passed; use --editor ${aliasMatch.alias} instead, as it's the canonical ID for the editor.`, + `--editor ${aliasMatch.id} was passed; use --editor ${aliasMatch.alias} instead, as it's the canonical ID for that editor.`, ); return aliasMatch.alias; }