Skip to content

Commit

Permalink
Merge branch 'block-plugins' into block-plugins-ai-experiment
Browse files Browse the repository at this point in the history
  • Loading branch information
YousefED committed Oct 11, 2023
2 parents e0a7d15 + efcb5b5 commit b058b74
Show file tree
Hide file tree
Showing 25 changed files with 1,035 additions and 322 deletions.
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 20 additions & 13 deletions packages/editor/src/app/documentRenderers/richtext/FrameHost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,40 +68,47 @@ export function FrameHost(props: {
processYjsMessage: async (message: ArrayBuffer) => {
provider.onMessage(message, "penpal");
},
registerTypeCellModuleCompiler: async (moduleName: string) => {
if (moduleManagers.has(moduleName)) {
console.warn("already has moduleManager for", moduleName);
return;
}
resolveModuleName: async (moduleName: string) => {
if (!moduleName.startsWith("!")) {
throw new Error("invalid module name");
}
const identifierStr = moduleName.substring(1);

const identifier = parseIdentifier(moduleName.substring(1));
const identifierStr = identifier.toString();
return identifierStr;
},
registerTypeCellModuleCompiler: async (identifierStr: string) => {
const identifier = parseIdentifier(identifierStr);
if (moduleManagers.has(identifierStr)) {
console.warn("already has moduleManager for", identifierStr);
return identifierStr;
}

const provider = new DocumentResourceModelProvider(
identifier,
props.sessionStore,
);

const forwarder = new ModelForwarder(
"modules/" + moduleName,
"modules/" + identifierStr,
provider,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
connectionMethods.current!,
);
moduleManagers.set(moduleName, { provider, forwarder });

moduleManagers.set(identifierStr, { provider, forwarder });
await forwarder.initialize();
return identifier.toString();
return identifierStr;
},
unregisterTypeCellModuleCompiler: async (moduleName: string) => {
const moduleManager = moduleManagers.get(moduleName);
unregisterTypeCellModuleCompiler: async (identifierStr: string) => {
const moduleManager = moduleManagers.get(identifierStr);
if (!moduleManager) {
console.warn("no moduleManager for", moduleName);
console.warn("no moduleManager for", identifierStr);
return;
}
moduleManager.provider.dispose();
moduleManager.forwarder.dispose();
moduleManagers.delete(moduleName);
moduleManagers.delete(identifierStr);
},
};

Expand Down
4 changes: 2 additions & 2 deletions packages/engine/src/executor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { autorun, runInAction } from "mobx";
import { autorun, runInAction, trace } from "mobx";
import { TypeCellContext } from "./context.js";
import { installHooks } from "./hookDisposables.js";
import { Module } from "./modules.js";
Expand Down Expand Up @@ -104,7 +104,7 @@ export async function runModule(
detectedLoop = true;
throw new Error("loop detected (child run)");
}
// trace(false);
trace(false);
if (initialRun) {
// log.debug("engine initial run", cell.id); //, func + "");
} else {
Expand Down
2 changes: 2 additions & 0 deletions packages/frame/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.0.3",
"private": true,
"dependencies": {
"@atlaskit/form": "^8.11.8",
"@blocknote/core": "^0.9.3",
"@blocknote/react": "^0.9.3",
"@typecell-org/util": "^0.0.3",
Expand All @@ -13,6 +14,7 @@
"@tiptap/react": "^2.0.4",
"@floating-ui/react": "^0.25.1",
"@syncedstore/yjs-reactive-bindings": "^0.5.1",
"lodash.memoize": "^4.1.2",
"localforage": "^1.10.0",
"lz-string": "^1.4.4",
"monaco-editor": "^0.35.0",
Expand Down
110 changes: 104 additions & 6 deletions packages/frame/src/EditorStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,53 @@ import { Block, BlockNoteEditor } from "@blocknote/core";
import {
ObservableMap,
action,
computed,
makeObservable,
observable,
onBecomeObserved,
reaction,
runInAction,
} from "mobx";
import { ExecutionHost } from "./runtime/executor/executionHosts/ExecutionHost";
import LocalExecutionHost from "./runtime/executor/executionHosts/local/LocalExecutionHost";

export class EditorStore {
private readonly blockCache = new ObservableMap<string, TypeCellBlock>();

// TODO: hacky properties
/** @internal */
public editor: BlockNoteEditor | undefined;
/** @internal */
public executionHost: LocalExecutionHost | undefined;
public topLevelBlocks: any;

Check warning on line 24 in packages/frame/src/EditorStore.ts

View workflow job for this annotation

GitHub Actions / Build

Unexpected any. Specify a different type

constructor() {
makeObservable(this, {
customBlocks: observable.shallow,
add: action,
delete: action,
topLevelBlocks: observable.ref,
});

onBecomeObserved(this, "topLevelBlocks", () => {
this.editor!.onEditorContentChange(() => {

Check warning on line 35 in packages/frame/src/EditorStore.ts

View workflow job for this annotation

GitHub Actions / Build

Forbidden non-null assertion
runInAction(() => {
this.topLevelBlocks = this.editor!.topLevelBlocks.map((block) =>

Check warning on line 37 in packages/frame/src/EditorStore.ts

View workflow job for this annotation

GitHub Actions / Build

Forbidden non-null assertion
this.getBlock(block.id),
);
});
});
this.topLevelBlocks = this.editor!.topLevelBlocks.map((block) =>

Check warning on line 42 in packages/frame/src/EditorStore.ts

View workflow job for this annotation

GitHub Actions / Build

Forbidden non-null assertion
this.getBlock(block.id),
);
});
}

customBlocks = new Map<string, any>();

Check warning on line 48 in packages/frame/src/EditorStore.ts

View workflow job for this annotation

GitHub Actions / Build

Unexpected any. Specify a different type

/**
* Add a custom block (slash menu command) to the editor
*/
public add(config: any) {

Check warning on line 53 in packages/frame/src/EditorStore.ts

View workflow job for this annotation

GitHub Actions / Build

Unexpected any. Specify a different type
if (this.customBlocks.has(config.id)) {
// already has block with this id, maybe loop of documents?
Expand All @@ -32,10 +58,17 @@ export class EditorStore {
this.customBlocks.set(config.id, config);
}

/**
* Remove a custom block (slash menu command) from the editor
*/
public delete(config: any) {

Check warning on line 64 in packages/frame/src/EditorStore.ts

View workflow job for this annotation

GitHub Actions / Build

Unexpected any. Specify a different type
this.customBlocks.delete(config.id);
}

/**
* EXPERIMENTAL
* @internal
* */
public getBlock(id: string) {
let block = this.blockCache.get(id);
if (!block) {
Expand All @@ -44,32 +77,97 @@ export class EditorStore {
return undefined;
}

block = new TypeCellBlock(id, this.editor!, () => {
block = new TypeCellBlock(id, this.editor!, this.executionHost!, () => {

Check warning on line 80 in packages/frame/src/EditorStore.ts

View workflow job for this annotation

GitHub Actions / Build

Forbidden non-null assertion

Check warning on line 80 in packages/frame/src/EditorStore.ts

View workflow job for this annotation

GitHub Actions / Build

Forbidden non-null assertion
this.blockCache.delete(id);
});
this.blockCache.set(id, block);
}

const b = block;
// eslint-disable-next-line @typescript-eslint/no-this-alias
const that = this;
return {
...block.block,
storage: block.storage,
get parent(): any {
const findParent = (
searchId: string,
parentId: string | undefined,
children: Block[],
): string | undefined => {
for (const child of children) {
if (child.id === searchId) {
return parentId;
}
const found = findParent(searchId, child.id, child.children);
if (found) {
return found;
}
}
return undefined;
};
const parentId = findParent(id, undefined, that.editor!.topLevelBlocks);
if (!parentId) {
return undefined;
}
return that.getBlock(parentId);
},
get context() {
return b.context;
},
};
}

/**
* EXPERIMENTAL
*
* @internal
* */
public get firstBlock() {
return this.getBlock(this.editor!.topLevelBlocks[0].id);
}
}

/**
* EXPERIMENTAL
*/
class TypeCellBlock {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore it's set using updatePropertiesFromEditorBlock
block: Block;
storage: Record<string, any> = {};

constructor(id: string, editor: BlockNoteEditor, onRemoved: () => void) {
get context() {
// TODO: hacky
const keys = [...this.executionHost.outputs.keys()].filter((key) =>
key.includes(this.block.id),
);

if (!keys.length) {
return undefined;
}
// return undefined;

// debugger;
const val = this.executionHost.outputs.get(keys[0])?.value;
if (val instanceof Error) {
return undefined;
}
return val;
// return Object.fromEntries(
// Object.getOwnPropertyNames(val).map((key) => [key, val[key]]),
// );
}

constructor(
id: string,
editor: BlockNoteEditor,
private readonly executionHost: ExecutionHost,
onRemoved: () => void,
) {
makeObservable(this, {
block: observable.ref,
context: computed,
storage: true,
});

Expand All @@ -82,11 +180,11 @@ class TypeCellBlock {
runInAction(() => {
this.block = newBlock;

if (newBlock.props.storage !== JSON.stringify(this.storage)) {
if (newBlock.props.storage) {
if ((newBlock.props as any).storage !== JSON.stringify(this.storage)) {
if (newBlock.props as any) {
try {
console.log("update cell storage");
this.storage = JSON.parse(newBlock.props.storage) || {};
this.storage = JSON.parse((newBlock.props as any).storage) || {};
} catch (e) {
console.error(e);
}
Expand Down Expand Up @@ -123,7 +221,7 @@ class TypeCellBlock {
editor.updateBlock(this.block, {
props: {
storage: val,
},
} as any,
});
}
},
Expand Down
Loading

0 comments on commit b058b74

Please sign in to comment.