跳到主要内容

3、代码块

代码块

文档中的代码块功能非常强大。

代码标题

你可以通过在语言后面添加 title 键(在它们之间留一个空格)来向代码块添加标题。

```jsx title="/src/components/HelloCodeTitle.js"
function HelloCodeTitle(props) {
return <h1>Hello, {props.name}</h1>;
}
```

http://localhost:3000

typora效果:

image-20240914213556998

docus渲染后效果:

image-20240914213516002

语法高亮

代码块是由 3 个反引号字符串包围的文本块。MDX 的规范可以查看 这个参考

```js
console.log('Every repo must come with a mascot.');
```

使用代码块的匹配语言元字符串,Docusaurus 将自动选择语法高亮,由 Prism React 渲染器 提供支持。

http://localhost:3000

console.log('Every repo must come with a mascot.');

image-20240914213647771

主题化

默认情况下,我们使用的 Prism 语法高亮主题苍夜。你可以通过在 docusaurus.config.js 中将 prism 中的 theme 字段作为 themeConfig 传递来将其更改为另一个主题。

例如,如果你更喜欢使用 dracula 高亮主题:

docusaurus.config.js

import {themes as prismThemes} from 'prism-react-renderer';

export default {
themeConfig: {
prism: {
theme: prismThemes.dracula,
},
},
};

因为 Prism 主题只是一个 JS 对象,所以如果你对默认主题不满意,也可以编写自己的主题。Docusaurus 增强了 githubvsDark 主题以提供更丰富的亮点,你可以查看我们对 lightdark 代码块主题的实现。

支持的语言

默认情况下,Docusaurus 附带 常用语言 的子集。

注意

默认情况下不启用一些流行语言,例如 Java、C# 或 PHP。

要为任何其他 Prism 支持的语言 添加语法高亮,请在其他语言数组中定义它。

信息

每种附加语言都必须是有效的 Prism 组件名称。例如,Prism 会将语言 cs 映射到 csharp,但只有 prism-csharp.js 作为组件存在,因此你需要使用 additionalLanguages: ['csharp']。你可以查看 node_modules/prismjs/components 以查找所有可用的组件(语言)。

例如,如果你想为 PowerShell 语言添加高亮:

docusaurus.config.js

export default {
// ...
themeConfig: {
prism: {
additionalLanguages: ['powershell'],
},
// ...
},
};

添加 additionalLanguages 后,重新启动 Docusaurus。

如果你想为 Prism 尚不支持的语言添加高亮,你可以 swizzle prism-include-languages

提示
npm run swizzle @docusaurus/theme-classic prism-include-languages

它将在你的 src/theme 文件夹中生成 prism-include-languages.js。你可以通过编辑 prism-include-languages.js 添加对自定义语言的高亮支持:

src/theme/prism-include-languages.js

const prismIncludeLanguages = (Prism) => {
// ...

additionalLanguages.forEach((lang) => {
require(`prismjs/components/prism-${lang}`);
});

require('/path/to/your/prism-language-definition');

// ...
};

当你编写自己的语言定义时,可以参考 Prism 的官方语言定义

添加自定义语言定义时,你不需要将语言添加到 additionalLanguages 配置数组,因为 Docusaurus 仅查找 Prism 提供的语言中的 additionalLanguages 字符串。在 prism-include-languages.js 中添加语言导入就足够了。

线条高亮

高亮并附有注释

你可以使用带有 highlight-next-linehighlight-starthighlight-end 的注释来选择高亮的行。

```js
function HighlightSomeText(highlight) {
if (highlight) {
return 'This text is highlighted!';
}

return 'Nothing highlighted';
}

function HighlightMoreText(highlight) {
if (highlight) {
return 'This range is highlighted!';
}

return 'Nothing highlighted';
}
```

http://localhost:3000

image-20240914214431893

支持的注释语法:

风格语法
C 型/* ... */// ...
JSX 风格{/* ... */}
Bash 风格# ...
HTML 风格<!-- ... -->

我们会尽力根据语言推断使用哪一组注释样式,并默认允许所有注释样式。如果当前不支持注释样式,我们愿意添加它们!欢迎拉请求。请注意,不同的注释风格没有语义差异,只有内容不同。

你可以为 src/css/custom.css 中高亮的代码行设置自己的背景颜色,这将更好地适合你选择的语法高亮主题。下面给出的颜色适用于默认的高亮主题 (Palenight),因此如果你使用其他主题,则必须相应地调整颜色。

/src/css/custom.css

