New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

json-summary

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

json-summary - npm Package Compare versions

Comparing version 0.2.5 to 1.0.0

743

dist/json-summary.js

@@ -1,409 +0,432 @@

// https://andrewtburks.dev/json-summary v0.2.5 Copyright 2019 Andrew Burks
// https://andrewtburks.dev/json-summary v1.0.0 Copyright 2019 Andrew Burks
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.jsonSummary = factory());
}(this, function () { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = global || self, factory(global.jsonSummary = {}));
}(this, function (exports) { 'use strict';
const summarizer = (function() {
let defaultOptions = {
arraySampleCount: 10,
indentation: " ", // or "\t"
indentCount: 2,
showExampleValue: true,
startExpanded: false,
theme: "dark"
};
var defaults = {
arraySampleCount: 10,
indentation: " ", // or "\t"
indentCount: 2,
showExampleValue: true,
startExpanded: false,
theme: "dark"
};
// summarizer utility class
return function({
arraySampleCount = 10,
indentation = " ", // or "\t"
indentCount = 2,
showExampleValue = true,
startExpanded = false,
theme = "dark"
} = defaultOptions) {
let defaultSummOpt = {
arraySampleCount: defaults.arraySampleCount
};
let options = {
arraySampleCount,
indentation,
indentCount,
showExampleValue,
startExpanded,
theme
};
// utility function to extract overall json structure without printing entire data object
function summarizeJSON(data, {
arraySampleCount = defaultSummOpt.arraySampleCount
} = defaultSummOpt) {
let summary = summarizeItem(data);
// clean up the marking
unmarkObject(data);
return summary;
// utility function to extract overall json structure without printing entire data object
function summarizeJSON(data) {
let summary = summarizeItem(data);
function summarizeItem(item) {
let summarize = {
Array: arr => {
let summarized = {
count: 1,
type: "Array",
length: arr.length
};
// recurse to items in the array
if (arr.length) {
if (arraySampleCount > 0) {
let numToSample = arraySampleCount === "all" ? arr.length : Math.min(arraySampleCount, arr.length);
let sampledItems = {};
// summarized.count = numToSample;
// clean up the marking
unmarkObject(data);
while (numToSample > 0) {
let sampleIndex = Math.floor(Math.random() * arr.length);
return summary;
}
function summarizeItem(item) {
let summarize = {
Array: arr => {
let summarized = {
count: 1,
type: "Array",
length: arr.length
};
// recurse to items in the array
if (arr.length) {
if (arraySampleCount > 0) {
let numToSample = Math.min(arraySampleCount, arr.length);
let sampledItems = {};
// summarized.count = numToSample;
while (numToSample > 0) {
let sampleIndex = Math.floor(Math.random() * arr.length);
if (!sampledItems.hasOwnProperty(sampleIndex)) {
sampledItems[sampleIndex] = arr[sampleIndex];
numToSample--;
}
if (!sampledItems.hasOwnProperty(sampleIndex)) {
sampledItems[sampleIndex] = arr[sampleIndex];
numToSample--;
}
}
let summarizedSamples = [];
let summarizedSamples = [];
for (let [idx, item] of Object.entries(sampledItems)) {
summarizedSamples.push(summarizeItem(item));
}
for (let pair of Object.entries(sampledItems)) {
let item = pair[1];
let joinedSample = joinSampledArray(summarizedSamples);
summarized.items = {
0: joinedSample
};
} else {
// sumamrized.count = 1;
summarized.items = {
0: summarizeItem(arr[0])
};
summarizedSamples.push(summarizeItem(item));
}
let joinedSample = joinSampledArray(summarizedSamples);
summarized.items = {
0: joinedSample
};
} else {
// sumamrized.count = 1;
summarized.items = {
0: undefined
0: summarizeItem(arr[0])
};
}
return summarized;
},
Object: obj => {
let summarized = {
count: 1,
type: "Object",
keys: Object.keys(obj),
items: {}
} else {
summarized.items = {
0: undefined
};
}
for (let key of summarized.keys) {
summarized.items[key] = summarizeItem(obj[key]);
}
return summarized;
},
Other: data => {
let range;
return summarized;
},
Object: obj => {
let summarized = {
count: 1,
type: "Object",
keys: Object.keys(obj),
items: {}
};
if (typeof data === "string") {
range = [data.length, data.length];
} else if (typeof data === "number") {
range = [data, data];
}
for (let key of summarized.keys) {
summarized.items[key] = summarizeItem(obj[key]);
}
return {
type: typeof data,
example: data,
count: 1,
range
};
return summarized;
},
Other: data => {
let range;
if (typeof data === "string") {
range = [data.length, data.length];
} else if (typeof data === "number") {
range = [data, data];
}
};
let type = "Other";
if (item instanceof Array) {
type = "Array";
} else if (item instanceof Object) {
type = "Object";
}
if (item && item["*snippets_mark*"]) {
return {
type: type,
circular: true
type: typeof data,
example: data,
count: 1,
range
};
} else {
// marked as visited to make sure it doesn't hit a circular structure
if (type !== "Other") {
Object.defineProperty(item, "*snippets_mark*", {
enumerable: false,
writable: true,
configurable: true
});
item["*snippets_mark*"] = true;
}
return summarize[type](item);
}
};
let type = "Other";
if (item instanceof Array) {
type = "Array";
} else if (item instanceof Object) {
type = "Object";
}
function joinSampledArray(itemset) {
// let type = itemset.map(d => d.type)
// .reduce((a, type) => {
// a[type] = [];
// return a;
// }, {});
// for (let item of itemset) {
// type[item.type].push(item);
// }
if (item && item["*snippets_mark*"]) {
return {
type: type,
circular: true
};
} else {
// marked as visited to make sure it doesn't hit a circular structure
if (type !== "Other") {
Object.defineProperty(item, "*snippets_mark*", {
enumerable: false,
writable: true,
configurable: true
});
item["*snippets_mark*"] = true;
}
// let joins = {};
return summarize[type](item);
}
}
// for (let [t, itemset] of Object.entries(type)) {
// joins[t] = joinItems(itemset, t);
// }
function joinSampledArray(itemset) {
// let type = itemset.map(d => d.type)
// .reduce((a, type) => {
// a[type] = [];
// return a;
// }, {});
// console.log(joins);
// for (let item of itemset) {
// type[item.type].push(item);
// }
// return
// let joins = {};
// assume theyre all a matching type
// for (let [t, itemset] of Object.entries(type)) {
// joins[t] = joinItems(itemset, t);
// }
let joinableTypes = {Array: true, Object: true, boolean: true, string: true, number: true};
let items = itemset.filter(i => joinableTypes[i.type]);
// console.log(joins);
if (items.length) {
let type = items[0].type;
return joinItems(items.filter(i => i.type === type), type);
} else {
// idk - no items to join?
return {
count: 0
};
}
// return
// assume theyre all a matching type
let joinableTypes = {Array: true, Object: true, boolean: true, string: true, number: true};
let items = itemset.filter(i => joinableTypes[i.type]);
if (items.length) {
let type = items[0].type;
return joinItems(items.filter(i => i.type === type), type);
} else {
// idk - no items to join?
return {
count: 0
};
}
function joinItems(itemArr, type) {
itemArr = itemArr.filter(i => i.type === type);
}
// functions to join items by type
let joiner = {
string: function(items) {
// string length range
let min = items.reduce((acc, item) => {
return Math.min(acc, item.range[0]);
}, Infinity);
function joinItems(itemArr, type) {
itemArr = itemArr.filter(i => i.type === type);
let max = items.reduce((acc, item) => {
return Math.max(acc, item.range[1]);
}, -Infinity);
// functions to join items by type
let joiner = {
string: function(items) {
// string length range
let min = items.reduce((acc, item) => {
return Math.min(acc, item.range[0]);
}, Infinity);
let joinedString = {
type: "string",
example: items[0].example,
range: [min, max],
count: items.reduce((a, i) => a + i.count, 0)
};
let max = items.reduce((acc, item) => {
return Math.max(acc, item.range[1]);
}, -Infinity);
return joinedString;
},
number: function(items) {
let min = items.reduce((acc, item) => {
return Math.min(acc, item.range[0]);
}, Infinity);
let joinedString = {
type: "string",
example: items[0].example,
range: [min, max],
count: items.reduce((a, i) => a + i.count, 0)
};
let max = items.reduce((acc, item) => {
return Math.max(acc, item.range[1]);
}, -Infinity);
return joinedString;
},
number: function(items) {
let min = items.reduce((acc, item) => {
return Math.min(acc, item.range[0]);
}, Infinity);
let joinedNumber = {
type: "number",
example: items[0].example,
range: [min, max],
count: items.reduce((a, i) => a + i.count, 0)
};
let max = items.reduce((acc, item) => {
return Math.max(acc, item.range[1]);
}, -Infinity);
return joinedNumber;
},
boolean: function(items) {
return {
type: "boolean",
example: items[0].example,
count: items.reduce((a, i) => a + i.count, 0)
};
},
Object: function(items) {
let masterKeys = {};
let joinedNumber = {
type: "number",
example: items[0].example,
range: [min, max],
count: items.reduce((a, i) => a + i.count, 0)
};
for (let obj of items) {
if (!obj.circular) {
for (let key of obj.keys) {
!masterKeys[key] && (masterKeys[key] = []);
return joinedNumber;
},
boolean: function(items) {
return {
type: "boolean",
example: items[0].example,
count: items.reduce((a, i) => a + i.count, 0)
};
},
Object: function(items) {
let masterKeys = {};
masterKeys[key].push(obj.items[key]);
}
for (let obj of items) {
if (!obj.circular) {
for (let key of obj.keys) {
!masterKeys[key] && (masterKeys[key] = []);
masterKeys[key].push(obj.items[key]);
}
}
}
let joinedObject = { type: "Object", keys: [], items: {}, count: items.length };
let joinedObject = { type: "Object", keys: [], items: {}, count: items.length };
for (let key of Object.keys(masterKeys)) {
joinedObject.keys.push(key);
for (let key of Object.keys(masterKeys)) {
joinedObject.keys.push(key);
joinedObject.items[key] = joinSampledArray(masterKeys[key]);
}
joinedObject.items[key] = joinSampledArray(masterKeys[key]);
}
return joinedObject;
},
Array: function(items) {
let joinedValues = joinSampledArray(items.map(i => i.items[0]).filter(i => i));
return joinedObject;
},
Array: function(items) {
let joinedValues = joinSampledArray(items.map(i => i.items[0]).filter(i => i));
let joinedArray = {
count: items.length,
items: {
0: joinedValues
},
length: joinedValues.count / items.length,
type: "Array"
};
let joinedArray = {
count: items.length,
items: {
0: joinedValues
},
length: joinedValues.count / items.length,
type: "Array"
};
return joinedArray;
}
};
return joinedArray;
}
};
return joiner[type](itemArr);
}
return joiner[type](itemArr);
}
function unmarkObject(obj) {
if (obj && obj["*snippets_mark*"]) {
delete obj["*snippets_mark*"];
// recurse to the next level
if (obj instanceof Array && obj.length) {
unmarkObject(obj[0]);
} else if (obj instanceof Object) {
for (let key of Object.keys(obj)) {
unmarkObject(obj[key]);
}
function unmarkObject(obj) {
if (obj && obj["*snippets_mark*"]) {
delete obj["*snippets_mark*"];
// recurse to the next level
if (obj instanceof Array && obj.length) {
unmarkObject(obj[0]);
} else if (obj instanceof Object) {
for (let key of Object.keys(obj)) {
unmarkObject(obj[key]);
}
}
}
}
}
// utility function to stringify the summary output from summarizeJSON
function printSummarizedJSON(summary) {
// start at 0 indentation
return `<div class='json-summary-wrapper ${options.theme}'>` + printSummaryLevel(summary, 0, 1);
}
function printSummaryLevel(data, l, prevCount) {
let string = "";
if (data.circular) {
string += wrapInHTML("(circular reference)", "circular");
} else if (data.type === "Object") {
string += "{";
let keys = data.keys.map(k => `'${k}'`).join(", ");
string += wrapInHTML(keys, "keys");
let childStrings = data.keys.map(key => {
return printSummaryLevel(data.items[key], l + 1, data.count);
});
if (childStrings.length) {
let childStringCombined = "\n";
for (let i = 0; i < data.keys.length; i++) {
childStringCombined += options.indentation.repeat(
(l + 1) * options.indentCount
var summarize = summarizeJSON;
let defaultPrintOpt = {
indentation: defaults.indentation, // or "\t"
indentCount: defaults.indentCount,
showExampleValue: defaults.showExampleValue,
startExpanded: defaults.startExpanded,
theme: defaults.theme
};
// utility function to stringify the summary output from summarizeJSON
function printSummarizedJSON(
summary,
{
indentation = defaultPrintOpt.indentation, // or "\t"
indentCount = defaultPrintOpt.indentCount,
showExampleValue = defaultPrintOpt.showExampleValue,
startExpanded = defaultPrintOpt.startExpanded,
theme = defaultPrintOpt.theme
} = defaultPrintOpt
) {
// start at 0 indentation
return (
`<div class="theme ${theme}"><div class='json-summary-wrapper'>` +
printSummaryLevel(summary, 0) +
`<div></div>`
);
function printSummaryLevel(data, l) {
let string = "";
if (data.circular) {
string += wrapInHTML("(circular reference)", "circular");
} else if (data.type === "Object") {
string += "{";
let keys = data.keys.map(k => `'${k}'`).join(", ");
string += wrapInHTML(keys, "keys");
let childStrings = data.keys.map(key => {
return printSummaryLevel(data.items[key], l + 1);
});
if (childStrings.length) {
let childStringCombined = "\n";
for (let i = 0; i < data.keys.length; i++) {
childStringCombined += indentation.repeat((l + 1) * indentCount);
childStringCombined += wrapInHTML(data.keys[i], "name") + ": ";
if (data.count > 1) {
childStringCombined += htmlPercentageBar(
(data.items[data.keys[i]].count / data.count) * 100
);
childStringCombined += wrapInHTML(data.keys[i], "name") + ": ";
}
if (data.count > 1) {
childStringCombined += htmlPercentageBar(data.items[data.keys[i]].count / data.count * 100);
}
childStringCombined += childStrings[i];
if (i < data.keys.length - 1) {
childStringCombined += ",";
}
childStringCombined += "\n";
childStringCombined += childStrings[i];
if (i < data.keys.length - 1) {
childStringCombined += ",";
}
childStringCombined += options.indentation.repeat(l * options.indentCount);
string += wrapInHTML(childStringCombined, "child");
childStringCombined += "\n";
}
string += "}";
string = wrapInHTML(string, "layer");
} else if (data.type === "Array") {
// string += "[]";
// string += `[ ${data.length ? `(${data.length}×)` : "∅"} `;
string += wrapInHTML(data.count > 1 ? "μ = " + data.length.toFixed(1) : data.length, "length") + ` [`;
if (data.length) {
let needsNewlines =
data.items["0"].type === "Object" || data.items["0"].type === "Array";
if (needsNewlines) {
string += "\n" + options.indentation.repeat((l + 1) * options.indentCount);
}
string += printSummaryLevel(data.items["0"], l + 1, data.count);
if (needsNewlines) {
string += "\n" + options.indentation.repeat(l * options.indentCount);
}
childStringCombined += indentation.repeat(l * indentCount);
string += wrapInHTML(childStringCombined, "child");
}
string += "}";
string = wrapInHTML(string, "layer");
} else if (data.type === "Array") {
// string += "[]";
// string += `[ ${data.length ? `(${data.length}×)` : "∅"} `;
string +=
wrapInHTML(
data.count > 1 ? "μ = " + data.length.toFixed(1) : data.length,
"length"
) + ` [`;
if (data.length) {
let needsNewlines =
data.items["0"].type === "Object" || data.items["0"].type === "Array";
if (needsNewlines) {
string += "\n" + indentation.repeat((l + 1) * indentCount);
}
string += "]";
// string = wrapInHTML(string, "layer");
} else {
if (data.example == null || data.example == undefined) {
string += wrapInHTML("?", "type");
} else {
string += wrapInHTML(data.type, "type");
string += printSummaryLevel(data.items["0"], l + 1, data.count);
if (needsNewlines) {
string += "\n" + indentation.repeat(l * indentCount);
}
if (options.showExampleValue) {
string += wrapInHTML(data.example, "value", data.type);
data.count > 1 && data.range && (string += wrapInHTML(data.range, "range", data.type));
}
}
return string;
string += "]";
// string = wrapInHTML(string, "layer");
} else {
if (data.example == null || data.example == undefined) {
string += wrapInHTML("?", "type");
} else {
string += wrapInHTML(data.type, "type");
}
if (showExampleValue) {
string += wrapInHTML(data.example, "value", data.type);
data.count > 1 &&
data.range &&
(string += wrapInHTML(data.range, "range", data.type));
}
}
function wrapInHTML(value, role, type) {
let tags = {
type: () => `<span class="json-summary json-summary-type json-summary-type-${value}">&lt;${value}&gt;</span>`,
value: () => `<span class="json-summary json-summary-value json-summary-value-${type}">${value}</span>`,
range: () => `<span class="json-summary json-summary-range json-summary-range-${type}">[${value[0]}, ${value[1]}]</span>`,
name: () => `<span class="json-summary json-summary-name">${value}</span>`,
length: () => `<span class="json-summary json-summary-length">(${value})</span>`,
circular: () => `<span class="json-summary json-summary-circular">${value}</span>`,
layer: () => `<span class="json-summary json-summary-checkbox ${
options.startExpanded ? "checked" : ""
}">
<input type="checkbox" ${
options.startExpanded ? "checked" : ""
}>
return string;
}
function wrapInHTML(value, role, type) {
let tags = {
type: () =>
`<span class="json-summary json-summary-type json-summary-type-${value}">&lt;${value}&gt;</span>`,
value: () =>
`<span class="json-summary json-summary-value json-summary-value-${type}">${value}</span>`,
range: () =>
`<span class="json-summary json-summary-range json-summary-range-${type}">[${
value[0]
}, ${value[1]}]</span>`,
name: () => `<span class="json-summary json-summary-name">${value}</span>`,
length: () =>
`<span class="json-summary json-summary-length">(${value})</span>`,
circular: () =>
`<span class="json-summary json-summary-circular">${value}</span>`,
layer: () => `<span class="json-summary json-summary-checkbox ${
startExpanded ? "checked" : ""
}">
<input type="checkbox" ${startExpanded ? "checked" : ""}>
<span class="json-summary-checkboxmarker" onclick="(function(me){

@@ -413,24 +436,34 @@ me.parentNode.classList.toggle('checked');

</span><div class="json-summary json-summary-layer">${value}</div>`,
child: () => `<div class="json-summary json-summary-child">${value}</div>`,
keys: () => `<span class="json-summary json-summary-keys">${value}</span>`
};
child: () => `<div class="json-summary json-summary-child">${value}</div>`,
keys: () => `<span class="json-summary json-summary-keys">${value}</span>`
};
return tags[role]();
}
return tags[role]();
}
function htmlPercentageBar(percentage) {
return `<div class="json-summary json-summary-bar" title="${percentage.toFixed(2)}%"><div class="json-summary json-summary-percentage" style="width:${percentage}%;"></div></div>`
}
return {
summarize: summarizeJSON,
printSummary: printSummarizedJSON
};
function htmlPercentageBar(percentage) {
return `<div class="json-summary json-summary-bar" title="${percentage.toFixed(
2
)}%"><div class="json-summary json-summary-percentage" style="width:${percentage}%;"></div></div>`;
}
}());
}
var jsonSummary = summarizer;
var printSummary = printSummarizedJSON;
return jsonSummary;
var jsonSummary = {
defaults: defaults,
summarize: summarize,
printSummary: printSummary
};
var jsonSummary_1 = jsonSummary.defaults;
var jsonSummary_2 = jsonSummary.summarize;
var jsonSummary_3 = jsonSummary.printSummary;
exports.default = jsonSummary;
exports.defaults = jsonSummary_1;
exports.printSummary = jsonSummary_3;
exports.summarize = jsonSummary_2;
Object.defineProperty(exports, '__esModule', { value: true });
}));

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

// https://andrewtburks.dev/json-summary v0.2.5 Copyright 2019 Andrew Burks
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).jsonSummary=t()}(this,function(){"use strict";return function(){let e={arraySampleCount:10,indentation:" ",indentCount:2,showExampleValue:!0,startExpanded:!1,theme:"dark"};return function({arraySampleCount:t=10,indentation:n=" ",indentCount:r=2,showExampleValue:a=!0,startExpanded:s=!1,theme:o="dark"}=e){let u={arraySampleCount:t,indentation:n,indentCount:r,showExampleValue:a,startExpanded:s,theme:o};function l(e){let t={Array:!0,Object:!0,boolean:!0,string:!0,number:!0},n=e.filter(e=>t[e.type]);if(n.length){let e=n[0].type;return function(e,t){return e=e.filter(e=>e.type===t),{string:function(e){let t=e.reduce((e,t)=>Math.min(e,t.range[0]),1/0),n=e.reduce((e,t)=>Math.max(e,t.range[1]),-1/0);return{type:"string",example:e[0].example,range:[t,n],count:e.reduce((e,t)=>e+t.count,0)}},number:function(e){let t=e.reduce((e,t)=>Math.min(e,t.range[0]),1/0),n=e.reduce((e,t)=>Math.max(e,t.range[1]),-1/0);return{type:"number",example:e[0].example,range:[t,n],count:e.reduce((e,t)=>e+t.count,0)}},boolean:function(e){return{type:"boolean",example:e[0].example,count:e.reduce((e,t)=>e+t.count,0)}},Object:function(e){let t={};for(let n of e)if(!n.circular)for(let e of n.keys)!t[e]&&(t[e]=[]),t[e].push(n.items[e]);let n={type:"Object",keys:[],items:{},count:e.length};for(let e of Object.keys(t))n.keys.push(e),n.items[e]=l(t[e]);return n},Array:function(e){let t=l(e.map(e=>e.items[0]).filter(e=>e));return{count:e.length,items:{0:t},length:t.count/e.length,type:"Array"}}}[t](e)}(n.filter(t=>t.type===e),e)}return{count:0}}function i(e,t,n){return{type:()=>`<span class="json-summary json-summary-type json-summary-type-${e}">&lt;${e}&gt;</span>`,value:()=>`<span class="json-summary json-summary-value json-summary-value-${n}">${e}</span>`,range:()=>`<span class="json-summary json-summary-range json-summary-range-${n}">[${e[0]}, ${e[1]}]</span>`,name:()=>`<span class="json-summary json-summary-name">${e}</span>`,length:()=>`<span class="json-summary json-summary-length">(${e})</span>`,circular:()=>`<span class="json-summary json-summary-circular">${e}</span>`,layer:()=>`<span class="json-summary json-summary-checkbox ${u.startExpanded?"checked":""}">\n <input type="checkbox" ${u.startExpanded?"checked":""}>\n <span class="json-summary-checkboxmarker" onclick="(function(me){\n me.parentNode.classList.toggle('checked');\n })(this)"></span>\n </span><div class="json-summary json-summary-layer">${e}</div>`,child:()=>`<div class="json-summary json-summary-child">${e}</div>`,keys:()=>`<span class="json-summary json-summary-keys">${e}</span>`}[t]()}return{summarize:function(e){let n=function e(n){let r={Array:n=>{let r={count:1,type:"Array",length:n.length};if(n.length)if(t>0){let a=Math.min(t,n.length),s={};for(;a>0;){let e=Math.floor(Math.random()*n.length);s.hasOwnProperty(e)||(s[e]=n[e],a--)}let o=[];for(let[t,n]of Object.entries(s))o.push(e(n));let u=l(o);r.items={0:u}}else r.items={0:e(n[0])};else r.items={0:void 0};return r},Object:t=>{let n={count:1,type:"Object",keys:Object.keys(t),items:{}};for(let r of n.keys)n.items[r]=e(t[r]);return n},Other:e=>{let t;return"string"==typeof e?t=[e.length,e.length]:"number"==typeof e&&(t=[e,e]),{type:typeof e,example:e,count:1,range:t}}},a="Other";return n instanceof Array?a="Array":n instanceof Object&&(a="Object"),n&&n["*snippets_mark*"]?{type:a,circular:!0}:("Other"!==a&&(Object.defineProperty(n,"*snippets_mark*",{enumerable:!1,writable:!0,configurable:!0}),n["*snippets_mark*"]=!0),r[a](n))}(e);return function e(t){if(t&&t["*snippets_mark*"])if(delete t["*snippets_mark*"],t instanceof Array&&t.length)e(t[0]);else if(t instanceof Object)for(let n of Object.keys(t))e(t[n])}(e),n},printSummary:function(e){return`<div class='json-summary-wrapper ${u.theme}'>`+function e(t,n,r){let a="";if(t.circular)a+=i("(circular reference)","circular");else if("Object"===t.type){a+="{";let r=t.keys.map(e=>`'${e}'`).join(", ");a+=i(r,"keys");let o=t.keys.map(r=>e(t.items[r],n+1,t.count));if(o.length){let e="\n";for(let r=0;r<t.keys.length;r++)e+=u.indentation.repeat((n+1)*u.indentCount),e+=i(t.keys[r],"name")+": ",t.count>1&&(e+=`<div class="json-summary json-summary-bar" title="${(s=t.items[t.keys[r]].count/t.count*100).toFixed(2)}%"><div class="json-summary json-summary-percentage" style="width:${s}%;"></div></div>`),e+=o[r],r<t.keys.length-1&&(e+=","),e+="\n";e+=u.indentation.repeat(n*u.indentCount),a+=i(e,"child")}a=i(a+="}","layer")}else if("Array"===t.type){if(a+=i(t.count>1?"μ = "+t.length.toFixed(1):t.length,"length")+" [",t.length){let r="Object"===t.items[0].type||"Array"===t.items[0].type;r&&(a+="\n"+u.indentation.repeat((n+1)*u.indentCount)),a+=e(t.items[0],n+1,t.count),r&&(a+="\n"+u.indentation.repeat(n*u.indentCount))}a+="]"}else null==t.example||null==t.example?a+=i("?","type"):a+=i(t.type,"type"),u.showExampleValue&&(a+=i(t.example,"value",t.type),t.count>1&&t.range&&(a+=i(t.range,"range",t.type)));var s;return a}(e,0)}}}}()});
// https://andrewtburks.dev/json-summary v1.0.0 Copyright 2019 Andrew Burks
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).jsonSummary={})}(this,function(e){"use strict";var t={arraySampleCount:10,indentation:" ",indentCount:2,showExampleValue:!0,startExpanded:!1,theme:"dark"};let n={arraySampleCount:t.arraySampleCount};let a={indentation:t.indentation,indentCount:t.indentCount,showExampleValue:t.showExampleValue,startExpanded:t.startExpanded,theme:t.theme};var r={defaults:t,summarize:function(e,{arraySampleCount:t=n.arraySampleCount}=n){let a=function e(n){let a={Array:n=>{let a={count:1,type:"Array",length:n.length};if(n.length)if(t>0){let s="all"===t?n.length:Math.min(t,n.length),l={};for(;s>0;){let e=Math.floor(Math.random()*n.length);l.hasOwnProperty(e)||(l[e]=n[e],s--)}let u=[];for(let t of Object.entries(l)){let n=t[1];u.push(e(n))}let m=r(u);a.items={0:m}}else a.items={0:e(n[0])};else a.items={0:void 0};return a},Object:t=>{let n={count:1,type:"Object",keys:Object.keys(t),items:{}};for(let a of n.keys)n.items[a]=e(t[a]);return n},Other:e=>{let t;return"string"==typeof e?t=[e.length,e.length]:"number"==typeof e&&(t=[e,e]),{type:typeof e,example:e,count:1,range:t}}},s="Other";return n instanceof Array?s="Array":n instanceof Object&&(s="Object"),n&&n["*snippets_mark*"]?{type:s,circular:!0}:("Other"!==s&&(Object.defineProperty(n,"*snippets_mark*",{enumerable:!1,writable:!0,configurable:!0}),n["*snippets_mark*"]=!0),a[s](n))}(e);return function e(t){if(t&&t["*snippets_mark*"])if(delete t["*snippets_mark*"],t instanceof Array&&t.length)e(t[0]);else if(t instanceof Object)for(let n of Object.keys(t))e(t[n])}(e),a;function r(e){let t={Array:!0,Object:!0,boolean:!0,string:!0,number:!0},n=e.filter(e=>t[e.type]);if(n.length){let e=n[0].type;return function(e,t){return e=e.filter(e=>e.type===t),{string:function(e){let t=e.reduce((e,t)=>Math.min(e,t.range[0]),1/0),n=e.reduce((e,t)=>Math.max(e,t.range[1]),-1/0);return{type:"string",example:e[0].example,range:[t,n],count:e.reduce((e,t)=>e+t.count,0)}},number:function(e){let t=e.reduce((e,t)=>Math.min(e,t.range[0]),1/0),n=e.reduce((e,t)=>Math.max(e,t.range[1]),-1/0);return{type:"number",example:e[0].example,range:[t,n],count:e.reduce((e,t)=>e+t.count,0)}},boolean:function(e){return{type:"boolean",example:e[0].example,count:e.reduce((e,t)=>e+t.count,0)}},Object:function(e){let t={};for(let n of e)if(!n.circular)for(let e of n.keys)!t[e]&&(t[e]=[]),t[e].push(n.items[e]);let n={type:"Object",keys:[],items:{},count:e.length};for(let e of Object.keys(t))n.keys.push(e),n.items[e]=r(t[e]);return n},Array:function(e){let t=r(e.map(e=>e.items[0]).filter(e=>e));return{count:e.length,items:{0:t},length:t.count/e.length,type:"Array"}}}[t](e)}(n.filter(t=>t.type===e),e)}return{count:0}}},printSummary:function(e,{indentation:t=a.indentation,indentCount:n=a.indentCount,showExampleValue:r=a.showExampleValue,startExpanded:s=a.startExpanded,theme:l=a.theme}=a){return`<div class="theme ${l}"><div class='json-summary-wrapper'>`+function e(a,s){let l="";if(a.circular)l+=u("(circular reference)","circular");else if("Object"===a.type){l+="{";let r=a.keys.map(e=>`'${e}'`).join(", ");l+=u(r,"keys");let o=a.keys.map(t=>e(a.items[t],s+1));if(o.length){let e="\n";for(let r=0;r<a.keys.length;r++)e+=t.repeat((s+1)*n),e+=u(a.keys[r],"name")+": ",a.count>1&&(e+=`<div class="json-summary json-summary-bar" title="${(m=a.items[a.keys[r]].count/a.count*100).toFixed(2)}%"><div class="json-summary json-summary-percentage" style="width:${m}%;"></div></div>`),e+=o[r],r<a.keys.length-1&&(e+=","),e+="\n";e+=t.repeat(s*n),l+=u(e,"child")}l=u(l+="}","layer")}else if("Array"===a.type){if(l+=u(a.count>1?"μ = "+a.length.toFixed(1):a.length,"length")+" [",a.length){let r="Object"===a.items[0].type||"Array"===a.items[0].type;r&&(l+="\n"+t.repeat((s+1)*n)),l+=e(a.items[0],s+1,a.count),r&&(l+="\n"+t.repeat(s*n))}l+="]"}else null==a.example||null==a.example?l+=u("?","type"):l+=u(a.type,"type"),r&&(l+=u(a.example,"value",a.type),a.count>1&&a.range&&(l+=u(a.range,"range",a.type)));var m;return l}(e,0)+"<div></div>";function u(e,t,n){return{type:()=>`<span class="json-summary json-summary-type json-summary-type-${e}">&lt;${e}&gt;</span>`,value:()=>`<span class="json-summary json-summary-value json-summary-value-${n}">${e}</span>`,range:()=>`<span class="json-summary json-summary-range json-summary-range-${n}">[${e[0]}, ${e[1]}]</span>`,name:()=>`<span class="json-summary json-summary-name">${e}</span>`,length:()=>`<span class="json-summary json-summary-length">(${e})</span>`,circular:()=>`<span class="json-summary json-summary-circular">${e}</span>`,layer:()=>`<span class="json-summary json-summary-checkbox ${s?"checked":""}">\n <input type="checkbox" ${s?"checked":""}>\n <span class="json-summary-checkboxmarker" onclick="(function(me){\n me.parentNode.classList.toggle('checked');\n })(this)"></span>\n </span><div class="json-summary json-summary-layer">${e}</div>`,child:()=>`<div class="json-summary json-summary-child">${e}</div>`,keys:()=>`<span class="json-summary json-summary-keys">${e}</span>`}[t]()}}},s=r.defaults,l=r.summarize,u=r.printSummary;e.default=r,e.defaults=s,e.printSummary=u,e.summarize=l,Object.defineProperty(e,"__esModule",{value:!0})});

@@ -1,424 +0,7 @@

const summarizer = (function() {
let defaultOptions = {
arraySampleCount: 10,
indentation: " ", // or "\t"
indentCount: 2,
showExampleValue: true,
startExpanded: false,
theme: "dark"
};
"use strict";
// summarizer utility class
return function({
arraySampleCount = 10,
indentation = " ", // or "\t"
indentCount = 2,
showExampleValue = true,
startExpanded = false,
theme = "dark"
} = defaultOptions) {
let options = {
arraySampleCount,
indentation,
indentCount,
showExampleValue,
startExpanded,
theme
};
// utility function to extract overall json structure without printing entire data object
function summarizeJSON(data) {
let summary = summarizeItem(data);
// clean up the marking
unmarkObject(data);
return summary;
}
function summarizeItem(item) {
let summarize = {
Array: arr => {
let summarized = {
count: 1,
type: "Array",
length: arr.length
};
// recurse to items in the array
if (arr.length) {
if (arraySampleCount > 0) {
let numToSample = Math.min(arraySampleCount, arr.length);
let sampledItems = {};
// summarized.count = numToSample;
while (numToSample > 0) {
let sampleIndex = Math.floor(Math.random() * arr.length);
if (!sampledItems.hasOwnProperty(sampleIndex)) {
sampledItems[sampleIndex] = arr[sampleIndex];
numToSample--;
}
}
let summarizedSamples = [];
for (let [idx, item] of Object.entries(sampledItems)) {
summarizedSamples.push(summarizeItem(item));
}
let joinedSample = joinSampledArray(summarizedSamples);
summarized.items = {
0: joinedSample
};
} else {
// sumamrized.count = 1;
summarized.items = {
0: summarizeItem(arr[0])
};
}
} else {
summarized.items = {
0: undefined
};
}
return summarized;
},
Object: obj => {
let summarized = {
count: 1,
type: "Object",
keys: Object.keys(obj),
items: {}
};
for (let key of summarized.keys) {
summarized.items[key] = summarizeItem(obj[key]);
}
return summarized;
},
Other: data => {
let range;
if (typeof data === "string") {
range = [data.length, data.length];
} else if (typeof data === "number") {
range = [data, data];
}
return {
type: typeof data,
example: data,
count: 1,
range
};
}
};
let type = "Other";
if (item instanceof Array) {
type = "Array";
} else if (item instanceof Object) {
type = "Object";
}
if (item && item["*snippets_mark*"]) {
return {
type: type,
circular: true
};
} else {
// marked as visited to make sure it doesn't hit a circular structure
if (type !== "Other") {
Object.defineProperty(item, "*snippets_mark*", {
enumerable: false,
writable: true,
configurable: true
});
item["*snippets_mark*"] = true;
}
return summarize[type](item);
}
}
function joinSampledArray(itemset) {
// let type = itemset.map(d => d.type)
// .reduce((a, type) => {
// a[type] = [];
// return a;
// }, {});
// for (let item of itemset) {
// type[item.type].push(item);
// }
// let joins = {};
// for (let [t, itemset] of Object.entries(type)) {
// joins[t] = joinItems(itemset, t);
// }
// console.log(joins);
// return
// assume theyre all a matching type
let joinableTypes = {Array: true, Object: true, boolean: true, string: true, number: true};
let items = itemset.filter(i => joinableTypes[i.type]);
if (items.length) {
let type = items[0].type;
return joinItems(items.filter(i => i.type === type), type);
} else {
// idk - no items to join?
return {
count: 0
};
}
}
function joinItems(itemArr, type) {
itemArr = itemArr.filter(i => i.type === type);
// functions to join items by type
let joiner = {
string: function(items) {
// string length range
let min = items.reduce((acc, item) => {
return Math.min(acc, item.range[0]);
}, Infinity);
let max = items.reduce((acc, item) => {
return Math.max(acc, item.range[1]);
}, -Infinity);
let joinedString = {
type: "string",
example: items[0].example,
range: [min, max],
count: items.reduce((a, i) => a + i.count, 0)
};
return joinedString;
},
number: function(items) {
let min = items.reduce((acc, item) => {
return Math.min(acc, item.range[0]);
}, Infinity);
let max = items.reduce((acc, item) => {
return Math.max(acc, item.range[1]);
}, -Infinity);
let joinedNumber = {
type: "number",
example: items[0].example,
range: [min, max],
count: items.reduce((a, i) => a + i.count, 0)
};
return joinedNumber;
},
boolean: function(items) {
return {
type: "boolean",
example: items[0].example,
count: items.reduce((a, i) => a + i.count, 0)
};
},
Object: function(items) {
let masterKeys = {};
for (let obj of items) {
if (!obj.circular) {
for (let key of obj.keys) {
!masterKeys[key] && (masterKeys[key] = []);
masterKeys[key].push(obj.items[key]);
}
}
}
let joinedObject = { type: "Object", keys: [], items: {}, count: items.length };
for (let key of Object.keys(masterKeys)) {
joinedObject.keys.push(key);
joinedObject.items[key] = joinSampledArray(masterKeys[key]);
}
return joinedObject;
},
Array: function(items) {
let joinedValues = joinSampledArray(items.map(i => i.items[0]).filter(i => i));
let joinedArray = {
count: items.length,
items: {
0: joinedValues
},
length: joinedValues.count / items.length,
type: "Array"
};
return joinedArray;
}
};
return joiner[type](itemArr);
}
function unmarkObject(obj) {
if (obj && obj["*snippets_mark*"]) {
delete obj["*snippets_mark*"];
// recurse to the next level
if (obj instanceof Array && obj.length) {
unmarkObject(obj[0]);
} else if (obj instanceof Object) {
for (let key of Object.keys(obj)) {
unmarkObject(obj[key]);
}
}
}
}
// utility function to stringify the summary output from summarizeJSON
function printSummarizedJSON(summary) {
// start at 0 indentation
return `<div class='json-summary-wrapper ${options.theme}'>` + printSummaryLevel(summary, 0, 1);
}
function printSummaryLevel(data, l, prevCount) {
let string = "";
if (data.circular) {
string += wrapInHTML("(circular reference)", "circular");
} else if (data.type === "Object") {
string += "{";
let keys = data.keys.map(k => `'${k}'`).join(", ");
string += wrapInHTML(keys, "keys");
let childStrings = data.keys.map(key => {
return printSummaryLevel(data.items[key], l + 1, data.count);
});
if (childStrings.length) {
let childStringCombined = "\n";
for (let i = 0; i < data.keys.length; i++) {
childStringCombined += options.indentation.repeat(
(l + 1) * options.indentCount
);
childStringCombined += wrapInHTML(data.keys[i], "name") + ": ";
if (data.count > 1) {
childStringCombined += htmlPercentageBar(data.items[data.keys[i]].count / data.count * 100);
}
childStringCombined += childStrings[i];
if (i < data.keys.length - 1) {
childStringCombined += ",";
}
childStringCombined += "\n";
}
childStringCombined += options.indentation.repeat(l * options.indentCount);
string += wrapInHTML(childStringCombined, "child");
}
string += "}";
string = wrapInHTML(string, "layer");
} else if (data.type === "Array") {
// string += "[]";
// string += `[ ${data.length ? `(${data.length}×)` : "∅"} `;
string += wrapInHTML(data.count > 1 ? "μ = " + data.length.toFixed(1) : data.length, "length") + ` [`;
if (data.length) {
let needsNewlines =
data.items["0"].type === "Object" || data.items["0"].type === "Array";
if (needsNewlines) {
string += "\n" + options.indentation.repeat((l + 1) * options.indentCount);
}
string += printSummaryLevel(data.items["0"], l + 1, data.count);
if (needsNewlines) {
string += "\n" + options.indentation.repeat(l * options.indentCount);
}
}
string += "]";
// string = wrapInHTML(string, "layer");
} else {
if (data.example == null || data.example == undefined) {
string += wrapInHTML("?", "type");
} else {
string += wrapInHTML(data.type, "type");
}
if (options.showExampleValue) {
string += wrapInHTML(data.example, "value", data.type);
data.count > 1 && data.range && (string += wrapInHTML(data.range, "range", data.type));
}
}
return string;
}
function wrapInHTML(value, role, type) {
let tags = {
type: () => `<span class="json-summary json-summary-type json-summary-type-${value}">&lt;${value}&gt;</span>`,
value: () => `<span class="json-summary json-summary-value json-summary-value-${type}">${value}</span>`,
range: () => `<span class="json-summary json-summary-range json-summary-range-${type}">[${value[0]}, ${value[1]}]</span>`,
name: () => `<span class="json-summary json-summary-name">${value}</span>`,
length: () => `<span class="json-summary json-summary-length">(${value})</span>`,
circular: () => `<span class="json-summary json-summary-circular">${value}</span>`,
layer: () => `<span class="json-summary json-summary-checkbox ${
options.startExpanded ? "checked" : ""
}">
<input type="checkbox" ${
options.startExpanded ? "checked" : ""
}>
<span class="json-summary-checkboxmarker" onclick="(function(me){
me.parentNode.classList.toggle('checked');
})(this)"></span>
</span><div class="json-summary json-summary-layer">${value}</div>`,
child: () => `<div class="json-summary json-summary-child">${value}</div>`,
keys: () => `<span class="json-summary json-summary-keys">${value}</span>`
};
return tags[role]();
}
function htmlPercentageBar(percentage) {
return `<div class="json-summary json-summary-bar" title="${percentage.toFixed(2)}%"><div class="json-summary json-summary-percentage" style="width:${percentage}%;"></div></div>`
}
return {
summarize: summarizeJSON,
printSummary: printSummarizedJSON
};
}
}());
module.exports = summarizer;
module.exports = {
defaults: require("./src/defaults"),
summarize: require("./src/summarize"),
printSummary: require("./src/printSummary")
};
{
"name": "json-summary",
"version": "0.2.5",
"version": "1.0.0",
"description": "A simple JSON summarizer to extract the structure from a JSON object",

@@ -12,6 +12,5 @@ "keywords": [

"main": "index.js",
"module": "dist/json-summary.esm.js",
"browser": "dist/json-summary.js",
"browserMin": "dist/json-summary.min.js",
"files":[
"files": [
"/dist",

@@ -24,3 +23,3 @@ "index.js"

"prepublish": "npm run build && npm test",
"build": "rollup -c && cp dist/json-summary.js docs/json-summary.js && cp summarizer.css docs/summarizer.css"
"build": "rollup -c && cp dist/json-summary.js docs/json-summary.js && sass style/main.scss dist/summarizer.css && cp dist/summarizer.css docs/summarizer.css"
},

@@ -42,2 +41,3 @@ "repository": {

"coveralls": "^3.0.3",
"eslint": "^5.16.0",
"jest": "^24.7.1",

@@ -47,5 +47,7 @@ "rollup": "^1.9.0",

"rollup-plugin-node-resolve": "^4.2.1",
"rollup-plugin-terser": "^4.0.4"
"rollup-plugin-terser": "^4.0.4",
"sass": "^1.18.0"
},
"dependencies": {}
"dependencies": {},
"eslintConfig": "./.eslintrc.json"
}
# json-summary
[![npm version](https://img.shields.io/travis/com/AndrewTBurks/json-summary.svg)](https://www.npmjs.com/package/json-summary)
[![npm downloads](https://img.shields.io/npm/v/json-summary.svg)](https://www.npmjs.com/package/json-summary)
[![npm downloads](https://img.shields.io/npm/dt/json-summary.svg)](https://www.npmjs.com/package/json-summary)
[![Coverage Status](https://coveralls.io/repos/github/AndrewTBurks/json-summary/badge.svg?branch=master)](https://coveralls.io/github/AndrewTBurks/json-summary?branch=master)
[![Travis (.com)](https://img.shields.io/travis/com/AndrewTBurks/json-summary.svg?style=for-the-badge)](https://www.npmjs.com/package/json-summary)
[![npm version](https://img.shields.io/npm/v/json-summary.svg?style=for-the-badge)](https://www.npmjs.com/package/json-summary)
[![npm downloads](https://img.shields.io/npm/dt/json-summary.svg?style=for-the-badge)](https://www.npmjs.com/package/json-summary)
[![npm bundle size](https://img.shields.io/bundlephobia/min/json-summary.svg?style=for-the-badge)](https://www.npmjs.com/package/json-summary)
[![Coveralls github](https://img.shields.io/coveralls/github/AndrewTBurks/json-summary.svg?style=for-the-badge)](https://coveralls.io/github/AndrewTBurks/json-summary?branch=master)

@@ -8,0 +9,0 @@

Sorry, the diff of this file is not supported yet

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