为 Sphinx 开发插件¶
由于许多项目在文件中需要特殊的功能,Sphinx 被设计成可在多个层面上进行扩展。
这里有几件你可以在插件中做的事情:
增加新的 构建器,以支持新的输出格式或对解析后的文件的操作。
使用 Docutils markup API 扩展标记,注册自定义的 reStructuredText 角色和指令。
在整个构建过程中的战略位置添加自定义代码到所谓的 “钩子点”,允许你注册一个钩子并运行专门的代码。例如,请参阅 Sphinx 核心事件。
一个插件只是一个带有 setup()
函数的 Python 模块。用户通过将插件的模块名称(或一个子模块)放在他们的 extensions
配置值中来激活插件。
当 sphinx-build 被执行时,Sphinx 会尝试导入每个被列出的模块,并执行 yourmodule.setup(app)。这个函数用来准备插件(比如执行 Python 代码),链接 Sphinx 在构建过程中使用的资源(比如 CSS 或 HTML 文件),并通知 Sphinx 插件提供的一切(比如指令或角色定义)。app
参数是 Sphinx
的一个实例,让你控制 Sphinx 构建的大部分方面。
备注
如果配置文件本身包含 setup()
函数,就可以被视为一个插件。所有其他要加载的插件必须在 extensions
配置值中列出。
本页面的其余部分描述了开发插件的一些高层次方面,以及你能控制的 Sphinx 行为的各个部分。关于如何建立和使用插件来控制 Sphinx 的不同部分的一些例子,请看 插件教程。
重要对象¶
在编写插件时,有几个关键对象的 API 你会用到。这些对象是:
- Application
应用程序对象(通常称为
app
)是Sphinx
的一个实例。它控制大多数高级功能,如插件的设置、事件调度和产生输出(日志)。如果你有环境对象,应用程序就可以作为
env.app
使用。- Environment
构建环境对象(通常称为
env
)是BuildEnvironment
的一个实例。它负责解析源文件,存储所有关于文件集的元数据,并在每次构建后被序列化到磁盘。它的 API 提供了访问元数据的方法,解决了引用等问题。它也可以被扩展用于缓存信息,这些信息应该在增量重建中持续存在。
如果你有应用程序或构建器对象,环境可作为
app.env
或builder.env
。- Builder
构建器对象(通常称为
builder
)是Builder
的特定子类的一个实例。每个构建器类都知道如何将解析后的文件转换为输出格式,或以其他方式处理它们(例如,检查外部链接)。如果你有应用程序对象,构建器可以作为
app.builder
使用。- Config
config 对象(通常称为
config
)提供了conf.py
中设置的配置值作为属性。它是Config
的一个实例。该配置可作为
app.config
或env.config
。
要看这些对象的使用实例,请参考 插件教程。
构建阶段¶
为了理解插件机制,至关重要的一点是 Sphinx 项目的构建方式:这分几个阶段进行。
阶段 0:初始化
在这个阶段,几乎没有发生我们感兴趣的事情。源目录被搜索为源文件,插件被初始化。如果存在一个存储的构建环境,它将被加载,否则将创建一个新的环境。
阶段 1:阅读
在第一阶段,所有的源文件(以及在随后的构建中,那些新的或改变的文件)都被读取和解析。这是 docutils 遇到指令和角色的阶段,相应的代码被执行。这个阶段的输出是每个源文件的 doctree;也就是 docutils 节点的树。对于那些在读取所有现有文件之前并不完全知道的文件元素,会创建临时节点。
有一些节点是由 docutils 提供的,这些节点在 docutils 文档 中都有记载。额外的节点由 Sphinx 提供, 这里有记录。
在阅读过程中,构建环境会更新所有已读文件的元数据和交叉参考数据,如标签、标题的名称、描述的 Python 对象和索引条目。这以后将被用来替换临时节点。
解析后的 doctree 存储在磁盘上,因为不可能在内存中容纳所有的 doctree。
阶段 2:一致性检查
做了一些检查,以确保建成的文件中没有意外。
阶段 3:解决问题
现在,所有现有文件的元数据和交叉引用数据都是已知的,所有的临时节点都被可以使用称为变换的组件转换为输出的节点所取代。例如,为存在的对象参考创建链接,为不存在的对象创建简单的 literal 节点。
阶段 4:写作
这一阶段将解决的 doctrees 转换为所需的输出格式,如 HTML 或 LaTeX。这是通过一个所谓的 docutils writer 实现的,它访问每个 doctree 的各个节点,并在这个过程中产生一些输出。
备注
一些构建器偏离了这个一般的构建计划,例如,检查外部链接的构建器除了解析的 doctrees 之外不需要其他东西,因此没有第2–4阶段。
要看一个应用程序的例子,请参考 开发 “TODO” 插件。
插件元数据¶
1.3 新版功能.
setup()
函数可以返回一个字典。这被 Sphinx 视为插件的元数据。目前识别的元数据键有:
'version'
:一个标识插件版本的字符串。它是用于检查插件的版本要求(见needs_extensions
)和信息用途。如果不给,则替换为"unknown version"
。'env_version'
:一个整数,如果插件将任何数据存储到环境中,则标识 env 数据结构的版本。它被用来检测数据结构是否在上次构建时发生了变化。当数据结构发生变化时,插件必须增加该版本。 如果没有给出,Sphinx 认为该插件没有存储任何数据到环境中。'parallel_read_safe'
:一个布尔值,用于指定在加载扩展时是否可以使用源文件的并行读取。它的默认值是False
,也就是说,你必须在检查后明确指定你的扩展是并行阅读安全的。备注
parallel-read-safe 插件必须满足以下条件:
插件的核心逻辑在阅读阶段是可以并行执行的。
如果在读取阶段将 dataa 存储到构建环境对象(env)中,它有
env-merge-info
和env-purge-doc
事件的处理程序。
'parallel_write_safe'
:一个布尔值,指定在加载扩展时是否可以使用输出文件的并行写入。由于扩展通常不会对进程产生负面影响,因此默认为True
。备注
parallel-write-safe 插件必须满足以下条件:
插件的核心逻辑在编写阶段是可以并行执行的。
用来编写插件程序的 API¶
这些部分提供了一个更完整的描述,在开发 Sphinx 插件时你可以使用的工具。有些是 Sphinx 的核心(比如 Application API),而其他的则是触发特定的行为(比如 i18n API)