mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-20 08:38:56 +01:00
Split markdown linkComputer from linkProvider (#152124)
Instead of passing around a full `vscode.DocumentLinkProvider`, we should pass just the more minimal interface that consumers need
This commit is contained in:
@@ -242,53 +242,12 @@ class NoLinkRanges {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class MdLinkProvider implements vscode.DocumentLinkProvider {
|
||||
export class MdLinkComputer {
|
||||
|
||||
constructor(
|
||||
private readonly engine: MarkdownEngine
|
||||
) { }
|
||||
|
||||
public async provideDocumentLinks(
|
||||
document: SkinnyTextDocument,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.DocumentLink[]> {
|
||||
const allLinks = await this.getAllLinks(document, token);
|
||||
if (token.isCancellationRequested) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const definitionSet = new LinkDefinitionSet(allLinks);
|
||||
return coalesce(allLinks
|
||||
.map(data => this.toValidDocumentLink(data, definitionSet)));
|
||||
}
|
||||
|
||||
private toValidDocumentLink(link: MdLink, definitionSet: LinkDefinitionSet): vscode.DocumentLink | undefined {
|
||||
switch (link.href.kind) {
|
||||
case 'external': {
|
||||
return new vscode.DocumentLink(link.source.hrefRange, link.href.uri);
|
||||
}
|
||||
case 'internal': {
|
||||
const uri = OpenDocumentLinkCommand.createCommandUri(link.source.resource, link.href.path, link.href.fragment);
|
||||
const documentLink = new vscode.DocumentLink(link.source.hrefRange, uri);
|
||||
documentLink.tooltip = localize('documentLink.tooltip', 'Follow link');
|
||||
return documentLink;
|
||||
}
|
||||
case 'reference': {
|
||||
const def = definitionSet.lookup(link.href.ref);
|
||||
if (def) {
|
||||
const documentLink = new vscode.DocumentLink(
|
||||
link.source.hrefRange,
|
||||
vscode.Uri.parse(`command:_markdown.moveCursorToPosition?${encodeURIComponent(JSON.stringify([def.source.hrefRange.start.line, def.source.hrefRange.start.character]))}`));
|
||||
documentLink.tooltip = localize('documentLink.referenceTooltip', 'Go to link definition');
|
||||
return documentLink;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async getAllLinks(document: SkinnyTextDocument, token: vscode.CancellationToken): Promise<MdLink[]> {
|
||||
const noLinkRanges = await NoLinkRanges.compute(document, this.engine);
|
||||
if (token.isCancellationRequested) {
|
||||
@@ -475,3 +434,57 @@ export class LinkDefinitionSet {
|
||||
return this._map.get(ref);
|
||||
}
|
||||
}
|
||||
|
||||
export class MdLinkProvider implements vscode.DocumentLinkProvider {
|
||||
|
||||
constructor(
|
||||
private readonly _linkComputer: MdLinkComputer,
|
||||
) { }
|
||||
|
||||
public async provideDocumentLinks(
|
||||
document: SkinnyTextDocument,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.DocumentLink[]> {
|
||||
const allLinks = (await this._linkComputer.getAllLinks(document, token)) ?? [];
|
||||
if (token.isCancellationRequested) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const definitionSet = new LinkDefinitionSet(allLinks);
|
||||
return coalesce(allLinks
|
||||
.map(data => this.toValidDocumentLink(data, definitionSet)));
|
||||
}
|
||||
|
||||
private toValidDocumentLink(link: MdLink, definitionSet: LinkDefinitionSet): vscode.DocumentLink | undefined {
|
||||
switch (link.href.kind) {
|
||||
case 'external': {
|
||||
return new vscode.DocumentLink(link.source.hrefRange, link.href.uri);
|
||||
}
|
||||
case 'internal': {
|
||||
const uri = OpenDocumentLinkCommand.createCommandUri(link.source.resource, link.href.path, link.href.fragment);
|
||||
const documentLink = new vscode.DocumentLink(link.source.hrefRange, uri);
|
||||
documentLink.tooltip = localize('documentLink.tooltip', 'Follow link');
|
||||
return documentLink;
|
||||
}
|
||||
case 'reference': {
|
||||
const def = definitionSet.lookup(link.href.ref);
|
||||
if (def) {
|
||||
const documentLink = new vscode.DocumentLink(
|
||||
link.source.hrefRange,
|
||||
vscode.Uri.parse(`command:_markdown.moveCursorToPosition?${encodeURIComponent(JSON.stringify([def.source.hrefRange.start.line, def.source.hrefRange.start.character]))}`));
|
||||
documentLink.tooltip = localize('documentLink.referenceTooltip', 'Go to link definition');
|
||||
return documentLink;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function registerDocumentLinkProvider(
|
||||
selector: vscode.DocumentSelector,
|
||||
linkComputer: MdLinkComputer,
|
||||
): vscode.Disposable {
|
||||
return vscode.languages.registerDocumentLinkProvider(selector, new MdLinkProvider(linkComputer));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user