Kryptos-FR/MarkView.Avalonia

Markdown viewer control for Avalonia

29

stars

75

commits

C#

primary language

Sep 5, 2026

updated

README

MarkView.Avalonia

NuGet Version NuGet Downloads Avalonia License CI

Markview.Avalonia logo

A Markdig-powered markdown viewer control for Avalonia UI v12. Drop MarkdownViewer into any Avalonia window or panel to render rich markdown — headings, code blocks, tables, task lists, links, images, and more — using native Avalonia controls with a fully customisable theme.

Installation

dotnet add package MarkView.Avalonia

Quick Start

Include the default theme and add MarkdownViewer to your XAML:

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mv="using:MarkView.Avalonia">
  <Window.Styles>
    <StyleInclude Source="avares://MarkView.Avalonia/Themes/MarkdownTheme.axaml" />
  </Window.Styles>

  <mv:MarkdownViewer Markdown="# Hello, MarkView!" />
</Window>
viewer.BaseUri = new Uri("https://raw.githubusercontent.com/Kryptos-FR/MarkView.Avalonia/main/");
viewer.Markdown = markdownText; // relative image paths resolved against BaseUri
viewer.LinkClicked += (_, e) =>
{
    // e.Url contains the clicked URL
    Process.Start(new ProcessStartInfo(e.Url) { UseShellExecute = true });
};

LinkClickedEvent is an Avalonia routed event (bubbles up) — subscribe globally once at app startup to handle all viewers:

// App.axaml.cs — applies to every MarkdownViewer in the application
MarkdownViewer.LinkClickedEvent.AddClassHandler<MarkdownViewer>((_, e) =>
    Process.Start(new ProcessStartInfo(e.Url) { UseShellExecute = true }));
viewer.ScrollToAnchor("my-heading");  // scrolls to the heading's anchor position

Using a custom Markdig pipeline

viewer.Pipeline = new MarkdownPipelineBuilder()
    .UseSupportedExtensions()
    .UseAlertBlocks()
    .UseFootnotes()
    .Build();

Extension Methods

Convenience methods configure a pipeline with a single opt-in feature:

viewer.UseAbbreviations();
viewer.UseAlertBlocks();
viewer.UseCitations();
viewer.UseFigures();
viewer.UseFootnotes();
viewer.UseHardlineBreaks();
viewer.UseMediaLinks();

To combine several opt-in features, build the pipeline explicitly (see above).

Application-Wide Defaults

MarkdownViewerDefaults lets you set a pipeline and/or extensions once so that every MarkdownViewer in the application inherits them automatically — no need to configure each instance:

// App.axaml.cs
MarkdownViewerDefaults.Pipeline = new MarkdownPipelineBuilder()
    .UseSupportedExtensions()
    .UseFootnotes()
    .UseAlertBlocks()
    .Build();

MarkdownViewerDefaults.Extensions.AddTextMateHighlighting();
MarkdownViewerDefaults.Extensions.AddSvg();
MarkdownViewerDefaults.Extensions.AddMermaid();

Per-instance Pipeline and Extensions take precedence over the defaults; an extension object shared between the defaults list and an instance list is only registered once per render.

Supported Markdown Features

CommonMark baseline (always on)

FeatureNotes
Headings H1–H6CommonMark
Bold, italicCommonMark
Inline codeCommonMark
Fenced code blocksCommonMark
BlockquotesCommonMark
Ordered and unordered listsCommonMark, tight and loose
Links and autolinksCommonMark + extension
ImagesCommonMark, remote URLs loaded async
Image sizing![alt](url =WxH) — inline pixel dimensions, e.g. =80x80
Thematic breaksCommonMark
Hard line breaksCommonMark (\ or two spaces)
HTML <br> / <br />Rendered as line break

Extensions (enabled by UseSupportedExtensions())

FeatureSyntax
Strikethrough~~text~~
Subscript~text~
Superscript^text^
Underline (inserted)++text++
Highlight (marked)==text==
Task lists- [x] item
Pipe tablesGFM-style | col | col |
Grid tablesRST-style grid tables
Autolinksbare https://… URLs
Emoji shortcodes:rocket: → 🚀 (ASCII smileys like :) are intentionally left as plain text)
CJK-friendly emphasisparser-only fix for emphasis next to Chinese/Japanese/Korean (CJK) punctuation
YAML front matter--- metadata block at the top of a document is parsed and hidden

