長らくHugoの未解決問題として、Shortcodeにfootnote(脚注)を組み合わせられない、というのがあった(当サイト調べ)。

別にHugoが悪いわけではなく、そもそも脚注はMarkdownの文章全体を見て構築する必要があるため、部分的にHTMLに処理してしまうShortcodeと相性が悪い。

例えば入力テキストをただ出力するだけのtext.htmlというshortcodeを作る。

{{- $text := .Get 0 -}}
{{ $text }}

これで以下のようなコードを書く

{{< text "**sample** text[^1]" >}}

以下のような出力となる。

markdownifyかけると ** のみHTMLに変換され、[^1] には無反応

{{- $text := .Get 0 -}}
{{ $text | markdownify }}

やりたいのは、この [^1] もちゃんと脚注としてレンダリングさせたい。

変換後のHTMLを直接出力させる

脚注がどう出力されるかは分かっているので、変換のHTMLをShortcodeから出力させる。具体的には、Hugoは[^1]と書くと <sup><a href="#fn:1">1</a></sup> のように変換することは分かっているので、それを直接出力させれば良い

{{- $text := .Get 0 -}}
{{- $processText := $text | replaceRE `\[\^(\d+)\]` `<sup><a href="#fn:$1" class="footnote-ref" role="doc-noteref">$1</a></sup>` | markdownify }}
{{ $processText | safeHTML}}

以下のように、右肩付き表示かつ脚注へのリンクが貼られた状態となる。

ただ、これだと右肩付きリンクが見えているだけで、脚注本体はレンダリングされない。本文に [^1] がなく、Hugoの脚注構築処理に入らないため。

ダミーの脚注リンクを設置する

隠し要素として、[^1]を書く。邪道だと思うけど、他にいい方法が全く思いつかない1

.hidden-footnote-refs {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
}

shortcodeの直前に、隠し要素を挿入する。

<span class="hidden-footnote-refs">[^1]</span>
{{< text "**sample** text[^1]" >}}

normal text[^2]

[^1]: link to hidden block
[^2]: normal footnote

以下のように、脚注リンクが表示され、かつ、脚注本体も表示される。通常の脚注との連番も問題ない。

vscode snippet

しかし <span class="hidden-footnote-refs">[^1]</span> をいちいち打つのはめんどくさい。クラス名なんて覚えてられないし。というわけで、vscodeのmarkdown snippetで入力補助を設定した。

"Hidden Footnote Reference": {
        "prefix": "hfn",
        "body": [
            "<span class=\"hidden-footnote-refs\">[^$1]</span>"
        ],
        "description": "Insert hidden footnote reference for caption footnotes"
    }

上記設定だと、hfnと打ってtabなりctrl+spaceで補完される。


  1. JavascriptでOverlayされる手もある ↩︎