1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const diff_1 = require("diff");
|
4 | const deep_diff_1 = require("deep-diff");
|
5 | const chalk_1 = require("chalk");
|
6 | function diff(firstItem, secondItem) {
|
7 | if (typeof firstItem === "string") {
|
8 | return diffString(firstItem, secondItem);
|
9 | }
|
10 | const diffs = deep_diff_1.diff(firstItem, secondItem) || [];
|
11 | return buildDiff(diffs);
|
12 | }
|
13 | exports.diff = diff;
|
14 | function diffString(firstString, secondString) {
|
15 | if (firstString === secondString) {
|
16 | return "no differences";
|
17 | }
|
18 | else if (!firstString) {
|
19 | return chalk_1.default.green(secondString);
|
20 | }
|
21 | else if (!secondString) {
|
22 | return chalk_1.default.red(firstString);
|
23 | }
|
24 | const diffs = /\s/.test(firstString) || /\s/.test(secondString)
|
25 | ? diff_1.diffWords(firstString, secondString)
|
26 | : diff_1.diffChars(firstString, secondString);
|
27 | return diffs.map(styleDiffItem).join("");
|
28 | }
|
29 | function styleDiffItem(diffItem) {
|
30 | if (diffItem.added) {
|
31 | return chalk_1.default.green(diffItem.value);
|
32 | }
|
33 | if (diffItem.removed) {
|
34 | return chalk_1.default.red(diffItem.value);
|
35 | }
|
36 | return diffItem.value;
|
37 | }
|
38 | function buildDiff(diffs) {
|
39 | if (diffs.every(d => d.path === undefined)) {
|
40 | return buildNonObjectDiff(diffs);
|
41 | }
|
42 | return buildObjectDiff(diffs);
|
43 | }
|
44 | function buildNonObjectDiff(diffs) {
|
45 | if (diffs.length === 0) {
|
46 | return "no differences";
|
47 | }
|
48 | else if (diffs.length === 1) {
|
49 | const onlyDiff = diffs[0];
|
50 | return diffString(JSON.stringify(onlyDiff.lhs), JSON.stringify(onlyDiff.rhs));
|
51 | }
|
52 | else {
|
53 | return `[\n${diffs
|
54 | .map(diffItem => buildDiff([diffItem]))
|
55 | .join("\n")}\n]`;
|
56 | }
|
57 | }
|
58 | function buildObjectDiff(diffs, depth = 1) {
|
59 | const padding = new Array(depth + 1).join(" ");
|
60 | const deeperDiffs = groupDiffsByProperty(diffs, depth);
|
61 | const properties = diffs
|
62 | .filter(diffItem => diffItem.path.length === depth)
|
63 | .map(diffItem => stringifyDiffProp(diffItem, padding))
|
64 | .concat(Object.keys(deeperDiffs).map(key => {
|
65 | const diffItems = deeperDiffs[key];
|
66 | return ` ${padding}${diffItems[0].path[depth - 1]}: ${buildObjectDiff(diffItems, depth + 1)}`;
|
67 | }))
|
68 | .join(",\n");
|
69 | return `{\n` + properties + `\n${depth === 1 ? "" : padding}}`;
|
70 | }
|
71 | function groupDiffsByProperty(diffs, depth) {
|
72 | return diffs
|
73 | .filter(diffItem => diffItem.path && diffItem.path.length > depth)
|
74 | .reduce((concat, diffItem) => {
|
75 | const prop = diffItem.path[depth];
|
76 | const value = concat[prop];
|
77 | concat[prop] = value ? [...value, diffItem] : [diffItem];
|
78 | return concat;
|
79 | }, {});
|
80 | }
|
81 | function buildDiffProp(diffInfo, value, padding) {
|
82 | return `${padding}${diffInfo.path[diffInfo.path.length - 1] || ""}: ${typeof value === "string" ? `"${value}"` : JSON.stringify(value)}`;
|
83 | }
|
84 | function safeToString(val) {
|
85 | if (val && val.toString) {
|
86 | return val.toString();
|
87 | }
|
88 | return String(val).toString();
|
89 | }
|
90 | function stringifyDiffProp(diffInfo, padding) {
|
91 | if (diffInfo.kind === "N") {
|
92 | return chalk_1.default.green(`+ ${buildDiffProp(diffInfo, diffInfo.rhs, padding)}`);
|
93 | }
|
94 | else if (diffInfo.kind === "D") {
|
95 | return chalk_1.default.red(`- ${buildDiffProp(diffInfo, diffInfo.lhs, padding)}`);
|
96 | }
|
97 | else if (diffInfo.kind === "E") {
|
98 | return ` ${buildDiffProp(diffInfo, diffString(safeToString(diffInfo.lhs), safeToString(diffInfo.rhs)), padding)}`;
|
99 | }
|
100 | }
|
101 |
|
\ | No newline at end of file |