Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

json-diff-kit

Package Overview
Dependencies
Maintainers
1
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

json-diff-kit - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1

.github/workflows/pages.yml

558

dist/index.js

@@ -1,3 +0,555 @@

(()=>{var I=Object.create;var b=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var W=Object.getPrototypeOf,J=Object.prototype.hasOwnProperty;var P=e=>b(e,"__esModule",{value:!0});var E=(e=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(e,{get:(t,i)=>(typeof require!="undefined"?require:t)[i]}):e)(function(e){if(typeof require!="undefined")return require.apply(this,arguments);throw new Error('Dynamic require of "'+e+'" is not supported')});var z=(e,t,i,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of T(t))!J.call(e,n)&&(i||n!=="default")&&b(e,n,{get:()=>t[n],enumerable:!(r=R(t,n))||r.enumerable});return e},_=(e,t)=>z(P(b(e!=null?I(W(e)):{},"default",!t&&e&&e.__esModule?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e);var $=(e,t=new Map)=>{if(typeof e!="object"||e===null)return!1;if(t.has(e))return!0;if(t.set(e,!0),Array.isArray(e)){for(let i=0;i<e.length;i++)if($(e[i],t))return!0;return!1}for(let i in e)if($(e[i],t))return!0;return!1},j=$;var g=(e,t,i,r=1/0)=>{if(!e||typeof e!="object")return JSON.stringify(e,t,i);let n=r<1?'"..."':Array.isArray(e)?`[${e.map(u=>g(u,t,i,r-1)).join(",")}]`:`{${Object.keys(e).map(u=>`"${u}": ${g(e[u],t,i,r-1)}`).join(", ")}}`;return JSON.stringify(JSON.parse(n),t,i)},c=g;var B=(e,t=1/0)=>Array.isArray(e)||typeof e=="object"?c(e,null,null,t):typeof e=="string"?`"${e}"`:String(e),y=B;var G=e=>Array.isArray(e)?"array":e===null?"null":typeof e,h=G;var C=(e,t,i=1,r,n)=>{if(i>r.maxDepth)return[[{level:i,type:"equal",text:"..."}],[{level:i,type:"equal",text:"..."}]];let u=[],s=[];if(e===null&&t===null||e===void 0&&t===void 0)return[u,s];if(e==null)return u.push({level:i,type:"equal",text:""}),s.push({level:i,type:"add",text:y(t)}),[u,s];if(t==null)return u.push({level:i,type:"remove",text:y(e)}),s.push({level:i,type:"equal",text:""}),[u,s];let o=Object.keys(e),a=Object.keys(t);for(o.sort(),a.sort();o.length||a.length;){let f=o[0]??null,p=a[0]??null;if(f===p)if(h(e[f])!==h(t[p]))r.showModifications?(u.push({level:i,type:"modify",text:`"${f}": ${y(e[f])}`}),s.push({level:i,type:"modify",text:`"${p}": ${y(t[p])}`})):(u.push({level:i,type:"remove",text:`"${f}": ${y(e[f])}`}),u.push({level:i,type:"equal",text:""}),s.push({level:i,type:"equal",text:""}),s.push({level:i,type:"add",text:`"${p}": ${y(t[p])}`}));else if(Array.isArray(e[f])){let x=[...e[f]],l=[...t[p]],[m,q]=n(x,l,f,p,i,r,[],[]);u.push(...m),s.push(...q)}else if(typeof e[f]=="object"){let x=C(e[f],t[p],i+1,r,n);u.push({level:i,type:"equal",text:`"${f}": {`}),u.push(...x[0]),u.push({level:i,type:"equal",text:"}"}),s.push({level:i,type:"equal",text:`"${p}": {`}),s.push(...x[1]),s.push({level:i,type:"equal",text:"}"})}else e[f]!==t[p]?r.showModifications?(u.push({level:i,type:"modify",text:`"${f}": ${y(e[f])}`}),s.push({level:i,type:"modify",text:`"${p}": ${y(t[p])}`})):(u.push({level:i,type:"remove",text:`"${f}": ${y(e[f])}`}),u.push({level:i,type:"equal",text:""}),s.push({level:i,type:"equal",text:""}),s.push({level:i,type:"add",text:`"${p}": ${y(t[p])}`})):(u.push({level:i,type:"equal",text:`"${f}": ${y(e[f])}`}),s.push({level:i,type:"equal",text:`"${p}": ${y(t[p])}`}));else f&&p?f<p?(u.push({level:i,type:"remove",text:`"${f}": ${y(e[f])}`}),s.push({level:i,type:"equal",text:""})):(u.push({level:i,type:"equal",text:""}),s.push({level:i,type:"add",text:`"${p}": ${y(t[p])}`})):f?(u.push({level:i,type:"remove",text:`"${f}": ${y(e[f])}`}),s.push({level:i,type:"equal",text:""})):p&&(u.push({level:i,type:"equal",text:""}),s.push({level:i,type:"add",text:`"${p}": ${y(t[p])}`}));f?p?f===p?(o.shift(),a.shift()):f<p?o.shift():a.shift():o.shift():a.shift()}if(u.length!==s.length)throw new Error("Diff error: length not match for left & right, please report a bug with your data.");return[u,s]},D=C;var H=(e,t,i,r,n,u)=>{let s=Array(e.length+1).fill(0).map(()=>Array(t.length+1).fill(0)),o=Array(e.length+1).fill(0).map(()=>Array(t.length+1).fill(0));for(let l=1;l<=e.length;l++)o[l][0]="up";for(let l=1;l<=t.length;l++)o[0][l]="left";for(let l=1;l<=e.length;l++)for(let m=1;m<=t.length;m++){let q=h(e[l-1]),V=h(t[m-1]);q===V&&(q==="array"||q==="object")||e[l-1]===t[m-1]?(s[l][m]=s[l-1][m-1]+1,o[l][m]="diag"):s[l-1][m]>=s[l][m-1]?(s[l][m]=s[l-1][m],o[l][m]="up"):(s[l][m]=s[l][m-1],o[l][m]="left")}let a=e.length,f=t.length,p=[],x=[];for(;a>0||f>0;)if(o[a][f]==="diag"){let l=h(e[a-1]);if(l==="array"){let[m,q]=A(e[a-1],t[f-1],i,r,n+2,u);p.unshift(...m),x.unshift(...q)}else if(l==="object"){let[m,q]=D(e[a-1],t[f-1],n+2,u,A);p.unshift({level:n+1,type:"equal",text:"}"}),x.unshift({level:n+1,type:"equal",text:"}"}),p.unshift(...m),x.unshift(...q),p.unshift({level:n+1,type:"equal",text:"{"}),x.unshift({level:n+1,type:"equal",text:"{"})}else p.unshift({level:n+1,type:"equal",text:y(e[a-1])}),x.unshift({level:n+1,type:"equal",text:y(t[f-1])});a--,f--}else o[a][f]==="up"?u.showModifications&&a>1&&o[a-1][f]==="left"?(p.unshift({level:n+1,type:"modify",text:y(e[a-1])}),x.unshift({level:n+1,type:"modify",text:y(t[f-1])}),a--,f--):(p.unshift({level:n+1,type:"remove",text:y(e[a-1])}),x.unshift({level:n+1,type:"equal",text:""}),a--):(p.unshift({level:n+1,type:"equal",text:""}),x.unshift({level:n+1,type:"add",text:y(t[f-1])}),f--);return[p,x]},A=(e,t,i,r,n,u,s=[],o=[])=>{if(i&&r?(s.push({level:n,type:"equal",text:`"${i}": [`}),o.push({level:n,type:"equal",text:`"${r}": [`})):(s.push({level:n,type:"equal",text:"["}),o.push({level:n,type:"equal",text:"["})),n>=u.maxDepth)s.push({level:n+1,type:"equal",text:"..."}),o.push({level:n+1,type:"equal",text:"..."});else{let[a,f]=H(e,t,i,r,n,u);s.push(...a),o.push(...f)}return s.push({level:n,type:"equal",text:"]"}),o.push({level:n,type:"equal",text:"]"}),[s,o]},S=A;var N=(e,t,i,r,n,u,s=[],o=[])=>{if(e=[...e],t=[...t],i&&r?(s.push({level:n,type:"equal",text:`"${i}": [`}),o.push({level:n,type:"equal",text:`"${r}": [`})):(s.push({level:n,type:"equal",text:"["}),o.push({level:n,type:"equal",text:"["})),n>=u.maxDepth)s.push({level:n+1,type:"equal",text:"..."}),o.push({level:n+1,type:"equal",text:"..."});else for(;e.length||t.length;){let a=e[0]??null,f=t[0]??null;if(a&&f){if(h(a)!==h(f))s.push({level:n+1,type:"remove",text:y(a)}),s.push({level:n,type:"equal",text:""}),o.push({level:n,type:"equal",text:""}),o.push({level:n+1,type:"add",text:y(f)});else if(h(a)==="object"){s.push({level:n+1,type:"equal",text:"{"}),o.push({level:n+1,type:"equal",text:"{"});let[p,x]=D(a,f,n+2,u,N);s.push(...p),o.push(...x),s.push({level:n+1,type:"equal",text:"}"}),o.push({level:n+1,type:"equal",text:"}"})}else if(h(a)==="array"){let[p,x]=N(a,f,"","",n+2,u,[],[]);s.push(...p),o.push(...x)}else a===f?(s.push({level:n+1,type:"equal",text:y(a)}),o.push({level:n+1,type:"equal",text:y(f)})):u.showModifications?(s.push({level:n+1,type:"modify",text:y(a)}),o.push({level:n+1,type:"modify",text:y(f)})):(s.push({level:n+1,type:"remove",text:y(a)}),s.push({level:n+1,type:"equal",text:""}),o.push({level:n+1,type:"equal",text:""}),o.push({level:n+1,type:"add",text:y(f)}));e.shift(),t.shift()}else a?(s.push({level:n+1,type:"remove",text:y(a)}),o.push({level:n+1,type:"equal",text:""}),e.shift()):f&&(s.push({level:n+1,type:"equal",text:""}),o.push({level:n+1,type:"add",text:y(f)}),t.shift())}return s.push({level:n,type:"equal",text:"]"}),o.push({level:n,type:"equal",text:"]"}),[s,o]},k=N;var w=e=>{if(!e||typeof e!="object")return e;if(Array.isArray(e)){let i=[...e];return i.sort((r,n)=>typeof r=="number"&&typeof n=="number"?r-n:String(r).localeCompare(String(n))),i.map(r=>w(r))}let t={...e};for(let i in t)t[i]=w(t[i]);return t},O=w;var F=class{options;arrayDiffFunc;constructor({detectCircular:t=!0,maxDepth:i=1/0,showModifications:r=!0,arrayDiffMethod:n="normal"}={}){this.options={detectCircular:t,maxDepth:i,showModifications:r,arrayDiffMethod:n},this.arrayDiffFunc=n==="lcs"||n==="unorder-lcs"?S:k}detectCircular(t){if(this.options.detectCircular&&j(t))throw new Error(`Circular reference detected in object (with keys ${Object.keys(t).map(i=>`"${i}"`).join(", ")})`)}sortResultLines(t,i){for(let r=0;r<t.length;r++){let n=!1;for(let u=1;u<t.length;u++)if(t[u].type==="remove"&&t[u-1].type==="equal"&&i[u].type==="equal"&&i[u-1].type==="add"){let s=t[u-1];t[u-1]=t[u],t[u]=s;let o=i[u-1];i[u-1]=i[u],i[u]=o,n=!0}if(!n)break}}calculateLineNumbers(t){let i=0;for(let r of t)!r.text||(r.lineNumber=++i)}calculateCommas(t){let i=Array(t.length).fill(0);for(let r=t.length-1;r>0;r--)t[r].text?i[r-1]=r:i[r-1]=i[r];for(let r=0;r<t.length;r++)!t[r].text.endsWith("{")&&!t[r].text.endsWith("[")&&t[r].text&&i[r]&&t[r].level<=t[i[r]].level&&(t[r].comma=!0)}diff(t,i){this.detectCircular(t),this.detectCircular(i),(this.options.arrayDiffMethod==="unorder-normal"||this.options.arrayDiffMethod==="unorder-lcs")&&(t=O(t),i=O(i));let r=[],n=[],u=h(t),s=h(i);if(u!==s){r=c(t,null,1,this.options.maxDepth).split(`
`).map(f=>({level:f.match(/^\s+/)?.[0]?.length||0,type:"remove",text:f.replace(/^\s+/,"").replace(/,$/g,""),comma:f.endsWith(",")})),n=c(i,null,1,this.options.maxDepth).split(`
`).map(f=>({level:f.match(/^\s+/)?.[0]?.length||0,type:"add",text:f.replace(/^\s+/,"").replace(/,$/g,""),comma:f.endsWith(",")}));let o=r.length,a=n.length;r.push(...Array(a).fill({level:0,type:"equal",text:""})),n.unshift(...Array(o).fill({level:0,type:"equal",text:""}))}else u==="object"?([r,n]=D(t,i,1,this.options,this.arrayDiffFunc),r.unshift({level:0,type:"equal",text:"{"}),r.push({level:0,type:"equal",text:"}"}),n.unshift({level:0,type:"equal",text:"{"}),n.push({level:0,type:"equal",text:"}"})):u==="array"?[r,n]=this.arrayDiffFunc(t,i,"","",0,this.options):t!==i?this.options.showModifications?(r=[{level:0,type:"modify",text:c(t,null,null,this.options.maxDepth)}],n=[{level:0,type:"modify",text:c(i,null,null,this.options.maxDepth)}]):(r=[{level:0,type:"remove",text:c(t,null,null,this.options.maxDepth)},{level:0,type:"equal",text:""}],n=[{level:0,type:"equal",text:""},{level:0,type:"add",text:c(i,null,null,this.options.maxDepth)}]):(r=[{level:0,type:"equal",text:c(t,null,null,this.options.maxDepth)}],n=[{level:0,type:"equal",text:c(i,null,null,this.options.maxDepth)}]);return this.sortResultLines(r,n),this.calculateLineNumbers(r),this.calculateLineNumbers(n),this.calculateCommas(r),this.calculateCommas(n),[r,n]}},K=F;var d=_(E("react")),M=e=>{let[t,i]=e.diff,r=`${String(t.length).length/2}em`,n=e.indent??2,u=n==="tab"?" ":" ",s=n==="tab"?1:n,o=a=>{let f=t[a],p=i[a];return d.createElement("tr",{key:a},e.lineNumbers&&d.createElement("td",{className:`line-${f.type} line-number`,style:{width:r}},f.lineNumber),d.createElement("td",{className:`line-${f.type}`},d.createElement("pre",null,f.text&&u.repeat(f.level*s),f.text,f.comma&&",")),e.lineNumbers&&d.createElement("td",{className:`line-${p.type} line-number`,style:{width:r}},p.lineNumber),d.createElement("td",{className:`line-${p.type}`},d.createElement("pre",null,p.text&&u.repeat(p.level*s),p.text,p.comma&&",")))};return d.createElement("table",{className:`json-diff-viewer ${e.className||""}`,style:e.style},d.createElement("tbody",null,t.map((a,f)=>o(f))))};M.displayName="Viewer";var Q=M;})();
// src/utils/detect-circular.ts
var detectCircular = (value, map = /* @__PURE__ */ new Map()) => {
if (typeof value !== "object" || value === null) {
return false;
}
if (map.has(value)) {
return true;
}
map.set(value, true);
if (Array.isArray(value)) {
for (let i = 0; i < value.length; i++) {
if (detectCircular(value[i], map)) {
return true;
}
}
return false;
}
for (const key in value) {
if (detectCircular(value[key], map)) {
return true;
}
}
return false;
};
var detect_circular_default = detectCircular;
// src/utils/stringify.ts
var stringify = (obj, replacer, space, depth = Infinity) => {
if (!obj || typeof obj !== "object") {
return JSON.stringify(obj, replacer, space);
}
const t = depth < 1 ? '"..."' : Array.isArray(obj) ? `[${obj.map((v) => stringify(v, replacer, space, depth - 1)).join(",")}]` : `{${Object.keys(obj).map((k) => `"${k}": ${stringify(obj[k], replacer, space, depth - 1)}`).join(", ")}}`;
return JSON.stringify(JSON.parse(t), replacer, space);
};
var stringify_default = stringify;
// src/utils/format-value.ts
var formatValue = (value, depth = Infinity) => {
if (Number.isNaN(value) || value === null) {
return "null";
}
if (Array.isArray(value) || typeof value === "object") {
return stringify_default(value, null, null, depth);
}
if (typeof value === "string") {
return `"${value}"`;
}
return String(value);
};
var format_value_default = formatValue;
// src/utils/get-type.ts
var getType = (value) => {
if (Array.isArray(value)) {
return "array";
}
if (value === null) {
return "null";
}
return typeof value;
};
var get_type_default = getType;
// src/utils/diff-object.ts
var diffObject = (lhs, rhs, level = 1, options, arrayDiffFunc) => {
if (level > options.maxDepth) {
return [
[{ level, type: "equal", text: "..." }],
[{ level, type: "equal", text: "..." }]
];
}
const linesLeft = [];
const linesRight = [];
if (lhs === null && rhs === null || lhs === void 0 && rhs === void 0) {
return [linesLeft, linesRight];
} else if (lhs === null || lhs === void 0) {
linesLeft.push({ level, type: "equal", text: "" });
linesRight.push({ level, type: "add", text: format_value_default(rhs) });
return [linesLeft, linesRight];
} else if (rhs === null || rhs === void 0) {
linesLeft.push({ level, type: "remove", text: format_value_default(lhs) });
linesRight.push({ level, type: "equal", text: "" });
return [linesLeft, linesRight];
}
const keysLeft = Object.keys(lhs);
const keysRight = Object.keys(rhs);
keysLeft.sort();
keysRight.sort();
while (keysLeft.length || keysRight.length) {
const keyLeft = keysLeft[0] ?? null;
const keyRight = keysRight[0] ?? null;
if (keyLeft === keyRight) {
if (get_type_default(lhs[keyLeft]) !== get_type_default(rhs[keyRight])) {
if (options.showModifications) {
linesLeft.push({ level, type: "modify", text: `"${keyLeft}": ${format_value_default(lhs[keyLeft])}` });
linesRight.push({ level, type: "modify", text: `"${keyRight}": ${format_value_default(rhs[keyRight])}` });
} else {
linesLeft.push({ level, type: "remove", text: `"${keyLeft}": ${format_value_default(lhs[keyLeft])}` });
linesLeft.push({ level, type: "equal", text: "" });
linesRight.push({ level, type: "equal", text: "" });
linesRight.push({ level, type: "add", text: `"${keyRight}": ${format_value_default(rhs[keyRight])}` });
}
} else if (Array.isArray(lhs[keyLeft])) {
const arrLeft = [...lhs[keyLeft]];
const arrRight = [...rhs[keyRight]];
const [resLeft, resRight] = arrayDiffFunc(arrLeft, arrRight, keyLeft, keyRight, level, options, [], []);
linesLeft.push(...resLeft);
linesRight.push(...resRight);
} else if (typeof lhs[keyLeft] === "object") {
const result = diffObject(lhs[keyLeft], rhs[keyRight], level + 1, options, arrayDiffFunc);
linesLeft.push({ level, type: "equal", text: `"${keyLeft}": {` });
linesLeft.push(...result[0]);
linesLeft.push({ level, type: "equal", text: "}" });
linesRight.push({ level, type: "equal", text: `"${keyRight}": {` });
linesRight.push(...result[1]);
linesRight.push({ level, type: "equal", text: "}" });
} else {
if (lhs[keyLeft] !== rhs[keyRight]) {
if (options.showModifications) {
linesLeft.push({ level, type: "modify", text: `"${keyLeft}": ${format_value_default(lhs[keyLeft])}` });
linesRight.push({ level, type: "modify", text: `"${keyRight}": ${format_value_default(rhs[keyRight])}` });
} else {
linesLeft.push({ level, type: "remove", text: `"${keyLeft}": ${format_value_default(lhs[keyLeft])}` });
linesLeft.push({ level, type: "equal", text: "" });
linesRight.push({ level, type: "equal", text: "" });
linesRight.push({ level, type: "add", text: `"${keyRight}": ${format_value_default(rhs[keyRight])}` });
}
} else {
linesLeft.push({ level, type: "equal", text: `"${keyLeft}": ${format_value_default(lhs[keyLeft])}` });
linesRight.push({ level, type: "equal", text: `"${keyRight}": ${format_value_default(rhs[keyRight])}` });
}
}
} else if (keyLeft && keyRight) {
if (keyLeft < keyRight) {
linesLeft.push({ level, type: "remove", text: `"${keyLeft}": ${format_value_default(lhs[keyLeft])}` });
linesRight.push({ level, type: "equal", text: "" });
} else {
linesLeft.push({ level, type: "equal", text: "" });
linesRight.push({ level, type: "add", text: `"${keyRight}": ${format_value_default(rhs[keyRight])}` });
}
} else if (keyLeft) {
linesLeft.push({ level, type: "remove", text: `"${keyLeft}": ${format_value_default(lhs[keyLeft])}` });
linesRight.push({ level, type: "equal", text: "" });
} else if (keyRight) {
linesLeft.push({ level, type: "equal", text: "" });
linesRight.push({ level, type: "add", text: `"${keyRight}": ${format_value_default(rhs[keyRight])}` });
}
if (!keyLeft) {
keysRight.shift();
} else if (!keyRight) {
keysLeft.shift();
} else if (keyLeft === keyRight) {
keysLeft.shift();
keysRight.shift();
} else if (keyLeft < keyRight) {
keysLeft.shift();
} else {
keysRight.shift();
}
}
if (linesLeft.length !== linesRight.length) {
throw new Error("Diff error: length not match for left & right, please report a bug with your data.");
}
return [linesLeft, linesRight];
};
var diff_object_default = diffObject;
// src/utils/diff-array-lcs.ts
var lcs = (arrLeft, arrRight, keyLeft, keyRight, level, options) => {
const f = Array(arrLeft.length + 1).fill(0).map(() => Array(arrRight.length + 1).fill(0));
const backtrack = Array(arrLeft.length + 1).fill(0).map(() => Array(arrRight.length + 1).fill(0));
for (let i2 = 1; i2 <= arrLeft.length; i2++) {
backtrack[i2][0] = "up";
}
for (let j2 = 1; j2 <= arrRight.length; j2++) {
backtrack[0][j2] = "left";
}
for (let i2 = 1; i2 <= arrLeft.length; i2++) {
for (let j2 = 1; j2 <= arrRight.length; j2++) {
const typeI = get_type_default(arrLeft[i2 - 1]);
const typeJ = get_type_default(arrRight[j2 - 1]);
if (typeI === typeJ && (typeI === "array" || typeI === "object")) {
f[i2][j2] = f[i2 - 1][j2 - 1] + 1;
backtrack[i2][j2] = "diag";
} else if (arrLeft[i2 - 1] === arrRight[j2 - 1]) {
f[i2][j2] = f[i2 - 1][j2 - 1] + 1;
backtrack[i2][j2] = "diag";
} else if (f[i2 - 1][j2] >= f[i2][j2 - 1]) {
f[i2][j2] = f[i2 - 1][j2];
backtrack[i2][j2] = "up";
} else {
f[i2][j2] = f[i2][j2 - 1];
backtrack[i2][j2] = "left";
}
}
}
let i = arrLeft.length;
let j = arrRight.length;
const tLeft = [];
const tRight = [];
while (i > 0 || j > 0) {
if (backtrack[i][j] === "diag") {
const type = get_type_default(arrLeft[i - 1]);
if (type === "array") {
const [l, r] = diffArrayLCS(arrLeft[i - 1], arrRight[j - 1], keyLeft, keyRight, level + 2, options);
tLeft.unshift(...l);
tRight.unshift(...r);
} else if (type === "object") {
const [l, r] = diff_object_default(arrLeft[i - 1], arrRight[j - 1], level + 2, options, diffArrayLCS);
tLeft.unshift({ level: level + 1, type: "equal", text: "}" });
tRight.unshift({ level: level + 1, type: "equal", text: "}" });
tLeft.unshift(...l);
tRight.unshift(...r);
tLeft.unshift({ level: level + 1, type: "equal", text: "{" });
tRight.unshift({ level: level + 1, type: "equal", text: "{" });
} else {
tLeft.unshift({ level: level + 1, type: "equal", text: format_value_default(arrLeft[i - 1]) });
tRight.unshift({ level: level + 1, type: "equal", text: format_value_default(arrRight[j - 1]) });
}
i--;
j--;
} else if (backtrack[i][j] === "up") {
if (options.showModifications && i > 1 && backtrack[i - 1][j] === "left") {
tLeft.unshift({ level: level + 1, type: "modify", text: format_value_default(arrLeft[i - 1]) });
tRight.unshift({ level: level + 1, type: "modify", text: format_value_default(arrRight[j - 1]) });
i--;
j--;
} else {
tLeft.unshift({ level: level + 1, type: "remove", text: format_value_default(arrLeft[i - 1]) });
tRight.unshift({ level: level + 1, type: "equal", text: "" });
i--;
}
} else {
tLeft.unshift({ level: level + 1, type: "equal", text: "" });
tRight.unshift({ level: level + 1, type: "add", text: format_value_default(arrRight[j - 1]) });
j--;
}
}
return [tLeft, tRight];
};
var diffArrayLCS = (arrLeft, arrRight, keyLeft, keyRight, level, options, linesLeft = [], linesRight = []) => {
if (keyLeft && keyRight) {
linesLeft.push({ level, type: "equal", text: `"${keyLeft}": [` });
linesRight.push({ level, type: "equal", text: `"${keyRight}": [` });
} else {
linesLeft.push({ level, type: "equal", text: "[" });
linesRight.push({ level, type: "equal", text: "[" });
}
if (level >= options.maxDepth) {
linesLeft.push({ level: level + 1, type: "equal", text: "..." });
linesRight.push({ level: level + 1, type: "equal", text: "..." });
} else {
const [tLeftReverse, tRightReverse] = lcs(arrLeft, arrRight, keyLeft, keyRight, level, options);
linesLeft.push(...tLeftReverse);
linesRight.push(...tRightReverse);
}
linesLeft.push({ level, type: "equal", text: "]" });
linesRight.push({ level, type: "equal", text: "]" });
return [linesLeft, linesRight];
};
var diff_array_lcs_default = diffArrayLCS;
// src/utils/diff-array-normal.ts
var diffArrayNormal = (arrLeft, arrRight, keyLeft, keyRight, level, options, linesLeft = [], linesRight = []) => {
arrLeft = [...arrLeft];
arrRight = [...arrRight];
if (keyLeft && keyRight) {
linesLeft.push({ level, type: "equal", text: `"${keyLeft}": [` });
linesRight.push({ level, type: "equal", text: `"${keyRight}": [` });
} else {
linesLeft.push({ level, type: "equal", text: "[" });
linesRight.push({ level, type: "equal", text: "[" });
}
if (level >= options.maxDepth) {
linesLeft.push({ level: level + 1, type: "equal", text: "..." });
linesRight.push({ level: level + 1, type: "equal", text: "..." });
} else {
while (arrLeft.length || arrRight.length) {
const itemLeft = arrLeft[0] ?? null;
const itemRight = arrRight[0] ?? null;
if (itemLeft && itemRight) {
if (get_type_default(itemLeft) !== get_type_default(itemRight)) {
linesLeft.push({ level: level + 1, type: "remove", text: format_value_default(itemLeft) });
linesLeft.push({ level, type: "equal", text: "" });
linesRight.push({ level, type: "equal", text: "" });
linesRight.push({ level: level + 1, type: "add", text: format_value_default(itemRight) });
} else if (get_type_default(itemLeft) === "object") {
linesLeft.push({ level: level + 1, type: "equal", text: "{" });
linesRight.push({ level: level + 1, type: "equal", text: "{" });
const [leftLines, rightLines] = diff_object_default(itemLeft, itemRight, level + 2, options, diffArrayNormal);
linesLeft.push(...leftLines);
linesRight.push(...rightLines);
linesLeft.push({ level: level + 1, type: "equal", text: "}" });
linesRight.push({ level: level + 1, type: "equal", text: "}" });
} else if (get_type_default(itemLeft) === "array") {
const [resLeft, resRight] = diffArrayNormal(itemLeft, itemRight, "", "", level + 2, options, [], []);
linesLeft.push(...resLeft);
linesRight.push(...resRight);
} else if (itemLeft === itemRight) {
linesLeft.push({ level: level + 1, type: "equal", text: format_value_default(itemLeft) });
linesRight.push({ level: level + 1, type: "equal", text: format_value_default(itemRight) });
} else {
if (options.showModifications) {
linesLeft.push({ level: level + 1, type: "modify", text: format_value_default(itemLeft) });
linesRight.push({ level: level + 1, type: "modify", text: format_value_default(itemRight) });
} else {
linesLeft.push({ level: level + 1, type: "remove", text: format_value_default(itemLeft) });
linesLeft.push({ level: level + 1, type: "equal", text: "" });
linesRight.push({ level: level + 1, type: "equal", text: "" });
linesRight.push({ level: level + 1, type: "add", text: format_value_default(itemRight) });
}
}
arrLeft.shift();
arrRight.shift();
} else if (itemLeft) {
linesLeft.push({ level: level + 1, type: "remove", text: format_value_default(itemLeft) });
linesRight.push({ level: level + 1, type: "equal", text: "" });
arrLeft.shift();
} else if (itemRight) {
linesLeft.push({ level: level + 1, type: "equal", text: "" });
linesRight.push({ level: level + 1, type: "add", text: format_value_default(itemRight) });
arrRight.shift();
}
}
}
linesLeft.push({ level, type: "equal", text: "]" });
linesRight.push({ level, type: "equal", text: "]" });
return [linesLeft, linesRight];
};
var diff_array_normal_default = diffArrayNormal;
// src/utils/sort-inner-arrays.ts
var getOrderByType = (value) => {
if (typeof value === "boolean") {
return 0;
}
if (typeof value === "number") {
return 1;
}
if (typeof value === "string") {
return 2;
}
if (value === null) {
return 3;
}
if (Array.isArray(value)) {
return 4;
}
if (typeof value === "object") {
return 5;
}
};
var cmp = (a, b) => {
const orderByTypeA = getOrderByType(a);
const orderByTypeB = getOrderByType(b);
if (orderByTypeA !== orderByTypeB) {
return orderByTypeA - orderByTypeB;
}
if (a === null && b === null || Array.isArray(a) && Array.isArray(b) || orderByTypeA === 5 && orderByTypeB === 5) {
return 0;
}
switch (typeof a) {
case "number":
return a - b;
case "string":
return a.localeCompare(b);
case "boolean":
return +a - +b;
}
};
var sortInnerArrays = (source) => {
if (!source || typeof source !== "object") {
return source;
}
if (Array.isArray(source)) {
const result2 = [...source];
result2.sort((a, b) => cmp(a, b));
return result2.map((item) => sortInnerArrays(item));
}
const result = { ...source };
for (const key in result) {
result[key] = sortInnerArrays(result[key]);
}
return result;
};
var sort_inner_arrays_default = sortInnerArrays;
// src/differ.ts
var Differ = class {
options;
arrayDiffFunc;
constructor({
detectCircular: detectCircular2 = true,
maxDepth = Infinity,
showModifications = true,
arrayDiffMethod = "normal"
} = {}) {
this.options = {
detectCircular: detectCircular2,
maxDepth,
showModifications,
arrayDiffMethod
};
this.arrayDiffFunc = arrayDiffMethod === "lcs" || arrayDiffMethod === "unorder-lcs" ? diff_array_lcs_default : diff_array_normal_default;
}
detectCircular(source) {
if (this.options.detectCircular) {
if (detect_circular_default(source)) {
throw new Error(`Circular reference detected in object (with keys ${Object.keys(source).map((t) => `"${t}"`).join(", ")})`);
}
}
}
sortResultLines(left, right) {
for (let k = 0; k < left.length; k++) {
let changed = false;
for (let i = 1; i < left.length; i++) {
if (left[i].type === "remove" && left[i - 1].type === "equal" && right[i].type === "equal" && right[i - 1].type === "add") {
const t1 = left[i - 1];
left[i - 1] = left[i];
left[i] = t1;
const t2 = right[i - 1];
right[i - 1] = right[i];
right[i] = t2;
changed = true;
}
}
if (!changed) {
break;
}
}
}
calculateLineNumbers(result) {
let lineNumber = 0;
for (const item of result) {
if (!item.text) {
continue;
}
item.lineNumber = ++lineNumber;
}
}
calculateCommas(result) {
const nextLine = Array(result.length).fill(0);
for (let i = result.length - 1; i > 0; i--) {
if (result[i].text) {
nextLine[i - 1] = i;
} else {
nextLine[i - 1] = nextLine[i];
}
}
for (let i = 0; i < result.length; i++) {
if (!result[i].text.endsWith("{") && !result[i].text.endsWith("[") && result[i].text && nextLine[i] && result[i].level <= result[nextLine[i]].level) {
result[i].comma = true;
}
}
}
diff(sourceLeft, sourceRight) {
this.detectCircular(sourceLeft);
this.detectCircular(sourceRight);
if (this.options.arrayDiffMethod === "unorder-normal" || this.options.arrayDiffMethod === "unorder-lcs") {
sourceLeft = sort_inner_arrays_default(sourceLeft);
sourceRight = sort_inner_arrays_default(sourceRight);
}
let resultLeft = [];
let resultRight = [];
const typeLeft = get_type_default(sourceLeft);
const typeRight = get_type_default(sourceRight);
if (typeLeft !== typeRight) {
resultLeft = stringify_default(sourceLeft, null, 1, this.options.maxDepth).split("\n").map((line) => ({
level: line.match(/^\s+/)?.[0]?.length || 0,
type: "remove",
text: line.replace(/^\s+/, "").replace(/,$/g, ""),
comma: line.endsWith(",")
}));
resultRight = stringify_default(sourceRight, null, 1, this.options.maxDepth).split("\n").map((line) => ({
level: line.match(/^\s+/)?.[0]?.length || 0,
type: "add",
text: line.replace(/^\s+/, "").replace(/,$/g, ""),
comma: line.endsWith(",")
}));
const lLength = resultLeft.length;
const rLength = resultRight.length;
resultLeft.push(...Array(rLength).fill({ level: 0, type: "equal", text: "" }));
resultRight.unshift(...Array(lLength).fill({ level: 0, type: "equal", text: "" }));
} else if (typeLeft === "object") {
[resultLeft, resultRight] = diff_object_default(sourceLeft, sourceRight, 1, this.options, this.arrayDiffFunc);
resultLeft.unshift({ level: 0, type: "equal", text: "{" });
resultLeft.push({ level: 0, type: "equal", text: "}" });
resultRight.unshift({ level: 0, type: "equal", text: "{" });
resultRight.push({ level: 0, type: "equal", text: "}" });
} else if (typeLeft === "array") {
[resultLeft, resultRight] = this.arrayDiffFunc(sourceLeft, sourceRight, "", "", 0, this.options);
} else if (sourceLeft !== sourceRight) {
if (this.options.showModifications) {
resultLeft = [{ level: 0, type: "modify", text: stringify_default(sourceLeft, null, null, this.options.maxDepth) }];
resultRight = [{ level: 0, type: "modify", text: stringify_default(sourceRight, null, null, this.options.maxDepth) }];
} else {
resultLeft = [
{ level: 0, type: "remove", text: stringify_default(sourceLeft, null, null, this.options.maxDepth) },
{ level: 0, type: "equal", text: "" }
];
resultRight = [
{ level: 0, type: "equal", text: "" },
{ level: 0, type: "add", text: stringify_default(sourceRight, null, null, this.options.maxDepth) }
];
}
} else {
resultLeft = [{ level: 0, type: "equal", text: stringify_default(sourceLeft, null, null, this.options.maxDepth) }];
resultRight = [{ level: 0, type: "equal", text: stringify_default(sourceRight, null, null, this.options.maxDepth) }];
}
this.sortResultLines(resultLeft, resultRight);
this.calculateLineNumbers(resultLeft);
this.calculateLineNumbers(resultRight);
this.calculateCommas(resultLeft);
this.calculateCommas(resultRight);
return [resultLeft, resultRight];
}
};
var differ_default = Differ;
// src/viewer.tsx
import * as React from "react";
var Viewer = (props) => {
const [linesLeft, linesRight] = props.diff;
const lineNumberWidth = `${String(linesLeft.length).length / 2}em`;
const indent = props.indent ?? 2;
const indentChar = indent === "tab" ? " " : " ";
const indentSize = indent === "tab" ? 1 : indent;
const renderLine = (index) => {
const l = linesLeft[index];
const r = linesRight[index];
return /* @__PURE__ */ React.createElement("tr", {
key: index
}, props.lineNumbers && /* @__PURE__ */ React.createElement("td", {
className: `line-${l.type} line-number`,
style: { width: lineNumberWidth }
}, l.lineNumber), /* @__PURE__ */ React.createElement("td", {
className: `line-${l.type}`
}, /* @__PURE__ */ React.createElement("pre", null, l.text && indentChar.repeat(l.level * indentSize), l.text, l.comma && ",")), props.lineNumbers && /* @__PURE__ */ React.createElement("td", {
className: `line-${r.type} line-number`,
style: { width: lineNumberWidth }
}, r.lineNumber), /* @__PURE__ */ React.createElement("td", {
className: `line-${r.type}`
}, /* @__PURE__ */ React.createElement("pre", null, r.text && indentChar.repeat(r.level * indentSize), r.text, r.comma && ",")));
};
return /* @__PURE__ */ React.createElement("table", {
className: `json-diff-viewer ${props.className || ""}`,
style: props.style
}, /* @__PURE__ */ React.createElement("tbody", null, linesLeft.map((_, index) => renderLine(index))));
};
Viewer.displayName = "Viewer";
var viewer_default = Viewer;
export {
differ_default as Differ,
viewer_default as Viewer
};

9

package.json
{
"name": "json-diff-kit",
"version": "1.0.0",
"version": "1.0.1",
"description": "A better JSON differ & viewer.",
"main": "dist/index.js",
"typings": "typings",

@@ -26,5 +27,7 @@ "repository": {

"@rollup/plugin-node-resolve": "^13.1.3",
"@types/jest": "^27.4.1",
"@types/react": "^17.0.38",
"@types/react-dom": "^17.0.11",
"esbuild": "^0.14.18",
"esbuild-jest": "^0.5.0",
"esbuild-plugin-less": "^1.1.6",

@@ -47,7 +50,7 @@ "jest": "^27.4.7",

"dev": "pnpm start",
"test": "jest",
"test": "jest --coverage",
"build": "node ./esbuild.mjs && tsc",
"build:pages": "NODE_ENV=production BASEDIR=docs rollup -c"
},
"readme": "# JSON Diff Kit\n\n[![NPM version][npm-image]][npm-url]\n[![Downloads][download-badge]][npm-url]\n\nA better JSON differ & viewer.\n\n> Notice: considering most of the browsers now support ES6, this library has only the ES6 version. If you need the compatibility with older browsers, please configure the compiler in your project (e.g. add this library to the `include` field in `babel.config.js`).\n\n## Install\n\nYou can install `json-diff-kit` via various package managers.\n\n```sh\n# using npm\nnpm i json-diff-kit --save\n\n# using yarn\nyarn add json-diff-kit\n\n# using pnpm\npnpm add json-diff-kit\n```\n\n## Quick Start\n\nTo generate the diff data:\n\n```ts\nimport { Differ } from 'json-diff-kit';\n\nconst before = {\n a: 1,\n b: 2,\n d: [1, 5, 4],\n e: ['1', 2, { f: 3, g: null, h: [5], i: [] }, 9],\n};\nconst after = {\n b: 2,\n c: 3,\n d: [1, 3, 4, 6],\n e: ['1', 2, 3, { f: 4, g: false, i: [7, 8] }, 10],\n};\n\n// all configs are optional\nconst differ = new Differ({\n detectCircular: true, // default `true`\n maxDepth: Infinity, // default `Infinity`\n showModifications: true, // default `true`\n arrayDiffMethod: 'lcs', // default `\"normal\"`\n});\n\nconst diff = differ.diff(before, after);\nconsole.log(diff);\n```\n\nYou can use your own component to visualize the `diff` data, or use the built-in viewer:\n\n```tsx\nimport { Viewer } from 'json-diff-kit';\nimport type { DiffResult } from 'json-diff-kit';\n\nimport 'json-diff-kit/dist/viewer.css';\n\ninterface PageProps {\n diff: [DiffResult[], DiffResult[]];\n}\n\nconst Page: React.FC<PageProps> = props => {\n return (\n <Viewer\n diff={props.diff} // required\n indent={4} // default `2`\n lineNumbers={true} // default `false`\n />\n );\n};\n```\n\nThe result is here:\n\n![The result (using LCS array diff method).](./preview.png)\n\n## More Complex Usages\n\nPlease check the [demo pages](https://json-diff-kit.js.org/).\n\n## License\n\nMIT\n\n[npm-url]: https://npmjs.org/package/json-diff-kit\n[npm-image]: https://img.shields.io/npm/v/json-diff-kit.svg?style=flat-square\n\n[download-badge]: https://img.shields.io/npm/dm/json-diff-kit.svg?style=flat-square\n"
"readme": "# JSON Diff Kit\n\n[![NPM version][npm-image]][npm-url]\n[![Downloads][download-badge]][npm-url]\n[![Codecov](https://codecov.io/gh/RexSkz/json-diff-kit/branch/master/graph/badge.svg?token=8YRG3M4WTO)](https://codecov.io/gh/RexSkz/json-diff-kit)\n\nA better JSON differ & viewer.\n\n> Notice: considering most of the browsers now support ES6, this library has only the ES6 version. If you need the compatibility with older browsers, please configure the compiler in your project (e.g. add this library to the `include` field in `babel.config.js`).\n\n## Install\n\nYou can install `json-diff-kit` via various package managers.\n\n```sh\n# using npm\nnpm i json-diff-kit --save\n\n# using yarn\nyarn add json-diff-kit\n\n# using pnpm\npnpm add json-diff-kit\n```\n\n## Quick Start\n\nTo generate the diff data:\n\n```ts\nimport { Differ } from 'json-diff-kit';\n\nconst before = {\n a: 1,\n b: 2,\n d: [1, 5, 4],\n e: ['1', 2, { f: 3, g: null, h: [5], i: [] }, 9],\n};\nconst after = {\n b: 2,\n c: 3,\n d: [1, 3, 4, 6],\n e: ['1', 2, 3, { f: 4, g: false, i: [7, 8] }, 10],\n};\n\n// all configs are optional\nconst differ = new Differ({\n detectCircular: true, // default `true`\n maxDepth: Infinity, // default `Infinity`\n showModifications: true, // default `true`\n arrayDiffMethod: 'lcs', // default `\"normal\"`\n});\n\nconst diff = differ.diff(before, after);\nconsole.log(diff);\n```\n\nYou can use your own component to visualize the `diff` data, or use the built-in viewer:\n\n```tsx\nimport { Viewer } from 'json-diff-kit';\nimport type { DiffResult } from 'json-diff-kit';\n\nimport 'json-diff-kit/dist/viewer.css';\n\ninterface PageProps {\n diff: [DiffResult[], DiffResult[]];\n}\n\nconst Page: React.FC<PageProps> = props => {\n return (\n <Viewer\n diff={props.diff} // required\n indent={4} // default `2`\n lineNumbers={true} // default `false`\n />\n );\n};\n```\n\nThe result is here:\n\n![The result (using LCS array diff method).](./preview.png)\n\n## More Complex Usages\n\nPlease check the [demo pages](https://json-diff-kit.js.org/).\n\n## Algorithm Details\n\nPlease refer to the article [JSON Diff Kit: A Combination of Several Simple Algorithms](https://blog.rexskz.info/json-diff-kit-a-combination-of-several-simple-algorithms.html).\n\n## License\n\nMIT\n\n[npm-url]: https://npmjs.org/package/json-diff-kit\n[npm-image]: https://img.shields.io/npm/v/json-diff-kit.svg\n\n[download-badge]: https://img.shields.io/npm/dm/json-diff-kit.svg\n"
}

@@ -5,2 +5,3 @@ # JSON Diff Kit

[![Downloads][download-badge]][npm-url]
[![Codecov](https://codecov.io/gh/RexSkz/json-diff-kit/branch/master/graph/badge.svg?token=8YRG3M4WTO)](https://codecov.io/gh/RexSkz/json-diff-kit)

@@ -89,2 +90,6 @@ A better JSON differ & viewer.

## Algorithm Details
Please refer to the article [JSON Diff Kit: A Combination of Several Simple Algorithms](https://blog.rexskz.info/json-diff-kit-a-combination-of-several-simple-algorithms.html).
## License

@@ -95,4 +100,4 @@

[npm-url]: https://npmjs.org/package/json-diff-kit
[npm-image]: https://img.shields.io/npm/v/json-diff-kit.svg?style=flat-square
[npm-image]: https://img.shields.io/npm/v/json-diff-kit.svg
[download-badge]: https://img.shields.io/npm/dm/json-diff-kit.svg?style=flat-square
[download-badge]: https://img.shields.io/npm/dm/json-diff-kit.svg

@@ -0,0 +0,0 @@ export interface DifferOptions {

@@ -0,0 +0,0 @@ import Differ from './differ';

declare const detectCircular: (value: any, map?: Map<any, boolean>) => boolean;
export default detectCircular;
import type { DifferOptions, DiffResult } from '../differ';
declare const diffArrayLCS: (arrLeft: any[], arrRight: any[], keyLeft: string, keyRight: string, level: number, options: DifferOptions, linesLeft?: DiffResult[], linesRight?: DiffResult[]) => [DiffResult[], DiffResult[]];
export default diffArrayLCS;
import type { DiffResult, DifferOptions } from '../differ';
declare const diffArrayNormal: (arrLeft: any[], arrRight: any[], keyLeft: string, keyRight: string, level: number, options: DifferOptions, linesLeft?: DiffResult[], linesRight?: DiffResult[]) => [DiffResult[], DiffResult[]];
export default diffArrayNormal;
import type { DifferOptions, DiffResult, ArrayDiffFunc } from '../differ';
declare const diffObject: (lhs: Record<string, any>, rhs: Record<string, any>, level: number, options: DifferOptions, arrayDiffFunc: ArrayDiffFunc) => [DiffResult[], DiffResult[]];
export default diffObject;
declare const formatValue: (value: any, depth?: number) => string;
export default formatValue;

@@ -1,2 +0,2 @@

declare const getType: (value: any) => "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | "array" | "null";
declare const getType: (value: any) => "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | "null" | "array";
export default getType;

@@ -0,2 +1,9 @@

/**
* The compare function to correct the order for "array" or "object":
* - The order for 2 values with different types are: boolean, number, string, null, array, object.
* - The order for 2 values with the same type is according to the type:
* - For boolean, number, string: use the `<` sign.
* - For array and object: preserve the original order (or do we have a better idea?)
*/
declare const sortInnerArrays: (source: any) => any;
export default sortInnerArrays;
declare const stringify: (obj: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number, depth?: number) => string;
export default stringify;

@@ -0,0 +0,0 @@ import * as React from 'react';

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc