From d2ddb4b2d9a005b450ea287a20b1c60fe201144a Mon Sep 17 00:00:00 2001 From: saberoueslati Date: Wed, 22 Apr 2026 03:03:40 +0100 Subject: [PATCH] markdown: Fix heading sizes and spacing in preview (#54374) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Context Heading sizes in the markdown preview were nearly identical to body text, making `# H1`, `## H2`, and `### H3` visually indistinguishable. The root cause was in `MarkdownStyle::themed()`: it set a `heading_level_styles` override with font sizes of `rems(1.05–1.15)`, which silently replaced the correct sizes applied by `apply_heading_style` (via GPUI's `text_3xl`/`text_2xl`/`text_xl` utilities `rems(1.875/1.5/1.25)`). Removing that override restores the intended hierarchy. A `mt_4()` top margin was also added so consecutive headings have visual breathing room. Closes #54358 Video of manual test below : [Screencast from 2026-04-21 02-22-12.webm](https://github.com/user-attachments/assets/8dd815f9-6f9b-4e88-bebb-28c79f019427) ## How to Review `crates/markdown/src/markdown.rs` Three changes: - (1) removed the `heading_level_styles` block from `MarkdownStyle::themed()` that was overriding heading font sizes with nearly-body-text values; - (2) added `mt_4()` to the heading div in `push_markdown_heading` for better vertical spacing; - (3) added `test_heading_font_sizes_are_distinct` which renders H1–H3 and a paragraph then asserts that line heights strictly decrease from H1 down to body text. ## Self-Review Checklist - [x] I've reviewed my own diff for quality, security, and reliability - [ ] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed heading sizes in the markdown preview to correctly reflect the H1–H6 size hierarchy, matching standard markdown renderers --- crates/markdown/src/markdown.rs | 57 +++++++++++++++++---------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/crates/markdown/src/markdown.rs b/crates/markdown/src/markdown.rs index 560ee02b8cf7b4210c3bf4013f58fff670144700..c2d8e45f16ea6f8dbe788cffae00a0bf7fc2b640 100644 --- a/crates/markdown/src/markdown.rs +++ b/crates/markdown/src/markdown.rs @@ -157,32 +157,6 @@ impl MarkdownStyle { rule_color: colors.border, block_quote_border_color: colors.border, code_block_overflow_x_scroll: true, - heading_level_styles: Some(HeadingLevelStyles { - h1: Some(TextStyleRefinement { - font_size: Some(rems(1.15).into()), - ..Default::default() - }), - h2: Some(TextStyleRefinement { - font_size: Some(rems(1.1).into()), - ..Default::default() - }), - h3: Some(TextStyleRefinement { - font_size: Some(rems(1.05).into()), - ..Default::default() - }), - h4: Some(TextStyleRefinement { - font_size: Some(rems(1.).into()), - ..Default::default() - }), - h5: Some(TextStyleRefinement { - font_size: Some(rems(0.95).into()), - ..Default::default() - }), - h6: Some(TextStyleRefinement { - font_size: Some(rems(0.875).into()), - ..Default::default() - }), - }), code_block: StyleRefinement { padding: EdgesRefinement { top: Some(DefiniteLength::Absolute(AbsoluteLength::Pixels(px(8.)))), @@ -1124,7 +1098,7 @@ impl MarkdownElement { text_align_override: Option, ) { let align = text_align_override.unwrap_or(self.style.base_text_style.text_align); - let mut heading = div().mb_2(); + let mut heading = div().mt_4().mb_2(); heading = apply_heading_style(heading, level, self.style.heading_level_styles.as_ref()); heading = match align { @@ -3650,4 +3624,33 @@ mod tests { } } } + + #[gpui::test] + fn test_heading_font_sizes_are_distinct(cx: &mut TestAppContext) { + let rendered = render_markdown("# H1\n\n## H2\n\n### H3\n\nBody text", cx); + + assert!( + rendered.lines.len() >= 4, + "expected at least 4 rendered lines, got {}", + rendered.lines.len() + ); + + let h1_line_height = rendered.lines[0].layout.line_height(); + let h2_line_height = rendered.lines[1].layout.line_height(); + let h3_line_height = rendered.lines[2].layout.line_height(); + let body_line_height = rendered.lines[3].layout.line_height(); + + assert!( + h1_line_height > h2_line_height, + "H1 line height ({h1_line_height:?}) should be greater than H2 ({h2_line_height:?})" + ); + assert!( + h2_line_height > h3_line_height, + "H2 line height ({h2_line_height:?}) should be greater than H3 ({h3_line_height:?})" + ); + assert!( + h3_line_height > body_line_height, + "H3 line height ({h3_line_height:?}) should be greater than body text ({body_line_height:?})" + ); + } }