@@ -50,6 +50,11 @@ addTransformationCase( AttributeDelta, WeakInsertDelta, ( a, b, context ) => {
5050
5151// Add special case for AttributeDelta x SplitDelta transformation.
5252addTransformationCase ( AttributeDelta , SplitDelta , ( a , b , context ) => {
53+ // Do not apply special transformation case if `SplitDelta` has `NoOperation` as the second operation.
54+ if ( ! b . position ) {
55+ return defaultTransform ( a , b , context ) ;
56+ }
57+
5358 const splitPosition = new Position ( b . position . root , b . position . path . slice ( 0 , - 1 ) ) ;
5459
5560 const deltas = defaultTransform ( a , b , context ) ;
@@ -173,6 +178,11 @@ addTransformationCase( MergeDelta, MoveDelta, ( a, b, context ) => {
173178
174179// Add special case for SplitDelta x SplitDelta transformation.
175180addTransformationCase ( SplitDelta , SplitDelta , ( a , b , context ) => {
181+ // Do not apply special transformation case if `SplitDelta` has `NoOperation` as the second operation.
182+ if ( ! a . position || ! b . position ) {
183+ return defaultTransform ( a , b , context ) ;
184+ }
185+
176186 const pathA = a . position . getParentPath ( ) ;
177187 const pathB = b . position . getParentPath ( ) ;
178188
@@ -202,6 +212,11 @@ addTransformationCase( SplitDelta, SplitDelta, ( a, b, context ) => {
202212
203213// Add special case for SplitDelta x UnwrapDelta transformation.
204214addTransformationCase ( SplitDelta , UnwrapDelta , ( a , b , context ) => {
215+ // Do not apply special transformation case if `SplitDelta` has `NoOperation` as the second operation.
216+ if ( ! a . position ) {
217+ return defaultTransform ( a , b , context ) ;
218+ }
219+
205220 // If incoming split delta tries to split a node that just got unwrapped, there is actually nothing to split,
206221 // so we discard that delta.
207222 if ( a . position . root == b . position . root && compareArrays ( b . position . path , a . position . getParentPath ( ) ) === 'same' ) {
@@ -213,6 +228,11 @@ addTransformationCase( SplitDelta, UnwrapDelta, ( a, b, context ) => {
213228
214229// Add special case for SplitDelta x WrapDelta transformation.
215230addTransformationCase ( SplitDelta , WrapDelta , ( a , b , context ) => {
231+ // Do not apply special transformation case if `SplitDelta` has `NoOperation` as the second operation.
232+ if ( ! a . position ) {
233+ return defaultTransform ( a , b , context ) ;
234+ }
235+
216236 // If split is applied at the position between wrapped nodes, we cancel the split as it's results may be unexpected and
217237 // very weird. Even if we do some "magic" we don't know what really are users' expectations.
218238
@@ -264,7 +284,12 @@ addTransformationCase( SplitDelta, WrapDelta, ( a, b, context ) => {
264284} ) ;
265285
266286// Add special case for SplitDelta x WrapDelta transformation.
267- addTransformationCase ( SplitDelta , AttributeDelta , ( a , b ) => {
287+ addTransformationCase ( SplitDelta , AttributeDelta , ( a , b , context ) => {
288+ // Do not apply special transformation case if `SplitDelta` has `NoOperation` as the second operation.
289+ if ( ! a . position ) {
290+ return defaultTransform ( a , b , context ) ;
291+ }
292+
268293 a = a . clone ( ) ;
269294
270295 const splitPosition = new Position ( a . position . root , a . position . path . slice ( 0 , - 1 ) ) ;
@@ -290,6 +315,11 @@ addTransformationCase( SplitDelta, AttributeDelta, ( a, b ) => {
290315
291316// Add special case for UnwrapDelta x SplitDelta transformation.
292317addTransformationCase ( UnwrapDelta , SplitDelta , ( a , b , context ) => {
318+ // Do not apply special transformation case if `SplitDelta` has `NoOperation` as the second operation.
319+ if ( ! b . position ) {
320+ return defaultTransform ( a , b , context ) ;
321+ }
322+
293323 // If incoming unwrap delta tries to unwrap node that got split we should unwrap the original node and the split copy.
294324 // This can be achieved either by reverting split and applying unwrap to singular node, or creating additional unwrap delta.
295325 if ( a . position . root == b . position . root && compareArrays ( a . position . path , b . position . getParentPath ( ) ) === 'same' ) {
@@ -316,9 +346,13 @@ addTransformationCase( WeakInsertDelta, AttributeDelta, ( a, b ) => {
316346
317347// Add special case for WrapDelta x SplitDelta transformation.
318348addTransformationCase ( WrapDelta , SplitDelta , ( a , b , context ) => {
349+ // Do not apply special transformation case if `SplitDelta` has `NoOperation` as the second operation.
350+ if ( ! b . position ) {
351+ return defaultTransform ( a , b , context ) ;
352+ }
353+
319354 // If incoming wrap delta tries to wrap range that contains split position, we have to cancel the split and apply
320355 // the wrap. Since split was already applied, we have to revert it.
321-
322356 const sameRoot = a . range . start . root == b . position . root ;
323357 const operateInSameParent = sameRoot && compareArrays ( a . range . start . getParentPath ( ) , b . position . getParentPath ( ) ) === 'same' ;
324358 const splitInsideWrapRange = a . range . start . offset < b . position . offset && a . range . end . offset >= b . position . offset ;
@@ -349,15 +383,22 @@ addTransformationCase( WrapDelta, SplitDelta, ( a, b, context ) => {
349383// Add special case for RenameDelta x SplitDelta transformation.
350384addTransformationCase ( RenameDelta , SplitDelta , ( a , b , context ) => {
351385 const undoMode = context . aWasUndone || context . bWasUndone ;
352- const posBeforeSplitParent = new Position ( b . position . root , b . position . path . slice ( 0 , - 1 ) ) ;
386+
387+ // The "clone operation" may be `InsertOperation`, `ReinsertOperation`, `MoveOperation` or `NoOperation`.
388+ // `MoveOperation` has `targetPosition` which we want to use. `NoOperation` has no `position` and we don't use special case then.
389+ let insertPosition = b . _cloneOperation . position || b . _cloneOperation . targetPosition ;
390+
391+ if ( insertPosition ) {
392+ insertPosition = insertPosition . getShiftedBy ( - 1 ) ;
393+ }
353394
354395 const deltas = defaultTransform ( a , b , context ) ;
355396
356- if ( ! undoMode && a . operations [ 0 ] . position . isEqual ( posBeforeSplitParent ) ) {
397+ if ( insertPosition && ! undoMode && a . operations [ 0 ] . position . isEqual ( insertPosition ) ) {
357398 // If a node that has been split has it's name changed, we should also change name of
358399 // the node created during splitting.
359400 const additionalRenameDelta = a . clone ( ) ;
360- additionalRenameDelta . operations [ 0 ] . position = posBeforeSplitParent . getShiftedBy ( 1 ) ;
401+ additionalRenameDelta . operations [ 0 ] . position = insertPosition . getShiftedBy ( 1 ) ;
361402
362403 deltas . push ( additionalRenameDelta ) ;
363404 }
@@ -368,12 +409,19 @@ addTransformationCase( RenameDelta, SplitDelta, ( a, b, context ) => {
368409// Add special case for SplitDelta x RenameDelta transformation.
369410addTransformationCase ( SplitDelta , RenameDelta , ( a , b , context ) => {
370411 const undoMode = context . aWasUndone || context . bWasUndone ;
371- const posBeforeSplitParent = new Position ( a . position . root , a . position . path . slice ( 0 , - 1 ) ) ;
412+
413+ // The "clone operation" may be `InsertOperation`, `ReinsertOperation`, `MoveOperation` or `NoOperation`.
414+ // `MoveOperation` has `targetPosition` which we want to use. `NoOperation` has no `position` and we don't use special case then.
415+ let insertPosition = a . _cloneOperation . position || a . _cloneOperation . targetPosition ;
416+
417+ if ( insertPosition ) {
418+ insertPosition = insertPosition . getShiftedBy ( - 1 ) ;
419+ }
372420
373421 // If element to split had it's name changed, we have to reflect this by creating additional rename operation.
374- if ( ! undoMode && b . operations [ 0 ] . position . isEqual ( posBeforeSplitParent ) ) {
422+ if ( insertPosition && ! undoMode && b . operations [ 0 ] . position . isEqual ( insertPosition ) ) {
375423 const additionalRenameDelta = b . clone ( ) ;
376- additionalRenameDelta . operations [ 0 ] . position = posBeforeSplitParent . getShiftedBy ( 1 ) ;
424+ additionalRenameDelta . operations [ 0 ] . position = insertPosition . getShiftedBy ( 1 ) ;
377425
378426 // `nodes` is a property that is available only if `SplitDelta` `a` has `InsertOperation`.
379427 // `SplitDelta` may have `ReinsertOperation` instead of `InsertOperation`.
0 commit comments