CommonMark 规范

版本 0.6 (2014-10-26)
John MacFarlane
这是本规范的一个旧版本。最新版本请见 https://spec.commonmark.cn

1 简介

1.1 什么是 Markdown?

Markdown 是一种用于编写结构化文档的纯文本格式,其基础是电子邮件和 Usenet 帖子中使用的格式约定。它由 John Gruber 于 2004 年开发,他用 Perl 编写了第一个 Markdown 转 HTML 转换器,并很快在网站中得到广泛应用。到 2014 年,已经有数十种不同语言的实现。其中一些扩展了基础 Markdown 语法,增加了脚注、定义列表、表格和其他构造的约定,还有一些不仅支持输出为 HTML,还支持 LaTeX 及其他多种格式。

1.2 为什么需要规范?

John Gruber 的 Markdown 语法权威描述并没有明确定义其语法。以下是一些它未能解答的问题示例:

  1. 子列表需要多少缩进?规范指出续行段落需要缩进四个空格,但对于子列表的描述并不明确。自然会想到它们也必须缩进四个空格,但 Markdown.pl 并不要求这样做。这绝非“边缘情况”,实现之间在此问题上的分歧往往会导致用户在实际文档中遇到意外。(参见 John Gruber 的这条评论。)

  2. 引用块或标题前是否需要空行?大多数实现不需要空行。然而,这可能在硬换行文本中导致意外结果,并导致解析歧义(注意,有些实现将标题放在引用块内,而另一些则不然)。(John Gruber 也曾明确表示 支持要求使用空行。)

  3. 缩进代码块前是否需要空行?(Markdown.pl 要求它,但文档中并未提及,且有些实现并不要求。)

    paragraph
        code?
  4. 确定列表项何时被 <p> 标签包裹的确切规则是什么?列表可以部分“松散”部分“紧凑”吗?我们该如何处理这样的列表?

    1. one
    
    2. two
    3. three

    或者这个?

    1.  one
        - a
    
        - b
    2.  two

    (John Gruber 在这里有一些相关的评论。)

  5. 列表标记可以缩进吗?有序列表标记可以右对齐吗?

     8. item 1
     9. item 2
    10. item 2a
  6. 这是一个包含水平分割线的列表项的列表,还是由水平分割线分隔的两个列表?

    * a
    * * * * *
    * b
  7. 当列表标记从数字变为圆点时,我们是有两个列表还是一个?(Markdown 语法描述暗示是两个,但 perl 脚本和许多其他实现会生成一个。)

    1. fee
    2. fie
    -  foe
    -  fum
  8. 行内结构标记的优先级规则是什么?例如,以下是有效的链接,还是代码片段拥有更高优先级?

    [a backtick (`)](/url) and [another backtick (`)](/url).
  9. 强调和加粗标记的优先级规则是什么?例如,以下应如何解析?

    *foo *bar* baz*
  10. 块级结构和行内级结构之间的优先级规则是什么?例如,以下应如何解析?

    - `a long code span can contain a hyphen like this
      - and it can screw things up`
  11. 列表项中可以包含标题吗?(Markdown.pl 不允许这样做,但在引用块中可以出现标题。)

    - # Heading
  12. 链接引用可以在块引用或列表项内定义吗?

    > Blockquote [foo].
    >
    > [foo]: /url
  13. 如果有多个同名引用定义,哪个具有优先权?

    [foo]: /url1
    [foo]: /url2
    
    [foo][]

在没有规范的情况下,早期的实现者咨询了 Markdown.pl 来解决这些歧义。但 Markdown.pl 存在很多缺陷,在许多情况下会产生明显糟糕的结果,因此它不能令人满意地替代规范。

由于没有明确的规范,各实现之间出现了相当大的分歧。结果,用户经常惊讶地发现,在某个系统(例如 github wiki)上以某种方式渲染的文档,在另一个系统(例如使用 pandoc 转换为 docbook)上渲染的效果却不同。更糟糕的是,由于 Markdown 中没有什么会被视为“语法错误”,这种差异往往无法立即被发现。

1.3 关于本文档

本文档旨在明确地规范 Markdown 语法。文中包含了许多 Markdown 与 HTML 并列的示例,这些示例旨在同时作为一致性测试使用。随附的脚本 runtests.pl 可用于针对任何 Markdown 程序运行这些测试。

perl runtests.pl spec.txt PROGRAM

由于本文档描述了如何将 Markdown 解析为抽象语法树,因此使用抽象语法树的抽象表示而非 HTML 更有意义。但 HTML 能够表示我们需要区分的结构,并且为测试选择 HTML 使得在不编写抽象语法树渲染器的情况下对实现进行测试成为可能。

本文档是由一个名为 spec.txt 的文本文件生成的,该文件以 Markdown 编写,并针对对比测试进行了一些小的扩展。脚本 spec2md.pl 可用于将 spec.txt 转换为 Pandoc Markdown,进而转换为其他格式。

在示例中,使用 字符来表示制表符。

2 预处理

是由零个或多个字符后跟一个行结束符(CR、LF 或 CRLF)或文件结束符组成的序列。

字符 是一个 Unicode 码位。本规范未指定编码;它将行视为由字符而非字节组成。符合规范的解析器可能受限于某种特定编码。

行中的制表符被扩展为空格,制表位为 4 个字符

示例 1  (交互)
→foo→baz→→bim
<pre><code>foo baz     bim
</code></pre>
示例 2  (交互)
    a→a
    ὐ→a
<pre><code>a   a
ὐ   a
</code></pre>

行结束符会被替换为换行符 (LF)。

不包含任何字符的行,或仅包含空格(制表符展开后)的行,被称为 空行

3 块级元素与行内元素

我们可以将文档视为一个 区块 的序列——即段落、块引用、列表、标题、规则和代码块等结构元素。区块可以包含其他区块,也可以包含 行内 内容:单词、空格、链接、强调文本、图片和行内代码。

3.1 优先级

块结构的指示符总是优先于行内结构的指示符。所以,例如,以下是一个包含两项的列表,而不是一个包含代码片段的项的列表:

示例 3  (交互)
- `one
- two`
<ul>
<li>`one</li>
<li>two`</li>
</ul>

这意味着解析可以分为两步进行:第一,辨别文档的块结构;第二,解析段落、标题和其他块结构中的文本行以确定行内结构。第二步需要仅在第一步结束时才能获得的关于链接引用定义的信息。请注意,第一步需要按顺序处理行,而第二步可以并行化,因为一个块元素的行内解析不会影响其他任何块元素的行内解析。

3.2 容器块与叶子块

我们可以将区块分为两类:容器区块 可以包含其他区块;以及 叶子区块 不可以包含其他区块。

4 叶子块

本节描述了构成 Markdown 文档的不同种类的叶子块。

4.1 水平分割线

由 0-3 个空格缩进,后跟三个或多个匹配的 -_* 字符组成的行,且每个字符后可跟任意数量的空格,构成一个 水平规则

示例 4  (交互)
***
---
___
<hr />
<hr />
<hr />

错误的字符

示例 5  (交互)
+++
<p>+++</p>
示例 6  (交互)
===
<p>===</p>

字符不足

示例 7  (交互)
--
**
__
<p>--
**
__</p>

允许一到三个空格的缩进

示例 8  (交互)
 ***
  ***
   ***
<hr />
<hr />
<hr />

四个空格太多了

示例 9  (交互)
    ***
<pre><code>***
</code></pre>
示例 10  (交互)
Foo
    ***
<p>Foo
***</p>

可以使用超过三个字符

示例 11  (交互)
_____________________________________
<hr />

字符之间允许有空格

示例 12  (交互)
 - - -
<hr />
示例 13  (交互)
 **  * ** * ** * **
<hr />
示例 14  (交互)
-     -      -      -
<hr />

末尾允许有空格

示例 15  (交互)
- - - -    
<hr />

然而,行中不能出现其他任何字符

示例 16  (交互)
_ _ _ _ a

a------

---a---
<p>_ _ _ _ a</p>
<p>a------</p>
<p>---a---</p>

要求所有的非空格字符必须相同。因此,这不是一条水平分割线

示例 17  (交互)
 *-*
<p><em>-</em></p>

水平分割线前后不需要空行

示例 18  (交互)
- foo
***
- bar
<ul>
<li>foo</li>
</ul>
<hr />
<ul>
<li>bar</li>
</ul>

水平分割线可以中断段落

示例 19  (交互)
Foo
***
bar
<p>Foo</p>
<hr />
<p>bar</p>

如果一行连字符符合上述水平分割线的条件,同时也能被解读为 Setext 标题 的下划线,则解读为 Setext 标题 的优先级更高。因此,举例来说,这是一个 Setext 标题,而不是一个段落后跟一条水平分割线

示例 20  (交互)
Foo
---
bar
<h2>Foo</h2>
<p>bar</p>

当一行同时可能被解读为水平分割线和列表项时,优先选择水平分割线

示例 21  (交互)
* Foo
* * *
* Bar
<ul>
<li>Foo</li>
</ul>
<hr />
<ul>
<li>Bar</li>
</ul>

如果你想在列表项中使用水平分割线,请使用不同的项目符号

示例 22  (交互)
- Foo
- * * *
<ul>
<li>Foo</li>
<li><hr /></li>
</ul>

4.2 ATX 标题

ATX 标题 由一串解析为行内内容的字符组成,位于起始的 1-6 个未转义的 # 字符序列和可选的末尾任意数量的 # 字符序列之间。起始的 # 字符序列后不能直接紧跟非空格字符。可选的末尾 # 序列前必须有一个空格,且其后只能跟空格。起始的 # 字符可以缩进 0-3 个空格。标题的原始内容在解析为行内内容之前,会剔除首尾空格。标题级别等于起始序列中 # 字符的数量。

简单标题

示例 23  (交互)
# foo
## foo
### foo
#### foo
##### foo
###### foo
<h1>foo</h1>
<h2>foo</h2>
<h3>foo</h3>
<h4>foo</h4>
<h5>foo</h5>
<h6>foo</h6>

超过六个 # 字符不是标题

示例 24  (交互)
####### foo
<p>####### foo</p>

# 字符和标题内容之间需要一个空格。请注意,许多实现目前不需要该空格。然而,原始的 ATX 实现 要求有空格,且这有助于防止类似以下内容被解析为标题

示例 25  (交互)
#5 bolt
<p>#5 bolt</p>

这不是标题,因为第一个 # 被转义了

示例 26  (交互)
\## foo
<p>## foo</p>

内容按行内元素解析

示例 27  (交互)
# foo *bar* \*baz\*
<h1>foo <em>bar</em> *baz*</h1>

解析行内内容时,首尾空格会被忽略

示例 28  (交互)
#                  foo                     
<h1>foo</h1>

允许 1 到 3 个空格的缩进

示例 29  (交互)
 ### foo
  ## foo
   # foo
<h3>foo</h3>
<h2>foo</h2>
<h1>foo</h1>

四个空格太多了

示例 30  (交互)
    # foo
<pre><code># foo
</code></pre>
示例 31  (交互)
foo
    # bar
<p>foo
# bar</p>

结束的 # 字符序列是可选的

示例 32  (交互)
## foo ##
  ###   bar    ###
<h2>foo</h2>
<h3>bar</h3>

它不需要与起始序列长度相同

示例 33  (交互)
# foo ##################################
##### foo ##
<h1>foo</h1>
<h5>foo</h5>

结束序列后允许有空格

示例 34  (交互)
### foo ###     
<h3>foo</h3>

后跟非空格字符的 # 字符序列不是结尾序列,而是计入标题内容的一部分

示例 35  (交互)
### foo ### b
<h3>foo ### b</h3>

结束序列前必须有一个空格

示例 36  (交互)
# foo#
<h1>foo#</h1>

反斜杠转义的 # 字符不计为结束序列的一部分

示例 37  (交互)
### foo \###
## foo #\##
# foo \#
<h3>foo ###</h3>
<h2>foo ###</h2>
<h1>foo #</h1>

ATX 标题不需要由空行与周围内容分隔,且它们可以中断段落

示例 38  (交互)
****
## foo
****
<hr />
<h2>foo</h2>
<hr />
示例 39  (交互)
Foo bar
# baz
Bar foo
<p>Foo bar</p>
<h1>baz</h1>
<p>Bar foo</p>

ATX 标题可以是空的

示例 40  (交互)
## 
#
### ###
<h2></h2>
<h1></h1>
<h3></h3>

4.3 Setext 标题

Setext 标题 由一行文本组成(包含至少一个非空格字符,缩进不超过 3 个空格),后跟一个 Setext 标题下划线。该文本行必须是那种如果不加下划线就会被解析为段落一部分的行:不能是代码块、标题、块引用、水平规则或列表。Setext 标题下划线 是一个由 = 字符或 - 字符组成的序列,缩进不超过 3 个空格,且可跟任意数量的尾随空格。如果使用 = 字符,则标题为一级;如果使用 - 字符,则标题为二级。标题内容是将第一行解析为 Markdown 行内内容的结果。

通常,Setext 标题前后不需要空行。但是,它不能中断段落,因此当 Setext 标题出现在段落之后时,它们之间需要一个空行。

简单示例

示例 41  (交互)
Foo *bar*
=========

Foo *bar*
---------
<h1>Foo <em>bar</em></h1>
<h2>Foo <em>bar</em></h2>

下划线可以是任意长度

示例 42  (交互)
Foo
-------------------------

Foo
=
<h2>Foo</h2>
<h1>Foo</h1>

标题内容最多可以缩进三个空格,且不必与下划线对齐

示例 43  (交互)
   Foo
---

  Foo
-----

  Foo
  ===
<h2>Foo</h2>
<h2>Foo</h2>
<h1>Foo</h1>

四个空格缩进太多了

示例 44  (交互)
    Foo
    ---

    Foo
---
<pre><code>Foo
---

Foo
</code></pre>
<hr />

Setext 标题下划线最多可以缩进三个空格,且末尾可以有空格

示例 45  (交互)
Foo
   ----      
<h2>Foo</h2>

四个空格太多了

示例 46  (交互)
Foo
     ---
<p>Foo
---</p>

Setext 标题下划线不能包含内部空格

示例 47  (交互)
Foo
= =

Foo
--- -
<p>Foo
= =</p>
<p>Foo</p>
<hr />

内容行中的尾随空格不会导致换行

示例 48  (交互)
Foo  
-----
<h2>Foo</h2>

结尾的反斜杠也不会导致换行

示例 49  (交互)
Foo\
----
<h2>Foo\</h2>

由于块结构的指示符优先于行内结构的指示符,以下是 Setext 标题

示例 50  (交互)
`Foo
----
`

