CommonMark 规范

版本 0.18 (2015-03-03)
John MacFarlane
Creative
   Commons BY-SA
CommonMark 规范John MacFarlane 创作,采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
这是本规范的一个旧版本。最新版本请见 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. 列表项可以为空吗?

    * a
    *
    * b
    
  13. 链接引用可以在块引用或列表项内定义吗?

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

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

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

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

1.3 关于本文档

本文档试图明确地规范 Markdown 语法。它包含了许多 Markdown 和 HTML 并排显示的示例。这些示例旨在兼作一致性测试。随附的脚本 spec_tests.py 可用于对任何 Markdown 程序运行这些测试:

python test/spec_tests.py --spec spec.txt --program PROGRAM

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

本文档由一个文本文件 spec.txt 生成,该文件以 Markdown 编写,并针对并排测试进行了微小的扩展。脚本 tools/makespec.py 可用于将 spec.txt 转换为 HTML 或 CommonMark(然后可以将其转换为其他格式)。

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

2 准备工作

2.1 字符与行

任何字符序列都是有效的 CommonMark 文档。

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

一行(line)是由零个或多个 字符 组成,并以 行尾 或文件结尾终止的序列。

一个 行尾 根据平台的不同,可以是换行符 (U+000A)、回车符 (U+000D) 或回车符加换行符。

出于安全原因,符合规范的解析器必须剔除或替换 Unicode 字符 U+0000

不包含字符的行,或仅包含空格 (U+0020) 或制表符 (U+0009) 的行,称为空行

本规范将使用以下字符类定义:

空白字符是空格 (U+0020)、制表符 (U+0009)、换行符 (U+000A)、行制表符 (U+000B)、换页符 (U+000C) 或回车符 (U+000D)。

空白是一个或多个空白字符的序列。

一个 Unicode 空白字符 是 Unicode Zs 类中的任何码位,或制表符 (U+0009)、回车符 (U+000D)、换行符 (U+000A) 或换页符 (U+000C)。

Unicode 空白 是一个或多个 Unicode 空白字符 的序列。

一个 非空格字符 是除 U+0020 以外的任何内容。

ASCII 标点字符!, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, 或 ~

一个 标点符号ASCII 标点符号 或任何 Unicode Pc, Pd, Pe, Pf, Pi, PoPs 类中的字符。

2.2 制表符扩展

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

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

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 标题下划线就会被解释为段落一部分的行:它不能是代码块、标题、块引用、水平分割线或列表。

一个 Setext 标题下划线 是一个 = 字符序列或 - 字符序列,缩进不超过 3 个空格,且末尾可有任意数量的空格。如果一行包含单个 - 且可以被解释为 列表项,则应将其解释为该列表项,而非 Setext 标题下划线

如果 Setext 标题下划线 使用 = 字符,则该标题为 1 级标题;如果使用 - 字符,则为 2 级标题。标题的内容是将第一行解析为 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; 实体替换空行。

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

一个 链接引用定义 由一个缩进最多三个空格的 链接标签,后跟冒号 (:)、可选的 空白(包含最多一个 行尾)、一个 链接目标、可选的 空白(包含最多一个 行尾)以及一个可选的 链接标题 组成,如果存在标题,必须通过 空白链接目标 分隔。该行上不得出现更多 非空格字符

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

示例 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 '
title
line1
line2
'

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

然而,它不能包含空行

示例 116  (交互)
[foo]: /url 'title

with blank line'

[foo]
<p>[foo]: /url 'title</p>
<p>with blank line'</p>
<p>[foo]</p>

标题可以省略

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

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

链接目标不能省略

示例 118  (交互)
[foo]:

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

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

示例 119  (交互)
[foo]

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

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

示例 120  (交互)
[foo]

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

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

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

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

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

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

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

这里是另一个

示例 124  (交互)
[
foo
]: /url
bar
<p>bar</p>

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

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

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

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

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

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

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

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

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

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

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

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

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

多个链接引用定义可以彼此连续出现,无需中间空行。

