代码块
代码块是技术文档的主体。一段 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
```
解题思路: 围栏代码块用三个反引号起止,闭合围栏要独占一行。难点在第二段:它的内容本身含有三个反引号,若外层也是三个,解析器会在内容里第一个反引号处就闭合,后面的内容就散架了。解法是把外层加长到四个反引号。另外整段放进列表项时,缩进要按列表项的内容起始列来。
详细步骤:
- 外层围栏统一用四个反引号,这样内层出现三个反引号时不会被误认为闭合标记。
- 第一段代码的语言标识写
bash,内容是pnpm install。 - 第二段代码的语言标识写
bash,内容是三个反引号包住的pnpm publish。 - 整段放进一个无序列表项:列表符号
-占两列,因此下面所有行都要缩进两个空格。 - 检验:渲染后是一个列表项,里面依次是两个代码块;第二个代码块里的三个反引号原样保留,没有把代码块截断。
最终答案:
- 第一步,安装依赖:
````bash
pnpm install
````
第二步,发布:
````bash
```
pnpm publish
```
````读完这一页,你应当能写出规范、闭合的围栏代码块,能在内容含反引号时主动把围栏加长,能说清缩进式代码块为什么不能带语言标识,也能在「整页都变成代码」时想到围栏没闭合。接下来贴示例代码时,你会先想清楚要不要高亮、缩进几列,再把围栏数量一次写对。
