A Neovim plugin to paste clipboard images into markdown and MDX files by saving and inserting image links automatically.
- Paste images directly from a clipboard full path or raw data using the
:PasteImage [filename]command.- If
filenameis provided, it's used as the image's filename (stem) and alt text. - If omitted, a random filename is generated.
- If
- Supports OS-standard clipboard tools:
- macOS:
pbpasteandosascript - Linux:
wl-pasteorxclip - Windows: PowerShell (
Get-Clipboard) (untested)
- macOS:
- Automatically expands shell variables like
~and$HOMEin path configurations. - Flexible image saving locations:
- Default path settings (
DefaultPastePath,DefaultPastePathType). - Project-specific overrides (
ProjectOverrides) based on project name or full path, which can also overridecustomImportsandcustomTextFormat.
- Default path settings (
- Automatic insertion of custom import statements (
customImports). - Customizable image reference text format (
customTextFormat).
- Neovim (0.10+ recommended)
- A command-line clipboard tool for your OS (see Features list).
- Using
packer.nvim
use {
'HidemaruOwO/mdxsnap.nvim',
config = function()
require('mdxsnap').setup()
end
}- Using
lazy.nvim
{
'HidemaruOwO/mdxsnap.nvim',
config = function()
require('mdxsnap').setup()
end
}- Open an MDX/Markdown file.
- Copy the full absolute path of an image file to your system clipboard.
- In Neovim (normal mode), run:
:PasteImage
- With file name
:PasteImage [filename]
- The plugin will:
- Copy the image to the configured directory (e.g.,
project_root/snaps/images/posts/your_doc_name/random_img.png). - Add necessary import statements (if configured via
customImports). - Insert an image reference at your cursor (formatted by
customTextFormat). - Show a success notification.
- Copy the image to the configured directory (e.g.,
Configure mdxsnap.nvim by calling the setup function. Here's an example with explanations:
-- In your Neovim configuration (e.g., init.lua or a dedicated plugins file)
require("mdxsnap").setup({
-- Default path for saving images.
-- If DefaultPastePathType is "relative", this is relative to the project root.
-- If "absolute", this is used as an absolute path.
DefaultPastePath = "snaps/images/posts", -- Default: "snaps/images/posts"
DefaultPastePathType = "relative", -- Default: "relative" ("absolute" is also an option)
-- Global custom import statements to ensure are present in the file (can be overridden by ProjectOverrides).
-- The plugin checks if an import matching `checkRegex` exists before adding `line`.
customImports = {
{
line = 'import { Image } from "astro:assets";', -- The full import line
checkRegex = 'astro:assets', -- A string/regex to check for existing import
},
-- Example:
-- { line = 'import MyCustomImage from "@/components/MyCustomImage.astro";', checkRegex = '@/components/MyCustomImage.astro' },
},
-- Global format for the inserted image reference text (can be overridden by ProjectOverrides).
-- `%s` is a placeholder.
-- - If one `%s`: it's replaced by the image path.
-- - If two `%s`: the first is replaced by alt text (filename stem of the new image, or the name provided to :PasteImage),
-- and the second by the image path.
customTextFormat = "", -- Default: Markdown image format ""
-- Example for Astro <Image /> component:
-- customTextFormat = '<Image alt="%s" src={"%s"} />',
-- Example for a simple <img> tag:
-- customTextFormat = '<img alt="%s" src="%s" />',
-- Override default settings for specific projects.
-- Rules are evaluated in order; the first match is used.
ProjectOverrides = {
-- Example 1: Match by project directory name
{
matchType = "projectName", -- "projectName" or "projectPath"
matchValue = "my-astro-blog", -- The name of the project's root directory
PastePath = "src/assets/blog-images", -- Custom path for this project
PastePathType = "relative",
customImports = { -- Override global customImports for this project
{ line = 'import { BlogImage } from "@/components/BlogImage.astro";', checkRegex = "@/components/BlogImage.astro" },
},
customTextFormat = '<BlogImage alt="%s" src="%s" />', -- Override global customTextFormat
},
-- Example 2: Match by project's absolute path (supports ~ and $HOME)
{
matchType = "projectPath",
matchValue = "~/dev/personal-website",
PastePath = "src/content/assets/images",
PastePathType = "absolute",
customTextFormat = "", -- Add a title to markdown images
},
-- Add more rules as needed
},
})Key Configuration Options:
DefaultPastePath(string): Default directory for saving images. Initial default is"snaps/images/posts".DefaultPastePathType(string): HowDefaultPastePathis interpreted. Can be"relative"(to project root) or"absolute". Initial default is"relative".ProjectOverrides(table of tables): A list of rules to override default settings for specific projects.matchType(string):"projectName"(matches the project root's directory name) or"projectPath"(matches the project root's absolute path, supports~,$HOME).matchValue(string): The value to match against (e.g., "my-blog", "~/dev/project-x").PastePath(string): The path to use if this rule matches.PastePathType(string): The type ("relative"or"absolute") for this rule'sPastePath.customImports(optional, table of tables): Overrides the globalcustomImportsfor this project.customTextFormat(optional, string): Overrides the globalcustomTextFormatfor this project.
customImports(table of tables): Global list of import statements to automatically add if not present. Can be overridden byProjectOverrides.line(string): The full import statement.checkRegex(string): A string or Lua pattern to check if a similar import already exists.
customTextFormat(string): Global format string for the text inserted into the document. Can be overridden byProjectOverrides.
Remember to restart Neovim or re-source your configuration after making changes.
For Zenn CLI projects:
{
matchType = "projectName",
matchValue = "zenn-articles", -- Replace with your actual repository name
PastePath = "images",
PastePathType = "relative",
},This automatically saves images to the images directory when working on your Zenn articles.
- Directory structure
.
βββ articles
βΒ Β βββ introduce-mdxsnapnvim.md
βββ books
βββ images
βΒ Β βββ introduce-mdxsnapnvim
βΒ Β βββ github.png
βΒ Β βββ neovim.png
βΒ Β βββ running-command.png
βΒ Β βββ zenn-setting.png
βββ README.md
βββ bun.lock
βββ package.json
By contributing to this project, you agree to the following terms:
- You grant a license: You grant the project owner a perpetual, worldwide, non-exclusive, royalty-free, irrevocable license to use, modify, distribute, and sublicense your contributions under the Apache License 2.0.
- You retain ownership: You still own the copyright of your contribution, but you waive any claims against the project related to your contribution.
- No additional patent rights: You do not grant additional patent rights beyond what is covered by Apache 2.0.
- Your contributions are original: You confirm that your contributions do not violate any third-party rights.
By submitting a pull request, you agree to these terms.
This project is dual-licensed under Apache License 2.0 and SUSHI-WARE LICENSE.
A reference to the latest license should be used, even if the attached license is outdated of major versions.
This repository was created using the MicroRepository template.

