diff --git a/docs/guide/ide-integration.md b/docs/guide/ide-integration.md index 0c28266b16..c1e4b53ce9 100644 --- a/docs/guide/ide-integration.md +++ b/docs/guide/ide-integration.md @@ -22,6 +22,10 @@ You can also manually set up the VS Code config: ```json [.vscode/settings.json] { "editor.defaultFormatter": "oxc.oxc-vscode", + "[javascript]": { "editor.defaultFormatter": "oxc.oxc-vscode" }, + "[javascriptreact]": { "editor.defaultFormatter": "oxc.oxc-vscode" }, + "[typescript]": { "editor.defaultFormatter": "oxc.oxc-vscode" }, + "[typescriptreact]": { "editor.defaultFormatter": "oxc.oxc-vscode" }, "oxc.fmt.configPath": "./vite.config.ts", "editor.formatOnSave": true, "editor.formatOnSaveMode": "file", @@ -31,7 +35,7 @@ You can also manually set up the VS Code config: } ``` -This gives the project a shared default formatter and enables Oxc-powered fix actions on save. Setting `oxc.fmt.configPath` to `./vite.config.ts` keeps editor format-on-save aligned with the `fmt` block in your Vite+ config. Vite+ uses `formatOnSaveMode: "file"` because Oxfmt does not support partial formatting. +This gives the project a shared default formatter and enables Oxc-powered fix actions on save. The language-specific override blocks (`[javascript]`, `[typescript]`, etc.) are required because VS Code prioritizes user-level `[language]` settings over the workspace-level `editor.defaultFormatter` — without them, a global Prettier configuration would silently take over. Setting `oxc.fmt.configPath` to `./vite.config.ts` keeps editor format-on-save aligned with the `fmt` block in your Vite+ config. Vite+ uses `formatOnSaveMode: "file"` because Oxfmt does not support partial formatting. To let the VS Code NPM Scripts panel run scripts through `vp`, add the following to your `.vscode/settings.json`: diff --git a/packages/cli/src/utils/__tests__/editor.spec.ts b/packages/cli/src/utils/__tests__/editor.spec.ts index 3aab6a6767..8e718c873e 100644 --- a/packages/cli/src/utils/__tests__/editor.spec.ts +++ b/packages/cli/src/utils/__tests__/editor.spec.ts @@ -111,6 +111,9 @@ describe('writeEditorConfigs', () => { expect(settings['oxc.fmt.configPath']).toBe('./vite.config.ts'); expect(settings['editor.formatOnSave']).toBe(true); expect(settings['npm.scriptRunner']).toBeUndefined(); + for (const lang of ['[javascript]', '[javascriptreact]', '[typescript]', '[typescriptreact]']) { + expect(settings[lang]).toEqual({ 'editor.defaultFormatter': 'oxc.oxc-vscode' }); + } }); it('includes additionalSettings in vscode settings.json when provided', async () => { @@ -142,6 +145,9 @@ describe('writeEditorConfigs', () => { `{ // JSONC comment "editor.formatOnSave": false, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + }, "editor.codeActionsOnSave": { // preserve existing key "source.organizeImports": "explicit", @@ -165,11 +171,17 @@ describe('writeEditorConfigs', () => { // Existing key is preserved (merge never overwrites) expect(settings['editor.formatOnSave']).toBe(false); + expect(settings['[typescript]']).toEqual({ + 'editor.defaultFormatter': 'esbenp.prettier-vscode', + }); // New keys are added expect(settings['editor.defaultFormatter']).toBe('oxc.oxc-vscode'); expect(settings['oxc.fmt.configPath']).toBe('./vite.config.ts'); expect(settings['npm.scriptRunner']).toBe('vp'); + for (const lang of ['[javascript]', '[javascriptreact]', '[typescriptreact]']) { + expect(settings[lang]).toEqual({ 'editor.defaultFormatter': 'oxc.oxc-vscode' }); + } const codeActions = settings['editor.codeActionsOnSave'] as Record; expect(codeActions['source.organizeImports']).toBe('explicit'); diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index b73426de94..b392808048 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -7,9 +7,17 @@ import * as prompts from '@voidzero-dev/vite-plus-prompts'; import { readJsonFile, writeJsonFile } from './json.ts'; +// Language-specific overrides because user-level [lang] settings beat the workspace default +const VSCODE_LANGUAGE_OVERRIDES = { + '[javascript]': { 'editor.defaultFormatter': 'oxc.oxc-vscode' }, + '[javascriptreact]': { 'editor.defaultFormatter': 'oxc.oxc-vscode' }, + '[typescript]': { 'editor.defaultFormatter': 'oxc.oxc-vscode' }, + '[typescriptreact]': { 'editor.defaultFormatter': 'oxc.oxc-vscode' }, +} as const; + const VSCODE_SETTINGS = { - // Set as default over per-lang to avoid conflicts with other formatters 'editor.defaultFormatter': 'oxc.oxc-vscode', + ...VSCODE_LANGUAGE_OVERRIDES, 'oxc.fmt.configPath': './vite.config.ts', 'editor.formatOnSave': true, // Oxfmt does not support partial formatting