@iget/editor
Version:
WYSIWYG Editor for Angular Material applications
1 lines • 54.9 kB
Source Map (JSON)
{"version":3,"file":"iget-editor.mjs","sources":["../../../src/app/iget-editor/common/default-iget-editor-config.ts","../../../src/app/iget-editor/common/utils/iget-editor.utils.ts","../../../src/app/iget-editor/common/services/message.service.ts","../../../src/app/iget-editor/common/services/command-executor.service.ts","../../../src/app/iget-editor/dialogs/link-dialog/link-dialog.component.ts","../../../src/app/iget-editor/dialogs/link-dialog/link-dialog.component.html","../../../src/app/iget-editor/iget-editor-toolbar/color-palette.ts","../../../src/app/iget-editor/iget-editor-toolbar-group/iget-editor-toolbar-group.component.ts","../../../src/app/iget-editor/iget-editor-toolbar-group/iget-editor-toolbar-group.component.html","../../../src/app/iget-editor/iget-editor-toolbar-button/iget-editor-toolbar-button.component.ts","../../../src/app/iget-editor/iget-editor-toolbar-button/iget-editor-toolbar-button.component.html","../../../src/app/iget-editor/iget-editor-toolbar/iget-editor-toolbar.component.ts","../../../src/app/iget-editor/iget-editor-toolbar/iget-editor-toolbar.component.html","../../../src/app/iget-editor/iget-editor-message/iget-editor-message.component.ts","../../../src/app/iget-editor/iget-editor-message/iget-editor-message.component.html","../../../src/app/iget-editor/iget-editor-grippie/iget-editor-grippie.component.ts","../../../src/app/iget-editor/iget-editor-grippie/iget-editor-grippie.component.html","../../../src/app/iget-editor/iget-editor.component.ts","../../../src/app/iget-editor/iget-editor.component.html","../../../src/app/iget-editor/iget-editor.module.ts","../../../src/app/iget-editor/validators/maxlength-validator.ts","../../../src/iget-editor.ts"],"sourcesContent":["/**\n * toolbar default configuration\n */\nimport {IgetEditorConfig} from '../iget-editor-config';\n\nexport const DefaultIgetEditorConfig: IgetEditorConfig = {\n editable: true,\n spellcheck: true,\n height: 'auto',\n minHeight: '0',\n width: 'auto',\n minWidth: '0',\n translate: 'yes',\n enableToolbar: true,\n showToolbar: true,\n placeholder: 'Enter text here...',\n toolbarPosition: 'after',\n resizable: true,\n toolbar: [\n ['bold', 'italic', 'underline', 'strikethrough'],\n ['font', 'fontSize', 'textColor', 'fillColor', 'removeFormat'],\n ['align'],\n ['indent', 'quote', 'unorderedList', 'orderedList'],\n ['undo', 'redo'],\n ['anchor']\n ]\n};\n","/**\n * enable or disable toolbar based on configuration\n *\n * @param value toolbar item\n * @param toolbar toolbar configuration object\n */\nexport function canEnableToolbarOptions(value: string, toolbar: any): boolean {\n if (value) {\n if (toolbar['length'] === 0) {\n return true;\n } else {\n const found = toolbar.filter(array => {\n return array.indexOf(value) !== -1;\n });\n\n return found.length ? true : false;\n }\n } else {\n return false;\n }\n}\n\n/**\n * return vertical if the element is the resizer property is set to basic\n *\n * @param resizer type of resizer, either basic or stack\n */\nexport function canResize(resizer: string): any {\n if (resizer === 'basic') {\n return 'vertical';\n }\n return false;\n}\n\n/**\n * save selection when the editor is focussed out\n */\nexport function saveSelection(): any {\n if (window.getSelection) {\n const sel = window.getSelection();\n if (sel.getRangeAt && sel.rangeCount) {\n return sel.getRangeAt(0);\n }\n } else if (document.getSelection && document.createRange) {\n return document.createRange();\n }\n return null;\n}\n\n/**\n * restore selection when the editor is focussed in\n *\n * @param range saved selection when the editor is focussed out\n */\nexport function restoreSelection(range): boolean {\n if (range) {\n if (window.getSelection) {\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n return true;\n } else if (document.getSelection && range.select) {\n range.select();\n return true;\n }\n } else {\n return false;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Subject, Observable } from 'rxjs';\n\n\n/** time in which the message has to be cleared */\nconst DURATION = 7000;\n\n@Injectable()\nexport class MessageService {\n /** variable to hold the user message */\n private message: Subject<string> = new Subject();\n\n constructor() { }\n\n /** returns the message sent by the editor */\n getMessage(): Observable<string> {\n return this.message.asObservable();\n }\n\n /**\n * sends message to the editor\n *\n * @param message message to be sent\n */\n sendMessage(message: string): void {\n this.message.next(message);\n this.clearMessageIn(DURATION);\n }\n\n /**\n * a short interval to clear message\n *\n * @param milliseconds time in seconds in which the message has to be cleared\n */\n private clearMessageIn(milliseconds: number): void {\n setTimeout(() => {\n this.message.next(undefined);\n }, milliseconds);\n }\n}\n","import { Injectable } from '@angular/core';\nimport * as Utils from '../utils/iget-editor.utils';\n\n@Injectable()\nexport class CommandExecutorService {\n /** saves the selection from the editor when focussed out */\n savedSelection: any = undefined;\n\n\n /**\n * executes command from the toolbar\n *\n * @param command command to be executed\n */\n execute(command: string): void {\n if (!this.savedSelection && command !== 'enableObjectResizing') {\n throw new Error('Range out of Editor');\n }\n\n if (command === 'enableObjectResizing') {\n document.execCommand('enableObjectResizing', true);\n }\n\n if (command === 'blockquote') {\n document.execCommand('formatBlock', false, 'blockquote');\n }\n\n if (command === 'removeBlockquote') {\n document.execCommand('formatBlock', false, 'div');\n }\n\n document.execCommand(command, false, null);\n }\n\n /**\n * inserts image in the editor\n *\n * @param imageURI url of the image to be inserted\n */\n insertImage(imageURI: string): void {\n if (this.savedSelection) {\n if (imageURI) {\n const restored = Utils.restoreSelection(this.savedSelection);\n if (restored) {\n const inserted = document.execCommand('insertImage', false, imageURI);\n if (!inserted) {\n throw new Error('Invalid URL');\n }\n }\n }\n } else {\n throw new Error('Range out of the editor');\n }\n }\n\n /**\n * inserts image in the editor\n *\n * @param videParams url of the image to be inserted\n */\n insertVideo(videParams: any): void {\n if (this.savedSelection) {\n if (videParams) {\n const restored = Utils.restoreSelection(this.savedSelection);\n if (restored) {\n if (this.isYoutubeLink(videParams.videoUrl)) {\n const youtubeURL = '<iframe width=\"' + videParams.width + '\" height=\"' + videParams.height + '\"'\n + 'src=\"' + videParams.videoUrl + '\"></iframe>';\n this.insertHtml(youtubeURL);\n } else if (this.checkTagSupportInBrowser('video')) {\n\n if (this.isValidURL(videParams.videoUrl)) {\n const videoSrc = '<video width=\"' + videParams.width + '\" height=\"' + videParams.height + '\"'\n + ' controls=\"true\"><source src=\"' + videParams.videoUrl + '\"></video>';\n this.insertHtml(videoSrc);\n } else {\n throw new Error('Invalid video URL');\n }\n\n } else {\n throw new Error('Unable to insert video');\n }\n }\n }\n } else {\n throw new Error('Range out of the editor');\n }\n }\n\n /**\n * checks the input url is a valid youtube URL or not\n *\n * @param url Youtue URL\n */\n private isYoutubeLink(url: string): boolean {\n const ytRegExp = /^(http(s)?:\\/\\/)?((w){3}.)?youtu(be|.be)?(\\.com)?\\/.+/;\n return ytRegExp.test(url);\n }\n\n /**\n * check whether the string is a valid url or not\n * @param url url\n */\n private isValidURL(url: string) {\n const urlRegExp = /(http|https):\\/\\/(\\w+:{0,1}\\w*)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%!\\-\\/]))?/;\n return urlRegExp.test(url);\n }\n\n /**\n * uploads image to the server\n *\n * @param file file that has to be uploaded\n * @param endPoint enpoint to which the image has to be uploaded\n */\n uploadImage(file: File, endPoint: string): any {\n // if (!endPoint) {\n // throw new Error('Image Endpoint isn`t provided or invalid');\n // }\n //\n // const formData: FormData = new FormData();\n //\n // if (file) {\n //\n // formData.append('file', file);\n //\n // const req = new HttpRequest('POST', endPoint, formData, {\n // reportProgress: true\n // });\n //\n // return this._http.request(req);\n //\n // } else {\n // throw new Error('Invalid Image');\n // }\n }\n\n /**\n * inserts link in the editor\n *\n * @param params parameters that holds the information for the link\n */\n createLink(params: any): void {\n if (this.savedSelection) {\n /**\n * check whether the saved selection contains a range or plain selection\n */\n if (params.urlNewTab) {\n const newUrl = '<a href=\"' + params.urlLink + '\" target=\"_blank\">' + params.urlText + '</a>';\n\n if (document.getSelection().type !== 'Range') {\n const restored = Utils.restoreSelection(this.savedSelection);\n if (restored) {\n this.insertHtml(newUrl);\n }\n } else {\n throw new Error('Only new links can be inserted. You cannot edit URL`s');\n }\n } else {\n const restored = Utils.restoreSelection(this.savedSelection);\n if (restored) {\n document.execCommand('createLink', false, params.urlLink);\n }\n }\n } else {\n throw new Error('Range out of the editor');\n }\n }\n\n /**\n * insert color either font or background\n *\n * @param color color to be inserted\n * @param where where the color has to be inserted either text/background\n */\n insertColor(color: string, where: string): void {\n if (this.savedSelection) {\n const restored = Utils.restoreSelection(this.savedSelection);\n if (restored && this.checkSelection()) {\n if (where === 'textColor') {\n document.execCommand('foreColor', false, color);\n } else {\n document.execCommand('hiliteColor', false, color);\n }\n }\n } else {\n throw new Error('Range out of the editor');\n }\n }\n\n /**\n * set font size for text\n *\n * @param fontSize font-size to be set\n */\n setFontSize(fontSize: string): void {\n if (this.savedSelection && this.checkSelection()) {\n const deletedValue = this.deleteAndGetElement();\n\n if (deletedValue) {\n const restored = Utils.restoreSelection(this.savedSelection);\n\n if (restored) {\n if (this.isNumeric(fontSize)) {\n const fontPx = '<span style=\"font-size: ' + fontSize + 'px;\">' + deletedValue + '</span>';\n this.insertHtml(fontPx);\n } else {\n const fontPx = '<span style=\"font-size: ' + fontSize + ';\">' + deletedValue + '</span>';\n this.insertHtml(fontPx);\n }\n }\n }\n } else {\n throw new Error('Range out of the editor');\n }\n }\n\n /**\n * set font name/family for text\n *\n * @param fontName font-family to be set\n */\n setFontName(fontName: string): void {\n if (this.savedSelection && this.checkSelection()) {\n const deletedValue = this.deleteAndGetElement();\n\n if (deletedValue) {\n const restored = Utils.restoreSelection(this.savedSelection);\n\n if (restored) {\n if (this.isNumeric(fontName)) {\n const fontFamily = '<span style=\"font-family: ' + fontName + 'px;\">' + deletedValue + '</span>';\n this.insertHtml(fontFamily);\n } else {\n const fontFamily = '<span style=\"font-family: ' + fontName + ';\">' + deletedValue + '</span>';\n this.insertHtml(fontFamily);\n }\n }\n }\n } else {\n throw new Error('Range out of the editor');\n }\n }\n\n /** insert HTML */\n private insertHtml(html: string): void {\n const isHTMLInserted = document.execCommand('insertHTML', false, html);\n\n if (!isHTMLInserted) {\n throw new Error('Unable to perform the operation');\n }\n }\n\n /**\n * check whether the value is a number or string\n * if number return true\n * else return false\n */\n private isNumeric(value: any): boolean {\n return /^-{0,1}\\d+$/.test(value);\n }\n\n /** delete the text at selected range and return the value */\n private deleteAndGetElement(): any {\n let slectedText;\n\n if (this.savedSelection) {\n slectedText = this.savedSelection.toString();\n this.savedSelection.deleteContents();\n return slectedText;\n }\n\n return false;\n }\n\n /** check any slection is made or not */\n private checkSelection(): any {\n const slectedText = this.savedSelection.toString();\n\n if (slectedText.length === 0) {\n throw new Error('No Selection Made');\n }\n\n return true;\n }\n\n /**\n * check tag is supported by browser or not\n *\n * @param tag HTML tag\n */\n private checkTagSupportInBrowser(tag: string): boolean {\n return !(document.createElement(tag) instanceof HTMLUnknownElement);\n }\n\n}\n","import {Component, Inject, OnInit} from '@angular/core';\nimport {FormBuilder, FormGroup, Validators} from '@angular/forms';\nimport {MAT_DIALOG_DATA} from '@angular/material/dialog';\n\nexport interface LinkDialogData {\n selection: any;\n}\n\n@Component({\n selector: 'iget-editor-link-dialog',\n templateUrl: './link-dialog.component.html',\n styleUrls: ['./link-dialog.component.scss'],\n providers: []\n})\nexport class LinkDialogComponent implements OnInit {\n form: FormGroup;\n\n constructor(\n private formBuilder: FormBuilder,\n @Inject(MAT_DIALOG_DATA) public data: LinkDialogData\n ) {}\n\n ngOnInit(): void {\n this.form = this.buildForm();\n\n if (this.data.selection) {\n this.form.patchValue({\n label: this.data.selection.toString()\n });\n }\n }\n\n private buildForm() {\n return this.formBuilder.group({\n 'label': [null, [Validators.required]],\n 'url': [null, [Validators.required]],\n });\n }\n}\n","<h1 mat-dialog-title>Edit Link</h1>\n<div mat-dialog-content [formGroup]=\"form\">\n <mat-form-field floatLabel=\"always\">\n <input matInput placeholder=\"Label\" formControlName=\"label\">\n </mat-form-field>\n <mat-form-field floatLabel=\"always\">\n <input matInput placeholder=\"Web address or email\" formControlName=\"url\" cdkFocusInitial>\n </mat-form-field>\n</div>\n<div mat-dialog-actions>\n <button mat-button [mat-dialog-close]>Cancel</button>\n <button mat-button [disabled]=\"form.invalid\" [mat-dialog-close]=\"form.value\">OK</button>\n</div>\n","export const COLOR_PALETTE = [\n '#000000', '#444444', '#666666', '#999999', '#cccccc', '#eeeeee', '#f3f3f3', '#ffffff',\n null,\n '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#0000ff', '#9900ff', '#ff00ff',\n null,\n '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#cfe2f3', '#d9d2e9', '#ead1dc',\n '#ea9999', '#f9cb9c', '#ffe599', '#b6d7a8', '#a2c4c9', '#9fc5e8', '#b4a7d6', '#d5a6bd',\n '#e06666', '#f6b26b', '#ffd966', '#93c47d', '#76a5af', '#6fa8dc', '#8e7cc3', '#c27ba0',\n '#cc0000', '#e69138', '#f1c232', '#6aa84f', '#45818e', '#3d85c6', '#674ea7', '#a64d79',\n '#990000', '#b45f06', '#bf9000', '#38761d', '#134f5c', '#0b5394', '#351c75', '#741b47',\n '#660000', '#783f04', '#7f6000', '#274e13', '#0c343d', '#073763', '#20124d', '#4c1130'\n];\n","import {Component} from '@angular/core';\n\n@Component({\n selector: 'iget-editor-toolbar-group',\n templateUrl: './iget-editor-toolbar-group.component.html',\n styleUrls: ['./iget-editor-toolbar-group.component.scss'],\n providers: []\n})\n\nexport class IgetEditorToolbarGroupComponent {\n}\n","<ng-content select=\"ng-container, iget-editor-toolbar-button, mat-menu\"></ng-content>\n","import {Component, Input, Output, EventEmitter} from '@angular/core';\n\n@Component({\n selector: 'iget-editor-toolbar-button',\n templateUrl: './iget-editor-toolbar-button.component.html',\n styleUrls: ['./iget-editor-toolbar-button.component.scss'],\n providers: []\n})\n\nexport class IgetEditorToolbarButtonComponent {\n @Input() icon: string;\n @Input() title: string;\n @Input() menu = false;\n\n @Output() clicked: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();\n\n handleClick($event: MouseEvent) {\n this.clicked.emit($event);\n\n $event.stopPropagation();\n }\n}\n","<button mat-icon-button [title]=\"title\" (click)=\"handleClick($event)\" *ngIf=\"!menu\">\n <mat-icon>{{ icon }}</mat-icon>\n</button>\n<ng-container *ngIf=\"menu\">\n <button mat-icon-button [title]=\"title\" (click)=\"handleClick($event)\" *ngIf=\"menu\" [matMenuTriggerFor]=\"dropdown\">\n <mat-icon>{{ icon }}</mat-icon>\n </button>\n <mat-menu #dropdown=\"matMenu\">\n <ng-content select=\"[mat-menu-item],[matMenuContent]\"></ng-content>\n </mat-menu>\n</ng-container>\n","import { Component, Input, Output, EventEmitter, OnInit, ViewChild } from '@angular/core';\nimport { CommandExecutorService } from '../common/services/command-executor.service';\nimport { MessageService } from '../common/services/message.service';\nimport * as Utils from '../common/utils/iget-editor.utils';\nimport {LinkDialogComponent} from '../dialogs/link-dialog/link-dialog.component';\nimport {MatDialog} from '@angular/material/dialog';\nimport {ToolbarConfig} from '../iget-editor-config';\nimport {COLOR_PALETTE} from './color-palette';\n\n@Component({\n selector: 'iget-editor-toolbar',\n templateUrl: './iget-editor-toolbar.component.html',\n styleUrls: ['./iget-editor-toolbar.component.scss'],\n providers: []\n})\n\nexport class IgetEditorToolbarComponent {\n /** font family name */\n fontName = '';\n /** font size */\n fontSize = '';\n\n /**\n * Editor configuration\n */\n @Input() config: ToolbarConfig;\n /**\n * Emits an event when a toolbar button is clicked\n */\n @Output() execute: EventEmitter<string> = new EventEmitter<string>();\n colors = COLOR_PALETTE;\n\n constructor(private _messageService: MessageService,\n private _commandExecutorService: CommandExecutorService,\n private dialog: MatDialog\n ) {}\n\n /**\n * enable or diable toolbar based on configuration\n *\n * @param value name of the toolbar buttons\n */\n canEnableToolbarOptions(value): boolean {\n return Utils.canEnableToolbarOptions(value, this.config['toolbar']);\n }\n\n /**\n * triggers command from the toolbar to be executed and emits an event\n *\n * @param command name of the command to be executed\n */\n triggerCommand(command: string): void {\n this.execute.emit(command);\n }\n\n /**\n * inserts link in the editor\n */\n insertLink(): void {\n const linkDialogRef = this.dialog.open(LinkDialogComponent, {\n data: {\n selection: this._commandExecutorService.savedSelection\n }\n });\n\n linkDialogRef.afterClosed().subscribe((data) => {\n if (data) {\n let urlLink = data.url;\n const emailPattern = new RegExp([\n '^(([^<>()\\\\[\\\\]\\\\.,;:\\\\s@\\\\\"]+(\\\\.[^<>()\\\\[\\\\]\\\\.,;:\\\\s@\\\\\"]+)*)',\n '|(\\\\\".+\\\\\"))@(([^<>()[\\\\]\\\\.,;:\\\\s@\\\\\"]+\\\\.)+[^<>()[\\\\]\\\\.,;:\\\\s',\n '@\\\\\"]{2,})$'\n ].join(''));\n\n if (emailPattern.exec(urlLink)) {\n urlLink = `mailto:${urlLink}`;\n }\n\n this._commandExecutorService.createLink({\n urlLink,\n urlText: data.label,\n });\n }\n });\n }\n\n /** insert text/background color */\n setTextColor(color: string): void {\n this.insertColor(color, 'textColor');\n }\n\n /** insert text/background color */\n setBackgroundColor(color: string): void {\n this.insertColor(color, 'backgroundColor');\n }\n\n /** insert text/background color */\n insertColor(color: string, where: string): void {\n try {\n this._commandExecutorService.insertColor(color, where);\n } catch (error) {\n this._messageService.sendMessage(error.message);\n }\n }\n\n /** set font size */\n setFontSize(fontSize: string): void {\n try {\n this._commandExecutorService.setFontSize(fontSize);\n } catch (error) {\n this._messageService.sendMessage(error.message);\n }\n }\n\n /** set font Name/family */\n setFontName(fontName: string): void {\n try {\n this._commandExecutorService.setFontName(fontName);\n } catch (error) {\n this._messageService.sendMessage(error.message);\n }\n }\n}\n","<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","import { Component } from '@angular/core';\n\nimport { MessageService } from '../common/services/message.service';\n\n@Component({\n selector: 'iget-editor-message',\n templateUrl: './iget-editor-message.component.html',\n styleUrls: ['./iget-editor-message.component.scss']\n})\n\nexport class IgetEditorMessageComponent {\n /** property that holds the message to be displayed on the editor */\n ngxMessage = undefined;\n\n /**\n * @param _messageService service to send message to the editor\n */\n constructor(private _messageService: MessageService) {\n this._messageService.getMessage().subscribe((message: string) => this.ngxMessage = message);\n }\n\n /**\n * clears editor message\n */\n clearMessage(): void {\n this.ngxMessage = undefined;\n }\n}\n","<div class=\"iget-editor-message\" *ngIf=\"ngxMessage\" (dblclick)=\"clearMessage()\">\n {{ ngxMessage }}\n</div>\n","import {Component, EventEmitter, HostListener, Output} from '@angular/core';\n\n@Component({\n selector: 'iget-editor-grippie',\n templateUrl: './iget-editor-grippie.component.html',\n styleUrls: ['./iget-editor-grippie.component.scss']\n})\n\nexport class IgetEditorGrippieComponent {\n /** height of the editor */\n height: number;\n /** previous value befor resizing the editor */\n oldY = 0;\n /** set to true on mousedown event */\n grabber = false;\n\n @Output() resized: EventEmitter<number> = new EventEmitter<number>();\n\n /**\n * Constructor\n */\n constructor() { }\n\n /**\n *\n * @param event Mouseevent\n *\n * Update the height of the editor when the grabber is dragged\n */\n @HostListener('document:mousemove', ['$event']) onMouseMove(event: MouseEvent) {\n if (!this.grabber) {\n return;\n }\n\n this.resized.emit(event.clientY - this.oldY);\n this.oldY = event.clientY;\n }\n\n /**\n *\n * @param event Mouseevent\n *\n * set the grabber to false on mouse up action\n */\n @HostListener('document:mouseup', ['$event']) onMouseUp(event: MouseEvent) {\n this.grabber = false;\n }\n\n @HostListener('mousedown', ['$event']) onResize(event: MouseEvent, resizer?: Function) {\n this.grabber = true;\n this.oldY = event.clientY;\n event.preventDefault();\n }\n\n}\n","<div class=\"iget-editor-grippie\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"isolation:isolate\" viewBox=\"651.6 235 26 5\"\n width=\"26\" height=\"5\">\n <g id=\"sprites\">\n <path d=\" M 651.6 235 L 653.6 235 L 653.6 237 L 651.6 237 M 654.6 238 L 656.6 238 L 656.6 240 L 654.6 240 M 660.6 238 L 662.6 238 L 662.6 240 L 660.6 240 M 666.6 238 L 668.6 238 L 668.6 240 L 666.6 240 M 672.6 238 L 674.6 238 L 674.6 240 L 672.6 240 M 657.6 235 L 659.6 235 L 659.6 237 L 657.6 237 M 663.6 235 L 665.6 235 L 665.6 237 L 663.6 237 M 669.6 235 L 671.6 235 L 671.6 237 L 669.6 237 M 675.6 235 L 677.6 235 L 677.6 237 L 675.6 237\"\n fill=\"rgb(147,153,159)\" />\n </g>\n </svg>\n</div>\n","import {\n Component, OnInit, Input, Output, ViewChild,\n EventEmitter, Renderer2, forwardRef, OnChanges\n} from '@angular/core';\nimport { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';\n\nimport { CommandExecutorService } from './common/services/command-executor.service';\nimport { MessageService } from './common/services/message.service';\n\nimport { DefaultIgetEditorConfig } from './common/default-iget-editor-config';\nimport * as Utils from './common/utils/iget-editor.utils';\nimport {DomSanitizer, SafeHtml} from '@angular/platform-browser';\nimport {IgetEditorCustomConfig} from './iget-editor-custom-config';\n\n@Component({\n selector: 'iget-editor',\n templateUrl: './iget-editor.component.html',\n styleUrls: ['./iget-editor.component.scss'],\n providers: [{\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => IgetEditorComponent),\n multi: true\n }]\n})\n\nexport class IgetEditorComponent implements OnInit, OnChanges, ControlValueAccessor {\n @Input() config: IgetEditorCustomConfig;\n\n /** emits `blured` event when focused out from the textarea */\n @Output() blured: EventEmitter<string> = new EventEmitter<string>();\n /** emits `focused` event when focused in to the textarea */\n @Output() focused: EventEmitter<string> = new EventEmitter<string>();\n\n @ViewChild('igetEditorTextArea') textArea: any;\n @ViewChild('igetEditorWrapper') wrapper: any;\n\n Utils: any = Utils;\n value: SafeHtml;\n showPlaceholder = true;\n\n private onChange: (value: string) => void;\n private onTouched: () => void;\n\n /**\n * @param sanitizer Dom Sanitizer\n * @param _messageService service to send message to the editor message component\n * @param _commandExecutor executes command from the toolbar\n * @param _renderer access and manipulate the dom element\n */\n constructor(\n private sanitizer: DomSanitizer,\n private _messageService: MessageService,\n private _commandExecutor: CommandExecutorService,\n private _renderer: Renderer2) { }\n\n /**\n * events\n */\n onTextAreaFocus(): void {\n this.focused.emit('focus');\n }\n\n /** focus the text area when the editor is focussed */\n onEditorFocus() {\n this.textArea.nativeElement.focus();\n }\n\n /**\n * Executed from the contenteditable section while the input property changes\n */\n onContentChange($event: Event): void {\n const innerHtml = ($event.target as HTMLElement).innerHTML;\n if (typeof this.onChange === 'function') {\n this.onChange(innerHtml);\n this.togglePlaceholder(innerHtml);\n }\n }\n\n onTextAreaBlur(): void {\n /** save selection if focussed out */\n this._commandExecutor.savedSelection = Utils.saveSelection();\n\n if (typeof this.onTouched === 'function') {\n this.onTouched();\n }\n this.blured.emit('blur');\n }\n\n /**\n * resizing text area\n *\n * @param offsetY vertical height of the editable portion of the editor\n */\n resizeTextArea(offsetY: number): void {\n const oldHeight = parseInt(getComputedStyle(this.textArea.nativeElement).height, 10);\n\n this.textArea.nativeElement.style.height = (oldHeight + offsetY) + 'px';\n }\n\n /**\n * editor actions, i.e., executes command from toolbar\n *\n * @param commandName name of the command to be executed\n */\n executeCommand(commandName: string): void {\n try {\n this._commandExecutor.execute(commandName);\n } catch (error) {\n this._messageService.sendMessage(error.message);\n }\n }\n\n /**\n * Write a new value to the element.\n *\n * @param value value to be executed when there is a change in contenteditable\n */\n writeValue(value: any): void {\n this.togglePlaceholder(value);\n\n if (value === null || value === undefined || value === '' || value === '<br>') {\n value = null;\n }\n\n this.value = this.sanitizer.bypassSecurityTrustHtml(value);\n }\n\n /**\n * Set the function to be called\n * when the control receives a change event.\n *\n * @param fn a function\n */\n registerOnChange(fn: any): void {\n this.onChange = fn;\n }\n\n /**\n * Set the function to be called\n * when the control receives a touch event.\n *\n * @param fn a function\n */\n registerOnTouched(fn: any): void {\n this.onTouched = fn;\n }\n\n /**\n * toggles placeholder based on input string\n *\n * @param value A HTML string from the editor\n */\n togglePlaceholder(value: any): void {\n if (!value || value === '<br>' || value === '') {\n this.showPlaceholder = true;\n } else {\n this.showPlaceholder = false;\n }\n }\n\n ngOnInit() {\n // this.height = this.height || this.textArea.nativeElement.offsetHeight;\n\n this.executeCommand('enableObjectResizing');\n }\n\n ngOnChanges(): void {\n this.config = Object.assign({}, DefaultIgetEditorConfig, this.config);\n }\n\n}\n","<div class=\"iget-editor\"\n tabindex=\"0\"\n [style.width]=\"config.width\"\n [style.minWidth]=\"config.minWidth\"\n [class.toolbar-before]=\"config.toolbarPosition === 'before'\"\n (focus)=\"onEditorFocus()\">\n\n <!-- text area -->\n <div class=\"iget-editor-wrapper\" #igetEditorWrapper>\n <div class=\"iget-editor-textarea\" [class.show-placeholder]=\"showPlaceholder\" [attr.contenteditable]=\"config.editable\" (input)=\"onContentChange($event)\"\n [attr.translate]=\"config['translate']\" [attr.spellcheck]=\"config.spellcheck\" [style.height]=\"config.height\"\n [style.minHeight]=\"config['minHeight']\" [style.resize]=\"'none'\" (focus)=\"onTextAreaFocus()\"\n (blur)=\"onTextAreaBlur()\" [innerHTML]=\"value\" #igetEditorTextArea></div>\n\n <span class=\"iget-editor-placeholder\">{{ config.placeholder }}</span>\n </div>\n\n <iget-editor-toolbar\n [config]=\"config.toolbar\"\n (execute)=\"executeCommand($event)\">\n </iget-editor-toolbar>\n\n <iget-editor-message></iget-editor-message>\n <iget-editor-grippie *ngIf=\"config.resizable\" (resized)=\"resizeTextArea($event)\"></iget-editor-grippie>\n</div>\n","import {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {FormsModule, ReactiveFormsModule} from '@angular/forms';\nimport {MatDialogModule} from '@angular/material/dialog';\nimport {MatIconModule} from '@angular/material/icon';\nimport {MatButtonModule} from '@angular/material/button';\nimport {MatMenuModule} from '@angular/material/menu';\nimport {IgetEditorComponent} from './iget-editor.component';\nimport {MatInputModule} from '@angular/material/input';\nimport {IgetEditorGrippieComponent} from './iget-editor-grippie/iget-editor-grippie.component';\nimport {IgetEditorMessageComponent} from './iget-editor-message/iget-editor-message.component';\nimport {IgetEditorToolbarComponent} from './iget-editor-toolbar/iget-editor-toolbar.component';\nimport {IgetEditorToolbarGroupComponent} from './iget-editor-toolbar-group/iget-editor-toolbar-group.component';\nimport {IgetEditorToolbarButtonComponent} from './iget-editor-toolbar-button/iget-editor-toolbar-button.component';\nimport {LinkDialogComponent} from './dialogs/link-dialog/link-dialog.component';\nimport {CommandExecutorService} from './common/services/command-executor.service';\nimport {MessageService} from './common/services/message.service';\n\n@NgModule({\n imports: [\n CommonModule,\n FormsModule,\n ReactiveFormsModule,\n MatDialogModule,\n MatIconModule,\n MatButtonModule,\n MatMenuModule,\n MatInputModule,\n ],\n declarations: [\n IgetEditorComponent,\n IgetEditorGrippieComponent,\n IgetEditorMessageComponent,\n IgetEditorToolbarComponent,\n IgetEditorToolbarGroupComponent,\n IgetEditorToolbarButtonComponent,\n /** Dialogs */\n LinkDialogComponent,\n ],\n exports: [IgetEditorComponent],\n providers: [CommandExecutorService, MessageService]\n})\n\nexport class IgetEditorModule { }\n","import { AbstractControl } from '@angular/forms';\n\ninterface IMaxLengthValidatorOptions {\n excludeLineBreaks?: boolean;\n concatWhiteSpaces?: boolean;\n excludeWhiteSpaces?: boolean;\n}\n\nexport function MaxLengthValidator(maxlength: number, options?: IMaxLengthValidatorOptions) {\n return (control: AbstractControl): { [key: string]: any } | null => {\n const parsedDocument = new DOMParser().parseFromString(control.value, 'text/html');\n let innerText = parsedDocument.body.innerText || '';\n\n // replace all linebreaks\n if (options.excludeLineBreaks) {\n innerText = innerText.replace(/(\\r\\n\\t|\\n|\\r\\t)/gm, '');\n }\n\n // concat multiple whitespaces into a single whitespace\n if (options.concatWhiteSpaces) {\n innerText = innerText.replace(/(\\s\\s+)/gm, ' ');\n }\n\n // remove all whitespaces\n if (options.excludeWhiteSpaces) {\n innerText = innerText.replace(/(\\s)/gm, '');\n }\n\n if (innerText.length > maxlength) {\n return {\n IgetEditor: {\n allowedLength: maxlength,\n textLength: innerText.length\n }\n };\n }\n return null;\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["Utils.restoreSelection","Utils.canEnableToolbarOptions","Utils.saveSelection"],"mappings":";;;;;;;;;;;;;;;;;;;;AAKO,MAAM,uBAAuB,GAAqB;IACvD,QAAQ,EAAE,IAAI;IACd,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,MAAM;IACd,SAAS,EAAE,GAAG;IACd,KAAK,EAAE,MAAM;IACb,QAAQ,EAAE,GAAG;IACb,SAAS,EAAE,KAAK;IAChB,aAAa,EAAE,IAAI;IACnB,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,oBAAoB;IACjC,eAAe,EAAE,OAAO;IACxB,SAAS,EAAE,IAAI;IACf,OAAO,EAAE;QACP,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,CAAC;QAChD,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,CAAC;QAC9D,CAAC,OAAO,CAAC;QACT,CAAC,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE,aAAa,CAAC;QACnD,CAAC,MAAM,EAAE,MAAM,CAAC;QAChB,CAAC,QAAQ,CAAC;KACX;CACF;;AC1BD;;;;;;SAMgB,uBAAuB,CAAC,KAAa,EAAE,OAAY;IACjE,IAAI,KAAK,EAAE;QACT,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;YAC3B,OAAO,IAAI,CAAC;SACb;aAAM;YACL,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK;gBAChC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;aACpC,CAAC,CAAC;YAEH,OAAO,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,KAAK,CAAC;SACpC;KACF;SAAM;QACL,OAAO,KAAK,CAAC;KACd;AACH,CAAC;AAED;;;;;SAKgB,SAAS,CAAC,OAAe;IACvC,IAAI,OAAO,KAAK,OAAO,EAAE;QACvB,OAAO,UAAU,CAAC;KACnB;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;SAGgB,aAAa;IAC3B,IAAI,MAAM,CAAC,YAAY,EAAE;QACvB,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;QAClC,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,EAAE;YACpC,OAAO,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;SAC1B;KACF;SAAM,IAAI,QAAQ,CAAC,YAAY,IAAI,QAAQ,CAAC,WAAW,EAAE;QACxD,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC;KAC/B;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;SAKgB,gBAAgB,CAAC,KAAK;IACpC,IAAI,KAAK,EAAE;QACT,IAAI,MAAM,CAAC,YAAY,EAAE;YACvB,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;YAClC,GAAG,CAAC,eAAe,EAAE,CAAC;YACtB,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,IAAI,CAAC;SACb;aAAM,IAAI,QAAQ,CAAC,YAAY,IAAI,KAAK,CAAC,MAAM,EAAE;YAChD,KAAK,CAAC,MAAM,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;SACb;KACF;SAAM;QACL,OAAO,KAAK,CAAC;KACd;AACH;;;;;;;;;;AChEA;AACA,MAAM,QAAQ,GAAG,IAAI,CAAC;MAGT,cAAc;IAIzB;;QAFQ,YAAO,GAAoB,IAAI,OAAO,EAAE,CAAC;KAEhC;;IAGjB,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;KACpC;;;;;;IAOD,WAAW,CAAC,OAAe;QACzB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3B,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;KAC/B;;;;;;IAOO,cAAc,CAAC,YAAoB;QACzC,UAAU,CAAC;YACT,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;SAC9B,EAAE,YAAY,CAAC,CAAC;KAClB;;2GA9BU,cAAc;+GAAd,cAAc;2FAAd,cAAc;kBAD1B,UAAU;;;MCHE,sBAAsB;IADnC;;QAGE,mBAAc,GAAQ,SAAS,CAAC;KAgSjC;;;;;;IAxRC,OAAO,CAAC,OAAe;QACrB,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,OAAO,KAAK,sBAAsB,EAAE;YAC9D,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;SACxC;QAED,IAAI,OAAO,KAAK,sBAAsB,EAAE;YACtC,QAAQ,CAAC,WAAW,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;SACpD;QAED,IAAI,OAAO,KAAK,YAAY,EAAE;YAC5B,QAAQ,CAAC,WAAW,CAAC,aAAa,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;SAC1D;QAED,IAAI,OAAO,KAAK,kBAAkB,EAAE;YAClC,QAAQ,CAAC,WAAW,CAAC,aAAa,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;SACnD;QAED,QAAQ,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;KAC5C;;;;;;IAOD,WAAW,CAAC,QAAgB;QAC1B,IAAI,IAAI,CAAC,cAAc,EAAE;YACvB,IAAI,QAAQ,EAAE;gBACZ,MAAM,QAAQ,GAAGA,gBAAsB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC7D,IAAI,QAAQ,EAAE;oBACZ,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,aAAa,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;oBACtE,IAAI,CAAC,QAAQ,EAAE;wBACb,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;qBAChC;iBACF;aACF;SACF;aAAM;YACL,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;SAC5C;KACF;;;;;;IAOD,WAAW,CAAC,UAAe;QACzB,IAAI,IAAI,CAAC,cAAc,EAAE;YACvB,IAAI,UAAU,EAAE;gBACd,MAAM,QAAQ,GAAGA,gBAAsB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC7D,IAAI,QAAQ,EAAE;oBACZ,IAAI,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;wBAC3C,MAAM,UAAU,GAAG,iBAAiB,GAAG,UAAU,CAAC,KAAK,GAAG,YAAY,GAAG,UAAU,CAAC,MAAM,GAAG,GAAG;8BAC5F,OAAO,GAAG,UAAU,CAAC,QAAQ,GAAG,aAAa,CAAC;wBAClD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;qBAC7B;yBAAM,IAAI,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC,EAAE;wBAEjD,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;4BACxC,MAAM,QAAQ,GAAG,gBAAgB,GAAG,UAAU,CAAC,KAAK,GAAG,YAAY,GAAG,UAAU,CAAC,MAAM,GAAG,GAAG;kCACzF,gCAAgC,GAAG,UAAU,CAAC,QAAQ,GAAG,YAAY,CAAC;4BAC1E,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;yBAC3B;6BAAM;4BACL,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;yBACtC;qBAEF;yBAAM;wBACL,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;qBAC3C;iBACF;aACF;SACF;aAAM;YACL,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;SAC5C;KACF;;;;;;IAOO,aAAa,CAAC,GAAW;QAC/B,MAAM,QAAQ,GAAG,uDAAuD,CAAC;QACzE,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;KAC3B;;;;;IAMO,UAAU,CAAC,GAAW;QAC5B,MAAM,SAAS,GAAG,6EAA6E,CAAC;QAChG,OAAO,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;KAC5B;;;;;;;IAQD,WAAW,CAAC,IAAU,EAAE,QAAgB;;;;;;;;;;;;;;;;;;;;KAoBvC;;;;;;IAOD,UAAU,CAAC,MAAW;QACpB,IAAI,IAAI,CAAC,cAAc,EAAE;;;;YAIvB,IAAI,MAAM,CAAC,SAAS,EAAE;gBACpB,MAAM,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC,OAAO,GAAG,oBAAoB,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC;gBAE7F,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE;oBAC5C,MAAM,QAAQ,GAAGA,gBAAsB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;oBAC7D,IAAI,QAAQ,EAAE;wBACZ,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;qBACzB;iBACF;qBAAM;oBACL,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;iBAC1E;aACF;iBAAM;gBACL,MAAM,QAAQ,GAAGA,gBAAsB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC7D,IAAI,QAAQ,EAAE;oBACZ,QAAQ,CAAC,WAAW,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;iBAC3D;aACF;SACF;aAAM;YACL,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;SAC5C;KACF;;;;;;;IAQD,WAAW,CAAC,KAAa,EAAE,KAAa;QACtC,IAAI,IAAI,CAAC,cAAc,EAAE;YACvB,MAAM,QAAQ,GAAGA,gBAAsB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC7D,IAAI,QAAQ,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE;gBACrC,IAAI,KAAK,KAAK,WAAW,EAAE;oBACzB,QAAQ,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;iBACjD;qBAAM;oBACL,QAAQ,CAAC,WAAW,CAAC,aAAa,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;iBACnD;aACF;SACF;aAAM;YACL,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;SAC5C;KACF;;;;;;IAOD,WAAW,CAAC,QAAgB;QAC1B,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE;YAChD,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAEhD,IAAI,YAAY,EAAE;gBAChB,MAAM,QAAQ,GAAGA,gBAAsB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAE7D,IAAI,QAAQ,EAAE;oBACZ,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;wBAC5B,MAAM,MAAM,GAAG,0BAA0B,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,CAAC;wBAC1F,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;qBACzB;yBAAM;wBACL,MAAM,MAAM,GAAG,0BAA0B,GAAG,QAAQ,GAAG,KAAK,GAAG,YAAY,GAAG,SAAS,CAAC;wBACxF,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;qBACzB;iBACF;aACF;SACF;aAAM;YACL,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;SAC5C;KACF;;;;;;IAOD,WAAW,CAAC,QAAgB;QAC1B,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE;YAChD,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAEhD,IAAI,YAAY,EAAE;gBAChB,MAAM,QAAQ,GAAGA,gBAAsB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAE7D,IAAI,QAAQ,EAAE;oBACZ,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;wBAC5B,MAAM,UAAU,GAAG,4BAA4B,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,CAAC;wBAChG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;qBAC7B;yBAAM;wBACL,MAAM,UAAU,GAAG,4BAA4B,GAAG,QAAQ,GAAG,KAAK,GAAG,YAAY,GAAG,SAAS,CAAC;wBAC9F,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;qBAC7B;iBACF;aACF;SACF;aAAM;YACL,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;SAC5C;KACF;;IAGO,UAAU,CAAC,IAAY;QAC7B,MAAM,cAAc,GAAG,QAAQ,CAAC,WAAW,CAAC,YAAY,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAEvE,IAAI,CAAC,cAAc,EAAE;YACnB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;SACpD;KACF;;;;;;IAOO,SAAS,CAAC,KAAU;QAC1B,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;KAClC;;IAGO,mBAAmB;QACzB,IAAI,WAAW,CAAC;QAEhB,IAAI,IAAI,CAAC,cAAc,EAAE;YACvB,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC;YAC7C,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC;YACrC,OAAO,WAAW,CAAC;SACpB;QAED,OAAO,KAAK,CAAC;KACd;;IAGO,cAAc;QACpB,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC;QAEnD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE;YAC5B,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;SACtC;QAED,OAAO,IAAI,CAAC;KACb;;;;;;IAOO,wBAAwB,CAAC,GAAW;QAC1C,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,kBAAkB,CAAC,CAAC;KACrE;;mHAhSU,sBAAsB;uHAAtB,sBAAsB;2FAAtB,sBAAsB;kBADlC,UAAU;;;MCWE,mBAAmB;IAG9B,YACU,WAAwB,EACA,IAAoB;QAD5C,gBAAW,GAAX,WAAW,CAAa;QACA,SAAI,GAAJ,IAAI,CAAgB;KAClD;IAEJ,QAAQ;QACN,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAE7B,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YACvB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;gBACnB,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE;aACtC,CAAC,CAAC;SACJ;KACF;IAEO,SAAS;QACf,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;YAC5B,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YACtC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;SACrC,CAAC,CAAC;KACJ;;gHAvBU,mBAAmB,6CAKpB,eAAe;oGALd,mBAAmB,kDAFnB,EAAE,0BCZf,gkBAaA;2FDCa,mBAAmB;kBAN/B,SAAS;+BACE,yBAAyB,aAGxB,EAAE;;;8BAOV,MAAM;+BAAC,eAAe;;;;AEnBpB,MAAM,aAAa,GAAG;IAC3B,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS;IACtF,IAAI;IACJ,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS;IACtF,IAAI;IACJ,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS;IACtF,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS;IACtF,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS;IACtF,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS;IACtF,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS;IACtF,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS;CACvF;;MCFY,+BAA+B;;4HAA/B,+BAA+B;gHAA/B,+BAA+B,oDAH/B,EAAE,0BCNf,2FACA;2FDQa,+BAA+B;kBAP3C,SAAS;+BACE,2BAA2B,aAG1B,EAAE;;;MEGF,gCAAgC;IAP7C;QAUW,SAAI,GAAG,KAAK,CAAC;QAEZ,YAAO,GAA6B,IAAI,YAAY,EAAc,CAAC;KAO9E;IALC,WAAW,CAAC,MAAkB;QAC5B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE1B,MAAM,CAAC,eAAe,EAAE,CAAC;KAC1B;;6HAXU,gCAAgC;iHAAhC,gCAAgC,8IAHhC,EAAE,0BCNf,4eAWA;2FDFa,gCAAgC;kBAP5C,SAAS;+BACE,4BAA4B,aAG3B,EAAE;8BAIJ,IAAI;sBAAZ,KAAK;gBACG,KAAK;sBAAb,KAAK;gBACG,IAAI;sBAAZ,KAAK;gBAEI,OAAO;sBAAhB,MAAM;;;MEEI,0BAA0B;IAgBrC,YAAoB,eAA+B,EACzC,uBAA+C,EAC/C,MAAiB;QAFP,oBAAe,GAAf,eAAe,CAAgB;QACzC,4BAAuB,GAAvB,uBAAuB,CAAwB;QAC/C,WAAM,GAAN,MAAM,CAAW;;QAhB3B,aAAQ,GAAG,EAAE,CAAC;;QAEd,aAAQ,GAAG,EAAE,CAAC;;;;QASJ,YAAO,GAAyB,IAAI,YAAY,EAAU,CAAC;QACrE,WAAM,GAAG,aAAa,CAAC;KAKnB;;;;;;IAOJ,uBAAuB,CAAC,KAAK;QAC3B,OAAOC,uBAA6B,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;KACrE;;;;;;IAOD,cAAc,CAAC,OAAe;QAC5B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;KAC5B;;;;IAKD,UAAU;QACR,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE;YAC1D,IAAI,EAAE;gBACJ,SAAS,EAAE,IAAI,CAAC,uBAAuB,CAAC,cAAc;aACvD;SACF,CAAC,CAAC;QAEH,aAAa,CAAC,WAAW,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI;YACzC,IAAI,IAAI,EAAE;gBACR,IAAI,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC;gBACvB,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC;oBAC9B,kEAAkE;oBAClE,kEAAkE;oBAClE,aAAa;iBACd,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;gBAEZ,IAAI,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;oBAC9B,OAAO,GAAG,UAAU,OAAO,EAAE,CAAC;iBAC/B;gBAED,IAAI,CAAC,uBAAuB,CAAC,UAAU,CAAC;oBACtC,OAAO;oBACP,OAAO,EAAE,IAAI,CAAC,KAAK;iBACpB,CAAC,CAAC;aACJ;SACF,CAAC,CAAC;KACJ;;IAGD,YAAY,CAAC,KAAa;QACxB,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;KACtC;;IAGD,kBAAkB,CAAC,KAAa;QAC9B,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;KAC5C;;IAGD,WAAW,CAAC,KAAa,EAAE,KAAa;QACtC,IAAI;YACF,IAAI,CAAC,uBAAuB,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;SACxD;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;SACjD;KACF;;IAGD,WAAW,CAAC,QAAgB;QAC1B,IAAI;YACF,IAAI,CAAC,uBAAuB,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;SACpD;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;SACjD;KACF;;IAGD,WAAW,CAAC,QAAgB;QAC1B,IAAI;YACF,IAAI,CAAC,uBAAuB,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;SACpD;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;SACjD;KACF;;uHAzGU,0BAA0B;2GAA1B,0BAA0B,6GAH1B,EAAE,0BCbf,g7JA6CA;2FD7Ba,0BAA0B;kBAPtC,SAAS;+BACE,qBAAqB,aAGpB,EAAE;4JAYJ,MAAM;sBAAd,KAAK;gBAII,OAAO;sBAAhB,MAAM;;;MEnBI,0BAA0B;;;;IAOrC,YAAoB,eAA+B;QAA/B,oBAAe,GAAf,eAAe,CAAgB;;QALnD,eAAU,GAAG,SAAS,CAAC;QAMrB,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,CAAC,SAAS,CAAC,CAAC,OAAe,KAAK,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,