Title: Decoration type for wrapping a range of sibling nodes in a container element
While working on a personal project, I ran into a limitation I think many ProseMirror editors would benefit from solving upstream: there’s no way to wrap a range of sibling block nodes in a decoration-injected container element.
The problem comes up whenever an editor needs section-level formatting — different CSS custom properties (or any styling) applied to different contiguous groups of top-level nodes. Think of a document where one section has column-count: 2 and the next is single-column, or one section has a narrower max-width than another, or different font-size / margin values per section.
For inline text properties, Decoration.node() works fine — you can set a different inline style on each individual node. But for properties that require a containing element (column layout, max-width, margin, and any CSS that needs to apply to a group rather than an individual node), there’s no decoration-based solution. Decoration.node() requires from/to to bracket exactly one node.
What I’d want is something like:
Decoration.wrap(from, to, {style: "column-count: 2; max-width: 29.7cm"})
…where from/to span a range of sibling nodes at the same depth, and a <div> wraps them — transparent to position mapping, like how MarkViewDesc wraps inline content with zero border.
Looking at the internals, MarkViewDesc already solves the same structural problem for inline content: it wraps runs of nodes in a DOM element that contributes no position offset. A block-level equivalent for decorations, modeled on the same pattern, seems like a natural extension.
Use cases I can see:
- Section-level formatting (different margins, font sizes, or orientations per section)
- Multi-column layouts where column count varies by section (common in academic papers: single-column abstract, two-column body)
- Chapter or part separators with different page widths
- Newsletter/magazine-style mixed layouts
Questions:
- Is this something you’d consider for prosemirror-view?
- Would you prefer a new
Decoration.wrap()type, or extendingDecoration.node()to relax the single-node constraint? - Are there position-mapping concerns beyond what
MarkViewDescalready handles? The pattern seems directly reusable for block content.
I’d be happy to implement this and submit a PR if the approach makes sense.