HugoのRender Hooksを利用してブロックの表現を拡張する

当ブログはHugoで構築していて、Markdownを使って記述しています。テーマを簡単に作れるので、自作テーマで好みに合わせてカスタマイズできるのが気に入っています。

しかしHugoが解釈できるMarkdownで表現可能な書式には限界があります。 そのためか、Markdownの一部表記からHTMLへの変換内容を自分で定義できるRender Hooksという機能が用意されています。

Hugo v0.93.0からはcodeblockのhookが追加され、以下の4種類のhooksを定義できるようになりました。

  • image
  • link
  • heading
  • codeblock

今回はnoteという名前でcodeblockのhookを作成し、注釈を記載するためのブロックを表現できるようにします。

記述例

```note
このように左に注釈の種類を示すアイコンを、右に注釈文を表示するようにします。
```

表示例

情報
このように左に注釈の種類を示すアイコンを、右に注釈文を表示するようにします。

Render Hooksの作成

HugoのMarkdown Render Hooksマニュアルによると、layouts/_default/markup/フォルダに規則に従った名前のファイルを作れば良いようです。

自作のテーマに追加するので、テーマ側のフォルダにrender-codeblock-note.htmlを作成してみました。

アイコンはMaterial Design IconsからSVG形式のアイコンを使用させていただきました。

render-codeblock-note.html

<div class="note-block">
  {{- $type := default "info" .Attributes.type -}}
  <div class="icon">
    {{- if eq $type "info" }}
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="icon-info">
      <title>情報</title>
      <path d="M13,9H11V7H13M13,17H11V11H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" />
    </svg>
    {{- else if eq $type "warning" }}
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="icon-warning">
      <title>警告</title>
      <path d="M13 14H11V9H13M13 18H11V16H13M1 21H23L12 2L1 21Z" />
    </svg>
    {{- else if eq $type "errata" }}
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="icon-errata">
      <title>訂正</title>
      <path d="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12H20A8,8 0 0,1 12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4V2M18.78,3C18.61,3 18.43,3.07 18.3,3.2L17.08,4.41L19.58,6.91L20.8,5.7C21.06,5.44 21.06,5 20.8,4.75L19.25,3.2C19.12,3.07 18.95,3 18.78,3M16.37,5.12L9,12.5V15H11.5L18.87,7.62L16.37,5.12Z" />
    </svg>
    {{ end -}}
  </div>
  <div class="note">{{- .Inner | markdownify }}</div>
</div>

css抜粋

.note-block {
  display: table;
  margin: 0 5px;;
}

.note-block .icon {
  display: table-cell;
  vertical-align: middle;
  border-right: 1px solid gray;
  margin: 0 16px 0 0;
}

.note-block .icon svg {
  padding: 8px;
  width: 48px;
  height: 48px;
}

.note-block .icon .icon-info {
  fill: steelblue;
}

.note-block .icon .icon-warning {
  fill: goldenrod;
}

.note-block .icon .icon-errata {
  fill: dimgray;
}

.note-block .note {
  display: table-cell;
  vertical-align: middle;
  padding: 0 0 0 16px;
}

.note-block .note p {
  margin: 8px 0;
}

アイコンの使い分け

ブロックにattributeを渡すことができるので、アイコンの使い分けはtypeという名前のattribute経由で指定できるようにしてみました。

type指定を省略するとinfoとして扱うようにします。

attribute指定例

```note {type=info}
```

{type=info}表示例

情報
情報です。

{type=warning}表示例

警告
警告文です。

{type=errata}表示例

訂正
訂正文です。

作ってみての所感

ブロックの使い方として正しいのかは置いておいて、markdown側の表記が比較的シンプルに済んだので習作の割に使い勝手良い物になりました。

hook側の定義が泥臭いように感じていて、もっと良い書き方がありそうに思うのですが、まずはこのまま使ってみて良い方法を見つけたら改良したいですね。

他にも、CLIのコマンドと出力結果をもっと見やすくできないかと常々考えていたので、Render Hooksを上手く利用して理想通りの表示ができるようにしたいです。

<<FessでWEB+DB PRESSのPDF検索システムを構築する WSL2のAlpine LinuxでDockerを使う>>