示例 130  (交互)
[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>

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

示例 131  (交互)
[foo]

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

4.8 段落

一系列不能被解释为其他类型块的非空行构成了一个段落。段落的内容是对段落原始内容进行行内解析的结果。段落的原始内容是通过连接各行并去除首尾的空白字符形成的。

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

示例 132  (交互)
aaa

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

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

示例 133  (交互)
aaa
bbb

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

段落之间的多个空行无效

示例 134  (交互)
aaa


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

前导空格会被忽略

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

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

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

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

示例 137  (交互)
   aaa
bbb
<p>aaa
bbb</p>
示例 138  (交互)
    aaa
bbb
<pre><code>aaa
</code></pre>
<p>bbb</p>

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

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

4.9 空行

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

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

示例 140  (交互)
  

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. 连续性。 如果两个引用块之间没有空行,文档不能包含两个连续的引用块。

除此之外的其他内容均不视为引用块

这是一个简单的例子

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

可以省略 > 字符后的空格

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

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

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

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

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

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

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

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

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

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

示例 147  (交互)
> foo
---
<blockquote>
<p>foo</p>
</blockquote>
<hr />
示例 148  (交互)
> - foo
- bar
<blockquote>
<ul>
<li>foo</li>
</ul>
</blockquote>
<ul>
<li>bar</li>
</ul>
示例 149  (交互)
>     foo
    bar
<blockquote>
<pre><code>foo
</code></pre>
</blockquote>
<pre><code>bar
</code></pre>
示例 150  (交互)
> ```
foo
```
<blockquote>
<pre><code></code></pre>
</blockquote>
<p>foo</p>
<pre><code></code></pre>

引用块可以为空

示例 151  (交互)
>
<blockquote>
</blockquote>
示例 152  (交互)
>
>  
> 
<blockquote>
</blockquote>

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

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

空行总是会分隔引用块

示例 154  (交互)
> foo

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

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

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

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

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

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

引用块可以中断段落

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

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

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

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

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

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

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

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

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

示例 164  (交互)
>     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 个空格,那么在 Ls 的第一行前加上 M 和随后的空格,并将 Ls 的后续行缩进 W + N 个空格的结果,就是一个内容为 Bs 的列表项。列表项的类型(项目符号或有序)由其列表标记的类型决定。如果列表项是有序的,则还会根据有序列表标记分配一个起始编号。

例如,设 Ls 为以下几行

示例 165  (交互)
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 相同

示例 166  (交互)
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>

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

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

示例 167  (交互)
- one

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

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

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

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

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

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

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

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

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

注意,列表标记和随后的任何内容之间至少需要一个空格,因此以下不是列表项

示例 173  (交互)
-one

2.two
<p>-one</p>
<p>2.two</p>

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

示例 174  (交互)
- foo

  bar

- foo


  bar

- ```
  foo


  bar
  ```

- baz

  + ```
    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>
<li>
<p>baz</p>
<ul>
<li>
<pre><code>foo


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

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

示例 175  (交互)
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 个空格

示例 176  (交互)
- foo

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

在这种情况下为 11 个空格

示例 177  (交互)
  10.  foo

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

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

示例 178  (交互)
    indented code

paragraph

    more code
<pre><code>indented code
</code></pre>
<p>paragraph</p>
<pre><code>more code
</code></pre>
示例 179  (交互)
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>

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

示例 180  (交互)
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) 它们以缩进代码块开头的情况。在像下面这样的情况下,第一个块以三个空格缩进开始,规则不允许我们通过缩进整个部分并添加列表标记来形成列表项

示例 181  (交互)
   foo

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

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

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

示例 183  (交互)
-  foo

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

以下是一些以空行开头但不为空的列表项

示例 184  (交互)
-
  foo
-
  ```
  bar
  ```
-
      baz
<ul>
<li>foo</li>
<li>
<pre><code>bar
</code></pre>
</li>
<li>
<pre><code>baz
</code></pre>
</li>
</ul>

这是一个空的无序列表项

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

列表标记之后是否有空格无关紧要

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

这是一个空的有序列表项

示例 187  (交互)
1. foo
2.
3. bar
<ol>
<li>foo</li>
<li></li>
<li>bar</li>
</ol>

列表可以以空的列表项开始或结束

示例 188  (交互)
*
<ul>
<li></li>
</ul>
  1. 缩进。 如果一串行 Ls 根据规则 #1, #2 或 #3 构成了一个列表项,那么将 L 的每一行缩进 1-3 个空格(每行缩进相同)的结果也构成一个具有相同内容和属性的列表项。如果一行是空的,则不需要缩进。

缩进一个空格

示例 189  (交互)
 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>

缩进两个空格

示例 190  (交互)
  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>

缩进三个空格

示例 191  (交互)
   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>

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

示例 192  (交互)
    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. 懒惰。 如果一串行 Ls 构成了一个内容为 Bs列表项,那么当下一行中缩进后的第一个 非空格字符段落续行文本 时,删除该行部分或全部缩进的结果依然是一个具有相同内容和属性的列表项。未缩进的行被称为 懒惰续行

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

示例 193  (交互)
  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>

缩进可以被部分删除

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

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

示例 195  (交互)
> 1. > Blockquote
continued here.
<blockquote>
<ol>
<li>
<blockquote>
<p>Blockquote
continued here.</p>
</blockquote>
</li>
</ol>
</blockquote>
示例 196  (交互)
> 1. > Blockquote
> continued here.
<blockquote>
<ol>
<li>
<blockquote>
<p>Blockquote
continued here.</p>
</blockquote>
</li>
</ol>
</blockquote>
  1. 结束。 根据规则 #1–5 未被计为列表项的内容均不视为列表项

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

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

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

一个空格是不够的

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

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

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

三个空格是不够的

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

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

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

列表项可以包含标题

示例 203  (交互)
- # Foo
- Bar
  ---
  baz
<ul>
<li>
<h1>Foo</h1>
</li>
<li>
<h2>Bar</h2>
baz</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 行为格式化的列表,前提是它们的布局方式对于人类阅读来说是自然的。

这里的策略是让列表标记的宽度和缩进决定块归入列表项所需的缩进,而不是使用固定和任意的数字。作者可以将列表项的主体视为一个单元,该单元向右缩进足够多以容纳列表标记(以及列表标记上的任何缩进)。(惰性规则 #5 然后允许在需要时取消对延续行的缩进。)

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

- 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> 标签中,而紧凑列表中的段落则不会。)

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

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

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

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

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

示例 207  (交互)
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 既定的实践更加一致。

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

示例 208  (交互)
- foo

- bar


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

如上文列表项部分所示,列表项内部块之间的两个空行也会结束列表

示例 209  (交互)
- foo


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

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

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


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

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

示例 211  (交互)
- foo
- bar


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

    notcode

-   foo


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

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

示例 213  (交互)
- 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>

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

示例 214  (交互)
- a
- b

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

这也是,第二个项为空

示例 215  (交互)
* a
*

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

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

示例 216  (交互)
- a
- b

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

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

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

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


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


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

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

示例 219  (交互)
- a
  - b

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

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

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

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

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

单段落列表是紧凑的

示例 222  (交互)
- a
<ul>
<li>a</li>
</ul>
示例 223  (交互)
- a
  - b
<ul>
<li>a
<ul>
<li>b</li>
</ul>
</li>
</ul>

这个列表是松散的,因为列表项中的两个块元素之间有空行

示例 224  (交互)
1. ```
   foo
   ```

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

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

示例 225  (交互)
* foo
  * bar

  baz
<ul>
<li>
<p>foo</p>
<ul>
<li>bar</li>
</ul>
<p>baz</p>
</li>
</ul>
示例 226  (交互)
- 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 行内元素

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

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

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

6.1 反斜杠转义

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

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

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

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

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

示例 230  (交互)
\*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>

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

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

行尾的反斜杠是 硬换行

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

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

示例 233  (交互)
`` \[\` ``
<p><code>\[\`</code></p>
示例 234  (交互)
    \[\]
<pre><code>\[\]
</code></pre>
示例 235  (交互)
~~~
\[\]
~~~
<pre><code>\[\]
</code></pre>
示例 236  (交互)
<http://example.com?find=\*>
<p><a href="http://example.com?find=%5C*">http://example.com?find=\*</a></p>
示例 237  (交互)
<a href="/bar\/)">
<p><a href="/bar\/)"></p>

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

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

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

6.2 实体

为了使本标准尽可能与 HTML 无关,所有有效的 HTML 实体(代码块和代码 span 除外)在存储到 AST 之前都会被识别并转换为 Unicode 字符。这意味着渲染为非 HTML 格式时无需感知 HTML 实体。HTML 渲染器可以选择将 Unicode 字符转义为实体或保持原样。(然而,", &, <, 和 > 必须始终渲染为实体。)

命名实体& 组成

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

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

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

十六进制实体&# + Xx + 1-8 位十六进制数字串

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

这里是一些非实体引用

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

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

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

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

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

实体在代码 span 或代码块之外的任何上下文中都被识别,包括原始 HTML、URL、链接标题受限代码块

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

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

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

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

6.3 代码片段

反引号字符串是指一串包含一个或多个反引号字符(`)的字符串,且其前后均无反引号。