Opt-in extensions

These require adding .UseXxx() to the pipeline (see Extension Methods above):

FeatureActivationSyntax
AbbreviationsUseAbbreviations()*[HTML]: …
GitHub alert blocksUseAlertBlocks()> [!NOTE] etc.
CitationsUseCitations()""quoted text""
FiguresUseFigures()^^^ / ^^^ caption
FootnotesUseFootnotes()[^1] / [^1]: …
Hardline breaksUseHardlineBreaks()every soft line break renders as a hard break
YouTube embedsUseMediaLinks()![title](https://youtu.be/…)

Extension Packages

MarkView.Avalonia ships optional NuGet packages that add richer rendering capabilities. Each package implements IMarkViewExtension and is activated via a convenience method on MarkdownViewer, or globally via MarkdownViewerDefaults.Extensions.AddXxx().

Syntax Highlighting (MarkView.Avalonia.SyntaxHighlighting)

Adds TextMate grammar-based syntax highlighting to fenced code blocks.

dotnet add package MarkView.Avalonia.SyntaxHighlighting
viewer.UseTextMateHighlighting(); // DarkPlus / LightPlus by default
// or with custom themes:
viewer.UseTextMateHighlighting(darkTheme: ThemeName.Monokai, lightTheme: ThemeName.QuietLight);

The extension replaces the built-in CodeBlockRenderer with TextMateCodeBlockRenderer, which tokenises each line and emits coloured Run elements. Unsupported languages fall back to the default monochrome rendering automatically.

Colours update in-place when the user switches between light and dark themes — no document rebuild or scroll reset.

Available ThemeName values are defined by TextMateSharp.Grammars: DarkPlus, LightPlus, Monokai, SolarizedDark, SolarizedLight, and more.

SVG Images (MarkView.Avalonia.Svg)

Renders SVG images embedded in markdown (![desc](path/to/image.svg)), including data:image/svg+xml data URIs and badge-service URLs that return SVG without a .svg extension.

dotnet add package MarkView.Avalonia.Svg
viewer.UseSvg();

The extension inserts SvgImageLoader at the front of the image loader chain. Regular raster images continue to load via the built-in HTTP fallback.

LaTeX Math (MarkView.Avalonia.Math)

Renders $...$ (inline) and $$...$$ (block) LaTeX math using CSharpMath's SkiaSharp renderer — pure .NET, no browser or WebView required.

dotnet add package MarkView.Avalonia.Math
viewer.UseMath();

Mermaid Diagrams (MarkView.Avalonia.Mermaid)

Renders fenced mermaid code blocks as SVG diagrams using the Mermaider library (pure .NET, no browser required). Works on all platforms including Linux. Diagrams re-render automatically when the user switches between light and dark themes.

dotnet add package MarkView.Avalonia.Mermaid
viewer.UseMermaid();

Markdown syntax:

```mermaid
graph TD
  A[Start] --> B{Decision}
  B -- Yes --> C[End]
  B -- No  --> A
```

Combining extensions

All four can be stacked:

viewer
    .UseTextMateHighlighting()
    .UseSvg()
    .UseMermaid()
    .UseMath();

Extensions are applied in the order they are added to viewer.Extensions. Each extension's Register method is called once per render pass, before the Markdig pipeline is set up.

Writing your own extension

Implement IMarkViewExtension from the core package:

using MarkView.Avalonia.Extensions;
using MarkView.Avalonia.Rendering;

public class MyExtension : IMarkViewExtension
{
    public void Register(AvaloniaRenderer renderer)
    {
        // swap a renderer, add an image loader, or set a code highlighter
        renderer.ObjectRenderers.ReplaceOrAdd<CodeBlockRenderer>(new MyCodeBlockRenderer());
    }
}

viewer.Extensions.Add(new MyExtension());

Theming / Customisation

Include MarkdownTheme.axaml for default styles. Override any style class in your own Styles to customise appearance:

Style classApplied toControls
markdown-h1markdown-h6HeadingsTextBlock
markdown-paragraphParagraphsTextBlock
markdown-code-blockCode blocksBorder
markdown-code-inlineInline codeBorder
markdown-blockquoteBlockquotesBorder
markdown-listListsStackPanel
markdown-thematic-breakHorizontal rulesSeparator
markdown-imageImagesImage
markdown-linkHyperlinksHyperlinkButton
markdown-tableTablesGrid
markdown-table-cellTable cellsBorder
markdown-table-headerHeader cellsBorder
markdown-markedHighlighted text (==…==)Span
markdown-alertAlert block containerBorder
markdown-alert-notemarkdown-alert-cautionPer-kind border colourBorder
markdown-alert-headerAlert kind labelTextBlock
markdown-figureFigure containerBorder
markdown-figure-captionFigure captionTextBlock
markdown-abbrAbbreviation with tooltipTextBlock
markdown-footnote-refFootnote reference linkHyperlinkButton
markdown-footnote-groupFootnote definition listStackPanel
markdown-footnote-itemIndividual footnote rowGrid

Extension packages may ship their own theme file with additional overridable colours — check the extension's README for its StyleInclude path and resource keys.

Example — increase heading size and add a bottom border:

<Style Selector="TextBlock.markdown-h1">
  <Setter Property="FontSize" Value="36" />
  <Setter Property="Foreground" Value="#1A1A2E" />
  <Setter Property="Margin" Value="0,12,0,6" />
</Style>

Text Selection

MarkdownViewer supports full document-wide text selection:

  • Click + drag to select a range.
  • Ctrl+A to select all text.
  • Ctrl+C to copy the selection to the clipboard.

Programmatic API:

viewer.SelectAll();
viewer.ClearSelection();
string text = viewer.GetSelectedText();
await viewer.CopyToClipboardAsync();

Images and task-list checkboxes are skipped during selection — see Known Limitations below.

Known Limitations

LimitationDetail
Images are non-selectableImages in inline position are embedded as InlineUIContainer — selection skips around them.
Task checkboxes are non-selectableSame reason as images.
Anchor scroll is instantBringIntoView() jumps without animation. Smooth scrolling is a future improvement.

License

MIT © Nicolas Musset

Contributors

Kryptos-FR

70 commits

Kryptos-FR/MarkView.Avalonia

Markdown viewer control for Avalonia

29

stars

75

commits

C#

primary language

Sep 5, 2026

updated

README

MarkView.Avalonia

NuGet Version NuGet Downloads Avalonia License CI

Markview.Avalonia logo

A Markdig-powered markdown viewer control for Avalonia UI v12. Drop MarkdownViewer into any Avalonia window or panel to render rich markdown — headings, code blocks, tables, task lists, links, images, and more — using native Avalonia controls with a fully customisable theme.

Installation

dotnet add package MarkView.Avalonia

Quick Start

Include the default theme and add MarkdownViewer to your XAML:

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mv="using:MarkView.Avalonia">
  <Window.Styles>
    <StyleInclude Source="avares://MarkView.Avalonia/Themes/MarkdownTheme.axaml" />
  </Window.Styles>

  <mv:MarkdownViewer Markdown="# Hello, MarkView!" />
</Window>
viewer.BaseUri = new Uri("https://raw.githubusercontent.com/Kryptos-FR/MarkView.Avalonia/main/");
viewer.Markdown = markdownText; // relative image paths resolved against BaseUri
viewer.LinkClicked += (_, e) =>
{
    // e.Url contains the clicked URL
    Process.Start(new ProcessStartInfo(e.Url) { UseShellExecute = true });
};

LinkClickedEvent is an Avalonia routed event (bubbles up) — subscribe globally once at app startup to handle all viewers:

// App.axaml.cs — applies to every MarkdownViewer in the application
MarkdownViewer.LinkClickedEvent.AddClassHandler<MarkdownViewer>((_, e) =>
    Process.Start(new ProcessStartInfo(e.Url) { UseShellExecute = true }));
viewer.ScrollToAnchor("my-heading");  // scrolls to the heading's anchor position

Using a custom Markdig pipeline

viewer.Pipeline = new MarkdownPipelineBuilder()
    .UseSupportedExtensions()
    .UseAlertBlocks()
    .UseFootnotes()
    .Build();

Extension Methods

Convenience methods configure a pipeline with a single opt-in feature:

viewer.UseAbbreviations();
viewer.UseAlertBlocks();
viewer.UseCitations();
viewer.UseFigures();
viewer.UseFootnotes();
viewer.UseHardlineBreaks();
viewer.UseMediaLinks();

To combine several opt-in features, build the pipeline explicitly (see above).

Application-Wide Defaults

MarkdownViewerDefaults lets you set a pipeline and/or extensions once so that every MarkdownViewer in the application inherits them automatically — no need to configure each instance:

// App.axaml.cs
MarkdownViewerDefaults.Pipeline = new MarkdownPipelineBuilder()
    .UseSupportedExtensions()
    .UseFootnotes()
    .UseAlertBlocks()
    .Build();

MarkdownViewerDefaults.Extensions.AddTextMateHighlighting();
MarkdownViewerDefaults.Extensions.AddSvg();
MarkdownViewerDefaults.Extensions.AddMermaid();

Per-instance Pipeline and Extensions take precedence over the defaults; an extension object shared between the defaults list and an instance list is only registered once per render.

Supported Markdown Features

CommonMark baseline (always on)

FeatureNotes
Headings H1–H6CommonMark
Bold, italicCommonMark
Inline codeCommonMark
Fenced code blocksCommonMark
BlockquotesCommonMark
Ordered and unordered listsCommonMark, tight and loose
Links and autolinksCommonMark + extension
ImagesCommonMark, remote URLs loaded async
Image sizing![alt](url =WxH) — inline pixel dimensions, e.g. =80x80
Thematic breaksCommonMark
Hard line breaksCommonMark (\ or two spaces)
HTML <br> / <br />Rendered as line break

Extensions (enabled by UseSupportedExtensions())

FeatureSyntax
Strikethrough~~text~~
Subscript~text~
Superscript^text^
Underline (inserted)++text++
Highlight (marked)==text==
Task lists- [x] item
Pipe tablesGFM-style | col | col |
Grid tablesRST-style grid tables
Autolinksbare https://… URLs
Emoji shortcodes:rocket: → 🚀 (ASCII smileys like :) are intentionally left as plain text)
CJK-friendly emphasisparser-only fix for emphasis next to Chinese/Japanese/Korean (CJK) punctuation
YAML front matter--- metadata block at the top of a document is parsed and hidden

