<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: GaHing</title>
    <description>The latest articles on DEV Community by GaHing (@francecil).</description>
    <link>https://dev.to/francecil</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1081344%2F8188871c-e9bc-46dc-9ae9-c03271280a4c.jpeg</url>
      <title>DEV Community: GaHing</title>
      <link>https://dev.to/francecil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/francecil"/>
    <language>en</language>
    <item>
      <title>VSCode New Version (1.79) Supports Pasting Images in Markdown</title>
      <dc:creator>GaHing</dc:creator>
      <pubDate>Wed, 19 Jul 2023 08:21:34 +0000</pubDate>
      <link>https://dev.to/francecil/vscode-new-version-179-supports-pasting-images-in-markdown-1fd2</link>
      <guid>https://dev.to/francecil/vscode-new-version-179-supports-pasting-images-in-markdown-1fd2</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Previously, users had to manually copy the image to their workspace and then add an image reference snippet in the Markdown document, such as &lt;code&gt;![](relative path to the image in the workspace)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;This document will focus on the following topics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduction to the new feature in VSCode&lt;/li&gt;
&lt;li&gt;Configuration for using the feature&lt;/li&gt;
&lt;li&gt;Feature comparison&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Introduction to the New Feature in VSCode
&lt;/h1&gt;

&lt;p&gt;In the VSCode &lt;a href="https://code.visualstudio.com/updates/v1_79" rel="noopener noreferrer"&gt;version 1.79&lt;/a&gt; release in May 2023, a new feature called "&lt;a href="https://code.visualstudio.com/updates/v1_79#_copy-external-media-files-into-workspace-on-drop-or-paste-for-markdown" rel="noopener noreferrer"&gt;Automatic copy of external files&lt;/a&gt;" 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.&lt;/p&gt;

&lt;p&gt;Here is an example of dragging and dropping an image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu79dejnnqj02hzuuh6hm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu79dejnnqj02hzuuh6hm.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;image.png&lt;/code&gt;):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;

&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;Alt text&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;image.png&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="sb"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In addition to images, this new feature also supports audio and video files, generating Markdown snippets with &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; tags. For simplicity, this document will only cover images.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configuration for Using the Feature
&lt;/h1&gt;

&lt;p&gt;In some cases, you may need to adjust the default behavior of this feature, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customizing the storage directory&lt;/li&gt;
&lt;li&gt;Renaming the files&lt;/li&gt;
&lt;li&gt;Overwriting files with the same name&lt;/li&gt;
&lt;li&gt;Disabling the feature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the convenience of the configuration examples, let's assume we have a project named "myProject" located at the absolute path &lt;code&gt;/User/me/myProject&lt;/code&gt;, and the following project structure:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

--docs
----api
------README.md
--assets


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Customizing the Storage Directory
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;markdown.copyFiles.destination&lt;/code&gt; configuration controls the storage directory for image files.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"markdown.copyFiles.destination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"/docs/api/**/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${documentWorkspaceFolder}/docs/images/"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

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

&lt;p&gt;There are two common configurations for storing the images:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creating a new directory at the same level as the current Markdown document&lt;/li&gt;
&lt;li&gt;Using a fixed directory within the workspace to manage all images&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. Same-Level Directory (Assuming it is named "images")
&lt;/h3&gt;

&lt;p&gt;VSCode configuration:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"markdown.copyFiles.destination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"**/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"images/"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Project structure:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

--docs
----api
------images
--------image.png
------README.md


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Markdown insertion:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;

&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;Alt text&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;images/image.png&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="sb"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  2. Fixed Workspace Directory (Assuming it is "&lt;code&gt;workspace_directory/assets&lt;/code&gt;")
&lt;/h3&gt;

&lt;p&gt;VSCode configuration:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"markdown.copyFiles.destination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"**/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${documentWorkspaceFolder}/assets/"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Project structure:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

--docs
----api
------README.md
--assets
----image.png


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Markdown insertion:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;

