テーマを作成してみよう
MkDocsでは、他の人が作ったテーマを使ったり、部分的にカスタマイズして使うことができますが、Jinja
というテンプレートエンジンを使って、自分の作りたいように一から作ることもできます。ここでは、テーマを自作する方法を見ていきます。
自作テーマを使う設定
テーマに最低限必要なものは、main.html
ファイルだけです。docs
と同じ階層に別のフォルダを作って、その下にテーマ用のファイルを保存していきます。例えば、次のようにファイルを作ったとしましょう。
mkdocs.yml
docs/
index.md
about.md
custom_theme/
main.html
...
custom_theme
というフォルダを作ってその下にファイルを作っています。このフォルダ名は自分の好きなものにできます。このテーマを使うには、mkdocs.yml
ファイルに次のように設定します。
theme:
name: null
custom_dir: 'custom_theme/'
テーマを null
にし、custom_dir
に自作テーマを置いている場所を指定します。これで、自作テーマの内容がサイトに反映されます。
custom_dir
は、既存テーマの一部を上書きするためにも使われます。例えば、name: mkdocs
と設定すると、mkdocs
のテーマをベースとし、custom_dir
内で追加したファイルだけが上書きされてサイトに反映されます。
基本的なテーマ
以下では、具体的にテーマの作り方を見ていきます。
ただ、一から全部作るのは大変なので、テーマのひな型をダウンロードしておくといいでしょう。mkdocs-basic-theme からダウンロードできます。また、デフォルトで入っている2つのテーマ のファイルも参考になります。
main.html
には、通常の HTML ファイルのように書いていきます。HTML ファイルのひな型に、最低限、次のようにしていけば、ページの表示ができます。
<title>{% if page.title %}{{ page.title }} - {% endif %}{{ config.site_name }}</title>
head
タグ内には、上のようにするとタイトルが表示されます。波かっこでくくられた部分は、Jinja によるものです。MkDocs のテーマは、Jinja というテンプレートエンジンを使っています。。
page.title
はページタイトルで、if
や endif
は Jinja の文法です。波かっこ2つで表します。上のように書くと、ページタイトルがあれば、それが表示されます。config.site_name
は、mkdocs.yml
ファイルで設定した site_name
のことです。
<body>
{{ page.content }}
</body>
body
タグは、最低限これだけでもかまいません。page.content
は、ページの内容です。Markdown で書いたものが HTML に変換されて表示されます。
このように、MkDocs で用意されたいくつかの変数と、Jinja の文法を組み合わせてテーマを作っていきます。
テーマに関連するファイル
テーマ内のファイルは、ファイルの種類によって、build
時の処理方法が異なります。
画像や CSS ファイルなどは、そのままコピーされます。
テーマ内の HTML ファイルは、テンプレートファイルとして扱われます。MkDocs は、このテンプレートファイルと docs
フォルダの内容とを組み合わせて、各ページを作成します。
もし、HTML ファイルをそのままコピーしたい場合は、static_templates
を使います。例えば、mkdocs
テーマでは、次のように設定されています。
static_templates:
- 404.html
このように設定すると、404.html
ファイルは、変換されることなく、そのまま site
フォルダにコピーされます。
テーマに関連するメタファイルは、コピーされません。テーマの設定が入った mkdocs_theme.yml
ファイルや、Python ファイルは site
フォルダにはコピーされません。また、 .
から始まるファイルやフォルダも無視されます。
テンプレート変数
テンプレートを作る際には、いろいろな変数を使います。先ほど見た、page.content
や page.title
などはその例です。テンプレート変数はたくさんあるのですべては紹介できないですが、いくつか見ていきます。
config
mkdocs.yml
で設定した内容は、config
変数で呼び出せます。 config.site_name
は先ほどの例でも出てきました。自分で新しく設定することもできますが、config.site_description
や config.copyright
などは、いろいろなテーマで使われるでしょう。
nav
ナビゲーションに関する設定は、nav
変数を使います。例えば、次のように書きます。
{% if nav|length>1 %}
<ul>
{% for nav_item in nav %}
{% if nav_item.children %}
<li>{{ nav_item.title }}
<ul>
{% for nav_item in nav_item.children %}
<li class="{% if nav_item.active%}current{% endif %}">
<a href="{{ nav_item.url|url }}">{{ nav_item.title }}</a>
</li>
{% endfor %}
</ul>
</li>
{% else %}
<li class="{% if nav_item.active%}current{% endif %}">
<a href="{{ nav_item.url|url }}">{{ nav_item.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
nav
は、複数の navigation
から構成されています。
nav|length
の |length
はフィルターといって、こう書くと要素数が取得できます。「nav
の要素が1より大きければ」ということです。
{% for nav_item in nav %}
は、nav
にある各要素について処理する、ということです。各要素は nav_item
にいれています。その次に {% if nav_item.children %}
とありますが、これは、さらに下の階層があるかどうかを確認しています。
階層があればさらに下の階層を見ます。{% if nav_item.active%}
は、今見ているページかどうかを判定しています。今見ているページなら、current
クラスが追加されるので、さらに CSS で見た目を設定します。
{{ nav_item.url|url }}
は、ページへのリンクです。|url
は、これも先ほど出てきたフィルターと呼ばれるもので、こうするとパスを良い感じに調整してくれます。 {{ nav_item.title }}
はページのタイトルです。
こうして、2階層下までのナビゲーションを表示することができます。
page
page
オブジェクトに各ページの情報が入っており、それらすべてが pages
に入っています。nav
は docs
フォルダに入っているものよりも、mkdocs.yml
で行った設定が優先されますが、pages
は本当にすべての page
が入っています。また、フォルダ・ファイルのアルファベット順になっています。なので、nav
に含まれているものとは中身が違っていることもあります。
page
には、page.title
(ページタイトル)、page.content
(コンテンツ)、page.url
(ページへのリンク)といった、よく使うそうな属性が用意されています。例えば、次のような書き方ができます。
<a href="{{ page.url|url }}">{{ page.title }}</a>
|url
フィルターにより、相対パスに変換できます。pages
に対して行えば、全記事を一覧表示することができます。
目次を作ることもできます。Markdown ファイルで、h1
タグなどを使えば、自動的に id
がつきます。英語ならうまく変換できるのですが、日本語の場合は変換されず、数字だけになってしまいます。この h*
タグの情報は、page.toc
に入っています。これを利用して、次のような書き方ができます。
<ul>
{% for toc_item in page.toc %}
<li><a href="{{ toc_item.url }}">{{ toc_item.title }}</a></li>
{% for toc_item in toc_item.children %}
<li><a href="{{ toc_item.url }}">{{ toc_item.title }}</a></li>
{% endfor %}
{% endfor %}
</ul>
2階層までの目次を表示します。 title
や url
は、それぞれタイトルと URL です。 children
はさらに下の階層を取得するためのものです。
page.meta
を使えば、各ページのメタ情報を使うこともできます。次のように、Markdown ファイルの上の方でメタ情報の設定を行います。
---
mydata:
- aaa
- bbb
---
# ページタイトル
コンテンツ
YAML 記法でこのように書いたとしましょう。このとき、テンプレートに以下のように書けば、aaa
, bbb
がリストで表示されます。
<ul>
{% for myvalue in page.meta.mydata %}
<li>myvalue</li>
{% endfor %}
</ul>
ナビゲーション関係では、前後の記事を表す page.previous_page
や page.next_page
があり、親の階層を表す page.parent
があります。最初のページの前のページや、最上階層の上の階層など、該当するものが存在しない場合は、None
が返ります。
テンプレートフィルター
Jinja には、変数の値を表示する際に表記を変換する等の処理ができる、フィルター と呼ばれる機能があります。MkDocs ではJinja のフィルターも使用できますが、MkDocs で用意されているフィルターもあります。
すでに出てきていますが、url
フィルターがあります。これは、絶対パスはそのまま表示し、相対パスで page
から呼び出された場合は、そのページからの相対パスに変換されます。それ以外は、base_url
がついたものになります。
tojson
フィルターは、Python を JavaScript で使える値に変換します。
おわりに
ここでは、テーマを作るための流れや構成、使用できるテンプレート変数について見てきました。テーマを作るには、HTML の知識だけでなく、CSS や JavaScript の知識も必要で、Jinja についても知る必要があります。複雑なことをするには Python に関する知識も必要になってくるかもしれません。
次のページでは、Material テーマという、オススメのテーマについて見ていきます。そのまま使うこともできますし、テーマを自作したり、カスタマイズするのにも参考になるでしょう。