## 経緯
前から気になっていた[[img-clip.nvim]]を試してみる。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" />
<span class="link-card-v2-site-name">GitHub</span>
</div>
<div class="link-card-v2-title">
GitHub - hakonharnes/img-clip.nvim: Embed images into any markup language, like LaTeX, Markdown or Typst
</div>
<div class="link-card-v2-content">
Embed images into any markup language, like LaTeX, Markdown or Typst - hakonharnes/img-clip.nvim
</div>
<img class="link-card-v2-image" src="https://opengraph.githubassets.com/6d2e9f46785f6fd01968276bd9e18227451077143109fc2497d5002c5dbe7688/hakonharnes/img-clip.nvim" />
<a href="https://github.com/hakonharnes/img-clip.nvim"></a>
</div>
仕事では[[Neovim]]を使って[[MkDocs]]のドキュメントを書くことが多いので、クリップボードの画像や[[PNG]]ファイルを[[WebP]]に変換して[[Markdown]]に挿入したくなることが多い。今だと以下の手順が必要。
1. [[Shottr]]でスクリーンショットをキャプチャする
2. [[Raycast]]の独自コマンドを使って、[[クリップボード]]の[[PNG]]画像を[[WebP]]画像ファイルに変換
3. [[Ghostty]]にて、2で作成されたファイルを、[[MkDocs]]の画像ディレクトリにコピーする
正直かなり面倒であり、画像の利用を本能的に避けてしまっている。
## インストール
```lua
return {
"HakonHarnes/img-clip.nvim",
event = "VeryLazy",
opts = {
},
keys = {
{ "<space>p", "<cmd>PasteImage<cr>", desc = "Paste image from system clipboard" },
},
}
```
[[クリップボード]]に画像をコピーして `<space>p` で起動。ファイル名の入力を求められるので必要なら入力。未入力だと勝手にファイル名を生成してくれる。
## 設定変更
最終的には以下のような設定にした。
```lua
return {
"HakonHarnes/img-clip.nvim",
event = "VeryLazy",
opts = {
default = {
dir_path = function()
-- WARN: CWDと同一の場合はうまく動かないが、mkdocsプロジェクトの場合はdocs配下になるので平気なはず
return vim.fn.expand("%:h") .. "/attachments"
end,
insert_mode_after_paste = false,
-- INFO: AVIFにコンバート. quality 35 は劣化が肉眼で判別困難なギリギリのレベル.
extension = "avif",
process_cmd = "convert - -quality 35 avif:-",
},
filetypes = {
markdown = {
-- https://minerva.mamansoft.net/vim-0004
template = "",
},
},
},
keys = {
{ "<space>p", "<cmd>PasteImage<cr>" },
},
}
```
重要な部分は後ほど。
## クリップボードからの貼り付け
[[クリップボード]]に[[PNG]]画像をコピーした状態から、貼り付ける形で画像挿入する場合。
### 画像が作成されるディレクトリパスの指定
以下のように設定すると、[[カレントディレクトリ (Neovim)|カレントディレクトリ]]からの相対パスとして `dir_path` で指定されたディレクトリ配下に画像が作成される。
```lua
default = {
dir_path = function()
-- WARN: CWDと同一の場合はうまく動かないが、mkdocsプロジェクトの場合はdocs配下になるので平気なはず
return vim.fn.expand("%:h") .. "/attachments"
end,
}
```
上記は『画像を挿入するファイルと同じ階層にある `attachments` ディレクトリ配下に画像を作成する』という設定。
### AVIF変換とクオリティ低下によるサイズ削減
[[クリップボード]]の[[PNG]]画像をそのまま挿入するとサイズが大きすぎるので、[[AVIF]]への変換とクオリティ指定によるサイズ削減を行う。
```lua
default = {
-- INFO: AVIFにコンバート. quality 35 は劣化が肉眼で判別困難なギリギリのレベル.
extension = "avif",
process_cmd = "convert - -quality 35 avif:-",
}
```
`extension` は単なる拡張子の指定。これだけだと画像のフォーマット変換(コンバート)は行われない。`process_cmd` の指定が必要。
もともとは[[WebP]]を使っていたが、 [[AVIF]]を利用することにした理由と、`-quality` が `35` である理由は以下。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" />
<span class="link-card-v2-site-name">Minerva</span>
</div>
<div class="link-card-v2-title">
💿MIN-0039 OGP以外の画像ファイルにはAVIFを使う
</div>
<div class="link-card-v2-content">OGPにはWebPを引き続き使うことを条件に、ファイル内の画像はAVIFにする。ネックだったコンバート速度が大きく改善され、macOSのRetinaディスプレイ対応により、ファイルサイズ削減の重要性が増したため。ImageMagicKの `-quality` は `35` を推奨とする。</div>
<img class="link-card-v2-image" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/minerva-adr3.webp" />
<a data-href="💿MIN-0039 OGP以外の画像ファイルにはAVIFを使う" class="internal-link"></a>
</div>
%%[[💿MIN-0039 OGP以外の画像ファイルにはAVIFを使う]]%%
## Markdownの画像リンクとして挿入する
画像リンクは[[Markdown]]の形式で挿入する。
```lua
default = {
filetypes = {
markdown = {
template = "",
},
},
},
```
設定のデフォルト値は `""` となっており、画像プレビューやファイル移動としてはそれでも問題ない。しかし、[[blink.cmp (Neovim)|blink.cmp]]は `./` から始まるパスでないと補完が表示されなかったので、明示的な相対パスにしている。
![[2025-06-09-00-37-28.avif|frame]]
*この補完が `./` からでないと出ない*
Wikiリンクを使わない理由は以下[[ADR]]を参照。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" />
<span class="link-card-v2-site-name">Minerva</span>
</div>
<div class="link-card-v2-title">
💿VIM-0004 MkDocsの画像表示はMarkdownリンクを使う
</div>
<div class="link-card-v2-content">標準のMarkdownリンク形式であり、ツールを問わず安定して動作しそうなこと。リネームの機会はそこまで多くないこと。blink.cmpや画像ファイルを開くアクションとの相性などを考慮し、メリット・デメリット共に優れていると判断した。</div>
<img class="link-card-v2-image" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/vim-adr.webp" />
<a data-href="💿VIM-0004 MkDocsの画像表示はMarkdownリンクを使う" class="internal-link"></a>
</div>
%%[[💿VIM-0004 MkDocsの画像表示はMarkdownリンクを使う]]%%
## ドラッグ&ドロップについて
[[PNG]]では対応しているが、[[WebP]]ではまだできなそう。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" />
<span class="link-card-v2-site-name">GitHub</span>
</div>
<div class="link-card-v2-title">
Allow more file types, like SVG and PDF · Issue #83 · hakonharnes/img-clip.nvim
</div>
<div class="link-card-v2-content">
Is your feature request related to a problem? Please describe. Using the telescope picker, I was actually expect ...
</div>
<img class="link-card-v2-image" src="https://opengraph.githubassets.com/2d57597c201079d5aa2c0fee45f60a9208a1c72fa49393957463e93e31882ea2/hakonharnes/img-clip.nvim/issues/83" />
<a href="https://github.com/hakonharnes/img-clip.nvim/issues/83"></a>
</div>
**外部からドラッグ&ドロップしたファイルを、`dir_path` 配下に複製したうえでリンクを貼る** ということができなければ、 ユースケースとしてそこまで使う機会はない気がする。