您将如何解析 Markdown?

编辑: 我最近了解到一个叫做 Common Mark 的项目,它 正确识别和处理原文中的歧义 它有很棒的 C # 库 支持。

您可以找到语法 给你

下载后面的源代码是用 Perl编写的,我无意尊重它。它充满了正则表达式,并且依赖于 MD5散列来转义某些字符。这事有点不对劲!

我将要为 降价硬编码一个解析器。有什么经验吗?

如果您对 Markdown 的实际解析没有什么有意义的话,请抽出时间给我。(这听起来可能有些刺耳,但是,是的,我正在寻找洞察力,而不是一个解决方案,也就是说,第三方库)。

为了帮助解答这些问题,正则表达式的意思是 识别模式!不要解析整个语法。人们认为这样做是愚蠢的。

  • 如果你考虑 Markdown,它基本上是基于段落的概念。
  • 因此,一个合理的方法可能是将输入分成段落。
  • 有许多类型的段落,例如,标题、文本、列表、块引用和代码。
  • 因此,挑战在于确定这些段落以及它们是在什么背景下发生的。

我会带着解决方案回来的,一旦我发现它值得分享。

55807 次浏览

如果您不喜欢 Perl,那么在 至少10种其他语言中有 Markdown 实现。他们可能并不都有100% 的兼容性,但往往是非常接近。

我可能读了足够多的语法规范来了解它,并对如何解析它有一定的感觉。

阅读现有的解析器代码当然很棒,既可以看到复杂性的主要来源,又可以看到是否使用了特殊的聪明技巧。MD5校验和的使用看起来有点奇怪,但是我还没有足够的研究代码来理解为什么要这样做。在一个叫 _EscapeSpecialChars()的例行程序中有一条评论说:

我们将每个这样的字符替换为相应的 MD5校验和值; 这可能是过度杀戮,但应该能防止我们撞上逃跑 偶然的价值观。

用一个完整的 MD5替换一个字符确实看起来很奢侈,但也许它真的有意义。

当然,为了让 弯曲这样的工具摆脱正则表达式的困境,考虑创建一个“ true”语法是明智的。

在这里 你可以找到一个 Markdown 的 JavaScript 实现。它还严重依赖于正则表达式,因为这是解析文本最快、最简单的方法。

但它省去了 MD5的部分。

我不能直接帮助解析的编码,但也许这个链接可以帮助您这样或那样。

有很多语言的库,包括 php,ruby,java,c # ,javascript。我建议你看看这些文章,寻找灵感。

这取决于您希望使用哪种语言,为了实现它的最佳方法,将有惯用和非惯用的方法来实现它。

正则表达式在 perl 中工作,因为 perl 和 regex 是最好的朋友。

如果您使用的编程语言有三个以上的其他语言 用户,您应该能够找到一个库来为您解析它 快速谷歌揭示了 CL,Haskell,Python, JavaScript、 Ruby 等等 重新发明这个轮子。

如果你真的需要从头开始写,我建议你写一个 使用这种技术,您不必逃避任何事情 使用 MD5散列。(我同意,如果您必须执行这样的操作, 是时候重新考虑你的设计了。)

Markdown 是一种 JAWL (只是另一种维基语言)

有大量的开源 wiki 可以检查解析器的代码。大多数使用 REGEX

看看螺旋转维基,它有一个有趣的多通道格式化管道,一个非常好的技术-参见/core/Formatter.cs 和/core/ formatterpipeline.cs

最好是使用/加入一个现有的项目,这些事情总是比它们看起来要难得多

如果我要解析 Markdown (及其扩展 降价加价) ,我想我会尝试使用一个状态机,一次解析一个字符,将一些内部结构连接在一起,这些内部结构表示文本位,然后,一旦所有内容都被解析,从所有串在一起的对象生成输出。

基本上,我会在读取输入文件时构建一个迷你 DOM 类树。
要生成输出,我只需遍历树并输出 HTML 或其他任何东西(PS、 LaTex、 RTF,...)

可能增加复杂性的事情:

  • 您可以混合使用 HTML 和 markdown,尽管这个规则可能很容易实现: 只要忽略两个平衡标记之间的任何内容,然后逐字输出即可。

  • URL 和注释可以在文本的底部引用它们。将数据结构用于超链接可以简单地记录以下内容:

    [my text to a link][linkkey]
    results in a structure like:
    URLStructure:
    |  InnerText : "my text to a link"
    |  Key       : "linkkey"
    |  URL       : <null>
    
  • Headers can be defined with an underline, that could force us to use a simple data structure for a generic paragraph and modify its properties as we read the file:

    ParagraphStructure:
    |  InnerText    : the current paragraph text
    |                 (beginning of line until end of line).
    |  HeadingLevel : <null> or 1-4 when we can assess
    |                 that paragraph heading level, if any.
    

Anyway, just some thoughts.

I'm sure that there are many small details to take care of and I'm pretty sure that Regexes could become handy during the process.
After all, they were meant to process text.

我所知道的唯一使用实际解析器的降价实现是 Jon MacFarleane价格便宜它的解析器是基于一个名为 Peg解析表达文法编译器编译程式。


编辑: Mauricio Fernandez最近发布了他的 简单 Markup Markdown 解析器,作为他的 OcsiBlog Weblog Engine 的一部分。因为解析器是用 奥卡姆编写的,所以它是 非常简单而短的(解析器为268 SLOC,HTML 发射器为43 SLOC) ,而 非常快(比 折扣快20% (用手工优化的 C 编写) ,比 简单 Markup Markdown 解析器0(简单 Markup Markdown 解析器1)快9倍) ,尽管事实上它甚至还没有为性能进行优化。因为它只是为毛里西奥自己的博客内部使用,有一些偏离 简单 Markup Markdown 解析器2,但毛里西奥已经创建了 简单 Markup Markdown 解析器3。

上周我发布了一个新的基于解析器的 Markdown Java 实现,称为 钉住。 Pegdown 使用 PEG 解析器首先构建一个抽象语法树,然后将其写入 HTML。因此,与基于正则表达式的方法相比,它非常干净,而且更容易阅读、维护和扩展。 PEG 语法是基于 John MacFarlane C 实现的“ PEG-markdown”。

也许你感兴趣的东西..。

MarkdownPapers 是另一个 Java 实现,其解析器是在 JavaCC语法中定义的。