UNPKG

ng-zorro-antd

Version:

An enterprise-class UI components based on Ant Design and Angular

251 lines (250 loc) 32.5 kB
/** * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE */ import { __decorate } from "tslib"; import { Platform } from '@angular/cdk/platform'; import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, forwardRef, Input, NgZone, Output, ViewEncapsulation } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { BehaviorSubject, combineLatest, fromEvent, Subject } from 'rxjs'; import { debounceTime, distinctUntilChanged, filter, map, takeUntil } from 'rxjs/operators'; import { warn } from 'ng-zorro-antd/core/logger'; import { inNextTick, InputBoolean } from 'ng-zorro-antd/core/util'; import { NzCodeEditorService } from './code-editor.service'; export class NzCodeEditorComponent { constructor(nzCodeEditorService, ngZone, elementRef, platform) { this.nzCodeEditorService = nzCodeEditorService; this.ngZone = ngZone; this.platform = platform; this.nzEditorMode = 'normal'; this.nzOriginalText = ''; this.nzLoading = false; this.nzFullControl = false; this.nzEditorInitialized = new EventEmitter(); this.editorOptionCached = {}; this.destroy$ = new Subject(); this.resize$ = new Subject(); this.editorOption$ = new BehaviorSubject({}); this.editorInstance = null; this.value = ''; this.modelSet = false; this.onDidChangeContentDisposable = null; this.onChange = (_value) => { }; this.onTouch = () => { }; this.el = elementRef.nativeElement; this.el.classList.add('ant-code-editor'); } set nzEditorOption(value) { this.editorOption$.next(value); } /** * Initialize a monaco editor instance. */ ngAfterViewInit() { if (!this.platform.isBrowser) { return; } this.nzCodeEditorService.requestToInit().subscribe(option => this.setup(option)); } ngOnDestroy() { if (this.onDidChangeContentDisposable) { this.onDidChangeContentDisposable.dispose(); this.onDidChangeContentDisposable = null; } if (this.editorInstance) { this.editorInstance.dispose(); this.editorInstance = null; } this.destroy$.next(); this.destroy$.complete(); } writeValue(value) { this.value = value; this.setValue(); } registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouch = fn; } layout() { this.resize$.next(); } setup(option) { inNextTick().subscribe(() => { this.editorOptionCached = option; this.registerOptionChanges(); this.initMonacoEditorInstance(); this.registerResizeChange(); this.setValue(); if (!this.nzFullControl) { this.setValueEmitter(); } this.nzEditorInitialized.emit(this.editorInstance); }); } registerOptionChanges() { combineLatest([this.editorOption$, this.nzCodeEditorService.option$]) .pipe(takeUntil(this.destroy$)) .subscribe(([selfOpt, defaultOpt]) => { this.editorOptionCached = Object.assign(Object.assign(Object.assign({}, this.editorOptionCached), defaultOpt), selfOpt); this.updateOptionToMonaco(); }); } initMonacoEditorInstance() { this.ngZone.runOutsideAngular(() => { this.editorInstance = this.nzEditorMode === 'normal' ? monaco.editor.create(this.el, Object.assign({}, this.editorOptionCached)) : monaco.editor.createDiffEditor(this.el, Object.assign({}, this.editorOptionCached)); }); } registerResizeChange() { this.ngZone.runOutsideAngular(() => { fromEvent(window, 'resize') .pipe(debounceTime(300), takeUntil(this.destroy$)) .subscribe(() => { this.layout(); }); this.resize$ .pipe(takeUntil(this.destroy$), filter(() => !!this.editorInstance), map(() => ({ width: this.el.clientWidth, height: this.el.clientHeight })), distinctUntilChanged((a, b) => a.width === b.width && a.height === b.height), debounceTime(50)) .subscribe(() => { this.editorInstance.layout(); }); }); } setValue() { if (!this.editorInstance) { return; } if (this.nzFullControl && this.value) { warn(`should not set value when you are using full control mode! It would result in ambiguous data flow!`); return; } if (this.nzEditorMode === 'normal') { if (this.modelSet) { const model = this.editorInstance.getModel(); this.preservePositionAndSelections(() => model.setValue(this.value)); } else { this.editorInstance.setModel(monaco.editor.createModel(this.value, this.editorOptionCached.language)); this.modelSet = true; } } else { if (this.modelSet) { const model = this.editorInstance.getModel(); this.preservePositionAndSelections(() => { model.modified.setValue(this.value); model.original.setValue(this.nzOriginalText); }); } else { const language = this.editorOptionCached.language; this.editorInstance.setModel({ original: monaco.editor.createModel(this.nzOriginalText, language), modified: monaco.editor.createModel(this.value, language) }); this.modelSet = true; } } } /** * {@link editor.ICodeEditor}#setValue resets the cursor position to the start of the document. * This helper memorizes the cursor position and selections and restores them after the given * function has been called. */ preservePositionAndSelections(fn) { if (!this.editorInstance) { fn(); return; } const position = this.editorInstance.getPosition(); const selections = this.editorInstance.getSelections(); fn(); if (position) { this.editorInstance.setPosition(position); } if (selections) { this.editorInstance.setSelections(selections); } } setValueEmitter() { const model = (this.nzEditorMode === 'normal' ? this.editorInstance.getModel() : this.editorInstance.getModel().modified); // The `onDidChangeContent` returns a disposable object (an object with `dispose()` method) which will cleanup // the listener. The callback, that we pass to `onDidChangeContent`, captures `this`. This leads to a circular reference // (`nz-code-editor -> monaco -> nz-code-editor`) and prevents the `nz-code-editor` from being GC'd. this.onDidChangeContentDisposable = model.onDidChangeContent(() => { this.emitValue(model.getValue()); }); } emitValue(value) { if (this.value === value) { // If the value didn't change there's no reason to send an update. // Specifically this may happen during an update from the model (writeValue) where sending an update to the model would actually be incorrect. return; } this.value = value; // We're re-entering the Angular zone only if the value has been changed since there's a `return` expression previously. // This won't cause "dead" change detections (basically when the `tick()` has been run, but there's nothing to update). this.ngZone.run(() => { this.onChange(value); }); } updateOptionToMonaco() { if (this.editorInstance) { this.editorInstance.updateOptions(Object.assign({}, this.editorOptionCached)); } } } NzCodeEditorComponent.decorators = [ { type: Component, args: [{ changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, selector: 'nz-code-editor', exportAs: 'nzCodeEditor', template: ` <div class="ant-code-editor-loading" *ngIf="nzLoading"> <nz-spin></nz-spin> </div> <div class="ant-code-editor-toolkit" *ngIf="nzToolkit"> <ng-template [ngTemplateOutlet]="nzToolkit"></ng-template> </div> `, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NzCodeEditorComponent), multi: true } ] },] } ]; NzCodeEditorComponent.ctorParameters = () => [ { type: NzCodeEditorService }, { type: NgZone }, { type: ElementRef }, { type: Platform } ]; NzCodeEditorComponent.propDecorators = { nzEditorMode: [{ type: Input }], nzOriginalText: [{ type: Input }], nzLoading: [{ type: Input }], nzFullControl: [{ type: Input }], nzToolkit: [{ type: Input }], nzEditorOption: [{ type: Input }], nzEditorInitialized: [{ type: Output }] }; __decorate([ InputBoolean() ], NzCodeEditorComponent.prototype, "nzLoading", void 0); __decorate([ InputBoolean() ], NzCodeEditorComponent.prototype, "nzFullControl", void 0); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29kZS1lZGl0b3IuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vY29tcG9uZW50cy9jb2RlLWVkaXRvci9jb2RlLWVkaXRvci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHOztBQUVILE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNqRCxPQUFPLEVBRUwsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFVBQVUsRUFDVixLQUFLLEVBQ0wsTUFBTSxFQUVOLE1BQU0sRUFFTixpQkFBaUIsRUFDbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMxRSxPQUFPLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFJNUYsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRWpELE9BQU8sRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFbkUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFnQzVELE1BQU0sT0FBTyxxQkFBcUI7SUEyQmhDLFlBQ1UsbUJBQXdDLEVBQ3hDLE1BQWMsRUFDdEIsVUFBc0IsRUFDZCxRQUFrQjtRQUhsQix3QkFBbUIsR0FBbkIsbUJBQW1CLENBQXFCO1FBQ3hDLFdBQU0sR0FBTixNQUFNLENBQVE7UUFFZCxhQUFRLEdBQVIsUUFBUSxDQUFVO1FBM0JuQixpQkFBWSxHQUFpQixRQUFRLENBQUM7UUFDdEMsbUJBQWMsR0FBRyxFQUFFLENBQUM7UUFD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UUFFRCxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNuQix3SEFBd0g7UUFDeEgsdUhBQXVIO1FBQ3ZILElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRTtZQUNuQixJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3ZCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLG9CQUFvQjtRQUMxQixJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUU7WUFDdkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxhQUFhLG1CQUFNLElBQUksQ0FBQyxrQkFBa0IsRUFBRyxDQUFDO1NBQ25FO0lBQ0gsQ0FBQzs7O1lBMVFGLFNBQVMsU0FBQztnQkFDVCxlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtnQkFDL0MsYUFBYSxFQUFFLGlCQUFpQixDQUFDLElBQUk7Z0JBQ3JDLFFBQVEsRUFBRSxnQkFBZ0I7Z0JBQzFCLFFBQVEsRUFBRSxjQUFjO2dCQUN4QixRQUFRLEVBQUU7Ozs7Ozs7O0dBUVQ7Z0JBQ0QsU0FBUyxFQUFFO29CQUNUO3dCQUNFLE9BQU8sRUFBRSxpQkFBaUI7d0JBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMscUJBQXFCLENBQUM7d0JBQ3BELEtBQUssRUFBRSxJQUFJO3FCQUNaO2lCQUNGO2FBQ0Y7OztZQS9CUSxtQkFBbUI7WUFoQjFCLE1BQU07WUFKTixVQUFVO1lBTEgsUUFBUTs7OzJCQTZEZCxLQUFLOzZCQUNMLEtBQUs7d0JBQ0wsS0FBSzs0QkFDTCxLQUFLO3dCQUNMLEtBQUs7NkJBRUwsS0FBSztrQ0FJTCxNQUFNOztBQVJrQjtJQUFmLFlBQVksRUFBRTt3REFBbUI7QUFDbEI7SUFBZixZQUFZLEVBQUU7NERBQXVCIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2dpdGh1Yi5jb20vTkctWk9SUk8vbmctem9ycm8tYW50ZC9ibG9iL21hc3Rlci9MSUNFTlNFXG4gKi9cblxuaW1wb3J0IHsgUGxhdGZvcm0gfSBmcm9tICdAYW5ndWxhci9jZGsvcGxhdGZvcm0nO1xuaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBmb3J3YXJkUmVmLFxuICBJbnB1dCxcbiAgTmdab25lLFxuICBPbkRlc3Ryb3ksXG4gIE91dHB1dCxcbiAgVGVtcGxhdGVSZWYsXG4gIFZpZXdFbmNhcHN1bGF0aW9uXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGNvbWJpbmVMYXRlc3QsIGZyb21FdmVudCwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgZmlsdGVyLCBtYXAsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgZWRpdG9yLCBJRGlzcG9zYWJsZSB9IGZyb20gJ21vbmFjby1lZGl0b3InO1xuXG5pbXBvcnQgeyB3YXJuIH0gZnJvbSAnbmctem9ycm8tYW50ZC9jb3JlL2xvZ2dlcic7XG5pbXBvcnQgeyBCb29sZWFuSW5wdXQsIE56U2FmZUFueSwgT25DaGFuZ2VUeXBlLCBPblRvdWNoZWRUeXBlIH0gZnJvbSAnbmctem9ycm8tYW50ZC9jb3JlL3R5cGVzJztcbmltcG9ydCB7IGluTmV4dFRpY2ssIElucHV0Qm9vbGVhbiB9IGZyb20gJ25nLXpvcnJvLWFudGQvY29yZS91dGlsJztcblxuaW1wb3J0IHsgTnpDb2RlRWRpdG9yU2VydmljZSB9IGZyb20gJy4vY29kZS1lZGl0b3Iuc2VydmljZSc7XG5pbXBvcnQgeyBEaWZmRWRpdG9yT3B0aW9ucywgRWRpdG9yT3B0aW9ucywgSm9pbmVkRWRpdG9yT3B0aW9ucywgTnpFZGl0b3JNb2RlIH0gZnJvbSAnLi90eXBpbmdzJztcblxuLy8gSW1wb3J0IHR5cGVzIGZyb20gbW9uYWNvIGVkaXRvci5cbmltcG9ydCBJVGV4dE1vZGVsID0gZWRpdG9yLklUZXh0TW9kZWw7XG5pbXBvcnQgSVN0YW5kYWxvbmVDb2RlRWRpdG9yID0gZWRpdG9yLklTdGFuZGFsb25lQ29kZUVkaXRvcjtcbmltcG9ydCBJU3RhbmRhbG9uZURpZmZFZGl0b3IgPSBlZGl0b3IuSVN0YW5kYWxvbmVEaWZmRWRpdG9yO1xuXG5kZWNsYXJlIGNvbnN0IG1vbmFjbzogTnpTYWZlQW55O1xuXG5AQ29tcG9uZW50KHtcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIHNlbGVjdG9yOiAnbnotY29kZS1lZGl0b3InLFxuICBleHBvcnRBczogJ256Q29kZUVkaXRvcicsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImFudC1jb2RlLWVkaXRvci1sb2FkaW5nXCIgKm5nSWY9XCJuekxvYWRpbmdcIj5cbiAgICAgIDxuei1zcGluPjwvbnotc3Bpbj5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgY2xhc3M9XCJhbnQtY29kZS1lZGl0b3ItdG9vbGtpdFwiICpuZ0lmPVwibnpUb29sa2l0XCI+XG4gICAgICA8bmctdGVtcGxhdGUgW25nVGVtcGxhdGVPdXRsZXRdPVwibnpUb29sa2l0XCI+PC9uZy10ZW1wbGF0ZT5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBOekNvZGVFZGl0b3JDb21wb25lbnQpLFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9XG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTnpDb2RlRWRpdG9yQ29tcG9uZW50IGltcGxlbWVudHMgT25EZXN0cm95LCBBZnRlclZpZXdJbml0IHtcbiAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX256TG9hZGluZzogQm9vbGVhbklucHV0O1xuICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfbnpGdWxsQ29udHJvbDogQm9vbGVhbklucHV0O1xuXG4gIEBJbnB1dCgpIG56RWRpdG9yTW9kZTogTnpFZGl0b3JNb2RlID0gJ25vcm1hbCc7XG4gIEBJbnB1dCgpIG56T3JpZ2luYWxUZXh0ID0gJyc7XG4gIEBJbnB1dCgpIEBJbnB1dEJvb2xlYW4oKSBuekxvYWRpbmcgPSBmYWxzZTtcbiAgQElucHV0KCkgQElucHV0Qm9vbGVhbigpIG56RnVsbENvbnRyb2wgPSBmYWxzZTtcbiAgQElucHV0KCkgbnpUb29sa2l0PzogVGVtcGxhdGVSZWY8dm9pZD47XG5cbiAgQElucHV0KCkgc2V0IG56RWRpdG9yT3B0aW9uKHZhbHVlOiBKb2luZWRFZGl0b3JPcHRpb25zKSB7XG4gICAgdGhpcy5lZGl0b3JPcHRpb24kLm5leHQodmFsdWUpO1xuICB9XG5cbiAgQE91dHB1dCgpIHJlYWRvbmx5IG56RWRpdG9ySW5pdGlhbGl6ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPElTdGFuZGFsb25lQ29kZUVkaXRvciB8IElTdGFuZGFsb25lRGlmZkVkaXRvcj4oKTtcblxuICBlZGl0b3JPcHRpb25DYWNoZWQ6IEpvaW5lZEVkaXRvck9wdGlvbnMgPSB7fTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGVsOiBIVE1MRWxlbWVudDtcbiAgcHJpdmF0ZSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIHByaXZhdGUgcmVzaXplJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIHByaXZhdGUgZWRpdG9yT3B0aW9uJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Sm9pbmVkRWRpdG9yT3B0aW9ucz4oe30pO1xuICBwcml2YXRlIGVkaXRvckluc3RhbmNlOiBJU3RhbmRhbG9uZUNvZGVFZGl0b3IgfCBJU3RhbmRhbG9uZURpZmZFZGl0b3IgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSB2YWx1ZSA9ICcnO1xuICBwcml2YXRlIG1vZGVsU2V0ID0gZmFsc2U7XG4gIHByaXZhdGUgb25EaWRDaGFuZ2VDb250ZW50RGlzcG9zYWJsZTogSURpc3Bvc2FibGUgfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIG56Q29kZUVkaXRvclNlcnZpY2U6IE56Q29kZUVkaXRvclNlcnZpY2UsXG4gICAgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSxcbiAgICBlbGVtZW50UmVmOiBFbGVtZW50UmVmLFxuICAgIHByaXZhdGUgcGxhdGZvcm06IFBsYXRmb3JtXG4gICkge1xuICAgIHRoaXMuZWwgPSBlbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgdGhpcy5lbC5jbGFzc0xpc3QuYWRkKCdhbnQtY29kZS1lZGl0b3InKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplIGEgbW9uYWNvIGVkaXRvciBpbnN0YW5jZS5cbiAgICovXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMucGxhdGZvcm0uaXNCcm93c2VyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMubnpDb2RlRWRpdG9yU2VydmljZS5yZXF1ZXN0VG9Jbml0KCkuc3Vic2NyaWJlKG9wdGlvbiA9PiB0aGlzLnNldHVwKG9wdGlvbikpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgaWYgKHRoaXMub25EaWRDaGFuZ2VDb250ZW50RGlzcG9zYWJsZSkge1xuICAgICAgdGhpcy5vbkRpZENoYW5nZUNvbnRlbnREaXNwb3NhYmxlLmRpc3Bvc2UoKTtcbiAgICAgIHRoaXMub25EaWRDaGFuZ2VDb250ZW50RGlzcG9zYWJsZSA9IG51bGw7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZWRpdG9ySW5zdGFuY2UpIHtcbiAgICAgIHRoaXMuZWRpdG9ySW5zdGFuY2UuZGlzcG9zZSgpO1xuICAgICAgdGhpcy5lZGl0b3JJbnN0YW5jZSA9IG51bGw7XG4gICAgfVxuXG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XG4gICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICB9XG5cbiAgd3JpdGVWYWx1ZSh2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgIHRoaXMuc2V0VmFsdWUoKTtcbiAgfVxuXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46IE9uQ2hhbmdlVHlwZSk6IE56U2FmZUFueSB7XG4gICAgdGhpcy5vbkNoYW5nZSA9IGZuO1xuICB9XG5cbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46IE9uVG91Y2hlZFR5cGUpOiB2b2lkIHtcbiAgICB0aGlzLm9uVG91Y2ggPSBmbjtcbiAgfVxuXG4gIG9uQ2hhbmdlOiBPbkNoYW5nZVR5cGUgPSAoX3ZhbHVlOiBzdHJpbmcpID0+IHt9O1xuXG4gIG9uVG91Y2g6IE9uVG91Y2hlZFR5cGUgPSAoKSA9PiB7fTtcblxuICBsYXlvdXQoKTogdm9pZCB7XG4gICAgdGhpcy5yZXNpemUkLm5leHQoKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0dXAob3B0aW9uOiBKb2luZWRFZGl0b3JPcHRpb25zKTogdm9pZCB7XG4gICAgaW5OZXh0VGljaygpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICB0aGlzLmVkaXRvck9wdGlvbkNhY2hlZCA9IG9wdGlvbjtcbiAgICAgIHRoaXMucmVnaXN0ZXJPcHRpb25DaGFuZ2VzKCk7XG4gICAgICB0aGlzLmluaXRNb25hY29FZGl0b3JJbnN0YW5jZSgpO1xuICAgICAgdGhpcy5yZWdpc3RlclJlc2l6ZUNoYW5nZSgpO1xuICAgICAgdGhpcy5zZXRWYWx1ZSgpO1xuXG4gICAgICBpZiAoIXRoaXMubnpGdWxsQ29udHJvbCkge1xuICAgICAgICB0aGlzLnNldFZhbHVlRW1pdHRlcigpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLm56RWRpdG9ySW5pdGlhbGl6ZWQuZW1pdCh0aGlzLmVkaXRvckluc3RhbmNlISk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHJlZ2lzdGVyT3B0aW9uQ2hhbmdlcygpOiB2b2lkIHtcbiAgICBjb21iaW5lTGF0ZXN0KFt0aGlzLmVkaXRvck9wdGlvbiQsIHRoaXMubnpDb2RlRWRpdG9yU2VydmljZS5vcHRpb24kXSlcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcbiAgICAgIC5zdWJzY3JpYmUoKFtzZWxmT3B0LCBkZWZhdWx0T3B0XSkgPT4ge1xuICAgICAgICB0aGlzLmVkaXRvck9wdGlvbkNhY2hlZCA9IHtcbiAgICAgICAgICAuLi50aGlzLmVkaXRvck9wdGlvbkNhY2hlZCxcbiAgICAgICAgICAuLi5kZWZhdWx0T3B0LFxuICAgICAgICAgIC4uLnNlbGZPcHRcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy51cGRhdGVPcHRpb25Ub01vbmFjbygpO1xuICAgICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGluaXRNb25hY29FZGl0b3JJbnN0YW5jZSgpOiB2b2lkIHtcbiAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICB0aGlzLmVkaXRvckluc3RhbmNlID1cbiAgICAgICAgdGhpcy5uekVkaXRvck1vZGUgPT09ICdub3JtYWwnXG4gICAgICAgICAgPyBtb25hY28uZWRpdG9yLmNyZWF0ZSh0aGlzLmVsLCB7IC4uLnRoaXMuZWRpdG9yT3B0aW9uQ2FjaGVkIH0pXG4gICAgICAgICAgOiBtb25hY28uZWRpdG9yLmNyZWF0ZURpZmZFZGl0b3IodGhpcy5lbCwge1xuICAgICAgICAgICAgICAuLi4odGhpcy5lZGl0b3JPcHRpb25DYWNoZWQgYXMgRGlmZkVkaXRvck9wdGlvbnMpXG4gICAgICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgcmVnaXN0ZXJSZXNpemVDaGFuZ2UoKTogdm9pZCB7XG4gICAgdGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgZnJvbUV2ZW50KHdpbmRvdywgJ3Jlc2l6ZScpXG4gICAgICAgIC5waXBlKGRlYm91bmNlVGltZSgzMDApLCB0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXG4gICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgIHRoaXMubGF5b3V0KCk7XG4gICAgICAgIH0pO1xuXG4gICAgICB0aGlzLnJlc2l6ZSRcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpLFxuICAgICAgICAgIGZpbHRlcigoKSA9PiAhIXRoaXMuZWRpdG9ySW5zdGFuY2UpLFxuICAgICAgICAgIG1hcCgoKSA9PiAoe1xuICAgICAgICAgICAgd2lkdGg6IHRoaXMuZWwuY2xpZW50V2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IHRoaXMuZWwuY2xpZW50SGVpZ2h0XG4gICAgICAgICAgfSkpLFxuICAgICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKChhLCBiKSA9PiBhLndpZHRoID09PSBiLndpZHRoICYmIGEuaGVpZ2h0ID09PSBiLmhlaWdodCksXG4gICAgICAgICAgZGVib3VuY2VUaW1lKDUwKVxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuZWRpdG9ySW5zdGFuY2UhLmxheW91dCgpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0VmFsdWUoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmVkaXRvckluc3RhbmNlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMubnpGdWxsQ29udHJvbCAmJiB0aGlzLnZhbHVlKSB7XG4gICAgICB3YXJuKGBzaG91bGQgbm90IHNldCB2YWx1ZSB3aGVuIHlvdSBhcmUgdXNpbmcgZnVsbCBjb250cm9sIG1vZGUhIEl0IHdvdWxkIHJlc3VsdCBpbiBhbWJpZ3VvdXMgZGF0YSBmbG93IWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm56RWRpdG9yTW9kZSA9PT0gJ25vcm1hbCcpIHtcbiAgICAgIGlmICh0aGlzLm1vZGVsU2V0KSB7XG4gICAgICAgIGNvbnN0IG1vZGVsID0gdGhpcy5lZGl0b3JJbnN0YW5jZS5nZXRNb2RlbCgpIGFzIElUZXh0TW9kZWw7XG4gICAgICAgIHRoaXMucHJlc2VydmVQb3NpdGlvbkFuZFNlbGVjdGlvbnMoKCkgPT4gbW9kZWwuc2V0VmFsdWUodGhpcy52YWx1ZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgKHRoaXMuZWRpdG9ySW5zdGFuY2UgYXMgSVN0YW5kYWxvbmVDb2RlRWRpdG9yKS5zZXRNb2RlbChcbiAgICAgICAgICBtb25hY28uZWRpdG9yLmNyZWF0ZU1vZGVsKHRoaXMudmFsdWUsICh0aGlzLmVkaXRvck9wdGlvbkNhY2hlZCBhcyBFZGl0b3JPcHRpb25zKS5sYW5ndWFnZSlcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5tb2RlbFNldCA9IHRydWU7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0aGlzLm1vZGVsU2V0KSB7XG4gICAgICAgIGNvbnN0IG1vZGVsID0gKHRoaXMuZWRpdG9ySW5zdGFuY2UgYXMgSVN0YW5kYWxvbmVEaWZmRWRpdG9yKS5nZXRNb2RlbCgpITtcbiAgICAgICAgdGhpcy5wcmVzZXJ2ZVBvc2l0aW9uQW5kU2VsZWN0aW9ucygoKSA9PiB7XG4gICAgICAgICAgbW9kZWwubW9kaWZpZWQuc2V0VmFsdWUodGhpcy52YWx1ZSk7XG4gICAgICAgICAgbW9kZWwub3JpZ2luYWwuc2V0VmFsdWUodGhpcy5uek9yaWdpbmFsVGV4dCk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgbGFuZ3VhZ2UgPSAodGhpcy5lZGl0b3JPcHRpb25DYWNoZWQgYXMgRWRpdG9yT3B0aW9ucykubGFuZ3VhZ2U7XG4gICAgICAgICh0aGlzLmVkaXRvckluc3RhbmNlIGFzIElTdGFuZGFsb25lRGlmZkVkaXRvcikuc2V0TW9kZWwoe1xuICAgICAgICAgIG9yaWdpbmFsOiBtb25hY28uZWRpdG9yLmNyZWF0ZU1vZGVsKHRoaXMubnpPcmlnaW5hbFRleHQsIGxhbmd1YWdlKSxcbiAgICAgICAgICBtb2RpZmllZDogbW9uYWNvLmVkaXRvci5jcmVhdGVNb2RlbCh0aGlzLnZhbHVlLCBsYW5ndWFnZSlcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMubW9kZWxTZXQgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiB7QGxpbmsgZWRpdG9yLklDb2RlRWRpdG9yfSNzZXRWYWx1ZSByZXNldHMgdGhlIGN1cnNvciBwb3NpdGlvbiB0byB0aGUgc3RhcnQgb2YgdGhlIGRvY3VtZW50LlxuICAgKiBUaGlzIGhlbHBlciBtZW1vcml6ZXMgdGhlIGN1cnNvciBwb3NpdGlvbiBhbmQgc2VsZWN0aW9ucyBhbmQgcmVzdG9yZXMgdGhlbSBhZnRlciB0aGUgZ2l2ZW5cbiAgICogZnVuY3Rpb24gaGFzIGJlZW4gY2FsbGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBwcmVzZXJ2ZVBvc2l0aW9uQW5kU2VsZWN0aW9ucyhmbjogKCkgPT4gdW5rbm93bik6IHZvaWQge1xuICAgIGlmICghdGhpcy5lZGl0b3JJbnN0YW5jZSkge1xuICAgICAgZm4oKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMuZWRpdG9ySW5zdGFuY2UuZ2V0UG9zaXRpb24oKTtcbiAgICBjb25zdCBzZWxlY3Rpb25zID0gdGhpcy5lZGl0b3JJbnN0YW5jZS5nZXRTZWxlY3Rpb25zKCk7XG5cbiAgICBmbigpO1xuXG4gICAgaWYgKHBvc2l0aW9uKSB7XG4gICAgICB0aGlzLmVkaXRvckluc3RhbmNlLnNldFBvc2l0aW9uKHBvc2l0aW9uKTtcbiAgICB9XG4gICAgaWYgKHNlbGVjdGlvbnMpIHtcbiAgICAgIHRoaXMuZWRpdG9ySW5zdGFuY2Uuc2V0U2VsZWN0aW9ucyhzZWxlY3Rpb25zKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNldFZhbHVlRW1pdHRlcigpOiB2b2lkIHtcbiAgICBjb25zdCBtb2RlbCA9IChcbiAgICAgIHRoaXMubnpFZGl0b3JNb2RlID09PSAnbm9ybWFsJ1xuICAgICAgICA/ICh0aGlzLmVkaXRvckluc3RhbmNlIGFzIElTdGFuZGFsb25lQ29kZUVkaXRvcikuZ2V0TW9kZWwoKVxuICAgICAgICA6ICh0aGlzLmVkaXRvckluc3RhbmNlIGFzIElTdGFuZGFsb25lRGlmZkVkaXRvcikuZ2V0TW9kZWwoKSEubW9kaWZpZWRcbiAgICApIGFzIElUZXh0TW9kZWw7XG5cbiAgICAvLyBUaGUgYG9uRGlkQ2hhbmdlQ29udGVudGAgcmV0dXJucyBhIGRpc3Bvc2FibGUgb2JqZWN0IChhbiBvYmplY3Qgd2l0aCBgZGlzcG9zZSgpYCBtZXRob2QpIHdoaWNoIHdpbGwgY2xlYW51cFxuICAgIC8vIHRoZSBsaXN0ZW5lci4gVGhlIGNhbGxiYWNrLCB0aGF0IHdlIHBhc3MgdG8gYG9uRGlkQ2hhbmdlQ29udGVudGAsIGNhcHR1cmVzIGB0aGlzYC4gVGhpcyBsZWFkcyB0byBhIGNpcmN1bGFyIHJlZmVyZW5jZVxuICAgIC8vIChgbnotY29kZS1lZGl0b3IgLT4gbW9uYWNvIC0+IG56LWNvZGUtZWRpdG9yYCkgYW5kIHByZXZlbnRzIHRoZSBgbnotY29kZS1lZGl0b3JgIGZyb20gYmVpbmcgR0MnZC5cbiAgICB0aGlzLm9uRGlkQ2hhbmdlQ29udGVudERpc3Bvc2FibGUgPSBtb2RlbC5vbkRpZENoYW5nZUNvbnRlbnQoKCkgPT4ge1xuICAgICAgdGhpcy5lbWl0VmFsdWUobW9kZWwuZ2V0VmFsdWUoKSk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGVtaXRWYWx1ZSh2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKHRoaXMudmFsdWUgPT09IHZhbHVlKSB7XG4gICAgICAvLyBJZiB0aGUgdmFsdWUgZGlkbid0IGNoYW5nZSB0aGVyZSdzIG5vIHJlYXNvbiB0byBzZW5kIGFuIHVwZGF0ZS5cbiAgICAgIC8vIFNwZWNpZmljYWxseSB0aGlzIG1heSBoYXBwZW4gZHVyaW5nIGFuIHVwZGF0ZSBmcm9tIHRoZSBtb2RlbCAod3JpdGVWYWx1ZSkgd2hlcmUgc2VuZGluZyBhbiB1cGRhdGUgdG8gdGhlIG1vZGVsIHdvdWxkIGFjdHVhbGx5IGJlIGluY29ycmVjdC5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgLy8gV2UncmUgcmUtZW50ZXJpbmcgdGhlIEFuZ3VsYXIgem9uZSBvbmx5IGlmIHRoZSB2YWx1ZSBoYXMgYmVlbiBjaGFuZ2VkIHNpbmNlIHRoZXJlJ3MgYSBgcmV0dXJuYCBleHByZXNzaW9uIHByZXZpb3VzbHkuXG4gICAgLy8gVGhpcyB3b24ndCBjYXVzZSBcImRlYWRcIiBjaGFuZ2UgZGV0ZWN0aW9ucyAoYmFzaWNhbGx5IHdoZW4gdGhlIGB0aWNrKClgIGhhcyBiZWVuIHJ1biwgYnV0IHRoZXJlJ3Mgbm90aGluZyB0byB1cGRhdGUpLlxuICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICB0aGlzLm9uQ2hhbmdlKHZhbHVlKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlT3B0aW9uVG9Nb25hY28oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZWRpdG9ySW5zdGFuY2UpIHtcbiAgICAgIHRoaXMuZWRpdG9ySW5zdGFuY2UudXBkYXRlT3B0aW9ucyh7IC4uLnRoaXMuZWRpdG9yT3B0aW9uQ2FjaGVkIH0pO1xuICAgIH1cbiAgfVxufVxuIl19