UNPKG

ng-zorro-antd

Version:

An enterprise-class UI components based on Ant Design and Angular

500 lines 55.7 kB
import { CdkDrag, CdkDragHandle } from '@angular/cdk/drag-drop';
import { ChangeDetectionStrategy, Component, EventEmitter, ViewChild, ViewEncapsulation } from '@angular/core';
import { fromEvent } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fadeMotion } from 'ng-zorro-antd/core/animation';
import { NzDestroyService } from 'ng-zorro-antd/core/services';
import { isNotNil } from 'ng-zorro-antd/core/util';
import { NzIconModule } from 'ng-zorro-antd/icon';
import { NZ_CONFIG_MODULE_NAME } from './image-config';
import { getClientSize, getFitContentPosition, getOffset } from './utils';
import * as i0 from "@angular/core";
import * as i1 from "ng-zorro-antd/core/config";
import * as i2 from "./image-preview-options";
import * as i3 from "ng-zorro-antd/core/services";
import * as i4 from "@angular/platform-browser";
import * as i5 from "ng-zorro-antd/icon";
const initialPosition = {
    x: 0,
    y: 0
};
export const NZ_DEFAULT_SCALE_STEP = 0.5;
const NZ_DEFAULT_ZOOM = 1;
const NZ_DEFAULT_ROTATE = 0;
export class NzImagePreviewComponent {
    get animationDisabled() {
        return this.config.nzNoAnimation ?? false;
    }
    get maskClosable() {
        const defaultConfig = this.nzConfigService.getConfigForComponent(NZ_CONFIG_MODULE_NAME) || {};
        return this.config.nzMaskClosable ?? defaultConfig.nzMaskClosable ?? true;
    }
    constructor(ngZone, cdr, nzConfigService, config, destroy$, sanitizer) {
        this.ngZone = ngZone;
        this.cdr = cdr;
        this.nzConfigService = nzConfigService;
        this.config = config;
        this.destroy$ = destroy$;
        this.sanitizer = sanitizer;
        this._defaultNzZoom = NZ_DEFAULT_ZOOM;
        this._defaultNzScaleStep = NZ_DEFAULT_SCALE_STEP;
        this._defaultNzRotate = NZ_DEFAULT_ROTATE;
        this.images = [];
        this.index = 0;
        this.isDragging = false;
        this.visible = true;
        this.animationStateChanged = new EventEmitter();
        this.scaleStepMap = new Map();
        this.previewImageTransform = '';
        this.previewImageWrapperTransform = '';
        this.operations = [
            {
                icon: 'close',
                onClick: () => {
                    this.onClose();
                },
                type: 'close'
            },
            {
                icon: 'zoom-in',
                onClick: () => {
                    this.onZoomIn();
                },
                type: 'zoomIn'
            },
            {
                icon: 'zoom-out',
                onClick: () => {
                    this.onZoomOut();
                },
                type: 'zoomOut'
            },
            {
                icon: 'rotate-right',
                onClick: () => {
                    this.onRotateRight();
                },
                type: 'rotateRight'
            },
            {
                icon: 'rotate-left',
                onClick: () => {
                    this.onRotateLeft();
                },
                type: 'rotateLeft'
            },
            {
                icon: 'swap',
                onClick: () => {
                    this.onHorizontalFlip();
                },
                type: 'flipHorizontally'
            },
            {
                icon: 'swap',
                onClick: () => {
                    this.onVerticalFlip();
                },
                type: 'flipVertically',
                rotate: 90
            }
        ];
        this.zoomOutDisabled = false;
        this.position = { ...initialPosition };
        this.closeClick = new EventEmitter();
        this.zoom = this.config.nzZoom ?? this._defaultNzZoom;
        this.scaleStep = this.config.nzScaleStep ?? this._defaultNzScaleStep;
        this.rotate = this.config.nzRotate ?? this._defaultNzRotate;
        this.flipHorizontally = this.config.nzFlipHorizontally ?? false;
        this.flipVertically = this.config.nzFlipVertically ?? false;
        this.updateZoomOutDisabled();
        this.updatePreviewImageTransform();
        this.updatePreviewImageWrapperTransform();
    }
    ngOnInit() {
        this.ngZone.runOutsideAngular(() => {
            fromEvent(this.imagePreviewWrapper.nativeElement, 'mousedown')
                .pipe(takeUntil(this.destroy$))
                .subscribe(() => {
                this.isDragging = true;
            });
            fromEvent(this.imagePreviewWrapper.nativeElement, 'wheel')
                .pipe(takeUntil(this.destroy$))
                .subscribe(event => {
                this.ngZone.run(() => this.wheelZoomEventHandler(event));
            });
        });
    }
    setImages(images, scaleStepMap) {
        if (scaleStepMap)
            this.scaleStepMap = scaleStepMap;
        this.images = images;
        this.markForCheck();
    }
    switchTo(index) {
        this.index = index;
        this.markForCheck();
    }
    next() {
        if (this.index < this.images.length - 1) {
            this.reset();
            this.index++;
            this.updatePreviewImageTransform();
            this.updatePreviewImageWrapperTransform();
            this.updateZoomOutDisabled();
            this.markForCheck();
        }
    }
    prev() {
        if (this.index > 0) {
            this.reset();
            this.index--;
            this.updatePreviewImageTransform();
            this.updatePreviewImageWrapperTransform();
            this.updateZoomOutDisabled();
            this.markForCheck();
        }
    }
    markForCheck() {
        this.cdr.markForCheck();
    }
    onClose() {
        this.visible = false;
        this.closeClick.emit();
    }
    onZoomIn() {
        const zoomStep = this.scaleStepMap.get(this.images[this.index].src ?? this.images[this.index].srcset) ?? this.scaleStep;
        this.zoom += zoomStep;
        this.updatePreviewImageTransform();
        this.updateZoomOutDisabled();
    }
    onZoomOut() {
        if (this.zoom > 1) {
            const zoomStep = this.scaleStepMap.get(this.images[this.index].src ?? this.images[this.index].srcset) ?? this.scaleStep;
            this.zoom -= zoomStep;
            this.updatePreviewImageTransform();
            this.updateZoomOutDisabled();
            if (this.zoom <= 1) {
                this.reCenterImage();
            }
        }
    }
    onRotateRight() {
        this.rotate += 90;
        this.updatePreviewImageTransform();
    }
    onRotateLeft() {
        this.rotate -= 90;
        this.updatePreviewImageTransform();
    }
    onSwitchLeft(event) {
        event.preventDefault();
        event.stopPropagation();
        this.prev();
    }
    onSwitchRight(event) {
        event.preventDefault();
        event.stopPropagation();
        this.next();
    }
    onHorizontalFlip() {
        this.flipHorizontally = !this.flipHorizontally;
        this.updatePreviewImageTransform();
    }
    onVerticalFlip() {
        this.flipVertically = !this.flipVertically;
        this.updatePreviewImageTransform();
    }
    wheelZoomEventHandler(event) {
        event.preventDefault();
        event.stopPropagation();
        this.handlerImageTransformationWhileZoomingWithMouse(event, event.deltaY);
        this.handleImageScaleWhileZoomingWithMouse(event.deltaY);
        this.updatePreviewImageWrapperTransform();
        this.updatePreviewImageTransform();
        this.markForCheck();
    }
    onAnimationStart(event) {
        this.animationStateChanged.emit(event);
    }
    onAnimationDone(event) {
        this.animationStateChanged.emit(event);
    }
    onDragEnd(event) {
        this.isDragging = false;
        const width = this.imageRef.nativeElement.offsetWidth * this.zoom;
        const height = this.imageRef.nativeElement.offsetHeight * this.zoom;
        const { left, top } = getOffset(this.imageRef.nativeElement);
        const { width: clientWidth, height: clientHeight } = getClientSize();
        const isRotate = this.rotate % 180 !== 0;
        const fitContentParams = {
            width: isRotate ? height : width,
            height: isRotate ? width : height,
            left,
            top,
            clientWidth,
            clientHeight
        };
        const fitContentPos = getFitContentPosition(fitContentParams);
        if (isNotNil(fitContentPos.x) || isNotNil(fitContentPos.y)) {
            this.position = { ...this.position, ...fitContentPos };
        }
        else if (!isNotNil(fitContentPos.x) && !isNotNil(fitContentPos.y)) {
            this.position = {
                x: event.source.getFreeDragPosition().x,
                y: event.source.getFreeDragPosition().y
            };
        }
    }
    sanitizerResourceUrl(url) {
        return this.sanitizer.bypassSecurityTrustResourceUrl(url);
    }
    updatePreviewImageTransform() {
        this.previewImageTransform = `scale3d(${this.zoom * (this.flipHorizontally ? -1 : 1)}, ${this.zoom * (this.flipVertically ? -1 : 1)}, 1) rotate(${this.rotate}deg)`;
    }
    updatePreviewImageWrapperTransform() {
        this.previewImageWrapperTransform = `translate3d(${this.position.x}px, ${this.position.y}px, 0)`;
    }
    updateZoomOutDisabled() {
        this.zoomOutDisabled = this.zoom <= 1;
    }
    handlerImageTransformationWhileZoomingWithMouse(event, deltaY) {
        let scaleValue;
        const imageElement = this.imageRef.nativeElement;
        const elementTransform = getComputedStyle(imageElement).transform;
        const matrixValue = elementTransform.match(/matrix.*\((.+)\)/);
        if (matrixValue) {
            scaleValue = +matrixValue[1].split(', ')[0];
        }
        else {
            scaleValue = this.zoom;
        }
        const x = (event.clientX - imageElement.getBoundingClientRect().x) / scaleValue;
        const y = (event.clientY - imageElement.getBoundingClientRect().y) / scaleValue;
        const halfOfScaleStepValue = deltaY < 0 ? this.scaleStep / 2 : -this.scaleStep / 2;
        this.position.x += -x * halfOfScaleStepValue * 2 + imageElement.offsetWidth * halfOfScaleStepValue;
        this.position.y += -y * halfOfScaleStepValue * 2 + imageElement.offsetHeight * halfOfScaleStepValue;
    }
    handleImageScaleWhileZoomingWithMouse(deltaY) {
        if (this.isZoomedInWithMouseWheel(deltaY)) {
            this.onZoomIn();
        }
        else {
            this.onZoomOut();
        }
        if (this.zoom <= 1) {
            this.reCenterImage();
        }
    }
    isZoomedInWithMouseWheel(delta) {
        return delta < 0;
    }
    reset() {
        this.zoom = this.config.nzZoom ?? this._defaultNzZoom;
        this.scaleStep = this.config.nzScaleStep ?? this._defaultNzScaleStep;
        this.rotate = this.config.nzRotate ?? this._defaultNzRotate;
        this.flipHorizontally = false;
        this.flipVertically = false;
        this.reCenterImage();
    }
    reCenterImage() {
        this.position = { ...initialPosition };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: NzImagePreviewComponent, deps: [{ token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i1.NzConfigService }, { token: i2.NzImagePreviewOptions }, { token: i3.NzDestroyService }, { token: i4.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.1", type: NzImagePreviewComponent, isStandalone: true, selector: "nz-image-preview", host: { listeners: { "@fadeMotion.start": "onAnimationStart($event)", "@fadeMotion.done": "onAnimationDone($event)" }, properties: { "class.ant-image-preview-moving": "isDragging", "style.zIndex": "config.nzZIndex", "@.disabled": "config.nzNoAnimation", "@fadeMotion": "visible ? 'enter' : 'leave'" }, classAttribute: "ant-image-preview-root" }, providers: [NzDestroyService], viewQueries: [{ propertyName: "imageRef", first: true, predicate: ["imgRef"], descendants: true }, { propertyName: "imagePreviewWrapper", first: true, predicate: ["imagePreviewWrapper"], descendants: true, static: true }], exportAs: ["nzImagePreview"], ngImport: i0, template: `
    <div class="ant-image-preview-mask"></div>

    <div class="ant-image-preview-operations-wrapper">
      @if (images.length > 1) {
        <div
          class="ant-image-preview-switch-left"
          [class.ant-image-preview-switch-left-disabled]="index <= 0"
          (click)="onSwitchLeft($event)"
        >
          <span nz-icon nzType="left" nzTheme="outline"></span>
        </div>
        <div
          class="ant-image-preview-switch-right"
          [class.ant-image-preview-switch-right-disabled]="index >= images.length - 1"
          (click)="onSwitchRight($event)"
        >
          <span nz-icon nzType="right" nzTheme="outline"></span>
        </div>
      }

      <ul class="ant-image-preview-operations">
        @if (images.length > 1) {
          <li class="ant-image-preview-operations-progress">{{ index + 1 }} / {{ images.length }}</li>
        }

        @for (option of operations; track option) {
          <li
            class="ant-image-preview-operations-operation"
            [class.ant-image-preview-operations-operation-disabled]="zoomOutDisabled && option.type === 'zoomOut'"
            (click)="option.onClick()"
          >
            <span
              class="ant-image-preview-operations-icon"
              nz-icon
              [nzType]="option.icon"
              [nzRotate]="option.rotate ?? 0"
              nzTheme="outline"
            ></span>
          </li>
        }
      </ul>
    </div>

    <div
      class="ant-image-preview-wrap"
      tabindex="-1"
      (click)="maskClosable && $event.target === $event.currentTarget && onClose()"
    >
      <div class="ant-image-preview" role="dialog" aria-modal="true">
        <div tabindex="0" aria-hidden="true" class="ant-image-preview-focus-trap"></div>
        <div class="ant-image-preview-content">
          <div class="ant-image-preview-body">
            <div
              class="ant-image-preview-img-wrapper"
              #imagePreviewWrapper
              cdkDrag
              [style.transform]="previewImageWrapperTransform"
              [cdkDragFreeDragPosition]="position"
              (cdkDragEnded)="onDragEnd($event)"
            >
              @for (image of images; track image; let imageIndex = $index) {
                @if (imageIndex === index) {
                  <img
                    cdkDragHandle
                    class="ant-image-preview-img"
                    #imgRef
                    [attr.src]="sanitizerResourceUrl(image.src)"
                    [attr.srcset]="image.srcset"
                    [attr.alt]="image.alt"
                    [style.width]="image.width"
                    [style.height]="image.height"
                    [style.transform]="previewImageTransform"
                  />
                }
              }
            </div>
          </div>
        </div>
        <div tabindex="0" aria-hidden="true" class="ant-image-preview-focus-trap"></div>
      </div>
    </div>
  `, isInline: true, dependencies: [{ kind: "ngmodule", type: NzIconModule }, { kind: "directive", type: i5.NzIconDirective, selector: "[nz-icon]", inputs: ["nzSpin", "nzRotate", "nzType", "nzTheme", "nzTwotoneColor", "nzIconfont"], exportAs: ["nzIcon"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }], animations: [fadeMotion], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: NzImagePreviewComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'nz-image-preview',
                    exportAs: 'nzImagePreview',
                    animations: [fadeMotion],
                    standalone: true,
                    template: `
    <div class="ant-image-preview-mask"></div>

    <div class="ant-image-preview-operations-wrapper">
      @if (images.length > 1) {
        <div
          class="ant-image-preview-switch-left"
          [class.ant-image-preview-switch-left-disabled]="index <= 0"
          (click)="onSwitchLeft($event)"
        >
          <span nz-icon nzType="left" nzTheme="outline"></span>
        </div>
        <div
          class="ant-image-preview-switch-right"
          [class.ant-image-preview-switch-right-disabled]="index >= images.length - 1"
          (click)="onSwitchRight($event)"
        >
          <span nz-icon nzType="right" nzTheme="outline"></span>
        </div>
      }

      <ul class="ant-image-preview-operations">
        @if (images.length > 1) {
          <li class="ant-image-preview-operations-progress">{{ index + 1 }} / {{ images.length }}</li>
        }

        @for (option of operations; track option) {
          <li
            class="ant-image-preview-operations-operation"
            [class.ant-image-preview-operations-operation-disabled]="zoomOutDisabled && option.type === 'zoomOut'"
            (click)="option.onClick()"
          >
            <span
              class="ant-image-preview-operations-icon"
              nz-icon
              [nzType]="option.icon"
              [nzRotate]="option.rotate ?? 0"
              nzTheme="outline"
            ></span>
          </li>
        }
      </ul>
    </div>

    <div
      class="ant-image-preview-wrap"
      tabindex="-1"
      (click)="maskClosable && $event.target === $event.currentTarget && onClose()"
    >
      <div class="ant-image-preview" role="dialog" aria-modal="true">
        <div tabindex="0" aria-hidden="true" class="ant-image-preview-focus-trap"></div>
        <div class="ant-image-preview-content">
          <div class="ant-image-preview-body">
            <div
              class="ant-image-preview-img-wrapper"
              #imagePreviewWrapper
              cdkDrag
              [style.transform]="previewImageWrapperTransform"
              [cdkDragFreeDragPosition]="position"
              (cdkDragEnded)="onDragEnd($event)"
            >
              @for (image of images; track image; let imageIndex = $index) {
                @if (imageIndex === index) {
                  <img
                    cdkDragHandle
                    class="ant-image-preview-img"
                    #imgRef
                    [attr.src]="sanitizerResourceUrl(image.src)"
                    [attr.srcset]="image.srcset"
                    [attr.alt]="image.alt"
                    [style.width]="image.width"
                    [style.height]="image.height"
                    [style.transform]="previewImageTransform"
                  />
                }
              }
            </div>
          </div>
        </div>
        <div tabindex="0" aria-hidden="true" class="ant-image-preview-focus-trap"></div>
      </div>
    </div>
  `,
                    preserveWhitespaces: false,
                    changeDetection: ChangeDetectionStrategy.OnPush,
                    encapsulation: ViewEncapsulation.None,
                    host: {
                        class: 'ant-image-preview-root',
                        '[class.ant-image-preview-moving]': 'isDragging',
                        '[style.zIndex]': 'config.nzZIndex',
                        '[@.disabled]': 'config.nzNoAnimation',
                        '[@fadeMotion]': `visible ? 'enter' : 'leave'`,
                        '(@fadeMotion.start)': 'onAnimationStart($event)',
                        '(@fadeMotion.done)': 'onAnimationDone($event)'
                    },
                    imports: [NzIconModule, CdkDragHandle, CdkDrag],
                    providers: [NzDestroyService]
                }]
        }], ctorParameters: () => [{ type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i1.NzConfigService }, { type: i2.NzImagePreviewOptions }, { type: i3.NzDestroyService }, { type: i4.DomSanitizer }], propDecorators: { imageRef: [{
                type: ViewChild,
                args: ['imgRef']
            }], imagePreviewWrapper: [{
                type: ViewChild,
                args: ['imagePreviewWrapper', { static: true }]
            }] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2UtcHJldmlldy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9jb21wb25lbnRzL2ltYWdlL2ltYWdlLXByZXZpZXcuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU1BLE9BQU8sRUFBRSxPQUFPLEVBQWMsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDNUUsT0FBTyxFQUNMLHVCQUF1QixFQUV2QixTQUFTLEVBRVQsWUFBWSxFQUdaLFNBQVMsRUFDVCxpQkFBaUIsRUFDbEIsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNqQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFM0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBRTFELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRS9ELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFbEQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFJdkQsT0FBTyxFQUFFLGFBQWEsRUFBRSxxQkFBcUIsRUFBRSxTQUFTLEVBQUUsTUFBTSxTQUFTLENBQUM7Ozs7Ozs7QUFTMUUsTUFBTSxlQUFlLEdBQUc7SUFDdEIsQ0FBQyxFQUFFLENBQUM7SUFDSixDQUFDLEVBQUUsQ0FBQztDQUNMLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyxHQUFHLENBQUM7QUFDekMsTUFBTSxlQUFlLEdBQUcsQ0FBQyxDQUFDO0FBQzFCLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0FBeUc1QixNQUFNLE9BQU8sdUJBQXVCO0lBaUZsQyxJQUFJLGlCQUFpQjtRQUNuQixPQUFPLElB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QXlFc0IsUUFBUTtzQkFBNUIsU0FBUzt1QkFBQyxRQUFRO2dCQUNpQyxtQkFBbUI7c0JBQXRFLFNBQVM7dUJBQUMscUJBQXFCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2dpdGh1Yi5jb20vTkctWk9SUk8vbmctem9ycm8tYW50ZC9ibG9iL21hc3Rlci9MSUNFTlNFXG4gKi9cblxuaW1wb3J0IHsgQW5pbWF0aW9uRXZlbnQgfSBmcm9tICdAYW5ndWxhci9hbmltYXRpb25zJztcbmltcG9ydCB7IENka0RyYWcsIENka0RyYWdFbmQsIENka0RyYWdIYW5kbGUgfSBmcm9tICdAYW5ndWxhci9jZGsvZHJhZy1kcm9wJztcbmltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIE5nWm9uZSxcbiAgT25Jbml0LFxuICBWaWV3Q2hpbGQsXG4gIFZpZXdFbmNhcHN1bGF0aW9uXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRG9tU2FuaXRpemVyLCBTYWZlUmVzb3VyY2VVcmwgfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcbmltcG9ydCB7IGZyb21FdmVudCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBmYWRlTW90aW9uIH0gZnJvbSAnbmctem9ycm8tYW50ZC9jb3JlL2FuaW1hdGlvbic7XG5pbXBvcnQgeyBOekNvbmZpZ1NlcnZpY2UgfSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUvY29uZmlnJztcbmltcG9ydCB7IE56RGVzdHJveVNlcnZpY2UgfSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUvc2VydmljZXMnO1xuaW1wb3J0IHsgTnpTYWZlQW55IH0gZnJvbSAnbmctem9ycm8tYW50ZC9jb3JlL3R5cGVzJztcbmltcG9ydCB7IGlzTm90TmlsIH0gZnJvbSAnbmctem9ycm8tYW50ZC9jb3JlL3V0aWwnO1xuaW1wb3J0IHsgTnpJY29uTW9kdWxlIH0gZnJvbSAnbmctem9ycm8tYW50ZC9pY29uJztcblxuaW1wb3J0IHsgTlpfQ09ORklHX01PRFVMRV9OQU1FIH0gZnJvbSAnLi9pbWFnZS1jb25maWcnO1xuaW1wb3J0IHsgTnpJbWFnZSwgTnpJbWFnZVByZXZpZXdPcHRpb25zIH0gZnJvbSAnLi9pbWFnZS1wcmV2aWV3LW9wdGlvbnMnO1xuaW1wb3J0IHsgTnpJbWFnZVByZXZpZXdSZWYgfSBmcm9tICcuL2ltYWdlLXByZXZpZXctcmVmJztcbmltcG9ydCB7IE56SW1hZ2VTY2FsZVN0ZXAsIE56SW1hZ2VVcmwgfSBmcm9tICcuL2ltYWdlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBnZXRDbGllbnRTaXplLCBnZXRGaXRDb250ZW50UG9zaXRpb24sIGdldE9mZnNldCB9IGZyb20gJy4vdXRpbHMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIE56SW1hZ2VDb250YWluZXJPcGVyYXRpb24ge1xuICBpY29uOiBzdHJpbmc7XG4gIHR5cGU6IHN0cmluZztcbiAgcm90YXRlPzogbnVtYmVyO1xuICBvbkNsaWNrKCk6IHZvaWQ7XG59XG5cbmNvbnN0IGluaXRpYWxQb3NpdGlvbiA9IHtcbiAgeDogMCxcbiAgeTogMFxufTtcblxuZXhwb3J0IGNvbnN0IE5aX0RFRkFVTFRfU0NBTEVfU1RFUCA9IDAuNTtcbmNvbnN0IE5aX0RFRkFVTFRfWk9PTSA9IDE7XG5jb25zdCBOWl9ERUZBVUxUX1JPVEFURSA9IDA7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ256LWltYWdlLXByZXZpZXcnLFxuICBleHBvcnRBczogJ256SW1hZ2VQcmV2aWV3JyxcbiAgYW5pbWF0aW9uczogW2ZhZGVNb3Rpb25dLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJhbnQtaW1hZ2UtcHJldmlldy1tYXNrXCI+PC9kaXY+XG5cbiAgICA8ZGl2IGNsYXNzPVwiYW50LWltYWdlLXByZXZpZXctb3BlcmF0aW9ucy13cmFwcGVyXCI+XG4gICAgICBAaWYgKGltYWdlcy5sZW5ndGggPiAxKSB7XG4gICAgICAgIDxkaXZcbiAgICAgICAgICBjbGFzcz1cImFudC1pbWFnZS1wcmV2aWV3LXN3aXRjaC1sZWZ0XCJcbiAgICAgICAgICBbY2xhc3MuYW50LWltYWdlLXByZXZpZXctc3dpdGNoLWxlZnQtZGlzYWJsZWRdPVwiaW5kZXggPD0gMFwiXG4gICAgICAgICAgKGNsaWNrKT1cIm9uU3dpdGNoTGVmdCgkZXZlbnQpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxzcGFuIG56LWljb24gbnpUeXBlPVwibGVmdFwiIG56VGhlbWU9XCJvdXRsaW5lXCI+PC9zcGFuPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdlxuICAgICAgICAgIGNsYXNzPVwiYW50LWltYWdlLXByZXZpZXctc3dpdGNoLXJpZ2h0XCJcbiAgICAgICAgICBbY2xhc3MuYW50LWltYWdlLXByZXZpZXctc3dpdGNoLXJpZ2h0LWRpc2FibGVkXT1cImluZGV4ID49IGltYWdlcy5sZW5ndGggLSAxXCJcbiAgICAgICAgICAoY2xpY2spPVwib25Td2l0Y2hSaWdodCgkZXZlbnQpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxzcGFuIG56LWljb24gbnpUeXBlPVwicmlnaHRcIiBuelRoZW1lPVwib3V0bGluZVwiPjwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG5cbiAgICAgIDx1bCBjbGFzcz1cImFudC1pbWFnZS1wcmV2aWV3LW9wZXJhdGlvbnNcIj5cbiAgICAgICAgQGlmIChpbWFnZXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgIDxsaSBjbGFzcz1cImFudC1pbWFnZS1wcmV2aWV3LW9wZXJhdGlvbnMtcHJvZ3Jlc3NcIj57eyBpbmRleCArIDEgfX0gLyB7eyBpbWFnZXMubGVuZ3RoIH19PC9saT5cbiAgICAgICAgfVxuXG4gICAgICAgIEBmb3IgKG9wdGlvbiBvZiBvcGVyYXRpb25zOyB0cmFjayBvcHRpb24pIHtcbiAgICAgICAgICA8bGlcbiAgICAgICAgICAgIGNsYXNzPVwiYW50LWltYWdlLXByZXZpZXctb3BlcmF0aW9ucy1vcGVyYXRpb25cIlxuICAgICAgICAgICAgW2NsYXNzLmFudC1pbWFnZS1wcmV2aWV3LW9wZXJhdGlvbnMtb3BlcmF0aW9uLWRpc2FibGVkXT1cInpvb21PdXREaXNhYmxlZCAmJiBvcHRpb24udHlwZSA9PT0gJ3pvb21PdXQnXCJcbiAgICAgICAgICAgIChjbGljayk9XCJvcHRpb24ub25DbGljaygpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8c3BhblxuICAgICAgICAgICAgICBjbGFzcz1cImFudC1pbWFnZS1wcmV2aWV3LW9wZXJhdGlvbnMtaWNvblwiXG4gICAgICAgICAgICAgIG56LWljb25cbiAgICAgICAgICAgICAgW256VHlwZV09XCJvcHRpb24uaWNvblwiXG4gICAgICAgICAgICAgIFtuelJvdGF0ZV09XCJvcHRpb24ucm90YXRlID8/IDBcIlxuICAgICAgICAgICAgICBuelRoZW1lPVwib3V0bGluZVwiXG4gICAgICAgICAgICA+PC9zcGFuPlxuICAgICAgICAgIDwvbGk+XG4gICAgICAgIH1cbiAgICAgIDwvdWw+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2XG4gICAgICBjbGFzcz1cImFudC1pbWFnZS1wcmV2aWV3LXdyYXBcIlxuICAgICAgdGFiaW5kZXg9XCItMVwiXG4gICAgICAoY2xpY2spPVwibWFza0Nsb3NhYmxlICYmICRldmVudC50YXJnZXQgPT09ICRldmVudC5jdXJyZW50VGFyZ2V0ICYmIG9uQ2xvc2UoKVwiXG4gICAgPlxuICAgICAgPGRpdiBjbGFzcz1cImFudC1pbWFnZS1wcmV2aWV3XCIgcm9sZT1cImRpYWxvZ1wiIGFyaWEtbW9kYWw9XCJ0cnVlXCI+XG4gICAgICAgIDxkaXYgdGFiaW5kZXg9XCIwXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCIgY2xhc3M9XCJhbnQtaW1hZ2UtcHJldmlldy1mb2N1cy10cmFwXCI+PC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJhbnQtaW1hZ2UtcHJldmlldy1jb250ZW50XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImFudC1pbWFnZS1wcmV2aWV3LWJvZHlcIj5cbiAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgY2xhc3M9XCJhbnQtaW1hZ2UtcHJldmlldy1pbWctd3JhcHBlclwiXG4gICAgICAgICAgICAgICNpbWFnZVByZXZpZXdXcmFwcGVyXG4gICAgICAgICAgICAgIGNka0RyYWdcbiAgICAgICAgICAgICAgW3N0eWxlLnRyYW5zZm9ybV09XCJwcmV2aWV3SW1hZ2VXcmFwcGVyVHJhbnNmb3JtXCJcbiAgICAgICAgICAgICAgW2Nka0RyYWdGcmVlRHJhZ1Bvc2l0aW9uXT1cInBvc2l0aW9uXCJcbiAgICAgICAgICAgICAgKGNka0RyYWdFbmRlZCk9XCJvbkRyYWdFbmQoJGV2ZW50KVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIEBmb3IgKGltYWdlIG9mIGltYWdlczsgdHJhY2sgaW1hZ2U7IGxldCBpbWFnZUluZGV4ID0gJGluZGV4KSB7XG4gICAgICAgICAgICAgICAgQGlmIChpbWFnZUluZGV4ID09PSBpbmRleCkge1xuICAgICAgICAgICAgICAgICAgPGltZ1xuICAgICAgICAgICAgICAgICAgICBjZGtEcmFnSGFuZGxlXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYW50LWltYWdlLXByZXZpZXctaW1nXCJcbiAgICAgICAgICAgICAgICAgICAgI2ltZ1JlZlxuICAgICAgICAgICAgICAgICAgICBbYXR0ci5zcmNdPVwic2FuaXRpemVyUmVzb3VyY2VVcmwoaW1hZ2Uuc3JjKVwiXG4gICAgICAgICAgICAgICAgICAgIFthdHRyLnNyY3NldF09XCJpbWFnZS5zcmNzZXRcIlxuICAgICAgICAgICAgICAgICAgICBbYXR0ci5hbHRdPVwiaW1hZ2UuYWx0XCJcbiAgICAgICAgICAgICAgICAgICAgW3N0eWxlLndpZHRoXT1cImltYWdlLndpZHRoXCJcbiAgICAgICAgICAgICAgICAgICAgW3N0eWxlLmhlaWdodF09XCJpbWFnZS5oZWlnaHRcIlxuICAgICAgICAgICAgICAgICAgICBbc3R5bGUudHJhbnNmb3JtXT1cInByZXZpZXdJbWFnZVRyYW5zZm9ybVwiXG4gICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IHRhYmluZGV4PVwiMFwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiIGNsYXNzPVwiYW50LWltYWdlLXByZXZpZXctZm9jdXMtdHJhcFwiPjwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIGAsXG4gIHByZXNlcnZlV2hpdGVzcGFjZXM6IGZhbHNlLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgaG9zdDoge1xuICAgIGNsYXNzOiAnYW50LWltYWdlLXByZXZpZXctcm9vdCcsXG4gICAgJ1tjbGFzcy5hbnQtaW1hZ2UtcHJldmlldy1tb3ZpbmddJzogJ2lzRHJhZ2dpbmcnLFxuICAgICdbc3R5bGUuekluZGV4XSc6ICdjb25maWcubnpaSW5kZXgnLFxuICAgICdbQC5kaXNhYmxlZF0nOiAnY29uZmlnLm56Tm9BbmltYXRpb24nLFxuICAgICdbQGZhZGVNb3Rpb25dJzogYHZpc2libGUgPyAnZW50ZXInIDogJ2xlYXZlJ2AsXG4gICAgJyhAZmFkZU1vdGlvbi5zdGFydCknOiAnb25BbmltYXRpb25TdGFydCgkZXZlbnQpJyxcbiAgICAnKEBmYWRlTW90aW9uLmRvbmUpJzogJ29uQW5pbWF0aW9uRG9uZSgkZXZlbnQpJ1xuICB9LFxuICBpbXBvcnRzOiBbTnpJY29uTW9kdWxlLCBDZGtEcmFnSGFuZGxlLCBDZGtEcmFnXSxcbiAgcHJvdmlkZXJzOiBbTnpEZXN0cm95U2VydmljZV1cbn0pXG5leHBvcnQgY2xhc3MgTnpJbWFnZVByZXZpZXdDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICByZWFkb25seSBfZGVmYXVsdE56Wm9vbSA9IE5aX0RFRkFVTFRfWk9PTTtcbiAgcmVhZG9ubHkgX2RlZmF1bHROelNjYWxlU3RlcCA9IE5aX0RFRkFVTFRfU0NBTEVfU1RFUDtcbiAgcmVhZG9ubHkgX2RlZmF1bHROelJvdGF0ZSA9IE5aX0RFRkFVTFRfUk9UQVRFO1xuXG4gIGltYWdlczogTnpJbWFnZVtdID0gW107XG4gIGluZGV4ID0gMDtcbiAgaXNEcmFnZ2luZyA9IGZhbHNlO1xuICB2aXNpYmxlID0gdHJ1ZTtcbiAgYW5pbWF0aW9uU3RhdGVDaGFuZ2VkID0gbmV3IEV2ZW50RW1pdHRlcjxBbmltYXRpb25FdmVudD4oKTtcbiAgc2NhbGVTdGVwTWFwOiBNYXA8TnpJbWFnZVVybCwgTnpJbWFnZVNjYWxlU3RlcD4gPSBuZXcgTWFwPE56SW1hZ2VVcmwsIE56SW1hZ2VTY2FsZVN0ZXA+KCk7XG5cbiAgcHJldmlld0ltYWdlVHJhbnNmb3JtID0gJyc7XG4gIHByZXZpZXdJbWFnZVdyYXBwZXJUcmFuc2Zvcm0gPSAnJztcbiAgb3BlcmF0aW9uczogTnpJbWFnZUNvbnRhaW5lck9wZXJhdGlvbltdID0gW1xuICAgIHtcbiAgICAgIGljb246ICdjbG9zZScsXG4gICAgICBvbkNsaWNrOiAoKSA9PiB7XG4gICAgICAgIHRoaXMub25DbG9zZSgpO1xuICAgICAgfSxcbiAgICAgIHR5cGU6ICdjbG9zZSdcbiAgICB9LFxuICAgIHtcbiAgICAgIGljb246ICd6b29tLWluJyxcbiAgICAgIG9uQ2xpY2s6ICgpID0+IHtcbiAgICAgICAgdGhpcy5vblpvb21JbigpO1xuICAgICAgfSxcbiAgICAgIHR5cGU6ICd6b29tSW4nXG4gICAgfSxcbiAgICB7XG4gICAgICBpY29uOiAnem9vbS1vdXQnLFxuICAgICAgb25DbGljazogKCkgPT4ge1xuICAgICAgICB0aGlzLm9uWm9vbU91dCgpO1xuICAgICAgfSxcbiAgICAgIHR5cGU6ICd6b29tT3V0J1xuICAgIH0sXG4gICAge1xuICAgICAgaWNvbjogJ3JvdGF0ZS1yaWdodCcsXG4gICAgICBvbkNsaWNrOiAoKSA9PiB7XG4gICAgICAgIHRoaXMub25Sb3RhdGVSaWdodCgpO1xuICAgICAgfSxcbiAgICAgIHR5cGU6ICdyb3RhdGVSaWdodCdcbiAgICB9LFxuICAgIHtcbiAgICAgIGljb246ICdyb3RhdGUtbGVmdCcsXG4gICAgICBvbkNsaWNrOiAoKSA9PiB7XG4gICAgICAgIHRoaXMub25Sb3RhdGVMZWZ0KCk7XG4gICAgICB9LFxuICAgICAgdHlwZTogJ3JvdGF0ZUxlZnQnXG4gICAgfSxcbiAgICB7XG4gICAgICBpY29uOiAnc3dhcCcsXG4gICAgICBvbkNsaWNrOiAoKSA9PiB7XG4gICAgICAgIHRoaXMub25Ib3Jpem9udGFsRmxpcCgpO1xuICAgICAgfSxcbiAgICAgIHR5cGU6ICdmbGlwSG9yaXpvbnRhbGx5J1xuICAgIH0sXG4gICAge1xuICAgICAgaWNvbjogJ3N3YXAnLFxuICAgICAgb25DbGljazogKCkgPT4ge1xuICAgICAgICB0aGlzLm9uVmVydGljYWxGbGlwKCk7XG4gICAgICB9LFxuICAgICAgdHlwZTogJ2ZsaXBWZXJ0aWNhbGx5JyxcbiAgICAgIHJvdGF0ZTogOTBcbiAgICB9XG4gIF07XG5cbiAgem9vbU91dERpc2FibGVkID0gZmFsc2U7XG4gIHBvc2l0aW9uID0geyAuLi5pbml0aWFsUG9zaXRpb24gfTtcbiAgcHJldmlld1JlZiE6IE56SW1hZ2VQcmV2aWV3UmVmO1xuICBjbG9zZUNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuXG4gIEBWaWV3Q2hpbGQoJ2ltZ1JlZicpIGltYWdlUmVmITogRWxlbWVudFJlZjxIVE1MSW1hZ2VFbGVtZW50PjtcbiAgQFZpZXdDaGlsZCgnaW1hZ2VQcmV2aWV3V3JhcHBlcicsIHsgc3RhdGljOiB0cnVlIH0pIGltYWdlUHJldmlld1dyYXBwZXIhOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcblxuICBwcml2YXRlIHpvb206IG51bWJlcjtcbiAgcHJpdmF0ZSByb3RhdGU6IG51bWJlcjtcbiAgcHJpdmF0ZSBzY2FsZVN0ZXA6IG51bWJlcjtcbiAgcHJpdmF0ZSBmbGlwSG9yaXpvbnRhbGx5OiBib29sZWFuO1xuICBwcml2YXRlIGZsaXBWZXJ0aWNhbGx5OiBib29sZWFuO1xuXG4gIGdldCBhbmltYXRpb25EaXNhYmxlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWcubnpOb0FuaW1hdGlvbiA/PyBmYWxzZTtcbiAgfVxuXG4gIGdldCBtYXNrQ2xvc2FibGUoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgZGVmYXVsdENvbmZpZzogTnpTYWZlQW55ID0gdGhpcy5uekNvbmZpZ1NlcnZpY2UuZ2V0Q29uZmlnRm9yQ29tcG9uZW50KE5aX0NPTkZJR19NT0RVTEVfTkFNRSkgfHwge307XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLm56TWFza0Nsb3NhYmxlID8/IGRlZmF1bHRDb25maWcubnpNYXNrQ2xvc2FibGUgPz8gdHJ1ZTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgbmdab25lOiBOZ1pvbmUsXG4gICAgcHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxuICAgIHB1YmxpYyBuekNvbmZpZ1NlcnZpY2U6IE56Q29uZmlnU2VydmljZSxcbiAgICBwdWJsaWMgY29uZmlnOiBOekltYWdlUHJldmlld09wdGlvbnMsXG4gICAgcHJpdmF0ZSBkZXN0cm95JDogTnpEZXN0cm95U2VydmljZSxcbiAgICBwcml2YXRlIHNhbml0aXplcjogRG9tU2FuaXRpemVyXG4gICkge1xuICAgIHRoaXMuem9vbSA9IHRoaXMuY29uZmlnLm56Wm9vbSA/PyB0aGlzLl9kZWZhdWx0Tnpab29tO1xuICAgIHRoaXMuc2NhbGVTdGVwID0gdGhpcy5jb25maWcubnpTY2FsZVN0ZXAgPz8gdGhpcy5fZGVmYXVsdE56U2NhbGVTdGVwO1xuICAgIHRoaXMucm90YXRlID0gdGhpcy5jb25maWcubnpSb3RhdGUgPz8gdGhpcy5fZGVmYXVsdE56Um90YXRlO1xuICAgIHRoaXMuZmxpcEhvcml6b250YWxseSA9IHRoaXMuY29uZmlnLm56RmxpcEhvcml6b250YWxseSA/PyBmYWxzZTtcbiAgICB0aGlzLmZsaXBWZXJ0aWNhbGx5ID0gdGhpcy5jb25maWcubnpGbGlwVmVydGljYWxseSA/PyBmYWxzZTtcbiAgICB0aGlzLnVwZGF0ZVpvb21PdXREaXNhYmxlZCgpO1xuICAgIHRoaXMudXBkYXRlUHJldmlld0ltYWdlVHJhbnNmb3JtKCk7XG4gICAgdGhpcy51cGRhdGVQcmV2aWV3SW1hZ2VXcmFwcGVyVHJhbnNmb3JtKCk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICBmcm9tRXZlbnQodGhpcy5pbWFnZVByZXZpZXdXcmFwcGVyLm5hdGl2ZUVsZW1lbnQsICdtb3VzZWRvd24nKVxuICAgICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXG4gICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IHRydWU7XG4gICAgICAgIH0pO1xuXG4gICAgICBmcm9tRXZlbnQ8V2hlZWxFdmVudD4odGhpcy5pbWFnZVByZXZpZXdXcmFwcGVyLm5hdGl2ZUVsZW1lbnQsICd3aGVlbCcpXG4gICAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcbiAgICAgICAgLnN1YnNjcmliZShldmVudCA9PiB7XG4gICAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHRoaXMud2hlZWxab29tRXZlbnRIYW5kbGVyKGV2ZW50KSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgc2V0SW1hZ2VzKGltYWdlczogTnpJbWFnZVtdLCBzY2FsZVN0ZXBNYXA/OiBNYXA8c3RyaW5nLCBudW1iZXI+KTogdm9pZCB7XG4gICAgaWYgKHNjYWxlU3RlcE1hcCkgdGhpcy5zY2FsZVN0ZXBNYXAgPSBzY2FsZVN0ZXBNYXA7XG4gICAgdGhpcy5pbWFnZXMgPSBpbWFnZXM7XG4gICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIHN3aXRjaFRvKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmluZGV4ID0gaW5kZXg7XG4gICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIG5leHQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaW5kZXggPCB0aGlzLmltYWdlcy5sZW5ndGggLSAxKSB7XG4gICAgICB0aGlzLnJlc2V0KCk7XG4gICAgICB0aGlzLmluZGV4Kys7XG4gICAgICB0aGlzLnVwZGF0ZVByZXZpZXdJbWFnZVRyYW5zZm9ybSgpO1xuICAgICAgdGhpcy51cGRhdGVQcmV2aWV3SW1hZ2VXcmFwcGVyVHJhbnNmb3JtKCk7XG4gICAgICB0aGlzLnVwZGF0ZVpvb21PdXREaXNhYmxlZCgpO1xuICAgICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgICB9XG4gIH1cblxuICBwcmV2KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmluZGV4ID4gMCkge1xuICAgICAgdGhpcy5yZXNldCgpO1xuICAgICAgdGhpcy5pbmRleC0tO1xuICAgICAgdGhpcy51cGRhdGVQcmV2aWV3SW1hZ2VUcmFuc2Zvcm0oKTtcbiAgICAgIHRoaXMudXBkYXRlUHJldmlld0ltYWdlV3JhcHBlclRyYW5zZm9ybSgpO1xuICAgICAgdGhpcy51cGRhdGVab29tT3V0RGlzYWJsZWQoKTtcbiAgICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gICAgfVxuICB9XG5cbiAgbWFya0ZvckNoZWNrKCk6IHZvaWQge1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgb25DbG9zZSgpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2libGUgPSBmYWxzZTtcbiAgICB0aGlzLmNsb3NlQ2xpY2suZW1pdCgpO1xuICB9XG5cbiAgb25ab29tSW4oKTogdm9pZCB7XG4gICAgY29uc3Qgem9vbVN0ZXAgPVxuICAgICAgdGhpcy5zY2FsZVN0ZXBNYXAuZ2V0KHRoaXMuaW1hZ2VzW3RoaXMuaW5kZXhdLnNyYyA/PyB0aGlzLmltYWdlc1t0aGlzLmluZGV4XS5zcmNzZXQpID8/IHRoaXMuc2NhbGVTdGVwO1xuICAgIHRoaXMuem9vbSArPSB6b29tU3RlcDtcbiAgICB0aGlzLnVwZGF0ZVByZXZpZXdJbWFnZVRyYW5zZm9ybSgpO1xuICAgIHRoaXMudXBkYXRlWm9vbU91dERpc2FibGVkKCk7XG4gIH1cblxuICBvblpvb21PdXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuem9vbSA+IDEpIHtcbiAgICAgIGNvbnN0IHpvb21TdGVwID1cbiAgICAgICAgdGhpcy5zY2FsZVN0ZXBNYXAuZ2V0KHRoaXMuaW1hZ2VzW3RoaXMuaW5kZXhdLnNyYyA/PyB0aGlzLmltYWdlc1t0aGlzLmluZGV4XS5zcmNzZXQpID8/IHRoaXMuc2NhbGVTdGVwO1xuICAgICAgdGhpcy56b29tIC09IHpvb21TdGVwO1xuICAgICAgdGhpcy51cGRhdGVQcmV2aWV3SW1hZ2VUcmFuc2Zvcm0oKTtcbiAgICAgIHRoaXMudXBkYXRlWm9vbU91dERpc2FibGVkKCk7XG5cbiAgICAgIGlmICh0aGlzLnpvb20gPD0gMSkge1xuICAgICAgICB0aGlzLnJlQ2VudGVySW1hZ2UoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBvblJvdGF0ZVJpZ2h0KCk6IHZvaWQge1xuICAgIHRoaXMucm90YXRlICs9IDkwO1xuICAgIHRoaXMudXBkYXRlUHJldmlld0ltYWdlVHJhbnNmb3JtKCk7XG4gIH1cblxuICBvblJvdGF0ZUxlZnQoKTogdm9pZCB7XG4gICAgdGhpcy5yb3RhdGUgLT0gOTA7XG4gICAgdGhpcy51cGRhdGVQcmV2aWV3SW1hZ2VUcmFuc2Zvcm0oKTtcbiAgfVxuXG4gIG9uU3dpdGNoTGVmdChldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgdGhpcy5wcmV2KCk7XG4gIH1cblxuICBvblN3aXRjaFJpZ2h0KGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLm5leHQoKTtcbiAgfVxuXG4gIG9uSG9yaXpvbnRhbEZsaXAoKTogdm9pZCB7XG4gICAgdGhpcy5mbGlwSG9yaXpvbnRhbGx5ID0gIXRoaXMuZmxpcEhvcml6b250YWxseTtcbiAgICB0aGlzLnVwZGF0ZVByZXZpZXdJbWFnZVRyYW5zZm9ybSgpO1xuICB9XG5cbiAgb25WZXJ0aWNhbEZsaXAoKTogdm9pZCB7XG4gICAgdGhpcy5mbGlwVmVydGljYWxseSA9ICF0aGlzLmZsaXBWZXJ0aWNhbGx5O1xuICAgIHRoaXMudXBkYXRlUHJldmlld0ltYWdlVHJhbnNmb3JtKCk7XG4gIH1cblxuICB3aGVlbFpvb21FdmVudEhhbmRsZXIoZXZlbnQ6IFdoZWVsRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgdGhpcy5oYW5kbGVySW1hZ2VUcmFuc2Zvcm1hdGlvbldoaWxlWm9vbWluZ1dpdGhNb3VzZShldmVudCwgZXZlbnQuZGVsdGFZKTtcbiAgICB0aGlzLmhhbmRsZUltYWdlU2NhbGVXaGlsZVpvb21pbmdXaXRoTW91c2UoZXZlbnQuZGVsdGFZKTtcblxuICAgIHRoaXMudXBkYXRlUHJldmlld0ltYWdlV3JhcHBlclRyYW5zZm9ybSgpO1xuICAgIHRoaXMudXBkYXRlUHJldmlld0ltYWdlVHJhbnNmb3JtKCk7XG5cbiAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgb25BbmltYXRpb25TdGFydChldmVudDogQW5pbWF0aW9uRXZlbnQpOiB2b2lkIHtcbiAgICB0aGlzLmFuaW1hdGlvblN0YXRlQ2hhbmdlZC5lbWl0KGV2ZW50KTtcbiAgfVxuXG4gIG9uQW5pbWF0aW9uRG9uZShldmVudDogQW5pbWF0aW9uRXZlbnQpOiB2b2lkIHtcbiAgICB0aGlzLmFuaW1hdGlvblN0YXRlQ2hhbmdlZC5lbWl0KGV2ZW50KTtcbiAgfVxuXG4gIG9uRHJhZ0VuZChldmVudDogQ2RrRHJhZ0VuZCk6IHZvaWQge1xuICAgIHRoaXMuaXNEcmFnZ2luZyA9IGZhbHNlO1xuICAgIGNvbnN0IHdpZHRoID0gdGhpcy5pbWFnZVJlZi5uYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoICogdGhpcy56b29tO1xuICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuaW1hZ2VSZWYubmF0aXZlRWxlbWVudC5vZmZzZXRIZWlnaHQgKiB0aGlzLnpvb207XG4gICAgY29uc3QgeyBsZWZ0LCB0b3AgfSA9IGdldE9mZnNldCh0aGlzLmltYWdlUmVmLm5hdGl2ZUVsZW1lbnQpO1xuICAgIGNvbnN0IHsgd2lkdGg6IGNsaWVudFdpZHRoLCBoZWlnaHQ6IGNsaWVudEhlaWdodCB9ID0gZ2V0Q2xpZW50U2l6ZSgpO1xuICAgIGNvbnN0IGlzUm90YXRlID0gdGhpcy5yb3RhdGUgJSAxODAgIT09IDA7XG4gICAgY29uc3QgZml0Q29udGVudFBhcmFtcyA9IHtcbiAgICAgIHdpZHRoOiBpc1JvdGF0ZSA/IGhlaWdodCA6IHdpZHRoLFxuICAgICAgaGVpZ2h0OiBpc1JvdGF0ZSA/IHdpZHRoIDogaGVpZ2h0LFxuICAgICAgbGVmdCxcbiAgICAgIHRvcCxcbiAgICAgIGNsaWVudFdpZHRoLFxuICAgICAgY2xpZW50SGVpZ2h0XG4gICAgfTtcbiAgICBjb25zdCBmaXRDb250ZW50UG9zID0gZ2V0Rml0Q29udGVudFBvc2l0aW9uKGZpdENvbnRlbnRQYXJhbXMpO1xuICAgIGlmIChpc05vdE5pbChmaXRDb250ZW50UG9zLngpIHx8IGlzTm90TmlsKGZpdENvbnRlbnRQb3MueSkpIHtcbiAgICAgIHRoaXMucG9zaXRpb24gPSB7IC4uLnRoaXMucG9zaXRpb24sIC4uLmZpdENvbnRlbnRQb3MgfTtcbiAgICB9IGVsc2UgaWYgKCFpc05vdE5pbChmaXRDb250ZW50UG9zLngpICYmICFpc05vdE5pbChmaXRDb250ZW50UG9zLnkpKSB7XG4gICAgICB0aGlzLnBvc2l0aW9uID0ge1xuICAgICAgICB4OiBldmVudC5zb3VyY2UuZ2V0RnJlZURyYWdQb3NpdGlvbigpLngsXG4gICAgICAgIHk6IGV2ZW50LnNvdXJjZS5nZXRGcmVlRHJhZ1Bvc2l0aW9uKCkueVxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBzYW5pdGl6ZXJSZXNvdXJjZVVybCh1cmw6IHN0cmluZyk6IFNhZmVSZXNvdXJjZVVybCB7XG4gICAgcmV0dXJuIHRoaXMuc2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RSZXNvdXJjZVVybCh1cmwpO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVQcmV2aWV3SW1hZ2VUcmFuc2Zvcm0oKTogdm9pZCB7XG4gICAgdGhpcy5wcmV2aWV3SW1hZ2VUcmFuc2Zvcm0gPSBgc2NhbGUzZCgke3RoaXMuem9vbSAqICh0aGlzLmZsaXBIb3Jpem9udGFsbHkgPyAtMSA6IDEpfSwgJHtcbiAgICAgIHRoaXMuem9vbSAqICh0aGlzLmZsaXBWZXJ0aWNhbGx5ID8gLTEgOiAxKVxuICAgIH0sIDEpIHJvdGF0ZSgke3RoaXMucm90YXRlfWRlZylgO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVQcmV2aWV3SW1hZ2VXcmFwcGVyVHJhbnNmb3JtKCk6IHZvaWQge1xuICAgIHRoaXMucHJldmlld0ltYWdlV3JhcHBlclRyYW5zZm9ybSA9IGB0cmFuc2xhdGUzZCgke3RoaXMucG9zaXRpb24ueH1weCwgJHt0aGlzLnBvc2l0aW9uLnl9cHgsIDApYDtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlWm9vbU91dERpc2FibGVkKCk6IHZvaWQge1xuICAgIHRoaXMuem9vbU91dERpc2FibGVkID0gdGhpcy56b29tIDw9IDE7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZXJJbWFnZVRyYW5zZm9ybWF0aW9uV2hpbGVab29taW5nV2l0aE1vdXNlKGV2ZW50OiBXaGVlbEV2ZW50LCBkZWx0YVk6IG51bWJlcik6IHZvaWQge1xuICAgIGxldCBzY2FsZVZhbHVlOiBudW1iZXI7XG4gICAgY29uc3QgaW1hZ2VFbGVtZW50ID0gdGhpcy5pbWFnZVJlZi5uYXRpdmVFbGVtZW50O1xuXG4gICAgY29uc3QgZWxlbWVudFRyYW5zZm9ybSA9IGdldENvbXB1dGVkU3R5bGUoaW1hZ2VFbGVtZW50KS50cmFuc2Zvcm07XG4gICAgY29uc3QgbWF0cml4VmFsdWUgPSBlbGVtZW50VHJhbnNmb3JtLm1hdGNoKC9tYXRyaXguKlxcKCguKylcXCkvKTtcblxuICAgIGlmIChtYXRyaXhWYWx1ZSkge1xuICAgICAgc2NhbGVWYWx1ZSA9ICttYXRyaXhWYWx1ZVsxXS5zcGxpdCgnLCAnKVswXTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2NhbGVWYWx1ZSA9IHRoaXMuem9vbTtcbiAgICB9XG5cbiAgICBjb25zdCB4ID0gKGV2ZW50LmNsaWVudFggLSBpbWFnZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkueCkgLyBzY2FsZVZhbHVlO1xuICAgIGNvbnN0IHkgPSAoZXZlbnQuY2xpZW50WSAtIGltYWdlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS55KSAvIHNjYWxlVmFsdWU7XG4gICAgY29uc3QgaGFsZk9mU2NhbGVTdGVwVmFsdWUgPSBkZWx0YVkgPCAwID8gdGhpcy5zY2FsZVN0ZXAgLyAyIDogLXRoaXMuc2NhbGVTdGVwIC8gMjtcblxuICAgIHRoaXMucG9zaXRpb24ueCArPSAteCAqIGhhbGZPZlNjYWxlU3RlcFZhbHVlICogMiArIGltYWdlRWxlbWVudC5vZmZzZXRXaWR0aCAqIGhhbGZPZlNjYWxlU3RlcFZhbHVlO1xuICAgIHRoaXMucG9zaXRpb24ueSArPSAteSAqIGhhbGZPZlNjYWxlU3RlcFZhbHVlICogMiArIGltYWdlRWxlbWVudC5vZmZzZXRIZWlnaHQgKiBoYWxmT2ZTY2FsZVN0ZXBWYWx1ZTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlSW1hZ2VTY2FsZVdoaWxlWm9vbWluZ1dpdGhNb3VzZShkZWx0YVk6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICh0aGlzLmlzWm9vbWVkSW5XaXRoTW91c2VXaGVlbChkZWx0YVkpKSB7XG4gICAgICB0aGlzLm9uWm9vbUluKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMub25ab29tT3V0KCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuem9vbSA8PSAxKSB7XG4gICAgICB0aGlzLnJlQ2VudGVySW1hZ2UoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzWm9vbWVkSW5XaXRoTW91c2VXaGVlbChkZWx0YTogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGRlbHRhIDwgMDtcbiAgfVxuXG4gIHByaXZhdGUgcmVzZXQoKTogdm9pZCB7XG4gICAgdGhpcy56b29tID0gdGhpcy5jb25maWcubnpab29tID8/IHRoaXMuX2RlZmF1bHROelpvb207XG4gICAgdGhpcy5zY2FsZVN0ZXAgPSB0aGlzLmNvbmZpZy5uelNjYWxlU3RlcCA/PyB0aGlzLl9kZWZhdWx0TnpTY2FsZVN0ZXA7XG4gICAgdGhpcy5yb3RhdGUgPSB0aGlzLmNvbmZpZy5uelJvdGF0ZSA/PyB0aGlzLl9kZWZhdWx0TnpSb3RhdGU7XG4gICAgdGhpcy5mbGlwSG9yaXpvbnRhbGx5ID0gZmFsc2U7XG4gICAgdGhpcy5mbGlwVmVydGljYWxseSA9IGZhbHNlO1xuICAgIHRoaXMucmVDZW50ZXJJbWFnZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSByZUNlbnRlckltYWdlKCk6IHZvaWQge1xuICAgIHRoaXMucG9zaXRpb24gPSB7IC4uLmluaXRpYWxQb3NpdGlvbiB9O1xuICB9XG59XG4iXX0=