Skip to content

Commit 51570f3

Browse files
authored
Merge branch 'master' into typings-pipe-api
2 parents 2e1b820 + b0f0566 commit 51570f3

File tree

4 files changed

+101
-38
lines changed

4 files changed

+101
-38
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Diff & patch JavaScript objects
2525
- html (check it at the [Live Demo](http://benjamine.github.com/jsondiffpatch/demo/index.html))
2626
- annotated json (html), makes the JSON delta format self-explained
2727
- console (colored), try running ```./node_modules/.bin/jsondiffpatch left.json right.json```
28+
- JSON Patch format RFC 6902 support
2829
- write your own! check [Formatters documentation](docs/formatters.md)
2930
- BONUS: `jsondiffpatch.clone(obj)` (deep clone)
3031

src/filters/lcs.js

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ reference: http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
77
*/
88

99
const defaultMatch = function(array1, array2, index1, index2) {
10-
return array1[index1] === array2[index2];
10+
return array1[ index1 ] === array2[ index2 ];
1111
};
1212

1313
const lengthMatrix = function(array1, array2, match, context) {
@@ -16,56 +16,56 @@ const lengthMatrix = function(array1, array2, match, context) {
1616
let x, y;
1717

1818
// initialize empty matrix of len1+1 x len2+1
19-
let matrix = [len1 + 1];
19+
let matrix = [ len1 + 1 ];
2020
for (x = 0; x < len1 + 1; x++) {
21-
matrix[x] = [len2 + 1];
21+
matrix[ x ] = [ len2 + 1 ];
2222
for (y = 0; y < len2 + 1; y++) {
23-
matrix[x][y] = 0;
23+
matrix[ x ][ y ] = 0;
2424
}
2525
}
2626
matrix.match = match;
2727
// save sequence lengths for each coordinate
2828
for (x = 1; x < len1 + 1; x++) {
2929
for (y = 1; y < len2 + 1; y++) {
3030
if (match(array1, array2, x - 1, y - 1, context)) {
31-
matrix[x][y] = matrix[x - 1][y - 1] + 1;
31+
matrix[ x ][ y ] = matrix[ x - 1 ][ y - 1 ] + 1;
3232
} else {
33-
matrix[x][y] = Math.max(matrix[x - 1][y], matrix[x][y - 1]);
33+
matrix[ x ][ y ] = Math.max(matrix[ x - 1 ][ y ], matrix[ x ][ y - 1 ]);
3434
}
3535
}
3636
}
3737
return matrix;
3838
};
3939

40-
const backtrack = function(matrix, array1, array2, index1, index2, context) {
41-
if (index1 === 0 || index2 === 0) {
42-
return {
43-
sequence: [],
44-
indices1: [],
45-
indices2: [],
46-
};
47-
}
48-
49-
if (matrix.match(array1, array2, index1 - 1, index2 - 1, context)) {
50-
const subsequence = backtrack(
51-
matrix,
52-
array1,
53-
array2,
54-
index1 - 1,
55-
index2 - 1,
56-
context
57-
);
58-
subsequence.sequence.push(array1[index1 - 1]);
59-
subsequence.indices1.push(index1 - 1);
60-
subsequence.indices2.push(index2 - 1);
61-
return subsequence;
62-
}
40+
const backtrack = function(matrix, array1, array2, context) {
41+
let index1 = array1.length;
42+
let index2 = array2.length;
43+
const subsequence = {
44+
sequence: [],
45+
indices1: [],
46+
indices2: [],
47+
};
6348

64-
if (matrix[index1][index2 - 1] > matrix[index1 - 1][index2]) {
65-
return backtrack(matrix, array1, array2, index1, index2 - 1, context);
66-
} else {
67-
return backtrack(matrix, array1, array2, index1 - 1, index2, context);
49+
while (index1 !== 0 && index2 !== 0) {
50+
const sameLetter =
51+
matrix.match(array1, array2, index1 - 1, index2 - 1, context);
52+
if (sameLetter) {
53+
subsequence.sequence.unshift(array1[ index1 - 1 ]);
54+
subsequence.indices1.unshift(index1 - 1);
55+
subsequence.indices2.unshift(index2 - 1);
56+
--index1;
57+
--index2;
58+
} else {
59+
const valueAtMatrixAbove = matrix[ index1 ][ index2 - 1 ];
60+
const valueAtMatrixLeft = matrix[ index1 - 1 ][ index2 ];
61+
if (valueAtMatrixAbove > valueAtMatrixLeft) {
62+
--index2;
63+
} else {
64+
--index1;
65+
}
66+
}
6867
}
68+
return subsequence;
6969
};
7070

7171
const get = function(array1, array2, match, context) {
@@ -80,8 +80,6 @@ const get = function(array1, array2, match, context) {
8080
matrix,
8181
array1,
8282
array2,
83-
array1.length,
84-
array2.length,
8583
innerContext
8684
);
8785
if (typeof array1 === 'string' && typeof array2 === 'string') {

src/index.d.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@ export interface Formatter {
22
format(delta: Delta, original: any): string;
33
}
44

5+
export interface HtmlFormatter extends Formatter {
6+
/**
7+
* Set whether to show or hide unchanged parts of a diff.
8+
* @param show Whether to show unchanged parts
9+
* @param node The root element the diff is contained within. (Default: body)
10+
* @param delay Transition time in ms. (Default: no transition)
11+
*/
12+
showUnchanged(show: boolean, node?: Element | null, delay?: number): void;
13+
14+
/**
15+
* An alias for showUnchanged(false, ...)
16+
* @param node The root element the diff is contained within (Default: body)
17+
* @param delay Transition time in ms. (Default: no transition)
18+
*/
19+
hideUnchanged(node?: Element | null, delay?: number): void;
20+
}
21+
522
export interface Delta {
623
[key: string]: any;
724
[key: number]: any;
@@ -167,14 +184,18 @@ export class DiffPatcher {
167184
unpatch: (right: any, delta: Delta) => any;
168185
}
169186

187+
export const create: (options?: any) => DiffPatcher
188+
170189
export const formatters: {
171-
annotated: Formatter;
172-
console: Formatter;
173-
html: Formatter;
190+
annotated: Formatter;
191+
console: Formatter;
192+
html: HTMLFormatter;
174193
};
175194

176195
export const console: Formatter
177196

197+
export const dateReviver: (key: string, value: any) => any;
198+
178199
export const diff: (left: any, right: any) => Delta | undefined;
179200
export const patch: (left: any, delta: Delta) => any;
180201
export const reverse: (delta: Delta) => Delta | undefined;

test/index.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import * as jsondiffpatch from '../build/jsondiffpatch.esm';
66
import examples from './examples/diffpatch';
77
import chai from 'chai';
8+
9+
import lcs from '../src/filters/lcs';
810
const expect = chai.expect;
911

1012
describe('jsondiffpatch', () => {
@@ -726,3 +728,44 @@ describe('DiffPatcher', () => {
726728
});
727729
});
728730
});
731+
732+
describe('lcs', () => {
733+
it('should lcs arrays ', () => {
734+
expect(lcs.get([], [])).to.deep.equal({
735+
sequence: [],
736+
indices1: [],
737+
indices2: [],
738+
});
739+
740+
expect(lcs.get([1], [2])).to.deep.equal({
741+
sequence: [],
742+
indices1: [],
743+
indices2: [],
744+
});
745+
746+
// indices1 and indices2 show where the sequence
747+
// elements are located in the original arrays
748+
expect(lcs.get([ 1 ], [ -9, 1 ])).to.deep.equal({
749+
sequence: [1],
750+
indices1: [0],
751+
indices2: [1],
752+
});
753+
});
754+
755+
it('should compute diff for large array', () => {
756+
const ARRAY_LENGTH = 5000; // js stack is about 50k
757+
function randomArray() {
758+
let result = [];
759+
for (let i = 0; i < ARRAY_LENGTH; i++) {
760+
if (Math.random() > 0.5) {
761+
result.push('A');
762+
} else {
763+
result.push('B');
764+
}
765+
}
766+
return result;
767+
}
768+
769+
lcs.get(randomArray(), randomArray());
770+
});
771+
});

0 commit comments

Comments
 (0)