> ## Documentation Index
> Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Форматирование Markdown

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 theme={"theme":{"light":"min-light","dark":"min-dark"}}
Привет, **мир**! См. [документацию](https://docs.openclaw.ai).
```

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

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "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 theme={"theme":{"light":"min-light","dark":"min-dark"}}
channels:
  discord:
    markdown:
      tables: code
    accounts:
      work:
        markdown:
          tables: off
```

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

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

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

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

* **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, а не смещения по кодовым точкам.
* Сохраняйте завершающие переводы строк в ограждённых блоках кода, чтобы закрывающий маркер
  располагался на отдельной строке.

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

> [card] [Потоковая передача и разбиение на фрагменты](https://docs2.openclaw.ai/ru/concepts/streaming.md)
>
> Поведение исходящей потоковой передачи, границы фрагментов и доставка с учётом особенностей каналов.

> [card] [Системная инструкция](https://docs2.openclaw.ai/ru/concepts/system-prompt.md)
>
> Что видит модель перед разговором, включая внедрённые файлы рабочей области.
