@getguru/slate-yjs-core 1.0.3

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.
Files changed (126) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +3 -0
  3. package/dist/applyToSlate/index.d.ts +23 -0
  4. package/dist/applyToSlate/textEvent.d.ts +4 -0
  5. package/dist/applyToYjs/index.d.ts +4 -0
  6. package/dist/applyToYjs/node/index.d.ts +4 -0
  7. package/dist/applyToYjs/node/insertNode.d.ts +4 -0
  8. package/dist/applyToYjs/node/mergeNode.d.ts +4 -0
  9. package/dist/applyToYjs/node/moveNode.d.ts +4 -0
  10. package/dist/applyToYjs/node/removeNode.d.ts +4 -0
  11. package/dist/applyToYjs/node/setNode.d.ts +4 -0
  12. package/dist/applyToYjs/node/splitNode.d.ts +4 -0
  13. package/dist/applyToYjs/text/index.d.ts +4 -0
  14. package/dist/applyToYjs/text/insertText.d.ts +4 -0
  15. package/dist/applyToYjs/text/removeText.d.ts +4 -0
  16. package/dist/applyToYjs/types.d.ts +9 -0
  17. package/dist/index.cjs +1360 -0
  18. package/dist/index.cjs.map +1 -0
  19. package/dist/index.d.ts +6 -0
  20. package/dist/index.global.js +10365 -0
  21. package/dist/index.global.js.map +1 -0
  22. package/dist/index.js +1338 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/model/types.d.ts +38 -0
  25. package/dist/plugins/index.d.ts +4 -0
  26. package/dist/plugins/withCursors.d.ts +39 -0
  27. package/dist/plugins/withYHistory.d.ts +20 -0
  28. package/dist/plugins/withYjs.d.ts +43 -0
  29. package/dist/utils/clone.d.ts +5 -0
  30. package/dist/utils/convert.d.ts +8 -0
  31. package/dist/utils/delta.d.ts +8 -0
  32. package/dist/utils/errors.d.ts +2 -0
  33. package/dist/utils/location.d.ts +12 -0
  34. package/dist/utils/object.d.ts +10 -0
  35. package/dist/utils/position.d.ts +20 -0
  36. package/dist/utils/slate.d.ts +3 -0
  37. package/dist/utils/yjs.d.ts +5 -0
  38. package/package.json +47 -0
  39. package/src/applyToSlate/index.ts +118 -0
  40. package/src/applyToSlate/textEvent.ts +280 -0
  41. package/src/applyToYjs/index.ts +28 -0
  42. package/src/applyToYjs/node/index.ts +17 -0
  43. package/src/applyToYjs/node/insertNode.ts +23 -0
  44. package/src/applyToYjs/node/mergeNode.ts +82 -0
  45. package/src/applyToYjs/node/moveNode.ts +57 -0
  46. package/src/applyToYjs/node/removeNode.ts +16 -0
  47. package/src/applyToYjs/node/setNode.ts +42 -0
  48. package/src/applyToYjs/node/splitNode.ts +98 -0
  49. package/src/applyToYjs/text/index.ts +9 -0
  50. package/src/applyToYjs/text/insertText.ts +27 -0
  51. package/src/applyToYjs/text/removeText.ts +16 -0
  52. package/src/applyToYjs/types.ts +12 -0
  53. package/src/index.ts +47 -0
  54. package/src/model/types.ts +50 -0
  55. package/src/plugins/index.ts +3 -0
  56. package/src/plugins/withCursors.ts +269 -0
  57. package/src/plugins/withYHistory.ts +183 -0
  58. package/src/plugins/withYjs.ts +284 -0
  59. package/src/utils/clone.ts +29 -0
  60. package/src/utils/convert.ts +48 -0
  61. package/src/utils/delta.ts +97 -0
  62. package/src/utils/errors.ts +20 -0
  63. package/src/utils/location.ts +157 -0
  64. package/src/utils/object.ts +93 -0
  65. package/src/utils/position.ts +300 -0
  66. package/src/utils/slate.ts +11 -0
  67. package/src/utils/yjs.ts +10 -0
  68. package/test/collaboration/addMark/acrossMarks.tsx +40 -0
  69. package/test/collaboration/addMark/acrossMarksSame.tsx +36 -0
  70. package/test/collaboration/addMark/atBeginningOfDocument.tsx +27 -0
  71. package/test/collaboration/addMark/atEndOfDocument.tsx +30 -0
  72. package/test/collaboration/addMark/withOtherMarks.tsx +31 -0
  73. package/test/collaboration/insertNode/atBeginningOfDocument.tsx +28 -0
  74. package/test/collaboration/insertNode/atEndOfDocument.tsx +28 -0
  75. package/test/collaboration/insertNode/inTheMiddle.tsx +30 -0
  76. package/test/collaboration/insertText/atBeginningOfBlock.tsx +26 -0
  77. package/test/collaboration/insertText/atBeginningOfDocument.tsx +26 -0
  78. package/test/collaboration/insertText/atEndOfBlock.tsx +26 -0
  79. package/test/collaboration/insertText/atEndOfDocument.tsx +26 -0
  80. package/test/collaboration/insertText/inTheMiddle.tsx +32 -0
  81. package/test/collaboration/insertText/inTheMiddleOfNestedBlock.tsx +30 -0
  82. package/test/collaboration/insertText/insideMarks.tsx +28 -0
  83. package/test/collaboration/insertText/withEmptyString.tsx +25 -0
  84. package/test/collaboration/insertText/withEntities.tsx +28 -0
  85. package/test/collaboration/insertText/withMarks.tsx +25 -0
  86. package/test/collaboration/insertText/withUnicode.tsx +28 -0
  87. package/test/collaboration/mergeNode/afterADeleteBackward.tsx +27 -0
  88. package/test/collaboration/mergeNode/inSameParent.tsx +34 -0
  89. package/test/collaboration/mergeNode/onMixedNestedNodes.tsx +29 -0
  90. package/test/collaboration/mergeNode/onMixedTypeNodes.tsx +27 -0
  91. package/test/collaboration/mergeNode/withUnicode.tsx +25 -0
  92. package/test/collaboration/moveNode/downward/whenBlockBecomesNested.tsx +43 -0
  93. package/test/collaboration/moveNode/downward/whenBlockBecomesNonNested.tsx +41 -0
  94. package/test/collaboration/moveNode/downward/whenBlockStaysNested.tsx +38 -0
  95. package/test/collaboration/moveNode/downward/whenBlockStaysNonNested.tsx +30 -0
  96. package/test/collaboration/moveNode/upward/whenBlockBecomesNested.tsx +43 -0
  97. package/test/collaboration/moveNode/upward/whenBlockBecomesNonNested.tsx +41 -0
  98. package/test/collaboration/moveNode/upward/whenBlockStaysNested.tsx +38 -0
  99. package/test/collaboration/moveNode/upward/whenBlockStaysNonNested.tsx +30 -0
  100. package/test/collaboration/removeMark/inTheMiddleOfText.tsx +43 -0
  101. package/test/collaboration/removeMark/withAddMark.tsx +31 -0
  102. package/test/collaboration/removeMark/withOtherMarks.tsx +47 -0
  103. package/test/collaboration/removeNode/atBeginningOfDocument.tsx +26 -0
  104. package/test/collaboration/removeNode/atEndOfDocument.tsx +26 -0
  105. package/test/collaboration/removeNode/nestedBlock.tsx +28 -0
  106. package/test/collaboration/removeNode/wrapperBlock.tsx +28 -0
  107. package/test/collaboration/removeText/atBeginningOfDocument.tsx +34 -0
  108. package/test/collaboration/removeText/atEndOfDocument.tsx +37 -0
  109. package/test/collaboration/removeText/withUnicode.tsx +29 -0
  110. package/test/collaboration/setNode/atBeginningOfDocument.tsx +27 -0
  111. package/test/collaboration/setNode/atEndOfDocument.tsx +27 -0
  112. package/test/collaboration/setNode/onDataChange.tsx +35 -0
  113. package/test/collaboration/setNode/onDataChangeOnInline.tsx +35 -0
  114. package/test/collaboration/setNode/onResetBlock.tsx +27 -0
  115. package/test/collaboration/setNode/withAChangeOfType.tsx +26 -0
  116. package/test/collaboration/splitNode/atBeginningOfDocument.tsx +28 -0
  117. package/test/collaboration/splitNode/atEndOfBlock.tsx +27 -0
  118. package/test/collaboration/splitNode/atEndOfDocument.tsx +27 -0
  119. package/test/collaboration/splitNode/onNonDefaultBlock.tsx +27 -0
  120. package/test/collaboration/splitNode/withMultipleSubNodes.tsx +32 -0
  121. package/test/collaboration/splitNode/withUnicode.tsx +29 -0
  122. package/test/index.test.ts +65 -0
  123. package/test/slate.d.ts +8 -0
  124. package/test/withTestingElements.ts +46 -0
  125. package/tsconfig.json +11 -0
  126. package/tsup.config.ts +32 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugins/withYjs.ts","../src/applyToSlate/index.ts","../src/utils/convert.ts","../src/utils/object.ts","../src/utils/delta.ts","../src/utils/slate.ts","../src/utils/errors.ts","../src/utils/position.ts","../src/utils/location.ts","../src/utils/yjs.ts","../src/applyToSlate/textEvent.ts","../src/applyToYjs/node/insertNode.ts","../src/applyToYjs/node/mergeNode.ts","../src/utils/clone.ts","../src/applyToYjs/node/moveNode.ts","../src/applyToYjs/node/removeNode.ts","../src/applyToYjs/node/setNode.ts","../src/applyToYjs/node/splitNode.ts","../src/applyToYjs/node/index.ts","../src/applyToYjs/text/insertText.ts","../src/applyToYjs/text/removeText.ts","../src/applyToYjs/text/index.ts","../src/applyToYjs/index.ts","../src/plugins/withYHistory.ts","../src/plugins/withCursors.ts"],"sourcesContent":["import { BaseEditor, Descendant, Editor, Operation, Point } from 'slate';\nimport * as Y from 'yjs';\nimport { applyYjsEvents } from '../applyToSlate';\nimport { applySlateOp } from '../applyToYjs';\nimport { yTextToSlateElement } from '../utils/convert';\nimport {\n getStoredPosition,\n getStoredPositions,\n relativePositionToSlatePoint,\n removeStoredPosition,\n setStoredPosition,\n slatePointToRelativePosition,\n} from '../utils/position';\nimport { assertDocumentAttachment } from '../utils/yjs';\n\ntype LocalChange = {\n op: Operation;\n doc: Descendant[];\n origin: unknown;\n};\n\nconst DEFAULT_LOCAL_ORIGIN = Symbol('slate-yjs-operation');\nconst DEFAULT_POSITION_STORAGE_ORIGIN = Symbol('slate-yjs-position-storage');\n\nconst ORIGIN: WeakMap<Editor, unknown> = new WeakMap();\nconst LOCAL_CHANGES: WeakMap<Editor, LocalChange[]> = new WeakMap();\nconst CONNECTED: WeakSet<Editor> = new WeakSet();\n\nexport type YjsEditor = BaseEditor & {\n sharedRoot: Y.XmlText;\n\n localOrigin: unknown;\n positionStorageOrigin: unknown;\n\n applyRemoteEvents: (events: Y.YEvent<Y.XmlText>[], origin: unknown) => void;\n\n storeLocalChange: (op: Operation) => void;\n flushLocalChanges: () => void;\n\n isLocalOrigin: (origin: unknown) => boolean;\n\n connect: () => void;\n disconnect: () => void;\n};\n\nexport const YjsEditor = {\n isYjsEditor(value: unknown): value is YjsEditor {\n return (\n Editor.isEditor(value) &&\n (value as YjsEditor).sharedRoot instanceof Y.XmlText &&\n 'localOrigin' in value &&\n 'positionStorageOrigin' in value &&\n typeof (value as YjsEditor).applyRemoteEvents === 'function' &&\n typeof (value as YjsEditor).storeLocalChange === 'function' &&\n typeof (value as YjsEditor).flushLocalChanges === 'function' &&\n typeof (value as YjsEditor).isLocalOrigin === 'function' &&\n typeof (value as YjsEditor).connect === 'function' &&\n typeof (value as YjsEditor).disconnect === 'function'\n );\n },\n\n localChanges(editor: YjsEditor): LocalChange[] {\n return LOCAL_CHANGES.get(editor) ?? [];\n },\n\n applyRemoteEvents(\n editor: YjsEditor,\n events: Y.YEvent<Y.XmlText>[],\n origin: unknown\n ): void {\n editor.applyRemoteEvents(events, origin);\n },\n\n storeLocalChange(editor: YjsEditor, op: Operation): void {\n editor.storeLocalChange(op);\n },\n\n flushLocalChanges(editor: YjsEditor): void {\n editor.flushLocalChanges();\n },\n\n connected(editor: YjsEditor): boolean {\n return CONNECTED.has(editor);\n },\n\n connect(editor: YjsEditor): void {\n editor.connect();\n },\n\n disconnect(editor: YjsEditor): void {\n editor.disconnect();\n },\n\n isLocal(editor: YjsEditor): boolean {\n return editor.isLocalOrigin(YjsEditor.origin(editor));\n },\n\n origin(editor: YjsEditor): unknown {\n const origin = ORIGIN.get(editor);\n return origin !== undefined ? origin : editor.localOrigin;\n },\n\n withOrigin(editor: YjsEditor, origin: unknown, fn: () => void): void {\n const prev = YjsEditor.origin(editor);\n ORIGIN.set(editor, origin);\n fn();\n ORIGIN.set(editor, prev);\n },\n\n storePosition(editor: YjsEditor, key: string, point: Point): void {\n const { sharedRoot, positionStorageOrigin: locationStorageOrigin } = editor;\n assertDocumentAttachment(sharedRoot);\n\n const position = slatePointToRelativePosition(sharedRoot, editor, point);\n\n sharedRoot.doc.transact(() => {\n setStoredPosition(sharedRoot, key, position);\n }, locationStorageOrigin);\n },\n\n removeStoredPosition(editor: YjsEditor, key: string): void {\n const { sharedRoot, positionStorageOrigin: locationStorageOrigin } = editor;\n assertDocumentAttachment(sharedRoot);\n\n sharedRoot.doc.transact(() => {\n removeStoredPosition(sharedRoot, key);\n }, locationStorageOrigin);\n },\n\n position(editor: YjsEditor, key: string): Point | null | undefined {\n const position = getStoredPosition(editor.sharedRoot, key);\n if (!position) {\n return undefined;\n }\n\n return relativePositionToSlatePoint(editor.sharedRoot, editor, position);\n },\n\n storedPositionsRelative(\n editor: YjsEditor\n ): Record<string, Y.RelativePosition> {\n return getStoredPositions(editor.sharedRoot);\n },\n};\n\nexport type WithYjsOptions = {\n autoConnect?: boolean;\n\n // Origin used when applying local slate operations to yjs\n localOrigin?: unknown;\n\n // Origin used when storing positions\n positionStorageOrigin?: unknown;\n};\n\nexport function withYjs<T extends Editor>(\n editor: T,\n sharedRoot: Y.XmlText,\n {\n localOrigin,\n positionStorageOrigin,\n autoConnect = false,\n }: WithYjsOptions = {}\n): T & YjsEditor {\n const e = editor as T & YjsEditor;\n\n e.sharedRoot = sharedRoot;\n\n e.localOrigin = localOrigin ?? DEFAULT_LOCAL_ORIGIN;\n e.positionStorageOrigin =\n positionStorageOrigin ?? DEFAULT_POSITION_STORAGE_ORIGIN;\n\n e.applyRemoteEvents = (events, origin) => {\n YjsEditor.flushLocalChanges(e);\n\n Editor.withoutNormalizing(e, () => {\n YjsEditor.withOrigin(e, origin, () => {\n applyYjsEvents(e.sharedRoot, e, events);\n });\n });\n };\n\n e.isLocalOrigin = (origin) => origin === e.localOrigin;\n\n const handleYEvents = (\n events: Y.YEvent<Y.XmlText>[],\n transaction: Y.Transaction\n ) => {\n if (e.isLocalOrigin(transaction.origin)) {\n return;\n }\n\n YjsEditor.applyRemoteEvents(e, events, transaction.origin);\n };\n\n let autoConnectTimeoutId: ReturnType<typeof setTimeout> | null = null;\n if (autoConnect) {\n autoConnectTimeoutId = setTimeout(() => {\n autoConnectTimeoutId = null;\n YjsEditor.connect(e);\n });\n }\n\n e.connect = () => {\n if (YjsEditor.connected(e)) {\n throw new Error('already connected');\n }\n\n e.sharedRoot.observeDeep(handleYEvents);\n const content = yTextToSlateElement(e.sharedRoot);\n e.children = content.children;\n CONNECTED.add(e);\n\n Editor.normalize(editor, { force: true });\n if (!editor.operations.length) {\n editor.onChange();\n }\n };\n\n e.disconnect = () => {\n if (autoConnectTimeoutId) {\n clearTimeout(autoConnectTimeoutId);\n }\n\n YjsEditor.flushLocalChanges(e);\n e.sharedRoot.unobserveDeep(handleYEvents);\n CONNECTED.delete(e);\n };\n\n e.storeLocalChange = (op) => {\n LOCAL_CHANGES.set(e, [\n ...YjsEditor.localChanges(e),\n { op, doc: editor.children, origin: YjsEditor.origin(e) },\n ]);\n };\n\n e.flushLocalChanges = () => {\n assertDocumentAttachment(e.sharedRoot);\n const localChanges = YjsEditor.localChanges(e);\n LOCAL_CHANGES.delete(e);\n\n // Group local changes by origin so we can apply them in the correct order\n // with the correct origin with a minimal amount of transactions.\n const txGroups: LocalChange[][] = [];\n localChanges.forEach((change) => {\n const currentGroup = txGroups[txGroups.length - 1];\n if (currentGroup && currentGroup[0].origin === change.origin) {\n return currentGroup.push(change);\n }\n\n txGroups.push([change]);\n });\n\n txGroups.forEach((txGroup) => {\n assertDocumentAttachment(e.sharedRoot);\n\n e.sharedRoot.doc.transact(() => {\n txGroup.forEach((change) => {\n assertDocumentAttachment(e.sharedRoot);\n applySlateOp(e.sharedRoot, { children: change.doc }, change.op);\n });\n }, txGroup[0].origin);\n });\n };\n\n const { apply, onChange } = e;\n e.apply = (op) => {\n if (YjsEditor.connected(e) && YjsEditor.isLocal(e)) {\n YjsEditor.storeLocalChange(e, op);\n }\n\n apply(op);\n };\n\n e.onChange = () => {\n if (YjsEditor.connected(e)) {\n YjsEditor.flushLocalChanges(e);\n }\n\n onChange();\n };\n\n return e;\n}\n","import { Editor, Operation, Transforms } from 'slate';\nimport * as Y from 'yjs';\nimport { RelativeRange } from '../model/types';\nimport { yTextToSlateElement } from '../utils/convert';\nimport { isSyncSkewError } from '../utils/errors';\nimport {\n relativeRangeToSlateRange,\n slateRangeToRelativeRange,\n} from '../utils/position';\nimport { translateYTextEvent } from './textEvent';\n\nlet lastResyncTime = 0;\nconst RESYNC_THROTTLE_MS = 1000;\n\n/**\n * Translate a yjs event into slate operations. The editor state has to match the\n * yText state before the event occurred.\n *\n * @param sharedType\n * @param op\n */\nexport function translateYjsEvent(\n sharedRoot: Y.XmlText,\n editor: Editor,\n event: Y.YEvent<Y.XmlText>\n): Operation[] {\n if (event instanceof Y.YTextEvent) {\n return translateYTextEvent(sharedRoot, editor, event);\n }\n\n throw new Error('Unexpected Y event type');\n}\n\n/**\n * Performs a full re-sync of the Slate editor from the Yjs shared root.\n * Preserves the user's selection if possible by converting to/from relative positions.\n */\nfunction resyncFromYjs(sharedRoot: Y.XmlText, editor: Editor): void {\n let savedSelection: RelativeRange | null = null;\n\n try {\n if (editor.selection) {\n savedSelection = slateRangeToRelativeRange(\n sharedRoot,\n editor,\n editor.selection\n );\n }\n } catch {\n // Selection conversion failed; we'll lose the selection but continue with re-sync\n }\n\n const content = yTextToSlateElement(sharedRoot);\n editor.children = content.children;\n Editor.normalize(editor, { force: true });\n\n if (savedSelection) {\n try {\n const newSelection = relativeRangeToSlateRange(\n sharedRoot,\n editor,\n savedSelection\n );\n if (newSelection) {\n Transforms.select(editor, newSelection);\n }\n } catch {\n // Selection restoration failed; cursor position is lost but document is correct\n }\n }\n}\n\n/**\n * Translates yjs events into slate operations and applies them to the editor. The\n * editor state has to match the yText state before the events occurred.\n *\n * If a sync-skew error occurs (e.g. invalid path due to Yjs/Slate mismatch),\n * the editor is re-synced from the Yjs shared root to recover gracefully.\n *\n * @param sharedRoot\n * @param editor\n * @param events\n */\nexport function applyYjsEvents(\n sharedRoot: Y.XmlText,\n editor: Editor,\n events: Y.YEvent<Y.XmlText>[]\n) {\n Editor.withoutNormalizing(editor, () => {\n for (const event of events) {\n try {\n const ops = translateYjsEvent(sharedRoot, editor, event);\n for (const op of ops) {\n editor.apply(op);\n }\n } catch (error) {\n if (isSyncSkewError(error)) {\n const now = Date.now();\n if (now - lastResyncTime >= RESYNC_THROTTLE_MS) {\n lastResyncTime = now;\n console.warn(\n '[slate-yjs] Sync skew detected, re-syncing from Yjs:',\n error instanceof Error ? error.message : error\n );\n resyncFromYjs(sharedRoot, editor);\n } else {\n console.warn(\n '[slate-yjs] Sync skew detected (throttled, skipping re-sync):',\n error instanceof Error ? error.message : error\n );\n }\n return;\n }\n throw error;\n }\n }\n });\n}\n","import { Element, Node, Text } from 'slate';\nimport * as Y from 'yjs';\nimport { DeltaInsert, InsertDelta } from '../model/types';\nimport { yTextToInsertDelta } from './delta';\nimport { getProperties } from './slate';\n\nexport function yTextToSlateElement(yText: Y.XmlText): Element {\n const delta = yTextToInsertDelta(yText);\n\n const children =\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n delta.length > 0 ? delta.map(deltaInsertToSlateNode) : [{ text: '' }];\n\n return { ...yText.getAttributes(), children };\n}\n\nexport function deltaInsertToSlateNode(insert: DeltaInsert): Node {\n if (typeof insert.insert === 'string') {\n return { ...insert.attributes, text: insert.insert };\n }\n\n return yTextToSlateElement(insert.insert);\n}\n\nexport function slateNodesToInsertDelta(nodes: Node[]): InsertDelta {\n return nodes.map((node) => {\n if (Text.isText(node)) {\n return { insert: node.text, attributes: getProperties(node) };\n }\n\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n return { insert: slateElementToYText(node) };\n });\n}\n\nexport function slateElementToYText({\n children,\n ...attributes\n}: Element): Y.XmlText {\n const yElement = new Y.XmlText();\n\n Object.entries(attributes).forEach(([key, value]) => {\n yElement.setAttribute(key, value);\n });\n\n yElement.applyDelta(slateNodesToInsertDelta(children), { sanitize: false });\n return yElement;\n}\n","type InspectableObject = Record<string | number | symbol, unknown>;\n\nfunction isObject(o: unknown): o is InspectableObject {\n return Object.prototype.toString.call(o) === '[object Object]';\n}\n\nexport function isPlainObject(o: unknown): o is InspectableObject {\n if (!isObject(o)) {\n return false;\n }\n\n // If has modified constructor\n const ctor = o.constructor;\n if (ctor === undefined) {\n return true;\n }\n\n // If has modified prototype\n const prot = ctor.prototype;\n if (isObject(prot) === false) {\n return false;\n }\n\n // If constructor does not have an Object-specific method\n if (prot.hasOwnProperty('isPrototypeOf') === false) {\n return false;\n }\n\n // Most likely a plain Object\n return true;\n}\n\n// Slates deep equality function: https://github.com/ianstormtaylor/slate/blob/68aff89e892fe15a16314398ff052ade6068900b/packages/slate/src/utils/deep-equal.ts#L13\n// We have to match slates deepEquals behavior to merge insert deltas in the same way slate does.\nexport function deepEquals(\n node: InspectableObject,\n another: InspectableObject\n): boolean {\n // eslint-disable-next-line guard-for-in\n for (const key in node) {\n const a = node[key];\n const b = another[key];\n\n if (isPlainObject(a) && isPlainObject(b)) {\n if (!deepEquals(a, b)) {\n return false;\n }\n } else if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n } else if (a !== b) {\n return false;\n }\n }\n\n for (const key in another) {\n if (node[key] === undefined && another[key] !== undefined) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function pick<TObj, TKeys extends keyof TObj>(\n obj: TObj,\n ...keys: TKeys[]\n): Pick<TObj, TKeys> {\n return Object.fromEntries(\n Object.entries(obj).filter(([key]) => keys.includes(key as TKeys))\n ) as Pick<TObj, TKeys>;\n}\n\nexport function omit<TObj, TKeys extends keyof TObj>(\n obj: TObj,\n ...keys: TKeys[]\n): Omit<TObj, TKeys> {\n return Object.fromEntries(\n Object.entries(obj).filter(([key]) => !keys.includes(key as TKeys))\n ) as Omit<TObj, TKeys>;\n}\n\nexport function omitNullEntries<TObj>(obj: TObj): {\n [K in keyof TObj]: TObj[K] extends null ? never : K;\n} {\n return Object.fromEntries(\n Object.entries(obj).filter(([, value]) => value !== null)\n ) as { [K in keyof TObj]: TObj[K] extends null ? never : K };\n}\n","import * as Y from 'yjs';\nimport { DeltaInsert, InsertDelta } from '../model/types';\nimport { deepEquals } from './object';\n\nexport function normalizeInsertDelta(delta: InsertDelta): InsertDelta {\n const normalized: InsertDelta = [];\n\n for (const element of delta) {\n if (typeof element.insert === 'string' && element.insert.length === 0) {\n continue;\n }\n\n const prev = normalized[normalized.length - 1];\n if (\n !prev ||\n typeof prev.insert !== 'string' ||\n typeof element.insert !== 'string'\n ) {\n normalized.push(element);\n continue;\n }\n\n const merge =\n prev.attributes === element.attributes ||\n (!prev.attributes === !element.attributes &&\n deepEquals(prev.attributes ?? {}, element.attributes ?? {}));\n\n if (merge) {\n prev.insert += element.insert;\n continue;\n }\n\n normalized.push(element);\n }\n\n return normalized;\n}\n\nexport function yTextToInsertDelta(yText: Y.XmlText): InsertDelta {\n return normalizeInsertDelta(yText.toDelta());\n}\n\nexport function getInsertLength({ insert }: DeltaInsert): number {\n return typeof insert === 'string' ? insert.length : 1;\n}\n\nexport function getInsertDeltaLength(delta: InsertDelta): number {\n return delta.reduce((curr, element) => curr + getInsertLength(element), 0);\n}\n\nexport function sliceInsertDelta(\n delta: InsertDelta,\n start: number,\n length: number\n): InsertDelta {\n if (length < 1) {\n return [];\n }\n\n let currentOffset = 0;\n const sliced: InsertDelta = [];\n const end = start + length;\n\n for (let i = 0; i < delta.length; i++) {\n if (currentOffset >= end) {\n break;\n }\n\n const element = delta[i];\n const elementLength = getInsertLength(element);\n\n if (currentOffset + elementLength <= start) {\n currentOffset += elementLength;\n continue;\n }\n\n if (typeof element.insert !== 'string') {\n currentOffset += elementLength;\n sliced.push(element);\n continue;\n }\n\n const startOffset = Math.max(0, start - currentOffset);\n const endOffset = Math.min(\n elementLength,\n elementLength - (currentOffset + elementLength - end)\n );\n\n sliced.push({\n ...element,\n insert: element.insert.slice(startOffset, endOffset),\n });\n currentOffset += elementLength;\n }\n\n return sliced;\n}\n","import { BaseText, Descendant, Text } from 'slate';\nimport { omit } from './object';\n\nexport function getProperties<TNode extends Descendant>(\n node: TNode\n): Omit<TNode, TNode extends BaseText ? 'text' : 'children'> {\n return omit(\n node,\n (Text.isText(node) ? 'text' : 'children') as keyof TNode\n ) as Omit<TNode, TNode extends BaseText ? 'text' : 'children'>;\n}\n","const SYNC_SKEW_ERROR_PATTERNS = [\n 'Cannot find a descendant at path',\n 'yOffset out of bounds',\n 'Cannot descent into slate text',\n \"yText isn't a descendant of root element\",\n \"Path doesn't match yText\",\n 'Unexpected y parent type',\n 'Path has to a have a length >= 1',\n 'yTarget spans multiple nodes',\n];\n\nexport function isSyncSkewError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n\n return SYNC_SKEW_ERROR_PATTERNS.some((pattern) =>\n error.message.includes(pattern)\n );\n}\n","import { BasePoint, BaseRange, Node, Text } from 'slate';\nimport * as Y from 'yjs';\nimport { InsertDelta, RelativeRange, TextRange } from '../model/types';\nimport { getInsertDeltaLength, yTextToInsertDelta } from './delta';\nimport { isSyncSkewError } from './errors';\nimport { getSlatePath, getYTarget, yOffsetToSlateOffsets } from './location';\nimport { assertDocumentAttachment } from './yjs';\n\nexport const STORED_POSITION_PREFIX = '__slateYjsStoredPosition_';\n\nexport function slatePointToRelativePosition(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n point: BasePoint\n): Y.RelativePosition {\n const { yTarget, yParent, textRange } = getYTarget(\n sharedRoot,\n slateRoot,\n point.path\n );\n\n if (yTarget) {\n throw new Error(\n 'Slate point points to a non-text element inside sharedRoot'\n );\n }\n\n const index = textRange.start + point.offset;\n return Y.createRelativePositionFromTypeIndex(\n yParent,\n index,\n index === textRange.end ? -1 : 0\n );\n}\n\nexport function absolutePositionToSlatePoint(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n { type, index, assoc }: Y.AbsolutePosition\n): BasePoint | null {\n if (!(type instanceof Y.XmlText)) {\n throw new Error('Absolute position points to a non-XMLText');\n }\n\n try {\n const parentPath = getSlatePath(sharedRoot, slateRoot, type);\n const parent = Node.get(slateRoot, parentPath);\n\n if (Text.isText(parent)) {\n return null;\n }\n\n const [pathOffset, textOffset] = yOffsetToSlateOffsets(parent, index, {\n assoc,\n });\n\n const target = parent.children[pathOffset];\n if (!Text.isText(target)) {\n return null;\n }\n\n return { path: [...parentPath, pathOffset], offset: textOffset };\n } catch (error) {\n if (isSyncSkewError(error)) {\n return null;\n }\n throw error;\n }\n}\n\nexport function relativePositionToSlatePoint(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n pos: Y.RelativePosition\n): BasePoint | null {\n if (!sharedRoot.doc) {\n throw new Error(\"sharedRoot isn't attach to a yDoc\");\n }\n\n const absPos = Y.createAbsolutePositionFromRelativePosition(\n pos,\n sharedRoot.doc\n );\n\n return absPos && absolutePositionToSlatePoint(sharedRoot, slateRoot, absPos);\n}\n\nexport function getStoredPosition(\n sharedRoot: Y.XmlText,\n key: string\n): Y.RelativePosition | null {\n const rawPosition = sharedRoot.getAttribute(STORED_POSITION_PREFIX + key);\n if (!rawPosition) {\n return null;\n }\n\n return Y.decodeRelativePosition(rawPosition);\n}\n\nexport function getStoredPositions(\n sharedRoot: Y.XmlText\n): Record<string, Y.RelativePosition> {\n return Object.fromEntries(\n Object.entries(sharedRoot.getAttributes())\n .filter(([key]) => key.startsWith(STORED_POSITION_PREFIX))\n .map(([key, position]) => [\n key.slice(STORED_POSITION_PREFIX.length),\n Y.createRelativePositionFromJSON(position),\n ])\n );\n}\n\nfunction getStoredPositionsAbsolute(sharedRoot: Y.XmlText) {\n assertDocumentAttachment(sharedRoot);\n\n return Object.fromEntries(\n Object.entries(sharedRoot.getAttributes())\n .filter(([key]) => key.startsWith(STORED_POSITION_PREFIX))\n .map(\n ([key, position]) =>\n [\n key.slice(STORED_POSITION_PREFIX.length),\n Y.createAbsolutePositionFromRelativePosition(\n Y.decodeRelativePosition(position),\n sharedRoot.doc\n ),\n ] as const\n )\n .filter(([, position]) => position)\n ) as Record<string, Y.AbsolutePosition>;\n}\n\nexport function removeStoredPosition(sharedRoot: Y.XmlText, key: string) {\n sharedRoot.removeAttribute(STORED_POSITION_PREFIX + key);\n}\n\nexport function setStoredPosition(\n sharedRoot: Y.XmlText,\n key: string,\n position: Y.RelativePosition\n) {\n sharedRoot.setAttribute(\n STORED_POSITION_PREFIX + key,\n Y.encodeRelativePosition(position)\n );\n}\n\nfunction getAbsolutePositionsInTextRange(\n absolutePositions: Record<string, Y.AbsolutePosition>,\n yTarget: Y.XmlText,\n textRange?: TextRange\n) {\n return Object.fromEntries(\n Object.entries(absolutePositions).filter(([, position]) => {\n if (position.type !== yTarget) {\n return false;\n }\n\n if (!textRange) {\n return true;\n }\n\n return position.assoc >= 0\n ? position.index >= textRange.start && position.index < textRange.end\n : position.index > textRange.start && position.index >= textRange.end;\n })\n );\n}\n\nfunction getAbsolutePositionsInYText(\n absolutePositions: Record<string, Y.AbsolutePosition>,\n yText: Y.XmlText,\n parentPath = ''\n): Record<string, Record<string, Y.AbsolutePosition>> {\n const positions = {\n [parentPath]: getAbsolutePositionsInTextRange(absolutePositions, yText),\n };\n\n const insertDelta = yTextToInsertDelta(yText);\n insertDelta.forEach(({ insert }, i) => {\n if (insert instanceof Y.XmlText) {\n Object.assign(\n positions,\n getAbsolutePositionsInYText(\n absolutePositions,\n insert,\n parentPath ? `${parentPath}.${i}` : i.toString()\n )\n );\n }\n });\n\n return positions;\n}\n\nexport function getStoredPositionsInDeltaAbsolute(\n sharedRoot: Y.XmlText,\n yText: Y.XmlText,\n delta: InsertDelta,\n deltaOffset = 0\n) {\n const absolutePositions = getStoredPositionsAbsolute(sharedRoot);\n\n const positions = {\n '': getAbsolutePositionsInTextRange(absolutePositions, yText, {\n start: deltaOffset,\n end: deltaOffset + getInsertDeltaLength(delta),\n }),\n };\n\n delta.forEach(({ insert }, i) => {\n if (insert instanceof Y.XmlText) {\n Object.assign(\n positions,\n getAbsolutePositionsInYText(absolutePositions, insert, i.toString())\n );\n }\n });\n\n return positions;\n}\n\nexport function restoreStoredPositionsWithDeltaAbsolute(\n sharedRoot: Y.XmlText,\n yText: Y.XmlText,\n absolutePositions: Record<string, Record<string, Y.AbsolutePosition>>,\n delta: InsertDelta,\n newDeltaOffset = 0,\n previousDeltaOffset = 0,\n path = ''\n) {\n const toRestore = absolutePositions[path];\n\n if (toRestore) {\n Object.entries(toRestore).forEach(([key, position]) => {\n setStoredPosition(\n sharedRoot,\n key,\n Y.createRelativePositionFromTypeIndex(\n yText,\n position.index - previousDeltaOffset + newDeltaOffset,\n position.assoc\n )\n );\n });\n }\n\n delta.forEach(({ insert }, i) => {\n if (insert instanceof Y.XmlText) {\n restoreStoredPositionsWithDeltaAbsolute(\n sharedRoot,\n insert,\n absolutePositions,\n yTextToInsertDelta(insert),\n 0,\n 0,\n path ? `${path}.${i}` : i.toString()\n );\n }\n });\n}\n\nexport function slateRangeToRelativeRange(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n range: BaseRange\n): RelativeRange {\n return {\n anchor: slatePointToRelativePosition(sharedRoot, slateRoot, range.anchor),\n focus: slatePointToRelativePosition(sharedRoot, slateRoot, range.focus),\n };\n}\n\nexport function relativeRangeToSlateRange(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n range: RelativeRange\n): BaseRange | null {\n const anchor = relativePositionToSlatePoint(\n sharedRoot,\n slateRoot,\n range.anchor\n );\n\n if (!anchor) {\n return null;\n }\n\n const focus = relativePositionToSlatePoint(\n sharedRoot,\n slateRoot,\n range.focus\n );\n\n if (!focus) {\n return null;\n }\n\n return { anchor, focus };\n}\n","import { Element, Node, Path, Text } from 'slate';\nimport * as Y from 'yjs';\nimport { YTarget } from '../model/types';\nimport { sliceInsertDelta, yTextToInsertDelta } from './delta';\n\nexport function getSlateNodeYLength(node: Node | undefined): number {\n if (!node) {\n return 0;\n }\n\n return Text.isText(node) ? node.text.length : 1;\n}\n\nexport function slatePathOffsetToYOffset(element: Element, pathOffset: number) {\n return element.children\n .slice(0, pathOffset)\n .reduce((yOffset, node) => yOffset + getSlateNodeYLength(node), 0);\n}\n\nexport function getYTarget(\n yRoot: Y.XmlText,\n slateRoot: Node,\n path: Path\n): YTarget {\n if (path.length === 0) {\n throw new Error('Path has to a have a length >= 1');\n }\n\n if (Text.isText(slateRoot)) {\n throw new Error('Cannot descent into slate text');\n }\n\n const [pathOffset, ...childPath] = path;\n\n const yOffset = slatePathOffsetToYOffset(slateRoot, pathOffset);\n const targetNode = slateRoot.children[pathOffset];\n\n const delta = yTextToInsertDelta(yRoot);\n const targetLength = getSlateNodeYLength(targetNode);\n\n const targetDelta = sliceInsertDelta(delta, yOffset, targetLength);\n if (targetDelta.length > 1) {\n throw new Error(\"Path doesn't match yText, yTarget spans multiple nodes\");\n }\n\n const yTarget = targetDelta[0]?.insert;\n if (childPath.length > 0) {\n if (!(yTarget instanceof Y.XmlText)) {\n throw new Error(\n \"Path doesn't match yText, cannot descent into non-yText\"\n );\n }\n\n return getYTarget(yTarget, targetNode, childPath);\n }\n\n return {\n yParent: yRoot,\n textRange: { start: yOffset, end: yOffset + targetLength },\n yTarget: yTarget instanceof Y.XmlText ? yTarget : undefined,\n slateParent: slateRoot,\n slateTarget: targetNode,\n targetDelta,\n };\n}\n\nexport function yOffsetToSlateOffsets(\n parent: Element,\n yOffset: number,\n opts: { assoc?: number; insert?: boolean } = {}\n): [number, number] {\n const { assoc = 0, insert = false } = opts;\n\n let currentOffset = 0;\n let lastNonEmptyPathOffset = 0;\n for (let pathOffset = 0; pathOffset < parent.children.length; pathOffset++) {\n const child = parent.children[pathOffset];\n const nodeLength = Text.isText(child) ? child.text.length : 1;\n\n if (nodeLength > 0) {\n lastNonEmptyPathOffset = pathOffset;\n }\n\n const endOffset = currentOffset + nodeLength;\n if (\n nodeLength > 0 &&\n (assoc >= 0 ? endOffset > yOffset : endOffset >= yOffset)\n ) {\n return [pathOffset, yOffset - currentOffset];\n }\n\n currentOffset += nodeLength;\n }\n\n if (yOffset > currentOffset + (insert ? 1 : 0)) {\n throw new Error('yOffset out of bounds');\n }\n\n if (insert) {\n return [parent.children.length, 0];\n }\n\n const child = parent.children[lastNonEmptyPathOffset];\n const textOffset = Text.isText(child) ? child.text.length : 1;\n return [lastNonEmptyPathOffset, textOffset];\n}\n\nexport function getSlatePath(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n yText: Y.XmlText\n): Path {\n const yNodePath = [yText];\n while (yNodePath[0] !== sharedRoot) {\n const { parent: yParent } = yNodePath[0];\n\n if (!yParent) {\n throw new Error(\"yText isn't a descendant of root element\");\n }\n\n if (!(yParent instanceof Y.XmlText)) {\n throw new Error('Unexpected y parent type');\n }\n\n yNodePath.unshift(yParent);\n }\n\n if (yNodePath.length < 2) {\n return [];\n }\n\n let slateParent = slateRoot;\n return yNodePath.reduce<Path>((path, yParent, idx) => {\n const yChild = yNodePath[idx + 1];\n if (!yChild) {\n return path;\n }\n\n let yOffset = 0;\n const currentDelta = yTextToInsertDelta(yParent);\n for (const element of currentDelta) {\n if (element.insert === yChild) {\n break;\n }\n\n yOffset += typeof element.insert === 'string' ? element.insert.length : 1;\n }\n\n if (Text.isText(slateParent)) {\n throw new Error('Cannot descent into slate text');\n }\n\n const [pathOffset] = yOffsetToSlateOffsets(slateParent, yOffset);\n slateParent = slateParent.children[pathOffset];\n return path.concat(pathOffset);\n }, []);\n}\n","import * as Y from 'yjs';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function assertDocumentAttachment<T extends Y.AbstractType<any>>(\n sharedType: T\n): asserts sharedType is T & { doc: NonNullable<T['doc']> } {\n if (!sharedType.doc) {\n throw new Error(\"shared type isn't attached to a document\");\n }\n}\n","import { Editor, Element, Node, Operation, Path, Text } from 'slate';\nimport * as Y from 'yjs';\nimport { Delta } from '../model/types';\nimport { deltaInsertToSlateNode } from '../utils/convert';\nimport {\n getSlateNodeYLength,\n getSlatePath,\n yOffsetToSlateOffsets,\n} from '../utils/location';\nimport { deepEquals, omitNullEntries, pick } from '../utils/object';\nimport { getProperties } from '../utils/slate';\n\nfunction applyDelta(node: Element, slatePath: Path, delta: Delta): Operation[] {\n const ops: Operation[] = [];\n\n let yOffset = delta.reduce((length, change) => {\n if ('retain' in change) {\n return length + change.retain;\n }\n\n if ('delete' in change) {\n return length + change.delete;\n }\n\n return length;\n }, 0);\n\n // Apply changes in reverse order to avoid path changes.\n delta.reverse().forEach((change) => {\n if ('attributes' in change && 'retain' in change) {\n const [startPathOffset, startTextOffset] = yOffsetToSlateOffsets(\n node,\n yOffset - change.retain\n );\n const [endPathOffset, endTextOffset] = yOffsetToSlateOffsets(\n node,\n yOffset,\n { assoc: -1 }\n );\n\n for (\n let pathOffset = endPathOffset;\n pathOffset >= startPathOffset;\n pathOffset--\n ) {\n const child = node.children[pathOffset];\n const childPath = [...slatePath, pathOffset];\n\n if (!Text.isText(child)) {\n // Ignore attribute updates on non-text nodes (which are backed by Y.XmlText)\n // to be consistent with deltaInsertToSlateNode. Y.XmlText attributes don't show\n // up in deltas but in key changes (YEvent.changes.keys).\n continue;\n }\n\n const newProperties = change.attributes;\n const properties = pick(\n node,\n ...(Object.keys(change.attributes) as Array<keyof Element>)\n );\n\n if (pathOffset === startPathOffset || pathOffset === endPathOffset) {\n const start = pathOffset === startPathOffset ? startTextOffset : 0;\n const end =\n pathOffset === endPathOffset ? endTextOffset : child.text.length;\n\n if (end !== child.text.length) {\n ops.push({\n type: 'split_node',\n path: childPath,\n position: end,\n properties: getProperties(child),\n });\n }\n\n if (start !== 0) {\n ops.push({\n type: 'split_node',\n path: childPath,\n position: start,\n properties: omitNullEntries({\n ...getProperties(child),\n ...newProperties,\n }),\n });\n\n continue;\n }\n }\n\n ops.push({\n type: 'set_node',\n newProperties,\n path: childPath,\n properties,\n });\n }\n }\n\n if ('retain' in change) {\n yOffset -= change.retain;\n }\n\n if ('delete' in change) {\n const [startPathOffset, startTextOffset] = yOffsetToSlateOffsets(\n node,\n yOffset - change.delete\n );\n const [endPathOffset, endTextOffset] = yOffsetToSlateOffsets(\n node,\n yOffset,\n { assoc: -1 }\n );\n\n for (\n let pathOffset =\n endTextOffset === 0 ? endPathOffset - 1 : endPathOffset;\n pathOffset >= startPathOffset;\n pathOffset--\n ) {\n const child = node.children[pathOffset];\n const childPath = [...slatePath, pathOffset];\n\n if (\n Text.isText(child) &&\n (pathOffset === startPathOffset || pathOffset === endPathOffset)\n ) {\n const start = pathOffset === startPathOffset ? startTextOffset : 0;\n const end =\n pathOffset === endPathOffset ? endTextOffset : child.text.length;\n\n ops.push({\n type: 'remove_text',\n offset: start,\n text: child.text.slice(start, end),\n path: childPath,\n });\n\n yOffset -= end - start;\n continue;\n }\n\n ops.push({\n type: 'remove_node',\n node: child,\n path: childPath,\n });\n yOffset -= getSlateNodeYLength(child);\n }\n\n return;\n }\n\n if ('insert' in change) {\n const [pathOffset, textOffset] = yOffsetToSlateOffsets(node, yOffset, {\n insert: true,\n });\n const child = node.children[pathOffset];\n const childPath = [...slatePath, pathOffset];\n\n if (Text.isText(child)) {\n const lastOp = ops[ops.length - 1];\n\n /**\n * The props that exist at the current path\n * Since we're not actually using slate to update the node\n * this is a simulation\n */\n const currentProps =\n lastOp != null && lastOp.type === 'insert_node'\n ? lastOp.node\n : getProperties(child);\n\n let lastPath: Path = [];\n\n if (\n lastOp != null &&\n (lastOp.type === 'insert_node' ||\n lastOp.type === 'insert_text' ||\n lastOp.type === 'split_node' ||\n lastOp.type === 'set_node')\n ) {\n lastPath = lastOp.path;\n }\n\n /**\n * If the insert is a string and the attributes are the same as the\n * props at the current path, we can just insert a text node\n */\n if (\n typeof change.insert === 'string' &&\n deepEquals(change.attributes ?? {}, currentProps) &&\n Path.equals(childPath, lastPath)\n ) {\n return ops.push({\n type: 'insert_text',\n offset: textOffset,\n text: change.insert,\n path: childPath,\n });\n }\n\n const toInsert = deltaInsertToSlateNode(change);\n if (textOffset === 0) {\n return ops.push({\n type: 'insert_node',\n path: childPath,\n node: toInsert,\n });\n }\n\n if (textOffset < child.text.length) {\n ops.push({\n type: 'split_node',\n path: childPath,\n position: textOffset,\n properties: getProperties(child),\n });\n }\n\n return ops.push({\n type: 'insert_node',\n path: Path.next(childPath),\n node: toInsert,\n });\n }\n\n return ops.push({\n type: 'insert_node',\n path: childPath,\n node: deltaInsertToSlateNode(change),\n });\n }\n });\n\n return ops;\n}\n\nexport function translateYTextEvent(\n sharedRoot: Y.XmlText,\n editor: Editor,\n event: Y.YTextEvent\n): Operation[] {\n const { target, changes } = event;\n const delta = event.delta as Delta;\n\n if (!(target instanceof Y.XmlText)) {\n throw new Error('Unexpected target node type');\n }\n\n const ops: Operation[] = [];\n const slatePath = getSlatePath(sharedRoot, editor, target);\n const targetElement = Node.get(editor, slatePath);\n\n if (Text.isText(targetElement)) {\n throw new Error('Cannot apply yTextEvent to text node');\n }\n\n const keyChanges = Array.from(changes.keys.entries());\n if (slatePath.length > 0 && keyChanges.length > 0) {\n const newProperties = Object.fromEntries(\n keyChanges.map(([key, info]) => [\n key,\n info.action === 'delete' ? null : target.getAttribute(key),\n ])\n );\n\n const properties = Object.fromEntries(\n keyChanges.map(([key]) => [key, targetElement[key]])\n );\n\n ops.push({ type: 'set_node', newProperties, properties, path: slatePath });\n }\n\n if (delta.length > 0) {\n ops.push(...applyDelta(targetElement, slatePath, delta));\n }\n\n return ops;\n}\n","import { InsertNodeOperation, Node, Text } from 'slate';\nimport * as Y from 'yjs';\nimport { slateElementToYText } from '../../utils/convert';\nimport { getYTarget } from '../../utils/location';\nimport { getProperties } from '../../utils/slate';\n\nexport function insertNode(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n op: InsertNodeOperation\n): void {\n const { yParent, textRange } = getYTarget(sharedRoot, slateRoot, op.path);\n\n if (Text.isText(op.node)) {\n return yParent.insert(\n textRange.start,\n op.node.text,\n getProperties(op.node)\n );\n }\n\n yParent.insertEmbed(textRange.start, slateElementToYText(op.node));\n}\n","import { MergeNodeOperation, Node, Path, Text } from 'slate';\nimport * as Y from 'yjs';\nimport { Delta } from '../../model/types';\nimport { cloneInsertDeltaDeep } from '../../utils/clone';\nimport { yTextToInsertDelta } from '../../utils/delta';\nimport { getYTarget } from '../../utils/location';\nimport {\n getStoredPositionsInDeltaAbsolute,\n restoreStoredPositionsWithDeltaAbsolute,\n} from '../../utils/position';\nimport { getProperties } from '../../utils/slate';\n\nexport function mergeNode(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n op: MergeNodeOperation\n): void {\n const target = getYTarget(sharedRoot, slateRoot, op.path);\n const prev = getYTarget(\n target.yParent,\n target.slateParent,\n Path.previous(op.path.slice(-1))\n );\n\n if (!target.yTarget !== !prev.yTarget) {\n throw new Error('Cannot merge y text with y element');\n }\n\n if (!prev.yTarget || !target.yTarget) {\n const { yParent: parent, textRange, slateTarget } = target;\n if (!slateTarget) {\n throw new Error('Expected Slate target node for merge op.');\n }\n\n const prevSibling = Node.get(slateRoot, Path.previous(op.path));\n if (!Text.isText(prevSibling)) {\n throw new Error('Path points to Y.Text but not a Slate text node.');\n }\n\n const targetProps = getProperties(slateTarget);\n const prevSiblingProps = getProperties(prevSibling);\n const unsetProps = Object.keys(targetProps).reduce((acc, key) => {\n const prevSiblingHasProp = key in prevSiblingProps;\n return prevSiblingHasProp ? acc : { ...acc, [key]: null };\n }, {});\n\n return parent.format(textRange.start, textRange.end - textRange.start, {\n ...unsetProps,\n ...prevSiblingProps,\n });\n }\n\n const deltaApplyYOffset = prev.yTarget.length;\n const targetDelta = yTextToInsertDelta(target.yTarget);\n const clonedDelta = cloneInsertDeltaDeep(targetDelta);\n\n const storedPositions = getStoredPositionsInDeltaAbsolute(\n sharedRoot,\n target.yTarget,\n targetDelta,\n deltaApplyYOffset\n );\n\n const applyDelta: Delta = [{ retain: deltaApplyYOffset }, ...clonedDelta];\n\n prev.yTarget.applyDelta(applyDelta, {\n sanitize: false,\n });\n\n target.yParent.delete(\n target.textRange.start,\n target.textRange.end - target.textRange.start\n );\n\n restoreStoredPositionsWithDeltaAbsolute(\n sharedRoot,\n prev.yTarget,\n storedPositions,\n clonedDelta,\n deltaApplyYOffset\n );\n}\n","import * as Y from 'yjs';\nimport { InsertDelta } from '../model/types';\nimport { yTextToInsertDelta } from './delta';\n\nexport function cloneInsertDeltaDeep(delta: InsertDelta): InsertDelta {\n return delta.map((element) => {\n if (typeof element.insert === 'string') {\n return element;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n return { ...element, insert: cloneDeep(element.insert) };\n });\n}\n\nexport function cloneDeep(yText: Y.XmlText): Y.XmlText {\n const clone = new Y.XmlText();\n\n const attributes = yText.getAttributes();\n Object.entries(attributes).forEach(([key, value]) => {\n clone.setAttribute(key, value);\n });\n\n clone.applyDelta(cloneInsertDeltaDeep(yTextToInsertDelta(yText)), {\n sanitize: false,\n });\n\n return clone;\n}\n","import { MoveNodeOperation, Node, Path, Text } from 'slate';\nimport * as Y from 'yjs';\nimport { Delta } from '../../model/types';\nimport { cloneInsertDeltaDeep } from '../../utils/clone';\nimport { getInsertDeltaLength, yTextToInsertDelta } from '../../utils/delta';\nimport { getYTarget } from '../../utils/location';\nimport {\n getStoredPositionsInDeltaAbsolute,\n restoreStoredPositionsWithDeltaAbsolute,\n} from '../../utils/position';\n\nexport function moveNode(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n op: MoveNodeOperation\n): void {\n const newParentPath = Path.parent(op.newPath);\n const newPathOffset = op.newPath[op.newPath.length - 1];\n const parent = Node.get(slateRoot, newParentPath);\n if (Text.isText(parent)) {\n throw new Error('Cannot move slate node into text element');\n }\n const normalizedNewPath = [\n ...newParentPath,\n Math.min(newPathOffset, parent.children.length),\n ];\n\n const origin = getYTarget(sharedRoot, slateRoot, op.path);\n const target = getYTarget(sharedRoot, slateRoot, normalizedNewPath);\n const insertDelta = cloneInsertDeltaDeep(origin.targetDelta);\n\n const storedPositions = getStoredPositionsInDeltaAbsolute(\n sharedRoot,\n origin.yParent,\n origin.targetDelta\n );\n\n origin.yParent.delete(\n origin.textRange.start,\n origin.textRange.end - origin.textRange.start\n );\n\n const targetLength = getInsertDeltaLength(yTextToInsertDelta(target.yParent));\n const deltaApplyYOffset = Math.min(target.textRange.start, targetLength);\n const applyDelta: Delta = [{ retain: deltaApplyYOffset }, ...insertDelta];\n\n target.yParent.applyDelta(applyDelta, { sanitize: false });\n\n restoreStoredPositionsWithDeltaAbsolute(\n sharedRoot,\n target.yParent,\n storedPositions,\n insertDelta,\n deltaApplyYOffset,\n origin.textRange.start\n );\n}\n","import { Node, RemoveNodeOperation } from 'slate';\nimport * as Y from 'yjs';\nimport { getYTarget } from '../../utils/location';\n\nexport function removeNode(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n op: RemoveNodeOperation\n): void {\n const { yParent: parent, textRange } = getYTarget(\n sharedRoot,\n slateRoot,\n op.path\n );\n parent.delete(textRange.start, textRange.end - textRange.start);\n}\n","import { Node, SetNodeOperation } from 'slate';\nimport * as Y from 'yjs';\nimport { getYTarget } from '../../utils/location';\n\nexport function setNode(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n op: SetNodeOperation\n): void {\n const { yTarget, textRange, yParent } = getYTarget(\n sharedRoot,\n slateRoot,\n op.path\n );\n\n if (yTarget) {\n Object.entries(op.newProperties).forEach(([key, value]) => {\n if (value === null) {\n return yTarget.removeAttribute(key);\n }\n\n yTarget.setAttribute(key, value);\n });\n\n return Object.entries(op.properties).forEach(([key]) => {\n if (!op.newProperties.hasOwnProperty(key)) {\n yTarget.removeAttribute(key);\n }\n });\n }\n\n const unset = Object.fromEntries(\n Object.keys(op.properties).map((key) => [key, null])\n );\n const newProperties = { ...unset, ...op.newProperties };\n\n yParent.format(\n textRange.start,\n textRange.end - textRange.start,\n newProperties\n );\n}\n","import { Node, SplitNodeOperation, Text } from 'slate';\nimport * as Y from 'yjs';\nimport { cloneInsertDeltaDeep } from '../../utils/clone';\nimport { sliceInsertDelta, yTextToInsertDelta } from '../../utils/delta';\nimport { getSlateNodeYLength, getYTarget } from '../../utils/location';\nimport {\n getStoredPositionsInDeltaAbsolute,\n restoreStoredPositionsWithDeltaAbsolute,\n} from '../../utils/position';\n\nexport function splitNode(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n op: SplitNodeOperation\n): void {\n const target = getYTarget(sharedRoot, slateRoot, op.path);\n\n if (!target.slateTarget) {\n throw new Error('Y target without corresponding slate node');\n }\n\n if (!target.yTarget) {\n if (!Text.isText(target.slateTarget)) {\n throw new Error('Mismatch node type between y target and slate node');\n }\n\n const unset: Record<string, null> = {};\n target.targetDelta.forEach((element) => {\n if (element.attributes) {\n Object.keys(element.attributes).forEach((key) => {\n unset[key] = null;\n });\n }\n });\n\n return target.yParent.format(\n target.textRange.start,\n target.textRange.end - target.textRange.start,\n { ...unset, ...op.properties }\n );\n }\n\n if (Text.isText(target.slateTarget)) {\n throw new Error('Mismatch node type between y target and slate node');\n }\n\n const splitTarget = getYTarget(target.yTarget, target.slateTarget, [\n op.position,\n ]);\n\n const ySplitOffset = target.slateTarget.children\n .slice(0, op.position)\n .reduce((length, child) => length + getSlateNodeYLength(child), 0);\n\n const length = target.slateTarget.children.reduce(\n (current, child) => current + getSlateNodeYLength(child),\n 0\n );\n\n const splitDelta = sliceInsertDelta(\n yTextToInsertDelta(target.yTarget),\n ySplitOffset,\n length - ySplitOffset\n );\n const clonedDelta = cloneInsertDeltaDeep(splitDelta);\n\n const storedPositions = getStoredPositionsInDeltaAbsolute(\n sharedRoot,\n target.yTarget,\n splitDelta,\n ySplitOffset\n );\n\n const toInsert = new Y.XmlText();\n toInsert.applyDelta(clonedDelta, {\n sanitize: false,\n });\n\n Object.entries(op.properties).forEach(([key, value]) => {\n toInsert.setAttribute(key, value);\n });\n\n target.yTarget.delete(\n splitTarget.textRange.start,\n target.yTarget.length - splitTarget.textRange.start\n );\n\n target.yParent.insertEmbed(target.textRange.end, toInsert);\n\n restoreStoredPositionsWithDeltaAbsolute(\n sharedRoot,\n toInsert,\n storedPositions,\n clonedDelta,\n 0,\n ySplitOffset\n );\n}\n","import { NodeOperation } from 'slate';\nimport { OpMapper } from '../types';\nimport { insertNode } from './insertNode';\nimport { mergeNode } from './mergeNode';\nimport { moveNode } from './moveNode';\nimport { removeNode } from './removeNode';\nimport { setNode } from './setNode';\nimport { splitNode } from './splitNode';\n\nexport const NODE_MAPPER: OpMapper<NodeOperation> = {\n insert_node: insertNode,\n remove_node: removeNode,\n set_node: setNode,\n merge_node: mergeNode,\n move_node: moveNode,\n split_node: splitNode,\n};\n","import { InsertTextOperation, Node, Text } from 'slate';\nimport type Y from 'yjs';\nimport { getYTarget } from '../../utils/location';\nimport { getProperties } from '../../utils/slate';\n\nexport function insertText(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n op: InsertTextOperation\n): void {\n const { yParent: target, textRange } = getYTarget(\n sharedRoot,\n slateRoot,\n op.path\n );\n\n const targetNode = Node.get(slateRoot, op.path);\n if (!Text.isText(targetNode)) {\n throw new Error('Cannot insert text into non-text node');\n }\n\n target.insert(\n textRange.start + op.offset,\n op.text,\n getProperties(targetNode)\n );\n}\n","import { Node, RemoveTextOperation } from 'slate';\nimport type Y from 'yjs';\nimport { getYTarget } from '../../utils/location';\n\nexport function removeText(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n op: RemoveTextOperation\n): void {\n const { yParent: target, textRange } = getYTarget(\n sharedRoot,\n slateRoot,\n op.path\n );\n target.delete(textRange.start + op.offset, op.text.length);\n}\n","import { TextOperation } from 'slate';\nimport { OpMapper } from '../types';\nimport { insertText } from './insertText';\nimport { removeText } from './removeText';\n\nexport const TEXT_MAPPER: OpMapper<TextOperation> = {\n insert_text: insertText,\n remove_text: removeText,\n};\n","import { Node, Operation } from 'slate';\nimport * as Y from 'yjs';\nimport { NODE_MAPPER } from './node';\nimport { TEXT_MAPPER } from './text';\nimport { ApplyFunc, OpMapper } from './types';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nconst NOOP = () => {};\n\nconst opMappers: OpMapper = {\n ...TEXT_MAPPER,\n ...NODE_MAPPER,\n\n set_selection: NOOP,\n};\n\nexport function applySlateOp(\n sharedRoot: Y.XmlText,\n slateRoot: Node,\n op: Operation\n): void {\n const apply = opMappers[op.type] as ApplyFunc<typeof op>;\n if (!apply) {\n throw new Error(`Unknown operation: ${op.type}`);\n }\n\n apply(sharedRoot, slateRoot, op);\n}\n","import { Editor, Transforms } from 'slate';\nimport * as Y from 'yjs';\nimport { HistoryStackItem, RelativeRange } from '../model/types';\nimport {\n relativeRangeToSlateRange,\n slateRangeToRelativeRange,\n} from '../utils/position';\nimport { YjsEditor } from './withYjs';\n\nconst LAST_SELECTION: WeakMap<Editor, RelativeRange | null> = new WeakMap();\nconst DEFAULT_WITHOUT_SAVING_ORIGIN = Symbol(\n 'slate-yjs-history-without-saving'\n);\n\nexport type YHistoryEditor = YjsEditor & {\n undoManager: Y.UndoManager;\n\n withoutSavingOrigin: unknown;\n\n undo: () => void;\n redo: () => void;\n};\n\nexport const YHistoryEditor = {\n isYHistoryEditor(value: unknown): value is YHistoryEditor {\n return (\n YjsEditor.isYjsEditor(value) &&\n (value as YHistoryEditor).undoManager instanceof Y.UndoManager &&\n typeof (value as YHistoryEditor).undo === 'function' &&\n typeof (value as YHistoryEditor).redo === 'function' &&\n 'withoutSavingOrigin' in value\n );\n },\n\n canUndo(editor: YHistoryEditor) {\n return editor.undoManager.undoStack.length > 0;\n },\n\n canRedo(editor: YHistoryEditor) {\n return editor.undoManager.redoStack.length > 0;\n },\n\n isSaving(editor: YHistoryEditor): boolean {\n return editor.undoManager.trackedOrigins.has(YjsEditor.origin(editor));\n },\n\n withoutSaving(editor: YHistoryEditor, fn: () => void) {\n YjsEditor.withOrigin(editor, editor.withoutSavingOrigin, fn);\n },\n};\n\nexport type WithYHistoryOptions = NonNullable<\n ConstructorParameters<typeof Y.UndoManager>[1]\n> & {\n withoutSavingOrigin?: unknown;\n};\n\nexport function withYHistory<T extends YjsEditor>(\n editor: T,\n {\n withoutSavingOrigin = DEFAULT_WITHOUT_SAVING_ORIGIN,\n trackedOrigins = new Set([editor.localOrigin]),\n ...options\n }: WithYHistoryOptions = {}\n): T & YHistoryEditor {\n const e = editor as T & YHistoryEditor;\n\n const undoManager = new Y.UndoManager(e.sharedRoot, {\n trackedOrigins,\n ...options,\n });\n\n e.undoManager = undoManager;\n e.withoutSavingOrigin = withoutSavingOrigin;\n\n const { onChange, isLocalOrigin } = e;\n e.onChange = () => {\n onChange();\n\n LAST_SELECTION.set(\n e,\n e.selection && slateRangeToRelativeRange(e.sharedRoot, e, e.selection)\n );\n };\n\n e.isLocalOrigin = (origin) =>\n origin === e.withoutSavingOrigin || isLocalOrigin(origin);\n\n const handleStackItemAdded = ({\n stackItem,\n }: {\n stackItem: HistoryStackItem;\n type: 'redo' | 'undo';\n }) => {\n stackItem.meta.set(\n 'selection',\n e.selection && slateRangeToRelativeRange(e.sharedRoot, e, e.selection)\n );\n stackItem.meta.set('selectionBefore', LAST_SELECTION.get(e));\n };\n\n const handleStackItemUpdated = ({\n stackItem,\n }: {\n stackItem: HistoryStackItem;\n type: 'redo' | 'undo';\n }) => {\n stackItem.meta.set(\n 'selection',\n e.selection && slateRangeToRelativeRange(e.sharedRoot, e, e.selection)\n );\n };\n\n const handleStackItemPopped = ({\n stackItem,\n type,\n }: {\n stackItem: HistoryStackItem;\n type: 'redo' | 'undo';\n }) => {\n // TODO: Change once https://github.com/yjs/yjs/issues/353 is resolved\n const inverseStack =\n type === 'undo' ? e.undoManager.redoStack : e.undoManager.undoStack;\n const inverseItem = inverseStack[inverseStack.length - 1];\n if (inverseItem) {\n inverseItem.meta.set('selection', stackItem.meta.get('selectionBefore'));\n inverseItem.meta.set('selectionBefore', stackItem.meta.get('selection'));\n }\n\n const relativeSelection = stackItem.meta.get(\n 'selectionBefore'\n ) as RelativeRange | null;\n\n if (!relativeSelection) {\n return;\n }\n\n const selection = relativeRangeToSlateRange(\n e.sharedRoot,\n e,\n relativeSelection\n );\n\n if (!selection) {\n return;\n }\n\n Transforms.select(e, selection);\n };\n\n const { connect, disconnect } = e;\n e.connect = () => {\n connect();\n\n e.undoManager.on('stack-item-added', handleStackItemAdded);\n e.undoManager.on('stack-item-popped', handleStackItemPopped);\n e.undoManager.on('stack-item-updated', handleStackItemUpdated);\n };\n\n e.disconnect = () => {\n e.undoManager.off('stack-item-added', handleStackItemAdded);\n e.undoManager.off('stack-item-popped', handleStackItemPopped);\n e.undoManager.off('stack-item-updated', handleStackItemUpdated);\n\n disconnect();\n };\n\n e.undo = () => {\n if (YjsEditor.connected(e)) {\n YjsEditor.flushLocalChanges(e);\n e.undoManager.undo();\n }\n };\n\n e.redo = () => {\n if (YjsEditor.connected(e)) {\n YjsEditor.flushLocalChanges(e);\n e.undoManager.redo();\n }\n };\n\n return e;\n}\n","import { Editor, Range } from 'slate';\nimport { Awareness } from 'y-protocols/awareness';\nimport * as Y from 'yjs';\nimport { RelativeRange } from '../model/types';\nimport { slateRangeToRelativeRange } from '../utils/position';\nimport { YjsEditor } from './withYjs';\n\nexport type CursorStateChangeEvent = {\n added: number[];\n updated: number[];\n removed: number[];\n};\n\nexport type RemoteCursorChangeEventListener = (\n event: CursorStateChangeEvent\n) => void;\n\nconst CURSOR_CHANGE_EVENT_LISTENERS: WeakMap<\n Editor,\n Set<RemoteCursorChangeEventListener>\n> = new WeakMap();\n\nexport type CursorState<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n> = {\n relativeSelection: RelativeRange | null;\n data?: TCursorData;\n clientId: number;\n};\n\nexport type CursorEditor<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n> = YjsEditor & {\n awareness: Awareness;\n\n cursorDataField: string;\n selectionStateField: string;\n\n sendCursorPosition: (range: Range | null) => void;\n sendCursorData: (data: TCursorData) => void;\n};\n\nexport const CursorEditor = {\n isCursorEditor(value: unknown): value is CursorEditor {\n return (\n YjsEditor.isYjsEditor(value) &&\n (value as CursorEditor).awareness &&\n typeof (value as CursorEditor).cursorDataField === 'string' &&\n typeof (value as CursorEditor).selectionStateField === 'string' &&\n typeof (value as CursorEditor).sendCursorPosition === 'function' &&\n typeof (value as CursorEditor).sendCursorData === 'function'\n );\n },\n\n sendCursorPosition<TCursorData extends Record<string, unknown>>(\n editor: CursorEditor<TCursorData>,\n range: Range | null = editor.selection\n ) {\n editor.sendCursorPosition(range);\n },\n\n sendCursorData<TCursorData extends Record<string, unknown>>(\n editor: CursorEditor<TCursorData>,\n data: TCursorData\n ) {\n editor.sendCursorData(data);\n },\n\n on<TCursorData extends Record<string, unknown>>(\n editor: CursorEditor<TCursorData>,\n event: 'change',\n handler: RemoteCursorChangeEventListener\n ) {\n if (event !== 'change') {\n return;\n }\n\n const listeners = CURSOR_CHANGE_EVENT_LISTENERS.get(editor) ?? new Set();\n listeners.add(handler);\n CURSOR_CHANGE_EVENT_LISTENERS.set(editor, listeners);\n },\n\n off<TCursorData extends Record<string, unknown>>(\n editor: CursorEditor<TCursorData>,\n event: 'change',\n listener: RemoteCursorChangeEventListener\n ) {\n if (event !== 'change') {\n return;\n }\n\n const listeners = CURSOR_CHANGE_EVENT_LISTENERS.get(editor);\n if (listeners) {\n listeners.delete(listener);\n }\n },\n\n cursorState<TCursorData extends Record<string, unknown>>(\n editor: CursorEditor<TCursorData>,\n clientId: number\n ): CursorState<TCursorData> | null {\n if (\n clientId === editor.awareness.clientID ||\n !YjsEditor.connected(editor)\n ) {\n return null;\n }\n\n const state = editor.awareness.getStates().get(clientId);\n if (!state) {\n return null;\n }\n\n return {\n relativeSelection: state[editor.selectionStateField] ?? null,\n data: state[editor.cursorDataField],\n clientId,\n };\n },\n\n cursorStates<TCursorData extends Record<string, unknown>>(\n editor: CursorEditor<TCursorData>\n ): Record<string, CursorState<TCursorData>> {\n if (!YjsEditor.connected(editor)) {\n return {};\n }\n\n return Object.fromEntries(\n Array.from(editor.awareness.getStates().entries(), ([id, state]) => {\n // Ignore own state\n if (id === editor.awareness.clientID || !state) {\n return null;\n }\n\n return [\n id,\n {\n relativeSelection: state[editor.selectionStateField],\n data: state[editor.cursorDataField],\n },\n ];\n }).filter(Array.isArray)\n );\n },\n};\n\nexport type WithCursorsOptions<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n> = {\n // Local state field used to store the user selection\n cursorStateField?: string;\n\n // Local state field used to store data attached to the local client\n cursorDataField?: string;\n\n data?: TCursorData;\n autoSend?: boolean;\n};\n\nexport function withCursors<\n TCursorData extends Record<string, unknown>,\n TEditor extends YjsEditor\n>(\n editor: TEditor,\n awareness: Awareness,\n {\n cursorStateField: selectionStateField = 'selection',\n cursorDataField = 'data',\n autoSend = true,\n data,\n }: WithCursorsOptions<TCursorData> = {}\n): TEditor & CursorEditor<TCursorData> {\n const e = editor as TEditor & CursorEditor<TCursorData>;\n\n e.awareness = awareness;\n e.cursorDataField = cursorDataField;\n e.selectionStateField = selectionStateField;\n\n e.sendCursorData = (cursorData: TCursorData) => {\n e.awareness.setLocalStateField(e.cursorDataField, cursorData);\n };\n\n e.sendCursorPosition = (range) => {\n const localState = e.awareness.getLocalState();\n const currentRange = localState?.[selectionStateField];\n\n if (!range) {\n if (currentRange) {\n e.awareness.setLocalStateField(e.selectionStateField, null);\n }\n\n return;\n }\n\n const { anchor, focus } = slateRangeToRelativeRange(e.sharedRoot, e, range);\n\n if (\n !currentRange ||\n !Y.compareRelativePositions(anchor, currentRange) ||\n !Y.compareRelativePositions(focus, currentRange)\n ) {\n e.awareness.setLocalStateField(e.selectionStateField, { anchor, focus });\n }\n };\n\n const awarenessChangeListener: RemoteCursorChangeEventListener = (yEvent) => {\n const listeners = CURSOR_CHANGE_EVENT_LISTENERS.get(e);\n if (!listeners) {\n return;\n }\n\n const localId = e.awareness.clientID;\n const event = {\n added: yEvent.added.filter((id) => id !== localId),\n removed: yEvent.removed.filter((id) => id !== localId),\n updated: yEvent.updated.filter((id) => id !== localId),\n };\n\n if (\n event.added.length > 0 ||\n event.removed.length > 0 ||\n event.updated.length > 0\n ) {\n listeners.forEach((listener) => listener(event));\n }\n };\n\n const { connect, disconnect } = e;\n e.connect = () => {\n connect();\n\n e.awareness.on('change', awarenessChangeListener);\n\n awarenessChangeListener({\n removed: [],\n added: Array.from(e.awareness.getStates().keys()),\n updated: [],\n });\n\n if (autoSend) {\n if (data) {\n CursorEditor.sendCursorData(e, data);\n }\n\n const { onChange } = e;\n e.onChange = () => {\n onChange();\n\n if (YjsEditor.connected(e)) {\n CursorEditor.sendCursorPosition(e);\n }\n };\n }\n };\n\n e.disconnect = () => {\n e.awareness.off('change', awarenessChangeListener);\n\n awarenessChangeListener({\n removed: Array.from(e.awareness.getStates().keys()),\n added: [],\n updated: [],\n });\n\n disconnect();\n };\n\n return e;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,38 @@
1
+ import type { Editor, Element, Node } from 'slate';
2
+ import type Y from 'yjs';
3
+ export declare type DeltaAttributes = {
4
+ retain: number;
5
+ attributes: Record<string, unknown>;
6
+ };
7
+ export declare type DeltaRetain = {
8
+ retain: number;
9
+ };
10
+ export declare type DeltaDelete = {
11
+ delete: number;
12
+ };
13
+ export declare type DeltaInsert = {
14
+ insert: string | Y.XmlText;
15
+ attributes?: Record<string, unknown>;
16
+ };
17
+ export declare type InsertDelta = Array<DeltaInsert>;
18
+ export declare type Delta = Array<DeltaRetain | DeltaDelete | DeltaInsert | DeltaAttributes>;
19
+ export declare type TextRange = {
20
+ start: number;
21
+ end: number;
22
+ };
23
+ export declare type HistoryStackItem = {
24
+ meta: Map<string, unknown>;
25
+ };
26
+ export declare type YTarget = {
27
+ textRange: TextRange;
28
+ yParent: Y.XmlText;
29
+ slateParent: Element | Editor;
30
+ yTarget?: Y.XmlText;
31
+ slateTarget?: Node;
32
+ targetDelta: InsertDelta;
33
+ };
34
+ export declare type RelativeRange = {
35
+ anchor: Y.RelativePosition;
36
+ focus: Y.RelativePosition;
37
+ };
38
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,4 @@
1
+ export * from './withYjs';
2
+ export * from './withYHistory';
3
+ export * from './withCursors';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,39 @@
1
+ import { Range } from 'slate';
2
+ import { Awareness } from 'y-protocols/awareness';
3
+ import { RelativeRange } from '../model/types';
4
+ import { YjsEditor } from './withYjs';
5
+ export declare type CursorStateChangeEvent = {
6
+ added: number[];
7
+ updated: number[];
8
+ removed: number[];
9
+ };
10
+ export declare type RemoteCursorChangeEventListener = (event: CursorStateChangeEvent) => void;
11
+ export declare type CursorState<TCursorData extends Record<string, unknown> = Record<string, unknown>> = {
12
+ relativeSelection: RelativeRange | null;
13
+ data?: TCursorData;
14
+ clientId: number;
15
+ };
16
+ export declare type CursorEditor<TCursorData extends Record<string, unknown> = Record<string, unknown>> = YjsEditor & {
17
+ awareness: Awareness;
18
+ cursorDataField: string;
19
+ selectionStateField: string;
20
+ sendCursorPosition: (range: Range | null) => void;
21
+ sendCursorData: (data: TCursorData) => void;
22
+ };
23
+ export declare const CursorEditor: {
24
+ isCursorEditor(value: unknown): value is CursorEditor<Record<string, unknown>>;
25
+ sendCursorPosition<TCursorData extends Record<string, unknown>>(editor: CursorEditor<TCursorData>, range?: Range | null): void;
26
+ sendCursorData<TCursorData_1 extends Record<string, unknown>>(editor: CursorEditor<TCursorData_1>, data: TCursorData_1): void;
27
+ on<TCursorData_2 extends Record<string, unknown>>(editor: CursorEditor<TCursorData_2>, event: 'change', handler: RemoteCursorChangeEventListener): void;
28
+ off<TCursorData_3 extends Record<string, unknown>>(editor: CursorEditor<TCursorData_3>, event: 'change', listener: RemoteCursorChangeEventListener): void;
29
+ cursorState<TCursorData_4 extends Record<string, unknown>>(editor: CursorEditor<TCursorData_4>, clientId: number): CursorState<TCursorData_4> | null;
30
+ cursorStates<TCursorData_5 extends Record<string, unknown>>(editor: CursorEditor<TCursorData_5>): Record<string, CursorState<TCursorData_5>>;
31
+ };
32
+ export declare type WithCursorsOptions<TCursorData extends Record<string, unknown> = Record<string, unknown>> = {
33
+ cursorStateField?: string;
34
+ cursorDataField?: string;
35
+ data?: TCursorData;
36
+ autoSend?: boolean;
37
+ };
38
+ export declare function withCursors<TCursorData extends Record<string, unknown>, TEditor extends YjsEditor>(editor: TEditor, awareness: Awareness, { cursorStateField: selectionStateField, cursorDataField, autoSend, data, }?: WithCursorsOptions<TCursorData>): TEditor & CursorEditor<TCursorData>;
39
+ //# sourceMappingURL=withCursors.d.ts.map
@@ -0,0 +1,20 @@
1
+ import * as Y from 'yjs';
2
+ import { YjsEditor } from './withYjs';
3
+ export declare type YHistoryEditor = YjsEditor & {
4
+ undoManager: Y.UndoManager;
5
+ withoutSavingOrigin: unknown;
6
+ undo: () => void;
7
+ redo: () => void;
8
+ };
9
+ export declare const YHistoryEditor: {
10
+ isYHistoryEditor(value: unknown): value is YHistoryEditor;
11
+ canUndo(editor: YHistoryEditor): boolean;
12
+ canRedo(editor: YHistoryEditor): boolean;
13
+ isSaving(editor: YHistoryEditor): boolean;
14
+ withoutSaving(editor: YHistoryEditor, fn: () => void): void;
15
+ };
16
+ export declare type WithYHistoryOptions = NonNullable<ConstructorParameters<typeof Y.UndoManager>[1]> & {
17
+ withoutSavingOrigin?: unknown;
18
+ };
19
+ export declare function withYHistory<T extends YjsEditor>(editor: T, { withoutSavingOrigin, trackedOrigins, ...options }?: WithYHistoryOptions): T & YHistoryEditor;
20
+ //# sourceMappingURL=withYHistory.d.ts.map
@@ -0,0 +1,43 @@
1
+ import { BaseEditor, Descendant, Editor, Operation, Point } from 'slate';
2
+ import * as Y from 'yjs';
3
+ declare type LocalChange = {
4
+ op: Operation;
5
+ doc: Descendant[];
6
+ origin: unknown;
7
+ };
8
+ export declare type YjsEditor = BaseEditor & {
9
+ sharedRoot: Y.XmlText;
10
+ localOrigin: unknown;
11
+ positionStorageOrigin: unknown;
12
+ applyRemoteEvents: (events: Y.YEvent<Y.XmlText>[], origin: unknown) => void;
13
+ storeLocalChange: (op: Operation) => void;
14
+ flushLocalChanges: () => void;
15
+ isLocalOrigin: (origin: unknown) => boolean;
16
+ connect: () => void;
17
+ disconnect: () => void;
18
+ };
19
+ export declare const YjsEditor: {
20
+ isYjsEditor(value: unknown): value is YjsEditor;
21
+ localChanges(editor: YjsEditor): LocalChange[];
22
+ applyRemoteEvents(editor: YjsEditor, events: Y.YEvent<Y.XmlText>[], origin: unknown): void;
23
+ storeLocalChange(editor: YjsEditor, op: Operation): void;
24
+ flushLocalChanges(editor: YjsEditor): void;
25
+ connected(editor: YjsEditor): boolean;
26
+ connect(editor: YjsEditor): void;
27
+ disconnect(editor: YjsEditor): void;
28
+ isLocal(editor: YjsEditor): boolean;
29
+ origin(editor: YjsEditor): unknown;
30
+ withOrigin(editor: YjsEditor, origin: unknown, fn: () => void): void;
31
+ storePosition(editor: YjsEditor, key: string, point: Point): void;
32
+ removeStoredPosition(editor: YjsEditor, key: string): void;
33
+ position(editor: YjsEditor, key: string): Point | null | undefined;
34
+ storedPositionsRelative(editor: YjsEditor): Record<string, Y.RelativePosition>;
35
+ };
36
+ export declare type WithYjsOptions = {
37
+ autoConnect?: boolean;
38
+ localOrigin?: unknown;
39
+ positionStorageOrigin?: unknown;
40
+ };
41
+ export declare function withYjs<T extends Editor>(editor: T, sharedRoot: Y.XmlText, { localOrigin, positionStorageOrigin, autoConnect, }?: WithYjsOptions): T & YjsEditor;
42
+ export {};
43
+ //# sourceMappingURL=withYjs.d.ts.map
@@ -0,0 +1,5 @@
1
+ import * as Y from 'yjs';
2
+ import { InsertDelta } from '../model/types';
3
+ export declare function cloneInsertDeltaDeep(delta: InsertDelta): InsertDelta;
4
+ export declare function cloneDeep(yText: Y.XmlText): Y.XmlText;
5
+ //# sourceMappingURL=clone.d.ts.map
@@ -0,0 +1,8 @@
1
+ import { Element, Node } from 'slate';
2
+ import * as Y from 'yjs';
3
+ import { DeltaInsert, InsertDelta } from '../model/types';
4
+ export declare function yTextToSlateElement(yText: Y.XmlText): Element;
5
+ export declare function deltaInsertToSlateNode(insert: DeltaInsert): Node;
6
+ export declare function slateNodesToInsertDelta(nodes: Node[]): InsertDelta;
7
+ export declare function slateElementToYText({ children, ...attributes }: Element): Y.XmlText;
8
+ //# sourceMappingURL=convert.d.ts.map
@@ -0,0 +1,8 @@
1
+ import * as Y from 'yjs';
2
+ import { DeltaInsert, InsertDelta } from '../model/types';
3
+ export declare function normalizeInsertDelta(delta: InsertDelta): InsertDelta;
4
+ export declare function yTextToInsertDelta(yText: Y.XmlText): InsertDelta;
5
+ export declare function getInsertLength({ insert }: DeltaInsert): number;
6
+ export declare function getInsertDeltaLength(delta: InsertDelta): number;
7
+ export declare function sliceInsertDelta(delta: InsertDelta, start: number, length: number): InsertDelta;
8
+ //# sourceMappingURL=delta.d.ts.map
@@ -0,0 +1,2 @@
1
+ export declare function isSyncSkewError(error: unknown): boolean;
2
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1,12 @@
1
+ import { Element, Node, Path } from 'slate';
2
+ import * as Y from 'yjs';
3
+ import { YTarget } from '../model/types';
4
+ export declare function getSlateNodeYLength(node: Node | undefined): number;
5
+ export declare function slatePathOffsetToYOffset(element: Element, pathOffset: number): number;
6
+ export declare function getYTarget(yRoot: Y.XmlText, slateRoot: Node, path: Path): YTarget;
7
+ export declare function yOffsetToSlateOffsets(parent: Element, yOffset: number, opts?: {
8
+ assoc?: number;
9
+ insert?: boolean;
10
+ }): [number, number];
11
+ export declare function getSlatePath(sharedRoot: Y.XmlText, slateRoot: Node, yText: Y.XmlText): Path;
12
+ //# sourceMappingURL=location.d.ts.map
@@ -0,0 +1,10 @@
1
+ declare type InspectableObject = Record<string | number | symbol, unknown>;
2
+ export declare function isPlainObject(o: unknown): o is InspectableObject;
3
+ export declare function deepEquals(node: InspectableObject, another: InspectableObject): boolean;
4
+ export declare function pick<TObj, TKeys extends keyof TObj>(obj: TObj, ...keys: TKeys[]): Pick<TObj, TKeys>;
5
+ export declare function omit<TObj, TKeys extends keyof TObj>(obj: TObj, ...keys: TKeys[]): Omit<TObj, TKeys>;
6
+ export declare function omitNullEntries<TObj>(obj: TObj): {
7
+ [K in keyof TObj]: TObj[K] extends null ? never : K;
8
+ };
9
+ export {};
10
+ //# sourceMappingURL=object.d.ts.map
@@ -0,0 +1,20 @@
1
+ import { BasePoint, BaseRange, Node } from 'slate';
2
+ import * as Y from 'yjs';
3
+ import { InsertDelta, RelativeRange } from '../model/types';
4
+ export declare const STORED_POSITION_PREFIX = "__slateYjsStoredPosition_";
5
+ export declare function slatePointToRelativePosition(sharedRoot: Y.XmlText, slateRoot: Node, point: BasePoint): Y.RelativePosition;
6
+ export declare function absolutePositionToSlatePoint(sharedRoot: Y.XmlText, slateRoot: Node, { type, index, assoc }: Y.AbsolutePosition): BasePoint | null;
7
+ export declare function relativePositionToSlatePoint(sharedRoot: Y.XmlText, slateRoot: Node, pos: Y.RelativePosition): BasePoint | null;
8
+ export declare function getStoredPosition(sharedRoot: Y.XmlText, key: string): Y.RelativePosition | null;
9
+ export declare function getStoredPositions(sharedRoot: Y.XmlText): Record<string, Y.RelativePosition>;
10
+ export declare function removeStoredPosition(sharedRoot: Y.XmlText, key: string): void;
11
+ export declare function setStoredPosition(sharedRoot: Y.XmlText, key: string, position: Y.RelativePosition): void;
12
+ export declare function getStoredPositionsInDeltaAbsolute(sharedRoot: Y.XmlText, yText: Y.XmlText, delta: InsertDelta, deltaOffset?: number): {
13
+ '': {
14
+ [k: string]: Y.AbsolutePosition;
15
+ };
16
+ };
17
+ export declare function restoreStoredPositionsWithDeltaAbsolute(sharedRoot: Y.XmlText, yText: Y.XmlText, absolutePositions: Record<string, Record<string, Y.AbsolutePosition>>, delta: InsertDelta, newDeltaOffset?: number, previousDeltaOffset?: number, path?: string): void;
18
+ export declare function slateRangeToRelativeRange(sharedRoot: Y.XmlText, slateRoot: Node, range: BaseRange): RelativeRange;
19
+ export declare function relativeRangeToSlateRange(sharedRoot: Y.XmlText, slateRoot: Node, range: RelativeRange): BaseRange | null;
20
+ //# sourceMappingURL=position.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { BaseText, Descendant } from 'slate';
2
+ export declare function getProperties<TNode extends Descendant>(node: TNode): Omit<TNode, TNode extends BaseText ? 'text' : 'children'>;
3
+ //# sourceMappingURL=slate.d.ts.map
@@ -0,0 +1,5 @@
1
+ import * as Y from 'yjs';
2
+ export declare function assertDocumentAttachment<T extends Y.AbstractType<any>>(sharedType: T): asserts sharedType is T & {
3
+ doc: NonNullable<T['doc']>;
4
+ };
5
+ //# sourceMappingURL=yjs.d.ts.map
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@getguru/slate-yjs-core",
3
+ "sideEffects": false,
4
+ "version": "1.0.3",
5
+ "description": "Yjs binding for Slate.",
6
+ "keywords": [
7
+ "slate",
8
+ "yjs",
9
+ "collaborative"
10
+ ],
11
+ "type": "module",
12
+ "exports": {
13
+ "require": "./dist/index.cjs",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "main": "dist/index.cjs",
17
+ "module": "dist/index.js",
18
+ "unpkg": "dist/index.global.js",
19
+ "types": "dist/index.d.ts",
20
+ "scripts": {
21
+ "build": "yarn run tsup && tsc --emitDeclarationOnly",
22
+ "dev": "yarn run tsup --watch"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/guruhq/slate-yjs.git"
27
+ },
28
+ "license": "MIT",
29
+ "devDependencies": {
30
+ "slate": "^0.82.1",
31
+ "slate-hyperscript": "^0.67.0",
32
+ "tsup": "^5.12.1",
33
+ "typescript": "^4.6.3",
34
+ "yjs": "^13.5.29"
35
+ },
36
+ "peerDependencies": {
37
+ "slate": ">=0.70.0",
38
+ "yjs": "^13.5.29"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/guruhq/slate-yjs/issues"
42
+ },
43
+ "homepage": "https://github.com/guruhq/slate-yjs#readme",
44
+ "dependencies": {
45
+ "y-protocols": "^1.0.5"
46
+ }
47
+ }
@@ -0,0 +1,118 @@
1
+ import { Editor, Operation, Transforms } from 'slate';
2
+ import * as Y from 'yjs';
3
+ import { RelativeRange } from '../model/types';
4
+ import { yTextToSlateElement } from '../utils/convert';
5
+ import { isSyncSkewError } from '../utils/errors';
6
+ import {
7
+ relativeRangeToSlateRange,
8
+ slateRangeToRelativeRange,
9
+ } from '../utils/position';
10
+ import { translateYTextEvent } from './textEvent';
11
+
12
+ let lastResyncTime = 0;
13
+ const RESYNC_THROTTLE_MS = 1000;
14
+
15
+ /**
16
+ * Translate a yjs event into slate operations. The editor state has to match the
17
+ * yText state before the event occurred.
18
+ *
19
+ * @param sharedType
20
+ * @param op
21
+ */
22
+ export function translateYjsEvent(
23
+ sharedRoot: Y.XmlText,
24
+ editor: Editor,
25
+ event: Y.YEvent<Y.XmlText>
26
+ ): Operation[] {
27
+ if (event instanceof Y.YTextEvent) {
28
+ return translateYTextEvent(sharedRoot, editor, event);
29
+ }
30
+
31
+ throw new Error('Unexpected Y event type');
32
+ }
33
+
34
+ /**
35
+ * Performs a full re-sync of the Slate editor from the Yjs shared root.
36
+ * Preserves the user's selection if possible by converting to/from relative positions.
37
+ */
38
+ function resyncFromYjs(sharedRoot: Y.XmlText, editor: Editor): void {
39
+ let savedSelection: RelativeRange | null = null;
40
+
41
+ try {
42
+ if (editor.selection) {
43
+ savedSelection = slateRangeToRelativeRange(
44
+ sharedRoot,
45
+ editor,
46
+ editor.selection
47
+ );
48
+ }
49
+ } catch {
50
+ // Selection conversion failed; we'll lose the selection but continue with re-sync
51
+ }
52
+
53
+ const content = yTextToSlateElement(sharedRoot);
54
+ editor.children = content.children;
55
+ Editor.normalize(editor, { force: true });
56
+
57
+ if (savedSelection) {
58
+ try {
59
+ const newSelection = relativeRangeToSlateRange(
60
+ sharedRoot,
61
+ editor,
62
+ savedSelection
63
+ );
64
+ if (newSelection) {
65
+ Transforms.select(editor, newSelection);
66
+ }
67
+ } catch {
68
+ // Selection restoration failed; cursor position is lost but document is correct
69
+ }
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Translates yjs events into slate operations and applies them to the editor. The
75
+ * editor state has to match the yText state before the events occurred.
76
+ *
77
+ * If a sync-skew error occurs (e.g. invalid path due to Yjs/Slate mismatch),
78
+ * the editor is re-synced from the Yjs shared root to recover gracefully.
79
+ *
80
+ * @param sharedRoot
81
+ * @param editor
82
+ * @param events
83
+ */
84
+ export function applyYjsEvents(
85
+ sharedRoot: Y.XmlText,
86
+ editor: Editor,
87
+ events: Y.YEvent<Y.XmlText>[]
88
+ ) {
89
+ Editor.withoutNormalizing(editor, () => {
90
+ for (const event of events) {
91
+ try {
92
+ const ops = translateYjsEvent(sharedRoot, editor, event);
93
+ for (const op of ops) {
94
+ editor.apply(op);
95
+ }
96
+ } catch (error) {
97
+ if (isSyncSkewError(error)) {
98
+ const now = Date.now();
99
+ if (now - lastResyncTime >= RESYNC_THROTTLE_MS) {
100
+ lastResyncTime = now;
101
+ console.warn(
102
+ '[slate-yjs] Sync skew detected, re-syncing from Yjs:',
103
+ error instanceof Error ? error.message : error
104
+ );
105
+ resyncFromYjs(sharedRoot, editor);
106
+ } else {
107
+ console.warn(
108
+ '[slate-yjs] Sync skew detected (throttled, skipping re-sync):',
109
+ error instanceof Error ? error.message : error
110
+ );
111
+ }
112
+ return;
113
+ }
114
+ throw error;
115
+ }
116
+ }
117
+ });
118
+ }