-
Notifications
You must be signed in to change notification settings - Fork 29.8k
/
updateLinksOnPaste.ts
87 lines (70 loc) · 3.41 KB
/
updateLinksOnPaste.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*---------------------------------------------------------------------------------------------
* 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';
import { MdLanguageClient } from '../client/client';
import { Mime } from '../util/mimes';
class UpdatePastedLinksEditProvider implements vscode.DocumentPasteEditProvider {
public static readonly kind = vscode.DocumentDropOrPasteEditKind.Text.append('updateLinks', 'markdown');
public static readonly metadataMime = 'application/vnd.vscode.markdown.updatelinks.metadata';
constructor(
private readonly _client: MdLanguageClient,
) { }
async prepareDocumentPaste(document: vscode.TextDocument, ranges: readonly vscode.Range[], dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise<void> {
if (!this._isEnabled(document)) {
return;
}
const metadata = await this._client.prepareUpdatePastedLinks(document.uri, ranges, token);
if (token.isCancellationRequested) {
return;
}
dataTransfer.set(UpdatePastedLinksEditProvider.metadataMime, new vscode.DataTransferItem(metadata));
}
async provideDocumentPasteEdits(
document: vscode.TextDocument,
ranges: readonly vscode.Range[],
dataTransfer: vscode.DataTransfer,
context: vscode.DocumentPasteEditContext,
token: vscode.CancellationToken,
): Promise<vscode.DocumentPasteEdit[] | undefined> {
if (!this._isEnabled(document)) {
return;
}
const metadata = dataTransfer.get(UpdatePastedLinksEditProvider.metadataMime)?.value;
if (!metadata) {
return;
}
const textItem = dataTransfer.get(Mime.textPlain);
const text = await textItem?.asString();
if (!text || token.isCancellationRequested) {
return;
}
// TODO: Handle cases such as:
// - copy empty line
// - Copy with multiple cursors and paste into multiple locations
// - ...
const edits = await this._client.getUpdatePastedLinksEdit(document.uri, ranges.map(x => new vscode.TextEdit(x, text)), metadata, token);
if (!edits?.length || token.isCancellationRequested) {
return;
}
const pasteEdit = new vscode.DocumentPasteEdit('', vscode.l10n.t("Paste and update pasted links"), UpdatePastedLinksEditProvider.kind);
const workspaceEdit = new vscode.WorkspaceEdit();
workspaceEdit.set(document.uri, edits.map(x => new vscode.TextEdit(new vscode.Range(x.range.start.line, x.range.start.character, x.range.end.line, x.range.end.character,), x.newText)));
pasteEdit.additionalEdit = workspaceEdit;
if (!context.only || !UpdatePastedLinksEditProvider.kind.contains(context.only)) {
pasteEdit.yieldTo = [vscode.DocumentDropOrPasteEditKind.Text];
}
return [pasteEdit];
}
private _isEnabled(document: vscode.TextDocument): boolean {
return vscode.workspace.getConfiguration('markdown', document.uri).get<boolean>('editor.updateLinksOnPaste.enabled', true);
}
}
export function registerUpdatePastedLinks(selector: vscode.DocumentSelector, client: MdLanguageClient) {
return vscode.languages.registerDocumentPasteEditProvider(selector, new UpdatePastedLinksEditProvider(client), {
copyMimeTypes: [UpdatePastedLinksEditProvider.metadataMime],
providedPasteEditKinds: [UpdatePastedLinksEditProvider.kind],
pasteMimeTypes: [UpdatePastedLinksEditProvider.metadataMime],
});
}