diff-leven 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,8 +17,9 @@
17
17
  - Strings (character-level differences)
18
18
  - Numbers, Booleans, and any serializable value
19
19
  - **Rich Output Options**:
20
- - Terminal-friendly colorized output (toggleable)
21
- - Git-style diff format with clear additions/removals
20
+
21
+ - Git-style colorized output diff format with clear additions/removals
22
+
22
23
  - **Flexible Configuration**:
23
24
  - `color`: Toggle color output (default: `true`)
24
25
  - `keysOnly`: Compare only object structure/keys (default: `false`)
package/dist/index.js CHANGED
@@ -1,446 +1,18 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- DiffType: () => DiffType,
34
- diff: () => diff,
35
- diffRaw: () => diffRaw
36
- });
37
- module.exports = __toCommonJS(index_exports);
38
-
39
- // src/diff.ts
40
- var import_leven = __toESM(require("leven"));
41
-
42
- // src/types.ts
43
- var DiffType = /* @__PURE__ */ ((DiffType2) => {
44
- DiffType2["ADDED"] = "added";
45
- DiffType2["REMOVED"] = "removed";
46
- DiffType2["CHANGED"] = "changed";
47
- DiffType2["UNCHANGED"] = "unchanged";
48
- return DiffType2;
49
- })(DiffType || {});
50
-
51
- // src/diff.ts
52
- function createDiff(oldValue, newValue, options = {}, path = []) {
53
- const { keysOnly = false, ignoreValues = false } = options;
54
- if (oldValue === void 0 && newValue === void 0) {
55
- return { type: "unchanged" /* UNCHANGED */ };
56
- }
57
- if (oldValue === void 0) {
58
- return { type: "added" /* ADDED */, path, newValue };
59
- }
60
- if (newValue === void 0) {
61
- return { type: "removed" /* REMOVED */, path, oldValue };
62
- }
63
- if (typeof oldValue !== "object" || typeof newValue !== "object" || oldValue === null || newValue === null) {
64
- if (keysOnly || ignoreValues) {
65
- return {
66
- type: "unchanged" /* UNCHANGED */,
67
- path,
68
- oldValue,
69
- newValue,
70
- meta: { ignored: true }
71
- };
72
- }
73
- if (oldValue === newValue) {
74
- return { type: "unchanged" /* UNCHANGED */, path, oldValue, newValue };
75
- }
76
- if (typeof oldValue === "string" && typeof newValue === "string") {
77
- const distance = (0, import_leven.default)(oldValue, newValue);
78
- const maxLength = Math.max(oldValue.length, newValue.length);
79
- const similarityRatio = maxLength > 0 ? 1 - distance / maxLength : 1;
80
- return {
81
- type: "changed" /* CHANGED */,
82
- path,
83
- oldValue,
84
- newValue,
85
- meta: {
86
- levenDistance: distance,
87
- similarity: similarityRatio
88
- }
89
- };
90
- }
91
- return { type: "changed" /* CHANGED */, path, oldValue, newValue };
92
- }
93
- if (Array.isArray(oldValue) && Array.isArray(newValue)) {
94
- return compareArrays(oldValue, newValue, options, path);
95
- }
96
- return compareObjects(
97
- oldValue,
98
- newValue,
99
- options,
100
- path
101
- );
102
- }
103
- function compareObjects(oldObj, newObj, options, path) {
104
- const { ignoreKeys = [] } = options;
105
- const allKeys = /* @__PURE__ */ new Set([
106
- ...Object.keys(oldObj).filter((key) => !ignoreKeys.includes(key)),
107
- ...Object.keys(newObj).filter((key) => !ignoreKeys.includes(key))
108
- ]);
109
- const children = [];
110
- let hasChanges = false;
111
- for (const key of allKeys) {
112
- const childPath = [...path, key];
113
- const oldValue = oldObj[key];
114
- const newValue = newObj[key];
115
- const childDiff = createDiff(oldValue, newValue, options, childPath);
116
- if (childDiff.type !== "unchanged" /* UNCHANGED */) {
117
- hasChanges = true;
118
- }
119
- children.push(childDiff);
120
- }
121
- if (hasChanges) {
122
- return {
123
- type: "changed" /* CHANGED */,
124
- path,
125
- oldValue: oldObj,
126
- newValue: newObj,
127
- children
128
- };
129
- }
130
- return { type: "unchanged" /* UNCHANGED */, path, oldValue: oldObj, newValue: newObj };
131
- }
132
- function compareArrays(oldArray, newArray, options, path) {
133
- if (oldArray.length !== newArray.length) {
134
- const children2 = [];
135
- const maxLength = Math.max(oldArray.length, newArray.length);
136
- for (let i = 0; i < maxLength; i++) {
137
- const childPath = [...path, i.toString()];
138
- if (i >= oldArray.length) {
139
- children2.push({
140
- type: "added" /* ADDED */,
141
- path: childPath,
142
- newValue: newArray[i]
143
- });
144
- } else if (i >= newArray.length) {
145
- children2.push({
146
- type: "removed" /* REMOVED */,
147
- path: childPath,
148
- oldValue: oldArray[i]
149
- });
150
- } else {
151
- children2.push(createDiff(oldArray[i], newArray[i], options, childPath));
152
- }
153
- }
154
- return {
155
- type: "changed" /* CHANGED */,
156
- path,
157
- oldValue: oldArray,
158
- newValue: newArray,
159
- children: children2
160
- };
161
- }
162
- const children = [];
163
- let hasChanges = false;
164
- for (let i = 0; i < oldArray.length; i++) {
165
- const childPath = [...path, i.toString()];
166
- const oldValue = oldArray[i];
167
- const newValue = newArray[i];
168
- let childDiff;
169
- if (typeof oldValue === "string" && typeof newValue === "string") {
170
- if (oldValue === newValue) {
171
- childDiff = {
172
- type: "unchanged" /* UNCHANGED */,
173
- path: childPath,
174
- oldValue,
175
- newValue
176
- };
177
- } else {
178
- const distance = (0, import_leven.default)(oldValue, newValue);
179
- const maxLength = Math.max(oldValue.length, newValue.length);
180
- const similarityRatio = maxLength > 0 ? 1 - distance / maxLength : 1;
181
- childDiff = {
182
- type: "changed" /* CHANGED */,
183
- path: childPath,
184
- oldValue,
185
- newValue,
186
- meta: {
187
- levenDistance: distance,
188
- similarity: similarityRatio
189
- }
190
- };
191
- hasChanges = true;
192
- }
193
- } else {
194
- childDiff = createDiff(oldValue, newValue, options, childPath);
195
- if (childDiff.type !== "unchanged" /* UNCHANGED */) {
196
- hasChanges = true;
197
- }
198
- }
199
- children.push(childDiff);
200
- }
201
- if (hasChanges) {
202
- return {
203
- type: "changed" /* CHANGED */,
204
- path,
205
- oldValue: oldArray,
206
- newValue: newArray,
207
- children
208
- };
209
- }
210
- return {
211
- type: "unchanged" /* UNCHANGED */,
212
- path,
213
- oldValue: oldArray,
214
- newValue: newArray
215
- };
216
- }
217
-
218
- // src/formatter.ts
219
- var colors = {
220
- reset: "\x1B[0m",
221
- red: "\x1B[31m",
222
- green: "\x1B[32m",
223
- gray: "\x1B[90m"
224
- };
225
- function formatDiff(diff2, options = {}) {
226
- const { color = true, full = false } = options;
227
- if (diff2.type === "unchanged" /* UNCHANGED */ && !full && (!diff2.children || diff2.children.length === 0)) {
228
- return "";
229
- }
230
- if (!diff2.children || diff2.children.length === 0) {
231
- return formatValue(diff2, color);
232
- }
233
- return formatComplex(diff2, options, 0);
234
- }
235
- function formatValue(diff2, useColor) {
236
- const prefix = getPrefix(diff2.type);
237
- let value = "";
238
- switch (diff2.type) {
239
- case "added" /* ADDED */:
240
- value = formatPrimitive(diff2.newValue);
241
- return useColor ? `${colors.green}${prefix} ${value}${colors.reset}` : `${prefix} ${value}`;
242
- case "removed" /* REMOVED */:
243
- value = formatPrimitive(diff2.oldValue);
244
- return useColor ? `${colors.red}${prefix} ${value}${colors.reset}` : `${prefix} ${value}`;
245
- case "changed" /* CHANGED */:
246
- const oldVal = formatPrimitive(diff2.oldValue);
247
- const newVal = formatPrimitive(diff2.newValue);
248
- let similarityInfo = "";
249
- if (diff2.meta?.similarity !== void 0 && typeof diff2.oldValue === "string" && typeof diff2.newValue === "string") {
250
- const similarity = Math.round(diff2.meta.similarity * 100);
251
- similarityInfo = useColor ? `${colors.gray} (${similarity}% similar)${colors.reset}` : ` (${similarity}% similar)`;
252
- }
253
- const oldLine = useColor ? `${colors.red}- ${oldVal}${colors.reset}` : `- ${oldVal}`;
254
- const newLine = useColor ? `${colors.green}+ ${newVal}${similarityInfo}${colors.reset}` : `+ ${newVal}${similarityInfo}`;
255
- return `${oldLine}
256
- ${newLine}`;
257
- default:
258
- value = formatPrimitive(diff2.newValue ?? diff2.oldValue);
259
- return useColor ? `${colors.gray}${prefix} ${value}${colors.reset}` : `${prefix} ${value}`;
260
- }
261
- }
262
- function formatComplex(diff2, options, indent = 0) {
263
- const { full = false } = options;
264
- if (diff2.type === "unchanged" /* UNCHANGED */ && !full && (!diff2.children || diff2.children.length === 0 || typeof diff2.oldValue !== "object" && typeof diff2.newValue !== "object")) {
265
- return "";
266
- }
267
- return Array.isArray(diff2.oldValue) || Array.isArray(diff2.newValue) ? formatArrayDiff(diff2, options, indent) : formatObjectDiff(diff2, options, indent);
268
- }
269
- function formatArrayDiff(diff2, options, indent = 0) {
270
- const { color = true, full = false } = options;
271
- const baseIndent = " ".repeat(indent);
272
- const innerIndent = " ".repeat(indent + 2);
273
- let result = `[
274
- `;
275
- let visibleItems = 0;
276
- if (diff2.children) {
277
- for (let i = 0; i < diff2.children.length; i++) {
278
- const child = diff2.children[i];
279
- if (child.type === "unchanged" /* UNCHANGED */ && !full && (!child.children || child.children.length === 0)) {
280
- continue;
281
- }
282
- if (child.children && child.children.length > 0) {
283
- const nestedOutput = Array.isArray(child.newValue || child.oldValue) ? formatArrayDiff(child, options, indent + 2) : formatObjectDiff(child, options, indent + 2);
284
- if (nestedOutput.trim().length > 2) {
285
- if (visibleItems > 0) {
286
- result += ",\n";
287
- }
288
- result += innerIndent;
289
- result += nestedOutput;
290
- visibleItems++;
291
- }
292
- } else {
293
- if (visibleItems > 0) {
294
- result += ",\n";
295
- }
296
- switch (child.type) {
297
- case "added" /* ADDED */:
298
- result += color ? `${innerIndent}${colors.green}+ ${formatPrimitive(child.newValue)}${colors.reset}` : `${innerIndent}+ ${formatPrimitive(child.newValue)}`;
299
- visibleItems++;
300
- break;
301
- case "removed" /* REMOVED */:
302
- result += color ? `${innerIndent}${colors.red}- ${formatPrimitive(child.oldValue)}${colors.reset}` : `${innerIndent}- ${formatPrimitive(child.oldValue)}`;
303
- visibleItems++;
304
- break;
305
- case "unchanged" /* UNCHANGED */:
306
- if (child.meta?.ignored && child.path) {
307
- result += color ? `${innerIndent}${colors.gray} ${child.path[child.path.length - 1] || ""}${colors.reset}` : `${innerIndent} ${child.path[child.path.length - 1] || ""}`;
308
- } else {
309
- result += color ? `${innerIndent}${colors.gray} ${formatPrimitive(child.newValue)}${colors.reset}` : `${innerIndent} ${formatPrimitive(child.newValue)}`;
310
- }
311
- visibleItems++;
312
- break;
313
- case "changed" /* CHANGED */:
314
- result += color ? `${innerIndent}${colors.red}- ${formatPrimitive(child.oldValue)}${colors.reset}
315
- ${innerIndent}${colors.green}+ ${formatPrimitive(child.newValue)}${colors.reset}` : `${innerIndent}- ${formatPrimitive(child.oldValue)}
316
- ${innerIndent}+ ${formatPrimitive(child.newValue)}`;
317
- visibleItems++;
318
- break;
319
- }
320
- }
321
- }
322
- }
323
- if (visibleItems > 0) {
324
- result += "\n";
325
- }
326
- result += `${baseIndent}]`;
327
- return result;
328
- }
329
- function formatObjectDiff(diff2, options, indent = 0) {
330
- const { color = true, full = false } = options;
331
- const baseIndent = " ".repeat(indent);
332
- const innerIndent = " ".repeat(indent + 2);
333
- let result = `{
334
- `;
335
- let visibleItems = 0;
336
- if (diff2.children) {
337
- const displayableChildren = diff2.children.filter((child) => {
338
- if (child.type !== "unchanged" /* UNCHANGED */) return true;
339
- if (full) return true;
340
- if (child.children && child.children.length > 0) return true;
341
- const key = child.path?.[child.path.length - 1] || "";
342
- if (options.outputKeys?.includes(key)) return true;
343
- return false;
344
- });
345
- for (let i = 0; i < displayableChildren.length; i++) {
346
- const child = displayableChildren[i];
347
- const key = child.path?.[child.path.length - 1] || "";
348
- const isLast = i === displayableChildren.length - 1;
349
- if (visibleItems > 0 && !result.endsWith("\n")) {
350
- result += ",\n";
351
- }
352
- if (child.children && child.children.length > 0) {
353
- const nestedContent = Array.isArray(child.newValue || child.oldValue) ? formatArrayDiff(child, options, indent + 2) : formatObjectDiff(child, options, indent + 2);
354
- if (nestedContent.trim().length > 2) {
355
- result += `${innerIndent}${key}: ${nestedContent}`;
356
- visibleItems++;
357
- }
358
- } else {
359
- switch (child.type) {
360
- case "added" /* ADDED */:
361
- result += color ? `${innerIndent}${colors.green}+ ${key}: ${formatPrimitive(child.newValue)}${colors.reset}` : `${innerIndent}+ ${key}: ${formatPrimitive(child.newValue)}`;
362
- visibleItems++;
363
- break;
364
- case "removed" /* REMOVED */:
365
- result += color ? `${innerIndent}${colors.red}- ${key}: ${formatPrimitive(child.oldValue)}${colors.reset}` : `${innerIndent}- ${key}: ${formatPrimitive(child.oldValue)}`;
366
- visibleItems++;
367
- break;
368
- case "changed" /* CHANGED */:
369
- result += color ? `${innerIndent}${colors.red}- ${key}: ${formatPrimitive(child.oldValue)}${colors.reset}
370
- ${innerIndent}${colors.green}+ ${key}: ${formatPrimitive(child.newValue)}${colors.reset}` : `${innerIndent}- ${key}: ${formatPrimitive(child.oldValue)}
371
- ${innerIndent}+ ${key}: ${formatPrimitive(child.newValue)}`;
372
- visibleItems++;
373
- break;
374
- case "unchanged" /* UNCHANGED */:
375
- if (full || options.outputKeys?.includes(key)) {
376
- if (child.meta?.ignored) {
377
- result += color ? `${innerIndent}${colors.gray} ${key}${colors.reset}` : `${innerIndent} ${key}`;
378
- } else {
379
- result += color ? `${innerIndent}${colors.gray} ${key}: ${formatPrimitive(child.newValue)}${colors.reset}` : `${innerIndent} ${key}: ${formatPrimitive(child.newValue)}`;
380
- }
381
- visibleItems++;
382
- }
383
- break;
384
- }
385
- }
386
- if (!isLast && !result.endsWith("\n")) {
387
- result += ",";
388
- }
389
- if (!result.endsWith("\n")) {
390
- result += "\n";
391
- }
392
- }
393
- }
394
- if (visibleItems > 0 && !result.endsWith("\n")) {
395
- result += "\n";
396
- }
397
- result += `${baseIndent}}`;
398
- return result;
399
- }
400
- function getPrefix(type) {
401
- switch (type) {
402
- case "added" /* ADDED */:
403
- return "+";
404
- case "removed" /* REMOVED */:
405
- return "-";
406
- case "changed" /* CHANGED */:
407
- return "!";
408
- default:
409
- return " ";
410
- }
411
- }
412
- function formatPrimitive(value) {
413
- if (value === void 0) {
414
- return "undefined";
415
- }
416
- if (value === null) {
417
- return "null";
418
- }
419
- if (typeof value === "string") {
420
- return `'${value}'`;
421
- }
422
- if (typeof value === "number" || typeof value === "boolean") {
423
- return value.toString();
424
- }
425
- if (typeof value === "object") {
426
- const json = JSON.stringify(value, null, 2);
427
- return json;
428
- }
429
- return String(value);
430
- }
431
-
432
- // src/index.ts
433
- function diffRaw(oldValue, newValue, options = {}) {
434
- return createDiff(oldValue, newValue, options);
435
- }
436
- function diff(oldValue, newValue, options = {}) {
437
- const diffResult = diffRaw(oldValue, newValue, options);
438
- return formatDiff(diffResult, options);
439
- }
440
- // Annotate the CommonJS export names for ESM import in node:
441
- 0 && (module.exports = {
442
- DiffType,
443
- diff,
444
- diffRaw
445
- });
446
- //# sourceMappingURL=index.js.map
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _leven = require('leven'); var _leven2 = _interopRequireDefault(_leven);var h=($=>($.ADDED="added",$.REMOVED="removed",$.CHANGED="changed",$.UNCHANGED="unchanged",$))(h||{});function y(e,t,a={},r=[]){let{keysOnly:$=!1,ignoreValues:g=!1}=a;if(e===void 0&&t===void 0)return{type:"unchanged"};if(e===void 0)return{type:"added",path:r,newValue:t};if(t===void 0)return{type:"removed",path:r,oldValue:e};if(typeof e!="object"||typeof t!="object"||e===null||t===null){if($||g)return{type:"unchanged",path:r,oldValue:e,newValue:t,meta:{ignored:!0}};if(e===t)return{type:"unchanged",path:r,oldValue:e,newValue:t};if(typeof e=="string"&&typeof t=="string"){let n=_leven2.default.call(void 0, e,t),s=Math.max(e.length,t.length),i=s>0?1-n/s:1;return{type:"changed",path:r,oldValue:e,newValue:t,meta:{levenDistance:n,similarity:i}}}return{type:"changed",path:r,oldValue:e,newValue:t}}return Array.isArray(e)&&Array.isArray(t)?R(e,t,a,r):N(e,t,a,r)}function N(e,t,a,r){let{ignoreKeys:$=[]}=a,g=new Set([...Object.keys(e).filter(i=>!$.includes(i)),...Object.keys(t).filter(i=>!$.includes(i))]),n=[],s=!1;for(let i of g){let c=[...r,i],l=e[i],f=t[i],D=y(l,f,a,c);D.type!=="unchanged"&&(s=!0),n.push(D)}return s?{type:"changed",path:r,oldValue:e,newValue:t,children:n}:{type:"unchanged",path:r,oldValue:e,newValue:t}}function R(e,t,a,r){if(e.length!==t.length){let n=[],s=Math.max(e.length,t.length);for(let i=0;i<s;i++){let c=[...r,i.toString()];i>=e.length?n.push({type:"added",path:c,newValue:t[i]}):i>=t.length?n.push({type:"removed",path:c,oldValue:e[i]}):n.push(y(e[i],t[i],a,c))}return{type:"changed",path:r,oldValue:e,newValue:t,children:n}}let $=[],g=!1;for(let n=0;n<e.length;n++){let s=[...r,n.toString()],i=e[n],c=t[n],l;if(typeof i=="string"&&typeof c=="string")if(i===c)l={type:"unchanged",path:s,oldValue:i,newValue:c};else{let f=_leven2.default.call(void 0, i,c),D=Math.max(i.length,c.length),p=D>0?1-f/D:1;l={type:"changed",path:s,oldValue:i,newValue:c,meta:{levenDistance:f,similarity:p}},g=!0}else l=y(i,c,a,s),l.type!=="unchanged"&&(g=!0);$.push(l)}return g?{type:"changed",path:r,oldValue:e,newValue:t,children:$}:{type:"unchanged",path:r,oldValue:e,newValue:t}}var u={reset:"\x1B[0m",red:"\x1B[31m",green:"\x1B[32m",gray:"\x1B[90m"};function b(e,t={}){let{color:a=!0,full:r=!1}=t;return e.type==="unchanged"&&!r&&(!e.children||e.children.length===0)?"":!e.children||e.children.length===0?A(e,a):C(e,t,0)}function A(e,t){let a=G(e.type),r="";switch(e.type){case"added":return r=o(e.newValue),t?`${u.green}${a} ${r}${u.reset}`:`${a} ${r}`;case"removed":return r=o(e.oldValue),t?`${u.red}${a} ${r}${u.reset}`:`${a} ${r}`;case"changed":let $=o(e.oldValue),g=o(e.newValue),n="";if(_optionalChain([e, 'access', _ => _.meta, 'optionalAccess', _2 => _2.similarity])!==void 0&&typeof e.oldValue=="string"&&typeof e.newValue=="string"){let c=Math.round(e.meta.similarity*100);n=t?`${u.gray} (${c}% similar)${u.reset}`:` (${c}% similar)`}let s=t?`${u.red}- ${$}${u.reset}`:`- ${$}`,i=t?`${u.green}+ ${g}${n}${u.reset}`:`+ ${g}${n}`;return`${s}
2
+ ${i}`;default:return r=o(_nullishCoalesce(e.newValue, () => (e.oldValue))),t?`${u.gray}${a} ${r}${u.reset}`:`${a} ${r}`}}function C(e,t,a=0){let{full:r=!1}=t;return e.type==="unchanged"&&!r&&(!e.children||e.children.length===0||typeof e.oldValue!="object"&&typeof e.newValue!="object")?"":Array.isArray(e.oldValue)||Array.isArray(e.newValue)?m(e,t,a):d(e,t,a)}function m(e,t,a=0){let{color:r=!0,full:$=!1}=t,g=" ".repeat(a),n=" ".repeat(a+2),s=`[
3
+ `,i=0;if(e.children)for(let c=0;c<e.children.length;c++){let l=e.children[c];if(!(l.type==="unchanged"&&!$&&(!l.children||l.children.length===0)))if(l.children&&l.children.length>0){let f=Array.isArray(l.newValue||l.oldValue)?m(l,t,a+2):d(l,t,a+2);f.trim().length>2&&(i>0&&(s+=`,
4
+ `),s+=n,s+=f,i++)}else switch(i>0&&(s+=`,
5
+ `),l.type){case"added":s+=r?`${n}${u.green}+ ${o(l.newValue)}${u.reset}`:`${n}+ ${o(l.newValue)}`,i++;break;case"removed":s+=r?`${n}${u.red}- ${o(l.oldValue)}${u.reset}`:`${n}- ${o(l.oldValue)}`,i++;break;case"unchanged":_optionalChain([l, 'access', _3 => _3.meta, 'optionalAccess', _4 => _4.ignored])&&l.path?s+=r?`${n}${u.gray} ${l.path[l.path.length-1]||""}${u.reset}`:`${n} ${l.path[l.path.length-1]||""}`:s+=r?`${n}${u.gray} ${o(l.newValue)}${u.reset}`:`${n} ${o(l.newValue)}`,i++;break;case"changed":s+=r?`${n}${u.red}- ${o(l.oldValue)}${u.reset}
6
+ ${n}${u.green}+ ${o(l.newValue)}${u.reset}`:`${n}- ${o(l.oldValue)}
7
+ ${n}+ ${o(l.newValue)}`,i++;break}}return i>0&&(s+=`
8
+ `),s+=`${g}]`,s}function d(e,t,a=0){let{color:r=!0,full:$=!1}=t,g=" ".repeat(a),n=" ".repeat(a+2),s=`{
9
+ `,i=0;if(e.children){let c=e.children.filter(l=>{if(l.type!=="unchanged"||$||l.children&&l.children.length>0)return!0;let f=_optionalChain([l, 'access', _5 => _5.path, 'optionalAccess', _6 => _6[l.path.length-1]])||"";return!!_optionalChain([t, 'access', _7 => _7.outputKeys, 'optionalAccess', _8 => _8.includes, 'call', _9 => _9(f)])});for(let l=0;l<c.length;l++){let f=c[l],D=_optionalChain([f, 'access', _10 => _10.path, 'optionalAccess', _11 => _11[f.path.length-1]])||"",p=l===c.length-1;if(i>0&&!s.endsWith(`
10
+ `)&&(s+=`,
11
+ `),f.children&&f.children.length>0){let V=Array.isArray(f.newValue||f.oldValue)?m(f,t,a+2):d(f,t,a+2);V.trim().length>2&&(s+=`${n}${D}: ${V}`,i++)}else switch(f.type){case"added":s+=r?`${n}${u.green}+ ${D}: ${o(f.newValue)}${u.reset}`:`${n}+ ${D}: ${o(f.newValue)}`,i++;break;case"removed":s+=r?`${n}${u.red}- ${D}: ${o(f.oldValue)}${u.reset}`:`${n}- ${D}: ${o(f.oldValue)}`,i++;break;case"changed":s+=r?`${n}${u.red}- ${D}: ${o(f.oldValue)}${u.reset}
12
+ ${n}${u.green}+ ${D}: ${o(f.newValue)}${u.reset}`:`${n}- ${D}: ${o(f.oldValue)}
13
+ ${n}+ ${D}: ${o(f.newValue)}`,i++;break;case"unchanged":($||_optionalChain([t, 'access', _12 => _12.outputKeys, 'optionalAccess', _13 => _13.includes, 'call', _14 => _14(D)]))&&(_optionalChain([f, 'access', _15 => _15.meta, 'optionalAccess', _16 => _16.ignored])?s+=r?`${n}${u.gray} ${D}${u.reset}`:`${n} ${D}`:s+=r?`${n}${u.gray} ${D}: ${o(f.newValue)}${u.reset}`:`${n} ${D}: ${o(f.newValue)}`,i++);break}!p&&!s.endsWith(`
14
+ `)&&(s+=","),s.endsWith(`
15
+ `)||(s+=`
16
+ `)}}return i>0&&!s.endsWith(`
17
+ `)&&(s+=`
18
+ `),s+=`${g}}`,s}function G(e){switch(e){case"added":return"+";case"removed":return"-";case"changed":return"!";default:return" "}}function o(e){return e===void 0?"undefined":e===null?"null":typeof e=="string"?`'${e}'`:typeof e=="number"||typeof e=="boolean"?e.toString():typeof e=="object"?JSON.stringify(e,null,2):String(e)}function H(e,t,a={}){return y(e,t,a)}function v(e,t,a={}){let r=H(e,t,a);return b(r,a)}exports.DiffType = h; exports.diff = v; exports.diffRaw = H;
package/dist/index.mjs CHANGED
@@ -1,407 +1,18 @@
1
- // src/diff.ts
2
- import leven from "leven";
3
-
4
- // src/types.ts
5
- var DiffType = /* @__PURE__ */ ((DiffType2) => {
6
- DiffType2["ADDED"] = "added";
7
- DiffType2["REMOVED"] = "removed";
8
- DiffType2["CHANGED"] = "changed";
9
- DiffType2["UNCHANGED"] = "unchanged";
10
- return DiffType2;
11
- })(DiffType || {});
12
-
13
- // src/diff.ts
14
- function createDiff(oldValue, newValue, options = {}, path = []) {
15
- const { keysOnly = false, ignoreValues = false } = options;
16
- if (oldValue === void 0 && newValue === void 0) {
17
- return { type: "unchanged" /* UNCHANGED */ };
18
- }
19
- if (oldValue === void 0) {
20
- return { type: "added" /* ADDED */, path, newValue };
21
- }
22
- if (newValue === void 0) {
23
- return { type: "removed" /* REMOVED */, path, oldValue };
24
- }
25
- if (typeof oldValue !== "object" || typeof newValue !== "object" || oldValue === null || newValue === null) {
26
- if (keysOnly || ignoreValues) {
27
- return {
28
- type: "unchanged" /* UNCHANGED */,
29
- path,
30
- oldValue,
31
- newValue,
32
- meta: { ignored: true }
33
- };
34
- }
35
- if (oldValue === newValue) {
36
- return { type: "unchanged" /* UNCHANGED */, path, oldValue, newValue };
37
- }
38
- if (typeof oldValue === "string" && typeof newValue === "string") {
39
- const distance = leven(oldValue, newValue);
40
- const maxLength = Math.max(oldValue.length, newValue.length);
41
- const similarityRatio = maxLength > 0 ? 1 - distance / maxLength : 1;
42
- return {
43
- type: "changed" /* CHANGED */,
44
- path,
45
- oldValue,
46
- newValue,
47
- meta: {
48
- levenDistance: distance,
49
- similarity: similarityRatio
50
- }
51
- };
52
- }
53
- return { type: "changed" /* CHANGED */, path, oldValue, newValue };
54
- }
55
- if (Array.isArray(oldValue) && Array.isArray(newValue)) {
56
- return compareArrays(oldValue, newValue, options, path);
57
- }
58
- return compareObjects(
59
- oldValue,
60
- newValue,
61
- options,
62
- path
63
- );
64
- }
65
- function compareObjects(oldObj, newObj, options, path) {
66
- const { ignoreKeys = [] } = options;
67
- const allKeys = /* @__PURE__ */ new Set([
68
- ...Object.keys(oldObj).filter((key) => !ignoreKeys.includes(key)),
69
- ...Object.keys(newObj).filter((key) => !ignoreKeys.includes(key))
70
- ]);
71
- const children = [];
72
- let hasChanges = false;
73
- for (const key of allKeys) {
74
- const childPath = [...path, key];
75
- const oldValue = oldObj[key];
76
- const newValue = newObj[key];
77
- const childDiff = createDiff(oldValue, newValue, options, childPath);
78
- if (childDiff.type !== "unchanged" /* UNCHANGED */) {
79
- hasChanges = true;
80
- }
81
- children.push(childDiff);
82
- }
83
- if (hasChanges) {
84
- return {
85
- type: "changed" /* CHANGED */,
86
- path,
87
- oldValue: oldObj,
88
- newValue: newObj,
89
- children
90
- };
91
- }
92
- return { type: "unchanged" /* UNCHANGED */, path, oldValue: oldObj, newValue: newObj };
93
- }
94
- function compareArrays(oldArray, newArray, options, path) {
95
- if (oldArray.length !== newArray.length) {
96
- const children2 = [];
97
- const maxLength = Math.max(oldArray.length, newArray.length);
98
- for (let i = 0; i < maxLength; i++) {
99
- const childPath = [...path, i.toString()];
100
- if (i >= oldArray.length) {
101
- children2.push({
102
- type: "added" /* ADDED */,
103
- path: childPath,
104
- newValue: newArray[i]
105
- });
106
- } else if (i >= newArray.length) {
107
- children2.push({
108
- type: "removed" /* REMOVED */,
109
- path: childPath,
110
- oldValue: oldArray[i]
111
- });
112
- } else {
113
- children2.push(createDiff(oldArray[i], newArray[i], options, childPath));
114
- }
115
- }
116
- return {
117
- type: "changed" /* CHANGED */,
118
- path,
119
- oldValue: oldArray,
120
- newValue: newArray,
121
- children: children2
122
- };
123
- }
124
- const children = [];
125
- let hasChanges = false;
126
- for (let i = 0; i < oldArray.length; i++) {
127
- const childPath = [...path, i.toString()];
128
- const oldValue = oldArray[i];
129
- const newValue = newArray[i];
130
- let childDiff;
131
- if (typeof oldValue === "string" && typeof newValue === "string") {
132
- if (oldValue === newValue) {
133
- childDiff = {
134
- type: "unchanged" /* UNCHANGED */,
135
- path: childPath,
136
- oldValue,
137
- newValue
138
- };
139
- } else {
140
- const distance = leven(oldValue, newValue);
141
- const maxLength = Math.max(oldValue.length, newValue.length);
142
- const similarityRatio = maxLength > 0 ? 1 - distance / maxLength : 1;
143
- childDiff = {
144
- type: "changed" /* CHANGED */,
145
- path: childPath,
146
- oldValue,
147
- newValue,
148
- meta: {
149
- levenDistance: distance,
150
- similarity: similarityRatio
151
- }
152
- };
153
- hasChanges = true;
154
- }
155
- } else {
156
- childDiff = createDiff(oldValue, newValue, options, childPath);
157
- if (childDiff.type !== "unchanged" /* UNCHANGED */) {
158
- hasChanges = true;
159
- }
160
- }
161
- children.push(childDiff);
162
- }
163
- if (hasChanges) {
164
- return {
165
- type: "changed" /* CHANGED */,
166
- path,
167
- oldValue: oldArray,
168
- newValue: newArray,
169
- children
170
- };
171
- }
172
- return {
173
- type: "unchanged" /* UNCHANGED */,
174
- path,
175
- oldValue: oldArray,
176
- newValue: newArray
177
- };
178
- }
179
-
180
- // src/formatter.ts
181
- var colors = {
182
- reset: "\x1B[0m",
183
- red: "\x1B[31m",
184
- green: "\x1B[32m",
185
- gray: "\x1B[90m"
186
- };
187
- function formatDiff(diff2, options = {}) {
188
- const { color = true, full = false } = options;
189
- if (diff2.type === "unchanged" /* UNCHANGED */ && !full && (!diff2.children || diff2.children.length === 0)) {
190
- return "";
191
- }
192
- if (!diff2.children || diff2.children.length === 0) {
193
- return formatValue(diff2, color);
194
- }
195
- return formatComplex(diff2, options, 0);
196
- }
197
- function formatValue(diff2, useColor) {
198
- const prefix = getPrefix(diff2.type);
199
- let value = "";
200
- switch (diff2.type) {
201
- case "added" /* ADDED */:
202
- value = formatPrimitive(diff2.newValue);
203
- return useColor ? `${colors.green}${prefix} ${value}${colors.reset}` : `${prefix} ${value}`;
204
- case "removed" /* REMOVED */:
205
- value = formatPrimitive(diff2.oldValue);
206
- return useColor ? `${colors.red}${prefix} ${value}${colors.reset}` : `${prefix} ${value}`;
207
- case "changed" /* CHANGED */:
208
- const oldVal = formatPrimitive(diff2.oldValue);
209
- const newVal = formatPrimitive(diff2.newValue);
210
- let similarityInfo = "";
211
- if (diff2.meta?.similarity !== void 0 && typeof diff2.oldValue === "string" && typeof diff2.newValue === "string") {
212
- const similarity = Math.round(diff2.meta.similarity * 100);
213
- similarityInfo = useColor ? `${colors.gray} (${similarity}% similar)${colors.reset}` : ` (${similarity}% similar)`;
214
- }
215
- const oldLine = useColor ? `${colors.red}- ${oldVal}${colors.reset}` : `- ${oldVal}`;
216
- const newLine = useColor ? `${colors.green}+ ${newVal}${similarityInfo}${colors.reset}` : `+ ${newVal}${similarityInfo}`;
217
- return `${oldLine}
218
- ${newLine}`;
219
- default:
220
- value = formatPrimitive(diff2.newValue ?? diff2.oldValue);
221
- return useColor ? `${colors.gray}${prefix} ${value}${colors.reset}` : `${prefix} ${value}`;
222
- }
223
- }
224
- function formatComplex(diff2, options, indent = 0) {
225
- const { full = false } = options;
226
- if (diff2.type === "unchanged" /* UNCHANGED */ && !full && (!diff2.children || diff2.children.length === 0 || typeof diff2.oldValue !== "object" && typeof diff2.newValue !== "object")) {
227
- return "";
228
- }
229
- return Array.isArray(diff2.oldValue) || Array.isArray(diff2.newValue) ? formatArrayDiff(diff2, options, indent) : formatObjectDiff(diff2, options, indent);
230
- }
231
- function formatArrayDiff(diff2, options, indent = 0) {
232
- const { color = true, full = false } = options;
233
- const baseIndent = " ".repeat(indent);
234
- const innerIndent = " ".repeat(indent + 2);
235
- let result = `[
236
- `;
237
- let visibleItems = 0;
238
- if (diff2.children) {
239
- for (let i = 0; i < diff2.children.length; i++) {
240
- const child = diff2.children[i];
241
- if (child.type === "unchanged" /* UNCHANGED */ && !full && (!child.children || child.children.length === 0)) {
242
- continue;
243
- }
244
- if (child.children && child.children.length > 0) {
245
- const nestedOutput = Array.isArray(child.newValue || child.oldValue) ? formatArrayDiff(child, options, indent + 2) : formatObjectDiff(child, options, indent + 2);
246
- if (nestedOutput.trim().length > 2) {
247
- if (visibleItems > 0) {
248
- result += ",\n";
249
- }
250
- result += innerIndent;
251
- result += nestedOutput;
252
- visibleItems++;
253
- }
254
- } else {
255
- if (visibleItems > 0) {
256
- result += ",\n";
257
- }
258
- switch (child.type) {
259
- case "added" /* ADDED */:
260
- result += color ? `${innerIndent}${colors.green}+ ${formatPrimitive(child.newValue)}${colors.reset}` : `${innerIndent}+ ${formatPrimitive(child.newValue)}`;
261
- visibleItems++;
262
- break;
263
- case "removed" /* REMOVED */:
264
- result += color ? `${innerIndent}${colors.red}- ${formatPrimitive(child.oldValue)}${colors.reset}` : `${innerIndent}- ${formatPrimitive(child.oldValue)}`;
265
- visibleItems++;
266
- break;
267
- case "unchanged" /* UNCHANGED */:
268
- if (child.meta?.ignored && child.path) {
269
- result += color ? `${innerIndent}${colors.gray} ${child.path[child.path.length - 1] || ""}${colors.reset}` : `${innerIndent} ${child.path[child.path.length - 1] || ""}`;
270
- } else {
271
- result += color ? `${innerIndent}${colors.gray} ${formatPrimitive(child.newValue)}${colors.reset}` : `${innerIndent} ${formatPrimitive(child.newValue)}`;
272
- }
273
- visibleItems++;
274
- break;
275
- case "changed" /* CHANGED */:
276
- result += color ? `${innerIndent}${colors.red}- ${formatPrimitive(child.oldValue)}${colors.reset}
277
- ${innerIndent}${colors.green}+ ${formatPrimitive(child.newValue)}${colors.reset}` : `${innerIndent}- ${formatPrimitive(child.oldValue)}
278
- ${innerIndent}+ ${formatPrimitive(child.newValue)}`;
279
- visibleItems++;
280
- break;
281
- }
282
- }
283
- }
284
- }
285
- if (visibleItems > 0) {
286
- result += "\n";
287
- }
288
- result += `${baseIndent}]`;
289
- return result;
290
- }
291
- function formatObjectDiff(diff2, options, indent = 0) {
292
- const { color = true, full = false } = options;
293
- const baseIndent = " ".repeat(indent);
294
- const innerIndent = " ".repeat(indent + 2);
295
- let result = `{
296
- `;
297
- let visibleItems = 0;
298
- if (diff2.children) {
299
- const displayableChildren = diff2.children.filter((child) => {
300
- if (child.type !== "unchanged" /* UNCHANGED */) return true;
301
- if (full) return true;
302
- if (child.children && child.children.length > 0) return true;
303
- const key = child.path?.[child.path.length - 1] || "";
304
- if (options.outputKeys?.includes(key)) return true;
305
- return false;
306
- });
307
- for (let i = 0; i < displayableChildren.length; i++) {
308
- const child = displayableChildren[i];
309
- const key = child.path?.[child.path.length - 1] || "";
310
- const isLast = i === displayableChildren.length - 1;
311
- if (visibleItems > 0 && !result.endsWith("\n")) {
312
- result += ",\n";
313
- }
314
- if (child.children && child.children.length > 0) {
315
- const nestedContent = Array.isArray(child.newValue || child.oldValue) ? formatArrayDiff(child, options, indent + 2) : formatObjectDiff(child, options, indent + 2);
316
- if (nestedContent.trim().length > 2) {
317
- result += `${innerIndent}${key}: ${nestedContent}`;
318
- visibleItems++;
319
- }
320
- } else {
321
- switch (child.type) {
322
- case "added" /* ADDED */:
323
- result += color ? `${innerIndent}${colors.green}+ ${key}: ${formatPrimitive(child.newValue)}${colors.reset}` : `${innerIndent}+ ${key}: ${formatPrimitive(child.newValue)}`;
324
- visibleItems++;
325
- break;
326
- case "removed" /* REMOVED */:
327
- result += color ? `${innerIndent}${colors.red}- ${key}: ${formatPrimitive(child.oldValue)}${colors.reset}` : `${innerIndent}- ${key}: ${formatPrimitive(child.oldValue)}`;
328
- visibleItems++;
329
- break;
330
- case "changed" /* CHANGED */:
331
- result += color ? `${innerIndent}${colors.red}- ${key}: ${formatPrimitive(child.oldValue)}${colors.reset}
332
- ${innerIndent}${colors.green}+ ${key}: ${formatPrimitive(child.newValue)}${colors.reset}` : `${innerIndent}- ${key}: ${formatPrimitive(child.oldValue)}
333
- ${innerIndent}+ ${key}: ${formatPrimitive(child.newValue)}`;
334
- visibleItems++;
335
- break;
336
- case "unchanged" /* UNCHANGED */:
337
- if (full || options.outputKeys?.includes(key)) {
338
- if (child.meta?.ignored) {
339
- result += color ? `${innerIndent}${colors.gray} ${key}${colors.reset}` : `${innerIndent} ${key}`;
340
- } else {
341
- result += color ? `${innerIndent}${colors.gray} ${key}: ${formatPrimitive(child.newValue)}${colors.reset}` : `${innerIndent} ${key}: ${formatPrimitive(child.newValue)}`;
342
- }
343
- visibleItems++;
344
- }
345
- break;
346
- }
347
- }
348
- if (!isLast && !result.endsWith("\n")) {
349
- result += ",";
350
- }
351
- if (!result.endsWith("\n")) {
352
- result += "\n";
353
- }
354
- }
355
- }
356
- if (visibleItems > 0 && !result.endsWith("\n")) {
357
- result += "\n";
358
- }
359
- result += `${baseIndent}}`;
360
- return result;
361
- }
362
- function getPrefix(type) {
363
- switch (type) {
364
- case "added" /* ADDED */:
365
- return "+";
366
- case "removed" /* REMOVED */:
367
- return "-";
368
- case "changed" /* CHANGED */:
369
- return "!";
370
- default:
371
- return " ";
372
- }
373
- }
374
- function formatPrimitive(value) {
375
- if (value === void 0) {
376
- return "undefined";
377
- }
378
- if (value === null) {
379
- return "null";
380
- }
381
- if (typeof value === "string") {
382
- return `'${value}'`;
383
- }
384
- if (typeof value === "number" || typeof value === "boolean") {
385
- return value.toString();
386
- }
387
- if (typeof value === "object") {
388
- const json = JSON.stringify(value, null, 2);
389
- return json;
390
- }
391
- return String(value);
392
- }
393
-
394
- // src/index.ts
395
- function diffRaw(oldValue, newValue, options = {}) {
396
- return createDiff(oldValue, newValue, options);
397
- }
398
- function diff(oldValue, newValue, options = {}) {
399
- const diffResult = diffRaw(oldValue, newValue, options);
400
- return formatDiff(diffResult, options);
401
- }
402
- export {
403
- DiffType,
404
- diff,
405
- diffRaw
406
- };
407
- //# sourceMappingURL=index.mjs.map
1
+ import E from"leven";var h=($=>($.ADDED="added",$.REMOVED="removed",$.CHANGED="changed",$.UNCHANGED="unchanged",$))(h||{});function y(e,t,a={},r=[]){let{keysOnly:$=!1,ignoreValues:g=!1}=a;if(e===void 0&&t===void 0)return{type:"unchanged"};if(e===void 0)return{type:"added",path:r,newValue:t};if(t===void 0)return{type:"removed",path:r,oldValue:e};if(typeof e!="object"||typeof t!="object"||e===null||t===null){if($||g)return{type:"unchanged",path:r,oldValue:e,newValue:t,meta:{ignored:!0}};if(e===t)return{type:"unchanged",path:r,oldValue:e,newValue:t};if(typeof e=="string"&&typeof t=="string"){let n=E(e,t),s=Math.max(e.length,t.length),i=s>0?1-n/s:1;return{type:"changed",path:r,oldValue:e,newValue:t,meta:{levenDistance:n,similarity:i}}}return{type:"changed",path:r,oldValue:e,newValue:t}}return Array.isArray(e)&&Array.isArray(t)?R(e,t,a,r):N(e,t,a,r)}function N(e,t,a,r){let{ignoreKeys:$=[]}=a,g=new Set([...Object.keys(e).filter(i=>!$.includes(i)),...Object.keys(t).filter(i=>!$.includes(i))]),n=[],s=!1;for(let i of g){let c=[...r,i],l=e[i],f=t[i],D=y(l,f,a,c);D.type!=="unchanged"&&(s=!0),n.push(D)}return s?{type:"changed",path:r,oldValue:e,newValue:t,children:n}:{type:"unchanged",path:r,oldValue:e,newValue:t}}function R(e,t,a,r){if(e.length!==t.length){let n=[],s=Math.max(e.length,t.length);for(let i=0;i<s;i++){let c=[...r,i.toString()];i>=e.length?n.push({type:"added",path:c,newValue:t[i]}):i>=t.length?n.push({type:"removed",path:c,oldValue:e[i]}):n.push(y(e[i],t[i],a,c))}return{type:"changed",path:r,oldValue:e,newValue:t,children:n}}let $=[],g=!1;for(let n=0;n<e.length;n++){let s=[...r,n.toString()],i=e[n],c=t[n],l;if(typeof i=="string"&&typeof c=="string")if(i===c)l={type:"unchanged",path:s,oldValue:i,newValue:c};else{let f=E(i,c),D=Math.max(i.length,c.length),p=D>0?1-f/D:1;l={type:"changed",path:s,oldValue:i,newValue:c,meta:{levenDistance:f,similarity:p}},g=!0}else l=y(i,c,a,s),l.type!=="unchanged"&&(g=!0);$.push(l)}return g?{type:"changed",path:r,oldValue:e,newValue:t,children:$}:{type:"unchanged",path:r,oldValue:e,newValue:t}}var u={reset:"\x1B[0m",red:"\x1B[31m",green:"\x1B[32m",gray:"\x1B[90m"};function b(e,t={}){let{color:a=!0,full:r=!1}=t;return e.type==="unchanged"&&!r&&(!e.children||e.children.length===0)?"":!e.children||e.children.length===0?A(e,a):C(e,t,0)}function A(e,t){let a=G(e.type),r="";switch(e.type){case"added":return r=o(e.newValue),t?`${u.green}${a} ${r}${u.reset}`:`${a} ${r}`;case"removed":return r=o(e.oldValue),t?`${u.red}${a} ${r}${u.reset}`:`${a} ${r}`;case"changed":let $=o(e.oldValue),g=o(e.newValue),n="";if(e.meta?.similarity!==void 0&&typeof e.oldValue=="string"&&typeof e.newValue=="string"){let c=Math.round(e.meta.similarity*100);n=t?`${u.gray} (${c}% similar)${u.reset}`:` (${c}% similar)`}let s=t?`${u.red}- ${$}${u.reset}`:`- ${$}`,i=t?`${u.green}+ ${g}${n}${u.reset}`:`+ ${g}${n}`;return`${s}
2
+ ${i}`;default:return r=o(e.newValue??e.oldValue),t?`${u.gray}${a} ${r}${u.reset}`:`${a} ${r}`}}function C(e,t,a=0){let{full:r=!1}=t;return e.type==="unchanged"&&!r&&(!e.children||e.children.length===0||typeof e.oldValue!="object"&&typeof e.newValue!="object")?"":Array.isArray(e.oldValue)||Array.isArray(e.newValue)?m(e,t,a):d(e,t,a)}function m(e,t,a=0){let{color:r=!0,full:$=!1}=t,g=" ".repeat(a),n=" ".repeat(a+2),s=`[
3
+ `,i=0;if(e.children)for(let c=0;c<e.children.length;c++){let l=e.children[c];if(!(l.type==="unchanged"&&!$&&(!l.children||l.children.length===0)))if(l.children&&l.children.length>0){let f=Array.isArray(l.newValue||l.oldValue)?m(l,t,a+2):d(l,t,a+2);f.trim().length>2&&(i>0&&(s+=`,
4
+ `),s+=n,s+=f,i++)}else switch(i>0&&(s+=`,
5
+ `),l.type){case"added":s+=r?`${n}${u.green}+ ${o(l.newValue)}${u.reset}`:`${n}+ ${o(l.newValue)}`,i++;break;case"removed":s+=r?`${n}${u.red}- ${o(l.oldValue)}${u.reset}`:`${n}- ${o(l.oldValue)}`,i++;break;case"unchanged":l.meta?.ignored&&l.path?s+=r?`${n}${u.gray} ${l.path[l.path.length-1]||""}${u.reset}`:`${n} ${l.path[l.path.length-1]||""}`:s+=r?`${n}${u.gray} ${o(l.newValue)}${u.reset}`:`${n} ${o(l.newValue)}`,i++;break;case"changed":s+=r?`${n}${u.red}- ${o(l.oldValue)}${u.reset}
6
+ ${n}${u.green}+ ${o(l.newValue)}${u.reset}`:`${n}- ${o(l.oldValue)}
7
+ ${n}+ ${o(l.newValue)}`,i++;break}}return i>0&&(s+=`
8
+ `),s+=`${g}]`,s}function d(e,t,a=0){let{color:r=!0,full:$=!1}=t,g=" ".repeat(a),n=" ".repeat(a+2),s=`{
9
+ `,i=0;if(e.children){let c=e.children.filter(l=>{if(l.type!=="unchanged"||$||l.children&&l.children.length>0)return!0;let f=l.path?.[l.path.length-1]||"";return!!t.outputKeys?.includes(f)});for(let l=0;l<c.length;l++){let f=c[l],D=f.path?.[f.path.length-1]||"",p=l===c.length-1;if(i>0&&!s.endsWith(`
10
+ `)&&(s+=`,
11
+ `),f.children&&f.children.length>0){let V=Array.isArray(f.newValue||f.oldValue)?m(f,t,a+2):d(f,t,a+2);V.trim().length>2&&(s+=`${n}${D}: ${V}`,i++)}else switch(f.type){case"added":s+=r?`${n}${u.green}+ ${D}: ${o(f.newValue)}${u.reset}`:`${n}+ ${D}: ${o(f.newValue)}`,i++;break;case"removed":s+=r?`${n}${u.red}- ${D}: ${o(f.oldValue)}${u.reset}`:`${n}- ${D}: ${o(f.oldValue)}`,i++;break;case"changed":s+=r?`${n}${u.red}- ${D}: ${o(f.oldValue)}${u.reset}
12
+ ${n}${u.green}+ ${D}: ${o(f.newValue)}${u.reset}`:`${n}- ${D}: ${o(f.oldValue)}
13
+ ${n}+ ${D}: ${o(f.newValue)}`,i++;break;case"unchanged":($||t.outputKeys?.includes(D))&&(f.meta?.ignored?s+=r?`${n}${u.gray} ${D}${u.reset}`:`${n} ${D}`:s+=r?`${n}${u.gray} ${D}: ${o(f.newValue)}${u.reset}`:`${n} ${D}: ${o(f.newValue)}`,i++);break}!p&&!s.endsWith(`
14
+ `)&&(s+=","),s.endsWith(`
15
+ `)||(s+=`
16
+ `)}}return i>0&&!s.endsWith(`
17
+ `)&&(s+=`
18
+ `),s+=`${g}}`,s}function G(e){switch(e){case"added":return"+";case"removed":return"-";case"changed":return"!";default:return" "}}function o(e){return e===void 0?"undefined":e===null?"null":typeof e=="string"?`'${e}'`:typeof e=="number"||typeof e=="boolean"?e.toString():typeof e=="object"?JSON.stringify(e,null,2):String(e)}function H(e,t,a={}){return y(e,t,a)}function v(e,t,a={}){let r=H(e,t,a);return b(r,a)}export{h as DiffType,v as diff,H as diffRaw};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "diff-leven",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Git like diff between two strings, using the Levenshtein distance algorithm",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -27,7 +27,11 @@
27
27
  "url": "git+https://github.com/kushalshit27/diff-leven.git"
