var md = require('markdown-it')();
var defaultRender = md.renderer.rules.image,
vimeoRE = /^https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/;
md.renderer.rules.image = function (tokens, idx, options, env, self) {
var token = tokens[idx],
aIndex = token.attrIndex('src');
if (vimeoRE.test(token.attrs[aIndex][1])) {
var id = token.attrs[aIndex][1].match(vimeoRE)[2];
return '<div class="embed-responsive embed-responsive-16by9">\n' +
' <iframe class="embed-responsive-item" src="//player.vimeo.com/video/' + id + '"></iframe>\n' +
'</div>\n';
}
// pass token to default renderer.
return defaultRender(tokens, idx, options, env, self);
};
rules.image 传入的函数参数可以查看 renderer.js 的源码:
Renderer.prototype.render = function (tokens, options, env) {
var i, len, type,
result = '',
rules = this.rules;
for (i = 0, len = tokens.length; i < len; i++) {
type = tokens[i].type;
if (type === 'inline') {
result += this.renderInline(tokens[i].children, options, env);
} else if (typeof rules[type] !== 'undefined') {
result += rules[tokens[i].type](tokens, i, options, env, this);
} else {
result += this.renderToken(tokens, i, options, env);
}
}
return result;
};
前言
在 《一篇带你用 VuePress + Github Pages 搭建博客》中,我们使用 VuePress 搭建了一个博客,最终的效果查看:TypeScript 中文文档。
在搭建博客的过程中,我们出于实际的需求,在《VuePress 博客优化之拓展 Markdown 语法》中讲解了如何写一个
markdown-it
插件,又在 《markdown-it 原理解析》中讲解了markdown-it
的执行原理,本篇我们将讲解具体的实战代码,帮助大家更好的写插件。renderer
markdown-it
的渲染过程分为两部分,Parse
和Render
,如果我们要更改渲染的效果,就比如在外层包裹一层div
,或者修改 HTML 元素的属性、添加class
等,就可以从Render
过程入手。在 markdown-it 的官方文档里就可以找到自定义
Render
渲染规则的方式:markdown-it
内置了一些默认的rules
,你可以直接修改它们,具体有哪些以及渲染方式可以查看 renderer.js 的源码,这里直接列出来:实例一
如果我们查看 VuePress 中代码块的渲染结果,我们会发现每一个代码块外层都包了一层带
extra-class
类名的div
:其实,这就是 VuePress 修改了渲染规则产生的,查看 VuePress 源码:
我们可以看到这里非常巧妙的避开了处理 token,直接使用渲染后的结果,在外层包了一层 div。
实例二
类似于 VuePress 的这种方式,我们也可以在获取默认渲染内容后,再使用 replace 替换掉一些内容,比如在《VuePress 博客优化之拓展 Markdown 语法》这篇中,我们自定义了一个代码块语法,就是在
rules.fence
中修改了渲染的内容:实例三
但不可能总是可以这么取巧,有的时候就是需要处理 token,这里我们参考 markdown-it 官方提供的设计准则中的例子,当渲染一个图片的时候,如果链接匹配
/^https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/
,我们就将其渲染为一个iframe
,其他的则保持默认渲染方式:rules.image
传入的函数参数可以查看renderer.js
的源码:我们可以看到 rules 传入的参数,其中 tokens 就是指 tokens 列表,idx 则是指要渲染的 token 索引,所以在代码里才可以通过
tokens[index]
获取目标 token。然后我们又使用了
tokens.attrIndex
,tokens 提供了哪些方法可以查看官方 API,或者直接查看 Token 源码。我们解释一下这个示例里用到的一些方法,先从 token 开始说起,我们举个例子,看下
![video link]([https://www.vimeo.com/123)](https://www.vimeo.com/123))
这句 markdown 语法产生的 token(这里进行了简化):可以看到 token 是有一个
attr
属性的,表明了要渲染的 img 标签的属性有哪些,token.attrIndex
就是通过名字获取属性索引,然后再通过token.attrs[aIndex][1]
获取具体的属性值。实例四
同样是来自 markdown-it 官方提供的设计准则中的例子,给所有的链接添加
target="_blank"
:也许你会奇怪,为什么会有
rules.link_open
?这个并不在默认规则里呀,可以直接使用吗?还真是可以的,其实这里的
link_open
和之前的image
、fence
等都是 token 的 type,所以只要是 token 的 type 就可以,那 token 有哪些 type 呢?有具体的说明文档吗?关于这个问题,![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6c5fda3c5cb24c26b93a7e3515e15fa4~tplv-k3u1fbpfcp-zoom-1.image)
markdown-it
也有 issues 里提出:作者的意思就是,没有,如果你想写插件,你就去看源码……
那成吧,其实在我们的实际开发中,如果你想要知道某一个 token type,其实完全可以打印出 token 看一下,官方的 Live Demo 提供了 debug 模式用于查看 token:
当然就这个例子里的需求,作者还提供了
markdown-it-for-inline
插件用于简化代码书写:关于
markdown-it-for-inline
就在以后的文章里介绍了。系列文章
博客搭建系列是我至今写的唯一一个偏实战的系列教程,预计 20 篇左右,讲解如何使用 VuePress 搭建、优化博客,并部署到 GitHub、Gitee、私有服务器等平台。全系列文章地址:https://github.com/mqyqingfeng/Blog
微信:「mqyqingfeng」,加我进冴羽唯一的读者群。
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。