代码块
文档中的代码块超级厉害 💪。
代码标题
你可以在语言后添加 title
(记得在语言和 title 之间加一个空格)来设置标题。
```jsx title="/src/components/HelloCodeTitle.js"
function HelloCodeTitle(props) {
return <h1>你好,{props.name}</h1>;
}
```
function HelloCodeTitle(props) {
return <h1>你好,{props.name}</h1>;
}
语法高亮
代码块是使用 3 个反引号包裹的文本块。 你可以参阅 MDX 的规范。
```js
console.log('每个仓库都应该有个吉祥物。');
```
在代码块中使用相应语言的标签,Docusaurus 会自动用 Prism React Renderer 选择相应的语法高亮。
console.log('每个仓库都应该有个吉祥物。');
高亮主题
默认情况下,我们使用 Palenight 作为 Prism 语法高亮主题。 你可以通过 docusaurus.config.js 中的 themeConfig.prism
的 theme
字段来更改主题。
举个例子,如果你喜欢 dracula
高亮主题:
import {themes as prismThemes} from 'prism-react-renderer';
export default {
themeConfig: {
prism: {
theme: prismThemes.dracula,
},
},
};
因为每个 Prism 主题都只是一个 JS 对象,所以如果你对默认值不满意,也可以写一个自己的主题。 Docusaurus 对 github
和 vsDark
主题进行了增强,以提供更丰富的高亮效果,你还可以查看我们对浅色和深色代码块主题的实现。
支持的语言
默认情况下,Docusaurus 附带了一些常用语言的子集。
一些流行语言,包括 Java、C#、PHP 在内,默认未启用。
要添加其他 Prism 所支持的语言的代码高亮,请定义在 additionalLanguages
列表中。
每个附加语言都必须是有效的 Prism 组件名称。 比如, Prism 会把 cs
这个_语言_映射到 csharp
,但只有 prism-csharp.js
才是真实存在的_组件_,所以你需要写 additionalLanguages: ['csharp']
。 你可以翻看 node_modules/prismjs/components
来找到所有可用的组件(和对应语言)。
举个例子,如果你想要支持 PowerShell 语言的高亮:
export default {
// ...
themeConfig: {
prism: {
additionalLanguages: ['powershell'],
},
// ...
},
};
添加 additionalLanguages
后,重启 Docusaurus。
如果你想添加 Prism 所不支持语言的语法高亮功能,你可以 swizzle prism-include-languages
:
- npm
- Yarn
- pnpm
npm run swizzle @docusaurus/theme-classic prism-include-languages
yarn swizzle @docusaurus/theme-classic prism-include-languages
pnpm run swizzle @docusaurus/theme-classic prism-include-languages
这个命令会在你的 src/theme
目录下生成 prism-include-languages.js
。 你也可以通过编辑 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-line
, highlight-start
, 和 highlight-end
来选中哪些行可以被高亮。
```js
function HighlightSomeText(highlight) {
if (highlight) {
// highlight-next-line
return '这行被高亮了!';
}
return '这里不会';
}
function HighlightMoreText(highlight) {
// highlight-start
if (highlight) {
return '这块被高亮了!';
}
// highlight-end
return '这里不会';
}
```
function HighlightSomeText(highlight) {
if (highlight) {
return '这行被高亮了!';
}
return '这里不会';
}
function HighlightMoreText(highlight) {
if (highlight) {
return '这段被高亮了!';
}
return '这里不会';
}
受支持的注释语法:
样式 | 语法 |
---|---|
C 样式 | /* ... */ 及 // ... |
JSX 样式 | {/* ... */} |
Bash 样式 | # ... |
HTML 样式 | <!-- ... --> |
我们会尽可能地根据语言来推断注释风格的样式,默认情况下允许_所有的_注释风格。 如果有任何注释风格暂时没有被支持,我们乐意去添加对它们的支持。 欢迎发起拉取请求。 需要注意的是,不同注释风格不会有语义上的差别,只会有内容上的。
你可以在你的自定义样式文件 src/css/custom.css
中为高亮的代码行设置自己的背景颜色,让它更适合你选定的语言高亮主题。 下方的颜色适用于默认的语法高亮主题(Palenight)。如果你使用其他的主题,也需要做出相应的颜色调整。
:root {
--docusaurus-highlighted-code-line-bg: rgb(72, 77, 91);
}
/* 如果你在暗黑模式用了不同的语法高亮主题。 */
[data-theme='dark'] }
/* 暗黑模式高亮主题下用的背景色 */
--docusaurus-highed code-bg: rgb(100, 100);
}
如果你还需要给高亮代码行加其他样式,你可以使用 theme-block-high-lighted-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;
```
import React from 'react';
function MyComponent(props) {
if (props.isBar) {
return <div>Bar</div>;
}
return <div>Foo</div>;
}
export default MyComponent;
推荐你使用注释来实现语法高亮。 如果你把通过内嵌的注释来高亮代码,你就不需要在代码块内容很长时手动去数代码行数了。 即使你添加/删除了某几行,你也不需要去调整行号的偏移范围。
- ```jsx {3}
+ ```jsx {4}
function HighlightSomeText(highlight) {
if (highlight) {
+ console.log('找到了高亮文本');
return '这个文本高亮了!';
}
return '没啥被高亮了';
}
```
下面我们将介绍可扩展的魔法注释是如何实现自定义指令及和功能的。 只有在不使用元数据字符串的数字范围时,魔法注释才会被解析。
自定义魔法注释
// highlight-next-line
和 // highlight-start
等注释方式被称作“魔法注释”,因为它们被用于为下一行添加元数据,或者为开始注释和结束注释之间的代码行添加元数据,它们会在被解析之后从代码块中删除。
你可以通过主题配置来设定你的自定义魔法注释。 例如,你可以通过注册另一个包含有 code-block-error-line
类名的魔法注释:
- docusaurus.config.js
- src/css/custom.css
- myDoc.md
export default {
themeConfig: {
prism: {
magicComments: [
// 记住也要扩展默认高亮类名称!
{
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',
},
],
},
},
};
.code-block-error-line {
background-color: #ff000020;
display: block;
margin: 0 calc(-1 * var(--ifm-pre-padding));
padding: 0 var(--ifm-pre-padding);
border-left: 3px solid #ff000080;
}
在 JavaScript 中,试图访问 `null` 的属性会报错。
```js
const name = null;
// This will error
console.log(name.toUpperCase());
// Uncaught TypeError: Cannot read properties of null (reading 'toUpperCase')
```
在 JavaScript 中,试图访问 null
上的属性时会报错。
const name = null;
console.log(name.toUpperCase());
// Uncaught TypeError: Cannot read properties of null (reading 'toUpperCase')
如果你在元数据字符串中用了数字范围(类似于 {1,3-4}
这种语法),Docusaurus 会使用 **magicComments
字段中第一项的 className ** 作为类名。 默认情况下,类名使用的是 theme-code-block-highlighted-line
,但如果你修改了配置中 magicComments
中的配置项,并且使用了不同的项目作为第一项的值,那么元数据字符串中数字范围的类名也会根据第一项的值而改变。
你可以通过设置 magicComments: []
来禁用默认的高亮注释样式。 如果魔法注释的配置是空数组,但使用了一个包含数字范围的代码块时,Docusaurus 就会报错,因为没有可以应用给类名的配置项——高亮的类名毕竟只是一个魔法注释配置的项目而已。
每个魔法注释的配置项会包含三个字段:classname
(必填);line
,会应用于魔法注释的下一行;block
字段(包含 start
和 end
两个字段),会应用于两个魔法注释所包裹的整个片段。
用 CSS 类名指定样式已经足够做很多事情了,但你可以通过 swizzling 来解锁这个功能的完整能力。
- npm
- Yarn
- pnpm
npm run swizzle @docusaurus/theme-classic CodeBlock/Line
yarn swizzle @docusaurus/theme-classic CodeBlock/Line
pnpm 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;
```
import React from 'react';
function MyComponent(props) {
if (props.isBar) {
return <div>Bar</div>;
}
return <div>Foo</div>;
}
export default MyComponent;
交互式代码编辑器
(由 React Live 驱动)
你可以通过 @docusaurus/theme-live-codeblock
插件创建可交互的代码编辑器, 首先,将插件添加到您的项目依赖。
- npm
- Yarn
- pnpm
npm install --save @docusaurus/theme-live-codeblock
yarn add @docusaurus/theme-live-codeblock
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>现在是 {date.toLocaleTimeString()}。</h2>
</div>
);
}
```
这个代码块会被渲染成一个可交互的代码编辑器。 代码的变更结果将会实时显示在结果的预览区域。
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>现在是 {date.toLocaleTimeString()}。</h2> </div> ); }
导入
你不能从 react-live 的代码编辑器中直接导入组件。你得显式地预先定义好所有组件导入项。
默认情况下,你可以使用 React 的所有导入项。 如果你需要更多可导入项,你通过 swizzle 组件 react-live scope 来获取:
- npm
- Yarn
- pnpm
npm run swizzle @docusaurus/theme-live-codeblock ReactLiveScope -- --eject
yarn swizzle @docusaurus/theme-live-codeblock ReactLiveScope --eject
pnpm run swizzle @docusaurus/theme-live-codeblock ReactLiveScope --eject
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,
}}
/>
);
// 在这里添加你需要的 react-live 导入项
const ReactLiveScope = {
React,
...React,
ButtonExample,
};
export default ReactLiveScope;
现在 ButtonExample
可以提供使用了。
function MyPlayground(props) { return ( <div> <ButtonExample {() => alert('hey!')}>点我</ButtonExample> </div> ); }
命令式渲染 (noInline)
如果你的代码涉及到跨行的多个组件或变量,你需要添加 noInline
项来避免报错。
```jsx live noInline
const project = 'Docusaurus';
const Greeting = () => <p>Hello {project}!</p>;
render(<Greeting />);
```
与普通交互式代码块不同,当使用 noInline
项时,React Live 不会把你的代码包裹在行内函数直接渲染。
你需要在代码块的末尾显式地调用 render()
来渲染结果。
const project = "Docusaurus"; const Greeting = () => ( <p>Hello {project}!</p> ); render( <Greeting /> );
在代码块中使用 JSX 标记
Markdown 中的代码块总是将其内容作为纯文本保留,这意味着你不能像下面这样这么写:
type EditUrlFunction = (params: {
// 这不会变成链接(很有道理!)
version: <a href="/docs/versioning">Version</a>;
versionDocsDirPath: string;
docPath: string;
permalink: string;
locale: string;
}) => string | undefined;
如果你想内嵌 HTML 标签,比如链接或者粗体,你可以用 <pre>
标签、<code>
标签、或 <CodeBlock>
组件。
<pre>
<b>输入:</b>1 2 3 4{'\n'}
<b>输出:</b>"366300745"{'\n'}
</pre>
Input: 1 2 3 4 Output: "366300745"
MDX 与 JSX 行为一致:即使在 <pre>
内,换行符也会转换成空格。 你必须显式地写一个换行符,它才会真的显示成换行效果。
语法高亮只适用于纯字符串。 Docusaurus 不会试图解析代码块里包含的 JSX 子元素中的内容。
支持多语言的代码块
你可以通过 MDX 的能力在文档中创造可交互的组件。例如,你可以用选项卡组件来切换并展示包含多种编程语言的代码示例。
我们并没有为多语言代码块去编写专用的组件,而是在经典主题中实现了通用的 <Tabs>
组件,以便你在其他非代码的场景中也能够使用。
下面的例子介绍了如何在文档中使用选项卡展示多个编程语言的代码块。 需要注意的是,我们特意在每一个代码块的上下各空了一行。 这是一个 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>
你将看到以下的效果:
- JavaScript
- Python
- Java
function helloWorld() {
console.log('Hello, world!');
}
def hello_world():
print("Hello, world!")
class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello, World");
}
}
如果你有多个多语言选项卡,而且你希望在多个选项组之间同步选项卡的选项,请参考同步选项章节。
Docusaurus npm2yarn remark 插件
需要同时显示 npm 和 Yarn 的 CLI 命令很常见,比如:
- npm
- Yarn
- pnpm
npm install @docusaurus/remark-plugin-npm2yarn
yarn add @docusaurus/remark-plugin-npm2yarn
pnpm add @docusaurus/remark-plugin-npm2yarn
Docusaurus 提供了这样一个工具,这样你就不用每次都写 Tabs
组件了。 要启用这个功能,请先安装 @docusaurus/remark-plugin-npm2yarn
插件,然后在 docusaurus.config.js
中,对于你需要这个插件功能的地方(文档、博客、页面等等),在 remarkPlugins
字段选项里注册这个插件。 (关于配置格式的更多详情,请参阅示例配置)
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
关键字来使用这个功能:
```bash npm2yarn
npm install @docusaurus/remark-plugin-npm2yarn
```
配置
选项 | 类型 | 默认值 | 描述 |
---|---|---|---|
sync | boolean | false | 是否在所有代码块中同步所选转换器。 |
converters | array | '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>你好,{props.name}</h1>;
}`}
</CodeBlock>
</div>
);
}
function HelloCodeTitle(props) {
return <h1>你好,{props.name}</h1>;
}
接受的属性名为 language
、title
和 showLineNumbers
,和你在 Markdown 中书写代码块的方法一样。
虽然不建议你这么做,但你也可以传入一个 metastring
属性,比如 metastring='{1-2} title="/src/components/HelloCodeTitle.js" showLineNumbers'
。Markdown 代码块在底层就是这么被处理的。 然而,我们还是建议你用注释实现行高亮。
如前文所述,语法高亮功能只会在 JSX 子元素是一个普通字符串时才启用。