UNPKG

ngx-image-cropper

Version:
196 lines 31 kB
import { getTransformationsFromExifData, supportsAutomaticRotation } from '../utils/exif.utils'; export class LoadImageService { constructor() { this.autoRotateSupported = supportsAutomaticRotation(); } async loadImageFile(file, options) { const arrayBuffer = await file.arrayBuffer(); if (options.checkImageType) { return await this.checkImageTypeAndLoadImageFromArrayBuffer(arrayBuffer, file.type, options); } return await this.loadImageFromArrayBuffer(arrayBuffer, options); } checkImageTypeAndLoadImageFromArrayBuffer(arrayBuffer, imageType, options) { if (!this.isValidImageType(imageType)) { return Promise.reject(new Error('Invalid image type')); } return this.loadImageFromArrayBuffer(arrayBuffer, options, imageType); } isValidImageType(type) { return /image\/(png|jpg|jpeg|heic|bmp|gif|tiff|svg|webp|x-icon|vnd.microsoft.icon|avif)/.test(type); } async loadImageFromURL(url, options) { const res = await fetch(url); const blob = await res.blob(); const buffer = await blob.arrayBuffer(); return await this.loadImageFromArrayBuffer(buffer, options, blob.type); } loadBase64Image(imageBase64, options) { const arrayBuffer = this.base64ToArrayBuffer(imageBase64); return this.loadImageFromArrayBuffer(arrayBuffer, options); } base64ToArrayBuffer(imageBase64) { imageBase64 = imageBase64.replace(/^data:([^;]+);base64,/gmi, ''); const binaryString = atob(imageBase64); const len = binaryString.length; const bytes = new Uint8Array(len); for (let i = 0; i < len; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes.buffer; } async loadImageFromArrayBuffer(arrayBuffer, options, imageType) { const res = await new Promise(async (resolve, reject) => { try { const blob = new Blob([arrayBuffer], imageType ? { type: imageType } : undefined); const objectUrl = URL.createObjectURL(blob); const originalImage = new Image(); const isSvg = imageType === 'image/svg+xml'; const originalImageSize = isSvg ? await this.getSvgImageSize(blob) : undefined; originalImage.onload = () => resolve({ originalImage, originalImageSize, originalObjectUrl: objectUrl, originalArrayBuffer: arrayBuffer }); originalImage.onerror = reject; originalImage.src = objectUrl; } catch (e) { reject(e); } }); return await this.transformImageFromArrayBuffer(res, options, res.originalImageSize != null); } async getSvgImageSize(blob) { const parser = new DOMParser(); const doc = parser.parseFromString(await blob.text(), 'image/svg+xml'); const svgElement = doc.querySelector('svg'); if (!svgElement) { throw Error('Failed to parse SVG image'); } const widthAttr = svgElement.getAttribute('width'); const heightAttr = svgElement.getAttribute('height'); if (widthAttr && heightAttr) { return null; } const viewBoxAttr = svgElement.getAttribute('viewBox') || svgElement.getAttribute('viewbox'); if (viewBoxAttr) { const viewBox = viewBoxAttr.split(' '); return { width: +viewBox[2], height: +viewBox[3] }; } throw Error('Failed to load SVG image. SVG must have width + height or viewBox definition.'); } async transformImageFromArrayBuffer(res, options, forceTransform = false) { const autoRotate = await this.autoRotateSupported; const exifTransform = getTransformationsFromExifData(autoRotate ? -1 : res.originalArrayBuffer); if (!res.originalImage || !res.originalImage.complete) { return Promise.reject(new Error('No image loaded')); } const loadedImage = { original: { objectUrl: res.originalObjectUrl, image: res.originalImage, size: res.originalImageSize ?? { width: res.originalImage.naturalWidth, height: res.originalImage.naturalHeight } }, exifTransform }; return this.transformLoadedImage(loadedImage, options, forceTransform); } async transformLoadedImage(loadedImage, options, forceTransform = false) { const canvasRotation = (options.canvasRotation ?? 0) + loadedImage.exifTransform.rotate; const originalSize = loadedImage.original.size; if (!forceTransform && canvasRotation === 0 && !loadedImage.exifTransform.flip && !options.containWithinAspectRatio) { return { original: { objectUrl: loadedImage.original.objectUrl, image: loadedImage.original.image, size: { ...originalSize } }, transformed: { objectUrl: loadedImage.original.objectUrl, image: loadedImage.original.image, size: { ...originalSize } }, exifTransform: loadedImage.exifTransform }; } const transformedSize = this.getTransformedSize(originalSize, loadedImage.exifTransform, options); const canvas = document.createElement('canvas'); canvas.width = transformedSize.width; canvas.height = transformedSize.height; const ctx = canvas.getContext('2d'); ctx?.setTransform(loadedImage.exifTransform.flip ? -1 : 1, 0, 0, 1, canvas.width / 2, canvas.height / 2); ctx?.rotate(Math.PI * (canvasRotation / 2)); ctx?.drawImage(loadedImage.original.image, -originalSize.width / 2, -originalSize.height / 2); const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/' + (options.format ?? 'png'))); if (!blob) { throw new Error('Failed to get Blob for transformed image.'); } const objectUrl = URL.createObjectURL(blob); const transformedImage = await this.loadImageFromObjectUrl(objectUrl); return { original: { objectUrl: loadedImage.original.objectUrl, image: loadedImage.original.image, size: { ...originalSize } }, transformed: { objectUrl: objectUrl, image: transformedImage, size: { width: transformedImage.width, height: transformedImage.height } }, exifTransform: loadedImage.exifTransform }; } loadImageFromObjectUrl(objectUrl) { return new Promise(((resolve, reject) => { const image = new Image(); image.onload = () => resolve(image); image.onerror = reject; image.src = objectUrl; })); } getTransformedSize(originalSize, exifTransform, options) { const canvasRotation = (options.canvasRotation ?? 0) + exifTransform.rotate; if (options.containWithinAspectRatio) { if (canvasRotation % 2) { const minWidthToContain = originalSize.width * (options.aspectRatio ?? 1); const minHeightToContain = originalSize.height / (options.aspectRatio ?? 1); return { width: Math.max(originalSize.height, minWidthToContain), height: Math.max(originalSize.width, minHeightToContain) }; } else { const minWidthToContain = originalSize.height * (options.aspectRatio ?? 1); const minHeightToContain = originalSize.width / (options.aspectRatio ?? 1); return { width: Math.max(originalSize.width, minWidthToContain), height: Math.max(originalSize.height, minHeightToContain) }; } } if (canvasRotation % 2) { return { height: originalSize.width, width: originalSize.height }; } return { width: originalSize.width, height: originalSize.height }; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZC1pbWFnZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWltYWdlLWNyb3BwZXIvc3JjL2xpYi9zZXJ2aWNlcy9sb2FkLWltYWdlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLDhCQUE4QixFQUFFLHlCQUF5QixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFTaEcsTUFBTSxPQUFPLGdCQUFnQjtJQUE3QjtRQUVVLHdCQUFtQixHQUFxQix5QkFBeUIsRUFBRSxDQUFDO0lBeU45RSxDQUFDO0lBdk5DLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBVSxFQUFFLE9BQXlCO1FBQ3ZELE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzdDLElBQUksT0FBTyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQzNCLE9BQU8sTUFBTSxJQUFJLENBQUMseUNBQXlDLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDL0YsQ0FBQztRQUNELE9BQU8sTUFBTSxJQUFJLENBQUMsd0JBQXdCLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFFTyx5Q0FBeUMsQ0FBQyxXQUE0QixFQUFFLFNBQWlCLEVBQUUsT0FBeUI7UUFDMUgsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQ3RDLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUM7UUFDekQsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLHdCQUF3QixDQUFDLFdBQVcsRUFBRSxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDeEUsQ0FBQztJQUVPLGdCQUFnQixDQUFDLElBQVk7UUFDbkMsT0FBTyxp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LENBQUM7Z0JBQ04sTUFBTSxpQkFBaUIsR0FBRyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsT0FBTyxDQUFDLFdBQVcsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDM0UsTUFBTSxrQkFBa0IsR0FBRyxZQUFZLENBQUMsS0FBSyxHQUFHLENBQUMsT0FBTyxDQUFDLFdBQVcsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDM0UsT0FBTztvQkFDTCxLQUFLLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLGlCQUFpQixDQUFDO29CQUN0RCxNQUFNLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLGtCQUFrQixDQUFDO2lCQUMxRCxDQUFDO1lBQ0osQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLGNBQWMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN2QixPQUFPO2dCQUNMLE1BQU0sRUFBRSxZQUFZLENBQUMsS0FBSztnQkFDMUIsS0FBSyxFQUFFLFlBQVksQ0FBQyxNQUFNO2FBQzNCLENBQUM7UUFDSixDQUFDO1FBQ0QsT0FBTztZQUNMLEtBQUssRUFBRSxZQUFZLENBQUMsS0FBSztZQUN6QixNQUFNLEVBQUUsWUFBWSxDQUFDLE1BQU07U0FDNUIsQ0FBQztJQUNKLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERpbWVuc2lvbnMsIExvYWRlZEltYWdlLCBMb2FkSW1hZ2VPcHRpb25zIH0gZnJvbSAnLi4vaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBFeGlmVHJhbnNmb3JtIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9leGlmLXRyYW5zZm9ybS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgZ2V0VHJhbnNmb3JtYXRpb25zRnJvbUV4aWZEYXRhLCBzdXBwb3J0c0F1dG9tYXRpY1JvdGF0aW9uIH0gZnJvbSAnLi4vdXRpbHMvZXhpZi51dGlscyc7XG5cbmludGVyZmFjZSBMb2FkSW1hZ2VBcnJheUJ1ZmZlciB7XG4gIG9yaWdpbmFsSW1hZ2U6IEhUTUxJbWFnZUVsZW1lbnQ7XG4gIG9yaWdpbmFsQXJyYXlCdWZmZXI6IEFycmF5QnVmZmVyTGlrZTtcbiAgb3JpZ2luYWxPYmplY3RVcmw6IHN0cmluZztcbiAgb3JpZ2luYWxJbWFnZVNpemU/OiB7IHdpZHRoOiBudW1iZXI7IGhlaWdodDogbnVtYmVyOyB9IHwgbnVsbDtcbn1cblxuZXhwb3J0IGNsYXNzIExvYWRJbWFnZVNlcnZpY2Uge1xuXG4gIHByaXZhdGUgYXV0b1JvdGF0ZVN1cHBvcnRlZDogUHJvbWlzZTxib29sZWFuPiA9IHN1cHBvcnRzQXV0b21hdGljUm90YXRpb24oKTtcblxuICBhc3luYyBsb2FkSW1hZ2VGaWxlKGZpbGU6IEZpbGUsIG9wdGlvbnM6IExvYWRJbWFnZU9wdGlvbnMpOiBQcm9taXNlPExvYWRlZEltYWdlPiB7XG4gICAgY29uc3QgYXJyYXlCdWZmZXIgPSBhd2FpdCBmaWxlLmFycmF5QnVmZmVyKCk7XG4gICAgaWYgKG9wdGlvbnMuY2hlY2tJbWFnZVR5cGUpIHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNoZWNrSW1hZ2VUeXBlQW5kTG9hZEltYWdlRnJvbUFycmF5QnVmZmVyKGFycmF5QnVmZmVyLCBmaWxlLnR5cGUsIG9wdGlvbnMpO1xuICAgIH1cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5sb2FkSW1hZ2VGcm9tQXJyYXlCdWZmZXIoYXJyYXlCdWZmZXIsIG9wdGlvbnMpO1xuICB9XG5cbiAgcHJpdmF0ZSBjaGVja0ltYWdlVHlwZUFuZExvYWRJbWFnZUZyb21BcnJheUJ1ZmZlcihhcnJheUJ1ZmZlcjogQXJyYXlCdWZmZXJMaWtlLCBpbWFnZVR5cGU6IHN0cmluZywgb3B0aW9uczogTG9hZEltYWdlT3B0aW9ucyk6IFByb21pc2U8TG9hZGVkSW1hZ2U+IHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZEltYWdlVHlwZShpbWFnZVR5cGUpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdJbnZhbGlkIGltYWdlIHR5cGUnKSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmxvYWRJbWFnZUZyb21BcnJheUJ1ZmZlcihhcnJheUJ1ZmZlciwgb3B0aW9ucywgaW1hZ2VUeXBlKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNWYWxpZEltYWdlVHlwZSh0eXBlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gL2ltYWdlXFwvKHBuZ3xqcGd8anBlZ3xoZWljfGJtcHxnaWZ8dGlmZnxzdmd8d2VicHx4LWljb258dm5kLm1pY3Jvc29mdC5pY29ufGF2aWYpLy50ZXN0KHR5cGUpO1xuICB9XG5cbiAgYXN5bmMgbG9hZEltYWdlRnJvbVVSTCh1cmw6IHN0cmluZywgb3B0aW9uczogTG9hZEltYWdlT3B0aW9ucyk6IFByb21pc2U8TG9hZGVkSW1hZ2U+IHtcbiAgICBjb25zdCByZXMgPSBhd2FpdCBmZXRjaCh1cmwpO1xuICAgIGNvbnN0IGJsb2IgPSBhd2FpdCByZXMuYmxvYigpO1xuICAgIGNvbnN0IGJ1ZmZlciA9IGF3YWl0IGJsb2IuYXJyYXlCdWZmZXIoKTtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5sb2FkSW1hZ2VGcm9tQXJyYXlCdWZmZXIoYnVmZmVyLCBvcHRpb25zLCBibG9iLnR5cGUpO1xuICB9XG5cbiAgbG9hZEJhc2U2NEltYWdlKGltYWdlQmFzZTY0OiBzdHJpbmcsIG9wdGlvbnM6IExvYWRJbWFnZU9wdGlvbnMpOiBQcm9taXNlPExvYWRlZEltYWdlPiB7XG4gICAgY29uc3QgYXJyYXlCdWZmZXIgPSB0aGlzLmJhc2U2NFRvQXJyYXlCdWZmZXIoaW1hZ2VCYXNlNjQpO1xuICAgIHJldHVybiB0aGlzLmxvYWRJbWFnZUZyb21BcnJheUJ1ZmZlcihhcnJheUJ1ZmZlciwgb3B0aW9ucyk7XG4gIH1cblxuICBwcml2YXRlIGJhc2U2NFRvQXJyYXlCdWZmZXIoaW1hZ2VCYXNlNjQ6IHN0cmluZyk6IEFycmF5QnVmZmVyTGlrZSB7XG4gICAgaW1hZ2VCYXNlNjQgPSBpbWFnZUJhc2U2NC5yZXBsYWNlKC9eZGF0YTooW147XSspO2Jhc2U2NCwvZ21pLCAnJyk7XG4gICAgY29uc3QgYmluYXJ5U3RyaW5nID0gYXRvYihpbWFnZUJhc2U2NCk7XG4gICAgY29uc3QgbGVuID0gYmluYXJ5U3RyaW5nLmxlbmd0aDtcbiAgICBjb25zdCBieXRlcyA9IG5ldyBVaW50OEFycmF5KGxlbik7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgYnl0ZXNbaV0gPSBiaW5hcnlTdHJpbmcuY2hhckNvZGVBdChpKTtcbiAgICB9XG4gICAgcmV0dXJuIGJ5dGVzLmJ1ZmZlcjtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9hZEltYWdlRnJvbUFycmF5QnVmZmVyKGFycmF5QnVmZmVyOiBBcnJheUJ1ZmZlckxpa2UsIG9wdGlvbnM6IExvYWRJbWFnZU9wdGlvbnMsIGltYWdlVHlwZT86IHN0cmluZyk6IFByb21pc2U8TG9hZGVkSW1hZ2U+IHtcbiAgICBjb25zdCByZXMgPSBhd2FpdCBuZXcgUHJvbWlzZTxMb2FkSW1hZ2VBcnJheUJ1ZmZlcj4oYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgYmxvYiA9IG5ldyBCbG9iKFthcnJheUJ1ZmZlcl0sIGltYWdlVHlwZSA/IHt0eXBlOiBpbWFnZVR5cGV9IDogdW5kZWZpbmVkKTtcbiAgICAgICAgY29uc3Qgb2JqZWN0VXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKTtcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxJbWFnZSA9IG5ldyBJbWFnZSgpO1xuICAgICAgICBjb25zdCBpc1N2ZyA9IGltYWdlVHlwZSA9PT0gJ2ltYWdlL3N2Zyt4bWwnO1xuICAgICAgICBjb25zdCBvcmlnaW5hbEltYWdlU2l6ZSA9IGlzU3ZnID8gYXdhaXQgdGhpcy5nZXRTdmdJbWFnZVNpemUoYmxvYikgOiB1bmRlZmluZWQ7XG4gICAgICAgIG9yaWdpbmFsSW1hZ2Uub25sb2FkID0gKCkgPT4gcmVzb2x2ZSh7XG4gICAgICAgICAgb3JpZ2luYWxJbWFnZSxcbiAgICAgICAgICBvcmlnaW5hbEltYWdlU2l6ZSxcbiAgICAgICAgICBvcmlnaW5hbE9iamVjdFVybDogb2JqZWN0VXJsLFxuICAgICAgICAgIG9yaWdpbmFsQXJyYXlCdWZmZXI6IGFycmF5QnVmZmVyXG4gICAgICAgIH0pO1xuICAgICAgICBvcmlnaW5hbEltYWdlLm9uZXJyb3IgPSByZWplY3Q7XG4gICAgICAgIG9yaWdpbmFsSW1hZ2Uuc3JjID0gb2JqZWN0VXJsO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZWplY3QoZSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMudHJhbnNmb3JtSW1hZ2VGcm9tQXJyYXlCdWZmZXIocmVzLCBvcHRpb25zLCByZXMub3JpZ2luYWxJbWFnZVNpemUgIT0gbnVsbCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldFN2Z0ltYWdlU2l6ZShibG9iOiBCbG9iKTogUHJvbWlzZTx7IHdpZHRoOiBudW1iZXI7IGhlaWdodDogbnVtYmVyOyB9IHwgbnVsbD4ge1xuICAgIGNvbnN0IHBhcnNlciA9IG5ldyBET01QYXJzZXIoKTtcbiAgICBjb25zdCBkb2MgPSBwYXJzZXIucGFyc2VGcm9tU3RyaW5nKGF3YWl0IGJsb2IudGV4dCgpLCAnaW1hZ2Uvc3ZnK3htbCcpO1xuICAgIGNvbnN0IHN2Z0VsZW1lbnQgPSBkb2MucXVlcnlTZWxlY3Rvcignc3ZnJyk7XG4gICAgaWYgKCFzdmdFbGVtZW50KSB7XG4gICAgICB0aHJvdyBFcnJvcignRmFpbGVkIHRvIHBhcnNlIFNWRyBpbWFnZScpO1xuICAgIH1cbiAgICBjb25zdCB3aWR0aEF0dHIgPSBzdmdFbGVtZW50LmdldEF0dHJpYnV0ZSgnd2lkdGgnKTtcbiAgICBjb25zdCBoZWlnaHRBdHRyID0gc3ZnRWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2hlaWdodCcpO1xuICAgIGlmICh3aWR0aEF0dHIgJiYgaGVpZ2h0QXR0cikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IHZpZXdCb3hBdHRyID0gc3ZnRWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnKVxuICAgICAgfHwgc3ZnRWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3ZpZXdib3gnKTtcbiAgICBpZiAodmlld0JveEF0dHIpIHtcbiAgICAgIGNvbnN0IHZpZXdCb3ggPSB2aWV3Qm94QXR0ci5zcGxpdCgnICcpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgd2lkdGg6ICt2aWV3Qm94WzJdLFxuICAgICAgICBoZWlnaHQ6ICt2aWV3Qm94WzNdXG4gICAgICB9O1xuICAgIH1cbiAgICB0aHJvdyBFcnJvcignRmFpbGVkIHRvIGxvYWQgU1ZHIGltYWdlLiBTVkcgbXVzdCBoYXZlIHdpZHRoICsgaGVpZ2h0IG9yIHZpZXdCb3ggZGVmaW5pdGlvbi4nKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdHJhbnNmb3JtSW1hZ2VGcm9tQXJyYXlCdWZmZXIocmVzOiBMb2FkSW1hZ2VBcnJheUJ1ZmZlciwgb3B0aW9uczogTG9hZEltYWdlT3B0aW9ucywgZm9yY2VUcmFuc2Zvcm0gPSBmYWxzZSk6IFByb21pc2U8TG9hZGVkSW1hZ2U+IHtcbiAgICBjb25zdCBhdXRvUm90YXRlID0gYXdhaXQgdGhpcy5hdXRvUm90YXRlU3VwcG9ydGVkO1xuICAgIGNvbnN0IGV4aWZUcmFuc2Zvcm0gPSBnZXRUcmFuc2Zvcm1hdGlvbnNGcm9tRXhpZkRhdGEoYXV0b1JvdGF0ZSA/IC0xIDogcmVzLm9yaWdpbmFsQXJyYXlCdWZmZXIpO1xuICAgIGlmICghcmVzLm9yaWdpbmFsSW1hZ2UgfHwgIXJlcy5vcmlnaW5hbEltYWdlLmNvbXBsZXRlKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdObyBpbWFnZSBsb2FkZWQnKSk7XG4gICAgfVxuICAgIGNvbnN0IGxvYWRlZEltYWdlID0ge1xuICAgICAgb3JpZ2luYWw6IHtcbiAgICAgICAgb2JqZWN0VXJsOiByZXMub3JpZ2luYWxPYmplY3RVcmwsXG4gICAgICAgIGltYWdlOiByZXMub3JpZ2luYWxJbWFnZSxcbiAgICAgICAgc2l6ZTogcmVzLm9yaWdpbmFsSW1hZ2VTaXplID8/IHtcbiAgICAgICAgICB3aWR0aDogcmVzLm9yaWdpbmFsSW1hZ2UubmF0dXJhbFdpZHRoLFxuICAgICAgICAgIGhlaWdodDogcmVzLm9yaWdpbmFsSW1hZ2UubmF0dXJhbEhlaWdodFxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZXhpZlRyYW5zZm9ybVxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMudHJhbnNmb3JtTG9hZGVkSW1hZ2UobG9hZGVkSW1hZ2UsIG9wdGlvbnMsIGZvcmNlVHJhbnNmb3JtKTtcbiAgfVxuXG4gIGFzeW5jIHRyYW5zZm9ybUxvYWRlZEltYWdlKGxvYWRlZEltYWdlOiBQYXJ0aWFsPExvYWRlZEltYWdlPiwgb3B0aW9uczogTG9hZEltYWdlT3B0aW9ucywgZm9yY2VUcmFuc2Zvcm0gPSBmYWxzZSk6IFByb21pc2U8TG9hZGVkSW1hZ2U+IHtcbiAgICBjb25zdCBjYW52YXNSb3RhdGlvbiA9IChvcHRpb25zLmNhbnZhc1JvdGF0aW9uID8/IDApICsgbG9hZGVkSW1hZ2UuZXhpZlRyYW5zZm9ybSEucm90YXRlO1xuICAgIGNvbnN0IG9yaWdpbmFsU2l6ZSA9IGxvYWRlZEltYWdlLm9yaWdpbmFsIS5zaXplO1xuICAgIGlmICghZm9yY2VUcmFuc2Zvcm0gJiYgY2FudmFzUm90YXRpb24gPT09IDAgJiYgIWxvYWRlZEltYWdlLmV4aWZUcmFuc2Zvcm0hLmZsaXAgJiYgIW9wdGlvbnMuY29udGFpbldpdGhpbkFzcGVjdFJhdGlvKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBvcmlnaW5hbDoge1xuICAgICAgICAgIG9iamVjdFVybDogbG9hZGVkSW1hZ2Uub3JpZ2luYWwhLm9iamVjdFVybCxcbiAgICAgICAgICBpbWFnZTogbG9hZGVkSW1hZ2Uub3JpZ2luYWwhLmltYWdlLFxuICAgICAgICAgIHNpemU6IHsuLi5vcmlnaW5hbFNpemV9XG4gICAgICAgIH0sXG4gICAgICAgIHRyYW5zZm9ybWVkOiB7XG4gICAgICAgICAgb2JqZWN0VXJsOiBsb2FkZWRJbWFnZS5vcmlnaW5hbCEub2JqZWN0VXJsLFxuICAgICAgICAgIGltYWdlOiBsb2FkZWRJbWFnZS5vcmlnaW5hbCEuaW1hZ2UsXG4gICAgICAgICAgc2l6ZTogey4uLm9yaWdpbmFsU2l6ZX1cbiAgICAgICAgfSxcbiAgICAgICAgZXhpZlRyYW5zZm9ybTogbG9hZGVkSW1hZ2UuZXhpZlRyYW5zZm9ybSFcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgdHJhbnNmb3JtZWRTaXplID0gdGhpcy5nZXRUcmFuc2Zvcm1lZFNpemUob3JpZ2luYWxTaXplLCBsb2FkZWRJbWFnZS5leGlmVHJhbnNmb3JtISwgb3B0aW9ucyk7XG4gICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgY2FudmFzLndpZHRoID0gdHJhbnNmb3JtZWRTaXplLndpZHRoO1xuICAgIGNhbnZhcy5oZWlnaHQgPSB0cmFuc2Zvcm1lZFNpemUuaGVpZ2h0O1xuICAgIGNvbnN0IGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgIGN0eD8uc2V0VHJhbnNmb3JtKFxuICAgICAgbG9hZGVkSW1hZ2UuZXhpZlRyYW5zZm9ybSEuZmxpcCA/IC0xIDogMSxcbiAgICAgIDAsXG4gICAgICAwLFxuICAgICAgMSxcbiAgICAgIGNhbnZhcy53aWR0aCAvIDIsXG4gICAgICBjYW52YXMuaGVpZ2h0IC8gMlxuICAgICk7XG4gICAgY3R4Py5yb3RhdGUoTWF0aC5QSSAqIChjYW52YXNSb3RhdGlvbiAvIDIpKTtcbiAgICBjdHg/LmRyYXdJbWFnZShcbiAgICAgIGxvYWRlZEltYWdlLm9yaWdpbmFsIS5pbWFnZSxcbiAgICAgIC1vcmlnaW5hbFNpemUud2lkdGggLyAyLFxuICAgICAgLW9yaWdpbmFsU2l6ZS5oZWlnaHQgLyAyXG4gICAgKTtcbiAgICBjb25zdCBibG9iID0gYXdhaXQgbmV3IFByb21pc2U8QmxvYiB8IG51bGw+KHJlc29sdmUgPT4gY2FudmFzLnRvQmxvYihyZXNvbHZlLCAnaW1hZ2UvJyArIChvcHRpb25zLmZvcm1hdCA/PyAncG5nJykpKTtcbiAgICBpZiAoIWJsb2IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGdldCBCbG9iIGZvciB0cmFuc2Zvcm1lZCBpbWFnZS4nKTtcbiAgICB9XG4gICAgY29uc3Qgb2JqZWN0VXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKTtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZEltYWdlID0gYXdhaXQgdGhpcy5sb2FkSW1hZ2VGcm9tT2JqZWN0VXJsKG9iamVjdFVybCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIG9yaWdpbmFsOiB7XG4gICAgICAgIG9iamVjdFVybDogbG9hZGVkSW1hZ2Uub3JpZ2luYWwhLm9iamVjdFVybCxcbiAgICAgICAgaW1hZ2U6IGxvYWRlZEltYWdlLm9yaWdpbmFsIS5pbWFnZSxcbiAgICAgICAgc2l6ZTogey4uLm9yaWdpbmFsU2l6ZX1cbiAgICAgIH0sXG4gICAgICB0cmFuc2Zvcm1lZDoge1xuICAgICAgICBvYmplY3RVcmw6IG9iamVjdFVybCxcbiAgICAgICAgaW1hZ2U6IHRyYW5zZm9ybWVkSW1hZ2UsXG4gICAgICAgIHNpemU6IHtcbiAgICAgICAgICB3aWR0aDogdHJhbnNmb3JtZWRJbWFnZS53aWR0aCxcbiAgICAgICAgICBoZWlnaHQ6IHRyYW5zZm9ybWVkSW1hZ2UuaGVpZ2h0XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBleGlmVHJhbnNmb3JtOiBsb2FkZWRJbWFnZS5leGlmVHJhbnNmb3JtIVxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGxvYWRJbWFnZUZyb21PYmplY3RVcmwob2JqZWN0VXJsOiBzdHJpbmcpOiBQcm9taXNlPEhUTUxJbWFnZUVsZW1lbnQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8SFRNTEltYWdlRWxlbWVudD4oKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IGltYWdlID0gbmV3IEltYWdlKCk7XG4gICAgICBpbWFnZS5vbmxvYWQgPSAoKSA9PiByZXNvbHZlKGltYWdlKTtcbiAgICAgIGltYWdlLm9uZXJyb3IgPSByZWplY3Q7XG4gICAgICBpbWFnZS5zcmMgPSBvYmplY3RVcmw7XG4gICAgfSkpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRUcmFuc2Zvcm1lZFNpemUoXG4gICAgb3JpZ2luYWxTaXplOiB7IHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyIH0sXG4gICAgZXhpZlRyYW5zZm9ybTogRXhpZlRyYW5zZm9ybSxcbiAgICBvcHRpb25zOiBMb2FkSW1hZ2VPcHRpb25zXG4gICk6IERpbWVuc2lvbnMge1xuICAgIGNvbnN0IGNhbnZhc1JvdGF0aW9uID0gKG9wdGlvbnMuY2FudmFzUm90YXRpb24gPz8gMCkgKyBleGlmVHJhbnNmb3JtLnJvdGF0ZTtcbiAgICBpZiAob3B0aW9ucy5jb250YWluV2l0aGluQXNwZWN0UmF0aW8pIHtcbiAgICAgIGlmIChjYW52YXNSb3RhdGlvbiAlIDIpIHtcbiAgICAgICAgY29uc3QgbWluV2lkdGhUb0NvbnRhaW4gPSBvcmlnaW5hbFNpemUud2lkdGggKiAob3B0aW9ucy5hc3BlY3RSYXRpbyA/PyAxKTtcbiAgICAgICAgY29uc3QgbWluSGVpZ2h0VG9Db250YWluID0gb3JpZ2luYWxTaXplLmhlaWdodCAvIChvcHRpb25zLmFzcGVjdFJhdGlvID8/IDEpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHdpZHRoOiBNYXRoLm1heChvcmlnaW5hbFNpemUuaGVpZ2h0LCBtaW5XaWR0aFRvQ29udGFpbiksXG4gICAgICAgICAgaGVpZ2h0OiBNYXRoLm1heChvcmlnaW5hbFNpemUud2lkdGgsIG1pbkhlaWdodFRvQ29udGFpbilcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IG1pbldpZHRoVG9Db250YWluID0gb3JpZ2luYWxTaXplLmhlaWdodCAqIChvcHRpb25zLmFzcGVjdFJhdGlvID8/IDEpO1xuICAgICAgICBjb25zdCBtaW5IZWlnaHRUb0NvbnRhaW4gPSBvcmlnaW5hbFNpemUud2lkdGggLyAob3B0aW9ucy5hc3BlY3RSYXRpbyA/PyAxKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB3aWR0aDogTWF0aC5tYXgob3JpZ2luYWxTaXplLndpZHRoLCBtaW5XaWR0aFRvQ29udGFpbiksXG4gICAgICAgICAgaGVpZ2h0OiBNYXRoLm1heChvcmlnaW5hbFNpemUuaGVpZ2h0LCBtaW5IZWlnaHRUb0NvbnRhaW4pXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhbnZhc1JvdGF0aW9uICUgMikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGVpZ2h0OiBvcmlnaW5hbFNpemUud2lkdGgsXG4gICAgICAgIHdpZHRoOiBvcmlnaW5hbFNpemUuaGVpZ2h0XG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgd2lkdGg6IG9yaWdpbmFsU2l6ZS53aWR0aCxcbiAgICAgIGhlaWdodDogb3JpZ2luYWxTaXplLmhlaWdodFxuICAgIH07XG4gIH1cbn1cbiJdfQ==