@silverbulletmd/silverbullet 2.9.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -23
- package/client/plugos/hooks/syscall.ts +24 -10
- package/client/plugos/syscalls/asset.ts +61 -23
- package/client/plugos/syscalls/clientStore.ts +32 -6
- package/client/plugos/syscalls/client_code_widget.ts +9 -4
- package/client/plugos/syscalls/code_widget.ts +26 -11
- package/client/plugos/syscalls/config.ts +146 -30
- package/client/plugos/syscalls/datastore.ts +146 -40
- package/client/plugos/syscalls/editor.ts +1432 -711
- package/client/plugos/syscalls/event.ts +46 -13
- package/client/plugos/syscalls/fetch.ts +123 -82
- package/client/plugos/syscalls/index.ts +242 -116
- package/client/plugos/syscalls/jsonschema.ts +107 -8
- package/client/plugos/syscalls/language.ts +38 -12
- package/client/plugos/syscalls/markdown.ts +166 -50
- package/client/plugos/syscalls/mq.ts +93 -20
- package/client/plugos/syscalls/schema_introspection.ts +33 -0
- package/client/plugos/syscalls/service_registry.ts +74 -20
- package/client/plugos/syscalls/shell.ts +51 -20
- package/client/plugos/syscalls/space.ts +169 -113
- package/client/plugos/syscalls/sync.ts +50 -19
- package/client/plugos/syscalls/system.ts +236 -139
- package/client/plugos/system.ts +21 -5
- package/client/space_lua/api_documentation.ts +107 -0
- package/client/space_lua/ast.ts +13 -0
- package/client/space_lua/eval.ts +12 -4
- package/client/space_lua/parse.ts +243 -108
- package/client/space_lua/pretty_print.ts +128 -54
- package/client/space_lua/query_collection.ts +4 -4
- package/client/space_lua/render_widget.ts +156 -0
- package/client/space_lua/runtime.ts +83 -22
- package/client/space_lua/stdlib/crypto.ts +8 -3
- package/client/space_lua/stdlib/encoding.ts +27 -9
- package/client/space_lua/stdlib/js.ts +137 -22
- package/client/space_lua/stdlib/load.ts +24 -15
- package/client/space_lua/stdlib/math.ts +323 -118
- package/client/space_lua/stdlib/net.ts +57 -9
- package/client/space_lua/stdlib/os.ts +111 -44
- package/client/space_lua/stdlib/space_lua.ts +344 -20
- package/client/space_lua/stdlib/string.ts +282 -104
- package/client/space_lua/stdlib/string_pack.ts +58 -19
- package/client/space_lua/stdlib/table.ts +195 -40
- package/client/space_lua/stdlib.ts +335 -93
- package/client/space_lua/syscalls.ts +270 -0
- package/dist/plug-compile.js +1 -1
- package/package.json +3 -3
- package/plug-api/lib/ref.ts +96 -0
- package/plug-api/lib/shortcut.ts +2 -1
- package/plug-api/syscalls/config.ts +5 -3
- package/plug-api/syscalls/editor.ts +16 -0
- package/plug-api/syscalls/index.ts +17 -1
- package/plug-api/syscalls/jsonschema.ts +9 -0
- package/plug-api/syscalls/lua.ts +7 -0
- package/plug-api/syscalls/shell.ts +0 -1
- package/plug-api/syscalls/system.ts +7 -0
- package/plug-api/system_mock.ts +2 -2
- package/plug-api/types/index.ts +52 -1
- package/plug-api/types/manifest.ts +22 -4
- package/plug-api/ui/cx.ts +1 -3
- package/plug-api/ui/index.ts +3 -0
- package/plug-api/ui/panel_styles.ts +4 -3
- package/plug-api/ui/slugify.ts +44 -0
- package/client/plugos/syscalls/lua.ts +0 -81
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import type { Client } from "../../client.ts";
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "@codemirror/language";
|
|
2
|
+
acceptCompletion,
|
|
3
|
+
closeCompletion,
|
|
4
|
+
moveCompletionSelection,
|
|
5
|
+
startCompletion,
|
|
6
|
+
} from "@codemirror/autocomplete";
|
|
9
7
|
import {
|
|
10
8
|
cursorCharLeft,
|
|
11
9
|
cursorCharRight,
|
|
@@ -54,773 +52,1496 @@ import {
|
|
|
54
52
|
transposeChars,
|
|
55
53
|
undo,
|
|
56
54
|
} from "@codemirror/commands";
|
|
55
|
+
import { insertNewlineContinueMarkup } from "@codemirror/lang-markdown";
|
|
57
56
|
import {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
foldAll,
|
|
58
|
+
foldCode,
|
|
59
|
+
toggleFold,
|
|
60
|
+
unfoldAll,
|
|
61
|
+
unfoldCode,
|
|
62
|
+
} from "@codemirror/language";
|
|
63
|
+
import { forceLinting } from "@codemirror/lint";
|
|
64
|
+
import { openSearchPanel } from "@codemirror/search";
|
|
63
65
|
import type { Transaction } from "@codemirror/state";
|
|
64
66
|
import { EditorView } from "@codemirror/view";
|
|
65
|
-
import {
|
|
66
|
-
|
|
67
|
+
import {
|
|
68
|
+
coerceAndValidateRef,
|
|
69
|
+
type Ref,
|
|
70
|
+
} from "@silverbulletmd/silverbullet/lib/ref";
|
|
67
71
|
import type {
|
|
68
72
|
FilterOption,
|
|
69
73
|
NotificationAction,
|
|
70
74
|
NotificationType,
|
|
71
75
|
UploadFile,
|
|
72
76
|
} from "@silverbulletmd/silverbullet/type/client";
|
|
73
|
-
import { openSearchPanel } from "@codemirror/search";
|
|
74
|
-
import { forceLinting } from "@codemirror/lint";
|
|
75
|
-
import { refreshLintEffect } from "../../codemirror/lint.ts";
|
|
76
|
-
import {
|
|
77
|
-
isValidPath,
|
|
78
|
-
parseToRef,
|
|
79
|
-
type Path,
|
|
80
|
-
type Ref,
|
|
81
|
-
} from "@silverbulletmd/silverbullet/lib/ref";
|
|
82
|
-
import { insertNewlineContinueMarkup } from "@codemirror/lang-markdown";
|
|
83
77
|
import type { VimConfig } from "@silverbulletmd/silverbullet/type/config";
|
|
84
78
|
import type { PageMeta } from "@silverbulletmd/silverbullet/type/index";
|
|
79
|
+
import { updateBakedSections } from "../../baked_sections/bake.ts";
|
|
80
|
+
import type { Client } from "../../client.ts";
|
|
81
|
+
import { refreshLintEffect } from "../../codemirror/lint.ts";
|
|
82
|
+
import { getVimModule } from "../../vim_loader.ts";
|
|
83
|
+
import type { SysCallMapping } from "../system.ts";
|
|
85
84
|
|
|
86
85
|
export function editorSyscalls(client: Client): SysCallMapping {
|
|
87
86
|
const syscalls: SysCallMapping = {
|
|
88
|
-
"editor.getCurrentPage":
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
},
|
|
131
|
-
"editor.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
selection.to,
|
|
136
|
-
);
|
|
137
|
-
return {
|
|
138
|
-
from: selection.from,
|
|
139
|
-
to: selection.to,
|
|
140
|
-
text,
|
|
141
|
-
};
|
|
142
|
-
},
|
|
143
|
-
"editor.save": () => {
|
|
144
|
-
return client.save(true);
|
|
145
|
-
},
|
|
146
|
-
"editor.navigate": async (
|
|
147
|
-
_ctx,
|
|
148
|
-
ref: Ref | string,
|
|
149
|
-
replaceState = false,
|
|
150
|
-
newWindow = false,
|
|
151
|
-
) => {
|
|
152
|
-
if (typeof ref === "string") {
|
|
153
|
-
const parsedRef = parseToRef(ref);
|
|
154
|
-
if (!parsedRef) {
|
|
155
|
-
throw new Error(
|
|
156
|
-
"Unable to parse string provided to `editor.navigate` as ref",
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
ref = parsedRef;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (
|
|
163
|
-
// @ts-expect-error: Legacy support
|
|
164
|
-
ref.page !== undefined
|
|
165
|
-
) {
|
|
166
|
-
console.warn(
|
|
167
|
-
"You are using legacy navigation syntax with `editor.navigate()`, this will be phased out in the future",
|
|
87
|
+
"editor.getCurrentPage": {
|
|
88
|
+
callback: (): string => {
|
|
89
|
+
return client.currentName();
|
|
90
|
+
},
|
|
91
|
+
description:
|
|
92
|
+
"Returns the name of the page or document currently open in the editor.",
|
|
93
|
+
returns: [{ type: "string", description: "The current page name." }],
|
|
94
|
+
},
|
|
95
|
+
"editor.getCurrentPageMeta": {
|
|
96
|
+
callback: (): Promise<PageMeta | undefined> => {
|
|
97
|
+
const name = client.currentName();
|
|
98
|
+
return client.objectIndex.getObjectByRef(name, "page", name);
|
|
99
|
+
},
|
|
100
|
+
description:
|
|
101
|
+
"Returns metadata for the page or document currently open in the editor.",
|
|
102
|
+
returns: [
|
|
103
|
+
{
|
|
104
|
+
type: "PageMeta | undefined",
|
|
105
|
+
description: "The current page metadata, if indexed.",
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
"editor.getCurrentPath": {
|
|
110
|
+
callback: (_ctx): string => {
|
|
111
|
+
return client.currentPath();
|
|
112
|
+
},
|
|
113
|
+
description:
|
|
114
|
+
"Returns the path of the page or document currently open in the editor.",
|
|
115
|
+
returns: [{ type: "string", description: "The current page path." }],
|
|
116
|
+
},
|
|
117
|
+
"editor.getCurrentEditor": {
|
|
118
|
+
callback: (): string => {
|
|
119
|
+
return client.contentManager.documentEditor?.name || "page";
|
|
120
|
+
},
|
|
121
|
+
description:
|
|
122
|
+
"Returns the name of the currently active editor implementation.",
|
|
123
|
+
returns: [
|
|
124
|
+
{
|
|
125
|
+
type: "string",
|
|
126
|
+
description: "The editor name, or `page` for the page editor.",
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
"editor.getRecentlyOpenedPages": {
|
|
131
|
+
callback: (): PageMeta[] => {
|
|
132
|
+
return client.ui.viewState.allPages.sort(
|
|
133
|
+
(a, b) => (b.lastOpened || 0) - (a.lastOpened || 0),
|
|
168
134
|
);
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
135
|
+
},
|
|
136
|
+
description:
|
|
137
|
+
"Returns page metadata ordered from most to least recently opened.",
|
|
138
|
+
returns: [{ type: "PageMeta[]", description: "Recently opened pages." }],
|
|
139
|
+
},
|
|
140
|
+
"editor.getText": {
|
|
141
|
+
callback: () => {
|
|
142
|
+
return client.editorView.state.sliceDoc();
|
|
143
|
+
},
|
|
144
|
+
description:
|
|
145
|
+
"Returns the full text of the currently open page or document.",
|
|
146
|
+
returns: [{ type: "string", description: "The editor contents." }],
|
|
147
|
+
},
|
|
148
|
+
"editor.getCurrentLine": {
|
|
149
|
+
callback: (): {
|
|
150
|
+
from: number;
|
|
151
|
+
to: number;
|
|
152
|
+
text: string;
|
|
153
|
+
textWithCursor: string;
|
|
154
|
+
} => {
|
|
155
|
+
const pos = client.editorView.state.selection.main.from;
|
|
156
|
+
const line = client.editorView.state.doc.lineAt(pos);
|
|
157
|
+
return {
|
|
158
|
+
...line,
|
|
159
|
+
textWithCursor:
|
|
160
|
+
line.text.slice(0, pos - line.from) +
|
|
161
|
+
"|^|" +
|
|
162
|
+
line.text.slice(pos - line.from),
|
|
176
163
|
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
164
|
+
},
|
|
165
|
+
description:
|
|
166
|
+
"Returns the current line's range and text, including a `|^|` cursor marker variant.",
|
|
167
|
+
returns: [
|
|
168
|
+
{
|
|
169
|
+
type: "{ from: number; to: number; text: string; textWithCursor: string }",
|
|
170
|
+
description: "The line containing the main selection head.",
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
"editor.setText": {
|
|
175
|
+
callback: (_ctx, newText: string, shouldIsolateHistory = false) => {
|
|
176
|
+
client.contentManager.setEditorText(newText, shouldIsolateHistory);
|
|
177
|
+
},
|
|
178
|
+
description:
|
|
179
|
+
"Updates the editor text with a minimal diff while preserving the cursor when possible.",
|
|
180
|
+
parameters: [
|
|
181
|
+
{
|
|
182
|
+
name: "newText",
|
|
183
|
+
type: "string",
|
|
184
|
+
description: "The complete replacement text.",
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: "shouldIsolateHistory",
|
|
188
|
+
type: "boolean",
|
|
189
|
+
description: "Whether to isolate the change in undo history.",
|
|
190
|
+
optional: true,
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
},
|
|
194
|
+
"editor.getCursor": {
|
|
195
|
+
callback: (): number => {
|
|
196
|
+
return client.editorView.state.selection.main.from;
|
|
197
|
+
},
|
|
198
|
+
description:
|
|
199
|
+
"Returns the cursor position as a character offset from the start of the document.",
|
|
200
|
+
returns: [{ type: "number", description: "The cursor offset." }],
|
|
201
|
+
},
|
|
202
|
+
"editor.getSelection": {
|
|
203
|
+
callback: (): { from: number; to: number; text: string } => {
|
|
204
|
+
const selection = client.editorView.state.selection.main;
|
|
205
|
+
const text = client.editorView.state.sliceDoc(
|
|
206
|
+
selection.from,
|
|
207
|
+
selection.to,
|
|
208
|
+
);
|
|
209
|
+
return {
|
|
210
|
+
from: selection.from,
|
|
211
|
+
to: selection.to,
|
|
212
|
+
text,
|
|
206
213
|
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
214
|
+
},
|
|
215
|
+
description: "Returns the current selection range and selected text.",
|
|
216
|
+
returns: [
|
|
217
|
+
{
|
|
218
|
+
type: "{ from: number; to: number; text: string }",
|
|
219
|
+
description: "The main editor selection.",
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
},
|
|
223
|
+
"editor.save": {
|
|
224
|
+
callback: () => {
|
|
225
|
+
return client.save(true);
|
|
226
|
+
},
|
|
227
|
+
description: "Forces the current page or document to be saved.",
|
|
228
|
+
},
|
|
229
|
+
"editor.navigate": {
|
|
230
|
+
callback: async (
|
|
231
|
+
_ctx,
|
|
232
|
+
ref: Ref | string,
|
|
233
|
+
replaceState = false,
|
|
234
|
+
newWindow = false,
|
|
235
|
+
) => {
|
|
236
|
+
await client.navigate(
|
|
237
|
+
coerceAndValidateRef(ref),
|
|
238
|
+
replaceState,
|
|
239
|
+
newWindow,
|
|
219
240
|
);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
"
|
|
241
|
+
},
|
|
242
|
+
description:
|
|
243
|
+
"Navigates to a page reference without restoring its remembered cursor and scroll position.",
|
|
244
|
+
parameters: [
|
|
245
|
+
{
|
|
246
|
+
name: "ref",
|
|
247
|
+
type: "Ref | string",
|
|
248
|
+
description: "The page reference to navigate to.",
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
name: "replaceState",
|
|
252
|
+
type: "boolean",
|
|
253
|
+
description: "Whether to replace the current browser history state.",
|
|
254
|
+
optional: true,
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
name: "newWindow",
|
|
258
|
+
type: "boolean",
|
|
259
|
+
description: "Whether to open the reference in a new window.",
|
|
260
|
+
optional: true,
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
examples: [{ code: 'editor.navigate("CHANGELOG@123")' }],
|
|
264
|
+
},
|
|
265
|
+
"editor.open": {
|
|
266
|
+
callback: async (
|
|
267
|
+
_ctx,
|
|
268
|
+
ref: Ref | string,
|
|
269
|
+
replaceState = false,
|
|
270
|
+
newWindow = false,
|
|
271
|
+
) => {
|
|
272
|
+
await client.open(coerceAndValidateRef(ref), replaceState, newWindow);
|
|
273
|
+
},
|
|
274
|
+
description:
|
|
275
|
+
"Opens a page reference and restores its remembered cursor and scroll position when possible.",
|
|
276
|
+
parameters: [
|
|
277
|
+
{
|
|
278
|
+
name: "ref",
|
|
279
|
+
type: "Ref | string",
|
|
280
|
+
description: "The page reference to open.",
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
name: "replaceState",
|
|
284
|
+
type: "boolean",
|
|
285
|
+
description: "Whether to replace the current browser history state.",
|
|
286
|
+
optional: true,
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: "newWindow",
|
|
290
|
+
type: "boolean",
|
|
291
|
+
description: "Whether to open the reference in a new window.",
|
|
292
|
+
optional: true,
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
examples: [{ code: 'editor.open("CHANGELOG")' }],
|
|
296
|
+
},
|
|
297
|
+
"editor.reloadPage": {
|
|
298
|
+
callback: async () => {
|
|
299
|
+
await client.reloadEditor();
|
|
300
|
+
},
|
|
301
|
+
description: "Force reloads the current page in the editor.",
|
|
302
|
+
},
|
|
303
|
+
"editor.forceLint": {
|
|
304
|
+
callback: () => {
|
|
305
|
+
// `forceLinting` alone is a no-op on unchanged content after the
|
|
306
|
+
// linter's internal "scheduled" flag has been cleared; the effect
|
|
307
|
+
// re-arms it via `needsRefresh`.
|
|
308
|
+
client.editorView.dispatch({
|
|
309
|
+
effects: refreshLintEffect.of(null),
|
|
310
|
+
});
|
|
311
|
+
forceLinting(client.editorView);
|
|
312
|
+
},
|
|
313
|
+
description:
|
|
314
|
+
"Forces editor linting to run, including when the content has not changed.",
|
|
315
|
+
},
|
|
316
|
+
"editor.reloadUI": {
|
|
317
|
+
callback: () => {
|
|
318
|
+
location.reload();
|
|
319
|
+
},
|
|
320
|
+
description: "Force reloads the browser UI.",
|
|
321
|
+
},
|
|
322
|
+
"editor.rebuildEditorState": {
|
|
323
|
+
callback: () => {
|
|
324
|
+
client.rebuildEditorState();
|
|
325
|
+
},
|
|
326
|
+
description:
|
|
327
|
+
"Rebuilds the CodeMirror editor state from the current client configuration.",
|
|
328
|
+
},
|
|
329
|
+
"editor.reloadConfigAndCommands": {
|
|
330
|
+
callback: async () => {
|
|
331
|
+
await client.clientSystem.system.localSyscall("system.loadScripts", []);
|
|
332
|
+
await client.clientSystem.system.localSyscall(
|
|
333
|
+
"system.loadSpaceStyles",
|
|
334
|
+
[],
|
|
228
335
|
);
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
336
|
+
client.rebuildEditorState();
|
|
337
|
+
},
|
|
338
|
+
description:
|
|
339
|
+
"Reloads space scripts and styles, then rebuilds the editor state.",
|
|
340
|
+
},
|
|
341
|
+
"editor.invokeCommand": {
|
|
342
|
+
callback: (_ctx, name: string, args?: string[]) => {
|
|
343
|
+
return client.runCommandByName(name, args);
|
|
344
|
+
},
|
|
345
|
+
description: "Invokes a client command by name.",
|
|
346
|
+
parameters: [
|
|
347
|
+
{ name: "name", type: "string", description: "The command name." },
|
|
348
|
+
{
|
|
349
|
+
name: "args",
|
|
350
|
+
type: "string[]",
|
|
351
|
+
description: "Arguments passed to the command.",
|
|
352
|
+
optional: true,
|
|
353
|
+
},
|
|
354
|
+
],
|
|
355
|
+
},
|
|
356
|
+
// Re-evaluate every baked section on the current page and rewrite each body
|
|
357
|
+
// with its latest output (same as the "Baked Sections: Update" command),
|
|
358
|
+
// exposed for programmatic use.
|
|
359
|
+
"editor.updateBakedSections": {
|
|
360
|
+
callback: (): Promise<void> => {
|
|
361
|
+
return updateBakedSections(client);
|
|
362
|
+
},
|
|
363
|
+
description:
|
|
364
|
+
"Re-evaluates every baked section on the current page and replaces each body with its latest output.",
|
|
365
|
+
},
|
|
366
|
+
"editor.openUrl": {
|
|
367
|
+
callback: (_ctx, url: string, existingWindow = false) => {
|
|
368
|
+
client.openUrl(url, existingWindow);
|
|
369
|
+
},
|
|
370
|
+
description: "Opens a URL in the browser.",
|
|
371
|
+
parameters: [
|
|
372
|
+
{ name: "url", type: "string", description: "The URL to open." },
|
|
373
|
+
{
|
|
374
|
+
name: "existingWindow",
|
|
375
|
+
type: "boolean",
|
|
376
|
+
description: "Whether to reuse an existing window.",
|
|
377
|
+
optional: true,
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
},
|
|
381
|
+
"editor.newWindow": {
|
|
382
|
+
callback: () => {
|
|
383
|
+
globalThis.open(
|
|
384
|
+
location.href,
|
|
385
|
+
`rnd${Math.random()}`,
|
|
386
|
+
`width=${globalThis.innerWidth},heigh=${globalThis.innerHeight}`,
|
|
248
387
|
);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
388
|
+
},
|
|
389
|
+
description:
|
|
390
|
+
"Opens the current SilverBullet URL in a new browser window.",
|
|
391
|
+
},
|
|
392
|
+
"editor.goHistory": {
|
|
393
|
+
callback: (_ctx, delta: number) => {
|
|
394
|
+
globalThis.history.go(delta);
|
|
395
|
+
},
|
|
396
|
+
description: "Moves backward or forward through browser history.",
|
|
397
|
+
parameters: [
|
|
398
|
+
{
|
|
399
|
+
name: "delta",
|
|
400
|
+
type: "number",
|
|
401
|
+
description:
|
|
402
|
+
"The relative history offset; negative moves backward and positive moves forward.",
|
|
403
|
+
},
|
|
404
|
+
],
|
|
405
|
+
},
|
|
406
|
+
"editor.downloadFile": {
|
|
407
|
+
callback: (_ctx, filename: string, dataUrl: string) => {
|
|
408
|
+
const link = document.createElement("a");
|
|
409
|
+
link.href = dataUrl;
|
|
410
|
+
link.download = filename;
|
|
411
|
+
link.click();
|
|
412
|
+
},
|
|
413
|
+
description:
|
|
414
|
+
"Triggers a browser download of a data URL under the given filename.",
|
|
415
|
+
parameters: [
|
|
416
|
+
{
|
|
417
|
+
name: "filename",
|
|
418
|
+
type: "string",
|
|
419
|
+
description: "The downloaded filename.",
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
name: "dataUrl",
|
|
423
|
+
type: "string",
|
|
424
|
+
description: "The data URL to download.",
|
|
425
|
+
},
|
|
426
|
+
],
|
|
427
|
+
examples: [
|
|
428
|
+
{
|
|
429
|
+
code: 'editor.downloadFile("test.txt", "data:text/plain;base64,SGVsbG8=")',
|
|
430
|
+
},
|
|
431
|
+
],
|
|
432
|
+
},
|
|
433
|
+
"editor.uploadFile": {
|
|
434
|
+
callback: (
|
|
435
|
+
_ctx,
|
|
436
|
+
accept?: string,
|
|
437
|
+
capture?: string,
|
|
438
|
+
): Promise<UploadFile> => {
|
|
439
|
+
return new Promise<UploadFile>((resolve, reject) => {
|
|
440
|
+
const input = document.createElement("input");
|
|
441
|
+
input.type = "file";
|
|
442
|
+
if (accept) {
|
|
443
|
+
input.accept = accept;
|
|
444
|
+
}
|
|
445
|
+
if (capture) {
|
|
446
|
+
input.capture = capture;
|
|
447
|
+
}
|
|
255
448
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
},
|
|
284
|
-
"editor.invokeCommand": (_ctx, name: string, args?: string[]) => {
|
|
285
|
-
return client.runCommandByName(name, args);
|
|
286
|
-
},
|
|
287
|
-
"editor.openUrl": (_ctx, url: string, existingWindow = false) => {
|
|
288
|
-
client.openUrl(url, existingWindow);
|
|
289
|
-
},
|
|
290
|
-
"editor.newWindow": () => {
|
|
291
|
-
globalThis.open(
|
|
292
|
-
location.href,
|
|
293
|
-
`rnd${Math.random()}`,
|
|
294
|
-
`width=${globalThis.innerWidth},heigh=${globalThis.innerHeight}`,
|
|
295
|
-
);
|
|
296
|
-
},
|
|
297
|
-
"editor.goHistory": (_ctx, delta: number) => {
|
|
298
|
-
globalThis.history.go(delta);
|
|
299
|
-
},
|
|
300
|
-
"editor.downloadFile": (_ctx, filename: string, dataUrl: string) => {
|
|
301
|
-
const link = document.createElement("a");
|
|
302
|
-
link.href = dataUrl;
|
|
303
|
-
link.download = filename;
|
|
304
|
-
link.click();
|
|
305
|
-
},
|
|
306
|
-
"editor.uploadFile": (
|
|
307
|
-
_ctx,
|
|
308
|
-
accept?: string,
|
|
309
|
-
capture?: string,
|
|
310
|
-
): Promise<UploadFile> => {
|
|
311
|
-
return new Promise<UploadFile>((resolve, reject) => {
|
|
312
|
-
const input = document.createElement("input");
|
|
313
|
-
input.type = "file";
|
|
314
|
-
if (accept) {
|
|
315
|
-
input.accept = accept;
|
|
316
|
-
}
|
|
317
|
-
if (capture) {
|
|
318
|
-
input.capture = capture;
|
|
319
|
-
}
|
|
449
|
+
input.onchange = () => {
|
|
450
|
+
const file = input.files?.item(0);
|
|
451
|
+
if (!file) {
|
|
452
|
+
reject(new Error("No file found"));
|
|
453
|
+
} else {
|
|
454
|
+
const reader = new FileReader();
|
|
455
|
+
reader.readAsArrayBuffer(file);
|
|
456
|
+
reader.onloadend = async (evt) => {
|
|
457
|
+
if (evt.target?.readyState === FileReader.DONE) {
|
|
458
|
+
resolve({
|
|
459
|
+
name: file.name,
|
|
460
|
+
contentType: file.type,
|
|
461
|
+
content: new Uint8Array(await file.arrayBuffer()),
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
reader.onabort = (e) => {
|
|
466
|
+
reject(e);
|
|
467
|
+
};
|
|
468
|
+
reader.onerror = (e) => {
|
|
469
|
+
reject(e);
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
input.onabort = (e) => {
|
|
474
|
+
reject(e);
|
|
475
|
+
};
|
|
320
476
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
477
|
+
input.style.display = "none";
|
|
478
|
+
document.body.appendChild(input);
|
|
479
|
+
input.click();
|
|
480
|
+
setTimeout(() => document.body.removeChild(input), 1000);
|
|
481
|
+
});
|
|
482
|
+
},
|
|
483
|
+
description:
|
|
484
|
+
"Opens the browser's native file picker and returns the selected file's bytes and metadata.",
|
|
485
|
+
parameters: [
|
|
486
|
+
{
|
|
487
|
+
name: "accept",
|
|
488
|
+
type: "string",
|
|
489
|
+
description: "Accepted file types for the file input.",
|
|
490
|
+
optional: true,
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
name: "capture",
|
|
494
|
+
type: "string",
|
|
495
|
+
description: "The media capture mode for the file input.",
|
|
496
|
+
optional: true,
|
|
497
|
+
},
|
|
498
|
+
],
|
|
499
|
+
returns: [
|
|
500
|
+
{
|
|
501
|
+
type: "UploadFile",
|
|
502
|
+
description: "The selected file's name, content type, and bytes.",
|
|
503
|
+
},
|
|
504
|
+
],
|
|
505
|
+
examples: [
|
|
506
|
+
{
|
|
507
|
+
code: 'local file = editor.uploadFile(".txt")\nprint(file.name)',
|
|
508
|
+
},
|
|
509
|
+
],
|
|
510
|
+
},
|
|
511
|
+
"editor.flashNotification": {
|
|
512
|
+
callback: (
|
|
513
|
+
_ctx,
|
|
514
|
+
message: string,
|
|
515
|
+
type: NotificationType = "info",
|
|
516
|
+
options?: { timeout?: number; actions?: NotificationAction[] },
|
|
517
|
+
) => {
|
|
518
|
+
client.ui.flashNotification(message, type, options);
|
|
519
|
+
},
|
|
520
|
+
description: "Shows a flash notification in the editor UI.",
|
|
521
|
+
parameters: [
|
|
522
|
+
{
|
|
523
|
+
name: "message",
|
|
524
|
+
type: "string",
|
|
525
|
+
description: "The message to display.",
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
name: "type",
|
|
529
|
+
type: "NotificationType",
|
|
530
|
+
description:
|
|
531
|
+
'The notification severity: "info", "error", or "warning".',
|
|
532
|
+
optional: true,
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
name: "options",
|
|
536
|
+
type: "{ timeout?: number; actions?: NotificationAction[] }",
|
|
537
|
+
description:
|
|
538
|
+
"Optional timeout and action buttons. A timeout of 0 keeps the notification visible until dismissed.",
|
|
539
|
+
optional: true,
|
|
540
|
+
},
|
|
541
|
+
],
|
|
542
|
+
examples: [
|
|
543
|
+
{
|
|
544
|
+
code: 'editor.flashNotification("Update available", "warning", {\n timeout = 0,\n actions = {{\n name = "Reload",\n run = function() editor.reloadUI() end\n }}\n})',
|
|
545
|
+
},
|
|
546
|
+
],
|
|
547
|
+
},
|
|
548
|
+
"editor.filterBox": {
|
|
549
|
+
callback: (
|
|
550
|
+
_ctx,
|
|
551
|
+
label: string,
|
|
552
|
+
options: FilterOption[],
|
|
553
|
+
helpText = "",
|
|
554
|
+
placeHolder = "",
|
|
555
|
+
): Promise<FilterOption | undefined> => {
|
|
556
|
+
return client.ui.filterBox(label, options, helpText, placeHolder);
|
|
557
|
+
},
|
|
558
|
+
description:
|
|
559
|
+
"Shows a filterable option picker similar to the page navigator.",
|
|
560
|
+
parameters: [
|
|
561
|
+
{
|
|
562
|
+
name: "label",
|
|
563
|
+
type: "string",
|
|
564
|
+
description: "The label shown beside the filter input.",
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
name: "options",
|
|
568
|
+
type: "FilterOption[]",
|
|
569
|
+
description: "The available options.",
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
name: "helpText",
|
|
573
|
+
type: "string",
|
|
574
|
+
description: "Help text shown below the picker.",
|
|
575
|
+
optional: true,
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
name: "placeHolder",
|
|
579
|
+
type: "string",
|
|
580
|
+
description: "Placeholder text for the filter input.",
|
|
581
|
+
optional: true,
|
|
582
|
+
},
|
|
583
|
+
],
|
|
584
|
+
returns: [
|
|
585
|
+
{
|
|
586
|
+
type: "FilterOption | undefined",
|
|
587
|
+
description: "The selected option, or undefined if dismissed.",
|
|
588
|
+
},
|
|
589
|
+
],
|
|
590
|
+
examples: [
|
|
591
|
+
{
|
|
592
|
+
code: 'local result = editor.filterBox("Select:", {\n {name = "Option 1", value = "1"},\n {name = "Option 2", value = "2", description = "More details"}\n})',
|
|
593
|
+
},
|
|
594
|
+
],
|
|
595
|
+
},
|
|
596
|
+
"editor.showPanel": {
|
|
597
|
+
callback: (
|
|
598
|
+
_ctx,
|
|
599
|
+
id: string,
|
|
600
|
+
mode: number,
|
|
601
|
+
html: HTMLElement | HTMLElement[] | string,
|
|
602
|
+
script: string,
|
|
603
|
+
) => {
|
|
604
|
+
client.ui.viewDispatch({
|
|
605
|
+
type: "show-panel",
|
|
606
|
+
id: id as any,
|
|
607
|
+
config: { html, script, mode },
|
|
608
|
+
});
|
|
609
|
+
setTimeout(() => {
|
|
610
|
+
// Dummy dispatch to rerender the editor and toggle the panel
|
|
611
|
+
client.editorView.dispatch({});
|
|
612
|
+
});
|
|
613
|
+
},
|
|
614
|
+
description: "Shows an HTML panel in a specified editor UI location.",
|
|
615
|
+
parameters: [
|
|
616
|
+
{
|
|
617
|
+
name: "id",
|
|
618
|
+
type: "string",
|
|
619
|
+
description: "The panel location identifier.",
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
name: "mode",
|
|
623
|
+
type: "number",
|
|
624
|
+
description: "The panel display mode or size.",
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
name: "html",
|
|
628
|
+
type: "HTMLElement | HTMLElement[] | string",
|
|
629
|
+
description: "The panel content.",
|
|
630
|
+
},
|
|
631
|
+
{
|
|
632
|
+
name: "script",
|
|
633
|
+
type: "string",
|
|
634
|
+
description: "A script associated with the panel content.",
|
|
635
|
+
},
|
|
636
|
+
],
|
|
637
|
+
},
|
|
638
|
+
"editor.focus": {
|
|
639
|
+
callback: () => {
|
|
640
|
+
client.focus();
|
|
641
|
+
},
|
|
642
|
+
description: "Returns focus to the main editor.",
|
|
643
|
+
},
|
|
644
|
+
"editor.hidePanel": {
|
|
645
|
+
callback: (_ctx, id: string) => {
|
|
646
|
+
client.ui.viewDispatch({
|
|
647
|
+
type: "hide-panel",
|
|
648
|
+
id: id as any,
|
|
649
|
+
});
|
|
650
|
+
setTimeout(() => {
|
|
651
|
+
// Dummy dispatch to rerender the editor and toggle the panel
|
|
652
|
+
client.editorView.dispatch({});
|
|
653
|
+
});
|
|
654
|
+
},
|
|
655
|
+
description: "Hides the panel at a specified editor UI location.",
|
|
656
|
+
parameters: [
|
|
657
|
+
{
|
|
658
|
+
name: "id",
|
|
659
|
+
type: "string",
|
|
660
|
+
description: "The panel location identifier.",
|
|
661
|
+
},
|
|
662
|
+
],
|
|
663
|
+
},
|
|
664
|
+
"editor.showProgress": {
|
|
665
|
+
callback: (
|
|
666
|
+
_ctx,
|
|
667
|
+
progressPercentage?: number,
|
|
668
|
+
progressType?: "sync" | "index",
|
|
669
|
+
) => {
|
|
670
|
+
client.ui.showProgress(progressPercentage, progressType);
|
|
671
|
+
},
|
|
672
|
+
description:
|
|
673
|
+
"Shows, updates, or hides a sync or indexing progress indicator.",
|
|
674
|
+
parameters: [
|
|
675
|
+
{
|
|
676
|
+
name: "progressPercentage",
|
|
677
|
+
type: "number",
|
|
678
|
+
description:
|
|
679
|
+
"Completion percentage, or undefined to hide the indicator.",
|
|
680
|
+
optional: true,
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
name: "progressType",
|
|
684
|
+
type: "sync | index",
|
|
685
|
+
description: "The operation represented by the indicator.",
|
|
686
|
+
optional: true,
|
|
687
|
+
},
|
|
688
|
+
],
|
|
689
|
+
},
|
|
690
|
+
"editor.insertAtPos": {
|
|
691
|
+
callback: (
|
|
692
|
+
_ctx,
|
|
693
|
+
text: string,
|
|
694
|
+
pos: number,
|
|
695
|
+
cursorPlaceHolder = false,
|
|
696
|
+
) => {
|
|
697
|
+
let cursorPlaceholderPos = -1;
|
|
698
|
+
if (cursorPlaceHolder) {
|
|
699
|
+
cursorPlaceholderPos = text.indexOf("|^|");
|
|
700
|
+
if (cursorPlaceholderPos !== -1) {
|
|
701
|
+
text =
|
|
702
|
+
text.slice(0, cursorPlaceholderPos) +
|
|
703
|
+
text.slice(cursorPlaceholderPos + 3);
|
|
325
704
|
} else {
|
|
326
|
-
|
|
327
|
-
reader.readAsArrayBuffer(file);
|
|
328
|
-
reader.onloadend = async (evt) => {
|
|
329
|
-
if (evt.target?.readyState === FileReader.DONE) {
|
|
330
|
-
resolve({
|
|
331
|
-
name: file.name,
|
|
332
|
-
contentType: file.type,
|
|
333
|
-
content: new Uint8Array(await file.arrayBuffer()),
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
};
|
|
337
|
-
reader.onabort = (e) => {
|
|
338
|
-
reject(e);
|
|
339
|
-
};
|
|
340
|
-
reader.onerror = (e) => {
|
|
341
|
-
reject(e);
|
|
342
|
-
};
|
|
705
|
+
cursorPlaceHolder = false;
|
|
343
706
|
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
client.focus();
|
|
391
|
-
},
|
|
392
|
-
"editor.hidePanel": (_ctx, id: string) => {
|
|
393
|
-
client.ui.viewDispatch({
|
|
394
|
-
type: "hide-panel",
|
|
395
|
-
id: id as any,
|
|
396
|
-
});
|
|
397
|
-
setTimeout(() => {
|
|
398
|
-
// Dummy dispatch to rerender the editor and toggle the panel
|
|
399
|
-
client.editorView.dispatch({});
|
|
400
|
-
});
|
|
401
|
-
},
|
|
402
|
-
"editor.showProgress": (
|
|
403
|
-
_ctx,
|
|
404
|
-
progressPercentage?: number,
|
|
405
|
-
progressType?: "sync" | "index",
|
|
406
|
-
) => {
|
|
407
|
-
client.ui.showProgress(progressPercentage, progressType);
|
|
408
|
-
},
|
|
409
|
-
"editor.insertAtPos": (
|
|
410
|
-
_ctx,
|
|
411
|
-
text: string,
|
|
412
|
-
pos: number,
|
|
413
|
-
cursorPlaceHolder = false,
|
|
414
|
-
) => {
|
|
415
|
-
let cursorPlaceholderPos = -1;
|
|
416
|
-
if (cursorPlaceHolder) {
|
|
417
|
-
cursorPlaceholderPos = text.indexOf("|^|");
|
|
418
|
-
if (cursorPlaceholderPos !== -1) {
|
|
707
|
+
}
|
|
708
|
+
client.editorView.dispatch({
|
|
709
|
+
changes: {
|
|
710
|
+
insert: text,
|
|
711
|
+
from: pos,
|
|
712
|
+
},
|
|
713
|
+
});
|
|
714
|
+
if (cursorPlaceHolder) {
|
|
715
|
+
const cursorPos = pos + cursorPlaceholderPos;
|
|
716
|
+
client.editorView.dispatch({
|
|
717
|
+
selection: {
|
|
718
|
+
anchor: cursorPos,
|
|
719
|
+
},
|
|
720
|
+
effects: [EditorView.scrollIntoView(cursorPos)],
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
},
|
|
724
|
+
description:
|
|
725
|
+
"Inserts text at a character offset, optionally placing the cursor at a `|^|` marker.",
|
|
726
|
+
parameters: [
|
|
727
|
+
{ name: "text", type: "string", description: "The text to insert." },
|
|
728
|
+
{
|
|
729
|
+
name: "pos",
|
|
730
|
+
type: "number",
|
|
731
|
+
description: "The character offset at which to insert.",
|
|
732
|
+
},
|
|
733
|
+
{
|
|
734
|
+
name: "cursorPlaceHolder",
|
|
735
|
+
type: "boolean",
|
|
736
|
+
description:
|
|
737
|
+
"Whether to remove `|^|` and move the cursor to its position.",
|
|
738
|
+
optional: true,
|
|
739
|
+
},
|
|
740
|
+
],
|
|
741
|
+
},
|
|
742
|
+
"editor.replaceRange": {
|
|
743
|
+
callback: (
|
|
744
|
+
_ctx,
|
|
745
|
+
from: number,
|
|
746
|
+
to: number,
|
|
747
|
+
text: string,
|
|
748
|
+
cursorPlaceHolder = false,
|
|
749
|
+
) => {
|
|
750
|
+
let cursorPlaceholderPos = -1;
|
|
751
|
+
if (cursorPlaceHolder) {
|
|
752
|
+
cursorPlaceholderPos = text.indexOf("|^|");
|
|
419
753
|
text =
|
|
420
754
|
text.slice(0, cursorPlaceholderPos) +
|
|
421
755
|
text.slice(cursorPlaceholderPos + 3);
|
|
422
|
-
} else {
|
|
423
|
-
cursorPlaceHolder = false;
|
|
424
756
|
}
|
|
425
|
-
}
|
|
426
|
-
client.editorView.dispatch({
|
|
427
|
-
changes: {
|
|
428
|
-
insert: text,
|
|
429
|
-
from: pos,
|
|
430
|
-
},
|
|
431
|
-
});
|
|
432
|
-
if (cursorPlaceHolder) {
|
|
433
|
-
const cursorPos = pos + cursorPlaceholderPos;
|
|
434
757
|
client.editorView.dispatch({
|
|
435
|
-
|
|
436
|
-
|
|
758
|
+
changes: {
|
|
759
|
+
insert: text,
|
|
760
|
+
from: from,
|
|
761
|
+
to: to,
|
|
437
762
|
},
|
|
438
|
-
effects: [EditorView.scrollIntoView(cursorPos)],
|
|
439
763
|
});
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
764
|
+
if (cursorPlaceHolder) {
|
|
765
|
+
const cursorPos = from + cursorPlaceholderPos;
|
|
766
|
+
client.editorView.dispatch({
|
|
767
|
+
selection: {
|
|
768
|
+
anchor: cursorPos,
|
|
769
|
+
},
|
|
770
|
+
effects: [EditorView.scrollIntoView(cursorPos)],
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
},
|
|
774
|
+
description:
|
|
775
|
+
"Replaces a text range, optionally placing the cursor at a `|^|` marker in the replacement.",
|
|
776
|
+
parameters: [
|
|
777
|
+
{
|
|
778
|
+
name: "from",
|
|
779
|
+
type: "number",
|
|
780
|
+
description: "The start offset of the range.",
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
name: "to",
|
|
784
|
+
type: "number",
|
|
785
|
+
description: "The end offset of the range.",
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
name: "text",
|
|
789
|
+
type: "string",
|
|
790
|
+
description: "The replacement text.",
|
|
791
|
+
},
|
|
792
|
+
{
|
|
793
|
+
name: "cursorPlaceHolder",
|
|
794
|
+
type: "boolean",
|
|
795
|
+
description:
|
|
796
|
+
"Whether to remove `|^|` and move the cursor to its position.",
|
|
797
|
+
optional: true,
|
|
798
|
+
},
|
|
799
|
+
],
|
|
800
|
+
},
|
|
801
|
+
"editor.moveCursor": {
|
|
802
|
+
callback: (_ctx, pos: number, center = false) => {
|
|
803
|
+
// Always scroll into view so callers don't strand the cursor
|
|
804
|
+
// off-screen; `nearest` (default) is a no-op when already visible.
|
|
805
|
+
client.editorView.dispatch({
|
|
806
|
+
selection: { anchor: pos },
|
|
807
|
+
effects: [
|
|
808
|
+
EditorView.scrollIntoView(pos, center ? { y: "center" } : {}),
|
|
809
|
+
],
|
|
810
|
+
});
|
|
811
|
+
client.editorView.focus();
|
|
812
|
+
},
|
|
813
|
+
description:
|
|
814
|
+
"Moves and focuses the cursor at a character offset, scrolling it into view.",
|
|
815
|
+
parameters: [
|
|
816
|
+
{
|
|
817
|
+
name: "pos",
|
|
818
|
+
type: "number",
|
|
819
|
+
description: "The character offset to move to.",
|
|
820
|
+
},
|
|
821
|
+
{
|
|
822
|
+
name: "center",
|
|
823
|
+
type: "boolean",
|
|
824
|
+
description: "Whether to vertically center the cursor.",
|
|
825
|
+
optional: true,
|
|
826
|
+
},
|
|
827
|
+
],
|
|
828
|
+
},
|
|
829
|
+
"editor.moveCursorToLine": {
|
|
830
|
+
callback: (_ctx, line: number, column = 1, center = false) => {
|
|
831
|
+
// CodeMirror already keeps information about lines
|
|
832
|
+
const cmLine = client.editorView.state.doc.line(line);
|
|
833
|
+
// How much to move inside the line, column number starts from 1
|
|
834
|
+
const offset = Math.max(0, Math.min(cmLine.length, column - 1));
|
|
835
|
+
// Just reuse the implementation above
|
|
836
|
+
const moveCursor = syscalls["editor.moveCursor"];
|
|
837
|
+
const moveCursorCallback =
|
|
838
|
+
typeof moveCursor === "function" ? moveCursor : moveCursor.callback;
|
|
839
|
+
moveCursorCallback(_ctx, cmLine.from + offset, center);
|
|
840
|
+
},
|
|
841
|
+
description:
|
|
842
|
+
"Moves the cursor to a one-based line and column, clamping the column to the line length.",
|
|
843
|
+
parameters: [
|
|
844
|
+
{
|
|
845
|
+
name: "line",
|
|
846
|
+
type: "number",
|
|
847
|
+
description: "The one-based line number.",
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
name: "column",
|
|
851
|
+
type: "number",
|
|
852
|
+
description: "The one-based column number.",
|
|
853
|
+
optional: true,
|
|
854
|
+
},
|
|
855
|
+
{
|
|
856
|
+
name: "center",
|
|
857
|
+
type: "boolean",
|
|
858
|
+
description: "Whether to vertically center the cursor.",
|
|
859
|
+
optional: true,
|
|
860
|
+
},
|
|
861
|
+
],
|
|
862
|
+
},
|
|
863
|
+
"editor.setSelection": {
|
|
864
|
+
callback: (_ctx, from: number, to: number) => {
|
|
465
865
|
client.editorView.dispatch({
|
|
466
866
|
selection: {
|
|
467
|
-
anchor:
|
|
867
|
+
anchor: from,
|
|
868
|
+
head: to,
|
|
468
869
|
},
|
|
469
|
-
effects: [EditorView.scrollIntoView(cursorPos)],
|
|
470
870
|
});
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
_ctx,
|
|
486
|
-
line: number,
|
|
487
|
-
column = 1,
|
|
488
|
-
center = false,
|
|
489
|
-
) => {
|
|
490
|
-
// CodeMirror already keeps information about lines
|
|
491
|
-
const cmLine = client.editorView.state.doc.line(line);
|
|
492
|
-
// How much to move inside the line, column number starts from 1
|
|
493
|
-
const offset = Math.max(0, Math.min(cmLine.length, column - 1));
|
|
494
|
-
// Just reuse the implementation above
|
|
495
|
-
syscalls["editor.moveCursor"](_ctx, cmLine.from + offset, center);
|
|
496
|
-
},
|
|
497
|
-
"editor.setSelection": (_ctx, from: number, to: number) => {
|
|
498
|
-
client.editorView.dispatch({
|
|
499
|
-
selection: {
|
|
500
|
-
anchor: from,
|
|
501
|
-
head: to,
|
|
502
|
-
},
|
|
503
|
-
});
|
|
871
|
+
},
|
|
872
|
+
description: "Sets the main editor selection to a character range.",
|
|
873
|
+
parameters: [
|
|
874
|
+
{
|
|
875
|
+
name: "from",
|
|
876
|
+
type: "number",
|
|
877
|
+
description: "The selection anchor offset.",
|
|
878
|
+
},
|
|
879
|
+
{
|
|
880
|
+
name: "to",
|
|
881
|
+
type: "number",
|
|
882
|
+
description: "The selection head offset.",
|
|
883
|
+
},
|
|
884
|
+
],
|
|
504
885
|
},
|
|
505
886
|
|
|
506
|
-
"editor.insertAtCursor":
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
text
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
},
|
|
555
|
-
"editor.
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
887
|
+
"editor.insertAtCursor": {
|
|
888
|
+
callback: (
|
|
889
|
+
_ctx,
|
|
890
|
+
text: string,
|
|
891
|
+
scrollIntoView = false,
|
|
892
|
+
cursorPlaceHolder = false,
|
|
893
|
+
) => {
|
|
894
|
+
const editorView = client.editorView;
|
|
895
|
+
const from = editorView.state.selection.main.from;
|
|
896
|
+
const cursorPlaceholderPos = text.indexOf("|^|");
|
|
897
|
+
if (cursorPlaceHolder && cursorPlaceholderPos !== -1) {
|
|
898
|
+
text =
|
|
899
|
+
text.slice(0, cursorPlaceholderPos) +
|
|
900
|
+
text.slice(cursorPlaceholderPos + 3);
|
|
901
|
+
} else {
|
|
902
|
+
cursorPlaceHolder = false;
|
|
903
|
+
}
|
|
904
|
+
editorView.dispatch({
|
|
905
|
+
changes: {
|
|
906
|
+
insert: text,
|
|
907
|
+
from: from,
|
|
908
|
+
},
|
|
909
|
+
selection: {
|
|
910
|
+
anchor: cursorPlaceHolder
|
|
911
|
+
? from + cursorPlaceholderPos
|
|
912
|
+
: from + text.length,
|
|
913
|
+
},
|
|
914
|
+
scrollIntoView,
|
|
915
|
+
});
|
|
916
|
+
},
|
|
917
|
+
description:
|
|
918
|
+
"Inserts text at the cursor and moves the cursor after it or to an optional `|^|` marker.",
|
|
919
|
+
parameters: [
|
|
920
|
+
{ name: "text", type: "string", description: "The text to insert." },
|
|
921
|
+
{
|
|
922
|
+
name: "scrollIntoView",
|
|
923
|
+
type: "boolean",
|
|
924
|
+
description: "Whether to scroll the new cursor position into view.",
|
|
925
|
+
optional: true,
|
|
926
|
+
},
|
|
927
|
+
{
|
|
928
|
+
name: "cursorPlaceHolder",
|
|
929
|
+
type: "boolean",
|
|
930
|
+
description:
|
|
931
|
+
"Whether to remove `|^|` and move the cursor to its position.",
|
|
932
|
+
optional: true,
|
|
933
|
+
},
|
|
934
|
+
],
|
|
935
|
+
},
|
|
936
|
+
"editor.dispatch": {
|
|
937
|
+
callback: (_ctx, change: Transaction) => {
|
|
938
|
+
client.editorView.dispatch(change);
|
|
939
|
+
},
|
|
940
|
+
description: "Dispatches a CodeMirror transaction to the editor view.",
|
|
941
|
+
parameters: [
|
|
942
|
+
{
|
|
943
|
+
name: "change",
|
|
944
|
+
type: "Transaction",
|
|
945
|
+
description: "The CodeMirror transaction to dispatch.",
|
|
946
|
+
},
|
|
947
|
+
],
|
|
948
|
+
},
|
|
949
|
+
"editor.prompt": {
|
|
950
|
+
callback: (
|
|
951
|
+
_ctx,
|
|
952
|
+
message: string,
|
|
953
|
+
defaultValue = "",
|
|
954
|
+
): Promise<string | undefined> => {
|
|
955
|
+
return client.ui.prompt(message, defaultValue);
|
|
956
|
+
},
|
|
957
|
+
description: "Prompts the user for text input.",
|
|
958
|
+
parameters: [
|
|
959
|
+
{
|
|
960
|
+
name: "message",
|
|
961
|
+
type: "string",
|
|
962
|
+
description: "The prompt message.",
|
|
963
|
+
},
|
|
964
|
+
{
|
|
965
|
+
name: "defaultValue",
|
|
966
|
+
type: "string",
|
|
967
|
+
description: "The initial input value.",
|
|
968
|
+
optional: true,
|
|
969
|
+
},
|
|
970
|
+
],
|
|
971
|
+
returns: [
|
|
972
|
+
{
|
|
973
|
+
type: "string | undefined",
|
|
974
|
+
description: "The entered text, or undefined if dismissed.",
|
|
975
|
+
},
|
|
976
|
+
],
|
|
977
|
+
},
|
|
978
|
+
"editor.confirm": {
|
|
979
|
+
callback: (
|
|
980
|
+
_ctx,
|
|
981
|
+
message: string,
|
|
982
|
+
options?: { destructive?: boolean },
|
|
983
|
+
): Promise<boolean> => {
|
|
984
|
+
return client.ui.confirm(message, options);
|
|
985
|
+
},
|
|
986
|
+
description: "Prompts the user to confirm or cancel an action.",
|
|
987
|
+
parameters: [
|
|
988
|
+
{
|
|
989
|
+
name: "message",
|
|
990
|
+
type: "string",
|
|
991
|
+
description: "The confirmation message.",
|
|
992
|
+
},
|
|
993
|
+
{
|
|
994
|
+
name: "options",
|
|
995
|
+
type: "{ destructive?: boolean }",
|
|
996
|
+
description: "Optional dialog styling settings.",
|
|
997
|
+
optional: true,
|
|
998
|
+
},
|
|
999
|
+
],
|
|
1000
|
+
returns: [
|
|
1001
|
+
{ type: "boolean", description: "Whether the user confirmed." },
|
|
1002
|
+
],
|
|
1003
|
+
},
|
|
1004
|
+
"editor.alert": {
|
|
1005
|
+
callback: (_ctx, message: string) => {
|
|
1006
|
+
alert(message);
|
|
1007
|
+
},
|
|
1008
|
+
description: "Shows a browser alert dialog.",
|
|
1009
|
+
parameters: [
|
|
1010
|
+
{
|
|
1011
|
+
name: "message",
|
|
1012
|
+
type: "string",
|
|
1013
|
+
description: "The alert message.",
|
|
1014
|
+
},
|
|
1015
|
+
],
|
|
1016
|
+
},
|
|
1017
|
+
"editor.getUiOption": {
|
|
1018
|
+
callback: (_ctx, key: string): any => {
|
|
1019
|
+
return (client.ui.viewState.uiOptions as any)[key];
|
|
1020
|
+
},
|
|
1021
|
+
description: "Returns the current value of an editor UI option.",
|
|
1022
|
+
parameters: [
|
|
1023
|
+
{ name: "key", type: "string", description: "The UI option key." },
|
|
1024
|
+
],
|
|
1025
|
+
returns: [{ type: "any", description: "The option value." }],
|
|
1026
|
+
},
|
|
1027
|
+
"editor.setUiOption": {
|
|
1028
|
+
callback: (_ctx, key: string, value: any) => {
|
|
1029
|
+
client.ui.viewDispatch({
|
|
1030
|
+
type: "set-ui-option",
|
|
1031
|
+
key,
|
|
1032
|
+
value,
|
|
1033
|
+
});
|
|
1034
|
+
void client.reloadEditor();
|
|
1035
|
+
},
|
|
1036
|
+
description: "Sets an editor UI option and reloads the editor.",
|
|
1037
|
+
parameters: [
|
|
1038
|
+
{ name: "key", type: "string", description: "The UI option key." },
|
|
1039
|
+
{ name: "value", type: "any", description: "The option value." },
|
|
1040
|
+
],
|
|
1041
|
+
},
|
|
1042
|
+
"editor.vimEx": {
|
|
1043
|
+
callback: (_ctx, exCommand: string) => {
|
|
1044
|
+
const vimMod = getVimModule();
|
|
1045
|
+
if (!vimMod) {
|
|
1046
|
+
throw new Error("Vim module not loaded.");
|
|
1047
|
+
}
|
|
1048
|
+
const cm = vimMod.getCM(client.editorView);
|
|
1049
|
+
if (cm?.state.vim) {
|
|
1050
|
+
return vimMod.Vim.handleEx(cm as any, exCommand);
|
|
609
1051
|
} else {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
1052
|
+
throw new Error("Vim mode not active or not initialized.");
|
|
1053
|
+
}
|
|
1054
|
+
},
|
|
1055
|
+
description: "Executes a Vim Ex command in the active Vim-mode editor.",
|
|
1056
|
+
parameters: [
|
|
1057
|
+
{
|
|
1058
|
+
name: "exCommand",
|
|
1059
|
+
type: "string",
|
|
1060
|
+
description: "The Ex command to execute.",
|
|
1061
|
+
},
|
|
1062
|
+
],
|
|
1063
|
+
},
|
|
1064
|
+
"editor.configureVimMode": {
|
|
1065
|
+
callback: () => {
|
|
1066
|
+
const vimMod = getVimModule();
|
|
1067
|
+
if (!vimMod) {
|
|
1068
|
+
throw new Error("Vim module not loaded.");
|
|
1069
|
+
}
|
|
1070
|
+
const { Vim } = vimMod;
|
|
1071
|
+
// Override the default "o" binding to be more intelligent and follow the markdown editor's behavior
|
|
1072
|
+
Vim.mapCommand("o", "action", "newline-continue-markup", {}, {});
|
|
1073
|
+
Vim.mapCommand("O", "action", "back-newline-continue-markup", {}, {});
|
|
1074
|
+
Vim.unmap("<C-q>", undefined as any);
|
|
1075
|
+
Vim.defineAction("newline-continue-markup", (cm) => {
|
|
1076
|
+
// Append at end of line
|
|
614
1077
|
Vim.handleKey(cm, "A", "+input");
|
|
615
|
-
// Insert
|
|
1078
|
+
// Insert newline continuing markup where appropriate
|
|
616
1079
|
insertNewlineContinueMarkup(client.editorView) ||
|
|
617
1080
|
insertNewlineAndIndent(client.editorView);
|
|
618
|
-
}
|
|
619
|
-
|
|
1081
|
+
});
|
|
1082
|
+
Vim.defineAction("back-newline-continue-markup", (cm) => {
|
|
1083
|
+
// Determine current line
|
|
1084
|
+
const pos = client.editorView.state.selection.main.from;
|
|
1085
|
+
const line = client.editorView.state.doc.lineAt(pos).number;
|
|
1086
|
+
if (line === 1) {
|
|
1087
|
+
// We're on the top line
|
|
1088
|
+
// Go to 0:0
|
|
1089
|
+
Vim.handleKey(cm, "0", "+input");
|
|
1090
|
+
// Insert a newline
|
|
1091
|
+
insertNewline(client.editorView);
|
|
1092
|
+
// Go up to the new line
|
|
1093
|
+
Vim.handleKey(cm, "k", "+input");
|
|
1094
|
+
// Into insert mode
|
|
1095
|
+
Vim.handleKey(cm, "i", "+input");
|
|
1096
|
+
} else {
|
|
1097
|
+
// We're elsewhere in the document
|
|
1098
|
+
// Go up
|
|
1099
|
+
Vim.handleKey(cm, "k", "+input");
|
|
1100
|
+
// Append mode at the end of the line
|
|
1101
|
+
Vim.handleKey(cm, "A", "+input");
|
|
1102
|
+
// Insert a newline using the continue markup thing
|
|
1103
|
+
insertNewlineContinueMarkup(client.editorView) ||
|
|
1104
|
+
insertNewlineAndIndent(client.editorView);
|
|
1105
|
+
}
|
|
1106
|
+
});
|
|
620
1107
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
1108
|
+
// Load the config if any
|
|
1109
|
+
const config = client.config.get<VimConfig>("vim", {});
|
|
1110
|
+
if (config) {
|
|
1111
|
+
config.unmap?.forEach((binding) => {
|
|
1112
|
+
if (typeof binding === "string") {
|
|
1113
|
+
console.log(`Unmapping ${binding}`);
|
|
1114
|
+
// @ts-expect-error: unmap expects a string for the mode, this is problematic with Ex mappings which requires undefined or false
|
|
1115
|
+
Vim.unmap(binding, undefined);
|
|
1116
|
+
} else if (binding.key) {
|
|
1117
|
+
console.log(
|
|
1118
|
+
`Unmapping ${binding.key} in ${binding.mode ?? "normal"}`,
|
|
1119
|
+
);
|
|
1120
|
+
Vim.unmap(binding.key, binding.mode ?? "normal");
|
|
1121
|
+
}
|
|
1122
|
+
});
|
|
1123
|
+
config.map?.forEach(({ map, to, mode }) => {
|
|
1124
|
+
console.log(`Mapping ${map} to ${to} for ${mode ?? "normal"}`);
|
|
1125
|
+
Vim.map(map, to, mode ?? "normal");
|
|
1126
|
+
});
|
|
1127
|
+
config.noremap?.forEach(({ map, to, mode }) => {
|
|
1128
|
+
console.log(`Noremapping ${map} to ${to} for ${mode ?? "normal"}`);
|
|
1129
|
+
Vim.noremap(map, to, mode ?? "normal");
|
|
1130
|
+
});
|
|
1131
|
+
config.commands?.forEach(({ ex, command }) => {
|
|
1132
|
+
console.log(`Mapping command '${command}' to Ex ${ex}`);
|
|
1133
|
+
Vim.defineEx(ex, "", (_, params) =>
|
|
1134
|
+
client.runCommandByName(command, params.args),
|
|
632
1135
|
);
|
|
633
|
-
|
|
634
|
-
|
|
1136
|
+
});
|
|
1137
|
+
} else {
|
|
1138
|
+
console.log("No vim config found");
|
|
1139
|
+
}
|
|
1140
|
+
},
|
|
1141
|
+
description:
|
|
1142
|
+
"Configures CodeMirror Vim mode from the current SilverBullet Vim settings.",
|
|
1143
|
+
},
|
|
1144
|
+
"editor.openPageNavigator": {
|
|
1145
|
+
callback: (_ctx, mode: "page" | "meta" | "document" | "all" = "page") => {
|
|
1146
|
+
client.startPageNavigate(mode);
|
|
1147
|
+
},
|
|
1148
|
+
description: "Opens the page navigator in the requested browsing mode.",
|
|
1149
|
+
parameters: [
|
|
1150
|
+
{
|
|
1151
|
+
name: "mode",
|
|
1152
|
+
type: "page | meta | document | all",
|
|
1153
|
+
description: "The navigator mode.",
|
|
1154
|
+
optional: true,
|
|
1155
|
+
},
|
|
1156
|
+
],
|
|
1157
|
+
},
|
|
1158
|
+
"editor.openCommandPalette": {
|
|
1159
|
+
callback: () => {
|
|
1160
|
+
void client.startCommandPalette();
|
|
1161
|
+
},
|
|
1162
|
+
description: "Opens the command palette.",
|
|
1163
|
+
},
|
|
1164
|
+
"editor.deleteLine": {
|
|
1165
|
+
callback: () => {
|
|
1166
|
+
deleteLine(client.editorView);
|
|
1167
|
+
},
|
|
1168
|
+
description:
|
|
1169
|
+
"Deletes the current line or the lines touched by the selection.",
|
|
1170
|
+
},
|
|
1171
|
+
"editor.selectAll": {
|
|
1172
|
+
callback: () => {
|
|
1173
|
+
return selectAll({
|
|
1174
|
+
state: client.editorView.state,
|
|
1175
|
+
dispatch: client.editorView.dispatch,
|
|
1176
|
+
});
|
|
1177
|
+
},
|
|
1178
|
+
description: "Selects the entire editor document.",
|
|
1179
|
+
},
|
|
1180
|
+
"editor.indentMore": {
|
|
1181
|
+
callback: () => {
|
|
1182
|
+
return indentMore({
|
|
1183
|
+
state: client.editorView.state,
|
|
1184
|
+
dispatch: client.editorView.dispatch,
|
|
635
1185
|
});
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
1186
|
+
},
|
|
1187
|
+
description: "Increases indentation for the current line or selection.",
|
|
1188
|
+
},
|
|
1189
|
+
"editor.indentLess": {
|
|
1190
|
+
callback: () => {
|
|
1191
|
+
return indentLess({
|
|
1192
|
+
state: client.editorView.state,
|
|
1193
|
+
dispatch: client.editorView.dispatch,
|
|
639
1194
|
});
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
1195
|
+
},
|
|
1196
|
+
description: "Decreases indentation for the current line or selection.",
|
|
1197
|
+
},
|
|
1198
|
+
"editor.toggleComment": {
|
|
1199
|
+
callback: () => {
|
|
1200
|
+
return toggleComment({
|
|
1201
|
+
state: client.editorView.state,
|
|
1202
|
+
dispatch: client.editorView.dispatch,
|
|
643
1203
|
});
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
1204
|
+
},
|
|
1205
|
+
description: "Comments or uncomments the current line or selection.",
|
|
1206
|
+
},
|
|
1207
|
+
"editor.moveLineUp": {
|
|
1208
|
+
callback: () => {
|
|
1209
|
+
return moveLineUp({
|
|
1210
|
+
state: client.editorView.state,
|
|
1211
|
+
dispatch: client.editorView.dispatch,
|
|
649
1212
|
});
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
void client.startCommandPalette();
|
|
662
|
-
},
|
|
663
|
-
"editor.deleteLine": () => {
|
|
664
|
-
deleteLine(client.editorView);
|
|
665
|
-
},
|
|
666
|
-
"editor.selectAll": () => {
|
|
667
|
-
return selectAll({
|
|
668
|
-
state: client.editorView.state,
|
|
669
|
-
dispatch: client.editorView.dispatch,
|
|
670
|
-
});
|
|
671
|
-
},
|
|
672
|
-
"editor.indentMore": () => {
|
|
673
|
-
return indentMore({
|
|
674
|
-
state: client.editorView.state,
|
|
675
|
-
dispatch: client.editorView.dispatch,
|
|
676
|
-
});
|
|
677
|
-
},
|
|
678
|
-
"editor.indentLess": () => {
|
|
679
|
-
return indentLess({
|
|
680
|
-
state: client.editorView.state,
|
|
681
|
-
dispatch: client.editorView.dispatch,
|
|
682
|
-
});
|
|
683
|
-
},
|
|
684
|
-
"editor.toggleComment": () => {
|
|
685
|
-
return toggleComment({
|
|
686
|
-
state: client.editorView.state,
|
|
687
|
-
dispatch: client.editorView.dispatch,
|
|
688
|
-
});
|
|
689
|
-
},
|
|
690
|
-
"editor.moveLineUp": () => {
|
|
691
|
-
return moveLineUp({
|
|
692
|
-
state: client.editorView.state,
|
|
693
|
-
dispatch: client.editorView.dispatch,
|
|
694
|
-
});
|
|
695
|
-
},
|
|
696
|
-
"editor.moveLineDown": () => {
|
|
697
|
-
return moveLineDown({
|
|
698
|
-
state: client.editorView.state,
|
|
699
|
-
dispatch: client.editorView.dispatch,
|
|
700
|
-
});
|
|
1213
|
+
},
|
|
1214
|
+
description: "Moves the current line or selected lines upward.",
|
|
1215
|
+
},
|
|
1216
|
+
"editor.moveLineDown": {
|
|
1217
|
+
callback: () => {
|
|
1218
|
+
return moveLineDown({
|
|
1219
|
+
state: client.editorView.state,
|
|
1220
|
+
dispatch: client.editorView.dispatch,
|
|
1221
|
+
});
|
|
1222
|
+
},
|
|
1223
|
+
description: "Moves the current line or selected lines downward.",
|
|
701
1224
|
},
|
|
702
1225
|
// Folding
|
|
703
|
-
"editor.fold":
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
},
|
|
709
|
-
"editor.
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
},
|
|
715
|
-
"editor.
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
},
|
|
721
|
-
"editor.
|
|
722
|
-
|
|
1226
|
+
"editor.fold": {
|
|
1227
|
+
callback: () => {
|
|
1228
|
+
foldCode(client.editorView);
|
|
1229
|
+
},
|
|
1230
|
+
description: "Folds the code or markup region at the cursor.",
|
|
1231
|
+
},
|
|
1232
|
+
"editor.unfold": {
|
|
1233
|
+
callback: () => {
|
|
1234
|
+
unfoldCode(client.editorView);
|
|
1235
|
+
},
|
|
1236
|
+
description: "Unfolds the folded region at the cursor.",
|
|
1237
|
+
},
|
|
1238
|
+
"editor.toggleFold": {
|
|
1239
|
+
callback: () => {
|
|
1240
|
+
toggleFold(client.editorView);
|
|
1241
|
+
},
|
|
1242
|
+
description: "Toggles folding for the region at the cursor.",
|
|
1243
|
+
},
|
|
1244
|
+
"editor.foldAll": {
|
|
1245
|
+
callback: () => {
|
|
1246
|
+
foldAll(client.editorView);
|
|
1247
|
+
},
|
|
1248
|
+
description: "Folds all foldable regions in the editor.",
|
|
1249
|
+
},
|
|
1250
|
+
"editor.unfoldAll": {
|
|
1251
|
+
callback: () => {
|
|
1252
|
+
unfoldAll(client.editorView);
|
|
1253
|
+
},
|
|
1254
|
+
description: "Unfolds all folded regions in the editor.",
|
|
1255
|
+
},
|
|
1256
|
+
"editor.undo": {
|
|
1257
|
+
callback: () => {
|
|
1258
|
+
return undo(client.editorView);
|
|
1259
|
+
},
|
|
1260
|
+
description: "Undoes the most recent editor change.",
|
|
1261
|
+
},
|
|
1262
|
+
"editor.redo": {
|
|
1263
|
+
callback: () => {
|
|
1264
|
+
return redo(client.editorView);
|
|
1265
|
+
},
|
|
1266
|
+
description: "Redoes the most recently undone editor change.",
|
|
723
1267
|
},
|
|
724
1268
|
// Cursor motion syscalls
|
|
725
|
-
"editor.cursorCharLeft":
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
"editor.
|
|
736
|
-
|
|
1269
|
+
"editor.cursorCharLeft": {
|
|
1270
|
+
callback: () => cursorCharLeft(client.editorView),
|
|
1271
|
+
description:
|
|
1272
|
+
"Moves the cursor one character left, respecting bidirectional text.",
|
|
1273
|
+
},
|
|
1274
|
+
"editor.cursorCharRight": {
|
|
1275
|
+
callback: () => cursorCharRight(client.editorView),
|
|
1276
|
+
description:
|
|
1277
|
+
"Moves the cursor one character right, respecting bidirectional text.",
|
|
1278
|
+
},
|
|
1279
|
+
"editor.cursorGroupLeft": {
|
|
1280
|
+
callback: () => cursorGroupLeft(client.editorView),
|
|
1281
|
+
description: "Moves the cursor left by one character group or word.",
|
|
1282
|
+
},
|
|
1283
|
+
"editor.cursorGroupRight": {
|
|
1284
|
+
callback: () => cursorGroupRight(client.editorView),
|
|
1285
|
+
description: "Moves the cursor right by one character group or word.",
|
|
1286
|
+
},
|
|
1287
|
+
"editor.cursorLineBoundaryLeft": {
|
|
1288
|
+
callback: () => cursorLineBoundaryLeft(client.editorView),
|
|
1289
|
+
description:
|
|
1290
|
+
"Moves the cursor to the left visual boundary of the current line.",
|
|
1291
|
+
},
|
|
1292
|
+
"editor.cursorLineBoundaryRight": {
|
|
1293
|
+
callback: () => cursorLineBoundaryRight(client.editorView),
|
|
1294
|
+
description:
|
|
1295
|
+
"Moves the cursor to the right visual boundary of the current line.",
|
|
1296
|
+
},
|
|
1297
|
+
"editor.cursorLineStart": {
|
|
1298
|
+
callback: () => cursorLineStart(client.editorView),
|
|
1299
|
+
description: "Moves the cursor to the start of the current logical line.",
|
|
1300
|
+
},
|
|
1301
|
+
"editor.cursorLineEnd": {
|
|
1302
|
+
callback: () => cursorLineEnd(client.editorView),
|
|
1303
|
+
description: "Moves the cursor to the end of the current logical line.",
|
|
1304
|
+
},
|
|
1305
|
+
"editor.cursorDocStart": {
|
|
1306
|
+
callback: () => cursorDocStart(client.editorView),
|
|
1307
|
+
description: "Moves the cursor to the start of the document.",
|
|
1308
|
+
},
|
|
1309
|
+
"editor.cursorDocEnd": {
|
|
1310
|
+
callback: () => cursorDocEnd(client.editorView),
|
|
1311
|
+
description: "Moves the cursor to the end of the document.",
|
|
1312
|
+
},
|
|
737
1313
|
// Cursor motions that also navigate the completion popup if it's open
|
|
738
|
-
"editor.cursorLineUp":
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
1314
|
+
"editor.cursorLineUp": {
|
|
1315
|
+
callback: () => {
|
|
1316
|
+
const view = client.editorView;
|
|
1317
|
+
if (moveCompletionSelection(false)(view)) return true;
|
|
1318
|
+
return cursorLineUp(view);
|
|
1319
|
+
},
|
|
1320
|
+
description:
|
|
1321
|
+
"Moves completion selection up when open, otherwise moves the cursor up one visual line.",
|
|
1322
|
+
},
|
|
1323
|
+
"editor.cursorLineDown": {
|
|
1324
|
+
callback: () => {
|
|
1325
|
+
const view = client.editorView;
|
|
1326
|
+
if (moveCompletionSelection(true)(view)) return true;
|
|
1327
|
+
return cursorLineDown(view);
|
|
1328
|
+
},
|
|
1329
|
+
description:
|
|
1330
|
+
"Moves completion selection down when open, otherwise moves the cursor down one visual line.",
|
|
1331
|
+
},
|
|
1332
|
+
"editor.cursorPageUp": {
|
|
1333
|
+
callback: () => {
|
|
1334
|
+
const view = client.editorView;
|
|
1335
|
+
if (moveCompletionSelection(false, "page")(view)) return true;
|
|
1336
|
+
return cursorPageUp(view);
|
|
1337
|
+
},
|
|
1338
|
+
description:
|
|
1339
|
+
"Moves completion selection up one page when open, otherwise moves the cursor up one viewport page.",
|
|
1340
|
+
},
|
|
1341
|
+
"editor.cursorPageDown": {
|
|
1342
|
+
callback: () => {
|
|
1343
|
+
const view = client.editorView;
|
|
1344
|
+
if (moveCompletionSelection(true, "page")(view)) return true;
|
|
1345
|
+
return cursorPageDown(view);
|
|
1346
|
+
},
|
|
1347
|
+
description:
|
|
1348
|
+
"Moves completion selection down one page when open, otherwise moves the cursor down one viewport page.",
|
|
757
1349
|
},
|
|
758
1350
|
// Selection-extending motions
|
|
759
|
-
"editor.selectCharLeft":
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
"editor.
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
"editor.
|
|
774
|
-
|
|
1351
|
+
"editor.selectCharLeft": {
|
|
1352
|
+
callback: () => selectCharLeft(client.editorView),
|
|
1353
|
+
description:
|
|
1354
|
+
"Extends the selection one character left, respecting bidirectional text.",
|
|
1355
|
+
},
|
|
1356
|
+
"editor.selectCharRight": {
|
|
1357
|
+
callback: () => selectCharRight(client.editorView),
|
|
1358
|
+
description:
|
|
1359
|
+
"Extends the selection one character right, respecting bidirectional text.",
|
|
1360
|
+
},
|
|
1361
|
+
"editor.selectGroupLeft": {
|
|
1362
|
+
callback: () => selectGroupLeft(client.editorView),
|
|
1363
|
+
description: "Extends the selection left by one character group or word.",
|
|
1364
|
+
},
|
|
1365
|
+
"editor.selectGroupRight": {
|
|
1366
|
+
callback: () => selectGroupRight(client.editorView),
|
|
1367
|
+
description:
|
|
1368
|
+
"Extends the selection right by one character group or word.",
|
|
1369
|
+
},
|
|
1370
|
+
"editor.selectLineBoundaryLeft": {
|
|
1371
|
+
callback: () => selectLineBoundaryLeft(client.editorView),
|
|
1372
|
+
description:
|
|
1373
|
+
"Extends the selection to the left visual boundary of the current line.",
|
|
1374
|
+
},
|
|
1375
|
+
"editor.selectLineBoundaryRight": {
|
|
1376
|
+
callback: () => selectLineBoundaryRight(client.editorView),
|
|
1377
|
+
description:
|
|
1378
|
+
"Extends the selection to the right visual boundary of the current line.",
|
|
1379
|
+
},
|
|
1380
|
+
"editor.selectLineStart": {
|
|
1381
|
+
callback: () => selectLineStart(client.editorView),
|
|
1382
|
+
description:
|
|
1383
|
+
"Extends the selection to the start of the current logical line.",
|
|
1384
|
+
},
|
|
1385
|
+
"editor.selectLineEnd": {
|
|
1386
|
+
callback: () => selectLineEnd(client.editorView),
|
|
1387
|
+
description:
|
|
1388
|
+
"Extends the selection to the end of the current logical line.",
|
|
1389
|
+
},
|
|
1390
|
+
"editor.selectDocStart": {
|
|
1391
|
+
callback: () => selectDocStart(client.editorView),
|
|
1392
|
+
description: "Extends the selection to the start of the document.",
|
|
1393
|
+
},
|
|
1394
|
+
"editor.selectDocEnd": {
|
|
1395
|
+
callback: () => selectDocEnd(client.editorView),
|
|
1396
|
+
description: "Extends the selection to the end of the document.",
|
|
1397
|
+
},
|
|
1398
|
+
"editor.selectLineUp": {
|
|
1399
|
+
callback: () => selectLineUp(client.editorView),
|
|
1400
|
+
description: "Extends the selection upward by one visual line.",
|
|
1401
|
+
},
|
|
1402
|
+
"editor.selectLineDown": {
|
|
1403
|
+
callback: () => selectLineDown(client.editorView),
|
|
1404
|
+
description: "Extends the selection downward by one visual line.",
|
|
1405
|
+
},
|
|
1406
|
+
"editor.selectPageUp": {
|
|
1407
|
+
callback: () => selectPageUp(client.editorView),
|
|
1408
|
+
description: "Extends the selection upward by one viewport page.",
|
|
1409
|
+
},
|
|
1410
|
+
"editor.selectPageDown": {
|
|
1411
|
+
callback: () => selectPageDown(client.editorView),
|
|
1412
|
+
description: "Extends the selection downward by one viewport page.",
|
|
1413
|
+
},
|
|
775
1414
|
// Delete
|
|
776
|
-
"editor.deleteCharBackward":
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
"editor.
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
"editor.
|
|
1415
|
+
"editor.deleteCharBackward": {
|
|
1416
|
+
callback: () => deleteCharBackward(client.editorView),
|
|
1417
|
+
description: "Deletes the selection or the character before the cursor.",
|
|
1418
|
+
},
|
|
1419
|
+
"editor.deleteCharForward": {
|
|
1420
|
+
callback: () => deleteCharForward(client.editorView),
|
|
1421
|
+
description: "Deletes the selection or the character after the cursor.",
|
|
1422
|
+
},
|
|
1423
|
+
"editor.deleteGroupBackward": {
|
|
1424
|
+
callback: () => deleteGroupBackward(client.editorView),
|
|
1425
|
+
description:
|
|
1426
|
+
"Deletes the selection or the character group before the cursor.",
|
|
1427
|
+
},
|
|
1428
|
+
"editor.deleteGroupForward": {
|
|
1429
|
+
callback: () => deleteGroupForward(client.editorView),
|
|
1430
|
+
description:
|
|
1431
|
+
"Deletes the selection or the character group after the cursor.",
|
|
1432
|
+
},
|
|
1433
|
+
"editor.deleteLineBoundaryBackward": {
|
|
1434
|
+
callback: () => deleteLineBoundaryBackward(client.editorView),
|
|
1435
|
+
description:
|
|
1436
|
+
"Deletes the selection or text back to the current line boundary.",
|
|
1437
|
+
},
|
|
1438
|
+
"editor.deleteLineBoundaryForward": {
|
|
1439
|
+
callback: () => deleteLineBoundaryForward(client.editorView),
|
|
1440
|
+
description:
|
|
1441
|
+
"Deletes the selection or text forward to the current line boundary.",
|
|
1442
|
+
},
|
|
1443
|
+
"editor.transposeChars": {
|
|
1444
|
+
callback: () => transposeChars(client.editorView),
|
|
1445
|
+
description: "Transposes the characters around the cursor.",
|
|
1446
|
+
},
|
|
785
1447
|
// Enter: accept completion if popup is open, else newline-and-indent
|
|
786
|
-
"editor.insertNewline":
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
1448
|
+
"editor.insertNewline": {
|
|
1449
|
+
callback: () => {
|
|
1450
|
+
const view = client.editorView;
|
|
1451
|
+
if (acceptCompletion(view)) return true;
|
|
1452
|
+
return insertNewlineAndIndent(view);
|
|
1453
|
+
},
|
|
1454
|
+
description:
|
|
1455
|
+
"Accepts the active completion, or inserts a newline with appropriate indentation.",
|
|
790
1456
|
},
|
|
791
1457
|
// Completion popup control
|
|
792
|
-
"editor.acceptCompletion":
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
1458
|
+
"editor.acceptCompletion": {
|
|
1459
|
+
callback: () => acceptCompletion(client.editorView),
|
|
1460
|
+
description:
|
|
1461
|
+
"Accepts the currently selected completion when the completion popup is active.",
|
|
1462
|
+
returns: [
|
|
1463
|
+
{
|
|
1464
|
+
type: "boolean",
|
|
1465
|
+
description: "Whether an active completion was accepted.",
|
|
1466
|
+
},
|
|
1467
|
+
],
|
|
1468
|
+
},
|
|
1469
|
+
"editor.startCompletion": {
|
|
1470
|
+
callback: () => startCompletion(client.editorView),
|
|
1471
|
+
description: "Explicitly starts editor completion at the cursor.",
|
|
1472
|
+
},
|
|
1473
|
+
"editor.closeCompletion": {
|
|
1474
|
+
callback: () => closeCompletion(client.editorView),
|
|
1475
|
+
description: "Closes the active editor completion popup.",
|
|
1476
|
+
},
|
|
1477
|
+
"editor.openSearchPanel": {
|
|
1478
|
+
callback: () => {
|
|
1479
|
+
openSearchPanel(client.editorView);
|
|
1480
|
+
},
|
|
1481
|
+
description: "Opens the editor's native search panel.",
|
|
1482
|
+
},
|
|
1483
|
+
"editor.copyToClipboard": {
|
|
1484
|
+
callback: async (_ctx, data: string | Blob) => {
|
|
1485
|
+
try {
|
|
1486
|
+
if (typeof data === "string") {
|
|
1487
|
+
await navigator.clipboard.writeText(data);
|
|
1488
|
+
} else {
|
|
1489
|
+
await navigator.clipboard.write([
|
|
1490
|
+
new ClipboardItem({ [data.type]: data }),
|
|
1491
|
+
]);
|
|
1492
|
+
}
|
|
1493
|
+
} catch (e) {
|
|
1494
|
+
console.error(e);
|
|
1495
|
+
client.ui.flashNotification(`Could not copy to clipboard: ${e}`);
|
|
806
1496
|
}
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
1497
|
+
},
|
|
1498
|
+
description:
|
|
1499
|
+
"Copies text or binary Blob data to the system clipboard. Clipboard access requires a secure HTTPS context.",
|
|
1500
|
+
parameters: [
|
|
1501
|
+
{
|
|
1502
|
+
name: "data",
|
|
1503
|
+
type: "string | Blob",
|
|
1504
|
+
description: "The text or Blob to copy.",
|
|
1505
|
+
},
|
|
1506
|
+
],
|
|
1507
|
+
examples: [{ code: 'editor.copyToClipboard("Copied text")' }],
|
|
811
1508
|
},
|
|
812
|
-
"editor.sendMessage":
|
|
813
|
-
|
|
1509
|
+
"editor.sendMessage": {
|
|
1510
|
+
callback: (_ctx, type: string, data: any) => {
|
|
1511
|
+
if (!client.contentManager.isDocumentEditor()) return;
|
|
814
1512
|
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
1513
|
+
client.contentManager.documentEditor.sendPublicMessage({
|
|
1514
|
+
type,
|
|
1515
|
+
data,
|
|
1516
|
+
});
|
|
1517
|
+
},
|
|
1518
|
+
description:
|
|
1519
|
+
"Sends a public message to the active document editor, if one is open.",
|
|
1520
|
+
parameters: [
|
|
1521
|
+
{ name: "type", type: "string", description: "The message type." },
|
|
1522
|
+
{
|
|
1523
|
+
name: "data",
|
|
1524
|
+
type: "any",
|
|
1525
|
+
description: "Data attached to the message.",
|
|
1526
|
+
optional: true,
|
|
1527
|
+
},
|
|
1528
|
+
],
|
|
819
1529
|
},
|
|
820
1530
|
|
|
821
|
-
"editor.isMobile":
|
|
822
|
-
|
|
823
|
-
|
|
1531
|
+
"editor.isMobile": {
|
|
1532
|
+
callback: () => {
|
|
1533
|
+
const mouseDetected = globalThis.matchMedia("(pointer:fine)").matches;
|
|
1534
|
+
return !mouseDetected;
|
|
1535
|
+
},
|
|
1536
|
+
description:
|
|
1537
|
+
"Checks whether the current device lacks a fine pointer and should be treated as mobile.",
|
|
1538
|
+
returns: [
|
|
1539
|
+
{
|
|
1540
|
+
type: "boolean",
|
|
1541
|
+
description:
|
|
1542
|
+
"Whether the editor is running in a mobile-style pointer environment.",
|
|
1543
|
+
},
|
|
1544
|
+
],
|
|
824
1545
|
},
|
|
825
1546
|
};
|
|
826
1547
|
|