ngx-editor-imageupload
Version:
WYSIWYG Editor for Angular Applications
399 lines • 32.4 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';
export class NgxEditorComponent {
/**
* @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
*/
constructor(_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
* @return {?}
*/
onTextAreaFocus() {
this.focus.emit('focus');
}
/**
* focus the text area when the editor is focussed
* @return {?}
*/
onEditorFocus() {
this.textArea.nativeElement.focus();
}
/**
* Executed from the contenteditable section while the input property changes
* @param {?} innerHTML
* @return {?}
*/
onContentChange(innerHTML) {
if (typeof this.onChange === 'function') {
this.onChange(innerHTML);
this.togglePlaceholder(innerHTML);
}
}
/**
* @return {?}
*/
onTextAreaBlur() {
/** 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
* @return {?}
*/
onUploadImage(image) {
this.uploadImage.emit(image);
}
/**
* resizing text area
*
* @param {?} offsetY vertical height of the eidtable portion of the editor
* @return {?}
*/
resizeTextArea(offsetY) {
/** @type {?} */
let 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
* @return {?}
*/
executeCommand(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
* @return {?}
*/
writeValue(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
* @return {?}
*/
registerOnChange(fn) {
this.onChange = fn;
}
/**
* Set the function to be called
* when the control receives a touch event.
*
* @param {?} fn a function
* @return {?}
*/
registerOnTouched(fn) {
this.onTouched = fn;
}
/**
* refresh view/HTML of the editor
*
* @param {?} value html string from the editor
* @return {?}
*/
refreshView(value) {
/** @type {?} */
const 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
* @return {?}
*/
togglePlaceholder(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
* @return {?}
*/
getCollectiveParams() {
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 {?}
*/
ngOnInit() {
/**
* 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 {?}
*/
ngOnChanges(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 {?}
*/
() => 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 = () => [
{ 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',] }]
};
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWVkaXRvci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtZWRpdG9yLWltYWdldXBsb2FkLyIsInNvdXJjZXMiOlsiYXBwL25neC1lZGl0b3Ivbmd4LWVkaXRvci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQVUsS0FBSyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQzNDLFlBQVksRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUNwQyxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsaUJBQWlCLEVBQXdCLE1BQU0sZ0JBQWdCLENBQUM7QUFFekUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFDcEYsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRW5FLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMvRCxPQUFPLEtBQUssS0FBSyxNQUFNLGlDQUFpQyxDQUFDO0FBYXpELE1BQU0sT0FBTyxrQkFBa0I7Ozs7OztJQXlFN0IsWUFDVSxlQUErQixFQUMvQixnQkFBd0MsRUFDeEMsU0FBb0I7UUFGcEIsb0JBQWUsR0FBZixlQUFlLENBQWdCO1FBQy9CLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBd0I7UUFDeEMsY0FBUyxHQUFULFNBQVMsQ0FBVzs7Ozs7Ozs7UUF4Q3JCLFlBQU8sR0FBRyxPQUFPLENBQUM7Ozs7Ozs7UUFPbEIsV0FBTSxHQUFHLGVBQWUsQ0FBQzs7OztRQVV4QixTQUFJLEdBQXlCLElBQUksWUFBWSxFQUFVLENBQUM7Ozs7UUFFeEQsVUFBSyxHQUF5QixJQUFJLFlBQVksRUFBVSxDQUFDOzs7O1FBRXpELGdCQUFXLEdBQW1DLElBQUksWUFBWSxFQUFvQixDQUFDO1FBSzdGLFVBQUssR0FBUSxLQUFLLENBQUM7SUFjZSxDQUFDOzs7OztJQUtuQyxlQUFlO1FBQ2IsSUFBSSxDQUFDLEtB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QUErQjs7Ozs7SUFHL0Isa0NBQWtFOzs7OztJQUVsRSxtQ0FBbUU7Ozs7O0lBRW5FLHlDQUE2Rjs7SUFFN0Ysc0NBQXdDOztJQUN4Qyx3Q0FBeUM7O0lBRXpDLG1DQUFtQjs7Ozs7SUFFbkIsc0NBQTBDOzs7OztJQUMxQyx1Q0FBOEI7O0lBQzlCLG1EQUE4Qjs7Ozs7SUFRNUIsNkNBQXVDOzs7OztJQUN2Qyw4Q0FBZ0Q7Ozs7O0lBQ2hELHVDQUE0QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ29tcG9uZW50LCBPbkluaXQsIElucHV0LCBPdXRwdXQsIFZpZXdDaGlsZCxcclxuICBFdmVudEVtaXR0ZXIsIFJlbmRlcmVyMiwgZm9yd2FyZFJlZiwgU2ltcGxlQ2hhbmdlcywgT25DaGFuZ2VzXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IE5HX1ZBTFVFX0FDQ0VTU09SLCBDb250cm9sVmFsdWVBY2Nlc3NvciB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuXHJcbmltcG9ydCB7IENvbW1hbmRFeGVjdXRvclNlcnZpY2UgfSBmcm9tICcuL2NvbW1vbi9zZXJ2aWNlcy9jb21tYW5kLWV4ZWN1dG9yLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBNZXNzYWdlU2VydmljZSB9IGZyb20gJy4vY29tbW9uL3NlcnZpY2VzL21lc3NhZ2Uuc2VydmljZSc7XHJcblxyXG5pbXBvcnQgeyBuZ3hFZGl0b3JDb25maWcgfSBmcm9tICcuL2NvbW1vbi9uZ3gtZWRpdG9yLmRlZmF1bHRzJztcclxuaW1wb3J0ICogYXMgVXRpbHMgZnJvbSAnLi9jb21tb24vdXRpbHMvbmd4LWVkaXRvci51dGlscyc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2FwcC1uZ3gtZWRpdG9yJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vbmd4LWVkaXRvci5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vbmd4LWVkaXRvci5jb21wb25lbnQuc2NzcyddLFxyXG4gIHByb3ZpZGVyczogW3tcclxuICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxyXG4gICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gTmd4RWRpdG9yQ29tcG9uZW50KSxcclxuICAgIG11bHRpOiB0cnVlXHJcbiAgfV1cclxufSlcclxuXHJcbmV4cG9ydCBjbGFzcyBOZ3hFZGl0b3JDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBPbkNoYW5nZXMge1xyXG4gIC8qKiBTcGVjaWZpZXMgd2VhdGhlciB0aGUgdGV4dGFyZWEgdG8gYmUgZWRpdGFibGUgb3Igbm90ICovXHJcbiAgQElucHV0KCkgZWRpdGFibGU6IGJvb2xlYW47XHJcbiAgLyoqIFRoZSBzcGVsbGNoZWNrIHByb3BlcnR5IHNwZWNpZmllcyB3aGV0aGVyIHRoZSBlbGVtZW50IGlzIHRvIGhhdmUgaXRzIHNwZWxsaW5nIGFuZCBncmFtbWFyIGNoZWNrZWQgb3Igbm90LiAqL1xyXG4gIEBJbnB1dCgpIHNwZWxsY2hlY2s6IGJvb2xlYW47XHJcbiAgLyoqIFBsYWNlaG9sZGVyIGZvciB0aGUgdGV4dEFyZWEgKi9cclxuICBASW5wdXQoKSBwbGFjZWhvbGRlcjogc3RyaW5nO1xyXG4gIC8qKlxyXG4gICAqIFRoZSB0cmFuc2xhdGUgcHJvcGVydHkgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIGNvbnRlbnQgb2YgYW4gZWxlbWVudCBzaG91bGQgYmUgdHJhbnNsYXRlZCBvciBub3QuXHJcbiAgICpcclxuICAgKiBDaGVjayBodHRwczovL3d3dy53M3NjaG9vbHMuY29tL3RhZ3MvYXR0X2dsb2JhbF90cmFuc2xhdGUuYXNwIGZvciBtb3JlIGluZm9ybWF0aW9uIGFuZCBicm93c2VyIHN1cHBvcnRcclxuICAgKi9cclxuICBASW5wdXQoKSB0cmFuc2xhdGU6IHN0cmluZztcclxuICAvKiogU2V0cyBoZWlnaHQgb2YgdGhlIGVkaXRvciAqL1xyXG4gIEBJbnB1dCgpIGhlaWdodDogc3RyaW5nO1xyXG4gIC8qKiBTZXRzIG1pbmltdW0gaGVpZ2h0IGZvciB0aGUgZWRpdG9yICovXHJcbiAgQElucHV0KCkgbWluSGVpZ2h0OiBzdHJpbmc7XHJcbiAgLyoqIFNldHMgV2lkdGggb2YgdGhlIGVkaXRvciAqL1xyXG4gIEBJbnB1dCgpIHdpZHRoOiBzdHJpbmc7XHJcbiAgLyoqIFNldHMgbWluaW11bSB3aWR0aCBvZiB0aGUgZWRpdG9yICovXHJcbiAgQElucHV0KCkgbWluV2lkdGg6IHN0cmluZztcclxuICAvKipcclxuICAgKiBUb29sYmFyIGFjY2VwdHMgYW4gYXJyYXkgd2hpY2ggc3BlY2lmaWVzIHRoZSBvcHRpb25zIHRvIGJlIGVuYWJsZWQgZm9yIHRoZSB0b29sYmFyXHJcbiAgICpcclxuICAgKiBDaGVjayBuZ3hFZGl0b3JDb25maWcgZm9yIHRvb2xiYXIgY29uZmlndXJhdGlvblxyXG4gICAqXHJcbiAgICogUGFzc2luZyBhbiBlbXB0eSBhcnJheSB3aWxsIGVuYWJsZSBhbGwgdG9vbGJhclxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHRvb2xiYXI6IE9iamVjdDtcclxuICAvKipcclxuICAgKiBUaGUgZWRpdG9yIGNhbiBiZSByZXNpemVkIHZlcnRpY2FsbHkuXHJcbiAgICpcclxuICAgKiBgYmFzaWNgIHJlc2l6ZXIgZW5hYmxlcyB0aGUgaHRtbDUgcmVzemllci4gQ2hlY2sgaGVyZSBodHRwczovL3d3dy53M3NjaG9vbHMuY29tL2Nzc3JlZi9jc3MzX3ByX3Jlc2l6ZS5hc3BcclxuICAgKlxyXG4gICAqIGBzdGFja2AgcmVzaXplciBlbmFibGUgYSByZXNpemVyIHRoYXQgbG9va3MgbGlrZSBhcyBpZiBpbiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tXHJcbiAgICovXHJcbiAgQElucHV0KCkgcmVzaXplciA9ICdzdGFjayc7XHJcbiAgLyoqXHJcbiAgICogVGhlIGNvbmZpZyBwcm9wZXJ0eSBpcyBhIEpTT04gb2JqZWN0XHJcbiAgICpcclxuICAgKiBBbGwgYXZhaWJhbGUgaW5wdXRzIGlucHV0cyBjYW4gYmUgcHJvdmlkZWQgaW4gdGhlIGNvbmZpZ3VyYXRpb24gYXMgSlNPTlxyXG4gICAqIGlucHV0cyBwcm92aWRlZCBkaXJlY3RseSBhcmUgY29uc2lkZXJlZCBhcyB0b3AgcHJpb3JpdHlcclxuICAgKi9cclxuICBASW5wdXQoKSBjb25maWcgPSBuZ3hFZGl0b3JDb25maWc7XHJcbiAgQElucHV0KCkgdXBsb2FkZWRJbWFnZVBhdGg6IHN0cmluZztcclxuICAvKiogV2VhdGhlciB0byBzaG93IG9yIGhpZGUgdG9vbGJhciAqL1xyXG4gIEBJbnB1dCgpIHNob3dUb29sYmFyOiBib29sZWFuO1xyXG4gIC8qKiBXZWF0aGVyIHRvIGVuYWJsZSBvciBkaXNhYmxlIHRoZSB0b29sYmFyICovXHJcbiAgQElucHV0KCkgZW5hYmxlVG9vbGJhcjogYm9vbGVhbjtcclxuICAvKiogRW5kcG9pbnQgZm9yIHdoaWNoIHRoZSBpbWFnZSB0byBiZSB1cGxvYWRlZCAqL1xyXG4gIEBJbnB1dCgpIGltYWdlRW5kUG9pbnQ6IHN0cmluZztcclxuXHJcbiAgLyoqIGVtaXRzIGBibHVyYCBldmVudCB3aGVuIGZvY3VzZWQgb3V0IGZyb20gdGhlIHRleHRhcmVhICovXHJcbiAgQE91dHB1dCgpIGJsdXI6IEV2ZW50RW1pdHRlcjxzdHJpbmc+ID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XHJcbiAgLyoqIGVtaXRzIGBmb2N1c2AgZXZlbnQgd2hlbiBmb2N1c2VkIGluIHRvIHRoZSB0ZXh0YXJlYSAqL1xyXG4gIEBPdXRwdXQoKSBmb2N1czogRXZlbnRFbWl0dGVyPHN0cmluZz4gPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuICAvKiogZW1pdHMgYHVwbG9hZEltYWdlYCBldmVudCB3aGVuIGltYWdlIGlzIHNlbGVjdGVkICovXHJcbiAgQE91dHB1dCgpIHVwbG9hZEltYWdlOiBFdmVudEVtaXR0ZXI8SFRNTElucHV0RWxlbWVudD4gPSBuZXcgRXZlbnRFbWl0dGVyPEhUTUxJbnB1dEVsZW1lbnQ+KCk7XHJcblxyXG4gIEBWaWV3Q2hpbGQoJ25neFRleHRBcmVhJykgdGV4dEFyZWE6IGFueTtcclxuICBAVmlld0NoaWxkKCduZ3hXcmFwcGVyJykgbmd4V3JhcHBlcjogYW55O1xyXG5cclxuICBVdGlsczogYW55ID0gVXRpbHM7XHJcblxyXG4gIHByaXZhdGUgb25DaGFuZ2U6ICh2YWx1ZTogc3RyaW5nKSA9PiB2b2lkO1xyXG4gIHByaXZhdGUgb25Ub3VjaGVkOiAoKSA9PiB2b2lkO1xyXG4gIHByZXZVcGxvYWRlZEltYWdlUGF0aDogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBAcGFyYW0gX21lc3NhZ2VTZXJ2aWNlIHNlcnZpY2UgdG8gc2VuZCBtZXNzYWdlIHRvIHRoZSBlZGl0b3IgbWVzc2FnZSBjb21wb25lbnRcclxuICAgKiBAcGFyYW0gX2NvbW1hbmRFeGVjdXRvciBleGVjdXRlcyBjb21tYW5kIGZyb20gdGhlIHRvb2xiYXJcclxuICAgKiBAcGFyYW0gX3JlbmRlcmVyIGFjY2VzcyBhbmQgbWFuaXB1bGF0ZSB0aGUgZG9tIGVsZW1lbnRcclxuICAgKi9cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgX21lc3NhZ2VTZXJ2aWNlOiBNZXNzYWdlU2VydmljZSxcclxuICAgIHByaXZhdGUgX2NvbW1hbmRFeGVjdXRvcjogQ29tbWFuZEV4ZWN1dG9yU2VydmljZSxcclxuICAgIHByaXZhdGUgX3JlbmRlcmVyOiBSZW5kZXJlcjIpIHsgfVxyXG5cclxuICAvKipcclxuICAgKiBldmVudHNcclxuICAgKi9cclxuICBvblRleHRBcmVhRm9jdXMoKTogdm9pZCB7XHJcbiAgICB0aGlzLmZvY3VzLmVtaXQoJ2ZvY3VzJyk7XHJcbiAgfVxyXG5cclxuICAvKiogZm9jdXMgdGhlIHRleHQgYXJlYSB3aGVuIHRoZSBlZGl0b3IgaXMgZm9jdXNzZWQgKi9cclxuICBvbkVkaXRvckZvY3VzKCkge1xyXG4gICAgdGhpcy50ZXh0QXJlYS5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFeGVjdXRlZCBmcm9tIHRoZSBjb250ZW50ZWRpdGFibGUgc2VjdGlvbiB3aGlsZSB0aGUgaW5wdXQgcHJvcGVydHkgY2hhbmdlc1xyXG4gICAqIEBwYXJhbSBodG1sIGh0bWwgc3RyaW5nIGZyb20gY29udGVudGVkaXRhYmxlXHJcbiAgICovXHJcbiAgb25Db250ZW50Q2hhbmdlKGlubmVySFRNTDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAodHlwZW9mIHRoaXMub25DaGFuZ2UgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgdGhpcy5vbkNoYW5nZShpbm5lckhUTUwpO1xyXG4gICAgICB0aGlzLnRvZ2dsZVBsYWNlaG9sZGVyKGlubmVySFRNTCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBvblRleHRBcmVhQmx1cigpOiB2b2lkIHtcclxuICAgIC8qKiBzYXZlIHNlbGVjdGlvbiBpZiBmb2N1c3NlZCBvdXQgKi9cclxuICAgIHRoaXMuX2NvbW1hbmRFeGVjdXRvci5zYXZlZFNlbGVjdGlvbiA9IFV0aWxzLnNhdmVTZWxlY3Rpb24oKTtcclxuXHJcbiAgICBpZiAodHlwZW9mIHRoaXMub25Ub3VjaGVkID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgIHRoaXMub25Ub3VjaGVkKCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmJsdXIuZW1pdCgnYmx1cicpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRXhlY3V0ZWQgd2hlbiB0aGUgaW1hZ2UgZnJvbSB0aGUgZGlzYyBpcyBzZWxlY3RlZFxyXG4gICAqIEBwYXJhbSBpbWFnZSB1cGxvYWRlZCBmaWxlIG9iamVjdFxyXG4gICAqL1xyXG4gIG9uVXBsb2FkSW1hZ2UoaW1hZ2U6IEhUTUxJbnB1dEVsZW1lbnQpOiB2b2lkIHtcclxuICAgIHRoaXMudXBsb2FkSW1hZ2UuZW1pdChpbWFnZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiByZXNpemluZyB0ZXh0IGFyZWFcclxuICAgKlxyXG4gICAqIEBwYXJhbSBvZmZzZXRZIHZlcnRpY2FsIGhlaWdodCBvZiB0aGUgZWlkdGFibGUgcG9ydGlvbiBvZiB0aGUgZWRpdG9yXHJcbiAgICovXHJcbiAgcmVzaXplVGV4dEFyZWEob2Zmc2V0WTogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBsZXQgbmV3SGVpZ2h0ID0gcGFyc2VJbnQodGhpcy5oZWlnaHQsIDEwKTtcclxuICAgIG5ld0hlaWdodCArPSBvZmZzZXRZO1xyXG4gICAgdGhpcy5oZWlnaHQgPSBuZXdIZWlnaHQgKyAncHgnO1xyXG4gICAgdGhpcy50ZXh0QXJlYS5uYXRpdmVFbGVtZW50LnN0eWxlLmhlaWdodCA9IHRoaXMuaGVpZ2h0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogZWRpdG9yIGFjdGlvbnMsIGkuZS4sIGV4ZWN1dGVzIGNvbW1hbmQgZnJvbSB0b29sYmFyXHJcbiAgICpcclxuICAgKiBAcGFyYW0gY29tbWFuZE5hbWUgbmFtZSBvZiB0aGUgY29tbWFuZCB0byBiZSBleGVjdXRlZFxyXG4gICAqL1xyXG4gIGV4ZWN1dGVDb21tYW5kKGNvbW1hbmROYW1lOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIHRoaXMuX2NvbW1hbmRFeGVjdXRvci5leGVjdXRlKGNvbW1hbmROYW1lKTtcclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIHRoaXMuX21lc3NhZ2VTZXJ2aWNlLnNlbmRNZXNzYWdlKGVycm9yLm1lc3NhZ2UpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogV3JpdGUgYSBuZXcgdmFsdWUgdG8gdGhlIGVsZW1lbnQuXHJcbiAgICpcclxuICAgKiBAcGFyYW0gdmFsdWUgdmFsdWUgdG8gYmUgZXhlY3V0ZWQgd2hlbiB0aGVyZSBpcyBhIGNoYW5nZSBpbiBjb250ZW50ZWRpdGFibGVcclxuICAgKi9cclxuICB3cml0ZVZhbHVlKHZhbHVlOiBhbnkpOiB2b2lkIHtcclxuICAgIHRoaXMudG9nZ2xlUGxhY2Vob2xkZXIodmFsdWUpO1xyXG5cclxuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSAnJyB8fCB2YWx1ZSA9PT0gJzxicj4nKSB7XHJcbiAgICAgIHZhbHVlID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnJlZnJlc2hWaWV3KHZhbHVlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldCB0aGUgZnVuY3Rpb24gdG8gYmUgY2FsbGVkXHJcbiAgICogd2hlbiB0aGUgY29udHJvbCByZWNlaXZlcyBhIGNoYW5nZSBldmVudC5cclxuICAgKlxyXG4gICAqIEBwYXJhbSBmbiBhIGZ1bmN0aW9uXHJcbiAgICovXHJcbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogYW55KTogdm9pZCB7XHJcbiAgICB0aGlzLm9uQ2hhbmdlID0gZm47XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZXQgdGhlIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxyXG4gICAqIHdoZW4gdGhlIGNvbnRyb2wgcmVjZWl2ZXMgYSB0b3VjaCBldmVudC5cclxuICAgKlxyXG4gICAqIEBwYXJhbSBmbiBhIGZ1bmN0aW9uXHJcbiAgICovXHJcbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSk6IHZvaWQge1xyXG4gICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIHJlZnJlc2ggdmlldy9IVE1MIG9mIHRoZSBlZGl0b3JcclxuICAgKlxyXG4gICAqIEBwYXJhbSB2YWx1ZSBodG1sIHN0cmluZyBmcm9tIHRoZSBlZGl0b3JcclxuICAgKi9cclxuICByZWZyZXNoVmlldyh2YWx1ZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBub3JtYWxpemVkVmFsdWUgPSB2YWx1ZSA9PT0gbnVsbCA/ICcnIDogdmFsdWU7XHJcbiAgICB0aGlzLl9yZW5kZXJlci5zZXRQcm9wZXJ0eSh0aGlzLnRleHRBcmVhLm5hdGl2ZUVsZW1lbnQsICdpbm5lckhUTUwnLCBub3JtYWxpemVkVmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogdG9nZ2xlcyBwbGFjZWhvbGRlciBiYXNlZCBvbiBpbnB1dCBzdHJpbmdcclxuICAgKlxyXG4gICAqIEBwYXJhbSB2YWx1ZSBBIEhUTUwgc3RyaW5nIGZyb20gdGhlIGVkaXRvclxyXG4gICAqL1xyXG4gIHRvZ2dsZVBsYWNlaG9sZGVyKHZhbHVlOiBhbnkpOiB2b2lkIHtcclxuICAgIGlmICghdmFsdWUgfHwgdmFsdWUgPT09ICc8YnI+JyB8fCB2YWx1ZSA9PT0gJycpIHtcclxuICAgICAgdGhpcy5fcmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5uZ3hXcmFwcGVyLm5hdGl2ZUVsZW1lbnQsICdzaG93LXBsYWNlaG9sZGVyJyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLl9yZW5kZXJlci5yZW1vdmVDbGFzcyh0aGlzLm5neFdyYXBwZXIubmF0aXZlRWxlbWVudCwgJ3Nob3ctcGxhY2Vob2xkZXInKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIHJldHVybnMgYSBqc29uIGNvbnRhaW5pbmcgaW5wdXQgcGFyYW1zXHJcbiAgICovXHJcbiAgZ2V0Q29sbGVjdGl2ZVBhcmFtcygpOiBhbnkge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgZWRpdGFibGU6IHRoaXMuZWRpdGFibGUsXHJcbiAgICAgIHNwZWxsY2hlY2s6IHRoaXMuc3BlbGxjaGVjayxcclxuICAgICAgcGxhY2Vob2xkZXI6IHRoaXMucGxhY2Vob2xkZXIsXHJcbiAgICAgIHRyYW5zbGF0ZTogdGhpcy50cmFuc2xhdGUsXHJcbiAgICAgIGhlaWdodDogdGhpcy5oZWlnaHQsXHJcbiAgICAgIG1pbkhlaWdodDogdGhpcy5taW5IZWlnaHQsXHJcbiAgICAgIHdpZHRoOiB0aGlzLndpZHRoLFxyXG4gICAgICBtaW5XaWR0aDogdGhpcy5taW5XaWR0aCxcclxuICAgICAgZW5hYmxlVG9vbGJhcjogdGhpcy5lbmFibGVUb29sYmFyLFxyXG4gICAgICBzaG93VG9vbGJhcjogdGhpcy5zaG93VG9vbGJhcixcclxuICAgICAgaW1hZ2VFbmRQb2ludDogdGhpcy5pbWFnZUVuZFBvaW50LFxyXG4gICAgICB0b29sYmFyOiB0aGlzLnRvb2xiYXJcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpIHtcclxuICAgIC8qKlxyXG4gICAgICogc2V0IGNvbmZpZ3VhcnRpb25cclxuICAgICAqL1xyXG4gICAgdGhpcy5jb25maWcgPSB0aGlzLlV0aWxzLmdldEVkaXRvckNvbmZpZ3VyYXRpb24odGhpcy5jb25maWcsIG5neEVkaXRvckNvbmZpZywgdGhpcy5nZXRDb2xsZWN0aXZlUGFyYW1zKCkpO1xyXG5cclxuICAgIHRoaXMuaGVpZ2h0ID0gdGhpcy5oZWlnaHQgfHwgdGhpcy50ZXh0QXJlYS5uYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodDtcclxuXHJcbiAgICB0aGlzLmV4ZWN1dGVDb21tYW5kKCdlbmFibGVPYmplY3RSZXNpemluZycpO1xyXG4gIH1cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy51cGxvYWRlZEltYWdlUGF0aCAmJiB0aGlzLnVwbG9hZGVkSW1hZ2VQYXRoICE9PSB0aGlzLnByZXZVcGxvYWRlZEltYWdlUGF0aCkge1xyXG4gICAgICB0aGlzLl9jb21tYW5kRXhlY3V0b3IuaW5zZXJ0SW1hZ2UodGhpcy51cGxvYWRlZEltYWdlUGF0aCk7XHJcbiAgICAgIHRoaXMucHJldlVwbG9hZGVkSW1hZ2VQYXRoID0gdGhpcy51cGxvYWRlZEltYWdlUGF0aDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19