Editor refactor: extract system stuff
parent
87b0e7e352
commit
b39a9b8e22
|
@ -8,9 +8,8 @@ import { renderDirectives } from "./directives.ts";
|
|||
import { extractFrontmatter } from "$sb/lib/frontmatter.ts";
|
||||
import { PageMeta } from "../../web/types.ts";
|
||||
|
||||
export async function updateDirectivesOnPageCommand(arg: any) {
|
||||
export async function updateDirectivesOnPageCommand() {
|
||||
// If `arg` is a string, it's triggered automatically via an event, not explicitly via a command
|
||||
const explicitCall = typeof arg !== "string";
|
||||
const pageMeta = await space.getPageMeta(await editor.getCurrentPage());
|
||||
const text = await editor.getText();
|
||||
const tree = await markdown.parseMarkdown(text);
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
import { PageNamespaceHook } from "../common/hooks/page_namespace.ts";
|
||||
import { Manifest, SilverBulletHooks } from "../common/manifest.ts";
|
||||
import buildMarkdown from "../common/markdown_parser/parser.ts";
|
||||
import { CronHook } from "../plugos/hooks/cron.ts";
|
||||
import { EventHook } from "../plugos/hooks/event.ts";
|
||||
import { DexieKVStore } from "../plugos/lib/kv_store.dexie.ts";
|
||||
import { createSandbox } from "../plugos/environments/webworker_sandbox.ts";
|
||||
|
||||
import assetSyscalls from "../plugos/syscalls/asset.ts";
|
||||
import { eventSyscalls } from "../plugos/syscalls/event.ts";
|
||||
import { storeSyscalls } from "../plugos/syscalls/store.dexie_browser.ts";
|
||||
import { SysCallMapping, System } from "../plugos/system.ts";
|
||||
import type { Editor } from "./editor.tsx";
|
||||
import { CodeWidgetHook } from "./hooks/code_widget.ts";
|
||||
import { CommandHook } from "./hooks/command.ts";
|
||||
import { SlashCommandHook } from "./hooks/slash_command.ts";
|
||||
import { clientStoreSyscalls } from "./syscalls/clientStore.ts";
|
||||
import { debugSyscalls } from "./syscalls/debug.ts";
|
||||
import { editorSyscalls } from "./syscalls/editor.ts";
|
||||
import { sandboxFetchSyscalls } from "./syscalls/fetch.ts";
|
||||
import { pageIndexSyscalls } from "./syscalls/index.ts";
|
||||
import { markdownSyscalls } from "./syscalls/markdown.ts";
|
||||
import { shellSyscalls } from "./syscalls/shell.ts";
|
||||
import { spaceSyscalls } from "./syscalls/space.ts";
|
||||
import { syncSyscalls } from "./syscalls/sync.ts";
|
||||
import { systemSyscalls } from "./syscalls/system.ts";
|
||||
import { yamlSyscalls } from "./syscalls/yaml.ts";
|
||||
import { Space } from "./space.ts";
|
||||
import {
|
||||
loadMarkdownExtensions,
|
||||
MDExt,
|
||||
} from "../common/markdown_parser/markdown_ext.ts";
|
||||
|
||||
export class ClientSystem {
|
||||
system: System<SilverBulletHooks> = new System("client");
|
||||
commandHook: CommandHook;
|
||||
slashCommandHook: SlashCommandHook;
|
||||
namespaceHook: PageNamespaceHook;
|
||||
indexSyscalls: SysCallMapping;
|
||||
codeWidgetHook: CodeWidgetHook;
|
||||
plugsUpdated = false;
|
||||
mdExtensions: MDExt[] = [];
|
||||
|
||||
constructor(
|
||||
private editor: Editor,
|
||||
private kvStore: DexieKVStore,
|
||||
private dbPrefix: string,
|
||||
private eventHook: EventHook,
|
||||
) {
|
||||
// Attach the page namespace hook
|
||||
const namespaceHook = new PageNamespaceHook();
|
||||
this.system.addHook(namespaceHook);
|
||||
|
||||
this.system.addHook(this.eventHook);
|
||||
|
||||
// Attach the page namespace hook
|
||||
this.namespaceHook = new PageNamespaceHook();
|
||||
this.system.addHook(namespaceHook);
|
||||
|
||||
// Cron hook
|
||||
const cronHook = new CronHook(this.system);
|
||||
this.system.addHook(cronHook);
|
||||
|
||||
this.indexSyscalls = pageIndexSyscalls(
|
||||
`${dbPrefix}_page_index`,
|
||||
globalThis.indexedDB,
|
||||
);
|
||||
|
||||
// Code widget hook
|
||||
this.codeWidgetHook = new CodeWidgetHook();
|
||||
this.system.addHook(this.codeWidgetHook);
|
||||
|
||||
// Command hook
|
||||
this.commandHook = new CommandHook();
|
||||
this.commandHook.on({
|
||||
commandsUpdated: (commandMap) => {
|
||||
this.editor.viewDispatch({
|
||||
type: "update-commands",
|
||||
commands: commandMap,
|
||||
});
|
||||
},
|
||||
});
|
||||
this.system.addHook(this.commandHook);
|
||||
|
||||
// Slash command hook
|
||||
this.slashCommandHook = new SlashCommandHook(this.editor);
|
||||
this.system.addHook(this.slashCommandHook);
|
||||
|
||||
this.eventHook.addLocalListener("plug:changed", async (fileName) => {
|
||||
console.log("Plug updated, reloading:", fileName);
|
||||
this.system.unload(fileName);
|
||||
const plug = await this.system.load(
|
||||
new URL(`/${fileName}`, location.href),
|
||||
createSandbox,
|
||||
);
|
||||
if ((plug.manifest! as Manifest).syntax) {
|
||||
// If there are syntax extensions, rebuild the markdown parser immediately
|
||||
this.updateMarkdownParser();
|
||||
}
|
||||
this.plugsUpdated = true;
|
||||
});
|
||||
this.registerSyscalls();
|
||||
}
|
||||
|
||||
registerSyscalls() {
|
||||
const storeCalls = storeSyscalls(this.kvStore);
|
||||
|
||||
// Slash command hook
|
||||
this.slashCommandHook = new SlashCommandHook(this.editor);
|
||||
this.system.addHook(this.slashCommandHook);
|
||||
|
||||
// Syscalls available to all plugs
|
||||
this.system.registerSyscalls(
|
||||
[],
|
||||
eventSyscalls(this.eventHook),
|
||||
editorSyscalls(this.editor),
|
||||
spaceSyscalls(this.editor),
|
||||
systemSyscalls(this.editor, this.system),
|
||||
markdownSyscalls(buildMarkdown(this.mdExtensions)),
|
||||
assetSyscalls(this.system),
|
||||
yamlSyscalls(),
|
||||
storeCalls,
|
||||
this.indexSyscalls,
|
||||
debugSyscalls(),
|
||||
syncSyscalls(this.editor),
|
||||
// LEGACY
|
||||
clientStoreSyscalls(storeCalls),
|
||||
);
|
||||
|
||||
// Syscalls that require some additional permissions
|
||||
this.system.registerSyscalls(
|
||||
["fetch"],
|
||||
sandboxFetchSyscalls(this.editor.remoteSpacePrimitives),
|
||||
);
|
||||
|
||||
this.system.registerSyscalls(
|
||||
["shell"],
|
||||
shellSyscalls(this.editor.remoteSpacePrimitives),
|
||||
);
|
||||
}
|
||||
|
||||
async reloadPlugsFromSpace(space: Space) {
|
||||
console.log("Loading plugs");
|
||||
await space.updatePageList();
|
||||
await this.system.unloadAll();
|
||||
console.log("(Re)loading plugs");
|
||||
await Promise.all((await space.listPlugs()).map(async (plugName) => {
|
||||
try {
|
||||
await this.system.load(
|
||||
new URL(plugName, location.origin),
|
||||
createSandbox,
|
||||
);
|
||||
} catch (e: any) {
|
||||
console.error("Could not load plug", plugName, "error:", e.message);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
updateMarkdownParser() {
|
||||
// Load all syntax extensions
|
||||
this.mdExtensions = loadMarkdownExtensions(this.system);
|
||||
// And reload the syscalls to use the new syntax extensions
|
||||
this.system.registerSyscalls(
|
||||
[],
|
||||
markdownSyscalls(buildMarkdown(this.mdExtensions)),
|
||||
);
|
||||
}
|
||||
|
||||
localSyscall(name: string, args: any[]) {
|
||||
return this.system.localSyscall("[local]", name, args);
|
||||
}
|
||||
}
|
|
@ -103,7 +103,8 @@ export function fencedCodePlugin(editor: Editor) {
|
|||
if (isCursorInRange(state, [from, to])) return;
|
||||
const text = state.sliceDoc(from, to);
|
||||
const [_, lang] = text.match(/^```(\w+)?/)!;
|
||||
const codeWidgetCallback = editor.codeWidgetHook.codeWidgetCallbacks
|
||||
const codeWidgetCallback = editor.system.codeWidgetHook
|
||||
.codeWidgetCallbacks
|
||||
.get(lang);
|
||||
if (codeWidgetCallback) {
|
||||
// We got a custom renderer!
|
||||
|
|
|
@ -137,17 +137,19 @@ export function Panel({
|
|||
break;
|
||||
case "syscall": {
|
||||
const { id, name, args } = data;
|
||||
editor.system.localSyscall("core", name, args).then((result) => {
|
||||
if (!iFrameRef.current?.contentWindow) {
|
||||
// iFrame already went away
|
||||
return;
|
||||
}
|
||||
iFrameRef.current!.contentWindow!.postMessage({
|
||||
type: "syscall-response",
|
||||
id,
|
||||
result,
|
||||
});
|
||||
}).catch((e: any) => {
|
||||
editor.system.localSyscall(name, args).then(
|
||||
(result) => {
|
||||
if (!iFrameRef.current?.contentWindow) {
|
||||
// iFrame already went away
|
||||
return;
|
||||
}
|
||||
iFrameRef.current!.contentWindow!.postMessage({
|
||||
type: "syscall-response",
|
||||
id,
|
||||
result,
|
||||
});
|
||||
},
|
||||
).catch((e: any) => {
|
||||
if (!iFrameRef.current?.contentWindow) {
|
||||
// iFrame already went away
|
||||
return;
|
||||
|
|
197
web/editor.tsx
197
web/editor.tsx
|
@ -52,21 +52,11 @@ import {
|
|||
xmlLanguage,
|
||||
yamlLanguage,
|
||||
} from "../common/deps.ts";
|
||||
import { Manifest, SilverBulletHooks } from "../common/manifest.ts";
|
||||
import {
|
||||
loadMarkdownExtensions,
|
||||
MDExt,
|
||||
} from "../common/markdown_parser/markdown_ext.ts";
|
||||
import buildMarkdown from "../common/markdown_parser/parser.ts";
|
||||
import { Space } from "./space.ts";
|
||||
import { markdownSyscalls } from "./syscalls/markdown.ts";
|
||||
import { FilterOption, PageMeta } from "./types.ts";
|
||||
import { isMacLike, parseYamlSettings, safeRun } from "../common/util.ts";
|
||||
import { createSandbox } from "../plugos/environments/webworker_sandbox.ts";
|
||||
import { EventHook } from "../plugos/hooks/event.ts";
|
||||
import assetSyscalls from "../plugos/syscalls/asset.ts";
|
||||
import { eventSyscalls } from "../plugos/syscalls/event.ts";
|
||||
import { System } from "../plugos/system.ts";
|
||||
import { cleanModePlugins } from "./cm_plugins/clean.ts";
|
||||
import {
|
||||
attachmentExtension,
|
||||
|
@ -91,14 +81,10 @@ import {
|
|||
useReducer,
|
||||
vim,
|
||||
} from "./deps.ts";
|
||||
import { AppCommand, CommandHook } from "./hooks/command.ts";
|
||||
import { SlashCommandHook } from "./hooks/slash_command.ts";
|
||||
import { AppCommand } from "./hooks/command.ts";
|
||||
import { PathPageNavigator } from "./navigator.ts";
|
||||
import reducer from "./reducer.ts";
|
||||
import customMarkdownStyle from "./style.ts";
|
||||
import { editorSyscalls } from "./syscalls/editor.ts";
|
||||
import { spaceSyscalls } from "./syscalls/space.ts";
|
||||
import { systemSyscalls } from "./syscalls/system.ts";
|
||||
import {
|
||||
Action,
|
||||
AppViewState,
|
||||
|
@ -111,33 +97,21 @@ import type {
|
|||
ClickEvent,
|
||||
CompleteEvent,
|
||||
} from "../plug-api/app_event.ts";
|
||||
import { CodeWidgetHook } from "./hooks/code_widget.ts";
|
||||
import { throttle } from "../common/async_util.ts";
|
||||
import { readonlyMode } from "./cm_plugins/readonly.ts";
|
||||
import { PageNamespaceHook } from "../common/hooks/page_namespace.ts";
|
||||
import { CronHook } from "../plugos/hooks/cron.ts";
|
||||
import { pageIndexSyscalls } from "./syscalls/index.ts";
|
||||
import { storeSyscalls } from "../plugos/syscalls/store.dexie_browser.ts";
|
||||
import { PlugSpacePrimitives } from "../common/spaces/plug_space_primitives.ts";
|
||||
import { IndexedDBSpacePrimitives } from "../common/spaces/indexeddb_space_primitives.ts";
|
||||
import { FileMetaSpacePrimitives } from "../common/spaces/file_meta_space_primitives.ts";
|
||||
import { EventedSpacePrimitives } from "../common/spaces/evented_space_primitives.ts";
|
||||
import { clientStoreSyscalls } from "./syscalls/clientStore.ts";
|
||||
import { sandboxFetchSyscalls } from "./syscalls/fetch.ts";
|
||||
import { shellSyscalls } from "./syscalls/shell.ts";
|
||||
import { SyncService } from "./sync_service.ts";
|
||||
import { yamlSyscalls } from "./syscalls/yaml.ts";
|
||||
import { simpleHash } from "../common/crypto.ts";
|
||||
import { DexieKVStore } from "../plugos/lib/kv_store.dexie.ts";
|
||||
import { SyncStatus } from "../common/spaces/sync.ts";
|
||||
import { HttpSpacePrimitives } from "../common/spaces/http_space_primitives.ts";
|
||||
import { FallbackSpacePrimitives } from "../common/spaces/fallback_space_primitives.ts";
|
||||
import { syncSyscalls } from "./syscalls/sync.ts";
|
||||
import { FilteredSpacePrimitives } from "../common/spaces/filtered_space_primitives.ts";
|
||||
import { isValidPageName } from "$sb/lib/page.ts";
|
||||
import { debugSyscalls } from "./syscalls/debug.ts";
|
||||
|
||||
const frontMatterRegex = /^---\n(([^\n]|\n)*?)---\n/;
|
||||
import { ClientSystem } from "./client_system.ts";
|
||||
|
||||
class PageState {
|
||||
constructor(
|
||||
|
@ -145,8 +119,9 @@ class PageState {
|
|||
readonly selection: EditorSelection,
|
||||
) {}
|
||||
}
|
||||
const frontMatterRegex = /^---\n(([^\n]|\n)*?)---\n/;
|
||||
|
||||
const saveInterval = 1000;
|
||||
const autoSaveInterval = 1000;
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -160,32 +135,27 @@ declare global {
|
|||
|
||||
// TODO: Oh my god, need to refactor this
|
||||
export class Editor {
|
||||
readonly commandHook: CommandHook;
|
||||
readonly slashCommandHook: SlashCommandHook;
|
||||
openPages = new Map<string, PageState>();
|
||||
editorView?: EditorView;
|
||||
viewState: AppViewState = initialViewState;
|
||||
viewDispatch: (action: Action) => void = () => {};
|
||||
pageNavigator?: PathPageNavigator;
|
||||
|
||||
space: Space;
|
||||
|
||||
remoteSpacePrimitives: HttpSpacePrimitives;
|
||||
plugSpaceRemotePrimitives: PlugSpacePrimitives;
|
||||
|
||||
pageNavigator?: PathPageNavigator;
|
||||
eventHook: EventHook;
|
||||
codeWidgetHook: CodeWidgetHook;
|
||||
saveTimeout?: number;
|
||||
|
||||
saveTimeout: any;
|
||||
debouncedUpdateEvent = throttle(() => {
|
||||
this.eventHook
|
||||
.dispatchEvent("editor:updated")
|
||||
.catch((e) => console.error("Error dispatching editor:updated event", e));
|
||||
}, 1000);
|
||||
system: System<SilverBulletHooks>;
|
||||
mdExtensions: MDExt[] = [];
|
||||
system: ClientSystem;
|
||||
|
||||
// Track if plugs have been updated since sync cycle
|
||||
private plugsUpdated = false;
|
||||
fullSyncCompleted = false;
|
||||
|
||||
// Runtime state (that doesn't make sense in viewState)
|
||||
|
@ -193,34 +163,16 @@ export class Editor {
|
|||
settings?: BuiltinSettings;
|
||||
kvStore: DexieKVStore;
|
||||
|
||||
// Event bus used to communicate between components
|
||||
eventHook: EventHook;
|
||||
|
||||
constructor(
|
||||
parent: Element,
|
||||
) {
|
||||
const runtimeConfig = window.silverBulletConfig;
|
||||
|
||||
// Instantiate a PlugOS system
|
||||
const system = new System<SilverBulletHooks>("client");
|
||||
this.system = system;
|
||||
|
||||
// Generate a semi-unique prefix for the database so not to reuse databases for different space paths
|
||||
const dbPrefix = "" + simpleHash(runtimeConfig.spaceFolderPath);
|
||||
|
||||
// Attach the page namespace hook
|
||||
const namespaceHook = new PageNamespaceHook();
|
||||
system.addHook(namespaceHook);
|
||||
|
||||
// Event hook
|
||||
this.eventHook = new EventHook();
|
||||
system.addHook(this.eventHook);
|
||||
|
||||
// Cron hook
|
||||
const cronHook = new CronHook(system);
|
||||
system.addHook(cronHook);
|
||||
|
||||
const indexSyscalls = pageIndexSyscalls(
|
||||
`${dbPrefix}_page_index`,
|
||||
globalThis.indexedDB,
|
||||
);
|
||||
const dbPrefix = "" + simpleHash(window.silverBulletConfig.spaceFolderPath);
|
||||
|
||||
this.kvStore = new DexieKVStore(
|
||||
`${dbPrefix}_store`,
|
||||
|
@ -228,7 +180,16 @@ export class Editor {
|
|||
globalThis.indexedDB,
|
||||
);
|
||||
|
||||
const storeCalls = storeSyscalls(this.kvStore);
|
||||
// Event hook
|
||||
this.eventHook = new EventHook();
|
||||
|
||||
// Instantiate a PlugOS system
|
||||
this.system = new ClientSystem(
|
||||
this,
|
||||
this.kvStore,
|
||||
dbPrefix,
|
||||
this.eventHook,
|
||||
);
|
||||
|
||||
// Setup space
|
||||
this.remoteSpacePrimitives = new HttpSpacePrimitives(
|
||||
|
@ -239,10 +200,11 @@ export class Editor {
|
|||
|
||||
this.plugSpaceRemotePrimitives = new PlugSpacePrimitives(
|
||||
this.remoteSpacePrimitives,
|
||||
namespaceHook,
|
||||
this.system.namespaceHook,
|
||||
);
|
||||
|
||||
let fileFilterFn: (s: string) => boolean = () => true;
|
||||
|
||||
const localSpacePrimitives = new FilteredSpacePrimitives(
|
||||
new FileMetaSpacePrimitives(
|
||||
new EventedSpacePrimitives(
|
||||
|
@ -256,7 +218,7 @@ export class Editor {
|
|||
),
|
||||
this.eventHook,
|
||||
),
|
||||
indexSyscalls,
|
||||
this.system.indexSyscalls,
|
||||
),
|
||||
(meta) => fileFilterFn(meta.name),
|
||||
async () => {
|
||||
|
@ -287,26 +249,6 @@ export class Editor {
|
|||
},
|
||||
);
|
||||
|
||||
// Code widget hook
|
||||
this.codeWidgetHook = new CodeWidgetHook();
|
||||
this.system.addHook(this.codeWidgetHook);
|
||||
|
||||
// Command hook
|
||||
this.commandHook = new CommandHook();
|
||||
this.commandHook.on({
|
||||
commandsUpdated: (commandMap) => {
|
||||
this.viewDispatch({
|
||||
type: "update-commands",
|
||||
commands: commandMap,
|
||||
});
|
||||
},
|
||||
});
|
||||
this.system.addHook(this.commandHook);
|
||||
|
||||
// Slash command hook
|
||||
this.slashCommandHook = new SlashCommandHook(this);
|
||||
this.system.addHook(this.slashCommandHook);
|
||||
|
||||
this.render(parent);
|
||||
|
||||
this.editorView = new EditorView({
|
||||
|
@ -314,35 +256,6 @@ export class Editor {
|
|||
parent: document.getElementById("sb-editor")!,
|
||||
});
|
||||
|
||||
// Syscalls available to all plugs
|
||||
this.system.registerSyscalls(
|
||||
[],
|
||||
eventSyscalls(this.eventHook),
|
||||
editorSyscalls(this),
|
||||
spaceSyscalls(this),
|
||||
systemSyscalls(this, this.system),
|
||||
markdownSyscalls(buildMarkdown(this.mdExtensions)),
|
||||
assetSyscalls(this.system),
|
||||
yamlSyscalls(),
|
||||
storeCalls,
|
||||
indexSyscalls,
|
||||
debugSyscalls(),
|
||||
syncSyscalls(this.syncService),
|
||||
// LEGACY
|
||||
clientStoreSyscalls(storeCalls),
|
||||
);
|
||||
|
||||
// Syscalls that require some additional permissions
|
||||
this.system.registerSyscalls(
|
||||
["fetch"],
|
||||
sandboxFetchSyscalls(this.remoteSpacePrimitives),
|
||||
);
|
||||
|
||||
this.system.registerSyscalls(
|
||||
["shell"],
|
||||
shellSyscalls(this.remoteSpacePrimitives),
|
||||
);
|
||||
|
||||
// Make keyboard shortcuts work even when the editor is in read only mode or not focused
|
||||
globalThis.addEventListener("keydown", (ev) => {
|
||||
if (!this.editorView?.hasFocus) {
|
||||
|
@ -370,20 +283,6 @@ export class Editor {
|
|||
this.viewDispatch({ type: "show-palette", context: this.getContext() });
|
||||
}
|
||||
});
|
||||
|
||||
this.eventHook.addLocalListener("plug:changed", async (fileName) => {
|
||||
console.log("Plug updated, reloading:", fileName);
|
||||
system.unload(fileName);
|
||||
const plug = await system.load(
|
||||
new URL(`/${fileName}`, location.href),
|
||||
createSandbox,
|
||||
);
|
||||
if ((plug.manifest! as Manifest).syntax) {
|
||||
// If there are syntax extensions, rebuild the markdown parser immediately
|
||||
this.updateMarkdownParser();
|
||||
}
|
||||
this.plugsUpdated = true;
|
||||
});
|
||||
}
|
||||
|
||||
get currentPage(): string | undefined {
|
||||
|
@ -431,8 +330,8 @@ export class Editor {
|
|||
console.log("Navigating to anchor", pos);
|
||||
|
||||
// We're going to look up the anchor through a direct page store query...
|
||||
// TODO: This should be extracted
|
||||
const posLookup = await this.system.localSyscall(
|
||||
"core",
|
||||
"index.get",
|
||||
[
|
||||
pageName,
|
||||
|
@ -489,7 +388,7 @@ export class Editor {
|
|||
// "sync:success" is called with a number of operations only from syncSpace(), not from syncing individual pages
|
||||
this.fullSyncCompleted = true;
|
||||
}
|
||||
if (this.plugsUpdated) {
|
||||
if (this.system.plugsUpdated) {
|
||||
// To register new commands, update editor state based on new plugs
|
||||
this.rebuildEditorState();
|
||||
this.dispatchAppEvent("editor:pageLoaded", this.currentPage);
|
||||
|
@ -500,7 +399,7 @@ export class Editor {
|
|||
}
|
||||
}
|
||||
// Reset for next sync cycle
|
||||
this.plugsUpdated = false;
|
||||
this.system.plugsUpdated = false;
|
||||
|
||||
this.viewDispatch({ type: "sync-change", synced: true });
|
||||
});
|
||||
|
@ -582,7 +481,7 @@ export class Editor {
|
|||
resolve();
|
||||
}
|
||||
},
|
||||
immediate ? 0 : saveInterval,
|
||||
immediate ? 0 : autoSaveInterval,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -695,7 +594,7 @@ export class Editor {
|
|||
readOnly: boolean,
|
||||
): EditorState {
|
||||
const commandKeyBindings: KeyBinding[] = [];
|
||||
for (const def of this.commandHook.editorCommands.values()) {
|
||||
for (const def of this.system.commandHook.editorCommands.values()) {
|
||||
if (def.command.key) {
|
||||
commandKeyBindings.push({
|
||||
key: def.command.key,
|
||||
|
@ -729,7 +628,7 @@ export class Editor {
|
|||
const editor = this;
|
||||
let touchCount = 0;
|
||||
|
||||
const markdownLanguage = buildMarkdown(this.mdExtensions);
|
||||
const markdownLanguage = buildMarkdown(this.system.mdExtensions);
|
||||
|
||||
return EditorState.create({
|
||||
doc: text,
|
||||
|
@ -884,12 +783,12 @@ export class Editor {
|
|||
markdownLanguage.data.of({
|
||||
closeBrackets: { brackets: ["(", "{", "[", "`"] },
|
||||
}),
|
||||
syntaxHighlighting(customMarkdownStyle(this.mdExtensions)),
|
||||
syntaxHighlighting(customMarkdownStyle(this.system.mdExtensions)),
|
||||
autocompletion({
|
||||
override: [
|
||||
this.editorComplete.bind(this),
|
||||
this.slashCommandHook.slashCommandCompleter.bind(
|
||||
this.slashCommandHook,
|
||||
this.system.slashCommandHook.slashCommandCompleter.bind(
|
||||
this.system.slashCommandHook,
|
||||
),
|
||||
],
|
||||
}),
|
||||
|
@ -1059,38 +958,16 @@ export class Editor {
|
|||
|
||||
async reloadPlugs() {
|
||||
console.log("Loading plugs");
|
||||
await this.space.updatePageList();
|
||||
await this.system.unloadAll();
|
||||
console.log("(Re)loading plugs");
|
||||
await Promise.all((await this.space.listPlugs()).map(async (plugName) => {
|
||||
try {
|
||||
await this.system.load(
|
||||
new URL(plugName, location.origin),
|
||||
createSandbox,
|
||||
);
|
||||
} catch (e: any) {
|
||||
console.error("Could not load plug", plugName, "error:", e.message);
|
||||
}
|
||||
}));
|
||||
await this.system.reloadPlugsFromSpace(this.space);
|
||||
this.rebuildEditorState();
|
||||
await this.dispatchAppEvent("plugs:loaded");
|
||||
}
|
||||
|
||||
updateMarkdownParser() {
|
||||
// Load all syntax extensions
|
||||
this.mdExtensions = loadMarkdownExtensions(this.system);
|
||||
// And reload the syscalls to use the new syntax extensions
|
||||
this.system.registerSyscalls(
|
||||
[],
|
||||
markdownSyscalls(buildMarkdown(this.mdExtensions)),
|
||||
);
|
||||
}
|
||||
|
||||
rebuildEditorState() {
|
||||
const editorView = this.editorView;
|
||||
console.log("Rebuilding editor state");
|
||||
|
||||
this.updateMarkdownParser();
|
||||
this.system.updateMarkdownParser();
|
||||
|
||||
if (editorView && this.currentPage) {
|
||||
// And update the editor if a page is loaded
|
||||
|
@ -1470,7 +1347,7 @@ export class Editor {
|
|||
return;
|
||||
}
|
||||
console.log("Now renaming page to...", newName);
|
||||
await editor.system.loadedPlugs.get("core")!.invoke(
|
||||
await editor.system.system.loadedPlugs.get("core")!.invoke(
|
||||
"renamePage",
|
||||
[{ page: newName }],
|
||||
);
|
||||
|
|
|
@ -3,26 +3,25 @@ import { SysCallMapping } from "../../plugos/system.ts";
|
|||
import { AttachmentMeta, PageMeta } from "../types.ts";
|
||||
|
||||
export function spaceSyscalls(editor: Editor): SysCallMapping {
|
||||
const space = editor.space;
|
||||
return {
|
||||
"space.listPages": (): Promise<PageMeta[]> => {
|
||||
return space.fetchPageList();
|
||||
return editor.space.fetchPageList();
|
||||
},
|
||||
"space.readPage": async (
|
||||
_ctx,
|
||||
name: string,
|
||||
): Promise<string> => {
|
||||
return (await space.readPage(name)).text;
|
||||
return (await editor.space.readPage(name)).text;
|
||||
},
|
||||
"space.getPageMeta": (_ctx, name: string): Promise<PageMeta> => {
|
||||
return space.getPageMeta(name);
|
||||
return editor.space.getPageMeta(name);
|
||||
},
|
||||
"space.writePage": (
|
||||
_ctx,
|
||||
name: string,
|
||||
text: string,
|
||||
): Promise<PageMeta> => {
|
||||
return space.writePage(name, text);
|
||||
return editor.space.writePage(name, text);
|
||||
},
|
||||
"space.deletePage": async (_ctx, name: string) => {
|
||||
// If we're deleting the current page, navigate to the index page
|
||||
|
@ -35,32 +34,32 @@ export function spaceSyscalls(editor: Editor): SysCallMapping {
|
|||
await editor.space.deletePage(name);
|
||||
},
|
||||
"space.listPlugs": (): Promise<string[]> => {
|
||||
return space.listPlugs();
|
||||
return editor.space.listPlugs();
|
||||
},
|
||||
"space.listAttachments": async (): Promise<AttachmentMeta[]> => {
|
||||
return await space.fetchAttachmentList();
|
||||
return await editor.space.fetchAttachmentList();
|
||||
},
|
||||
"space.readAttachment": async (
|
||||
_ctx,
|
||||
name: string,
|
||||
): Promise<Uint8Array> => {
|
||||
return (await space.readAttachment(name)).data;
|
||||
return (await editor.space.readAttachment(name)).data;
|
||||
},
|
||||
"space.getAttachmentMeta": async (
|
||||
_ctx,
|
||||
name: string,
|
||||
): Promise<AttachmentMeta> => {
|
||||
return await space.getAttachmentMeta(name);
|
||||
return await editor.space.getAttachmentMeta(name);
|
||||
},
|
||||
"space.writeAttachment": (
|
||||
_ctx,
|
||||
name: string,
|
||||
data: Uint8Array,
|
||||
): Promise<AttachmentMeta> => {
|
||||
return space.writeAttachment(name, data);
|
||||
return editor.space.writeAttachment(name, data);
|
||||
},
|
||||
"space.deleteAttachment": async (_ctx, name: string) => {
|
||||
await space.deleteAttachment(name);
|
||||
await editor.space.deleteAttachment(name);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { SysCallMapping } from "../../plugos/system.ts";
|
||||
import { SyncService } from "../sync_service.ts";
|
||||
import type { Editor } from "../editor.tsx";
|
||||
|
||||
export function syncSyscalls(syncService: SyncService): SysCallMapping {
|
||||
export function syncSyscalls(editor: Editor): SysCallMapping {
|
||||
return {
|
||||
"sync.isSyncing": (): Promise<boolean> => {
|
||||
return syncService.isSyncing();
|
||||
return editor.syncService.isSyncing();
|
||||
},
|
||||
"sync.hasInitialSyncCompleted": (): Promise<boolean> => {
|
||||
return syncService.hasInitialSyncCompleted();
|
||||
return editor.syncService.hasInitialSyncCompleted();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ export function systemSyscalls(
|
|||
},
|
||||
"system.listCommands": (): { [key: string]: CommandDef } => {
|
||||
const allCommands: { [key: string]: CommandDef } = {};
|
||||
for (let [cmd, def] of editor.commandHook.editorCommands) {
|
||||
for (const [cmd, def] of editor.system.commandHook.editorCommands) {
|
||||
allCommands[cmd] = def.command;
|
||||
}
|
||||
return allCommands;
|
||||
|
|
Loading…
Reference in New Issue