@silverbulletmd/silverbullet 2.9.0 → 2.11.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 (123) hide show
  1. package/README.md +38 -25
  2. package/client/asset_bundle/bundle.ts +0 -1
  3. package/client/config.ts +343 -0
  4. package/client/markdown_parser/constants.ts +3 -1
  5. package/client/plugos/hooks/command.ts +0 -5
  6. package/client/plugos/hooks/event.ts +0 -6
  7. package/client/plugos/hooks/mq.ts +0 -3
  8. package/client/plugos/hooks/slash_command.ts +1 -7
  9. package/client/plugos/hooks/syscall.ts +24 -14
  10. package/client/plugos/manifest_cache.ts +0 -32
  11. package/client/plugos/plug.ts +0 -3
  12. package/client/plugos/plug_compile.ts +3 -13
  13. package/client/plugos/sandboxes/worker_sandbox.ts +19 -9
  14. package/client/plugos/syscalls/asset.ts +61 -23
  15. package/client/plugos/syscalls/clientStore.ts +32 -6
  16. package/client/plugos/syscalls/client_code_widget.ts +9 -4
  17. package/client/plugos/syscalls/code_widget.ts +26 -11
  18. package/client/plugos/syscalls/config.ts +146 -30
  19. package/client/plugos/syscalls/datastore.ts +146 -40
  20. package/client/plugos/syscalls/editor.ts +1518 -722
  21. package/client/plugos/syscalls/event.ts +44 -13
  22. package/client/plugos/syscalls/fetch.ts +120 -83
  23. package/client/plugos/syscalls/icon.ts +46 -0
  24. package/client/plugos/syscalls/index.ts +267 -121
  25. package/client/plugos/syscalls/jsonschema.ts +107 -9
  26. package/client/plugos/syscalls/language.ts +38 -12
  27. package/client/plugos/syscalls/markdown.ts +166 -50
  28. package/client/plugos/syscalls/mq.ts +92 -20
  29. package/client/plugos/syscalls/navigator.ts +143 -0
  30. package/client/plugos/syscalls/schema_introspection.ts +33 -0
  31. package/client/plugos/syscalls/search.ts +44 -0
  32. package/client/plugos/syscalls/service_registry.ts +74 -20
  33. package/client/plugos/syscalls/shell.ts +51 -21
  34. package/client/plugos/syscalls/space.ts +412 -113
  35. package/client/plugos/syscalls/sync.ts +103 -20
  36. package/client/plugos/syscalls/system.ts +274 -139
  37. package/client/plugos/system.ts +28 -10
  38. package/client/plugos/worker_runtime.ts +0 -2
  39. package/client/space_lua/aggregates.ts +0 -16
  40. package/client/space_lua/api_documentation.ts +107 -0
  41. package/client/space_lua/ast.ts +13 -5
  42. package/client/space_lua/ast_narrow.ts +0 -5
  43. package/client/space_lua/budget.ts +113 -0
  44. package/client/space_lua/budget_ui.ts +49 -0
  45. package/client/space_lua/eval.ts +125 -92
  46. package/client/space_lua/labels.ts +0 -4
  47. package/client/space_lua/numeric.ts +0 -5
  48. package/client/space_lua/parse.ts +243 -125
  49. package/client/space_lua/pretty_print.ts +128 -54
  50. package/client/space_lua/quarantine.ts +127 -0
  51. package/client/space_lua/query_collection.ts +7 -51
  52. package/client/space_lua/query_env.ts +0 -2
  53. package/client/space_lua/render_lua_markdown.ts +2 -7
  54. package/client/space_lua/render_widget.ts +173 -0
  55. package/client/space_lua/runtime.ts +133 -92
  56. package/client/space_lua/stdlib/crypto.ts +8 -3
  57. package/client/space_lua/stdlib/encoding.ts +27 -9
  58. package/client/space_lua/stdlib/format.ts +0 -12
  59. package/client/space_lua/stdlib/js.ts +136 -23
  60. package/client/space_lua/stdlib/load.ts +24 -16
  61. package/client/space_lua/stdlib/math.ts +331 -133
  62. package/client/space_lua/stdlib/net.ts +57 -13
  63. package/client/space_lua/stdlib/os.ts +111 -54
  64. package/client/space_lua/stdlib/pattern.ts +10 -15
  65. package/client/space_lua/stdlib/space_lua.ts +344 -21
  66. package/client/space_lua/stdlib/string.ts +282 -104
  67. package/client/space_lua/stdlib/string_pack.ts +58 -22
  68. package/client/space_lua/stdlib/table.ts +195 -45
  69. package/client/space_lua/stdlib.ts +354 -125
  70. package/client/space_lua/syscalls.ts +270 -0
  71. package/client/space_lua/tonumber.ts +0 -9
  72. package/dist/plug-compile.js +2 -3
  73. package/package.json +15 -5
  74. package/plug-api/lib/async.ts +1 -6
  75. package/plug-api/lib/collation.ts +22 -0
  76. package/plug-api/lib/crypto.ts +16 -15
  77. package/plug-api/lib/dates.ts +33 -0
  78. package/plug-api/lib/fuzzy.ts +282 -0
  79. package/plug-api/lib/json.ts +0 -6
  80. package/plug-api/lib/limited_map.ts +0 -2
  81. package/plug-api/lib/link_write.ts +27 -0
  82. package/plug-api/{ui → lib}/panel_styles.ts +4 -3
  83. package/plug-api/lib/ref.ts +124 -5
  84. package/plug-api/lib/resolve.ts +0 -1
  85. package/plug-api/lib/resolve_path.ts +290 -0
  86. package/plug-api/lib/shortcut.ts +17 -1
  87. package/plug-api/lib/tags.ts +0 -3
  88. package/plug-api/lib/transclusion.ts +28 -1
  89. package/plug-api/lib/tree.ts +0 -5
  90. package/plug-api/lib/yaml.ts +3 -42
  91. package/plug-api/syscall.ts +1 -5
  92. package/plug-api/syscalls/config.ts +7 -5
  93. package/plug-api/syscalls/editor.ts +70 -208
  94. package/plug-api/syscalls/icon.ts +18 -0
  95. package/plug-api/syscalls/index.ts +39 -5
  96. package/plug-api/syscalls/jsonschema.ts +9 -0
  97. package/plug-api/syscalls/lua.ts +7 -0
  98. package/plug-api/syscalls/search.ts +11 -0
  99. package/plug-api/syscalls/shell.ts +0 -1
  100. package/plug-api/syscalls/space.ts +122 -5
  101. package/plug-api/syscalls/sync.ts +23 -2
  102. package/plug-api/syscalls/system.ts +53 -0
  103. package/plug-api/syscalls.ts +2 -0
  104. package/plug-api/system_mock.ts +15 -2
  105. package/plug-api/types/client.ts +4 -3
  106. package/plug-api/types/datastore.ts +11 -2
  107. package/plug-api/types/index.ts +62 -1
  108. package/plug-api/types/manifest.ts +22 -4
  109. package/plug-api/types/profile.ts +13 -0
  110. package/plug-api/types/revisions.ts +67 -0
  111. package/plug-api/ui/cx.ts +1 -3
  112. package/plug-api/ui/description.ts +64 -0
  113. package/plug-api/ui/hover.ts +69 -0
  114. package/plug-api/ui/index.ts +61 -2
  115. package/plug-api/ui/scroll.ts +30 -0
  116. package/plug-api/ui/slugify.ts +44 -0
  117. package/plug-api/ui/tree_model.ts +263 -0
  118. package/plug-api/ui/tree_types.ts +66 -0
  119. package/plug-api/ui/use_fit_collapse.ts +67 -0
  120. package/plugs/builtin_plugs.ts +0 -1
  121. package/plugs/index/types.ts +9 -0
  122. package/client/plugos/syscalls/lua.ts +0 -81
  123. package/plug-api/lib/memory_cache.ts +0 -21
