ngx-onscreen-twelvekeyboard
Version:
A twelve key (0-9, * and #) keypad on-screen touch keyboard for Angular applications.
185 lines • 35.1 kB
JavaScript
import { Component, EventEmitter, Input, Output, } from '@angular/core';
import { keyAssignments } from '../key-assignments/key-assignments';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
export class KeypadComponent {
constructor() {
this.languageAssignment = keyAssignments['eng'];
this.timeoutDuration = 2000;
this.value = '';
this.backspaceEnabled = false;
this.clearEnabled = false;
this.shift = false;
this.shiftChange = new EventEmitter();
this.valueChange = new EventEmitter();
this.vanityChange = new EventEmitter();
this.pressedKeysChange = new EventEmitter();
this.inputFocusChange = new EventEmitter();
this._pressedKeys = '';
this._keyAssignmentIndex = -1;
this._inputTimeout = 0;
}
get pressedKeys() {
return this._pressedKeys;
}
set pressedKeys(value) {
this._pressedKeys = value;
}
get keyAssignmentIndex() {
return this._keyAssignmentIndex;
}
set keyAssignmentIndex(index) {
this._keyAssignmentIndex = index;
}
get inputTimeout() {
return this._inputTimeout;
}
set inputTimeout(inputTimeout) {
this._inputTimeout = inputTimeout;
}
get setButton() {
return this._setButton;
}
set setButton(button) {
this._setButton = button;
}
ngOnInit() {
if (!(this.language && this.language in keyAssignments)) {
console.error(`Given language "${this.language}" is not supported yet.`);
}
else {
this.languageAssignment = keyAssignments[this.language];
}
}
ngOnDestroy() {
this.clearTimeout();
}
getButtonClickFunction(button) {
return (event) => this.onButtonClick(button, event);
}
onButtonClick(button, event) {
event.preventDefault();
if (this.backspaceEnabled && button === '*') {
this.handleBackspace();
}
else if (this.clearEnabled && button === '#') {
this.handleClear();
}
else {
if (button !== this.setButton) {
this.updateValue();
this.keyAssignmentIndex = 0;
}
else {
this.keyAssignmentIndex = (this.keyAssignmentIndex + 1) %
this.languageAssignment.keys[button].length;
}
this.setButton = button;
this.setPressedKeys(this.pressedKeys += button);
}
this.resetTimeout();
}
reset() {
this.pressedKeys = '';
this.value = '';
this.keyAssignmentIndex = -1;
this.setButton = void 0;
}
emitInputFocusEvent(value) {
this.inputFocusChange.emit(value);
}
handleBackspace() {
this.setPressedKeys(this.pressedKeys.substring(0, this.pressedKeys.length - 1));
this.setValue(this.value.substring(0, this.value.length - 1));
this.setButton = void 0;
}
handleClear() {
this.setPressedKeys('');
this.setValue('');
this.setButton = void 0;
}
updateVanity() {
let vanity = '^';
for (const pressedKey of this.pressedKeys) {
vanity += `(${this.languageAssignment.keys[pressedKey].join('|')})`;
}
this.vanityChange.emit(vanity);
}
resetTimeout() {
window.clearTimeout(this._inputTimeout);
this._inputTimeout = window.setTimeout(() => {
if (this.setButton) {
this.updateValue();
}
this.setButton = void 0;
this.inputTimeout = 0;
this.keyAssignmentIndex = -1;
}, this.timeoutDuration);
}
setPressedKeys(pressedKeys) {
this.pressedKeys = pressedKeys;
this.pressedKeysChange.emit(this.pressedKeys);
this.updateVanity();
}
setShift(value) {
this.shift = value;
this.shiftChange.emit(value);
}
updateValue() {
if (this.setButton) {
const newCharacter = this.languageAssignment.keys[this.setButton][this.keyAssignmentIndex];
this.setValue(this.value +
(this.shift ? newCharacter.toUpperCase() : newCharacter));
this.setShift(false);
}
}
clearTimeout() {
window.clearTimeout(this._inputTimeout);
}
setValue(value) {
this.value = value;
this.valueChange.emit(this.value);
}
}
KeypadComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: KeypadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
KeypadComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: KeypadComponent, selector: "osk-keypad", inputs: { buttonTemplate: "buttonTemplate", backspaceTemplate: "backspaceTemplate", clearTemplate: "clearTemplate", language: "language", timeoutDuration: "timeoutDuration", value: "value", backspaceEnabled: "backspaceEnabled", clearEnabled: "clearEnabled", shift: "shift" }, outputs: { shiftChange: "shiftChange", valueChange: "valueChange", vanityChange: "vanity", pressedKeysChange: "pressedKeys", inputFocusChange: "inputFocus" }, ngImport: i0, template: "<ng-template #defaultButtonTemplate let-click=\"click\" let-content=\"content\">\n <button (mousedown)=\"click($event)\">\n <ng-container [ngTemplateOutlet]=\"content\"></ng-container>\n </button>\n</ng-template>\n\n<ng-template #defaultBackspaceTemplate>\n <span><-</span>\n</ng-template>\n\n<ng-template #defaultClearTemplate>\n <span>x</span>\n</ng-template>\n\n<div class=\"button-container\">\n <div class=\"button-row\">\n <ng-container [ngTemplateOutletContext]=\"{content: buttonOneContent, click: getButtonClickFunction('1')}\"\n [ngTemplateOutlet]=\"buttonTemplate || defaultButtonTemplate\">\n <ng-template #buttonOneContent>\n <span>1<br>\n .@&</span>\n </ng-template>\n </ng-container>\n <ng-container [ngTemplateOutletContext]=\"{content: buttonTwoContent, click: getButtonClickFunction('2')}\"\n [ngTemplateOutlet]=\"buttonTemplate || defaultButtonTemplate\">\n <ng-template #buttonTwoContent>\n <span>2<br>\n <ng-container *ngIf=\"shift; else twoElse\">ABC</ng-container>\n <ng-template #twoElse>abc</ng-template></span>\n </ng-template>\n </ng-container>\n <ng-container [ngTemplateOutletContext]=\"{content: buttonThreeContent, click: getButtonClickFunction('3')}\"\n [ngTemplateOutlet]=\"buttonTemplate || defaultButtonTemplate\">\n <ng-template #buttonThreeContent>\n <span>3<br>\n <ng-container *ngIf=\"shift; else threeElse\">DEF</ng-container>\n <ng-template #threeElse>def</ng-template></span>\n </ng-template>\n </ng-container>\n </div>\n <div class=\"button-row\">\n <ng-container [ngTemplateOutletContext]=\"{content: buttonFourContent, click: getButtonClickFunction('4')}\"\n [ngTemplateOutlet]=\"buttonTemplate || defaultButtonTemplate\">\n <ng-template #buttonFourContent>\n <span>4<br>\n <ng-container *ngIf=\"shift; else fourElse\">GHI</ng-container>\n <ng-template #fourElse>ghi</ng-template></span>\n </ng-template>\n </ng-container>\n <ng-container [ngTemplateOutletContext]=\"{content: buttonFiveContent, click: getButtonClickFunction('5')}\"\n [ngTemplateOutlet]=\"buttonTemplate || defaultButtonTemplate\">\n <ng-template #buttonFiveContent>\n <span>5<br>\n <ng-container *ngIf=\"shift; else fiveElse\">JKL</ng-container>\n <ng-template #fiveElse>jkl</ng-template></span>\n </ng-template>\n </ng-container>\n <ng-container [ngTemplateOutletContext]=\"{content: buttonSixContent, click: getButtonClickFunction('6')}\"\n [ngTemplateOutlet]=\"buttonTemplate || defaultButtonTemplate\">\n <ng-template #buttonSixContent>\n <span>6<br>\n <ng-container *ngIf=\"shift; else sixElse\">MNO</ng-container>\n <ng-template #sixElse>mno</ng-template></span>\n </ng-template>\n </ng-container>\n </div>\n <div class=\"button-row\">\n <ng-container [ngTemplateOutletContext]=\"{content: buttonSevenContent, click: getButtonClickFunction('7')}\"\n [ngTemplateOutlet]=\"buttonTemplate || defaultButtonTemplate\">\n <ng-template #buttonSevenContent>\n <span>7<br>\n <ng-container *ngIf=\"shift; else sevenElse\">PQRS</ng-container>\n <ng-template #sevenElse>pqrs</ng-template></span>\n </ng-template>\n </ng-container>\n <ng-container [ngTemplateOutletContext]=\"{content: buttonEightContent, click: getButtonClickFunction('8')}\"\n [ngTemplateOutlet]=\"buttonTemplate || defaultButtonTemplate\">\n <ng-template #buttonEightContent>\n <span>8<br>\n <ng-container *ngIf=\"shift; else eightElse\">TUV</ng-container>\n <ng-template #eightElse>tuv</ng-template></span>\n </ng-template>\n </ng-container>\n <ng-container [ngTemplateOutletContext]=\"{content: buttonNineContent, click: getButtonClickFunction('9')}\"\n [ngTemplateOutlet]=\"buttonTemplate || defaultButtonTemplate\">\n <ng-template #buttonNineContent>\n <span>9<br>\n <ng-container *ngIf=\"shift; else nineElse\">WXYZ</ng-container>\n <ng-template #nineElse>wxyz</ng-template></span>\n </ng-template>\n </ng-container>\n </div>\n <div class=\"button-row\">\n <ng-container [ngTemplateOutletContext]=\"{content: buttonTenContent, click: getButtonClickFunction('*')}\"\n [ngTemplateOutlet]=\"buttonTemplate || defaultButtonTemplate\">\n <ng-template #buttonTenContent>\n <ng-container *ngIf=\"backspaceEnabled; else backspaceElse\"\n [ngTemplateOutlet]=\"backspaceTemplate || defaultBackspaceTemplate\">\n </ng-container>\n <ng-template #backspaceElse>\n <span>*</span>\n </ng-template>\n </ng-template>\n </ng-container>\n <ng-container [ngTemplateOutletContext]=\"{content: buttonElevenContent, click: getButtonClickFunction('0')}\"\n [ngTemplateOutlet]=\"buttonTemplate || defaultButtonTemplate\">\n <ng-template #buttonElevenContent>\n <span>0</span>\n </ng-template>\n </ng-container>\n <ng-container [ngTemplateOutletContext]=\"{content: buttonTwelveContent, click: getButtonClickFunction('#')}\"\n [ngTemplateOutlet]=\"buttonTemplate || defaultButtonTemplate\">\n <ng-template #buttonTwelveContent>\n <ng-container *ngIf=\"clearEnabled; else clearElse\"\n [ngTemplateOutlet]=\"clearTemplate || defaultClearTemplate\">\n </ng-container>\n <ng-template #clearElse>\n <span>#</span>\n </ng-template>\n </ng-template>\n </ng-container>\n </div>\n</div>\n", styles: [".button-container{display:flex;flex-direction:column;grid-row-gap:var(--osk-row-gap);row-gap:var(--osk-row-gap)}.button-row{display:flex;flex-direction:row;grid-column-gap:var(--osk-col-gap);column-gap:var(--osk-col-gap)}\n"], directives: [{ type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: KeypadComponent, decorators: [{
type: Component,
args: [{
selector: 'osk-keypad',
templateUrl: './keypad.component.html',
styleUrls: ['./keypad.component.scss'],
}]
}], propDecorators: { buttonTemplate: [{
type: Input
}], backspaceTemplate: [{
type: Input
}], clearTemplate: [{
type: Input
}], language: [{
type: Input
}], timeoutDuration: [{
type: Input
}], value: [{
type: Input
}], backspaceEnabled: [{
type: Input
}], clearEnabled: [{
type: Input
}], shift: [{
type: Input
}], shiftChange: [{
type: Output
}], valueChange: [{
type: Output
}], vanityChange: [{
type: Output,
args: ['vanity']
}], pressedKeysChange: [{
type: Output,
args: ['pressedKeys']
}], inputFocusChange: [{
type: Output,
args: ['inputFocus']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5cGFkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1vbnNjcmVlbi10d2VsdmVrZXlib2FyZC9zcmMvbGliL2tleXBhZC9rZXlwYWQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LW9uc2NyZWVuLXR3ZWx2ZWtleWJvYXJkL3NyYy9saWIva2V5cGFkL2tleXBhZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBR0wsTUFBTSxHQUVQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxvQ0FBb0MsQ0FBQzs7O0FBUWxFLE1BQU0sT0FBTyxlQUFlO0lBTDVCO1FBa0JTLHVCQUFrQixHQUF3QixjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7UUFHaEUsb0JBQWUsR0FBVyxJQUFJLENBQUM7UUFHL0IsVUFBSyxHQUFXLEVBQUUsQ0FBQztRQUduQixxQkFBZ0IsR0FBWSxLQUFLLENBQUM7UUFHbEMsaUJBQVksR0FBWSxLQUFLLENBQUM7UUFHOUIsVUFBSyxHQUFZLEtBQUssQ0FBQztRQUd2QixnQkFBVyxHQUEwQixJQUFJLFlBQVksRUFBVyxDQUFDO1FBR2pFLGdCQUFXLEdBQXlCLElBQUksWUFBWSxFQUFVLENBQUM7UUFHL0QsaUJBQVksR0FBeUIsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUdoRSxzQkFBaUIsR0FBeUIsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUdyRSxxQkFBZ0IsR0FBMEIsSUFBSSxZQUFZLEVBQVcsQ0FBQztRQUVyRSxpQkFBWSxHQUFXLEVBQUUsQ0FBQztRQVUxQix3QkFBbUIsR0FBVyxDQUFDLENBQUMsQ0FBQztRQVVqQyxrQkFBYSxHQUFXLENBQUMsQ0FBQztLQWtJbkM7SUFwSkMsSUFBVyxXQUFXO1FBQ3BC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QUFHLEtBQUssQ0FBQztRQUNuQixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDcEMsQ0FBQzs7NkdBbE1VLGVBQWU7aUdBQWYsZUFBZSxxZUNqQjVCLG9wTEEySEE7NEZEMUdhLGVBQWU7a0JBTDNCLFNBQVM7bUJBQUM7b0JBQ0UsUUFBUSxFQUFLLFlBQVk7b0JBQ3pCLFdBQVcsRUFBRSx5QkFBeUI7b0JBQ3RDLFNBQVMsRUFBSSxDQUFDLHlCQUF5QixDQUFDO2lCQUN6Qzs4QkFHSCxjQUFjO3NCQURwQixLQUFLO2dCQUlDLGlCQUFpQjtzQkFEdkIsS0FBSztnQkFJQyxhQUFhO3NCQURuQixLQUFLO2dCQUlDLFFBQVE7c0JBRGQsS0FBSztnQkFNQyxlQUFlO3NCQURyQixLQUFLO2dCQUlDLEtBQUs7c0JBRFgsS0FBSztnQkFJQyxnQkFBZ0I7c0JBRHRCLEtBQUs7Z0JBSUMsWUFBWTtzQkFEbEIsS0FBSztnQkFJQyxLQUFLO3NCQURYLEtBQUs7Z0JBSUMsV0FBVztzQkFEakIsTUFBTTtnQkFJQSxXQUFXO3NCQURqQixNQUFNO2dCQUlBLFlBQVk7c0JBRGxCLE1BQU07dUJBQUMsUUFBUTtnQkFJVCxpQkFBaUI7c0JBRHZCLE1BQU07dUJBQUMsYUFBYTtnQkFJZCxnQkFBZ0I7c0JBRHRCLE1BQU07dUJBQUMsWUFBWSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgVGVtcGxhdGVSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtrZXlBc3NpZ25tZW50c30gZnJvbSAnLi4va2V5LWFzc2lnbm1lbnRzL2tleS1hc3NpZ25tZW50cyc7XG5pbXBvcnQge0lMYW5ndWFnZUFzc2lnbm1lbnR9IGZyb20gJy4uL2tleS1hc3NpZ25tZW50cy9pLWxhbmd1YWdlLWFzc2lnbm1lbnQnO1xuXG5AQ29tcG9uZW50KHtcbiAgICAgICAgICAgICBzZWxlY3RvcjogICAgJ29zay1rZXlwYWQnLFxuICAgICAgICAgICAgIHRlbXBsYXRlVXJsOiAnLi9rZXlwYWQuY29tcG9uZW50Lmh0bWwnLFxuICAgICAgICAgICAgIHN0eWxlVXJsczogICBbJy4va2V5cGFkLmNvbXBvbmVudC5zY3NzJ10sXG4gICAgICAgICAgIH0pXG5leHBvcnQgY2xhc3MgS2V5cGFkQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICBASW5wdXQoKVxuICBwdWJsaWMgYnV0dG9uVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT4gfCB1bmRlZmluZWQ7XG5cbiAgQElucHV0KClcbiAgcHVibGljIGJhY2tzcGFjZVRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+IHwgdW5kZWZpbmVkO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjbGVhclRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+IHwgdW5kZWZpbmVkO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBsYW5ndWFnZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIHB1YmxpYyBsYW5ndWFnZUFzc2lnbm1lbnQ6IElMYW5ndWFnZUFzc2lnbm1lbnQgPSBrZXlBc3NpZ25tZW50c1snZW5nJ107XG5cbiAgQElucHV0KClcbiAgcHVibGljIHRpbWVvdXREdXJhdGlvbjogbnVtYmVyID0gMjAwMDtcblxuICBASW5wdXQoKVxuICBwdWJsaWMgdmFsdWU6IHN0cmluZyA9ICcnO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBiYWNrc3BhY2VFbmFibGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgQElucHV0KClcbiAgcHVibGljIGNsZWFyRW5hYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBzaGlmdDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIEBPdXRwdXQoKVxuICBwdWJsaWMgc2hpZnRDaGFuZ2U6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcblxuICBAT3V0cHV0KClcbiAgcHVibGljIHZhbHVlQ2hhbmdlOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIEBPdXRwdXQoJ3Zhbml0eScpXG4gIHB1YmxpYyB2YW5pdHlDaGFuZ2U6IEV2ZW50RW1pdHRlcjxzdHJpbmc+ID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cbiAgQE91dHB1dCgncHJlc3NlZEtleXMnKVxuICBwdWJsaWMgcHJlc3NlZEtleXNDaGFuZ2U6IEV2ZW50RW1pdHRlcjxzdHJpbmc+ID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cbiAgQE91dHB1dCgnaW5wdXRGb2N1cycpXG4gIHB1YmxpYyBpbnB1dEZvY3VzQ2hhbmdlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG5cbiAgcHJpdmF0ZSBfcHJlc3NlZEtleXM6IHN0cmluZyA9ICcnO1xuXG4gIHB1YmxpYyBnZXQgcHJlc3NlZEtleXMoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fcHJlc3NlZEtleXM7XG4gIH1cblxuICBwcml2YXRlIHNldCBwcmVzc2VkS2V5cyh2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5fcHJlc3NlZEtleXMgPSB2YWx1ZTtcbiAgfVxuXG4gIHByaXZhdGUgX2tleUFzc2lnbm1lbnRJbmRleDogbnVtYmVyID0gLTE7XG5cbiAgcHVibGljIGdldCBrZXlBc3NpZ25tZW50SW5kZXgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fa2V5QXNzaWdubWVudEluZGV4O1xuICB9XG5cbiAgcHJpdmF0ZSBzZXQga2V5QXNzaWdubWVudEluZGV4KGluZGV4OiBudW1iZXIpIHtcbiAgICB0aGlzLl9rZXlBc3NpZ25tZW50SW5kZXggPSBpbmRleDtcbiAgfVxuXG4gIHByaXZhdGUgX2lucHV0VGltZW91dDogbnVtYmVyID0gMDtcblxuICBwdWJsaWMgZ2V0IGlucHV0VGltZW91dCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9pbnB1dFRpbWVvdXQ7XG4gIH1cblxuICBwcml2YXRlIHNldCBpbnB1dFRpbWVvdXQoaW5wdXRUaW1lb3V0OiBudW1iZXIpIHtcbiAgICB0aGlzLl9pbnB1dFRpbWVvdXQgPSBpbnB1dFRpbWVvdXQ7XG4gIH1cblxuICBwcml2YXRlIF9zZXRCdXR0b246IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBwdWJsaWMgZ2V0IHNldEJ1dHRvbigpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9zZXRCdXR0b247XG4gIH1cblxuICBwcml2YXRlIHNldCBzZXRCdXR0b24oYnV0dG9uOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl9zZXRCdXR0b24gPSBidXR0b247XG4gIH1cblxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKCEodGhpcy5sYW5ndWFnZSAmJiB0aGlzLmxhbmd1YWdlIGluIGtleUFzc2lnbm1lbnRzKSkge1xuICAgICAgY29uc29sZS5lcnJvcihgR2l2ZW4gbGFuZ3VhZ2UgXCIke3RoaXMubGFuZ3VhZ2V9XCIgaXMgbm90IHN1cHBvcnRlZCB5ZXQuYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubGFuZ3VhZ2VBc3NpZ25tZW50ID0ga2V5QXNzaWdubWVudHNbdGhpcy5sYW5ndWFnZV07XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuY2xlYXJUaW1lb3V0KCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0QnV0dG9uQ2xpY2tGdW5jdGlvbihidXR0b246IHN0cmluZyk6IChldmVudDogTW91c2VFdmVudCkgPT4gdm9pZCB7XG4gICAgcmV0dXJuIChldmVudCkgPT4gdGhpcy5vbkJ1dHRvbkNsaWNrKGJ1dHRvbiwgZXZlbnQpO1xuICB9XG5cbiAgcHVibGljIG9uQnV0dG9uQ2xpY2soYnV0dG9uOiBzdHJpbmcsIGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgIGlmICh0aGlzLmJhY2tzcGFjZUVuYWJsZWQgJiYgYnV0dG9uID09PSAnKicpIHtcbiAgICAgIHRoaXMuaGFuZGxlQmFja3NwYWNlKCk7XG4gICAgfSBlbHNlIGlmICh0aGlzLmNsZWFyRW5hYmxlZCAmJiBidXR0b24gPT09ICcjJykge1xuICAgICAgdGhpcy5oYW5kbGVDbGVhcigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYnV0dG9uICE9PSB0aGlzLnNldEJ1dHRvbikge1xuICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlKCk7XG4gICAgICAgIHRoaXMua2V5QXNzaWdubWVudEluZGV4ID0gMDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMua2V5QXNzaWdubWVudEluZGV4ID0gKHRoaXMua2V5QXNzaWdubWVudEluZGV4ICsgMSkgJVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGFuZ3VhZ2VBc3NpZ25tZW50LmtleXNbYnV0dG9uXS5sZW5ndGg7XG4gICAgICB9XG4gICAgICB0aGlzLnNldEJ1dHRvbiA9IGJ1dHRvbjtcbiAgICAgIHRoaXMuc2V0UHJlc3NlZEtleXModGhpcy5wcmVzc2VkS2V5cyArPSBidXR0b24pO1xuICAgIH1cblxuICAgIHRoaXMucmVzZXRUaW1lb3V0KCk7XG4gIH1cblxuICBwdWJsaWMgcmVzZXQoKTogdm9pZCB7XG4gICAgdGhpcy5wcmVzc2VkS2V5cyAgICAgICAgPSAnJztcbiAgICB0aGlzLnZhbHVlICAgICAgICAgICAgICA9ICcnO1xuICAgIHRoaXMua2V5QXNzaWdubWVudEluZGV4ID0gLTE7XG4gICAgdGhpcy5zZXRCdXR0b24gICAgICAgICAgPSB2b2lkIDA7XG4gIH1cblxuICBwdWJsaWMgZW1pdElucHV0Rm9jdXNFdmVudCh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuaW5wdXRGb2N1c0NoYW5nZS5lbWl0KHZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlQmFja3NwYWNlKCk6IHZvaWQge1xuICAgIHRoaXMuc2V0UHJlc3NlZEtleXModGhpcy5wcmVzc2VkS2V5cy5zdWJzdHJpbmcoMCwgdGhpcy5wcmVzc2VkS2V5cy5sZW5ndGggLSAxKSk7XG4gICAgdGhpcy5zZXRWYWx1ZSh0aGlzLnZhbHVlLnN1YnN0cmluZygwLCB0aGlzLnZhbHVlLmxlbmd0aCAtIDEpKTtcbiAgICB0aGlzLnNldEJ1dHRvbiA9IHZvaWQgMDtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlQ2xlYXIoKTogdm9pZCB7XG4gICAgdGhpcy5zZXRQcmVzc2VkS2V5cygnJyk7XG4gICAgdGhpcy5zZXRWYWx1ZSgnJyk7XG4gICAgdGhpcy5zZXRCdXR0b24gPSB2b2lkIDA7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVZhbml0eSgpOiB2b2lkIHtcbiAgICBsZXQgdmFuaXR5ID0gJ14nO1xuICAgIGZvciAoY29uc3QgcHJlc3NlZEtleSBvZiB0aGlzLnByZXNzZWRLZXlzKSB7XG4gICAgICB2YW5pdHkgKz0gYCgke3RoaXMubGFuZ3VhZ2VBc3NpZ25tZW50LmtleXNbcHJlc3NlZEtleV0uam9pbignfCcpfSlgO1xuICAgIH1cbiAgICB0aGlzLnZhbml0eUNoYW5nZS5lbWl0KHZhbml0eSk7XG4gIH1cblxuICBwcml2YXRlIHJlc2V0VGltZW91dCgpOiB2b2lkIHtcbiAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHRoaXMuX2lucHV0VGltZW91dCk7XG4gICAgdGhpcy5faW5wdXRUaW1lb3V0ID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuc2V0QnV0dG9uKSB7XG4gICAgICAgIHRoaXMudXBkYXRlVmFsdWUoKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zZXRCdXR0b24gICAgICAgICAgPSB2b2lkIDA7XG4gICAgICB0aGlzLmlucHV0VGltZW91dCAgICAgICA9IDA7XG4gICAgICB0aGlzLmtleUFzc2lnbm1lbnRJbmRleCA9IC0xO1xuICAgIH0sIHRoaXMudGltZW91dER1cmF0aW9uKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0UHJlc3NlZEtleXMocHJlc3NlZEtleXM6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMucHJlc3NlZEtleXMgPSBwcmVzc2VkS2V5cztcbiAgICB0aGlzLnByZXNzZWRLZXlzQ2hhbmdlLmVtaXQodGhpcy5wcmVzc2VkS2V5cyk7XG4gICAgdGhpcy51cGRhdGVWYW5pdHkoKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0U2hpZnQodmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLnNoaWZ0ID0gdmFsdWU7XG4gICAgdGhpcy5zaGlmdENoYW5nZS5lbWl0KHZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlVmFsdWUoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2V0QnV0dG9uKSB7XG4gICAgICBjb25zdCBuZXdDaGFyYWN0ZXIgPSB0aGlzLmxhbmd1YWdlQXNzaWdubWVudC5rZXlzW3RoaXMuc2V0QnV0dG9uXVt0aGlzLmtleUFzc2lnbm1lbnRJbmRleF07XG4gICAgICB0aGlzLnNldFZhbHVlKHRoaXMudmFsdWUgK1xuICAgICAgICAgICAgICAgICAgICAodGhpcy5zaGlmdCA/IG5ld0NoYXJhY3Rlci50b1VwcGVyQ2FzZSgpIDogbmV3Q2hhcmFjdGVyKSk7XG4gICAgICB0aGlzLnNldFNoaWZ0KGZhbHNlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNsZWFyVGltZW91dCgpOiB2b2lkIHtcbiAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHRoaXMuX2lucHV0VGltZW91dCk7XG4gIH1cblxuICBwcml2YXRlIHNldFZhbHVlKHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgdGhpcy52YWx1ZUNoYW5nZS5lbWl0KHRoaXMudmFsdWUpO1xuICB9XG59XG4iLCI8bmctdGVtcGxhdGUgI2RlZmF1bHRCdXR0b25UZW1wbGF0ZSBsZXQtY2xpY2s9XCJjbGlja1wiIGxldC1jb250ZW50PVwiY29udGVudFwiPlxuICA8YnV0dG9uIChtb3VzZWRvd24pPVwiY2xpY2soJGV2ZW50KVwiPlxuICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwiY29udGVudFwiPjwvbmctY29udGFpbmVyPlxuICA8L2J1dHRvbj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjZGVmYXVsdEJhY2tzcGFjZVRlbXBsYXRlPlxuICA8c3Bhbj48LTwvc3Bhbj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjZGVmYXVsdENsZWFyVGVtcGxhdGU+XG4gIDxzcGFuPng8L3NwYW4+XG48L25nLXRlbXBsYXRlPlxuXG48ZGl2IGNsYXNzPVwiYnV0dG9uLWNvbnRhaW5lclwiPlxuICA8ZGl2IGNsYXNzPVwiYnV0dG9uLXJvd1wiPlxuICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cIntjb250ZW50OiBidXR0b25PbmVDb250ZW50LCBjbGljazogZ2V0QnV0dG9uQ2xpY2tGdW5jdGlvbignMScpfVwiXG4gICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJidXR0b25UZW1wbGF0ZSB8fCBkZWZhdWx0QnV0dG9uVGVtcGxhdGVcIj5cbiAgICAgIDxuZy10ZW1wbGF0ZSAjYnV0dG9uT25lQ29udGVudD5cbiAgICAgICAgPHNwYW4+MTxicj5cbiAgICAgICAgICAgICAgJiN4MDAyZTsmI3gwMDQwOyYjeDAwMjY7PC9zcGFuPlxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7Y29udGVudDogYnV0dG9uVHdvQ29udGVudCwgY2xpY2s6IGdldEJ1dHRvbkNsaWNrRnVuY3Rpb24oJzInKX1cIlxuICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiYnV0dG9uVGVtcGxhdGUgfHwgZGVmYXVsdEJ1dHRvblRlbXBsYXRlXCI+XG4gICAgICA8bmctdGVtcGxhdGUgI2J1dHRvblR3b0NvbnRlbnQ+XG4gICAgICAgIDxzcGFuPjI8YnI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJzaGlmdDsgZWxzZSB0d29FbHNlXCI+QUJDPC9uZy1jb250YWluZXI+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjdHdvRWxzZT5hYmM8L25nLXRlbXBsYXRlPjwvc3Bhbj5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie2NvbnRlbnQ6IGJ1dHRvblRocmVlQ29udGVudCwgY2xpY2s6IGdldEJ1dHRvbkNsaWNrRnVuY3Rpb24oJzMnKX1cIlxuICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiYnV0dG9uVGVtcGxhdGUgfHwgZGVmYXVsdEJ1dHRvblRlbXBsYXRlXCI+XG4gICAgICA8bmctdGVtcGxhdGUgI2J1dHRvblRocmVlQ29udGVudD5cbiAgICAgICAgPHNwYW4+Mzxicj5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInNoaWZ0OyBlbHNlIHRocmVlRWxzZVwiPkRFRjwvbmctY29udGFpbmVyPlxuICAgICAgICA8bmctdGVtcGxhdGUgI3RocmVlRWxzZT5kZWY8L25nLXRlbXBsYXRlPjwvc3Bhbj5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9uZy1jb250YWluZXI+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiYnV0dG9uLXJvd1wiPlxuICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cIntjb250ZW50OiBidXR0b25Gb3VyQ29udGVudCwgY2xpY2s6IGdldEJ1dHRvbkNsaWNrRnVuY3Rpb24oJzQnKX1cIlxuICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiYnV0dG9uVGVtcGxhdGUgfHwgZGVmYXVsdEJ1dHRvblRlbXBsYXRlXCI+XG4gICAgICA8bmctdGVtcGxhdGUgI2J1dHRvbkZvdXJDb250ZW50PlxuICAgICAgICA8c3Bhbj40PGJyPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwic2hpZnQ7IGVsc2UgZm91ckVsc2VcIj5HSEk8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPG5nLXRlbXBsYXRlICNmb3VyRWxzZT5naGk8L25nLXRlbXBsYXRlPjwvc3Bhbj5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie2NvbnRlbnQ6IGJ1dHRvbkZpdmVDb250ZW50LCBjbGljazogZ2V0QnV0dG9uQ2xpY2tGdW5jdGlvbignNScpfVwiXG4gICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJidXR0b25UZW1wbGF0ZSB8fCBkZWZhdWx0QnV0dG9uVGVtcGxhdGVcIj5cbiAgICAgIDxuZy10ZW1wbGF0ZSAjYnV0dG9uRml2ZUNvbnRlbnQ+XG4gICAgICAgIDxzcGFuPjU8YnI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJzaGlmdDsgZWxzZSBmaXZlRWxzZVwiPkpLTDwvbmctY29udGFpbmVyPlxuICAgICAgICA8bmctdGVtcGxhdGUgI2ZpdmVFbHNlPmprbDwvbmctdGVtcGxhdGU+PC9zcGFuPlxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7Y29udGVudDogYnV0dG9uU2l4Q29udGVudCwgY2xpY2s6IGdldEJ1dHRvbkNsaWNrRnVuY3Rpb24oJzYnKX1cIlxuICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiYnV0dG9uVGVtcGxhdGUgfHwgZGVmYXVsdEJ1dHRvblRlbXBsYXRlXCI+XG4gICAgICA8bmctdGVtcGxhdGUgI2J1dHRvblNpeENvbnRlbnQ+XG4gICAgICAgIDxzcGFuPjY8YnI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJzaGlmdDsgZWxzZSBzaXhFbHNlXCI+TU5PPC9uZy1jb250YWluZXI+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjc2l4RWxzZT5tbm88L25nLXRlbXBsYXRlPjwvc3Bhbj5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9uZy1jb250YWluZXI+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiYnV0dG9uLXJvd1wiPlxuICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cIntjb250ZW50OiBidXR0b25TZXZlbkNvbnRlbnQsIGNsaWNrOiBnZXRCdXR0b25DbGlja0Z1bmN0aW9uKCc3Jyl9XCJcbiAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImJ1dHRvblRlbXBsYXRlIHx8IGRlZmF1bHRCdXR0b25UZW1wbGF0ZVwiPlxuICAgICAgPG5nLXRlbXBsYXRlICNidXR0b25TZXZlbkNvbnRlbnQ+XG4gICAgICAgIDxzcGFuPjc8YnI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJzaGlmdDsgZWxzZSBzZXZlbkVsc2VcIj5QUVJTPC9uZy1jb250YWluZXI+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjc2V2ZW5FbHNlPnBxcnM8L25nLXRlbXBsYXRlPjwvc3Bhbj5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie2NvbnRlbnQ6IGJ1dHRvbkVpZ2h0Q29udGVudCwgY2xpY2s6IGdldEJ1dHRvbkNsaWNrRnVuY3Rpb24oJzgnKX1cIlxuICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiYnV0dG9uVGVtcGxhdGUgfHwgZGVmYXVsdEJ1dHRvblRlbXBsYXRlXCI+XG4gICAgICA8bmctdGVtcGxhdGUgI2J1dHRvbkVpZ2h0Q29udGVudD5cbiAgICAgICAgPHNwYW4+ODxicj5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInNoaWZ0OyBlbHNlIGVpZ2h0RWxzZVwiPlRVVjwvbmctY29udGFpbmVyPlxuICAgICAgICA8bmctdGVtcGxhdGUgI2VpZ2h0RWxzZT50dXY8L25nLXRlbXBsYXRlPjwvc3Bhbj5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie2NvbnRlbnQ6IGJ1dHRvbk5pbmVDb250ZW50LCBjbGljazogZ2V0QnV0dG9uQ2xpY2tGdW5jdGlvbignOScpfVwiXG4gICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJidXR0b25UZW1wbGF0ZSB8fCBkZWZhdWx0QnV0dG9uVGVtcGxhdGVcIj5cbiAgICAgIDxuZy10ZW1wbGF0ZSAjYnV0dG9uTmluZUNvbnRlbnQ+XG4gICAgICAgIDxzcGFuPjk8YnI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJzaGlmdDsgZWxzZSBuaW5lRWxzZVwiPldYWVo8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPG5nLXRlbXBsYXRlICNuaW5lRWxzZT53eHl6PC9uZy10ZW1wbGF0ZT48L3NwYW4+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L2Rpdj5cbiAgPGRpdiBjbGFzcz1cImJ1dHRvbi1yb3dcIj5cbiAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7Y29udGVudDogYnV0dG9uVGVuQ29udGVudCwgY2xpY2s6IGdldEJ1dHRvbkNsaWNrRnVuY3Rpb24oJyonKX1cIlxuICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiYnV0dG9uVGVtcGxhdGUgfHwgZGVmYXVsdEJ1dHRvblRlbXBsYXRlXCI+XG4gICAgICA8bmctdGVtcGxhdGUgI2J1dHRvblRlbkNvbnRlbnQ+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJiYWNrc3BhY2VFbmFibGVkOyBlbHNlIGJhY2tzcGFjZUVsc2VcIlxuICAgICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImJhY2tzcGFjZVRlbXBsYXRlIHx8IGRlZmF1bHRCYWNrc3BhY2VUZW1wbGF0ZVwiPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPG5nLXRlbXBsYXRlICNiYWNrc3BhY2VFbHNlPlxuICAgICAgICAgIDxzcGFuPio8L3NwYW4+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cIntjb250ZW50OiBidXR0b25FbGV2ZW5Db250ZW50LCBjbGljazogZ2V0QnV0dG9uQ2xpY2tGdW5jdGlvbignMCcpfVwiXG4gICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJidXR0b25UZW1wbGF0ZSB8fCBkZWZhdWx0QnV0dG9uVGVtcGxhdGVcIj5cbiAgICAgIDxuZy10ZW1wbGF0ZSAjYnV0dG9uRWxldmVuQ29udGVudD5cbiAgICAgICAgPHNwYW4+MDwvc3Bhbj5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie2NvbnRlbnQ6IGJ1dHRvblR3ZWx2ZUNvbnRlbnQsIGNsaWNrOiBnZXRCdXR0b25DbGlja0Z1bmN0aW9uKCcjJyl9XCJcbiAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImJ1dHRvblRlbXBsYXRlIHx8IGRlZmF1bHRCdXR0b25UZW1wbGF0ZVwiPlxuICAgICAgPG5nLXRlbXBsYXRlICNidXR0b25Ud2VsdmVDb250ZW50PlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiY2xlYXJFbmFibGVkOyBlbHNlIGNsZWFyRWxzZVwiXG4gICAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiY2xlYXJUZW1wbGF0ZSB8fCBkZWZhdWx0Q2xlYXJUZW1wbGF0ZVwiPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPG5nLXRlbXBsYXRlICNjbGVhckVsc2U+XG4gICAgICAgICAgPHNwYW4+Izwvc3Bhbj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9uZy1jb250YWluZXI+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=