Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge cd543b6 into 8fa632c
Browse files Browse the repository at this point in the history
  • Loading branch information
scofalik committed Sep 21, 2018
2 parents 8fa632c + cd543b6 commit b74b85f
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/model/operation/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,56 @@ setTransformation( MergeOperation, MergeOperation, ( a, b, context ) => {
}
}

// Case 2:
//
// Same merge source position but different target position.
//
// This can happen during collaboration. For example, if one client merged a paragraph to the previous paragraph
// and the other person removed that paragraph and merged the same paragraph to something before:
//
// Client A:
// <p>Foo</p><p>Bar</p><p>[]Xyz</p>
// <p>Foo</p><p>BarXyz</p>
//
// Client B:
// <p>Foo</p>[<p>Bar</p>]<p>Xyz</p>
// <p>Foo</p><p>[]Xyz</p>
// <p>FooXyz</p>
//
// In this case we need to decide where finally "Xyz" will land:
//
// <p>FooXyz</p> graveyard: <p>Bar</p>
// <p>Foo</p> graveyard: <p>BarXyz</p>
//
// Let's move it in a way so that a merge operation that does not target to graveyard is more important so that
// nodes does not end up in the graveyard. It makes sense. Both for Client A and for Client B "Xyz" finally did not
// end up in the graveyard (see above).
//
// If neither or both operations point to graveyard, then let `aIsStrong` decide.
//
if ( a.sourcePosition.isEqual( b.sourcePosition ) && !a.targetPosition.isEqual( b.targetPosition ) && !context.bWasUndone ) {
const aToGraveyard = a.targetPosition.root.rootName == '$graveyard';
const bToGraveyard = b.targetPosition.root.rootName == '$graveyard';

// If `aIsWeak` it means that `a` points to graveyard while `b` doesn't. Don't move nodes then.
const aIsWeak = aToGraveyard && !bToGraveyard;

// If `bIsWeak` it means that `b` points to graveyard while `a` doesn't. Force moving nodes then.
const bIsWeak = bToGraveyard && !aToGraveyard;

// Force move if `b` is weak or neither operation is weak but `a` is stronger through `context.aIsStrong`.
const forceMove = bIsWeak || ( !aIsWeak && context.aIsStrong );

if ( forceMove ) {
const sourcePosition = b.targetPosition._getTransformedByMergeOperation( b );
const targetPosition = a.targetPosition._getTransformedByMergeOperation( b );

return [ new MoveOperation( sourcePosition, a.howMany, targetPosition, 0 ) ];
} else {
return [ new NoOperation( 0 ) ];
}
}

// The default case.
//
if ( a.sourcePosition.hasSameParentAs( b.targetPosition ) ) {
Expand Down
12 changes: 12 additions & 0 deletions tests/model/operation/transform/merge.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,18 @@ describe( 'transform', () => {

expectClients( '<paragraph>For</paragraph>' );
} );

it( 'merged elements and some text', () => {
john.setData( '<paragraph>Foo</paragraph><paragraph></paragraph>[]<paragraph>Bar</paragraph>' );
kate.setData( '<paragraph>F[oo</paragraph><paragraph></paragraph><paragraph>Ba]r</paragraph>' );

john.merge();
kate.delete();

syncClients();

expectClients( '<paragraph>Fr</paragraph>' );
} );
} );

describe( 'by wrap', () => {
Expand Down

0 comments on commit b74b85f

Please sign in to comment.