@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.
Files changed (63) hide show
  1. package/README.md +36 -23
  2. package/client/plugos/hooks/syscall.ts +24 -10
  3. package/client/plugos/syscalls/asset.ts +61 -23
  4. package/client/plugos/syscalls/clientStore.ts +32 -6
  5. package/client/plugos/syscalls/client_code_widget.ts +9 -4
  6. package/client/plugos/syscalls/code_widget.ts +26 -11
  7. package/client/plugos/syscalls/config.ts +146 -30
  8. package/client/plugos/syscalls/datastore.ts +146 -40
  9. package/client/plugos/syscalls/editor.ts +1432 -711
  10. package/client/plugos/syscalls/event.ts +46 -13
  11. package/client/plugos/syscalls/fetch.ts +123 -82
  12. package/client/plugos/syscalls/index.ts +242 -116
  13. package/client/plugos/syscalls/jsonschema.ts +107 -8
  14. package/client/plugos/syscalls/language.ts +38 -12
  15. package/client/plugos/syscalls/markdown.ts +166 -50
  16. package/client/plugos/syscalls/mq.ts +93 -20
  17. package/client/plugos/syscalls/schema_introspection.ts +33 -0
  18. package/client/plugos/syscalls/service_registry.ts +74 -20
  19. package/client/plugos/syscalls/shell.ts +51 -20
  20. package/client/plugos/syscalls/space.ts +169 -113
  21. package/client/plugos/syscalls/sync.ts +50 -19
  22. package/client/plugos/syscalls/system.ts +236 -139
  23. package/client/plugos/system.ts +21 -5
  24. package/client/space_lua/api_documentation.ts +107 -0
  25. package/client/space_lua/ast.ts +13 -0
  26. package/client/space_lua/eval.ts +12 -4
  27. package/client/space_lua/parse.ts +243 -108
  28. package/client/space_lua/pretty_print.ts +128 -54
  29. package/client/space_lua/query_collection.ts +4 -4
  30. package/client/space_lua/render_widget.ts +156 -0
  31. package/client/space_lua/runtime.ts +83 -22
  32. package/client/space_lua/stdlib/crypto.ts +8 -3
  33. package/client/space_lua/stdlib/encoding.ts +27 -9
  34. package/client/space_lua/stdlib/js.ts +137 -22
  35. package/client/space_lua/stdlib/load.ts +24 -15
  36. package/client/space_lua/stdlib/math.ts +323 -118
  37. package/client/space_lua/stdlib/net.ts +57 -9
  38. package/client/space_lua/stdlib/os.ts +111 -44
  39. package/client/space_lua/stdlib/space_lua.ts +344 -20
  40. package/client/space_lua/stdlib/string.ts +282 -104
  41. package/client/space_lua/stdlib/string_pack.ts +58 -19
  42. package/client/space_lua/stdlib/table.ts +195 -40
  43. package/client/space_lua/stdlib.ts +335 -93
  44. package/client/space_lua/syscalls.ts +270 -0
  45. package/dist/plug-compile.js +1 -1
  46. package/package.json +3 -3
  47. package/plug-api/lib/ref.ts +96 -0
  48. package/plug-api/lib/shortcut.ts +2 -1
  49. package/plug-api/syscalls/config.ts +5 -3
  50. package/plug-api/syscalls/editor.ts +16 -0
  51. package/plug-api/syscalls/index.ts +17 -1
  52. package/plug-api/syscalls/jsonschema.ts +9 -0
  53. package/plug-api/syscalls/lua.ts +7 -0
  54. package/plug-api/syscalls/shell.ts +0 -1
  55. package/plug-api/syscalls/system.ts +7 -0
  56. package/plug-api/system_mock.ts +2 -2
  57. package/plug-api/types/index.ts +52 -1
  58. package/plug-api/types/manifest.ts +22 -4
  59. package/plug-api/ui/cx.ts +1 -3
  60. package/plug-api/ui/index.ts +3 -0
  61. package/plug-api/ui/panel_styles.ts +4 -3
  62. package/plug-api/ui/slugify.ts +44 -0
  63. package/client/plugos/syscalls/lua.ts +0 -81
