|
| 1 | +diff --git a/dist/delta/delta.d.ts b/dist/delta/delta.d.ts |
| 2 | +index 1f97a3d..b6f9db5 100644 |
| 3 | +--- a/dist/delta/delta.d.ts |
| 4 | ++++ b/dist/delta/delta.d.ts |
| 5 | +@@ -905,7 +905,7 @@ export function from<NodeName extends string | null, Attrs extends { |
| 6 | + children: Extract<Children, Array<any>> extends Array<infer Ac> ? (unknown extends Ac ? never : Ac) : never; |
| 7 | + text: Extract<Children, string> extends never ? false : true; |
| 8 | + }>; |
| 9 | +-export function diff<Conf_1 extends DeltaConf>(d1: Delta<Conf_1>, d2: NoInfer<Delta<Conf_1>>): Delta<Conf_1>; |
| 10 | ++export function diff<Conf_1 extends DeltaConf>(d1: Delta<Conf_1>, d2: NoInfer<Delta<Conf_1>>, matchNodes?: (a: any, b: any) => boolean): Delta<Conf_1>; |
| 11 | + export function diffChangesetWithSeparator(changeset: Array<{ |
| 12 | + index: number; |
| 13 | + remove: Array<any>; |
| 14 | +diff --git a/src/delta/delta.js b/src/delta/delta.js |
| 15 | +index d4be86c..89ddc86 100644 |
| 16 | +--- a/src/delta/delta.js |
| 17 | ++++ b/src/delta/delta.js |
| 18 | +@@ -2443,9 +2443,14 @@ class _DiffStringWrapper { |
| 19 | + * @template {DeltaConf} Conf |
| 20 | + * @param {Delta<Conf>} d1 |
| 21 | + * @param {NoInfer<Delta<Conf>>} d2 |
| 22 | ++ * @param {(a: DeltaAny, b: DeltaAny) => boolean} [matchNodes] decides whether a |
| 23 | ++ * removed node and an inserted node are the *same* node (→ diffed/modified in |
| 24 | ++ * place) or different (→ replaced). Defaults to name-equality. Override to force |
| 25 | ++ * a *replace* for nodes that should be treated as atomic - e.g. raising a diff |
| 26 | ++ * boundary when a node's identifying child changes type. |
| 27 | + * @return {Delta<Conf>} |
| 28 | + */ |
| 29 | +-export const diff = (d1, d2) => { |
| 30 | ++export const diff = (d1, d2, matchNodes = (a, b) => a.name === b.name) => { |
| 31 | + const d = create(d1.name === d2.name ? d1.name : null, $deltaAny) |
| 32 | + if (d1.fingerprint !== d2.fingerprint) { |
| 33 | + /** |
| 34 | +@@ -2533,7 +2538,7 @@ export const diff = (d1, d2) => { |
| 35 | + const changeset3 = diffChangesetWithSeparator(changeset2, patience.smartSplitRegex) |
| 36 | + // split all |
| 37 | + const changeset4 = diffChangesetWithSeparator(changeset3, /./g) |
| 38 | +- applyChangesetToDelta(d, changeset4) |
| 39 | ++ applyChangesetToDelta(d, changeset4, matchNodes) |
| 40 | + if (formattingNeedsDiff) { |
| 41 | + const formattingDiff = create() |
| 42 | + // update opsIs with content diff. then we can figure out the formatting diff. |
| 43 | +@@ -2602,7 +2607,7 @@ export const diff = (d1, d2) => { |
| 44 | + const prevVal = attr1?.value |
| 45 | + const nextVal = attr2.value |
| 46 | + if ($deltaAny.check(prevVal) && $deltaAny.check(nextVal) && prevVal.name === nextVal.name) { |
| 47 | +- d.modifyAttr(key, diff(prevVal, nextVal)) |
| 48 | ++ d.modifyAttr(key, diff(prevVal, nextVal, matchNodes)) |
| 49 | + } else { |
| 50 | + d.setAttr(key, nextVal) |
| 51 | + } |
| 52 | +@@ -2648,8 +2653,9 @@ const applyInserts = (d, cins, len) => { len > 0 && cins.splice(0, len).forEach( |
| 53 | + /** |
| 54 | + * @param {DeltaBuilderAny} d |
| 55 | + * @param {Array<{ index: number, remove: Array<any>, insert: Array<any> }>} changeset |
| 56 | ++ * @param {(a: DeltaAny, b: DeltaAny) => boolean} [matchNodes] see {@link diff} |
| 57 | + */ |
| 58 | +-const applyChangesetToDelta = (d, changeset) => { |
| 59 | ++const applyChangesetToDelta = (d, changeset, matchNodes = (a, b) => a.name === b.name) => { |
| 60 | + for (let ci = 0, lastIndex = 0; ci < changeset.length; ci++) { |
| 61 | + const c = changeset[ci] |
| 62 | + d.retain(c.index - lastIndex) |
| 63 | +@@ -2660,14 +2666,14 @@ const applyChangesetToDelta = (d, changeset) => { |
| 64 | + const cremoveDeltaIndex = c.remove.findIndex(cc => $deltaAny.check(cc)) |
| 65 | + if (cremoveDeltaIndex < 0) break |
| 66 | + const cremoveDelta = c.remove[cremoveDeltaIndex] |
| 67 | +- const cinsertDeltaIndex = c.insert.findIndex(cc => $deltaAny.check(cc) && cc.name === cremoveDelta.name) |
| 68 | ++ const cinsertDeltaIndex = c.insert.findIndex(cc => $deltaAny.check(cc) && matchNodes(cremoveDelta, cc)) |
| 69 | + if (cinsertDeltaIndex < 0) { |
| 70 | + applyRemoves(d, c.remove, cremoveDeltaIndex + 1) |
| 71 | + continue |
| 72 | + } |
| 73 | + applyRemoves(d, c.remove, cremoveDeltaIndex) |
| 74 | + applyInserts(d, c.insert, cinsertDeltaIndex) |
| 75 | +- d.modify(diff(c.remove[0], c.insert[0])) |
| 76 | ++ d.modify(diff(c.remove[0], c.insert[0], matchNodes)) |
| 77 | + c.remove.splice(0, 1) |
| 78 | + c.insert.splice(0, 1) |
| 79 | + } |
0 commit comments