Enable angle bracket path completions in markdown (#153158)

Fixes #152510
This commit is contained in:
Matt Bierner 2022-06-24 15:04:40 -07:00 committed by GitHub
parent 6ee7176751
commit 7fd834b64f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 4 deletions

View file

@ -66,6 +66,11 @@ interface CompletionContext {
* Info if the link looks like it is for an anchor: `[](#header)`
*/
readonly anchorInfo?: AnchorContext;
/**
* Indicates that the completion does not require encoding.
*/
readonly skipEncoding?: boolean;
}
function tryDecodeUriComponent(str: string): string {
@ -150,7 +155,7 @@ export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProv
}
/// [...](...|
private readonly linkStartPattern = /\[([^\]]*?)\]\(\s*([^\s\(\)]*)$/;
private readonly linkStartPattern = /\[([^\]]*?)\]\(\s*(<[^\>\)]*|[^\s\(\)]*)$/;
/// [...][...|
private readonly referenceLinkStartPattern = /\[([^\]]*?)\]\[\s*([^\s\(\)]*)$/;
@ -166,18 +171,20 @@ export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProv
const linkPrefixMatch = linePrefixText.match(this.linkStartPattern);
if (linkPrefixMatch) {
const prefix = linkPrefixMatch[2];
const isAngleBracketLink = linkPrefixMatch[2].startsWith('<');
const prefix = linkPrefixMatch[2].slice(isAngleBracketLink ? 1 : 0);
if (this.refLooksLikeUrl(prefix)) {
return undefined;
}
const suffix = lineSuffixText.match(/^[^\)\s]*/);
const suffix = lineSuffixText.match(/^[^\)\s][^\)\s\>]*/);
return {
kind: CompletionContextKind.Link,
linkPrefix: tryDecodeUriComponent(prefix),
linkTextStartPosition: position.translate({ characterDelta: -prefix.length }),
linkSuffix: suffix ? suffix[0] : '',
anchorInfo: this.getAnchorContext(prefix),
skipEncoding: isAngleBracketLink,
};
}
@ -293,7 +300,7 @@ export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProv
const isDir = type === vscode.FileType.Directory;
yield {
label: isDir ? name + '/' : name,
insertText: isDir ? encodeURIComponent(name) + '/' : encodeURIComponent(name),
insertText: (context.skipEncoding ? name : encodeURIComponent(name)) + (isDir ? '/' : ''),
kind: isDir ? vscode.CompletionItemKind.Folder : vscode.CompletionItemKind.File,
range: {
inserting: insertRange,

View file

@ -156,6 +156,31 @@ suite('Markdown path completion provider', () => {
assert.ok(completions.some(x => x.insertText === 'file%20with%20space.md'), 'Has encoded path completion');
});
test('Should support completions on angle bracket path with spaces', async () => {
const completions = await getCompletionsAtCursor(workspacePath('new.md'), joinLines(
`[](</sub with space/${CURSOR}`
));
assert.ok(completions.some(x => x.insertText === 'file.md'), 'Has path completion');
});
test('Should not escape spaces in path names that use angle brackets', async () => {
{
const completions = await getCompletionsAtCursor(workspacePath('new.md'), joinLines(
`[](<./sub/${CURSOR}`
));
assert.ok(completions.some(x => x.insertText === 'file with space.md'), 'Has encoded path completion');
}
{
const completions = await getCompletionsAtCursor(workspacePath('new.md'), joinLines(
`[](<./sub/${CURSOR}>`
));
assert.ok(completions.some(x => x.insertText === 'file with space.md'), 'Has encoded path completion');
}
});
test('Should complete paths for path with encoded spaces', async () => {
const completions = await getCompletionsAtCursor(workspacePath('new.md'), joinLines(
`[](./sub%20with%20space/${CURSOR})`