代码跨度以反引号字符串开始,并以等长的反引号字符串结束。代码跨度的内容是两个反引号字符串之间的字符,其中前导和尾随空格以及 行尾符 会被移除,且 空白字符 会被折叠为单个空格。

这是一个简单的代码跨度

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

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

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

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

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

行尾符被视为类似空格的处理。

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

内部空格和 行尾符 会被折叠为单个空格,就像浏览器处理它们一样。

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

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

(现有实现对内部空格和 行尾符 的处理方式各不相同。一些实现,包括 Markdown.plshowdown,会将内部 行尾符 转换为 <br /> 标签。但这给喜欢硬换行段落的用户造成了困难,因为代码跨度中间的换行会导致输出中出现非预期的换行。其他实现则直接保留内部空格,如果目标仅是 HTML,这是没问题的。)

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

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

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

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

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

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

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

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

代码跨度、HTML 标签和自动链接具有相同的优先级。因此,这是代码。

示例 262  (交互)
`<a href="`">`
<p><code>&lt;a href=&quot;</code>&quot;&gt;`</p>

但这却是一个 HTML 标签。

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

而这则是代码。

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

但这又是一个自动链接。

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

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

示例 266  (交互)
```foo``
<p>```foo``</p>
示例 267  (交互)
`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

下面给出的规则涵盖了所有这些模式,同时允许不回溯的高效解析策略。

首先,进行一些定义。定界符序列(delimiter run)是指一个或多个 * 字符组成的序列(且前后均无 *),或一个或多个 _ 字符组成的序列(且前后均无 _)。

一个 左侧侧翼定界符运行 是一个 定界符运行,它 (a) 不后跟 Unicode 空白,并且 (b) 不后跟 标点符号,或者前面有 Unicode 空白标点符号 或行首。

一个 右侧侧翼定界符运行 是一个 定界符运行,它 (a) 不前跟 Unicode 空白,并且 (b) 不前跟 标点符号,或者后面有 Unicode 空白标点符号 或行尾。

以下是一些定界符序列的示例。

(根据前后的字符来区分左侧侧翼和右侧侧翼定界符序列的想法来源于 Roopesh Chander 的 vfmd。vfmd 使用“强调指示符字符串”而不是“定界符序列”这一术语,其区分左右侧翼序列的规则比这里给出的要复杂一些。)

以下规则定义了强调和强强调。

  1. 单个 * 字符 可以开启强调,当且仅当它是 左侧侧翼定界符运行 的一部分。

  2. 单个 _ 字符 可以开启强调,当且仅当它是 左侧侧翼定界符运行 的一部分且不是 右侧侧翼定界符运行 的一部分。

  3. 单个 * 字符 可以关闭强调,当且仅当它是 右侧侧翼定界符序列 的一部分。

  4. 单个 _ 字符 可以关闭强调,当且仅当它是 右侧侧翼定界符运行 的一部分且不是 左侧侧翼定界符运行 的一部分。

  5. ** 可以开启强强调,当且仅当它是 左侧侧翼定界符序列 的一部分。

  6. __ 可以开启强强调,当且仅当它是 左侧侧翼定界符运行 的一部分且不是 右侧侧翼定界符运行 的一部分。

  7. ** 可以关闭强强调,当且仅当它是 右侧侧翼定界符序列 的一部分。

  8. __ 可以关闭强强调,当且仅当它是 右侧侧翼定界符运行 的一部分且不是 左侧侧翼定界符运行 的一部分。

  9. 强调以 可以开启强调 的定界符开始,并以 可以关闭强调 的定界符结束,且使用与开启定界符相同的字符(_*)。开启定界符和关闭定界符之间必须存在非空的行内序列;这些形成了强调行内的内容。

  10. 强强调以 可以开启强强调 的定界符开始,并以 可以关闭强强调 的定界符结束,且使用与开启定界符相同的字符(_*)。开启定界符和关闭定界符之间必须存在非空的行内序列;这些形成了强强调行内的内容。

  11. 除非经过反斜杠转义,否则字面意义上的 * 字符不能出现在 * 定界的强调或 ** 定界的强强调的开头或结尾。

  12. 除非经过反斜杠转义,否则字面意义上的 _ 字符不能出现在 _ 定界的强调或 __ 定界的强强调的开头或结尾。

在上述 1–12 条规则与多种解析结果兼容的情况下,以下原则用于解决歧义。

  1. 应尽可能减少嵌套数量。因此,例如,解释为 <strong>...</strong> 总是优先于 <em><em>...</em></em>

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

  3. 当两个潜在的强调或强强调跨度重叠时,即第二个在第一个结束之前开始,而在第一个结束之后才结束,则第一个优先。因此,例如,*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. 当有两个具有相同关闭定界符的潜在强调或强强调跨度时,较短的一个(后开启的那个)优先。因此,例如,**foo **bar baz** 被解析为 **foo <strong>bar baz</strong> 而不是 <strong>foo **bar baz</strong>

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

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

规则 1

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

这不是强调,因为开启的 * 后跟有空格,因此不是 左侧侧翼定界符序列 的一部分。

示例 269  (交互)
a * foo bar*
<p>a * foo bar*</p>

这不是强调,因为开启的 * 前是字母数字,后是标点符号,因此不是 左侧侧翼定界符序列 的一部分。

示例 270  (交互)
a*"foo"*
<p>a*&quot;foo&quot;*</p>

Unicode 不换行空格也计为空白字符。

示例 271  (交互)
* a *
<p>* a *</p>

允许使用 * 进行词内强调。

示例 272  (交互)
foo*bar*
<p>foo<em>bar</em></p>
示例 273  (交互)
5*6*78
<p>5<em>6</em>78</p>

规则 2

示例 274  (交互)
_foo bar_
<p><em>foo bar</em></p>

这不是强调,因为开启的 _ 后跟有空格。

示例 275  (交互)
_ foo bar_
<p>_ foo bar_</p>

这不是强调,因为开启的 _ 前是字母数字,后是标点符号。

示例 276  (交互)
a_"foo"_
<p>a_&quot;foo&quot;_</p>

不允许在单词内部使用 _ 进行强调。

示例 277  (交互)
foo_bar_
<p>foo_bar_</p>
示例 278  (交互)
5_6_78
<p>5_6_78</p>
示例 279  (交互)
пристаням_стремятся_
<p>пристаням_стремятся_</p>

此处 _ 不产生强调,因为第一个定界符序列是右侧侧翼,而第二个是左侧侧翼。

示例 280  (交互)
aa_"bb"_cc
<p>aa_&quot;bb&quot;_cc</p>

这里没有强调,因为定界符运行既是左侧侧翼也是右侧侧翼

示例 281  (交互)
"aa"_"bb"_"cc"
<p>&quot;aa&quot;_&quot;bb&quot;_&quot;cc&quot;</p>

规则 3

这不是强调,因为关闭定界符与开启定界符不匹配。

示例 282  (交互)
_foo*
<p>_foo*</p>

这不是强调,因为关闭的 * 前面有空格。

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

换行符也被计为空白字符。

示例 284  (交互)
*foo bar
*
<p>*foo bar</p>
<ul>
<li></li>
</ul>

这不是强调,因为第二个 * 前面是标点符号,后面是字母数字(因此它不是 右侧侧翼定界符序列 的一部分)。

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

此限制的意义可以通过以下示例更清楚地理解。

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

允许使用 * 进行词内强调。

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

规则 4

这不是强调,因为关闭的 _ 前面有空格。

示例 288  (交互)
_foo bar _
<p>_foo bar _</p>

这不是强调,因为第二个 _ 前面是标点符号,后面是字母数字。

示例 289  (交互)
_(_foo)
<p>_(_foo)</p>

这是强调嵌套在强调中。

示例 290  (交互)
_(_foo_)_
<p><em>(<em>foo</em>)</em></p>

对于 _ 不允许进行词内强调。

示例 291  (交互)
_foo_bar
<p>_foo_bar</p>
示例 292  (交互)
_пристаням_стремятся
<p>_пристаням_стремятся</p>
示例 293  (交互)
_foo_bar_baz_
<p><em>foo_bar_baz</em></p>

规则 5

示例 294  (交互)
**foo bar**
<p><strong>foo bar</strong></p>

这不是强强调,因为开启定界符后跟有空格。

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

这不是强强调,因为开启的 ** 前是字母数字,后是标点符号,因此不是 左侧侧翼定界符序列 的一部分。

示例 296  (交互)
a**"foo"**
<p>a**&quot;foo&quot;**</p>

允许使用 ** 进行词内强强调。

示例 297  (交互)
foo**bar**
<p>foo<strong>bar</strong></p>

规则 6

示例 298  (交互)
__foo bar__
<p><strong>foo bar</strong></p>

这不是强强调,因为开启定界符后跟有空格。

示例 299  (交互)
__ foo bar__
<p>__ foo bar__</p>

换行符计为空白字符。

示例 300  (交互)
__
foo bar__
<p>__
foo bar__</p>

这不是强强调,因为开启的 __ 前是字母数字,后是标点符号。

示例 301  (交互)
a__"foo"__
<p>a__&quot;foo&quot;__</p>

禁止使用 __ 进行词内强强调。

示例 302  (交互)
foo__bar__
<p>foo__bar__</p>
示例 303  (交互)
5__6__78
<p>5__6__78</p>
示例 304  (交互)
пристаням__стремятся__
<p>пристаням__стремятся__</p>
示例 305  (交互)
__foo, __bar__, baz__
<p><strong>foo, <strong>bar</strong>, baz</strong></p>

规则 7

这不是强强调,因为关闭定界符前面有空格。

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

(根据规则 11,它也不能被解释为强调的 *foo bar *。)

这不是强强调,因为第二个 ** 前是标点符号,后是字母数字。

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

此限制的意义可以通过这些示例更清楚地理解。

示例 308  (交互)
*(**foo**)*
<p><em>(<strong>foo</strong>)</em></p>
示例 309  (交互)
**Gomphocarpus (*Gomphocarpus physocarpus*, syn.
*Asclepias physocarpa*)**
<p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.
<em>Asclepias physocarpa</em>)</strong></p>
示例 310  (交互)
**foo "*bar*" foo**
<p><strong>foo &quot;<em>bar</em>&quot; foo</strong></p>

词内强调

示例 311  (交互)
**foo**bar
<p><strong>foo</strong>bar</p>

规则 8

这不是强强调,因为关闭定界符前面有空格。

示例 312  (交互)
__foo bar __
<p>__foo bar __</p>

这不是强强调,因为第二个 __ 前是标点符号,后是字母数字。

示例 313  (交互)
__(__foo)
<p>__(__foo)</p>

此限制的意义可以通过以下示例更清楚地理解。

示例 314  (交互)
_(__foo__)_
<p><em>(<strong>foo</strong>)</em></p>

禁止使用 __ 进行词内强强调。

示例 315  (交互)
__foo__bar
<p>__foo__bar</p>
示例 316  (交互)
__пристаням__стремятся
<p>__пристаням__стремятся</p>
示例 317  (交互)
__foo__bar__baz__
<p><strong>foo__bar__baz</strong></p>

规则 9

任何非空的行内元素序列都可以作为强调跨度的内容。

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

特别是,强调和强强调可以嵌套在强调内。

示例 320  (交互)
_foo __bar__ baz_
<p><em>foo <strong>bar</strong> baz</em></p>
示例 321  (交互)
_foo _bar_ baz_
<p><em>foo <em>bar</em> baz</em></p>
示例 322  (交互)
__foo_ bar_
<p><em><em>foo</em> bar</em></p>
示例 323  (交互)
*foo *bar**
<p><em>foo <em>bar</em></em></p>
示例 324  (交互)
*foo **bar** baz*
<p><em>foo <strong>bar</strong> baz</em></p>

但请注意:

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

区别在于,在上述情况中,内部定界符 可以关闭强调,而在有空格的情况下,它们不能。

示例 326  (交互)
***foo** bar*
<p><em><strong>foo</strong> bar</em></p>
示例 327  (交互)
*foo **bar***
<p><em>foo <strong>bar</strong></em></p>

注意,在以下情况中我们无法得到强强调,因为开启定界符在 bar 之前的第一个 * 处即被关闭。

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

支持无限级的嵌套。

示例 329  (交互)
*foo **bar *baz* bim** bop*
<p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>
示例 330  (交互)
*foo [*bar*](/url)*
<p><em>foo <a href="/url"><em>bar</em></a></em></p>

不存在空强调或空强强调。

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

规则 10

任何非空的行内元素序列都可以作为强强调跨度的内容。

示例 333  (交互)
**foo [bar](/url)**
<p><strong>foo <a href="/url">bar</a></strong></p>
示例 334  (交互)
**foo
bar**
<p><strong>foo
bar</strong></p>

特别是,强调和强强调可以嵌套在强强调内。

示例 335  (交互)
__foo _bar_ baz__
<p><strong>foo <em>bar</em> baz</strong></p>
示例 336  (交互)
__foo __bar__ baz__
<p><strong>foo <strong>bar</strong> baz</strong></p>
示例 337  (交互)
____foo__ bar__
<p><strong><strong>foo</strong> bar</strong></p>
示例 338  (交互)
**foo **bar****
<p><strong>foo <strong>bar</strong></strong></p>
示例 339  (交互)
**foo *bar* baz**
<p><strong>foo <em>bar</em> baz</strong></p>

但请注意:

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

区别在于,在上述情况中,内部定界符 可以关闭强调,而在有空格的情况下,它们不能。

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

支持无限级的嵌套。

示例 343  (交互)
**foo *bar **baz**
bim* bop**
<p><strong>foo <em>bar <strong>baz</strong>
bim</em> bop</strong></p>
示例 344  (交互)
**foo [*bar*](/url)**
<p><strong>foo <a href="/url"><em>bar</em></a></strong></p>

不存在空强调或空强强调。

示例 345  (交互)
__ is not an empty emphasis
<p>__ is not an empty emphasis</p>
示例 346  (交互)
____ is not an empty strong emphasis
<p>____ is not an empty strong emphasis</p>

规则 11

