@silverbulletmd/silverbullet 2.6.1 → 2.8.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 +0 -3
- package/client/markdown_parser/constants.ts +1 -0
- package/client/plugos/hooks/command.ts +46 -16
- package/client/plugos/hooks/slash_command.ts +3 -1
- package/client/plugos/plug.ts +5 -2
- package/client/plugos/plug_compile.ts +52 -2
- package/client/plugos/sandboxes/worker_sandbox.ts +11 -1
- package/client/plugos/syscalls/client_code_widget.ts +3 -1
- package/client/plugos/syscalls/config.ts +9 -2
- package/client/plugos/syscalls/editor.ts +147 -0
- package/client/plugos/syscalls/index.ts +8 -1
- package/client/plugos/syscalls/jsonschema.ts +1 -19
- package/client/plugos/syscalls/system.ts +13 -0
- package/client/plugos/system.ts +14 -10
- package/client/plugos/types.ts +25 -0
- package/client/plugos/util.ts +20 -0
- package/client/space_lua/aggregates.ts +2 -2
- package/client/space_lua/query_collection.ts +4 -4
- package/client/space_lua/render_lua_markdown.ts +1 -1
- package/client/space_lua/runtime.ts +1 -1
- package/client/space_lua/{liq_null.ts → sliq_null.ts} +2 -2
- package/client/space_lua/stdlib/space_lua.ts +1 -1
- package/client/space_lua/stdlib.ts +1 -1
- package/dist/plug-compile.js +44 -2
- package/package.json +1 -1
- package/plug-api/constants.ts +20 -0
- package/plug-api/lib/ref.ts +9 -2
- package/plug-api/lib/shortcut.ts +16 -0
- package/plug-api/lib/tree.ts +35 -4
- package/plug-api/syscalls/config.ts +37 -0
- package/plug-api/syscalls/editor.ts +160 -0
- package/plug-api/syscalls/index.ts +30 -0
- package/plug-api/syscalls/system.ts +15 -0
- package/plug-api/types/client.ts +12 -0
- package/plug-api/types/manifest.ts +63 -0
- package/plugs/builtin_plugs.ts +1 -1
- package/client/plugos/sandboxes/web_worker_sandbox.ts +0 -17
package/client/plugos/util.ts
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-clone a value, replacing any functions with null.
|
|
3
|
+
* Needed because values containing functions can't be serialized
|
|
4
|
+
* via postMessage or validated with JSON Schema.
|
|
5
|
+
*/
|
|
6
|
+
export function stripFunctions(value: any): any {
|
|
7
|
+
if (typeof value === "function") return null;
|
|
8
|
+
if (value === null || value === undefined || typeof value !== "object") {
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
if (Array.isArray(value)) {
|
|
12
|
+
return value.map(stripFunctions);
|
|
13
|
+
}
|
|
14
|
+
const result: Record<string, any> = {};
|
|
15
|
+
for (const key of Object.keys(value)) {
|
|
16
|
+
result[key] = stripFunctions(value[key]);
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
|
|
1
21
|
/**
|
|
2
22
|
* Checks if an object is sendable across the plugos worker boundary.
|
|
3
23
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Aggregate function definitions and execution for
|
|
2
|
+
* Aggregate function definitions and execution for SLIQ.
|
|
3
3
|
*
|
|
4
4
|
* Builtins implement ILuaFunction via plain objects rather than
|
|
5
5
|
* LuaBuiltinFunction instances. This avoids ES module TDZ issues:
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
luaValueToJS,
|
|
17
17
|
type LuaValue,
|
|
18
18
|
} from "./runtime.ts";
|
|
19
|
-
import { isSqlNull } from "./
|
|
19
|
+
import { isSqlNull } from "./sliq_null.ts";
|
|
20
20
|
import type { LuaExpression, LuaOrderBy } from "./ast.ts";
|
|
21
21
|
import { buildItemEnv } from "./query_env.ts";
|
|
22
22
|
import { asyncMergeSort } from "./util.ts";
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
type LuaValue,
|
|
27
27
|
singleResult,
|
|
28
28
|
} from "./runtime.ts";
|
|
29
|
-
import { isSqlNull,
|
|
29
|
+
import { isSqlNull, SLIQ_NULL } from "./sliq_null.ts";
|
|
30
30
|
import { evalExpression, luaOp } from "./eval.ts";
|
|
31
31
|
import { asyncMergeSort } from "./util.ts";
|
|
32
32
|
import type { DataStore } from "../data/datastore.ts";
|
|
@@ -295,7 +295,7 @@ function containsAggregate(expr: LuaExpression, config?: Config): boolean {
|
|
|
295
295
|
// Wrap a value for select result tables so that the column key survives
|
|
296
296
|
// in the `LuaTable`
|
|
297
297
|
function selectVal(v: LuaValue): LuaValue {
|
|
298
|
-
return v === null || v === undefined ?
|
|
298
|
+
return v === null || v === undefined ? SLIQ_NULL : v;
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
/**
|
|
@@ -491,7 +491,7 @@ function normalizeSelectResults(results: any[]): any[] {
|
|
|
491
491
|
const rebuilt = new LuaTable();
|
|
492
492
|
for (const k of canonicalKeys) {
|
|
493
493
|
const v = item.rawGet(k);
|
|
494
|
-
void rebuilt.rawSet(k, v === undefined || v === null ?
|
|
494
|
+
void rebuilt.rawSet(k, v === undefined || v === null ? SLIQ_NULL : v);
|
|
495
495
|
}
|
|
496
496
|
for (const k of luaKeys(item)) {
|
|
497
497
|
if (typeof k !== "string") {
|
|
@@ -675,7 +675,7 @@ async function evalSelectExpression(
|
|
|
675
675
|
for (const k of luaKeys(result)) {
|
|
676
676
|
const v = result.rawGet(k);
|
|
677
677
|
if (v === null || v === undefined) {
|
|
678
|
-
void result.rawSet(k,
|
|
678
|
+
void result.rawSet(k, SLIQ_NULL);
|
|
679
679
|
}
|
|
680
680
|
}
|
|
681
681
|
return result;
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
escapeRegularPipes,
|
|
4
4
|
jsonToMDTable,
|
|
5
5
|
} from "../markdown_renderer/result_render.ts";
|
|
6
|
-
import { isSqlNull } from "../space_lua/
|
|
6
|
+
import { isSqlNull } from "../space_lua/sliq_null.ts";
|
|
7
7
|
import { isTaggedFloat } from "../space_lua/numeric.ts";
|
|
8
8
|
import { LuaTable, luaFormatNumber } from "../space_lua/runtime.ts";
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ import { evalStatement } from "./eval.ts";
|
|
|
3
3
|
import { asyncQuickSort } from "./util.ts";
|
|
4
4
|
import { isPromise, rpAll } from "./rp.ts";
|
|
5
5
|
import { isNegativeZero, isTaggedFloat } from "./numeric.ts";
|
|
6
|
-
import { isSqlNull } from "./
|
|
6
|
+
import { isSqlNull } from "./sliq_null.ts";
|
|
7
7
|
import { luaFormat } from "./stdlib/format.ts";
|
|
8
8
|
|
|
9
9
|
export type LuaType =
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sentinel value representing SQL NULL in query results.
|
|
2
|
-
export const
|
|
2
|
+
export const SLIQ_NULL = Symbol.for("silverbullet.sqlNull");
|
|
3
3
|
|
|
4
4
|
export function isSqlNull(v: any): boolean {
|
|
5
|
-
return v ===
|
|
5
|
+
return v === SLIQ_NULL;
|
|
6
6
|
}
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
luaValueToJS,
|
|
13
13
|
singleResult,
|
|
14
14
|
} from "../runtime.ts";
|
|
15
|
-
import { isSqlNull } from "../
|
|
15
|
+
import { isSqlNull } from "../sliq_null.ts";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* These are Space Lua specific functions that are available to all scripts, but are not part of the standard Lua language.
|
|
@@ -35,7 +35,7 @@ import { cryptoApi } from "./stdlib/crypto.ts";
|
|
|
35
35
|
import { netApi } from "./stdlib/net.ts";
|
|
36
36
|
import { isTaggedFloat, makeLuaFloat } from "./numeric.ts";
|
|
37
37
|
import { isPromise } from "./rp.ts";
|
|
38
|
-
import { isSqlNull } from "./
|
|
38
|
+
import { isSqlNull } from "./sliq_null.ts";
|
|
39
39
|
|
|
40
40
|
const printFunction = new LuaBuiltinFunction(async (_sf, ...args) => {
|
|
41
41
|
console.log("[Lua]", ...(await Promise.all(args.map((v) => luaToString(v)))));
|
package/dist/plug-compile.js
CHANGED
|
@@ -4,14 +4,22 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
6
6
|
// version.ts
|
|
7
|
-
var version = "2.
|
|
7
|
+
var version = "2.8.0";
|
|
8
8
|
|
|
9
9
|
// client/plugos/plug_compile.ts
|
|
10
10
|
import * as path from "node:path";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
copyFile,
|
|
13
|
+
mkdir,
|
|
14
|
+
mkdtemp,
|
|
15
|
+
readFile as readFile2,
|
|
16
|
+
rm,
|
|
17
|
+
writeFile
|
|
18
|
+
} from "node:fs/promises";
|
|
12
19
|
import { tmpdir } from "node:os";
|
|
13
20
|
import * as YAML from "js-yaml";
|
|
14
21
|
import * as esbuild from "esbuild";
|
|
22
|
+
import * as sass from "sass";
|
|
15
23
|
|
|
16
24
|
// client/asset_bundle/builder.ts
|
|
17
25
|
import { readFile, readdir } from "node:fs/promises";
|
|
@@ -1339,6 +1347,12 @@ async function compileManifest(manifestPath, destPath, options = {}) {
|
|
|
1339
1347
|
if (!manifest.name) {
|
|
1340
1348
|
throw new Error(`Missing 'name' in ${manifestPath}`);
|
|
1341
1349
|
}
|
|
1350
|
+
if (manifest.build) {
|
|
1351
|
+
await Promise.all(
|
|
1352
|
+
manifest.build.map((step) => runBuildStep(step, rootPath, options))
|
|
1353
|
+
);
|
|
1354
|
+
delete manifest.build;
|
|
1355
|
+
}
|
|
1342
1356
|
const assetsBundle = await bundleAssets(
|
|
1343
1357
|
path.resolve(rootPath),
|
|
1344
1358
|
manifest.assets || []
|
|
@@ -1435,6 +1449,34 @@ async function compileManifests(manifestFiles, dist, options = {}) {
|
|
|
1435
1449
|
}
|
|
1436
1450
|
await buildAll();
|
|
1437
1451
|
}
|
|
1452
|
+
async function runBuildStep(step, rootPath, options) {
|
|
1453
|
+
const type = step.type ?? "esbuild";
|
|
1454
|
+
const inFile = path.resolve(rootPath, step.in);
|
|
1455
|
+
const outFile = path.resolve(rootPath, step.out);
|
|
1456
|
+
await mkdir(path.dirname(outFile), { recursive: true });
|
|
1457
|
+
if (type === "esbuild") {
|
|
1458
|
+
await esbuild.build({
|
|
1459
|
+
entryPoints: [inFile],
|
|
1460
|
+
bundle: true,
|
|
1461
|
+
format: "iife",
|
|
1462
|
+
platform: "browser",
|
|
1463
|
+
minify: !options.debug,
|
|
1464
|
+
outfile: outFile,
|
|
1465
|
+
treeShaking: true
|
|
1466
|
+
});
|
|
1467
|
+
} else if (type === "sass") {
|
|
1468
|
+
const scss = await readFile2(inFile, "utf-8");
|
|
1469
|
+
const result = sass.compileString(scss, {
|
|
1470
|
+
loadPaths: [path.dirname(inFile)],
|
|
1471
|
+
style: options.debug ? "expanded" : "compressed"
|
|
1472
|
+
});
|
|
1473
|
+
await writeFile(outFile, result.css, "utf-8");
|
|
1474
|
+
} else if (type === "copy") {
|
|
1475
|
+
await copyFile(inFile, outFile);
|
|
1476
|
+
} else {
|
|
1477
|
+
throw new Error(`Unsupported build step type: ${type}`);
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1438
1480
|
function patchBundledJS(code) {
|
|
1439
1481
|
return code.replaceAll("/(?<=\\n)/", "/()/");
|
|
1440
1482
|
}
|
package/package.json
CHANGED
package/plug-api/constants.ts
CHANGED
|
@@ -8,3 +8,23 @@ export const wrongSpacePathError: Error = new Error(
|
|
|
8
8
|
);
|
|
9
9
|
export const pingTimeout: number = 2000;
|
|
10
10
|
export const pingInterval: number = 5000;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Determines if an error thrown by fetch() is a network-level error
|
|
14
|
+
* (as opposed to a server-side or application error).
|
|
15
|
+
*
|
|
16
|
+
* Browser-specific error messages when there is no internet connection:
|
|
17
|
+
* - Firefox: "NetworkError when attempting to fetch resource"
|
|
18
|
+
* - Safari (service worker): "FetchEvent.respondWith received an error: TypeError: Load failed"
|
|
19
|
+
* - Safari (no service worker): "Load failed"
|
|
20
|
+
* - Chrome: "Failed to fetch"
|
|
21
|
+
*/
|
|
22
|
+
export function isNetworkError(e: any): boolean {
|
|
23
|
+
const msg = (e?.message || "").toLowerCase();
|
|
24
|
+
return (
|
|
25
|
+
msg.includes("fetch") ||
|
|
26
|
+
msg.includes("load failed") ||
|
|
27
|
+
msg.includes("networkerror") ||
|
|
28
|
+
msg.includes("unavailable")
|
|
29
|
+
);
|
|
30
|
+
}
|
package/plug-api/lib/ref.ts
CHANGED
|
@@ -23,7 +23,8 @@ export type Ref = {
|
|
|
23
23
|
details?:
|
|
24
24
|
| { type: "position"; pos: number }
|
|
25
25
|
| { type: "linecolumn"; line: number; column: number }
|
|
26
|
-
| { type: "header"; header: string }
|
|
26
|
+
| { type: "header"; header: string }
|
|
27
|
+
| { type: "anchor"; name: string };
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
/**
|
|
@@ -96,7 +97,7 @@ export function isValidPath(path: string): path is Path {
|
|
|
96
97
|
* TO THE INNER WORKINGS OF SILVERBULLET AND CHANGES COULD INTRODUCE MAJOR BUGS
|
|
97
98
|
*/
|
|
98
99
|
const refRegex =
|
|
99
|
-
/^(?<meta>\^)?(?<path>(?!.*\.[a-zA-Z0-9]+\.md$)(?!\/?(\.|\^))(?!.*(?:\/|^)\.{1,2}(?:\/|$)|.*\/{2})(?!.*(?:\]\]|\[\[))[
|
|
100
|
+
/^(?<meta>\^)?(?<path>(?!.*\.[a-zA-Z0-9]+\.md$)(?!\/?(\.|\^))(?!.*(?:\/|^)\.{1,2}(?:\/|$)|.*\/{2})(?!.*(?:\]\]|\[\[))[^@#|<>$]*)(@(?<pos>\d+)|@[Ll](?<line>\d+)(?:[Cc](?<col>\d+))?|#\s*(?<header>.*)|\$(?<anchor>[A-Za-z_][A-Za-z0-9_/:-]*))?$/;
|
|
100
101
|
|
|
101
102
|
/**
|
|
102
103
|
* Parses a reference string into a ref object.
|
|
@@ -132,6 +133,8 @@ export function parseToRef(stringRef: string): Ref | null {
|
|
|
132
133
|
type: "header",
|
|
133
134
|
header: groups.header,
|
|
134
135
|
};
|
|
136
|
+
} else if (groups.anchor !== undefined) {
|
|
137
|
+
ref.details = { type: "anchor", name: groups.anchor };
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
return ref;
|
|
@@ -158,6 +161,8 @@ export function encodeRef(ref: Ref): string {
|
|
|
158
161
|
stringRef += `@${ref.details.pos}`;
|
|
159
162
|
} else if (ref.details?.type === "header") {
|
|
160
163
|
stringRef += `#${ref.details.header}`;
|
|
164
|
+
} else if (ref.details?.type === "anchor") {
|
|
165
|
+
stringRef += `$${ref.details.name}`;
|
|
161
166
|
}
|
|
162
167
|
|
|
163
168
|
return stringRef;
|
|
@@ -191,6 +196,8 @@ export function getOffsetFromRef(
|
|
|
191
196
|
case "header": {
|
|
192
197
|
return getOffsetFromHeader(parseTree, ref.details.header);
|
|
193
198
|
}
|
|
199
|
+
case "anchor":
|
|
200
|
+
return -1;
|
|
194
201
|
}
|
|
195
202
|
}
|
|
196
203
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const isMacLike = typeof navigator !== "undefined" &&
|
|
2
|
+
/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);
|
|
3
|
+
|
|
4
|
+
export function prettifyShortcut(shortcut: string): string {
|
|
5
|
+
if (!isMacLike) return shortcut;
|
|
6
|
+
const pretty = shortcut
|
|
7
|
+
.replace(/Mod-/g, "⌘")
|
|
8
|
+
.replace(/Cmd-/g, "⌘")
|
|
9
|
+
.replace(/Ctrl-/g, "⌃")
|
|
10
|
+
.replace(/Alt-/g, "⌥")
|
|
11
|
+
.replace(/Shift-/g, "⇧");
|
|
12
|
+
return pretty.replace(
|
|
13
|
+
/([⌘⌃⌥⇧])([a-z])$/,
|
|
14
|
+
(_, mod, key) => mod + key.toUpperCase(),
|
|
15
|
+
);
|
|
16
|
+
}
|
package/plug-api/lib/tree.ts
CHANGED
|
@@ -191,13 +191,29 @@ export function traverseTree(
|
|
|
191
191
|
tree: ParseTree,
|
|
192
192
|
// Return value = should stop traversal into children?
|
|
193
193
|
matchFn: (tree: ParseTree) => boolean,
|
|
194
|
+
// Just log errors on exceptions, but don't stop traversal
|
|
195
|
+
catchVisitorErrors = false,
|
|
194
196
|
): void {
|
|
195
|
-
|
|
197
|
+
let stop = false;
|
|
198
|
+
if (catchVisitorErrors) {
|
|
199
|
+
try {
|
|
200
|
+
stop = matchFn(tree);
|
|
201
|
+
} catch (e: any) {
|
|
202
|
+
console.error(
|
|
203
|
+
`traverseTree visitor failed at node ${tree.type}@${tree.from}:`,
|
|
204
|
+
e?.stack ?? e,
|
|
205
|
+
);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
stop = matchFn(tree);
|
|
210
|
+
}
|
|
211
|
+
if (stop) {
|
|
196
212
|
return;
|
|
197
213
|
}
|
|
198
214
|
if (tree.children) {
|
|
199
215
|
for (const child of tree.children) {
|
|
200
|
-
traverseTree(child, matchFn);
|
|
216
|
+
traverseTree(child, matchFn, catchVisitorErrors);
|
|
201
217
|
}
|
|
202
218
|
}
|
|
203
219
|
}
|
|
@@ -206,13 +222,28 @@ export async function traverseTreeAsync(
|
|
|
206
222
|
tree: ParseTree,
|
|
207
223
|
// Return value = should stop traversal into children?
|
|
208
224
|
matchFn: (tree: ParseTree) => Promise<boolean>,
|
|
225
|
+
catchVisitorErrors = false,
|
|
209
226
|
): Promise<void> {
|
|
210
|
-
|
|
227
|
+
let stop = false;
|
|
228
|
+
if (catchVisitorErrors) {
|
|
229
|
+
try {
|
|
230
|
+
stop = await matchFn(tree);
|
|
231
|
+
} catch (e: any) {
|
|
232
|
+
console.error(
|
|
233
|
+
`traverseTreeAsync visitor failed at node ${tree.type}@${tree.from}:`,
|
|
234
|
+
e?.stack ?? e,
|
|
235
|
+
);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
stop = await matchFn(tree);
|
|
240
|
+
}
|
|
241
|
+
if (stop) {
|
|
211
242
|
return;
|
|
212
243
|
}
|
|
213
244
|
if (tree.children) {
|
|
214
245
|
for (const child of tree.children) {
|
|
215
|
-
await traverseTreeAsync(child, matchFn);
|
|
246
|
+
await traverseTreeAsync(child, matchFn, catchVisitorErrors);
|
|
216
247
|
}
|
|
217
248
|
}
|
|
218
249
|
}
|
|
@@ -53,3 +53,40 @@ export function has(path: string): Promise<boolean> {
|
|
|
53
53
|
export function define(key: string, schema: any): Promise<void> {
|
|
54
54
|
return syscall("config.define", key, schema);
|
|
55
55
|
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Defines (or updates) a UI category for the configuration manager. Categories
|
|
59
|
+
* are referenced by name from a schema field's `ui.category` and are sorted in
|
|
60
|
+
* ascending `order` (default 0); unknown categories fall to the bottom in
|
|
61
|
+
* alphabetical order.
|
|
62
|
+
*/
|
|
63
|
+
export function defineCategory(
|
|
64
|
+
definition: { name: string; description?: string; order?: number },
|
|
65
|
+
): Promise<void> {
|
|
66
|
+
return syscall("config.defineCategory", definition);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Gets all config values as a single object.
|
|
71
|
+
* @returns The entire config values object
|
|
72
|
+
*/
|
|
73
|
+
export function getValues(): Promise<Record<string, any>> {
|
|
74
|
+
return syscall("config.getValues");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Gets all defined config schemas.
|
|
79
|
+
* @returns The schema definitions object
|
|
80
|
+
*/
|
|
81
|
+
export function getSchemas(): Promise<Record<string, any>> {
|
|
82
|
+
return syscall("config.getSchemas");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Gets all registered UI categories for the configuration manager.
|
|
87
|
+
*/
|
|
88
|
+
export function getCategories(): Promise<
|
|
89
|
+
Record<string, { name: string; description?: string; order?: number }>
|
|
90
|
+
> {
|
|
91
|
+
return syscall("config.getCategories");
|
|
92
|
+
}
|
|
@@ -153,6 +153,11 @@ export function reloadPage(): Promise<void> {
|
|
|
153
153
|
return syscall("editor.reloadPage");
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
/** Useful when a plug toggles a piece of state that lint subscribers consult. */
|
|
157
|
+
export function forceLint(): Promise<void> {
|
|
158
|
+
return syscall("editor.forceLint");
|
|
159
|
+
}
|
|
160
|
+
|
|
156
161
|
/**
|
|
157
162
|
* Force reloads the browser UI
|
|
158
163
|
*/
|
|
@@ -269,6 +274,13 @@ export function hidePanel(id: "lhs" | "rhs" | "bhs" | "modal"): Promise<void> {
|
|
|
269
274
|
return syscall("editor.hidePanel", id);
|
|
270
275
|
}
|
|
271
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Returns focus to the main editor.
|
|
279
|
+
*/
|
|
280
|
+
export function focus(): Promise<void> {
|
|
281
|
+
return syscall("editor.focus");
|
|
282
|
+
}
|
|
283
|
+
|
|
272
284
|
export function showProgress(
|
|
273
285
|
progressPercentage?: number,
|
|
274
286
|
progressType?: string,
|
|
@@ -466,6 +478,27 @@ export function deleteLine(): Promise<void> {
|
|
|
466
478
|
return syscall("editor.deleteLine");
|
|
467
479
|
}
|
|
468
480
|
|
|
481
|
+
/**
|
|
482
|
+
* Select the entire document
|
|
483
|
+
*/
|
|
484
|
+
export function selectAll(): Promise<void> {
|
|
485
|
+
return syscall("editor.selectAll");
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Increase indentation of the current line or selection
|
|
490
|
+
*/
|
|
491
|
+
export function indentMore(): Promise<void> {
|
|
492
|
+
return syscall("editor.indentMore");
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Decrease indentation of the current line or selection
|
|
497
|
+
*/
|
|
498
|
+
export function indentLess(): Promise<void> {
|
|
499
|
+
return syscall("editor.indentLess");
|
|
500
|
+
}
|
|
501
|
+
|
|
469
502
|
/**
|
|
470
503
|
* Comment or uncomment the current line in the editor
|
|
471
504
|
*/
|
|
@@ -481,6 +514,133 @@ export function moveLineDown(): Promise<void> {
|
|
|
481
514
|
return syscall("editor.moveLineDown");
|
|
482
515
|
}
|
|
483
516
|
|
|
517
|
+
// Cursor motion syscalls (wrappers around @codemirror/commands functions)
|
|
518
|
+
export function cursorCharLeft(): Promise<void> {
|
|
519
|
+
return syscall("editor.cursorCharLeft");
|
|
520
|
+
}
|
|
521
|
+
export function cursorCharRight(): Promise<void> {
|
|
522
|
+
return syscall("editor.cursorCharRight");
|
|
523
|
+
}
|
|
524
|
+
export function cursorGroupLeft(): Promise<void> {
|
|
525
|
+
return syscall("editor.cursorGroupLeft");
|
|
526
|
+
}
|
|
527
|
+
export function cursorGroupRight(): Promise<void> {
|
|
528
|
+
return syscall("editor.cursorGroupRight");
|
|
529
|
+
}
|
|
530
|
+
export function cursorLineBoundaryLeft(): Promise<void> {
|
|
531
|
+
return syscall("editor.cursorLineBoundaryLeft");
|
|
532
|
+
}
|
|
533
|
+
export function cursorLineBoundaryRight(): Promise<void> {
|
|
534
|
+
return syscall("editor.cursorLineBoundaryRight");
|
|
535
|
+
}
|
|
536
|
+
export function cursorLineStart(): Promise<void> {
|
|
537
|
+
return syscall("editor.cursorLineStart");
|
|
538
|
+
}
|
|
539
|
+
export function cursorLineEnd(): Promise<void> {
|
|
540
|
+
return syscall("editor.cursorLineEnd");
|
|
541
|
+
}
|
|
542
|
+
export function cursorDocStart(): Promise<void> {
|
|
543
|
+
return syscall("editor.cursorDocStart");
|
|
544
|
+
}
|
|
545
|
+
export function cursorDocEnd(): Promise<void> {
|
|
546
|
+
return syscall("editor.cursorDocEnd");
|
|
547
|
+
}
|
|
548
|
+
export function cursorLineUp(): Promise<void> {
|
|
549
|
+
return syscall("editor.cursorLineUp");
|
|
550
|
+
}
|
|
551
|
+
export function cursorLineDown(): Promise<void> {
|
|
552
|
+
return syscall("editor.cursorLineDown");
|
|
553
|
+
}
|
|
554
|
+
export function cursorPageUp(): Promise<void> {
|
|
555
|
+
return syscall("editor.cursorPageUp");
|
|
556
|
+
}
|
|
557
|
+
export function cursorPageDown(): Promise<void> {
|
|
558
|
+
return syscall("editor.cursorPageDown");
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// Selection-extending motions
|
|
562
|
+
export function selectCharLeft(): Promise<void> {
|
|
563
|
+
return syscall("editor.selectCharLeft");
|
|
564
|
+
}
|
|
565
|
+
export function selectCharRight(): Promise<void> {
|
|
566
|
+
return syscall("editor.selectCharRight");
|
|
567
|
+
}
|
|
568
|
+
export function selectGroupLeft(): Promise<void> {
|
|
569
|
+
return syscall("editor.selectGroupLeft");
|
|
570
|
+
}
|
|
571
|
+
export function selectGroupRight(): Promise<void> {
|
|
572
|
+
return syscall("editor.selectGroupRight");
|
|
573
|
+
}
|
|
574
|
+
export function selectLineBoundaryLeft(): Promise<void> {
|
|
575
|
+
return syscall("editor.selectLineBoundaryLeft");
|
|
576
|
+
}
|
|
577
|
+
export function selectLineBoundaryRight(): Promise<void> {
|
|
578
|
+
return syscall("editor.selectLineBoundaryRight");
|
|
579
|
+
}
|
|
580
|
+
export function selectLineStart(): Promise<void> {
|
|
581
|
+
return syscall("editor.selectLineStart");
|
|
582
|
+
}
|
|
583
|
+
export function selectLineEnd(): Promise<void> {
|
|
584
|
+
return syscall("editor.selectLineEnd");
|
|
585
|
+
}
|
|
586
|
+
export function selectDocStart(): Promise<void> {
|
|
587
|
+
return syscall("editor.selectDocStart");
|
|
588
|
+
}
|
|
589
|
+
export function selectDocEnd(): Promise<void> {
|
|
590
|
+
return syscall("editor.selectDocEnd");
|
|
591
|
+
}
|
|
592
|
+
export function selectLineUp(): Promise<void> {
|
|
593
|
+
return syscall("editor.selectLineUp");
|
|
594
|
+
}
|
|
595
|
+
export function selectLineDown(): Promise<void> {
|
|
596
|
+
return syscall("editor.selectLineDown");
|
|
597
|
+
}
|
|
598
|
+
export function selectPageUp(): Promise<void> {
|
|
599
|
+
return syscall("editor.selectPageUp");
|
|
600
|
+
}
|
|
601
|
+
export function selectPageDown(): Promise<void> {
|
|
602
|
+
return syscall("editor.selectPageDown");
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Delete
|
|
606
|
+
export function deleteCharBackward(): Promise<void> {
|
|
607
|
+
return syscall("editor.deleteCharBackward");
|
|
608
|
+
}
|
|
609
|
+
export function deleteCharForward(): Promise<void> {
|
|
610
|
+
return syscall("editor.deleteCharForward");
|
|
611
|
+
}
|
|
612
|
+
export function deleteGroupBackward(): Promise<void> {
|
|
613
|
+
return syscall("editor.deleteGroupBackward");
|
|
614
|
+
}
|
|
615
|
+
export function deleteGroupForward(): Promise<void> {
|
|
616
|
+
return syscall("editor.deleteGroupForward");
|
|
617
|
+
}
|
|
618
|
+
export function deleteLineBoundaryBackward(): Promise<void> {
|
|
619
|
+
return syscall("editor.deleteLineBoundaryBackward");
|
|
620
|
+
}
|
|
621
|
+
export function deleteLineBoundaryForward(): Promise<void> {
|
|
622
|
+
return syscall("editor.deleteLineBoundaryForward");
|
|
623
|
+
}
|
|
624
|
+
export function transposeChars(): Promise<void> {
|
|
625
|
+
return syscall("editor.transposeChars");
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Enter: accepts completion if popup open, else inserts newline
|
|
629
|
+
export function insertNewline(): Promise<void> {
|
|
630
|
+
return syscall("editor.insertNewline");
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// Completion popup
|
|
634
|
+
export function acceptCompletion(): Promise<boolean> {
|
|
635
|
+
return syscall("editor.acceptCompletion");
|
|
636
|
+
}
|
|
637
|
+
export function startCompletion(): Promise<void> {
|
|
638
|
+
return syscall("editor.startCompletion");
|
|
639
|
+
}
|
|
640
|
+
export function closeCompletion(): Promise<void> {
|
|
641
|
+
return syscall("editor.closeCompletion");
|
|
642
|
+
}
|
|
643
|
+
|
|
484
644
|
// Vim-mode specific syscalls
|
|
485
645
|
|
|
486
646
|
/**
|
|
@@ -27,6 +27,18 @@ export function validateObjects<T>(
|
|
|
27
27
|
return syscall("index.validateObjects", page, objects);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Run the full indexing pipeline (validation, multi-tag expansion,
|
|
32
|
+
* tag transforms) and return the resulting objects each paired with
|
|
33
|
+
* the tag they're indexed under. Read-only — no DB writes.
|
|
34
|
+
*/
|
|
35
|
+
export function previewProcessedObjects(
|
|
36
|
+
page: string,
|
|
37
|
+
objects: ObjectValue[],
|
|
38
|
+
): Promise<{ tag: string; object: ObjectValue }[]> {
|
|
39
|
+
return syscall("index.previewProcessedObjects", page, objects);
|
|
40
|
+
}
|
|
41
|
+
|
|
30
42
|
/**
|
|
31
43
|
* Queries objects using a Lua-based collection query
|
|
32
44
|
* @param tag - The tag to filter objects by
|
|
@@ -75,3 +87,21 @@ export function deleteObject(
|
|
|
75
87
|
): Promise<void> {
|
|
76
88
|
return syscall("index.deleteObject", page, tag, ref);
|
|
77
89
|
}
|
|
90
|
+
|
|
91
|
+
export type {
|
|
92
|
+
AnchorHit,
|
|
93
|
+
ResolveAnchorResult,
|
|
94
|
+
} from "../../plugs/index/types.ts";
|
|
95
|
+
import type { ResolveAnchorResult } from "../../plugs/index/types.ts";
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Resolves a `$name` anchor to its host. Returns `ok: true` with page +
|
|
99
|
+
* hostTag + range on success, or `ok: false` with `missing`/`duplicate`
|
|
100
|
+
* reason. When `page` is provided, the lookup is filtered to that page.
|
|
101
|
+
*/
|
|
102
|
+
export function resolveAnchor(
|
|
103
|
+
name: string,
|
|
104
|
+
page?: string,
|
|
105
|
+
): Promise<ResolveAnchorResult> {
|
|
106
|
+
return syscall("index.resolveAnchor", name, page);
|
|
107
|
+
}
|
|
@@ -51,6 +51,21 @@ export function reloadPlugs(): Promise<void> {
|
|
|
51
51
|
return syscall("system.reloadPlugs");
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Load (or reload) a single plug from a space file path.
|
|
56
|
+
*/
|
|
57
|
+
export function loadPlug(path: string): Promise<void> {
|
|
58
|
+
return syscall("system.loadPlug", path);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Unload a plug previously loaded from the given space file path.
|
|
63
|
+
* Returns true if a plug was unloaded.
|
|
64
|
+
*/
|
|
65
|
+
export function unloadPlug(path: string): Promise<boolean> {
|
|
66
|
+
return syscall("system.unloadPlug", path);
|
|
67
|
+
}
|
|
68
|
+
|
|
54
69
|
/**
|
|
55
70
|
* Returns the current mode of the system, either "ro" (read-only) or "rw" (read-write)
|
|
56
71
|
*/
|
package/plug-api/types/client.ts
CHANGED
|
@@ -54,6 +54,18 @@ export type LintDiagnostic = {
|
|
|
54
54
|
to: number;
|
|
55
55
|
severity: "error" | "warning" | "info" | "hint";
|
|
56
56
|
message: string;
|
|
57
|
+
/**
|
|
58
|
+
* Optional HTML rendered into the hover tooltip for this diagnostic.
|
|
59
|
+
* When present, takes precedence over `message` for tooltip display.
|
|
60
|
+
* `message` is still used as a plain-text fallback (e.g. in the lint
|
|
61
|
+
* panel) and as the diagnostic's accessible label.
|
|
62
|
+
*/
|
|
63
|
+
messageHtml?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Optional CSS class added to the inline range mark for this diagnostic,
|
|
66
|
+
* in addition to CodeMirror's default `.cm-lintRange-<severity>` class.
|
|
67
|
+
*/
|
|
68
|
+
markClass?: string;
|
|
57
69
|
};
|
|
58
70
|
|
|
59
71
|
export type UploadFile = {
|