AxDa.Markdown
1.0.3
Prefix Reserved
dotnet add package AxDa.Markdown --version 1.0.3
NuGet\Install-Package AxDa.Markdown -Version 1.0.3
<PackageReference Include="AxDa.Markdown" Version="1.0.3" />
<PackageVersion Include="AxDa.Markdown" Version="1.0.3" />
<PackageReference Include="AxDa.Markdown" />
paket add AxDa.Markdown --version 1.0.3
#r "nuget: AxDa.Markdown, 1.0.3"
#:package AxDa.Markdown@1.0.3
#addin nuget:?package=AxDa.Markdown&version=1.0.3
#tool nuget:?package=AxDa.Markdown&version=1.0.3
LINQ to Markdown Overview
LINQ to Markdown provides an in-memory Markdown programming interface that leverages the .NET Language-Integrated Query (LINQ) Framework. LINQ to Markdown uses .NET capabilities and is comparable to the LINQ to XML
programming interface. These query expressions provide functionality similar to XPath.
Markdown has been widely adopted as a way to format data in many contexts. For example, you can find Markdown on the Web, in documentation files, and in databases.
LINQ to Markdown is an up-to-date approach to programming with Markdown. It provides the in-memory document modification capabilities of a Markdown Document Object Model (MDOM), and supports LINQ query expressions.
LINQ to Markdown is a pure native .NET library, increasing professional developers' productivity by leveraging the prevalent and powerful Markdown language without the need to additionally install and run a Node.js ecosystem.
LINQ to Markdown is a Markdown programming interface
LINQ to Markdown is a LINQ-enabled, in-memory Markdown programming interface that enables you to work with Markdown from within the .NET programming languages.
LINQ to Markdown brings the Markdown document into memory. You can query and modify the document, and after you modify it, you can save it to a file or serialize it and send it over the Internet.
- It provides an object model that's light-weight and easy to work with.
- It takes advantage of language features in C# and Visual Basic.
The most important advantage of LINQ to Markdown is its integration with Language-Integrated Query (LINQ). This integration enables you to write queries on the in-memory Markdown document to retrieve collections of Markdown language items, called "tokens". The query capability of LINQ to Markdown is comparable in functionality (although not in syntax) to XPath and XQuery. The integration of LINQ in C# and Visual Basic provides stronger typing, compile-time checking, and improved debugger support.
Another advantage of LINQ to Markdown is the ability to use query results as parameters to Markdown token object constructors which enables a powerful approach to creating Markdown trees. This approach, called functional construction, enables developers to easily transform Markdown trees from one shape to another.
For example, you might have a typical ReadMe.md
file. By using LINQ to Markdown, you could run the following query to obtain all top-level headings in the Markdown document:
MarkdownDocument md = new MarkdownDocument(File.ReadAllText(@".\ReadMe.md"))
IEnumerable<HeadingToken>? headings
= from heading in md.Root?.Children<HeadingToken>()
where heading.HeadingLevel == 1
select heading;
}
In C# this can be rewritten in method syntax form:
MarkdownDocument md = new MarkdownDocument(File.ReadAllText(@".\ReadMe.md"))
IEnumerable<HeadingToken>? headings
= md.Root
?.Children<HeadingToken>()
.Where(h => h.HeadingLevel == 1);
}
The examples in this documentation are written in C#. Yet, you can use LINQ to Markdown with any .NET language you prefer.
MarkdownDocument class overview
The MarkdownDocument
class is one of the fundamental classes in LINQ to Markdown. It represents a Markdown document. The following list shows what you can use this class for:
- Load a Markdown tree from string or stream.
- Save a Markdown tree to string or stream.
- Add, change, or delete child elements.
- Add, change, or delete a YAML Frontmatter header.
You can read Markdown files in different ways, including the following:
- You can construct a Markdown tree in code. For more information, see Construct Markdown trees.
- You can parse Markdown from various sources, including a
TextReader
, text files, or a Web address (URL). For more information, see Parse Markdown.
You can use the MarkdownDocument.Root
property to populate a Markdown tree. For more information, see Construct Markdown trees.
In addition to manipulating the Markdown object tree itself, using LINQ to Markdown you can also read, add, change or delete YAML Frontmatter information to the Markdown tree using the MarkdownDocument.YamlHeader
property.
Parse a string (LINQ to Markdown)
The following C# code shows how to load and parse Markdown strings:
using AxDa.Markdown;
MarkdownDocument md1 = new MarkdownDocument("# A heading in a Markdown document");
MarkdownDocument md2 = new MarkdownDocument();
md2.Parse("# A heading in another Markdown document");
MarkdownDocument md3 = new MarkdownDocument();
md2.Load(@".\ReadMe.md");
Note: Parsing text or loading a Markdown document from a text file is less efficient than functional construction. If you're initializing a Markdown tree from code, it takes less processor time to use functional construction than to parse text.
Construct Markdown trees
One of the most significant advantages of programming with LINQ to Markdown is that it's easy to create Markdown trees. For example, to create a small Markdown tree, you can write code as follows:
using AxDa.Markdown;
using AxDa.Markdown.Tokens.Block;
using AxDa.Markdown.Tokens.Inline;
using AxDa.Markdown.Tokens.List;
MarkdownDocument md = new MarkdownDocument();
md.Root = new RootToken(
new HeadingToken(1,
new TextToken("This is a heading")
),
new ParagraphToken(
new TextToken("This is the first paragraph")
),
new ParagraphToken(
new TextToken("This is another paragraph with text in "),
new ItalicToken(
new TextToken("italic")
),
new TextToken(".")
)
);
string markdown = md.ToString();
The above code assigns the following result to the markdown
string variable:
# This is a heading
This is the first paragraph
This is another paragraph with text in *italic*.
Construct Markdown tables
Using LINQ to Markdown, it's also easy to create Markdown tables. For example, to create a small Markdown table, you can write code as follows:
using AxDa.Markdown;
using AxDa.Markdown.Tokens.Inline;
using AxDa.Markdown.Tokens.List;
using AxDa.Markdown.Tokens.Table;
MarkdownDocument md = new MarkdownDocument()
{
Root = new RootToken(
new TableToken(
new TableRow( // table header row
new TableCellToken(new TextToken("Header1")),
new TableCellToken(new TextToken("Header2"))
),
[ // table column alignment
TableColumnAlignment.Center,
TableColumnAlignment.Right
],
new TableRow( // table row #1
new TableCellToken(
new BoldToken(new TextToken("Row1")),
new TextToken(" in Column1")
),
new TableCellToken(new TextToken("Column2"))
),
new TableRow( // table row #2
new TableCellToken(
new BoldToken(new TextToken("Row2")),
new TextToken(" in Column1")
),
new TableCellToken(new TextToken("Column2"))
),
new TableRow( // table row #3
new TableCellToken(
new BoldToken(new TextToken("Row3")),
new TextToken(" in Column1")
),
new TableCellToken(new TextToken("Column2"))
)
)
)
};
string markdown = md.ToString();
The above code assigns the following result to the markdown
string variable:
|Header1|Header2|
|:-:|-:|
|**Row1** in Column1|Column2|
|**Row2** in Column1|Column2|
|**Row3** in Column1|Column2|
Construct Markdown lists
Using LINQ to Markdown, it's also easy to create Markdown lists.
LINQ to Markdown supports two kinds of lists:
- Ordered lists
- Unordered lists
For example, to create these two types of lists, you can write code as follows:
using AxDa.Markdown;
using AxDa.Markdown.Tokens.Block;
using AxDa.Markdown.Tokens.Inline;
using AxDa.Markdown.Tokens.List;
MarkdownDocument md = new MarkdownDocument()
{
Root = new RootToken(
new OrderedListItemToken(
new ParagraphToken(
new TextToken("This is the first item")
)
),
new OrderedListItemToken(
new ParagraphToken(
new TextToken("This is the second item")
)
),
new UnorderedListItemToken(
new ParagraphToken(
new TextToken("This is a bullet list item")
)
)
)
};
string markdown = md.ToString();
The above code assigns the following result to the markdown
string variable:
1. This is the first item
2. This is the second item
- This is a bullet list item
Construct Task items
LINQ to Markdown also supports task items as featured by GitLab and GitHub.
On these websites, task items can be used to interactively report progress within issue, merge request or pull request comments and discussion threads.
The TaskToken
list type covers task items as featured by GitLab, providing the following three task states:
Pending
Approved
Denied
At the time of writing, the GitHub website only supports Pending
and Approved
task states.
Task items have some restrictions:
- They must contain inline content. So, adding text to them is mandatory.
- They must be a list item's first child.
For example, to create three small task items, each with a different initial state, you can write code as follows:
using AxDa.Markdown;
using AxDa.Markdown.Tokens.Inline;
using AxDa.Markdown.Tokens.List;
MarkdownDocument md = new MarkdownDocument
{
Root = new RootToken(
new UnorderedListItemToken(
new TaskToken(TaskItemStatus.Pending,
new TextToken("This is a "),
new ItalicToken(
new TextToken("pending")
),
new TextToken(" item")
)
),
new UnorderedListItemToken(
new TaskToken(TaskItemStatus.Approved,
new TextToken("This is an approved item")
)
),
new OrderedListItemToken(
new TaskToken(TaskItemStatus.Denied,
new TextToken("This is a denied item")
)
)
)
};
string markdown = md.ToString();
The above code assigns the following result to the markdown
string variable:
- [ ] This is a *pending* item
- [X] This is an approved item
1. [~] This is a denied item
Construct Hyperlinks
Another advantage of LINQ to Markdown is its full support of all types of hyperlinks that are available in Markdown:
Hyperlink Type | Token Class | Example |
---|---|---|
Text hyperlink | TextHyperlinkToken |
[text](uri) |
Image hyperlink | ImageHyperlinkToken |
 |
Hyperlink reference item | HyperlinkReferenceToken |
label: uri |
Reference text hyperlink | TextHyperlinkReferenceToken |
[text][label] |
Reference image hyperlink | ImageHyperlinkReferenceToken |
![text][label] |
You can easily add hyperlinks to your inline text. For example, to create a small Markdown tree containing a line of text with a text hyperlink within, you can write code as follows:
using AxDa.Markdown;
using AxDa.Markdown.Tokens.Block;
using AxDa.Markdown.Tokens.Inline;
using AxDa.Markdown.Tokens.List;
MarkdownDocument md = new MarkdownDocument();
md.Root = new RootToken(
new ParagraphToken(
new TextToken("For details, see "),
new TextHyperlinkToken("https://contoso.com/",
new TextToken("here")
),
new TextToken(".")
)
);
string markdown = md.ToString();
The above code assigns the following result to the markdown
string variable:
For details, see [here](https://contoso.com/).
Apply text formatting
Using LINQ to Markdown, it's also easy to apply formatting to text. For example, to create a formatted paragraph of text, a horizontal line, and a code block, you can write code as follows:
using AxDa.Markdown;
using AxDa.Markdown.Tokens.Block;
using AxDa.Markdown.Tokens.Inline;
using AxDa.Markdown.Tokens.List;
MarkdownDocument md = new MarkdownDocument()
{
Root = new RootToken(
new ParagraphToken(
new BoldToken(
new TextToken("This")
),
new TextToken(" text "),
new BoldToken(
new ItalicToken(
new TextToken("emphasizes")
)
),
new TextToken(" on the fact that "),
new StrikeThroughToken(
new TextToken("anything")
),
new TextToken(" "),
new ItalicToken(
new TextToken("everything")
),
new TextToken(Environment.NewLine + "may be "),
new CodeToken("code"),
new TextToken(" formatted.")
),
new HorizontalLineToken(),
new CodeBlockToken("c#",
@"MarkdownDocument md = new MarkdownDocument();
md.Parse(""# My example heading"");
string test = md.ToString();"
)
),
};
string markdown = md.ToString();
The above code assigns the following result to the markdown
string variable:
__This__ text __*emphasizes*__ on the fact that ~anything~ *everything*<br/>may be `code` formatted.
---
``` c#
MarkdownDocument md = new MarkdownDocument();
md.Parse("# My example heading");
string test = md.ToString();
```
Construct YAML Front Matter document header
Using LINQ to Markdown, you can easily apply a YAML Front Matter document header to your Markdown document. For example, you can write code as follows to apply a YAML Front Matter document header to your Markdown document:
using AxDa.Markdown;
using AxDa.Markdown.Tokens.Block;
using AxDa.Markdown.Tokens.Inline;
using AxDa.Markdown.Tokens.List;
MarkdownDocument md = new MarkdownDocument();
md.YamlHeader = new YamlFrontMatterToken(
@"- Author: me@contoso.com
- Date: 2025-04-29"
);
md.Root = new RootToken(
new ParagraphToken(
new TextToken("Test")
)
);
string markdown = md.ToString();
The above code assigns the following result to the markdown
string variable:
---
- Author: me@contoso.com
- Date: 2025-04-29
---
Test
HTML Tags
LINQ to Markdown supports embedding HTML document fragments to a Markdown document tree.
You can easily populate a Markdown tree with HTML by adding a HTML fragment as plain text to a TextToken
object.
For example, to enclose text with a <details>
HTML element, you can write code as follows:
using AxDa.Markdown;
using AxDa.Markdown.Tokens.Block;
using AxDa.Markdown.Tokens.Inline;
using AxDa.Markdown.Tokens.List;
MarkdownDocument md = new MarkdownDocument
{
Root = new RootToken(
new ParagraphToken(
new TextToken("<details>")
),
new ParagraphToken(
new TextToken("This is some initially hidden text.")
),
new ParagraphToken(
new TextToken("</details>")
)
)
};
string markdown = md.ToString();
The above code assigns the following result to the markdown
string variable:
<details>
This is some initially hidden text.
</details>
Exceptions To This Rule: <br>
and <hr>
HTML Tags
While, in general, LINQ to Markdown treats HTML tags as plain, unprocessed text, the following two HTML tags are treated differently:
HTML
<br>
tags in aTextToken
object's text content will be converted to the current operating system's new-line character sequence on object creation. Conversely, when a Markdown object tree is serialized, any type of line break string in the text content of aTextToken
object is converted to an HTML<br>
tag.When loading or parsing an existing Markdown document using the
MarkdownDocument
object's constructor and methods, HTML<hr>
tags found in the document are recognized and converted toHorizontalLineToken
Markdown objects when the Markdown object tree is created. However, when manually creating a newTextToken
object with text content containing "<hr>
" or "<hr/>
", such content is interpreted as plain text and no conversion occurs.
Additional notes
When serializing a Markdown tree, LINQ to Markdown writes blank lines between block elements, even in situations where they aren't required. This ensures that block elements will never be falsely interpreted as a lazy continuation line. It also makes it easier for the human eye to grasp the content when reading complex Markdown text. A serialized LINQ to Markdown tree will always end with a blank line. You may want to trim the output string if you find the trailing blank line confusing.
Feedback, Sponsorship and Contact
You may reach me on axeldahmen.de or LinkedIn
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. 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 was computed. 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. |
-
net9.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on AxDa.Markdown:
Package | Downloads |
---|---|
AxDa.XamlDocConverter.Markdown
Converts WPF flow document content from XAML format to Markdown and vice versa. |
GitHub repositories
This package is not used by any popular GitHub repositories.
- Text style token stacking fixed.