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
JavaScript
/**
* @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