前言

又是好久没写博客了

其实也不是没写,是最近在「做一个博客」,从2月21日开始,大概一个多星期的时间,疯狂刷进度,边写代码边写了一整系列的博客开发笔记,目前为止已经写了16篇了,然后上3月之后工作有点忙加上有点沉迷原神,然后进度就暂时慢下来了

事实证明做什么事情一旦停下来就会产生惰性,于是停了这么久,我终于下定决心继续更新!

这次开发的博客用的是C#语言,搭配.netcore技术栈;前端继续用我比较熟悉的Bootstrap做布局,然后稍微折腾一下;管理端用的是Vue…… 过程中总能遇到一些技术问题,除了在博客开发笔记系列里记录,还是把一些普适性的解决方案单独拿出来。

我的博客采用程序员最爱的Markdown语法书写,而众所周知markdown有一个缺点就是关联图片资源麻烦

因为我的博客需要实现本地用Typora写的Markdown文档导入,所以解析markdown文档并处理导入图片资源是一个绕不过的坎。

如题,本文介绍的是C#解析Markdown文档。

Markdig库

之前我用Python实现过解析Markdown文档,Python生态里相关的库太多了,有很多很好的选择,之前我写的用Python实现解析Markdown的文章:python实现解析markdown文档中的图片,并且保存到本地~

然而C#这边基本没啥可选的,官方的Markdown库也标记为弃用状态,推荐迁移到Markdig这个库……

所以就没得选了,只能用这个Markdig。

官方介绍:

Markdig is a fast, powerful, CommonMark compliant, extensible Markdown processor for .NET.

其实这个库也不难用,但注意官方介绍里有这么一句话:

NOTE: The repository is under construction. There will be a dedicated website and proper documentation at some point!

喵的!就是完全没文档,用法基本靠猜和啃源码 ヽ(ー_ー)ノ

为了实现这个markdown图片导入,我只能硬着头皮搞起来

实现思路

Markdig有一个管道机制

举个例子的伪代码如下:

  1. var pipeline = new MarkdownPipelineBuilder()
  2. .UseExt1()
  3. .UseExt2()
  4. .UseExt3()
  5. .Build();
  6. var result = Markdown.ToHtml("This is a text with some *emphasis*", pipeline);

可以在解析Markdown过程中对Markdown文档做一些修饰处理

一开始我想到自己写一个管道来实现将Markdown里的图片链接做替换处理

然而(可能因为太菜)看了好几个官方的管道代码,也没琢磨出怎么实现我要的效果

直到我回想起官方介绍里的一个关键词:CommonMark compliant,就是说这玩意是兼容CommonMark

灵光一闪,Markdig因为是新项目还没文档,那作为老项目的CommonMark总有文档吧,于是我去找到了CommonMark.NET项目,一看果然有文档,虽然两者的API并不完全一致,但经过我的半蒙半猜的探索,终于是把要的功能搞定了~ ( ̄▽ ̄)~*

实现代码

终于上代码啦~

首先读取一个Markdown文档,得到MarkdownDocument对象

  1. // 引入需要用到的命名空间
  2. using Markdig;
  3. using Markdig.Renderers.Normalize;
  4. using Markdig.Syntax;
  5. using Markdig.Syntax.Inlines;
  6. var filepath = "temp/blog/机器学习/多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.md";
  7. var md = File.ReadAllText(filepath);
  8. var document = Markdown.Parse(md);

这个文档的部分内容如下:

  1. ## 前言
  2. 前段时间无聊回坑玩《开罗拉面店》,这是一款模拟经营类的小游戏,不管是画风还是游戏性都很对我胃口。
  3. ![](多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-ea70bbc1e5c28b62.png)
  4. ![](多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-3dd13511e9063800.png)
  5. ![](多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-8fcc0475f92cfc84.png)
  6. 里面有一个玩法是拉面店布局,就给你一块地,还有几家店铺,你可以随便铺随便摆,当然肯定是摆的越多家店铺越好。
  7. ![](多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-f2c6578cb8f77c31.png)
  8. 我一开始玩的时候也没想那么多,随便摆了摆就完事了,但玩到后期人气上不去,我就突发奇想,能不能把所有店铺摆进去?或者能不能尽可能多地去铺满这块地?

