UNPKG

ngx-image-drawing

Version:
473 lines 61.4 kB
import * as tslib_1 from "tslib"; import { Component, EventEmitter, Input, Output, TemplateRef } from '@angular/core'; import { fabric } from 'fabric'; import { I18nEn, i18nLanguages } from './i18n'; import { Observable, of } from 'rxjs'; import { switchMap } from 'rxjs/operators'; var ImageDrawingComponent = /** @class */ (function () { function ImageDrawingComponent() { this.forceSizeCanvas = true; this.forceSizeExport = false; this.enableRemoveImage = false; this.enableLoadAnotherImage = false; this.enableTooltip = true; this.showCancelButton = true; this.locale = 'en'; /* @deprecated Use i18n.saveBtn */ this.saveBtnText = 'Save'; /* @deprecated Use i18n.cancelBtn */ this.cancelBtnText = 'Cancel'; /* @deprecated Use i18n.loading */ this.loadingText = 'Loading…'; /* @deprecated Use i18n.loadError */ this.errorText = 'Error loading %@'; this.outputMimeType = 'image/jpeg'; this.outputQuality = 0.8; this.borderCss = 'none'; this.drawingSizes = { small: 5, medium: 10, large: 25, }; this.colors = { black: '#000', white: '#fff', yellow: '#ffeb3b', red: '#f44336', blue: '#2196f3', green: '#4caf50', purple: '#7a08af', }; this.save = new EventEmitter(); this.cancel = new EventEmitter(); this.currentTool = 'brush'; this.currentSize = 'medium'; this.currentColor = 'black'; this.i18n = I18nEn; this.canUndo = false; this.canRedo = false; this.isLoading = false; this.hasError = false; this.errorMessage = ''; this.stack = []; this.colorsName = []; this.drawingSizesName = []; } ImageDrawingComponent.prototype.ngOnInit = function () { var _this = this; this.colorsName = Object.keys(this.colors); this.drawingSizesName = Object.keys(this.drawingSizes); this.canvas = new fabric.Canvas('canvas', { hoverCursor: 'pointer', isDrawingMode: true, }); this.canvas.backgroundColor = 'white'; if (this.src) { this.importPhotoFromSrc(this.src); } else { if (!this.width || !this.height) { throw new Error('No width or hight given !'); } this.canvas.setWidth(this.width); this.canvas.setHeight(this.height); } this.canvas.on('path:created', function () { _this.stack = []; _this.setUndoRedo(); }); this.selectTool(this.currentTool); this.selectColor(this.currentColor); this.selectDrawingSize(this.currentSize); if (this.locale && i18nLanguages[this.locale.toLowerCase()]) { this.i18n = i18nLanguages[this.locale.toLowerCase()]; } // FIXME remove after a while because properties are now deprecated if (this.saveBtnText) { this.i18n.saveBtn = this.saveBtnText; } if (this.cancelBtnText) { this.i18n.cancelBtn = this.cancelBtnText; } if (this.loadingText) { this.i18n.loading = this.loadingText; } if (this.errorText) { this.i18n.loadError = this.errorText; } }; // Tools ImageDrawingComponent.prototype.selectTool = function (tool) { this.currentTool = tool; }; ImageDrawingComponent.prototype.selectDrawingSize = function (size) { this.currentSize = size; if (this.canvas) { this.canvas.freeDrawingBrush.width = this.drawingSizes[size]; } }; ImageDrawingComponent.prototype.selectColor = function (color) { this.currentColor = color; if (this.canvas) { this.canvas.freeDrawingBrush.color = this.colors[color]; } }; // Actions ImageDrawingComponent.prototype.undo = function () { if (this.canUndo) { var lastId = this.canvas.getObjects().length - 1; var lastObj = this.canvas.getObjects()[lastId]; this.stack.push(lastObj); this.canvas.remove(lastObj); this.setUndoRedo(); } }; ImageDrawingComponent.prototype.redo = function () { if (this.canRedo) { var firstInStack = this.stack.splice(-1, 1)[0]; if (firstInStack) { this.canvas.insertAt(firstInStack, this.canvas.getObjects().length - 1, false); } this.setUndoRedo(); } }; ImageDrawingComponent.prototype.clearCanvas = function () { var _a; if (this.canvas) { (_a = this.canvas).remove.apply(_a, tslib_1.__spread(this.canvas.getObjects())); this.setUndoRedo(); } }; ImageDrawingComponent.prototype.saveImage = function () { var _this = this; if (!this.forceSizeExport || (this.forceSizeExport && this.width && this.height)) { var canvasScaledElement = document.createElement('canvas'); var canvasScaled_1 = new fabric.Canvas(canvasScaledElement); canvasScaled_1.backgroundColor = 'white'; new Observable(function (observer) { if (_this.imageUsed) { if (_this.forceSizeExport) { canvasScaled_1.setWidth(_this.width); canvasScaled_1.setHeight(_this.height); _this.imageUsed.cloneAsImage(function (imageCloned) { imageCloned.scaleToWidth(_this.width, false); imageCloned.scaleToHeight(_this.height, false); canvasScaled_1.setBackgroundImage(imageCloned, function (img) { if (!img) { observer.error(new Error('Impossible to draw the image on the temporary canvas')); } observer.next(canvasScaled_1); observer.complete(); }, { crossOrigin: 'anonymous', originX: 'left', originY: 'top' }); }); } else { canvasScaled_1.setBackgroundImage(_this.imageUsed, function (img) { if (!img) { observer.error(new Error('Impossible to draw the image on the temporary canvas')); } canvasScaled_1.setWidth(img.width); canvasScaled_1.setHeight(img.height); observer.next(canvasScaled_1); observer.complete(); }, { crossOrigin: 'anonymous', originX: 'left', originY: 'top' }); } } else { canvasScaled_1.setWidth(_this.width); canvasScaled_1.setHeight(_this.height); } }).pipe(switchMap(function () { var process = of(canvasScaled_1); if (_this.canvas.getObjects().length > 0) { var ratioX_1 = canvasScaled_1.getWidth() / _this.canvas.getWidth(); var ratioY_1 = canvasScaled_1.getHeight() / _this.canvas.getHeight(); _this.canvas.getObjects().forEach(function (originalObject, i) { process = process.pipe(switchMap(function () { return new Observable(function (observerObject) { originalObject.clone(function (clonedObject) { clonedObject.set('left', originalObject.left * ratioX_1); clonedObject.set('top', originalObject.top * ratioY_1); clonedObject.scaleToWidth(originalObject.width * ratioX_1); clonedObject.scaleToHeight(originalObject.height * ratioY_1); canvasScaled_1.insertAt(clonedObject, i, false); canvasScaled_1.renderAll(); observerObject.next(canvasScaled_1); observerObject.complete(); }); }); })); }); } return process; })).subscribe(function () { canvasScaled_1.renderAll(); canvasScaled_1.getElement().toBlob(function (data) { _this.save.emit(data); }, _this.outputMimeType, _this.outputQuality); }); } else { this.canvas.getElement().toBlob(function (data) { _this.save.emit(data); }, this.outputMimeType, this.outputQuality); } }; ImageDrawingComponent.prototype.cancelAction = function () { this.cancel.emit(); }; ImageDrawingComponent.prototype.getTextTranslated = function (name) { var strOk = name.split('.').reduce(function (o, i) { return o[i]; }, this.i18n); if (this.i18nUser) { try { var str = name.split('.').reduce(function (o, i) { return o[i]; }, this.i18nUser); if (str) { strOk = str; } } catch (e) { // if we pass here, ignored } } if (!strOk) { console.error(name + ' translation not found !'); } return strOk; }; ImageDrawingComponent.prototype.getTooltipTranslated = function (name) { if (this.enableTooltip) { return this.getTextTranslated(name); } else { return ''; } }; ImageDrawingComponent.prototype.setUndoRedo = function () { this.canUndo = this.canvas.getObjects().length > 0; this.canRedo = this.stack.length > 0; this.canvas.renderAll(); }; ImageDrawingComponent.prototype.importPhotoFromFile = function (event) { if (event.target.files && event.target.files.length > 0) { var file = event.target.files[0]; if (file.type.match('image.*')) { this.importPhotoFromBlob(file); } else { throw new Error('Not an image !'); } } }; ImageDrawingComponent.prototype.removeImage = function () { if (this.imageUsed) { this.imageUsed.dispose(); this.imageUsed = null; } this.canvas.backgroundImage = null; if (this.width && this.height) { this.canvas.setWidth(this.width); this.canvas.setHeight(this.height); } this.canvas.renderAll(); }; Object.defineProperty(ImageDrawingComponent.prototype, "hasImage", { get: function () { return !!this.canvas.backgroundImage; }, enumerable: true, configurable: true }); ImageDrawingComponent.prototype.importPhotoFromSrc = function (src) { var _this = this; this.isLoading = true; var isFirstTry = true; var imgEl = new Image(); imgEl.setAttribute('crossOrigin', 'anonymous'); imgEl.src = src; imgEl.onerror = function () { // Retry with cors proxy if (isFirstTry) { imgEl.src = 'https://cors-anywhere.herokuapp.com/' + _this.src; isFirstTry = false; } else { _this.isLoading = false; _this.hasError = true; _this.errorMessage = _this.getTextTranslated('loadError').replace('%@', _this.src); } }; imgEl.onload = function () { _this.isLoading = false; _this.imageUsed = new fabric.Image(imgEl); _this.imageUsed.cloneAsImage(function (image) { var width = imgEl.width; var height = imgEl.height; if (_this.width) { width = _this.width; } if (_this.height) { height = _this.height; } image.scaleToWidth(width, false); image.scaleToHeight(height, false); _this.canvas.setBackgroundImage(image, (function (img) { if (img) { if (_this.forceSizeCanvas) { _this.canvas.setWidth(width); _this.canvas.setHeight(height); } else { _this.canvas.setWidth(image.getScaledWidth()); _this.canvas.setHeight(image.getScaledHeight()); } } }), { crossOrigin: 'anonymous', originX: 'left', originY: 'top' }); }); }; }; ImageDrawingComponent.prototype.importPhotoFromBlob = function (file) { var _this = this; var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function (evtReader) { if (evtReader.target.readyState == FileReader.DONE) { _this.importPhotoFromSrc(evtReader.target.result); } }; }; ImageDrawingComponent.prototype.importPhotoFromUrl = function () { var url = prompt(this.getTooltipTranslated('loadImageUrl')); if (url) { this.importPhotoFromSrc(url); } }; ImageDrawingComponent.prototype.ngOnChanges = function (changes) { if (changes.src && !changes.src.firstChange && changes.src.currentValue) { if (typeof changes.src.currentValue === 'string') { this.importPhotoFromSrc(changes.src.currentValue); } else if (changes.src.currentValue instanceof Blob) { this.importPhotoFromBlob(changes.src.currentValue); } } }; tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", String) ], ImageDrawingComponent.prototype, "src", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Number) ], ImageDrawingComponent.prototype, "width", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Number) ], ImageDrawingComponent.prototype, "height", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "forceSizeCanvas", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "forceSizeExport", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "enableRemoveImage", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "enableLoadAnotherImage", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "enableTooltip", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "showCancelButton", void 0); tslib_1.__decorate([ Input('i18n'), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "i18nUser", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", String) ], ImageDrawingComponent.prototype, "locale", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "saveBtnText", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "cancelBtnText", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "loadingText", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "errorText", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", TemplateRef) ], ImageDrawingComponent.prototype, "loadingTemplate", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", TemplateRef) ], ImageDrawingComponent.prototype, "errorTemplate", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "outputMimeType", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "outputQuality", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", String) ], ImageDrawingComponent.prototype, "borderCss", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "drawingSizes", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Object) ], ImageDrawingComponent.prototype, "colors", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ImageDrawingComponent.prototype, "save", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ImageDrawingComponent.prototype, "cancel", void 0); ImageDrawingComponent = tslib_1.__decorate([ Component({ selector: 'image-drawing', template: "<link href=\"https://fonts.googleapis.com/icon?family=Material+Icons\" rel=\"stylesheet\" />\n\n<div class=\"loading\" *ngIf=\"isLoading\">\n <ng-container *ngTemplateOutlet=\"loadingTemplate ? loadingTemplate : defaultLoading\"></ng-container>\n</div>\n<div class=\"error\" *ngIf=\"hasError\">\n <ng-container *ngTemplateOutlet=\"errorTemplate ? errorTemplate : defaultError\"></ng-container>\n</div>\n\n<ng-template #defaultLoading><p>{{ getTextTranslated('loading') }}</p></ng-template>\n<ng-template #defaultError> <p>{{ errorMessage }}</p> </ng-template>\n\n<div [ngStyle]=\"{ border: borderCss }\">\n <canvas id=\"canvas\"></canvas>\n</div>\n<div class=\"toolbar\" *ngIf=\"!isLoading\">\n <div class=\"tools\">\n <div class=\"row\">\n <i class=\"material-icons btn\" [class.selected]=\"currentTool == 'brush'\" (click)=\"selectTool('brush')\"\n [title]=\"getTooltipTranslated('tools.brush')\">brush</i>\n <span *ngFor=\"let drawingSizeName of drawingSizesName\" class=\"size btn\"\n [style.width.px]=\"drawingSizes[drawingSizeName] * 0.8 + 8\"\n [style.height.px]=\"drawingSizes[drawingSizeName] * 0.8 + 8\"\n [style.borderRadius.px]=\"drawingSizes[drawingSizeName] * 0.4 + 4\"\n [class.selected]=\"currentSize == drawingSizeName\"\n [title]=\"getTooltipTranslated('sizes.' + drawingSizeName)\"\n (click)=\"selectDrawingSize(drawingSizeName)\">\n </span>\n\n <input style=\"display: none\" type=\"file\" #fileInput (change)=\"importPhotoFromFile($event)\"\n accept=\"image/*\"/>\n <i class=\"material-icons btn\" *ngIf=\"enableLoadAnotherImage && !hasImage\" (click)=\"fileInput.click();\"\n [title]=\"getTooltipTranslated('loadImage')\">attach_file</i>\n <i class=\"material-icons btn\" *ngIf=\"enableLoadAnotherImage && !hasImage\" (click)=\"importPhotoFromUrl()\"\n [title]=\"getTooltipTranslated('loadImageUrl')\">insert_drive_file</i>\n <i class=\"material-icons btn\" *ngIf=\"enableRemoveImage && hasImage\" (click)=\"removeImage()\"\n [title]=\"getTooltipTranslated('removeImage')\">clear</i>\n\n <i class=\"material-icons btn\" [class.disabled]=\"!canUndo\" (click)=\"undo()\"\n [title]=\"getTooltipTranslated('undo')\">undo</i>\n <i class=\"material-icons btn\" [class.disabled]=\"!canRedo\" (click)=\"redo()\"\n [title]=\"getTooltipTranslated('redo')\">redo</i>\n <i class=\"material-icons btn\" (click)=\"clearCanvas()\" [title]=\"getTooltipTranslated('clear')\">delete</i>\n </div>\n <div class=\"row\">\n <div *ngFor=\"let colorName of colorsName\" [class.selected]=\"currentColor == colorName\" class=\"color\"\n [ngClass]=\"colorName\"\n [style.background]=\"colors[colorName]\" [title]=\"getTooltipTranslated('colors.' + colorName)\"\n (click)=\"selectColor(colorName)\">\n </div>\n </div>\n </div>\n <div class=\"buttons\">\n <a href=\"#\" class=\"button btn-primary\"\n (click)=\"saveImage(); $event.preventDefault()\">{{ getTextTranslated('saveBtn') }}</a>\n <a href=\"#\" class=\"button btn-light\" *ngIf=\"showCancelButton\"\n (click)=\"cancelAction(); $event.preventDefault()\">{{ getTextTranslated('cancelBtn') }}</a>\n </div>\n <!-- Any additional toolbar buttons to be projected by the consuming app -->\n <ng-content></ng-content>\n</div>\n", styles: [":host{display:flex;flex-direction:column;align-items:center}:host .toolbar{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap}:host .tools{display:inline-flex;flex-direction:column;padding:20px;margin:10px;background:#fff;border-radius:6px;box-shadow:0 3px 10px rgba(0,0,0,.4)}:host .row{display:flex;width:300px;justify-content:space-around;align-items:center}:host .row:first-child{margin-bottom:10px}:host .btn{cursor:pointer}:host .btn.selected{color:#bdbdbd}:host .btn.disabled{cursor:initial;color:#bdbdbd}:host .size{background-color:#000}:host .size.selected{background-color:#bdbdbd}:host .color{width:28px;height:28px;border-radius:14px;cursor:pointer;display:flex;align-items:center;justify-content:center}:host .color.selected::after{content:\"\";width:10px;height:10px;background:#000;display:flex;border-radius:5px}:host .color.black{background-color:#000}:host .color.black.selected::after{background:#fff}:host .color.white{border:1px solid #a7a7a7}:host .buttons{margin:10px;display:flex;flex-direction:column}:host .button{cursor:pointer;outline:0;border:none;white-space:nowrap;text-decoration:none;vertical-align:baseline;text-align:center;min-width:64px;line-height:36px;padding:3px 16px;border-radius:4px;overflow:visible;transition:background .4s cubic-bezier(.25,.8,.25,1),box-shadow 280ms cubic-bezier(.4,0,.2,1);margin:10px}:host .button:hover{text-decoration:none!important}:host .button.btn-primary{background-color:#ef5f27;color:#fff}:host .button.btn-primary:hover{background-color:rgba(239,95,39,.8)}:host .button.btn-light{color:#ef5f27}:host .button.btn-light:hover{background-color:rgba(239,95,39,.1)}"] }), tslib_1.__metadata("design:paramtypes", []) ], ImageDrawingComponent); return ImageDrawingComponent; }()); export { ImageDrawingComponent }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2UtZHJhd2luZy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtaW1hZ2UtZHJhd2luZy8iLCJzb3VyY2VzIjpbInNyYy9pbWFnZS1kcmF3aW5nLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFxQixNQUFNLEVBQWlCLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN0SCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ2hDLE9BQU8sRUFBRSxNQUFNLEVBQWlCLGFBQWEsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUM5RCxPQUFPLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN0QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFPM0M7SUF3RUk7UUFsRWdCLG9CQUFlLEdBQUcsSUFBSSxDQUFDO1FBQ3ZCLG9CQUFlLEdBQUcsS0FBSyxDQUFDO1FBQ3hCLHNCQUFpQixHQUFHLEtBQUssQ0FBQztRQUMxQiwyQkFBc0IsR0FBRyxLQUFLLENBQUM7UUFDL0Isa0JBQWEsR0FBRyxJQUFJLENBQUM7UUFDckIscUJBQWdCLEdBQUcsSUFBSSxDQUFDO1FBSXhCLFdBQU0sR0FBVyxJQUFJLENBQUM7UUFDdEMsa0NBQWtDO1FBQ2xCLGdCQUFXLEdBQUcsTUFBTSxDQUFDO1FBQ3JDLG9DQUFvQztRQUNwQixrQkFBYSxHQUFHLFFBQVEsQ0FBQztRQUN6QyxrQ0FBa0M7UUFDbEIsZ0JBQVcsR0FBRyxVQUFVLENBQUM7UUFDekMsb0NBQW9DO1FBQ3BCLGNBQVMsR0FBRyxrQkFBa0IsQ0FBQztRQUsvQixtQkFBYyxHQUFHLFlBQVksQ0FBQztRQUM5QixrQkFBYSxHQUFHLEdBQUcsQ0FBQztRQUVwQixjQUFTLEdBQVcsTUFBTSxDQUFDO1FBRTNCLGlCQUFZLEdBQStCO1lBQ3ZELEtBQUss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QVk7eURBQWtDO0lBbEQ5RCxxQkFBcUI7UUFMakMsU0FBUyxDQUFDO1lBQ1AsUUFBUSxFQUFFLGVBQWU7WUFFekIsbWtIQUE2Qzs7U0FDaEQsQ0FBQzs7T0FDVyxxQkFBcUIsQ0FxYWpDO0lBQUQsNEJBQUM7Q0FBQSxBQXJhRCxJQXFhQztTQXJhWSxxQkFBcUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uQ2hhbmdlcywgT25Jbml0LCBPdXRwdXQsIFNpbXBsZUNoYW5nZXMsIFRlbXBsYXRlUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBmYWJyaWMgfSBmcm9tICdmYWJyaWMnO1xuaW1wb3J0IHsgSTE4bkVuLCBJMThuSW50ZXJmYWNlLCBpMThuTGFuZ3VhZ2VzIH0gZnJvbSAnLi9pMThuJztcbmltcG9ydCB7IE9ic2VydmFibGUsIG9mIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBzd2l0Y2hNYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnaW1hZ2UtZHJhd2luZycsXG4gICAgc3R5bGVVcmxzOiBbJy4vaW1hZ2UtZHJhd2luZy5jb21wb25lbnQuc2NzcyddLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9pbWFnZS1kcmF3aW5nLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBJbWFnZURyYXdpbmdDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcyB7XG5cbiAgICBASW5wdXQoKSBwdWJsaWMgc3JjPzogc3RyaW5nO1xuICAgIEBJbnB1dCgpIHB1YmxpYyB3aWR0aD86IG51bWJlcjtcbiAgICBASW5wdXQoKSBwdWJsaWMgaGVpZ2h0PzogbnVtYmVyO1xuXG4gICAgQElucHV0KCkgcHVibGljIGZvcmNlU2l6ZUNhbnZhcyA9IHRydWU7XG4gICAgQElucHV0KCkgcHVibGljIGZvcmNlU2l6ZUV4cG9ydCA9IGZhbHNlO1xuICAgIEBJbnB1dCgpIHB1YmxpYyBlbmFibGVSZW1vdmVJbWFnZSA9IGZhbHNlO1xuICAgIEBJbnB1dCgpIHB1YmxpYyBlbmFibGVMb2FkQW5vdGhlckltYWdlID0gZmFsc2U7XG4gICAgQElucHV0KCkgcHVibGljIGVuYWJsZVRvb2x0aXAgPSB0cnVlO1xuICAgIEBJbnB1dCgpIHB1YmxpYyBzaG93Q2FuY2VsQnV0dG9uID0gdHJ1ZTtcblxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBASW5wdXQoJ2kxOG4nKSBwdWJsaWMgaTE4blVzZXI6IEkxOG5JbnRlcmZhY2U7XG4gICAgQElucHV0KCkgcHVibGljIGxvY2FsZTogc3RyaW5nID0gJ2VuJztcbiAgICAvKiBAZGVwcmVjYXRlZCBVc2UgaTE4bi5zYXZlQnRuICovXG4gICAgQElucHV0KCkgcHVibGljIHNhdmVCdG5UZXh0ID0gJ1NhdmUnO1xuICAgIC8qIEBkZXByZWNhdGVkIFVzZSBpMThuLmNhbmNlbEJ0biAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBjYW5jZWxCdG5UZXh0ID0gJ0NhbmNlbCc7XG4gICAgLyogQGRlcHJlY2F0ZWQgVXNlIGkxOG4ubG9hZGluZyAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBsb2FkaW5nVGV4dCA9ICdMb2FkaW5n4oCmJztcbiAgICAvKiBAZGVwcmVjYXRlZCBVc2UgaTE4bi5sb2FkRXJyb3IgKi9cbiAgICBASW5wdXQoKSBwdWJsaWMgZXJyb3JUZXh0ID0gJ0Vycm9yIGxvYWRpbmcgJUAnO1xuXG4gICAgQElucHV0KCkgcHVibGljIGxvYWRpbmdUZW1wbGF0ZT86IFRlbXBsYXRlUmVmPGFueT47XG4gICAgQElucHV0KCkgcHVibGljIGVycm9yVGVtcGxhdGU/OiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gICAgQElucHV0KCkgcHVibGljIG91dHB1dE1pbWVUeXBlID0gJ2ltYWdlL2pwZWcnO1xuICAgIEBJbnB1dCgpIHB1YmxpYyBvdXRwdXRRdWFsaXR5ID0gMC44O1xuXG4gICAgQElucHV0KCkgcHVibGljIGJvcmRlckNzczogc3RyaW5nID0gJ25vbmUnO1xuXG4gICAgQElucHV0KCkgcHVibGljIGRyYXdpbmdTaXplczogeyBbbmFtZTogc3RyaW5nXTogbnVtYmVyIH0gPSB7XG4gICAgICAgIHNtYWxsOiA1LFxuICAgICAgICBtZWRpdW06IDEwLFxuICAgICAgICBsYXJnZTogMjUsXG4gICAgfTtcblxuICAgIEBJbnB1dCgpIHB1YmxpYyBjb2xvcnM6IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICAgICBibGFjazogJyMwMDAnLFxuICAgICAgICB3aGl0ZTogJyNmZmYnLFxuICAgICAgICB5ZWxsb3c6ICcjZmZlYjNiJyxcbiAgICAgICAgcmVkOiAnI2Y0NDMzNicsXG4gICAgICAgIGJsdWU6ICcjMjE5NmYzJyxcbiAgICAgICAgZ3JlZW46ICcjNGNhZjUwJyxcbiAgICAgICAgcHVycGxlOiAnIzdhMDhhZicsXG4gICAgfTtcblxuICAgIEBPdXRwdXQoKSBwdWJsaWMgc2F2ZTogRXZlbnRFbWl0dGVyPEJsb2I+ID0gbmV3IEV2ZW50RW1pdHRlcjxCbG9iPigpO1xuICAgIEBPdXRwdXQoKSBwdWJsaWMgY2FuY2VsOiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgICBwdWJsaWMgY3VycmVudFRvb2wgPSAnYnJ1c2gnO1xuICAgIHB1YmxpYyBjdXJyZW50U2l6ZSA9ICdtZWRpdW0nO1xuICAgIHB1YmxpYyBjdXJyZW50Q29sb3IgPSAnYmxhY2snO1xuICAgIHB1YmxpYyBpMThuOiBJMThuSW50ZXJmYWNlID0gSTE4bkVuO1xuXG4gICAgcHVibGljIGNhblVuZG8gPSBmYWxzZTtcbiAgICBwdWJsaWMgY2FuUmVkbyA9IGZhbHNlO1xuXG4gICAgcHVibGljIGlzTG9hZGluZyA9IGZhbHNlO1xuICAgIHB1YmxpYyBoYXNFcnJvciA9IGZhbHNlO1xuICAgIHB1YmxpYyBlcnJvck1lc3NhZ2UgPSAnJztcblxuICAgIHByaXZhdGUgY2FudmFzOiBmYWJyaWMuQ2FudmFzO1xuICAgIHByaXZhdGUgc3RhY2s6IGZhYnJpYy5PYmplY3RbXSA9IFtdO1xuXG4gICAgcHVibGljIGNvbG9yc05hbWU6IHN0cmluZ1tdID0gW107XG4gICAgcHVibGljIGRyYXdpbmdTaXplc05hbWU6IHN0cmluZ1tdID0gW107XG5cbiAgICBwcml2YXRlIGltYWdlVXNlZD86IGZhYnJpYy5JbWFnZTtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgIH1cblxuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jb2xvcnNOYW1lID0gT2JqZWN0LmtleXModGhpcy5jb2xvcnMpO1xuICAgICAgICB0aGlzLmRyYXdpbmdTaXplc05hbWUgPSBPYmplY3Qua2V5cyh0aGlzLmRyYXdpbmdTaXplcyk7XG5cbiAgICAgICAgdGhpcy5jYW52YXMgPSBuZXcgZmFicmljLkNhbnZhcygnY2FudmFzJywge1xuICAgICAgICAgICAgaG92ZXJDdXJzb3I6ICdwb2ludGVyJyxcbiAgICAgICAgICAgIGlzRHJhd2luZ01vZGU6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmNhbnZhcy5iYWNrZ3JvdW5kQ29sb3IgPSAnd2hpdGUnO1xuXG4gICAgICAgIGlmICh0aGlzLnNyYykge1xuICAgICAgICAgICAgdGhpcy5pbXBvcnRQaG90b0Zyb21TcmModGhpcy5zcmMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKCF0aGlzLndpZHRoIHx8ICF0aGlzLmhlaWdodCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gd2lkdGggb3IgaGlnaHQgZ2l2ZW4gIScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmNhbnZhcy5zZXRXaWR0aCh0aGlzLndpZHRoKTtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnNldEhlaWdodCh0aGlzLmhlaWdodCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNhbnZhcy5vbigncGF0aDpjcmVhdGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdGFjayA9IFtdO1xuICAgICAgICAgICAgdGhpcy5zZXRVbmRvUmVkbygpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnNlbGVjdFRvb2wodGhpcy5jdXJyZW50VG9vbCk7XG4gICAgICAgIHRoaXMuc2VsZWN0Q29sb3IodGhpcy5jdXJyZW50Q29sb3IpO1xuICAgICAgICB0aGlzLnNlbGVjdERyYXdpbmdTaXplKHRoaXMuY3VycmVudFNpemUpO1xuXG4gICAgICAgIGlmICh0aGlzLmxvY2FsZSAmJiBpMThuTGFuZ3VhZ2VzW3RoaXMubG9jYWxlLnRvTG93ZXJDYXNlKCldKSB7XG4gICAgICAgICAgICB0aGlzLmkxOG4gPSBpMThuTGFuZ3VhZ2VzW3RoaXMubG9jYWxlLnRvTG93ZXJDYXNlKCldO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRklYTUUgcmVtb3ZlIGFmdGVyIGEgd2hpbGUgYmVjYXVzZSBwcm9wZXJ0aWVzIGFyZSBub3cgZGVwcmVjYXRlZFxuICAgICAgICBpZiAodGhpcy5zYXZlQnRuVGV4dCkge1xuICAgICAgICAgICAgdGhpcy5pMThuLnNhdmVCdG4gPSB0aGlzLnNhdmVCdG5UZXh0O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmNhbmNlbEJ0blRleHQpIHtcbiAgICAgICAgICAgIHRoaXMuaTE4bi5jYW5jZWxCdG4gPSB0aGlzLmNhbmNlbEJ0blRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMubG9hZGluZ1RleHQpIHtcbiAgICAgICAgICAgIHRoaXMuaTE4bi5sb2FkaW5nID0gdGhpcy5sb2FkaW5nVGV4dDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5lcnJvclRleHQpIHtcbiAgICAgICAgICAgIHRoaXMuaTE4bi5sb2FkRXJyb3IgPSB0aGlzLmVycm9yVGV4dDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRvb2xzXG4gICAgcHVibGljIHNlbGVjdFRvb2wodG9vbDogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuY3VycmVudFRvb2wgPSB0b29sO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZWxlY3REcmF3aW5nU2l6ZShzaXplOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50U2l6ZSA9IHNpemU7XG4gICAgICAgIGlmICh0aGlzLmNhbnZhcykge1xuICAgICAgICAgICAgdGhpcy5jYW52YXMuZnJlZURyYXdpbmdCcnVzaC53aWR0aCA9IHRoaXMuZHJhd2luZ1NpemVzW3NpemVdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHNlbGVjdENvbG9yKGNvbG9yOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50Q29sb3IgPSBjb2xvcjtcbiAgICAgICAgaWYgKHRoaXMuY2FudmFzKSB7XG4gICAgICAgICAgICB0aGlzLmNhbnZhcy5mcmVlRHJhd2luZ0JydXNoLmNvbG9yID0gdGhpcy5jb2xvcnNbY29sb3JdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQWN0aW9uc1xuXG4gICAgcHVibGljIHVuZG8oKSB7XG4gICAgICAgIGlmICh0aGlzLmNhblVuZG8pIHtcbiAgICAgICAgICAgIGNvbnN0IGxhc3RJZCA9IHRoaXMuY2FudmFzLmdldE9iamVjdHMoKS5sZW5ndGggLSAxO1xuICAgICAgICAgICAgY29uc3QgbGFzdE9iaiA9IHRoaXMuY2FudmFzLmdldE9iamVjdHMoKVtsYXN0SWRdO1xuICAgICAgICAgICAgdGhpcy5zdGFjay5wdXNoKGxhc3RPYmopO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMucmVtb3ZlKGxhc3RPYmopO1xuICAgICAgICAgICAgdGhpcy5zZXRVbmRvUmVkbygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHJlZG8oKSB7XG4gICAgICAgIGlmICh0aGlzLmNhblJlZG8pIHtcbiAgICAgICAgICAgIGNvbnN0IGZpcnN0SW5TdGFjayA9IHRoaXMuc3RhY2suc3BsaWNlKC0xLCAxKVswXTtcbiAgICAgICAgICAgIGlmIChmaXJzdEluU3RhY2spIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbnZhcy5pbnNlcnRBdChmaXJzdEluU3RhY2ssIHRoaXMuY2FudmFzLmdldE9iamVjdHMoKS5sZW5ndGggLSAxLCBmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnNldFVuZG9SZWRvKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgY2xlYXJDYW52YXMoKSB7XG4gICAgICAgIGlmICh0aGlzLmNhbnZhcykge1xuICAgICAgICAgICAgdGhpcy5jYW52YXMucmVtb3ZlKC4uLnRoaXMuY2FudmFzLmdldE9iamVjdHMoKSk7XG4gICAgICAgICAgICB0aGlzLnNldFVuZG9SZWRvKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgc2F2ZUltYWdlKCkge1xuICAgICAgICBpZiAoIXRoaXMuZm9yY2VTaXplRXhwb3J0IHx8ICh0aGlzLmZvcmNlU2l6ZUV4cG9ydCAmJiB0aGlzLndpZHRoICYmIHRoaXMuaGVpZ2h0KSkge1xuICAgICAgICAgICAgY29uc3QgY2FudmFzU2NhbGVkRWxlbWVudDogSFRNTENhbnZhc0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgIGNvbnN0IGNhbnZhc1NjYWxlZCA9IG5ldyBmYWJyaWMuQ2FudmFzKGNhbnZhc1NjYWxlZEVsZW1lbnQpO1xuICAgICAgICAgICAgY2FudmFzU2NhbGVkLmJhY2tncm91bmRDb2xvciA9ICd3aGl0ZSc7XG5cbiAgICAgICAgICAgIG5ldyBPYnNlcnZhYmxlPGZhYnJpYy5DYW52YXM+KG9ic2VydmVyID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbWFnZVVzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZm9yY2VTaXplRXhwb3J0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYW52YXNTY2FsZWQuc2V0V2lkdGgodGhpcy53aWR0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYW52YXNTY2FsZWQuc2V0SGVpZ2h0KHRoaXMuaGVpZ2h0KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbWFnZVVzZWQuY2xvbmVBc0ltYWdlKGltYWdlQ2xvbmVkID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbWFnZUNsb25lZC5zY2FsZVRvV2lkdGgodGhpcy53aWR0aCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltYWdlQ2xvbmVkLnNjYWxlVG9IZWlnaHQodGhpcy5oZWlnaHQsIGZhbHNlKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhc1NjYWxlZC5zZXRCYWNrZ3JvdW5kSW1hZ2UoaW1hZ2VDbG9uZWQsIChpbWc6IEhUTUxJbWFnZUVsZW1lbnQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpbWcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmV