ADR 0069: Markdown Preview — инструмент MFD, renderer-first decoupling и отказ от inline preview в документе¶
Статус: Accepted · Implemented
Дата: 2026-04-19
Заменяет по архитектуре surface/placement: 0026 (исторический канон markdown_preview_placement / forward_split).
Связанные ADR¶
| ADR | Роль |
|---|---|
| 0021 | PFD vs MFD; длинные тексты и вторичные потоки — в MFD |
| 0023 | Markdown authoring, диаграммы, export expanded |
| 0026 | прежний канон размещения; этим ADR superseded по архитектуре surface/placement |
| 0035 | WebView на MFD как отдельный доверенный/ограниченный слой, не базовый renderer |
| 0036 | канал → surface |
| 0066 | инструмент vs хром IDE |
| 0068 | разделение payload / projection / slot |
Резюме¶
- Markdown Preview — инструмент MFD, не обязательная часть вкладки документа.
- Renderer-first: native Markdig по умолчанию; WebView — optional adaptor (0035).
forward_splitснят с канона; заменяет 0026.- Authoring (0023) ортогонален preview.
Контекст¶
Текущая реализация preview Markdown выросла как виджет внутри документа (DockDocumentView, forward_split) с дополнительным окном и незавершённым mfd-маршрутом из 0026. На практике это привело к неверной связности:
- Документ зависит от preview-renderer'а. Падение или бинарная несовместимость preview-библиотеки ломает открытие файла как таковое.
- Placement и renderer смешаны. Inline preview в документе одновременно решает где показывать и чем рендерить.
forward_splitпротиворечит модели внимания. Для длинных Markdown/docos превью в лобовом редакторе отнимает площадь у primary work surface, хотя по 0021 чтение длинных вторичных материалов естественнее для MFD, а не для PFD и не для primary forward surface.- В продукте уже существует authoring-линия Markdown: include, Kroki/diagram expansion, export expanded, потенциальное authoring-расширение поверх Markdown (0023). Preview должен быть потребителем результата authoring-пайплайна, а не архитектурным хозяином Markdown-файла.
Дополнительный триггер: inline preview, жёстко зависящий от стороннего Avalonia Markdown-renderer, стал источником runtime-крэша при открытии документа. Это подтвердило, что preview нужно изолировать как инструмент, а не как обязательную часть жизненного цикла вкладки документа.
Решение¶
1. Preview Markdown больше не живёт внутри DockDocumentView¶
DockDocumentView и редактор документа не должны содержать обязательный preview-renderer в визуальном дереве по умолчанию.
Инвариант: файл Markdown открывается и редактируется даже если ни один preview renderer недоступен или временно падает.
forward_split как основная архитектурная форма снимается с канона. Мы не вводим deprecated-режим ради совместимости: продукт пока не обязан сохранять старую UX-топологию.
2. Preview Markdown становится отдельным инструментом (tool surface)¶
Preview рассматривается как отдельный инструмент / вторичная поверхность, а не как “часть документа”. Базовое целевое размещение:
- Primary:
mfd_tool - Secondary:
separate_window
PFD для preview не используется: по 0021 PFD держит situational awareness и текущий контекст, а не длинные тексты/доки.
3. Placement и renderer — две независимые оси¶
Нужно явно разделить:
| Ось | Вопрос |
|---|---|
| Placement | Где показать preview: MFD tool, отдельное окно, в будущем иная secondary surface |
| Renderer | Чем рендерить markdown: native renderer, WebView renderer, fallback-заглушка |
Инвариант: смена renderer'а не должна менять семантику surface, а смена placement не должна требовать другой модели данных preview.
4. Канон renderer'ов: native first, WebView optional¶
Базовый канон:
native_markdig— целевой основной renderer.webview_html— отдельный renderer/adaptor, допустимый только как secondary MFD-oriented surface или отдельное окно; не базовый путь.disabled/unavailable— явный fallback без падения документа.
Почему native_markdig:
- лучше контролируется из Avalonia-host без жёсткой зависимости от веб-стека;
- легче держать внутри модели surfaces/tools;
- проще встроить в authoring pipeline и подчинить продуктовым ограничениям;
- не ломает PFD/MFD-семантику и не делает preview “маленьким браузером по умолчанию”.
Почему webview_html всё равно нужен:
- он уже планируется по 0035;
- он полезен для richer HTML-like rendering, когда MFD сознательно выступает вторичной rich surface.
Но WebView не становится каноном preview как такового: это только один renderer-adaptor.
5. Preview потребляет authoring pipeline, а не владеет им¶
Preview-слой получает уже подготовленный source payload:
- raw markdown,
- expanded markdown (после include / diagram expansion),
- metadata (title, source file, origin, возможно link-map / anchor map),
- renderer options.
Authoring-расширение Markdown остаётся отдельной линией продукта:
- оно отвечает за authoring affordances;
- preview отвечает только за presentation уже сформированного payload;
- contract публикации /
export expanded markdownиз 0023 остаётся приоритетнее, чем “ещё один красивый runtime renderer”.
6. Рекомендуемая модель в коде¶
Вводится явная абстракция наподобие:
MarkdownPreviewSource/MarkdownPreviewPayloadIMarkdownPreviewRendererMarkdownPreviewToolViewModelMarkdownPreviewToolView
Минимальный renderer-contract:
- принять payload preview,
- либо вернуть Avalonia
Control, - либо обновить уже существующий host,
- при сбое деградировать в “preview unavailable”, а не бросать исключение наружу в документ/tool host.
Последствия¶
Позитивные¶
- Открытие документа перестаёт зависеть от preview renderer'а.
- Архитектура лучше совпадает с 0021: длинное чтение и rich preview — в MFD, не в PFD и не в forward core.
- Легче добавлять несколько renderer'ов без перешивания всей UI-топологии.
- Authoring extension Markdown может эволюционировать отдельно от визуального preview.
Стоимость¶
- Придётся снять старый
forward_splitпуть и переподключить UX-команды preview. - Нужен новый tool/page в secondary shell.
- Нужен собственный native renderer поверх
Markdigвместо reliance на случайный сторонний Avalonia Markdown control как фундамент.
Не-цели¶
- Не делать сейчас полноценный WYSIWYG-редактор Markdown.
- Не обещать пиксельную совместимость с GitHub/VS Code preview.
- Не превращать preview в общий браузерный runtime для любых rich surfaces.
- Не переносить preview в PFD.
Изменение канона по сравнению с ADR 0026¶
Этот ADR superseded 0026 в части:
forward_splitкак канонического placement,- embedding preview внутрь
DockDocumentView, - implicit coupling между placement и renderer.
Из 0026 сохраняют смысл, но читаются через новый слой:
- preview как secondary surface, а не часть authoring semantics;
- внутренние ссылки/peek как UX-возможность preview;
- отдельное окно как допустимый secondary placement.
Альтернативы¶
| Вариант | Почему отклонён |
|---|---|
| Оставить inline preview в документе и только поменять библиотеку | Не решает архитектурную связность: документ всё ещё зависит от preview |
| Сделать WebView базовым renderer'ом для всего preview | Слишком тяжёлый и вторгающийся центр тяжести; хуже для native surface-модели |
| Держать только отдельное окно и не делать MFD tool | Противоречит целевой роли MFD как secondary instrument surface |