Decorating whole words and individual letters

Hi all,

I’m running into an issue with overlapping decorations in ProseMirror. I have two plugins:

  1. One that colors every other letter of a word in a different color.
  2. Another that adds a tooltip in the middle of each word, always visible.

Ideally, this would be simple using two inline decorations – one for coloring every other letter, and one for marking each word (allowing me to position a tooltip via ::before or ::after). However, these two decorations collide, interleaving and creating multiple DOM elements of the tooltip. This seems pretty expected.

I tried using a widget decoration for the tooltip, approximating the size. While it mostly worked, the tooltips weren’t perfectly centered, and worse, it caused issues on Android phones, making the keyboard hide and reappear when backspacing / deleting the widget character.

I also attempted modifying toDOM() for the text node to wrap words in a <span>, like this:

text: {
  group: "inline",
  toDOM(node) {
    return ["span", { class: "text-wrapper" }, node.text];
  }
}

But I couldn’t get it working as expected.

Is there another approach I might be missing? It seems like inline decorations could be the cleanest solution, but alas, don’t work. Any suggestions?

Thanks!

Indeed, this isn’t supported—text content is divided into chunks based on decoration boundaries, and each chunk gets wrapped in decoration nodes separately.

I don’t really have a suggestion for this use case. You could try with marks on the words, but that’s kind of ugly in that it stores information in the document that’s really presentation-related.

I figured as much—thanks for confirming!

I’ve been working on this a bit, and I noticed that if I set a larger line-height, WebKit browsers display a large caret rather than the font-size one. Have you come across this and found any workaround? I realize ProseMirror isn’t what’s rendering the caret, but I’m hoping this is a known issue.

Here’s a CodePen that reproduces it:

https://codepen.io/punk-plan6281/pen/RNbXpxR

And this is how it renders in Safari:

I can’t be too annoyed about that, but I thought I’d ask.

Indeed, the caret is the native one, and browsers aren’t always very reasonable about how they draw it. I don’t know any workaround for this.