yjs / y-prosemirror

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

Cursor plugin causes word breaking #97

Closed bkempe closed 2 years ago

bkempe commented 2 years ago

Checklist

Describe the bug The cursor plugin breaks words which can be observed especially when the cursor is placed in long words and using a smaller width of the text space.

To Reproduce Steps to reproduce the behavior:

  1. Open two browser windows with width 800px
  2. In both windows, go to https://demos.yjs.dev/prosemirror/prosemirror.html
  3. Paste "Test test 123 Test test 123 Test test 123 Test test 123 Test test 123 Test test 123 Test test 123 Donaudampfschiffahrtsgesellschaftskapitän" in one window
  4. Place the cursor after Donaudampf in one window
  5. See that the word gets broken in the other window.

The DOM looks like this:

<p>Test test 123 Test test 123 Test test 123 Test test 123 Test test 123 Test test 123 Test test 123 Donaudampf<span 
class="ProseMirror-yjs-cursor ProseMirror-widget" style="border-color: #ffa500" contenteditable="false"><div 
style="background-color: #ffa500">User: 255092616</div></span>schiffahrtsgesellschaftskapitän</p>

Expected behavior Words should not get broken. Example: https://slate-yjs.dev/remote-cursors-overlay

Screenshots

Screen Shot 2022-03-21 at 20 27 06

Additional context

We are a Sponsor :)

dmonad commented 2 years ago

Hi @bkempe,

As we discussed in the last Y Community meeting, there is no good solution for this.

The reason why the words break is that the user-name is represented using a HTML block element. WebKit will automatically break when they see a block element. Gecko-based browsers won't break the word.

Btw, if you the the div to display: none, then everything will work as expected. But you won't have any user-names above the cursors anymore.

.ProseMirror-yjs-cursor > div {
  display: none;
}

An alternative solution would be to use the same approach that quill-cursors is using and render the cursors as absolutely-positioned elements. However, my experience with this approach is that it is very performant for large documents and requires extreme care to implement correctly.

I'll leave this issue open in case somebody finds a better solution.

bkempe commented 2 years ago

@dmonad Thanks for looking into this! One compromise solution may be to only wrap URLs(which are the most likely items to be long in a typical notepad) in a block.

dmonad commented 2 years ago

That makes sense. You can basically set them in a <div style="white-space: nowrap;"> element.

dmonad commented 2 years ago

There's now a solution to this problem. See https://github.com/yjs/y-codemirror.next/pull/12

I'll be porting the solution to y-prosemirror (probably in the next ~two weeks). But if somebody wants to give this a try, that would be great!

bkempe commented 2 years ago

@dmonad BTW, this is how Atlassian, which also uses Prosemirror, does it: https://bitbucket.org/atlassian/atlassian-frontend-mirror/src/f388d30ecaa34cf83e8d8a55167b800c9f027db9/editor/editor-core/src/plugins/collab-edit/utils.ts?at=master#lines-105

dmonad commented 2 years ago

This issue is finally fixed in y-prosemirror@v1.0.19 :tada: