From 5ff1a8bae3ff3696ed757edd97fef817c7d6ed5d Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Mon, 28 Aug 2023 17:12:15 +0200 Subject: [PATCH] Refactor all the things --- .gitignore | 1 + Dockerfile | 2 +- cli/plug_run.ts | 6 +- cmd/server.ts | 2 +- plug-api/plugos-syscall/mq.ts | 4 +- plug-api/silverbullet-syscall/system.ts | 11 +- plug-api/syscalls.ts | 2 + plug-api/types.ts | 9 +- plugos/hooks/mq.ts | 8 +- plugos/lib/kv_store.deno_kv.test.ts | 7 +- plugos/lib/kv_store.deno_kv.ts | 18 +- plugos/lib/mq.deno_kv.test.ts | 20 + plugos/lib/mq.deno_kv.ts | 87 ++++ plugos/lib/mq.dexie.ts | 30 +- plugos/lib/mq.ts | 16 + plugos/syscalls/mq.dexie.ts | 4 +- plugs/builtin_plugs.ts | 6 +- plugs/core/cloud.ts | 85 ---- plugs/core/core.plug.yaml | 515 -------------------- plugs/directive/command.ts | 9 +- plugs/directive/complete.ts | 6 +- plugs/directive/data.ts | 3 +- plugs/directive/directive.plug.yaml | 10 +- plugs/directive/eval_directive.ts | 8 +- plugs/directive/query_directive.ts | 6 +- plugs/directive/template_directive.ts | 11 +- plugs/directive/util.ts | 4 +- plugs/{core => editor}/account.ts | 2 +- plugs/{core => editor}/broken_links.ts | 6 +- plugs/editor/client.ts | 7 + plugs/{core => editor}/command.ts | 4 +- plugs/{core => editor}/debug.ts | 2 +- plugs/editor/editor.plug.yaml | 240 +++++++++ plugs/{core => editor}/editor.ts | 2 +- plugs/{core => editor}/embed.ts | 2 +- plugs/{core => editor}/help.ts | 2 +- plugs/{core => editor}/link.ts | 3 +- plugs/{core => editor}/navigate.ts | 2 +- plugs/{core => editor}/page.ts | 82 +--- plugs/{core => editor}/stats.ts | 2 +- plugs/{core => editor}/text.ts | 2 +- plugs/{core => editor}/vim.ts | 5 +- plugs/emoji/emoji.ts | 2 +- plugs/federation/federation.ts | 4 +- plugs/{core => index}/anchor.ts | 2 +- plugs/{core => index}/attachment.ts | 2 +- plugs/{core => index}/attributes.ts | 2 +- plugs/index/index.plug.yaml | 133 +++++ plugs/{core => index}/item.ts | 2 +- plugs/index/page.ts | 77 +++ plugs/{core => index}/page_links.ts | 2 +- plugs/{core => index}/refactor.ts | 2 +- plugs/{core => index}/tags.ts | 4 +- plugs/markdown/markdown.ts | 3 +- plugs/markdown/markdown_render.test.ts | 2 +- plugs/markdown/preview.ts | 6 +- plugs/markdown/util.ts | 2 +- plugs/markdown/widget.ts | 6 +- plugs/plug-manager/plug-manager.plug.yaml | 26 + plugs/{core => plug-manager}/plugmanager.ts | 3 +- plugs/search/engine.ts | 2 +- plugs/search/search.plug.yaml | 2 +- plugs/search/search.ts | 11 +- plugs/share/publish.ts | 3 +- plugs/sync/sync.plug.yaml | 9 + plugs/{core => sync}/sync.ts | 2 +- plugs/tasks/task.ts | 10 +- plugs/tasks/tasks.plug.yaml | 2 +- plugs/template/template.plug.yaml | 115 +++++ plugs/{core => template}/template.ts | 2 +- server/server_system.ts | 24 +- {cli => server}/syscalls/index.test.ts | 7 +- {cli => server}/syscalls/index.ts | 0 {cli => server}/syscalls/space.ts | 0 web/boot.ts | 3 +- web/client.ts | 1 - web/client_system.ts | 25 +- web/editor_ui.tsx | 2 +- web/index.html | 4 +- web/syscalls/editor.ts | 11 + web/syscalls/mq.proxy.ts | 13 + web/syscalls/system.ts | 18 +- web/syscalls/util.ts | 9 +- website/CHANGELOG.md | 6 + website/Cloud Links.md | 6 +- website/SETTINGS.md | 2 +- website/🔌 Directive.md | 4 +- 87 files changed, 930 insertions(+), 896 deletions(-) create mode 100644 plug-api/syscalls.ts create mode 100644 plugos/lib/mq.deno_kv.test.ts create mode 100644 plugos/lib/mq.deno_kv.ts create mode 100644 plugos/lib/mq.ts delete mode 100644 plugs/core/cloud.ts delete mode 100644 plugs/core/core.plug.yaml rename plugs/{core => editor}/account.ts (64%) rename plugs/{core => editor}/broken_links.ts (95%) create mode 100644 plugs/editor/client.ts rename plugs/{core => editor}/command.ts (77%) rename plugs/{core => editor}/debug.ts (81%) create mode 100644 plugs/editor/editor.plug.yaml rename plugs/{core => editor}/editor.ts (94%) rename plugs/{core => editor}/embed.ts (95%) rename plugs/{core => editor}/help.ts (83%) rename plugs/{core => editor}/link.ts (93%) rename plugs/{core => editor}/navigate.ts (97%) rename plugs/{core => editor}/page.ts (54%) rename plugs/{core => editor}/stats.ts (90%) rename plugs/{core => editor}/text.ts (98%) rename plugs/{core => editor}/vim.ts (82%) rename plugs/{core => index}/anchor.ts (95%) rename plugs/{core => index}/attachment.ts (81%) rename plugs/{core => index}/attributes.ts (98%) create mode 100644 plugs/index/index.plug.yaml rename plugs/{core => index}/item.ts (97%) create mode 100644 plugs/index/page.ts rename plugs/{core => index}/page_links.ts (98%) rename plugs/{core => index}/refactor.ts (98%) rename plugs/{core => index}/tags.ts (92%) create mode 100644 plugs/plug-manager/plug-manager.plug.yaml rename plugs/{core => plug-manager}/plugmanager.ts (97%) create mode 100644 plugs/sync/sync.plug.yaml rename plugs/{core => sync}/sync.ts (73%) create mode 100644 plugs/template/template.plug.yaml rename plugs/{core => template}/template.ts (99%) rename {cli => server}/syscalls/index.test.ts (90%) rename {cli => server}/syscalls/index.ts (100%) rename {cli => server}/syscalls/space.ts (100%) create mode 100644 web/syscalls/mq.proxy.ts diff --git a/.gitignore b/.gitignore index c5cd65a..192f334 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ node_modules *.db test_space silverbullet +.silverbullet.db* \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 98d4708..548d1ab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM lukechannings/deno:v1.36.1 +FROM lukechannings/deno:v1.36.3 # The volume that will keep the space data # Create a volume first: # docker volume create myspace diff --git a/cli/plug_run.ts b/cli/plug_run.ts index 36cf69a..83b2d32 100644 --- a/cli/plug_run.ts +++ b/cli/plug_run.ts @@ -38,7 +38,7 @@ export async function runPlug( }); if (indexFirst) { - await serverSystem.system.loadedPlugs.get("core")!.invoke( + await serverSystem.system.loadedPlugs.get("index")!.invoke( "reindexSpace", [], ); @@ -53,8 +53,8 @@ export async function runPlug( } const result = await plug.invoke(funcName, args); await serverSystem.close(); - await serverSystem.kvStore?.delete(); - // await Deno.remove(tempFile); + serverSystem.denoKv.close(); + await Deno.remove(tempFile); serverController.abort(); return result; } else { diff --git a/cmd/server.ts b/cmd/server.ts index 0019c06..bbdef95 100644 --- a/cmd/server.ts +++ b/cmd/server.ts @@ -95,7 +95,7 @@ To allow outside connections, pass -L 0.0.0.0 as a flag, and put a TLS terminato system = serverSystem.system; if (options.reindex) { console.log("Reindexing space (requested via --reindex flag)"); - await serverSystem.system.loadedPlugs.get("core")!.invoke( + await serverSystem.system.loadedPlugs.get("index")!.invoke( "reindexSpace", [], ); diff --git a/plug-api/plugos-syscall/mq.ts b/plug-api/plugos-syscall/mq.ts index c5891c9..39d9534 100644 --- a/plug-api/plugos-syscall/mq.ts +++ b/plug-api/plugos-syscall/mq.ts @@ -1,5 +1,5 @@ import { syscall } from "$sb/plugos-syscall/syscall.ts"; -import { QueueStats } from "$sb/types.ts"; +import { MQStats } from "$sb/types.ts"; export function send(queue: string, body: any) { return syscall("mq.send", queue, body); @@ -17,6 +17,6 @@ export function batchAck(queue: string, ids: string[]) { return syscall("mq.batchAck", queue, ids); } -export function getQueueStats(queue: string): Promise { +export function getQueueStats(queue: string): Promise { return syscall("mq.getQueueStats", queue); } diff --git a/plug-api/silverbullet-syscall/system.ts b/plug-api/silverbullet-syscall/system.ts index 9c87ca2..9b65623 100644 --- a/plug-api/silverbullet-syscall/system.ts +++ b/plug-api/silverbullet-syscall/system.ts @@ -1,20 +1,11 @@ import type { CommandDef } from "../../web/hooks/command.ts"; import { syscall } from "./syscall.ts"; -export function invoke( - name: string, - ...args: any[] -): Promise { - return syscall("system.invoke", name, ...args); -} - -// @deprecated use invoke instead export function invokeFunction( - env: string, name: string, ...args: any[] ): Promise { - return syscall("system.invokeFunction", env, name, ...args); + return syscall("system.invokeFunction", name, ...args); } // Only available on the client diff --git a/plug-api/syscalls.ts b/plug-api/syscalls.ts new file mode 100644 index 0000000..740ff3a --- /dev/null +++ b/plug-api/syscalls.ts @@ -0,0 +1,2 @@ +export * from "$sb/silverbullet-syscall/mod.ts"; +export * from "$sb/plugos-syscall/mod.ts"; diff --git a/plug-api/types.ts b/plug-api/types.ts index b6cdb64..310dd16 100644 --- a/plug-api/types.ts +++ b/plug-api/types.ts @@ -1,16 +1,21 @@ -export type Message = { +export type MQMessage = { id: string; queue: string; body: any; retries?: number; }; -export type QueueStats = { +export type MQStats = { queued: number; processing: number; dlq: number; }; +export type MQSubscribeOptions = { + batchSize?: number; + pollInterval?: number; +}; + export type FileMeta = { name: string; lastModified: number; diff --git a/plugos/hooks/mq.ts b/plugos/hooks/mq.ts index 4239254..08d8309 100644 --- a/plugos/hooks/mq.ts +++ b/plugos/hooks/mq.ts @@ -1,8 +1,8 @@ import { Hook, Manifest } from "../types.ts"; import { System } from "../system.ts"; -import { DexieMQ } from "../lib/mq.dexie.ts"; import { fullQueueName } from "../lib/mq_util.ts"; -import { Message } from "$sb/types.ts"; +import { MQMessage } from "$sb/types.ts"; +import { MessageQueue } from "../lib/mq.ts"; type MQSubscription = { queue: string; @@ -17,7 +17,7 @@ export type MQHookT = { export class MQHook implements Hook { subscriptions: (() => void)[] = []; - constructor(private system: System, readonly mq: DexieMQ) { + constructor(private system: System, readonly mq: MessageQueue) { } apply(system: System): void { @@ -64,7 +64,7 @@ export class MQHook implements Hook { { batchSize: subscriptionDef.batchSize, }, - async (messages: Message[]) => { + async (messages: MQMessage[]) => { try { await plug.invoke(name, [messages]); if (subscriptionDef.autoAck) { diff --git a/plugos/lib/kv_store.deno_kv.test.ts b/plugos/lib/kv_store.deno_kv.test.ts index dc24326..d067647 100644 --- a/plugos/lib/kv_store.deno_kv.test.ts +++ b/plugos/lib/kv_store.deno_kv.test.ts @@ -2,8 +2,8 @@ import { assertEquals } from "../../test_deps.ts"; import { DenoKVStore } from "./kv_store.deno_kv.ts"; Deno.test("Test KV index", async () => { - const kv = new DenoKVStore(); - await kv.init("test.db"); + const denoKv = await Deno.openKv("test.db"); + const kv = new DenoKVStore(denoKv); await kv.set("name", "Peter"); assertEquals(await kv.get("name"), "Peter"); @@ -52,5 +52,6 @@ Deno.test("Test KV index", async () => { await kv.deletePrefix(""); assertEquals(await kv.queryPrefix(""), []); - await kv.delete(); + denoKv.close(); + await Deno.remove("test.db"); }); diff --git a/plugos/lib/kv_store.deno_kv.ts b/plugos/lib/kv_store.deno_kv.ts index 58cc51e..60933bb 100644 --- a/plugos/lib/kv_store.deno_kv.ts +++ b/plugos/lib/kv_store.deno_kv.ts @@ -5,23 +5,7 @@ import { KV, KVStore } from "./kv_store.ts"; const kvBatchSize = 10; export class DenoKVStore implements KVStore { - kv!: Deno.Kv; - path: string | undefined; - - async init(path?: string) { - this.path = path; - this.kv = await Deno.openKv(path); - } - - close() { - this.kv.close(); - } - - async delete() { - this.kv.close(); - if (this.path) { - await Deno.remove(this.path); - } + constructor(private kv: Deno.Kv) { } del(key: string): Promise { diff --git a/plugos/lib/mq.deno_kv.test.ts b/plugos/lib/mq.deno_kv.test.ts new file mode 100644 index 0000000..02e1bcb --- /dev/null +++ b/plugos/lib/mq.deno_kv.test.ts @@ -0,0 +1,20 @@ +import { sleep } from "../../common/async_util.ts"; +import { DenoKvMQ } from "./mq.deno_kv.ts"; + +Deno.test("Deno MQ", async () => { + const denoKv = await Deno.openKv("test.db"); + const mq = new DenoKvMQ(denoKv); + const unsub = mq.subscribe("test", {}, (messages) => { + console.log("Received on test", messages); + }); + const unsub2 = mq.subscribe("test2", {}, (messages) => { + console.log("Received on test2", messages); + }); + await mq.send("test", "Hello World"); + await mq.batchSend("test2", ["Hello World 2", "Hello World 3"]); + + // Let's avoid a panic here + await sleep(20); + denoKv.close(); + await Deno.remove("test.db"); +}); diff --git a/plugos/lib/mq.deno_kv.ts b/plugos/lib/mq.deno_kv.ts new file mode 100644 index 0000000..c72f97a --- /dev/null +++ b/plugos/lib/mq.deno_kv.ts @@ -0,0 +1,87 @@ +/// + +import { + MQMessage, + MQStats, + MQSubscribeOptions, +} from "../../plug-api/types.ts"; +import { MessageQueue } from "./mq.ts"; + +type QueuedMessage = [string, MQMessage]; + +export class DenoKvMQ implements MessageQueue { + listeners: Map void | Promise>> = + new Map(); + + constructor(private kv: Deno.Kv) { + kv.listenQueue(async (message: unknown) => { + const [queue, body] = message as QueuedMessage; + const listeners = this.listeners.get(queue); + if (!listeners) { + return; + } + for (const listener of listeners) { + await Promise.resolve(listener([{ id: "_dummyid", queue, body }])); + } + }); + } + + // Dummy implementation + getQueueStats(_queue: string): Promise { + return Promise.resolve({ + queued: 0, + processing: 0, + dlq: 0, + }); + } + + // Dummy implementation + getAllQueueStats(): Promise> { + return Promise.resolve({}); + } + + async batchSend(queue: string, bodies: any[]): Promise { + const results = await Promise.all( + bodies.map((body) => this.kv.enqueue([queue, body])), + ); + for (const result of results) { + if (!result.ok) { + throw result; + } + } + } + async send(queue: string, body: any): Promise { + const result = await this.kv.enqueue([queue, body]); + if (!result.ok) { + throw result; + } + } + subscribe( + queue: string, + _options: MQSubscribeOptions, + callback: (messages: MQMessage[]) => void | Promise, + ): () => void { + const listeners = this.listeners.get(queue); + if (!listeners) { + this.listeners.set(queue, new Set([callback])); + } else { + listeners.add(callback); + } + + return () => { + const listeners = this.listeners.get(queue); + if (!listeners) { + return; + } + listeners.delete(callback); + }; + } + ack(_queue: string, _id: string): Promise { + // Doesn't apply to this implementation + return Promise.resolve(); + } + batchAck(_queue: string, _ids: string[]): Promise { + // Doesn't apply to this implementation + return Promise.resolve(); + } +} diff --git a/plugos/lib/mq.dexie.ts b/plugos/lib/mq.dexie.ts index 718a5c4..e224a8a 100644 --- a/plugos/lib/mq.dexie.ts +++ b/plugos/lib/mq.dexie.ts @@ -1,18 +1,14 @@ import Dexie, { Table } from "dexie"; -import { Message, QueueStats } from "$sb/types.ts"; +import { MQMessage, MQStats, MQSubscribeOptions } from "$sb/types.ts"; +import { MessageQueue } from "./mq.ts"; -export type ProcessingMessage = Message & { +export type ProcessingMessage = MQMessage & { ts: number; }; -export type SubscribeOptions = { - batchSize?: number; - pollInterval?: number; -}; - -export class DexieMQ { +export class DexieMQ implements MessageQueue { db: Dexie; - queued: Table; + queued: Table; processing: Table; dlq: Table; @@ -63,13 +59,15 @@ export class DexieMQ { return this.batchSend(queue, [body]); } - poll(queue: string, maxItems: number): Promise { + poll(queue: string, maxItems: number): Promise { return this.db.transaction( "rw", [this.queued, this.processing], async (tx) => { const messages = - (await tx.table("queued").where({ queue }) + (await tx.table("queued").where({ + queue, + }) .sortBy("id")).slice(0, maxItems); const ids: [string, string][] = messages.map((m) => [queue, m.id]); await tx.table("queued").bulkDelete(ids); @@ -93,8 +91,8 @@ export class DexieMQ { */ subscribe( queue: string, - options: SubscribeOptions, - callback: (messages: Message[]) => Promise | void, + options: MQSubscribeOptions, + callback: (messages: MQMessage[]) => Promise | void, ): () => void { let running = true; let timeout: number | undefined; @@ -219,7 +217,7 @@ export class DexieMQ { return this.dlq.clear(); } - getQueueStats(queue: string): Promise { + getQueueStats(queue: string): Promise { return this.db.transaction( "r", [this.queued, this.processing, this.dlq], @@ -237,8 +235,8 @@ export class DexieMQ { ); } - async getAllQueueStats(): Promise> { - const allStatus: Record = {}; + async getAllQueueStats(): Promise> { + const allStatus: Record = {}; await this.db.transaction( "r", [this.queued, this.processing, this.dlq], diff --git a/plugos/lib/mq.ts b/plugos/lib/mq.ts new file mode 100644 index 0000000..3717a57 --- /dev/null +++ b/plugos/lib/mq.ts @@ -0,0 +1,16 @@ +import { MQMessage, MQStats, MQSubscribeOptions } from "$sb/types.ts"; + +export interface MessageQueue { + batchSend(queue: string, bodies: any[]): Promise; + send(queue: string, body: any): Promise; + subscribe( + queue: string, + options: MQSubscribeOptions, + callback: (messages: MQMessage[]) => Promise | void, + ): () => void; + ack(queue: string, id: string): Promise; + batchAck(queue: string, ids: string[]): Promise; + + getQueueStats(queue: string): Promise; + getAllQueueStats(): Promise>; +} diff --git a/plugos/syscalls/mq.dexie.ts b/plugos/syscalls/mq.dexie.ts index 0bbf397..b4af2eb 100644 --- a/plugos/syscalls/mq.dexie.ts +++ b/plugos/syscalls/mq.dexie.ts @@ -1,9 +1,9 @@ import { SysCallMapping } from "../system.ts"; -import { DexieMQ } from "../lib/mq.dexie.ts"; import { fullQueueName } from "../lib/mq_util.ts"; +import { MessageQueue } from "../lib/mq.ts"; export function mqSyscalls( - mq: DexieMQ, + mq: MessageQueue, ): SysCallMapping { return { "mq.send": (ctx, queue: string, body: any) => { diff --git a/plugs/builtin_plugs.ts b/plugs/builtin_plugs.ts index 2ac354f..4669640 100644 --- a/plugs/builtin_plugs.ts +++ b/plugs/builtin_plugs.ts @@ -1,6 +1,10 @@ // TODO: Figure out how to keep this up-to-date automatically export const builtinPlugNames = [ - "core", + "editor", + "index", + "sync", + "template", + "plug-manager", "directive", "emoji", "markdown", diff --git a/plugs/core/cloud.ts b/plugs/core/cloud.ts deleted file mode 100644 index 993ff0b..0000000 --- a/plugs/core/cloud.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { renderToText, replaceNodesMatching } from "$sb/lib/tree.ts"; -import { parseMarkdown } from "$sb/silverbullet-syscall/markdown.ts"; -import { FileMeta } from "$sb/types.ts"; - -export const cloudPrefix = "💭 "; - -export async function readFileCloud( - name: string, -): Promise<{ data: Uint8Array; meta: FileMeta } | undefined> { - const originalUrl = name.substring( - cloudPrefix.length, - name.length - ".md".length, - ); - let url = originalUrl; - if (!url.includes("/")) { - url += "/index"; - } - if (!url.startsWith("127.0.0.1")) { - url = `https://${url}`; - } else { - url = `http://${url}`; - } - let text = ""; - - try { - const r = await fetch(`${encodeURI(url)}.md`); - text = await r.text(); - if (!r.ok) { - text = `ERROR: ${text}`; - } - } catch (e: any) { - console.error("ERROR thrown", e.message); - text = `ERROR: ${e.message}`; - } - text = await translateLinksWithPrefix( - text, - `${cloudPrefix}${originalUrl.split("/")[0]}/`, - ); - return { - data: new TextEncoder().encode(text), - meta: { - name, - contentType: "text/markdown", - lastModified: 0, - size: text.length, - perm: "ro", - }, - }; -} - -export function writeFileCloud( - name: string, -): Promise { - console.log("Writing cloud file", name); - return getFileMetaCloud(name); -} - -async function translateLinksWithPrefix( - text: string, - prefix: string, -): Promise { - const tree = await parseMarkdown(text); - replaceNodesMatching(tree, (tree) => { - if (tree.type === "WikiLinkPage") { - // Add the prefix in the link text - if (!tree.children![0].text!.startsWith(cloudPrefix)) { - // Only for links that aren't already cloud links - tree.children![0].text = prefix + tree.children![0].text; - } - } - return undefined; - }); - text = renderToText(tree); - return text; -} - -export function getFileMetaCloud(name: string): Promise { - return Promise.resolve({ - name, - size: 0, - contentType: "text/markdown", - lastModified: 0, - perm: "ro", - }); -} diff --git a/plugs/core/core.plug.yaml b/plugs/core/core.plug.yaml deleted file mode 100644 index 751fc55..0000000 --- a/plugs/core/core.plug.yaml +++ /dev/null @@ -1,515 +0,0 @@ -name: core -requiredPermissions: - - fetch -syntax: - Hashtag: - firstCharacters: - - "#" - regex: "#[^#\\d\\s\\[\\]]+\\w+" - className: sb-hashtag - NakedURL: - firstCharacters: - - "h" - regex: "https?:\\/\\/[-a-zA-Z0-9@:%._\\+~#=]{1,256}([-a-zA-Z0-9()@:%_\\+.~#?&=\\/]*)" - className: sb-naked-url - NamedAnchor: - firstCharacters: - - "$" - regex: "\\$[a-zA-Z\\.\\-\\/]+[\\w\\.\\-\\/]*" - className: sb-named-anchor -functions: - setEditorMode: - path: "./editor.ts:setEditorMode" - events: - - editor:init - toggleDarkMode: - path: "./editor.ts:toggleDarkMode" - command: - name: "Editor: Toggle Dark Mode" - centerCursor: - path: "./editor.ts:centerCursorCommand" - command: - name: "Editor: Center Cursor" - key: "Ctrl-Alt-l" - moveToPos: - path: "./editor.ts:moveToPosCommand" - command: - name: "Editor: Move Cursor to Position" - clearPageIndex: - path: "./page.ts:clearPageIndex" - env: server - events: - - page:saved - - page:deleted - pageQueryProvider: - path: ./page.ts:pageQueryProvider - events: - - query:page - parseIndexTextRepublish: - path: "./page.ts:parseIndexTextRepublish" - env: server - events: - - page:index_text - reindexSpaceCommand: - path: "./page.ts:reindexCommand" - command: - name: "Space: Reindex" - processIndexQueue: - path: ./page.ts:processIndexQueue - mqSubscriptions: - - queue: indexQueue - batchSize: 10 - autoAck: true - reindexSpace: - path: "./page.ts:reindexSpace" - deletePage: - path: "./page.ts:deletePage" - command: - name: "Page: Delete" - copyPage: - path: "./page.ts:copyPage" - command: - name: "Page: Copy" - - syncSpaceCommand: - path: "./sync.ts:syncSpaceCommand" - command: - name: "Sync: Now" - key: "Alt-Shift-s" - mac: "Cmd-Shift-s" - - # Attachments - attachmentQueryProvider: - path: ./attachment.ts:attachmentQueryProvider - events: - - query:attachment - - # Backlinks - indexLinks: - path: "./page_links.ts:indexLinks" - events: - - page:index - linkQueryProvider: - path: ./page_links.ts:linkQueryProvider - events: - - query:link - - pageComplete: - path: "./page.ts:pageComplete" - events: - - editor:complete - - attributeComplete: - path: "./attributes.ts:attributeComplete" - events: - - editor:complete - - customAttributeCompleter: - path: ./attributes.ts:customAttributeCompleter - events: - - attribute:complete:page - - attribute:complete:task - - attribute:complete:item - - attribute:complete:* - - builtinAttributeCompleter: - path: ./attributes.ts:builtinAttributeCompleter - events: - - attribute:complete:page - - attribute:complete:task - - attribute:complete:item - - attribute:complete:* - - # Commands - commandComplete: - path: "./command.ts:commandComplete" - events: - - editor:complete - - # Item indexing - indexItem: - path: "./item.ts:indexItems" - events: - - page:index - itemQueryProvider: - path: "./item.ts:queryProvider" - events: - - query:item - - # Navigation - linkNavigate: - path: "./navigate.ts:linkNavigate" - command: - name: Navigate To page - key: Ctrl-Enter - mac: Cmd-Enter - clickNavigate: - path: "./navigate.ts:clickNavigate" - events: - - page:click - navigateHome: - path: "./navigate.ts:navigateCommand" - command: - name: "Navigate: Home" - key: "Alt-h" - page: "" - - # Hashtags - indexTags: - path: "./tags.ts:indexTags" - events: - - page:index - tagComplete: - path: "./tags.ts:tagComplete" - events: - - editor:complete - tagProvider: - path: "./tags.ts:tagProvider" - events: - - query:tag - - # Anchors - indexAnchors: - path: "./anchor.ts:indexAnchors" - events: - - page:index - anchorComplete: - path: "./anchor.ts:anchorComplete" - events: - - editor:complete - - # Template commands - insertTemplateText: - path: "./template.ts:insertTemplateText" - applyLineReplace: - path: ./template.ts:applyLineReplace - insertFrontMatter: - redirect: insertTemplateText - slashCommand: - name: front-matter - description: Insert page front matter - value: | - --- - |^| - --- - makeH1: - redirect: applyLineReplace - slashCommand: - name: h1 - description: Turn line into h1 header - match: "^#*\\s*" - replace: "# " - makeH2: - redirect: applyLineReplace - slashCommand: - name: h2 - description: Turn line into h2 header - match: "^#*\\s*" - replace: "## " - makeH3: - redirect: applyLineReplace - slashCommand: - name: h3 - description: Turn line into h3 header - match: "^#*\\s*" - replace: "### " - makeH4: - redirect: applyLineReplace - slashCommand: - name: h4 - description: Turn line into h4 header - match: "^#*\\s*" - replace: "#### " - insertCodeBlock: - redirect: insertTemplateText - slashCommand: - name: code - description: Insert code block - value: | - ``` - |^| - ``` - - newPage: - path: ./page.ts:newPageCommand - command: - name: "Page: New" - key: "Alt-Shift-n" - - insertHRTemplate: - redirect: insertTemplateText - slashCommand: - name: hr - description: Insert a horizontal rule - value: "---" - insertTable: - redirect: insertTemplateText - slashCommand: - name: table - description: Insert a table - boost: -1 # Low boost because it's likely not very commonly used - value: | - | Header A | Header B | - |----------|----------| - | Cell A|^| | Cell B | - quickNoteCommand: - path: ./template.ts:quickNoteCommand - command: - name: "Quick Note" - key: "Alt-Shift-n" - priority: 1 - dailyNoteCommand: - path: ./template.ts:dailyNoteCommand - command: - name: "Open Daily Note" - key: "Alt-Shift-d" - weeklyNoteCommand: - path: ./template.ts:weeklyNoteCommand - command: - name: "Open Weekly Note" - key: "Alt-Shift-w" - - instantiateTemplateCommand: - path: ./template.ts:instantiateTemplateCommand - command: - name: "Template: Instantiate Page" - insertSnippet: - path: ./template.ts:insertSnippet - command: - name: "Template: Insert Snippet" - slashCommand: - name: snippet - description: Insert a snippet - applyPageTemplateCommand: - path: ./template.ts:applyPageTemplateCommand - slashCommand: - name: page-template - description: Apply a page template - insertTodayCommand: - path: "./template.ts:insertTemplateText" - slashCommand: - name: today - description: Insert today's date - value: "{{today}}" - insertTomorrowCommand: - path: "./template.ts:insertTemplateText" - slashCommand: - name: tomorrow - description: Insert tomorrow's date - value: "{{tomorrow}}" - - # Text editing commands - quoteSelectionCommand: - path: ./text.ts:quoteSelection - command: - name: "Text: Quote Selection" - key: "Ctrl-Shift-." - mac: "Cmd-Shift-." - listifySelection: - path: ./text.ts:listifySelection - command: - name: "Text: Listify Selection" - key: "Ctrl-Shift-8" - mac: "Cmd-Shift-8" - numberListifySelection: - path: ./text.ts:numberListifySelection - command: - name: "Text: Number Listify Selection" - linkSelection: - path: ./text.ts:linkSelection - command: - name: "Text: Link Selection" - key: "Ctrl-Shift-k" - mac: "Cmd-Shift-k" - bold: - path: ./text.ts:wrapSelection - command: - name: "Text: Bold" - key: "Ctrl-b" - mac: "Cmd-b" - wrapper: "**" - italic: - path: ./text.ts:wrapSelection - command: - name: "Text: Italic" - key: "Ctrl-i" - mac: "Cmd-i" - wrapper: "_" - strikethrough: - path: ./text.ts:wrapSelection - command: - name: "Text: Strikethrough" - key: "Ctrl-Shift-s" - mac: "Cmd-Shift-s" - wrapper: "~~" - marker: - path: ./text.ts:wrapSelection - command: - name: "Text: Marker" - key: "Alt-m" - wrapper: "==" - - # Refactoring Commands - extractToPageCommand: - path: ./refactor.ts:extractToPageCommand - command: - name: "Page: Extract" - renamePageCommand: - path: "./refactor.ts:renamePageCommand" - command: - name: "Page: Rename" - mac: Cmd-Alt-r - key: Ctrl-Alt-r - page: "" - renamePrefixCommand: - path: "./refactor.ts:renamePrefixCommand" - command: - name: "Page: Batch Rename Prefix" - - # Plug manager - updatePlugsCommand: - path: ./plugmanager.ts:updatePlugsCommand - command: - name: "Plugs: Update" - key: "Ctrl-Shift-p" - mac: "Cmd-Shift-p" - getPlugHTTPS: - path: "./plugmanager.ts:getPlugHTTPS" - events: - - get-plug:https - getPlugGithub: - path: "./plugmanager.ts:getPlugGithub" - events: - - get-plug:github - getPlugGithubRelease: - path: "./plugmanager.ts:getPlugGithubRelease" - events: - - get-plug:ghr - addPlugCommand: - path: ./plugmanager.ts:addPlugCommand - command: - name: "Plugs: Add" - - # Debug commands - parseCommand: - path: ./debug.ts:parsePageCommand - command: - name: "Debug: Parse Document" - - reloadUICommand: - path: ./debug.ts:reloadUICommand - command: - name: "Debug: Reload UI" - - resetClientCommand: - path: ./debug.ts:resetClientCommand - command: - name: "Debug: Reset Client" - - versionCommand: - path: ./help.ts:versionCommand - command: - name: "Help: Version" - gettingStartedCommand: - path: ./help.ts:gettingStartedCommand - command: - name: "Help: Getting Started" - - accountLogoutCommand: - path: ./account.ts:accountLogoutCommand - command: - name: "Account: Logout" - - # Link unfurl infrastructure - unfurlLink: - path: ./link.ts:unfurlCommand - command: - name: "Link: Unfurl" - key: "Ctrl-Shift-u" - mac: "Cmd-Shift-u" - contexts: - - NakedURL - - # Title-based link unfurl - titleUnfurlOptions: - path: ./link.ts:titleUnfurlOptions - events: - - unfurl:options - titleUnfurl: - path: ./link.ts:titleUnfurl - events: - - unfurl:title-unfurl - - embedWidget: - path: ./embed.ts:embedWidget - codeWidget: embed - - # Folding commands - foldCommand: - path: ./editor.ts:foldCommand - command: - name: "Fold: Fold" - mac: "Cmd-Alt-[" - key: "Ctrl-Shift-[" - unfoldCommand: - path: ./editor.ts:unfoldCommand - command: - name: "Fold: Unfold" - mac: "Cmd-Alt-]" - key: "Ctrl-Shift-]" - toggleFoldCommand: - path: ./editor.ts:toggleFoldCommand - command: - name: "Fold: Toggle Fold" - mac: "Cmd-Alt-f" - key: "Ctrl-Alt-f" - foldAllCommand: - path: ./editor.ts:foldAllCommand - command: - name: "Fold: Fold All" - key: "Ctrl-Alt-[" - unfoldAllCommand: - path: ./editor.ts:unfoldAllCommand - command: - name: "Fold: Unfold All" - key: "Ctrl-Alt-]" - - # Random stuff - statsCommand: - path: ./stats.ts:statsCommand - command: - name: "Stats: Show" - - # Cloud pages - readPageCloud: - path: ./cloud.ts:readFileCloud - pageNamespace: - pattern: "💭 .+" - operation: readFile - writePageCloud: - path: ./cloud.ts:writeFileCloud - pageNamespace: - pattern: "💭 .+" - operation: writeFile - getPageMetaCloud: - path: ./cloud.ts:getFileMetaCloud - pageNamespace: - pattern: "💭 .+" - operation: getFileMeta - - # Vim - toggleVimMode: - path: "./vim.ts:toggleVimMode" - command: - name: "Editor: Toggle Vim Mode" - loadVimRc: - path: "./vim.ts:loadVimRc" - command: - name: "Editor: Vim: Load VIMRC" - events: - - editor:modeswitch - - brokenLinksCommand: - path: ./broken_links.ts:brokenLinksCommand - command: - name: "Broken Links: Show" diff --git a/plugs/directive/command.ts b/plugs/directive/command.ts index 3ea444c..f2c1f37 100644 --- a/plugs/directive/command.ts +++ b/plugs/directive/command.ts @@ -1,4 +1,4 @@ -import { editor, markdown, space, sync } from "$sb/silverbullet-syscall/mod.ts"; +import { editor, markdown, mq, space, sync } from "$sb/syscalls.ts"; import { ParseTree, removeParentPointers, @@ -7,10 +7,9 @@ import { } from "$sb/lib/tree.ts"; import { renderDirectives } from "./directives.ts"; import { extractFrontmatter } from "$sb/lib/frontmatter.ts"; -import { PageMeta } from "../../web/types.ts"; +import type { PageMeta } from "../../web/types.ts"; import { isFederationPath } from "$sb/lib/resolve.ts"; -import { mq } from "$sb/plugos-syscall/mod.ts"; -import { Message } from "$sb/types.ts"; +import { MQMessage } from "$sb/types.ts"; import { sleep } from "../../common/async_util.ts"; const directiveUpdateQueueName = "directiveUpdateQueue"; @@ -92,7 +91,7 @@ export async function updateDirectivesInSpaceCommand() { await editor.flashNotification("Updating of all directives completed!"); } -export async function processUpdateQueue(messages: Message[]) { +export async function processUpdateQueue(messages: MQMessage[]) { for (const message of messages) { const pageName: string = message.body; console.log("Updating directives in page", pageName); diff --git a/plugs/directive/complete.ts b/plugs/directive/complete.ts index 10a43a5..fa9076e 100644 --- a/plugs/directive/complete.ts +++ b/plugs/directive/complete.ts @@ -1,11 +1,11 @@ -import { events } from "$sb/plugos-syscall/mod.ts"; +import { events } from "$sb/syscalls.ts"; import { CompleteEvent } from "$sb/app_event.ts"; import { buildHandebarOptions } from "./util.ts"; import type { PageMeta } from "../../web/types.ts"; -import { +import type { AttributeCompleteEvent, AttributeCompletion, -} from "../core/attributes.ts"; +} from "../index/attributes.ts"; export async function queryComplete(completeEvent: CompleteEvent) { const querySourceMatch = /#query\s+([\w\-_]*)$/.exec( diff --git a/plugs/directive/data.ts b/plugs/directive/data.ts index c42b307..456912c 100644 --- a/plugs/directive/data.ts +++ b/plugs/directive/data.ts @@ -2,10 +2,9 @@ // data:page@pos import type { IndexTreeEvent, QueryProviderEvent } from "$sb/app_event.ts"; -import { index } from "$sb/silverbullet-syscall/mod.ts"; +import { index, YAML } from "$sb/syscalls.ts"; import { collectNodesOfType, findNodeOfType } from "$sb/lib/tree.ts"; import { applyQuery, removeQueries } from "$sb/lib/query.ts"; -import { YAML } from "$sb/plugos-syscall/mod.ts"; export async function indexData({ name, tree }: IndexTreeEvent) { const dataObjects: { key: string; value: any }[] = []; diff --git a/plugs/directive/directive.plug.yaml b/plugs/directive/directive.plug.yaml index a2ff9ae..a54271a 100644 --- a/plugs/directive/directive.plug.yaml +++ b/plugs/directive/directive.plug.yaml @@ -39,7 +39,7 @@ functions: # Templates insertQuery: - redirect: core.insertTemplateText + redirect: template.insertTemplateText slashCommand: name: query description: Insert a query @@ -48,7 +48,7 @@ functions: insertInclude: - redirect: core.insertTemplateText + redirect: template.insertTemplateText slashCommand: name: include description: Include another page @@ -57,7 +57,7 @@ functions: insertUseTemplate: - redirect: core.insertTemplateText + redirect: template.insertTemplateText slashCommand: name: use description: Use a template @@ -66,7 +66,7 @@ functions: insertUseVerboseTemplate: - redirect: core.insertTemplateText + redirect: template.insertTemplateText slashCommand: name: use-verbose description: Use a template (verbose mode) @@ -75,7 +75,7 @@ functions: insertEvalTemplate: - redirect: core.insertTemplateText + redirect: template.insertTemplateText slashCommand: name: eval description: Evaluate a JavaScript expression diff --git a/plugs/directive/eval_directive.ts b/plugs/directive/eval_directive.ts index 8a60753..63e0075 100644 --- a/plugs/directive/eval_directive.ts +++ b/plugs/directive/eval_directive.ts @@ -1,10 +1,10 @@ // This is some shocking stuff. My profession would kill me for this. -import { YAML } from "$sb/plugos-syscall/mod.ts"; +import { YAML } from "$sb/syscalls.ts"; import { ParseTree } from "$sb/lib/tree.ts"; import { jsonToMDTable, renderTemplate } from "./util.ts"; -import { PageMeta } from "../../web/types.ts"; -import { replaceTemplateVars } from "../core/template.ts"; +import type { PageMeta } from "../../web/types.ts"; +import { replaceTemplateVars } from "../template/template.ts"; // Enables plugName.functionName(arg1, arg2) syntax in JS expressions function translateJs(js: string): string { @@ -44,7 +44,7 @@ export async function evalDirectiveRenderer( const result = await (0, eval)( `(async () => { function invokeFunction(name, ...args) { - return syscall("system.invoke", name, ...args); + return syscall("system.invokeFunction", name, ...args); } return ${replaceTemplateVars(translateJs(expression), pageMeta)}; })()`, diff --git a/plugs/directive/query_directive.ts b/plugs/directive/query_directive.ts index a41b727..1c4c2f8 100644 --- a/plugs/directive/query_directive.ts +++ b/plugs/directive/query_directive.ts @@ -1,11 +1,11 @@ -import { events } from "$sb/plugos-syscall/mod.ts"; +import { events } from "$sb/syscalls.ts"; -import { replaceTemplateVars } from "../core/template.ts"; +import { replaceTemplateVars } from "../template/template.ts"; import { renderTemplate } from "./util.ts"; import { parseQuery } from "./parser.ts"; import { jsonToMDTable } from "./util.ts"; import { ParseTree } from "$sb/lib/tree.ts"; -import { PageMeta } from "../../web/types.ts"; +import type { PageMeta } from "../../web/types.ts"; export async function queryDirectiveRenderer( _directive: string, diff --git a/plugs/directive/template_directive.ts b/plugs/directive/template_directive.ts index 37dc826..74ca6f7 100644 --- a/plugs/directive/template_directive.ts +++ b/plugs/directive/template_directive.ts @@ -1,14 +1,9 @@ import { queryRegex } from "$sb/lib/query.ts"; -import { - findNodeOfType, - ParseTree, - renderToText, - traverseTree, -} from "$sb/lib/tree.ts"; -import { markdown, space } from "$sb/silverbullet-syscall/mod.ts"; +import { ParseTree, renderToText } from "$sb/lib/tree.ts"; +import { markdown, space } from "$sb/syscalls.ts"; import Handlebars from "handlebars"; -import { replaceTemplateVars } from "../core/template.ts"; +import { replaceTemplateVars } from "../template/template.ts"; import { extractFrontmatter } from "$sb/lib/frontmatter.ts"; import { directiveRegex } from "./directives.ts"; import { updateDirectives } from "./command.ts"; diff --git a/plugs/directive/util.ts b/plugs/directive/util.ts index 8c51dd9..6ecfa51 100644 --- a/plugs/directive/util.ts +++ b/plugs/directive/util.ts @@ -1,7 +1,7 @@ import Handlebars from "handlebars"; -import { space } from "$sb/silverbullet-syscall/mod.ts"; -import { PageMeta } from "../../web/types.ts"; +import { space } from "$sb/syscalls.ts"; +import type { PageMeta } from "../../web/types.ts"; import { handlebarHelpers } from "./handlebar_helpers.ts"; const maxWidth = 70; diff --git a/plugs/core/account.ts b/plugs/editor/account.ts similarity index 64% rename from plugs/core/account.ts rename to plugs/editor/account.ts index bef45eb..4616c01 100644 --- a/plugs/core/account.ts +++ b/plugs/editor/account.ts @@ -1,4 +1,4 @@ -import { editor } from "$sb/silverbullet-syscall/mod.ts"; +import { editor } from "$sb/syscalls.ts"; export async function accountLogoutCommand() { await editor.openUrl("/.client/logout.html", true); diff --git a/plugs/core/broken_links.ts b/plugs/editor/broken_links.ts similarity index 95% rename from plugs/core/broken_links.ts rename to plugs/editor/broken_links.ts index f926b6e..0102fb9 100644 --- a/plugs/core/broken_links.ts +++ b/plugs/editor/broken_links.ts @@ -1,9 +1,5 @@ import { traverseTree } from "../../plug-api/lib/tree.ts"; -import { - editor, - markdown, - space, -} from "../../plug-api/silverbullet-syscall/mod.ts"; +import { editor, markdown, space } from "$sb/syscalls.ts"; export async function brokenLinksCommand() { const pageName = "BROKEN LINKS"; diff --git a/plugs/editor/client.ts b/plugs/editor/client.ts new file mode 100644 index 0000000..bda6e4a --- /dev/null +++ b/plugs/editor/client.ts @@ -0,0 +1,7 @@ +import { editor } from "$sb/syscalls.ts"; + +export async function setThinClient(def: any) { + console.log("Setting thin client to", def.value); + await editor.setUiOption("thinClientMode", def.value); + await editor.reloadUI(); +} diff --git a/plugs/core/command.ts b/plugs/editor/command.ts similarity index 77% rename from plugs/core/command.ts rename to plugs/editor/command.ts index e7be471..846b9d7 100644 --- a/plugs/core/command.ts +++ b/plugs/editor/command.ts @@ -1,5 +1,5 @@ -import { system } from "$sb/silverbullet-syscall/mod.ts"; -import { CompleteEvent } from "../../plug-api/app_event.ts"; +import { system } from "$sb/syscalls.ts"; +import { CompleteEvent } from "$sb/app_event.ts"; export async function commandComplete(completeEvent: CompleteEvent) { const match = /\{\[([^\]]*)$/.exec(completeEvent.linePrefix); diff --git a/plugs/core/debug.ts b/plugs/editor/debug.ts similarity index 81% rename from plugs/core/debug.ts rename to plugs/editor/debug.ts index 5bf02e3..8366077 100644 --- a/plugs/core/debug.ts +++ b/plugs/editor/debug.ts @@ -1,4 +1,4 @@ -import { debug, editor, markdown } from "$sb/silverbullet-syscall/mod.ts"; +import { debug, editor, markdown } from "$sb/syscalls.ts"; export async function parsePageCommand() { console.log( diff --git a/plugs/editor/editor.plug.yaml b/plugs/editor/editor.plug.yaml new file mode 100644 index 0000000..9f4cd9a --- /dev/null +++ b/plugs/editor/editor.plug.yaml @@ -0,0 +1,240 @@ +name: editor +requiredPermissions: + - fetch +syntax: + NakedURL: + firstCharacters: + - "h" + regex: "https?:\\/\\/[-a-zA-Z0-9@:%._\\+~#=]{1,256}([-a-zA-Z0-9()@:%_\\+.~#?&=\\/]*)" + className: sb-naked-url +functions: + setEditorMode: + path: "./editor.ts:setEditorMode" + events: + - editor:init + toggleDarkMode: + path: "./editor.ts:toggleDarkMode" + command: + name: "Editor: Toggle Dark Mode" + + # Page operations + deletePage: + path: "./page.ts:deletePage" + command: + name: "Page: Delete" + copyPage: + path: "./page.ts:copyPage" + command: + name: "Page: Copy" + newPage: + path: ./page.ts:newPageCommand + command: + name: "Page: New" + key: "Alt-Shift-n" + + # Completion + pageComplete: + path: "./page.ts:pageComplete" + events: + - editor:complete + commandComplete: + path: "./command.ts:commandComplete" + events: + - editor:complete + + # Navigation + linkNavigate: + path: "./navigate.ts:linkNavigate" + command: + name: Navigate To page + key: Ctrl-Enter + mac: Cmd-Enter + clickNavigate: + path: "./navigate.ts:clickNavigate" + events: + - page:click + navigateHome: + path: "./navigate.ts:navigateCommand" + command: + name: "Navigate: Home" + key: "Alt-h" + page: "" + + # Text editing commands + quoteSelectionCommand: + path: ./text.ts:quoteSelection + command: + name: "Text: Quote Selection" + key: "Ctrl-Shift-." + mac: "Cmd-Shift-." + listifySelection: + path: ./text.ts:listifySelection + command: + name: "Text: Listify Selection" + key: "Ctrl-Shift-8" + mac: "Cmd-Shift-8" + numberListifySelection: + path: ./text.ts:numberListifySelection + command: + name: "Text: Number Listify Selection" + linkSelection: + path: ./text.ts:linkSelection + command: + name: "Text: Link Selection" + key: "Ctrl-Shift-k" + mac: "Cmd-Shift-k" + bold: + path: ./text.ts:wrapSelection + command: + name: "Text: Bold" + key: "Ctrl-b" + mac: "Cmd-b" + wrapper: "**" + italic: + path: ./text.ts:wrapSelection + command: + name: "Text: Italic" + key: "Ctrl-i" + mac: "Cmd-i" + wrapper: "_" + strikethrough: + path: ./text.ts:wrapSelection + command: + name: "Text: Strikethrough" + key: "Ctrl-Shift-s" + mac: "Cmd-Shift-s" + wrapper: "~~" + marker: + path: ./text.ts:wrapSelection + command: + name: "Text: Marker" + key: "Alt-m" + wrapper: "==" + centerCursor: + path: "./editor.ts:centerCursorCommand" + command: + name: "Editor: Center Cursor" + key: "Ctrl-Alt-l" + moveToPos: + path: "./editor.ts:moveToPosCommand" + command: + name: "Editor: Move Cursor to Position" + + # Debug commands + parseCommand: + path: ./debug.ts:parsePageCommand + command: + name: "Debug: Parse Document" + + # Link unfurl infrastructure + unfurlLink: + path: ./link.ts:unfurlCommand + command: + name: "Link: Unfurl" + key: "Ctrl-Shift-u" + mac: "Cmd-Shift-u" + contexts: + - NakedURL + + # Title-based link unfurl + titleUnfurlOptions: + path: ./link.ts:titleUnfurlOptions + events: + - unfurl:options + titleUnfurl: + path: ./link.ts:titleUnfurl + events: + - unfurl:title-unfurl + + embedWidget: + path: ./embed.ts:embedWidget + codeWidget: embed + + # Folding commands + foldCommand: + path: ./editor.ts:foldCommand + command: + name: "Fold: Fold" + mac: "Cmd-Alt-[" + key: "Ctrl-Shift-[" + unfoldCommand: + path: ./editor.ts:unfoldCommand + command: + name: "Fold: Unfold" + mac: "Cmd-Alt-]" + key: "Ctrl-Shift-]" + toggleFoldCommand: + path: ./editor.ts:toggleFoldCommand + command: + name: "Fold: Toggle Fold" + mac: "Cmd-Alt-f" + key: "Ctrl-Alt-f" + foldAllCommand: + path: ./editor.ts:foldAllCommand + command: + name: "Fold: Fold All" + key: "Ctrl-Alt-[" + unfoldAllCommand: + path: ./editor.ts:unfoldAllCommand + command: + name: "Fold: Unfold All" + key: "Ctrl-Alt-]" + + # Vim + toggleVimMode: + path: "./vim.ts:toggleVimMode" + command: + name: "Editor: Toggle Vim Mode" + loadVimRc: + path: "./vim.ts:loadVimRc" + command: + name: "Editor: Vim: Load VIMRC" + events: + - editor:modeswitch + + brokenLinksCommand: + path: ./broken_links.ts:brokenLinksCommand + command: + name: "Broken Links: Show" + + # Client mode + enableThinClient: + path: ./client.ts:setThinClient + command: + name: "Client: Enable Thin Client" + value: true + disableThinClient: + path: ./client.ts:setThinClient + command: + name: "Client: Disable Thin Client" + value: false + + # Random stuff + statsCommand: + path: ./stats.ts:statsCommand + command: + name: "Stats: Show" + reloadUICommand: + path: ./debug.ts:reloadUICommand + command: + name: "Debug: Reload UI" + + resetClientCommand: + path: ./debug.ts:resetClientCommand + command: + name: "Debug: Reset Client" + + versionCommand: + path: ./help.ts:versionCommand + command: + name: "Help: Version" + gettingStartedCommand: + path: ./help.ts:gettingStartedCommand + command: + name: "Help: Getting Started" + + accountLogoutCommand: + path: ./account.ts:accountLogoutCommand + command: + name: "Account: Logout" + diff --git a/plugs/core/editor.ts b/plugs/editor/editor.ts similarity index 94% rename from plugs/core/editor.ts rename to plugs/editor/editor.ts index 865a2e1..9ec3c74 100644 --- a/plugs/core/editor.ts +++ b/plugs/editor/editor.ts @@ -1,4 +1,4 @@ -import { clientStore, editor } from "$sb/silverbullet-syscall/mod.ts"; +import { clientStore, editor } from "$sb/syscalls.ts"; // Run on "editor:init" export async function setEditorMode() { diff --git a/plugs/core/embed.ts b/plugs/editor/embed.ts similarity index 95% rename from plugs/core/embed.ts rename to plugs/editor/embed.ts index cc4fab6..9021c1c 100644 --- a/plugs/core/embed.ts +++ b/plugs/editor/embed.ts @@ -1,4 +1,4 @@ -import { YAML } from "$sb/plugos-syscall/mod.ts"; +import { YAML } from "$sb/syscalls.ts"; import type { WidgetContent } from "$sb/app_event.ts"; type EmbedConfig = { diff --git a/plugs/core/help.ts b/plugs/editor/help.ts similarity index 83% rename from plugs/core/help.ts rename to plugs/editor/help.ts index d2ae12d..1270734 100644 --- a/plugs/core/help.ts +++ b/plugs/editor/help.ts @@ -1,4 +1,4 @@ -import { editor } from "$sb/silverbullet-syscall/mod.ts"; +import { editor } from "$sb/syscalls.ts"; import { version } from "../../version.ts"; export async function versionCommand() { diff --git a/plugs/core/link.ts b/plugs/editor/link.ts similarity index 93% rename from plugs/core/link.ts rename to plugs/editor/link.ts index 0276e7e..b3844e1 100644 --- a/plugs/core/link.ts +++ b/plugs/editor/link.ts @@ -1,6 +1,5 @@ import { nodeAtPos } from "$sb/lib/tree.ts"; -import { editor, markdown } from "$sb/silverbullet-syscall/mod.ts"; -import { events } from "$sb/plugos-syscall/mod.ts"; +import { editor, events, markdown } from "$sb/syscalls.ts"; type UnfurlOption = { id: string; diff --git a/plugs/core/navigate.ts b/plugs/editor/navigate.ts similarity index 97% rename from plugs/core/navigate.ts rename to plugs/editor/navigate.ts index 53e1a93..19ec9e5 100644 --- a/plugs/core/navigate.ts +++ b/plugs/editor/navigate.ts @@ -1,5 +1,5 @@ import type { ClickEvent } from "$sb/app_event.ts"; -import { editor, markdown, system } from "$sb/silverbullet-syscall/mod.ts"; +import { editor, markdown, system } from "$sb/syscalls.ts"; import { addParentPointers, findNodeOfType, diff --git a/plugs/core/page.ts b/plugs/editor/page.ts similarity index 54% rename from plugs/core/page.ts rename to plugs/editor/page.ts index 44d75ab..25eeb69 100644 --- a/plugs/core/page.ts +++ b/plugs/editor/page.ts @@ -1,33 +1,9 @@ -import type { - CompleteEvent, - IndexEvent, - QueryProviderEvent, -} from "$sb/app_event.ts"; -import { - editor, - index, - markdown, - space, -} from "$sb/silverbullet-syscall/mod.ts"; +import type { CompleteEvent } from "$sb/app_event.ts"; +import { editor, space } from "$sb/syscalls.ts"; -import { events, mq } from "$sb/plugos-syscall/mod.ts"; - -import { applyQuery } from "$sb/lib/query.ts"; -import { invoke } from "$sb/silverbullet-syscall/system.ts"; -import type { Message } from "$sb/types.ts"; -import { sleep } from "../../common/async_util.ts"; import { cacheFileListing } from "../federation/federation.ts"; import type { PageMeta } from "../../web/types.ts"; -// Key space: -// meta: => metaJson - -export async function pageQueryProvider({ - query, -}: QueryProviderEvent): Promise { - return applyQuery(query, await space.listPages()); -} - export async function deletePage() { const pageName = await editor.getCurrentPage(); if ( @@ -85,12 +61,6 @@ export async function newPageCommand() { await editor.navigate(pageName); } -export async function reindexCommand() { - await editor.flashNotification("Performing full page reindex..."); - await reindexSpace(); - await editor.flashNotification("Done with page index!"); -} - // Completion export async function pageComplete(completeEvent: CompleteEvent) { const match = /\[\[([^\]@:\{}]*)$/.exec(completeEvent.linePrefix); @@ -130,51 +100,3 @@ export async function pageComplete(completeEvent: CompleteEvent) { }), }; } - -export async function reindexSpace() { - console.log("Clearing page index..."); - await index.clearPageIndex(); - // Executed this way to not have to embed the search plug code here - await invoke("search.clearIndex"); - const pages = await space.listPages(); - - // Queue all page names to be indexed - await mq.batchSend("indexQueue", pages.map((page) => page.name)); - - // Now let's wait for the processing to finish - let queueStats = await mq.getQueueStats("indexQueue"); - while (queueStats.queued > 0 || queueStats.processing > 0) { - sleep(1000); - queueStats = await mq.getQueueStats("indexQueue"); - } - // And notify the user - console.log("Indexing completed!"); -} - -export async function processIndexQueue(messages: Message[]) { - for (const message of messages) { - const name: string = message.body; - console.log(`Indexing page ${name}`); - const text = await space.readPage(name); - // console.log("Going to parse markdown"); - const parsed = await markdown.parseMarkdown(text); - // console.log("Dispatching ;age:index"); - await events.dispatchEvent("page:index", { - name, - tree: parsed, - }); - } -} - -export async function clearPageIndex(page: string) { - // console.log("Clearing page index for page", page); - await index.clearPageIndexForPage(page); -} - -export async function parseIndexTextRepublish({ name, text }: IndexEvent) { - console.log("Reindexing", name); - await events.dispatchEvent("page:index", { - name, - tree: await markdown.parseMarkdown(text), - }); -} diff --git a/plugs/core/stats.ts b/plugs/editor/stats.ts similarity index 90% rename from plugs/core/stats.ts rename to plugs/editor/stats.ts index 27307a2..3e961b1 100644 --- a/plugs/core/stats.ts +++ b/plugs/editor/stats.ts @@ -1,4 +1,4 @@ -import { editor, space } from "$sb/silverbullet-syscall/mod.ts"; +import { editor, space } from "$sb/syscalls.ts"; function countWords(str: string): number { const matches = str.match(/[\w\d\'-]+/gi); diff --git a/plugs/core/text.ts b/plugs/editor/text.ts similarity index 98% rename from plugs/core/text.ts rename to plugs/editor/text.ts index 7570bac..3312535 100644 --- a/plugs/core/text.ts +++ b/plugs/editor/text.ts @@ -1,4 +1,4 @@ -import { editor } from "$sb/silverbullet-syscall/mod.ts"; +import { editor } from "$sb/syscalls.ts"; export async function quoteSelection() { let text = await editor.getText(); diff --git a/plugs/core/vim.ts b/plugs/editor/vim.ts similarity index 82% rename from plugs/core/vim.ts rename to plugs/editor/vim.ts index 4064647..50fa75b 100644 --- a/plugs/core/vim.ts +++ b/plugs/editor/vim.ts @@ -1,6 +1,5 @@ -import { readCodeBlockPage } from "../../plug-api/lib/yaml_page.ts"; -import { editor } from "$sb/silverbullet-syscall/mod.ts"; -import { store } from "$sb/plugos-syscall/mod.ts"; +import { readCodeBlockPage } from "$sb/lib/yaml_page.ts"; +import { editor, store } from "$sb/syscalls.ts"; export async function toggleVimMode() { let vimMode = await store.get("vimMode"); diff --git a/plugs/emoji/emoji.ts b/plugs/emoji/emoji.ts index cf1622d..775b9a4 100644 --- a/plugs/emoji/emoji.ts +++ b/plugs/emoji/emoji.ts @@ -1,5 +1,5 @@ import emojis from "./emoji.json" assert { type: "json" }; -import type { CompleteEvent } from "../../plug-api/app_event.ts"; +import type { CompleteEvent } from "$sb/app_event.ts"; export function emojiCompleter({ linePrefix, pos }: CompleteEvent) { const match = /:([\w]+)$/.exec(linePrefix); diff --git a/plugs/federation/federation.ts b/plugs/federation/federation.ts index 1da15ef..59d9c8e 100644 --- a/plugs/federation/federation.ts +++ b/plugs/federation/federation.ts @@ -1,8 +1,8 @@ import "$sb/lib/fetch.ts"; import { federatedPathToUrl } from "$sb/lib/resolve.ts"; import { readFederationConfigs } from "./config.ts"; -import { store } from "$sb/plugos-syscall/mod.ts"; -import { FileMeta } from "$sb/types.ts"; +import { store } from "$sb/syscalls.ts"; +import type { FileMeta } from "$sb/types.ts"; async function responseToFileMeta( r: Response, diff --git a/plugs/core/anchor.ts b/plugs/index/anchor.ts similarity index 95% rename from plugs/core/anchor.ts rename to plugs/index/anchor.ts index 05879c1..a47bf8c 100644 --- a/plugs/core/anchor.ts +++ b/plugs/index/anchor.ts @@ -1,5 +1,5 @@ import { collectNodesOfType } from "$sb/lib/tree.ts"; -import { index } from "$sb/silverbullet-syscall/mod.ts"; +import { index } from "$sb/syscalls.ts"; import type { CompleteEvent, IndexTreeEvent } from "$sb/app_event.ts"; import { removeQueries } from "$sb/lib/query.ts"; diff --git a/plugs/core/attachment.ts b/plugs/index/attachment.ts similarity index 81% rename from plugs/core/attachment.ts rename to plugs/index/attachment.ts index d1285f8..2568672 100644 --- a/plugs/core/attachment.ts +++ b/plugs/index/attachment.ts @@ -1,6 +1,6 @@ import { QueryProviderEvent } from "$sb/app_event.ts"; import { applyQuery } from "$sb/lib/query.ts"; -import { space } from "$sb/silverbullet-syscall/mod.ts"; +import { space } from "$sb/syscalls.ts"; export async function attachmentQueryProvider({ query }: QueryProviderEvent) { return applyQuery(query, await space.listAttachments()); diff --git a/plugs/core/attributes.ts b/plugs/index/attributes.ts similarity index 98% rename from plugs/core/attributes.ts rename to plugs/index/attributes.ts index c64fe9f..7bea7c0 100644 --- a/plugs/core/attributes.ts +++ b/plugs/index/attributes.ts @@ -1,6 +1,6 @@ import { index } from "$sb/silverbullet-syscall/mod.ts"; import type { CompleteEvent } from "$sb/app_event.ts"; -import { events } from "$sb/plugos-syscall/mod.ts"; +import { events } from "$sb/syscalls.ts"; export type AttributeContext = "page" | "item" | "task"; diff --git a/plugs/index/index.plug.yaml b/plugs/index/index.plug.yaml new file mode 100644 index 0000000..a8c8e74 --- /dev/null +++ b/plugs/index/index.plug.yaml @@ -0,0 +1,133 @@ +name: index +syntax: + Hashtag: + firstCharacters: + - "#" + regex: "#[^#\\d\\s\\[\\]]+\\w+" + className: sb-hashtag + NamedAnchor: + firstCharacters: + - "$" + regex: "\\$[a-zA-Z\\.\\-\\/]+[\\w\\.\\-\\/]*" + className: sb-named-anchor +functions: + clearPageIndex: + path: "./page.ts:clearPageIndex" + env: server + events: + - page:saved + - page:deleted + pageQueryProvider: + path: ./page.ts:pageQueryProvider + events: + - query:page + parseIndexTextRepublish: + path: "./page.ts:parseIndexTextRepublish" + env: server + events: + - page:index_text + reindexSpaceCommand: + path: "./page.ts:reindexCommand" + command: + name: "Space: Reindex" + processIndexQueue: + path: ./page.ts:processIndexQueue + mqSubscriptions: + - queue: indexQueue + batchSize: 10 + autoAck: true + reindexSpace: + path: "./page.ts:reindexSpace" + + # Attachments + attachmentQueryProvider: + path: ./attachment.ts:attachmentQueryProvider + events: + - query:attachment + + # Backlinks + indexLinks: + path: "./page_links.ts:indexLinks" + events: + - page:index + linkQueryProvider: + path: ./page_links.ts:linkQueryProvider + events: + - query:link + + attributeComplete: + path: "./attributes.ts:attributeComplete" + events: + - editor:complete + + customAttributeCompleter: + path: ./attributes.ts:customAttributeCompleter + events: + - attribute:complete:page + - attribute:complete:task + - attribute:complete:item + - attribute:complete:* + + builtinAttributeCompleter: + path: ./attributes.ts:builtinAttributeCompleter + events: + - attribute:complete:page + - attribute:complete:task + - attribute:complete:item + - attribute:complete:* + + # Item indexing + indexItem: + path: "./item.ts:indexItems" + events: + - page:index + itemQueryProvider: + path: "./item.ts:queryProvider" + events: + - query:item + + # Anchors + indexAnchors: + path: "./anchor.ts:indexAnchors" + events: + - page:index + anchorComplete: + path: "./anchor.ts:anchorComplete" + events: + - editor:complete + + + + # Hashtags + indexTags: + path: "./tags.ts:indexTags" + events: + - page:index + tagComplete: + path: "./tags.ts:tagComplete" + events: + - editor:complete + tagProvider: + path: "./tags.ts:tagProvider" + events: + - query:tag + + renamePageCommand: + path: "./refactor.ts:renamePageCommand" + command: + name: "Page: Rename" + mac: Cmd-Alt-r + key: Ctrl-Alt-r + page: "" + renamePrefixCommand: + path: "./refactor.ts:renamePrefixCommand" + command: + name: "Page: Batch Rename Prefix" + + # Refactoring Commands + extractToPageCommand: + path: ./refactor.ts:extractToPageCommand + command: + name: "Page: Extract" + + diff --git a/plugs/core/item.ts b/plugs/index/item.ts similarity index 97% rename from plugs/core/item.ts rename to plugs/index/item.ts index 295f686..cd47f54 100644 --- a/plugs/core/item.ts +++ b/plugs/index/item.ts @@ -1,6 +1,6 @@ import type { IndexTreeEvent, QueryProviderEvent } from "$sb/app_event.ts"; -import { index } from "$sb/silverbullet-syscall/mod.ts"; +import { index } from "$sb/syscalls.ts"; import { collectNodesOfType, ParseTree, renderToText } from "$sb/lib/tree.ts"; import { applyQuery, removeQueries } from "$sb/lib/query.ts"; import { extractAttributes } from "$sb/lib/attribute.ts"; diff --git a/plugs/index/page.ts b/plugs/index/page.ts new file mode 100644 index 0000000..4296e43 --- /dev/null +++ b/plugs/index/page.ts @@ -0,0 +1,77 @@ +import type { IndexEvent, QueryProviderEvent } from "$sb/app_event.ts"; +import { + editor, + events, + index, + markdown, + mq, + space, + system, +} from "$sb/syscalls.ts"; + +import { applyQuery } from "$sb/lib/query.ts"; +import type { MQMessage } from "$sb/types.ts"; +import { sleep } from "../../common/async_util.ts"; + +// Key space: +// meta: => metaJson + +export async function pageQueryProvider({ + query, +}: QueryProviderEvent): Promise { + return applyQuery(query, await space.listPages()); +} + +export async function reindexCommand() { + await editor.flashNotification("Performing full page reindex..."); + await reindexSpace(); + await editor.flashNotification("Done with page index!"); +} + +export async function reindexSpace() { + console.log("Clearing page index..."); + await index.clearPageIndex(); + // Executed this way to not have to embed the search plug code here + await system.invokeFunction("search.clearIndex"); + const pages = await space.listPages(); + + // Queue all page names to be indexed + await mq.batchSend("indexQueue", pages.map((page) => page.name)); + + // Now let's wait for the processing to finish + let queueStats = await mq.getQueueStats("indexQueue"); + while (queueStats.queued > 0 || queueStats.processing > 0) { + sleep(1000); + queueStats = await mq.getQueueStats("indexQueue"); + } + // And notify the user + console.log("Indexing completed!"); +} + +export async function processIndexQueue(messages: MQMessage[]) { + for (const message of messages) { + const name: string = message.body; + console.log(`Indexing page ${name}`); + const text = await space.readPage(name); + // console.log("Going to parse markdown"); + const parsed = await markdown.parseMarkdown(text); + // console.log("Dispatching ;age:index"); + await events.dispatchEvent("page:index", { + name, + tree: parsed, + }); + } +} + +export async function clearPageIndex(page: string) { + // console.log("Clearing page index for page", page); + await index.clearPageIndexForPage(page); +} + +export async function parseIndexTextRepublish({ name, text }: IndexEvent) { + console.log("Reindexing", name); + await events.dispatchEvent("page:index", { + name, + tree: await markdown.parseMarkdown(text), + }); +} diff --git a/plugs/core/page_links.ts b/plugs/index/page_links.ts similarity index 98% rename from plugs/core/page_links.ts rename to plugs/index/page_links.ts index bc3b488..a7b9c83 100644 --- a/plugs/core/page_links.ts +++ b/plugs/index/page_links.ts @@ -1,4 +1,4 @@ -import { index } from "$sb/silverbullet-syscall/mod.ts"; +import { index } from "$sb/syscalls.ts"; import { findNodeOfType, traverseTree } from "$sb/lib/tree.ts"; import { extractFrontmatter } from "$sb/lib/frontmatter.ts"; import { extractAttributes } from "$sb/lib/attribute.ts"; diff --git a/plugs/core/refactor.ts b/plugs/index/refactor.ts similarity index 98% rename from plugs/core/refactor.ts rename to plugs/index/refactor.ts index 3a0ab6a..289594d 100644 --- a/plugs/core/refactor.ts +++ b/plugs/index/refactor.ts @@ -1,4 +1,4 @@ -import { editor, space } from "$sb/silverbullet-syscall/mod.ts"; +import { editor, space } from "$sb/syscalls.ts"; import { validatePageName } from "$sb/lib/page.ts"; import { getBackLinks } from "./page_links.ts"; diff --git a/plugs/core/tags.ts b/plugs/index/tags.ts similarity index 92% rename from plugs/core/tags.ts rename to plugs/index/tags.ts index 909e171..8edb6f8 100644 --- a/plugs/core/tags.ts +++ b/plugs/index/tags.ts @@ -1,12 +1,12 @@ import { collectNodesOfType } from "$sb/lib/tree.ts"; -import { index } from "$sb/silverbullet-syscall/mod.ts"; +import { index } from "$sb/syscalls.ts"; import type { CompleteEvent, IndexTreeEvent, QueryProviderEvent, } from "$sb/app_event.ts"; import { applyQuery, removeQueries } from "$sb/lib/query.ts"; -import { extractFrontmatter } from "../../plug-api/lib/frontmatter.ts"; +import { extractFrontmatter } from "$sb/lib/frontmatter.ts"; // Key space // tag:TAG => true (for completion) diff --git a/plugs/markdown/markdown.ts b/plugs/markdown/markdown.ts index 4151ae0..5e17c61 100644 --- a/plugs/markdown/markdown.ts +++ b/plugs/markdown/markdown.ts @@ -1,7 +1,6 @@ -import { editor } from "$sb/silverbullet-syscall/mod.ts"; +import { clientStore, editor } from "$sb/syscalls.ts"; import { readSettings } from "$sb/lib/settings_page.ts"; import { updateMarkdownPreview } from "./preview.ts"; -import { clientStore } from "$sb/silverbullet-syscall/mod.ts"; export async function togglePreview() { const currentValue = !!(await clientStore.get("enableMarkdownPreview")); diff --git a/plugs/markdown/markdown_render.test.ts b/plugs/markdown/markdown_render.test.ts index 065e655..a824a5a 100644 --- a/plugs/markdown/markdown_render.test.ts +++ b/plugs/markdown/markdown_render.test.ts @@ -10,7 +10,7 @@ import { assertEquals } from "../../test_deps.ts"; Deno.test("Markdown render", async () => { const system = new System("server"); await system.load( - new URL("../../dist_plug_bundle/_plug/core.plug.js", import.meta.url), + new URL("../../dist_plug_bundle/_plug/editor.plug.js", import.meta.url), createSandbox, ); await system.load( diff --git a/plugs/markdown/preview.ts b/plugs/markdown/preview.ts index da81118..778e86b 100644 --- a/plugs/markdown/preview.ts +++ b/plugs/markdown/preview.ts @@ -1,6 +1,4 @@ -import { clientStore, editor, system } from "$sb/silverbullet-syscall/mod.ts"; -import { asset } from "$sb/plugos-syscall/mod.ts"; -import { parseMarkdown } from "$sb/silverbullet-syscall/markdown.ts"; +import { asset, clientStore, editor, markdown, system } from "$sb/syscalls.ts"; import { renderMarkdownToHtml } from "./markdown_render.ts"; import { resolvePath } from "$sb/lib/resolve.ts"; @@ -10,7 +8,7 @@ export async function updateMarkdownPreview() { } const currentPage = await editor.getCurrentPage(); const text = await editor.getText(); - const mdTree = await parseMarkdown(text); + const mdTree = await markdown.parseMarkdown(text); // const cleanMd = await cleanMarkdown(text); const css = await asset.readAsset("assets/styles.css"); const js = await asset.readAsset("assets/handler.js"); diff --git a/plugs/markdown/util.ts b/plugs/markdown/util.ts index 776ac0e..38e9450 100644 --- a/plugs/markdown/util.ts +++ b/plugs/markdown/util.ts @@ -3,7 +3,7 @@ import { renderToText, replaceNodesMatching, } from "$sb/lib/tree.ts"; -import { markdown } from "$sb/silverbullet-syscall/mod.ts"; +import { markdown } from "$sb/syscalls.ts"; export function encodePageUrl(name: string): string { return name; diff --git a/plugs/markdown/widget.ts b/plugs/markdown/widget.ts index 50ef7c8..1ebfeed 100644 --- a/plugs/markdown/widget.ts +++ b/plugs/markdown/widget.ts @@ -1,13 +1,13 @@ -import { parseMarkdown } from "$sb/silverbullet-syscall/markdown.ts"; +import { markdown } from "$sb/syscalls.ts"; import type { WidgetContent } from "$sb/app_event.ts"; import { renderMarkdownToHtml } from "./markdown_render.ts"; export async function markdownWidget( bodyText: string, ): Promise { - const mdTree = await parseMarkdown(bodyText); + const mdTree = await markdown.parseMarkdown(bodyText); - const html = await renderMarkdownToHtml(mdTree, { + const html = renderMarkdownToHtml(mdTree, { smartHardBreak: true, }); return Promise.resolve({ diff --git a/plugs/plug-manager/plug-manager.plug.yaml b/plugs/plug-manager/plug-manager.plug.yaml new file mode 100644 index 0000000..03dfb89 --- /dev/null +++ b/plugs/plug-manager/plug-manager.plug.yaml @@ -0,0 +1,26 @@ +name: plug-manager +requiredPermissions: + - fetch +functions: + updatePlugsCommand: + path: ./plugmanager.ts:updatePlugsCommand + command: + name: "Plugs: Update" + key: "Ctrl-Shift-p" + mac: "Cmd-Shift-p" + getPlugHTTPS: + path: "./plugmanager.ts:getPlugHTTPS" + events: + - get-plug:https + getPlugGithub: + path: "./plugmanager.ts:getPlugGithub" + events: + - get-plug:github + getPlugGithubRelease: + path: "./plugmanager.ts:getPlugGithubRelease" + events: + - get-plug:ghr + addPlugCommand: + path: ./plugmanager.ts:addPlugCommand + command: + name: "Plugs: Add" diff --git a/plugs/core/plugmanager.ts b/plugs/plug-manager/plugmanager.ts similarity index 97% rename from plugs/core/plugmanager.ts rename to plugs/plug-manager/plugmanager.ts index da5b021..5b9d9e6 100644 --- a/plugs/core/plugmanager.ts +++ b/plugs/plug-manager/plugmanager.ts @@ -1,5 +1,4 @@ -import { events } from "$sb/plugos-syscall/mod.ts"; -import { editor, space, system } from "$sb/silverbullet-syscall/mod.ts"; +import { editor, events, space, system } from "$sb/syscalls.ts"; import { readYamlPage } from "$sb/lib/yaml_page.ts"; import { builtinPlugNames } from "../builtin_plugs.ts"; diff --git a/plugs/search/engine.ts b/plugs/search/engine.ts index e73cae2..10fc511 100644 --- a/plugs/search/engine.ts +++ b/plugs/search/engine.ts @@ -58,7 +58,7 @@ export class SimpleSearchEngine { const uniqueStemmedWords = [...new Set(stemmedWords)]; const currentIdsArray = await this.index.get(uniqueStemmedWords); - stemmedWords.forEach((stemmedWord, i) => { + stemmedWords.forEach((stemmedWord) => { const currentIds = currentIdsArray[uniqueStemmedWords.indexOf(stemmedWord)] || []; diff --git a/plugs/search/search.plug.yaml b/plugs/search/search.plug.yaml index d70100e..bbaa25b 100644 --- a/plugs/search/search.plug.yaml +++ b/plugs/search/search.plug.yaml @@ -3,7 +3,7 @@ functions: indexPage: path: search.ts:indexPage # Only enable in client for now - env: client + # env: client events: - page:index diff --git a/plugs/search/search.ts b/plugs/search/search.ts index b488cd1..7074bed 100644 --- a/plugs/search/search.ts +++ b/plugs/search/search.ts @@ -1,8 +1,7 @@ import { IndexTreeEvent, QueryProviderEvent } from "$sb/app_event.ts"; import { renderToText } from "$sb/lib/tree.ts"; -import { store } from "$sb/plugos-syscall/mod.ts"; import { applyQuery } from "$sb/lib/query.ts"; -import { editor, index } from "$sb/silverbullet-syscall/mod.ts"; +import { editor, index, store } from "$sb/syscalls.ts"; import { BatchKVStore, SimpleSearchEngine } from "./engine.ts"; import { FileMeta } from "$sb/types.ts"; @@ -26,10 +25,10 @@ class StoreKVStore implements BatchKVStore { } } -const engine = new SimpleSearchEngine( - new StoreKVStore("fts:"), - new StoreKVStore("fts_rev:"), -); +const ftsKvStore = new StoreKVStore("fts:"); +const ftsRevKvStore = new StoreKVStore("fts_rev:"); + +const engine = new SimpleSearchEngine(ftsKvStore, ftsRevKvStore); export async function indexPage({ name, tree }: IndexTreeEvent) { const text = renderToText(tree); diff --git a/plugs/share/publish.ts b/plugs/share/publish.ts index c0ffb9a..b023fbb 100644 --- a/plugs/share/publish.ts +++ b/plugs/share/publish.ts @@ -1,5 +1,4 @@ -import { events } from "$sb/plugos-syscall/mod.ts"; -import { editor, markdown } from "$sb/silverbullet-syscall/mod.ts"; +import { editor, events, markdown } from "$sb/syscalls.ts"; import { extractFrontmatter } from "$sb/lib/frontmatter.ts"; import { PublishEvent } from "$sb/app_event.ts"; diff --git a/plugs/sync/sync.plug.yaml b/plugs/sync/sync.plug.yaml new file mode 100644 index 0000000..8e51538 --- /dev/null +++ b/plugs/sync/sync.plug.yaml @@ -0,0 +1,9 @@ +name: sync +functions: + syncSpaceCommand: + path: "./sync.ts:syncSpaceCommand" + command: + name: "Sync: Now" + key: "Alt-Shift-s" + mac: "Cmd-Shift-s" + diff --git a/plugs/core/sync.ts b/plugs/sync/sync.ts similarity index 73% rename from plugs/core/sync.ts rename to plugs/sync/sync.ts index 3984c97..f03819a 100644 --- a/plugs/core/sync.ts +++ b/plugs/sync/sync.ts @@ -1,4 +1,4 @@ -import { editor, sync } from "$sb/silverbullet-syscall/mod.ts"; +import { editor, sync } from "$sb/syscalls.ts"; export async function syncSpaceCommand() { await editor.flashNotification("Syncing space..."); diff --git a/plugs/tasks/task.ts b/plugs/tasks/task.ts index 772017c..4f21e86 100644 --- a/plugs/tasks/task.ts +++ b/plugs/tasks/task.ts @@ -4,13 +4,7 @@ import type { QueryProviderEvent, } from "$sb/app_event.ts"; -import { - editor, - index, - markdown, - space, - sync, -} from "$sb/silverbullet-syscall/mod.ts"; +import { editor, index, markdown, space, sync } from "$sb/syscalls.ts"; import { addParentPointers, @@ -26,7 +20,7 @@ import { applyQuery, removeQueries } from "$sb/lib/query.ts"; import { niceDate } from "$sb/lib/dates.ts"; import { extractAttributes } from "$sb/lib/attribute.ts"; import { rewritePageRefs } from "$sb/lib/resolve.ts"; -import { indexAttributes } from "../core/attributes.ts"; +import { indexAttributes } from "../index/attributes.ts"; export type Task = { name: string; diff --git a/plugs/tasks/tasks.plug.yaml b/plugs/tasks/tasks.plug.yaml index 778473e..e17125c 100644 --- a/plugs/tasks/tasks.plug.yaml +++ b/plugs/tasks/tasks.plug.yaml @@ -20,7 +20,7 @@ syntax: backgroundColor: "rgba(22,22,22,0.07)" functions: turnIntoTask: - redirect: core.applyLineReplace + redirect: template.applyLineReplace slashCommand: name: task description: Turn into task diff --git a/plugs/template/template.plug.yaml b/plugs/template/template.plug.yaml new file mode 100644 index 0000000..5d2c7bc --- /dev/null +++ b/plugs/template/template.plug.yaml @@ -0,0 +1,115 @@ +name: template +functions: + # Template commands + insertTemplateText: + path: "./template.ts:insertTemplateText" + applyLineReplace: + path: ./template.ts:applyLineReplace + insertFrontMatter: + redirect: insertTemplateText + slashCommand: + name: front-matter + description: Insert page front matter + value: | + --- + |^| + --- + makeH1: + redirect: applyLineReplace + slashCommand: + name: h1 + description: Turn line into h1 header + match: "^#*\\s*" + replace: "# " + makeH2: + redirect: applyLineReplace + slashCommand: + name: h2 + description: Turn line into h2 header + match: "^#*\\s*" + replace: "## " + makeH3: + redirect: applyLineReplace + slashCommand: + name: h3 + description: Turn line into h3 header + match: "^#*\\s*" + replace: "### " + makeH4: + redirect: applyLineReplace + slashCommand: + name: h4 + description: Turn line into h4 header + match: "^#*\\s*" + replace: "#### " + insertCodeBlock: + redirect: insertTemplateText + slashCommand: + name: code + description: Insert code block + value: | + ``` + |^| + ``` + + insertHRTemplate: + redirect: insertTemplateText + slashCommand: + name: hr + description: Insert a horizontal rule + value: "---" + insertTable: + redirect: insertTemplateText + slashCommand: + name: table + description: Insert a table + boost: -1 # Low boost because it's likely not very commonly used + value: | + | Header A | Header B | + |----------|----------| + | Cell A|^| | Cell B | + quickNoteCommand: + path: ./template.ts:quickNoteCommand + command: + name: "Quick Note" + key: "Alt-Shift-n" + priority: 1 + dailyNoteCommand: + path: ./template.ts:dailyNoteCommand + command: + name: "Open Daily Note" + key: "Alt-Shift-d" + weeklyNoteCommand: + path: ./template.ts:weeklyNoteCommand + command: + name: "Open Weekly Note" + key: "Alt-Shift-w" + + instantiateTemplateCommand: + path: ./template.ts:instantiateTemplateCommand + command: + name: "Template: Instantiate Page" + insertSnippet: + path: ./template.ts:insertSnippet + command: + name: "Template: Insert Snippet" + slashCommand: + name: snippet + description: Insert a snippet + applyPageTemplateCommand: + path: ./template.ts:applyPageTemplateCommand + slashCommand: + name: page-template + description: Apply a page template + insertTodayCommand: + path: "./template.ts:insertTemplateText" + slashCommand: + name: today + description: Insert today's date + value: "{{today}}" + insertTomorrowCommand: + path: "./template.ts:insertTemplateText" + slashCommand: + name: tomorrow + description: Insert tomorrow's date + value: "{{tomorrow}}" diff --git a/plugs/core/template.ts b/plugs/template/template.ts similarity index 99% rename from plugs/core/template.ts rename to plugs/template/template.ts index 6ad44e6..978a417 100644 --- a/plugs/core/template.ts +++ b/plugs/template/template.ts @@ -1,4 +1,4 @@ -import { editor, markdown, space } from "$sb/silverbullet-syscall/mod.ts"; +import { editor, markdown, space } from "$sb/syscalls.ts"; import { extractFrontmatter } from "$sb/lib/frontmatter.ts"; import { renderToText } from "$sb/lib/tree.ts"; import { niceDate } from "$sb/lib/dates.ts"; diff --git a/server/server_system.ts b/server/server_system.ts index 098bea1..edf2466 100644 --- a/server/server_system.ts +++ b/server/server_system.ts @@ -11,7 +11,6 @@ import { EndpointHook } from "../plugos/hooks/endpoint.ts"; import { EventHook } from "../plugos/hooks/event.ts"; import { MQHook } from "../plugos/hooks/mq.ts"; import { DenoKVStore } from "../plugos/lib/kv_store.deno_kv.ts"; -import { DexieMQ } from "../plugos/lib/mq.dexie.ts"; import assetSyscalls from "../plugos/syscalls/asset.ts"; import { eventSyscalls } from "../plugos/syscalls/event.ts"; import { mqSyscalls } from "../plugos/syscalls/mq.dexie.ts"; @@ -19,16 +18,16 @@ import { storeSyscalls } from "../plugos/syscalls/store.ts"; import { System } from "../plugos/system.ts"; import { Space } from "../web/space.ts"; import { debugSyscalls } from "../web/syscalls/debug.ts"; -import { pageIndexSyscalls } from "../cli/syscalls/index.ts"; +import { pageIndexSyscalls } from "./syscalls/index.ts"; import { markdownSyscalls } from "../web/syscalls/markdown.ts"; -import { spaceSyscalls } from "../cli/syscalls/space.ts"; +import { spaceSyscalls } from "./syscalls/space.ts"; import { systemSyscalls } from "../web/syscalls/system.ts"; import { yamlSyscalls } from "../web/syscalls/yaml.ts"; import { Application, path } from "./deps.ts"; import { sandboxFetchSyscalls } from "../plugos/syscalls/fetch.ts"; import { shellSyscalls } from "../plugos/syscalls/shell.deno.ts"; -import { IDBKeyRange, indexedDB } from "https://esm.sh/fake-indexeddb@4.0.2"; import { SpacePrimitives } from "../common/spaces/space_primitives.ts"; +import { DenoKvMQ } from "../plugos/lib/mq.deno_kv.ts"; const fileListInterval = 30 * 1000; // 30s @@ -38,6 +37,7 @@ export class ServerSystem { private requeueInterval?: number; kvStore?: DenoKVStore; listInterval?: number; + denoKv!: Deno.Kv; constructor( private baseSpacePrimitives: SpacePrimitives, @@ -56,19 +56,15 @@ export class ServerSystem { const cronHook = new CronHook(this.system); this.system.addHook(cronHook); - this.kvStore = new DenoKVStore(); - await this.kvStore.init(this.dbPath); + this.denoKv = await Deno.openKv(this.dbPath); + + this.kvStore = new DenoKVStore(this.denoKv); // Endpoint hook this.system.addHook(new EndpointHook(this.app, "/_/")); // Use DexieMQ for this, in memory - const mq = new DexieMQ("mq", indexedDB, IDBKeyRange); - - this.requeueInterval = setInterval(() => { - // Timeout after 5s, retries 3 times, otherwise drops the message (no DLQ) - mq.requeueTimeouts(5000, 3, true).catch(console.error); - }, 20000); // Look to requeue every 20s + const mq = new DenoKvMQ(this.denoKv); const pageIndexCalls = pageIndexSyscalls(this.kvStore); @@ -148,9 +144,7 @@ export class ServerSystem { const tempDir = await Deno.makeTempDir(); try { for (const { name } of await this.spacePrimitives.fetchFileList()) { - if ( - name.endsWith(".plug.js") // && !filePath.includes("search.plug.js") - ) { + if (name.endsWith(".plug.js")) { const plugPath = path.join(tempDir, name); await Deno.mkdir(path.dirname(plugPath), { recursive: true }); await Deno.writeFile( diff --git a/cli/syscalls/index.test.ts b/server/syscalls/index.test.ts similarity index 90% rename from cli/syscalls/index.test.ts rename to server/syscalls/index.test.ts index 8d3e7bd..e59570e 100644 --- a/cli/syscalls/index.test.ts +++ b/server/syscalls/index.test.ts @@ -4,8 +4,8 @@ import { pageIndexSyscalls } from "./index.ts"; Deno.test("Test KV index", async () => { const ctx: any = {}; - const kv = new DenoKVStore(); - await kv.init("test.db"); + const denoKv = await Deno.openKv("test.db"); + const kv = new DenoKVStore(denoKv); const calls = pageIndexSyscalls(kv); await calls["index.set"](ctx, "page", "test", "value"); assertEquals(await calls["index.get"](ctx, "page", "test"), "value"); @@ -33,5 +33,6 @@ Deno.test("Test KV index", async () => { await calls["index.clearPageIndex"](ctx); results = await calls["index.queryPrefix"](ctx, ""); assertEquals(results.length, 0); - await kv.delete(); + denoKv.close(); + await Deno.remove("test.db"); }); diff --git a/cli/syscalls/index.ts b/server/syscalls/index.ts similarity index 100% rename from cli/syscalls/index.ts rename to server/syscalls/index.ts diff --git a/cli/syscalls/space.ts b/server/syscalls/space.ts similarity index 100% rename from cli/syscalls/space.ts rename to server/syscalls/space.ts diff --git a/web/boot.ts b/web/boot.ts index c3f4cf2..438adf3 100644 --- a/web/boot.ts +++ b/web/boot.ts @@ -1,7 +1,8 @@ import { safeRun } from "../common/util.ts"; import { Client } from "./client.ts"; -const thinClientMode = window.silverBulletConfig.thinClientMode === "on"; +const thinClientMode = !!localStorage.getItem("thinClientMode"); + safeRun(async () => { console.log("Booting SilverBullet..."); diff --git a/web/client.ts b/web/client.ts index 14a57a6..40e9e79 100644 --- a/web/client.ts +++ b/web/client.ts @@ -47,7 +47,6 @@ declare global { // Injected via index.html silverBulletConfig: { spaceFolderPath: string; - thinClientMode: "on" | "off"; }; client: Client; } diff --git a/web/client_system.ts b/web/client_system.ts index b17bd6a..071bef7 100644 --- a/web/client_system.ts +++ b/web/client_system.ts @@ -35,6 +35,7 @@ import { MQHook } from "../plugos/hooks/mq.ts"; import { mqSyscalls } from "../plugos/syscalls/mq.dexie.ts"; import { indexProxySyscalls } from "./syscalls/index.proxy.ts"; import { storeProxySyscalls } from "./syscalls/store.proxy.ts"; +import { mqProxySyscalls } from "./syscalls/mq.proxy.ts"; export class ClientSystem { commandHook: CommandHook; @@ -82,7 +83,9 @@ export class ClientSystem { this.system.addHook(this.codeWidgetHook); // MQ hook - this.system.addHook(new MQHook(this.system, this.mq)); + if (!this.thinClientMode) { + this.system.addHook(new MQHook(this.system, this.mq)); + } // Command hook this.commandHook = new CommandHook(); @@ -120,17 +123,17 @@ export class ClientSystem { // console.log("New file list", files); // }); - this.eventHook.addLocalListener("file:changed", (file) => { - console.log("File changed", file); - }); + // this.eventHook.addLocalListener("file:changed", (file) => { + // console.log("File changed", file); + // }); - this.eventHook.addLocalListener("file:created", (file) => { - console.log("File created", file); - }); + // this.eventHook.addLocalListener("file:created", (file) => { + // console.log("File created", file); + // }); - this.eventHook.addLocalListener("file:deleted", (file) => { - console.log("File deleted", file); - }); + // this.eventHook.addLocalListener("file:deleted", (file) => { + // console.log("File deleted", file); + // }); this.registerSyscalls(); } @@ -154,7 +157,7 @@ export class ClientSystem { markdownSyscalls(buildMarkdown(this.mdExtensions)), assetSyscalls(this.system), yamlSyscalls(), - mqSyscalls(this.mq), + this.thinClientMode ? mqProxySyscalls(this.client) : mqSyscalls(this.mq), storeCalls, this.indexSyscalls, debugSyscalls(), diff --git a/web/editor_ui.tsx b/web/editor_ui.tsx index a088c31..1eb19a4 100644 --- a/web/editor_ui.tsx +++ b/web/editor_ui.tsx @@ -195,7 +195,7 @@ export class MainUI { return; } console.log("Now renaming page to...", newName); - await editor.system.system.loadedPlugs.get("core")!.invoke( + await editor.system.system.loadedPlugs.get("index")!.invoke( "renamePageCommand", [{ page: newName }], ); diff --git a/web/index.html b/web/index.html index 62177c7..b285793 100644 --- a/web/index.html +++ b/web/index.html @@ -34,14 +34,12 @@ }; window.silverBulletConfig = { // These {{VARIABLES}} are replaced by http_server.ts - spaceFolderPath: "{{SPACE_PATH}}", - thinClientMode: "{{THIN_CLIENT_MODE}}", + spaceFolderPath: "{{SPACE_PATH}}" }; // But in case these variables aren't replaced by the server, fall back fully static mode (no sync) if (window.silverBulletConfig.spaceFolderPath.includes("{{")) { window.silverBulletConfig = { spaceFolderPath: "", - thinClientMode: "off", }; } diff --git a/web/syscalls/editor.ts b/web/syscalls/editor.ts index f7fdd2d..bab6545 100644 --- a/web/syscalls/editor.ts +++ b/web/syscalls/editor.ts @@ -171,9 +171,20 @@ export function editorSyscalls(editor: Client): SysCallMapping { return editor.confirm(message); }, "editor.getUiOption": (_ctx, key: string): any => { + if (key === "thinClientMode") { + return !!localStorage.getItem("thinClientMode"); + } return (editor.ui.viewState.uiOptions as any)[key]; }, "editor.setUiOption": (_ctx, key: string, value: any) => { + if (key === "thinClientMode") { + if (value) { + localStorage.setItem("thinClientMode", "true"); + } else { + localStorage.removeItem("thinClientMode"); + } + return; + } editor.ui.viewDispatch({ type: "set-ui-option", key, diff --git a/web/syscalls/mq.proxy.ts b/web/syscalls/mq.proxy.ts new file mode 100644 index 0000000..9f0f996 --- /dev/null +++ b/web/syscalls/mq.proxy.ts @@ -0,0 +1,13 @@ +import { SysCallMapping } from "../../plugos/system.ts"; +import { Client } from "../client.ts"; +import { proxySyscalls } from "./util.ts"; + +export function mqProxySyscalls(client: Client): SysCallMapping { + return proxySyscalls(client, [ + "mq.send", + "mq.batchSend", + "mq.ack", + "mq.batchAck", + "mq.getQueueStats", + ]); +} diff --git a/web/syscalls/system.ts b/web/syscalls/system.ts index 8508e39..312010b 100644 --- a/web/syscalls/system.ts +++ b/web/syscalls/system.ts @@ -10,16 +10,6 @@ export function systemSyscalls( ): SysCallMapping { const api: SysCallMapping = { "system.invokeFunction": ( - ctx, - _env: string, - name: string, - ...args: any[] - ) => { - // For backwards compatibility - // TODO: Remove at some point - return api["system.invoke"](ctx, name, ...args); - }, - "system.invoke": ( ctx, name: string, ...args: any[] @@ -28,6 +18,12 @@ export function systemSyscalls( throw Error("No plug associated with context"); } + if (name === "server" || name === "client") { + // Backwards compatibility mode (previously there was an 'env' argument) + name = args[0]; + args = args.slice(1); + } + let plug: Plug | undefined = ctx.plug; if (name.indexOf(".") !== -1) { // plug name in the name @@ -44,7 +40,7 @@ export function systemSyscalls( } if (functionDef.env && system.env && functionDef.env !== system.env) { // Proxy to another environment - return proxySyscall(editor.remoteSpacePrimitives, name, args); + return proxySyscall(ctx, editor.remoteSpacePrimitives, name, args); } return plug.invoke(name, args); }, diff --git a/web/syscalls/util.ts b/web/syscalls/util.ts index ff36969..eb52ca5 100644 --- a/web/syscalls/util.ts +++ b/web/syscalls/util.ts @@ -1,19 +1,21 @@ +import { plugCompileCommand } from "../../cmd/plug_compile.ts"; import { HttpSpacePrimitives } from "../../common/spaces/http_space_primitives.ts"; -import { SysCallMapping } from "../../plugos/system.ts"; +import { SyscallContext, SysCallMapping } from "../../plugos/system.ts"; import { SyscallResponse } from "../../server/rpc.ts"; import { Client } from "../client.ts"; export function proxySyscalls(client: Client, names: string[]): SysCallMapping { const syscalls: SysCallMapping = {}; for (const name of names) { - syscalls[name] = (_ctx, ...args: any[]) => { - return proxySyscall(client.remoteSpacePrimitives, name, args); + syscalls[name] = (ctx, ...args: any[]) => { + return proxySyscall(ctx, client.remoteSpacePrimitives, name, args); }; } return syscalls; } export async function proxySyscall( + ctx: SyscallContext, httpSpacePrimitives: HttpSpacePrimitives, name: string, args: any[], @@ -23,6 +25,7 @@ export async function proxySyscall( { method: "POST", body: JSON.stringify({ + ctx: ctx.plug.name, operation: "syscall", name, args, diff --git a/website/CHANGELOG.md b/website/CHANGELOG.md index 350be91..43f5716 100644 --- a/website/CHANGELOG.md +++ b/website/CHANGELOG.md @@ -3,6 +3,12 @@ release. --- +## Next +* Another heavy behind-the-scenes refactoring release, refactoring the large “core” plug into multiple smaller ones, documentation to be updated to reflect this. +* Removed [[Cloud Links]] support in favor of [[Federation]] + +--- + ## 0.3.11 * Cookies set when using SilverBullet's built-in [[Authentication]] are now per domain + port, allowing you to run multiple instances of SB on a single host with different ports without the authentication interfering. diff --git a/website/Cloud Links.md b/website/Cloud Links.md index 60ddc09..0003f04 100644 --- a/website/Cloud Links.md +++ b/website/Cloud Links.md @@ -1,5 +1 @@ -You can access the “markdown web” through SilverBullet directly. The idea of the the markdown web (we really need a better name) is simple: the Internet is a messy place — tracking everywhere, tons of banners and other stuff — let’s bring it back to the basics. How about Markdown? - -SilverBullet supports navigating this markdown web via cloud links, they’re simply wiki links that start with “💭 “. For instance: [[💭 silverbullet.md/SilverBullet]]. When you click one of these links, SilverBullet will simply pull in its content and present it to you in read-only mode (and do some clever internal link rewriting). What it does is simply fetch the link via HTTPs and postfix the url with `.md`, so [[💭 silverbullet.md/SilverBullet]] will fetch [this page](https://silverbullet.md/Silver%20Bullet.md). You can access all of the SilverBullet website this way, for instance here’s the [[💭 silverbullet.md/CHANGELOG]]. - -To publish your own content this way, simply create an `index.md` on your host (this will be fetched as the main page), and publish all the rest of your content as `.md` files alongside it. That’s all there’s to it. \ No newline at end of file +Deprecated in favor of [[Federation]] \ No newline at end of file diff --git a/website/SETTINGS.md b/website/SETTINGS.md index 2946167..d5dd01c 100644 --- a/website/SETTINGS.md +++ b/website/SETTINGS.md @@ -33,7 +33,7 @@ spaceIgnore: | plugOverrides: core: # Matching this YAML structure: - # https://github.com/silverbulletmd/silverbullet/blob/main/plugs/core/core.plug.yaml + # https://github.com/silverbulletmd/silverbullet/blob/main/plugs/editor/editor.plug.yaml # and overriding the "key" for centering the cursor functions.centerCursor.command.key: Ctrl-Alt-p # However, it's even possible to define custom slash commands this way without building a plug (/today-header in this case): diff --git a/website/🔌 Directive.md b/website/🔌 Directive.md index 010ba3b..dd118f3 100644 --- a/website/🔌 Directive.md +++ b/website/🔌 Directive.md @@ -57,7 +57,7 @@ A simple example is multiplying numbers: However, you can also invoke arbitrary plug functions, e.g. the `titleUnfurlOptions` function in the `core` plug: - + |id |name | |------------|-------------| |title-unfurl|Extract title| @@ -65,7 +65,7 @@ However, you can also invoke arbitrary plug functions, e.g. the `titleUnfurlOpti Optionally, you can use a `render` clause to render the result as a template, similar to [[🔌 Directive/Query]]: - + id: title-unfurl name: Extract title ---