アイコンがない場合は イラスト屋さん を使えばいいことに気づきました。
- この記事では 現時点での最新である
0.0.51
のバージョンを使います。
Miyadaiku とは
@ぁっぉ さんが開発した静的サイトジェネレータです。 python.jpもこれでできているそうです。 プログラミング言語 Python 総合情報サイト - python.jpプログラミング言語 Pythonの紹介・ダウンロードとインストール・Python入門講座などhttps://www.python.jp/index.html
Miyadaiku リファレンスに書いてある先頭 数行 を引用します。
Miyadaiku は、 Jinja2職人のための静的サイトジェネレータです。
- コンテンツを reStructuredText, Markdown, HTML, Jupyter Notebook, YAML で記述できます。
- Jinja2 テンプレートでコンテンツからHTMLを作成します。
.ipynb
ファイルを配置することで Jupyter Notebook に書いたことをそのまま記事にすることができるので
データサイエンティストにとってもうれしいんじゃないでしょうか。
これは @どりらん さんのご提案だそうです。すばらしい! (ブログをリニューアルしました)
Jupyter Notebook の記事もいつか書いてみたいですねぇ。
デフォルトのテーマでどういったページが作れるかは サンプル を参照ください。
セットアップ
info
- Python 3.6 以上に対応しているそうなので、最新のPythonをインストールしてからご利用ください。
- 基本的にこの内容は チュートリアル に書いてあるので、詳しく知りたい方はそちらを参照ください。
まずはインストールから
$ pip install miyadaiku
とします。
セットアップは簡単で、
$ miyadaiku-start ./blog # blog/ に作る場合
とするだけです。
これによって、対象のディレクトリ (ここでは ./blog/
配下)に 設定ファイルとディレクトリが作られます。
設定ファイル
この状態でもすでにサイトは作成できる状態になっていますが、まずは設定ファイルをいじりましょう。
まず、プロジェクト全体の設定するため config.yml
を編集します。
今回はこんな感じにしてみます
# Miyadaiku config file # Base URL of the site site_url: http://localhost:8181 # Title of the site site_title: sample # Default language code lang: en-US # Default charset charset: utf-8 # Default timezone timezone: Etc/UTC # List of site theme themes: - miyadaiku.themes.sample.blog
デフォルトでは themes
がコメントアウトされているので外しておきます。
他のテーマを利用する場合はここを変えます。 組み込みテーマ以外は別途インストールが必要です (テーマ リファレンス)
ここで設定した項目は テンプレートから読み出すことができます。
チュートリアルではサイトとブログで分かれていますが、基本的にやることは同じです。 そして、ここではブログを作る前提で進めます。普通のサイトの方が設定は少ないと思います。
ディレクトリ構造を知る
Miyadaikuプロジェクト ページ を読むのが早いですが解説します。
contents/
記事などの文書を入れるディレクトリです。ここに入れたファイルの内
- reStructuredText (
.rst
) - Markdown (
.md
) - HTML (
.html
) - Jupyter Notebook (
.ipynb
) - YAML (
.yml
or.yaml
)
に該当するファイルはビルドの対象となります。
それ以外のファイルはビルド対象から外れますが 公開対象にはなります。
特定の記事からのみ参照するような画像などはこのディレクトリに入れておくとよいでしょう。
info:
これは個人的な感覚ですが YAML
はコンテンツというより設定ファイルに近いものと考えたほうがよいかもしれません。
それ以外の形式のファイルは入力に対して 一つの HTML が出力されるのに対し
(type: snippet
の記事は除く: Snippet リファレンス)
YAMLは 一覧をどのように出力するかを定義するファイルなので、ページングの際に複数のHTMLが出力されることもありえます。
実際、リファレンスには以下のような記述が
コンフィグファイルは、Miyadaikuプロジェクト全体の設定や、 文書プロパティのデフォルト値をディレクトリごとに指定する YAMLファイルです。HTMLファイルは出力しません
参考
よし、 Ansible の Playbook を YAML で公開したろ 彡(\^)(\^)
みたいに考えてると KeyError
で落ちます 彡()()
(type:
が必須なんだね)
ビルドされたくないファイルは files/
に置きましょう。
解説ありがとうございます。
— Atsuo Ishimoto (@atsuoishimoto) March 21, 2018
miyadaikuで処理する必要のないyamlやrstは、filesディレクトリに入れておくとそのままコピーされます。e.g. contents/a/b/X.htmlに<a href='./sample.yaml'> とあれば、contents/a/b/sample.yamlではなく、files/a/b/sample.yaml にファイルを置いておきます。
私は以下の3つの YAML ファイルを配置しています。 ファイル名は拡張子以外に制約はないですが直感的な方が良いでしょう。
- ファイル名
- index.yml
- index_tags.yml
- atom.yml
- 目的
- 記事一覧画面を生成するため
- タグに紐付いた記事一覧画面を生成するため
- RSSフィードを生成するため 以前と同じように /feed/ でアクセスできるように index.html で出力していますが、 特に制約がない人は デフォルト で出力すればよいでしょう。
- コード
type: index # type を index に指定 indexpage_max_articles: 10 indexpage_template: 'page_index.html'
type: index # type を index に指定 indexpage_max_articles: 10 indexpage_template: 'page_index.html' indexpage_group_filename_templ: 'tags_{{ value }}.html' groupby: tags
type: feed # type を feed に設定 feedtype: atom feed_num_articles: 10 filename: feed/index.html
これによって、一覧画面(タグに紐づくタグ一覧も含む) と RSS フィード が生成されました。
一旦サイトが出来上がったら一番いじることになるのはこのディレクトリになると思います。
files/
画像などのメディアファイルを入れるファイルです。 私は JavaScript ファイルをここに配置しています。
サイト全体から参照するようなファイルはここにいれることになると思います。
outputs/
サイトとして公開するためのファイルが格納されるディレクトリです。
以下のファイルが ディレクトリ構造を保ったまま outputs/
にコピーされます。
contents/
配下のビルド済み(またはビルドからスキップされた) ファイルfiles/
配下のファイル
- warning
contents/
とfiles/
でファイル名が重複してもエラーにはならず、contents/
側のファイルが勝ちます(単なるコピー順の問題かもしれませんが)- 同じ名前のディレクトリがあると、その配下のファイルが混ざります。
contents/
(入力)1.txt
(a
と書かれている2.txt
(b
と書かれている
files/
(入力)2.txt
(c
と書かれている3.txt
(d
と書かれている
outputs/
(出力)1.txt
(a
と書かれている2.txt
(b
と書かれている3.txt
(d
と書かれている
- おそらく Undocumented な挙動なので、これを前提とした運用はオススメしません。
- 同じ名前のディレクトリがあると、その配下のファイルが混ざります。
contentns/
とfiles/
の両方からファイルが削除されたとしてもoutputs/
に残っているファイルは削除されません。- そのままアップロードすると意図しないファイルが公開される可能性があります
- すでに一回やりました汗
- その時は未公開のタグが 公開されてしまう不具合があったのですが
0.0.51
で修正されたので、手元のバージョンが低い人は上げましょう - 見ちゃった人は忘れてね (はーと
- その時は未公開のタグが 公開されてしまう不具合があったのですが
templates/
ページの出力するためのテンプレートを配置するディレクトリです。
用意されているテーマを使う場合はこのディレクトリを弄る必要はありません。 テンプレートは全てカスタマイズすることもできますし、既存のテーマを拡張することもできます。
テンプレートは Jinja2 と呼ばれるテンプレートライブラリで解析され出力されるので 拡張したい方は記法を勉強しておきましょう。
文書ページ を表す アーティクルテンプレート
と 一覧ページ
を表す インデックステンプレート
に分かれます。
アーティクルテンプレート
デフォルトでは templates/page_article.html
がアーティクルテンプレートとなります。
アーティクルテンプレートの中では 以下の変数を参照して記事を描画をします。
- page
- 該当記事の情報が格納されたオブジェクト
- contents
- すべてのコンテンツ情報が格納されたオブジェクト。 これは記事そのものだけでなくタグやカテゴリなどの情報も含みます。
メインの文章は contents/
に配置されたファイルがビルドされて描画されることになるので、
外側のレイアウトを考えることになります。
雑に 1 から作るとこんな感じでしょうか(ひどい
<html> <head><meta charset="{{ page.charset }}" /></head> <body> <h1>{{ page.title }}</h1><hr /> {{ page.html }} </body></html>
詳しくは テンプレート リファレンス を参照してください。
今回は テーマを拡張して使ってみます
この辺はドキュメントを見つけられなかったので、いじるときは テーマのソースコード を見ながら頑張りましょう。
{% extends "miyadaiku.themes.sample.blog!page_article.html" %} {% block container_body %} {{ article_metadata(page) }} <h1 class="article-title">{{ page.title }}</h1> <hr /> <b style="font-size: 30px">刮目せよ:</b> <div class="article-body">{{ page.html }}</div> {% endblock container_body %}
インデックステンプレート
デフォルトでは templates/page_index.html
がインデックステンプレートとなります。 (1ページ目と2ページ目以降でテンプレートを分けることもできるみたいです。
変数は結構たくさんあるので、これも詳しくは テンプレート リファレンス
を見てほしいんですが、 特に重要なのは 文書のリストが格納された articles
オブジェクトです。
記事一覧を出力するテンプレートを 1から書いてみます。(これもひどい
<html> <head><meta charset="{{ page.charset }}" /></head> <body> <h1>{{ cur_page }} ページ目の記事たち::</h1> <ul> {% for article in articles %} <li> {% if article.image %}<img src="{{ article.image }}" width="100" height="100" />{% endif %} <a href="{{ article.path() }}">{{ article.title }}</a> </li> {% endfor %} </ul> </body></html>
今回は テーマを拡張して使ってみます
{% extends "miyadaiku.themes.sample.blog!page_index.html" %} {% block container_body %} <ul> {% for article in articles %} <li> {% if article.image %}<img src="{{ article.image }}" width="50" height="50" />{% endif %} <a href="{{ article.path() }}">{{ article.title }}</a> </li> {% endfor %} </ul> {% if cur_page != 1 %}<a href="{{page.path_to(page, values=group_values, npage=cur_page-1)}}">←</a>{% endif %} {% if not is_last %}<a href="{{ page.path_to(page, values=group_values, npage=cur_page+1) }}">→</a>{% endif %} {% endblock container_body %}
記事を書いてみる
例えば以下のような記事 (estructuredText形式) を
contents/test/index.rst
として置きます。
.. article:: :title: test の記事 :tags: a, b, c :category: なにか :date: 2099-01-01 :canonical_url: /test/ :image: https://pbs.twimg.com/media/DXqgfdvW4AYg6wq.jpg aaa === .. code-block:: python def test(): print('test') bbb --- - ccc
一つだけでは寂しいのでもうひとつ(Markdown) で
contents/test2.md
を置きます。
date: 2017-01-01 title: testその2 category: カテゴリ1 tags: a, c, d | Tables | Are | Cool | | ------------- |:-------------:| -----:| | col 3 is | right-aligned | $1600 | | col 2 is | centered | $12 | - [Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#tables)
article
ディレクティブには記事のメタ情報を記述し、それ以降には思いの丈を書きなぐってください。
上記の例で言うと image
以外はもともと意味が割り当てられています。
詳しくは アーティクル リファレンス を参照してください。
ここに設定した内容は テンプレートから参照できます。
例えば、 :image: /test.png
の用に設定しておけば {{ page.image }}
などのようにして
この値が読み出せます。自分はこのやり方で記事一覧の画像を出力しています。
もしかすると今後のアップデートによりこの属性に別の意味が割り当てられてしまうかもしれませんが、 その時は一括で書き換えればいいだけです。
- info
- 記事は 拡張子だけが変換されて同じ階層に出力されます。
- 例えば、
contensts/
ディレクトリ上で/test.rst
ならoutputs/
には/test.html
として出力されますし、 今回の例だと/test/index.rst
なので/test/index.html
として出力されます。 - デフォルトでは 一覧ページから
.html
としてリンクされますが もともと/
で終わるような URL (trailing slash というそうです) の場合は.html
でリンクされては困ります。 - そこで
canonical_url
を指定すると その URL でリンクしてくれるようになります。 - 多くの Web サーバでは
/
で終わるディレクトリにアクセスすると そのディレクトリの配下に置かれたindex.html
を返してくれる設定になっているので/test/
というリンクを実現できます。
ビルドする
$ miyadaiku-build ./blog
とすることで、 outputs/
配下に ビルドされた ファイルが outputs/
に出力されます。
ここに対してアクセスをすればサイトが閲覧できます。
よって、 自分で配信するときはこのディレクトリ配下をすべてアップロードすれば良いです。
サーバ上でコマンドを実行する権限があるなら tgz
とかで送ってから展開&リプレースするのが簡単だと思います。
私はFTPの権限しかなかったので 一つひとつ転送するプログラム を書きました。
GitHub Pages でやる場合は このディレクトリ配下を Git リポジトリにして
$ git remote add origin git@github.com:username/reponame.git
みたいにすればいいでしょう。
初めから GitHub を使っている人は outputs/
配下を配信するように設定すればOKだと思います。
記事を更新するたびに ビルドするのがめんどくさいという方は --watch
でファイル更新を検知してビルドができます。
(たまに例外のキャッチに失敗して死にます)
毎回 ビルドコマンドを叩くのが面倒だという場合は Docker (docker-compose) を使うと便利です。
version: "3" services: blog: image: python:latest volumes: - .:/root/blog/ working_dir: /root/blog command: | /bin/bash -c "\ rm -rf outputs/ 2> /dev/null &&\ python3.6 -m venv venv/ 2> /dev/null &&\ venv/bin/pip install pip miyadaiku -U &&\ venv/bin/miyadaiku-build . --watch --server --port 8181" ports: - "8181:8181"
- warning
- これを使うときは
venv/
をリポジトリの管理対象から外すことをオススメします。
- これを使うときは
これを docker-compose.yml
として ディレクトリに配置して
$ docker-compose up
とすれば 自動ビルド と 簡易サーバが起動します。
- info
miyadaiku-start blog
はやってある前提です。localhost:8181
にアクセスすれば見れます。ポートとかは勝手にいじってください。outputs/
に意図しないファイルが残っていると事故の元なので、起動のたびにリセットします。
さっきの記事とテンプレート作ったサイトにアクセスしてみます
- http://localhost:8181/
- http://localhost:8181/test/
- http://localhost:8181/test.html
できましたね。
ちなみに自分の環境ではこれに加えて webpack の watch も動かしてます。