markdown-to-whatsapp
Markdown to WhatsApp Converter
将标准 Markdown 转换为 WhatsApp 的格式化语法——可作为网页、npm 库、命令行工具或面向智能体的 MCP 服务器使用。
npm i markdown-to-whatsapp · npx markdown-to-whatsapp mcp

本工具的用途
WhatsApp 在文本格式化上使用非标准语法(例如 *bold*、_italic_、~strikethrough~)。这与标准 Markdown 相似,但并不完全相同。
本工具提供了一种简单的方式,将来自 Markdown 来源(文本编辑器、Google Docs 等)的文本转换为 WhatsApp 所需的格式,省去了手动修正的麻烦。
整个转换过程完全在浏览器本地借助 JavaScript 完成,解析器随页面一同提供。不会向服务器发送任何数据——页面发出的唯一请求是获取字体。
Related MCP server: AI Group Markdown to Word MCP Server
支持的转换
脚本使用 marked 库进行基于 AST 的正确解析,可处理:
文本样式
加粗:
**text**→*text*斜体:
*text*或_text_→_text_删除线:
~~text~~→~text~行内代码:
`code`→`code`粗体+斜体:
***text***→_*text*_(保留两种样式)
标题
标题会转换为带分级 emoji 前缀的粗体文本:
# H1→*📌 H1*## H2→*🟠 H2*### H3→*🟡 H3*依此类推……
可以在界面中关闭 emoji 前缀(标题 · Emoji 选项),此时只保留纯文本 *Title*。
列表
无序列表: 使用
*前缀,嵌套层级追加◦第 1 层:
* Item第 2 层:
* ◦ Item第 3 层:
* ◦ ◦ Item
有序列表: 保留数字编号,用
◦标记嵌套层级1. A/◦ 1. A/◦ ◦ 1. A/2. B
任务列表:
- [x]→☑,- [ ]→☐,也支持有序列表(1. ☑ done)松散的项目: 同一列表项中的多个段落会合并到一行
列表项中的块内容: 代码块、引用块和嵌套列表会在该列表项下方单独成行输出
气泡宽度
WhatsApp 气泡在手机上能容纳的等宽字符数是固定的——360 px 的屏幕上大约 26 个,这也是默认值。要测量你的手机,可以给自己发一段代码块,数它在哪个位置断电,然后在工具栏中把 宽度 设置为该数值(旁边的 ? 也说明了这一点)。该字段接受 10 至 80,任何手机都不超出这个范围。
这个数字是手机自身的属性,不是任何一张表格的属性,因此它统治所有等宽内容:表格会不断降级以保持在该宽度之内,预览也会精确地按 monoWidth 绘制每个代码块,换行位置与接收方 WhatsApp 实际一致。
表格
表格按 两种样式 之一渲染,可在界面中直接对整篇文档或某一张表格单独选择:
自动(默认):等宽块中绘制出的表格,宽度按需取,且绝不会超过气泡——一旦完全画不出方框,就退化为项目符号列表。
+--------+-------------+ | Name | Description | +========+=============+ | Value | Details | +--------+-------------+列表:始终使用项目符号列表。
列表布局
列表支持三种单元格分组方式。转换器会从表头及粗体单元格中 自动推测,该推测也可按表格单独调整(布局:自动 · 行 · 列 · 对):
对(对) — 恰好两列(与表头无关):每一行都输出为一条
key: value。在绝大多数表格中,在每行上拼写表头,阅读效果都远不如Italy: Rome。* *CPU:* Intel Xeon * *RAM:* 64 GB * *Storage:* 1 TB SSD列(Columns) — 三列及以上,它的首列表头为空或命名一个属性("Feature"、"Spec"、"Parameter"…),或者它的第一列是粗体:这是一个比较矩阵,被比较的是各列,因此每列成为一组。
* *Proxmox* * ◦ _Kernel:_ KVM * ◦ _License:_ AGPL v3 * *ESXi* * ◦ _Kernel:_ VMkernel * ◦ _License:_ Proprietary行(Rows) — 其他所有情况:每行一组,并以该行的第一个作为组的标签。
* *Product:* Laptop * ◦ _Price:_ $999 * ◦ _Stock:_ 50 * *Product:* Smartphone * ◦ _Price:_ $599 * ◦ _Stock:_ 100
这些属性词(Property)按单词一对一词匹配("Species" 不会算作 "spec"),支持 11 种语言:英语、意大利语、西班牙语、法语、葡萄牙语、德语、俄语、阿拉伯语、印度地语、孟加拉语和印度尼西亚语。Pairs 需要恰好两列;若对一张更宽的表格请求 Pair 布局,则按行处理。
方框的低级方式
方框并不是在任何宽度之下都会绘制:它不断逐级下降,直到恰好占满 monoWidth,而当完全没有一种方案可行时,它索性成为列表。没有办法要求一张比气泡更宽的表格。
完整方框,从最右到最左,逐列移除留白。
紧凑无边框 样式,同样逐步移除留白:
Head1|Head2 |Head-N ------+------------+------ A |BBBBBBBBBBBB|C换行方框,先完整边框,后无边框:每一列至少得到自己最长单词的宽度,剩余的宽度按比例分配,单元格运转换行。行高可以无限增加——没有限制——而且在两行之间总是绘有一条交叉线,否则两行自动换行的内容会粘连。单元格对齐到所在行的顶部。
+---------+--------------+ | Feature | Notes here | +=========+==============+ | Alpha | short note | +---------+--------------+ | Beta | a slightly | | | longer note | +---------+--------------+项目符号列表,当最长单词还是放不下时(如超长 URL、26 个字符宽度内五列……)。
很长的换行方框是否真的比列表更好,这个判断由预览帮你在直接完成:该表格自带的小面板会把它切换为列表。而当一张表格完全找不到方框方案时,面板会提醒说明,并直接提供列表布局,而不是一个根本无法起作用的样式。
表格的其他行为
列宽按显示的单元格计算,从而 emoji 文本对齐(
✅、日本語占两列)——不过手机能力也重要:这些字形同样来自后备字体,因此对齐只能尽力而为,不像 ASCII 边框那样可以精确预测。表格对齐(
:---、:---:``、---:`) 在方框样式、紧凑样式中均生效。只含表头的表格,不会渲染出空表格主体或无谓重复的边框。
单元格内的
<br>会被替换为一个空格,转义的\|会被换成¦,这样它就不能再假装多出一列。边框使用纯 ASCII 字符(
+|=),这出自设计的需要。WhatsApp 的等宽字体并没有画线的象形字:"数字配套字体把─、┌从替换字体中取来,因此宽度随字体变化而不可以任意,一条 26 个─的水平线,可能在旁边文本行不折行的情况下自己换到下一行。+-|是等宽字体真正保证宽度的字符,这也是为什么该\|还原为¦,因为¦和à一样都在 Latin-1 字符集,属于真正的字体区。行分隔线(默认关闭)在表格框和紧凑方式下,在行间绘制一条规则;而在换行表格中则无条件绘制。
样式、行分隔线 和 列表布局 均可以按表格单独设置:在预览中悬停一张表格会出现它自身的控件,这些控件以整篇的默认值为起点,但只对该表格覆盖默认值,并只展示将它们仍然适用的(分隔线在框、布局在列表)。宽度不在其中——只有一个气泡,对每张卡片都一样。一个带自定义设置的表格会保持一条虚线标记,因为面板顶部的控件会下意识避开它,而“重置”按钮则把它的设置还原好归还给顶部面板。这些覆盖随表格的题头文本一并保存,因此在上方增删表格都不会移动它们。放在列表项或引用块内部的表格,永远跟随整篇默认值。
代码块
Chatter和缩进的代码块会原样送到 WhatsApp:转换器绝不会对它们重新换行或重新缩进,因为代码里的换行是内容而不是排版。WhatsApp 自动处理超长行并允许任意单词点中断,而聊天气泡没有横向滚动,因此预览也以 monoWidth 模拟这种断行并如期展示接收者实际看到断行的位置。
其他元素
链接:
[text](url)→text (url);自主链接(autolink)如<https://x>、[url](url)及<me@be>邮箱地址>,只显示裸链接或邮箱地址(不重复、不出现mailto:)HTML 实体: 十进制与十六进制引用以及常见的命名实体——Latin-1 字母、字符和符号(
café→café,©→©,A→A),而生僻实体(希腊文、数学等)按原样保留。行内 HTML:
<b>/<strong>→*,<i>/<em>→_,<s>/<del>→~,<code>->`,<br>→ 换行;注释及其他标签被剥离HTML 块: 去除标签,按块边界转换换行,解码实体
引用块:
>``>保留,支持嵌套(> >嵌入在句子中)代码块: 保留三重反引号;如果内容中还出现了三重反引号,会替换为
ˋˋˋ以防止提前关闭代码块水平线:
---→───────────────转义字符: 使用与自身等价似的 Unicode 字符(
∗、_、∼),避免 WhatsApp 把它当作格式符号
特殊于 WhatsApp 的处理
单词中间的格式被忽略:
super**bold**ly→superboldly(WhatsApp 不支持词中格式化)标点可以作为边界:
**Name**: value→*Name*: value;遇到(之类也会生效,如(**(x**))和**end**.
使用方法
将
.md贴入、键入或拖放 到left面板。“试一个示例”可将该表单演示文本。rename面板以 WhatsApp 气泡形式 显示消息,展示收件人最终的效果;“查看原始语法”会显示将要复制的文本。两个板 同步滚动——鼠标所在的那个板作为驱动端——并在编辑时一边输入一边定位到光标处。
“复制到 WhatsApp” 或 “分享到 WhatsApp” 通过
wa.me打开聊天,并预置完整消息。太长的消息无法放进链接——浏览器会在几千字后切断 URL,因此此时“分享”选项会消失,只提示您复制。
界面使用操作系统的浅色或深色主题,页头的切换按钮可覆盖并记住你的配置。选项栏里按类型分组,只有当文档中包含该类内容时才显示:Bubble(气泡宽度,当出现表格或换行时)、Tables(样式和分隔线)、Headings(标题 Emoji 前缀)。某个控件被其它设置逻辑所覆盖而没有意义——像 List 下的分隔线、没有等宽内需要绘制时的宽度——都会原地置灰而不删除,以此让工具栏的整体维持不变。这些选项与主题一起保存在记忆的 localStorage 中。按表格所做的选择本身并不存储,因为它属于被转换的那段文本。
在代码、Shell、智能体中使用
同一个转换器也以 markdown-to-whatsapp 这个 npm 包发布(需要 Node 20 或更高)。选项与上文完全相同,名称、默认值亦同,完整列表见本节末。
作为库使用
npm install markdown-to-whatsapp作为 CommonISJ 模块:
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)、--auto(表格或列表)、--layout auto|rows|columns|pairs、--separator、--no-emoji、--json、以及 -h, --help 和 -v, --version,输出写到 stdout,未知选项会把原因写到 stderr 并退出码为 2。
MCP 服务器
该包可作为 Model Context Protocol 服务器运行在 stdio 之上,让智能体直接转换文本——这对表格非常关键:给 26 字符的气泡计算列数,是模型最容易错而本工具最可靠的地方。
claude mcp add markdown-to-whatsapp -- npx -y markdown-to-whatsapp mcp或者,在 Claude Desktop 及其他接受 JSON 配置的客户端中:
{
"mcpServers": {
"markdown-to-whatsapp": {
"command": "npx",
"args": ["-y", "markdown-to-whatsapp", "mcp"]
}
}
}它暴露了一个工具 convert_markdown_to_whatsapp,接收 markdown 以及可选的 monoWidth、tableFormat、listLayout、rowSeparator 和 headingEmojis。文本作为工具的内容返回,而结构化结果则将其携带为 text,并附带 tables:每个表格对应一个条目,包含 key、columns、fitsBox、asList 和 listLayout,因此代理可以区分哪些表格变成了方框,哪些变成了列表。该工具是只读且幂等的。
选项
选项包括 tableFormat(auto | list)、monoWidth、rowSeparator、headingEmojis、listLayout(auto | rows | columns | pairs)以及 tableOverrides —— 要么是一个按表格在文档中的位置索引的数组,要么是一个以表格的 key 为键的对象(键为表头文本用 | 连接,重复表头再追加 #2、#3…),每个条目仅对该表格覆盖其他任何选项。页面只在按表格设置时暴露 listLayout。
旧名称仍然可在输入中使用:tableThreshold 对应 monoWidth,ascii / always 对应 tableFormat(ascii 从未画出比气泡更宽的方框,因此映射到 auto)。当旧名称和新名称同时给出时,新名称优先,旧名称被丢弃。borderStyle 过去用于选择 Unicode 方框绘制,现在被接受但忽略。
开发
运行测试
Node 20 或更高版本,在仓库根目录:
npm install
npm test测试套件使用基于文件的测试:
tests/inputs/*.md- Markdown 输入文件tests/inputs/*.json- 可选的按 fixture 提供的转换器选项(例如{ "monoWidth": 40 })tests/expected/*.txt- 期望的 WhatsApp 输出
此外还有一些不变量:vendor 目录中的解析器与安装的解析器一致,convertToBlocks 报告正确的源行,包的入口是页面脚本。
测试还会在每次推送和拉取请求时于 CI 中运行(.github/workflows/test.yml)。
项目结构
docs/converter.js- 转换器本身:纯 ES 模块、不依赖 DOM,选项作为参数传入。它既是页面导入的脚本,也是 npm 包的入口(exports["."]),因此只有一份,没有构建步骤。它暴露convertTextToWhatsapp(markdown, options)、convertToBlocks(markdown, options)—— 相同的转换,但顶层块被分离,并标记每个块来自哪个表格,per-table选项正是建立在此基础上——以及mdContainsTable/mdContainsHeading/mdContainsCode查询,UI 用它来仅在适用时显示某个选项。convertToBlocks的每个块都报告其开始的源line—— 这使两个面板保持同步滚动——每个表格块还报告其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复制;页面的导入映射将marked解析到该目录bin/markdown-to-whatsapp.js- 命令行工具;bin/mcp.js- 它在mcp参数下启动的 MCP 服务器,仅在那时加载,因此转换文件不会加载协议 SDKscripts/vendor.js- 将 marked 的 ES 构建复制到docs/vendor/(npm run vendor)tests/- fixtures 和测试运行器
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 文件。
Available Tools
1 toolconvert_markdown_to_whatsappConvert Markdown to WhatsAppARead-onlyIdempotent
Convert Markdown into the formatting WhatsApp renders (bold, italic, strike, code, lists, quotes), ready to paste or send.
Use it instead of hand-writing WhatsApp syntax whenever the text has tables, nested lists, headings or inline formatting next to punctuation.
It applies WhatsApp's real rules: markers only on word boundaries, escapes that WhatsApp does not interpret, no mid-word formatting.
Each table is drawn as a monospace box sized to the reader's phone, degrading in this order: cell padding removed, then borders, then cells word-wrapped. It becomes a bulleted list only when no box fits.
Counting columns against a 26-character bubble is exactly what this tool does and a model does not.
| Name | Required | Description | Default |
|---|---|---|---|
| markdown | Yes | The Markdown text to convert | |
| monoWidth | No | Monospace characters that fit on one line of the reader's WhatsApp bubble; about 26 on a 360 px phone (default 26). Tables are drawn to fit this width. | |
| listLayout | No | How a table reads when it is a list: rows (one group per row), columns (one group per column, for comparison matrices), pairs (bare "key: value" lines, two columns only). auto guesses from the headers. Default auto. | |
| tableFormat | No | auto: a drawn table when it fits monoWidth, a bulleted list otherwise. list: always a bulleted list. Default auto. | |
| rowSeparator | No | Draw a rule between table rows. Always drawn when a row wraps. Default false. | |
| headingEmojis | No | Prefix headings with a level emoji (📌 🟠 🟡 …) before the bold text. Default true. |
Output Schema
| Name | Required | Description |
|---|---|---|
| text | Yes | The WhatsApp-formatted message |
| tables | Yes | One entry per table in the document, in order |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses real behavioral rules: markers only on word boundaries, escapes that WhatsApp does not interpret, no mid-word formatting, and a detailed table-degradation order (padding removed, then borders, then word-wrapping, then becoming a bulleted list). The annotations already indicate read-only and idempotent behavior, and the description adds substantial context beyond that without contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences carry the core purpose, usage triggers, formatting rules, and table behavior without filler. The main conversion statement is front-loaded, and each sentence contributes distinct, necessary information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 6 parameters, a complete input schema, and an output schema, the description covers purpose, when to use it, behavioral nuances, and table degradation fallbacks. Nothing significant is missing for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds general context about the 26-character bubble and table-fitting behavior, but it does not explain individual parameters beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Convert Markdown into the formatting WhatsApp renders' and lists concrete formatting constructs (*bold*, _italic_, ~strike~, `code`, lists, quotes). The scope is precise and there are no sibling tools to confuse it with.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells when to use it: 'Use it instead of hand-writing WhatsApp syntax whenever the text has tables, nested lists, headings or inline formatting next to punctuation.' It names the alternative (hand-writing) and gives concrete trigger conditions, though it does not state when not to use the tool or list exclusions for simple text.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v1.0.2- First observed
convert_markdown_to_whatsapp
TDQS
Scored across 1 tool
With only one tool, there is no possibility of confusion or misselection. The tool's purpose is entirely unambiguous within the server's scope.
The single tool name uses a clear snake_case verb_noun pattern that directly describes its action and target. Even without other tools for comparison, the naming is predictable and self-consistent.
The server has just one tool, but its purpose is extremely focused: converting Markdown to WhatsApp formatting. This is slightly below the typical 3-15 tool range, yet the single tool fully covers the server's stated domain.
The tool comprehensively handles the full conversion scenario, including tables, nested lists, headings, inline formatting, and WhatsApp's real formatting rules. Within the narrow markdown-to-WhatsApp domain, there are no obvious missing operations.
Maintenance
Related MCP Connectors
Markdown to PDF: headings, bold, code, lists, rules. A4/Letter/Legal. Free 30/hr. MCP + REST.
Use your own Word templates to convert Markdown → DOCX/PDF/HTML from any MCP-compatible AI.
Free deterministic PDF, Markdown, citation, invisible-character, and formatting cleanup for agents.
11PDF/Word/Excel/HTML to clean Markdown for LLMs and RAG. Keys $19/mo; 50 free calls a day.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceConverts various file formats to Markdown using the MarkItDown utility and can be integrated with MCP clients for seamless document processing and conversion.88MIT
- AlicenseAqualityCmaintenanceConverts Markdown documents to professional Word documents with advanced formatting capabilities including mathematical formulas, custom styling, tables, images, headers/footers, and watermarks.480 npm14MIT
- FlicenseNot gradedqualityDmaintenanceConverts documents (PDF, DOCX, images, etc.) to Markdown using Microsoft's Markitdown library, with no local setup required. Integrates with AI agents via MCP for seamless document conversion.1-
- AlicenseNot gradedqualityAmaintenanceA stdio MCP server that converts CommonMark/GFM Markdown into Slack mrkdwn, Microsoft Teams HTML, Jira wiki markup, and plain text, enabling agents to transform content for downstream platforms without posting or sending messages.7 npmMIT