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*_(сохраняются оба стиля)
Заголовки
Заголовки преобразуются в жирный текст с эмодзи‑префиксами, зависящими от уровня:
# H1→*📌 H1*## H2→*🟠 H2*### H3→*🟡 H3*И так далее…
Эмодзи‑префикс можно отключить в интерфейсе (Заголовки · Эмодзи), и останется обычное *Title*.
Списки
Маркированные списки: используется префикс
*и◦для вложенных уровнейУровень 1:
* ItemУровень 2:
* ◦ ItemУровень 3:
* ◦ ◦ Item
Нумерованные списки: нумерация сохраняется, а вложенные уровни обозначаются
◦1. A/◦ 2. A1/◦ ◦ 3. A1a/4. B
Задачи:
- [x]→☑,- [ ]→☐, в том числе внутри нумерованных списков (1. ☑ done)Свободные пункты: несколько абзацев одного пункта объединяются в одну строку
Блочное содержимое в пунктах: код, цитаты и вложенные списки выносятся на отдельные строки под пунктом
Ширина пузыря
В пузыре WhatsApp помещается фиксированное число моноширинных символов в строку — примерно 26 на телефоне с шириной экрана 360px, и это значение по умолчанию. Измерьте свой пузырь: отправьте себе код‑блок и посмотрите, где он переносится, затем укажите Width на панели (стоящий рядом ? говорит то же самое). Поле принимает значения от 10 до 80 — телефонов вне этого диапазона не суще. „
Число — свойство телефона, а не отдельной таблицы, поэтому оно управляет всем моноширинным: таблицы уменьшаются, чтобы вписаться в него, а превью рисует каждый код‑блок ровно этой ширины, с переносом в том месте, где переносит на телефоне получателя.
Таблиц
Таблица отображается одним из двух стилей, выбранной в интерфейсе для всего документа или для одной таблицы:
Авто (по умолчанию): отрисованная таблица внутри моноширинного блока — нужной ширины, но никогда не шире пузы́ря, — а в случае, когда не нарисовать никакой рамки, маркированный список.
+--------+-------------+ | Name | Description | +========+=============+ | Value | Details | +--------+-------------+Список: всегда маркированный список.
Как формируется список
Список может группировать ячейки тремя способами. Конвертер угадывает способ по заголовкам и жирным ячейкам, а догадку можно переопределить для каждой таблицы (Макет: Автоматически · Строки · Столбцы · Пары):
Пары — 2 столбца, независимо от заголовков: каждая строка по структуре
ключ: значение. Развёртывать заголовки в каждой строке читается почти в любой таблице хуже, чемItaly: Rome.* *CPU:* Intel Xeon * *RAM:* 64 GB * *Storage:* 1 TB SSDСтолбцы — 3+ столбца, у которых первый заголовок пуст или задаёт свойство («Feature», «Spec», «Parameter»…), либо первая колонка жирная: это сравнительная матрица, где сравнивается именно столбцы, поэтому каждой столбец становится группой.
* *Proxmox* * ◦ _Kernel:_ KVM * ◦ _License:_ AGPL v3 * *ESXi* * ◦ _Kernel:_ VMkernel * ◦ _License:_ ProprietaryRows — всё остальное: одна группа на строку, названная по своей первой ячейке.
* *Product:* Laptop * ◦ _Price:_ $999 * ◦ _Stock:_ 50 * *Product:* Smartphone * ◦ _Price:_ $599 * ◦ _Stock:_ 100
“Property”‑слова сопоставляются по слову («Species» не считается «spec») на 11 языках: английском, итальянском, испанском, французском, португальском, немецком, русском, арабском, хинди, бенгальском и индонезийском. Пары требуют ровно двух столбцов; если их запросить для таблицы шире, они читаются как «строки».
Как деградирует рамка
Рамка не выводится при любой ширине: она упрощается до тех, пока не впишется в monoWidth, а если ивписывается никак — превращается в список. У таблиц нет способа попросить второй ширины, чем пузырь.
Полная рамка, удаляющая отступы по колонкам (сначала правые, затем левые).
Компактный стиль без границ, тоже постепенно удаляя отступы:
Head1|Head2 |Head-N ------+------------+------ A |BBBBBBBBBBBB|CОбёрнутая рамка — сначала с полными границами, затем компактная: каждая колонка получает минимум самое длинное слово, оставшаяся ширина распределяется пропорционально, ячейки переносятся по словам. Строки растут до любой — предела нет, и между столбцами всегда проводится линия, ведь без неё две перенесённые строки слепляются. Ячейки выравниваются по верхней части строки.
+---------+--------------+ | Feature | Notes here | +=========+==============+ | Alpha | short note | +---------+--------------+ | Beta | a slightly | | | longer note | +---------+--------------+Маркированный список, когда не помещаются даже самые длинные слова (длинный URL, пять колонок при 26 символах…).
Что читается лучше — высокая обёрнутая рамка или список, — вы сами решаете в превью: на соответствующей таблице её панель переводит её в список. Если таблица не вписывается ни в какую рамка, панель об этом сообщает и предлагает макет списком вместо стиля, который не смог бы ничего изменить.
Дополнительное поведение таблиц
Ширина столбцов измеряется в ячейках отображения, поэтому эмодзи и текст CJK остаются выровненными (
✅,日本語занимают две колонки).Выравнивание столбцов (
:---,:---:,---:) учитывается в стиле рамки и в компактном стиле.Таблица только из шапки выводится без пустого тела или двойной границы.
<br>внутри ячейки становится пробелом, а экранированный\|образуют¦, чтобы нельзя было создать фильшивую лишнюю колонку.Границы выполняются обычным ASCII (
+-|=), сознательно. У моноширинного шрифта WhatsApp нет символов псевдографики: телефон берёт─и┌из своего запасного шрифта, с какой бы шириной ни давал их этот шрифт, и линия из 26 таких символов переносится, в то время как соседние текстовые ряды не переносятся.+-|— единственные символы, ширину которых моноширинная гарнитура передаёт на самом деле; поэтому экранированная палка становится¦— символом Latin‑1 из того же шрифта, что иà.Разделитель строк (отключён по умолчанию) рисует линию между столбцами во всех вариантах и в компактных стилях; обёрнутая таблица рисует её всегда.
Стиль, разделитель строк и макет списка можно задавать для каждой таблицы: наведя на таблицу превью, видно её собственные элементы управления, которые отправляются от умолчаний документа и переопределяют их только для той таблицы, показывая только им подходящие (разделитель на рамке таблицы, макет на списке). Ширины среди них нет — пузы́рь один, и он одинаков для всех таблиц. Таблица со своими настройками сохраняет пунктир, поскольку управление в верней части панели её сознательно не трогает; свою сброс возвращает её к ним. Переопределения следуют за таблицей по тексту её заголовка, поэтому добавление или удаление таблицы выше не сдвигает её. Таблица, вложенная в пункт списка или цитату, всегда использует шёе по умолчанию.
Блоки кода
Блоки с ограждением и с отступом попадают в WhatsApp без изменений: конвертер никогда не переносит и не меняет их отступ, ведь разрыв строки внутри кода — это содержимое, а не оформление. WhatsApp сам переносит длинные строки посреди слова, а у чата‑пузыря нет горизонтальной прокрутки, — поэтому превью воспроизводит такой перенос по monoWidth без прокрутки и показывает точното место, где разрыв увидит получатель.
Прочие элементы
Ссылки:
[text](url)→text (url); автологические ссылки,<https://x>,[url](url)и<me@x.com>отдаются как открытый URL или адрес (без дублирования и без утечкиmailto:)HTML‑сущности: десятичные и шестнадцатеричные ссылки, а также распространённые именованные — латинские буквы, пунктуация и символы (
café→café,©→©,A→A). Более редкие (греческие, математические) остаются как есть.Inline‑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‑файл в левую панель. Кнопка «Try an example» заполняет её примером сообщения.На правой панели сообщение отображается в пузыре WhatsApp ровно так, как его увидит получатель; «просмотр сырого синтаксиса» показывает текст для копирования. Панели прокручиваются даже вместе — активна та, которая под указателем, — и при наборе превью следует за визуальным курсором.
«Скопировать для WhatsApp» или «Поделиться WhatsApp» для открытия чата с готовым сообщением через
wa.me. Длинное сообщение не влезает в ссылку — браузеры обрезают URL после нескольких тысяч символов, — поэтому кнопка «Поделиться» уходит в сторону и предлагает вместо этого копировать.
Интерфейс следует светлой или тёмный теме операционной системы; переключатель в заголовке переопределяет её, и этот выбор запоминается. Панель параметров содержит по разделу на каждый тип содержимого, и каждый появляется, только пока в тексте есть такое содержимое: Bubble (ширина, когда есть таблица или код‑блок), Tables (стиль и разделитель) и Headings (эмодзи анкоров). Управляющий элемент, который другой параметр делает бессмысленным — разделитель в стили Table List, ширина при пустом моноширинном, — блокитивно и никуда не исчезает, чтобы панель сохраняла форму. Параметры хранятся в localStorage вместе с темой. Выбор для каждой отдельной таблицы не хранится: он принадлежит преобразуемому тексту.
Использование из кода, командной строки или агента
Тот же преобразователь опубликован на npm под именем markdown-to-whatsapp (требуется Node 20 или новее). Параметры — расмотренные выше, с теми же именами и значениями по умолчанию; они полностью перечислены в конце этого раздела.
Библиотека
npm install markdown-to-whatsappimport { 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‑сервер
Пакет запускается как 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— необязательные опции конвертера для конкретной фикстуры (например,{ "monoWidth": 40 })tests/expected/*.txt— ожидаемый вывод WhatsApp
плюс несколько инвариантов: поставляемый парсер совпадает с установленным, convertToBlocks сообщает правильные исходные строки, точка входа пакета — скрипт страницы.
Тесты также запускаются в CI для каждого push и pull request (.github/workflows/test.yml).
Структура проекта
docs/converterjs— сам конвертер: чистый ES-модуль, без DOM, опции передаются как параметр. Он одновременно и скрипт, который импортирует страница, и точка входа npm-пакета (exports["."]), так что существует одна копия и никакого шага сборки нет. Он предоставляетconvertTextToWhatsapp(markdown, options),convertToBlocks(markdown, options)— то же преобразование, но блоки верхнего уровня разделены и каждый помечен таблицей, из которой он пришёл, и именно на этом строятся опции для конкретной таблицы, — а такжеmdToTontainsTable/mdToHeading/mdContainsCode, которые интерфейс использует, чтобы показывать опцию только тогда, когда она применима. Каждый блок изconvertToBlocksсообщает исходный код строки, с которой начинается, — это обеспечивает синхронную прокрутку двух панелей, а каждый табличный блок дополнительно содержитkey,columns,fitsBox(блок возможен),sizeList(что было записано) иlistLayout, чтобы интерфейс мог предложить ровно оставшиеся варианты.docs/ui.js— связка страницы: тема, контекстные опции, предпросмотр WhatsApp, синхронная прокрутка панеле, копирование и отправкаdocs/index.html,docs/style.css— разметка и стиль, написанный вручную (без CSS-фреймворка)docs/vendor/— ES-сборка marked, скопированная изnode_modulesкомандойnpm run vendor; карта импорта страницы сопоставляетmarkedс этой сборкой;bin/markdown-to-whatsapp.js— утилита командной строки;bin/mcp.js— запускаемый по командеmcpMCP-сервер, загружается только в этот момент, поэтому преобразование файла никогда не загружает SDK протоколаscripts/vendor.js— копирует ES-сборкуmarkedв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.
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