Sign in

    moon-md-viewer

    Render CommonMark as ANSI for the terminal.

    Download zip
    Author
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    2 days ago
    Downloads
    12

    #moon-md-viewer

    Render CommonMark as text a terminal can actually display.

    Markdown tooling usually stops at HTML, and a terminal has no engine to render HTML — you either look at raw tags or you open a browser. moon-md-viewer walks the CommonMark AST and writes ANSI instead: headings keep their ## markers and gain a colour, lists keep their indentation, tables are drawn as boxes, and links become OSC 8 hyperlinks you can click.

    Rendered at 56 columns:

    ## Installation Add the dependency and build: bash │ moon add daqing/moon-md-viewer ┌─────────┬───────────────────────┐ │ Option │ Meaning │ ├─────────┼───────────────────────┤ │ --theme │ dark, light or none │ │ --width │ wrap width in columns │ └─────────┴───────────────────────┘ - Headings keep their markers - Links become OSC 8 hyperlinks

    #Running

    With the MoonBit toolchain installed:

    moon run cmd/main -- README.mbt.md moon run cmd/main -- --width 60 docs/design.md cat notes.md | moon run cmd/main

    moon build --release writes a standalone binary to _build/native/release/build/cmd/main/main.exe.

    #Options

    OptionDefaultMeaning
    --theme <dark\|light\|none>darkColour palette; none emits no colour at all.
    --width <columns>$COLUMNS, else 80Wrap width.
    --color <auto\|always\|never>autoauto colours only when stdout is a terminal that supports it.
    --pager <auto\|always\|never>autoauto pages through $PAGER when stdout is a terminal.

    Any remaining arguments are input files; -, or no file at all, reads standard input. Colour is suppressed when stdout is not a terminal, TERM is dumb, or NO_COLOR is set.

    #Paging

    Output going to a terminal is piped through $PAGER, or through less when $PAGER is unset. $LESS defaults to FRX — the settings git uses — so colour reaches the pager, the text stays on screen after quitting, and less exits by itself when the document already fits on one screen. --pager never prints directly, --pager always pages even when stdout is a pipe, and a pager that cannot be started falls back to printing.

    #Library

    ///|
    let text = @moon-md-viewer.render(
    markdown,
    theme=@moon-md-viewer.Dark,
    width=80,
    )

    render returns the document and a trailing newline, or an empty string for input that holds nothing printable. Theme is Dark, Light or NoColor. char_width, display_width and truncate_visible are exported for callers that need to measure or cut styled text themselves.

    #What it handles

    • Widths are measured in terminal columns, so CJK and emoji count as two; wrapping, table columns and truncation stay aligned in a CJK document.
    • CJK text breaks between characters, and closing punctuation (。, ,, 」 …) never starts a line.
    • Code blocks are emitted verbatim and are never rewrapped.
    • Emphasis, strikethrough, task lists, footnotes, block quotes, tables, thematic breaks, autolinks and math spans ($…$, shown as written).

    #What it does not do

    • Images: the alt text is shown with the URL beside it.
    • Syntax highlighting inside code blocks.
    • Raw HTML: dropped inline, shown dimmed and verbatim as a block.

    #Development

    moon test # 34 behavioural and unit tests moon info && moon fmt

    Theme

    pub(all) enum Theme {
    Dark
    Light
    NoColor
    }

    Colour theme for terminal output.

    NoColor emits no SGR escape sequences at all and is meant for output that is piped into a file or another program.

    char_width

    fn char_width(c : Char) -> Int

    Number of terminal columns a single character occupies.

    display_width

    fn display_width(s : String) -> Int

    Number of terminal columns s occupies, ignoring ANSI escape sequences.

    render

    fn render(markdown : String, theme? : Theme, width? : Int) -> String

    Render CommonMark into text meant to be read in a terminal.

    The document is parsed with the cmark extensions enabled (tables, task lists, strikethrough, footnotes, math) and laid out to width columns. Theme::NoColor produces plain text with no escape sequences at all.

    truncate_visible

    fn truncate_visible(s : String, max : Int) -> String

    Cut s down to at most max columns, appending an ellipsis when something was dropped. Escape sequences pass through untouched and a style left open by the cut is closed.