@silverbulletmd/silverbullet 2.8.1 → 2.10.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 (65) hide show
  1. package/README.md +42 -25
  2. package/client/plugos/hooks/syscall.ts +24 -10
  3. package/client/plugos/syscalls/asset.ts +61 -23
  4. package/client/plugos/syscalls/clientStore.ts +32 -6
  5. package/client/plugos/syscalls/client_code_widget.ts +9 -4
  6. package/client/plugos/syscalls/code_widget.ts +26 -11
  7. package/client/plugos/syscalls/config.ts +146 -30
  8. package/client/plugos/syscalls/datastore.ts +146 -40
  9. package/client/plugos/syscalls/editor.ts +1432 -700
  10. package/client/plugos/syscalls/event.ts +46 -13
  11. package/client/plugos/syscalls/fetch.ts +123 -82
  12. package/client/plugos/syscalls/index.ts +243 -114
  13. package/client/plugos/syscalls/jsonschema.ts +107 -8
  14. package/client/plugos/syscalls/language.ts +38 -12
  15. package/client/plugos/syscalls/markdown.ts +166 -50
  16. package/client/plugos/syscalls/mq.ts +93 -20
  17. package/client/plugos/syscalls/schema_introspection.ts +33 -0
  18. package/client/plugos/syscalls/service_registry.ts +74 -20
  19. package/client/plugos/syscalls/shell.ts +51 -20
  20. package/client/plugos/syscalls/space.ts +169 -113
  21. package/client/plugos/syscalls/sync.ts +50 -19
  22. package/client/plugos/syscalls/system.ts +236 -139
  23. package/client/plugos/system.ts +21 -5
  24. package/client/space_lua/api_documentation.ts +107 -0
  25. package/client/space_lua/ast.ts +13 -0
  26. package/client/space_lua/eval.ts +12 -4
  27. package/client/space_lua/parse.ts +254 -119
  28. package/client/space_lua/pretty_print.ts +465 -0
  29. package/client/space_lua/query_collection.ts +3 -3
  30. package/client/space_lua/render_widget.ts +156 -0
  31. package/client/space_lua/runtime.ts +83 -22
  32. package/client/space_lua/stdlib/crypto.ts +8 -3
  33. package/client/space_lua/stdlib/encoding.ts +27 -9
  34. package/client/space_lua/stdlib/js.ts +137 -22
  35. package/client/space_lua/stdlib/load.ts +26 -17
  36. package/client/space_lua/stdlib/math.ts +323 -118
  37. package/client/space_lua/stdlib/net.ts +57 -9
  38. package/client/space_lua/stdlib/os.ts +111 -44
  39. package/client/space_lua/stdlib/space_lua.ts +397 -13
  40. package/client/space_lua/stdlib/string.ts +282 -104
  41. package/client/space_lua/stdlib/string_pack.ts +58 -19
  42. package/client/space_lua/stdlib/table.ts +195 -40
  43. package/client/space_lua/stdlib.ts +336 -94
  44. package/client/space_lua/syscalls.ts +270 -0
  45. package/dist/plug-compile.js +1 -1
  46. package/package.json +12 -4
  47. package/plug-api/lib/ref.ts +96 -0
  48. package/plug-api/lib/shortcut.ts +2 -1
  49. package/plug-api/syscalls/config.ts +5 -3
  50. package/plug-api/syscalls/editor.ts +23 -2
  51. package/plug-api/syscalls/index.ts +24 -1
  52. package/plug-api/syscalls/jsonschema.ts +9 -0
  53. package/plug-api/syscalls/lua.ts +28 -1
  54. package/plug-api/syscalls/shell.ts +0 -1
  55. package/plug-api/syscalls/system.ts +7 -0
  56. package/plug-api/system_mock.ts +2 -2
  57. package/plug-api/types/config.ts +1 -1
  58. package/plug-api/types/index.ts +52 -1
  59. package/plug-api/types/manifest.ts +22 -4
  60. package/plug-api/ui/cx.ts +4 -0
  61. package/plug-api/ui/index.ts +22 -0
  62. package/plug-api/ui/panel_styles.ts +33 -0
  63. package/plug-api/ui/slugify.ts +44 -0
  64. package/plugs/builtin_plugs.ts +1 -0
  65. package/client/plugos/syscalls/lua.ts +0 -58
@@ -28,22 +28,35 @@ function capturesToLua(caps: CaptureResult[]): any {
28
28
  }
29
29
 
30
30
  export const stringApi = new LuaTable({
31
- byte: new LuaBuiltinFunction((_sf, s: string, i?: number, j?: number) => {
32
- i = i ?? 1;
33
- j = j ?? i;
34
- if (j > s.length) j = s.length;
35
- if (i < 1) i = 1;
36
- const result = [];
37
- for (let k = i; k <= j; k++) {
38
- result.push(s.charCodeAt(k - 1));
39
- }
40
- return new LuaMultiRes(result);
41
- }),
42
- char: new LuaBuiltinFunction((_sf, ...args: number[]) => {
43
- return String.fromCharCode(...args);
44
- }),
45
- find: new LuaBuiltinFunction(
46
- (_sf, s: string, pattern: string, init = 1, plain = false) => {
31
+ byte: new LuaBuiltinFunction({
32
+ callback: (_sf, s: string, i?: number, j?: number) => {
33
+ i = i ?? 1;
34
+ j = j ?? i;
35
+ if (j > s.length) j = s.length;
36
+ if (i < 1) i = 1;
37
+ const result = [];
38
+ for (let k = i; k <= j; k++) {
39
+ result.push(s.charCodeAt(k - 1));
40
+ }
41
+ return new LuaMultiRes(result);
42
+ },
43
+ description:
44
+ "Returns the numeric character codes in the inclusive range from `i` to `j`.",
45
+ parameters: [
46
+ { name: "s", type: "string" },
47
+ { name: "i", type: "integer", optional: true },
48
+ { name: "j", type: "integer", optional: true },
49
+ ],
50
+ returns: [{ type: "integer", description: "One result per character." }],
51
+ }),
52
+ char: new LuaBuiltinFunction({
53
+ callback: (_sf, ...args: number[]) => String.fromCharCode(...args),
54
+ description: "Creates a string from numeric character codes.",
55
+ signatures: ["string.char(...): string"],
56
+ returns: [{ type: "string" }],
57
+ }),
58
+ find: new LuaBuiltinFunction({
59
+ callback: (_sf, s: string, pattern: string, init = 1, plain = false) => {
47
60
  const r = patternFind(s, pattern, init, plain);
48
61
  if (!r) return null;
49
62
  const result: any[] = [r.start, r.end];
@@ -52,15 +65,42 @@ export const stringApi = new LuaTable({
52
65
  }
53
66
  return new LuaMultiRes(result);
54
67
  },
55
- ),
56
- format: new LuaBuiltinFunction((_sf, format: string, ...args: any[]) => {
57
- for (let i = 0; i < args.length; i++) {
58
- args[i] = untagNumber(args[i]);
59
- }
60
- return luaFormat(format, ...args);
61
- }),
62
- gmatch: new LuaBuiltinFunction(
63
- (_sf, s: string, pattern: string, init = 1) => {
68
+ description:
69
+ "Finds the first Lua-pattern match and returns its bounds followed by captures.",
70
+ parameters: [
71
+ { name: "s", type: "string" },
72
+ { name: "pattern", type: "string" },
73
+ { name: "init", type: "integer", optional: true },
74
+ { name: "plain", type: "boolean", optional: true },
75
+ ],
76
+ returns: [
77
+ { type: "integer|nil", description: "Start index or `nil`." },
78
+ { type: "integer", description: "End index." },
79
+ ],
80
+ }),
81
+ format: new LuaBuiltinFunction({
82
+ callback: (_sf, format: string, ...args: any[]) => {
83
+ for (let i = 0; i < args.length; i++) {
84
+ args[i] = untagNumber(args[i]);
85
+ }
86
+ return luaFormat(format, ...args);
87
+ },
88
+ description: "Formats values according to a C-style format string.",
89
+ signatures: ["string.format(format, ...): string"],
90
+ parameters: [
91
+ { name: "format", type: "string" },
92
+ {
93
+ name: "...",
94
+ description: "Values consumed by conversion specifiers.",
95
+ },
96
+ ],
97
+ returns: [{ type: "string" }],
98
+ examples: [
99
+ { code: 'print(string.format("Name: %s, score: %.1f", "Ada", 9.5))' },
100
+ ],
101
+ }),
102
+ gmatch: new LuaBuiltinFunction({
103
+ callback: (_sf, s: string, pattern: string, init = 1) => {
64
104
  const iter = patternGmatch(s, pattern, init);
65
105
  return () => {
66
106
  const caps = iter();
@@ -68,9 +108,22 @@ export const stringApi = new LuaTable({
68
108
  return capturesToLua(caps);
69
109
  };
70
110
  },
71
- ),
72
- gsub: new LuaBuiltinFunction(
73
- async (sf, s: string, pattern: string, repl: any, n?: number) => {
111
+ description:
112
+ "Returns an iterator over successive Lua-pattern matches and captures.",
113
+ parameters: [
114
+ { name: "s", type: "string" },
115
+ { name: "pattern", type: "string" },
116
+ { name: "init", type: "integer", optional: true },
117
+ ],
118
+ returns: [{ type: "function", description: "Match iterator." }],
119
+ examples: [
120
+ {
121
+ code: 'for word in string.gmatch("hello world", "%w+") do\n print(word)\nend',
122
+ },
123
+ ],
124
+ }),
125
+ gsub: new LuaBuiltinFunction({
126
+ callback: async (sf, s: string, pattern: string, repl: any, n?: number) => {
74
127
  const callbacks: GsubCallbacks = {};
75
128
  if (typeof repl === "string") {
76
129
  callbacks.replString = repl;
@@ -103,61 +156,135 @@ export const stringApi = new LuaTable({
103
156
  const [result, count] = await patternGsub(s, pattern, callbacks, n);
104
157
  return new LuaMultiRes([result, count]);
105
158
  },
106
- ),
107
- len: new LuaBuiltinFunction((_sf, s: string) => {
108
- return s.length;
109
- }),
110
- lower: new LuaBuiltinFunction((_sf, s: string) => {
111
- return luaToString(s.toLowerCase());
112
- }),
113
- upper: new LuaBuiltinFunction((_sf, s: string) => {
114
- return luaToString(s.toUpperCase());
115
- }),
116
- match: new LuaBuiltinFunction((_sf, s: string, pattern: string, init = 1) => {
117
- const caps = patternMatch(s, pattern, init);
118
- if (!caps) return null;
119
- return capturesToLua(caps);
120
- }),
121
- rep: new LuaBuiltinFunction((_sf, s: string, n: number, sep?: string) => {
122
- if (n <= 0) return "";
123
- sep = sep ?? "";
124
- const parts: string[] = [];
125
- for (let i = 0; i < n; i++) {
126
- parts.push(s);
127
- }
128
- return parts.join(sep);
129
- }),
130
- reverse: new LuaBuiltinFunction((_sf, s: string) => {
131
- return s.split("").reverse().join("");
132
- }),
133
- sub: new LuaBuiltinFunction((_sf, s: string, i: number, j?: number) => {
134
- const len = s.length;
135
- let start: number;
136
- if (i > 0) {
137
- start = i;
138
- } else if (i < -len) {
139
- start = 1;
140
- } else {
141
- start = i === 0 ? 1 : len + i + 1;
142
- }
143
- let end: number;
144
- if (j === undefined || j === null || j > len) {
145
- end = len;
146
- } else if (j >= 0) {
147
- end = j;
148
- } else if (j < -len) {
149
- end = 0;
150
- } else {
151
- end = len + j + 1;
152
- }
153
- if (start <= end) {
154
- return s.substring(start - 1, end);
155
- }
156
- return "";
159
+ description:
160
+ "Replaces Lua-pattern matches using a string, table, or function replacement.",
161
+ parameters: [
162
+ { name: "s", type: "string" },
163
+ { name: "pattern", type: "string" },
164
+ { name: "replacement", type: "string|table|function" },
165
+ { name: "n", type: "integer", optional: true },
166
+ ],
167
+ returns: [
168
+ { type: "string", description: "Result string." },
169
+ { type: "integer", description: "Number of replacements." },
170
+ ],
171
+ examples: [
172
+ {
173
+ code: 'local result, count = string.gsub("hello hello", "hello", "hi", 1)\nprint(result, count) -- hi hello 1',
174
+ },
175
+ ],
176
+ }),
177
+ len: new LuaBuiltinFunction({
178
+ callback: (_sf, s: string) => s.length,
179
+ description: "Returns the length of a string.",
180
+ parameters: [{ name: "s", type: "string" }],
181
+ returns: [{ type: "integer" }],
182
+ }),
183
+ lower: new LuaBuiltinFunction({
184
+ callback: (_sf, s: string) => luaToString(s.toLowerCase()),
185
+ description: "Returns a copy of a string converted to lowercase.",
186
+ parameters: [{ name: "s", type: "string" }],
187
+ returns: [{ type: "string" }],
188
+ }),
189
+ upper: new LuaBuiltinFunction({
190
+ callback: (_sf, s: string) => luaToString(s.toUpperCase()),
191
+ description: "Returns a copy of a string converted to uppercase.",
192
+ parameters: [{ name: "s", type: "string" }],
193
+ returns: [{ type: "string" }],
194
+ }),
195
+ match: new LuaBuiltinFunction({
196
+ callback: (_sf, s: string, pattern: string, init = 1) => {
197
+ const caps = patternMatch(s, pattern, init);
198
+ if (!caps) return null;
199
+ return capturesToLua(caps);
200
+ },
201
+ description:
202
+ "Returns captures from the first Lua-pattern match, or `nil` when none is found.",
203
+ parameters: [
204
+ { name: "s", type: "string" },
205
+ { name: "pattern", type: "string" },
206
+ { name: "init", type: "integer", optional: true },
207
+ ],
208
+ returns: [{ description: "Pattern captures, whole match, or `nil`." }],
209
+ examples: [
210
+ { code: 'local year, month = string.match("2024-03", "(%d+)%-(%d+)")' },
211
+ ],
212
+ }),
213
+ rep: new LuaBuiltinFunction({
214
+ callback: (_sf, s: string, n: number, sep?: string) => {
215
+ if (n <= 0) return "";
216
+ sep = sep ?? "";
217
+ const parts: string[] = [];
218
+ for (let i = 0; i < n; i++) {
219
+ parts.push(s);
220
+ }
221
+ return parts.join(sep);
222
+ },
223
+ description:
224
+ "Returns `n` copies of a string joined by an optional separator.",
225
+ parameters: [
226
+ { name: "s", type: "string" },
227
+ { name: "n", type: "integer" },
228
+ { name: "sep", type: "string", optional: true },
229
+ ],
230
+ returns: [{ type: "string" }],
231
+ }),
232
+ reverse: new LuaBuiltinFunction({
233
+ callback: (_sf, s: string) => s.split("").reverse().join(""),
234
+ description: "Returns a string with its characters in reverse order.",
235
+ parameters: [{ name: "s", type: "string" }],
236
+ returns: [{ type: "string" }],
237
+ }),
238
+ sub: new LuaBuiltinFunction({
239
+ callback: (_sf, s: string, i: number, j?: number) => {
240
+ const len = s.length;
241
+ let start: number;
242
+ if (i > 0) {
243
+ start = i;
244
+ } else if (i < -len) {
245
+ start = 1;
246
+ } else {
247
+ start = i === 0 ? 1 : len + i + 1;
248
+ }
249
+ let end: number;
250
+ if (j === undefined || j === null || j > len) {
251
+ end = len;
252
+ } else if (j >= 0) {
253
+ end = j;
254
+ } else if (j < -len) {
255
+ end = 0;
256
+ } else {
257
+ end = len + j + 1;
258
+ }
259
+ if (start <= end) {
260
+ return s.substring(start - 1, end);
261
+ }
262
+ return "";
263
+ },
264
+ description:
265
+ "Returns the substring from inclusive index `i` through `j`, supporting negative indices.",
266
+ parameters: [
267
+ { name: "s", type: "string" },
268
+ { name: "i", type: "integer" },
269
+ { name: "j", type: "integer", optional: true },
270
+ ],
271
+ returns: [{ type: "string" }],
157
272
  }),
158
273
 
159
- split: new LuaBuiltinFunction((_sf, s: string, sep: string) => {
160
- return s.split(sep);
274
+ split: new LuaBuiltinFunction({
275
+ callback: (_sf, s: string, sep: string) => s.split(sep),
276
+ description:
277
+ "Splits a string on a literal separator and returns the substrings.",
278
+ parameters: [
279
+ { name: "s", type: "string" },
280
+ { name: "sep", type: "string" },
281
+ ],
282
+ returns: [{ type: "table" }],
283
+ examples: [
284
+ {
285
+ code: 'for part in each(string.split("a,b,c", ",")) do\n print(part)\nend',
286
+ },
287
+ ],
161
288
  }),
162
289
 
163
290
  pack: strPackFn,
@@ -165,34 +292,85 @@ export const stringApi = new LuaTable({
165
292
  packsize: strPackSizeFn,
166
293
 
167
294
  // Non-standard extensions
168
- startsWith: new LuaBuiltinFunction((_sf, s: string, prefix: string) => {
169
- return s.startsWith(prefix);
295
+ startsWith: new LuaBuiltinFunction({
296
+ callback: (_sf, s: string, prefix: string) => s.startsWith(prefix),
297
+ description: "Returns whether a string starts with a literal prefix.",
298
+ parameters: [
299
+ { name: "s", type: "string" },
300
+ { name: "prefix", type: "string" },
301
+ ],
302
+ returns: [{ type: "boolean" }],
170
303
  }),
171
- endsWith: new LuaBuiltinFunction((_sf, s: string, suffix: string) => {
172
- return s.endsWith(suffix);
304
+ endsWith: new LuaBuiltinFunction({
305
+ callback: (_sf, s: string, suffix: string) => s.endsWith(suffix),
306
+ description: "Returns whether a string ends with a literal suffix.",
307
+ parameters: [
308
+ { name: "s", type: "string" },
309
+ { name: "suffix", type: "string" },
310
+ ],
311
+ returns: [{ type: "boolean" }],
173
312
  }),
174
- trim: new LuaBuiltinFunction((_sf, s: string) => {
175
- return s.trim();
313
+ trim: new LuaBuiltinFunction({
314
+ callback: (_sf, s: string) => s.trim(),
315
+ description: "Removes whitespace from both ends of a string.",
316
+ parameters: [{ name: "s", type: "string" }],
317
+ returns: [{ type: "string" }],
176
318
  }),
177
- trimStart: new LuaBuiltinFunction((_sf, s: string) => {
178
- return s.trimStart();
319
+ trimStart: new LuaBuiltinFunction({
320
+ callback: (_sf, s: string) => s.trimStart(),
321
+ description: "Removes whitespace from the beginning of a string.",
322
+ parameters: [{ name: "s", type: "string" }],
323
+ returns: [{ type: "string" }],
179
324
  }),
180
- trimEnd: new LuaBuiltinFunction((_sf, s: string) => {
181
- return s.trimEnd();
325
+ trimEnd: new LuaBuiltinFunction({
326
+ callback: (_sf, s: string) => s.trimEnd(),
327
+ description: "Removes whitespace from the end of a string.",
328
+ parameters: [{ name: "s", type: "string" }],
329
+ returns: [{ type: "string" }],
182
330
  }),
183
- matchRegex: new LuaBuiltinFunction((_sf, s: string, pattern: string) => {
184
- const regex = new RegExp(pattern);
185
- const result = s.match(regex);
186
- return jsToLuaValue(result);
331
+ matchRegex: new LuaBuiltinFunction({
332
+ callback: (_sf, s: string, pattern: string) => {
333
+ const regex = new RegExp(pattern);
334
+ const result = s.match(regex);
335
+ return jsToLuaValue(result);
336
+ },
337
+ description:
338
+ "Matches a string with a JavaScript regular expression and returns the match array.",
339
+ parameters: [
340
+ { name: "s", type: "string" },
341
+ { name: "pattern", type: "string" },
342
+ ],
343
+ returns: [{ type: "table|nil" }],
344
+ examples: [
345
+ {
346
+ code: 'local match = string.matchRegex("hello123", "([a-z]+)([0-9]+)")\nprint(match[1], match[2], match[3])',
347
+ },
348
+ ],
187
349
  }),
188
- matchRegexAll: new LuaBuiltinFunction((_sf, s: string, pattern: string) => {
189
- const regex = new RegExp(pattern, "g");
190
- return () => {
191
- const match = regex.exec(s);
192
- if (!match) {
193
- return;
194
- }
195
- return jsToLuaValue(match);
196
- };
350
+ matchRegexAll: new LuaBuiltinFunction({
351
+ callback: (_sf, s: string, pattern: string) => {
352
+ const regex = new RegExp(pattern, "g");
353
+ return () => {
354
+ const match = regex.exec(s);
355
+ if (!match) {
356
+ return;
357
+ }
358
+ return jsToLuaValue(match);
359
+ };
360
+ },
361
+ description:
362
+ "Returns an iterator over all JavaScript regular-expression matches.",
363
+ parameters: [
364
+ { name: "s", type: "string" },
365
+ { name: "pattern", type: "string" },
366
+ ],
367
+ returns: [
368
+ { type: "function", description: "Iterator yielding match arrays." },
369
+ ],
370
+ examples: [
371
+ {
372
+ code: 'for match in string.matchRegexAll("a1b2", "([a-z])([0-9])") do\n print(match[1], match[2], match[3])\nend',
373
+ },
374
+ ],
197
375
  }),
198
376
  });
@@ -252,8 +252,8 @@ function unpackFloat64(
252
252
  );
253
253
  }
254
254
 
255
- export const strPackFn = new LuaBuiltinFunction(
256
- (sf, fmt: string, ...args: any[]) => {
255
+ export const strPackFn = new LuaBuiltinFunction({
256
+ callback: (sf, fmt: string, ...args: any[]) => {
257
257
  const h = makeHeader();
258
258
  const parts: Uint8Array[] = [];
259
259
  let totalsize = 0;
@@ -364,10 +364,18 @@ export const strPackFn = new LuaBuiltinFunction(
364
364
  for (let i = 0; i < out.length; i++) result += String.fromCharCode(out[i]);
365
365
  return result;
366
366
  },
367
- );
367
+ description:
368
+ "Packs values into a binary string according to a Lua 5.4 format string.",
369
+ signatures: ["string.pack(format, ...): string"],
370
+ parameters: [
371
+ { name: "format", type: "string", description: "Binary packing format." },
372
+ { name: "...", description: "Values consumed by the format options." },
373
+ ],
374
+ returns: [{ type: "string", description: "Packed binary string." }],
375
+ });
368
376
 
369
- export const strUnpackFn = new LuaBuiltinFunction(
370
- (sf, fmt: string, data: string, init?: number) => {
377
+ export const strUnpackFn = new LuaBuiltinFunction({
378
+ callback: (sf, fmt: string, data: string, init?: number) => {
371
379
  const h = makeHeader();
372
380
 
373
381
  const buf = new Uint8Array(data.length);
@@ -468,23 +476,54 @@ export const strUnpackFn = new LuaBuiltinFunction(
468
476
  results.push(pos + 1);
469
477
  return new LuaMultiRes(results);
470
478
  },
471
- );
479
+ description:
480
+ "Unpacks values from a binary string according to a Lua 5.4 format string.",
481
+ parameters: [
482
+ {
483
+ name: "format",
484
+ type: "string",
485
+ description: "Binary unpacking format.",
486
+ },
487
+ { name: "data", type: "string", description: "Packed binary string." },
488
+ {
489
+ name: "init",
490
+ type: "integer",
491
+ description: "One-based starting position.",
492
+ optional: true,
493
+ },
494
+ ],
495
+ returns: [
496
+ { description: "Unpacked values followed by the next unread position." },
497
+ ],
498
+ });
472
499
 
473
- export const strPackSizeFn = new LuaBuiltinFunction((_sf, fmt: string) => {
474
- const h = makeHeader();
475
- let totalsize = 0;
476
- let pos = 0;
500
+ export const strPackSizeFn = new LuaBuiltinFunction({
501
+ callback: (_sf, fmt: string) => {
502
+ const h = makeHeader();
503
+ let totalsize = 0;
504
+ let pos = 0;
477
505
 
478
- while (pos < fmt.length) {
479
- let opt: ParsedOption;
480
- [opt, pos] = getDetails(fmt, pos, h, totalsize);
506
+ while (pos < fmt.length) {
507
+ let opt: ParsedOption;
508
+ [opt, pos] = getDetails(fmt, pos, h, totalsize);
481
509
 
482
- if (opt.opt === "string" || opt.opt === "zstr") {
483
- throw new LuaRuntimeError("variable-length format", _sf);
484
- }
510
+ if (opt.opt === "string" || opt.opt === "zstr") {
511
+ throw new LuaRuntimeError("variable-length format", _sf);
512
+ }
485
513
 
486
- totalsize += opt.ntoalign + opt.size;
487
- }
514
+ totalsize += opt.ntoalign + opt.size;
515
+ }
488
516
 
489
- return totalsize;
517
+ return totalsize;
518
+ },
519
+ description:
520
+ "Returns the byte size of a fixed-length Lua 5.4 packing format.",
521
+ parameters: [
522
+ {
523
+ name: "format",
524
+ type: "string",
525
+ description: "Fixed-length binary packing format.",
526
+ },
527
+ ],
528
+ returns: [{ type: "integer", description: "Packed byte count." }],
490
529
  });