diff --git a/codex-rs/tui/src/markdown_render.rs b/codex-rs/tui/src/markdown_render.rs index a008958b2e..d55504be3b 100644 --- a/codex-rs/tui/src/markdown_render.rs +++ b/codex-rs/tui/src/markdown_render.rs @@ -434,10 +434,8 @@ where // If we buffered code for a known language, syntax-highlight it now. if let Some(lang) = self.code_block_lang.take() { let code = std::mem::take(&mut self.code_block_buffer); - // Trim trailing newline to avoid a spurious empty line. - let code = code.trim_end_matches('\n'); if !code.is_empty() { - let highlighted = highlight_code_to_lines(code, &lang); + let highlighted = highlight_code_to_lines(&code, &lang); for hl_line in highlighted { self.push_line(Line::default()); for span in hl_line.spans { diff --git a/codex-rs/tui/src/markdown_render_tests.rs b/codex-rs/tui/src/markdown_render_tests.rs index c20930b7f1..fb1f8bab84 100644 --- a/codex-rs/tui/src/markdown_render_tests.rs +++ b/codex-rs/tui/src/markdown_render_tests.rs @@ -1063,3 +1063,36 @@ fn nested_item_continuation_paragraph_is_indented() { ]); assert_eq!(text, expected); } + +#[test] +fn code_block_preserves_trailing_blank_lines() { + // A fenced code block with an intentional trailing blank line must keep it. + let md = "```rust\nfn main() {}\n\n```\n"; + let text = render_markdown_text(md); + let content: Vec = text + .lines + .iter() + .map(|l| { + l.spans + .iter() + .map(|s| s.content.clone()) + .collect::() + }) + .collect(); + // Should have: "fn main() {}" then "" (the blank line). + // Filter only to content lines (skip leading/trailing empty from rendering). + assert!( + content.iter().any(|c| c == "fn main() {}"), + "expected code line, got {content:?}" + ); + // The trailing blank line inside the fence should be preserved. + let code_start = content.iter().position(|c| c == "fn main() {}").unwrap(); + assert!( + content.len() > code_start + 1, + "expected a line after 'fn main() {{}}' but content ends: {content:?}" + ); + assert_eq!( + content[code_start + 1], "", + "trailing blank line inside code fence was lost: {content:?}" + ); +}