@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
@@ -56,7 +56,6 @@ function parseSpec(
56
56
  }
57
57
  }
58
58
 
59
- // Parse width
60
59
  let width = 0;
61
60
  if (i < len && fmt.charCodeAt(i) === 42) {
62
61
  // '*'
@@ -69,7 +68,6 @@ function parseSpec(
69
68
  }
70
69
  }
71
70
 
72
- // Parse precision
73
71
  let hasPrec = false;
74
72
  let prec = 0;
75
73
  if (i < len && fmt.charCodeAt(i) === 46) {
@@ -183,7 +181,6 @@ function formatInt(n: number, spec: FormatSpec): string {
183
181
 
184
182
  if (upper) digits = digits.toUpperCase();
185
183
 
186
- // Precision
187
184
  if (spec.hasPrec) {
188
185
  if (spec.prec === 0 && v === 0) {
189
186
  digits = "";
@@ -192,7 +189,6 @@ function formatInt(n: number, spec: FormatSpec): string {
192
189
  }
193
190
  }
194
191
 
195
- // Alt flag
196
192
  let prefix = "";
197
193
  if (spec.flags & FLAG_HASH) {
198
194
  if (base === 8 && (digits.length === 0 || digits.charCodeAt(0) !== 48)) {
@@ -277,7 +273,6 @@ function formatFloat(n: number, spec: FormatSpec): string {
277
273
  // Alt flag for 'f'/'e': ensure decimal point exists
278
274
  if (spec.flags & FLAG_HASH && lower !== 103) {
279
275
  if (body.indexOf(".") === -1) {
280
- // Insert dot before 'e' if present, else append
281
276
  const eIdx = body.indexOf("e");
282
277
  const EIdx = body.indexOf("E");
283
278
  const expIdx = eIdx !== -1 ? eIdx : EIdx;
@@ -348,7 +343,6 @@ function stripTrailingZerosG(s: string): string {
348
343
  // '0'
349
344
  end--;
350
345
  }
351
- // Remove dot if nothing after it
352
346
  if (end === dotIdx + 1) {
353
347
  end = dotIdx;
354
348
  }
@@ -452,13 +446,11 @@ function hexFloatBody(abs: number, spec: FormatSpec): string {
452
446
  let mantBits: bigint;
453
447
 
454
448
  if (biasedExp === 0) {
455
- // Subnormal
456
449
  if (frac === 0n) return "0x0p+0";
457
450
  const shift = 52 - bitLength(frac) + 1;
458
451
  mantBits = frac << BigInt(shift);
459
452
  exponent = -1022 - shift;
460
453
  } else {
461
- // Normal
462
454
  exponent = biasedExp - 1023;
463
455
  mantBits = frac | (1n << 52n);
464
456
  }
@@ -680,8 +672,6 @@ export function luaFormat(fmt: string, ...args: any[]): string {
680
672
  while (i < len) {
681
673
  const c = fmt.charCodeAt(i);
682
674
  if (c !== 37) {
683
- // not '%'
684
- // Fast path: scan for next '%' or end
685
675
  let j = i + 1;
686
676
  while (j < len && fmt.charCodeAt(j) !== 37) j++;
687
677
  out += fmt.slice(i, j);
@@ -689,7 +679,6 @@ export function luaFormat(fmt: string, ...args: any[]): string {
689
679
  continue;
690
680
  }
691
681
 
692
- // '%' found
693
682
  i++;
694
683
  if (i >= len) {
695
684
  throw new Error("invalid format (ends with '%')");
@@ -705,7 +694,6 @@ export function luaFormat(fmt: string, ...args: any[]): string {
705
694
  const { spec, end } = parseSpec(fmt, i);
706
695
  i = end + 1;
707
696
 
708
- // Resolve `*` width and precision from args
709
697
  let width = spec.width;
710
698
  if (width === -1) {
711
699
  width = Number(args[ai++]) || 0;
@@ -4,6 +4,7 @@ import {
4
4
  LuaTable,
5
5
  luaValueToJS,
6
6
  } from "../runtime.ts";
7
+ import { fsEndpoint } from "../../spaces/constants.ts";
7
8
 
8
9
  export const jsApi = new LuaTable({
9
10
  /**
@@ -12,58 +13,170 @@ export const jsApi = new LuaTable({
12
13
  * @param args - The arguments to pass to the constructor.
13
14
  * @returns The new instance.
14
15
  */
15
- new: new LuaBuiltinFunction((sf, constructorFn: any, ...args) => {
16
- return new constructorFn(...args.map((v) => luaValueToJS(v, sf)));
16
+ new: new LuaBuiltinFunction({
17
+ callback: (sf, constructorFn: any, ...args) => {
18
+ return new constructorFn(...args.map((v) => luaValueToJS(v, sf)));
19
+ },
20
+ description: "Creates an instance of a JavaScript class.",
21
+ signatures: ["js.new(constructor, ...): userdata"],
22
+ parameters: [
23
+ {
24
+ name: "constructor",
25
+ type: "userdata",
26
+ description: "JavaScript constructor function.",
27
+ },
28
+ {
29
+ name: "...",
30
+ description: "Constructor arguments converted to JavaScript values.",
31
+ },
32
+ ],
33
+ returns: [{ type: "userdata", description: "New JavaScript instance." }],
34
+ examples: [{ code: 'local value = js.new(js.window.Date, "2024-03-14")' }],
17
35
  }),
18
36
  /**
19
37
  * Imports a JavaScript module.
20
38
  * @param url - The URL of the module to import.
21
39
  * @returns The imported module.
22
40
  */
23
- import: new LuaBuiltinFunction(async (_sf, url) => {
24
- let m = await import(url);
25
- // Unwrap default if it exists
26
- if (Object.keys(m).length === 1 && m.default) {
27
- m = m.default;
28
- }
29
- return m;
41
+ import: new LuaBuiltinFunction({
42
+ callback: async (_sf, url) => {
43
+ let m = await import(url);
44
+ if (Object.keys(m).length === 1 && m.default) {
45
+ m = m.default;
46
+ }
47
+ return m;
48
+ },
49
+ description: "Dynamically imports a JavaScript module from a URL.",
50
+ parameters: [{ name: "url", type: "string", description: "Module URL." }],
51
+ returns: [
52
+ {
53
+ type: "userdata",
54
+ description: "Imported module, with a sole default export unwrapped.",
55
+ },
56
+ ],
57
+ examples: [
58
+ { code: 'local lib = js.import("https://esm.sh/lodash@4.17.21")' },
59
+ ],
30
60
  }),
31
- eachIterable: new LuaBuiltinFunction((_sf, val) => {
32
- const iterator = val[Symbol.asyncIterator]();
33
- return async () => {
34
- const result = await iterator.next();
35
- if (result.done) {
36
- return;
61
+ /**
62
+ * Like `js.import`, but takes a path to a file in the current space (e.g.
63
+ * "Library/foo/bar.js") and resolves it to its full same-origin `/.fs` URL
64
+ * before importing.
65
+ * @param path - Space-relative path to the JS module (leading "/" optional).
66
+ * @returns The imported module (with a sole `default` export unwrapped).
67
+ */
68
+ importFromSpace: new LuaBuiltinFunction({
69
+ callback: async (_sf, path: string) => {
70
+ const base = document.baseURI.replace(/\/*$/, "/");
71
+ const rel = String(path).replace(/^\/+/, "");
72
+ let m = await import(`${base}${fsEndpoint.slice(1)}/${rel}`);
73
+ // Unwrap default if it exists (same contract as `js.import`).
74
+ if (Object.keys(m).length === 1 && m.default) {
75
+ m = m.default;
37
76
  }
38
- return result.value;
39
- };
77
+ return m;
78
+ },
79
+ description:
80
+ "Imports a JavaScript module from a file in the current space.",
81
+ parameters: [
82
+ {
83
+ name: "path",
84
+ type: "string",
85
+ description:
86
+ "Space-relative module path, with an optional leading slash.",
87
+ },
88
+ ],
89
+ returns: [
90
+ {
91
+ type: "userdata",
92
+ description: "Imported module, with a sole default export unwrapped.",
93
+ },
94
+ ],
95
+ examples: [
96
+ { code: 'local acme = js.importFromSpace("Library/acme/acme.js")' },
97
+ ],
98
+ }),
99
+ eachIterable: new LuaBuiltinFunction({
100
+ callback: (_sf, val) => {
101
+ const iterator = val[Symbol.asyncIterator]();
102
+ return async () => {
103
+ const result = await iterator.next();
104
+ if (result.done) {
105
+ return;
106
+ }
107
+ return result.value;
108
+ };
109
+ },
110
+ description: "Creates a Lua iterator over a JavaScript async iterable.",
111
+ parameters: [
112
+ {
113
+ name: "iterable",
114
+ type: "userdata",
115
+ description: "JavaScript async iterable.",
116
+ },
117
+ ],
118
+ returns: [
119
+ {
120
+ type: "function",
121
+ description: "Iterator yielding successive JavaScript values.",
122
+ },
123
+ ],
124
+ examples: [
125
+ {
126
+ code: "for value in js.eachIterable(someJsAsyncIterable) do\n print(value)\nend",
127
+ },
128
+ ],
40
129
  }),
41
130
  /**
42
131
  * Converts a JavaScript value to a Lua value.
43
132
  * @param val - The JavaScript value to convert.
44
133
  * @returns The Lua value.
45
134
  */
46
- tolua: new LuaBuiltinFunction((_sf, val) => jsToLuaValue(val)),
135
+ tolua: new LuaBuiltinFunction({
136
+ callback: (_sf, val) => jsToLuaValue(val),
137
+ description: "Converts a JavaScript value to its Lua representation.",
138
+ parameters: [
139
+ { name: "value", description: "JavaScript value to convert." },
140
+ ],
141
+ returns: [{ description: "Converted Lua value." }],
142
+ examples: [{ code: "local luaTable = js.tolua(jsArray)" }],
143
+ }),
47
144
  /**
48
145
  * Converts a Lua value to a JavaScript value.
49
146
  * @param val - The Lua value to convert.
50
147
  * @returns The JavaScript value.
51
148
  */
52
- tojs: new LuaBuiltinFunction((sf, val) => luaValueToJS(val, sf)),
149
+ tojs: new LuaBuiltinFunction({
150
+ callback: (sf, val) => luaValueToJS(val, sf),
151
+ description: "Converts a Lua value to its JavaScript representation.",
152
+ parameters: [{ name: "value", description: "Lua value to convert." }],
153
+ returns: [{ description: "Converted JavaScript value." }],
154
+ examples: [{ code: "local jsArray = js.tojs({1, 2, 3})" }],
155
+ }),
53
156
  /**
54
157
  * Logs a message to the console.
55
158
  * @param args - The arguments to log.
56
159
  */
57
- log: new LuaBuiltinFunction((_sf, ...args) => {
58
- console.log(...args);
160
+ log: new LuaBuiltinFunction({
161
+ callback: (_sf, ...args) => {
162
+ console.log(...args);
163
+ },
164
+ description: "Logs values to the JavaScript console.",
165
+ parameters: [{ name: "...", description: "Values to log." }],
166
+ examples: [{ code: 'js.log("User data:", {name = "Ada"})' }],
59
167
  }),
60
168
  /**
61
169
  * Converts a Lua value to a JSON string.
62
170
  * @param val - The Lua value to convert.
63
171
  * @returns The JSON string.
64
172
  */
65
- stringify: new LuaBuiltinFunction((_sf, val) => JSON.stringify(val)),
173
+ stringify: new LuaBuiltinFunction({
174
+ callback: (_sf, val) => JSON.stringify(val),
175
+ description: "Serializes a value as JSON using JavaScript semantics.",
176
+ parameters: [{ name: "value", description: "Value to serialize." }],
177
+ returns: [{ type: "string", description: "JSON representation." }],
178
+ examples: [{ code: "print(js.stringify({1, 2, 3})) -- [1,2,3]" }],
179
+ }),
66
180
 
67
- // Expose the global window object
68
181
  window: globalThis,
69
182
  });
@@ -16,7 +16,6 @@ export function luaLoad(code: LuaValue, sf: LuaStackFrame): LuaValue {
16
16
  const block = parseBlock(s, sf.astCtx || {});
17
17
  const globalEnvMaybe = sf.threadLocal.get("_GLOBAL");
18
18
 
19
- // Be vocal when no _GLOBAL is set
20
19
  if (!globalEnvMaybe) {
21
20
  console.warn("load() called without _GLOBAL in thread-local environment");
22
21
  return new LuaMultiRes([null, "Global environment not set"]);
@@ -24,22 +23,31 @@ export function luaLoad(code: LuaValue, sf: LuaStackFrame): LuaValue {
24
23
 
25
24
  const globalEnv: LuaEnv = globalEnvMaybe as LuaEnv;
26
25
 
27
- const runner = new LuaBuiltinFunction(async (innerSf: LuaStackFrame) => {
28
- const res = await evalStatement(block, globalEnv, innerSf, true);
29
- if (res === undefined) {
30
- return null;
31
- } else {
32
- if (res && typeof res === "object" && (res as any).ctrl === "return") {
33
- return new LuaMultiRes((res as any).values);
26
+ const runner = new LuaBuiltinFunction({
27
+ callback: async (innerSf: LuaStackFrame) => {
28
+ const res = await evalStatement(block, globalEnv, innerSf, true);
29
+ if (res === undefined) {
30
+ return null;
31
+ } else {
32
+ if (
33
+ res &&
34
+ typeof res === "object" &&
35
+ (res as any).ctrl === "return"
36
+ ) {
37
+ return new LuaMultiRes((res as any).values);
38
+ }
39
+ if (res && typeof res === "object" && (res as any).ctrl === "break") {
40
+ throw new Error("break outside loop");
41
+ }
42
+ if (res && typeof res === "object" && (res as any).ctrl === "goto") {
43
+ throw new Error("unexpected goto signal");
44
+ }
45
+ return null;
34
46
  }
35
- if (res && typeof res === "object" && (res as any).ctrl === "break") {
36
- throw new Error("break outside loop");
37
- }
38
- if (res && typeof res === "object" && (res as any).ctrl === "goto") {
39
- throw new Error("unexpected goto signal");
40
- }
41
- return null;
42
- }
47
+ },
48
+ description: "Executes the Lua chunk compiled by `load`.",
49
+ signatures: ["function(...)"],
50
+ returns: [{ description: "Values returned by the compiled chunk." }],
43
51
  });
44
52
 
45
53
  return runner;