前言
继第二篇博客文章发布后,博客文章在阅读方面已基本不存在问题。然而,对于一些 Hexo 无法识别的语法,目前尚未进行处理。在本篇内容中,我们将把 Markdown 的呼出块语法与高亮语法进行转换。
markdown 转 AST
此次需要解析的 Markdown 语法相对较为复杂,不能像上一篇那样直接使用正则匹配语法,否则可能会导致不应该转换的地方也被转换了。因此,我们需要借助 Markdown 解析库,将其转换为抽象语法树(AST)。
什么是 AST
在深入探讨之前,我们先来简要介绍一下什么是 AST,以免有些朋友在阅读时感到困惑。
AST(抽象语法树)是一种将代码组织成树形结构的形式,使得计算机能够更轻松地理解代码的含义。可以将其看作是代码的 “骨架图”,每一个节点代表代码中的一个小结构(例如变量、运算符、函数等),而这些小结构通过分支连接起来,展示了代码的整体逻辑关系。
例如,假设我们有一段代码:a = 5 + 2
。转换为 AST 后,计算机能够识别出 “变量 a
被赋值给 5 + 2
”,而不仅仅是看到 “a = 5 + 2
” 这几个字符。这样,它就知道这段代码在进行一个赋值操作,左边是变量,右边是加法运算。
这个结构化的 “骨架” 对于许多工具都非常有用,比如编译器(将代码翻译成机器可以运行的指令)、代码检查工具(查找代码中的错误或优化点),甚至是自动格式化工具(调整代码风格)。通过 AST,这些工具能够准确地分析代码、优化代码,或者将其转换为其他语言。
JS AST
下面是一个简单的 JavaScript AST 示例:
markdown AST
下面是一个简单的 markdown AST 示例:
实现过程
ast 解析库
我们自然不可能手动实现一个 Markdown 的 AST 解析库,因此需要引入现有的知名库来帮助我们进行处理。
我们采用 remark
这个库来进行 Markdown 的转换。
我们需要引入四个库,分别是remark
、remark-parse
、remark-stringify
和unist-util-visit
。remark
作为主库,通过插件的方式集成了remark-parse
和remark-stringify
。remark-parse
用于将 Markdown 转换为 AST 对象,而remark-stringify
则将 AST 对象再转换为 Markdown 文本。最后的unist-util-visit
用于处理转换好的 AST,通过这个库,我们可以轻松地处理需要处理的节点与类型,而无需自己编写递归遍历方法。
使用 ast 解析库
首先,将 Markdown 正文转换为 AST。
接着,遍历并修改 AST 中的内容。
最后,将处理后的 AST 转换回 Markdown 文本。
具体代码实现
呼出块语法转换
Obsidian 呼出块的语法及样式如下:
同时,他还支持通过在在后面追加 +
、-
, 设置为可以展开的呼出块:
我们首先通过visit
方法,过滤出blockquot
语法块内容,即:使用>
开头的语法。
然后,通过正则匹配首行内容是否以[!xxx]
开头,或者[!xxx]+
、[!xxx]-
开头的,前者是正常的呼出块,后者是可折叠的呼出块。
通过正则匹配出呼出块的类型、是否可折叠以及呼出块的标题,再根据 Hexo 的语法转换进行转换。
Hexo 可折叠的 tag 语法如下:
我们需要将> [!INFO]
语法转换为{% note info %}
语法,> [!NOTE]+
转换为{% fold info @标题 %}
语法。
高亮语法转换
高亮语法块通过四个等号作为高亮语法,效果如下:
Markdown 的语法很简单,我们直接匹配text
类型的节点,然后直接过滤掉code
类型的语法块,也就是代码块,因为代码块中出现这种类型的语法概率比较大,比如本文下面的这个代码块就用到了。
然后使用正则根据分割出高亮语法块,这里我们要手动判断一下匹配出的内容前后是否有空格,如果有空格则说明不是高亮语法块,所以需要还原回去,如果没有空格,则是高亮语法块,我们通过span
标签,添加一个显著的高亮色 (这里就看个人喜好了,我更喜欢橘黄色的字体,而不是屎黄色的背景色)。
结语
基本语法转换就介绍到这里了。目前我遇到的需要兼容的语法也就这两个,所以也仅转换了这两个语法。
至此,博客文章的展示效果又得到了进一步优化。如果是一般的 Obsidian 用户,基本已经大功告成了。但如果你使用了 Excalidraw 插件,那么还需要进一步优化。