舎路(シアトル)日記

シアトルで働く日本人プログラマの日記です

以前に Saqoosha さんが、WordPress を JSON を出力できる管理画面として使って、dot by dot inc. のコーポレートサイトを作っていて

Inside “dotby.jp 2015”

日々増えるニュースを簡単に更新できるようなブログ形式、前バージョンの背景エフェクトもってくる(かつページ遷移においてリロードしない=エフェクトを途切れさせない)という前提で検討した結果、WordPress を CMS に使いつつ WP REST API で JSON ひっぱってきて React でごにょごにょやるんがいーかなーと。

そういうことを Hugo でやるためにはどうすればいいのか、という話。

Custom Output Formats

Hugo には Output Formats という仕組みがあって、この種類のページには、こういうフォーマットでも出力してください、ということを指定できる。テンプレートファイルをどこに配置するかは、Templates for Your Output Formats という章で例示をまじえて説明されている。

私の場合は、全記事のタイトル、日付、そしてリンクをふくんだ JSON ファイルを生成したかったので、config.toml に

[outputs]
home = ["html", "rss", "json"]

というのを書き足して、自作テーマの一部として themes/x17/layouts/index.json というファイルを作成した。

テンプレートのなかみ

Hugo のテンプレートは Go の html/template をベースにしつつも、多様な要望に応えるためのミニプログラミング言語化しつつあり、正直ちょっと厳しい。

{{ $.Scratch.Add "items" slice }}

{{- range where .Data.Pages "Section" "post" -}}
  {{- $.Scratch.Add "items" (dict "title" .Title "published" .PublishDate "url" .Permalink) -}}
{{- end -}}

{ "items": {{ $.Scratch.Get "items" | jsonify }} }

今回のテンプレートはこんな感じで

  • Scratch はローカル変数を宣言する代わりに使える連想配列
  • slice, dict, range などは、それぞれ Hugo の定義している テンプレート関数 で、リスト、連想配列などを返す。
  • .Data.Pages は Hugo が用意している テンプレート変数 のひとつで、記事のデータにアクセスするために使う。

といったことがわかれば、なんとなく雰囲気で読めると思う。

JSON をテンプレートで出力するのは、最後に余計なカンマをつけてしまったり、エラーのもとになりがちなので、ここでは、普通に変数として JSON の構造を組み立てて、最後にそれを jsonify に渡して変換している。