1. Home
  2. /
  3. Saltの使い方
  4. /
  5. Content adaptersに対応しました&既存の記事の移行方法

Content adaptersに対応しました&既存の記事の移行方法

Content adaptersに対応しました&既存の記事の移行方法

Hugo Theme Salt v3.0.0でもContent adaptersに対応しました。
使用方法と移行方法をまとめたので参考にして下さい

前提として

  • 目次が使えません
  • ページバンドル内の画像ファイル等が考慮されていません(記事本文を修正する必要あり)
  • 本文内にHugoの記法がある場合ビルドエラーになります({{ xxx }}の記述)
  • ディレクトリ構造について
    • 下記の構成で記事を保存している
      • content/article/[category]/[article]/index.md
      • content/article/[category]/[article]/thumbnail.jpg
    • 記事ディレクトリパスと記事URLパスが同一(slugを使用している場合は未検証)

Content adaptersを使用した記事表示方法

大まかな流れとしては下記の通り

  1. assetsディレクトリ内に記事jsonとサムネ画像を配置
  2. カテゴリーディレクトリに_content.gotmplを作成(今回は「hugo-release」カテゴリー)

1. assetsディレクトリ内に記事jsonとサムネ画像を配置

下記形式で記事データを配置して下さい

├── assets
│   ├── article
│   │   └── hugo-release
│   │       ├── v0.145.0
│   │       │   ├── index.json
│   │       │   └── thumbnail.png
│   │       ├── v0.146.0
│   │       │   ├── index.json
│   │       │   └── thumbnail.png
│   │       └── v0.147.0
│   │           ├── index.json
│   │           └── thumbnail.jpg

サムネを使用する場合はthumbnail: にassetsディレクトリ内の画像パスを記載して下さい

assets/article/hugo-release/v0.145.0/index.json

{
    "path": "v0.145.0",
    "title": "Hugo v0.145.0 リリースノートまとめ",
    "description": "",
    "date": "2025-05-29T15:23:31+09:00",
    "lastmod": "2025-05-29T15:23:31+09:00",
    "draft": false,
    "tags": [
        "Hugo",
        "Hugoリリースノートまとめ"
    ],
    "categories": "Hugoリリース",
    "archives": [
        "2025年5月"
    ],
    "share": true,
    "toc": false,
    "comment": true,
    "thumbnail": "/article/hugo-release/v0.145.0/thumbnail.png",
    "content": "<div class=\"markdown-alert markdown-alert-warning\" dir=\"auto\"><p class=\"markdown-alert-title\" dir=\"auto\">..."
}

2. カテゴリー内に_content.gotmplを作成

_content.gotmplを作成

├── content
│   ├── article
│   │   └── hugo-release
│   │       └── _content.gotmpl

gotmpl内の読み込みディレクトリ(article/[category])は対象のカテゴリに変更して下さい

exampleContent/article/hugo-release/_content.gotmpl

{{ $data := slice }}

{{ range where (os.ReadDir "assets/article/hugo-release") "IsDir" "eq" true }}
    {{ $path := .Name }}
    {{ with resources.Get (printf "article/hugo-release/%s/index.json" $path) }}
        {{ with . | transform.Unmarshal }}
            {{ $data = $data | append . }}
        {{ end }}
    {{ end }}
{{ end }}

{{ range $data }}
    {{ $content := dict
        "mediaType" "text/markdown"
        "value" .content
    }}
    {{ $dates := dict
        "date" (time.AsTime .date)
        "lastmod" (time.AsTime .lastmod)
    }}
    {{ $params := dict
        "title" .title
        "description" .description
        "date" (time.AsTime .date)
        "lastmod" (time.AsTime .lastmod)
        "tags" .tags
        "categories" .categories
        "archives" .archives
        "draft" .draft
        "share" .share
        "toc" .toc
        "comment" .comment
        "thumbnail" .thumbnail
    }}
    {{ $page := dict
        "path" .path
        "title" .title
        "draft" .draft
        "dates" $dates
        "content" $content
        "params" $params
    }}
    {{ $.AddPage $page }}
{{ end }}

Hugoサーバーを起動して記事が表示される事を確認して下さい

hugo server -D --disableFastRender

実際のソースはこちらを参考にしてみて下さい

https://github.com/okdyy75/hugo-theme-salt/tree/main/assets/article/hugo-release/v0.145.0

https://github.com/okdyy75/hugo-theme-salt/tree/main/exampleContent/article/hugo-release/v0.145.0


移行の流れ

大まかな移行の流れとしては下記の通りです

  1. 移行したい記事のURL一覧、記事データをjson出力
  2. assets配下に記事データをコピーするスクリプトを実行
  3. Content adaptersへの移行
  4. 後片付け

移行したい記事のURL一覧、記事データをjson出力

json出力するためにconfig.ymlに下記を追記して下さい

config.yml

outputs:
  home:
    - html
    - json
  page:
    - html
    - json

Hugo Theme Salt内で全記事を対象にする場合は下記の様にして下さい

layouts/_default/home.json

[
  {{- range $index, $page := where .Site.RegularPages "Section" "article" -}}
    {{- if $index }},{{- end -}}
    {{- $page.Permalink | jsonify -}}
  {{- end -}}
]

layouts/_default/single.json

{
    "path": {{ path.BaseName .RelPermalink | jsonify }},
    "title": {{ .Params.Title | jsonify }},
    "description": {{ .Params.Description | jsonify }},
    "date": {{ .Params.Date | jsonify }},
    "lastmod": {{ .Params.Lastmod | jsonify }},
    "draft": {{ .Draft | jsonify }},
    "tags": {{ .Params.Tags | jsonify }},
    "categories": {{ .Params.Categories | jsonify }},
    "archives": {{ .Params.Archives | jsonify }},
    "share": {{ .Params.share | jsonify }},
    "toc": {{ .Params.toc | jsonify }},
    "comment": {{ .Params.comment | jsonify }},
    {{ with .Resources.GetMatch "thumbnail.*" }}
        "thumbnail": {{ .RelPermalink | jsonify }},
    {{ else with .Params.thumbnail }}
        "thumbnail": {{ . | jsonify }},
    {{ end }}
    "content": {{ .Content | jsonify }}
}

ローカルサーバーを起動して

hugo server -D --disableFastRender

URL一覧と
http://localhost:1313/index.json

記事データがjsonが出力されているかを確認して下さい
http://localhost:1313/article/hugo-release/v0.147.0/index.json

②assets配下に記事データをコピーするスクリプトを実行

記事のURL一覧を元に、記事json&サムネ画像を保存するスクリプトを実行します

node scripts/copy-article-to-assets.js

scripts/copy-article-to-assets.js

const fs = require('fs')
const path = require('path')

/**
 * 記事データをコピーし、assetsディレクトリに保存するスクリプト
 * Usage: node scripts/copy-article-to-assets.js
 */

// ベースディレクトリの設定
const BASE_DIR = path.resolve(__dirname, '..')
const ASSETS_DIR = path.join(BASE_DIR, 'assets')
const CONTENT_DIR = path.join(BASE_DIR, 'content')

/**
 * JSONのURLを取得して指定ディレクトリにindex.jsonとして保存する
 */
async function saveIndexJson(inputJsonUrl, outputJsonDir) {
    const response = await fetch(inputJsonUrl)
    const jsonData = await response.json()
    const saveFilePath = path.join(outputJsonDir, 'index.json')
    fs.mkdirSync(outputJsonDir, { recursive: true })
    fs.writeFileSync(saveFilePath, JSON.stringify(jsonData, null, 4), 'utf-8')
    console.log(`index.jsonを保存しました: ${saveFilePath}`)
}

/**
 * 指定ディレクトリからthumbnail画像をコピーする
 */
function copyThumbnailImage(inputThumbnailDir, outputThumbnailDir) {
    if (!fs.existsSync(inputThumbnailDir)) {
        // ディレクトリが存在しない場合はコピーしない
        return
    }
    const files = fs.readdirSync(inputThumbnailDir)
    const thumbnailFiles = files.filter((file) => /^thumbnail\..+/.test(file))

    if (thumbnailFiles.length > 0) {
        const thumbnailFile = thumbnailFiles[0]
        const inputFilePath = path.join(inputThumbnailDir, thumbnailFile)
        const outputFilePath = path.join(outputThumbnailDir, thumbnailFile)
        fs.mkdirSync(outputThumbnailDir, { recursive: true })
        fs.copyFileSync(inputFilePath, outputFilePath)
        console.log(`サムネイル画像をコピーしました`)
        console.log(`from: ${inputFilePath}`)
        console.log(`  to: ${outputFilePath}`)
    }
}

/**
 * メイン処理
 */
async function main() {
    // サイトのindex.jsonからURL一覧を取得
    const siteIndexUrl = 'http://localhost:1313/index.json'
    const response = await fetch(siteIndexUrl)
    const urls = await response.json()

    for (const url of urls) {
        console.log('==========================================')
        console.log(`対象URL: ${url}`)

        // URLからパスを抽出
        const urlObj = new URL(url)
        const urlPath = urlObj.pathname

        // 1. index.jsonを取得&保存
        const inputJsonUrl = `${url}index.json`
        const outputJsonDir = path.join(ASSETS_DIR, urlPath)
        await saveIndexJson(inputJsonUrl, outputJsonDir)

        // 2. thumbnail画像をコピー
        const inputThumbnailDir = path.join(CONTENT_DIR, urlPath)
        const outputThumbnailDir = path.join(ASSETS_DIR, urlPath)
        copyThumbnailImage(inputThumbnailDir, outputThumbnailDir)
        console.log('==========================================\n')
    }
}

;(async () => {
    console.log('処理を開始します...')
    await main()
    console.log('処理が完了しました!')
})()

実行後は下記の形式で保存されます

assets/article/[category]/[article]/index.json
assets/article/[category]/[article]/thumbnail.png

③Content adaptersへの移行

Content adaptersを使用した記事表示の流れを参考にContent adaptersを実装して下さい

④後片付け

最後に移行作業用に作成したファイルや記述を削除して作業完了です!

config.ymlの下記記述を削除

-outputs:
-  home:
-    - html
-    - json
-  page:
-    - html
-    - json
-

移行に使用したテンプレートファイルを削除

rm layouts/_default/home.json
rm layouts/_default/single.json

関連記事

Hugo標準のgistショートコードをテーマ内に移行しました

Hugo標準のgistショートコードをテーマ内に移行しました

Hugo公式のgistショートコードはバージョン0.143.0で非推奨となり、将来のリリースで削除されるそうなので Hugo Theme Salt内ののショートコードとして使えるように移行しました

WARN  The "gist" shortcode was deprecated in v0.143.0 and will be removed in a future release. See https://gohugo.io/shortcodes/gist for instructions to create a replacement.

Hugo公式ページでは下記の通り

Gist shortcode

Embed a GitHub Gist in your content using the gist shortcode.


The gist shortcode was deprecated in version 0.143.0 and will be removed in a future release. To continue embedding > GitHub Gists in your content, you’ll need to create a custom shortcode:

Gist ショートコードはバージョン 0.143.0 で非推奨となり、今後のリリースで削除される予定です。コンテンツに GitHub Gist を埋め込むには、カスタムショートコードを作成する必要があります。

Hugo v0.147.0 リリースノートまとめ

Hugo v0.147.0 リリースノートまとめ

Warning

※この記事は生成AIを使用して作成された記事です。(create by GPT-4o)
記事内容については未検証ですので参考程度にご活用ください

2025年4月25日にリリースされた Hugo v0.147.0 の主な更新内容をまとめます。既存ユーザー向けに 新機能主な変更点バグ修正非推奨事項を分類し、プロジェクトへの影響や対応方法のヒントを解説します。

新機能

  • images.Text の縦位置指定オプション追加
    画像操作機能 images.Text にテキストの縦位置を指定できる新オプション aligny が導入されました。従来からの alignx オプションと組み合わせることで、画像上のテキストを縦横とも中央に配置するなど、柔軟なレイアウトが可能になります。

主な変更点

  • 設定(config)マージの改善
    デフォルト設定の適用順序が見直され、モジュールやテーマから読み込んだ設定をルートの設定により柔軟に統合できるようになりました。具体的には、config.toml 等で _merge = "deep" を指定すると、インポートしたモジュールやテーマの設定を深い階層までマージするようになります。これにより、複数サイトで共通設定を共有する際に、設定の上書きや階層構造が意図しない形で失われる問題を回避しやすくなります。詳細についてはドキュメントを参照してください。

  • テーマスケルトンのテンプレート名調整
    テーマ作成用スケルトン (create/skeletons) において、一部テンプレートファイル名が変更されました。既存のカスタムテーマをインポートしている場合は、ファイル名の差分に注意してください。

バグ修正

  • コードブロックレンダリング
    組み込みのコードブロックレンダリングを、カスタムの render-codeblock-*.html テンプレートよりも優先するよう修正されました。

  • Vimeo/YouTube ショートコード
    allowFullScreen オプションの不具合が修正され、YouTube/Vimeo ショートコードで全画面表示が正しく機能するようになりました。

  • 設定マージ (_merge) のバグ
    キーが存在しない場合の _merge 処理に関する不具合が修正されました。

  • タイポ・文言修正
    ドキュメントやコード内の軽微な誤記やコメント表記の修正が行われました。

非推奨事項

今回のリリースでは、非推奨(deprecation)とされた機能は特にありません。既存の機能が削除・変更される予定も発表されていないため、現状のコードをそのまま継続利用できます。

影響と対応のヒント

  • 画像テキスト配置の活用
    新しい aligny オプションにより、images.Text を使用した画像上のテキスト配置の自由度が高まりました。alignx と組み合わせて使うことで、テキストを画像の縦横中央に配置するレイアウトが簡単になります。必要に応じてショートコードやテンプレートの更新を検討してください。

  • 設定統合の活用
    複数テーマやモジュールにまたがる設定を共通化している場合、config.toml_merge = "deep" を追加すると良いでしょう。これにより、インポートした設定を階層構造のまままとめて取り込めます。ただし、マージ時に意図しない上書きが発生しないか、アップデート後に設定ファイルの挙動を確認してください。

  • カスタムテンプレートの確認
    独自に作成した render-codeblock-*.html テンプレートなどがある場合、内部レンダリングの優先度変更によって出力結果が変わる可能性があります。新バージョンでサイトをビルドした際に、コードブロックの表示が期待通りかチェックしておくと安心です。

  • ショートコードの挙動確認
    既存サイトで Vimeo/YouTube ショートコードの allowFullScreen オプションを使用している場合、今回の修正により全画面表示が正しく動作するようになります。特に何か対応する必要はありませんが、アップデート前後で動作に差がないか確認しておくと良いでしょう。


参考: Hugo v0.147.0 リリースノート(GitHub)