|
1 |
| -import Diff from './base'; |
| 1 | +import Diff, {DiffOptions} from './base'; |
2 | 2 | import {lineDiff} from './line';
|
3 | 3 |
|
4 |
| -export const jsonDiff = new Diff(); |
5 |
| -// Discriminate between two lines of pretty-printed, serialized JSON where one of them has a |
6 |
| -// dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output: |
7 |
| -// TODO: Override getter |
8 |
| -jsonDiff.useLongestToken = true; |
| 4 | +class JsonDiff extends Diff<string, string> { |
| 5 | + protected get useLongestToken() { |
| 6 | + // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a |
| 7 | + // dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output: |
| 8 | + return true; |
| 9 | + } |
| 10 | + |
| 11 | + protected tokenize = lineDiff.tokenize |
| 12 | + |
| 13 | + protected castInput(value: string, options: DiffOptions<string>) { |
| 14 | + const {undefinedReplacement, stringifyReplacer = (k, v) => typeof v === 'undefined' ? undefinedReplacement : v} = options; |
| 15 | + |
| 16 | + return typeof value === 'string' ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), stringifyReplacer, ' '); |
| 17 | + }; |
| 18 | + |
| 19 | + protected equals(left: string, right: string, options: DiffOptions<string>) { |
| 20 | + return super.equals.call(jsonDiff, left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1'), options); |
| 21 | + }; |
| 22 | +} |
9 | 23 |
|
10 |
| -jsonDiff.tokenize = lineDiff.tokenize; |
11 |
| -jsonDiff.castInput = function(value, options) { |
12 |
| - const {undefinedReplacement, stringifyReplacer = (k, v) => typeof v === 'undefined' ? undefinedReplacement : v} = options; |
| 24 | +const jsonDiff = new JsonDiff(); |
13 | 25 |
|
14 |
| - return typeof value === 'string' ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), stringifyReplacer, ' '); |
15 |
| -}; |
16 |
| -jsonDiff.equals = function(left, right, options) { |
17 |
| - return Diff.prototype.equals.call(jsonDiff, left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1'), options); |
18 |
| -}; |
19 | 26 |
|
20 |
| -export function diffJson(oldObj, newObj, options) { return jsonDiff.diff(oldObj, newObj, options); } |
| 27 | +export function diffJson(oldObj: any, newObj: any, options: DiffOptions<string>) { return jsonDiff.diff(oldObj, newObj, options); } |
21 | 28 |
|
22 | 29 | // This function handles the presence of circular references by bailing out when encountering an
|
23 | 30 | // object that is already on the "stack" of items being processed. Accepts an optional replacer
|
24 |
| -export function canonicalize(obj, stack, replacementStack, replacer, key) { |
| 31 | +export function canonicalize(obj: any, stack: Array<any> | null, replacementStack: Array<any> | null, replacer: (string, any) => any, key?: string) { |
25 | 32 | stack = stack || [];
|
26 | 33 | replacementStack = replacementStack || [];
|
27 | 34 |
|
|
0 commit comments