@silverbulletmd/silverbullet 2.7.0 → 2.8.1

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 CHANGED
@@ -27,8 +27,6 @@ SilverBullet's frontend is written in [TypeScript](https://www.typescriptlang.or
27
27
 
28
28
  The server backend is written in Go.
29
29
 
30
- If you're considering contributing changes, be aware of the [LLM use policy](https://silverbullet.md/LLM%20Use).
31
-
32
30
  ## Code structure
33
31
  * `client/`: The SilverBullet client, implemented with TypeScript
34
32
  * `server/`: The SilverBullet server, written in Go
@@ -1,10 +1,12 @@
1
1
  import type { SysCallMapping } from "../../plugos/system.ts";
2
+ import type { Client } from "../../client.ts";
2
3
  import { reloadAllWidgets } from "../../codemirror/code_widget.ts";
3
4
  import { broadcastReload } from "../../components/widget_sandbox_iframe.ts";
4
5
 
5
- export function clientCodeWidgetSyscalls(): SysCallMapping {
6
+ export function clientCodeWidgetSyscalls(client: Client): SysCallMapping {
6
7
  return {
7
8
  "codeWidget.refreshAll": () => {
9
+ client.widgetCache.clearPrewarm();
8
10
  broadcastReload();
9
11
  return reloadAllWidgets();
10
12
  },
@@ -71,6 +71,8 @@ import type {
71
71
  UploadFile,
72
72
  } from "@silverbulletmd/silverbullet/type/client";
73
73
  import { openSearchPanel } from "@codemirror/search";
74
+ import { forceLinting } from "@codemirror/lint";
75
+ import { refreshLintEffect } from "../../codemirror/lint.ts";
74
76
  import {
75
77
  isValidPath,
76
78
  parseToRef,
@@ -249,6 +251,15 @@ export function editorSyscalls(client: Client): SysCallMapping {
249
251
  "editor.reloadPage": async () => {
250
252
  await client.reloadEditor();
251
253
  },
254
+ "editor.forceLint": () => {
255
+ // `forceLinting` alone is a no-op on unchanged content after the
256
+ // linter's internal "scheduled" flag has been cleared; the effect
257
+ // re-arms it via `needsRefresh`.
258
+ client.editorView.dispatch({
259
+ effects: refreshLintEffect.of(null),
260
+ });
261
+ forceLinting(client.editorView);
262
+ },
252
263
  "editor.reloadUI": () => {
253
264
  location.reload();
254
265
  },
@@ -453,20 +464,14 @@ export function editorSyscalls(client: Client): SysCallMapping {
453
464
  }
454
465
  },
455
466
  "editor.moveCursor": (_ctx, pos: number, center = false) => {
467
+ // Always scroll into view so callers don't strand the cursor
468
+ // off-screen; `nearest` (default) is a no-op when already visible.
456
469
  client.editorView.dispatch({
457
- selection: {
458
- anchor: pos,
459
- },
470
+ selection: { anchor: pos },
471
+ effects: [
472
+ EditorView.scrollIntoView(pos, center ? { y: "center" } : {}),
473
+ ],
460
474
  });
461
- if (center) {
462
- client.editorView.dispatch({
463
- effects: [
464
- EditorView.scrollIntoView(pos, {
465
- y: "center",
466
- }),
467
- ],
468
- });
469
- }
470
475
  client.editorView.focus();
471
476
  },
472
477
  "editor.moveCursorToLine": (
@@ -17,8 +17,25 @@ export function indexSyscalls(
17
17
  client: Client,
18
18
  ): SysCallMapping {
19
19
  return {
20
+ // Query collection API
20
21
  "index.tag": (_ctx, tagName: string): LuaQueryCollection => {
21
- return objectIndex.tag(tagName);
22
+ return objectIndex.objectsWithTag(tagName);
23
+ },
24
+ // Alias for tag
25
+ "index.objects": (_ctx, tagName: string): LuaQueryCollection => {
26
+ return objectIndex.objectsWithTag(tagName);
27
+ },
28
+ "index.pages": (_ctx, tagName?: string): LuaQueryCollection => {
29
+ return objectIndex.rootTaggedObjects("page", tagName);
30
+ },
31
+ "index.subPages": (_ctx, pageName: string): LuaQueryCollection => {
32
+ return objectIndex.subPages(pageName);
33
+ },
34
+ "index.documents": (): LuaQueryCollection => {
35
+ return objectIndex.objectsWithTag("document");
36
+ },
37
+ "index.links": (): LuaQueryCollection => {
38
+ return objectIndex.objectsWithTag("link");
22
39
  },
23
40
  "index.contentPages": (): LuaQueryCollection => {
24
41
  return objectIndex.contentPages();
@@ -26,6 +43,28 @@ export function indexSyscalls(
26
43
  "index.metaPages": (): LuaQueryCollection => {
27
44
  return objectIndex.metaPages();
28
45
  },
46
+ "index.tasks": (_ctx, tagName?: string): LuaQueryCollection => {
47
+ return objectIndex.rootTaggedObjects("task", tagName);
48
+ },
49
+ "index.headers": (_ctx, tagName?: string): LuaQueryCollection => {
50
+ return objectIndex.rootTaggedObjects("header", tagName);
51
+ },
52
+ "index.items": (_ctx, tagName?: string): LuaQueryCollection => {
53
+ return objectIndex.rootTaggedObjects("item", tagName);
54
+ },
55
+ "index.paragraphs": (_ctx, tagName?: string): LuaQueryCollection => {
56
+ return objectIndex.rootTaggedObjects("paragraph", tagName);
57
+ },
58
+ "index.tables": (_ctx, tagName?: string): LuaQueryCollection => {
59
+ return objectIndex.rootTaggedObjects("table", tagName);
60
+ },
61
+ "index.tags": (): LuaQueryCollection => {
62
+ return objectIndex.objectsWithTag("tag");
63
+ },
64
+ "index.aspiringPages": (): LuaQueryCollection => {
65
+ return objectIndex.aspiringPages();
66
+ },
67
+ // Internals
29
68
  "index.aggregates": (): LuaQueryCollection => {
30
69
  return objectIndex.aggregates();
31
70
  },
@@ -61,6 +100,13 @@ export function indexSyscalls(
61
100
  }
62
101
  }
63
102
  },
103
+ "index.previewProcessedObjects": (
104
+ _ctx,
105
+ page: string,
106
+ objects: ObjectValue[],
107
+ ): Promise<{ tag: string; object: ObjectValue }[]> => {
108
+ return objectIndex.previewProcessedObjects(page, objects);
109
+ },
64
110
  "index.getObjectByRef": (
65
111
  _ctx,
66
112
  page: string,
@@ -4,7 +4,7 @@
4
4
  import { Command } from "commander";
5
5
 
6
6
  // version.ts
7
- var version = "2.7.0";
7
+ var version = "2.8.1";
8
8
 
9
9
  // client/plugos/plug_compile.ts
10
10
  import * as path from "node:path";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silverbulletmd/silverbullet",
3
- "version": "2.7.0",
3
+ "version": "2.8.1",
4
4
  "type": "module",
5
5
  "description": "A self-hosted, web-based note taking app",
6
6
  "publishConfig": {
@@ -153,6 +153,11 @@ export function reloadPage(): Promise<void> {
153
153
  return syscall("editor.reloadPage");
154
154
  }
155
155
 
156
+ /** Useful when a plug toggles a piece of state that lint subscribers consult. */
157
+ export function forceLint(): Promise<void> {
158
+ return syscall("editor.forceLint");
159
+ }
160
+
156
161
  /**
157
162
  * Force reloads the browser UI
158
163
  */
@@ -1,4 +1,7 @@
1
- import type { LuaCollectionQuery } from "../../client/space_lua/query_collection.ts";
1
+ import type {
2
+ LuaCollectionQuery,
3
+ LuaQueryCollection,
4
+ } from "../../client/space_lua/query_collection.ts";
2
5
  import { syscall } from "@silverbulletmd/silverbullet/syscall";
3
6
  import type { ObjectValue } from "../../plug-api/types/index.ts";
4
7
 
@@ -27,6 +30,103 @@ export function validateObjects<T>(
27
30
  return syscall("index.validateObjects", page, objects);
28
31
  }
29
32
 
33
+ /**
34
+ * Run the full indexing pipeline (validation, multi-tag expansion,
35
+ * tag transforms) and return the resulting objects each paired with
36
+ * the tag they're indexed under. Read-only — no DB writes.
37
+ */
38
+ export function previewProcessedObjects(
39
+ page: string,
40
+ objects: ObjectValue[],
41
+ ): Promise<{ tag: string; object: ObjectValue }[]> {
42
+ return syscall("index.previewProcessedObjects", page, objects);
43
+ }
44
+
45
+ /**
46
+ * Returns objects carrying the given tag as a query collection.
47
+ */
48
+ export function objects(tagName: string): Promise<LuaQueryCollection> {
49
+ return syscall("index.objects", tagName);
50
+ }
51
+
52
+ /**
53
+ * Returns all pages (optionally filtered by an additional tag) as a query collection.
54
+ */
55
+ export function pages(tagName?: string): Promise<LuaQueryCollection> {
56
+ return syscall("index.pages", tagName);
57
+ }
58
+
59
+ /**
60
+ * Returns all sub-pages of the given page (pages whose name starts with `<pageName>/`)
61
+ * as a query collection.
62
+ */
63
+ export function subPages(pageName: string): Promise<LuaQueryCollection> {
64
+ return syscall("index.subPages", pageName);
65
+ }
66
+
67
+ /**
68
+ * Returns all documents as a query collection.
69
+ */
70
+ export function documents(): Promise<LuaQueryCollection> {
71
+ return syscall("index.documents");
72
+ }
73
+
74
+ /**
75
+ * Returns all links as a query collection.
76
+ */
77
+ export function links(): Promise<LuaQueryCollection> {
78
+ return syscall("index.links");
79
+ }
80
+
81
+ /**
82
+ * Returns all tasks (optionally filtered by an additional tag) as a query collection.
83
+ */
84
+ export function tasks(tagName?: string): Promise<LuaQueryCollection> {
85
+ return syscall("index.tasks", tagName);
86
+ }
87
+
88
+ /**
89
+ * Returns all headers (optionally filtered by an additional tag) as a query collection.
90
+ */
91
+ export function headers(tagName?: string): Promise<LuaQueryCollection> {
92
+ return syscall("index.headers", tagName);
93
+ }
94
+
95
+ /**
96
+ * Returns all list items (optionally filtered by an additional tag) as a query collection.
97
+ */
98
+ export function items(tagName?: string): Promise<LuaQueryCollection> {
99
+ return syscall("index.items", tagName);
100
+ }
101
+
102
+ /**
103
+ * Returns all paragraphs (optionally filtered by an additional tag) as a query collection.
104
+ */
105
+ export function paragraphs(tagName?: string): Promise<LuaQueryCollection> {
106
+ return syscall("index.paragraphs", tagName);
107
+ }
108
+
109
+ /**
110
+ * Returns all tables (optionally filtered by an additional tag) as a query collection.
111
+ */
112
+ export function tables(tagName?: string): Promise<LuaQueryCollection> {
113
+ return syscall("index.tables", tagName);
114
+ }
115
+
116
+ /**
117
+ * Returns all aspiring (referenced but not yet created) pages as a query collection.
118
+ */
119
+ export function aspiringPages(): Promise<LuaQueryCollection> {
120
+ return syscall("index.aspiringPages");
121
+ }
122
+
123
+ /**
124
+ * Returns all tag objects as a query collection.
125
+ */
126
+ export function tags(): Promise<LuaQueryCollection> {
127
+ return syscall("index.tags");
128
+ }
129
+
30
130
  /**
31
131
  * Queries objects using a Lua-based collection query
32
132
  * @param tag - The tag to filter objects by
@@ -54,6 +54,18 @@ export type LintDiagnostic = {
54
54
  to: number;
55
55
  severity: "error" | "warning" | "info" | "hint";
56
56
  message: string;
57
+ /**
58
+ * Optional HTML rendered into the hover tooltip for this diagnostic.
59
+ * When present, takes precedence over `message` for tooltip display.
60
+ * `message` is still used as a plain-text fallback (e.g. in the lint
61
+ * panel) and as the diagnostic's accessible label.
62
+ */
63
+ messageHtml?: string;
64
+ /**
65
+ * Optional CSS class added to the inline range mark for this diagnostic,
66
+ * in addition to CodeMirror's default `.cm-lintRange-<severity>` class.
67
+ */
68
+ markClass?: string;
57
69
  };
58
70
 
59
71
  export type UploadFile = {