静的サイトジェネレータHugoを使ったサイト構築(メニュー編)

こんにちは、tamaoki (@t0shiya) です。
今回は、静的サイトジェネレータ Hugoメニュー について解説します。

メニューとは?

Hugoにはシンプルなメニュー構築機能が備わっています。メニュー機能は以下のような特徴があります。

  • コンテンツを任意のメニュー(複数可)に追加できる
  • メニューを階層化できる
  • コンテンツなしでもメニューを追加できる
  • 選択中のメニュー表示を変更できる

内部構造的に言うとメニューとは .Site.Menu という変数でアクセスできる連想配列のようなものです。
例えば main というメニューは .Site.Menu.main でアクセスします。

メニューには以下のようなプロパティがあります。

URLコンテンツのパーマリンク、または指定URL
Name表示名
Menu所属メニュー
Identifierセクション名、または指定文字列
Pre指定HTML
Post指定HTML
Weight並び順
Parent親メニュー名
Children子メニュー

また、HasChildren という関数で子メニューが存在するか確認できます。

メニューの追加

メニューを追加する方法は二つあります。一つはコンテンツのフロントマターで指定する方法、もう一つは config.toml で指定する方法です。

コンテンツをメニューに追加

コンテンツのフロントマターにメニュー項目を書くだけで、メニュー定義の追加とメニューへのコンテンツ登録が行われます。
フロントマターには以下のように記述します。

---
// YAML形式の場合
menu: "main"

// 複数のメニューに追加する場合
menu: ["main", "footer"]
---

次のように親メニュー項目を指定して階層化したり、weight で並べ替えをすることもできます。

---
// YAML形式の場合
menu:
  main:
    parent: 'extras'
    weight: 20
---

config.toml でメニューを追加

menuの表示順を変更したり、リンク等のコンテンツに紐付かないメニューを追加する場合は config.toml に定義を記載します。

[[menu.main]]
    name = "about hugo"
    pre = "<i class='fa fa-heart'></i>"
    weight = -110
    identifier = "about"
    url = "http://gohugo.io/"
[[menu.main]]
    name = "getting started"
    pre = "<i class='fa fa-road'></i>"
    weight = -100
    url = "/getting-started/"

各項目は前述の通りです。url は絶対パスまたはbaseURLからの相対パスで指定してください。

メニューを表示

冒頭で記した通りテンプレートからは .Site.Menus 変数を介してアクセスします。
例えば、メニュー項目 main を表示するには以下のように記述します。

<ul class="menu">
  {{ $currentNode := . }}
  {{ range .Site.Menus.main }}
    {{ if .HasChildren }}
      <li class="sub-menu{{if $currentNode.HasMenuCurrent "main" . }} active{{end}}">
      <a href="javascript:;" class="">
          {{ .Pre }}
          <span>{{ .Name }}</span>
          <span class="menu-arrow arrow_carrot-right"></span>
      </a>
      <ul class="sub">
          {{ range .Children }}
          <li{{if $currentNode.IsMenuCurrent "main" . }} class="active"{{end}}><a href="{{.URL}}"> {{ .Name }} </a> </li>
          {{ end }}
      </ul>
      </li>
    {{else}}
      <li>
      <a class="" href="{{.URL}}">
          {{ .Pre }}
          <span>{{ .Name }}</span>
      </a>
      </li>
    {{end}}
  {{end}}
</ul>

2行目は range の中から現在の表示ページ情報を参照するため、$currentNode に . を代入しています。
.Site.Menus.main に対して階層化されているかどうかで処理を切り替えています。$currentNode.HasMenuCurrent, $currentNode.IsMenuCurrent でそれぞれ表示中のコンテンツが当該メニューの配下にいるか、当該メニューであるか、を判定しています。

セクションをメニューに登録

次の設定を config.toml に記載すると全セクション、コンテンツが main メニューに一括登録されます。

SectionPagesMenu = "main"

デフォルトでは、セクション名が表示名になります。表示名や並び順を変更したい場合は config.toml に定義を追加してください。この時、identifier をセクション名にしてください。

 [[menu.main]]
        name = "This is the post section"
        weight = -110
        identifier = "post"
        url = "/post/"

feedtailor では、静的サイトジェネレータの利用に限らず、ウェブサイト静的化の御相談を承っておりますのでお気軽にお問い合わせください。

このエントリーをはてなブックマークに追加