Hello,
we have developed a colloborative editing module using ProseMirror. The document is periodically auto saved under editing to persist its contents. If a user opens the document therefore it takes the content from the database and then applies any steps for a higher version for that document.
A user can edit and paste some text and in their own browser session and it is fine. If another user also had the same document open before this editing took place then they receive push notifications and the remote transactions are applied as expected. However, if a user reloads the web page or opens the document for a first time it seems quite easy to end up in a state where when trying to apply the steps on to the document fails with an error “TransformError: Inconsistent open depths”
An example is below. The content in the db for the prose mirror JSON content from the last auto save is {“type”:“doc”,“content”:[{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:“wa”}]}]}
Then we apply the following saved steps that a user performed
- {“stepType”:“replace”,“from”:2,“to”:2,“slice”:{“content”:[{“type”:“text”,“text”:“a”}]},“clientID”:1906592447}
- {“stepType”:“replace”,“from”:3,“to”:3,“slice”:{“content”:[{“type”:“text”,“text”:“d”}]},“clientID”:1906592447}
- {“stepType”:“replace”,“from”:4,“to”:4,“slice”:{“content”:[{“type”:“text”,“text”:“f”}]},“clientID”:1906592447}
- {“stepType”:“replace”,“from”:5,“to”:5,“slice”:{“content”:[{“type”:“text”,“text”:“a”}]},“clientID”:1906592447}
- {“stepType”:“replace”,“from”:6,“to”:6,“slice”:{“content”:[{“type”:“text”,“text”:“d”}]},“clientID”:1906592447}
- {“stepType”:“replace”,“from”:7,“to”:7,“slice”:{“content”:[{“type”:“text”,“text”:“f”}]},“clientID”:1906592447}
- {“stepType”:“replace”,“from”:8,“to”:8,“slice”:{“content”:[{“type”:“paragraph”},{“type”:“paragraph”}],“openStart”:1,“openEnd”:1},“structure”:true,“clientID”:1906592447}
- {“stepType”:“replace”,“from”:9,“to”:11,“slice”:{“content”:[{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:“Her tight boots twinged her feet as Jane skaled to the top of the rockface and looked out toward Mount Ranier, her grappling hook\u2019s sharp barb straining against the side of the rock a dozen meters above her head. She was stunned by the beauty of the surrounding scene every time.”}]},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:“It was morning in the mountains of Washington and she squinted in the bright and brilliant sunlight, cursing the fact that she had forgotten her specialized sunglasses on this climb, a rookie mistake she would just have to except. The breeze blew very cold air against her sweat-dotted brow even though the sun was all ready high in the sky. Higher and higher Jane climbed, heart pumping and adrenaline rising as the ground grew smaller and smaller below her until the trees were nothing more than a smattering of many different multicolored jewels in the ground\u2019s tan field. Smiling to herself as she reached a stopping point, Jane pushed up onto her knees and stood up straightening her spine so that she was practically walking a long the ledge on the side of the mountain, her body slanted against the horizon and the extremely blue sky.”}]},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:“Over the months after she had started making this climb a daily ritaull (this was climb number forty two), Jane had grown to treasure these moments when it was just her, her climbing equipment, a very big mountain and gravity; it was like a moving type of meditation that kept her sharp and kept her independence alive. Some mornings it was not easy to get herself out of bed and up the mountain, but she never regretted it once she was on the wall. It was good to remember what she was capable of and the challenge of the climb ensured that her recent change of circumstances didn\u2019t go to her head.”}]},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:“Finally, she hauled herself up over the top of the final ledge, reveling in the feeling of her feet on flat, solid ground once more. From this point of view she had an excellent view to the panoramic rivers, gorgeous mountains, and far off in the distance, the elegant cities that glistened in the sunlight with their tall metal towers and constant streams of cars, massive trucks, people running to and fro. The city was always shocking to her in it\u2019s extreme beauty even when she was surrounded by the majesty of nature.”}]},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:“There was a shrill, loud ring from her pocket. \u201cOh great,\u201d she exclaimed exasperatedly, and then frowned as she looked down at her cell phone without any hope of maintaining her morning peace.”}]},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:“Do you want to remove? Or you want me to delete myself?”}]},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:“This is the only thing”}]},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:"\u201cJack,\u201d she said shortly when she reluctantly pushed the button to take the call."}]},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:"\u201cYou sure took long enough to answer my call, you know,\u201d Jack replied sardonically. \u201cWhere are you right now? It\u2019s almost 9:00 AM and you\u2019re still not here.\u201d"}]},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:"\u201cI\u2019m taking some flex time,\u201d Jane responded. \u201cSince, you know, we\u2019re allowed to do those types of things.\u201d"}]},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:"Let\u2019s do this, you can try to remove "}]},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:“You can try to do this”}]},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:“Jack scoffed and Jane struggled not to groan. In the six months she\u2019d worked with Jack she had quickly learned that even the tiniest sign that she was not as much of a workaholic as he was would result in a huge attitude. She made the decision to update her resume this evening and then turned to go back down the mountain.”}]},{“type”:“paragraph”},{“type”:“paragraph”}]},“clientID”:1906592447}
The last step fails with the Inconsistent open depths error. The first 7 steps are applied fine. If I manually manipulate the from and to values of the 8th step to be from 9 and to 9 instead of from 9 and to 11 it works. I can tell you the user pasted that massive chunk of text in step 8.
I dump out the ProseMirror Json after applying each step on load so right before applying the 8th and failing step the document JSON is
{“type”:“doc”,“content”:[{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:“wadfadf”}]},{“type”:“paragraph”,“content”:[{“type”:“text”,“text”:“a”}]}]}
It seems like this error is something about a replacement operation straddling between nodes. Can someone please elaborate on what is it trying to tell me and what the issue with the series of steps above actually is? Is it because positions 10 and 11 are off the end of the document? I am just applying the steps generated from sendableSteps on one client which are broadcast to our central authority and persisted if accepted.
We are latest npm packages
“prosemirror-collab”: “^1.2.2”, “prosemirror-commands”: “^1.1.7”, “prosemirror-example-setup”: “^1.1.2”, “prosemirror-inputrules”: “^1.1.2”, “prosemirror-model”: “^1.14.0”, “prosemirror-schema-basic”: “^1.1.2”, “prosemirror-schema-list”: “^1.1.2”, “prosemirror-state”: “^1.3.3”, “prosemirror-tables”: “^1.1.1”, “prosemirror-view”: “^1.18.3”,
Thanks