@@ -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
  *
@@ -70,7 +180,6 @@ export async function interpolateLuaString(
70
180
 
71
181
  result += template.slice(currentIndex, startIndex);
72
182
 
73
- // Find matching closing brace by counting nesting
74
183
  let nestLevel = 1;
75
184
  let endIndex = startIndex + 2;
76
185
  while (nestLevel > 0 && endIndex < template.length) {
@@ -126,6 +235,93 @@ function toPrintOptions(
126
235
  }
127
236
 
128
237
  export const spaceluaApi = new LuaTable({
238
+ describe: new LuaBuiltinFunction({
239
+ callback: (sf, target: ILuaFunction | string) => {
240
+ const value =
241
+ typeof target === "string" ? resolveApiValue(sf, target) : target;
242
+ return describeFunction(
243
+ value,
244
+ typeof target === "string" ? target : undefined,
245
+ );
246
+ },
247
+ description:
248
+ "Returns structured documentation for a Lua function value or dotted API name.",
249
+ parameters: [
250
+ {
251
+ name: "functionOrName",
252
+ type: "function|string",
253
+ description: "Function value or dotted API name to inspect.",
254
+ },
255
+ ],
256
+ returns: [
257
+ {
258
+ type: "table|nil",
259
+ description:
260
+ "Structured function metadata, or `nil` when the target is not a function.",
261
+ },
262
+ ],
263
+ examples: [
264
+ {
265
+ code: 'local info = spacelua.describe(editor.getText)\nprint(info.name, info.kind, info.see)\n\nlocal sameInfo = spacelua.describe("editor.getText")',
266
+ },
267
+ ],
268
+ see: "API/spacelua",
269
+ }),
270
+ listFunctions: new LuaBuiltinFunction({
271
+ callback: (sf, target?: LuaTable | string) =>
272
+ jsToLuaValue(listFunctionInfo(sf, target)),
273
+ description:
274
+ "Lists documented functions in the global environment or an API namespace.",
275
+ parameters: [
276
+ {
277
+ name: "namespace",
278
+ type: "table|string",
279
+ description: "Namespace table or dotted name; omit for globals.",
280
+ optional: true,
281
+ },
282
+ ],
283
+ returns: [{ type: "table", description: "Function metadata records." }],
284
+ examples: [
285
+ {
286
+ code: 'for info in each(spacelua.listFunctions("editor")) do\n print(info.name, info.description or info.see)\nend',
287
+ },
288
+ ],
289
+ see: "API/spacelua",
290
+ }),
291
+ renderApiDocumentation: new LuaBuiltinFunction({
292
+ callback: (sf, target?: ILuaFunction | LuaTable | string): string => {
293
+ const selection = apiDocumentationTarget(sf, target);
294
+ return renderApiDocumentationMarkdown(
295
+ selection.functions,
296
+ selection.context,
297
+ );
298
+ },
299
+ description:
300
+ "Renders API documentation for a function, namespace, or the global environment as Markdown.",
301
+ parameters: [
302
+ {
303
+ name: "target",
304
+ type: "function|table|string",
305
+ description:
306
+ "Function value, namespace table, or dotted API name to document; omit for globals.",
307
+ optional: true,
308
+ },
309
+ ],
310
+ returns: [{ type: "string", description: "Rendered Markdown." }],
311
+ examples: [
312
+ {
313
+ code: '${spacelua.renderApiDocumentation("lua")}',
314
+ description: "Render a namespace as a live API-page directive.",
315
+ language: "markdown",
316
+ },
317
+ {
318
+ code: '${spacelua.renderApiDocumentation("editor.getText")}',
319
+ description: "Render one function by its dotted API name.",
320
+ language: "markdown",
321
+ },
322
+ ],
323
+ see: "API/spacelua",
324
+ }),
129
325
  /**
130
326
  * Parses a lua expression and returns the parsed expression.
131
327
  *
@@ -133,8 +329,25 @@ export const spaceluaApi = new LuaTable({
133
329
  * @param luaExpression - The lua expression to parse.
134
330
  * @returns The parsed expression.
135
331
  */
136
- parseExpression: new LuaBuiltinFunction((_sf, luaExpression: string) => {
137
- return parseExpressionString(luaExpression);
332
+ parseExpression: new LuaBuiltinFunction({
333
+ callback: (_sf, luaExpression: string) => {
334
+ return parseExpressionString(luaExpression);
335
+ },
336
+ description: "Parses a Lua expression and returns its AST.",
337
+ parameters: [
338
+ {
339
+ name: "luaExpression",
340
+ type: "string",
341
+ description: "Lua expression to parse.",
342
+ },
343
+ ],
344
+ returns: [{ type: "table", description: "Parsed expression AST." }],
345
+ examples: [
346
+ {
347
+ code: 'local parsed = spacelua.parseExpression("1 + 1")',
348
+ },
349
+ ],
350
+ see: "API/spacelua",
138
351
  }),
139
352
  /**
140
353
  * Parses a lua chunk (block) and returns the parsed AST block.
@@ -143,8 +356,22 @@ export const spaceluaApi = new LuaTable({
143
356
  * @param code - The lua code to parse.
144
357
  * @returns The parsed block.
145
358
  */
146
- parseBlock: new LuaBuiltinFunction((_sf, code: string): LuaBlock => {
147
- return parseBlock(code);
359
+ parseBlock: new LuaBuiltinFunction({
360
+ callback: (_sf, code: string): LuaBlock => {
361
+ return parseBlock(code);
362
+ },
363
+ description:
364
+ "Parses a Lua chunk and returns its AST. Blocks retain comments in source order with their exact text, kind, and source range.",
365
+ parameters: [
366
+ { name: "code", type: "string", description: "Lua code to parse." },
367
+ ],
368
+ returns: [{ type: "table", description: "Parsed block AST." }],
369
+ examples: [
370
+ {
371
+ code: 'local parsed = spacelua.parseBlock("local x = 1\\nreturn x + 2")',
372
+ },
373
+ ],
374
+ see: "API/spacelua",
148
375
  }),
149
376
  /**
150
377
  * Pretty-prints a parsed lua block AST back to formatted source.
@@ -154,11 +381,30 @@ export const spaceluaApi = new LuaTable({
154
381
  * @param opts - Optional formatting options.
155
382
  * @returns The formatted lua source.
156
383
  */
157
- prettyPrintBlock: new LuaBuiltinFunction(
158
- (sf, block: LuaBlock, opts?: LuaTable): string => {
384
+ prettyPrintBlock: new LuaBuiltinFunction({
385
+ callback: (sf, block: LuaBlock, opts?: LuaTable): string => {
159
386
  return prettyPrintBlock(block, toPrintOptions(sf, opts));
160
387
  },
161
- ),
388
+ description:
389
+ "Pretty-prints a parsed Lua block AST. Comments are preserved while their placement and indentation are normalized.",
390
+ parameters: [
391
+ { name: "block", type: "table", description: "Parsed block AST." },
392
+ {
393
+ name: "options",
394
+ type: "table",
395
+ description:
396
+ "Formatting options: `indentWidth`, `quote`, and `trailingComma`.",
397
+ optional: true,
398
+ },
399
+ ],
400
+ returns: [{ type: "string", description: "Formatted Lua source." }],
401
+ examples: [
402
+ {
403
+ code: 'local formatted = spacelua.prettyPrintBlock(spacelua.parseBlock("if a then return 1 end"))\nprint(formatted)',
404
+ },
405
+ ],
406
+ see: "API/spacelua",
407
+ }),
162
408
  /**
163
409
  * Pretty-prints a parsed lua expression AST back to formatted source.
164
410
  *
@@ -167,11 +413,33 @@ export const spaceluaApi = new LuaTable({
167
413
  * @param opts - Optional formatting options.
168
414
  * @returns The formatted lua source.
169
415
  */
170
- prettyPrintExpression: new LuaBuiltinFunction(
171
- (sf, expr: LuaExpression, opts?: LuaTable): string => {
416
+ prettyPrintExpression: new LuaBuiltinFunction({
417
+ callback: (sf, expr: LuaExpression, opts?: LuaTable): string => {
172
418
  return prettyPrintExpression(expr, toPrintOptions(sf, opts));
173
419
  },
174
- ),
420
+ description: "Pretty-prints a parsed Lua expression AST.",
421
+ parameters: [
422
+ {
423
+ name: "parsedExpr",
424
+ type: "table",
425
+ description: "Parsed expression AST.",
426
+ },
427
+ {
428
+ name: "options",
429
+ type: "table",
430
+ description:
431
+ "Formatting options: `indentWidth`, `quote`, and `trailingComma`.",
432
+ optional: true,
433
+ },
434
+ ],
435
+ returns: [{ type: "string", description: "Formatted Lua source." }],
436
+ examples: [
437
+ {
438
+ code: 'local parsed = spacelua.parseExpression("{a=1,b=2}")\nprint(spacelua.prettyPrintExpression(parsed))',
439
+ },
440
+ ],
441
+ see: "API/spacelua",
442
+ }),
175
443
  /**
176
444
  * Evaluates a parsed lua expression and returns the result.
177
445
  *
@@ -180,28 +448,83 @@ export const spaceluaApi = new LuaTable({
180
448
  * @param envAugmentation - An optional environment to augment the global environment with.
181
449
  * @returns The result of the evaluated expression.
182
450
  */
183
- evalExpression: new LuaBuiltinFunction(
184
- async (sf, parsedExpr: LuaExpression, envAugmentation?: LuaTable) => {
451
+ evalExpression: new LuaBuiltinFunction({
452
+ callback: async (
453
+ sf,
454
+ parsedExpr: LuaExpression,
455
+ envAugmentation?: LuaTable,
456
+ ) => {
185
457
  const env = createAugmentedEnv(sf, envAugmentation);
186
458
  return luaValueToJS(await evalExpression(parsedExpr, env, sf), sf);
187
459
  },
188
- ),
460
+ description:
461
+ "Evaluates a parsed Lua expression, optionally with additional environment values.",
462
+ parameters: [
463
+ {
464
+ name: "parsedExpr",
465
+ type: "table",
466
+ description: "Parsed expression AST.",
467
+ },
468
+ {
469
+ name: "envAugmentation",
470
+ type: "table",
471
+ description: "Values added to the expression environment.",
472
+ optional: true,
473
+ },
474
+ ],
475
+ returns: [{ description: "Evaluated result." }],
476
+ examples: [
477
+ {
478
+ code: 'local parsed = spacelua.parseExpression("x + y")\nlocal result = spacelua.evalExpression(parsed, {x = 1, y = 2})\nprint(result)',
479
+ },
480
+ ],
481
+ see: "API/spacelua",
482
+ }),
189
483
  /**
190
484
  * Interpolates a string with lua expressions and returns the result.
191
485
  */
192
- interpolate: new LuaBuiltinFunction(
193
- (sf, template: string, envAugmentation?: LuaTable | any) => {
486
+ interpolate: new LuaBuiltinFunction({
487
+ callback: (sf, template: string, envAugmentation?: LuaTable | any) => {
194
488
  if (envAugmentation && !(envAugmentation instanceof LuaTable)) {
195
489
  envAugmentation = jsToLuaValue(envAugmentation);
196
490
  }
197
491
  return interpolateLuaString(sf, template, envAugmentation);
198
492
  },
199
- ),
493
+ description:
494
+ "Interpolates `${...}` Lua expressions in a string, optionally with additional environment values.",
495
+ parameters: [
496
+ {
497
+ name: "template",
498
+ type: "string",
499
+ description: "Template containing `${...}` expressions.",
500
+ },
501
+ {
502
+ name: "envAugmentation",
503
+ type: "table",
504
+ description: "Values added to the interpolation environment.",
505
+ optional: true,
506
+ },
507
+ ],
508
+ returns: [{ type: "string", description: "Interpolated string." }],
509
+ examples: [
510
+ {
511
+ code: 'local greeting = spacelua.interpolate("Hello ${name}!", {name = "Pete"})\nprint(greeting)',
512
+ },
513
+ ],
514
+ see: "API/spacelua",
515
+ }),
200
516
  /**
201
517
  * Returns your SilverBullet instance's base URL
202
518
  */
203
- baseUrl: new LuaBuiltinFunction(() => {
204
- //NOTE: Removing trailing slash to stay compatible with original code: `location.protocol + "//" + location.host;`
205
- return document.baseURI.replace(/\/*$/, "");
519
+ baseUrl: new LuaBuiltinFunction({
520
+ callback: () => {
521
+ // The origin contract excludes a trailing slash.
522
+ return document.baseURI.replace(/\/*$/, "");
523
+ },
524
+ description:
525
+ "Returns the SilverBullet instance's base URL, or `nil` when run on the server.",
526
+ returns: [{ type: "string|nil" }],
527
+ examples: [{ code: "local url = spacelua.baseUrl()\nprint(url)" }],
528
+ see: "API/spacelua",
206
529
  }),
207
530
  });