@silverbulletmd/silverbullet 2.4.2 → 2.6.1

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 (97) hide show
  1. package/README.md +19 -4
  2. package/client/asset_bundle/bundle.ts +3 -9
  3. package/client/data/datastore.ts +4 -5
  4. package/client/markdown_parser/constants.ts +5 -4
  5. package/client/plugos/hooks/code_widget.ts +3 -8
  6. package/client/plugos/hooks/command.ts +8 -8
  7. package/client/plugos/hooks/document_editor.ts +10 -15
  8. package/client/plugos/hooks/event.ts +33 -36
  9. package/client/plugos/hooks/mq.ts +17 -17
  10. package/client/plugos/hooks/plug_namespace.ts +3 -8
  11. package/client/plugos/hooks/slash_command.ts +13 -28
  12. package/client/plugos/hooks/syscall.ts +3 -3
  13. package/client/plugos/manifest_cache.ts +22 -15
  14. package/client/plugos/plug.ts +2 -6
  15. package/client/plugos/plug_compile.ts +79 -78
  16. package/client/plugos/protocol.ts +28 -28
  17. package/client/plugos/proxy_fetch.ts +7 -6
  18. package/client/plugos/sandboxes/web_worker_sandbox.ts +1 -1
  19. package/client/plugos/sandboxes/worker_sandbox.ts +18 -18
  20. package/client/plugos/syscalls/asset.ts +1 -3
  21. package/client/plugos/syscalls/code_widget.ts +1 -3
  22. package/client/plugos/syscalls/config.ts +1 -5
  23. package/client/plugos/syscalls/datastore.ts +1 -1
  24. package/client/plugos/syscalls/editor.ts +72 -69
  25. package/client/plugos/syscalls/event.ts +9 -12
  26. package/client/plugos/syscalls/fetch.ts +31 -23
  27. package/client/plugos/syscalls/index.ts +10 -1
  28. package/client/plugos/syscalls/jsonschema.ts +72 -32
  29. package/client/plugos/syscalls/language.ts +9 -5
  30. package/client/plugos/syscalls/markdown.ts +29 -7
  31. package/client/plugos/syscalls/mq.ts +4 -12
  32. package/client/plugos/syscalls/service_registry.ts +1 -4
  33. package/client/plugos/syscalls/shell.ts +2 -5
  34. package/client/plugos/syscalls/space.ts +1 -1
  35. package/client/plugos/syscalls/sync.ts +69 -60
  36. package/client/plugos/syscalls/system.ts +2 -3
  37. package/client/plugos/system.ts +6 -12
  38. package/client/plugos/worker_runtime.ts +12 -33
  39. package/client/space_lua/aggregates.ts +782 -0
  40. package/client/space_lua/ast.ts +42 -8
  41. package/client/space_lua/ast_narrow.ts +4 -2
  42. package/client/space_lua/eval.ts +886 -575
  43. package/client/space_lua/labels.ts +7 -12
  44. package/client/space_lua/liq_null.ts +6 -0
  45. package/client/space_lua/numeric.ts +5 -8
  46. package/client/space_lua/parse.ts +346 -120
  47. package/client/space_lua/query_collection.ts +926 -82
  48. package/client/space_lua/query_env.ts +26 -0
  49. package/client/space_lua/render_lua_markdown.ts +369 -0
  50. package/client/space_lua/rp.ts +5 -4
  51. package/client/space_lua/runtime.ts +288 -155
  52. package/client/space_lua/stdlib/format.ts +53 -39
  53. package/client/space_lua/stdlib/js.ts +3 -7
  54. package/client/space_lua/stdlib/load.ts +1 -3
  55. package/client/space_lua/stdlib/math.ts +84 -58
  56. package/client/space_lua/stdlib/net.ts +27 -17
  57. package/client/space_lua/stdlib/os.ts +81 -85
  58. package/client/space_lua/stdlib/pattern.ts +695 -0
  59. package/client/space_lua/stdlib/prng.ts +148 -0
  60. package/client/space_lua/stdlib/space_lua.ts +17 -23
  61. package/client/space_lua/stdlib/string.ts +102 -190
  62. package/client/space_lua/stdlib/string_pack.ts +490 -0
  63. package/client/space_lua/stdlib/table.ts +76 -16
  64. package/client/space_lua/stdlib.ts +53 -39
  65. package/client/space_lua/tonumber.ts +82 -42
  66. package/client/space_lua/util.ts +53 -15
  67. package/dist/plug-compile.js +55 -98
  68. package/package.json +27 -20
  69. package/plug-api/constants.ts +0 -32
  70. package/plug-api/lib/async.ts +20 -7
  71. package/plug-api/lib/crypto.ts +16 -17
  72. package/plug-api/lib/dates.ts +15 -7
  73. package/plug-api/lib/json.ts +11 -5
  74. package/plug-api/lib/limited_map.ts +1 -1
  75. package/plug-api/lib/native_fetch.ts +2 -0
  76. package/plug-api/lib/ref.ts +23 -23
  77. package/plug-api/lib/resolve.ts +7 -11
  78. package/plug-api/lib/tags.ts +13 -4
  79. package/plug-api/lib/transclusion.ts +10 -21
  80. package/plug-api/lib/tree.ts +165 -45
  81. package/plug-api/lib/yaml.ts +35 -25
  82. package/plug-api/syscalls/asset.ts +1 -1
  83. package/plug-api/syscalls/config.ts +1 -4
  84. package/plug-api/syscalls/editor.ts +15 -15
  85. package/plug-api/syscalls/jsonschema.ts +1 -3
  86. package/plug-api/syscalls/lua.ts +3 -9
  87. package/plug-api/syscalls/mq.ts +1 -4
  88. package/plug-api/syscalls/shell.ts +4 -1
  89. package/plug-api/syscalls/space.ts +3 -10
  90. package/plug-api/syscalls/system.ts +1 -4
  91. package/plug-api/syscalls/yaml.ts +2 -6
  92. package/plug-api/system_mock.ts +0 -1
  93. package/plug-api/types/client.ts +16 -1
  94. package/plug-api/types/event.ts +6 -4
  95. package/plug-api/types/manifest.ts +8 -9
  96. package/plugs/builtin_plugs.ts +2 -2
  97. package/client/plugos/sandboxes/deno_worker_sandbox.ts +0 -6
@@ -25,7 +25,9 @@ function serializeToYamlScalar(
25
25
  // Simple strings without special chars/meaning don't need quotes
26
26
  return value;
27
27
  } else if (
28
- typeof value === "number" || typeof value === "boolean" || value === null
28
+ typeof value === "number" ||
29
+ typeof value === "boolean" ||
30
+ value === null
29
31
  ) {
30
32
  return String(value);
31
33
  }
@@ -44,36 +46,44 @@ function serializeToYamlValue(
44
46
  return "[]"; // Use flow style for empty arrays for simplicity
45
47
  }
46
48
  // Determine indentation for list items (base + 2 spaces)
47
- const itemIndentation = baseIndentation + " ";
49
+ const itemIndentation = `${baseIndentation} `;
48
50
  // Format each item recursively, preceded by '- ' marker
49
- return "\n" +
50
- value.map((item) =>
51
- `${itemIndentation}- ${serializeToYamlValue(item, itemIndentation)}`
52
- ).join("\n");
51
+ return (
52
+ "\n" +
53
+ value
54
+ .map(
55
+ (item) =>
56
+ `${itemIndentation}- ${serializeToYamlValue(item, itemIndentation)}`,
57
+ )
58
+ .join("\n")
59
+ );
53
60
  // Note: serializeToYamlValue is used recursively here to handle nested arrays/objects if needed in future
54
61
  // However, the current `applyMinimalSetKeyPatches` only handles top-level keys.
