Forge
markdowndeeb25a2
1<!-- English translation of adr/0023-markdown-diagrams-language-tooling.md. Canonical Russian: ../../adr/0023-markdown-diagrams-language-tooling.md -->
2
3# ADR 0023: Markdown + diagrams (Mermaid/PlantUML) - first-class experience through LSP and workflow
4
5**Status:** Proposed
6**Date:** 2026-04-08
7
8## Related ADRs
9
10| ADR | Role |
11|-----|------|
12| [0015](0015-editor-toml-syntax-highlighting.md) | TextMate highlighting as a fast baseline |
13| [0008](0008-mcp-contracts-and-testable-infrastructure.md) | external processes and testable abstractions |
14| [0021](0021-pfd-mfd-cockpit-attention-model.md) | cockpit attention model |
15| [0026](0026-markdown-preview-surfaces-and-placement.md) | **where** the Markdown preview widget is mounted - `workspace.toml`; canon for posting previews |
16
17## Summary
18
19- Markdown + **Mermaid/PlantUML** - first-class via LSP and workflow.
20- Kroki, export expanded, authoring - **orthogonal** preview ([0069](0069-markdown-preview-tool-surface-and-renderer-decoupling.md)).
21
22---
23## Context
24
25There are a lot of `*.md` in repo and production scripts, as well as Mermaid/PlantUML diagrams (often right in fenced blocks). The comfort of working with them is usually worse than with C# (diagnostics, completion, navigation, rename links, quick cycle “edit → see the result”).
26
27Important restrictions:
28
29- Markdown is a container: “nested languages” live inside fenced blocks, but LSP usually works per file, not per range.
30- “Make it like C#” for fenced blocks requires a complex infrastructure: virtual documents, two-way mapping of coordinates/diagnostics, synchronization of edits.
31- There are different rendering backends for diagrams (locally, PlantUML Server, Kroki). For some commands (for example, Kroki/PlantUML server), the diagram source goes to an external server - this affects privacy.
32
33---
34
35## Solution
36
37Adopt the incremental path “80% value fast”:
38
391. **Markdown becomes first-class via Markdown LSP (`marksman`) as an external process.**
40 Goal: links/anchors/wikilinks, go-to-definition, references, rename, basic diagnostics - on the entire `*.md` array.
41
422. **PlantUML receives LSP at the individual file level (`*.puml` / `*.plantuml`) via `plantuml-lsp` as an external process.**
43 Goal: completion/hover/diagnostics in a “real” PlantUML document, without Markdown injection on v1.
44
453. **Mermaid (and PlantUML inside Markdown) on v1 is provided via:**
46 - baseline: **TextMate highlighting**, snippets/templates (if necessary),
47 - **preview/render** in Markdown (built-in workflow IDE),
48 - **workflow commands** for extracting diagrams from Markdown into separate `*.mmd`/`*.puml` files when “language” experience is needed (LSP, navigation, diagnostics).
49
504. **LSP injection into fenced Markdown blocks (virtual documents) - deferred** as a separate ADR/phase after:
51 - Markdown LSP is stable,
52 - UX rules are highlighted (how to show diagnostics inside Markdown, how to do quick-fix),
53 - solved privacy/offline issues for diagram rendering.
54
55---
56
57## Diagram storage canon + include directive
58
59**The canonical format for storing diagrams is separate files** next to the documentation:
60
61- Mermaid: `*.mmd` (or `*.mermaid`)
62- PlantUML: `*.puml` / `*.plantuml`
63
64Markdown (`*.md`) uses fenced blocks **optional**, but prefers **inlining** for:
65
66- chart revision,
67- cleaner diffs,
68- enabling LSP at the “real file” level (`plantuml-lsp` for `*.puml`),
69- “like C# rename” capabilities (updating links/paths).
70
71**Syntax include (one line, compatible with the pattern from the `resume` repo):**```mermaid
72{{ INCLUDE: example.mmd }}
73```
74
75```plantuml
76{{ INCLUDE: example.puml }}
77```
78Optional (not necessary for MVP, but useful for large sections): `INCLUDE_MANIFEST`, `INCLUDE_GLOB` - as in `resume`.
79
80Rules (v1, benchmark):
81
82- **case-insensitive** directive (`INCLUDE`/`include`) and allows spaces;
83- the default path is considered **relative to the `*.md`** file in which the fenced block is located (as opposed to `resume`, where the path is from the root of the repo);
84- limit the include depth (for example, max depth 5) and detect cycles;
85- include errors (file not found, loop, too deep) should be displayed in the preview as a clear diagnostic.
86
87---
88
89## Publishing (so as not to “break external Markdown”)
90
91Include directives (`{{ INCLUDE: ... }}` and variants) are **not a Markdown standard** and outside of CascadeIDE they can break the rendering of diagrams.
92
93Principle:
94
95- **Inside CascadeIDE / in the sources** you can keep an include structure (authoring convenience).
96- **Publish/rummage outside** (GitHub/GitLab/Confluence/…): only **assembled/expanded** Markdown variants, where include has already been replaced with the actual text of diagrams/fragments.
97
98Consequence (product requirement):
99
100- The IDE should provide an explicit path “**Export / Build expanded Markdown**” (command/operation) so that the user can get a portable version of the document to publish.
101
102---
103
104## UX details (guideline)
105
106- **Placement of the Markdown preview widget** (forward / window / MFD, TOML) - **[0026](0026-markdown-preview-surfaces-and-placement.md)**; here - only language, diagrams and workflow commands.
107- For diagrams there is an explicit “confidence threshold”:
108 - if the rendering is done through a server (Kroki/PlantUML server), there is a switch and URL in the settings;
109 - offline/private mode - through your own instance (or disabling network rendering).
110- **Workflow commands (MVP):**
111 - “Extract diagram to file...” (from fenced `mermaid`/`plantuml` → `*.mmd`/`*.puml` + link/include back),
112 - “Open diagram in dedicated editor” (as a quick transition to a separate file or to a virtual document in the future),
113 - “Render diagram” (update preview/image on demand, without constant polling).
114
115---
116
117## Consequences
118
119- Markdown will become more comfortable immediately (LSP at the file level).
120- PlantUML will get “like a language” experience where it is really needed - in `*.puml`.
121- There will be a gap for fenced blocks (there is no full-fledged LSP inside Markdown), but there will be a quick way to “take it out and live normally.”
122- An infrastructure of external LSP processes will appear, which can be extended to other languages.
123
124---
125
126## Rejected alternatives
127
128- **Immediately do LSP injection into Markdown fenced blocks** - rejected as too much volume/risk for v1 (complicated synchronization and mapping of diagnostics).
129- **Rely only on the preview of diagrams without LSP** - rejected: the goal is not only to “see the picture”, but also to “type like a language”.
130- **Embedding LSP as an in-process library** - rejected: easier to update/replace external LSP servers, and lower risk of IDE dependency bloat.
131
132---
133
134## Open questions
135
136- Where to store and how to configure paths to `marksman` / `plantuml-lsp` (system PATH vs built-in tool manager).
137- Support for `.mmd` as a separate document: is a separate “Mermaid mode” (highlighting/snippets/validation) needed without a full LSP.
138- What is the format of the link from Markdown to the rendered diagram (regular link to a file, embed image, include-pragma).
View only · write via MCP/CIDE