From c5187385510ce7e05900cb90a3cd68c049ba5df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atle=20Sj=C3=B8n=C3=B8st?= Date: Sat, 18 Oct 2025 22:42:36 +0200 Subject: [PATCH] fix(json-patch-ot): merge equal str_ins operations at same position --- .../src/json-patch-ot/__tests__/scenarios.spec.ts | 8 ++++++++ packages/json-joy/src/json-patch-ot/transforms/xStrIns.ts | 1 + 2 files changed, 9 insertions(+) diff --git a/packages/json-joy/src/json-patch-ot/__tests__/scenarios.spec.ts b/packages/json-joy/src/json-patch-ot/__tests__/scenarios.spec.ts index 795694e9ff..00b5ba16cb 100644 --- a/packages/json-joy/src/json-patch-ot/__tests__/scenarios.spec.ts +++ b/packages/json-joy/src/json-patch-ot/__tests__/scenarios.spec.ts @@ -785,6 +785,14 @@ const groups: ScenarioGroup[] = [ user2: [{op: 'str_ins', path: '/a', pos: 2, str: '_bar_'}], docEnd: {a: '12_foo__bar_345'}, }, + { + // changed: discard multiple same inserts (will typically happen in markdown task lists) + name: 'Merge equal inserts at same position.', + docStart: {a: '12345'}, + user1: [{op: 'str_ins', path: '/a', pos: 2, str: '_foo_'}], + user2: [{op: 'str_ins', path: '/a', pos: 2, str: '_foo_'}], + docEnd: {a: '12_foo_345'}, + }, ], }, { diff --git a/packages/json-joy/src/json-patch-ot/transforms/xStrIns.ts b/packages/json-joy/src/json-patch-ot/transforms/xStrIns.ts index 9bd76e0a8a..ba482cbf75 100644 --- a/packages/json-joy/src/json-patch-ot/transforms/xStrIns.ts +++ b/packages/json-joy/src/json-patch-ot/transforms/xStrIns.ts @@ -6,6 +6,7 @@ export const xStrIns = (ins: OpStrIns, op: Op): null | Op | Op[] => { if (op instanceof OpStrIns) { if (!isPathEqual(ins.path, op.path)) return op; if (ins.pos > op.pos) return op; + if (ins.pos === op.pos && ins.str === op.str) return null; return operationToOp({...op.toJson(), pos: op.pos + ins.str.length}, {}); } else if (op instanceof OpStrDel) { if (!isPathEqual(ins.path, op.path)) return op;