おんがえしの blog

作ったプログラムと調べた技術情報

Obsidian のノートに前後関係を設定する

Obsidian というノートエディタをここ数年愛用している。リンクを貼るときの自動補完が特に素晴らしい。この原稿も Obsidian で書いているし、ライフログ的なものも、 Zettelkasten 的なアイデアメモもすべてここにまとめている。Obsidian Sync もサブスクしていて、スマホでもPCでもどこからでも書けるようにしている。

基本的には大変便利なのだが、時系列に追加されていく、前後関係のあるノート群を作成するのが面倒だという問題があった。

例として、 [[献立 2025-W10]][[献立 2025-W11]][[献立 2025-W12]] のように毎週の献立をメモするノート(Wは週番号)を作り、前後に移動できるようにしたいとする。新規に[[献立 2025-W13]] を作成するには以下の手順が必要となる。

  1. 新規ノート[[献立 2025-W13]]を作成。
  2. [[献立 2025-W13]]から[[献立 2025-W12]]へのリンクを貼る。
  3. [[献立 2025-W12]]を開く。
  4. [[献立 2025-W12]]から[[献立 2025-W13]]へのリンクを貼る。

テンプレートで自動的にリンクを作成する、という方法もあるが、[[アイデア1]][[アイデア1の発展]][[アイデア1の追加機能]] ...のように不定期に発生&タイトルも微妙に変動するようなものもある。

後から見返すときは、リンクで前後に移動できるようにしておいた方が便利なので極力貼っておきたいのだが、作成するときは、その作業が結構面倒くさい。

ノートへの前後関係の設定を、もう少し簡単にやる手段はないだろうかとしばらく考えていた。

previous プロパティを使って前後に移動する

ある日、Obsidian のフロントマターに、プロパティとして前のページのリンクを貼る、というアイデアを思いついた。

プロパティには previous という名前を付けた。

献立 2025-W12

---
previous: "[[献立 2025-W11]]"
---
[[にんじんシリシリ]]
[[ピーマンの肉詰め]]

献立 2025-W13

---
previous: "[[献立 2025-W12]]"
---
[[蒸しブロッコリー]]
[[かぼちゃのしょうゆ煮]]

前のページに戻るときは、各ページの previous プロパティを順に辿る。

次のページに進みたいときは、バックリンクを使う。バックリンクを開き、自分をリンクしている次のページ を探してあげればよい。バックリンクをうまく使うことで1つのリンクから前後への移動が可能になった。

この方法なら、新規ノートを作ってリンクで前後に移動できるように設定する作業は、

  1. 新規ノート[[献立 2025-W13]]を作成。
  2. [[献立 2025-W13]]から[[献立 2025-W12]]へのリンクを貼る。

だけで済む。編集するノートとリンクが1つで済むのがとても気に入った。

次のノートへの移動の自動化

前のノートへの移動は大分便利になったが、次のノートへの移動が、バックリンクを開いて、その中から次のページを探し、クリックするのが段々面倒くさくなってきた。もう少し簡単にならないだろうか。

改めて考えると、

  1. バックリンクのノート群を列挙して
  2. previous プロパティから自身のノートに対してリンクを貼っているノート

を探せばよい。アルゴリズムになったので、この処理はプログラムで書けそうだ。 初めて Obsidian プラグインを作ってみることにした。

github.com

次のノートを探す関数はgetNextNotes() のようになった。

export function getNextNotes(app: App, file: TFile): TFile[] {
  const currentPath = file.path;
  const backlinks = app.metadataCache.resolvedLinks;
  const nextNotes: TFile[] = [];

  for (const [sourcePath, targets] of Object.entries(backlinks)) {
    // Check if the source note links to the current note.
    if (!targets[currentPath]) {
      continue;
    }

    const targetFile = app.vault.getAbstractFileByPath(sourcePath);
    if (!(targetFile instanceof TFile)) {
      continue;
    }

    const previousLinkText = getPreviousLinkpath(app, targetFile);
    if (!previousLinkText) {
      continue;
    }

    // Add only if the `previous` field points to the current note.
    if (previousLinkText === file.basename || previousLinkText === currentPath) {
      nextNotes.push(targetFile);
    }
  }
}

本体はここで、 previous プロパティからリンクしているノートのパスと、現在開いているノートのパスが一致している場合に次のノートと判定する。

    // `previous`フィールドが現在のノートを指している場合のみ、次のノートとして追加する。
    if (previousLinkText === file.basename || previousLinkText === currentPath) {
      nextNotes.push(targetFile);
    }

プラグインコマンドとして作成した go-to-previous-noteAlt-, に、 go-to-next-noteAlt-. に割り当ててみた。キーボードで前後に動けるようになり大分快適になった。

Previous River

前のリンクを設定することで川のように分岐していく前後関係を設定できることから、 Previous River と名付けた。

コミュニティプラグインとして申請しているが、まだ審査待ちの状態なので、気になる人は以下のリリースから main.js と manifest.json をダウンロードして、

https://github.com/ongaeshi/previous-river/releases/tag/0.1.0

自分の vault の下に .obsidian/plugins/previous-river フォルダを掘って置くと使えます。コミュニティプラグインを有効にしてください。

コミュニティプラグインの設定