代码块
文档中的代码块超级厉害 💪。
代码标题
你可以在语言后添加 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。 你可以通过 docusaurus.config.js 中的 themeConfig.prism
的 theme
字段来更改主题。
举个例子,如果你喜欢 dracula
高亮主题:
module.exports = {
themeConfig: {
prism: {
theme: require('prism-react-renderer/themes/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 语言的高亮:
module.exports = {
// ...
themeConfig: {
prism: {
additionalLanguages: ['powershell'],
},
// ...
},
};
添加 additionalLanguages
后,重启 Docusaurus。
如果你想添加 Prism 所不支持语言的语法高亮功能,你可以 swizzle prism-include-languages
:
- npm
- Yarn
npm run swizzle @docusaurus/theme-classic prism-include-languages
yarn 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 的官方语言定义。
行高亮
用注释实现行高亮
你可以用 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);
}
如果你还需要给高亮代码行加其他样式,你可以在 CSS 里用 theme-block-high-lighted-line
类名。
用元数据字符串实现高亮
你也可以在元字符串中指定高亮的行范围(在语言名后留一个空格)。 要高亮多行内容,请使用半角逗号来分隔行号,或使用范围语法来选择多行代码块。 这个功能用的是 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
module.export = {
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
第一项内容的类名。 默认情况下,这就是 theme-code-block-highlighted-line
, 但如果你更改了 magicComments
配置,用了其他东西作为第一条内容,那数字范围的含义也会改变。
你可以用 magicComments: []
来禁用默认的高亮注释。 如果魔法注释配置是空的,但 Docusaurus 遇到了一个包含数字范围的代码块,它会报错,因为没有可以用在这里的类名——高亮的类名毕竟也只是一种魔法注释。
每个魔法评论项目会包含三个字段:classname
(必填);line
,会应用于紧挨着的下一行;block
(包含 start
和 end
两个字段),会应用于这两个注释所包裹的整个片段。
用 CSS 给类名指定样式已经可以做很多事情了,但要解锁这个功能的全部潜力,你可以 swizzle。
- npm
- Yarn
npm run swizzle @docusaurus/theme-classic CodeBlock/Line
yarn 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
npm install --save @docusaurus/theme-live-codeblock
yarn add @docusaurus/theme-live-codeblock
你还需要把插件添加到 docusaurus.config.js
中。
module.exports = {
// ...
themes: ['@docusaurus/theme-live-codeblock'],
// ...
};
要使用此插件,只需要创建一个代码块,同时在语言元标签中加上 live
。
```jsx live
function Clock(props) {
const [date, setDate] = useState(new Date());
useEffect(() => {
var 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 的作用域:
- npm
- Yarn
npm run swizzle @docusaurus/theme-live-codeblock ReactLiveScope
yarn run swizzle @docusaurus/theme-live-codeblock ReactLiveScope
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
组件了:
在代码块中使用 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>
输入:1 2 3 4
输出:"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
npm install @docusaurus/remark-plugin-npm2yarn
yarn add @docusaurus/remark-plugin-npm2yarn
Docusaurus 提供了这样一个工具,这样你就不用每次都写 Tabs
组件了。 要启用这个功能,请先安装 @docusaurus/remark-plugin-npm2yarn
包,然后在 docusaurus.config.js
中,对于你需要此功能的插件(文档、博客、页面,等等),在 remarkPlugins
选项里注册这个插件。 (关于配置格式的更多详情,请参阅文档配置)
module.exports = {
// ...
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
remarkPlugins: [
[require('@docusaurus/remark-plugin-npm2yarn'), {sync: true}],
],
},
pages: {
remarkPlugins: [require('@docusaurus/remark-plugin-npm2yarn')],
},
blog: {
// ...
},
},
],
],
};
然后要使用它,只需在代码块中添加 npm2yarn
键:
```bash npm2yarn
npm install @docusaurus/remark-plugin-npm2yarn
```
{sync: true}
选项会让所有选项卡选项同步。 因为选项存储在同一个命名空间 npm2yarn
下,所以不同的 npm2yarn
插件实例也会同步它们的选择。
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>;}
可接受的 props 有 language
、title
、showLineNumbers
,和你写 Markdown 代码块是一样的。
虽然不建议你这么做,但你也可以传递一个 metastring
prop,比如 metastring='{1-2} title="/src/components/HelloCodeTitle.js" showLineNumbers'
。Markdown 代码块在底层就是这么被处理的。 然而,我们还是建议你用注释来实现高亮行。
如前文所述,语法高亮只会在 children 是一个普通字符串时才开启。