Created
November 8, 2022 18:25
-
-
Save fantactuka/ee8ef8ac1c51d179c7a9199262444b04 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
import type { LexicalEditor, LexicalNode } from "Lexical"; | |
import type { Binding, Provider } from "LexicalYjs"; | |
import { | |
createBinding, | |
syncLexicalUpdateToYjs, | |
syncYjsChangesToLexical, | |
} from "LexicalYjs"; | |
import { Doc, encodeStateAsUpdate } from "yjs"; | |
export default function headlessConvertYDocStateToLexicalJSON( | |
nodes: Array<Class<LexicalNode>>, | |
yDocState: Uint8Array | |
): SerializedEditorState { | |
const { binding, editor } = createHeadlessCollaborationEditor(nodes); | |
applyUpdate(binding.doc, yDocState, { isUpdateRemote: true }); | |
editor.update(() => {}, { discrete: true }); | |
return editor.getEditorState().toJSON(); | |
} | |
/** | |
* Creates headless collaboration editor with no-op provider (since it won't | |
* connect to message distribution infra) and binding. It also sets up | |
* bi-directional synchronization between yDoc and editor | |
*/ | |
function createHeadlessCollaborationEditor(nodes: Array<Class<LexicalNode>>): { | |
editor: LexicalEditor, | |
provider: Provider, | |
binding: Binding, | |
} { | |
const editor = createEditor({ | |
headless: true, | |
namespace: "headless", | |
nodes, | |
onError: (error) => { | |
throw error; | |
}, | |
}); | |
const id = "main"; | |
const doc = new Doc(); | |
const docMap = new Map([[id, doc]]); | |
const provider = createNoOpProvider(); | |
const binding = createBinding(editor, provider, id, doc, docMap); | |
registerCollaborationListeners(editor, provider, binding); | |
return { | |
binding, | |
editor, | |
provider, | |
}; | |
} | |
function registerCollaborationListeners( | |
editor: LexicalEditor, | |
provider: Provider, | |
binding: Binding | |
): void { | |
editor.registerUpdateListener( | |
({ | |
dirtyElements, | |
dirtyLeaves, | |
editorState, | |
normalizedNodes, | |
prevEditorState, | |
tags, | |
}) => { | |
if (tags.has("skip-collab") === false) { | |
syncLexicalUpdateToYjs( | |
binding, | |
provider, | |
prevEditorState, | |
editorState, | |
dirtyElements, | |
dirtyLeaves, | |
normalizedNodes, | |
tags | |
); | |
} | |
} | |
); | |
binding.root.getSharedType().observeDeep((events, transaction) => { | |
if (transaction?.origin !== binding) { | |
syncYjsChangesToLexical(binding, provider, events); | |
} | |
}); | |
} | |
function createNoOpProvider(): Provider { | |
const emptyFunction = () => {}; | |
return { | |
awareness: { | |
getLocalState: () => null, | |
getStates: () => new Map(), | |
off: emptyFunction, | |
on: emptyFunction, | |
setLocalState: emptyFunction, | |
}, | |
connect: emptyFunction, | |
disconnect: emptyFunction, | |
off: emptyFunction, | |
on: emptyFunction, | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@jamespantalones thanks for the reply!
I think I was having a different issue, but it was also related to ESM and CommonJS issues. Got it worked out by your hint on ESM/CommonJS. Thanks for that!