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.5", 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.5", 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.5", 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGluay5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZWRpdG9yL3NyYy9saWIvbW9kdWxlcy9tZW51L2xpbmsvbGluay5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZWRpdG9yL3NyYy9saWIvbW9kdWxlcy9tZW51L2xpbmsvbGluay5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUFjLFdBQVcsRUFDbEMsWUFBWSxHQUNiLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBbUIsV0FBVyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQU1yRixPQUFPLElBQUksTUFBTSxnQkFBZ0IsQ0FBQztBQUNsQyxPQUFPLEVBQUUsSUFBSSxJQUFJLFdBQVcsRUFBRSxNQUFNLGlCQUFpQixDQUFDOzs7Ozs7O0FBUXRELE1BQU0sT0FBTyxhQUFhO0lBZ0J4QixZQUNVLEVBQWMsRUFDZCxXQUE2QixFQUM3QixXQUF3QjtRQUZ4QixPQUFFLEdBQUYsRUFBRSxDQUFZO1FBQ2QsZ0JBQVcsR0FBWCxXQUFXLENBQWtCO1FBQzdCLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBbEJsQyxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ2xCLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFDVCxlQUFVLEdBQUcsSUFBSSxDQUFDO1FBSTFCLFNBQUksR0FBRyxJQUFJLFNBQVMsQ0FBQztZQUNuQixJQUFJLEVBQUUsSUFBSSxXQUFXLENBQUMsRUFBRSxFQUFFO2dCQUN4QixVQUFVLENBQUMsUUFBUTtnQkFDbkIsVUFBVSxDQUFDLE9BQU8sQ0FBQyxnRkFBZ0YsQ0FBQzthQUNyRyxDQUFDO1lBQ0YsSUFBSSxFQUFFLElBQUksV0FBVyxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FB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QyxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztTQUM1QztRQUNELElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNsQixDQUFDO0lBRUQsUUFBUTtRQUNOLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDO1FBRS9DLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBZ0IsRUFBRSxFQUFFO1lBQ3RGLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUN4QyxDQUFDOzswR0FwSVUsYUFBYTs4RkFBYixhQUFhLDJPQ25CMUIsNG9EQXlDQTsyRkR0QmEsYUFBYTtrQkFOekIsU0FBUzsrQkFDRSxVQUFVOzBKQTJCa0MsS0FBSztzQkFBMUQsV0FBVzt1QkFBQyxtQ0FBbUM7Z0JBSUYsUUFBUTtzQkFBckQsV0FBVzt1QkFBQywyQkFBMkI7Z0JBb0JRLGVBQWU7c0JBQTlELFlBQVk7dUJBQUMsb0JBQW9CLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEhvc3RCaW5kaW5nLFxuICBIb3N0TGlzdGVuZXIsIE9uRGVzdHJveSwgT25Jbml0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEVkaXRvclZpZXcgfSBmcm9tICdwcm9zZW1pcnJvci12aWV3JztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBOZ3hFZGl0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vZWRpdG9yLnNlcnZpY2UnO1xuaW1wb3J0IHsgTWVudVNlcnZpY2UgfSBmcm9tICcuLi9tZW51LnNlcnZpY2UnO1xuaW1wb3J0IEljb24gZnJvbSAnLi4vLi4vLi4vaWNvbnMnO1xuaW1wb3J0IHsgTGluayBhcyBMaW5rQ29tbWFuZCB9IGZyb20gJy4uL01lbnVDb21tYW5kcyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1saW5rJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2xpbmsuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9saW5rLmNvbXBvbmVudC5zY3NzJ10sXG59KVxuXG5leHBvcnQgY2xhc3MgTGlua0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgc2hvd1BvcHVwID0gZmFsc2U7XG4gIGlzQWN0aXZlID0gZmFsc2U7XG4gIHByaXZhdGUgY2FuRXhlY3V0ZSA9IHRydWU7XG4gIHByaXZhdGUgZWRpdG9yVmlldzogRWRpdG9yVmlldztcbiAgcHJpdmF0ZSB1cGRhdGVTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcblxuICBmb3JtID0gbmV3IEZvcm1Hcm91cCh7XG4gICAgaHJlZjogbmV3IEZvcm1Db250cm9sKCcnLCBbXG4gICAgICBWYWxpZGF0b3JzLnJlcXVpcmVkLFxuICAgICAgVmFsaWRhdG9ycy5wYXR0ZXJuKCcoaHR0cHM/Oi8vKT8oW1xcXFxkYS16Li1dKylcXFxcLihbYS16Ll17Miw2fSlbL1xcXFx3IC4tXSovPz8oW14jXFxuXFxyXSopPyM/KFteXFxuXFxyXSopJyksXG4gICAgXSksXG4gICAgdGV4dDogbmV3IEZvcm1Db250cm9sKCcnLCBbVmFsaWRhdG9ycy5yZXF1aXJlZF0pLFxuICAgIG9wZW5Jbk5ld1RhYjogbmV3IEZvcm1Db250cm9sKHRydWUpLFxuICB9KTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVsOiBFbGVtZW50UmVmLFxuICAgIHByaXZhdGUgbmd4ZVNlcnZpY2U6IE5neEVkaXRvclNlcnZpY2UsXG4gICAgcHJpdmF0ZSBtZW51U2VydmljZTogTWVudVNlcnZpY2UsXG4gICkgeyB9XG5cbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5OZ3hFZGl0b3JfX01lbnVJdGVtLS1BY3RpdmUnKSBnZXQgdmFsaWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaXNBY3RpdmUgfHwgdGhpcy5zaG93UG9wdXA7XG4gIH1cblxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLk5neEVkaXRvci0tRGlzYWJsZWQnKSBnZXQgZGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICF0aGlzLmNhbkV4ZWN1dGU7XG4gIH1cblxuICBnZXQgaWNvbigpOiBzdHJpbmcge1xuICAgIHJldHVybiBJY29uLmdldCh0aGlzLmlzQWN0aXZlID8gJ3VubGluaycgOiAnbGluaycpO1xuICB9XG5cbiAgZ2V0IHRpdGxlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMubmd4ZVNlcnZpY2UubG9jYWxzLmdldCh0aGlzLmlzQWN0aXZlID8gJ3JlbW92ZUxpbmsnIDogJ2luc2VydExpbmsnKTtcbiAgfVxuXG4gIGdldCBocmVmKCk6IEFic3RyYWN0Q29udHJvbCB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybS5nZXQoJ2hyZWYnKTtcbiAgfVxuXG4gIGdldCB0ZXh0KCk6IEFic3RyYWN0Q29udHJvbCB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybS5nZXQoJ3RleHQnKTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50Om1vdXNlZG93bicsIFsnJGV2ZW50J10pIG9uRG9jdW1lbnRDbGljayhlOiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmVsLm5hdGl2ZUVsZW1lbnQuY29udGFpbnMoZS50YXJnZXQpICYmIHRoaXMuc2hvd1BvcHVwKSB7XG4gICAgICB0aGlzLmhpZGVGb3JtKCk7XG4gICAgfVxuICB9XG5cbiAgZ2V0TGFiZWwoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm5neGVTZXJ2aWNlLmxvY2Fscy5nZXQoa2V5KTtcbiAgfVxuXG4gIHByaXZhdGUgaGlkZUZvcm0oKTogdm9pZCB7XG4gICAgdGhpcy5zaG93UG9wdXAgPSBmYWxzZTtcbiAgICB0aGlzLmZvcm0ucmVzZXQoe1xuICAgICAgaHJlZjogJycsXG4gICAgICB0ZXh0OiAnJyxcbiAgICAgIG9wZW5Jbk5ld1RhYjogdHJ1ZSxcbiAgICB9KTtcbiAgICB0aGlzLnRleHQuZW5hYmxlKCk7XG4gIH1cblxuICBvbk1vdXNlRG93bihlOiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKGUuYnV0dG9uICE9PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgeyBzdGF0ZSwgZGlzcGF0Y2ggfSA9IHRoaXMuZWRpdG9yVmlldztcblxuICAgIGlmICh0aGlzLmlzQWN0aXZlKSB7XG4gICAgICBMaW5rQ29tbWFuZC5yZW1vdmUoc3RhdGUsIGRpc3BhdGNoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnNob3dQb3B1cCA9ICF0aGlzLnNob3dQb3B1cDtcbiAgICBpZiAodGhpcy5zaG93UG9wdXApIHtcbiAgICAgIHRoaXMuc2V0VGV4dCgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2V0VGV4dCA9ICgpID0+IHtcbiAgICBjb25zdCB7IHN0YXRlOiB7IHNlbGVjdGlvbiwgZG9jIH0gfSA9IHRoaXMuZWRpdG9yVmlldztcbiAgICBjb25zdCB7IGVtcHR5LCBmcm9tLCB0byB9ID0gc2VsZWN0aW9uO1xuICAgIGNvbnN0IHNlbGVjdGVkVGV4dCA9ICFlbXB0eSA/IGRvYy50ZXh0QmV0d2Vlbihmcm9tLCB0bykgOiAnJztcblxuICAgIGlmIChzZWxlY3RlZFRleHQpIHtcbiAgICAgIHRoaXMudGV4dC5wYXRjaFZhbHVlKHNlbGVjdGVkVGV4dCk7XG4gICAgICB0aGlzLnRleHQuZGlzYWJsZSgpO1xuICAgIH1cbiAgfTtcblxuICBwcml2YXRlIHVwZGF0ZSA9ICh2aWV3OiBFZGl0b3JWaWV3KSA9PiB7XG4gICAgY29uc3QgeyBzdGF0ZSB9ID0gdmlldztcbiAgICB0aGlzLmlzQWN0aXZlID0gTGlua0NvbW1hbmQuaXNBY3RpdmUoc3RhdGUsIHsgc3RyaWN0OiBmYWxzZSB9KTtcbiAgICB0aGlzLmNhbkV4ZWN1dGUgPSBMaW5rQ29tbWFuZC5jYW5FeGVjdXRlKHN0YXRlKTtcbiAgfTtcblxuICBpbnNlcnRMaW5rKGU6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgY29uc3QgeyB0ZXh0LCBocmVmLCBvcGVuSW5OZXdUYWIgfSA9IHRoaXMuZm9ybS5nZXRSYXdWYWx1ZSgpO1xuICAgIGNvbnN0IHsgZGlzcGF0Y2gsIHN0YXRlIH0gPSB0aGlzLmVkaXRvclZpZXc7XG4gICAgY29uc3QgeyBzZWxlY3Rpb24gfSA9IHN0YXRlO1xuXG4gICAgY29uc3QgYXR0cnMgPSB7XG4gICAgICB0aXRsZTogaHJlZixcbiAgICAgIGhyZWYsXG4gICAgICB0YXJnZXQ6IG9wZW5Jbk5ld1RhYiA/ICdfYmxhbmsnIDogJ19zZWxmJyxcbiAgICB9O1xuXG4gICAgaWYgKHNlbGVjdGlvbi5lbXB0eSkge1xuICAgICAgTGlua0NvbW1hbmQuaW5zZXJ0KHRleHQsIGF0dHJzKShzdGF0ZSwgZGlzcGF0Y2gpO1xuICAgICAgdGhpcy5lZGl0b3JWaWV3LmZvY3VzKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIExpbmtDb21tYW5kLnVwZGF0ZShhdHRycykoc3RhdGUsIGRpc3BhdGNoKTtcbiAgICB9XG4gICAgdGhpcy5oaWRlRm9ybSgpO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5lZGl0b3JWaWV3ID0gdGhpcy5tZW51U2VydmljZS5lZGl0b3IudmlldztcblxuICAgIHRoaXMudXBkYXRlU3Vic2NyaXB0aW9uID0gdGhpcy5tZW51U2VydmljZS5lZGl0b3IudXBkYXRlLnN1YnNjcmliZSgodmlldzogRWRpdG9yVmlldykgPT4ge1xuICAgICAgdGhpcy51cGRhdGUodmlldyk7XG4gICAgfSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnVwZGF0ZVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwiTmd4RWRpdG9yX19NZW51SXRlbS0tSWNvbkNvbnRhaW5lclwiIFtpbm5lckhUTUxdPVwiaWNvbiB8IHNhbml0aXplSHRtbFwiIChtb3VzZWRvd24pPVwib25Nb3VzZURvd24oJGV2ZW50KVwiXG4gIFt0aXRsZV09XCJ0aXRsZVwiPlxuPC9kaXY+XG5cbjwhLS0gcG9wdXAgLS0+XG48ZGl2ICpuZ0lmPVwic2hvd1BvcHVwXCIgY2xhc3M9XCJOZ3hFZGl0b3JfX1BvcHVwXCI+XG4gIDxmb3JtIGNsYXNzPVwiTmd4RWRpdG9yX19Qb3B1cC0tRm9ybVwiIFtmb3JtR3JvdXBdPVwiZm9ybVwiIChuZ1N1Ym1pdCk9XCJpbnNlcnRMaW5rKCRldmVudClcIj5cblxuICAgIDxkaXYgY2xhc3M9XCJOZ3hFZGl0b3JfX1BvcHVwLS1Gb3JtR3JvdXBcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJOZ3hFZGl0b3JfX1BvcHVwLS1Db2xcIj5cbiAgICAgICAgPGxhYmVsIGNsYXNzPVwiTmd4RWRpdG9yX19Qb3B1cC0tTGFiZWxcIj57e2dldExhYmVsKCd1cmwnKX19PC9sYWJlbD5cbiAgICAgICAgPGlucHV0IHR5cGU9XCJocmVmXCIgaWQ9XCJocmVmXCIgZm9ybUNvbnRyb2xOYW1lPVwiaHJlZlwiIGF1dG9mb2N1cyBhdXRvY29tcGxldGU9XCJvZmZcIiAvPlxuICAgICAgICA8ZGl2ICpuZ0lmPVwiaHJlZi50b3VjaGVkICYmIGhyZWYuaW52YWxpZFwiIGNsYXNzPVwiTmd4RWRpdG9yX19IZWxwVGV4dCBOZ3hFZGl0b3JfX0hlbHBUZXh0LS1FcnJvclwiPlxuICAgICAgICAgIHt7IGhyZWYuZXJyb3JzPy5bJ3BhdHRlcm4nXSAmJiAnUGxlYXNlIGVudGVyIHZhbGlkIHVybC4nIH19XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2IGNsYXNzPVwiTmd4RWRpdG9yX19Qb3B1cC0tRm9ybUdyb3VwXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiTmd4RWRpdG9yX19Qb3B1cC0tQ29sXCI+XG4gICAgICAgIDxsYWJlbCBjbGFzcz1cIk5neEVkaXRvcl9fUG9wdXAtLUxhYmVsXCI+e3tnZXRMYWJlbCgndGV4dCcpfX08L2xhYmVsPlxuICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBmb3JtQ29udHJvbE5hbWU9XCJ0ZXh0XCIgYXV0b2NvbXBsZXRlPVwib2ZmXCIgLz5cbiAgICAgICAgPGRpdiAqbmdJZj1cInRleHQudG91Y2hlZCAmJiB0ZXh0LmludmFsaWRcIiBjbGFzcz1cIk5neEVkaXRvcl9fSGVscFRleHQgTmd4RWRpdG9yX19IZWxwVGV4dC0tRXJyb3JcIj5cbiAgICAgICAgICB7eyB0ZXh0LmVycm9ycz8uWydyZXF1aXJlZCddICYmICdUaGlzIGlzIHJlcXVpcmVkJyB9fVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiBjbGFzcz1cIk5neEVkaXRvcl9fUG9wdXAtLUZvcm1Hcm91cFwiPlxuICAgICAgPGRpdiBjbGFzcz1cIk5neEVkaXRvcl9fUG9wdXAtLUNvbFwiPlxuICAgICAgICA8bGFiZWw+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGZvcm1Db250cm9sTmFtZT1cIm9wZW5Jbk5ld1RhYlwiIC8+XG4gICAgICAgICAge3tnZXRMYWJlbCgnb3BlbkluTmV3VGFiJyl9fVxuICAgICAgICA8L2xhYmVsPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgICA8YnV0dG9uIHR5cGU9XCJzdWJtaXRcIiBbZGlzYWJsZWRdPVwiIWZvcm0udmFsaWRcIj57e2dldExhYmVsKCdpbnNlcnQnKX19PC9idXR0b24+XG5cbiAgPC9mb3JtPlxuPC9kaXY+XG4iXX0=