-
Notifications
You must be signed in to change notification settings - Fork 133
Expand file tree
/
Copy pathcustomEditorProvider.ts
More file actions
123 lines (105 loc) Β· 4.28 KB
/
customEditorProvider.ts
File metadata and controls
123 lines (105 loc) Β· 4.28 KB
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import vscode from "vscode";
import { CustomHTML } from "../webviews/CustomUI";
const customEditors: Map<string, CustomEditor<any>> = new Map;
export class CustomEditor<T> extends CustomHTML implements vscode.CustomDocument {
readonly uri: vscode.Uri;
private data: T = {} as T;
valid?: boolean;
dirty = false;
constructor(target: string, private readonly onSave: (data: T) => Promise<void>, private readonly onClosed?: () => void) {
super();
this.uri = vscode.Uri.from({ scheme: "code4i", path: `/${target}` });
}
protected getSpecificScript() {
return /* javascript */ `
const theForm = document.querySelector('#laforma');
for (const field of submitfields) {
const fieldElement = document.getElementById(field);
fieldElement.addEventListener(inputFields.some(f => f.id === field) ? 'input' : 'change', function(event) {
event?.preventDefault();
const data = {};
new FormData(theForm).entries().forEach(([key, value]) => data[key] = value);
// Convert checkboxes value to actual boolean
checkboxes.forEach(checkbox => data[checkbox] = (data[checkbox] === 'on'));
data.valid = validateInputs();
vscode.postMessage({ type: 'dataChange', data });
});
}
//Prevent form from being submitted
theForm.addEventListener("submit", (event) => event?.preventDefault());
`;
}
open() {
customEditors.set(this.uri.toString(), this);
vscode.commands.executeCommand("vscode.open", this.uri);
}
load(webviewPanel: vscode.WebviewPanel) {
const webview = webviewPanel.webview;
webview.options = {
enableScripts: true,
enableCommandUris: true
};
webview.html = this.getHTML(webviewPanel, this.uri.path);
}
onDataChange(data: T & { valid?: boolean }) {
this.dirty = true;
this.valid = data.valid;
delete data.valid;
this.data = data;
}
async save() {
await this.onSave(this.data);
}
dispose() {
this.onClosed?.();
}
}
export class CustomEditorProvider implements vscode.CustomEditorProvider<CustomEditor<any>> {
readonly eventEmitter = new vscode.EventEmitter<vscode.CustomDocumentEditEvent<CustomEditor<any>>>();
readonly onDidChangeCustomDocument = this.eventEmitter.event;
async saveCustomDocument(document: CustomEditor<any>, cancellation: vscode.CancellationToken) {
if (document.dirty) {
if (document.valid) {
await document.save();
document.dirty = false;
}
else {
throw new Error("Can't save: some inputs are invalid");
}
}
}
async openCustomDocument(uri: vscode.Uri, openContext: vscode.CustomDocumentOpenContext, token: vscode.CancellationToken) {
const customEditor = customEditors.get(uri.toString());
if (customEditor) {
customEditors.delete(uri.toString());
return customEditor;
}
else {
//Fail safe: do not fail, return an empty editor asking to reopen the editor
//Throwing an error here prevents that URI to be opened until the editor is closed and VS Code is restarted
return new CustomEditor(uri.path.substring(1), async () => { }).addHeading("Please close this editor and re-open it.", 3);
}
}
async resolveCustomEditor(document: CustomEditor<any>, webviewPanel: vscode.WebviewPanel, token: vscode.CancellationToken) {
document.load(webviewPanel);
webviewPanel.webview.onDidReceiveMessage(async body => {
if (body.type === "dataChange") {
document.onDataChange(body.data);
this.eventEmitter.fire({
document,
redo: () => { throw new Error("Redo not supported."); },
undo: () => { throw new Error("Undo not supported."); }
});
}
});
}
saveCustomDocumentAs(document: CustomEditor<any>, destination: vscode.Uri, cancellation: vscode.CancellationToken): Thenable<void> {
throw new Error("Save As is not supported.");
}
revertCustomDocument(document: CustomEditor<any>, cancellation: vscode.CancellationToken): Thenable<void> {
throw new Error("Revert is not supported.");
}
backupCustomDocument(document: CustomEditor<any>, context: vscode.CustomDocumentBackupContext, cancellation: vscode.CancellationToken): Thenable<vscode.CustomDocumentBackup> {
throw new Error("Backup is not supported.");
}
}