@silverbulletmd/silverbullet 2.4.1 → 2.5.3

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 (57) hide show
  1. package/README.md +20 -4
  2. package/client/markdown_parser/constants.ts +2 -2
  3. package/client/plugos/hooks/code_widget.ts +0 -3
  4. package/client/plugos/hooks/document_editor.ts +0 -3
  5. package/client/plugos/hooks/event.ts +1 -1
  6. package/client/plugos/hooks/mq.ts +1 -1
  7. package/client/plugos/hooks/plug_namespace.ts +0 -3
  8. package/client/plugos/hooks/slash_command.ts +2 -2
  9. package/client/plugos/plug.ts +0 -1
  10. package/client/plugos/plug_compile.ts +28 -29
  11. package/client/plugos/proxy_fetch.ts +1 -1
  12. package/client/plugos/sandboxes/web_worker_sandbox.ts +1 -1
  13. package/client/plugos/sandboxes/worker_sandbox.ts +2 -3
  14. package/client/plugos/syscalls/editor.ts +12 -12
  15. package/client/plugos/syscalls/fetch.ts +1 -1
  16. package/client/plugos/syscalls/jsonschema.ts +1 -1
  17. package/client/plugos/syscalls/mq.ts +1 -1
  18. package/client/plugos/syscalls/space.ts +1 -1
  19. package/client/plugos/system.ts +2 -2
  20. package/client/plugos/worker_runtime.ts +8 -29
  21. package/client/space_lua/aggregates.ts +209 -0
  22. package/client/space_lua/ast.ts +24 -2
  23. package/client/space_lua/eval.ts +58 -53
  24. package/client/space_lua/labels.ts +1 -1
  25. package/client/space_lua/parse.ts +117 -12
  26. package/client/space_lua/query_collection.ts +850 -70
  27. package/client/space_lua/query_env.ts +26 -0
  28. package/client/space_lua/runtime.ts +47 -17
  29. package/client/space_lua/stdlib/format.ts +19 -19
  30. package/client/space_lua/stdlib/math.ts +73 -48
  31. package/client/space_lua/stdlib/net.ts +2 -2
  32. package/client/space_lua/stdlib/os.ts +5 -0
  33. package/client/space_lua/stdlib/pattern.ts +702 -0
  34. package/client/space_lua/stdlib/prng.ts +145 -0
  35. package/client/space_lua/stdlib/space_lua.ts +3 -8
  36. package/client/space_lua/stdlib/string.ts +103 -181
  37. package/client/space_lua/stdlib/string_pack.ts +486 -0
  38. package/client/space_lua/stdlib/table.ts +73 -9
  39. package/client/space_lua/stdlib.ts +38 -14
  40. package/client/space_lua/tonumber.ts +3 -2
  41. package/client/space_lua/util.ts +43 -9
  42. package/dist/plug-compile.js +23 -69
  43. package/dist/worker_runtime_bundle.js +233 -0
  44. package/package.json +16 -11
  45. package/plug-api/constants.ts +0 -32
  46. package/plug-api/lib/async.ts +2 -2
  47. package/plug-api/lib/crypto.ts +11 -11
  48. package/plug-api/lib/json.ts +1 -1
  49. package/plug-api/lib/limited_map.ts +1 -1
  50. package/plug-api/lib/native_fetch.ts +2 -0
  51. package/plug-api/lib/ref.ts +5 -5
  52. package/plug-api/lib/transclusion.ts +5 -5
  53. package/plug-api/lib/tree.ts +50 -2
  54. package/plug-api/lib/yaml.ts +10 -10
  55. package/plug-api/syscalls/editor.ts +1 -1
  56. package/plug-api/system_mock.ts +0 -1
  57. package/client/plugos/sandboxes/deno_worker_sandbox.ts +0 -6
@@ -4,6 +4,7 @@ import {
4
4
  cleanTree,
5
5
  type ParseTree,
6
6
  } from "@silverbulletmd/silverbullet/lib/tree";
7
+ // @ts-expect-error - Local generated JavaScript file without type definitions
7
8
  import { parser } from "./parse-lua.js";
