When to use | Installation | Quick Start | Elements | Theming | Extensions | Composing | Examples
herald-md parses Markdown with goldmark (CommonMark + GFM) and renders it to the terminal through herald's typography system - themed headings, styled code blocks, tables, alerts, and more, all controlled by a single Typography instance.
glamour is an excellent library for rendering Markdown in the terminal.
herald-md takes a different approach. Paired with herald, it gives you a full typography layer where Markdown is one input format among many. Use it when:
- You want one theme for your entire CLI or TUI - pick a built-in theme (Dracula, Catppuccin, Base16, Charm) or define your own, and both Markdown and programmatic output use it automatically - no separate style configuration needed.
- You need fine-grained customization - functional options and
ColorPalettegive you full control over every element. - You are mixing Markdown with programmatic elements -
Renderreturns a plain string you can pass directly to herald'sComposealongside other herald calls.
Requires Go 1.25+.
go get github.com/indaco/herald-md@latestNote
The Go module path is github.com/indaco/herald-md but the package name is heraldmd. Use an import alias: heraldmd "github.com/indaco/herald-md".
package main
import (
"fmt"
"os"
"github.com/indaco/herald"
heraldmd "github.com/indaco/herald-md"
)
func main() {
source, _ := os.ReadFile("doc.md")
ty := herald.New()
fmt.Println(heraldmd.Render(ty, source))
}| Element | Markdown syntax | Herald method |
|---|---|---|
| Headings H1–H6 | # H1 … ###### H6 |
H1() – H6() |
| Paragraph | plain text | P() |
| Blockquote | > text |
Blockquote() |
| Fenced code block | ```lang |
CodeBlock(code, lang) |
| Indented code block | 4-space indent | CodeBlock(code) |
| Horizontal rule | --- |
HR() |
| Unordered list | - item |
UL() / NestUL() |
| Ordered list | 1. item |
OL() / NestOL() |
| Bold | **text** |
Bold() |
| Italic | *text* |
Italic() |
| Strikethrough | ~~text~~ |
Strikethrough() |
| Inline code | `code` |
Code() |
| Link | [label](url) |
Link(label, url) |
| Autolink | <https://...> |
Link(url) |
| Image |  |
Link(alt, url) (terminals cannot render images) |
| GFM table | pipe table syntax | Table() / TableWithOpts() |
| GitHub alert | > [!NOTE] etc. |
Alert() / Note() / Tip() etc. |
| Definition list * | Term + : desc |
DL() |
| Footnote ref * | [^1] |
FootnoteRef() |
| Footnote section * | [^1]: text |
FootnoteSection() |
| Inline quotation | <q>text</q> |
Q() |
| Citation | <cite>text</cite> |
Cite() |
| Sample output | <samp>text</samp> |
Samp() |
| Variable | <var>text</var> |
Var() |
| Keyboard key | <kbd>text</kbd> |
Kbd() |
| Highlight | <mark>text</mark> |
Mark() |
| Inserted text | <ins>text</ins> |
Ins() |
| Deleted text | <del>text</del> |
Del() |
| Subscript | <sub>text</sub> |
Sub() |
| Superscript | <sup>text</sup> |
Sup() |
| Abbreviation | <abbr>text</abbr> |
Abbr() |
| Underline | <u>text</u> |
Underline() |
| Small text | <small>text</small> |
Small() |
Elements marked with * require enabling the corresponding goldmark extension via NewRenderer. All other elements work out of the box with the default GFM configuration.
- Inline HTML tags (
<q>,<cite>,<samp>,<var>,<kbd>,<mark>,<ins>,<del>,<sub>,<sup>,<abbr>,<u>,<small>,<b>,<i>,<s>,<em>,<strong>,<code>) are mapped to the corresponding herald method. Unknown HTML tags pass through as raw text. - Nested lists are automatically rendered with
NestUL/NestOLwhen sub-lists are detected, falling back to flatUL/OLfor simple lists. - Column alignment specified in GFM tables (
:-,:-:,-:) is preserved viaWithColumnAlign.
Pass any herald theme to herald.New() and all Markdown output will use it:
ty := herald.New(herald.WithTheme(herald.DraculaTheme()))
fmt.Println(heraldmd.Render(ty, source))Custom ColorPalette values and individual With* options work the same way - configure the Typography instance once and Render inherits everything.
Use NewRenderer to add goldmark extensions beyond the default GFM set:
r := heraldmd.NewRenderer(
goldmark.WithExtensions(extension.Footnote),
)
fmt.Println(r.Render(ty, source))The package-level Render function uses a default renderer with GFM enabled.
Because Render returns a string, it composes directly with other herald output via ty.Compose:
ty := herald.New()
page := ty.Compose(
ty.H1("My App"),
heraldmd.Render(ty, readmeBytes), // readmeBytes loaded via os.ReadFile(...)
ty.HR(),
ty.KVGroup([][2]string{
{"Version", "1.0.0"},
{"License", "MIT"},
}),
)
fmt.Println(page)Runnable examples are in the examples/ directory:
| Example | Description | Run |
|---|---|---|
| 000_render-file | Render a Markdown file with the default theme; accepts any .md as argument |
go run ./examples/000_render-file/ |
Examples in this range are separate Go modules with their own go.mod to keep extra dependencies out of herald-md's core. Run them with cd into the example directory first.
| Example | Description | Run |
|---|---|---|
| 100_definition-list | Custom goldmark extension: definition lists rendered as herald DL |
cd examples/100_definition-list && go run . |
This project is licensed under the MIT License - see the LICENSE file for details.