PDF Pair

unlisted

by takosasi-dev

Find PDFs that were built from an older version of their Markdown note. Read-only.

Updated 2d agoMIT
View on GitHub

PDF Pair

Markdown のノート(md)と、そこから作った PDF の組を見つけ、その PDF が「今の md の中身」から作られた物かを、右サイドバーの一覧とタブの見出し部のアイコンで知らせる Obsidian プラグインです。vault のファイルは読むだけで、md も PDF も書き換えません(書くのはプラグイン自身の data.json だけ)。ネットワークには出ません。PC でもモバイルでも動く作りです。

English summary is at the bottom.

先に知っておくこと: PDF を作る側が、PDF の Keywords に pdfpair:{...} の印を書いている必要があります。 印の無い PDF は、古いとも新しいとも言えないので、全部「由来不明」に出ます。このプラグインは PDF を作りませんし、印も書きません。印の形は下の「印の形」に、印を書く生成スクリプトの例は generator/ にあります。

できること

  • 組を見つける: PDF と同じフォルダの同名の md か、「PDF」という名前のフォルダを 1 段抜いた場所の同名の md を組にする
  • 中身で判定する: 印に入っている SHA-256 と、今の md・図の SHA-256 を比べる。更新日時は判定に使わない
  • 5 つに分ける: 古い / 要確認 / 読めない / 由来不明 / 一致
  • 一覧: 右サイドバーに、分け方ごとの件数と組の一覧を出す。行を押すと md、ボタンで PDF が開く
  • 見出し部のアイコン: 組のある md を開くと状態のアイコンが 1 つ、組のある PDF を開くと「元の md を開く」が出る
  • 確認印: 印の無い PDF を自分の目で見て「確認済みにする」と、その後 md が変わったときに「古い」と出る
  • 依頼文のコピー: 古くなった組を並べた、作り直しを頼む文をクリップボードに入れる
  • 変化への追従: ファイルの変化がおさまってから判定し直す。md を直して元に戻せば「一致」に戻る

向いている vault(前提)

md と PDF が、次のどちらかの置き方になっている vault です。名前は同じ(拡張子だけ違う)であること。

Notes/guide.md
Notes/guide.pdf          ← 同じフォルダの同名。guide.md と組になる
Notes/PDF/memo.pdf       ← 「PDF」フォルダを 1 段抜いた Notes/memo.md と組になる
Notes/PDF/sub/plan.pdf   ← Notes/sub/plan.md と組になる
  • 「PDF」というフォルダ名は既定の値です。違う名前なら、設定の「PDF を入れるフォルダの名前」を書き換えます
  • 両方に同じ名前の md があれば同じフォルダの方を採り、行に 候補が2つ(同じフォルダの md を採った) と出ます
  • 印があって、印が指す md が vault にあれば、名前の規則よりそちらを採ります
  • 名前の規則で md が見つからない PDF は、印があっても一覧に出ません

印の形

PDF の Info の Keywords を、pdfpair: で始まり、その後ろが JSON 1 つの文字列にします。

pdfpair:{"v":1,"tool":"my-pdf-tool","inputs":[{"path":"../memo.md","sha256":"<64 桁の 16 進>"},{"path":"../fig/chart.svg","sha256":"<64 桁の 16 進>"}],"built":"2026-01-15T12:00:00+09:00"}
項目型要るか中身
接頭辞 pdfpair:—必須Keywords の先頭がこの文字であること。前に空白やほかのキーワードがあると「印なし」になる
v数必須1
inputs配列必須1 つ以上。先頭が md、2 つ目からは PDF に取り込んだ図や画像
inputs[].path文字必須PDF のあるフォルダからの相対パス。区切りは /。.. で上のフォルダを指せるが、vault の根は越えられない
inputs[].sha256文字必須PDF を作ったときに読んだ、そのファイルの生のバイト列の SHA-256(64 桁の 16 進)
tool文字任意作った道具の名前。記録用で、今の版では画面に出ない
built文字任意作った日時。「一致」の理由に 印 <built> と出るだけで、判定には使わない
  • 知らない項目があっても無視します。pdfpair: で始まるのに形が合わない印は、印なしと同じに扱い、設定画面の「形式外の印」に件数だけ出します
  • 同梱の例は、日本語のパスを \uXXXX の形にして、ASCII だけの JSON を書きます。ほかの道具でも同じにしておくのが無難です

印を書く生成側の例

