ng-devui
Version:
DevUI components based on Angular
331 lines • 54.7 kB
JavaScript
import { DOCUMENT } from '@angular/common';
import { ChangeDetectorRef, Component, Directive, ElementRef, HostListener, Inject, Input, Renderer2, ViewChild, ViewContainerRef, } from '@angular/core';
import { ResizeDirective } from 'ng-devui/splitter';
import { backdropFadeInOut, flyInOut } from 'ng-devui/utils';
import { isNumber, parseInt, trim } from 'lodash-es';
import { Subject, fromEvent } from 'rxjs';
import { debounceTime, distinctUntilChanged, filter, map, switchMap, takeUntil, tap } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/cdk/scrolling";
import * as i3 from "ng-devui/splitter";
export class DrawerContentDirective {
constructor(viewContainerRef) {
this.viewContainerRef = viewContainerRef;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerContentDirective, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: DrawerContentDirective, selector: "[dDrawerContentHost]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerContentDirective, decorators: [{
type: Directive,
args: [{
selector: '[dDrawerContentHost]',
}]
}], ctorParameters: () => [{ type: i0.ViewContainerRef }] });
export class DrawerComponent {
constructor(elementRef, renderer, doc, cdr) {
this.elementRef = elementRef;
this.renderer = renderer;
this.doc = doc;
this.cdr = cdr;
this.animateState = 'void';
this.width = '300px';
this.isCover = true;
/**
* @deprecated
*/
this.fullScreen = false;
this.showAnimation = true;
this.clickDoms = [];
this.position = 'right';
this.bodyScrollable = true; // drawer打开body是否可滚动
this.resizable = false;
this.animationDone = new Subject();
this.stopPropagation = ({ originalEvent: event }) => {
event.stopPropagation();
if (event.cancelable) {
event.preventDefault();
}
};
this.moveStream = (resize) => (mouseDown) => resize.dragEvent.pipe(takeUntil(resize.releaseEvent), map(({ pageX, pageY }) => ({
originalX: mouseDown.pageX,
originalY: mouseDown.pageY,
pageX,
pageY,
})));
this.document = this.doc;
}
ngOnInit() {
this.setWidth(this.width);
this._isCover = this.isCover === undefined ? true : this.isCover;
// some browsers(ie11 & edge) fire the animation done event twice
this.animationDoneSub = this.animationDone
.pipe(distinctUntilChanged((x, y) => {
return x.fromState === y.fromState && x.toState === y.toState;
}))
.subscribe((event) => {
this.onAnimationEnd(event);
});
}
setWidth(width) {
if (typeof window === 'undefined') {
return;
}
if (width.indexOf('%') >= 0) {
const widthStr = trim(width, '%');
const widthNum = parseInt(widthStr, 10);
this._width = isNumber(widthNum) ? (widthNum * window.innerWidth) / 100 + 'px' : '0px';
if (!this.windowResizeSub) {
this.windowResizeSub = fromEvent(window, 'resize')
.pipe(debounceTime(100))
.subscribe(() => {
if (!this.isFullScreen) {
this.setWidth(this.width);
}
});
}
}
else {
this._width = width;
}
this._right = parseInt(this._width) > window.innerWidth ? -(parseInt(this._width) - (window.innerWidth - 100)) + 'px' : '0px';
this.oldWidth = this._width;
}
ngOnDestroy() {
if (this.animationDoneSub) {
this.animationDoneSub.unsubscribe();
}
if (this.resizeSub) {
this.resizeSub.unsubscribe();
}
if (this.windowResizeSub) {
this.windowResizeSub.unsubscribe();
}
}
keydownHandler(event) {
event.stopPropagation();
if (this.escKeyCloseable && !this.isHaveDialogOrUpload()) {
this.hide();
}
}
onAnimationEnd(event) {
if (this.animateState === 'void') {
this.onHidden();
}
if (this.animateState === 'in' && this.afterOpened) {
this.afterOpened();
}
}
// Will overwrite by drawer service
onHidden() { }
show() {
if (this.document.documentElement.scrollHeight > this.document.documentElement.clientHeight) {
this.documentOverFlow = true;
this.scrollTop = this.document.documentElement.scrollTop || this.document.body.scrollTop;
this.scrollLeft = this.document.documentElement.scrollLeft || this.document.body.scrollLeft;
this.renderer.addClass(this.document.body, 'devui-body-scrollblock');
this.renderer.setStyle(this.document.body, 'top', `-${this.scrollTop}px`);
this.renderer.setStyle(this.document.body, 'left', `-${this.scrollLeft}px`);
}
if (!this.bodyScrollable && this.documentOverFlow) {
this.renderer.addClass(this.document.body, 'devui-body-overflow-hidden');
}
this.animateState = 'in';
const activeElement = this.document.activeElement;
if (activeElement && typeof activeElement.blur === 'function') {
activeElement.blur();
}
setTimeout(() => {
this.handleResizeWidth();
}, 0);
this.isCover = this.isCover === undefined ? true : this.isCover;
if (!this.backdropCloseable || this.isCover) {
return;
}
const documentClick = fromEvent(document, 'click');
setTimeout(() => {
this.subscription = documentClick.subscribe((event) => {
if (this.clickDoms && this.clickDoms.length > 0) {
this.clickDoms.forEach((dom) => {
if (dom !== null && dom.contains(event.target)) {
this.hide();
return;
}
});
}
else {
const target = event.target;
// 一定要document.contains(event.target),因为event.target可能已经不在document里了,这个时候就不能进hide了
if (this.animateState === 'in' &&
!this.elementRef.nativeElement.contains(target) &&
this.document.body.contains(target) &&
!this.isHaveDialogOrUpload()) {
this.hide();
}
}
});
});
}
hide() {
this.canHideModel().then((canHide) => {
if (!canHide) {
return;
}
this.hideOperation();
});
}
hideDirectly() {
this.hideOperation();
}
hideOperation() {
if (this.documentOverFlow) {
this.renderer.removeStyle(this.document.body, 'top');
this.renderer.removeStyle(this.document.body, 'left');
this.renderer.removeClass(this.document.body, 'devui-body-scrollblock');
this.renderer.removeClass(this.document.body, 'devui-body-overflow-hidden');
this.document.documentElement.scrollTop = this.scrollTop;
this.document.body.scrollTop = this.scrollTop;
this.document.documentElement.scrollLeft = this.scrollLeft;
this.document.body.scrollLeft = this.scrollLeft;
}
this.animateState = 'void';
if (this.subscription) {
this.subscription.unsubscribe();
this.subscription = undefined;
}
}
// Will overwrite by drawer service
destroy() { }
isHaveDialogOrUpload() {
const dialog = this.document.getElementsByClassName('modal-dialog');
const upload = this.document.getElementById('d-upload-temp');
return (dialog && dialog.length > 0) || upload;
}
canHideModel() {
let hiddenResult = Promise.resolve(true);
if (this.beforeHidden) {
const result = this.beforeHidden();
if (typeof result !== 'undefined') {
if (result.then) {
hiddenResult = result;
}
else if (result.subscribe) {
hiddenResult = result.toPromise();
}
else {
hiddenResult = Promise.resolve(result);
}
}
}
return hiddenResult;
}
_setFullScreen(fullScreen) {
if (typeof window === 'undefined') {
return;
}
const drawerContainerEle = this.drawerContainer.nativeElement;
if (this._width === this.oldWidth) {
if (fullScreen === true || fullScreen === undefined) {
this.isFullScreen = true;
this._width = this._isCover ? '100%' : window.innerWidth + 'px';
this.renderer.setStyle(drawerContainerEle, 'transition', this.showAnimation ? `width .3s cubic-bezier(0.5, 0.05, 0.5, 0.95)` : 'none');
if (!this._isCover) {
const resizeEv = fromEvent(window, 'resize');
const result = resizeEv.pipe(debounceTime(100));
this.resizeSub = result.subscribe((ev) => {
this._width = window.innerWidth + 'px';
});
}
}
}
else {
if (!fullScreen) {
this.isFullScreen = false;
this._width = this.oldWidth;
if (this.resizeSub) {
this.resizeSub.unsubscribe();
}
}
}
}
toggleFullScreen() {
this._setFullScreen();
}
setFullScreen(fullScreen) {
this._setFullScreen(fullScreen);
}
handleResizeWidth() {
if (this.resizable) {
this.resizeCmp.pressEvent
.pipe(tap(this.stopPropagation), filter(() => {
this._curWidth = this._width;
return this.resizable;
}), switchMap(this.moveStream(this.resizeCmp)))
.subscribe(({ pageX, originalX }) => {
this.showAnimation = false;
let tmpWidth;
if (this.position === 'left') {
tmpWidth = parseInt(this._curWidth, 10) + pageX - originalX + 'px';
}
else {
tmpWidth = parseInt(this._curWidth, 10) + originalX - pageX + 'px';
}
this.setWidth(tmpWidth);
this.cdr.detectChanges();
});
this.resizeCmp.releaseEvent.subscribe(() => {
this.showAnimation = true;
});
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: DOCUMENT }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DrawerComponent, selector: "d-drawer", inputs: { id: "id", width: "width", zIndex: "zIndex", isCover: "isCover", fullScreen: "fullScreen", showAnimation: "showAnimation", backdropCloseable: "backdropCloseable", escKeyCloseable: "escKeyCloseable", beforeHidden: "beforeHidden", clickDoms: "clickDoms", afterOpened: "afterOpened", position: "position", bodyScrollable: "bodyScrollable", resizable: "resizable" }, host: { listeners: { "document:keydown.escape": "keydownHandler($event)" } }, viewQueries: [{ propertyName: "drawerContentHost", first: true, predicate: DrawerContentDirective, descendants: true, static: true }, { propertyName: "drawerContainer", first: true, predicate: ["drawerContainer"], descendants: true, static: true }, { propertyName: "resizeCmp", first: true, predicate: ["resizeBar"], descendants: true, read: ResizeDirective }], ngImport: i0, template: "<div\n class=\"drawer\"\n [attr.id]=\"id\"\n [ngStyle]=\"{ 'z-index': zIndex }\"\n [ngClass]=\"{ 'display-width': _isCover && animateState === 'in' }\"\n [style.left]=\"position === 'left' ? 0 : null\"\n [style.right]=\"position === 'right' ? 0 : null\"\n>\n <div\n class=\"overlay-wrapper\"\n [ngClass]=\"{ 'display-width': _isCover && animateState === 'in' }\"\n [style.left]=\"position === 'left' ? 0 : null\"\n [style.right]=\"position === 'right' ? 0 : null\"\n >\n <div\n class=\"overlay-backdrop\"\n [ngClass]=\"{ 'display-width': _isCover && animateState === 'in' }\"\n [@backdropAnimation]=\"animateState\"\n [@.disabled]=\"!showAnimation\"\n (click)=\"backdropCloseable && hide()\"\n ></div>\n <div\n #drawerContainer\n class=\"drawer-nav\"\n [ngStyle]=\"{ width: _width }\"\n [@flyInOut]=\"position + '-' + animateState\"\n (@flyInOut.done)=\"animationDone.next($event)\"\n [@.disabled]=\"!showAnimation\"\n [style.left]=\"position === 'left' ? 0 : null\"\n [style.right]=\"position === 'right' ? _right : null\"\n >\n <div class=\"drawer-content\" cdkScrollable>\n <ng-template dDrawerContentHost></ng-template>\n </div>\n <div *ngIf=\"contentTemplate\" class=\"drawer-content\" cdkScrollable>\n <ng-template [ngTemplateOutlet]=\"contentTemplate\"></ng-template>\n </div>\n <div\n #resizeBar\n dResize\n class=\"devui-drawer-resize-bar\"\n [ngClass]=\"{\n 'devui-drawer-can-hover': resizable,\n 'devui-drawer-resize-bar-left': position === 'left',\n 'devui-drawer-resize-bar-right': position === 'right'\n }\"\n ></div>\n </div>\n </div>\n</div>\n", styles: [".drawer{position:fixed;top:0;bottom:0;z-index:var(--devui-z-index-drawer, 1040)}.overlay-wrapper{display:flex;justify-content:center;align-items:center;position:absolute;top:0;bottom:0}.display-width{left:0;right:0}.overlay-backdrop{position:absolute;top:0;bottom:0!important;background:var(--devui-feedback-overlay-backdrop, rgba(0, 0, 0, .3))}.drawer-nav,.drawer-content{position:absolute;top:0;bottom:0;border-radius:var(--devui-border-radius, 2px)}.drawer-nav{background:var(--devui-base-bg, #ffffff)}.drawer-content{left:0;right:0;box-shadow:var(--devui-shadow-length-fullscreen-overlay, 0 16px 48px 0) var(--devui-shadow, rgba(0, 0, 0, .16));overflow:auto}.drawer-content::-webkit-scrollbar-thumb{background-color:transparent}.drawer-content:hover::-webkit-scrollbar-thumb{background-color:var(--devui-line, #dbdbdb)}.drawer-content:hover::-webkit-scrollbar-thumb:hover{background-color:var(--devui-placeholder, #808080)}.devui-drawer-resize-bar{position:absolute;top:0;height:100%;width:4px;z-index:10;border-left:1px solid var(--devui-dividing-line, #f0f0f0)}.devui-drawer-resize-bar.devui-drawer-resize-bar-left{right:-1px}.devui-drawer-resize-bar.devui-drawer-resize-bar-right{left:-1px}.devui-drawer-resize-bar.devui-drawer-can-hover:hover{border-left-color:var(--devui-brand-hover, #3979f9);border-left-width:2px;cursor:col-resize}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "directive", type: i3.ResizeDirective, selector: "[dResize]", inputs: ["enableResize"], outputs: ["pressEvent", "dragEvent", "releaseEvent"] }, { kind: "directive", type: DrawerContentDirective, selector: "[dDrawerContentHost]" }], animations: [backdropFadeInOut, flyInOut] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerComponent, decorators: [{
type: Component,
args: [{ selector: 'd-drawer', animations: [backdropFadeInOut, flyInOut], preserveWhitespaces: false, template: "<div\n class=\"drawer\"\n [attr.id]=\"id\"\n [ngStyle]=\"{ 'z-index': zIndex }\"\n [ngClass]=\"{ 'display-width': _isCover && animateState === 'in' }\"\n [style.left]=\"position === 'left' ? 0 : null\"\n [style.right]=\"position === 'right' ? 0 : null\"\n>\n <div\n class=\"overlay-wrapper\"\n [ngClass]=\"{ 'display-width': _isCover && animateState === 'in' }\"\n [style.left]=\"position === 'left' ? 0 : null\"\n [style.right]=\"position === 'right' ? 0 : null\"\n >\n <div\n class=\"overlay-backdrop\"\n [ngClass]=\"{ 'display-width': _isCover && animateState === 'in' }\"\n [@backdropAnimation]=\"animateState\"\n [@.disabled]=\"!showAnimation\"\n (click)=\"backdropCloseable && hide()\"\n ></div>\n <div\n #drawerContainer\n class=\"drawer-nav\"\n [ngStyle]=\"{ width: _width }\"\n [@flyInOut]=\"position + '-' + animateState\"\n (@flyInOut.done)=\"animationDone.next($event)\"\n [@.disabled]=\"!showAnimation\"\n [style.left]=\"position === 'left' ? 0 : null\"\n [style.right]=\"position === 'right' ? _right : null\"\n >\n <div class=\"drawer-content\" cdkScrollable>\n <ng-template dDrawerContentHost></ng-template>\n </div>\n <div *ngIf=\"contentTemplate\" class=\"drawer-content\" cdkScrollable>\n <ng-template [ngTemplateOutlet]=\"contentTemplate\"></ng-template>\n </div>\n <div\n #resizeBar\n dResize\n class=\"devui-drawer-resize-bar\"\n [ngClass]=\"{\n 'devui-drawer-can-hover': resizable,\n 'devui-drawer-resize-bar-left': position === 'left',\n 'devui-drawer-resize-bar-right': position === 'right'\n }\"\n ></div>\n </div>\n </div>\n</div>\n", styles: [".drawer{position:fixed;top:0;bottom:0;z-index:var(--devui-z-index-drawer, 1040)}.overlay-wrapper{display:flex;justify-content:center;align-items:center;position:absolute;top:0;bottom:0}.display-width{left:0;right:0}.overlay-backdrop{position:absolute;top:0;bottom:0!important;background:var(--devui-feedback-overlay-backdrop, rgba(0, 0, 0, .3))}.drawer-nav,.drawer-content{position:absolute;top:0;bottom:0;border-radius:var(--devui-border-radius, 2px)}.drawer-nav{background:var(--devui-base-bg, #ffffff)}.drawer-content{left:0;right:0;box-shadow:var(--devui-shadow-length-fullscreen-overlay, 0 16px 48px 0) var(--devui-shadow, rgba(0, 0, 0, .16));overflow:auto}.drawer-content::-webkit-scrollbar-thumb{background-color:transparent}.drawer-content:hover::-webkit-scrollbar-thumb{background-color:var(--devui-line, #dbdbdb)}.drawer-content:hover::-webkit-scrollbar-thumb:hover{background-color:var(--devui-placeholder, #808080)}.devui-drawer-resize-bar{position:absolute;top:0;height:100%;width:4px;z-index:10;border-left:1px solid var(--devui-dividing-line, #f0f0f0)}.devui-drawer-resize-bar.devui-drawer-resize-bar-left{right:-1px}.devui-drawer-resize-bar.devui-drawer-resize-bar-right{left:-1px}.devui-drawer-resize-bar.devui-drawer-can-hover:hover{border-left-color:var(--devui-brand-hover, #3979f9);border-left-width:2px;cursor:col-resize}\n"] }]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }, { type: i0.ChangeDetectorRef }], propDecorators: { id: [{
type: Input
}], width: [{
type: Input
}], zIndex: [{
type: Input
}], isCover: [{
type: Input
}], fullScreen: [{
type: Input
}], showAnimation: [{
type: Input
}], drawerContentHost: [{
type: ViewChild,
args: [DrawerContentDirective, { static: true }]
}], backdropCloseable: [{
type: Input
}], escKeyCloseable: [{
type: Input
}], beforeHidden: [{
type: Input
}], clickDoms: [{
type: Input
}], afterOpened: [{
type: Input
}], position: [{
type: Input
}], bodyScrollable: [{
type: Input
}], resizable: [{
type: Input
}], drawerContainer: [{
type: ViewChild,
args: ['drawerContainer', { static: true }]
}], resizeCmp: [{
type: ViewChild,
args: ['resizeBar', { read: ResizeDirective }]
}], keydownHandler: [{
type: HostListener,
args: ['document:keydown.escape', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJhd2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2RldnVpL2RyYXdlci9kcmF3ZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vZGV2dWkvZHJhd2VyL2RyYXdlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFHTCxTQUFTLEVBRVQsU0FBUyxFQUNULGdCQUFnQixHQUNqQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDcEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLFFBQVEsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdELE9BQU8sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNyRCxPQUFPLEVBQWMsT0FBTyxFQUFnQixTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDcEUsT0FBTyxFQUFFLFlBQVksRUFBRSxvQkFBb0IsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7O0FBSzVHLE1BQU0sT0FBTyxzQkFBc0I7SUFDakMsWUFBbUIsZ0JBQWtDO1FBQWxDLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBa0I7SUFBRyxDQUFDOytHQUQ5QyxzQkFBc0I7bUdBQXRCLHNCQUFzQjs7NEZBQXRCLHNCQUFzQjtrQkFIbEMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsc0JBQXNCO2lCQUNqQzs7QUFZRCxNQUFNLE9BQU8sZUFBZTtJQTJDMUIsWUFDVSxVQUFzQixFQUN0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RyxTQUFTO3NCQUFqQixLQUFLO2dCQUMwQyxlQUFlO3NCQUE5RCxTQUFTO3VCQUFDLGlCQUFpQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFDSyxTQUFTO3NCQUEzRCxTQUFTO3VCQUFDLFdBQVcsRUFBRSxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUU7Z0JBa0ZJLGNBQWM7c0JBQWxFLFlBQVk7dUJBQUMseUJBQXlCLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBbmltYXRpb25FdmVudCB9IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xyXG5pbXBvcnQgeyBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7XHJcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgQ29tcG9uZW50LFxyXG4gIERpcmVjdGl2ZSxcclxuICBFbGVtZW50UmVmLFxyXG4gIEhvc3RMaXN0ZW5lcixcclxuICBJbmplY3QsXHJcbiAgSW5wdXQsXHJcbiAgT25EZXN0cm95LFxyXG4gIE9uSW5pdCxcclxuICBSZW5kZXJlcjIsXHJcbiAgVGVtcGxhdGVSZWYsXHJcbiAgVmlld0NoaWxkLFxyXG4gIFZpZXdDb250YWluZXJSZWYsXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFJlc2l6ZURpcmVjdGl2ZSB9IGZyb20gJ25nLWRldnVpL3NwbGl0dGVyJztcclxuaW1wb3J0IHsgYmFja2Ryb3BGYWRlSW5PdXQsIGZseUluT3V0IH0gZnJvbSAnbmctZGV2dWkvdXRpbHMnO1xyXG5pbXBvcnQgeyBpc051bWJlciwgcGFyc2VJbnQsIHRyaW0gfSBmcm9tICdsb2Rhc2gtZXMnO1xyXG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0LCBTdWJzY3JpcHRpb24sIGZyb21FdmVudCB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUsIGRpc3RpbmN0VW50aWxDaGFuZ2VkLCBmaWx0ZXIsIG1hcCwgc3dpdGNoTWFwLCB0YWtlVW50aWwsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuXHJcbkBEaXJlY3RpdmUoe1xyXG4gIHNlbGVjdG9yOiAnW2REcmF3ZXJDb250ZW50SG9zdF0nLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgRHJhd2VyQ29udGVudERpcmVjdGl2ZSB7XHJcbiAgY29uc3RydWN0b3IocHVibGljIHZpZXdDb250YWluZXJSZWY6IFZpZXdDb250YWluZXJSZWYpIHt9XHJcbn1cclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnZC1kcmF3ZXInLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9kcmF3ZXIuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2RyYXdlci5jb21wb25lbnQuc2NzcyddLFxyXG4gIGFuaW1hdGlvbnM6IFtiYWNrZHJvcEZhZGVJbk91dCwgZmx5SW5PdXRdLFxyXG4gIHByZXNlcnZlV2hpdGVzcGFjZXM6IGZhbHNlLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgRHJhd2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xyXG4gIGFuaW1hdGVTdGF0ZSA9ICd2b2lkJztcclxuICBASW5wdXQoKSBpZDogc3RyaW5nO1xyXG4gIEBJbnB1dCgpIHdpZHRoID0gJzMwMHB4JztcclxuICBASW5wdXQoKSB6SW5kZXg6IG51bWJlcjtcclxuICBASW5wdXQoKSBpc0NvdmVyID0gdHJ1ZTtcclxuICAvKipcclxuICAgKiBAZGVwcmVjYXRlZFxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIGZ1bGxTY3JlZW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBzaG93QW5pbWF0aW9uID0gdHJ1ZTtcclxuICBAVmlld0NoaWxkKERyYXdlckNvbnRlbnREaXJlY3RpdmUsIHsgc3RhdGljOiB0cnVlIH0pIGRyYXdlckNvbnRlbnRIb3N0OiBEcmF3ZXJDb250ZW50RGlyZWN0aXZlO1xyXG4gIEBJbnB1dCgpIGJhY2tkcm9wQ2xvc2VhYmxlOiBib29sZWFuO1xyXG4gIEBJbnB1dCgpIGVzY0tleUNsb3NlYWJsZTogYm9vbGVhbjtcclxuICBASW5wdXQoKSBiZWZvcmVIaWRkZW46ICgpID0+IGJvb2xlYW4gfCBQcm9taXNlPGJvb2xlYW4+IHwgT2JzZXJ2YWJsZTxib29sZWFuPjtcclxuICBASW5wdXQoKSBjbGlja0RvbXM6IGFueSA9IFtdO1xyXG4gIC8vIFdpbGwgb3ZlcndyaXRlIGJ5IGRyYXdlciBzZXJ2aWNlXHJcbiAgQElucHV0KCkgYWZ0ZXJPcGVuZWQ6IEZ1bmN0aW9uO1xyXG4gIEBJbnB1dCgpIHBvc2l0aW9uOiAncmlnaHQnIHwgJ2xlZnQnID0gJ3JpZ2h0JztcclxuICBASW5wdXQoKSBib2R5U2Nyb2xsYWJsZSA9IHRydWU7IC8vIGRyYXdlcuaJk+W8gGJvZHnmmK/lkKblj6/mu5rliqhcclxuICBASW5wdXQoKSByZXNpemFibGUgPSBmYWxzZTtcclxuICBAVmlld0NoaWxkKCdkcmF3ZXJDb250YWluZXInLCB7IHN0YXRpYzogdHJ1ZSB9KSBkcmF3ZXJDb250YWluZXI6IEVsZW1lbnRSZWY7XHJcbiAgQFZpZXdDaGlsZCgncmVzaXplQmFyJywgeyByZWFkOiBSZXNpemVEaXJlY3RpdmUgfSkgcmVzaXplQ21wOiBSZXNpemVEaXJlY3RpdmU7XHJcbiAgX3dpZHRoOiBzdHJpbmc7XHJcbiAgLy8g5YWo5bGP5pe255So5p2l6K6w5b2V5LmL5YmN55qE5a695bqm77yM5Zug5Li65rKh6YGu572p55qE5oOF5Ya15LiLd2lkdGjkuI3og73mmK/nmb7liIbmr5RcclxuICBvbGRXaWR0aDogc3RyaW5nO1xyXG4gIF9pc0NvdmVyOiBib29sZWFuO1xyXG4gIHN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xyXG4gIGlzRnVsbFNjcmVlbjogYm9vbGVhbjtcclxuXHJcbiAgYW5pbWF0aW9uRG9uZSA9IG5ldyBTdWJqZWN0PEFuaW1hdGlvbkV2ZW50PigpO1xyXG4gIGFuaW1hdGlvbkRvbmVTdWI6IFN1YnNjcmlwdGlvbjtcclxuICByZXNpemVTdWI6IFN1YnNjcmlwdGlvbjtcclxuICB3aW5kb3dSZXNpemVTdWI6IFN1YnNjcmlwdGlvbjtcclxuICBkb2N1bWVudE92ZXJGbG93OiBib29sZWFuO1xyXG4gIHNjcm9sbFRvcDogbnVtYmVyO1xyXG4gIHNjcm9sbExlZnQ6IG51bWJlcjtcclxuICBkb2N1bWVudDogRG9jdW1lbnQ7XHJcblxyXG4gIGNvbnRlbnRUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcclxuICBfcmlnaHQ6IHN0cmluZztcclxuICBfY3VyV2lkdGg7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBlbGVtZW50UmVmOiBFbGVtZW50UmVmLFxyXG4gICAgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLFxyXG4gICAgQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2M6IGFueSxcclxuICAgIHByaXZhdGUgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZlxyXG4gICkge1xyXG4gICAgdGhpcy5kb2N1bWVudCA9IHRoaXMuZG9jO1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICB0aGlzLnNldFdpZHRoKHRoaXMud2lkdGgpO1xyXG4gICAgdGhpcy5faXNDb3ZlciA9IHRoaXMuaXNDb3ZlciA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IHRoaXMuaXNDb3ZlcjtcclxuXHJcbiAgICAvLyBzb21lIGJyb3dzZXJzKGllMTEgJiBlZGdlKSBmaXJlIHRoZSBhbmltYXRpb24gZG9uZSBldmVudCB0d2ljZVxyXG4gICAgdGhpcy5hbmltYXRpb25Eb25lU3ViID0gdGhpcy5hbmltYXRpb25Eb25lXHJcbiAgICAgIC5waXBlKFxyXG4gICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCh4LCB5KSA9PiB7XHJcbiAgICAgICAgICByZXR1cm4geC5mcm9tU3RhdGUgPT09IHkuZnJvbVN0YXRlICYmIHgudG9TdGF0ZSA9PT0geS50b1N0YXRlO1xyXG4gICAgICAgIH0pXHJcbiAgICAgIClcclxuICAgICAgLnN1YnNjcmliZSgoZXZlbnQpID0+IHtcclxuICAgICAgICB0aGlzLm9uQW5pbWF0aW9uRW5kKGV2ZW50KTtcclxuICAgICAgfSk7XHJcbiAgfVxyXG4gIHNldFdpZHRoKHdpZHRoOiBzdHJpbmcpIHtcclxuICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBpZiAod2lkdGguaW5kZXhPZignJScpID49IDApIHtcclxuICAgICAgY29uc3Qgd2lkdGhTdHIgPSB0cmltKHdpZHRoLCAnJScpO1xyXG4gICAgICBjb25zdCB3aWR0aE51bSA9IHBhcnNlSW50KHdpZHRoU3RyLCAxMCk7XHJcbiAgICAgIHRoaXMuX3dpZHRoID0gaXNOdW1iZXIod2lkdGhOdW0pID8gKHdpZHRoTnVtICogd2luZG93LmlubmVyV2lkdGgpIC8gMTAwICsgJ3B4JyA6ICcwcHgnO1xyXG4gICAgICBpZiAoIXRoaXMud2luZG93UmVzaXplU3ViKSB7XHJcbiAgICAgICAgdGhpcy53aW5kb3dSZXNpemVTdWIgPSBmcm9tRXZlbnQod2luZG93LCAncmVzaXplJylcclxuICAgICAgICAgIC5waXBlKGRlYm91bmNlVGltZSgxMDApKVxyXG4gICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5pc0Z1bGxTY3JlZW4pIHtcclxuICAgICAgICAgICAgICB0aGlzLnNldFdpZHRoKHRoaXMud2lkdGgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5fd2lkdGggPSB3aWR0aDtcclxuICAgIH1cclxuICAgIHRoaXMuX3JpZ2h0ID0gcGFyc2VJbnQodGhpcy5fd2lkdGgpID4gd2luZG93LmlubmVyV2lkdGggPyAtKHBhcnNlSW50KHRoaXMuX3dpZHRoKSAtICh3aW5kb3cuaW5uZXJXaWR0aCAtIDEwMCkpICsgJ3B4JyA6ICcwcHgnO1xyXG4gICAgdGhpcy5vbGRXaWR0aCA9IHRoaXMuX3dpZHRoO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKSB7XHJcbiAgICBpZiAodGhpcy5hbmltYXRpb25Eb25lU3ViKSB7XHJcbiAgICAgIHRoaXMuYW5pbWF0aW9uRG9uZVN1Yi51bnN1YnNjcmliZSgpO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMucmVzaXplU3ViKSB7XHJcbiAgICAgIHRoaXMucmVzaXplU3ViLnVuc3Vic2NyaWJlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMud2luZG93UmVzaXplU3ViKSB7XHJcbiAgICAgIHRoaXMud2luZG93UmVzaXplU3ViLnVuc3Vic2NyaWJlKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDprZXlkb3duLmVzY2FwZScsIFsnJGV2ZW50J10pIGtleWRvd25IYW5kbGVyKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XHJcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgIGlmICh0aGlzLmVzY0tleUNsb3NlYWJsZSAmJiAhdGhpcy5pc0hhdmVEaWFsb2dPclVwbG9hZCgpKSB7XHJcbiAgICAgIHRoaXMuaGlkZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25BbmltYXRpb25FbmQoZXZlbnQpIHtcclxuICAgIGlmICh0aGlzLmFuaW1hdGVTdGF0ZSA9PT0gJ3ZvaWQnKSB7XHJcbiAgICAgIHRoaXMub25IaWRkZW4oKTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmFuaW1hdGVTdGF0ZSA9PT0gJ2luJyAmJiB0aGlzLmFmdGVyT3BlbmVkKSB7XHJcbiAgICAgIHRoaXMuYWZ0ZXJPcGVuZWQoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIFdpbGwgb3ZlcndyaXRlIGJ5IGRyYXdlciBzZXJ2aWNlXHJcbiAgb25IaWRkZW4oKSB7fVxyXG5cclxuICBzaG93KCkge1xyXG4gICAgaWYgKHRoaXMuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbEhlaWdodCA+IHRoaXMuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodCkge1xyXG4gICAgICB0aGlzLmRvY3VtZW50T3ZlckZsb3cgPSB0cnVlO1xyXG4gICAgICB0aGlzLnNjcm9sbFRvcCA9IHRoaXMuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcCB8fCB0aGlzLmRvY3VtZW50LmJvZHkuc2Nyb2xsVG9wO1xyXG4gICAgICB0aGlzLnNjcm9sbExlZnQgPSB0aGlzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0IHx8IHRoaXMuZG9jdW1lbnQuYm9keS5zY3JvbGxMZWZ0O1xyXG4gICAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKHRoaXMuZG9jdW1lbnQuYm9keSwgJ2RldnVpLWJvZHktc2Nyb2xsYmxvY2snKTtcclxuICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmRvY3VtZW50LmJvZHksICd0b3AnLCBgLSR7dGhpcy5zY3JvbGxUb3B9cHhgKTtcclxuICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmRvY3VtZW50LmJvZHksICdsZWZ0JywgYC0ke3RoaXMuc2Nyb2xsTGVmdH1weGApO1xyXG4gICAgfVxyXG4gICAgaWYgKCF0aGlzLmJvZHlTY3JvbGxhYmxlICYmIHRoaXMuZG9jdW1lbnRPdmVyRmxvdykge1xyXG4gICAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKHRoaXMuZG9jdW1lbnQuYm9keSwgJ2RldnVpLWJvZHktb3ZlcmZsb3ctaGlkZGVuJyk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmFuaW1hdGVTdGF0ZSA9ICdpbic7XHJcbiAgICBjb25zdCBhY3RpdmVFbGVtZW50ID0gdGhpcy5kb2N1bWVudC5hY3RpdmVFbGVtZW50O1xyXG4gICAgaWYgKGFjdGl2ZUVsZW1lbnQgJiYgdHlwZW9mIChhY3RpdmVFbGVtZW50IGFzIGFueSkuYmx1ciA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAoYWN0aXZlRWxlbWVudCBhcyBhbnkpLmJsdXIoKTtcclxuICAgIH1cclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLmhhbmRsZVJlc2l6ZVdpZHRoKCk7XHJcbiAgICB9LCAwKTtcclxuICAgIHRoaXMuaXNDb3ZlciA9IHRoaXMuaXNDb3ZlciA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IHRoaXMuaXNDb3ZlcjtcclxuICAgIGlmICghdGhpcy5iYWNrZHJvcENsb3NlYWJsZSB8fCB0aGlzLmlzQ292ZXIpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgY29uc3QgZG9jdW1lbnRDbGljayA9IGZyb21FdmVudDxLZXlib2FyZEV2ZW50Pihkb2N1bWVudCwgJ2NsaWNrJyk7XHJcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgdGhpcy5zdWJzY3JpcHRpb24gPSBkb2N1bWVudENsaWNrLnN1YnNjcmliZSgoZXZlbnQ6IEV2ZW50KSA9PiB7XHJcbiAgICAgICAgaWYgKHRoaXMuY2xpY2tEb21zICYmIHRoaXMuY2xpY2tEb21zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgIHRoaXMuY2xpY2tEb21zLmZvckVhY2goKGRvbSkgPT4ge1xyXG4gICAgICAgICAgICBpZiAoZG9tICE9PSBudWxsICYmIGRvbS5jb250YWlucyhldmVudC50YXJnZXQpKSB7XHJcbiAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XHJcbiAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgY29uc3QgdGFyZ2V0OiBhbnkgPSBldmVudC50YXJnZXQ7XHJcbiAgICAgICAgICAvLyDkuIDlrpropoFkb2N1bWVudC5jb250YWlucyhldmVudC50YXJnZXQp77yM5Zug5Li6ZXZlbnQudGFyZ2V05Y+v6IO95bey57uP5LiN5ZyoZG9jdW1lbnTph4zkuobvvIzov5nkuKrml7blgJnlsLHkuI3og73ov5toaWRl5LqGXHJcbiAgICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgIHRoaXMuYW5pbWF0ZVN0YXRlID09PSAnaW4nICYmXHJcbiAgICAgICAgICAgICF0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5jb250YWlucyh0YXJnZXQpICYmXHJcbiAgICAgICAgICAgIHRoaXMuZG9jdW1lbnQuYm9keS5jb250YWlucyh0YXJnZXQpICYmXHJcbiAgICAgICAgICAgICF0aGlzLmlzSGF2ZURpYWxvZ09yVXBsb2FkKClcclxuICAgICAgICAgICkge1xyXG4gICAgICAgICAgICB0aGlzLmhpZGUoKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBoaWRlKCkge1xyXG4gICAgdGhpcy5jYW5IaWRlTW9kZWwoKS50aGVuKChjYW5IaWRlKSA9PiB7XHJcbiAgICAgIGlmICghY2FuSGlkZSkge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmhpZGVPcGVyYXRpb24oKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgaGlkZURpcmVjdGx5KCkge1xyXG4gICAgdGhpcy5oaWRlT3BlcmF0aW9uKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGhpZGVPcGVyYXRpb24oKSB7XHJcbiAgICBpZiAodGhpcy5kb2N1bWVudE92ZXJGbG93KSB7XHJcbiAgICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlU3R5bGUodGhpcy5kb2N1bWVudC5ib2R5LCAndG9wJyk7XHJcbiAgICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlU3R5bGUodGhpcy5kb2N1bWVudC5ib2R5LCAnbGVmdCcpO1xyXG4gICAgICB0aGlzLnJlbmRlcmVyLnJlbW92ZUNsYXNzKHRoaXMuZG9jdW1lbnQuYm9keSwgJ2RldnVpLWJvZHktc2Nyb2xsYmxvY2snKTtcclxuICAgICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyh0aGlzLmRvY3VtZW50LmJvZHksICdkZXZ1aS1ib2R5LW92ZXJmbG93LWhpZGRlbicpO1xyXG4gICAgICB0aGlzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgPSB0aGlzLnNjcm9sbFRvcDtcclxuICAgICAgdGhpcy5kb2N1bWVudC5ib2R5LnNjcm9sbFRvcCA9IHRoaXMuc2Nyb2xsVG9wO1xyXG4gICAgICB0aGlzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0ID0gdGhpcy5zY3JvbGxMZWZ0O1xyXG4gICAgICB0aGlzLmRvY3VtZW50LmJvZHkuc2Nyb2xsTGVmdCA9IHRoaXMuc2Nyb2xsTGVmdDtcclxuICAgIH1cclxuICAgIHRoaXMuYW5pbWF0ZVN0YXRlID0gJ3ZvaWQnO1xyXG4gICAgaWYgKHRoaXMuc3Vic2NyaXB0aW9uKSB7XHJcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XHJcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gV2lsbCBvdmVyd3JpdGUgYnkgZHJhd2VyIHNlcnZpY2VcclxuICBkZXN0cm95KCkge31cclxuXHJcbiAgaXNIYXZlRGlhbG9nT3JVcGxvYWQoKSB7XHJcbiAgICBjb25zdCBkaWFsb2c6IGFueSA9IHRoaXMuZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnbW9kYWwtZGlhbG9nJyk7XHJcbiAgICBjb25zdCB1cGxvYWQ6IGFueSA9IHRoaXMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2QtdXBsb2FkLXRlbXAnKTtcclxuICAgIHJldHVybiAoZGlhbG9nICYmIGRpYWxvZy5sZW5ndGggPiAwKSB8fCB1cGxvYWQ7XHJcbiAgfVxyXG5cclxuICBjYW5IaWRlTW9kZWwoKSB7XHJcbiAgICBsZXQgaGlkZGVuUmVzdWx0ID0gUHJvbWlzZS5yZXNvbHZlKHRydWUpO1xyXG5cclxuICAgIGlmICh0aGlzLmJlZm9yZUhpZGRlbikge1xyXG4gICAgICBjb25zdCByZXN1bHQ6IGFueSA9IHRoaXMuYmVmb3JlSGlkZGVuKCk7XHJcbiAgICAgIGlmICh0eXBlb2YgcmVzdWx0ICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgICAgIGlmIChyZXN1bHQudGhlbikge1xyXG4gICAgICAgICAgaGlkZGVuUmVzdWx0ID0gcmVzdWx0O1xyXG4gICAgICAgIH0gZWxzZSBpZiAocmVzdWx0LnN1YnNjcmliZSkge1xyXG4gICAgICAgICAgaGlkZGVuUmVzdWx0ID0gKHJlc3VsdCBhcyBPYnNlcnZhYmxlPGJvb2xlYW4+KS50b1Byb21pc2UoKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgaGlkZGVuUmVzdWx0ID0gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGhpZGRlblJlc3VsdDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX3NldEZ1bGxTY3JlZW4oZnVsbFNjcmVlbj86IGJvb2xlYW4pIHtcclxuICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBjb25zdCBkcmF3ZXJDb250YWluZXJFbGUgPSB0aGlzLmRyYXdlckNvbnRhaW5lci5uYXRpdmVFbGVtZW50O1xyXG4gICAgaWYgKHRoaXMuX3dpZHRoID09PSB0aGlzLm9sZFdpZHRoKSB7XHJcbiAgICAgIGlmIChmdWxsU2NyZWVuID09PSB0cnVlIHx8IGZ1bGxTY3JlZW4gPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIHRoaXMuaXNGdWxsU2NyZWVuID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLl93aWR0aCA9IHRoaXMuX2lzQ292ZXIgPyAnMTAwJScgOiB3aW5kb3cuaW5uZXJXaWR0aCArICdweCc7XHJcbiAgICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShcclxuICAgICAgICAgIGRyYXdlckNvbnRhaW5lckVsZSxcclxuICAgICAgICAgICd0cmFuc2l0aW9uJyxcclxuICAgICAgICAgIHRoaXMuc2hvd0FuaW1hdGlvbiA/IGB3aWR0aCAuM3MgY3ViaWMtYmV6aWVyKDAuNSwgMC4wNSwgMC41LCAwLjk1KWAgOiAnbm9uZSdcclxuICAgICAgICApO1xyXG4gICAgICAgIGlmICghdGhpcy5faXNDb3Zlcikge1xyXG4gICAgICAgICAgY29uc3QgcmVzaXplRXYgPSBmcm9tRXZlbnQod2luZG93LCAncmVzaXplJyk7XHJcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSByZXNpemVFdi5waXBlKGRlYm91bmNlVGltZSgxMDApKTtcclxuICAgICAgICAgIHRoaXMucmVzaXplU3ViID0gcmVzdWx0LnN1YnNjcmliZSgoZXYpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5fd2lkdGggPSB3aW5kb3cuaW5uZXJXaWR0aCArICdweCc7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmICghZnVsbFNjcmVlbikge1xyXG4gICAgICAgIHRoaXMuaXNGdWxsU2NyZWVuID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy5fd2lkdGggPSB0aGlzLm9sZFdpZHRoO1xyXG4gICAgICAgIGlmICh0aGlzLnJlc2l6ZVN1Yikge1xyXG4gICAgICAgICAgdGhpcy5y