Markdown 并没有对标题 id 的内建支持,而我们经常希望能定义一个 id 来支持页面内跳转。本文通过试验各种方案在不同平台上的效果,尝试使用一种最佳方案来定义 header id。
可能的方案
首先,我们看看有哪些可能的方案。
我们知道,形如 ## Header
的字段将会转换成 <h2>Header</h2>
如果要支持锚点跳转,我们可以生成如下几种形式的 HTML:
<h2 id="header-id">Header</h2>
<h2><a id="header-id"></a>Header</h2>
<h2><a name="header-id"></a>Header</h2>
第一种显然是最优方案,但绝大部分的 Markdown 转换工具都无法支持转换成这样的目标代码。
我测试了下面几种 Markdown 转换器(编辑器):
- GitHub Code Preview
- Kramdown (for Jekyll page generate)
- Redcarpet (for Jekyll)
- StackEdit (Online Markdown Editor)
- MWeb (Mac App)
尝试
完全自动生成
完全自动生成的方式倒是少了很多麻烦,但很多转化器对于中文的支持不是很好,比如 Kramdown 无法识别中文,将会自动生成诸如 section-1
一类的id,所以我们无法知道 Markdown 最终会生成怎样的id。
指定 header id
<h2 id="header-id">Header</h2>
从我的了解来看,只有 Kramdown 和 StackEdit 支持自定义的 header id,语法如下:
## Header {#header-id}
其他转换器会把后面的代码识别成普通文字。
添加带 id 或 name 的 anchor tag
<h2><a id="header-id"></a>Header</h2>
<h2><a name="header-id"></a>Header</h2>
这两种方式支持大部分的转换器,我测试测试过的几种转换器都支持这样的内嵌tag。
但缺点是,Kramdown等自动生成的 header id 比较乱,会生成类似 a-id-header-id-a--header
这样的 id。导致一些自动生成目录(TOC)的js工具,会指向这个比较乱的id,导致用户无法分享这个链接了。
结合自定义 id 和带 name 的 anchor tag
为了最友好的支持 Jekyll 站的锚点跳转,我最终决定结合 Kramdown 的自定义语法和 anchor tag 的跳转,以实现比较好的效果。
首先,使用 {#id}
语法,使得 Jekyll 生成的站点有很好的 header id。在线的 StackEdit 也有较好的体验。
其次,使用 <a name="id"></a>
,使得不支持自定义 id 的 GitHub 以及 MWeb 也能在预览时支持锚点的跳转。
其语法如下:
### <a name="header-id"></a>Header {#header-id}
当然,这样生成的标题,在不支持 {#id}
的编辑器中会显示出来,但我想这反倒是比较好的告知其他开发者,我这里使用的锚点名称是什么,只要不是最终输出文件,应该也不算是特别大的障碍吧。
Comments