yjs / y-prosemirror

ProseMirror editor binding for Yjs
https://demos.yjs.dev/prosemirror/prosemirror.html
MIT License
345 stars 120 forks source link

Use `findDiffStart` instead of `equalityDeep` #46

Closed BrianHung closed 3 years ago

BrianHung commented 3 years ago

Use ProseMirror method findDiffStart to compare / diff documents instead of converting to JSON and then using lib0's equalityDeep:

- !fun.equalityDeep(view.state.doc.type.createAndFill().content.toJSON(), view.state.doc.content.toJSON())
+ view.state.doc.content.findDiffStart(view.state.doc.type.createAndFill().content) != null

Reasoning is equalityDeep fails on two equal JSON objects created by ProseMirror's toJSON(), because ProseMirror uses Object.empty(null) to initialize node attrs, which results in equalityDeep returning false because Object.create(null).constructor is undefined (instead of Object as expected). See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#custom_and_null_objects.

Another work around would be to use

!fun.equalityDeep(
  JSON.parse(JSON.stringify(view.state.doc.type.createAndFill().content.toJSON())), 
  JSON.parse(JSON.stringify(view.state.doc.content.toJSON())),
);

which works correctly by converting Object.create(null) and forcing it to inherit the Object.constructor method. But

  1. we're already working with ProseMirror objects, and
  2. it requires an extra step in JSON.parse(JSON.stringify(.
dmonad commented 3 years ago

Thanks! @BrianHung Merged and published the fix in v1.0.9