cfc-ds
Version:
Design System do Conselho Federal de Contabilidade baseado no govbr-ds
188 lines • 38.9 kB
JavaScript
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/flex-layout/extended";
export class ModalComponent {
elementRef;
isOpen = false;
title;
primaryButtonLabel;
secondaryButtonLabel;
hasCloseButton = true;
closeOnOverlayClick = true;
isLoading = false;
autoCloseTimeout;
maxWidth = '480px';
alignButtons = 'right';
singleButtonCenter = true;
size = 'medium';
width;
customClass;
close = new EventEmitter();
primaryClick = new EventEmitter();
secondaryClick = new EventEmitter();
titleElement;
modalContainer;
isTitleOverflowing = false;
fullTitle = '';
autoCloseTimer;
constructor(elementRef) {
this.elementRef = elementRef;
}
ngOnInit() {
if (this.isOpen && this.autoCloseTimeout) {
this.startAutoCloseTimer();
}
}
ngOnChanges(changes) {
if (changes['isOpen'] && changes['isOpen'].currentValue) {
document.body.style.overflow = 'hidden';
if (this.autoCloseTimeout) {
this.startAutoCloseTimer();
}
// Adiciona listener para a tecla ESC
document.addEventListener('keydown', this.handleEscKey);
}
else if (changes['isOpen'] && !changes['isOpen'].currentValue) {
document.body.style.overflow = 'auto';
this.clearAutoCloseTimer();
document.removeEventListener('keydown', this.handleEscKey);
}
// Verifica o título quando ele mudar
if (changes['title'] && this.titleElement) {
this.checkTitleOverflow();
}
}
ngAfterViewInit() {
if (this.title && this.titleElement) {
this.checkTitleOverflow();
}
}
ngOnDestroy() {
document.body.style.overflow = 'auto';
this.clearAutoCloseTimer();
document.removeEventListener('keydown', this.handleEscKey);
}
handleEscKey = (event) => {
if (event.key === 'Escape' && this.isOpen) {
this.onClose();
}
};
onOverlayClick(event) {
if (this.closeOnOverlayClick &&
this.modalContainer &&
!this.modalContainer.nativeElement.contains(event.target)) {
this.onClose();
}
}
onClose() {
this.close.emit();
}
onPrimaryClick() {
this.primaryClick.emit();
}
onSecondaryClick() {
if (this.secondaryClick.observers.length) {
this.secondaryClick.emit();
}
else {
this.onClose();
}
}
getButtonsClass() {
if (this.secondaryButtonLabel && this.primaryButtonLabel) {
return this.alignButtons === 'right' ? 'modal-buttons-right' : 'modal-buttons-center';
}
return this.singleButtonCenter ? 'modal-buttons-center' : 'modal-buttons-right';
}
checkTitleOverflow() {
if (!this.titleElement)
return;
const element = this.titleElement.nativeElement;
this.fullTitle = this.title || '';
// Resetar o conteúdo para o título original para verificar o overflow
element.textContent = this.fullTitle;
if (element.scrollHeight > element.clientHeight ||
element.scrollWidth > element.clientWidth) {
this.isTitleOverflowing = true;
// Truncar o título e adicionar reticências
const words = this.fullTitle.split(' ');
let truncatedTitle = '';
let i = 0;
while (i < words.length) {
const testTitle = truncatedTitle + ' ' + words[i];
element.textContent = testTitle + '...';
if (element.scrollHeight > element.clientHeight ||
element.scrollWidth > element.clientWidth) {
break;
}
truncatedTitle = testTitle;
i++;
}
element.textContent = truncatedTitle.trim() + '...';
}
else {
this.isTitleOverflowing = false;
}
}
startAutoCloseTimer() {
if (this.autoCloseTimeout) {
this.clearAutoCloseTimer();
this.autoCloseTimer = setTimeout(() => {
this.onClose();
}, this.autoCloseTimeout);
}
}
clearAutoCloseTimer() {
if (this.autoCloseTimer) {
clearTimeout(this.autoCloseTimer);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ModalComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ModalComponent, selector: "cfc-modal", inputs: { isOpen: "isOpen", title: "title", primaryButtonLabel: "primaryButtonLabel", secondaryButtonLabel: "secondaryButtonLabel", hasCloseButton: "hasCloseButton", closeOnOverlayClick: "closeOnOverlayClick", isLoading: "isLoading", autoCloseTimeout: "autoCloseTimeout", maxWidth: "maxWidth", alignButtons: "alignButtons", singleButtonCenter: "singleButtonCenter", size: "size", width: "width", customClass: "customClass" }, outputs: { close: "close", primaryClick: "primaryClick", secondaryClick: "secondaryClick" }, viewQueries: [{ propertyName: "titleElement", first: true, predicate: ["modalTitle"], descendants: true }, { propertyName: "modalContainer", first: true, predicate: ["modalContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"br-scrim-util modal-overlay\" *ngIf=\"isOpen\" (click)=\"onOverlayClick($event)\">\r\n <div\r\n class=\"div br-modal\"\r\n aria-modal=\"true\"\r\n role=\"dialog\"\r\n aria-labelledby=\"modalalerttitle\"\r\n [style.maxWidth]=\"maxWidth\"\r\n [ngClass]=\"{ 'medium': size === 'medium' }\"\r\n [style.width]=\"size === 'auto' ? 'auto' : width\"\r\n [ngClass]=\"customClass\"\r\n >\r\n <div class=\"br-modal-header\">\r\n @if (title) {\r\n <div class=\"modal-title\" id=\"modalalerttitle\">{{ title }}</div>\r\n }\r\n <button\r\n class=\"br-button close circle\"\r\n type=\"button\"\r\n data-dismiss=\"br-modal\"\r\n aria-label=\"Fechar\"\r\n (click)=\"onClose()\"\r\n >\r\n <i class=\"fas fa-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n <div class=\"br-modal-body\" [ngClass]=\"{ 'loading medium': isLoading }\">\r\n @if (!isLoading) {\r\n <ng-container>\r\n <ng-content></ng-content>\r\n </ng-container>\r\n }\r\n </div>\r\n @if (secondaryButtonLabel || primaryButtonLabel) {\r\n <div class=\"br-modal-footer justify-content-end d-flex gap-3\">\r\n <button\r\n class=\"br-button secondary\"\r\n type=\"button\"\r\n (click)=\"onSecondaryClick()\"\r\n >\r\n {{ secondaryButtonLabel }}\r\n </button>\r\n <button\r\n class=\"br-button primary\"\r\n type=\"button\"\r\n (click)=\"onPrimaryClick()\"\r\n >\r\n {{ primaryButtonLabel }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n\r\n\r\n <div class=\"modal-container\" #modalContainer [style.maxWidth]=\"maxWidth\">\r\n <div class=\"modal-header\" *ngIf=\"title\">\r\n <h3\r\n class=\"modal-title\"\r\n #modalTitle\r\n [attr.title]=\"isTitleOverflowing ? fullTitle : null\"\r\n >\r\n\r\n </h3>\r\n <button\r\n *ngIf=\"hasCloseButton\"\r\n type=\"button\"\r\n class=\"modal-close\"\r\n (click)=\"onClose()\"\r\n aria-label=\"Fechar\"\r\n >\r\n \u00D7\r\n </button>\r\n </div>\r\n\r\n <div class=\"modal-content\">\r\n <div *ngIf=\"isLoading\" class=\"modal-loading\">\r\n <div class=\"modal-spinner\"></div>\r\n <p>Carregando...</p>\r\n <button class=\"modal-button modal-button-secondary\" (click)=\"onClose()\">\r\n Cancelar\r\n </button>\r\n </div>\r\n <ng-container *ngIf=\"!isLoading\">\r\n <ng-content></ng-content>\r\n\r\n <div\r\n *ngIf=\"primaryButtonLabel || secondaryButtonLabel\"\r\n class=\"modal-buttons\"\r\n [ngClass]=\"getButtonsClass()\"\r\n >\r\n <button\r\n *ngIf=\"secondaryButtonLabel\"\r\n type=\"button\"\r\n class=\"modal-button modal-button-secondary\"\r\n (click)=\"onSecondaryClick()\"\r\n >\r\n {{ secondaryButtonLabel }}\r\n </button>\r\n <button\r\n *ngIf=\"primaryButtonLabel\"\r\n type=\"button\"\r\n class=\"modal-button modal-button-primary\"\r\n (click)=\"onPrimaryClick()\"\r\n >\r\n {{ primaryButtonLabel }}\r\n </button>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n", styles: [":host{display:contents}.modal-overlay{position:fixed;inset:0;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000}.br-modal{--modal-size: var(--modal-medium);--modal-xsmall: 220px;--modal-small: 300px;--modal-medium: 500px;--modal-large: 640px;--modal-auto: auto;background:var(--background);box-shadow:var(--surface-shadow-sm);display:flex;flex-direction:column;max-width:var(--modal-size);z-index:var(--z-index-layer-4)}.br-modal-header{font-size:var(--font-size-scale-up-01);font-weight:var(--font-weight-bold);padding:var(--spacing-scale-2x) var(--spacing-scale-2x) 0;position:relative}.br-modal-header .close{position:absolute;right:var(--spacing-scale-base);top:var(--spacing-scale-base)}.br-modal .modal-title{font-size:var(--font-size-scale-up-01);font-weight:var(--font-weight-bold);margin-right:40px;max-height:calc(var(--font-size-scale-up-01) * 3);overflow:hidden;text-overflow:ellipsis}.br-modal-body{flex:1;margin:var(--spacing-scale-3x) 0 var(--spacing-scale-2x);overflow:auto;padding:0 var(--spacing-scale-2x);width:auto}.br-modal-body::-webkit-scrollbar{height:var(--spacing-scale-base);width:var(--spacing-scale-base)}.br-modal-body::-webkit-scrollbar-track{background:var(--gray-10)}.br-modal-body::-webkit-scrollbar-thumb{background:var(--gray-30)}.br-modal-body:hover::-webkit-scrollbar-thumb{background:var(--gray-40)}.br-modal-body>*:last-child{margin-bottom:0}.br-modal-footer{display:flex;flex-wrap:wrap;padding:var(--spacing-scale-2x)}.br-modal.is-xsmall,.br-modal.xsmall{--modal-size: var(--modal-xsmall)}.br-modal.is-small,.br-modal.small{--modal-size: var(--modal-small)}.br-modal.is-medium,.br-modal.medium{--modal-size: var(--modal-medium)}.br-modal.is-large,.br-modal.large{--modal-size: var(--modal-large)}.br-modal.is-auto,.br-modal.auto{--modal-size: var(--modal-auto)}.br-modal .loading.medium{min-height:calc(var(--loading-indetermined-diameter-md) + var(--spacing-scale-2x) * 2)}.br-modal .terms{border:0;box-shadow:var(--surface-shadow-sm-inset),var(--surface-shadow-sm-inset-up);font-size:var(--font-size-scale-base);height:216px;margin-bottom:var(--spacing-scale-2x);margin-left:calc(var(--spacing-scale-2x) * -1);margin-right:calc(var(--spacing-scale-2x) * -1);overflow:auto;padding:var(--spacing-scale-2x);resize:none;width:auto}.br-modal .terms::-webkit-scrollbar{height:var(--spacing-scale-base);width:var(--spacing-scale-base)}.br-modal .terms::-webkit-scrollbar-track{background:var(--gray-10)}.br-modal .terms::-webkit-scrollbar-thumb{background:var(--gray-30)}.br-modal .terms:hover::-webkit-scrollbar-thumb{background:var(--gray-40)}.br-modal .terms:active{outline:none}.br-modal .terms:hover::-webkit-scrollbar-thumb{background:var(--color-secondary-07)}@media (max-width: 991px){.br-modal .terms{margin-left:unset!important;margin-right:unset!important}.br-modal-header .close{top:0}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultClassDirective, selector: " [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ModalComponent, decorators: [{
type: Component,
args: [{ selector: 'cfc-modal', template: "<div class=\"br-scrim-util modal-overlay\" *ngIf=\"isOpen\" (click)=\"onOverlayClick($event)\">\r\n <div\r\n class=\"div br-modal\"\r\n aria-modal=\"true\"\r\n role=\"dialog\"\r\n aria-labelledby=\"modalalerttitle\"\r\n [style.maxWidth]=\"maxWidth\"\r\n [ngClass]=\"{ 'medium': size === 'medium' }\"\r\n [style.width]=\"size === 'auto' ? 'auto' : width\"\r\n [ngClass]=\"customClass\"\r\n >\r\n <div class=\"br-modal-header\">\r\n @if (title) {\r\n <div class=\"modal-title\" id=\"modalalerttitle\">{{ title }}</div>\r\n }\r\n <button\r\n class=\"br-button close circle\"\r\n type=\"button\"\r\n data-dismiss=\"br-modal\"\r\n aria-label=\"Fechar\"\r\n (click)=\"onClose()\"\r\n >\r\n <i class=\"fas fa-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n <div class=\"br-modal-body\" [ngClass]=\"{ 'loading medium': isLoading }\">\r\n @if (!isLoading) {\r\n <ng-container>\r\n <ng-content></ng-content>\r\n </ng-container>\r\n }\r\n </div>\r\n @if (secondaryButtonLabel || primaryButtonLabel) {\r\n <div class=\"br-modal-footer justify-content-end d-flex gap-3\">\r\n <button\r\n class=\"br-button secondary\"\r\n type=\"button\"\r\n (click)=\"onSecondaryClick()\"\r\n >\r\n {{ secondaryButtonLabel }}\r\n </button>\r\n <button\r\n class=\"br-button primary\"\r\n type=\"button\"\r\n (click)=\"onPrimaryClick()\"\r\n >\r\n {{ primaryButtonLabel }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n\r\n\r\n <div class=\"modal-container\" #modalContainer [style.maxWidth]=\"maxWidth\">\r\n <div class=\"modal-header\" *ngIf=\"title\">\r\n <h3\r\n class=\"modal-title\"\r\n #modalTitle\r\n [attr.title]=\"isTitleOverflowing ? fullTitle : null\"\r\n >\r\n\r\n </h3>\r\n <button\r\n *ngIf=\"hasCloseButton\"\r\n type=\"button\"\r\n class=\"modal-close\"\r\n (click)=\"onClose()\"\r\n aria-label=\"Fechar\"\r\n >\r\n \u00D7\r\n </button>\r\n </div>\r\n\r\n <div class=\"modal-content\">\r\n <div *ngIf=\"isLoading\" class=\"modal-loading\">\r\n <div class=\"modal-spinner\"></div>\r\n <p>Carregando...</p>\r\n <button class=\"modal-button modal-button-secondary\" (click)=\"onClose()\">\r\n Cancelar\r\n </button>\r\n </div>\r\n <ng-container *ngIf=\"!isLoading\">\r\n <ng-content></ng-content>\r\n\r\n <div\r\n *ngIf=\"primaryButtonLabel || secondaryButtonLabel\"\r\n class=\"modal-buttons\"\r\n [ngClass]=\"getButtonsClass()\"\r\n >\r\n <button\r\n *ngIf=\"secondaryButtonLabel\"\r\n type=\"button\"\r\n class=\"modal-button modal-button-secondary\"\r\n (click)=\"onSecondaryClick()\"\r\n >\r\n {{ secondaryButtonLabel }}\r\n </button>\r\n <button\r\n *ngIf=\"primaryButtonLabel\"\r\n type=\"button\"\r\n class=\"modal-button modal-button-primary\"\r\n (click)=\"onPrimaryClick()\"\r\n >\r\n {{ primaryButtonLabel }}\r\n </button>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n", styles: [":host{display:contents}.modal-overlay{position:fixed;inset:0;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000}.br-modal{--modal-size: var(--modal-medium);--modal-xsmall: 220px;--modal-small: 300px;--modal-medium: 500px;--modal-large: 640px;--modal-auto: auto;background:var(--background);box-shadow:var(--surface-shadow-sm);display:flex;flex-direction:column;max-width:var(--modal-size);z-index:var(--z-index-layer-4)}.br-modal-header{font-size:var(--font-size-scale-up-01);font-weight:var(--font-weight-bold);padding:var(--spacing-scale-2x) var(--spacing-scale-2x) 0;position:relative}.br-modal-header .close{position:absolute;right:var(--spacing-scale-base);top:var(--spacing-scale-base)}.br-modal .modal-title{font-size:var(--font-size-scale-up-01);font-weight:var(--font-weight-bold);margin-right:40px;max-height:calc(var(--font-size-scale-up-01) * 3);overflow:hidden;text-overflow:ellipsis}.br-modal-body{flex:1;margin:var(--spacing-scale-3x) 0 var(--spacing-scale-2x);overflow:auto;padding:0 var(--spacing-scale-2x);width:auto}.br-modal-body::-webkit-scrollbar{height:var(--spacing-scale-base);width:var(--spacing-scale-base)}.br-modal-body::-webkit-scrollbar-track{background:var(--gray-10)}.br-modal-body::-webkit-scrollbar-thumb{background:var(--gray-30)}.br-modal-body:hover::-webkit-scrollbar-thumb{background:var(--gray-40)}.br-modal-body>*:last-child{margin-bottom:0}.br-modal-footer{display:flex;flex-wrap:wrap;padding:var(--spacing-scale-2x)}.br-modal.is-xsmall,.br-modal.xsmall{--modal-size: var(--modal-xsmall)}.br-modal.is-small,.br-modal.small{--modal-size: var(--modal-small)}.br-modal.is-medium,.br-modal.medium{--modal-size: var(--modal-medium)}.br-modal.is-large,.br-modal.large{--modal-size: var(--modal-large)}.br-modal.is-auto,.br-modal.auto{--modal-size: var(--modal-auto)}.br-modal .loading.medium{min-height:calc(var(--loading-indetermined-diameter-md) + var(--spacing-scale-2x) * 2)}.br-modal .terms{border:0;box-shadow:var(--surface-shadow-sm-inset),var(--surface-shadow-sm-inset-up);font-size:var(--font-size-scale-base);height:216px;margin-bottom:var(--spacing-scale-2x);margin-left:calc(var(--spacing-scale-2x) * -1);margin-right:calc(var(--spacing-scale-2x) * -1);overflow:auto;padding:var(--spacing-scale-2x);resize:none;width:auto}.br-modal .terms::-webkit-scrollbar{height:var(--spacing-scale-base);width:var(--spacing-scale-base)}.br-modal .terms::-webkit-scrollbar-track{background:var(--gray-10)}.br-modal .terms::-webkit-scrollbar-thumb{background:var(--gray-30)}.br-modal .terms:hover::-webkit-scrollbar-thumb{background:var(--gray-40)}.br-modal .terms:active{outline:none}.br-modal .terms:hover::-webkit-scrollbar-thumb{background:var(--color-secondary-07)}@media (max-width: 991px){.br-modal .terms{margin-left:unset!important;margin-right:unset!important}.br-modal-header .close{top:0}}\n"] }]
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { isOpen: [{
type: Input
}], title: [{
type: Input
}], primaryButtonLabel: [{
type: Input
}], secondaryButtonLabel: [{
type: Input
}], hasCloseButton: [{
type: Input
}], closeOnOverlayClick: [{
type: Input
}], isLoading: [{
type: Input
}], autoCloseTimeout: [{
type: Input
}], maxWidth: [{
type: Input
}], alignButtons: [{
type: Input
}], singleButtonCenter: [{
type: Input
}], size: [{
type: Input
}], width: [{
type: Input
}], customClass: [{
type: Input
}], close: [{
type: Output
}], primaryClick: [{
type: Output
}], secondaryClick: [{
type: Output
}], titleElement: [{
type: ViewChild,
args: ['modalTitle']
}], modalContainer: [{
type: ViewChild,
args: ['modalContainer']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2ZjLWRzL3NyYy9saWIvY29tcG9uZW50cy9tb2RhbC9tb2RhbC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jZmMtZHMvc3JjL2xpYi9jb21wb25lbnRzL21vZGFsL21vZGFsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBaUIsU0FBUyxFQUFjLFlBQVksRUFBRSxLQUFLLEVBQWdDLE1BQU0sRUFBaUIsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDOzs7O0FBVTFKLE1BQU0sT0FBTyxjQUFjO0lBMkJMO0lBMUJYLE1BQU0sR0FBWSxLQUFLLENBQUM7SUFDeEIsS0FBSyxDQUFVO0lBQ2Ysa0JBQWtCLENBQVU7SUFDNUIsb0JBQW9CLENBQVU7SUFDOUIsY0FBYyxHQUFZLElBQUksQ0FBQztJQUMvQixtQkFBbUIsR0FBWSxJQUFJLENBQUM7SUFDcEMsU0FBUyxHQUFZLEtBQUssQ0FBQztJQUMzQixnQkFBZ0IsQ0FBVTtJQUMxQixRQUFRLEdBQVcsT0FBTyxDQUFDO0lBQzNCLFlBQVksR0FBdUIsT0FBTyxDQUFDO0lBQzNDLGtCQUFrQixHQUFZLElBQUksQ0FBQztJQUNuQyxJQUFJLEdBQXFELFFBQVEsQ0FBQztJQUNsRSxLQUFLLENBQVc7SUFDaEIsV0FBVyxDQUFXO0lBRXJCLEtBQUssR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO0lBQ2pDLFlBQVksR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO0lBQ3hDLGNBQWMsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO0lBRTNCLFlBQVksQ0FBYztJQUN0QixjQUFjLENBQWM7SUFFekQsa0JBQWtCLEdBQVksS0FBSyxDQUFDO0lBQ3BDLFNBQVMsR0FBVyxFQUFFLENBQUM7SUFDdkIsY0FBYyxDQUFPO0lBRXJCLFlB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QVM7c0JBQWpCLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxrQkFBa0I7c0JBQTFCLEtBQUs7Z0JBQ0csSUFBSTtzQkFBWixLQUFLO2dCQUNHLEtBQUs7c0JBQWIsS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVJLEtBQUs7c0JBQWQsTUFBTTtnQkFDRyxZQUFZO3NCQUFyQixNQUFNO2dCQUNHLGNBQWM7c0JBQXZCLE1BQU07Z0JBRWtCLFlBQVk7c0JBQXBDLFNBQVM7dUJBQUMsWUFBWTtnQkFDTSxjQUFjO3NCQUExQyxTQUFTO3VCQUFDLGdCQUFnQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENvbXBvbmVudCwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3V0cHV0LCBTaW1wbGVDaGFuZ2VzLCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgTW9kYWxEZW5zaXR5IH0gZnJvbSAnLi4vLi4vZW51bXMvbW9kYWwtZGVuc2l0eS5lbnVtJztcclxuaW1wb3J0IHsgQnV0dG9uVHlwZSB9IGZyb20gJy4uLy4uL2VudW1zL2J1dHRvbi10eXBlLmVudW0nO1xyXG5pbXBvcnQgeyBNb2RhbFR5cGUgfSBmcm9tICcuLi8uLi9lbnVtcy9tb2RhbC10eXBlLmVudW0nO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdjZmMtbW9kYWwnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9tb2RhbC5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmw6ICcuL21vZGFsLmNvbXBvbmVudC5zY3NzJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgTW9kYWxDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcclxuICBASW5wdXQoKSBpc09wZW46IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSB0aXRsZT86IHN0cmluZztcclxuICBASW5wdXQoKSBwcmltYXJ5QnV0dG9uTGFiZWw/OiBzdHJpbmc7XHJcbiAgQElucHV0KCkgc2Vjb25kYXJ5QnV0dG9uTGFiZWw/OiBzdHJpbmc7XHJcbiAgQElucHV0KCkgaGFzQ2xvc2VCdXR0b246IGJvb2xlYW4gPSB0cnVlO1xyXG4gIEBJbnB1dCgpIGNsb3NlT25PdmVybGF5Q2xpY2s6IGJvb2xlYW4gPSB0cnVlO1xyXG4gIEBJbnB1dCgpIGlzTG9hZGluZzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIGF1dG9DbG9zZVRpbWVvdXQ/OiBudW1iZXI7XHJcbiAgQElucHV0KCkgbWF4V2lkdGg6IHN0cmluZyA9ICc0ODBweCc7XHJcbiAgQElucHV0KCkgYWxpZ25CdXR0b25zOiAncmlnaHQnIHwgJ2NlbnRlcicgPSAncmlnaHQnO1xyXG4gIEBJbnB1dCgpIHNpbmdsZUJ1dHRvbkNlbnRlcjogYm9vbGVhbiA9IHRydWU7XHJcbiAgQElucHV0KCkgc2l6ZTogJ3hzbWFsbCcgfCAnc21hbGwnIHwgJ21lZGl1bScgfCAnbGFyZ2UnIHwgJ2F1dG8nID0gJ21lZGl1bSc7XHJcbiAgQElucHV0KCkgd2lkdGg/OiBzdHJpbmcgO1xyXG4gIEBJbnB1dCgpIGN1c3RvbUNsYXNzPzogc3RyaW5nIDtcclxuXHJcbiAgQE91dHB1dCgpIGNsb3NlID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG4gIEBPdXRwdXQoKSBwcmltYXJ5Q2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XHJcbiAgQE91dHB1dCgpIHNlY29uZGFyeUNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG5cclxuICBAVmlld0NoaWxkKCdtb2RhbFRpdGxlJykgdGl0bGVFbGVtZW50PzogRWxlbWVudFJlZjtcclxuICBAVmlld0NoaWxkKCdtb2RhbENvbnRhaW5lcicpIG1vZGFsQ29udGFpbmVyPzogRWxlbWVudFJlZjtcclxuXHJcbiAgaXNUaXRsZU92ZXJmbG93aW5nOiBib29sZWFuID0gZmFsc2U7XHJcbiAgZnVsbFRpdGxlOiBzdHJpbmcgPSAnJztcclxuICBhdXRvQ2xvc2VUaW1lcj86IGFueTtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBlbGVtZW50UmVmOiBFbGVtZW50UmVmKSB7fVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmlzT3BlbiAmJiB0aGlzLmF1dG9DbG9zZVRpbWVvdXQpIHtcclxuICAgICAgdGhpcy5zdGFydEF1dG9DbG9zZVRpbWVyKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XHJcbiAgICBpZiAoY2hhbmdlc1snaXNPcGVuJ10gJiYgY2hhbmdlc1snaXNPcGVuJ10uY3VycmVudFZhbHVlKSB7XHJcbiAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUub3ZlcmZsb3cgPSAnaGlkZGVuJztcclxuXHJcbiAgICAgIGlmICh0aGlzLmF1dG9DbG9zZVRpbWVvdXQpIHtcclxuICAgICAgICB0aGlzLnN0YXJ0QXV0b0Nsb3NlVGltZXIoKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gQWRpY2lvbmEgbGlzdGVuZXIgcGFyYSBhIHRlY2xhIEVTQ1xyXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5oYW5kbGVFc2NLZXkpO1xyXG4gICAgfSBlbHNlIGlmIChjaGFuZ2VzWydpc09wZW4nXSAmJiAhY2hhbmdlc1snaXNPcGVuJ10uY3VycmVudFZhbHVlKSB7XHJcbiAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUub3ZlcmZsb3cgPSAnYXV0byc7XHJcbiAgICAgIHRoaXMuY2xlYXJBdXRvQ2xvc2VUaW1lcigpO1xyXG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5oYW5kbGVFc2NLZXkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFZlcmlmaWNhIG8gdMOtdHVsbyBxdWFuZG8gZWxlIG11ZGFyXHJcbiAgICBpZiAoY2hhbmdlc1sndGl0bGUnXSAmJiB0aGlzLnRpdGxlRWxlbWVudCkge1xyXG4gICAgICB0aGlzLmNoZWNrVGl0bGVPdmVyZmxvdygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMudGl0bGUgJiYgdGhpcy50aXRsZUVsZW1lbnQpIHtcclxuICAgICAgdGhpcy5jaGVja1RpdGxlT3ZlcmZsb3coKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xyXG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5vdmVyZmxvdyA9ICdhdXRvJztcclxuICAgIHRoaXMuY2xlYXJBdXRvQ2xvc2VUaW1lcigpO1xyXG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuaGFuZGxlRXNjS2V5KTtcclxuICB9XHJcblxyXG4gIGhhbmRsZUVzY0tleSA9IChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQgPT4ge1xyXG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ0VzY2FwZScgJiYgdGhpcy5pc09wZW4pIHtcclxuICAgICAgdGhpcy5vbkNsb3NlKCk7XHJcbiAgICB9XHJcbiAgfTtcclxuXHJcbiAgb25PdmVybGF5Q2xpY2soZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmNsb3NlT25PdmVybGF5Q2xpY2sgJiZcclxuICAgICAgICB0aGlzLm1vZGFsQ29udGFpbmVyICYmXHJcbiAgICAgICAgIXRoaXMubW9kYWxDb250YWluZXIubmF0aXZlRWxlbWVudC5jb250YWlucyhldmVudC50YXJnZXQpKSB7XHJcbiAgICAgIHRoaXMub25DbG9zZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25DbG9zZSgpOiB2b2lkIHtcclxuICAgIHRoaXMuY2xvc2UuZW1pdCgpO1xyXG4gIH1cclxuXHJcbiAgb25QcmltYXJ5Q2xpY2soKTogdm9pZCB7XHJcbiAgICB0aGlzLnByaW1hcnlDbGljay5lbWl0KCk7XHJcbiAgfVxyXG5cclxuICBvblNlY29uZGFyeUNsaWNrKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuc2Vjb25kYXJ5Q2xpY2sub2JzZXJ2ZXJzLmxlbmd0aCkge1xyXG4gICAgICB0aGlzLnNlY29uZGFyeUNsaWNrLmVtaXQoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMub25DbG9zZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZ2V0QnV0dG9uc0NsYXNzKCk6IHN0cmluZyB7XHJcbiAgICBpZiAodGhpcy5zZWNvbmRhcnlCdXR0b25MYWJlbCAmJiB0aGlzLnByaW1hcnlCdXR0b25MYWJlbCkge1xyXG4gICAgICByZXR1cm4gdGhpcy5hbGlnbkJ1dHRvbnMgPT09ICdyaWdodCcgPyAnbW9kYWwtYnV0dG9ucy1yaWdodCcgOiAnbW9kYWwtYnV0dG9ucy1jZW50ZXInO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRoaXMuc2luZ2xlQnV0dG9uQ2VudGVyID8gJ21vZGFsLWJ1dHRvbnMtY2VudGVyJyA6ICdtb2RhbC1idXR0b25zLXJpZ2h0JztcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY2hlY2tUaXRsZU92ZXJmbG93KCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLnRpdGxlRWxlbWVudCkgcmV0dXJuO1xyXG5cclxuICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLnRpdGxlRWxlbWVudC5uYXRpdmVFbGVtZW50O1xyXG4gICAgdGhpcy5mdWxsVGl0bGUgPSB0aGlzLnRpdGxlIHx8ICcnO1xyXG5cclxuICAgIC8vIFJlc2V0YXIgbyBjb250ZcO6ZG8gcGFyYSBvIHTDrXR1bG8gb3JpZ2luYWwgcGFyYSB2ZXJpZmljYXIgbyBvdmVyZmxvd1xyXG4gICAgZWxlbWVudC50ZXh0Q29udGVudCA9IHRoaXMuZnVsbFRpdGxlO1xyXG5cclxuICAgIGlmIChlbGVtZW50LnNjcm9sbEhlaWdodCA+IGVsZW1lbnQuY2xpZW50SGVpZ2h0IHx8XHJcbiAgICAgICAgZWxlbWVudC5zY3JvbGxXaWR0aCA+IGVsZW1lbnQuY2xpZW50V2lkdGgpIHtcclxuICAgICAgdGhpcy5pc1RpdGxlT3ZlcmZsb3dpbmcgPSB0cnVlO1xyXG5cclxuICAgICAgLy8gVHJ1bmNhciBvIHTDrXR1bG8gZSBhZGljaW9uYXIgcmV0aWPDqm5jaWFzXHJcbiAgICAgIGNvbnN0IHdvcmRzID0gdGhpcy5mdWxsVGl0bGUuc3BsaXQoJyAnKTtcclxuICAgICAgbGV0IHRydW5jYXRlZFRpdGxlID0gJyc7XHJcbiAgICAgIGxldCBpID0gMDtcclxuXHJcbiAgICAgIHdoaWxlIChpIDwgd29yZHMubGVuZ3RoKSB7XHJcbiAgICAgICAgY29uc3QgdGVzdFRpdGxlID0gdHJ1bmNhdGVkVGl0bGUgKyAnICcgKyB3b3Jkc1tpXTtcclxuICAgICAgICBlbGVtZW50LnRleHRDb250ZW50ID0gdGVzdFRpdGxlICsgJy4uLic7XHJcblxyXG4gICAgICAgIGlmIChlbGVtZW50LnNjcm9sbEhlaWdodCA+IGVsZW1lbnQuY2xpZW50SGVpZ2h0IHx8XHJcbiAgICAgICAgICAgIGVsZW1lbnQuc2Nyb2xsV2lkdGggPiBlbGVtZW50LmNsaWVudFdpZHRoKSB7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRydW5jYXRlZFRpdGxlID0gdGVzdFRpdGxlO1xyXG4gICAgICAgIGkrKztcclxuICAgICAgfVxyXG5cclxuICAgICAgZWxlbWVudC50ZXh0Q29udGVudCA9IHRydW5jYXRlZFRpdGxlLnRyaW0oKSArICcuLi4nO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5pc1RpdGxlT3ZlcmZsb3dpbmcgPSBmYWxzZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgc3RhcnRBdXRvQ2xvc2VUaW1lcigpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmF1dG9DbG9zZVRpbWVvdXQpIHtcclxuICAgICAgdGhpcy5jbGVhckF1dG9DbG9zZVRpbWVyKCk7XHJcbiAgICAgIHRoaXMuYXV0b0Nsb3NlVGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICB0aGlzLm9uQ2xvc2UoKTtcclxuICAgICAgfSwgdGhpcy5hdXRvQ2xvc2VUaW1lb3V0KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgY2xlYXJBdXRvQ2xvc2VUaW1lcigpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmF1dG9DbG9zZVRpbWVyKSB7XHJcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLmF1dG9DbG9zZVRpbWVyKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiPGRpdiBjbGFzcz1cImJyLXNjcmltLXV0aWwgbW9kYWwtb3ZlcmxheVwiICpuZ0lmPVwiaXNPcGVuXCIgKGNsaWNrKT1cIm9uT3ZlcmxheUNsaWNrKCRldmVudClcIj5cclxuICA8ZGl2XHJcbiAgICBjbGFzcz1cImRpdiBici1tb2RhbFwiXHJcbiAgICBhcmlhLW1vZGFsPVwidHJ1ZVwiXHJcbiAgICByb2xlPVwiZGlhbG9nXCJcclxuICAgIGFyaWEtbGFiZWxsZWRieT1cIm1vZGFsYWxlcnR0aXRsZVwiXHJcbiAgICBbc3R5bGUubWF4V2lkdGhdPVwibWF4V2lkdGhcIlxyXG4gICAgW25nQ2xhc3NdPVwieyAnbWVkaXVtJzogc2l6ZSA9PT0gJ21lZGl1bScgfVwiXHJcbiAgICBbc3R5bGUud2lkdGhdPVwic2l6ZSA9PT0gJ2F1dG8nID8gJ2F1dG8nIDogd2lkdGhcIlxyXG4gICAgW25nQ2xhc3NdPVwiY3VzdG9tQ2xhc3NcIlxyXG4gID5cclxuICAgIDxkaXYgY2xhc3M9XCJici1tb2RhbC1oZWFkZXJcIj5cclxuICAgICAgQGlmICh0aXRsZSkge1xyXG4gICAgICA8ZGl2IGNsYXNzPVwibW9kYWwtdGl0bGVcIiBpZD1cIm1vZGFsYWxlcnR0aXRsZVwiPnt7IHRpdGxlIH19PC9kaXY+XHJcbiAgICAgIH1cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgIGNsYXNzPVwiYnItYnV0dG9uIGNsb3NlIGNpcmNsZVwiXHJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgZGF0YS1kaXNtaXNzPVwiYnItbW9kYWxcIlxyXG4gICAgICAgIGFyaWEtbGFiZWw9XCJGZWNoYXJcIlxyXG4gICAgICAgIChjbGljayk9XCJvbkNsb3NlKClcIlxyXG4gICAgICA+XHJcbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtdGltZXNcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgPC9kaXY+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYnItbW9kYWwtYm9keVwiIFtuZ0NsYXNzXT1cInsgJ2xvYWRpbmcgbWVkaXVtJzogaXNMb2FkaW5nIH1cIj5cclxuICAgICAgQGlmICghaXNMb2FkaW5nKSB7XHJcbiAgICAgIDxuZy1jb250YWluZXI+XHJcbiAgICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxyXG4gICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgfVxyXG4gICAgPC9kaXY+XHJcbiAgICBAaWYgKHNlY29uZGFyeUJ1dHRvbkxhYmVsIHx8IHByaW1hcnlCdXR0b25MYWJlbCkge1xyXG4gICAgPGRpdiBjbGFzcz1cImJyLW1vZGFsLWZvb3RlciBqdXN0aWZ5LWNvbnRlbnQtZW5kIGQtZmxleCBnYXAtM1wiPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgY2xhc3M9XCJici1idXR0b24gc2Vjb25kYXJ5XCJcclxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAoY2xpY2spPVwib25TZWNvbmRhcnlDbGljaygpXCJcclxuICAgICAgPlxyXG4gICAgICAgIHt7IHNlY29uZGFyeUJ1dHRvbkxhYmVsIH19XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgY2xhc3M9XCJici1idXR0b24gcHJpbWFyeVwiXHJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgKGNsaWNrKT1cIm9uUHJpbWFyeUNsaWNrKClcIlxyXG4gICAgICA+XHJcbiAgICAgICAge3sgcHJpbWFyeUJ1dHRvbkxhYmVsIH19XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgPC9kaXY+XHJcbiAgICB9XHJcbiAgPC9kaXY+XHJcbjwvZGl2PlxyXG5cclxuXHJcbiAgPGRpdiBjbGFzcz1cIm1vZGFsLWNvbnRhaW5lclwiICNtb2RhbENvbnRhaW5lciBbc3R5bGUubWF4V2lkdGhdPVwibWF4V2lkdGhcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJtb2RhbC1oZWFkZXJcIiAqbmdJZj1cInRpdGxlXCI+XHJcbiAgICAgIDxoM1xyXG4gICAgICAgIGNsYXNzPVwibW9kYWwtdGl0bGVcIlxyXG4gICAgICAgICNtb2RhbFRpdGxlXHJcbiAgICAgICAgW2F0dHIudGl0bGVdPVwiaXNUaXRsZU92ZXJmbG93aW5nID8gZnVsbFRpdGxlIDogbnVsbFwiXHJcbiAgICAgID5cclxuXHJcbiAgICAgIDwvaDM+XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICAqbmdJZj1cImhhc0Nsb3NlQnV0dG9uXCJcclxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICBjbGFzcz1cIm1vZGFsLWNsb3NlXCJcclxuICAgICAgICAoY2xpY2spPVwib25DbG9zZSgpXCJcclxuICAgICAgICBhcmlhLWxhYmVsPVwiRmVjaGFyXCJcclxuICAgICAgPlxyXG4gICAgICAgIMOXXHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPGRpdiBjbGFzcz1cIm1vZGFsLWNvbnRlbnRcIj5cclxuICAgICAgPGRpdiAqbmdJZj1cImlzTG9hZGluZ1wiIGNsYXNzPVwibW9kYWwtbG9hZGluZ1wiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJtb2RhbC1zcGlubmVyXCI+PC9kaXY+XHJcbiAgICAgICAgPHA+Q2FycmVnYW5kby4uLjwvcD5cclxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwibW9kYWwtYnV0dG9uIG1vZGFsLWJ1dHRvbi1zZWNvbmRhcnlcIiAoY2xpY2spPVwib25DbG9zZSgpXCI+XHJcbiAgICAgICAgICBDYW5jZWxhclxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpc0xvYWRpbmdcIj5cclxuICAgICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XHJcblxyXG4gICAgICAgIDxkaXZcclxuICAgICAgICAgICpuZ0lmPVwicHJpbWFyeUJ1dHRvbkxhYmVsIHx8IHNlY29uZGFyeUJ1dHRvbkxhYmVsXCJcclxuICAgICAgICAgIGNsYXNzPVwibW9kYWwtYnV0dG9uc1wiXHJcbiAgICAgICAgICBbbmdDbGFzc109XCJnZXRCdXR0b25zQ2xhc3MoKVwiXHJcbiAgICAgICAgPlxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAqbmdJZj1cInNlY29uZGFyeUJ1dHRvbkxhYmVsXCJcclxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwibW9kYWwtYnV0dG9uIG1vZGFsLWJ1dHRvbi1zZWNvbmRhcnlcIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwib25TZWNvbmRhcnlDbGljaygpXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAge3sgc2Vjb25kYXJ5QnV0dG9uTGFiZWwgfX1cclxuICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAqbmdJZj1cInByaW1hcnlCdXR0b25MYWJlbFwiXHJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICBjbGFzcz1cIm1vZGFsLWJ1dHRvbiBtb2RhbC1idXR0b24tcHJpbWFyeVwiXHJcbiAgICAgICAgICAgIChjbGljayk9XCJvblByaW1hcnlDbGljaygpXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAge3sgcHJpbWFyeUJ1dHRvbkxhYmVsIH19XHJcbiAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuIl19