如何用 Markdown 编写文档

本页面介绍了我们如何在 MDN Web 文档上使用 Markdown 编写文档。我们选择了 GitHub 风格的 Markdown (GFM) 作为基础,并添加了扩展以支持 MDN 所需的功能。

基础:GitHub 风格的 Markdown

MDN Markdown 的基础是 GitHub 风格的 Markdown (GFM):https://github.github.com/gfm/。这意味着本页面未明确说明的任何内容都可以参考 GFM 规范。GFM 又是 CommonMark 的超集 (https://spec.commonmark.org/)。

GFM 规范定义了两种基本的链接类型

  • 行内链接,其中链接目的地紧跟在链接文本之后给出。
  • 参考链接,其中链接目的地在文档的其他地方定义。

在 MDN 上,我们倾向于使用行内链接,因为它们更容易阅读和维护,而不会丢失上下文。这是在 MDN 上编写链接的首选方式

md
[Macarons](https://en.wikipedia.org/wiki/Macaron) are delicious but tricky to make.

然而,在某些情况下,参考链接因其紧凑性而更合适。例如,缩小宽表格可以使其更容易审阅和编辑。

md
| Name                 | Features                                                                                         |
| -------------------- | ------------------------------------------------------------------------------------------------ |
| [Macarons][macarons] | Delicious but tricky to make. Add more class to a tea party than almost any other confectionary. |
| [Biscotti][biscotti] | Crisp and easier to make.                                                                        |

[macarons]: https://en.wikipedia.org/wiki/Macaron
[biscotti]: https://en.wikipedia.org/wiki/Biscotti

在极少数需要使用参考链接的情况下,请确保它们紧跟在使用它们的上下文之后。

代码块示例

在 GFM 和 CommonMark 中,作者可以使用“代码围栏”来划分 <pre> 块。开头的代码围栏后面可以跟一些文本,这被称为“信息字符串”。代码示例的语言必须使用信息字符串的第一个词指定,这将用于为该块提供语法高亮。支持以下词语

  • 编程语言
    • JavaScript
      • js - JavaScript
      • ts - TypeScript
      • jsx - React JSX
      • tsx - React TSX
    • C 语言家族
      • c - C
      • cpp - C++
      • cs - C#
      • java - Java
    • 其他
      • python - Python
      • php - PHP
      • rust - Rust
      • glsl - GLSL (OpenGL 着色器)
      • sql - SeQueL 命令
      • wat - WebAssembly
      • webidl - Web 接口定义语言
  • 样式
    • css - CSS
    • scss - Sass (SCSS)
    • less - Less
  • 标记语言
    • html - HTML
    • svg - SVG
    • xml - XML
    • mathml - MathML
    • md - Markdown
    • latex - LaTeX
  • 命令提示符
    • bash - Bash/Shell
    • batch - Batch (Windows Shell)
    • powershell - PowerShell
  • 配置/数据文件
    • json - JSON
    • ini - INI
    • yaml - YAML
    • toml - TOML
    • sql - SQL 数据库
    • ignore - Gitignore 文件
    • apacheconf - Apache 配置
    • nginx - NGINX 配置
  • 模板
    • django - Django 模板
    • svelte - Svelte 模板
    • hbs - Handlebars 模板
    • pug - Pug 模板(可由 Express 使用)
  • 其他
    • plain - 纯文本
    • diff - Diff 文件
    • http - HTTP 头部
    • regex - 正则表达式
    • uri - URI 和 URL

例如

md
```js
const greeting = "I will get JavaScript syntax highlighting";
```

如果您希望使用的语法高亮不在上述列表中,您应该将代码块标记为 plain。可以通过 GitHub 上讨论的流程 请求添加其他语言。

注意:请严格按照上面列出的语言标识符使用。例如,不允许使用 javascript,您必须编写 js

禁止代码检查

作者可以向任何语言标识符添加 -nolint 后缀

md
```html-nolint
<p>
I will not be linted.
</p>
```

这样的代码块将获得适当的语法高亮,并会被实时示例系统识别,但会被代码检查工具或 Prettier 等自动格式化工具忽略。作者应使用此后缀来显示无效代码或不应由代码检查工具或格式化工具修复的替代格式。

附加类(信息字符串)

GFM 支持信息字符串,允许作者提供有关代码块的附加信息。在 MDN 上,信息字符串会转换为类名。

作者可以提供以下信息字符串之一

  • example-good:将此示例样式设置为好示例(应遵循的示例)
  • example-bad:将此示例样式设置为坏示例(应避免的示例)
  • hidden:不在页面中渲染此代码块。这用于实时示例。

例如

md
```js example-good
const greeting = "I'm a good example";
```

```js example-bad
const greeting = "I'm a bad example";
```

```js hidden
const greeting = "I'm a secret greeting";
```

这些将渲染为

js
const greeting = "I'm a good example";
js
const greeting = "I'm a bad example";

讨论参考

此问题已解决于

备注、警告和标注

作者可以使用 GFM 警报语法 来特别突出内容。警报分为三种类型:备注、警告和标注。

注意:MDN Web 文档在支持 GFM 警报之前,已支持带有其自身语法的警报,并将其称为“noteblocks”。MDN 不支持以下 GFM 警报:[!TIP][!CAUTION][!IMPORTANT]。GFM 不支持 [!CALLOUT]

  • 要添加备注,请创建一个块引用,其第一行是 [!NOTE]
  • 要添加警告,请创建一个块引用,其第一行是 [!WARNING]
  • 要添加标注,请创建一个块引用,其第一行是 [!CALLOUT]

备注和警告会在输出开头添加本地化的 Note:Warning:,而标注则不会。这使得标注成为作者想要提供自定义标题时的良好选择。

通过块引用中的空行,可以像普通段落一样生成多行。此外,没有空格的多行也像普通 Markdown 行一样处理,并连接起来。

块引用可以包含代码块或其他块元素。

示例

备注

md
> [!NOTE]
> This is how you write a note.
>
> It can have multiple lines.

这将生成以下 HTML

html
<div class="notecard note">
  <p><strong>Note:</strong> This is how you write a note.</p>
  <p>It can have multiple lines.</p>
</div>

此 HTML 将渲染为一个高亮框

注意:这就是如何编写备注。

它可以有多行。

警告

md
> [!WARNING]
> This is how you write a warning.
>
> It can have multiple paragraphs.

这将生成以下 HTML

html
<div class="notecard warning">
  <p><strong>Warning:</strong> This is how you write a warning.</p>
  <p>It can have multiple paragraphs.</p>
</div>

此 HTML 将渲染为一个高亮框

警告:这就是如何编写警告。

它可以有多个段落。

标注

md
> [!CALLOUT]
>
> **This is how you write a callout.**
>
> It can have multiple paragraphs.

这将生成以下 HTML

html
<div class="callout">
  <p><strong>This is how you write a callout.</strong></p>
  <p>It can have multiple paragraphs.</p>
</div>

此 HTML 将渲染为一个高亮框

这就是如何编写标注。

它可以有多个段落。

包含代码块的备注

此示例包含一个代码块。

md
> [!NOTE]
> This is how you write a note.
>
> It can contain code blocks.
>
> ```js
> const s = "I'm in a code block";
> ```
>
> Like that.

这将生成以下 HTML

html
<div class="notecard note">
  <p><strong>Note:</strong> This is how you write a note.</p>
  <p>It can contain code blocks.</p>
  <pre class="brush: js">const s = "I'm in a code block";</pre>
  <p>Like that.</p>
</div>

此 HTML 将与代码块一起渲染

注意:这就是如何编写备注。

它可以包含代码块。

js
const s = "I'm in a code block";

就像这样。

讨论参考

此问题已解决于 https://github.com/mdn/content/issues/3483

定义列表

定义列表在 MDN 中广泛使用,但 GFM 不支持。MDN 引入了一种自定义的定义列表格式,它是 GFM 无序列表 (<ul>) 的修改形式。在此格式中

  • GFM <ul> 包含任意数量的顶级 GFM <li> 元素。
  • 每个顶级 GFM <li> 元素必须包含一个 GFM <ul> 元素作为其最终元素。
  • 这个最终嵌套的 <ul> 必须包含一个 GFM <li> 元素,其文本内容必须以“: ”(冒号后跟一个空格)开头。此元素可以包含块元素,包括段落、代码块、嵌入列表和备注。

这些顶级 GFM <li> 元素中的每一个都将转换为 <dt>/<dd> 对,如下所示

  • 顶级 GFM <li> 元素将被解析为 GFM <li> 元素,其内部内容将构成 <dt> 的内容,但最终嵌套的 <ul> 不会包含在 <dt> 中。
  • 最终嵌套的 <ul> 中的 <li> 元素将被解析为 GFM <li> 元素,其内部内容将构成 <dd> 的内容,但开头的“: ”将被丢弃。

例如,这是一个 <dl>

md
- term1
  - : My description of term1
- `term2`
  - : My description of term2

    It can have multiple paragraphs, and code blocks too:

    ```js
    const thing = 1;
    ```

在 GFM/CommonMark 中,这将生成以下 HTML

html
<ul>
  <li>
    <p>term1</p>
    <ul>
      <li>: My description of term1</li>
    </ul>
  </li>
  <li>
    <p><code>term2</code></p>
    <ul>
      <li>
        <p>: My description of term2</p>
        <p>It can have multiple paragraphs, and code blocks too:</p>
        <pre>
          <code class="brush: js">const thing = 1;</code>
        </pre>
      </li>
    </ul>
  </li>
</ul>

在 MDN 上,这将生成以下 HTML

html
<dl>
  <dt>
    <p>term1</p>
  </dt>
  <dd>My description of term1</dd>
  <dt>
    <p><code>term2</code></p>
  </dt>
  <dd>
    <p>My description of term2</p>
    <p>It can have multiple paragraphs, and code blocks too:</p>
    <pre>
       <code class="brush: js">const thing = 1;</code>
    </pre>
  </dd>
</dl>

使用此语法编写的定义列表必须由 <dt>/<dd> 元素对组成。使用此语法,不可能编写包含多个连续 <dt> 元素或多个连续 <dd> 元素的列表:解析器会将其视为错误。我们预计 MDN 上的几乎所有定义列表都将适用此限制,对于不适用的列表,作者可以回退到原始 HTML。

这是不允许的

md
- `param1`, `param2`, `param3`
  - : My description of `param1`
  - : My description of `param2`
  - : My description of `param3`

作为一种变通方法,当作者需要将多个 <dt> 项与单个 <dd> 关联时,可以考虑将它们作为单个 <dt> 提供,其中包含多个术语,用逗号分隔,如下所示

md
- `param1`, `param2`, `param3`
  - : My description of params 1, 2, and 3

此处描述的语法的理由是,它与期望 CommonMark 的工具(例如 Prettier 或 GitHub 预览)配合得很好,同时编写和解析起来也相当容易。

讨论参考

此问题已解决于 https://github.com/mdn/content/issues/4367

表格

GFM 提供了创建表格的语法,我们在 MDN 中使用了它。然而,有时 GFM 表格不符合我们的需求

  • GFM 语法仅支持 HTML 中可用功能的一个子集。如果您需要使用 GFM 不支持的表格功能,请使用 HTML 来创建表格。
  • 如果表格的 GFM 表示形式宽度超过 150 个字符,请使用 HTML 来创建表格。
  • 我们支持一种特殊类型的表格,称为“属性表”,它有自己的 CSS 类,因此始终是 HTML。

因此,一般原则是,作者应尽可能使用 GFM Markdown 语法,并在必要时或 HTML 更具可读性时回退到原始 HTML。有关更多信息,请参阅何时使用 HTML 表格

GFM 表格语法样式

在 GFM 表格语法中,作者可以省略行的开头和结尾管道符。然而,为了可读性,MDN 作者必须包含这些管道符。此外,作者必须在行中提供尾随空格,以便列中的所有单元格在纯文本中长度相同。

也就是说,MDN 作者必须使用这种样式

md
| Heading 1 | Heading 2 | Heading 3 |
| --------- | --------- | --------- |
| cell 1    | cell 2    | cell 3    |
| cell 4    | cell 5    | cell 6    |

而不是这种样式

md
| Heading 1 | Heading 2 | Heading 3 |
| --------- | --- |----------------------|
| cell 1 | cell 2 | cell 3 |
cell 4 | cell 5 | cell 6

表格由 Prettier 格式化,因此作者依赖工具来正确格式化表格。

何时使用 HTML 表格

作者应使用 HTML 表格而非 GFM 语法的三种主要情况

  1. 表格使用了 GFM 不支持的功能(见下文)。
  2. GFM 表格太宽而无法阅读。
  3. 作者需要一种特殊类型的表格,称为“属性表”。

GFM 不支持的表格功能

GFM 表格语法的主要限制是

  • GFM 表格必须有标题行。
  • GFM 表格不能有标题列。
  • GFM 不会解析表格单元格中的 GFM 块元素。例如,您不能在表格单元格中包含列表。
  • GFM 表格无法分配类。
  • GFM 不支持 <table><tr><th><td> 以外的任何表格元素。
  • GFM 不支持任何表格元素属性,如 colspanrowspanscope

如果作者需要使用任何不支持的功能,他们应该用 HTML 编写表格。

请注意,我们不建议在表格中普遍使用 <caption> 元素,因为这也会排除 GFM 语法。

GFM 表格最大宽度

即使表格可以用 GFM 编写,有时使用 HTML 也会更好,因为 GFM 对表格采用“ASCII 艺术”方法,当表格行很长时不易阅读。考虑以下表格

html
<table>
  <tr>
    <th>A heading 1</th>
    <th>A heading 2</th>
    <th>A heading 3</th>
    <th>A heading 4</th>
    <th>A heading 5</th>
    <th>A heading 6</th>
  </tr>
  <tr>
    <td>Something shortish</td>
    <td>
      Something much longer that really goes into a lot of detail about
      something, so much so that the table formatting starts to look bad in GFM
      format.
    </td>
    <td>Something shortish</td>
    <td>
      Another cell with lots of text in it, that also really goes into a lot of
      detail about something, so much so that the table formatting starts to
      look bad in GFM format.
    </td>
    <td>Something shortish</td>
    <td>Something shortish</td>
  </tr>
</table>

在 GFM 中,它看起来像

md
| A heading 1        | A heading 2                                                                                                                                         | A heading 3        | A heading 4                                                                                                                                                              | A heading 5        | A heading 6        |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------ | ------------------ |
| Something shortish | Something much longer that really goes into a lot of detail about something, so much so that the table formatting starts to look bad in GFM format. | Something shortish | Another cell with lots of text in it, that also really goes into a lot of detail about something, so much so that the table formatting starts to look bad in GFM format. | Something shortish | Something shortish |

在这种情况下,最好使用 HTML。

这导致了以下指导原则:如果表格的 Markdown 表示形式宽度超过 150 个字符,请使用 HTML 来创建表格

属性表

属性表是一种特定类型的表格,用于在特定类型的一组页面中显示结构化的属性-值内容。这些表格有两列:第一列是标题列,列出属性;第二列列出此特定项的值。例如,以下是 PannerNode 接口的属性表

输入数量 1
输出数量 0
通道计数模式 “explicit”
声道数 2
通道解释 “speakers”

这些页面无法在 GFM 中表示,因为它们有标题列,因此作者在这种情况下应使用 HTML。为了获得特殊样式,作者应将 "properties" 类应用于表格

html
<table class="properties"></table>

讨论参考

此问题已解决于 https://github.com/mdn/content/issues/4325https://github.com/mdn/content/issues/7342https://github.com/mdn/content/issues/7898#issuecomment-913265900

上标和下标

作者在必要时可以使用 HTML <sup><sub> 元素,但如果可能,应使用替代方案。特别是

  • 对于幂运算,使用 ^ 符号:2^53
  • 对于序数表达式,如 1st,更倾向于使用“first”这样的单词。
  • 对于脚注,不要标记脚注引用,例如 <sup>[1]</sup>

讨论参考

此问题已解决于 https://github.com/mdn/content/issues/4578

页面摘要

页面摘要是页面中的第一个“内容”段落——出现在页面前言和任何侧边栏页面横幅宏之后的第一个文本。

此摘要用于搜索引擎优化 (SEO),并且也由某些宏自动包含在页面列表中。因此,第一个段落应该既简洁又富有信息。

讨论参考

此问题已解决于 https://github.com/mdn/content/issues/3923

作者在散文中使用宏来模板化常见的链接模式,或包含特定的代码块或文本

md
The **`margin`** [CSS](/en-US/docs/Web/CSS) property sets the margin area on all four sides of an element.
It is a shorthand for {{cssxref("margin-top")}}, {{cssxref("margin-right")}}, {{cssxref("margin-bottom")}}, and {{cssxref("margin-left")}}.
…

有关更多信息,请参阅使用宏