如何写一个markdown-it插件(一)
时间:2023-03-29 10:49:31
HTML
前言在《一篇带你用 VuePress + Github Pages 搭建博客》中,我们使用VuePress搭建了一个博客,最终效果可以查看:TypeScript中文文档。在搭建博客的过程中,我们针对实际需要在《VuePress 博客优化之拓展 Markdown 语法》中讲解了如何编写markdown-it插件,在《markdown-it 原理解析》中讲解了markdown-it的执行原理。在这篇文章中,我们将详细讲解实战代码,帮助大家更好的编写插件。renderermarkdown-it的渲染过程分为两部分,Parse和Render。如果我们要改变渲染效果,比如在外层包裹一个div,或者修改HTML元素的属性,添加类等,我们可以从Render流程入手。可以在markdown-it的官方文档:Renderer实例中找到自定义Render渲染规则的方法。用它来修改输出外观。或者为新的令牌类型添加渲染规则,由plugins.varmd=require('markdown-it')();functionmyToken(tokens,idx,options,env,self){//...returnresult;};md.renderer.rules['my_token']=myTokenmarkdown-它有一些内置的默认规则,你可以直接修改它们,具体细节和渲染方式可以查看renderer.js的源码,直接列出此处:code_inlinecode_blockfenceimagehardbreaksoftbreaktexthtml_blockhtml_inline示例1我们查看VuePress中代码块的渲染结果,会发现每个代码块每一层都包裹着一层extra-class类名的div:其实这是VuePress修改生成的渲染规则。查看VuePress的源码:module.exports=md=>{constfence=md.renderer.rules.fencemd.renderer.rules.fence=(...args)=>{const[tokens,idx]=argsconsttoken=tokens[idx]constrawCode=fence(...args)return``+`${rawCode}
`}}我们可以看到这里很巧妙的避开了token,直接使用渲染结果,在外层包裹了一层div示例2类似于VuePress的方式。我们也可以在获取到默认渲染内容后,使用replace来替换一些内容。比如在《VuePress 博客优化之拓展 Markdown 语法》一文中,我们自定义了一个代码块语法,在rules中。fence中修改渲染内容:md.use(function(md){constfence=md.renderer.rules.fencemd.renderer.rules.fence=(...args)=>{letrawCode=fence(...args);rawCode=rawCode.replace(/
\/\/尝试链接https:\/\/(.*)<\/span>\n/ig,'Try');return`${rawCode}`}})例3但是不可能一直这么刁钻,有些时候需要处理token。这里我们参考markdown-it官方提供的设计指南中的示例。渲染图像时,如果链接匹配/^https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/,我们会将其渲染为iframe,并且其他人将保留默认渲染方法:varmd=require('markdown-it')();vardefaultRender=md.renderer.rules.image,vimeoRE=/^https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/;md.renderer.rules.image=function(tokens,idx,options,env,self){vartoken=tokens[idx],aIndex=token.属性索引('src');如果(vimeoRE.test(token.attrs[aIndex][1])){varid=token.attrs[aIndex][1].match(vimeoRE)[2];返回'??\n'+'\n'+' \n';}//将令牌传递给默认渲染器。返回defaultRender(tokens,idx,options,env,self);};rules.image传入的函数参数可以在renderer.js的源码中查看:Renderer.prototype.render=function(tokens,options,env){vari,len,type,result='',rules=这个。规则;对于(i=0,len=tokens.length;i