5

我的应用程序需要一个相对简单的降价解析器。只是简单的东西,比如粗体、斜体等。我在四处寻找图书馆,很多似乎都很大。例如,marked很受欢迎,有 20,000 颗星。它接近 2,000 行代码。我什至不确定这个有多大,但它似乎很复杂。

一般来说,我尽量保持简单,并尽可能限制我的依赖。我不确定所有这些行在做什么?我很高兴很快就找到了这个甚至不到 100 行的库,它只是使用一个简单的正则表达式将文本转换为相应的降价。

我的问题是,基本上,那些其他图书馆在做什么?我是否因为选择使用更简单、以正则表达式为重点的方法而遗漏了什么?后一个图书馆在某种程度上不安全吗?我应该考虑其他一些我不知道的因素吗?

显然,我似乎遗漏了一些重要的东西,因为前一个库似乎很受欢迎,而后一个库甚至没有一颗星。我只是不确定那是什么。我希望这种情况是后者适用于简单的情况,而前者更“完整”,如果这是你需要的,但我不想跳到那个结论。

4

1 回答 1

6

有许多因素会导致 Markdown 解析器的复杂性。也就是说,您可以使用“简单的基于正则表达式”的方法来构建 Markdown 解析器。事实上,这正是参考实现所使用的(在 Perl 中)。它运行一系列正则表达式,将现有文档上的 Markdown 语法替换为 HTML 语法。即使这样,源代码也由 1451 行代码组成,包括注释、许可证等。当然,它包括对原始语法规则中描述的整个功能列表的支持。这些功能包括对嵌套、转义等的支持,这使正则表达式的使用变得非常复杂。

一些人发现这样的实现限制。这一切都取决于你想从 Markdown 解析器中得到什么。

例如,使用参考实现几乎不可能扩展语法。例如,Python-Markdown(我是其中的开发人员)采用了参考实现,为每个正则表达式命名,并为第三方扩展提供了一种方法来替换或插入新的正则表达式。样板代码只是为了允许这样做添加了相当多的代码行。顺便说一句,Markdown 已经过时了,像 Python-Markdown 这样的库多年来已经发生了变化和发展。第一个版本非常接近地模仿了参考实现,但今天你很难看到它们之间有任何相似之处。

其他人对扩展语法并不感兴趣,而是对提供一种控制输出的方法感兴趣。例如,标记的JS 库输出一个抽象语法树 (AST),然后可以将其传递给渲染器。渲染器接受 AST(基本上是令牌列表)并输出其他格式。其他格式可以是 HTML,也可以是其他格式。Pandoc利用这一点来转换多种文档格式。自然,这会增加额外的代码行。

另一个因素,无论是否实现,许多人会争辩说,如果一个实现不支持规则中的所有功能,那么它就不是 Markdown。事实上,多年来,许多实现都添加了非标准特性(以 GitHub Flavored Markdown 为例)。人们开始依赖这些非标准特性,并会提交错误报告,抱怨实现不支持它们。作为 Python-Markdown 的开发人员,当 lib 实际上提供支持时,我经常会看到此类报告。它只是默认情况下未启用。当向他们指出这一点时,他们的反应往往不如理解。因此,如果不支持所有标准功能,任何针对一般消费的实现都不会持续很长时间。

增加额外的复杂性是在标准特性的实现之间没有完美的协议。有关详细信息,请参阅Babelmark 2 常见问题解答。在该常见问题解答中,您会发现许多记录在案的差异非常细微。人们确实发现这些细微差别很重要。为此,一群人创建了Commonmark, Markdown 的严格规范。然而,由于 Commonmark 从未得到过 Markdown 创始人的加持,有人质疑它是否可以被认为是 Markdown。此外,在某些地方,规范自己承认直接违反了原始规则。无论如何,要成为 Commonmark 的实现,必须提供一个完整的解决方案,其中包含规范的所有记录特性。参考实现(在 JS 和 C 中)都非常大。实际上,我怀疑您是否可以像使用基于 rexed 的简单替换的实现来实现 Commonmark markdown.pl

关键是,除了最简单的实现之外,您得到的不仅仅是正则表达式替换的集合。确切的功能因实现而异,需要仔细阅读每个功能的文档。无论如何,即使是“简单”的正则表达式替换集合也相当复杂和冗长,要实现 Markdown 的所有记录功能。任何更少的东西都不会被视为 Markdown。

另一个考虑因素是性能。虽然基于正则表达式的解析器对于大多数一般用途来说“足够好”(作为参考实现的设计目的从命令行运行),但性能更高的实现(例如标记或 Commonmark 参考实现)会产生 AST 并使用渲染器. 基于正则表达式的实现永远不会在性能上接近匹配,如果您的 Web 服务器在每个请求上将 Markdown 转换为 HTML,这一点很重要。

于 2019-09-04T18:12:25.823 回答