UNPKG

ngx-input-color

Version:

Angular color input component and color picker (with HSL, HSV, RGB, CMYK, HEX, alpha, eye-dropper, etc)

245 lines 47.7 kB
import { CommonModule } from '@angular/common'; import { Component, ChangeDetectionStrategy, forwardRef, HostListener, ViewChild, Input, Output, EventEmitter, } from '@angular/core'; import { NG_VALUE_ACCESSOR, NG_VALIDATORS, FormsModule, } from '@angular/forms'; import { getOffsetPosition } from '../../utils/get-offset-position'; import { parseBoxShadowToPx, stringifyBoxShadow } from '../../utils/box-shadow'; import { NgxInputColorModule } from '../../ngx-input-color.module'; import * as i0 from "@angular/core"; import * as i1 from "@angular/forms"; import * as i2 from "../../directives/ngx-input-color.directive"; export class NgxBoxShadowComponent { set setTheme(val) { if (!val || val == 'auto') { this.theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; } else { this.theme = val; } } constructor(cd) { this.cd = cd; this.theme = 'light'; /** * The maximum range of the box shadow. * @default 25 */ this.maxRange = 25; this.change = new EventEmitter(); this.isDisabled = false; this.isDragging = false; this.value = { x: 0, y: 0 }; this.x = 0; this.y = 0; this.blur = 0; this.spread = 0; this.color = 'black'; this.line = { x1: 0, y1: 0, x2: 0, y2: 0 }; this.center = { x: 0, y: 0 }; this._onChange = (value) => { }; this._onTouched = () => { }; this._onValidateChange = () => { }; } ngOnInit() { } ngAfterViewInit() { this.updateRects(); } ngOnDestroy() { } registerOnChange(fn) { this._onChange = fn; } registerOnTouched(fn) { this._onTouched = fn; } setDisabledState(disabled) { this.isDisabled = disabled; } registerOnValidatorChange(fn) { this._onValidateChange = fn; } validate(control) { return null; } writeValue(value) { this.resetPosition(); if (value) { const boxShadow = parseBoxShadowToPx(value); console.log(boxShadow); if (boxShadow) { this.value = { x: boxShadow.offsetX, y: boxShadow.offsetY }; this.blur = boxShadow.blurRadius; this.spread = boxShadow.spreadRadius; this.color = boxShadow.color; this.convertValueToPosition(boxShadow.offsetX, boxShadow.offsetY); } } } dragStart(ev) { ev.stopPropagation(); ev.preventDefault(); this.isDragging = true; this.updatePosition(ev); this.updateRects(); } updateRects() { this.padRect = this.pad.nativeElement.getBoundingClientRect(); this.thumbRect = this.thumb.nativeElement.getBoundingClientRect(); } resetPosition() { if (!this.padRect || !this.thumbRect) this.updateRects(); this.center = { x: this.padRect.width / 2, y: this.padRect.height / 2 }; this.x = this.center.x - this.thumbRect.width / 2; this.y = this.center.y - this.thumbRect.height / 2; this.line = { x1: this.center.x, y1: this.center.y, x2: this.center.x, y2: this.center.y }; this.cd.detectChanges(); } onResize() { this.writeValue(this.value); } onDrag(ev) { if (!this.isDragging) return; this.updatePosition(ev); } updatePosition(ev) { if (!this.isDragging) return; if (!this.padRect || !this.thumbRect) this.updateRects(); const position = getOffsetPosition(ev, this.pad.nativeElement); const padRec = this.padRect; const thumbRec = this.thumbRect; const minX = thumbRec.width / 2; const maxX = padRec.width - thumbRec.width / 2; const minY = thumbRec.height / 2; const maxY = padRec.height - thumbRec.height / 2; const clampedX = Math.max(minX, Math.min(position.x, maxX)); const clampedY = Math.max(minY, Math.min(position.y, maxY)); // فقط یکبار از وسط اصلاح کن this.x = clampedX - thumbRec.width / 2; this.y = clampedY - thumbRec.height / 2; this.line = { x1: this.center.x, y1: this.center.y, x2: this.x + thumbRec.width / 2, y2: this.y + thumbRec.height / 2, }; this.setValueByPosition(thumbRec, padRec); } onDragEnd(ev) { this.isDragging = false; } setValueByPosition(thumbRec, padRec) { const padCenterX = (padRec.width - thumbRec.width) / 2; const padCenterY = (padRec.height - thumbRec.height) / 2; // فاصله thumb از مرکز const dx = this.x - padCenterX; const dy = this.y - padCenterY; // مقیاس تبدیل به -50 تا +50 (یا هرچقدر بخوای) const halfRangeX = (padRec.width - thumbRec.width) / 2; const halfRangeY = (padRec.height - thumbRec.height) / 2; let valueX = (dx / halfRangeX) * this.maxRange; // -50 تا +50 let valueY = (dy / halfRangeY) * this.maxRange; // رُند کردن valueX = Math.round(valueX); valueY = Math.round(valueY); // محدود کردن به -50 تا +50 یا هر مقدار دلخواه valueX = Math.min(Math.max(valueX, -this.maxRange), this.maxRange); valueY = Math.min(Math.max(valueY, -this.maxRange), this.maxRange); const newValue = { x: valueX, y: valueY }; if (!this.value || this.value.x !== valueX || this.value.y !== valueY) { this.value = newValue; this.onChangeData(); } } onChangeValue() { this.convertValueToPosition(this.value.x, this.value.y); this.onChangeData(); } convertValueToPosition(offsetX, offsetY) { if (!this.padRect || !this.thumbRect) this.updateRects(); // موقعیت پیشنهادی بر اساس offset let proposedX = this.padRect.width / 2 + offsetX - this.thumbRect.width / 2; let proposedY = this.padRect.height / 2 + offsetY - this.thumbRect.height / 2; // محدود کردن (clamp) تا خارج از pad نره const minX = 0; const maxX = this.padRect.width - this.thumbRect.width; const minY = 0; const maxY = this.padRect.height - this.thumbRect.height; this.x = Math.min(Math.max(proposedX, minX), maxX); this.y = Math.min(Math.max(proposedY, minY), maxY); // رسم خط راهنما از مرکز به thumb this.line = { x1: this.center.x, y1: this.center.y, x2: this.x + this.thumbRect.width / 2, y2: this.y + this.thumbRect.height / 2, }; this.cd.detectChanges(); } onChangeData() { const boxShadow = stringifyBoxShadow({ inset: false, offsetX: this.value.x, offsetY: this.value.y, blurRadius: this.blur, spreadRadius: this.spread, color: this.color, }); this._onChange(boxShadow); this.change.emit(boxShadow); } stopPropagation(ev) { ev.stopPropagation(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NgxBoxShadowComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NgxBoxShadowComponent, isStandalone: true, selector: "ngx-box-shadow", inputs: { setTheme: ["theme", "setTheme"], maxRange: "maxRange" }, outputs: { change: "change" }, host: { listeners: { "window:resize": "onResize($event)", "document:mousemove": "onDrag($event)", "document:touchmove": "onDrag($event)", "document:mouseup": "onDragEnd($event)", "document:touchend": "onDragEnd($event)" } }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgxBoxShadowComponent), multi: true }, { provide: NG_VALIDATORS, multi: true, useExisting: NgxBoxShadowComponent, }, ], viewQueries: [{ propertyName: "pad", first: true, predicate: ["pad"], descendants: true, static: true }, { propertyName: "thumb", first: true, predicate: ["thumb"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"ngx-box-shadow-container\" (click)=\"stopPropagation($event)\">\r\n <div class=\"pad-container\" #pad>\r\n <svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <line\r\n [attr.x1]=\"line.x1\"\r\n [attr.y1]=\"line.y1\"\r\n [attr.x2]=\"line.x2\"\r\n [attr.y2]=\"line.y2\"\r\n stroke=\"blue\"\r\n stroke-width=\"2\" />\r\n </svg>\r\n <div\r\n class=\"thumb\"\r\n #thumb\r\n [style.left.px]=\"x\"\r\n [style.top.px]=\"y\"\r\n (mousedown)=\"dragStart($event)\"\r\n (touchstart)=\"dragStart($event)\"></div>\r\n </div>\r\n\r\n <div class=\"ngx-settings\">\r\n <div class=\"ngx-setting-item\">\r\n <div class=\"ngx-row\">\r\n <span>Offset X</span>\r\n <input type=\"number\" id=\"offsetX\" [(ngModel)]=\"value.x\" (ngModelChange)=\"onChangeValue()\" />\r\n </div>\r\n <input\r\n type=\"range\"\r\n id=\"offsetX\"\r\n [(ngModel)]=\"value.x\"\r\n (ngModelChange)=\"onChangeValue()\"\r\n step=\"1\"\r\n [min]=\"-maxRange\"\r\n [max]=\"maxRange\" />\r\n </div>\r\n <div class=\"ngx-setting-item\">\r\n <div class=\"ngx-row\">\r\n <span>Offset Y</span>\r\n <input type=\"number\" id=\"offsetY\" [(ngModel)]=\"value.y\" (ngModelChange)=\"onChangeValue()\" />\r\n </div>\r\n <input\r\n type=\"range\"\r\n id=\"offsetY\"\r\n [(ngModel)]=\"value.y\"\r\n (ngModelChange)=\"onChangeValue()\"\r\n step=\"1\"\r\n [min]=\"-maxRange\"\r\n [max]=\"maxRange\" />\r\n </div>\r\n <div class=\"ngx-setting-item\">\r\n <div class=\"ngx-row\">\r\n <span>Blur</span>\r\n <input type=\"number\" id=\"blur\" [(ngModel)]=\"blur\" (ngModelChange)=\"onChangeValue()\" />\r\n </div>\r\n <input type=\"range\" id=\"blur\" [(ngModel)]=\"blur\" (ngModelChange)=\"onChangeValue()\" step=\"1\" />\r\n </div>\r\n <div class=\"ngx-setting-item\">\r\n <div class=\"ngx-row\">\r\n <span>Spread</span>\r\n <input type=\"number\" id=\"spread\" [(ngModel)]=\"spread\" (ngModelChange)=\"onChangeValue()\" />\r\n </div>\r\n <input type=\"range\" id=\"spread\" [(ngModel)]=\"spread\" (ngModelChange)=\"onChangeValue()\" step=\"1\" />\r\n </div>\r\n <div class=\"ngx-setting-item\">\r\n <div class=\"ngx-row\">\r\n <span>color</span>\r\n <input\r\n type=\"text\"\r\n readonly\r\n id=\"color\"\r\n [(ngModel)]=\"color\"\r\n ngxInputColor\r\n [simpleMode]=\"true\"\r\n (ngModelChange)=\"onChangeData()\"\r\n autocomplete=\"off\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n</div>\r\n", styles: [".ngx-box-shadow-container{width:180px;max-width:100%;border:1px #bfbfbf solid;border-radius:15px;background-color:#fff;overflow:hidden;box-shadow:0 0 20px #0000004f;direction:ltr;padding:12px}.ngx-box-shadow-container *{box-sizing:border-box}.pad-container{position:relative;width:100px;height:100px;border:1px #545454 solid;box-sizing:border-box;direction:ltr;border-radius:3px}.pad-container:after,.pad-container:before{content:\"\";position:absolute;border:1px rgba(145,145,145,.4117647059) solid}.pad-container:after{width:100%;top:calc(50% - 1px);left:0}.pad-container:before{height:100%;top:0;left:calc(50% - 1px)}.pad-container .thumb{box-shadow:inset 0 0 0 2px #fff;width:15px;height:15px;display:block;border-radius:10px;position:absolute;cursor:pointer;background:#00f}.ngx-settings .ngx-row{display:flex;align-items:flex-end;justify-content:space-between}.ngx-settings input:not([type=range]){width:46px;border:none;border:1px solid rgba(145,145,145,.4117647059);padding:2px 4px;border-radius:5px;background-color:transparent;color:#000;font-size:14px;font-weight:500;text-align:center;direction:ltr}.ngx-settings input:not([type=range]):focus{outline:none;border:1px solid #09218d}.ngx-settings input[type=range]{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { 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: "ngmodule", type: NgxInputColorModule }, { kind: "directive", type: i2.NgxInputColorDirective, selector: "[ngxInputColor]", inputs: ["setInputBackgroundColor", "defaultInspector", "simpleMode", "outputType", "theme", "ngxInputColor"], outputs: ["change"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NgxBoxShadowComponent, decorators: [{ type: Component, args: [{ standalone: true, selector: 'ngx-box-shadow', changeDetection: ChangeDetectionStrategy.OnPush, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgxBoxShadowComponent), multi: true }, { provide: NG_VALIDATORS, multi: true, useExisting: NgxBoxShadowComponent, }, ], imports: [CommonModule, FormsModule, NgxInputColorModule], template: "<div class=\"ngx-box-shadow-container\" (click)=\"stopPropagation($event)\">\r\n <div class=\"pad-container\" #pad>\r\n <svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <line\r\n [attr.x1]=\"line.x1\"\r\n [attr.y1]=\"line.y1\"\r\n [attr.x2]=\"line.x2\"\r\n [attr.y2]=\"line.y2\"\r\n stroke=\"blue\"\r\n stroke-width=\"2\" />\r\n </svg>\r\n <div\r\n class=\"thumb\"\r\n #thumb\r\n [style.left.px]=\"x\"\r\n [style.top.px]=\"y\"\r\n (mousedown)=\"dragStart($event)\"\r\n (touchstart)=\"dragStart($event)\"></div>\r\n </div>\r\n\r\n <div class=\"ngx-settings\">\r\n <div class=\"ngx-setting-item\">\r\n <div class=\"ngx-row\">\r\n <span>Offset X</span>\r\n <input type=\"number\" id=\"offsetX\" [(ngModel)]=\"value.x\" (ngModelChange)=\"onChangeValue()\" />\r\n </div>\r\n <input\r\n type=\"range\"\r\n id=\"offsetX\"\r\n [(ngModel)]=\"value.x\"\r\n (ngModelChange)=\"onChangeValue()\"\r\n step=\"1\"\r\n [min]=\"-maxRange\"\r\n [max]=\"maxRange\" />\r\n </div>\r\n <div class=\"ngx-setting-item\">\r\n <div class=\"ngx-row\">\r\n <span>Offset Y</span>\r\n <input type=\"number\" id=\"offsetY\" [(ngModel)]=\"value.y\" (ngModelChange)=\"onChangeValue()\" />\r\n </div>\r\n <input\r\n type=\"range\"\r\n id=\"offsetY\"\r\n [(ngModel)]=\"value.y\"\r\n (ngModelChange)=\"onChangeValue()\"\r\n step=\"1\"\r\n [min]=\"-maxRange\"\r\n [max]=\"maxRange\" />\r\n </div>\r\n <div class=\"ngx-setting-item\">\r\n <div class=\"ngx-row\">\r\n <span>Blur</span>\r\n <input type=\"number\" id=\"blur\" [(ngModel)]=\"blur\" (ngModelChange)=\"onChangeValue()\" />\r\n </div>\r\n <input type=\"range\" id=\"blur\" [(ngModel)]=\"blur\" (ngModelChange)=\"onChangeValue()\" step=\"1\" />\r\n </div>\r\n <div class=\"ngx-setting-item\">\r\n <div class=\"ngx-row\">\r\n <span>Spread</span>\r\n <input type=\"number\" id=\"spread\" [(ngModel)]=\"spread\" (ngModelChange)=\"onChangeValue()\" />\r\n </div>\r\n <input type=\"range\" id=\"spread\" [(ngModel)]=\"spread\" (ngModelChange)=\"onChangeValue()\" step=\"1\" />\r\n </div>\r\n <div class=\"ngx-setting-item\">\r\n <div class=\"ngx-row\">\r\n <span>color</span>\r\n <input\r\n type=\"text\"\r\n readonly\r\n id=\"color\"\r\n [(ngModel)]=\"color\"\r\n ngxInputColor\r\n [simpleMode]=\"true\"\r\n (ngModelChange)=\"onChangeData()\"\r\n autocomplete=\"off\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n</div>\r\n", styles: [".ngx-box-shadow-container{width:180px;max-width:100%;border:1px #bfbfbf solid;border-radius:15px;background-color:#fff;overflow:hidden;box-shadow:0 0 20px #0000004f;direction:ltr;padding:12px}.ngx-box-shadow-container *{box-sizing:border-box}.pad-container{position:relative;width:100px;height:100px;border:1px #545454 solid;box-sizing:border-box;direction:ltr;border-radius:3px}.pad-container:after,.pad-container:before{content:\"\";position:absolute;border:1px rgba(145,145,145,.4117647059) solid}.pad-container:after{width:100%;top:calc(50% - 1px);left:0}.pad-container:before{height:100%;top:0;left:calc(50% - 1px)}.pad-container .thumb{box-shadow:inset 0 0 0 2px #fff;width:15px;height:15px;display:block;border-radius:10px;position:absolute;cursor:pointer;background:#00f}.ngx-settings .ngx-row{display:flex;align-items:flex-end;justify-content:space-between}.ngx-settings input:not([type=range]){width:46px;border:none;border:1px solid rgba(145,145,145,.4117647059);padding:2px 4px;border-radius:5px;background-color:transparent;color:#000;font-size:14px;font-weight:500;text-align:center;direction:ltr}.ngx-settings input:not([type=range]):focus{outline:none;border:1px solid #09218d}.ngx-settings input[type=range]{width:100%}\n"] }] }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { setTheme: [{ type: Input, args: ['theme'] }], maxRange: [{ type: Input }], change: [{ type: Output }], pad: [{ type: ViewChild, args: ['pad', { static: true }] }], thumb: [{ type: ViewChild, args: ['thumb', { static: true }] }], onResize: [{ type: HostListener, args: ['window:resize', ['$event']] }], onDrag: [{ type: HostListener, args: ['document:mousemove', ['$event']] }, { type: HostListener, args: ['document:touchmove', ['$event']] }], onDragEnd: [{ type: HostListener, args: ['document:mouseup', ['$event']] }, { type: HostListener, args: ['document:touchend', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWJveC1zaGFkb3cuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWlucHV0LWNvbG9yL3NyYy9saWIvbmd4LWJveC1zaGFkb3cvbmd4LWJveC1zaGFkb3cuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWlucHV0LWNvbG9yL3NyYy9saWIvbmd4LWJveC1zaGFkb3cvbmd4LWJveC1zaGFkb3cuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFDTCxTQUFTLEVBQ1QsdUJBQXVCLEVBQ3ZCLFVBQVUsRUFJVixZQUFZLEVBRVosU0FBUyxFQUVULEtBQUssRUFDTCxNQUFNLEVBQ04sWUFBWSxHQUNiLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsYUFBYSxFQUNiLFdBQVcsR0FLWixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBRXBFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2hGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDhCQUE4QixDQUFDOzs7O0FBa0JuRSxNQUFNLE9BQU8scUJBQXFCO0lBRWhDLElBQW9CLFFBQVEsQ0FBQyxHQUE4QjtRQUN6RCxJQUFJLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsOEJBQThCLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO1FBQzVGLENBQUM7YUFBTSxDQUFDO1lB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LENBQUM7O3NCQUM3QyxZQUFZO3VCQUFDLG9CQUFvQixFQUFFLENBQUMsUUFBUSxDQUFDO2dCQXNDOUMsU0FBUztzQkFGUixZQUFZO3VCQUFDLGtCQUFrQixFQUFFLENBQUMsUUFBUSxDQUFDOztzQkFDM0MsWUFBWTt1QkFBQyxtQkFBbUIsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7XHJcbiAgQ29tcG9uZW50LFxyXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxyXG4gIGZvcndhcmRSZWYsXHJcbiAgT25Jbml0LFxyXG4gIE9uRGVzdHJveSxcclxuICBDaGFuZ2VEZXRlY3RvclJlZixcclxuICBIb3N0TGlzdGVuZXIsXHJcbiAgRWxlbWVudFJlZixcclxuICBWaWV3Q2hpbGQsXHJcbiAgQWZ0ZXJWaWV3SW5pdCxcclxuICBJbnB1dCxcclxuICBPdXRwdXQsXHJcbiAgRXZlbnRFbWl0dGVyLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge1xyXG4gIE5HX1ZBTFVFX0FDQ0VTU09SLFxyXG4gIE5HX1ZBTElEQVRPUlMsXHJcbiAgRm9ybXNNb2R1bGUsXHJcbiAgQ29udHJvbFZhbHVlQWNjZXNzb3IsXHJcbiAgVmFsaWRhdG9yLFxyXG4gIEFic3RyYWN0Q29udHJvbCxcclxuICBWYWxpZGF0aW9uRXJyb3JzLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgZ2V0T2Zmc2V0UG9zaXRpb24gfSBmcm9tICcuLi8uLi91dGlscy9nZXQtb2Zmc2V0LXBvc2l0aW9uJztcclxuaW1wb3J0IHsgSVBvc2l0aW9uIH0gZnJvbSAnLi4vLi4vbW9kZWxzL0lQb3NpdGlvbic7XHJcbmltcG9ydCB7IHBhcnNlQm94U2hhZG93VG9QeCwgc3RyaW5naWZ5Qm94U2hhZG93IH0gZnJvbSAnLi4vLi4vdXRpbHMvYm94LXNoYWRvdyc7XHJcbmltcG9ydCB7IE5neElucHV0Q29sb3JNb2R1bGUgfSBmcm9tICcuLi8uLi9uZ3gtaW5wdXQtY29sb3IubW9kdWxlJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbiAgc2VsZWN0b3I6ICduZ3gtYm94LXNoYWRvdycsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL25neC1ib3gtc2hhZG93LmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9uZ3gtYm94LXNoYWRvdy5jb21wb25lbnQuc2NzcyddLFxyXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxyXG4gIHByb3ZpZGVyczogW1xyXG4gICAgeyBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUiwgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gTmd4Qm94U2hhZG93Q29tcG9uZW50KSwgbXVsdGk6IHRydWUgfSxcclxuICAgIHtcclxuICAgICAgcHJvdmlkZTogTkdfVkFMSURBVE9SUyxcclxuICAgICAgbXVsdGk6IHRydWUsXHJcbiAgICAgIHVzZUV4aXN0aW5nOiBOZ3hCb3hTaGFkb3dDb21wb25lbnQsXHJcbiAgICB9LFxyXG4gIF0sXHJcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRm9ybXNNb2R1bGUsIE5neElucHV0Q29sb3JNb2R1bGVdLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTmd4Qm94U2hhZG93Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3ksIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBWYWxpZGF0b3Ige1xyXG4gIHRoZW1lOiAnbGlnaHQnIHwgJ2RhcmsnIHwgJ2F1dG8nID0gJ2xpZ2h0JztcclxuICBASW5wdXQoJ3RoZW1lJykgc2V0IHNldFRoZW1lKHZhbDogJ2xpZ2h0JyB8ICdkYXJrJyB8ICdhdXRvJykge1xyXG4gICAgaWYgKCF2YWwgfHwgdmFsID09ICdhdXRvJykge1xyXG4gICAgICB0aGlzLnRoZW1lID0gd2luZG93Lm1hdGNoTWVkaWEoJyhwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyayknKS5tYXRjaGVzID8gJ2RhcmsnIDogJ2xpZ2h0JztcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMudGhlbWUgPSB2YWw7XHJcbiAgICB9XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIFRoZSBtYXhpbXVtIHJhbmdlIG9mIHRoZSBib3ggc2hhZG93LlxyXG4gICAqIEBkZWZhdWx0IDI1XHJcbiAgICovXHJcbiAgQElucHV0KCkgbWF4UmFuZ2UgPSAyNTtcclxuICBAT3V0cHV0KCkgY2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XHJcbiAgaXNEaXNhYmxlZCA9IGZhbHNlO1xyXG4gIGlzRHJhZ2dpbmcgPSBmYWxzZTtcclxuICB2YWx1ZTogSVBvc2l0aW9uID0geyB4OiAwLCB5OiAwIH07XHJcbiAgeCA9IDA7XHJcbiAgeSA9IDA7XHJcbiAgYmx1ciA9IDA7XHJcbiAgc3ByZWFkID0gMDtcclxuICBjb2xvciA9ICdibGFjayc7XHJcbiAgbGluZTogeyB4MTogbnVtYmVyOyB5MTogbnVtYmVyOyB4MjogbnVtYmVyOyB5MjogbnVtYmVyIH0gPSB7IHgxOiAwLCB5MTogMCwgeDI6IDAsIHkyOiAwIH07XHJcbiAgY2VudGVyOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0gPSB7IHg6IDAsIHk6IDAgfTtcclxuXHJcbiAgcGFkUmVjdD86IERPTVJlY3Q7XHJcbiAgdGh1bWJSZWN0PzogRE9NUmVjdDtcclxuICBfb25DaGFuZ2UgPSAodmFsdWU6IHN0cmluZykgPT4ge307XHJcbiAgX29uVG91Y2hlZCA9ICgpID0+IHt9O1xyXG4gIF9vblZhbGlkYXRlQ2hhbmdlID0gKCkgPT4ge307XHJcblxyXG4gIEBWaWV3Q2hpbGQoJ3BhZCcsIHsgc3RhdGljOiB0cnVlIH0pIHBhZCE6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+O1xyXG4gIEBWaWV3Q2hpbGQoJ3RodW1iJywgeyBzdGF0aWM6IHRydWUgfSkgdGh1bWIhOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PjtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjZDogQ2hhbmdlRGV0ZWN0b3JSZWYpIHt9XHJcblxyXG4gIG5nT25Jbml0KCk6IHZvaWQge31cclxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XHJcbiAgICB0aGlzLnVwZGF0ZVJlY3RzKCk7XHJcbiAgfVxyXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge31cclxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpOiB2b2lkIHtcclxuICAgIHRoaXMuX29uQ2hhbmdlID0gZm47XHJcbiAgfVxyXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiBhbnkpOiB2b2lkIHtcclxuICAgIHRoaXMuX29uVG91Y2hlZCA9IGZuO1xyXG4gIH1cclxuICBzZXREaXNhYmxlZFN0YXRlKGRpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLmlzRGlzYWJsZWQgPSBkaXNhYmxlZDtcclxuICB9XHJcbiAgcmVnaXN0ZXJPblZhbGlkYXRvckNoYW5nZShmbjogKCkgPT4gdm9pZCk6IHZvaWQge1xyXG4gICAgdGhpcy5fb25WYWxpZGF0ZUNoYW5nZSA9IGZuO1xyXG4gIH1cclxuICB2YWxpZGF0ZShjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCB7XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIHdyaXRlVmFsdWUodmFsdWU6IGFueSk6IHZvaWQge1xyXG4gICAgdGhpcy5yZXNldFBvc2l0aW9uKCk7XHJcbiAgICBpZiAodmFsdWUpIHtcclxuICAgICAgY29uc3QgYm94U2hhZG93ID0gcGFyc2VCb3hTaGFkb3dUb1B4KHZhbHVlKTtcclxuICAgICAgY29uc29sZS5sb2coYm94U2hhZG93KTtcclxuICAgICAgaWYgKGJveFNoYWRvdykge1xyXG4gICAgICAgIHRoaXMudmFsdWUgPSB7IHg6IGJveFNoYWRvdy5vZmZzZXRYLCB5OiBib3hTaGFkb3cub2Zmc2V0WSB9O1xyXG4gICAgICAgIHRoaXMuYmx1ciA9IGJveFNoYWRvdy5ibHVyUmFkaXVzO1xyXG4gICAgICAgIHRoaXMuc3ByZWFkID0gYm94U2hhZG93LnNwcmVhZFJhZGl1cztcclxuICAgICAgICB0aGlzLmNvbG9yID0gYm94U2hhZG93LmNvbG9yO1xyXG4gICAgICAgIHRoaXMuY29udmVydFZhbHVlVG9Qb3NpdGlvbihib3hTaGFkb3cub2Zmc2V0WCwgYm94U2hhZG93Lm9mZnNldFkpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBkcmFnU3RhcnQoZXY6IE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50KSB7XHJcbiAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICB0aGlzLmlzRHJhZ2dpbmcgPSB0cnVlO1xyXG4gICAgdGhpcy51cGRhdGVQb3NpdGlvbihldik7XHJcbiAgICB0aGlzLnVwZGF0ZVJlY3RzKCk7XHJcbiAgfVxyXG4gIHByaXZhdGUgdXBkYXRlUmVjdHMoKSB7XHJcbiAgICB0aGlzLnBhZFJlY3QgPSB0aGlzLnBhZC5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgdGhpcy50aHVtYlJlY3QgPSB0aGlzLnRodW1iLm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XHJcbiAgfVxyXG4gIHByaXZhdGUgcmVzZXRQb3NpdGlvbigpIHtcclxuICAgIGlmICghdGhpcy5wYWRSZWN0IHx8ICF0aGlzLnRodW1iUmVjdCkgdGhpcy51cGRhdGVSZWN0cygpO1xyXG4gICAgdGhpcy5jZW50ZXIgPSB7IHg6IHRoaXMucGFkUmVjdCEud2lkdGggLyAyLCB5OiB0aGlzLnBhZFJlY3QhLmhlaWdodCAvIDIgfTtcclxuICAgIHRoaXMueCA9IHRoaXMuY2VudGVyLnggLSB0aGlzLnRodW1iUmVjdCEud2lkdGggLyAyO1xyXG4gICAgdGhpcy55ID0gdGhpcy5jZW50ZXIueSAtIHRoaXMudGh1bWJSZWN0IS5oZWlnaHQgLyAyO1xyXG4gICAgdGhpcy5saW5lID0geyB4MTogdGhpcy5jZW50ZXIueCwgeTE6IHRoaXMuY2VudGVyLnksIHgyOiB0aGlzLmNlbnRlci54LCB5MjogdGhpcy5jZW50ZXIueSB9O1xyXG4gICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6cmVzaXplJywgWyckZXZlbnQnXSlcclxuICBvblJlc2l6ZSgpIHtcclxuICAgIHRoaXMud3JpdGVWYWx1ZSh0aGlzLnZhbHVlKTtcclxuICB9XHJcblxyXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50Om1vdXNlbW92ZScsIFsnJGV2ZW50J10pXHJcbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6dG91Y2htb3ZlJywgWyckZXZlbnQnXSlcclxuICBvbkRyYWcoZXY6IE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50KSB7XHJcbiAgICBpZiAoIXRoaXMuaXNEcmFnZ2luZykgcmV0dXJuO1xyXG4gICAgdGhpcy51cGRhdGVQb3NpdGlvbihldik7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVwZGF0ZVBvc2l0aW9uKGV2OiBNb3VzZUV2ZW50IHwgVG91Y2hFdmVudCkge1xyXG4gICAgaWYgKCF0aGlzLmlzRHJhZ2dpbmcpIHJldHVybjtcclxuICAgIGlmICghdGhpcy5wYWRSZWN0IHx8ICF0aGlzLnRodW1iUmVjdCkgdGhpcy51cGRhdGVSZWN0cygpO1xyXG4gICAgY29uc3QgcG9zaXRpb24gPSBnZXRPZmZzZXRQb3NpdGlvbihldiwgdGhpcy5wYWQubmF0aXZlRWxlbWVudCk7XHJcblxyXG4gICAgY29uc3QgcGFkUmVjID0gdGhpcy5wYWRSZWN0ITtcclxuICAgIGNvbnN0IHRodW1iUmVjID0gdGhpcy50aHVtYlJlY3QhO1xyXG5cclxuICAgIGNvbnN0IG1pblggPSB0aHVtYlJlYy53aWR0aCAvIDI7XHJcbiAgICBjb25zdCBtYXhYID0gcGFkUmVjLndpZHRoIC0gdGh1bWJSZWMud2lkdGggLyAyO1xyXG4gICAgY29uc3QgbWluWSA9IHRodW1iUmVjLmhlaWdodCAvIDI7XHJcbiAgICBjb25zdCBtYXhZID0gcGFkUmVjLmhlaWdodCAtIHRodW1iUmVjLmhlaWdodCAvIDI7XHJcblxyXG4gICAgY29uc3QgY2xhbXBlZFggPSBNYXRoLm1heChtaW5YLCBNYXRoLm1pbihwb3NpdGlvbi54LCBtYXhYKSk7XHJcbiAgICBjb25zdCBjbGFtcGVkWSA9IE1hdGgubWF4KG1pblksIE1hdGgubWluKHBvc2l0aW9uLnksIG1heFkpKTtcclxuXHJcbiAgICAvLyDZgdmC2Lcg24zaqdio2KfYsSDYp9iyINmI2LPYtyDYp9i12YTYp9itINqp2YZcclxuICAgIHRoaXMueCA9IGNsYW1wZWRYIC0gdGh1bWJSZWMud2lkdGggLyAyO1xyXG4gICAgdGhpcy55ID0gY2xhbXBlZFkgLSB0aHVtYlJlYy5oZWlnaHQgLyAyO1xyXG5cclxuICAgIHRoaXMubGluZSA9IHtcclxuICAgICAgeDE6IHRoaXMuY2VudGVyLngsXHJcbiAgICAgIHkxOiB0aGlzLmNlbnRlci55LFxyXG4gICAgICB4MjogdGhpcy54ICsgdGh1bWJSZWMud2lkdGggLyAyLFxyXG4gICAgICB5MjogdGhpcy55ICsgdGh1bWJSZWMuaGVpZ2h0IC8gMixcclxuICAgIH07XHJcblxyXG4gICAgdGhpcy5zZXRWYWx1ZUJ5UG9zaXRpb24odGh1bWJSZWMsIHBhZFJlYyk7XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDptb3VzZXVwJywgWyckZXZlbnQnXSlcclxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDp0b3VjaGVuZCcsIFsnJGV2ZW50J10pXHJcbiAgb25EcmFnRW5kKGV2OiBNb3VzZUV2ZW50IHwgVG91Y2hFdmVudCkge1xyXG4gICAgdGhpcy5pc0RyYWdnaW5nID0gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBzZXRWYWx1ZUJ5UG9zaXRpb24odGh1bWJSZWM6IERPTVJlY3QsIHBhZFJlYzogRE9NUmVjdCkge1xyXG4gICAgY29uc3QgcGFkQ2VudGVyWCA9IChwYWRSZWMud2lkdGggLSB0aHVtYlJlYy53aWR0aCkgLyAyO1xyXG4gICAgY29uc3QgcGFkQ2VudGVyWSA9IChwYWRSZWMuaGVpZ2h0IC0gdGh1bWJSZWMuaGVpZ2h0KSAvIDI7XHJcblxyXG4gICAgLy8g2YHYp9i12YTZhyB0aHVtYiDYp9iyINmF2LHaqdiyXHJcbiAgICBjb25zdCBkeCA9IHRoaXMueCAtIHBhZENlbnRlclg7XHJcbiAgICBjb25zdCBkeSA9IHRoaXMueSAtIHBhZENlbnRlclk7XHJcblxyXG4gICAgLy8g2YXZgtuM2KfYsyDYqtio2K/bjNmEINio2YcgLTUwINiq2KcgKzUwICjbjNinINmH2LHahtmC2K/YsSDYqNiu2YjYp9uMKVxyXG4gICAgY29uc3QgaGFsZlJhbmdlWCA9IChwYWRSZWMud2lkdGggLSB0aHVtYlJlYy53aWR0aCkgLyAyO1xyXG4gICAgY29uc3QgaGFsZlJhbmdlWSA9IChwYWRSZWMuaGVpZ2h0IC0gdGh1bWJSZWMuaGVpZ2h0KSAvIDI7XHJcblxyXG4gICAgbGV0IHZhbHVlWCA9IChkeCAvIGhhbGZSYW5nZVgpICogdGhpcy5tYXhSYW5nZTsgLy8gLTUwINiq2KcgKzUwXHJcbiAgICBsZXQgdmFsdWVZID0gKGR5IC8gaGFsZlJhbmdlWSkgKiB0aGlzLm1heFJhbmdlO1xyXG5cclxuICAgIC8vINix2Y/ZhtivINqp2LHYr9mGXHJcbiAgICB2YWx1ZVggPSBNYXRoLnJvdW5kKHZhbHVlWCk7XHJcbiAgICB2YWx1ZVkgPSBNYXRoLnJvdW5kKHZhbHVlWSk7XHJcblxyXG4gICAgLy8g2YXYrdiv2YjYryDaqdix2K/ZhiDYqNmHIC01MCDYqtinICs1MCDbjNinINmH2LEg2YXZgtiv2KfYsSDYr9mE2K7ZiNin2YdcclxuICAgIHZhbHVlWCA9IE1hdGgubWluKE1hdGgubWF4KHZhbHVlWCwgLXRoaXMubWF4UmFuZ2UpLCB0aGlzLm1heFJhbmdlKTtcclxuICAgIHZhbHVlWSA9IE1hdGgubWluKE1hdGgubWF4KHZhbHVlWSwgLXRoaXMubWF4UmFuZ2UpLCB0aGlzLm1heFJhbmdlKTtcclxuXHJcbiAgICBjb25zdCBuZXdWYWx1ZSA9IHsgeDogdmFsdWVYLCB5OiB2YWx1ZVkgfTtcclxuXHJcbiAgICBpZiAoIXRoaXMudmFsdWUgfHwgdGhpcy52YWx1ZS54ICE9PSB2YWx1ZVggfHwgdGhpcy52YWx1ZS55ICE9PSB2YWx1ZVkpIHtcclxuICAgICAgdGhpcy52YWx1ZSA9IG5ld1ZhbHVlO1xyXG4gICAgICB0aGlzLm9uQ2hhbmdlRGF0YSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHVibGljIG9uQ2hhbmdlVmFsdWUoKSB7XHJcbiAgICB0aGlzLmNvbnZlcnRWYWx1ZVRvUG9zaXRpb24odGhpcy52YWx1ZS54LCB0aGlzLnZhbHVlLnkpO1xyXG4gICAgdGhpcy5vbkNoYW5nZURhdGEoKTtcclxuICB9XHJcbiAgcHJpdmF0ZSBjb252ZXJ0VmFsdWVUb1Bvc2l0aW9uKG9mZnNldFg6IG51bWJlciwgb2Zmc2V0WTogbnVtYmVyKSB7XHJcbiAgICBpZiAoIXRoaXMucGFkUmVjdCB8fCAhdGhpcy50aHVtYlJlY3QpIHRoaXMudXBkYXRlUmVjdHMoKTtcclxuXHJcbiAgICAvLyDZhdmI2YLYuduM2Kog2b7bjNi02YbZh9in2K/bjCDYqNixINin2LPYp9izIG9mZnNldFxyXG4gICAgbGV0IHByb3Bvc2VkWCA9IHRoaXMucGFkUmVjdCEud2lkdGggLyAyICsgb2Zmc2V0WCAtIHRoaXMudGh1bWJSZWN0IS53aWR0aCAvIDI7XHJcbiAgICBsZXQgcHJvcG9zZWRZID0gdGhpcy5wYWRSZWN0IS5oZWlnaHQgLyAyICsgb2Zmc2V0WSAtIHRoaXMudGh1bWJSZWN0IS5oZWlnaHQgLyAyO1xyXG5cclxuICAgIC8vINmF2K3Yr9mI2K8g2qnYsdiv2YYgKGNsYW1wKSDYqtinINiu2KfYsdisINin2LIgcGFkINmG2LHZh1xyXG4gICAgY29uc3QgbWluWCA9IDA7XHJcbiAgICBjb25zdCBtYXhYID0gdGhpcy5wYWRSZWN0IS53aWR0aCAtIHRoaXMudGh1bWJSZWN0IS53aWR0aDtcclxuICAgIGNvbnN0IG1pblkgPSAwO1xyXG4gICAgY29uc3QgbWF4WSA9IHRoaXMucGFkUmVjdCEuaGVpZ2h0IC0gdGhpcy50aHVtYlJlY3QhLmhlaWdodDtcclxuXHJcbiAgICB0aGlzLnggPSBNYXRoLm1pbihNYXRoLm1heChwcm9wb3NlZFgsIG1pblgpLCBtYXhYKTtcclxuICAgIHRoaXMueSA9IE1hdGgubWluKE1hdGgubWF4KHByb3Bvc2VkWSwgbWluWSksIG1heFkpO1xyXG5cclxuICAgIC8vINix2LPZhSDYrti3INix2KfZh9mG2YXYpyDYp9iyINmF2LHaqdiyINio2YcgdGh1bWJcclxuICAgIHRoaXMubGluZSA9IHtcclxuICAgICAgeDE6IHRoaXMuY2VudGVyLngsXHJcbiAgICAgIHkxOiB0aGlzLmNlbnRlci55LFxyXG4gICAgICB4MjogdGhpcy54ICsgdGhpcy50aHVtYlJlY3QhLndpZHRoIC8gMixcclxuICAgICAgeTI6IHRoaXMueSArIHRoaXMudGh1bWJSZWN0IS5oZWlnaHQgLyAyLFxyXG4gICAgfTtcclxuXHJcbiAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcclxuICB9XHJcblxyXG4gIG9uQ2hhbmdlRGF0YSgpIHtcclxuICAgIGNvbnN0IGJveFNoYWRvdyA9IHN0cmluZ2lmeUJveFNoYWRvdyh7XHJcbiAgICAgIGluc2V0OiBmYWxzZSxcclxuICAgICAgb2Zmc2V0WDogdGhpcy52YWx1ZS54LFxyXG4gICAgICBvZmZzZXRZOiB0aGlzLnZhbHVlLnksXHJcbiAgICAgIGJsdXJSYWRpdXM6IHRoaXMuYmx1cixcclxuICAgICAgc3ByZWFkUmFkaXVzOiB0aGlzLnNwcmVhZCxcclxuICAgICAgY29sb3I6IHRoaXMuY29sb3IsXHJcbiAgICB9KTtcclxuICAgIHRoaXMuX29uQ2hhbmdlKGJveFNoYWRvdyk7XHJcbiAgICB0aGlzLmNoYW5nZS5lbWl0KGJveFNoYWRvdyk7XHJcbiAgfVxyXG5cclxuICBzdG9wUHJvcGFnYXRpb24oZXY6IEV2ZW50KSB7XHJcbiAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcclxuICB9XHJcbn1cclxuIiwiPGRpdiBjbGFzcz1cIm5neC1ib3gtc2hhZG93LWNvbnRhaW5lclwiIChjbGljayk9XCJzdG9wUHJvcGFnYXRpb24oJGV2ZW50KVwiPlxyXG4gIDxkaXYgY2xhc3M9XCJwYWQtY29udGFpbmVyXCIgI3BhZD5cclxuICAgIDxzdmcgdmlld0JveD1cIjAgMCAxMDAgMTAwXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiPlxyXG4gICAgICA8bGluZVxyXG4gICAgICAgIFthdHRyLngxXT1cImxpbmUueDFcIlxyXG4gICAgICAgIFthdHRyLnkxXT1cImxpbmUueTFcIlxyXG4gICAgICAgIFthdHRyLngyXT1cImxpbmUueDJcIlxyXG4gICAgICAgIFthdHRyLnkyXT1cImxpbmUueTJcIlxyXG4gICAgICAgIHN0cm9rZT1cImJsdWVcIlxyXG4gICAgICAgIHN0cm9rZS13aWR0aD1cIjJcIiAvPlxyXG4gICAgPC9zdmc+XHJcbiAgICA8ZGl2XHJcbiAgICAgIGNsYXNzPVwidGh1bWJcIlxyXG4gICAgICAjdGh1bWJcclxuICAgICAgW3N0eWxlLmxlZnQucHhdPVwieFwiXHJcbiAgICAgIFtzdHlsZS50b3AucHhdPVwieVwiXHJcbiAgICAgIChtb3VzZWRvd24pPVwiZHJhZ1N0YXJ0KCRldmVudClcIlxyXG4gICAgICAodG91Y2hzdGFydCk9XCJkcmFnU3RhcnQoJGV2ZW50KVwiPjwvZGl2PlxyXG4gIDwvZGl2PlxyXG5cclxuICA8ZGl2IGNsYXNzPVwibmd4LXNldHRpbmdzXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwibmd4LXNldHRpbmctaXRlbVwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwibmd4LXJvd1wiPlxyXG4gICAgICAgIDxzcGFuPk9mZnNldCBYPC9zcGFuPlxyXG4gICAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCIgaWQ9XCJvZmZzZXRYXCIgWyhuZ01vZGVsKV09XCJ2YWx1ZS54XCIgKG5nTW9kZWxDaGFuZ2UpPVwib25DaGFuZ2VWYWx1ZSgpXCIgLz5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxpbnB1dFxyXG4gICAgICAgIHR5cGU9XCJyYW5nZVwiXHJcbiAgICAgICAgaWQ9XCJvZmZzZXRYXCJcclxuICAgICAgICBbKG5nTW9kZWwpXT1cInZhbHVlLnhcIlxyXG4gICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uQ2hhbmdlVmFsdWUoKVwiXHJcbiAgICAgICAgc3RlcD1cIjFcIlxyXG4gICAgICAgIFttaW5dPVwiLW1heFJhbmdlXCJcclxuICAgICAgICBbbWF4XT1cIm1heFJhbmdlXCIgLz5cclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdiBjbGFzcz1cIm5neC1zZXR0aW5nLWl0ZW1cIj5cclxuICAgICAgPGRpdiBjbGFzcz1cIm5neC1yb3dcIj5cclxuICAgICAgICA8c3Bhbj5PZmZzZXQgWTwvc3Bhbj5cclxuICAgICAgICA8aW5wdXQgdHlwZT1cIm51bWJlclwiIGlkPVwib2Zmc2V0WVwiIFsobmdNb2RlbCldPVwidmFsdWUueVwiIChuZ01vZGVsQ2hhbmdlKT1cIm9uQ2hhbmdlVmFsdWUoKVwiIC8+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8aW5wdXRcclxuICAgICAgICB0eXBlPVwicmFuZ2VcIlxyXG4gICAgICAgIGlkPVwib2Zmc2V0WVwiXHJcbiAgICAgICAgWyhuZ01vZGVsKV09XCJ2YWx1ZS55XCJcclxuICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJvbkNoYW5nZVZhbHVlKClcIlxyXG4gICAgICAgIHN0ZXA9XCIxXCJcclxuICAgICAgICBbbWluXT1cIi1tYXhSYW5nZVwiXHJcbiAgICAgICAgW21heF09XCJtYXhSYW5nZVwiIC8+XHJcbiAgICA8L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJuZ3gtc2V0dGluZy1pdGVtXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJuZ3gtcm93XCI+XHJcbiAgICAgICAgPHNwYW4+Qmx1cjwvc3Bhbj5cclxuICAgICAgICA8aW5wdXQgdHlwZT1cIm51bWJlclwiIGlkPVwiYmx1clwiIFsobmdNb2RlbCldPVwiYmx1clwiIChuZ01vZGVsQ2hhbmdlKT1cIm9uQ2hhbmdlVmFsdWUoKVwiIC8+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8aW5wdXQgdHlwZT1cInJhbmdlXCIgaWQ9XCJibHVyXCIgWyhuZ01vZGVsKV09XCJibHVyXCIgKG5nTW9kZWxDaGFuZ2UpPVwib25DaGFuZ2VWYWx1ZSgpXCIgc3RlcD1cIjFcIiAvPlxyXG4gICAgPC9kaXY+XHJcbiAgICA8ZGl2IGNsYXNzPVwibmd4LXNldHRpbmctaXRlbVwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwibmd4LXJvd1wiPlxyXG4gICAgICAgIDxzcGFuPlNwcmVhZDwvc3Bhbj5cclxuICAgICAgICA8aW5wdXQgdHlwZT1cIm51bWJlclwiIGlkPVwic3ByZWFkXCIgWyhuZ01vZGVsKV09XCJzcHJlYWRcIiAobmdNb2RlbENoYW5nZSk9XCJvbkNoYW5nZVZhbHVlKClcIiAvPlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGlucHV0IHR5cGU9XCJyYW5nZVwiIGlkPVwic3ByZWFkXCIgWyhuZ01vZGVsKV09XCJzcHJlYWRcIiAobmdNb2RlbENoYW5nZSk9XCJvbkNoYW5nZVZhbHVlKClcIiBzdGVwPVwiMVwiIC8+XHJcbiAgICA8L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJuZ3gtc2V0dGluZy1pdGVtXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJuZ3gtcm93XCI+XHJcbiAgICAgICAgPHNwYW4+Y29sb3I8L3NwYW4+XHJcbiAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICB0eXBlPVwidGV4dFwiXHJcbiAgICAgICAgICByZWFkb25seVxyXG4gICAgICAgICAgaWQ9XCJjb2xvclwiXHJcbiAgICAgICAgICBbKG5nTW9kZWwpXT1cImNvbG9yXCJcclxuICAgICAgICAgIG5neElucHV0Q29sb3JcclxuICAgICAgICAgIFtzaW1wbGVNb2RlXT1cInRydWVcIlxyXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25DaGFuZ2VEYXRhKClcIlxyXG4gICAgICAgICAgYXV0b2NvbXBsZXRlPVwib2ZmXCIgLz5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuXHJcbjwvZGl2PlxyXG4iXX0=