HUGOで独自Shortcodeを作る

Blog

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" "ひよこまめ" >}}
  • 引数として、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を作成します。

例: <div style="padding: 0.75em; margin-bottom: 1rem; color: #fff; background-color: #78c2ad; border: 1px solid transparent; border-radius: 0.25rem;">こんな感じにメッセージを表示するメッセージブロック</div>

完成イメージ

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

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

次のようなHTMLを生成します[^1]。 [^1]: 本来は、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 }}で取得します。