Parsing Markdown Documents and Handling Image Links in C#
Preface It's been a long time since I last wrote a blog post It's not that I haven't been writing—I've been "building a blog" recently. Starting from February 21st, I spent about a week or so frantically pushing progress, writing code while also writing a whole series of blog development notes. So far I've written 16 of them. Then after March, work got a bit busy ~~plus I got a bit addicted to Genshin Impact~~, so progress slowed down for a while It's proven that once you stop doing something, inertia sets in. After pausing for so long, I've finally made up my mind to continue updating! The blog I'm developing this time uses the C# language, with the .NET Core tech stack; front
目录6 个章节
Preface
It's been a long time since I last wrote a blog post
It's not that I haven't been writing—I've been "building a blog" recently. Starting from February 21st, I spent about a week or so frantically pushing progress, writing code while also writing a whole series of blog development notes. So far I've written 16 of them. Then after March, work got a bit busy plus I got a bit addicted to Genshin Impact, so progress slowed down for a while
It's proven that once you stop doing something, inertia sets in. After pausing for so long, I've finally made up my mind to continue updating!
The blog I'm developing this time uses the C# language, with the .NET Core tech stack. For the frontend I'll continue using Bootstrap, which I'm fairly familiar with, for layout, with a bit of tinkering. The admin side uses Vue... Along the way I keep running into technical problems. Besides recording them in the blog development notes series, I'll also pull out some more generally applicable solutions separately.
My blog is written in Markdown, programmers' favorite syntax, and as everyone knows, one downside of markdown is that associating image resources is a hassle
Because my blog needs to support importing Markdown documents written locally in Typora, parsing markdown documents and handling imported image resources is a hurdle I can't avoid.
As the title says, this article is about parsing Markdown documents in C#.
The Markdig Library
I previously implemented Markdown document parsing in Python. There are tons of related libraries in the Python ecosystem, with many great options. Here's an article I wrote before about parsing Markdown in Python: Parsing images in a markdown document with Python and saving them locally~
However, on the C# side there's basically nothing to choose from. The official Markdown library is also marked as deprecated, and they recommend migrating to the Markdig library...
So there's no choice—I have to use this Markdig.
Official introduction:
Markdig is a fast, powerful, CommonMark compliant, extensible Markdown processor for .NET.
This library isn't actually that hard to use, but notice this sentence in the official introduction:
NOTE: The repository is under construction. There will be a dedicated website and proper documentation at some point!
Damn it! There's basically no documentation at all. Usage is pretty much all guessing and digging through the source code ヽ(ー_ー)ノ
To implement this markdown image import, I had no choice but to grit my teeth and get on with it
Implementation Approach
Markdig has a pipeline mechanism
Here's some example pseudocode:
var pipeline = new MarkdownPipelineBuilder()
.UseExt1()
.UseExt2()
.UseExt3()
.Build();
var result = Markdown.ToHtml("This is a text with some *emphasis*", pipeline);
You can apply some modifications to the Markdown document during the parsing process
At first I thought of writing my own pipeline to replace the image links in the Markdown
However (maybe because I'm too noob) after looking at several official pipeline code samples, I still couldn't figure out how to achieve the effect I wanted
Until I recalled a key phrase from the official introduction: CommonMark compliant, meaning this thing is compatible with CommonMark
A flash of inspiration: since Markdig is a new project without documentation yet, the older CommonMark project should have docs, right? So I went and found the CommonMark.NET project, and sure enough it had documentation. Although the APIs of the two aren't completely identical, after some half-guessing, half-exploring, I finally got the functionality I needed working~ ( ̄▽ ̄)~*
Implementation Code
Finally, time for the code~
First, read a Markdown document to get a MarkdownDocument object
// 引入需要用到的命名空间
using Markdig;
using Markdig.Renderers.Normalize;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;
var filepath = "temp/blog/机器学习/多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.md";
var md = File.ReadAllText(filepath);
var document = Markdown.Parse(md);
Part of this document looks like this:
## 前言
前段时间无聊回坑玩《开罗拉面店》,这是一款模拟经营类的小游戏,不管是画风还是游戏性都很对我胃口。



里面有一个玩法是拉面店布局,就给你一块地,还有几家店铺,你可以随便铺随便摆,当然肯定是摆的越多家店铺越好。

我一开始玩的时候也没想那么多,随便摆了摆就完事了,但玩到后期人气上不去,我就突发奇想,能不能把所有店铺摆进去?或者能不能尽可能多地去铺满这块地?
Markdig parses the Markdown document into a document tree, and then you can traverse the document nodes just like DOM operations~
The following code finds image link nodes in the Markdown and adds a prefix to the image links
foreach (var node in document.AsEnumerable()) {
if (node is ParagraphBlock { Inline: { } } paragraphBlock) {
foreach (var inline in paragraphBlock.Inline) {
if (inline is LinkInline {IsImage: true} linkInline) {
// 这里就是图片链接了
// 实现给图片链接加上前缀
linkInline.Url = $"http://127.0.0.1:5038/assets/blog/{linkInline.Url}";
Console.WriteLine(linkInline.Url);
}
}
}
}
Then re-output the modified Markdown document:
using (var writer = new StringWriter()) {
var render = new NormalizeRenderer(writer);
render.Render(document);
Console.WriteLine(writer.ToString());
}
The final result looks like this
## 前言
前段时间无聊回坑玩《开罗拉面店》,这是一款模拟经营类的小游戏,不管是画风还是游戏性都很对我胃口。



里面有一个玩法是拉面店布局,就给你一块地,还有几家店铺,你可以随便铺随便摆,当然肯定是摆的越多家店铺越好。
Follow-up
Once you can extract the image links from a markdown document, the subsequent image import and link replacement become easy. Of course that's content for the blog development notes, so I won't cover it in this article.
C# is a great language, but unfortunately the third-party library ecosystem is still a bit lacking. If I were using Python, this problem would have been solved long ago, but with C# I just have to tinker. I even considered rolling my own parser at one point...
It shouldn't actually be that hard. The approach I thought of was to iterate through the document line by line, then use regex to match the image links, and after subsequent processing use regex again for replacement. It's just not very elegant, though. In this era of writing code by copying, you still need to have some standards, otherwise what's the difference between you and a salted fish...
Let me also chat a bit about some fun things I've been working on recently:
- "De-Windows-ification" prompted by the Russia-Ukraine war
- Looking for a domestic WeChat alternative: "De-Tencent-ification"
OK, next I should start updating the blog development notes series~(*^▽^*)
References
- CommonMark.NET Wiki: https://github.com/Knagis/CommonMark.NET/wiki
- Markdig project homepage: https://github.com/xoofx/markdig
- Related issues: https://github.com/xoofx/markdig/issues/599
- Related source code: https://github.com/xoofx/markdig/blob/master/src/Markdig/Renderers/Normalize/NormalizeRenderer.cs
- Microsoft docs: https://docs.microsoft.com/en-us/windows/communitytoolkit/parsers/markdownparser
- https://www.songshizhao.com/blog/blogPage/1044.html
_EOF_
Parsing Markdown Documents and Handling Image Links in C#
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
C#学习(二)匿名方法和委托的多种使用方式
前言 上次简单介绍了委托的概念和使用,今天继续,并且引入匿名方法的概念,匿名方法在很多语言里面都有,比如Python、js、java8,尤其js,前端小伙伴可能深受js回调地狱之苦,这里面匿名方法功不可没。 js的匿名方法就像这样: 这还没用lambda,因为我想下篇再介绍lambda。 document.querySelector('.btn').onclick = function () {
2021-12-18 · C# · 约 1 分钟
使用C#和MemoryCache组件实现轮流调用APIKey以提高并发能力
本文介绍了如何利用C#语言中的MemoryCache组件,结合并发编程技巧,实现轮流调用多个API Key以提高系统的并发能力。通过示例代码和详细说明,读者将了解如何有效地管理API Key的调用次数限制,并优化系统性能。
2024-03-09 · C# · 约 1 分钟
SharpIco:用纯C#打造零依赖的.ico图标生成器,支持.NET9与AOT编译
SharpIco 是一款纯 C# 实现的跨平台图标生成工具,支持 AOT 编译,无需外部依赖。它能将 PNG 图片分解为多尺寸(16x16至512x512)合成 ICO 图标,并支持图标结构分析。工具提供命令行界面,可通过 dotnet tool 一键安装,并已发布至 NuGet 和 Scoop。项目旨在简化图标生成与验证,追求轻量、纯粹、易集成的使用体验。
2025-05-26 · C# · 约 1 分钟
开发现代化的.NetCore控制台程序:(2)创建一个C#项目模板
又一个.NetCore模板?FluentConsole.Templates,一键生成骨架,包含DI、日志、配置。安装?dotnet new install,然后dotnet new flu-cli -n MyProject。太简单了吧,谁在乎?
2023-11-10 · C# · 约 1 分钟
讨论
共 0 条加载评论中…