| 1 | # ADR 0023: Markdown + диаграммы (Mermaid/PlantUML) — first-class опыт через LSP и workflow |
| 2 | |
| 3 | **Статус:** Proposed |
| 4 | **Дата:** 2026-04-08 |
| 5 | |
| 6 | ## Связанные ADR |
| 7 | |
| 8 | | ADR | Роль | |
| 9 | |-----|------| |
| 10 | | [0015](0015-editor-toml-syntax-highlighting.md) | TextMate подсветка как быстрый baseline | |
| 11 | | [0008](0008-mcp-contracts-and-testable-infrastructure.md) | внешние процессы и тестируемые абстракции | |
| 12 | | [0021](0021-pfd-mfd-cockpit-attention-model.md) | модель внимания кокпита | |
| 13 | | [0026](0026-markdown-preview-surfaces-and-placement.md) | **где** монтируется виджет превью Markdown — `workspace.toml`; канон по размещению превью | |
| 14 | |
| 15 | ## Резюме |
| 16 | |
| 17 | - Markdown + **Mermaid/PlantUML** — first-class через LSP и workflow. |
| 18 | - Kroki, export expanded, authoring — **ортогонально** preview ([0069](0069-markdown-preview-tool-surface-and-renderer-decoupling.md)). |
| 19 | |
| 20 | --- |
| 21 | ## Контекст |
| 22 | |
| 23 | В repo и в рабочих сценариях много `*.md`, а также Mermaid/PlantUML диаграмм (часто прямо в fenced-блоках). Комфорт работы с ними обычно хуже, чем с C# (диагностики, completion, навигация, rename ссылок, быстрый цикл “редактирую → вижу результат”). |
| 24 | |
| 25 | Важные ограничения: |
| 26 | |
| 27 | - Markdown — контейнер: внутри fenced-блоков живут “вложенные языки”, но LSP обычно работает по файлу, а не по диапазонам. |
| 28 | - “Сделать как C#” для fenced-блоков требует сложной инфраструктуры: виртуальные документы, двусторонний маппинг координат/диагностик, синхронизация edits. |
| 29 | - Для диаграмм есть разные бэкенды рендера (локально, PlantUML Server, Kroki). Для части команд (например, Kroki/PlantUML server) исходник диаграммы уходит на внешний сервер — это влияет на приватность. |
| 30 | |
| 31 | --- |
| 32 | |
| 33 | ## Решение |
| 34 | |
| 35 | Принять инкрементальный путь “80% ценности быстро”: |
| 36 | |
| 37 | 1. **Markdown становится first-class через Markdown LSP (`marksman`) как внешний процесс.** |
| 38 | Цель: ссылки/якоря/викилинки, go-to-definition, references, rename, базовые диагностики — на всём массиве `*.md`. |
| 39 | |
| 40 | 2. **PlantUML получает LSP на уровне отдельного файла (`*.puml` / `*.plantuml`) через `plantuml-lsp` как внешний процесс.** |
| 41 | Цель: completion/hover/diagnostics в “настоящем” документе PlantUML, без инъекции в Markdown на v1. |
| 42 | |
| 43 | 3. **Mermaid (и PlantUML внутри Markdown) на v1 обеспечиваются через:** |
| 44 | - baseline: **TextMate подсветка**, snippets/шаблоны (при необходимости), |
| 45 | - **превью/рендер** в Markdown (встроенный workflow IDE), |
| 46 | - **workflow-команды** для извлечения диаграмм из Markdown в отдельные `*.mmd`/`*.puml` файлы, когда нужен “языковой” опыт (LSP, навигация, диагностики). |
| 47 | |
| 48 | 4. **Инъекцию LSP в fenced-блоки Markdown (виртуальные документы) — отложить** как отдельный ADR/фаза, после того как: |
| 49 | - Markdown LSP стабилен, |
| 50 | - выделены UX-правила (как показывать диагностики внутри Markdown, как делать quick-fix), |
| 51 | - решены вопросы приватности/офлайна для рендера диаграмм. |
| 52 | |
| 53 | --- |
| 54 | |
| 55 | ## Канон хранения диаграмм + include-директива |
| 56 | |
| 57 | **Каноничный формат хранения диаграмм — отдельные файлы** рядом с документацией: |
| 58 | |
| 59 | - Mermaid: `*.mmd` (или `*.mermaid`) |
| 60 | - PlantUML: `*.puml` / `*.plantuml` |
| 61 | |
| 62 | Markdown (`*.md`) использует fenced-блоки **по необходимости**, но предпочитает **встраивание через include** для: |
| 63 | |
| 64 | - реюза диаграмм, |
| 65 | - более чистых диффов, |
| 66 | - включения LSP на уровне “настоящего файла” (`plantuml-lsp` для `*.puml`), |
| 67 | - возможности “как C# rename” (обновление ссылок/путей). |
| 68 | |
| 69 | **Синтаксис include (одна строка, совместим с паттерном из repo `resume`):** |
| 70 | |
| 71 | ```mermaid |
| 72 | {{ INCLUDE: example.mmd }} |
| 73 | ``` |
| 74 | |
| 75 | ```plantuml |
| 76 | {{ INCLUDE: example.puml }} |
| 77 | ``` |
| 78 | |
| 79 | Опционально (необязательно для MVP, но полезно для больших разделов): `INCLUDE_MANIFEST`, `INCLUDE_GLOB` — как в `resume`. |
| 80 | |
| 81 | Правила (v1, ориентир): |
| 82 | |
| 83 | - директива **case-insensitive** (`INCLUDE`/`include`) и допускает пробелы; |
| 84 | - путь по умолчанию считается **relative к файлу `*.md`**, в котором находится fenced-блок (в отличие от `resume`, где пути от корня репо); |
| 85 | - ограничить глубину include (например, max depth 5) и детектить циклы; |
| 86 | - ошибки include (файл не найден, цикл, слишком глубоко) должны отображаться в превью как понятная диагностика. |
| 87 | |
| 88 | --- |
| 89 | |
| 90 | ## Публикация (чтобы не “сломать внешний Markdown”) |
| 91 | |
| 92 | Include-директивы (`{{ INCLUDE: ... }}` и варианты) — **не являются стандартом Markdown** и вне CascadeIDE могут ломать рендер диаграмм. |
| 93 | |
| 94 | Принцип: |
| 95 | |
| 96 | - **Внутри CascadeIDE / в исходниках** можно держать include-структуру (authoring convenience). |
| 97 | - **Публиковать/шарить наружу** (GitHub/GitLab/Confluence/…): только **собранные/развёрнутые** варианты Markdown, где include уже заменён на реальный текст диаграмм/фрагментов. |
| 98 | |
| 99 | Следствие (требование к продукту): |
| 100 | |
| 101 | - IDE должна предоставлять явный путь “**Export / Build expanded Markdown**” (команда/операция), чтобы пользователь мог получить переносимую версию документа для публикации. |
| 102 | |
| 103 | --- |
| 104 | |
| 105 | ## Детали UX (ориентир) |
| 106 | |
| 107 | - **Размещение виджета превью Markdown** (forward / окно / MFD, TOML) — **[0026](0026-markdown-preview-surfaces-and-placement.md)**; здесь — только язык, диаграммы и workflow-команды. |
| 108 | - Для диаграмм — явный “порог доверия”: |
| 109 | - если рендер идёт через сервер (Kroki/PlantUML server), в настройках есть выключатель и URL; |
| 110 | - офлайн/приватный режим — через свой инстанс (или отключение сетевого рендера). |
| 111 | - **Команды workflow (MVP):** |
| 112 | - “Extract diagram to file…” (из fenced `mermaid`/`plantuml` → `*.mmd`/`*.puml` + ссылка/инклюд обратно), |
| 113 | - “Open diagram in dedicated editor” (как быстрый переход к отдельному файлу или к виртуальному документу в будущем), |
| 114 | - “Render diagram” (обновить превью/картинку по требованию, без постоянного polling). |
| 115 | |
| 116 | --- |
| 117 | |
| 118 | ## Последствия |
| 119 | |
| 120 | - Markdown станет комфортнее сразу (LSP на уровне файлов). |
| 121 | - PlantUML получит “как язык” опыт там, где это реально нужно — в `*.puml`. |
| 122 | - Для fenced-блоков останется разрыв (нет полноценного LSP внутри Markdown), но появится быстрый путь “вынести и жить нормально”. |
| 123 | - Появится инфраструктура внешних LSP-процессов, которую можно расширять на другие языки. |
| 124 | |
| 125 | --- |
| 126 | |
| 127 | ## Отклонённые альтернативы |
| 128 | |
| 129 | - **Сразу делать LSP-инъекцию в fenced-блоки Markdown** — отклонено как слишком большой объём/риск для v1 (сложная синхронизация и маппинг диагностик). |
| 130 | - **Опереться только на превью диаграмм без LSP** — отклонено: цель не только “видеть картинку”, но и “набирать как язык”. |
| 131 | - **Встраивать LSP как библиотеку in-process** — отклонено: легче обновлять/заменять внешние LSP-серверы, и ниже риск раздувания зависимостей IDE. |
| 132 | |
| 133 | --- |
| 134 | |
| 135 | ## Открытые вопросы |
| 136 | |
| 137 | - Где хранить и как настраивать пути к `marksman` / `plantuml-lsp` (system PATH vs встроенный менеджер инструментов). |
| 138 | - Поддержка `.mmd` как отдельного документа: нужен ли отдельный “Mermaid mode” (подсветка/snippets/валидация) без полноценного LSP. |
| 139 | - Какой формат ссылки из Markdown на вынесенную диаграмму (обычная ссылка на файл, embed-картинка, include-pragma). |
| 140 | |
| 141 | |