markdown-it自定义输出标签格式


这两天在从零开始手写新博客,在收尾阶段处理了下markdown的解析,用到的是markdown-it库。

用法很简单,直接v-html="markdownIt.render(markdown内容)"就行了

但因为特殊需求,比如给tabel标签外套一层div,用来做水平溢出滚动效果,需要更改下输出配置,这可就犯难了

上网到处找,但相关内容太少,官方文档也过于简单,直到看到这个大佬的文章:使用markdown-it插件

思路

文章中提到了markdown-it是借用Token序列渲染导出配置的,而对应渲染规则的方法则在markdownIt.renderer.rules内,每个html元素都对应两个渲染方法[DOM_NAME]_open
[DOM_NAME]_close,如a标签的规则名字就是link_open

但问题来了,这个DOM_NAME怎么获得呢?文章中给出了通过打印参数Token来获取,但我尝试了,未果,随意写一个dom_name的话得到的token为null;即使手动重写了已知的link_open
,其参数token也仅仅包含文章中的a标签,并不包括其他标签。网上也找不到相关文章,这就把我难住了

查看源码

最终我决定去翻阅markdown-it源码,发现他的lib目录中有各自的解析规则,如下图,我所需要的table就在这里

这三个文件夹内为所有的标签规则

打开 table.js,找到这一部分

包含规则标签的部分

这部分可以看出,table标签包含的渲染规则名有:table_open、thead_open、tr_open、th_open、inline、th_close、tr_close、thead_close、table_close

既然拿到了规则,那么可以很容易的开始着手于修改渲染结果了

修改渲染规则

新建markdown/index.js文件,填入以下基本内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import Vue from 'vue'
// 引入 markdownIt
import MarkdownIt from 'markdown-it'

const md = new MarkdownIt({
html: true,
linkify: true,
typographer: true
})

// 这里为渲染规则修改部分配置
...

// 写入Vue全局方便调用
Vue.prototype.$markdownIt = md

简单修改

我希望渲染的table标签被包裹在自带类名table-responsive和box-shadow-wrap-lg的div中,根据前文源码得知,table起始和结束的标签规则名为table_opentable_close
,则配置代码如下

1
2
3
4
5
6
md.renderer.rules.table_open = (tokens, idx, options, env, self) => {
return '<div class="table-responsive box-shadow-wrap-lg"><table>'
}
md.renderer.rules.table_close = (tokens, idx, options, env, self) => {
return '</table></div>'
}

深层修改

规则渲染方法几个形参作用解释:

  • tokens:文章所有此规则集合(一篇文章会有多个table标签)
  • idx:当前渲染标签在规则集合中的索引

通过这几个形参,可以获得每个渲染标签的详细内容,如

1
2
3
4
// 获取当前渲染标签的属性数组
tokens[idx].attrs
// 获取标签内容
tokens[idx].content

既然这样,那就可以来点更深层次的修改了。

我希望能让每一个image标签被渲染为如下几个特点

  • 独居一行
  • 图片下方包含介绍文本
  • 介绍文本自带类名方便修改样式 规则代码处理方式如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
md.renderer.rules.image = (tokens, idx, options, env, self) => {
const srcItem = tokens[idx].attrs.find(item => {
return item[0] === 'src'
})
const src = srcItem[1]
const alt = tokens[idx].content
return `<p>
<div class="light-link" data-fancybox="gallery" no-pjax="" data-type="image" data-caption="${alt}">
<img src="${src}" alt="${alt}" />
<span class="post-img-desc">${alt}</span>
</div>
</p>`
}

小幅修改

有的时候可能只是想给原规则渲染结果添加一个属性(如class类名),并不需要其他大幅修改

渲染对象提供了attrSet方法来实现添加属性这一操作,添加后直接将规则原路返回即可实现规则渲染修改

例如,我希望给删除线的渲染结果添加一个title属性,代码处理如下

1
2
3
4
5
// 复写删除线
md.renderer.rules.s_open = (tokens, idx, options, env, self) => {
tokens[idx].attrSet('title', '你知道的太多了')
return md.renderer.renderToken(tokens, idx, options, env, self)
}

参考

使用markdown-it插件