示例 347  (交互)
foo ***
<p>foo ***</p>
示例 348  (交互)
foo *\**
<p>foo <em>*</em></p>
示例 349  (交互)
foo *_*
<p>foo <em>_</em></p>
示例 350  (交互)
foo *****
<p>foo *****</p>
示例 351  (交互)
foo **\***
<p>foo <strong>*</strong></p>
示例 352  (交互)
foo **_**
<p>foo <strong>_</strong></p>

请注意,当定界符不均匀匹配时,规则 11 确定多余的字面 * 字符将出现在强调之外,而不是之内。

示例 353  (交互)
**foo*
<p>*<em>foo</em></p>
示例 354  (交互)
*foo**
<p><em>foo</em>*</p>
示例 355  (交互)
***foo**
<p>*<strong>foo</strong></p>
示例 356  (交互)
****foo*
<p>***<em>foo</em></p>
示例 357  (交互)
**foo***
<p><strong>foo</strong>*</p>
示例 358  (交互)
*foo****
<p><em>foo</em>***</p>

规则 12

示例 359  (交互)
foo ___
<p>foo ___</p>
示例 360  (交互)
foo _\__
<p>foo <em>_</em></p>
示例 361  (交互)
foo _*_
<p>foo <em>*</em></p>
示例 362  (交互)
foo _____
<p>foo _____</p>
示例 363  (交互)
foo __\___
<p>foo <strong>_</strong></p>
示例 364  (交互)
foo __*__
<p>foo <strong>*</strong></p>
示例 365  (交互)
__foo_
<p>_<em>foo</em></p>

请注意,当定界符不均匀匹配时,规则 12 确定多余的字面 _ 字符将出现在强调之外,而不是之内。

示例 366  (交互)
_foo__
<p><em>foo</em>_</p>
示例 367  (交互)
___foo__
<p>_<strong>foo</strong></p>
示例 368  (交互)
____foo_
<p>___<em>foo</em></p>
示例 369  (交互)
__foo___
<p><strong>foo</strong>_</p>
示例 370  (交互)
_foo____
<p><em>foo</em>___</p>

规则 13 意味着,如果您希望强调直接嵌套在强调内,则必须使用不同的定界符。

示例 371  (交互)
**foo**
<p><strong>foo</strong></p>
示例 372  (交互)
*_foo_*
<p><em><em>foo</em></em></p>
示例 373  (交互)
__foo__
<p><strong>foo</strong></p>
示例 374  (交互)
_*foo*_
<p><em><em>foo</em></em></p>

然而,在不切换定界符的情况下,强强调嵌套在强强调内是可能的。

示例 375  (交互)
****foo****
<p><strong><strong>foo</strong></strong></p>
示例 376  (交互)
____foo____
<p><strong><strong>foo</strong></strong></p>

规则 13 可应用于任意长度的定界符序列。

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

规则 14

示例 378  (交互)
***foo***
<p><strong><em>foo</em></strong></p>
示例 379  (交互)
_____foo_____
<p><strong><strong><em>foo</em></strong></strong></p>

规则 15

示例 380  (交互)
*foo _bar* baz_
<p><em>foo _bar</em> baz_</p>
示例 381  (交互)
**foo*bar**
<p><em><em>foo</em>bar</em>*</p>

规则 16

示例 382  (交互)
**foo **bar baz**
<p>**foo <strong>bar baz</strong></p>
示例 383  (交互)
*foo *bar baz*
<p>*foo <em>bar baz</em></p>

规则 17

示例 384  (交互)
*[bar*](/url)
<p>*<a href="/url">bar*</a></p>
示例 385  (交互)
_foo [bar_](/url)
<p>_foo <a href="/url">bar_</a></p>
示例 386  (交互)
*<img src="foo" title="*"/>
<p>*<img src="foo" title="*"/></p>
示例 387  (交互)
**<a href="**">
<p>**<a href="**"></p>
示例 388  (交互)
__<a href="__">
<p>__<a href="__"></p>
示例 389  (交互)
*a `*`*
<p><em>a <code>*</code></em></p>
示例 390  (交互)
_a `_`_
<p><em>a <code>_</code></em></p>
示例 391  (交互)
**a<http://foo.bar/?q=**>
<p>**a<a href="http://foo.bar/?q=**">http://foo.bar/?q=**</a></p>
示例 392  (交互)
__a<http://foo.bar/?q=__>
<p>__a<a href="http://foo.bar/?q=__">http://foo.bar/?q=__</a></p>

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

链接文本由方括号([])括起来的零个或多个行内元素序列组成。适用以下规则:

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

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

尽管 链接标题 可以跨越多行,但它们不得包含 空行

行内链接链接文本 紧随左圆括号 (、可选的 空白字符、可选的 链接目标、通过 空白字符 与链接目标分隔的可选 链接标题、可选的 空白字符 以及右圆括号 ) 组成。链接文本包含 链接文本 中包含的行内元素(不包括包围的方括号)。链接 URI 包含链接目标,若存在则不包括包围的 <...>,并按上述规定应用反斜杠转义。链接标题包含链接标题,不包括其包围的定界符,并按上述规定应用反斜杠转义。

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

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

标题可以省略

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

标题和目标均可省略。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

