Hugo のテーマを自作した
このブログに使用している Hugo のテーマを変更した。勉強も兼ねて自分でテーマを作成してみた。
作成したテーマ
以下のテーマを作成し、このブログ(m1yam0t0.com)に反映している。
いろいろなページを参考にしながら作成したため、テーマ用のリポジトリを別途用意したが、 個人用で作成したテーマであるため、このブログを管理しているリポジトリで直接管理したほうが良かったかもしれない。 (このリポジトリを Submodule として追加している)
テーマの雛形を作成
まず、作成したテーマの動作確認を行うために、Hugo 公式で用意されているサンプルサイトを clone する。
gohugoio/hugoBasicExample: Example site to use with Hugo & Hugo Themes
git clone https://github.com/gohugoio/hugoBasicExample.git
cd hugoBasicExample
hugo new theme
コマンドでテーマを作成するために必要なファイルを生成する。
hugo new theme ${作成したいテーマ名}
コマンドを実行すると themes
ディレクトリ配下に以下のようなファイルが生成される。
new-theme
で作成した場合、themes/new-theme
ディレクトリにファイルが作成される。
themes
└── new-theme # 作成したテーマ名がディレクトリ名になる
├── archetypes
│ └── default.md
├── layouts
│ ├── 404.html
│ ├── _default
│ │ ├── baseof.html
│ │ ├── list.html
│ │ └── single.html
│ ├── index.html
│ └── partials
│ ├── footer.html
│ ├── head.html
│ └── header.html
├── LICENSE
├── static
│ ├── css
│ └── js
└── theme.toml
生成されたディレクトリについては以下のようになっている。テーマ作成時は layouts と static(CSS) を修正する機会が多いと思われる。
- archetypes
- Hugo で新規 Post を作成するときに使用されるテンプレート
- テーマ側では指定することはあまりないので、あまり変更する機会はなさそう
- Archetypes | Hugo
- layouts
- Hugo で作成されるページの HTML のレイアウトを決めるディレクトリ
- static
- CSS や Javascript などの静的ファイルを格納するディレクトリ
- theme.toml
- テーマの設定を記載するファイル。
- https://themes.gohugo.io/ で公開するときはちゃんと設定したほうが良さそう
最低限必要な設定を行う
テーマの雛形を作成したのみでは、何もページが表示されない状態となっているため、必要最低限の設定をする。
Hugo のテンプレートの仕組み
設定するに当たり、Hugo のページがどのように生成されるか仕組みを理解したほうが良い。以下の公式ドキュメントに詳細は記載されているため、そちらを読んでおいたほうが良い。
Base Templates and Blocks | Hugo
詳細については、こちらをクリック
Hugo で生成されるページは、baseof.html
をもとに HTML が生成される。何も設定していない状態だと、テーマのディレクトリのlayouts/_default/baseof.html
に以下の内容が出力される。
hugo では HTML 内に Go のテンプレートを混ぜた記述になっており、hugo で使用できるテンプレートを記述してページの構成を組み立てていく。
<!DOCTYPE html>
<html>
{{- partial "head.html" . -}}
<body>
{{- partial "header.html" . -}}
<div id="content">{{- block "main" . }}{{- end }}</div>
{{- partial "footer.html" . -}}
</body>
</html>
{{ partial "hoge.html" . }}
と記載すると、テーマのディレクトリ内の layouts/partial
内にある HTML ファイルの内容が出力される。
{{- partial "head.html" . -}}
上記の例だと、layouts/partials/head.html
の内容を出力するということになる。
テーマを編集する際に、再利用する HTML のパーツがあるのであれば、上記のように partial ディレクトリから呼び出す形にすると良い。
初期設定の場合は、以下の 3 つを呼び出すようになっている。初期状態だと中身は空のため、必要な要素をこれらのファイルに追記していく。
head.html
<head>
タグとして記述する内容
header.html
- ページ上部に表示するヘッダー(サイトのロゴやメニューなどを表示する部分)
footer.html
- ページ下部に表示するフッター(コピーライトやメニューなどを表示する部分)
以下のように block を定義すると、各ページ(index.html, list.html など)の HTML 内に block を設定すると、その内容が出力される。
{{ block "main" . }}{{ end }}
例えば、以下の内容の index.html
を用意し、Hugo でビルドを行う。
{{ define "main" }} これはテストです {{ end }}
ビルドした結果、index.html
は以下のように出力される。
(本当は partial の部分も変換されるが、省略している。)
<!DOCTYPE html>
<html>
{{- partial "head.html" . -}}
<body>
{{- partial "header.html" . -}}
- <div id="content">{{- block "main" . }}{{- end }}</div>
+ <div id="content">これはテストです</div>
{{- partial "footer.html" . -}}
</body>
</html>
block は main 以外にも設定できるので、用途によって block を使用してページごとに出力内容を変更できる。
index.html の削除
ブログ用のテーマであるため、トップページである index.html
は不要なので削除する。list.html
を編集して記事の一覧を表示させるようにする。
トップページを用意したい場合は、index.html
をそのまま編集すればよい。
rm -f layouts/index.html
どのページが読み込まれるかについては、以下の公式ドキュメントが参考になる。
list.html の編集
記事の一覧を表示する list.html
の中身が空であるため、以下のように編集する。
{{ define "main" }} {{- $title := .Title -}} {{- $pages := .Pages -}} {{-
$summary := false -}} {{- if .IsHome -}} {{- $title = "Homepage" -}} {{- $pages
= where site.RegularPages "Type" "in" site.Params.mainSections -}} {{- $summary
= true -}} {{- end -}}
<h1>{{ $title }}</h1>
{{ range $pages }}
<article>
<h3>
<time class="metadata" datetime="{{ .Date }}">
{{- .Date | time.Format (default "2006/01/02" site.Params.DateFormat) -}}
</time>
<a href="{{ .Permalink }}">{{ .Title }}</a>
</h3>
{{- if $summary -}} {{ .Summary }} {{- end -}}
</article>
{{ end }} {{ end }}
トップページの場合、.IsHome
が true
となるので、以下のように if 文で処理を分岐させて、トップページとそうでないページで処理を分けることができる。
{{ if .IsHome }}
...
{{ end }}
ページの一覧を range で繰り返し処理をする際、.IsHome
は使用できないので、range 内で処理の棲み分けをしたい場合は、.IsHome
を使わず、別途変数を設けて処理を行う必要がある。
以下のように、トップページのみサマリーを表示させたい場合に、$summary
という変数を別途設定し、判定させると目的の動作となる。
記入例(一部省略)
{{- $summary := false -}}
{{- if .IsHome -}}
{{- $summary = true -}}
{{- end -}}
{{ range $pages }}
{{- if $summary -}}
{{ .Summary }}
{{- end -}}
{{- end -}}
上記の内容で hugo server -t new-theme
すると、トップページと投稿一覧で表示が別れるようになっている。
single.html の編集
それぞれの post を表示するために single.html
を編集する。以下のような HTML を記載する。
{{ define "main" }}
<h1>{{ .Title }}</h1>
{{- if not .Date.IsZero }}
<div>
Date: {{ .Date | time.Format (default "2006/01/02" site.Params.DateFormat) }}
</div>
{{- end }} {{- if .Params.tags }}
<div>
Tags: {{- range ($.GetTerms "tags") }}
<a href="{{ .Permalink}}">{{ .LinkTitle }}</a>
{{- end }}
</div>
{{- end }} {{ .Content }} {{ end }}
上記の内容で、以下の画像のように各 post が表示される。
テーマの編集
あとは自分の好みに合わせてテーマを編集していく。最低限必要そうな以下の作業を実施した。
Google Analytics の対応
公式で template が用意されているので、layouts/partials/head.html
に以下の記述を追記する。
手元で確認したりするときには挿入したくないので、hugo.IsProduction
の判定処理を入れる。
そうすることで、hugo server
を実行した場合や、hugo -e development
でビルドした場合は挿入されなくなる。
{{ if hugo.IsProduction }}
{{ template "_internal/google_analytics.html" . }}
{{ end }}
CSS の編集
デザインを自分好みに編集する。static/css
に CSS ファイルを追加し、自分好みに編集する。layouts/partials/head.html
に以下の記述を追加して、CSS を読み込ませた。
(普段 CSS をいじらないので、めちゃくちゃ苦労した。)
<link rel="stylesheet" href="/css/style.css" />
コードブロックの色を変更するために highlight.js を利用する
Hugo には 標準でコードブロックの色を変更できるようになっているが、用意されている色で自分好みのものがなかったため、highlight.js を使用した。
highlight.js demo で好きな色を選び、以下の内容を head.html
に追加すれば良い。
nord.min.css
の部分は自分の好きなテーマのものにすれば変更できる。
<link
rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/nord.min.css"
/>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script>
<script>
hljs.highlightAll();
</script>
これだけだと、Code
のようなケースのハイライトができないため、以下のようにテーマに合わせた style の設定を追加した。
:root {
--hljs-background-color: #2e3440;
--hljs-color: #d8dee9;
}
code {
background-color: var(--hljs-background-color);
color: var(--hljs-color);
}
他にもいろいろとやるべきところはあるだろうが、無限に時間が溶けそうなので、ひとまずここまでにする。 気づいたときに少しづつ直せたらと思うが、おそらく当分このままになりそう。
さいごに
普段仕事で、フロントエンドを触ることがないので、HTML や CSS をいじることがなかったため、非常に苦労した。 有名なテーマのソースコードを参照したり、同様の内容の記事を参考にさせていただいた。自分一人の力ではきっとできなかったと思う。
本当にありがとうございました。 この記事が誰かの参考になれば幸いです。
参考
- Hugo の公式ドキュメント、公式フォーラム
- 参考にさせていただいた記事
- 参考にさせていただいたテーマ