&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;Alt text&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;../../assets/image.png&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="sb"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Renaming Files
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;markdown.copyFiles.destination&lt;/code&gt; configuration field can also be used for renaming images.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Here is an example configuration:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"markdown.copyFiles.destination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"**/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"images/custom-${fileName}"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If the original image name is "image.png", the new image name will be "images/custom-image.png".&lt;/p&gt;

&lt;p&gt;Currently, the configuration supports regular expression variable replacement syntax similar to &lt;a href="https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax" rel="noopener noreferrer"&gt;snippet syntax&lt;/a&gt;, 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.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"markdown.copyFiles.destination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"/docs/**/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"images/me.${fileName/(.*)&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.(.*)/$2/}"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;If the pasted image is &lt;code&gt;test.jpg&lt;/code&gt;, the new image path will be &lt;code&gt;images/me.jpg&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Therefore, at present, the renaming capability is limited and cannot fulfill more complex encoding transformations and other requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overwriting Files with the Same Name
&lt;/h2&gt;

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

&lt;p&gt;For example, if there is a duplicate named &lt;code&gt;image.png&lt;/code&gt;, the new image name will be &lt;code&gt;image-1.png&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want to overwrite files with the same name, you can configure the &lt;code&gt;overwriteBehavior&lt;/code&gt; field:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"markdown.copyFiles.overwriteBehavior"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"overwrite"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Disabling the Feature&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;This feature is enabled by default. However, if you find it disruptive, you can configure the &lt;code&gt;copyIntoWorkspace&lt;/code&gt; field to disable it.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;For&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;drag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;drop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;behavior&lt;/span&gt;&lt;span class="w"&gt;&lt;br&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"markdown.editor.drop.copyIntoWorkspace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"never"&lt;/span&gt;&lt;span class="w"&gt;&lt;br&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;For&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;paste&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;behavior&lt;/span&gt;&lt;span class="w"&gt;&lt;br&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"markdown.editor.filePaste.copyInto

&lt;p&gt;Workspace"&lt;/p&gt;&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"never"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Feature Comparison&lt;br&gt;
&lt;/h1&gt;

&lt;p&gt;Let's compare the built-in capability with the Markdown image paste plugins and summarize the built-in capability.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Basic Capability&lt;/th&gt;
&lt;th&gt;Custom Storage Directory&lt;/th&gt;
&lt;th&gt;Renaming&lt;/th&gt;
&lt;th&gt;Overwriting&lt;/th&gt;
&lt;th&gt;Extended Capability&lt;/th&gt;
&lt;th&gt;Maintenance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Limited, supports simple replacement&lt;/td&gt;
&lt;td&gt;✅ Supports automatic suffix addition to avoid conflicts&lt;/td&gt;
&lt;td&gt;- Supports pasting audio and video &lt;br&gt; - Supports drag and drop&lt;/td&gt;
&lt;td&gt;Active development&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=mushan.vscode-paste-image" rel="noopener noreferrer"&gt;Paste Image&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;br&gt; Note: Paste command is &lt;code&gt;Ctrl+Alt+V&lt;/code&gt; / &lt;code&gt;Cmd+Option+V&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ &lt;br&gt; Supports various methods, including automatic and manual&lt;/td&gt;
&lt;td&gt;Prompt for overwrite, default behavior uses timestamps to avoid conflicts&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Discontinued&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=telesoho.vscode-markdown-paste-image" rel="noopener noreferrer"&gt;Markdown Paste&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;br&gt; Note: Paste command is &lt;code&gt;Ctrl+Alt+V&lt;/code&gt; / &lt;code&gt;Cmd+Option+V&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ Same as above&lt;/td&gt;
&lt;td&gt;Same as above&lt;/td&gt;
&lt;td&gt;- Supports converting HTML content and rich text to Markdown snippets &lt;br&gt; - Supports inlining base64-encoded images&lt;/td&gt;
&lt;td&gt;Continuously maintained, an enhanced version of Paste Image&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Basic Capability&lt;/strong&gt; refers to the support for pasting images into the workspace and generating the corresponding Markdown syntax snippets.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Overall, the &lt;a href="https://marketplace.visualstudio.com/items?itemName=telesoho.vscode-markdown-paste-image" rel="noopener noreferrer"&gt;Markdown Paste&lt;/a&gt; plugin provides the most powerful features, but it requires an additional installation and has different default paste shortcuts compared to the built-in functionality.&lt;/p&gt;

&lt;h1&gt;
  
  
  Usage Recommendations
&lt;/h1&gt;

&lt;p&gt;If you don't have specific requirements for renaming, the built-in capability is sufficient.&lt;/p&gt;

&lt;p&gt;However, if you wish to automatically rename images, such as using timestamps to replace the original file name, then you can use the &lt;a href="https://marketplace.visualstudio.com/items?itemName=telesoho.vscode-markdown-paste-image" rel="noopener noreferrer"&gt;Markdown Paste&lt;/a&gt; plugin. Since the paste shortcuts are different between the two, you can actually use both simultaneously.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please consider whether you really need renaming in your regular projects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

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

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://marketplace.visualstudio.com/items?itemName=telesoho.vscode-markdown-paste-image" rel="noopener noreferrer"&gt;Markdown Paste&lt;/a&gt; plugin offering the most advanced features when needed.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>markdown</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Lockfile merge conflicts, how to handle it correctly?</title>
      <dc:creator>GaHing</dc:creator>
      <pubDate>Fri, 14 Jul 2023 08:21:17 +0000</pubDate>
      <link>https://dev.to/francecil/lockfile-merge-conflicts-how-to-handle-it-correctly-588b</link>
      <guid>https://dev.to/francecil/lockfile-merge-conflicts-how-to-handle-it-correctly-588b</guid>
      <description>&lt;p&gt;During a frontend development project, a new npm package was added, and conflicts were encountered when merging the lockfile.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lockfile refers to the lock file of package management tools, such as &lt;code&gt;package-lock.json&lt;/code&gt;, &lt;code&gt;yarn.lock&lt;/code&gt;, &lt;code&gt;pnpm-lock.yaml&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Manually resolving conflicts can be highly inefficient and error-prone. Here are several commonly used solutions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Delete the lockfile and reinstall the dependencies later.&lt;/li&gt;
&lt;li&gt;Reset the lockfile to that of one branch and reinstall the dependencies later.&lt;/li&gt;
&lt;li&gt;Run the dependency installation command to leverage the built-in mechanism of the package management tool to resolve lockfile conflicts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Option 1 will result in the loss of lock records and is generally not preferred.&lt;/p&gt;

&lt;p&gt;Are options 2 and 3 feasible? What are the considerations? This article will discuss these questions and provide the &lt;strong&gt;best practices&lt;/strong&gt; at the end.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you prefer to skip the details, you can scroll to the end directly to see the "Best Practices."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before we dive into these questions, let's first understand the situations in which lockfile merge conflicts can occur.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reasons for Lockfile Merge Conflicts
&lt;/h1&gt;

&lt;p&gt;The reason for conflicts during a Git merge is when two branches make modifications to the &lt;strong&gt;same region&lt;/strong&gt; of a &lt;strong&gt;single file&lt;/strong&gt;. If the modifications are in different regions, Git will attempt an automatic merge (auto-merge) to resolve the conflict.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're not familiar with resolving Git merge conflicts, you can refer to the article &lt;a href="https://www.freecodecamp.org/news/resolve-merge-conflicts-in-git-a-practical-guide/" rel="noopener noreferrer"&gt;How to Resolve Merge Conflicts in Git – A Practical Guide with Examples&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp3-juejin.byteimg.com%2Ftos-cn-i-k3u1fbpfcp%2F0a422803436f442eaffe658cb8a81dfa~tplv-k3u1fbpfcp-zoom-1.image" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp3-juejin.byteimg.com%2Ftos-cn-i-k3u1fbpfcp%2F0a422803436f442eaffe658cb8a81dfa~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key to merge conflicts is &lt;strong&gt;changes in the same region&lt;/strong&gt;. Let's take the dependency configuration in &lt;code&gt;package.json&lt;/code&gt; as an example. The first two examples below illustrate a conflicting scenario and a non-conflicting scenario, respectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp3-juejin.byteimg.com%2Ftos-cn-i-k3u1fbpfcp%2F41ad242807f04c49b39322cf42fb9748~tplv-k3u1fbpfcp-zoom-1.image" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp3-juejin.byteimg.com%2Ftos-cn-i-k3u1fbpfcp%2F41ad242807f04c49b39322cf42fb9748~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For lockfiles, changes in the same region typically occur in the following two situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Incompatible merging due to differences in the structure of the lockfile caused by inconsistent versions of the package management tool. To address this issue, it is recommended to maintain consistency in the package management tool's version. You can refer to my other article: &lt;a href="https://juejin.cn/post/7250383386183876645" rel="noopener noreferrer"&gt;Why is it so hard to maintain consistent frontend dependencies? - 掘金&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  Both branches have made changes to the dependency configuration in &lt;code&gt;package.json&lt;/code&gt; and modified the same region in the lockfile.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When does the same region of the lockfile get modified?&lt;/p&gt;

&lt;p&gt;This is a complex issue as different package management tools and their versions have different generation strategies. It is difficult for developers to avoid conflicts by adjusting the writing style of &lt;code&gt;package.json&lt;/code&gt;. Therefore, it is not necessary to focus too much on this aspect. The important thing is to know how to resolve the issue when it occurs.&lt;/p&gt;

&lt;p&gt;Next, we will discuss two commonly used resolution strategies.&lt;/p&gt;

&lt;h1&gt;
  
  
  Analysis of the Solutions: Resetting Branch Lockfile
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Resetting the branch lockfile means restoring the lockfile to the version from the &lt;strong&gt;target branch&lt;/strong&gt; or the &lt;strong&gt;current branch&lt;/strong&gt;, which also means losing some lock records from a branch and may lead to errors. This issue is challenging to resolve completely and can only be mitigated by improving the development process and performing necessary manual reviews.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Resetting the branch lockfile refers to "merging by using the lockfile from the &lt;strong&gt;target branch&lt;/strong&gt; or the &lt;strong&gt;current branch&lt;/strong&gt;" and then re-executing the dependency installation command to update the lockfile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Resetting Solutions
&lt;/h2&gt;

&lt;p&gt;The following three solutions can be used to easily reset the branch lockfile:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ignore the conflict prompt and stash the lockfile changes, then discard those changes, indicating the continuation of the lockfile from the current branch.&lt;/li&gt;
&lt;li&gt;Execute the &lt;code&gt;git checkout --ours "*lock*"&lt;/code&gt; or &lt;code&gt;git checkout --theirs "*lock*"&lt;/code&gt; command to automatically resolve lockfile conflicts based on the &lt;strong&gt;current branch&lt;/strong&gt; or &lt;strong&gt;target branch&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Implement lockfile conflict resolution automation based on Git configuration. This requires two essential steps, both of which are necessary:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;code&gt;.gitattributes&lt;/code&gt; file to configure the merge strategy. Example:
```
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;# .gitattributes&lt;br&gt;
  # When there's a conflict in pnpm-lock.yaml, use the lockfile from the current branch&lt;br&gt;
  pnpm-lock.yaml merge=ours&lt;/p&gt;


&lt;/li&gt;

&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   2. Execute the `git config merge.ours.driver true` command to enable the merge driver configuration (if using the `theirs` merge strategy, the command should be changed to `merge.theirs.driver`).
   3. Reference documentation:
      1. [Have Git Select Local Version On Merge Conflict on a Specific File?](http://stackoverflow.com/a/930495/958481)
      2. [Merge Strategies](https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes#Merge-Strategies:~:text=further%20development%20work.-,Merge%20Strategies,-You%20can%20also)

## Existing Issues

Regardless of whether the lockfile is reset based on the **current branch** or the **target branch** and the subsequent update of dependencies, it **means losing some lock records and may lead to errors**.

Here's an example encountered in a real business scenario:

![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/311d530bcede45dbafaa0e09f3db8735~tplv-k3u1fbpfcp-watermark.image?)

1. From the main branch, create a development branch called `feat1` with a new dependency `A^1.0.0`, and the installed version is `1.0.0`.
2. During the development of `feat1`, another development branch, `feat2`, is merged into the main branch and adds a dependency `B^2.0.0`, with the installed version being `2.0.0`.
3. After completing the development in `feat1` and preparing to merge it into the main branch, a lockfile conflict is discovered.
4. Using the aforementioned **"Resetting Branch Lockfile"** solution, the dependencies are reinstalled.
5. At this time, the community releases versions `A@1.0.1` and `B@2.0.1` with *`BREAKING CHANGE`*. Since the **"Resetting Branch Lockfile"** solution ignores lock records added by `feat1` or the main branch (`feat2`), it installs the newer versions `A@1.0.1` or `B@2.0.1`.
6. `feat1` is directly merged into the main branch, causing errors in the production code.

## Solution

Some people may suggest **using fixed versions when installing dependencies** instead of using version ranges. For example, using `"A": "1.0.0"` and `"B": "2.0.0"` as dependencies instead of using version range notation (`^`).

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;{&lt;br&gt;
    "dependencies": {&lt;br&gt;
      "A": "1.0.0",&lt;br&gt;
      "B": "2.0.0",&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Firstly, for **application projects**, using fixed versions is feasible. However, for **library projects**, it is not recommended to use fixed versions for the following reasons:

- The dependencies of the library project cannot be efficiently reused by dependent application projects (e.g., `^1.0.0` and `^1.1.0` can be merged into `^1.1.0`).
- In the event of security vulnerabilities in the **indirect dependencies** of the library project, they cannot be directly fixed by reinstalling the dependencies.

Furthermore, locking the versions of direct dependencies is not a complete solution as losing the lockfile can still lead to the automatic upgrade of indirectly dependent dependencies, which can result in *`BREAKING CHANGE`*.

Therefore, once this solution is chosen, either **trust that other dependencies will not have issues (leave it to chance)** or perform **necessary manual lockfile reviews** and ensure it through **a well-defined development process**.

- **Well-defined development process**: During the development stage, promptly merge or rebase code from the main branch, resolve conflicts ahead of time rather than waiting until just before testing and deployment. Before merging after testing, if code conflicts are found, resolve them and retest the relevant code to ensure it works as expected (if project importance and manpower allow).
- **Necessary manual lockfile reviews**: Focus only on changes to **direct dependencies** (e.g., the `specifier` and `version` sections in the `pnpm-lock.yaml` file). It is less likely to encounter automatic upgrade errors for **indirect dependencies** introduced by direct dependencies (since multiple projects would be affected if errors occurred) and the review cost would be too high. Trusting the community or performing "change testing" is a viable option.

## Summary of Solutions

1. Resetting the branch lockfile means restoring the lockfile to the version from the **target branch** or the **current branch**.
2. There are three solutions available to facilitate the resetting of the branch lockfile.
3. Resetting the branch lockfile leads to the loss of lock records from one branch, which can result in errors.
4. Locking the versions of direct dependencies is not the ultimate solution and can lead to other issues.
5. Rely on a well-defined development process, perform conflict testing promptly, and conduct sufficient manual reviews.

# Analysis of the Solution: Package Manager's Built-in Mechanism

&amp;gt; **TL;DR**: The conflicting lockfile can be resolved by parsing the conflicting file into different versions of lock objects and then merging those lock objects. Each package manager has its own merge strategy, with pnpm being the most effective overall. However, regardless of the approach, some data will be lost, and it cannot guarantee 100% error-free merging.

When a lockfile merge conflict occurs, the mainstream package managers support running dependency installation commands (`npm install/yarn/pnpm install`) to automatically resolve the conflict.

-   npm: [Resolving lockfile conflicts](https://docs.npmjs.com/cli/v6/configuring-npm/package-locks#resolving-lockfile-conflicts), supported from v5.7 onwards
-   yarn: [Auto-merging of lockfiles](https://engineering.fb.com/2017/09/07/web/announcing-yarn-1-0/#:~:text=Auto%2Dmerging%20of%20lockfiles), supported from v1.0 onwards
-   pnpm: [Merge conflicts](https://pnpm.io/git#merge-conflicts), supported from v5.11 onwards

&amp;gt; It can be assumed that most users are using versions of the package managers that support this feature.

So, how do these package managers resolve conflicts?

## npm's Conflict Resolution Strategy

I have analyzed this issue in another article, "[A Discussion on the Algorithm for Resolving Merge Conflicts in package-lock.json](https://juejin.cn/post/7251895470548697143)".

In general, the strategy is to **base the resolution on the target branch (`theirs`) and apply the changes from the current branch (`ours`)**.

For example, when merging a `development branch` into the `main branch` (`git merge feat-branch`), `theirs` refers to the `development branch`, and `ours` refers to the `main branch`. In this case, the lock records will be based on the `development branch` and the changes from the `main branch` will be applied.

In other words, **if both branches update the version of the same module, the version from the main branch (`ours`) will be used, which may lead to errors in rare cases**.

The suggested solution in the article is to reduce the impact through processes and retesting, as explained later.

## yarn's Conflict Resolution Strategy

The PR for [Auto detect and merge lockfile conflicts](https://github.com/yarnpkg/yarn/pull/3544) provides insight into the latest implementation in [/src/lockfile/parse.js](https://github.com/yarnpkg/yarn/blob/master/src/lockfile/parse.js#L334).

In fact, understanding just one line of code is sufficient:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Object.assign({}, parse(variants[0], fileLoc), parse(variants[1], fileLoc));&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
This **shallow merge** combines the YAML objects from both branches, and when the same property exists in both objects, the value from the target branch (`theirs`) will be used.

In other words, when conflicting versions of the same dependency are encountered, **the version from the target branch is used**. This is the opposite of npm's strategy, but the issues and solutions are similar.

## pnpm's Conflict Resolution Strategy

The conflict resolution algorithm for pnpm is maintained by the [@pnpm/merge-lockfile-changes](https://github.com/pnpm/pnpm/tree/main/lockfile/merge-lockfile-changes) project.

The implementation involves breaking down the conflicting parts into the contents from the target branch (`theirs`) and the current branch (`ours`), and then merging them. However, unlike yarn's straightforward shallow merge, pnpm performs a **deep merge** (the lockfile structure only has two levels) and selects the version with the higher version number when there is a version conflict.

Here's a demo test:

```js


