5

基于.NetCore开发博客项目 StarBlog - (19) Markdown渲染方案探索 - 程序设计实验室

 1 year ago
source link: https://www.cnblogs.com/deali/p/16834452.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

基于.NetCore开发博客项目 StarBlog

笔者认为,一个博客网站,最核心的是阅读体验。

在开发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_contrast and colorblind variants. 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内味了,但还没代码高亮

866942-20221028091030612-911024774.png

目前使用 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>

有了代码高亮,一下就不一样了

866942-20221028091049592-1073147716.png

还有很多其他主题,styles 目录下很多,引入css的时候自行选择即可

我来换个深色的主题看看

866942-20221028091101151-735364741.png

__EOF__


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK