Skip to content

Commit bcc93a4

Browse files
oilaterjong-kyung
andauthored
feat(vscode): add language-specific formatter overrides to .vscode/settings.json (#1491)
Closes #1485 ## Summary - Re-assert `editor.defaultFormatter: oxc.oxc-vscode` inside `[javascript]`/`[javascriptreact]`/`[typescript]`/`[typescriptreact]` blocks in the generated `.vscode/settings.json`. Without these, a user-level `[language]` setting (e.g. a global Prettier override) silently wins over the workspace-level default. - Extract the override blocks into a dedicated `VSCODE_LANGUAGE_OVERRIDES` constant so `VSCODE_SETTINGS` keeps a single concern. - Update `docs/guide/ide-integration.md` to reflect the new shape and explain why per-language blocks are required. - Existing `deepMerge` behavior is unchanged, so a user's pre-existing `[typescript]: prettier` block is still preserved during `vp create` against an existing `.vscode/settings.json`. ## Approach The main question was whether to map `[lang]` blocks per project template or to always include the JS/TS family. Picked the latter because - `vp create` accepts remote templates (`github:user/repo`, arbitrary `create-*` packages) where the language set can't be known up front — a per-template branch ends in a JS/TS fallback for these anyway, so the per-template path doesn't actually buy correctness for the cases it's meant to help. - Keeps `vp create` and `vp migrate` consistent with a single source of truth in `VSCODE_SETTINGS`. - Including unused `[lang]` blocks has no runtime effect (VS Code only applies them when matching files are opened) and is evolution-safe if the user later adds a `.ts` file to an initially JS-only project. ## Tests - `pnpm -F vite-plus test src/utils/__tests__/editor.spec.ts` — extended assertions verify the four `[lang]` blocks are written, and that an existing user's `[typescript]: prettier` is preserved during merge. --------- Co-authored-by: JongKyung Lee <118944686+jong-kyung@users.noreply.github.com>
1 parent 6f7fbfa commit bcc93a4

3 files changed

Lines changed: 26 additions & 2 deletions

File tree

docs/guide/ide-integration.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ You can also manually set up the VS Code config:
2222
```json [.vscode/settings.json]
2323
{
2424
"editor.defaultFormatter": "oxc.oxc-vscode",
25+
"[javascript]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
26+
"[javascriptreact]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
27+
"[typescript]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
28+
"[typescriptreact]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
2529
"oxc.fmt.configPath": "./vite.config.ts",
2630
"editor.formatOnSave": true,
2731
"editor.formatOnSaveMode": "file",
@@ -31,7 +35,7 @@ You can also manually set up the VS Code config:
3135
}
3236
```
3337

34-
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.
38+
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.
3539

3640
To let the VS Code NPM Scripts panel run scripts through `vp`, add the following to your `.vscode/settings.json`:
3741

packages/cli/src/utils/__tests__/editor.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ describe('writeEditorConfigs', () => {
111111
expect(settings['oxc.fmt.configPath']).toBe('./vite.config.ts');
112112
expect(settings['editor.formatOnSave']).toBe(true);
113113
expect(settings['npm.scriptRunner']).toBeUndefined();
114+
for (const lang of ['[javascript]', '[javascriptreact]', '[typescript]', '[typescriptreact]']) {
115+
expect(settings[lang]).toEqual({ 'editor.defaultFormatter': 'oxc.oxc-vscode' });
116+
}
114117
});
115118

116119
it('includes additionalSettings in vscode settings.json when provided', async () => {
@@ -142,6 +145,9 @@ describe('writeEditorConfigs', () => {
142145
`{
143146
// JSONC comment
144147
"editor.formatOnSave": false,
148+
"[typescript]": {
149+
"editor.defaultFormatter": "esbenp.prettier-vscode",
150+
},
145151
"editor.codeActionsOnSave": {
146152
// preserve existing key
147153
"source.organizeImports": "explicit",
@@ -165,11 +171,17 @@ describe('writeEditorConfigs', () => {
165171

166172
// Existing key is preserved (merge never overwrites)
167173
expect(settings['editor.formatOnSave']).toBe(false);
174+
expect(settings['[typescript]']).toEqual({
175+
'editor.defaultFormatter': 'esbenp.prettier-vscode',
176+
});
168177

169178
// New keys are added
170179
expect(settings['editor.defaultFormatter']).toBe('oxc.oxc-vscode');
171180
expect(settings['oxc.fmt.configPath']).toBe('./vite.config.ts');
172181
expect(settings['npm.scriptRunner']).toBe('vp');
182+
for (const lang of ['[javascript]', '[javascriptreact]', '[typescriptreact]']) {
183+
expect(settings[lang]).toEqual({ 'editor.defaultFormatter': 'oxc.oxc-vscode' });
184+
}
173185

174186
const codeActions = settings['editor.codeActionsOnSave'] as Record<string, unknown>;
175187
expect(codeActions['source.organizeImports']).toBe('explicit');

packages/cli/src/utils/editor.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,17 @@ import * as prompts from '@voidzero-dev/vite-plus-prompts';
77

88
import { readJsonFile, writeJsonFile } from './json.ts';
99

10+
// Language-specific overrides because user-level [lang] settings beat the workspace default
11+
const VSCODE_LANGUAGE_OVERRIDES = {
12+
'[javascript]': { 'editor.defaultFormatter': 'oxc.oxc-vscode' },
13+
'[javascriptreact]': { 'editor.defaultFormatter': 'oxc.oxc-vscode' },
14+
'[typescript]': { 'editor.defaultFormatter': 'oxc.oxc-vscode' },
15+
'[typescriptreact]': { 'editor.defaultFormatter': 'oxc.oxc-vscode' },
16+
} as const;
17+
1018
const VSCODE_SETTINGS = {
11-
// Set as default over per-lang to avoid conflicts with other formatters
1219
'editor.defaultFormatter': 'oxc.oxc-vscode',
20+
...VSCODE_LANGUAGE_OVERRIDES,
1321
'oxc.fmt.configPath': './vite.config.ts',
1422
'editor.formatOnSave': true,
1523
// Oxfmt does not support partial formatting

0 commit comments

Comments
 (0)