Markdig会把Markdown文档解析成一个文档树,接下来可以像DOM操作那样遍历文档节点了~

下面的代码是找出Markdown中的图片链接节点,并给图片链接加上前缀

  1. foreach (var node in document.AsEnumerable()) {
  2. if (node is ParagraphBlock { Inline: { } } paragraphBlock) {
  3. foreach (var inline in paragraphBlock.Inline) {
  4. if (inline is LinkInline {IsImage: true} linkInline) {
  5. // 这里就是图片链接了
  6. // 实现给图片链接加上前缀
  7. linkInline.Url = $"http://127.0.0.1:5038/assets/blog/{linkInline.Url}";
  8. Console.WriteLine(linkInline.Url);
  9. }
  10. }
  11. }
  12. }

然后把修改完的Markdown文档重新输出:

  1. using (var writer = new StringWriter()) {
  2. var render = new NormalizeRenderer(writer);
  3. render.Render(document);
  4. Console.WriteLine(writer.ToString());
  5. }

最终实现的效果就是这样

  1. ## 前言
  2. 前段时间无聊回坑玩《开罗拉面店》,这是一款模拟经营类的小游戏,不管是画风还是游戏性都很对我胃口。
  3. ![](http://127.0.0.1:5038/assets/blog/多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-ea70bbc1e5c28b62.png)
  4. ![](http://127.0.0.1:5038/assets/blog/多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-3dd13511e9063800.png)
  5. ![](http://127.0.0.1:5038/assets/blog/多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局.assets/8869373-8fcc0475f92cfc84.png)
  6. 里面有一个玩法是拉面店布局,就给你一块地,还有几家店铺,你可以随便铺随便摆,当然肯定是摆的越多家店铺越好。

后续

能实现把markdown文档里的图片链接拿出来,那后续的图片导入、链接替换就好办了,当然这是博客开发笔记里的内容,本文就不写了。

C#语言很不错,可惜第三方库的生态还是差了点,这个问题如果我用Python的话早就解决了,但C#的话就只能折腾,我甚至一度想要自己造个轮子来解析了……

其实应该不难,我想到的办法就是每一行遍历文档,然后用正则表达式把图片链接匹配出来,后续处理完成再用正则做替换,不过不太优雅就是了,在这个写代码靠copy的时代还是要有点追求,不然跟咸鱼有什么区别呢……

然后再唠一下最近在搞的好玩的东西:

  • 受俄乌战争警醒的「去Windows化」
  • 寻找国内的微信替代品「去腾讯化」

OK,接下来应该会开始更新博客开发笔记系列文章~(*^▽^*)

参考资料

C#解析Markdown文档,实现替换图片链接操作的更多相关文章

  1. python实现解析markdown文档中的图片,并且保存到本地~

    背景 前阵子简书好像说是凉了,搞得我有点小慌,毕竟我的大部分博客都是放在简书上面的,虽然简书提供了打包导出功能,但是只能导出文字,图片的话还是存在简书服务器上面,再加上我一直想要重新做一个个人博客,于 ...

  2. js 加载并解析Markdown文档

    网上有很多网站会通过.md文档来做页面内容(比如,阮一峰老师的es6入门blog: http://es6.ruanyifeng.com/),很好奇,这是怎么做的?(至于.md是什么,或许(https: ...

  3. 01将图片嵌入到Markdown文档中

    将图片内嵌入Markdown文档中 将图片嵌入Markdown文档中一直是一个比较麻烦的事情.通常的做法是将图片存入本地某个路径或者网络存储空间,使用URL链接的形式插入图片: ![image][ur ...

  4. C#实现生成Markdown文档目录树

    前言 之前我写了一篇关于C#处理Markdown文档的文章:C#解析Markdown文档,实现替换图片链接操作 算是第一次尝试使用C#处理Markdown文档,然后最近又把博客网站的前台改了一下,目前 ...

  5. 使用Python从Markdown文档中自动生成标题导航

    概述 知识与思路 代码实现 概述 Markdown 很适合于技术写作,因为技术写作并不需要花哨的排版和内容, 只要内容生动而严谨,文笔朴实而优美. 为了编写对读者更友好的文章,有必要生成文章的标题导航 ...

  6. 精讲 org.w3c.dom(java dom)解析XML文档

    org.w3c.dom(java dom)解析XML文档 位于org.w3c.dom操作XML会比较简单,就是将XML看做是一颗树,DOM就是对这颗树的一个数据结构的描述,但对大型XML文件效果可能会 ...

  7. go语言生成markdown文档工具

    虽然有go语言的swagger,但是go版本的swagger对代码的侵入比较大,因此抽空实现了基于GO语言生成markdown文档的工具 开源链接地址: https://github.com/w3li ...

  8. python 解析docx文档的方法,以及利用Python从docx文档提取插入的文本对象和图片

    首先安装docx模块,通过pip install docx或者在docx官方链接上下载安装都可以 下面来看下如何解析docx文档:文档格式如下 有3个部分组成 1 正文:text文档 2 一个表格. ...

  9. php解析word,获得文档中的图片

    背景 前段时间在写一个功能:用原生php将获得word中的内容并导入到网站系统中.因为文档中存在公式,图片,表格等,因此写的比较麻烦. 思路 大体思路是先将word中格式为doc的文档转化为docx, ...

随机推荐

  1. SpringCloud微服务实战——搭建企业级开发框架(三十六):使用Spring Cloud Stream实现可灵活配置消息中间件的功能

      在以往消息队列的使用中,我们通常使用集成消息中间件开源包来实现对应功能,而消息中间件的实现又有多种,比如目前比较主流的ActiveMQ.RocketMQ.RabbitMQ.Kafka,Stream ...

  2. Solution -「AGC 036D」「AT 5147」Negative Cycle

    \(\mathcal{Descriprtion}\)   Link.   在一个含 \(n\) 个结点的有向图中,存在边 \(\lang i,i+1,0\rang\),它们不能被删除:还有边 \(\l ...

  3. scrapy爬取《坏蛋是怎样练成的4》

    scrapy具体介绍就不用说了,自己百度一下.或者参考以下文档 https://blog.csdn.net/u011054333/article/details/70165401 直接在cmd里运行 ...

  4. ASP.NET Core 6框架揭秘实例演示[09]:配置绑定

    我们倾向于将IConfiguration对象转换成一个具体的对象,以面向对象的方式来使用配置,我们将这个转换过程称为配置绑定.除了将配置树叶子节点配置节的绑定为某种标量对象外,我们还可以直接将一个配置 ...

  5. k8s容器拷贝文件到本地、本地文件拷贝到k8s容器

    k8s容器拷贝文件到本地 kubectl cp qzcsbj/order-b477c8947-tr8rz:/tmp/jstack.txt /root/test/jstack.txt 本地文件拷贝到k8 ...

  6. [杂记]如何在LaTeX里插入高亮代码

    继上次学会在ppt里面插入带有高亮的c程序代码之后,zyy在这条不归路上越走越远-- 好的,长话短说,今天我介绍的是怎么在LaTeX中插入高亮的c程序代码.(其实不止c程序的代码,别的语言也是可以的, ...

  7. 【C# .Net GC】延迟模式 latencyMode 通过API-GC调优

    延迟模式 lowlatency 使用环境:后台工作方式只影响第 2 代中的垃圾回收:第 0 代和第 1 代中的垃圾回收始终是非并发的,因为它们完成的速度很快.GC模式是针对进程配置的,进程运行期间不能 ...

  8. 【windows 操作系统】进程间通信(IPC)简述|无名管道和命名管道 消息队列、信号量、共享存储、Socket、Streams等

    一.进程间通信简述 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进 ...

  9. C#源代码的组成

    引用 using  ...表达式  i=5.i>5 语句:int i=5: 快( block ):{ }

  10. Oracle之表和字段的注释

    给表名加上注释 --给表名加上注释的语法结构 --语法结构:COMMENT ON TABLE 英文表名 IS '中文注释' COMMENT ON TABLE DEPT IS '部门表'; 给字段加上注 ...