Hide local file link destinations in TUI markdown (#12705)

## Summary
- hide appended destinations for local path-style markdown links in the
TUI renderer
- keep web links rendering with their visible destination and style link
labels consistently
- add markdown renderer tests and a snapshot for the new file-link
output

## Testing
- just fmt
- cargo test -p codex-tui
<img width="1120" height="968" alt="image"
src="https://github.com/user-attachments/assets/490e8eda-ae47-4231-89fa-b254a1f83eed"
/>
This commit is contained in:
pash-openai
2026-02-25 21:28:37 -08:00
committed by GitHub
Unverified
parent cbbf302f5f
commit 9a96b6f509
3 changed files with 82 additions and 6 deletions
+36 -5
View File
@@ -85,6 +85,30 @@ pub(crate) fn render_markdown_text_with_width(input: &str, width: Option<usize>)
w.text
}
#[derive(Clone, Debug)]
struct LinkState {
destination: String,
show_destination: bool,
}
fn should_render_link_destination(dest_url: &str) -> bool {
!is_local_path_like_link(dest_url)
}
fn is_local_path_like_link(dest_url: &str) -> bool {
dest_url.starts_with("file://")
|| dest_url.starts_with('/')
|| dest_url.starts_with("~/")
|| dest_url.starts_with("./")
|| dest_url.starts_with("../")
|| dest_url.starts_with("\\\\")
|| matches!(
dest_url.as_bytes(),
[drive, b':', separator, ..]
if drive.is_ascii_alphabetic() && matches!(separator, b'/' | b'\\')
)
}
struct Writer<'a, I>
where
I: Iterator<Item = Event<'a>>,
@@ -95,7 +119,7 @@ where
inline_styles: Vec<Style>,
indent_stack: Vec<IndentContext>,
list_indices: Vec<Option<u64>>,
link: Option<String>,
link: Option<LinkState>,
needs_newline: bool,
pending_marker_line: bool,
in_paragraph: bool,
@@ -467,14 +491,21 @@ where
}
fn push_link(&mut self, dest_url: String) {
self.link = Some(dest_url);
self.push_inline_style(self.styles.link);
self.link = Some(LinkState {
show_destination: should_render_link_destination(&dest_url),
destination: dest_url,
});
}
fn pop_link(&mut self) {
if let Some(link) = self.link.take() {
self.push_span(" (".into());
self.push_span(Span::styled(link, self.styles.link));
self.push_span(")".into());
self.pop_inline_style();
if link.show_destination {
self.push_span(" (".into());
self.push_span(Span::styled(link.destination, self.styles.link));
self.push_span(")".into());
}
}
}
+41 -1
View File
@@ -643,7 +643,7 @@ fn strong_emphasis() {
fn link() {
let text = render_markdown_text("[Link](https://example.com)");
let expected = Text::from(Line::from_iter([
"Link".into(),
"Link".cyan().underlined(),
" (".into(),
"https://example.com".cyan().underlined(),
")".into(),
@@ -651,6 +651,46 @@ fn link() {
assert_eq!(text, expected);
}
#[test]
fn file_link_hides_destination() {
let text =
render_markdown_text("[markdown_render.rs:74](/Users/example/code/codex/codex-rs/tui/src/markdown_render.rs:74)");
let expected = Text::from(Line::from("markdown_render.rs:74".cyan().underlined()));
assert_eq!(text, expected);
}
#[test]
fn url_link_shows_destination() {
let text = render_markdown_text("[docs](https://example.com/docs)");
let expected = Text::from(Line::from_iter([
"docs".cyan().underlined(),
" (".into(),
"https://example.com/docs".cyan().underlined(),
")".into(),
]));
assert_eq!(text, expected);
}
#[test]
fn markdown_render_file_link_snapshot() {
let text = render_markdown_text(
"See [markdown_render.rs:74](/Users/example/code/codex/codex-rs/tui/src/markdown_render.rs:74).",
);
let rendered = text
.lines
.iter()
.map(|l| {
l.spans
.iter()
.map(|s| s.content.clone())
.collect::<String>()
})
.collect::<Vec<_>>()
.join("\n");
assert_snapshot!(rendered);
}
#[test]
fn code_block_known_lang_has_syntax_colors() {
let text = render_markdown_text("```rust\nfn main() {}\n```\n");
@@ -0,0 +1,5 @@
---
source: tui/src/markdown_render_tests.rs
expression: rendered
---
See markdown_render.rs:74.