Skip to content
0

img-clip.nvim

The img-clip.nvim plugin is designed to streamline the process of embedding images into markup languages (like Markdown, LaTeX, or HTML) by automating the clipboard-to-disk workflow. Instead of manually saving a screenshot, moving it to a specific directory, and typing out the image link, the plugin handles these steps with a single command.

Main Logic of img-clip.nvim

  1. Clipboard Detection: When triggered, the plugin checks your system clipboard for image data.
  2. Automated File Management: It generates a unique filename (often based on a timestamp) and saves the image to a directory relative to your current file.
  3. Context-Aware Injection: It detects the filetype of your current buffer (e.g., Markdown) and injects the appropriate syntax (e.g., ![](path/to/image.png)) at your cursor position.
  4. Configuration Overrides: It allows for highly specific configurations based on the project directory or filetype, which is particularly useful for frameworks like VitePress where assets must live in specific folders like public/ or .vitepress/dist/.

The plugin evaluates the options in the following order:

  1. Custom options
  2. File specific options
  3. Directory specific options
  4. Filetype specific options
  5. Default options

Prerequisite

bash
brew install pngpaste

Image Handling for Normal Directory

lua
vim.pack.add({
  "https://github.com/HakonHarnes/img-clip.nvim",
})

require("img-clip").setup({
  -- priority #5
  default = {
    dir_path = function()
      return vim.fn.expand("%:t:r") .. "-img"
    end,
    extension = "avif", ---@type string
    relative_to_current_file = true, ---@type boolean
    process_cmd = "convert - -quality 75 avif:-", ---@type string
  },
  -- priority #4
  filetypes = {
    markdown = {
      template = "![$FILE_NAME]($FILE_PATH)", ---@type string
    },
  },
  -- priority #3, #2, #1
  -- directory, file, and custom triggered options
  -- dirs = {}, ---@type table | fun(): table
  -- files = {}, ---@type table | fun(): table
  -- custom = {}, ---@type table | fun(): table
})

vim.keymap.set("n", "<leader>pi", "<cmd>PasteImage<cr>", { desc = "Paste image from clipboard" })

Automatic Directory Creation

For general Markdown files outside of the blog project, the configuration uses a dynamic directory naming strategy: dir_path = function() return vim.fn.expand("%:t:r") .. "-img" end

This automatically creates a folder sharing the name of your Markdown file with an -img suffix (e.g., Notes.md will store its images in Notes-img/). This keeps images organized and tightly coupled with their respective documents.

Localized Asset Management

By setting relative_to_current_file = true, images are saved in the same directory as the Markdown file. This "local storage" approach is ideal for general notes or documentation where portability of a single folder (containing both the .md and its -img folder) is the priority.

Format and Quality

To maintain consistency across all environments, even normal directories use the .avif format with a quality setting of 75. This ensures that all images, regardless of where they are stored, benefit from modern compression standards.

Copying an Image

Before you could use the defined keymap <leader>ip to actually paste the image into your Markdown file, how can you get an image copied into the system clipboard in the first place?

Since you are operating primarily within a terminal-centric environment, getting an image into your system clipboard depends on your OS and the specific tools you have installed.

Because img-clip.nvim looks for raw image data (not a file path or a filename) in the clipboard, here are the most common ways to populate it:

1. System Screenshots (Most Common)

This is the fastest way to "copy" an image without saving a file first.

  • macOS: Press Cmd + Ctrl + Shift + 4. This allows you to select an area, and the result is sent directly to the clipboard rather than saved to the Desktop.
  • Windows: Press Win + Shift + S. Use the Snipping Tool to select an area; it is automatically added to your clipboard.
  • Linux (GNOME/KDE): Most modern desktops have a "Print Screen" utility. In GNOME, Ctrl + PrintScreen usually copies the area to the clipboard.

2. Browser Context Menu

If you are researching for your blog and see an image on the web:

  1. Right-click the image in your browser (Chrome, Firefox, etc.).
  2. Select "Copy Image" (do not select "Copy Image Address").
  3. Go back to Neovim and hit <leader>ip.

3. Terminal Utilities (CLI)

