ReverseMarkdown (.NET HTML to Markdown converter)

repository·master·Indexed 18 days ago

https://github.com/mysticmind/reversemarkdown-net

A high-performance HTML to Markdown converter library for C# using AngleSharp for HTML5 parsing. It supports multiple Markdown flavors including GitHub, CommonMark, Slack, Telegram, MultiMarkdown, and Pandoc. Version 6 introduces a Markdown DOM architecture that decouples parsing from rendering, allowing for structured document manipulation. The library targets netstandard2.0, net8.0, net9.0, and net10.0, and is compatible with .NET Framework 4.6.1+, .NET Core 2.0+, Mono, and Unity.

Tokens
8.3K
Snippets
19
Records
49
Agent score
60%

What's inside ReverseMarkdown

  1. Overview of ReverseMarkdown features

    master

    ReverseMarkdown is a high-performance HTML to Markdown converter for C# that uses AngleSharp for HTML5 parsing. Key capabilities include:

    • Multiple Output Flavors: Supports Default, GitHub, CommonMark, Slack, Telegram, MultiMarkdown, and Pandoc via the MarkdownFlavor enum.
    • Spec-compliant Round-trips: High fidelity for CommonMark/GitHub and MultiMarkdown/Pandoc.
    • Extensibility: Supports custom readers via IMdReader and the [MarkdownReader] attribute, as well as a Parse/Render Markdown DOM for transformations.
    • Advanced Element Handling: Supports nested tables, captions, smart hrefs, URI-scheme whitelisting, and configurable base64 image handling (include, skip, or save to disk).
    • Modern Runtime Support: Targets netstandard2.0, net8.0, net9.0, and net10.0. It is compatible with .NET Framework 4.6.1+, .NET Core 2.0+, Mono, and Unity.
    • AOT/Trimming Ready: The default path avoids reflection. For Native AOT or trimming, use RegisterReader to add custom readers.
  2. Overview of ReverseMarkdown

    master
    ReverseMarkdown is a fast, spec-compliant HTML to Markdown converter for .NET. Version 6 is built using the AngleSharp HTML5 parser and a Markdown DOM pipeline. It supports seven different output flavors and is designed to be extensible and compatible with modern .NET deployment requirements like Trimming and Native AOT.
  3. How the v6 Markdown DOM architecture works

    master

    Starting with v6, ReverseMarkdown uses an intermediate Markdown DOM (an mdast-equivalent typed document tree) to decouple HTML parsing from Markdown rendering. This architecture splits the conversion process into two distinct phases:

    1. Parsing (Parse): Readers convert HtmlNode objects into a rich, flavor-agnostic Markdown DOM. This phase builds a superset tree containing all possible structural information.
    2. Rendering (Render): Writers take the Markdown DOM and convert it into a specific Markdown flavor string. Writers own all flavor-specific logic and decisions regarding how to represent (or degrade) nodes that a specific flavor cannot support.

    This design allows you to perform structured operations on the document—such as querying, pruning, or reshaping the tree—before finally rendering it to a string. This is particularly useful if you need to filter specific parts of the document based on its Markdown structure rather than just its HTML attributes.

  4. Update Markdown flavor selection in v6

    master

    The MarkdownFlavor enum is now the single, canonical way to select a flavor. Several previous flavor types are now obsolete aliases of Flavor.

    Obsolete Flavor Aliases

    • SlackFlavored (now Flavor)
    • TelegramMarkdownV2 (now Flavor)
    • CommonMark (now Flavor)

    Important Note on GitHub Flavored Markdown

    GithubFlavored remains distinct. It produces clean GFM markdown using the default writer. Do not confuse it with Flavor = MarkdownFlavor.GitHub, which is a CommonMark-based writer that preserves raw HTML.

  5. Supported Markdown flavors in ReverseMarkdown

    master

    ReverseMarkdown allows you to select the output format using a single Flavor enum. The supported flavors are:

    • Default
    • GitHub (Verified for 100% round-trip compliance against canonical cmark-gfm)
    • CommonMark (Verified for 100% round-trip compliance against canonical cmark-gfm)
    • Slack
    • Telegram
    • MultiMarkdown (Verified against canonical pandoc)
    • Pandoc (Verified against canonical pandoc)
  6. Use the CommonMark flavor for round-trip fidelity

    master

    The CommonMark flavor is designed for round-trip-faithful conversion. It preserves soft line breaks, escapes markup-significant characters, and escapes line-start markers to ensure literal text is not reinterpreted during conversion.

    Note: The legacy CommonMark = true switch is an obsolete alias for Flavor = MarkdownFlavor.CommonMark and should be avoided in favor of the explicit flavor setting.

    // Use the explicit flavor instead of the obsolete CommonMark = true switch
    var converter = new ReverseMarkdownConverter(new ConversionOptions
    {
        Flavor = MarkdownFlavor.CommonMark
    });
  7. Understanding the v6 Reader API change: IElement vs HtmlNode

    master

    In version 6 of ReverseMarkdown, the HTML parsing engine has transitioned from HtmlAgilityPack to AngleSharp. This change introduces a breaking change to the public API surface for readers:

    • v5 and earlier: The IConverter interface exposed HtmlNode (from HtmlAgilityPack).
    • v6 and later: The IMdReader.Read method now exposes IElement (from AngleSharp).

    When implementing or using custom readers in v6, you must work with AngleSharp.IElement instead of HtmlAgilityPack.HtmlNode. This transition provides spec-compliant tree construction, native CSS selector support via QuerySelector, and automatic entity decoding through IText.Data and GetAttribute.

  8. Alias a tag for conversion

    master

    You can reuse the conversion logic of an existing tag for a different tag using Tags.Aliases. The key in the dictionary is the tag you want to remap, and the value is the tag it should be converted as.

    // Example mapping: treat 'span' as 'em' (italics)
    var converter = new ReverseMarkdown.Converter(new ConversionOptions {
        Tags = new Tags {
            Aliases = new Dictionary<string, string> { { "span", "em" } }
        }
    });
  9. Telegram flavor formatting and escaping behavior

    master

    When using MarkdownFlavor.Telegram, the following conversion behaviors are applied to ensure compatibility with Telegram's strict escaping rules:

    • Escaping: Text and link labels automatically escape Telegram-reserved characters. List markers for ordered (1\.) and unordered (\-) lists are also escaped.
    • Images: <img> tags are converted to link labels using the format [Image: alt](url).
    • Tables: <table> tags fall back to a preformatted code block representation.
    • Superscript: <sup> tags fall back to caret notation (e.g., x^2).