基于.NetCore开发博客项目 StarBlog - (19) Markdown渲染方案探索
前言
笔者认为,一个博客网站,最核心的是阅读体验。
在开发StarBlog的过程中,最耗时的恰恰也是文章的展示部分功能。
最开始还没研究出来如何很好的使用后端渲染,所以只能先用Editor.md组件做前端渲染,过渡一下。前端渲染我是不满意的,因为性能较差,页面加载出来还会闪一下,有割裂感,影响体验。
现在我已经做出了比较完善的后端渲染方案,前端渲染就可以直接退休了。本文介绍StarBlog博客开发过程中的各种Markdown渲染方案(主要是介绍后端渲染)。
两种方案
前端渲染
使用 Editor.md 组件进行渲染,效果差强人意,主要是看中了其可以生成 ToC(文章目录) 的功能,但生成的 ToC 效果也比较差,后面是我fork了一份源码进行魔改才好一点。
魔改过程在这篇文章:魔改editormd组件,优化ToC渲染效果
优化 ToC 的这个功能我给官方提了PR,但没有响应,看了一下GitHub里有几十个PR,上次提交也是快4年前的事了,看来这个项目真的凉了……
除了这个 editor.md ,还有其他几个前端的方案:
看起来都不错,有没有 ToC 我没研究,博客园上有大佬写了一篇比较的文章,有兴趣的同学可以在参考资料中看看~
后端渲染
目前 C# 可用的 Markdown 库似乎只有 Markdig ,一开始我还在吐槽文档缺失导致很难用,甚至一度想自己造轮子重新做一个,不过最近有所改善,在研究了官方新增的几个文档之后,我对这个库的了解又加深了一些,功能确实很多,设计得也不错,扩展性很好~
所以暂时就用这个啦~
目前我的做法是用 Markdig 将 Markdown 生成 HTML,然后前端展示这个 HTML ,再结合 Bootstrap 或者 github-markdown-css 等样式库来美化正文显示效果,用 highlight.js 之类的JS库实现代码高亮。
至于文章的 ToC ,Markdig 没有现成的,我自己造轮子实现~
详见这篇文章:C#实现生成Markdown文档目录树
其实算是一种混合式的方案吧~
接下来介绍的内容围绕后端渲染展开。
处理 ToC
上一篇文章对于生成目录树已经说得比较清楚了,本文不再重复那么多,只说一下有区别的地方~
先解析Markdown文档,拿到所有标题节点
var headings = new List<Heading>();
foreach (var heading in document.Descendants<HeadingBlock>()) {
var item = new Heading {Level = heading.Level, Text = heading.Inline?.FirstChild?.ToString()};
headings.Add(item);
}
遍历进行处理。
原本直接把标题作为锚点的 href 属性,实际使用的时候是不行的,根据测试,Markdig生成锚点ID的规则如下
中文按照
- section
- section-1
- section-2
- ...
section后面的数字是在所有中文标题里出现的顺序,不是在全部标题里面的顺序。
英文就替换空格 + 转小写 (未考虑其他情况,事实上应该把特殊符号也一并替换掉)
所以处理 href 的时候分两种情况,用正则表达式 [\u4e00-\u9fbb] 检测是否包含中文字符。
var chineseTitleCount = 0;
for (var i = 0; i < headings.Count; i++) {
var item = headings[i];
var text = item.Text ?? "";
if (Regex.IsMatch(text, "[\u4e00-\u9fbb]")) {
item.Slug = chineseTitleCount == 0 ? "section" : $"section-{chineseTitleCount}";
chineseTitleCount++;
}
else {
item.Slug = text.Replace(" ", "-").ToLower();
}
// ...
}
搞定
样式
bootstrap 默认样式
默认样式还可以,不过会觉得少了点啥,或许可以研究一下各种在线Markdown编辑器的样式~
github-markdown-css
顾名思义是GitHub的markdown样式
地址: https://www.npmjs.com/package/github-markdown-css
安装后有三个文件
- github-markdown.css: (默认) 通过
@media (prefers-color-scheme)实现自动切换亮色/暗色主题 - github-markdown-light.css: 亮色主题
- github-markdown-dark.css: 暗色主题
官网还有一句话,但我不知道怎么自己生成,难道要我去github扒css下来?
You may know that now GitHub supports more than 2 themes including
dark_dimmed,dark_high_contrastandcolorblindvariants. If you want to try these themes, you can generate them on your own!
安装
yarn add github-markdown-css
引入
<link rel="stylesheet" href="~/lib/github-markdown-css/github-markdown-light.css">
使用
<div class="markdown-body">
@Html.Raw(Model.ContentHtml)
</div>
效果
确实有GitHub内味了,但还没代码高亮

代码高亮
目前使用 highlight.js 包,官网: https://www.npmjs.com/package/highlight.js
有很多其他的工具,不展开了,用这个足够了~
下载
要在网页上直接用没办法通过安装NPM包的方式,只能通过网址下载: https://highlightjs.org/download/
如果不想下载的话可以用CDN,但就只能支持部分语言高亮。
里面有好多种语言,竟然没全选按钮,一个个选太麻烦了,我写了个全选脚本,复制到浏览器控制台执行就能全选,然后下载。
document.querySelectorAll('input').forEach( item => {
if(item.getAttribute('type')==='checkbox') item.checked=true
})
引入
下载后把zip解压放到 wwwroot/lib 下
<link rel="stylesheet" href="~/lib/highlight/styles/default.min.css">
<script src="~/lib/highlight/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
或者不下载,直接使用 CDN
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/default.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
效果
有了代码高亮,一下就不一样了

