Avalonia.Controls.Markdown
12.3.0
Prefix Reserved
See the version list below for details.
dotnet add package Avalonia.Controls.Markdown --version 12.3.0
NuGet\Install-Package Avalonia.Controls.Markdown -Version 12.3.0
<PackageReference Include="Avalonia.Controls.Markdown" Version="12.3.0" />
<PackageVersion Include="Avalonia.Controls.Markdown" Version="12.3.0" />
<PackageReference Include="Avalonia.Controls.Markdown" />
paket add Avalonia.Controls.Markdown --version 12.3.0
#r "nuget: Avalonia.Controls.Markdown, 12.3.0"
#:package Avalonia.Controls.Markdown@12.3.0
#addin nuget:?package=Avalonia.Controls.Markdown&version=12.3.0
#tool nuget:?package=Avalonia.Controls.Markdown&version=12.3.0
Avalonia.Controls.Markdown
The Avalonia.Controls.Markdown package provides a Markdown rendering control for Avalonia applications. It enables you to display Markdown-formatted text with support for common Markdown features and styling.
Features
- Render Markdown content
- Styling support with named resources
Quick Start
Add the Avalonia.Controls.Markdown package to your Avalonia project.
XAML Usage
<Markdown xml:space="preserve">
# Markdown
## Headings
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6
**Bold Text**
*Italic Text*
~~Strikethrough~~
__Bold__ and _Italic_
[Link to Avalonia](https://avaloniaui.net)
`Inline code`
- Unordered list item 1
- Unordered list item 2
- Nested item 2a
- Nested item 2b
---
1. Ordered list item 1
2. Ordered list item 2
1. Nested ordered 2a
2. Nested ordered 2b
---
> Blockquote example
>> Nested blockquote
---
| Header 1 | Header 2 |
|----------|----------|
| Cell 1 | Cell 2 |
| Cell 3 | Cell 4 |

</Markdown>
C# Usage
var markdown = new Markdown
{
Text = "# Hello, Markdown!"
};
Documentation: https://docs.avaloniaui.net/controls/data-display/text-display/markdown
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Avalonia (>= 12.0.3)
- Avalonia.Controls.Documents (>= 12.3.0)
- Avalonia.Controls.Documents.Serialization.Html (>= 12.3.0)
- AvaloniaUI.Licensing (>= 3.1.2)
- Markdig.Signed (>= 1.0.0)
-
net8.0
- Avalonia (>= 12.0.3)
- Avalonia.Controls.Documents (>= 12.3.0)
- Avalonia.Controls.Documents.Serialization.Html (>= 12.3.0)
- AvaloniaUI.Licensing (>= 3.1.2)
- Markdig.Signed (>= 1.0.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Avalonia.Controls.Markdown:
| Package | Downloads |
|---|---|
|
Avalonia.Controls.Markdown.TextMate
Optional TextMate-based syntax highlighting integration for Avalonia.Controls.Markdown |
|
|
Avalonia.Controls.Markdown.ColorCode
Optional ColorCode-based syntax highlighting integration for Avalonia.Controls.Markdown |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 13.0.0-rc2 | 123 | 9/10/2026 |
| 12.3.0 | 671 | 9/11/2026 |
| 12.2.3 | 2,272 | 8/20/2026 |
| 12.2.2 | 23,998 | 7/31/2026 |
| 12.2.1 | 486 | 7/29/2026 |
| 12.2.0 | 10,046 | 7/23/2026 |
| 12.1.5 | 8,982 | 6/29/2026 |
| 12.1.4 | 4,799 | 6/22/2026 |
| 12.1.3 | 619 | 6/9/2026 |
| 12.1.2 | 664 | 6/2/2026 |
| 12.1.1 | 1,078 | 5/14/2026 |
| 12.1.0 | 352 | 5/12/2026 |
| 12.0.0 | 5,551 | 4/7/2026 |
| 11.3.5 | 16,343 | 3/3/2026 |
| 11.3.4 | 4,483 | 12/4/2025 |
| 11.3.3 | 383 | 12/3/2025 |
| 11.3.2 | 715 | 11/24/2025 |
| 11.3.1 | 3,364 | 11/17/2025 |
| 11.3.0 | 1,244 | 10/13/2025 |
## 12.3.0
Adds to 12.2.3 and removes nothing: every type and member a 12.2.3 build could reference is still there with the same signature, checked against the released packages on every build.
### Features
- `MarkdownSerializer` now writes markdown: `Serialize` no longer throws, and a `Serialize(DocumentSnapshot)` string convenience was added. Documents loaded from markdown (or authored with the markdown-specific elements) round-trip to an equivalent document; output spellings (bullet marker, emphasis and fence characters, ordered delimiter, hard-break form) are configurable via the new `MarkdownSerializerOptions` on the `Options` property. Grid-table writing and YAML front matter are not covered.
- New typed markdown elements make fidelity data survive editing sessions and enable authoring through the FlowDocument API: `MarkdownHeading` (`Level`), `MarkdownAlertBlock` (`AlertKind`), `MarkdownHtmlBlock` / `MarkdownHtmlInline` (`RawHtml`), plus `MarkdownImage.AltText`.
- Footnotes load onto the document's own footnote model instead of a markdown-only one: the first citation of a label becomes the note's `RichFootnoteReference` anchor, numbered in citation order, and the definition becomes a `Footnote` in `FlowDocument.Footnotes` carrying its label as the new `Footnote.Label`, so the notes render, paginate, print and export like every other document's notes and the editor's footnote commands work on them. Later citations of the same label, and citations inside a note, become `RichFootnoteCitation` elements pointing at the same note: they show its number without storing it, so adding or deleting a note renumbers every citation of it, no digit reaches the document's text, and they still write back as `[^label]`. Clicking one scrolls to its note, as clicking the anchor does; a note created in the editor is named by its position when written.
- Unedited HTML blocks write back their original source verbatim; unrecognized inline HTML tags are preserved instead of dropped.
- Footnote citations navigate: clicking an anchor or a further citation scrolls its note into view. Previously nothing handled a citation's `#label` target, so the click reached the platform launcher with a relative URI and went nowhere. A fragment that names no note - `[Back to top](#top)`, a heading anchor - is left unhandled and keeps bubbling, so an application implementing its own anchors still receives it.
- `MarkdownCodeBlock.InfoArguments` carries the rest of a fence's info string after the language identifier, so directives such as ` ```js {highlight=3} ` or ` ```text title=foo ` survive a save.
- `MarkdownNodeKinds.Marked` gives a `==marked==` span a kind of its own, and its element carries the `marked` CSS class the shipped theme styles.
- `CodeHighlighter` can be derived from. Its constructor and its abstract `Highlight` method were internal, so only the two bundled adapters could subclass it.
- `Markdown.CodeHighlighter` and `Markdown.ImageLoader` put the two extension points on the control a consumer actually places. Both are inheriting attached properties, so they reach every code block and image below them.
- `MarkdownSerializer` configures through its constructor: `new MarkdownSerializer(options, codeHighlighter)`. Both properties remain settable.
- `MarkdownSerializer` gains the synchronous `Deserialize(Stream, CancellationToken)`, `Serialize(DocumentSnapshot, Stream, CancellationToken)` and `Deserialize(string)`, and declares `CanRead`.
- `Markdown.CopyAsync` returns the task, so a caller can see a clipboard failure and sequence work after the write. `Markdown.Copy` is unchanged beside it.
### Behavioural changes
- Two generated visuals moved out of the document into the render layer, so they no longer appear as content. An alert's kind header is drawn by the alert block, and a task list item's checkbox by its marker.
- Footnotes are no longer lowered to a superscript hyperlink per citation and loose paragraphs per definition. Styles or code that targeted that lowering find `RichFootnoteReference` and a `Footnote` instead.
- `MarkdownTaskListItem` styles as `ListItem`, so a selector naming `MarkdownTaskListItem` matches nothing, with no compile error and no warning.
- The dead alert-header theme rules and resources were removed: `BlockUIContainer.alertBlockHeader`, its five `ContentControl.{kind}` icon rules and the five `MarkdownAlertBlockHeader{Kind}ContentTemplate` templates.
- `MarkdownSerializer` observes its `CancellationToken`. It was accepted and ignored: the whole parse plus snapshot render ran uninterruptibly and `MarkdownWriter.Write` took no token at all.
- `MarkdownSerializer.CanDeserialize` returns false for a null or unreadable stream instead of an unconditional true. A format-sniffing loop stopped at markdown whatever the stream's state.
### Fixes
- `BeginStreaming` keeps the document it installs when `Text` was assigned beforehand. It clears `Text` so that setting it after the session ends always reads as a change, but clearing a locally set value is itself a change, and it did so before the session was in place: the control reparsed and replaced the document the session holds, so every `Append` landed in a document the control no longer showed and the view stayed blank. Clearing the view before starting a stream, `markdown.Text = string.Empty` followed by `markdown.BeginStreaming()`, is the shape that hit it.
- The parser no longer loses data it cannot show: link titles, image alt text, footnote definition labels and grouping, the pipe-table header row, and CommonMark angle autolinks (previously dropped entirely) are all captured now; a missing image title is no longer replaced by the URL, and footnote back-links no longer pollute definition text.
- The typed markdown elements use their base type's style key (`MarkdownHeading` styles as `Paragraph`, `MarkdownAlertBlock` as `Section`, and so on), so theme and consumer selectors such as `Paragraph.h1` or `Section.alertBlock` keep matching; style these constructs via their CSS classes, not their type names. `MarkdownCodeBlock` and `MarkdownImage` keep their own keys as documented. `MarkdownTaskListItem`'s move to the `ListItem` key is a silent break - see Breaking changes.
- An inline HTML tag left unclosed no longer discards the rest of the document. `Some <b>bold text here.` followed by another paragraph parsed to a document whose entire text was "Some ", which is the state every streaming flush passes through between a model emitting `<b>` and emitting `</b>`. An unclosed tag now formats to the end of its block.
- An inline HTML close tag closes only the container its own tag opened. A stray `</b>` is preserved as raw HTML instead of vanishing from the file, and it can no longer end a link or an emphasis it did not open.
- A footnote definition nothing cites is kept. Opening a notes file holding `[^todo]: check this later` and saving it deleted the line; a file of definitions only opened and saved empty.
- A footnote label containing `]`, `[` or `\` is escaped on write. It was written raw, which ended the citation early and turned both the citation and its definition into literal text: one save destroyed the note.
- A code span whose content is only spaces no longer grows by two characters on every save.
- A table whose first row is not the header gets an empty header row instead of having its first row of data promoted into one. This affected grid tables, tables that reached the model from another format, and tables whose header row was deleted in the editor.
- An ordered task list keeps its numbering: `1. [x] done` was written back as `- [x] done`.
- A `==marked==` span is recognized by its kind, so recolouring the highlight no longer makes the next save write it as plain text with no `==`.
- An alert kind outside the theme's five (`> [!INFO]`, `> [!DANGER]`) falls back to the note styling instead of reserving a border thickness with no brush to paint it.