Skip to main content
Glama
drsound

markdown-to-whatsapp

Markdown to WhatsApp Converter

License: MIT tests npm

Преобразуйте стандартный Markdown в синтаксис форматирования WhatsApp — как веб‑страницу, npm‑библиотеку, инструмент командной строки или MCP‑сервер для агентов.

➡️ Перейти к живому инструменту

npm i markdown-to-whatsapp · npx markdown-to-whatsapp mcp

Screenshot of the app


Назначение этого инструмента

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 — телефонов вне этого диапазона не суще. „

Число — свойство телефона, а не отдельной таблицы, поэтому оно управляет всем моноширинным: таблицы уменьшаются, чтобы вписаться в него, а превью рисует каждый код‑блок ровно этой ширины, с переносом в том месте, где переносит на телефоне получателя.

Таблиц

Таблица отображается одним из двух стилей, выбранной в интерфейсе для всего документа или для одной таблицы:

  1. Авто (по умолчанию): отрисованная таблица внутри моноширинного блока — нужной ширины, но никогда не шире пузы́ря, — а в случае, когда не нарисовать никакой рамки, маркированный список.

    +--------+-------------+
    | Name   | Description |
    +========+=============+
    | Value  | Details     |
    +--------+-------------+
  2. Список: всегда маркированный список.

Как формируется список

Список может группировать ячейки тремя способами. Конвертер угадывает способ по заголовкам и жирным ячейкам, а догадку можно переопределить для каждой таблицы (Макет: Автоматически · Строки · Столбцы · Пары):

  • Пары — 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:_ Proprietary
  • Rows — всё остальное: одна группа на строку, названная по своей первой ячейке.

    * *Product:* Laptop
    * ◦ _Price:_ $999
    * ◦ _Stock:_ 50
    * *Product:* Smartphone
    * ◦ _Price:_ $599
    * ◦ _Stock:_ 100

“Property”‑слова сопоставляются по слову («Species» не считается «spec») на 11 языках: английском, итальянском, испанском, французском, португальском, немецком, русском, арабском, хинди, бенгальском и индонезийском. Пары требуют ровно двух столбцов; если их запросить для таблицы шире, они читаются как «строки».

Как деградирует рамка

Рамка не выводится при любой ширине: она упрощается до тех, пока не впишется в monoWidth, а если ивписывается никак — превращается в список. У таблиц нет способа попросить второй ширины, чем пузырь.

  1. Полная рамка, удаляющая отступы по колонкам (сначала правые, затем левые).

  2. Компактный стиль без границ, тоже постепенно удаляя отступы:

     Head1|Head2       |Head-N
    ------+------------+------
     A    |BBBBBBBBBBBB|C
  3. Обёрнутая рамка — сначала с полными границами, затем компактная: каждая колонка получает минимум самое длинное слово, оставшаяся ширина распределяется пропорционально, ячейки переносятся по словам. Строки растут до любой — предела нет, и между столбцами всегда проводится линия, ведь без неё две перенесённые строки слепляются. Ячейки выравниваются по верхней части строки.

    +---------+--------------+
    | Feature | Notes here   |
    +=========+==============+
    | Alpha   | short note   |
    +---------+--------------+
    | Beta    | a slightly   |
    |         | longer note  |
    +---------+--------------+
  4. Маркированный список, когда не помещаются даже самые длинные слова (длинный 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&eacute; → café, &copy; → ©, &#65; → 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**.

Как использовать

  1. Откройте веб‑страницу: https://drsound.github.io/markdown-to-whatsapp/

  2. Вставьте набранный текст или перетащите .md‑файл в левую панель. Кнопка «Try an example» заполняет её примером сообщения.

  3. На правой панели сообщение отображается в пузыре WhatsApp ровно так, как его увидит получатель; «просмотр сырого синтаксиса» показывает текст для копирования. Панели прокручиваются даже вместе — активна та, которая под указателем, — и при наборе превью следует за визуальным курсором.

  4. «Скопировать для WhatsApp» или «Поделиться WhatsApp» для открытия чата с готовым сообщением через wa.me. Длинное сообщение не влезает в ссылку — браузеры обрезают URL после нескольких тысяч символов, — поэтому кнопка «Поделиться» уходит в сторону и предлагает вместо этого копировать.

Интерфейс следует светлой или тёмный теме операционной системы; переключатель в заголовке переопределяет её, и этот выбор запоминается. Панель параметров содержит по разделу на каждый тип содержимого, и каждый появляется, только пока в тексте есть такое содержимое: Bubble (ширина, когда есть таблица или код‑блок), Tables (стиль и разделитель) и Headings (эмодзи анкоров). Управляющий элемент, который другой параметр делает бессмысленным — разделитель в стили Table List, ширина при пустом моноширинном, — блокитивно и никуда не исчезает, чтобы панель сохраняла форму. Параметры хранятся в 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‑сервер

Пакет запускается как 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 — запускаемый по команде mcp MCP-сервер, загружается только в этот момент, поэтому преобразование файла никогда не загружает 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 tool
convert_markdown_to_whatsappConvert Markdown to WhatsAppA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
markdownYesThe Markdown text to convert
monoWidthNoMonospace 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.
listLayoutNoHow 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.
tableFormatNoauto: a drawn table when it fits monoWidth, a bulleted list otherwise. list: always a bulleted list. Default auto.
rowSeparatorNoDraw a rule between table rows. Always drawn when a row wraps. Default false.
headingEmojisNoPrefix headings with a level emoji (📌 🟠 🟡 …) before the bold text. Default true.

Output Schema

ParametersJSON Schema
NameRequiredDescription
textYesThe WhatsApp-formatted message
tablesYesOne entry per table in the document, in order

TDQS

A4.5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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. 1 tool updatev1.0.2
    • First observedconvert_markdown_to_whatsapp

TDQS

A4.6/5.0

Scored across 1 tool

Disambiguation5/5

With only one tool, there is no possibility of confusion or misselection. The tool's purpose is entirely unambiguous within the server's scope.

Naming Consistency5/5

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.

Tool Count4/5

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.

Completeness5/5

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

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers