@covalent/core
Version:
Core Teradata UI Platform for layouts, icons, custom components and themes. This should be added as a dependency for any project that wants to use layouts, icons and themes for Angular Material.
222 lines • 31.7 kB
JavaScript
import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef, Optional, } from '@angular/core';
import { Dir } from '@angular/cdk/bidi';
import { tdCollapseAnimation } from './collapse.animation';
import * as i0 from "@angular/core";
import * as i1 from "@angular/cdk/bidi";
import * as i2 from "@angular/common";
import * as i3 from "@angular/material/tooltip";
import * as i4 from "@angular/material/icon";
export class TdJsonFormatterComponent {
_changeDetectorRef;
_dir;
/**
* Max length for property names. Any names bigger than this get trunctated.
*/
static KEY_MAX_LENGTH = 30;
/**
* Max length for preview string. Any names bigger than this get trunctated.
*/
static PREVIEW_STRING_MAX_LENGTH = 80;
/**
* Max tooltip preview elements.
*/
static PREVIEW_LIMIT = 5;
_key;
_data;
_children;
_open = false;
_levelsOpen = 0;
/**
* levelsOpen?: number
* Levels opened by default when JS object is formatted and rendered.
*/
set levelsOpen(levelsOpen) {
if (!Number.isInteger(levelsOpen)) {
throw new Error('[levelsOpen] needs to be an integer.');
}
this._levelsOpen = levelsOpen;
this._open = levelsOpen > 0;
}
get levelsOpen() {
return this._levelsOpen;
}
get open() {
return this._open;
}
/**
* key?: string
* Tag to be displayed next to formatted object.
*/
set key(key) {
this._key = key;
}
get key() {
const elipsis = this._key && this._key.length > TdJsonFormatterComponent.KEY_MAX_LENGTH
? '…'
: '';
return this._key
? this._key.substring(0, TdJsonFormatterComponent.KEY_MAX_LENGTH) +
elipsis
: this._key ?? '';
}
/**
* data: any
* JS object to be formatted.
*/
set data(data) {
this._data = data;
this.parseChildren();
}
get data() {
return this._data;
}
get children() {
return this._children ?? [];
}
get isRTL() {
if (this._dir) {
return this._dir.dir === 'rtl';
}
return false;
}
constructor(_changeDetectorRef, _dir) {
this._changeDetectorRef = _changeDetectorRef;
this._dir = _dir;
}
/**
* Refreshes json-formatter and rerenders [data]
*/
refresh() {
this._changeDetectorRef.markForCheck();
}
/**
* Toggles collapse/expanded state of component.
*/
toggle() {
this._open = !this._open;
}
isObject() {
return this.getType(this._data) === 'object';
}
isArray() {
return Array.isArray(this._data);
}
hasChildren() {
return (this._children && this._children.length > 0) ?? false;
}
/**
* Gets parsed value depending on value type.
*/
getValue(value) {
const type = this.getType(value);
if (type === 'undefined' || type === 'null') {
return type;
}
else if (type === 'date') {
value = new Date(value).toString();
}
else if (type === 'string') {
value = '"' + value + '"';
}
else if (type === 'function') {
// Remove content of the function
return (value
.toString()
.replace(/[\r\n]/g, '')
.replace(/\{.*\}/, '') + '{…}');
}
else if (Array.isArray(value)) {
return this.getObjectName() + ' [' + value.length + ']';
}
return value;
}
/**
* Gets type of object.
* returns 'null' if object is null and 'date' if value is object and can be parsed to a date.
*/
getType(object) {
if (typeof object === 'object') {
if (!object) {
return 'null';
}
if (Array.isArray(object)) {
return 'object';
}
const date = new Date(object);
if (Object.prototype.toString.call(date) === '[object Date]' &&
!Number.isNaN(date.getTime())) {
return 'date';
}
}
return typeof object;
}
/**
* Generates string representation depending if its an object or function.
* see: http://stackoverflow.com/a/332429
*/
getObjectName() {
const object = this._data;
if (this.isObject() && !object.constructor) {
return 'Object';
}
const funcNameRegex = /function (.{1,})\(/;
const results = funcNameRegex.exec(object.constructor.toString());
if (results && results.length > 1) {
return results[1];
}
else {
return '';
}
}
/**
* Creates preview of nodes children to render in tooltip depending if its an array or an object.
*/
getPreview() {
let previewData;
let startChar = '{ ';
let endChar = ' }';
if (this.isArray()) {
const previewArray = Object.entries(this._data).slice(0, TdJsonFormatterComponent.PREVIEW_LIMIT) ?? [];
previewData = previewArray.map((obj) => {
return this.getValue(obj);
});
startChar = '[';
endChar = ']';
}
else {
const previewKeys = this._children?.slice(0, TdJsonFormatterComponent.PREVIEW_LIMIT) ?? [];
previewData = previewKeys.map((key) => {
return key + ': ' + this.getValue(this._data[key] ?? undefined);
});
}
const previewString = previewData.join(', ');
const ellipsis = previewData.length >= TdJsonFormatterComponent.PREVIEW_LIMIT ||
previewString.length > TdJsonFormatterComponent.PREVIEW_STRING_MAX_LENGTH
? '…'
: '';
return (startChar +
previewString.substring(0, TdJsonFormatterComponent.PREVIEW_STRING_MAX_LENGTH) +
ellipsis +
endChar);
}
parseChildren() {
if (this.isObject()) {
this._children = Object.keys(this._data ?? {});
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: TdJsonFormatterComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.Dir, optional: true }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.2", type: TdJsonFormatterComponent, selector: "td-json-formatter", inputs: { levelsOpen: "levelsOpen", key: "key", data: "data" }, ngImport: i0, template: "<div class=\"td-json-formatter-wrapper\">\n <a\n class=\"td-key\"\n [class.td-key-node]=\"hasChildren()\"\n [class.td-key-leaf]=\"!hasChildren()\"\n [tabIndex]=\"isObject() ? 0 : -1\"\n (keydown.enter)=\"toggle()\"\n (click)=\"toggle()\"\n >\n <mat-icon class=\"td-node-icon\" *ngIf=\"hasChildren()\">\n {{\n open\n ? 'keyboard_arrow_down'\n : isRTL\n ? 'keyboard_arrow_left'\n : 'keyboard_arrow_right'\n }}\n </mat-icon>\n <span *ngIf=\"key\" class=\"key\">{{ key }}:</span>\n <span class=\"value\">\n <span\n [class.td-empty]=\"!hasChildren()\"\n *ngIf=\"isObject()\"\n [matTooltip]=\"getPreview()\"\n matTooltipPosition=\"after\"\n >\n <span class=\"td-object-name\">{{ getObjectName() }}</span>\n <span class=\"td-array-length\" *ngIf=\"isArray()\"\n >[{{ data['length'] }}]</span\n >\n </span>\n <span *ngIf=\"!isObject()\" [class]=\"getType(data)\">{{\n getValue(data)\n }}</span>\n </span>\n </a>\n <div class=\"td-object-children\" [@tdCollapse]=\"!(hasChildren() && open)\">\n <ng-template let-key ngFor [ngForOf]=\"children\">\n <td-json-formatter\n [key]=\"key\"\n [data]=\"data[key]\"\n [levelsOpen]=\"levelsOpen - 1\"\n ></td-json-formatter>\n </ng-template>\n </div>\n</div>\n", styles: [":host{display:block}.td-json-formatter-wrapper{padding-top:2px;padding-bottom:2px}.td-json-formatter-wrapper .td-key{box-sizing:border-box;display:flex;flex-direction:row;align-items:flex-start;align-content:center;max-width:100%;justify-content:flex-start}.td-json-formatter-wrapper .td-key.td-key-node:hover{cursor:pointer}.td-json-formatter-wrapper .td-object-children.ng-animating{overflow:hidden}.td-json-formatter-wrapper .td-object-children .td-key,.td-json-formatter-wrapper .td-object-children .td-object-children{padding-left:24px}::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-key,::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-object-children{padding-right:24px;padding-left:0}.td-json-formatter-wrapper .td-object-children .td-key.td-key-leaf,.td-json-formatter-wrapper .td-object-children .td-object-children.td-key-leaf{padding-left:48px}::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-key.td-key-leaf,::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-object-children.td-key-leaf{padding-right:48px;padding-left:0}.td-json-formatter-wrapper .value{margin-left:5px}::ng-deep [dir=rtl] .td-json-formatter-wrapper .value{padding-right:5px;padding-left:0}.td-json-formatter-wrapper .value .td-empty{opacity:.5;text-decoration:line-through}.td-json-formatter-wrapper .value .string,.td-json-formatter-wrapper .value .date{word-break:break-word}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: TdJsonFormatterComponent, selector: "td-json-formatter", inputs: ["levelsOpen", "key", "data"] }], animations: [tdCollapseAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: TdJsonFormatterComponent, decorators: [{
type: Component,
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'td-json-formatter', animations: [tdCollapseAnimation], template: "<div class=\"td-json-formatter-wrapper\">\n <a\n class=\"td-key\"\n [class.td-key-node]=\"hasChildren()\"\n [class.td-key-leaf]=\"!hasChildren()\"\n [tabIndex]=\"isObject() ? 0 : -1\"\n (keydown.enter)=\"toggle()\"\n (click)=\"toggle()\"\n >\n <mat-icon class=\"td-node-icon\" *ngIf=\"hasChildren()\">\n {{\n open\n ? 'keyboard_arrow_down'\n : isRTL\n ? 'keyboard_arrow_left'\n : 'keyboard_arrow_right'\n }}\n </mat-icon>\n <span *ngIf=\"key\" class=\"key\">{{ key }}:</span>\n <span class=\"value\">\n <span\n [class.td-empty]=\"!hasChildren()\"\n *ngIf=\"isObject()\"\n [matTooltip]=\"getPreview()\"\n matTooltipPosition=\"after\"\n >\n <span class=\"td-object-name\">{{ getObjectName() }}</span>\n <span class=\"td-array-length\" *ngIf=\"isArray()\"\n >[{{ data['length'] }}]</span\n >\n </span>\n <span *ngIf=\"!isObject()\" [class]=\"getType(data)\">{{\n getValue(data)\n }}</span>\n </span>\n </a>\n <div class=\"td-object-children\" [@tdCollapse]=\"!(hasChildren() && open)\">\n <ng-template let-key ngFor [ngForOf]=\"children\">\n <td-json-formatter\n [key]=\"key\"\n [data]=\"data[key]\"\n [levelsOpen]=\"levelsOpen - 1\"\n ></td-json-formatter>\n </ng-template>\n </div>\n</div>\n", styles: [":host{display:block}.td-json-formatter-wrapper{padding-top:2px;padding-bottom:2px}.td-json-formatter-wrapper .td-key{box-sizing:border-box;display:flex;flex-direction:row;align-items:flex-start;align-content:center;max-width:100%;justify-content:flex-start}.td-json-formatter-wrapper .td-key.td-key-node:hover{cursor:pointer}.td-json-formatter-wrapper .td-object-children.ng-animating{overflow:hidden}.td-json-formatter-wrapper .td-object-children .td-key,.td-json-formatter-wrapper .td-object-children .td-object-children{padding-left:24px}::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-key,::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-object-children{padding-right:24px;padding-left:0}.td-json-formatter-wrapper .td-object-children .td-key.td-key-leaf,.td-json-formatter-wrapper .td-object-children .td-object-children.td-key-leaf{padding-left:48px}::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-key.td-key-leaf,::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-object-children.td-key-leaf{padding-right:48px;padding-left:0}.td-json-formatter-wrapper .value{margin-left:5px}::ng-deep [dir=rtl] .td-json-formatter-wrapper .value{padding-right:5px;padding-left:0}.td-json-formatter-wrapper .value .td-empty{opacity:.5;text-decoration:line-through}.td-json-formatter-wrapper .value .string,.td-json-formatter-wrapper .value .date{word-break:break-word}\n"] }]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.Dir, decorators: [{
type: Optional
}] }], propDecorators: { levelsOpen: [{
type: Input
}], key: [{
type: Input
}], data: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvbi1mb3JtYXR0ZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy9hbmd1bGFyL2pzb24tZm9ybWF0dGVyL3NyYy9qc29uLWZvcm1hdHRlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9saWJzL2FuZ3VsYXIvanNvbi1mb3JtYXR0ZXIvc3JjL2pzb24tZm9ybWF0dGVyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsS0FBSyxFQUNMLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsUUFBUSxHQUNULE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN4QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7Ozs7O0FBUzNELE1BQU0sT0FBTyx3QkFBd0I7SUFzRnpCO0lBQ1k7SUF0RnRCOztPQUVHO0lBQ0ssTUFBTSxDQUFDLGNBQWMsR0FBRyxFQUFFLENBQUM7SUFFbkM7O09BRUc7SUFDSyxNQUFNLENBQUMseUJBQXlCLEdBQUcsRUFBRSxDQUFDO0lBRTlDOztPQUVHO0lBQ0ssTUFBTSxDQUFDLGFBQWEsR0FBRyxDQUFDLENBQUM7SUFFekIsSUFBSSxDQUFVO0lBQ2QsS0FBSyxDQUF1QjtJQUM1QixTQUFTLENBQVk7SUFDckIsS0FBSyxHQUFHLEtBQUssQ0FBQztJQUNkLFdBQVcsR0FBRyxDQUFDLENBQUM7SUFFeEI7OztPQUdHO0lBQ0gsSUFDSSxVQUFVLENBQUMsVUFBa0I7UUFDL0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztZQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7UUFDMUQsQ0FBQztRQUNELElBQUksQ0FBQyxXQUFXLEdBQUcsVUFBVSxDQUFDO1FB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QyxtQkFBbUIsQ0FBQzs7MEJBeUY5QixRQUFRO3lDQTVEUCxVQUFVO3NCQURiLEtBQUs7Z0JBcUJGLEdBQUc7c0JBRE4sS0FBSztnQkFvQkYsSUFBSTtzQkFEUCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBJbnB1dCxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBPcHRpb25hbCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBEaXIgfSBmcm9tICdAYW5ndWxhci9jZGsvYmlkaSc7XG5pbXBvcnQgeyB0ZENvbGxhcHNlQW5pbWF0aW9uIH0gZnJvbSAnLi9jb2xsYXBzZS5hbmltYXRpb24nO1xuXG5AQ29tcG9uZW50KHtcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHNlbGVjdG9yOiAndGQtanNvbi1mb3JtYXR0ZXInLFxuICBzdHlsZVVybHM6IFsnLi9qc29uLWZvcm1hdHRlci5jb21wb25lbnQuc2NzcyddLFxuICB0ZW1wbGF0ZVVybDogJy4vanNvbi1mb3JtYXR0ZXIuY29tcG9uZW50Lmh0bWwnLFxuICBhbmltYXRpb25zOiBbdGRDb2xsYXBzZUFuaW1hdGlvbl0sXG59KVxuZXhwb3J0IGNsYXNzIFRkSnNvbkZvcm1hdHRlckNvbXBvbmVudCB7XG4gIC8qKlxuICAgKiBNYXggbGVuZ3RoIGZvciBwcm9wZXJ0eSBuYW1lcy4gQW55IG5hbWVzIGJpZ2dlciB0aGFuIHRoaXMgZ2V0IHRydW5jdGF0ZWQuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBLRVlfTUFYX0xFTkdUSCA9IDMwO1xuXG4gIC8qKlxuICAgKiBNYXggbGVuZ3RoIGZvciBwcmV2aWV3IHN0cmluZy4gQW55IG5hbWVzIGJpZ2dlciB0aGFuIHRoaXMgZ2V0IHRydW5jdGF0ZWQuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBQUkVWSUVXX1NUUklOR19NQVhfTEVOR1RIID0gODA7XG5cbiAgLyoqXG4gICAqIE1heCB0b29sdGlwIHByZXZpZXcgZWxlbWVudHMuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBQUkVWSUVXX0xJTUlUID0gNTtcblxuICBwcml2YXRlIF9rZXk/OiBzdHJpbmc7XG4gIHByaXZhdGUgX2RhdGEhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICBwcml2YXRlIF9jaGlsZHJlbj86IHN0cmluZ1tdO1xuICBwcml2YXRlIF9vcGVuID0gZmFsc2U7XG4gIHByaXZhdGUgX2xldmVsc09wZW4gPSAwO1xuXG4gIC8qKlxuICAgKiBsZXZlbHNPcGVuPzogbnVtYmVyXG4gICAqIExldmVscyBvcGVuZWQgYnkgZGVmYXVsdCB3aGVuIEpTIG9iamVjdCBpcyBmb3JtYXR0ZWQgYW5kIHJlbmRlcmVkLlxuICAgKi9cbiAgQElucHV0KClcbiAgc2V0IGxldmVsc09wZW4obGV2ZWxzT3BlbjogbnVtYmVyKSB7XG4gICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGxldmVsc09wZW4pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1tsZXZlbHNPcGVuXSBuZWVkcyB0byBiZSBhbiBpbnRlZ2VyLicpO1xuICAgIH1cbiAgICB0aGlzLl9sZXZlbHNPcGVuID0gbGV2ZWxzT3BlbjtcbiAgICB0aGlzLl9vcGVuID0gbGV2ZWxzT3BlbiA+IDA7XG4gIH1cbiAgZ2V0IGxldmVsc09wZW4oKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fbGV2ZWxzT3BlbjtcbiAgfVxuXG4gIGdldCBvcGVuKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9vcGVuO1xuICB9XG5cbiAgLyoqXG4gICAqIGtleT86IHN0cmluZ1xuICAgKiBUYWcgdG8gYmUgZGlzcGxheWVkIG5leHQgdG8gZm9ybWF0dGVkIG9iamVjdC5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHNldCBrZXkoa2V5OiBzdHJpbmcpIHtcbiAgICB0aGlzLl9rZXkgPSBrZXk7XG4gIH1cbiAgZ2V0IGtleSgpOiBzdHJpbmcge1xuICAgIGNvbnN0IGVsaXBzaXM6IHN0cmluZyA9XG4gICAgICB0aGlzLl9rZXkgJiYgdGhpcy5fa2V5Lmxlbmd0aCA+IFRkSnNvbkZvcm1hdHRlckNvbXBvbmVudC5LRVlfTUFYX0xFTkdUSFxuICAgICAgICA/ICfigKYnXG4gICAgICAgIDogJyc7XG4gICAgcmV0dXJuIHRoaXMuX2tleVxuICAgICAgPyB0aGlzLl9rZXkuc3Vic3RyaW5nKDAsIFRkSnNvbkZvcm1hdHRlckNvbXBvbmVudC5LRVlfTUFYX0xFTkdUSCkgK1xuICAgICAgICAgIGVsaXBzaXNcbiAgICAgIDogdGhpcy5fa2V5ID8/ICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIGRhdGE6IGFueVxuICAgKiBKUyBvYmplY3QgdG8gYmUgZm9ybWF0dGVkLlxuICAgKi9cbiAgQElucHV0KClcbiAgc2V0IGRhdGEoZGF0YTogUmVjb3JkPHN0cmluZywgYW55Pikge1xuICAgIHRoaXMuX2RhdGEgPSBkYXRhO1xuICAgIHRoaXMucGFyc2VDaGlsZHJlbigpO1xuICB9XG4gIGdldCBkYXRhKCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICAgIHJldHVybiB0aGlzLl9kYXRhO1xuICB9XG5cbiAgZ2V0IGNoaWxkcmVuKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5fY2hpbGRyZW4gPz8gW107XG4gIH1cblxuICBnZXQgaXNSVEwoKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuX2Rpcikge1xuICAgICAgcmV0dXJuIHRoaXMuX2Rpci5kaXIgPT09ICdydGwnO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9jaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSBfZGlyOiBEaXJcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBSZWZyZXNoZXMganNvbi1mb3JtYXR0ZXIgYW5kIHJlcmVuZGVycyBbZGF0YV1cbiAgICovXG4gIHJlZnJlc2goKTogdm9pZCB7XG4gICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKipcbiAgICogVG9nZ2xlcyBjb2xsYXBzZS9leHBhbmRlZCBzdGF0ZSBvZiBjb21wb25lbnQuXG4gICAqL1xuICB0b2dnbGUoKTogdm9pZCB7XG4gICAgdGhpcy5fb3BlbiA9ICF0aGlzLl9vcGVuO1xuICB9XG5cbiAgaXNPYmplY3QoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VHlwZSh0aGlzLl9kYXRhKSA9PT0gJ29iamVjdCc7XG4gIH1cblxuICBpc0FycmF5KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBBcnJheS5pc0FycmF5KHRoaXMuX2RhdGEpO1xuICB9XG5cbiAgaGFzQ2hpbGRyZW4oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICh0aGlzLl9jaGlsZHJlbiAmJiB0aGlzLl9jaGlsZHJlbi5sZW5ndGggPiAwKSA/PyBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHBhcnNlZCB2YWx1ZSBkZXBlbmRpbmcgb24gdmFsdWUgdHlwZS5cbiAgICovXG4gIGdldFZhbHVlKHZhbHVlOiBhbnkpOiBzdHJpbmcge1xuICAgIGNvbnN0IHR5cGU6IHN0cmluZyA9IHRoaXMuZ2V0VHlwZSh2YWx1ZSk7XG4gICAgaWYgKHR5cGUgPT09ICd1bmRlZmluZWQnIHx8IHR5cGUgPT09ICdudWxsJykge1xuICAgICAgcmV0dXJuIHR5cGU7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnZGF0ZScpIHtcbiAgICAgIHZhbHVlID0gbmV3IERhdGUodmFsdWUpLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgdmFsdWUgPSAnXCInICsgdmFsdWUgKyAnXCInO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gUmVtb3ZlIGNvbnRlbnQgb2YgdGhlIGZ1bmN0aW9uXG4gICAgICByZXR1cm4gKFxuICAgICAgICB2YWx1ZVxuICAgICAgICAgIC50b1N0cmluZygpXG4gICAgICAgICAgLnJlcGxhY2UoL1tcXHJcXG5dL2csICcnKVxuICAgICAgICAgIC5yZXBsYWNlKC9cXHsuKlxcfS8sICcnKSArICd74oCmfSdcbiAgICAgICk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0T2JqZWN0TmFtZSgpICsgJyBbJyArIHZhbHVlLmxlbmd0aCArICddJztcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdHlwZSBvZiBvYmplY3QuXG4gICAqIHJldHVybnMgJ251bGwnIGlmIG9iamVjdCBpcyBudWxsIGFuZCAnZGF0ZScgaWYgdmFsdWUgaXMgb2JqZWN0IGFuZCBjYW4gYmUgcGFyc2VkIHRvIGEgZGF0ZS5cbiAgICovXG4gIGdldFR5cGUob2JqZWN0OiBhbnkpOiBzdHJpbmcge1xuICAgIGlmICh0eXBlb2Ygb2JqZWN0ID09PSAnb2JqZWN0Jykge1xuICAgICAgaWYgKCFvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuICdudWxsJztcbiAgICAgIH1cbiAgICAgIGlmIChBcnJheS5pc0FycmF5KG9iamVjdCkpIHtcbiAgICAgICAgcmV0dXJuICdvYmplY3QnO1xuICAgICAgfVxuICAgICAgY29uc3QgZGF0ZTogRGF0ZSA9IG5ldyBEYXRlKG9iamVjdCk7XG4gICAgICBpZiAoXG4gICAgICAgIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChkYXRlKSA9PT0gJ1tvYmplY3QgRGF0ZV0nICYmXG4gICAgICAgICFOdW1iZXIuaXNOYU4oZGF0ZS5nZXRUaW1lKCkpXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuICdkYXRlJztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHR5cGVvZiBvYmplY3Q7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIHN0cmluZyByZXByZXNlbnRhdGlvbiBkZXBlbmRpbmcgaWYgaXRzIGFuIG9iamVjdCBvciBmdW5jdGlvbi5cbiAgICogc2VlOiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8zMzI0MjlcbiAgICovXG4gIGdldE9iamVjdE5hbWUoKTogc3RyaW5nIHtcbiAgICBjb25zdCBvYmplY3Q6IGFueSA9IHRoaXMuX2RhdGE7XG4gICAgaWYgKHRoaXMuaXNPYmplY3QoKSAmJiAhb2JqZWN0LmNvbnN0cnVjdG9yKSB7XG4gICAgICByZXR1cm4gJ09iamVjdCc7XG4gICAgfVxuICAgIGNvbnN0IGZ1bmNOYW1lUmVnZXggPSAvZnVuY3Rpb24gKC57MSx9KVxcKC87XG4gICAgY29uc3QgcmVzdWx0cyA9IGZ1bmNOYW1lUmVnZXguZXhlYyhvYmplY3QuY29uc3RydWN0b3IudG9TdHJpbmcoKSk7XG4gICAgaWYgKHJlc3VsdHMgJiYgcmVzdWx0cy5sZW5ndGggPiAxKSB7XG4gICAgICByZXR1cm4gcmVzdWx0c1sxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIHByZXZpZXcgb2Ygbm9kZXMgY2hpbGRyZW4gdG8gcmVuZGVyIGluIHRvb2x0aXAgZGVwZW5kaW5nIGlmIGl0cyBhbiBhcnJheSBvciBhbiBvYmplY3QuXG4gICAqL1xuICBnZXRQcmV2aWV3KCk6IHN0cmluZyB7XG4gICAgbGV0IHByZXZpZXdEYXRhOiBzdHJpbmdbXTtcbiAgICBsZXQgc3RhcnRDaGFyID0gJ3sgJztcbiAgICBsZXQgZW5kQ2hhciA9ICcgfSc7XG4gICAgaWYgKHRoaXMuaXNBcnJheSgpKSB7XG4gICAgICBjb25zdCBwcmV2aWV3QXJyYXk6IGFueVtdID1cbiAgICAgICAgT2JqZWN0LmVudHJpZXModGhpcy5fZGF0YSkuc2xpY2UoXG4gICAgICAgICAgMCxcbiAgICAgICAgICBUZEpzb25Gb3JtYXR0ZXJDb21wb25lbnQuUFJFVklFV19MSU1JVFxuICAgICAgICApID8/IFtdO1xuICAgICAgcHJldmlld0RhdGEgPSBwcmV2aWV3QXJyYXkubWFwKChvYmo6IGFueSkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRWYWx1ZShvYmopO1xuICAgICAgfSk7XG4gICAgICBzdGFydENoYXIgPSAnWyc7XG4gICAgICBlbmRDaGFyID0gJ10nO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBwcmV2aWV3S2V5czogc3RyaW5nW10gPVxuICAgICAgICB0aGlzLl9jaGlsZHJlbj8uc2xpY2UoMCwgVGRKc29uRm9ybWF0dGVyQ29tcG9uZW50LlBSRVZJRVdfTElNSVQpID8/IFtdO1xuICAgICAgcHJldmlld0RhdGEgPSBwcmV2aWV3S2V5cy5tYXAoKGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgIHJldHVybiBrZXkgKyAnOiAnICsgdGhpcy5nZXRWYWx1ZSh0aGlzLl9kYXRhW2tleV0gPz8gdW5kZWZpbmVkKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBjb25zdCBwcmV2aWV3U3RyaW5nOiBzdHJpbmcgPSBwcmV2aWV3RGF0YS5qb2luKCcsICcpO1xuICAgIGNvbnN0IGVsbGlwc2lzOiBzdHJpbmcgPVxuICAgICAgcHJldmlld0RhdGEubGVuZ3RoID49IFRkSnNvbkZvcm1hdHRlckNvbXBvbmVudC5QUkVWSUVXX0xJTUlUIHx8XG4gICAgICBwcmV2aWV3U3RyaW5nLmxlbmd0aCA+IFRkSnNvbkZvcm1hdHRlckNvbXBvbmVudC5QUkVWSUVXX1NUUklOR19NQVhfTEVOR1RIXG4gICAgICAgID8gJ+KApidcbiAgICAgICAgOiAnJztcbiAgICByZXR1cm4gKFxuICAgICAgc3RhcnRDaGFyICtcbiAgICAgIHByZXZpZXdTdHJpbmcuc3Vic3RyaW5nKFxuICAgICAgICAwLFxuICAgICAgICBUZEpzb25Gb3JtYXR0ZXJDb21wb25lbnQuUFJFVklFV19TVFJJTkdfTUFYX0xFTkdUSFxuICAgICAgKSArXG4gICAgICBlbGxpcHNpcyArXG4gICAgICBlbmRDaGFyXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VDaGlsZHJlbigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc09iamVjdCgpKSB7XG4gICAgICB0aGlzLl9jaGlsZHJlbiA9IE9iamVjdC5rZXlzKHRoaXMuX2RhdGEgPz8ge30pO1xuICAgIH1cbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cInRkLWpzb24tZm9ybWF0dGVyLXdyYXBwZXJcIj5cbiAgPGFcbiAgICBjbGFzcz1cInRkLWtleVwiXG4gICAgW2NsYXNzLnRkLWtleS1ub2RlXT1cImhhc0NoaWxkcmVuKClcIlxuICAgIFtjbGFzcy50ZC1rZXktbGVhZl09XCIhaGFzQ2hpbGRyZW4oKVwiXG4gICAgW3RhYkluZGV4XT1cImlzT2JqZWN0KCkgPyAwIDogLTFcIlxuICAgIChrZXlkb3duLmVudGVyKT1cInRvZ2dsZSgpXCJcbiAgICAoY2xpY2spPVwidG9nZ2xlKClcIlxuICA+XG4gICAgPG1hdC1pY29uIGNsYXNzPVwidGQtbm9kZS1pY29uXCIgKm5nSWY9XCJoYXNDaGlsZHJlbigpXCI+XG4gICAgICB7e1xuICAgICAgICBvcGVuXG4gICAgICAgICAgPyAna2V5Ym9hcmRfYXJyb3dfZG93bidcbiAgICAgICAgICA6IGlzUlRMXG4gICAgICAgICAgPyAna2V5Ym9hcmRfYXJyb3dfbGVmdCdcbiAgICAgICAgICA6ICdrZXlib2FyZF9hcnJvd19yaWdodCdcbiAgICAgIH19XG4gICAgPC9tYXQtaWNvbj5cbiAgICA8c3BhbiAqbmdJZj1cImtleVwiIGNsYXNzPVwia2V5XCI+e3sga2V5IH19Ojwvc3Bhbj5cbiAgICA8c3BhbiBjbGFzcz1cInZhbHVlXCI+XG4gICAgICA8c3BhblxuICAgICAgICBbY2xhc3MudGQtZW1wdHldPVwiIWhhc0NoaWxkcmVuKClcIlxuICAgICAgICAqbmdJZj1cImlzT2JqZWN0KClcIlxuICAgICAgICBbbWF0VG9vbHRpcF09XCJnZXRQcmV2aWV3KClcIlxuICAgICAgICBtYXRUb29sdGlwUG9zaXRpb249XCJhZnRlclwiXG4gICAgICA+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwidGQtb2JqZWN0LW5hbWVcIj57eyBnZXRPYmplY3ROYW1lKCkgfX08L3NwYW4+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwidGQtYXJyYXktbGVuZ3RoXCIgKm5nSWY9XCJpc0FycmF5KClcIlxuICAgICAgICAgID5be3sgZGF0YVsnbGVuZ3RoJ10gfX1dPC9zcGFuXG4gICAgICAgID5cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuICpuZ0lmPVwiIWlzT2JqZWN0KClcIiBbY2xhc3NdPVwiZ2V0VHlwZShkYXRhKVwiPnt7XG4gICAgICAgIGdldFZhbHVlKGRhdGEpXG4gICAgICB9fTwvc3Bhbj5cbiAgICA8L3NwYW4+XG4gIDwvYT5cbiAgPGRpdiBjbGFzcz1cInRkLW9iamVjdC1jaGlsZHJlblwiIFtAdGRDb2xsYXBzZV09XCIhKGhhc0NoaWxkcmVuKCkgJiYgb3BlbilcIj5cbiAgICA8bmctdGVtcGxhdGUgbGV0LWtleSBuZ0ZvciBbbmdGb3JPZl09XCJjaGlsZHJlblwiPlxuICAgICAgPHRkLWpzb24tZm9ybWF0dGVyXG4gICAgICAgIFtrZXldPVwia2V5XCJcbiAgICAgICAgW2RhdGFdPVwiZGF0YVtrZXldXCJcbiAgICAgICAgW2xldmVsc09wZW5dPVwibGV2ZWxzT3BlbiAtIDFcIlxuICAgICAgPjwvdGQtanNvbi1mb3JtYXR0ZXI+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==