@silverbulletmd/silverbullet 2.5.3 → 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 (90) hide show
  1. package/README.md +4 -5
  2. package/client/asset_bundle/bundle.ts +3 -9
  3. package/client/data/datastore.ts +4 -5
  4. package/client/markdown_parser/constants.ts +3 -2
  5. package/client/plugos/hooks/code_widget.ts +3 -5
  6. package/client/plugos/hooks/command.ts +8 -8
  7. package/client/plugos/hooks/document_editor.ts +10 -12
  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 -5
  11. package/client/plugos/hooks/slash_command.ts +12 -27
  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 -5
  15. package/client/plugos/plug_compile.ts +67 -65
  16. package/client/plugos/protocol.ts +28 -28
  17. package/client/plugos/proxy_fetch.ts +7 -6
  18. package/client/plugos/sandboxes/worker_sandbox.ts +16 -15
  19. package/client/plugos/syscalls/asset.ts +1 -3
  20. package/client/plugos/syscalls/code_widget.ts +1 -3
  21. package/client/plugos/syscalls/config.ts +1 -5
  22. package/client/plugos/syscalls/datastore.ts +1 -1
  23. package/client/plugos/syscalls/editor.ts +63 -60
  24. package/client/plugos/syscalls/event.ts +9 -12
  25. package/client/plugos/syscalls/fetch.ts +30 -22
  26. package/client/plugos/syscalls/index.ts +10 -1
  27. package/client/plugos/syscalls/jsonschema.ts +72 -32
  28. package/client/plugos/syscalls/language.ts +9 -5
  29. package/client/plugos/syscalls/markdown.ts +29 -7
  30. package/client/plugos/syscalls/mq.ts +3 -11
  31. package/client/plugos/syscalls/service_registry.ts +1 -4
  32. package/client/plugos/syscalls/shell.ts +2 -5
  33. package/client/plugos/syscalls/sync.ts +69 -60
  34. package/client/plugos/syscalls/system.ts +2 -3
  35. package/client/plugos/system.ts +4 -10
  36. package/client/plugos/worker_runtime.ts +4 -3
  37. package/client/space_lua/aggregates.ts +632 -59
  38. package/client/space_lua/ast.ts +21 -9
  39. package/client/space_lua/ast_narrow.ts +4 -2
  40. package/client/space_lua/eval.ts +842 -536
  41. package/client/space_lua/labels.ts +6 -11
  42. package/client/space_lua/liq_null.ts +6 -0
  43. package/client/space_lua/numeric.ts +5 -8
  44. package/client/space_lua/parse.ts +290 -169
  45. package/client/space_lua/query_collection.ts +213 -149
  46. package/client/space_lua/render_lua_markdown.ts +369 -0
  47. package/client/space_lua/rp.ts +5 -4
  48. package/client/space_lua/runtime.ts +245 -142
  49. package/client/space_lua/stdlib/format.ts +34 -20
  50. package/client/space_lua/stdlib/js.ts +3 -7
  51. package/client/space_lua/stdlib/load.ts +1 -3
  52. package/client/space_lua/stdlib/math.ts +15 -14
  53. package/client/space_lua/stdlib/net.ts +25 -15
  54. package/client/space_lua/stdlib/os.ts +76 -85
  55. package/client/space_lua/stdlib/pattern.ts +28 -35
  56. package/client/space_lua/stdlib/prng.ts +15 -12
  57. package/client/space_lua/stdlib/space_lua.ts +16 -17
  58. package/client/space_lua/stdlib/string.ts +7 -17
  59. package/client/space_lua/stdlib/string_pack.ts +23 -19
  60. package/client/space_lua/stdlib/table.ts +5 -9
  61. package/client/space_lua/stdlib.ts +20 -30
  62. package/client/space_lua/tonumber.ts +79 -40
  63. package/client/space_lua/util.ts +14 -10
  64. package/dist/plug-compile.js +44 -41
  65. package/package.json +24 -22
  66. package/plug-api/lib/async.ts +19 -6
  67. package/plug-api/lib/crypto.ts +5 -6
  68. package/plug-api/lib/dates.ts +15 -7
  69. package/plug-api/lib/json.ts +10 -4
  70. package/plug-api/lib/ref.ts +18 -18
  71. package/plug-api/lib/resolve.ts +7 -11
  72. package/plug-api/lib/tags.ts +13 -4
  73. package/plug-api/lib/transclusion.ts +6 -17
  74. package/plug-api/lib/tree.ts +115 -43
  75. package/plug-api/lib/yaml.ts +25 -15
  76. package/plug-api/syscalls/asset.ts +1 -1
  77. package/plug-api/syscalls/config.ts +1 -4
  78. package/plug-api/syscalls/editor.ts +14 -14
  79. package/plug-api/syscalls/jsonschema.ts +1 -3
  80. package/plug-api/syscalls/lua.ts +3 -9
  81. package/plug-api/syscalls/mq.ts +1 -4
  82. package/plug-api/syscalls/shell.ts +4 -1
  83. package/plug-api/syscalls/space.ts +3 -10
  84. package/plug-api/syscalls/system.ts +1 -4
  85. package/plug-api/syscalls/yaml.ts +2 -6
  86. package/plug-api/types/client.ts +16 -1
  87. package/plug-api/types/event.ts +6 -4
  88. package/plug-api/types/manifest.ts +8 -9
  89. package/plugs/builtin_plugs.ts +2 -2
  90. package/dist/worker_runtime_bundle.js +0 -233
