truly-ui
Version:
Web Components for Desktop Applications.
268 lines (266 loc) • 41 kB
JavaScript
/*
MIT License
Copyright (c) 2019 Temainfo Software
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import { Component, Input, ViewChild, Output, Optional, Inject, EventEmitter, Self, } from '@angular/core';
import { InputMask } from './core/input-mask';
import { CdkOverlayOrigin } from '@angular/cdk/overlay';
import { ValueAccessorBase } from './core/value-accessor';
import { INPUT_CONFIG } from './core/input.config';
import { Subscription } from 'rxjs';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@angular/common";
import * as i3 from "../icons/icons";
import * as i4 from "../internals/components/label/label";
import * as i5 from "@angular/cdk/overlay";
/**
* Input Component personalized with few features.
*
* import { InputModule } from 'truly-ui';
*
* @Component({
* selector: 'my-app-comp',
* template: '
* <tl-input
* [(ngModel)]="title"
* [iconBefore]="'ion-email'"
* [iconAfter]="'ion-email'"
* [textBefore]="'R$'"
* [textAfter]="'00,00'"
* [placeholder]="'Meu Input'"
* [clearButton]="true"
* [readonly]="true"
* [disabled]="true"
* [toUpperCase]="true">
* </tl-input>
* '
* })
*/
export class TlInput extends ValueAccessorBase {
constructor(inputConfig, ngControl, tlInput, renderer, change) {
super();
this.inputConfig = inputConfig;
this.ngControl = ngControl;
this.tlInput = tlInput;
this.renderer = renderer;
this.change = change;
this.textBefore = '';
this.textAfter = '';
this.labelPlacement = 'left';
this.labelSize = '100px';
this.name = '';
this.label = '';
this.color = 'basic';
this.iconBefore = '';
this.iconAfter = '';
this.clearButton = false;
this.readonly = null;
this.required = null;
this.disabled = null;
this.autocomplete = 'off';
this.maxlength = -1;
this.tabindex = 0;
this.textAlign = 'left';
this.mask = '';
this.placeholder = ' ';
this.type = 'text';
this.height = '23px';
this.withBorder = true;
this.flatBorder = false;
this.clear = new EventEmitter();
this.overlayOrigin = new EventEmitter();
this.clickAddon = new EventEmitter();
this.click = new EventEmitter();
this.focus = new EventEmitter();
this.blur = new EventEmitter();
this.valid = new EventEmitter();
this.completeMask = new EventEmitter();
this.isShowingMessages = false;
this.subscription = new Subscription();
this.setControl();
this.setOptions(this.inputConfig);
}
get control() {
return this.ngControl?.control;
}
setControl() {
if (this.ngControl) {
this.ngControl.valueAccessor = this;
}
}
ngOnInit() {
this.overlayOrigin.emit(this.cdkOverlayOrigin);
}
ngAfterViewInit() {
this.handleValidator();
this.handleRequiredValidator();
this.handleMask();
}
handleRequiredValidator() {
if (this.control && this.control.errors && this.control.errors.hasOwnProperty('required')) {
this.required = this.control.errors['required'];
this.change.detectChanges();
}
}
handleValidator() {
if (this.control) {
this.hasValidator = this.control.validator;
this.change.detectChanges();
}
}
handleMask() {
if (this.mask) {
this.fieldMask = new InputMask(this, this.renderer, this.mask);
this.subscription.add(this.fieldMask.complete.subscribe(() => {
this.completeMask.emit(true);
}));
}
}
onClickAddon($event, side) {
this.stopEvent($event);
this.clickAddon.emit({ $event, side });
}
onInputClick($event) {
this.stopEvent($event);
this.isShowingMessages = true;
this.click.emit($event);
}
setOptions(options) {
if (options) {
const self = this;
Object.keys(options).forEach(function (key) {
self[key] = options[key];
});
}
}
stopEvent($event) {
$event.preventDefault();
$event.stopPropagation();
}
setFocus() {
this.input.nativeElement.focus();
}
getNativeInput() {
return this.input.nativeElement;
}
onInputFocus($event) {
this.isShowingMessages = true;
this.focus.emit($event);
}
onInputBlur($event) {
this.isShowingMessages = false;
this.blur.emit($event);
this.propagateTouched();
}
clearInput($event) {
this.value = '';
this.input.nativeElement.focus();
this.clear.emit($event);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
/** @nocollapse */ TlInput.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlInput, deps: [{ token: INPUT_CONFIG, optional: true }, { token: i1.NgControl, optional: true, self: true }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ TlInput.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TlInput, selector: "tl-input", inputs: { textBefore: "textBefore", textAfter: "textAfter", labelPlacement: "labelPlacement", labelSize: "labelSize", name: "name", label: "label", color: "color", iconBefore: "iconBefore", iconAfter: "iconAfter", clearButton: "clearButton", readonly: "readonly", required: "required", disabled: "disabled", autocomplete: "autocomplete", maxlength: "maxlength", tabindex: "tabindex", textAlign: "textAlign", mask: "mask", placeholder: "placeholder", type: "type", height: "height", withBorder: "withBorder", flatBorder: "flatBorder" }, outputs: { clear: "clear", overlayOrigin: "overlayOrigin", clickAddon: "clickAddon", click: "click", focus: "focus", blur: "blur", valid: "valid", completeMask: "completeMask" }, viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, static: true }, { propertyName: "inputBox", first: true, predicate: ["inputBox"], descendants: true, static: true }, { propertyName: "cdkOverlayOrigin", first: true, predicate: CdkOverlayOrigin, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<div [class]=\"'tl-input-box ' + color\" #inputBox>\n\n <tl-label *ngIf=\"label\" [required]=\"required\" [labelTitle]=\"label\" [labelPlacement]=\"labelPlacement\" [labelSize]=\"labelSize\"></tl-label>\n\n <span *ngIf=\"iconBefore\" (click)=\"onClickAddon($event, 'before')\"\n [ngClass]=\"{ 'withoutBorder' : !withBorder, '-flatborders': flatBorder }\" class=\"addon -borderleft\">\n <tl-icon>{{ iconBefore }}</tl-icon>\n </span>\n\n <span *ngIf=\"textBefore\" (click)=\"onClickAddon($event, 'before')\" class=\"addon -borderleft\"\n [ngClass]=\"\n {\n 'predefined' : textBefore,\n 'withBorder': withBorder,\n 'withoutBorder' : !withBorder,\n '-flatborders': flatBorder\n }\">\n {{textBefore}}\n </span>\n\n <div class=\"ui-wrapper-input\" [ngClass]=\"{'-flatborders': flatBorder}\" [style.height]=\"height\">\n <input [style.padding-right]=\"clearButton ? '20px' : '12px'\"\n [style.height]=\"height\"\n #input\n [type]=\"type\"\n cdkOverlayOrigin\n [tabindex]=\"tabindex\"\n [style.text-align]=\"textAlign\"\n [disabled]=\"disabled || isDisabled\"\n class=\"field\"\n [ngClass]=\"{\n 'ng-invalid': control?.errors,\n 'ng-valid': !control?.errors,\n 'ng-touched': control?.touched,\n 'ng-untouched': control?.untouched,\n 'withValidators': hasValidator,\n 'withoutValidators': !hasValidator,\n 'withBorder': withBorder,\n 'withoutBorder' : !withBorder,\n '-borderleft': iconBefore || textBefore,\n '-flatborders': flatBorder,\n '-borderright': iconAfter || textAfter\n }\"\n [attr.readonly]=\"readonly ? true : null\"\n [attr.required]=\"required ? true : null\"\n [attr.autocomplete]=\"autocomplete\"\n [attr.maxlength]=\"maxlength\"\n [attr.name]=\"name\"\n [placeholder]=\"placeholder\"\n [(ngModel)]=\"value\"\n (click)=\"onInputClick($event)\"\n (blur)=\"onInputBlur($event)\"\n (focus)=\"onInputFocus($event)\">\n <i *ngIf=\"clearButton && value\" (click)=\"clearInput($event)\"\n class=\"ion ion-ios-close-circle-outline clearButton\">\n </i>\n </div>\n\n <span #afterIcon *ngIf=\"iconAfter\"\n (click)=\"onClickAddon($event, 'after')\" class=\"addon -borderright\"\n [ngClass]=\"{ 'withoutBorder' : !withBorder, '-flatborders': flatBorder, '-borderright': iconAfter || textAfter }\">\n <tl-icon>{{ iconAfter }}</tl-icon>\n </span>\n\n <span *ngIf=\"textAfter\" (click)=\"onClickAddon($event, 'after')\" #afterText class=\"addon -borderright\"\n [ngClass]=\"{ '-predefined' : textAfter, '-flatborders': flatBorder, 'withoutBorder' : !withBorder }\">{{textAfter}}</span>\n</div>\n", styles: ["*{box-sizing:border-box}.tl-input-box{width:100%;position:relative;display:table;border-collapse:separate}.tl-input-box .addon{display:table-cell;padding:3px 12px;font-size:14px;font-weight:400;line-height:1;text-align:center;width:1%;white-space:nowrap;vertical-align:middle}.tl-input-box .addon.-borderleft{border-radius:3px 0 0 3px}.tl-input-box .addon.-borderright{border-radius:0 3px 3px 0}.tl-input-box .addon.-clearbutton{font-size:11px;position:absolute;border:0;top:3px;right:4px;cursor:pointer}.tl-input-box .addon.-flatborders{border-radius:0}.tl-input-box .addon.-predefined{font-family:Segoe UI,Lato,\"sans-serif\",Arial}.tl-input-box .addon:hover{cursor:pointer}.tl-input-box>.ui-wrapper-input{position:relative;display:flex;align-items:center;justify-content:center}.tl-input-box>.ui-wrapper-input>.field{display:table-cell;height:23px;padding:4px 20px 4px 6px;font-family:Segoe UI,Lato,\"sans-serif\",Arial;font-size:1em;width:100%;font-weight:400;border-radius:3px;transition:background-color .23s ease-in-out}.tl-input-box>.ui-wrapper-input>.field.-borderleft{border-top-left-radius:0;border-bottom-left-radius:0}.tl-input-box>.ui-wrapper-input>.field.-borderright{border-top-right-radius:0;border-bottom-right-radius:0}.tl-input-box>.ui-wrapper-input>.field.-flatborders{border-radius:0}.tl-input-box>.ui-wrapper-input>.field::placeholder{font-family:Segoe UI,Lato,\"sans-serif\",Arial;font-size:1em}.tl-input-box>.ui-wrapper-input>.field.-disabled{cursor:default!important}.tl-input-box>.ui-wrapper-input>.clearButton{position:absolute;font-size:22px;padding-right:5px;right:0;color:#ccc}.tl-input-box>.ui-wrapper-input>.clearButton:hover{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.TlIcons, selector: "tl-icon", inputs: ["icon", "lib", "style", "size", "animation", "color", "align"] }, { kind: "component", type: i4.TlLabel, selector: "tl-label", inputs: ["labelPlacement", "required", "labelSize", "labelTitle"] }, { kind: "directive", type: i5.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlInput, decorators: [{
type: Component,
args: [{ selector: 'tl-input', template: "<div [class]=\"'tl-input-box ' + color\" #inputBox>\n\n <tl-label *ngIf=\"label\" [required]=\"required\" [labelTitle]=\"label\" [labelPlacement]=\"labelPlacement\" [labelSize]=\"labelSize\"></tl-label>\n\n <span *ngIf=\"iconBefore\" (click)=\"onClickAddon($event, 'before')\"\n [ngClass]=\"{ 'withoutBorder' : !withBorder, '-flatborders': flatBorder }\" class=\"addon -borderleft\">\n <tl-icon>{{ iconBefore }}</tl-icon>\n </span>\n\n <span *ngIf=\"textBefore\" (click)=\"onClickAddon($event, 'before')\" class=\"addon -borderleft\"\n [ngClass]=\"\n {\n 'predefined' : textBefore,\n 'withBorder': withBorder,\n 'withoutBorder' : !withBorder,\n '-flatborders': flatBorder\n }\">\n {{textBefore}}\n </span>\n\n <div class=\"ui-wrapper-input\" [ngClass]=\"{'-flatborders': flatBorder}\" [style.height]=\"height\">\n <input [style.padding-right]=\"clearButton ? '20px' : '12px'\"\n [style.height]=\"height\"\n #input\n [type]=\"type\"\n cdkOverlayOrigin\n [tabindex]=\"tabindex\"\n [style.text-align]=\"textAlign\"\n [disabled]=\"disabled || isDisabled\"\n class=\"field\"\n [ngClass]=\"{\n 'ng-invalid': control?.errors,\n 'ng-valid': !control?.errors,\n 'ng-touched': control?.touched,\n 'ng-untouched': control?.untouched,\n 'withValidators': hasValidator,\n 'withoutValidators': !hasValidator,\n 'withBorder': withBorder,\n 'withoutBorder' : !withBorder,\n '-borderleft': iconBefore || textBefore,\n '-flatborders': flatBorder,\n '-borderright': iconAfter || textAfter\n }\"\n [attr.readonly]=\"readonly ? true : null\"\n [attr.required]=\"required ? true : null\"\n [attr.autocomplete]=\"autocomplete\"\n [attr.maxlength]=\"maxlength\"\n [attr.name]=\"name\"\n [placeholder]=\"placeholder\"\n [(ngModel)]=\"value\"\n (click)=\"onInputClick($event)\"\n (blur)=\"onInputBlur($event)\"\n (focus)=\"onInputFocus($event)\">\n <i *ngIf=\"clearButton && value\" (click)=\"clearInput($event)\"\n class=\"ion ion-ios-close-circle-outline clearButton\">\n </i>\n </div>\n\n <span #afterIcon *ngIf=\"iconAfter\"\n (click)=\"onClickAddon($event, 'after')\" class=\"addon -borderright\"\n [ngClass]=\"{ 'withoutBorder' : !withBorder, '-flatborders': flatBorder, '-borderright': iconAfter || textAfter }\">\n <tl-icon>{{ iconAfter }}</tl-icon>\n </span>\n\n <span *ngIf=\"textAfter\" (click)=\"onClickAddon($event, 'after')\" #afterText class=\"addon -borderright\"\n [ngClass]=\"{ '-predefined' : textAfter, '-flatborders': flatBorder, 'withoutBorder' : !withBorder }\">{{textAfter}}</span>\n</div>\n", styles: ["*{box-sizing:border-box}.tl-input-box{width:100%;position:relative;display:table;border-collapse:separate}.tl-input-box .addon{display:table-cell;padding:3px 12px;font-size:14px;font-weight:400;line-height:1;text-align:center;width:1%;white-space:nowrap;vertical-align:middle}.tl-input-box .addon.-borderleft{border-radius:3px 0 0 3px}.tl-input-box .addon.-borderright{border-radius:0 3px 3px 0}.tl-input-box .addon.-clearbutton{font-size:11px;position:absolute;border:0;top:3px;right:4px;cursor:pointer}.tl-input-box .addon.-flatborders{border-radius:0}.tl-input-box .addon.-predefined{font-family:Segoe UI,Lato,\"sans-serif\",Arial}.tl-input-box .addon:hover{cursor:pointer}.tl-input-box>.ui-wrapper-input{position:relative;display:flex;align-items:center;justify-content:center}.tl-input-box>.ui-wrapper-input>.field{display:table-cell;height:23px;padding:4px 20px 4px 6px;font-family:Segoe UI,Lato,\"sans-serif\",Arial;font-size:1em;width:100%;font-weight:400;border-radius:3px;transition:background-color .23s ease-in-out}.tl-input-box>.ui-wrapper-input>.field.-borderleft{border-top-left-radius:0;border-bottom-left-radius:0}.tl-input-box>.ui-wrapper-input>.field.-borderright{border-top-right-radius:0;border-bottom-right-radius:0}.tl-input-box>.ui-wrapper-input>.field.-flatborders{border-radius:0}.tl-input-box>.ui-wrapper-input>.field::placeholder{font-family:Segoe UI,Lato,\"sans-serif\",Arial;font-size:1em}.tl-input-box>.ui-wrapper-input>.field.-disabled{cursor:default!important}.tl-input-box>.ui-wrapper-input>.clearButton{position:absolute;font-size:22px;padding-right:5px;right:0;color:#ccc}.tl-input-box>.ui-wrapper-input>.clearButton:hover{cursor:pointer}\n"] }]
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [INPUT_CONFIG]
}] }, { type: i1.NgControl, decorators: [{
type: Optional
}, {
type: Self
}] }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { textBefore: [{
type: Input
}], textAfter: [{
type: Input
}], labelPlacement: [{
type: Input
}], labelSize: [{
type: Input
}], name: [{
type: Input
}], label: [{
type: Input
}], color: [{
type: Input
}], iconBefore: [{
type: Input
}], iconAfter: [{
type: Input
}], clearButton: [{
type: Input
}], readonly: [{
type: Input
}], required: [{
type: Input
}], disabled: [{
type: Input
}], autocomplete: [{
type: Input
}], maxlength: [{
type: Input
}], tabindex: [{
type: Input
}], textAlign: [{
type: Input
}], mask: [{
type: Input
}], placeholder: [{
type: Input
}], type: [{
type: Input
}], height: [{
type: Input
}], withBorder: [{
type: Input
}], flatBorder: [{
type: Input
}], input: [{
type: ViewChild,
args: ['input', { static: true }]
}], inputBox: [{
type: ViewChild,
args: ['inputBox', { static: true }]
}], cdkOverlayOrigin: [{
type: ViewChild,
args: [CdkOverlayOrigin, { static: true }]
}], clear: [{
type: Output
}], overlayOrigin: [{
type: Output
}], clickAddon: [{
type: Output
}], click: [{
type: Output
}], focus: [{
type: Output
}], blur: [{
type: Output
}], valid: [{
type: Output
}], completeMask: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy90cnVseS11aS9zcmMvY29tcG9uZW50cy9pbnB1dC9pbnB1dC50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RydWx5LXVpL3NyYy9jb21wb25lbnRzL2lucHV0L2lucHV0Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBQ0wsU0FBUyxFQUVULE1BQU0sRUFDTixRQUFRLEVBQ1IsTUFBTSxFQUNOLFlBQVksRUFBeUYsSUFBSSxHQUMxRyxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUMsU0FBUyxFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFJNUMsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFDdEQsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDeEQsT0FBTyxFQUFDLFlBQVksRUFBYyxNQUFNLHFCQUFxQixDQUFDO0FBQzlELE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxNQUFNLENBQUM7Ozs7Ozs7QUFFbEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FzQkc7QUFPSCxNQUFNLE9BQU8sT0FBUSxTQUFRLGlCQUF5QjtJQThFcEQsWUFBc0QsV0FBd0IsRUFDdkMsU0FBb0IsRUFDdkMsT0FBbUIsRUFBVSxRQUFtQixFQUNoRCxNQUF5QjtRQUMzQyxLQUFLLEVBQUUsQ0FBQztRQUo0QyxnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQUN2QyxjQUFTLEdBQVQsU0FBUyxDQUFXO1FBQ3ZDLFlBQU8sR0FBUCxPQUFPLENBQVk7UUFBVSxhQUFRLEdBQVIsUUFBUSxDQUFXO1FBQ2hELFdBQU0sR0FBTixNQUFNLENBQW1CO1FBL0VwQyxlQUFVLEdBQUcsRUFBRSxDQUFDO1FBRWhCLGNBQVMsR0FBRyxF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aW5mbyBTb2Z0d2FyZVxuXG4gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbiBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsXG4gY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEVcbiBTT0ZUV0FSRS5cbiAqL1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBJbnB1dCxcbiAgVmlld0NoaWxkLFxuICBBZnRlclZpZXdJbml0LFxuICBPdXRwdXQsXG4gIE9wdGlvbmFsLFxuICBJbmplY3QsXG4gIEV2ZW50RW1pdHRlciwgUmVuZGVyZXIyLCBFbGVtZW50UmVmLCBPbkluaXQsIENvbnRlbnRDaGlsZCwgZm9yd2FyZFJlZiwgQ2hhbmdlRGV0ZWN0b3JSZWYsIE9uRGVzdHJveSwgU2VsZiwgSW5qZWN0b3IsIEFmdGVyQ29udGVudEluaXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtJbnB1dE1hc2t9IGZyb20gJy4vY29yZS9pbnB1dC1tYXNrJztcbmltcG9ydCB7XG4gIEFic3RyYWN0Q29udHJvbCwgTmdDb250cm9sLFxufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge0Nka092ZXJsYXlPcmlnaW59IGZyb20gJ0Bhbmd1bGFyL2Nkay9vdmVybGF5JztcbmltcG9ydCB7VmFsdWVBY2Nlc3NvckJhc2V9IGZyb20gJy4vY29yZS92YWx1ZS1hY2Nlc3Nvcic7XG5pbXBvcnQge0lOUFVUX0NPTkZJRywgSW5wdXRDb25maWd9IGZyb20gJy4vY29yZS9pbnB1dC5jb25maWcnO1xuaW1wb3J0IHtTdWJzY3JpcHRpb259IGZyb20gJ3J4anMnO1xuXG4vKipcbiAqIElucHV0IENvbXBvbmVudCBwZXJzb25hbGl6ZWQgd2l0aCBmZXcgZmVhdHVyZXMuXG4gKlxuICogaW1wb3J0IHsgSW5wdXRNb2R1bGUgfSBmcm9tICd0cnVseS11aSc7XG4gKlxuICogQENvbXBvbmVudCh7XG4gKiAgc2VsZWN0b3I6ICdteS1hcHAtY29tcCcsXG4gKiAgdGVtcGxhdGU6ICdcbiAqICA8dGwtaW5wdXRcbiAqICAgWyhuZ01vZGVsKV09XCJ0aXRsZVwiXG4gKiAgIFtpY29uQmVmb3JlXT1cIidpb24tZW1haWwnXCJcbiAqICAgW2ljb25BZnRlcl09XCInaW9uLWVtYWlsJ1wiXG4gKiAgIFt0ZXh0QmVmb3JlXT1cIidSJCdcIlxuICogICBbdGV4dEFmdGVyXT1cIicwMCwwMCdcIlxuICogICBbcGxhY2Vob2xkZXJdPVwiJ01ldSBJbnB1dCdcIlxuICogICBbY2xlYXJCdXR0b25dPVwidHJ1ZVwiXG4gKiAgIFtyZWFkb25seV09XCJ0cnVlXCJcbiAqICAgW2Rpc2FibGVkXT1cInRydWVcIlxuICogICBbdG9VcHBlckNhc2VdPVwidHJ1ZVwiPlxuICogIDwvdGwtaW5wdXQ+XG4gKiAgJ1xuICogfSlcbiAqL1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0bC1pbnB1dCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9pbnB1dC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vaW5wdXQuc2NzcyddXG59KVxuZXhwb3J0IGNsYXNzIFRsSW5wdXQgZXh0ZW5kcyBWYWx1ZUFjY2Vzc29yQmFzZTxzdHJpbmc+IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQge1xuXG4gIEBJbnB1dCgpIHRleHRCZWZvcmUgPSAnJztcblxuICBASW5wdXQoKSB0ZXh0QWZ0ZXIgPSAnJztcblxuICBASW5wdXQoKSBsYWJlbFBsYWNlbWVudCA9ICdsZWZ0JztcblxuICBASW5wdXQoKSBsYWJlbFNpemUgPSAnMTAwcHgnO1xuXG4gIEBJbnB1dCgpIG5hbWUgPSAnJztcblxuICBASW5wdXQoKSBsYWJlbCA9ICcnO1xuXG4gIEBJbnB1dCgpIGNvbG9yID0gJ2Jhc2ljJztcblxuICBASW5wdXQoKSBpY29uQmVmb3JlID0gJyc7XG5cbiAgQElucHV0KCkgaWNvbkFmdGVyID0gJyc7XG5cbiAgQElucHV0KCkgY2xlYXJCdXR0b24gPSBmYWxzZTtcblxuICBASW5wdXQoKSByZWFkb25seTogYm9vbGVhbiA9IG51bGw7XG5cbiAgQElucHV0KCkgcmVxdWlyZWQ6IGJvb2xlYW4gPSBudWxsO1xuXG4gIEBJbnB1dCgpIGRpc2FibGVkOiBib29sZWFuID0gbnVsbDtcblxuICBASW5wdXQoKSBhdXRvY29tcGxldGUgPSAnb2ZmJztcblxuICBASW5wdXQoKSBtYXhsZW5ndGggPSAtMTtcblxuICBASW5wdXQoKSB0YWJpbmRleCA9IDA7XG5cbiAgQElucHV0KCkgdGV4dEFsaWduOiAnbGVmdCcgfCAncmlnaHQnIHwgJ2NlbnRlcicgfCAnanVzdGlmeScgPSAnbGVmdCc7XG5cbiAgQElucHV0KCkgbWFzayA9ICcnO1xuXG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyID0gJyAnO1xuXG4gIEBJbnB1dCgpIHR5cGUgPSAndGV4dCc7XG5cbiAgQElucHV0KCkgaGVpZ2h0ID0gJzIzcHgnO1xuXG4gIEBJbnB1dCgpIHdpdGhCb3JkZXIgPSB0cnVlO1xuXG4gIEBJbnB1dCgpIGZsYXRCb3JkZXIgPSBmYWxzZTtcblxuICBAVmlld0NoaWxkKCdpbnB1dCcsIHtzdGF0aWM6IHRydWV9ICkgaW5wdXQ7XG5cbiAgQFZpZXdDaGlsZCgnaW5wdXRCb3gnLCB7c3RhdGljOiB0cnVlfSApIGlucHV0Qm94O1xuXG4gIEBWaWV3Q2hpbGQoQ2RrT3ZlcmxheU9yaWdpbiwge3N0YXRpYzogdHJ1ZX0gKSBjZGtPdmVybGF5T3JpZ2luOiBDZGtPdmVybGF5T3JpZ2luO1xuXG4gIEBPdXRwdXQoKSBjbGVhcjogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpIG92ZXJsYXlPcmlnaW46IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBPdXRwdXQoKSBjbGlja0FkZG9uOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCkgY2xpY2s6IEV2ZW50RW1pdHRlcjxNb3VzZUV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCkgZm9jdXM6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBPdXRwdXQoKSBibHVyOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCkgdmFsaWQ6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCkgY29tcGxldGVNYXNrOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcHVibGljIGlzU2hvd2luZ01lc3NhZ2VzID0gZmFsc2U7XG5cbiAgcHVibGljIGZpZWxkTWFzazogSW5wdXRNYXNrO1xuXG4gIHB1YmxpYyBoYXNWYWxpZGF0b3I7XG5cbiAgcHJpdmF0ZSBzdWJzY3JpcHRpb24gPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG5cbiAgY29uc3RydWN0b3IoQE9wdGlvbmFsKCkgQEluamVjdChJTlBVVF9DT05GSUcpIHByaXZhdGUgaW5wdXRDb25maWc6IElucHV0Q29uZmlnLFxuICAgICAgICAgICAgICBAT3B0aW9uYWwoKSBAU2VsZigpIHB1YmxpYyBuZ0NvbnRyb2w6IE5nQ29udHJvbCxcbiAgICAgICAgICAgICAgcHJpdmF0ZSB0bElucHV0OiBFbGVtZW50UmVmLCBwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgICAgICAgICAgIHByaXZhdGUgY2hhbmdlOiBDaGFuZ2VEZXRlY3RvclJlZikge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5zZXRDb250cm9sKCk7XG4gICAgdGhpcy5zZXRPcHRpb25zKHRoaXMuaW5wdXRDb25maWcpO1xuICB9XG5cbiAgZ2V0IGNvbnRyb2woKSB7XG4gICAgcmV0dXJuIHRoaXMubmdDb250cm9sPy5jb250cm9sO1xuICB9XG5cbiAgc2V0Q29udHJvbCgpIHtcbiAgICBpZiAoIHRoaXMubmdDb250cm9sICkge1xuICAgICAgdGhpcy5uZ0NvbnRyb2wudmFsdWVBY2Nlc3NvciA9IHRoaXM7XG4gICAgfVxuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5vdmVybGF5T3JpZ2luLmVtaXQodGhpcy5jZGtPdmVybGF5T3JpZ2luKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLmhhbmRsZVZhbGlkYXRvcigpO1xuICAgIHRoaXMuaGFuZGxlUmVxdWlyZWRWYWxpZGF0b3IoKTtcbiAgICB0aGlzLmhhbmRsZU1hc2soKTtcbiAgfVxuXG4gIGhhbmRsZVJlcXVpcmVkVmFsaWRhdG9yKCkge1xuICAgIGlmICh0aGlzLmNvbnRyb2wgJiYgdGhpcy5jb250cm9sLmVycm9ycyAmJiB0aGlzLmNvbnRyb2wuZXJyb3JzLmhhc093blByb3BlcnR5KCdyZXF1aXJlZCcpKSB7XG4gICAgICB0aGlzLnJlcXVpcmVkID0gdGhpcy5jb250cm9sLmVycm9yc1sncmVxdWlyZWQnXTtcbiAgICAgIHRoaXMuY2hhbmdlLmRldGVjdENoYW5nZXMoKTtcbiAgICB9XG4gIH1cblxuICBoYW5kbGVWYWxpZGF0b3IoKSB7XG4gICAgaWYgKHRoaXMuY29udHJvbCkge1xuICAgICAgdGhpcy5oYXNWYWxpZGF0b3IgPSB0aGlzLmNvbnRyb2wudmFsaWRhdG9yO1xuICAgICAgdGhpcy5jaGFuZ2UuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cbiAgfVxuXG4gIGhhbmRsZU1hc2soKSB7XG4gICAgaWYgKHRoaXMubWFzaykge1xuICAgICAgdGhpcy5maWVsZE1hc2sgPSBuZXcgSW5wdXRNYXNrKHRoaXMsIHRoaXMucmVuZGVyZXIsIHRoaXMubWFzayk7XG4gICAgICB0aGlzLnN1YnNjcmlwdGlvbi5hZGQodGhpcy5maWVsZE1hc2suY29tcGxldGUuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5jb21wbGV0ZU1hc2suZW1pdCh0cnVlKTtcbiAgICAgIH0pKTtcbiAgICB9XG4gIH1cblxuICBvbkNsaWNrQWRkb24oJGV2ZW50LCBzaWRlKSB7XG4gICAgdGhpcy5zdG9wRXZlbnQoJGV2ZW50KTtcbiAgICB0aGlzLmNsaWNrQWRkb24uZW1pdCh7JGV2ZW50LCBzaWRlfSk7XG4gIH1cblxuICBvbklucHV0Q2xpY2soJGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgdGhpcy5zdG9wRXZlbnQoJGV2ZW50KTtcbiAgICB0aGlzLmlzU2hvd2luZ01lc3NhZ2VzID0gdHJ1ZTtcbiAgICB0aGlzLmNsaWNrLmVtaXQoJGV2ZW50KTtcbiAgfVxuXG4gIHNldE9wdGlvbnMob3B0aW9uczogSW5wdXRDb25maWcpIHtcbiAgICBpZiAob3B0aW9ucykge1xuICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICBPYmplY3Qua2V5cyhvcHRpb25zKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgc2VsZltrZXldID0gb3B0aW9uc1trZXldO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgc3RvcEV2ZW50KCRldmVudCkge1xuICAgICRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxuXG4gIHNldEZvY3VzKCkge1xuICAgIHRoaXMuaW5wdXQubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICB9XG5cbiAgZ2V0TmF0aXZlSW5wdXQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaW5wdXQubmF0aXZlRWxlbWVudDtcbiAgfVxuXG4gIG9uSW5wdXRGb2N1cygkZXZlbnQpIHtcbiAgICB0aGlzLmlzU2hvd2luZ01lc3NhZ2VzID0gdHJ1ZTtcbiAgICB0aGlzLmZvY3VzLmVtaXQoJGV2ZW50KTtcbiAgfVxuXG4gIG9uSW5wdXRCbHVyKCRldmVudCkge1xuICAgIHRoaXMuaXNTaG93aW5nTWVzc2FnZXMgPSBmYWxzZTtcbiAgICB0aGlzLmJsdXIuZW1pdCgkZXZlbnQpO1xuICAgIHRoaXMucHJvcGFnYXRlVG91Y2hlZCgpO1xuICB9XG5cbiAgY2xlYXJJbnB1dCgkZXZlbnQ/KSB7XG4gICAgdGhpcy52YWx1ZSA9ICcnO1xuICAgIHRoaXMuaW5wdXQubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgIHRoaXMuY2xlYXIuZW1pdCgkZXZlbnQpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG59XG4iLCI8ZGl2IFtjbGFzc109XCIndGwtaW5wdXQtYm94ICcgKyBjb2xvclwiICNpbnB1dEJveD5cblxuICA8dGwtbGFiZWwgKm5nSWY9XCJsYWJlbFwiIFtyZXF1aXJlZF09XCJyZXF1aXJlZFwiIFtsYWJlbFRpdGxlXT1cImxhYmVsXCIgW2xhYmVsUGxhY2VtZW50XT1cImxhYmVsUGxhY2VtZW50XCIgW2xhYmVsU2l6ZV09XCJsYWJlbFNpemVcIj48L3RsLWxhYmVsPlxuXG4gIDxzcGFuICpuZ0lmPVwiaWNvbkJlZm9yZVwiIChjbGljayk9XCJvbkNsaWNrQWRkb24oJGV2ZW50LCAnYmVmb3JlJylcIlxuICAgICAgICBbbmdDbGFzc109XCJ7ICd3aXRob3V0Qm9yZGVyJyA6ICF3aXRoQm9yZGVyLCAnLWZsYXRib3JkZXJzJzogZmxhdEJvcmRlciB9XCIgY2xhc3M9XCJhZGRvbiAtYm9yZGVybGVmdFwiPlxuICAgIDx0bC1pY29uPnt7IGljb25CZWZvcmUgfX08L3RsLWljb24+XG4gIDwvc3Bhbj5cblxuICA8c3BhbiAqbmdJZj1cInRleHRCZWZvcmVcIiAoY2xpY2spPVwib25DbGlja0FkZG9uKCRldmVudCwgJ2JlZm9yZScpXCIgY2xhc3M9XCJhZGRvbiAtYm9yZGVybGVmdFwiXG4gICAgICAgIFtuZ0NsYXNzXT1cIlxuICAgICAgICB7XG4gICAgICAgICdwcmVkZWZpbmVkJyA6IHRleHRCZWZvcmUsXG4gICAgICAgICd3aXRoQm9yZGVyJzogd2l0aEJvcmRlcixcbiAgICAgICAgJ3dpdGhvdXRCb3JkZXInIDogIXdpdGhCb3JkZXIsXG4gICAgICAgICctZmxhdGJvcmRlcnMnOiBmbGF0Qm9yZGVyXG4gICAgICAgIH1cIj5cbiAgICB7e3RleHRCZWZvcmV9fVxuICA8L3NwYW4+XG5cbiAgPGRpdiBjbGFzcz1cInVpLXdyYXBwZXItaW5wdXRcIiBbbmdDbGFzc109XCJ7Jy1mbGF0Ym9yZGVycyc6IGZsYXRCb3JkZXJ9XCIgW3N0eWxlLmhlaWdodF09XCJoZWlnaHRcIj5cbiAgICA8aW5wdXQgW3N0eWxlLnBhZGRpbmctcmlnaHRdPVwiY2xlYXJCdXR0b24gPyAnMjBweCcgOiAnMTJweCdcIlxuICAgICAgICAgICBbc3R5bGUuaGVpZ2h0XT1cImhlaWdodFwiXG4gICAgICAgICAgICNpbnB1dFxuICAgICAgICAgICBbdHlwZV09XCJ0eXBlXCJcbiAgICAgICAgICAgY2RrT3ZlcmxheU9yaWdpblxuICAgICAgICAgICBbdGFiaW5kZXhdPVwidGFiaW5kZXhcIlxuICAgICAgICAgICBbc3R5bGUudGV4dC1hbGlnbl09XCJ0ZXh0QWxpZ25cIlxuICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWQgfHwgaXNEaXNhYmxlZFwiXG4gICAgICAgICAgIGNsYXNzPVwiZmllbGRcIlxuICAgICAgICAgICBbbmdDbGFzc109XCJ7XG4gICAgICAgICAgICAgJ25nLWludmFsaWQnOiBjb250cm9sPy5lcnJvcnMsXG4gICAgICAgICAgICAgJ25nLXZhbGlkJzogIWNvbnRyb2w/LmVycm9ycyxcbiAgICAgICAgICAgICAnbmctdG91Y2hlZCc6IGNvbnRyb2w/LnRvdWNoZWQsXG4gICAgICAgICAgICAgJ25nLXVudG91Y2hlZCc6IGNvbnRyb2w/LnVudG91Y2hlZCxcbiAgICAgICAgICAgICAnd2l0aFZhbGlkYXRvcnMnOiBoYXNWYWxpZGF0b3IsXG4gICAgICAgICAgICAgJ3dpdGhvdXRWYWxpZGF0b3JzJzogIWhhc1ZhbGlkYXRvcixcbiAgICAgICAgICAgICAnd2l0aEJvcmRlcic6IHdpdGhCb3JkZXIsXG4gICAgICAgICAgICAgJ3dpdGhvdXRCb3JkZXInIDogIXdpdGhCb3JkZXIsXG4gICAgICAgICAgICAgJy1ib3JkZXJsZWZ0JzogaWNvbkJlZm9yZSB8fCB0ZXh0QmVmb3JlLFxuICAgICAgICAgICAgICctZmxhdGJvcmRlcnMnOiBmbGF0Qm9yZGVyLFxuICAgICAgICAgICAgICctYm9yZGVycmlnaHQnOiBpY29uQWZ0ZXIgfHwgdGV4dEFmdGVyXG4gICAgICAgICAgICAgfVwiXG4gICAgICAgICAgIFthdHRyLnJlYWRvbmx5XT1cInJlYWRvbmx5ID8gdHJ1ZSA6IG51bGxcIlxuICAgICAgICAgICBbYXR0ci5yZXF1aXJlZF09XCJyZXF1aXJlZCA/IHRydWUgOiBudWxsXCJcbiAgICAgICAgICAgW2F0dHIuYXV0b2NvbXBsZXRlXT1cImF1dG9jb21wbGV0ZVwiXG4gICAgICAgICAgIFthdHRyLm1heGxlbmd0aF09XCJtYXhsZW5ndGhcIlxuICAgICAgICAgICBbYXR0ci5uYW1lXT1cIm5hbWVcIlxuICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICAgICAgICAgICBbKG5nTW9kZWwpXT1cInZhbHVlXCJcbiAgICAgICAgICAgKGNsaWNrKT1cIm9uSW5wdXRDbGljaygkZXZlbnQpXCJcbiAgICAgICAgICAgKGJsdXIpPVwib25JbnB1dEJsdXIoJGV2ZW50KVwiXG4gICAgICAgICAgIChmb2N1cyk9XCJvbklucHV0Rm9jdXMoJGV2ZW50KVwiPlxuICAgIDxpICpuZ0lmPVwiY2xlYXJCdXR0b24gJiYgdmFsdWVcIiAoY2xpY2spPVwiY2xlYXJJbnB1dCgkZXZlbnQpXCJcbiAgICAgICBjbGFzcz1cImlvbiBpb24taW9zLWNsb3NlLWNpcmNsZS1vdXRsaW5lIGNsZWFyQnV0dG9uXCI+XG4gICAgPC9pPlxuICA8L2Rpdj5cblxuICA8c3BhbiAjYWZ0ZXJJY29uICpuZ0lmPVwiaWNvbkFmdGVyXCJcbiAgICAgICAgKGNsaWNrKT1cIm9uQ2xpY2tBZGRvbigkZXZlbnQsICdhZnRlcicpXCIgY2xhc3M9XCJhZGRvbiAtYm9yZGVycmlnaHRcIlxuICAgICAgICBbbmdDbGFzc109XCJ7ICd3aXRob3V0Qm9yZGVyJyA6ICF3aXRoQm9yZGVyLCAnLWZsYXRib3JkZXJzJzogZmxhdEJvcmRlciwgJy1ib3JkZXJyaWdodCc6IGljb25BZnRlciB8fCB0ZXh0QWZ0ZXIgfVwiPlxuICAgIDx0bC1pY29uPnt7IGljb25BZnRlciB9fTwvdGwtaWNvbj5cbiAgPC9zcGFuPlxuXG4gIDxzcGFuICpuZ0lmPVwidGV4dEFmdGVyXCIgKGNsaWNrKT1cIm9uQ2xpY2tBZGRvbigkZXZlbnQsICdhZnRlcicpXCIgI2FmdGVyVGV4dCBjbGFzcz1cImFkZG9uIC1ib3JkZXJyaWdodFwiXG4gICAgICAgIFtuZ0NsYXNzXT1cInsgJy1wcmVkZWZpbmVkJyA6IHRleHRBZnRlciwgJy1mbGF0Ym9yZGVycyc6IGZsYXRCb3JkZXIsICd3aXRob3V0Qm9yZGVyJyA6ICF3aXRoQm9yZGVyIH1cIj57e3RleHRBZnRlcn19PC9zcGFuPlxuPC9kaXY+XG4iXX0=