ObsidianとHugoを連携させる

やりたいこと

  1. Obsidianで管理しているvaultのディレクトリ内の.mdをhugoの記事としても公開したい。

前提

  • Obsidian ・・・Windowsにインストール。vaultはOneDriveに保存してある。
    • 設定
      • Wikiリンクはオフ
      • 添付ファイルの保存場所はカレントフォルダ下の「files」サブフォルダ
  • Hugo ・・・Ubuntu on WSL2にバイナリを置いて実行している。レポジトリはWSL2上に配置。

ディレクトリ構成

 1Obsidian
 2Vault
 3├ post (Hugoでも公開用)
 4│ ├ files (画像などの添付ファイルを格納)
 5│ ├ メモ.md (.mdを格納)
 6├ private (非公開のメモ)
 7├ template (テンプレート)
 8
 9Hugo
10├ content
11│ ├ post (ObsidianのVaultのpostへのシンボリックリンク)

フォルダで階層を分けるとHugoとObsidian両方で機能するリンクが作成できなかったためobsidianのVault内にpostフォルダを作成し、その中に一階層で記事となる.mdを作成していく。

やったこと

  1. HugoのcontentディレクトリからObsidianのvaultディレクトリにあるpostフォルダへ「post」という名前でシンボリックリンクを張る
1cd content
2ln -s /mnt/c/Users/shipw/OneDrive/Obsidian/Inbox/post post
  1. リンクのスニペットを次のファイルに作成→ layouts/_default/_markup/render-link.html (なければ作成)
 1{{- $url := urls.Parse .Destination -}}
 2{{- $scheme := $url.Scheme -}}
 3
 4<a href="
 5  {{- if eq $scheme "" -}}
 6    {{- if strings.HasSuffix $url.Path ".md" -}}
 7      {{- relref .Page .Destination | safeURL -}}
 8    {{- else -}}
 9      {{- printf "/%sfiles/%s" .Page.File.Dir .Destination | safeURL -}}
10    {{- end -}}
11  {{- else -}}
12    {{- .Destination | safeURL -}}
13  {{- end -}}"
14  {{- with .Title }} title="{{ . | safeHTML }}"{{- end -}}>
15  {{- .Text | safeHTML -}}
16</a>
17
18{{- /* whitespace stripped here to avoid trailing newline in rendered result caused by file EOL */ -}}

Obsidianの設定で添付ファイルの保存場所をカレントフォルダ下の「files」サブフォルダへ配置するようにしているので、添付ファイルはfilesフォルダ以下のファイルへリンクさせたい。それを実現するのがこの行。

1{{- printf "/%sfiles/%s" .Page.File.Dir .Destination | safeURL -}}

これにより.md以外の拡張子で終わる相対リンクは添付ファイルへのリンクとしてfilesサブフォルダ内にある同名のファイルへのリンクへ変換される。
3.画像のスニペットを次のファイルに作成→ layouts/_default/_markup/render-image.html (これもなければ作成)

 1{{- $url := urls.Parse .Destination -}}
 2{{- $scheme := $url.Scheme -}}
 3
 4<img src="
 5  {{- if eq $scheme "" -}}
 6    {{- if strings.HasSuffix $url.Path ".md" -}}
 7      {{- relref .Page .Destination | safeURL -}}
 8    {{- else if strings.HasPrefix $url.Path "/" -}}
 9      {{- .Destination | safeURL -}}
10    {{- else -}}
11      {{- printf "/%sfiles/%s" .Page.File.Dir .Destination | safeURL -}}
12    {{- end -}}
13  {{- else -}}
14    {{- .Destination | safeURL -}}
15  {{- end -}}"
16  {{- with .Title }} title="{{ . | safeHTML }}"{{- end -}}
17  {{- with .Text }} alt="{{ . | safeHTML }}"
18  {{- end -}}
19/>
20
21{{- /* whitespace stripped here to avoid trailing newline in rendered result caused by file EOL */ -}}

画像も添付ファイルの一種として扱っているので相対パスの画像については「ページのディレクトリパス+"files/"+画像ファイル名」のURLを生成することで画像が表示されるようにしている。

運用

  1. ,Obsidianで通常通りファイルを作成する
  2. テンプレートでフロントマターを挿入する。ObsidianとHugoで共通のフロントマターが使用できる。

YAML形式のサンプル

 1---
 2title: {{title}} 
 3date: {{date:YYYY-MM-DD}}T{{time:HH:mm:ss}}+09:00
 4slug: 
 5aliases:
 6  - 
 7categories:
 8  - 
 9tags:
10  - メモ
11---
  • ファイル名は2バイト文字も使用するが、URLはURLエンコーディングされない文字だけにしてすっきりさせたいので、slugを英数字とハイフンで指定する。
  1. ガシガシ書く。画像もコピペやドラッグで挿入するだけで、画像はfilesフォルダに入り、適切なマークダウンが記述されるので、いちいち「画像のマークダウンなんだっけ??」「ファイル名をコピペして~」として記述する必要がなくなり大変便利になった。

問題点

ホットリロードが効かない

通常ならファイル変更を検知してホットリロードが効くのだけど、Windows上のNTFSだとファイル変更が検知されない。そのためプレビューするためにはファイルを修正するたびにビルドしてブラウザを再読み込みしなければならない。

これは面倒なので--pollオプションを使うと指定した間隔でポーリングしてファイル変更を検出してリロードしてくれるようになる。

例)15秒間隔でチェックする場合

1hugo server --poll 15s

スクリーンショット

[!NOTE] 運用のポイント フォルダを分けないため、記事が多くなると一覧性が悪くなるのでタグの付け方でカバー

Mac OSでも同じ運用を行うポイント

Macでも同じようにOneDriveに保存してあるObsidianのvault内のpostディレクトリにシンボリックリンクを貼ることで同様の運用にできた。

ただ、Hugoのバージョンを上げた影響かpostディレクトリ配下のfilesがpublicディレクトリにコピーされない症状が出てしまった。

Page Bundleの仕組み的にこれまでコピーされていたのがおかしかったのだろうが画像が表示されなくなるのは困る。

そこで、mountsというmoduleを使って、postsディレクトリの中のfilesディレクトリをstaticディレクトリにマウントするようにした。そうすることで、publicディレクトリにもコピーされるようになり、画像が表示されるようになった。

1[module]
2[[module.mounts]]
3  excludeFiles = '*.md'
4  source = 'content/post/files'
5  target = 'static/post/files'
6[[module.mounts]]
7  excludeFiles = '*.md'
8  source = 'content/book/files'
9  target = 'static/book/files'

画像が403になったのでパーミッションを見てみると600だった。デプロイ時にrsyncの--chmod=a+r オプションで読み込み属性を追加。

関連記事