@liveblocks/node-lexical 1.12.0-lexical3 → 1.12.0-lexical6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +35 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +34 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Liveblocks } from '@liveblocks/node';
|
|
2
|
-
import { Klass, LexicalNode, LexicalNodeReplacement,
|
|
2
|
+
import { Klass, LexicalNode, LexicalNodeReplacement, LexicalEditor, EditorState } from 'lexical';
|
|
3
3
|
export { $createParagraphNode, $createTextNode, $getRoot } from 'lexical';
|
|
4
4
|
|
|
5
|
+
declare function getEditor(client: Liveblocks, roomId: string, nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>): Promise<LexicalEditor>;
|
|
6
|
+
declare function getTextContent(client: Liveblocks, roomId: string, nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>): Promise<string>;
|
|
5
7
|
declare function getEditorState(client: Liveblocks, roomId: string, nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>): Promise<EditorState>;
|
|
6
|
-
declare function modifyDocument(client: Liveblocks, roomId: string, nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>, modifyFn: (
|
|
8
|
+
declare function modifyDocument(client: Liveblocks, roomId: string, nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>, modifyFn: (editor: LexicalEditor) => void): Promise<void>;
|
|
7
9
|
|
|
8
|
-
export { getEditorState, modifyDocument };
|
|
10
|
+
export { getEditor, getEditorState, getTextContent, modifyDocument };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Liveblocks } from '@liveblocks/node';
|
|
2
|
-
import { Klass, LexicalNode, LexicalNodeReplacement,
|
|
2
|
+
import { Klass, LexicalNode, LexicalNodeReplacement, LexicalEditor, EditorState } from 'lexical';
|
|
3
3
|
export { $createParagraphNode, $createTextNode, $getRoot } from 'lexical';
|
|
4
4
|
|
|
5
|
+
declare function getEditor(client: Liveblocks, roomId: string, nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>): Promise<LexicalEditor>;
|
|
6
|
+
declare function getTextContent(client: Liveblocks, roomId: string, nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>): Promise<string>;
|
|
5
7
|
declare function getEditorState(client: Liveblocks, roomId: string, nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>): Promise<EditorState>;
|
|
6
|
-
declare function modifyDocument(client: Liveblocks, roomId: string, nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>, modifyFn: (
|
|
8
|
+
declare function modifyDocument(client: Liveblocks, roomId: string, nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>, modifyFn: (editor: LexicalEditor) => void): Promise<void>;
|
|
7
9
|
|
|
8
|
-
export { getEditorState, modifyDocument };
|
|
10
|
+
export { getEditor, getEditorState, getTextContent, modifyDocument };
|
package/dist/index.js
CHANGED
|
@@ -181,13 +181,43 @@ var ThreadMarkNode = class _ThreadMarkNode extends _lexical.ElementNode {
|
|
|
181
181
|
|
|
182
182
|
// src/version.ts
|
|
183
183
|
var PKG_NAME = "@liveblocks/node-lexical";
|
|
184
|
-
var PKG_VERSION = "1.12.0-
|
|
184
|
+
var PKG_VERSION = "1.12.0-lexical6";
|
|
185
185
|
var PKG_FORMAT = "cjs";
|
|
186
186
|
|
|
187
187
|
// src/index.ts
|
|
188
188
|
|
|
189
189
|
_core.detectDupes.call(void 0, PKG_NAME, PKG_VERSION, PKG_FORMAT);
|
|
190
190
|
var LIVEBLOCKS_NODES = [ThreadMarkNode, MentionNode];
|
|
191
|
+
async function getEditor(client, roomId, nodes) {
|
|
192
|
+
const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);
|
|
193
|
+
const update = new Uint8Array(doc);
|
|
194
|
+
return withHeadlessCollaborationEditor(
|
|
195
|
+
[...LIVEBLOCKS_NODES, ...nodes],
|
|
196
|
+
(editor, binding) => {
|
|
197
|
+
_yjs.applyUpdate.call(void 0, binding.doc, update);
|
|
198
|
+
editor.update(() => {
|
|
199
|
+
}, { discrete: true });
|
|
200
|
+
return editor;
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
async function getTextContent(client, roomId, nodes) {
|
|
205
|
+
const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);
|
|
206
|
+
const update = new Uint8Array(doc);
|
|
207
|
+
return withHeadlessCollaborationEditor(
|
|
208
|
+
[...LIVEBLOCKS_NODES, ...nodes],
|
|
209
|
+
(editor, binding) => {
|
|
210
|
+
_yjs.applyUpdate.call(void 0, binding.doc, update);
|
|
211
|
+
editor.update(() => {
|
|
212
|
+
}, { discrete: true });
|
|
213
|
+
let content = "";
|
|
214
|
+
editor.getEditorState().read(() => {
|
|
215
|
+
content = _lexical.$getRoot.call(void 0, ).getTextContent();
|
|
216
|
+
});
|
|
217
|
+
return content;
|
|
218
|
+
}
|
|
219
|
+
);
|
|
220
|
+
}
|
|
191
221
|
async function getEditorState(client, roomId, nodes) {
|
|
192
222
|
const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);
|
|
193
223
|
const update = new Uint8Array(doc);
|
|
@@ -213,8 +243,7 @@ async function modifyDocument(client, roomId, nodes, modifyFn) {
|
|
|
213
243
|
const beforeVector = _yjs.encodeStateVectorFromUpdate.call(void 0, update);
|
|
214
244
|
editor.update(
|
|
215
245
|
() => {
|
|
216
|
-
|
|
217
|
-
modifyFn(root);
|
|
246
|
+
modifyFn(editor);
|
|
218
247
|
},
|
|
219
248
|
{ discrete: true }
|
|
220
249
|
);
|
|
@@ -229,5 +258,7 @@ async function modifyDocument(client, roomId, nodes, modifyFn) {
|
|
|
229
258
|
|
|
230
259
|
|
|
231
260
|
|
|
232
|
-
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
exports.$createParagraphNode = _lexical.$createParagraphNode; exports.$createTextNode = _lexical.$createTextNode; exports.$getRoot = _lexical.$getRoot; exports.getEditor = getEditor; exports.getEditorState = getEditorState; exports.getTextContent = getTextContent; exports.modifyDocument = modifyDocument;
|
|
233
264
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/headless.ts","../src/MentionNodeLite.ts","../src/ThreadNodeLite.ts","../src/version.ts"],"names":["applyUpdate","$applyNodeReplacement","$getRoot"],"mappings":"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","sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\nimport type { Liveblocks } from \"@liveblocks/node\";\nimport type {\n EditorState,\n Klass,\n LexicalNode,\n LexicalNodeReplacement,\n RootNode,\n} from \"lexical\";\nimport { $getRoot } from \"lexical\";\nimport {\n applyUpdate,\n encodeStateAsUpdate,\n encodeStateVectorFromUpdate,\n} from \"yjs\";\n\nimport { withHeadlessCollaborationEditor } from \"./headless\";\nimport { MentionNode } from \"./MentionNodeLite\";\nimport { ThreadMarkNode } from \"./ThreadNodeLite\";\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nconst LIVEBLOCKS_NODES = [ThreadMarkNode, MentionNode];\n\nexport { $createParagraphNode, $createTextNode, $getRoot } from \"lexical\";\n\n// get editor state\nexport async function getEditorState(\n client: Liveblocks,\n roomId: string,\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>\n): Promise<EditorState> {\n const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);\n const update = new Uint8Array(doc);\n return withHeadlessCollaborationEditor(\n [...LIVEBLOCKS_NODES, ...nodes],\n (editor, binding) => {\n applyUpdate(binding.doc, update);\n editor.update(() => {}, { discrete: true });\n return editor.getEditorState();\n }\n );\n}\n\n// modify document\nexport async function modifyDocument(\n client: Liveblocks,\n roomId: string,\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>,\n modifyFn: (root: RootNode) => void\n): Promise<void> {\n const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);\n const update = new Uint8Array(doc);\n await withHeadlessCollaborationEditor(\n [...LIVEBLOCKS_NODES, ...nodes],\n (editor, binding) => {\n applyUpdate(binding.doc, update);\n editor.update(() => {}, { discrete: true });\n const beforeVector = encodeStateVectorFromUpdate(update);\n editor.update(\n () => {\n const root = $getRoot();\n modifyFn(root);\n },\n { discrete: true }\n );\n const afterUpdate = encodeStateAsUpdate(binding.doc, beforeVector);\n return client.sendYjsBinaryUpdate(roomId, afterUpdate);\n }\n );\n}\n","import { createHeadlessEditor } from \"@lexical/headless\";\nimport type { Binding, Provider } from \"@lexical/yjs\";\nimport {\n createBinding,\n syncLexicalUpdateToYjs,\n syncYjsChangesToLexical,\n} from \"@lexical/yjs\";\nimport type {\n Klass,\n LexicalEditor,\n LexicalNode,\n LexicalNodeReplacement,\n SerializedEditorState,\n SerializedLexicalNode,\n} from \"lexical\";\nimport type { Transaction, YEvent } from \"yjs\";\nimport { applyUpdate, Doc } from \"yjs\";\n\nexport function headlessConvertYDocStateToLexicalJSON(\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>,\n yDocState: Uint8Array\n): SerializedEditorState<SerializedLexicalNode> {\n return withHeadlessCollaborationEditor(nodes, (editor, binding) => {\n applyUpdate(binding.doc, yDocState, { isUpdateRemote: true });\n editor.update(() => {}, { discrete: true });\n\n return editor.getEditorState().toJSON();\n });\n}\nexport function withHeadlessCollaborationEditor<T>(\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>,\n callback: (editor: LexicalEditor, binding: Binding, provider: Provider) => T\n): T {\n const editor = createHeadlessEditor({\n nodes,\n });\n\n const id = \"root\";\n const doc = new Doc();\n const docMap = new Map([[id, doc]]);\n const provider = createNoOpProvider();\n const binding = createBinding(editor, provider, id, doc, docMap);\n\n const unsubscribe = registerCollaborationListeners(editor, provider, binding);\n\n const res = callback(editor, binding, provider);\n\n unsubscribe();\n\n return res;\n}\n\nfunction registerCollaborationListeners(\n editor: LexicalEditor,\n provider: Provider,\n binding: Binding\n): () => void {\n const unsubscribeUpdateListener = editor.registerUpdateListener(\n ({\n dirtyElements,\n dirtyLeaves,\n editorState,\n normalizedNodes,\n prevEditorState,\n tags,\n }) => {\n if (tags.has(\"skip-collab\") === false) {\n syncLexicalUpdateToYjs(\n binding,\n provider,\n prevEditorState,\n editorState,\n dirtyElements,\n dirtyLeaves,\n normalizedNodes,\n tags\n );\n }\n }\n );\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const observer = (events: Array<YEvent<any>>, transaction: Transaction) => {\n if (transaction.origin !== binding) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n syncYjsChangesToLexical(binding, provider, events, false);\n }\n };\n\n binding.root.getSharedType().observeDeep(observer);\n\n return () => {\n unsubscribeUpdateListener();\n binding.root.getSharedType().unobserveDeep(observer);\n };\n}\n\nfunction createNoOpProvider(): Provider {\n const emptyFunction = () => {};\n\n return {\n awareness: {\n getLocalState: () => null,\n getStates: () => new Map(),\n off: emptyFunction,\n on: emptyFunction,\n setLocalState: emptyFunction,\n },\n connect: emptyFunction,\n disconnect: emptyFunction,\n off: emptyFunction,\n on: emptyFunction,\n };\n}\n","import type { NodeKey, SerializedLexicalNode, Spread } from \"lexical\";\nimport { $applyNodeReplacement, DecoratorNode } from \"lexical\";\n\nexport type SerializedMentionNode = Spread<\n {\n value: string;\n },\n SerializedLexicalNode\n>;\n\nexport class MentionNode extends DecoratorNode<null> {\n __id: string;\n\n constructor(value: string, key?: NodeKey) {\n super(key);\n this.__id = value;\n }\n\n static getType(): string {\n return \"lb-mention\";\n }\n\n static clone(node: MentionNode): MentionNode {\n return new MentionNode(node.__id);\n }\n\n static importJSON(serializedNode: SerializedMentionNode): MentionNode {\n const node = new MentionNode(serializedNode.value);\n return $applyNodeReplacement(node);\n }\n\n exportJSON(): SerializedMentionNode {\n return {\n value: this.getTextContent(),\n type: \"lb-mention\",\n version: 1,\n };\n }\n\n getTextContent(): string {\n const self = this.getLatest();\n return self.__id;\n }\n\n decorate(): null {\n return null;\n }\n}\n","import type {\n BaseSelection,\n LexicalNode,\n NodeKey,\n SerializedElementNode,\n Spread,\n} from \"lexical\";\nimport { $applyNodeReplacement, $isRangeSelection, ElementNode } from \"lexical\";\n\nexport type SerializedThreadMarkNode = Spread<\n {\n ids: Array<string>;\n },\n SerializedElementNode\n>;\n\nexport class ThreadMarkNode extends ElementNode {\n /** @internal */\n __ids: Array<string>; // The ids of the threads that this mark is associated with\n\n static getType(): string {\n return \"lb-thread-mark\";\n }\n\n static clone(node: ThreadMarkNode): ThreadMarkNode {\n return new ThreadMarkNode(Array.from(node.__ids), node.__key);\n }\n\n static importJSON(serializedNode: SerializedThreadMarkNode): ThreadMarkNode {\n const node = $applyNodeReplacement<ThreadMarkNode>(\n new ThreadMarkNode(serializedNode.ids)\n );\n node.setFormat(serializedNode.format);\n node.setIndent(serializedNode.indent);\n node.setDirection(serializedNode.direction);\n return node;\n }\n\n exportJSON(): SerializedThreadMarkNode {\n return {\n ...super.exportJSON(),\n ids: this.getIDs(),\n type: \"lb-thread-mark\",\n version: 1,\n };\n }\n\n getIDs(): Array<string> {\n const self = this.getLatest();\n return self instanceof ThreadMarkNode ? self.__ids : [];\n }\n\n constructor(ids: Array<string>, key?: NodeKey) {\n super(key);\n this.__ids = ids || [];\n }\n\n canInsertTextBefore(): false {\n return false;\n }\n\n canInsertTextAfter(): false {\n return false;\n }\n\n canBeEmpty(): false {\n return false;\n }\n\n isInline(): true {\n return true;\n }\n\n extractWithChild(\n _: LexicalNode,\n selection: BaseSelection,\n destination: \"clone\" | \"html\"\n ): boolean {\n if (!$isRangeSelection(selection) || destination === \"html\") {\n return false;\n }\n const anchor = selection.anchor;\n const focus = selection.focus;\n const anchorNode = anchor.getNode();\n const focusNode = focus.getNode();\n const isBackward = selection.isBackward();\n const selectionLength = isBackward\n ? anchor.offset - focus.offset\n : focus.offset - anchor.offset;\n return (\n this.isParentOf(anchorNode) &&\n this.isParentOf(focusNode) &&\n this.getTextContent().length === selectionLength\n );\n }\n\n excludeFromCopy(destination: \"clone\" | \"html\"): boolean {\n return destination !== \"clone\";\n }\n}\n","declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/node-lexical\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/headless.ts","../src/MentionNodeLite.ts","../src/ThreadNodeLite.ts","../src/version.ts"],"names":["applyUpdate","$applyNodeReplacement","$getRoot"],"mappings":"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","sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\nimport type { Liveblocks } from \"@liveblocks/node\";\nimport type {\n EditorState,\n Klass,\n LexicalEditor,\n LexicalNode,\n LexicalNodeReplacement,\n} from \"lexical\";\nimport { $getRoot } from \"lexical\";\nimport {\n applyUpdate,\n encodeStateAsUpdate,\n encodeStateVectorFromUpdate,\n} from \"yjs\";\n\nimport { withHeadlessCollaborationEditor } from \"./headless\";\nimport { MentionNode } from \"./MentionNodeLite\";\nimport { ThreadMarkNode } from \"./ThreadNodeLite\";\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nconst LIVEBLOCKS_NODES = [ThreadMarkNode, MentionNode];\n\nexport { $createParagraphNode, $createTextNode, $getRoot } from \"lexical\";\n\n// gets a sync'd headless editor\nexport async function getEditor(\n client: Liveblocks,\n roomId: string,\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>\n): Promise<LexicalEditor> {\n const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);\n const update = new Uint8Array(doc);\n return withHeadlessCollaborationEditor(\n [...LIVEBLOCKS_NODES, ...nodes],\n (editor, binding) => {\n applyUpdate(binding.doc, update);\n editor.update(() => {}, { discrete: true });\n return editor;\n }\n );\n}\n\n// gets text content\nexport async function getTextContent(\n client: Liveblocks,\n roomId: string,\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>\n): Promise<string> {\n const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);\n const update = new Uint8Array(doc);\n return withHeadlessCollaborationEditor(\n [...LIVEBLOCKS_NODES, ...nodes],\n (editor, binding) => {\n applyUpdate(binding.doc, update);\n editor.update(() => {}, { discrete: true });\n let content: string = \"\";\n editor.getEditorState().read(() => {\n content = $getRoot().getTextContent();\n });\n return content;\n }\n );\n}\n\n// get editor state\nexport async function getEditorState(\n client: Liveblocks,\n roomId: string,\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>\n): Promise<EditorState> {\n const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);\n const update = new Uint8Array(doc);\n return withHeadlessCollaborationEditor(\n [...LIVEBLOCKS_NODES, ...nodes],\n (editor, binding) => {\n applyUpdate(binding.doc, update);\n editor.update(() => {}, { discrete: true });\n return editor.getEditorState();\n }\n );\n}\n\n// modify document\nexport async function modifyDocument(\n client: Liveblocks,\n roomId: string,\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>,\n modifyFn: (editor: LexicalEditor) => void\n): Promise<void> {\n const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);\n const update = new Uint8Array(doc);\n await withHeadlessCollaborationEditor(\n [...LIVEBLOCKS_NODES, ...nodes],\n (editor, binding) => {\n applyUpdate(binding.doc, update);\n editor.update(() => {}, { discrete: true });\n const beforeVector = encodeStateVectorFromUpdate(update);\n editor.update(\n () => {\n modifyFn(editor);\n },\n { discrete: true }\n );\n const afterUpdate = encodeStateAsUpdate(binding.doc, beforeVector);\n return client.sendYjsBinaryUpdate(roomId, afterUpdate);\n }\n );\n}\n","import { createHeadlessEditor } from \"@lexical/headless\";\nimport type { Binding, Provider } from \"@lexical/yjs\";\nimport {\n createBinding,\n syncLexicalUpdateToYjs,\n syncYjsChangesToLexical,\n} from \"@lexical/yjs\";\nimport type {\n Klass,\n LexicalEditor,\n LexicalNode,\n LexicalNodeReplacement,\n SerializedEditorState,\n SerializedLexicalNode,\n} from \"lexical\";\nimport type { Transaction, YEvent } from \"yjs\";\nimport { applyUpdate, Doc } from \"yjs\";\n\nexport function headlessConvertYDocStateToLexicalJSON(\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>,\n yDocState: Uint8Array\n): SerializedEditorState<SerializedLexicalNode> {\n return withHeadlessCollaborationEditor(nodes, (editor, binding) => {\n applyUpdate(binding.doc, yDocState, { isUpdateRemote: true });\n editor.update(() => {}, { discrete: true });\n\n return editor.getEditorState().toJSON();\n });\n}\nexport function withHeadlessCollaborationEditor<T>(\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>,\n callback: (editor: LexicalEditor, binding: Binding, provider: Provider) => T\n): T {\n const editor = createHeadlessEditor({\n nodes,\n });\n\n const id = \"root\";\n const doc = new Doc();\n const docMap = new Map([[id, doc]]);\n const provider = createNoOpProvider();\n const binding = createBinding(editor, provider, id, doc, docMap);\n\n const unsubscribe = registerCollaborationListeners(editor, provider, binding);\n\n const res = callback(editor, binding, provider);\n\n unsubscribe();\n\n return res;\n}\n\nfunction registerCollaborationListeners(\n editor: LexicalEditor,\n provider: Provider,\n binding: Binding\n): () => void {\n const unsubscribeUpdateListener = editor.registerUpdateListener(\n ({\n dirtyElements,\n dirtyLeaves,\n editorState,\n normalizedNodes,\n prevEditorState,\n tags,\n }) => {\n if (tags.has(\"skip-collab\") === false) {\n syncLexicalUpdateToYjs(\n binding,\n provider,\n prevEditorState,\n editorState,\n dirtyElements,\n dirtyLeaves,\n normalizedNodes,\n tags\n );\n }\n }\n );\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const observer = (events: Array<YEvent<any>>, transaction: Transaction) => {\n if (transaction.origin !== binding) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n syncYjsChangesToLexical(binding, provider, events, false);\n }\n };\n\n binding.root.getSharedType().observeDeep(observer);\n\n return () => {\n unsubscribeUpdateListener();\n binding.root.getSharedType().unobserveDeep(observer);\n };\n}\n\nfunction createNoOpProvider(): Provider {\n const emptyFunction = () => {};\n\n return {\n awareness: {\n getLocalState: () => null,\n getStates: () => new Map(),\n off: emptyFunction,\n on: emptyFunction,\n setLocalState: emptyFunction,\n },\n connect: emptyFunction,\n disconnect: emptyFunction,\n off: emptyFunction,\n on: emptyFunction,\n };\n}\n","import type { NodeKey, SerializedLexicalNode, Spread } from \"lexical\";\nimport { $applyNodeReplacement, DecoratorNode } from \"lexical\";\n\nexport type SerializedMentionNode = Spread<\n {\n value: string;\n },\n SerializedLexicalNode\n>;\n\nexport class MentionNode extends DecoratorNode<null> {\n __id: string;\n\n constructor(value: string, key?: NodeKey) {\n super(key);\n this.__id = value;\n }\n\n static getType(): string {\n return \"lb-mention\";\n }\n\n static clone(node: MentionNode): MentionNode {\n return new MentionNode(node.__id);\n }\n\n static importJSON(serializedNode: SerializedMentionNode): MentionNode {\n const node = new MentionNode(serializedNode.value);\n return $applyNodeReplacement(node);\n }\n\n exportJSON(): SerializedMentionNode {\n return {\n value: this.getTextContent(),\n type: \"lb-mention\",\n version: 1,\n };\n }\n\n getTextContent(): string {\n const self = this.getLatest();\n return self.__id;\n }\n\n decorate(): null {\n return null;\n }\n}\n","import type {\n BaseSelection,\n LexicalNode,\n NodeKey,\n SerializedElementNode,\n Spread,\n} from \"lexical\";\nimport { $applyNodeReplacement, $isRangeSelection, ElementNode } from \"lexical\";\n\nexport type SerializedThreadMarkNode = Spread<\n {\n ids: Array<string>;\n },\n SerializedElementNode\n>;\n\nexport class ThreadMarkNode extends ElementNode {\n /** @internal */\n __ids: Array<string>; // The ids of the threads that this mark is associated with\n\n static getType(): string {\n return \"lb-thread-mark\";\n }\n\n static clone(node: ThreadMarkNode): ThreadMarkNode {\n return new ThreadMarkNode(Array.from(node.__ids), node.__key);\n }\n\n static importJSON(serializedNode: SerializedThreadMarkNode): ThreadMarkNode {\n const node = $applyNodeReplacement<ThreadMarkNode>(\n new ThreadMarkNode(serializedNode.ids)\n );\n node.setFormat(serializedNode.format);\n node.setIndent(serializedNode.indent);\n node.setDirection(serializedNode.direction);\n return node;\n }\n\n exportJSON(): SerializedThreadMarkNode {\n return {\n ...super.exportJSON(),\n ids: this.getIDs(),\n type: \"lb-thread-mark\",\n version: 1,\n };\n }\n\n getIDs(): Array<string> {\n const self = this.getLatest();\n return self instanceof ThreadMarkNode ? self.__ids : [];\n }\n\n constructor(ids: Array<string>, key?: NodeKey) {\n super(key);\n this.__ids = ids || [];\n }\n\n canInsertTextBefore(): false {\n return false;\n }\n\n canInsertTextAfter(): false {\n return false;\n }\n\n canBeEmpty(): false {\n return false;\n }\n\n isInline(): true {\n return true;\n }\n\n extractWithChild(\n _: LexicalNode,\n selection: BaseSelection,\n destination: \"clone\" | \"html\"\n ): boolean {\n if (!$isRangeSelection(selection) || destination === \"html\") {\n return false;\n }\n const anchor = selection.anchor;\n const focus = selection.focus;\n const anchorNode = anchor.getNode();\n const focusNode = focus.getNode();\n const isBackward = selection.isBackward();\n const selectionLength = isBackward\n ? anchor.offset - focus.offset\n : focus.offset - anchor.offset;\n return (\n this.isParentOf(anchorNode) &&\n this.isParentOf(focusNode) &&\n this.getTextContent().length === selectionLength\n );\n }\n\n excludeFromCopy(destination: \"clone\" | \"html\"): boolean {\n return destination !== \"clone\";\n }\n}\n","declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/node-lexical\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -181,13 +181,43 @@ var ThreadMarkNode = class _ThreadMarkNode extends ElementNode {
|
|
|
181
181
|
|
|
182
182
|
// src/version.ts
|
|
183
183
|
var PKG_NAME = "@liveblocks/node-lexical";
|
|
184
|
-
var PKG_VERSION = "1.12.0-
|
|
184
|
+
var PKG_VERSION = "1.12.0-lexical6";
|
|
185
185
|
var PKG_FORMAT = "esm";
|
|
186
186
|
|
|
187
187
|
// src/index.ts
|
|
188
188
|
import { $createParagraphNode, $createTextNode, $getRoot as $getRoot2 } from "lexical";
|
|
189
189
|
detectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);
|
|
190
190
|
var LIVEBLOCKS_NODES = [ThreadMarkNode, MentionNode];
|
|
191
|
+
async function getEditor(client, roomId, nodes) {
|
|
192
|
+
const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);
|
|
193
|
+
const update = new Uint8Array(doc);
|
|
194
|
+
return withHeadlessCollaborationEditor(
|
|
195
|
+
[...LIVEBLOCKS_NODES, ...nodes],
|
|
196
|
+
(editor, binding) => {
|
|
197
|
+
applyUpdate2(binding.doc, update);
|
|
198
|
+
editor.update(() => {
|
|
199
|
+
}, { discrete: true });
|
|
200
|
+
return editor;
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
async function getTextContent(client, roomId, nodes) {
|
|
205
|
+
const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);
|
|
206
|
+
const update = new Uint8Array(doc);
|
|
207
|
+
return withHeadlessCollaborationEditor(
|
|
208
|
+
[...LIVEBLOCKS_NODES, ...nodes],
|
|
209
|
+
(editor, binding) => {
|
|
210
|
+
applyUpdate2(binding.doc, update);
|
|
211
|
+
editor.update(() => {
|
|
212
|
+
}, { discrete: true });
|
|
213
|
+
let content = "";
|
|
214
|
+
editor.getEditorState().read(() => {
|
|
215
|
+
content = $getRoot().getTextContent();
|
|
216
|
+
});
|
|
217
|
+
return content;
|
|
218
|
+
}
|
|
219
|
+
);
|
|
220
|
+
}
|
|
191
221
|
async function getEditorState(client, roomId, nodes) {
|
|
192
222
|
const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);
|
|
193
223
|
const update = new Uint8Array(doc);
|
|
@@ -213,8 +243,7 @@ async function modifyDocument(client, roomId, nodes, modifyFn) {
|
|
|
213
243
|
const beforeVector = encodeStateVectorFromUpdate(update);
|
|
214
244
|
editor.update(
|
|
215
245
|
() => {
|
|
216
|
-
|
|
217
|
-
modifyFn(root);
|
|
246
|
+
modifyFn(editor);
|
|
218
247
|
},
|
|
219
248
|
{ discrete: true }
|
|
220
249
|
);
|
|
@@ -227,7 +256,9 @@ export {
|
|
|
227
256
|
$createParagraphNode,
|
|
228
257
|
$createTextNode,
|
|
229
258
|
$getRoot2 as $getRoot,
|
|
259
|
+
getEditor,
|
|
230
260
|
getEditorState,
|
|
261
|
+
getTextContent,
|
|
231
262
|
modifyDocument
|
|
232
263
|
};
|
|
233
264
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/headless.ts","../src/MentionNodeLite.ts","../src/ThreadNodeLite.ts","../src/version.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\nimport type { Liveblocks } from \"@liveblocks/node\";\nimport type {\n EditorState,\n Klass,\n LexicalNode,\n LexicalNodeReplacement,\n RootNode,\n} from \"lexical\";\nimport { $getRoot } from \"lexical\";\nimport {\n applyUpdate,\n encodeStateAsUpdate,\n encodeStateVectorFromUpdate,\n} from \"yjs\";\n\nimport { withHeadlessCollaborationEditor } from \"./headless\";\nimport { MentionNode } from \"./MentionNodeLite\";\nimport { ThreadMarkNode } from \"./ThreadNodeLite\";\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nconst LIVEBLOCKS_NODES = [ThreadMarkNode, MentionNode];\n\nexport { $createParagraphNode, $createTextNode, $getRoot } from \"lexical\";\n\n// get editor state\nexport async function getEditorState(\n client: Liveblocks,\n roomId: string,\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>\n): Promise<EditorState> {\n const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);\n const update = new Uint8Array(doc);\n return withHeadlessCollaborationEditor(\n [...LIVEBLOCKS_NODES, ...nodes],\n (editor, binding) => {\n applyUpdate(binding.doc, update);\n editor.update(() => {}, { discrete: true });\n return editor.getEditorState();\n }\n );\n}\n\n// modify document\nexport async function modifyDocument(\n client: Liveblocks,\n roomId: string,\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>,\n modifyFn: (root: RootNode) => void\n): Promise<void> {\n const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);\n const update = new Uint8Array(doc);\n await withHeadlessCollaborationEditor(\n [...LIVEBLOCKS_NODES, ...nodes],\n (editor, binding) => {\n applyUpdate(binding.doc, update);\n editor.update(() => {}, { discrete: true });\n const beforeVector = encodeStateVectorFromUpdate(update);\n editor.update(\n () => {\n const root = $getRoot();\n modifyFn(root);\n },\n { discrete: true }\n );\n const afterUpdate = encodeStateAsUpdate(binding.doc, beforeVector);\n return client.sendYjsBinaryUpdate(roomId, afterUpdate);\n }\n );\n}\n","import { createHeadlessEditor } from \"@lexical/headless\";\nimport type { Binding, Provider } from \"@lexical/yjs\";\nimport {\n createBinding,\n syncLexicalUpdateToYjs,\n syncYjsChangesToLexical,\n} from \"@lexical/yjs\";\nimport type {\n Klass,\n LexicalEditor,\n LexicalNode,\n LexicalNodeReplacement,\n SerializedEditorState,\n SerializedLexicalNode,\n} from \"lexical\";\nimport type { Transaction, YEvent } from \"yjs\";\nimport { applyUpdate, Doc } from \"yjs\";\n\nexport function headlessConvertYDocStateToLexicalJSON(\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>,\n yDocState: Uint8Array\n): SerializedEditorState<SerializedLexicalNode> {\n return withHeadlessCollaborationEditor(nodes, (editor, binding) => {\n applyUpdate(binding.doc, yDocState, { isUpdateRemote: true });\n editor.update(() => {}, { discrete: true });\n\n return editor.getEditorState().toJSON();\n });\n}\nexport function withHeadlessCollaborationEditor<T>(\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>,\n callback: (editor: LexicalEditor, binding: Binding, provider: Provider) => T\n): T {\n const editor = createHeadlessEditor({\n nodes,\n });\n\n const id = \"root\";\n const doc = new Doc();\n const docMap = new Map([[id, doc]]);\n const provider = createNoOpProvider();\n const binding = createBinding(editor, provider, id, doc, docMap);\n\n const unsubscribe = registerCollaborationListeners(editor, provider, binding);\n\n const res = callback(editor, binding, provider);\n\n unsubscribe();\n\n return res;\n}\n\nfunction registerCollaborationListeners(\n editor: LexicalEditor,\n provider: Provider,\n binding: Binding\n): () => void {\n const unsubscribeUpdateListener = editor.registerUpdateListener(\n ({\n dirtyElements,\n dirtyLeaves,\n editorState,\n normalizedNodes,\n prevEditorState,\n tags,\n }) => {\n if (tags.has(\"skip-collab\") === false) {\n syncLexicalUpdateToYjs(\n binding,\n provider,\n prevEditorState,\n editorState,\n dirtyElements,\n dirtyLeaves,\n normalizedNodes,\n tags\n );\n }\n }\n );\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const observer = (events: Array<YEvent<any>>, transaction: Transaction) => {\n if (transaction.origin !== binding) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n syncYjsChangesToLexical(binding, provider, events, false);\n }\n };\n\n binding.root.getSharedType().observeDeep(observer);\n\n return () => {\n unsubscribeUpdateListener();\n binding.root.getSharedType().unobserveDeep(observer);\n };\n}\n\nfunction createNoOpProvider(): Provider {\n const emptyFunction = () => {};\n\n return {\n awareness: {\n getLocalState: () => null,\n getStates: () => new Map(),\n off: emptyFunction,\n on: emptyFunction,\n setLocalState: emptyFunction,\n },\n connect: emptyFunction,\n disconnect: emptyFunction,\n off: emptyFunction,\n on: emptyFunction,\n };\n}\n","import type { NodeKey, SerializedLexicalNode, Spread } from \"lexical\";\nimport { $applyNodeReplacement, DecoratorNode } from \"lexical\";\n\nexport type SerializedMentionNode = Spread<\n {\n value: string;\n },\n SerializedLexicalNode\n>;\n\nexport class MentionNode extends DecoratorNode<null> {\n __id: string;\n\n constructor(value: string, key?: NodeKey) {\n super(key);\n this.__id = value;\n }\n\n static getType(): string {\n return \"lb-mention\";\n }\n\n static clone(node: MentionNode): MentionNode {\n return new MentionNode(node.__id);\n }\n\n static importJSON(serializedNode: SerializedMentionNode): MentionNode {\n const node = new MentionNode(serializedNode.value);\n return $applyNodeReplacement(node);\n }\n\n exportJSON(): SerializedMentionNode {\n return {\n value: this.getTextContent(),\n type: \"lb-mention\",\n version: 1,\n };\n }\n\n getTextContent(): string {\n const self = this.getLatest();\n return self.__id;\n }\n\n decorate(): null {\n return null;\n }\n}\n","import type {\n BaseSelection,\n LexicalNode,\n NodeKey,\n SerializedElementNode,\n Spread,\n} from \"lexical\";\nimport { $applyNodeReplacement, $isRangeSelection, ElementNode } from \"lexical\";\n\nexport type SerializedThreadMarkNode = Spread<\n {\n ids: Array<string>;\n },\n SerializedElementNode\n>;\n\nexport class ThreadMarkNode extends ElementNode {\n /** @internal */\n __ids: Array<string>; // The ids of the threads that this mark is associated with\n\n static getType(): string {\n return \"lb-thread-mark\";\n }\n\n static clone(node: ThreadMarkNode): ThreadMarkNode {\n return new ThreadMarkNode(Array.from(node.__ids), node.__key);\n }\n\n static importJSON(serializedNode: SerializedThreadMarkNode): ThreadMarkNode {\n const node = $applyNodeReplacement<ThreadMarkNode>(\n new ThreadMarkNode(serializedNode.ids)\n );\n node.setFormat(serializedNode.format);\n node.setIndent(serializedNode.indent);\n node.setDirection(serializedNode.direction);\n return node;\n }\n\n exportJSON(): SerializedThreadMarkNode {\n return {\n ...super.exportJSON(),\n ids: this.getIDs(),\n type: \"lb-thread-mark\",\n version: 1,\n };\n }\n\n getIDs(): Array<string> {\n const self = this.getLatest();\n return self instanceof ThreadMarkNode ? self.__ids : [];\n }\n\n constructor(ids: Array<string>, key?: NodeKey) {\n super(key);\n this.__ids = ids || [];\n }\n\n canInsertTextBefore(): false {\n return false;\n }\n\n canInsertTextAfter(): false {\n return false;\n }\n\n canBeEmpty(): false {\n return false;\n }\n\n isInline(): true {\n return true;\n }\n\n extractWithChild(\n _: LexicalNode,\n selection: BaseSelection,\n destination: \"clone\" | \"html\"\n ): boolean {\n if (!$isRangeSelection(selection) || destination === \"html\") {\n return false;\n }\n const anchor = selection.anchor;\n const focus = selection.focus;\n const anchorNode = anchor.getNode();\n const focusNode = focus.getNode();\n const isBackward = selection.isBackward();\n const selectionLength = isBackward\n ? anchor.offset - focus.offset\n : focus.offset - anchor.offset;\n return (\n this.isParentOf(anchorNode) &&\n this.isParentOf(focusNode) &&\n this.getTextContent().length === selectionLength\n );\n }\n\n excludeFromCopy(destination: \"clone\" | \"html\"): boolean {\n return destination !== \"clone\";\n }\n}\n","declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/node-lexical\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"],"mappings":"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","names":["applyUpdate","$applyNodeReplacement","$getRoot","applyUpdate"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/headless.ts","../src/MentionNodeLite.ts","../src/ThreadNodeLite.ts","../src/version.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\nimport type { Liveblocks } from \"@liveblocks/node\";\nimport type {\n EditorState,\n Klass,\n LexicalEditor,\n LexicalNode,\n LexicalNodeReplacement,\n} from \"lexical\";\nimport { $getRoot } from \"lexical\";\nimport {\n applyUpdate,\n encodeStateAsUpdate,\n encodeStateVectorFromUpdate,\n} from \"yjs\";\n\nimport { withHeadlessCollaborationEditor } from \"./headless\";\nimport { MentionNode } from \"./MentionNodeLite\";\nimport { ThreadMarkNode } from \"./ThreadNodeLite\";\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nconst LIVEBLOCKS_NODES = [ThreadMarkNode, MentionNode];\n\nexport { $createParagraphNode, $createTextNode, $getRoot } from \"lexical\";\n\n// gets a sync'd headless editor\nexport async function getEditor(\n client: Liveblocks,\n roomId: string,\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>\n): Promise<LexicalEditor> {\n const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);\n const update = new Uint8Array(doc);\n return withHeadlessCollaborationEditor(\n [...LIVEBLOCKS_NODES, ...nodes],\n (editor, binding) => {\n applyUpdate(binding.doc, update);\n editor.update(() => {}, { discrete: true });\n return editor;\n }\n );\n}\n\n// gets text content\nexport async function getTextContent(\n client: Liveblocks,\n roomId: string,\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>\n): Promise<string> {\n const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);\n const update = new Uint8Array(doc);\n return withHeadlessCollaborationEditor(\n [...LIVEBLOCKS_NODES, ...nodes],\n (editor, binding) => {\n applyUpdate(binding.doc, update);\n editor.update(() => {}, { discrete: true });\n let content: string = \"\";\n editor.getEditorState().read(() => {\n content = $getRoot().getTextContent();\n });\n return content;\n }\n );\n}\n\n// get editor state\nexport async function getEditorState(\n client: Liveblocks,\n roomId: string,\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>\n): Promise<EditorState> {\n const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);\n const update = new Uint8Array(doc);\n return withHeadlessCollaborationEditor(\n [...LIVEBLOCKS_NODES, ...nodes],\n (editor, binding) => {\n applyUpdate(binding.doc, update);\n editor.update(() => {}, { discrete: true });\n return editor.getEditorState();\n }\n );\n}\n\n// modify document\nexport async function modifyDocument(\n client: Liveblocks,\n roomId: string,\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>,\n modifyFn: (editor: LexicalEditor) => void\n): Promise<void> {\n const doc = await client.getYjsDocumentAsBinaryUpdate(roomId);\n const update = new Uint8Array(doc);\n await withHeadlessCollaborationEditor(\n [...LIVEBLOCKS_NODES, ...nodes],\n (editor, binding) => {\n applyUpdate(binding.doc, update);\n editor.update(() => {}, { discrete: true });\n const beforeVector = encodeStateVectorFromUpdate(update);\n editor.update(\n () => {\n modifyFn(editor);\n },\n { discrete: true }\n );\n const afterUpdate = encodeStateAsUpdate(binding.doc, beforeVector);\n return client.sendYjsBinaryUpdate(roomId, afterUpdate);\n }\n );\n}\n","import { createHeadlessEditor } from \"@lexical/headless\";\nimport type { Binding, Provider } from \"@lexical/yjs\";\nimport {\n createBinding,\n syncLexicalUpdateToYjs,\n syncYjsChangesToLexical,\n} from \"@lexical/yjs\";\nimport type {\n Klass,\n LexicalEditor,\n LexicalNode,\n LexicalNodeReplacement,\n SerializedEditorState,\n SerializedLexicalNode,\n} from \"lexical\";\nimport type { Transaction, YEvent } from \"yjs\";\nimport { applyUpdate, Doc } from \"yjs\";\n\nexport function headlessConvertYDocStateToLexicalJSON(\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>,\n yDocState: Uint8Array\n): SerializedEditorState<SerializedLexicalNode> {\n return withHeadlessCollaborationEditor(nodes, (editor, binding) => {\n applyUpdate(binding.doc, yDocState, { isUpdateRemote: true });\n editor.update(() => {}, { discrete: true });\n\n return editor.getEditorState().toJSON();\n });\n}\nexport function withHeadlessCollaborationEditor<T>(\n nodes: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>,\n callback: (editor: LexicalEditor, binding: Binding, provider: Provider) => T\n): T {\n const editor = createHeadlessEditor({\n nodes,\n });\n\n const id = \"root\";\n const doc = new Doc();\n const docMap = new Map([[id, doc]]);\n const provider = createNoOpProvider();\n const binding = createBinding(editor, provider, id, doc, docMap);\n\n const unsubscribe = registerCollaborationListeners(editor, provider, binding);\n\n const res = callback(editor, binding, provider);\n\n unsubscribe();\n\n return res;\n}\n\nfunction registerCollaborationListeners(\n editor: LexicalEditor,\n provider: Provider,\n binding: Binding\n): () => void {\n const unsubscribeUpdateListener = editor.registerUpdateListener(\n ({\n dirtyElements,\n dirtyLeaves,\n editorState,\n normalizedNodes,\n prevEditorState,\n tags,\n }) => {\n if (tags.has(\"skip-collab\") === false) {\n syncLexicalUpdateToYjs(\n binding,\n provider,\n prevEditorState,\n editorState,\n dirtyElements,\n dirtyLeaves,\n normalizedNodes,\n tags\n );\n }\n }\n );\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const observer = (events: Array<YEvent<any>>, transaction: Transaction) => {\n if (transaction.origin !== binding) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n syncYjsChangesToLexical(binding, provider, events, false);\n }\n };\n\n binding.root.getSharedType().observeDeep(observer);\n\n return () => {\n unsubscribeUpdateListener();\n binding.root.getSharedType().unobserveDeep(observer);\n };\n}\n\nfunction createNoOpProvider(): Provider {\n const emptyFunction = () => {};\n\n return {\n awareness: {\n getLocalState: () => null,\n getStates: () => new Map(),\n off: emptyFunction,\n on: emptyFunction,\n setLocalState: emptyFunction,\n },\n connect: emptyFunction,\n disconnect: emptyFunction,\n off: emptyFunction,\n on: emptyFunction,\n };\n}\n","import type { NodeKey, SerializedLexicalNode, Spread } from \"lexical\";\nimport { $applyNodeReplacement, DecoratorNode } from \"lexical\";\n\nexport type SerializedMentionNode = Spread<\n {\n value: string;\n },\n SerializedLexicalNode\n>;\n\nexport class MentionNode extends DecoratorNode<null> {\n __id: string;\n\n constructor(value: string, key?: NodeKey) {\n super(key);\n this.__id = value;\n }\n\n static getType(): string {\n return \"lb-mention\";\n }\n\n static clone(node: MentionNode): MentionNode {\n return new MentionNode(node.__id);\n }\n\n static importJSON(serializedNode: SerializedMentionNode): MentionNode {\n const node = new MentionNode(serializedNode.value);\n return $applyNodeReplacement(node);\n }\n\n exportJSON(): SerializedMentionNode {\n return {\n value: this.getTextContent(),\n type: \"lb-mention\",\n version: 1,\n };\n }\n\n getTextContent(): string {\n const self = this.getLatest();\n return self.__id;\n }\n\n decorate(): null {\n return null;\n }\n}\n","import type {\n BaseSelection,\n LexicalNode,\n NodeKey,\n SerializedElementNode,\n Spread,\n} from \"lexical\";\nimport { $applyNodeReplacement, $isRangeSelection, ElementNode } from \"lexical\";\n\nexport type SerializedThreadMarkNode = Spread<\n {\n ids: Array<string>;\n },\n SerializedElementNode\n>;\n\nexport class ThreadMarkNode extends ElementNode {\n /** @internal */\n __ids: Array<string>; // The ids of the threads that this mark is associated with\n\n static getType(): string {\n return \"lb-thread-mark\";\n }\n\n static clone(node: ThreadMarkNode): ThreadMarkNode {\n return new ThreadMarkNode(Array.from(node.__ids), node.__key);\n }\n\n static importJSON(serializedNode: SerializedThreadMarkNode): ThreadMarkNode {\n const node = $applyNodeReplacement<ThreadMarkNode>(\n new ThreadMarkNode(serializedNode.ids)\n );\n node.setFormat(serializedNode.format);\n node.setIndent(serializedNode.indent);\n node.setDirection(serializedNode.direction);\n return node;\n }\n\n exportJSON(): SerializedThreadMarkNode {\n return {\n ...super.exportJSON(),\n ids: this.getIDs(),\n type: \"lb-thread-mark\",\n version: 1,\n };\n }\n\n getIDs(): Array<string> {\n const self = this.getLatest();\n return self instanceof ThreadMarkNode ? self.__ids : [];\n }\n\n constructor(ids: Array<string>, key?: NodeKey) {\n super(key);\n this.__ids = ids || [];\n }\n\n canInsertTextBefore(): false {\n return false;\n }\n\n canInsertTextAfter(): false {\n return false;\n }\n\n canBeEmpty(): false {\n return false;\n }\n\n isInline(): true {\n return true;\n }\n\n extractWithChild(\n _: LexicalNode,\n selection: BaseSelection,\n destination: \"clone\" | \"html\"\n ): boolean {\n if (!$isRangeSelection(selection) || destination === \"html\") {\n return false;\n }\n const anchor = selection.anchor;\n const focus = selection.focus;\n const anchorNode = anchor.getNode();\n const focusNode = focus.getNode();\n const isBackward = selection.isBackward();\n const selectionLength = isBackward\n ? anchor.offset - focus.offset\n : focus.offset - anchor.offset;\n return (\n this.isParentOf(anchorNode) &&\n this.isParentOf(focusNode) &&\n this.getTextContent().length === selectionLength\n );\n }\n\n excludeFromCopy(destination: \"clone\" | \"html\"): boolean {\n return destination !== \"clone\";\n }\n}\n","declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/node-lexical\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"],"mappings":"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","names":["applyUpdate","$applyNodeReplacement","$getRoot","applyUpdate"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/node-lexical",
|
|
3
|
-
"version": "1.12.0-
|
|
3
|
+
"version": "1.12.0-lexical6",
|
|
4
4
|
"description": "A server-side utility that lets you modify lexical documents hosted in Liveblocks.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -33,12 +33,13 @@
|
|
|
33
33
|
"test:watch": "jest --silent --verbose --color=always --watch"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@liveblocks/core": "1.12.0-
|
|
37
|
-
"@liveblocks/node": "1.12.0-
|
|
36
|
+
"@liveblocks/core": "1.12.0-lexical6",
|
|
37
|
+
"@liveblocks/node": "1.12.0-lexical6",
|
|
38
38
|
"yjs": "^13.6.15"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@lexical/headless": "0.14.5",
|
|
42
|
+
"@lexical/selection": "0.14.3",
|
|
42
43
|
"@lexical/yjs": "0.14.5",
|
|
43
44
|
"lexical": "0.14.5"
|
|
44
45
|
},
|