Selection bug?

I am trying to achieve that the text, when wrapped it, maintains the indentation, but, when i try to select the text this happens. someone know how to solve this issue?

the selection goes from “r” of “risks”. and ends in left of [!TIP]

Note that the text “critical … risk” is at the same cm-line.

Are you doing anything odd with those widgets? Like making them float or absolutely positioning them?

This is all the css for that element

lineHeight: “1lh”,
display: “inline-block”,
paddingLeft: “6px”,
textIndent: “-7px”,
ariaHidden: “true”

Can you condense this down to a minimal example that can be run on codemirror.net/try?

Yes, i already did it, i try my best to replicated

import {minimalSetup , EditorView} from "codemirror"
import {markdown} from "@codemirror/lang-markdown"
import {languages} from "@codemirror/language-data"
import {ViewPlugin} from "@codemirror/view";
import { Decoration } from "@codemirror/view";
import { syntaxTree } from "@codemirror/language";

export const visibleNodes = ( view, iterator ) => {
    for (const { from, to } of view.visibleRanges) 
        syntaxTree(view.state).iterate({ ...iterator, from, to });
}

export function decorator(view, _) {
    const iterable = [ "Document", "ListItem", "BulletList", "OrderedList" ]

    const types = { Blockquote: () => { } }
    
    const marks = {
        QuoteMark: (from, to, type) => {
            const class_ = ["qt-mk"];
            if (type in quoteTypes) class_.push(quoteTypes[type]);
            else class_.push(quoteTypes["none"]);
            
            return Decoration.mark({
                class: class_.join(" ")
            }).range(from, to)
        },
        BlockquoteLine: (from, selected) => Decoration.line({ class: "bq-line " + (selected ? "sw": "") }).range(from),
        quoteLine: (from, to, offset) => {
            const width = `calc(100% - ${Math.max(0, offset) + 1.2}ch)`;
            return Decoration.mark({
                class: "bq-text-line",
                attributes: { style: `width: ${width}` }
            }).range(from, to)
        }
    }
    
    const getDecorations = (view, node, startLine, lines) => {
        const decorations = [];
        const { from, to } = node;
        const begin = startLine.number;
        
        const iterator = (start, end) => {
            let marksCount = 0;
            const stack = [];
            let marksEnd = 0;
            
            return {
                enter({ name, node, from, to }) {
                    if (name === "Blockquote") stack.push("none");
                    if (name === "QuoteMark") {
                        marksEnd = to;
                        marksCount++;
                    }
                },
                leave({ name, from, to }) {
                    if (name === "Paragraph") {
                        if (marksEnd < end) {
                            decorations.push(marks.quoteLine(marksEnd, end, marksEnd - start));
                        }
                    }
                }
            }
        }
        
        for ( let index = begin; index < lines + begin; index++) {
            const { from, to } = view.state.doc.line(index);
            decorations.push(marks.BlockquoteLine(from, true));
            
            syntaxTree(view.state).iterate({ from, to, ... iterator(from, to) })
        }
        
        
        return decorations
    }

    const widgets = [];
    
    visibleNodes(view, { 
        enter: ({ name }) => !(name in iterable),
        leave: ({ name, from, to, node}) => { 
            if (name !== "Blockquote") return;
            console.log("hola")
            const lines = view.state.sliceDoc(from, to).split("\n");
            const startLine = view.state.doc.lineAt(from);
            
            widgets.push(... getDecorations(view, node, startLine, lines.length))
        },
    });
    
    return Decoration.set(widgets, true)
}

export const PluginFactory = (func, conf, pluginSpec = {}) =>  {
    const decorator = class Decorator {
        decorations;
        conf;

        constructor(view) {
            this.conf = conf;
            this.decorations = func(view, this.conf);
        }

        update(update) {
            if (
                update.docChanged ||
                update.viewportChanged ||
                update.selectionSet
            ) this.decorations = func(update.view, this.conf);
        }
    }

    return ViewPlugin.fromClass(decorator, { decorations: (v) => v.decorations, ...pluginSpec })
}

export const coreTheme = () => {
    const width = "4px";
    return EditorView.baseTheme({
        "& .bq-text-line": { 
            lineHeight: "1lh",
            display: "inline-block",
            paddingLeft: "6px",
            textIndent: "-7px",
            ariaHidden: "true"
        },
    })
}
let view = new EditorView({
  doc: "some lines before\n> This is an example were the lime wraps, for that it need so much text, and more, and more and more.",
  extensions: [
    minimalSetup,
    EditorView.lineWrapping,
    PluginFactory(decorator, {}),
    coreTheme(),
    markdown({codeLanguages: languages})
  ],
  parent: document.body
})

and it works exactly like the other:

image.

Thanks for your time btw