You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Sphinx扩展在当前文档下创建新文档页面

开发Sphinx扩展实现调用时生成子目录文档页面

需求:要做一个Sphinx扩展,当在RST文档(比如foo.rst)里调用该扩展时,能在当前文档的目录下生成独立的新文档页面,例如foo/bar.html、foo/baz.html这类。

以下是用户提供的简化扩展代码(已翻译注释):

class NetYnlInclude(Directive):
    def run(self):
        file = "my_file.txt"     
        # 将文件添加到依赖记录,确保文件变化时Sphinx会重新构建
        self.state.document.settings.record_dependencies.add(file)                     
        parsed_str = parse(file) # 将文件解析为字符串
        # 将解析后的内容转为行,插入到当前文档的渲染流程中
        self.state_machine.insert_input(
            statemachine.string2lines(parsed_str), filename)

        # 返回空段落节点,不影响当前文档的输出
        paragraph_node = nodes.paragraph()
        return paragraph_node

现有代码的局限

当前代码只是把解析后的文本嵌入到调用扩展的RST文档里,并没有生成独立的新页面。要实现生成独立子页面的需求,需要修改逻辑,在Sphinx的构建环境中主动添加新的文档条目。

修改后的实现方案

要生成独立页面,需要在扩展中动态创建新的RST文档文件,并将其注册到Sphinx的构建环境中,让Sphinx把这些新文档当成独立页面来处理。以下是调整后的示例代码:

from docutils.parsers.rst import Directive
from docutils import nodes
import os
from sphinx.util import logging
from sphinx.util.osutil import relpath

logger = logging.getLogger(__name__)

class NetYnlInclude(Directive):
    def run(self):
        # 获取当前调用扩展的文档路径(比如foo.rst对应docname为foo)
        current_doc = self.state.document.settings.env.docname
        current_dir = os.path.dirname(current_doc)
        # 定义要生成的新文档名称(无需后缀)
        new_doc_names = ["bar", "baz"]
        input_file = "my_file.txt"
        
        # 记录依赖,确保输入文件变化时触发重新构建
        self.state.document.settings.record_dependencies.add(input_file)
        # 解析输入文件内容,这里假设parse函数返回可复用的内容模板
        base_content = parse(input_file)

        for doc_name in new_doc_names:
            # 构建新文档的完整标识路径(比如foo/bar)
            new_docname = os.path.join(current_dir, doc_name)
            # 避免重复添加相同文档
            if new_docname not in self.state.document.settings.env.docnames:
                # 为新文档生成RST内容,可根据需求拆分或定制
                new_rst = f".. _ref-{new_docname}:\n\n# {doc_name}页面\n\n{base_content}\n"
                # 拼接新文档的物理路径
                new_rst_path = os.path.join(self.state.document.settings.env.srcdir, f"{new_docname}.rst")
                # 创建RST文件
                os.makedirs(os.path.dirname(new_rst_path), exist_ok=True)
                with open(new_rst_path, "w", encoding="utf-8") as f:
                    f.write(new_rst)
                # 将新文档注册到Sphinx构建环境
                self.state.document.settings.env.found_docs.add(new_docname)
                logger.info(f"已添加新文档: {new_docname}")
        
        # 返回空节点,不影响当前文档的渲染结果
        return [nodes.paragraph()]

def setup(app):
    app.add_directive("netynl-include", NetYnlInclude)
    return {
        'version': '0.1',
        'parallel_read_safe': True,
        'parallel_write_safe': True,
    }

关键实现说明

  • 动态创建RST文件:根据当前文档的目录,生成对应子目录下的RST文件,Sphinx会自动识别这些文件并构建成HTML页面。
  • 注册新文档:通过found_docs.add()将新文档添加到Sphinx的待构建列表,确保这些文档会被处理。
  • 依赖管理:记录原始输入文件的依赖,当my_file.txt内容变化时,所有生成的新文档都会重新构建。
  • 路径处理:自动创建所需的子目录,避免因目录不存在导致文件写入失败。

内容的提问来源于stack exchange,提问作者Breno Leitão

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 06:23:32