前言最近在看vuePress源码的时候,发现除了用markdownLoader,我用了很多markdown-it插件,除了社区插件(比如高亮代码,锚点积分、表情符号识别等),同时自己也写了很多自定义插件(比如区分内外链渲染等)。文章结合源码和我之前写的插件详细讲解了如何编写markdown-it插件规则。介绍markdown——是一个辅助解析markdown的库。它可以完成从#test到
test
的转换。渲染过程类似于babelParse->Transform->Generate。Parsesource通过三个嵌套的规则链core、block和inline进行解析:corecore.rule1(normalize)...core.ruleXblockblock.rule1(blockquote)...block.ruleXinline(应用于每个带有“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',functionreplace(state,startLine,endLine,silent){//...});上述代码在md.block.ruler.fence之前添加了Snippet规则,用于解析<<<@/filepath等代码。它会把文件路径取出来和根路径放在一起,然后读取文件内容。具体代码就不详细分析了。一般parse阶段用到的情况比较少。有兴趣的可以自行查看vuePress源码。TransformToken通过官方在线示例以#test为例,将得到如下结果:[{"type":"heading_open","tag":"h1","attrs":null,"map":[0,1],"嵌套":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,“孩子”:空,"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,“嵌套”:-1,“level”:0,“children”:null,“content”:“”,“markup”:“#”,“info”:"","meta":null,"block":true,"hidden":false}]使用更底层的数据来表示Token,而不是传统的AST区别很简单:它是一个简单的数组,有单独的开始和结束标签,会有一些特殊的标记(类型:“内联”)嵌套标记,按照标记的顺序排序(粗体,斜体,文本,......)更详细的数据模型可以通过Token类定义查看。Renderertoken生成后,传递给renderer,renderer会将所有的token传递给每条与token相同类型的rule。renderer的规则都是在md.renderer.rules[name]中定义的,都是参数相同的函数。Rules代表了token的渲染规则,可以更新或者扩展,后续的实例基本都从这里开始。用法基础用法constMarkdownIt=require('markdown-it');constmd=newMarkdownIt();constresult=md.render('#test');预设和选项预设定义活动规则和选项组合。可以是通用标记、零、默认值。commonmarkstrictCommonMarkmodedefaultdefaultGFMmode,nohtml,typographer,autolinkeroptionszeronorules//commonmarkmodeconstmd=require('markdown-it')('commonmark');//默认模式constmd=require('markdown-it')();//启用所有constmd=require('markdown-it')({html:true,linkify:true,typographer:true});optiondocumentation:参数类型默认值说明htmlBooleanfalse在源代码中启用HTML标签xhtmlOutBooleanfalse使用/来关闭单个标签(如)该选项只兼容完整的CommonMark模式breaksBooleanfalse将段落中的\n转换为
langPrefixStringlanguage-CSSforfencedcodeblocks语言前缀对于额外高亮代码很有用linkifyBooleanfalse自动将类似URL的文本转换为链接启用highlightFunctionfunction(str,lang){return'';}高亮函数,如果源字符串未更改,则返回转义的HTML或'',如果结果以
'),rawCode.indexOf('
'))constlines=code.split('\n')constlineNumbersCode=[...Array(lines.length-1)].map((行,索引)=>``).join('')constlineNumbersWrapperCode=`