Hugoでは、ちょっとしたHTMLタグを記事やテンプレートに差し込みたいと思った場合、ShortCodesという便利な機能が使えます。

例えば、

  • Twitterのツイート埋め込み
  • Slideshare, Speakerdeckなどのスライドの埋め込み
  • Youtubeなどの動画埋め込み
  • Amazonアフィリエイトリンク
  • Instagramの写真
  • imgタグ
  • Adsense

などがあります。

Shortcodesのメリット

HTMLタグを直書きと比べて何が嬉しいかというと、

  1. 変更に強い
  2. 見た目がシンプル

の2点が挙げられます。

埋め込みURLでよくあるパターンが、各記事に主導でコードを埋め込んだはいいが、ちょっと変更を加えたいときに、1つ1つ直していかなければいけないというものです。

HTML直書きだと変更に対して明らかに弱いです。

一方、Shortcodesにしておけば、コードは変えずにレイアウトを後からいくらでも変更できます。サイトのテーマを変えたとしても、Shortcodesは変わりません。

このように変更に強いのはShortcodesのメリットです。

AMP化をするときも、このShortcodesが役になってくれました。 (img -> amp-imgも、Shortcodesのレイアウトを1箇所変換すれば、Shortcodesを埋め込んだ箇所全てが変更されます)

次に、「見た目がシンプル」になるのがメリットです。

HTML直打ちだと、divタグやらimgタグやらで、どうしてもごちゃごちゃしてしまいます。Shortcodesなら、{{% img src='/test.jpg' %}}と、シンプルに書くことができます。

Shortcodesのデメリット

逆にShortcodesのデメリットはあまり思いつきません。強いて挙げるならば、各種Webサービスの埋め込みコードはHTML直書きに最適化されており、単純にそのまま貼り付けても使えない点です。

一度、HTMLを貼り付けて、それを自分でShortcodes用に変換してあげる必要があります。難しいことはないのですが、ちょっと面倒です。

Shortcodesの作り方

1. hoge.htmlというファイルをlayouts > shortcodesの中に作る

2. hoge.htmlの中身を書く

例えば、baseurl.htmlとして、単純に.Site.BaseURLを返すだけのShortcodesの場合の記述例は以下の通り。

baseurl.html

{{ .Site.BaseURL }}

3. Shortcodesを呼び出したいところで、Shortcodesを記述する

例えば、記事中に以下のように記述する。

Shortcodes

{{% baseurl %}}

4. hugo serverでプレビューして確認する

https://www.meganii.com/ のようにShortcodes({{% baseurl %}})が展開される。

Shortcodesの例

Speakerdeck

{{% speakerdeck XXXXXXX %}}

AMP version

{{ $id := .Get 0 }}

<amp-iframe
  width="710"
  height="596"
  allowfullscreen
  sandbox="allow-scripts allow-same-origin allow-popups allow-presentation"
  layout="responsive"
  frameborder="0"
  src="https://speakerdeck.com/player/{{$id}}">
</amp-iframe>

Amazonアフィリエイト

例えば、以下のように名前付きと、引数1つの場合を切り分けたい場合、.IsNamedParamsを利用することで処理を分けることができます。

{{% amazon 477418392X %}}
{{% amazon id="477418392X" width="100" height="100" %}}

ここでの注意点は、Go Templateの変数スコープです。一般的な変数スコープなら、以下のようにif文の中で再代入できると思ったのですが、Go Templateでは再代入・再割当ができないっぽいです。

{{ $v := "init" }}
{{ if true }}
    {{ $v := "changed" }}
{{ end }}
v: {{ $v }} {{/* => init */}}

では、どのように回避するかというと、HugoではScratchというFunctionを利用するそうです。

text/template: add support for nested variable assignment · Issue #10608 · golang/go

Scratchの使い方

  • 設定 $.Scratch.Add "Name" "Value"
  • 取得 $.Scratch.Get "Name"

改めて、AmazonアフィリエイトのShortcodesです。$jsonデータは、Data Folderのファイルを読み込んでいます。

{{ $associateId := "meganii-22" }}
{{ $json := .Site.Data.amazon }}

{{ if .IsNamedParams }}
  {{ $.Scratch.Add "amazonItemId" ( .Get "id") }}
  {{ $.Scratch.Add "amazonItemWidth" ( .Get "width") }}
  {{ $.Scratch.Add "amazonItemHeight" ( .Get "height") }}
{{ else }}
  {{ $.Scratch.Add "amazonItemId" ( .Get 0) }}
  {{ $.Scratch.Add "amazonItemWidth" "100" }}
  {{ $.Scratch.Add "amazonItemHeight" "100" }}
{{ end }}

{{ $itemId := $.Scratch.Get "amazonItemId" }}
{{ $imgWidth := $.Scratch.Get "amazonItemWidth" }}
{{ $imgHeight := $.Scratch.Get "amazonItemHeight" }}

<div>
{{ range $json }}
  {{ if eq .Item.ASIN $itemId }}
  <div class="amazon-shortcode-box">
      <div class="amazon-shortcode-inner">
        <div class="amazon-shortcode-content">
          <div class="amazon-shortcode-image">
            <a href="http://www.amazon.co.jp/exec/obidos/ASIN/{{ $itemId }}/{{ $associateId }}/" name="amazon-shortcode">
              <amp-img class="thumb" src="{{ .Item.SmallImage.URL }}" alt="{{ .title }}" width="{{ .Item.SmallImage.Width }}" height="{{ .Item.SmallImage.Height }}" layout="fixed" />
            </a>
          </div>
          <div class="amazon-shortcode-body">
            <div class="amazon-shortcode-info">
              <p class="amazon-shortcode-title">
                <a href="http://www.amazon.co.jp/exec/obidos/ASIN/{{ $itemId }}/{{ $associateId }}/" name="amazon-shortcode">{{ .Item.ItemAttributes.Title }}</a>
              </p>
              {{ with .author }}
                <p class="amazon-shortcode-author">{{ . }}</p>
              {{ end }}
              <div class="amazon-shortcode-detail">
                {{ if or ( eq .productgroup "Book") (eq .productgroup "eBooks") }}
                  <p>出版社:{{ .publisher }}</p>
                {{ else }}
                  <p>{{ .label }}</p>
                {{ end }}
                {{ with .publicationdate }}
                  <p>発売日:{{ . }}</p>
                {{ end }}
              </div>
              <p>
                <a href="http://www.amazon.co.jp/exec/obidos/ASIN/{{ $itemId }}/{{ $associateId }}/" name="backport">
                  <i class="fa fa-amazon" aria-hidden="true"></i> Amazonで詳細を見る
                </a>
              </p>
            </div>
          </div>
        </div>
      </div>
    </div>
  {{ end }}
{{ end }}
<div>

ぜひあなたも、HugoのShortcodesを使って、便利に簡潔に記述してみませんか? おすすめのShortcodesがあったらぜひ教えてください。