还有很多其他主题,styles 目录下很多,引入css的时候自行选择即可
我来换个深色的主题看看

系列文章
- 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客?
- 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目
- 基于.NetCore开发博客项目 StarBlog - (3) 模型设计
- 基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入
- 基于.NetCore开发博客项目 StarBlog - (5) 开始搭建Web项目
- 基于.NetCore开发博客项目 StarBlog - (6) 页面开发之博客文章列表
- 基于.NetCore开发博客项目 StarBlog - (7) 页面开发之文章详情页面
- 基于.NetCore开发博客项目 StarBlog - (8) 分类层级结构展示
- 基于.NetCore开发博客项目 StarBlog - (9) 图片批量导入
- 基于.NetCore开发博客项目 StarBlog - (10) 图片瀑布流
- 基于.NetCore开发博客项目 StarBlog - (11) 实现访问统计
- 基于.NetCore开发博客项目 StarBlog - (12) Razor页面动态编译
- 基于.NetCore开发博客项目 StarBlog - (13) 加入友情链接功能
- 基于.NetCore开发博客项目 StarBlog - (14) 实现主题切换功能
- 基于.NetCore开发博客项目 StarBlog - (15) 生成随机尺寸图片
- 基于.NetCore开发博客项目 StarBlog - (16) 一些新功能 (监控/统计/配置/初始化)
- 基于.NetCore开发博客项目 StarBlog - (17) 自动下载文章里的外部图片
- 基于.NetCore开发博客项目 StarBlog - (18) 实现本地Typora文章打包上传
- 基于.NetCore开发博客项目 StarBlog - (19) Markdown渲染方案探索
参考资料
- JavaScript解析和渲染Markdown - https://www.cnblogs.com/makalochen/p/14464519.html#5117019
基于.NetCore开发博客项目 StarBlog - (19) Markdown渲染方案探索的更多相关文章
- 基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (5) 开始搭建Web项目
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (6) 页面开发之博客文章列表
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (7) 页面开发之文章详情页面
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (8) 分类层级结构展示
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (9) 图片批量导入
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (10) 图片瀑布流
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (11) 实现访问统计
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (12) Razor页面动态编译
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
随机推荐
- PerfView专题 (第七篇):如何洞察触发 GC 的 C# 代码?
一:背景 上一篇我们聊到了如何用 PerfView 洞察 GC 的变化,但总感觉还缺了点什么? 对,就是要跟踪到底是什么代码触发了 GC,这对我们分析由于 GC 导致的 CPU 爆高有非常大的参考价值 ...
- Excelize 发布 2.2.0 版本, Go 语言 Excel 文档基础库
Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准.可以使用它来读取.写入由 Microsoft Exc ...
- 使用MindSpore计算旋转矩阵
技术背景 坐标变换.旋转矩阵,是在线性空间常用的操作,在分子动力学模拟领域有非常广泛的应用.比如在一个体系中切换坐标,或者对整体分子进行旋转平移等.如果直接使用Numpy,是很容易可以实现的,只要把相 ...
- Flink介绍
1,简介 Flink是Apache基金会旗下的一个开源大数据处理框架.Flink很牛逼,好多牛逼的公司都在用. 2,特征 *高吞吐和低延迟.每秒处理百万个时间,毫秒级延迟.有点既要老婆好,又要彩礼少的 ...
- LGV 引理——二维DAG上 n 点对不相交路径方案数
文章目录 引入 简介 定义 引理 证明 例题 释疑 扩展 引入 有这样一个问题: 甲和乙在一张网格图上,初始位置 ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1,y_1),(x_ ...
- 【Java】学习路径33-在IDEA中使用junit单元测试运行单个方法
首先在菜单找到 文件-项目结构 项目设置-库-"+" 选择Java 找到IDEA安装目录,打开lib/junit4.jar 的jar包,然后打开即可. 然后选择确定. 然后再项目中 ...
- 分布式协同AI基准测试项目Ianvs:工业场景提升5倍研发效率
摘要:全场景可扩展的分布式协同AI基准测试项目 Ianvs(雅努斯),能为算法及服务开发者提供全面开发套件支持,以研发.衡量和优化分布式协同AI系统. 本文分享自华为云社区<KubeEdge|分 ...
- 第四十八篇:webpack的基本使用(二) --安装和配置webpack-dev-server插件
好家伙, 1.webpack中的默认约定 默认的打包入口文件为src -->index.js 默认的输出文件路径为dist -->main.js 既然有默认,那么就说明肯定能改 2.en ...
- MySQL Workbench生成E-R图
因为做毕业设计文档,需要写ER图,故记录此篇 第一步 选择添加 选择数据库 一直next选择要生成的表 再一直下一步就ok了
- PostgreSQL 涉及复杂视图查询的优化案例
一.前言 对于含有union , group by 等的视图,我们称之为复杂视图. 这类的视图会影响优化器对于视图的提升,也就是视图无法与父查询进行合并,从而影响访问路径.连接方法.连接顺序等.本文通 ...