diff --git a/src/diff.spec.ts b/src/diff.spec.ts index 5009e04..00b9eba 100644 --- a/src/diff.spec.ts +++ b/src/diff.spec.ts @@ -123,6 +123,24 @@ describe("diff", () => } ); + it( + "Returns [ ..., [ '-', ], [ '+', ], ... ] for replaced " + +"values.", + () => + { + expect(diff([ 1 ], [ 2 ])).toEqual([ [ "-", 1 ], [ "+", 2 ] ]); + } + ); + + it("Does not forget additions at the end of b.", () => + { + expect(diff([ 1 ], [ 2, 3 ])).toEqual([ + [ "-", 1 ], + [ "+", 2 ], + [ "+", 3 ] + ]); + }); + it( "Returns [ ..., [ '+', ] ] when a is missing a value.", () => diff --git a/src/diff.ts b/src/diff.ts index 8935948..d7f2ddb 100644 --- a/src/diff.ts +++ b/src/diff.ts @@ -5,6 +5,7 @@ export const diff = (a: any, b: any): any => { if (a instanceof Array && b instanceof Array) { + const result: any[] = []; if (a.length === b.length) @@ -14,6 +15,8 @@ export const diff = (a: any, b: any): any => return undefined; } + let finalIndices = 0; + a.forEach((value, index) => { if (b[index] === undefined) @@ -32,21 +35,31 @@ export const diff = (a: any, b: any): any => else result.push([ " ", value ]); + + finalIndices++; } else if (value !== b[index] && value === b[index+1]) + { result.push([ "+", b[index] ], [ " ", value ]); + finalIndices += 2; + } + + else if (value !== b[index] && value !== b[index+1]) + { + result.push([ "-", value ], [ "+", b[index] ]); + finalIndices++; + } else + { result.push([ " ", value ]); + finalIndices++; + } + }); - if (result.length < a.length) - { - a.slice(b.length).forEach((value) => - result.push([ "-", value ])); - } - else if (result.length < b.length) + if (finalIndices < b.length) { b.slice(a.length).forEach((value) => result.push([ "+", value ])); diff --git a/src/patching.ts b/src/patching.ts index 9695984..2163c25 100644 --- a/src/patching.ts +++ b/src/patching.ts @@ -1,5 +1,5 @@ import * as Y from "yjs"; -import { diff, } from "json-diff"; +import { diff, } from "./diff"; import { arrayToYArray, objectToYMap, } from "./mapping"; import { State, StoreApi, } from "zustand/vanilla";