|
|
@@ -1,453 +0,0 @@
|
|
|
-// import {
|
|
|
-// isObject,
|
|
|
-// getObjectName,
|
|
|
-// getType,
|
|
|
-// getValuePreview,
|
|
|
-// getPreview,
|
|
|
-// cssClass,
|
|
|
-// createElement
|
|
|
-// } from './helpers';
|
|
|
-//
|
|
|
-// import './style.less';
|
|
|
-//
|
|
|
-// const DATE_STRING_REGEX = /(^\d{1,4}[\.|\\/|-]\d{1,2}[\.|\\/|-]\d{1,4})(\s*(?:0?[1-9]:[0-5]|1(?=[012])\d:[0-5])\d\s*[ap]m)?$/;
|
|
|
-// const PARTIAL_DATE_REGEX = /\d{2}:\d{2}:\d{2} GMT-\d{4}/;
|
|
|
-// const JSON_DATE_REGEX = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/;
|
|
|
-//
|
|
|
-// // When toggleing, don't animated removal or addition of more than a few items
|
|
|
-// const MAX_ANIMATED_TOGGLE_ITEMS = 10;
|
|
|
-//
|
|
|
-// const requestAnimationFrame = window.requestAnimationFrame || function(cb: ()=>void) { cb(); return 0; };
|
|
|
-//
|
|
|
-// export interface JSONFormatterConfiguration {
|
|
|
-// hoverPreviewEnabled?: boolean;
|
|
|
-// hoverPreviewArrayCount?: number;
|
|
|
-// hoverPreviewFieldCount?: number;
|
|
|
-// animateOpen?: boolean;
|
|
|
-// animateClose?: boolean;
|
|
|
-// theme?: string;
|
|
|
-// };
|
|
|
-//
|
|
|
-// const _defaultConfig: JSONFormatterConfiguration = {
|
|
|
-// hoverPreviewEnabled: false,
|
|
|
-// hoverPreviewArrayCount: 100,
|
|
|
-// hoverPreviewFieldCount: 5,
|
|
|
-// animateOpen: true,
|
|
|
-// animateClose: true,
|
|
|
-// theme: null
|
|
|
-// };
|
|
|
-//
|
|
|
-//
|
|
|
-// #<{(|*
|
|
|
-// * @class JSONFormatter
|
|
|
-// *
|
|
|
-// * JSONFormatter allows you to render JSON objects in HTML with a
|
|
|
-// * **collapsible** navigation.
|
|
|
-// |)}>#
|
|
|
-// export default class JSONFormatter {
|
|
|
-//
|
|
|
-// // Hold the open state after the toggler is used
|
|
|
-// private _isOpen: boolean = null;
|
|
|
-//
|
|
|
-// // A reference to the element that we render to
|
|
|
-// private element: Element;
|
|
|
-//
|
|
|
-// #<{(|*
|
|
|
-// * @param {object} json The JSON object you want to render. It has to be an
|
|
|
-// * object or array. Do NOT pass raw JSON string.
|
|
|
-// *
|
|
|
-// * @param {number} [open=1] his number indicates up to how many levels the
|
|
|
-// * rendered tree should expand. Set it to `0` to make the whole tree collapsed
|
|
|
-// * or set it to `Infinity` to expand the tree deeply
|
|
|
-// *
|
|
|
-// * @param {object} [config=defaultConfig] -
|
|
|
-// * defaultConfig = {
|
|
|
-// * hoverPreviewEnabled: false,
|
|
|
-// * hoverPreviewArrayCount: 100,
|
|
|
-// * hoverPreviewFieldCount: 5
|
|
|
-// * }
|
|
|
-// *
|
|
|
-// * Available configurations:
|
|
|
-// * #####Hover Preview
|
|
|
-// * * `hoverPreviewEnabled`: enable preview on hover
|
|
|
-// * * `hoverPreviewArrayCount`: number of array items to show in preview Any
|
|
|
-// * array larger than this number will be shown as `Array[XXX]` where `XXX`
|
|
|
-// * is length of the array.
|
|
|
-// * * `hoverPreviewFieldCount`: number of object properties to show for object
|
|
|
-// * preview. Any object with more properties that thin number will be
|
|
|
-// * truncated.
|
|
|
-// *
|
|
|
-// * @param {string} [key=undefined] The key that this object in it's parent
|
|
|
-// * context
|
|
|
-// |)}>#
|
|
|
-// constructor(public json: any, private open = 1, private config: JSONFormatterConfiguration = _defaultConfig, private key?: string) {
|
|
|
-//
|
|
|
-// // Setting default values for config object
|
|
|
-// if (this.config.hoverPreviewEnabled === undefined) {
|
|
|
-// this.config.hoverPreviewEnabled = _defaultConfig.hoverPreviewEnabled;
|
|
|
-// }
|
|
|
-// if (this.config.hoverPreviewArrayCount === undefined) {
|
|
|
-// this.config.hoverPreviewArrayCount = _defaultConfig.hoverPreviewArrayCount;
|
|
|
-// }
|
|
|
-// if (this.config.hoverPreviewFieldCount === undefined) {
|
|
|
-// this.config.hoverPreviewFieldCount = _defaultConfig.hoverPreviewFieldCount;
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|
|
|
|
-// * is formatter open?
|
|
|
-// |)}>#
|
|
|
-// private get isOpen(): boolean {
|
|
|
-// if (this._isOpen !== null) {
|
|
|
-// return this._isOpen;
|
|
|
-// } else {
|
|
|
-// return this.open > 0;
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|
|
|
|
-// * set open state (from toggler)
|
|
|
-// |)}>#
|
|
|
-// private set isOpen(value: boolean) {
|
|
|
-// this._isOpen = value;
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|
|
|
|
-// * is this a date string?
|
|
|
-// |)}>#
|
|
|
-// private get isDate(): boolean {
|
|
|
-// return (this.type === 'string') &&
|
|
|
-// (DATE_STRING_REGEX.test(this.json) ||
|
|
|
-// JSON_DATE_REGEX.test(this.json) ||
|
|
|
-// PARTIAL_DATE_REGEX.test(this.json));
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|
|
|
|
-// * is this a URL string?
|
|
|
-// |)}>#
|
|
|
-// private get isUrl(): boolean {
|
|
|
-// return this.type === 'string' && (this.json.indexOf('http') === 0);
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|
|
|
|
-// * is this an array?
|
|
|
-// |)}>#
|
|
|
-// private get isArray(): boolean {
|
|
|
-// return Array.isArray(this.json);
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|
|
|
|
-// * is this an object?
|
|
|
-// * Note: In this context arrays are object as well
|
|
|
-// |)}>#
|
|
|
-// private get isObject(): boolean {
|
|
|
-// return isObject(this.json);
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|
|
|
|
-// * is this an empty object with no properties?
|
|
|
-// |)}>#
|
|
|
-// private get isEmptyObject(): boolean {
|
|
|
-// return !this.keys.length && !this.isArray;
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|
|
|
|
-// * is this an empty object or array?
|
|
|
-// |)}>#
|
|
|
-// private get isEmpty(): boolean {
|
|
|
-// return this.isEmptyObject || (this.keys && !this.keys.length && this.isArray);
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|
|
|
|
-// * did we recieve a key argument?
|
|
|
-// * This means that the formatter was called as a sub formatter of a parent formatter
|
|
|
-// |)}>#
|
|
|
-// private get hasKey(): boolean {
|
|
|
-// return typeof this.key !== 'undefined';
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|
|
|
|
-// * if this is an object, get constructor function name
|
|
|
-// |)}>#
|
|
|
-// private get constructorName(): string {
|
|
|
-// return getObjectName(this.json);
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|
|
|
|
-// * get type of this value
|
|
|
-// * Possible values: all JavaScript primitive types plus "array" and "null"
|
|
|
-// |)}>#
|
|
|
-// private get type(): string {
|
|
|
-// return getType(this.json);
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|
|
|
|
-// * get object keys
|
|
|
-// * If there is an empty key we pad it wit quotes to make it visible
|
|
|
-// |)}>#
|
|
|
-// private get keys(): string[] {
|
|
|
-// if (this.isObject) {
|
|
|
-// return Object.keys(this.json).map((key)=> key ? key : '""');
|
|
|
-// } else {
|
|
|
-// return [];
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|*
|
|
|
-// * Toggles `isOpen` state
|
|
|
-// *
|
|
|
-// |)}>#
|
|
|
-// toggleOpen() {
|
|
|
-// this.isOpen = !this.isOpen;
|
|
|
-//
|
|
|
-// if (this.element) {
|
|
|
-// if (this.isOpen) {
|
|
|
-// this.appendChildren(this.config.animateOpen);
|
|
|
-// } else{
|
|
|
-// this.removeChildren(this.config.animateClose);
|
|
|
-// }
|
|
|
-// this.element.classList.toggle(cssClass('open'));
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|*
|
|
|
-// * Open all children up to a certain depth.
|
|
|
-// * Allows actions such as expand all/collapse all
|
|
|
-// *
|
|
|
-// |)}>#
|
|
|
-// openAtDepth(depth = 1) {
|
|
|
-// if (depth < 0) {
|
|
|
-// return;
|
|
|
-// }
|
|
|
-//
|
|
|
-// this.open = depth;
|
|
|
-// this.isOpen = (depth !== 0);
|
|
|
-//
|
|
|
-// if (this.element) {
|
|
|
-// this.removeChildren(false);
|
|
|
-//
|
|
|
-// if (depth === 0) {
|
|
|
-// this.element.classList.remove(cssClass('open'));
|
|
|
-// } else {
|
|
|
-// this.appendChildren(this.config.animateOpen);
|
|
|
-// this.element.classList.add(cssClass('open'));
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|*
|
|
|
-// * Generates inline preview
|
|
|
-// *
|
|
|
-// * @returns {string}
|
|
|
-// |)}>#
|
|
|
-// getInlinepreview() {
|
|
|
-// if (this.isArray) {
|
|
|
-//
|
|
|
-// // if array length is greater then 100 it shows "Array[101]"
|
|
|
-// if (this.json.length > this.config.hoverPreviewArrayCount) {
|
|
|
-// return `Array[${this.json.length}]`;
|
|
|
-// } else {
|
|
|
-// return `[${this.json.map(getPreview).join(', ')}]`;
|
|
|
-// }
|
|
|
-// } else {
|
|
|
-//
|
|
|
-// const keys = this.keys;
|
|
|
-//
|
|
|
-// // the first five keys (like Chrome Developer Tool)
|
|
|
-// const narrowKeys = keys.slice(0, this.config.hoverPreviewFieldCount);
|
|
|
-//
|
|
|
-// // json value schematic information
|
|
|
-// const kvs = narrowKeys.map(key => `${key}:${getPreview(this.json[key])}`);
|
|
|
-//
|
|
|
-// // if keys count greater then 5 then show ellipsis
|
|
|
-// const ellipsis = keys.length >= this.config.hoverPreviewFieldCount ? '…' : '';
|
|
|
-//
|
|
|
-// return `{${kvs.join(', ')}${ellipsis}}`;
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-//
|
|
|
-// #<{(|*
|
|
|
-// * Renders an HTML element and installs event listeners
|
|
|
-// *
|
|
|
-// * @returns {HTMLDivElement}
|
|
|
-// |)}>#
|
|
|
-// render(): HTMLDivElement {
|
|
|
-//
|
|
|
-// // construct the root element and assign it to this.element
|
|
|
-// this.element = createElement('div', 'row');
|
|
|
-//
|
|
|
-// // construct the toggler link
|
|
|
-// const togglerLink = createElement('a', 'toggler-link');
|
|
|
-//
|
|
|
-// // if this is an object we need a wrapper span (toggler)
|
|
|
-// if (this.isObject) {
|
|
|
-// togglerLink.appendChild(createElement('span', 'toggler'));
|
|
|
-// }
|
|
|
-//
|
|
|
-// // if this is child of a parent formatter we need to append the key
|
|
|
-// if (this.hasKey) {
|
|
|
-// togglerLink.appendChild(createElement('span', 'key', `${this.key}:`));
|
|
|
-// }
|
|
|
-//
|
|
|
-// // Value for objects and arrays
|
|
|
-// if (this.isObject) {
|
|
|
-//
|
|
|
-// // construct the value holder element
|
|
|
-// const value = createElement('span', 'value');
|
|
|
-//
|
|
|
-// // we need a wrapper span for objects
|
|
|
-// const objectWrapperSpan = createElement('span');
|
|
|
-//
|
|
|
-// // get constructor name and append it to wrapper span
|
|
|
-// var constructorName = createElement('span', 'constructor-name', this.constructorName);
|
|
|
-// objectWrapperSpan.appendChild(constructorName);
|
|
|
-//
|
|
|
-// // if it's an array append the array specific elements like brackets and length
|
|
|
-// if (this.isArray) {
|
|
|
-// const arrayWrapperSpan = createElement('span');
|
|
|
-// arrayWrapperSpan.appendChild(createElement('span', 'bracket', '['));
|
|
|
-// arrayWrapperSpan.appendChild(createElement('span', 'number', (this.json.length)));
|
|
|
-// arrayWrapperSpan.appendChild(createElement('span', 'bracket', ']'));
|
|
|
-// objectWrapperSpan.appendChild(arrayWrapperSpan);
|
|
|
-// }
|
|
|
-//
|
|
|
-// // append object wrapper span to toggler link
|
|
|
-// value.appendChild(objectWrapperSpan);
|
|
|
-// togglerLink.appendChild(value);
|
|
|
-//
|
|
|
-// // Primitive values
|
|
|
-// } else {
|
|
|
-//
|
|
|
-// // make a value holder element
|
|
|
-// const value = this.isUrl ? createElement('a') : createElement('span');
|
|
|
-//
|
|
|
-// // add type and other type related CSS classes
|
|
|
-// value.classList.add(cssClass(this.type));
|
|
|
-// if (this.isDate) {
|
|
|
-// value.classList.add(cssClass('date'));
|
|
|
-// }
|
|
|
-// if (this.isUrl) {
|
|
|
-// value.classList.add(cssClass('url'));
|
|
|
-// value.setAttribute('href', this.json);
|
|
|
-// }
|
|
|
-//
|
|
|
-// // Append value content to value element
|
|
|
-// const valuePreview = getValuePreview(this.json, this.json);
|
|
|
-// value.appendChild(document.createTextNode(valuePreview));
|
|
|
-//
|
|
|
-// // append the value element to toggler link
|
|
|
-// togglerLink.appendChild(value);
|
|
|
-// }
|
|
|
-//
|
|
|
-// // if hover preview is enabled, append the inline preview element
|
|
|
-// if (this.isObject && this.config.hoverPreviewEnabled) {
|
|
|
-// const preview = createElement('span', 'preview-text');
|
|
|
-// preview.appendChild(document.createTextNode(this.getInlinepreview()));
|
|
|
-// togglerLink.appendChild(preview);
|
|
|
-// }
|
|
|
-//
|
|
|
-// // construct a children element
|
|
|
-// const children = createElement('div', 'children');
|
|
|
-//
|
|
|
-// // set CSS classes for children
|
|
|
-// if (this.isObject) {
|
|
|
-// children.classList.add(cssClass('object'));
|
|
|
-// }
|
|
|
-// if (this.isArray) {
|
|
|
-// children.classList.add(cssClass('array'));
|
|
|
-// }
|
|
|
-// if (this.isEmpty) {
|
|
|
-// children.classList.add(cssClass('empty'));
|
|
|
-// }
|
|
|
-//
|
|
|
-// // set CSS classes for root element
|
|
|
-// if (this.config && this.config.theme) {
|
|
|
-// this.element.classList.add(cssClass(this.config.theme));
|
|
|
-// }
|
|
|
-// if (this.isOpen) {
|
|
|
-// this.element.classList.add(cssClass('open'));
|
|
|
-// }
|
|
|
-//
|
|
|
-// // append toggler and children elements to root element
|
|
|
-// this.element.appendChild(togglerLink);
|
|
|
-// this.element.appendChild(children);
|
|
|
-//
|
|
|
-// // if formatter is set to be open call appendChildren
|
|
|
-// if (this.isObject && this.isOpen) {
|
|
|
-// this.appendChildren();
|
|
|
-// }
|
|
|
-//
|
|
|
-// // add event listener for toggling
|
|
|
-// if (this.isObject) {
|
|
|
-// togglerLink.addEventListener('click', this.toggleOpen.bind(this));
|
|
|
-// }
|
|
|
-//
|
|
|
-// return this.element as HTMLDivElement;
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|*
|
|
|
-// * Appends all the children to children element
|
|
|
-// * Animated option is used when user triggers this via a click
|
|
|
-// |)}>#
|
|
|
-// appendChildren(animated = false) {
|
|
|
-// const children = this.element.querySelector(`div.${cssClass('children')}`);
|
|
|
-//
|
|
|
-// if (!children || this.isEmpty) { return; }
|
|
|
-//
|
|
|
-// if (animated) {
|
|
|
-// let index = 0;
|
|
|
-// const addAChild = ()=> {
|
|
|
-// const key = this.keys[index];
|
|
|
-// const formatter = new JSONFormatter(this.json[key], this.open - 1, this.config, key);
|
|
|
-// children.appendChild(formatter.render());
|
|
|
-//
|
|
|
-// index += 1;
|
|
|
-//
|
|
|
-// if (index < this.keys.length) {
|
|
|
-// if (index > MAX_ANIMATED_TOGGLE_ITEMS) {
|
|
|
-// addAChild();
|
|
|
-// } else {
|
|
|
-// requestAnimationFrame(addAChild);
|
|
|
-// }
|
|
|
-// }
|
|
|
-// };
|
|
|
-//
|
|
|
-// requestAnimationFrame(addAChild);
|
|
|
-//
|
|
|
-// } else {
|
|
|
-// this.keys.forEach(key => {
|
|
|
-// const formatter = new JSONFormatter(this.json[key], this.open - 1, this.config, key);
|
|
|
-// children.appendChild(formatter.render());
|
|
|
-// });
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// #<{(|*
|
|
|
-// * Removes all the children from children element
|
|
|
-// * Animated option is used when user triggers this via a click
|
|
|
-// |)}>#
|
|
|
-// removeChildren(animated = false) {
|
|
|
-// const childrenElement = this.element.querySelector(`div.${cssClass('children')}`) as HTMLDivElement;
|
|
|
-//
|
|
|
-// if (animated) {
|
|
|
-// let childrenRemoved = 0;
|
|
|
-// const removeAChild = ()=> {
|
|
|
-// if (childrenElement && childrenElement.children.length) {
|
|
|
-// childrenElement.removeChild(childrenElement.children[0]);
|
|
|
-// childrenRemoved += 1;
|
|
|
-// if (childrenRemoved > MAX_ANIMATED_TOGGLE_ITEMS) {
|
|
|
-// removeAChild();
|
|
|
-// } else {
|
|
|
-// requestAnimationFrame(removeAChild);
|
|
|
-// }
|
|
|
-// }
|
|
|
-// };
|
|
|
-// requestAnimationFrame(removeAChild);
|
|
|
-// } else {
|
|
|
-// if (childrenElement) {
|
|
|
-// childrenElement.innerHTML = '';
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|