代码块

代码块是技术文档的主体。一段 shell 命令、一个配置文件、一段函数实现,如果全都用行内代码塞进句子,读者没法复制,也没法看清缩进。代码块解决的正是这件事:给出一块原样保留、不会被解析的内容。这一页讲清围栏代码块与缩进式代码块两套写法的规则,以及它们放进列表和引用里该怎么缩进。

围栏代码块

用三个反引号把内容夹在中间就能得到一个代码块。围栏的起止反引号数量必须一致,结束围栏要独占一行:

```bash
pnpm install
pnpm build
```

```js
function add(a, b) {
  return a + b;
}
```
<pre><code class="language-bash">pnpm install
pnpm build
</code></pre>
<pre><code class="language-js">function add(a, b) {
  return a + b;
}
</code></pre>

围栏后面紧跟的第一个词是语言标识(info string),它本身不产生视觉变化,只是给渲染器一个提示:这个块该用什么语言来高亮。不写标识的围栏同样成立,只是没有高亮机会:

```
纯文本内容
```
<pre><code>纯文本内容
</code></pre>

围栏可以更长

围栏不止三个反引号。当内容本身就含有三个反引号时(比如讲解 Markdown 语法的文档),把外层围栏加长到四个或更多,解析器就能正确区分:

````markdown
```js
const a = 1;
```

```html
<pre><code class="language-markdown">```js
const a = 1;
```
</code></pre>
```

### 波浪号围栏

用三个波浪号也能开一个围栏,它和反引号围栏等价,区别在于波浪号围栏里可以放心地写反引号:

````markdown
~~~js
const a = "`not a fence`";
~~~
<pre><code class="language-js">const a = "`not a fence`";
</code></pre>

标识后面还能跟东西

语言标识后面允许再跟一段说明,渲染器只取第一个词当作语言,其余部分当作附加信息保留:

```js title="utils.js"
export const noop = () => {};
```
<pre><code class="language-js">export const noop = () => {};
</code></pre>

缩进式代码块

比围栏更古老、也更受限的写法是缩进式代码块:内容整体缩进四个空格或一个制表符,就会被当成代码:

段落

    const a = 1;
<p>段落</p>
<pre><code>const a = 1;
</code></pre>

注意它和围栏的一个本质差别:缩进式代码块无法携带语言标识,生成的 HTML 里也就没有 language- 这个类名,渲染器无从判断用什么语言高亮,所以它只能展示纯文本片段。

更要命的是它和列表会打架:列表项的内容本身就有缩进,再往里缩进四个空格,很容易越过「内容起始列」这条线,结果代码块变成普通段落、段落变成代码块。

代码块放进列表和引用

代码块可以嵌在列表项里,此时要按列表项的内容起始列缩进。- 占两列,所以内容缩进两个空格即可:

- 列表项

  ```js
  const a = 1;
  ```
<ul>
<li>
<p>列表项</p>
<pre><code class="language-js">const a = 1;
</code></pre>
</li>
</ul>

放进引用块里则是每一行都加 > 前缀:

> 引用里的代码:
>
> ```js
> const a = 1;
> ```
<blockquote>
<p>引用里的代码:</p>
<pre><code class="language-js">const a = 1;
</code></pre>
</blockquote>

常见坑

写法实际渲染原因
反引号开、四反引号关不成代码块起止长度必须一致
只有开围栏没有关围栏延伸到文末未闭合的围栏吃到文末
缩进四格写代码代码块没有语言标识,无高亮
列表项里再缩进四格代码块错位应按内容起始列缩进
标识写成 JS可能不识别语言标识区分大小写

练习

把下面这段内容改写成 Markdown,要求:两段代码分别用围栏代码块表示并带上正确的语言标识;第二段代码含有三个反引号,要确保围栏能正确包住它;整段放在一个无序列表项里。

第一步,安装依赖:
pnpm install

第二步,发布:
```
pnpm publish
```
嵌套反引号

解题思路: 围栏代码块用三个反引号起止,闭合围栏要独占一行。难点在第二段:它的内容本身含有三个反引号,若外层也是三个,解析器会在内容里第一个反引号处就闭合,后面的内容就散架了。解法是把外层加长到四个反引号。另外整段放进列表项时,缩进要按列表项的内容起始列来。

详细步骤:

  1. 外层围栏统一用四个反引号,这样内层出现三个反引号时不会被误认为闭合标记。
  2. 第一段代码的语言标识写 bash,内容是 pnpm install。
  3. 第二段代码的语言标识写 bash,内容是三个反引号包住的 pnpm publish。
  4. 整段放进一个无序列表项:列表符号 - 占两列,因此下面所有行都要缩进两个空格。
  5. 检验:渲染后是一个列表项,里面依次是两个代码块;第二个代码块里的三个反引号原样保留,没有把代码块截断。

最终答案:

- 第一步,安装依赖:

  ````bash
  pnpm install
  ````

  第二步,发布:

  ````bash
  ```
  pnpm publish
  ```
  ````

小结

读完这一页,你应当能写出规范、闭合的围栏代码块,能在内容含反引号时主动把围栏加长,能说清缩进式代码块为什么不能带语言标识,也能在「整页都变成代码」时想到围栏没闭合。接下来贴示例代码时,你会先想清楚要不要高亮、缩进几列,再把围栏数量一次写对。

发现内容有问题?

告诉我们哪里需要改进。