Files
plainleaf/client/plugos/hooks/document_editor.ts
T

73 lines
2.1 KiB
TypeScript

import type { Hook, Manifest } from "../types.ts";
import type { DocumentEditorT } from "@silverbulletmd/silverbullet/type/manifest";
import type { System } from "../system.ts";
import type { DocumentEditorCallback } from "@silverbulletmd/silverbullet/type/client";
export class DocumentEditorHook implements Hook<DocumentEditorT> {
documentEditors = new Map<
string,
{ extensions: string[]; callback: DocumentEditorCallback }
>();
collectAllDocumentEditors(system: System<DocumentEditorT>) {
this.documentEditors.clear();
for (const plug of system.loadedPlugs.values()) {
for (const [name, functionDef] of Object.entries(
plug.manifest!.functions,
)) {
if (!functionDef.editor) {
continue;
}
const keys = Array.isArray(functionDef.editor)
? functionDef.editor
: [functionDef.editor];
const conflict = Array.from(this.documentEditors.entries()).find(
([_, { extensions }]) => keys.some((key) => extensions.includes(key)),
);
if (conflict) {
console.log(
`Extension definition of document editor ${name}: [${keys}] conflicts with the one from ${
conflict[0]
}: [${conflict[1].extensions}]! Using the latter.`,
);
}
this.documentEditors.set(name, {
extensions: keys,
callback: () => plug.invoke(name, []),
});
}
}
}
apply(system: System<DocumentEditorT>): void {
this.collectAllDocumentEditors(system);
system.on({
plugLoaded: () => {
this.collectAllDocumentEditors(system);
},
});
}
validateManifest(manifest: Manifest<DocumentEditorT>): string[] {
const errors = [];
for (const functionDef of Object.values(manifest.functions)) {
if (!functionDef.editor) {
continue;
}
if (
typeof functionDef.editor !== "string" &&
!Array.isArray(functionDef.editor)
) {
errors.push(
`Document editors require a string name or an array of string names.`,
);
}
}
return errors;
}
}