Skip to content

Commit 4be04d5

Browse files
authored
Fix file uri markdown link pasting (microsoft#203377)
Fixes microsoft#203180 Enables this feature for uris without authorities and also makes sure these uris are not rewritten to relative paths
1 parent 053610e commit 4be04d5

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import * as vscode from 'vscode';
77
import { IMdParser } from '../../markdownEngine';
88
import { ITextDocument } from '../../types/textDocument';
99
import { Mime } from '../../util/mimes';
10-
import { createInsertUriListEdit } from './shared';
1110
import { Schemes } from '../../util/schemes';
11+
import { createInsertUriListEdit } from './shared';
1212

1313
export enum PasteUrlAsMarkdownLink {
1414
Always = 'always',
@@ -59,7 +59,7 @@ class PasteUrlEditProvider implements vscode.DocumentPasteEditProvider {
5959
return;
6060
}
6161

62-
const edit = createInsertUriListEdit(document, ranges, uriText);
62+
const edit = createInsertUriListEdit(document, ranges, uriText, { preserveAbsoluteUris: true });
6363
if (!edit) {
6464
return;
6565
}
@@ -212,8 +212,10 @@ const externalUriSchemes: ReadonlySet<string> = new Set([
212212
export function findValidUriInText(text: string): string | undefined {
213213
const trimmedUrlList = text.trim();
214214

215-
// Uri must consist of a single sequence of characters without spaces
216-
if (!/^\S+$/.test(trimmedUrlList)) {
215+
if (
216+
!/^\S+$/.test(trimmedUrlList) // Uri must consist of a single sequence of characters without spaces
217+
|| !trimmedUrlList.includes(':') // And it must have colon somewhere for the scheme. We will verify the schema again later
218+
) {
217219
return;
218220
}
219221

@@ -225,7 +227,21 @@ export function findValidUriInText(text: string): string | undefined {
225227
return;
226228
}
227229

228-
if (!externalUriSchemes.has(uri.scheme.toLowerCase()) || uri.authority.length <= 1) {
230+
// `Uri.parse` is lenient and will return a `file:` uri even for non-uri text such as `abc`
231+
// Make sure that the resolved scheme starts the original text
232+
if (!trimmedUrlList.toLowerCase().startsWith(uri.scheme.toLowerCase() + ':')) {
233+
return;
234+
}
235+
236+
// Only enable for an allow list of schemes. Otherwise this can be accidentally activated for non-uri text
237+
// such as `c:\abc` or `value:foo`
238+
if (!externalUriSchemes.has(uri.scheme.toLowerCase())) {
239+
return;
240+
}
241+
242+
// Some part of the uri must not be empty
243+
// This disables the feature for text such as `http:`
244+
if (!uri.authority && uri.path.length < 2 && !uri.query && !uri.fragment) {
229245
return;
230246
}
231247

extensions/markdown-language-features/src/languageFeatures/copyFiles/shared.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export function createInsertUriListEdit(
6969
document: ITextDocument,
7070
ranges: readonly vscode.Range[],
7171
urlList: string,
72+
options?: UriListSnippetOptions,
7273
): { edits: vscode.SnippetTextEdit[]; label: string } | undefined {
7374
if (!ranges.length) {
7475
return;
@@ -103,6 +104,7 @@ export function createInsertUriListEdit(
103104
const snippet = createUriListSnippet(document.uri, entries, {
104105
placeholderText: range.isEmpty ? undefined : document.getText(range),
105106
placeholderStartIndex: allRangesAreEmpty ? 1 : placeHolderStartIndex,
107+
...options,
106108
});
107109
if (!snippet) {
108110
continue;
@@ -134,6 +136,13 @@ interface UriListSnippetOptions {
134136
readonly insertAsMedia?: boolean;
135137

136138
readonly separator?: string;
139+
140+
/**
141+
* Prevents uris from being made relative to the document.
142+
*
143+
* This is mostly useful for `file:` uris.
144+
*/
145+
readonly preserveAbsoluteUris?: boolean;
137146
}
138147

139148

@@ -168,7 +177,7 @@ export function createUriListSnippet(
168177
let placeholderIndex = options?.placeholderStartIndex ?? 1;
169178

170179
uris.forEach((uri, i) => {
171-
const mdPath = getRelativeMdPath(documentDir, uri.uri) ?? uri.str ?? uri.uri.toString();
180+
const mdPath = (!options?.preserveAbsoluteUris ? getRelativeMdPath(documentDir, uri.uri) : undefined) ?? uri.str ?? uri.uri.toString();
172181

173182
const ext = URI.Utils.extname(uri.uri).toLowerCase().replace('.', '');
174183
const insertAsMedia = options?.insertAsMedia || (typeof options?.insertAsMedia === 'undefined' && mediaFileExtensions.has(ext));

0 commit comments

Comments
 (0)