Tui-markdown
An experimental Proof of Concept library for converting markdown content to a Ratatui Text
value. See Markdown-reader for an example application that uses this library.
GitHub Repository · API Docs · [Examples] · Changelog · Contributing
Installation
cargo add tui-markdown
Usage
let input = "# Heading\n\n**bold**"; // this can come from wherever
let text = from_str;
text.render;
Syntax highlighting themes
With the default highlight-code feature enabled, fenced code blocks whose language is recognized
use the built-in Base16OceanDark syntax-highlighting theme. Pass a BuiltinCodeTheme to select
a different bundled theme:
use ;
let options = default.code_theme;
let markdown = r#"```rust
fn main() {}
```"#;
let text = from_str_with_options;
CodeTheme::from_file reads and parses a TextMate .tmTheme file immediately. The returned theme
owns the parsed data, so rendering does not access the file again:
use ;
Use CodeTheme::from_textmate with include_str! to compile a theme into the application
instead of reading it at runtime. The returned theme owns the parsed data and does not borrow the
source string:
use ;
Markdown presentation symbols
The renderer normally retains heading markers and frames block code with triple backticks. A custom
style sheet can replace either symbol with StyleSheet::heading_marker() and
StyleSheet::code_block_fence(), or return an empty string to hide it:
use Style;
use ;
;
let options = new;
let markdown = "# Heading\n\n```text\ncode\n```";
let text = from_str_with_options;
assert_eq!;
The code-block fence choice is independent of syntax highlighting and applies to fenced and indented code blocks alike. Other presentation symbols, such as list markers, blockquote prefixes, image indicators, and table borders, retain their standard output.
Status
This is working code, but not every markdown feature is supported. PRs welcome!
- Headings
- Heading attributes / classes / anchors
- Normal paragraphs
- Block quotes
- Nested block quotes
- GFM alerts
- Bold (strong)
- Italic (emphasis)
- Strikethrough
- Ordered lists
- Unordered lists
- Code blocks
- HTML
- Math
- Footnotes
- Definition lists
- Linebreak handling
- Rule
- Tables
- Tasklists
- Links
- Images
- Metadata blocks
- Superscript
- Subscript
Linebreaks are rendered with Markdown defaults: soft breaks become spaces, hard breaks insert a new line.
Images render as text fallbacks rather than terminal graphics. The default output uses [img]
followed by the image description, or the destination when the description is empty. For example,
Before  after renders as Before [img] diagram after.
Use ImageFallback to show the destination instead, or to include it after the description:
use ;
let options = default.image_fallback;
let text = from_str_with_options;
assert_eq!;
GFM tables render with Unicode box-drawing borders and honor left, center, and right column alignment:
┌──────┬────────┐
│ Name │ Status │
├──────┼────────┤
│ API │ Ready │
└──────┴────────┘
Column widths use terminal display width, so wide CJK and emoji characters remain aligned. Use
StyleSheet::table_header() for header cells, StyleSheet::table_cell() for body cells, and
StyleSheet::table_border() for the box-drawing borders. Cell styles cover content and padding
while preserving inline formatting unless they set the same style property.
Links are rendered as label (URL). The link style applies to both the visible label and URL while
preserving nested inline formatting such as bold text.
GFM alerts render a bold icon and canonical English label above their quoted body. Customize each
kind's color with StyleSheet::alert(), its terminal-friendly icon with
StyleSheet::alert_icon(), and its label with StyleSheet::alert_label(). Returning an empty
icon or label displays only the other component.
Raw inline HTML tags and HTML blocks are displayed literally rather than interpreted as terminal
markup. They are dimmed by default and can be customized with StyleSheet::html().
Inline and display math keep their $...$ and $$...$$ delimiters visible. Inline math is
magenta and italic by default, while display math is magenta and preserves multiline formulas as
separate terminal lines. Customize these styles with StyleSheet::math_inline() and
StyleSheet::math_display().
Footnote references such as [^source] are displayed as [source], and definitions are displayed
as [source]: .... References are dim and italic by default, while definitions are dim. Customize
these styles with StyleSheet::footnote_ref() and StyleSheet::footnote_def().
Definition-list terms are bold by default, with each description rendered on its own line after a
colon-and-space prefix. Customize them with StyleSheet::definition_term() and
StyleSheet::definition_description().
Metadata blocks are rendered using the metadata block style so front matter is visible, including
the delimiter lines (for example --- in YAML-style blocks).
use Text;
use from_str;
let markdown = r#"---
title: Demo
tags:
- one
- two
---
Body
"#;
let text = from_str;
assert_eq!;
License
Copyright (c) 2024 Josh McKinney
This project is licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
See CONTRIBUTING.md.