diff --git a/apps/oxfmt/src-js/config.generated.ts b/apps/oxfmt/src-js/config.generated.ts index 6e60de5b86216..336f8d883a1e5 100644 --- a/apps/oxfmt/src-js/config.generated.ts +++ b/apps/oxfmt/src-js/config.generated.ts @@ -197,7 +197,7 @@ export interface Oxfmtrc { * Specify the number of spaces per indentation-level. * * - Default: `2` - * - Overrides `.editorconfig.indent_size` + * - Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`) */ tabWidth?: number; /** @@ -474,7 +474,7 @@ export interface FormatConfig { * Specify the number of spaces per indentation-level. * * - Default: `2` - * - Overrides `.editorconfig.indent_size` + * - Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`) */ tabWidth?: number; /** diff --git a/apps/oxfmt/src/core/config.rs b/apps/oxfmt/src/core/config.rs index 9e8318978bf95..3b938aec6b9b1 100644 --- a/apps/oxfmt/src/core/config.rs +++ b/apps/oxfmt/src/core/config.rs @@ -611,6 +611,7 @@ fn load_editorconfig( /// - end_of_line /// - indent_style /// - indent_size +/// - tab_width /// - insert_final_newline fn has_editorconfig_overrides(editorconfig: &EditorConfig, path: &Path) -> bool { let sections = editorconfig.sections(); @@ -632,6 +633,7 @@ fn has_editorconfig_overrides(editorconfig: &EditorConfig, path: &Path) -> bool || resolved.end_of_line != root.end_of_line || resolved.indent_style != root.indent_style || resolved.indent_size != root.indent_size + || resolved.tab_width != root.tab_width || resolved.insert_final_newline != root.insert_final_newline } // No `[*]` section means any resolved property is an override @@ -640,6 +642,7 @@ fn has_editorconfig_overrides(editorconfig: &EditorConfig, path: &Path) -> bool || resolved.end_of_line != EditorConfigProperty::Unset || resolved.indent_style != EditorConfigProperty::Unset || resolved.indent_size != EditorConfigProperty::Unset + || resolved.tab_width != EditorConfigProperty::Unset || resolved.insert_final_newline != EditorConfigProperty::Unset } } @@ -676,11 +679,17 @@ fn apply_editorconfig(config: &mut FormatConfig, props: &EditorConfigProperties) }); } - #[expect(clippy::cast_possible_truncation)] - if config.tab_width.is_none() - && let EditorConfigProperty::Value(size) = props.indent_size - { - config.tab_width = Some(size as u8); + if config.tab_width.is_none() { + // Match Prettier's behavior: Only use `indent_size` when `useTabs: false`. + // https://github.com/prettier/prettier/blob/90983f40dce5e20beea4e5618b5e0426a6a7f4f0/src/config/editorconfig/editorconfig-to-prettier.js#L25-L30 + #[expect(clippy::cast_possible_truncation)] + if config.use_tabs == Some(false) + && let EditorConfigProperty::Value(size) = props.indent_size + { + config.tab_width = Some(size as u8); + } else if let EditorConfigProperty::Value(size) = props.tab_width { + config.tab_width = Some(size as u8); + } } if config.insert_final_newline.is_none() diff --git a/apps/oxfmt/src/core/oxfmtrc/format_config.rs b/apps/oxfmt/src/core/oxfmtrc/format_config.rs index 4bf9325eec4a3..3e8d550474f81 100644 --- a/apps/oxfmt/src/core/oxfmtrc/format_config.rs +++ b/apps/oxfmt/src/core/oxfmtrc/format_config.rs @@ -63,7 +63,7 @@ pub struct FormatConfig { /// Specify the number of spaces per indentation-level. /// /// - Default: `2` - /// - Overrides `.editorconfig.indent_size` + /// - Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`) #[serde(skip_serializing_if = "Option::is_none")] pub tab_width: Option, /// Which end of line characters to apply. diff --git a/apps/oxfmt/test/cli/editorconfig/__snapshots__/editorconfig.test.ts.snap b/apps/oxfmt/test/cli/editorconfig/__snapshots__/editorconfig.test.ts.snap index 1cc939a6af269..53155cc38a210 100644 --- a/apps/oxfmt/test/cli/editorconfig/__snapshots__/editorconfig.test.ts.snap +++ b/apps/oxfmt/test/cli/editorconfig/__snapshots__/editorconfig.test.ts.snap @@ -153,3 +153,17 @@ nested/deep/test.json --------------------" `; + +exports[`editorconfig > tab_width fallback when indent_size is not set 1`] = ` +"--- FILE ----------- +test.js +--- BEFORE --------- +if (condition) { console.log("hello world"); } + +--- AFTER ---------- +if (condition) { + console.log("hello world"); +} + +--------------------" +`; diff --git a/apps/oxfmt/test/cli/editorconfig/editorconfig.test.ts b/apps/oxfmt/test/cli/editorconfig/editorconfig.test.ts index 1398ab267d04d..26cda5a909467 100644 --- a/apps/oxfmt/test/cli/editorconfig/editorconfig.test.ts +++ b/apps/oxfmt/test/cli/editorconfig/editorconfig.test.ts @@ -78,6 +78,18 @@ describe("editorconfig", () => { expect(snapshot).toMatchSnapshot(); }); + // .editorconfig: + // [*] indent_style=space, tab_width=8 + // (no indent_size) + // + // Expected: useTabs=false, tabWidth=8 (tab_width used as fallback for indent_size) + // - Indentation should use 8 spaces + it("tab_width fallback when indent_size is not set", async () => { + const cwd = join(fixturesDir, "tab_width_fallback"); + const snapshot = await runWriteModeAndSnapshot(cwd, ["test.js"]); + expect(snapshot).toMatchSnapshot(); + }); + // .editorconfig: (empty file) // // Expected: default settings (useTabs=false, tabWidth=2) diff --git a/apps/oxfmt/test/cli/editorconfig/fixtures/tab_width_fallback/.editorconfig b/apps/oxfmt/test/cli/editorconfig/fixtures/tab_width_fallback/.editorconfig new file mode 100644 index 0000000000000..6abab0fb71661 --- /dev/null +++ b/apps/oxfmt/test/cli/editorconfig/fixtures/tab_width_fallback/.editorconfig @@ -0,0 +1,3 @@ +[*] +indent_style = space +tab_width = 8 diff --git a/apps/oxfmt/test/cli/editorconfig/fixtures/tab_width_fallback/test.js b/apps/oxfmt/test/cli/editorconfig/fixtures/tab_width_fallback/test.js new file mode 100644 index 0000000000000..c62814b697ed6 --- /dev/null +++ b/apps/oxfmt/test/cli/editorconfig/fixtures/tab_width_fallback/test.js @@ -0,0 +1 @@ +if (condition) { console.log("hello world"); } diff --git a/npm/oxfmt/configuration_schema.json b/npm/oxfmt/configuration_schema.json index 7e1eaf864128f..2fa1c4432a30a 100644 --- a/npm/oxfmt/configuration_schema.json +++ b/npm/oxfmt/configuration_schema.json @@ -162,11 +162,11 @@ "markdownDescription": "Sort Tailwind CSS classes.\n\nUsing the same algorithm as [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss).\nOption names omit the `tailwind` prefix used in the original plugin (e.g., `config` instead of `tailwindConfig`).\nFor details, see each field's documentation.\n\nPass `true` or an object to enable with defaults, or omit/set `false` to disable.\n\n- Default: Disabled" }, "tabWidth": { - "description": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size`", + "description": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`)", "type": "integer", "format": "uint8", "minimum": 0.0, - "markdownDescription": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size`" + "markdownDescription": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`)" }, "trailingComma": { "description": "Print trailing commas wherever possible in multi-line comma-separated syntactic structures.\n\nA single-line array, for example, never gets trailing commas.\n\n- Default: `\"all\"`", @@ -391,11 +391,11 @@ "markdownDescription": "Sort Tailwind CSS classes.\n\nUsing the same algorithm as [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss).\nOption names omit the `tailwind` prefix used in the original plugin (e.g., `config` instead of `tailwindConfig`).\nFor details, see each field's documentation.\n\nPass `true` or an object to enable with defaults, or omit/set `false` to disable.\n\n- Default: Disabled" }, "tabWidth": { - "description": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size`", + "description": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`)", "type": "integer", "format": "uint8", "minimum": 0.0, - "markdownDescription": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size`" + "markdownDescription": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`)" }, "trailingComma": { "description": "Print trailing commas wherever possible in multi-line comma-separated syntactic structures.\n\nA single-line array, for example, never gets trailing commas.\n\n- Default: `\"all\"`", diff --git a/tasks/website_formatter/src/snapshots/schema_json.snap b/tasks/website_formatter/src/snapshots/schema_json.snap index 83b06ad44e9c5..4205ce222ee55 100644 --- a/tasks/website_formatter/src/snapshots/schema_json.snap +++ b/tasks/website_formatter/src/snapshots/schema_json.snap @@ -166,11 +166,11 @@ expression: json "markdownDescription": "Sort Tailwind CSS classes.\n\nUsing the same algorithm as [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss).\nOption names omit the `tailwind` prefix used in the original plugin (e.g., `config` instead of `tailwindConfig`).\nFor details, see each field's documentation.\n\nPass `true` or an object to enable with defaults, or omit/set `false` to disable.\n\n- Default: Disabled" }, "tabWidth": { - "description": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size`", + "description": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`)", "type": "integer", "format": "uint8", "minimum": 0.0, - "markdownDescription": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size`" + "markdownDescription": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`)" }, "trailingComma": { "description": "Print trailing commas wherever possible in multi-line comma-separated syntactic structures.\n\nA single-line array, for example, never gets trailing commas.\n\n- Default: `\"all\"`", @@ -395,11 +395,11 @@ expression: json "markdownDescription": "Sort Tailwind CSS classes.\n\nUsing the same algorithm as [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss).\nOption names omit the `tailwind` prefix used in the original plugin (e.g., `config` instead of `tailwindConfig`).\nFor details, see each field's documentation.\n\nPass `true` or an object to enable with defaults, or omit/set `false` to disable.\n\n- Default: Disabled" }, "tabWidth": { - "description": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size`", + "description": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`)", "type": "integer", "format": "uint8", "minimum": 0.0, - "markdownDescription": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size`" + "markdownDescription": "Specify the number of spaces per indentation-level.\n\n- Default: `2`\n- Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`)" }, "trailingComma": { "description": "Print trailing commas wherever possible in multi-line comma-separated syntactic structures.\n\nA single-line array, for example, never gets trailing commas.\n\n- Default: `\"all\"`", diff --git a/tasks/website_formatter/src/snapshots/schema_markdown.snap b/tasks/website_formatter/src/snapshots/schema_markdown.snap index 7d8f49b210089..72d72d61fe425 100644 --- a/tasks/website_formatter/src/snapshots/schema_markdown.snap +++ b/tasks/website_formatter/src/snapshots/schema_markdown.snap @@ -970,7 +970,7 @@ type: `integer` Specify the number of spaces per indentation-level. - Default: `2` -- Overrides `.editorconfig.indent_size` +- Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`) ##### overrides[n].options.trailingComma @@ -1443,7 +1443,7 @@ type: `integer` Specify the number of spaces per indentation-level. - Default: `2` -- Overrides `.editorconfig.indent_size` +- Overrides `.editorconfig.indent_size` (falls back to `.editorconfig.tab_width`) ## trailingComma