一个结构清晰的,易于维护的,现代的PHP Markdown解析器

Last update: Jun 21, 2022

为何要写这样一个解析器

Markdown已经面世许多年了,国内外许多大大小小的网站都在用它,但是它的解析器却依然混乱不堪。SegmentFault 是中国较大规模使用 Markdown 语法的网站,我们一直在使用一些开源类库,包括但不限于

  1. php-markdown
  2. CommonMark for PHP
  3. Parsedown

他们都有或多或少的毛病,有的性能较差,有的代码比较业余,更多的情况是由于Markdown本身解析比较复杂,因此我们几乎无法去维护另外一个人写的代码。基于这个原因,我为 SegmentFault 专门编写了这么一个Markdown解析器。

使用方法

与常规的解析类库没有任何区别

$parser = new HyperDown\Parser;
$html = $parser->makeHtml($text);

当前支持的语法

  • 标题
  • 列表(可递归)
  • 引用(可递归)
  • 缩进风格的代码块
  • Github风格的代码块
  • 各种行内文字加粗,斜体等效果
  • 链接,图片
  • 自动链接
  • 段内折行
  • 脚标
  • 分隔符
  • 表格
  • 图片和链接支持互相套用

浏览器中使用请参阅 HyperDown.js

GitHub

https://github.com/SegmentFault/HyperDown
Comments
  • 1. table有问题?

    | Left-Aligned  | Center Aligned  | Right Aligned |
    | :------------ |:---------------:| -----:|
    | col 3 is      | some wordy text | $1600 |
    | col 2 is      | centered        |   $12 |
    | zebra stripes | are neat        |    $1 |
    
    | Item      | Value |
    | --------- | -----:|
    | Computer  | $1600 |
    | Phone     |   $12 |
    | Pipe      |    $1 |
    

    找的demo,发现错误

    | Left-Aligned | Center Aligned | Right Aligned | | :-- | :-: | --: | | col 3 is | some wordy text | $1600 | | col 2 is | centered | $12 | | zebra stripes | are neat | $1 |

    | Item | Value | | --- | --: | | Computer | $1600 | | Phone | $12 | | Pipe | $1 |

    Reviewed by hellobbq at 2015-11-07 12:23
  • 2. 列表解析

    1. test1
    + test2
    

    这样的markdown语句解析得到的html为

    <ol></ol><ul><li><p>test1</p></li><li><p>test2</p></li></ul>
    

    按常理说应该是全部ol,或者是test1为ol, test2为ul;而不应该是现在这个结果。希望解答,谢谢。

    Reviewed by bingtaoli at 2015-10-01 07:42
  • 3. 行内代码解析问题,造成部分内容不显示

    具体情况请看 http://segmentfault.com/q/1010000003098262 上的讨论

    虽然不能确定是 HyperDown 造成的,但是我猜是,估计 SegmentFault 最近后台换 HyperDown 解析了。 顺便,希望 HyperDown 的解析能和预览里的脚本解析效果一致,不然预览都不可信了。

    Reviewed by jamesfancy at 2015-08-15 12:41
  • 4. 一些review

    -line 393 if (strlen($matches[1]) >= $this->getBlock()[3]) { -line 401 if (strlen($matches[1]) >= $this->getBlock()[3][0]) { 这数组存储的--.

    function parseInline str_replace(['[', ']'], ['[', ']'], $matches[1]) 上面这行代码,同一函数定义的数组重复多次-。- 是否可以优化

    Reviewed by lhkzh at 2015-08-14 02:54
  • 5. 列表解析问题很多

    一旦列表中使用了 ``` 代码段,则列表无法结束,比如下面这段,“这是列表外的内容。”始终显示在列表内。

    • ⽆序列表:

      使⽤星号(*)、加号(+)或是减号(-),在后面再加一个空白作为列表标记:

      * 红色
      * 绿色
      * 蓝色
      

      列表结尾

    这是列表外的内容。


    如果列表中使用了缩进形式的代码段则列表会提前结束:

    • ⽆序列表:

      使⽤星号(*)、加号(+)或是减号(-),在后面再加一个空白作为列表标记:

      * 红色
      * 绿色
      * 蓝色
      

      列表结尾

    这是列表外内容。


    用空行分开的列表项,会连载一起:

    • aaa
    • bbb

    • aaa

    • bbb

    显示一样

    Reviewed by han-jingyu at 2019-09-28 08:43
  • 6. 是否能增加白名单 tag 功能?

    开启了 html 标签白名单以后,如果用户插入一段这样的代码

    <i onclick="alert(233)">XSS</i>
    

    还是可以成功触发 onclick 事件 是否能加入一个白名单的功能,比如指定了只能加入 style、class 这些 tag 谢谢。

    Reviewed by kasuganosoras at 2018-10-25 15:12
Related tags