C# 将 Markdown 转 HTML 的 3 种方案:我为什么最终选择了 Markdig

一个真实项目的选型对比:从踩坑正则库到拥抱 AST,性能提升 100 倍。

痛点开局:博客系统里的 500 毫秒

前阵子给一个开源社区写 Wiki 插件。需求很简单:把用户存的 .md 文件渲染成网页。

第一版方案更简单。网上搜了个老教程,直接 Install-Package MarkdownSharp,20 行代码搞定。上线第三天,运维群里炸了:“某个 2 万字的架构设计文档打不开,页面转了 5 秒白屏。”

我一看代码,心跳漏了半拍。那个类库基于 正则表达式 递归解析,遇到超长文本和复杂嵌套列表直接飚到 400-500ms 响应耗时 。

有个坑: 你以为选个下载量高的库就稳了?NuGet 上排第一的 MarkdownSharp 虽然有 3200 万下载,但它其实是个“历史包袱”,性能比现代解析器慢 100 倍。具体数据我们后面看。

说白了,对 Markdown 解析这种场景,选错引擎比选错框架更致命

正文:三个主流选项与致命伤

先给结论:如果你现在还在纠结用哪个,直接选 Markdig。它现在几乎是 .NET 生态的事实标准。

1. MarkdownSharp:老古董的叹息

这个是 Stack Overflow 早期用的移植版,纯 C# 实现,依赖正则 。

优点:不用学新 API,简单的文本转换一把梭。
致命伤无 AST(抽象语法树) 。这意味着它一旦遇到复杂嵌套(比如列表套引用再套代码块),容易触发正则回溯灾难。

2. CommonMark.NET:曾经的优等生,现已停更

这是严格按照 CommonMark 规范(0.30 版本)实现的库,由 .NET 基金会维护过一段时间 。比 MarkdownSharp 规范,不会乱解析斜体。

然而它有个大问题:扩展性为 0。你想支持 GFM 任务列表(- [x])?不支持。想支持表格?默认不支持。而且这个项目已基本处于停更状态

3. Markdig:核弹级生产力

作者 Alexandre Mutel 写的,完全遵循 CommonMark 标准,通过了 600+ 官方测试用例

它不是简单的转换器,它先把 Markdown 解析成 AST(语法树),再渲染成 HTML。这个结构让拓展、修改、语法高亮、来回转换都变得极其优雅

性能实测:Markdig 到底有多快?

我直接贴官方 benchmark 实测数据 :

方法 平均耗时 (Mean) 性能对比
markdig 1.979 ms 基准(最快)
cmark (C 参考实现) 2.571 ms 慢约 30%
CommonMark.NET 2.016 ms 略慢但合规
MarkdownSharp 221.455 ms 慢 100 倍以上

你没看错,在处理复杂文档时,Markdig 甚至比 CommonMark 的 C 语言参考实现(cmark)还要快 20%。

实战代码:从 Hello World 到工业级配置

场景一:最简入门(几乎零配置)

默认使用的是严格 CommonMark 模式,不开启任何花哨的 GFM 扩展。

using Markdig;

var markdown = "# 标题 \n 这是一段带 *强调* 的文字。";
var html = Markdown.ToHtml(markdown);

Console.WriteLine(html);
// 输出: <h1>标题</h1>\n<p>这是一段带 <em>强调</em> 的文字。</p>

场景二:开启“黑科技”(管道模式)

这是 Markdig 最精髓的地方。你可以像搭积木一样配置解析器。

我们的 Wiki 系统需要支持:表格、任务列表、脚注、删除线,甚至 Mermaid 流程图。

using Markdig;

// 构建管道:使用 AdvancedExtensions 一次性开启 90% 的常用功能
var pipeline = new MarkdownPipelineBuilder()
    .UseAdvancedExtensions()   // 包含表格、任务列表、脚注等
    .UseEmojiAndSmiley()       // 支持 :smile: 转义
    .UseMathematics()          // 支持 LaTeX $数学公式$
    .Build();

var complexMd = @"
# 功能演示
| 语法 | 支持 |
|------|------|
| 表格 | ✅ |
- [x] 已完成任务
这是一个脚注[^1]。
[^1]: 这是脚注内容。
";

var result = Markdown.ToHtml(complexMd, pipeline);

踩坑实录:XSS 攻击与代码高亮

坑 1:默认不防 XSS

Markdig 默认不转义 HTML 标签。如果用户输入包含 <script>,会被直接输出到页面。

解决方案:渲染前启用 DisableHtml 扩展。

var safePipeline = new MarkdownPipelineBuilder()
    .DisableHtml() // 关键!这会忽略原始 HTML 标签
    .UseAdvancedExtensions()
    .Build();

坑 2:代码块高亮需要自己接入

Markdig 本身不携带 Prism 或 Highlight.js 的 CSS/JS 逻辑,它只负责生成 <code> 标签并标注 language-csharp

正确做法:后端渲染出带 lang 属性的代码块,前端配合 highlight.js 初始化。

// Markdig 渲染结果示意
// 输入: ```csharp\nvar x = 1;\n

// 输出: <pre><code class="language-csharp">var x = 1;</code></pre>
```

总结:我为什么放弃其他选型

Markdig 赢在哪?

  1. :20% 快过 C 语言实现 。
  2. :管道模式让它像中间件一样可配置 。
  3. :持续跟新 CommonMark 标准 (0.31.2) 。

如果你的业务涉及论坛、CMS、文档中心,或者需要做复杂的 Markdown 编辑预览,直接上 Markdig,别再重复造轮子了。

分享到:

本文链接:https://www.biyeyuanma.cn/post/149.html

猜你喜欢

随机文章
热门标签
图片名称

服务热线

加我微信

加我微信