Hiding widget buffers for better text wrapping

My understanding is that widget buffers exist to work around browser bugs with contenteditable.

I want to avoid unnecessary text wrapping by adding display: none to .cm-widgetBuffer. Specifically, my use-case is to avoid punctuation after a widget from being wrapped to the next line.

Would it be safe to do so if I guarantee that any selection that touches a widget immediately replaces that widget with a non-widget decoration?

Doing this does seems to work without issue in simple cases, but could there be edge cases where it would re-introduce the browser bugs that the widget buffers were meant to work around?

1 Like

Maybe. But what about other widgets added by other extensions?

I spent some more time looking for alternatives to the <img> element hack that do not cause line wrapping, but failed to find any that are as practical. (Zero-width characters can’t be distinguished from content text, on the DOM level, and thus tend to find ways to bleed into the document through weird browser editing behavior. The element needs to be editable, because it is intended to fix a number of misbehaviors that occur when the cursor is next to uneditable elements. But that means composite elements that aren’t just a single atomic thing will cause all kinds of issues with the cursor and inserted text ending up inside of them, or native editing actions mixing them up with the real content.)

1 Like

Thank you marijn for taking another look at this. It’s a shame the browsers still have these bugs we have to work around; I’m tempted to take a try at fixing them upstream myself = P.

That’s a good point. For anyone else with a similar situation, here’s a way to only target the buffers of specific widgets:

EditorView.baseTheme({
  ':is(.cm-widgetBuffer:has(+ .my-widget), .my-widget + .cm-widgetBuffer)': {
    display: 'none'
  },
})