UNPKG

@kephas/angular-ace

Version:

Provides the integration of the Ace editor with Kephas and Angular.

363 lines 36.7 kB
import { ValueEditorBase, provideWidget, provideValueAccessor } from '@kephas/angular'; import { ViewContainerRef, ElementRef, Component, Input } from '@angular/core'; import { edit } from 'brace'; import 'brace/theme/monokai'; import 'brace/mode/abap'; import 'brace/mode/lua'; import 'brace/mode/sh'; import 'brace/mode/sql'; import 'brace/mode/powershell'; import 'brace/mode/text'; import 'brace/mode/json'; /** * Value editor based on Ace. * * @export * @class AceComponent * @extends {(ValueEditorBase<string | {} | null>)} */ export class AceComponent extends ValueEditorBase { /** * Creates an instance of AceComponent. * * @param {ElementRef} elementRef The element reference. * @param {ViewContainerRef} viewContainerRef The view container reference. * @memberof AceComponent */ constructor(elementRef, viewContainerRef) { super(elementRef, viewContainerRef); this._theme = 'monokai'; this._editorType = 'json'; this._valueIsObject = false; } /** * Gets or sets the editor type. * * @type {string} * @memberof AceComponent */ get editorType() { return this._editorType; } set editorType(value) { if (this._editorType === value) { return; } this._editorType = value; this.setEditorType(value); } /** * Gets or sets the editor options. * * @memberof AceComponent */ set options(value) { if (this.editor) { this.editor.setOptions(value || {}); } } get options() { return this.editor && this.editor.getOptions(); } /** * Gets or sets the editor theme. * * @type {string} * @memberof AceComponent */ get theme() { return this._theme; } set theme(value) { if (this._theme === value) { return; } this._theme = value; this.setEditorTheme(value); } /** * Gets or sets a value indicating whether the bound value is an object or not. * * @readonly * @type {boolean} * @memberof AceComponent */ get valueIsObject() { return this._valueIsObject; } set valueIsObject(value) { this._valueIsObject = value; } /** * A callback method that is invoked immediately after the * default change detector has checked the directive's * data-bound properties for the first time, * and before any of the view or content children have been checked. * It is invoked only once when the directive is instantiated. * * @memberof AceComponent */ ngOnInit() { super.ngOnInit(); const hostElement = this.elementRef.nativeElement.children[0]; this.editor = edit(hostElement); this.editor.setShowPrintMargin(false); this.setEditorTheme(this._theme); this.setEditorType(this._editorType); this.setEditorReadOnly(this.readonly); this.setEditorValue(this.value); this.editor.on('change', e => this.onEditorChange(e)); this.editor.on('paste', e => this.onEditorChange(e)); this.editor.commands.addCommand({ name: 'formatDocumentCommand', bindKey: { win: 'Ctrl-Shift-F', mac: 'Command-Shift-F' }, exec: (e) => { this.formatDocument(); } }); } /** * A callback method that is invoked immediately after * Angular has completed initialization of a component's view. * It is invoked only once when the view is instantiated. * * @memberof AceComponent */ ngAfterViewInit() { super.ngAfterViewInit(); if (!this.observeVisibilityOf) { return; } this.observeVisibility(this.observeVisibilityOf); } /** * A callback method that performs custom clean-up, invoked immediately * after a directive, pipe, or service instance is destroyed. * * @memberof AceComponent */ ngOnDestroy() { super.ngOnDestroy(); if (this._observer) { this._observer.disconnect(); } } /** * Observes the visibility of the elements in the query string, * and if they are visible, it will trigger an editor resize. * This is required to fix a problem in the ACE editor when * setValue doesn't work if the editor is hidden. * * See also https://github.com/ajaxorg/ace/issues/3070. * See also https://github.com/Starcounter/Content/commit/91a757d8750523431fc1637fdf57409d0fcb13db. * * @param {string} queryString * @memberof ScriptEditorComponent */ observeVisibility(queryStrings) { if (this._observer) { this._observer.disconnect(); } if (typeof queryStrings === 'string') { queryStrings = [queryStrings]; } this._observer = new MutationObserver(mutations => { const changedTargets = []; mutations.forEach(mutationRecord => { if (changedTargets.findIndex(e => e === mutationRecord.target) < 0) { changedTargets.push(mutationRecord.target); } }); changedTargets.forEach(t => { if (this._isAceVisible(t) && this.editor) { this.editor.resize(true); } }); }); for (const queryString of queryStrings) { const query = top.document.querySelectorAll(queryString); for (let i = 0; i < query.length; i++) { this._observer.observe(query[i], { attributes: true, attributeFilter: ['style'] }); } } } /** * Formats the JSON document inside the editor. * * @protected * @returns * @memberof AceComponent */ formatDocument() { if (!this.editor) { return; } if (this.editorType.toLowerCase() === 'json') { let stringValue = this.editor.getValue(); try { const objectValue = JSON.parse(stringValue); stringValue = this._getFormattedJson(objectValue); this.editor.setValue(stringValue); } catch (error) { // too bad we could not format this.notification.notifyWarning(error); } } } /** * Sets the value of the underlying editor. * * @protected * @param {string | {} | null} value * @memberof ValueEditorBase */ setEditorValue(value) { if (!this.editor) { return; } let stringValue = ''; if (typeof value === 'object') { this._valueIsObject = true; stringValue = this._getFormattedJson(value); } else if (typeof value === 'string') { if (value) { this._valueIsObject = false; } stringValue = value; } else { stringValue = value && value.toString(); } this.editor.setValue(stringValue || ''); this.editor.clearSelection(); } /** * Gets the underlying editor's value. * * @protected * @returns {string | {} | null} The widget value. * @memberof ValueEditorBase */ getEditorValue() { if (!this.editor) { return null; } const stringValue = this.editor.getValue(); if (this._valueIsObject) { if (!stringValue) { return stringValue; } try { const objectValue = JSON.parse(stringValue); return objectValue; } catch (error) { return stringValue; } } return stringValue; } /** * When overridden in a derived class, this method is called when the read only state changes. * * @protected * @param {boolean} oldValue The old value. * @param {boolean} newValue The new value. * * @memberof EditorBase */ onReadOnlyChanged(oldValue, newValue) { if (this.editor) { this.setEditorReadOnly(newValue); } } /** * Sets the readonly state of the editor. * * @protected * @param {boolean} value * @memberof AceComponent */ setEditorReadOnly(value) { if (this.editor) { this.editor.setReadOnly(value); } } /** * Sets the editor theme. * * @protected * @param {string} theme * @memberof AceComponent */ setEditorTheme(theme) { if (this.editor && theme) { this.editor.setTheme(`ace/theme/${theme}`); } } /** * Sets the editor type. * * @protected * @param {string} editorType * @memberof AceComponent */ setEditorType(editorType) { if (this.editor && editorType) { const mode = this.getEditorMode(editorType); this.editor.getSession().setMode(`ace/mode/${mode}`); this.editor.$blockScrolling = Infinity; } } /** * Gets the editor mode based on the provided editor type. * * @protected * @param {string} editorType The editor type. * @returns {string} * @memberof AceComponent */ getEditorMode(editorType) { return editorType; } /** * Updates the underlying editor with the provided value. * * @protected * @param {TValue} value The value to be set in the underlying component. * @returns {boolean} * @memberof AceComponent */ updateEditor(value) { value = value || ''; return super.updateEditor(value); } _getFormattedJson(obj) { return JSON.stringify(obj, null, 4); } _isAceVisible(element) { const style = window.getComputedStyle(element); return !(style.display === 'none'); } } AceComponent.decorators = [ { type: Component, args: [{ selector: 'ace', template: `<div class="form-control ace"></div>`, providers: [provideWidget(AceComponent), provideValueAccessor(AceComponent)] },] } ]; AceComponent.ctorParameters = () => [ { type: ElementRef }, { type: ViewContainerRef } ]; AceComponent.propDecorators = { observeVisibilityOf: [{ type: Input }], editorType: [{ type: Input }], options: [{ type: Input }], theme: [{ type: Input }], valueIsObject: [{ type: Input }] }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIuLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWFjZS9zcmMvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9hY2UuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDSCxlQUFlLEVBQUUsYUFBYSxFQUFFLG9CQUFvQixFQUN2RCxNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFDSCxnQkFBZ0IsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFFakQsTUFBTSxlQUFlLENBQUE7QUFFdEIsT0FBTyxFQUFVLElBQUksRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUVyQyxPQUFPLHFCQUFxQixDQUFDO0FBRTdCLE9BQU8saUJBQWlCLENBQUM7QUFDekIsT0FBTyxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLGVBQWUsQ0FBQztBQUN2QixPQUFPLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLGlCQUFpQixDQUFDO0FBRXpCOzs7Ozs7R0FNRztBQU1ILE1BQU0sT0FBTyxZQUFhLFNBQVEsZUFBbUM7SUFlakU7Ozs7OztPQU1HO0lBQ0gsWUFDSSxVQUFzQixFQUN0QixnQkFBa0M7UUFFbEMsS0FBSyxDQUFDLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBaEJoQyxXQUFNLEdBQUcsU0FBUyxDQUFDO1FBQ25CLGdCQUFXLEdBQVcsTUFBTSxDQUFDO1FBQzdCLG1CQUFjLEdBQUcsS0FBSyxDQUFDO0lBZS9CLENBQUM7SUFXRDs7Ozs7T0FLRztJQUNILElBQ0ksVUFBVTtRQUNWLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQztJQUM1QixDQUFDO0lBQ0QsSUFBSSxVQUFVLENBQUMsS0FBYTtRQUN4QixJQUFJLElBQUksQ0FBQyxXQUFXLEtBQUssS0FBSyxFQUFFO1lBQzVCLE9BQU87U0FDVjtR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LE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxLQUFLLE1BQU0sQ0FBQyxDQUFBO0lBQ3RDLENBQUM7OztZQW5ZSixTQUFTLFNBQUM7Z0JBQ1AsUUFBUSxFQUFFLEtBQUs7Z0JBQ2YsUUFBUSxFQUFFLHNDQUFzQztnQkFDaEQsU0FBUyxFQUFFLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxFQUFFLG9CQUFvQixDQUFDLFlBQVksQ0FBQyxDQUFDO2FBQy9FOzs7WUEzQnFCLFVBQVU7WUFBNUIsZ0JBQWdCOzs7a0NBK0RmLEtBQUs7eUJBU0wsS0FBSztzQkFrQkwsS0FBSztvQkFlTCxLQUFLOzRCQW9CTCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICAgIFZhbHVlRWRpdG9yQmFzZSwgcHJvdmlkZVdpZGdldCwgcHJvdmlkZVZhbHVlQWNjZXNzb3JcclxufSBmcm9tICdAa2VwaGFzL2FuZ3VsYXInO1xyXG5pbXBvcnQge1xyXG4gICAgVmlld0NvbnRhaW5lclJlZiwgRWxlbWVudFJlZiwgQ29tcG9uZW50LCBJbnB1dCwgT25Jbml0LFxyXG4gICAgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95XHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcclxuXHJcbmltcG9ydCB7IEVkaXRvciwgZWRpdCB9IGZyb20gJ2JyYWNlJztcclxuXHJcbmltcG9ydCAnYnJhY2UvdGhlbWUvbW9ub2thaSc7XHJcblxyXG5pbXBvcnQgJ2JyYWNlL21vZGUvYWJhcCc7XHJcbmltcG9ydCAnYnJhY2UvbW9kZS9sdWEnO1xyXG5pbXBvcnQgJ2JyYWNlL21vZGUvc2gnO1xyXG5pbXBvcnQgJ2JyYWNlL21vZGUvc3FsJztcclxuaW1wb3J0ICdicmFjZS9tb2RlL3Bvd2Vyc2hlbGwnO1xyXG5pbXBvcnQgJ2JyYWNlL21vZGUvdGV4dCc7XHJcbmltcG9ydCAnYnJhY2UvbW9kZS9qc29uJztcclxuXHJcbi8qKlxyXG4gKiBWYWx1ZSBlZGl0b3IgYmFzZWQgb24gQWNlLlxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBjbGFzcyBBY2VDb21wb25lbnRcclxuICogQGV4dGVuZHMgeyhWYWx1ZUVkaXRvckJhc2U8c3RyaW5nIHwge30gfCBudWxsPil9XHJcbiAqL1xyXG5AQ29tcG9uZW50KHtcclxuICAgIHNlbGVjdG9yOiAnYWNlJyxcclxuICAgIHRlbXBsYXRlOiBgPGRpdiBjbGFzcz1cImZvcm0tY29udHJvbCBhY2VcIj48L2Rpdj5gLFxyXG4gICAgcHJvdmlkZXJzOiBbcHJvdmlkZVdpZGdldChBY2VDb21wb25lbnQpLCBwcm92aWRlVmFsdWVBY2Nlc3NvcihBY2VDb21wb25lbnQpXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgQWNlQ29tcG9uZW50IGV4dGVuZHMgVmFsdWVFZGl0b3JCYXNlPHN0cmluZyB8IHt9IHwgbnVsbD5cclxuICAgIGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIG9yIHNldHMgdGhlIEFjZSBlZGl0b3IuXHJcbiAgICAgKlxyXG4gICAgICogQHR5cGUge2FjZS5FZGl0b3J9XHJcbiAgICAgKiBAbWVtYmVyb2YgQWNlQ29tcG9uZW50XHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBlZGl0b3I/OiBFZGl0b3I7XHJcblxyXG4gICAgcHJpdmF0ZSBfdGhlbWUgPSAnbW9ub2thaSc7XHJcbiAgICBwcml2YXRlIF9lZGl0b3JUeXBlOiBzdHJpbmcgPSAnanNvbic7XHJcbiAgICBwcml2YXRlIF92YWx1ZUlzT2JqZWN0ID0gZmFsc2U7XHJcbiAgICBwcml2YXRlIF9vYnNlcnZlcj86IE11dGF0aW9uT2JzZXJ2ZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIEFjZUNvbXBvbmVudC5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0VsZW1lbnRSZWZ9IGVsZW1lbnRSZWYgVGhlIGVsZW1lbnQgcmVmZXJlbmNlLlxyXG4gICAgICogQHBhcmFtIHtWaWV3Q29udGFpbmVyUmVmfSB2aWV3Q29udGFpbmVyUmVmIFRoZSB2aWV3IGNvbnRhaW5lciByZWZlcmVuY2UuXHJcbiAgICAgKiBAbWVtYmVyb2YgQWNlQ29tcG9uZW50XHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXHJcbiAgICAgICAgdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZixcclxuICAgICkge1xyXG4gICAgICAgIHN1cGVyKGVsZW1lbnRSZWYsIHZpZXdDb250YWluZXJSZWYpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyBvciBzZXRzIGEgdmFsdWUgaW5kaWNhdGluZ1xyXG4gICAgICpcclxuICAgICAqIEB0eXBlIHsoc3RyaW5nIHwgc3RyaW5nW10pfVxyXG4gICAgICogQG1lbWJlcm9mIEFjZUNvbXBvbmVudFxyXG4gICAgICovXHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIG9ic2VydmVWaXNpYmlsaXR5T2Y/OiBzdHJpbmcgfCBzdHJpbmdbXTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldHMgb3Igc2V0cyB0aGUgZWRpdG9yIHR5cGUuXHJcbiAgICAgKlxyXG4gICAgICogQHR5cGUge3N0cmluZ31cclxuICAgICAqIEBtZW1iZXJvZiBBY2VDb21wb25lbnRcclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIGdldCBlZGl0b3JUeXBlKCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VkaXRvclR5cGU7XHJcbiAgICB9XHJcbiAgICBzZXQgZWRpdG9yVHlwZSh2YWx1ZTogc3RyaW5nKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuX2VkaXRvclR5cGUgPT09IHZhbHVlKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuX2VkaXRvclR5cGUgPSB2YWx1ZTtcclxuICAgICAgICB0aGlzLnNldEVkaXRvclR5cGUodmFsdWUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyBvciBzZXRzIHRoZSBlZGl0b3Igb3B0aW9ucy5cclxuICAgICAqXHJcbiAgICAgKiBAbWVtYmVyb2YgQWNlQ29tcG9uZW50XHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIHNldCBvcHRpb25zKHZhbHVlOiBhbnkpIHtcclxuICAgICAgICBpZiAodGhpcy5lZGl0b3IpIHtcclxuICAgICAgICAgICAgdGhpcy5lZGl0b3Iuc2V0T3B0aW9ucyh2YWx1ZSB8fCB7fSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgZ2V0IG9wdGlvbnMoKTogYW55IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5lZGl0b3IgJiYgdGhpcy5lZGl0b3IuZ2V0T3B0aW9ucygpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyBvciBzZXRzIHRoZSBlZGl0b3IgdGhlbWUuXHJcbiAgICAgKlxyXG4gICAgICogQHR5cGUge3N0cmluZ31cclxuICAgICAqIEBtZW1iZXJvZiBBY2VDb21wb25lbnRcclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIGdldCB0aGVtZSgpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl90aGVtZTtcclxuICAgIH1cclxuICAgIHNldCB0aGVtZSh2YWx1ZTogc3RyaW5nKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuX3RoZW1lID09PSB2YWx1ZSkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLl90aGVtZSA9IHZhbHVlO1xyXG4gICAgICAgIHRoaXMuc2V0RWRpdG9yVGhlbWUodmFsdWUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyBvciBzZXRzIGEgdmFsdWUgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSBib3VuZCB2YWx1ZSBpcyBhbiBvYmplY3Qgb3Igbm90LlxyXG4gICAgICpcclxuICAgICAqIEByZWFkb25seVxyXG4gICAgICogQHR5cGUge2Jvb2xlYW59XHJcbiAgICAgKiBAbWVtYmVyb2YgQWNlQ29tcG9uZW50XHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBnZXQgdmFsdWVJc09iamVjdCgpOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWVJc09iamVjdDtcclxuICAgIH1cclxuICAgIHNldCB2YWx1ZUlzT2JqZWN0KHZhbHVlOiBib29sZWFuKSB7XHJcbiAgICAgICAgdGhpcy5fdmFsdWVJc09iamVjdCA9IHZhbHVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQSBjYWxsYmFjayBtZXRob2QgdGhhdCBpcyBpbnZva2VkIGltbWVkaWF0ZWx5IGFmdGVyIHRoZVxyXG4gICAgICogZGVmYXVsdCBjaGFuZ2UgZGV0ZWN0b3IgaGFzIGNoZWNrZWQgdGhlIGRpcmVjdGl2ZSdzXHJcbiAgICAgKiBkYXRhLWJvdW5kIHByb3BlcnRpZXMgZm9yIHRoZSBmaXJzdCB0aW1lLFxyXG4gICAgICogYW5kIGJlZm9yZSBhbnkgb2YgdGhlIHZpZXcgb3IgY29udGVudCBjaGlsZHJlbiBoYXZlIGJlZW4gY2hlY2tlZC5cclxuICAgICAqIEl0IGlzIGludm9rZWQgb25seSBvbmNlIHdoZW4gdGhlIGRpcmVjdGl2ZSBpcyBpbnN0YW50aWF0ZWQuXHJcbiAgICAgKlxyXG4gICAgICogQG1lbWJlcm9mIEFjZUNvbXBvbmVudFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICAgICAgc3VwZXIubmdPbkluaXQoKTtcclxuXHJcbiAgICAgICAgY29uc3QgaG9zdEVsZW1lbnQgPSAodGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQpLmNoaWxkcmVuWzBdIGFzIEhUTUxFbGVtZW50O1xyXG5cclxuICAgICAgICB0aGlzLmVkaXRvciA9IGVkaXQoaG9zdEVsZW1lbnQpO1xyXG4gICAgICAgIHRoaXMuZWRpdG9yLnNldFNob3dQcmludE1hcmdpbihmYWxzZSk7XHJcbiAgICAgICAgdGhpcy5zZXRFZGl0b3JUaGVtZSh0aGlzLl90aGVtZSk7XHJcbiAgICAgICAgdGhpcy5zZXRFZGl0b3JUeXBlKHRoaXMuX2VkaXRvclR5cGUpO1xyXG4gICAgICAgIHRoaXMuc2V0RWRpdG9yUmVhZE9ubHkodGhpcy5yZWFkb25seSk7XHJcbiAgICAgICAgdGhpcy5zZXRFZGl0b3JWYWx1ZSh0aGlzLnZhbHVlKTtcclxuICAgICAgICB0aGlzLmVkaXRvci5vbignY2hhbmdlJywgZSA9PiB0aGlzLm9uRWRpdG9yQ2hhbmdlKGUpKTtcclxuICAgICAgICB0aGlzLmVkaXRvci5vbigncGFzdGUnLCBlID0+IHRoaXMub25FZGl0b3JDaGFuZ2UoZSkpO1xyXG4gICAgICAgIHRoaXMuZWRpdG9yLmNvbW1hbmRzLmFkZENvbW1hbmQoe1xyXG4gICAgICAgICAgICBuYW1lOiAnZm9ybWF0RG9jdW1lbnRDb21tYW5kJyxcclxuICAgICAgICAgICAgYmluZEtleTogeyB3aW46ICdDdHJsLVNoaWZ0LUYnLCBtYWM6ICdDb21tYW5kLVNoaWZ0LUYnIH0sXHJcbiAgICAgICAgICAgIGV4ZWM6IChlOiBFZGl0b3IpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZm9ybWF0RG9jdW1lbnQoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQSBjYWxsYmFjayBtZXRob2QgdGhhdCBpcyBpbnZva2VkIGltbWVkaWF0ZWx5IGFmdGVyXHJcbiAgICAgKiBBbmd1bGFyIGhhcyBjb21wbGV0ZWQgaW5pdGlhbGl6YXRpb24gb2YgYSBjb21wb25lbnQncyB2aWV3LlxyXG4gICAgICogSXQgaXMgaW52b2tlZCBvbmx5IG9uY2Ugd2hlbiB0aGUgdmlldyBpcyBpbnN0YW50aWF0ZWQuXHJcbiAgICAgKlxyXG4gICAgICogQG1lbWJlcm9mIEFjZUNvbXBvbmVudFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgICAgIHN1cGVyLm5nQWZ0ZXJWaWV3SW5pdCgpO1xyXG4gICAgICAgIGlmICghdGhpcy5vYnNlcnZlVmlzaWJpbGl0eU9mKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMub2JzZXJ2ZVZpc2liaWxpdHkodGhpcy5vYnNlcnZlVmlzaWJpbGl0eU9mKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEEgY2FsbGJhY2sgbWV0aG9kIHRoYXQgcGVyZm9ybXMgY3VzdG9tIGNsZWFuLXVwLCBpbnZva2VkIGltbWVkaWF0ZWx5XHJcbiAgICAgKiBhZnRlciBhIGRpcmVjdGl2ZSwgcGlwZSwgb3Igc2VydmljZSBpbnN0YW5jZSBpcyBkZXN0cm95ZWQuXHJcbiAgICAgKlxyXG4gICAgICogQG1lbWJlcm9mIEFjZUNvbXBvbmVudFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKSB7XHJcbiAgICAgICAgc3VwZXIubmdPbkRlc3Ryb3koKTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuX29ic2VydmVyKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX29ic2VydmVyLmRpc2Nvbm5lY3QoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPYnNlcnZlcyB0aGUgdmlzaWJpbGl0eSBvZiB0aGUgZWxlbWVudHMgaW4gdGhlIHF1ZXJ5IHN0cmluZyxcclxuICAgICAqIGFuZCBpZiB0aGV5IGFyZSB2aXNpYmxlLCBpdCB3aWxsIHRyaWdnZXIgYW4gZWRpdG9yIHJlc2l6ZS5cclxuICAgICAqIFRoaXMgaXMgcmVxdWlyZWQgdG8gZml4IGEgcHJvYmxlbSBpbiB0aGUgQUNFIGVkaXRvciB3aGVuXHJcbiAgICAgKiBzZXRWYWx1ZSBkb2Vzbid0IHdvcmsgaWYgdGhlIGVkaXRvciBpcyBoaWRkZW4uXHJcbiAgICAgKlxyXG4gICAgICogU2VlIGFsc28gaHR0cHM6Ly9naXRodWIuY29tL2FqYXhvcmcvYWNlL2lzc3Vlcy8zMDcwLlxyXG4gICAgICogU2VlIGFsc28gaHR0cHM6Ly9naXRodWIuY29tL1N0YXJjb3VudGVyL0NvbnRlbnQvY29tbWl0LzkxYTc1N2Q4NzUwNTIzNDMxZmMxNjM3ZmRmNTc0MDlkMGZjYjEzZGIuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHF1ZXJ5U3RyaW5nXHJcbiAgICAgKiBAbWVtYmVyb2YgU2NyaXB0RWRpdG9yQ29tcG9uZW50XHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBvYnNlcnZlVmlzaWJpbGl0eShxdWVyeVN0cmluZ3M6IHN0cmluZyB8IHN0cmluZ1tdKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKHRoaXMuX29ic2VydmVyKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX29ic2VydmVyLmRpc2Nvbm5lY3QoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2YgcXVlcnlTdHJpbmdzID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICBxdWVyeVN0cmluZ3MgPSBbcXVlcnlTdHJpbmdzXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuX29ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIobXV0YXRpb25zID0+IHtcclxuICAgICAgICAgICAgY29uc3QgY2hhbmdlZFRhcmdldHM6IE5vZGVbXSA9IFtdO1xyXG5cclxuICAgICAgICAgICAgbXV0YXRpb25zLmZvckVhY2gobXV0YXRpb25SZWNvcmQgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKGNoYW5nZWRUYXJnZXRzLmZpbmRJbmRleChlID0+IGUgPT09IG11dGF0aW9uUmVjb3JkLnRhcmdldCkgPCAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY2hhbmdlZFRhcmdldHMucHVzaChtdXRhdGlvblJlY29yZC50YXJnZXQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIGNoYW5nZWRUYXJnZXRzLmZvckVhY2godCA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5faXNBY2VWaXNpYmxlKHQgYXMgRWxlbWVudCkgJiYgdGhpcy5lZGl0b3IpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmVkaXRvci5yZXNpemUodHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IHF1ZXJ5U3RyaW5nIG9mIHF1ZXJ5U3RyaW5ncykge1xyXG4gICAgICAgICAgICBjb25zdCBxdWVyeSA9IHRvcC5kb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHF1ZXJ5U3RyaW5nKTtcclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBxdWVyeS5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fb2JzZXJ2ZXIub2JzZXJ2ZShxdWVyeVtpXSwgeyBhdHRyaWJ1dGVzOiB0cnVlLCBhdHRyaWJ1dGVGaWx0ZXI6IFsnc3R5bGUnXSB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEZvcm1hdHMgdGhlIEpTT04gZG9jdW1lbnQgaW5zaWRlIHRoZSBlZGl0b3IuXHJcbiAgICAgKlxyXG4gICAgICogQHByb3RlY3RlZFxyXG4gICAgICogQHJldHVybnNcclxuICAgICAqIEBtZW1iZXJvZiBBY2VDb21wb25lbnRcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGZvcm1hdERvY3VtZW50KCkge1xyXG4gICAgICAgIGlmICghdGhpcy5lZGl0b3IpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMuZWRpdG9yVHlwZS50b0xvd2VyQ2FzZSgpID09PSAnanNvbicpIHtcclxuICAgICAgICAgICAgbGV0IHN0cmluZ1ZhbHVlID0gdGhpcy5lZGl0b3IuZ2V0VmFsdWUoKTtcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG9iamVjdFZhbHVlID0gSlNPTi5wYXJzZShzdHJpbmdWYWx1ZSk7XHJcbiAgICAgICAgICAgICAgICBzdHJpbmdWYWx1ZSA9IHRoaXMuX2dldEZvcm1hdHRlZEpzb24ob2JqZWN0VmFsdWUpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5lZGl0b3Iuc2V0VmFsdWUoc3RyaW5nVmFsdWUpO1xyXG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgICAgICAgICAgLy8gdG9vIGJhZCB3ZSBjb3VsZCBub3QgZm9ybWF0XHJcbiAgICAgICAgICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbi5ub3RpZnlXYXJuaW5nKGVycm9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFNldHMgdGhlIHZhbHVlIG9mIHRoZSB1bmRlcmx5aW5nIGVkaXRvci5cclxuICAgICAqXHJcbiAgICAgKiBAcHJvdGVjdGVkXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZyB8IHt9IHwgbnVsbH0gdmFsdWVcclxuICAgICAqIEBtZW1iZXJvZiBWYWx1ZUVkaXRvckJhc2VcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIHNldEVkaXRvclZhbHVlKHZhbHVlOiBzdHJpbmcgfCB7fSB8IG51bGwpOiB2b2lkIHtcclxuICAgICAgICBpZiAoIXRoaXMuZWRpdG9yKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBzdHJpbmdWYWx1ZSA9ICcnO1xyXG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX3ZhbHVlSXNPYmplY3QgPSB0cnVlO1xyXG4gICAgICAgICAgICBzdHJpbmdWYWx1ZSA9IHRoaXMuX2dldEZvcm1hdHRlZEpzb24odmFsdWUhKTtcclxuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgICAgICAgaWYgKHZhbHVlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl92YWx1ZUlzT2JqZWN0ID0gZmFsc2U7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgc3RyaW5nVmFsdWUgPSB2YWx1ZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBzdHJpbmdWYWx1ZSA9IHZhbHVlICYmIHZhbHVlLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmVkaXRvci5zZXRWYWx1ZShzdHJpbmdWYWx1ZSB8fCAnJyk7XHJcbiAgICAgICAgdGhpcy5lZGl0b3IuY2xlYXJTZWxlY3Rpb24oKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldHMgdGhlIHVuZGVybHlpbmcgZWRpdG9yJ3MgdmFsdWUuXHJcbiAgICAgKlxyXG4gICAgICogQHByb3RlY3RlZFxyXG4gICAgICogQHJldHVybnMge3N0cmluZyB8IHt9IHwgbnVsbH0gVGhlIHdpZGdldCB2YWx1ZS5cclxuICAgICAqIEBtZW1iZXJvZiBWYWx1ZUVkaXRvckJhc2VcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGdldEVkaXRvclZhbHVlKCk6IHN0cmluZyB8IHt9IHwgbnVsbCB7XHJcbiAgICAgICAgaWYgKCF0aGlzLmVkaXRvcikge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHN0cmluZ1ZhbHVlID0gdGhpcy5lZGl0b3IuZ2V0VmFsdWUoKTtcclxuICAgICAgICBpZiAodGhpcy5fdmFsdWVJc09iamVjdCkge1xyXG4gICAgICAgICAgICBpZiAoIXN0cmluZ1ZhbHVlKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nVmFsdWU7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBvYmplY3RWYWx1ZSA9IEpTT04ucGFyc2Uoc3RyaW5nVmFsdWUpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdFZhbHVlO1xyXG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1ZhbHVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gc3RyaW5nVmFsdWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXaGVuIG92ZXJyaWRkZW4gaW4gYSBkZXJpdmVkIGNsYXNzLCB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgd2hlbiB0aGUgcmVhZCBvbmx5IHN0YXRlIGNoYW5nZXMuXHJcbiAgICAgKlxyXG4gICAgICogQHByb3RlY3RlZFxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvbGRWYWx1ZSBUaGUgb2xkIHZhbHVlLlxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBuZXdWYWx1ZSBUaGUgbmV3IHZhbHVlLlxyXG4gICAgICpcclxuICAgICAqIEBtZW1iZXJvZiBFZGl0b3JCYXNlXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBvblJlYWRPbmx5Q2hhbmdlZChvbGRWYWx1ZTogYm9vbGVhbiwgbmV3VmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgICAgICBpZiAodGhpcy5lZGl0b3IpIHtcclxuICAgICAgICAgICAgdGhpcy5zZXRFZGl0b3JSZWFkT25seShuZXdWYWx1ZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2V0cyB0aGUgcmVhZG9ubHkgc3RhdGUgb2YgdGhlIGVkaXRvci5cclxuICAgICAqXHJcbiAgICAgKiBAcHJvdGVjdGVkXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHZhbHVlXHJcbiAgICAgKiBAbWVtYmVyb2YgQWNlQ29tcG9uZW50XHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBzZXRFZGl0b3JSZWFkT25seSh2YWx1ZTogYm9vbGVhbikge1xyXG4gICAgICAgIGlmICh0aGlzLmVkaXRvcikge1xyXG4gICAgICAgICAgICB0aGlzLmVkaXRvci5zZXRSZWFkT25seSh2YWx1ZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2V0cyB0aGUgZWRpdG9yIHRoZW1lLlxyXG4gICAgICpcclxuICAgICAqIEBwcm90ZWN0ZWRcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0aGVtZVxyXG4gICAgICogQG1lbWJlcm9mIEFjZUNvbXBvbmVudFxyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgc2V0RWRpdG9yVGhlbWUodGhlbWU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLmVkaXRvciAmJiB0aGVtZSkge1xyXG4gICAgICAgICAgICB0aGlzLmVkaXRvci5zZXRUaGVtZShgYWNlL3RoZW1lLyR7dGhlbWV9YCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2V0cyB0aGUgZWRpdG9yIHR5cGUuXHJcbiAgICAgKlxyXG4gICAgICogQHByb3RlY3RlZFxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGVkaXRvclR5cGVcclxuICAgICAqIEBtZW1iZXJvZiBBY2VDb21wb25lbnRcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIHNldEVkaXRvclR5cGUoZWRpdG9yVHlwZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKHRoaXMuZWRpdG9yICYmIGVkaXRvclR5cGUpIHtcclxuICAgICAgICAgICAgY29uc3QgbW9kZSA9IHRoaXMuZ2V0RWRpdG9yTW9kZShlZGl0b3JUeXBlKTtcclxuICAgICAgICAgICAgdGhpcy5lZGl0b3IuZ2V0U2Vzc2lvbigpLnNldE1vZGUoYGFjZS9tb2RlLyR7bW9kZX1gKTtcclxuICAgICAgICAgICAgdGhpcy5lZGl0b3IuJGJsb2NrU2Nyb2xsaW5nID0gSW5maW5pdHk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgZWRpdG9yIG1vZGUgYmFzZWQgb24gdGhlIHByb3ZpZGVkIGVkaXRvciB0eXBlLlxyXG4gICAgICpcclxuICAgICAqIEBwcm90ZWN0ZWRcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBlZGl0b3JUeXBlIFRoZSBlZGl0b3IgdHlwZS5cclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XHJcbiAgICAgKiBAbWVtYmVyb2YgQWNlQ29tcG9uZW50XHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBnZXRFZGl0b3JNb2RlKGVkaXRvclR5cGU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIGVkaXRvclR5cGU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBVcGRhdGVzIHRoZSB1bmRlcmx5aW5nIGVkaXRvciB3aXRoIHRoZSBwcm92aWRlZCB2YWx1ZS5cclxuICAgICAqXHJcbiAgICAgKiBAcHJvdGVjdGVkXHJcbiAgICAgKiBAcGFyYW0ge1RWYWx1ZX0gdmFsdWUgVGhlIHZhbHVlIHRvIGJlIHNldCBpbiB0aGUgdW5kZXJseWluZyBjb21wb25lbnQuXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICAgICAqIEBtZW1iZXJvZiBBY2VDb21wb25lbnRcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIHVwZGF0ZUVkaXRvcih2YWx1ZTogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICAgICAgdmFsdWUgPSB2YWx1ZSB8fCAnJztcclxuICAgICAgICByZXR1cm4gc3VwZXIudXBkYXRlRWRpdG9yKHZhbHVlKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9nZXRGb3JtYXR0ZWRKc29uKG9iajoge30pIHtcclxuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCA0KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9pc0FjZVZpc2libGUoZWxlbWVudDogRWxlbWVudCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGNvbnN0IHN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XHJcbiAgICAgICAgcmV0dXJuICEoc3R5bGUuZGlzcGxheSA9PT0gJ25vbmUnKVxyXG4gICAgfVxyXG59XHJcbiJdfQ==