generator/ に、md から日本語の PDF を作り、最後に上の印を書く Python のスクリプト(build_pdf.py)と、その説明(generator/README.md)があります。プラグインとは別の物で、Chromium を動かして PDF を書き出します(下の「安全のための決まり」はプラグインの話で、generator には当てはまりません)。PDF と同じ場所に、同じ名前の .html(中間のファイル)が残ります。自分の生成の道具に印を足すときは、read_input・stamp_keywords・write_stamp の 3 つの関数が見本になります。

入れ方

BRAT で入れる(おすすめ)

  1. コミュニティプラグインの「BRAT」(Obsidian42 - BRAT)を入れて有効にする。
  2. BRAT の設定 → 「Add Beta plugin」に takosasi-dev/pdf-pair を入れる。
  3. コミュニティプラグインの一覧で「PDF Pair」を有効にする。

手で入れる

Releases から main.js・manifest.json・styles.css を落とし、vault の .obsidian/plugins/pdf-pair/ に置いて、コミュニティプラグインの一覧で有効にします。

使い方

コマンド

コマンドパレットに出る名前すること
PDF Pair: PDF の組の一覧を開く右サイドバーに一覧「PDF の組」を出す
PDF Pair: PDF の組を判定し直す控えを捨てて、全部の組を読み直す。PDF Pair: N 組を判定しました(古い M 件) と知らせる
PDF Pair: 古い PDF の作り直しの依頼文をコピー「古い」の組を並べた依頼文をクリップボードに入れる。無ければ PDF Pair: 「古い」の組はありません と知らせる

既定のホットキーはありません。

画面の見方

一覧(右サイドバー): 上に 古い N / 要確認 N / 読めない N / 由来不明 N / 一致 N と 最後の判定 <日時>、ボタン「判定し直す」「古い物の依頼文をコピー」。下に、分け方ごとに畳める組の一覧(「一致」は最初は畳んである)。行には md の名前・PDF のパス・<分け方>: <理由> が出ます。行を押すと md、「PDF」で PDF が開き、「…」か右クリックでその組のメニューが出ます。

分け方意味行に出る理由
古いPDF を作った後で md か図の中身が変わったmd が変わった / 図が変わった: <パス> / 確認の後に md が変わった
要確認自動では決められない印の md が見つからない: <パス> / 図が見つからない: <パス> / 図を確かめられなかった / 確認の後に PDF が変わった
読めないPDF・md・図のどれかが読めない。PDF が大きさの上限を超えたpdf.js: <メッセージ> / 大きすぎ / 読めない: <パス>
由来不明印も確認印も無い印なし
一致印(か確認印)のハッシュが、今の中身と全部同じ印 <作った日時> / 確認印 <確認した日時>

見出し部のアイコン: 組のある md のタブに、状態のアイコンが 1 つ付きます(古い=赤・要確認=橙・読めない=紫・由来不明=灰・一致=緑。形も違う)。乗せると <分け方>: <理由> — <PDF のパス>、押すとメニューが出ます。1 つの md に PDF が 2 つあるときは、一覧で上に来る方の状態になります。組のある PDF のタブには 元の md を開く: <md のパス> が付きます。

組のメニュー:

  • 「PDF を開く」(見出し部のアイコンからだけ)
  • 「確認済みにする」: 印が無い「由来不明」「要確認」の組にだけ出る。今の md と PDF のハッシュを確認印として残し、「一致」になる
  • 「確認印を外す」: 確認印のある組に出る
  • 「作り直しの依頼文をコピー」: その 1 組の依頼文をクリップボードに入れる
  • 「一覧を開く」(見出し部のアイコンからだけ)

依頼文は次の形です(パスは例)。文面は固定で、1 行目の「スキル ja-pdf-build」は作者の環境での生成の道具の呼び名です(中身は同梱の generator/)。ほかの道具で作っているなら、貼った後で書き換えてください。

次の PDF を、スキル ja-pdf-build で md から作り直してください(PdfPair の判定 2026-01-15 21:00、古い 1 件)。
- Notes/memo.md → Notes/PDF/memo.pdf(md が変わった)
PDF は同じパスに上書きし、作り直した後に PdfPair の一覧で「一致」になることを確かめてください。

設定

項目既定内容
除外フォルダ空1行に1つ。vault からの相対パス。md か PDF のどちらかが配下にある組を出さない
PDF を入れるフォルダの名前PDF1行に1つ。PDF のパスからこの名前のフォルダを1段抜いた場所の、同名の md を組にする
起動時に全部の組を判定するON切ると、開いたノートの組だけをその場で判定し、全部は一覧を開いたときとコマンドのときに判定する
変化をまとめて受ける時間(ミリ秒)1000ファイルの変化がこの時間おさまってから判定し直す
読む PDF の大きさの上限(MB)20これを超える PDF は読まずに「読めない」(理由 大きすぎ)にする
確認印の数(見るだけ)確認印の件数と、どの組にも当たらない物の件数
どの組にも当たらない確認印をまとめて外す(ボタン)md の名前を変えた後などに残った確認印を外す
pdf.js の版 / 最後に全部の組を判定したとき / 読めなかった組 / 形式外の印(見るだけ)診断の 4 行。組の数・かかった時間・読めなかった数など

