spruce/markdown
Markdown to ANSI terminal rendering.
Rendering is driven by the mork
parser (canonical home: https://git.liten.app/krig/mork) and walks its
document AST directly rather than going through mork’s HTML output.
GFM support
The following GitHub Flavored Markdown extensions are supported:
- Tables (rendered via
spruce/table) - Task list items (
- [x]/- [ ]) - Strikethrough (
~~text~~) - Extended autolinks for bare URLs and
www.links
In addition, GitHub-style alerts (> [!NOTE], [!TIP], [!IMPORTANT],
[!WARNING], [!CAUTION]) and Astro/Starlight :::type[Title] container
directives are rendered as colored callouts.
Known limitations
These are GitHub/Markdown features that are not rendered. Most stem from
upstream mork (tracked in its
TODO.md); a few
are deliberate choices here.
- Emoji shortcodes (
:rocket:) are not expanded.morkonly expands them in its HTML output path, not in the document AST this module renders, so enablingmork.emojishas no effect here. - Email autolinks (bare
me@example.com) are not linked; extended email autolinking is unimplemented upstream (morkTODO: “autolink (email)”). - Footnotes: a
[^1]reference renders as literal[^1]and the definition body is dropped. Footnote bodies are not yet implemented upstream, and inline footnotes (^[...]) are unsupported. - Heading ID attributes (
## Title {#id}) are stripped from the rendered text (viamork.heading_ids), since a terminal has no anchors to link to. The id itself is parsed but not rendered. - Raw HTML is not sanitized. Inline and block HTML is passed through
(rendered dimmed), not escaped or stripped.
morkdoes not implement GFM’s tagfilter. This is harmless in a terminal, but do not rely on this module to neutralize untrusted HTML.
Types
Markdown rendering options: the theme and an optional wrap width.
pub opaque type Options
A set of styles controlling how each Markdown element is rendered.
Use a built-in theme as a base and replace selected fields:
markdown.Theme(
..markdown.dark_theme(),
h1: style.new() |> style.bold |> style.fg(style.Hex(0xff6b6b)),
)
The public constructor also supports defining every style from scratch.
pub type Theme {
Theme(
h1: style.Style,
h2: style.Style,
h3: style.Style,
h4: style.Style,
h5: style.Style,
h6: style.Style,
emphasis: style.Style,
strong: style.Style,
strikethrough: style.Style,
highlight: style.Style,
code_span: style.Style,
link: style.Style,
link_target: style.Style,
html: style.Style,
code: highlight.Theme,
code_border: style.Color,
quote_border: style.Color,
rule: style.Style,
table_header: style.Style,
)
}
Constructors
-
Theme( h1: style.Style, h2: style.Style, h3: style.Style, h4: style.Style, h5: style.Style, h6: style.Style, emphasis: style.Style, strong: style.Style, strikethrough: style.Style, highlight: style.Style, code_span: style.Style, link: style.Style, link_target: style.Style, html: style.Style, code: highlight.Theme, code_border: style.Color, quote_border: style.Color, rule: style.Style, table_header: style.Style, )
Values
pub fn adaptive_theme() -> Theme
A theme whose colors adapt to the terminal background (light vs dark),
resolved per render from spruce.background. This is the default theme used
by render and default_options. On Unknown backgrounds it renders as
dark.
pub fn default_options() -> Options
Default options: the adaptive theme and no width limit.
pub fn print(context: spruce.Spruce, markdown: String) -> Nil
Render Markdown with the default options and print it to stdout.
pub fn render(context: spruce.Spruce, markdown: String) -> String
Render Markdown to styled terminal text using the default options.
pub fn render_with(
context: spruce.Spruce,
markdown: String,
options: Options,
) -> String
Render Markdown to styled terminal text with explicit options.
pub fn with_width(options: Options, width: Int) -> Options
Wrap rendered output to a maximum visual width, including context indentation and structural markers. Negative values clamp to 0, and 0 keeps the output unconstrained. Indentation, structural markers, and frames are reduced or omitted when the width cannot fit them. A single grapheme that is wider than the limit is preserved.