@silverbulletmd/silverbullet 2.8.1 → 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 +42 -25
- 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 -700
- package/client/plugos/syscalls/event.ts +46 -13
- package/client/plugos/syscalls/fetch.ts +123 -82
- package/client/plugos/syscalls/index.ts +243 -114
- 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 +254 -119
- package/client/space_lua/pretty_print.ts +465 -0
- package/client/space_lua/query_collection.ts +3 -3
- 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 +26 -17
- 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 +397 -13
- 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 +336 -94
- package/client/space_lua/syscalls.ts +270 -0
- package/dist/plug-compile.js +1 -1
- package/package.json +12 -4
- 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 +23 -2
- package/plug-api/syscalls/index.ts +24 -1
- package/plug-api/syscalls/jsonschema.ts +9 -0
- package/plug-api/syscalls/lua.ts +28 -1
- 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/config.ts +1 -1
- package/plug-api/types/index.ts +52 -1
- package/plug-api/types/manifest.ts +22 -4
- package/plug-api/ui/cx.ts +4 -0
- package/plug-api/ui/index.ts +22 -0
- package/plug-api/ui/panel_styles.ts +33 -0
- package/plug-api/ui/slugify.ts +44 -0
- package/plugs/builtin_plugs.ts +1 -0
- package/client/plugos/syscalls/lua.ts +0 -58
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import type { ASTCtx, LuaBlock, LuaExpression } from "./ast.ts";
|
|
2
|
+
import { evalExpression } from "./eval.ts";
|
|
3
|
+
import { parseBlock, parseExpressionString } from "./parse.ts";
|
|
4
|
+
import {
|
|
5
|
+
type PrintOptions,
|
|
6
|
+
prettyPrintBlock,
|
|
7
|
+
prettyPrintExpression,
|
|
8
|
+
} from "./pretty_print.ts";
|
|
9
|
+
import {
|
|
10
|
+
isILuaFunction,
|
|
11
|
+
LuaEnv,
|
|
12
|
+
LuaStackFrame,
|
|
13
|
+
LuaTable,
|
|
14
|
+
luaGet,
|
|
15
|
+
luaKeys,
|
|
16
|
+
luaToString,
|
|
17
|
+
luaTypeOf,
|
|
18
|
+
luaValueToJS,
|
|
19
|
+
} from "./runtime.ts";
|
|
20
|
+
import { buildThreadLocalEnv } from "../space_lua_api.ts";
|
|
21
|
+
import type { SysCallMapping, System } from "../plugos/system.ts";
|
|
22
|
+
import { isSendable } from "../plugos/util.ts";
|
|
23
|
+
import type {
|
|
24
|
+
LuaFunctionInfo,
|
|
25
|
+
LuaPropertyInspection,
|
|
26
|
+
LuaValueInspection,
|
|
27
|
+
} from "../../plug-api/types/index.ts";
|
|
28
|
+
import { encodeRef } from "../../plug-api/lib/ref.ts";
|
|
29
|
+
import { resolveASTReference } from "../space_lua.ts";
|
|
30
|
+
|
|
31
|
+
async function inspectValue(
|
|
32
|
+
value: unknown,
|
|
33
|
+
path: string[],
|
|
34
|
+
): Promise<Omit<LuaValueInspection, "properties">> {
|
|
35
|
+
const type = value instanceof LuaEnv ? "table" : await luaTypeOf(value);
|
|
36
|
+
if (!isILuaFunction(value)) {
|
|
37
|
+
return { type };
|
|
38
|
+
}
|
|
39
|
+
const functionInfo: LuaFunctionInfo = {
|
|
40
|
+
...(value.info ?? { kind: "builtin" }),
|
|
41
|
+
name: value.info?.name ?? path.join("."),
|
|
42
|
+
};
|
|
43
|
+
const definitionRef =
|
|
44
|
+
functionInfo.kind === "lua" && functionInfo.source
|
|
45
|
+
? resolveASTReference(functionInfo.source as ASTCtx)
|
|
46
|
+
: null;
|
|
47
|
+
return {
|
|
48
|
+
type,
|
|
49
|
+
functionInfo,
|
|
50
|
+
definition: definitionRef ? encodeRef(definitionRef) : undefined,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function inspectLuaPath(
|
|
55
|
+
env: LuaEnv,
|
|
56
|
+
path: string[],
|
|
57
|
+
): Promise<LuaValueInspection | null> {
|
|
58
|
+
const sf = LuaStackFrame.createWithGlobalEnv(env);
|
|
59
|
+
let value: unknown = env;
|
|
60
|
+
for (const key of path) {
|
|
61
|
+
value = await luaGet(value, key, null, sf);
|
|
62
|
+
if (value === null || value === undefined) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const properties: LuaPropertyInspection[] = [];
|
|
68
|
+
const keys =
|
|
69
|
+
value instanceof LuaEnv
|
|
70
|
+
? value.keys()
|
|
71
|
+
: value instanceof LuaTable ||
|
|
72
|
+
Array.isArray(value) ||
|
|
73
|
+
(typeof value === "object" && value !== null)
|
|
74
|
+
? luaKeys(value)
|
|
75
|
+
: [];
|
|
76
|
+
for (const key of [...new Set(keys)]
|
|
77
|
+
.filter((candidate): candidate is string => typeof candidate === "string")
|
|
78
|
+
.sort()) {
|
|
79
|
+
const child = await luaGet(value, key, null, sf);
|
|
80
|
+
if (child === null || child === undefined) continue;
|
|
81
|
+
properties.push({
|
|
82
|
+
key,
|
|
83
|
+
...(await inspectValue(child, [...path, key])),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
...(await inspectValue(value, path)),
|
|
89
|
+
properties,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function luaSyscalls(
|
|
94
|
+
system: System<any>,
|
|
95
|
+
getEnvironment: () => LuaEnv,
|
|
96
|
+
): SysCallMapping {
|
|
97
|
+
return {
|
|
98
|
+
"lua.parseBlock": {
|
|
99
|
+
callback: (_ctx, code: string): LuaBlock => parseBlock(code),
|
|
100
|
+
description:
|
|
101
|
+
"Parses a Space Lua chunk and returns its AST. Blocks retain comments in source order with their exact text, kind, and source range.",
|
|
102
|
+
parameters: [
|
|
103
|
+
{ name: "code", type: "string", description: "Lua code to parse." },
|
|
104
|
+
],
|
|
105
|
+
returns: [{ type: "table", description: "Parsed Lua block AST." }],
|
|
106
|
+
examples: [
|
|
107
|
+
{
|
|
108
|
+
code: 'local ast = lua.parseBlock("print(\\"Hello\\")")',
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
see: "API/lua",
|
|
112
|
+
},
|
|
113
|
+
// Deprecated alias for `lua.parseBlock`, kept for backwards compatibility.
|
|
114
|
+
"lua.parse": {
|
|
115
|
+
callback: (_ctx, code: string): LuaBlock => parseBlock(code),
|
|
116
|
+
description: "Deprecated alias for lua.parseBlock.",
|
|
117
|
+
parameters: [
|
|
118
|
+
{ name: "code", type: "string", description: "Lua code to parse." },
|
|
119
|
+
],
|
|
120
|
+
returns: [{ type: "table", description: "Parsed Lua block AST." }],
|
|
121
|
+
deprecated: "Use lua.parseBlock instead.",
|
|
122
|
+
see: "API/lua",
|
|
123
|
+
},
|
|
124
|
+
"lua.parseExpression": {
|
|
125
|
+
callback: (_ctx, expression: string): LuaExpression =>
|
|
126
|
+
parseExpressionString(expression),
|
|
127
|
+
description: "Parses a Space Lua expression and returns its AST.",
|
|
128
|
+
parameters: [
|
|
129
|
+
{
|
|
130
|
+
name: "expression",
|
|
131
|
+
type: "string",
|
|
132
|
+
description: "Lua expression to parse.",
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
returns: [{ type: "table", description: "Parsed expression AST." }],
|
|
136
|
+
examples: [
|
|
137
|
+
{
|
|
138
|
+
code: 'local expression = lua.parseExpression("1 + 2 * 3")',
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
see: "API/lua",
|
|
142
|
+
},
|
|
143
|
+
"lua.prettyPrintBlock": {
|
|
144
|
+
callback: (_ctx, block: LuaBlock, opts?: PrintOptions): string =>
|
|
145
|
+
prettyPrintBlock(block, opts),
|
|
146
|
+
description:
|
|
147
|
+
"Pretty-prints a parsed Space Lua block. Comments are preserved while their placement and indentation are normalized.",
|
|
148
|
+
parameters: [
|
|
149
|
+
{ name: "block", type: "table", description: "Parsed block AST." },
|
|
150
|
+
{
|
|
151
|
+
name: "options",
|
|
152
|
+
type: "table",
|
|
153
|
+
description:
|
|
154
|
+
"Formatting options: `indentWidth`, `quote`, and `trailingComma`.",
|
|
155
|
+
optional: true,
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
returns: [{ type: "string", description: "Formatted Lua source." }],
|
|
159
|
+
examples: [
|
|
160
|
+
{
|
|
161
|
+
code: 'local formatted = lua.prettyPrintBlock(lua.parseBlock("if a then return 1 end"))',
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
see: "API/lua",
|
|
165
|
+
},
|
|
166
|
+
"lua.prettyPrintExpression": {
|
|
167
|
+
callback: (
|
|
168
|
+
_ctx,
|
|
169
|
+
expression: LuaExpression,
|
|
170
|
+
opts?: PrintOptions,
|
|
171
|
+
): string => prettyPrintExpression(expression, opts),
|
|
172
|
+
description: "Pretty-prints a parsed Space Lua expression.",
|
|
173
|
+
parameters: [
|
|
174
|
+
{
|
|
175
|
+
name: "expression",
|
|
176
|
+
type: "table",
|
|
177
|
+
description: "Parsed expression AST.",
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "options",
|
|
181
|
+
type: "table",
|
|
182
|
+
description:
|
|
183
|
+
"Formatting options: `indentWidth`, `quote`, and `trailingComma`.",
|
|
184
|
+
optional: true,
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
returns: [{ type: "string", description: "Formatted Lua source." }],
|
|
188
|
+
examples: [
|
|
189
|
+
{
|
|
190
|
+
code: 'local formatted = lua.prettyPrintExpression(lua.parseExpression("{a=1,b=2}"))',
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
see: "API/lua",
|
|
194
|
+
},
|
|
195
|
+
/**
|
|
196
|
+
* Evaluates a Lua expression and returns the result as a JavaScript value
|
|
197
|
+
* @param _ctx
|
|
198
|
+
* @param expression
|
|
199
|
+
* @returns
|
|
200
|
+
*/
|
|
201
|
+
"lua.evalExpression": {
|
|
202
|
+
callback: async (_ctx, expression: string) => {
|
|
203
|
+
try {
|
|
204
|
+
const ast = parseExpressionString(expression);
|
|
205
|
+
const globalEnv = getEnvironment();
|
|
206
|
+
const env = await buildThreadLocalEnv(system, globalEnv);
|
|
207
|
+
const sf = new LuaStackFrame(env, null);
|
|
208
|
+
const luaResult = await evalExpression(ast, globalEnv, sf);
|
|
209
|
+
const jsResult = luaValueToJS(luaResult, sf);
|
|
210
|
+
if (isSendable(jsResult)) {
|
|
211
|
+
return jsResult;
|
|
212
|
+
} else {
|
|
213
|
+
// This may evaluate to e.g. a function, which is not sendable, in this case we'll console.warn and return a stringified version of the result
|
|
214
|
+
console.warn(
|
|
215
|
+
"Lua eval result is not sendable, returning stringified version",
|
|
216
|
+
jsResult,
|
|
217
|
+
);
|
|
218
|
+
return luaToString(luaResult);
|
|
219
|
+
}
|
|
220
|
+
} catch (e: any) {
|
|
221
|
+
console.error("Lua eval error: ", e.message, e.sf?.astCtx);
|
|
222
|
+
throw e;
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
description: "Evaluates a Space Lua expression.",
|
|
226
|
+
parameters: [
|
|
227
|
+
{
|
|
228
|
+
name: "expression",
|
|
229
|
+
type: "string",
|
|
230
|
+
description: "Lua expression to evaluate.",
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
returns: [{ description: "Evaluated result." }],
|
|
234
|
+
examples: [
|
|
235
|
+
{
|
|
236
|
+
code: 'local result = lua.evalExpression("1 + 2 * 3")\nprint(result)',
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
see: "API/lua",
|
|
240
|
+
},
|
|
241
|
+
"lua.inspect": {
|
|
242
|
+
callback: (_ctx, path: string[] = []) =>
|
|
243
|
+
inspectLuaPath(getEnvironment(), path),
|
|
244
|
+
description:
|
|
245
|
+
"Inspects a value in the live Space Lua environment and returns serializable type, function, definition, and property metadata.",
|
|
246
|
+
parameters: [
|
|
247
|
+
{
|
|
248
|
+
name: "path",
|
|
249
|
+
type: "table",
|
|
250
|
+
description:
|
|
251
|
+
"Sequence of property names from the global environment; omit to inspect globals.",
|
|
252
|
+
optional: true,
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
returns: [
|
|
256
|
+
{
|
|
257
|
+
type: "table|nil",
|
|
258
|
+
description:
|
|
259
|
+
"Inspection metadata, or nil when the requested path does not exist.",
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
examples: [
|
|
263
|
+
{
|
|
264
|
+
code: 'local info = lua.inspect({"editor", "getText"})',
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
see: "API/lua",
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
package/dist/plug-compile.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@silverbulletmd/silverbullet",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A self-hosted, web-based note taking app",
|
|
6
6
|
"publishConfig": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"./syscall": "./plug-api/syscall.ts",
|
|
11
11
|
"./syscalls": "./plug-api/syscalls.ts",
|
|
12
12
|
"./constants": "./plug-api/constants.ts",
|
|
13
|
+
"./ui": "./plug-api/ui/index.ts",
|
|
13
14
|
"./lib/json": "./plug-api/lib/json.ts",
|
|
14
15
|
"./lib/tree": "./plug-api/lib/tree.ts",
|
|
15
16
|
"./lib/ref": "./plug-api/lib/ref.ts",
|
|
@@ -61,8 +62,12 @@
|
|
|
61
62
|
"fmt": "biome format --write .",
|
|
62
63
|
"fmt:check": "biome format .",
|
|
63
64
|
"bench": "vitest bench",
|
|
64
|
-
"
|
|
65
|
-
"test:e2e
|
|
65
|
+
"index-stats": "tsx plugs/index/index_stats.ts",
|
|
66
|
+
"test:e2e": "npx playwright test --project=chromium",
|
|
67
|
+
"test:e2e:headed": "npx playwright test --project=chromium --headed"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"preact": "^10.25.0"
|
|
66
71
|
},
|
|
67
72
|
"dependencies": {
|
|
68
73
|
"@cfworker/json-schema": "^4.1.1",
|
|
@@ -91,10 +96,11 @@
|
|
|
91
96
|
"@replit/codemirror-vim": "6.3.0",
|
|
92
97
|
"commander": "^14.0.3",
|
|
93
98
|
"crelt": "1.0.6",
|
|
99
|
+
"d3-force": "^3.0.0",
|
|
94
100
|
"esbuild": "^0.27.3",
|
|
95
101
|
"fast-diff": "1.3.0",
|
|
102
|
+
"force-graph": "^1.49.0",
|
|
96
103
|
"fast-glob": "^3.3.3",
|
|
97
|
-
"fuse.js": "7.1.0",
|
|
98
104
|
"gitignore-parser": "0.0.2",
|
|
99
105
|
"idb": "8.0.3",
|
|
100
106
|
"js-yaml": "^4.1.1",
|
|
@@ -110,11 +116,13 @@
|
|
|
110
116
|
"@biomejs/biome": "2.4.6",
|
|
111
117
|
"@playwright/test": "^1.58.2",
|
|
112
118
|
"@preact/preset-vite": "^2.10.3",
|
|
119
|
+
"@types/d3-force": "^3.0.10",
|
|
113
120
|
"@types/gitignore-parser": "^0.0.3",
|
|
114
121
|
"@types/js-yaml": "^4.0.9",
|
|
115
122
|
"@types/node": "^22.0.0",
|
|
116
123
|
"@types/turndown": "^5.0.6",
|
|
117
124
|
"fake-indexeddb": "6.0.1",
|
|
125
|
+
"preact-render-to-string": "^6.7.0",
|
|
118
126
|
"tsx": "^4.19.0",
|
|
119
127
|
"typescript": "^5.9.3",
|
|
120
128
|
"vite": "^7.3.1",
|
package/plug-api/lib/ref.ts
CHANGED
|
@@ -140,6 +140,102 @@ export function parseToRef(stringRef: string): Ref | null {
|
|
|
140
140
|
return ref;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Coerces a ref-or-string (including the legacy `{ page, pos, header }` shape)
|
|
145
|
+
* into a {@link Ref} and validates its structure, throwing on malformed input.
|
|
146
|
+
* Used wherever an external caller (e.g. a syscall) hands in a ref that may be a
|
|
147
|
+
* string or a legacy object.
|
|
148
|
+
*/
|
|
149
|
+
export function coerceAndValidateRef(ref: Ref | string): Ref {
|
|
150
|
+
if (typeof ref === "string") {
|
|
151
|
+
const parsedRef = parseToRef(ref);
|
|
152
|
+
if (!parsedRef) {
|
|
153
|
+
throw new Error("Unable to parse string as ref");
|
|
154
|
+
}
|
|
155
|
+
ref = parsedRef;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (
|
|
159
|
+
// @ts-expect-error: Legacy support
|
|
160
|
+
ref.page !== undefined
|
|
161
|
+
) {
|
|
162
|
+
console.warn(
|
|
163
|
+
"You are using legacy navigation syntax (`{ page, pos, header }`), this will be phased out in the future",
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const legacyRef = ref as unknown as {
|
|
167
|
+
kind: "page" | "document";
|
|
168
|
+
page: string;
|
|
169
|
+
pos?: number | { line: number; column: number };
|
|
170
|
+
header?: string;
|
|
171
|
+
meta?: boolean;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
legacyRef.kind ??= "page";
|
|
175
|
+
|
|
176
|
+
let details: Ref["details"];
|
|
177
|
+
|
|
178
|
+
if (typeof legacyRef.pos === "number") {
|
|
179
|
+
details = { type: "position", pos: legacyRef.pos };
|
|
180
|
+
} else if (legacyRef.pos) {
|
|
181
|
+
details = {
|
|
182
|
+
type: "linecolumn",
|
|
183
|
+
line: legacyRef.pos.line,
|
|
184
|
+
column: legacyRef.pos.column,
|
|
185
|
+
};
|
|
186
|
+
} else if (legacyRef.header) {
|
|
187
|
+
details = { type: "header", header: legacyRef.header };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
ref = {
|
|
191
|
+
path: (legacyRef.kind === "page"
|
|
192
|
+
? `${legacyRef.page}.md`
|
|
193
|
+
: legacyRef.page) as Path,
|
|
194
|
+
details,
|
|
195
|
+
meta: legacyRef.meta,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (!isValidPath(ref.path) && ref.path !== "") {
|
|
200
|
+
throw new Error("Path passed in ref is invalid");
|
|
201
|
+
} else if (typeof ref.meta !== "boolean" && ref.meta !== undefined) {
|
|
202
|
+
throw new Error("ref.meta has to be of type `boolean`");
|
|
203
|
+
} else if (ref.details !== undefined && typeof ref.details !== "object") {
|
|
204
|
+
throw new Error("ref.details has to be of type `object` or `undefined`");
|
|
205
|
+
} else if (
|
|
206
|
+
ref.details &&
|
|
207
|
+
!["position", "linecolumn", "header", "anchor"].includes(ref.details.type)
|
|
208
|
+
) {
|
|
209
|
+
throw new Error(
|
|
210
|
+
"ref.details.type has to be 'position', 'linecolumn', 'header' or 'anchor'",
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (ref.details?.type === "position" && typeof ref.details.pos !== "number") {
|
|
215
|
+
throw new Error("ref.details.pos has to be of type `number`");
|
|
216
|
+
} else if (
|
|
217
|
+
ref.details?.type === "header" &&
|
|
218
|
+
typeof ref.details.header !== "string"
|
|
219
|
+
) {
|
|
220
|
+
throw new Error("ref.details.header has to be of type `string`");
|
|
221
|
+
} else if (
|
|
222
|
+
ref.details?.type === "linecolumn" &&
|
|
223
|
+
typeof ref.details.line !== "number" &&
|
|
224
|
+
typeof ref.details.column !== "number"
|
|
225
|
+
) {
|
|
226
|
+
throw new Error(
|
|
227
|
+
"ref.details.line and ref.details.column has to be of type `number`",
|
|
228
|
+
);
|
|
229
|
+
} else if (
|
|
230
|
+
ref.details?.type === "anchor" &&
|
|
231
|
+
typeof ref.details.name !== "string"
|
|
232
|
+
) {
|
|
233
|
+
throw new Error("ref.details.name has to be of type `string`");
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return ref;
|
|
237
|
+
}
|
|
238
|
+
|
|
143
239
|
/**
|
|
144
240
|
* The inverse of {@link parseToRef}, encodes a ref object into a reference string.
|
|
145
241
|
* It tries to produce the shortest valid representation
|
package/plug-api/lib/shortcut.ts
CHANGED
|
@@ -60,9 +60,11 @@ export function define(key: string, schema: any): Promise<void> {
|
|
|
60
60
|
* ascending `order` (default 0); unknown categories fall to the bottom in
|
|
61
61
|
* alphabetical order.
|
|
62
62
|
*/
|
|
63
|
-
export function defineCategory(
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
export function defineCategory(definition: {
|
|
64
|
+
name: string;
|
|
65
|
+
description?: string;
|
|
66
|
+
order?: number;
|
|
67
|
+
}): Promise<void> {
|
|
66
68
|
return syscall("config.defineCategory", definition);
|
|
67
69
|
}
|
|
68
70
|
|
|
@@ -129,6 +129,22 @@ export function navigate(
|
|
|
129
129
|
return syscall("editor.navigate", ref, replaceState, newWindow);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Opens the specified page reference, restoring the previous cursor and scroll
|
|
134
|
+
* position for that page when one is remembered from the current session. Like
|
|
135
|
+
* navigate(), an explicit pointer in the ref (e.g. `#header`, `@123`) still wins.
|
|
136
|
+
* @param ref the page reference to open
|
|
137
|
+
* @param replaceState whether to replace the current history state in the browser history
|
|
138
|
+
* @param newWindow whether to open the page in a new window
|
|
139
|
+
*/
|
|
140
|
+
export function open(
|
|
141
|
+
ref: Ref | string,
|
|
142
|
+
replaceState = false,
|
|
143
|
+
newWindow = false,
|
|
144
|
+
): Promise<void> {
|
|
145
|
+
return syscall("editor.open", ref, replaceState, newWindow);
|
|
146
|
+
}
|
|
147
|
+
|
|
132
148
|
/**
|
|
133
149
|
* Opens the page navigator
|
|
134
150
|
* @param mode the mode to open the navigator in
|
|
@@ -374,10 +390,15 @@ export function prompt(
|
|
|
374
390
|
/**
|
|
375
391
|
* Prompt the user for confirmation
|
|
376
392
|
* @param message the message to show in the confirmation dialog
|
|
393
|
+
* @param options optional settings; set `destructive: true` to style the
|
|
394
|
+
* confirm button as a destructive (danger) action
|
|
377
395
|
* @returns
|
|
378
396
|
*/
|
|
379
|
-
export function confirm(
|
|
380
|
-
|
|
397
|
+
export function confirm(
|
|
398
|
+
message: string,
|
|
399
|
+
options?: { destructive?: boolean },
|
|
400
|
+
): Promise<boolean> {
|
|
401
|
+
return syscall("editor.confirm", message, options);
|
|
381
402
|
}
|
|
382
403
|
|
|
383
404
|
/**
|
|
@@ -4,7 +4,6 @@ import type {
|
|
|
4
4
|
} from "../../client/space_lua/query_collection.ts";
|
|
5
5
|
import { syscall } from "@silverbulletmd/silverbullet/syscall";
|
|
6
6
|
import type { ObjectValue } from "../../plug-api/types/index.ts";
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* Exposes the SilverBullet object indexing system
|
|
10
9
|
* @module
|
|
@@ -78,6 +77,13 @@ export function links(): Promise<LuaQueryCollection> {
|
|
|
78
77
|
return syscall("index.links");
|
|
79
78
|
}
|
|
80
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Returns all relation objects as a query collection.
|
|
82
|
+
*/
|
|
83
|
+
export function relations(): Promise<LuaQueryCollection> {
|
|
84
|
+
return syscall("index.relations");
|
|
85
|
+
}
|
|
86
|
+
|
|
81
87
|
/**
|
|
82
88
|
* Returns all tasks (optionally filtered by an additional tag) as a query collection.
|
|
83
89
|
*/
|
|
@@ -193,3 +199,20 @@ export function resolveAnchor(
|
|
|
193
199
|
): Promise<ResolveAnchorResult> {
|
|
194
200
|
return syscall("index.resolveAnchor", name, page);
|
|
195
201
|
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Returns a map of tag name → raw JSON Schema for every defined object-type /
|
|
205
|
+
* [[Tag]] that declares a schema. Tags without a schema are omitted.
|
|
206
|
+
* Use it to discover what attributes a tag's objects carry before querying them.
|
|
207
|
+
*/
|
|
208
|
+
export function describeSchema(): Promise<Record<string, unknown>> {
|
|
209
|
+
return syscall("index.describeSchema");
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Returns the raw JSON Schema for a single tag, or null if the tag is not
|
|
214
|
+
* defined or has no schema.
|
|
215
|
+
*/
|
|
216
|
+
export function tagSchema(tagName: string): Promise<unknown | null> {
|
|
217
|
+
return syscall("index.tagSchema", tagName);
|
|
218
|
+
}
|
|
@@ -21,3 +21,12 @@ export function validateObject(
|
|
|
21
21
|
export function validateSchema(schema: any): Promise<string | undefined> {
|
|
22
22
|
return syscall("jsonschema.validateSchema", schema);
|
|
23
23
|
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Infers a best-effort JSON schema from a sample value's shape.
|
|
27
|
+
* @param object the sample value to infer a schema from
|
|
28
|
+
* @returns an inferred JSON schema (draft 2020-12), marked `x-inferred`
|
|
29
|
+
*/
|
|
30
|
+
export function inferFromObject(object: any): Promise<any> {
|
|
31
|
+
return syscall("jsonschema.inferFromObject", object);
|
|
32
|
+
}
|
package/plug-api/syscalls/lua.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { syscall } from "../syscall.ts";
|
|
2
2
|
import type { LuaBlock, LuaExpression } from "../../client/space_lua/ast.ts";
|
|
3
|
+
import type { PrintOptions } from "../../client/space_lua/pretty_print.ts";
|
|
4
|
+
import type { LuaValueInspection } from "../types/index.ts";
|
|
3
5
|
|
|
6
|
+
export function parseBlock(code: string): Promise<LuaBlock> {
|
|
7
|
+
return syscall("lua.parseBlock", code);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** @deprecated use {@link parseBlock} instead */
|
|
4
11
|
export function parse(code: string): Promise<LuaBlock> {
|
|
5
|
-
return syscall("lua.
|
|
12
|
+
return syscall("lua.parseBlock", code);
|
|
6
13
|
}
|
|
7
14
|
|
|
8
15
|
export function parseExpression(expression: string): Promise<LuaExpression> {
|
|
@@ -12,3 +19,23 @@ export function parseExpression(expression: string): Promise<LuaExpression> {
|
|
|
12
19
|
export function evalExpression(expression: string): Promise<any> {
|
|
13
20
|
return syscall("lua.evalExpression", expression);
|
|
14
21
|
}
|
|
22
|
+
|
|
23
|
+
export function prettyPrintBlock(
|
|
24
|
+
block: LuaBlock,
|
|
25
|
+
opts?: PrintOptions,
|
|
26
|
+
): Promise<string> {
|
|
27
|
+
return syscall("lua.prettyPrintBlock", block, opts);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function prettyPrintExpression(
|
|
31
|
+
expression: LuaExpression,
|
|
32
|
+
opts?: PrintOptions,
|
|
33
|
+
): Promise<string> {
|
|
34
|
+
return syscall("lua.prettyPrintExpression", expression, opts);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function inspect(
|
|
38
|
+
path: string[] = [],
|
|
39
|
+
): Promise<LuaValueInspection | null> {
|
|
40
|
+
return syscall("lua.inspect", path);
|
|
41
|
+
}
|
|
@@ -51,6 +51,13 @@ export function reloadPlugs(): Promise<void> {
|
|
|
51
51
|
return syscall("system.reloadPlugs");
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Make edited-on-disk state live and wait until the client is ready again.
|
|
56
|
+
*/
|
|
57
|
+
export function reboot(): Promise<void> {
|
|
58
|
+
return syscall("system.reboot");
|
|
59
|
+
}
|
|
60
|
+
|
|
54
61
|
/**
|
|
55
62
|
* Load (or reload) a single plug from a space file path.
|
|
56
63
|
*/
|
package/plug-api/system_mock.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { eventSyscalls } from "../client/plugos/syscalls/event.ts";
|
|
|
12
12
|
import { indexSyscalls } from "../client/plugos/syscalls/index.ts";
|
|
13
13
|
import { jsonschemaSyscalls } from "../client/plugos/syscalls/jsonschema.ts";
|
|
14
14
|
import { languageSyscalls } from "../client/plugos/syscalls/language.ts";
|
|
15
|
-
import { luaSyscalls } from "../client/
|
|
15
|
+
import { luaSyscalls } from "../client/space_lua/syscalls.ts";
|
|
16
16
|
import { markdownSyscalls } from "../client/plugos/syscalls/markdown.ts";
|
|
17
17
|
import { mqSyscalls } from "../client/plugos/syscalls/mq.ts";
|
|
18
18
|
import {
|
|
@@ -64,7 +64,7 @@ export function createMockSystem() {
|
|
|
64
64
|
languageSyscalls(),
|
|
65
65
|
jsonschemaSyscalls(),
|
|
66
66
|
indexSyscalls(objectIndex, clientMock),
|
|
67
|
-
luaSyscalls(clientSystemMock),
|
|
67
|
+
luaSyscalls(system, () => clientSystemMock.spaceLuaEnv.env),
|
|
68
68
|
mqSyscalls(mq),
|
|
69
69
|
dataStoreReadSyscalls(ds, clientSystemMock),
|
|
70
70
|
dataStoreWriteSyscalls(ds),
|
package/plug-api/types/config.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type QueryCollationConfig = {
|
|
|
7
7
|
options?: object;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
type vimMode = "normal" | "insert" | "visual";
|
|
10
|
+
type vimMode = "normal" | "insert" | "visual" | "operator";
|
|
11
11
|
|
|
12
12
|
export type VimConfig = {
|
|
13
13
|
unmap?: (string | { key: string; mode?: vimMode })[];
|