:root {
--docusaurus-highlighted-code-line-bg: rgb(72, 77, 91);
}

/* If you have a different syntax highlighting theme for dark mode. */
[data-theme='dark'] {
/* Color which works with dark mode syntax highlighting theme */
--docusaurus-highlighted-code-line-bg: rgb(100, 100, 100);
}

如果你还需要以其他方式设置高亮的代码行的样式,则可以针对 theme-code-block-highlighted-line CSS 类。

使用元数据字符串高亮

你还可以在语言元字符串中指定高亮的行范围(在语言后面留一个空格)。要高亮多行,请用逗号分隔行号或使用范围语法来选择一行块。此功能使用 parse-number-range 库,你可以在其项目详细信息中找到 更多语法

```jsx {1,4-6,11}
import React from 'react';

function MyComponent(props) {
if (props.isBar) {
return <div>Bar</div>;
}

return <div>Foo</div>;
}

export default MyComponent;
```

http://localhost:3000

image-20240915110035620

更喜欢注释

最好尽可能用注释来高亮。通过在代码中内联高亮,如果代码块变长,你不必手动计算行数。如果你添加/删除行,你也不必偏移行范围。

- ```jsx {3}
+ ```jsx {4}
function HighlightSomeText(highlight) {
if (highlight) {
+ console.log('Highlighted text found');
return 'This text is highlighted!';
}

return 'Nothing highlighted';
}
```

下面,我们将介绍如何扩展魔法注释系统来定义自定义指令及其功能。仅当高亮元字符串不存在时才会解析魔术注释。

自定义魔法注释

// highlight-next-line// highlight-start 等被称为 "神奇的注释",因为它们将被解析和删除,它们的目的是将元数据添加到下一行,或一对开始和结束注释所包含的部分。

你可以通过主题配置声明自定义魔法注释。例如,你可以注册另一个添加 code-block-error-line 类名的魔术注释:

提示
export default {
themeConfig: {
prism: {
magicComments: [
// Remember to extend the default highlight class name as well!
{
className: 'theme-code-block-highlighted-line',
line: 'highlight-next-line',
block: {start: 'highlight-start', end: 'highlight-end'},
},
{
className: 'code-block-error-line',
line: 'This will error',
},
],
},
},
};

http://localhost:3000

在 JavaScript 中,尝试访问 null 上的属性将会出错。

image-20240915111116492


如果你在元字符串({1,3-4} 语法)中使用数字范围,Docusaurus 将应用第一个 magicComments 条目的类名称。默认情况下,这是 theme-code-block-highlighted-line,但如果你更改 magicComments 配置并使用不同的条目作为第一个条目,元字符串范围的含义也会改变。

你可以使用 magicComments: [] 禁用默认行高亮注释。如果没有魔法注释配置,但 Docusaurus 遇到包含元字符串范围的代码块,它将出错,因为没有可应用的类名 - 毕竟,高亮的类名只是一个魔法注释条目。

每个神奇的注释条目将包含三个键:className(必需)、line(适用于直接下一行)或 block(包含 startend)(适用于两个注释所包围的整个块)。

使用 CSS 来定位类已经可以做很多事情,但是你可以通过 swizzling 释放此功能的全部潜力。

提示
npm run swizzle @docusaurus/theme-classic CodeBlock/Line

Line 组件将接收类名列表,你可以根据该列表有条件地渲染不同的标记。

行编号

你可以通过在语言元字符串中使用 showLineNumbers 键来为代码块启用行编号(不要忘记在该键之前直接添加空格)。

```jsx {1,4-6,11} showLineNumbers
import React from 'react';

function MyComponent(props) {
if (props.isBar) {
return <div>Bar</div>;
}

return <div>Foo</div>;
}

export default MyComponent;
```

http://localhost:3000

image-20240915111755654

交互式代码编辑器

(由 React Live 提供支持)

你可以使用 @docusaurus/theme-live-codeblock 插件创建交互式编码编辑器。首先,将插件添加到你的包中。

  • npm
  • Yarn
  • pnpm
pnpm add @docusaurus/theme-live-codeblock

你还需要将该插件添加到你的 docusaurus.config.js

export default {
// ...
themes: ['@docusaurus/theme-live-codeblock'],
// ...
};

要使用该插件,请创建一个代码块,并将 live 附加到语言元字符串。

```jsx live
function Clock(props) {
const [date, setDate] = useState(new Date());
useEffect(() => {
const timerID = setInterval(() => tick(), 1000);

return function cleanup() {
clearInterval(timerID);
};
});

function tick() {
setDate(new Date());
}

return (
<div>
<h2>It is {date.toLocaleTimeString()}.</h2>
</div>
);
}
```

代码块将渲染为交互式编辑器。对代码的更改将实时反映在结果面板上。

http://localhost:3000

LIVE EDITOR

function Clock(props) {
const [date, setDate] = useState(new Date());
useEffect(() => {
const timerID = setInterval(() => tick(), 1000);

return function cleanup() {
clearInterval(timerID);
};
});

function tick() {
setDate(new Date());
}

return (
<div>
<h2>It is {date.toLocaleTimeString()}.</h2>
</div>
);
}

RESULT

It is 21:31:39.

导入

REACT-LIVE 并导入

无法直接从 React-Live 代码编辑器导入组件,你必须预先定义可用的导入。

默认情况下,所有 React 导入都可用。如果你需要更多可用的导入,请调整 react-live 范围:

  • npm
  • Yarn
  • pnpm
pnpm run swizzle @docusaurus/theme-live-codeblock ReactLiveScope --eject

src/theme/ReactLiveScope/index.js

import React from 'react';

const ButtonExample = (props) => (
<button
{...props}
style={{
backgroundColor: 'white',
color: 'black',
border: 'solid red',
borderRadius: 20,
padding: 10,
cursor: 'pointer',
...props.style,
}}
/>
);

// Add react-live imports you need here
const ReactLiveScope = {
React,
...React,
ButtonExample,
};

export default ReactLiveScope;

ButtonExample 组件现在可供使用:

http://localhost:3000

LIVE EDITOR

function MyPlayground(props) {
return (
<div>
<ButtonExample onClick={() => alert('hey!')}>Click me</ButtonExample>
</div>
);
}

RESULT

Click me

命令式渲染(noInline)

当代码跨越多个组件或变量时,应使用 noInline 选项来避免错误。

```jsx live noInline
const project = 'Docusaurus';

const Greeting = () => <p>Hello {project}!</p>;

render(<Greeting />);
```

与普通的交互式代码块不同,使用 noInline React Live 时不会将代码封装在内联函数中来渲染它。

你需要在代码末尾显式调用 render() 才能显示输出。

http://localhost:3000

jsx live noInline const 项目 = "Docusaurus";

¥jsx live noInline
const project = "Docusaurus";

const 问候语 = () => ( <p>Hello {project}!</p> );

¥const Greeting = () => (
<p>Hello {project}!</p>
);

使成为(

¥render(

<Greeting />

);
## 在代码块中使用 JSX 标记 \{#using-jsx-markup-in-code-blocks}

¥Using JSX markup in code blocks

Markdown 中的代码块始终将其内容保留为纯文本,这意味着你不能执行以下操作:

¥Code block in Markdown always preserves its content as plain text, meaning you can't do something like:

```ts
type EditUrlFunction = (params: {
// This doesn't turn into a link (for good reason!)
version: <a href="/docs/versioning">Version</a>;
versionDocsDirPath: string;
docPath: string;
permalink: string;
locale: string;
}) => string | undefined;

如果要嵌入 HTML 标记(例如锚链接或粗体类型),可以使用 <pre> 标签、<code> 标签或 <CodeBlock> 组件。

<pre>
<b>Input: </b>1 2 3 4{'\n'}
<b>Output: </b>"366300745"{'\n'}
</pre>

http://localhost:3000

Input: 1 2 3 4
Output: "366300745"

MDX 对空格不敏感

MDX 与 JSX 行为一致:换行符,即使在 <pre> 内,也会变成空格。你必须显式地编写换行符才能将其打印出来。

警告

语法高亮仅适用于纯字符串。Docusaurus 不会尝试解析包含 JSX 子项的代码块内容。

多语言支持代码块

使用 MDX,你可以轻松地在文档中创建交互式组件,例如,以多种编程语言显示代码并使用选项卡组件在它们之间进行切换。

我们没有为多语言支持代码块实现专用组件,而是在经典主题中实现了通用的 `` 组件,以便你也可以将其用于其他非代码场景。

以下示例介绍了如何在文档中拥有多语言代码选项卡。请注意,每个语言块上方和下方的空行是故意的。这是 MDX 当前的限制:你必须在 Markdown 语法周围留下空行,以便 MDX 解析器知道它是 Markdown 语法而不是 JSX。

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

<Tabs>
<TabItem value="js" label="JavaScript">