<a title="a lot
---
of dashes"/>
<h2>`Foo</h2>
<p>`</p>
<h2>&lt;a title=&quot;a lot</h2>
<p>of dashes&quot;/&gt;</p>

Setext 标题下划线不能是列表项或块引用中的 懒惰续行

示例 51  (交互)
> Foo
---
<blockquote>
<p>Foo</p>
</blockquote>
<hr />
示例 52  (交互)
- Foo
---
<ul>
<li>Foo</li>
</ul>
<hr />

Setext 标题不能中断段落

示例 53  (交互)
Foo
Bar
---

Foo
Bar
===
<p>Foo
Bar</p>
<hr />
<p>Foo
Bar
===</p>

但通常前后不需要空行

示例 54  (交互)
---
Foo
---
Bar
---
Baz
<hr />
<h2>Foo</h2>
<h2>Bar</h2>
<p>Baz</p>

Setext 标题不能为空

示例 55  (交互)

====
<p>====</p>

Setext 标题文本行不能被解释为除段落以外的块结构。因此,这些例子中的破折号行被解释为水平分割线

示例 56  (交互)
---
---
<hr />
<hr />
示例 57  (交互)
- foo
-----
<ul>
<li>foo</li>
</ul>
<hr />
示例 58  (交互)
    foo
---
<pre><code>foo
</code></pre>
<hr />
示例 59  (交互)
> foo
-----
<blockquote>
<p>foo</p>
</blockquote>
<hr />

如果你想要一个以 > foo 作为字面文本的标题,可以使用反斜杠转义

示例 60  (交互)
\> foo
------
<h2>&gt; foo</h2>

4.4 缩进代码块

缩进代码块 由一个或多个被空行分隔的 缩进块 组成。缩进块 是一个非空行序列,每一行都缩进四个或更多空格。缩进代码块不能中断段落,因此如果它出现在段落之前或之后,必须有一个空行间隔。代码块的内容是行的字面内容(包括尾随换行符),减去四个空格的缩进。缩进代码块没有属性。

示例 61  (交互)
    a simple
      indented code block
<pre><code>a simple
  indented code block
</code></pre>

内容为字面文本,不会被解析为 Markdown

示例 62  (交互)
    <a/>
    *hi*

    - one
<pre><code>&lt;a/&gt;
*hi*

- one
</code></pre>

这里我们有三个由空行分隔的片段

示例 63  (交互)
    chunk1

    chunk2
  
 
 
    chunk3
<pre><code>chunk1

chunk2



chunk3
</code></pre>

超过四个空格的任何初始空格都将包含在内容中,即使在内部空行中也是如此

示例 64  (交互)
    chunk1
      
      chunk2
<pre><code>chunk1
  
  chunk2
</code></pre>

缩进代码块不能打断段落。(这允许悬挂缩进等。)

示例 65  (交互)
Foo
    bar
<p>Foo
bar</p>

然而,任何前导空格少于四个的非空行都会立即结束代码块。所以一个段落可能会紧接在缩进代码之后

示例 66  (交互)
    foo
bar
<pre><code>foo
</code></pre>
<p>bar</p>

缩进代码可以紧接在其他类型的块之前和之后

示例 67  (交互)
# Header
    foo
Header
------
    foo
----
<h1>Header</h1>
<pre><code>foo
</code></pre>
<h2>Header</h2>
<pre><code>foo
</code></pre>
<hr />

第一行可以缩进超过四个空格

示例 68  (交互)
        foo
    bar
<pre><code>    foo
bar
</code></pre>

缩进代码块之前或之后的空行不包含在其中

示例 69  (交互)

    
    foo
    
<pre><code>foo
</code></pre>

尾随空格包含在代码块的内容中

示例 70  (交互)
    foo  
<pre><code>foo  
</code></pre>

4.5 围栏代码块

代码围栏 是至少三个连续反引号 (`) 或波浪号 (~) 的序列。(波浪号和反引号不能混用。)围栏代码块 以代码围栏开始,缩进不超过三个空格。

起始代码围栏的行可以选择在围栏后包含一些文本;这部分文本会剔除首尾空格,被称为 信息字符串 信息字符串不得包含任何反引号。(此限制的原因是,否则某些行内代码会被错误地解释为围栏代码块的开始。)

代码块的内容由所有后续行组成,直到出现与代码块开头相同类型(反引号或波浪号)且至少与起始代码围栏一样长的关闭 代码围栏。如果起始代码围栏缩进了 N 个空格,则每行内容会去除最多 N 个空格的缩进(如果存在)。(如果内容行没有缩进,则保持不变。如果缩进少于 N 个空格,则去除所有缩进。)

关闭代码围栏最多可以缩进三个空格,并且后面只能跟空格,这些空格会被忽略。如果达到了包含块(或文档)的末尾且未找到关闭代码围栏,则代码块包含起始代码围栏之后到包含块(或文档)末尾的所有行。(另一种规范会在未找到关闭代码围栏时要求回溯。但这会使解析效率大打折扣,且这里描述的行为似乎并没有什么真正的弊端。)

围栏代码块可以打断段落,且不需要之前或之后有空行。

代码围栏内的内容被视为字面文本,不会被解析为行内内容。信息字符串的第一个单词通常用于指定代码示例的语言,并渲染在 code 标签的 class 属性中。然而,本规范并未强制要求对信息字符串进行任何特定处理。

这是一个带有反引号的简单示例

示例 71  (交互)
```
<
 >
```
<pre><code>&lt;
 &gt;
</code></pre>

带有波浪号的情况

示例 72  (交互)
~~~
<
 >
~~~
<pre><code>&lt;
 &gt;
</code></pre>

关闭代码围栏必须使用与起始围栏相同的字符

示例 73  (交互)
```
aaa
~~~
```
<pre><code>aaa
~~~
</code></pre>
示例 74  (交互)
~~~
aaa
```
~~~
<pre><code>aaa
```
</code></pre>

关闭代码围栏必须至少与起始围栏一样长

示例 75  (交互)
````
aaa
```
``````
<pre><code>aaa
```
</code></pre>
示例 76  (交互)
~~~~
aaa
~~~
~~~~
<pre><code>aaa
~~~
</code></pre>

未关闭的代码块会在文档末尾处关闭

示例 77  (交互)
```
<pre><code></code></pre>
示例 78  (交互)
`````

```
aaa
<pre><code>
```
aaa
</code></pre>

代码块的内容可以全为空行

示例 79  (交互)
```

  
```
<pre><code>
  
</code></pre>

代码块可以为空

示例 80  (交互)
```
```
<pre><code></code></pre>

围栏可以缩进。如果起始围栏缩进,则内容行中的相应起始缩进将被移除(如果存在)

示例 81  (交互)
 ```
 aaa
aaa
```
<pre><code>aaa
aaa
</code></pre>
示例 82  (交互)
  ```
aaa
  aaa
aaa
  ```
<pre><code>aaa
aaa
aaa
</code></pre>
示例 83  (交互)
   ```
   aaa
    aaa
  aaa
   ```
<pre><code>aaa
 aaa
aaa
</code></pre>

四个空格缩进会产生缩进代码块

示例 84  (交互)
    ```
    aaa
    ```
<pre><code>```
aaa
```
</code></pre>

关闭围栏可以缩进 0-3 个空格,且其缩进无需与起始围栏匹配

示例 85  (交互)
```
aaa
  ```
<pre><code>aaa
</code></pre>
示例 86  (交互)
   ```
aaa
  ```
<pre><code>aaa
</code></pre>

这不是关闭围栏,因为它缩进了 4 个空格

示例 87  (交互)
```
aaa
    ```
<pre><code>aaa
    ```
</code></pre>

代码围栏(起始和关闭)不能包含内部空格

示例 88  (交互)
``` ```
aaa
<p><code></code>
aaa</p>
示例 89  (交互)
~~~~~~
aaa
~~~ ~~
<pre><code>aaa
~~~ ~~
</code></pre>

围栏代码块可以打断段落,且可以紧接着段落,中间不需要空行

示例 90  (交互)
foo
```
bar
```
baz
<p>foo</p>
<pre><code>bar
</code></pre>
<p>baz</p>

其他块也可以出现在围栏代码块之前和之后,且中间无需空行

示例 91  (交互)
foo
---
~~~
bar
~~~
# baz
<h2>foo</h2>
<pre><code>bar
</code></pre>
<h1>baz</h1>

可以在起始代码围栏之后提供一个 信息字符串。首尾空格将被去除,第一个单词(加上 language- 前缀)将用作包含 pre 元素内的 code 元素的 class 属性值。

示例 92  (交互)
```ruby
def foo(x)
  return 3
end
```
<pre><code class="language-ruby">def foo(x)
  return 3
end
</code></pre>
示例 93  (交互)
~~~~    ruby startline=3 $%@#$
def foo(x)
  return 3
end
~~~~~~~
<pre><code class="language-ruby">def foo(x)
  return 3
end
</code></pre>
示例 94  (交互)
````;
````
<pre><code class="language-;"></code></pre>

反引号代码块的信息字符串不能包含反引号

示例 95  (交互)
``` aa ```
foo
<p><code>aa</code>
foo</p>

结尾的围栏代码块不能包含信息字符串

示例 96  (交互)
```
``` aaa
```
<pre><code>``` aaa
</code></pre>

4.6 HTML 块

HTML 块标签 是指标签名称为以下内容之一(不区分大小写)的 开始标签结束标签article, header, aside, hgroup, blockquote, hr, iframe, body, li, map, button, object, canvas, ol, caption, output, col, p, colgroup, pre, dd, progress, div, section, dl, table, td, dt, tbody, embed, textarea, fieldset, tfoot, figcaption, th, figure, thead, footer, tr, form, ul, h1, h2, h3, h4, h5, h6, video, script, style

HTML 区块 HTML 区块标签HTML 注释处理指令声明CDATA 节 开始。当遇到 空行 或输入结束时,它结束。初始行最多可缩进三个空格,后续行可以有任何缩进。HTML 区块的内容被解释为原始 HTML,不会在 HTML 输出中进行转义。

一些简单的例子

示例 97  (交互)
<table>
  <tr>
    <td>
           hi
    </td>
  </tr>
</table>

okay.
<table>
  <tr>
    <td>
           hi
    </td>
  </tr>
</table>
<p>okay.</p>
示例 98  (交互)
 <div>
  *hello*
         <foo><a>
 <div>
  *hello*
         <foo><a>

这里我们有两个 HTML 块,中间有一个 Markdown 段落

示例 99  (交互)
<DIV CLASS="foo">

*Markdown*

</DIV>
<DIV CLASS="foo">
<p><em>Markdown</em></p>
</DIV>

在以下例子中,看起来像 Markdown 代码块的内容实际上是 HTML 块的一部分,该块一直持续到遇到空行或文档结束

示例 100  (交互)
<div></div>
``` c
int x = 33;
```
<div></div>
``` c
int x = 33;
```

注释

示例 101  (交互)
<!-- Foo
bar
   baz -->
<!-- Foo
bar
   baz -->

处理指令

示例 102  (交互)
<?php
  echo '>';
?>
<?php
  echo '>';
?>

CDATA

示例 103  (交互)
<![CDATA[
function matchwo(a,b)
{
if (a < b && a < 0) then
  {
  return 1;
  }
else
  {
  return 0;
  }
}
]]>
<![CDATA[
function matchwo(a,b)
{
if (a < b && a < 0) then
  {
  return 1;
  }
else
  {
  return 0;
  }
}
]]>

起始标签可以缩进 1-3 个空格,但不能缩进 4 个

示例 104  (交互)
  <!-- foo -->

    <!-- foo -->
  <!-- foo -->
<pre><code>&lt;!-- foo --&gt;
</code></pre>

HTML 块可以中断段落,且前面不需要空行。

示例 105  (交互)
Foo
<div>
bar
</div>
<p>Foo</p>
<div>
bar
</div>

然而,后续始终需要一个空行,除非在文档末尾

示例 106  (交互)
<div>
bar
</div>
*foo*
<div>
bar
</div>
*foo*

不完整的 HTML 块标签也可以开启一个 HTML 块

示例 107  (交互)
<div class
foo
<div class
foo

此规则与 John Gruber 原来的 Markdown 语法规范不同,后者指出:

唯一的限制是块级 HTML 元素(例如 <div>, <table>, <pre>, <p> 等)必须与周围内容用空行分隔,且该块的开始和结束标签不应使用制表符或空格缩进。

在某些方面,Gruber 的规则比这里给出的规则更严格:

事实上,大多数 Markdown 实现(包括 Gruber 自己的一些 Perl 实现)并未施加这些限制。

然而,在有一个方面,Gruber 的规则比这里给出的规则更宽松,因为它允许 HTML 块内出现空行。这里禁止它们有两个原因。首先,它消除了解析平衡标签的需要,这很昂贵,并且如果未找到匹配的结束标签,可能需要从文档末尾回溯。其次,它提供了一种在 HTML 标签内包含 Markdown 内容的非常简单且灵活的方法:只需使用空行将 Markdown 与 HTML 分隔开。

示例 108  (交互)
<div>

*Emphasized* text.

</div>
<div>
<p><em>Emphasized</em> text.</p>
</div>

比较:

示例 109  (交互)
<div>
*Emphasized* text.
</div>
<div>
*Emphasized* text.
</div>

一些 Markdown 实现采用了如果开始标签具有 markdown=1 属性就将标签内内容解释为文本的约定。上述规则似乎是一种更简单、更优雅的实现相同表达能力的方法,解析起来也简单得多。

主要潜在的缺点是人们无法再 100% 可靠地将 HTML 块粘贴到 Markdown 文档中。但是,在大多数情况下这可以正常工作,因为 HTML 中的空行通常后跟 HTML 块标签。例如:

示例 110  (交互)
<table>

<tr>

<td>
Hi
</td>

</tr>

</table>
<table>
<tr>
<td>
Hi
</td>
</tr>
</table>

此外,空行通常是不必要的,可以删除。特例是在 <pre> 标签内;在这里,可以用 &#10; 实体替换空行。

因此,使用新规则并不会造成实质性的表达能力损失。

链接引用定义 由一个缩进最多三个空格的 链接标签、后跟一个冒号 (:)、可选空格(包括最多一个换行符)、一个 链接目标、可选空格(包括最多一个换行符)以及一个可选的 链接标题 组成,如果存在标题,必须用空白字符与 链接目标 分隔。该行不得再有其他非空格字符。

链接引用定义 不对应文档的结构元素。相反,它定义了一个标签,该标签可在文档其他地方的 引用链接 和引用样式 图像 中使用。链接引用定义 可以出现在使用它们的链接之前或之后。

示例 111  (交互)
[foo]: /url "title"

[foo]
<p><a href="/url" title="title">foo</a></p>
示例 112  (交互)
   [foo]: 
      /url  
           'the title'  

[foo]
<p><a href="/url" title="the title">foo</a></p>
示例 113  (交互)
[Foo*bar\]]:my_(url) 'title (with parens)'

[Foo*bar\]]
<p><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
示例 114  (交互)
[Foo bar]:
<my url>
'title'

[Foo bar]
<p><a href="my%20url" title="title">Foo bar</a></p>

标题可以省略

示例 115  (交互)
[foo]:
/url

[foo]
<p><a href="/url">foo</a></p>

链接目标不能省略

示例 116  (交互)
[foo]:

[foo]
<p>[foo]:</p>
<p>[foo]</p>

链接可以出现在其对应的定义之前

示例 117  (交互)
[foo]

[foo]: url
<p><a href="url">foo</a></p>

如果有多个匹配的定义,第一个具有优先权

示例 118  (交互)
[foo]

[foo]: first
[foo]: second
<p><a href="first">foo</a></p>

链接一节所述,标签匹配是不区分大小写的(参见 matches)。

示例 119  (交互)
[FOO]: /url

[Foo]
<p><a href="/url">Foo</a></p>
示例 120  (交互)
[ΑΓΩ]: /φου

[αγω]
<p><a href="/%CF%86%CE%BF%CF%85">αγω</a></p>

这是一个没有对应链接的链接引用定义。它对文档没有任何贡献。

示例 121  (交互)
[foo]: /url

这不是一个链接引用定义,因为标题后面还有非空格字符

示例 122  (交互)
[foo]: /url "title" ok
<p>[foo]: /url &quot;title&quot; ok</p>

这不是链接引用定义,因为它缩进了四个空格

示例 123  (交互)
    [foo]: /url "title"

[foo]
<pre><code>[foo]: /url &quot;title&quot;
</code></pre>
<p>[foo]</p>

这不是一个链接引用定义,因为它出现在代码块内部

示例 124  (交互)
```
[foo]: /url
```

[foo]
<pre><code>[foo]: /url
</code></pre>
<p>[foo]</p>

链接引用定义不能中断段落。

示例 125  (交互)
Foo
[bar]: /baz

[bar]
<p>Foo
[bar]: /baz</p>
<p>[bar]</p>

然而,它可以直接跟在其他块元素(如标题和水平分割线)之后,且后面不需要空行。

示例 126  (交互)
# [Foo]
[foo]: /url
> bar
<h1><a href="/url">Foo</a></h1>
<blockquote>
<p>bar</p>
</blockquote>

多个 链接引用 可以一个接一个地出现,中间无需空行。

示例 127  (交互)
[foo]: /foo-url "foo"
[bar]: /bar-url
  "bar"
[baz]: /baz-url

[foo],
[bar],
[baz]
<p><a href="/foo-url" title="foo">foo</a>,
<a href="/bar-url" title="bar">bar</a>,
<a href="/baz-url">baz</a></p>

链接引用定义可以出现在块容器(如列表和引用块)内部。它们影响整个文档,而不仅仅是定义它们的那个容器。

示例 128  (交互)
[foo]

> [foo]: /url
<p><a href="/url">foo</a></p>
<blockquote>
</blockquote>

4.8 段落

不能被解释为其他类型区块的非空行序列构成一个 段落 段落内容是将段落原始内容解析为行内元素的结果。段落的原始内容是通过拼接这些行并删除起始和结尾的空格形成的。

一个有两个段落的简单示例

示例 129  (交互)
aaa

bbb
<p>aaa</p>
<p>bbb</p>

段落可以包含多行,但不能包含空行

示例 130  (交互)
aaa
bbb

ccc
ddd
<p>aaa
bbb</p>
<p>ccc
ddd</p>

段落之间的多个空行无效

示例 131  (交互)
aaa


bbb
<p>aaa</p>
<p>bbb</p>

前导空格会被忽略

示例 132  (交互)
  aaa
 bbb
<p>aaa
bbb</p>

第一行之后的各行可以有任意数量的缩进,因为缩进代码块不能中断段落。

示例 133  (交互)
aaa
             bbb
                                       ccc
<p>aaa
bbb
ccc</p>

然而,第一行的缩进最多只能有三个空格,否则会触发缩进代码块

示例 134  (交互)
   aaa
bbb
<p>aaa
bbb</p>
示例 135  (交互)
    aaa
bbb
<pre><code>aaa
</code></pre>
<p>bbb</p>

行尾空格在行内解析前会被剔除,因此以两个或更多空格结尾的段落不会以 硬换行 结尾

示例 136  (交互)
aaa     
bbb     
<p>aaa<br />
bbb</p>

4.9 空行

块级元素之间的空行会被忽略,但在确定列表紧凑还是松散时起作用。

文档开头和结尾的空行也会被忽略。

示例 137  (交互)
  

aaa
  

# aaa

  
<p>aaa</p>
<h1>aaa</h1>

5 容器块

容器块 是指将其他块作为其内容的块。容器块有两种基本类型:引用块列表项列表列表项 的元容器。

我们以递归方式定义容器块的语法。定义的一般形式是

如果 X 是一系列块,那么以某种方式转换 X 的结果就是类型为 Y 的容器,其内容为这些块。

因此,我们通过解释如何从内容中 生成 块引用或列表项来定义它们。这足以定义语法,尽管它没有提供 解析 这些结构的具体方案。(方案在下方的 解析策略 一节中提供。)

5.1 引用块

块引用标记 由 0-3 个空格的初始缩进,加上 (a) 字符 > 连同随后的一个空格,或 (b) 单个字符 > 但其后不跟空格组成。

以下规则定义了 块引用

  1. 基本情况。 如果一行字符串 Ls 构成一系列块 Bs,那么在 Ls 中每一行的开头添加一个 引用块标记,其结果就是包含 Bs引用块

  2. 懒惰规则(Laziness)。 如果一串行 Ls 构成了内容为 Bs块引用,那么从一行或多行中删除初始 块引用标记(前提是 块引用标记 后的下一个非空格字符是 段落延续文本),其结果仍是一个内容为 Bs 的块引用。 段落延续文本 是指将被解析为段落内容一部分,但不是段落起始的文本。

  3. 连续性。 一个文档中不能连续包含两个 引用块,除非它们之间有一个 空行

除此之外,任何内容都不算作 引用块

这是一个简单的例子

示例 138  (交互)
> # Foo
> bar
> baz
<blockquote>
<h1>Foo</h1>
<p>bar
baz</p>
</blockquote>

可以省略 > 字符后的空格

示例 139  (交互)
># Foo
>bar
> baz
<blockquote>
<h1>Foo</h1>
<p>bar
baz</p>
</blockquote>

> 字符可以缩进 1-3 个空格

示例 140  (交互)
   > # Foo
   > bar
 > baz
<blockquote>
<h1>Foo</h1>
<p>bar
baz</p>
</blockquote>

四个空格会产生一个代码块

示例 141  (交互)
    > # Foo
    > bar
    > baz
<pre><code>&gt; # Foo
&gt; bar
&gt; baz
</code></pre>

惰性匹配条款允许我们在段落延续行之前省略 >

示例 142  (交互)
> # Foo
> bar
baz
<blockquote>
<h1>Foo</h1>
<p>bar
baz</p>
</blockquote>

引用块可以包含一些惰性匹配行和一些非惰性匹配行

示例 143  (交互)
> bar
baz
> foo
<blockquote>
<p>bar
baz
foo</p>
</blockquote>

懒惰仅适用于段落的续行。包含指示块结构的字符或缩进的行不能是懒惰的。

示例 144  (交互)
> foo
---
<blockquote>
<p>foo</p>
</blockquote>
<hr />
示例 145  (交互)
> - foo
- bar
<blockquote>
<ul>
<li>foo</li>
</ul>
</blockquote>
<ul>
<li>bar</li>
</ul>
示例 146  (交互)
>     foo
    bar
<blockquote>
<pre><code>foo
</code></pre>
</blockquote>
<pre><code>bar
</code></pre>
示例 147  (交互)
> ```
foo
```
<blockquote>
<pre><code></code></pre>
</blockquote>
<p>foo</p>
<pre><code></code></pre>

引用块可以为空

示例 148  (交互)
>
<blockquote>
</blockquote>
示例 149  (交互)
>
>  
> 
<blockquote>
</blockquote>

引用块可以有初始或最终空行

示例 150  (交互)
>
> foo
>  
<blockquote>
<p>foo</p>
</blockquote>

空行总是会分隔引用块

示例 151  (交互)
> foo

> bar
<blockquote>
<p>foo</p>
</blockquote>
<blockquote>
<p>bar</p>
</blockquote>

(大多数当前的 Markdown 实现,包括 John Gruber 最初的 Markdown.pl,会将此示例解析为一个包含两个段落的单个引用块。但让作者决定想要两个还是一个引用块似乎更好。)

连续性意味着如果我们把这些引用块放在一起,我们就会得到一个单一的引用块

示例 152  (交互)
> foo
> bar
<blockquote>
<p>foo
bar</p>
</blockquote>

要获得包含两个段落的引用块,请使用

示例 153  (交互)
> foo
>
> bar
<blockquote>
<p>foo</p>
<p>bar</p>
</blockquote>

引用块可以中断段落

示例 154  (交互)
foo
> bar
<p>foo</p>
<blockquote>
<p>bar</p>
</blockquote>

通常情况下,引用块前后不需要空行

示例 155  (交互)
> aaa
***
> bbb
<blockquote>
<p>aaa</p>
</blockquote>
<hr />
<blockquote>
<p>bbb</p>
</blockquote>

然而,由于惰性,在引用块和随后的段落之间需要一个空行

示例 156  (交互)
> bar
baz
<blockquote>
<p>bar
baz</p>
</blockquote>
示例 157  (交互)
> bar

baz
<blockquote>
<p>bar</p>
</blockquote>
<p>baz</p>
示例 158  (交互)
> bar
>
baz
<blockquote>
<p>bar</p>
</blockquote>
<p>baz</p>

惰性规则的一个结果是,在嵌套引用块的延续行上可以省略任意数量的初始 >

示例 159  (交互)
> > > foo
bar
<blockquote>
<blockquote>
<blockquote>
<p>foo
bar</p>
</blockquote>
</blockquote>
</blockquote>
示例 160  (交互)
>>> foo
> bar
>>baz
<blockquote>
<blockquote>
<blockquote>
<p>foo
bar
baz</p>
</blockquote>
</blockquote>
</blockquote>

当在引用块中包含缩进代码块时,请记住引用块标记包括 > 及其后的一个空格。因此 > 之后需要五个空格

示例 161  (交互)
>     code

>    not code
<blockquote>
<pre><code>code
</code></pre>
</blockquote>
<blockquote>
<p>not code</p>
</blockquote>

5.2 列表项

列表标记 无序列表标记有序列表标记

无序列表标记 是一个 -, +, 或 * 字符。

有序列表标记 是一个或多个数字 (0-9) 组成的序列,后跟一个 . 字符或 ) 字符。

以下规则定义了 列表项

  1. 基本情况。 如果一系列行 Ls 构成一系列块 Bs(以非空格字符开头,且彼此之间分隔不超过一个空行),且 M 是宽度为 W 的列表标记,后跟 0 < N < 5 个空格,那么将 M 及其后的空格添加到 Ls 的第一行,并将 Ls 的后续行缩进 W + N 个空格,其结果就是一个内容为 Bs 的列表项。列表项的类型(无序或有序)由其列表标记类型决定。如果列表项是有序的,则根据有序列表标记分配一个起始编号。

例如,设 Ls 为以下几行

示例 162  (交互)
A paragraph
with two lines.

    indented code

> A block quote.
<p>A paragraph
with two lines.</p>
<pre><code>indented code
</code></pre>
<blockquote>
<p>A block quote.</p>
</blockquote>

M 为标记 1.N = 2。规则 #1 表明以下内容是一个起始编号为 1 的有序列表项,其内容与 Ls 相同

示例 163  (交互)
1.  A paragraph
    with two lines.

        indented code

    > A block quote.
<ol>
<li><p>A paragraph
with two lines.</p>
<pre><code>indented code
</code></pre>
<blockquote>
<p>A block quote.</p>
</blockquote></li>
</ol>

最重要的一点是,列表标记后的文本位置决定了后续列表项块所需的缩进量。如果列表标记占用两个空格,且列表标记与下一个非空格字符之间有三个空格,则后续块必须缩进五个空格才能归属于该列表项。

以下是一些显示内容必须缩进多少才能置于列表项之下的示例

示例 164  (交互)
- one

 two
<ul>
<li>one</li>
</ul>
<p>two</p>
示例 165  (交互)
- one

  two
<ul>
<li><p>one</p>
<p>two</p></li>
</ul>
示例 166  (交互)
 -    one

     two
<ul>
<li>one</li>
</ul>
<pre><code> two
</code></pre>
示例 167  (交互)
 -    one

      two
<ul>
<li><p>one</p>
<p>two</p></li>
</ul>

人们很容易从列的角度去思考:延续块必须至少缩进到列表标记后第一个非空格字符的列位置。然而,这并不完全准确。列表标记后的空格决定了所需的相对缩进量。此缩进所到达的列取决于列表项如何嵌入到其他结构中,如本例所示

示例 168  (交互)
   > > 1.  one
>>
>>     two
<blockquote>
<blockquote>
<ol>
<li><p>one</p>
<p>two</p></li>
</ol>
</blockquote>
</blockquote>

这里 two 出现在与列表标记 1. 相同的列中,但实际上包含在列表项中,因为在最后一个包含的块引用标记之后有足够的缩进。

反之亦然。在以下示例中,单词 two 出现在列表项初始文本 one 的远右侧,但它不被视为列表项的一部分,因为它在引用块标记之后的缩进不足

示例 169  (交互)
>>- one
>>
  >  > two
<blockquote>
<blockquote>
<ul>
<li>one</li>
</ul>
<p>two</p>
</blockquote>
</blockquote>

列表项不能包含被超过一个空行分隔的块。因此,两个空行将结束一个列表,除非这两个空行包含在围栏代码块中。

示例 170  (交互)
- foo

  bar

- foo


  bar

- ```
  foo


  bar
  ```
<ul>
<li><p>foo</p>
<p>bar</p></li>
<li><p>foo</p></li>
</ul>
<p>bar</p>
<ul>
<li><pre><code>foo


bar
</code></pre></li>
</ul>

列表项可以包含任何类型的块

示例 171  (交互)
1.  foo

    ```
    bar
    ```

    baz

    > bam
<ol>
<li><p>foo</p>
<pre><code>bar
</code></pre>
<p>baz</p>
<blockquote>
<p>bam</p>
</blockquote></li>
</ol>
  1. 以缩进代码开头的项。 如果一串行 Ls 构成一系列以缩进代码块开头且互不被超过一个空行分隔的块 Bs,且 M 是一个宽度为 W 的列表标记,后跟一个空格,那么在 Ls 的第一行前加上 M 和随后的空格,并将 Ls 的后续行缩进 W + 1 个空格的结果,就是一个内容为 Bs 的列表项。如果一行是空的,则不需要缩进。列表项的类型由其列表标记的类型决定。如果列表项是有序的,则还会根据有序列表标记分配一个起始编号。

缩进代码块需要缩进到列表项中包含文本区域边缘之外的四个空格。在下一种情况下,即为 6 个空格

示例 172  (交互)
- foo

      bar
<ul>
<li><p>foo</p>
<pre><code>bar
</code></pre></li>
</ul>

在这种情况下为 11 个空格

示例 173  (交互)
  10.  foo

           bar
<ol start="10">
<li><p>foo</p>
<pre><code>bar
</code></pre></li>
</ol>

如果列表项中的第一个块是缩进代码块,则根据规则 #2,其内容必须在列表标记之后缩进一个空格

示例 174  (交互)
    indented code

paragraph

    more code
<pre><code>indented code
</code></pre>
<p>paragraph</p>
<pre><code>more code
</code></pre>
示例 175  (交互)
1.     indented code

   paragraph

       more code
<ol>
<li><pre><code>indented code
</code></pre>
<p>paragraph</p>
<pre><code>more code
</code></pre></li>
</ol>

注意,额外的空格缩进会被解释为代码块内的空格

示例 176  (交互)
1.      indented code

   paragraph

       more code
<ol>
<li><pre><code> indented code
</code></pre>
<p>paragraph</p>
<pre><code>more code
</code></pre></li>
</ol>

请注意,规则 #1 和 #2 仅适用于两种情况:(a) 包含在列表项中的行以非空格字符开头的情况,以及 (b) 以缩进代码块开头的情况。在如下情况中,即第一个块以三个空格缩进开始,规则不允许我们通过缩进整体并添加列表标记来形成列表项

示例 177  (交互)
   foo

bar
<p>foo</p>
<p>bar</p>
示例 178  (交互)
-    foo

  bar
<ul>
<li>foo</li>
</ul>
<p>bar</p>

这不是一个显著的限制,因为当一个块以 1-3 个空格缩进开头时,缩进总是可以移除而不改变解释,从而允许应用规则 #1。所以,在上述情况下

示例 179  (交互)
-  foo

   bar
<ul>
<li><p>foo</p>
<p>bar</p></li>
</ul>
  1. 缩进。 如果一系列行 Ls 根据规则 #1 或 #2 构成列表项,那么将 L 的每一行缩进 1-3 个空格(每行相同)的结果,也构成了具有相同内容和属性的列表项。如果某行是空的,则无需缩进。

缩进一个空格

示例 180  (交互)
 1.  A paragraph
     with two lines.

         indented code

     > A block quote.
<ol>
<li><p>A paragraph
with two lines.</p>
<pre><code>indented code
</code></pre>
<blockquote>
<p>A block quote.</p>
</blockquote></li>
</ol>

缩进两个空格

示例 181  (交互)
  1.  A paragraph
      with two lines.

          indented code

      > A block quote.
<ol>
<li><p>A paragraph
with two lines.</p>
<pre><code>indented code
</code></pre>
<blockquote>
<p>A block quote.</p>
</blockquote></li>
</ol>

缩进三个空格

示例 182  (交互)
   1.  A paragraph
       with two lines.

           indented code

       > A block quote.
<ol>
<li><p>A paragraph
with two lines.</p>
<pre><code>indented code
</code></pre>
<blockquote>
<p>A block quote.</p>
</blockquote></li>
</ol>

四个空格缩进产生一个代码块

示例 183  (交互)
    1.  A paragraph
        with two lines.

            indented code

        > A block quote.
<pre><code>1.  A paragraph
    with two lines.

        indented code

    &gt; A block quote.
</code></pre>
  1. 懒惰规则(Laziness)。 如果一串行 Ls 构成了内容为 Bs列表项,那么从一行或多行中删除部分或全部缩进(前提是缩进后的下一个非空格字符是 段落延续文本),其结果仍是一个具有相同内容和属性的列表项。

这是一个带有惰性延续行的示例

示例 184  (交互)
  1.  A paragraph
with two lines.

          indented code

      > A block quote.
<ol>
<li><p>A paragraph
with two lines.</p>
<pre><code>indented code
</code></pre>
<blockquote>
<p>A block quote.</p>
</blockquote></li>
</ol>

缩进可以被部分删除

示例 185  (交互)
  1.  A paragraph
    with two lines.
<ol>
<li>A paragraph
with two lines.</li>
</ol>

这些示例显示了惰性匹配如何在嵌套结构中工作

示例 186  (交互)
> 1. > Blockquote
continued here.
<blockquote>
<ol>
<li><blockquote>
<p>Blockquote
continued here.</p>
</blockquote></li>
</ol>
</blockquote>
示例 187  (交互)
> 1. > Blockquote
> continued here.
<blockquote>
<ol>
<li><blockquote>
<p>Blockquote
continued here.</p>
</blockquote></li>
</ol>
</blockquote>
  1. 仅此而已。 凡是不被规则 #1–4 计为列表项的内容,均不算作 列表项

子列表的规则遵循上述通用规则。子列表必须缩进与段落包含在列表项中所需的相同数量的空格。

因此,在这种情况下我们需要两个空格的缩进

示例 188  (交互)
- foo
  - bar
    - baz
<ul>
<li>foo
<ul>
<li>bar
<ul>
<li>baz</li>
</ul></li>
</ul></li>
</ul>

一个空格是不够的

示例 189  (交互)
- foo
 - bar
  - baz
<ul>
<li>foo</li>
<li>bar</li>
<li>baz</li>
</ul>

这里我们需要四个,因为列表标记更宽

示例 190  (交互)
10) foo
    - bar
<ol start="10">
<li>foo
<ul>
<li>bar</li>
</ul></li>
</ol>

三个空格是不够的

示例 191  (交互)
10) foo
   - bar
<ol start="10">
<li>foo</li>
</ol>
<ul>
<li>bar</li>
</ul>

列表可以是列表项中的第一个块

示例 192  (交互)
- - foo
<ul>
<li><ul>
<li>foo</li>
</ul></li>
</ul>
示例 193  (交互)
1. - 2. foo
<ol>
<li><ul>
<li><ol start="2">
<li>foo</li>
</ol></li>
</ul></li>
</ol>

列表项可以为空

示例 194  (交互)
- foo
-
- bar
<ul>
<li>foo</li>
<li></li>
<li>bar</li>
</ul>
示例 195  (交互)
-
<ul>
<li></li>
</ul>

列表项可以包含标题

示例 196  (交互)
- # Foo
- Bar
  ---
  baz
<ul>
<li><h1>Foo</h1></li>
<li><h2>Bar</h2>
<p>baz</p></li>
</ul>

5.2.1 设计动机

John Gruber 的 Markdown 规范中关于列表项的内容如下:

  1. “列表标记通常从左边距开始,但最多可以缩进三个空格。列表标记必须后跟一个或多个空格或一个制表符。”

  2. “为了让列表看起来美观,你可以用悬挂缩进包装项目……但如果你不想这样做,也没必要。”

  3. “列表项可以由多个段落组成。列表项中的每个后续段落必须缩进四个空格或一个制表符。”

  4. “缩进后续段落的每一行看起来很不错,但同样,Markdown 会允许你变得懒惰。”

  5. “要在列表项中放入引用块,引用块的 > 分隔符需要缩进。”

  6. “要在列表项中放入代码块,代码块需要缩进两次——8 个空格或两个制表符。”

这些规则指定列表项下的段落必须缩进四个空格(据推测是从左边距,而不是列表标记的开头,但这未说明),并且列表项下的代码必须缩进八个空格而不是通常的四个。它们还说引用块必须缩进,但没有说明缩进多少;然而,给出的示例有四个空格的缩进。虽然没有提到其他类型的块级内容,但推断列表项下的所有块元素(包括其他列表)都必须缩进四个空格当然是合理的。这一原则被称为四空格规则

四空格规则清晰且有原则,如果参考实现 Markdown.pl 遵循它,它可能会成为标准。然而,Markdown.pl 至少在外部层级上允许段落和子列表以仅两个空格的缩进开始。更糟糕的是,其行为不一致:外部列表的子列表需要两个空格缩进,但该子列表的子列表却需要三个空格。因此,Markdown 的不同实现为确定列表项下的内容开发了截然不同的规则并不奇怪。(例如,Pandoc 和 python-Markdown 坚持 Gruber 的语法描述和四空格规则,而 discount、redcarpet、marked、PHP Markdown 等则更紧密地遵循 Markdown.pl 的行为。)

不幸的是,考虑到实现之间的分歧,没有办法给出一个保证不会破坏现有文档的列表项规范。然而,此处给出的规范应该能正确处理使用四空格规则或更宽容的 Markdown.pl 行为格式化的列表,前提是它们的布局方式对于人类阅读来说是自然的。

这里的策略是让列表标记的宽度和缩进决定块归属于列表项所需的缩进,而不是设置一个固定且随意的数字。作者可以将列表项的主体视为一个整体,为了容纳列表标记(以及列表标记上的任何缩进),将其向右缩进足够的距离。(惰性规则 #4 随后允许延续行在需要时取消缩进。)

我们认为此规则优于任何要求从边距固定缩进级别的规则。四空格规则很清晰但不自然。以下内容:

- foo

  bar

  - baz

被解析为两个列表并伴随一个插入的段落,

<ul>
<li>foo</li>
</ul>
<p>bar</p>
<ul>
<li>baz</li>
</ul>

如四空格规则所要求的那样,而不是一个单一的列表,这非常不直观。

<ul>
<li><p>foo</p>
<p>bar</p>
<ul>
<li>baz</li>
</ul></li>
</ul>

四个空格的选择是任意的。它可以被学习,但不太可能被猜到,而且经常让初学者受挫。

采用双空格规则有帮助吗?问题在于,这样的规则,加上允许列表标记初始缩进 1-3 个空格的规则,允许缩进少于原始列表标记的文本包含在列表项中。例如,Markdown.pl 将:

   - one

  two

解析为单个列表项,其中 two 是延续段落

<ul>
<li><p>one</p>
<p>two</p></li>
</ul>

同样

>   - one
>
>  two

作为

<blockquote>
<ul>
<li><p>one</p>
<p>two</p></li>
</ul>
</blockquote>

这是极其不直观的。

我们不需要从边距进行固定缩进,而是可以要求从列表标记(其本身可能已缩进)进行固定缩进(比如两个空格,甚至一个空格)。该提案将消除上述最后一个异常。与上述规范不同,它会将以下内容视为带有子段落的列表项,即使段落 bar 的缩进程度没有第一段 foo 那么大:

 10. foo

   bar  

可以说这段文本读起来确实像一个列表项,而 bar 是一个子段落,这可能对该提案有利。然而,按照这个提案,缩进代码在列表标记后必须缩进六个空格。这将破坏许多现有的 Markdown,它们具有以下模式:

1.  foo

        indented code

其中代码缩进八个空格。相比之下,上述规范将按预期解析此文本,因为代码块的缩进是从 foo 的开头开始测量的。

唯一需要特殊处理的情况是缩进代码开头的列表项。在这种情况下需要多少缩进,因为我们没有“第一段”来测量?规则 #2 只是规定,在这种情况下,我们要求列表标记缩进一个空格(然后是缩进代码通常的四个空格)。在列表标记加上其初始缩进占用四个空格的情况下(一种常见情况),这将符合四空格规则,但在其他情况下则会分歧。

5.3 列表

列表 是一个或多个 同类型 列表项的序列。列表项之间可以用单个 空行 分隔,但两个空行会结束所有包含列表。

如果两个列表项以同类型的 列表标记 开头,则它们是 同类型 的。 如果两个列表标记满足以下条件,则它们是同类型的:(a) 它们是使用相同字符 (-, +, 或 *) 的无序列表标记,或 (b) 它们是使用相同分隔符 (.)) 的有序列表数字。

如果列表的组成列表项以 有序列表标记 开头,则该列表为 有序列表;如果以 无序列表标记 开头,则为 无序列表

有序列表起始编号 由其第一个列表项的数字决定。后续列表项的编号将被忽略。

如果列表的任一组成列表项被空行分隔,或者任一组成列表项直接包含两个中间有空行的块级元素,则该列表是 松散列表 否则该列表是 紧凑列表 (在 HTML 输出中的区别是:松散列表中的段落会被包裹在 <p> 标签中,而紧凑列表中的段落则不会。)

更改无序或有序列表分隔符会开始一个新的列表

示例 197  (交互)
- foo
- bar
+ baz
<ul>
<li>foo</li>
<li>bar</li>
</ul>
<ul>
<li>baz</li>
</ul>
示例 198  (交互)
1. foo
2. bar
3) baz
<ol>
<li>foo</li>
<li>bar</li>
</ol>
<ol start="3">
<li>baz</li>
</ol>

在 CommonMark 中,列表可以中断段落。也就是说,段落和随后的列表之间不需要空行

示例 199  (交互)
Foo
- bar
- baz
<p>Foo</p>
<ul>
<li>bar</li>
<li>baz</li>
</ul>

Markdown.pl 不允许这样做,因为它担心会在硬换行中触发带有数字的列表

示例 200  (交互)
The number of windows in my house is
14.  The number of doors is 6.
<p>The number of windows in my house is</p>
<ol start="14">
<li>The number of doors is 6.</li>
</ol>

奇怪的是,Markdown.pl 确实允许引用块中断段落,尽管同样的考虑可能适用。我们认为这两种情况应该同样处理。以下是允许列表中断段落的两个原因

首先,人们在没有空行的情况下开始列表是很自然的,这并不罕见

I need to buy
- new shoes
- a coat
- a plane ticket

其次,我们被一种

一致性原则 如果一段文本具有某种含义,当它被放入列表项时,它将继续保持相同的含义。

(实际上,列表项 的规范预设了这一点。) 该原则暗示,如果

  * I need to buy
    - new shoes
    - a coat
    - a plane ticket

是一个包含段落后跟嵌套子列表的列表项(正如所有 Markdown 实现所同意的那样,尽管由于列表是“紧凑的”,段落可能在渲染时没有 <p> 标签),那么

I need to buy
- new shoes
- a coat
- a plane ticket

