yzhang-gh / vscode-markdown

Markdown All in One
https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one
MIT License
2.91k stars 323 forks source link

Copy/paste that ensures correct relative links #779

Open max92334 opened 4 years ago

max92334 commented 4 years ago

What is the problem?

Copy/paste markdown between files will break relative links (e.g. to images or local files).

While it is easy to capture images and paste them into markdown (e.g. using https://marketplace.visualstudio.com/items?itemName=mushan.vscode-paste-image), there is no easy way to move markdown content between files if both files are in different folders.

This is a serious limitation, as it makes it very difficult to rearrange content, a process that is trivial in any word processor.

How can I reproduce it?

Create a file first.md in folder path/to/file/a/ containing a link to an image.

### This is file path/to/file/a/first.md
![Some Image]("2020-08-09-09-20-21.png")

Then copy and paste the markdown into a file second.md in folder path/to/file/b.

The link in the 2nd file will be broken, as the relative path now points to the wrong folder.

Is there any error message in the console?

No

Solution

We need modified copy/paste commands that either updates relative paths, or copy linked files as well (setting copyLinkedFiles).

Copy should convert every path referenced in the file to an absolute path, i.e. ![Some Image]("path/to/file/a/first.md/2020-08-09-09-20-21.png").

Paste should convert any absolute path to a path relative to the 2nd file. In the case above, this would be ![Some Image]("../a/first.md/2020-08-09-09-20-21.png").

If copyLinkedFiles=true, paste should copy all referenced files under folder a to folder b (potentially preserving subfolders, e.g. if the file is in a folder "images" on a it should be copied to a folder "images" on b as well.

If the first path and the second path reside on different drives, the linked files should be copied by default.

Note: Always using absolute paths is not a solution, as in this case the markdown files can't be moved around freely (e.g. onto a USB or network drive).

yzhang-gh commented 4 years ago

Thanks for the feedback.

However, I'm not sure whether there is any Markdown (or general?) editor doing what you said, which doesn't look like a duty of an editor.

Also, I'm afraid it is not technically feasible for a VSCode extension. We have APIs for text copy/paste, not sure about file copy/paste.

max92334 commented 4 years ago

Thanks for your comments. The relative image paths are really a downside of Markdown, but it should be possible to handle it in the editors in principle. I think other editors (like MarkdownMonster) have a prefix variable for the path to make it work for web applications, but that is not a good solution for the issue either.

I am still learning how extensions work, but I think it is possible to solve this issue in VSCode. If I did not overlook anything, it would be a big improvement in usability and would not break compatibility.

The way to go is to define two new commands CopyMarkdown and PasteMarkdown.

CopyMarkdown will:

  1. Get the full text of the current document
  2. Find all links with relative paths. I am not sure if there is a Markdown API that can go through all links, but regular expression will be good.
  3. Put the path to the active file before all relative path.
  4. Put the modified text into the clipboard with writeText .

PasteMarkdown will:

  1. Get access of the current clipboard by vscode.env.clipboard.readText()
  2. Get the absolute path of current file (paste target)'
  3. Parse the clipboard again.
  4. Replace all absolute paths with paths relative to current directory using path.relative
  5. Files can be copy using copy(source: Uri, target: Uri, options?: {overwrite: boolean}): Thenable<void> and createDirectory(uri: Uri): Thenable<void> https://code.visualstudio.com/api/references/vscode-api#Clipboard

    extension https://github.com/telesoho/vscode-markdown-paste-image pastes images and html into Markdown.

yzhang-gh commented 4 years ago

I would suggest you make a standalone extension. As for this extension, I will leave this issue open to collect more feedback.

max92334 commented 4 years ago

Sounds good. Maybe someone with more experience than me with extensions will comment, I am still learning. Thank you!

Lemmingh commented 4 years ago

It could be possible to check the existence of relative links and show warnings and code actions. Though it's not a direct solution, I still think this can help a lot.

Please also note that there are many corner cases in URIs.

BTW, markdown-it provides a MarkdownIt.parse() method. Then, it might be feasible to build a language server on it to gain more knowledge of a document.

milahu commented 1 year ago

https://github.com/foambubble/foam can Sync links on file rename which works for markdown-links and wikilinks

https://github.com/svsool/memo has Automatic links synchronization on file rename which works only for wikilinks

yzhang-gh commented 1 year ago

As of VS Code 1.73, it natively supports automatic link updates on file rename/move.