Opt-in extensions

These require adding .UseXxx() to the pipeline (see Extension Methods above):

FeatureActivationSyntax
AbbreviationsUseAbbreviations()*[HTML]: …
GitHub alert blocksUseAlertBlocks()> [!NOTE] etc.
CitationsUseCitations()""quoted text""
FiguresUseFigures()^^^ / ^^^ caption
FootnotesUseFootnotes()[^1] / [^1]: …
Hardline breaksUseHardlineBreaks()every soft line break renders as a hard break
YouTube embedsUseMediaLinks()![title](https://youtu.be/…)

Extension Packages

MarkView.Avalonia ships optional NuGet packages that add richer rendering capabilities. Each package implements IMarkViewExtension and is activated via a convenience method on MarkdownViewer, or globally via MarkdownViewerDefaults.Extensions.AddXxx().

Syntax Highlighting (MarkView.Avalonia.SyntaxHighlighting)

Adds TextMate grammar-based syntax highlighting to fenced code blocks.

dotnet add package MarkView.Avalonia.SyntaxHighlighting
viewer.UseTextMateHighlighting(); // DarkPlus / LightPlus by default
// or with custom themes:
viewer.UseTextMateHighlighting(darkTheme: ThemeName.Monokai, lightTheme: ThemeName.QuietLight);

The extension replaces the built-in CodeBlockRenderer with TextMateCodeBlockRenderer, which tokenises each line and emits coloured Run elements. Unsupported languages fall back to the default monochrome rendering automatically.

Colours update in-place when the user switches between light and dark themes — no document rebuild or scroll reset.

Available ThemeName values are defined by TextMateSharp.Grammars: DarkPlus, LightPlus, Monokai, SolarizedDark, SolarizedLight, and more.

SVG Images (MarkView.Avalonia.Svg)

Renders SVG images embedded in markdown (![desc](path/to/image.svg)), including data:image/svg+xml data URIs and badge-service URLs that return SVG without a .svg extension.

dotnet add package MarkView.Avalonia.Svg
viewer.UseSvg();

The extension inserts SvgImageLoader at the front of the image loader chain. Regular raster images continue to load via the built-in HTTP fallback.

LaTeX Math (MarkView.Avalonia.Math)

Renders $...$ (inline) and $$...$$ (block) LaTeX math using CSharpMath's SkiaSharp renderer — pure .NET, no browser or WebView required.

dotnet add package MarkView.Avalonia.Math
viewer.UseMath();

Mermaid Diagrams (MarkView.Avalonia.Mermaid)

Renders fenced mermaid code blocks as SVG diagrams using the Mermaider library (pure .NET, no browser required). Works on all platforms including Linux. Diagrams re-render automatically when the user switches between light and dark themes.

dotnet add package MarkView.Avalonia.Mermaid
viewer.UseMermaid();

Markdown syntax:

```mermaid
graph TD
  A[Start] --> B{Decision}
  B -- Yes --> C[End]
  B -- No  --> A
```

Combining extensions

All four can be stacked:

viewer
    .UseTextMateHighlighting()
    .UseSvg()
    .UseMermaid()
    .UseMath();

Extensions are applied in the order they are added to viewer.Extensions. Each extension's Register method is called once per render pass, before the Markdig pipeline is set up.

Writing your own extension

Implement IMarkViewExtension from the core package:

using MarkView.Avalonia.Extensions;
using MarkView.Avalonia.Rendering;

public class MyExtension : IMarkViewExtension
{
    public void Register(AvaloniaRenderer renderer)
    {
        // swap a renderer, add an image loader, or set a code highlighter
        renderer.ObjectRenderers.ReplaceOrAdd<CodeBlockRenderer>(new MyCodeBlockRenderer());
    }
}

viewer.Extensions.Add(new MyExtension());

Theming / Customisation

Include MarkdownTheme.axaml for default styles. Override any style class in your own Styles to customise appearance:

Style classApplied toControls
markdown-h1markdown-h6HeadingsTextBlock
markdown-paragraphParagraphsTextBlock
markdown-code-blockCode blocksBorder
markdown-code-inlineInline codeBorder
markdown-blockquoteBlockquotesBorder
markdown-listListsStackPanel
markdown-thematic-breakHorizontal rulesSeparator
markdown-imageImagesImage
markdown-linkHyperlinksHyperlinkButton
markdown-tableTablesGrid
markdown-table-cellTable cellsBorder
markdown-table-headerHeader cellsBorder
markdown-markedHighlighted text (==…==)Span
markdown-alertAlert block containerBorder
markdown-alert-notemarkdown-alert-cautionPer-kind border colourBorder
markdown-alert-headerAlert kind labelTextBlock
markdown-figureFigure containerBorder
markdown-figure-captionFigure captionTextBlock
markdown-abbrAbbreviation with tooltipTextBlock
markdown-footnote-refFootnote reference linkHyperlinkButton
markdown-footnote-groupFootnote definition listStackPanel
markdown-footnote-itemIndividual footnote rowGrid

Extension packages may ship their own theme file with additional overridable colours — check the extension's README for its StyleInclude path and resource keys.

Example — increase heading size and add a bottom border:

<Style Selector="TextBlock.markdown-h1">
  <Setter Property="FontSize" Value="36" />
  <Setter Property="Foreground" Value="#1A1A2E" />
  <Setter Property="Margin" Value="0,12,0,6" />
</Style>

Text Selection

MarkdownViewer supports full document-wide text selection:

  • Click + drag to select a range.
  • Ctrl+A to select all text.
  • Ctrl+C to copy the selection to the clipboard.

Programmatic API:

viewer.SelectAll();
viewer.ClearSelection();
string text = viewer.GetSelectedText();
await viewer.CopyToClipboardAsync();

Images and task-list checkboxes are skipped during selection — see Known Limitations below.

Known Limitations

LimitationDetail
Images are non-selectableImages in inline position are embedded as InlineUIContainer — selection skips around them.
Task checkboxes are non-selectableSame reason as images.
Anchor scroll is instantBringIntoView() jumps without animation. Smooth scrolling is a future improvement.

License

MIT © Nicolas Musset

Contributors

Kryptos-FR

70 commits

Languages

C#

100.0%