diff --git a/extensions/markdown-language-features/src/features/documentLinkProvider.ts b/extensions/markdown-language-features/src/features/documentLinkProvider.ts index 47ddd25d053..75d843c0ea1 100644 --- a/extensions/markdown-language-features/src/features/documentLinkProvider.ts +++ b/extensions/markdown-language-features/src/features/documentLinkProvider.ts @@ -3,34 +3,38 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; import * as path from 'path'; +import * as vscode from 'vscode'; import { OpenDocumentLinkCommand } from '../commands/openDocumentLink'; +import { getUriForLinkWithKnownExternalScheme } from '../util/links'; function normalizeLink( document: vscode.TextDocument, link: string, base: string ): vscode.Uri { - const uri = vscode.Uri.parse(link); - if (uri.scheme) { - return uri; + const externalSchemeUri = getUriForLinkWithKnownExternalScheme(link); + if (externalSchemeUri) { + return externalSchemeUri; } - // assume it must be a file - let resourcePath = uri.path; - if (!uri.path) { + // Assume it must be an relative or absolute file path + // Use a fake scheme to avoid parse warnings + const tempUri = vscode.Uri.parse(`fake-scheme:${link}`); + + let resourcePath = tempUri.path; + if (!tempUri.path) { resourcePath = document.uri.path; - } else if (uri.path[0] === '/') { + } else if (tempUri.path[0] === '/') { const root = vscode.workspace.getWorkspaceFolder(document.uri); if (root) { - resourcePath = path.join(root.uri.fsPath, uri.path); + resourcePath = path.join(root.uri.fsPath, tempUri.path); } } else { - resourcePath = path.join(base, uri.path); + resourcePath = path.join(base, tempUri.path); } - return OpenDocumentLinkCommand.createCommandUri(resourcePath, uri.fragment); + return OpenDocumentLinkCommand.createCommandUri(resourcePath, tempUri.fragment); } function matchAll( diff --git a/extensions/markdown-language-features/src/markdownEngine.ts b/extensions/markdown-language-features/src/markdownEngine.ts index bc67e0bee18..8a1ef1f3115 100644 --- a/extensions/markdown-language-features/src/markdownEngine.ts +++ b/extensions/markdown-language-features/src/markdownEngine.ts @@ -8,6 +8,7 @@ import * as path from 'path'; import * as vscode from 'vscode'; import { MarkdownContributions } from './markdownExtensions'; import { Slugifier } from './slugify'; +import { getUriForLinkWithKnownExternalScheme } from './util/links'; const FrontMatterRegex = /^---\s*[^]*?(-{3}|\.{3})\s*/; @@ -146,8 +147,17 @@ export class MarkdownEngine { const normalizeLink = md.normalizeLink; md.normalizeLink = (link: string) => { try { - let uri = vscode.Uri.parse(link); - if (!uri.scheme && uri.path) { + const externalSchemeUri = getUriForLinkWithKnownExternalScheme(link); + if (externalSchemeUri) { + return normalizeLink(externalSchemeUri.toString()); + } + + + // Assume it must be an relative or absolute file path + // Use a fake scheme to avoid parse warnings + let uri = vscode.Uri.parse(`fake-scheme:${link}`); + + if (uri.path) { // Assume it must be a file const fragment = uri.fragment; if (uri.path[0] === '/') { @@ -165,7 +175,7 @@ export class MarkdownEngine { }); } return normalizeLink(uri.with({ scheme: 'vscode-resource' }).toString(true)); - } else if (!uri.scheme && !uri.path && uri.fragment) { + } else if (!uri.path && uri.fragment) { return normalizeLink(uri.with({ fragment: this.slugifier.fromHeading(uri.fragment).value }).toString(true)); diff --git a/extensions/markdown-language-features/src/util/links.ts b/extensions/markdown-language-features/src/util/links.ts new file mode 100644 index 00000000000..e1fc274d092 --- /dev/null +++ b/extensions/markdown-language-features/src/util/links.ts @@ -0,0 +1,18 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; + +const knownSchemes = ['http:', 'https:', 'file:', 'mailto:']; + +export function getUriForLinkWithKnownExternalScheme( + link: string, +): vscode.Uri | undefined { + if (knownSchemes.some(knownScheme => link.toLowerCase().startsWith(knownScheme))) { + return vscode.Uri.parse(link); + } + + return undefined; +} \ No newline at end of file