GPUI Box GitHub

Components / content

Markdown builder

A rendered Markdown document.

A builder is RenderOnce. Construct and mount it in one expression.

use gpui_kit::content::Markdown;

Reviewed in markdown.

Construct
new(ident: impl Into<Ident>, source: impl Into<SharedString>) -> Self
Options

Chain onto the value.

block_renderer(renderer: impl Fn(&Ident, &Block, u64, &mut Window, &mut App) -> Option<AnyElement> + 'static) -> Self
max_lines(lines: usize) -> Self
selection_order_start(order: u64) -> Self
on_event(handler: impl Fn(&MarkdownEvent, &mut Window, &mut App) + 'static) -> Self
image(source: impl Fn(&ImageRequest, &mut Window, &mut App) -> Option<AnyElement> + 'static) -> Self
streaming(streaming: bool) -> Self
code_presentation(presentation: MarkdownCodePresentation) -> Self
highlight(highlighter: impl Fn(&CodeBlock) -> Vec<CodeSpan> + 'static) -> Self
Reports

The variants of the event it emits. It never applies the change itself.

  • LinkClicked
  • ImageRequested
  • CodeCopied
  • CodeCopyRefused
  • MoreRequested
Example · markdown
fn markdown(_window: &mut Window, cx: &mut App) -> AnyElement {
    let theme = cx.theme().clone();
    let document = stack(&theme)
        .w(px(640.0))
        .child(Markdown::new("scene.markdown.document", SCENE_DOCUMENT).on_event(|_, _, _| {}))
        .child(
            Divider::new()
                .id("scene.markdown.flat-rule")
                .label("The same fence in flat presentation"),
        )
        .child(
            Markdown::new(
                "scene.markdown.flat",
                "```rust\nfn main() { println!(\"a long line keeps its horizontal code overflow\"); }\n```",
            )
            .code_presentation(MarkdownCodePresentation::Flat)
            .on_event(|_, _, _| {}),
        )
        .child(Divider::new().id("scene.markdown.rule").label("Truncated"))
        .child(
            Markdown::new("scene.markdown.short", SCENE_DOCUMENT)
                .max_lines(4)
                .on_event(|_, _, _| {}),
        );
    div().row().child(document).child(
        stack(&theme).w(px(272.0))
            .child(caption(&theme, "Unicode line breaks · CJK and Latin"))
            .child(Markdown::new(
                "scene.markdown.unicode-wrap",
                "设计图通过后仍需运行、测量和批注;截图不能证明可玩。请检查「运行结果」(第12轮),然后比较 Hello world你好世界与 internationalization 2026-09。",
            ))
            .child(caption(&theme, "Frontmatter stays data"))
            .child(Markdown::new("scene.markdown.metadata", "---\ntitle: Review fixture\ntrusted: false\n---\n\nMetadata is visible, never applied."))
            .child(caption(&theme, "Host block plugin · native rendering"))
            .child(Markdown::new("scene.markdown.plugin", "```notice\nThis fixture uses a trusted native block renderer.\n```\n\n```unknown\nUnknown fences remain code.\n```")
                .block_renderer(|ident, block, _, _, _| {
                    if let crate::content::markdown::Block::Code { language, text } = block
                        && language.as_deref() == Some("notice") {
                        Some(Callout::new(text.clone(), Tone::Info).id(ident.clone()).into_any_element())
                    } else { None }
                }))
            // Hold worker states deterministically; the executor/coalescing
            // tests exercise the actual transition into and out of them.
            .child(caption(&theme, "Background parsing · state fixtures"))
            .child(Markdown::new("scene.markdown.loading", "").parsing(true))
            .child(Markdown::new("scene.markdown.refreshing", "The **last verified text** stays visible while its replacement is parsed.").parsing(true)),
    )
        .into_any_element()
}

Source: crates/gpui-kit/src/content/markdown.rs