An open API service indexing awesome lists of open source software.

https://github.com/indaco/herald-md

Render Markdown to the terminal with herald's full theming and composability.
https://github.com/indaco/herald-md

Last synced: 4 months ago
JSON representation

Render Markdown to the terminal with herald's full theming and composability.

Awesome Lists containing this project

README

          


herald-md


Render Markdown to the terminal with herald's full theming and composability.



CI


Code coverage


Go Report Card


Security Scan


version


Go Reference


License


When to use |
Installation |
Quick Start |
Elements |
Theming |
Extensions |
Composing |
Examples

herald-md parses Markdown with [goldmark](https://github.com/yuin/goldmark) (CommonMark + GFM) and renders it to the terminal through [herald](https://github.com/indaco/herald)'s typography system - themed headings, styled code blocks, tables, alerts, and more, all controlled by a single `Typography` instance.

## When to use herald-md

[glamour](https://github.com/charmbracelet/glamour) is an excellent library for rendering Markdown in the terminal.

herald-md takes a different approach. Paired with [herald](https://github.com/indaco/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 `ColorPalette` give you full control over every element.
- You are **mixing Markdown with programmatic elements** - `Render` returns a plain string you can pass directly to herald's [`Compose`](https://github.com/indaco/herald#composing-elements) alongside other herald calls.

## Installation

Requires Go 1.25+.

```sh
go get github.com/indaco/herald-md@latest
```

## Quick Start

> [!NOTE]
> 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"`.

```go
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))
}
```

## Supported elements

| 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 | `` | `Link(url)` |
| Image | `![alt](url)` | `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 | `text` | `Q()` |
| Citation | `text` | `Cite()` |
| Sample output | `text` | `Samp()` |
| Variable | `text` | `Var()` |
| Keyboard key | `text` | `Kbd()` |
| Highlight | `text` | `Mark()` |
| Inserted text | `text` | `Ins()` |
| Deleted text | `text` | `Del()` |
| Subscript | `text` | `Sub()` |
| Superscript | `text` | `Sup()` |
| Abbreviation | `text` | `Abbr()` |
| Underline | `text` | `Underline()` |
| Small text | `text` | `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 (``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``) are mapped to the corresponding herald method. Unknown HTML tags pass through as raw text.
- Nested lists are automatically rendered with `NestUL`/`NestOL` when sub-lists are detected, falling back to flat `UL`/`OL` for simple lists.
- Column alignment specified in GFM tables (`:-`, `:-:`, `-:`) is preserved via `WithColumnAlign`.

## Theming

Pass any herald theme to `herald.New()` and all Markdown output will use it:

```go
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.

## Custom goldmark extensions

Use `NewRenderer` to add goldmark extensions beyond the default GFM set:

```go
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.

## Composing with herald

Because `Render` returns a string, it composes directly with other herald output via `ty.Compose`:

```go
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)
```

## Examples

Runnable examples are in the [`examples/`](examples/) directory:

### Core (`0xx`)

| Example | Description | Run |
| -------------------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------ |
| [000_render-file](examples/000_render-file/) | Render a Markdown file with the default theme; accepts any `.md` as argument | `go run ./examples/000_render-file/` |

### Extensions (`1xx`)

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](examples/100_definition-list/) | Custom goldmark extension: definition lists rendered as herald `DL` | `cd examples/100_definition-list && go run .` |

## License

This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.