HTML主题开发

Added in version 0.6.

备注

此文档提供有关创建您自己的主题的信息.如果您只是希望使用现有的 HTML 主题,请参阅 HTML 主题 .

Sphinx支持通过*主题*更改其HTML输出的外观.主题是HTML模板、样式表及其他静态文件的集合.此外,它还有一个配置文件,指定了要继承哪个主题、使用哪种高亮样式以及用于自定义主题外观和感觉的选项.

主题旨在与项目无关,因此可以在不同的项目中使用而无需更改.

备注

有关开发主题的更多信息,请参见 Sphinx API .

创建主题

主题可以是一个目录或一个压缩文件(其名称即为主题名称),包含以下内容:

  • 可以是 theme.toml 文件(优选)或 theme.conf 文件.

  • HTML 模板,如果需要的话.

  • 一个 static/ 目录,包含在构建时将被复制到输出静态目录的任何静态文件.这些可以是图像、样式、脚本文件.

主题配置( theme.toml

The theme.toml file is a TOML document, containing two tables: [theme] and [options].

The [theme] table defines the theme’s settings:

  • inherit (字符串): 要继承设置、选项、模板和静态文件的基础主题的名称.将使用主题”祖先”的所有静态文件.该主题将使用在继承主题中定义的所有选项.最后,将使用继承主题来定位缺失的模板(例如,如果使用 "basic" 作为基础主题,则大多数模板将已经被定义).

    如果设置为 "none" ,则主题将不从任何其他主题继承.继承是递归的,形成一个继承主题的链(例如 default -> classic -> basic -> none ).

  • 样式表 (字符串列表): 一系列将被包含在生成的 HTML 头部的 CSS 文件名.设置 html_style 配置值将覆盖此设置.

    将多个样式表包含在内的其他机制包括在CSS中使用 @import 或使用带有适当 <link rel="stylesheet"> 标签的自定义HTML模板.

  • **侧边栏**(字符串列表):一个侧边栏模板的列表.用户可以通过 html_sidebars 配置值来覆盖此设置.

  • pygments_style (表): 一个 TOML 表,用于定义用于高亮语法的 Pygments 样式名称.该表有两个被认可的键:defaultdark .当 CSS 媒体查询 (prefers-color-scheme: dark) 返回 true 时,将使用 dark 键中定义的样式.

    [theme.pygments_style.default] can be overridden by the user via the pygments_style config value.

The [options] table defines the options for the theme. It is structured such that each key-value pair corresponds to a variable name and the corresponding default value. These options can be overridden by the user in html_theme_options and are accessible from all templates as theme_<name>.

Added in version 7.3: theme.toml support.

示例 theme.toml 文件:

[theme]
inherit = "basic"
stylesheets = [
    "main-CSS-stylesheet.css",
]
sidebars = [
    "localtoc.html",
    "relations.html",
    "sourcelink.html",
    "searchbox.html",
]
# Style names from https://pygments.org/styles/
pygments_style = { default = "style_name", dark = "dark_style" }

[options]
variable = "default value"

主题配置( theme.conf

theme.conf 文件采用 INI 格式 [1] (可通过标准 Python configparser 模块读取),其结构如下:

[theme]
inherit = base theme
stylesheet = main CSS name
pygments_style = stylename
sidebars = localtoc.html, relations.html, sourcelink.html, searchbox.html

[options]
variable = default value
  • inherit 设置给出了 “基本主题 “的名称,或者 none .基本主题将用于定位缺失的模板(大多数主题如果使用 basic 作为基本主题,则不必提供大多数模板),它的选项将被继承,所有的静态文件也将被使用.如果您还想继承样式表,请通过您的 CSS 中的 @import 来包含它.

  • 在设置中,**样式表**选项提供了一组由逗号分隔的CSS文件名,这些文件将在HTML头部被引用.您还可以使用CSS的 @import 技术将多个样式表包括在内,或者使用自定义的HTML模板按需添加 <link rel="stylesheet"> 标签.设置:confval:html_style 配置值将会覆盖此设置.

  • 设置 pygments_style 指定要使用的 Pygments 风格名称以进行高亮显示.用户可以在 pygments_style 配置值中覆盖此设置.

  • pygments_dark_style 设置给出了在 CSS 媒体查询 (prefers-color-scheme: dark) 评估为真时用于高亮显示的 Pygments 样式名称.它是通过 add_css_file() 注入到页面中的.

  • **侧边栏**设置提供用于构建侧边栏的以逗号分隔的侧边栏模板列表.用户可以在:confval:html_sidebars 配置值中覆盖此设置.

  • **选项**部分包含变量名称和默认值的配对.这些选项可以被用户在 html_theme_options 中覆盖,并且可以从所有模板中作为 theme_<name> 访问.

Added in version 1.7: 边栏设置

在 5.1 版本发生变更: 样式表设置接受多个CSS文件名

theme.conf 转换为 theme.toml

INI 风格的主题配置文件 ( theme.conf ) 可以通过与 Sphinx 一起分发的辅助程序转换为 TOML.这是一次性使用的,可能会在未来版本的 Sphinx 中不经通知而被移除.

$ python -m sphinx.theming conf_to_toml [THEME DIRECTORY PATH]

所需参数是一个指向包含 theme.conf 文件的目录的路径.程序将在相同的目录中写入 theme.toml 文件,并且不会修改原始的 theme.conf 文件.

Added in version 7.3.

将您的主题作为Python包分发

将主题分发的方式,你可以使用一个Python包.这使得用户更容易设置你的主题.

要将您的主题作为 Python 包进行分发,请在您的 pyproject.toml 文件中定义一个名为 sphinx.html_themes 的入口点,并编写一个 setup() 函数来使用 add_html_theme() API 注册您的主题:

# pyproject.toml

[project.entry-points."sphinx.html_themes"]
name_of_theme = "your_theme_package"
# your_theme_package.py
from os import path

def setup(app):
    app.add_html_theme('name_of_theme', path.abspath(path.dirname(__file__)))

如果您的主题包包含两个或更多主题,请调用 add_html_theme() 两次或更多次.

Added in version 1.2: ‘sphinx_themes’ 入口点功能.

自 1.6 版本弃用: sphinx_themes entry_points has been deprecated.

Added in version 1.6: sphinx.html_themes entry_points feature.

使用CSS样式

The stylesheets setting can be used to add custom CSS files to a theme.

小心

HTML元素及其类的结构目前不是一个定义良好的公共API.请通过检查构建的HTML页面来推断它们.虽然我们无法保证完全稳定,但它们往往相对稳定.

为分类样式化搜索结果条目

Added in version 8.0.

搜索结果项具有指示搜索词出现上下文的类.您可以使用CSS选择器:

  • ul.search li.context-index: For results in an index, such as the glossary

  • ul.search li.context-object: For results in source code, like Python function definitions

  • ul.search li.context-title: For results found in section headings

  • ul.search li.context-text: For results found anywhere else in the documentation text

作为其他主题继承的基础, basic 主题故意保持最小化,并且不使用这些定义CSS规则.衍生主题被鼓励根据需要使用这些选择器.例如,以下样式表为搜索结果列表添加了上下文图标:

ul.search {
    padding-left: 30px;
}
ul.search li {
    padding: 5px 0 5px 10px;
    list-style-type: "\25A1";  /* Unicode: White Square */
}
ul.search li.context-index {
    list-style-type: "\1F4D1";  /* Unicode: Bookmark Tabs */
}
ul.search li.context-object {
    list-style-type: "\1F4E6";  /* Unicode: Package */
}
ul.search li.context-title {
    list-style-type: "\1F4C4";  /* Unicode: Page Facing Up */
}
ul.search li.context-text {
    list-style-type: "\1F4C4";  /* Unicode: Page Facing Up */
}

模版化

模板指南 guide to templating 如果您想编写自己的模板,这将很有帮助. 要记住的重要事项是 Sphinx 搜索模板的顺序:

  • 首先,在用户的 templates_path 目录中.

  • 然后,在所选主题中.

  • 然后,在它的基础主题、它的基础主题的基础主题等.

当使用相同名称的基本主题扩展模板时,请将主题名称作为显式目录: {% extends "basic/layout.html" %} . 从用户的 templates_path 模板中,您仍然可以使用 “感叹号” 语法,如 在模板文档中所述 .

静态模板

由于主题选项是为了让用户更容易配置主题,而不需要编写自定义样式表,因此有必要能够对静态文件以及 HTML 文件进行模板化.因此,Sphinx 支持所谓的”静态模板”,如下所示:

如果主题的 static/ 目录中(或用户的静态路径中)某个文件的名称以 .jinja_t 结尾,它将被模板引擎处理.最终文件名将去掉该后缀.

例如,一个包含 static/theme_styles.css.jinja 文件的主题可以使用模板将选项放入样式表中.当用该主题构建文档项目时,输出目录将包含一个 _static/theme_styles.css 文件,所有模板标签都已被处理.

在 7.4 版本发生变更:

静态模板的首选后缀现在是 .jinja ,与 Jinja 项目的 推荐文件扩展名 一致.

The _t file suffix for static templates is now considered ‘legacy’, and support may eventually be removed.

如果检测到具有 _t 后缀或 .jinja 后缀的静态模板,它将被模板引擎处理,最终文件名将去掉后缀.

在HTML模板中使用自定义页面元数据

字段列表 中放置的任何键/值对,*在*页面标题之前,将在构建页面时通过 meta 属性提供给 Jinja 模板.例如,如果一个页面在其第一个标题之前有以下文本:

:mykey: My value

My first title
--------------

然后可以在 Jinja 模板中像这样访问它:

{%- if meta is mapping %}
    {{ meta.get("mykey") }}
{%- endif %}

注意检查 meta 是一个字典(在 Jinja 术语中称为 “mapping”),以确保以这种方式使用它是有效的.

定义自定义模板函数

有时候,定义您自己的 Python 函数是有用的,以便在模板中使用.例如,如果您希望插入一个模板值,而这个值的逻辑依赖于项目中的用户配置,或者如果您希望在模板中包含非平凡的检查并提供友好的错误信息以应对不正确的配置.

要定义您自己的模板函数,您需要在模块内定义两个函数:

  • 一个 页面上下文事件处理程序**(或 **注册)函数.它通过事件回调与 Sphinx 应用程序相连接.

  • 一个 模板函数,你将在你的 Jinja 模板中使用.

首先,定义注册函数,该函数接受 html-page-context 的参数.

在注册函数内,定义您希望在 Jinja 中使用的模板函数.模板函数应返回一个字符串或包含字符串的 Python 对象(列表、字典),Jinja 会在模板处理过程中使用这些字符串

备注

模板函数将可以访问传递给注册函数的所有变量.

在注册函数的末尾,将模板函数添加到 Sphinx 应用程序的上下文中,使用 context['template_func'] = template_func .

最后,在你的扩展的 setup() 函数中,将你的注册函数作为 html-page-context 的回调添加.

# The registration function
 def setup_my_func(app, pagename, templatename, context, doctree):
     # The template function
     def my_func(mystring):
         return "Your string is %s" % mystring
     # Add it to the page's context
     context['my_func'] = my_func

 # Your extension's setup function
 def setup(app):
     app.connect("html-page-context", setup_my_func)

现在,您将以如下方式在jinja中访问此功能:

<div>
{{ my_func("some string") }}
</div>

将您自己的静态文件添加到构建资产中

默认情况下,Sphinx 会将静态文件复制到模板目录的 static/ 目录中.然而,如果你的包需要将静态文件出于某种原因放置在 static/ 目录之外,你需要在构建过程中通过事件钩子手动将它们复制到 HTML 输出的 _static/ 目录中.以下是实现此功能的代码示例:

import shutil

def copy_custom_files(app, exc):
    if app.builder.format == 'html' and not exc:
        static_dir = app.outdir / '_static'
        shutil.copyfile('path/to/myextension/_static/myjsfile.js', static_dir)

def setup(app):
    app.connect('build-finished', copy_custom_files)

根据用户配置注入JavaScript

如果您的扩展使用了 JavaScript,允许用户通过他们的 Sphinx 配置来控制其行为可能会很有用.然而,如果您的 JavaScript 以静态库的形式出现(这不会与 Jinja 一起构建),那么实现起来可能会很困难.

根据用户配置,有两种方法可以将变量注入到JavaScript空间.

首先,您可以在任何包含在扩展中的静态文件的末尾添加 _t .这将导致 Sphinx 使用模板引擎处理这些文件,从而允许您嵌入变量并控制行为.

例如,以下JavaScript结构:

mymodule/
├── _static
│   └── myjsfile.js_t
└── mymodule.py

将导致生成以下静态文件,放置在您的HTML构建输出中:

_build/
└── html
    └── _static
        └── myjsfile.js

有关更多信息,请参阅 静态模板 .

其次,您可以使用 Sphinx.add_js_file() 方法,而不指向一个文件.通常,此方法用于将一个新的 JavaScript 文件插入到您的站点中.然而,如果您*不*传递一个文件路径,而是将一个字符串传递给 “body” 参数,那么这段文本将作为 JavaScript 插入到您站点的头部.这使您可以从 Python 将变量插入到项目的 JavaScript 中.

例如,以下代码将读取用户配置的值,然后将此值插入为一个JavaScript变量,您的扩展的JavaScript代码可以使用这个变量:

# This function reads in a variable and inserts it into JavaScript
def add_js_variable(app):
    # This is a configuration that you've specified for users in `conf.py`
    js_variable = app.config['my_javascript_variable']
    js_text = "var my_variable = '%s';" % js_variable
    app.add_js_file(None, body=js_text)
# We connect this function to the step after the builder is initialized
def setup(app):
    # Tell Sphinx about this configuration variable
    app.add_config_value('my_javascript_variable', 0, 'html')
    # Run the function after the builder is initialized
    app.connect('builder-inited', add_js_variable)

因此,在您的主题中,您可以使用依赖于此变量存在的代码.用户可以通过在他们的 conf.py 文件中定义它来控制变量的值.