@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
@@ -147,7 +147,6 @@ function buildSpecMap(d: Date, utc: boolean): Record<string, () => string> {
147
147
  const dow = () => wd(d, utc);
148
148
 
149
149
  return {
150
- // Date
151
150
  Y: () => yr(d, utc).toString(),
152
151
  y: () => pad2(yr(d, utc) % 100),
153
152
  C: () => pad2(Math.floor(yr(d, utc) / 100)),
@@ -156,14 +155,12 @@ function buildSpecMap(d: Date, utc: boolean): Record<string, () => string> {
156
155
  e: () => da(d, utc).toString().padStart(2, " "),
157
156
  j: () => pad3(dayOfYear(d, utc)),
158
157
 
159
- // Time
160
158
  H: () => pad2(h()),
161
159
  I: () => pad2(h12()),
162
160
  M: () => pad2(mi(d, utc)),
163
161
  S: () => pad2(sc(d, utc)),
164
162
  p: () => (h() >= 12 ? "PM" : "AM"),
165
163
 
166
- // Weekday
167
164
  A: () =>
168
165
  d.toLocaleString("en-US", {
169
166
  weekday: "long",
@@ -177,7 +174,6 @@ function buildSpecMap(d: Date, utc: boolean): Record<string, () => string> {
177
174
  w: () => dow().toString(),
178
175
  u: () => (dow() === 0 ? 7 : dow()).toString(),
179
176
 
180
- // Month name
181
177
  b: () =>
182
178
  d.toLocaleString("en-US", {
183
179
  month: "short",
@@ -194,14 +190,12 @@ function buildSpecMap(d: Date, utc: boolean): Record<string, () => string> {
194
190
  ...(utc ? { timeZone: "UTC" } : {}),
195
191
  }),
196
192
 
197
- // Week number
198
193
  U: () => pad2(weekNumber(d, utc, 0, false)),
199
194
  W: () => pad2(weekNumber(d, utc, 1, false)),
200
195
  V: () => pad2(weekNumber(d, utc, 1, true)),
201
196
  G: () => isoWeekYear(d, utc).toString(),
202
197
  g: () => pad2(isoWeekYear(d, utc) % 100),
203
198
 
204
- // Composite specifiers
205
199
  c: () =>
206
200
  d.toLocaleString("en-US", {
207
201
  ...(utc ? { timeZone: "UTC" } : {}),
@@ -225,14 +219,11 @@ function buildSpecMap(d: Date, utc: boolean): Record<string, () => string> {
225
219
  h() >= 12 ? "PM" : "AM"
226
220
  }`,
227
221
 
228
- // Epoch
229
222
  s: () => Math.floor(d.getTime() / 1000).toString(),
230
223
 
231
- // Whitespace
232
224
  n: () => "\n",
233
225
  t: () => "\t",
234
226
 
235
- // Timezone
236
227
  Z: () => {
237
228
  if (utc) return "UTC";
238
229
  const match = d.toTimeString().match(/\((.*)\)/);
@@ -246,7 +237,6 @@ function buildSpecMap(d: Date, utc: boolean): Record<string, () => string> {
246
237
  return `${sign}${pad2(Math.floor(abs / 60))}${pad2(abs % 60)}`;
247
238
  },
248
239
 
249
- // Literal
250
240
  "%": () => "%",
251
241
  };
252
242
  }
@@ -282,38 +272,71 @@ function luaFormatTime(fmt: string, d: Date, utc: boolean): string {
282
272
  }
283
273
 
284
274
  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");
275
+ time: new LuaBuiltinFunction({
276
+ callback: (_sf, tbl?: LuaTable) => {
277
+ if (tbl) {
278
+ if (!tbl.has("year")) {
279
+ throw new Error("time(): year is required");
280
+ }
281
+
282
+ if (!tbl.has("month")) {
283
+ throw new Error("time(): month is required");
284
+ }
285
+
286
+ if (!tbl.has("day")) {
287
+ throw new Error("time(): day is required");
288
+ }
289
+
290
+ const year = tbl.get("year");
291
+ const month = tbl.get("month");
292
+ const day = tbl.get("day");
293
+ const hour = tbl.get("hour") ?? 12;
294
+ const min = tbl.get("min") ?? 0;
295
+ const sec = tbl.get("sec") ?? 0;
296
+ const date = new Date(year, month - 1, day, hour, min, sec);
297
+
298
+ return Math.floor(date.getTime() / 1000);
289
299
  }
290
300
 
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);
301
+ return Math.floor(Date.now() / 1000);
302
+ },
303
+ description:
304
+ "Returns the current Unix timestamp or one built from a local date table.",
305
+ signatures: ["os.time(): integer", "os.time(dateTable): integer"],
306
+ parameters: [
307
+ {
308
+ name: "dateTable",
309
+ type: "table",
310
+ description:
311
+ "Local date fields `year`, `month`, `day`, and optional `hour`, `min`, and `sec`.",
312
+ optional: true,
313
+ },
314
+ ],
315
+ returns: [
316
+ { type: "integer", description: "Seconds since the Unix epoch." },
317
+ ],
318
+ examples: [
319
+ {
320
+ code: "local timestamp = os.time({year = 2020, month = 1, day = 1})",
321
+ },
322
+ ],
311
323
  }),
312
324
 
313
325
  // Returns the difference, from time `t1` to time `t2` in seconds
314
326
  // 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;
327
+ difftime: new LuaBuiltinFunction({
328
+ callback: (_sf, t2: number, t1: number): number => {
329
+ return t2 - t1;
330
+ },
331
+ description:
332
+ "Returns the difference in seconds from timestamp `t1` to `t2`.",
333
+ parameters: [
334
+ { name: "t2", type: "number" },
335
+ { name: "t1", type: "number" },
336
+ ],
337
+ returns: [
338
+ { type: "number", description: "The value `t2 - t1` in seconds." },
339
+ ],
317
340
  }),
318
341
 
319
342
  // Returns a string or a table containing date and time, formatted
@@ -336,29 +359,63 @@ export const osApi = new LuaTable({
336
359
  // Otherwise, format specifiers follow ISO C `strftime`.
337
360
  //
338
361
  // 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
- }
362
+ date: new LuaBuiltinFunction({
363
+ callback: (_sf, format?: string, timestamp?: number) => {
364
+ let fmt = format ?? "%c";
365
+ let utc = false;
366
+
367
+ if (fmt.startsWith("!")) {
368
+ utc = true;
369
+ fmt = fmt.slice(1);
370
+ }
347
371
 
348
- const d =
349
- timestamp !== undefined && timestamp !== null
350
- ? new Date(timestamp * 1000)
351
- : new Date();
372
+ const d =
373
+ timestamp !== undefined && timestamp !== null
374
+ ? new Date(timestamp * 1000)
375
+ : new Date();
352
376
 
353
- if (fmt === "*t") {
354
- return dateTable(d, utc);
355
- }
377
+ if (fmt === "*t") {
378
+ return dateTable(d, utc);
379
+ }
356
380
 
357
- return luaFormatTime(fmt, d, utc);
381
+ return luaFormatTime(fmt, d, utc);
382
+ },
383
+ description:
384
+ "Formats a timestamp as a date string or date table, optionally in UTC.",
385
+ parameters: [
386
+ {
387
+ name: "format",
388
+ type: "string",
389
+ description:
390
+ "`strftime`-style format, `*t` for a table, and optional leading `!` for UTC.",
391
+ optional: true,
392
+ },
393
+ {
394
+ name: "timestamp",
395
+ type: "number",
396
+ description: "Unix timestamp; defaults to the current time.",
397
+ optional: true,
398
+ },
399
+ ],
400
+ returns: [
401
+ { type: "string|table", description: "Formatted date or date fields." },
402
+ ],
403
+ examples: [
404
+ { code: 'print(os.date("%Y-%m-%d"))\nlocal utc = os.date("!*t")' },
405
+ ],
358
406
  }),
359
407
 
360
408
  // Returns an approximation of CPU time used by the program in seconds.
361
- clock: new LuaBuiltinFunction((_sf): number => {
362
- return performance.now() / 1000.0;
409
+ clock: new LuaBuiltinFunction({
410
+ callback: (_sf): number => {
411
+ return performance.now() / 1000.0;
412
+ },
413
+ description: "Returns a high-resolution elapsed time value in seconds.",
414
+ returns: [
415
+ {
416
+ type: "number",
417
+ description: "Browser performance timer in seconds.",
418
+ },
419
+ ],
363
420
  }),
364
421
  });
@@ -1,5 +1,3 @@
1
- // Lua Optimized Pattern Matching Engine Implementation
2
-
3
1
  const CH_ESC = 37; // '%'
4
2
  const CH_OPEN = 40; // '('
5
3
  const CH_CLOSE = 41; // ')'
@@ -40,21 +38,21 @@ interface Capture {
40
38
  }
41
39
 
42
40
  export interface MatchState {
43
- src: string; // original source string (for substring extraction)
44
- s: Uint8Array; // source bytes
41
+ src: string;
42
+ s: Uint16Array;
45
43
  slen: number;
46
- p: Uint8Array; // pattern bytes
44
+ p: Uint16Array;
47
45
  plen: number;
48
46
  level: number;
49
47
  capture: Capture[]; // pre-allocated, length `MAX_CAPTURES`
50
48
  matchdepth: number;
51
49
  }
52
50
 
53
- function toBytes(s: string): Uint8Array {
51
+ function toCodeUnits(s: string): Uint16Array {
54
52
  const len = s.length;
55
- const arr = new Uint8Array(len);
53
+ const arr = new Uint16Array(len);
56
54
  for (let i = 0; i < len; i++) {
57
- arr[i] = s.charCodeAt(i) & 0xff;
55
+ arr[i] = s.charCodeAt(i);
58
56
  }
59
57
  return arr;
60
58
  }
@@ -108,7 +106,7 @@ function matchClass(c: number, cl: number): boolean {
108
106
  return cl >= 97 && cl <= 122 ? res : !res;
109
107
  }
110
108
 
111
- function classEnd(p: Uint8Array, plen: number, pi: number): number {
109
+ function classEnd(p: Uint16Array, plen: number, pi: number): number {
112
110
  const ch = p[pi];
113
111
  pi++;
114
112
  if (ch === CH_ESC) {
@@ -138,7 +136,7 @@ function classEnd(p: Uint8Array, plen: number, pi: number): number {
138
136
 
139
137
  function matchBracketClass(
140
138
  c: number,
141
- p: Uint8Array,
139
+ p: Uint16Array,
142
140
  pi: number,
143
141
  ec: number,
144
142
  ): boolean {
@@ -404,8 +402,8 @@ function match(ms: MatchState, si: number, pi: number): number {
404
402
  }
405
403
 
406
404
  function createMatchState(s: string, p: string): MatchState {
407
- const sb = toBytes(s);
408
- const pb = toBytes(p);
405
+ const sb = toCodeUnits(s);
406
+ const pb = toCodeUnits(p);
409
407
  const capture: Capture[] = new Array(MAX_CAPTURES);
410
408
  for (let i = 0; i < MAX_CAPTURES; i++) {
411
409
  capture[i] = { init: 0, len: 0 };
@@ -434,8 +432,6 @@ function noSpecials(p: string): boolean {
434
432
  return true;
435
433
  }
436
434
 
437
- // Public API
438
-
439
435
  export type CaptureResult = { s: string } | { position: number };
440
436
 
441
437
  interface RawCapture {
@@ -615,7 +611,6 @@ function expandReplacementString(
615
611
  throw new Error("invalid use of '%' in replacement string");
616
612
  }
617
613
  } else {
618
- // Collect consecutive literal characters
619
614
  let j = i + 1;
620
615
  while (j < repl.length && repl.charCodeAt(j) !== CH_ESC) j++;
621
616
  parts.push(repl.substring(i, j));