28
28
  },
29
29
  "keywords": [
30
- "diff"
30
+ "diff",
31
+ "leven",
32
+ "compare",
33
+ "levenshtein",
34
+ "comparison"
31
35
  ],
32
36
  "author": "kushalshit27",
33
37
  "license": "MIT",
@@ -50,8 +54,5 @@
50
54
  },
51
55
  "dependencies": {
52
56
  "leven": "^4.0.0"
53
- },
54
- "publishConfig": {
55
- "access": "public"
56
57
  }
57
58
  }
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/diff.ts","../src/types.ts","../src/formatter.ts"],"sourcesContent":["import { createDiff } from './diff';\nimport { formatDiff } from './formatter';\nimport { DiffOptions, DiffResult, DiffType, SerializableValue } from './types';\n\n/**\n * Compare two values and generate a detailed diff result object\n *\n * @param oldValue - Original value to compare from\n * @param newValue - New value to compare against\n * @param options - Configuration options for the diff\n * @returns A structured diff result object\n */\nexport function diffRaw(\n oldValue: SerializableValue,\n newValue: SerializableValue,\n options: DiffOptions = {},\n): DiffResult {\n return createDiff(oldValue, newValue, options);\n}\n\n/**\n * Compare two values and generate a formatted diff string\n *\n * @param oldValue - Original value to compare from\n * @param newValue - New value to compare against\n * @param options - Configuration options for the diff\n * @returns A formatted string representation of the diff\n */\nexport function diff(\n oldValue: SerializableValue,\n newValue: SerializableValue,\n options: DiffOptions = {},\n): string {\n const diffResult = diffRaw(oldValue, newValue, options);\n return formatDiff(diffResult, options);\n}\n\n// Export types\nexport type { DiffOptions, DiffResult, SerializableValue };\nexport { DiffType };\n","import leven from 'leven';\nimport { DiffOptions, DiffResult, DiffType, SerializableValue } from './types';\n\n/**\n * Compares two values (objects, arrays, strings, etc.) and creates a diff result\n * Uses the Levenshtein distance algorithm for string comparison\n *\n * @param oldValue - The original value to compare\n * @param newValue - The new value to compare against\n * @param options - Configuration options\n * @param path - Current path in the object tree (used internally for recursion)\n * @returns A diff result object\n */\nexport function createDiff(\n oldValue: SerializableValue,\n newValue: SerializableValue,\n options: DiffOptions = {},\n path: string[] = [],\n): DiffResult {\n const { keysOnly = false, ignoreValues = false } = options;\n\n // Handle case where one or both values are undefined\n if (oldValue === undefined && newValue === undefined) {\n return { type: DiffType.UNCHANGED };\n }\n if (oldValue === undefined) {\n return { type: DiffType.ADDED, path, newValue };\n }\n if (newValue === undefined) {\n return { type: DiffType.REMOVED, path, oldValue };\n }\n\n // Handle primitive values\n if (\n typeof oldValue !== 'object' ||\n typeof newValue !== 'object' ||\n oldValue === null ||\n newValue === null\n ) {\n if (keysOnly || ignoreValues) {\n // For ignoreValues, retain the path information for better formatting\n return {\n type: DiffType.UNCHANGED,\n path,\n oldValue,\n newValue,\n meta: { ignored: true },\n };\n }\n if (oldValue === newValue) {\n return { type: DiffType.UNCHANGED, path, oldValue, newValue };\n }\n\n // Special handling for strings - use Levenshtein distance\n if (typeof oldValue === 'string' && typeof newValue === 'string') {\n const distance = leven(oldValue, newValue);\n const maxLength = Math.max(oldValue.length, newValue.length);\n const similarityRatio = maxLength > 0 ? 1 - distance / maxLength : 1;\n\n return {\n type: DiffType.CHANGED,\n path,\n oldValue,\n newValue,\n meta: {\n levenDistance: distance,\n similarity: similarityRatio,\n },\n };\n }\n\n return { type: DiffType.CHANGED, path, oldValue, newValue };\n }\n\n // Handle arrays\n if (Array.isArray(oldValue) && Array.isArray(newValue)) {\n return compareArrays(oldValue, newValue, options, path);\n }\n\n // Handle objects\n return compareObjects(\n oldValue as Record<string, any>,\n newValue as Record<string, any>,\n options,\n path,\n );\n}\n\n/**\n * Compare two objects and generate a diff\n */\nfunction compareObjects(\n oldObj: Record<string, any>,\n newObj: Record<string, any>,\n options: DiffOptions,\n path: string[],\n): DiffResult {\n const { ignoreKeys = [] } = options;\n\n const allKeys = new Set([\n ...Object.keys(oldObj).filter((key) => !ignoreKeys.includes(key)),\n ...Object.keys(newObj).filter((key) => !ignoreKeys.includes(key)),\n ]);\n\n const children: DiffResult[] = [];\n let hasChanges = false;\n\n for (const key of allKeys) {\n const childPath = [...path, key];\n const oldValue = oldObj[key];\n const newValue = newObj[key];\n\n const childDiff = createDiff(oldValue, newValue, options, childPath);\n\n if (childDiff.type !== DiffType.UNCHANGED) {\n hasChanges = true;\n }\n\n children.push(childDiff);\n }\n\n if (hasChanges) {\n return {\n type: DiffType.CHANGED,\n path,\n oldValue: oldObj,\n newValue: newObj,\n children,\n };\n }\n\n return { type: DiffType.UNCHANGED, path, oldValue: oldObj, newValue: newObj };\n}\n\n/**\n * Compare two arrays and generate a diff\n * Uses Levenshtein distance for finding optimal matching between array elements\n */\nfunction compareArrays(\n oldArray: any[],\n newArray: any[],\n options: DiffOptions,\n path: string[],\n): DiffResult {\n // Simple case: arrays of different lengths\n if (oldArray.length !== newArray.length) {\n const children: DiffResult[] = [];\n const maxLength = Math.max(oldArray.length, newArray.length);\n\n for (let i = 0; i < maxLength; i++) {\n const childPath = [...path, i.toString()];\n if (i >= oldArray.length) {\n children.push({\n type: DiffType.ADDED,\n path: childPath,\n newValue: newArray[i],\n });\n } else if (i >= newArray.length) {\n children.push({\n type: DiffType.REMOVED,\n path: childPath,\n oldValue: oldArray[i],\n });\n } else {\n children.push(createDiff(oldArray[i], newArray[i], options, childPath));\n }\n }\n\n return {\n type: DiffType.CHANGED,\n path,\n oldValue: oldArray,\n newValue: newArray,\n children,\n };\n }\n\n // For arrays of primitive values or objects, compare each element\n const children: DiffResult[] = [];\n let hasChanges = false;\n\n for (let i = 0; i < oldArray.length; i++) {\n const childPath = [...path, i.toString()];\n const oldValue = oldArray[i];\n const newValue = newArray[i];\n let childDiff;\n\n // Special handling for strings - use Levenshtein distance\n if (typeof oldValue === 'string' && typeof newValue === 'string') {\n if (oldValue === newValue) {\n childDiff = {\n type: DiffType.UNCHANGED,\n path: childPath,\n oldValue,\n newValue,\n };\n } else {\n const distance = leven(oldValue, newValue);\n const maxLength = Math.max(oldValue.length, newValue.length);\n const similarityRatio = maxLength > 0 ? 1 - distance / maxLength : 1;\n\n childDiff = {\n type: DiffType.CHANGED,\n path: childPath,\n oldValue,\n newValue,\n meta: {\n levenDistance: distance,\n similarity: similarityRatio,\n },\n };\n hasChanges = true;\n }\n } else {\n // For other types\n childDiff = createDiff(oldValue, newValue, options, childPath);\n if (childDiff.type !== DiffType.UNCHANGED) {\n hasChanges = true;\n }\n }\n\n children.push(childDiff);\n }\n\n if (hasChanges) {\n return {\n type: DiffType.CHANGED,\n path,\n oldValue: oldArray,\n newValue: newArray,\n children,\n };\n }\n\n return {\n type: DiffType.UNCHANGED,\n path,\n oldValue: oldArray,\n newValue: newArray,\n };\n}\n","/**\n * Options for diff generation\n */\nexport interface DiffOptions {\n /**\n * Whether to use colorized output\n * @default true\n */\n color?: boolean;\n\n /**\n * Only compare object keys/structure (ignore values)\n * @default false\n */\n keysOnly?: boolean;\n\n /**\n * Output the entire object tree, not just differences\n * @default false\n */\n full?: boolean;\n\n /**\n * Always include these keys in output for objects with differences\n * @default []\n */\n outputKeys?: string[];\n\n /**\n * Skip these keys when comparing objects\n * @default []\n */\n ignoreKeys?: string[];\n\n /**\n * Ignore value differences, focus only on structure\n * @default false\n */\n ignoreValues?: boolean;\n}\n\n/**\n * Enum for diff change types\n */\nexport enum DiffType {\n ADDED = 'added',\n REMOVED = 'removed',\n CHANGED = 'changed',\n UNCHANGED = 'unchanged',\n}\n\n/**\n * Represents a change between two values\n */\nexport interface DiffResult {\n type: DiffType;\n path?: string[];\n oldValue?: any;\n newValue?: any;\n children?: DiffResult[];\n /**\n * Additional metadata about the diff, such as Levenshtein distance metrics\n */\n meta?: {\n /** Levenshtein distance between strings */\n levenDistance?: number;\n /** Similarity ratio (0-1) where 1 means identical */\n similarity?: number;\n /** Any other metadata properties */\n [key: string]: any;\n };\n}\n\n/**\n * Type for handling any serializable value\n */\nexport type SerializableValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | { [key: string]: SerializableValue }\n | SerializableValue[];\n","import { DiffOptions, DiffResult, DiffType } from './types';\n\n// ANSI color codes\nconst colors = {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n gray: '\\x1b[90m',\n};\n\n/**\n * Format a diff result as a string with optional colors and formatting\n * @param diff - The diff result to format\n * @param options - Formatting options\n * @returns A formatted string representation of the diff\n */\nexport function formatDiff(\n diff: DiffResult,\n options: DiffOptions = {},\n): string {\n const { color = true, full = false } = options;\n\n // For unchanged values with no children, we may skip them unless full output is requested\n if (\n diff.type === DiffType.UNCHANGED &&\n !full &&\n (!diff.children || diff.children.length === 0)\n ) {\n return '';\n }\n\n // Handle primitive values\n if (!diff.children || diff.children.length === 0) {\n return formatValue(diff, color);\n }\n\n // Handle objects and arrays\n return formatComplex(diff, options, 0);\n}\n\n/**\n * Format a primitive value diff (added, removed, changed)\n */\nfunction formatValue(diff: DiffResult, useColor: boolean): string {\n const prefix = getPrefix(diff.type);\n let value = '';\n\n switch (diff.type) {\n case DiffType.ADDED:\n value = formatPrimitive(diff.newValue);\n return useColor\n ? `${colors.green}${prefix} ${value}${colors.reset}`\n : `${prefix} ${value}`;\n\n case DiffType.REMOVED:\n value = formatPrimitive(diff.oldValue);\n return useColor\n ? `${colors.red}${prefix} ${value}${colors.reset}`\n : `${prefix} ${value}`;\n\n case DiffType.CHANGED:\n const oldVal = formatPrimitive(diff.oldValue);\n const newVal = formatPrimitive(diff.newValue);\n\n // Add similarity information for strings if available\n let similarityInfo = '';\n if (\n diff.meta?.similarity !== undefined &&\n typeof diff.oldValue === 'string' &&\n typeof diff.newValue === 'string'\n ) {\n const similarity = Math.round(diff.meta.similarity * 100);\n similarityInfo = useColor\n ? `${colors.gray} (${similarity}% similar)${colors.reset}`\n : ` (${similarity}% similar)`;\n }\n\n // Git-style diff format: -old value followed by +new value\n const oldLine = useColor\n ? `${colors.red}- ${oldVal}${colors.reset}`\n : `- ${oldVal}`;\n\n const newLine = useColor\n ? `${colors.green}+ ${newVal}${similarityInfo}${colors.reset}`\n : `+ ${newVal}${similarityInfo}`;\n\n return `${oldLine}\\n${newLine}`;\n\n default:\n value = formatPrimitive(diff.newValue ?? diff.oldValue);\n return useColor\n ? `${colors.gray}${prefix} ${value}${colors.reset}`\n : `${prefix} ${value}`;\n }\n}\n\n/**\n * Format complex objects and arrays\n * For objects, use Git-like diff format with JSON-style indentation\n */\nfunction formatComplex(\n diff: DiffResult,\n options: DiffOptions,\n indent: number = 0,\n): string {\n const { full = false } = options;\n\n // Early return for unchanged primitives\n if (\n diff.type === DiffType.UNCHANGED &&\n !full &&\n (!diff.children ||\n diff.children.length === 0 ||\n (typeof diff.oldValue !== 'object' && typeof diff.newValue !== 'object'))\n ) {\n return '';\n }\n\n return Array.isArray(diff.oldValue) || Array.isArray(diff.newValue)\n ? formatArrayDiff(diff, options, indent)\n : formatObjectDiff(diff, options, indent);\n}\n\n/**\n * Format array diffs with proper indentation and Git-style markers\n */\nfunction formatArrayDiff(\n diff: DiffResult,\n options: DiffOptions,\n indent: number = 0,\n): string {\n const { color = true, full = false } = options;\n const baseIndent = ' '.repeat(indent);\n const innerIndent = ' '.repeat(indent + 2);\n let result = `[\\n`;\n let visibleItems = 0;\n\n if (diff.children) {\n for (let i = 0; i < diff.children.length; i++) {\n const child = diff.children[i];\n\n // Skip unchanged items unless full output is requested\n if (\n child.type === DiffType.UNCHANGED &&\n !full &&\n (!child.children || child.children.length === 0)\n ) {\n continue;\n }\n\n if (child.children && child.children.length > 0) {\n // Handle nested objects/arrays within the array\n const nestedOutput = Array.isArray(child.newValue || child.oldValue)\n ? formatArrayDiff(child, options, indent + 2)\n : formatObjectDiff(child, options, indent + 2);\n\n // Only add if there's actual content\n if (nestedOutput.trim().length > 2) {\n // More than just '[]' or '{}'\n if (visibleItems > 0) {\n result += ',\\n';\n }\n result += innerIndent;\n result += nestedOutput;\n visibleItems++;\n }\n } else {\n // Handle primitive values\n if (visibleItems > 0) {\n result += ',\\n';\n }\n\n switch (child.type) {\n case DiffType.ADDED:\n result += color\n ? `${innerIndent}${colors.green}+ ${formatPrimitive(child.newValue)}${colors.reset}`\n : `${innerIndent}+ ${formatPrimitive(child.newValue)}`;\n visibleItems++;\n break;\n case DiffType.REMOVED:\n result += color\n ? `${innerIndent}${colors.red}- ${formatPrimitive(child.oldValue)}${colors.reset}`\n : `${innerIndent}- ${formatPrimitive(child.oldValue)}`;\n visibleItems++;\n break;\n case DiffType.UNCHANGED:\n // Special handling for ignored values (when using ignoreValues: true)\n if (child.meta?.ignored && child.path) {\n result += color\n ? `${innerIndent}${colors.gray} ${child.path[child.path.length - 1] || ''}${colors.reset}`\n : `${innerIndent} ${child.path[child.path.length - 1] || ''}`;\n } else {\n result += color\n ? `${innerIndent}${colors.gray} ${formatPrimitive(child.newValue)}${colors.reset}`\n : `${innerIndent} ${formatPrimitive(child.newValue)}`;\n }\n visibleItems++;\n break;\n case DiffType.CHANGED:\n result += color\n ? `${innerIndent}${colors.red}- ${formatPrimitive(child.oldValue)}${colors.reset}\\n` +\n `${innerIndent}${colors.green}+ ${formatPrimitive(child.newValue)}${colors.reset}`\n : `${innerIndent}- ${formatPrimitive(child.oldValue)}\\n` +\n `${innerIndent}+ ${formatPrimitive(child.newValue)}`;\n visibleItems++;\n break;\n }\n }\n }\n }\n\n if (visibleItems > 0) {\n result += '\\n';\n }\n result += `${baseIndent}]`;\n return result;\n}\n\n/**\n * Format object diffs with proper indentation and Git-style markers\n */\nfunction formatObjectDiff(\n diff: DiffResult,\n options: DiffOptions,\n indent: number = 0,\n): string {\n const { color = true, full = false } = options;\n const baseIndent = ' '.repeat(indent);\n const innerIndent = ' '.repeat(indent + 2);\n let result = `{\\n`;\n let visibleItems = 0;\n\n if (diff.children) {\n // First, filter out children that won't be displayed\n const displayableChildren = diff.children.filter((child) => {\n if (child.type !== DiffType.UNCHANGED) return true;\n if (full) return true;\n if (child.children && child.children.length > 0) return true;\n const key = child.path?.[child.path.length - 1] || '';\n if (options.outputKeys?.includes(key)) return true;\n return false;\n });\n\n for (let i = 0; i < displayableChildren.length; i++) {\n const child = displayableChildren[i];\n const key = child.path?.[child.path.length - 1] || '';\n const isLast = i === displayableChildren.length - 1;\n\n // If we already added an item, and we're not at a new line, add a comma and new line\n if (visibleItems > 0 && !result.endsWith('\\n')) {\n result += ',\\n';\n }\n\n if (child.children && child.children.length > 0) {\n // Handle nested objects/arrays\n const nestedContent = Array.isArray(child.newValue || child.oldValue)\n ? formatArrayDiff(child, options, indent + 2)\n : formatObjectDiff(child, options, indent + 2);\n\n // Only add if there's actual content in the nested structure\n if (nestedContent.trim().length > 2) {\n // More than just '{}' or '[]'\n result += `${innerIndent}${key}: ${nestedContent}`;\n visibleItems++;\n }\n } else {\n // Handle primitive values\n switch (child.type) {\n case DiffType.ADDED:\n result += color\n ? `${innerIndent}${colors.green}+ ${key}: ${formatPrimitive(child.newValue)}${colors.reset}`\n : `${innerIndent}+ ${key}: ${formatPrimitive(child.newValue)}`;\n visibleItems++;\n break;\n case DiffType.REMOVED:\n result += color\n ? `${innerIndent}${colors.red}- ${key}: ${formatPrimitive(child.oldValue)}${colors.reset}`\n : `${innerIndent}- ${key}: ${formatPrimitive(child.oldValue)}`;\n visibleItems++;\n break;\n case DiffType.CHANGED:\n result += color\n ? `${innerIndent}${colors.red}- ${key}: ${formatPrimitive(child.oldValue)}${colors.reset}\\n` +\n `${innerIndent}${colors.green}+ ${key}: ${formatPrimitive(child.newValue)}${colors.reset}`\n : `${innerIndent}- ${key}: ${formatPrimitive(child.oldValue)}\\n` +\n `${innerIndent}+ ${key}: ${formatPrimitive(child.newValue)}`;\n visibleItems++;\n break;\n case DiffType.UNCHANGED:\n if (full || options.outputKeys?.includes(key)) {\n // Special handling for ignored values (when using ignoreValues: true)\n if (child.meta?.ignored) {\n result += color\n ? `${innerIndent}${colors.gray} ${key}${colors.reset}`\n : `${innerIndent} ${key}`;\n } else {\n result += color\n ? `${innerIndent}${colors.gray} ${key}: ${formatPrimitive(child.newValue)}${colors.reset}`\n : `${innerIndent} ${key}: ${formatPrimitive(child.newValue)}`;\n }\n visibleItems++;\n }\n break;\n }\n }\n\n // Add comma if not the last item and not already ending with newline\n if (!isLast && !result.endsWith('\\n')) {\n result += ',';\n }\n\n // Always ensure we end with a newline before the next item\n if (!result.endsWith('\\n')) {\n result += '\\n';\n }\n }\n }\n\n // Only add final newline if we have content\n if (visibleItems > 0 && !result.endsWith('\\n')) {\n result += '\\n';\n }\n\n result += `${baseIndent}}`;\n return result;\n}\n\n/**\n * Get the prefix for a diff type\n */\nfunction getPrefix(type: DiffType | string): string {\n switch (type) {\n case DiffType.ADDED:\n return '+';\n case DiffType.REMOVED:\n return '-';\n case DiffType.CHANGED:\n return '!';\n default:\n return ' ';\n }\n}\n\n/**\n * Format a primitive value for output\n */\nfunction formatPrimitive(value: any): string {\n if (value === undefined) {\n return 'undefined';\n }\n\n if (value === null) {\n return 'null';\n }\n\n if (typeof value === 'string') {\n // Use JavaScript object notation with single quotes\n return `'${value}'`;\n }\n\n if (typeof value === 'number' || typeof value === 'boolean') {\n return value.toString();\n }\n\n // For objects and arrays, use properly formatted JavaScript object notation\n if (typeof value === 'object') {\n const json = JSON.stringify(value, null, 2);\n return json;\n }\n\n return String(value);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAAkB;;;AC4CX,IAAK,WAAL,kBAAKA,cAAL;AACL,EAAAA,UAAA,WAAQ;AACR,EAAAA,UAAA,aAAU;AACV,EAAAA,UAAA,aAAU;AACV,EAAAA,UAAA,eAAY;AAJF,SAAAA;AAAA,GAAA;;;AD/BL,SAAS,WACd,UACA,UACA,UAAuB,CAAC,GACxB,OAAiB,CAAC,GACN;AACZ,QAAM,EAAE,WAAW,OAAO,eAAe,MAAM,IAAI;AAGnD,MAAI,aAAa,UAAa,aAAa,QAAW;AACpD,WAAO,EAAE,kCAAyB;AAAA,EACpC;AACA,MAAI,aAAa,QAAW;AAC1B,WAAO,EAAE,2BAAsB,MAAM,SAAS;AAAA,EAChD;AACA,MAAI,aAAa,QAAW;AAC1B,WAAO,EAAE,+BAAwB,MAAM,SAAS;AAAA,EAClD;AAGA,MACE,OAAO,aAAa,YACpB,OAAO,aAAa,YACpB,aAAa,QACb,aAAa,MACb;AACA,QAAI,YAAY,cAAc;AAE5B,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM,EAAE,SAAS,KAAK;AAAA,MACxB;AAAA,IACF;AACA,QAAI,aAAa,UAAU;AACzB,aAAO,EAAE,mCAA0B,MAAM,UAAU,SAAS;AAAA,IAC9D;AAGA,QAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UAAU;AAChE,YAAM,eAAW,aAAAC,SAAM,UAAU,QAAQ;AACzC,YAAM,YAAY,KAAK,IAAI,SAAS,QAAQ,SAAS,MAAM;AAC3D,YAAM,kBAAkB,YAAY,IAAI,IAAI,WAAW,YAAY;AAEnE,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,YAAY;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,+BAAwB,MAAM,UAAU,SAAS;AAAA,EAC5D;AAGA,MAAI,MAAM,QAAQ,QAAQ,KAAK,MAAM,QAAQ,QAAQ,GAAG;AACtD,WAAO,cAAc,UAAU,UAAU,SAAS,IAAI;AAAA,EACxD;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKA,SAAS,eACP,QACA,QACA,SACA,MACY;AACZ,QAAM,EAAE,aAAa,CAAC,EAAE,IAAI;AAE5B,QAAM,UAAU,oBAAI,IAAI;AAAA,IACtB,GAAG,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,WAAW,SAAS,GAAG,CAAC;AAAA,IAChE,GAAG,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,WAAW,SAAS,GAAG,CAAC;AAAA,EAClE,CAAC;AAED,QAAM,WAAyB,CAAC;AAChC,MAAI,aAAa;AAEjB,aAAW,OAAO,SAAS;AACzB,UAAM,YAAY,CAAC,GAAG,MAAM,GAAG;AAC/B,UAAM,WAAW,OAAO,GAAG;AAC3B,UAAM,WAAW,OAAO,GAAG;AAE3B,UAAM,YAAY,WAAW,UAAU,UAAU,SAAS,SAAS;AAEnE,QAAI,UAAU,sCAA6B;AACzC,mBAAa;AAAA,IACf;AAEA,aAAS,KAAK,SAAS;AAAA,EACzB;AAEA,MAAI,YAAY;AACd,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,mCAA0B,MAAM,UAAU,QAAQ,UAAU,OAAO;AAC9E;AAMA,SAAS,cACP,UACA,UACA,SACA,MACY;AAEZ,MAAI,SAAS,WAAW,SAAS,QAAQ;AACvC,UAAMC,YAAyB,CAAC;AAChC,UAAM,YAAY,KAAK,IAAI,SAAS,QAAQ,SAAS,MAAM;AAE3D,aAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAClC,YAAM,YAAY,CAAC,GAAG,MAAM,EAAE,SAAS,CAAC;AACxC,UAAI,KAAK,SAAS,QAAQ;AACxB,QAAAA,UAAS,KAAK;AAAA,UACZ;AAAA,UACA,MAAM;AAAA,UACN,UAAU,SAAS,CAAC;AAAA,QACtB,CAAC;AAAA,MACH,WAAW,KAAK,SAAS,QAAQ;AAC/B,QAAAA,UAAS,KAAK;AAAA,UACZ;AAAA,UACA,MAAM;AAAA,UACN,UAAU,SAAS,CAAC;AAAA,QACtB,CAAC;AAAA,MACH,OAAO;AACL,QAAAA,UAAS,KAAK,WAAW,SAAS,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,SAAS,CAAC;AAAA,MACxE;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAAA;AAAA,IACF;AAAA,EACF;AAGA,QAAM,WAAyB,CAAC;AAChC,MAAI,aAAa;AAEjB,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,YAAY,CAAC,GAAG,MAAM,EAAE,SAAS,CAAC;AACxC,UAAM,WAAW,SAAS,CAAC;AAC3B,UAAM,WAAW,SAAS,CAAC;AAC3B,QAAI;AAGJ,QAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UAAU;AAChE,UAAI,aAAa,UAAU;AACzB,oBAAY;AAAA,UACV;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA;AAAA,QACF;AAAA,MACF,OAAO;AACL,cAAM,eAAW,aAAAD,SAAM,UAAU,QAAQ;AACzC,cAAM,YAAY,KAAK,IAAI,SAAS,QAAQ,SAAS,MAAM;AAC3D,cAAM,kBAAkB,YAAY,IAAI,IAAI,WAAW,YAAY;AAEnE,oBAAY;AAAA,UACV;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA,MAAM;AAAA,YACJ,eAAe;AAAA,YACf,YAAY;AAAA,UACd;AAAA,QACF;AACA,qBAAa;AAAA,MACf;AAAA,IACF,OAAO;AAEL,kBAAY,WAAW,UAAU,UAAU,SAAS,SAAS;AAC7D,UAAI,UAAU,sCAA6B;AACzC,qBAAa;AAAA,MACf;AAAA,IACF;AAEA,aAAS,KAAK,SAAS;AAAA,EACzB;AAEA,MAAI,YAAY;AACd,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AACF;;;AE7OA,IAAM,SAAS;AAAA,EACb,OAAO;AAAA,EACP,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM;AACR;AAQO,SAAS,WACdE,OACA,UAAuB,CAAC,GAChB;AACR,QAAM,EAAE,QAAQ,MAAM,OAAO,MAAM,IAAI;AAGvC,MACEA,MAAK,wCACL,CAAC,SACA,CAACA,MAAK,YAAYA,MAAK,SAAS,WAAW,IAC5C;AACA,WAAO;AAAA,EACT;AAGA,MAAI,CAACA,MAAK,YAAYA,MAAK,SAAS,WAAW,GAAG;AAChD,WAAO,YAAYA,OAAM,KAAK;AAAA,EAChC;AAGA,SAAO,cAAcA,OAAM,SAAS,CAAC;AACvC;AAKA,SAAS,YAAYA,OAAkB,UAA2B;AAChE,QAAM,SAAS,UAAUA,MAAK,IAAI;AAClC,MAAI,QAAQ;AAEZ,UAAQA,MAAK,MAAM;AAAA,IACjB;AACE,cAAQ,gBAAgBA,MAAK,QAAQ;AACrC,aAAO,WACH,GAAG,OAAO,KAAK,GAAG,MAAM,IAAI,KAAK,GAAG,OAAO,KAAK,KAChD,GAAG,MAAM,IAAI,KAAK;AAAA,IAExB;AACE,cAAQ,gBAAgBA,MAAK,QAAQ;AACrC,aAAO,WACH,GAAG,OAAO,GAAG,GAAG,MAAM,IAAI,KAAK,GAAG,OAAO,KAAK,KAC9C,GAAG,MAAM,IAAI,KAAK;AAAA,IAExB;AACE,YAAM,SAAS,gBAAgBA,MAAK,QAAQ;AAC5C,YAAM,SAAS,gBAAgBA,MAAK,QAAQ;AAG5C,UAAI,iBAAiB;AACrB,UACEA,MAAK,MAAM,eAAe,UAC1B,OAAOA,MAAK,aAAa,YACzB,OAAOA,MAAK,aAAa,UACzB;AACA,cAAM,aAAa,KAAK,MAAMA,MAAK,KAAK,aAAa,GAAG;AACxD,yBAAiB,WACb,GAAG,OAAO,IAAI,KAAK,UAAU,aAAa,OAAO,KAAK,KACtD,KAAK,UAAU;AAAA,MACrB;AAGA,YAAM,UAAU,WACZ,GAAG,OAAO,GAAG,KAAK,MAAM,GAAG,OAAO,KAAK,KACvC,KAAK,MAAM;AAEf,YAAM,UAAU,WACZ,GAAG,OAAO,KAAK,KAAK,MAAM,GAAG,cAAc,GAAG,OAAO,KAAK,KAC1D,KAAK,MAAM,GAAG,cAAc;AAEhC,aAAO,GAAG,OAAO;AAAA,EAAK,OAAO;AAAA,IAE/B;AACE,cAAQ,gBAAgBA,MAAK,YAAYA,MAAK,QAAQ;AACtD,aAAO,WACH,GAAG,OAAO,IAAI,GAAG,MAAM,IAAI,KAAK,GAAG,OAAO,KAAK,KAC/C,GAAG,MAAM,IAAI,KAAK;AAAA,EAC1B;AACF;AAMA,SAAS,cACPA,OACA,SACA,SAAiB,GACT;AACR,QAAM,EAAE,OAAO,MAAM,IAAI;AAGzB,MACEA,MAAK,wCACL,CAAC,SACA,CAACA,MAAK,YACLA,MAAK,SAAS,WAAW,KACxB,OAAOA,MAAK,aAAa,YAAY,OAAOA,MAAK,aAAa,WACjE;AACA,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,QAAQA,MAAK,QAAQ,KAAK,MAAM,QAAQA,MAAK,QAAQ,IAC9D,gBAAgBA,OAAM,SAAS,MAAM,IACrC,iBAAiBA,OAAM,SAAS,MAAM;AAC5C;AAKA,SAAS,gBACPA,OACA,SACA,SAAiB,GACT;AACR,QAAM,EAAE,QAAQ,MAAM,OAAO,MAAM,IAAI;AACvC,QAAM,aAAa,IAAI,OAAO,MAAM;AACpC,QAAM,cAAc,IAAI,OAAO,SAAS,CAAC;AACzC,MAAI,SAAS;AAAA;AACb,MAAI,eAAe;AAEnB,MAAIA,MAAK,UAAU;AACjB,aAAS,IAAI,GAAG,IAAIA,MAAK,SAAS,QAAQ,KAAK;AAC7C,YAAM,QAAQA,MAAK,SAAS,CAAC;AAG7B,UACE,MAAM,wCACN,CAAC,SACA,CAAC,MAAM,YAAY,MAAM,SAAS,WAAW,IAC9C;AACA;AAAA,MACF;AAEA,UAAI,MAAM,YAAY,MAAM,SAAS,SAAS,GAAG;AAE/C,cAAM,eAAe,MAAM,QAAQ,MAAM,YAAY,MAAM,QAAQ,IAC/D,gBAAgB,OAAO,SAAS,SAAS,CAAC,IAC1C,iBAAiB,OAAO,SAAS,SAAS,CAAC;AAG/C,YAAI,aAAa,KAAK,EAAE,SAAS,GAAG;AAElC,cAAI,eAAe,GAAG;AACpB,sBAAU;AAAA,UACZ;AACA,oBAAU;AACV,oBAAU;AACV;AAAA,QACF;AAAA,MACF,OAAO;AAEL,YAAI,eAAe,GAAG;AACpB,oBAAU;AAAA,QACZ;AAEA,gBAAQ,MAAM,MAAM;AAAA,UAClB;AACE,sBAAU,QACN,GAAG,WAAW,GAAG,OAAO,KAAK,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KAChF,GAAG,WAAW,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AACtD;AACA;AAAA,UACF;AACE,sBAAU,QACN,GAAG,WAAW,GAAG,OAAO,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KAC9E,GAAG,WAAW,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AACtD;AACA;AAAA,UACF;AAEE,gBAAI,MAAM,MAAM,WAAW,MAAM,MAAM;AACrC,wBAAU,QACN,GAAG,WAAW,GAAG,OAAO,IAAI,KAAK,MAAM,KAAK,MAAM,KAAK,SAAS,CAAC,KAAK,EAAE,GAAG,OAAO,KAAK,KACvF,GAAG,WAAW,KAAK,MAAM,KAAK,MAAM,KAAK,SAAS,CAAC,KAAK,EAAE;AAAA,YAChE,OAAO;AACL,wBAAU,QACN,GAAG,WAAW,GAAG,OAAO,IAAI,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KAC/E,GAAG,WAAW,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAAA,YACxD;AACA;AACA;AAAA,UACF;AACE,sBAAU,QACN,GAAG,WAAW,GAAG,OAAO,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK;AAAA,EAC3E,WAAW,GAAG,OAAO,KAAK,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KAChF,GAAG,WAAW,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAAA,EAC/C,WAAW,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AACtD;AACA;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,eAAe,GAAG;AACpB,cAAU;AAAA,EACZ;AACA,YAAU,GAAG,UAAU;AACvB,SAAO;AACT;AAKA,SAAS,iBACPA,OACA,SACA,SAAiB,GACT;AACR,QAAM,EAAE,QAAQ,MAAM,OAAO,MAAM,IAAI;AACvC,QAAM,aAAa,IAAI,OAAO,MAAM;AACpC,QAAM,cAAc,IAAI,OAAO,SAAS,CAAC;AACzC,MAAI,SAAS;AAAA;AACb,MAAI,eAAe;AAEnB,MAAIA,MAAK,UAAU;AAEjB,UAAM,sBAAsBA,MAAK,SAAS,OAAO,CAAC,UAAU;AAC1D,UAAI,MAAM,qCAA6B,QAAO;AAC9C,UAAI,KAAM,QAAO;AACjB,UAAI,MAAM,YAAY,MAAM,SAAS,SAAS,EAAG,QAAO;AACxD,YAAM,MAAM,MAAM,OAAO,MAAM,KAAK,SAAS,CAAC,KAAK;AACnD,UAAI,QAAQ,YAAY,SAAS,GAAG,EAAG,QAAO;AAC9C,aAAO;AAAA,IACT,CAAC;AAED,aAAS,IAAI,GAAG,IAAI,oBAAoB,QAAQ,KAAK;AACnD,YAAM,QAAQ,oBAAoB,CAAC;AACnC,YAAM,MAAM,MAAM,OAAO,MAAM,KAAK,SAAS,CAAC,KAAK;AACnD,YAAM,SAAS,MAAM,oBAAoB,SAAS;AAGlD,UAAI,eAAe,KAAK,CAAC,OAAO,SAAS,IAAI,GAAG;AAC9C,kBAAU;AAAA,MACZ;AAEA,UAAI,MAAM,YAAY,MAAM,SAAS,SAAS,GAAG;AAE/C,cAAM,gBAAgB,MAAM,QAAQ,MAAM,YAAY,MAAM,QAAQ,IAChE,gBAAgB,OAAO,SAAS,SAAS,CAAC,IAC1C,iBAAiB,OAAO,SAAS,SAAS,CAAC;AAG/C,YAAI,cAAc,KAAK,EAAE,SAAS,GAAG;AAEnC,oBAAU,GAAG,WAAW,GAAG,GAAG,KAAK,aAAa;AAChD;AAAA,QACF;AAAA,MACF,OAAO;AAEL,gBAAQ,MAAM,MAAM;AAAA,UAClB;AACE,sBAAU,QACN,GAAG,WAAW,GAAG,OAAO,KAAK,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KACxF,GAAG,WAAW,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAC9D;AACA;AAAA,UACF;AACE,sBAAU,QACN,GAAG,WAAW,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KACtF,GAAG,WAAW,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAC9D;AACA;AAAA,UACF;AACE,sBAAU,QACN,GAAG,WAAW,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK;AAAA,EACnF,WAAW,GAAG,OAAO,KAAK,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KACxF,GAAG,WAAW,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAAA,EACvD,WAAW,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAC9D;AACA;AAAA,UACF;AACE,gBAAI,QAAQ,QAAQ,YAAY,SAAS,GAAG,GAAG;AAE7C,kBAAI,MAAM,MAAM,SAAS;AACvB,0BAAU,QACN,GAAG,WAAW,GAAG,OAAO,IAAI,KAAK,GAAG,GAAG,OAAO,KAAK,KACnD,GAAG,WAAW,KAAK,GAAG;AAAA,cAC5B,OAAO;AACL,0BAAU,QACN,GAAG,WAAW,GAAG,OAAO,IAAI,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KACvF,GAAG,WAAW,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAAA,cAChE;AACA;AAAA,YACF;AACA;AAAA,QACJ;AAAA,MACF;AAGA,UAAI,CAAC,UAAU,CAAC,OAAO,SAAS,IAAI,GAAG;AACrC,kBAAU;AAAA,MACZ;AAGA,UAAI,CAAC,OAAO,SAAS,IAAI,GAAG;AAC1B,kBAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAGA,MAAI,eAAe,KAAK,CAAC,OAAO,SAAS,IAAI,GAAG;AAC9C,cAAU;AAAA,EACZ;AAEA,YAAU,GAAG,UAAU;AACvB,SAAO;AACT;AAKA,SAAS,UAAU,MAAiC;AAClD,UAAQ,MAAM;AAAA,IACZ;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAKA,SAAS,gBAAgB,OAAoB;AAC3C,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,UAAU,UAAU;AAE7B,WAAO,IAAI,KAAK;AAAA,EAClB;AAEA,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,WAAW;AAC3D,WAAO,MAAM,SAAS;AAAA,EACxB;AAGA,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,OAAO,KAAK,UAAU,OAAO,MAAM,CAAC;AAC1C,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,KAAK;AACrB;;;AHvWO,SAAS,QACd,UACA,UACA,UAAuB,CAAC,GACZ;AACZ,SAAO,WAAW,UAAU,UAAU,OAAO;AAC/C;AAUO,SAAS,KACd,UACA,UACA,UAAuB,CAAC,GAChB;AACR,QAAM,aAAa,QAAQ,UAAU,UAAU,OAAO;AACtD,SAAO,WAAW,YAAY,OAAO;AACvC;","names":["DiffType","leven","children","diff"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/diff.ts","../src/types.ts","../src/formatter.ts","../src/index.ts"],"sourcesContent":["import leven from 'leven';\nimport { DiffOptions, DiffResult, DiffType, SerializableValue } from './types';\n\n/**\n * Compares two values (objects, arrays, strings, etc.) and creates a diff result\n * Uses the Levenshtein distance algorithm for string comparison\n *\n * @param oldValue - The original value to compare\n * @param newValue - The new value to compare against\n * @param options - Configuration options\n * @param path - Current path in the object tree (used internally for recursion)\n * @returns A diff result object\n */\nexport function createDiff(\n oldValue: SerializableValue,\n newValue: SerializableValue,\n options: DiffOptions = {},\n path: string[] = [],\n): DiffResult {\n const { keysOnly = false, ignoreValues = false } = options;\n\n // Handle case where one or both values are undefined\n if (oldValue === undefined && newValue === undefined) {\n return { type: DiffType.UNCHANGED };\n }\n if (oldValue === undefined) {\n return { type: DiffType.ADDED, path, newValue };\n }\n if (newValue === undefined) {\n return { type: DiffType.REMOVED, path, oldValue };\n }\n\n // Handle primitive values\n if (\n typeof oldValue !== 'object' ||\n typeof newValue !== 'object' ||\n oldValue === null ||\n newValue === null\n ) {\n if (keysOnly || ignoreValues) {\n // For ignoreValues, retain the path information for better formatting\n return {\n type: DiffType.UNCHANGED,\n path,\n oldValue,\n newValue,\n meta: { ignored: true },\n };\n }\n if (oldValue === newValue) {\n return { type: DiffType.UNCHANGED, path, oldValue, newValue };\n }\n\n // Special handling for strings - use Levenshtein distance\n if (typeof oldValue === 'string' && typeof newValue === 'string') {\n const distance = leven(oldValue, newValue);\n const maxLength = Math.max(oldValue.length, newValue.length);\n const similarityRatio = maxLength > 0 ? 1 - distance / maxLength : 1;\n\n return {\n type: DiffType.CHANGED,\n path,\n oldValue,\n newValue,\n meta: {\n levenDistance: distance,\n similarity: similarityRatio,\n },\n };\n }\n\n return { type: DiffType.CHANGED, path, oldValue, newValue };\n }\n\n // Handle arrays\n if (Array.isArray(oldValue) && Array.isArray(newValue)) {\n return compareArrays(oldValue, newValue, options, path);\n }\n\n // Handle objects\n return compareObjects(\n oldValue as Record<string, any>,\n newValue as Record<string, any>,\n options,\n path,\n );\n}\n\n/**\n * Compare two objects and generate a diff\n */\nfunction compareObjects(\n oldObj: Record<string, any>,\n newObj: Record<string, any>,\n options: DiffOptions,\n path: string[],\n): DiffResult {\n const { ignoreKeys = [] } = options;\n\n const allKeys = new Set([\n ...Object.keys(oldObj).filter((key) => !ignoreKeys.includes(key)),\n ...Object.keys(newObj).filter((key) => !ignoreKeys.includes(key)),\n ]);\n\n const children: DiffResult[] = [];\n let hasChanges = false;\n\n for (const key of allKeys) {\n const childPath = [...path, key];\n const oldValue = oldObj[key];\n const newValue = newObj[key];\n\n const childDiff = createDiff(oldValue, newValue, options, childPath);\n\n if (childDiff.type !== DiffType.UNCHANGED) {\n hasChanges = true;\n }\n\n children.push(childDiff);\n }\n\n if (hasChanges) {\n return {\n type: DiffType.CHANGED,\n path,\n oldValue: oldObj,\n newValue: newObj,\n children,\n };\n }\n\n return { type: DiffType.UNCHANGED, path, oldValue: oldObj, newValue: newObj };\n}\n\n/**\n * Compare two arrays and generate a diff\n * Uses Levenshtein distance for finding optimal matching between array elements\n */\nfunction compareArrays(\n oldArray: any[],\n newArray: any[],\n options: DiffOptions,\n path: string[],\n): DiffResult {\n // Simple case: arrays of different lengths\n if (oldArray.length !== newArray.length) {\n const children: DiffResult[] = [];\n const maxLength = Math.max(oldArray.length, newArray.length);\n\n for (let i = 0; i < maxLength; i++) {\n const childPath = [...path, i.toString()];\n if (i >= oldArray.length) {\n children.push({\n type: DiffType.ADDED,\n path: childPath,\n newValue: newArray[i],\n });\n } else if (i >= newArray.length) {\n children.push({\n type: DiffType.REMOVED,\n path: childPath,\n oldValue: oldArray[i],\n });\n } else {\n children.push(createDiff(oldArray[i], newArray[i], options, childPath));\n }\n }\n\n return {\n type: DiffType.CHANGED,\n path,\n oldValue: oldArray,\n newValue: newArray,\n children,\n };\n }\n\n // For arrays of primitive values or objects, compare each element\n const children: DiffResult[] = [];\n let hasChanges = false;\n\n for (let i = 0; i < oldArray.length; i++) {\n const childPath = [...path, i.toString()];\n const oldValue = oldArray[i];\n const newValue = newArray[i];\n let childDiff;\n\n // Special handling for strings - use Levenshtein distance\n if (typeof oldValue === 'string' && typeof newValue === 'string') {\n if (oldValue === newValue) {\n childDiff = {\n type: DiffType.UNCHANGED,\n path: childPath,\n oldValue,\n newValue,\n };\n } else {\n const distance = leven(oldValue, newValue);\n const maxLength = Math.max(oldValue.length, newValue.length);\n const similarityRatio = maxLength > 0 ? 1 - distance / maxLength : 1;\n\n childDiff = {\n type: DiffType.CHANGED,\n path: childPath,\n oldValue,\n newValue,\n meta: {\n levenDistance: distance,\n similarity: similarityRatio,\n },\n };\n hasChanges = true;\n }\n } else {\n // For other types\n childDiff = createDiff(oldValue, newValue, options, childPath);\n if (childDiff.type !== DiffType.UNCHANGED) {\n hasChanges = true;\n }\n }\n\n children.push(childDiff);\n }\n\n if (hasChanges) {\n return {\n type: DiffType.CHANGED,\n path,\n oldValue: oldArray,\n newValue: newArray,\n children,\n };\n }\n\n return {\n type: DiffType.UNCHANGED,\n path,\n oldValue: oldArray,\n newValue: newArray,\n };\n}\n","/**\n * Options for diff generation\n */\nexport interface DiffOptions {\n /**\n * Whether to use colorized output\n * @default true\n */\n color?: boolean;\n\n /**\n * Only compare object keys/structure (ignore values)\n * @default false\n */\n keysOnly?: boolean;\n\n /**\n * Output the entire object tree, not just differences\n * @default false\n */\n full?: boolean;\n\n /**\n * Always include these keys in output for objects with differences\n * @default []\n */\n outputKeys?: string[];\n\n /**\n * Skip these keys when comparing objects\n * @default []\n */\n ignoreKeys?: string[];\n\n /**\n * Ignore value differences, focus only on structure\n * @default false\n */\n ignoreValues?: boolean;\n}\n\n/**\n * Enum for diff change types\n */\nexport enum DiffType {\n ADDED = 'added',\n REMOVED = 'removed',\n CHANGED = 'changed',\n UNCHANGED = 'unchanged',\n}\n\n/**\n * Represents a change between two values\n */\nexport interface DiffResult {\n type: DiffType;\n path?: string[];\n oldValue?: any;\n newValue?: any;\n children?: DiffResult[];\n /**\n * Additional metadata about the diff, such as Levenshtein distance metrics\n */\n meta?: {\n /** Levenshtein distance between strings */\n levenDistance?: number;\n /** Similarity ratio (0-1) where 1 means identical */\n similarity?: number;\n /** Any other metadata properties */\n [key: string]: any;\n };\n}\n\n/**\n * Type for handling any serializable value\n */\nexport type SerializableValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | { [key: string]: SerializableValue }\n | SerializableValue[];\n","import { DiffOptions, DiffResult, DiffType } from './types';\n\n// ANSI color codes\nconst colors = {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n gray: '\\x1b[90m',\n};\n\n/**\n * Format a diff result as a string with optional colors and formatting\n * @param diff - The diff result to format\n * @param options - Formatting options\n * @returns A formatted string representation of the diff\n */\nexport function formatDiff(\n diff: DiffResult,\n options: DiffOptions = {},\n): string {\n const { color = true, full = false } = options;\n\n // For unchanged values with no children, we may skip them unless full output is requested\n if (\n diff.type === DiffType.UNCHANGED &&\n !full &&\n (!diff.children || diff.children.length === 0)\n ) {\n return '';\n }\n\n // Handle primitive values\n if (!diff.children || diff.children.length === 0) {\n return formatValue(diff, color);\n }\n\n // Handle objects and arrays\n return formatComplex(diff, options, 0);\n}\n\n/**\n * Format a primitive value diff (added, removed, changed)\n */\nfunction formatValue(diff: DiffResult, useColor: boolean): string {\n const prefix = getPrefix(diff.type);\n let value = '';\n\n switch (diff.type) {\n case DiffType.ADDED:\n value = formatPrimitive(diff.newValue);\n return useColor\n ? `${colors.green}${prefix} ${value}${colors.reset}`\n : `${prefix} ${value}`;\n\n case DiffType.REMOVED:\n value = formatPrimitive(diff.oldValue);\n return useColor\n ? `${colors.red}${prefix} ${value}${colors.reset}`\n : `${prefix} ${value}`;\n\n case DiffType.CHANGED:\n const oldVal = formatPrimitive(diff.oldValue);\n const newVal = formatPrimitive(diff.newValue);\n\n // Add similarity information for strings if available\n let similarityInfo = '';\n if (\n diff.meta?.similarity !== undefined &&\n typeof diff.oldValue === 'string' &&\n typeof diff.newValue === 'string'\n ) {\n const similarity = Math.round(diff.meta.similarity * 100);\n similarityInfo = useColor\n ? `${colors.gray} (${similarity}% similar)${colors.reset}`\n : ` (${similarity}% similar)`;\n }\n\n // Git-style diff format: -old value followed by +new value\n const oldLine = useColor\n ? `${colors.red}- ${oldVal}${colors.reset}`\n : `- ${oldVal}`;\n\n const newLine = useColor\n ? `${colors.green}+ ${newVal}${similarityInfo}${colors.reset}`\n : `+ ${newVal}${similarityInfo}`;\n\n return `${oldLine}\\n${newLine}`;\n\n default:\n value = formatPrimitive(diff.newValue ?? diff.oldValue);\n return useColor\n ? `${colors.gray}${prefix} ${value}${colors.reset}`\n : `${prefix} ${value}`;\n }\n}\n\n/**\n * Format complex objects and arrays\n * For objects, use Git-like diff format with JSON-style indentation\n */\nfunction formatComplex(\n diff: DiffResult,\n options: DiffOptions,\n indent: number = 0,\n): string {\n const { full = false } = options;\n\n // Early return for unchanged primitives\n if (\n diff.type === DiffType.UNCHANGED &&\n !full &&\n (!diff.children ||\n diff.children.length === 0 ||\n (typeof diff.oldValue !== 'object' && typeof diff.newValue !== 'object'))\n ) {\n return '';\n }\n\n return Array.isArray(diff.oldValue) || Array.isArray(diff.newValue)\n ? formatArrayDiff(diff, options, indent)\n : formatObjectDiff(diff, options, indent);\n}\n\n/**\n * Format array diffs with proper indentation and Git-style markers\n */\nfunction formatArrayDiff(\n diff: DiffResult,\n options: DiffOptions,\n indent: number = 0,\n): string {\n const { color = true, full = false } = options;\n const baseIndent = ' '.repeat(indent);\n const innerIndent = ' '.repeat(indent + 2);\n let result = `[\\n`;\n let visibleItems = 0;\n\n if (diff.children) {\n for (let i = 0; i < diff.children.length; i++) {\n const child = diff.children[i];\n\n // Skip unchanged items unless full output is requested\n if (\n child.type === DiffType.UNCHANGED &&\n !full &&\n (!child.children || child.children.length === 0)\n ) {\n continue;\n }\n\n if (child.children && child.children.length > 0) {\n // Handle nested objects/arrays within the array\n const nestedOutput = Array.isArray(child.newValue || child.oldValue)\n ? formatArrayDiff(child, options, indent + 2)\n : formatObjectDiff(child, options, indent + 2);\n\n // Only add if there's actual content\n if (nestedOutput.trim().length > 2) {\n // More than just '[]' or '{}'\n if (visibleItems > 0) {\n result += ',\\n';\n }\n result += innerIndent;\n result += nestedOutput;\n visibleItems++;\n }\n } else {\n // Handle primitive values\n if (visibleItems > 0) {\n result += ',\\n';\n }\n\n switch (child.type) {\n case DiffType.ADDED:\n result += color\n ? `${innerIndent}${colors.green}+ ${formatPrimitive(child.newValue)}${colors.reset}`\n : `${innerIndent}+ ${formatPrimitive(child.newValue)}`;\n visibleItems++;\n break;\n case DiffType.REMOVED:\n result += color\n ? `${innerIndent}${colors.red}- ${formatPrimitive(child.oldValue)}${colors.reset}`\n : `${innerIndent}- ${formatPrimitive(child.oldValue)}`;\n visibleItems++;\n break;\n case DiffType.UNCHANGED:\n // Special handling for ignored values (when using ignoreValues: true)\n if (child.meta?.ignored && child.path) {\n result += color\n ? `${innerIndent}${colors.gray} ${child.path[child.path.length - 1] || ''}${colors.reset}`\n : `${innerIndent} ${child.path[child.path.length - 1] || ''}`;\n } else {\n result += color\n ? `${innerIndent}${colors.gray} ${formatPrimitive(child.newValue)}${colors.reset}`\n : `${innerIndent} ${formatPrimitive(child.newValue)}`;\n }\n visibleItems++;\n break;\n case DiffType.CHANGED:\n result += color\n ? `${innerIndent}${colors.red}- ${formatPrimitive(child.oldValue)}${colors.reset}\\n` +\n `${innerIndent}${colors.green}+ ${formatPrimitive(child.newValue)}${colors.reset}`\n : `${innerIndent}- ${formatPrimitive(child.oldValue)}\\n` +\n `${innerIndent}+ ${formatPrimitive(child.newValue)}`;\n visibleItems++;\n break;\n }\n }\n }\n }\n\n if (visibleItems > 0) {\n result += '\\n';\n }\n result += `${baseIndent}]`;\n return result;\n}\n\n/**\n * Format object diffs with proper indentation and Git-style markers\n */\nfunction formatObjectDiff(\n diff: DiffResult,\n options: DiffOptions,\n indent: number = 0,\n): string {\n const { color = true, full = false } = options;\n const baseIndent = ' '.repeat(indent);\n const innerIndent = ' '.repeat(indent + 2);\n let result = `{\\n`;\n let visibleItems = 0;\n\n if (diff.children) {\n // First, filter out children that won't be displayed\n const displayableChildren = diff.children.filter((child) => {\n if (child.type !== DiffType.UNCHANGED) return true;\n if (full) return true;\n if (child.children && child.children.length > 0) return true;\n const key = child.path?.[child.path.length - 1] || '';\n if (options.outputKeys?.includes(key)) return true;\n return false;\n });\n\n for (let i = 0; i < displayableChildren.length; i++) {\n const child = displayableChildren[i];\n const key = child.path?.[child.path.length - 1] || '';\n const isLast = i === displayableChildren.length - 1;\n\n // If we already added an item, and we're not at a new line, add a comma and new line\n if (visibleItems > 0 && !result.endsWith('\\n')) {\n result += ',\\n';\n }\n\n if (child.children && child.children.length > 0) {\n // Handle nested objects/arrays\n const nestedContent = Array.isArray(child.newValue || child.oldValue)\n ? formatArrayDiff(child, options, indent + 2)\n : formatObjectDiff(child, options, indent + 2);\n\n // Only add if there's actual content in the nested structure\n if (nestedContent.trim().length > 2) {\n // More than just '{}' or '[]'\n result += `${innerIndent}${key}: ${nestedContent}`;\n visibleItems++;\n }\n } else {\n // Handle primitive values\n switch (child.type) {\n case DiffType.ADDED:\n result += color\n ? `${innerIndent}${colors.green}+ ${key}: ${formatPrimitive(child.newValue)}${colors.reset}`\n : `${innerIndent}+ ${key}: ${formatPrimitive(child.newValue)}`;\n visibleItems++;\n break;\n case DiffType.REMOVED:\n result += color\n ? `${innerIndent}${colors.red}- ${key}: ${formatPrimitive(child.oldValue)}${colors.reset}`\n : `${innerIndent}- ${key}: ${formatPrimitive(child.oldValue)}`;\n visibleItems++;\n break;\n case DiffType.CHANGED:\n result += color\n ? `${innerIndent}${colors.red}- ${key}: ${formatPrimitive(child.oldValue)}${colors.reset}\\n` +\n `${innerIndent}${colors.green}+ ${key}: ${formatPrimitive(child.newValue)}${colors.reset}`\n : `${innerIndent}- ${key}: ${formatPrimitive(child.oldValue)}\\n` +\n `${innerIndent}+ ${key}: ${formatPrimitive(child.newValue)}`;\n visibleItems++;\n break;\n case DiffType.UNCHANGED:\n if (full || options.outputKeys?.includes(key)) {\n // Special handling for ignored values (when using ignoreValues: true)\n if (child.meta?.ignored) {\n result += color\n ? `${innerIndent}${colors.gray} ${key}${colors.reset}`\n : `${innerIndent} ${key}`;\n } else {\n result += color\n ? `${innerIndent}${colors.gray} ${key}: ${formatPrimitive(child.newValue)}${colors.reset}`\n : `${innerIndent} ${key}: ${formatPrimitive(child.newValue)}`;\n }\n visibleItems++;\n }\n break;\n }\n }\n\n // Add comma if not the last item and not already ending with newline\n if (!isLast && !result.endsWith('\\n')) {\n result += ',';\n }\n\n // Always ensure we end with a newline before the next item\n if (!result.endsWith('\\n')) {\n result += '\\n';\n }\n }\n }\n\n // Only add final newline if we have content\n if (visibleItems > 0 && !result.endsWith('\\n')) {\n result += '\\n';\n }\n\n result += `${baseIndent}}`;\n return result;\n}\n\n/**\n * Get the prefix for a diff type\n */\nfunction getPrefix(type: DiffType | string): string {\n switch (type) {\n case DiffType.ADDED:\n return '+';\n case DiffType.REMOVED:\n return '-';\n case DiffType.CHANGED:\n return '!';\n default:\n return ' ';\n }\n}\n\n/**\n * Format a primitive value for output\n */\nfunction formatPrimitive(value: any): string {\n if (value === undefined) {\n return 'undefined';\n }\n\n if (value === null) {\n return 'null';\n }\n\n if (typeof value === 'string') {\n // Use JavaScript object notation with single quotes\n return `'${value}'`;\n }\n\n if (typeof value === 'number' || typeof value === 'boolean') {\n return value.toString();\n }\n\n // For objects and arrays, use properly formatted JavaScript object notation\n if (typeof value === 'object') {\n const json = JSON.stringify(value, null, 2);\n return json;\n }\n\n return String(value);\n}\n","import { createDiff } from './diff';\nimport { formatDiff } from './formatter';\nimport { DiffOptions, DiffResult, DiffType, SerializableValue } from './types';\n\n/**\n * Compare two values and generate a detailed diff result object\n *\n * @param oldValue - Original value to compare from\n * @param newValue - New value to compare against\n * @param options - Configuration options for the diff\n * @returns A structured diff result object\n */\nexport function diffRaw(\n oldValue: SerializableValue,\n newValue: SerializableValue,\n options: DiffOptions = {},\n): DiffResult {\n return createDiff(oldValue, newValue, options);\n}\n\n/**\n * Compare two values and generate a formatted diff string\n *\n * @param oldValue - Original value to compare from\n * @param newValue - New value to compare against\n * @param options - Configuration options for the diff\n * @returns A formatted string representation of the diff\n */\nexport function diff(\n oldValue: SerializableValue,\n newValue: SerializableValue,\n options: DiffOptions = {},\n): string {\n const diffResult = diffRaw(oldValue, newValue, options);\n return formatDiff(diffResult, options);\n}\n\n// Export types\nexport type { DiffOptions, DiffResult, SerializableValue };\nexport { DiffType };\n"],"mappings":";AAAA,OAAO,WAAW;;;AC4CX,IAAK,WAAL,kBAAKA,cAAL;AACL,EAAAA,UAAA,WAAQ;AACR,EAAAA,UAAA,aAAU;AACV,EAAAA,UAAA,aAAU;AACV,EAAAA,UAAA,eAAY;AAJF,SAAAA;AAAA,GAAA;;;AD/BL,SAAS,WACd,UACA,UACA,UAAuB,CAAC,GACxB,OAAiB,CAAC,GACN;AACZ,QAAM,EAAE,WAAW,OAAO,eAAe,MAAM,IAAI;AAGnD,MAAI,aAAa,UAAa,aAAa,QAAW;AACpD,WAAO,EAAE,kCAAyB;AAAA,EACpC;AACA,MAAI,aAAa,QAAW;AAC1B,WAAO,EAAE,2BAAsB,MAAM,SAAS;AAAA,EAChD;AACA,MAAI,aAAa,QAAW;AAC1B,WAAO,EAAE,+BAAwB,MAAM,SAAS;AAAA,EAClD;AAGA,MACE,OAAO,aAAa,YACpB,OAAO,aAAa,YACpB,aAAa,QACb,aAAa,MACb;AACA,QAAI,YAAY,cAAc;AAE5B,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM,EAAE,SAAS,KAAK;AAAA,MACxB;AAAA,IACF;AACA,QAAI,aAAa,UAAU;AACzB,aAAO,EAAE,mCAA0B,MAAM,UAAU,SAAS;AAAA,IAC9D;AAGA,QAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UAAU;AAChE,YAAM,WAAW,MAAM,UAAU,QAAQ;AACzC,YAAM,YAAY,KAAK,IAAI,SAAS,QAAQ,SAAS,MAAM;AAC3D,YAAM,kBAAkB,YAAY,IAAI,IAAI,WAAW,YAAY;AAEnE,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,YAAY;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,+BAAwB,MAAM,UAAU,SAAS;AAAA,EAC5D;AAGA,MAAI,MAAM,QAAQ,QAAQ,KAAK,MAAM,QAAQ,QAAQ,GAAG;AACtD,WAAO,cAAc,UAAU,UAAU,SAAS,IAAI;AAAA,EACxD;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKA,SAAS,eACP,QACA,QACA,SACA,MACY;AACZ,QAAM,EAAE,aAAa,CAAC,EAAE,IAAI;AAE5B,QAAM,UAAU,oBAAI,IAAI;AAAA,IACtB,GAAG,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,WAAW,SAAS,GAAG,CAAC;AAAA,IAChE,GAAG,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,WAAW,SAAS,GAAG,CAAC;AAAA,EAClE,CAAC;AAED,QAAM,WAAyB,CAAC;AAChC,MAAI,aAAa;AAEjB,aAAW,OAAO,SAAS;AACzB,UAAM,YAAY,CAAC,GAAG,MAAM,GAAG;AAC/B,UAAM,WAAW,OAAO,GAAG;AAC3B,UAAM,WAAW,OAAO,GAAG;AAE3B,UAAM,YAAY,WAAW,UAAU,UAAU,SAAS,SAAS;AAEnE,QAAI,UAAU,sCAA6B;AACzC,mBAAa;AAAA,IACf;AAEA,aAAS,KAAK,SAAS;AAAA,EACzB;AAEA,MAAI,YAAY;AACd,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,mCAA0B,MAAM,UAAU,QAAQ,UAAU,OAAO;AAC9E;AAMA,SAAS,cACP,UACA,UACA,SACA,MACY;AAEZ,MAAI,SAAS,WAAW,SAAS,QAAQ;AACvC,UAAMC,YAAyB,CAAC;AAChC,UAAM,YAAY,KAAK,IAAI,SAAS,QAAQ,SAAS,MAAM;AAE3D,aAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAClC,YAAM,YAAY,CAAC,GAAG,MAAM,EAAE,SAAS,CAAC;AACxC,UAAI,KAAK,SAAS,QAAQ;AACxB,QAAAA,UAAS,KAAK;AAAA,UACZ;AAAA,UACA,MAAM;AAAA,UACN,UAAU,SAAS,CAAC;AAAA,QACtB,CAAC;AAAA,MACH,WAAW,KAAK,SAAS,QAAQ;AAC/B,QAAAA,UAAS,KAAK;AAAA,UACZ;AAAA,UACA,MAAM;AAAA,UACN,UAAU,SAAS,CAAC;AAAA,QACtB,CAAC;AAAA,MACH,OAAO;AACL,QAAAA,UAAS,KAAK,WAAW,SAAS,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,SAAS,CAAC;AAAA,MACxE;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAAA;AAAA,IACF;AAAA,EACF;AAGA,QAAM,WAAyB,CAAC;AAChC,MAAI,aAAa;AAEjB,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,YAAY,CAAC,GAAG,MAAM,EAAE,SAAS,CAAC;AACxC,UAAM,WAAW,SAAS,CAAC;AAC3B,UAAM,WAAW,SAAS,CAAC;AAC3B,QAAI;AAGJ,QAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UAAU;AAChE,UAAI,aAAa,UAAU;AACzB,oBAAY;AAAA,UACV;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA;AAAA,QACF;AAAA,MACF,OAAO;AACL,cAAM,WAAW,MAAM,UAAU,QAAQ;AACzC,cAAM,YAAY,KAAK,IAAI,SAAS,QAAQ,SAAS,MAAM;AAC3D,cAAM,kBAAkB,YAAY,IAAI,IAAI,WAAW,YAAY;AAEnE,oBAAY;AAAA,UACV;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA,MAAM;AAAA,YACJ,eAAe;AAAA,YACf,YAAY;AAAA,UACd;AAAA,QACF;AACA,qBAAa;AAAA,MACf;AAAA,IACF,OAAO;AAEL,kBAAY,WAAW,UAAU,UAAU,SAAS,SAAS;AAC7D,UAAI,UAAU,sCAA6B;AACzC,qBAAa;AAAA,MACf;AAAA,IACF;AAEA,aAAS,KAAK,SAAS;AAAA,EACzB;AAEA,MAAI,YAAY;AACd,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AACF;;;AE7OA,IAAM,SAAS;AAAA,EACb,OAAO;AAAA,EACP,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM;AACR;AAQO,SAAS,WACdC,OACA,UAAuB,CAAC,GAChB;AACR,QAAM,EAAE,QAAQ,MAAM,OAAO,MAAM,IAAI;AAGvC,MACEA,MAAK,wCACL,CAAC,SACA,CAACA,MAAK,YAAYA,MAAK,SAAS,WAAW,IAC5C;AACA,WAAO;AAAA,EACT;AAGA,MAAI,CAACA,MAAK,YAAYA,MAAK,SAAS,WAAW,GAAG;AAChD,WAAO,YAAYA,OAAM,KAAK;AAAA,EAChC;AAGA,SAAO,cAAcA,OAAM,SAAS,CAAC;AACvC;AAKA,SAAS,YAAYA,OAAkB,UAA2B;AAChE,QAAM,SAAS,UAAUA,MAAK,IAAI;AAClC,MAAI,QAAQ;AAEZ,UAAQA,MAAK,MAAM;AAAA,IACjB;AACE,cAAQ,gBAAgBA,MAAK,QAAQ;AACrC,aAAO,WACH,GAAG,OAAO,KAAK,GAAG,MAAM,IAAI,KAAK,GAAG,OAAO,KAAK,KAChD,GAAG,MAAM,IAAI,KAAK;AAAA,IAExB;AACE,cAAQ,gBAAgBA,MAAK,QAAQ;AACrC,aAAO,WACH,GAAG,OAAO,GAAG,GAAG,MAAM,IAAI,KAAK,GAAG,OAAO,KAAK,KAC9C,GAAG,MAAM,IAAI,KAAK;AAAA,IAExB;AACE,YAAM,SAAS,gBAAgBA,MAAK,QAAQ;AAC5C,YAAM,SAAS,gBAAgBA,MAAK,QAAQ;AAG5C,UAAI,iBAAiB;AACrB,UACEA,MAAK,MAAM,eAAe,UAC1B,OAAOA,MAAK,aAAa,YACzB,OAAOA,MAAK,aAAa,UACzB;AACA,cAAM,aAAa,KAAK,MAAMA,MAAK,KAAK,aAAa,GAAG;AACxD,yBAAiB,WACb,GAAG,OAAO,IAAI,KAAK,UAAU,aAAa,OAAO,KAAK,KACtD,KAAK,UAAU;AAAA,MACrB;AAGA,YAAM,UAAU,WACZ,GAAG,OAAO,GAAG,KAAK,MAAM,GAAG,OAAO,KAAK,KACvC,KAAK,MAAM;AAEf,YAAM,UAAU,WACZ,GAAG,OAAO,KAAK,KAAK,MAAM,GAAG,cAAc,GAAG,OAAO,KAAK,KAC1D,KAAK,MAAM,GAAG,cAAc;AAEhC,aAAO,GAAG,OAAO;AAAA,EAAK,OAAO;AAAA,IAE/B;AACE,cAAQ,gBAAgBA,MAAK,YAAYA,MAAK,QAAQ;AACtD,aAAO,WACH,GAAG,OAAO,IAAI,GAAG,MAAM,IAAI,KAAK,GAAG,OAAO,KAAK,KAC/C,GAAG,MAAM,IAAI,KAAK;AAAA,EAC1B;AACF;AAMA,SAAS,cACPA,OACA,SACA,SAAiB,GACT;AACR,QAAM,EAAE,OAAO,MAAM,IAAI;AAGzB,MACEA,MAAK,wCACL,CAAC,SACA,CAACA,MAAK,YACLA,MAAK,SAAS,WAAW,KACxB,OAAOA,MAAK,aAAa,YAAY,OAAOA,MAAK,aAAa,WACjE;AACA,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,QAAQA,MAAK,QAAQ,KAAK,MAAM,QAAQA,MAAK,QAAQ,IAC9D,gBAAgBA,OAAM,SAAS,MAAM,IACrC,iBAAiBA,OAAM,SAAS,MAAM;AAC5C;AAKA,SAAS,gBACPA,OACA,SACA,SAAiB,GACT;AACR,QAAM,EAAE,QAAQ,MAAM,OAAO,MAAM,IAAI;AACvC,QAAM,aAAa,IAAI,OAAO,MAAM;AACpC,QAAM,cAAc,IAAI,OAAO,SAAS,CAAC;AACzC,MAAI,SAAS;AAAA;AACb,MAAI,eAAe;AAEnB,MAAIA,MAAK,UAAU;AACjB,aAAS,IAAI,GAAG,IAAIA,MAAK,SAAS,QAAQ,KAAK;AAC7C,YAAM,QAAQA,MAAK,SAAS,CAAC;AAG7B,UACE,MAAM,wCACN,CAAC,SACA,CAAC,MAAM,YAAY,MAAM,SAAS,WAAW,IAC9C;AACA;AAAA,MACF;AAEA,UAAI,MAAM,YAAY,MAAM,SAAS,SAAS,GAAG;AAE/C,cAAM,eAAe,MAAM,QAAQ,MAAM,YAAY,MAAM,QAAQ,IAC/D,gBAAgB,OAAO,SAAS,SAAS,CAAC,IAC1C,iBAAiB,OAAO,SAAS,SAAS,CAAC;AAG/C,YAAI,aAAa,KAAK,EAAE,SAAS,GAAG;AAElC,cAAI,eAAe,GAAG;AACpB,sBAAU;AAAA,UACZ;AACA,oBAAU;AACV,oBAAU;AACV;AAAA,QACF;AAAA,MACF,OAAO;AAEL,YAAI,eAAe,GAAG;AACpB,oBAAU;AAAA,QACZ;AAEA,gBAAQ,MAAM,MAAM;AAAA,UAClB;AACE,sBAAU,QACN,GAAG,WAAW,GAAG,OAAO,KAAK,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KAChF,GAAG,WAAW,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AACtD;AACA;AAAA,UACF;AACE,sBAAU,QACN,GAAG,WAAW,GAAG,OAAO,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KAC9E,GAAG,WAAW,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AACtD;AACA;AAAA,UACF;AAEE,gBAAI,MAAM,MAAM,WAAW,MAAM,MAAM;AACrC,wBAAU,QACN,GAAG,WAAW,GAAG,OAAO,IAAI,KAAK,MAAM,KAAK,MAAM,KAAK,SAAS,CAAC,KAAK,EAAE,GAAG,OAAO,KAAK,KACvF,GAAG,WAAW,KAAK,MAAM,KAAK,MAAM,KAAK,SAAS,CAAC,KAAK,EAAE;AAAA,YAChE,OAAO;AACL,wBAAU,QACN,GAAG,WAAW,GAAG,OAAO,IAAI,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KAC/E,GAAG,WAAW,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAAA,YACxD;AACA;AACA;AAAA,UACF;AACE,sBAAU,QACN,GAAG,WAAW,GAAG,OAAO,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK;AAAA,EAC3E,WAAW,GAAG,OAAO,KAAK,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KAChF,GAAG,WAAW,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAAA,EAC/C,WAAW,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AACtD;AACA;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,eAAe,GAAG;AACpB,cAAU;AAAA,EACZ;AACA,YAAU,GAAG,UAAU;AACvB,SAAO;AACT;AAKA,SAAS,iBACPA,OACA,SACA,SAAiB,GACT;AACR,QAAM,EAAE,QAAQ,MAAM,OAAO,MAAM,IAAI;AACvC,QAAM,aAAa,IAAI,OAAO,MAAM;AACpC,QAAM,cAAc,IAAI,OAAO,SAAS,CAAC;AACzC,MAAI,SAAS;AAAA;AACb,MAAI,eAAe;AAEnB,MAAIA,MAAK,UAAU;AAEjB,UAAM,sBAAsBA,MAAK,SAAS,OAAO,CAAC,UAAU;AAC1D,UAAI,MAAM,qCAA6B,QAAO;AAC9C,UAAI,KAAM,QAAO;AACjB,UAAI,MAAM,YAAY,MAAM,SAAS,SAAS,EAAG,QAAO;AACxD,YAAM,MAAM,MAAM,OAAO,MAAM,KAAK,SAAS,CAAC,KAAK;AACnD,UAAI,QAAQ,YAAY,SAAS,GAAG,EAAG,QAAO;AAC9C,aAAO;AAAA,IACT,CAAC;AAED,aAAS,IAAI,GAAG,IAAI,oBAAoB,QAAQ,KAAK;AACnD,YAAM,QAAQ,oBAAoB,CAAC;AACnC,YAAM,MAAM,MAAM,OAAO,MAAM,KAAK,SAAS,CAAC,KAAK;AACnD,YAAM,SAAS,MAAM,oBAAoB,SAAS;AAGlD,UAAI,eAAe,KAAK,CAAC,OAAO,SAAS,IAAI,GAAG;AAC9C,kBAAU;AAAA,MACZ;AAEA,UAAI,MAAM,YAAY,MAAM,SAAS,SAAS,GAAG;AAE/C,cAAM,gBAAgB,MAAM,QAAQ,MAAM,YAAY,MAAM,QAAQ,IAChE,gBAAgB,OAAO,SAAS,SAAS,CAAC,IAC1C,iBAAiB,OAAO,SAAS,SAAS,CAAC;AAG/C,YAAI,cAAc,KAAK,EAAE,SAAS,GAAG;AAEnC,oBAAU,GAAG,WAAW,GAAG,GAAG,KAAK,aAAa;AAChD;AAAA,QACF;AAAA,MACF,OAAO;AAEL,gBAAQ,MAAM,MAAM;AAAA,UAClB;AACE,sBAAU,QACN,GAAG,WAAW,GAAG,OAAO,KAAK,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KACxF,GAAG,WAAW,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAC9D;AACA;AAAA,UACF;AACE,sBAAU,QACN,GAAG,WAAW,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KACtF,GAAG,WAAW,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAC9D;AACA;AAAA,UACF;AACE,sBAAU,QACN,GAAG,WAAW,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK;AAAA,EACnF,WAAW,GAAG,OAAO,KAAK,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KACxF,GAAG,WAAW,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAAA,EACvD,WAAW,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAC9D;AACA;AAAA,UACF;AACE,gBAAI,QAAQ,QAAQ,YAAY,SAAS,GAAG,GAAG;AAE7C,kBAAI,MAAM,MAAM,SAAS;AACvB,0BAAU,QACN,GAAG,WAAW,GAAG,OAAO,IAAI,KAAK,GAAG,GAAG,OAAO,KAAK,KACnD,GAAG,WAAW,KAAK,GAAG;AAAA,cAC5B,OAAO;AACL,0BAAU,QACN,GAAG,WAAW,GAAG,OAAO,IAAI,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,KACvF,GAAG,WAAW,KAAK,GAAG,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AAAA,cAChE;AACA;AAAA,YACF;AACA;AAAA,QACJ;AAAA,MACF;AAGA,UAAI,CAAC,UAAU,CAAC,OAAO,SAAS,IAAI,GAAG;AACrC,kBAAU;AAAA,MACZ;AAGA,UAAI,CAAC,OAAO,SAAS,IAAI,GAAG;AAC1B,kBAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAGA,MAAI,eAAe,KAAK,CAAC,OAAO,SAAS,IAAI,GAAG;AAC9C,cAAU;AAAA,EACZ;AAEA,YAAU,GAAG,UAAU;AACvB,SAAO;AACT;AAKA,SAAS,UAAU,MAAiC;AAClD,UAAQ,MAAM;AAAA,IACZ;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAKA,SAAS,gBAAgB,OAAoB;AAC3C,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,UAAU,UAAU;AAE7B,WAAO,IAAI,KAAK;AAAA,EAClB;AAEA,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,WAAW;AAC3D,WAAO,MAAM,SAAS;AAAA,EACxB;AAGA,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,OAAO,KAAK,UAAU,OAAO,MAAM,CAAC;AAC1C,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,KAAK;AACrB;;;ACvWO,SAAS,QACd,UACA,UACA,UAAuB,CAAC,GACZ;AACZ,SAAO,WAAW,UAAU,UAAU,OAAO;AAC/C;AAUO,SAAS,KACd,UACA,UACA,UAAuB,CAAC,GAChB;AACR,QAAM,aAAa,QAAQ,UAAU,UAAU,OAAO;AACtD,SAAO,WAAW,YAAY,OAAO;AACvC;","names":["DiffType","children","diff"]}