如何遍历Sphinx所有文档并提取已有figure指令的元信息?
实现Sphinx全局图片列表扩展
要实现遍历现有.. figure::指令生成图片列表的自定义扩展,核心思路参考Sphinx官方Todo扩展的全局注册模式,分为元数据收集和列表渲染两个部分:
1. 核心实现逻辑
1.1 收集所有figure的元数据
通过监听Sphinx的doctree-read事件,在每个文档解析完成后,遍历其中的figure节点,提取图片的标题、文件路径、编号等元信息,存储到Sphinx环境(env)的全局变量中,供后续指令调用。
1.2 定义渲染列表的自定义指令
创建一个自定义指令(比如.. figure-list::),读取环境中收集到的所有figure数据,生成对应的列表节点,最终渲染到文档中。
2. 完整可运行代码
from docutils import nodes from sphinx.util.docutils import SphinxDirective from sphinx.application import Sphinx def collect_figures(app: Sphinx, doctree): # 初始化全局存储容器,仅在第一次运行时创建 if not hasattr(app.env, 'all_figures'): app.env.all_figures = [] # 遍历当前文档中的所有figure节点 for figure_node in doctree.findall(nodes.figure): # 提取图片标题(如果有caption) caption = "" caption_node = figure_node.find(nodes.caption) if caption_node: caption = caption_node.astext() # 提取图片文件路径(figure节点的第一个子节点通常是image节点) img_path = "" img_node = figure_node.find(nodes.image) if img_node and 'uri' in img_node.attributes: img_path = img_node['uri'] # 提取图片编号(由Sphinx自动生成的编号) fig_number = figure_node.get('number', "") # 收集元数据,包含标题、路径、编号、所在文档 app.env.all_figures.append({ 'caption': caption, 'img_path': img_path, 'number': fig_number, 'docname': app.env.docname }) class FigureListDirective(SphinxDirective): def run(self): env = self.state.document.settings.env # 获取全局收集的所有figure数据 all_figures = getattr(env, 'all_figures', []) # 创建无序列表节点 list_node = nodes.bullet_list() for fig in all_figures: # 创建列表项节点 list_item = nodes.list_item() # 构建列表项内容:编号 + 标题 + 路径 content_text = f"{fig['number']} {fig['caption']} ({fig['img_path']})" para_node = nodes.paragraph(text=content_text) list_item.append(para_node) list_node.append(list_item) return [list_node] def setup(app: Sphinx): # 注册事件监听,用于收集figure数据 app.connect('doctree-read', collect_figures) # 注册自定义指令 app.add_directive('figure-list', FigureListDirective) return { 'version': '0.1', 'parallel_read_safe': True, 'parallel_write_safe': True, }
3. 使用说明
- 将上述代码保存为
sphinx_figure_list.py,放在你的Sphinx项目的扩展目录(比如_extensions)中。 - 在
conf.py中添加扩展:extensions = [ # 其他扩展... '_extensions.sphinx_figure_list', ] - 在任意
.rst文档中添加指令.. figure-list::,即可生成所有图片的列表。
4. 关键细节说明
- 元数据收集时机:
doctree-read事件在每个文档被解析为doctree后触发,确保能捕获所有figure节点。 - 全局存储:使用
app.env.all_figures作为全局容器,Sphinx会在构建过程中维护这个环境变量,跨文档共享数据。 - 节点遍历:通过
doctree.findall(nodes.figure)精准定位所有figure节点,再从中提取caption、image路径等关键信息。
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

