cfc-ds
Version:
Design System do Conselho Federal de Contabilidade baseado no govbr-ds
185 lines • 38.6 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;
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" }, 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 >\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 >\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
}], close: [{
type: Output
}], primaryClick: [{
type: Output
}], secondaryClick: [{
type: Output
}], titleElement: [{
type: ViewChild,
args: ['modalTitle']
}], modalContainer: [{
type: ViewChild,
args: ['modalContainer']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2ZjLWRzL3NyYy9saWIvY29tcG9uZW50cy9tb2RhbC9tb2RhbC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jZmMtZHMvc3JjL2xpYi9jb21wb25lbnRzL21vZGFsL21vZGFsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBaUIsU0FBUyxFQUFjLFlBQVksRUFBRSxLQUFLLEVBQWdDLE1BQU0sRUFBaUIsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDOzs7O0FBVTFKLE1BQU0sT0FBTyxjQUFjO0lBMEJMO0lBekJYLE1BQU0sR0FBWSxLQUFLLENBQUM7SUFDeEIsS0FBSyxDQUFVO0lBQ2Ysa0JBQWtCLENBQVU7SUFDNUIsb0JBQW9CLENBQVU7SUFDOUIsY0FBYyxHQUFZLElBQUksQ0FBQztJQUMvQixtQkFBbUIsR0FBWSxJQUFJLENBQUM7SUFDcEMsU0FBUyxHQUFZLEtBQUssQ0FBQztJQUMzQixnQkFBZ0IsQ0FBVTtJQUMxQixRQUFRLEdBQVcsT0FBTyxDQUFDO0lBQzNCLFlBQVksR0FBdUIsT0FBTyxDQUFDO0lBQzNDLGtCQUFrQixHQUFZLElBQUksQ0FBQztJQUNuQyxJQUFJLEdBQXFELFFBQVEsQ0FBQztJQUNsRSxLQUFLLENBQVc7SUFFZixLQUFLLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztJQUNqQyxZQUFZLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztJQUN4QyxjQUFjLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztJQUUzQixZQUFZLENBQWM7SUFDdEIsY0FBYyxDQUFjO0lBRXpELGtCQUFrQixHQUFZLEtBQUssQ0FBQztJQUNwQyxTQUFTLEdBQVcsRUFBRSxDQUFDO0lBQ3ZCLGNBQWMsQ0FBTztJQUVyQixZQUFvQixVQUFzQjtRQUF0Qixl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QUNHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csa0JBQWtCO3NCQUExQixLQUFLO2dCQUNHLElBQUk7c0JBQVosS0FBSztnQkFDRyxLQUFLO3NCQUFiLEtBQUs7Z0JBRUksS0FBSztzQkFBZCxNQUFNO2dCQUNHLFlBQVk7c0JBQXJCLE1BQU07Z0JBQ0csY0FBYztzQkFBdkIsTUFBTTtnQkFFa0IsWUFBWTtzQkFBcEMsU0FBUzt1QkFBQyxZQUFZO2dCQUNNLGNBQWM7c0JBQTFDLFNBQVM7dUJBQUMsZ0JBQWdCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIElucHV0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgT25Jbml0LCBPdXRwdXQsIFNpbXBsZUNoYW5nZXMsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBNb2RhbERlbnNpdHkgfSBmcm9tICcuLi8uLi9lbnVtcy9tb2RhbC1kZW5zaXR5LmVudW0nO1xyXG5pbXBvcnQgeyBCdXR0b25UeXBlIH0gZnJvbSAnLi4vLi4vZW51bXMvYnV0dG9uLXR5cGUuZW51bSc7XHJcbmltcG9ydCB7IE1vZGFsVHlwZSB9IGZyb20gJy4uLy4uL2VudW1zL21vZGFsLXR5cGUuZW51bSc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2NmYy1tb2RhbCcsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL21vZGFsLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybDogJy4vbW9kYWwuY29tcG9uZW50LnNjc3MnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBNb2RhbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xyXG4gIEBJbnB1dCgpIGlzT3BlbjogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHRpdGxlPzogc3RyaW5nO1xyXG4gIEBJbnB1dCgpIHByaW1hcnlCdXR0b25MYWJlbD86IHN0cmluZztcclxuICBASW5wdXQoKSBzZWNvbmRhcnlCdXR0b25MYWJlbD86IHN0cmluZztcclxuICBASW5wdXQoKSBoYXNDbG9zZUJ1dHRvbjogYm9vbGVhbiA9IHRydWU7XHJcbiAgQElucHV0KCkgY2xvc2VPbk92ZXJsYXlDbGljazogYm9vbGVhbiA9IHRydWU7XHJcbiAgQElucHV0KCkgaXNMb2FkaW5nOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgYXV0b0Nsb3NlVGltZW91dD86IG51bWJlcjtcclxuICBASW5wdXQoKSBtYXhXaWR0aDogc3RyaW5nID0gJzQ4MHB4JztcclxuICBASW5wdXQoKSBhbGlnbkJ1dHRvbnM6ICdyaWdodCcgfCAnY2VudGVyJyA9ICdyaWdodCc7XHJcbiAgQElucHV0KCkgc2luZ2xlQnV0dG9uQ2VudGVyOiBib29sZWFuID0gdHJ1ZTtcclxuICBASW5wdXQoKSBzaXplOiAneHNtYWxsJyB8ICdzbWFsbCcgfCAnbWVkaXVtJyB8ICdsYXJnZScgfCAnYXV0bycgPSAnbWVkaXVtJztcclxuICBASW5wdXQoKSB3aWR0aD86IHN0cmluZyA7XHJcblxyXG4gIEBPdXRwdXQoKSBjbG9zZSA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcclxuICBAT3V0cHV0KCkgcHJpbWFyeUNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG4gIEBPdXRwdXQoKSBzZWNvbmRhcnlDbGljayA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcclxuXHJcbiAgQFZpZXdDaGlsZCgnbW9kYWxUaXRsZScpIHRpdGxlRWxlbWVudD86IEVsZW1lbnRSZWY7XHJcbiAgQFZpZXdDaGlsZCgnbW9kYWxDb250YWluZXInKSBtb2RhbENvbnRhaW5lcj86IEVsZW1lbnRSZWY7XHJcblxyXG4gIGlzVGl0bGVPdmVyZmxvd2luZzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIGZ1bGxUaXRsZTogc3RyaW5nID0gJyc7XHJcbiAgYXV0b0Nsb3NlVGltZXI/OiBhbnk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZikge31cclxuXHJcbiAgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5pc09wZW4gJiYgdGhpcy5hdXRvQ2xvc2VUaW1lb3V0KSB7XHJcbiAgICAgIHRoaXMuc3RhcnRBdXRvQ2xvc2VUaW1lcigpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xyXG4gICAgaWYgKGNoYW5nZXNbJ2lzT3BlbiddICYmIGNoYW5nZXNbJ2lzT3BlbiddLmN1cnJlbnRWYWx1ZSkge1xyXG4gICAgICBkb2N1bWVudC5ib2R5LnN0eWxlLm92ZXJmbG93ID0gJ2hpZGRlbic7XHJcblxyXG4gICAgICBpZiAodGhpcy5hdXRvQ2xvc2VUaW1lb3V0KSB7XHJcbiAgICAgICAgdGhpcy5zdGFydEF1dG9DbG9zZVRpbWVyKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIEFkaWNpb25hIGxpc3RlbmVyIHBhcmEgYSB0ZWNsYSBFU0NcclxuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuaGFuZGxlRXNjS2V5KTtcclxuICAgIH0gZWxzZSBpZiAoY2hhbmdlc1snaXNPcGVuJ10gJiYgIWNoYW5nZXNbJ2lzT3BlbiddLmN1cnJlbnRWYWx1ZSkge1xyXG4gICAgICBkb2N1bWVudC5ib2R5LnN0eWxlLm92ZXJmbG93ID0gJ2F1dG8nO1xyXG4gICAgICB0aGlzLmNsZWFyQXV0b0Nsb3NlVGltZXIoKTtcclxuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuaGFuZGxlRXNjS2V5KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBWZXJpZmljYSBvIHTDrXR1bG8gcXVhbmRvIGVsZSBtdWRhclxyXG4gICAgaWYgKGNoYW5nZXNbJ3RpdGxlJ10gJiYgdGhpcy50aXRsZUVsZW1lbnQpIHtcclxuICAgICAgdGhpcy5jaGVja1RpdGxlT3ZlcmZsb3coKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnRpdGxlICYmIHRoaXMudGl0bGVFbGVtZW50KSB7XHJcbiAgICAgIHRoaXMuY2hlY2tUaXRsZU92ZXJmbG93KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIGRvY3VtZW50LmJvZHkuc3R5bGUub3ZlcmZsb3cgPSAnYXV0byc7XHJcbiAgICB0aGlzLmNsZWFyQXV0b0Nsb3NlVGltZXIoKTtcclxuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLmhhbmRsZUVzY0tleSk7XHJcbiAgfVxyXG5cclxuICBoYW5kbGVFc2NLZXkgPSAoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkID0+IHtcclxuICAgIGlmIChldmVudC5rZXkgPT09ICdFc2NhcGUnICYmIHRoaXMuaXNPcGVuKSB7XHJcbiAgICAgIHRoaXMub25DbG9zZSgpO1xyXG4gICAgfVxyXG4gIH07XHJcblxyXG4gIG9uT3ZlcmxheUNsaWNrKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5jbG9zZU9uT3ZlcmxheUNsaWNrICYmXHJcbiAgICAgICAgdGhpcy5tb2RhbENvbnRhaW5lciAmJlxyXG4gICAgICAgICF0aGlzLm1vZGFsQ29udGFpbmVyLm5hdGl2ZUVsZW1lbnQuY29udGFpbnMoZXZlbnQudGFyZ2V0KSkge1xyXG4gICAgICB0aGlzLm9uQ2xvc2UoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG9uQ2xvc2UoKTogdm9pZCB7XHJcbiAgICB0aGlzLmNsb3NlLmVtaXQoKTtcclxuICB9XHJcblxyXG4gIG9uUHJpbWFyeUNsaWNrKCk6IHZvaWQge1xyXG4gICAgdGhpcy5wcmltYXJ5Q2xpY2suZW1pdCgpO1xyXG4gIH1cclxuXHJcbiAgb25TZWNvbmRhcnlDbGljaygpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnNlY29uZGFyeUNsaWNrLm9ic2VydmVycy5sZW5ndGgpIHtcclxuICAgICAgdGhpcy5zZWNvbmRhcnlDbGljay5lbWl0KCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLm9uQ2xvc2UoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGdldEJ1dHRvbnNDbGFzcygpOiBzdHJpbmcge1xyXG4gICAgaWYgKHRoaXMuc2Vjb25kYXJ5QnV0dG9uTGFiZWwgJiYgdGhpcy5wcmltYXJ5QnV0dG9uTGFiZWwpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuYWxpZ25CdXR0b25zID09PSAncmlnaHQnID8gJ21vZGFsLWJ1dHRvbnMtcmlnaHQnIDogJ21vZGFsLWJ1dHRvbnMtY2VudGVyJztcclxuICAgIH1cclxuICAgIHJldHVybiB0aGlzLnNpbmdsZUJ1dHRvbkNlbnRlciA/ICdtb2RhbC1idXR0b25zLWNlbnRlcicgOiAnbW9kYWwtYnV0dG9ucy1yaWdodCc7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNoZWNrVGl0bGVPdmVyZmxvdygpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy50aXRsZUVsZW1lbnQpIHJldHVybjtcclxuXHJcbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy50aXRsZUVsZW1lbnQubmF0aXZlRWxlbWVudDtcclxuICAgIHRoaXMuZnVsbFRpdGxlID0gdGhpcy50aXRsZSB8fCAnJztcclxuXHJcbiAgICAvLyBSZXNldGFyIG8gY29udGXDumRvIHBhcmEgbyB0w610dWxvIG9yaWdpbmFsIHBhcmEgdmVyaWZpY2FyIG8gb3ZlcmZsb3dcclxuICAgIGVsZW1lbnQudGV4dENvbnRlbnQgPSB0aGlzLmZ1bGxUaXRsZTtcclxuXHJcbiAgICBpZiAoZWxlbWVudC5zY3JvbGxIZWlnaHQgPiBlbGVtZW50LmNsaWVudEhlaWdodCB8fFxyXG4gICAgICAgIGVsZW1lbnQuc2Nyb2xsV2lkdGggPiBlbGVtZW50LmNsaWVudFdpZHRoKSB7XHJcbiAgICAgIHRoaXMuaXNUaXRsZU92ZXJmbG93aW5nID0gdHJ1ZTtcclxuXHJcbiAgICAgIC8vIFRydW5jYXIgbyB0w610dWxvIGUgYWRpY2lvbmFyIHJldGljw6puY2lhc1xyXG4gICAgICBjb25zdCB3b3JkcyA9IHRoaXMuZnVsbFRpdGxlLnNwbGl0KCcgJyk7XHJcbiAgICAgIGxldCB0cnVuY2F0ZWRUaXRsZSA9ICcnO1xyXG4gICAgICBsZXQgaSA9IDA7XHJcblxyXG4gICAgICB3aGlsZSAoaSA8IHdvcmRzLmxlbmd0aCkge1xyXG4gICAgICAgIGNvbnN0IHRlc3RUaXRsZSA9IHRydW5jYXRlZFRpdGxlICsgJyAnICsgd29yZHNbaV07XHJcbiAgICAgICAgZWxlbWVudC50ZXh0Q29udGVudCA9IHRlc3RUaXRsZSArICcuLi4nO1xyXG5cclxuICAgICAgICBpZiAoZWxlbWVudC5zY3JvbGxIZWlnaHQgPiBlbGVtZW50LmNsaWVudEhlaWdodCB8fFxyXG4gICAgICAgICAgICBlbGVtZW50LnNjcm9sbFdpZHRoID4gZWxlbWVudC5jbGllbnRXaWR0aCkge1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0cnVuY2F0ZWRUaXRsZSA9IHRlc3RUaXRsZTtcclxuICAgICAgICBpKys7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGVsZW1lbnQudGV4dENvbnRlbnQgPSB0cnVuY2F0ZWRUaXRsZS50cmltKCkgKyAnLi4uJztcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuaXNUaXRsZU92ZXJmbG93aW5nID0gZmFsc2U7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN0YXJ0QXV0b0Nsb3NlVGltZXIoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5hdXRvQ2xvc2VUaW1lb3V0KSB7XHJcbiAgICAgIHRoaXMuY2xlYXJBdXRvQ2xvc2VUaW1lcigpO1xyXG4gICAgICB0aGlzLmF1dG9DbG9zZVRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgdGhpcy5vbkNsb3NlKCk7XHJcbiAgICAgIH0sIHRoaXMuYXV0b0Nsb3NlVGltZW91dCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNsZWFyQXV0b0Nsb3NlVGltZXIoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5hdXRvQ2xvc2VUaW1lcikge1xyXG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5hdXRvQ2xvc2VUaW1lcik7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiIsIjxkaXYgY2xhc3M9XCJici1zY3JpbS11dGlsIG1vZGFsLW92ZXJsYXlcIiAqbmdJZj1cImlzT3BlblwiIChjbGljayk9XCJvbk92ZXJsYXlDbGljaygkZXZlbnQpXCI+XHJcbiAgPGRpdlxyXG4gICAgY2xhc3M9XCJkaXYgYnItbW9kYWxcIlxyXG4gICAgYXJpYS1tb2RhbD1cInRydWVcIlxyXG4gICAgcm9sZT1cImRpYWxvZ1wiXHJcbiAgICBhcmlhLWxhYmVsbGVkYnk9XCJtb2RhbGFsZXJ0dGl0bGVcIlxyXG4gICAgW3N0eWxlLm1heFdpZHRoXT1cIm1heFdpZHRoXCJcclxuICAgIFtuZ0NsYXNzXT1cInsgJ21lZGl1bSc6IHNpemUgPT09ICdtZWRpdW0nIH1cIlxyXG4gICAgW3N0eWxlLndpZHRoXT1cInNpemUgPT09ICdhdXRvJyA/ICdhdXRvJyA6IHdpZHRoXCJcclxuICA+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYnItbW9kYWwtaGVhZGVyXCI+XHJcbiAgICAgIEBpZiAodGl0bGUpIHtcclxuICAgICAgPGRpdiBjbGFzcz1cIm1vZGFsLXRpdGxlXCIgaWQ9XCJtb2RhbGFsZXJ0dGl0bGVcIj57eyB0aXRsZSB9fTwvZGl2PlxyXG4gICAgICB9XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICBjbGFzcz1cImJyLWJ1dHRvbiBjbG9zZSBjaXJjbGVcIlxyXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgIGRhdGEtZGlzbWlzcz1cImJyLW1vZGFsXCJcclxuICAgICAgICBhcmlhLWxhYmVsPVwiRmVjaGFyXCJcclxuICAgICAgICAoY2xpY2spPVwib25DbG9zZSgpXCJcclxuICAgICAgPlxyXG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXRpbWVzXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdiBjbGFzcz1cImJyLW1vZGFsLWJvZHlcIiBbbmdDbGFzc109XCJ7ICdsb2FkaW5nIG1lZGl1bSc6IGlzTG9hZGluZyB9XCI+XHJcbiAgICAgIEBpZiAoIWlzTG9hZGluZykge1xyXG4gICAgICA8bmctY29udGFpbmVyPlxyXG4gICAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cclxuICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgIH1cclxuICAgIDwvZGl2PlxyXG4gICAgQGlmIChzZWNvbmRhcnlCdXR0b25MYWJlbCB8fCBwcmltYXJ5QnV0dG9uTGFiZWwpIHtcclxuICAgIDxkaXYgY2xhc3M9XCJici1tb2RhbC1mb290ZXIganVzdGlmeS1jb250ZW50LWVuZCBkLWZsZXggZ2FwLTNcIj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgIGNsYXNzPVwiYnItYnV0dG9uIHNlY29uZGFyeVwiXHJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgKGNsaWNrKT1cIm9uU2Vjb25kYXJ5Q2xpY2soKVwiXHJcbiAgICAgID5cclxuICAgICAgICB7eyBzZWNvbmRhcnlCdXR0b25MYWJlbCB9fVxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgIGNsYXNzPVwiYnItYnV0dG9uIHByaW1hcnlcIlxyXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgIChjbGljayk9XCJvblByaW1hcnlDbGljaygpXCJcclxuICAgICAgPlxyXG4gICAgICAgIHt7IHByaW1hcnlCdXR0b25MYWJlbCB9fVxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgIDwvZGl2PlxyXG4gICAgfVxyXG4gIDwvZGl2PlxyXG48L2Rpdj5cclxuXHJcblxyXG4gIDxkaXYgY2xhc3M9XCJtb2RhbC1jb250YWluZXJcIiAjbW9kYWxDb250YWluZXIgW3N0eWxlLm1heFdpZHRoXT1cIm1heFdpZHRoXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwibW9kYWwtaGVhZGVyXCIgKm5nSWY9XCJ0aXRsZVwiPlxyXG4gICAgICA8aDNcclxuICAgICAgICBjbGFzcz1cIm1vZGFsLXRpdGxlXCJcclxuICAgICAgICAjbW9kYWxUaXRsZVxyXG4gICAgICAgIFthdHRyLnRpdGxlXT1cImlzVGl0bGVPdmVyZmxvd2luZyA/IGZ1bGxUaXRsZSA6IG51bGxcIlxyXG4gICAgICA+XHJcblxyXG4gICAgICA8L2gzPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgKm5nSWY9XCJoYXNDbG9zZUJ1dHRvblwiXHJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgY2xhc3M9XCJtb2RhbC1jbG9zZVwiXHJcbiAgICAgICAgKGNsaWNrKT1cIm9uQ2xvc2UoKVwiXHJcbiAgICAgICAgYXJpYS1sYWJlbD1cIkZlY2hhclwiXHJcbiAgICAgID5cclxuICAgICAgICDDl1xyXG4gICAgICA8L2J1dHRvbj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDxkaXYgY2xhc3M9XCJtb2RhbC1jb250ZW50XCI+XHJcbiAgICAgIDxkaXYgKm5nSWY9XCJpc0xvYWRpbmdcIiBjbGFzcz1cIm1vZGFsLWxvYWRpbmdcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwibW9kYWwtc3Bpbm5lclwiPjwvZGl2PlxyXG4gICAgICAgIDxwPkNhcnJlZ2FuZG8uLi48L3A+XHJcbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cIm1vZGFsLWJ1dHRvbiBtb2RhbC1idXR0b24tc2Vjb25kYXJ5XCIgKGNsaWNrKT1cIm9uQ2xvc2UoKVwiPlxyXG4gICAgICAgICAgQ2FuY2VsYXJcclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNMb2FkaW5nXCI+XHJcbiAgICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxyXG5cclxuICAgICAgICA8ZGl2XHJcbiAgICAgICAgICAqbmdJZj1cInByaW1hcnlCdXR0b25MYWJlbCB8fCBzZWNvbmRhcnlCdXR0b25MYWJlbFwiXHJcbiAgICAgICAgICBjbGFzcz1cIm1vZGFsLWJ1dHRvbnNcIlxyXG4gICAgICAgICAgW25nQ2xhc3NdPVwiZ2V0QnV0dG9uc0NsYXNzKClcIlxyXG4gICAgICAgID5cclxuICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgKm5nSWY9XCJzZWNvbmRhcnlCdXR0b25MYWJlbFwiXHJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICBjbGFzcz1cIm1vZGFsLWJ1dHRvbiBtb2RhbC1idXR0b24tc2Vjb25kYXJ5XCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cIm9uU2Vjb25kYXJ5Q2xpY2soKVwiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIHt7IHNlY29uZGFyeUJ1dHRvbkxhYmVsIH19XHJcbiAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgKm5nSWY9XCJwcmltYXJ5QnV0dG9uTGFiZWxcIlxyXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgY2xhc3M9XCJtb2RhbC1idXR0b24gbW9kYWwtYnV0dG9uLXByaW1hcnlcIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwib25QcmltYXJ5Q2xpY2soKVwiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIHt7IHByaW1hcnlCdXR0b25MYWJlbCB9fVxyXG4gICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbiJdfQ==