UNPKG

ngx-editor-imageupload

Version:

WYSIWYG Editor for Angular Applications

529 lines 37 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, Input, Output, ViewChild, EventEmitter, Renderer2, forwardRef } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { CommandExecutorService } from './common/services/command-executor.service'; import { MessageService } from './common/services/message.service'; import { ngxEditorConfig } from './common/ngx-editor.defaults'; import * as Utils from './common/utils/ngx-editor.utils'; var NgxEditorComponent = /** @class */ (function () { /** * @param _messageService service to send message to the editor message component * @param _commandExecutor executes command from the toolbar * @param _renderer access and manipulate the dom element */ function NgxEditorComponent(_messageService, _commandExecutor, _renderer) { this._messageService = _messageService; this._commandExecutor = _commandExecutor; this._renderer = _renderer; /** * The editor can be resized vertically. * * `basic` resizer enables the html5 reszier. Check here https://www.w3schools.com/cssref/css3_pr_resize.asp * * `stack` resizer enable a resizer that looks like as if in https://stackoverflow.com */ this.resizer = 'stack'; /** * The config property is a JSON object * * All avaibale inputs inputs can be provided in the configuration as JSON * inputs provided directly are considered as top priority */ this.config = ngxEditorConfig; /** * emits `blur` event when focused out from the textarea */ this.blur = new EventEmitter(); /** * emits `focus` event when focused in to the textarea */ this.focus = new EventEmitter(); /** * emits `uploadImage` event when image is selected */ this.uploadImage = new EventEmitter(); this.Utils = Utils; } /** * events */ /** * events * @return {?} */ NgxEditorComponent.prototype.onTextAreaFocus = /** * events * @return {?} */ function () { this.focus.emit('focus'); }; /** focus the text area when the editor is focussed */ /** * focus the text area when the editor is focussed * @return {?} */ NgxEditorComponent.prototype.onEditorFocus = /** * focus the text area when the editor is focussed * @return {?} */ function () { this.textArea.nativeElement.focus(); }; /** * Executed from the contenteditable section while the input property changes * @param html html string from contenteditable */ /** * Executed from the contenteditable section while the input property changes * @param {?} innerHTML * @return {?} */ NgxEditorComponent.prototype.onContentChange = /** * Executed from the contenteditable section while the input property changes * @param {?} innerHTML * @return {?} */ function (innerHTML) { if (typeof this.onChange === 'function') { this.onChange(innerHTML); this.togglePlaceholder(innerHTML); } }; /** * @return {?} */ NgxEditorComponent.prototype.onTextAreaBlur = /** * @return {?} */ function () { /** save selection if focussed out */ this._commandExecutor.savedSelection = Utils.saveSelection(); if (typeof this.onTouched === 'function') { this.onTouched(); } this.blur.emit('blur'); }; /** * Executed when the image from the disc is selected * @param image uploaded file object */ /** * Executed when the image from the disc is selected * @param {?} image uploaded file object * @return {?} */ NgxEditorComponent.prototype.onUploadImage = /** * Executed when the image from the disc is selected * @param {?} image uploaded file object * @return {?} */ function (image) { this.uploadImage.emit(image); }; /** * resizing text area * * @param offsetY vertical height of the eidtable portion of the editor */ /** * resizing text area * * @param {?} offsetY vertical height of the eidtable portion of the editor * @return {?} */ NgxEditorComponent.prototype.resizeTextArea = /** * resizing text area * * @param {?} offsetY vertical height of the eidtable portion of the editor * @return {?} */ function (offsetY) { /** @type {?} */ var newHeight = parseInt(this.height, 10); newHeight += offsetY; this.height = newHeight + 'px'; this.textArea.nativeElement.style.height = this.height; }; /** * editor actions, i.e., executes command from toolbar * * @param commandName name of the command to be executed */ /** * editor actions, i.e., executes command from toolbar * * @param {?} commandName name of the command to be executed * @return {?} */ NgxEditorComponent.prototype.executeCommand = /** * editor actions, i.e., executes command from toolbar * * @param {?} commandName name of the command to be executed * @return {?} */ function (commandName) { try { this._commandExecutor.execute(commandName); } catch (error) { this._messageService.sendMessage(error.message); } }; /** * Write a new value to the element. * * @param value value to be executed when there is a change in contenteditable */ /** * Write a new value to the element. * * @param {?} value value to be executed when there is a change in contenteditable * @return {?} */ NgxEditorComponent.prototype.writeValue = /** * Write a new value to the element. * * @param {?} value value to be executed when there is a change in contenteditable * @return {?} */ function (value) { this.togglePlaceholder(value); if (value === null || value === undefined || value === '' || value === '<br>') { value = null; } this.refreshView(value); }; /** * Set the function to be called * when the control receives a change event. * * @param fn a function */ /** * Set the function to be called * when the control receives a change event. * * @param {?} fn a function * @return {?} */ NgxEditorComponent.prototype.registerOnChange = /** * Set the function to be called * when the control receives a change event. * * @param {?} fn a function * @return {?} */ function (fn) { this.onChange = fn; }; /** * Set the function to be called * when the control receives a touch event. * * @param fn a function */ /** * Set the function to be called * when the control receives a touch event. * * @param {?} fn a function * @return {?} */ NgxEditorComponent.prototype.registerOnTouched = /** * Set the function to be called * when the control receives a touch event. * * @param {?} fn a function * @return {?} */ function (fn) { this.onTouched = fn; }; /** * refresh view/HTML of the editor * * @param value html string from the editor */ /** * refresh view/HTML of the editor * * @param {?} value html string from the editor * @return {?} */ NgxEditorComponent.prototype.refreshView = /** * refresh view/HTML of the editor * * @param {?} value html string from the editor * @return {?} */ function (value) { /** @type {?} */ var normalizedValue = value === null ? '' : value; this._renderer.setProperty(this.textArea.nativeElement, 'innerHTML', normalizedValue); }; /** * toggles placeholder based on input string * * @param value A HTML string from the editor */ /** * toggles placeholder based on input string * * @param {?} value A HTML string from the editor * @return {?} */ NgxEditorComponent.prototype.togglePlaceholder = /** * toggles placeholder based on input string * * @param {?} value A HTML string from the editor * @return {?} */ function (value) { if (!value || value === '<br>' || value === '') { this._renderer.addClass(this.ngxWrapper.nativeElement, 'show-placeholder'); } else { this._renderer.removeClass(this.ngxWrapper.nativeElement, 'show-placeholder'); } }; /** * returns a json containing input params */ /** * returns a json containing input params * @return {?} */ NgxEditorComponent.prototype.getCollectiveParams = /** * returns a json containing input params * @return {?} */ function () { return { editable: this.editable, spellcheck: this.spellcheck, placeholder: this.placeholder, translate: this.translate, height: this.height, minHeight: this.minHeight, width: this.width, minWidth: this.minWidth, enableToolbar: this.enableToolbar, showToolbar: this.showToolbar, imageEndPoint: this.imageEndPoint, toolbar: this.toolbar }; }; /** * @return {?} */ NgxEditorComponent.prototype.ngOnInit = /** * @return {?} */ function () { /** * set configuartion */ this.config = this.Utils.getEditorConfiguration(this.config, ngxEditorConfig, this.getCollectiveParams()); this.height = this.height || this.textArea.nativeElement.offsetHeight; this.executeCommand('enableObjectResizing'); }; /** * @param {?} changes * @return {?} */ NgxEditorComponent.prototype.ngOnChanges = /** * @param {?} changes * @return {?} */ function (changes) { if (this.uploadedImagePath && this.uploadedImagePath !== this.prevUploadedImagePath) { this._commandExecutor.insertImage(this.uploadedImagePath); this.prevUploadedImagePath = this.uploadedImagePath; } }; NgxEditorComponent.decorators = [ { type: Component, args: [{ selector: 'app-ngx-editor', template: "<div class=\"ngx-editor\" id=\"ngxEditor\" [style.width]=\"config['width']\" [style.minWidth]=\"config['minWidth']\" tabindex=\"0\"\r\n (focus)=\"onEditorFocus()\">\r\n\r\n <app-ngx-editor-toolbar [config]=\"config\" (execute)=\"executeCommand($event)\" (uploadImage)=\"onUploadImage($event)\"></app-ngx-editor-toolbar>\r\n\r\n <!-- text area -->\r\n <div class=\"ngx-wrapper\" #ngxWrapper>\r\n <div class=\"ngx-editor-textarea\" [attr.contenteditable]=\"config['editable']\" (input)=\"onContentChange($event.target.innerHTML)\"\r\n [attr.translate]=\"config['translate']\" [attr.spellcheck]=\"config['spellcheck']\" [attr.uploadedImagePath]=\"uploadedImagePath\" [style.height]=\"config['height']\"\r\n [style.minHeight]=\"config['minHeight']\" [style.resize]=\"Utils?.canResize(resizer)\" (focus)=\"onTextAreaFocus()\"\r\n (blur)=\"onTextAreaBlur()\" #ngxTextArea></div>\r\n\r\n <span class=\"ngx-editor-placeholder\">{{ placeholder || config['placeholder'] }}</span>\r\n </div>\r\n\r\n <app-ngx-editor-message></app-ngx-editor-message>\r\n <app-ngx-grippie *ngIf=\"resizer === 'stack'\"></app-ngx-grippie>\r\n\r\n</div>\r\n", providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((/** * @return {?} */ function () { return NgxEditorComponent; })), multi: true }], styles: [".ngx-editor{position:relative}.ngx-editor ::ng-deep [contenteditable=true]:empty:before{content:attr(placeholder);display:block;color:#868e96;opacity:1}.ngx-editor .ngx-wrapper{position:relative}.ngx-editor .ngx-wrapper .ngx-editor-textarea{min-height:5rem;padding:.5rem .8rem 1rem;border:1px solid #ddd;background-color:transparent;overflow-x:hidden;overflow-y:auto;z-index:2;position:relative}.ngx-editor .ngx-wrapper .ngx-editor-textarea.focus,.ngx-editor .ngx-wrapper .ngx-editor-textarea:focus{outline:0}.ngx-editor .ngx-wrapper .ngx-editor-textarea ::ng-deep blockquote{margin-left:1rem;border-left:.2em solid #dfe2e5;padding-left:.5rem}.ngx-editor .ngx-wrapper ::ng-deep p{margin-bottom:0}.ngx-editor .ngx-wrapper .ngx-editor-placeholder{display:none;position:absolute;top:0;padding:.5rem .8rem 1rem .9rem;z-index:1;color:#6c757d;opacity:1}.ngx-editor .ngx-wrapper.show-placeholder .ngx-editor-placeholder{display:block}"] }] } ]; /** @nocollapse */ NgxEditorComponent.ctorParameters = function () { return [ { type: MessageService }, { type: CommandExecutorService }, { type: Renderer2 } ]; }; NgxEditorComponent.propDecorators = { editable: [{ type: Input }], spellcheck: [{ type: Input }], placeholder: [{ type: Input }], translate: [{ type: Input }], height: [{ type: Input }], minHeight: [{ type: Input }], width: [{ type: Input }], minWidth: [{ type: Input }], toolbar: [{ type: Input }], resizer: [{ type: Input }], config: [{ type: Input }], uploadedImagePath: [{ type: Input }], showToolbar: [{ type: Input }], enableToolbar: [{ type: Input }], imageEndPoint: [{ type: Input }], blur: [{ type: Output }], focus: [{ type: Output }], uploadImage: [{ type: Output }], textArea: [{ type: ViewChild, args: ['ngxTextArea',] }], ngxWrapper: [{ type: ViewChild, args: ['ngxWrapper',] }] }; return NgxEditorComponent; }()); export { NgxEditorComponent }; if (false) { /** * Specifies weather the textarea to be editable or not * @type {?} */ NgxEditorComponent.prototype.editable; /** * The spellcheck property specifies whether the element is to have its spelling and grammar checked or not. * @type {?} */ NgxEditorComponent.prototype.spellcheck; /** * Placeholder for the textArea * @type {?} */ NgxEditorComponent.prototype.placeholder; /** * The translate property specifies whether the content of an element should be translated or not. * * Check https://www.w3schools.com/tags/att_global_translate.asp for more information and browser support * @type {?} */ NgxEditorComponent.prototype.translate; /** * Sets height of the editor * @type {?} */ NgxEditorComponent.prototype.height; /** * Sets minimum height for the editor * @type {?} */ NgxEditorComponent.prototype.minHeight; /** * Sets Width of the editor * @type {?} */ NgxEditorComponent.prototype.width; /** * Sets minimum width of the editor * @type {?} */ NgxEditorComponent.prototype.minWidth; /** * Toolbar accepts an array which specifies the options to be enabled for the toolbar * * Check ngxEditorConfig for toolbar configuration * * Passing an empty array will enable all toolbar * @type {?} */ NgxEditorComponent.prototype.toolbar; /** * The editor can be resized vertically. * * `basic` resizer enables the html5 reszier. Check here https://www.w3schools.com/cssref/css3_pr_resize.asp * * `stack` resizer enable a resizer that looks like as if in https://stackoverflow.com * @type {?} */ NgxEditorComponent.prototype.resizer; /** * The config property is a JSON object * * All avaibale inputs inputs can be provided in the configuration as JSON * inputs provided directly are considered as top priority * @type {?} */ NgxEditorComponent.prototype.config; /** @type {?} */ NgxEditorComponent.prototype.uploadedImagePath; /** * Weather to show or hide toolbar * @type {?} */ NgxEditorComponent.prototype.showToolbar; /** * Weather to enable or disable the toolbar * @type {?} */ NgxEditorComponent.prototype.enableToolbar; /** * Endpoint for which the image to be uploaded * @type {?} */ NgxEditorComponent.prototype.imageEndPoint; /** * emits `blur` event when focused out from the textarea * @type {?} */ NgxEditorComponent.prototype.blur; /** * emits `focus` event when focused in to the textarea * @type {?} */ NgxEditorComponent.prototype.focus; /** * emits `uploadImage` event when image is selected * @type {?} */ NgxEditorComponent.prototype.uploadImage; /** @type {?} */ NgxEditorComponent.prototype.textArea; /** @type {?} */ NgxEditorComponent.prototype.ngxWrapper; /** @type {?} */ NgxEditorComponent.prototype.Utils; /** * @type {?} * @private */ NgxEditorComponent.prototype.onChange; /** * @type {?} * @private */ NgxEditorComponent.prototype.onTouched; /** @type {?} */ NgxEditorComponent.prototype.prevUploadedImagePath; /** * @type {?} * @private */ NgxEditorComponent.prototype._messageService; /** * @type {?} * @private */ NgxEditorComponent.prototype._commandExecutor; /** * @type {?} * @private */ NgxEditorComponent.prototype._renderer; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWVkaXRvci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtZWRpdG9yLWltYWdldXBsb2FkLyIsInNvdXJjZXMiOlsiYXBwL25neC1lZGl0b3Ivbmd4LWVkaXRvci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQVUsS0FBSyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQzNDLFlBQVksRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUNwQyxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsaUJBQWlCLEVBQXdCLE1BQU0sZ0JBQWdCLENBQUM7QUFFekUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFDcEYsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRW5FLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMvRCxPQUFPLEtBQUssS0FBSyxNQUFNLGlDQUFpQyxDQUFDO0FBRXpEO0lBK0VFOzs7O09BSUc7SUFDSCw0QkFDVSxlQUErQixFQUMvQixnQkFBd0MsRUFDeEMsU0FBb0I7UUFGcEIsb0JBQWUsR0FBZixlQUFlLENBQWdCO1FBQy9CLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBd0I7UUFDeEMsY0FBUyxHQUFULFNBQVMsQ0FBVzs7Ozs7Ozs7UUF4Q3JCLFlBQU8sR0FBRyxPQUFPLENBQUM7Ozs7Ozs7UUFPbEIsV0FBTSxHQUFHLGVBQWUsQ0FBQzs7OztRQVV4QixTQUFJLEdBQXlCLElBQUksWUFBWSxFQUFVLENBQUM7Ozs7UUFFeEQsVUFBSyxHQUF5QixJQUFJLFlBQVksRUFBVSxDQUFDOzs7O1FBRXpELGdCQUFXLEdBQW1DLElBQUksWUFBWSxFQUFvQixDQUFDO1FBSzdGLFVBQUssR0FBUSxLQUFLLENBQUM7SUFjZSxDQUFDO0lBRW5DOztPQUVHOzs7OztJQUNILDRDQUFlOzs7O0lBQWY7UUFDRSxJ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TTsyQkFFTixTQUFTLFNBQUMsYUFBYTs2QkFDdkIsU0FBUyxTQUFDLFlBQVk7O0lBa0x6Qix5QkFBQztDQUFBLEFBelBELElBeVBDO1NBOU9ZLGtCQUFrQjs7Ozs7O0lBRTdCLHNDQUEyQjs7Ozs7SUFFM0Isd0NBQTZCOzs7OztJQUU3Qix5Q0FBNkI7Ozs7Ozs7SUFNN0IsdUNBQTJCOzs7OztJQUUzQixvQ0FBd0I7Ozs7O0lBRXhCLHVDQUEyQjs7Ozs7SUFFM0IsbUNBQXVCOzs7OztJQUV2QixzQ0FBMEI7Ozs7Ozs7OztJQVExQixxQ0FBeUI7Ozs7Ozs7OztJQVF6QixxQ0FBMkI7Ozs7Ozs7O0lBTzNCLG9DQUFrQzs7SUFDbEMsK0NBQW1DOzs7OztJQUVuQyx5Q0FBOEI7Ozs7O0lBRTlCLDJDQUFnQzs7Ozs7SUFFaEMsMkNBQStCOzs7OztJQUcvQixrQ0FBa0U7Ozs7O0lBRWxFLG1DQUFtRTs7Ozs7SUFFbkUseUNBQTZGOztJQUU3RixzQ0FBd0M7O0lBQ3hDLHdDQUF5Qzs7SUFFekMsbUNBQW1COzs7OztJQUVuQixzQ0FBMEM7Ozs7O0lBQzFDLHVDQUE4Qjs7SUFDOUIsbURBQThCOzs7OztJQVE1Qiw2Q0FBdUM7Ozs7O0lBQ3ZDLDhDQUFnRDs7Ozs7SUFDaEQsdUNBQTRCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBDb21wb25lbnQsIE9uSW5pdCwgSW5wdXQsIE91dHB1dCwgVmlld0NoaWxkLFxyXG4gIEV2ZW50RW1pdHRlciwgUmVuZGVyZXIyLCBmb3J3YXJkUmVmLCBTaW1wbGVDaGFuZ2VzLCBPbkNoYW5nZXNcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgTkdfVkFMVUVfQUNDRVNTT1IsIENvbnRyb2xWYWx1ZUFjY2Vzc29yIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5cclxuaW1wb3J0IHsgQ29tbWFuZEV4ZWN1dG9yU2VydmljZSB9IGZyb20gJy4vY29tbW9uL3NlcnZpY2VzL2NvbW1hbmQtZXhlY3V0b3Iuc2VydmljZSc7XHJcbmltcG9ydCB7IE1lc3NhZ2VTZXJ2aWNlIH0gZnJvbSAnLi9jb21tb24vc2VydmljZXMvbWVzc2FnZS5zZXJ2aWNlJztcclxuXHJcbmltcG9ydCB7IG5neEVkaXRvckNvbmZpZyB9IGZyb20gJy4vY29tbW9uL25neC1lZGl0b3IuZGVmYXVsdHMnO1xyXG5pbXBvcnQgKiBhcyBVdGlscyBmcm9tICcuL2NvbW1vbi91dGlscy9uZ3gtZWRpdG9yLnV0aWxzJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnYXBwLW5neC1lZGl0b3InLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9uZ3gtZWRpdG9yLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9uZ3gtZWRpdG9yLmNvbXBvbmVudC5zY3NzJ10sXHJcbiAgcHJvdmlkZXJzOiBbe1xyXG4gICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXHJcbiAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBOZ3hFZGl0b3JDb21wb25lbnQpLFxyXG4gICAgbXVsdGk6IHRydWVcclxuICB9XVxyXG59KVxyXG5cclxuZXhwb3J0IGNsYXNzIE5neEVkaXRvckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE9uQ2hhbmdlcyB7XHJcbiAgLyoqIFNwZWNpZmllcyB3ZWF0aGVyIHRoZSB0ZXh0YXJlYSB0byBiZSBlZGl0YWJsZSBvciBub3QgKi9cclxuICBASW5wdXQoKSBlZGl0YWJsZTogYm9vbGVhbjtcclxuICAvKiogVGhlIHNwZWxsY2hlY2sgcHJvcGVydHkgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgdG8gaGF2ZSBpdHMgc3BlbGxpbmcgYW5kIGdyYW1tYXIgY2hlY2tlZCBvciBub3QuICovXHJcbiAgQElucHV0KCkgc3BlbGxjaGVjazogYm9vbGVhbjtcclxuICAvKiogUGxhY2Vob2xkZXIgZm9yIHRoZSB0ZXh0QXJlYSAqL1xyXG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyOiBzdHJpbmc7XHJcbiAgLyoqXHJcbiAgICogVGhlIHRyYW5zbGF0ZSBwcm9wZXJ0eSBzcGVjaWZpZXMgd2hldGhlciB0aGUgY29udGVudCBvZiBhbiBlbGVtZW50IHNob3VsZCBiZSB0cmFuc2xhdGVkIG9yIG5vdC5cclxuICAgKlxyXG4gICAqIENoZWNrIGh0dHBzOi8vd3d3Lnczc2Nob29scy5jb20vdGFncy9hdHRfZ2xvYmFsX3RyYW5zbGF0ZS5hc3AgZm9yIG1vcmUgaW5mb3JtYXRpb24gYW5kIGJyb3dzZXIgc3VwcG9ydFxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHRyYW5zbGF0ZTogc3RyaW5nO1xyXG4gIC8qKiBTZXRzIGhlaWdodCBvZiB0aGUgZWRpdG9yICovXHJcbiAgQElucHV0KCkgaGVpZ2h0OiBzdHJpbmc7XHJcbiAgLyoqIFNldHMgbWluaW11bSBoZWlnaHQgZm9yIHRoZSBlZGl0b3IgKi9cclxuICBASW5wdXQoKSBtaW5IZWlnaHQ6IHN0cmluZztcclxuICAvKiogU2V0cyBXaWR0aCBvZiB0aGUgZWRpdG9yICovXHJcbiAgQElucHV0KCkgd2lkdGg6IHN0cmluZztcclxuICAvKiogU2V0cyBtaW5pbXVtIHdpZHRoIG9mIHRoZSBlZGl0b3IgKi9cclxuICBASW5wdXQoKSBtaW5XaWR0aDogc3RyaW5nO1xyXG4gIC8qKlxyXG4gICAqIFRvb2xiYXIgYWNjZXB0cyBhbiBhcnJheSB3aGljaCBzcGVjaWZpZXMgdGhlIG9wdGlvbnMgdG8gYmUgZW5hYmxlZCBmb3IgdGhlIHRvb2xiYXJcclxuICAgKlxyXG4gICAqIENoZWNrIG5neEVkaXRvckNvbmZpZyBmb3IgdG9vbGJhciBjb25maWd1cmF0aW9uXHJcbiAgICpcclxuICAgKiBQYXNzaW5nIGFuIGVtcHR5IGFycmF5IHdpbGwgZW5hYmxlIGFsbCB0b29sYmFyXHJcbiAgICovXHJcbiAgQElucHV0KCkgdG9vbGJhcjogT2JqZWN0O1xyXG4gIC8qKlxyXG4gICAqIFRoZSBlZGl0b3IgY2FuIGJlIHJlc2l6ZWQgdmVydGljYWxseS5cclxuICAgKlxyXG4gICAqIGBiYXNpY2AgcmVzaXplciBlbmFibGVzIHRoZSBodG1sNSByZXN6aWVyLiBDaGVjayBoZXJlIGh0dHBzOi8vd3d3Lnczc2Nob29scy5jb20vY3NzcmVmL2NzczNfcHJfcmVzaXplLmFzcFxyXG4gICAqXHJcbiAgICogYHN0YWNrYCByZXNpemVyIGVuYWJsZSBhIHJlc2l6ZXIgdGhhdCBsb29rcyBsaWtlIGFzIGlmIGluIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb21cclxuICAgKi9cclxuICBASW5wdXQoKSByZXNpemVyID0gJ3N0YWNrJztcclxuICAvKipcclxuICAgKiBUaGUgY29uZmlnIHByb3BlcnR5IGlzIGEgSlNPTiBvYmplY3RcclxuICAgKlxyXG4gICAqIEFsbCBhdmFpYmFsZSBpbnB1dHMgaW5wdXRzIGNhbiBiZSBwcm92aWRlZCBpbiB0aGUgY29uZmlndXJhdGlvbiBhcyBKU09OXHJcbiAgICogaW5wdXRzIHByb3ZpZGVkIGRpcmVjdGx5IGFyZSBjb25zaWRlcmVkIGFzIHRvcCBwcmlvcml0eVxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIGNvbmZpZyA9IG5neEVkaXRvckNvbmZpZztcclxuICBASW5wdXQoKSB1cGxvYWRlZEltYWdlUGF0aDogc3RyaW5nO1xyXG4gIC8qKiBXZWF0aGVyIHRvIHNob3cgb3IgaGlkZSB0b29sYmFyICovXHJcbiAgQElucHV0KCkgc2hvd1Rvb2xiYXI6IGJvb2xlYW47XHJcbiAgLyoqIFdlYXRoZXIgdG8gZW5hYmxlIG9yIGRpc2FibGUgdGhlIHRvb2xiYXIgKi9cclxuICBASW5wdXQoKSBlbmFibGVUb29sYmFyOiBib29sZWFuO1xyXG4gIC8qKiBFbmRwb2ludCBmb3Igd2hpY2ggdGhlIGltYWdlIHRvIGJlIHVwbG9hZGVkICovXHJcbiAgQElucHV0KCkgaW1hZ2VFbmRQb2ludDogc3RyaW5nO1xyXG5cclxuICAvKiogZW1pdHMgYGJsdXJgIGV2ZW50IHdoZW4gZm9jdXNlZCBvdXQgZnJvbSB0aGUgdGV4dGFyZWEgKi9cclxuICBAT3V0cHV0KCkgYmx1cjogRXZlbnRFbWl0dGVyPHN0cmluZz4gPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuICAvKiogZW1pdHMgYGZvY3VzYCBldmVudCB3aGVuIGZvY3VzZWQgaW4gdG8gdGhlIHRleHRhcmVhICovXHJcbiAgQE91dHB1dCgpIGZvY3VzOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xyXG4gIC8qKiBlbWl0cyBgdXBsb2FkSW1hZ2VgIGV2ZW50IHdoZW4gaW1hZ2UgaXMgc2VsZWN0ZWQgKi9cclxuICBAT3V0cHV0KCkgdXBsb2FkSW1hZ2U6IEV2ZW50RW1pdHRlcjxIVE1MSW5wdXRFbGVtZW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8SFRNTElucHV0RWxlbWVudD4oKTtcclxuXHJcbiAgQFZpZXdDaGlsZCgnbmd4VGV4dEFyZWEnKSB0ZXh0QXJlYTogYW55O1xyXG4gIEBWaWV3Q2hpbGQoJ25neFdyYXBwZXInKSBuZ3hXcmFwcGVyOiBhbnk7XHJcblxyXG4gIFV0aWxzOiBhbnkgPSBVdGlscztcclxuXHJcbiAgcHJpdmF0ZSBvbkNoYW5nZTogKHZhbHVlOiBzdHJpbmcpID0+IHZvaWQ7XHJcbiAgcHJpdmF0ZSBvblRvdWNoZWQ6ICgpID0+IHZvaWQ7XHJcbiAgcHJldlVwbG9hZGVkSW1hZ2VQYXRoOiBzdHJpbmc7XHJcblxyXG4gIC8qKlxyXG4gICAqIEBwYXJhbSBfbWVzc2FnZVNlcnZpY2Ugc2VydmljZSB0byBzZW5kIG1lc3NhZ2UgdG8gdGhlIGVkaXRvciBtZXNzYWdlIGNvbXBvbmVudFxyXG4gICAqIEBwYXJhbSBfY29tbWFuZEV4ZWN1dG9yIGV4ZWN1dGVzIGNvbW1hbmQgZnJvbSB0aGUgdG9vbGJhclxyXG4gICAqIEBwYXJhbSBfcmVuZGVyZXIgYWNjZXNzIGFuZCBtYW5pcHVsYXRlIHRoZSBkb20gZWxlbWVudFxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBfbWVzc2FnZVNlcnZpY2U6IE1lc3NhZ2VTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBfY29tbWFuZEV4ZWN1dG9yOiBDb21tYW5kRXhlY3V0b3JTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBfcmVuZGVyZXI6IFJlbmRlcmVyMikgeyB9XHJcblxyXG4gIC8qKlxyXG4gICAqIGV2ZW50c1xyXG4gICAqL1xyXG4gIG9uVGV4dEFyZWFGb2N1cygpOiB2b2lkIHtcclxuICAgIHRoaXMuZm9jdXMuZW1pdCgnZm9jdXMnKTtcclxuICB9XHJcblxyXG4gIC8qKiBmb2N1cyB0aGUgdGV4dCBhcmVhIHdoZW4gdGhlIGVkaXRvciBpcyBmb2N1c3NlZCAqL1xyXG4gIG9uRWRpdG9yRm9jdXMoKSB7XHJcbiAgICB0aGlzLnRleHRBcmVhLm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEV4ZWN1dGVkIGZyb20gdGhlIGNvbnRlbnRlZGl0YWJsZSBzZWN0aW9uIHdoaWxlIHRoZSBpbnB1dCBwcm9wZXJ0eSBjaGFuZ2VzXHJcbiAgICogQHBhcmFtIGh0bWwgaHRtbCBzdHJpbmcgZnJvbSBjb250ZW50ZWRpdGFibGVcclxuICAgKi9cclxuICBvbkNvbnRlbnRDaGFuZ2UoaW5uZXJIVE1MOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICh0eXBlb2YgdGhpcy5vbkNoYW5nZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICB0aGlzLm9uQ2hhbmdlKGlubmVySFRNTCk7XHJcbiAgICAgIHRoaXMudG9nZ2xlUGxhY2Vob2xkZXIoaW5uZXJIVE1MKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG9uVGV4dEFyZWFCbHVyKCk6IHZvaWQge1xyXG4gICAgLyoqIHNhdmUgc2VsZWN0aW9uIGlmIGZvY3Vzc2VkIG91dCAqL1xyXG4gICAgdGhpcy5fY29tbWFuZEV4ZWN1dG9yLnNhdmVkU2VsZWN0aW9uID0gVXRpbHMuc2F2ZVNlbGVjdGlvbigpO1xyXG5cclxuICAgIGlmICh0eXBlb2YgdGhpcy5vblRvdWNoZWQgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgdGhpcy5vblRvdWNoZWQoKTtcclxuICAgIH1cclxuICAgIHRoaXMuYmx1ci5lbWl0KCdibHVyJyk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFeGVjdXRlZCB3aGVuIHRoZSBpbWFnZSBmcm9tIHRoZSBkaXNjIGlzIHNlbGVjdGVkXHJcbiAgICogQHBhcmFtIGltYWdlIHVwbG9hZGVkIGZpbGUgb2JqZWN0XHJcbiAgICovXHJcbiAgb25VcGxvYWRJbWFnZShpbWFnZTogSFRNTElucHV0RWxlbWVudCk6IHZvaWQge1xyXG4gICAgdGhpcy51cGxvYWRJbWFnZS5lbWl0KGltYWdlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIHJlc2l6aW5nIHRleHQgYXJlYVxyXG4gICAqXHJcbiAgICogQHBhcmFtIG9mZnNldFkgdmVydGljYWwgaGVpZ2h0IG9mIHRoZSBlaWR0YWJsZSBwb3J0aW9uIG9mIHRoZSBlZGl0b3JcclxuICAgKi9cclxuICByZXNpemVUZXh0QXJlYShvZmZzZXRZOiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGxldCBuZXdIZWlnaHQgPSBwYXJzZUludCh0aGlzLmhlaWdodCwgMTApO1xyXG4gICAgbmV3SGVpZ2h0ICs9IG9mZnNldFk7XHJcbiAgICB0aGlzLmhlaWdodCA9IG5ld0hlaWdodCArICdweCc7XHJcbiAgICB0aGlzLnRleHRBcmVhLm5hdGl2ZUVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBlZGl0b3IgYWN0aW9ucywgaS5lLiwgZXhlY3V0ZXMgY29tbWFuZCBmcm9tIHRvb2xiYXJcclxuICAgKlxyXG4gICAqIEBwYXJhbSBjb21tYW5kTmFtZSBuYW1lIG9mIHRoZSBjb21tYW5kIHRvIGJlIGV4ZWN1dGVkXHJcbiAgICovXHJcbiAgZXhlY3V0ZUNvbW1hbmQoY29tbWFuZE5hbWU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdHJ5IHtcclxuICAgICAgdGhpcy5fY29tbWFuZEV4ZWN1dG9yLmV4ZWN1dGUoY29tbWFuZE5hbWUpO1xyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgdGhpcy5fbWVzc2FnZVNlcnZpY2Uuc2VuZE1lc3NhZ2UoZXJyb3IubWVzc2FnZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBXcml0ZSBhIG5ldyB2YWx1ZSB0byB0aGUgZWxlbWVudC5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB2YWx1ZSB2YWx1ZSB0byBiZSBleGVjdXRlZCB3aGVuIHRoZXJlIGlzIGEgY2hhbmdlIGluIGNvbnRlbnRlZGl0YWJsZVxyXG4gICAqL1xyXG4gIHdyaXRlVmFsdWUodmFsdWU6IGFueSk6IHZvaWQge1xyXG4gICAgdGhpcy50b2dnbGVQbGFjZWhvbGRlcih2YWx1ZSk7XHJcblxyXG4gICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09ICcnIHx8IHZhbHVlID09PSAnPGJyPicpIHtcclxuICAgICAgdmFsdWUgPSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMucmVmcmVzaFZpZXcodmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0IHRoZSBmdW5jdGlvbiB0byBiZSBjYWxsZWRcclxuICAgKiB3aGVuIHRoZSBjb250cm9sIHJlY2VpdmVzIGEgY2hhbmdlIGV2ZW50LlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGZuIGEgZnVuY3Rpb25cclxuICAgKi9cclxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpOiB2b2lkIHtcclxuICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldCB0aGUgZnVuY3Rpb24gdG8gYmUgY2FsbGVkXHJcbiAgICogd2hlbiB0aGUgY29udHJvbCByZWNlaXZlcyBhIHRvdWNoIGV2ZW50LlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGZuIGEgZnVuY3Rpb25cclxuICAgKi9cclxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KTogdm9pZCB7XHJcbiAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogcmVmcmVzaCB2aWV3L0hUTUwgb2YgdGhlIGVkaXRvclxyXG4gICAqXHJcbiAgICogQHBhcmFtIHZhbHVlIGh0bWwgc3RyaW5nIGZyb20gdGhlIGVkaXRvclxyXG4gICAqL1xyXG4gIHJlZnJlc2hWaWV3KHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGNvbnN0IG5vcm1hbGl6ZWRWYWx1ZSA9IHZhbHVlID09PSBudWxsID8gJycgOiB2YWx1ZTtcclxuICAgIHRoaXMuX3JlbmRlcmVyLnNldFByb3BlcnR5KHRoaXMudGV4dEFyZWEubmF0aXZlRWxlbWVudCwgJ2lubmVySFRNTCcsIG5vcm1hbGl6ZWRWYWx1ZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiB0b2dnbGVzIHBsYWNlaG9sZGVyIGJhc2VkIG9uIGlucHV0IHN0cmluZ1xyXG4gICAqXHJcbiAgICogQHBhcmFtIHZhbHVlIEEgSFRNTCBzdHJpbmcgZnJvbSB0aGUgZWRpdG9yXHJcbiAgICovXHJcbiAgdG9nZ2xlUGxhY2Vob2xkZXIodmFsdWU6IGFueSk6IHZvaWQge1xyXG4gICAgaWYgKCF2YWx1ZSB8fCB2YWx1ZSA9PT0gJzxicj4nIHx8IHZhbHVlID09PSAnJykge1xyXG4gICAgICB0aGlzLl9yZW5kZXJlci5hZGRDbGFzcyh0aGlzLm5neFdyYXBwZXIubmF0aXZlRWxlbWVudCwgJ3Nob3ctcGxhY2Vob2xkZXInKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuX3JlbmRlcmVyLnJlbW92ZUNsYXNzKHRoaXMubmd4V3JhcHBlci5uYXRpdmVFbGVtZW50LCAnc2hvdy1wbGFjZWhvbGRlcicpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogcmV0dXJucyBhIGpzb24gY29udGFpbmluZyBpbnB1dCBwYXJhbXNcclxuICAgKi9cclxuICBnZXRDb2xsZWN0aXZlUGFyYW1zKCk6IGFueSB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBlZGl0YWJsZTogdGhpcy5lZGl0YWJsZSxcclxuICAgICAgc3BlbGxjaGVjazogdGhpcy5zcGVsbGNoZWNrLFxyXG4gICAgICBwbGFjZWhvbGRlcjogdGhpcy5wbGFjZWhvbGRlcixcclxuICAgICAgdHJhbnNsYXRlOiB0aGlzLnRyYW5zbGF0ZSxcclxuICAgICAgaGVpZ2h0OiB0aGlzLmhlaWdodCxcclxuICAgICAgbWluSGVpZ2h0OiB0aGlzLm1pbkhlaWdodCxcclxuICAgICAgd2lkdGg6IHRoaXMud2lkdGgsXHJcbiAgICAgIG1pbldpZHRoOiB0aGlzLm1pbldpZHRoLFxyXG4gICAgICBlbmFibGVUb29sYmFyOiB0aGlzLmVuYWJsZVRvb2xiYXIsXHJcbiAgICAgIHNob3dUb29sYmFyOiB0aGlzLnNob3dUb29sYmFyLFxyXG4gICAgICBpbWFnZUVuZFBvaW50OiB0aGlzLmltYWdlRW5kUG9pbnQsXHJcbiAgICAgIHRvb2xiYXI6IHRoaXMudG9vbGJhclxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgLyoqXHJcbiAgICAgKiBzZXQgY29uZmlndWFydGlvblxyXG4gICAgICovXHJcbiAgICB0aGlzLmNvbmZpZyA9IHRoaXMuVXRpbHMuZ2V0RWRpdG9yQ29uZmlndXJhdGlvbih0aGlzLmNvbmZpZywgbmd4RWRpdG9yQ29uZmlnLCB0aGlzLmdldENvbGxlY3RpdmVQYXJhbXMoKSk7XHJcblxyXG4gICAgdGhpcy5oZWlnaHQgPSB0aGlzLmhlaWdodCB8fCB0aGlzLnRleHRBcmVhLm5hdGl2ZUVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xyXG5cclxuICAgIHRoaXMuZXhlY3V0ZUNvbW1hbmQoJ2VuYWJsZU9iamVjdFJlc2l6aW5nJyk7XHJcbiAgfVxyXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnVwbG9hZGVkSW1hZ2VQYXRoICYmIHRoaXMudXBsb2FkZWRJbWFnZVBhdGggIT09IHRoaXMucHJldlVwbG9hZGVkSW1hZ2VQYXRoKSB7XHJcbiAgICAgIHRoaXMuX2NvbW1hbmRFeGVjdXRvci5pbnNlcnRJbWFnZSh0aGlzLnVwbG9hZGVkSW1hZ2VQYXRoKTtcclxuICAgICAgdGhpcy5wcmV2VXBsb2FkZWRJbWFnZVBhdGggPSB0aGlzLnVwbG9hZGVkSW1hZ2VQYXRoO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0=