概述
Markdown 是一种轻量级标记语言,具有纯文本格式语法。
——维基百科
Markdown 是一种创作格式,更多的关注语义。因而,即便是查看其纯文本形式,依然有很高的可读性。
Markdown 可以转换成多种格式的文件,常见的 Markdown 编辑器通常是将其转换为 HTML 文档进行预览或查看。
与常规意义上的纯文本不同,Markdown 具有自己的语法,因此它具有内在一致性。
具有内在一致性是计算机的最爱,换句话说,计算机可以很容易地处理 Markdown 文档。因此,Markdown 具有一次编辑即可转换成多种格式的优点。(这听起来有点像是专门为开发人员编写的文件类型,但事实并非如此。)
Markdown vs. HTML
Markdown 并未涵盖所有 HTML 标签特性,但它与 HTML 是兼容的。换句话说,可以在 Markdown 文档中直接使用 HTML。虽然 Markdown 与 HTML 可以混合使用,但是有一些限制:
- HTML 块级元素需要始于新行,但行级元素可以与 Markdown 文本混合出现于同一行中。
- Markdown 语法在 HTML 块级元素中不会被处理,但在行级元素中会被解析。
- HTML 最外层标签前不能有缩进(因为这是 Markdown 代码块的语法)。
另外一点差异在于特殊字符的书写,对于 HTML 而言需要处理诸如 <
和 &
等特殊字符,而 Markdown 通常可以自然书写它们。在 Markdown 中特殊字符的书写与转义有以下一些规则:
- 如
&
是 HTML 字符实体的一部分,它会保留原状,否则转换成&
。 - 如
<
是 HTML 标签定界符,它会保留原状,否则转换成<
。 - 在代码区块中,
&
和<
一定会转换成字符实体。 \
是转义前缀,可以转义:\ ` * _ {} [] () # + - . !
。
块级元素
段落
对于 Markdown 而言,段落就是连续行上的文本。不同的段落前后以至少一个空行分隔。
注意,段落前后的空行不必是严格意义上的空行,只包含空格和制表符的行也视为空行。
与段落相关的一个概念是换行,它代表的是“硬换行”,其前后的内容还是属于同一段落。
在 Word 中,段落对应的是回车(Enter),而换行对应的是
Shift
+Enter
。如果设置“段落符号”可视的话,段落显示的是类似回车键上的符号,而换行显示的是向下的箭头。
在 Markdown 中,键入回车并不能起到换行的效果,它造成的效果仅仅是相当于插入了一个空格。要换行,需在行末插入至少 2 个空格,然后再键入回车。
换行与插入 <br />
标签是等效的,而想要插入多个换行的唯一方式就是使用 <br />
。
标题
Markdown 支持 2 种形式的标题:Setext 和 atx。
Setext 样式的标题如下:
1 | 一级标题 |
其中 =
和 -
的数量是任意的,但通常至少要有 3 个。
从语法可知,Setext 样式仅支持两级标题,这通常不够用。
另一缺点是,并非所有 Markdown 编辑器都支持它。
atx 样式的标题如下:
1 | # 一级标题 |
atx 最多支持六级标题。#
闭合是可选,并且闭合字符数量不必与开始的匹配。
分隔线
1 | *** |
分隔线有 3 种候选的标记符号:*
(星号)、-
(连接线)、_
(下划线)。
需要 3 个及以上字符,且除空格和制表符外,行内无其他字符。
使用 -
(连接线)时,与上一段落间至少应有一空行,否则会将上一行文字解释为二级标题。
大多 Markdown 编辑器中,二级标题预览样式下方也是有分隔线的。
块引用
1 | > 段落一 |
块引用使用 >
字符,最佳实践是在每一行前面都添加 >
。也可以只在每个段落前添加 >
。
块引用可嵌套使用其他 Markdown 元素,比如,标题、列表、代码块,甚至是块引用。
通常,Markdown 编辑器生成的块引用都是每行前加
>
。
代码块
顾名思义,代码块用以插入代码段。
其中一种语法是:在每一行前添加 4 个空格或 1 个制表符。
1 | // 4 个空格或 1 个制表符缩进 |
每一行仅移除一级缩进,其他的会被保留。
代码块中所有字符都能自然书写,比如 HTML 标签,甚至是 Markdown 代码。
代码块会一直持续到没有缩进的那一行或文件结束。
另一种代码块语法是使用 `
(反引号):
1 | ```markdown |
在大多数 Markdown 编辑器中,反引号语法更为常用,甚至一些编辑器会自动转换成反引号语法形式。因为,在代码块开始标记后可以指定代码的语言,这有利于编辑器在预览代码块时应用相应的语法高亮显示。
理论上,代码块中可以自然书写任意代码。但是,如果同上面的示例代码一样,代码块中书写的正好是代码块示例代码呢?这时,为了能正确关闭代码块,代码块标记将由
`
(反引号)改为~
(波浪号)。不过,并非所有编辑器都支持它,但值得庆幸的是 GitHub 支持。
列表
Markdown 支持有序列表、无序列表和任务列表。
1 | 无序列表: |
列表标记前最多可有 3 个空格(否则解析为代码块),之后至少接一个空格或制表符。
当列表项包含多个段落时,每个段落必须用 4 个空格或 1 个制表符来缩进。可以缩进每一行,以使列表美观,但这不是必须的。
列表项中嵌套块引用、代码块等时,需要双倍缩进。
与列表格式相同的文本需要使用 \
转义列表标记,有序列表转义的是英文句点(.
)。
在同一文档中,尽量使用同一个无序列表标记,而不应混用。
有序列表前的数字不必是有序的,甚至可以是任意数字,但是为了 Markdown 原始文档的可读性,应使数字与其序号一致。
在一些 Markdown 编辑器中,并不支持任务列表。
支持任务列表的编辑器中,通常预览显示为复选框开头的列表。
表格
表格通常有 2 写法,其中一种简洁写法如下:
1 | First Header|Second Header |
有的 Markdown 编辑器不一定支持这种写法;也有可能会正确识别,但会转换为下一种“标准”写法。
1 | | Table | Col1 | Col2 | |
注意,:
在哪端表示向哪端对齐,两端都有表示居中。默认为左对齐。
并非所有 Markdown 编辑器都支持文本对齐特性,但通常都能正常解析表格。
行级元素
超链接
自动链接
在 Markdown 中,如果要将一个 URL 或 email 标记为超链接,最简单的是使用“自动链接”,即使用 <>
将其包裹起来:
1 | <http://myurl.com> |
自动链接在大多数 Markdown 编辑器中的预览效果是,URL 或 email 原样显示的超链接。
部分编辑器中,直接书写的 URL 即便不用
<>
包裹也会以超链接的形式预览显示。
显然,自动链接必然会显示链接本身,而通常情况下,超链接显示的是文本而不是显示指向的 URL。对于这种情况,Markdown 有 2 种形式的链接:内联链接和引用链接。
内联链接
内联链接语法如下:
1 | 我的[主页](http://myurl.com "title"),点击访问。 |
内联链接分为了两部分:
[]
中的是显示文本()
中的是 URL 信息,又分为两部分:- 前半部分是 URL
- 后半部分是链接的
title
属性(即鼠标悬停在链接上时显示的帮助信息)。
- URL 部分可以用
<>
包起来;title
是可选的,并且可以用单引号或双引号。
引用链接
当一个 URL 在同一个 Markdown 文档中多次出现,就应该考虑将其用引用链接表示,一方面形式上更为简洁,另一方面修改 URL 时只需要修改一处。语法如下:
1 | 我的[主页][id] |
顾名思义,引用链接就是引用了某个链接定义的链接。因此,引用链接必然包括定义与引用两部分(注意,其顺序不重要)。
其中,引用部分又分为两部分:
- 前一个
[]
中是显示文本 - 后一个
[]
中是链接标识,它是在链接定义中指定的
定义部分也分为两部分:
[]
中是链接标识,其后紧跟:
和空格/制表符- 后面部分是 URL 信息(这跟内联链接 URL 信息部分类似)
- 链接标识可包含字母、数字、空格和标点符号等,大小写不敏感;
- URL 部分可以用
<>
包起来;title
是可选,并可用双引号、单引号或圆括号;- 使用引用链接时,可以省略链接标识,比如
[Google][]
,此时引用链接的链接标识就是前面显示的文本。在不同 Markdown 编辑器中,引用链接的定义部分的可见性可能是不同的。通常而言,“所见即所得”模式的编辑器中是可见,而“编辑-阅读”模式的编辑器的阅读视图中是不可见的,但输出的网页中均没有定义部分。
脚注
语法如下:
1 | 正文文本[^id] |
脚注跟引用链接语法很像,只是脚注标识是带有 ^
前缀的。
在 Markdown 编辑器预览时:
- 正文中的脚注标识
- 通常显示为上标
- 通常是指向对应脚注定义的超链接
- 可能会将脚注内容显示为悬停帮助信息
- 无论标识为何都会按出现顺序转换为有序数字序列
- 脚注定义
- 总是会显示在正文末尾,且通常以分隔线与正文分开
- 脚注内容末尾可能会显示一个链接跳转回脚注对应的正文
图片
与超链接类似,图片也有内联与引用之分:
1 | 内联图片语法 |
语法上看,只是比对应的链接形式多了一个 !
前缀,而 []
中的是图片的 alt
属性。
值得注意的是,以上两种语法不仅仅支持指定图片链接,还可以内嵌 base64 编码的图片。(具体可参考 这里)
使用内嵌图片的好处就是图文一体,不需要依赖图床等;但其缺点也很明显,base64 编码巨长,在编辑器中通常使得可读性较差,还可能引起滚动卡顿。
文本样式
内联代码
上文提到了代码块语法,通常用以显示大段代码。如果只是嵌在行内的一小段代码,则应使用如下语法:
1 | 后面是一段代码 `code` 使用反引号将代码包裹起来 |
如果代码片段中也包含
`
,可以使用多个反引号将其包裹。如果代码片段中仅包含
`
,则需要在开始标记后及结束标记前插入一个空格。
强调
1 | *斜体text* |
- 使用 1 个或 2 个
*
或_
符号包裹 - 1 个符号包裹转换成
<em>
,2 个符号包裹转换成<strong>
- 开闭标记必须匹配,不能混用
- 开闭标记内部不能紧临空格,否则会被当成普通符号
- 如果要输出强调语法类似的字面量,需要使用
\
转义标记
删除线
1 | ~~delete~~ |
高亮
1 | ==高亮== |
注意,高亮与内联代码不是同一概念。从外观上看,可能在某些环境下是相似的。但它们的语义不同,转换为的标签也不同。高亮语义上是强调,会转换为
<mark>
标签;而内联代码语义上代表代码段,会转换为<code>
标签。大多数 Markdown 编辑器不支持该语法(目前已知仅 Typora 支持),GitHub 也不支持。为了跨环境兼容,可以使用
<mark>
代替。
上下标
1 | 普通文本^上标^ |
有的 Markdown 编辑器中,上标的语法有所不同,仅需要开始标记而不需要关闭标记,
普通文本^上标
。各 Markdown 编辑器对上标/下标的支持也不心如人意,如果想保证跨环境兼容,应该使用
<sup>
和<sub>
标签。
杂项
目录
与 Word 类似,Markdown 支持依据各级标题生成目录,最简单的语法如下:
1 | [TOC] |
如果使用 jekyll 这样的工具生成静态网站,那么生成目录需要用以下语法:
1 | * content |
后一种语法 Markdown 编辑器不一定支持。
YAML Front Matter
YAML Front Matter 主要用于提供文档信息,在 jekyll 中会使用到:
1 | --- |
转义
由于 Markdown 语法使用了一些常用符号作为标记,当要使用这些符号的字面量时,需要用 \
进行转义,可转义的字符有:
1 | \ backslash |
小结
本文讲述了大部分常用的 Markdown 语法,但并非全部。至少 Markdown 还支持公式以及流程图,不过这些内容比较多且繁杂,会采用专题的方式对其进行讲解。
参考
文章
《GitHub 风格的 Markdown 正式规范》发布:GFM 规范发布说明
规范文档
站点
CommonMark 官网:目前 GFM 基于此构建
CommonMark 论坛讨论区: 可以提出关于该规范的的问题和更改建议
GitHub 仓库
Sundown:一个 Markdown 解析器,老版本的 GitHub Markdown 解析器基于此构建
cmark:CommonMark 的 C 语言实现
cmark-gfm:GFM 的 C 语言实现,cmark 的衍生版本
commonmark-spec:CommonMark 各种语言实现的列表