它本身应该是一个段落后跟一个嵌套子列表。

我们对统一原则的坚持使我们倾向于认为有两种连贯的方案

  1. 所有列表和引用块之前要求空行,包括作为列表项内部子列表出现的列表。

  2. 在这些地方都不要求空行。

reStructuredText 采取了第一种方法,这很有道理。但第二种方法似乎与 Markdown 既定的实践更加一致。

项之间可以有空行,但两个空行结束列表

示例 201  (交互)
- foo

- bar


- baz
<ul>
<li><p>foo</p></li>
<li><p>bar</p></li>
</ul>
<ul>
<li>baz</li>
</ul>

正如上面关于 列表项 的章节中所述,列表项 内部 块之间的两个空行也会结束一个列表

示例 202  (交互)
- foo


  bar
- baz
<ul>
<li>foo</li>
</ul>
<p>bar</p>
<ul>
<li>baz</li>
</ul>

事实上,两个空行将结束所有包含的列表

示例 203  (交互)
- foo
  - bar
    - baz


      bim
<ul>
<li>foo
<ul>
<li>bar
<ul>
<li>baz</li>
</ul></li>
</ul></li>
</ul>
<pre><code>  bim
</code></pre>

因此,两个空行可用于分隔相同类型的连续列表,或将列表与本应被解析为最终列表项的子段落的缩进代码块分开

示例 204  (交互)
- foo
- bar


- baz
- bim
<ul>
<li>foo</li>
<li>bar</li>
</ul>
<ul>
<li>baz</li>
<li>bim</li>
</ul>
示例 205  (交互)
-   foo

    notcode

-   foo


    code
<ul>
<li><p>foo</p>
<p>notcode</p></li>
<li><p>foo</p></li>
</ul>
<pre><code>code
</code></pre>

列表项不需要缩进到同一级别。以下列表项将被视为同一列表级别的项目,因为没有一个缩进足够多而属于前一个列表项

示例 206  (交互)
- a
 - b
  - c
   - d
  - e
 - f
- g
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>e</li>
<li>f</li>
<li>g</li>
</ul>

这是一个松散列表,因为两个列表项之间有一个空行

示例 207  (交互)
- a
- b

- c
<ul>
<li><p>a</p></li>
<li><p>b</p></li>
<li><p>c</p></li>
</ul>

这也是,第二个项为空

示例 208  (交互)
* a
*

* c
<ul>
<li><p>a</p></li>
<li></li>
<li><p>c</p></li>
</ul>

这些是松散列表,即使项之间没有空格,因为其中一个项直接包含两个中间有空行的块级元素

示例 209  (交互)
- a
- b

  c
- d
<ul>
<li><p>a</p></li>
<li><p>b</p>
<p>c</p></li>
<li><p>d</p></li>
</ul>
示例 210  (交互)
- a
- b

  [ref]: /url
- d
<ul>
<li><p>a</p></li>
<li><p>b</p></li>
<li><p>d</p></li>
</ul>

这是一个紧凑列表,因为空行在代码块中

示例 211  (交互)
- a
- ```
  b


  ```
- c
<ul>
<li>a</li>
<li><pre><code>b


</code></pre></li>
<li>c</li>
</ul>

这是一个紧凑列表,因为空行位于子列表的两个段落之间。因此子列表是松散的,而外部列表是紧凑的

示例 212  (交互)
- a
  - b

    c
- d
<ul>
<li>a
<ul>
<li><p>b</p>
<p>c</p></li>
</ul></li>
<li>d</li>
</ul>

这个列表是紧凑的,因为空行在引用块内

示例 213  (交互)
* a
  > b
  >
* c
<ul>
<li>a
<blockquote>
<p>b</p>
</blockquote></li>
<li>c</li>
</ul>

这个列表是紧凑的,因为连续的块元素没有被空行分隔

示例 214  (交互)
- a
  > b
  ```
  c
  ```
- d
<ul>
<li>a
<blockquote>
<p>b</p>
</blockquote>
<pre><code>c
</code></pre></li>
<li>d</li>
</ul>

单段落列表是紧凑的

示例 215  (交互)
- a
<ul>
<li>a</li>
</ul>
示例 216  (交互)
- a
  - b
<ul>
<li>a
<ul>
<li>b</li>
</ul></li>
</ul>

这里外部列表是松散的,内部列表是紧凑的

示例 217  (交互)
* foo
  * bar

  baz
<ul>
<li><p>foo</p>
<ul>
<li>bar</li>
</ul>
<p>baz</p></li>
</ul>
示例 218  (交互)
- a
  - b
  - c

- d
  - e
  - f
<ul>
<li><p>a</p>
<ul>
<li>b</li>
<li>c</li>
</ul></li>
<li><p>d</p>
<ul>
<li>e</li>
<li>f</li>
</ul></li>
</ul>

6 行内元素

行内元素是从字符流的开头到结尾(从左到右,在从左到右的语言中)依次解析的。例如:

示例 219  (交互)
`hi`lo`
<p><code>hi</code>lo`</p>

hi 被解析为代码,末尾的反引号作为字面量反引号保留。

6.1 反斜杠转义

任何 ASCII 标点字符都可以使用反斜杠转义

示例 220  (交互)
\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~
<p>!&quot;#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^_`{|}~</p>

其他字符前的反斜杠被视为字面量反斜杠

示例 221  (交互)
\→\A\a\ \3\φ\«
<p>\   \A\a\ \3\φ\«</p>

转义字符被视为普通字符,不具有其通常的 Markdown 含义

示例 222  (交互)
\*not emphasized*
\<br/> not a tag
\[not a link](/foo)
\`not code`
1\. not a list
\* not a list
\# not a header
\[foo]: /url "not a reference"
<p>*not emphasized*
&lt;br/&gt; not a tag
[not a link](/foo)
`not code`
1. not a list
* not a list
# not a header
[foo]: /url &quot;not a reference&quot;</p>

如果反斜杠本身被转义,则随后的字符不被转义

示例 223  (交互)
\\*emphasis*
<p>\<em>emphasis</em></p>

行尾的反斜杠是 硬换行

示例 224  (交互)
foo\
bar
<p>foo<br />
bar</p>

反斜杠转义在代码块、代码片段、自动链接或原生 HTML 中不起作用

示例 225  (交互)
`` \[\` ``
<p><code>\[\`</code></p>
示例 226  (交互)
    \[\]
<pre><code>\[\]
</code></pre>
示例 227  (交互)
~~~
\[\]
~~~
<pre><code>\[\]
</code></pre>
示例 228  (交互)
<http://example.com?find=\*>
<p><a href="http://example.com?find=%5C*">http://example.com?find=\*</a></p>
示例 229  (交互)
<a href="/bar\/)">
<p><a href="/bar\/)"></p>

但它们在所有其他上下文中都有效,包括 URL 和链接标题、链接引用,以及 围栏代码块 中的信息字符串

示例 230  (交互)
[foo](/bar\* "ti\*tle")
<p><a href="/bar*" title="ti*tle">foo</a></p>
示例 231  (交互)
[foo]

[foo]: /bar\* "ti\*tle"
<p><a href="/bar*" title="ti*tle">foo</a></p>
示例 232  (交互)
``` foo\+bar
foo
```
<pre><code class="language-foo+bar">foo
</code></pre>

6.2 实体

为了使该标准尽可能与 HTML 无关,在任何上下文中的所有有效 HTML 实体都会被识别并转换为 Unicode 字符,然后再存储到 AST 中。

这使得针对 HTML 输出的实现可以在生成 HTML 时轻松地转义实体,并简化了针对其他语言的实现的编写工作,因为这些实现只需要处理 Unicode 字符,而无需感知 HTML 实体。

命名实体 & + 任意有效的 HTML5 实体名称 + ; 组成。以下文档 被用作有效实体名称及其对应码位的权威来源。

针对 HTML 的兼容实现不需要生成所有现有的有效命名实体,除了 " (&quot;)、& (&amp;)、< (&lt;) 和 > (&gt;),出于安全原因,这些实体始终必须以实体形式编写。

示例 233  (交互)
&nbsp; &amp; &copy; &AElig; &Dcaron; &frac34; &HilbertSpace; &DifferentialD; &ClockwiseContourIntegral;
<p>  &amp; © Æ Ď ¾ ℋ ⅆ ∲</p>

十进制实体 &# + 一串 1-8 位阿拉伯数字 + ; 组成。同样,这些实体需要被识别并转换为其对应的 UTF-8 码位。无效的 Unicode 码位将写入为“未知码位”字符 (0xFFFD)。

示例 234  (交互)
&#35; &#1234; &#992; &#98765432;
<p># Ӓ Ϡ �</p>

十六进制实体 &# + Xx + 一串 1-8 位十六进制数字 + ; 组成。它们也将被解析并在抽象语法树(AST)中转换为其对应的 UTF-8 值。

示例 235  (交互)
&#X22; &#XD06; &#xcab;
<p>&quot; ആ ಫ</p>

这里是一些非实体引用

示例 236  (交互)
&nbsp &x; &#; &#x; &ThisIsWayTooLongToBeAnEntityIsntIt; &hi?;
<p>&amp;nbsp &amp;x; &amp;#; &amp;#x; &amp;ThisIsWayTooLongToBeAnEntityIsntIt; &amp;hi?;</p>

尽管 HTML5 确实接受某些没有末尾分号的实体(如 &copy),但此处它们不被识别为实体,因为这会使语法变得过于模棱两可

示例 237  (交互)
&copy
<p>&amp;copy</p>

不在 HTML5 命名实体列表中的字符串也不会被识别为实体

示例 238  (交互)
&MadeUpEntity;
<p>&amp;MadeUpEntity;</p>

实体在代码片段或代码块之外的任何上下文中均被识别,包括原生 HTML、URL、链接标题围栏代码块 的信息字符串

示例 239  (交互)
<a href="&ouml;&ouml;.html">
<p><a href="&ouml;&ouml;.html"></p>
示例 240  (交互)
[foo](/f&ouml;&ouml; "f&ouml;&ouml;")
<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
示例 241  (交互)
[foo]

[foo]: /f&ouml;&ouml; "f&ouml;&ouml;"
<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
示例 242  (交互)
``` f&ouml;&ouml;
foo
```
<pre><code class="language-föö">foo
</code></pre>

实体在代码 span 和代码块中被视为字面文本

示例 243  (交互)
`f&ouml;&ouml;`
<p><code>f&amp;ouml;&amp;ouml;</code></p>
示例 244  (交互)
    f&ouml;f&ouml;
<pre><code>f&amp;ouml;f&amp;ouml;
</code></pre>

6.3 代码片段

反引号字符串 是一个或多个反引号 (`) 组成的字符串,其前后均无反引号。

代码段以反引号字符串开始,并以等长的反引号字符串结束。代码段的内容是两个反引号字符串之间的字符,剔除首尾的空格和换行符,并将连续的空格和换行符压缩为单个空格。

这是一个简单的代码跨度

示例 245  (交互)
`foo`
<p><code>foo</code></p>

这里使用了两个反引号,因为代码中包含一个反引号。此示例还演示了如何去除前导和尾随空格。

示例 246  (交互)
`` foo ` bar  ``
<p><code>foo ` bar</code></p>

此示例展示了去除前导和尾随空格的原因。

示例 247  (交互)
` `` `
<p><code>``</code></p>

换行符被视为与空格相同

示例 248  (交互)
``
foo
``
<p><code>foo</code></p>

内部的空格和换行符被压缩为单个空格,就像浏览器所做的那样

示例 249  (交互)
`foo   bar
  baz`
<p><code>foo bar baz</code></p>

问:既然浏览器无论如何都会折叠空格,为什么不直接保留它们呢?答:因为我们可能需要面向非 HTML 格式,我们不应依赖特定于 HTML 的渲染假设。

(现有的实现对内部空格和换行符的处理方式各不相同。包括 Markdown.plshowdown 在内的一些实现会将内部换行符转换为 <br /> 标签。但这给那些喜欢硬换行段落的人带来了困难,因为代码片段中间的换行会导致输出中出现意想不到的换行。其他实现则只是按原样保留内部空格,如果目标仅是 HTML,这没有问题。)

示例 250  (交互)
`foo `` bar`
<p><code>foo `` bar</code></p>

请注意,反斜杠转义在代码跨度中不起作用。所有反斜杠均被视为字面字符。

