markdown: Don't retain MarkdownStyle in favor of using MarkdownElement directly (#28255)

This PR removes the retained `MarkdownStyle` on the `Markdown` entity in
favor of using the `MarkdownElement` directly and passing the
`MarkdownStyle` to it.

This makes it so switching themes will be reflected live in the code
block styles.

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Agus Zubiaga <hi@aguz.me>
This commit is contained in:
Marshall Bowers 2025-04-07 15:03:24 -04:00 committed by GitHub
parent aa026156f2
commit b6ee367ee0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 370 additions and 374 deletions

View file

@ -7,7 +7,7 @@ use gpui::{
};
use language::Buffer;
use language::CodeLabel;
use markdown::Markdown;
use markdown::{Markdown, MarkdownElement};
use multi_buffer::{Anchor, ExcerptId};
use ordered_float::OrderedFloat;
use project::CompletionSource;
@ -622,21 +622,18 @@ impl CompletionsMenu {
let language = editor
.language_at(self.initial_position, cx)
.map(|l| l.name().to_proto());
Markdown::new(
SharedString::default(),
hover_markdown_style(window, cx),
languages,
language,
cx,
)
.copy_code_block_buttons(false)
.open_url(open_markdown_url)
Markdown::new(SharedString::default(), languages, language, cx)
.copy_code_block_buttons(false)
.open_url(open_markdown_url)
})
});
markdown.update(cx, |markdown, cx| {
markdown.reset(parsed.clone(), cx);
});
div().child(markdown.clone())
div().child(MarkdownElement::new(
markdown.clone(),
hover_markdown_style(window, cx),
))
}
CompletionDocumentation::MultiLineMarkdown(_) => return None,
CompletionDocumentation::SingleLine(_) => return None,

View file

@ -3912,9 +3912,13 @@ impl EditorElement {
);
let hover_popovers = self.editor.update(cx, |editor, cx| {
editor
.hover_state
.render(snapshot, visible_display_row_range.clone(), max_size, cx)
editor.hover_state.render(
snapshot,
visible_display_row_range.clone(),
max_size,
window,
cx,
)
});
let Some((position, hover_popovers)) = hover_popovers else {
return;

View file

@ -14,7 +14,7 @@ use gpui::{
use itertools::Itertools;
use language::{DiagnosticEntry, Language, LanguageRegistry};
use lsp::DiagnosticSeverity;
use markdown::{Markdown, MarkdownStyle};
use markdown::{Markdown, MarkdownElement, MarkdownStyle};
use multi_buffer::{MultiOrSingleBufferOffsetRange, ToOffset};
use project::{HoverBlock, HoverBlockKind, InlayHintLabelPart};
use settings::Settings;
@ -310,7 +310,7 @@ fn show_hover(
let mut background_color: Option<Hsla> = None;
let parsed_content = cx
.new_window_entity(|window, cx| {
.new_window_entity(|_window, cx| {
let status_colors = cx.theme().status();
match local_diagnostic.diagnostic.severity {
@ -335,32 +335,8 @@ fn show_hover(
border_color = Some(status_colors.ignored_border);
}
};
let settings = ThemeSettings::get_global(cx);
let mut base_text_style = window.text_style();
base_text_style.refine(&TextStyleRefinement {
font_family: Some(settings.ui_font.family.clone()),
font_fallbacks: settings.ui_font.fallbacks.clone(),
font_size: Some(settings.ui_font_size(cx).into()),
color: Some(cx.theme().colors().editor_foreground),
background_color: Some(gpui::transparent_black()),
..Default::default()
});
let markdown_style = MarkdownStyle {
base_text_style,
selection_background_color: { cx.theme().players().local().selection },
link: TextStyleRefinement {
underline: Some(gpui::UnderlineStyle {
thickness: px(1.),
color: Some(cx.theme().colors().editor_foreground),
wavy: false,
}),
..Default::default()
},
..Default::default()
};
Markdown::new_text(SharedString::new(text), markdown_style.clone(), cx)
.open_url(open_markdown_url)
Markdown::new_text(SharedString::new(text), cx).open_url(open_markdown_url)
})
.ok();
@ -563,10 +539,9 @@ async fn parse_blocks(
.join("\n\n");
let rendered_block = cx
.new_window_entity(|window, cx| {
.new_window_entity(|_window, cx| {
Markdown::new(
combined_text.into(),
hover_markdown_style(window, cx),
Some(language_registry.clone()),
fallback_language_name,
cx,
@ -704,6 +679,7 @@ impl HoverState {
snapshot: &EditorSnapshot,
visible_rows: Range<DisplayRow>,
max_size: Size<Pixels>,
window: &mut Window,
cx: &mut Context<Editor>,
) -> Option<(DisplayPoint, Vec<AnyElement>)> {
// If there is a diagnostic, position the popovers based on that.
@ -738,10 +714,10 @@ impl HoverState {
let mut elements = Vec::new();
if let Some(diagnostic_popover) = self.diagnostic_popover.as_ref() {
elements.push(diagnostic_popover.render(max_size, cx));
elements.push(diagnostic_popover.render(max_size, window, cx));
}
for info_popover in &mut self.info_popovers {
elements.push(info_popover.render(max_size, cx));
elements.push(info_popover.render(max_size, window, cx));
}
Some((point, elements))
@ -781,6 +757,7 @@ impl InfoPopover {
pub(crate) fn render(
&mut self,
max_size: Size<Pixels>,
window: &mut Window,
cx: &mut Context<Editor>,
) -> AnyElement {
let keyboard_grace = Rc::clone(&self.keyboard_grace);
@ -806,7 +783,10 @@ impl InfoPopover {
.max_h(max_size.height)
.p_2()
.track_scroll(&self.scroll_handle)
.child(markdown.clone()),
.child(MarkdownElement::new(
markdown.clone(),
hover_markdown_style(window, cx),
)),
)
.child(self.render_vertical_scrollbar(cx));
}
@ -868,11 +848,41 @@ pub struct DiagnosticPopover {
}
impl DiagnosticPopover {
pub fn render(&self, max_size: Size<Pixels>, cx: &mut Context<Editor>) -> AnyElement {
pub fn render(
&self,
max_size: Size<Pixels>,
window: &mut Window,
cx: &mut Context<Editor>,
) -> AnyElement {
let keyboard_grace = Rc::clone(&self.keyboard_grace);
let mut markdown_div = div().py_1().px_2();
if let Some(markdown) = &self.parsed_content {
markdown_div = markdown_div.child(markdown.clone());
let settings = ThemeSettings::get_global(cx);
let mut base_text_style = window.text_style();
base_text_style.refine(&TextStyleRefinement {
font_family: Some(settings.ui_font.family.clone()),
font_fallbacks: settings.ui_font.fallbacks.clone(),
font_size: Some(settings.ui_font_size(cx).into()),
color: Some(cx.theme().colors().editor_foreground),
background_color: Some(gpui::transparent_black()),
..Default::default()
});
let markdown_style = MarkdownStyle {
base_text_style,
selection_background_color: { cx.theme().players().local().selection },
link: TextStyleRefinement {
underline: Some(gpui::UnderlineStyle {
thickness: px(1.),
color: Some(cx.theme().colors().editor_foreground),
wavy: false,
}),
..Default::default()
},
..Default::default()
};
markdown_div =
markdown_div.child(MarkdownElement::new(markdown.clone(), markdown_style));
}
if let Some(background_color) = &self.background_color {