はじめに

JekyllからHugoへの移行で一番困ったのが、Jekyllで利用していたAmazonの商品を表示するためのプラグインが利用できなくなることだった。

HugoにはShortcodeという記事内に独自タグを利用できるようにする機能があるのだが、以下の理由ですんなり利用できなかった。

  • Shortcodeは外部のデータリースを参照することが可能だが、JSONかCSVのみ
  • Amazonの商品情報を取得するためのAmazon Product Advertising APIのインタフェイスがXML

まあ、今時XMLで返してくれるなという話ではあるんだけども、こればっかりは仕方がない。

こういう事情から

JSONを返すAmazon Product Advertising APIのラッパーAPIを自前で用意する

というアプローチをしているケースが多かったので、自分もそうすることにした。

Amazon Product JSON

こういう小さな付属品的なアプリケーションは、インストールするというよりはバイナリデータをダウンロードしてきて実行ぐらいのお手軽感が良いかなと思ったので、Golangで作られているやつがないかなと思ったけど、良さげなのが無かったので自分で作ることにした。

longkey1/amazon-product-json

ちなみにバイナリデータはこちらのTagsページにある。

使い方

http://localhost:8888/items/{asin}のようにASINを渡せば、JSONが返してくれるという非常にシンプルなWebアプリケーション。

どこかのHTTPサーバに設置して常時使えるようにしているケースも見たが、それだけの為にHTTPサーバ用意するのも嫌だなと思ったので、自分の場合はその都度ローカルで立ち上げて利用することを想定している。

ビルド時の依存関係の解決が必要になったので、hugoコマンドを叩いてビルドするのを辞めて、makeコマンドでビルドするようにMakefileも用意した。
Makefile便利。

一度実行すれば、同じASINであればキャッシュされるので、全記事内に新しいASINが出てくるまで、hugo serverだけでOKになる。
これまた便利。

Shortcode

実際のShortcodeはこんな感じになった。

使い方

{{< amazon asin="{asin}" type="image-large" >}}

テンプレートファイル

自分のHTML力が乏しいので愚直な感じになっているが、ご愛嬌。

{{- $asin := .Get "asin" -}}
{{- $type := .Get "type" -}}
{{- $json := getJSON .Site.Params.AmazonProductJsonBaseURL $asin -}}
{{- $item := index $json.AmazonItems.Items 0 -}}
{{- $title := $item.ItemAttributes.Title -}}

<div class="amazon-box">
  {{ if eq $type "text" }}
    <a href="{{ $item.DetailPageURL }}" target="_blank"> {{ $title }}</a>
  {{ else if eq $type "image-small" }}
    {{- $image := $item.SmallImage -}}
    <img src="{{ $image.URL }}" alt="{{ $title }}" width="{{ $image.Width }}" height="{{ $image.Height }}"></img>
  {{ else if eq $type "image-medium" }}
    {{- $image := $item.MediumImage -}}
    <img src="{{ $image.URL }}" alt="{{ $title }}" width="{{ $image.Width }}" height="{{ $image.Height }}"></img>
  {{ else if eq $type "image-large" }}
    {{- $image := $item.LargeImage -}}
    <img src="{{ $image.URL }}" alt="{{ $title }}" width="{{ $image.Width }}" height="{{ $image.Height }}"></img>
  {{ else if eq $type "image" }}
    {{- $image := $item.MediumImage -}}
    <img src="{{ $image.URL }}" alt="{{ $title }}" width="{{ $image.Width }}" height="{{ $image.Height }}"></img>
  {{ end }}
</div>

とても簡単に実装できた。

おわりに

最初はどうしたもんかと思ったが、Shortcodesのような制約のあるシンプルな仕様でも、意外とどうにかなるもんだなと思った。
Golangには簡単なWeb APIサーバーを作る道具が結構揃っているので、今回みたいな用途には最適だなと思った。
HugoもGolang製だし。

参考