@@ -282,38 +282,71 @@ function luaFormatTime(fmt: string, d: Date, utc: boolean): string {
282
282
  }
283
283
 
284
284
  export const osApi = new LuaTable({
285
- time: new LuaBuiltinFunction((_sf, tbl?: LuaTable) => {
286
- if (tbl) {
287
- if (!tbl.has("year")) {
288
- throw new Error("time(): year is required");
285
+ time: new LuaBuiltinFunction({
286
+ callback: (_sf, tbl?: LuaTable) => {
287
+ if (tbl) {
288
+ if (!tbl.has("year")) {
289
+ throw new Error("time(): year is required");
290
+ }
291
+
292
+ if (!tbl.has("month")) {
293
+ throw new Error("time(): month is required");
294
+ }
295
+
296
+ if (!tbl.has("day")) {
297
+ throw new Error("time(): day is required");
298
+ }
299
+
300
+ const year = tbl.get("year");
301
+ const month = tbl.get("month");
302
+ const day = tbl.get("day");
303
+ const hour = tbl.get("hour") ?? 12;
304
+ const min = tbl.get("min") ?? 0;
305
+ const sec = tbl.get("sec") ?? 0;
306
+ const date = new Date(year, month - 1, day, hour, min, sec);
307
+
308
+ return Math.floor(date.getTime() / 1000);
289
309
  }
290
310
 
291
- if (!tbl.has("month")) {
292
- throw new Error("time(): month is required");
293
- }
294
-
295
- if (!tbl.has("day")) {
296
- throw new Error("time(): day is required");
297
- }
298
-
299
- const year = tbl.get("year");
300
- const month = tbl.get("month");
301
- const day = tbl.get("day");
302
- const hour = tbl.get("hour") ?? 12;
303
- const min = tbl.get("min") ?? 0;
304
- const sec = tbl.get("sec") ?? 0;
305
- const date = new Date(year, month - 1, day, hour, min, sec);
306
-
307
- return Math.floor(date.getTime() / 1000);
308
- }
309
-
310
- return Math.floor(Date.now() / 1000);
311
+ return Math.floor(Date.now() / 1000);
312
+ },
313
+ description:
314
+ "Returns the current Unix timestamp or one built from a local date table.",
315
+ signatures: ["os.time(): integer", "os.time(dateTable): integer"],
316
+ parameters: [
317
+ {
318
+ name: "dateTable",
319
+ type: "table",
320
+ description:
321
+ "Local date fields `year`, `month`, `day`, and optional `hour`, `min`, and `sec`.",
322
+ optional: true,
323
+ },
324
+ ],
325
+ returns: [
326
+ { type: "integer", description: "Seconds since the Unix epoch." },
327
+ ],
328
+ examples: [
329
+ {
330
+ code: "local timestamp = os.time({year = 2020, month = 1, day = 1})",
331
+ },
332
+ ],
311
333
  }),
312
334
 
313
335
  // Returns the difference, from time `t1` to time `t2` in seconds
314
336
  // In POSIX and some other systems, this value is exactly $t2-t1$.
315
- difftime: new LuaBuiltinFunction((_sf, t2: number, t1: number): number => {
316
- return t2 - t1;
337
+ difftime: new LuaBuiltinFunction({
338
+ callback: (_sf, t2: number, t1: number): number => {
339
+ return t2 - t1;
340
+ },
341
+ description:
342
+ "Returns the difference in seconds from timestamp `t1` to `t2`.",
343
+ parameters: [
344
+ { name: "t2", type: "number" },
345
+ { name: "t1", type: "number" },
346
+ ],
347
+ returns: [
348
+ { type: "number", description: "The value `t2 - t1` in seconds." },
349
+ ],
317
350
  }),
318
351
 
319
352
  // Returns a string or a table containing date and time, formatted
@@ -336,29 +369,63 @@ export const osApi = new LuaTable({
336
369
  // Otherwise, format specifiers follow ISO C `strftime`.
337
370
  //
338
371
  // If format is absent, it defaults to `%c`.
339
- date: new LuaBuiltinFunction((_sf, format?: string, timestamp?: number) => {
340
- let fmt = format ?? "%c";
341
- let utc = false;
342
-
343
- if (fmt.startsWith("!")) {
344
- utc = true;
345
- fmt = fmt.slice(1);
346
- }
372
+ date: new LuaBuiltinFunction({
373
+ callback: (_sf, format?: string, timestamp?: number) => {
374
+ let fmt = format ?? "%c";
375
+ let utc = false;
376
+
377
+ if (fmt.startsWith("!")) {
378
+ utc = true;
379
+ fmt = fmt.slice(1);
380
+ }
347
381
 
348
- const d =
349
- timestamp !== undefined && timestamp !== null
350
- ? new Date(timestamp * 1000)
351
- : new Date();
382
+ const d =
383
+ timestamp !== undefined && timestamp !== null
384
+ ? new Date(timestamp * 1000)
385
+ : new Date();
352
386
 
353
- if (fmt === "*t") {
354
- return dateTable(d, utc);
355
- }
387
+ if (fmt === "*t") {
388
+ return dateTable(d, utc);
389
+ }
356
390
 
357
- return luaFormatTime(fmt, d, utc);
391
+ return luaFormatTime(fmt, d, utc);
392
+ },
393
+ description:
394
+ "Formats a timestamp as a date string or date table, optionally in UTC.",
395
+ parameters: [
396
+ {
397
+ name: "format",
398
+ type: "string",
399
+ description:
400
+ "`strftime`-style format, `*t` for a table, and optional leading `!` for UTC.",
401
+ optional: true,
402
+ },
403
+ {
404
+ name: "timestamp",
405
+ type: "number",
406
+ description: "Unix timestamp; defaults to the current time.",
407
+ optional: true,
408
+ },
409
+ ],
410
+ returns: [
411
+ { type: "string|table", description: "Formatted date or date fields." },
412
+ ],
413
+ examples: [
414
+ { code: 'print(os.date("%Y-%m-%d"))\nlocal utc = os.date("!*t")' },
415
+ ],
358
416
  }),
359
417
 
360
418
  // Returns an approximation of CPU time used by the program in seconds.
361
- clock: new LuaBuiltinFunction((_sf): number => {
362
- return performance.now() / 1000.0;
419
+ clock: new LuaBuiltinFunction({
420
+ callback: (_sf): number => {
421
+ return performance.now() / 1000.0;
422
+ },
423
+ description: "Returns a high-resolution elapsed time value in seconds.",
424
+ returns: [
425
+ {
426
+ type: "number",
427
+ description: "Browser performance timer in seconds.",
428
+ },
429
+ ],
363
430
  }),
364
431
  });
@@ -1,12 +1,16 @@
1
- import { parseBlock, parseExpressionString } from "../parse.ts";
1
+ import type { LuaFunctionInfo } from "../../../plug-api/types/index.ts";
2
+ import { renderApiDocumentationMarkdown } from "../api_documentation.ts";
2
3
  import type { LuaBlock, LuaExpression } from "../ast.ts";
3
4
  import { evalExpression } from "../eval.ts";
5
+ import { parseBlock, parseExpressionString } from "../parse.ts";
4
6
  import {
5
7
  type PrintOptions,
6
8
  prettyPrintBlock,
7
9
  prettyPrintExpression,
8
10
  } from "../pretty_print.ts";
9
11
  import {
12
+ type ILuaFunction,
13
+ isILuaFunction,
10
14
  jsToLuaValue,
11
15
  LuaBuiltinFunction,
12
16
  LuaEnv,
@@ -45,6 +49,112 @@ function createAugmentedEnv(
45
49
  return env;
46
50
  }
47
51
 
52
+ function globalEnv(sf: LuaStackFrame): LuaEnv {
53
+ const env = sf.threadLocal.get("_GLOBAL");
54
+ if (!(env instanceof LuaEnv)) {
55
+ throw new Error("_GLOBAL not defined");
56
+ }
57
+ return env;
58
+ }
59
+
60
+ function resolveApiValue(
61
+ sf: LuaStackFrame,
62
+ path: string,
63
+ ): ILuaFunction | LuaTable | LuaEnv | null {
64
+ let value: any = globalEnv(sf);
65
+ for (const part of path.split(".")) {
66
+ if (value instanceof LuaEnv || value instanceof LuaTable) {
67
+ value = value.get(part, sf);
68
+ } else {
69
+ return null;
70
+ }
71
+ if (value && typeof value.then === "function") {
72
+ throw new Error("Cannot describe asynchronously resolved API values");
73
+ }
74
+ if (value === null || value === undefined) return null;
75
+ }
76
+ return value;
77
+ }
78
+
79
+ function functionInfo(
80
+ value: unknown,
81
+ resolvedName?: string,
82
+ ): LuaFunctionInfo | null {
83
+ if (!isILuaFunction(value)) return null;
84
+ return {
85
+ ...(value.info ?? { kind: "builtin" }),
86
+ name: value.info?.name ?? resolvedName,
87
+ };
88
+ }
89
+
90
+ function describeFunction(
91
+ value: unknown,
92
+ resolvedName?: string,
93
+ ): LuaTable | null {
94
+ const info = functionInfo(value, resolvedName);
95
+ return info ? (jsToLuaValue(info) as LuaTable) : null;
96
+ }
97
+
98
+ function listFunctionInfo(
99
+ sf: LuaStackFrame,
100
+ target?: LuaTable | string,
101
+ ): LuaFunctionInfo[] {
102
+ let namespace: LuaTable | LuaEnv;
103
+ let prefix = "";
104
+ if (typeof target === "string") {
105
+ const resolved = resolveApiValue(sf, target);
106
+ if (!(resolved instanceof LuaTable) && !(resolved instanceof LuaEnv)) {
107
+ return [];
108
+ }
109
+ namespace = resolved;
110
+ prefix = `${target}.`;
111
+ } else if (target instanceof LuaTable) {
112
+ namespace = target;
113
+ } else {
114
+ namespace = globalEnv(sf);
115
+ }
116
+
117
+ const functions: LuaFunctionInfo[] = [];
118
+ for (const key of [...new Set(namespace.keys())].sort()) {
119
+ const value = namespace.get(key, sf);
120
+ if (value && typeof (value as any).then === "function") continue;
121
+ const info = functionInfo(value, `${prefix}${key}`);
122
+ if (info) functions.push(info);
123
+ }
124
+ return functions;
125
+ }
126
+
127
+ function functionNamespace(info: LuaFunctionInfo): string | undefined {
128
+ const separator = info.name?.lastIndexOf(".") ?? -1;
129
+ return separator > 0 ? info.name!.slice(0, separator) : undefined;
130
+ }
131
+
132
+ function apiDocumentationTarget(
133
+ sf: LuaStackFrame,
134
+ target?: ILuaFunction | LuaTable | string,
135
+ ): { functions: LuaFunctionInfo[]; context?: string } {
136
+ if (typeof target === "string") {
137
+ const resolved = resolveApiValue(sf, target);
138
+ const info = functionInfo(resolved, target);
139
+ if (info) {
140
+ return { functions: [info], context: functionNamespace(info) };
141
+ }
142
+ if (resolved instanceof LuaTable || resolved instanceof LuaEnv) {
143
+ return { functions: listFunctionInfo(sf, target), context: target };
144
+ }
145
+ return { functions: [], context: target };
146
+ }
147
+
148
+ const info = functionInfo(target);
149
+ if (info) {
150
+ return { functions: [info], context: functionNamespace(info) };
151
+ }
152
+ if (target instanceof LuaTable) {
153
+ return { functions: listFunctionInfo(sf, target) };
154
+ }
155
+ return { functions: listFunctionInfo(sf) };
156
+ }
157
+
48
158
  /**
49
159
  * Interpolates a string with lua expressions and returns the result.
50
160
  *
@@ -126,6 +236,93 @@ function toPrintOptions(
126
236
  }
127
237
 
128
238
  export const spaceluaApi = new LuaTable({
239
+ describe: new LuaBuiltinFunction({
240
+ callback: (sf, target: ILuaFunction | string) => {
241
+ const value =
242
+ typeof target === "string" ? resolveApiValue(sf, target) : target;
243
+ return describeFunction(
244
+ value,
245
+ typeof target === "string" ? target : undefined,
246
+ );
247
+ },
248
+ description:
249
+ "Returns structured documentation for a Lua function value or dotted API name.",
250
+ parameters: [
251
+ {
252
+ name: "functionOrName",
253
+ type: "function|string",
254
+ description: "Function value or dotted API name to inspect.",
255
+ },
256
+ ],
257
+ returns: [
258
+ {
259
+ type: "table|nil",
260
+ description:
261
+ "Structured function metadata, or `nil` when the target is not a function.",
262
+ },
263
+ ],
264
+ examples: [
265
+ {
266
+ code: 'local info = spacelua.describe(editor.getText)\nprint(info.name, info.kind, info.see)\n\nlocal sameInfo = spacelua.describe("editor.getText")',
267
+ },
268
+ ],
269
+ see: "API/spacelua",
270
+ }),
271
+ listFunctions: new LuaBuiltinFunction({
272
+ callback: (sf, target?: LuaTable | string) =>
273
+ jsToLuaValue(listFunctionInfo(sf, target)),
274
+ description:
275
+ "Lists documented functions in the global environment or an API namespace.",
276
+ parameters: [
277
+ {
278
+ name: "namespace",
279
+ type: "table|string",
280
+ description: "Namespace table or dotted name; omit for globals.",
281
+ optional: true,
282
+ },
283
+ ],
284
+ returns: [{ type: "table", description: "Function metadata records." }],
285
+ examples: [
286
+ {
287
+ code: 'for info in each(spacelua.listFunctions("editor")) do\n print(info.name, info.description or info.see)\nend',
288
+ },
289
+ ],
290
+ see: "API/spacelua",
291
+ }),
292
+ renderApiDocumentation: new LuaBuiltinFunction({
293
+ callback: (sf, target?: ILuaFunction | LuaTable | string): string => {
294
+ const selection = apiDocumentationTarget(sf, target);
295
+ return renderApiDocumentationMarkdown(
296
+ selection.functions,
297
+ selection.context,
298
+ );
299
+ },
300
+ description:
301
+ "Renders API documentation for a function, namespace, or the global environment as Markdown.",
302
+ parameters: [
303
+ {
304
+ name: "target",
305
+ type: "function|table|string",
306
+ description:
307
+ "Function value, namespace table, or dotted API name to document; omit for globals.",
308
+ optional: true,
309
+ },
310
+ ],
311
+ returns: [{ type: "string", description: "Rendered Markdown." }],
312
+ examples: [
313
+ {
314
+ code: '${spacelua.renderApiDocumentation("lua")}',
315
+ description: "Render a namespace as a live API-page directive.",
316
+ language: "markdown",
317
+ },
318
+ {
319
+ code: '${spacelua.renderApiDocumentation("editor.getText")}',
320
+ description: "Render one function by its dotted API name.",
321
+ language: "markdown",
322
+ },
323
+ ],
324
+ see: "API/spacelua",
325
+ }),
129
326
  /**
130
327
  * Parses a lua expression and returns the parsed expression.
131
328
  *
@@ -133,8 +330,25 @@ export const spaceluaApi = new LuaTable({
133
330
  * @param luaExpression - The lua expression to parse.
134
331
  * @returns The parsed expression.
135
332
  */
136
- parseExpression: new LuaBuiltinFunction((_sf, luaExpression: string) => {
137
- return parseExpressionString(luaExpression);
333
+ parseExpression: new LuaBuiltinFunction({
334
+ callback: (_sf, luaExpression: string) => {
335
+ return parseExpressionString(luaExpression);
336
+ },
337
+ description: "Parses a Lua expression and returns its AST.",
338
+ parameters: [
339
+ {
340
+ name: "luaExpression",
341
+ type: "string",
342
+ description: "Lua expression to parse.",
343
+ },
344
+ ],
345
+ returns: [{ type: "table", description: "Parsed expression AST." }],
346
+ examples: [
347
+ {
348
+ code: 'local parsed = spacelua.parseExpression("1 + 1")',
349
+ },
350
+ ],
351
+ see: "API/spacelua",
138
352
  }),
139
353
  /**
140
354
  * Parses a lua chunk (block) and returns the parsed AST block.
@@ -143,8 +357,22 @@ export const spaceluaApi = new LuaTable({
143
357
  * @param code - The lua code to parse.
144
358
  * @returns The parsed block.
145
359
  */
146
- parseBlock: new LuaBuiltinFunction((_sf, code: string): LuaBlock => {
147
- return parseBlock(code);
360
+ parseBlock: new LuaBuiltinFunction({
361
+ callback: (_sf, code: string): LuaBlock => {
362
+ return parseBlock(code);
363
+ },
364
+ description:
365
+ "Parses a Lua chunk and returns its AST. Blocks retain comments in source order with their exact text, kind, and source range.",
366
+ parameters: [
367
+ { name: "code", type: "string", description: "Lua code to parse." },
368
+ ],
369
+ returns: [{ type: "table", description: "Parsed block AST." }],
370
+ examples: [
371
+ {
372
+ code: 'local parsed = spacelua.parseBlock("local x = 1\\nreturn x + 2")',
373
+ },
374
+ ],
375
+ see: "API/spacelua",
148
376
  }),
149
377
  /**
150
378
  * Pretty-prints a parsed lua block AST back to formatted source.
@@ -154,11 +382,30 @@ export const spaceluaApi = new LuaTable({
154
382
  * @param opts - Optional formatting options.
155
383
  * @returns The formatted lua source.
156
384
  */
157
- prettyPrintBlock: new LuaBuiltinFunction(
158
- (sf, block: LuaBlock, opts?: LuaTable): string => {
385
+ prettyPrintBlock: new LuaBuiltinFunction({
386
+ callback: (sf, block: LuaBlock, opts?: LuaTable): string => {
159
387
  return prettyPrintBlock(block, toPrintOptions(sf, opts));
160
388
  },
161
- ),
389
+ description:
390
+ "Pretty-prints a parsed Lua block AST. Comments are preserved while their placement and indentation are normalized.",
391
+ parameters: [
392
+ { name: "block", type: "table", description: "Parsed block AST." },
393
+ {
394
+ name: "options",
395
+ type: "table",
396
+ description:
397
+ "Formatting options: `indentWidth`, `quote`, and `trailingComma`.",
398
+ optional: true,
399
+ },
400
+ ],
401
+ returns: [{ type: "string", description: "Formatted Lua source." }],
402
+ examples: [
403
+ {
404
+ code: 'local formatted = spacelua.prettyPrintBlock(spacelua.parseBlock("if a then return 1 end"))\nprint(formatted)',
405
+ },
406
+ ],
407
+ see: "API/spacelua",
408
+ }),
162
409
  /**
163
410
  * Pretty-prints a parsed lua expression AST back to formatted source.
164
411
  *
@@ -167,11 +414,33 @@ export const spaceluaApi = new LuaTable({
167
414
  * @param opts - Optional formatting options.
168
415
  * @returns The formatted lua source.
169
416
  */
170
- prettyPrintExpression: new LuaBuiltinFunction(
171
- (sf, expr: LuaExpression, opts?: LuaTable): string => {
417
+ prettyPrintExpression: new LuaBuiltinFunction({
418
+ callback: (sf, expr: LuaExpression, opts?: LuaTable): string => {
172
419
  return prettyPrintExpression(expr, toPrintOptions(sf, opts));
173
420
  },
174
- ),
421
+ description: "Pretty-prints a parsed Lua expression AST.",
422
+ parameters: [
423
+ {
424
+ name: "parsedExpr",
425
+ type: "table",
426
+ description: "Parsed expression AST.",
427
+ },
428
+ {
429
+ name: "options",
430
+ type: "table",
431
+ description:
432
+ "Formatting options: `indentWidth`, `quote`, and `trailingComma`.",
433
+ optional: true,
434
+ },
435
+ ],
436
+ returns: [{ type: "string", description: "Formatted Lua source." }],
437
+ examples: [
438
+ {
439
+ code: 'local parsed = spacelua.parseExpression("{a=1,b=2}")\nprint(spacelua.prettyPrintExpression(parsed))',
440
+ },
441
+ ],
442
+ see: "API/spacelua",
443
+ }),
175
444
  /**
176
445
  * Evaluates a parsed lua expression and returns the result.
177
446
  *
@@ -180,28 +449,83 @@ export const spaceluaApi = new LuaTable({
180
449
  * @param envAugmentation - An optional environment to augment the global environment with.
181
450
  * @returns The result of the evaluated expression.
182
451
  */
183
- evalExpression: new LuaBuiltinFunction(
184
- async (sf, parsedExpr: LuaExpression, envAugmentation?: LuaTable) => {
452
+ evalExpression: new LuaBuiltinFunction({
453
+ callback: async (
454
+ sf,
455
+ parsedExpr: LuaExpression,
456
+ envAugmentation?: LuaTable,
457
+ ) => {
185
458
  const env = createAugmentedEnv(sf, envAugmentation);
186
459
  return luaValueToJS(await evalExpression(parsedExpr, env, sf), sf);
187
460
  },
188
- ),
461
+ description:
462
+ "Evaluates a parsed Lua expression, optionally with additional environment values.",
463
+ parameters: [
464
+ {
465
+ name: "parsedExpr",
466
+ type: "table",
467
+ description: "Parsed expression AST.",
468
+ },
469
+ {
470
+ name: "envAugmentation",
471
+ type: "table",
472
+ description: "Values added to the expression environment.",
473
+ optional: true,
474
+ },
475
+ ],
476
+ returns: [{ description: "Evaluated result." }],
477
+ examples: [
478
+ {
479
+ code: 'local parsed = spacelua.parseExpression("x + y")\nlocal result = spacelua.evalExpression(parsed, {x = 1, y = 2})\nprint(result)',
480
+ },
481
+ ],
482
+ see: "API/spacelua",
483
+ }),
189
484
  /**
190
485
  * Interpolates a string with lua expressions and returns the result.
191
486
  */
192
- interpolate: new LuaBuiltinFunction(
193
- (sf, template: string, envAugmentation?: LuaTable | any) => {
487
+ interpolate: new LuaBuiltinFunction({
488
+ callback: (sf, template: string, envAugmentation?: LuaTable | any) => {
194
489
  if (envAugmentation && !(envAugmentation instanceof LuaTable)) {
195
490
  envAugmentation = jsToLuaValue(envAugmentation);
196
491
  }
197
492
  return interpolateLuaString(sf, template, envAugmentation);
198
493
  },
199
- ),
494
+ description:
495
+ "Interpolates `${...}` Lua expressions in a string, optionally with additional environment values.",
496
+ parameters: [
497
+ {
498
+ name: "template",
499
+ type: "string",
500
+ description: "Template containing `${...}` expressions.",
501
+ },
502
+ {
503
+ name: "envAugmentation",
504
+ type: "table",
505
+ description: "Values added to the interpolation environment.",
506
+ optional: true,
507
+ },
508
+ ],
509
+ returns: [{ type: "string", description: "Interpolated string." }],
510
+ examples: [
511
+ {
512
+ code: 'local greeting = spacelua.interpolate("Hello ${name}!", {name = "Pete"})\nprint(greeting)',
513
+ },
514
+ ],
515
+ see: "API/spacelua",
516
+ }),
200
517
  /**
201
518
  * Returns your SilverBullet instance's base URL
202
519
  */
203
- baseUrl: new LuaBuiltinFunction(() => {
204
- //NOTE: Removing trailing slash to stay compatible with original code: `location.protocol + "//" + location.host;`
205
- return document.baseURI.replace(/\/*$/, "");
520
+ baseUrl: new LuaBuiltinFunction({
521
+ callback: () => {
522
+ //NOTE: Removing trailing slash to stay compatible with original code: `location.protocol + "//" + location.host;`
523
+ return document.baseURI.replace(/\/*$/, "");
524
+ },
525
+ description:
526
+ "Returns the SilverBullet instance's base URL, or `nil` when run on the server.",
527
+ returns: [{ type: "string|nil" }],
528
+ examples: [{ code: "local url = spacelua.baseUrl()\nprint(url)" }],
529
+ see: "API/spacelua",
206
530
  }),
207
531
  });