備忘録的なもの

Hugo のテーマ自作ことはじめ

Hugo のテーマを自作するにあたって、前準備としてやったことをまとめる。

Hugo でブログを始めてから公式サイトに載っているテーマの一つの Mainroad を使っていたが、 見出しの階層がわかりにくかったり(本文の装飾がシンプルで <h2><h3> の判別が難しい)、 メインコンテンツ部分の幅が狭かったり(コードブロックですぐにスクロール必要になるのが微妙)と、 いくつか気になる部分が出てきていた。

今のテーマに手を加える手もあったが、 以前からいつかは自作のテーマ使いたいとは思っていたのと、 他の方のブログを色々見る中で自作したい欲も強くなってきていたので自作する事にした。

ということで自分が何処から手を付けていったかとかをまとめておく。

テーマファイルの雛形を作成する

実際に Hugo のテーマを作っていく前に、 サンプルサイトの準備と雛形を用意する。

テーマを作るなら、確認のためにある程度のコンテンツを持ったサイトが必要になるが、 Hugo がサンプルサイト( gohugoio/hugoBasicExample: Example site to use with Hugo & Hugo Themes )を用意してくれているので、 今回はこれを使う。

既にこのブログでいくつか記事を書いているので、そのリポジトリでブランチ切って作っていくでも良い気はしたが、 別のテーマ用に行っている設定とごっちゃになって何かにハマりそうな気がしたため一旦公式サンプルサイトを使うことにした。

ということでサンプルサイトを clone してくる。

$ git clone https://github.com/gohugoio/hugoBasicExample.git
$ cd hugoBasicExample

次に hugo コマンドの中にテーマの雛形作成用のサブコマンド( hugo new theme <theme-name> )が有るのでそれを実行する。

$ hugo new theme hugo-theme

すると themes ディレクトリにこんな感じの雛形が作成される。 Hugo はこの中のテンプレート( .html なファイル)を参照して実際の HTML を生成するので、 テーマを自作する際はこれらのファイルを弄っていくことになる。

❯ tree -A themes/
themes/
└── hugo-theme
    ├── archetypes
    │   └── default.md
    ├── layouts
    │   ├── 404.html
    │   ├── _default
    │   │   ├── baseof.html
    │   │   ├── list.html
    │   │   └── single.html
    │   ├── index.html
    │   └── partials
    │       ├── footer.html
    │       ├── header.html
    │       └── head.html
    ├── LICENSE
    ├── static
    │   ├── css
    │   └── js
    └── theme.toml

9 directories, 11 files

あと、自分は最終的に submodule の形でサイトに反映するつもりなので、このタイミングで git init と GitHub でのリポジトリ作成もやっておく。

$ cd theme/hugo-theme

$ echo '# hugo-theme' >> README.md
$ git init
$ git add .
$ git commit -m 'init'

$ gh repo create hugo-theme --public
$ git remote add origin [email protected]:goshida/hugo-theme.git
$ git push origin main

サンプルをコピーして最低限サイトを見れる状態にする

前述の hugo new theme <theme-name> で生成した雛形だが、 ほぼ空ファイルなため、この状態で hugo server -D -t <theme-name> とかでローカルサーバを起動してもコンテンツは見れない。

$ find . -type f | grep -v '/.git' | xargs ls -lh
-rw-r--r-- 1 shida shida    8 Feb 22 10:13 ./archetypes/default.md
-rw-r--r-- 1 shida shida    0 Feb 22 10:13 ./layouts/404.html
-rw-r--r-- 1 shida shida  250 Feb 22 10:13 ./layouts/_default/baseof.html
-rw-r--r-- 1 shida shida    0 Feb 22 10:13 ./layouts/_default/list.html
-rw-r--r-- 1 shida shida    0 Feb 22 10:13 ./layouts/_default/single.html
-rw-r--r-- 1 shida shida    0 Feb 22 10:13 ./layouts/index.html
-rw-r--r-- 1 shida shida    0 Feb 22 10:13 ./layouts/partials/footer.html
-rw-r--r-- 1 shida shida    0 Feb 22 10:13 ./layouts/partials/header.html
-rw-r--r-- 1 shida shida    0 Feb 22 10:13 ./layouts/partials/head.html
-rw-r--r-- 1 shida shida 1.1K Feb 22 10:13 ./LICENSE
-rw-r--r-- 1 shida shida   13 Feb 22 13:01 ./README.md
-rw-r--r-- 1 shida shida  438 Feb 22 10:13 ./theme.toml
生成した雛形そのままでの生成結果
生成した雛形そのままでサーバを起動した様子

なので、まず最低限サイトを回れる様にしていく。

中身の細かい理解はひとまず置いといて、 Hugo のドキュメントにサンプルテンプレートが色々あるので、以下のような感じでコピーしてくる。

