GFM 与 Redcarpet 的不同点
GFM 即 GitHub Flavored Markdown,是 GitHub 用在 Respository、Issues、Comments 和 Pull requests 里的一种 Markdown 引擎,它与标准 Markdown 有所区别,增加了一些 GitHub 自己扩展的功能。
Redcarpet 是另一种 Markdown 引擎,我的基于 GitHub Pages 的博客采用它来解析 md 文件,_config.yml 文件里的配置如下:
markdown: redcarpet
redcarpet:
    extensions: 
        - no_intra_emphasis
        - fenced_code_blocks
        - autolink
        - tables
        - with_toc_data
        - strikethrough
在 vmg/redcarpet#379 的讨论中可以得知 GFM 其实是基于 Redcarpet 的一个非开源子集开发的,Redcarpet 也支持众多自定义的扩展,本文记录的是当前 GFM 与使用如上配置的 Redcarpet 的一些差异,以备在 GitHub 不同的地方写作时参考。
目录
换行
第一行(后面没有空格)
第二行
在 GFM 里会显示成跟上面一样。
而在 Redcarpet 里会显示成
第一行(后面没有空格)第二行
在 Redcarpet 里如果需要换行,要么在行尾加两个空格,要么在下面空一行新开一个段落。
锚点链接
GFM 与 Redcarpet 支持对 #、## 和 ### 这样的标题自动生成锚点链接,只不过在生成的链接 url 上会有少许差异。
当然,强烈建议在标题中不要使用奇怪的符号。
在这里做个小广告:如果你使用 Vim 编辑 Markdown,那可以试试我写的能自动生成 GFM 和 Redcarpet 这两种风格 TOC 的 Vim 插件 vim-markdown-toc。
共同点:
- 
    反引号(即 1 左边那个符号)会直接忽略掉。 
- 
    字母要全小写。 
- 
    空格会转换成 -。
不同点:
下面的表格列举了一些我曾经遇到过的案例,并不全,完整的实现逻辑在表格下方有说明。
| 字符 | GFM | Redcarpet | 
|---|---|---|
| " | 忽略 | 替换成 quot,如果前后有字符,用-连接 | 
| ' | 忽略 | 替换成 39,如果前后有字符,用-连接 | 
| & | 忽略 | 替换成 amp,如果前后有字符,用-连接 | 
| / | 忽略 | 首尾的忽略,中间的替换成 - | 
| @ | 忽略 | 首尾的忽略,中间的替换成 - | 
| # | 忽略 | 首尾的忽略,中间的替换成 - | 
| $ | 忽略 | 首尾的忽略,中间的替换成 - | 
| % | 忽略 | 首尾的忽略,中间的替换成 - | 
| ^ | 忽略 | 首尾的忽略,中间的替换成 - | 
| + | 忽略 | |
| \* | 忽略 | 首尾的忽略,中间的替换成 - | 
| ~ | 忽略 | 首尾的忽略,中间的替换成 - | 
| ; | 忽略 | 首尾的忽略,中间的替换成 - | 
| . | 忽略 | 首尾的忽略,中间的替换成 - | 
| , | 忽略 | 首尾的忽略,中间的替换成 - | 
| ? | 忽略 | 首尾的忽略,中间的替换成 - | 
| : | 忽略 | 首尾的忽略,中间的替换成 - | 
| 竖线 | 忽略 | 首尾的忽略,中间的替换成 - | 
| ! | 忽略 | 首尾的忽略,中间的替换成 - | 
| () | 忽略 | 替换成 - | 
| ( | 忽略 | 忽略 | 
| ) | 忽略 | 忽略 | 
| ? | 忽略 | 保留 | 
| , | 忽略 | 保留 | 
| 。 | 忽略 | 保留 | 
| 、 | 忽略 | 保留 | 
| ! | 忽略 | 保留 | 
| : | 忽略 | 保留 | 
| ; | 忽略 | 保留 | 
| “ | 忽略 | 保留 | 
| ” | 忽略 | 保留 | 
| 《 | 忽略 | 保留 | 
| 》 | 忽略 | 保留 | 
| 「 | 忽略 | 保留 | 
| 」 | 忽略 | 保留 | 
| 『 | 忽略 | 保留 | 
| 』 | 忽略 | 保留 | 
| —— | 忽略 | 保留 | 
总的来说就是 GFM 遇到奇怪的字符就忽略,而 Redcarpet 应用了几种不同的规则来处理。
当然这只是表面上看起来的现象,这里简单说一下它们的实现逻辑:
GFM 的 TOC 链接处理实现
- 使用 Ruby 的正则表达式 /[^\p{Word}\- ]/u过滤掉所有中英文标点符号、特殊符号等。
- 将空格替换为 -。
- 如果相同的链接 id 已经存在了,那在链接 id 后面添加 -{num},比如标题hello,world生成链接#helloworld,而标题hello!world生成链接#helloworld-1。
Redcarpet 的 TOC 链接处理实现
- 将 HTML 标签,即成对的 <与>及它们之间的内容删除。
- 进行 HTML Encode,即将 &、"和'等转换为相应 HTML 实体。
- 将字符 -&+$,/:;=?@"#{}|^~[]`\*()%.!和空格替换为-,有两个及以上-的地方修复成一个,将链接串首尾的-_删除。
列表下嵌套内容
在 Redcarpet 中有如下规则:
- 如果嵌套非列表,需要缩进并且空行。
- 如果嵌套列表,需要缩进,但不空行。
而 GFM 则没有。
YML 解析
在 Redcarpet 中,解析头部 YML 里的内容有些需要转义:
---
tags: C\+\+
---
而 GFM 则不需要。
GFM 独有特性
GFM 自己添加的一些特性我甚是喜欢,可惜在 GitHub Pages 里使用 Redcarpet 享受不到了。
Task Lists
这货真是个好东西,用 - [  ] 和 - [ x ] 就能做出清单列表项的显示效果来,而且如果你有编辑权限的话点选后文本能自动更新。
用法参见 Task Lists in GFM: Issues/Pulls, Comments
自动生成引用链接
Update 2015-12-06 参见 @Mentions on GitHub Pages,GitHub Pages 现在也支持使用 @username 来 at 一个 GitHub 用户了,只是用户不会收到通知。我对此功能并无需求,而且貌似会对其它使用 @ 号的地方产生非预期的解析,所以本博客当前并未启用。
对于如下格式的文本,GFM 会自动创建到对应用户对应仓库的对应链接。
* SHA: a5c3785ed8d6a35868bc169f07e40e889087fd2e
* User@SHA: jlord@a5c3785ed8d6a35868bc169f07e40e889087fd2e
* User/Repository@SHA: jlord/sheetsee.js@a5c3785ed8d6a35868bc169f07e40e889087fd2e
* #Num: #26
* GH-Num: GH-26
* User#Num: jlord#26
* User/Repository#Num: jlord/sheetsee.js#26
Emoji
Update 2015-12-06 参见 Emoji on GitHub Pages, GitHub Pages 现在也支持使用 Emoji 表情啦!:+1::+1::+1:
GitHub Pages 如果能使用这个,文章一定生动不少。
参考链接
评论:
技术文章推送
手机、电脑实用软件分享
 
     微信公众号:AndrewYG的算法世界
        微信公众号:AndrewYG的算法世界
     
                    