📚

【Hugo】Shortcodesの内側のMarkdownのレンダリング

2021/02/06に公開

TL; DR

  • Hugo のShortcodes 内部でMarkdownがうまく変換されなかったことのトラブルシューティング
  • Shortcodesは2種類の構文(%構文と<構文)があり、内側の文章をMarkdownパーサーに渡すかどうかが違う
  • v0.60から、デフォルトパーサーがgoldmarkになり、HTMLの入力を <-- raw HTML omitted --> と無視するので余計にややこしく
  • 一番内側に%構文で何もしないShortcodesを呼び、外側のShortcodesは全て<構文で呼べばよい

1. Hugoの基本

静的サイトジェネレータのHugoを利用してブログプロジェクトサイトを構築しています。HugoはGoで書かれており、Markdownからの変換が速いとしばしば言われています。(私も、CIで毎回生成し直していますが、特に生成時間が気になったことはありません。)

2. HugoのShortcodesの基本

Hugoには、Shortcodesというテンプレート機能により、Markdownで表現できないような複雑なHTMLをサイトに含めることができます。

Shortcodesは、以下の3つのパターンがあります。

  1. ユーザー独自のShortcodes
    • layouts/shortcodes/(ショートコード名).html
  2. 利用しているテーマが提供するShortcodes
    • theme/(テーマ名)/layouts/shortcodes/(ショートコード名).html
  3. Hugo本体が提供する公式Shortcodes

ショートコードは、HTMLのタグのように、開く・閉じるのセットが基本となっており、その利用は次の2つの構文があります。

  1. {{< ショートコード名 >}}文章{{< /ショートコード名 >}}
    • 内側の文章を生の文字列として扱い、これ以上何も変換しない
    • この記事では、<構文と呼ぶ
  2. {{% ショートコード名 %}}文章{{% /ショートコード名 %}}
    • 内側の文章をMarkdownパーサーに渡す
    • この記事では%構文と呼ぶ

(v0.55で%構文の挙動が変わったみたいだが、ドキュメントがよく分からないと多くの人が言っている。私にも何を言っているのか良く分からなかったので、今回のトラブルシューティングが大変だった。)

3. 遭遇したトラブル

元々全て%構文でShortcodesを呼び出していたが、Shortcodesをネストさせたら <-- raw HTML omitted --> と表示され、本来の文章がなくなってしまった。これは、v0.60以降デフォルトのMarkdownパーサーが、Blackfridayからgoldmarkに変更になったことに由来するらしい。
(少しでもHTMLが含まれていると、HTMLタグだけではなくその文章の断片全体を取り除くので被害は甚大でした。)

尚、以下のようにgoldmarkの設定を変えるとHTMLの入力を許容するらしいが、unsafe と言われると嫌だなぁと思い他の対処法を探すことにした。

config.toml
[markup]
  [markup.goldmark]
    [markup.goldmark.renderer]
      unsafe = true

4. 対処法

HTMLに変換済みの文章を再度goldmarkにわたすことが問題のため、以下のような何もしないShortcodesを作成して、Markdownを変換したい内側の文章だけをそのShortcodesの%構文でラップする。本来利用したかった外側のShortcodesは全て<構文で呼び出してやれば良い。
(※ もし、利用しているテーマが markdownify という名前でShortcodesを提供していると覆い隠してしまうので、別の名前をつけてください。)

layouts/shortcodes/markdownify.html
{{.Inner}}
index.md
{{< (本来利用したいShortcodes) >}}
{{% markdownify %}}
[リンク](example.com)
{{% /markdownify %}}
{{< /(本来利用したいShortcodes) >}}

参考文献

Discussion