HTML theme development¶
バージョン 0.6 で追加.
注釈
This document provides information about creating your own theme. If you simply wish to use a pre-existing HTML themes, refer to HTML Theming.
Sphinxは テーマ を使って出力したHTMLの見た目を変更する機能をサポートしています。テーマというのは、HTMLのテンプレート、スタイルシート、およびその他の静的なファイル類を集めたものです。これに加えて、どのテーマから継承するか、どのようなハイライトのスタイルを使用するか、テーマのルックアンドフィールをカスタマイズするためにどのようなオプションがあるのか、といったことが書かれている設定ファイルがあります。
テーマというのは特定のプロジェクトに依存しないものです。そのため、他のプロジェクトに適用する際に変更する必要はありません。
注釈
See Sphinx拡張機能の開発 for more information that may be helpful in developing themes.
テーマを作成する¶
Themes take the form of either a directory or a zipfile (whose name is the theme name), containing the following:
A
theme.conf
file.HTMLテンプレート(必要に応じて)
ビルド時に出力のディレクトリにコピーされる静的ファイルを含む
static/
ディレクトリ。画像、スタイルシート、スクリプトファイルなどです。
theme.conf
ファイルは Pythonの標準ライブラリの ConfigParser
モジュールで読み込み可能な INIフォーマット 1 で記述します。以下のような構造になっています:
[theme]
inherit = base theme
stylesheet = main CSS name
pygments_style = stylename
sidebars = localtoc.html, relations.html, sourcelink.html, searchbox.html
[options]
variable = default value
The inherit setting gives the name of a "base theme", or
none
. The base theme will be used to locate missing templates (most themes will not have to supply most templates if they usebasic
as the base theme), its options will be inherited, and all of its static files will be used as well. If you want to also inherit the stylesheet, include it via CSS'@import
in your own.stylesheet にはHTMLのヘッダから参照される、CSSファイルの名前を設定します。CSSファイルを一つ以上提供したい場合には、CSSの
@import
を使用して他のCSSをインクルードするか、必要なだけ<link rel="stylesheet">
タグを追加する、カスタムのHTMLテンプレートを使用します。この設定はhtml_style
の設定値で上書きされます。pygments_style には、ハイライトに使用する、Pygmentsのスタイルの名前を設定します。この設定は、コンフィグ値の
pygments_style
を使用することで、上書きできます。The pygments_dark_style setting gives the name of a Pygments style to use for highlighting when the CSS media query
(prefers-color-scheme: dark)
evaluates to true. It is injected into the page usingadd_css_file()
.The sidebars setting gives the comma separated list of sidebar templates for constructing sidebars. This can be overridden by the user in the
html_sidebars
config value.options セクションには変数名と、デフォルト値のペアを記述していきます。これらのオプションは、
html_theme_options
を設定することで、ユーザ側で上書きできます。また、すべてのテンプレートからは、theme_<名前>
として、この設定値にアクセスできます。
バージョン 1.7 で追加: sidebar settings
Distribute your theme as a Python package¶
As a way to distribute your theme, you can use Python package. Python package brings to users easy setting up ways.
To distribute your theme as a Python package, please define an entry point
called sphinx.html_themes
in your setup.py
file, and write a setup()
function to register your themes using add_html_theme()
API in it:
# 'setup.py'
setup(
...
entry_points = {
'sphinx.html_themes': [
'name_of_theme = your_package',
]
},
...
)
# 'your_package.py'
from os import path
def setup(app):
app.add_html_theme('name_of_theme', path.abspath(path.dirname(__file__)))
If your theme package contains two or more themes, please call
add_html_theme()
twice or more.
バージョン 1.2 で追加: entry_points の sphinx_themes 機能
バージョン 1.6 で非推奨: sphinx_themes
entry_points has been deprecated.
バージョン 1.6 で追加: sphinx.html_themes
entry_points feature.
テンプレート¶
The guide to templating is helpful if you want to write your own templates. What is important to keep in mind is the order in which Sphinx searches for templates:
最初は、ユーザの
templates_path
ディレクトリその次は、選択されたテーマ内
それから先は、テーマの継承元のテーマを順に探索
継承元のテーマに含まれるテンプレートと同名のテンプレートを作成して、拡張する場合には、 {% extends "継承元のテーマ名/layout.html" %}
という風にテーマ名をディレクトリとして明示して行います。ユーザの templates_path
の中のテンプレートでも、 "エクスクラメーションマーク(!)" のシンタックスを使用して、テンプレートのドキュメント内であると指定することもできます。
静的テンプレート¶
テーマオプションを使用すると、ユーザがカスタムのスタイルシートを書く必要もなく、テーマを簡単にカスタマイズできるようになります。これはHTMLファイルと同じように、テンプレート静的ファイルでも行えます。Sphinxはこのために、"静的テンプレート"と呼ばれるものをサポートしています。
もし、テーマの中の static/
ディレクトリ(もしくはユーザの静的ファイルパス)の中に、末尾が _t
のファイルがあったとすると、そのファイルはテンプレートエンジンによって処理されます。 _t
は最終的なファイル名からは除外されます。例えば、 classic テーマは static/classic.css_t
というファイルを持っていますが、これは色のオプションを持ったスタイルシートのテンプレートです。ドキュメントがビルドされる時に、すべてのテンプレートタグが処理されて、色のオプションがスタイルシートに書き込まれて、出力ディレクトリには _static/classic.css
ファイルとして出力されます。
Use custom page metadata in HTML templates¶
Any key / value pairs in field lists
that are placed before the page's title will be available to the Jinja
template when building the page within the meta
attribute. For example,
if a page had the following text before its first title:
:mykey: My value
My first title
--------------
Then it could be accessed within a Jinja template like so:
{%- if meta is mapping %}
{{ meta.get("mykey") }}
{%- endif %}
Note the check that meta
is a dictionary ("mapping" in Jinja
terminology) to ensure that using it in this way is valid.
Defining custom template functions¶
Sometimes it is useful to define your own function in Python that you wish to then use in a template. For example, if you'd like to insert a template value with logic that depends on the user's configuration in the project, or if you'd like to include non-trivial checks and provide friendly error messages for incorrect configuration in the template.
To define your own template function, you'll need to define two functions inside your module:
A page context event handler (or registration) function. This is connected to the
Sphinx
application via an event callback.A template function that you will use in your Jinja template.
First, define the registration function, which accepts the arguments for
html-page-context
.
Within the registration function, define the template function that you'd like to use within Jinja. The template function should return a string or Python objects (lists, dictionaries) with strings inside that Jinja uses in the templating process
注釈
The template function will have access to all of the variables that are passed to the registration function.
At the end of the registration function, add the template function to the
Sphinx application's context with context['template_func'] = template_func
.
Finally, in your extension's setup()
function, add your registration
function as a callback for 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)
Now, you will have access to this function in jinja like so:
<div>
{{ my_func("some string") }}
</div>
Add your own static files to the build assets¶
If you are packaging your own build assets with an extension
(e.g., a CSS or JavaScript file), you need to ensure that they are placed
in the _static/
folder of HTML outputs. To do so, you may copy them directly
into a build's _static/
folder at build time, generally via an event hook.
Here is some sample code to accomplish this:
def copy_custom_files(app, exc):
if app.builder.format == 'html' and not exc:
staticdir = path.join(app.builder.outdir, '_static')
copy_asset_file('path/to/myextension/_static/myjsfile.js', staticdir)
def setup(app):
app.connect('builder-inited', copy_custom_files)
Inject JavaScript based on user configuration¶
If your extension makes use of JavaScript, it can be useful to allow users to control its behavior using their Sphinx configuration. However, this can be difficult to do if your JavaScript comes in the form of a static library (which will not be built with Jinja).
There are two ways to inject variables into the JavaScript space based on user configuration.
First, you may append _t
to the end of any static files included with your
extension. This will cause Sphinx to process these files with the templating
engine, allowing you to embed variables and control behavior.
For example, the following JavaScript structure:
mymodule/
├── _static
│ └── myjsfile.js_t
└── mymodule.py
Will result in the following static file placed in your HTML's build output:
_build/
└── html
└── _static
└── myjsfile.js
See 静的テンプレート for more information.
Second, you may use the Sphinx.add_js_file()
method without pointing it
to a file. Normally, this method is used to insert a new JavaScript file
into your site. However, if you do not pass a file path, but instead pass
a string to the "body" argument, then this text will be inserted as JavaScript
into your site's head. This allows you to insert variables into your project's
JavaScript from Python.
For example, the following code will read in a user-configured value and then insert this value as a JavaScript variable, which your extension's JavaScript code may use:
# 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')
# Run the function after the builder is initialized
app.connect('builder-inited', add_js_variable)
As a result, in your theme you can use code that depends on the presence of
this variable. Users can control the variable's value by defining it in their
conf.py
file.
- 1
これは
conf.py
とは異なり、実行可能はPythonファイルではありません。これは、テーマが共有されても、不必要なセキュリティのリスクを抱えないようにするために、このようになっています。