示例 408  (交互)
[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>

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

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

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

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

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

示例 411  (交互)
[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 不允许。采用一个简单、合理的规则,在行内链接和链接引用定义中以同样方式工作,显然更为可取。)

目标和标题周围允许使用 空白字符

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

但链接文本和随后的圆括号之间不允许使用。

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

链接文本可以包含平衡的括号,但不能包含不平衡的括号,除非它们经过转义。

示例 414  (交互)
[link [foo [bar]]](/uri)
<p><a href="/uri">link [foo [bar]]</a></p>
示例 415  (交互)
[link] bar](/uri)
<p>[link] bar](/uri)</p>
示例 416  (交互)
[link [bar](/uri)
<p>[link <a href="/uri">bar</a></p>
示例 417  (交互)
[link \[bar](/uri)
<p><a href="/uri">link [bar</a></p>

链接文本可以包含行内内容。

示例 418  (交互)
[link *foo **bar** `#`*](/uri)
<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
示例 419  (交互)
[![moon](moon.jpg)](/uri)
<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>

但是,链接不得包含其他链接,无论嵌套层级如何。

示例 420  (交互)
[foo [bar](/uri)](/uri)
<p>[foo <a href="/uri">bar</a>](/uri)</p>
示例 421  (交互)
[foo *[bar [baz](/uri)](/uri)*](/uri)
<p>[foo <em>[bar <a href="/uri">baz</a>](/uri)</em>](/uri)</p>
示例 422  (交互)
![[[foo](uri1)](uri2)](uri3)
<p><img src="uri3" alt="[foo](uri2)" /></p>

这些情况说明了链接文本分组优于强调分组的优先级。

示例 423  (交互)
*[foo*](/uri)
<p>*<a href="/uri">foo*</a></p>
示例 424  (交互)
[foo *bar](baz*)
<p><a href="baz*">foo *bar</a></p>

请注意,属于链接的方括号没有优先级。

示例 425  (交互)
*foo [bar* baz]
<p><em>foo [bar</em> baz]</p>

这些情况说明了 HTML 标签、代码跨度和自动链接优于链接分组的优先级。

示例 426  (交互)
[foo <bar attr="](baz)">
<p>[foo <bar attr="](baz)"></p>
示例 427  (交互)
[foo`](/uri)`
<p>[foo<code>](/uri)</code></p>
示例 428  (交互)
[foo<http://example.com/?search=](uri)>
<p>[foo<a href="http://example.com/?search=%5D(uri)">http://example.com/?search=](uri)</a></p>

引用链接有三种:完整折叠快捷

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

一个 链接标签 以左括号 ([) 开始,并以第一个未被反斜杠转义的右括号 (]) 结束。链接标签 中不允许出现未转义的方括号字符。链接标签内的方括号字符数最多为 999 个。

一个标签 匹配 另一个标签,仅当它们的归一化形式相等时。归一化标签的方法是:执行 Unicode 大小写折叠,并将连续的内部 空白 合并为单个空格。如果存在多个匹配的引用链接定义,则使用文档中首先出现的那个。(在这种情况下发出警告是值得推荐的。)

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

这是一个简单的例子

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

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

链接文本 的规则与 行内链接 的规则相同。因此:

链接文本可以包含平衡的括号,但不能包含不平衡的括号,除非它们经过转义。

示例 430  (交互)
[link [foo [bar]]][ref]

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

[ref]: /uri
<p><a href="/uri">link [bar</a></p>

链接文本可以包含行内内容。

示例 432  (交互)
[link *foo **bar** `#`*][ref]

[ref]: /uri
<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
示例 433  (交互)
[![moon](moon.jpg)][ref]

[ref]: /uri
<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>

但是,链接不得包含其他链接,无论嵌套层级如何。

示例 434  (交互)
[foo [bar](/uri)][ref]

[ref]: /uri
<p>[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
示例 435  (交互)
[foo *bar [baz][ref]*][ref]

[ref]: /uri
<p>[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>

(在上述示例中,我们有两个 快捷引用链接,而不是一个 完整引用链接。)

以下情况说明了链接文本分组优于强调分组的优先级。

示例 436  (交互)
*[foo*][ref]

[ref]: /uri
<p>*<a href="/uri">foo*</a></p>
示例 437  (交互)
[foo *bar][ref]

[ref]: /uri
<p><a href="/uri">foo *bar</a></p>

这些情况说明了 HTML 标签、代码跨度和自动链接优于链接分组的优先级。

示例 438  (交互)
[foo <bar attr="][ref]">

[ref]: /uri
<p>[foo <bar attr="][ref]"></p>
示例 439  (交互)
[foo`][ref]`

[ref]: /uri
<p>[foo<code>][ref]</code></p>
示例 440  (交互)
[foo<http://example.com/?search=][ref]>

[ref]: /uri
<p>[foo<a href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>

匹配时大小写不敏感。

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

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

使用 Unicode 大小写折叠。

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

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

在确定匹配时,连续的内部 空白字符 被视为一个空格。

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

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

链接文本链接标签 之间可以有 空白

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

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

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

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

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

[foo]: /url2

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

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

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

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

链接标签 不能包含括号,除非它们经过反斜杠转义。

示例 448  (交互)
[foo][ref[]

[ref[]: /uri
<p>[foo][ref[]</p>
<p>[ref[]: /uri</p>
示例 449  (交互)
[foo][ref[bar]]

[ref[bar]]: /uri
<p>[foo][ref[bar]]</p>
<p>[ref[bar]]: /uri</p>
示例 450  (交互)
[[[foo]]]

[[[foo]]]: /url
<p>[[[foo]]]</p>
<p>[[[foo]]]: /url</p>
示例 451  (交互)
[foo][ref\[]

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

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

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

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

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

链接标签不区分大小写。

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

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

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

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

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

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

示例 456  (交互)
[foo]

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

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

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

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

链接标签不区分大小写。

示例 460  (交互)
[Foo]

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

链接文本后的空格应予以保留。

示例 461  (交互)
[foo] bar

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

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

示例 462  (交互)
\[foo]

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

请注意,这是一个链接,因为链接标签以第一个随后的闭合方括号结束。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

6.6 图像

图像语法类似于链接语法,但有一点不同。我们拥有的不是 链接文本,而是 图像描述。其规则与 链接文本 相同,除了 (a) 图像描述以 ![ 开头而不是 [,以及 (b) 图像描述可以包含链接。图像描述将行内元素作为其内容。当图像渲染为 HTML 时,这通常用作图像的 alt 属性。

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

[foo *bar*]: train.jpg "train & tracks"
<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
示例 470  (交互)
![foo ![bar](/url)](/url2)
<p><img src="/url2" alt="foo bar" /></p>
示例 471  (交互)
![foo [bar](/url)](/url2)
<p><img src="/url2" alt="foo bar" /></p>

尽管本规范关注的是解析而不是渲染,但建议在渲染为 HTML 时,仅使用 图像描述 的纯字符串内容。请注意,在上面的示例中,alt 属性的值是 foo bar,而不是 foo [bar](/url)foo <a href="/url">bar</a>。只有纯字符串内容被渲染,不带任何格式。

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

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

[FOOBAR]: train.jpg "train & tracks"
<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
示例 474  (交互)
![foo](train.jpg)
<p><img src="train.jpg" alt="foo" /></p>
示例 475  (交互)
My ![foo bar](/path/to/train.jpg  "title"   )
<p>My <img src="/path/to/train.jpg" alt="foo bar" title="title" /></p>
示例 476  (交互)
![foo](<url>)
<p><img src="url" alt="foo" /></p>
示例 477  (交互)
![](/url)
<p><img src="/url" alt="" /></p>

引用式:

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

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

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

折叠式:

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

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

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

标签不区分大小写。

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

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

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

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

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

快捷式:

示例 484  (交互)
![foo]

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

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

请注意,链接标签不能包含未转义的括号。

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

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

链接标签不区分大小写。

示例 487  (交互)
![Foo]

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

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

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

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

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

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

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

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

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

绝对 URI 在此处的定义是由 [方案] 紧随冒号(:)再紧随零个或多个非 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

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

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

大写字母也可以。

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

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

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

反斜杠转义在自动链接内不起作用。

示例 495  (交互)
<http://example.com/\[\>
<p><a href="http://example.com/%5C%5B%5C">http://example.com/\[\</a></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])?)*$/

电子邮件自动链接示例:

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

反斜杠转义在电子邮件自动链接内不起作用。

示例 498  (交互)
<foo\+@bar.example.com>
<p>&lt;foo+@bar.example.com&gt;</p>

这些不是自动链接:

示例 499  (交互)
<>
<p>&lt;&gt;</p>
示例 500  (交互)
<heck://bing.bong>
<p>&lt;heck://bing.bong&gt;</p>
示例 501  (交互)
< http://foo.bar >
<p>&lt; http://foo.bar &gt;</p>
示例 502  (交互)
<foo.bar.baz>
<p>&lt;foo.bar.baz&gt;</p>
示例 503  (交互)
<localhost:5001/foo>
<p>&lt;localhost:5001/foo&gt;</p>
示例 504  (交互)
http://example.com
<p>http://example.com</p>
示例 505  (交互)
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 注释<!-- + 文本 + --> 组成,其中 文本 不能以 >-> 开头,不能以 - 结尾,且不能包含 --。(参见 HTML5 规范。)

一个 处理指令 (processing instruction) 由字符串 <?、一段不包含字符串 ?> 的字符序列,以及字符串 ?> 组成。

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

一个 CDATA 部分 (CDATA section) 由字符串 <![CDATA[、一段不包含字符串 ]]> 的字符序列,以及字符串 ]]> 组成。

一个 HTML 标签开始标签结束标签HTML 注释处理指令声明CDATA 节 组成。

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

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

空元素

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

允许使用 空白字符

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

带有属性

示例 509  (交互)
<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

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

非法属性名称

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

非法属性值

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

非法 空白字符

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

缺失 空白字符

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

结束标签

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

结束标签中的非法属性

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

注释

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

非注释

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

foo <!-- foo--->
<p>foo &lt;!--&gt; foo --&gt;</p>
<p>foo &lt;!-- foo---&gt;</p>

处理指令

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

声明

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

CDATA 部分

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

实体在 HTML 属性中会被保留

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

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

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

6.9 硬换行

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

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

作为一种更直观的替代方案,可以在 行尾 之前使用反斜杠来代替两个空格

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

可以使用超过两个的空格

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

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

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

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

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

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

示例 533  (交互)
`code  
span`
<p><code>code span</code></p>
示例 534  (交互)
`code\
span`
<p><code>code\ span</code></p>

或者 HTML 标签内

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

硬换行用于分隔块内的内联内容。两种硬换行语法在段落或其他块元素的末尾均无效

示例 537  (交互)
foo\
<p>foo\</p>
示例 538  (交互)
foo  
<p>foo</p>
示例 539  (交互)
### foo\
<h3>foo\</h3>
示例 540  (交互)
### foo  
<h3>foo</h3>

6.10 软换行

一个常规换行符(不在代码 span 或 HTML 标签内)如果前面没有两个或更多空格,则被解析为软换行。(软换行在 HTML 中可以渲染为 行尾 或空格。在浏览器中结果是一样的。在此处的例子中,将使用 行尾。)

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

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

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

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

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

6.11 文本内容

上述规则未定义的任何字符将被解析为普通文本内容。

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

内部空格会被逐字保留

示例 545  (交互)
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 或任何其他格式。