From e29352556b9ad4f1513dbce73fdb8e9c926144eb Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Wed, 7 Aug 2024 11:09:56 +0200 Subject: [PATCH] Expose syscalls in space script via globals (no more syscall calls) --- common/space_script.ts | 13 +++++++++++++ plug-api/syscall.ts | 5 ++++- website/Space Script.md | 24 +++++++----------------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/common/space_script.ts b/common/space_script.ts index 8dc4b91f..d7b0d6a5 100644 --- a/common/space_script.ts +++ b/common/space_script.ts @@ -3,6 +3,7 @@ import type { ParseTree } from "../plug-api/lib/tree.ts"; import type { ScriptObject } from "../plugs/index/script.ts"; import type { AppCommand, CommandDef } from "$lib/command.ts"; import { Intl, Temporal, toTemporalInstant } from "@js-temporal/polyfill"; +import * as syscalls from "@silverbulletmd/silverbullet/syscalls"; // @ts-ignore: Temporal polyfill Date.prototype.toTemporalInstant = toTemporalInstant; @@ -95,15 +96,23 @@ export class ScriptEnvironment { // Internal API evalScript(script: string, system: System) { try { + const syscallArgs = []; + const syscallValues = []; + for (const [tl, value] of Object.entries(syscalls)) { + syscallArgs.push(tl); + syscallValues.push(value); + } const fn = Function( "silverbullet", "syscall", + ...syscallArgs, script, ); fn.call( {}, this, (name: string, ...args: any[]) => system.syscall({}, name, args), + ...syscallValues, ); } catch (e: any) { throw new Error( @@ -113,6 +122,10 @@ export class ScriptEnvironment { } async loadFromSystem(system: System) { + // Install global syscall function on globalThis + (globalThis as any).syscall = (name: string, ...args: any[]) => + system.syscall({}, name, args); + if (!system.loadedPlugs.has("index")) { console.warn("Index plug not found, skipping loading space scripts"); return; diff --git a/plug-api/syscall.ts b/plug-api/syscall.ts index ae6aa293..0061606a 100644 --- a/plug-api/syscall.ts +++ b/plug-api/syscall.ts @@ -11,4 +11,7 @@ if (typeof self === "undefined") { }; } -export const syscall = (globalThis as any).syscall; +// Late binding syscall +export function syscall(name: string, ...args: any[]) { + return (globalThis as any).syscall(name, ...args); +} diff --git a/website/Space Script.md b/website/Space Script.md index ffe79955..5c8ff734 100644 --- a/website/Space Script.md +++ b/website/Space Script.md @@ -36,7 +36,7 @@ Depending on where code is run (client or server), a slightly different JavaScri * `silverbullet.registerCommand(def, callback)`: registers a custom command (see [[#Custom commands]]). * `silverbullet.registerEventListener`: registers an event listener (see [[#Custom event listeners]]). * `silverbullet.registerAttributeExtractor(def, callback)`: registers a custom attribute extractor. -* `syscall(name, args...)`: invoke a syscall (see [[#Syscalls]]). +* Various SilverBullet syscalls, see [[#Syscalls]] Many standard JavaScript APIs are available, such as: @@ -59,7 +59,7 @@ Even though a [[Functions#readPage(name)]] function already exist, you could imp ```space-script silverbullet.registerFunction({name: "myReadPage"}, async (name) => { - const pageContent = await syscall("space.readPage", name); + const pageContent = await space.readPage(name); return pageContent; }) ``` @@ -79,7 +79,7 @@ Here is an example of defining a custom command using space script: ```space-script silverbullet.registerCommand({name: "My First Command"}, async () => { - await syscall("editor.flashNotification", "Hello there!"); + await editor.flashNotification("Hello there!"); }); ``` @@ -123,7 +123,7 @@ silverbullet.registerEventListener({name: "task:stateChange"}, async (event) => const {from, to, newState} = event.data; if(newState !== " ") { // Now dispatch an editor change to add the completion date at the end of the task - await syscall("editor.dispatch", { + await editor.dispatch({ changes: { from: to, // insert at the end of the task insert: " ✅ " + Temporal.Now.plainDateISO().toString(), @@ -204,7 +204,7 @@ Note that indexing happens on every page save. You have to run {[Space: Reindex] ## Example Let’s say you want to use the syntax `✅ 2024-02-27` in a task to signify when that task was completed and strip it from the task name. Here’s an example: -* [x] I’ve done this ✅ 2024-02-27 +* [x] I’ve done this ✅ 2024-08-07 The following attribute extractor will accomplish this: @@ -236,16 +236,6 @@ Result: # Syscalls The primary way to interact with the SilverBullet environment is using “syscalls”. Syscalls expose SilverBullet functionality largely available both on the client and server in a safe way. -In your space script, a syscall is invoked via `syscall(name, arg1, arg2)` and usually returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) with the result. +In your space script, all syscalls are exposed via the global environment, and all return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) with the result. -Here are all available syscalls: - -```template -{{#each @module in {syscall select replace(name, /\.\w+$/, "") as name}}} -## {{@module.name}} -{{#each {syscall where @module.name = replace(name, /\.\w+$/, "")}}} -* `{{name}}` -{{/each}} - -{{/each}} -``` +[A full list of syscall are documented here](https://jsr.io/@silverbulletmd/silverbullet/doc/syscalls/~) \ No newline at end of file