@ckeditor/ckeditor5-angular
Version:
Official Angular 2+ component for CKEditor 5 – the best browser-based rich text editor.
436 lines • 32.9 kB
JavaScript
/**
* @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