ngx-editor-imageupload
Version:
WYSIWYG Editor for Angular Applications
529 lines • 37 kB
JavaScript
/**
* @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=