有大佬曾经说过:

Any application that can be written in JavaScript, will eventually be written in JavaScript.
— Jeff Atwood

Markdown 已经是一个非常普及的标记语言了,JavaScript 的解析和渲染可以让它在前端界发挥更大的作用。
比如用 Markdown 写博客,通过 JavaScript 实现在线预览,也就是我现在正在做的事情。
JavaScript 实现的解析器还有一个其他语言无法比拟的优势,就是通过 Node.js 可以实现前后端用同一份代码来解析,可以确保得到的结果是完全一样的。
通过对 Markdown 语法的扩展,我们还可以做更多的事情,比如用 Markdown 快速搭建一个页面,甚至通过特定语法快速实现一些复杂的交互,快速嵌入一个复杂组件,等等。

目前比较流行的 Markdown 解析库有(按照 Star 数从多到少排列):

我分别使用了一下,并稍微扒了一下他们的实现,下面我将从几个方面来比较一下他们的优劣。

TL;DR

  • Marked:速度最快,扩展性差,中文支持好;
  • Showdown:扩展性好,中文支持好;
  • markdown-it:扩展性好,中文支持不好。

具体分析

Marked

  1. 设计思想:
    Marked 的代码实现就一个字,烂。
    这应该是一个古老的项目,感觉并没有什么设计思想,所有的代码都在一个文件中,毫无组件化、模块化,满屏都是正则表达式。这个项目如果出现 bug,我是不会想去排查的。
    Marked 的整个解析过程都在一个大函数里,基本无法扩展。当然,他暴露了解析的方法,我们可以自己实现一个替换它,不过那样的话,我还要这个库干啥?

  2. 解析原理:

    前面已经说过了,满屏都是正则表达式。没错,Marked 就是通过正则匹配来解析 Markdown 的。讲道理,用正则来解析语法实在是不太可靠,但好在 Markdown 是用来写文档的,通常不会出现太多复杂的 edge case,所以从结果来看也能接受(中文支持不错)。

    正则解析的好处:

    • 开发速度快。(维护我就不说了 = =!)
    • 性能好。毕竟可以借力浏览器对正则所做的优化,比自己逐字符解析要快不少。
  3. 性能:
    虽然这个库的代码可读性不怎么样,但是换一个角度来看,这又未必是一件坏事。首先,代码基于 ES5,无需编译,没有组件化、模块化,减少了一些提高可读性带来的额外开销,而且各种奇技淫巧的使用,对性能的提升肯定是有帮助的。从 benchmark 来看,Marked 的速度确实是遥遥领先的。

总结:扩展性差、正则解析(中文支持好)、性能好。

Showdown

  1. 代码实现:
    这个项目有了模块化的概念,而且引入了 extension 机制,可以快速扩展。
    Showdown 定义了一系列的 subParser,可以分别解析不同的语法,还定义了一些生命周期事件可以用于在特定时机触发一些行为,逻辑上很清晰,我们也可以很方便地注册自己的 subParser 或者 extension,来扩展新的语法。
    唯一有一点担心的是,它的解析机制非常灵活,一个 subParser 的实现如果有问题,有可能导致其他的 subParser 的解析也受影响。
  2. 解析原理:
    Showdown 也是通过正则表达式来解析的,不过它根据不同的语法做了区分,每一个 subParser 就负责解析一个语法,正则表达式也更加清晰。使用正则解析的优劣和 Marked 差不多,就不多说了。另外,他的匹配规则也适用于中文,所以中文支持不错。
  3. 性能:
    Showdown 虽然也是使用正则解析 Markdown,但是由于它的模块化、功能拆分、生命周期的引入,导致解析的效率明显降低,速度是远不如 Marked 的。不过在硬件快速发展的今天,C 端并不那么在乎性能,扩展性更为重要。

总结:扩展性好、正则解析(中文支持好)、性能较差。

markdown-it

  1. 代码实现:
    按功能拆分,模块化,可读性好,文档完善,有一套完善的设计思想,而且提供了完备的扩展开发方案。
  2. 解析原理:
    严格按照 CommonMark 规范,逐字符解析,准确性是很可靠的。
    然而,CommonMark 规范的设计者似乎并没有考虑到中文等不使用空格分隔的语言的存在,所以对这部分语言的支持很不好。相关 issue 已经很多了,然而开发者们一直表示 CommonMark 规范就是这么设计的,所以目前无法支持。
    而且规范细节的实现基本都是硬编码的,无法通过扩展的方式进行修改,这成了目前使用这个库最大的障碍。
  3. 性能:
    这样当然会损失一部分性能,所以它的解析速度是不如 Marked 的,但是根据官方的 benchmark,大概是做了一些优化,性能差距也不大。

总结:扩展性好、逐字符解析(中文支持不好)、性能较好。

结论

  • 如果我们不需要扩展,只希望快速得到一个 Markdown 解析和渲染的工具,那么 Marked 是很好的选择。
  • 如果我们希望进行定制,扩展自定义的组件和语法,那么 Showdown 是一个很好的选择。
  • 至于 markdown-it,等它对中文支持友好了再说吧。

参考:

https://www.jianshu.com/p/549cace91e22