UNPKG

@iget/editor

Version:

WYSIWYG Editor for Angular Material applications

117 lines 31.5 kB
import { Component, Input, Output, EventEmitter } from '@angular/core'; import * as Utils from '../common/utils/iget-editor.utils'; import { LinkDialogComponent } from '../dialogs/link-dialog/link-dialog.component'; import { COLOR_PALETTE } from './color-palette'; import * as i0 from "@angular/core"; import * as i1 from "../common/services/message.service"; import * as i2 from "../common/services/command-executor.service"; import * as i3 from "@angular/material/dialog"; import * as i4 from "../iget-editor-toolbar-group/iget-editor-toolbar-group.component"; import * as i5 from "../iget-editor-toolbar-button/iget-editor-toolbar-button.component"; import * as i6 from "@angular/material/menu"; import * as i7 from "@angular/common"; export class IgetEditorToolbarComponent { constructor(_messageService, _commandExecutorService, dialog) { this._messageService = _messageService; this._commandExecutorService = _commandExecutorService; this.dialog = dialog; /** font family name */ this.fontName = ''; /** font size */ this.fontSize = ''; /** * Emits an event when a toolbar button is clicked */ this.execute = new EventEmitter(); this.colors = COLOR_PALETTE; } /** * enable or diable toolbar based on configuration * * @param value name of the toolbar buttons */ canEnableToolbarOptions(value) { return Utils.canEnableToolbarOptions(value, this.config['toolbar']); } /** * triggers command from the toolbar to be executed and emits an event * * @param command name of the command to be executed */ triggerCommand(command) { this.execute.emit(command); } /** * inserts link in the editor */ insertLink() { const linkDialogRef = this.dialog.open(LinkDialogComponent, { data: { selection: this._commandExecutorService.savedSelection } }); linkDialogRef.afterClosed().subscribe((data) => { if (data) { let urlLink = data.url; const emailPattern = new RegExp([ '^(([^<>()\\[\\]\\.,;:\\s@\\"]+(\\.[^<>()\\[\\]\\.,;:\\s@\\"]+)*)', '|(\\".+\\"))@(([^<>()[\\]\\.,;:\\s@\\"]+\\.)+[^<>()[\\]\\.,;:\\s', '@\\"]{2,})$' ].join('')); if (emailPattern.exec(urlLink)) { urlLink = `mailto:${urlLink}`; } this._commandExecutorService.createLink({ urlLink, urlText: data.label, }); } }); } /** insert text/background color */ setTextColor(color) { this.insertColor(color, 'textColor'); } /** insert text/background color */ setBackgroundColor(color) { this.insertColor(color, 'backgroundColor'); } /** insert text/background color */ insertColor(color, where) { try { this._commandExecutorService.insertColor(color, where); } catch (error) { this._messageService.sendMessage(error.message); } } /** set font size */ setFontSize(fontSize) { try { this._commandExecutorService.setFontSize(fontSize); } catch (error) { this._messageService.sendMessage(error.message); } } /** set font Name/family */ setFontName(fontName) { try { this._commandExecutorService.setFontName(fontName); } catch (error) { this._messageService.sendMessage(error.message); } } } IgetEditorToolbarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: IgetEditorToolbarComponent, deps: [{ token: i1.MessageService }, { token: i2.CommandExecutorService }, { token: i3.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); IgetEditorToolbarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.1", type: IgetEditorToolbarComponent, selector: "iget-editor-toolbar", inputs: { config: "config" }, outputs: { execute: "execute" }, providers: [], ngImport: i0, template: "<iget-editor-toolbar-group *ngFor=\"let group of config\">\n <ng-container *ngFor=\"let button of group\">\n <iget-editor-toolbar-button *ngIf=\"button === 'bold'\" icon=\"format_bold\" title=\"Bold\" (clicked)=\"triggerCommand('bold')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'italic'\" icon=\"format_italic\" title=\"Italic\" (clicked)=\"triggerCommand('italic')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'underline'\" icon=\"format_underline\" title=\"Underline\" (clicked)=\"triggerCommand('underline')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'strikethrough'\" icon=\"format_strikethrough\" title=\"Strikethrough\" (clicked)=\"triggerCommand('strikethrough')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'font'\" icon=\"font_download\" title=\"Font Family\" [menu]=\"true\">\n <button mat-menu-item (clicked)=\"setFontName('sans-serif')\" [style.fontFamily]=\"'sans-serif'\">Sans-serif</button>\n <button mat-menu-item (clicked)=\"setFontName('serif')\" [style.fontFamily]=\"'serif'\">Serif</button>\n <button mat-menu-item (clicked)=\"setFontName('monospace')\" [style.fontFamily]=\"'monospace'\">Monospace</button>\n </iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'fontSize'\" icon=\"format_size\" title=\"Font size\" [menu]=\"true\">\n <button mat-menu-item (clicked)=\"setFontSize('10')\" [style.fontSize]=\"'10px'\">Small</button>\n <button mat-menu-item (clicked)=\"setFontSize('13')\" [style.fontSize]=\"'13px'\">Regular</button>\n <button mat-menu-item (clicked)=\"setFontSize('18')\" [style.fontSize]=\"'18px'\">Large</button>\n <button mat-menu-item (clicked)=\"setFontSize('32')\" [style.fontSize]=\"'32px'\">Huge</button>\n </iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'textColor'\" icon=\"format_color_text\" title=\"Text color\" [menu]=\"true\">\n <div class=\"colors\" matMenuContent>\n <span *ngFor=\"let color of colors\" [style.backgroundColor]=\"color\" [class.separator]=\"!color\" (clicked)=\"setTextColor(color)\"></span>\n </div>\n </iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'fillColor'\" icon=\"format_color_fill\" title=\"Fill color\" [menu]=\"true\">\n <div class=\"colors\" matMenuContent>\n <span *ngFor=\"let color of colors\" [style.backgroundColor]=\"color\" [class.separator]=\"!color\" (clicked)=\"setBackgroundColor(color)\"></span>\n </div>\n </iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'removeFormat'\" icon=\"format_clear\" title=\"Clear formatting\" (clicked)=\"triggerCommand('removeFormat')\"></iget-editor-toolbar-button>\n <ng-container *ngIf=\"button === 'align'\">\n <iget-editor-toolbar-button icon=\"format_align_left\" title=\"Align left\" (clicked)=\"triggerCommand('justifyLeft')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button icon=\"format_align_center\" title=\"Align center\" (clicked)=\"triggerCommand('justifyCenter')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button icon=\"format_align_right\" title=\"Align right\" (clicked)=\"triggerCommand('justifyRight')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button icon=\"format_align_justify\" title=\"Justify\" (clicked)=\"triggerCommand('justifyFull')\"></iget-editor-toolbar-button>\n </ng-container>\n <ng-container *ngIf=\"button === 'indent'\">\n <iget-editor-toolbar-button icon=\"format_indent_decrease\" title=\"Outdent\" (clicked)=\"triggerCommand('outdent')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button icon=\"format_indent_increase\" title=\"Indent\" (clicked)=\"triggerCommand('indent')\"></iget-editor-toolbar-button>\n </ng-container>\n <iget-editor-toolbar-button *ngIf=\"button === 'quote'\" icon=\"format_quote\" title=\"Blockquote\" (clicked)=\"triggerCommand('blockquote')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'unorderedList'\" icon=\"format_list_bulleted\" title=\"Unordered list\" (clicked)=\"triggerCommand('insertUnorderedList')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'orderedList'\" icon=\"format_list_numbered\" title=\"Ordered list\" (clicked)=\"triggerCommand('insertOrderedList')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'undo'\" icon=\"undo\" title=\"Undo\" (clicked)=\"triggerCommand('undo')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'redo'\" icon=\"redo\" title=\"Redo\" (clicked)=\"triggerCommand('redo')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'anchor'\" icon=\"insert_link\" title=\"Insert link\" (clicked)=\"insertLink()\"></iget-editor-toolbar-button>\n </ng-container>\n", styles: [":host{display:flex;flex-wrap:wrap;box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f}.mat-button{padding:0;min-width:36px}.colors{display:flex;flex-wrap:wrap;width:180px;margin:0 8px}.colors>span:not(.separator){width:calc(12.5% - 2px);display:block;height:auto;padding-top:calc(12.5% - 2px);cursor:pointer;border:1px solid white}.colors>span:not(.separator):hover{border-color:#000}.colors>span.separator{width:100%;height:4px}\n"], components: [{ type: i4.IgetEditorToolbarGroupComponent, selector: "iget-editor-toolbar-group" }, { type: i5.IgetEditorToolbarButtonComponent, selector: "iget-editor-toolbar-button", inputs: ["icon", "title", "menu"], outputs: ["clicked"] }, { type: i6.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }], directives: [{ type: i7.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: IgetEditorToolbarComponent, decorators: [{ type: Component, args: [{ selector: 'iget-editor-toolbar', providers: [], template: "<iget-editor-toolbar-group *ngFor=\"let group of config\">\n <ng-container *ngFor=\"let button of group\">\n <iget-editor-toolbar-button *ngIf=\"button === 'bold'\" icon=\"format_bold\" title=\"Bold\" (clicked)=\"triggerCommand('bold')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'italic'\" icon=\"format_italic\" title=\"Italic\" (clicked)=\"triggerCommand('italic')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'underline'\" icon=\"format_underline\" title=\"Underline\" (clicked)=\"triggerCommand('underline')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'strikethrough'\" icon=\"format_strikethrough\" title=\"Strikethrough\" (clicked)=\"triggerCommand('strikethrough')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'font'\" icon=\"font_download\" title=\"Font Family\" [menu]=\"true\">\n <button mat-menu-item (clicked)=\"setFontName('sans-serif')\" [style.fontFamily]=\"'sans-serif'\">Sans-serif</button>\n <button mat-menu-item (clicked)=\"setFontName('serif')\" [style.fontFamily]=\"'serif'\">Serif</button>\n <button mat-menu-item (clicked)=\"setFontName('monospace')\" [style.fontFamily]=\"'monospace'\">Monospace</button>\n </iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'fontSize'\" icon=\"format_size\" title=\"Font size\" [menu]=\"true\">\n <button mat-menu-item (clicked)=\"setFontSize('10')\" [style.fontSize]=\"'10px'\">Small</button>\n <button mat-menu-item (clicked)=\"setFontSize('13')\" [style.fontSize]=\"'13px'\">Regular</button>\n <button mat-menu-item (clicked)=\"setFontSize('18')\" [style.fontSize]=\"'18px'\">Large</button>\n <button mat-menu-item (clicked)=\"setFontSize('32')\" [style.fontSize]=\"'32px'\">Huge</button>\n </iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'textColor'\" icon=\"format_color_text\" title=\"Text color\" [menu]=\"true\">\n <div class=\"colors\" matMenuContent>\n <span *ngFor=\"let color of colors\" [style.backgroundColor]=\"color\" [class.separator]=\"!color\" (clicked)=\"setTextColor(color)\"></span>\n </div>\n </iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'fillColor'\" icon=\"format_color_fill\" title=\"Fill color\" [menu]=\"true\">\n <div class=\"colors\" matMenuContent>\n <span *ngFor=\"let color of colors\" [style.backgroundColor]=\"color\" [class.separator]=\"!color\" (clicked)=\"setBackgroundColor(color)\"></span>\n </div>\n </iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'removeFormat'\" icon=\"format_clear\" title=\"Clear formatting\" (clicked)=\"triggerCommand('removeFormat')\"></iget-editor-toolbar-button>\n <ng-container *ngIf=\"button === 'align'\">\n <iget-editor-toolbar-button icon=\"format_align_left\" title=\"Align left\" (clicked)=\"triggerCommand('justifyLeft')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button icon=\"format_align_center\" title=\"Align center\" (clicked)=\"triggerCommand('justifyCenter')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button icon=\"format_align_right\" title=\"Align right\" (clicked)=\"triggerCommand('justifyRight')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button icon=\"format_align_justify\" title=\"Justify\" (clicked)=\"triggerCommand('justifyFull')\"></iget-editor-toolbar-button>\n </ng-container>\n <ng-container *ngIf=\"button === 'indent'\">\n <iget-editor-toolbar-button icon=\"format_indent_decrease\" title=\"Outdent\" (clicked)=\"triggerCommand('outdent')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button icon=\"format_indent_increase\" title=\"Indent\" (clicked)=\"triggerCommand('indent')\"></iget-editor-toolbar-button>\n </ng-container>\n <iget-editor-toolbar-button *ngIf=\"button === 'quote'\" icon=\"format_quote\" title=\"Blockquote\" (clicked)=\"triggerCommand('blockquote')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'unorderedList'\" icon=\"format_list_bulleted\" title=\"Unordered list\" (clicked)=\"triggerCommand('insertUnorderedList')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'orderedList'\" icon=\"format_list_numbered\" title=\"Ordered list\" (clicked)=\"triggerCommand('insertOrderedList')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'undo'\" icon=\"undo\" title=\"Undo\" (clicked)=\"triggerCommand('undo')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'redo'\" icon=\"redo\" title=\"Redo\" (clicked)=\"triggerCommand('redo')\"></iget-editor-toolbar-button>\n <iget-editor-toolbar-button *ngIf=\"button === 'anchor'\" icon=\"insert_link\" title=\"Insert link\" (clicked)=\"insertLink()\"></iget-editor-toolbar-button>\n </ng-container>\n", styles: [":host{display:flex;flex-wrap:wrap;box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f}.mat-button{padding:0;min-width:36px}.colors{display:flex;flex-wrap:wrap;width:180px;margin:0 8px}.colors>span:not(.separator){width:calc(12.5% - 2px);display:block;height:auto;padding-top:calc(12.5% - 2px);cursor:pointer;border:1px solid white}.colors>span:not(.separator):hover{border-color:#000}.colors>span.separator{width:100%;height:4px}\n"] }] }], ctorParameters: function () { return [{ type: i1.MessageService }, { type: i2.CommandExecutorService }, { type: i3.MatDialog }]; }, propDecorators: { config: [{ type: Input }], execute: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWdldC1lZGl0b3ItdG9vbGJhci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL2lnZXQtZWRpdG9yL2lnZXQtZWRpdG9yLXRvb2xiYXIvaWdldC1lZGl0b3ItdG9vbGJhci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL2lnZXQtZWRpdG9yL2lnZXQtZWRpdG9yLXRvb2xiYXIvaWdldC1lZGl0b3ItdG9vbGJhci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFxQixNQUFNLGVBQWUsQ0FBQztBQUcxRixPQUFPLEtBQUssS0FBSyxNQUFNLG1DQUFtQyxDQUFDO0FBQzNELE9BQU8sRUFBQyxtQkFBbUIsRUFBQyxNQUFNLDhDQUE4QyxDQUFDO0FBR2pGLE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7Ozs7O0FBUzlDLE1BQU0sT0FBTywwQkFBMEI7SUFnQnJDLFlBQW9CLGVBQStCLEVBQ3pDLHVCQUErQyxFQUMvQyxNQUFpQjtRQUZQLG9CQUFlLEdBQWYsZUFBZSxDQUFnQjtRQUN6Qyw0QkFBdUIsR0FBdkIsdUJBQXVCLENBQXdCO1FBQy9DLFdBQU0sR0FBTixNQUFNLENBQVc7UUFqQjNCLHVCQUF1QjtRQUN2QixhQUFRLEdBQUcsRUFBRSxDQUFDO1FBQ2QsZ0JBQWdCO1FBQ2hCLGFBQVEsR0FBRyxFQUFFLENBQUM7UUFNZDs7V0FFRztRQUNPLFlBQU8sR0FBeUIsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUNyRSxXQUFNLEdBQUcsYUFBYSxDQUFDO0lBS3BCLENBQUM7SUFFSjs7OztPQUlHO0lBQ0gsdUJBQXVCLENBQUMsS0FBSztRQUMzQixPQUFPLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ3RFLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsY0FBYyxDQUFDLE9BQWU7UUFDNUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVEOztPQUVHO0lBQ0gsVUFBVTtRQUNSLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFO1lBQzFELElBQUksRUFBRTtnQkFDSixTQUFTLEVBQUUsSUFBSSxDQUFDLHVCQUF1QixDQUFDLGNBQWM7YUFDdkQ7U0FDRixDQUFDLENBQUM7UUFFSCxhQUFhLENBQUMsV0FBVyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7WUFDN0MsSUFBSSxJQUFJLEVBQUU7Z0JBQ1IsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQztnQkFDdkIsTUFBTSxZQUFZLEdBQUcsSUFBSSxNQUFNLENBQUM7b0JBQzlCLGtFQUFrRTtvQkFDbEUsa0VBQWtFO29CQUNsRSxhQUFhO2lCQUNkLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBRVosSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFO29CQUM5QixPQUFPLEdBQUcsVUFBVSxPQUFPLEVBQUUsQ0FBQztpQkFDL0I7Z0JBRUQsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFVBQVUsQ0FBQztvQkFDdEMsT0FBTztvQkFDUCxPQUFPLEVBQUUsSUFBSSxDQUFDLEtBQUs7aUJBQ3BCLENBQUMsQ0FBQzthQUNKO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsbUNBQW1DO0lBQ25DLFlBQVksQ0FBQyxLQUFhO1FBQ3hCLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFFRCxtQ0FBbUM7SUFDbkMsa0JBQWtCLENBQUMsS0FBYTtRQUM5QixJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRCxtQ0FBbUM7SUFDbkMsV0FBVyxDQUFDLEtBQWEsRUFBRSxLQUFhO1FBQ3RDLElBQUk7WUFDRixJQUFJLENBQUMsdUJBQXVCLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztTQUN4RDtRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsSUFBSSxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQ2pEO0lBQ0gsQ0FBQztJQUVELG9CQUFvQjtJQUNwQixXQUFXLENBQUMsUUFBZ0I7UUFDMUIsSUFBSTtZQUNGLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDcEQ7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLElBQUksQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUNqRDtJQUNILENBQUM7SUFFRCwyQkFBMkI7SUFDM0IsV0FBVyxDQUFDLFFBQWdCO1FBQzFCLElBQUk7WUFDRixJQUFJLENBQUMsdUJBQXVCLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQ3BEO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZCxJQUFJLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDakQ7SUFDSCxDQUFDOzt1SEF6R1UsMEJBQTBCOzJHQUExQiwwQkFBMEIsNkdBSDFCLEVBQUUsMEJDYmYsZzdKQTZDQTsyRkQ3QmEsMEJBQTBCO2tCQVB0QyxTQUFTOytCQUNFLHFCQUFxQixhQUdwQixFQUFFO2tLQVlKLE1BQU07c0JBQWQsS0FBSztnQkFJSSxPQUFPO3NCQUFoQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIE9uSW5pdCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tYW5kRXhlY3V0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vY29tbW9uL3NlcnZpY2VzL2NvbW1hbmQtZXhlY3V0b3Iuc2VydmljZSc7XG5pbXBvcnQgeyBNZXNzYWdlU2VydmljZSB9IGZyb20gJy4uL2NvbW1vbi9zZXJ2aWNlcy9tZXNzYWdlLnNlcnZpY2UnO1xuaW1wb3J0ICogYXMgVXRpbHMgZnJvbSAnLi4vY29tbW9uL3V0aWxzL2lnZXQtZWRpdG9yLnV0aWxzJztcbmltcG9ydCB7TGlua0RpYWxvZ0NvbXBvbmVudH0gZnJvbSAnLi4vZGlhbG9ncy9saW5rLWRpYWxvZy9saW5rLWRpYWxvZy5jb21wb25lbnQnO1xuaW1wb3J0IHtNYXREaWFsb2d9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2RpYWxvZyc7XG5pbXBvcnQge1Rvb2xiYXJDb25maWd9IGZyb20gJy4uL2lnZXQtZWRpdG9yLWNvbmZpZyc7XG5pbXBvcnQge0NPTE9SX1BBTEVUVEV9IGZyb20gJy4vY29sb3ItcGFsZXR0ZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2lnZXQtZWRpdG9yLXRvb2xiYXInLFxuICB0ZW1wbGF0ZVVybDogJy4vaWdldC1lZGl0b3ItdG9vbGJhci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2lnZXQtZWRpdG9yLXRvb2xiYXIuY29tcG9uZW50LnNjc3MnXSxcbiAgcHJvdmlkZXJzOiBbXVxufSlcblxuZXhwb3J0IGNsYXNzIElnZXRFZGl0b3JUb29sYmFyQ29tcG9uZW50IHtcbiAgLyoqIGZvbnQgZmFtaWx5IG5hbWUgKi9cbiAgZm9udE5hbWUgPSAnJztcbiAgLyoqIGZvbnQgc2l6ZSAqL1xuICBmb250U2l6ZSA9ICcnO1xuXG4gIC8qKlxuICAgKiBFZGl0b3IgY29uZmlndXJhdGlvblxuICAgKi9cbiAgQElucHV0KCkgY29uZmlnOiBUb29sYmFyQ29uZmlnO1xuICAvKipcbiAgICogRW1pdHMgYW4gZXZlbnQgd2hlbiBhIHRvb2xiYXIgYnV0dG9uIGlzIGNsaWNrZWRcbiAgICovXG4gIEBPdXRwdXQoKSBleGVjdXRlOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuICBjb2xvcnMgPSBDT0xPUl9QQUxFVFRFO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgX21lc3NhZ2VTZXJ2aWNlOiBNZXNzYWdlU2VydmljZSxcbiAgICBwcml2YXRlIF9jb21tYW5kRXhlY3V0b3JTZXJ2aWNlOiBDb21tYW5kRXhlY3V0b3JTZXJ2aWNlLFxuICAgIHByaXZhdGUgZGlhbG9nOiBNYXREaWFsb2dcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBlbmFibGUgb3IgZGlhYmxlIHRvb2xiYXIgYmFzZWQgb24gY29uZmlndXJhdGlvblxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgbmFtZSBvZiB0aGUgdG9vbGJhciBidXR0b25zXG4gICAqL1xuICBjYW5FbmFibGVUb29sYmFyT3B0aW9ucyh2YWx1ZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBVdGlscy5jYW5FbmFibGVUb29sYmFyT3B0aW9ucyh2YWx1ZSwgdGhpcy5jb25maWdbJ3Rvb2xiYXInXSk7XG4gIH1cblxuICAvKipcbiAgICogdHJpZ2dlcnMgY29tbWFuZCBmcm9tIHRoZSB0b29sYmFyIHRvIGJlIGV4ZWN1dGVkIGFuZCBlbWl0cyBhbiBldmVudFxuICAgKlxuICAgKiBAcGFyYW0gY29tbWFuZCBuYW1lIG9mIHRoZSBjb21tYW5kIHRvIGJlIGV4ZWN1dGVkXG4gICAqL1xuICB0cmlnZ2VyQ29tbWFuZChjb21tYW5kOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmV4ZWN1dGUuZW1pdChjb21tYW5kKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBpbnNlcnRzIGxpbmsgaW4gdGhlIGVkaXRvclxuICAgKi9cbiAgaW5zZXJ0TGluaygpOiB2b2lkIHtcbiAgICBjb25zdCBsaW5rRGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3BlbihMaW5rRGlhbG9nQ29tcG9uZW50LCB7XG4gICAgICBkYXRhOiB7XG4gICAgICAgIHNlbGVjdGlvbjogdGhpcy5fY29tbWFuZEV4ZWN1dG9yU2VydmljZS5zYXZlZFNlbGVjdGlvblxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgbGlua0RpYWxvZ1JlZi5hZnRlckNsb3NlZCgpLnN1YnNjcmliZSgoZGF0YSkgPT4ge1xuICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgbGV0IHVybExpbmsgPSBkYXRhLnVybDtcbiAgICAgICAgY29uc3QgZW1haWxQYXR0ZXJuID0gbmV3IFJlZ0V4cChbXG4gICAgICAgICAgJ14oKFtePD4oKVxcXFxbXFxcXF1cXFxcLiw7OlxcXFxzQFxcXFxcIl0rKFxcXFwuW148PigpXFxcXFtcXFxcXVxcXFwuLDs6XFxcXHNAXFxcXFwiXSspKiknLFxuICAgICAgICAgICd8KFxcXFxcIi4rXFxcXFwiKSlAKChbXjw+KClbXFxcXF1cXFxcLiw7OlxcXFxzQFxcXFxcIl0rXFxcXC4pK1tePD4oKVtcXFxcXVxcXFwuLDs6XFxcXHMnLFxuICAgICAgICAgICdAXFxcXFwiXXsyLH0pJCdcbiAgICAgICAgXS5qb2luKCcnKSk7XG5cbiAgICAgICAgaWYgKGVtYWlsUGF0dGVybi5leGVjKHVybExpbmspKSB7XG4gICAgICAgICAgdXJsTGluayA9IGBtYWlsdG86JHt1cmxMaW5rfWA7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9jb21tYW5kRXhlY3V0b3JTZXJ2aWNlLmNyZWF0ZUxpbmsoe1xuICAgICAgICAgIHVybExpbmssXG4gICAgICAgICAgdXJsVGV4dDogZGF0YS5sYWJlbCxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKiogaW5zZXJ0IHRleHQvYmFja2dyb3VuZCBjb2xvciAqL1xuICBzZXRUZXh0Q29sb3IoY29sb3I6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuaW5zZXJ0Q29sb3IoY29sb3IsICd0ZXh0Q29sb3InKTtcbiAgfVxuXG4gIC8qKiBpbnNlcnQgdGV4dC9iYWNrZ3JvdW5kIGNvbG9yICovXG4gIHNldEJhY2tncm91bmRDb2xvcihjb2xvcjogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5pbnNlcnRDb2xvcihjb2xvciwgJ2JhY2tncm91bmRDb2xvcicpO1xuICB9XG5cbiAgLyoqIGluc2VydCB0ZXh0L2JhY2tncm91bmQgY29sb3IgKi9cbiAgaW5zZXJ0Q29sb3IoY29sb3I6IHN0cmluZywgd2hlcmU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLl9jb21tYW5kRXhlY3V0b3JTZXJ2aWNlLmluc2VydENvbG9yKGNvbG9yLCB3aGVyZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMuX21lc3NhZ2VTZXJ2aWNlLnNlbmRNZXNzYWdlKGVycm9yLm1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBzZXQgZm9udCBzaXplICovXG4gIHNldEZvbnRTaXplKGZvbnRTaXplOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5fY29tbWFuZEV4ZWN1dG9yU2VydmljZS5zZXRGb250U2l6ZShmb250U2l6ZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMuX21lc3NhZ2VTZXJ2aWNlLnNlbmRNZXNzYWdlKGVycm9yLm1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBzZXQgZm9udCBOYW1lL2ZhbWlseSAqL1xuICBzZXRGb250TmFtZShmb250TmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuX2NvbW1hbmRFeGVjdXRvclNlcnZpY2Uuc2V0Rm9udE5hbWUoZm9udE5hbWUpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLl9tZXNzYWdlU2VydmljZS5zZW5kTWVzc2FnZShlcnJvci5tZXNzYWdlKTtcbiAgICB9XG4gIH1cbn1cbiIsIjxpZ2V0LWVkaXRvci10b29sYmFyLWdyb3VwICpuZ0Zvcj1cImxldCBncm91cCBvZiBjb25maWdcIj5cbiAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgYnV0dG9uIG9mIGdyb3VwXCI+XG4gICAgPGlnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uICpuZ0lmPVwiYnV0dG9uID09PSAnYm9sZCdcIiBpY29uPVwiZm9ybWF0X2JvbGRcIiB0aXRsZT1cIkJvbGRcIiAoY2xpY2tlZCk9XCJ0cmlnZ2VyQ29tbWFuZCgnYm9sZCcpXCI+PC9pZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbj5cbiAgICA8aWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24gKm5nSWY9XCJidXR0b24gPT09ICdpdGFsaWMnXCIgaWNvbj1cImZvcm1hdF9pdGFsaWNcIiB0aXRsZT1cIkl0YWxpY1wiIChjbGlja2VkKT1cInRyaWdnZXJDb21tYW5kKCdpdGFsaWMnKVwiPjwvaWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24+XG4gICAgPGlnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uICpuZ0lmPVwiYnV0dG9uID09PSAndW5kZXJsaW5lJ1wiIGljb249XCJmb3JtYXRfdW5kZXJsaW5lXCIgdGl0bGU9XCJVbmRlcmxpbmVcIiAoY2xpY2tlZCk9XCJ0cmlnZ2VyQ29tbWFuZCgndW5kZXJsaW5lJylcIj48L2lnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uPlxuICAgIDxpZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbiAqbmdJZj1cImJ1dHRvbiA9PT0gJ3N0cmlrZXRocm91Z2gnXCIgaWNvbj1cImZvcm1hdF9zdHJpa2V0aHJvdWdoXCIgdGl0bGU9XCJTdHJpa2V0aHJvdWdoXCIgKGNsaWNrZWQpPVwidHJpZ2dlckNvbW1hbmQoJ3N0cmlrZXRocm91Z2gnKVwiPjwvaWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24+XG4gICAgPGlnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uICpuZ0lmPVwiYnV0dG9uID09PSAnZm9udCdcIiBpY29uPVwiZm9udF9kb3dubG9hZFwiIHRpdGxlPVwiRm9udCBGYW1pbHlcIiBbbWVudV09XCJ0cnVlXCI+XG4gICAgICA8YnV0dG9uIG1hdC1tZW51LWl0ZW0gKGNsaWNrZWQpPVwic2V0Rm9udE5hbWUoJ3NhbnMtc2VyaWYnKVwiIFtzdHlsZS5mb250RmFtaWx5XT1cIidzYW5zLXNlcmlmJ1wiPlNhbnMtc2VyaWY8L2J1dHRvbj5cbiAgICAgIDxidXR0b24gbWF0LW1lbnUtaXRlbSAoY2xpY2tlZCk9XCJzZXRGb250TmFtZSgnc2VyaWYnKVwiIFtzdHlsZS5mb250RmFtaWx5XT1cIidzZXJpZidcIj5TZXJpZjwvYnV0dG9uPlxuICAgICAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIChjbGlja2VkKT1cInNldEZvbnROYW1lKCdtb25vc3BhY2UnKVwiIFtzdHlsZS5mb250RmFtaWx5XT1cIidtb25vc3BhY2UnXCI+TW9ub3NwYWNlPC9idXR0b24+XG4gICAgPC9pZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbj5cbiAgICA8aWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24gKm5nSWY9XCJidXR0b24gPT09ICdmb250U2l6ZSdcIiBpY29uPVwiZm9ybWF0X3NpemVcIiB0aXRsZT1cIkZvbnQgc2l6ZVwiIFttZW51XT1cInRydWVcIj5cbiAgICAgIDxidXR0b24gbWF0LW1lbnUtaXRlbSAoY2xpY2tlZCk9XCJzZXRGb250U2l6ZSgnMTAnKVwiIFtzdHlsZS5mb250U2l6ZV09XCInMTBweCdcIj5TbWFsbDwvYnV0dG9uPlxuICAgICAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIChjbGlja2VkKT1cInNldEZvbnRTaXplKCcxMycpXCIgW3N0eWxlLmZvbnRTaXplXT1cIicxM3B4J1wiPlJlZ3VsYXI8L2J1dHRvbj5cbiAgICAgIDxidXR0b24gbWF0LW1lbnUtaXRlbSAoY2xpY2tlZCk9XCJzZXRGb250U2l6ZSgnMTgnKVwiIFtzdHlsZS5mb250U2l6ZV09XCInMThweCdcIj5MYXJnZTwvYnV0dG9uPlxuICAgICAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIChjbGlja2VkKT1cInNldEZvbnRTaXplKCczMicpXCIgW3N0eWxlLmZvbnRTaXplXT1cIiczMnB4J1wiPkh1Z2U8L2J1dHRvbj5cbiAgICA8L2lnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uPlxuICAgIDxpZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbiAqbmdJZj1cImJ1dHRvbiA9PT0gJ3RleHRDb2xvcidcIiBpY29uPVwiZm9ybWF0X2NvbG9yX3RleHRcIiB0aXRsZT1cIlRleHQgY29sb3JcIiBbbWVudV09XCJ0cnVlXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiY29sb3JzXCIgbWF0TWVudUNvbnRlbnQ+XG4gICAgICAgIDxzcGFuICpuZ0Zvcj1cImxldCBjb2xvciBvZiBjb2xvcnNcIiBbc3R5bGUuYmFja2dyb3VuZENvbG9yXT1cImNvbG9yXCIgW2NsYXNzLnNlcGFyYXRvcl09XCIhY29sb3JcIiAoY2xpY2tlZCk9XCJzZXRUZXh0Q29sb3IoY29sb3IpXCI+PC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgPC9pZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbj5cbiAgICA8aWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24gKm5nSWY9XCJidXR0b24gPT09ICdmaWxsQ29sb3InXCIgaWNvbj1cImZvcm1hdF9jb2xvcl9maWxsXCIgdGl0bGU9XCJGaWxsIGNvbG9yXCIgW21lbnVdPVwidHJ1ZVwiPlxuICAgICAgPGRpdiBjbGFzcz1cImNvbG9yc1wiIG1hdE1lbnVDb250ZW50PlxuICAgICAgICA8c3BhbiAqbmdGb3I9XCJsZXQgY29sb3Igb2YgY29sb3JzXCIgW3N0eWxlLmJhY2tncm91bmRDb2xvcl09XCJjb2xvclwiIFtjbGFzcy5zZXBhcmF0b3JdPVwiIWNvbG9yXCIgKGNsaWNrZWQpPVwic2V0QmFja2dyb3VuZENvbG9yKGNvbG9yKVwiPjwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgIDwvaWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24+XG4gICAgPGlnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uICpuZ0lmPVwiYnV0dG9uID09PSAncmVtb3ZlRm9ybWF0J1wiIGljb249XCJmb3JtYXRfY2xlYXJcIiB0aXRsZT1cIkNsZWFyIGZvcm1hdHRpbmdcIiAoY2xpY2tlZCk9XCJ0cmlnZ2VyQ29tbWFuZCgncmVtb3ZlRm9ybWF0JylcIj48L2lnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uPlxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJidXR0b24gPT09ICdhbGlnbidcIj5cbiAgICAgIDxpZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbiBpY29uPVwiZm9ybWF0X2FsaWduX2xlZnRcIiB0aXRsZT1cIkFsaWduIGxlZnRcIiAoY2xpY2tlZCk9XCJ0cmlnZ2VyQ29tbWFuZCgnanVzdGlmeUxlZnQnKVwiPjwvaWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24+XG4gICAgICA8aWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24gaWNvbj1cImZvcm1hdF9hbGlnbl9jZW50ZXJcIiB0aXRsZT1cIkFsaWduIGNlbnRlclwiIChjbGlja2VkKT1cInRyaWdnZXJDb21tYW5kKCdqdXN0aWZ5Q2VudGVyJylcIj48L2lnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uPlxuICAgICAgPGlnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uIGljb249XCJmb3JtYXRfYWxpZ25fcmlnaHRcIiB0aXRsZT1cIkFsaWduIHJpZ2h0XCIgKGNsaWNrZWQpPVwidHJpZ2dlckNvbW1hbmQoJ2p1c3RpZnlSaWdodCcpXCI+PC9pZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbj5cbiAgICAgIDxpZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbiBpY29uPVwiZm9ybWF0X2FsaWduX2p1c3RpZnlcIiB0aXRsZT1cIkp1c3RpZnlcIiAoY2xpY2tlZCk9XCJ0cmlnZ2VyQ29tbWFuZCgnanVzdGlmeUZ1bGwnKVwiPjwvaWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImJ1dHRvbiA9PT0gJ2luZGVudCdcIj5cbiAgICAgIDxpZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbiBpY29uPVwiZm9ybWF0X2luZGVudF9kZWNyZWFzZVwiIHRpdGxlPVwiT3V0ZGVudFwiIChjbGlja2VkKT1cInRyaWdnZXJDb21tYW5kKCdvdXRkZW50JylcIj48L2lnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uPlxuICAgICAgPGlnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uIGljb249XCJmb3JtYXRfaW5kZW50X2luY3JlYXNlXCIgdGl0bGU9XCJJbmRlbnRcIiAoY2xpY2tlZCk9XCJ0cmlnZ2VyQ29tbWFuZCgnaW5kZW50JylcIj48L2lnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uPlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxpZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbiAqbmdJZj1cImJ1dHRvbiA9PT0gJ3F1b3RlJ1wiIGljb249XCJmb3JtYXRfcXVvdGVcIiB0aXRsZT1cIkJsb2NrcXVvdGVcIiAoY2xpY2tlZCk9XCJ0cmlnZ2VyQ29tbWFuZCgnYmxvY2txdW90ZScpXCI+PC9pZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbj5cbiAgICA8aWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24gKm5nSWY9XCJidXR0b24gPT09ICd1bm9yZGVyZWRMaXN0J1wiIGljb249XCJmb3JtYXRfbGlzdF9idWxsZXRlZFwiIHRpdGxlPVwiVW5vcmRlcmVkIGxpc3RcIiAoY2xpY2tlZCk9XCJ0cmlnZ2VyQ29tbWFuZCgnaW5zZXJ0VW5vcmRlcmVkTGlzdCcpXCI+PC9pZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbj5cbiAgICA8aWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24gKm5nSWY9XCJidXR0b24gPT09ICdvcmRlcmVkTGlzdCdcIiBpY29uPVwiZm9ybWF0X2xpc3RfbnVtYmVyZWRcIiB0aXRsZT1cIk9yZGVyZWQgbGlzdFwiIChjbGlja2VkKT1cInRyaWdnZXJDb21tYW5kKCdpbnNlcnRPcmRlcmVkTGlzdCcpXCI+PC9pZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbj5cbiAgICA8aWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24gKm5nSWY9XCJidXR0b24gPT09ICd1bmRvJ1wiIGljb249XCJ1bmRvXCIgdGl0bGU9XCJVbmRvXCIgKGNsaWNrZWQpPVwidHJpZ2dlckNvbW1hbmQoJ3VuZG8nKVwiPjwvaWdldC1lZGl0b3ItdG9vbGJhci1idXR0b24+XG4gICAgPGlnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uICpuZ0lmPVwiYnV0dG9uID09PSAncmVkbydcIiBpY29uPVwicmVkb1wiIHRpdGxlPVwiUmVkb1wiIChjbGlja2VkKT1cInRyaWdnZXJDb21tYW5kKCdyZWRvJylcIj48L2lnZXQtZWRpdG9yLXRvb2xiYXItYnV0dG9uPlxuICAgIDxpZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbiAqbmdJZj1cImJ1dHRvbiA9PT0gJ2FuY2hvcidcIiBpY29uPVwiaW5zZXJ0X2xpbmtcIiB0aXRsZT1cIkluc2VydCBsaW5rXCIgKGNsaWNrZWQpPVwiaW5zZXJ0TGluaygpXCI+PC9pZ2V0LWVkaXRvci10b29sYmFyLWJ1dHRvbj5cbiAgPC9uZy1jb250YWluZXI+XG4iXX0=