UNPKG

image-resizer-cropper

Version:

A simple image crop with resizing built for Angular 7, compatible with Angular Universal (SSR).

493 lines (492 loc) 50.1 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ import { Component, Input, ElementRef, Renderer2, Inject, PLATFORM_ID, Output, EventEmitter } from "@angular/core"; import { isPlatformBrowser } from "@angular/common"; export class ImageResizerCropperComponent { /** * @param {?} _el * @param {?} _renderer * @param {?} platformId */ constructor(_el, _renderer, platformId) { this._el = _el; this._renderer = _renderer; this.platformId = platformId; this.croppedImage = new EventEmitter(null); this.error = new EventEmitter(null); this.isDown = false; this.offSet = []; this.isBrowser = isPlatformBrowser(this.platformId); if (this.isBrowser) { this.canvasOne = this._renderer.createElement("canvas"); this.contextOne = this.canvasOne.getContext("2d"); this.canvasTwo = this._renderer.createElement("canvas"); this.contextTwo = this.canvasTwo.getContext("2d"); this.canvasThree = this._renderer.createElement("canvas"); this.contextThree = this.canvasThree.getContext("2d"); this.canvasFour = this._renderer.createElement("canvas"); this.contextFour = this.canvasFour.getContext("2d"); this.imgOne = this._renderer.createElement("img"); this.imgTwo = this._renderer.createElement("img"); } } /** * @return {?} */ get crContainer() { return this._el.nativeElement.querySelector(".cr-container"); } /** * @return {?} */ get crRange() { return this._el.nativeElement.querySelector("#cr-range"); } /** * @return {?} */ get crImage() { return this._el.nativeElement.querySelector("#cr-image"); } /** * @return {?} */ get crLens() { return this._el.nativeElement.querySelector("#cr-lens"); } /** * @return {?} */ get btn() { return this._el.nativeElement.querySelector("#crop"); } /** * @return {?} */ get testImg() { return this._el.nativeElement.querySelector("#test-img"); } /** * @return {?} */ get finalCrop() { return this._el.nativeElement.querySelector("#final-crop"); } /** * @return {?} */ get fileUpload() { return this._el.nativeElement.querySelector("#file-upload"); } /** * @return {?} */ ngOnInit() { if (this.sourceImage) { if (this.sourceImage.target && this.sourceImage.target.files) { this.parseFile(this.sourceImage); } } } /** * @return {?} */ ngAfterViewInit() { if (this.sourceImage) { if (this.imgOne) { this._renderer.setProperty(this.imgOne, "src", this.crImage.getAttribute("src")); } this.setUpListeners(); this.setUpConfigurations(); } } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { if (changes["sourceImage"] && !changes["sourceImage"].firstChange && changes["sourceImage"].currentValue) { this.clearImagePosition(); if (changes["sourceImage"].currentValue.target && changes["sourceImage"].currentValue.target.files) { this.parseFile(this.sourceImage); } else { if (this.imgOne) { this._renderer.setProperty(this.imgOne, "src", this.crImage.getAttribute("src")); this.setUpListeners(); this.setUpConfigurations(); } } } } /** * @return {?} */ setUpListeners() { if (this.isBrowser) { this._renderer.listen(this.crRange, "input", event => { this.linkImageToRangeInput(event.target.value); }); this._renderer.listen(this.crImage, "mousedown", event => { this.mouseDownOnImage(event); }); this._renderer.listen(this.crImage, "mouseup", event => { this.mouseUpOnImage(); if (this.autoCrop) { this.resizeAndCropImage(); } }); this._renderer.listen(this.crImage, "mousemove", event => { event.preventDefault(); this.mouseMoveOnImage(event); }); this._renderer.listen(this.crContainer, "mouseout", event => { this.keepMouseMoveInsideContainer(); }); this._renderer.listen(this.btn, "click", event => { this.resizeAndCropImage(); }); } } /** * @return {?} */ setUpConfigurations() { this.setBorderColor(); this.setBackgroundOpacity(); this.setLensHeightAndWidth(); } /** * @param {?} value * @return {?} */ linkImageToRangeInput(value) { /** @type {?} */ const val = value / 100; this.crImage.style.transform = `scale(${val})`; } /** * @param {?} event * @return {?} */ mouseDownOnImage(event) { this.isDown = true; this.offSet = [ event.target.offsetLeft - event.clientX, event.target.offsetTop - event.clientY ]; } /** * @return {?} */ mouseUpOnImage() { this.isDown = false; } /** * @param {?} event * @return {?} */ mouseMoveOnImage(event) { if (this.isDown) { /** @type {?} */ const mousePosition = { x: event.clientX, y: event.clientY }; this.crImage.style.left = mousePosition.x + this.offSet[0] + "px"; this.crImage.style.top = mousePosition.y + this.offSet[1] + "px"; } } /** * @return {?} */ keepMouseMoveInsideContainer() { this.isDown = false; } /** * @param {?} e1 * @param {?} e2 * @return {?} */ checkForOverlap(e1, e2) { if (e1.length && e1.length > 1) { e1 = e1[0]; } if (e2.length && e2.length > 1) { e2 = e2[0]; } /** @type {?} */ const rect1 = e1 instanceof Element ? e1.getBoundingClientRect() : false; /** @type {?} */ const rect2 = e2 instanceof Element ? e2.getBoundingClientRect() : false; /** @type {?} */ let overlap = null; if (rect1 && rect2) { overlap = !(rect1.right < rect2.left || rect1.left > rect2.right || rect1.bottom < rect2.top || rect1.top > rect2.bottom); return [overlap, rect1, rect2]; } else { return [overlap, rect1, rect2]; } } /** * @return {?} */ getResizeRatio() { /** @type {?} */ const transform = this.crImage.style.transform; /** @type {?} */ const matrix = transform .substring(transform.indexOf("(") + 1, transform.indexOf(")")) .split(","); return matrix.length > 0 ? matrix[0] : null; } /** * @return {?} */ drawImageResize() { /** @type {?} */ const ratio = this.getResizeRatio(); this.canvasTwo.width = this.imgOne.width; this.canvasTwo.height = this.imgOne.height; this.contextTwo.drawImage(this.imgOne, 0, 0); this.canvasOne.width = this.imgOne.width * ratio; this.canvasOne.height = this.imgOne.height * ratio; this.contextOne.drawImage(this.canvasTwo, 0, 0, this.canvasTwo.width, this.canvasTwo.height, 0, 0, this.canvasOne.width, this.canvasOne.height); /** @type {?} */ const i = this.canvasOne.toDataURL("image/png", 100); if (this.testImg) { this._renderer.setProperty(this.testImg, "src", i); } return i; } /** * @param {?} src * @return {?} */ drawImageCrop(src) { /** @type {?} */ const overlap = this.checkForOverlap(this.crLens, this.crImage); if (this.imgTwo) { this._renderer.setProperty(this.imgTwo, "src", src); return new Promise((resolve, reject) => { this._renderer.listen(this.imgTwo, "load", event => { this.canvasThree.width = event.target.width; this.canvasThree.height = event.target.height; this.contextThree.drawImage(this.imgTwo, 0, 0); this.canvasFour.width = this.lensWidth; this.canvasFour.height = this.lensHeight; if (overlap) { /** @type {?} */ const xCrop = overlap[1]["x"] - overlap[2]["x"]; /** @type {?} */ const yCrop = overlap[1]["y"] - overlap[2]["y"]; this.contextFour.drawImage(this.canvasThree, xCrop, yCrop, this.lensWidth, this.lensHeight, 0, 0, this.lensWidth, this.lensHeight); if (this.roundCrop) { this.contextFour.globalCompositeOperation = "destination-in"; this.contextFour.beginPath(); this.contextFour.arc(this.lensWidth / 2, this.lensHeight / 2, this.lensHeight / 2, 0, Math.PI * 2); this.contextFour.closePath(); this.contextFour.fill(); } /** @type {?} */ const b = this.canvasFour.toDataURL("image/png", 100); this.cropAvailable = true; setTimeout(() => { if (this.finalCrop) { this._renderer.setProperty(this.finalCrop, "src", b); } }); resolve(b); } }); }); } } /** * @return {?} */ resizeAndCropImage() { /** @type {?} */ const imgSrc = this.drawImageResize(); this.drawImageCrop(imgSrc).then(result => { this.croppedImage.emit(result); console.log(result); }); } /** * @return {?} */ setLensHeightAndWidth() { if (this.lensHeight && this.lensHeight !== 150) { this._renderer.setStyle(this.crLens, "height", this.lensHeight + "px"); } if (this.lensWidth && this.lensWidth !== 150) { this._renderer.setStyle(this.crLens, "width", this.lensWidth + "px"); } if (this.roundCrop) { this._renderer.addClass(this.crLens, "rounded"); } } /** * @return {?} */ setBorderColor() { if (this.borderColor) { this._renderer.setStyle(this.crContainer, "border-color", this.borderColor); this._renderer.setStyle(this.crLens, "border-color", this.borderColor); /** @type {?} */ const spans = this.crLens.querySelectorAll("span"); spans.forEach(element => { this._renderer.setStyle(element, "border-color", this.borderColor); }); } } /** * @return {?} */ setBackgroundOpacity() { if (this.backgroundOpacity && this.crLens) { this._renderer.setStyle(this.crLens, "box-shadow", "0 0 0 200000px rgba(0, 0, 0, " + this.backgroundOpacity + ")"); } } /** * @param {?} event * @return {?} */ parseFile(event) { /** @type {?} */ const file = event.target.files[0]; if (file.type === "image/png" || file.type === "image/jpeg" || file.type === "image/gif" || file.type === "image/tiff") { /** @type {?} */ const reader = new FileReader(); reader.readAsDataURL(file); reader.addEventListener("load", e => { /** @type {?} */ const val = reader.result.toString(); this._renderer.setProperty(this.crImage, "src", val); this.loadedSourceImage = this.crImage.getAttribute("src"); this._renderer.setProperty(this.imgOne, "src", this.crImage.getAttribute("src")); this.setUpListeners(); this.setUpConfigurations(); }); reader.onerror = function () { console.log("there are some problems"); }; } else { this.loadedSourceImage = null; if (this.crContainer) { this._renderer.addClass(this.crContainer, "error"); } this.errorMessage = "Invalid file type."; this.error.emit(this.errorMessage); } } /** * @return {?} */ clearImagePosition() { if (this.crImage) { this.crImage.style.left = "auto"; this.crImage.style.top = "auto"; } } } ImageResizerCropperComponent.decorators = [ { type: Component, args: [{ selector: "irc-image-resizer-cropper", template: "<ng-container *ngIf=\"sourceImage\">\n <div class=\"cr-container\">\n <div id=\"cr-lens\">\n <span></span>\n <span></span>\n <span></span>\n <span></span>\n </div>\n <img\n src=\"{{ loadedSourceImage }}\"\n style=\"transform: scale(1);\"\n draggable=\"false\"\n id=\"cr-image\"\n />\n <div *ngIf=\"errorMessage\" id=\"error-message\">{{ errorMessage }}</div>\n </div>\n <div class=\"cr-range-selector\">\n <input type=\"range\" id=\"cr-range\" min=\"10\" max=\"200\" />\n </div>\n <div class=\"text-center\">\n <button id=\"crop\" type=\"button\">Crop</button>\n </div>\n <div>\n <img src=\"#\" id=\"test-img\" style=\"display:none;\" />\n <img src=\"#\" *ngIf=\"previewCrop && cropAvailable\" id=\"final-crop\" />\n </div>\n</ng-container>\n", styles: [".text-center{text-align:center}.cr-container{display:-webkit-box;display:flex;-webkit-box-align:center;align-items:center;-webkit-box-pack:center;justify-content:center;position:relative;min-height:300px;margin:0 auto;overflow:hidden;border:2px dashed #333}.cr-range-selector{margin:1rem 0;text-align:center}#cr-lens{height:150px;width:150px;border:2px solid #333;z-index:999999;box-shadow:0 0 0 200000px rgba(0,0,0,.2);position:relative}#cr-lens.rounded{border-radius:50%}#cr-lens span{position:absolute;width:15px;height:15px}#cr-lens span:nth-child(1){top:-17px;left:-17px;border-right:2px dashed #333;border-bottom:2px dashed #333}#cr-lens span:nth-child(2){top:-17px;right:-17px;border-left:2px dashed #333;border-bottom:2px dashed #333}#cr-lens span:nth-child(3){bottom:-17px;right:-17px;border-left:2px dashed #333;border-top:2px dashed #333}#cr-lens span:nth-child(4){bottom:-17px;left:-17px;border-right:2px dashed #333;border-top:2px dashed #333}#cr-image{display:block;position:absolute;-webkit-transform-origin:center center;transform-origin:center center;cursor:move}"] }] } ]; /** @nocollapse */ ImageResizerCropperComponent.ctorParameters = () => [ { type: ElementRef }, { type: Renderer2 }, { type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] } ]; ImageResizerCropperComponent.propDecorators = { sourceImage: [{ type: Input }], lensHeight: [{ type: Input }], lensWidth: [{ type: Input }], autoCrop: [{ type: Input }], previewCrop: [{ type: Input }], roundCrop: [{ type: Input }], borderColor: [{ type: Input }], backgroundOpacity: [{ type: Input }], croppedImage: [{ type: Output }], error: [{ type: Output }] }; if (false) { /** @type {?} */ ImageResizerCropperComponent.prototype.isBrowser; /** @type {?} */ ImageResizerCropperComponent.prototype.sourceImage; /** @type {?} */ ImageResizerCropperComponent.prototype.lensHeight; /** @type {?} */ ImageResizerCropperComponent.prototype.lensWidth; /** @type {?} */ ImageResizerCropperComponent.prototype.autoCrop; /** @type {?} */ ImageResizerCropperComponent.prototype.previewCrop; /** @type {?} */ ImageResizerCropperComponent.prototype.roundCrop; /** @type {?} */ ImageResizerCropperComponent.prototype.borderColor; /** @type {?} */ ImageResizerCropperComponent.prototype.backgroundOpacity; /** @type {?} */ ImageResizerCropperComponent.prototype.croppedImage; /** @type {?} */ ImageResizerCropperComponent.prototype.error; /** @type {?} */ ImageResizerCropperComponent.prototype.cropAvailable; /** @type {?} */ ImageResizerCropperComponent.prototype.loadedSourceImage; /** @type {?} */ ImageResizerCropperComponent.prototype.errorMessage; /** @type {?} */ ImageResizerCropperComponent.prototype.isDown; /** @type {?} */ ImageResizerCropperComponent.prototype.offSet; /** @type {?} */ ImageResizerCropperComponent.prototype.imgOne; /** @type {?} */ ImageResizerCropperComponent.prototype.imgTwo; /** @type {?} */ ImageResizerCropperComponent.prototype.canvasOne; /** @type {?} */ ImageResizerCropperComponent.prototype.contextOne; /** @type {?} */ ImageResizerCropperComponent.prototype.canvasTwo; /** @type {?} */ ImageResizerCropperComponent.prototype.contextTwo; /** @type {?} */ ImageResizerCropperComponent.prototype.canvasThree; /** @type {?} */ ImageResizerCropperComponent.prototype.contextThree; /** @type {?} */ ImageResizerCropperComponent.prototype.canvasFour; /** @type {?} */ ImageResizerCropperComponent.prototype.contextFour; /** @type {?} */ ImageResizerCropperComponent.prototype._el; /** @type {?} */ ImageResizerCropperComponent.prototype._renderer; /** @type {?} */ ImageResizerCropperComponent.prototype.platformId; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2UtcmVzaXplci1jcm9wcGVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2ltYWdlLXJlc2l6ZXItY3JvcHBlci8iLCJzb3VyY2VzIjpbImxpYi9pbWFnZS1yZXNpemVyLWNyb3BwZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUVULEtBQUssRUFDTCxVQUFVLEVBQ1YsU0FBUyxFQUVULE1BQU0sRUFDTixXQUFXLEVBQ1gsTUFBTSxFQUNOLFlBQVksRUFHYixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQU9wRCxNQUFNOzs7Ozs7SUFxQ0osWUFDVSxLQUNBLFdBQ3FCLFVBQWtCO1FBRnZDLFFBQUcsR0FBSCxHQUFHO1FBQ0gsY0FBUyxHQUFULFNBQVM7UUFDWSxlQUFVLEdBQVYsVUFBVSxDQUFROzRCQTNCTCxJQUFJLFlBQVksQ0FBTSxJQUFJLENBQUM7cUJBQy9CLElBQUksWUFBWSxDQUFTLElBQUksQ0FBQztzQkFLN0QsS0FBSztzQkFDVSxFQUFFO1FBc0J4QixJQUFJLENBQUMsU0FBUyxHQUFHLGlCQUFpQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUVwRCxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDbEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUN4RCxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRWxELElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDeEQsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxJQUFJ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RUwsTUFBTTtvQkFDTixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBPbkluaXQsXG4gIElucHV0LFxuICBFbGVtZW50UmVmLFxuICBSZW5kZXJlcjIsXG4gIEFmdGVyVmlld0luaXQsXG4gIEluamVjdCxcbiAgUExBVEZPUk1fSUQsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBPbkNoYW5nZXMsXG4gIFNpbXBsZUNoYW5nZXNcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IGlzUGxhdGZvcm1Ccm93c2VyIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vblwiO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwiaXJjLWltYWdlLXJlc2l6ZXItY3JvcHBlclwiLFxuICB0ZW1wbGF0ZVVybDogXCIuL2ltYWdlLXJlc2l6ZXItY3JvcHBlci5jb21wb25lbnQuaHRtbFwiLFxuICBzdHlsZVVybHM6IFtcIi4vaW1hZ2UtcmVzaXplci1jcm9wcGVyLmNvbXBvbmVudC5jc3NcIl1cbn0pXG5leHBvcnQgY2xhc3MgSW1hZ2VSZXNpemVyQ3JvcHBlckNvbXBvbmVudFxuICBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25DaGFuZ2VzIHtcbiAgaXNCcm93c2VyOiBib29sZWFuO1xuXG4gIEBJbnB1dCgpIHNvdXJjZUltYWdlOiBhbnk7XG4gIEBJbnB1dCgpIGxlbnNIZWlnaHQ6IG51bWJlcjtcbiAgQElucHV0KCkgbGVuc1dpZHRoOiBudW1iZXI7XG4gIEBJbnB1dCgpIGF1dG9Dcm9wOiBib29sZWFuO1xuICBASW5wdXQoKSBwcmV2aWV3Q3JvcDogYm9vbGVhbjtcbiAgQElucHV0KCkgcm91bmRDcm9wOiBib29sZWFuO1xuICBASW5wdXQoKSBib3JkZXJDb2xvcjogc3RyaW5nO1xuICBASW5wdXQoKSBiYWNrZ3JvdW5kT3BhY2l0eTogc3RyaW5nO1xuXG4gIEBPdXRwdXQoKSBjcm9wcGVkSW1hZ2U6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KG51bGwpO1xuICBAT3V0cHV0KCkgZXJyb3I6IEV2ZW50RW1pdHRlcjxzdHJpbmc+ID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KG51bGwpO1xuICBjcm9wQXZhaWxhYmxlOiBib29sZWFuO1xuICBsb2FkZWRTb3VyY2VJbWFnZTogYW55O1xuXG4gIGVycm9yTWVzc2FnZTogc3RyaW5nO1xuICBpc0Rvd24gPSBmYWxzZTtcbiAgb2ZmU2V0OiBBcnJheTxudW1iZXI+ID0gW107XG5cbiAgaW1nT25lOiBIVE1MSW1hZ2VFbGVtZW50O1xuICBpbWdUd286IEhUTUxJbWFnZUVsZW1lbnQ7XG5cbiAgY2FudmFzT25lOiBIVE1MQ2FudmFzRWxlbWVudDtcbiAgY29udGV4dE9uZTogYW55O1xuXG4gIGNhbnZhc1R3bzogSFRNTENhbnZhc0VsZW1lbnQ7XG4gIGNvbnRleHRUd286IGFueTtcblxuICBjYW52YXNUaHJlZTogSFRNTENhbnZhc0VsZW1lbnQ7XG4gIGNvbnRleHRUaHJlZTogYW55O1xuXG4gIGNhbnZhc0ZvdXI6IEhUTUxDYW52YXNFbGVtZW50O1xuICBjb250ZXh0Rm91cjogYW55O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX2VsOiBFbGVtZW50UmVmLFxuICAgIHByaXZhdGUgX3JlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBwbGF0Zm9ybUlkOiBPYmplY3RcbiAgKSB7XG4gICAgdGhpcy5pc0Jyb3dzZXIgPSBpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpO1xuXG4gICAgaWYgKHRoaXMuaXNCcm93c2VyKSB7XG4gICAgICB0aGlzLmNhbnZhc09uZSA9IHRoaXMuX3JlbmRlcmVyLmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIik7XG4gICAgICB0aGlzLmNvbnRleHRPbmUgPSB0aGlzLmNhbnZhc09uZS5nZXRDb250ZXh0KFwiMmRcIik7XG5cbiAgICAgIHRoaXMuY2FudmFzVHdvID0gdGhpcy5fcmVuZGVyZXIuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtcbiAgICAgIHRoaXMuY29udGV4dFR3byA9IHRoaXMuY2FudmFzVHdvLmdldENvbnRleHQoXCIyZFwiKTtcblxuICAgICAgdGhpcy5jYW52YXNUaHJlZSA9IHRoaXMuX3JlbmRlcmVyLmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIik7XG4gICAgICB0aGlzLmNvbnRleHRUaHJlZSA9IHRoaXMuY2FudmFzVGhyZWUuZ2V0Q29udGV4dChcIjJkXCIpO1xuXG4gICAgICB0aGlzLmNhbnZhc0ZvdXIgPSB0aGlzLl9yZW5kZXJlci5jcmVhdGVFbGVtZW50KFwiY2FudmFzXCIpO1xuICAgICAgdGhpcy5jb250ZXh0Rm91ciA9IHRoaXMuY2FudmFzRm91ci5nZXRDb250ZXh0KFwiMmRcIik7XG5cbiAgICAgIHRoaXMuaW1nT25lID0gdGhpcy5fcmVuZGVyZXIuY3JlYXRlRWxlbWVudChcImltZ1wiKTtcbiAgICAgIHRoaXMuaW1nVHdvID0gdGhpcy5fcmVuZGVyZXIuY3JlYXRlRWxlbWVudChcImltZ1wiKTtcbiAgICB9XG4gIH1cblxuICBnZXQgY3JDb250YWluZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2VsLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcihcIi5jci1jb250YWluZXJcIik7XG4gIH1cblxuICBnZXQgY3JSYW5nZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fZWwubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKFwiI2NyLXJhbmdlXCIpO1xuICB9XG5cbiAgZ2V0IGNySW1hZ2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2VsLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcihcIiNjci1pbWFnZVwiKTtcbiAgfVxuXG4gIGdldCBjckxlbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2VsLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcihcIiNjci1sZW5zXCIpO1xuICB9XG5cbiAgZ2V0IGJ0bigpIHtcbiAgICByZXR1cm4gdGhpcy5fZWwubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKFwiI2Nyb3BcIik7XG4gIH1cblxuICBnZXQgdGVzdEltZygpIHtcbiAgICByZXR1cm4gdGhpcy5fZWwubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKFwiI3Rlc3QtaW1nXCIpO1xuICB9XG5cbiAgZ2V0IGZpbmFsQ3JvcCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZWwubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKFwiI2ZpbmFsLWNyb3BcIik7XG4gIH1cblxuICBnZXQgZmlsZVVwbG9hZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZWwubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKFwiI2ZpbGUtdXBsb2FkXCIpO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgaWYgKHRoaXMuc291cmNlSW1hZ2UpIHtcbiAgICAgIGlmICh0aGlzLnNvdXJjZUltYWdlLnRhcmdldCAmJiB0aGlzLnNvdXJjZUltYWdlLnRhcmdldC5maWxlcykge1xuICAgICAgICB0aGlzLnBhcnNlRmlsZSh0aGlzLnNvdXJjZUltYWdlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgaWYgKHRoaXMuc291cmNlSW1hZ2UpIHtcbiAgICAgIGlmICh0aGlzLmltZ09uZSkge1xuICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRQcm9wZXJ0eShcbiAgICAgICAgICB0aGlzLmltZ09uZSxcbiAgICAgICAgICBcInNyY1wiLFxuICAgICAgICAgIHRoaXMuY3JJbWFnZS5nZXRBdHRyaWJ1dGUoXCJzcmNcIilcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuc2V0VXBMaXN0ZW5lcnMoKTtcbiAgICAgIHRoaXMuc2V0VXBDb25maWd1cmF0aW9ucygpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBpZiAoXG4gICAgICBjaGFuZ2VzLnNvdXJjZUltYWdlICYmXG4gICAgICAhY2hhbmdlcy5zb3VyY2VJbWFnZS5maXJzdENoYW5nZSAmJlxuICAgICAgY2hhbmdlcy5zb3VyY2VJbWFnZS5jdXJyZW50VmFsdWVcbiAgICApIHtcbiAgICAgIHRoaXMuY2xlYXJJbWFnZVBvc2l0aW9uKCk7XG5cbiAgICAgIGlmIChcbiAgICAgICAgY2hhbmdlcy5zb3VyY2VJbWFnZS5jdXJyZW50VmFsdWUudGFyZ2V0ICYmXG4gICAgICAgIGNoYW5nZXMuc291cmNlSW1hZ2UuY3VycmVudFZhbHVlLnRhcmdldC5maWxlc1xuICAgICAgKSB7XG4gICAgICAgIHRoaXMucGFyc2VGaWxlKHRoaXMuc291cmNlSW1hZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHRoaXMuaW1nT25lKSB7XG4gICAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0UHJvcGVydHkoXG4gICAgICAgICAgICB0aGlzLmltZ09uZSxcbiAgICAgICAgICAgIFwic3JjXCIsXG4gICAgICAgICAgICB0aGlzLmNySW1hZ2UuZ2V0QXR0cmlidXRlKFwic3JjXCIpXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHRoaXMuc2V0VXBMaXN0ZW5lcnMoKTtcbiAgICAgICAgICB0aGlzLnNldFVwQ29uZmlndXJhdGlvbnMoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHNldFVwTGlzdGVuZXJzKCkge1xuICAgIGlmICh0aGlzLmlzQnJvd3Nlcikge1xuICAgICAgdGhpcy5fcmVuZGVyZXIubGlzdGVuKHRoaXMuY3JSYW5nZSwgXCJpbnB1dFwiLCBldmVudCA9PiB7XG4gICAgICAgIHRoaXMubGlua0ltYWdlVG9SYW5nZUlucHV0KGV2ZW50LnRhcmdldC52YWx1ZSk7XG4gICAgICB9KTtcblxuICAgICAgdGhpcy5fcmVuZGVyZXIubGlzdGVuKHRoaXMuY3JJbWFnZSwgXCJtb3VzZWRvd25cIiwgZXZlbnQgPT4ge1xuICAgICAgICB0aGlzLm1vdXNlRG93bk9uSW1hZ2UoZXZlbnQpO1xuICAgICAgfSk7XG5cbiAgICAgIHRoaXMuX3JlbmRlcmVyLmxpc3Rlbih0aGlzLmNySW1hZ2UsIFwibW91c2V1cFwiLCBldmVudCA9PiB7XG4gICAgICAgIHRoaXMubW91c2VVcE9uSW1hZ2UoKTtcblxuICAgICAgICBpZiAodGhpcy5hdXRvQ3JvcCkge1xuICAgICAgICAgIHRoaXMucmVzaXplQW5kQ3JvcEltYWdlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9yZW5kZXJlci5saXN0ZW4odGhpcy5jckltYWdlLCBcIm1vdXNlbW92ZVwiLCBldmVudCA9PiB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMubW91c2VNb3ZlT25JbWFnZShldmVudCk7XG4gICAgICB9KTtcblxuICAgICAgdGhpcy5fcmVuZGVyZXIubGlzdGVuKHRoaXMuY3JDb250YWluZXIsIFwibW91c2VvdXRcIiwgZXZlbnQgPT4ge1xuICAgICAgICB0aGlzLmtlZXBNb3VzZU1vdmVJbnNpZGVDb250YWluZXIoKTtcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9yZW5kZXJlci5saXN0ZW4odGhpcy5idG4sIFwiY2xpY2tcIiwgZXZlbnQgPT4ge1xuICAgICAgICB0aGlzLnJlc2l6ZUFuZENyb3BJbWFnZSgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgc2V0VXBDb25maWd1cmF0aW9ucygpIHtcbiAgICB0aGlzLnNldEJvcmRlckNvbG9yKCk7XG4gICAgdGhpcy5zZXRCYWNrZ3JvdW5kT3BhY2l0eSgpO1xuICAgIHRoaXMuc2V0TGVuc0hlaWdodEFuZFdpZHRoKCk7XG4gIH1cblxuICBsaW5rSW1hZ2VUb1JhbmdlSW5wdXQodmFsdWU6IGFueSkge1xuICAgIGNvbnN0IHZhbCA9IHZhbHVlIC8gMTAwO1xuICAgIHRoaXMuY3JJbWFnZS5zdHlsZS50cmFuc2Zvcm0gPSBgc2NhbGUoJHt2YWx9KWA7XG4gIH1cblxuICBtb3VzZURvd25PbkltYWdlKGV2ZW50OiBhbnkpIHtcbiAgICB0aGlzLmlzRG93biA9IHRydWU7XG4gICAgdGhpcy5vZmZTZXQgPSBbXG4gICAgICBldmVudC50YXJnZXQub2Zmc2V0TGVmdCAtIGV2ZW50LmNsaWVudFgsXG4gICAgICBldmVudC50YXJnZXQub2Zmc2V0VG9wIC0gZXZlbnQuY2xpZW50WVxuICAgIF07XG4gIH1cblxuICBtb3VzZVVwT25JbWFnZSgpIHtcbiAgICB0aGlzLmlzRG93biA9IGZhbHNlO1xuICB9XG5cbiAgbW91c2VNb3ZlT25JbWFnZShldmVudDogYW55KSB7XG4gICAgaWYgKHRoaXMuaXNEb3duKSB7XG4gICAgICBjb25zdCBtb3VzZVBvc2l0aW9uID0ge1xuICAgICAgICB4OiBldmVudC5jbGllbnRYLFxuICAgICAgICB5OiBldmVudC5jbGllbnRZXG4gICAgICB9O1xuICAgICAgdGhpcy5jckltYWdlLnN0eWxlLmxlZnQgPSBtb3VzZVBvc2l0aW9uLnggKyB0aGlzLm9mZlNldFswXSArIFwicHhcIjtcbiAgICAgIHRoaXMuY3JJbWFnZS5zdHlsZS50b3AgPSBtb3VzZVBvc2l0aW9uLnkgKyB0aGlzLm9mZlNldFsxXSArIFwicHhcIjtcbiAgICB9XG4gIH1cblxuICBrZWVwTW91c2VNb3ZlSW5zaWRlQ29udGFpbmVyKCkge1xuICAgIHRoaXMuaXNEb3duID0gZmFsc2U7XG4gIH1cblxuICBjaGVja0Zvck92ZXJsYXAoZTEsIGUyKSB7XG4gICAgaWYgKGUxLmxlbmd0aCAmJiBlMS5sZW5ndGggPiAxKSB7XG4gICAgICBlMSA9IGUxWzBdO1xuICAgIH1cbiAgICBpZiAoZTIubGVuZ3RoICYmIGUyLmxlbmd0aCA+IDEpIHtcbiAgICAgIGUyID0gZTJbMF07XG4gICAgfVxuICAgIGNvbnN0IHJlY3QxID0gZTEgaW5zdGFuY2VvZiBFbGVtZW50ID8gZTEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkgOiBmYWxzZTtcbiAgICBjb25zdCByZWN0MiA9IGUyIGluc3RhbmNlb2YgRWxlbWVudCA/IGUyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpIDogZmFsc2U7XG5cbiAgICBsZXQgb3ZlcmxhcCA9IG51bGw7XG4gICAgaWYgKHJlY3QxICYmIHJlY3QyKSB7XG4gICAgICBvdmVybGFwID0gIShcbiAgICAgICAgcmVjdDEucmlnaHQgPCByZWN0Mi5sZWZ0IHx8XG4gICAgICAgIHJlY3QxLmxlZnQgPiByZWN0Mi5yaWdodCB8fFxuICAgICAgICByZWN0MS5ib3R0b20gPCByZWN0Mi50b3AgfHxcbiAgICAgICAgcmVjdDEudG9wID4gcmVjdDIuYm90dG9tXG4gICAgICApO1xuICAgICAgcmV0dXJuIFtvdmVybGFwLCByZWN0MSwgcmVjdDJdO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gW292ZXJsYXAsIHJlY3QxLCByZWN0Ml07XG4gICAgfVxuICB9XG5cbiAgZ2V0UmVzaXplUmF0aW8oKSB7XG4gICAgY29uc3QgdHJhbnNmb3JtID0gdGhpcy5jckltYWdlLnN0eWxlLnRyYW5zZm9ybTtcbiAgICBjb25zdCBtYXRyaXggPSB0cmFuc2Zvcm1cbiAgICAgIC5zdWJzdHJpbmcodHJhbnNmb3JtLmluZGV4T2YoXCIoXCIpICsgMSwgdHJhbnNmb3JtLmluZGV4T2YoXCIpXCIpKVxuICAgICAgLnNwbGl0KFwiLFwiKTtcbiAgICByZXR1cm4gbWF0cml4Lmxlbmd0aCA+IDAgPyBtYXRyaXhbMF0gOiBudWxsO1xuICB9XG5cbiAgZHJhd0ltYWdlUmVzaXplKCkge1xuICAgIGNvbnN0IHJhdGlvID0gdGhpcy5nZXRSZXNpemVSYXRpbygpO1xuICAgIHRoaXMuY2FudmFzVHdvLndpZHRoID0gdGhpcy5pbWdPbmUud2lkdGg7XG4gICAgdGhpcy5jYW52YXNUd28uaGVpZ2h0ID0gdGhpcy5pbWdPbmUuaGVpZ2h0O1xuICAgIHRoaXMuY29udGV4dFR3by5kcmF3SW1hZ2UodGhpcy5pbWdPbmUsIDAsIDApO1xuICAgIHRoaXMuY2FudmFzT25lLndpZHRoID0gdGhpcy5pbWdPbmUud2lkdGggKiByYXRpbztcbiAgICB0aGlzLmNhbnZhc09uZS5oZWlnaHQgPSB0aGlzLmltZ09uZS5oZWlnaHQgKiByYXRpbztcbiAgICB0aGlzLmNvbnRleHRPbmUuZHJhd0ltYWdlKFxuICAgICAgdGhpcy5jYW52YXNUd28sXG4gICAgICAwLFxuICAgICAgMCxcbiAgICAgIHRoaXMuY2FudmFzVHdvLndpZHRoLFxuICAgICAgdGhpcy5jYW52YXNUd28uaGVpZ2h0LFxuICAgICAgMCxcbiAgICAgIDAsXG4gICAgICB0aGlzLmNhbnZhc09uZS53aWR0aCxcbiAgICAgIHRoaXMuY2FudmFzT25lLmhlaWdodFxuICAgICk7XG5cbiAgICBjb25zdCBpID0gdGhpcy5jYW52YXNPbmUudG9EYXRhVVJMKFwiaW1hZ2UvcG5nXCIsIDEwMCk7XG5cbiAgICBpZiAodGhpcy50ZXN0SW1nKSB7XG4gICAgICB0aGlzLl9yZW5kZXJlci5zZXRQcm9wZXJ0eSh0aGlzLnRlc3RJbWcsIFwic3JjXCIsIGkpO1xuICAgIH1cbiAgICByZXR1cm4gaTtcbiAgfVxuXG4gIGRyYXdJbWFnZUNyb3Aoc3JjOiBzdHJpbmcpIHtcbiAgICBjb25zdCBvdmVybGFwID0gdGhpcy5jaGVja0Zvck92ZXJsYXAodGhpcy5jckxlbnMsIHRoaXMuY3JJbWFnZSk7XG5cbiAgICBpZiAodGhpcy5pbWdUd28pIHtcbiAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFByb3BlcnR5KHRoaXMuaW1nVHdvLCBcInNyY1wiLCBzcmMpO1xuXG4gICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICB0aGlzLl9yZW5kZXJlci5saXN0ZW4odGhpcy5pbWdUd28sIFwibG9hZFwiLCBldmVudCA9PiB7XG4gICAgICAgICAgdGhpcy5jYW52YXNUaHJlZS53aWR0aCA9IGV2ZW50LnRhcmdldC53aWR0aDtcbiAgICAgICAgICB0aGlzLmNhbnZhc1RocmVlLmhlaWdodCA9IGV2ZW50LnRhcmdldC5oZWlnaHQ7XG4gICAgICAgICAgdGhpcy5jb250ZXh0VGhyZWUuZHJhd0ltYWdlKHRoaXMuaW1nVHdvLCAwLCAwKTtcbiAgICAgICAgICB0aGlzLmNhbnZhc0ZvdXIud2lkdGggPSB0aGlzLmxlbnNXaWR0aDtcbiAgICAgICAgICB0aGlzLmNhbnZhc0ZvdXIuaGVpZ2h0ID0gdGhpcy5sZW5zSGVpZ2h0O1xuXG4gICAgICAgICAgaWYgKG92ZXJsYXApIHtcbiAgICAgICAgICAgIGNvbnN0IHhDcm9wID0gb3ZlcmxhcFsxXVtcInhcIl0gLSBvdmVybGFwWzJdW1wieFwiXTtcbiAgICAgICAgICAgIGNvbnN0IHlDcm9wID0gb3ZlcmxhcFsxXVtcInlcIl0gLSBvdmVybGFwWzJdW1wieVwiXTtcblxuICAgICAgICAgICAgdGhpcy5jb250ZXh0Rm91ci5kcmF3SW1hZ2UoXG4gICAgICAgICAgICAgIHRoaXMuY2FudmFzVGhyZWUsXG4gICAgICAgICAgICAgIHhDcm9wLFxuICAgICAgICAgICAgICB5Q3JvcCxcbiAgICAgICAgICAgICAgdGhpcy5sZW5zV2lkdGgsXG4gICAgICAgICAgICAgIHRoaXMubGVuc0hlaWdodCxcbiAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgdGhpcy5sZW5zV2lkdGgsXG4gICAgICAgICAgICAgIHRoaXMubGVuc0hlaWdodFxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMucm91bmRDcm9wKSB7XG4gICAgICAgICAgICAgIHRoaXMuY29udGV4dEZvdXIuZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uID0gXCJkZXN0aW5hdGlvbi1pblwiO1xuICAgICAgICAgICAgICB0aGlzLmNvbnRleHRGb3VyLmJlZ2luUGF0aCgpO1xuICAgICAgICAgICAgICB0aGlzLmNvbnRleHRGb3VyLmFyYyhcbiAgICAgICAgICAgICAgICB0aGlzLmxlbnNXaWR0aCAvIDIsXG4gICAgICAgICAgICAgICAgdGhpcy5sZW5zSGVpZ2h0IC8gMixcbiAgICAgICAgICAgICAgICB0aGlzLmxlbnNIZWlnaHQgLyAyLFxuICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgICAgTWF0aC5QSSAqIDJcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgdGhpcy5jb250ZXh0Rm91ci5jbG9zZVBhdGgoKTtcbiAgICAgICAgICAgICAgdGhpcy5jb250ZXh0Rm91ci5maWxsKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGIgPSB0aGlzLmNhbnZhc0ZvdXIudG9EYXRhVVJMKFwiaW1hZ2UvcG5nXCIsIDEwMCk7XG4gICAgICAgICAgICB0aGlzLmNyb3BBdmFpbGFibGUgPSB0cnVlO1xuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKHRoaXMuZmluYWxDcm9wKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0UHJvcGVydHkodGhpcy5maW5hbENyb3AsIFwic3JjXCIsIGIpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgcmVzb2x2ZShiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcmVzaXplQW5kQ3JvcEltYWdlKCkge1xuICAgIGNvbnN0IGltZ1NyYyA9IHRoaXMuZHJhd0ltYWdlUmVzaXplKCk7XG4gICAgdGhpcy5kcmF3SW1hZ2VDcm9wKGltZ1NyYykudGhlbihyZXN1bHQgPT4ge1xuICAgICAgdGhpcy5jcm9wcGVkSW1hZ2UuZW1pdChyZXN1bHQpO1xuICAgICAgY29uc29sZS5sb2cocmVzdWx0KTtcbiAgICB9KTtcbiAgfVxuXG4gIHNldExlbnNIZWlnaHRBbmRXaWR0aCgpIHtcbiAgICBpZiAodGhpcy5sZW5zSGVpZ2h0ICYmIHRoaXMubGVuc0hlaWdodCAhPT0gMTUwKSB7XG4gICAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmNyTGVucywgXCJoZWlnaHRcIiwgdGhpcy5sZW5zSGVpZ2h0ICsgXCJweFwiKTtcbiAgICB9XG4gICAgaWYgKHRoaXMubGVuc1dpZHRoICYmIHRoaXMubGVuc1dpZHRoICE9PSAxNTApIHtcbiAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKHRoaXMuY3JMZW5zLCBcIndpZHRoXCIsIHRoaXMubGVuc1dpZHRoICsgXCJweFwiKTtcbiAgICB9XG4gICAgaWYgKHRoaXMucm91bmRDcm9wKSB7XG4gICAgICB0aGlzLl9yZW5kZXJlci5hZGRDbGFzcyh0aGlzLmNyTGVucywgXCJyb3VuZGVkXCIpO1xuICAgIH1cbiAgfVxuXG4gIHNldEJvcmRlckNvbG9yKCkge1xuICAgIGlmICh0aGlzLmJvcmRlckNvbG9yKSB7XG4gICAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZShcbiAgICAgICAgdGhpcy5jckNvbnRhaW5lcixcbiAgICAgICAgXCJib3JkZXItY29sb3JcIixcbiAgICAgICAgdGhpcy5ib3JkZXJDb2xvclxuICAgICAgKTtcblxuICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0U3R5bGUodGhpcy5jckxlbnMsIFwiYm9yZGVyLWNvbG9yXCIsIHRoaXMuYm9yZGVyQ29sb3IpO1xuXG4gICAgICBjb25zdCBzcGFucyA9IHRoaXMuY3JMZW5zLnF1ZXJ5U2VsZWN0b3JBbGwoXCJzcGFuXCIpO1xuICAgICAgc3BhbnMuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0U3R5bGUoZWxlbWVudCwgXCJib3JkZXItY29sb3JcIiwgdGhpcy5ib3JkZXJDb2xvcik7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBzZXRCYWNrZ3JvdW5kT3BhY2l0eSgpIHtcbiAgICBpZiAodGhpcy5iYWNrZ3JvdW5kT3BhY2l0eSAmJiB0aGlzLmNyTGVucykge1xuICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0U3R5bGUoXG4gICAgICAgIHRoaXMuY3JMZW5zLFxuICAgICAgICBcImJveC1zaGFkb3dcIixcbiAgICAgICAgXCIwIDAgMCAyMDAwMDBweCByZ2JhKDAsIDAsIDAsIFwiICsgdGhpcy5iYWNrZ3JvdW5kT3BhY2l0eSArIFwiKVwiXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHBhcnNlRmlsZShldmVudDogYW55KSB7XG4gICAgY29uc3QgZmlsZSA9IGV2ZW50LnRhcmdldC5maWxlc1swXTtcblxuICAgIGlmIChcbiAgICAgIGZpbGUudHlwZSA9PT0gXCJpbWFnZS9wbmdcIiB8fFxuICAgICAgZmlsZS50eXBlID09PSBcImltYWdlL2pwZWdcIiB8fFxuICAgICAgZmlsZS50eXBlID09PSBcImltYWdlL2dpZlwiIHx8XG4gICAgICBmaWxlLnR5cGUgPT09IFwiaW1hZ2UvdGlmZlwiXG4gICAgKSB7XG4gICAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgICAgcmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZSk7XG5cbiAgICAgIHJlYWRlci5hZGRFdmVudExpc3RlbmVyKFwibG9hZFwiLCBlID0+IHtcbiAgICAgICAgY29uc3QgdmFsID0gcmVhZGVyLnJlc3VsdC50b1N0cmluZygpO1xuXG4gICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFByb3BlcnR5KHRoaXMuY3JJbWFnZSwgXCJzcmNcIiwgdmFsKTtcbiAgICAgICAgdGhpcy5sb2FkZWRTb3VyY2VJbWFnZSA9IHRoaXMuY3JJbWFnZS5nZXRBdHRyaWJ1dGUoXCJzcmNcIik7XG5cbiAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0UHJvcGVydHkoXG4gICAgICAgICAgdGhpcy5pbWdPbmUsXG4gICAgICAgICAgXCJzcmNcIixcbiAgICAgICAgICB0aGlzLmNySW1hZ2UuZ2V0QXR0cmlidXRlKFwic3JjXCIpXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5zZXRVcExpc3RlbmVycygpO1xuICAgICAgICB0aGlzLnNldFVwQ29uZmlndXJhdGlvbnMoKTtcbiAgICAgIH0pO1xuICAgICAgcmVhZGVyLm9uZXJyb3IgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJ0aGVyZSBhcmUgc29tZSBwcm9ibGVtc1wiKTtcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubG9hZGVkU291cmNlSW1hZ2UgPSBudWxsO1xuICAgICAgaWYgKHRoaXMuY3JDb250YWluZXIpIHtcbiAgICAgICAgdGhpcy5fcmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5jckNvbnRhaW5lciwgXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuZXJyb3JNZXNzYWdlID0gXCJJbnZhbGlkIGZpbGUgdHlwZS5cIjtcbiAgICAgIHRoaXMuZXJyb3IuZW1pdCh0aGlzLmVycm9yTWVzc2FnZSk7XG4gICAgfVxuICB9XG5cbiAgY2xlYXJJbWFnZVBvc2l0aW9uKCkge1xuICAgIGlmICh0aGlzLmNySW1hZ2UpIHtcbiAgICAgIHRoaXMuY3JJbWFnZS5z