Markdown4D is a CommonMark / GFM markdown library written in Delphi. It parses markdown into a typed AST, renders HTML, writes markdown back out, and ships custom-drawn viewer and editor components for VCL and FMX. Everything is plain Object Pascal on top of the RTL; rendering happens on a canvas, without an embedded browser.
Markdown4D Studio, the editor example, in the light and the dark theme. Source
on the left, TMarkdownEditor; rendered document on the right,
TMarkdownViewer. The table, the bar chart, the flowchart and the highlighted
code are all drawn on the canvas from the markdown you see next to them.
Markdown is a handy way to give plain text a visual shape, and Delphi had no
component that rendered it well, at runtime or on the form designer. So we
built one, starting from a parser rather than a shortcut: Markdown4D passes
all 652 official CommonMark examples, and the library is interface-based
throughout, handing you a typed IMarkdownDocument rather than a string of
HTML.
VCL and FMX are both supported, with no external dependencies. Charts, mermaid diagrams and LaTeX formulas are drawn natively, alongside the usual markdown constructs: tables, task lists, links, raw HTML.
The pipeline builder accepts inline and block syntax of your own. The renderer turns a document into HTML, the writer turns it back into markdown, so a round trip through the tree gets you clean markdown out the other end. And it streams, if that is what you need.
An incremental parser reparses only the region that changed. That is what makes streaming practical: a log that grows, an import reporting as it runs, a model answering a token at a time. It is also what keeps an editor responsive on a large document.
Everything under Source\ was written for this project and uses only the RTL:
no DLL of its own, no package manager involved. Delphi 12 Athens and Delphi
13, MIT licensed.
| Area | What you get |
|---|---|
| CommonMark 0.31.2 + GFM | 652/652 official examples; tables, task lists, strikethrough, extended autolinks |
| Public AST | Typed node interfaces, a visitor, and a round-trip writer back to clean markdown |
| Incremental parser | Reparses only the changed region, which is what keeps an editor fast and a stream practical |
| VCL & FMX viewer and editor | One API on both frameworks: theming, selection, find, syntax-highlighted source, a live preview |
| Chart extension | chart fences drawn natively: bar, line, pie, doughnut, radar, scatter |
| Mermaid extension | mermaid fences drawn natively: flowchart, sequence, pie |
| Math | $...$ and $$ blocks set on the canvas: fractions, roots, limits, matrices, stretchy delimiters; \(...\) HTML for KaTeX and MathJax |
| Raw HTML in the viewer | The allowed subset renders through the ordinary path; <script> and <style> are dropped with their content |
| Extension API | Block/inline parsers, delimiter processors, renderer hooks, document processors, block overrides |
The document builder, the table of contents, the HTML renderer's safety modes and the SVG engine are documented in docs/API.md.
Markdown to HTML:
uses
Markdown4D;
const Html = TMarkdown.ToHtml('# Hello *world*');ToHtml renders safely: raw HTML is omitted and scripting destinations such as
javascript: are emptied. For byte-for-byte specification output on input you
trust, use TMarkdown.ToUnsafeHtml.
A configured pipeline (GFM, raw HTML allowed):
uses
Markdown4D.Pipeline,
Markdown4D.Extensions.Interfaces;
const Html = TMarkdownPipeline.Create
.UseGfm
.UnsafeHtml
.Build
.ToHtml(Source);A viewer on a VCL form:
uses
Markdown4D.Theme,
Markdown4D.Vcl.Viewer;
const Viewer = TMarkdownViewer.Create(Self);
Viewer.Parent := Self;
Viewer.Align := alClient;
Viewer.ThemePreset := TMarkdownThemePreset.Dark;
Viewer.Text := '# Welcome'#10#10 + 'This is **Markdown4D**.';Text that arrives in pieces. The viewer reparses incrementally, debounces relayout and follows the tail:
procedure TReportForm.OnChunkReceived(const Chunk: string);
begin
FViewer.AppendMarkdown(Chunk);
end;A chunk may split a word, a **bold** span, a fenced block or a table row; the
incremental parser reconciles it when the next chunk completes it. That covers a
log that grows, an import that reports as it runs, a document assembled on the
fly, and a model that answers token by token.
AppendMarkdown is safe to call from a worker thread; it marshals to the UI
thread for you. See docs/STREAMING.md.
The same thing running: source on the left, live preview on the right, text
arriving a chunk at a time. The chart and the diagram appear as their fences
close. Nothing here is a browser, and the animation itself is rendered by the
library through tools\Make-Demo.ps1 rather than captured off a screen.
Markdown4D ships as source, all of it, under the MIT licence. Add these folders to your project:
Source\Core framework-neutral parser, AST, renderer, writer, extensions
Source\Layout framework-neutral layout engine, theme, viewer/editor models,
rasterizer, SVG engine
Source\Vcl VCL painter, viewer, editor
Source\Fmx FMX painter, viewer, editor
If you only render to HTML, Source\Core is all you need.
For the design-time components, build the packages in packages\ and install
the two design packages in the IDE. The full instructions are in
packages/INSTALL.md.
The Examples\ folder contains four runnable projects:
| Project | Framework | Shows |
|---|---|---|
Markdown4DStudioVCL |
VCL | Editor + live preview + table of contents, with native charts, mermaid diagrams and formulas |
StreamingMarkdownVCL |
VCL | Text streamed into a chat-style window: incremental render, async images, live charts, diagrams and formulas |
Markdown4DStudioFMX |
FMX | Editor + live preview, with native charts, mermaid diagrams and formulas |
StreamingMarkdownFMX |
FMX | The same streaming window on FireMonkey, with live charts, diagrams and formulas |
Markdown4D is strictly layered. Core and Layout are framework-neutral; only
the outermost layer knows about VCL or FMX.
+----------------------+ +----------------------+
VCL app | Source\Vcl | | Source\Fmx | FMX app
| Painter / Viewer | | Painter / Viewer |
| Editor | | Editor |
+----------+-----------+ +-----------+----------+
| |
+---------------+--------------+
|
+---------------------v---------------------+
| Source\Layout | framework-neutral
| Layout engine, display list, theme, |
| hit-testing, viewer and editor models, |
| block overrides (charts, mermaid) |
+---------------------+---------------------+
|
+---------------------v---------------------+
| Source\Core | framework-neutral
| Parser (blocks and inlines), incremental |
| parser, AST, HTML renderer, markdown |
| writer, TOC, extensions, pipeline |
| builder |
+-------------------------------------------+
A single string of markdown flows through
source → pipeline → AST → (HTML renderer | markdown writer | layout engine → display list → painter).
The suite runs the CommonMark and GFM specification corpora plus round-trip and
incremental parsing corpora on every build. The table below is regenerated by
build.bat.
| Corpus | Test cases | Passed | Pass rate |
|---|---|---|---|
| CommonMark | 26 | 26 | 100.0% |
| Gfm | 5 | 5 | 100.0% |
| Math | 19 | 19 | 100.0% |
| RoundTrip | 31 | 31 | 100.0% |
| Incremental | 63 | 63 | 100.0% |
| Total | 144 | 144 | 100.0% |
A test case runs a group of specification examples rather than a single one, so
the counts above are groups. The CommonMark corpus behind them covers all 652
official examples of version 0.31.2, the GFM corpus covers the extension
examples, and the math corpus covers the $ syntax.
Run the build script from the repository root:
build.batIt compiles and runs the DUnitX main and FMX test suites, builds every example and every package, and regenerates the conformance dashboard above.
- docs/API.md covers the public surface: facade, pipeline, AST, builder, TOC, theme, math, and the viewer and editor components.
- docs/EXTENSIONS.md explains how to write extensions:
the
==mark==parser extension, an admonition custom-rendering walkthrough on theIExtensionCanvas, and the bundled chart and mermaid extensions. - docs/STREAMING.md is the streaming integration guide:
AppendMarkdown, debounce, threading, charts andTextsemantics. - packages/INSTALL.md describes the package build and the IDE install.
No third-party code. Every line under Source\ is written for this project,
including the anti-aliased polygon rasterizer, the SVG engine and the formula
layout engine behind the viewers.
One font travels with it. Source\Fonts\STIXTwoMath-Regular.otf is STIX Two
Math by the STIX Fonts project, under the SIL Open Font License 1.1
(Source\Fonts\OFL.txt). The VCL and FMX packages compile it in as a resource;
an application installs it for its own process by adding
Markdown4D.Vcl.MathFont or Markdown4D.Fmx.MathFont to a uses clause, as the
examples do. Leave that unit out and formulas use the math font the platform
ships with, Cambria Math on Windows and STIX Two Math on macOS.
Two things an SVG needs from the machine it runs on, glyph outlines and image decoding, are reached through seams. The system font engine and the VCL picture classes answer them on Windows, and FMX answers them everywhere it runs, so the library itself adds nothing to what you deploy.
One footnote, because it is visible in the build output: the FMX examples set
GlobalUseSkia := True, which switches FireMonkey to its Skia canvas for
accurate text metrics in the editor and brings sk4d.dll along. That is a
choice of those examples, not a requirement of Markdown4D. The VCL examples ship
as a single executable.
The specification corpora under Tests\specs come from the CommonMark and GFM
specifications; see Tests/specs/README.md for their
origin and licence.
Markdown4D is released under the MIT License.
Copyright (c) 2026 GDK Software
Markdown4D is MIT licensed, so it is free to use. For companies we offer a support and maintenance contract, including sponsored development of the features you need. Get in touch at gdksoftware.com/contact-us, or open an issue.
Markdown4D is developed by GDK Software, a software company building Delphi developer tools, MCP integrations, and enterprise Delphi applications.