55
62
  } else if (typeof value === "object" && value !== null) {
56
63
  // Basic object serialization (not requested, but good to consider)
57
64
  // This is highly simplified and doesn't handle nesting well without more context
58
- const itemIndentation = baseIndentation + " ";
65
+ const itemIndentation = `${baseIndentation} `;
59
66
  const entries = Object.entries(value);
60
67
  if (entries.length === 0) return "{}"; // Flow style empty objects
61
- return "\n" +
62
- entries.map(([key, val]) =>
63
- `${itemIndentation}${key}: ${
64
- serializeToYamlValue(val, itemIndentation)
65
- }`
66
- ).join("\n");
68
+ return (
69
+ "\n" +
70
+ entries
71
+ .map(
72
+ ([key, val]) =>
73
+ `${itemIndentation}${key}: ${serializeToYamlValue(
74
+ val,
75
+ itemIndentation,
76
+ )}`,
77
+ )
78
+ .join("\n")
79
+ );
67
80
  } else {
68
81
  // Handle scalars using the dedicated function
69
82
  return serializeToYamlScalar(value);
70
83
  }
71
84
  }
72
85
 
73
- export function applyPatches(
74
- yamlString: string,
75
- patches: YamlPatch[],
76
- ): string {
86
+ export function applyPatches(yamlString: string, patches: YamlPatch[]): string {
77
87
  let currentYaml = yamlString;
78
88
 
79
89
  for (const patch of patches) {
@@ -89,7 +99,7 @@ export function applyPatches(
89
99
  for (let i = 0; i < lines.length; i++) {
90
100
  const line = lines[i];
91
101
  const trimmedLine = line.trim();
92
- if (trimmedLine.startsWith(key + ":")) {
102
+ if (trimmedLine.startsWith(`${key}:`)) {
93
103
  keyLineIndex = i;
94
104
  startDeleteIndex = i;
95
105
  endDeleteIndex = i;
@@ -203,7 +213,7 @@ export function applyPatches(
203
213
  for (let i = 0; i < lines.length; i++) {
204
214
  const line = lines[i];
205
215
  const trimmedLine = line.trim();
206
- if (trimmedLine.startsWith(key + ":")) {
216
+ if (trimmedLine.startsWith(`${key}:`)) {
207
217
  keyLineIndex = i;
208
218
  // Extract inline comment if present
209
219
  const commentMatch = line.match(/#.*$/);
@@ -214,7 +224,7 @@ export function applyPatches(
214
224
  for (let j = i - 1; j >= 0; j--) {
215
225
  const prevLine = lines[j].trim();
216
226
  if (prevLine.startsWith("#")) {
217
- commentBlock = lines[j] + "\n" + commentBlock;
227
+ commentBlock = `${lines[j]}\n${commentBlock}`;
218
228
  } else if (prevLine !== "") {
219
229
  break;
220
230
  }
@@ -223,7 +233,7 @@ export function applyPatches(
223
233
  for (let j = i + 1; j < lines.length; j++) {
224
234
  const nextLine = lines[j].trim();
225
235
  if (nextLine.startsWith("#")) {
226
- trailingComments += lines[j] + "\n";
236
+ trailingComments += `${lines[j]}\n`;
227
237
  } else if (nextLine !== "") {
228
238
  break;
229
239
  }
@@ -243,7 +253,7 @@ export function applyPatches(
243
253
  } else {
244
254
  // For scalars, format as key: value
245
255
  replacementLine = `${key}: ${serializedNewValue}${
246
- inlineComment ? " " + inlineComment : ""
256
+ inlineComment ? ` ${inlineComment}` : ""
247
257
  }`;
248
258
  }
249
259
 
@@ -267,14 +277,14 @@ export function applyPatches(
267
277
  ];
268
278
 
269
279
  // Join lines and ensure proper newlines
270
- currentYaml = newContent.join("\n").replace(/\n*$/, "\n") + "\n";
280
+ currentYaml = `${newContent.join("\n").replace(/\n*$/, "\n")}\n`;
271
281
  } else {
272
282
  // Key not found: Add the new key-value pair to the end
273
283
  const newLineBlock = replacementLine;
274
284
  if (currentYaml.trim() === "") {
275
- currentYaml = newLineBlock + "\n";
285
+ currentYaml = `${newLineBlock}\n`;
276
286
  } else {
277
- currentYaml = currentYaml.replace(/\n*$/, "\n") + newLineBlock + "\n";
287
+ currentYaml = `${currentYaml.replace(/\n*$/, "\n") + newLineBlock}\n`;
278
288
  }
279
289
  }
280
290
  }
@@ -15,7 +15,7 @@ export async function readAsset(
15
15
  name: string,
16
16
  encoding: "utf8" | "dataurl" = "utf8",
17
17
  ): Promise<string> {
18
- const dataUrl = await syscall("asset.readAsset", plugName, name) as string;
18
+ const dataUrl = (await syscall("asset.readAsset", plugName, name)) as string;
19
19
  switch (encoding) {
20
20
  case "utf8":
21
21
  return new TextDecoder().decode(base64DecodeDataUrl(dataUrl));
@@ -31,10 +31,7 @@ export function set<T>(
31
31
  /**
32
32
  * Inserts a config value into an array
33
33
  */
34
- export function insert<T>(
35
- path: string | string[],
36
- value: T,
37
- ): Promise<void> {
34
+ export function insert<T>(path: string | string[], value: T): Promise<void> {
38
35
  return syscall("config.insert", path, value);
39
36
  }
40
37
 
@@ -1,5 +1,9 @@
1
1
  import { syscall } from "../syscall.ts";
2
- import type { FilterOption, UploadFile } from "../../plug-api/types/client.ts";
2
+ import type {
3
+ FilterOption,
4
+ NotificationType,
5
+ UploadFile,
6
+ } from "../../plug-api/types/client.ts";
3
7
  import type { Path, Ref } from "../lib/ref.ts";
4
8
  import type { PageMeta } from "../../plug-api/types/index.ts";
5
9
 
@@ -77,9 +81,11 @@ export function getCursor(): Promise<number> {
77
81
  /**
78
82
  * Returns the line number and column number of the cursor in the editor
79
83
  */
80
- export function getSelection(): Promise<
81
- { from: number; to: number; text: string }
82
- > {
84
+ export function getSelection(): Promise<{
85
+ from: number;
86
+ to: number;
87
+ text: string;
88
+ }> {
83
89
  return syscall("editor.getSelection");
84
90
  }
85
91
 
@@ -218,7 +224,7 @@ export function uploadFile(
218
224
  */
219
225
  export function flashNotification(
220
226
  message: string,
221
- type: "info" | "error" = "info",
227
+ type: NotificationType = "info",
222
228
  ): Promise<void> {
223
229
  return syscall("editor.flashNotification", message, type);
224
230
  }
@@ -249,7 +255,7 @@ export function filterBox(
249
255
  export function showPanel(
250
256
  id: "lhs" | "rhs" | "bhs" | "modal",
251
257
  mode: number,
252
- html: string,
258
+ html: HTMLElement | HTMLElement[] | string,
253
259
  script = "",
254
260
  ): Promise<void> {
255
261
  return syscall("editor.showPanel", id, mode, html, script);
@@ -259,9 +265,7 @@ export function showPanel(
259
265
  * Hides a panel in the editor
260
266
  * @param id the location of the panel to hide
261
267
  */
262
- export function hidePanel(
263
- id: "lhs" | "rhs" | "bhs" | "modal",
264
- ): Promise<void> {
268
+ export function hidePanel(id: "lhs" | "rhs" | "bhs" | "modal"): Promise<void> {
265
269
  return syscall("editor.hidePanel", id);
266
270
  }
267
271
 
@@ -360,9 +364,7 @@ export function prompt(
360
364
  * @param message the message to show in the confirmation dialog
361
365
  * @returns
362
366
  */
363
- export function confirm(
364
- message: string,
365
- ): Promise<boolean> {
367
+ export function confirm(message: string): Promise<boolean> {
366
368
  return syscall("editor.confirm", message);
367
369
  }
368
370
 
@@ -371,9 +373,7 @@ export function confirm(
371
373
  * @param message the message to show in the confirmation dialog
372
374
  * @returns
373
375
  */
374
- export function alert(
375
- message: string,
376
- ): Promise<boolean> {
376
+ export function alert(message: string): Promise<boolean> {
377
377
  return syscall("editor.alert", message);
378
378
  }
379
379
 
@@ -18,8 +18,6 @@ export function validateObject(
18
18
  * @param schema the JSON schema to validate
19
19
  * @returns an error message if the schema is invalid, or undefined if it is valid
20
20
  */
21
- export function validateSchema(
22
- schema: any,
23
- ): Promise<string | undefined> {
21
+ export function validateSchema(schema: any): Promise<string | undefined> {
24
22
  return syscall("jsonschema.validateSchema", schema);
25
23
  }
@@ -1,20 +1,14 @@
1
1
  import { syscall } from "../syscall.ts";
2
2
  import type { LuaBlock, LuaExpression } from "../../client/space_lua/ast.ts";
3
3
 
4
- export function parse(
5
- code: string,
6
- ): Promise<LuaBlock> {
4
+ export function parse(code: string): Promise<LuaBlock> {
7
5
  return syscall("lua.parse", code);
8
6
  }
9
7
 
10
- export function parseExpression(
11
- expression: string,
12
- ): Promise<LuaExpression> {
8
+ export function parseExpression(expression: string): Promise<LuaExpression> {
13
9
  return syscall("lua.parseExpression", expression);
14
10
  }
15
11
 
16
- export function evalExpression(
17
- expression: string,
18
- ): Promise<any> {
12
+ export function evalExpression(expression: string): Promise<any> {
19
13
  return syscall("lua.evalExpression", expression);
20
14
  }
@@ -21,10 +21,7 @@ export function send(queue: string, body: any): Promise<void> {
21
21
  * @param queue the name of the queue
22
22
  * @param bodies the bodies of the messages to send
23
23
  */
24
- export function batchSend(
25
- queue: string,
26
- bodies: any[],
27
- ): Promise<void> {
24
+ export function batchSend(queue: string, bodies: any[]): Promise<void> {
28
25
  return syscall("mq.batchSend", queue, bodies);
29
26
  }
30
27
 
@@ -4,11 +4,14 @@ import { syscall } from "../syscall.ts";
4
4
  * Runs a shell command.
5
5
  * @param cmd the command to run
6
6
  * @param args the arguments to pass to the command
7
+ * @param stdin optional string to pass as stdin to the command
7
8
  * @returns the stdout, stderr, and exit code of the command
8
9
  */
9
10
  export function run(
10
11
  cmd: string,
11
12
  args: string[],
13
+ stdin?: string,
12
14
  ): Promise<{ stdout: string; stderr: string; code: number }> {
13
- return syscall("shell.run", cmd, args);
15
+ return syscall("shell.run", cmd, args, stdin);
14
16
  }
17
+
@@ -44,9 +44,7 @@ export function pageExists(name: string): Promise<boolean> {
44
44
  * @param name the name of the page to read
45
45
  * @returns the text of the page
46
46
  */
47
- export function readPage(
48
- name: string,
49
- ): Promise<string> {
47
+ export function readPage(name: string): Promise<string> {
50
48
  return syscall("space.readPage", name);
51
49
  }
52
50
 
@@ -111,9 +109,7 @@ export function getDocumentMeta(name: string): Promise<DocumentMeta> {
111
109
  * @param name path of the document to read
112
110
  * @returns the document data as a UInt8Array
113
111
  */
114
- export function readDocument(
115
- name: string,
116
- ): Promise<Uint8Array> {
112
+ export function readDocument(name: string): Promise<Uint8Array> {
117
113
  return syscall("space.readDocument", name);
118
114
  }
119
115
 
@@ -192,10 +188,7 @@ export function getFileMeta(name: string): Promise<FileMeta> {
192
188
  * @param data the data of the file to write
193
189
  * @returns the metadata for the written file
194
190
  */
195
- export function writeFile(
196
- name: string,
197
- data: Uint8Array,
198
- ): Promise<FileMeta> {
191
+ export function writeFile(name: string, data: Uint8Array): Promise<FileMeta> {
199
192
  return syscall("space.writeFile", name, data);
200
193
  }
201
194
 
@@ -13,10 +13,7 @@ import type { SyscallMeta } from "@silverbulletmd/silverbullet/type/index";
13
13
  * @param args arguments to pass to the function
14
14
  * @returns
15
15
  */
16
- export function invokeFunction(
17
- name: string,
18
- ...args: any[]
19
- ): Promise<any> {
16
+ export function invokeFunction(name: string, ...args: any[]): Promise<any> {
20
17
  return syscall("system.invokeFunction", name, ...args);
21
18
  }
22
19
 
@@ -10,9 +10,7 @@ import { syscall } from "../syscall.ts";
10
10
  * @param text the YAML text to parse
11
11
  * @returns a JavaScript object representation of the YAML text
12
12
  */
13
- export function parse(
14
- text: string,
15
- ): Promise<any> {
13
+ export function parse(text: string): Promise<any> {
16
14
  return syscall("yaml.parse", text);
17
15
  }
18
16
 
@@ -21,8 +19,6 @@ export function parse(
21
19
  * @param obj the object to stringify
22
20
  * @returns a YAML string representation of the object
23
21
  */
24
- export function stringify(
25
- obj: any,
26
- ): Promise<string> {
22
+ export function stringify(obj: any): Promise<string> {
27
23
  return syscall("yaml.stringify", obj);
28
24
  }
@@ -71,7 +71,6 @@ export function createMockSystem() {
71
71
  systemSyscalls(clientMock, false),
72
72
  );
73
73
 
74
- // @ts-ignore: global
75
74
  globalThis.syscall = (name: string, ...args: any): Promise<any> => {
76
75
  return system.localSyscall(name, args);
77
76
  };
@@ -11,11 +11,26 @@ export type FilterOption = {
11
11
  prefix?: string;
12
12
  } & Record<string, any>;
13
13
 
14
+ export type NotificationType = "info" | "error" | "warning";
15
+
16
+ export const notificationDismissTimeouts: Record<NotificationType, number> = {
17
+ info: 4000,
18
+ error: 5000,
19
+ warning: 8000,
20
+ };
21
+
22
+ export type NotificationAction = {
23
+ name: string;
24
+ run: () => void;
25
+ };
26
+
14
27
  export type Notification = {
15
28
  id: number;
16
29
  message: string;
17
- type: "info" | "error";
30
+ type: NotificationType;
18
31
  date: Date;
32
+ actions?: NotificationAction[];
33
+ persistent?: boolean;
19
34
  };
20
35
 
21
36
  export type PanelMode = number;
@@ -21,7 +21,9 @@ export type EventSubscription = EventSubscriptionDef & {
21
21
  run: (...args: any[]) => Promise<any>;
22
22
  };
23
23
 
24
- export type ResolvedPlug = {
25
- code: string;
26
- name?: string; // This will only dictate the filename
27
- } | string;
24
+ export type ResolvedPlug =
25
+ | {
26
+ code: string;
27
+ name?: string; // This will only dictate the filename
28
+ }
29
+ | string;
@@ -81,15 +81,14 @@ export type DocumentEditorT = {
81
81
  *
82
82
  * related: plugos/ui_types.ts#FunctionDef
83
83
  */
84
- export type SilverBulletHooks =
85
- & CommandHookT
86
- & SlashCommandHookT
87
- & MQHookT
88
- & EventHookT
89
- & CodeWidgetT
90
- & PlugNamespaceHookT
91
- & DocumentEditorT
92
- & SyscallHookT;
84
+ export type SilverBulletHooks = CommandHookT &
85
+ SlashCommandHookT &
86
+ MQHookT &
87
+ EventHookT &
88
+ CodeWidgetT &
89
+ PlugNamespaceHookT &
90
+ DocumentEditorT &
91
+ SyscallHookT;
93
92
 
94
93
  /** A plug manifest configures hooks, declares syntax extensions, and describes plug metadata.
95
94
  *
@@ -9,6 +9,6 @@ export const builtinPlugNames = [
9
9
  "image-viewer",
10
10
  ];
11
11
 
12
- export const builtinPlugPaths = builtinPlugNames.map((name) =>
13
- `Library/Std/Plugs/${name}.plug.js`
12
+ export const builtinPlugPaths = builtinPlugNames.map(
13
+ (name) => `Library/Std/Plugs/${name}.plug.js`,
14
14
  );
@@ -1,6 +0,0 @@
1
- import { WorkerSandbox } from "./worker_sandbox.ts";
2
- import type { SandboxFactory } from "./sandbox.ts";
3
-
4
- export function createSandbox<HookT>(workerUrl: URL): SandboxFactory<HookT> {
5
- return (plug) => new WorkerSandbox(plug, workerUrl);
6
- }