From d8bb2b7956cd3d35ebb29220de4a5b2a82ecf139 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sun, 14 Jan 2024 14:55:14 -0300 Subject: [PATCH] Patch incomplete markdown for links that contain a title/argument --- src/vs/base/browser/markdownRenderer.ts | 14 +++++++++++++- .../base/test/browser/markdownRenderer.test.ts | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/vs/base/browser/markdownRenderer.ts b/src/vs/base/browser/markdownRenderer.ts index fa4352fd344..951a60ff113 100644 --- a/src/vs/base/browser/markdownRenderer.ts +++ b/src/vs/base/browser/markdownRenderer.ts @@ -581,7 +581,8 @@ function mergeRawTokenText(tokens: marked.Token[]): string { } function completeSingleLinePattern(token: marked.Tokens.ListItem | marked.Tokens.Paragraph): marked.Token | undefined { - for (const subtoken of token.tokens) { + for (let i = 0; i < token.tokens.length; i++) { + const subtoken = token.tokens[i]; if (subtoken.type === 'text') { const lines = subtoken.raw.split('\n'); const lastLine = lines[lines.length - 1]; @@ -596,6 +597,13 @@ function completeSingleLinePattern(token: marked.Tokens.ListItem | marked.Tokens } else if (lastLine.match(/(^|\s)_\w/)) { return completeUnderscore(token); } else if (lastLine.match(/(^|\s)\[.*\]\(\w*/)) { + const nextTwoSubTokens = token.tokens.slice(i + 1); + if (nextTwoSubTokens[0]?.type === 'link' && nextTwoSubTokens[1]?.type === 'text' && nextTwoSubTokens[1].raw.match(/^ *"[^"]*$/)) { + // A markdown link can look like + // [link text](https://microsoft.com "more text") + // Where "more text" is a title for the link or an argument to a vscode command link + return completeLinkTargetArg(token); + } return completeLinkTarget(token); } else if (lastLine.match(/(^|\s)\[\w/)) { return completeLinkText(token); @@ -693,6 +701,10 @@ function completeLinkTarget(tokens: marked.Token): marked.Token { return completeWithString(tokens, ')'); } +function completeLinkTargetArg(tokens: marked.Token): marked.Token { + return completeWithString(tokens, '")'); +} + function completeLinkText(tokens: marked.Token): marked.Token { return completeWithString(tokens, '](about:blank)'); } diff --git a/src/vs/base/test/browser/markdownRenderer.test.ts b/src/vs/base/test/browser/markdownRenderer.test.ts index 0c02a319432..01803b7434d 100644 --- a/src/vs/base/test/browser/markdownRenderer.test.ts +++ b/src/vs/base/test/browser/markdownRenderer.test.ts @@ -678,6 +678,24 @@ suite('MarkdownRenderer', () => { assert.deepStrictEqual(newTokens, completeTokens); }); + test('incomplete link target 2', () => { + const incomplete = 'foo [text](http://microsoft.com'; + const tokens = marked.lexer(incomplete); + const newTokens = fillInIncompleteTokens(tokens); + + const completeTokens = marked.lexer(incomplete + ')'); + assert.deepStrictEqual(newTokens, completeTokens); + }); + + test('incomplete link target with arg', () => { + const incomplete = 'foo [text](http://microsoft.com "more text here '; + const tokens = marked.lexer(incomplete); + const newTokens = fillInIncompleteTokens(tokens); + + const completeTokens = marked.lexer(incomplete + '")'); + assert.deepStrictEqual(newTokens, completeTokens); + }); + test.skip('incomplete link in list', () => { const incomplete = '- [text'; const tokens = marked.lexer(incomplete);