Hello! I am trying to implement a line background layer as mentioned in Line background color and selection layering . This is my code:
import { RectangleMarker } from '@codemirror/view';
import { layer } from '@codemirror/view';
export const backlayer = layer({
update: (update) => update.docChanged,
markers: (view) => {
const offsetTop = 14; // how to not hard code these numbers?
const offsetLeft = 4;
return view.viewportLineBlocks.map((block) => {
const { left } = view.coordsAtPos(block.to);
return new RectangleMarker(
'cm-backlayer',
offsetLeft, // left
block.top + offsetTop, // top
left, // width
block.height // height
);
});
},
});
This works perfectly but when I turn on lineWrapping, the rectangles won’t fit for wrapped lines:
Here, line 5 would have needed two rectangles… the reason why this happens is that view.viewportLineBlocks
only returns one LineBlock
per line, even if a line spans multiple real lines (like line 5). Obviously, a single rectangle won’t work to wrap 2 lines of different length…
Is there another way to get the line blocks for each individual “real” line? Or maybe there’s a completely different way to solve this problem?
I have also tried to use RectangleMarker.forRange
:
RectangleMarker.forRange(
view,
'cm-backlayer',
SelectionRange.fromJSON({
from: 0,
to: view.state.doc.length,
anchor: 0,
head: view.state.doc.length,
empty: false,
assoc: 0,
bidiLevel: null,
}),
)
The problem here is that I will just get a giant rectangle that is also behind empty areas.
Thanks for reading, I hope someone can help me with this