---
id: 01-syntax
updated: 2026-08-10 17:40 GMT+3
---

# Синтаксис Демонстратора

Материал — один Markdown-файл. Интерактив — блоки `:::тип` … `:::/тип`.

## Жёсткие правила

1. Открытие: `:::имя` в начале строки. Закрытие: **только** `:::/имя` в начале строки. Для каждого открытого блока — своё закрытие. Без исключений.
2. URL и текст тела — **со следующей строки** после `:::имя`. На строке `:::имя` — только имя, вариант и модификаторы.
3. Не выдумывай имена, варианты и модификаторы вне таблицы ниже.
4. `%%` в начале строки — комментарий. При рендере отбрасывается.
5. GFM-таблицы и автолинки поддерживаются.
6. Блок **многострочный**: `:::имя`, пункты `===`, тело и `:::/имя` — **отдельные строки**. Не склеивай в одну строку (`:::steps === … === … :::/steps` — запрещено).
7. Смысл строки `===` **зависит от блока** (см. таблицу ниже). Не копируй паттерн `=== Заголовок` из `acc`/`steps` в `columns`.
8. `:::important` — короткая врезка (обычно несколько предложений). **Не** оборачивай в important весь урок, статью или файл с `#` заголовками и несколькими разделами.
9. Русский текст — по `06-russian-typography.md`: тире —, кавычки «ёлочки», многоточие …; не `-` и не `"..."` в прозе.

### Строка `===` по типу блока

| Блоки | Строка `===` | Заголовок пункта / колонки |
|---|---|---|
| `acc`, `tab`/`tabs`, `flip`, `steps`, `compare`, `checklist` | `=== Текст` — текст **обязателен** | Текст на той же строке после `===` |
| `columns` | **пустой** `===` — только разделитель колонок | Заголовок колонки — только `###` внутри колонки |
| `test` | `===` (часто пустой) или с текстом вопроса — по канону test | Не путай с заголовком колонок |

Если в превью видны сырые `===` или обрывки `:::/…` — сломан разделитель или fence: чаще всего `=== Заголовок` внутри `:::columns` или незакрытый блок.

## Полная таблица блоков

| Блок | Варианты (после имени) | Модификаторы | Размеры на строке `:::` | Закрытие |
|---|---|---|---|---|
| `acc` | — | — | — | `:::/acc` |
| `tab` / `tabs` | — | — | — | `:::/tab` |
| `flip` | — | — | — | `:::/flip` |
| `test` | — | — | — | `:::/test` |
| `steps` | `grid` | — | — | `:::/steps` |
| `checklist` | `duo` | — | — | `:::/checklist` |
| `compare` | — | — | — | `:::/compare` |
| `button` | `group` | — | — | `:::/button` |
| `important` | `idea`, `problem`, `solution`, `info`, `rule` | — | — | `:::/important` |
| `tmp` | `video`, `sim`, `dialog`, `hotspot`, `hint` | — | — | `:::/tmp` |
| `embed` | — | `wide` | — (размеры в теле) | `:::/embed` |
| `audio` | — | — | — | `:::/audio` |
| `video` | — | `wide` | `WxH` (напр. `960x540`) | `:::/video` |
| `file` | — | — | — | `:::/file` |
| `web_archive` | — | `wide` | `WxH` | `:::/web_archive` |
| `ai_widget` | — | `wide` | `WxH` | `:::/ai_widget` |
| `picfont` | `chat`, `right` | — | — | `:::/picfont` |
| `slider` | `duo` | `wide` | — | `:::/slider` |
| `hotspot` | — | `wide` | — | `:::/hotspot` |
| `columns` | — | `wide` | — | `:::/columns` |

Пиши `:::columns` … `:::/columns`.

`:::comments` — служебный. Не создавай вручную.

Картинка в обычном Markdown — `![подпись](URL)`. **Не** оборачивай в `![…](…)` URL внутри блоков, где синтаксис требует голый URL (`:::audio` / `:::video` / `:::picfont` / аватары в `:::picfont chat` и т.п.). Исключение: кадры `:::slider` и фон `:::hotspot` — там как раз `![…](URL)`.

## Вложенность

- Внутри `:::acc`, `:::tab`, `:::flip`, `:::steps`, `:::compare` разрешён **один** уровень вложенных блоков `:::` или картинок `![…](URL)`.
- Внутри пункта `:::hotspot` после координат — только плоский Markdown. Вложенные `:::` **запрещены**.
- Не вкладывай блок того же типа в себя (`:::acc` внутри `:::acc`).
- Колонки глубже одного уровня не используй.

## Заголовки

Только ATX уровней 1–3:

# Заголовок H1
## Заголовок H2
### Заголовок H3

H4–H6 и setext не используй.

## Текст

| Назначение | Синтаксис | Запрещено |
|---|---|---|
| Жирный | `**текст**` или `__текст__` | — |
| Курсив | `*текст*` или `_текст_` | — |
| Код | `` `код` `` | — |
| Ссылка | `[текст](URL)` | — |
| Картинка | `![подпись](URL)` | `[текст](URL)` без `!` — это ссылка, не картинка |

Списки: `- пункт` или `* пункт`; нумерованные `1.` `2.`. Маркер `+` в обычном списке не используй (в чеклисте `+` — отдельный синтаксис).

Цитата: `>`, `>>`, `>>>` в начале строки.

Разделитель: строка из минимум трёх дефисов `---`.

## Изображение

Канон:

![Подпись под картинкой](https://cdn.longread.agency/demo/image-demo.webp)

- Текст в `![…]` — подпись под картинкой (figcaption).
- Пиши осмысленную подпись. Пустые `![](URL)` и `![ ](URL)` парсер принимает, но для обычных картинок и хотспотов не используй.
- HTTPS-URL с любого хоста для markdown-картинок **разрешены**. Для демо бери CDN ниже. Без MCP: CDN-заполнитель или URL от пользователя.

## Важное

Краткая форма (одна строка):

!!! Текст замечания.

Блочная форма:

:::important
Текст замечания.
:::/important

С вариантом:

:::important rule
Не храните пароли в чате.
:::/important

| Вариант | Когда | Что рисует система |
|---|---|---|
| *(без)* | Замечание | Иконка info, серый фон |
| `idea` | Совет | Лампочка, жёлтый фон |
| `problem` | Ошибка | Треугольник, красный фон |
| `solution` | Решение | Галочка, зелёный фон |
| `info` | Справка | Info, синий фон |
| `rule` | Норма / принцип | Параграф §, акцентный фон |

Иконку система добавляет сама. **Не** вставляй эмодзи и символы иконок в текст блока.

Не используй important как обёртку всего материала. Каркас урока — обычный Markdown (`#` / `##` / абзацы); important — точечный акцент внутри.

## Медиа: единый формат тела

| Блок | Строка 1 тела | Строка 2+ | Пример открытия |
|---|---|---|---|
| `audio` | URL | подпись (необязательно) | `:::audio` |
| `video` | URL | подпись (необязательно) | `:::video` или `:::video wide` или `:::video 960x540` |
| `file` | URL | имя файла (обязательно для подписи) | `:::file` |
| `web_archive` | URL | подпись (необязательно) | `:::web_archive` / `wide` / `WxH` |
| `ai_widget` | URL | подпись (необязательно) | `:::ai_widget` / `wide` / `WxH` |
| `embed` | `URL === WxH` одной строкой | — | `:::embed` или `:::embed wide` |
| `picfont` | URL | текст рядом | `:::picfont` или `:::picfont right` |
| `picfont chat` | после `=== Имя` — **голый URL** аватара, затем текст реплики | — | `:::picfont chat` |

:::audio
https://cdn.longread.agency/demo/audio-sample.mp3
:::/audio

:::video
https://cdn.longread.agency/demo/video-sample.mp4
:::/video

:::file
https://cdn.longread.agency/demo/file-demo.pdf
Раздаточный материал
:::/file

:::web_archive
https://cdn.longread.agency/demo/archive-demo/index.html
:::/web_archive

:::ai_widget
https://cdn.longread.agency/demo/widget-demo.html
:::/ai_widget

Имя блока — **`ai_widget`** (не `ai-widget`). Голый URL HTML в абзаце или «ссылка в чат» **не** заменяют блок.

ИИ-HTML через MCP: `create-widget` → `save-widget-draft` → `bake-widget` → **`insert-ai-widget-block`** (fence = id) → poll `archives/` по маркеру. Не сдавай по draft. Без вставки в материал задача не сдана. Правила — `05-html-widget-rules.md`. Внешние картинки без расширения файла на CDN блокируются при bake.

:::embed
https://longread.media === 640x360
:::/embed

По умолчанию для embed без размеров в теле — 640×360.

:::picfont
https://cdn.longread.agency/demo/picfont-icon.webp
Короткий факт рядом с картинкой.
:::/picfont

:::picfont chat
=== Ассистент
https://cdn.longread.agency/demo/avatar-bot.webp
Ответ ассистента.

=== Пользователь
https://cdn.longread.agency/demo/avatar-user.webp
Вопрос пользователя.
:::/picfont

В `:::picfont chat` у каждой реплики:

1. `=== Имя` (имя собеседника)
2. **Следующая строка — только голый HTTPS-URL аватара** (без `!`, без `[…]`, без подписи)
3. Далее текст сообщения

**Нельзя** (ломает чат — аватар становится огромной картинкой в пузыре):

```
=== Новичок
![Новичок](https://cdn.longread.agency/images/….webp)
Текст реплики.
```

**Нужно:**

```
=== Новичок
https://cdn.longread.agency/images/….webp
Текст реплики.
```

При замене локальных путей / CDN-URL внутри `:::picfont chat` меняй **только** строку URL. Не превращай её в markdown-картинку `![…](url)`.

Обычный `:::picfont` (не chat): тоже голый URL на первой строке тела, текст — со второй. Не `![…](url)`.

## Слайдер

:::slider
=== Кадр 1
![Кадр 1](https://cdn.longread.agency/demo/slider-1.webp)
Текст первого кадра.

=== Кадр 2
![Кадр 2](https://cdn.longread.agency/demo/slider-2.webp)
Текст второго кадра.
:::/slider

:::slider duo
=== Было
![До правки](https://cdn.longread.agency/demo/slider-before.webp)
Интерфейс до изменений.

=== Стало
![После правки](https://cdn.longread.agency/demo/slider-after.webp)
Новый интерфейс.
:::/slider

`:::slider wide` и `:::slider duo wide` допустимы.

## Интерактивы

### Аккордеон

:::acc
=== Заголовок пункта
Содержимое пункта.

=== Второй заголовок
Содержимое второго пункта.
:::/acc

### Вкладки

:::tab
=== Вкладка 1
Содержимое первой вкладки.

=== Вкладка 2
Содержимое второй вкладки.
:::/tab

### Карточки flip

:::flip
=== Термин
Определение на обороте.

=== Второй термин
Второй ответ.
:::/flip

Допустимо однострочно: `лицо === оборот`.

### Хотспот

:::hotspot
![Схема](https://cdn.longread.agency/demo/hotspot-demo.webp)
=== 30% 40% Зона A
Пояснение зоны A.

=== 1 70% 55% Зона B
Маркер с цифрой 1.
:::/hotspot

- `=== 30% 40% Имя` — точка.
- `=== 1 70% 55% Имя` — маркер с цифрой.
- Координаты — проценты от левого верхнего угла.
- Без строк `===` блок = обычное изображение.

### Кнопка

Кнопки — только внешние ссылки. Не используй их как навигацию по материалу или проекту: у экспорта проекта есть встроенный плеер.

:::button
Подробнее на Longread.Media === https://longread.media
:::/button

:::button group
=== Longread.Media === https://longread.media
=== Ecourse.Studio === https://ecourse.studio
:::/button

### Шаги

:::steps
=== Откройте файл
Дважды щёлкните по ярлыку.
=== Сохраните файл
Ctrl+S.
:::/steps

`:::steps` — столбец со стрелками ↓. `:::steps grid` — сетка без стрелок.

### Чеклист

Маркер в начале строки задаёт тон пункта:

| Маркер | Вид | Когда |
|---|---|---|
| `+` | Зелёная галочка ✓ | Плюс, возможность, «как надо», факт-преимущество |
| `-` | Красный крест ✗ | Минус, ошибка, «как не надо» |

Список возможностей / фич / преимуществ — **только** `+`. Не ставь `-` «по привычке списка»: `-` в чеклисте = негатив.

:::checklist
+ Правильный пункт
- Неправильный пункт
Пояснение без маркера
:::/checklist

:::checklist duo
=== + Правильно
Верный подход.
=== - Неправильно
Ошибочный подход.
:::/checklist

### Сравнение

Ровно две секции `===`:

:::compare
=== Плохо
Неструктурированный текст.
=== Хорошо
Текст с заголовками.
:::/compare

### Тест

Открытие — **только** строка `:::test`. Режим — **следующая** строка тела: `[test]` / `[verification]` или `[think]` / `[narrative]`.

| Нельзя | Надо |
|---|---|
| `:::test[test]` | `:::test` затем строка `[test]` |
| `:::test test` | то же |
| режим на одной строке с `:::` | режим внутри тела |

Режим `[test]` / `[verification]`: нужен минимум один `+` и один `-`.

:::test
[test]
===
Вопрос?
+ Правильный вариант
- Неправильный вариант
ye: Верно!
no: Подумайте ещё.
:::/test

Режим `[think]` / `[narrative]`: вариантов с `+` нет.

:::test
[think]
===
Что вы думаете?
- Вариант 1
- Вариант 2
- Вариант 3
ok: Спасибо за ответ!
:::/test

Строки `ye:`, `no:`, `ok:` необязательны: если их нет, система подставит дефолтный текст. Пиши их явно, когда нужен свой текст обратной связи.

### Заглушка

| Открытие | Вид заглушки |
|---|---|
| `:::tmp` | Карточка 2:1, подпись «Заглушка» |
| `:::tmp video` | Подпись «Видео» |
| `:::tmp sim` | Подпись «Симулятор» |
| `:::tmp dialog` | Подпись «Диалог» |
| `:::tmp hotspot` | Подпись «Маркеры» |
| `:::tmp hint` | Текстовая плашка без картинки |

:::tmp
Скоро здесь будет схема
:::/tmp

### Колонки

:::columns
70-30
===
Первая колонка.
===
Вторая колонка.
:::/columns

- Первая строка тела — соотношение: `50-50`, `70-30`, `2:1`, `1:1:1`. **Не** `50/50`.
- Разделитель колонок — `===` на отдельной строке **без текста** после `===`.
- Заголовок внутри колонки — `###` или `**…**`, не `=== Заголовок`.
- Широкий ряд: `:::columns wide`.

| Нельзя | Надо |
|---|---|
| `50/50` | `50-50` или `1:1` |
| `=== Заголовок` как разделитель | `===` пустой; заголовок — `###` |

## Служебное

Строка `<<текст>>` — метка задачи. Рендерится как текст в угловых кавычках.

## CDN-заполнители

| Блок | URL |
|---|---|
| Изображение | `https://cdn.longread.agency/demo/image-demo.webp` |
| Хотспот | `https://cdn.longread.agency/demo/hotspot-demo.webp` |
| Аудио | `https://cdn.longread.agency/demo/audio-sample.mp3` |
| Видео | `https://cdn.longread.agency/demo/video-sample.mp4` |
| Файл | `https://cdn.longread.agency/demo/file-demo.pdf` |
| Веб-архив | `https://cdn.longread.agency/demo/archive-demo/index.html` |
| ИИ-HTML | `https://cdn.longread.agency/demo/widget-demo.html` |
| Picfont | `https://cdn.longread.agency/demo/picfont-icon.webp` |
| Аватар бот | `https://cdn.longread.agency/demo/avatar-bot.webp` |
| Аватар пользователь | `https://cdn.longread.agency/demo/avatar-user.webp` |
| Слайдер | `…/slider-1.webp`, `slider-2.webp`, `slider-3.webp` |
| Слайдер duo | `…/slider-before.webp`, `…/slider-after.webp` |
| Обложка проекта | `https://cdn.longread.agency/demo/project-cover.webp` |
