HTMLテーマ開発

バージョン 0.6 で追加.

注釈

このドキュメントでは、独自のテーマを作成する方法について説明します。既存のHTMLテーマを使用するだけの場合は、HTMLテーマを参照してください。

Sphinxは、テーマ を介してHTML出力の外観を変更することをサポートしています。テーマは、HTMLテンプレート、スタイルシート、その他の静的ファイルのコレクションです。さらに、どのテーマを継承するか、どのハイライトスタイルを使用するか、テーマの外観をカスタマイズするためのオプションを指定する設定ファイルがあります。

テーマはプロジェクトに依存しないように設計されているため、変更なしに異なるプロジェクトで使用できます。

注釈

テーマの開発に役立つ可能性のある詳細については、Sphinx API を参照してください。

テーマの作成

テーマは、次のものを含むディレクトリまたはzipファイル(名前がテーマ名)の形式を取ります。

  • theme.toml ファイル(推奨)または theme.conf ファイルのいずれか。

  • 必要に応じてHTMLテンプレート。

  • ビルド時に出力静的ディレクトリにコピーされる静的ファイルを含む static/ ディレクトリ。これらは、画像、スタイル、スクリプトファイルなどです。

テーマ設定 (theme.toml)

theme.toml ファイルは、TOML ドキュメントであり、[theme] および [options] の2つのテーブルが含まれています。

[theme] テーブルは、テーマの設定を定義します

  • inherit (文字列): 設定、オプション、テンプレート、および静的ファイルを継承するベーステーマの名前。テーマ「先祖」からのすべての静的ファイルが使用されます。テーマは、継承されたテーマで定義されたすべてのオプションを使用します。最後に、継承されたテーマを使用して、不足しているテンプレートを見つけます(たとえば、"basic" がベーステーマとして使用されている場合、ほとんどのテンプレートはすでに定義されています)。

    "none" に設定すると、テーマは他のテーマを継承しません。継承は再帰的であり、継承されたテーマのチェーンを形成します(例:default -> classic -> basic -> none)。

  • stylesheets (文字列のリスト): 生成されたHTMLヘッダーに含まれるCSSファイル名のリスト。html_style 設定値を設定すると、この設定は上書きされます。

    複数のスタイルシートを含めるその他のメカニズムには、CSSでの @import または適切な <link rel="stylesheet"> タグを持つカスタムHTMLテンプレートの使用が含まれます。

  • sidebars (文字列のリスト): サイドバーテンプレートのリスト。これは、ユーザーが html_sidebars 設定値を介して上書きできます。

  • pygments_style (テーブル): 構文の強調表示に使用するPygmentsスタイルの名前を定義するTOMLテーブル。テーブルには、defaultdark の2つの認識されるキーがあります。dark キーで定義されたスタイルは、CSSメディアクエリ (prefers-color-scheme: dark) がtrueと評価されたときに使用されます。

    [theme.pygments_style.default] は、ユーザーが pygments_style 設定値を介して上書きできます。

[options] テーブルは、テーマのオプションを定義します。各キーと値のペアが変数名と対応するデフォルト値に対応するように構造化されています。これらのオプションは、ユーザーが html_theme_options で上書きでき、すべてのテンプレートから theme_<name> としてアクセスできます。

バージョン 7.3 で追加: theme.toml のサポート。

サンプル theme.toml ファイル

[theme]
inherit = "basic"
stylesheets = [
    "main-CSS-stylesheet.css",
]
sidebars = [
    "localtoc.html",
    "relations.html",
    "sourcelink.html",
    "searchbox.html",
]
# Style names from https://pygments.dokyumento.jp/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 を介して含めます。

  • stylesheet 設定は、HTMLヘッダーで参照されるカンマで区切られたCSSファイル名のリストを示します。CSSの @import テクニックを使用して他のCSSファイルから含めたり、必要に応じて <link rel="stylesheet"> タグを追加するカスタムHTMLテンプレートを使用したりすることもできます。html_style 設定値を設定すると、この設定は上書きされます。

  • pygments_style 設定は、強調表示に使用するPygmentsスタイルの名前を示します。これは、ユーザーが pygments_style 設定値で上書きできます。

  • pygments_dark_style 設定は、CSSメディアクエリ (prefers-color-scheme: dark) が true と評価されたときに強調表示に使用する Pygments スタイルの名前を示します。add_css_file() を使用してページに挿入されます。

  • sidebars 設定は、サイドバーを構築するためのカンマで区切られたサイドバーテンプレートのリストを示します。これは、ユーザーが html_sidebars 設定値で上書きできます。

  • options セクションには、変数名とデフォルト値のペアが含まれています。これらのオプションは、ユーザーが html_theme_options で上書きでき、すべてのテンプレートから theme_<name> としてアクセスできます。

バージョン 1.7 で追加: サイドバー設定

バージョン 5.1 で変更: stylesheet 設定が複数のCSSファイル名を受け入れるようになりました

theme.conftheme.toml に変換する

