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

  • interface ListItemProps

    • checked?: boolean

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

    • children: unknown[]
  • interface ListMeta

    Meta passed to the list callback.

    • 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.checked is set for task list items (- [x] / - [ ]). Only passed 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 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 });