Skip to content

Commit 9a96b6f

Browse files
authored
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" />
1 parent cbbf302 commit 9a96b6f

File tree

3 files changed

+82
-6
lines changed

3 files changed

+82
-6
lines changed

codex-rs/tui/src/markdown_render.rs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,30 @@ pub(crate) fn render_markdown_text_with_width(input: &str, width: Option<usize>)
8585
w.text
8686
}
8787

88+
#[derive(Clone, Debug)]
89+
struct LinkState {
90+
destination: String,
91+
show_destination: bool,
92+
}
93+
94+
fn should_render_link_destination(dest_url: &str) -> bool {
95+
!is_local_path_like_link(dest_url)
96+
}
97+
98+
fn is_local_path_like_link(dest_url: &str) -> bool {
99+
dest_url.starts_with("file://")
100+
|| dest_url.starts_with('/')
101+
|| dest_url.starts_with("~/")
102+
|| dest_url.starts_with("./")
103+
|| dest_url.starts_with("../")
104+
|| dest_url.starts_with("\\\\")
105+
|| matches!(
106+
dest_url.as_bytes(),
107+
[drive, b':', separator, ..]
108+
if drive.is_ascii_alphabetic() && matches!(separator, b'/' | b'\\')
109+
)
110+
}
111+
88112
struct Writer<'a, I>
89113
where
90114
I: Iterator<Item = Event<'a>>,
@@ -95,7 +119,7 @@ where
95119
inline_styles: Vec<Style>,
96120
indent_stack: Vec<IndentContext>,
97121
list_indices: Vec<Option<u64>>,
98-
link: Option<String>,
122+
link: Option<LinkState>,
99123
needs_newline: bool,
100124
pending_marker_line: bool,
101125
in_paragraph: bool,
@@ -467,14 +491,21 @@ where
467491
}
468492

469493
fn push_link(&mut self, dest_url: String) {
470-
self.link = Some(dest_url);
494+
self.push_inline_style(self.styles.link);
495+
self.link = Some(LinkState {
496+
show_destination: should_render_link_destination(&dest_url),
497+
destination: dest_url,
498+
});
471499
}
472500

473501
fn pop_link(&mut self) {
474502
if let Some(link) = self.link.take() {
475-
self.push_span(" (".into());
476-
self.push_span(Span::styled(link, self.styles.link));
477-
self.push_span(")".into());
503+
self.pop_inline_style();
504+
if link.show_destination {
505+
self.push_span(" (".into());
506+
self.push_span(Span::styled(link.destination, self.styles.link));
507+
self.push_span(")".into());
508+
}
478509
}
479510
}
480511

codex-rs/tui/src/markdown_render_tests.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,14 +643,54 @@ fn strong_emphasis() {
643643
fn link() {
644644
let text = render_markdown_text("[Link](https://example.com)");
645645
let expected = Text::from(Line::from_iter([
646-
"Link".into(),
646+
"Link".cyan().underlined(),
647647
" (".into(),
648648
"https://example.com".cyan().underlined(),
649649
")".into(),
650650
]));
651651
assert_eq!(text, expected);
652652
}
653653

654+
#[test]
655+
fn file_link_hides_destination() {
656+
let text =
657+
render_markdown_text("[markdown_render.rs:74](/Users/example/code/codex/codex-rs/tui/src/markdown_render.rs:74)");
658+
let expected = Text::from(Line::from("markdown_render.rs:74".cyan().underlined()));
659+
assert_eq!(text, expected);
660+
}
661+
662+
#[test]
663+
fn url_link_shows_destination() {
664+
let text = render_markdown_text("[docs](https://example.com/docs)");
665+
let expected = Text::from(Line::from_iter([
666+
"docs".cyan().underlined(),
667+
" (".into(),
668+
"https://example.com/docs".cyan().underlined(),
669+
")".into(),
670+
]));
671+
assert_eq!(text, expected);
672+
}
673+
674+
#[test]
675+
fn markdown_render_file_link_snapshot() {
676+
let text = render_markdown_text(
677+
"See [markdown_render.rs:74](/Users/example/code/codex/codex-rs/tui/src/markdown_render.rs:74).",
678+
);
679+
let rendered = text
680+
.lines
681+
.iter()
682+
.map(|l| {
683+
l.spans
684+
.iter()
685+
.map(|s| s.content.clone())
686+
.collect::<String>()
687+
})
688+
.collect::<Vec<_>>()
689+
.join("\n");
690+
691+
assert_snapshot!(rendered);
692+
}
693+
654694
#[test]
655695
fn code_block_known_lang_has_syntax_colors() {
656696
let text = render_markdown_text("```rust\nfn main() {}\n```\n");
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
source: tui/src/markdown_render_tests.rs
3+
expression: rendered
4+
---
5+
See markdown_render.rs:74.

0 commit comments

Comments
 (0)