示例 251  (交互)
`foo\`bar`
<p><code>foo\</code>bar`</p>

反斜杠转义永远是不需要的,因为人们总是可以选择包含 n 个反引号字符的字符串作为定界符,而代码本身不包含任何恰好为 n 个反引号的字符串。

代码跨度的反引号优先级高于除了 HTML 标签和自动链接之外的任何行内结构。因此,例如,这不会被解析为强调文本,因为第二个 * 是代码跨度的一部分。

示例 252  (交互)
*foo`*`
<p>*foo<code>*</code></p>

且这也不会被解析为链接。

示例 253  (交互)
[not a `link](/foo`)
<p>[not a <code>link](/foo</code>)</p>

但这是一个链接

示例 254  (交互)
<http://foo.bar.`baz>`
<p><a href="http://foo.bar.%60baz">http://foo.bar.`baz</a>`</p>

这是一个 HTML 标签

示例 255  (交互)
<a href="`">`
<p><a href="`">`</p>

当反引号字符串没有匹配的反引号字符串闭合时,我们得到的只是字面意义上的反引号。

示例 256  (交互)
```foo``
<p>```foo``</p>
示例 257  (交互)
`foo
<p>`foo</p>

6.4 强调与加粗强调

John Gruber 原版的 Markdown 语法描述 说道:

Markdown 将星号(*)和下划线(_)视为强调的指示符。被单个 *_ 包围的文本将被 HTML <em> 标签包裹;双星号或双下划线将被 HTML <strong> 标签包裹。

这对于大多数用户来说足够了,但这些规则在处理嵌套强调时留下了许多不确定性。原版 Markdown.pl 测试套件清楚地表明,三重 ***___ 定界符可以用于强强调,并且大多数实现也都允许以下模式。

***strong emph***
***strong** in emph*
***emph* in strong**
**in strong *emph***
*in emph **strong***

以下模式支持度较低,但意图明确且很有用(特别是在参考文献条目等上下文中)。

*emph *with emph* in it*
**strong **with strong** in it**

许多实现还限制了词内强调仅能使用 * 形式,以避免在包含内部下划线的单词中产生不必要的强调。(最好将其放在代码跨度中,但用户往往不会这样做。)

internal emphasis: foo*bar*baz
no emphasis: foo_bar_baz

以下规则捕获了所有这些模式,同时允许不进行回溯的高效解析策略

  1. 单个 * 字符 可以开启强调 当且仅当:

    1. 它不是四个或更多未转义 * 序列的一部分,
    2. 它后面没有空白字符,并且
    3. 它要么后面没有 * 字符,要么后面紧跟强调或加粗强调。
  2. 单个 _ 字符 可以开启强调 当且仅当:

    1. 它不是四个或更多未转义 _ 序列的一部分,
    2. 它后面没有空白字符,
    3. 它前面没有 ASCII 字母数字字符,并且
    4. 它要么后面没有 _ 字符,要么后面紧跟强调或加粗强调。
  3. 单个 * 字符 可以关闭强调 当且仅当:

    1. 它不是四个或更多未转义 * 序列的一部分,并且
    2. 它前面没有空白字符。
  4. 单个 _ 字符 可以关闭强调 当且仅当:

    1. 它不是四个或更多未转义 _ 序列的一部分,
    2. 它前面没有空白字符,并且
    3. 它后面没有 ASCII 字母数字字符。
  5. ** 可以开启加粗强调 当且仅当:

    1. 它不是四个或更多未转义 * 序列的一部分,
    2. 它后面没有空白字符,并且
    3. 它要么后面没有 * 字符,要么后面紧跟强调。
  6. __ 可以开启加粗强调 当且仅当:

    1. 它不是四个或更多未转义 _ 序列的一部分,
    2. 它后面没有空白字符,并且
    3. 它前面没有 ASCII 字母数字字符,并且
    4. 它要么后面没有 _ 字符,要么后面紧跟强调。
  7. ** 可以关闭加粗强调 当且仅当:

    1. 它不是四个或更多未转义 * 序列的一部分,并且
    2. 它前面没有空白字符。
  8. __ 可以关闭加粗强调 当且仅当:

    1. 它不是四个或更多未转义 _ 序列的一部分,
    2. 它前面没有空白字符,并且
    3. 它后面没有 ASCII 字母数字字符。
  9. 强调以一个 可以开启强调 的分隔符开始,并以一个 可以关闭强调 的分隔符结束,且使用与开启分隔符相同的字符 (_*)。开启分隔符和关闭分隔符之间的行内元素即为强调行内内容。

  10. 加粗强调以一个 可以开启加粗强调 的分隔符开始,并以一个 可以关闭加粗强调 的分隔符结束,且使用与开启分隔符相同的字符 (_*)。开启分隔符和关闭分隔符之间的行内元素即为加粗强调行内内容。

当上述 1-10 条规则与多种解析方式兼容时,以下原则用于解决歧义:

  1. 解析 <strong>...</strong> 总是优于 <em><em>...</em></em>

  2. 解释为 <strong><em>...</em></strong> 总是优先于 <em><strong>..</strong></em>

  3. 较早的闭合优先于较晚的闭合。因此,当两个潜在的强调(emphasis)或强强调(strong emphasis)范围重叠时,前者优先:例如,*foo _bar* baz_ 被解析为 <em>foo _bar</em> baz_ 而不是 *foo <em>bar* baz</em>。出于同样的原因,**foo*bar** 被解析为 <em><em>foo</em>bar</em>* 而不是 <strong>foo*bar</strong>

  4. 行内代码跨度、链接、图像和 HTML 标签的结合比强调更紧密。因此,当在包含这些元素与不包含这些元素的解释之间进行选择时,前者总是胜出。因此,例如,*[foo*](bar) 被解析为 *<a href="bar">foo*</a> 而不是 <em>[foo</em>](bar)

这些规则可以通过一系列示例来说明。

简单强调

示例 258  (交互)
*foo bar*
<p><em>foo bar</em></p>
示例 259  (交互)
_foo bar_
<p><em>foo bar</em></p>

简单加粗强调

示例 260  (交互)
**foo bar**
<p><strong>foo bar</strong></p>
示例 261  (交互)
__foo bar__
<p><strong>foo bar</strong></p>

强调可以跨越换行符

示例 262  (交互)
*foo
bar*
<p><em>foo
bar</em></p>
示例 263  (交互)
_foo
bar_
<p><em>foo
bar</em></p>
示例 264  (交互)
**foo
bar**
<p><strong>foo
bar</strong></p>
示例 265  (交互)
__foo
bar__
<p><strong>foo
bar</strong></p>

强调可以包含其他行内结构

示例 266  (交互)
*foo [bar](/url)*
<p><em>foo <a href="/url">bar</a></em></p>
示例 267  (交互)
_foo [bar](/url)_
<p><em>foo <a href="/url">bar</a></em></p>
示例 268  (交互)
**foo [bar](/url)**
<p><strong>foo <a href="/url">bar</a></strong></p>
示例 269  (交互)
__foo [bar](/url)__
<p><strong>foo <a href="/url">bar</a></strong></p>

包含在其他行内结构中的符号不会关闭强调

示例 270  (交互)
*foo [bar*](/url)
<p>*foo <a href="/url">bar*</a></p>
示例 271  (交互)
_foo [bar_](/url)
<p>_foo <a href="/url">bar_</a></p>
示例 272  (交互)
**<a href="**">
<p>**<a href="**"></p>
示例 273  (交互)
__<a href="__">
<p>__<a href="__"></p>
示例 274  (交互)
*a `*`*
<p><em>a <code>*</code></em></p>
示例 275  (交互)
_a `_`_
<p><em>a <code>_</code></em></p>
示例 276  (交互)
**a<http://foo.bar?q=**>
<p>**a<a href="http://foo.bar?q=**">http://foo.bar?q=**</a></p>
示例 277  (交互)
__a<http://foo.bar?q=__>
<p>__a<a href="http://foo.bar?q=__">http://foo.bar?q=__</a></p>

这不是强调,因为开启分隔符后有空白字符

示例 278  (交互)
and * foo bar*
<p>and * foo bar*</p>
示例 279  (交互)
_ foo bar_
<p>_ foo bar_</p>
示例 280  (交互)
and ** foo bar**
<p>and ** foo bar**</p>
示例 281  (交互)
__ foo bar__
<p>__ foo bar__</p>

这不是强调,因为关闭分隔符前有空白字符

示例 282  (交互)
and *foo bar *
<p>and *foo bar *</p>
示例 283  (交互)
and _foo bar _
<p>and _foo bar _</p>
示例 284  (交互)
and **foo bar **
<p>and **foo bar **</p>
示例 285  (交互)
and __foo bar __
<p>and __foo bar __</p>

这些规则暗示四个或更多未转义的 *_ 字符序列总是会被解析为字面字符串

示例 286  (交互)
****hi****
<p>****hi****</p>
示例 287  (交互)
_____hi_____
<p>_____hi_____</p>
示例 288  (交互)
Sign here: _________
<p>Sign here: _________</p>

这些规则也暗示不存在空的强调或加粗强调

示例 289  (交互)
** is not an empty emphasis
<p>** is not an empty emphasis</p>
示例 290  (交互)
**** is not an empty strong emphasis
<p>**** is not an empty strong emphasis</p>

要在强调部分包含 *_,请使用反斜杠转义或代码段

示例 291  (交互)
*here is a \**
<p><em>here is a *</em></p>
示例 292  (交互)
__this is a double underscore (`__`)__
<p><strong>this is a double underscore (<code>__</code>)</strong></p>

或者使用另一种强调字符

示例 293  (交互)
*_*
<p><em>_</em></p>
示例 294  (交互)
_*_
<p><em>*</em></p>
示例 295  (交互)
*__*
<p><em>__</em></p>
示例 296  (交互)
_**_
<p><em>**</em></p>

* 分隔符允许单词内强调;_ 分隔符则不允许

示例 297  (交互)
foo*bar*baz
<p>foo<em>bar</em>baz</p>
示例 298  (交互)
foo_bar_baz
<p>foo_bar_baz</p>
示例 299  (交互)
foo__bar__baz
<p>foo__bar__baz</p>
示例 300  (交互)
_foo_bar_baz_
<p><em>foo_bar_baz</em></p>
示例 301  (交互)
11*15*32
<p>11<em>15</em>32</p>
示例 302  (交互)
11_15_32
<p>11_15_32</p>

内部下划线在下划线分隔的强调中会被忽略

示例 303  (交互)
_foo_bar_baz_
<p><em>foo_bar_baz</em></p>
示例 304  (交互)
__foo__bar__baz__
<p><strong>foo__bar__baz</strong></p>

这些规则足以处理以下嵌套模式

示例 305  (交互)
***foo bar***
<p><strong><em>foo bar</em></strong></p>
示例 306  (交互)
___foo bar___
<p><strong><em>foo bar</em></strong></p>
示例 307  (交互)
***foo** bar*
<p><em><strong>foo</strong> bar</em></p>
示例 308  (交互)
___foo__ bar_
<p><em><strong>foo</strong> bar</em></p>
示例 309  (交互)
***foo* bar**
<p><strong><em>foo</em> bar</strong></p>
示例 310  (交互)
___foo_ bar__
<p><strong><em>foo</em> bar</strong></p>
示例 311  (交互)
*foo **bar***
<p><em>foo <strong>bar</strong></em></p>
示例 312  (交互)
_foo __bar___
<p><em>foo <strong>bar</strong></em></p>
示例 313  (交互)
**foo *bar***
<p><strong>foo <em>bar</em></strong></p>
示例 314  (交互)
__foo _bar___
<p><strong>foo <em>bar</em></strong></p>
示例 315  (交互)
*foo **bar***
<p><em>foo <strong>bar</strong></em></p>
示例 316  (交互)
_foo __bar___
<p><em>foo <strong>bar</strong></em></p>
示例 317  (交互)
*foo *bar* baz*
<p><em>foo <em>bar</em> baz</em></p>
示例 318  (交互)
_foo _bar_ baz_
<p><em>foo <em>bar</em> baz</em></p>
示例 319  (交互)
**foo **bar** baz**
<p><strong>foo <strong>bar</strong> baz</strong></p>
示例 320  (交互)
__foo __bar__ baz__
<p><strong>foo <strong>bar</strong> baz</strong></p>
示例 321  (交互)
*foo **bar** baz*
<p><em>foo <strong>bar</strong> baz</em></p>
示例 322  (交互)
_foo __bar__ baz_
<p><em>foo <strong>bar</strong> baz</em></p>
示例 323  (交互)
**foo *bar* baz**
<p><strong>foo <em>bar</em> baz</strong></p>
示例 324  (交互)
__foo _bar_ baz__
<p><strong>foo <em>bar</em> baz</strong></p>
示例 325  (交互)
**foo, *bar*, baz**
<p><strong>foo, <em>bar</em>, baz</strong></p>
示例 326  (交互)
__foo, _bar_, baz__
<p><strong>foo, <em>bar</em>, baz</strong></p>

但请注意:

示例 327  (交互)
*foo**bar**baz*
<p><em>foo</em><em>bar</em><em>baz</em></p>
示例 328  (交互)
**foo*bar*baz**
<p><em><em>foo</em>bar</em>baz**</p>

区别在于,在前面的两种情况下,内部分隔符 可以关闭强调,而在有空格的情况下,它们则不能。

请注意,你不能使用相同的分隔符在强调内直接嵌套强调,或者在加粗强调内直接嵌套加粗强调

示例 329  (交互)
**foo**
<p><strong>foo</strong></p>
示例 330  (交互)
****foo****
<p>****foo****</p>

对于这些嵌套,你需要切换分隔符

示例 331  (交互)
*_foo_*
<p><em><em>foo</em></em></p>
示例 332  (交互)
**__foo__**
<p><strong><strong>foo</strong></strong></p>

请注意,* 后跟 * 可以关闭强调,** 后跟 * 可以关闭加粗强调(___ 同理)

示例 333  (交互)
*foo**
<p><em>foo</em>*</p>
示例 334  (交互)
*foo *bar**
<p><em>foo <em>bar</em></em></p>
示例 335  (交互)
**foo***
<p><strong>foo</strong>*</p>
示例 336  (交互)
***foo* bar***
<p><strong><em>foo</em> bar</strong>*</p>
示例 337  (交互)
***foo** bar***
<p><em><strong>foo</strong> bar</em>**</p>

以下内容不包含加粗强调,因为开启分隔符在 bar 之前的第一个 * 处就被关闭了

示例 338  (交互)
*foo**bar***
<p><em>foo</em><em>bar</em>**</p>

然而,四个或更多 **** 的字符串永远无法关闭强调

示例 339  (交互)
*foo****
<p>*foo****</p>

在这些情况下我们保持对称性

示例 340  (交互)
*foo**

**foo*
<p><em>foo</em>*</p>
<p>*<em>foo</em></p>
示例 341  (交互)
*foo *bar**

**foo* bar*
<p><em>foo <em>bar</em></em></p>
<p><em><em>foo</em> bar</em></p>

更多分隔符不匹配的情况

示例 342  (交互)
*bar***
<p><em>bar</em>**</p>
示例 343  (交互)
***foo*
<p>**<em>foo</em></p>
示例 344  (交互)
**bar***
<p><strong>bar</strong>*</p>
示例 345  (交互)
***foo**
<p>*<strong>foo</strong></p>
示例 346  (交互)
***foo *bar*
<p>***foo <em>bar</em></p>

以下案例说明了第 13 条规则

示例 347  (交互)
*foo _bar* baz_
<p><em>foo _bar</em> baz_</p>
示例 348  (交互)
**foo bar* baz**
<p><em><em>foo bar</em> baz</em>*</p>

以下案例说明了第 14 条规则

示例 349  (交互)
*[foo*](bar)
<p>*<a href="bar">foo*</a></p>
示例 350  (交互)
*![foo*](bar)
<p>*<img src="bar" alt="foo*" /></p>
示例 351  (交互)
*<img src="foo" title="*"/>
<p>*<img src="foo" title="*"/></p>
示例 352  (交互)
*a`a*`
<p>*a<code>a*</code></p>

链接包含一个 链接标签(可见文本)、一个 目标(作为链接目标的 URI),以及一个可选的 链接标题。Markdown 中有两种基本的链接。在 行内链接 中,目标和标题紧跟在标签之后给出。在 引用链接 中,目标和标题在文档的其他地方定义。

一个 链接标签 由以下部分组成:

这些规则由以下直观想法推动:

一个 链接目标 由以下之一组成:

一个 链接标题 由以下之一组成:

一个 行内链接 由一个紧跟左圆括号 (链接标签、可选的空白字符、一个可选的 链接目标、一个可选的用空格与链接目标分隔的 链接标题、可选的空白字符和一个右圆括号 ) 组成。链接的文本由作为行内元素解析的标签(不包括包围的方括号)组成。链接的 URI 由链接目标组成,剔除(如果存在)包围的 <...>,并应用上述的反斜杠转义。链接的标题由链接标题组成,剔除其包围的分隔符,并应用上述的反斜杠转义。

这是一个简单的行内链接:

示例 353  (交互)
[link](/uri "title")
<p><a href="/uri" title="title">link</a></p>

标题可以省略

示例 354  (交互)
[link](/uri)
<p><a href="/uri">link</a></p>

标题和目标均可省略。

示例 355  (交互)
[link]()
<p><a href="">link</a></p>
示例 356  (交互)
[link](<>)
<p><a href="">link</a></p>

如果目标包含空格,必须将其括在尖括号中。

示例 357  (交互)
[link](/my uri)
<p>[link](/my uri)</p>
示例 358  (交互)
[link](</my uri>)
<p><a href="/my%20uri">link</a></p>

目标不能包含换行符,即使使用尖括号也是如此。

示例 359  (交互)
[link](foo
bar)
<p>[link](foo
bar)</p>

在不进行转义的情况下,允许使用一层平衡的圆括号。

示例 360  (交互)
[link]((foo)and(bar))
<p><a href="(foo)and(bar)">link</a></p>

但是,如果圆括号内有圆括号,则需要进行转义或使用 <...> 形式。

示例 361  (交互)
[link](foo(and(bar)))
<p>[link](foo(and(bar)))</p>
示例 362  (交互)
[link](foo(and\(bar\)))
<p><a href="foo(and(bar))">link</a></p>
示例 363  (交互)
[link](<foo(and(bar))>)
<p><a href="foo(and(bar))">link</a></p>

圆括号和其他符号也可以按照 Markdown 中的惯例进行转义。

示例 364  (交互)
[link](foo\)\:)
<p><a href="foo):">link</a></p>

URL 转义在目标内部应保持原样,因为所有 URL 转义字符也是有效的 URL 字符。目标中的 HTML 实体将像往常一样解析为它们的 UTF-8 码位,并在写入 HTML 时可选地进行 URL 转义。

示例 365  (交互)
[link](foo%20b&auml;)
<p><a href="foo%20b%C3%A4">link</a></p>

请注意,由于标题通常可以被解析为目标,如果您尝试省略目标并保留标题,则会得到意外结果。

示例 366  (交互)
[link]("title")
<p><a href="%22title%22">link</a></p>

标题可以使用单引号、双引号或圆括号。

示例 367  (交互)
[link](/url "title")
[link](/url 'title')
[link](/url (title))
<p><a href="/url" title="title">link</a>
<a href="/url" title="title">link</a>
<a href="/url" title="title">link</a></p>

反斜杠转义和实体可以在标题中使用

示例 368  (交互)
[link](/url "title \"&quot;")
<p><a href="/url" title="title &quot;&quot;">link</a></p>

除非经过转义,否则不允许嵌套平衡的引号。

示例 369  (交互)
[link](/url "title "and" title")
<p>[link](/url &quot;title &quot;and&quot; title&quot;)</p>

但可以通过使用不同的引号类型轻松解决此问题。

示例 370  (交互)
[link](/url 'title "and" title')
<p><a href="/url" title="title &quot;and&quot; title">link</a></p>

(注:Markdown.pl 确实允许在双引号标题中使用双引号,其测试套件包含一个证明此点的测试。但很难看出这种额外复杂性带来的合理性,因为已经有多种方式——反斜杠转义、实体或为封闭标题使用不同的引号类型——来编写包含双引号的标题。Markdown.pl 对标题的处理还有许多其他奇怪的特性。例如,它允许在行内链接中使用单引号标题,但不支持引用链接。而且,在引用链接中,它允许标题以 " 开始并以 ) 结束,这在行内链接中是不允许的。Markdown.pl 1.0.1 甚至允许没有结束引号的标题,尽管 1.0.2b8 不允许。采用一个简单、合理的规则,在行内链接和链接引用定义中以同样方式工作,显然更为可取。)

目标和标题周围允许有空白

示例 371  (交互)
[link](   /uri
  "title"  )
<p><a href="/uri" title="title">link</a></p>

但它不允许出现在链接标签和随后的括号之间

示例 372  (交互)
[link] (/uri)
<p>[link] (/uri)</p>

请注意,这不是一个链接,因为结束的 ] 出现在 HTML 标签中

示例 373  (交互)
[foo <bar attr="](baz)">
<p>[foo <bar attr="](baz)"></p>

有三种 引用链接

一个 完整引用链接 由一个 链接标签、可选的空白字符,以及另一个 匹配 文档其他地方的 链接引用定义链接标签 组成。

如果两个标签的规范化形式相等,则一个标签 匹配 另一个。要规范化标签,执行 Unicode 大小写折叠 并将连续的内部空格压缩为单个空格。如果存在多个匹配的引用链接定义,则使用文档中出现的第一个定义。(在这种情况下,发出警告是可取的。)

第一个链接标签的内容被解析为行内元素,用作链接的文本。链接的 URI 和标题由匹配的 链接引用定义 提供。

这是一个简单的例子

示例 374  (交互)
[foo][bar]

[bar]: /url "title"
<p><a href="/url" title="title">foo</a></p>

第一个标签可以包含行内内容

示例 375  (交互)
[*foo\!*][bar]

[bar]: /url "title"
<p><a href="/url" title="title"><em>foo!</em></a></p>

匹配时大小写不敏感。

示例 376  (交互)
[foo][BaR]

[bar]: /url "title"
<p><a href="/url" title="title">foo</a></p>

使用 Unicode 大小写折叠。

示例 377  (交互)
[Толпой][Толпой] is a Russian word.

[ТОЛПОЙ]: /url
<p><a href="/url">Толпой</a> is a Russian word.</p>

为了确定匹配,连续的内部空白被视为一个空格

示例 378  (交互)
[Foo
  bar]: /url

[Baz][Foo bar]
<p><a href="/url">Baz</a></p>

两个标签之间可以有空格

示例 379  (交互)
[foo] [bar]

[bar]: /url "title"
<p><a href="/url" title="title">foo</a></p>
示例 380  (交互)
[foo]
[bar]

[bar]: /url "title"
<p><a href="/url" title="title">foo</a></p>

当存在多个匹配的 链接引用定义 时,使用第一个。

示例 381  (交互)
[foo]: /url1

[foo]: /url2

[bar][foo]
<p><a href="/url1">bar</a></p>

请注意,匹配是在规范化字符串上执行的,而不是在解析的行内内容上。因此,以下内容不匹配,即使标签定义了等效的行内内容。

示例 382  (交互)
[bar][foo\!]

[foo!]: /url
<p>[bar][foo!]</p>

一个 折叠引用链接 由一个 匹配 文档其他地方的 链接引用定义链接标签、可选的空白字符和字符串 [] 组成。第一个链接标签的内容被解析为行内元素,并用作链接文本。链接的 URI 和标题由匹配的链接引用定义提供。因此,[foo][] 等同于 [foo][foo]

示例 383  (交互)
[foo][]

[foo]: /url "title"
<p><a href="/url" title="title">foo</a></p>
示例 384  (交互)
[*foo* bar][]

[*foo* bar]: /url "title"
<p><a href="/url" title="title"><em>foo</em> bar</a></p>

链接标签不区分大小写。

示例 385  (交互)
[Foo][]

[foo]: /url "title"
<p><a href="/url" title="title">Foo</a></p>

与完整引用链接一样,两组方括号之间允许有空白

示例 386  (交互)
[foo] 
[]

[foo]: /url "title"
<p><a href="/url" title="title">foo</a></p>

一个 快捷引用链接 由一个 匹配 文档其他地方的 链接引用定义 且后面不跟 [] 或其他链接标签的 链接标签 组成。第一个链接标签的内容被解析为行内元素,并用作链接文本。链接的 URI 和标题由匹配的链接引用定义提供。因此,[foo] 等同于 [foo][]

示例 387  (交互)
[foo]

[foo]: /url "title"
<p><a href="/url" title="title">foo</a></p>
示例 388  (交互)
[*foo* bar]

[*foo* bar]: /url "title"
<p><a href="/url" title="title"><em>foo</em> bar</a></p>
示例 389  (交互)
[[*foo* bar]]

[*foo* bar]: /url "title"
<p>[<a href="/url" title="title"><em>foo</em> bar</a>]</p>

链接标签不区分大小写。

示例 390  (交互)
[Foo]

[foo]: /url "title"
<p><a href="/url" title="title">Foo</a></p>

如果您只想使用方括号文本,可以对左方括号进行反斜杠转义以避免链接。

示例 391  (交互)
\[foo]

[foo]: /url "title"
<p>[foo]</p>

请注意这是一个链接,因为链接标签的绑定比强调更紧

示例 392  (交互)
[foo*]: /url

*[foo*]
<p>*<a href="/url">foo*</a></p>

然而这不是,因为链接标签的绑定比代码反引号更松

示例 393  (交互)
[foo`]: /url

