> ## 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 сохраняет
исходный текст без изменений, одновременно передавая диапазоны стилей/ссылок, чтобы разбиение на фрагменты и рендеринг
оставались согласованными между каналами.

## Цели

* **Согласованность:** один этап разбора, несколько рендереров.
* **Безопасное разбиение:** разделение текста перед рендерингом, чтобы встроенное форматирование никогда
  не разрывалось между фрагментами.
* **Соответствие каналу:** сопоставление одного и того же IR с Slack mrkdwn, Telegram HTML и диапазонами
  стилей Signal без повторного разбора Markdown.

## Конвейер

1. **Разбор Markdown -> IR**
   * IR — это обычный текст плюс диапазоны стилей (жирный/курсив/зачеркнутый/код/спойлер) и диапазоны ссылок.
   * Смещения указаны в кодовых единицах UTF-16, чтобы диапазоны стилей Signal совпадали с его API.
   * Таблицы разбираются только тогда, когда канал включает преобразование таблиц.
2. **Разбиение IR (сначала форматирование)**
   * Разбиение выполняется по тексту IR перед рендерингом.
   * Встроенное форматирование не разделяется между фрагментами; диапазоны нарезаются для каждого фрагмента.
3. **Рендеринг для каждого канала**
   * **Slack:** токены mrkdwn (жирный/курсив/зачеркнутый/код), ссылки как `<url|label>`.
   * **Telegram:** HTML-теги (`<b>`, `<i>`, `<s>`, `<code>`, `<pre><code>`, `<a href>`).
   * **Signal:** обычный текст + диапазоны `text-style`; ссылки становятся `label (url)`, когда метка отличается.

## Пример IR

Входной Markdown:

```markdown theme={"theme":{"light":"min-light","dark":"min-dark"}}
Hello **world** - see [docs](https://docs.openclaw.ai).
```

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

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "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, Microsoft Teams, Discord) по-прежнему используют обычный текст или
  собственные правила форматирования, с преобразованием таблиц Markdown перед
  разбиением, когда оно включено.

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

Таблицы Markdown поддерживаются клиентами чатов неодинаково. Используйте
`markdown.tables`, чтобы управлять преобразованием для каждого канала (и для каждой учетной записи).

* `code`: рендерить таблицы как блоки кода (по умолчанию для большинства каналов).
* `bullets`: преобразовывать каждую строку в пункты маркированного списка (по умолчанию для Matrix, Signal и WhatsApp).
* `off`: отключить разбор и преобразование таблиц; исходный текст таблицы передается дальше.

Ключи конфигурации:

```yaml theme={"theme":{"light":"min-light","dark":"min-dark"}}
channels:
  discord:
    markdown:
      tables: code
    accounts:
      work:
        markdown:
          tables: off
```

## Правила разбиения

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

Если вам нужно больше информации о поведении разбиения между каналами, см.
[Потоковая передача + разбиение](/ru/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. Другие каналы обрабатывают их как обычный текст.

## Как добавить или обновить форматтер канала

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

## Частые подводные камни

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

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

<CardGroup cols={2}>
  <Card title="Streaming and chunking" href="/ru/concepts/streaming" icon="bars-staggered">
    Поведение исходящей потоковой передачи, границы фрагментов и доставка с учетом особенностей канала.
  </Card>

  <Card title="System prompt" href="/ru/concepts/system-prompt" icon="message-lines">
    Что модель видит перед разговором, включая внедренные файлы рабочей области.
  </Card>
</CardGroup>