const { mergeLockfileChanges } = require("@pnpm/merge-lockfile-changes");
const simpleLockfile = {
  importers: {},
  lockfileVersion: 5.2,
};
const mergedLockfile = mergeLockfileChanges(
  {
    ...simpleLockfile,
    packages: {
      ".": {
        version: "1.1.0",
        dependencies: {
          foo: "1.2.0",
          bar: "3.0.0_qar@1.0.0",
          zoo: "4.0.0_qar@1.0.0",
          ktv: "5.0.0"
        },
      },
    },
  },
  {
    ...simpleLockfile,
    packages: {
      ".": {
        version: "1.2.0",
        dependencies: {
          foo: "1.1.0",
          bar: "4.0.0_qar@1.0.0",
          zoo: "3.0.0_qar@1.0.0",
          pua: "5.0.0"
        },
      },
    },
  }
);
console.log(JSON.stringify(mergedLockfile, null, 2));


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The output will be:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;importers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lockfileVersion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;5.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;packages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.2.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dependencies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.2.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;4.0.0_qar@1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zoo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;4.0.0_qar@1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ktv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pua&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In pnpm's strategy, the &lt;strong&gt;updated version&lt;/strong&gt; is chosen. If there is a problem, it implies that the new version has introduced a &lt;code&gt;BREAKING CHANGE&lt;/code&gt;. However, the probability of encountering this issue is lower compared to selecting an older version and facing a &lt;code&gt;BREAKING CHANGE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Currently, the pnpm team is continuously improving the lockfile solution to reduce conflicts, including:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using different lock files for different branches: &lt;a href="https://github.com/pnpm/pnpm/pull/4475" rel="noopener noreferrer"&gt;https://github.com/pnpm/pnpm/pull/4475&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Changing the lockfile format to reduce the number of conflicts: &lt;a href="https://github.com/pnpm/rfcs/pull/1" rel="noopener noreferrer"&gt;https://github.com/pnpm/rfcs/pull/1&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Additionally, pnpm provides a &lt;a href="https://pnpm.io/npmrc#resolution-mode" rel="noopener noreferrer"&gt;resolution-mode&lt;/a&gt; configuration where users can decide the dependency version selection strategy during installation: lowest (default), highest, or time-based (related to the last direct dependency).&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary of the Solutions
&lt;/h2&gt;

&lt;p&gt;All three solutions involve merging the lockfile, but they have different merge strategies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;npm&lt;/strong&gt;: Deep merge based on the current branch (&lt;code&gt;ours&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;yarn&lt;/strong&gt;: Shallow merge based on the target branch (&lt;code&gt;theirs&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;pnpm&lt;/strong&gt;: Deep merge based on the version number, selecting the higher version.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pnpm solution has the smallest probability of encountering issues, but it is not without its potential problems, as stated in the &lt;a href="https://pnpm.io/git#%E5%90%88%E5%B9%B6%E5%86%B2%E7%AA%81" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is recommended to inspect the changes before submitting, as we can't guarantee that pnpm will choose the correct head—it builds most of the updated lockfile, which is ideal in most cases.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In conclusion, while the pnpm solution has the lowest probability of encountering issues, it is not guaranteed to be error-free. As shown in the diagram above, some issues may still arise.&lt;/p&gt;

&lt;h1&gt;
  
  
  Best Practices
&lt;/h1&gt;

&lt;p&gt;The built-in mechanisms provided by package managers result in fewer lost lockfile records and fewer issues compared to the approach of resetting the branch's lockfile. Based on the analysis above, we can summarize the best practices as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Avoid manually resolving conflicts as it can lead to syntax errors.&lt;/li&gt;
&lt;li&gt;Utilize the conflict resolution mechanisms provided by the package manager whenever possible.&lt;/li&gt;
&lt;li&gt;If you have the flexibility to choose a package manager, consider using &lt;code&gt;pnpm&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Additionally, it's important to note that while the package manager solutions are generally effective, extreme scenarios may still result in issues. If the project is of significant value, it is recommended to perform manual reviews and conduct regression testing. You can refer to the "Analysis of the Solution: Resetting Branch Lockfile" section for specific guidelines on how to approach these situations.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This article provided a comprehensive analysis of common approaches to resolving lockfile conflicts and presented the best practices. It is essential to broaden our perspectives and elevate our understanding of best practices at the software level, which can then be shared with the community.&lt;/p&gt;




&lt;p&gt;Finally, if you found this article helpful, please consider giving it a thumbs up, bookmarking it, and sharing it with others. 🍻&lt;/p&gt;

&lt;h1&gt;
  
  
  Further Reading
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://7tonshark.com/posts/avoid-conflicts-in-pnpm-lock/" rel="noopener noreferrer"&gt;Avoid lockfile conflicts in Rush&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://juejin.cn/post/6953948250671939591" rel="noopener noreferrer"&gt;Thoughts on a yarn.lock conflict&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>npm</category>
      <category>git</category>
      <category>frontend</category>
      <category>pnpm</category>
    </item>
  </channel>
</rss>
