Форматирование Markdown
OpenClaw форматирует исходящий Markdown, преобразуя его в общее промежуточное представление (IR) перед рендерингом вывода для конкретного канала. IR сохраняет исходный текст нетронутым, при этом неся диапазоны стилей/ссылок, чтобы чанкинг и рендеринг могли оставаться консистентными на разных каналах.
Цели
- Консистентность: один шаг парсинга, несколько рендереров.
- Безопасный чанкинг: разделение текста перед рендерингом, чтобы встроенное форматирование никогда не разрывалось между чанками.
- Соответствие каналу: сопоставление одного и того же IR в Slack mrkdwn, Telegram HTML и диапазоны стилей Signal без повторного парсинга Markdown.
Конвейер
- Парсинг Markdown -> IR
- IR — это простой текст плюс диапазоны стилей (bold/italic/strike/code/spoiler) и диапазоны ссылок.
- Смещения — это кодовые единицы UTF-16, чтобы диапазоны стилей Signal соответствовали его API.
- Таблицы парсятся только когда канал выбирает конвертацию таблиц.
- Чанкинг IR (сначала формат)
- Чанкинг происходит на тексте IR перед рендерингом.
- Встроенное форматирование не разделяется между чанками; диапазоны нарезаются для каждого чанка.
- Рендеринг для каждого канала
- Slack: токены mrkdwn (bold/italic/strike/code), ссылки как <url|label>.
- Telegram: HTML-теги (<b>, <i>, <s>, <code>, <pre><code>, <a href>).
- Signal: простой текст + диапазоны text-style; ссылки становятся label (url), когда метка отличается.
Пример IR
Входной Markdown:
Hello **world** — see [docs](https://docs.openclaw.ai).
IR (схема):
{
"text": "Hello world — see docs.",
"styles": [
{ "start": 6, "end": 11, "style": "bold" }
],
"links": [
{ "start": 19, "end": 23, "href": "https://docs.openclaw.ai" }
]
}
Где это используется
- Адаптеры исходящих Slack, Telegram и Signal рендерят из IR.
- Другие каналы (WhatsApp, iMessage, MS Teams, Discord) все еще используют простой текст или собственные правила форматирования, с конвертацией таблиц Markdown, применяемой перед чанкингом, когда включена.
Обработка таблиц
Таблицы Markdown не консистентно поддерживаются в чат-клиентах. Используйте markdown.tables для управления конвертацией для каждого канала (и для каждого аккаунта).
- code: рендерить таблицы как блоки кода (по умолчанию для большинства каналов).
- bullets: преобразовать каждую строку в буллеты (по умолчанию для Signal + WhatsApp).
- off: отключить парсинг и конвертацию таблиц; сырой текст таблицы проходит насквозь.
Ключи конфигурации:
channels:
discord:
markdown:
tables: code
accounts:
work:
markdown:
tables: off
Правила чанкинга
- Лимиты чанков поступают из адаптеров/конфигурации каналов и применяются к тексту IR.
- Блоки кода сохраняются как один блок с замыкающей новой строкой, чтобы каналы рендерили их правильно.
- Префиксы списков и префиксы blockquote являются частью текста IR, поэтому чанкинг не разделяет в середине префикса.
- Встроенные стили (bold/italic/strike/inline-code/spoiler) никогда не разделяются между чанками; рендерер повторно открывает стили внутри каждого чанка.
Если вам нужно больше о поведении чанкинга на разных каналах, см. Потоковая передача + чанкинг.
Политика ссылок
- Slack: [label](url) -> <url|label>; голые URL остаются голыми. Autolink отключен во время парсинга, чтобы избежать двойных ссылок.
- Telegram: [label](url) -> <a href="url">label</a> (режим парсинга HTML).
- Signal: [label](url) -> label (url), если метка не соответствует URL.
Спойлеры
Маркеры спойлеров (||spoiler||) парсятся только для Signal, где они сопоставляются с диапазонами стиля SPOILER. Другие каналы обрабатывают их как простой текст.
Как добавить или обновить форматтер канала
- Парсить один раз: используйте общий помощник markdownToIR(...) с подходящими для канала опциями (autolink, стиль заголовка, префикс blockquote).
- Рендерить: реализуйте рендерер с renderMarkdownWithMarkers(...) и картой маркеров стилей (или диапазоны стилей Signal).
- Чанкинг: вызовите chunkMarkdownIR(...) перед рендерингом; рендерите каждый чанк.
- Связывание адаптера: обновите адаптер исходящего канала для использования нового чанкера и рендерера.
- Тестирование: добавьте или обновите тесты форматирования и тест доставки исходящих, если канал использует чанкинг.
Распространенные подводные камни
- Токены угловых скобок Slack (<@U123>, <#C123>, <https://...>) должны быть сохранены; экранируйте сырой HTML безопасно.
- Telegram HTML требует экранирования текста вне тегов, чтобы избежать поломанной разметки.
- Диапазоны стилей Signal зависят от смещений UTF-16; не используйте смещения кодовых точек.
- Сохраняйте замыкающие новые строки для огражденных блоков кода, чтобы закрывающие маркеры оказались на своей собственной строке.