markdown-it
markdown-it是一个用来解析markdown的库,它能够将markdown代码编译为html代码。
模式
markdown-it 提供了三种模式:commonmark、default、zero。分别对应最严格、GFM、最宽松的解析模式。
解析
markdown-it 的解析规则可分为块(block)和内联(inline)两种。具体可体现为 MarkdownIt.block
对应的是解析块规则的 ParserBlock, MarkdownIt.inline
对应的是解析内联规则的 ParserInline。解析的过程是,首先创建一个 Core Parser,这个 Core Parser 包含一系列的缺省 rules。这些rules 将顺序执行,每个 rules 都在前面的 Tokens 的基础上,要么修改原来的 Token,要么添加新的 Token。这个 rules 的链条被称为 Core Chain。
经过解析后我们得到的结果不是一颗 AST 树,而是一个数组,markdown-it 称之为 token 流。为什么呢?
官方解释是:
- Tokens 是一个简单的数组。(AST 是一个对象)
- 打开的标签和关闭的标签可以隔离。
- 将“内联容器(inline container)”作为一种特殊的 block token 对象。它有嵌套的 tokens,如粗体,斜体,文本等等。
这样做有什么好处呢?这样就可以并行处理 block 和 inline 类型的 token 了。
比如通过markdown-it我们可以把# change!
转化为以下内容:
[
{
"type": "heading_open",
"tag": "h1",
"attrs": null,
"map": [
0,
1
],
"nesting": 1,
"level": 0,
"children": null,
"content": "",
"markup": "#",
"info": "",
"meta": null,
"block": true,
"hidden": false
},
{
"type": "inline",
"tag": "",
"attrs": null,
"map": [
0,
1
],
"nesting": 0,
"level": 1,
"children": [
{
"type": "text",
"tag": "",
"attrs": null,
"map": null,
"nesting": 0,
"level": 0,
"children": null,
"content": "change!",
"markup": "",
"info": "",
"meta": null,
"block": false,
"hidden": false
}
],
"content": "change!",
"markup": "",
"info": "",
"meta": null,
"block": true,
"hidden": false
},
{
"type": "heading_close",
"tag": "h1",
"attrs": null,
"map": null,
"nesting": -1,
"level": 0,
"children": null,
"content": "",
"markup": "#",
"info": "",
"meta": null,
"block": true,
"hidden": false
}
]
渲染器
它会遍历所有 token,将每个 token 传递给与 token 的 type 属性同名的规则。markdown-it 内置了九种规则:围栏、行内代码、代码块、html 块、行内 html、图片、硬换行、软换行、文本。type 属性不在内置规则的 token 将会被被传入 renderToken 中当一个普通 token 处理。MarkdownIt.renderer.render
和 MarkdownIt.renderer.renderInline
分别对应按照块规则和内联规则生成 HTML 代码。而在 MarkdownIt.renderer 中有一个特殊的属性:rules,它代表着对于 token 们的渲染规则,可以被使用者更新或扩展:
var md = require('markdown-it')();
md.renderer.rules.strong_open = function () { return ''; };
md.renderer.rules.strong_close = function () { return ''; };
var result = md.renderInline(...);
比如这段代码就更新了渲染 strong_open 和 strong_close 这两种 token 的渲染规则。
插件系统
markdown-it 只做纯粹的 markdown 解析,但我们们可以通过提供插件来实现不同的功能。通过MarkdownIt.use便可以将指定的插件加载到当前的解析器实例中:
var md = require('markdown-it')()
.use(require('markdown-it-container'), name [, options]);