Open48

Hugo再入門

shotakahashotakaha

サイト設定

https://gohugo.io/getting-started/configuration/

  • サイト設定は toml / yaml / json 形式が使えるで、自分の好きなものを選ぶ
  • デフォルト値は /config.toml
  • hugo --config ファイル名で設定することができる
$ hugo --config staging.toml

テーマの設定の引き継ぎ

New in v0.84.0 となっている機能

  • その直前の不便さを知らないので、現在は、デフォルトの挙動でよきようになっていると思って使うことにする
  • なので、ここは必要になったら読むことにする
shotakahashotakaha
  • v0.109.0から設定ファイルはhugo.tomlになった
  • 現在は後方互換性のためconfig.tomlでもOKだが、移行を推奨
shotakahashotakaha

設定ファイルのディレクトリ構造

https://gohugo.io/getting-started/configuration/#configuration-directory

  • 設定ファイルは複数ファイルに分割できる
  • 設定項目は下記のとおり

The root configuration keys are:
build, caches, cascade, deployment, frontmatter, imaging, languages, markup, mediatypes, menus, minify, module, outputformats, outputs, params, permalinks, privacy, related, security, server, services, sitemap, and taxonomies.

  • 基本はHugoのデフォルトでよさそうだが、以下の設定ファイルは作ったほうがよい
/config/_default/
|-- hugo.toml
|-- languages.ja.toml
|-- menus.ja.toml
|-- params.toml

環境(=用途)ごとに設定を変更できる

  • 環境(=用途)ごとにサブディレクトリを作成することで、設定を分岐できる
  • デフォルト設定(config/_default/)は必ず読み込まれるので、違うところを書いておけばOK
  • 例:ステージングとプロダクションで公開URLが異なる場合は、baseURLだけ変更すればOK

環境を指定して構築

$ hugo --environment staging
$ hugo -e production
  • --environment / -eオプションで環境を指定して構築できる
  • デフォルトではの環境は以下のとおり
    • hugo server = development
    • hugo = production
      となっている
shotakahashotakaha

言語ごとの設定項目

  • 多言語サイト(日本語と英語)を想定した
    • 共通の設定 : hugo.toml
    • 日本語の設定 : languages.ja.toml
    • 英語の設定 : languages.en.toml
config/_default/hugo.toml
baseURL = "https://example.com"
title = "ウェブサイト名"
copyright = "著作者表示"
theme = ["テーマ名"]

defaultContentLanguage = "ja"
defaultContentLanguageInSubdir = false  # true / false
hasCJKLanguage = true
config/_default/languages.ja.toml
# [languages.ja]に相当
disabled = false
languageCode = "ja"
languageDirection = "ltr"
languageName = "日本語"
weight = 1
title = "ウェブサイト名(日本語向け)"

[params]
dateFormat = "2006-01-02"
description = "ウェブサイトの説明"
config/_default/languages.en.toml
# [languages.en]に相当
disabled = false
languageCode = "en"
languageDirection = "ltr"
languageName = "English"
weight = 2
title = "ウェブサイト名(in English)"

[params]
dateFormat = "2006-01-02"
description = "ウェブサイトの説明 in english"
shotakahashotakaha

図の変換

https://gohugo.io/content-management/image-processing/

  • リサイズ、フィット、フィル、フィルターの処理ができる
  • Resize = 幅と高さを指定。幅だけ、高さだけの場合は、アスペクト比を保存してリサイズ。
  • Fit = 幅と高さを指定。アスペクト比を保存してリサイズ。
  • Fill = 幅と高さを指定。リサイズ&クロップ。
  • Filter = 画像にフィルターを適用。
shotakahashotakaha
  • ページリソースを取得する場合
    • index.md(or _index.md)があるディレクトリにある画像
    • 例として./sunset.jpgを取得した場合
{{ $image := .Resources.Get "sunset.jpg" }}
  • グローバルリソースを取得する場合
    • 例として/assets/images/sunset.jpgを取得した場合
{{ $image := resources.Get "images/sunset.jpg" }}
  • 違い
    • .Resources.Get
    • resources.Get
shotakahashotakaha

マッチする画像を検索

  • リソースから画像を取得する場合、.Getを使ってピンポイントでファイル名を指定するのではなく、.GetMatchでキーワードを(正規表現で)指定することがよくある

https://github.com/nunocoracao/blowfish/blob/main/layouts/partials/hero/big.html

例として、Blowfishの部分テンプレートでやっていることを確認した

  • L3: {{- $images : = .Resources.ByType "image" -}}
    • 画像ファイルを一括で取得
  • L4: {{- $featured := $images.GetMatch "*feature*" -}}
    • 画像ファイルのリストを持った変数($images)から、ファイル名にfeatureが含まれるファイルを取得
  • L5 : {{- if not $featured}} ......
    • $featureがなかった場合、coverthumbnailのいずれかが含まれるファイルを取得
  • L14: ``{{ with .Resize "1200"x }}
    • ファイルがある場合、1200xにリサイズしてimgタグで表示する
  • ファイルがなければ、表示しない(なにもしない)
shotakahashotakaha

内部テンプレート/ショートコード

https://github.com/gohugoio/hugo/tree/master/tpl/tplimpl/embedded/templates

  • Hugoの内部で定義されてるテンプレート/ショートコードの本体
  • ドキュメントには全部の引数が書かれていない気がするので、ここを読んだ方が分かりそう
shotakahashotakaha

OGPの設定

  • opengraph.html
  • og:title = .Title
  • og.description = .Description / .Summary / .Site.Params.description
  • og:type = article / website
  • og:url = .Permalink
  • og:image = $.Params.images > Featured画像 > カバー画像 = サムネイル画像 > $.Site.Params.images

og:image

  • $.Params.images = フロントマターで設定; 最初の6枚を使用
  • Featured画像 = Page bundle; ファイル名に*feature*を含む画像;1枚
  • カバー画像 = Page bundle; ファイル名に *cover*を含む画像;1枚
  • サムネイル画像 = Page bundle; ファイル名に *thumbnail*を含む画像;1枚
  • $.Site.Params.images = サイト設定で設定; 1枚
shotakahashotakaha

ビルトインのOpenGraph設定

以前、詳しく調べてたみたいだけど、このURLも貼っておく

https://gohugo.io/templates/internal#open-graph

  • サイト設定(config.toml)と各ページのフロントマターの設定の組み合わせ
  • seriesのタクソノミーを使うと see also のページに使われるらしい

The series taxonomy is used to specify related “see also” pages by placing them in the same series.

shotakahashotakaha

YouTube動画の埋め込み

