UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

292 lines 38.7 kB
import { __decorate, __metadata } from "tslib"; import { Component, ElementRef, EventEmitter, Inject, Injector, Input, Optional, Output, ViewChild } from '@angular/core'; import { Debounce } from '@microsoft/windows-admin-center-sdk/core/base/decorators/debounce.decorators'; import { Yield } from '@microsoft/windows-admin-center-sdk/core/base/decorators/yield.decorator'; import { CoreBaseComponent } from '../common/base.component'; import { SME_LAYOUT_PROVIDER } from '../common/layout'; import { DetailsResponsiveWindowManager } from './details-responsive-window-manager'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; const _c0 = ["expander"]; const _c1 = function (a0, a1) { return { "sme-icon-chevronUpMed": a0, "sme-icon-chevronDownMed": a1 }; }; function DetailsComponent_span_5_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelement(0, "span", 8); } if (rf & 2) { const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵstyleProp("order", ctx_r1.chevronPosition); i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction2(3, _c1, !ctx_r1.isExpanded, ctx_r1.isExpanded)); } } function DetailsComponent_span_6_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelement(0, "span", 8); } if (rf & 2) { const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵstyleProp("order", ctx_r2.chevronPosition); i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction2(3, _c1, ctx_r2.isExpanded, !ctx_r2.isExpanded)); } } function DetailsComponent_hr_12_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelement(0, "hr"); } } const _c2 = function (a0, a1) { return { "sme-layout-absolute-phone-up sme-position-inset-none sme-padding-bottom-sm sme-arrange-overflow-auto": a0, "sme-layout-relative sme-position-stretch-v": a1 }; }; const _c3 = ["*"]; /** * * @smeDoc {@label Details @id sme-details} * * @overview * @file {@filepath ./examples/details-overview.md} * * @example {@label Basic Usage @id basic-usage} * @file {@filename component.ts @filepath ./examples/details-example.component.ts} * @file {@filename component.html @filepath ./examples/details-example.component.html} * */ export var ChevronPosition; (function (ChevronPosition) { ChevronPosition["Left"] = "-1"; ChevronPosition["Right"] = "0"; })(ChevronPosition || (ChevronPosition = {})); export class DetailsComponent extends CoreBaseComponent { constructor(injector, layout) { super(injector); this.resourceStrings = MsftSme.getStrings().MsftSmeShell.Angular.Details; /** * The detail component's height will be determined on the whole children's height. */ this.autoHeight = false; this.isExpandedChange = new EventEmitter(); this.layoutChanged = new EventEmitter(); this.initialHeightPercentage = 30; if (layout) { this.detailsResponsiveWindowManager = new DetailsResponsiveWindowManager(layout); // on parent layout changes, re-emit the layout change to our event this.subscriptions.push(layout.layoutChanged.subscribe((() => this.onLayoutChanged()))); // on window break point changes, emit the event about critical classes and styling updates signal. this.subscriptions.push(layout.windowBreakpointChanged.subscribe(() => this.onWindowBreakpointChanged())); this.deferredOnLayoutChanged(); } } get minExpanderHeight() { return this.detailsResponsiveWindowManager.minExpanderHeight; } get shouldContentSlim() { return this.detailsResponsiveWindowManager.shouldContentSlim; } /** * The source name to use for logging */ get logSourceName() { return 'DetailsComponent'; } /** * @deprecated since 02/25/2019. Please use 'header' instead */ set title(value) { this.header = value; } get title() { return this.header; } ngOnChanges(changes) { super.ngOnChanges(changes); if (changes.isExpanded) { this.onLayoutChanged(); } } toggleExpansion() { this.isExpanded = !this.isExpanded; this.isExpandedChange.emit(this.isExpanded); this.onLayoutChanged(); } refresh() { this.onLayoutChanged(); } /** * The on window breakpoint changed handler. * Adding yield for component to get ElementRef after initialization. */ onWindowBreakpointChanged() { this.detailsResponsiveWindowManager.onWindowSizeChanged(this.hostElement?.nativeElement); } /** * The deferred layout changed handler. */ deferredOnLayoutChanged() { this.onLayoutChanged(); } /** * The layout changed event handler. */ onLayoutChanged() { if (!this.hostElement || !this.hostElement.nativeElement) { return; } const expanderOffsetHeight = MsftSme.getValue(this.expander, 'nativeElement.offsetHeight') || 0; const expanderHeight = expanderOffsetHeight > 0 ? `{0}px`.format(expanderOffsetHeight) : this.minExpanderHeight; if (!this.isExpanded) { this.hostElement.nativeElement.style.height = expanderHeight; this.hostElement.nativeElement.style.minHeight = ''; return; } let potentialHeight = this.hostElement.nativeElement.offsetParent.offsetHeight || 0; const parentOffsetTop = this.hostElement.nativeElement.offsetParent.offsetTop || 0; const totalHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); const detailContentHeight = this.detailsResponsiveWindowManager.detailContentHeight; // Enforces a max height when setting the default height. const maxHeight = detailContentHeight.max; const minHeight = detailContentHeight.min; const phoneDown = detailContentHeight.phoneDown; // On small window height, the detail pane height would be the smaller value [window height * 0.6, maxHeight] if (phoneDown) { potentialHeight = Math.min(totalHeight - parentOffsetTop, potentialHeight); // Prevents the initial size exceed max height potentialHeight = Math.min(potentialHeight, maxHeight); potentialHeight = Math.max(potentialHeight, minHeight); const portHeight = window.innerHeight; if (portHeight < minHeight) { potentialHeight = minHeight; } else if (portHeight > minHeight && portHeight < maxHeight) { // Math.ceil can make calculation without rounding issues. potentialHeight = Math.ceil(portHeight * 0.6); } else if (portHeight > maxHeight && portHeight * 0.4 > maxHeight) { potentialHeight = Math.ceil(maxHeight); } else if (portHeight > maxHeight && portHeight * 0.4 > minHeight) { potentialHeight = Math.ceil(portHeight * 0.4); } this.hostElement.nativeElement.style.height = ''; } else { // Shrink only if exceeds parents offset height; if (potentialHeight > this.hostElement.nativeElement.offsetParent.offsetHeight) { // Set initial expanded height to 30vh. // Poor design that needs to re-visit. const oneVh = totalHeight / 100; potentialHeight = oneVh * this.initialHeightPercentage; } else { // sme-border-top-sm on the details resizer border. // minus the border height to get rid of the extra scroll bar. potentialHeight -= 1; } potentialHeight = Math.min(potentialHeight, maxHeight); potentialHeight = Math.max(potentialHeight, minHeight); this.hostElement.nativeElement.style.minHeight = ''; if (!this.autoHeight) { this.hostElement.nativeElement.style.height = `{0}px`.format(potentialHeight); } else { this.hostElement.nativeElement.style.height = ''; } } setTimeout(() => { // the height would be changed on window height or width change // re-calculate the potential height should be notifying parents. this.layoutChanged.emit(); }); } getInitialHostClasses() { return super.getInitialHostClasses().concat([ 'sme-arrange-stack-v' ]); } createIdBag() { return { detailsSpan: '' }; } } /** @nocollapse */ DetailsComponent.ɵfac = function DetailsComponent_Factory(t) { return new (t || DetailsComponent)(i0.ɵɵdirectiveInject(i0.Injector), i0.ɵɵdirectiveInject(SME_LAYOUT_PROVIDER, 8)); }; /** @nocollapse */ DetailsComponent.ɵcmp = /** @pureOrBreakMyCode */ i0.ɵɵdefineComponent({ type: DetailsComponent, selectors: [["sme-details"]], viewQuery: function DetailsComponent_Query(rf, ctx) { if (rf & 1) { i0.ɵɵviewQuery(_c0, 5); } if (rf & 2) { let _t; i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.expander = _t.first); } }, inputs: { initialHeightPercentage: "initialHeightPercentage", header: "header", chevronInverted: "chevronInverted", chevronPosition: "chevronPosition", addBottomBorder: "addBottomBorder", autoHeight: "autoHeight", title: "title", isExpanded: "isExpanded" }, outputs: { isExpandedChange: "isExpandedChange" }, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], ngContentSelectors: _c3, decls: 13, vars: 20, consts: [["role", "button", "tabindex", "0", 1, "sme-button", "sme-button-trigger", "sme-button-auto-width", "sme-position-flex-none", "sme-padding-squish-v-md", "sme-padding-horizontal-lg", "sme-position-stretch-h", "sme-position-left-inline", "sme-arrange-stack-h", "sme-focus-zone", 3, "click"], ["expander", ""], [1, "sme-font-h3", "sme-position-flex-auto", "sme-arrange-ellipsis"], ["class", "sme-icon sme-position-flex-none sme-margin-horizontal-xs", "aria-hidden", "true", 3, "order", "ngClass", 4, "ngIf"], [1, "sme-screen-reader", 3, "id"], [1, "sme-position-flex-auto", "sme-layout-relative"], [3, "ngClass"], [4, "ngIf"], ["aria-hidden", "true", 1, "sme-icon", "sme-position-flex-none", "sme-margin-horizontal-xs", 3, "ngClass"]], template: function DetailsComponent_Template(rf, ctx) { if (rf & 1) { i0.ɵɵprojectionDef(); i0.ɵɵelementStart(0, "h3")(1, "div", 0, 1); i0.ɵɵlistener("click", function DetailsComponent_Template_div_click_1_listener() { return ctx.toggleExpansion(); }); i0.ɵɵelementStart(3, "span", 2); i0.ɵɵtext(4); i0.ɵɵelementEnd(); i0.ɵɵtemplate(5, DetailsComponent_span_5_Template, 1, 6, "span", 3); i0.ɵɵtemplate(6, DetailsComponent_span_6_Template, 1, 6, "span", 3); i0.ɵɵelementStart(7, "div", 4); i0.ɵɵtext(8); i0.ɵɵelementEnd()()(); i0.ɵɵelementStart(9, "div", 5)(10, "div", 6); i0.ɵɵprojection(11); i0.ɵɵelementEnd()(); i0.ɵɵtemplate(12, DetailsComponent_hr_12_Template, 1, 0, "hr", 7); } if (rf & 2) { i0.ɵɵadvance(1); i0.ɵɵstyleProp("min-height", ctx.minExpanderHeight); i0.ɵɵattribute("aria-expanded", !!ctx.isExpanded)("aria-describedBy", ctx.idBag.detailsSpan); i0.ɵɵadvance(3); i0.ɵɵtextInterpolate(ctx.header); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", !ctx.chevronInverted); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", ctx.chevronInverted); i0.ɵɵadvance(1); i0.ɵɵproperty("id", ctx.idBag.detailsSpan); i0.ɵɵadvance(1); i0.ɵɵtextInterpolate1(" ", ctx.resourceStrings.AriaDescription, ""); i0.ɵɵadvance(1); i0.ɵɵclassProp("sme-margin-horizontal-lg", ctx.shouldContentSlim)("sme-position-stretch-v", ctx.autoHeight); i0.ɵɵadvance(1); i0.ɵɵclassProp("sme-layout-none", !ctx.isExpanded); i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction2(17, _c2, !ctx.autoHeight, ctx.autoHeight)); i0.ɵɵadvance(2); i0.ɵɵproperty("ngIf", ctx.addBottomBorder); } }, dependencies: [i1.NgClass, i1.NgIf], encapsulation: 2 }); __decorate([ Yield(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], DetailsComponent.prototype, "onWindowBreakpointChanged", null); __decorate([ Debounce(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], DetailsComponent.prototype, "deferredOnLayoutChanged", null); __decorate([ Yield(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], DetailsComponent.prototype, "onLayoutChanged", null); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DetailsComponent, [{ type: Component, args: [{ selector: 'sme-details', template: "<h3>\r\n <div #expander\r\n class=\"sme-button sme-button-trigger sme-button-auto-width sme-position-flex-none sme-padding-squish-v-md sme-padding-horizontal-lg sme-position-stretch-h sme-position-left-inline sme-arrange-stack-h sme-focus-zone\"\r\n role=\"button\" tabindex=\"0\" (click)=\"toggleExpansion()\" [style.min-height]=\"minExpanderHeight\"\r\n [attr.aria-expanded]=\"!!isExpanded\" [attr.aria-describedBy]=\"idBag.detailsSpan\">\r\n <span class=\"sme-font-h3 sme-position-flex-auto sme-arrange-ellipsis\">{{ header }}</span>\r\n <span [style.order]=\"chevronPosition\" *ngIf=\"!chevronInverted\" class=\"sme-icon sme-position-flex-none sme-margin-horizontal-xs\"\r\n [ngClass]=\"{'sme-icon-chevronUpMed': !isExpanded, 'sme-icon-chevronDownMed': isExpanded}\"\r\n aria-hidden=\"true\"></span>\r\n <span [style.order]=\"chevronPosition\" *ngIf=\"chevronInverted\" class=\"sme-icon sme-position-flex-none sme-margin-horizontal-xs\"\r\n [ngClass]=\"{'sme-icon-chevronUpMed': isExpanded, 'sme-icon-chevronDownMed': !isExpanded}\"\r\n aria-hidden=\"true\"></span>\r\n <div class=\"sme-screen-reader\" [id]=\"idBag.detailsSpan\"> {{ resourceStrings.AriaDescription }}</div>\r\n </div>\r\n</h3>\r\n\r\n<div class=\"sme-position-flex-auto sme-layout-relative\" [class.sme-margin-horizontal-lg]=\"shouldContentSlim\" [class.sme-position-stretch-v]=\"autoHeight\">\r\n <div [ngClass]=\"{'sme-layout-absolute-phone-up sme-position-inset-none sme-padding-bottom-sm sme-arrange-overflow-auto': !autoHeight, 'sme-layout-relative sme-position-stretch-v': autoHeight}\"\r\n [class.sme-layout-none]=\"!isExpanded\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n\r\n<hr *ngIf=\"addBottomBorder\">\r\n" }] }], function () { return [{ type: i0.Injector }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [SME_LAYOUT_PROVIDER] }] }]; }, { expander: [{ type: ViewChild, args: ['expander'] }], initialHeightPercentage: [{ type: Input }], header: [{ type: Input }], chevronInverted: [{ type: Input }], chevronPosition: [{ type: Input }], addBottomBorder: [{ type: Input }], autoHeight: [{ type: Input }], title: [{ type: Input }], isExpanded: [{ type: Input }], isExpandedChange: [{ type: Output }], onWindowBreakpointChanged: [], deferredOnLayoutChanged: [], onLayoutChanged: [] }); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV0YWlscy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9hbmd1bGFyL3NyYy9jb250cm9scy9kZXRhaWxzL2RldGFpbHMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vYW5ndWxhci9zcmMvY29udHJvbHMvZGV0YWlscy9kZXRhaWxzLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQ0gsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osTUFBTSxFQUNOLFFBQVEsRUFDUixLQUFLLEVBRUwsUUFBUSxFQUNSLE1BQU0sRUFFTixTQUFTLEVBQ1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDhFQUE4RSxDQUFDO0FBQ3hHLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSwwRUFBMEUsQ0FBQztBQUVqRyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM3RCxPQUFPLEVBQVUsbUJBQW1CLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMvRCxPQUFPLEVBQUUsOEJBQThCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQzs7Ozs7O0lDWmpGLDBCQUU0Qjs7O0lBRnRCLCtDQUErQjtJQUNuQywyRkFBeUY7OztJQUUzRiwwQkFFNEI7OztJQUZ0QiwrQ0FBK0I7SUFDbkMsMkZBQXlGOzs7SUFhL0YscUJBQTRCOzs7O0FESDVCOzs7Ozs7Ozs7OztHQVdHO0FBRUgsTUFBTSxDQUFOLElBQVksZUFHWDtBQUhELFdBQVksZUFBZTtJQUN2Qiw4QkFBVyxDQUFBO0lBQ1gsOEJBQVcsQ0FBQTtBQUNmLENBQUMsRUFIVyxlQUFlLEtBQWYsZUFBZSxRQUcxQjtBQUtELE1BQU0sT0FBTyxnQkFBaUIsU0FBUSxpQkFBaUI7SUFnRW5ELFlBQVksUUFBa0IsRUFBMkMsTUFBYztRQUNuRixLQUFL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LEVBQUE7UUFHUixpRUFBNEI7O1FBcEIrQixlQUFzQztRQUF0QyxtREFBc0M7UUFDN0YsaURBQW1DLDJDQUFBO1FBQ21DLGVBQVk7UUFBWixnQ0FBWTtRQUMzQyxlQUFzQjtRQUF0QiwyQ0FBc0I7UUFHdEIsZUFBcUI7UUFBckIsMENBQXFCO1FBRzdCLGVBQXdCO1FBQXhCLDBDQUF3QjtRQUFFLGVBQXFDO1FBQXJDLG1FQUFxQztRQUkxQyxlQUFvRDtRQUFwRCxpRUFBb0QsMENBQUE7UUFFeEcsZUFBcUM7UUFBckMsa0RBQXFDO1FBRGxDLHNGQUEyTDtRQU03TCxlQUFxQjtRQUFyQiwwQ0FBcUI7O0FEcUh0QjtJQUFDLEtBQUssRUFBRTs7OztpRUFHUDtBQUtEO0lBQUMsUUFBUSxFQUFFOzs7OytEQUdWO0FBS0Q7SUFBQyxLQUFLLEVBQUU7Ozs7dURBMkVQO3VGQTlMUSxnQkFBZ0I7Y0FKNUIsU0FBUzsyQkFDSSxhQUFhOztzQkFtRVUsUUFBUTs7c0JBQUksTUFBTTt1QkFBQyxtQkFBbUI7d0JBN0NoRSxRQUFRO2tCQURkLFNBQVM7bUJBQUMsVUFBVTtZQUlkLHVCQUF1QjtrQkFEN0IsS0FBSztZQUlDLE1BQU07a0JBRFosS0FBSztZQUlDLGVBQWU7a0JBRHJCLEtBQUs7WUFJQyxlQUFlO2tCQURyQixLQUFLO1lBSUMsZUFBZTtrQkFEckIsS0FBSztZQU9DLFVBQVU7a0JBRGhCLEtBQUs7WUFPSyxLQUFLO2tCQURmLEtBQUs7WUFVQyxVQUFVO2tCQURoQixLQUFLO1lBSUMsZ0JBQWdCO2tCQUR0QixNQUFNO1lBMkNBLHlCQUF5QixNQVF4Qix1QkFBdUIsTUFRdkIsZUFBZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgICBDb21wb25lbnQsXHJcbiAgICBFbGVtZW50UmVmLFxyXG4gICAgRXZlbnRFbWl0dGVyLFxyXG4gICAgSW5qZWN0LFxyXG4gICAgSW5qZWN0b3IsXHJcbiAgICBJbnB1dCxcclxuICAgIE9uQ2hhbmdlcyxcclxuICAgIE9wdGlvbmFsLFxyXG4gICAgT3V0cHV0LFxyXG4gICAgU2ltcGxlQ2hhbmdlcyxcclxuICAgIFZpZXdDaGlsZFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBEZWJvdW5jZSB9IGZyb20gJ0BtaWNyb3NvZnQvd2luZG93cy1hZG1pbi1jZW50ZXItc2RrL2NvcmUvYmFzZS9kZWNvcmF0b3JzL2RlYm91bmNlLmRlY29yYXRvcnMnO1xyXG5pbXBvcnQgeyBZaWVsZCB9IGZyb20gJ0BtaWNyb3NvZnQvd2luZG93cy1hZG1pbi1jZW50ZXItc2RrL2NvcmUvYmFzZS9kZWNvcmF0b3JzL3lpZWxkLmRlY29yYXRvcic7XHJcbmltcG9ydCB7IFN0cmluZ3MgfSBmcm9tICcuLi8uLi9nZW5lcmF0ZWQvc3RyaW5ncyc7XHJcbmltcG9ydCB7IENvcmVCYXNlQ29tcG9uZW50IH0gZnJvbSAnLi4vY29tbW9uL2Jhc2UuY29tcG9uZW50JztcclxuaW1wb3J0IHsgTGF5b3V0LCBTTUVfTEFZT1VUX1BST1ZJREVSIH0gZnJvbSAnLi4vY29tbW9uL2xheW91dCc7XHJcbmltcG9ydCB7IERldGFpbHNSZXNwb25zaXZlV2luZG93TWFuYWdlciB9IGZyb20gJy4vZGV0YWlscy1yZXNwb25zaXZlLXdpbmRvdy1tYW5hZ2VyJztcclxuXHJcbi8qKlxyXG4gKlxyXG4gKiBAc21lRG9jIHtAbGFiZWwgRGV0YWlscyBAaWQgc21lLWRldGFpbHN9XHJcbiAqXHJcbiAqIEBvdmVydmlld1xyXG4gKiBAZmlsZSB7QGZpbGVwYXRoIC4vZXhhbXBsZXMvZGV0YWlscy1vdmVydmlldy5tZH1cclxuICpcclxuICogQGV4YW1wbGUge0BsYWJlbCBCYXNpYyBVc2FnZSBAaWQgYmFzaWMtdXNhZ2V9XHJcbiAqIEBmaWxlIHtAZmlsZW5hbWUgY29tcG9uZW50LnRzIEBmaWxlcGF0aCAuL2V4YW1wbGVzL2RldGFpbHMtZXhhbXBsZS5jb21wb25lbnQudHN9XHJcbiAqIEBmaWxlIHtAZmlsZW5hbWUgY29tcG9uZW50Lmh0bWwgQGZpbGVwYXRoIC4vZXhhbXBsZXMvZGV0YWlscy1leGFtcGxlLmNvbXBvbmVudC5odG1sfVxyXG4gKlxyXG4gKi9cclxuXHJcbmV4cG9ydCBlbnVtIENoZXZyb25Qb3NpdGlvbiB7XHJcbiAgICBMZWZ0ID0gJy0xJyxcclxuICAgIFJpZ2h0ID0gJzAnXHJcbn1cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ3NtZS1kZXRhaWxzJyxcclxuICAgIHRlbXBsYXRlVXJsOiAnLi9kZXRhaWxzLmNvbXBvbmVudC5odG1sJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgRGV0YWlsc0NvbXBvbmVudCBleHRlbmRzIENvcmVCYXNlQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzIHtcclxuXHJcbiAgICBwdWJsaWMgZ2V0IG1pbkV4cGFuZGVySGVpZ2h0KCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmRldGFpbHNSZXNwb25zaXZlV2luZG93TWFuYWdlci5taW5FeHBhbmRlckhlaWdodDtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0IHNob3VsZENvbnRlbnRTbGltKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmRldGFpbHNSZXNwb25zaXZlV2luZG93TWFuYWdlci5zaG91bGRDb250ZW50U2xpbTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBzb3VyY2UgbmFtZSB0byB1c2UgZm9yIGxvZ2dpbmdcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGdldCBsb2dTb3VyY2VOYW1lKCkge1xyXG4gICAgICAgIHJldHVybiAnRGV0YWlsc0NvbXBvbmVudCc7XHJcbiAgICB9XHJcbiAgICBwdWJsaWMgcmVzb3VyY2VTdHJpbmdzID0gTXNmdFNtZS5nZXRTdHJpbmdzPFN0cmluZ3M+KCkuTXNmdFNtZVNoZWxsLkFuZ3VsYXIuRGV0YWlscztcclxuXHJcbiAgICBAVmlld0NoaWxkKCdleHBhbmRlcicpXHJcbiAgICBwdWJsaWMgZXhwYW5kZXI6IEVsZW1lbnRSZWY7XHJcblxyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBpbml0aWFsSGVpZ2h0UGVyY2VudGFnZTogbnVtYmVyO1xyXG5cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgaGVhZGVyOiBzdHJpbmc7XHJcblxyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBjaGV2cm9uSW52ZXJ0ZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBjaGV2cm9uUG9zaXRpb246IHN0cmluZztcclxuXHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIGFkZEJvdHRvbUJvcmRlcjogYm9vbGVhbjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBkZXRhaWwgY29tcG9uZW50J3MgaGVpZ2h0IHdpbGwgYmUgZGV0ZXJtaW5lZCBvbiB0aGUgd2hvbGUgY2hpbGRyZW4ncyBoZWlnaHQuXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgYXV0b0hlaWdodCA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGRlcHJlY2F0ZWQgc2luY2UgMDIvMjUvMjAxOS4gUGxlYXNlIHVzZSAnaGVhZGVyJyBpbnN0ZWFkXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2V0IHRpdGxlKHZhbHVlOiBzdHJpbmcpIHtcclxuICAgICAgICB0aGlzLmhlYWRlciA9IHZhbHVlO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgdGl0bGUoKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5oZWFkZXI7XHJcbiAgICB9XHJcblxyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBpc0V4cGFuZGVkOiBib29sZWFuO1xyXG5cclxuICAgIEBPdXRwdXQoKVxyXG4gICAgcHVibGljIGlzRXhwYW5kZWRDaGFuZ2U6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcclxuXHJcbiAgICBwdWJsaWMgbGF5b3V0Q2hhbmdlZDogRXZlbnRFbWl0dGVyPHZvaWQ+ID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG5cclxuICAgIHByaXZhdGUgZGV0YWlsc1Jlc3BvbnNpdmVXaW5kb3dNYW5hZ2VyOiBEZXRhaWxzUmVzcG9uc2l2ZVdpbmRvd01hbmFnZXI7XHJcblxyXG4gICAgY29uc3RydWN0b3IoaW5qZWN0b3I6IEluamVjdG9yLCBAT3B0aW9uYWwoKSBASW5qZWN0KFNNRV9MQVlPVVRfUFJPVklERVIpIGxheW91dDogTGF5b3V0KSB7XHJcbiAgICAgICAgc3VwZXIoaW5qZWN0b3IpO1xyXG4gICAgICAgIHRoaXMuaW5pdGlhbEhlaWdodFBlcmNlbnRhZ2UgPSAzMDtcclxuICAgICAgICBpZiAobGF5b3V0KSB7XHJcbiAgICAgICAgICAgIHRoaXMuZGV0YWlsc1Jlc3BvbnNpdmVXaW5kb3dNYW5hZ2VyID0gbmV3IERldGFpbHNSZXNwb25zaXZlV2luZG93TWFuYWdlcihsYXlvdXQpO1xyXG4gICAgICAgICAgICAvLyBvbiBwYXJlbnQgbGF5b3V0IGNoYW5nZXMsIHJlLWVtaXQgdGhlIGxheW91dCBjaGFuZ2UgdG8gb3VyIGV2ZW50XHJcbiAgICAgICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKGxheW91dC5sYXlvdXRDaGFuZ2VkLnN1YnNjcmliZSgoKCkgPT4gdGhpcy5vbkxheW91dENoYW5nZWQoKSkpKTtcclxuICAgICAgICAgICAgLy8gb24gd2luZG93IGJyZWFrIHBvaW50IGNoYW5nZXMsIGVtaXQgdGhlIGV2ZW50IGFib3V0IGNyaXRpY2FsIGNsYXNzZXMgYW5kIHN0eWxpbmcgdXBkYXRlcyBzaWduYWwuXHJcbiAgICAgICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKGxheW91dC53aW5kb3dCcmVha3BvaW50Q2hhbmdlZC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5vbldpbmRvd0JyZWFrcG9pbnRDaGFuZ2VkKCkpKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuZGVmZXJyZWRPbkxheW91dENoYW5nZWQoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcclxuICAgICAgICBzdXBlci5uZ09uQ2hhbmdlcyhjaGFuZ2VzKTtcclxuICAgICAgICBpZiAoY2hhbmdlcy5pc0V4cGFuZGVkKSB7XHJcbiAgICAgICAgICAgIHRoaXMub25MYXlvdXRDaGFuZ2VkKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyB0b2dnbGVFeHBhbnNpb24oKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5pc0V4cGFuZGVkID0gIXRoaXMuaXNFeHBhbmRlZDtcclxuICAgICAgICB0aGlzLmlzRXhwYW5kZWRDaGFuZ2UuZW1pdCh0aGlzLmlzRXhwYW5kZWQpO1xyXG4gICAgICAgIHRoaXMub25MYXlvdXRDaGFuZ2VkKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHJlZnJlc2goKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5vbkxheW91dENoYW5nZWQoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBvbiB3aW5kb3cgYnJlYWtwb2ludCBjaGFuZ2VkIGhhbmRsZXIuXHJcbiAgICAgKiBBZGRpbmcgeWllbGQgZm9yIGNvbXBvbmVudCB0byBnZXQgRWxlbWVudFJlZiBhZnRlciBpbml0aWFsaXphdGlvbi5cclxuICAgICAqL1xyXG4gICAgQFlpZWxkKClcclxuICAgIHB1YmxpYyBvbldpbmRvd0JyZWFrcG9pbnRDaGFuZ2VkKCkge1xyXG4gICAgICAgIHRoaXMuZGV0YWlsc1Jlc3BvbnNpdmVXaW5kb3dNYW5hZ2VyLm9uV2luZG93U2l6ZUNoYW5nZWQodGhpcy5ob3N0RWxlbWVudD8ubmF0aXZlRWxlbWVudCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgZGVmZXJyZWQgbGF5b3V0IGNoYW5nZWQgaGFuZGxlci5cclxuICAgICAqL1xyXG4gICAgQERlYm91bmNlKClcclxuICAgIHByaXZhdGUgZGVmZXJyZWRPbkxheW91dENoYW5nZWQoKSB7XHJcbiAgICAgICAgdGhpcy5vbkxheW91dENoYW5nZWQoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBsYXlvdXQgY2hhbmdlZCBldmVudCBoYW5kbGVyLlxyXG4gICAgICovXHJcbiAgICBAWWllbGQoKVxyXG4gICAgcHJpdmF0ZSBvbkxheW91dENoYW5nZWQoKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKCF0aGlzLmhvc3RFbGVtZW50IHx8ICF0aGlzLmhvc3RFbGVtZW50Lm5hdGl2ZUVsZW1lbnQpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgZXhwYW5kZXJPZmZzZXRIZWlnaHQgPSBNc2Z0U21lLmdldFZhbHVlPG51bWJlcj4odGhpcy5leHBhbmRlciwgJ25hdGl2ZUVsZW1lbnQub2Zmc2V0SGVpZ2h0JykgfHwgMDtcclxuICAgICAgICBjb25zdCBleHBhbmRlckhlaWdodCA9IGV4cGFuZGVyT2Zmc2V0SGVpZ2h0ID4gMCA/IGB7MH1weGAuZm9ybWF0KGV4cGFuZGVyT2Zmc2V0SGVpZ2h0KSA6IHRoaXMubWluRXhwYW5kZXJIZWlnaHQ7XHJcbiAgICAgICAgaWYgKCF0aGlzLmlzRXhwYW5kZWQpIHtcclxuICAgICAgICAgICAgdGhpcy5ob3N0RWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLmhlaWdodCA9IGV4cGFuZGVySGVpZ2h0O1xyXG4gICAgICAgICAgICB0aGlzLmhvc3RFbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUubWluSGVpZ2h0ID0gJyc7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBwb3RlbnRpYWxIZWlnaHQgPSB0aGlzLmhvc3RFbGVtZW50Lm5hdGl2ZUVsZW1lbnQub2Zmc2V0UGFyZW50Lm9mZnNldEhlaWdodCB8fCAwO1xyXG4gICAgICAgIGNvbnN0IHBhcmVudE9mZnNldFRvcCA9IHRoaXMuaG9zdEVsZW1lbnQubmF0aXZlRWxlbWVudC5vZmZzZXRQYXJlbnQub2Zmc2V0VG9wIHx8IDA7XHJcbiAgICAgICAgY29uc3QgdG90YWxIZWlnaHQgPSBNYXRoLm1heChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0LCB3aW5kb3cuaW5uZXJIZWlnaHQgfHwgMCk7XHJcblxyXG4gICAgICAgIGNvbnN0IGRldGFpbENvbnRlbnRIZWlnaHQgPSB0aGlzLmRldGFpbHNSZXNwb25zaXZlV2luZG93TWFuYWdlci5kZXRhaWxDb250ZW50SGVpZ2h0O1xyXG5cclxuICAgICAgICAvLyBFbmZvcmNlcyBhIG1heCBoZWlnaHQgd2hlbiBzZXR0aW5nIHRoZSBkZWZhdWx0IGhlaWdodC5cclxuICAgICAgICBjb25zdCBtYXhIZWlnaHQgPSBkZXRhaWxDb250ZW50SGVpZ2h0Lm1heDtcclxuICAgICAgICBjb25zdCBtaW5IZWlnaHQgPSBkZXRhaWxDb250ZW50SGVpZ2h0Lm1pbjtcclxuICAgICAgICBjb25zdCBwaG9uZURvd24gPSBkZXRhaWxDb250ZW50SGVpZ2h0LnBob25lRG93bjtcclxuXHJcbiAgICAgICAgLy8gT24gc21hbGwgd2luZG93IGhlaWdodCwgdGhlIGRldGFpbCBwYW5lIGhlaWdodCB3b3VsZCBiZSB0aGUgc21hbGxlciB2YWx1ZSBbd2luZG93IGhlaWdodCAqIDAuNiwgbWF4SGVpZ2h0XVxyXG4gICAgICAgIGlmIChwaG9uZURvd24pIHtcclxuICAgICAgICAgICAgcG90ZW50aWFsSGVpZ2h0ID0gTWF0aC5taW4odG90YWxIZWlnaHQgLSBwYXJlbnRPZmZzZXRUb3AsIHBvdGVudGlhbEhlaWdodCk7XHJcbiAgICAgICAgICAgIC8vIFByZXZlbnRzIHRoZSBpbml0aWFsIHNpemUgZXhjZWVkIG1heCBoZWlnaHRcclxuICAgICAgICAgICAgcG90ZW50aWFsSGVpZ2h0ID0gTWF0aC5taW4ocG90ZW50aWFsSGVpZ2h0LCBtYXhIZWlnaHQpO1xyXG4gICAgICAgICAgICBwb3RlbnRpYWxIZWlnaHQgPSBNYXRoLm1heChwb3RlbnRpYWxIZWlnaHQsIG1pbkhlaWdodCk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBwb3J0SGVpZ2h0ID0gd2luZG93LmlubmVySGVpZ2h0O1xyXG4gICAgICAgICAgICBpZiAocG9ydEhlaWdodCA8IG1pbkhlaWdodCkge1xyXG4gICAgICAgICAgICAgICAgcG90ZW50aWFsSGVpZ2h0ID0gbWluSGVpZ2h0O1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHBvcnRIZWlnaHQgPiBtaW5IZWlnaHQgJiYgcG9ydEhlaWdodCA8IG1heEhlaWdodCkge1xyXG4gICAgICAgICAgICAgICAgLy8gTWF0aC5jZWlsIGNhbiBtYWtlIGNhbGN1bGF0aW9uIHdpdGhvdXQgcm91bmRpbmcgaXNzdWVzLlxyXG4gICAgICAgICAgICAgICAgcG90ZW50aWFsSGVpZ2h0ID0gTWF0aC5jZWlsKHBvcnRIZWlnaHQgKiAwLjYpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHBvcnRIZWlnaHQgPiBtYXhIZWlnaHQgJiYgcG9ydEhlaWdodCAqIDAuNCA+IG1heEhlaWdodCkge1xyXG4gICAgICAgICAgICAgICAgcG90ZW50aWFsSGVpZ2h0ID0gTWF0aC5jZWlsKG1heEhlaWdodCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocG9ydEhlaWdodCA+IG1heEhlaWdodCAmJiBwb3J0SGVpZ2h0ICogMC40ID4gbWluSGVpZ2h0KSB7XHJcbiAgICAgICAgICAgICAgICBwb3RlbnRpYWxIZWlnaHQgPSBNYXRoLmNlaWwocG9ydEhlaWdodCAqIDAuNCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRoaXMuaG9zdEVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQgPSAnJztcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBTaHJpbmsgb25seSBpZiBleGNlZWRzIHBhcmVudHMgb2Zmc2V0IGhlaWdodDtcclxuICAgICAgICAgICAgaWYgKHBvdGVudGlhbEhlaWdodCA+IHRoaXMuaG9zdEVsZW1lbnQubmF0aXZlRWxlbWVudC5vZmZzZXRQYXJlbnQub2Zmc2V0SGVpZ2h0KSB7XHJcbiAgICAgICAgICAgICAgICAvLyBTZXQgaW5pdGlhbCBleHBhbmRlZCBoZWlnaHQgdG8gMzB2aC5cclxuICAgICAgICAgICAgICAgIC8vIFBvb3IgZGVzaWduIHRoYXQgbmVlZHMgdG8gcmUtdmlzaXQuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBvbmVWaCA9IHRvdGFsSGVpZ2h0IC8gMTAwO1xyXG4gICAgICAgICAgICAgICAgcG90ZW50aWFsSGVpZ2h0ID0gb25lVmggKiB0aGlzLmluaXRpYWxIZWlnaHRQZXJjZW50YWdlO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgLy8gc21lLWJvcmRlci10b3Atc20gb24gdGhlIGRldGFpbHMgcmVzaXplciBib3JkZXIuXHJcbiAgICAgICAgICAgICAgICAvLyBtaW51cyB0aGUgYm9yZGVyIGhlaWdodCB0byBnZXQgcmlkIG9mIHRoZSBleHRyYSBzY3JvbGwgYmFyLlxyXG4gICAgICAgICAgICAgICAgcG90ZW50aWFsSGVpZ2h0IC09IDE7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHBvdGVudGlhbEhlaWdodCA9IE1hdGgubWluKHBvdGVudGlhbEhlaWdodCwgbWF4SGVpZ2h0KTtcclxuICAgICAgICAgICAgcG90ZW50aWFsSGVpZ2h0ID0gTWF0aC5tYXgocG90ZW50aWFsSGVpZ2h0LCBtaW5IZWlnaHQpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5ob3N0RWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLm1pbkhlaWdodCA9ICcnO1xyXG5cclxuICAgICAgICAgICAgaWYgKCF0aGlzLmF1dG9IZWlnaHQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuaG9zdEVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQgPSBgezB9cHhgLmZvcm1hdChwb3RlbnRpYWxIZWlnaHQpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5ob3N0RWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLmhlaWdodCA9ICcnO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgLy8gdGhlIGhlaWdodCB3b3VsZCBiZSBjaGFuZ2VkIG9uIHdpbmRvdyBoZWlnaHQgb3Igd2lkdGggY2hhbmdlXHJcbiAgICAgICAgICAgIC8vIHJlLWNhbGN1bGF0ZSB0aGUgcG90ZW50aWFsIGhlaWdodCBzaG91bGQgYmUgbm90aWZ5aW5nIHBhcmVudHMuXHJcbiAgICAgICAgICAgIHRoaXMubGF5b3V0Q2hhbmdlZC5lbWl0KCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJvdGVjdGVkIGdldEluaXRpYWxIb3N0Q2xhc3NlcygpIHtcclxuICAgICAgICByZXR1cm4gc3VwZXIuZ2V0SW5pdGlhbEhvc3RDbGFzc2VzKCkuY29uY2F0KFtcclxuICAgICAgICAgICAgJ3NtZS1hcnJhbmdlLXN0YWNrLXYnXHJcbiAgICAgICAgXSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJvdGVjdGVkIGNyZWF0ZUlkQmFnKCk6IE1zZnRTbWUuU3RyaW5nTWFwPHN0cmluZz4ge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIGRldGFpbHNTcGFuOiAnJ1xyXG4gICAgICAgIH07XHJcbiAgICB9XHJcbn1cclxuIiwiPGgzPlxyXG4gIDxkaXYgI2V4cGFuZGVyXHJcbiAgICBjbGFzcz1cInNtZS1idXR0b24gc21lLWJ1dHRvbi10cmlnZ2VyIHNtZS1idXR0b24tYXV0by13aWR0aCBzbWUtcG9zaXRpb24tZmxleC1ub25lIHNtZS1wYWRkaW5nLXNxdWlzaC12LW1kIHNtZS1wYWRkaW5nLWhvcml6b250YWwtbGcgc21lLXBvc2l0aW9uLXN0cmV0Y2gtaCBzbWUtcG9zaXRpb24tbGVmdC1pbmxpbmUgc21lLWFycmFuZ2Utc3RhY2staCBzbWUtZm9jdXMtem9uZVwiXHJcbiAgICByb2xlPVwiYnV0dG9uXCIgdGFiaW5kZXg9XCIwXCIgKGNsaWNrKT1cInRvZ2dsZUV4cGFuc2lvbigpXCIgW3N0eWxlLm1pbi1oZWlnaHRdPVwibWluRXhwYW5kZXJIZWlnaHRcIlxyXG4gICAgW2F0dHIuYXJpYS1leHBhbmRlZF09XCIhIWlzRXhwYW5kZWRcIiBbYXR0ci5hcmlhLWRlc2NyaWJlZEJ5XT1cImlkQmFnLmRldGFpbHNTcGFuXCI+XHJcbiAgICA8c3BhbiBjbGFzcz1cInNtZS1mb250LWgzIHNtZS1wb3NpdGlvbi1mbGV4LWF1dG8gc21lLWFycmFuZ2UtZWxsaXBzaXNcIj57eyBoZWFkZXIgfX08L3NwYW4+XHJcbiAgICA8c3BhbiBbc3R5bGUub3JkZXJdPVwiY2hldnJvblBvc2l0aW9uXCIgKm5nSWY9XCIhY2hldnJvbkludmVydGVkXCIgY2xhc3M9XCJzbWUtaWNvbiBzbWUtcG9zaXRpb24tZmxleC1ub25lIHNtZS1tYXJnaW4taG9yaXpvbnRhbC14c1wiXHJcbiAgICAgIFtuZ0NsYXNzXT1cInsnc21lLWljb24tY2hldnJvblVwTWVkJzogIWlzRXhwYW5kZWQsICdzbWUtaWNvbi1jaGV2cm9uRG93bk1lZCc6IGlzRXhwYW5kZWR9XCJcclxuICAgICAgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9zcGFuPlxyXG4gICAgPHNwYW4gW3N0eWxlLm9yZGVyXT1cImNoZXZyb25Qb3NpdGlvblwiICpuZ0lmPVwiY2hldnJvbkludmVydGVkXCIgY2xhc3M9XCJzbWUtaWNvbiBzbWUtcG9zaXRpb24tZmxleC1ub25lIHNtZS1tYXJnaW4taG9yaXpvbnRhbC14c1wiXHJcbiAgICAgIFtuZ0NsYXNzXT1cInsnc21lLWljb24tY2hldnJvblVwTWVkJzogaXNFeHBhbmRlZCwgJ3NtZS1pY29uLWNoZXZyb25Eb3duTWVkJzogIWlzRXhwYW5kZWR9XCJcclxuICAgICAgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9zcGFuPlxyXG4gICAgPGRpdiBjbGFzcz1cInNtZS1zY3JlZW4tcmVhZGVyXCIgW2lkXT1cImlkQmFnLmRldGFpbHNTcGFuXCI+IHt7IHJlc291cmNlU3RyaW5ncy5BcmlhRGVzY3JpcHRpb24gfX08L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9oMz5cclxuXHJcbjxkaXYgY2xhc3M9XCJzbWUtcG9zaXRpb24tZmxleC1hdXRvIHNtZS1sYXlvdXQtcmVsYXRpdmVcIiBbY2xhc3Muc21lLW1hcmdpbi1ob3Jpem9udGFsLWxnXT1cInNob3VsZENvbnRlbnRTbGltXCIgW2NsYXNzLnNtZS1wb3NpdGlvbi1zdHJldGNoLXZdPVwiYXV0b0hlaWdodFwiPlxyXG4gIDxkaXYgW25nQ2xhc3NdPVwieydzbWUtbGF5b3V0LWFic29sdXRlLXBob25lLXVwIHNtZS1wb3NpdGlvbi1pbnNldC1ub25lIHNtZS1wYWRkaW5nLWJvdHRvbS1zbSBzbWUtYXJyYW5nZS1vdmVyZmxvdy1hdXRvJzogIWF1dG9IZWlnaHQsICdzbWUtbGF5b3V0LXJlbGF0aXZlIHNtZS1wb3NpdGlvbi1zdHJldGNoLXYnOiBhdXRvSGVpZ2h0fVwiXHJcbiAgICBbY2xhc3Muc21lLWxheW91dC1ub25lXT1cIiFpc0V4cGFuZGVkXCI+XHJcbiAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XHJcbiAgPC9kaXY+XHJcbjwvZGl2PlxyXG5cclxuPGhyICpuZ0lmPVwiYWRkQm90dG9tQm9yZGVyXCI+XHJcbiJdfQ==