Request: multi-line decorations

The restriction that decorations can only span a single line before being split is typically OK if the decorations are purely for styling.

But there are some cases where it would be useful to decorate multiple lines of code with a single element, particularly when that element may have some semantic meaning. For example, we might want to render a single <blockquote> element that spans multiple lines. With multiple Decoration.line decorations we can create something that looks like a block quote, but it’s impossible to create a single element. This makes it impossible to implement accessible, semantic HTML.

Another example might be rendering a comment or annotation that applies to several lines. Visually it’s not too difficult to make it look like multiple line decorations are part of the same group, but it’s not really possible to convey that semantically, and it would be much cleaner and more maintainable to render a single element.

There are also cases where being restricted to an element per line makes certain styles impossible. You can’t apply a box-shadow or outline around a multi-line chunk of text, for example. ::hover and similar stylings also become much harder when things are split across multiple elements, requiring JS-based event handlers instead of pure CSS.

In a project I’m currently working on, we’ve worked around this by tricking the editor into thinking that its entire contents are one line by setting the line separator to a character that isn’t present in the content: EditorState.lineSeparator.of(String.fromCodePoint(0xe000)). With this we’ve been able to render mark decorations that span many lines. But obviously this is a huge hack - it breaks all of the APIs that work around lines, built-in language support, most of the default line-level keymaps and interactions, the entire gutter and line numbers, virtualization, and probably many other things I haven’t discovered yet.

I’d really love to have a better solution so we can get rid of the hack, but the only thing I’ve been able to come up with now is implementing our own EditorView from scratch. There doesn’t seem to be a way around this currently.

Given the DOM structure of CodeMirror’s view, I don’t expect we’d ever have mark decorations that span multiple lines - that would require splitting a .cm-line apart into multiple elements, which doesn’t seem feasible or desirable.

On the other hand, grouping multiple .cm-line elements together into a single container feels more realistic and would solve the problem for block-level decorations, which I think would cover the majority of use cases here.

API-wise, I’d imagine this would probably be a new decoration type - something like Decoration.lines or Decoration.lineGroup.

If you think this is a realistic concept and if you’d be open to contributions, we might be able to contribute some engineering time to help build this out.

This is indeed not something the current system is built for. I’m not terribly interested in having engineering time contributed, since I’d still be on the hook to review, integrate, and maintain the result. But if you’d be open to paying for an implementation, we can discuss that over email.

Makes sense to me re the contributing front. I’ll reach out over email :+1: