如何在Docusaurus中实现类似Sphinx的指定代码片段引入功能?
Docusaurus 实现指定区间代码提取的方案
当然可以实现类似 Sphinx 的指定行代码提取功能,下面是几种社区常用的实践方式,核心思路就是利用 MDX/JSX 能力或者构建阶段的脚本处理,替代 Sphinx 的 include 指令:
方案1:自定义 MDX 组件 + 预构建脚本
这是最灵活的方式,完全可控:
- 先写一个用于展示代码的 React 组件(比如
src/components/CodeSnippet.jsx):
import React from 'react'; import CodeBlock from '@theme/CodeBlock'; export default function CodeSnippet({ code, language }) { return <CodeBlock className={`language-${language}`}>{code}</CodeBlock>; }
- 写一个 Node 脚本(
scripts/extract-snippets.js),在构建前自动提取代码片段并保存为 JSON:
const fs = require('fs'); const path = require('path'); // 提取标记间的代码 function getSnippet(filePath, startMarker, endMarker) { const content = fs.readFileSync(filePath, 'utf8'); const startPos = content.indexOf(startMarker) + startMarker.length; const endPos = content.indexOf(endMarker); return content.slice(startPos, endPos).trim(); } // 定义需要提取的所有片段 const snippets = { mattsPythonScript: getSnippet( './scripts/matts_script.py', '# marker_1', '# marker_2' ) }; // 写入数据文件 fs.writeFileSync( path.join(__dirname, '../src/data/snippets.json'), JSON.stringify(snippets) );
- 在
package.json里添加预构建/预启动命令,确保脚本先执行:
"scripts": { "prestart": "node scripts/extract-snippets.js", "prebuild": "node scripts/extract-snippets.js", "start": "docusaurus start", "build": "docusaurus build" }
- 最后在 MDX 文档里引入组件和数据:
import CodeSnippet from '@site/src/components/CodeSnippet'; import snippets from '@site/src/data/snippets.json'; <CodeSnippet code={snippets.mattsPythonScript} language="python" />
方案2:自定义 Remark 插件(更贴近 Sphinx 写法)
如果想保留类似 Sphinx 的指令风格,可以写一个 Remark 插件,在 Markdown 解析阶段自动替换自定义指令为代码块:
- 编写插件(
plugins/remark-include-snippet.js):
const fs = require('fs'); const path = require('path'); const visit = require('unist-util-visit'); module.exports = function () { return function (tree, file) { // 遍历所有代码块,识别自定义的include指令 visit(tree, 'code', (node) => { if (node.lang === 'include') { const [filePath, startMarker, endMarker] = node.value.split('\n').filter(line => line.trim()); const fullPath = path.resolve(path.dirname(file.path), filePath); const content = fs.readFileSync(fullPath, 'utf8'); // 提取标记间的代码 const startPos = content.indexOf(startMarker) + startMarker.length; const endPos = content.indexOf(endMarker); const snippet = content.slice(startPos, endPos).trim(); // 替换为对应语言的代码块 node.lang = 'python'; // 根据实际文件类型调整 node.value = snippet; } }); }; };
- 在
docusaurus.config.js里注册这个插件:
module.exports = { presets: [ [ '@docusaurus/preset-classic', { docs: { remarkPlugins: [require('./plugins/remark-include-snippet')], }, }, ], ], };
- 在 Markdown 里直接用类似 Sphinx 的写法:
```include ./scripts/matts_script.py # marker_1 # marker_2
## 注意事项 - 所有文件读取操作必须在**构建阶段**完成,因为 Docusaurus 生成的是静态站点,客户端无法访问本地文件系统。 - 建议给脚本添加异常处理(比如标记不存在时抛出提示),避免构建失败。 - 开发时如果需要实时更新代码片段,可以给预启动脚本加上文件监听逻辑,修改源文件后自动重新提取。 内容的提问来源于stack exchange,提问作者kenna
相关产品推荐
相关产品推荐

