diff --git a/packages/cli/src/utils/editor.ts b/packages/cli/src/utils/editor.ts index 297dc82b21..ce25c25043 100644 --- a/packages/cli/src/utils/editor.ts +++ b/packages/cli/src/utils/editor.ts @@ -21,6 +21,119 @@ const VSCODE_EXTENSIONS = { recommendations: ['VoidZero.vite-plus-extension-pack'], } as const; +const ZED_SETTINGS = { + lsp: { + oxlint: { + initialization_options: { + settings: { + configPath: './.oxlintrc.json', + run: 'onType', + disableNestedConfig: false, + fixKind: 'safe_fix', + typeAware: true, + unusedDisableDirectives: 'deny', + }, + }, + }, + oxfmt: { + initialization_options: { + settings: { + configPath: './.oxfmtrc.jsonc', + run: 'onSave', + }, + }, + }, + }, + languages: { + CSS: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + GraphQL: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + Handlebars: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + HTML: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + JavaScript: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + code_action: 'source.fixAll.oxc', + }, + JSX: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + JSON: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + JSON5: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + JSONC: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + Less: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + Markdown: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + MDX: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + SCSS: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + TypeScript: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + TSX: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + Vue: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + YAML: { + format_on_save: 'on', + prettier: { allowed: false }, + formatter: [{ language_server: { name: 'oxfmt' } }], + }, + }, +} as const; + export const EDITORS = [ { id: 'vscode', @@ -31,6 +144,14 @@ export const EDITORS = [ 'extensions.json': VSCODE_EXTENSIONS as Record, }, }, + { + id: 'zed', + label: 'Zed', + targetDir: '.zed', + files: { + 'settings.json': ZED_SETTINGS as Record, + }, + }, ] as const; export type EditorId = (typeof EDITORS)[number]['id']; @@ -247,9 +368,15 @@ function mergeEditorConfigs( }; } - // settings.json: 2-level deep merge, preserving existing keys - const result = { ...existing }; - for (const [key, value] of Object.entries(incoming)) { + return deepMerge(existing, incoming); +} + +function deepMerge( + target: Record, + source: Record, +): Record { + const result = { ...target }; + for (const [key, value] of Object.entries(source)) { if (!(key in result)) { result[key] = value; } else if ( @@ -260,13 +387,11 @@ function mergeEditorConfigs( value !== null && !Array.isArray(value) ) { - // Nested object: merge preserving existing keys - result[key] = { - ...(value as Record), - ...(result[key] as Record), - }; + result[key] = deepMerge( + result[key] as Record, + value as Record, + ); } - // else: existing key is preserved as-is } return result; }