@@ -4,7 +4,7 @@ import {
4
4
  type ParseTree,
5
5
  renderToText,
6
6
  } from "@silverbulletmd/silverbullet/lib/tree";
7
- import { extendedMarkdownLanguage } from "../../markdown_parser/parser.ts";
7
+ import { buildExtendedMarkdownLanguage } from "../../markdown_parser/parser.ts";
8
8
  import {
9
9
  expandMarkdown,
10
10
  type MarkdownExpandOptions,
@@ -18,11 +18,12 @@ import {
18
18
  jsonToMDTable,
19
19
  refCellTransformer,
20
20
  } from "../../markdown_renderer/result_render.ts";
21
+ import * as TagConstants from "../../../plugs/index/constants.ts";
21
22
 
22
23
  export function markdownSyscalls(client: Client): SysCallMapping {
23
24
  return {
24
25
  "markdown.parseMarkdown": (_ctx, text: string): ParseTree => {
25
- return parse(extendedMarkdownLanguage, text);
26
+ return parse(markdownLanguageWithUserExtensions(client), text);
26
27
  },
27
28
  "markdown.renderParseTree": (_ctx, tree: ParseTree): string => {
28
29
  return renderToText(tree);
@@ -34,7 +35,10 @@ export function markdownSyscalls(client: Client): SysCallMapping {
34
35
  ): Promise<ParseTree | string> => {
35
36
  const outputString = typeof treeOrText === "string";
36
37
  if (typeof treeOrText === "string") {
37
- treeOrText = parse(extendedMarkdownLanguage, treeOrText);
38
+ treeOrText = parse(
39
+ markdownLanguageWithUserExtensions(client),
40
+ treeOrText,
41
+ );
38
42
  }
39
43
  const result = await expandMarkdownWithClient(
40
44
  client,
@@ -52,23 +56,38 @@ export function markdownSyscalls(client: Client): SysCallMapping {
52
56
  text: string,
53
57
  options: MarkdownRenderOptions = {},
54
58
  ) => {
55
- let mdTree = parse(extendedMarkdownLanguage, text);
59
+ let mdTree = parse(markdownLanguageWithUserExtensions(client), text);
56
60
  if (options.expand) {
57
61
  mdTree = await expandMarkdownWithClient(client, mdTree);
58
62
  }
63
+ if (!options.resolveTagHref) {
64
+ options.resolveTagHref = (tagName: string) => {
65
+ return client.config.get<string | null>(
66
+ ["tags", tagName, "tagPage"],
67
+ null,
68
+ ) ?? TagConstants.tagPrefix + tagName;
69
+ };
70
+ }
59
71
  return renderMarkdownToHtml(mdTree, options);
60
72
  },
61
73
  "markdown.objectsToTable": (
62
74
  _ctx,
63
75
  data: any[],
64
- options: { renderCell?: (val: any, key: string) => Promise<any> | any } =
65
- {},
76
+ options: {
77
+ renderCell?: (val: any, key: string) => Promise<any> | any;
78
+ } = {},
66
79
  ) => {
67
80
  return jsonToMDTable(data, options.renderCell || refCellTransformer);
68
81
  },
69
82
  };
70
83
  }
71
84
 
85
+ function markdownLanguageWithUserExtensions(client: Client) {
86
+ return buildExtendedMarkdownLanguage(
87
+ client.config.get("syntaxExtensions", {}),
88
+ );
89
+ }
90
+
72
91
  function expandMarkdownWithClient(
73
92
  client: Client,
74
93
  tree: ParseTree,
@@ -79,6 +98,9 @@ function expandMarkdownWithClient(
79
98
  client.currentName(),
80
99
  tree,
81
100
  client.clientSystem.spaceLuaEnv,
82
- options,
101
+ {
102
+ ...options,
103
+ syntaxExtensions: client.config.get("syntaxExtensions", {}),
104
+ },
83
105
  );
84
106
  }
@@ -6,23 +6,15 @@ export type EventSubscription = MQListenerSpec & {
6
6
  run: (...args: any[]) => Promise<any>;
7
7
  };
8
8
 
9
- export function mqSyscalls(
10
- mq: DataStoreMQ,
11
- ): SysCallMapping {
9
+ export function mqSyscalls(mq: DataStoreMQ): SysCallMapping {
12
10
  return {
13
11
  /**
14
12
  * Define a Lua event listener
15
13
  */
16
- "mq.subscribe": (
17
- _ctx,
18
- def: MQListenerSpec,
19
- ) => {
14
+ "mq.subscribe": (_ctx, def: MQListenerSpec) => {
20
15
  def.autoAck = def.autoAck !== false;
21
16
  // console.log("Registering Lua event listener: ", def.name);
22
- client.config.insert([
23
- "mqSubscriptions",
24
- def.queue,
25
- ], def);
17
+ client.config.insert(["mqSubscriptions", def.queue], def);
26
18
  },
27
19
  "mq.send": (_ctx, queue: string, body: any) => {
28
20
  return mq.send(queue, body);
@@ -12,10 +12,7 @@ export function serviceRegistrySyscalls(
12
12
  /**
13
13
  * Define a Lua event listener
14
14
  */
15
- "service.define": (
16
- _ctx,
17
- def: ServiceSpec,
18
- ) => {
15
+ "service.define": (_ctx, def: ServiceSpec) => {
19
16
  return serviceRegistry.define(def);
20
17
  },
21
18
  "service.discover": (
@@ -2,9 +2,7 @@ import type { SysCallMapping } from "../system.ts";
2
2
  import type { Client } from "../../client.ts";
3
3
  import { fsEndpoint } from "../../spaces/constants.ts";
4
4
 
5
- export function shellSyscalls(
6
- client: Client,
7
- ): SysCallMapping {
5
+ export function shellSyscalls(client: Client): SysCallMapping {
8
6
  return {
9
7
  "shell.run": async (
10
8
  _ctx,
@@ -34,6 +32,5 @@ export function shellSyscalls(
34
32
 
35
33
  function buildShellUrl(client: Client) {
36
34
  // Strip off the /.fs and replace with /.shell
37
- return client.httpSpacePrimitives.url.slice(0, -fsEndpoint.length) +
38
- "/.shell";
35
+ return `${client.httpSpacePrimitives.url.slice(0, -fsEndpoint.length)}/.shell`;
39
36
  }
@@ -1,77 +1,86 @@
1
1
  import type { SysCallMapping } from "../system.ts";
2
2
  import type { Client } from "../../client.ts";
3
3
 
4
- // TODO: Reimplement this
5
4
  export function syncSyscalls(client: Client): SysCallMapping {
6
- return {
7
- "sync.hasInitialSyncCompleted": (): boolean => {
8
- return client.fullSyncCompleted;
9
- },
10
- "sync.performFileSync": (_ctx, path: string): Promise<void> => {
11
- client.postServiceWorkerMessage({ type: "perform-file-sync", path });
12
- return waitForServiceWorkerActivation(path);
13
- },
14
- "sync.performSpaceSync": (): Promise<number> => {
15
- client.postServiceWorkerMessage({ type: "perform-space-sync" });
16
- return waitForServiceWorkerActivation();
17
- },
18
- };
19
- }
5
+ const syncTimeoutMs = 30000;
20
6
 
21
- function waitForServiceWorkerActivation(path?: string): Promise<any> {
22
- return new Promise<any>((resolve, reject) => {
23
- client.eventHook.addLocalListener(
24
- "service-worker:file-sync-complete",
25
- eventHandler,
26
- );
27
- client.eventHook.addLocalListener(
28
- "service-worker:space-sync-complete",
29
- eventHandler,
30
- );
31
- client.eventHook.addLocalListener(
32
- "service-worker:sync-error",
33
- errorHandler,
34
- );
35
- function eventHandler(data: any) {
36
- // If data.path is set, we are notified about a specific file sync -> all good, even for an individual file sync
37
- // If data.path is not set, we are notified about a full space sync
38
- // If we were waiting for a specific path, ignore other paths
39
- if (data.path && path && data.path !== path) {
40
- // Event for other file sync
41
- return;
7
+ function waitForServiceWorkerActivation(path?: string): Promise<any> {
8
+ return new Promise<any>((resolve, reject) => {
9
+ const timeout = setTimeout(() => {
10
+ cleanup();
11
+ reject(new Error(`Sync timeout after ${syncTimeoutMs / 1000}s`));
12
+ }, syncTimeoutMs);
13
+
14
+ function cleanup() {
15
+ clearTimeout(timeout);
16
+ client.eventHook.removeLocalListener(
17
+ "service-worker:file-sync-complete",
18
+ eventHandler,
19
+ );
20
+ client.eventHook.removeLocalListener(
21
+ "service-worker:space-sync-complete",
22
+ eventHandler,
23
+ );
24
+ client.eventHook.removeLocalListener(
25
+ "service-worker:sync-error",
26
+ errorHandler,
27
+ );
42
28
  }
43
- // If we were waiting for a specific path, ignore other paths
44
- resolve(data);
45
29
 
46
- // Unsubscribe from all these events
47
- client.eventHook.removeLocalListener(
48
- "service-worker:file-sync-complete",
49
- eventHandler,
50
- );
51
- client.eventHook.removeLocalListener(
52
- "service-worker:space-sync-complete",
53
- eventHandler,
54
- );
55
- client.eventHook.removeLocalListener(
56
- "service-worker:sync-error",
57
- errorHandler,
58
- );
59
- }
60
- function errorHandler(e: any) {
61
- reject(e);
62
- // Unsubscribe from all these events
63
- client.eventHook.removeLocalListener(
30
+ client.eventHook.addLocalListener(
64
31
  "service-worker:file-sync-complete",
65
32
  eventHandler,
66
33
  );
67
- client.eventHook.removeLocalListener(
34
+ client.eventHook.addLocalListener(
68
35
  "service-worker:space-sync-complete",
69
36
  eventHandler,
70
37
  );
71
- client.eventHook.removeLocalListener(
38
+ client.eventHook.addLocalListener(
72
39
  "service-worker:sync-error",
73
40
  errorHandler,
74
41
  );
75
- }
76
- });
42
+
43
+ function eventHandler(data: any) {
44
+ if (data.path && path && data.path !== path) {
45
+ return;
46
+ }
47
+ cleanup();
48
+ resolve(data);
49
+ }
50
+
51
+ function errorHandler(e: any) {
52
+ // Only reject if the error is for our specific path, or if no path was specified
53
+ if (e.path && path && e.path !== path) {
54
+ return;
55
+ }
56
+ cleanup();
57
+ reject(e);
58
+ }
59
+ });
60
+ }
61
+
62
+ return {
63
+ "sync.hasInitialSyncCompleted": (): boolean => {
64
+ return client.fullSyncCompleted;
65
+ },
66
+ "sync.performFileSync": async (_ctx, path: string): Promise<void> => {
67
+ await client.postServiceWorkerMessage({
68
+ type: "perform-file-sync",
69
+ path,
70
+ });
71
+ // postServiceWorkerMessage returns silently if no SW, so only wait if SW is active
72
+ const registration = await navigator.serviceWorker.getRegistration();
73
+ if (registration?.active) {
74
+ return waitForServiceWorkerActivation(path);
75
+ }
76
+ },
77
+ "sync.performSpaceSync": async (): Promise<number> => {
78
+ await client.postServiceWorkerMessage({ type: "perform-space-sync" });
79
+ const registration = await navigator.serviceWorker.getRegistration();
80
+ if (registration?.active) {
81
+ return waitForServiceWorkerActivation();
82
+ }
83
+ return 0;
84
+ },
85
+ };
77
86
  }
@@ -66,9 +66,8 @@ export function systemSyscalls(
66
66
  },
67
67
  "system.listSyscalls": (): SyscallMeta[] => {
68
68
  const syscalls: SyscallMeta[] = [];
69
- for (
70
- const [name, info] of client.clientSystem.system.registeredSyscalls
71
- ) {
69
+ for (const [name, info] of client.clientSystem.system
70
+ .registeredSyscalls) {
72
71
  syscalls.push({
73
72
  name,
74
73
  requiredPermissions: info.requiredPermissions,
@@ -24,9 +24,7 @@ export type SyscallContext = {
24
24
  plug?: string;
25
25
  };
26
26
 
27
- type SyscallSignature = (
28
- ...args: any[]
29
- ) => Promise<any> | any;
27
+ type SyscallSignature = (...args: any[]) => Promise<any> | any;
30
28
 
31
29
  type Syscall = {
32
30
  requiredPermissions: string[];
@@ -112,11 +110,7 @@ export class System<HookT> extends EventEmitter<SystemEvents<HookT>> {
112
110
  return this.syscall({}, name, args);
113
111
  }
114
112
 
115
- syscall(
116
- ctx: SyscallContext,
117
- name: string,
118
- args: any[],
119
- ): Promise<any> {
113
+ syscall(ctx: SyscallContext, name: string, args: any[]): Promise<any> {
120
114
  const syscall = this.registeredSyscalls.get(name);
121
115
  if (!syscall) {
122
116
  throw Error(`Unregistered syscall ${name}`);
@@ -188,8 +182,8 @@ export class System<HookT> extends EventEmitter<SystemEvents<HookT>> {
188
182
  if (!plug) {
189
183
  return;
190
184
  }
191
- plug.stop();
192
- this.emit("plugUnloaded", name);
185
+ void plug.stop();
186
+ void this.emit("plugUnloaded", name);
193
187
  this.plugs.delete(name);
194
188
  }
195
189
 
@@ -19,7 +19,8 @@ let workerPostMessage = (_msg: ControllerMessage): void => {
19
19
  // - in a browser's main thread, typeof window is "object"
20
20
  // - in a browser's worker threads, typeof window === "undefined"
21
21
  // - in Cloudflare workers typeof window === "undefined", but typeof globalThis.WebSocketPair is defined
22
- const runningAsWebWorker = typeof window === "undefined" &&
22
+ const runningAsWebWorker =
23
+ typeof window === "undefined" &&
23
24
  // @ts-expect-error: globalThis
24
25
  typeof globalThis.WebSocketPair === "undefined";
25
26
 
@@ -147,8 +148,8 @@ export function monkeyPatchFetch() {
147
148
  ): Promise<Response> => {
148
149
  const encodedBody = init?.body
149
150
  ? base64Encode(
150
- new Uint8Array(await (new Response(init.body)).arrayBuffer()),
151
- )
151
+ new Uint8Array(await new Response(init.body).arrayBuffer()),
152
+ )
152
153
  : undefined;
153
154
  const r = await sandboxFetch(
154
155
  reqInfo,