---
read_when:
    - Вы изменяете форматирование Markdown или разбиение на фрагменты для исходящих каналов
    - Вы добавляете новый форматтер канала или сопоставление стилей
    - Вы устраняете регрессии форматирования в разных каналах
summary: Конвейер форматирования Markdown для исходящих каналов
title: Форматирование Markdown
x-i18n:
    generated_at: "2026-07-13T18:03:28Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    prompt_version: 24
    provider: openai
    source_hash: f9a35fd9a6386068e1e3bec73ec6e692f49239b468f42dd737f919b1c6a88e41
    source_path: concepts/markdown-formatting.md
    workflow: 16
---

OpenClaw преобразует исходящий Markdown в общее промежуточное представление
(IR) перед формированием вывода для конкретного канала. IR хранит обычный текст вместе с
диапазонами стилей и ссылок, поэтому один этап синтаксического анализа обслуживает все каналы, а разбиение на фрагменты никогда
не разделяет форматирование внутри диапазона.

## Конвейер

1. **Преобразование Markdown в IR** (`markdownToIR`) — обычный текст и диапазоны стилей
   (полужирный, курсив, зачёркнутый, код, блок кода, спойлер, цитата,
   заголовок 1-6), а также диапазоны ссылок. Смещения измеряются в кодовых единицах UTF-16, поэтому диапазоны стилей Signal
   напрямую соответствуют его API. Таблицы анализируются только тогда, когда канал
   включает один из режимов таблиц.
2. **Разбиение IR на фрагменты** (`chunkMarkdownIR` / `renderMarkdownIRChunksWithinLimit`)
   - разбиение выполняется по тексту IR перед формированием вывода, поэтому встроенные стили и
     ссылки разделяются по фрагментам, а не обрываются на границе.
3. **Формирование вывода для каждого канала** (`renderMarkdownWithMarkers`) — карта маркеров стилей
   преобразует диапазоны во встроенную разметку канала.

| Канал                                                            | Средство формирования вывода                                                        | Примечания                                                                                                     |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| Slack                                                            | токены mrkdwn (`*bold*`, `_italic_`, `` `code` ``, ограждения кода)                   | Ссылки преобразуются в `<url\|label>`; автоматическое распознавание ссылок отключено при анализе во избежание дублирования ссылок |
| Telegram                                                         | HTML-теги (`<b>`, `<i>`, `<s>`, `<code>`, `<pre><code>`, `<a href>`, `<tg-spoiler>`) | Также поддерживает таблицы и заголовки форматированных сообщений (`<h1>`-`<h6>`), когда включён `richMessages` |
| Signal                                                           | обычный текст + диапазоны `text-style`                                              | Ссылки формируются как `label (url)`, когда подпись отличается от URL                                         |
| Discord, WhatsApp, iMessage, Microsoft Teams и другие каналы     | обычный текст                                                                        | Стилизация на основе IR отсутствует; преобразование таблиц Markdown по-прежнему выполняется через `convertMarkdownTables` |

## Пример IR

Входной Markdown:

```markdown
Привет, **мир**! См. [документацию](https://docs.openclaw.ai).
```

IR (схематично):

```json
{
  "text": "Привет, мир! См. документацию.",
  "styles": [{ "start": 6, "end": 11, "style": "bold" }],
  "links": [{ "start": 19, "end": 23, "href": "https://docs.openclaw.ai" }]
}
```

## Обработка таблиц

`markdown.tables` определяет, как канал преобразует таблицы Markdown, отдельно для
каждого канала и при необходимости для каждой учётной записи:

| Режим    | Поведение                                                                            |
| -------- | ------------------------------------------------------------------------------------ |
| `code`    | Формировать выровненную ASCII-таблицу внутри блока кода (режим по умолчанию при откате) |
| `bullets` | Преобразовывать каждую строку в пункты маркированного списка `label: value`           |
| `block`   | Сохранять нативные таблицы, если транспорт их поддерживает; иначе переходить к `code` |
| `off`     | Отключить анализ таблиц; исходный текст таблицы передаётся без изменений              |

