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: 38 functions, 11 classes, 2 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 = '') -> NoneRenders ![[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)
document¶
def document(id: str, size: Optional[ImVec2Like] = None, options: Optional[DocumentOptions] = None) -> ContextManager[None]A document, as a context manager: with rich_md.document("doc"): calls begin_document() on entry and
end_document() on exit. (Python only; C++: BeginDocument() / EndDocument())
rich_md_host.h¶
MarkdownDownloadStatus (enum)¶
enum class MarkdownDownloadStatusStatus of a download (see HostServices::Download)
| Member | Value | C++ | |
|---|---|---|---|
not_started | 0 | NotStarted | Download has not been initiated |
downloading | 1 | Downloading | Download is in progress (show placeholder) |
ready | 2 | Ready | Download complete, data is available |
failed | 3 | Failed | Download failed, errorMessage has details |
MarkdownDownloadResult (class)¶
struct MarkdownDownloadResultResult of a download attempt
| Attribute | C++ | |
|---|---|---|
status: MarkdownDownloadStatus | MarkdownDownloadStatus status = MarkdownDownloadStatus::NotStarted; | |
error_message: str | std::string errorMessage; | Only valid if status == Failed |
MarkdownDownloadResult.__init__¶
def __init__(self) -> NoneAutogenerated default constructor
MarkdownDownloadResult.fill_from_bytes¶
def fill_from_bytes(self, data: bytes) -> NoneFill the result data from a Python bytes object.
Python additions¶
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]]) -> NoneSets the function that downloads URL images (HostServices
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 = '', root: str = '') -> strstd::string ResolveTransclusions(const std::string& markdown, const ReadTextFile& readFile, const std::string& currentFile = "", const std::string& root = "");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.
The embeds name files beside or below the document only (root empty: the folder of currentFile; for a text
from no file, relative paths, below the assets): a document from anyone must not show a file of the machine.
A caller that trusts the text widens it: root is the folder the embeds may reach, “/” for any file.
rich_md.h¶
render¶
def render(markdown_string: str) -> Nonevoid 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).
Its size follows a size pushed with ImGui::PushFont(None, size), relative to the frame’s base size:
PushFont(None, ImGui::GetStyle().FontSizeBase * 0.8) renders it at 80%.
render_raw¶
def render_raw(markdown_string: str) -> Nonevoid RenderRaw(const std::string& markdownString);Renders a markdown string as is (no unindent, no transclusion)
push_selectable_text¶
def push_selectable_text(selectable: bool) -> Nonevoid 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() -> Nonevoid PopSelectableText();set_selectable_text_default¶
def set_selectable_text_default(selectable: bool) -> Nonevoid SetSelectableTextDefault(bool selectable);Whether the text can be selected, outside of a PushSelectableText(): changes the option selectableText of the current context
Headings¶
Heading (class)¶
struct HeadingA heading of the last render
| Attribute | C++ | |
|---|---|---|
level: int | int level = 1; | 1 to 6 |
text: str | std::string text; | without markup |
slug: str | std::string slug; | its anchor, made from the text as GitHub does (a repeated title gets -1, -2...) |
y: float | float y = 0.f; | its top, in its window’s content coordinates: SetScrollY(y) shows it at the top |
hidden: bool | bool hidden = false; | inside a collapsed <details> or a fold: y is the one of what hides it |
Heading.__init__¶
def __init__(self) -> NoneAutogenerated default constructor
last_render_headings¶
def last_render_headings() -> List[Heading]const std::vector<Heading>& LastRenderHeadings();The headings of the last Render() call (valid until the next one)
fold_all_headings¶
def fold_all_headings(folded: bool) -> Nonevoid FoldAllHeadings(bool folded);Folds (or unfolds) all the foldable headings (MarkdownOptions::foldableHeadings), from the next frame: those of the current document between BeginDocument() and EndDocument(), else those of the last Render()
Documents¶
ScrollAnimation (enum)¶
enum class ScrollAnimationThe scroll to a match, a heading or an anchor: eased over scrollAnimationSeconds, unless reduced motion is asked
| Member | Value | C++ | |
|---|---|---|---|
follow_system | 0 | FollowSystem | animated, unless the system asks for reduced motion (HostServices::PrefersReducedMotion) |
always | 1 | Always | |
never | 2 | Never |
DocumentOptions (class)¶
struct DocumentOptionsThe options of a document
| Attribute | C++ | |
|---|---|---|
toc: bool | bool toc = true; | |
toc_min_headings: int | int tocMinHeadings = 3; | with fewer headings, no table of contents |
toc_max_level: int | int tocMaxLevel = 3; | the deepest level listed |
narrow_width: float | float narrowWidth = 40.f; | |
search: bool | bool search = true; | |
scroll_animation: ScrollAnimation | ScrollAnimation scrollAnimation = ScrollAnimation::FollowSystem; | |
scroll_animation_seconds: float | float scrollAnimationSeconds = 0.3f; | the duration of an animated scroll, whatever its distance |
scroll_anchoring: bool | bool scrollAnchoring = true; | |
foldable_headings: bool | bool foldableHeadings = false; |
DocumentOptions.__init__¶
def __init__(self) -> NoneAutogenerated default constructor
begin_document¶
def begin_document(id: str, size: Optional[ImVec2Like] = None, options: Optional[DocumentOptions] = None) -> Nonevoid BeginDocument(const char* id, ImVec2 size = ImVec2(0.f, 0.f), const DocumentOptions& options = DocumentOptions());A document: the renders and the widgets drawn until EndDocument() share a scroll area and their headings. size: as BeginChild (0: all the available space). Call EndDocument() in the same frame. The content is always drawn: there is no return value to skip it. One document at a time.
Python bindings defaults:
If any of the params below is None, then its default value below will be used:
* size: ImVec2(0., 0.)
* options: DocumentOptions()
end_document¶
def end_document() -> Nonevoid EndDocument();render_document¶
def render_document(id: str, markdown: str, size: Optional[ImVec2Like] = None, options: Optional[DocumentOptions] = None) -> Nonevoid RenderDocument(const char* id, const std::string& markdown, ImVec2 size = ImVec2(0.f, 0.f), const DocumentOptions& options = DocumentOptions());The one-call form: BeginDocument(id, size, options), Render(markdown), EndDocument()
Python bindings defaults:
If any of the params below is None, then its default value below will be used:
* size: ImVec2(0., 0.)
* options: DocumentOptions()
document_heading¶
def document_heading(level: int, text: str, draw_title: bool = True) -> boolbool DocumentHeading(int level, const std::string& text, bool drawTitle = true);Starts a section of the document that is not markdown (widgets, a plot): a heading of the document, with its slug
(an anchor for [text](#slug) links). drawTitle: draws the text as a markdown heading of that level; False when
the title is drawn by other means (an ImGui text, a plot’s own title), or not at all. Returns whether the section
shows: False when a fold hides it (MarkdownOptions::foldableHeadings), and the application skips its widgets.
Folding text¶
FoldingTextOptions (class)¶
struct FoldingTextOptionsThe options of a folding text
| Attribute | C++ | |
|---|---|---|
start_folded: bool | bool startFolded = false; | folded at first (else open, until the user folds it) |
fold_on_click_elsewhere: bool | bool foldOnClickElsewhere = false; | it folds when the user clicks or taps elsewhere in the window |
animation_seconds: float | float animationSeconds = 0.25f; | the slide (none when the system asks for reduced motion) |
FoldingTextOptions.__init__¶
def __init__(self) -> NoneAutogenerated default constructor
render_folding¶
def render_folding(id: str, markdown: str, options: Optional[FoldingTextOptions] = None) -> boolbool RenderFolding(const char* id, const std::string& markdown, const FoldingTextOptions& options = FoldingTextOptions());Renders a markdown text, folded to its first paragraph (the headings before it stay) or to a line , or open; a link at its end folds or unfolds it. id: keeps its state, in the current window. Returns whether it is open.
Python bindings defaults:
If options is None, then its default value will be: FoldingTextOptions()
Options and callbacks¶
MarkdownFontOptions (class)¶
struct MarkdownFontOptions| Attribute | C++ | |
|---|---|---|
font_base_path: str | std::string fontBasePath = "fonts/Roboto/Roboto"; | |
regular_size: float | float regularSize = 16.f; | |
header_size_factors: np.ndarray | float 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) -> NoneAutogenerated default constructor
MarkdownImage (class)¶
struct MarkdownImage| Attribute | C++ | |
|---|---|---|
texture_id: ImTextureID | ImTextureID texture_id; | |
size: ImVec2 | ImVec2 size; | |
uv0: ImVec2 | ImVec2 uv0; | |
uv1: ImVec2 | ImVec2 uv1; | |
col_tint: ImVec4 | ImVec4 col_tint; | |
col_border: ImVec4 | ImVec4 col_border; |
MarkdownImage.__init__¶
def __init__(self) -> NoneAutogenerated default constructor
on_image_default¶
def on_image_default(image_path: str) -> Optional[MarkdownImage]std::optional<MarkdownImage> OnImage_Default(const std::string& image_path);on_open_link_default¶
def on_open_link_default(url: str) -> Nonevoid OnOpenLink_Default(const std::string& url);is_web_url¶
def is_web_url(url: str) -> boolbool IsWebUrl(const std::string& url);Whether a link is a web address (http:// or https://, any case): the only ones OnOpenLink_Default opens
MarkdownCallbacks (class)¶
struct MarkdownCallbacks| Attribute | C++ | |
|---|---|---|
on_open_link: StringFunction | StringFunction OnOpenLink = OnOpenLink_Default; | |
on_image: MarkdownImageFunction | MarkdownImageFunction OnImage = OnImage_Default; | |
on_html_div: HtmlDivFunction | HtmlDivFunction OnHtmlDiv; | |
on_html_span: HtmlSpanFunction | HtmlSpanFunction 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) -> NoneAutogenerated 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]]) -> NoneDeprecated: 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)¶
struct MarkdownOptions| Attribute | C++ | |
|---|---|---|
font_options: MarkdownFontOptions | MarkdownFontOptions fontOptions; | |
callbacks: MarkdownCallbacks | MarkdownCallbacks callbacks; | |
with_latex: bool | bool withLatex = false; | |
autolinks: bool | bool autolinks = true; | |
hard_soft_breaks: bool | bool hardSoftBreaks = false; | |
selectable_text: bool | bool selectableText = true; | |
foldable_headings: bool | bool foldableHeadings = false; | |
foldable_headings_min_level: int | int foldableHeadingsMinLevel = 2; | the first level that folds (a “#” heading often titles the whole text) |
MarkdownOptions.__init__¶
def __init__(self) -> NoneAutogenerated default constructor
Context¶
create_context¶
def create_context(options: Optional[MarkdownOptions] = None) -> ContextContext* 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) -> Nonevoid DestroyContext(Context* context = nullptr);set_current_context¶
def set_current_context(context: Context) -> Nonevoid SetCurrentContext(Context* context);get_current_context¶
def get_current_context() -> ContextContext* GetCurrentContext();set_assets_folder¶
def set_assets_folder(folder: str) -> Nonevoid 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 = '') -> Nonevoid 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).
render_file() 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]) -> Nonevoid 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) -> Nonevoid 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.
render_text_as_link¶
def render_text_as_link(text: str, url: str) -> Nonevoid 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)¶
struct SizedFontNote: 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)
| Attribute | C++ | |
|---|---|---|
font: ImFont | ImFont* font; | |
size: float | float size; |
SizedFont.__init__¶
def __init__(self) -> NoneAutogenerated default constructor
get_code_font¶
def get_code_font() -> SizedFontSizedFont GetCodeFont();The markdown’s fonts, at the size that a render would use now (see Render(): they follow a pushed size)
MarkdownFontSpec (class)¶
struct MarkdownFontSpec| Attribute | C++ | |
|---|---|---|
italic: bool | bool italic = false; | |
bold: bool | bool bold = false; | |
header_level: int | int 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) -> NoneMarkdownFontSpec(bool italic_ = false, bool bold_ = false, int headerLevel_ = 0) :get_font¶
def get_font(font_spec: MarkdownFontSpec) -> SizedFontSizedFont GetFont(const MarkdownFontSpec& fontSpec);link_color¶
def link_color() -> ImVec4ImVec4 LinkColor();Capabilities¶
has_latex¶
def has_latex() -> boolbool 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() -> boolbool HasUrlImages();images downloaded from http(s) urls
has_code_editor¶
def has_code_editor() -> boolbool HasCodeEditor();code blocks with syntax highlighting (else plain monospaced blocks)
Legacy names¶
initialize_markdown¶
def initialize_markdown(options: Optional[MarkdownOptions] = None) -> Nonevoid 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() -> Nonevoid DeInitializeMarkdown();render_unindented¶
def render_unindented(markdown_string: str) -> Nonevoid RenderUnindented(const std::string& markdownString);The former name of Render
get_font_loader_function¶
def get_font_loader_function() -> VoidFunctionVoidFunction 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).