From 5d88d9c0d776055041b4ecc9c1b9a302dd1eb083 Mon Sep 17 00:00:00 2001 From: Bennet Bo Fenner <53836821+bennetbo@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:06:30 +0200 Subject: [PATCH] markdown preview: Add link tooltips (#10161) Adds tooltips to the markdown preview, similar to how its done for `RichText` https://github.com/zed-industries/zed/assets/53836821/523519d4-e392-46ef-9fe0-6692871b317d Release Notes: - Added tooltips when hovering over links inside the markdown preview --- .../markdown_preview/src/markdown_elements.rs | 26 ++++++++++++++++--- .../markdown_preview/src/markdown_renderer.rs | 19 ++++++++++++-- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/crates/markdown_preview/src/markdown_elements.rs b/crates/markdown_preview/src/markdown_elements.rs index adb56f38042cac80e19a994ee271d955fb83ab48..77ec160926d47a6f61ba312cef90a45d1516c661 100644 --- a/crates/markdown_preview/src/markdown_elements.rs +++ b/crates/markdown_preview/src/markdown_elements.rs @@ -2,7 +2,7 @@ use gpui::{ px, FontStyle, FontWeight, HighlightStyle, SharedString, StrikethroughStyle, UnderlineStyle, }; use language::HighlightId; -use std::{ops::Range, path::PathBuf}; +use std::{fmt::Display, ops::Range, path::PathBuf}; #[derive(Debug)] #[cfg_attr(test, derive(PartialEq))] @@ -226,7 +226,9 @@ pub enum Link { }, /// A link to a path on the filesystem. Path { - /// The path to the item. + /// The path as provided in the Markdown document. + display_path: PathBuf, + /// The absolute path to the item. path: PathBuf, }, } @@ -239,16 +241,32 @@ impl Link { let path = PathBuf::from(&text); if path.is_absolute() && path.exists() { - return Some(Link::Path { path }); + return Some(Link::Path { + display_path: path.clone(), + path, + }); } if let Some(file_location_directory) = file_location_directory { + let display_path = path; let path = file_location_directory.join(text); if path.exists() { - return Some(Link::Path { path }); + return Some(Link::Path { display_path, path }); } } None } } + +impl Display for Link { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Link::Web { url } => write!(f, "{}", url), + Link::Path { + display_path, + path: _, + } => write!(f, "{}", display_path.display()), + } + } +} diff --git a/crates/markdown_preview/src/markdown_renderer.rs b/crates/markdown_preview/src/markdown_renderer.rs index 597b2bd39d56aa78f663d2bceeb0187751b6ca7f..69034811528c4471e965632cb31354ca1cbaa5b7 100644 --- a/crates/markdown_preview/src/markdown_renderer.rs +++ b/crates/markdown_preview/src/markdown_renderer.rs @@ -13,7 +13,7 @@ use std::{ sync::Arc, }; use theme::{ActiveTheme, SyntaxTheme}; -use ui::{h_flex, v_flex, Checkbox, Selection}; +use ui::{h_flex, v_flex, Checkbox, LinkPreview, Selection}; use workspace::Workspace; pub struct RenderContext { @@ -328,11 +328,26 @@ fn render_markdown_text(parsed: &ParsedMarkdownText, cx: &mut RenderContext) -> element_id, StyledText::new(parsed.contents.clone()).with_highlights(&cx.text_style, highlights), ) + .tooltip({ + let links = links.clone(); + let link_ranges = link_ranges.clone(); + move |idx, cx| { + for (ix, range) in link_ranges.iter().enumerate() { + if range.contains(&idx) { + return Some(LinkPreview::new(&links[ix].to_string(), cx)); + } + } + None + } + }) .on_click( link_ranges, move |clicked_range_ix, window_cx| match &links[clicked_range_ix] { Link::Web { url } => window_cx.open_url(url), - Link::Path { path } => { + Link::Path { + path, + display_path: _, + } => { if let Some(workspace) = &workspace { _ = workspace.update(window_cx, |workspace, cx| { workspace.open_abs_path(path.clone(), false, cx).detach();