Bun

namespace

markdown

namespace markdown

Markdown related APIs.

Provides fast markdown parsing and rendering with three output modes:

  • html() — render to an HTML string
  • render() — render with custom callbacks for each element
  • react() — parse to React-compatible JSX elements

Supports GFM extensions (tables, strikethrough, task lists, autolinks) and component overrides to replace default HTML tags with custom components.

// Render markdown to HTML
const html = Bun.markdown.html("# Hello **world**");
// "<h1>Hello <strong>world</strong></h1>\n"

// Render with custom callbacks
const ansi = Bun.markdown.render("# Hello **world**", {
  heading: (children, { level }) => `\x1b[1m${children}\x1b[0m\n`,
  strong: (children) => `\x1b[1m${children}\x1b[22m`,
  paragraph: (children) => children + "\n",
});

// Render as a React component
function Markdown({ text }: { text: string }) {
  return Bun.markdown.react(text);
}

// With component overrides
const element = Bun.markdown.react("# Hello", { h1: MyHeadingComponent });
  • interface AnsiTheme

    Theme for ANSI terminal rendering.

    • colors?: boolean

      Emit ANSI color + styling escape sequences. When false, the renderer falls back to plain ASCII chrome (no box drawing, no emoji, no escape codes).

    • columns?: number

      Line width used for word-wrapping paragraphs and headings and for the horizontal rule. Pass 0 to disable wrapping.

    • kittyGraphics?: boolean

      Inline images using the Kitty Graphics Protocol when the src resolves to a local file on disk. Falls through to the text alt for remote URLs. Supported by Kitty, WezTerm, and Ghostty.

    • light?: boolean

      True when the terminal background is light. Affects the color palette chosen for inline code backgrounds. Defaults to detecting from the COLORFGBG environment variable.

  • interface CellMeta

    Meta passed to th and td callbacks.

    • align?: 'left' | 'center' | 'right'

      Column alignment.

  • interface CellProps

    • align?: 'left' | 'center' | 'right'

      Column alignment.

    • children: unknown[]
  • interface ChildrenProps

  • interface CodeBlockMeta

    Meta passed to the code callback.

    • language?: string

      The info-string language (e.g. "js").

  • interface CodeBlockProps

  • interface ComponentOverrides

    Component overrides for react().

    Replace default HTML tags with custom React components. Each override receives the same props the default element would get.

    function Code({ language, children }: { language?: string; children: React.ReactNode }) {
      return <pre data-language={language}><code>{children}</code></pre>;
    }
    Bun.markdown.react(text, { pre: Code });
    
  • interface HeadingMeta

    Meta passed to the heading callback.

    • id?: string

      Heading ID slug. Set when headings: { ids: true } is enabled.

    • level: number

      Heading level (1–6).

  • interface HeadingProps

    • children: unknown[]
    • id?: string

      Heading ID slug. Set when headings: { ids: true } is enabled.

  • interface ImageMeta

    Meta passed to the image callback.

    • src: string

      Image URL.

    • title?: string

      Image title attribute.

  • interface ImageProps

    • alt?: string

      Alt text.

    • src: string

      Image URL.

    • title?: string

      Image title attribute.

  • interface LinkMeta

    Meta passed to the link callback.

    • href: string

      Link URL.

    • title?: string

      Link title attribute.

  • interface LinkProps

  • interface ListItemMeta

    Meta passed to the listItem callback.

    • checked?: boolean

      Task list checked state. Set for - [x] / - [ ] items.

    • depth: number

      Nesting depth of the parent list. 0 for items in a top-level list.

    • index: number

      0-based index of this item within its parent list.

    • ordered: boolean

      Whether the parent list is ordered.

    • start?: number

      The start number of the parent list (only set when ordered is true).

  • interface ListItemProps

    • checked?: boolean

      Task list checked state. Set for - [x] / - [ ] items.

    • children: unknown[]
  • interface ListMeta

    Meta passed to the list callback.

    • depth: number

      Nesting depth. 0 for a top-level list, 1 for a list inside a list item, etc.

    • ordered: boolean

      Whether this is an ordered list.

    • start?: number

      The start number for ordered lists.

  • interface Options

    Options for configuring the markdown parser.

    By default, GFM extensions (tables, strikethrough, task lists) are enabled.

    • collapseWhitespace?: boolean

      Collapse whitespace in text content. Default: false.

    • hardSoftBreaks?: boolean

      Treat soft line breaks as hard line breaks. Default: false.

    • headings?: boolean | { autolink: boolean; ids: boolean }

      Configure heading IDs and autolink headings. Pass true to enable both heading IDs and autolink headings, or an object to configure individually.

      // Enable both heading IDs and autolink headings
      { headings: true }
      // Enable only heading IDs
      { headings: { ids: true } }
      
    • latexMath?: boolean

      Enable LaTeX math ($inline$ and $$display$$). Default: false.

    • noHtmlBlocks?: boolean

      Disable HTML blocks. Default: false.

    • noHtmlSpans?: boolean

      Disable inline HTML spans. Default: false.

    • noIndentedCodeBlocks?: boolean

      Disable indented code blocks. Default: false.

    • permissiveAtxHeaders?: boolean

      Allow ATX headers without a space after #. Default: false.

    • strikethrough?: boolean

      Enable GFM strikethrough (~~text~~). Default: true.

    • tables?: boolean

      Enable GFM tables. Default: true.

    • tagFilter?: boolean

      Enable the GFM tag filter, which replaces < with &lt; for disallowed HTML tags (e.g. <script>, <style>, <iframe>). Default: false.

    • tasklists?: boolean

      Enable GFM task lists (- [x] item). Default: true.

    • underline?: boolean

      Enable underline syntax (__text__ renders as <u> instead of <strong>). Default: false.

  • interface OrderedListProps

  • interface ReactOptions

    Options for react() — parser options and element symbol configuration.

    • collapseWhitespace?: boolean

      Collapse whitespace in text content. Default: false.

    • hardSoftBreaks?: boolean

      Treat soft line breaks as hard line breaks. Default: false.

    • headings?: boolean | { autolink: boolean; ids: boolean }

      Configure heading IDs and autolink headings. Pass true to enable both heading IDs and autolink headings, or an object to configure individually.

      // Enable both heading IDs and autolink headings
      { headings: true }
      // Enable only heading IDs
      { headings: { ids: true } }
      
    • latexMath?: boolean

      Enable LaTeX math ($inline$ and $$display$$). Default: false.

    • noHtmlBlocks?: boolean

      Disable HTML blocks. Default: false.

    • noHtmlSpans?: boolean

      Disable inline HTML spans. Default: false.

    • noIndentedCodeBlocks?: boolean

      Disable indented code blocks. Default: false.

    • permissiveAtxHeaders?: boolean

      Allow ATX headers without a space after #. Default: false.

    • reactVersion?: 18 | 19

      Which $$typeof symbol to use on the generated elements.

      • 19 (default): Symbol.for('react.transitional.element')
      • 18: Symbol.for('react.element') — use this for React 18 and older
    • strikethrough?: boolean

      Enable GFM strikethrough (~~text~~). Default: true.

    • tables?: boolean

      Enable GFM tables. Default: true.

    • tagFilter?: boolean

      Enable the GFM tag filter, which replaces < with &lt; for disallowed HTML tags (e.g. <script>, <style>, <iframe>). Default: false.

    • tasklists?: boolean

      Enable GFM task lists (- [x] item). Default: true.

    • underline?: boolean

      Enable underline syntax (__text__ renders as <u> instead of <strong>). Default: false.

  • interface RenderCallbacks

    • blockquote?: (children: string) => undefined | null | string

      Blockquote.

    • code?: (children: string, meta?: CodeBlockMeta) => undefined | null | string

      Code block. meta.language is the info-string (e.g. "js"). Only passed for fenced code blocks with a language.

    • codespan?: (children: string) => undefined | null | string

      Inline code (`code`).

    • emphasis?: (children: string) => undefined | null | string

      Emphasis (*text*).

    • heading?: (children: string, meta: HeadingMeta) => undefined | null | string

      Heading (level 1–6). id is set when headings: { ids: true } is enabled.

    • hr?: (children: string) => undefined | null | string

      Horizontal rule.

    • html?: (children: string) => undefined | null | string

      Raw HTML content.

    • image?: (children: string, meta: ImageMeta) => undefined | null | string

      Image. src is the URL, title is the optional title attribute.

    • list?: (children: string, meta: ListMeta) => undefined | null | string

      Ordered or unordered list. start is the first item number for ordered lists.

    • listItem?: (children: string, meta: ListItemMeta) => undefined | null | string

      List item. meta always includes {index, depth, ordered}. meta.start is set for ordered lists; meta.checked is set for task list items.

    • paragraph?: (children: string) => undefined | null | string

      Paragraph.

    • strikethrough?: (children: string) => undefined | null | string

      Strikethrough (~~text~~).

    • strong?: (children: string) => undefined | null | string

      Strong emphasis (**text**).

    • table?: (children: string) => undefined | null | string

      Table.

    • tbody?: (children: string) => undefined | null | string

      Table body.

    • td?: (children: string, meta?: CellMeta) => undefined | null | string

      Table data cell. meta.align is set when column alignment is specified.

    • text?: (text: string) => undefined | null | string

      Plain text content.

    • th?: (children: string, meta?: CellMeta) => undefined | null | string

      Table header cell. meta.align is set when column alignment is specified.

    • thead?: (children: string) => undefined | null | string

      Table head.

    • tr?: (children: string) => undefined | null | string

      Table row.

  • type Component<P = {}> = string | (props: P) => any | new (props: P) => any

    A component that accepts props P: a function, class, or HTML tag name.

  • function ansi(
    input: string | ArrayBufferLike | TypedArray<ArrayBufferLike> | DataView<ArrayBuffer>,
    theme?: AnsiTheme
    ): string;

    Render markdown to an ANSI-colored terminal string.

    Supports headings, lists, tables, inline styles, syntax-highlighted code blocks, links, images, and blockquotes. By default, enables all GFM extensions plus wikilinks, underline, and LaTeX math.

    @param input

    The markdown string or buffer to render

    @param theme

    Optional theme overrides

    @returns

    An ANSI-colored string

    const out = Bun.markdown.ansi("# Hello\n\n**bold** and *italic*\n");
    process.stdout.write(out);
    
    // Plain text, no escape codes
    const plain = Bun.markdown.ansi("# Hello", { colors: false });
    
    // Enable clickable OSC 8 hyperlinks
    const linked = Bun.markdown.ansi("[docs](https://bun.com)", {
      hyperlinks: true,
    });
    
    // Inline images via Kitty Graphics Protocol
    const withImg = Bun.markdown.ansi("![alt](./logo.png)", {
      kittyGraphics: true,
    });
    
    // Custom width
    const wrapped = Bun.markdown.ansi(longText, { columns: 60 });
    
  • function html(
    input: string | ArrayBufferLike | TypedArray<ArrayBufferLike> | DataView<ArrayBuffer>,
    options?: Options
    ): string;

    Render markdown to an HTML string.

    @param input

    The markdown string or buffer to render

    @param options

    Parser options

    @returns

    An HTML string

    const html = Bun.markdown.html("# Hello **world**");
    // "<h1>Hello <strong>world</strong></h1>\n"
    
    // With options
    const html = Bun.markdown.html("## Hello", { headings: { ids: true } });
    // '<h2 id="hello">Hello</h2>\n'
    
  • function react(
    input: string | ArrayBufferLike | TypedArray<ArrayBufferLike> | DataView<ArrayBuffer>,
    components?: ComponentOverrides,
    options?: ReactOptions
    ): unknown;

    Render markdown to React JSX elements.

    Returns a React Fragment containing the parsed markdown as children. Can be returned directly from a component or passed to renderToString().

    Override any HTML element with a custom component by passing it in the second argument, keyed by tag name. Custom components receive the same props the default elements would (e.g. href for links, language for code blocks).

    Parser options (including reactVersion) are passed as a separate third argument. Uses Symbol.for('react.transitional.element') by default (React 19). Pass reactVersion: 18 for React 18 and older.

    @param input

    The markdown string or buffer to parse

    @param components

    Component overrides keyed by HTML tag name

    @param options

    Parser options and element symbol configuration

    @returns

    A React Fragment element containing the parsed markdown

    // Use directly as a component return value
    function Markdown({ text }: { text: string }) {
      return Bun.markdown.react(text);
    }
    
    // Server-side rendering
    import { renderToString } from "react-dom/server";
    const html = renderToString(Bun.markdown.react("# Hello **world**"));
    
    // Custom components receive element props
    function Code({ language, children }: { language?: string; children: React.ReactNode }) {
      return <pre data-language={language}><code>{children}</code></pre>;
    }
    function Link({ href, children }: { href: string; children: React.ReactNode }) {
      return <a href={href} target="_blank">{children}</a>;
    }
    const el = Bun.markdown.react(text, { pre: Code, a: Link });
    
    // For React 18 and older
    const el18 = Bun.markdown.react(text, undefined, { reactVersion: 18 });
    
  • function render(
    input: string | ArrayBufferLike | TypedArray<ArrayBufferLike> | DataView<ArrayBuffer>,
    callbacks?: RenderCallbacks,
    options?: Options
    ): string;

    Render markdown with custom JavaScript callbacks for each element.

    Each callback receives the accumulated children as a string and optional metadata, and returns a string. Return null or undefined to omit an element. If no callback is registered, children pass through unchanged.

    Parser options are passed as a separate third argument.

    @param input

    The markdown string to render

    @param callbacks

    Callbacks for each element type

    @param options

    Parser options

    @returns

    The accumulated string output

    // Custom HTML with classes
    const html = Bun.markdown.render("# Title\n\nHello **world**", {
      heading: (children, { level }) => `<h${level} class="title">${children}</h${level}>`,
      paragraph: (children) => `<p>${children}</p>`,
      strong: (children) => `<b>${children}</b>`,
    });
    
    // ANSI terminal output
    const ansi = Bun.markdown.render("# Hello\n\n**bold**", {
      heading: (children) => `\x1b[1;4m${children}\x1b[0m\n`,
      paragraph: (children) => children + "\n",
      strong: (children) => `\x1b[1m${children}\x1b[22m`,
    });
    
    // With parser options as third argument
    const text = Bun.markdown.render("Visit www.example.com", {
      link: (children, { href }) => `[${children}](${href})`,
      paragraph: (children) => children,
    }, { autolinks: true });