Markdown: display math through RaTeX, Mermaid through mermaid-rs-renderer, pictures from the owner's folder
CI / site (push) Successful in 32s
CI / platforms (windows-latest) (push) Successful in 4m47s
CI / crate (push) Failing after 25m44s
CI / platforms (ubuntu-24.04) (push) Canceled after 0s

Latex typesets with RaTeX to outlined SVG drawn by gpui's SvgRenderer at the
window's scale, loaded as an asset off the main thread. Diagram draws a
mermaid block in Mermaid's theme for the mode. MarkdownRenderer::base names
the folder pictures load from; data addresses decode, web ones stay unloaded.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-11 23:38:22 -04:00
1 parent 508cc55af6
commit d5ecc5a69e
11 files changed
+927 -328

No files matched your search

+25 -20
View File
@@ -1,4 +1,4 @@
use std::rc::Rc;
use std::{path::Path, rc::Rc, sync::Arc};
use gpui::{
AnyElement, App, ElementId, Entity, FontStyle, FontWeight, HighlightStyle, InteractiveText,
@@ -7,7 +7,11 @@ use gpui::{
};
use markdown::mdast::AlignKind;
use super::tree::{Inline, Node, Style, parse};
use super::{
diagram::Diagram,
picture::Picture,
tree::{Inline, Node, Style, parse},
};
use crate::{
editor::code_colors,
navigation::{Anchor, Sections},
@@ -28,6 +32,7 @@ pub struct MarkdownRenderer {
size: TextSize,
sections: Option<Entity<Sections>>,
code: Option<DrawCode>,
base: Option<Arc<Path>>,
}
impl MarkdownRenderer {
@@ -39,9 +44,16 @@ impl MarkdownRenderer {
size: TextSize::Base,
sections: None,
code: None,
base: None,
}
}
/// The folder relative picture addresses start from.
pub fn base(mut self, folder: impl Into<Arc<Path>>) -> Self {
self.base = Some(folder.into());
self
}
/// The body's size; headings keep theirs.
pub fn text_size(mut self, size: TextSize) -> Self {
self.size = size;
@@ -78,6 +90,7 @@ struct Draw<'a> {
sections: &'a Option<Entity<Sections>>,
headings: std::cell::Cell<usize>,
code: &'a Option<DrawCode>,
base: &'a Option<Arc<Path>>,
}
impl Draw<'_> {
@@ -200,6 +213,9 @@ impl Draw<'_> {
.children(self.nodes(inner, cx))
.into_any_element(),
Node::Code { language, text } => {
if language.as_deref() == Some("mermaid") {
return Diagram::new(text.clone()).into_any_element();
}
if let Some(draw) = self.code {
return draw(
self.key("code"),
@@ -336,7 +352,7 @@ impl Draw<'_> {
.justify_center()
.py_2()
.child(match Latex::parse(tex) {
Ok(math) => math.into_any_element(),
Ok(math) => math.display().into_any_element(),
Err(error) => div()
.text_color(colors.danger)
.child(error.to_string())
@@ -344,23 +360,11 @@ impl Draw<'_> {
})
.into_any_element(),
Node::Image { alt, url, link } => {
let picture = div()
.id(self.key("image"))
.flex()
.items_center()
.gap_2()
.p_3()
.rounded(theme.radius(Radius::Md))
.border_1()
.border_color(colors.border)
.text_color(colors.fg_muted)
.child(
Icon::new(IconName::Image)
.size(IconSize::Sm)
.color(colors.fg_subtle),
)
.child(div().flex_1().child(alt.clone()))
.child(div().text_color(colors.fg_subtle).child(url.clone()));
let picture = div().id(self.key("image")).child(Picture {
alt: alt.clone(),
url: url.clone(),
base: self.base.clone(),
});
let Some(link) = link.clone() else {
return picture.into_any_element();
};
@@ -443,6 +447,7 @@ impl RenderOnce for MarkdownRenderer {
sections: &self.sections,
headings: std::cell::Cell::new(0),
code: &self.code,
base: &self.base,
};
div()
.flex()