HUGOのCode Block Render Hooksを使って、コードブロックにファイル名を表示する
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="ファイル名"}
のように記載します。
```js {name="foo.js"}
(() => {
'use strict';
console.log("Hello World!");
})();
```
Code Block Render Hooksとして、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を書いたとします。
```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;
}