2018-03-21

Miyadaiku を始めよう

アイコンがない場合は イラスト屋さん を使えばいいことに気づきました。

  • この記事では 現時点での最新である 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/ に置きましょう。

私は以下の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)}}">&larr;</a>{% endif %} {% if not is_last %}<a href="{{ page.path_to(page, values=group_values, npage=cur_page+1) }}">&rarr;</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 も動かしてます。