UNPKG

material-dynamic-table

Version:

Dynamic table component for angular built on top of angular material table. It offers sorting, pagination, filtering per column and the ability to specify content types and components used for displaying them.

239 lines 35.4 kB
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { Inject, Injectable, CSP_NONCE, Optional } from '@angular/core'; import { DOCUMENT } from '@angular/common'; import { coerceCssPixelValue } from '@angular/cdk/coercion'; import { CdkTable, _CoalescedStyleScheduler, _COALESCED_STYLE_SCHEDULER } from '@angular/cdk/table'; import { ColumnResize } from './column-resize'; import * as i0 from "@angular/core"; import * as i1 from "./column-resize"; import * as i2 from "@angular/cdk/table"; /** * Provides an implementation for resizing a column. * The details of how resizing works for tables for flex mat-tables are quite different. */ export class ResizeStrategy { constructor() { this._pendingResizeDelta = null; } /** Adjusts the width of the table element by the specified delta. */ updateTableWidthAndStickyColumns(delta) { if (this._pendingResizeDelta === null) { const tableElement = this.columnResize.elementRef.nativeElement; const tableWidth = getElementWidth(tableElement); this.styleScheduler.schedule(() => { tableElement.style.width = coerceCssPixelValue(tableWidth + this._pendingResizeDelta); this._pendingResizeDelta = null; }); this.styleScheduler.scheduleEnd(() => { this.table.updateStickyColumnStyles(); }); } this._pendingResizeDelta = (this._pendingResizeDelta ?? 0) + delta; } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ResizeStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ResizeStrategy }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ResizeStrategy, decorators: [{ type: Injectable }] }); /** * The optimally performing resize strategy for <table> elements with table-layout: fixed. * Tested against and outperformed: * CSS selector * CSS selector w/ CSS variable * Updating all cell nodes */ export class TableLayoutFixedResizeStrategy extends ResizeStrategy { constructor(columnResize, styleScheduler, table) { super(); this.columnResize = columnResize; this.styleScheduler = styleScheduler; this.table = table; } applyColumnSize(_, columnHeader, sizeInPx, previousSizeInPx) { const delta = sizeInPx - (previousSizeInPx ?? getElementWidth(columnHeader)); if (delta === 0) { return; } this.styleScheduler.schedule(() => { columnHeader.style.width = coerceCssPixelValue(sizeInPx); }); this.updateTableWidthAndStickyColumns(delta); } applyMinColumnSize(_, columnHeader, sizeInPx) { const currentWidth = getElementWidth(columnHeader); const newWidth = Math.max(currentWidth, sizeInPx); this.applyColumnSize(_, columnHeader, newWidth, currentWidth); } applyMaxColumnSize(_, columnHeader, sizeInPx) { const currentWidth = getElementWidth(columnHeader); const newWidth = Math.min(currentWidth, sizeInPx); this.applyColumnSize(_, columnHeader, newWidth, currentWidth); } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TableLayoutFixedResizeStrategy, deps: [{ token: i1.ColumnResize }, { token: _COALESCED_STYLE_SCHEDULER }, { token: i2.CdkTable }], target: i0.ɵɵFactoryTarget.Injectable }); } /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TableLayoutFixedResizeStrategy }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TableLayoutFixedResizeStrategy, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.ColumnResize }, { type: i2._CoalescedStyleScheduler, decorators: [{ type: Inject, args: [_COALESCED_STYLE_SCHEDULER] }] }, { type: i2.CdkTable }] }); /** * The optimally performing resize strategy for flex mat-tables. * Tested against and outperformed: * CSS selector w/ CSS variable * Updating all mat-cell nodes */ export class CdkFlexTableResizeStrategy extends ResizeStrategy { constructor(columnResize, styleScheduler, table, document, _nonce) { super(); this.columnResize = columnResize; this.styleScheduler = styleScheduler; this.table = table; this._nonce = _nonce; this._columnIndexes = new Map(); this._columnProperties = new Map(); this._indexSequence = 0; this.defaultMinSize = 0; this.defaultMaxSize = Number.MAX_SAFE_INTEGER; this._document = document; } applyColumnSize(cssFriendlyColumnName, columnHeader, sizeInPx, previousSizeInPx) { // Optimization: Check applied width first as we probably set it already before reading // offsetWidth which triggers layout. const delta = sizeInPx - (previousSizeInPx ?? (this._getAppliedWidth(cssFriendlyColumnName) || columnHeader.offsetWidth)); if (delta === 0) { return; } const cssSize = coerceCssPixelValue(sizeInPx); this._applyProperty(cssFriendlyColumnName, 'flex', `0 0.01 ${cssSize}`); this.updateTableWidthAndStickyColumns(delta); } applyMinColumnSize(cssFriendlyColumnName, _, sizeInPx) { const cssSize = coerceCssPixelValue(sizeInPx); this._applyProperty(cssFriendlyColumnName, 'min-width', cssSize, sizeInPx !== this.defaultMinSize); this.updateTableWidthAndStickyColumns(0); } applyMaxColumnSize(cssFriendlyColumnName, _, sizeInPx) { const cssSize = coerceCssPixelValue(sizeInPx); this._applyProperty(cssFriendlyColumnName, 'max-width', cssSize, sizeInPx !== this.defaultMaxSize); this.updateTableWidthAndStickyColumns(0); } getColumnCssClass(cssFriendlyColumnName) { return `cdk-column-${cssFriendlyColumnName}`; } ngOnDestroy() { this._styleElement?.remove(); this._styleElement = undefined; } _getPropertyValue(cssFriendlyColumnName, key) { const properties = this._getColumnPropertiesMap(cssFriendlyColumnName); return properties.get(key); } _getAppliedWidth(cssFriendslyColumnName) { return coercePixelsFromFlexValue(this._getPropertyValue(cssFriendslyColumnName, 'flex')); } _applyProperty(cssFriendlyColumnName, key, value, enable = true) { const properties = this._getColumnPropertiesMap(cssFriendlyColumnName); this.styleScheduler.schedule(() => { if (enable) { properties.set(key, value); } else { properties.delete(key); } this._applySizeCss(cssFriendlyColumnName); }); } _getStyleSheet() { if (!this._styleElement) { this._styleElement = this._document.createElement('style'); if (this._nonce) { this._styleElement.setAttribute('nonce', this._nonce); } this._styleElement.appendChild(this._document.createTextNode('')); this._document.head.appendChild(this._styleElement); } return this._styleElement.sheet; } _getColumnPropertiesMap(cssFriendlyColumnName) { let properties = this._columnProperties.get(cssFriendlyColumnName); if (properties === undefined) { properties = new Map(); this._columnProperties.set(cssFriendlyColumnName, properties); } return properties; } _applySizeCss(cssFriendlyColumnName) { const properties = this._getColumnPropertiesMap(cssFriendlyColumnName); const propertyKeys = Array.from(properties.keys()); let index = this._columnIndexes.get(cssFriendlyColumnName); if (index === undefined) { if (!propertyKeys.length) { // Nothing to set or unset. return; } index = this._indexSequence++; this._columnIndexes.set(cssFriendlyColumnName, index); } else { this._getStyleSheet().deleteRule(index); } const columnClassName = this.getColumnCssClass(cssFriendlyColumnName); const tableClassName = this.columnResize.getUniqueCssClass(); const selector = `.${tableClassName} .${columnClassName}`; const body = propertyKeys.map(key => `${key}:${properties.get(key)}`).join(';'); this._getStyleSheet().insertRule(`${selector} {${body}}`, index); } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CdkFlexTableResizeStrategy, deps: [{ token: i1.ColumnResize }, { token: _COALESCED_STYLE_SCHEDULER }, { token: i2.CdkTable }, { token: DOCUMENT }, { token: CSP_NONCE, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CdkFlexTableResizeStrategy }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CdkFlexTableResizeStrategy, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.ColumnResize }, { type: i2._CoalescedStyleScheduler, decorators: [{ type: Inject, args: [_COALESCED_STYLE_SCHEDULER] }] }, { type: i2.CdkTable }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT] }] }, { type: undefined, decorators: [{ type: Inject, args: [CSP_NONCE] }, { type: Optional }] }] }); /** Converts CSS pixel values to numbers, eg "123px" to 123. Returns NaN for non pixel values. */ function coercePixelsFromCssValue(cssValue) { return Number(cssValue.match(/(\d+)px/)?.[1]); } /** Gets the style.width pixels on the specified element if present, otherwise its offsetWidth. */ function getElementWidth(element) { // Optimization: Check style.width first as we probably set it already before reading // offsetWidth which triggers layout. return coercePixelsFromCssValue(element.style.width) || element.offsetWidth; } /** * Converts CSS flex values as set in CdkFlexTableResizeStrategy to numbers, * eg "0 0.01 123px" to 123. */ function coercePixelsFromFlexValue(flexValue) { return Number(flexValue?.match(/0 0\.01 (\d+)px/)?.[1]); } export const TABLE_LAYOUT_FIXED_RESIZE_STRATEGY_PROVIDER = { provide: ResizeStrategy, useClass: TableLayoutFixedResizeStrategy, }; export const FLEX_RESIZE_STRATEGY_PROVIDER = { provide: ResizeStrategy, useClass: CdkFlexTableResizeStrategy, }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzaXplLXN0cmF0ZWd5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbWF0ZXJpYWwtZHluYW1pYy10YWJsZS9zcmMvbGliL2NvbHVtbi1yZXNpemUvcmVzaXplLXN0cmF0ZWd5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUF1QixTQUFTLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdGLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMzQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsUUFBUSxFQUFFLHdCQUF3QixFQUFFLDBCQUEwQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFcEcsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDOzs7O0FBRS9DOzs7R0FHRztBQUVILE1BQU0sT0FBZ0IsY0FBYztJQURwQztRQU1VLHdCQUFtQixHQUFrQixJQUFJLENBQUM7S0EyQ25EO0lBbkJDLHFFQUFxRTtJQUMzRCxnQ0FBZ0MsQ0FBQyxLQUFhO1FBQ3RELElBQUksSUFBSSxDQUFDLG1CQUFtQixLQUFLLElBQUksRUFBRSxDQUFDO1lBQ3RDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQztZQUNoRSxNQUFNLFVBQVUsR0FBRyxlQUFlLENBQUMsWUFBWSxDQUFDLENBQUM7WUFFakQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFO2dCQUNoQyxZQUFZLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxtQkFBbUIsQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLG1CQUFvQixDQUFDLENBQUM7Z0JBRXZGLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJ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LE1BQU07MkJBQUMsMEJBQTBCOzswQkFHakMsTUFBTTsyQkFBQyxRQUFROzswQkFDZixNQUFNOzJCQUFDLFNBQVM7OzBCQUFHLFFBQVE7O0FBNEloQyxpR0FBaUc7QUFDakcsU0FBUyx3QkFBd0IsQ0FBQyxRQUFnQjtJQUNoRCxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNoRCxDQUFDO0FBRUQsa0dBQWtHO0FBQ2xHLFNBQVMsZUFBZSxDQUFDLE9BQW9CO0lBQzNDLHFGQUFxRjtJQUNyRixxQ0FBcUM7SUFDckMsT0FBTyx3QkFBd0IsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLE9BQU8sQ0FBQyxXQUFXLENBQUM7QUFDOUUsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMseUJBQXlCLENBQUMsU0FBNkI7SUFDOUQsT0FBTyxNQUFNLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMxRCxDQUFDO0FBRUQsTUFBTSxDQUFDLE1BQU0sMkNBQTJDLEdBQWE7SUFDbkUsT0FBTyxFQUFFLGNBQWM7SUFDdkIsUUFBUSxFQUFFLDhCQUE4QjtDQUN6QyxDQUFDO0FBQ0YsTUFBTSxDQUFDLE1BQU0sNkJBQTZCLEdBQWE7SUFDckQsT0FBTyxFQUFFLGNBQWM7SUFDdkIsUUFBUSxFQUFFLDBCQUEwQjtDQUNyQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXHJcbiAqIEBsaWNlbnNlXHJcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXHJcbiAqXHJcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXHJcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcclxuICovXHJcblxyXG5pbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUsIE9uRGVzdHJveSwgUHJvdmlkZXIsIENTUF9OT05DRSwgT3B0aW9uYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBjb2VyY2VDc3NQaXhlbFZhbHVlIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2NvZXJjaW9uJztcclxuaW1wb3J0IHsgQ2RrVGFibGUsIF9Db2FsZXNjZWRTdHlsZVNjaGVkdWxlciwgX0NPQUxFU0NFRF9TVFlMRV9TQ0hFRFVMRVIgfSBmcm9tICdAYW5ndWxhci9jZGsvdGFibGUnO1xyXG5cclxuaW1wb3J0IHsgQ29sdW1uUmVzaXplIH0gZnJvbSAnLi9jb2x1bW4tcmVzaXplJztcclxuXHJcbi8qKlxyXG4gKiBQcm92aWRlcyBhbiBpbXBsZW1lbnRhdGlvbiBmb3IgcmVzaXppbmcgYSBjb2x1bW4uXHJcbiAqIFRoZSBkZXRhaWxzIG9mIGhvdyByZXNpemluZyB3b3JrcyBmb3IgdGFibGVzIGZvciBmbGV4IG1hdC10YWJsZXMgYXJlIHF1aXRlIGRpZmZlcmVudC5cclxuICovXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFJlc2l6ZVN0cmF0ZWd5IHtcclxuICBwcm90ZWN0ZWQgYWJzdHJhY3QgcmVhZG9ubHkgY29sdW1uUmVzaXplOiBDb2x1bW5SZXNpemU7XHJcbiAgcHJvdGVjdGVkIGFic3RyYWN0IHJlYWRvbmx5IHN0eWxlU2NoZWR1bGVyOiBfQ29hbGVzY2VkU3R5bGVTY2hlZHVsZXI7XHJcbiAgcHJvdGVjdGVkIGFic3RyYWN0IHJlYWRvbmx5IHRhYmxlOiBDZGtUYWJsZTx1bmtub3duPjtcclxuXHJcbiAgcHJpdmF0ZSBfcGVuZGluZ1Jlc2l6ZURlbHRhOiBudW1iZXIgfCBudWxsID0gbnVsbDtcclxuXHJcbiAgLyoqIFVwZGF0ZXMgdGhlIHdpZHRoIG9mIHRoZSBzcGVjaWZpZWQgY29sdW1uLiAqL1xyXG4gIGFic3RyYWN0IGFwcGx5Q29sdW1uU2l6ZShcclxuICAgIGNzc0ZyaWVuZGx5Q29sdW1uTmFtZTogc3RyaW5nLFxyXG4gICAgY29sdW1uSGVhZGVyOiBIVE1MRWxlbWVudCxcclxuICAgIHNpemVJblB4OiBudW1iZXIsXHJcbiAgICBwcmV2aW91c1NpemVJblB4PzogbnVtYmVyLFxyXG4gICk6IHZvaWQ7XHJcblxyXG4gIC8qKiBBcHBsaWVzIGEgbWluaW11bSB3aWR0aCB0byB0aGUgc3BlY2lmaWVkIGNvbHVtbiwgdXBkYXRpbmcgaXRzIGN1cnJlbnQgd2lkdGggYXMgbmVlZGVkLiAqL1xyXG4gIGFic3RyYWN0IGFwcGx5TWluQ29sdW1uU2l6ZShcclxuICAgIGNzc0ZyaWVuZGx5Q29sdW1uTmFtZTogc3RyaW5nLFxyXG4gICAgY29sdW1uSGVhZGVyOiBIVE1MRWxlbWVudCxcclxuICAgIG1pblNpemVJblB4OiBudW1iZXIsXHJcbiAgKTogdm9pZDtcclxuXHJcbiAgLyoqIEFwcGxpZXMgYSBtYXhpbXVtIHdpZHRoIHRvIHRoZSBzcGVjaWZpZWQgY29sdW1uLCB1cGRhdGluZyBpdHMgY3VycmVudCB3aWR0aCBhcyBuZWVkZWQuICovXHJcbiAgYWJzdHJhY3QgYXBwbHlNYXhDb2x1bW5TaXplKFxyXG4gICAgY3NzRnJpZW5kbHlDb2x1bW5OYW1lOiBzdHJpbmcsXHJcbiAgICBjb2x1bW5IZWFkZXI6IEhUTUxFbGVtZW50LFxyXG4gICAgbWluU2l6ZUluUHg6IG51bWJlcixcclxuICApOiB2b2lkO1xyXG5cclxuICAvKiogQWRqdXN0cyB0aGUgd2lkdGggb2YgdGhlIHRhYmxlIGVsZW1lbnQgYnkgdGhlIHNwZWNpZmllZCBkZWx0YS4gKi9cclxuICBwcm90ZWN0ZWQgdXBkYXRlVGFibGVXaWR0aEFuZFN0aWNreUNvbHVtbnMoZGVsdGE6IG51bWJlcik6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuX3BlbmRpbmdSZXNpemVEZWx0YSA9PT0gbnVsbCkge1xyXG4gICAgICBjb25zdCB0YWJsZUVsZW1lbnQgPSB0aGlzLmNvbHVtblJlc2l6ZS5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICAgIGNvbnN0IHRhYmxlV2lkdGggPSBnZXRFbGVtZW50V2lkdGgodGFibGVFbGVtZW50KTtcclxuXHJcbiAgICAgIHRoaXMuc3R5bGVTY2hlZHVsZXIuc2NoZWR1bGUoKCkgPT4ge1xyXG4gICAgICAgIHRhYmxlRWxlbWVudC5zdHlsZS53aWR0aCA9IGNvZXJjZUNzc1BpeGVsVmFsdWUodGFibGVXaWR0aCArIHRoaXMuX3BlbmRpbmdSZXNpemVEZWx0YSEpO1xyXG5cclxuICAgICAgICB0aGlzLl9wZW5kaW5nUmVzaXplRGVsdGEgPSBudWxsO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuc3R5bGVTY2hlZHVsZXIuc2NoZWR1bGVFbmQoKCkgPT4ge1xyXG4gICAgICAgIHRoaXMudGFibGUudXBkYXRlU3RpY2t5Q29sdW1uU3R5bGVzKCk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuX3BlbmRpbmdSZXNpemVEZWx0YSA9ICh0aGlzLl9wZW5kaW5nUmVzaXplRGVsdGEgPz8gMCkgKyBkZWx0YTtcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBUaGUgb3B0aW1hbGx5IHBlcmZvcm1pbmcgcmVzaXplIHN0cmF0ZWd5IGZvciAmbHQ7dGFibGUmZ3Q7IGVsZW1lbnRzIHdpdGggdGFibGUtbGF5b3V0OiBmaXhlZC5cclxuICogVGVzdGVkIGFnYWluc3QgYW5kIG91dHBlcmZvcm1lZDpcclxuICogICBDU1Mgc2VsZWN0b3JcclxuICogICBDU1Mgc2VsZWN0b3Igdy8gQ1NTIHZhcmlhYmxlXHJcbiAqICAgVXBkYXRpbmcgYWxsIGNlbGwgbm9kZXNcclxuICovXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIFRhYmxlTGF5b3V0Rml4ZWRSZXNpemVTdHJhdGVneSBleHRlbmRzIFJlc2l6ZVN0cmF0ZWd5IHtcclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByb3RlY3RlZCByZWFkb25seSBjb2x1bW5SZXNpemU6IENvbHVtblJlc2l6ZSxcclxuICAgIEBJbmplY3QoX0NPQUxFU0NFRF9TVFlMRV9TQ0hFRFVMRVIpXHJcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgc3R5bGVTY2hlZHVsZXI6IF9Db2FsZXNjZWRTdHlsZVNjaGVkdWxlcixcclxuICAgIHByb3RlY3RlZCByZWFkb25seSB0YWJsZTogQ2RrVGFibGU8dW5rbm93bj4sXHJcbiAgKSB7XHJcbiAgICBzdXBlcigpO1xyXG4gIH1cclxuXHJcbiAgYXBwbHlDb2x1bW5TaXplKFxyXG4gICAgXzogc3RyaW5nLFxyXG4gICAgY29sdW1uSGVhZGVyOiBIVE1MRWxlbWVudCxcclxuICAgIHNpemVJblB4OiBudW1iZXIsXHJcbiAgICBwcmV2aW91c1NpemVJblB4PzogbnVtYmVyLFxyXG4gICk6IHZvaWQge1xyXG4gICAgY29uc3QgZGVsdGEgPSBzaXplSW5QeCAtIChwcmV2aW91c1NpemVJblB4ID8/IGdldEVsZW1lbnRXaWR0aChjb2x1bW5IZWFkZXIpKTtcclxuXHJcbiAgICBpZiAoZGVsdGEgPT09IDApIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuc3R5bGVTY2hlZHVsZXIuc2NoZWR1bGUoKCkgPT4ge1xyXG4gICAgICBjb2x1bW5IZWFkZXIuc3R5bGUud2lkdGggPSBjb2VyY2VDc3NQaXhlbFZhbHVlKHNpemVJblB4KTtcclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMudXBkYXRlVGFibGVXaWR0aEFuZFN0aWNreUNvbHVtbnMoZGVsdGEpO1xyXG4gIH1cclxuXHJcbiAgYXBwbHlNaW5Db2x1bW5TaXplKF86IHN0cmluZywgY29sdW1uSGVhZGVyOiBIVE1MRWxlbWVudCwgc2l6ZUluUHg6IG51bWJlcik6IHZvaWQge1xyXG4gICAgY29uc3QgY3VycmVudFdpZHRoID0gZ2V0RWxlbWVudFdpZHRoKGNvbHVtbkhlYWRlcik7XHJcbiAgICBjb25zdCBuZXdXaWR0aCA9IE1hdGgubWF4KGN1cnJlbnRXaWR0aCwgc2l6ZUluUHgpO1xyXG5cclxuICAgIHRoaXMuYXBwbHlDb2x1bW5TaXplKF8sIGNvbHVtbkhlYWRlciwgbmV3V2lkdGgsIGN1cnJlbnRXaWR0aCk7XHJcbiAgfVxyXG5cclxuICBhcHBseU1heENvbHVtblNpemUoXzogc3RyaW5nLCBjb2x1bW5IZWFkZXI6IEhUTUxFbGVtZW50LCBzaXplSW5QeDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBjb25zdCBjdXJyZW50V2lkdGggPSBnZXRFbGVtZW50V2lkdGgoY29sdW1uSGVhZGVyKTtcclxuICAgIGNvbnN0IG5ld1dpZHRoID0gTWF0aC5taW4oY3VycmVudFdpZHRoLCBzaXplSW5QeCk7XHJcblxyXG4gICAgdGhpcy5hcHBseUNvbHVtblNpemUoXywgY29sdW1uSGVhZGVyLCBuZXdXaWR0aCwgY3VycmVudFdpZHRoKTtcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBUaGUgb3B0aW1hbGx5IHBlcmZvcm1pbmcgcmVzaXplIHN0cmF0ZWd5IGZvciBmbGV4IG1hdC10YWJsZXMuXHJcbiAqIFRlc3RlZCBhZ2FpbnN0IGFuZCBvdXRwZXJmb3JtZWQ6XHJcbiAqICAgQ1NTIHNlbGVjdG9yIHcvIENTUyB2YXJpYWJsZVxyXG4gKiAgIFVwZGF0aW5nIGFsbCBtYXQtY2VsbCBub2Rlc1xyXG4gKi9cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgQ2RrRmxleFRhYmxlUmVzaXplU3RyYXRlZ3kgZXh0ZW5kcyBSZXNpemVTdHJhdGVneSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBfZG9jdW1lbnQ6IERvY3VtZW50O1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgX2NvbHVtbkluZGV4ZXMgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgX2NvbHVtblByb3BlcnRpZXMgPSBuZXcgTWFwPHN0cmluZywgTWFwPHN0cmluZywgc3RyaW5nPj4oKTtcclxuXHJcbiAgcHJpdmF0ZSBfc3R5bGVFbGVtZW50PzogSFRNTFN0eWxlRWxlbWVudDtcclxuICBwcml2YXRlIF9pbmRleFNlcXVlbmNlID0gMDtcclxuXHJcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGRlZmF1bHRNaW5TaXplID0gMDtcclxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGVmYXVsdE1heFNpemUgPSBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUjtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgY29sdW1uUmVzaXplOiBDb2x1bW5SZXNpemUsXHJcbiAgICBASW5qZWN0KF9DT0FMRVNDRURfU1RZTEVfU0NIRURVTEVSKVxyXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHN0eWxlU2NoZWR1bGVyOiBfQ29hbGVzY2VkU3R5bGVTY2hlZHVsZXIsXHJcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgdGFibGU6IENka1RhYmxlPHVua25vd24+LFxyXG4gICAgQEluamVjdChET0NVTUVOVCkgZG9jdW1lbnQ6IGFueSxcclxuICAgIEBJbmplY3QoQ1NQX05PTkNFKSBAT3B0aW9uYWwoKSBwcml2YXRlIHJlYWRvbmx5IF9ub25jZT86IHN0cmluZyB8IG51bGwsXHJcbiAgKSB7XHJcbiAgICBzdXBlcigpO1xyXG4gICAgdGhpcy5fZG9jdW1lbnQgPSBkb2N1bWVudDtcclxuICB9XHJcblxyXG4gIGFwcGx5Q29sdW1uU2l6ZShcclxuICAgIGNzc0ZyaWVuZGx5Q29sdW1uTmFtZTogc3RyaW5nLFxyXG4gICAgY29sdW1uSGVhZGVyOiBIVE1MRWxlbWVudCxcclxuICAgIHNpemVJblB4OiBudW1iZXIsXHJcbiAgICBwcmV2aW91c1NpemVJblB4PzogbnVtYmVyLFxyXG4gICk6IHZvaWQge1xyXG4gICAgLy8gT3B0aW1pemF0aW9uOiBDaGVjayBhcHBsaWVkIHdpZHRoIGZpcnN0IGFzIHdlIHByb2JhYmx5IHNldCBpdCBhbHJlYWR5IGJlZm9yZSByZWFkaW5nXHJcbiAgICAvLyBvZmZzZXRXaWR0aCB3aGljaCB0cmlnZ2VycyBsYXlvdXQuXHJcbiAgICBjb25zdCBkZWx0YSA9XHJcbiAgICAgIHNpemVJblB4IC1cclxuICAgICAgKHByZXZpb3VzU2l6ZUluUHggPz9cclxuICAgICAgICAodGhpcy5fZ2V0QXBwbGllZFdpZHRoKGNzc0ZyaWVuZGx5Q29sdW1uTmFtZSkgfHwgY29sdW1uSGVhZGVyLm9mZnNldFdpZHRoKSk7XHJcblxyXG4gICAgaWYgKGRlbHRhID09PSAwKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBjc3NTaXplID0gY29lcmNlQ3NzUGl4ZWxWYWx1ZShzaXplSW5QeCk7XHJcblxyXG4gICAgdGhpcy5fYXBwbHlQcm9wZXJ0eShjc3NGcmllbmRseUNvbHVtbk5hbWUsICdmbGV4JywgYDAgMC4wMSAke2Nzc1NpemV9YCk7XHJcbiAgICB0aGlzLnVwZGF0ZVRhYmxlV2lkdGhBbmRTdGlja3lDb2x1bW5zKGRlbHRhKTtcclxuICB9XHJcblxyXG4gIGFwcGx5TWluQ29sdW1uU2l6ZShjc3NGcmllbmRseUNvbHVtbk5hbWU6IHN0cmluZywgXzogSFRNTEVsZW1lbnQsIHNpemVJblB4OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGNvbnN0IGNzc1NpemUgPSBjb2VyY2VDc3NQaXhlbFZhbHVlKHNpemVJblB4KTtcclxuXHJcbiAgICB0aGlzLl9hcHBseVByb3BlcnR5KFxyXG4gICAgICBjc3NGcmllbmRseUNvbHVtbk5hbWUsXHJcbiAgICAgICdtaW4td2lkdGgnLFxyXG4gICAgICBjc3NTaXplLFxyXG4gICAgICBzaXplSW5QeCAhPT0gdGhpcy5kZWZhdWx0TWluU2l6ZSxcclxuICAgICk7XHJcbiAgICB0aGlzLnVwZGF0ZVRhYmxlV2lkdGhBbmRTdGlja3lDb2x1bW5zKDApO1xyXG4gIH1cclxuXHJcbiAgYXBwbHlNYXhDb2x1bW5TaXplKGNzc0ZyaWVuZGx5Q29sdW1uTmFtZTogc3RyaW5nLCBfOiBIVE1MRWxlbWVudCwgc2l6ZUluUHg6IG51bWJlcik6IHZvaWQge1xyXG4gICAgY29uc3QgY3NzU2l6ZSA9IGNvZXJjZUNzc1BpeGVsVmFsdWUoc2l6ZUluUHgpO1xyXG5cclxuICAgIHRoaXMuX2FwcGx5UHJvcGVydHkoXHJcbiAgICAgIGNzc0ZyaWVuZGx5Q29sdW1uTmFtZSxcclxuICAgICAgJ21heC13aWR0aCcsXHJcbiAgICAgIGNzc1NpemUsXHJcbiAgICAgIHNpemVJblB4ICE9PSB0aGlzLmRlZmF1bHRNYXhTaXplLFxyXG4gICAgKTtcclxuICAgIHRoaXMudXBkYXRlVGFibGVXaWR0aEFuZFN0aWNreUNvbHVtbnMoMCk7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgZ2V0Q29sdW1uQ3NzQ2xhc3MoY3NzRnJpZW5kbHlDb2x1bW5OYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIGBjZGstY29sdW1uLSR7Y3NzRnJpZW5kbHlDb2x1bW5OYW1lfWA7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuX3N0eWxlRWxlbWVudD8ucmVtb3ZlKCk7XHJcbiAgICB0aGlzLl9zdHlsZUVsZW1lbnQgPSB1bmRlZmluZWQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9nZXRQcm9wZXJ0eVZhbHVlKGNzc0ZyaWVuZGx5Q29sdW1uTmFtZTogc3RyaW5nLCBrZXk6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XHJcbiAgICBjb25zdCBwcm9wZXJ0aWVzID0gdGhpcy5fZ2V0Q29sdW1uUHJvcGVydGllc01hcChjc3NGcmllbmRseUNvbHVtbk5hbWUpO1xyXG4gICAgcmV0dXJuIHByb3BlcnRpZXMuZ2V0KGtleSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9nZXRBcHBsaWVkV2lkdGgoY3NzRnJpZW5kc2x5Q29sdW1uTmFtZTogc3RyaW5nKTogbnVtYmVyIHtcclxuICAgIHJldHVybiBjb2VyY2VQaXhlbHNGcm9tRmxleFZhbHVlKHRoaXMuX2dldFByb3BlcnR5VmFsdWUoY3NzRnJpZW5kc2x5Q29sdW1uTmFtZSwgJ2ZsZXgnKSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9hcHBseVByb3BlcnR5KFxyXG4gICAgY3NzRnJpZW5kbHlDb2x1bW5OYW1lOiBzdHJpbmcsXHJcbiAgICBrZXk6IHN0cmluZyxcclxuICAgIHZhbHVlOiBzdHJpbmcsXHJcbiAgICBlbmFibGUgPSB0cnVlLFxyXG4gICk6IHZvaWQge1xyXG4gICAgY29uc3QgcHJvcGVydGllcyA9IHRoaXMuX2dldENvbHVtblByb3BlcnRpZXNNYXAoY3NzRnJpZW5kbHlDb2x1bW5OYW1lKTtcclxuXHJcbiAgICB0aGlzLnN0eWxlU2NoZWR1bGVyLnNjaGVkdWxlKCgpID0+IHtcclxuICAgICAgaWYgKGVuYWJsZSkge1xyXG4gICAgICAgIHByb3BlcnRpZXMuc2V0KGtleSwgdmFsdWUpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHByb3BlcnRpZXMuZGVsZXRlKGtleSk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5fYXBwbHlTaXplQ3NzKGNzc0ZyaWVuZGx5Q29sdW1uTmFtZSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX2dldFN0eWxlU2hlZXQoKTogQ1NTU3R5bGVTaGVldCB7XHJcbiAgICBpZiAoIXRoaXMuX3N0eWxlRWxlbWVudCkge1xyXG4gICAgICB0aGlzLl9zdHlsZUVsZW1lbnQgPSB0aGlzLl9kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzdHlsZScpO1xyXG5cclxuICAgICAgaWYgKHRoaXMuX25vbmNlKSB7XHJcbiAgICAgICAgdGhpcy5fc3R5bGVFbGVtZW50LnNldEF0dHJpYnV0ZSgnbm9uY2UnLCB0aGlzLl9ub25jZSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRoaXMuX3N0eWxlRWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLl9kb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnJykpO1xyXG4gICAgICB0aGlzLl9kb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHRoaXMuX3N0eWxlRWxlbWVudCk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuX3N0eWxlRWxlbWVudC5zaGVldCBhcyBDU1NTdHlsZVNoZWV0O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfZ2V0Q29sdW1uUHJvcGVydGllc01hcChjc3NGcmllbmRseUNvbHVtbk5hbWU6IHN0cmluZyk6IE1hcDxzdHJpbmcsIHN0cmluZz4ge1xyXG4gICAgbGV0IHByb3BlcnRpZXMgPSB0aGlzLl9jb2x1bW5Qcm9wZXJ0aWVzLmdldChjc3NGcmllbmRseUNvbHVtbk5hbWUpO1xyXG4gICAgaWYgKHByb3BlcnRpZXMgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICBwcm9wZXJ0aWVzID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcclxuICAgICAgdGhpcy5fY29sdW1uUHJvcGVydGllcy5zZXQoY3NzRnJpZW5kbHlDb2x1bW5OYW1lLCBwcm9wZXJ0aWVzKTtcclxuICAgIH1cclxuICAgIHJldHVybiBwcm9wZXJ0aWVzO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfYXBwbHlTaXplQ3NzKGNzc0ZyaWVuZGx5Q29sdW1uTmFtZTogc3RyaW5nKSB7XHJcbiAgICBjb25zdCBwcm9wZXJ0aWVzID0gdGhpcy5fZ2V0Q29sdW1uUHJvcGVydGllc01hcChjc3NGcmllbmRseUNvbHVtbk5hbWUpO1xyXG4gICAgY29uc3QgcHJvcGVydHlLZXlzID0gQXJyYXkuZnJvbShwcm9wZXJ0aWVzLmtleXMoKSk7XHJcblxyXG4gICAgbGV0IGluZGV4ID0gdGhpcy5fY29sdW1uSW5kZXhlcy5nZXQoY3NzRnJpZW5kbHlDb2x1bW5OYW1lKTtcclxuICAgIGlmIChpbmRleCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIGlmICghcHJvcGVydHlLZXlzLmxlbmd0aCkge1xyXG4gICAgICAgIC8vIE5vdGhpbmcgdG8gc2V0IG9yIHVuc2V0LlxyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgaW5kZXggPSB0aGlzLl9pbmRleFNlcXVlbmNlKys7XHJcbiAgICAgIHRoaXMuX2NvbHVtbkluZGV4ZXMuc2V0KGNzc0ZyaWVuZGx5Q29sdW1uTmFtZSwgaW5kZXgpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5fZ2V0U3R5bGVTaGVldCgpLmRlbGV0ZVJ1bGUoaW5kZXgpO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGNvbHVtbkNsYXNzTmFtZSA9IHRoaXMuZ2V0Q29sdW1uQ3NzQ2xhc3MoY3NzRnJpZW5kbHlDb2x1bW5OYW1lKTtcclxuICAgIGNvbnN0IHRhYmxlQ2xhc3NOYW1lID0gdGhpcy5jb2x1bW5SZXNpemUuZ2V0VW5pcXVlQ3NzQ2xhc3MoKTtcclxuXHJcbiAgICBjb25zdCBzZWxlY3RvciA9IGAuJHt0YWJsZUNsYXNzTmFtZX0gLiR7Y29sdW1uQ2xhc3NOYW1lfWA7XHJcbiAgICBjb25zdCBib2R5ID0gcHJvcGVydHlLZXlzLm1hcChrZXkgPT4gYCR7a2V5fToke3Byb3BlcnRpZXMuZ2V0KGtleSl9YCkuam9pbignOycpO1xyXG5cclxuICAgIHRoaXMuX2dldFN0eWxlU2hlZXQoKS5pbnNlcnRSdWxlKGAke3NlbGVjdG9yfSB7JHtib2R5fX1gLCBpbmRleCEpO1xyXG4gIH1cclxufVxyXG5cclxuLyoqIENvbnZlcnRzIENTUyBwaXhlbCB2YWx1ZXMgdG8gbnVtYmVycywgZWcgXCIxMjNweFwiIHRvIDEyMy4gUmV0dXJucyBOYU4gZm9yIG5vbiBwaXhlbCB2YWx1ZXMuICovXHJcbmZ1bmN0aW9uIGNvZXJjZVBpeGVsc0Zyb21Dc3NWYWx1ZShjc3NWYWx1ZTogc3RyaW5nKTogbnVtYmVyIHtcclxuICByZXR1cm4gTnVtYmVyKGNzc1ZhbHVlLm1hdGNoKC8oXFxkKylweC8pPy5bMV0pO1xyXG59XHJcblxyXG4vKiogR2V0cyB0aGUgc3R5bGUud2lkdGggcGl4ZWxzIG9uIHRoZSBzcGVjaWZpZWQgZWxlbWVudCBpZiBwcmVzZW50LCBvdGhlcndpc2UgaXRzIG9mZnNldFdpZHRoLiAqL1xyXG5mdW5jdGlvbiBnZXRFbGVtZW50V2lkdGgoZWxlbWVudDogSFRNTEVsZW1lbnQpIHtcclxuICAvLyBPcHRpbWl6YXRpb246IENoZWNrIHN0eWxlLndpZHRoIGZpcnN0IGFzIHdlIHByb2JhYmx5IHNldCBpdCBhbHJlYWR5IGJlZm9yZSByZWFkaW5nXHJcbiAgLy8gb2Zmc2V0V2lkdGggd2hpY2ggdHJpZ2dlcnMgbGF5b3V0LlxyXG4gIHJldHVybiBjb2VyY2VQaXhlbHNGcm9tQ3NzVmFsdWUoZWxlbWVudC5zdHlsZS53aWR0aCkgfHwgZWxlbWVudC5vZmZzZXRXaWR0aDtcclxufVxyXG5cclxuLyoqXHJcbiAqIENvbnZlcnRzIENTUyBmbGV4IHZhbHVlcyBhcyBzZXQgaW4gQ2RrRmxleFRhYmxlUmVzaXplU3RyYXRlZ3kgdG8gbnVtYmVycyxcclxuICogZWcgXCIwIDAuMDEgMTIzcHhcIiB0byAxMjMuXHJcbiAqL1xyXG5mdW5jdGlvbiBjb2VyY2VQaXhlbHNGcm9tRmxleFZhbHVlKGZsZXhWYWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcclxuICByZXR1cm4gTnVtYmVyKGZsZXhWYWx1ZT8ubWF0Y2goLzAgMFxcLjAxIChcXGQrKXB4Lyk/LlsxXSk7XHJcbn1cclxuXHJcbmV4cG9ydCBjb25zdCBUQUJMRV9MQVlPVVRfRklYRURfUkVTSVpFX1NUUkFURUdZX1BST1ZJREVSOiBQcm92aWRlciA9IHtcclxuICBwcm92aWRlOiBSZXNpemVTdHJhdGVneSxcclxuICB1c2VDbGFzczogVGFibGVMYXlvdXRGaXhlZFJlc2l6ZVN0cmF0ZWd5LFxyXG59O1xyXG5leHBvcnQgY29uc3QgRkxFWF9SRVNJWkVfU1RSQVRFR1lfUFJPVklERVI6IFByb3ZpZGVyID0ge1xyXG4gIHByb3ZpZGU6IFJlc2l6ZVN0cmF0ZWd5LFxyXG4gIHVzZUNsYXNzOiBDZGtGbGV4VGFibGVSZXNpemVTdHJhdGVneSxcclxufTtcclxuIl19