ng-cw-v12
Version:
Angular UI component library
402 lines • 66.3 kB
JavaScript
import { __awaiter } from "tslib";
import { Component, EventEmitter, Input, Output } from '@angular/core';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/forms";
export class ImgClipComponent {
constructor(eleRef) {
this.eleRef = eleRef;
this.ncConfirm = new EventEmitter(); //确认裁剪回调
this.ncImgType = 'base64'; //裁剪回调返回图片格式
this.ncWidth = 300; //容器宽度
this.ncClipSize = 0.7; //默认裁剪框的尺寸占图片比例
this.ncClipMinWidth = 50; //裁剪框最小宽度
this.ncClipMinHeight = 50; //裁剪框最小高度
this.downloadMode = false;
this.toolMode = false;
this.uploadMode = false;
this.hasImage = false;
// 图片当前宽高
this.clipImageWidth = 0;
this.clipImageHeight = 0;
// 图片原始宽高
this.clipImageOriginWidth = 0;
this.clipImageOriginHeight = 0;
this.scale = 0; //缩放比例
this.clipWidth = 0; //裁剪框宽度
this.clipHeight = 0; //裁剪框高度
this.clipX = 0; //裁剪框x
this.clipY = 0; //裁剪框y
}
set ncUrl(value) {
setTimeout(() => {
//加延迟,防止其他传入参数未获取到
this.readImage(value);
});
}
;
//确认裁剪时是否下载图片
set ncDownload(value) {
this.downloadMode = value !== null && value !== undefined && value !== false && value !== 'false';
}
//调整工具栏
set ncTool(value) {
this.toolMode = value !== null && value !== undefined && value !== false && value !== 'false';
}
//上传
set ncUpload(value) {
this.uploadMode = value !== null && value !== undefined && value !== false && value !== 'false';
}
ngOnInit() {
this.clipImage = this.eleRef.nativeElement.querySelector('#clipImage');
this.clipPathImg = this.eleRef.nativeElement.querySelector('#clipPathImg');
this.clip = this.eleRef.nativeElement.querySelector('#clip');
if (this.uploadMode) {
setTimeout(() => {
this.file = this.eleRef.nativeElement.querySelector('#file');
// 监听上传状态 浏览图片
this.file.addEventListener('change', (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
this.readImage(reader.result);
};
});
});
}
//裁剪框缩放、拖拽
this.clipBoxZoom();
this.clipBpxDrag();
}
//读取图片
readImage(url) {
// 读取到的图片数据
this.clipImage.src = url;
// 裁剪使用的图片
this.clipPathImg.src = url;
//获取当前图片的宽高
this.getClipImageSize(url).then((res) => {
// 初始化
this.init();
this.hasImage = true;
});
}
// 获取上传图片的当前尺寸和原始尺寸
getClipImageSize(dataurl) {
return __awaiter(this, void 0, void 0, function* () {
const data = yield new Promise((resolve) => {
this.clipImage.onload = () => {
resolve(this.clipImage);
};
});
// 获取图片当前宽高
this.clipImageWidth = data.width;
this.clipImageHeight = data.height;
const data_1 = yield new Promise((resolve_1) => {
// 获取图片原始宽高
let img = document.createElement('img');
img.src = dataurl;
img.onload = () => {
resolve_1(img);
};
});
// 获取图片原始宽高
this.clipImageOriginWidth = data_1.width;
this.clipImageOriginHeight = data_1.height;
return yield Promise.resolve();
});
}
// 初始化
init() {
// 显示裁剪框
this.clip.style.display = 'block';
// 缩放比例
this.scale = this.clipImageOriginWidth / this.clipImageWidth;
// 设置裁剪框的宽高
let clipWidth = Math.floor(this.clipImageWidth * this.ncClipSize);
let clipHeight = Math.floor(this.clipImageHeight * this.ncClipSize);
this.setClipSize(clipWidth, clipHeight);
// 设置裁剪框的位置
let x = Math.floor((this.clipImageWidth - clipWidth) / 2);
let y = Math.floor((this.clipImageHeight - clipHeight) / 2);
this.setClipPosition(x, y);
}
// 设置裁剪框的尺寸
setClipSize(clipWidth, clipHeight) {
this.clip.style.setProperty('--clipWidth', clipWidth + 'px');
this.clip.style.setProperty('--clipHeight', clipHeight + 'px');
this.clipWidth = clipWidth;
this.clipHeight = clipHeight;
}
// 设置裁剪框的位置
setClipPosition(x, y) {
this.clip.style.setProperty('--clipX', x + 'px');
this.clip.style.setProperty('--clipY', y + 'px');
this.clipX = x;
this.clipY = y;
// 设置裁剪阴影
this.setClipPath();
}
// 设置裁剪阴影
setClipPath() {
let lt = this.clip.offsetLeft + 'px' + ' ' + this.clip.offsetTop + 'px';
let rt = (this.clip.offsetLeft + this.clip.offsetWidth) + 'px' + ' ' + this.clip.offsetTop + 'px';
let rb = (this.clip.offsetLeft + this.clip.offsetWidth) + 'px' + ' ' + (this.clip.offsetTop + this.clip.offsetHeight) + 'px';
let lb = this.clip.offsetLeft + 'px' + ' ' + (this.clip.offsetTop + this.clip.offsetHeight) + 'px';
this.clipPathImg.style.setProperty('--clipPath', `polygon(${lt}, ${rt}, ${rb}, ${lb})`);
}
// 裁剪
clipImg(x, y, cutWidth, cutHeight, width, height) {
return __awaiter(this, void 0, void 0, function* () {
let canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(this.clipImage, x, y, cutWidth, cutHeight, 0, 0, width, height);
//下载
if (this.downloadMode) {
const a = document.createElement('a');
a.download = '裁剪图片';
a.href = canvas.toDataURL('image/png');
a.click();
}
// 返回裁剪后的图片
return new Promise((resolve) => {
if (this.ncImgType == 'base64') {
resolve(canvas.toDataURL('image/png'));
}
else {
canvas.toBlob((blob) => {
resolve(new File([blob], 'clip.png', { type: 'image/png' }));
});
}
});
});
}
//确认裁剪
confirm() {
return __awaiter(this, void 0, void 0, function* () {
let res = yield this.clipImg(this.clip.offsetLeft * this.scale, this.clip.offsetTop * this.scale, this.clip.offsetWidth * this.scale, this.clip.offsetHeight * this.scale, this.clip.offsetWidth, this.clip.offsetHeight);
this.ncConfirm.emit(res);
});
}
//裁剪框的拖拽
clipBpxDrag() {
// 鼠标按下
this.clip.onmousedown = (e) => {
// 偏移量
let py = {
x: e.clientX - this.clip.offsetLeft,
y: e.clientY - this.clip.offsetTop
};
// 鼠标移动
window.onmousemove = (e) => {
// 鼠标移动的距离
let moveX = e.clientX - py.x;
let moveY = e.clientY - py.y;
// 裁剪框的位置
let left = moveX;
let top = moveY;
// 裁剪框的位置限制
if (left < 0) {
left = 0;
}
if (top < 0) {
top = 0;
}
if (left > this.clipImageWidth - this.clip.offsetWidth) {
left = this.clipImageWidth - this.clip.offsetWidth;
}
if (top > this.clipImageHeight - this.clip.offsetHeight) {
top = this.clipImageHeight - this.clip.offsetHeight;
}
// 设置裁剪框的位置
this.setClipPosition(left, top);
};
// 鼠标松开
window.onmouseup = () => {
window.onmouseup = null;
window.onmousemove = null;
};
};
}
//裁剪框缩放
clipBoxZoom() {
// 获取裁剪框的四个角
let zoomDom = {
lt: this.eleRef.nativeElement.querySelector('.lt'),
rt: this.eleRef.nativeElement.querySelector('.rt'),
rb: this.eleRef.nativeElement.querySelector('.rb'),
lb: this.eleRef.nativeElement.querySelector('.lb'),
};
// 鼠标按下时的位置
let zoomInfo = {
x: 0,
y: 0,
minWidth: this.ncClipMinWidth,
minHeight: this.ncClipMinHeight
};
// 鼠标按下时裁剪框的位置
for (let key in zoomDom) {
zoomDom[key].onmousedown = (e) => {
// 禁止冒泡
e.stopPropagation();
// 鼠标按下时的位置
zoomInfo.x = e.clientX;
zoomInfo.y = e.clientY;
// 鼠标移动
window.onmousemove = (e) => {
// 鼠标移动的距离
let moveX = e.clientX - zoomInfo.x;
let moveY = e.clientY - zoomInfo.y;
// 裁剪框的位置
let left = 0;
let top = 0;
// 裁剪框的尺寸
let width = 0;
let height = 0;
// 左上角
if (key === 'lt') {
// 裁剪框的位置
left = this.clip.offsetLeft + moveX;
top = this.clip.offsetTop + moveY;
// 裁剪框的尺寸
width = this.clip.offsetWidth - moveX;
height = this.clip.offsetHeight - moveY;
// 裁剪框的位置限制
if (left < 0) {
left = 0;
// 原来宽度+原来left
width = this.clip.offsetWidth + this.clip.offsetLeft;
}
if (top < 0) {
top = 0;
// 原来高度+原来top
height = this.clip.offsetHeight + this.clip.offsetTop;
}
}
// 右上角
if (key === 'rt') {
// 裁剪框的位置
top = this.clip.offsetTop + moveY;
left = this.clip.offsetLeft;
// 裁剪框的尺寸
width = this.clip.offsetWidth + moveX;
height = this.clip.offsetHeight - moveY;
// 裁剪框的位置限制
if (top < 0) {
top = 0;
// 原来高度+原来top
height = this.clip.offsetHeight + this.clip.offsetTop;
}
if (left + width > this.clipImageWidth) {
// 图片当前宽-原来left
width = this.clipImageWidth - left;
}
}
// 右下角
if (key === 'rb') {
// 裁剪框的尺寸
top = this.clip.offsetTop;
left = this.clip.offsetLeft;
width = this.clip.offsetWidth + moveX;
height = this.clip.offsetHeight + moveY;
// 裁剪框的位置限制
// 当前的left+当前的width>图片当前宽
if (this.clip.offsetLeft + width > this.clipImageWidth) {
width = this.clipImageWidth - left;
}
// 当前的top+当前的height>图片当前宽
if (this.clip.offsetTop + height > this.clipImageHeight) {
height = this.clipImageHeight - top;
}
}
// 左下角
if (key === 'lb') {
// 裁剪框的位置
left = this.clip.offsetLeft + moveX;
top = this.clip.offsetTop;
// 裁剪框的尺寸
width = this.clip.offsetWidth - moveX;
height = this.clip.offsetHeight + moveY;
// 裁剪框的位置限制
if (left < 0) {
left = 0;
width = this.clip.offsetWidth + this.clip.offsetLeft;
}
// 当前的top+当前的height>图片当前宽
if (this.clip.offsetTop + height > this.clipImageHeight) {
height = this.clipImageHeight - top;
}
}
// 裁剪框的限制
({ width, height, left, top } = this.ClipWidthPosition(zoomInfo, width, height, left, top));
// 设置裁剪框的位置
this.setClipPosition(left, top);
// 设置裁剪框的尺寸
this.setClipSize(width, height);
// 记录上一次的位置
zoomInfo.x = e.clientX;
zoomInfo.y = e.clientY;
};
// 鼠标松开
window.onmouseup = () => {
window.onmouseup = null;
window.onmousemove = null;
};
};
}
}
// 裁剪框的宽高限制以及位置限制
ClipWidthPosition(zoomInfo, w, h, l, t) {
let width = w; //裁剪框宽度
let height = h; //裁剪框的高度
let left = l; //裁剪框的left
let top = t; //裁剪框的top
if (w < zoomInfo.minWidth) {
width = zoomInfo.minWidth;
left = this.clip.offsetLeft;
}
if (h < zoomInfo.minHeight) {
height = zoomInfo.minHeight;
top = this.clip.offsetTop;
}
return { width, height, left, top };
}
//尺寸输入框变化
sizeInputChange() {
this.setClipSize(this.clipWidth, this.clipHeight);
this.setClipPosition(this.clipX, this.clipY);
}
}
ImgClipComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: ImgClipComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
ImgClipComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: ImgClipComponent, selector: "nc-img-clip", inputs: { ncUrl: "ncUrl", ncImgType: "ncImgType", ncWidth: "ncWidth", ncClipSize: "ncClipSize", ncClipMinWidth: "ncClipMinWidth", ncClipMinHeight: "ncClipMinHeight", ncDownload: "ncDownload", ncTool: "ncTool", ncUpload: "ncUpload" }, outputs: { ncConfirm: "ncConfirm" }, ngImport: i0, template: "<div class=\"clipContainer\" [ngStyle]=\"{'width': ncWidth + 'px'}\">\r\n <div class=\"clipBtnContainer\">\r\n <div *ngIf=\"uploadMode\" class=\"filebutton\">\r\n <div>\u4E0A\u4F20\u56FE\u7247</div>\r\n <input type=\"file\" id=\"file\" class=\"fileInput\" accept=\"image/*\">\r\n </div>\r\n <div *ngIf=\"hasImage\" class=\"confirmBtn\" (click)=\"confirm()\">\u786E\u5B9A</div>\r\n </div>\r\n <div class=\"clipImageCantainer\">\r\n <img id=\"clipImage\" src=\"\" crossorigin=\"anonymous\">\r\n <img id=\"clipPathImg\" src=\"\">\r\n <div id=\"clip\">\r\n <div class=\"corner lt\"></div>\r\n <div class=\"corner rt\"></div>\r\n <div class=\"corner rb\"></div>\r\n <div class=\"corner lb\"></div>\r\n </div>\r\n </div>\r\n <div class=\"bottomInputContainer\" *ngIf=\"hasImage && toolMode\">\r\n <div class=\"inputRow\">\r\n <div class=\"inputCol\">\r\n <div class=\"rowLabel\">\u5BBD\uFF1A</div>\r\n <input class=\"nc-input-number sizeInput\" type=\"number\" [(ngModel)]=\"clipWidth\" [min]=\"ncClipMinWidth\"\r\n [max]=\"clipImageWidth\" step=\"1\" (ngModelChange)=\"sizeInputChange()\">\r\n </div>\r\n <div class=\"inputCol\">\r\n <div class=\"rowLabel\">\u9AD8\uFF1A</div>\r\n <input class=\"nc-input-number sizeInput\" type=\"number\" [(ngModel)]=\"clipHeight\" [min]=\"ncClipMinHeight\"\r\n [max]=\"clipImageHeight\" step=\"1\" (ngModelChange)=\"sizeInputChange()\">\r\n </div>\r\n </div>\r\n <div class=\"inputRow\">\r\n <div class=\"inputCol\">\r\n <div class=\"rowLabel\">X\uFF1A</div>\r\n <input class=\"nc-input-number sizeInput\" type=\"number\" [(ngModel)]=\"clipX\" [min]=\"0\"\r\n [max]=\"clipImageWidth - clipWidth\" step=\"1\" (ngModelChange)=\"sizeInputChange()\">\r\n </div>\r\n <div class=\"inputCol\">\r\n <div class=\"rowLabel\">Y\uFF1A</div>\r\n <input class=\"nc-input-number sizeInput\" type=\"number\" [(ngModel)]=\"clipY\" [min]=\"0\"\r\n [max]=\"clipImageHeight - clipHeight\" step=\"1\" (ngModelChange)=\"sizeInputChange()\">\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".clipContainer{margin:5px}.clipContainer .clipBtnContainer{display:flex;align-items:center;justify-content:space-between;margin-bottom:5px}.clipContainer .clipBtnContainer .filebutton{position:relative;display:inline-block;overflow:hidden}.clipContainer .clipBtnContainer .filebutton input{position:absolute;top:0;opacity:0;font-size:0;width:100%;height:100%;cursor:pointer}.clipContainer .clipBtnContainer .filebutton div{font-size:13px;background:#00aeff;color:#fff;padding:4px 8px;border-radius:3px}.clipContainer .clipBtnContainer .confirmBtn{font-size:13px;background:#00aeff;color:#fff;padding:4px 8px;border-radius:3px;cursor:pointer}.clipContainer .clipImageCantainer{width:100%;position:relative}.clipContainer .clipImageCantainer:after{content:\"\";position:absolute;width:100%;height:100%;top:0;left:0;background:rgba(0,0,0,.5);z-index:1}.clipContainer .clipImageCantainer img{width:100%;top:0;left:0;display:block}.clipContainer .clipImageCantainer #clipPathImg{position:absolute;top:0;left:0;width:100%;height:100%;z-index:2;clip-path:var(--clipPath)}.clipContainer .clipImageCantainer #clip{position:absolute;top:0;left:0;width:var(--clipWidth);height:var(--clipHeight);left:var(--clipX);top:var(--clipY);z-index:3;cursor:move;border:1px dashed white;display:none}.clipContainer .clipImageCantainer #clip .corner{position:absolute;width:10px;height:10px;background:#fff;border:1px solid #000}.clipContainer .clipImageCantainer #clip .lt{cursor:nw-resize;left:-5px;top:-5px}.clipContainer .clipImageCantainer #clip .rt{cursor:ne-resize;right:-5px;top:-5px}.clipContainer .clipImageCantainer #clip .lb{cursor:sw-resize;left:-5px;bottom:-5px}.clipContainer .clipImageCantainer #clip .rb{cursor:se-resize;right:-5px;bottom:-5px}.clipContainer .bottomInputContainer .inputRow{display:flex;align-items:center;margin-top:5px}.clipContainer .bottomInputContainer .inputRow .inputCol{display:flex;align-items:center;margin-right:10px}.clipContainer .bottomInputContainer .inputRow .inputCol .rowLabel{width:30px;display:flex;justify-content:flex-end;color:#b9b9b9;mix-blend-mode:difference}.clipContainer .bottomInputContainer .inputRow .inputCol .sizeInput{width:70px}\n"], directives: [{ type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { type: i2.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: ImgClipComponent, decorators: [{
type: Component,
args: [{
selector: 'nc-img-clip',
templateUrl: './img-clip.component.html',
styleUrls: ['./img-clip.component.less']
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { ncUrl: [{
type: Input
}], ncConfirm: [{
type: Output
}], ncImgType: [{
type: Input
}], ncWidth: [{
type: Input
}], ncClipSize: [{
type: Input
}], ncClipMinWidth: [{
type: Input
}], ncClipMinHeight: [{
type: Input
}], ncDownload: [{
type: Input
}], ncTool: [{
type: Input
}], ncUpload: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1nLWNsaXAuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvY29tcG9uZW50cy9pbWctY2xpcC9pbWctY2xpcC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2ltZy1jbGlwL2ltZy1jbGlwLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFjLFlBQVksRUFBRSxLQUFLLEVBQVUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDOzs7O0FBTzNGLE1BQU0sT0FBTyxnQkFBZ0I7SUErQ3pCLFlBQW9CLE1BQWtCO1FBQWxCLFdBQU0sR0FBTixNQUFNLENBQVk7UUF4QzVCLGNBQVMsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDLENBQUEsUUFBUTtRQUN4QyxjQUFTLEdBQXNCLFFBQVEsQ0FBQyxDQUFBLFlBQVk7UUFDcEQsWUFBTyxHQUFXLEdBQUcsQ0FBQyxDQUFBLE1BQU07UUFDNUIsZUFBVSxHQUFXLEdBQUcsQ0FBQyxDQUFBLGVBQWU7UUFDeEMsbUJBQWMsR0FBVyxFQUFFLENBQUMsQ0FBQSxTQUFTO1FBQ3JDLG9CQUFlLEdBQVcsRUFBRSxDQUFDLENBQUEsU0FBUztRQWMvQyxpQkFBWSxHQUFZLEtBQUssQ0FBQztRQUM5QixhQUFRLEdBQVksS0FBSyxDQUFDO1FBQzFCLGVBQVUsR0FBWSxLQUFLLENBQUM7UUFFNUIsYUFBUSxHQUFZLEtBQUssQ0FBQztRQUsxQixTQUFTO1FBQ1QsbUJBQWMsR0FBVyxDQUFDLENBQUM7UUFDM0Isb0JBQWUsR0FBVyxDQUFDLENBQUM7UUFDNUIsU0FBUztRQUNULHlCQUFvQixHQUFXLENBQUMsQ0FBQztRQUNqQywwQkFBcUIsR0FBVyxDQUFDLENBQUM7UUFDbEMsVUFBSyxHQUFXLENBQUMsQ0FBQyxDQUFBLE1BQU07UUFDeEIsY0FBUyxHQUFXLENBQUMsQ0FBQyxDQUFB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LEtBQUssRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBQ3hDLENBQUM7SUFFRCxTQUFTO0lBQ1QsZUFBZTtRQUNYLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNqRCxDQUFDOzs2R0ExWFEsZ0JBQWdCO2lHQUFoQixnQkFBZ0Isa1VDUDdCLHc0RUE0Q007MkZEckNPLGdCQUFnQjtrQkFMNUIsU0FBUzttQkFBQztvQkFDUCxRQUFRLEVBQUUsYUFBYTtvQkFDdkIsV0FBVyxFQUFFLDJCQUEyQjtvQkFDeEMsU0FBUyxFQUFFLENBQUMsMkJBQTJCLENBQUM7aUJBQzNDO2lHQUVnQixLQUFLO3NCQUFqQixLQUFLO2dCQU1JLFNBQVM7c0JBQWxCLE1BQU07Z0JBQ0UsU0FBUztzQkFBakIsS0FBSztnQkFDRyxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxjQUFjO3NCQUF0QixLQUFLO2dCQUNHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBRU8sVUFBVTtzQkFBdEIsS0FBSztnQkFJTyxNQUFNO3NCQUFsQixLQUFLO2dCQUlPLFFBQVE7c0JBQXBCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uSW5pdCwgT3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICAgIHNlbGVjdG9yOiAnbmMtaW1nLWNsaXAnLFxyXG4gICAgdGVtcGxhdGVVcmw6ICcuL2ltZy1jbGlwLmNvbXBvbmVudC5odG1sJyxcclxuICAgIHN0eWxlVXJsczogWycuL2ltZy1jbGlwLmNvbXBvbmVudC5sZXNzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIEltZ0NsaXBDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xyXG4gICAgQElucHV0KCkgc2V0IG5jVXJsKHZhbHVlOiBzdHJpbmcpIHtcclxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgLy/liqDlu7bov5/vvIzpmLLmraLlhbbku5bkvKDlhaXlj4LmlbDmnKrojrflj5bliLBcclxuICAgICAgICAgICAgdGhpcy5yZWFkSW1hZ2UodmFsdWUpO1xyXG4gICAgICAgIH0pXHJcbiAgICB9O1xyXG4gICAgQE91dHB1dCgpIG5jQ29uZmlybSA9IG5ldyBFdmVudEVtaXR0ZXIoKTsvL+ehruiupOijgeWJquWbnuiwg1xyXG4gICAgQElucHV0KCkgbmNJbWdUeXBlOiAnYmFzZTY0JyB8ICdmaWxlJyA9ICdiYXNlNjQnOy8v6KOB5Ymq5Zue6LCD6L+U5Zue5Zu+54mH5qC85byPXHJcbiAgICBASW5wdXQoKSBuY1dpZHRoOiBudW1iZXIgPSAzMDA7Ly/lrrnlmajlrr3luqZcclxuICAgIEBJbnB1dCgpIG5jQ2xpcFNpemU6IG51bWJlciA9IDAuNzsvL+m7mOiupOijgeWJquahhueahOWwuuWvuOWNoOWbvueJh+avlOS+i1xyXG4gICAgQElucHV0KCkgbmNDbGlwTWluV2lkdGg6IG51bWJlciA9IDUwOy8v6KOB5Ymq5qGG5pyA5bCP5a695bqmXHJcbiAgICBASW5wdXQoKSBuY0NsaXBNaW5IZWlnaHQ6IG51bWJlciA9IDUwOy8v6KOB5Ymq5qGG5pyA5bCP6auY5bqmXHJcbiAgICAvL+ehruiupOijgeWJquaXtuaYr+WQpuS4i+i9veWbvueJh1xyXG4gICAgQElucHV0KCkgc2V0IG5jRG93bmxvYWQodmFsdWU6IGJvb2xlYW4gfCBzdHJpbmcpIHtcclxuICAgICAgICB0aGlzLmRvd25sb2FkTW9kZSA9IHZhbHVlICE9PSBudWxsICYmIHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IGZhbHNlICYmIHZhbHVlICE9PSAnZmFsc2UnO1xyXG4gICAgfVxyXG4gICAgLy/osIPmlbTlt6XlhbfmoI9cclxuICAgIEBJbnB1dCgpIHNldCBuY1Rvb2wodmFsdWU6IGJvb2xlYW4gfCBzdHJpbmcpIHtcclxuICAgICAgICB0aGlzLnRvb2xNb2RlID0gdmFsdWUgIT09IG51bGwgJiYgdmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gZmFsc2UgJiYgdmFsdWUgIT09ICdmYWxzZSc7XHJcbiAgICB9XHJcbiAgICAvL+S4iuS8oFxyXG4gICAgQElucHV0KCkgc2V0IG5jVXBsb2FkKHZhbHVlOiBib29sZWFuIHwgc3RyaW5nKSB7XHJcbiAgICAgICAgdGhpcy51cGxvYWRNb2RlID0gdmFsdWUgIT09IG51bGwgJiYgdmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gZmFsc2UgJiYgdmFsdWUgIT09ICdmYWxzZSc7XHJcbiAgICB9XHJcblxyXG4gICAgZG93bmxvYWRNb2RlOiBib29sZWFuID0gZmFsc2U7XHJcbiAgICB0b29sTW9kZTogYm9vbGVhbiA9IGZhbHNlO1xyXG4gICAgdXBsb2FkTW9kZTogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAgIGhhc0ltYWdlOiBib29sZWFuID0gZmFsc2U7XHJcbiAgICBmaWxlOiBhbnk7Ly9maWxl6YCJ5oup5qGGXHJcbiAgICBjbGlwSW1hZ2U6IGFueTsvL+ijgeWJquiDjOaZr+WbvueJh1xyXG4gICAgY2xpcFBhdGhJbWc6IGFueTsvL+ijgeWJquS9v+eUqOeahOWbvueJh1xyXG4gICAgY2xpcDogYW55Oy8v6KOB5Ymq5qGGXHJcbiAgICAvLyDlm77niYflvZPliY3lrr3pq5hcclxuICAgIGNsaXBJbWFnZVdpZHRoOiBudW1iZXIgPSAwO1xyXG4gICAgY2xpcEltYWdlSGVpZ2h0OiBudW1iZXIgPSAwO1xyXG4gICAgLy8g5Zu+54mH5Y6f5aeL5a696auYXHJcbiAgICBjbGlwSW1hZ2VPcmlnaW5XaWR0aDogbnVtYmVyID0gMDtcclxuICAgIGNsaXBJbWFnZU9yaWdpbkhlaWdodDogbnVtYmVyID0gMDtcclxuICAgIHNjYWxlOiBudW1iZXIgPSAwOy8v57yp5pS+5q+U5L6LXHJcbiAgICBjbGlwV2lkdGg6IG51bWJlciA9IDA7Ly/oo4HliarmoYblrr3luqZcclxuICAgIGNsaXBIZWlnaHQ6IG51bWJlciA9IDA7Ly/oo4HliarmoYbpq5jluqZcclxuICAgIGNsaXBYOiBudW1iZXIgPSAwOy8v6KOB5Ymq5qGGeFxyXG4gICAgY2xpcFk6IG51bWJlciA9IDA7Ly/oo4HliarmoYZ5XHJcblxyXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBlbGVSZWY6IEVsZW1lbnRSZWYpIHsgfVxyXG5cclxuICAgIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuY2xpcEltYWdlID0gdGhpcy5lbGVSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCcjY2xpcEltYWdlJyk7XHJcbiAgICAgICAgdGhpcy5jbGlwUGF0aEltZyA9IHRoaXMuZWxlUmVmLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcignI2NsaXBQYXRoSW1nJyk7XHJcbiAgICAgICAgdGhpcy5jbGlwID0gdGhpcy5lbGVSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCcjY2xpcCcpO1xyXG4gICAgICAgIGlmICh0aGlzLnVwbG9hZE1vZGUpIHtcclxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmZpbGUgPSB0aGlzLmVsZVJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJyNmaWxlJyk7XHJcbiAgICAgICAgICAgICAgICAvLyDnm5HlkKzkuIrkvKDnirbmgIEg5rWP6KeI5Zu+54mHXHJcbiAgICAgICAgICAgICAgICB0aGlzLmZpbGUuYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgKGU6IGFueSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbGUgPSBlLnRhcmdldC5maWxlc1swXTtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xyXG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5vbmxvYWQgPSAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVhZEltYWdlKHJlYWRlci5yZXN1bHQpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8v6KOB5Ymq5qGG57yp5pS+44CB5ouW5ou9XHJcbiAgICAgICAgdGhpcy5jbGlwQm94Wm9vbSgpO1xyXG4gICAgICAgIHRoaXMuY2xpcEJweERyYWcoKTtcclxuICAgIH1cclxuXHJcbiAgICAvL+ivu+WPluWbvueJh1xyXG4gICAgcmVhZEltYWdlKHVybDogYW55KSB7XHJcbiAgICAgICAgLy8g6K+75Y+W5Yiw55qE5Zu+54mH5pWw5o2uXHJcbiAgICAgICAgdGhpcy5jbGlwSW1hZ2Uuc3JjID0gdXJsO1xyXG4gICAgICAgIC8vIOijgeWJquS9v+eUqOeahOWbvueJh1xyXG4gICAgICAgIHRoaXMuY2xpcFBhdGhJbWcuc3JjID0gdXJsO1xyXG4gICAgICAgIC8v6I635Y+W5b2T5YmN5Zu+54mH55qE5a696auYXHJcbiAgICAgICAgdGhpcy5nZXRDbGlwSW1hZ2VTaXplKHVybCkudGhlbigocmVzOiBhbnkpID0+IHtcclxuICAgICAgICAgICAgLy8g5Yid5aeL5YyWXHJcbiAgICAgICAgICAgIHRoaXMuaW5pdCgpO1xyXG4gICAgICAgICAgICB0aGlzLmhhc0ltYWdlID0gdHJ1ZTtcclxuICAgICAgICB9KVxyXG4gICAgfVxyXG5cclxuICAgIC8vIOiOt+WPluS4iuS8oOWbvueJh+eahOW9k+WJjeWwuuWvuOWSjOWOn+Wni+WwuuWvuFxyXG4gICAgYXN5bmMgZ2V0Q2xpcEltYWdlU2l6ZShkYXRhdXJsOiBhbnkpIHtcclxuICAgICAgICBjb25zdCBkYXRhOiBhbnkgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLmNsaXBJbWFnZS5vbmxvYWQgPSAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuY2xpcEltYWdlKTtcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9KTtcclxuICAgICAgICAvLyDojrflj5blm77niYflvZPliY3lrr3pq5hcclxuICAgICAgICB0aGlzLmNsaXBJbWFnZVdpZHRoID0gZGF0YS53aWR0aDtcclxuICAgICAgICB0aGlzLmNsaXBJbWFnZUhlaWdodCA9IGRhdGEuaGVpZ2h0O1xyXG4gICAgICAgIGNvbnN0IGRhdGFfMTogYW55ID0gYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmVfMSkgPT4ge1xyXG4gICAgICAgICAgICAvLyDojrflj5blm77niYfljp/lp4vlrr3pq5hcclxuICAgICAgICAgICAgbGV0IGltZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xyXG4gICAgICAgICAgICBpbWcuc3JjID0gZGF0YXVybDtcclxuICAgICAgICAgICAgaW1nLm9ubG9hZCA9ICgpID0+IHtcclxuICAgICAgICAgICAgICAgIHJlc29sdmVfMShpbWcpO1xyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIC8vIOiOt+WPluWbvueJh+WOn+Wni+WuvemrmFxyXG4gICAgICAgIHRoaXMuY2xpcEltYWdlT3JpZ2luV2lkdGggPSBkYXRhXzEud2lkdGg7XHJcbiAgICAgICAgdGhpcy5jbGlwSW1hZ2VPcmlnaW5IZWlnaHQgPSBkYXRhXzEuaGVpZ2h0O1xyXG4gICAgICAgIHJldHVybiBhd2FpdCBQcm9taXNlLnJlc29sdmUoKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyDliJ3lp4vljJZcclxuICAgIGluaXQoKSB7XHJcbiAgICAgICAgLy8g5pi+56S66KOB5Ymq5qGGXHJcbiAgICAgICAgdGhpcy5jbGlwLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xyXG4gICAgICAgIC8vIOe8qeaUvuavlOS+i1xyXG4gICAgICAgIHRoaXMuc2NhbGUgPSB0aGlzLmNsaXBJbWFnZU9yaWdpbldpZHRoIC8gdGhpcy5jbGlwSW1hZ2VXaWR0aDtcclxuICAgICAgICAvLyDorr7nva7oo4HliarmoYbnmoTlrr3pq5hcclxuICAgICAgICBsZXQgY2xpcFdpZHRoID0gTWF0aC5mbG9vcih0aGlzLmNsaXBJbWFnZVdpZHRoICogdGhpcy5uY0NsaXBTaXplKTtcclxuICAgICAgICBsZXQgY2xpcEhlaWdodCA9IE1hdGguZmxvb3IodGhpcy5jbGlwSW1hZ2VIZWlnaHQgKiB0aGlzLm5jQ2xpcFNpemUpO1xyXG4gICAgICAgIHRoaXMuc2V0Q2xpcFNpemUoY2xpcFdpZHRoLCBjbGlwSGVpZ2h0KTtcclxuXHJcbiAgICAgICAgLy8g6K6+572u6KOB5Ymq5qGG55qE5L2N572uXHJcbiAgICAgICAgbGV0IHggPSBNYXRoLmZsb29yKCh0aGlzLmNsaXBJbWFnZVdpZHRoIC0gY2xpcFdpZHRoKSAvIDIpO1xyXG4gICAgICAgIGxldCB5ID0gTWF0aC5mbG9vcigodGhpcy5jbGlwSW1hZ2VIZWlnaHQgLSBjbGlwSGVpZ2h0KSAvIDIpO1xyXG4gICAgICAgIHRoaXMuc2V0Q2xpcFBvc2l0aW9uKHgsIHkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIOiuvue9ruijgeWJquahhueahOWwuuWvuFxyXG4gICAgc2V0Q2xpcFNpemUoY2xpcFdpZHRoOiBudW1iZXIsIGNsaXBIZWlnaHQ6IG51bWJlcikge1xyXG4gICAgICAgIHRoaXMuY2xpcC5zdHlsZS5zZXRQcm9wZXJ0eSgnLS1jbGlwV2lkdGgnLCBjbGlwV2lkdGggKyAncHgnKTtcclxuICAgICAgICB0aGlzLmNsaXAuc3R5bGUuc2V0UHJvcGVydHkoJy0tY2xpcEhlaWdodCcsIGNsaXBIZWlnaHQgKyAncHgnKTtcclxuICAgICAgICB0aGlzLmNsaXBXaWR0aCA9IGNsaXBXaWR0aDtcclxuICAgICAgICB0aGlzLmNsaXBIZWlnaHQgPSBjbGlwSGVpZ2h0O1xyXG4gICAgfVxyXG5cclxuICAgIC8vIOiuvue9ruijgeWJquahhueahOS9jee9rlxyXG4gICAgc2V0Q2xpcFBvc2l0aW9uKHg6IG51bWJlciwgeTogbnVtYmVyKSB7XHJcbiAgICAgICAgdGhpcy5jbGlwLnN0eWxlLnNldFByb3BlcnR5KCctLWNsaXBYJywgeCArICdweCcpO1xyXG4gICAgICAgIHRoaXMuY2xpcC5zdHlsZS5zZXRQcm9wZXJ0eSgnLS1jbGlwWScsIHkgKyAncHgnKTtcclxuICAgICAgICB0aGlzLmNsaXBYID0geDtcclxuICAgICAgICB0aGlzLmNsaXBZID0geTtcclxuICAgICAgICAvLyDorr7nva7oo4HliarpmLTlvbFcclxuICAgICAgICB0aGlzLnNldENsaXBQYXRoKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8g6K6+572u6KOB5Ymq6Zi05b2xXHJcbiAgICBzZXRDbGlwUGF0aCgpIHtcclxuICAgICAgICBsZXQgbHQgPSB0aGlzLmNsaXAub2Zmc2V0TGVmdCArICdweCcgKyAnICcgKyB0aGlzLmNsaXAub2Zmc2V0VG9wICsgJ3B4JztcclxuICAgICAgICBsZXQgcnQgPSAodGhpcy5jbGlwLm9mZnNldExlZnQgKyB0aGlzLmNsaXAub2Zmc2V0V2lkdGgpICsgJ3B4JyArICcgJyArIHRoaXMuY2xpcC5vZmZzZXRUb3AgKyAncHgnO1xyXG4gICAgICAgIGxldCByYiA9ICh0aGlzLmNsaXAub2Zmc2V0TGVmdCArIHRoaXMuY2xpcC5vZmZzZXRXaWR0aCkgKyAncHgnICsgJyAnICsgKHRoaXMuY2xpcC5vZmZzZXRUb3AgKyB0aGlzLmNsaXAub2Zmc2V0SGVpZ2h0KSArICdweCc7XHJcbiAgICAgICAgbGV0IGxiID0gdGhpcy5jbGlwLm9mZnNldExlZnQgKyAncHgnICsgJyAnICsgKHRoaXMuY2xpcC5vZmZzZXRUb3AgKyB0aGlzLmNsaXAub2Zmc2V0SGVpZ2h0KSArICdweCc7XHJcbiAgICAgICAgdGhpcy5jbGlwUGF0aEltZy5zdHlsZS5zZXRQcm9wZXJ0eSgnLS1jbGlwUGF0aCcsIGBwb2x5Z29uKCR7bHR9LCAke3J0fSwgJHtyYn0sICR7bGJ9KWApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIOijgeWJqlxyXG4gICAgYXN5bmMgY2xpcEltZyh4OiBudW1iZXIsIHk6IG51bWJlciwgY3V0V2lkdGg6IG51bWJlciwgY3V0SGVpZ2h0OiBudW1iZXIsIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XHJcbiAgICAgICAgbGV0IGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcclxuICAgICAgICBjYW52YXMud2lkdGggPSB3aWR0aDtcclxuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xyXG4gICAgICAgIGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpIS5kcmF3SW1hZ2UodGhpcy5jbGlwSW1hZ2UsIHgsIHksIGN1dFdpZHRoLCBjdXRIZWlnaHQsIDAsIDAsIHdpZHRoLCBoZWlnaHQpO1xyXG5cclxuICAgICAgICAvL+S4i+i9vVxyXG4gICAgICAgIGlmICh0aGlzLmRvd25sb2FkTW9kZSkge1xyXG4gICAgICAgICAgICBjb25zdCBhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xyXG4gICAgICAgICAgICBhLmRvd25sb2FkID0gJ+ijgeWJquWbvueJhyc7XHJcbiAgICAgICAgICAgIGEuaHJlZiA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpO1xyXG4gICAgICAgICAgICBhLmNsaWNrKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyDov5Tlm57oo4HliarlkI7nmoTlm77niYdcclxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcclxuICAgICAgICAgICAgaWYgKHRoaXMubmNJbWdUeXBlID09ICdiYXNlNjQnKSB7XHJcbiAgICAgICAgICAgICAgICByZXNvbHZlKGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGNhbnZhcy50b0Jsb2IoKGJsb2I6IGFueSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUobmV3IEZpbGUoW2Jsb2JdLCAnY2xpcC5wbmcnLCB7IHR5cGU6ICdpbWFnZS9wbmcnIH0pKTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9