Markdown 分割线怎么写,以及 --- 的坑

Markdown 写作约 5 分钟

单独一行写 ---、*** 或 ___,上面留一个空行,三种写法画出来的都是同一条分割线(CommonMark 里叫 thematic break),但 --- 有个坑,直接贴在一行文字下面时,那行文字会变成标题而不是分割线。在妙言 V4.5.0 里还要多记两件事,同样的 --- 在 PPT 模式里是幻灯片的分页符,写在笔记最开头时又是 front matter 的围栏。

三种写法

线上面的段落。

---

***

___

线下面的段落。

CommonMark 规范对分割线的定义是,一行里有三个或更多相同的 -、_ 或 *,前面最多三个空格,除了空格和制表符之外不能有别的字符。规范自己的例子里字符之间带空格也算,所以 - - - 和 * * * 同样是分割线,一行 37 个下划线也是;混着写不行,规范要求除空格和制表符以外的字符必须全部相同。

不成立的写法也很具体,-- 和 ** 太短,只是普通文字,+++ 不是分割线,---a--- 或 a------ 这种一行里还有别的字符的,是普通段落,缩进到四个空格以上会变成代码块或上一段的延续。

GitHub 渲染按 GitHub Flavored Markdown 规范走,规范里关于分割线的例子同样列了这三种。GitHub 文档里「基本写作和格式语法」那一页完全没提分割线,要查就看规范。

setext 标题的坑

第一节
---

下一段。

这不是「一段文字加一条线」。CommonMark 里一行文字下面紧贴 ---,就是 setext 标题,「第一节」会变成 <h2>,规范的例子是 Foo、---、bar,输出 <h2>Foo</h2> 加 <p>bar</p>,两种读法冲突时标题赢。=== 贴在文字下面也一样,变成 <h1>,单独一行的 === 只是普通文字,不是分割线。

办法是在横线上面留一个空行,规范并不强制,但留了就没有歧义。更省事的是直接用 ***,规范的例子 Foo、***、bar 输出段落、<hr />、段落,不会变成标题。

列表有自己的规则,一行既能当列表符号又能当分割线时,按分割线算,* * * 是分割线,不是空的列表项。要在列表项里放分割线,规范建议换一个和列表不同的符号,比如 - * * *。- 条目 下面紧贴 --- 时,列表在这里结束并画出分割线,不会把条目变成标题,这也是规范里的例子。

写成 HTML

<hr>

Markdown 允许内嵌 HTML,三种写法最后生成的就是 <hr>。妙言预览渲染时开着 cmark-gfm 的 unsafe 选项,原样放行 HTML,所以 <hr> 在这里能用。有些发布平台会过滤内嵌 HTML,在那里还是写 Markdown 形式更稳。

Markdown 没有给分割线加 class 或内联样式的语法,要加只能写 HTML,能不能保留要看渲染器的 HTML 过滤。

妙言怎么画它

妙言 V4.5.0 用 cmark-gfm 渲染笔记,再把 HTML 放进网页视图。分割线输出为 <hr>,预览样式表(内置 DownView 资源里的 typography.css)给它 1 像素高、无边框、背景取主题的边框色,上下各留 1.6em 的外边距。浅色主题的边框色是 #e6e6e6,深色主题是 #454545,两种主题下都比较淡。

自己的网页里要改分割线的样子,是 CSS 的事,不是 Markdown 的事:

hr {
  border: 0;
  height: 1px;
  margin: 2em 0;
  background: #d0d0d0;
}

妙言里 --- 的另外两个用途

幻灯片分页符

在 PPT 模式(Command + Option + P)里,妙言把笔记交给 reveal.js,它的 Markdown 插件按 \r?\n---\r?\n 这个模式切页,也就是前后各有换行的一行 ---。这带来三个结果,一行 --- 就是一张幻灯片的边界,所以不能拿它在一页里当分隔线;---- 或者 --- 后面跟了空格,都匹配不上;setext 的坑在幻灯片里也不存在,因为切分发生在解析器看到这一行之前,--- 上面紧贴的文字只是上一页的结尾,不会变成标题。

***、___ 和 <hr> 匹配不上这个模式,会留在当前这页里,和其他行一样交给 reveal 的 Markdown 渲染器,一页内要分隔线就试它们,演示前在 PPT 模式里看一眼这一页。完整流程见 Markdown 转幻灯片。

快捷键只检查笔记里有没有 --- 这三个字符,表格分隔行 |---|---| 里就含有,所以只有表格、没有真正分页符的笔记也会启动 PPT 模式。

front matter 围栏

笔记第一行是 --- 时,妙言会往下找下一个以三个短横线开头的行,这一行正好是 ---,两行之间的内容就当成 front matter,在预览、PPT 模式和导出里隐藏,如果是 ---- 或者短横线后面还有别的字,就什么都不隐藏。笔记中间的三个短横线仍然是普通分割线。所以开头写一条装饰性的 --- 会让第一段消失,开头先写标题,或者顶上那条用 ***。完整规则见 Markdown front matter。

分割线没出来时

  • 出现的是标题而不是线。 --- 上面紧贴着文字,加一个空行,或者换成 ***。
  • 线是字面字符。 少于三个字符、字符混用、同一行有别的字符,或者缩进了四个空格。
  • 笔记开头不见了。 笔记以 --- 开头,后面某行正好是 ---,中间的内容被当成了 front matter。
  • 幻灯片在不该分的地方分了。 PPT 模式下每一行 --- 都是边界,分隔线换成 *** 或 <hr>。
  • 在妙言以外的应用里没有线。 渲染器可能过滤了 <hr>,改用 --- 并在上面留空行。

CommonMark 和 GFM 各自规定了什么,见 CommonMark 与 GFM 的区别,其余语法见 Markdown 语法速查。

常见问题

三种写法该用哪个?

--- 最常见,纯文本里最好读。线可能紧贴在段落下面时用 ***,它不会变成标题。

能让分割线变粗或者变色吗?

Markdown 里不行,没有这种语法。在显示 HTML 的页面里给 hr 写 CSS。

为什么我的 --- 变成了大标题?

它直接贴在一行文字下面,CommonMark 把它当成 setext 标题的下划线,在两者之间加一个空行。