HUGO で独自 Shortcode を作る

October 15, 2019

HUGO では、記事ファイルを軽量マークアップ言語である Markdown 形式で作成します。しかし、Markdown の表現力には限りがあるため、HTML に頼りたくなる場合があります。 とはいえ、何度も同じような HTML を記述するのは面倒& HTML タグを記述することでファイルの可読性が落ちてしまいます。

この問題を解決するため、HUGO には、Shortcode(以下、ショートコード)という機能があります。 Markdown ファイル内で {{< ショートコード名 >}} と記述すると、コンテンツ内にショートコードとして定義したテンプレートファイルの HTML の内容を埋め込ます。

HUGO には、Twitter ツイートや Gist コードの埋め込みなど、ビルドインのショートコードが用意されています。 一方で独自にショートコードを作成できるので、この記事ではテンプレートファイルの作成方法を説明します。

リンクを新規タブで開くショートコードを作る

Markdown で [リンク名](リンクURL) と記述すると、そのリンクは同一タブに開かれます。 新規タブで開きたい場面もあるので、新規タブで開くようなショートコード target_blank を作成します。

完成イメージ

このショートコードは、記事ファイルに次のように記述します。

{{< target_blank url="https://blog.chick-p.work" title="ひよこまめ" >}}
  • 引数として、src にリンク先の URL、title に a タグを設定する文字列を渡します。

次のような HTML を生成します。

生成される HTML:

<a href="https://blog.chick-p.work" target="_blank">ひよこまめ</a>

テンプレートファイルの作成

ショートコードは、layouts/shortcodes というディレクトリの下にある、ショートコードと同名の HTML ファイルをテンプレートファイルとして認識します。

  1. layoutsの下に、shortcodes というディレクトリを作成します。

  2. ショートコードと同じ名前の HTML ファイルを作成します。今回のショートコード名は target_blank なので、target_blank.html を作成します。

    ├── ...
    ├── layouts
    │   ├── shortcodes
    │   │   └── target_blank.html
    ├── ...
  3. target_blank.html に次の HTML を記述します。

    {{- $url := .Get "url" -}}
    {{- if not $url -}}
      {{ errorf "missing value for param 'url': %s" .Position }}
    {{- end -}}
    <a href="{{ $url }}" target="_blank">{{ .Get "title" }}</a>
    • HUGO では、変数や関数を{{ }}で囲います(参考:HUGO のテンプレート記法)。
      • - は、前後の空白や改行をトリムします。
    • ショートコードで渡された引数は、.Get "引数名"で受け取ることができます。
    • $変数名 := 値 の形で変数を定義します。変数 $url に引数の url で渡された値を設定しています。
    • 1〜3行目は、url が未指定または値が空なら、エラーとする処理です。
      • IF 文は{{ if 条件式 }} 条件式が成り立つときの処理 {{ end }} という形で記述します。
    • {{ $変数名 }} で定義した変数の値を呼び出します。

メッセージブロックを表示するショートコードを作る

Bootstrap のアラートのようなメッセージブロックを表示するショートコード message_box を作成します。

例:

こんな感じにメッセージを表示するメッセージブロック

完成イメージ

このショートコードは、記事ファイルに次のように記述します。

{{< message_box color="success" >}}
表示したいコメント
{{< /message_box >}}
  • ショートコードの{{</* message_box */>}}{{</* /message_box */>}}で囲まれた内容をブロック内の文字列として出力します。
  • 引数 color で色を指定します(successdangerwarning を指定可能とする)。

次のような HTML を生成します11: 本来は、CSS 部分はクラスを定義して独自のスタイルシートファイルを読み込んだほうがよいですが、今回は割愛します。

<div style="padding: 0.75em; margin-bottom: 1rem; color: #fff; background-color: #78c2ad; border: 1px solid transparent; border-radius: 0.25rem;">
  表示したいコメント
</div>

テンプレートファイルの作成

  1. layouts/shortcodes の下に、message_box.html を作成します。

    ├── ...
    ├── layouts
    │   ├── shortcodes
    │   │   └── message_box.html
    ├── ...
  2. message_box.html に次の HTML を記述します。

    {{- $color:= .Get "color" -}}
    {{- if not $color -}}
      {{ errorf "missing value for param 'color': %s" .Position }}
    {{- end -}}
    {{- $bgcolor := "" -}}
    {{- if eq $color "success" -}}{{ $bgcolor = "#78c2ad" }}
    {{- else if eq $color "danger" -}}{{ $bgcolor = "#ff7851" }}
    {{- else if eq $color "warning" -}}{{ $bgcolor = "#ffce67" }}
    {{- else -}}{{ $bgcolor = "#6cc3d5" }}
    {{- end -}}
    <div style="padding: 0.75em; margin-bottom: 1rem; color: #fff; background-color: {{ $bgcolor }}; border: 1px solid transparent; border-radius: 0.25rem;">
      {{- .Inner -}}
    </div>
    • {{ if 条件 }}$color の値に応じて、$bgcolor に値を設定します。
      • if eq 値1 値2 で「値1と値2が等しければ」となります。
      • 一度定義した変数は $変数名 = 値 で値を再代入できます。
    • {{< ショートコード名 >}}{{< /ショートコード名 */>}}で囲まれた内容の値は {{ .Inner }}で取得します。