BunでMarkdownをネイティブにパースする
unified、remark-parse、remark-rehype、rehype-stringifyを組み合わせてMarkdown文字列をHTMLに変換したことがある方なら、そのオーバーヘッドをご存知でしょう。Bun 1.3.8(2026年1月リリース)には、この一連の処理を単一のAPI呼び出しで置き換える組み込みMarkdownパーサーが搭載されています。インストール、インポート、プラグイン設定は一切不要です。
本記事では、新しいBun.markdown APIの機能、動作原理、そしてワークフローへの組み込み方について解説します。
要点
Bun.markdownは、Bunランタイムに組み込まれたネイティブMarkdownパーサーで、md4c CライブラリのZigポートによって駆動されます。html()メソッドは、外部ライブラリを必要とせず、単一の呼び出しでMarkdownをHTMLに変換します。render()は、各要素タイプに対するJavaScriptコールバックを通じて、カスタム出力形式(スタイル付きHTML、ANSI、プレーンテキスト)をサポートします。react()はReact要素を直接返し、Markdownコンテンツをコンポーネントツリーの一部としてレンダリングできます。- このAPIはまだ不安定版とマークされているため、Bunのバージョンを固定し、本番環境にデプロイする前に出力を検証してください。
Bun Markdownパーサーとは?
Bun.markdownは、Bunランタイムに直接組み込まれたネイティブMarkdownパーサーです。CommonMark仕様に準拠しており、Qtなどのパフォーマンス重視の環境で使用されているmd4c CライブラリのZigポートとして実装されています。
JavaScriptではなくコンパイル済みのZigコードとして実行されるため、unifiedやremarkなどのJavaScriptベースのパース処理のオーバーヘッドを回避できます。複数のパッケージを連鎖させる代わりに、BunはMarkdown処理のための単一のランタイムAPIを提供します。
注意:
Bun.markdownAPIは現在、公式Bunドキュメントで**不安定版(unstable)**とマークされています。このインターフェースは現時点で動作しますが、特定のオプションやメソッドシグネチャは将来のBunリリースで変更される可能性があります。本番環境でアップグレードする前に、Bunリリースノートを確認してください。
BunでMarkdownをHTMLに変換:html()メソッド
最もシンプルなユースケース — MarkdownをHTML文字列に変換する — は、セットアップ不要です:
const html = Bun.markdown.html("# Hello **world**")
// "<h1>Hello <strong>world</strong></h1>\n"
第2引数としてオプションを渡すことができます。headingsオプションは、ドキュメントサイトや目次生成に便利です:
const html = Bun.markdown.html("## Getting Started", {
headings: { ids: true }
})
// '<h2 id="getting-started">Getting Started</h2>\n'
GitHub Flavored Markdown(GFM)拡張機能はデフォルトで有効になっており、テーブル、取り消し線(~~text~~)、タスクリスト(- [x] done)、寛容な自動リンクが含まれます。wikiLinks、latexMath、見出しの自動リンクなどの追加オプションもサポートされています。
Bun.markdown.render()によるカスタムレンダリング
標準的なHTMLではない出力 — スタイル付きマークアップ、ANSIターミナル出力、プレーンテキスト — が必要な場合、render()は各要素タイプに対するJavaScriptコールバックを受け付けます:
// 要素にCSSクラスを追加
const html = Bun.markdown.render("# Title\n\nHello **world**", {
heading: (children, { level }) => `<h${level} class="title">${children}</h${level}>`,
paragraph: (children) => `<p class="body">${children}</p>`,
strong: (children) => `<b>${children}</b>`,
})
// すべての書式をプレーンテキストに削除
const plain = Bun.markdown.render("# Title\n\n**bold** text", {
heading: (children) => children + "\n",
strong: (children) => children,
paragraph: (children) => children + "\n",
})
// nullを返すことで特定の要素を完全に省略
const noImages = Bun.markdown.render("# Title\n\n", {
image: () => null,
heading: (children) => `<h1>${children}</h1>`,
})
これにより、render()はCLIツール、メール生成、またはHTMLがターゲット形式ではないあらゆるパイプラインで有用です。
Discover how at OpenReplay.com.
react()によるBun Markdown Reactレンダリング
Bun.markdown.react()は、コンポーネントツリーで直接使用できるReact要素を返します:
function Markdown({ text }: { text: string }) {
return Bun.markdown.react(text)
}
// Markdown要素をカスタムコンポーネントにマッピング
const element = Bun.markdown.react("# Hello", {
h1: ({ children }) => <h1 className="page-title">{children}</h1>,
})
// サーバーサイドレンダリングでも動作
import { renderToString } from "react-dom/server"
const html = renderToString(Bun.markdown.react("# Hello **world**"))
React 18以前を使用している場合は、互換性オプションを渡すことができます:
Bun.markdown.react(markdownText, undefined, { reactVersion: 18 })
Bun.markdown vs. Remarkの使い分け
| シナリオ | 推奨 |
|---|---|
| 基本的なMarkdown-to-HTML変換 | Bun.markdown.html() |
| カスタム出力(ANSI、スタイル付きHTML) | Bun.markdown.render() |
| Reactコンポーネントツリー | Bun.markdown.react() |
| シンタックスハイライト、脚注、複雑なプラグイン | unified/remarkを継続使用 |
まとめ
Bun 1.3.8以降を既に実行している場合、Bun.markdownはグローバルに利用可能です — インストールは不要です。シンプルなコンテンツパイプラインにはBun.markdown.html()から始め、出力をより細かく制御する必要がある場合はrender()またはreact()を使用してください。
このAPIはまだ不安定版とマークされているため、Bunのバージョンを固定し、本番環境にデプロイする前にレンダリング出力を期待されるHTMLと照合してテストしてください。
よくある質問
いいえ。Bun.markdownは標準的なMarkdown-to-HTML変換を処理しますが、組み込みのシンタックスハイライトは含まれていません。コードのハイライトには、ShikiやPrismなどのライブラリでHTML出力を後処理するか、専用のハイライトプラグインを使用したunified/remarkパイプラインを使用する必要があります。
いいえ。Bun.markdownはBunランタイムに組み込まれたネイティブAPIであり、Node.jsでは利用できません。プロジェクトがNode上で実行される場合は、unified、remark、markdown-itなどのライブラリを引き続き使用してMarkdownをパースする必要があります。
Bun.markdownには組み込みのHTMLサニタイゼーションは含まれていません。ユーザーが送信したMarkdownを処理する場合は、クロスサイトスクリプティングの問題を防ぐために、生成されたHTMLをブラウザでレンダリングする前にDOMPurifyやsanitize-htmlなどのサニタイゼーションライブラリを通してください。
いいえ。Bun.markdownはGitHub Flavored Markdown拡張機能を備えたCommonMarkを実装しています。MDX、カスタムディレクティブ、またはunifiedとremarkで利用可能なプラグインエコシステムはサポートしていません。これらのユースケースには、remarkベースのパイプラインが引き続き適切な選択肢です。
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.