UNPKG

@ckeditor/ckeditor5-angular

Version:

Official Angular 2+ component for CKEditor 5 – the best browser-based rich text editor.

508 lines 36.4 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import * as tslib_1 from "tslib"; /** * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved. * For licensing, see LICENSE.md. */ import { Component, Input, Output, NgZone, EventEmitter, forwardRef, ElementRef } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; var CKEditorComponent = /** @class */ (function () { function CKEditorComponent(elementRef, ngZone) { /** * The configuration of the editor. * See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editorconfig-EditorConfig.html * to learn more. */ this.config = {}; /** * The initial data of the editor. Useful when not using the ngModel. * See https://angular.io/api/forms/NgModel to learn more. */ this.data = ''; /** * Tag name of the editor component. * * The default tag is 'div'. */ this.tagName = 'div'; /** * Fires when the editor is ready. It corresponds with the `editor#ready` * https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html#event-ready * event. */ this.ready = new EventEmitter(); /** * Fires when the content of the editor has changed. It corresponds with the `editor.model.document#change` * https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_model_document-Document.html#event-change * event. */ this.change = new EventEmitter(); /** * Fires when the editing view of the editor is blurred. It corresponds with the `editor.editing.view.document#blur` * https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_view_document-Document.html#event-event:blur * event. */ this.blur = new EventEmitter(); /** * Fires when the editing view of the editor is focused. It corresponds with the `editor.editing.view.document#focus` * https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_view_document-Document.html#event-event:focus * event. */ this.focus = new EventEmitter(); /** * The instance of the editor created by this component. */ this.editorInstance = null; /** * If the component is read–only before the editor instance is created, it remembers that state, * so the editor can become read–only once it is ready. */ this.initialIsDisabled = false; this.ngZone = ngZone; this.elementRef = elementRef; } Object.defineProperty(CKEditorComponent.prototype, "disabled", { get: /** * @return {?} */ function () { if (this.editorInstance) { return this.editorInstance.isReadOnly; } return this.initialIsDisabled; }, /** * When set `true`, the editor becomes read-only. * See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html#member-isReadOnly * to learn more. */ set: /** * When set `true`, the editor becomes read-only. * See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html#member-isReadOnly * to learn more. * @param {?} isDisabled * @return {?} */ function (isDisabled) { this.setDisabledState(isDisabled); }, enumerable: true, configurable: true }); // Implementing the AfterViewInit interface. // Implementing the AfterViewInit interface. /** * @return {?} */ CKEditorComponent.prototype.ngAfterViewInit = // Implementing the AfterViewInit interface. /** * @return {?} */ function () { var _this = this; this.ngZone.runOutsideAngular((/** * @return {?} */ function () { _this.createEditor(); })); }; // Implementing the OnDestroy interface. // Implementing the OnDestroy interface. /** * @return {?} */ CKEditorComponent.prototype.ngOnDestroy = // Implementing the OnDestroy interface. /** * @return {?} */ function () { if (this.editorInstance) { this.editorInstance.destroy(); this.editorInstance = null; } }; // Implementing the ControlValueAccessor interface (only when binding to ngModel). // Implementing the ControlValueAccessor interface (only when binding to ngModel). /** * @param {?} value * @return {?} */ CKEditorComponent.prototype.writeValue = // Implementing the ControlValueAccessor interface (only when binding to ngModel). /** * @param {?} value * @return {?} */ function (value) { // This method is called with the `null` value when the form resets. // A component's responsibility is to restore to the initial state. if (value === null) { value = ''; } // If already initialized. if (this.editorInstance) { this.editorInstance.setData(value); } // If not, wait for it to be ready; store the data. else { this.data = value; // If the editor element is already available, then update its content. // If the ngModel is used then the editor element should be updated directly here. if (this.editorElement) { this.editorElement.innerHTML = this.data; } } }; // Implementing the ControlValueAccessor interface (only when binding to ngModel). // Implementing the ControlValueAccessor interface (only when binding to ngModel). /** * @param {?} callback * @return {?} */ CKEditorComponent.prototype.registerOnChange = // Implementing the ControlValueAccessor interface (only when binding to ngModel). /** * @param {?} callback * @return {?} */ function (callback) { this.cvaOnChange = callback; }; // Implementing the ControlValueAccessor interface (only when binding to ngModel). // Implementing the ControlValueAccessor interface (only when binding to ngModel). /** * @param {?} callback * @return {?} */ CKEditorComponent.prototype.registerOnTouched = // Implementing the ControlValueAccessor interface (only when binding to ngModel). /** * @param {?} callback * @return {?} */ function (callback) { this.cvaOnTouched = callback; }; // Implementing the ControlValueAccessor interface (only when binding to ngModel). // Implementing the ControlValueAccessor interface (only when binding to ngModel). /** * @param {?} isDisabled * @return {?} */ CKEditorComponent.prototype.setDisabledState = // Implementing the ControlValueAccessor interface (only when binding to ngModel). /** * @param {?} isDisabled * @return {?} */ function (isDisabled) { // If already initialized if (this.editorInstance) { this.editorInstance.isReadOnly = isDisabled; } // If not, wait for it to be ready; store the state. else { this.initialIsDisabled = isDisabled; } }; /** * Creates the editor instance, sets initial editor data, then integrates * the editor with the Angular component. This method does not use the `editor.setData()` * because of the issue in the collaboration mode (#6). */ /** * Creates the editor instance, sets initial editor data, then integrates * the editor with the Angular component. This method does not use the `editor.setData()` * because of the issue in the collaboration mode (#6). * @private * @return {?} */ CKEditorComponent.prototype.createEditor = /** * Creates the editor instance, sets initial editor data, then integrates * the editor with the Angular component. This method does not use the `editor.setData()` * because of the issue in the collaboration mode (#6). * @private * @return {?} */ function () { var _this = this; /** @type {?} */ var element = document.createElement(this.tagName); this.editorElement = element; if (this.data && this.config.initialData) { throw new Error('Editor data should be provided either using `config.initialData` or `data` properties.'); } // Merge two possible ways of providing data into the `config.initialData` field. /** @type {?} */ var config = tslib_1.__assign({}, this.config, { initialData: this.config.initialData || this.data || '' }); this.elementRef.nativeElement.appendChild(element); return (/** @type {?} */ (this.editor)).create(element, config) .then((/** * @param {?} editor * @return {?} */ function (editor) { _this.editorInstance = editor; if (_this.initialIsDisabled) { editor.isReadOnly = _this.initialIsDisabled; } _this.ngZone.run((/** * @return {?} */ function () { _this.ready.emit(editor); })); _this.setUpEditorEvents(editor); })) .catch((/** * @param {?} err * @return {?} */ function (err) { console.error(err.stack); })); }; /** * Integrates the editor with the component by attaching related event listeners. */ /** * Integrates the editor with the component by attaching related event listeners. * @private * @param {?} editor * @return {?} */ CKEditorComponent.prototype.setUpEditorEvents = /** * Integrates the editor with the component by attaching related event listeners. * @private * @param {?} editor * @return {?} */ function (editor) { var _this = this; /** @type {?} */ var modelDocument = editor.model.document; /** @type {?} */ var viewDocument = editor.editing.view.document; modelDocument.on('change:data', (/** * @param {?} evt * @return {?} */ function (evt) { _this.ngZone.run((/** * @return {?} */ function () { if (_this.cvaOnChange) { /** @type {?} */ var data = editor.getData(); _this.cvaOnChange(data); } _this.change.emit({ event: evt, editor: editor }); })); })); viewDocument.on('focus', (/** * @param {?} evt * @return {?} */ function (evt) { _this.ngZone.run((/** * @return {?} */ function () { _this.focus.emit({ event: evt, editor: editor }); })); })); viewDocument.on('blur', (/** * @param {?} evt * @return {?} */ function (evt) { _this.ngZone.run((/** * @return {?} */ function () { if (_this.cvaOnTouched) { _this.cvaOnTouched(); } _this.blur.emit({ event: evt, editor: editor }); })); })); }; CKEditorComponent.decorators = [ { type: Component, args: [{ selector: 'ckeditor', template: '<ng-template></ng-template>', // Integration with @angular/forms. providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((/** * @return {?} */ function () { return CKEditorComponent; })), multi: true, } ] }] } ]; /** @nocollapse */ CKEditorComponent.ctorParameters = function () { return [ { type: ElementRef }, { type: NgZone } ]; }; CKEditorComponent.propDecorators = { editor: [{ type: Input }], config: [{ type: Input }], data: [{ type: Input }], tagName: [{ type: Input }], disabled: [{ type: Input }], ready: [{ type: Output }], change: [{ type: Output }], blur: [{ type: Output }], focus: [{ type: Output }] }; return CKEditorComponent; }()); export { CKEditorComponent }; if (false) { /** * The reference to the DOM element created by the component. * @type {?} * @private */ CKEditorComponent.prototype.elementRef; /** * The constructor of the editor to be used for the instance of the component. * It can be e.g. the `ClassicEditorBuild`, `InlineEditorBuild` or some custom editor. * @type {?} */ CKEditorComponent.prototype.editor; /** * The configuration of the editor. * See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editorconfig-EditorConfig.html * to learn more. * @type {?} */ CKEditorComponent.prototype.config; /** * The initial data of the editor. Useful when not using the ngModel. * See https://angular.io/api/forms/NgModel to learn more. * @type {?} */ CKEditorComponent.prototype.data; /** * Tag name of the editor component. * * The default tag is 'div'. * @type {?} */ CKEditorComponent.prototype.tagName; /** * Fires when the editor is ready. It corresponds with the `editor#ready` * https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html#event-ready * event. * @type {?} */ CKEditorComponent.prototype.ready; /** * Fires when the content of the editor has changed. It corresponds with the `editor.model.document#change` * https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_model_document-Document.html#event-change * event. * @type {?} */ CKEditorComponent.prototype.change; /** * Fires when the editing view of the editor is blurred. It corresponds with the `editor.editing.view.document#blur` * https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_view_document-Document.html#event-event:blur * event. * @type {?} */ CKEditorComponent.prototype.blur; /** * Fires when the editing view of the editor is focused. It corresponds with the `editor.editing.view.document#focus` * https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_view_document-Document.html#event-event:focus * event. * @type {?} */ CKEditorComponent.prototype.focus; /** * The instance of the editor created by this component. * @type {?} */ CKEditorComponent.prototype.editorInstance; /** * If the component is read–only before the editor instance is created, it remembers that state, * so the editor can become read–only once it is ready. * @type {?} * @private */ CKEditorComponent.prototype.initialIsDisabled; /** * An instance of https://angular.io/api/core/NgZone to allow the interaction with the editor * withing the Angular event loop. * @type {?} * @private */ CKEditorComponent.prototype.ngZone; /** * A callback executed when the content of the editor changes. Part of the * `ControlValueAccessor` (https://angular.io/api/forms/ControlValueAccessor) interface. * * Note: Unset unless the component uses the `ngModel`. * @type {?} * @private */ CKEditorComponent.prototype.cvaOnChange; /** * A callback executed when the editor has been blurred. Part of the * `ControlValueAccessor` (https://angular.io/api/forms/ControlValueAccessor) interface. * * Note: Unset unless the component uses the `ngModel`. * @type {?} * @private */ CKEditorComponent.prototype.cvaOnTouched; /** * Reference to the source element used by the editor. * @type {?} * @private */ CKEditorComponent.prototype.editorElement; } /** * @record */ export function BlurEvent() { } if (false) { /** @type {?} */ BlurEvent.prototype.event; /** @type {?} */ BlurEvent.prototype.editor; } /** * @record */ export function FocusEvent() { } if (false) { /** @type {?} */ FocusEvent.prototype.event; /** @type {?} */ FocusEvent.prototype.editor; } /** * @record */ export function ChangeEvent() { } if (false) { /** @type {?} */ ChangeEvent.prototype.event; /** @type {?} */ ChangeEvent.prototype.editor; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2tlZGl0b3IuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vQGNrZWRpdG9yL2NrZWRpdG9yNS1hbmd1bGFyLyIsInNvdXJjZXMiOlsiY2tlZGl0b3IuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUtBLE9BQU8sRUFDTixTQUFTLEVBQ1QsS0FBSyxFQUNMLE1BQU0sRUFDTixNQUFNLEVBQ04sWUFBWSxFQUNaLFVBQVUsRUFFVixVQUFVLEVBQ1YsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUVOLGlCQUFpQixFQUNqQixNQUFNLGdCQUFnQixDQUFDO0FBSXhCO0lBZ0lDLDJCQUFhLFVBQXNCLEVBQUUsTUFBYzs7Ozs7O1FBbEcxQyxXQUFNLEdBQXFCLEVBQUUsQ0FBQzs7Ozs7UUFNOUIsU0FBSSxHQUFHLEVBQUUsQ0FBQzs7Ozs7O1FBT1YsWUFBTyxHQUFHLEtBQUssQ0FBQzs7Ozs7O1FBd0JmLFVBQUssR0FBRyxJQUFJLFlBQVksRUFBb0IsQ0FBQzs7Ozs7O1FBTzdDLFdBQU0sR0FBOEIsSUFBSSxZQUFZLEVBQWUsQ0FBQzs7Ozs7O1FBT3BFLFNBQUksR0FBNEIsSUFBSSxZQUFZLEVBQWEsQ0FBQzs7Ozs7O1FBTzlELFVBQUssR0FBNkIsSUFBSSxZQUFZLEVBQWMsQ0FBQzs7OztRQUtwRSxtQkFBYyxHQUE0QixJQUFJLENBQUM7Ozs7O1FBTTlDLHNCQUFpQixHQUFHLEtBQUssQ0FBQztRQThCakMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7SUFDOUIsQ0FBQztJQWpGRCxzQkFBYSx1Q0FBUTs7OztRQUlyQjtZQUNDLElBQUssSUFBSSxDQUFDLGNBQWMsRUFBRztnQkFDMUIsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQzthQUN0QztZQUVELE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDO1FBQy9CLENBQUM7UUFm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Q0FBOEM7Ozs7Ozs7SUFPOUMsbUNBQXVDOzs7Ozs7SUFNdkMsaUNBQW1COzs7Ozs7O0lBT25CLG9DQUF5Qjs7Ozs7OztJQXdCekIsa0NBQXVEOzs7Ozs7O0lBT3ZELG1DQUE4RTs7Ozs7OztJQU85RSxpQ0FBd0U7Ozs7Ozs7SUFPeEUsa0NBQTJFOzs7OztJQUszRSwyQ0FBc0Q7Ozs7Ozs7SUFNdEQsOENBQWtDOzs7Ozs7O0lBTWxDLG1DQUF1Qjs7Ozs7Ozs7O0lBUXZCLHdDQUErQzs7Ozs7Ozs7O0lBUS9DLHlDQUFrQzs7Ozs7O0lBS2xDLDBDQUFvQzs7Ozs7QUFpSnJDLCtCQUdDOzs7SUFGQSwwQkFBbUM7O0lBQ25DLDJCQUF5Qjs7Ozs7QUFHMUIsZ0NBR0M7OztJQUZBLDJCQUFvQzs7SUFDcEMsNEJBQXlCOzs7OztBQUcxQixpQ0FHQzs7O0lBRkEsNEJBQTBDOztJQUMxQyw2QkFBeUIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlIENvcHlyaWdodCAoYykgMjAwMy0yMDE5LCBDS1NvdXJjZSAtIEZyZWRlcmljbyBLbmFiYmVuLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogRm9yIGxpY2Vuc2luZywgc2VlIExJQ0VOU0UubWQuXG4gKi9cblxuaW1wb3J0IHtcblx0Q29tcG9uZW50LFxuXHRJbnB1dCxcblx0T3V0cHV0LFxuXHROZ1pvbmUsXG5cdEV2ZW50RW1pdHRlcixcblx0Zm9yd2FyZFJlZixcblx0QWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95LFxuXHRFbGVtZW50UmVmXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQge1xuXHRDb250cm9sVmFsdWVBY2Nlc3Nvcixcblx0TkdfVkFMVUVfQUNDRVNTT1Jcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBDS0VkaXRvcjUgfSBmcm9tICcuL2NrZWRpdG9yJztcblxuQENvbXBvbmVudCgge1xuXHRzZWxlY3RvcjogJ2NrZWRpdG9yJyxcblx0dGVtcGxhdGU6ICc8bmctdGVtcGxhdGU+PC9uZy10ZW1wbGF0ZT4nLFxuXG5cdC8vIEludGVncmF0aW9uIHdpdGggQGFuZ3VsYXIvZm9ybXMuXG5cdHByb3ZpZGVyczogW1xuXHRcdHtcblx0XHRcdHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuXHRcdFx0dXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoICgpID0+IENLRWRpdG9yQ29tcG9uZW50ICksXG5cdFx0XHRtdWx0aTogdHJ1ZSxcblx0XHR9XG5cdF1cbn0gKVxuZXhwb3J0IGNsYXNzIENLRWRpdG9yQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95LCBDb250cm9sVmFsdWVBY2Nlc3NvciB7XG5cdC8qKlxuXHQgKiBUaGUgcmVmZXJlbmNlIHRvIHRoZSBET00gZWxlbWVudCBjcmVhdGVkIGJ5IHRoZSBjb21wb25lbnQuXG5cdCAqL1xuXHRwcml2YXRlIGVsZW1lbnRSZWYhOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcblxuXHQvKipcblx0ICogVGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBlZGl0b3IgdG8gYmUgdXNlZCBmb3IgdGhlIGluc3RhbmNlIG9mIHRoZSBjb21wb25lbnQuXG5cdCAqIEl0IGNhbiBiZSBlLmcuIHRoZSBgQ2xhc3NpY0VkaXRvckJ1aWxkYCwgYElubGluZUVkaXRvckJ1aWxkYCBvciBzb21lIGN1c3RvbSBlZGl0b3IuXG5cdCAqL1xuXHRASW5wdXQoKSBlZGl0b3I/OiBDS0VkaXRvcjUuRWRpdG9yQ29uc3RydWN0b3I7XG5cblx0LyoqXG5cdCAqIFRoZSBjb25maWd1cmF0aW9uIG9mIHRoZSBlZGl0b3IuXG5cdCAqIFNlZSBodHRwczovL2NrZWRpdG9yLmNvbS9kb2NzL2NrZWRpdG9yNS9sYXRlc3QvYXBpL21vZHVsZV9jb3JlX2VkaXRvcl9lZGl0b3Jjb25maWctRWRpdG9yQ29uZmlnLmh0bWxcblx0ICogdG8gbGVhcm4gbW9yZS5cblx0ICovXG5cdEBJbnB1dCgpIGNvbmZpZzogQ0tFZGl0b3I1LkNvbmZpZyA9IHt9O1xuXG5cdC8qKlxuXHQgKiBUaGUgaW5pdGlhbCBkYXRhIG9mIHRoZSBlZGl0b3IuIFVzZWZ1bCB3aGVuIG5vdCB1c2luZyB0aGUgbmdNb2RlbC5cblx0ICogU2VlIGh0dHBzOi8vYW5ndWxhci5pby9hcGkvZm9ybXMvTmdNb2RlbCB0byBsZWFybiBtb3JlLlxuXHQgKi9cblx0QElucHV0KCkgZGF0YSA9ICcnO1xuXG5cdC8qKlxuXHQgKiBUYWcgbmFtZSBvZiB0aGUgZWRpdG9yIGNvbXBvbmVudC5cblx0ICpcblx0ICogVGhlIGRlZmF1bHQgdGFnIGlzICdkaXYnLlxuXHQgKi9cblx0QElucHV0KCkgdGFnTmFtZSA9ICdkaXYnO1xuXG5cdC8qKlxuXHQgKiBXaGVuIHNldCBgdHJ1ZWAsIHRoZSBlZGl0b3IgYmVjb21lcyByZWFkLW9ubHkuXG5cdCAqIFNlZSBodHRwczovL2NrZWRpdG9yLmNvbS9kb2NzL2NrZWRpdG9yNS9sYXRlc3QvYXBpL21vZHVsZV9jb3JlX2VkaXRvcl9lZGl0b3ItRWRpdG9yLmh0bWwjbWVtYmVyLWlzUmVhZE9ubHlcblx0ICogdG8gbGVhcm4gbW9yZS5cblx0ICovXG5cdEBJbnB1dCgpIHNldCBkaXNhYmxlZCggaXNEaXNhYmxlZDogYm9vbGVhbiApIHtcblx0XHR0aGlzLnNldERpc2FibGVkU3RhdGUoIGlzRGlzYWJsZWQgKTtcblx0fVxuXG5cdGdldCBkaXNhYmxlZCgpIHtcblx0XHRpZiAoIHRoaXMuZWRpdG9ySW5zdGFuY2UgKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5lZGl0b3JJbnN0YW5jZS5pc1JlYWRPbmx5O1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLmluaXRpYWxJc0Rpc2FibGVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZpcmVzIHdoZW4gdGhlIGVkaXRvciBpcyByZWFkeS4gSXQgY29ycmVzcG9uZHMgd2l0aCB0aGUgYGVkaXRvciNyZWFkeWBcblx0ICogaHR0cHM6Ly9ja2VkaXRvci5jb20vZG9jcy9ja2VkaXRvcjUvbGF0ZXN0L2FwaS9tb2R1bGVfY29yZV9lZGl0b3JfZWRpdG9yLUVkaXRvci5odG1sI2V2ZW50LXJlYWR5XG5cdCAqIGV2ZW50LlxuXHQgKi9cblx0QE91dHB1dCgpIHJlYWR5ID0gbmV3IEV2ZW50RW1pdHRlcjxDS0VkaXRvcjUuRWRpdG9yPigpO1xuXG5cdC8qKlxuXHQgKiBGaXJlcyB3aGVuIHRoZSBjb250ZW50IG9mIHRoZSBlZGl0b3IgaGFzIGNoYW5nZWQuIEl0IGNvcnJlc3BvbmRzIHdpdGggdGhlIGBlZGl0b3IubW9kZWwuZG9jdW1lbnQjY2hhbmdlYFxuXHQgKiBodHRwczovL2NrZWRpdG9yLmNvbS9kb2NzL2NrZWRpdG9yNS9sYXRlc3QvYXBpL21vZHVsZV9lbmdpbmVfbW9kZWxfZG9jdW1lbnQtRG9jdW1lbnQuaHRtbCNldmVudC1jaGFuZ2Vcblx0ICogZXZlbnQuXG5cdCAqL1xuXHRAT3V0cHV0KCkgY2hhbmdlOiBFdmVudEVtaXR0ZXI8Q2hhbmdlRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxDaGFuZ2VFdmVudD4oKTtcblxuXHQvKipcblx0ICogRmlyZXMgd2hlbiB0aGUgZWRpdGluZyB2aWV3IG9mIHRoZSBlZGl0b3IgaXMgYmx1cnJlZC4gSXQgY29ycmVzcG9uZHMgd2l0aCB0aGUgYGVkaXRvci5lZGl0aW5nLnZpZXcuZG9jdW1lbnQjYmx1cmBcblx0ICogaHR0cHM6Ly9ja2VkaXRvci5jb20vZG9jcy9ja2VkaXRvcjUvbGF0ZXN0L2FwaS9tb2R1bGVfZW5naW5lX3ZpZXdfZG9jdW1lbnQtRG9jdW1lbnQuaHRtbCNldmVudC1ldmVudDpibHVyXG5cdCAqIGV2ZW50LlxuXHQgKi9cblx0QE91dHB1dCgpIGJsdXI6IEV2ZW50RW1pdHRlcjxCbHVyRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxCbHVyRXZlbnQ+KCk7XG5cblx0LyoqXG5cdCAqIEZpcmVzIHdoZW4gdGhlIGVkaXRpbmcgdmlldyBvZiB0aGUgZWRpdG9yIGlzIGZvY3VzZWQuIEl0IGNvcnJlc3BvbmRzIHdpdGggdGhlIGBlZGl0b3IuZWRpdGluZy52aWV3LmRvY3VtZW50I2ZvY3VzYFxuXHQgKiBodHRwczovL2NrZWRpdG9yLmNvbS9kb2NzL2NrZWRpdG9yNS9sYXRlc3QvYXBpL21vZHVsZV9lbmdpbmVfdmlld19kb2N1bWVudC1Eb2N1bWVudC5odG1sI2V2ZW50LWV2ZW50OmZvY3VzXG5cdCAqIGV2ZW50LlxuXHQgKi9cblx0QE91dHB1dCgpIGZvY3VzOiBFdmVudEVtaXR0ZXI8Rm9jdXNFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyPEZvY3VzRXZlbnQ+KCk7XG5cblx0LyoqXG5cdCAqIFRoZSBpbnN0YW5jZSBvZiB0aGUgZWRpdG9yIGNyZWF0ZWQgYnkgdGhpcyBjb21wb25lbnQuXG5cdCAqL1xuXHRwdWJsaWMgZWRpdG9ySW5zdGFuY2U6IENLRWRpdG9yNS5FZGl0b3IgfCBudWxsID0gbnVsbDtcblxuXHQvKipcblx0ICogSWYgdGhlIGNvbXBvbmVudCBpcyByZWFk4oCTb25seSBiZWZvcmUgdGhlIGVkaXRvciBpbnN0YW5jZSBpcyBjcmVhdGVkLCBpdCByZW1lbWJlcnMgdGhhdCBzdGF0ZSxcblx0ICogc28gdGhlIGVkaXRvciBjYW4gYmVjb21lIHJlYWTigJNvbmx5IG9uY2UgaXQgaXMgcmVhZHkuXG5cdCAqL1xuXHRwcml2YXRlIGluaXRpYWxJc0Rpc2FibGVkID0gZmFsc2U7XG5cblx0LyoqXG5cdCAqIEFuIGluc3RhbmNlIG9mIGh0dHBzOi8vYW5ndWxhci5pby9hcGkvY29yZS9OZ1pvbmUgdG8gYWxsb3cgdGhlIGludGVyYWN0aW9uIHdpdGggdGhlIGVkaXRvclxuXHQgKiB3aXRoaW5nIHRoZSBBbmd1bGFyIGV2ZW50IGxvb3AuXG5cdCAqL1xuXHRwcml2YXRlIG5nWm9uZTogTmdab25lO1xuXG5cdC8qKlxuXHQgKiBBIGNhbGxiYWNrIGV4ZWN1dGVkIHdoZW4gdGhlIGNvbnRlbnQgb2YgdGhlIGVkaXRvciBjaGFuZ2VzLiBQYXJ0IG9mIHRoZVxuXHQgKiBgQ29udHJvbFZhbHVlQWNjZXNzb3JgIChodHRwczovL2FuZ3VsYXIuaW8vYXBpL2Zvcm1zL0NvbnRyb2xWYWx1ZUFjY2Vzc29yKSBpbnRlcmZhY2UuXG5cdCAqXG5cdCAqIE5vdGU6IFVuc2V0IHVubGVzcyB0aGUgY29tcG9uZW50IHVzZXMgdGhlIGBuZ01vZGVsYC5cblx0ICovXG5cdHByaXZhdGUgY3ZhT25DaGFuZ2U/OiAoIGRhdGE6IHN0cmluZyApID0+IHZvaWQ7XG5cblx0LyoqXG5cdCAqIEEgY2FsbGJhY2sgZXhlY3V0ZWQgd2hlbiB0aGUgZWRpdG9yIGhhcyBiZWVuIGJsdXJyZWQuIFBhcnQgb2YgdGhlXG5cdCAqIGBDb250cm9sVmFsdWVBY2Nlc3NvcmAgKGh0dHBzOi8vYW5ndWxhci5pby9hcGkvZm9ybXMvQ29udHJvbFZhbHVlQWNjZXNzb3IpIGludGVyZmFjZS5cblx0ICpcblx0ICogTm90ZTogVW5zZXQgdW5sZXNzIHRoZSBjb21wb25lbnQgdXNlcyB0aGUgYG5nTW9kZWxgLlxuXHQgKi9cblx0cHJpdmF0ZSBjdmFPblRvdWNoZWQ/OiAoKSA9PiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBSZWZlcmVuY2UgdG8gdGhlIHNvdXJjZSBlbGVtZW50IHVzZWQgYnkgdGhlIGVkaXRvci5cblx0ICovXG5cdHByaXZhdGUgZWRpdG9yRWxlbWVudD86IEhUTUxFbGVtZW50O1xuXG5cdGNvbnN0cnVjdG9yKCBlbGVtZW50UmVmOiBFbGVtZW50UmVmLCBuZ1pvbmU6IE5nWm9uZSApIHtcblx0XHR0aGlzLm5nWm9uZSA9IG5nWm9uZTtcblx0XHR0aGlzLmVsZW1lbnRSZWYgPSBlbGVtZW50UmVmO1xuXHR9XG5cblx0Ly8gSW1wbGVtZW50aW5nIHRoZSBBZnRlclZpZXdJbml0IGludGVyZmFjZS5cblx0bmdBZnRlclZpZXdJbml0KCkge1xuXHRcdHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCAoKSA9PiB7XG5cdFx0XHR0aGlzLmNyZWF0ZUVkaXRvcigpO1xuXHRcdH0gKTtcblx0fVxuXG5cdC8vIEltcGxlbWVudGluZyB0aGUgT25EZXN0cm95IGludGVyZmFjZS5cblx0bmdPbkRlc3Ryb3koKSB7XG5cdFx0aWYgKCB0aGlzLmVkaXRvckluc3RhbmNlICkge1xuXHRcdFx0dGhpcy5lZGl0b3JJbnN0YW5jZS5kZXN0cm95KCk7XG5cdFx0XHR0aGlzLmVkaXRvckluc3RhbmNlID0gbnVsbDtcblx0XHR9XG5cdH1cblxuXHQvLyBJbXBsZW1lbnRpbmcgdGhlIENvbnRyb2xWYWx1ZUFjY2Vzc29yIGludGVyZmFjZSAob25seSB3aGVuIGJpbmRpbmcgdG8gbmdNb2RlbCkuXG5cdHdyaXRlVmFsdWUoIHZhbHVlOiBzdHJpbmcgfCBudWxsICk6IHZvaWQge1xuXHRcdC8vIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCB3aXRoIHRoZSBgbnVsbGAgdmFsdWUgd2hlbiB0aGUgZm9ybSByZXNldHMuXG5cdFx0Ly8gQSBjb21wb25lbnQncyByZXNwb25zaWJpbGl0eSBpcyB0byByZXN0b3JlIHRvIHRoZSBpbml0aWFsIHN0YXRlLlxuXHRcdGlmICggdmFsdWUgPT09IG51bGwgKSB7XG5cdFx0XHR2YWx1ZSA9ICcnO1xuXHRcdH1cblxuXHRcdC8vIElmIGFscmVhZHkgaW5pdGlhbGl6ZWQuXG5cdFx0aWYgKCB0aGlzLmVkaXRvckluc3RhbmNlICkge1xuXHRcdFx0dGhpcy5lZGl0b3JJbnN0YW5jZS5zZXREYXRhKCB2YWx1ZSApO1xuXHRcdH1cblx0XHQvLyBJZiBub3QsIHdhaXQgZm9yIGl0IHRvIGJlIHJlYWR5OyBzdG9yZSB0aGUgZGF0YS5cblx0XHRlbHNlIHtcblx0XHRcdHRoaXMuZGF0YSA9IHZhbHVlO1xuXG5cdFx0XHQvLyBJZiB0aGUgZWRpdG9yIGVsZW1lbnQgaXMgYWxyZWFkeSBhdmFpbGFibGUsIHRoZW4gdXBkYXRlIGl0cyBjb250ZW50LlxuXHRcdFx0Ly8gSWYgdGhlIG5nTW9kZWwgaXMgdXNlZCB0aGVuIHRoZSBlZGl0b3IgZWxlbWVudCBzaG91bGQgYmUgdXBkYXRlZCBkaXJlY3RseSBoZXJlLlxuXHRcdFx0aWYgKCB0aGlzLmVkaXRvckVsZW1lbnQgKSB7XG5cdFx0XHRcdHRoaXMuZWRpdG9yRWxlbWVudC5pbm5lckhUTUwgPSB0aGlzLmRhdGE7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gSW1wbGVtZW50aW5nIHRoZSBDb250cm9sVmFsdWVBY2Nlc3NvciBpbnRlcmZhY2UgKG9ubHkgd2hlbiBiaW5kaW5nIHRvIG5nTW9kZWwpLlxuXHRyZWdpc3Rlck9uQ2hhbmdlKCBjYWxsYmFjazogKCBkYXRhOiBzdHJpbmcgKSA9PiB2b2lkICk6IHZvaWQge1xuXHRcdHRoaXMuY3ZhT25DaGFuZ2UgPSBjYWxsYmFjaztcblx0fVxuXG5cdC8vIEltcGxlbWVudGluZyB0aGUgQ29udHJvbFZhbHVlQWNjZXNzb3IgaW50ZXJmYWNlIChvbmx5IHdoZW4gYmluZGluZyB0byBuZ01vZGVsKS5cblx0cmVnaXN0ZXJPblRvdWNoZWQoIGNhbGxiYWNrOiAoKSA9PiB2b2lkICk6IHZvaWQge1xuXHRcdHRoaXMuY3ZhT25Ub3VjaGVkID0gY2FsbGJhY2s7XG5cdH1cblxuXHQvLyBJbXBsZW1lbnRpbmcgdGhlIENvbnRyb2xWYWx1ZUFjY2Vzc29yIGludGVyZmFjZSAob25seSB3aGVuIGJpbmRpbmcgdG8gbmdNb2RlbCkuXG5cdHNldERpc2FibGVkU3RhdGUoIGlzRGlzYWJsZWQ6IGJvb2xlYW4gKTogdm9pZCB7XG5cdFx0Ly8gSWYgYWxyZWFkeSBpbml0aWFsaXplZFxuXHRcdGlmICggdGhpcy5lZGl0b3JJbnN0YW5jZSApIHtcblx0XHRcdHRoaXMuZWRpdG9ySW5zdGFuY2UuaXNSZWFkT25seSA9IGlzRGlzYWJsZWQ7XG5cdFx0fVxuXHRcdC8vIElmIG5vdCwgd2FpdCBmb3IgaXQgdG8gYmUgcmVhZHk7IHN0b3JlIHRoZSBzdGF0ZS5cblx0XHRlbHNlIHtcblx0XHRcdHRoaXMuaW5pdGlhbElzRGlzYWJsZWQgPSBpc0Rpc2FibGVkO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIHRoZSBlZGl0b3IgaW5zdGFuY2UsIHNldHMgaW5pdGlhbCBlZGl0b3IgZGF0YSwgdGhlbiBpbnRlZ3JhdGVzXG5cdCAqIHRoZSBlZGl0b3Igd2l0aCB0aGUgQW5ndWxhciBjb21wb25lbnQuIFRoaXMgbWV0aG9kIGRvZXMgbm90IHVzZSB0aGUgYGVkaXRvci5zZXREYXRhKClgXG5cdCAqIGJlY2F1c2Ugb2YgdGhlIGlzc3VlIGluIHRoZSBjb2xsYWJvcmF0aW9uIG1vZGUgKCM2KS5cblx0ICovXG5cdHByaXZhdGUgY3JlYXRlRWRpdG9yKCk6IFByb21pc2U8dm9pZD4ge1xuXHRcdGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCB0aGlzLnRhZ05hbWUgKTtcblx0XHR0aGlzLmVkaXRvckVsZW1lbnQgPSBlbGVtZW50O1xuXG5cdFx0aWYgKCB0aGlzLmRhdGEgJiYgdGhpcy5jb25maWcuaW5pdGlhbERhdGEgKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoICdFZGl0b3IgZGF0YSBzaG91bGQgYmUgcHJvdmlkZWQgZWl0aGVyIHVzaW5nIGBjb25maWcuaW5pdGlhbERhdGFgIG9yIGBkYXRhYCBwcm9wZXJ0aWVzLicgKTtcblx0XHR9XG5cblx0XHQvLyBNZXJnZSB0d28gcG9zc2libGUgd2F5cyBvZiBwcm92aWRpbmcgZGF0YSBpbnRvIHRoZSBgY29uZmlnLmluaXRpYWxEYXRhYCBmaWVsZC5cblx0XHRjb25zdCBjb25maWcgPSB7XG5cdFx0XHQuLi50aGlzLmNvbmZpZyxcblx0XHRcdGluaXRpYWxEYXRhOiB0aGlzLmNvbmZpZy5pbml0aWFsRGF0YSB8fCB0aGlzLmRhdGEgfHwgJydcblx0XHR9O1xuXG5cdFx0dGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuYXBwZW5kQ2hpbGQoIGVsZW1lbnQgKTtcblxuXHRcdHJldHVybiB0aGlzLmVkaXRvciEuY3JlYXRlKCBlbGVtZW50LCBjb25maWcgKVxuXHRcdFx0LnRoZW4oIGVkaXRvciA9PiB7XG5cdFx0XHRcdHRoaXMuZWRpdG9ySW5zdGFuY2UgPSBlZGl0b3I7XG5cblx0XHRcdFx0aWYgKCB0aGlzLmluaXRpYWxJc0Rpc2FibGVkICkge1xuXHRcdFx0XHRcdGVkaXRvci5pc1JlYWRPbmx5ID0gdGhpcy5pbml0aWFsSXNEaXNhYmxlZDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMubmdab25lLnJ1biggKCkgPT4ge1xuXHRcdFx0XHRcdHRoaXMucmVhZHkuZW1pdCggZWRpdG9yICk7XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHR0aGlzLnNldFVwRWRpdG9yRXZlbnRzKCBlZGl0b3IgKTtcblx0XHRcdH0gKVxuXHRcdFx0LmNhdGNoKCAoIGVycjogRXJyb3IgKSA9PiB7XG5cdFx0XHRcdGNvbnNvbGUuZXJyb3IoIGVyci5zdGFjayApO1xuXHRcdFx0fSApO1xuXHR9XG5cblx0LyoqXG5cdCAqIEludGVncmF0ZXMgdGhlIGVkaXRvciB3aXRoIHRoZSBjb21wb25lbnQgYnkgYXR0YWNoaW5nIHJlbGF0ZWQgZXZlbnQgbGlzdGVuZXJzLlxuXHQgKi9cblx0cHJpdmF0ZSBzZXRVcEVkaXRvckV2ZW50cyggZWRpdG9yOiBDS0VkaXRvcjUuRWRpdG9yICk6IHZvaWQge1xuXHRcdGNvbnN0IG1vZGVsRG9jdW1lbnQgPSBlZGl0b3IubW9kZWwuZG9jdW1lbnQ7XG5cdFx0Y29uc3Qgdmlld0RvY3VtZW50ID0gZWRpdG9yLmVkaXRpbmcudmlldy5kb2N1bWVudDtcblxuXHRcdG1vZGVsRG9jdW1lbnQub24oICdjaGFuZ2U6ZGF0YScsICggZXZ0OiBDS0VkaXRvcjUuRXZlbnRJbmZvPCdjaGFuZ2U6ZGF0YSc+ICkgPT4ge1xuXHRcdFx0dGhpcy5uZ1pvbmUucnVuKCAoKSA9PiB7XG5cdFx0XHRcdGlmICggdGhpcy5jdmFPbkNoYW5nZSApIHtcblx0XHRcdFx0XHRjb25zdCBkYXRhID0gZWRpdG9yLmdldERhdGEoKTtcblxuXHRcdFx0XHRcdHRoaXMuY3ZhT25DaGFuZ2UoIGRhdGEgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMuY2hhbmdlLmVtaXQoIHsgZXZlbnQ6IGV2dCwgZWRpdG9yIH0gKTtcblx0XHRcdH0gKTtcblx0XHR9ICk7XG5cblx0XHR2aWV3RG9jdW1lbnQub24oICdmb2N1cycsICggZXZ0OiBDS0VkaXRvcjUuRXZlbnRJbmZvPCdmb2N1cyc+ICkgPT4ge1xuXHRcdFx0dGhpcy5uZ1pvbmUucnVuKCAoKSA9PiB7XG5cdFx0XHRcdHRoaXMuZm9jdXMuZW1pdCggeyBldmVudDogZXZ0LCBlZGl0b3IgfSApO1xuXHRcdFx0fSApO1xuXHRcdH0gKTtcblxuXHRcdHZpZXdEb2N1bWVudC5vbiggJ2JsdXInLCAoIGV2dDogQ0tFZGl0b3I1LkV2ZW50SW5mbzwnYmx1cic+ICkgPT4ge1xuXHRcdFx0dGhpcy5uZ1pvbmUucnVuKCAoKSA9PiB7XG5cdFx0XHRcdGlmICggdGhpcy5jdmFPblRvdWNoZWQgKSB7XG5cdFx0XHRcdFx0dGhpcy5jdmFPblRvdWNoZWQoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMuYmx1ci5lbWl0KCB7IGV2ZW50OiBldnQsIGVkaXRvciB9ICk7XG5cdFx0XHR9ICk7XG5cdFx0fSApO1xuXHR9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQmx1ckV2ZW50IHtcblx0ZXZlbnQ6IENLRWRpdG9yNS5FdmVudEluZm88J2JsdXInPjtcblx0ZWRpdG9yOiBDS0VkaXRvcjUuRWRpdG9yO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZvY3VzRXZlbnQge1xuXHRldmVudDogQ0tFZGl0b3I1LkV2ZW50SW5mbzwnZm9jdXMnPjtcblx0ZWRpdG9yOiBDS0VkaXRvcjUuRWRpdG9yO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENoYW5nZUV2ZW50IHtcblx0ZXZlbnQ6IENLRWRpdG9yNS5FdmVudEluZm88J2NoYW5nZTpkYXRhJz47XG5cdGVkaXRvcjogQ0tFZGl0b3I1LkVkaXRvcjtcbn1cbiJdfQ==