Since you are a heavy terminal user, you might want to pipe an existing file into the clipboard so you can "paste" it into a different directory via img-clip.

  • macOS (using pngpaste or pbcopy): While pbcopy is usually for text, you can use utilities to put image data into the clipboard.

  • Linux (using xclip or wl-copy): If you have an existing image file (e.g., diagram.png) and want to put it in the clipboard to use the img-clip processing logic:

    bash
    # For X11
    xclip -selection clipboard -t image/png -i diagram.png
    
    # For Wayland
    wl-copy < diagram.png

4. Direct Graphic Editors

If you are editing an image in a tool like Photoshop, GIMP, or even a simple "Preview" app:

  1. Select all (Cmd/Ctrl + A) or a specific region.
  2. Press Cmd/Ctrl + C.
  3. The raw pixel data is now in your clipboard buffer, ready for img-clip to convert it to .avif and save it to your project folder.

Pro-Tip for your Workflow: Since you are using a conversion command (convert), you don't need to worry about the source format (PNG, JPEG, etc.). As long as it is image data in the clipboard, img-clip will intercept it, run your process_cmd, and save the optimized .avif file.

Choosing Your Conversion Tool

While the configuration above uses ImageMagick's convert, there are other popular tools like cwebp. Here is a brief comparison to help you choose the right tool for your needs:

1. ImageMagick (convert)

  • The Swiss Army Knife: A comprehensive suite for creating, editing, and composing bitmap images. It supports over 200 formats.
  • Why use it? If you need versatility. It can handle conversion to almost any format (AVIF, WebP, PNG, etc.) and offers advanced processing like resizing, color adjustment, and watermarking within the same command.
  • Best for: Users who want a single tool that "just works" for everything.

2. WebP Tools (cwebp)

  • The Specialist: A dedicated command-line utility from Google specifically for encoding images into the WebP format.
  • Why use it? It is extremely fast and highly optimized for WebP. It often yields slightly better compression ratios for WebP files compared to general-purpose tools.
  • Best for: Projects where WebP is the only target format and performance/minimal file size are the absolute priorities.

Summary: Which should I use?

In our current configuration, we use ImageMagick (convert) because it is already a dependency for many system tools and it handles the modern .avif format natively with excellent results. If you primarily target older browsers that only support WebP, cwebp is a great alternative.

Image Handling for Blog Directory

For the VitePress blog directory, a specialized configuration is implemented in .img-clip.lua at the project root. This setup differs from the default behavior to ensure compatibility with VitePress's build system and remote hosting (e.g., Vercel, Tencent EdgeOne).

lua
local year = os.date("%Y")

return {
  -- priority #5
  default = {
    -- VitePress Specific: Centralized storage in public folder
    dir_path = "docs/public/img/" .. year,
    extension = "avif",

    -- Compression: Matches global config (avif @ 75%)
    process_cmd = "convert - -quality 75 avif:-",

    -- Path calculations
    -- VitePress Specific: relative_template_path must be true for build/preview compatibility
    use_absolute_path = false,
    relative_to_current_file = false,
    relative_template_path = true,
  },

  -- priority #4
  filetypes = {
    markdown = {
      -- Matches global config template
      template = "![$FILE_NAME]($FILE_PATH)",
    },
  },
}

Centralized Asset Storage

Instead of saving images relative to each Markdown file, all blog images are centralized in: docs/public/img/YYYY/ (where YYYY is the current year).

This matches VitePress's standard structure for public assets, keeping the content directories clean.

Cross-Environment Compatibility

The configuration uses relative template paths (relative_template_path = true). This is critical for two reasons:

  1. Local Preview: Neovim and local Markdown editors can resolve the image path (e.g., ../../public/img/2026/image.avif) to display the image directly in the buffer or previewer.
  2. VitePress Build: During the docs:build process, VitePress correctly resolves these relative paths and maps them to the final production URLs. This ensures images load correctly regardless of whether the site is accessed via a local dev server or a global CDN.

Automatic Compression

Images are automatically converted to .avif format using ImageMagick's convert command with a quality setting of 75. This matches the global Neovim configuration, providing superior compression and quality for web-ready assets.

最近更新