{{< youtube id="必須" >}}
  • Shortcodesのドキュメントとソース(youtube.html)を読むと
    • id : 必須
    • title : 文字列("YouTube Video")
    • autoplay : ブーリアン(false
    • class : クラス名(デフォルトのiframeのスタイル)
  • [privacy.youtube.disable]の値で、Cookieの利用をどうするか変更できる
    • disable = false(デフォルトの挙動)の場合は、外部プレイヤーに移動しても、Cookieを使ったトラッキングがON
    • disable=trueの場合は、youtube-nocookieで埋め込まれ、埋めんだ動画を再生しないかぎり、ユーザー情報は残らない

プライバシー設定

  • サイト設定でいろんなサービスのプライバシー設定(GDPR対策)ができる

https://gohugo.io/about/hugo-and-gdpr/

shotakahashotakaha

PostCSS

https://gohugo.io/hugo-pipes/postcss/

  • PostCSS = CSSをビルドするためのフレームワーク
    • ベースとなるCSSから新しいCSSを作ることができる
    • 例:autoprefixerで ベンダー用 prefix を追加する、とか
  • npmを使ってある程度のパッケージのインストールが必要
    • postcss / postcss-cli / autoprefixer
  • 設定は /postcss.config.js に書く
shotakahashotakaha
{{ $css := resources.Get "css/main.css" }}
{{ $style := $css | resources.PostCSS }}
  • /assets/css/main.css を読み込んで PostCSSに食べさせている
  • たぶん(じゃなくても)、このように一行で書くこともできる
    • Goの書き方を間違えているかもしれないけど、やりたいことは分かるはず
{{ $style := resources.Get "css/main.css" | resources.PostCSS }}
shotakahashotakaha
  • PostCSSの使い方

https://github.com/postcss/postcss-cli

  • この使い方の例が、上と同じ
$ cat input.css | postcss -u autoprefixer > output.css  # Piping input & output
  • cat input.css = 元のCSSを読み込む(パイプする)
  • -u autoprefixer = プラグインを指定する(ここでは autoprefixer
  • > output.css = 変換したCSSを書き出す
  • オプションは他にもあって、使うものは postcss.config.js に書いておくことができる
shotakahashotakaha

https://absarcs.info/how-to/install-tailwind-css-hugo/

  • ここに書いてあることを試してみた
  • postcss.config.jsをそのまま真似するとエラーが出る
ERROR 2022/03/11 05:36:54 POSTCSS: failed to transform "style.css" (text/css):
TypeError: Cannot read properties of undefined (reading 'config') at getTailwindConfig (node_modules/tailwindcss/lib/lib/setupTrackingContext.js:81:62)
  • PostCSSのドキュメントにあるように require を使った書き方に修正するとエラーが出なくなった
postcss.config.js
module.exports = {
    plugins: [
        require('tailwindcss')({}),
        require('autoprefixer')({}),
    ]
}
  • でもページにCSSが適用されていない。どうして?
shotakahashotakaha

日時のフォーマット指定

https://gohugo.io/functions/dateformat/

time.Format 日付フォーマット 入力値
  • 日付フォーマットは "Mon Jan 2 15:04:05 2006 MST" を並び替えて指定する必要がある
    • MSTは米国山岳標準時 = UTC-07

この値を使う理由はよく知らない・・・

  • 0 1 2 3:4:5 6 7みたいな並びになってるのかな?
  • Hugoを使いはじめたとき、この日時に意味があることを知らなかったので、日付が全く表示されなくて困ったことがあった(いやぁ、分かんないよ)
shotakahashotakaha

predefinedなフォーマッタ

  • v0.87.0以降のHugoに predefined なフォーマッタが追加された
{{ .Date | time.Format ":date_full" }}    // => Thursday, Mar 17, 2022
{{ .Date | time.Format ":time_full" }}    // => 11:41 pm UTC
  • あまり(僕の好み的に)使えそうなフォーマッタはない
  • 日本語の場合どういう表示になるか確認が必要
shotakahashotakaha

メニューの追加

https://gohugo.io/content-management/menus/

  • サイトのメニュー(ナビゲーション)の作成に使うことができる機能
  • 簡単に多言語対応できる
config/_default/menus.ja.toml
[[main]]
name = "About"
pageRef = "about"
weight = 10

[[main]]
name = "ブログ"
pageRef = "posts"
weight = 20
config/_default/menus.en.toml
[[main]]
name = "About"
pageRef = "about"
weight = 10

[[main]]
name = "Posts"
pageRef = "posts"
weight = 20
shotakahashotakaha

セクション

https://gohugo.io/content-management/sections/

  1. /content/直下の first-level のディレクトリ名が section になる
  2. _index.mdがあるサブディレクトリもsectionになる
shotakahashotakaha
  1. セクションテンプレートが自動で適用されるのは1の場合
  2. 2の場合はフロントマターで type or layout を設定する必要がある
shotakahashotakaha

Section Templates

https://gohugo.io/templates/section-templates/

5つの kind それぞれのインデックスページがある。
日本語にしても分かりにくいだけなので、URLを見て理解するほうがよいと思う

  1. home = トップ(/index.hdml
  2. page = 記事/ページ(/posts/my-post/index.html
  3. section = セクション(/posts/index.html
  4. taxonomy = タグ自体のインデックス(/tags/index.html
  5. term = タグの中の単語のインデックス(/tags/name/index.html
shotakahashotakaha

Goldmark

https://gohugo.io/getting-started/configuration-markup

  • Markdownのレンダラーには Goldmark が使われている
    • v0.60以降のデフォルト
    • それ以前は BlackFridayが使われていた
shotakahashotakaha
  • デフォルトでは.mdファイルの中でHTMLタグなどを使うことができない
  • HTMLタグを使いたい場合は unsafe = true に変更しないといけない
    • FontAwesomeなどアイコンフォントを使う場合は、設定を変える必要があるかもしれない
config.toml
[markup]
[markup.goldmark.renderer]
unsafe = true
shotakahashotakaha

Google Analytics の設定

  • UA-タグが2023年7月に廃止になるみたい
  • Hugoの中でUA-タグからG-タグへの変更がどうなってるのか確認した
  • 該当のファイルを見つけるために、トラッキングコードに使われている googletag を含むファイルを検索した
$ rg googletag
docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/gtag.html
2:<script async src="https://www.googletagmanager.com/gtag/js?id={{ . }}"></script>

tpl/tplimpl/embedded/templates/google_analytics.html
4:<script async src="https://www.googletagmanager.com/gtag/js?id={{ . }}"></script>

tpl/.../google_analytics.htmlの中身を確認

  • プライバシー設定(.Site.Config.Privacy.GoogleAnalytics)の値を確認
  • GoogleアナリティクスのID(.Site.GoogleAnalytics)の値を確認
  • {{ if hasPrefix . "G-" }} / {{ else if hasPrefix . "UA-" }} となっていて、どちらにも対応

UA-G-は併用できなさそうなので、さっさとUAをGに切り替えるのがよさそう

shotakahashotakaha

サイトマップの設定

https://gohugo.io/templates/sitemap-template/

  • config.toml[sitemap]でグローバルに設定できる
    • disableKindsに入れると生成しないようにできる
  • ページのフロントマターで個別に設定できる
  • カスタマイズしたい場合は layouts/sitemap.xml / layouts/_default/sitemap.xml に作成する
shotakahashotakaha
config.toml
[sitemap]
changefreq = "daily"
priority = 0.5
  • filenameはデフォルトのまま(sitemap.xml)でいいので書いていない
  • changefreqalways / hourly / daily / weekly / monthly / yearly / never から選択する
  • priority0.0 から 1.0 の間で指定する
shotakahashotakaha

公開URL

https://gohugo.io/content-management/urls/

  • サイト設定(config.toml)で指定した contentDir のフォルダ/ファイル階層に従って、publishDirにHTMLファイルが生成される
  • permalinks設定で、公開URLのルールを変更することができる

設定例

config.toml
[permalinks]
posts = "/posts/:year/:month/:day/:03:04/"
pages = "/:section/:filename/"
  • 記事ページ(posts)と固定ページ(pages)で、公開URLのルールを変更する
    • すべての投稿コンテンツは「公開日に意味がある or ない」で区別して、いずれかに分類する
  • 記事ページは公開日をベースに /posts/年/月/日/時分/ にする
    • Go time format が使えるらしいので時(:03)分(:04)で設定できるはず
  • 固定ページはファイル名をベースに /セクション/ファイル名/にする
shotakahashotakaha

Pretty URLsUgly URLs

  • Hugoのデフォルトは pretty URL
  • pretty URLはURL末尾がファイル名/となる(要するに index.html が作成される)
  • ugly URLはURL末尾がファイル名.htmlとなる
  • 好みの問題かもしれない
shotakahashotakaha

canonifyURLsrelativeURLs

  • コンテンツ内の基本的にそのまま処理される
  • すべてを絶対パスに変換したい場合はconfig.tomlで設定できる
    • SEO対策のcanonical化とは関係がなさそう
config.toml
canonifyURLs = true # デフォルトは false
  • 相対パスに変換する設定もある
    • すでに絶対パスで入力されているものは変換されない
config.toml
relativeURLs = true # デフォルトは false
shotakahashotakaha

タクソノミー

https://gohugo.io/content-management/taxonomies/

  • 日本語訳を調べると「分類」「分類法」「分類学」とか出てくるけど、ちょうどいい日本語ってなんだろう?
  • categoriestags の機能のこと
デフォルトで有効になっている設定
[taxonomies]
category = 'categories'
tag = 'tags'
  • 単数形 = "複数形" の形で書くのが基本(とどこかに書いてあったきがする)
  • それぞれの値は記事のフロントマターで設定する
+++
title = "記事のタイトル"
categories = ["カテゴリ1", "カテゴリ2"]
tags = ["タグ1", "タグ2", "タグ3"]
+++
shotakahashotakaha

日本語のカテゴリ名/タグ名

  • カテゴリ/タグの値はそのままURLになる
  • カテゴリ名/タグ名が日本語の場合、URLが日本語になる
日本語が混じったURL
https://example.com/categories/カテゴリ1/
https://example.com/categories/カテゴリ2/
https://example.com/tags/タグ1/
https://example.com/tags/タグ2/
https://example.com/tags/タグ3/

英語スラッグにしたい

  • 日本語URLでもアクセスするには問題ない
  • でも、URLを共有するときを考えると、URLは英語にしておきたい
URLは英語にしておきたい
https://example.com/categories/category1/
https://example.com/categories/category2/
https://example.com/tags/tag1/
https://example.com/tags/tag2/
https://example.com/tags/tag3/

ちょっと調べてみているがconfig.tomlでできることはなさそう🤔

代替手段(たぶん;まだテストしてない)

  • フロントマターにはカテゴリ名/タグ名を英語で入力する
記事のフロントマター
+++
title = "記事のタイトル"
categories = ["category1", "category2"]
tags = ["tag1", "tag2", "tag3"]
+++
  • それぞれのカテゴリ名/タグ名に対して_index.mdを作成する
_index.mdのパス
/content/categories/category1/_index.md
/content/categories/category2/_index.md
/content/tags/tag1/_index.md
/content/tags/tag2/_index.md
/content/tags/tag3/_index.md
  • _index.mdのフロントマターに日本語タイトルを書く
_index.mdのフロントマター
+++
title = "カテゴリ1"
+++

たぶんこれでいけるはず😎

shotakahashotakaha

Page Variables

https://gohugo.io/variables/page/

.Is系の変数を調べてみる

  • .IsHome : true in the context of the homepage
  • .IsNode : always false for regular content pages. .IsPage と対になるフラグ
  • .IsPage : always true for regular content pages. .IsNode と対になるフラグ
  • .IsSection : true if .Kind is section
  • .IsTranslated : true if there are translation to display.

  • .Site.IsMultilingual
  • .Site.IsServer
  • .IsNamedParams
shotakahashotakaha

繰り返し

https://gohugo.io/templates/introduction/#iteration

  • ページの一覧を作ったり、フロントマターで設定した配列から値を取り出したりするときは range を使う
  • とりあえずテンプレートに書いてみて、値を取り出せることを確認しながら、必要なコンポーネントを埋め込んでいけばよい
フロントマター
videos = ["attic/video0.mp4", "attic/video1.mp4", "attic/video2.mp4"]
ページ変数が配列であることを確認
{{ .Params.videos }}
// ==> [attic/video0.mp4 attic/video1.mp4 attic/video2.mp4]
配列から順番に読み出す
{{ range .Params.videos }}
  {{ . }}
{{ end }}
// ==>
// attic/video0.mp4
// attic/video1.mp4
// attic/video2.mp4
変数名をつけて読み出すこともできる
{{ range $video := .Params.videos }}
  {{ $video }}
{{ end }}
// ==> 結果は上と同じ
インデックスも読み出したい場合
{{ range $index, $video := .Params.videos }}
  {{ $index}} : {{ $video }}
{{ end }}
// ==>
// 0 : attic/video0.mp4
// 1 : attic/video1.mp4
// 2 : attic/video2.mp4
shotakahashotakaha

最初の項目だけ条件をつける

  • 画像/動画をスライダーを使って表示するときに、最初の項目に class="active"をつける必要があった
  • 配列のインデックスが 0(``{{ if eq $index 0}}...{{ end }} )かどうかで判断することにした
説明に必要そうなHTMLタグに絞ってある
<div class="carousel-inner">
    {{ range $index, $video := .Params.videos }}
    <div class="carousel-item {{ if eq $index 0 }}active{{ end }}">
        <video>
            <source src="{{ $video | relURL }} " type="video/mp4">
        </video>
    </div>
    {{ end }
</div>
shotakahashotakaha

テンプレートで変数を使いたい

{{ $var1 := "変数を代入" }}
  • Goの基本的な書き方(なのかもしれない)
  • :=を使って変数を定義できる