Skip to content

Commit

Permalink
Don't put the DOM selection between block elements
Browse files Browse the repository at this point in the history
FIX: Fix an issue where the cursor could be shown in a position that doesn't allow
a cursor when the selection is in a block widget.

See https://discuss.codemirror.net/t/gutter-marker-next-to-decoration-replaced-lines-with-a-widget/7075
  • Loading branch information
marijnh committed Sep 11, 2023
1 parent 832e684 commit f4d79ef
Showing 1 changed file with 20 additions and 3 deletions.
23 changes: 20 additions & 3 deletions src/docview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,8 @@ export class DocView extends ContentView {
this.forceSelection = false

let main = this.view.state.selection.main
// FIXME need to handle the case where the selection falls inside a block range
let anchor = this.domAtPos(main.anchor)
let head = main.empty ? anchor : this.domAtPos(main.head)
let anchor = this.moveToLine(this.domAtPos(main.anchor))
let head = main.empty ? anchor : this.moveToLine(this.domAtPos(main.head))

// Always reset on Firefox when next to an uneditable node to
// avoid invisible cursor bugs (#111)
Expand Down Expand Up @@ -320,6 +319,24 @@ export class DocView extends ContentView {
sel.collapse(anchorNode, anchorOffset)
}

// If a position is in/near a block widget, move it to a nearby text
// line, since we don't want the cursor inside a block widget.
moveToLine(pos: DOMPos) {
// Block widgets will return positions before/after them, which
// are thus directly in the document DOM element.
let dom = this.dom!, newPos
if (pos.node != dom) return pos
for (let i = pos.offset; !newPos && i < dom.childNodes.length; i++) {
let view = ContentView.get(dom.childNodes[i])
if (view instanceof LineView) newPos = view.domAtPos(0)
}
for (let i = pos.offset - 1; !newPos && i >= 0; i--) {
let view = ContentView.get(dom.childNodes[i])
if (view instanceof LineView) newPos = view.domAtPos(view.length)
}
return newPos ? new DOMPos(newPos.node, newPos.offset, true) : pos
}

nearest(dom: Node): ContentView | null {
for (let cur: Node | null = dom; cur;) {
let domView = ContentView.get(cur)
Expand Down

0 comments on commit f4d79ef

Please sign in to comment.