Значения плагинов по умолчанию для каналов: Signal, WhatsApp и Matrix по умолчанию используют
`bullets`; Mattermost — `off`; Telegram — `block` (который
разрешается в `code`, если для учётной записи не включён `richMessages`). Любой
канал без явно заданного значения плагина по умолчанию переходит к `code`.

```yaml
channels:
  discord:
    markdown:
      tables: code
    accounts:
      work:
        markdown:
          tables: off
```

## Правила разбиения на фрагменты

- Ограничения размера фрагментов задаются адаптерами или конфигурацией каналов и применяются к тексту IR, а не к
  сформированному выводу.
- Ограждённые блоки кода сохраняются как единый блок с завершающим переводом строки, чтобы
  каналы корректно формировали закрывающее ограждение.
- Префиксы списков и цитат входят в текст IR, поэтому разбиение на фрагменты никогда
  не происходит внутри префикса.
- Встроенные стили никогда не разделяются между фрагментами; средство формирования вывода повторно открывает незакрытый
  стиль в начале следующего фрагмента.

Поведение границ фрагментов и доставки в разных каналах описано в разделе
[Потоковая передача и разбиение на фрагменты](/concepts/streaming).

## Политика ссылок

- **Slack:** `[label](url)` -> `<url|label>`; URL без подписи остаются без изменений.
- **Telegram:** `[label](url)` -> `<a href="url">label</a>` (режим анализа HTML).
- **Signal:** `[label](url)` -> `label (url)`, если подпись ещё
  не совпадает с URL.

## Спойлеры

Маркеры спойлеров (`||spoiler||`) анализируются для Signal (преобразуются в диапазоны стиля `SPOILER`)
и Telegram (преобразуются в `<tg-spoiler>`). Другие каналы обрабатывают
`||...||` как обычный текст.

## Добавление или обновление средства форматирования канала

1. **Выполните анализ один раз** с помощью `markdownToIR(...)`, передав подходящие для канала
   параметры (`autolink`, `headingStyle`, `blockquotePrefix`, `tableMode`).
2. **Сформируйте вывод** с помощью `renderMarkdownWithMarkers(...)` и карты маркеров стилей (либо
   пользовательской логики диапазонов стилей для таких транспортов, как Signal).
3. **Разбейте на фрагменты** с помощью `chunkMarkdownIR(...)` или
   `renderMarkdownIRChunksWithinLimit(...)` перед формированием каждого фрагмента.
4. **Подключите адаптер**, чтобы новый механизм разбиения и средство формирования вывода вызывались из
   пути отправки исходящих сообщений.
5. **Протестируйте** с помощью тестов форматирования и теста исходящей доставки, если канал
   разбивает сообщения на фрагменты.

## Распространённые ошибки

- Токены Slack в угловых скобках (`<@U123>`, `<#C123>`, `<https://...>`) должны
  сохраняться при экранировании; необработанный HTML по-прежнему необходимо безопасно экранировать.
- Для HTML в Telegram необходимо экранировать текст за пределами тегов, чтобы избежать повреждения разметки.
- Диапазоны стилей Signal используют смещения UTF-16, а не смещения по кодовым точкам.
- Сохраняйте завершающие переводы строк в ограждённых блоках кода, чтобы закрывающий маркер
  располагался на отдельной строке.

## Связанные материалы

<CardGroup cols={2}>
  <Card title="Потоковая передача и разбиение на фрагменты" href="/ru/concepts/streaming" icon="bars-staggered">
    Поведение исходящей потоковой передачи, границы фрагментов и доставка с учётом особенностей каналов.
  </Card>
  <Card title="Системная инструкция" href="/ru/concepts/system-prompt" icon="message-lines">
    Что видит модель перед разговором, включая внедрённые файлы рабочей области.
  </Card>
</CardGroup>
