diff --git a/crates/markdown/src/markdown.rs b/crates/markdown/src/markdown.rs index 2d2f3cebe0..c012f1e33d 100644 --- a/crates/markdown/src/markdown.rs +++ b/crates/markdown/src/markdown.rs @@ -1213,7 +1213,10 @@ impl MarkdownElement { range: Range, cx: &App, ) { - let link_url = if builder.code_block_stack.is_empty() && builder.link_depth == 0 { + let link_url = if builder.code_block_stack.is_empty() + && builder.link_depth == 0 + && !self.style.prevent_mouse_interaction + { self.code_span_link .as_ref() .and_then(|callback| callback(text, cx)) @@ -3490,7 +3493,10 @@ mod tests { use super::*; use gpui::{TestAppContext, size}; use language::{Language, LanguageConfig, LanguageMatcher}; - use std::sync::Arc; + use std::sync::{ + Arc, + atomic::{AtomicUsize, Ordering}, + }; fn ensure_theme_initialized(cx: &mut TestAppContext) { cx.update(|cx| { @@ -3562,6 +3568,15 @@ mod tests { markdown: &str, callback: impl Fn(&str, &App) -> Option + 'static, cx: &mut TestAppContext, + ) -> RenderedText { + render_markdown_with_code_span_link_style(markdown, MarkdownStyle::default(), callback, cx) + } + + fn render_markdown_with_code_span_link_style( + markdown: &str, + style: MarkdownStyle, + callback: impl Fn(&str, &App) -> Option + 'static, + cx: &mut TestAppContext, ) -> RenderedText { struct TestWindow; @@ -3580,7 +3595,7 @@ mod tests { Default::default(), size(px(600.0), px(600.0)), |_window, _cx| { - MarkdownElement::new(markdown, MarkdownStyle::default()) + MarkdownElement::new(markdown, style) .on_code_span_link(callback) .code_block_renderer(CodeBlockRenderer::Default { copy_button_visibility: CopyButtonVisibility::Hidden, @@ -4251,6 +4266,31 @@ mod tests { ); } + #[gpui::test] + fn test_code_span_link_ignores_code_when_mouse_interaction_is_prevented( + cx: &mut TestAppContext, + ) { + let callback_count = Arc::new(AtomicUsize::new(0)); + let rendered = render_markdown_with_code_span_link_style( + "see `foo.rs` for details", + MarkdownStyle { + prevent_mouse_interaction: true, + ..MarkdownStyle::default() + }, + { + let callback_count = callback_count.clone(); + move |text, _cx| { + callback_count.fetch_add(1, Ordering::Relaxed); + (text == "foo.rs").then(|| "file:///tmp/foo.rs".into()) + } + }, + cx, + ); + + assert!(rendered.links.is_empty()); + assert_eq!(callback_count.load(Ordering::Relaxed), 0); + } + #[gpui::test] fn test_code_span_link_ignores_code_without_callback(cx: &mut TestAppContext) { let rendered = render_markdown("see `foo.rs` for details", cx);