开发了一个 “Hello world” 扩展

本教程的目的是创建一个非常基本的扩展,添加一个新指令。 该指令将输出包含“ hello world”的段落。

本教程仅提供基本信息。 有关更多信息,请参阅其他教程<index>。

警告

对于此扩展,您将需要对 docutils 和 Python 有一些基本了解。

概述

我们希望插件将以下内容添加到Sphinx中:

  • 一个“ helloworld”指令,将仅输出文本“ hello world”。

系统需求

我们不会通过`PyPI`_分发此插件,而是将其包含在现有项目中。 这意味着您将需要使用现有项目或使用:program:sphinx-quickstart 创建一个新项目。

我们假设您使用的是单独的 source(:file:source)和build(:file:build)文件夹。 您的扩展文件可以在项目的任何文件夹中。 在我们的情况下,让我们执行以下操作:

  1. 创建了 _ext folder in source

  2. _ext folder called helloworld.py 创建了一个 Python 文件

这是您将获得的文件夹结构的示例:

└── source
    ├── _ext
    │   └── helloworld.py
    ├── _static
    ├── conf.py
    ├── somefolder
    ├── index.rst
    ├── somefile.rst
    └── someotherfile.rst

编写扩展

打开 helloworld.py 并将下列代码粘进去:

 1from docutils import nodes
 2from docutils.parsers.rst import Directive
 3
 4from sphinx.application import Sphinx
 5from sphinx.util.typing import ExtensionMetadata
 6
 7
 8class HelloWorld(Directive):
 9    def run(self):
10        paragraph_node = nodes.paragraph(text='Hello World!')
11        return [paragraph_node]
12
13
14def setup(app: Sphinx) -> ExtensionMetadata:
15    app.add_directive('helloworld', HelloWorld)
16
17    return {
18        'version': '0.1',
19        'parallel_read_safe': True,
20        'parallel_write_safe': True,
21    }

在此示例中,发生了一些重要的事情,您将在所有指令中看到它们。

指令类

我们的新指令将会在 HelloWorld 类中声明。

1from sphinx.util.typing import ExtensionMetadata
2
3
4class HelloWorld(Directive):
5    def run(self):

此类扩展了docutils``Directive``类。 所有创建指令的扩展都应扩展此类。

参见

`docutils 有关创建指令<docutils directives>的文档_

此类包含一个 run 方法。 此方法是必需的,并且是每个指令的一部分。 它包含指令的主要逻辑,并返回 Sphinx 要处理的 docutils 节点列表。 这些节点是docutils 表示文档内容的方式。 有多种类型的节点可用:文本,段落,引用,表格等。

nodes.paragraph 类创建一个新的段落节点。 段落节点通常包含一些我们可以在实例化期间使用 text 参数设置的文本。

setup 功能

此功能是必需的。 我们使用它将我们的新指令插入 Sphinx。

 1
 2
 3def setup(app: Sphinx) -> ExtensionMetadata:
 4    app.add_directive('helloworld', HelloWorld)
 5
 6    return {
 7        'version': '0.1',
 8        'parallel_read_safe': True,
 9        'parallel_write_safe': True,
10    }

The simplest thing you can do is to call the add_directive() method, which is what we’ve done here. For this particular call, the first argument is the name of the directive itself as used in a reST file. In this case, we would use helloworld. For example:

Some intro text here...

.. helloworld::

Some more text here...

我们还返回了扩展元数据<ext-metadata>,它指示扩展的版本,以及可以安全地将扩展用于并行读取和写入的事实。

使用扩展

该扩展名必须在您的:file:`conf.py`文件中声明,以使 Sphinx 意识到这一点。 这里需要两个步骤:

  1. 使用sys.path.append将`_ext`目录将新增到 Python 路径_中。 这应该放在文件的顶部。

  2. 更新或创建扩展名列表,并将扩展名添加到列表中

例如:

import os
import sys

sys.path.append(os.path.abspath("./_ext"))

extensions = ['helloworld']

小技巧

我们不以 Python 包的形式分发此扩展,我们需要修改 Python 路径以便 Sphinx 可以找到我们的扩展。 这就是为什么我们需要调用 sys.path.append 的原因。

现在,您可以在文件中使用扩展名。 例如:

Some intro text here...

.. helloworld::

Some more text here...

上面的示例将生成:

Some intro text here...

Hello World!

Some more text here...

延伸阅读

这是创建新指令的扩展的最基本原理。

想看更多有些样例,请参考 Developing a “TODO” extension.