@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 CHANGED
@@ -1,8 +1,10 @@
1
1
  import { Liveblocks } from '@liveblocks/node';
2
- import { Klass, LexicalNode, LexicalNodeReplacement, EditorState, RootNode } from 'lexical';
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: (root: RootNode) => void): Promise<void>;
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, EditorState, RootNode } from 'lexical';
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: (root: RootNode) => void): Promise<void>;
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-lexical2";
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
- const root = _lexical.$getRoot.call(void 0, );
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
- exports.$createParagraphNode = _lexical.$createParagraphNode; exports.$createTextNode = _lexical.$createTextNode; exports.$getRoot = _lexical.$getRoot; exports.getEditorState = getEditorState; exports.modifyDocument = modifyDocument;
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-lexical2";
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
- const root = $getRoot();
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
@@ -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-lexical3",
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-lexical2",
37
- "@liveblocks/node": "1.12.0-lexical2",
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
  },