AvalonMarkdown 5.0.0
dotnet add package AvalonMarkdown --version 5.0.0
NuGet\Install-Package AvalonMarkdown -Version 5.0.0
<PackageReference Include="AvalonMarkdown" Version="5.0.0" />
<PackageVersion Include="AvalonMarkdown" Version="5.0.0" />
<PackageReference Include="AvalonMarkdown" />
paket add AvalonMarkdown --version 5.0.0
#r "nuget: AvalonMarkdown, 5.0.0"
#:package AvalonMarkdown@5.0.0
#addin nuget:?package=AvalonMarkdown&version=5.0.0
#tool nuget:?package=AvalonMarkdown&version=5.0.0
AvalonMarkdown
π δΈζζζ‘£
A Markdown preview control built on AvaloniaUI's NativeWebView.
Installation
dotnet add package AvalonMarkdown
Quick Start
1. Declare in XAML
<Window xmlns="https://github.com/avaloniaui"
xmlns:md="clr-namespace:AvalonMarkdown.Views;assembly=AvalonMarkdown">
<md:MarkdownView x:Name="Preview" />
</Window>
2. Data Binding (Recommended)
Bind Markdown text to the Text property; the control automatically renders and deduplicates updates:
<md:MarkdownView Text="{Binding MarkdownContent}" />
3. Event-Driven Approach
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Preview.OnReady += async (_, _) =>
{
await Preview.RenderMarkdownAsync("# Hello World\n\n**Bold** *Italic*");
};
}
}
API Reference
Properties
| Property | Type | Binding Mode | Description |
|---|---|---|---|
Text |
string? |
TwoWay | Markdown text; auto-renders with Myers diff deduplication to avoid redundant renders |
Methods
| Method | Return | Description |
|---|---|---|
RenderMarkdownAsync(string?) |
Task |
Renders Markdown content |
RestartPreviewAsync() |
Task |
Restarts the previewer (re-establishes local HTTP server + navigation) |
ApplyConfigAsync(string) |
Task |
Executes a JS config expression (e.g., "setPreviewConfig({fontSize:16})") |
InvokeScriptAsync(string) |
Task<string?> |
Executes custom JavaScript |
ApplyCustomCssAsync(string) |
Task |
Injects custom CSS to override renderer theme styles |
Events
| Event | Parameters | Trigger Condition |
|---|---|---|
OnReady |
EventHandler |
Control is fully ready (HTML loaded + JS CDN scripts loaded); safe to call RenderMarkdownAsync |
ErrorOccurred |
EventHandler<MarkdownViewErrorEventArgs> |
Internal recoverable errors (JS runtime errors / CDN load timeout / script timeout / link open failures, etc.) |
Built-in Error Panel
MarkdownView includes a built-in error panel at the bottom (initially hidden), which automatically appears when internal errors occur:
| Control | Description |
|---|---|
ErrorTitle |
Error title (red) |
ErrorMessage |
Error details (auto-wrapped) |
RetryButton |
Click to call RestartPreviewAsync() and restart the preview |
DismissErrorButton |
Click to dismiss the error panel |
Error Event Arguments
| Member | Type | Description |
|---|---|---|
Title |
string |
Error title |
Message |
string |
Error details |
Timestamp |
DateTime |
Time the error occurred |
MarkdownThemeView (Theme Editor)
A ready-to-use theme editing control that provides RGB sliders for real-time customization of the MarkdownView rendering appearance.
<md:MarkdownView x:Name="Preview" />
<md:MarkdownThemeView Target="{Binding #Preview}" />
Collapsed by default; expand the editing panel by clicking the title bar. Supports customization of:
Colors (RGB Three-Channel Sliders + Real-Time Hex Preview)
- 6 Core Colors: Background, Text, Link, Heading, Inline Code Text, Border
- 6 Extended Colors: Secondary Background, Secondary Text, Inline Code Background, Code Block Background, Table Header Background, Scrollbar (Thumb/Hover)
- Blockquote Colors: Blockquote Left Border, Blockquote Background
- Auto-Derived: Modifying core color R/G/B channels automatically updates Secondary Background, Secondary Text, Inline Code Background, Code Block Background, Table Header Background, Blockquote Border, and Scrollbar colors
Typography
| Property | Default | Description |
|---|---|---|
BodyFontSize |
14px | β |
CodeFontSize |
13px | β |
LineHeight |
1.6 | β |
BorderRadius |
6px | Code block border radius |
Mermaid Diagrams
| Property | Default | Description |
|---|---|---|
MermaidTheme |
dark |
dark / light / base |
MermaidBgHex |
#1E1E1E |
RGB three-channel slider |
MermaidContainerPadding |
8px | β |
MermaidContainerMargin |
16px | β |
MermaidBorderRadius |
4px | β |
PlantUML Diagrams
| Property | Default | Description |
|---|---|---|
PumlBgHex |
#1E1E1E |
RGB three-channel slider |
PumlContainerPadding |
12px | β |
PumlContainerMargin |
8px | β |
PumlBorderRadius |
6px | β |
PumlDarkInvert |
0.882 | CSS filter: invert() value in dark mode |
highlight.js Code Highlighting Colors
Supports independent control of the following syntax highlighting color categories:
| Group | Properties (Examples) | Default |
|---|---|---|
| Keyword / Literal / Symbol | HljsKeyword / Literal / Symbol / Name |
#569cd6 |
| Built-in / Type | HljsBuiltIn / Type |
#4ec9b0 |
| Class / Number | HljsClass / Number |
#b5cea8 |
| String / Meta-String | HljsString / MetaString |
#d69d85 |
| Title | HljsTitle / TitleClass / TitleClassInherited |
#DCDCAA / #4EC9B0 |
| Parameters / Variables | HljsParams / Variable / TemplateVariable |
#9CDCFE / #bd63c5 |
| Comments / Quotes | HljsComment / Quote |
#6a9955 |
| Attributes / Tags / Meta | HljsAttr / Attribute / Meta / Tag |
#9cdcfe / #9b9b9b / #569cd6 |
| Selectors | HljsSelectorAttr / SelectorClass / SelectorId etc. |
#d7ba7d |
| Background / Foreground | HljsBackground / Foreground |
#1e1e1e / #dcdcdc |
Auto-Push
All property changes automatically mark dirty data; a 10Hz timer periodically calls ApplyCustomCssAsync to inject updates into the bound MarkdownView control (held via WeakReference, doesn't block GC).
Rendering Capabilities
renderer.js loads third-party libraries via CDN and executes the full rendering pipeline inside the WebView:
- Markdown β markdown-it 14.1.0 + footnote 4.0.0 + task-lists 2.1.1 + strikethrough
- Math Formulas β KaTeX 0.16.11 (inline
$...$/ block$$...$$) - Code Highlighting β highlight.js 11.10.0, VS Code-style color scheme (supports full token color customization via
ApplyCustomCssAsync/ Theme Editor) - Diagrams β Mermaid 11.4.1 (flowcharts, sequence diagrams, pie charts, Git graphs, class diagrams, state diagrams)
- PlantUML β Encoded via
plantuml-encoder1.4.0 and rendered as SVG through the PlantUML online service, with dark/light theme adaptation (CSSinvert()+hue-rotate()) - Video Embedding β Supports direct video files (
.mp4/.webm/.ogg/.mov/.avi/.mkv) and auto-detection of platform URLs- YouTube β
youtube.com/watch?v=ID/youtu.be/IDβ responsive iframe embedding - Bilibili β
bilibili.com/video/BVxxxβ responsive iframe embedding - Vimeo β
vimeo.com/IDβ responsive iframe embedding
- YouTube β
- Code Blocks β Language labels Β· Copy button (with
navigator.clipboardordocument.execCommandfallback) Β· Height adjustment (+/- per-block independent control) Β· Configurable max height (maxCodeBlockHeight) - Task Lists β Custom checkboxes
- Footnotes / Tables / Blockquotes / Strikethrough
- External Links β Auto-intercepted and opened in the system browser via C# bridge (
window.openfallback for WASM environments) - Preview Configuration β Dynamic adjustment via
setPreviewConfigfor font size (fontSize), line height (lineHeight), code language label display (showCodeLanguage), copy button toggle (showCopyButton), and code block max height (maxCodeBlockHeight) - Theme Editor β Built-in
MarkdownThemeViewcontrol providing RGB sliders for real-time customization of colors, typography, Mermaid/PlantUML styles, and code highlighting colors
JS-Exposed Global Functions
| Function | Description |
|---|---|
window.renderMarkdown(text) |
Renders Markdown text to the preview area |
window.onMarkdownUpdate(text) |
Alias for renderMarkdown |
window.setPreviewConfig(config) |
Updates preview configuration and re-renders |
window.setTheme(theme) |
Switches theme ('light' / 'dark'), updates CSS class + Mermaid theme + re-renders |
window.setCustomCss(cssText) |
Replaces <style id="custom-theme-css"> content to override default styles |
window.showPreviewError(detail) |
Displays a JS runtime error overlay |
window.dismissErrorOverlay() |
Closes the JS runtime error overlay |
window.escapeHtml(s) |
HTML escape utility function |
WebView Error Handling
- C# Side:
MarkdownViewincludes a built-in bottom error panel (ErrorPanel) that automatically appears on errors, with retry and dismiss buttons - JS Side: An
error-overlayoverlay (with close button) inside the WebView is automatically triggered bywindow.onerrorandunhandledrejection - All errors are simultaneously raised via the
ErrorOccurredevent for external subscription
Cross-Platform Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MarkdownView Control β
β (Avalonia UserControl + NativeWebView) β
βββββββββββββ¬ββββββββββββ¬ββββββββββββ¬ββββββββββββ¬ββββββββββββ€
β Desktop β Browser β Android β iOS β Future β
β WebView2 β WASM β WebView β WKWebView β Platforms β
β http:// β about: β http:// β http:// β β
β 127.0.0.1 β blank + β 127.0.0.1 β 127.0.0.1 β β
β :dynport β doc.write β :dynport β :dynport β β
βββββββββββββ΄ββββββββββββ΄ββββββββββββ΄ββββββββββββ΄ββββββββββββ
Loading Strategy
All platforms use EmbeddedHtmlSourceProvider (implementing IWebViewSourceProvider) to read embedded resources at runtime and inline renderer.css / renderer.js, then follow different loading paths per platform:
- Desktop (WebView2) β Starts
LocalHtmlServer(loopbackhttp://127.0.0.1:dynamic-port) β navigates to that address- Uses
http://instead offile://to avoid same-origin policy restrictions for third-party iframes (e.g., YouTube)
- Uses
- Android / iOS β Same as Desktop: starts
LocalHtmlServerβ navigates tohttp://127.0.0.1:dynamic-port - Browser (WASM) β
about:blankβdocument.writeinjects full HTML (TCP services cannot be started within WASM sandbox)
Extension Point: The
IWebViewSourceProviderinterface allows custom HTML content sources for injecting different page structures or CDN mirror addresses.
Platform Readiness Signal Differences
| Platform | Readiness Detection Mechanism |
|---|---|
| Desktop | CDN scripts loaded by the time NavigationCompleted fires; calls SetReady() directly |
| Android | NavigationCompleted fires before CDN scripts load β polls typeof window.renderMarkdown === 'function' (200ms interval, 15s timeout) |
| iOS | Same as Android (same architecture) |
| Browser | CDN scripts executed synchronously via document.write after InjectViaDocumentWriteAsync completes |
Dependencies
| Component | Purpose | Loading Method |
|---|---|---|
| Avalonia | UI Framework | NuGet |
| Avalonia.Controls.WebView | NativeWebView Control | NuGet |
| renderer.js (inlined) | Renderer core logic | Embedded resource (inlined at build time) |
| renderer.css (inlined) | Renderer styles | Embedded resource (inlined at build time) |
| markdown-it 14.1.0 / footnote 4.0.0 / task-lists 2.1.1 | Markdown parsing | CDN (loaded at runtime) |
| highlight.js 11.10.0 | Code highlighting | CDN (loaded at runtime) |
| KaTeX 0.16.11 / katex.min.css | Math formula rendering + CSS styles | CDN (loaded at runtime) |
| Mermaid 11.4.1 | Diagram rendering | CDN (loaded at runtime) |
| plantuml-encoder 1.4.0 | PlantUML encoding | CDN (loaded at runtime) |
Network Requirements: Only
renderer.js/renderer.css/index.htmlare embedded resources inlined at build time. CDN libraries (markdown-it and plugins, highlight.js, KaTeX with CSS, Mermaid, plantuml-encoder) require runtime network loading. If CDN is blocked by network or tracking protection, only the corresponding features are affected (e.g., math formulas or diagrams fail to render); basic Markdown preview remains functional. The control includes a 15-second JS readiness timeout detection; if exceeded, an error panel is displayed.
Theme System
Supports automatic system theme following (Light / Dark), with all active instances (managed via a static WeakReference list) synchronizing reactively:
// Auto-pushed on system theme change
// 1. C# side: WebViewHost / NativeWebView background color
// 2. JS side: setTheme('light'|'dark') toggles CSS class + Mermaid theme + re-renders
- On first
MarkdownViewinstance creation, subscribes to the globalApplication.Current.ActualThemeVariantChangedevent - On theme change, iterates through the static instance list and calls
PushThemeToWebViewfor each WebView - Also updates the theme class in the HTML returned by
LocalHtmlServerto ensure consistency on restart/refresh
Real-time color customization is available via the MarkdownThemeView control; modifications are automatically injected into the WebView through the ApplyCustomCssAsync interface. A 10Hz DispatcherTimer with dirty flag ensures efficient batching, avoiding excessive script calls during rapid slider dragging.
License
MIT Β© Axvser
| 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.0)
- Avalonia.Controls.WebView (>= 12.0.0)
- Avalonia.Fonts.Inter (>= 12.0.0)
- Avalonia.Themes.Fluent (>= 12.0.0)
-
net8.0
- Avalonia (>= 12.0.0)
- Avalonia.Controls.WebView (>= 12.0.0)
- Avalonia.Fonts.Inter (>= 12.0.0)
- Avalonia.Themes.Fluent (>= 12.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.