ADR-011 — Markdown and renderer selection
ADR |
ADR-011 |
|---|---|
Title |
Markdown and renderer selection |
State |
Accepted |
Author |
klenkes74 |
Decision Body |
klenkes74 |
Valid from |
2025-10-25 |
Expires |
./. |
1. Context
Content in the application may be edited by humans and needs to be rendered into HTML for server-side templates (JTE). Requirements: human-editable source, stable diffs in VCS, CommonMark/GFM features, XSS-safe output, maintainability and reasonable runtime behaviour.
2. Decision Drivers
-
Editor-friendliness and portability of stored content
-
Security: protection against XSS
-
Feature completeness (tables, task lists, autolinks, etc.)
-
Active maintenance and ecosystem
-
Ease of integration with Spring Boot and JTE
-
Runtime performance and caching capabilities
3. Decision
Store author content as Markdown and render server-side using flexmark-java.
After rendering, sanitize produced HTML (e.g. OWASP Java HTML Sanitizer) and cache sanitized HTML where appropriate before injecting unescaped into JTE templates.
4. Consequences
Pros:
-
Markdown bleibt menschlich lesbar, vektorisch diffbar und portabel.
-
Zentrale Rendering-Pipeline erlaubt einheitliche Feature-Policies.
-
flexmark-javabietet breite CommonMark/GFM-Unterstützung und Erweiterungen. -
Sanitization step reduziert XSS risk; zentrale Kontrolle über erlaubte HTML-Elemente.
-
Möglichkeit, gerendertes HTML zu cachen und so Laufzeitkosten zu reduzieren.
Cons:
-
Zusätzlicher Build-/Runtime-Abhängigkeit \(flexmark\) und optional Sanitizer.
-
Laufzeitaufwand für Render+Sanitize (mit Caching beherrschbar).
-
Migrationsaufwand beim Ersetzen bestehender HTML-speicherungs-Strategien.
5. Options
5.1. Option 1: Store Markdown, render with flexmark-java (recommended)
Pros:
-
Full CommonMark compliance, many official extensions.
-
Active maintenance and good documentation.
-
Fine-grained rendering options and good integration with sanitizers.
-
Centralized control of rendering policy; portable content.
Cons:
-
Larger dependency footprint than minimal libraries.
-
Slightly more complex configuration.
Implementation notes:
-
Add dependency:
com.vladsch.flexmark:flexmark-all:0.62.2. -
Typical flow: parse with
Parser.builder().extensions(…), render withHtmlRenderer, sanitize result and cache.
5.2. Option 2: Store Markdown, use txtmark (lightweight)
Pros:
-
Small, simple API; low footprint.
-
Minimal changes if already present.
Cons:
-
Limited CommonMark/GFM support and fewer extensions.
-
Less active maintenance; harder to reach feature parity.
5.3. Option 3: Store HTML directly
Pros:
-
No render step at read time; exact WYSIWYG output from editors.
-
Simpler runtime if input is guaranteed safe.
Cons:
-
High XSS risk if input sanitization is missed.
-
Poor VCS diffs and portability; inconsistent markup from different editors.
-
Harder to enforce centralized rendering policy.
6. Discussion: single decision rationale
Storing Markdown preserves human editability and portability, and enables uniform rendering rules and easier migration.
Rendering server-side with flexmark-java gives the most feature coverage and configurability among JVM libraries; pairing it with a robust sanitizer addresses security concerns.
Caching rendered+sanitized HTML mitigates runtime cost.
Choosing to store raw HTML trades security and portability for slightly simpler runtime behaviour but is not recommended for the project requirements.