UNPKG

@taiga-ui/kit

Version:

Taiga UI Angular main components kit

189 lines 38.4 kB
import { NgIf } from '@angular/common'; import { ChangeDetectionStrategy, Component, computed, ElementRef, inject, Input, signal, ViewChild, ViewChildren, } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { tuiAsControl, TuiControl } from '@taiga-ui/cdk/classes'; import { CHAR_EN_DASH, CHAR_NO_BREAK_SPACE, EMPTY_QUERY } from '@taiga-ui/cdk/constants'; import { TUI_IS_MOBILE, tuiFallbackValueProvider } from '@taiga-ui/cdk/tokens'; import { tuiIsNativeFocused } from '@taiga-ui/cdk/utils/focus'; import { TUI_TEXTFIELD_OPTIONS, TuiTextfield } from '@taiga-ui/core/components/textfield'; import { TuiInputNumber, TuiInputNumberDirective, TuiQuantumValueTransformerBase, } from '@taiga-ui/kit/components/input-number'; import { TuiRange } from '@taiga-ui/kit/components/range'; import { tuiSliderOptionsProvider, } from '@taiga-ui/kit/components/slider'; import { PolymorpheusOutlet, } from '@taiga-ui/polymorpheus'; import * as i0 from "@angular/core"; import * as i1 from "@angular/forms"; import * as i2 from "@taiga-ui/kit/components/input-number"; import * as i3 from "@taiga-ui/core/components/textfield"; class TuiInputRangeComponent extends TuiControl { constructor() { super(...arguments); this.inputNumberRefs = EMPTY_QUERY; this.isMobile = inject(TUI_IS_MOBILE); this.quantum = signal(0); this.quantumTransformer = computed(() => new TuiQuantumValueTransformerBase(this.quantum())); this.size = inject(TUI_TEXTFIELD_OPTIONS).size; this.textfieldValueStart = this.value()[0]; this.textfieldValueEnd = this.value()[1]; this.lastActiveSide = 'start'; this.content = signal(['', '']); this.contentStart = computed(() => { const [start, end] = this.content().map((x, i) => { const value = this.value()[i]; return typeof x === 'function' ? x({ $implicit: value }) : x || value; }); if (this.interactive() || !this.isPrimitive(start) || !this.isPrimitive(end)) { return this.content()[0]; } return `${start}${CHAR_NO_BREAK_SPACE}${CHAR_EN_DASH}${CHAR_NO_BREAK_SPACE}${end}`; }); this.contentEnd = computed(() => this.contentStart() === this.content()[0] ? this.content()[1] : ''); this.min = 0; this.max = 100; this.step = 1; this.segments = 1; this.keySteps = null; this.prefix = ['', '']; this.postfix = ['', '']; } // TODO(v5): use signal inputs set quantumSetter(x) { this.quantum.set(x); } // TODO(v5): use signal inputs set contentSetter(x) { this.content.set(x); } writeValue(value) { super.writeValue(value); this.setTextfieldValues(this.value()); } ngAfterViewInit() { if (this.range) { this.range.legacyMode = false; // TODO(v5): remove backward compatibility } } get contentStartHidden() { return this.interactive() && tuiIsNativeFocused(this.textfieldStart); } get contentEndHidden() { return (!this.content()[1] || (this.interactive() && tuiIsNativeFocused(this.textfieldEnd))); } takeStep(event, coefficients) { if (!this.interactive() || !this.range) { return; } event.preventDefault(); const [start, end] = this.value(); const newValue = this.valueGuard(this.range.takeStep(coefficients)); if (newValue[0] !== start || newValue[1] !== end) { this.onExternalValueUpdate(newValue); } } onInput([start, end]) { const [prevStart, prevEnd] = this.value(); this.setValue([start ?? prevStart, end ?? prevEnd]); } onExternalValueUpdate(value) { this.setValue(value); this.setTextfieldValues(this.value()); setTimeout((end = Number.MAX_SAFE_INTEGER) => { if (tuiIsNativeFocused(this.activeTextfield)) { this.activeTextfield?.setSelectionRange(end, end); } }); } focusToTextfield() { if (!this.isMobile) { this.activeTextfield?.focus(); } } onBlur() { this.onTouched(); this.setTextfieldValues(this.value()); } onActiveThumbChange(activeThumb) { // TODO(v5): remove backward compatibility this.lastActiveSide = activeThumb === 'left' ? 'start' : 'end'; } setTextfieldValues([start, end]) { this.textfieldValueStart = start; this.textfieldValueEnd = end; } get textfieldStart() { return this.inputNumberRefs.first?.nativeElement || null; } get textfieldEnd() { return this.inputNumberRefs.last?.nativeElement || null; } get activeTextfield() { return this.lastActiveSide === 'start' ? this.textfieldStart : this.textfieldEnd; } setValue(value) { this.onChange(this.valueGuard(value)); } valueGuard(value) { const [prevStart, prevEnd] = this.value(); const [start, end] = value.map((x) => this.quantumTransformer().toControlValue(x) ?? x); return [Math.min(start, prevEnd), Math.max(end, prevStart)]; } isPrimitive(x) { return Object(x) !== x; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiInputRangeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "16.2.12", type: TuiInputRangeComponent, isStandalone: true, selector: "tui-input-range", inputs: { min: "min", max: "max", step: "step", segments: "segments", keySteps: "keySteps", prefix: ["prefix", "prefix", (x) => x ?? ['', '']], postfix: ["postfix", "postfix", (x) => x ?? ['', '']], quantumSetter: ["quantum", "quantumSetter"], contentSetter: ["content", "contentSetter"] }, host: { attributes: { "new": "" }, properties: { "attr.data-size": "size()", "style.--t-icon-lock": "contentEnd() ? \"none\" : null" } }, providers: [ tuiAsControl(TuiInputRangeComponent), tuiSliderOptionsProvider({ trackColor: 'transparent' }), tuiFallbackValueProvider([0, 0]), ], viewQueries: [{ propertyName: "range", first: true, predicate: TuiRange, descendants: true }, { propertyName: "inputNumberRefs", predicate: TuiInputNumberDirective, descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "<tui-textfield [content]=\"contentStartHidden ? '' : contentStart()\">\n <ng-container ngProjectAs=\"label\">\n <ng-content select=\"label\" />\n </ng-container>\n\n <input\n tuiInputNumber\n [disabled]=\"disabled()\"\n [invalid]=\"invalid()\"\n [max]=\"value()[1]\"\n [min]=\"min\"\n [postfix]=\"postfix[0]\"\n [prefix]=\"prefix[0]\"\n [readOnly]=\"readOnly()\"\n [(ngModel)]=\"textfieldValueStart\"\n (blur)=\"onBlur()\"\n (keydown.arrowDown)=\"takeStep($event, [-1, 0])\"\n (keydown.arrowUp)=\"takeStep($event, [1, 0])\"\n (ngModelChange)=\"onInput([$event, null])\"\n />\n\n <input\n tuiInputNumber\n tuiTextfieldAppearance=\"none\"\n class=\"t-end\"\n [class._hidden]=\"!contentEndHidden || !this.interactive()\"\n [disabled]=\"disabled()\"\n [invalid]=\"invalid()\"\n [max]=\"max\"\n [min]=\"value()[0]\"\n [postfix]=\"postfix[1]\"\n [prefix]=\"prefix[1]\"\n [readOnly]=\"readOnly()\"\n [(ngModel)]=\"textfieldValueEnd\"\n (blur)=\"onBlur()\"\n (keydown.arrowDown)=\"takeStep($event, [0, -1])\"\n (keydown.arrowUp)=\"takeStep($event, [0, 1])\"\n (ngModelChange)=\"onInput([null, $event])\"\n />\n\n <div\n class=\"t-content-end\"\n [class._hidden]=\"contentEndHidden\"\n >\n <ng-container *polymorpheusOutlet=\"contentEnd() as text; context: {$implicit: value()[1]}\">\n {{ text }}\n </ng-container>\n </div>\n</tui-textfield>\n\n<tui-range\n *ngIf=\"interactive()\"\n [focusable]=\"false\"\n [keySteps]=\"keySteps\"\n [max]=\"max\"\n [min]=\"min\"\n [ngModel]=\"value()\"\n [segments]=\"segments\"\n [step]=\"step\"\n (activeThumbChange)=\"onActiveThumbChange($event)\"\n (mousedown.prevent)=\"focusToTextfield()\"\n (ngModelChange)=\"onExternalValueUpdate($event)\"\n/>\n", styles: [":host{position:relative;display:block}.t-end{position:absolute;top:0;bottom:0;right:0;left:50%;display:flex;inline-size:50%;text-align:end;outline:none!important;border:none;padding-inline-end:var(--t-padding);color:var(--tui-text-primary);transition:none}.t-end:dir(rtl){right:unset;inset-inline-end:0}.t-content-end{color:var(--tui-text-primary)}tui-textfield:has(label:not(:empty)) .t-content-end{padding-block-start:calc(var(--t-height) / 3)}tui-textfield._with-label .t-content-end{padding-block-start:calc(var(--t-height) / 3)}._hidden._hidden{opacity:0}tui-range{position:absolute;top:100%;left:1rem;right:1rem;z-index:1;margin:calc(-1 * var(--tui-thickness)) 0 0}:host[data-size=m] tui-range{right:.75rem;left:.75rem}:host[data-size=s] tui-range{right:.625rem;left:.625rem}tui-textfield::ng-deep .t-clear{display:none!important}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }, { kind: "directive", type: i2.TuiInputNumberDirective, selector: "input[tuiInputNumber]", inputs: ["min", "max", "prefix", "postfix"] }, { kind: "component", type: TuiRange, selector: "tui-range", inputs: ["min", "max", "step", "size", "segments", "keySteps", "focusable", "margin", "limit"] }, { kind: "component", type: i3.TuiTextfieldComponent, selector: "tui-textfield:not([multi])" }, { kind: "directive", type: i3.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } export { TuiInputRangeComponent }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiInputRangeComponent, decorators: [{ type: Component, args: [{ standalone: true, selector: 'tui-input-range', imports: [ FormsModule, NgIf, PolymorpheusOutlet, TuiInputNumber, TuiRange, TuiTextfield, ], changeDetection: ChangeDetectionStrategy.OnPush, providers: [ tuiAsControl(TuiInputRangeComponent), tuiSliderOptionsProvider({ trackColor: 'transparent' }), tuiFallbackValueProvider([0, 0]), ], host: { new: '', // TODO: use css :host:has(tui-textfield[data-size]) after browser bump '[attr.data-size]': 'size()', '[style.--t-icon-lock]': 'contentEnd() ? "none" : null', }, template: "<tui-textfield [content]=\"contentStartHidden ? '' : contentStart()\">\n <ng-container ngProjectAs=\"label\">\n <ng-content select=\"label\" />\n </ng-container>\n\n <input\n tuiInputNumber\n [disabled]=\"disabled()\"\n [invalid]=\"invalid()\"\n [max]=\"value()[1]\"\n [min]=\"min\"\n [postfix]=\"postfix[0]\"\n [prefix]=\"prefix[0]\"\n [readOnly]=\"readOnly()\"\n [(ngModel)]=\"textfieldValueStart\"\n (blur)=\"onBlur()\"\n (keydown.arrowDown)=\"takeStep($event, [-1, 0])\"\n (keydown.arrowUp)=\"takeStep($event, [1, 0])\"\n (ngModelChange)=\"onInput([$event, null])\"\n />\n\n <input\n tuiInputNumber\n tuiTextfieldAppearance=\"none\"\n class=\"t-end\"\n [class._hidden]=\"!contentEndHidden || !this.interactive()\"\n [disabled]=\"disabled()\"\n [invalid]=\"invalid()\"\n [max]=\"max\"\n [min]=\"value()[0]\"\n [postfix]=\"postfix[1]\"\n [prefix]=\"prefix[1]\"\n [readOnly]=\"readOnly()\"\n [(ngModel)]=\"textfieldValueEnd\"\n (blur)=\"onBlur()\"\n (keydown.arrowDown)=\"takeStep($event, [0, -1])\"\n (keydown.arrowUp)=\"takeStep($event, [0, 1])\"\n (ngModelChange)=\"onInput([null, $event])\"\n />\n\n <div\n class=\"t-content-end\"\n [class._hidden]=\"contentEndHidden\"\n >\n <ng-container *polymorpheusOutlet=\"contentEnd() as text; context: {$implicit: value()[1]}\">\n {{ text }}\n </ng-container>\n </div>\n</tui-textfield>\n\n<tui-range\n *ngIf=\"interactive()\"\n [focusable]=\"false\"\n [keySteps]=\"keySteps\"\n [max]=\"max\"\n [min]=\"min\"\n [ngModel]=\"value()\"\n [segments]=\"segments\"\n [step]=\"step\"\n (activeThumbChange)=\"onActiveThumbChange($event)\"\n (mousedown.prevent)=\"focusToTextfield()\"\n (ngModelChange)=\"onExternalValueUpdate($event)\"\n/>\n", styles: [":host{position:relative;display:block}.t-end{position:absolute;top:0;bottom:0;right:0;left:50%;display:flex;inline-size:50%;text-align:end;outline:none!important;border:none;padding-inline-end:var(--t-padding);color:var(--tui-text-primary);transition:none}.t-end:dir(rtl){right:unset;inset-inline-end:0}.t-content-end{color:var(--tui-text-primary)}tui-textfield:has(label:not(:empty)) .t-content-end{padding-block-start:calc(var(--t-height) / 3)}tui-textfield._with-label .t-content-end{padding-block-start:calc(var(--t-height) / 3)}._hidden._hidden{opacity:0}tui-range{position:absolute;top:100%;left:1rem;right:1rem;z-index:1;margin:calc(-1 * var(--tui-thickness)) 0 0}:host[data-size=m] tui-range{right:.75rem;left:.75rem}:host[data-size=s] tui-range{right:.625rem;left:.625rem}tui-textfield::ng-deep .t-clear{display:none!important}\n"] }] }], propDecorators: { inputNumberRefs: [{ type: ViewChildren, args: [TuiInputNumberDirective, { read: ElementRef }] }], range: [{ type: ViewChild, args: [TuiRange] }], min: [{ type: Input }], max: [{ type: Input }], step: [{ type: Input }], segments: [{ type: Input }], keySteps: [{ type: Input }], prefix: [{ type: Input, args: [{ transform: (x) => x ?? ['', ''] }] }], postfix: [{ type: Input, args: [{ transform: (x) => x ?? ['', ''] }] }], quantumSetter: [{ type: Input, args: ['quantum'] }], contentSetter: [{ type: Input, args: ['content'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQtcmFuZ2UuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMva2l0L2NvbXBvbmVudHMvaW5wdXQtcmFuZ2UvaW5wdXQtcmFuZ2UuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMva2l0L2NvbXBvbmVudHMvaW5wdXQtcmFuZ2UvaW5wdXQtcmFuZ2UudGVtcGxhdGUuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsSUFBSSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDckMsT0FBTyxFQUVILHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsUUFBUSxFQUNSLFVBQVUsRUFDVixNQUFNLEVBQ04sS0FBSyxFQUVMLE1BQU0sRUFDTixTQUFTLEVBQ1QsWUFBWSxHQUNmLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLEVBQUMsWUFBWSxFQUFFLFVBQVUsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBQy9ELE9BQU8sRUFBQyxZQUFZLEVBQUUsbUJBQW1CLEVBQUUsV0FBVyxFQUFDLE1BQU0seUJBQXlCLENBQUM7QUFDdkYsT0FBTyxFQUFDLGFBQWEsRUFBRSx3QkFBd0IsRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBRTdFLE9BQU8sRUFBQyxrQkFBa0IsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBQzdELE9BQU8sRUFBQyxxQkFBcUIsRUFBRSxZQUFZLEVBQUMsTUFBTSxxQ0FBcUMsQ0FBQztBQUN4RixPQUFPLEVBQ0gsY0FBYyxFQUNkLHVCQUF1QixFQUN2Qiw4QkFBOEIsR0FDakMsTUFBTSx1Q0FBdUMsQ0FBQztBQUMvQyxPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0sZ0NBQWdDLENBQUM7QUFDeEQsT0FBTyxFQUVILHdCQUF3QixHQUMzQixNQUFNLGlDQUFpQyxDQUFDO0FBQ3pD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LHVCQUF1QixFQUFFLEVBQUMsSUFBSSxFQUFFLFVBQVUsRUFBQztnQkFLeEMsS0FBSztzQkFEckIsU0FBUzt1QkFBQyxRQUFRO2dCQXVDWixHQUFHO3NCQURULEtBQUs7Z0JBSUMsR0FBRztzQkFEVCxLQUFLO2dCQUlDLElBQUk7c0JBRFYsS0FBSztnQkFJQyxRQUFRO3NCQURkLEtBQUs7Z0JBSUMsUUFBUTtzQkFEZCxLQUFLO2dCQUlDLE1BQU07c0JBRFosS0FBSzt1QkFBQyxFQUFDLFNBQVMsRUFBRSxDQUFDLENBQW1DLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBQztnQkFJbkUsT0FBTztzQkFEYixLQUFLO3VCQUFDLEVBQUMsU0FBUyxFQUFFLENBQUMsQ0FBbUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFDO2dCQUsvRCxhQUFhO3NCQUR2QixLQUFLO3VCQUFDLFNBQVM7Z0JBT0wsYUFBYTtzQkFEdkIsS0FBSzt1QkFBQyxTQUFTIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtOZ0lmfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgICB0eXBlIEFmdGVyVmlld0luaXQsXG4gICAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gICAgQ29tcG9uZW50LFxuICAgIGNvbXB1dGVkLFxuICAgIEVsZW1lbnRSZWYsXG4gICAgaW5qZWN0LFxuICAgIElucHV0LFxuICAgIHR5cGUgUXVlcnlMaXN0LFxuICAgIHNpZ25hbCxcbiAgICBWaWV3Q2hpbGQsXG4gICAgVmlld0NoaWxkcmVuLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7Rm9ybXNNb2R1bGV9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7dHVpQXNDb250cm9sLCBUdWlDb250cm9sfSBmcm9tICdAdGFpZ2EtdWkvY2RrL2NsYXNzZXMnO1xuaW1wb3J0IHtDSEFSX0VOX0RBU0gsIENIQVJfTk9fQlJFQUtfU1BBQ0UsIEVNUFRZX1FVRVJZfSBmcm9tICdAdGFpZ2EtdWkvY2RrL2NvbnN0YW50cyc7XG5pbXBvcnQge1RVSV9JU19NT0JJTEUsIHR1aUZhbGxiYWNrVmFsdWVQcm92aWRlcn0gZnJvbSAnQHRhaWdhLXVpL2Nkay90b2tlbnMnO1xuaW1wb3J0IHt0eXBlIFR1aUNvbnRleHR9IGZyb20gJ0B0YWlnYS11aS9jZGsvdHlwZXMnO1xuaW1wb3J0IHt0dWlJc05hdGl2ZUZvY3VzZWR9IGZyb20gJ0B0YWlnYS11aS9jZGsvdXRpbHMvZm9jdXMnO1xuaW1wb3J0IHtUVUlfVEVYVEZJRUxEX09QVElPTlMsIFR1aVRleHRmaWVsZH0gZnJvbSAnQHRhaWdhLXVpL2NvcmUvY29tcG9uZW50cy90ZXh0ZmllbGQnO1xuaW1wb3J0IHtcbiAgICBUdWlJbnB1dE51bWJlcixcbiAgICBUdWlJbnB1dE51bWJlckRpcmVjdGl2ZSxcbiAgICBUdWlRdWFudHVtVmFsdWVUcmFuc2Zvcm1lckJhc2UsXG59IGZyb20gJ0B0YWlnYS11aS9raXQvY29tcG9uZW50cy9pbnB1dC1udW1iZXInO1xuaW1wb3J0IHtUdWlSYW5nZX0gZnJvbSAnQHRhaWdhLXVpL2tpdC9jb21wb25lbnRzL3JhbmdlJztcbmltcG9ydCB7XG4gICAgdHlwZSBUdWlLZXlTdGVwcyxcbiAgICB0dWlTbGlkZXJPcHRpb25zUHJvdmlkZXIsXG59IGZyb20gJ0B0YWlnYS11aS9raXQvY29tcG9uZW50cy9zbGlkZXInO1xuaW1wb3J0IHtcbiAgICB0eXBlIFBvbHltb3JwaGV1c0NvbnRlbnQsXG4gICAgUG9seW1vcnBoZXVzT3V0bGV0LFxuICAgIHR5cGUgUG9seW1vcnBoZXVzUHJpbWl0aXZlLFxufSBmcm9tICdAdGFpZ2EtdWkvcG9seW1vcnBoZXVzJztcblxuQENvbXBvbmVudCh7XG4gICAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgICBzZWxlY3RvcjogJ3R1aS1pbnB1dC1yYW5nZScsXG4gICAgaW1wb3J0czogW1xuICAgICAgICBGb3Jtc01vZHVsZSxcbiAgICAgICAgTmdJZixcbiAgICAgICAgUG9seW1vcnBoZXVzT3V0bGV0LFxuICAgICAgICBUdWlJbnB1dE51bWJlcixcbiAgICAgICAgVHVpUmFuZ2UsXG4gICAgICAgIFR1aVRleHRmaWVsZCxcbiAgICBdLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9pbnB1dC1yYW5nZS50ZW1wbGF0ZS5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9pbnB1dC1yYW5nZS5zdHlsZS5sZXNzJ10sXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIHR1aUFzQ29udHJvbChUdWlJbnB1dFJhbmdlQ29tcG9uZW50KSxcbiAgICAgICAgdHVpU2xpZGVyT3B0aW9uc1Byb3ZpZGVyKHt0cmFja0NvbG9yOiAndHJhbnNwYXJlbnQnfSksXG4gICAgICAgIHR1aUZhbGxiYWNrVmFsdWVQcm92aWRlcihbMCwgMF0pLFxuICAgIF0sXG4gICAgaG9zdDoge1xuICAgICAgICBuZXc6ICcnLCAvLyBUT0RPKHY1KTogcmVtb3ZlIGFmdGVyIGRlbGV0aW9uIG9mIGxlZ2FjeSBjb250cm9sXG4gICAgICAgIC8vIFRPRE86IHVzZSBjc3MgOmhvc3Q6aGFzKHR1aS10ZXh0ZmllbGRbZGF0YS1zaXplXSkgYWZ0ZXIgYnJvd3NlciBidW1wXG4gICAgICAgICdbYXR0ci5kYXRhLXNpemVdJzogJ3NpemUoKScsXG4gICAgICAgICdbc3R5bGUuLS10LWljb24tbG9ja10nOiAnY29udGVudEVuZCgpID8gXCJub25lXCIgOiBudWxsJyxcbiAgICB9LFxufSlcbmV4cG9ydCBjbGFzcyBUdWlJbnB1dFJhbmdlQ29tcG9uZW50XG4gICAgZXh0ZW5kcyBUdWlDb250cm9sPHJlYWRvbmx5IFtudW1iZXIsIG51bWJlcl0+XG4gICAgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0XG57XG4gICAgQFZpZXdDaGlsZHJlbihUdWlJbnB1dE51bWJlckRpcmVjdGl2ZSwge3JlYWQ6IEVsZW1lbnRSZWZ9KVxuICAgIHByaXZhdGUgcmVhZG9ubHkgaW5wdXROdW1iZXJSZWZzOiBRdWVyeUxpc3Q8RWxlbWVudFJlZjxIVE1MSW5wdXRFbGVtZW50Pj4gPVxuICAgICAgICBFTVBUWV9RVUVSWTtcblxuICAgIEBWaWV3Q2hpbGQoVHVpUmFuZ2UpXG4gICAgcHJpdmF0ZSByZWFkb25seSByYW5nZT86IFR1aVJhbmdlO1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSBpc01vYmlsZSA9IGluamVjdChUVUlfSVNfTU9CSUxFKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IHF1YW50dW0gPSBzaWduYWwoMCk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBxdWFudHVtVHJhbnNmb3JtZXIgPSBjb21wdXRlZChcbiAgICAgICAgKCkgPT4gbmV3IFR1aVF1YW50dW1WYWx1ZVRyYW5zZm9ybWVyQmFzZSh0aGlzLnF1YW50dW0oKSksXG4gICAgKTtcblxuICAgIHByb3RlY3RlZCByZWFkb25seSBzaXplID0gaW5qZWN0KFRVSV9URVhURklFTERfT1BUSU9OUykuc2l6ZTtcbiAgICBwcm90ZWN0ZWQgdGV4dGZpZWxkVmFsdWVTdGFydCA9IHRoaXMudmFsdWUoKVswXTtcbiAgICBwcm90ZWN0ZWQgdGV4dGZpZWxkVmFsdWVFbmQgPSB0aGlzLnZhbHVlKClbMV07XG4gICAgcHJvdGVjdGVkIGxhc3RBY3RpdmVTaWRlOiAnZW5kJyB8ICdzdGFydCcgPSAnc3RhcnQnO1xuICAgIHByb3RlY3RlZCByZWFkb25seSBjb250ZW50ID0gc2lnbmFsPFxuICAgICAgICByZWFkb25seSBbXG4gICAgICAgICAgICBQb2x5bW9ycGhldXNDb250ZW50PFR1aUNvbnRleHQ8bnVtYmVyPj4sXG4gICAgICAgICAgICBQb2x5bW9ycGhldXNDb250ZW50PFR1aUNvbnRleHQ8bnVtYmVyPj4sXG4gICAgICAgIF1cbiAgICA+KFsnJywgJyddKTtcblxuICAgIHByb3RlY3RlZCByZWFkb25seSBjb250ZW50U3RhcnQgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IFtzdGFydCwgZW5kXSA9IHRoaXMuY29udGVudCgpLm1hcCgoeCwgaSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnZhbHVlKClbaV0hO1xuXG4gICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09ICdmdW5jdGlvbicgPyB4KHskaW1wbGljaXQ6IHZhbHVlfSkgOiB4IHx8IHZhbHVlO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodGhpcy5pbnRlcmFjdGl2ZSgpIHx8ICF0aGlzLmlzUHJpbWl0aXZlKHN0YXJ0KSB8fCAhdGhpcy5pc1ByaW1pdGl2ZShlbmQpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250ZW50KClbMF07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYCR7c3RhcnR9JHtDSEFSX05PX0JSRUFLX1NQQUNFfSR7Q0hBUl9FTl9EQVNIfSR7Q0hBUl9OT19CUkVBS19TUEFDRX0ke2VuZH1gO1xuICAgIH0pO1xuXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGNvbnRlbnRFbmQgPSBjb21wdXRlZCgoKSA9PlxuICAgICAgICB0aGlzLmNvbnRlbnRTdGFydCgpID09PSB0aGlzLmNvbnRlbnQoKVswXSA/IHRoaXMuY29udGVudCgpWzFdIDogJycsXG4gICAgKTtcblxuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIG1pbiA9IDA7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBtYXggPSAxMDA7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBzdGVwID0gMTtcblxuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIHNlZ21lbnRzID0gMTtcblxuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGtleVN0ZXBzOiBUdWlLZXlTdGVwcyB8IG51bGwgPSBudWxsO1xuXG4gICAgQElucHV0KHt0cmFuc2Zvcm06ICh4OiByZWFkb25seSBbc3RyaW5nLCBzdHJpbmddIHwgbnVsbCkgPT4geCA/PyBbJycsICcnXX0pXG4gICAgcHVibGljIHByZWZpeDogcmVhZG9ubHkgW3N0cmluZywgc3RyaW5nXSA9IFsnJywgJyddO1xuXG4gICAgQElucHV0KHt0cmFuc2Zvcm06ICh4OiByZWFkb25seSBbc3RyaW5nLCBzdHJpbmddIHwgbnVsbCkgPT4geCA/PyBbJycsICcnXX0pXG4gICAgcHVibGljIHBvc3RmaXg6IHJlYWRvbmx5IFtzdHJpbmcsIHN0cmluZ10gPSBbJycsICcnXTtcblxuICAgIC8vIFRPRE8odjUpOiB1c2Ugc2lnbmFsIGlucHV0c1xuICAgIEBJbnB1dCgncXVhbnR1bScpXG4gICAgcHVibGljIHNldCBxdWFudHVtU2V0dGVyKHg6IG51bWJlcikge1xuICAgICAgICB0aGlzLnF1YW50dW0uc2V0KHgpO1xuICAgIH1cblxuICAgIC8vIFRPRE8odjUpOiB1c2Ugc2lnbmFsIGlucHV0c1xuICAgIEBJbnB1dCgnY29udGVudCcpXG4gICAgcHVibGljIHNldCBjb250ZW50U2V0dGVyKFxuICAgICAgICB4OiByZWFkb25seSBbXG4gICAgICAgICAgICBQb2x5bW9ycGhldXNDb250ZW50PFR1aUNvbnRleHQ8bnVtYmVyPj4sXG4gICAgICAgICAgICBQb2x5bW9ycGhldXNDb250ZW50PFR1aUNvbnRleHQ8bnVtYmVyPj4sXG4gICAgICAgIF0sXG4gICAgKSB7XG4gICAgICAgIHRoaXMuY29udGVudC5zZXQoeCk7XG4gICAgfVxuXG4gICAgcHVibGljIG92ZXJyaWRlIHdyaXRlVmFsdWUodmFsdWU6IFtudW1iZXIsIG51bWJlcl0pOiB2b2lkIHtcbiAgICAgICAgc3VwZXIud3JpdGVWYWx1ZSh2YWx1ZSk7XG4gICAgICAgIHRoaXMuc2V0VGV4dGZpZWxkVmFsdWVzKHRoaXMudmFsdWUoKSk7XG4gICAgfVxuXG4gICAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMucmFuZ2UpIHtcbiAgICAgICAgICAgIHRoaXMucmFuZ2UubGVnYWN5TW9kZSA9IGZhbHNlOyAvLyBUT0RPKHY1KTogcmVtb3ZlIGJhY2t3YXJkIGNvbXBhdGliaWxpdHlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXQgY29udGVudFN0YXJ0SGlkZGVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pbnRlcmFjdGl2ZSgpICYmIHR1aUlzTmF0aXZlRm9jdXNlZCh0aGlzLnRleHRmaWVsZFN0YXJ0KTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0IGNvbnRlbnRFbmRIaWRkZW4oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAhdGhpcy5jb250ZW50KClbMV0gfHxcbiAgICAgICAgICAgICh0aGlzLmludGVyYWN0aXZlKCkgJiYgdHVpSXNOYXRpdmVGb2N1c2VkKHRoaXMudGV4dGZpZWxkRW5kKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgdGFrZVN0ZXAoXG4gICAgICAgIGV2ZW50OiBFdmVudCB8IEtleWJvYXJkRXZlbnQsXG4gICAgICAgIGNvZWZmaWNpZW50czogcmVhZG9ubHkgW251bWJlciwgbnVtYmVyXSxcbiAgICApOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLmludGVyYWN0aXZlKCkgfHwgIXRoaXMucmFuZ2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgY29uc3QgW3N0YXJ0LCBlbmRdID0gdGhpcy52YWx1ZSgpO1xuICAgICAgICBjb25zdCBuZXdWYWx1ZSA9IHRoaXMudmFsdWVHdWFyZCh0aGlzLnJhbmdlLnRha2VTdGVwKGNvZWZmaWNpZW50cykpO1xuXG4gICAgICAgIGlmIChuZXdWYWx1ZVswXSAhPT0gc3RhcnQgfHwgbmV3VmFsdWVbMV0gIT09IGVuZCkge1xuICAgICAgICAgICAgdGhpcy5vbkV4dGVybmFsVmFsdWVVcGRhdGUobmV3VmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIG9uSW5wdXQoW3N0YXJ0LCBlbmRdOiBbbnVtYmVyIHwgbnVsbCwgbnVtYmVyIHwgbnVsbF0pOiB2b2lkIHtcbiAgICAgICAgY29uc3QgW3ByZXZTdGFydCwgcHJldkVuZF0gPSB0aGlzLnZhbHVlKCk7XG5cbiAgICAgICAgdGhpcy5zZXRWYWx1ZShbc3RhcnQgPz8gcHJldlN0YXJ0LCBlbmQgPz8gcHJldkVuZF0pO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBvbkV4dGVybmFsVmFsdWVVcGRhdGUodmFsdWU6IHJlYWRvbmx5IFtudW1iZXIsIG51bWJlcl0pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRWYWx1ZSh2YWx1ZSk7XG4gICAgICAgIHRoaXMuc2V0VGV4dGZpZWxkVmFsdWVzKHRoaXMudmFsdWUoKSk7XG5cbiAgICAgICAgc2V0VGltZW91dCgoZW5kID0gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIpID0+IHtcbiAgICAgICAgICAgIGlmICh0dWlJc05hdGl2ZUZvY3VzZWQodGhpcy5hY3RpdmVUZXh0ZmllbGQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVUZXh0ZmllbGQ/LnNldFNlbGVjdGlvblJhbmdlKGVuZCwgZW5kKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGZvY3VzVG9UZXh0ZmllbGQoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5pc01vYmlsZSkge1xuICAgICAgICAgICAgdGhpcy5hY3RpdmVUZXh0ZmllbGQ/LmZvY3VzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgb25CbHVyKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uVG91Y2hlZCgpO1xuICAgICAgICB0aGlzLnNldFRleHRmaWVsZFZhbHVlcyh0aGlzLnZhbHVlKCkpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBvbkFjdGl2ZVRodW1iQ2hhbmdlKGFjdGl2ZVRodW1iOiAnbGVmdCcgfCAncmlnaHQnKTogdm9pZCB7XG4gICAgICAgIC8vIFRPRE8odjUpOiByZW1vdmUgYmFja3dhcmQgY29tcGF0aWJpbGl0eVxuICAgICAgICB0aGlzLmxhc3RBY3RpdmVTaWRlID0gYWN0aXZlVGh1bWIgPT09ICdsZWZ0JyA/ICdzdGFydCcgOiAnZW5kJztcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc2V0VGV4dGZpZWxkVmFsdWVzKFtzdGFydCwgZW5kXTogcmVhZG9ubHkgW251bWJlciwgbnVtYmVyXSk6IHZvaWQge1xuICAgICAgICB0aGlzLnRleHRmaWVsZFZhbHVlU3RhcnQgPSBzdGFydDtcbiAgICAgICAgdGhpcy50ZXh0ZmllbGRWYWx1ZUVuZCA9IGVuZDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldCB0ZXh0ZmllbGRTdGFydCgpOiBIVE1MSW5wdXRFbGVtZW50IHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLmlucHV0TnVtYmVyUmVmcy5maXJzdD8ubmF0aXZlRWxlbWVudCB8fCBudWxsO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IHRleHRmaWVsZEVuZCgpOiBIVE1MSW5wdXRFbGVtZW50IHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLmlucHV0TnVtYmVyUmVmcy5sYXN0Py5uYXRpdmVFbGVtZW50IHx8IG51bGw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXQgYWN0aXZlVGV4dGZpZWxkKCk6IEhUTUxJbnB1dEVsZW1lbnQgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGFzdEFjdGl2ZVNpZGUgPT09ICdzdGFydCcgPyB0aGlzLnRleHRmaWVsZFN0YXJ0IDogdGhpcy50ZXh0ZmllbGRFbmQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZXRWYWx1ZSh2YWx1ZTogcmVhZG9ubHkgW251bWJlciwgbnVtYmVyXSk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uQ2hhbmdlKHRoaXMudmFsdWVHdWFyZCh2YWx1ZSkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgdmFsdWVHdWFyZCh2YWx1ZTogcmVhZG9ubHkgW251bWJlciwgbnVtYmVyXSk6IHJlYWRvbmx5IFtudW1iZXIsIG51bWJlcl0ge1xuICAgICAgICBjb25zdCBbcHJldlN0YXJ0LCBwcmV2RW5kXSA9IHRoaXMudmFsdWUoKTtcbiAgICAgICAgY29uc3QgW3N0YXJ0LCBlbmRdID0gdmFsdWUubWFwKFxuICAgICAgICAgICAgKHgpID0+IHRoaXMucXVhbnR1bVRyYW5zZm9ybWVyKCkudG9Db250cm9sVmFsdWUoeCkgPz8geCxcbiAgICAgICAgKSBhcyB1bmtub3duIGFzIHJlYWRvbmx5IFtudW1iZXIsIG51bWJlcl07XG5cbiAgICAgICAgcmV0dXJuIFtNYXRoLm1pbihzdGFydCwgcHJldkVuZCksIE1hdGgubWF4KGVuZCwgcHJldlN0YXJ0KV07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpc1ByaW1pdGl2ZSh4OiBQb2x5bW9ycGhldXNDb250ZW50KTogeCBpcyBQb2x5bW9ycGhldXNQcmltaXRpdmUge1xuICAgICAgICByZXR1cm4gT2JqZWN0KHgpICE9PSB4O1xuICAgIH1cbn1cbiIsIjx0dWktdGV4dGZpZWxkIFtjb250ZW50XT1cImNvbnRlbnRTdGFydEhpZGRlbiA/ICcnIDogY29udGVudFN0YXJ0KClcIj5cbiAgICA8bmctY29udGFpbmVyIG5nUHJvamVjdEFzPVwibGFiZWxcIj5cbiAgICAgICAgPG5nLWNvbnRlbnQgc2VsZWN0PVwibGFiZWxcIiAvPlxuICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgPGlucHV0XG4gICAgICAgIHR1aUlucHV0TnVtYmVyXG4gICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZCgpXCJcbiAgICAgICAgW2ludmFsaWRdPVwiaW52YWxpZCgpXCJcbiAgICAgICAgW21heF09XCJ2YWx1ZSgpWzFdXCJcbiAgICAgICAgW21pbl09XCJtaW5cIlxuICAgICAgICBbcG9zdGZpeF09XCJwb3N0Zml4WzBdXCJcbiAgICAgICAgW3ByZWZpeF09XCJwcmVmaXhbMF1cIlxuICAgICAgICBbcmVhZE9ubHldPVwicmVhZE9ubHkoKVwiXG4gICAgICAgIFsobmdNb2RlbCldPVwidGV4dGZpZWxkVmFsdWVTdGFydFwiXG4gICAgICAgIChibHVyKT1cIm9uQmx1cigpXCJcbiAgICAgICAgKGtleWRvd24uYXJyb3dEb3duKT1cInRha2VTdGVwKCRldmVudCwgWy0xLCAwXSlcIlxuICAgICAgICAoa2V5ZG93bi5hcnJvd1VwKT1cInRha2VTdGVwKCRldmVudCwgWzEsIDBdKVwiXG4gICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uSW5wdXQoWyRldmVudCwgbnVsbF0pXCJcbiAgICAvPlxuXG4gICAgPGlucHV0XG4gICAgICAgIHR1aUlucHV0TnVtYmVyXG4gICAgICAgIHR1aVRleHRmaWVsZEFwcGVhcmFuY2U9XCJub25lXCJcbiAgICAgICAgY2xhc3M9XCJ0LWVuZFwiXG4gICAgICAgIFtjbGFzcy5faGlkZGVuXT1cIiFjb250ZW50RW5kSGlkZGVuIHx8ICF0aGlzLmludGVyYWN0aXZlKClcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWQoKVwiXG4gICAgICAgIFtpbnZhbGlkXT1cImludmFsaWQoKVwiXG4gICAgICAgIFttYXhdPVwibWF4XCJcbiAgICAgICAgW21pbl09XCJ2YWx1ZSgpWzBdXCJcbiAgICAgICAgW3Bvc3RmaXhdPVwicG9zdGZpeFsxXVwiXG4gICAgICAgIFtwcmVmaXhdPVwicHJlZml4WzFdXCJcbiAgICAgICAgW3JlYWRPbmx5XT1cInJlYWRPbmx5KClcIlxuICAgICAgICBbKG5nTW9kZWwpXT1cInRleHRmaWVsZFZhbHVlRW5kXCJcbiAgICAgICAgKGJsdXIpPVwib25CbHVyKClcIlxuICAgICAgICAoa2V5ZG93bi5hcnJvd0Rvd24pPVwidGFrZVN0ZXAoJGV2ZW50LCBbMCwgLTFdKVwiXG4gICAgICAgIChrZXlkb3duLmFycm93VXApPVwidGFrZVN0ZXAoJGV2ZW50LCBbMCwgMV0pXCJcbiAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25JbnB1dChbbnVsbCwgJGV2ZW50XSlcIlxuICAgIC8+XG5cbiAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwidC1jb250ZW50LWVuZFwiXG4gICAgICAgIFtjbGFzcy5faGlkZGVuXT1cImNvbnRlbnRFbmRIaWRkZW5cIlxuICAgID5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqcG9seW1vcnBoZXVzT3V0bGV0PVwiY29udGVudEVuZCgpIGFzIHRleHQ7IGNvbnRleHQ6IHskaW1wbGljaXQ6IHZhbHVlKClbMV19XCI+XG4gICAgICAgICAgICB7eyB0ZXh0IH19XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgIDwvZGl2PlxuPC90dWktdGV4dGZpZWxkPlxuXG48dHVpLXJhbmdlXG4gICAgKm5nSWY9XCJpbnRlcmFjdGl2ZSgpXCJcbiAgICBbZm9jdXNhYmxlXT1cImZhbHNlXCJcbiAgICBba2V5U3RlcHNdPVwia2V5U3RlcHNcIlxuICAgIFttYXhdPVwibWF4XCJcbiAgICBbbWluXT1cIm1pblwiXG4gICAgW25nTW9kZWxdPVwidmFsdWUoKVwiXG4gICAgW3NlZ21lbnRzXT1cInNlZ21lbnRzXCJcbiAgICBbc3RlcF09XCJzdGVwXCJcbiAgICAoYWN0aXZlVGh1bWJDaGFuZ2UpPVwib25BY3RpdmVUaHVtYkNoYW5nZSgkZXZlbnQpXCJcbiAgICAobW91c2Vkb3duLnByZXZlbnQpPVwiZm9jdXNUb1RleHRmaWVsZCgpXCJcbiAgICAobmdNb2RlbENoYW5nZSk9XCJvbkV4dGVybmFsVmFsdWVVcGRhdGUoJGV2ZW50KVwiXG4vPlxuIl19