Show widget decoration at the start of certain words

Hello everyone, any ideas would be appreciated :pray:

What I want to do

I want to display a UI element (not a CSS pseudo-element) at the start of certain words within the editor. A key requirement is that the container width is not fixed. If a word wraps onto the next line due to line breaks, I need the UI element to wrap with it so that it stays at the beginning of the word on the new line.

<p>Hello <div class="widget-decoration"/>World</p>
<!-- ^ bad, "World" will break into a new line,
       but .widget-decoration stays on the first line. 
       Unaware of any CSS that could fix this. -->

<p>Hello <span class="inline-decoration"><div class="widget-decoration"/>World</span></p>
<!-- ^ good, but DOM structure can't be achieved with ProseMirror? -->

How I do it

  1. Wrap words in a span via Decoration.inline.
  2. Hook into view updates and manually render DOM elements inside the nodes produced by Decoration.inline.
  3. Use ignoreMutation to avoid parsing the manually rendered DOM nodes

I hate manually modifying ProseMirror DOM. Any alternative approaches would be greatly appreciated!

Thanks, V!

PS. Can’t use marks. I could achieve the desired structure using Marks, however since I’m in a collaborative environment, I don’t want to be modify the document to achieve what is a view layer funcionality.

Does an inline decoration with a widget decoration (with a positive side option) at its start not produce a structure like this?

Hey, thanks for response. No luck using side: 1. Here’s a jsfiddle playground

DecorationSet.create(doc, [
  Decoration.widget(8, createEl(), {
    side: 1,
  }),
  Decoration.inline(8, 13, { class: "inline-decoration" }),
]);

// Produces
// <span class="widget-decoration ProseMirror-widget" contenteditable="false"></span>
// <span class="inline-decoration">world</span>
//
// But also, if I bump 8 to 9, making widget inside the inline, I get
// <span class="inline-decoration">w</span>
// <span class="widget-decoration ProseMirror-widget" contenteditable="false"></span>
// <span class="inline-decoration">orld</span>

Ah, indeed, inline decorations aren’t drawn around widgets. It looks like the structure you are looking for cannot be created with ProseMirror decorations.

1 Like

I see, thank you for confirming. Now going with ignoreMutation approach feels more justified :+1:

1 Like