@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.
- package/README.md +38 -25
- package/client/asset_bundle/bundle.ts +0 -1
- package/client/config.ts +343 -0
- package/client/markdown_parser/constants.ts +3 -1
- package/client/plugos/hooks/command.ts +0 -5
- package/client/plugos/hooks/event.ts +0 -6
- package/client/plugos/hooks/mq.ts +0 -3
- package/client/plugos/hooks/slash_command.ts +1 -7
- package/client/plugos/hooks/syscall.ts +24 -14
- package/client/plugos/manifest_cache.ts +0 -32
- package/client/plugos/plug.ts +0 -3
- package/client/plugos/plug_compile.ts +3 -13
- package/client/plugos/sandboxes/worker_sandbox.ts +19 -9
- package/client/plugos/syscalls/asset.ts +61 -23
- package/client/plugos/syscalls/clientStore.ts +32 -6
- package/client/plugos/syscalls/client_code_widget.ts +9 -4
- package/client/plugos/syscalls/code_widget.ts +26 -11
- package/client/plugos/syscalls/config.ts +146 -30
- package/client/plugos/syscalls/datastore.ts +146 -40
- package/client/plugos/syscalls/editor.ts +1518 -722
- package/client/plugos/syscalls/event.ts +44 -13
- package/client/plugos/syscalls/fetch.ts +120 -83
- package/client/plugos/syscalls/icon.ts +46 -0
- package/client/plugos/syscalls/index.ts +267 -121
- package/client/plugos/syscalls/jsonschema.ts +107 -9
- package/client/plugos/syscalls/language.ts +38 -12
- package/client/plugos/syscalls/markdown.ts +166 -50
- package/client/plugos/syscalls/mq.ts +92 -20
- package/client/plugos/syscalls/navigator.ts +143 -0
- package/client/plugos/syscalls/schema_introspection.ts +33 -0
- package/client/plugos/syscalls/search.ts +44 -0
- package/client/plugos/syscalls/service_registry.ts +74 -20
- package/client/plugos/syscalls/shell.ts +51 -21
- package/client/plugos/syscalls/space.ts +412 -113
- package/client/plugos/syscalls/sync.ts +103 -20
- package/client/plugos/syscalls/system.ts +274 -139
- package/client/plugos/system.ts +28 -10
- package/client/plugos/worker_runtime.ts +0 -2
- package/client/space_lua/aggregates.ts +0 -16
- package/client/space_lua/api_documentation.ts +107 -0
- package/client/space_lua/ast.ts +13 -5
- package/client/space_lua/ast_narrow.ts +0 -5
- package/client/space_lua/budget.ts +113 -0
- package/client/space_lua/budget_ui.ts +49 -0
- package/client/space_lua/eval.ts +125 -92
- package/client/space_lua/labels.ts +0 -4
- package/client/space_lua/numeric.ts +0 -5
- package/client/space_lua/parse.ts +243 -125
- package/client/space_lua/pretty_print.ts +128 -54
- package/client/space_lua/quarantine.ts +127 -0
- package/client/space_lua/query_collection.ts +7 -51
- package/client/space_lua/query_env.ts +0 -2
- package/client/space_lua/render_lua_markdown.ts +2 -7
- package/client/space_lua/render_widget.ts +173 -0
- package/client/space_lua/runtime.ts +133 -92
- package/client/space_lua/stdlib/crypto.ts +8 -3
- package/client/space_lua/stdlib/encoding.ts +27 -9
- package/client/space_lua/stdlib/format.ts +0 -12
- package/client/space_lua/stdlib/js.ts +136 -23
- package/client/space_lua/stdlib/load.ts +24 -16
- package/client/space_lua/stdlib/math.ts +331 -133
- package/client/space_lua/stdlib/net.ts +57 -13
- package/client/space_lua/stdlib/os.ts +111 -54
- package/client/space_lua/stdlib/pattern.ts +10 -15
- package/client/space_lua/stdlib/space_lua.ts +344 -21
- package/client/space_lua/stdlib/string.ts +282 -104
- package/client/space_lua/stdlib/string_pack.ts +58 -22
- package/client/space_lua/stdlib/table.ts +195 -45
- package/client/space_lua/stdlib.ts +354 -125
- package/client/space_lua/syscalls.ts +270 -0
- package/client/space_lua/tonumber.ts +0 -9
- package/dist/plug-compile.js +2 -3
- package/package.json +15 -5
- package/plug-api/lib/async.ts +1 -6
- package/plug-api/lib/collation.ts +22 -0
- package/plug-api/lib/crypto.ts +16 -15
- package/plug-api/lib/dates.ts +33 -0
- package/plug-api/lib/fuzzy.ts +282 -0
- package/plug-api/lib/json.ts +0 -6
- package/plug-api/lib/limited_map.ts +0 -2
- package/plug-api/lib/link_write.ts +27 -0
- package/plug-api/{ui → lib}/panel_styles.ts +4 -3
- package/plug-api/lib/ref.ts +124 -5
- package/plug-api/lib/resolve.ts +0 -1
- package/plug-api/lib/resolve_path.ts +290 -0
- package/plug-api/lib/shortcut.ts +17 -1
- package/plug-api/lib/tags.ts +0 -3
- package/plug-api/lib/transclusion.ts +28 -1
- package/plug-api/lib/tree.ts +0 -5
- package/plug-api/lib/yaml.ts +3 -42
- package/plug-api/syscall.ts +1 -5
- package/plug-api/syscalls/config.ts +7 -5
- package/plug-api/syscalls/editor.ts +70 -208
- package/plug-api/syscalls/icon.ts +18 -0
- package/plug-api/syscalls/index.ts +39 -5
- package/plug-api/syscalls/jsonschema.ts +9 -0
- package/plug-api/syscalls/lua.ts +7 -0
- package/plug-api/syscalls/search.ts +11 -0
- package/plug-api/syscalls/shell.ts +0 -1
- package/plug-api/syscalls/space.ts +122 -5
- package/plug-api/syscalls/sync.ts +23 -2
- package/plug-api/syscalls/system.ts +53 -0
- package/plug-api/syscalls.ts +2 -0
- package/plug-api/system_mock.ts +15 -2
- package/plug-api/types/client.ts +4 -3
- package/plug-api/types/datastore.ts +11 -2
- package/plug-api/types/index.ts +62 -1
- package/plug-api/types/manifest.ts +22 -4
- package/plug-api/types/profile.ts +13 -0
- package/plug-api/types/revisions.ts +67 -0
- package/plug-api/ui/cx.ts +1 -3
- package/plug-api/ui/description.ts +64 -0
- package/plug-api/ui/hover.ts +69 -0
- package/plug-api/ui/index.ts +61 -2
- package/plug-api/ui/scroll.ts +30 -0
- package/plug-api/ui/slugify.ts +44 -0
- package/plug-api/ui/tree_model.ts +263 -0
- package/plug-api/ui/tree_types.ts +66 -0
- package/plug-api/ui/use_fit_collapse.ts +67 -0
- package/plugs/builtin_plugs.ts +0 -1
- package/plugs/index/types.ts +9 -0
- package/client/plugos/syscalls/lua.ts +0 -81
- package/plug-api/lib/memory_cache.ts +0 -21
|
@@ -99,8 +99,7 @@ export type Classified =
|
|
|
99
99
|
headers: string[];
|
|
100
100
|
rowCount: number;
|
|
101
101
|
getCell: (rowIndex: number, header: string) => any;
|
|
102
|
-
// LuaTable record-arrays
|
|
103
|
-
// JS record-arrays are tagged as "table". Preserved for compatibility.
|
|
102
|
+
// Compatibility contract: LuaTable record-arrays use "list"; JS arrays use "table".
|
|
104
103
|
dataType: "table" | "list";
|
|
105
104
|
}
|
|
106
105
|
| { kind: "scalarArray"; items: any[]; dataType: "list" };
|
|
@@ -138,7 +137,6 @@ export function classifyResult(result: any): Classified {
|
|
|
138
137
|
const arrayLen = result.length;
|
|
139
138
|
const hasStrKeys = keys.some((k) => typeof k === "string");
|
|
140
139
|
|
|
141
|
-
// Pure array
|
|
142
140
|
if (arrayLen > 0 && !hasStrKeys) {
|
|
143
141
|
const elements: any[] = [];
|
|
144
142
|
for (let i = 1; i <= arrayLen; i++) elements.push(result.rawGet(i));
|
|
@@ -162,7 +160,6 @@ export function classifyResult(result: any): Classified {
|
|
|
162
160
|
return { kind: "scalarArray", items: elements, dataType: "list" };
|
|
163
161
|
}
|
|
164
162
|
|
|
165
|
-
// Has string keys (record or mixed) — single-row table
|
|
166
163
|
const headers = keys.map(String);
|
|
167
164
|
return {
|
|
168
165
|
kind: "record",
|
|
@@ -267,9 +264,7 @@ export function renderResultToMarkdown(
|
|
|
267
264
|
/**
|
|
268
265
|
* Cell transformer for the clean-markdown (copy) path. Renders:
|
|
269
266
|
* - `ref` columns as wiki links,
|
|
270
|
-
* - scalar arrays as `<br/>`-joined lines
|
|
271
|
-
* path, and relies on the markdown renderer now handling self-closing
|
|
272
|
-
* `<br/>` inside GFM table cells),
|
|
267
|
+
* - scalar arrays as `<br/>`-joined lines inside GFM table cells,
|
|
273
268
|
* - everything else via `defaultTransformer` (which Lua-encodes nested
|
|
274
269
|
* tables and escapes pipes for scalars).
|
|
275
270
|
*/
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import type { ASTCtx } from "./ast.ts";
|
|
2
|
+
import { evalExpression } from "./eval.ts";
|
|
3
|
+
import { parseExpressionString } from "./parse.ts";
|
|
4
|
+
import {
|
|
5
|
+
type ILuaFunction,
|
|
6
|
+
LuaEnv,
|
|
7
|
+
LuaRuntimeError,
|
|
8
|
+
LuaStackFrame,
|
|
9
|
+
LuaTable,
|
|
10
|
+
type LuaValue,
|
|
11
|
+
luaValueToJS,
|
|
12
|
+
singleResult,
|
|
13
|
+
} from "./runtime.ts";
|
|
14
|
+
import {
|
|
15
|
+
BUSY_LIMIT_DEFAULT_MS,
|
|
16
|
+
LuaBudgetStopped,
|
|
17
|
+
makeLuaBudget,
|
|
18
|
+
} from "./budget.ts";
|
|
19
|
+
import { isTaggedFloat } from "./numeric.ts";
|
|
20
|
+
import {
|
|
21
|
+
encodeRef,
|
|
22
|
+
getNameFromPath,
|
|
23
|
+
} from "@silverbulletmd/silverbullet/lib/ref";
|
|
24
|
+
import { resolveASTReference } from "../space_lua.ts";
|
|
25
|
+
import type { Client } from "../client.ts";
|
|
26
|
+
import { isViewValue } from "../navigator/view_value.ts";
|
|
27
|
+
import {
|
|
28
|
+
classifyResult,
|
|
29
|
+
renderResultToCleanMarkdown,
|
|
30
|
+
} from "./render_lua_markdown.ts";
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Run a Space Lua computation and convert its result into something the
|
|
34
|
+
* LuaWidget renderer understands (a widget table, markdown string, or number).
|
|
35
|
+
* Shared by the `${...}` directive and Lua code widgets so the conversion +
|
|
36
|
+
* error formatting live in one place.
|
|
37
|
+
*/
|
|
38
|
+
export async function renderLuaWidgetResult(
|
|
39
|
+
client: Client,
|
|
40
|
+
compute: (env: LuaEnv, sf: LuaStackFrame) => Promise<LuaValue> | LuaValue,
|
|
41
|
+
ctx: ASTCtx,
|
|
42
|
+
currentPageMeta?: { name: string } | undefined,
|
|
43
|
+
): Promise<any> {
|
|
44
|
+
try {
|
|
45
|
+
const tl = new LuaEnv();
|
|
46
|
+
tl.setLocal(
|
|
47
|
+
"currentPage",
|
|
48
|
+
currentPageMeta ||
|
|
49
|
+
(client.ui.viewState.current
|
|
50
|
+
? { name: getNameFromPath(client.ui.viewState.current.path) }
|
|
51
|
+
: undefined),
|
|
52
|
+
);
|
|
53
|
+
const sf = LuaStackFrame.createWithGlobalEnv(
|
|
54
|
+
client.clientSystem.spaceLuaEnv.env,
|
|
55
|
+
ctx,
|
|
56
|
+
);
|
|
57
|
+
sf.threadState.budget = makeLuaBudget({
|
|
58
|
+
busyLimitMs: BUSY_LIMIT_DEFAULT_MS,
|
|
59
|
+
onLimit: (b) => {
|
|
60
|
+
b.stopped = true;
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
const env = new LuaEnv(client.clientSystem.spaceLuaEnv.env);
|
|
64
|
+
env.setLocal("_CTX", tl);
|
|
65
|
+
const rawResult = singleResult(await compute(env, sf));
|
|
66
|
+
if (isTaggedFloat(rawResult) || typeof rawResult === "number") {
|
|
67
|
+
return rawResult;
|
|
68
|
+
}
|
|
69
|
+
if (rawResult instanceof LuaTable) {
|
|
70
|
+
if (rawResult.rawGet("_isWidget")) {
|
|
71
|
+
return luaValueToJS(rawResult, sf);
|
|
72
|
+
}
|
|
73
|
+
return rawResult;
|
|
74
|
+
}
|
|
75
|
+
return luaValueToJS(rawResult, sf);
|
|
76
|
+
} catch (e: any) {
|
|
77
|
+
if (e instanceof LuaBudgetStopped) {
|
|
78
|
+
return `**Lua timeout:** this widget took too long to render and was stopped. Reload the page to try again.`;
|
|
79
|
+
}
|
|
80
|
+
if (e instanceof LuaRuntimeError && e.sf?.astCtx) {
|
|
81
|
+
const source = resolveASTReference(e.sf.astCtx);
|
|
82
|
+
if (source) {
|
|
83
|
+
return `**Lua error:** ${e.message} (Origin: [[${encodeRef(source)}]])`;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return `**Lua error:** ${e.message}`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Evaluate a `${...}`-style expression string and render it as a widget. */
|
|
91
|
+
export async function renderLuaExpression(
|
|
92
|
+
client: Client,
|
|
93
|
+
expressionText: string,
|
|
94
|
+
currentPageMeta?: { name: string } | undefined,
|
|
95
|
+
): Promise<any> {
|
|
96
|
+
if (expressionText.trim().length === 0) {
|
|
97
|
+
return "**Error:** Empty Lua expression";
|
|
98
|
+
}
|
|
99
|
+
const expr = parseExpressionString(expressionText);
|
|
100
|
+
return renderLuaWidgetResult(
|
|
101
|
+
client,
|
|
102
|
+
(env, sf) => evalExpression(expr, env, sf),
|
|
103
|
+
expr.ctx,
|
|
104
|
+
currentPageMeta,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Call a stored Lua render function (e.g. a code widget) and render it. */
|
|
109
|
+
export async function renderLuaCallback(
|
|
110
|
+
client: Client,
|
|
111
|
+
fn: ILuaFunction,
|
|
112
|
+
args: LuaValue[],
|
|
113
|
+
currentPageMeta?: { name: string } | undefined,
|
|
114
|
+
): Promise<any> {
|
|
115
|
+
return renderLuaWidgetResult(
|
|
116
|
+
client,
|
|
117
|
+
(_env, sf) => fn.call(sf, ...args),
|
|
118
|
+
{} as ASTCtx,
|
|
119
|
+
currentPageMeta,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export type PortableMarkdownResult =
|
|
124
|
+
| { ok: true; markdown: string }
|
|
125
|
+
| { ok: false; reason: string };
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Evaluate a `${...}`-style expression and produce portable GFM markdown — the
|
|
129
|
+
* same clean rendering the Copy button uses — or report why it can't be baked.
|
|
130
|
+
* - nil/empty → ok with empty markdown
|
|
131
|
+
* - Lua error → not ok (the eval error string)
|
|
132
|
+
* - widget object: portable only if it exposes a `markdown` rendering;
|
|
133
|
+
* html-only widgets are not bakeable
|
|
134
|
+
* - scalars / tables / arrays / strings → clean GFM
|
|
135
|
+
*/
|
|
136
|
+
export async function expressionToPortableMarkdown(
|
|
137
|
+
client: Client,
|
|
138
|
+
expressionText: string,
|
|
139
|
+
currentPageMeta?: { name: string } | undefined,
|
|
140
|
+
): Promise<PortableMarkdownResult> {
|
|
141
|
+
const rawResult = await renderLuaExpression(
|
|
142
|
+
client,
|
|
143
|
+
expressionText,
|
|
144
|
+
currentPageMeta,
|
|
145
|
+
);
|
|
146
|
+
if (isViewValue(rawResult)) {
|
|
147
|
+
return { ok: false, reason: "A view has no portable Markdown rendering" };
|
|
148
|
+
}
|
|
149
|
+
if (rawResult === null || rawResult === undefined) {
|
|
150
|
+
return { ok: true, markdown: "" };
|
|
151
|
+
}
|
|
152
|
+
// renderLuaExpression returns eval failures as markdown error strings.
|
|
153
|
+
if (
|
|
154
|
+
typeof rawResult === "string" &&
|
|
155
|
+
(rawResult.startsWith("**Lua error:**") ||
|
|
156
|
+
rawResult.startsWith("**Error:**"))
|
|
157
|
+
) {
|
|
158
|
+
return { ok: false, reason: rawResult };
|
|
159
|
+
}
|
|
160
|
+
// Widget objects: portable only when they expose a `markdown` rendering.
|
|
161
|
+
if (typeof rawResult === "object" && (rawResult as any)._isWidget) {
|
|
162
|
+
const md = (rawResult as any).markdown;
|
|
163
|
+
if (typeof md === "string") {
|
|
164
|
+
return { ok: true, markdown: md.trim() };
|
|
165
|
+
}
|
|
166
|
+
return { ok: false, reason: "html-only widget (no markdown rendering)" };
|
|
167
|
+
}
|
|
168
|
+
const markdown = await renderResultToCleanMarkdown(
|
|
169
|
+
rawResult,
|
|
170
|
+
classifyResult(rawResult),
|
|
171
|
+
);
|
|
172
|
+
return { ok: true, markdown };
|
|
173
|
+
}
|