VSCode New Version (1.79) Supports Pasting Images in Markdown
Tags: vscode, markdown, frontend
Published: 2023-07-19 08:21:34

With the release of VSCode 1.79, a new feature has been introduced that allows direct pasting of images in Markdown documents. This addresses a common issue faced by users when working with Markdown in VSCode, where they couldn't directly add clipboard images to their Markdown documents.

Previously, users had to manually copy the image to their workspace and then add an image reference snippet in the Markdown document, such as `![](relative path to the image in the workspace)`.

To solve this problem, users previously relied on plugins like "Markdown Paste" or "Paste Image". However, with the latest update of VSCode to version 1.79, this functionality is now built-in and no longer requires additional plugins.

This document will focus on the following topics:
1. Introduction to the new feature in VSCode
2. Configuration for using the feature
3. Feature comparison

# Introduction to the New Feature in VSCode

In the VSCode [version 1.79](https://code.visualstudio.com/updates/v1_79) release in May 2023, a new feature called "[Automatic copy of external files](https://code.visualstudio.com/updates/v1_79#_copy-external-media-files-into-workspace-on-drop-or-paste-for-markdown)" was introduced. This feature enables automatic copying of external media files (such as images, audio, and video) into the workspace and inserts the corresponding image reference snippets in Markdown documents when users drag and drop or paste these files onto the Markdown document.

Here is an example of dragging and dropping an image:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u79dejnnqj02hzuuh6hm.png)


Moreover, clipboard images, including system copy or tool screenshots, can also be used. Users can simply paste the image into the Markdown document, and VS Code will create a new image file from the clipboard data and insert a Markdown image link referencing the new file.

By default, the images are stored in the same directory as the Markdown file where the image was pasted, and the inserted Markdown snippet will be as follows (assuming the image name is `image.png`):
```markdown
![Alt text](image.png)
```

In addition to images, this new feature also supports audio and video files, generating Markdown snippets with `<audio>` and `<video>` tags. For simplicity, this document will only cover images.

# Configuration for Using the Feature

In some cases, you may need to adjust the default behavior of this feature, including:
- Customizing the storage directory
- Renaming the files
- Overwriting files with the same name
- Disabling the feature

For the convenience of the configuration examples, let's assume we have a project named "myProject" located at the absolute path `/User/me/myProject`, and the following project structure:
```
--docs
----api
------README.md
--assets
```

## Customizing the Storage Directory

The `markdown.copyFiles.destination` configuration controls the storage directory for image files.

```json
    "markdown.copyFiles.destination": {
        "/docs/api/**/*": "${documentWorkspaceFolder}/docs/images/"
    }
```

This configuration is an object where the keys use the Glob syntax to match the Markdown documents, and the values represent the storage directories for the matched Markdown documents. You can use simple variables within the values.

- `${documentFileName}` - The complete file name of the Markdown document, e.g., `README.md`
- `${documentBaseName}` - The base file name of the Markdown document, e.g., `README`
- `${documentExtName}` - The extension name of the Markdown document, e.g., `md`
- `${documentDirName}` - The parent directory name of the Markdown document, e.g., `api`
- `${documentWorkspaceFolder}` - The workspace path of the Markdown document, e.g., `/Users/me/myProject`. If the Markdown document is not part of the workspace, this value will be the same as `${documentDirName}`
- `${fileName}` - The name of the dragged or pasted image file, e.g., `image.png`

There are two common configurations for storing the images:
1. Creating a new directory at the same level as the current Markdown document
2. Using a fixed directory within the workspace to manage all images

### 1. Same-Level Directory (Assuming it is named "images")

VSCode configuration:
```json
    "markdown.copyFiles.destination": {
        "**/*": "images/"
    }
```

Project structure:
```
--docs
----api
------images
--------image.png
------README.md
```

Markdown insertion:
```markdown
![Alt text](images/image.png)
```

### 2. Fixed Workspace Directory (Assuming it is "`workspace_directory/assets`")

VSCode configuration:
```json
    "markdown.copyFiles.destination": {
        "**/*": "${documentWorkspaceFolder}/assets/"
    }
```

Project structure:
```
--docs
----api
------README.md
--assets
----image.png
```

Markdown insertion:
```markdown
![Alt text](../../assets/image.png)
```

## Renaming Files

The `markdown.copyFiles.destination` configuration field can also be used for renaming images.

When the configuration ends with a "/" character, VSCode treats it as a directory and prepends it to the original file name as the new file path. However, if it doesn't end with a "/", VSCode treats it as the exact file path.