[foo`]`
<p>[foo<code>]</code></p>

链接标签可以包含匹配的方括号

示例 394  (交互)
[[[foo]]]

[[[foo]]]: /url
<p><a href="/url">[[foo]]</a></p>
示例 395  (交互)
[[[foo]]]

[[[foo]]]: /url1
[foo]: /url2
<p><a href="/url1">[[foo]]</a></p>

对于不匹配的括号,请使用反斜杠转义

示例 396  (交互)
[\[foo]

[\[foo]: /url
<p><a href="/url">[foo</a></p>

完整引用优先于快捷引用。

示例 397  (交互)
[foo][bar]

[foo]: /url1
[bar]: /url2
<p><a href="/url2">foo</a></p>

在以下情况中,[bar][baz] 被解析为引用,[foo] 被解析为普通文本。

示例 398  (交互)
[foo][bar][baz]

[baz]: /url
<p>[foo]<a href="/url">bar</a></p>

然而在这里,[foo][bar] 被解析为引用,因为定义了 [bar]

示例 399  (交互)
[foo][bar][baz]

[baz]: /url1
[bar]: /url2
<p><a href="/url2">foo</a><a href="/url1">baz</a></p>

在这里 [foo] 没有被解析为快捷引用,因为它后面紧跟一个链接标签(即使 [bar] 没有定义)。

示例 400  (交互)
[foo][bar][baz]

[baz]: /url1
[foo]: /url2
<p>[foo]<a href="/url1">bar</a></p>

6.6 图像

一个(未转义的)感叹号 (!) 后跟一个引用链接或行内链接将被解析为图片。链接标签将用作图片的替代文本(alt text),如果有链接标题,将用作图片的标题。

示例 401  (交互)
![foo](/url "title")
<p><img src="/url" alt="foo" title="title" /></p>
示例 402  (交互)
![foo *bar*]

[foo *bar*]: train.jpg "train & tracks"
<p><img src="train.jpg" alt="foo &lt;em&gt;bar&lt;/em&gt;" title="train &amp; tracks" /></p>
示例 403  (交互)
![foo *bar*][]

[foo *bar*]: train.jpg "train & tracks"
<p><img src="train.jpg" alt="foo &lt;em&gt;bar&lt;/em&gt;" title="train &amp; tracks" /></p>
示例 404  (交互)
![foo *bar*][foobar]

[FOOBAR]: train.jpg "train & tracks"
<p><img src="train.jpg" alt="foo &lt;em&gt;bar&lt;/em&gt;" title="train &amp; tracks" /></p>
示例 405  (交互)
![foo](train.jpg)
<p><img src="train.jpg" alt="foo" /></p>
示例 406  (交互)
My ![foo bar](/path/to/train.jpg  "title"   )
<p>My <img src="/path/to/train.jpg" alt="foo bar" title="title" /></p>
示例 407  (交互)
![foo](<url>)
<p><img src="url" alt="foo" /></p>
示例 408  (交互)
![](/url)
<p><img src="/url" alt="" /></p>

引用式:

示例 409  (交互)
![foo] [bar]

[bar]: /url
<p><img src="/url" alt="foo" /></p>
示例 410  (交互)
![foo] [bar]

[BAR]: /url
<p><img src="/url" alt="foo" /></p>

折叠式:

示例 411  (交互)
![foo][]

[foo]: /url "title"
<p><img src="/url" alt="foo" title="title" /></p>
示例 412  (交互)
![*foo* bar][]

[*foo* bar]: /url "title"
<p><img src="/url" alt="&lt;em&gt;foo&lt;/em&gt; bar" title="title" /></p>

标签不区分大小写。

示例 413  (交互)
![Foo][]

[foo]: /url "title"
<p><img src="/url" alt="Foo" title="title" /></p>

与完整引用链接一样,两组方括号之间允许有空白

示例 414  (交互)
![foo] 
[]

[foo]: /url "title"
<p><img src="/url" alt="foo" title="title" /></p>

快捷式:

示例 415  (交互)
![foo]

[foo]: /url "title"
<p><img src="/url" alt="foo" title="title" /></p>
示例 416  (交互)
![*foo* bar]

[*foo* bar]: /url "title"
<p><img src="/url" alt="&lt;em&gt;foo&lt;/em&gt; bar" title="title" /></p>
示例 417  (交互)
![[foo]]

[[foo]]: /url "title"
<p><img src="/url" alt="[foo]" title="title" /></p>

链接标签不区分大小写。

示例 418  (交互)
![Foo]

[foo]: /url "title"
<p><img src="/url" alt="Foo" title="title" /></p>

如果您只想使用方括号文本,可以对开启的 ![ 进行反斜杠转义。

示例 419  (交互)
\!\[foo]

[foo]: /url "title"
<p>![foo]</p>

如果您想在字面意义上的 ! 之后使用链接,请对 ! 进行反斜杠转义。

示例 420  (交互)
\![foo]

[foo]: /url "title"
<p>!<a href="/url" title="title">foo</a></p>

自动链接是位于 <> 之间的绝对 URI 和电子邮件地址。它们被解析为链接,URL 或电子邮件地址即为链接标签。

一个 URI 自动链接 <、后跟一个不包含 <绝对 URI、再后跟 > 组成。它被解析为指向该 URI 的链接,并以 URI 本身作为链接标签。

一个 绝对 URI 在此处指代一个 协议(scheme),后跟一个冒号 (:),再后跟零个或多个非 ASCII 空白字符、控制字符、<> 的字符。如果 URI 包含这些字符,你必须使用百分号编码(例如,空格使用 %20)。

以下 方案 是被认可的(不区分大小写):coap, doi, javascript, aaa, aaas, about, acap, cap, cid, crid, data, dav, dict, dns, file, ftp, geo, go, gopher, h323, http, https, iax, icap, im, imap, info, ipp, iris, iris.beep, iris.xpc, iris.xpcs, iris.lwz, ldap, mailto, mid, msrp, msrps, mtqp, mupdate, news, nfs, ni, nih, nntp, opaquelocktoken, pop, pres, rtsp, service, session, shttp, sieve, sip, sips, sms, snmp,soap.beep, soap.beeps, tag, tel, telnet, tftp, thismessage, tn3270, tip, tv, urn, vemmi, ws, wss, xcon, xcon-userid, xmlrpc.beep, xmlrpc.beeps, xmpp, z39.50r, z39.50s, adiumxtra, afp, afs, aim, apt,attachment, aw, beshare, bitcoin, bolo, callto, chrome,chrome-extension, com-eventbrite-attendee, content, cvs,dlna-playsingle, dlna-playcontainer, dtn, dvb, ed2k, facetime, feed, finger, fish, gg, git, gizmoproject, gtalk, hcp, icon, ipn, irc, irc6, ircs, itms, jar, jms, keyparc, lastfm, ldaps, magnet, maps, market,message, mms, ms-help, msnim, mumble, mvn, notes, oid, palm, paparazzi, platform, proxy, psyc, query, res, resource, rmi, rsync, rtmp, secondlife, sftp, sgn, skype, smb, soldat, spotify, ssh, steam, svn, teamspeak, things, udp, unreal, ut2004, ventrilo, view-source, webcal, wtai, wyciwyg, xfire, xri, ymsgr

以下是一些有效的自动链接:

示例 421  (交互)
<http://foo.bar.baz>
<p><a href="http://foo.bar.baz">http://foo.bar.baz</a></p>
示例 422  (交互)
<http://foo.bar.baz?q=hello&id=22&boolean>
<p><a href="http://foo.bar.baz?q=hello&amp;id=22&amp;boolean">http://foo.bar.baz?q=hello&amp;id=22&amp;boolean</a></p>
示例 423  (交互)
<irc://foo.bar:2233/baz>
<p><a href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>

大写字母也可以。

示例 424  (交互)
<MAILTO:FOO@BAR.BAZ>
<p><a href="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>

自动链接中不允许出现空格。

示例 425  (交互)
<http://foo.bar/baz bim>
<p>&lt;http://foo.bar/baz bim&gt;</p>

一个 电子邮件自动链接 <、后跟一个 电子邮件地址、再后跟 > 组成。链接标签即为电子邮件地址,URL 为 mailto: 后跟电子邮件地址。

一个 电子邮件地址 在此处指代任何匹配 HTML5 规范中的非规范性正则表达式 的内容。

/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?
(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/

电子邮件自动链接示例:

示例 426  (交互)
<foo@bar.example.com>
<p><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
示例 427  (交互)
<foo+special@Bar.baz-bar0.com>
<p><a href="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>

这些不是自动链接:

示例 428  (交互)
<>
<p>&lt;&gt;</p>
示例 429  (交互)
<heck://bing.bong>
<p>&lt;heck://bing.bong&gt;</p>
示例 430  (交互)
< http://foo.bar >
<p>&lt; http://foo.bar &gt;</p>
示例 431  (交互)
<foo.bar.baz>
<p>&lt;foo.bar.baz&gt;</p>
示例 432  (交互)
<localhost:5001/foo>
<p>&lt;localhost:5001/foo&gt;</p>
示例 433  (交互)
http://example.com
<p>http://example.com</p>
示例 434  (交互)
foo@bar.example.com
<p>foo@bar.example.com</p>

6.8 原生 HTML

<> 之间看起来像 HTML 标签的文本会被解析为原始 HTML 标签,并将直接在 HTML 中渲染而不会进行转义。标签和属性名称不限于当前的 HTML 标签,因此可以使用自定义标签(甚至可以例如使用 DocBook 标签)。

这是标签语法:

一个 标签名 由一个 ASCII 字母后跟零个或多个 ASCII 字母或数字组成。

一个 属性 由空白字符、一个 属性名 和一个可选的 属性值说明 组成。

一个 属性名 由一个 ASCII 字母、_:,后跟零个或多个 ASCII 字母、数字、_.:- 组成。(注意:这是受限于 ASCII 的 XML 规范。HTML5 更加宽松。)

一个 属性值说明 由可选的空白字符、一个 = 字符、可选的空白字符和一个 属性值 组成。

一个 属性值 未引号引用的属性值单引号引用的属性值双引号引用的属性值 组成。

一个 未引号引用的属性值 是一个非空的字符字符串,不包含空格、"'=<>`

一个 单引号引用的属性值 '、零个或多个不包含 ' 的字符以及一个最终的 ' 组成。

一个 双引号引用的属性值 "、零个或多个不包含 " 的字符以及一个最终的 " 组成。

一个 起始标签 由一个 < 字符、一个 标签名、零个或多个 属性、可选的空白字符、一个可选的 / 字符和一个 > 字符组成。

一个 结束标签 由字符串 </、一个 标签名、可选的空白字符和字符 > 组成。

一个 HTML 注释 由字符串 <!--、一串不包含字符串 -- 的字符以及字符串 --> 组成。

一个 处理指令 由字符串 <?、一串不包含字符串 ?> 的字符以及字符串 ?> 组成。

一个 声明 由字符串 <!、一个由一个或多个大写 ASCII 字母组成的名称、空白字符、一串不包含 > 的字符以及字符 > 组成。

一个 CDATA 节 由字符串 <![CDATA[、一串不包含字符串 ]]> 的字符以及字符串 ]]> 组成。

一个 HTML 标签 由一个 起始标签结束标签HTML 注释处理指令元素类型声明CDATA 节 组成。

以下是一些简单的开始标签

示例 435  (交互)
<a><bab><c2c>
<p><a><bab><c2c></p>

空元素

示例 436  (交互)
<a/><b2/>
<p><a/><b2/></p>

允许存在空白

示例 437  (交互)
<a  /><b2
data="foo" >
<p><a  /><b2
data="foo" ></p>

带有属性

示例 438  (交互)
<a foo="bar" bam = 'baz <em>"</em>'
_boolean zoop:33=zoop:33 />
<p><a foo="bar" bam = 'baz <em>"</em>'
_boolean zoop:33=zoop:33 /></p>

非法标签名称,不会被解析为 HTML

示例 439  (交互)
<33> <__>
<p>&lt;33&gt; &lt;__&gt;</p>

非法属性名称

示例 440  (交互)
<a h*#ref="hi">
<p>&lt;a h*#ref=&quot;hi&quot;&gt;</p>

非法属性值

示例 441  (交互)
<a href="hi'> <a href=hi'>
<p>&lt;a href=&quot;hi'&gt; &lt;a href=hi'&gt;</p>

非法空白

示例 442  (交互)
< a><
foo><bar/ >
<p>&lt; a&gt;&lt;
foo&gt;&lt;bar/ &gt;</p>

缺少空白

示例 443  (交互)
<a href='bar'title=title>
<p>&lt;a href='bar'title=title&gt;</p>

结束标签

示例 444  (交互)
</a>
</foo >
<p></a>
</foo ></p>

结束标签中的非法属性

示例 445  (交互)
</a href="foo">
<p>&lt;/a href=&quot;foo&quot;&gt;</p>

注释

示例 446  (交互)
foo <!-- this is a
comment - with hyphen -->
<p>foo <!-- this is a
comment - with hyphen --></p>
示例 447  (交互)
foo <!-- not a comment -- two hyphens -->
<p>foo &lt;!-- not a comment -- two hyphens --&gt;</p>

处理指令

示例 448  (交互)
foo <?php echo $a; ?>
<p>foo <?php echo $a; ?></p>

声明

示例 449  (交互)
foo <!ELEMENT br EMPTY>
<p>foo <!ELEMENT br EMPTY></p>

CDATA 部分

示例 450  (交互)
foo <![CDATA[>&<]]>
<p>foo <![CDATA[>&<]]></p>

实体在 HTML 属性中会被保留

示例 451  (交互)
<a href="&ouml;">
<p><a href="&ouml;"></p>

反斜杠转义在 HTML 属性中无效

示例 452  (交互)
<a href="\*">
<p><a href="\*"></p>
示例 453  (交互)
<a href="\"">
<p>&lt;a href=&quot;&quot;&quot;&gt;</p>

6.9 硬换行

一个位于代码段或 HTML 标签之外的换行符,如果其前有两个或更多空格,则被解析为 硬换行(在 HTML 中渲染为 <br /> 标签)。

示例 454  (交互)
foo  
baz
<p>foo<br />
baz</p>

作为一种更显眼的替代方案,可以在换行符之前使用反斜杠,而不是使用两个空格

示例 455  (交互)
foo\
baz
<p>foo<br />
baz</p>

可以使用超过两个的空格

示例 456  (交互)
foo       
baz
<p>foo<br />
baz</p>

下一行开头的空格会被忽略

示例 457  (交互)
foo  
     bar
<p>foo<br />
bar</p>
示例 458  (交互)
foo\
     bar
<p>foo<br />
bar</p>

换行符可以出现在强调、链接以及其他允许内联内容的结构中

示例 459  (交互)
*foo  
bar*
<p><em>foo<br />
bar</em></p>
示例 460  (交互)
*foo\
bar*
<p><em>foo<br />
bar</em></p>

换行符不会出现在代码行内

示例 461  (交互)
`code  
span`
<p><code>code span</code></p>
示例 462  (交互)
`code\
span`
<p><code>code\ span</code></p>

或者 HTML 标签内

示例 463  (交互)
<a href="foo  
bar">
<p><a href="foo  
bar"></p>
示例 464  (交互)
<a href="foo\
bar">
<p><a href="foo\
bar"></p>

6.10 软换行

一个常规换行(不在代码片段或 HTML 标签内)且前面没有两个或更多空格的换行被解析为软换行。(软换行在 HTML 中可以渲染为换行符或空格。在浏览器中结果相同。此处的示例中将使用换行符。)

示例 465  (交互)
foo
baz
<p>foo
baz</p>

行末和下一行开头的空格会被移除

示例 466  (交互)
foo 
 baz
<p>foo
baz</p>

符合标准的解析器可以将 HTML 中的软换行渲染为换行符或空格。

渲染器也可以提供一个选项,将软换行渲染为硬换行。

6.11 字符串

任何上述规则未赋予解释的字符都将被解析为字符串内容。

示例 467  (交互)
hello $.;'there
<p>hello $.;'there</p>
示例 468  (交互)
Foo χρῆν
<p>Foo χρῆν</p>

内部空格会被逐字保留

示例 469  (交互)
Multiple     spaces
<p>Multiple     spaces</p>

附录 A:解析策略

概述

解析分为两个阶段

  1. 第一阶段,消耗输入行并构建文档的块结构——即将其划分为段落、块引用、列表项等。文本被分配给这些块,但不进行解析。链接引用定义会被解析并构建一个链接映射表。

  2. 在第二阶段,段落和标题的原始文本内容被解析为一系列 Markdown 行内元素(字符串、代码 span、链接、强调等),并使用第一阶段构建的链接引用映射。

文档树

在处理的每个点,文档都被表示为由组成的树。树的根是 document 块。document 可以拥有任意数量的其他块作为子节点。这些子节点依次又可以拥有其他块作为子节点。块的最后一个子节点通常被视为开放的,意味着后续的输入行可以改变其内容。(未开放的块即为已关闭的。)例如,这是一个可能的文档树,箭头标记了开放的块

-> document
  -> block_quote
       paragraph
         "Lorem ipsum dolor\nsit amet."
    -> list (type=bullet tight=true bullet_char=-)
         list_item
           paragraph
             "Qui *quodsi iracundia*"
      -> list_item
        -> paragraph
             "aliquando id"

源行如何改变文档树

每一行被处理的文本都会对这棵树产生影响。通过分析该行,根据其内容,文档可以通过以下一种或多种方式进行变更

  1. 一个或多个开放的块可能会被关闭。
  2. 一个或多个新的块可能会作为最后一个开放块的子节点被创建。
  3. 文本可以被添加到树上最后一个(最深层的)开放块中。

一旦某一行以这种方式被合并到树中,它就可以被丢弃,因此输入可以以流的形式读取。

通过考虑上述树是如何由四行 Markdown 生成的,我们可以看出其工作原理

> Lorem ipsum dolor
sit amet.
> - Qui *quodsi iracundia*
> - aliquando id

起初,我们的文档模型仅仅是

-> document

第一行文本,

> Lorem ipsum dolor

导致一个 block_quote 块作为我们开放的 document 块的子节点被创建,而一个 paragraph 块作为 block_quote 的子节点。然后文本被添加到最后一个开放块,即 paragraph 中。

-> document
  -> block_quote
    -> paragraph
         "Lorem ipsum dolor"

下一行,

sit amet.

是开放 paragraph 的“惰性延续”,因此它被添加到段落的文本中。

-> document
  -> block_quote
    -> paragraph
         "Lorem ipsum dolor\nsit amet."

第三行,

> - Qui *quodsi iracundia*

导致 paragraph 块被关闭,一个新的 list 块作为 block_quote 的子节点被打开。一个 list_item 也作为 list 的子节点被添加,而一个 paragraph 作为 list_item 的子节点。然后文本被添加到新的 paragraph 中。

-> document
  -> block_quote
       paragraph
         "Lorem ipsum dolor\nsit amet."
    -> list (type=bullet tight=true bullet_char=-)
      -> list_item
        -> paragraph
             "Qui *quodsi iracundia*"

第四行,

> - aliquando id

导致 list_item(及其子节点 paragraph)被关闭,一个新的 list_item 作为 list 的子节点被打开。一个 paragraph 被添加为新 list_item 的子节点,用于包含文本。这样我们就得到了最终的树。

-> document
  -> block_quote
       paragraph
         "Lorem ipsum dolor\nsit amet."
    -> list (type=bullet tight=true bullet_char=-)
         list_item
           paragraph
             "Qui *quodsi iracundia*"
      -> list_item
        -> paragraph
             "aliquando id"

从块结构到最终文档

一旦所有输入都被解析完毕,所有的开放块都会被关闭。

然后我们“遍历树”,访问每个节点,并将段落和标题的原始字符串内容解析为行内元素。此时我们已经看到了所有的链接引用定义,因此可以在遍历过程中解析引用链接。

document
  block_quote
    paragraph
      str "Lorem ipsum dolor"
      softbreak
      str "sit amet."
    list (type=bullet tight=true bullet_char=-)
      list_item
        paragraph
          str "Qui "
          emph
            str "quodsi iracundia"
      list_item
        paragraph
          str "aliquando id"

请注意第一个段落中的换行符如何被解析为 softbreak,以及第一个列表项中的星号如何变为 emph

给定适当的渲染器,文档可以渲染为 HTML 或任何其他格式。