forked from kpdecker/jsdiff
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjson.js
More file actions
71 lines (60 loc) · 2.18 KB
/
Copy pathjson.js
File metadata and controls
71 lines (60 loc) · 2.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import Diff from './base';
import {lineDiff} from './line';
const objectPrototypeToString = Object.prototype.toString;
export const jsonDiff = new Diff();
// Discriminate between two lines of pretty-printed, serialized JSON where one of them has a
// dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output:
jsonDiff.useLongestToken = true;
jsonDiff.tokenize = lineDiff.tokenize;
jsonDiff.castInput = function(value) {
return typeof value === 'string' ? value : JSON.stringify(canonicalize(value), undefined, ' ');
};
jsonDiff.equals = function(left, right) {
return Diff.prototype.equals(left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1'));
};
export function diffJson(oldObj, newObj, callback) { return jsonDiff.diff(oldObj, newObj, callback); }
// This function handles the presence of circular references by bailing out when encountering an
// object that is already on the "stack" of items being processed.
export function canonicalize(obj, stack, replacementStack) {
stack = stack || [];
replacementStack = replacementStack || [];
let i;
for (i = 0; i < stack.length; i += 1) {
if (stack[i] === obj) {
return replacementStack[i];
}
}
let canonicalizedObj;
if ('[object Array]' === objectPrototypeToString.call(obj)) {
stack.push(obj);
canonicalizedObj = new Array(obj.length);
replacementStack.push(canonicalizedObj);
for (i = 0; i < obj.length; i += 1) {
canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack);
}
stack.pop();
replacementStack.pop();
} else if (typeof obj === 'object' && obj !== null) {
stack.push(obj);
canonicalizedObj = {};
replacementStack.push(canonicalizedObj);
let sortedKeys = [],
key;
for (key in obj) {
/* istanbul ignore else */
if (obj.hasOwnProperty(key)) {
sortedKeys.push(key);
}
}
sortedKeys.sort();
for (i = 0; i < sortedKeys.length; i += 1) {
key = sortedKeys[i];
canonicalizedObj[key] = canonicalize(obj[key], stack, replacementStack);
}
stack.pop();
replacementStack.pop();
} else {
canonicalizedObj = obj;
}
return canonicalizedObj;
}