UNPKG

@ckeditor/ckeditor5-angular

Version:

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

436 lines 32.9 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @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'; export class CKEditorComponent { /** * @param {?} elementRef * @param {?} ngZone */ constructor(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; } /** * 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 {?} */ set disabled(isDisabled) { this.setDisabledState(isDisabled); } /** * @return {?} */ get disabled() { if (this.editorInstance) { return this.editorInstance.isReadOnly; } return this.initialIsDisabled; } // Implementing the AfterViewInit interface. /** * @return {?} */ ngAfterViewInit() { this.ngZone.runOutsideAngular((/** * @return {?} */ () => { this.createEditor(); })); } // Implementing the OnDestroy interface. /** * @return {?} */ ngOnDestroy() { if (this.editorInstance) { this.editorInstance.destroy(); this.editorInstance = null; } } // Implementing the ControlValueAccessor interface (only when binding to ngModel). /** * @param {?} value * @return {?} */ writeValue(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). /** * @param {?} callback * @return {?} */ registerOnChange(callback) { this.cvaOnChange = callback; } // Implementing the ControlValueAccessor interface (only when binding to ngModel). /** * @param {?} callback * @return {?} */ registerOnTouched(callback) { this.cvaOnTouched = callback; } // Implementing the ControlValueAccessor interface (only when binding to ngModel). /** * @param {?} isDisabled * @return {?} */ setDisabledState(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). * @private * @return {?} */ createEditor() { /** @type {?} */ const 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 {?} */ const config = Object.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 {?} */ editor => { this.editorInstance = editor; if (this.initialIsDisabled) { editor.isReadOnly = this.initialIsDisabled; } this.ngZone.run((/** * @return {?} */ () => { this.ready.emit(editor); })); this.setUpEditorEvents(editor); })) .catch((/** * @param {?} err * @return {?} */ (err) => { console.error(err.stack); })); } /** * Integrates the editor with the component by attaching related event listeners. * @private * @param {?} editor * @return {?} */ setUpEditorEvents(editor) { /** @type {?} */ const modelDocument = editor.model.document; /** @type {?} */ const viewDocument = editor.editing.view.document; modelDocument.on('change:data', (/** * @param {?} evt * @return {?} */ (evt) => { this.ngZone.run((/** * @return {?} */ () => { if (this.cvaOnChange) { /** @type {?} */ const data = editor.getData(); this.cvaOnChange(data); } this.change.emit({ event: evt, editor }); })); })); viewDocument.on('focus', (/** * @param {?} evt * @return {?} */ (evt) => { this.ngZone.run((/** * @return {?} */ () => { this.focus.emit({ event: evt, editor }); })); })); viewDocument.on('blur', (/** * @param {?} evt * @return {?} */ (evt) => { this.ngZone.run((/** * @return {?} */ () => { if (this.cvaOnTouched) { this.cvaOnTouched(); } this.blur.emit({ event: evt, 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 {?} */ () => CKEditorComponent)), multi: true, } ] }] } ]; /** @nocollapse */ CKEditorComponent.ctorParameters = () => [ { 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 }] }; 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2tlZGl0b3IuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vQGNrZWRpdG9yL2NrZWRpdG9yNS1hbmd1bGFyLyIsInNvdXJjZXMiOlsiY2tlZGl0b3IuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBS0EsT0FBTyxFQUNOLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLE1BQU0sRUFDTixZQUFZLEVBQ1osVUFBVSxFQUVWLFVBQVUsRUFDVixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBRU4saUJBQWlCLEVBQ2pCLE1BQU0sZ0JBQWdCLENBQUM7QUFpQnhCLE1BQU0sT0FBTyxpQkFBaUI7Ozs7O0lBbUg3QixZQUFhLFVBQXNCLEVBQUUsTUFBYzs7Ozs7O1FBbEcxQyxXQUFNLEdBQXFCLEVBQUUsQ0FBQzs7Ozs7UUFNOUIsU0FBSSxHQUFHLEVBQUUsQ0FBQzs7Ozs7O1FBT1YsWUFBTyxHQUFHLEtBQUssQ0FBQzs7Ozs7O1FBd0JmLFVBQUssR0FBRyxJQUFJLFlBQVksRUFBb0IsQ0FBQzs7Ozs7O1FBTzdDLFdBQU0sR0FBOEIsSUFBSSxZQUFZLEVBQWUsQ0FBQzs7Ozs7O1FBT3BFLFNBQUksR0FBNEIsSUFBSSxZQUFZLEVBQWEsQ0FBQzs7Ozs7O1FBTzlELFVBQUssR0FBNkIsSUFBSSxZQUFZLEVBQWMsQ0FBQzs7OztRQUtwRSxtQkFBYyxHQUE0QixJQUFJLENBQUM7Ozs7O1FBTTlDLHNCQUFpQixHQUFHLEtBQUssQ0FBQztRQThCakMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7SUFDOUIsQ0FBQzs7Ozs7Ozs7SUFqRkQsSUFBYSxRQUFRLENBQUUsVUFBbUI7UUFDekMsSUFBSSxDQUFDLGdCQUFnQixDQUFFLFVBQVUsQ0FBRSxDQUFDO0lBQ3JDLENBQUM7Ozs7SUFFRCxJQUFJLFFBQVE7UUFDWCxJQUFLLElBQUksQ0FBQyxjQUFj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SUFRdkIsd0NBQStDOzs7Ozs7Ozs7SUFRL0MseUNBQWtDOzs7Ozs7SUFLbEMsMENBQW9DOzs7OztBQWlKckMsK0JBR0M7OztJQUZBLDBCQUFtQzs7SUFDbkMsMkJBQXlCOzs7OztBQUcxQixnQ0FHQzs7O0lBRkEsMkJBQW9DOztJQUNwQyw0QkFBeUI7Ozs7O0FBRzFCLGlDQUdDOzs7SUFGQSw0QkFBMEM7O0lBQzFDLDZCQUF5QiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2UgQ29weXJpZ2h0IChjKSAyMDAzLTIwMTksIENLU291cmNlIC0gRnJlZGVyaWNvIEtuYWJiZW4uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiBGb3IgbGljZW5zaW5nLCBzZWUgTElDRU5TRS5tZC5cbiAqL1xuXG5pbXBvcnQge1xuXHRDb21wb25lbnQsXG5cdElucHV0LFxuXHRPdXRwdXQsXG5cdE5nWm9uZSxcblx0RXZlbnRFbWl0dGVyLFxuXHRmb3J3YXJkUmVmLFxuXHRBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3ksXG5cdEVsZW1lbnRSZWZcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7XG5cdENvbnRyb2xWYWx1ZUFjY2Vzc29yLFxuXHROR19WQUxVRV9BQ0NFU1NPUlxufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IENLRWRpdG9yNSB9IGZyb20gJy4vY2tlZGl0b3InO1xuXG5AQ29tcG9uZW50KCB7XG5cdHNlbGVjdG9yOiAnY2tlZGl0b3InLFxuXHR0ZW1wbGF0ZTogJzxuZy10ZW1wbGF0ZT48L25nLXRlbXBsYXRlPicsXG5cblx0Ly8gSW50ZWdyYXRpb24gd2l0aCBAYW5ndWxhci9mb3Jtcy5cblx0cHJvdmlkZXJzOiBbXG5cdFx0e1xuXHRcdFx0cHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG5cdFx0XHR1c2VFeGlzdGluZzogZm9yd2FyZFJlZiggKCkgPT4gQ0tFZGl0b3JDb21wb25lbnQgKSxcblx0XHRcdG11bHRpOiB0cnVlLFxuXHRcdH1cblx0XVxufSApXG5leHBvcnQgY2xhc3MgQ0tFZGl0b3JDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3ksIENvbnRyb2xWYWx1ZUFjY2Vzc29yIHtcblx0LyoqXG5cdCAqIFRoZSByZWZlcmVuY2UgdG8gdGhlIERPTSBlbGVtZW50IGNyZWF0ZWQgYnkgdGhlIGNvbXBvbmVudC5cblx0ICovXG5cdHByaXZhdGUgZWxlbWVudFJlZiE6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+O1xuXG5cdC8qKlxuXHQgKiBUaGUgY29uc3RydWN0b3Igb2YgdGhlIGVkaXRvciB0byBiZSB1c2VkIGZvciB0aGUgaW5zdGFuY2Ugb2YgdGhlIGNvbXBvbmVudC5cblx0ICogSXQgY2FuIGJlIGUuZy4gdGhlIGBDbGFzc2ljRWRpdG9yQnVpbGRgLCBgSW5saW5lRWRpdG9yQnVpbGRgIG9yIHNvbWUgY3VzdG9tIGVkaXRvci5cblx0ICovXG5cdEBJbnB1dCgpIGVkaXRvcj86IENLRWRpdG9yNS5FZGl0b3JDb25zdHJ1Y3RvcjtcblxuXHQvKipcblx0ICogVGhlIGNvbmZpZ3VyYXRpb24gb2YgdGhlIGVkaXRvci5cblx0ICogU2VlIGh0dHBzOi8vY2tlZGl0b3IuY29tL2RvY3MvY2tlZGl0b3I1L2xhdGVzdC9hcGkvbW9kdWxlX2NvcmVfZWRpdG9yX2VkaXRvcmNvbmZpZy1FZGl0b3JDb25maWcuaHRtbFxuXHQgKiB0byBsZWFybiBtb3JlLlxuXHQgKi9cblx0QElucHV0KCkgY29uZmlnOiBDS0VkaXRvcjUuQ29uZmlnID0ge307XG5cblx0LyoqXG5cdCAqIFRoZSBpbml0aWFsIGRhdGEgb2YgdGhlIGVkaXRvci4gVXNlZnVsIHdoZW4gbm90IHVzaW5nIHRoZSBuZ01vZGVsLlxuXHQgKiBTZWUgaHR0cHM6Ly9hbmd1bGFyLmlvL2FwaS9mb3Jtcy9OZ01vZGVsIHRvIGxlYXJuIG1vcmUuXG5cdCAqL1xuXHRASW5wdXQoKSBkYXRhID0gJyc7XG5cblx0LyoqXG5cdCAqIFRhZyBuYW1lIG9mIHRoZSBlZGl0b3IgY29tcG9uZW50LlxuXHQgKlxuXHQgKiBUaGUgZGVmYXVsdCB0YWcgaXMgJ2RpdicuXG5cdCAqL1xuXHRASW5wdXQoKSB0YWdOYW1lID0gJ2Rpdic7XG5cblx0LyoqXG5cdCAqIFdoZW4gc2V0IGB0cnVlYCwgdGhlIGVkaXRvciBiZWNvbWVzIHJlYWQtb25seS5cblx0ICogU2VlIGh0dHBzOi8vY2tlZGl0b3IuY29tL2RvY3MvY2tlZGl0b3I1L2xhdGVzdC9hcGkvbW9kdWxlX2NvcmVfZWRpdG9yX2VkaXRvci1FZGl0b3IuaHRtbCNtZW1iZXItaXNSZWFkT25seVxuXHQgKiB0byBsZWFybiBtb3JlLlxuXHQgKi9cblx0QElucHV0KCkgc2V0IGRpc2FibGVkKCBpc0Rpc2FibGVkOiBib29sZWFuICkge1xuXHRcdHRoaXMuc2V0RGlzYWJsZWRTdGF0ZSggaXNEaXNhYmxlZCApO1xuXHR9XG5cblx0Z2V0IGRpc2FibGVkKCkge1xuXHRcdGlmICggdGhpcy5lZGl0b3JJbnN0YW5jZSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVkaXRvckluc3RhbmNlLmlzUmVhZE9ubHk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuaW5pdGlhbElzRGlzYWJsZWQ7XG5cdH1cblxuXHQvKipcblx0ICogRmlyZXMgd2hlbiB0aGUgZWRpdG9yIGlzIHJlYWR5LiBJdCBjb3JyZXNwb25kcyB3aXRoIHRoZSBgZWRpdG9yI3JlYWR5YFxuXHQgKiBodHRwczovL2NrZWRpdG9yLmNvbS9kb2NzL2NrZWRpdG9yNS9sYXRlc3QvYXBpL21vZHVsZV9jb3JlX2VkaXRvcl9lZGl0b3ItRWRpdG9yLmh0bWwjZXZlbnQtcmVhZHlcblx0ICogZXZlbnQuXG5cdCAqL1xuXHRAT3V0cHV0KCkgcmVhZHkgPSBuZXcgRXZlbnRFbWl0dGVyPENLRWRpdG9yNS5FZGl0b3I+KCk7XG5cblx0LyoqXG5cdCAqIEZpcmVzIHdoZW4gdGhlIGNvbnRlbnQgb2YgdGhlIGVkaXRvciBoYXMgY2hhbmdlZC4gSXQgY29ycmVzcG9uZHMgd2l0aCB0aGUgYGVkaXRvci5tb2RlbC5kb2N1bWVudCNjaGFuZ2VgXG5cdCAqIGh0dHBzOi8vY2tlZGl0b3IuY29tL2RvY3MvY2tlZGl0b3I1L2xhdGVzdC9hcGkvbW9kdWxlX2VuZ2luZV9tb2RlbF9kb2N1bWVudC1Eb2N1bWVudC5odG1sI2V2ZW50LWNoYW5nZVxuXHQgKiBldmVudC5cblx0ICovXG5cdEBPdXRwdXQoKSBjaGFuZ2U6IEV2ZW50RW1pdHRlcjxDaGFuZ2VFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyPENoYW5nZUV2ZW50PigpO1xuXG5cdC8qKlxuXHQgKiBGaXJlcyB3aGVuIHRoZSBlZGl0aW5nIHZpZXcgb2YgdGhlIGVkaXRvciBpcyBibHVycmVkLiBJdCBjb3JyZXNwb25kcyB3aXRoIHRoZSBgZWRpdG9yLmVkaXRpbmcudmlldy5kb2N1bWVudCNibHVyYFxuXHQgKiBodHRwczovL2NrZWRpdG9yLmNvbS9kb2NzL2NrZWRpdG9yNS9sYXRlc3QvYXBpL21vZHVsZV9lbmdpbmVfdmlld19kb2N1bWVudC1Eb2N1bWVudC5odG1sI2V2ZW50LWV2ZW50OmJsdXJcblx0ICogZXZlbnQuXG5cdCAqL1xuXHRAT3V0cHV0KCkgYmx1cjogRXZlbnRFbWl0dGVyPEJsdXJFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyPEJsdXJFdmVudD4oKTtcblxuXHQvKipcblx0ICogRmlyZXMgd2hlbiB0aGUgZWRpdGluZyB2aWV3IG9mIHRoZSBlZGl0b3IgaXMgZm9jdXNlZC4gSXQgY29ycmVzcG9uZHMgd2l0aCB0aGUgYGVkaXRvci5lZGl0aW5nLnZpZXcuZG9jdW1lbnQjZm9jdXNgXG5cdCAqIGh0dHBzOi8vY2tlZGl0b3IuY29tL2RvY3MvY2tlZGl0b3I1L2xhdGVzdC9hcGkvbW9kdWxlX2VuZ2luZV92aWV3X2RvY3VtZW50LURvY3VtZW50Lmh0bWwjZXZlbnQtZXZlbnQ6Zm9jdXNcblx0ICogZXZlbnQuXG5cdCAqL1xuXHRAT3V0cHV0KCkgZm9jdXM6IEV2ZW50RW1pdHRlcjxGb2N1c0V2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8Rm9jdXNFdmVudD4oKTtcblxuXHQvKipcblx0ICogVGhlIGluc3RhbmNlIG9mIHRoZSBlZGl0b3IgY3JlYXRlZCBieSB0aGlzIGNvbXBvbmVudC5cblx0ICovXG5cdHB1YmxpYyBlZGl0b3JJbnN0YW5jZTogQ0tFZGl0b3I1LkVkaXRvciB8IG51bGwgPSBudWxsO1xuXG5cdC8qKlxuXHQgKiBJZiB0aGUgY29tcG9uZW50IGlzIHJlYWTigJNvbmx5IGJlZm9yZSB0aGUgZWRpdG9yIGluc3RhbmNlIGlzIGNyZWF0ZWQsIGl0IHJlbWVtYmVycyB0aGF0IHN0YXRlLFxuXHQgKiBzbyB0aGUgZWRpdG9yIGNhbiBiZWNvbWUgcmVhZOKAk29ubHkgb25jZSBpdCBpcyByZWFkeS5cblx0ICovXG5cdHByaXZhdGUgaW5pdGlhbElzRGlzYWJsZWQgPSBmYWxzZTtcblxuXHQvKipcblx0ICogQW4gaW5zdGFuY2Ugb2YgaHR0cHM6Ly9hbmd1bGFyLmlvL2FwaS9jb3JlL05nWm9uZSB0byBhbGxvdyB0aGUgaW50ZXJhY3Rpb24gd2l0aCB0aGUgZWRpdG9yXG5cdCAqIHdpdGhpbmcgdGhlIEFuZ3VsYXIgZXZlbnQgbG9vcC5cblx0ICovXG5cdHByaXZhdGUgbmdab25lOiBOZ1pvbmU7XG5cblx0LyoqXG5cdCAqIEEgY2FsbGJhY2sgZXhlY3V0ZWQgd2hlbiB0aGUgY29udGVudCBvZiB0aGUgZWRpdG9yIGNoYW5nZXMuIFBhcnQgb2YgdGhlXG5cdCAqIGBDb250cm9sVmFsdWVBY2Nlc3NvcmAgKGh0dHBzOi8vYW5ndWxhci5pby9hcGkvZm9ybXMvQ29udHJvbFZhbHVlQWNjZXNzb3IpIGludGVyZmFjZS5cblx0ICpcblx0ICogTm90ZTogVW5zZXQgdW5sZXNzIHRoZSBjb21wb25lbnQgdXNlcyB0aGUgYG5nTW9kZWxgLlxuXHQgKi9cblx0cHJpdmF0ZSBjdmFPbkNoYW5nZT86ICggZGF0YTogc3RyaW5nICkgPT4gdm9pZDtcblxuXHQvKipcblx0ICogQSBjYWxsYmFjayBleGVjdXRlZCB3aGVuIHRoZSBlZGl0b3IgaGFzIGJlZW4gYmx1cnJlZC4gUGFydCBvZiB0aGVcblx0ICogYENvbnRyb2xWYWx1ZUFjY2Vzc29yYCAoaHR0cHM6Ly9hbmd1bGFyLmlvL2FwaS9mb3Jtcy9Db250cm9sVmFsdWVBY2Nlc3NvcikgaW50ZXJmYWNlLlxuXHQgKlxuXHQgKiBOb3RlOiBVbnNldCB1bmxlc3MgdGhlIGNvbXBvbmVudCB1c2VzIHRoZSBgbmdNb2RlbGAuXG5cdCAqL1xuXHRwcml2YXRlIGN2YU9uVG91Y2hlZD86ICgpID0+IHZvaWQ7XG5cblx0LyoqXG5cdCAqIFJlZmVyZW5jZSB0byB0aGUgc291cmNlIGVsZW1lbnQgdXNlZCBieSB0aGUgZWRpdG9yLlxuXHQgKi9cblx0cHJpdmF0ZSBlZGl0b3JFbGVtZW50PzogSFRNTEVsZW1lbnQ7XG5cblx0Y29uc3RydWN0b3IoIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsIG5nWm9uZTogTmdab25lICkge1xuXHRcdHRoaXMubmdab25lID0gbmdab25lO1xuXHRcdHRoaXMuZWxlbWVudFJlZiA9IGVsZW1lbnRSZWY7XG5cdH1cblxuXHQvLyBJbXBsZW1lbnRpbmcgdGhlIEFmdGVyVmlld0luaXQgaW50ZXJmYWNlLlxuXHRuZ0FmdGVyVmlld0luaXQoKSB7XG5cdFx0dGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoICgpID0+IHtcblx0XHRcdHRoaXMuY3JlYXRlRWRpdG9yKCk7XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gSW1wbGVtZW50aW5nIHRoZSBPbkRlc3Ryb3kgaW50ZXJmYWNlLlxuXHRuZ09uRGVzdHJveSgpIHtcblx0XHRpZiAoIHRoaXMuZWRpdG9ySW5zdGFuY2UgKSB7XG5cdFx0XHR0aGlzLmVkaXRvckluc3RhbmNlLmRlc3Ryb3koKTtcblx0XHRcdHRoaXMuZWRpdG9ySW5zdGFuY2UgPSBudWxsO1xuXHRcdH1cblx0fVxuXG5cdC8vIEltcGxlbWVudGluZyB0aGUgQ29udHJvbFZhbHVlQWNjZXNzb3IgaW50ZXJmYWNlIChvbmx5IHdoZW4gYmluZGluZyB0byBuZ01vZGVsKS5cblx0d3JpdGVWYWx1ZSggdmFsdWU6IHN0cmluZyB8IG51bGwgKTogdm9pZCB7XG5cdFx0Ly8gVGhpcyBtZXRob2QgaXMgY2FsbGVkIHdpdGggdGhlIGBudWxsYCB2YWx1ZSB3aGVuIHRoZSBmb3JtIHJlc2V0cy5cblx0XHQvLyBBIGNvbXBvbmVudCdzIHJlc3BvbnNpYmlsaXR5IGlzIHRvIHJlc3RvcmUgdG8gdGhlIGluaXRpYWwgc3RhdGUuXG5cdFx0aWYgKCB2YWx1ZSA9PT0gbnVsbCApIHtcblx0XHRcdHZhbHVlID0gJyc7XG5cdFx0fVxuXG5cdFx0Ly8gSWYgYWxyZWFkeSBpbml0aWFsaXplZC5cblx0XHRpZiAoIHRoaXMuZWRpdG9ySW5zdGFuY2UgKSB7XG5cdFx0XHR0aGlzLmVkaXRvckluc3RhbmNlLnNldERhdGEoIHZhbHVlICk7XG5cdFx0fVxuXHRcdC8vIElmIG5vdCwgd2FpdCBmb3IgaXQgdG8gYmUgcmVhZHk7IHN0b3JlIHRoZSBkYXRhLlxuXHRcdGVsc2Uge1xuXHRcdFx0dGhpcy5kYXRhID0gdmFsdWU7XG5cblx0XHRcdC8vIElmIHRoZSBlZGl0b3IgZWxlbWVudCBpcyBhbHJlYWR5IGF2YWlsYWJsZSwgdGhlbiB1cGRhdGUgaXRzIGNvbnRlbnQuXG5cdFx0XHQvLyBJZiB0aGUgbmdNb2RlbCBpcyB1c2VkIHRoZW4gdGhlIGVkaXRvciBlbGVtZW50IHNob3VsZCBiZSB1cGRhdGVkIGRpcmVjdGx5IGhlcmUuXG5cdFx0XHRpZiAoIHRoaXMuZWRpdG9yRWxlbWVudCApIHtcblx0XHRcdFx0dGhpcy5lZGl0b3JFbGVtZW50LmlubmVySFRNTCA9IHRoaXMuZGF0YTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBJbXBsZW1lbnRpbmcgdGhlIENvbnRyb2xWYWx1ZUFjY2Vzc29yIGludGVyZmFjZSAob25seSB3aGVuIGJpbmRpbmcgdG8gbmdNb2RlbCkuXG5cdHJlZ2lzdGVyT25DaGFuZ2UoIGNhbGxiYWNrOiAoIGRhdGE6IHN0cmluZyApID0+IHZvaWQgKTogdm9pZCB7XG5cdFx0dGhpcy5jdmFPbkNoYW5nZSA9IGNhbGxiYWNrO1xuXHR9XG5cblx0Ly8gSW1wbGVtZW50aW5nIHRoZSBDb250cm9sVmFsdWVBY2Nlc3NvciBpbnRlcmZhY2UgKG9ubHkgd2hlbiBiaW5kaW5nIHRvIG5nTW9kZWwpLlxuXHRyZWdpc3Rlck9uVG91Y2hlZCggY2FsbGJhY2s6ICgpID0+IHZvaWQgKTogdm9pZCB7XG5cdFx0dGhpcy5jdmFPblRvdWNoZWQgPSBjYWxsYmFjaztcblx0fVxuXG5cdC8vIEltcGxlbWVudGluZyB0aGUgQ29udHJvbFZhbHVlQWNjZXNzb3IgaW50ZXJmYWNlIChvbmx5IHdoZW4gYmluZGluZyB0byBuZ01vZGVsKS5cblx0c2V0RGlzYWJsZWRTdGF0ZSggaXNEaXNhYmxlZDogYm9vbGVhbiApOiB2b2lkIHtcblx0XHQvLyBJZiBhbHJlYWR5IGluaXRpYWxpemVkXG5cdFx0aWYgKCB0aGlzLmVkaXRvckluc3RhbmNlICkge1xuXHRcdFx0dGhpcy5lZGl0b3JJbnN0YW5jZS5pc1JlYWRPbmx5ID0gaXNEaXNhYmxlZDtcblx0XHR9XG5cdFx0Ly8gSWYgbm90LCB3YWl0IGZvciBpdCB0byBiZSByZWFkeTsgc3RvcmUgdGhlIHN0YXRlLlxuXHRcdGVsc2Uge1xuXHRcdFx0dGhpcy5pbml0aWFsSXNEaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgdGhlIGVkaXRvciBpbnN0YW5jZSwgc2V0cyBpbml0aWFsIGVkaXRvciBkYXRhLCB0aGVuIGludGVncmF0ZXNcblx0ICogdGhlIGVkaXRvciB3aXRoIHRoZSBBbmd1bGFyIGNvbXBvbmVudC4gVGhpcyBtZXRob2QgZG9lcyBub3QgdXNlIHRoZSBgZWRpdG9yLnNldERhdGEoKWBcblx0ICogYmVjYXVzZSBvZiB0aGUgaXNzdWUgaW4gdGhlIGNvbGxhYm9yYXRpb24gbW9kZSAoIzYpLlxuXHQgKi9cblx0cHJpdmF0ZSBjcmVhdGVFZGl0b3IoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0Y29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIHRoaXMudGFnTmFtZSApO1xuXHRcdHRoaXMuZWRpdG9yRWxlbWVudCA9IGVsZW1lbnQ7XG5cblx0XHRpZiAoIHRoaXMuZGF0YSAmJiB0aGlzLmNvbmZpZy5pbml0aWFsRGF0YSApIHtcblx0XHRcdHRocm93IG5ldyBFcnJvciggJ0VkaXRvciBkYXRhIHNob3VsZCBiZSBwcm92aWRlZCBlaXRoZXIgdXNpbmcgYGNvbmZpZy5pbml0aWFsRGF0YWAgb3IgYGRhdGFgIHByb3BlcnRpZXMuJyApO1xuXHRcdH1cblxuXHRcdC8vIE1lcmdlIHR3byBwb3NzaWJsZSB3YXlzIG9mIHByb3ZpZGluZyBkYXRhIGludG8gdGhlIGBjb25maWcuaW5pdGlhbERhdGFgIGZpZWxkLlxuXHRcdGNvbnN0IGNvbmZpZyA9IHtcblx0XHRcdC4uLnRoaXMuY29uZmlnLFxuXHRcdFx0aW5pdGlhbERhdGE6IHRoaXMuY29uZmlnLmluaXRpYWxEYXRhIHx8IHRoaXMuZGF0YSB8fCAnJ1xuXHRcdH07XG5cblx0XHR0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5hcHBlbmRDaGlsZCggZWxlbWVudCApO1xuXG5cdFx0cmV0dXJuIHRoaXMuZWRpdG9yIS5jcmVhdGUoIGVsZW1lbnQsIGNvbmZpZyApXG5cdFx0XHQudGhlbiggZWRpdG9yID0+IHtcblx0XHRcdFx0dGhpcy5lZGl0b3JJbnN0YW5jZSA9IGVkaXRvcjtcblxuXHRcdFx0XHRpZiAoIHRoaXMuaW5pdGlhbElzRGlzYWJsZWQgKSB7XG5cdFx0XHRcdFx0ZWRpdG9yLmlzUmVhZE9ubHkgPSB0aGlzLmluaXRpYWxJc0Rpc2FibGVkO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5uZ1pvbmUucnVuKCAoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy5yZWFkeS5lbWl0KCBlZGl0b3IgKTtcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdHRoaXMuc2V0VXBFZGl0b3JFdmVudHMoIGVkaXRvciApO1xuXHRcdFx0fSApXG5cdFx0XHQuY2F0Y2goICggZXJyOiBFcnJvciApID0+IHtcblx0XHRcdFx0Y29uc29sZS5lcnJvciggZXJyLnN0YWNrICk7XG5cdFx0XHR9ICk7XG5cdH1cblxuXHQvKipcblx0ICogSW50ZWdyYXRlcyB0aGUgZWRpdG9yIHdpdGggdGhlIGNvbXBvbmVudCBieSBhdHRhY2hpbmcgcmVsYXRlZCBldmVudCBsaXN0ZW5lcnMuXG5cdCAqL1xuXHRwcml2YXRlIHNldFVwRWRpdG9yRXZlbnRzKCBlZGl0b3I6IENLRWRpdG9yNS5FZGl0b3IgKTogdm9pZCB7XG5cdFx0Y29uc3QgbW9kZWxEb2N1bWVudCA9IGVkaXRvci5tb2RlbC5kb2N1bWVudDtcblx0XHRjb25zdCB2aWV3RG9jdW1lbnQgPSBlZGl0b3IuZWRpdGluZy52aWV3LmRvY3VtZW50O1xuXG5cdFx0bW9kZWxEb2N1bWVudC5vbiggJ2NoYW5nZTpkYXRhJywgKCBldnQ6IENLRWRpdG9yNS5FdmVudEluZm88J2NoYW5nZTpkYXRhJz4gKSA9PiB7XG5cdFx0XHR0aGlzLm5nWm9uZS5ydW4oICgpID0+IHtcblx0XHRcdFx0aWYgKCB0aGlzLmN2YU9uQ2hhbmdlICkge1xuXHRcdFx0XHRcdGNvbnN0IGRhdGEgPSBlZGl0b3IuZ2V0RGF0YSgpO1xuXG5cdFx0XHRcdFx0dGhpcy5jdmFPbkNoYW5nZSggZGF0YSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5jaGFuZ2UuZW1pdCggeyBldmVudDogZXZ0LCBlZGl0b3IgfSApO1xuXHRcdFx0fSApO1xuXHRcdH0gKTtcblxuXHRcdHZpZXdEb2N1bWVudC5vbiggJ2ZvY3VzJywgKCBldnQ6IENLRWRpdG9yNS5FdmVudEluZm88J2ZvY3VzJz4gKSA9PiB7XG5cdFx0XHR0aGlzLm5nWm9uZS5ydW4oICgpID0+IHtcblx0XHRcdFx0dGhpcy5mb2N1cy5lbWl0KCB7IGV2ZW50OiBldnQsIGVkaXRvciB9ICk7XG5cdFx0XHR9ICk7XG5cdFx0fSApO1xuXG5cdFx0dmlld0RvY3VtZW50Lm9uKCAnYmx1cicsICggZXZ0OiBDS0VkaXRvcjUuRXZlbnRJbmZvPCdibHVyJz4gKSA9PiB7XG5cdFx0XHR0aGlzLm5nWm9uZS5ydW4oICgpID0+IHtcblx0XHRcdFx0aWYgKCB0aGlzLmN2YU9uVG91Y2hlZCApIHtcblx0XHRcdFx0XHR0aGlzLmN2YU9uVG91Y2hlZCgpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5ibHVyLmVtaXQoIHsgZXZlbnQ6IGV2dCwgZWRpdG9yIH0gKTtcblx0XHRcdH0gKTtcblx0XHR9ICk7XG5cdH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBCbHVyRXZlbnQge1xuXHRldmVudDogQ0tFZGl0b3I1LkV2ZW50SW5mbzwnYmx1cic+O1xuXHRlZGl0b3I6IENLRWRpdG9yNS5FZGl0b3I7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRm9jdXNFdmVudCB7XG5cdGV2ZW50OiBDS0VkaXRvcjUuRXZlbnRJbmZvPCdmb2N1cyc+O1xuXHRlZGl0b3I6IENLRWRpdG9yNS5FZGl0b3I7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2hhbmdlRXZlbnQge1xuXHRldmVudDogQ0tFZGl0b3I1LkV2ZW50SW5mbzwnY2hhbmdlOmRhdGEnPjtcblx0ZWRpdG9yOiBDS0VkaXRvcjUuRWRpdG9yO1xufVxuIl19