Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

rich_md

Rich Markdown: markdown rendered in ImGui: text styles, headings, lists, tables, images, links, code blocks, LaTeX math and diagrams.

render(markdown_string) draws a markdown text; render_unindented() accepts an indented one; render_file() renders a file. Run the app with immapp.run(..., with_markdown=True), which loads the fonts.

Its former name, imgui_bundle.imgui_md, stays as an alias.

The module imgui_bundle.rich_md, the Python API of Rich Markdown, from bindings/imgui_bundle/rich_md.pyi: 29 functions, 8 classes, 1 enums. Each entry gives the Python signature, then the C++ one, then the doc of the C++ header. The sections are the header’s.

render_this_file

def render_this_file(target: str = '') -> None

Renders ![[this_file#target]] (see resolve_transclusions): a program can be its own narrative. target: a section (“Intro”), its code (“Escape#code”), a code region, or empty (the whole file). (Python only; C++: RICHMD_RENDER_THIS_FILE)

rich_md_host.h

MarkdownDownloadStatus (enum)

Status of a download (see HostServices::Download)

MemberValueC++
not_started0NotStartedDownload has not been initiated
downloading1DownloadingDownload is in progress (show placeholder)
ready2ReadyDownload complete, data is available
failed3FailedDownload failed, errorMessage has details

MarkdownDownloadResult (class)

Result of a download attempt

AttributeC++
status: MarkdownDownloadStatusMarkdownDownloadStatus status = MarkdownDownloadStatus::NotStarted;
error_message: strstd::string errorMessage;Only valid if status == Failed
MarkdownDownloadResult.__init__
def __init__(self) -> None

Autogenerated default constructor

MarkdownDownloadResult.fill_from_bytes
def fill_from_bytes(self, data: bytes) -> None

Fill the result data from a Python bytes object.

The services

Context (class)

A markdown context (its options, its fonts, its caches): made by create_context, destroyed by destroy_context. Opaque.

set_download_function

def set_download_function(fn: Optional[Callable[[str], MarkdownDownloadResult]]) -> None

Sets the function that downloads URL images (HostServices.Download), for every markdown context. imgui_bundle installs one at import (urllib in a thread on desktop, JS fetch in Pyodide).
Called every frame for a URL until it returns Ready or Failed; an asynchronous download returns
Downloading first and tracks its pending downloads itself. None disables URL images.

narrative_programming.h

resolve_transclusions

def resolve_transclusions(markdown: str, read_file: ReadTextFile, current_file: str = '') -> str
std::string ResolveTransclusions(const std::string& markdown, const ReadTextFile& readFile, const std::string& currentFile = "");

ResolveTransclusions replaces the embeds of a markdown text: readFile reads a file (or returns std::nullopt); currentFile is the file the text comes from, if any. Render() calls it with the host’s ReadAsset.

rich_md.h

render

def render(markdown_string: str) -> None
void Render(const std::string& markdownString);

Renders a markdown string. Its common indentation is removed first (so that a string written inside an indented function renders as expected; no-op on flush-left text), then its transclusions are resolved (see ResolveTransclusions; the files are read through the host’s ReadAsset).

render_raw

def render_raw(markdown_string: str) -> None
void RenderRaw(const std::string& markdownString);

Renders a markdown string as is (no unindent, no transclusion)

push_selectable_text

def push_selectable_text(selectable: bool) -> None
void PushSelectableText(bool selectable);

Whether the text of the renders that follow can be selected, until the matching PopSelectableText(), in the same frame. For markdown inside something that reacts to a drag itself (a node of a node editor, a custom widget).

pop_selectable_text

def pop_selectable_text() -> None
void PopSelectableText();

set_selectable_text_default

def set_selectable_text_default(selectable: bool) -> None
void SetSelectableTextDefault(bool selectable);

Whether the text can be selected, outside of a PushSelectableText(): changes the option selectableText of the current context

Options and callbacks

MarkdownFontOptions (class)

AttributeC++
font_base_path: strstd::string fontBasePath = "fonts/Roboto/Roboto";
regular_size: floatfloat regularSize = 16.f;
header_size_factors: np.ndarrayfloat headerSizeFactors[6] = { 1.42f, 1.33f, 1.24f, 1.15f, 1.10f, 1.05f };ndarray[type=float, size=6] default:float( 1.42, 1.33, 1.24, 1.15, 1.10, 1.05 )
merge_fonts: List[str]std::vector<std::string> mergeFonts;
MarkdownFontOptions.__init__
def __init__(self) -> None

Autogenerated default constructor

MarkdownImage (class)

AttributeC++
texture_id: ImTextureIDImTextureID texture_id;
size: ImVec2ImVec2 size;
uv0: ImVec2ImVec2 uv0;
uv1: ImVec2ImVec2 uv1;
col_tint: ImVec4ImVec4 col_tint;
col_border: ImVec4ImVec4 col_border;
MarkdownImage.__init__
def __init__(self) -> None

Autogenerated default constructor

on_image_default

def on_image_default(image_path: str) -> Optional[MarkdownImage]
std::optional<MarkdownImage> OnImage_Default(const std::string& image_path);
def on_open_link_default(url: str) -> None
void OnOpenLink_Default(const std::string& url);

MarkdownCallbacks (class)

AttributeC++
on_open_link: StringFunctionStringFunction OnOpenLink = OnOpenLink_Default;
on_image: MarkdownImageFunctionMarkdownImageFunction OnImage = OnImage_Default;
on_html_div: HtmlDivFunctionHtmlDivFunction OnHtmlDiv;
on_html_span: HtmlSpanFunctionHtmlSpanFunction OnHtmlSpan;
can_use_child_windows: Callable[[], bool]std::function<bool()> CanUseChildWindows;
on_wiki_link: Callable[[str], None]std::function<void(const std::string& target)> OnWikiLink;
on_heading: Callable[[int, str], None]std::function<void(int level, const std::string& text)> OnHeading;
MarkdownCallbacks.__init__
def __init__(self) -> None

Autogenerated default constructor

MarkdownCallbacks.on_download_data
@property
def on_download_data(self) -> Optional[str]

@on_download_data.setter
def on_download_data(self, fn: Optional[Callable[[str], MarkdownDownloadResult]]) -> None

Deprecated: use rich_md.set_download_function. Returns None if not set, or a status string (reading back the callable itself is not supported).

MarkdownOptions (class)

AttributeC++
font_options: MarkdownFontOptionsMarkdownFontOptions fontOptions;
callbacks: MarkdownCallbacksMarkdownCallbacks callbacks;
with_latex: boolbool withLatex = false;
autolinks: boolbool autolinks = true;
hard_soft_breaks: boolbool hardSoftBreaks = false;
selectable_text: boolbool selectableText = true;
MarkdownOptions.__init__
def __init__(self) -> None

Autogenerated default constructor

Context

create_context

def create_context(options: Optional[MarkdownOptions] = None) -> Context
Context* CreateContext(const MarkdownOptions& options = MarkdownOptions());

A context holds the options, the fonts and the caches (textures, formulas, diagrams). Most applications have one.
Contexts: CreateContext makes one, any time after ImGui::CreateContext(); it becomes the current context when there is none. The fonts load at the first Render() (Dear ImGui 1.92 loads glyphs on demand).
DestroyContext destroys one (None: the current one) and frees its textures: call it while the rendering backend is still alive. Several contexts (e.g. two font sizes, several ImGui contexts) can live together; all the other functions act on the current one. In ImGui Bundle, ImmApp makes one for you when markdown is enabled.

Python bindings defaults:
If options is None, then its default value will be: MarkdownOptions()

destroy_context

def destroy_context(context: Optional[Context] = None) -> None
void DestroyContext(Context* context = nullptr);

set_current_context

def set_current_context(context: Context) -> None
void SetCurrentContext(Context* context);

get_current_context

def get_current_context() -> Context
Context* GetCurrentContext();

set_assets_folder

def set_assets_folder(folder: str) -> None
void SetAssetsFolder(const std::string& folder);

The folder where the default host reads the assets (fonts, images) from the file system, when they are not embedded in the binary. Default: the current directory.

Rendering files

render_file

def render_file(path: str, target: str = '') -> None
void RenderFile(const std::string& path, const std::string& target = "");

Renders ![[path#target]]: target is a section (“Intro”), its code (“Escape#code”), a code region, a heading of a markdown document, or empty (the whole file). The path is looked up in the assets first, then on the file system: a source file renders its own narrative with RICHMD_RENDER_THIS_FILE(“Intro”) (C++) or rich_md.render_this_file(“Intro”) (Python).

RenderFile() renders a section, a code region or a whole file: a program renders its own narrative with RICHMD_RENDER_THIS_FILE. The syntax and the resolver: narrative_programming.h.

Extensions

register_fenced_block_renderer

def register_fenced_block_renderer(language: str, renderer: Callable[[str], None]) -> None
void RegisterFencedBlockRenderer(const std::string& language, std::function<void(const std::string& code)> renderer);

Renders the code blocks of a given language (mermaid, csv, ...) with your own function, instead of the code block renderer. Applies to the current context.

Your own renderers for fenced code blocks, Mermaid diagrams and links outside of markdown.

render_mermaid

def render_mermaid(source: str) -> None
void RenderMermaid(const std::string& source);

Renders a Mermaid diagram (flowchart, sequence or class diagram), as ```mermaid blocks do. A diagram that cannot be parsed is shown as code, with the error below it; so is any diagram when the library is built without IMGUI_RICHMD_WITH_MERMAID.
Limitations: a subset of Mermaid, for small and medium diagrams, with its own layout (not a copy of mermaid.js) and the colors of the ImGui style. The other diagram types, styles (classDef, style), click, themes, front matter and markdown in labels are not supported. Details: docs/mermaid.md in imgui_rich_md.

def render_text_as_link(text: str, url: str) -> None
void RenderTextAsLink(const char* text, const char* url);

Renders a link with the given text and url. Can be used outside of markdown rendering.

Style and fonts

SizedFont (class)

Note: Since v1.92, Fonts can be displayed at any size: in order to display a font at a given size, we need to call
ImGui::PushFont(font, size) (or call separately ImGui::PushFontSize)

AttributeC++
font: ImFontImFont* font;
size: floatfloat size;
SizedFont.__init__
def __init__(self) -> None

Autogenerated default constructor

get_code_font

def get_code_font() -> SizedFont
SizedFont GetCodeFont();

MarkdownFontSpec (class)

AttributeC++
italic: boolbool italic = false;
bold: boolbool bold = false;
header_level: intint headerLevel = 0;0 means no header, 1 means h1, 2 means h2, etc.
MarkdownFontSpec.__init__
def __init__(self, italic_: bool = False, bold_: bool = False, header_level_: int = 0) -> None
MarkdownFontSpec(bool italic_ = false, bool bold_ = false, int headerLevel_ = 0) :
            italic(italic_), bold(bold_), headerLevel(headerLevel_);

get_font

def get_font(font_spec: MarkdownFontSpec) -> SizedFont
SizedFont GetFont(const MarkdownFontSpec& fontSpec);
def link_color() -> ImVec4
ImVec4 LinkColor();

Capabilities

has_latex

def has_latex() -> bool
bool HasLatex();

... and

......

rendered as formulas (else shown as their source)

What this build and its host provide (available once a context exists).

has_url_images

def has_url_images() -> bool
bool HasUrlImages();

images downloaded from http(s) urls

has_code_editor

def has_code_editor() -> bool
bool HasCodeEditor();

code blocks with syntax highlighting (else plain monospaced blocks)

Legacy names

initialize_markdown

def initialize_markdown(options: Optional[MarkdownOptions] = None) -> None
void InitializeMarkdown(const MarkdownOptions& options = MarkdownOptions());

The former names, kept for existing code.
The former names: InitializeMarkdown makes a default context and makes it current (a second call does nothing); DeInitializeMarkdown destroys it.

Python bindings defaults:
If options is None, then its default value will be: MarkdownOptions()

de_initialize_markdown

def de_initialize_markdown() -> None
void DeInitializeMarkdown();

render_unindented

def render_unindented(markdown_string: str) -> None
void RenderUnindented(const std::string& markdownString);

The former name of Render

get_font_loader_function

def get_font_loader_function() -> VoidFunction
VoidFunction GetFontLoaderFunction();

Legacy: the fonts now load at the first Render(). The returned function loads them right away, for hosts that build their font atlas once (no dynamic fonts).