markdown-to-whatsapp について
markdown-to-whatsappは、MarkdownをWhatsApp向け書式に変換するウェブツール、npmライブラリ、コマンドラインツール、MCPサーバーです。表は設定した等幅バブル幅に合わせて整形され、必要に応じてリスト形式になります。
主な機能
- 01WhatsApp向けMarkdown書式への変換
- 02指定したバブル幅に合わせた表の整形
- 03表とリストのレイアウト選択
- 04WhatsAppバブル内でのメッセージプレビュー
- 05ライブラリ、コマンドライン、ウェブでの利用
活用シーン
- 01WhatsApp送信用の書式付きメモを作成
- 02Markdown表をスマートフォンの幅に調整
- 03ファイルや標準入力のMarkdownを変換
- 04共有前にメッセージの折り返しを確認
MCP 対応
AgentがMarkdownからWhatsApp形式への変換に使えるMCPサーバーを提供します。README抜粋にはMCPツールや設定方法の説明がありません。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
1掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| markdown | string | はい | 変換する Markdown テキスト |
| monoWidth | integer | いいえ | 読者の WhatsApp の吹き出しで1行に収まる等幅文字数。360 px のスマートフォンでは約26文字(デフォルトは26)。テーブルはこの幅に収まるように描画されます。 |
| listLayout | enum | いいえ | テーブルをリストとして表示する方法:rows(行ごとに1グループ)、columns(比較マトリクス向けに列ごとに1グループ)、pairs(2列のみ。「key: value」形式のプレーンな行)。auto はヘッダーから推測します。デフォルトは auto。auto | rows | columns | pairs |
| tableFormat | enum | いいえ | auto:monoWidth に収まる場合はテーブルを描画し、それ以外は箇条書きにします。list:常に箇条書きにします。デフォルトは auto。auto | list |
| rowSeparator | boolean | いいえ | テーブルの行間に罫線を描画します。行が折り返される場合は常に描画します。デフォルトは false。 |
| headingEmojis | boolean | いいえ | 見出しの太字テキストの前に、レベルを示す絵文字(📌 🟠 🟡 …)を付けます。デフォルトは true。 |
詳細
Markdown から WhatsApp への変換ツール
標準的な Markdown を WhatsApp の書式構文に変換します。Web ページ、npm ライブラリ、コマンドラインツール、またはエージェント向けの MCP サーバーとして利用できます。
npm i markdown-to-whatsapp · npx markdown-to-whatsapp mcp
このツールの目的
WhatsApp では、テキストの書式設定に標準とは異なる構文(例:*bold*、_italic_、~strikethrough~)を使用します。標準的な Markdown に似ていますが、同じではありません。
このツールを使うと、テキストエディターや Google Docs などの Markdown ソースから、WhatsApp が求める形式に簡単に変換でき、手作業で修正する必要がなくなります。
変換処理はすべて JavaScript を使ってブラウザー内でローカルに実行され、パーサーもページに含まれています。データがサーバーに送信されることはありません。ページ外部への唯一のリクエストは、フォントの取得です。
対応している変換
このスクリプトは、適切な AST ベースの解析に marked ライブラリを使用し、以下を処理します。
テキストスタイル
- 太字:
**text**→*text* - 斜体:
*text*または_text_→_text_ - 取り消し線:
~~text~~→~text~ - インラインコード:
`code`→`code` - 太字+斜体:
***text***→_*text*_(両方のスタイルを保持)
見出し
見出しは、レベルごとに異なる絵文字を先頭に付けた太字テキストに変換されます。
# H1→*📌 H1*## H2→*🟠 H2*### H3→*🟡 H3*- 以下同様...
UI(見出し · 絵文字)で絵文字をオフにすると、絵文字なしの *Title* になります。
リスト
- 順序なしリスト:
*を先頭に付け、ネストしたレベルには◦を使用します- レベル 1:
* Item - レベル 2:
* ◦ Item - レベル 3:
* ◦ ◦ Item
- レベル 1:
- 順序付きリスト: 番号を維持し、ネストしたレベルには
◦を付けます1. A/◦ 1. A1/◦ ◦ 1. A1a/2. B
- タスクリスト:
- [x]→☑、- [ ]→☐。順序付きリスト内でも使用できます(1. ☑ done) - 複数段落の項目: 1 つの項目に複数の段落がある場合、1 行にまとめます
- 項目内のブロックコンテンツ: コードブロック、引用、ネストしたリストは、項目の下の独立した行に出力されます
吹き出しの幅
WhatsApp の吹き出しには、1 行に固定数の等幅文字を表示できます。デフォルトでは、幅 360 px のスマートフォンで約 26 文字です。自分宛てにコードブロックを送って、どこで折り返されるかを数え、その数値をバーの 幅 に設定してください。隣の ? にも同じ説明があります。このフィールドには 10~80 を指定できます。この範囲外の幅のスマートフォンはありません。
この数値はスマートフォンの特性であり、個々の表に依存するものではありません。そのため、すべての等幅コンテンツに適用されます。表は幅の範囲内に収まるよう調整され、プレビューではすべてのコードブロックが指定した幅で描画されます。受信者側の WhatsApp で折り返される位置と同じ場所で折り返されます。
表
表は 2 種類のスタイル のいずれかで描画されます。ドキュメント全体、または表ごとに UI で選択できます。
-
自動(デフォルト):等幅ブロック内に罫線付きの表を描画します。必要な幅で表示し、吹き出しの幅を超えることはありません。罫線を描けない場合は、箇条書きリストになります。
+--------+-------------+ | Name | Description | +========+=============+ | Value | Details | +--------+-------------+ -
リスト:常に箇条書きリストになります。
リストのレイアウト
リストでは、セルを 3 通りの方法でグループ化できます。コンバーターはヘッダーと太字のセルから推測しますが、表ごとに推測結果を変更できます(レイアウト:自動 · 行 · 列 · ペア)。
-
ペア — ヘッダーの内容を問わず、2 列の場合です。各行が
key: valueの形式になります。ほとんどの表では、各行にヘッダーを明記するよりも、Italy: Romeのようにするほうが読みやすくなります。* *CPU:* Intel Xeon * *RAM:* 64 GB * *Storage:* 1 TB SSD -
列 — 先頭のヘッダーが空欄またはプロパティ(「Feature」「Spec」「Parameter」など)を示す、あるいは先頭列が太字になっている 3 列以上の表です。比較マトリックスであり、比較対象が列になっているため、各列がグループになります。
* *Proxmox* * ◦ _Kernel:_ KVM * ◦ _License:_ AGPL v3 * *ESXi* * ◦ _Kernel:_ VMkernel * ◦ _License:_ Proprietary -
行 — それ以外の場合です。各行が 1 つのグループとなり、先頭のセルがラベルになります。
* *Product:* Laptop * ◦ _Price:_ $999 * ◦ _Stock:_ 50 * *Product:* Smartphone * ◦ _Price:_ $599 * ◦ _Stock:_ 100
プロパティを示す語は 11 言語で単語ごとに照合されます(「Species」は「spec」として認識されません)。対応言語は、英語、イタリア語、スペイン語、フランス語、ポルトガル語、ドイツ語、ロシア語、アラビア語、ヒンディー語、ベンガル語、インドネシア語です。ペアとして認識されるには列がちょうど 2 つ必要です。列数の多い表に対して指定すると、行として表示されます。
ボックスの表示が変わる仕組み
ボックスはどの幅でもそのまま描画されるわけではありません。monoWidth に収まるまで表示が変わり、どの形式も収まらない場合はリストになります。吹き出しより広い表を指定する方法はありません。
- 完全なボックス。まず右側から、次に左側から、列ごとに余白を取り除きます。
- コンパクトな枠線なしスタイル。同様に、余白を段階的に取り除きます。
Head1|Head2 |Head-N ------+------------+------ A |BBBBBBBBBBBB|C - 折り返しボックス。まず完全な枠線付き、次にコンパクトな形式になります。各列には少なくとも最長の単語が収まる幅が割り当てられ、残りの幅は列ごとに比例配分され、セル内のテキストは単語単位で折り返されます。行の高さに上限はなく、必要に応じて広がります。また、折り返された行どうしがつながってしまわないよう、行間には必ず罫線が引かれます。セルの内容は行の上端に揃います。
+---------+--------------+ | Feature | Notes here | +=========+==============+ | Alpha | short note | +---------+--------------+ | Beta | a slightly | | | longer note | +---------+--------------+ - 箇条書きリスト。最長の単語すら収まらない場合(長い URL や、26 文字幅で 5 列の場合など)に使われます。
折り返しで縦長になったボックスとリストのどちらが読みやすいかは、プレビューで判断できます。その表のパネルで、リストに切り替えられます。ボックス形式がまったく収まらない表は、パネルにその旨が表示され、何も変わらないスタイルの代わりにリストレイアウトが選べます。
表の追加の動作
- 列幅は表示セル数で測定されるため、絵文字や CJK テキストも揃います(
✅と日本語はそれぞれ 2 列として数えられます)。ただし、スマートフォンの表示幅が許す範囲に限られます。これらのグリフもフォールバックフォントから表示されるため、ASCII の枠線とは異なり、配置はできる限り揃える形になります。 - 列の配置(
:---、:---:、---:)は、ボックス形式とコンパクト形式で反映されます。 - ヘッダーだけの表は、空の本文や二重の枠線を付けずに表示されます。
- セル内の
<br>はスペースになり、エスケープされた\|は¦になって、列が余分に増えるのを防ぎます。 - 枠線には意図的にプレーンな ASCII(
+-|=)を使っています。WhatsApp の等幅フォントには罫線用のグリフがありません。スマートフォンでは、─や┌は使用中のフォールバックフォントから表示され、そのフォントによって幅が異なります。そのため、26 個の罫線文字が 2 行に折り返されても、隣のテキスト行は折り返されないことがあります。等幅フォントで幅が保証される文字は+-|だけです。エスケープされたパイプが¦になるのも同じ理由で、これはàと同じフォントの Latin-1 文字です。 - 行区切り(デフォルトではオフ)は、すべてのボックス形式とコンパクト形式で本文の行間に罫線を引きます。折り返し形式の表では常に罫線が引かれます。
- スタイル、行区切り、リストレイアウトは表ごとに設定できます。プレビューで表にカーソルを合わせると、その表専用のコントロールが表示されます。コントロールはドキュメントのデフォルト設定を初期値として、その表にのみ適用されます。また、該当するものだけが表示されます(ボックスでは行区切り、リストではレイアウト)。幅は設定できません。吹き出しは 1 つで、すべての表で共通です。表に個別の設定がある場合は破線のマークが表示されます。パネル上部のコントロールは意図的にその設定に手を加えず、「リセット」ボタンを押すとパネル上部の設定に戻ります。オーバーライドは表のヘッダーテキストに関連付けられるため、表を上に追加したり削除したりしても、適用先は変わりません。リスト項目や引用ブロック内にネストされた表は、常にドキュメントのデフォルト設定に従います。
コードブロック
フェンス付きブロックとインデント付きブロックは、そのまま WhatsApp に渡されます。コード内の改行はレイアウトではなく内容なので、コンバーターは折り返しやインデントの変更を行いません。WhatsApp は長い行を単語の途中でも自動的に折り返し、チャットの吹き出しには横スクロールがありません。そのため、プレビューではスクロールする代わりに monoWidth で折り返しを再現し、受信者に表示される改行位置を正確に示します。
その他の要素
- リンク:
[text](url)→text (url)。自動リンク、<https://x>、[url](url)、<[email protected]>は、重複やmailto:の漏れなく、URL またはアドレスのみで表示されます - HTML エンティティ: 10 進数および 16 進数の参照と、一般的な名前付き参照(Latin-1 の文字、句読点、記号)に対応しています(
café→café、©→©、A→A)。あまり一般的でない参照(ギリシャ文字、数学記号)はそのまま残ります - インライン HTML:
<b>/<strong>→*、<i>/<em>→_、<s>/<del>→~、<code>→`、<br>→ 改行。コメントとその他のタグは削除されます - HTML ブロック: タグを削除し、ブロックの境界を改行に変換して、エンティティをデコードします
- 引用ブロック:
>の接頭辞を保持し、入れ子(> > nested)に対応します - コードブロック: トリプルバッククォートを付けて保持します。内容に含まれるトリプルバッククォートは
ˋˋˋに置き換え、ブロックが途中で閉じないようにします - 水平線:
---→─────────────── - エスケープ文字: Unicode の類似文字(
∗、_、∼)を使用し、WhatsApp に書式として解釈されないようにします
WhatsApp 固有の処理
- 単語の途中の書式設定は無視されます:
super**bold**ly→superboldly(WhatsApp は単語の途中の書式設定に対応していません) - 句読点は有効な境界です:
**Name**: value→*Name*: value。(**x**)や**end**.も同様です
使い方
- ウェブページを開きます: https://drsound.github.io/markdown-to-whatsapp/
- 左側のパネルに
.mdファイルを貼り付ける、入力する、またはドロップします。「例を試す」を選ぶと、サンプルメッセージが入力されます。 - 右側のパネルには、受信者に表示されるとおりのメッセージが WhatsApp の吹き出し内に 表示されます。「raw syntax を表示」すると、コピーされるテキストが表示されます。2 つのパネルは 一緒にスクロール し、ポインターの下にあるほうに合わせて動きます。また、入力中はプレビューがカーソルに追従します。
- 「WhatsApp 用にコピー」、または 「WhatsApp で共有」 を選ぶと、メッセージが入力された状態で
wa.meからチャットを開きます。非常に長いメッセージはリンクに収まりません。ブラウザーは数千文字を超える URL を切り詰めるため、「共有」は実行せず、代わりにコピーするよう案内します。
インターフェースは オペレーティングシステムのライトテーマまたはダークテーマ に従います。ヘッダーの切り替えで上書きでき、その設定は記憶されます。オプションバーにはコンテンツの種類ごとにセクションがあり、それぞれテキストに該当する内容が含まれる場合にのみ表示されます。吹き出し(テーブルまたはコードブロックがある場合の幅)、テーブル(スタイルと区切り文字)、見出し(絵文字の接頭辞)が用意されています。別の設定によって不要になるコントロール(リストスタイルでの区切り文字や、等幅表示する内容がない場合の幅)は削除せず、その場で薄く表示します。これにより、バーの形状が保たれます。オプションはテーマとともに localStorage に保存されます。テーブルごとの選択は保存されません。変換対象のテキストに紐づくためです。
コード、シェル、またはエージェントから使用する
同じコンバーターが npm で markdown-to-whatsapp として公開されています(Node 20 以降)。オプションは上記の説明と同じ名前・デフォルト値で、すべてこのセクションの末尾に記載されています。
ライブラリ
npm install markdown-to-whatsapp
import { convertTextToWhatsapp, convertToBlocks } from 'markdown-to-whatsapp';
convertTextToWhatsapp('# Hi **there**');
// → '*📌 Hi there*'
convertTextToWhatsapp(markdown, { monoWidth: 30, tableFormat: 'auto', headingEmojis: false });
// The same conversion with the blocks kept apart: each has the source `line` it starts on,
// and each table its `key`, `columns`, `fitsBox`, `asList` and `listLayout`
const { text, blocks } = convertToBlocks(markdown, { monoWidth: 30 });
コマンドライン
npx markdown-to-whatsapp notes.md # a file…
cat notes.md | npx markdown-to-whatsapp # …or stdin
npx markdown-to-whatsapp notes.md --width 32 --tables list --no-emoji
npx markdown-to-whatsapp notes.md --json # the blocks, for scripting
npx markdown-to-whatsapp --help
--width(10~80)、--tables auto|list、--layout auto|rows|columns|pairs、--separator、--no-emoji、--json に加え、-h, --help と -v, --version を指定できます。出力は stdout に送られます。無効なオプションを指定すると理由が stderr に出力され、終了コード 2 で終了します。
MCP サーバー
このパッケージは、stdio 経由でModel Context Protocolサーバーとして実行されるため、エージェントがテキストを自分で変換できます。これは表で重要です。26 文字幅の吹き出しに列が収まるかを数えるのはモデルが苦手とする作業ですが、このツールなら正確に処理できます。
claude mcp add markdown-to-whatsapp -- npx -y markdown-to-whatsapp mcp
または、JSON 設定を使用する Claude Desktop やその他のクライアントの場合:
{
"mcpServers": {
"markdown-to-whatsapp": {
"command": "npx",
"args": ["-y", "markdown-to-whatsapp", "mcp"]
}
}
}
このサーバーは、markdown と、任意の monoWidth、tableFormat、listLayout、rowSeparator、headingEmojis を受け取るツール convert_markdown_to_whatsapp を 1 つ公開します。テキストはツールのコンテンツとして返され、構造化された結果には text と tables が含まれます。tables は各表につき 1 つのエントリーを持ち、key、columns、fitsBox、asList、listLayout が含まれるため、エージェントはどの表がボックスになり、どの表がリストになったかを判別できます。このツールは読み取り専用で、冪等です。
オプション
オプションは、tableFormat(auto | list)、monoWidth、rowSeparator、headingEmojis、listLayout(auto | rows | columns | pairs)、および tableOverrides です。tableOverrides は、ドキュメント内の表の位置をインデックスにした配列、または表の key(ヘッダーテキストを | で連結したもの。ヘッダーが重複する場合は #2、#3…を付加)をキーにしたオブジェクトです。各エントリーは、その表に限り、他のオプションを上書きします。ページで表ごとに設定できるのは listLayout のみです。
以前の名前も入力時には引き続き使用できます。tableThreshold は monoWidth に、ascii / always は tableFormat に対応します(ascii は吹き出しより幅の広いボックスを描画しなかったため、auto に対応します)。以前の名前と新しい名前の両方が指定された場合は、新しい名前が優先され、以前の名前は破棄されます。Unicode のボックス描画形式を選択していた borderStyle は、受け付けますが無視されます。
開発
テストの実行
Node 20 以降を使用し、リポジトリのルートから実行します。
npm install
npm test
テストスイートでは、ファイルベースのテストを使用します。
tests/inputs/*.md- Markdown 入力ファイルtests/inputs/*.json- フィクスチャごとの任意のコンバーターオプション(例:{ "monoWidth": 40 })tests/expected/*.txt- 期待される WhatsApp 出力
これに加えて、いくつかの不変条件もテストします。ベンダーに含まれるパーサーがインストール済みのものと一致すること、convertToBlocks が正しいソース行を報告すること、パッケージのエントリーポイントがページスクリプトであることです。
テストは、プッシュおよびプルリクエストのたびに CI でも実行されます(.github/workflows/test.yml)。
プロジェクト構成
docs/converter.js- コンバーター本体です。純粋な ES モジュールで、DOM に依存せず、オプションはパラメーターとして渡されます。ページがインポートするスクリプトであると同時に、npm パッケージのエントリーポイント(exports["."])でもあるため、コピーは 1 つだけで、ビルド手順もありません。convertTextToWhatsapp(markdown, options)、convertToBlocks(markdown, options)(トップレベルのブロックを分離し、それぞれに元となる表のタグを付ける、同じ変換処理です。表ごとのオプションはこれを基にしています)、および UI が該当する場合にのみオプションを表示するために使うmdContainsTable/mdContainsHeading/mdContainsCodeクエリを公開します。convertToBlocksの各ブロックは開始位置のソースlineを報告します。これにより、2 つのパネルのスクロールが同期します。また、各表ブロックはkey、columns、fitsBox(ボックス表示が可能か)、asList(実際に出力された形式)、listLayoutも報告するため、インターフェースは残りの選択肢だけを提示できます。docs/ui.js- ページの動作設定です。テーマ、コンテキストに応じたオプション、WhatsApp プレビュー、パネル間のスクロール同期、コピー、共有を扱います。docs/index.html、docs/style.css- マークアップと手書きのスタイルシートです(CSS フレームワークは使用していません)。docs/vendor/- marked の ES ビルドです。npm run vendorによりnode_modulesからコピーされ、ページの import map がmarkedをこのファイルに解決します。bin/markdown-to-whatsapp.js- コマンドラインツールです。bin/mcp.jsはmcpで起動する MCP サーバーで、変換時にプロトコル SDK が読み込まれないよう、そのときにのみ読み込まれます。scripts/vendor.js-markedの ES ビルドをdocs/vendor/にコピーします(npm run vendor)。tests/- フィクスチャとテストランナーです。
marked の依存関係
marked のバージョンは package.json で 18.0.10 に固定されており、ページが docs/vendor/ から読み込むコピーがこれと一致することをテストスイートで確認しています。そのため、ページ、パッケージ、テストで常に同じ方法で Markdown を解析できます。バージョンを上げるには、固定バージョンを変更し、npm install、npm run vendor、npm test を実行します。
公開
npm test
npm pack --dry-run # docs/converter.js, bin/, README, LICENSE — nothing else
npm publish
ローカル開発
cd docs
python3 -m http.server 8080
# Open http://localhost:8080
ライセンス
MIT。LICENSE ファイルを参照してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。
