曦远 (DealiAxy)一份私人的文字刊物

StarBlog
返回文章列表折页手记阅读全文
C#

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

曦远 (DealiAxy)约 20 分钟
目录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:

## 前言
前段时间无聊回坑玩《开罗拉面店》,这是一款模拟经营类的小游戏,不管是画风还是游戏性都很对我胃口。

![](多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-ea70bbc1e5c28b62.png)

![](多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-3dd13511e9063800.png)

![](多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-8fcc0475f92cfc84.png)

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

![](多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-f2c6578cb8f77c31.png)

我一开始玩的时候也没想那么多,随便摆了摆就完事了,但玩到后期人气上不去,我就突发奇想,能不能把所有店铺摆进去?或者能不能尽可能多地去铺满这块地?

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

## 前言

前段时间无聊回坑玩《开罗拉面店》,这是一款模拟经营类的小游戏,不管是画风还是游戏性都很对我胃口。

![](http://127.0.0.1:5038/assets/blog/多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-ea70bbc1e5c28b62.png)

![](http://127.0.0.1:5038/assets/blog/多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-3dd13511e9063800.png)

![](http://127.0.0.1:5038/assets/blog/多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-8fcc0475f92cfc84.png)

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

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

_EOF_

Parsing Markdown Documents and Handling Image Links in C#

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

C#爬虫开发小结

前言 2023年以来一直很忙,临近春节,各种琐事更多,但鸽了太久没写文章总是不舒坦,忙中偷闲来记录下最近用C#写爬虫的一些笔记。 爬虫一般都是用Python来写,生态丰富,动态语言开发速度快,调试也很方便 但是 我要说但是,动态语言也有其局限性,笔者作为老爬虫带师,几乎各种语言都搞过,现在这个任务并不复杂,用我最喜欢的C#做小菜一碟~ 开始 之前做 OneCat 项目的时候,最开始的数据采集模块,

2023-01-24 · C# · 约 1 分钟

并行化优化KD树算法:使用C#实现高效的最近邻搜索

本文介绍了如何使用并行计算技术优化 KD 树算法,并使用 C# 编程语言实现了高效的最近邻搜索。首先,我们简要介绍了 KD 树的原理和构建过程,然后详细讨论了如何利用并行计算库在多个 CPU 核心上并行构建 KD 树,从而加速搜索过程。通过实验验证,我们证明了并行化优化能够显著提高 KD 树的构建速度和搜索效率,为大规模数据集下的最近邻搜索问题提供了一种高效的解决方案。

2024-03-10 · C# · 约 1 分钟

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…