@@ -5,7 +5,7 @@ import browser from "./browser"
55import { DOMReader , DOMPoint , LineBreakPlaceholder } from "./domreader"
66import { findCompositionNode } from "./docview"
77import { EditorSelection , Text , Transaction , TransactionSpec } from "@codemirror/state"
8- import { skipAtomsForSelection } from "./cursor"
8+ import { skipAtomsForSelection , skipAtomicRanges } from "./cursor"
99
1010export class DOMChange {
1111 bounds : {
@@ -175,10 +175,20 @@ export function applyDOMChangeInner(
175175
176176function applyDefaultInsert ( view : EditorView , change : { from : number , to : number , insert : Text } ,
177177 newSel : EditorSelection | null ) : Transaction {
178- let tr : TransactionSpec , startState = view . state , sel = startState . selection . main
179- if ( change . from >= sel . from && change . to <= sel . to && change . to - change . from >= ( sel . to - sel . from ) / 3 &&
180- ( ! newSel || newSel . main . empty && newSel . main . from == change . from + change . insert . length ) &&
181- view . inputState . composing < 0 ) {
178+ let tr : TransactionSpec , startState = view . state , sel = startState . selection . main , inAtomic = - 1
179+ if ( change . from == change . to && change . from < sel . from || change . from > sel . to ) {
180+ let side : - 1 | 1 = change . from < sel . from ? - 1 : 1 , pos = side < 0 ? sel . from : sel . to
181+ let moved = skipAtomicRanges ( startState . facet ( atomicRanges ) . map ( f => f ( view ) ) , pos , side )
182+ if ( change . from == moved ) inAtomic = moved
183+ }
184+ if ( inAtomic > - 1 ) {
185+ tr = {
186+ changes : change ,
187+ selection : EditorSelection . cursor ( change . from + change . insert . length , - 1 )
188+ }
189+ } else if ( change . from >= sel . from && change . to <= sel . to && change . to - change . from >= ( sel . to - sel . from ) / 3 &&
190+ ( ! newSel || newSel . main . empty && newSel . main . from == change . from + change . insert . length ) &&
191+ view . inputState . composing < 0 ) {
182192 let before = sel . from < change . from ? startState . sliceDoc ( sel . from , change . from ) : ""
183193 let after = sel . to > change . to ? startState . sliceDoc ( change . to , sel . to ) : ""
184194 tr = startState . replaceSelection ( view . state . toText (
@@ -188,7 +198,7 @@ function applyDefaultInsert(view: EditorView, change: {from: number, to: number,
188198 let mainSel = newSel && newSel . main . to <= changes . newLength ? newSel . main : undefined
189199 // Try to apply a composition change to all cursors
190200 if ( startState . selection . ranges . length > 1 && view . inputState . composing >= 0 &&
191- change . to <= sel . to && change . to >= sel . to - 10 ) {
201+ change . to <= sel . to && change . to >= sel . to - 10 ) {
192202 let replaced = view . state . sliceDoc ( change . from , change . to )
193203 let compositionRange : { from : number , to : number } , composition = newSel && findCompositionNode ( view , newSel . main . head )
194204 if ( composition ) {
@@ -203,11 +213,11 @@ function applyDefaultInsert(view: EditorView, change: {from: number, to: number,
203213 return { changes, range : mainSel || range . map ( changes ) }
204214 let to = range . to - offset , from = to - replaced . length
205215 if ( range . to - range . from != size || view . state . sliceDoc ( from , to ) != replaced ||
206- // Unfortunately, there's no way to make multiple
207- // changes in the same node work without aborting
208- // composition, so cursors in the composition range are
209- // ignored.
210- range . to >= compositionRange . from && range . from <= compositionRange . to )
216+ // Unfortunately, there's no way to make multiple
217+ // changes in the same node work without aborting
218+ // composition, so cursors in the composition range are
219+ // ignored.
220+ range . to >= compositionRange . from && range . from <= compositionRange . to )
211221 return { range}
212222 let rangeChanges = startState . changes ( { from, to, insert : change ! . insert } ) , selOff = range . to - sel . to
213223 return {
0 commit comments