由于工作中需要将 markdown 格式的文件转换成 html,因此抽空研究了下业界的工具Showdown
,Showdown 是一个可以将标准 markdown 规范解析生成基础 html 的工具,使用起来很简单,通过命令:showdown makehtml -i <input> -o <output>
即可完成转化,详细的介绍请参考官方文档 Showdown,在此就不过多赘述了。
Extensions 与 Listeners
通过研究发现,当需要解析一些”自定义”的 markdown 规范时,Showdown 提供了清晰良好的代码格式,方便我们扩展,包括extensions
, listener
的方式,可以进行注册,监听,来看 Showdown 的入口文件,里面有这样三行代码:
1 | //src/cli/makehtml.cmd.js |
可以分析出,converter
通过接受参数,来配置各种extensions
和listener
,然后直接从源文件中读取,经过 makeHtml 一转换就变成 html 了
官方也提供了几个现有的 extensions
, 如 table-extension prettify-extension 等,这些现有的extensions
都是对 markdown 的元素进行了自定义的解析和渲染,如果是基于标准的 markdown 语法,使用这种方式进行自定义渲染就非常方便了
关于 Listeners 可以参考下面的工作原理章节
工作原理
关于工作原理,可以用一句话来概括:Showdown使用正则表达式解析 markdown 语法,然后直接渲染成 html,注意这里面有两个关键词:
正则表达式解析
来看一个 Parser 的源码片段:
1 | // 斜体和黑体的解析器:italicsAndBold |
每个 Parser 的开始和结束,都抛出了相应的事件供监听,这就是 listener
扩展的机制,每次处理的结果都是返回 text 文本,可以看到在解析器中,对输入的文本进行正则表达式的匹配并直接替换成了相应的 html 元素
直接渲染
所谓直接渲染,就是上面代码中的
replace
,这样的处理为后续的需求埋下隐患:如果某个 markdown 片段需要作为整体的渲染,则无法满足
如果对渲染之后的 html 进行样式更改,加入css,则无法满足
可以看出,replace 替换的仅仅是 html 基本元素样式,且没有 id,class 等信息,因此极大程度上约束了生成的 html 样式,并不利于满足一些实际需求,然而 Showdown 的代码架构,将各个 markdown 元素分别定义了单独的解析器,这就为我们提供了一个思路,可以根据自定义的 markdown 的格式通过自定义的 parser 解析出来就好了,例如:
1
2
3
4
5
6### start 修订记录 ###
1.0
date: 11.3
2.0
date: 12.9
### end 修订记录 ###
解析器可以以 start 和 end 作为判断,整体将修订记录渲染成想要的格式,因此,对 Showdown 工程有以下重构想法:
解析和渲染解耦,不通过 replace 直接完成, 而是通过 taffydb 将解析出来的数据进行存储(参考jsdoc),这样做的好处是:规则制定者可以自定义 markdown 语法片段并通过解析器解析出来,然后存放到数据库中,不需要关心接下来如何渲染,前端工程师可以直接从数据库中取出相应的片段信息,配合css,进行定制化渲染。借助于中间数据库的解耦,使得最后生成出来的html可以加入css样式,从而满足一切定制化需求,即 解析 - 数据 -渲染
总结
以上是在结合工作需求的基础上研究 Showdown 工具的一些想法,还是软件工程里的一句老话:从需求出发的改动才附有意义