8
9
  import { styleTags, tags as t } from "@lezer/highlight";
9
10
  import { indentNodeProp, LRLanguage } from "@codemirror/language";
@@ -35,7 +36,7 @@ const luaStyleTags = styleTags({
35
36
  CompareOp: t.operator,
36
37
  "true false": t.bool,
37
38
  Comment: t.lineComment,
38
- "return break goto do end while repeat until function local if then else elseif in for nil or and not query from where limit select order by desc":
39
+ "return break goto do end while repeat until function local if then else elseif in for nil or and not query from where limit select order by desc asc nulls first last group having filter using":
39
40
  t.keyword,
40
41
  });
41
42
 
@@ -131,6 +132,7 @@ function expressionHasFunctionDef(e: LuaExpression): boolean {
131
132
  break;
132
133
  case "Where":
133
134
  case "Select":
135
+ case "Having":
134
136
  if (expressionHasFunctionDef(c.expression)) return true;
135
137
  break;
136
138
  case "Limit":
@@ -142,11 +144,26 @@ function expressionHasFunctionDef(e: LuaExpression): boolean {
142
144
  if (expressionHasFunctionDef(c.orderBy[j].expression)) {
143
145
  return true;
144
146
  }
147
+ if (
148
+ c.orderBy[j].using && typeof c.orderBy[j].using !== "string"
149
+ ) {
150
+ return true;
151
+ }
152
+ }
153
+ break;
154
+ case "GroupBy":
155
+ for (let j = 0; j < c.expressions.length; j++) {
156
+ if (expressionHasFunctionDef(c.expressions[j])) return true;
145
157
  }
146
158
  break;
147
159
  }
148
160
  }
149
161
  return false;
162
+ case "FilteredCall":
163
+ return (
164
+ expressionHasFunctionDef(e.call) ||
165
+ expressionHasFunctionDef(e.filter)
166
+ );
150
167
  default:
151
168
  return false;
152
169
  }
@@ -213,6 +230,7 @@ function exprReferencesNames(e: LuaExpression, names: Set<string>): boolean {
213
230
  break;
214
231
  case "Where":
215
232
  case "Select":
233
+ case "Having":
216
234
  if (exprReferencesNames(c.expression, names)) return true;
217
235
  break;
218
236
  case "Limit":
@@ -224,11 +242,27 @@ function exprReferencesNames(e: LuaExpression, names: Set<string>): boolean {
224
242
  if (exprReferencesNames(c.orderBy[j].expression, names)) {
225
243
  return true;
226
244
  }
245
+ if (
246
+ typeof c.orderBy[j].using === "string" &&
247
+ names.has(c.orderBy[j].using as string)
248
+ ) {
249
+ return true;
250
+ }
251
+ }
252
+ break;
253
+ case "GroupBy":
254
+ for (let j = 0; j < c.expressions.length; j++) {
255
+ if (exprReferencesNames(c.expressions[j], names)) return true;
227
256
  }
228
257
  break;
229
258
  }
230
259
  }
231
260
  return false;
261
+ case "FilteredCall":
262
+ return (
263
+ exprReferencesNames(e.call, names) ||
264
+ exprReferencesNames(e.filter, names)
265
+ );
232
266
  default:
233
267
  return false;
234
268
  }
@@ -512,6 +546,7 @@ function exprCapturesNames(e: LuaExpression, names: Set<string>): boolean {
512
546
  break;
513
547
  case "Where":
514
548
  case "Select":
549
+ case "Having":
515
550
  if (exprCapturesNames(c.expression, names)) return true;
516
551
  break;
517
552
  case "Limit":
@@ -523,11 +558,25 @@ function exprCapturesNames(e: LuaExpression, names: Set<string>): boolean {
523
558
  if (exprCapturesNames(c.orderBy[j].expression, names)) {
524
559
  return true;
525
560
  }
561
+ const u = c.orderBy[j].using;
562
+ if (u && typeof u !== "string") {
563
+ if (functionBodyCapturesNames(u, names)) return true;
564
+ }
565
+ }
566
+ break;
567
+ case "GroupBy":
568
+ for (let j = 0; j < c.expressions.length; j++) {
569
+ if (exprCapturesNames(c.expressions[j], names)) return true;
526
570
  }
527
571
  break;
528
572
  }
