You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
var_rules=[// First 2 params - rule name & source. Secondary array - list of rules,// which can be terminated by this one.['table',require('./rules_block/table'),['paragraph','reference']],['code',require('./rules_block/code')],['fence',require('./rules_block/fence'),['paragraph','reference','blockquote','list']],['blockquote',require('./rules_block/blockquote'),['paragraph','reference','blockquote','list']],['hr',require('./rules_block/hr'),['paragraph','reference','blockquote','list']],['list',require('./rules_block/list'),['paragraph','reference','blockquote']],['reference',require('./rules_block/reference')],['html_block',require('./rules_block/html_block'),['paragraph','reference','blockquote']],['heading',require('./rules_block/heading'),['paragraph','reference','blockquote']],['lheading',require('./rules_block/lheading')],['paragraph',require('./rules_block/paragraph')]];
前言
在 《一篇带你用 VuePress + Github Pages 搭建博客》中,我们使用 VuePress 搭建了一个博客,最终的效果查看:TypeScript 中文文档。
在搭建博客的过程中,我们出于实际的需求,在《VuePress 博客优化之拓展 Markdown 语法》中讲解了如何写一个
markdown-it
插件,又在 《markdown-it 原理解析》中讲解了markdown-it
的执行原理,本篇我们将讲解具体的实战代码,帮助大家更好的写插件。Parse
markdown-it
的渲染过程分为两部分,Parse
和Render
,如果我们要实现新的 markdown 语法,举个例子,比如我们希望解析@ header
为<h1>header</h1>
,就可以从Parse
过程入手。在 markdown-it 的官方文档里可以找到自定义 parse 规则的方式,那就是通过
Ruler
类:这句话的意思是指在
markdown-it
的解析 block 的一组规则中,在paragraph
规则前插入一个名为my_rule
的自定义规则,我们慢慢来解释。首先是
md.block.ruler
,除此之外,还有md.inline.ruler
、md.core.ruler
可以自定义其中的规则。然后是
.before
,查看 Ruler 相关的 API,还有after
、at
、disable
、enable
等方法,这是因为规则是按照顺序执行的,某一规则的改变可能会影响其他规则。接着是
paragraph
,我怎么知道插入在哪个规则前面或者后面呢?这就需要你看源码了,并没有文档给你讲这个……如果是
md.block
,查看 parse_block.js,如果是md.inline
,查看 parse_inline.js,如果是md.core
,查看 parse_core.js,我们以md.block
为例,可以看到源码里写了这些规则:最后是
function replace(state)
,这里函数的参数其实不止有state
,我们查看任何一个具体规则的 parse 代码,就比如heading.js
:可以看出除了
state
,还有startLine
、endLine
、silent
,而具体这其中的代码怎么写,其实最好的方式就是参考这些已经实现的代码。实例讲解
接下来我们以解析
@ header
为<h1>header</h1>
为例,讲解其中涉及的代码,这是要渲染的内容:正常它的渲染结果是:
现在期望的渲染结果是:
我们来看看如何实现,先参照 header.js 的代码依葫芦画瓢:
parse 的过程是根据换行符逐行扫描的,所以每一行的内容都会执行我们这个自定义函数进行匹配,函数支持传入四个参数,其中,
state
记录了各种状态数据,startLine
表示本次的起始行数,而endLine
表示总的结束行数。我们打印下
state``startLine
,endLine
等数据:这是打印的结果:
其中
state
的内容我们简化下展示出来:state
中这些字段的具体含义可以查看 state_block.js 文件,这其中:我们看下
pos
的计算逻辑为state.bMarks[startLine] + state.tShift[startLine]
,其中startLine
是 0,所以pos = 0 + 0 = 0
再看下
max
的计算逻辑为state.eMarks[startLine]
,所以max = 8
从这也可以看出,其实
pos
就是这行字符的初始位置,max
这行字符的结束位置,通过pos
和max
,我们可以截取出这行字符串:打印结果为:
在代码里我们加入了
state.line = startLine + 1;
和return true
,这是为了进入到下一行的遍历之中。如果我们能取出每次用于判断的字符串,那我们就可以进行正则匹配,如果匹配,就自定义 tokens,剩下的逻辑很简单,我们直接给出最后的代码:
至此,就实现了预期的效果:
系列文章
博客搭建系列是我至今写的唯一一个偏实战的系列教程,预计 20 篇左右,讲解如何使用 VuePress 搭建、优化博客,并部署到 GitHub、Gitee、私有服务器等平台。全系列文章地址:https://github.com/mqyqingfeng/Blog
微信:「mqyqingfeng」,加我进冴羽唯一的读者群。
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。
The text was updated successfully, but these errors were encountered: