HugoのMarkdown Render Hooksでコードブロックの出力をカスタマイズする
HugoのMarkdown Render Hooksでコードブロックを表示するマークダウン記法のレンダリング処理をカスタマイズして数式を表示できるようにしてみました。
はじめに
HugoではMarkdown Render Hooksという機能を利用することでマークダウンのHTMLへのレンダリング処理をカスタマイズすることができます。
以前アップした記事「HugoのMarkdown Render Hooksで画像の出力をカスタマイズする」ではこの機能を利用して画像を表示するマークダウン記法のレンダリング処理をカスタマイズしました。
今回はMarkdown Render Hooksを利用してTex
の数式をコードブロックに書くことでブラウザ上に数式が表示されるようにしました。
```math { title="行ベクトルと列ベクトルの内積" }
\begin{aligned}
\begin{pmatrix} 1 & 2 \end{pmatrix}
\begin{pmatrix} 3 \\ 4 \end{pmatrix}
&= 1 \times 3 + 2 \times 4 \\
&= 11
\end{aligned}
```
またオプションでタイトルを設定できるようにしました。
```math { title="行ベクトルと列ベクトルの内積" }
ショートコードで作成するか迷ったのですがMermaid Diagramsを表示するサンプルをみてMarkdown Render Hooksで作成することにしました。
数式を表示する方法について
Tex
の数式をブラウザ上に表示するライブラリではMathJaxが有名ですが、MathJaxより高速に動作するKaTeXを使用することにしました。
KaTeXを利用するには以下のドキュメントを参照してライブラリのスタイルシートとJavaScriptをページに読み込みます。
KaTeX supports all major browsers, including Chrome, Safari, Firefox, Opera, Edge, and IE 11.
KaTeXではレンダリング処理を自動で行ってくれる拡張機能が用意されています。
初期設定では以下のようにページ内の$$
のシンボルで囲まれた数式や\(
と\)
のシンボルで囲まれたインラインの数式などがその対象となっています。
数式を\\(\\KaTeX\\)で表示します。
$$
\begin{pmatrix} 1 & 2 \end{pmatrix}
\begin{pmatrix} 3 \\\\ 4 \end{pmatrix}
$$
数式を\(\KaTeX\)で表示します。 $$ \begin{pmatrix} 1 & 2 \end{pmatrix} \begin{pmatrix} 3 \\ 4 \end{pmatrix} $$
自動でレンダリング処理を行う対象を指定するシンボルは変更することもできます。
数式をマークダウンに書く場合の注意点
マークダウンにTex
の数式を書くだけでブラウザ上にKaTeXで数式がレンダリングされます。
ただしマークダウンではエスケープ文字が\
となっているため以下のように\\
を記述する場合\\\\
のように2重で記述する必要があります。
$$
\begin{pmatrix} 1 & 2 \end{pmatrix}
\begin{pmatrix} 3 \\\\ 4 \end{pmatrix}
$$
HTMLタグで囲むことで回避することは可能です。
<span>
$$
\begin{pmatrix} 1 & 2 \end{pmatrix}
\begin{pmatrix} 3 \\\\ 4 \end{pmatrix}
$$
</span>
このエスケープ文字を2重で書くことを回避したいこともあり数式の表示にコードブロックのMarkdown Render Hooksを利用しようと考えました。
コードブロックのMarkdown Render Hooksについて
まずはコードブロックのMarkdown Render Hooksについて調べたことをまとめます。公式のドキュメントは以下です。
Render Hooks allow custom templates to override markdown rendering functionality.
テンプレートを作成する場所
コードブロックのMarkdown Render Hooksではマークダウンのレンダリング処理をカスタマイズするテンプレートを作成します。
- layouts
- _defaultすべてのページで利用されるテンプレートはこのフォルダに配置します
- _markup
- render-codeblock.htmlコードブロック全般で利用されるテンプレートです
- render-codeblock-math.htmlmathを指定したコードブロックで利用されるテンプレートです
- render-codeblock-javascript.htmljavascriptを指定したコードブロックで利用されるテンプレートです
- postsタイプがpostsのページで利用されるテンプレートはこのフォルダに配置します
- _markup
- render-codeblock.htmlタイプがpostsのページのコードブロック全般で利用されるテンプレートです
特定のページのタイプやセクションで利用したいテンプレートはそのページのタイプやセクションのフォルダ以下に作成します。
またファイル名に-言語
をつけたテンプレートを作成することでコードブロックの言語ごとに利用されるテンプレートを切り替えることができます。
テンプレートに渡されるパラメータの確認
コードブロックのMarkdown Render Hooksのテンプレートに渡されるパラメータを確認するため以下のテンプレートを作成しました。
テンプレートを作成したらコードブロックを表示するマークダウン記法を書いてレンダリングされた内容からパラメータの値を確認してみます。
```actionscript { hl_lines=1, title=Title }
<p>Inner Text</p>
```
以下のHTMLがレンダリングされました。
<pre>
.Page |{Page(/posts/blog/hugo-render-codeblock/index.md) nopPage nopPage}
.Options |map[hl_lines:1]
.Attributes |map[title:Title]
.Type |actionscript
.Inner |<p>Inner Text</p>
.Ordinal |8
.Position |"E:\blog\content\posts\blog\hugo-render-codeblock\index.md:163:1"
</pre>
ドキュメントにもありますがOptions
にChroma Lexerで指定することができるオプションが設定されるのはコードブロックにChroma Lexerが対応している言語が指定されている場合のみです。
テンプレート名をrender-codeblock-math.html
で作成した場合の出力は以下です。
<pre>
.Page |{Page(/posts/blog/hugo-render-codeblock/index.md) nopPage nopPage}
.Options |map[]
.Attributes |map[hl_lines:1 title:Title]
.Type |math
.Inner |<p>Inner Text</p>
.Ordinal |10
.Position |"E:\blog\content\posts\blog\hugo-render-codeblock\index.md:164:1"
</pre>
Chroma Lexerの対応する言語にmath
という言語がありませんのでChroma Lexerで指定することができるオプションもAttributes
に設定されます。
コードブロックで数式を表示するテンプレートの作成
まずコードブロックで数式を表示するMarkdown Render Hooksのテンプレートを作成することで実現したいことは以下です。
- エスケープ文字を2重で書くことを回避する
- 自動でレンダリングされる数式のシンボルの記述を一か所で行う
- 数式を書いたときにだけKaTeXのライブラリを読み込むようにする
コードブロックにmath
を指定した場合に利用されるMarkdown Render Hooksの以下のテンプレートを作成しました。
Inner
にはコードブロックの中に書いた数式が設定されているので$${{ .Inner }}$$
とすることで常に同じシンボルで記述されることになります。
またInner
はマークダウンとしてレンダリングせず、そのまま出力することでエスケープ文字を2重で書くことを回避しています。
あとは「3. 数式を書いたときにだけKaTeXのライブラリを読み込むようにする」ですが、この数式を表示するテンプレートが使用されたかどうかのフラグuseMath
をページのStore
に設定します。
{{- .Page.Store.Set "useMath" true -}}
レイアウト用のテンプレートにはページのStore
のuseMath
がtrue
の場合にKaTeXのライブラリを読み込むように設定を追加しました。
インラインの数式のみページに書いた場合のためページのParams
の設定でもKaTeXのライブラリを読み込むようにしています。
ページのContent
の呼び出しよりも後ろに設定を追加している理由はMarkdown Render HooksではページのStore
に設定した値はページのContent
が呼び出された後でしか参照することができないためです。
おわりに
今回はコードブロックのMarkdown Render Hooksについて調べてTex
の数式を表示するために利用してみました。
ショートコードの場合は使用されたかどうかをページのContent
を呼び出しより前にHasShortcode
でチェックすることができますがMarkdown Render Hooksの場合はContent
を呼び出しより後でしか使用されたかどうかチェックできない点は少し使いずらいとは思います。
また今回の方法はmath
という存在しない言語を利用した少し強引なやり方ではありますが今のところ満足しています。