This commit is contained in:
parent
a2fbba682e
commit
b4259b767c
2 changed files with 608 additions and 24 deletions
|
|
@ -143,6 +143,9 @@ export interface ReconcileApi {
|
|||
* This is the primary function for 3-way text merging. Unlike traditional merge tools
|
||||
* that produce conflict markers, this function automatically resolves conflicts by
|
||||
* applying both sets of changes where possible.
|
||||
* Replaying either unchanged input against the same base preserves the merged
|
||||
* text. Replay stability can supersede ambiguous concurrent edits; the guarantee
|
||||
* applies to text, not the combined cursor list.
|
||||
*
|
||||
* @param original - The original/base version of the text that both sides diverged from
|
||||
* @param left - The left version of the text (either string or TextWithCursors with cursor positions)
|
||||
|
|
|
|||
|
|
@ -73,6 +73,40 @@ describe.each(backends)('reconcile [$name]', ({ api }) => {
|
|||
expect(result.history.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it.each(['a', ''])(
|
||||
'replaying conflicting replacements with base %p keeps both edits',
|
||||
(base) => {
|
||||
for (const tokenizer of ['Character', 'Line', 'Markdown', 'Word'] as const) {
|
||||
const merged = reconcile(base, 'b', 'x', tokenizer);
|
||||
expect(merged.text).toBe('bx');
|
||||
expect(reconcile(base, merged, 'x', tokenizer)).toEqual(merged);
|
||||
expect(reconcile(base, merged, 'b', tokenizer)).toEqual(merged);
|
||||
expect(reconcileWithHistory(base, merged, 'x', tokenizer).text).toBe('bx');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
it('preserves intentional repeats and Unicode cursor positions on replay', () => {
|
||||
const repeated = reconcile('a', 'bb', 'x');
|
||||
expect(repeated.text).toBe('bbx');
|
||||
expect(reconcile('a', repeated, 'x')).toEqual(repeated);
|
||||
const local = {
|
||||
text: '🦊x',
|
||||
cursors: [
|
||||
{ id: 1, position: 1 },
|
||||
{ id: 2, position: 2 },
|
||||
],
|
||||
};
|
||||
const result = reconcile('a', local, {
|
||||
text: 'x',
|
||||
cursors: [{ id: 3, position: 1 }],
|
||||
});
|
||||
expect(result.text).toBe(local.text);
|
||||
expect(result.cursors).toEqual(
|
||||
expect.arrayContaining([...local.cursors, { id: 3, position: 2 }])
|
||||
);
|
||||
});
|
||||
|
||||
it('undiff accepts bigint entries (per the Array<number | bigint | string> type)', () => {
|
||||
const original = 'Hello world';
|
||||
const changed = 'Hello cruel world';
|
||||
|
|
|
|||
Loading…
Reference in a new issue