UNPKG

ngx-editor

Version:

Rich Text Editor for angular using ProseMirror

135 lines 23 kB
import { Component, HostBinding, HostListener } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import Icon from '../../../icons'; import { Link as LinkCommand } from '../MenuCommands'; import * as i0 from "@angular/core"; import * as i1 from "../../../editor.service"; import * as i2 from "../menu.service"; import * as i3 from "@angular/common"; import * as i4 from "@angular/forms"; import * as i5 from "../../../pipes/sanitize/sanitize-html.pipe"; export class LinkComponent { constructor(el, ngxeService, menuService) { this.el = el; this.ngxeService = ngxeService; this.menuService = menuService; this.showPopup = false; this.isActive = false; this.canExecute = true; this.form = new FormGroup({ href: new FormControl('', [ Validators.required, Validators.pattern('(https?://)?([\\da-z.-]+)\\.([a-z.]{2,6})[/\\w .-]*/??([^#\n\r]*)?#?([^\n\r]*)') ]), text: new FormControl('', [Validators.required]), openInNewTab: new FormControl(true) }); this.setText = () => { const { state: { selection, doc } } = this.editorView; const { empty, from, to } = selection; const selectedText = !empty ? doc.textBetween(from, to) : ''; if (selectedText) { this.text.patchValue(selectedText); this.text.disable(); } }; this.update = (view) => { const { state } = view; this.isActive = LinkCommand.isActive(state, { strict: false }); this.canExecute = LinkCommand.canExecute(state); }; } get valid() { return this.isActive || this.showPopup; } get disabled() { return !this.canExecute; } get icon() { return Icon.get(this.isActive ? 'unlink' : 'link'); } get title() { return this.ngxeService.locals.get(this.isActive ? 'removeLink' : 'insertLink'); } get href() { return this.form.get('href'); } get text() { return this.form.get('text'); } onDocumentClick(e) { if (!this.el.nativeElement.contains(e.target) && this.showPopup) { this.hideForm(); } } getLabel(key) { return this.ngxeService.locals.get(key); } hideForm() { this.showPopup = false; this.form.reset({ href: '', text: '', openInNewTab: true }); this.text.enable(); } onMouseDown(e) { if (e.button !== 0) { return; } const { state, dispatch } = this.editorView; if (this.isActive) { LinkCommand.remove(state, dispatch); return; } this.showPopup = !this.showPopup; if (this.showPopup) { this.setText(); } } insertLink(e) { e.preventDefault(); const { text, href, openInNewTab } = this.form.getRawValue(); const { dispatch, state } = this.editorView; const { selection } = state; const attrs = { title: href, href, target: openInNewTab ? '_blank' : '_self' }; if (selection.empty) { LinkCommand.insert(text, attrs)(state, dispatch); this.editorView.focus(); } else { LinkCommand.update(attrs)(state, dispatch); } this.hideForm(); } ngOnInit() { this.editorView = this.menuService.editor.view; this.updateSubscription = this.menuService.editor.update.subscribe((view) => { this.update(view); }); } ngOnDestroy() { this.updateSubscription.unsubscribe(); } } LinkComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.0", ngImport: i0, type: LinkComponent, deps: [{ token: i0.ElementRef }, { token: i1.NgxEditorService }, { token: i2.MenuService }], target: i0.ɵɵFactoryTarget.Component }); LinkComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.0", type: LinkComponent, selector: "ngx-link", host: { listeners: { "document:mousedown": "onDocumentClick($event)" }, properties: { "class.NgxEditor__MenuItem--Active": "this.valid", "class.NgxEditor--Disabled": "this.disabled" } }, ngImport: i0, template: "<div class=\"NgxEditor__MenuItem--IconContainer\" [innerHTML]=\"icon | sanitizeHtml\" (mousedown)=\"onMouseDown($event)\"\n [title]=\"title\">\n</div>\n\n<!-- popup -->\n<div *ngIf=\"showPopup\" class=\"NgxEditor__Popup\">\n <form class=\"NgxEditor__Popup--Form\" [formGroup]=\"form\" (ngSubmit)=\"insertLink($event)\">\n\n <div class=\"NgxEditor__Popup--FormGroup\">\n <div class=\"NgxEditor__Popup--Col\">\n <label class=\"NgxEditor__Popup--Label\">{{getLabel('url')}}</label>\n <input type=\"href\" id=\"href\" formControlName=\"href\" autofocus autocomplete=\"off\" />\n <div *ngIf=\"href.touched && href.invalid\" class=\"NgxEditor__HelpText NgxEditor__HelpText--Error\">\n {{ href.errors?.['pattern'] && 'Please enter valid url.' }}\n </div>\n </div>\n </div>\n\n <div class=\"NgxEditor__Popup--FormGroup\">\n <div class=\"NgxEditor__Popup--Col\">\n <label class=\"NgxEditor__Popup--Label\">{{getLabel('text')}}</label>\n <input type=\"text\" formControlName=\"text\" autocomplete=\"off\" />\n <div *ngIf=\"text.touched && text.invalid\" class=\"NgxEditor__HelpText NgxEditor__HelpText--Error\">\n {{ text.errors?.['required'] && 'This is required' }}\n </div>\n </div>\n </div>\n\n <div class=\"NgxEditor__Popup--FormGroup\">\n <div class=\"NgxEditor__Popup--Col\">\n <label>\n <input type=\"checkbox\" formControlName=\"openInNewTab\" />\n {{getLabel('openInNewTab')}}\n </label>\n </div>\n </div>\n\n <button type=\"submit\" [disabled]=\"!form.valid\">{{getLabel('insert')}}</button>\n\n </form>\n</div>\n", styles: [""], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i4.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }], pipes: { "sanitizeHtml": i5.SanitizeHtmlPipe } }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.0", ngImport: i0, type: LinkComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-link', template: "<div class=\"NgxEditor__MenuItem--IconContainer\" [innerHTML]=\"icon | sanitizeHtml\" (mousedown)=\"onMouseDown($event)\"\n [title]=\"title\">\n</div>\n\n<!-- popup -->\n<div *ngIf=\"showPopup\" class=\"NgxEditor__Popup\">\n <form class=\"NgxEditor__Popup--Form\" [formGroup]=\"form\" (ngSubmit)=\"insertLink($event)\">\n\n <div class=\"NgxEditor__Popup--FormGroup\">\n <div class=\"NgxEditor__Popup--Col\">\n <label class=\"NgxEditor__Popup--Label\">{{getLabel('url')}}</label>\n <input type=\"href\" id=\"href\" formControlName=\"href\" autofocus autocomplete=\"off\" />\n <div *ngIf=\"href.touched && href.invalid\" class=\"NgxEditor__HelpText NgxEditor__HelpText--Error\">\n {{ href.errors?.['pattern'] && 'Please enter valid url.' }}\n </div>\n </div>\n </div>\n\n <div class=\"NgxEditor__Popup--FormGroup\">\n <div class=\"NgxEditor__Popup--Col\">\n <label class=\"NgxEditor__Popup--Label\">{{getLabel('text')}}</label>\n <input type=\"text\" formControlName=\"text\" autocomplete=\"off\" />\n <div *ngIf=\"text.touched && text.invalid\" class=\"NgxEditor__HelpText NgxEditor__HelpText--Error\">\n {{ text.errors?.['required'] && 'This is required' }}\n </div>\n </div>\n </div>\n\n <div class=\"NgxEditor__Popup--FormGroup\">\n <div class=\"NgxEditor__Popup--Col\">\n <label>\n <input type=\"checkbox\" formControlName=\"openInNewTab\" />\n {{getLabel('openInNewTab')}}\n </label>\n </div>\n </div>\n\n <button type=\"submit\" [disabled]=\"!form.valid\">{{getLabel('insert')}}</button>\n\n </form>\n</div>\n", styles: [""] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.NgxEditorService }, { type: i2.MenuService }]; }, propDecorators: { valid: [{ type: HostBinding, args: ['class.NgxEditor__MenuItem--Active'] }], disabled: [{ type: HostBinding, args: ['class.NgxEditor--Disabled'] }], onDocumentClick: [{ type: HostListener, args: ['document:mousedown', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGluay5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZWRpdG9yL3NyYy9saWIvbW9kdWxlcy9tZW51L2xpbmsvbGluay5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZWRpdG9yL3NyYy9saWIvbW9kdWxlcy9tZW51L2xpbmsvbGluay5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUFjLFdBQVcsRUFDbEMsWUFBWSxFQUNiLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBbUIsV0FBVyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQU1yRixPQUFPLElBQUksTUFBTSxnQkFBZ0IsQ0FBQztBQUNsQyxPQUFPLEVBQUUsSUFBSSxJQUFJLFdBQVcsRUFBRSxNQUFNLGlCQUFpQixDQUFDOzs7Ozs7O0FBUXRELE1BQU0sT0FBTyxhQUFhO0lBZ0J4QixZQUNVLEVBQWMsRUFDZCxXQUE2QixFQUM3QixXQUF3QjtRQUZ4QixPQUFFLEdBQUYsRUFBRSxDQUFZO1FBQ2QsZ0JBQVcsR0FBWCxXQUFXLENBQWtCO1FBQzdCLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBbEJsQyxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ2xCLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFDVCxlQUFVLEdBQUcsSUFBSSxDQUFDO1FBSTFCLFNBQUksR0FBRyxJQUFJLFNBQVMsQ0FBQztZQUNuQixJQUFJLEVBQUUsSUFBSSxXQUFXLENBQUMsRUFBRSxFQUFFO2dCQUN4QixVQUFVLENBQUMsUUFBUTtnQkFDbkIsVUFBVSxDQUFDLE9BQU8sQ0FBQyxnRkFBZ0YsQ0FBQzthQUNyRyxDQUFDO1lBQ0YsSUFBSSxFQUFFLElBQUksV0FBVyxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FB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QyxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztTQUM1QztRQUNELElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNsQixDQUFDO0lBRUQsUUFBUTtRQUNOLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDO1FBRS9DLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBZ0IsRUFBRSxFQUFFO1lBQ3RGLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUN4QyxDQUFDOzswR0FwSVUsYUFBYTs4RkFBYixhQUFhLDJPQ25CMUIsNG9EQXlDQTsyRkR0QmEsYUFBYTtrQkFOekIsU0FBUzsrQkFDRSxVQUFVOzBKQTJCa0MsS0FBSztzQkFBMUQsV0FBVzt1QkFBQyxtQ0FBbUM7Z0JBSUYsUUFBUTtzQkFBckQsV0FBVzt1QkFBQywyQkFBMkI7Z0JBb0JRLGVBQWU7c0JBQTlELFlBQVk7dUJBQUMsb0JBQW9CLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEhvc3RCaW5kaW5nLFxuICBIb3N0TGlzdGVuZXIsIE9uRGVzdHJveSwgT25Jbml0XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBGb3JtQ29udHJvbCwgRm9ybUdyb3VwLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgRWRpdG9yVmlldyB9IGZyb20gJ3Byb3NlbWlycm9yLXZpZXcnO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IE5neEVkaXRvclNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9lZGl0b3Iuc2VydmljZSc7XG5pbXBvcnQgeyBNZW51U2VydmljZSB9IGZyb20gJy4uL21lbnUuc2VydmljZSc7XG5pbXBvcnQgSWNvbiBmcm9tICcuLi8uLi8uLi9pY29ucyc7XG5pbXBvcnQgeyBMaW5rIGFzIExpbmtDb21tYW5kIH0gZnJvbSAnLi4vTWVudUNvbW1hbmRzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWxpbmsnLFxuICB0ZW1wbGF0ZVVybDogJy4vbGluay5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2xpbmsuY29tcG9uZW50LnNjc3MnXVxufSlcblxuZXhwb3J0IGNsYXNzIExpbmtDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIHNob3dQb3B1cCA9IGZhbHNlO1xuICBpc0FjdGl2ZSA9IGZhbHNlO1xuICBwcml2YXRlIGNhbkV4ZWN1dGUgPSB0cnVlO1xuICBwcml2YXRlIGVkaXRvclZpZXc6IEVkaXRvclZpZXc7XG4gIHByaXZhdGUgdXBkYXRlU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cbiAgZm9ybSA9IG5ldyBGb3JtR3JvdXAoe1xuICAgIGhyZWY6IG5ldyBGb3JtQ29udHJvbCgnJywgW1xuICAgICAgVmFsaWRhdG9ycy5yZXF1aXJlZCxcbiAgICAgIFZhbGlkYXRvcnMucGF0dGVybignKGh0dHBzPzovLyk/KFtcXFxcZGEtei4tXSspXFxcXC4oW2Etei5dezIsNn0pWy9cXFxcdyAuLV0qLz8/KFteI1xcblxccl0qKT8jPyhbXlxcblxccl0qKScpXG4gICAgXSksXG4gICAgdGV4dDogbmV3IEZvcm1Db250cm9sKCcnLCBbVmFsaWRhdG9ycy5yZXF1aXJlZF0pLFxuICAgIG9wZW5Jbk5ld1RhYjogbmV3IEZvcm1Db250cm9sKHRydWUpXG4gIH0pO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZWw6IEVsZW1lbnRSZWYsXG4gICAgcHJpdmF0ZSBuZ3hlU2VydmljZTogTmd4RWRpdG9yU2VydmljZSxcbiAgICBwcml2YXRlIG1lbnVTZXJ2aWNlOiBNZW51U2VydmljZVxuICApIHsgfVxuXG4gIEBIb3N0QmluZGluZygnY2xhc3MuTmd4RWRpdG9yX19NZW51SXRlbS0tQWN0aXZlJykgZ2V0IHZhbGlkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlIHx8IHRoaXMuc2hvd1BvcHVwO1xuICB9XG5cbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5OZ3hFZGl0b3ItLURpc2FibGVkJykgZ2V0IGRpc2FibGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhdGhpcy5jYW5FeGVjdXRlO1xuICB9XG5cbiAgZ2V0IGljb24oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gSWNvbi5nZXQodGhpcy5pc0FjdGl2ZSA/ICd1bmxpbmsnIDogJ2xpbmsnKTtcbiAgfVxuXG4gIGdldCB0aXRsZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm5neGVTZXJ2aWNlLmxvY2Fscy5nZXQodGhpcy5pc0FjdGl2ZSA/ICdyZW1vdmVMaW5rJyA6ICdpbnNlcnRMaW5rJyk7XG4gIH1cblxuICBnZXQgaHJlZigpOiBBYnN0cmFjdENvbnRyb2wge1xuICAgIHJldHVybiB0aGlzLmZvcm0uZ2V0KCdocmVmJyk7XG4gIH1cblxuICBnZXQgdGV4dCgpOiBBYnN0cmFjdENvbnRyb2wge1xuICAgIHJldHVybiB0aGlzLmZvcm0uZ2V0KCd0ZXh0Jyk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDptb3VzZWRvd24nLCBbJyRldmVudCddKSBvbkRvY3VtZW50Q2xpY2soZTogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5lbC5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKGUudGFyZ2V0KSAmJiB0aGlzLnNob3dQb3B1cCkge1xuICAgICAgdGhpcy5oaWRlRm9ybSgpO1xuICAgIH1cbiAgfVxuXG4gIGdldExhYmVsKGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5uZ3hlU2VydmljZS5sb2NhbHMuZ2V0KGtleSk7XG4gIH1cblxuICBwcml2YXRlIGhpZGVGb3JtKCk6IHZvaWQge1xuICAgIHRoaXMuc2hvd1BvcHVwID0gZmFsc2U7XG4gICAgdGhpcy5mb3JtLnJlc2V0KHtcbiAgICAgIGhyZWY6ICcnLFxuICAgICAgdGV4dDogJycsXG4gICAgICBvcGVuSW5OZXdUYWI6IHRydWVcbiAgICB9KTtcbiAgICB0aGlzLnRleHQuZW5hYmxlKCk7XG4gIH1cblxuICBvbk1vdXNlRG93bihlOiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKGUuYnV0dG9uICE9PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgeyBzdGF0ZSwgZGlzcGF0Y2ggfSA9IHRoaXMuZWRpdG9yVmlldztcblxuICAgIGlmICh0aGlzLmlzQWN0aXZlKSB7XG4gICAgICBMaW5rQ29tbWFuZC5yZW1vdmUoc3RhdGUsIGRpc3BhdGNoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnNob3dQb3B1cCA9ICF0aGlzLnNob3dQb3B1cDtcbiAgICBpZiAodGhpcy5zaG93UG9wdXApIHtcbiAgICAgIHRoaXMuc2V0VGV4dCgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2V0VGV4dCA9ICgpID0+IHtcbiAgICBjb25zdCB7IHN0YXRlOiB7IHNlbGVjdGlvbiwgZG9jIH0gfSA9IHRoaXMuZWRpdG9yVmlldztcbiAgICBjb25zdCB7IGVtcHR5LCBmcm9tLCB0byB9ID0gc2VsZWN0aW9uO1xuICAgIGNvbnN0IHNlbGVjdGVkVGV4dCA9ICFlbXB0eSA/IGRvYy50ZXh0QmV0d2Vlbihmcm9tLCB0bykgOiAnJztcblxuICAgIGlmIChzZWxlY3RlZFRleHQpIHtcbiAgICAgIHRoaXMudGV4dC5wYXRjaFZhbHVlKHNlbGVjdGVkVGV4dCk7XG4gICAgICB0aGlzLnRleHQuZGlzYWJsZSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlID0gKHZpZXc6IEVkaXRvclZpZXcpID0+IHtcbiAgICBjb25zdCB7IHN0YXRlIH0gPSB2aWV3O1xuICAgIHRoaXMuaXNBY3RpdmUgPSBMaW5rQ29tbWFuZC5pc0FjdGl2ZShzdGF0ZSwgeyBzdHJpY3Q6IGZhbHNlIH0pO1xuICAgIHRoaXMuY2FuRXhlY3V0ZSA9IExpbmtDb21tYW5kLmNhbkV4ZWN1dGUoc3RhdGUpO1xuICB9XG5cbiAgaW5zZXJ0TGluayhlOiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGNvbnN0IHsgdGV4dCwgaHJlZiwgb3BlbkluTmV3VGFiIH0gPSB0aGlzLmZvcm0uZ2V0UmF3VmFsdWUoKTtcbiAgICBjb25zdCB7IGRpc3BhdGNoLCBzdGF0ZSB9ID0gdGhpcy5lZGl0b3JWaWV3O1xuICAgIGNvbnN0IHsgc2VsZWN0aW9uIH0gPSBzdGF0ZTtcblxuICAgIGNvbnN0IGF0dHJzID0ge1xuICAgICAgdGl0bGU6IGhyZWYsXG4gICAgICBocmVmLFxuICAgICAgdGFyZ2V0OiBvcGVuSW5OZXdUYWIgPyAnX2JsYW5rJyA6ICdfc2VsZidcbiAgICB9O1xuXG4gICAgaWYgKHNlbGVjdGlvbi5lbXB0eSkge1xuICAgICAgTGlua0NvbW1hbmQuaW5zZXJ0KHRleHQsIGF0dHJzKShzdGF0ZSwgZGlzcGF0Y2gpO1xuICAgICAgdGhpcy5lZGl0b3JWaWV3LmZvY3VzKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIExpbmtDb21tYW5kLnVwZGF0ZShhdHRycykoc3RhdGUsIGRpc3BhdGNoKTtcbiAgICB9XG4gICAgdGhpcy5oaWRlRm9ybSgpO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5lZGl0b3JWaWV3ID0gdGhpcy5tZW51U2VydmljZS5lZGl0b3IudmlldztcblxuICAgIHRoaXMudXBkYXRlU3Vic2NyaXB0aW9uID0gdGhpcy5tZW51U2VydmljZS5lZGl0b3IudXBkYXRlLnN1YnNjcmliZSgodmlldzogRWRpdG9yVmlldykgPT4ge1xuICAgICAgdGhpcy51cGRhdGUodmlldyk7XG4gICAgfSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnVwZGF0ZVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwiTmd4RWRpdG9yX19NZW51SXRlbS0tSWNvbkNvbnRhaW5lclwiIFtpbm5lckhUTUxdPVwiaWNvbiB8IHNhbml0aXplSHRtbFwiIChtb3VzZWRvd24pPVwib25Nb3VzZURvd24oJGV2ZW50KVwiXG4gIFt0aXRsZV09XCJ0aXRsZVwiPlxuPC9kaXY+XG5cbjwhLS0gcG9wdXAgLS0+XG48ZGl2ICpuZ0lmPVwic2hvd1BvcHVwXCIgY2xhc3M9XCJOZ3hFZGl0b3JfX1BvcHVwXCI+XG4gIDxmb3JtIGNsYXNzPVwiTmd4RWRpdG9yX19Qb3B1cC0tRm9ybVwiIFtmb3JtR3JvdXBdPVwiZm9ybVwiIChuZ1N1Ym1pdCk9XCJpbnNlcnRMaW5rKCRldmVudClcIj5cblxuICAgIDxkaXYgY2xhc3M9XCJOZ3hFZGl0b3JfX1BvcHVwLS1Gb3JtR3JvdXBcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJOZ3hFZGl0b3JfX1BvcHVwLS1Db2xcIj5cbiAgICAgICAgPGxhYmVsIGNsYXNzPVwiTmd4RWRpdG9yX19Qb3B1cC0tTGFiZWxcIj57e2dldExhYmVsKCd1cmwnKX19PC9sYWJlbD5cbiAgICAgICAgPGlucHV0IHR5cGU9XCJocmVmXCIgaWQ9XCJocmVmXCIgZm9ybUNvbnRyb2xOYW1lPVwiaHJlZlwiIGF1dG9mb2N1cyBhdXRvY29tcGxldGU9XCJvZmZcIiAvPlxuICAgICAgICA8ZGl2ICpuZ0lmPVwiaHJlZi50b3VjaGVkICYmIGhyZWYuaW52YWxpZFwiIGNsYXNzPVwiTmd4RWRpdG9yX19IZWxwVGV4dCBOZ3hFZGl0b3JfX0hlbHBUZXh0LS1FcnJvclwiPlxuICAgICAgICAgIHt7IGhyZWYuZXJyb3JzPy5bJ3BhdHRlcm4nXSAmJiAnUGxlYXNlIGVudGVyIHZhbGlkIHVybC4nIH19XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2IGNsYXNzPVwiTmd4RWRpdG9yX19Qb3B1cC0tRm9ybUdyb3VwXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiTmd4RWRpdG9yX19Qb3B1cC0tQ29sXCI+XG4gICAgICAgIDxsYWJlbCBjbGFzcz1cIk5neEVkaXRvcl9fUG9wdXAtLUxhYmVsXCI+e3tnZXRMYWJlbCgndGV4dCcpfX08L2xhYmVsPlxuICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBmb3JtQ29udHJvbE5hbWU9XCJ0ZXh0XCIgYXV0b2NvbXBsZXRlPVwib2ZmXCIgLz5cbiAgICAgICAgPGRpdiAqbmdJZj1cInRleHQudG91Y2hlZCAmJiB0ZXh0LmludmFsaWRcIiBjbGFzcz1cIk5neEVkaXRvcl9fSGVscFRleHQgTmd4RWRpdG9yX19IZWxwVGV4dC0tRXJyb3JcIj5cbiAgICAgICAgICB7eyB0ZXh0LmVycm9ycz8uWydyZXF1aXJlZCddICYmICdUaGlzIGlzIHJlcXVpcmVkJyB9fVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiBjbGFzcz1cIk5neEVkaXRvcl9fUG9wdXAtLUZvcm1Hcm91cFwiPlxuICAgICAgPGRpdiBjbGFzcz1cIk5neEVkaXRvcl9fUG9wdXAtLUNvbFwiPlxuICAgICAgICA8bGFiZWw+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGZvcm1Db250cm9sTmFtZT1cIm9wZW5Jbk5ld1RhYlwiIC8+XG4gICAgICAgICAge3tnZXRMYWJlbCgnb3BlbkluTmV3VGFiJyl9fVxuICAgICAgICA8L2xhYmVsPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgICA8YnV0dG9uIHR5cGU9XCJzdWJtaXRcIiBbZGlzYWJsZWRdPVwiIWZvcm0udmFsaWRcIj57e2dldExhYmVsKCdpbnNlcnQnKX19PC9idXR0b24+XG5cbiAgPC9mb3JtPlxuPC9kaXY+XG4iXX0=