安全のための決まり

  • vault のファイルは 1 つも書き換えません。md・PDF・図を読むだけで、横にファイルも作りません
  • 書くのは自分の data.json(設定と確認印)だけです。確認印に残すのは、md と PDF のパス・md の SHA-256・PDF の大きさと SHA-256・確認した日時。戻すには「確認印を外す」を選ぶか、data.json を消します
  • data.json が壊れている・版が違うときは既定値で動き、上書きしません(PDF Pair: …。既定値で動かします(data.json は上書きしません) と知らせます)
  • ネットワークに出ません。Node.js / Electron の機能を使いません(モバイルでも動く作り)。PDF は Obsidian に入っている pdf.js で読み、外から部品を読み込みません
  • クリップボードに書くのは、依頼文のコピーを自分で選んだときだけです

動作確認の状況

  • 版 0.1.0。Windows の Obsidian 1.14.4 で動作を確認(一覧・見出し部のアイコン・「確認済みにする」と、読み込み直した後も確認印が残ること)
  • iPhone・Android の実機は未確認(モバイル表示のエミュレーションで読み込みと表示まで確認)
  • generator/ で実際に PDF を作る確認は、まだできていません。 そのため、本物の印つきの PDF で「一致」「古い」になる所は実機で見ていません(印の読み取りと判定はテストで確かめてあります)
  • 本物のクリップボードへの書き込みも未確認です

分かっている限界

  • 印の無い PDF は「由来不明」に出るだけです。古いとも新しいとも言いません。「確認済みにする」で扱うか、印を書く道具で作り直します
  • md の生のバイト列でハッシュを取るので、改行コードが変わっただけでも「古い」になり得ます。Obsidian は、CRLF 混じりのノートを開くと LF にそろえて保存することがあります。PDF を作る前に md の改行を LF にそろえておくと避けられます
  • front matter だけ直しても「古い」になります(md 全体のハッシュなので)。図を差し替えても「古い」になります
  • md や PDF を動かす・名前を変えると、印のパスが外れて「要確認」になるか、組から消えます。確認印も当たらなくなります(設定の「どの組にも当たらない確認印をまとめて外す」で片づけます)
  • 確認済みにできるのは、印の無い組だけです。確認の後に md が変わって「古い」になった組は、確認印を外してから付け直します
  • 暗号化された PDF・壊れた PDF は「読めない」になります。vault の外の PDF は見ません

開発

npm install
npm run build        # main.js を作る(型チェックつき)
npm test             # vitest
npm run lint         # eslint-plugin-obsidianmd

組の見つけ方・印の読み取り・判定・SHA-256 は obsidian を import しない関数で、テストは作り物の vault だけを使います。generator/ のテストは python -m pytest generator -p no:cacheprovider で回します(実際に PDF を作るテストは、依存がそろっているときだけ回ります)。

ライセンス

MIT。LICENSE を見てください。


English summary

PDF Pair tells you whether a PDF in your vault was built from the current content of its Markdown note.

  • Pairs x.pdf with x.md in the same folder, or with x.md one level up from a folder named PDF (the folder name is a setting).
  • Requires a stamp written by your PDF generator: the PDF's Keywords must be pdfpair: + JSON {"v":1,"inputs":[{"path","sha256"},...],"tool","built"}. inputs[0] is the note, the rest are embedded figures; path is relative to the PDF's folder; sha256 is the SHA-256 of the raw file bytes. An example generator that writes the stamp is in generator/ (Python, separate from the plugin; building real PDFs with it has not been verified yet).
  • Five states: stale, needs checking, unreadable, unknown origin, match. PDFs without a stamp are listed as "unknown origin"; you can mark them as confirmed by hand.
  • Judged by content hashes only, never by modification time. A change of line endings alone (CRLF to LF) makes a note count as changed.
  • Read-only: never changes notes or PDFs. Writes only its own data.json (settings and manual confirmations). Writes to the clipboard only when you choose to copy a rebuild request.
  • No network. No Node.js or Electron APIs; PDFs are read with the pdf.js bundled in Obsidian.
  • Install with BRAT: takosasi-dev/pdf-pair. The UI is in Japanese.
  • Tested on Windows desktop (Obsidian 1.14.4) only; real phones are untested.

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.