INI形式のテーマ構成ファイル(theme.conf)は、Sphinxに付属するヘルパープログラムを使用してTOMLに変換できます。これは1回限りの使用を目的としており、将来のバージョンのSphinxでは予告なしに削除される可能性があります。

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

必要な引数は、theme.conf ファイルを含むディレクトリへのパスです。プログラムは同じディレクトリに theme.toml ファイルを書き込み、元の theme.conf ファイルは変更しません。

バージョン 7.3 で追加.

テーマをPythonパッケージとして配布する

テーマを配布する方法として、Pythonパッケージを使用できます。これにより、ユーザーがテーマを設定しやすくなります。

テーマをPythonパッケージとして配布するには、pyproject.tomlファイル内でsphinx.html_themesというエントリポイントを定義し、add_html_theme() APIを使用してテーマを登録するsetup()関数を記述してください。

# 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()を2回以上呼び出してください。

バージョン 1.2 で追加: ‘sphinx_themes’ エントリポイント機能。

バージョン 1.6 で非推奨: sphinx_themes エントリポイントは非推奨になりました。

バージョン 1.6 で追加: sphinx.html_themes エントリポイント機能。

CSSによるスタイリング

stylesheets 設定を使用すると、カスタムCSSファイルをテーマに追加できます。

注意

HTML要素の構造とそのクラスは、現在、明確に定義されたパブリックAPIではありません。構築されたHTMLページを調べて推測してください。完全な安定性は保証できませんが、比較的安定している傾向があります。

カテゴリ別の検索結果エントリのスタイリング

バージョン 8.0 で追加。

検索結果の項目には、検索語が見つかったコンテキストを示すクラスがあります。CSSセレクタを使用できます。

  • ul.search li.context-index: 用語集などのインデックスでの結果の場合

  • ul.search li.context-object: Python関数定義のようなソースコードでの結果の場合

  • ul.search li.context-title: セクション見出しで見つかった結果の場合

  • ul.search li.context-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 */
}

テンプレート

自分でテンプレートを作成したい場合は、テンプレートガイドが役立ちます。覚えておくべき重要なことは、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になりました。

静的テンプレートの_tファイルサフィックスは、「レガシー」と見なされるようになり、サポートは最終的に削除される可能性があります。

_tサフィックスまたは.jinjaサフィックスのいずれかを持つ静的テンプレートが検出された場合、テンプレートエンジンによって処理され、サフィックスは最終的なファイル名から削除されます。

HTMLテンプレートでカスタムページメタデータを使用する

ページのタイトルのに配置されたフィールドリスト内の任意のキー/値ペアは、meta属性内でページを構築するときにJinjaテンプレートで使用できます。たとえば、ページに最初のタイトルの前に次のテキストがあった場合

:mykey: My value

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

その後、次のようにJinjaテンプレート内でアクセスできます。

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

この方法での使用が有効であることを確認するために、metaが辞書である(Jinja用語では「マッピング」)というチェックに注意してください。

カスタムテンプレート関数の定義

テンプレートで使用したい独自の関数をPythonで定義すると便利な場合があります。たとえば、プロジェクトのユーザー構成に依存するロジックを使用してテンプレート値を挿入したり、テンプレートで些細なチェックを含めて、正しくない構成に対してわかりやすいエラーメッセージを提供したりする場合などです。

独自のテンプレート関数を定義するには、モジュール内で2つの関数を定義する必要があります。

  • ページコンテキストイベントハンドラー(または登録)関数。これは、イベントコールバックを介してSphinxアプリケーションに接続されます。

  • Jinjaテンプレートで使用するテンプレート関数

最初に、html-page-contextの引数を受け入れる登録関数を定義します。

登録関数内で、Jinja内で使用したいテンプレート関数を定義します。テンプレート関数は、Jinjaがテンプレート処理で使用する文字列または文字列を含むPythonオブジェクト(リスト、辞書)を返す必要があります。

注釈

テンプレート関数は、登録関数に渡されるすべての変数にアクセスできます。

登録関数の最後に、context['template_func'] = template_funcを使用して、テンプレート関数をSphinxアプリケーションのコンテキストに追加します。

最後に、拡張機能の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スペースに変数を注入する方法は2つあります。

まず、拡張機能に含まれる静的ファイルの末尾に_tを追加できます。これにより、Sphinxはこれらのファイルをテンプレートエンジンで処理し、変数と制御動作を埋め込むことができます。

たとえば、次のJavaScript構造の場合

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

次の静的ファイルがHTMLのビルド出力に配置されます。

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

詳細については、静的テンプレートを参照してください。

次に、ファイルを参照せずにSphinx.add_js_file()メソッドを使用できます。通常、このメソッドは、新しいJavaScriptファイルをサイトに挿入するために使用されます。ただし、ファイルパスを渡さに、代わりに「body」引数に文字列を渡すと、このテキストはJavaScriptとしてサイトのheadに挿入されます。これにより、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ファイルで変数を定義することにより、変数の値を制御できます。