前言最近看vuePress源码时发现在应用markdownLoader之余应用了大量的markdown-it插件,除了社区插件(如高亮代码、代码块包裹、emoji等),同时也自行编写了很多自定义插件(如内外链辨别渲染等)。文章联合源码和本人之前写过的插件来具体解读如何编写一个markdown-it插件。
简介markdown-it是一个辅助解析markdown的库,能够实现从 # test 到 <h1>test</h1> 的转换,渲染过程和babel相似为Parse -> Transform -> Generate。
Parsesource通过3个嵌套的规定链core、block & inline进行解析:
core core.rule1 (normalize) ... core.ruleX block block.rule1 (blockquote) ... block.ruleX inline (applied to each block token with "inline" type) inline.rule1 (text) ... inline.ruleX解析的后果是一个token列表,将传递给renderer以生成html内容。如果要实现新的markdown语法,能够从Parse过程动手:能够在md.core.ruler、md.block.ruler & md.inline.ruler中自定义规定,规定的定义方法有before、after、at、disable、enable等。
// @vuepress/markdown代码片段md.block.ruler.before('fence', 'snippet', function replace(state, startLine, endLine, silent) { //...});上述代码在md.block.ruler.fence之前退出snippet规定,用作解析 <<< @/filepath 这样的代码。具体代码就不详细分析了,个别parse阶段用到的状况比拟少,感兴趣的能够自行查看vuePress源码。
TransformToken通过[官网在线示例](https://markdown-it.github.io/)拿 # test 举例,会失去如下后果:
[ { "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": "test", "markup": "", "info": "", "meta": null, "block": false, "hidden": false } ], "content": "test", "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,代替传统的 AST。区别很简略:
...