```js
function helloWorld() {
console.log('Hello, world!');
}
```

</TabItem>
<TabItem value="py" label="Python">

```py
def hello_world():
print("Hello, world!")
```

</TabItem>
<TabItem value="java" label="Java">

```java
class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello, World");
}
}
```

</TabItem>
</Tabs>

你将得到以下信息:

¥And you will get the following:

<BrowserWindow>
<Tabs>
<TabItem value="js" label="JavaScript">

```js
function helloWorld() {
console.log('Hello, world!');
}
```

</TabItem>
<TabItem value="py" label="Python">

```py
def hello_world():
print("Hello, world!")
```

</TabItem>
<TabItem value="java" label="Java">

```java
class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello, World");
}
}
```

</TabItem>
</Tabs>
</BrowserWindow>

如果你有多个这样的多语言代码选项卡,并且你想要跨选项卡实例同步选择,请参阅 [同步选项卡选择部分](markdown-features-tabs.mdx#syncing-tab-choices)

¥If you have multiple of these multi-language code tabs, and you want to sync the selection across the tab instances, refer to the [Syncing tab choices section](markdown-features-tabs.mdx#syncing-tab-choices).

### Docusaurus npm2yarn remark 插件 \{#docusaurus-npm2yarn-remark-plugin}

¥Docusaurus npm2yarn remark plugin

在 npm 和 Yarn 中显示 CLI 命令是一种非常常见的需求,例如:

¥Displaying CLI commands in both npm and Yarn is a very common need, for example:

```bash npm2yarn
npm install @docusaurus/remark-plugin-npm2yarn
```

Docusaurus 提供了这样一个开箱即用的实用程序,使你不必每次都使用 `Tabs` 组件。要启用此功能,首先如上安装 `@docusaurus/remark-plugin-npm2yarn` 软件包,然后在 `docusaurus.config.js` 中,对于需要此功能的插件(文档、博客、页面等),将其注册到 `remarkPlugins` 选项中。(配置格式详见 [文档配置](../../api/plugins/plugin-content-docs.mdx#ex-config)

¥Docusaurus provides such a utility out of the box, freeing you from using the `Tabs` component every time. To enable this feature, first install the `@docusaurus/remark-plugin-npm2yarn` package as above, and then in `docusaurus.config.js`, for the plugins where you need this feature (doc, blog, pages, etc.), register it in the `remarkPlugins` option. (See [Docs configuration](../../api/plugins/plugin-content-docs.mdx#ex-config) for more details on configuration format)

```js title="docusaurus.config.js"
export default {
// ...
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
remarkPlugins: [
[require('@docusaurus/remark-plugin-npm2yarn'), {sync: true}],
],
},
pages: {
remarkPlugins: [require('@docusaurus/remark-plugin-npm2yarn')],
},
blog: {
remarkPlugins: [
[
require('@docusaurus/remark-plugin-npm2yarn'),
{converters: ['pnpm']},
],
],
// ...
},
},
],
],
};
```

然后通过将 `npm2yarn` 键添加到代码块来使用它:

¥And then use it by adding the `npm2yarn` key to the code block:

````md
```bash npm2yarn
npm install @docusaurus/remark-plugin-npm2yarn
```

配置

选项类型默认描述
syncbooleanfalse是否在所有代码块之间同步选定的转换器。
convertersarray'yarn''pnpm'要使用的转换器列表。转换器的顺序很重要,因为第一个转换器将用作默认选择。

在 JSX 中的用法

在 Markdown 之外,你可以使用 @theme/CodeBlock 组件来获得相同的输出。

import CodeBlock from '@theme/CodeBlock';

export default function MyReactPage() {
return (
<div>
<CodeBlock
language="jsx"
title="/src/components/HelloCodeTitle.js"
showLineNumbers>
{`function HelloCodeTitle(props) {
return <h1>Hello, {props.name}</h1>;
}`}
</CodeBlock>
</div>
);
}

http://localhost:3000

/src/components/HelloCodeTitle.js

function HelloCodeTitle(props) {
return <h1>Hello, {props.name}</h1>;
}

接受的 props 是 languagetitleshowLineNumbers,与编写 Markdown 代码块的方式相同。

尽管不鼓励,你也可以传递像 metastring='{1-2} title="/src/components/HelloCodeTitle.js" showLineNumbers' 这样的 metastring 属性,这就是 Markdown 代码块在底层的处理方式。不过,我们推荐你 使用注释来高亮行

前面说过 一样,仅当子项是简单字符串时才应用语法高亮。