大约去年,拼拼凑凑写过几个markdown-it插件,差不多忘干净了。
还得再次翻阅文档理解一下:
说明
markdown-it内置了一些默认渲染规则(可以通过打印console.log(Object.keys(md.renderer.rules))
来看到):
'code_inline',
'code_block',
'fence',
'image',
'hardbreak',
'softbreak',
'text',
'html_block',
'html_inline'
'code_inline',
'code_block',
'fence',
'image',
'hardbreak',
'softbreak',
'text',
'html_block',
'html_inline'
对于此数组中未明确列出的任何元素,将应用其默认规则。
简单理解就是,markdown-it解析文档的时候,将markdown文档的内容分成若干部分(和ast解析不一样)。每个部分会给与一个标识token。
例如:
greed is `good`
greed is `good`
会被渲染成
<p>greed is <code>good</code></p>
<p>greed is <code>good</code></p>
中间处理成token list 如下:
{
"type": "paragraph_open",
"tag": "p",
"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": "greed is ",
"markup": "",
"info": "",
"meta": null,
"block": false,
"hidden": false
},
{
"type": "code_inline",
"tag": "code",
"attrs": null,
"map": null,
"nesting": 0,
"level": 0,
"children": null,
"content": "good",
"markup": "`",
"info": "",
"meta": null,
"block": false,
"hidden": false
}
],
"content": "greed is `good`",
"markup": "",
"info": "",
"meta": null,
"block": true,
"hidden": false
},
{
"type": "paragraph_close",
"tag": "p",
"attrs": null,
"map": null,
"nesting": -1,
"level": 0,
"children": null,
"content": "",
"markup": "",
"info": "",
"meta": null,
"block": true,
"hidden": false
}
]
{
"type": "paragraph_open",
"tag": "p",
"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": "greed is ",
"markup": "",
"info": "",
"meta": null,
"block": false,
"hidden": false
},
{
"type": "code_inline",
"tag": "code",
"attrs": null,
"map": null,
"nesting": 0,
"level": 0,
"children": null,
"content": "good",
"markup": "`",
"info": "",
"meta": null,
"block": false,
"hidden": false
}
],
"content": "greed is `good`",
"markup": "",
"info": "",
"meta": null,
"block": true,
"hidden": false
},
{
"type": "paragraph_close",
"tag": "p",
"attrs": null,
"map": null,
"nesting": -1,
"level": 0,
"children": null,
"content": "",
"markup": "",
"info": "",
"meta": null,
"block": true,
"hidden": false
}
]
画个草图描述下:
示例1. 官方示例
给每个ul
标签增加一个名为lorem_ipsum
的class:
通过在线debug,可以看到看到ul
开标签对应的type为 bulle_list_open
,由于这个标签没有默认渲染规则里,因此默认渲染的时会使用Renderer.prototype.renderToken
来渲染。("For example the rule bullet_list_open
is not defined, so when markdown-it tries to parse a list to HTML it defaults to ua generic renderer called Renderer.prototype.renderToken
")
js
// 开发插件的最佳实践是保存元素的默认渲染器,并对规则做最小的改动,而不是重新发明轮子:
const proxy = (tokens, idx, options, env, self) => self.renderToken(tokens, idx, options);
const defaultBulletListOpenRenderer = md.renderer.rules.bullet_list_open || proxy;
// 增加新的rules:
md.renderer.rules.bullet_list_open = function(tokens, idx, options, env, self) {
// tokens: 正在解析的所有的token列表
// idx: tokens 中当前 token 的 key 对应的数字
// options: 创建新的 markdown-it 对象时定义的选项(在我们的例子中为 {})
// env ???
// self: renderer自身的引用
// attrJoin 通过空格将值连接到现有属性。如果不存在则创建新属性。
tokens[idx].attrJoin("class", "lorem_ipsum")
// Make your changes here ...
// ... then render it using the existing logic
return defaultBulletListOpenRenderer(tokens, idx, options, env, self)
};
// 开发插件的最佳实践是保存元素的默认渲染器,并对规则做最小的改动,而不是重新发明轮子:
const proxy = (tokens, idx, options, env, self) => self.renderToken(tokens, idx, options);
const defaultBulletListOpenRenderer = md.renderer.rules.bullet_list_open || proxy;
// 增加新的rules:
md.renderer.rules.bullet_list_open = function(tokens, idx, options, env, self) {
// tokens: 正在解析的所有的token列表
// idx: tokens 中当前 token 的 key 对应的数字
// options: 创建新的 markdown-it 对象时定义的选项(在我们的例子中为 {})
// env ???
// self: renderer自身的引用
// attrJoin 通过空格将值连接到现有属性。如果不存在则创建新属性。
tokens[idx].attrJoin("class", "lorem_ipsum")
// Make your changes here ...
// ... then render it using the existing logic
return defaultBulletListOpenRenderer(tokens, idx, options, env, self)
};
相关名词
- nesting
{ nesting: 1}
is an opening tag:<ul>
{ nesting: -1}
is a closing tag:</ul>
{ nesting: 0}
is a self-closing tag:<br />
更多见API文档: markdown-it 14.1.0 API documentation