ショートコードを使ってHUGOでドキュメントを部品化する

Blog

マニュアルを書く際に、複数のページに同じ内容を書くことがある。
しかし、複数のページに同じ内容を書くと、記載内容が変わったときに修正漏れが発生しうる。
そのため、複数のページに掲載したい内容を部品化し、利用したいページで部品を呼び出しできると便利である。

HUGOでは、指定したパスのページを呼び出すショートコードを実装することで、ドキュメントを部品化できる。

動作を確認した環境

  • HUGO v0.126.1

ショートコードの実装

layouts/shortcodesディレクトリに配置する。

layouts/shortcodes/include.html
{{ with site.GetPage (.Get 0) }}
  {{ .RenderShortcodes | .RenderString }}
{{ end }}

部品ページを呼び出す場合は、Markdownファイル内でショートコードを記述する。

content/post/foo.md
{{< include "path/to/page.md" >}}

動作確認

それぞれ次の構成でファイルを配置したとする。
今回は簡略化のため、コンテンツに直接「layouts」ディレクトリを作成している。

.
├── ...省略...
├── content
   ├── _index.md
   ├── post
   ├── _index.md
   ├── func1.md # 部品ページを呼び出すページ
   └── snippets
       └── deprecated.md # 部品ページ
├── hugo.toml
└── layouts
    ├── ...省略...
    └── shortcodes
        ├── include.html
        └── note.html # 注意書きを表示するショートコード

部品化したい内容を記載したページ(部品ページ)は、snippetsディレクトリへ配置することにした。
Frontmatterのtitleは出力されないが、HUGOの仕様上必要なため記載している。
また、注意書きを表示するショートコードが実装されているものとする。

content/snippets/deprecated.md
---
title: "ここは出力されない"
---

{{< note >}}

この機能は非推奨です。v2.0で削除される予定です。

{{< /note >}}

このファイルを呼び出すページをpostディレクトリに配置する。

content/post/func1.md
---
title: "昔々の機能"
date: 2024-04-07
---

{{< include "/snippets/deprecated.md" >}}

HUGOのローカルサーバーを起動しhttp://localhost:1313/post/func1/にアクセスすると、次のように表示される。

スクリーンショット:部品ページを呼び出している

ちなみに、http://localhost:1313/snippet/deprecated/のURLも有効である。
ユーザーにアクセスさせたくない場合には、検索よけをするなどの対処が必要となる。

部品ページの画像を使う

部品ページをショートコードで呼び出す場合、基準位置は呼び出したページとなる。
上記の例であれば、部品ページを「func1.md」で呼び出しているため、「func1.md」が基準位置となる。
部品ページ内で画像を相対パスで指定した場合、呼び出したページを基準として画像を探すため「func1」ディレクトリ内に配置した画像が呼び出される。

部品ページを呼び出すページの画像が使われることの確認

たとえば、それぞれ以下のような画像を配置しているとする。

  • func1/image.png:「func1」を表示した画像
  • deprecated/image.png:「deprecated」を表示した画像
.
├── ...省略...
├── content
   ├── _index.md
   ├── post
   ├── _index.md
   ├── func1
   └── image.png # <=== この画像が呼び出される
   ├── func1.md # 部品ページを呼び出すページ
   └── snippets
       ├── deprecated
   └── image.png
       └── deprecated.md # 部品ページ

部品ページに次のように記載した場合、「func1」ディレクトリ内の画像が呼び出される。

content/snippets/deprecated.md
---
title: "ここは出力されない"
---

![画像](image.png)

画像:呼び出し先のページの画像が呼び出されている

部品ページの画像を使う

部品ページの画像を使うには、HUGOが用意しているRender Hooksを利用する。

このRender Hooks内の処理の5行目の.PageInnerがポイントで、.PageInnerは部品ページページを指している。
5行目では、最初に部品ページのリソースを取得し、見つからない場合は呼び出した先のページのリソースを取得する。

tpl/tplimpl/embedded/templates/_default/_markup/render-image.html
  {{- with or (.PageInner.Resources.Get $path) (resources.Get $path) -}}

HUGOが用意しているRender Hooksを利用するには、HUGOの設定ファイルでmarkup.goldmark.renderHooks.image.enableDefaultを有効にする。

hugo.toml
[markup]
[markup.goldmark]
[markup.goldmark.renderHooks]
[markup.goldmark.renderHooks.image]
enableDefault = true

有効にすると、先ほどのページの画像は部品ページの画像、すなわち「deprecated」ディレクトリ内の画像が呼び出される。

画像:部品ページの画像が呼び出されている