Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vscode.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Bierner <matb@microsoft.com>2022-06-07 23:58:29 +0300
committerGitHub <noreply@github.com>2022-06-07 23:58:29 +0300
commit9545af80f69becea056b57f1fd846f7e764f018c (patch)
tree45ddc06b4c12864963d616bf4e408e30cdde328f /extensions
parent677d79a4cd2e7091e5bd9882146f67f31d097063 (diff)
Fix markdown link detection for links with titles (#151459)
Fixes #151458
Diffstat (limited to 'extensions')
-rw-r--r--extensions/markdown-language-features/src/languageFeatures/documentLinkProvider.ts4
-rw-r--r--extensions/markdown-language-features/src/test/diagnostic.test.ts52
-rw-r--r--extensions/markdown-language-features/src/test/documentLinkProvider.test.ts19
3 files changed, 62 insertions, 13 deletions
diff --git a/extensions/markdown-language-features/src/languageFeatures/documentLinkProvider.ts b/extensions/markdown-language-features/src/languageFeatures/documentLinkProvider.ts
index 92e0e6d1164..d1457dd3e2a 100644
--- a/extensions/markdown-language-features/src/languageFeatures/documentLinkProvider.ts
+++ b/extensions/markdown-language-features/src/languageFeatures/documentLinkProvider.ts
@@ -185,12 +185,12 @@ function stripAngleBrackets(link: string) {
/**
* Matches `[text](link)`
*/
-const linkPattern = /(\[((!\[[^\]]*?\]\(\s*)([^\s\(\)]+?)\s*\)\]|(?:\\\]|[^\]])*\])\(\s*)(([^\s\(\)]|\([^\s\(\)]*?\))+)\s*(".*?")?\)/g;
+const linkPattern = /(\[((!\[[^\]]*?\]\(\s*)([^\s\(\)]+?)\s*\)\]|(?:\\\]|[^\]])*\])\(\s*)(([^\s\(\)]|\([^\s\(\)]*?\))+)\s*("[^"]*"|'[^']*'|\([^\(\)]*\))?\s*\)/g;
/**
* Matches `[text](<link>)`
*/
-const linkPatternAngle = /(\[((!\[[^\]]*?\]\(\s*)([^\s\(\)]+?)\s*\)\]|(?:\\\]|[^\]])*\])\(\s*<)(([^<>]|\([^\s\(\)]*?\))+)>\s*(".*?")?\)/g;
+const linkPatternAngle = /(\[((!\[[^\]]*?\]\(\s*)([^\s\(\)]+?)\s*\)\]|(?:\\\]|[^\]])*\])\(\s*<)(([^<>]|\([^\s\(\)]*?\))+)>\s*("[^"]*"|'[^']*'|\([^\(\)]*\))?\s*\)/g;
/**
diff --git a/extensions/markdown-language-features/src/test/diagnostic.test.ts b/extensions/markdown-language-features/src/test/diagnostic.test.ts
index 1c6ae3dd6e8..d84a69dd20c 100644
--- a/extensions/markdown-language-features/src/test/diagnostic.test.ts
+++ b/extensions/markdown-language-features/src/test/diagnostic.test.ts
@@ -37,6 +37,14 @@ function createDiagnosticsManager(workspaceContents: MdWorkspaceContents, config
return new DiagnosticManager(new DiagnosticComputer(engine, workspaceContents, linkProvider), configuration);
}
+function assertDiagnosticsEqual(actual: readonly vscode.Diagnostic[], expectedRanges: readonly vscode.Range[]) {
+ assert.strictEqual(actual.length, expectedRanges.length);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assertRangeEqual(actual[i].range, expectedRanges[i], `Range ${i} to be equal`);
+ }
+}
+
class MemoryDiagnosticConfiguration implements DiagnosticConfiguration {
private readonly _onDidChange = new vscode.EventEmitter<void>();
@@ -87,9 +95,10 @@ suite('markdown: Diagnostics', () => {
));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryWorkspaceMarkdownDocuments([doc]));
- assert.deepStrictEqual(diagnostics.length, 2);
- assertRangeEqual(new vscode.Range(0, 6, 0, 22), diagnostics[0].range);
- assertRangeEqual(new vscode.Range(3, 11, 3, 27), diagnostics[1].range);
+ assertDiagnosticsEqual(diagnostics, [
+ new vscode.Range(0, 6, 0, 22),
+ new vscode.Range(3, 11, 3, 27),
+ ]);
});
test('Should generate diagnostics for links to header that does not exist in current file', async () => {
@@ -103,9 +112,10 @@ suite('markdown: Diagnostics', () => {
));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryWorkspaceMarkdownDocuments([doc]));
- assert.deepStrictEqual(diagnostics.length, 2);
- assertRangeEqual(new vscode.Range(2, 6, 2, 21), diagnostics[0].range);
- assertRangeEqual(new vscode.Range(5, 11, 5, 26), diagnostics[1].range);
+ assertDiagnosticsEqual(diagnostics, [
+ new vscode.Range(2, 6, 2, 21),
+ new vscode.Range(5, 11, 5, 26),
+ ]);
});
test('Should generate diagnostics for links to non-existent headers in other files', async () => {
@@ -123,8 +133,9 @@ suite('markdown: Diagnostics', () => {
));
const diagnostics = await getComputedDiagnostics(doc1, new InMemoryWorkspaceMarkdownDocuments([doc1, doc2]));
- assert.deepStrictEqual(diagnostics.length, 1);
- assertRangeEqual(new vscode.Range(5, 6, 5, 35), diagnostics[0].range);
+ assertDiagnosticsEqual(diagnostics, [
+ new vscode.Range(5, 6, 5, 35),
+ ]);
});
test('Should support links both with and without .md file extension', async () => {
@@ -150,8 +161,9 @@ suite('markdown: Diagnostics', () => {
));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryWorkspaceMarkdownDocuments([doc]));
- assert.deepStrictEqual(diagnostics.length, 1);
- assertRangeEqual(new vscode.Range(1, 11, 1, 18), diagnostics[0].range);
+ assertDiagnosticsEqual(diagnostics, [
+ new vscode.Range(1, 11, 1, 18),
+ ]);
});
test('Should not generate diagnostics when validate is disabled', async () => {
@@ -281,4 +293,24 @@ suite('markdown: Diagnostics', () => {
const { diagnostics } = await manager.recomputeDiagnosticState(doc1, noopToken);
assert.deepStrictEqual(diagnostics.length, 0);
});
+
+ test('Should detect invalid links with titles', async () => {
+ const doc = new InMemoryDocument(workspacePath('doc1.md'), joinLines(
+ `[link](<no such.md> "text")`,
+ `[link](<no such.md> 'text')`,
+ `[link](<no such.md> (text))`,
+ `[link](no-such.md "text")`,
+ `[link](no-such.md 'text')`,
+ `[link](no-such.md (text))`,
+ ));
+ const diagnostics = await getComputedDiagnostics(doc, new InMemoryWorkspaceMarkdownDocuments([doc]));
+ assertDiagnosticsEqual(diagnostics, [
+ new vscode.Range(0, 8, 0, 18),
+ new vscode.Range(1, 8, 1, 18),
+ new vscode.Range(2, 8, 2, 18),
+ new vscode.Range(3, 7, 3, 17),
+ new vscode.Range(4, 7, 4, 17),
+ new vscode.Range(5, 7, 5, 17),
+ ]);
+ });
});
diff --git a/extensions/markdown-language-features/src/test/documentLinkProvider.test.ts b/extensions/markdown-language-features/src/test/documentLinkProvider.test.ts
index 29793b2a5d8..37d9330d357 100644
--- a/extensions/markdown-language-features/src/test/documentLinkProvider.test.ts
+++ b/extensions/markdown-language-features/src/test/documentLinkProvider.test.ts
@@ -408,5 +408,22 @@ suite('markdown.DocumentLinkProvider', () => {
assertLinksEqual(links, [new vscode.Range(0, 8, 0, 13)]);
});
-
+ test('Should find links with titles', async () => {
+ const links = await getLinksForFile(joinLines(
+ `[link](<no such.md> "text")`,
+ `[link](<no such.md> 'text')`,
+ `[link](<no such.md> (text))`,
+ `[link](no-such.md "text")`,
+ `[link](no-such.md 'text')`,
+ `[link](no-such.md (text))`,
+ ));
+ assertLinksEqual(links, [
+ new vscode.Range(0, 8, 0, 18),
+ new vscode.Range(1, 8, 1, 18),
+ new vscode.Range(2, 8, 2, 18),
+ new vscode.Range(3, 7, 3, 17),
+ new vscode.Range(4, 7, 4, 17),
+ new vscode.Range(5, 7, 5, 17),
+ ]);
+ });
});