{{ define "main" }}
<main>
    <article>
        <header>
            <h1>{{.Title}}</h1>
        </header>
        <!-- "{{.Content}}" pulls from the markdown content of the corresponding _index.md -->
        {{.Content}}
    </article>
    <ul>
    <!-- Ranges through content/posts/*.md -->
    {{ range .Pages }}
        <li>
            <a href="{{.Permalink}}">{{.Date.Format "2006-01-02"}} | {{.Title}}</a>
        </li>
    {{ end }}
    </ul>
</main>
{{ end }}
{{ define "main" }}

<section id="main">
  <h1 id="title">{{ .Title }}</h1>
  <div>
        <article id="content">
           {{ .Content }}
        </article>
  </div>
</section>
<aside id="meta">
    <div>
    <section>
      <h4 id="date"> {{ .Date.Format "Mon Jan 2, 2006" }} </h4>
      <h5 id="wordcount"> {{ .WordCount }} Words </h5>
    </section>
      {{ with .GetTerms "topics" }}
        <ul id="topics">
          {{ range . }}
            <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
          {{ end }}
        </ul>
      {{ end }}
      {{ with .GetTerms "tags" }}
        <ul id="tags">
          {{ range . }}
            <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
          {{ end }}
        </ul>
      {{ end }}
    </div>
    <div>
        {{ with .PrevInSection }}
          <a class="previous" href="{{.Permalink}}"> {{.Title}}</a>
        {{ end }}
        {{ with .NextInSection }}
          <a class="next" href="{{.Permalink}}"> {{.Title}}</a>
        {{ end }}
    </div>
</aside>
{{ end }}
  • layouts/index.html
    • ホームページで使われるテンプレート
    • ブログだと単純化のため削除してしまって layouts/_default/list.html を使う様にしている人も多いっぽい
      • 自分は記事リストへのリンクが欲しかったので一旦残した
    • Taxonomy Templates | Hugo
<ul>
    {{ range .Pages }}
        <li>
            <a href="{{ .Permalink }}">{{ .Title }}</a>
            {{ .Params.wikipedia }}
        </li>
    {{ end }}
</ul>
{{ define "main"}}
    <main id="main">
      <div>
       <h1 id="title"><a href="{{ "" | relURL }}">Go Home</a></h1>
      </div>
    </main>
{{ end }}

コピーが終わったら改めてサーバを起動してブラウザから見ると、 以下の様な感じで最低限リンクを踏んで個別の記事まで辿り付けるようになる。

トップページの生成結果
サイトのトップページ
記事一覧ページの生成結果
post セクションの記事一覧(トップページから Posts のリンク先)
個別記事ページの生成結果
個別の記事ページ
404ページの生成結果
404ページ(適当な URL )

テンプレートと生成されるHTMLの関係を把握する

最低限サイトを回れる様にはなったので、 テンプレートと実際に生成されたサイト、公式のドキュメントを見つつ Hugo がどのテンプレートを参照して、 ページを生成しているかを把握する。

生成の基本的なルールについては公式ドキュメントの以下ページにまとまっている。

そこまで複雑なものでも無いが、以下のような感じで見ていくと追いやすかった。

  • Hugo がページを生成する際は最初に baseof.html を参照する
    • {{ block <hoge> }} が出てきたら、対応する定義 {{ define <hoge> }} をテンプレートの中から探す
      • 定義探す際に、生成するページの種類に応じてどのファイルをどういった順番で見ていくかを書いているのが上のドキュメント
      • テンプレートを弄る際は基本的には優先度の低い _default の中を弄って、個別(ホームページ、特定のセクション下、等)で何かをしたくなったら上の階層もしくは別ディレクトリに同名ファイルを作ってオーバーライドする感じ
    • {{ partial <fuga>.html }} が出てきたら layouts/partials/<fuga>.html の中身で置き換える

また、サンプルテンプレート内で使われている各種関数や変数に関してもドキュメントにまとまっているので、 その辺を参照しつつテンプレート読んでいけば、基本的な書き方は把握できると思う。

サンプルテンプレートが理解できたら、大まかなサイトのデザインをざっくり決めて、あとは弄りながら理解を深めていく。

おわりに

ということで、 Hugo のテーマを作っていくにあたって、最低限の下準備はできた。

この後実際に HTML やら CSS やらを弄っていくのだが、 ある程度ちゃんとしたテーマを目指すなら、気を付ける事や最低限実装すべきものも把握する必要がありそう。

ただ、公式のガイドラインやベストプラクティスみたいなものは見つけられなかったので、 こういった先人の記事や既に公開されているテーマ等を参考にしつつ、実際に作りながら身につけていくしかなさそう。 この辺はテーマがある程度形になったタイミングで自分でも振り返ってまとめてみたい。

なるべく早く形にしたいとは思っているものの、 HTML も10年くらい触ってなく何も覚えてないので、 今使っているテーマから自作テーマに置き換えられるのはいつ頃になるだろうか、という感じではある。

参考