529
573
  }
530
574
  return false;
575
+ case "FilteredCall":
576
+ return (
577
+ exprCapturesNames(e.call, names) ||
578
+ exprCapturesNames(e.filter, names)
579
+ );
531
580
  default:
532
581
  return false;
533
582
  }
@@ -537,7 +586,7 @@ function parseBlock(t: ParseTree, ctx: ASTCtx): LuaBlock {
537
586
  if (t.type !== "Block") {
538
587
  throw new Error(`Expected Block, got ${t.type}`);
539
588
  }
540
- const stmtNodes = t.children!.filter((c) => c && c.type);
589
+ const stmtNodes = t.children!.filter((c) => c?.type);
541
590
  const statements = stmtNodes.map((s) => parseStatement(s, ctx));
542
591
  const block: LuaBlock = { type: "Block", statements, ctx: context(t, ctx) };
543
592
 
@@ -765,7 +814,7 @@ function parseStatement(t: ParseTree, ctx: ASTCtx): LuaStatement {
765
814
  from?: number;
766
815
  to?: number;
767
816
  }[] = [];
768
- let elseBlock: LuaBlock | undefined = undefined;
817
+ let elseBlock: LuaBlock | undefined ;
769
818
  for (let i = 0; i < t.children!.length; i += 4) {
770
819
  const child = t.children![i];
771
820
  if (!child || !child.children || !child.children[0]) {
@@ -900,7 +949,7 @@ function parseStatement(t: ParseTree, ctx: ASTCtx): LuaStatement {
900
949
  console.error(t);
901
950
  throw new Error(
902
951
  `Unknown statement type: ${
903
- t.children![0] && t.children![0].text
952
+ t.children![0]?.text
904
953
  ? t.children![0].text
905
954
  : String(t.type)
906
955
  }`,
@@ -995,7 +1044,7 @@ function parseFunctionName(t: ParseTree, ctx: ASTCtx): LuaFunctionName {
995
1044
  throw new Error(`Expected FunctionName, got ${t.type}`);
996
1045
  }
997
1046
  const propNames: string[] = [];
998
- let colonName: string | undefined = undefined;
1047
+ let colonName: string | undefined ;
999
1048
  for (let i = 0; i < t.children!.length; i += 2) {
1000
1049
  const prop = t.children![i];
1001
1050
  propNames.push(prop.children![0].text!);
@@ -1103,8 +1152,9 @@ function parseExpression(t: ParseTree, ctx: ASTCtx): LuaExpression {
1103
1152
  return {
1104
1153
  type: "Number",
1105
1154
  // Use the integer parser fox 0x literals
1155
+ // biome-ignore lint/correctness/useParseIntRadix: hex strings need auto-detect radix
1106
1156
  value: text.includes("x") ? parseInt(text) : parseFloat(text),
1107
- numericType: /[\.eEpP]/.test(text) ? "float" : "int",
1157
+ numericType: /[.eEpP]/.test(text) ? "float" : "int",
1108
1158
  ctx: context(t, ctx),
1109
1159
  };
1110
1160
  }
@@ -1190,6 +1240,16 @@ function parseExpression(t: ParseTree, ctx: ASTCtx): LuaExpression {
1190
1240
  clauses: t.children!.slice(2, -1).map((c) => parseQueryClause(c, ctx)),
1191
1241
  ctx: context(t, ctx),
1192
1242
  };
1243
+ case "FilteredCall": {
1244
+ const call = parseFunctionCall(t.children![0], ctx);
1245
+ const filterExpr = parseExpression(t.children![4], ctx);
1246
+ return {
1247
+ type: "FilteredCall",
1248
+ call,
1249
+ filter: filterExpr,
1250
+ ctx: context(t, ctx),
1251
+ };
1252
+ }
1193
1253
  default:
1194
1254
  console.error(t);
1195
1255
  throw new Error(`Unknown expression type: ${t.type}`);
@@ -1240,12 +1300,36 @@ function parseQueryClause(t: ParseTree, ctx: ASTCtx): LuaQueryClause {
1240
1300
  const orderBy: LuaOrderBy[] = [];
1241
1301
  for (const child of t.children!) {
1242
1302
  if (child.type === "OrderBy") {
1243
- orderBy.push({
1303
+ const kids = child.children!;
1304
+ let direction: "asc" | "desc" = "asc";
1305
+ let nulls: "first" | "last" | undefined;
1306
+ let usingVal: string | LuaFunctionBody | undefined;
1307
+ for (let i = 1; i < kids.length; i++) {
1308
+ const typ = kids[i].type;
1309
+ if (typ === "desc") direction = "desc";
1310
+ else if (typ === "asc") direction = "asc";
1311
+ else if (typ === "first") nulls = "first";
1312
+ else if (typ === "last") nulls = "last";
1313
+ else if (typ === "using") {
1314
+ const next = kids[i + 1];
1315
+ if (next.type === "function") {
1316
+ usingVal = parseFunctionBody(kids[i + 2], ctx);
1317
+ i += 2;
1318
+ } else {
1319
+ usingVal = next.children![0].text!;
1320
+ i++;
1321
+ }
1322
+ }
1323
+ }
1324
+ const ob: LuaOrderBy = {
1244
1325
  type: "Order",
1245
- expression: parseExpression(child.children![0], ctx),
1246
- direction: child.children![1]?.type === "desc" ? "desc" : "asc",
1326
+ expression: parseExpression(kids[0], ctx),
1327
+ direction,
1247
1328
  ctx: context(child, ctx),
1248
- });
1329
+ };
1330
+ if (nulls) ob.nulls = nulls;
1331
+ if (usingVal !== undefined) ob.using = usingVal;
1332
+ orderBy.push(ob);
1249
1333
  }
1250
1334
  }
1251
1335
  return {
@@ -1261,6 +1345,27 @@ function parseQueryClause(t: ParseTree, ctx: ASTCtx): LuaQueryClause {
1261
1345
  ctx: context(t, ctx),
1262
1346
  };
1263
1347
  }
1348
+ case "GroupByClause": {
1349
+ // children: ckw<"group">, ckw<"by">, exp, ",", exp, ...
1350
+ const expressions: LuaExpression[] = t.children!
1351
+ .filter((c) =>
1352
+ c.type !== undefined && c.type !== "group" && c.type !== "by" &&
1353
+ c.type !== ","
1354
+ )
1355
+ .map((c) => parseExpression(c, ctx));
1356
+ return {
1357
+ type: "GroupBy",
1358
+ expressions,
1359
+ ctx: context(t, ctx),
1360
+ };
1361
+ }
1362
+ case "HavingClause": {
1363
+ return {
1364
+ type: "Having",
1365
+ expression: parseExpression(t.children![1], ctx),
1366
+ ctx: context(t, ctx),
1367
+ };
1368
+ }
1264
1369
  default:
1265
1370
  console.error(t);
1266
1371
  throw new Error(`Unknown query clause type: ${t.type}`);
@@ -1371,7 +1476,7 @@ export function stripLuaComments(s: string): string {
1371
1476
  if (s[j] === "[") {
1372
1477
  // Found long string start
1373
1478
  const openBracket = s.substring(i, j + 1);
1374
- const closeBracket = "]" + "=".repeat(equalsCount) + "]";
1479
+ const closeBracket = `]${"=".repeat(equalsCount)}]`;
1375
1480
  result += openBracket;
1376
1481
  i = j + 1;
1377
1482
 
@@ -1424,7 +1529,7 @@ export function stripLuaComments(s: string): string {
1424
1529
  }
1425
1530
  if (s[j] === "[") {
1426
1531
  // Found long comment start
1427
- const closeBracket = "]" + "=".repeat(equalsCount) + "]";
1532
+ const closeBracket = `]${"=".repeat(equalsCount)}]`;
1428
1533
  // Replace opening bracket with spaces
1429
1534
  result += " ".repeat(j - i + 1);
1430
1535
  i = j + 1;