Here is an example configuration:
```json
    "markdown.copyFiles.destination": {
        "**/*": "images/custom-${fileName}"
    }
```

If the original image name is "image.png", the new image name will be "images/custom-image.png".

Currently, the configuration supports regular expression variable replacement syntax similar to [snippet syntax](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax), but with limited functionality and lacking built-in variables and converters. There is an open issue on GitHub regarding timestamp-based renaming, which would require full support for snippet syntax if addressed by the official team.

```json
    "markdown.copyFiles.destination": {
        "/docs/**/*": "images/me.${fileName/(.*)\\.(.*)/$2/}"
    }
```
> If the pasted image is `test.jpg`, the new image path will be `images/me.jpg`.

Therefore, at present, the renaming capability is limited and cannot fulfill more complex encoding transformations and other requirements.

## Overwriting Files with the Same Name

By default, if there is a file with the same name (usually occurs with screenshots, where the image name is always `image.png`), it will not be overwritten. Instead, the image name will be modified by appending a suffix to avoid conflicts.

For example, if there is a duplicate named `image.png`, the new image name will be `image-1.png`.

If you want to overwrite files with the same name, you can configure the `overwriteBehavior` field:

```json
"markdown.copyFiles.overwriteBehavior": "overwrite"
```

## Disabling the Feature

This feature is enabled by default. However, if you find it disruptive, you can configure the `copyIntoWorkspace` field to disable it.

```json
// For drag and drop behavior
"markdown.editor.drop.copyIntoWorkspace": "never"
// For paste behavior
"markdown.editor.filePaste.copyInto

Workspace": "never"
```

# Feature Comparison

Let's compare the built-in capability with the Markdown image paste plugins and summarize the built-in capability.

|  | Basic Capability | Custom Storage Directory | Renaming | Overwriting | Extended Capability | Maintenance |
| --- | --- | --- | --- | --- | --- | --- |
| Built-in | ✅ | ✅ | Limited, supports simple replacement | ✅ Supports automatic suffix addition to avoid conflicts | - Supports pasting audio and video <br/> - Supports drag and drop | Active development |
| [Paste Image](https://marketplace.visualstudio.com/items?itemName=mushan.vscode-paste-image) | ✅ <br/> Note: Paste command is `Ctrl+Alt+V` / `Cmd+Option+V` | ✅ | ✅ <br/> Supports various methods, including automatic and manual | Prompt for overwrite, default behavior uses timestamps to avoid conflicts | - | Discontinued |
| [Markdown Paste](https://marketplace.visualstudio.com/items?itemName=telesoho.vscode-markdown-paste-image) | ✅ <br/> Note: Paste command is `Ctrl+Alt+V` / `Cmd+Option+V` | ✅ | ✅ Same as above | Same as above | - Supports converting HTML content and rich text to Markdown snippets <br/> - Supports inlining base64-encoded images | Continuously maintained, an enhanced version of Paste Image |

> **Basic Capability** refers to the support for pasting images into the workspace and generating the corresponding Markdown syntax snippets.

Overall, the [Markdown Paste](https://marketplace.visualstudio.com/items?itemName=telesoho.vscode-markdown-paste-image) plugin provides the most powerful features, but it requires an additional installation and has different default paste shortcuts compared to the built-in functionality.

# Usage Recommendations

If you don't have specific requirements for renaming, the built-in capability is sufficient.

However, if you wish to automatically rename images, such as using timestamps to replace the original file name, then you can use the [Markdown Paste](https://marketplace.visualstudio.com/items?itemName=telesoho.vscode-markdown-paste-image) plugin. Since the paste shortcuts are different between the two, you can actually use both simultaneously.

> Please consider whether you really need renaming in your regular projects.

However, the built-in capability in VSCode is continuously evolving, and it is expected to eventually fully replace the need for the "Markdown Paste" plugin.

# Conclusion

This article introduced the new image pasting feature in VSCode 1.79, eliminating the need for external plugins to insert images into Markdown documents.

It provided common configurations for using the feature, including customizing the storage directory, renaming files, overwriting files with the same name, and disabling the feature.

Finally, it compared the capabilities of the built-in feature with other plugins and concluded that the built-in functionality is sufficient for most cases, with the [Markdown Paste](https://marketplace.visualstudio.com/items?itemName=telesoho.vscode-markdown-paste-image) plugin offering the most advanced features when needed.