@tiptap/y-tiptap 3.0.0-beta.3 → 3.0.1

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/README.md CHANGED
@@ -4,6 +4,14 @@
4
4
 
5
5
  This binding maps a Y.XmlFragment to the ProseMirror state.
6
6
 
7
+ ## Why was this package forked from [y-prosemirror](https://github.com/yjs/y-prosemirror)?
8
+
9
+ We forked y-prosemirror to create a Tiptap-specific package with changes we needed for Tiptap-related features. These modifications were too specific to be merged upstream or would have added maintenance overhead for the y-prosemirror maintainers.
10
+
11
+ Where feasible, we contribute improvements and fixes back to y-prosemirror to support the broader ecosystem.
12
+
13
+ This package is designed for use with Tiptap and is not intended as a general-purpose Yjs binding for ProseMirror.
14
+
7
15
  ## Features
8
16
 
9
17
  * Sync ProseMirror state
package/dist/y-tiptap.cjs CHANGED
@@ -330,7 +330,7 @@ const restoreRelativeSelection = (tr, relSel, binding) => {
330
330
  relSel.anchor,
331
331
  binding.mapping
332
332
  );
333
- tr.setSelection(prosemirrorState.NodeSelection.create(tr.doc, anchor));
333
+ tr.setSelection(createSafeNodeSelection(tr, anchor));
334
334
  } else {
335
335
  const anchor = relativePositionToAbsolutePosition(
336
336
  binding.doc,
@@ -351,6 +351,23 @@ const restoreRelativeSelection = (tr, relSel, binding) => {
351
351
  }
352
352
  };
353
353
 
354
+ /**
355
+ * @param {import('prosemirror-state').Transaction} tr
356
+ * @param {number} pos
357
+ * @returns {import('prosemirror-state').Selection}
358
+ *
359
+ * Creates a NodeSelection if the position points to a valid node, otherwise
360
+ * creates a TextSelection near the position.
361
+ */
362
+ const createSafeNodeSelection = (tr, pos) => {
363
+ const $pos = tr.doc.resolve(pos);
364
+ if ($pos.nodeAfter) {
365
+ return prosemirrorState.NodeSelection.create(tr.doc, pos)
366
+ } else {
367
+ return prosemirrorState.TextSelection.near($pos)
368
+ }
369
+ };
370
+
354
371
  /**
355
372
  * @param {ProsemirrorBinding} pmbinding
356
373
  * @param {import('prosemirror-state').EditorState} state
@@ -1033,9 +1050,18 @@ const equalYTextPText = (ytext, ptexts) => {
1033
1050
  delta.every(/** @type {(d:any,i:number) => boolean} */ (d, i) =>
1034
1051
  d.insert === /** @type {any} */ (ptexts[i]).text &&
1035
1052
  object__namespace.keys(d.attributes || {}).length === ptexts[i].marks.length &&
1036
- object__namespace.every(d.attributes, (attr, yattrname) => {
1053
+ object__namespace.every(d.attributes, (attr, /** @type {string} */ yattrname) => {
1037
1054
  const markname = yattr2markname(yattrname);
1038
1055
  const pmarks = ptexts[i].marks;
1056
+
1057
+ const pmark = pmarks.find(/** @param {any} mark */ mark => mark.type.name === markname);
1058
+
1059
+ // Ensure the pmark is present in the ptexts before checking equality. When replacing a mark with another mark
1060
+ // the pmark will be missing from the ptexts and the equalAttrs will throw an error.
1061
+ if (!pmark) {
1062
+ return false
1063
+ }
1064
+
1039
1065
  return equalAttrs(attr, pmarks.find(/** @param {any} mark */ mark => mark.type.name === markname)?.attrs)
1040
1066
  })
1041
1067
  )