HUGO の Code Block Render Hooks を使って、コードブロックにファイル名を表示する

Posts

Markdown のコードブロックに記述したコードを、「foo.js」のようにファイル名をつけて表示できるようにします。
スクリーンショット:ファイル名付きで表示したコードブロックの例

この記事では、v0.93.0 で追加された Code Block Render Hooks を使います。
Code Block Render Hooks が追加されるまでは、下記のページで紹介されているように、ショートコードを実装する必要がありました。
ソースコードをハイライト表示する (highlight)

Code Block Render Hooks を使うと、Markdown Syntax のコードブロックのまま、ファイル名を表示できるようになります。
この場合、ショートコードを使うときとは異なり、JavaScript のコードであれば eslint-plugin-markdown を使って ESLint を適用できます。

動作を確認した環境

HUGO v0.93.0

Code Block Render Hooks とは

コードブロック用の Render Hooks は、layouts > _default > _markup の下に、render-codeblock.html を作成します。
参考. 公式ドキュメント

ファイルの位置
layouts
└── _default
    └── _markup
        └── render-codeblock.html
        └── render-codeblock-bash.html

表示する言語ごとに、Code Block Render Hooks テンプレートを出し分けることもできます。
render-codeblock- のプレフィックスと言語の識別子をファイルの名前につけます。
言語の識別子とは、````js` のようにバッククォート 3 つの後に付ける言語名のことです。

HUGO のドキュメントには、mermaid を使って図を表示する例が紹介されています。

ファイル名を表示する Code Block Render Hooks を実装する

コンテンツのファイルに、次のようにコードブロックを記述することを考えます。
表示するファイル名は、言語の識別子の後に {name="ファイル名"} のように記載します。

Markdownの例
```js {name="foo.js"}
(() => {
  'use strict';
  console.log("Hello World!");
})();
```

Code Block Render Hooks として、render-codeblock.html に次の内容を記載します。

render-codeblock.html
<div>
  {{- $name := .Attributes.name -}}
  {{ with $name }}<div class="codeblock--name">{{ . }}</div>{{ end }}
  <div class="codeblock--content">
    {{- highlight (.Inner | safeHTML) .Type .Options }}
  </div>
</div>

{} 内で渡したファイル名は、.Attributes で受け取ります。
コードブロック内の内容は .Inner で受け取ることができるため、highlight 関数でハイライト表示します。

HUGO でハイライト表示するときに {} 内へ指定できる、行番号の開始数などのオプションは、.Options に格納されます。
highlight 関数の第 3 引数として .Options を渡すと、同じように行番号の開始数などを指定できます。
行番号の開始数などのオプションの詳細は、Highlighting in Code Fences を参照してください。

例えば、次のように行番号を変更したり、行をハイライト表示するオプションを指定して Markdown を書いたとします。

Markdownの例
```js {linenos=table,hl_lines=["2-3"],linenostart=199,name="foo.js"}
(() => {
  'use strict';
  console.log("Hello");
})();
```

前述のrender-codeblock.html では highlight 関数に .Options` を渡しているため、指定したオプションが反映されています。

スクリーンショット:行番号の開始や行のハイライトを指定したときの例

ちなみに、今回のファイル名の表示部分には、次のような css を適用しています。

.codeblock--name {
  width: fit-content;
  margin: 1rem 0 0;
  padding: 0.4rem;
  font-size: 0.9rem;
  color: rgb(255, 255, 255);
  background-color: #05acc1;
}

.codeblock--name + .codeblock--content {
  margin-top: 0;
}