これはなに
静的サイトジェネレーターHugoで、ページ内リンクが日本語の際にうまく動作しない問題について解説し、その解決方法を述べる。
発生した問題
Hugoを使用して、本文中で日本語の小見出しをリンク参照したい場合に、次のように記述する。
[発生した問題](#発生した問題)
こうすることで、クリックして小見出しを参照できるリンクが生成されるはずである。 しかし、筆者の環境では、このリンクが正常に動作しなかった。
問題の原因
この問題は、Hugoがリンクのアンカータグ(タグ)を生成する際に、日本語の文字列を正しく扱えていないことが原因である。Hugoは、ページ内リンクのアンカータグを生成する際に、リンク先の見出しのテキストを元にID属性を付与し、そのID属性に基づいてa
タグのhref
属性を生成する。このとき、生成されたa
タグのhref
属性がエンコードされてしまったため、リンクが正常に動作しなかった。
つまり、筆者の環境で日本語を含むリンクがエンコードされてしまうことが問題の原因だった。
解決方法の実行
この問題を解決するために、リンクを貼った際にエンコードしないように設定した。
まず、元のテーマからlayouts/_default/_markup/render-link.html
をコピーする。
cp ./themes/hugo-theme-stack/layouts/_default/_markup/render-link.html ./layouts/_default/_markup/
元のファイルでは、次のように記述されていた。
<a class="link" href="{{ .Destination | safeURL }}" {{ with .Title}} title="{{ . }}"
{{ end }}{{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener"
{{ end }}>{{ .Text | safeHTML }}</a>
このhref="{{ .Destination | safeURL }}"
を、{{ printf "href=%q" .Destination | safeHTMLAttr }}
に変更する。変更後の記述は次のようになる。
<a class="link" {{ printf "href=%q" .Destination | safeHTMLAttr }}
{{ with .Title}} title="{{ . }}"{{ end }}
{{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener"
{{ end }}>{{ .Text | safeHTML }}</a>
{{ printf "href=%q" .Destination | safeHTMLAttr }}
にすることで、日本語の文字列がエンコードされずにhref
属性へ設定される。これにより、日本語のページ内リンクが正常に動作するようになる。
まとめ
この記事では、Hugoで日本語のページ内リンクが正常に動作しない問題とその解決方法を紹介した。問題の原因は、Hugoが日本語の文字列を正しく扱えないことであり、layouts/_default/_markup/render-link.html
のhref
属性の設定を変更することで解決した。Hugoを使用して日本語のページ内リンクを設定する際にお悩みの方は、ぜひこの解決方法を試してみてほしい。