@tiptap/y-tiptap 3.0.0 → 3.0.2

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/y-tiptap.js CHANGED
@@ -296,7 +296,7 @@ const restoreRelativeSelection = (tr, relSel, binding) => {
296
296
  relSel.anchor,
297
297
  binding.mapping
298
298
  );
299
- tr.setSelection(NodeSelection.create(tr.doc, anchor));
299
+ tr.setSelection(createSafeNodeSelection(tr, anchor));
300
300
  } else {
301
301
  const anchor = relativePositionToAbsolutePosition(
302
302
  binding.doc,
@@ -317,6 +317,23 @@ const restoreRelativeSelection = (tr, relSel, binding) => {
317
317
  }
318
318
  };
319
319
 
320
+ /**
321
+ * @param {import('prosemirror-state').Transaction} tr
322
+ * @param {number} pos
323
+ * @returns {import('prosemirror-state').Selection}
324
+ *
325
+ * Creates a NodeSelection if the position points to a valid node, otherwise
326
+ * creates a TextSelection near the position.
327
+ */
328
+ const createSafeNodeSelection = (tr, pos) => {
329
+ const $pos = tr.doc.resolve(pos);
330
+ if ($pos.nodeAfter) {
331
+ return NodeSelection.create(tr.doc, pos)
332
+ } else {
333
+ return TextSelection.near($pos)
334
+ }
335
+ };
336
+
320
337
  /**
321
338
  * @param {ProsemirrorBinding} pmbinding
322
339
  * @param {import('prosemirror-state').EditorState} state
@@ -999,9 +1016,18 @@ const equalYTextPText = (ytext, ptexts) => {
999
1016
  delta.every(/** @type {(d:any,i:number) => boolean} */ (d, i) =>
1000
1017
  d.insert === /** @type {any} */ (ptexts[i]).text &&
1001
1018
  object.keys(d.attributes || {}).length === ptexts[i].marks.length &&
1002
- object.every(d.attributes, (attr, yattrname) => {
1019
+ object.every(d.attributes, (attr, /** @type {string} */ yattrname) => {
1003
1020
  const markname = yattr2markname(yattrname);
1004
1021
  const pmarks = ptexts[i].marks;
1022
+
1023
+ const pmark = pmarks.find(/** @param {any} mark */ mark => mark.type.name === markname);
1024
+
1025
+ // Ensure the pmark is present in the ptexts before checking equality. When replacing a mark with another mark
1026
+ // the pmark will be missing from the ptexts and the equalAttrs will throw an error.
1027
+ if (!pmark) {
1028
+ return false
1029
+ }
1030
+
1005
1031
  return equalAttrs(attr, pmarks.find(/** @param {any} mark */ mark => mark.type.name === markname)?.attrs)
1006
1032
  })
1007
1033
  )
@@ -1782,7 +1808,11 @@ function yXmlFragmentToProsemirrorJSON (xmlFragment) {
1782
1808
  * @param {any} _user user data
1783
1809
  * @return {boolean}
1784
1810
  */
1785
- const defaultAwarenessStateFilter = (currentClientId, userClientId, _user) => currentClientId !== userClientId;
1811
+ const defaultAwarenessStateFilter = (
1812
+ currentClientId,
1813
+ userClientId,
1814
+ _user
1815
+ ) => currentClientId !== userClientId;
1786
1816
 
1787
1817
  /**
1788
1818
  * Default generator for a cursor element
@@ -1836,10 +1866,14 @@ const createDecorations = (
1836
1866
  createSelection
1837
1867
  ) => {
1838
1868
  const ystate = ySyncPluginKey.getState(state);
1869
+ if (ystate == null || ystate.doc == null || ystate.binding == null) {
1870
+ return DecorationSet.create(state.doc, [])
1871
+ }
1839
1872
  const y = ystate.doc;
1840
1873
  const decorations = [];
1841
1874
  if (
1842
- ystate.snapshot != null || ystate.prevSnapshot != null ||
1875
+ ystate.snapshot != null ||
1876
+ ystate.prevSnapshot != null ||
1843
1877
  ystate.binding.mapping.size === 0
1844
1878
  ) {
1845
1879
  // do not render cursors while snapshot is active