Miyadaiku を始めよう
2018-03-21

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

先日 WordPress から Miyadaiku に 引っ越しました

WordPress からの 記事移行については WordPressからMiyadaikuへの記事移行 を参考ください。

というわけでみんなもやろうぜ!

Note

  • この記事では 現時点での最新である 0.0.51 のバージョンを使います。

Miyadaiku とは what what

ぁっぉ さんが開発した 静的サイトジェネレータです。 python.jp もこれでできているそうです。

Miyadaiku リファレンス に書いてある先頭 数行 を引用します。

Miyadaiku は、 Jinja2職人のための静的サイトジェネレータです。

  • コンテンツを reStructuredText, Markdown, HTML, Jupyter Notebook, YAML で記述できます。

  • Jinja2 テンプレートでコンテンツからHTMLを作成します。

.ipynb ファイルを配置することで Jupyter Notebook に書いたことをそのまま記事にすることができるので データサイエンティストにとってもうれしいんじゃないでしょうか。

これは どりらん さんのご提案だそうです。すばらしい! (ブログをリニューアルしました)

Jupyter Notebook の記事もいつか書いてみたいですねぇ。

デフォルトのテーマでどういったページが作れるかは サンプル を参照ください。

セットアップ setup setup

Note

  • Python 3.6 以上に対応しているそうなので、最新のPythonをインストールしてからご利用ください。

  • 基本的にこの内容は チュートリアル に書いてあるので、詳しく知りたい方はそちらを参照ください。

まずはインストールから

$ pip install miyadaiku

とします。

セットアップは簡単で、

$ miyadaiku-start ./blog # blog/ に作る場合

とするだけです。これによって、対象のディレクトリ (ここでは ./blog/ 配下)に 設定ファイルとディレクトリが作られます。

設定ファイル config config

この状態でもすでにサイトは作成できる状態になっていますが、まずは設定ファイルをいじりましょう。

まず、プロジェクト全体の設定するため 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 がコメントアウトされているので 外しておきます。

他のテーマを利用する場合は ここを変えます。組み込みテーマ以外は別途インストールが必要です (テーマ リファレンス)

ここで設定した項目は テンプレートから読み出すことができます。

チュートリアルではサイトとブログで分かれていますが、基本的にやることは同じです。 そして、ここではブログを作る前提で進めます。普通のサイトの方が設定は少ないと思います。

ディレクトリ構造を知る construction construction

Miyadaikuプロジェクト ページ を読むのが早いですが解説します。

contents/ contents contents

記事などの文書を入れるディレクトリです。ここに入れたファイルの内

  • reStructuredText (.rst)

  • Markdown (.md)

  • HTML (.html)

  • Jupyter Notebook (.ipynb)

  • YAML (.yml or .yaml)

に該当するファイルはビルドの対象となります。

それ以外のファイルはビルド対象から外れますが 公開対象にはなります。

特定の記事からのみ参照するような画像などはこのディレクトリに入れておくとよいでしょう。

Note

これは個人的な感覚ですが 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/ files files

画像などのメディアファイルを入れるファイルです。 私は JavaScript ファイルをここに配置しています。

サイト全体から参照するようなファイルはここにいれることになると思います。

outputs/ outputs 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/ templates 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 %}

記事を書いてみる article article

例えば以下のような記事 (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 |

- via: [Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#tables)

article ディレクティブには記事のメタ情報を記述し、それ以降には思いの丈を書きなぐってください。

上記の例で言うと image 以外は もともと意味が割り当てられています。 詳しくは アーティクル リファレンス を 参照してください。

ここに設定した内容は テンプレートから参照できます。

例えば、 :image: /test.png の用に設定しておけば {{ page.image }} などのようにして この値が読み出せます。自分はこのやり方で記事一覧の画像を出力しています。

もしかすると今後のアップデートによりこの属性に別の意味が割り当てられてしまうかもしれませんが、 その時は一括で書き換えればいいだけです。

ビルドする build build

$ 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

とすれば 自動ビルド と 簡易サーバが起動します。

Note

  • miyadaiku-start blog はやってある前提です。

  • localhost:8181 にアクセスすれば見れます。ポートとかは勝手にいじってください。

  • outputs/ に意図しないファイルが残っていると事故の元なので、起動のたびにリセットします。

さっきの記事とテンプレート作ったサイトにアクセスしてみます

http://localhost:8181/

index.png

http://localhost:8181/test/

article1.png

http://localhost:8181/test.html

article2.png

できましたね。

ちなみに自分の環境ではこれに加えて webpack の watch も動かしてます。