UNPKG

ngx-cytoscapejs

Version:
192 lines 22.1 kB
import { Component, EventEmitter, inject, Input, Output, ViewChild, } from '@angular/core'; import cytoscape from 'cytoscape'; import { debounceTime, fromEvent, Subject, takeUntil } from 'rxjs'; import { CxConverter } from '../enum/cx-converter.enum'; import { CxService } from '../service/cx.service'; import * as i0 from "@angular/core"; /** * This component handles rendering the Cytoscape.js graph. */ export class CytoscapejsComponent { /** * Object containing information about a graph. Must conform to [CytoscapeOptions]{@link https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/cytoscape/index.d.ts}. A specified container is ignored. * Should not be defined, if you are using {@link cxData} to build a graph. */ cytoscapeOptions; /** * Responsible for automatically resizing the graph when the browser window changes its size. * If true, resizing the graph is triggered. * If false, changes in window size are ignored. */ autoFit = true; /** * Responsible for applying the background color specified in the CX file to the canvas. * If true, the network's background color will be set to the color specified in the CX. * If false, the network's background color will be white. */ applyCxBackgroundColor = false; /** * Object containing information about a graph. Must conform to [CX data model]{@link https://home.ndexbio.org/data-model/}. * Should not be defined, if you are using {@link cytoscapeOptions} to build a graph. */ cxData; /** * List of {@link CxConverter}s you wish to use for conversion of your {@link cxData}. * Arrange the converters in the order, in which they are to be executed, e.g. the first converter you specify will be tried first. * The first successful conversion result will be rendered. */ cxConverters = [ CxConverter.cx2js, CxConverter.cxVizConverter, ]; /** * Each time a new [Cytoscape.js core]{@link https://js.cytoscape.org/#core} is built, this output is firing an event containing the recent core. */ coreChanged = new EventEmitter(); /** * Each time a new [Cytoscape.js core]{@link https://js.cytoscape.org/#core} is built using [cx2js]{@link https://github.com/cytoscape/cx2js} the * resulting attributeNameMap object is emitted as well. */ cxAttributeNameMapChanged = new EventEmitter(); /** * Reference to the HTMLElement that is used as a [container]{@link https://js.cytoscape.org/#core/initialisation} for the graph. * * @internal */ cyElementRef; /** * Represents a state in the [Angular lifecycle]{@link https://angular.io/guide/lifecycle-hooks} indicating, that the view has been initialized. * * @internal */ isViewInitialized = false; /** * [Cytoscape.js core]{@link https://js.cytoscape.org/#core} that is rendered. * * @internal */ core; /** * Serves as an indicator, when the component has been destroyed. * * @internal */ destroy$ = new Subject(); /** * Service responsible for conversion * * @internal */ cxService = inject(CxService); /** * [Angular lifecycle]{@link https://angular.io/guide/lifecycle-hooks} which is called as soon as the view has been initialized. * Used to subscribe to any window resize event. Triggers initial rendering. */ ngAfterViewInit() { fromEvent(window, 'resize') .pipe(takeUntil(this.destroy$), debounceTime(300)) .subscribe(() => this.fit()); this.isViewInitialized = true; this.preRender(); } /** * [Angular lifecycle]{@link https://angular.io/guide/lifecycle-hooks} which is called every time, an input property changes its value. * Used to update the graph's visualization. * * @param {SimpleChanges} changes Object containing all changes */ ngOnChanges(changes) { const { cytoscapeOptions, cxData, autoFit } = changes; if (cytoscapeOptions || cxData) { this.preRender(); } if (autoFit) { this.fit(); } } /** * [Angular lifecycle]{@link https://angular.io/guide/lifecycle-hooks} which is called as soon as the component is destroyed. * Used to unsubscribe from window resize events. */ ngOnDestroy() { this.destroy$.next(true); this.destroy$.complete(); } /** * Based on the user's input, this method decides, if rendering can happen and which input is to be used. */ preRender() { if (!this.isViewInitialized || (!this.cytoscapeOptions && !this.cxData)) { return; } if (this.cytoscapeOptions) { this.render(this.cytoscapeOptions); } else if (this.cxData) { const conversion = this.cxService.convert(this.cxData, this.cxConverters); if (conversion) { const { options, attributeNameMap, backgroundColor } = conversion; if (this.cyElementRef && this.cyElementRef.nativeElement) { const htmlElement = this.cyElementRef.nativeElement; if (this.applyCxBackgroundColor && backgroundColor) { htmlElement.style.backgroundColor = backgroundColor; } else { htmlElement.style.backgroundColor = ''; } } this.cxAttributeNameMapChanged.emit(attributeNameMap); if (options) { this.render(options); } } } } /** * Renders the graph using [CytoscapeOptions]{@link https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/cytoscape/index.d.ts}. * * @param {CytoscapeOptions} options Object containing graph information */ render(options) { if (options) { this.core = cytoscape({ ...options, container: this.cyElementRef.nativeElement, }); this.core.fit(); this.coreChanged.emit(this.core); } } /** * Resizes and repositions the graph to fit the current window size. */ fit() { if (this.autoFit && this.core) { this.core.fit(); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: CytoscapejsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.1.3", type: CytoscapejsComponent, isStandalone: true, selector: "cytoscapejs", inputs: { cytoscapeOptions: "cytoscapeOptions", autoFit: "autoFit", applyCxBackgroundColor: "applyCxBackgroundColor", cxData: "cxData", cxConverters: "cxConverters" }, outputs: { coreChanged: "coreChanged", cxAttributeNameMapChanged: "cxAttributeNameMapChanged" }, viewQueries: [{ propertyName: "cyElementRef", first: true, predicate: ["cy"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div id=\"cy\" #cy></div>\n", styles: ["#cy{height:100%;width:100%}\n"] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: CytoscapejsComponent, decorators: [{ type: Component, args: [{ selector: 'cytoscapejs', standalone: true, template: "<div id=\"cy\" #cy></div>\n", styles: ["#cy{height:100%;width:100%}\n"] }] }], propDecorators: { cytoscapeOptions: [{ type: Input }], autoFit: [{ type: Input }], applyCxBackgroundColor: [{ type: Input }], cxData: [{ type: Input }], cxConverters: [{ type: Input }], coreChanged: [{ type: Output }], cxAttributeNameMapChanged: [{ type: Output }], cyElementRef: [{ type: ViewChild, args: ['cy'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3l0b3NjYXBlanMuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWN5dG9zY2FwZWpzL3NyYy9saWIvY29tcG9uZW50L2N5dG9zY2FwZWpzLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1jeXRvc2NhcGVqcy9zcmMvbGliL2NvbXBvbmVudC9jeXRvc2NhcGVqcy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsU0FBUyxFQUVULFlBQVksRUFDWixNQUFNLEVBQ04sS0FBSyxFQUdMLE1BQU0sRUFFTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxTQUFxQyxNQUFNLFdBQVcsQ0FBQztBQUM5RCxPQUFPLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRW5FLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7O0FBRWxEOztHQUVHO0FBT0gsTUFBTSxPQUFPLG9CQUFvQjtJQUcvQjs7O09BR0c7SUFDTSxnQkFBZ0IsQ0FBb0I7SUFFN0M7Ozs7T0FJRztJQUNNLE9BQU8sR0FBWSxJQUFJLENBQUM7SUFFakM7Ozs7T0FJRztJQUNNLHNCQUFzQixHQUFZLEtBQUssQ0FBQztJQUVqRDs7O09BR0c7SUFDTSxNQUFNLENBQU87SUFFdEI7Ozs7T0FJRztJQUNNLFlBQVksR0FBa0I7UUFDckMsV0FBVyxDQUFDLEtBQUs7UUFDakIsV0FBVyxDQUFDLGNBQWM7S0FDM0IsQ0FBQztJQUVGOztPQUVHO0lBQ08sV0FBVyxHQUF1QixJQUFJLFlBQVksRUFBUSxDQUFDO0lBRXJFOzs7T0FHRztJQUNPLHlCQUF5QixHQUNqQyxJQUFJLFlBQVksRUFBc0Is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SUFFRDs7OztPQUlHO0lBQ0ssTUFBTSxDQUFDLE9BQXlCO1FBQ3RDLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixJQUFJLENBQUMsSUFBSSxHQUFHLFNBQVMsQ0FBQztnQkFDcEIsR0FBRyxPQUFPO2dCQUNWLFNBQVMsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWE7YUFDM0MsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNoQixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbkMsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNLLEdBQUc7UUFDVCxJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzlCLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDbEIsQ0FBQztJQUNILENBQUM7dUdBeExVLG9CQUFvQjsyRkFBcEIsb0JBQW9CLHljQzVCakMsNkJBQ0E7OzJGRDJCYSxvQkFBb0I7a0JBTmhDLFNBQVM7K0JBQ0UsYUFBYSxjQUNYLElBQUk7OEJBV1AsZ0JBQWdCO3NCQUF4QixLQUFLO2dCQU9HLE9BQU87c0JBQWYsS0FBSztnQkFPRyxzQkFBc0I7c0JBQTlCLEtBQUs7Z0JBTUcsTUFBTTtzQkFBZCxLQUFLO2dCQU9HLFlBQVk7c0JBQXBCLEtBQUs7Z0JBUUksV0FBVztzQkFBcEIsTUFBTTtnQkFNRyx5QkFBeUI7c0JBQWxDLE1BQU07Z0JBUVUsWUFBWTtzQkFBNUIsU0FBUzt1QkFBQyxJQUFJIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIGluamVjdCxcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgY3l0b3NjYXBlLCB7IENvcmUsIEN5dG9zY2FwZU9wdGlvbnMgfSBmcm9tICdjeXRvc2NhcGUnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBmcm9tRXZlbnQsIFN1YmplY3QsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgQ3hBdHRyaWJ1dGVOYW1lTWFwIH0gZnJvbSAnLi4vaW50ZXJmYWNlL2N4LWF0dHJpYnV0ZS1uYW1lLW1hcC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgQ3hDb252ZXJ0ZXIgfSBmcm9tICcuLi9lbnVtL2N4LWNvbnZlcnRlci5lbnVtJztcbmltcG9ydCB7IEN4U2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2UvY3guc2VydmljZSc7XG5cbi8qKlxuICogVGhpcyBjb21wb25lbnQgaGFuZGxlcyByZW5kZXJpbmcgdGhlIEN5dG9zY2FwZS5qcyBncmFwaC5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnY3l0b3NjYXBlanMnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICB0ZW1wbGF0ZVVybDogJy4vY3l0b3NjYXBlanMuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vY3l0b3NjYXBlanMuY29tcG9uZW50LnNjc3MnLFxufSlcbmV4cG9ydCBjbGFzcyBDeXRvc2NhcGVqc0NvbXBvbmVudFxuICBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95XG57XG4gIC8qKlxuICAgKiBPYmplY3QgY29udGFpbmluZyBpbmZvcm1hdGlvbiBhYm91dCBhIGdyYXBoLiBNdXN0IGNvbmZvcm0gdG8gW0N5dG9zY2FwZU9wdGlvbnNde0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9EZWZpbml0ZWx5VHlwZWQvRGVmaW5pdGVseVR5cGVkL2Jsb2IvbWFzdGVyL3R5cGVzL2N5dG9zY2FwZS9pbmRleC5kLnRzfS4gQSBzcGVjaWZpZWQgY29udGFpbmVyIGlzIGlnbm9yZWQuXG4gICAqIFNob3VsZCBub3QgYmUgZGVmaW5lZCwgaWYgeW91IGFyZSB1c2luZyB7QGxpbmsgY3hEYXRhfSB0byBidWlsZCBhIGdyYXBoLlxuICAgKi9cbiAgQElucHV0KCkgY3l0b3NjYXBlT3B0aW9ucyE6IEN5dG9zY2FwZU9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFJlc3BvbnNpYmxlIGZvciBhdXRvbWF0aWNhbGx5IHJlc2l6aW5nIHRoZSBncmFwaCB3aGVuIHRoZSBicm93c2VyIHdpbmRvdyBjaGFuZ2VzIGl0cyBzaXplLlxuICAgKiBJZiB0cnVlLCByZXNpemluZyB0aGUgZ3JhcGggaXMgdHJpZ2dlcmVkLlxuICAgKiBJZiBmYWxzZSwgY2hhbmdlcyBpbiB3aW5kb3cgc2l6ZSBhcmUgaWdub3JlZC5cbiAgICovXG4gIEBJbnB1dCgpIGF1dG9GaXQ6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBSZXNwb25zaWJsZSBmb3IgYXBwbHlpbmcgdGhlIGJhY2tncm91bmQgY29sb3Igc3BlY2lmaWVkIGluIHRoZSBDWCBmaWxlIHRvIHRoZSBjYW52YXMuXG4gICAqIElmIHRydWUsIHRoZSBuZXR3b3JrJ3MgYmFja2dyb3VuZCBjb2xvciB3aWxsIGJlIHNldCB0byB0aGUgY29sb3Igc3BlY2lmaWVkIGluIHRoZSBDWC5cbiAgICogSWYgZmFsc2UsIHRoZSBuZXR3b3JrJ3MgYmFja2dyb3VuZCBjb2xvciB3aWxsIGJlIHdoaXRlLlxuICAgKi9cbiAgQElucHV0KCkgYXBwbHlDeEJhY2tncm91bmRDb2xvcjogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBPYmplY3QgY29udGFpbmluZyBpbmZvcm1hdGlvbiBhYm91dCBhIGdyYXBoLiBNdXN0IGNvbmZvcm0gdG8gW0NYIGRhdGEgbW9kZWxde0BsaW5rIGh0dHBzOi8vaG9tZS5uZGV4YmlvLm9yZy9kYXRhLW1vZGVsL30uXG4gICAqIFNob3VsZCBub3QgYmUgZGVmaW5lZCwgaWYgeW91IGFyZSB1c2luZyB7QGxpbmsgY3l0b3NjYXBlT3B0aW9uc30gdG8gYnVpbGQgYSBncmFwaC5cbiAgICovXG4gIEBJbnB1dCgpIGN4RGF0YSE6IGFueTtcblxuICAvKipcbiAgICogTGlzdCBvZiB7QGxpbmsgQ3hDb252ZXJ0ZXJ9cyB5b3Ugd2lzaCB0byB1c2UgZm9yIGNvbnZlcnNpb24gb2YgeW91ciB7QGxpbmsgY3hEYXRhfS5cbiAgICogQXJyYW5nZSB0aGUgY29udmVydGVycyBpbiB0aGUgb3JkZXIsIGluIHdoaWNoIHRoZXkgYXJlIHRvIGJlIGV4ZWN1dGVkLCBlLmcuIHRoZSBmaXJzdCBjb252ZXJ0ZXIgeW91IHNwZWNpZnkgd2lsbCBiZSB0cmllZCBmaXJzdC5cbiAgICogVGhlIGZpcnN0IHN1Y2Nlc3NmdWwgY29udmVyc2lvbiByZXN1bHQgd2lsbCBiZSByZW5kZXJlZC5cbiAgICovXG4gIEBJbnB1dCgpIGN4Q29udmVydGVyczogQ3hDb252ZXJ0ZXJbXSA9IFtcbiAgICBDeENvbnZlcnRlci5jeDJqcyxcbiAgICBDeENvbnZlcnRlci5jeFZpekNvbnZlcnRlcixcbiAgXTtcblxuICAvKipcbiAgICogRWFjaCB0aW1lIGEgbmV3IFtDeXRvc2NhcGUuanMgY29yZV17QGxpbmsgaHR0cHM6Ly9qcy5jeXRvc2NhcGUub3JnLyNjb3JlfSBpcyBidWlsdCwgdGhpcyBvdXRwdXQgaXMgZmlyaW5nIGFuIGV2ZW50IGNvbnRhaW5pbmcgdGhlIHJlY2VudCBjb3JlLlxuICAgKi9cbiAgQE91dHB1dCgpIGNvcmVDaGFuZ2VkOiBFdmVudEVtaXR0ZXI8Q29yZT4gPSBuZXcgRXZlbnRFbWl0dGVyPENvcmU+KCk7XG5cbiAgLyoqXG4gICAqIEVhY2ggdGltZSBhIG5ldyBbQ3l0b3NjYXBlLmpzIGNvcmVde0BsaW5rIGh0dHBzOi8vanMuY3l0b3NjYXBlLm9yZy8jY29yZX0gaXMgYnVpbHQgdXNpbmcgW2N4MmpzXXtAbGluayBodHRwczovL2dpdGh1Yi5jb20vY3l0b3NjYXBlL2N4MmpzfSB0aGVcbiAgICogcmVzdWx0aW5nIGF0dHJpYnV0ZU5hbWVNYXAgb2JqZWN0IGlzIGVtaXR0ZWQgYXMgd2VsbC5cbiAgICovXG4gIEBPdXRwdXQoKSBjeEF0dHJpYnV0ZU5hbWVNYXBDaGFuZ2VkOiBFdmVudEVtaXR0ZXI8Q3hBdHRyaWJ1dGVOYW1lTWFwPiA9XG4gICAgbmV3IEV2ZW50RW1pdHRlcjxDeEF0dHJpYnV0ZU5hbWVNYXA+KCk7XG5cbiAgLyoqXG4gICAqIFJlZmVyZW5jZSB0byB0aGUgSFRNTEVsZW1lbnQgdGhhdCBpcyB1c2VkIGFzIGEgW2NvbnRhaW5lcl17QGxpbmsgaHR0cHM6Ly9qcy5jeXRvc2NhcGUub3JnLyNjb3JlL2luaXRpYWxpc2F0aW9ufSBmb3IgdGhlIGdyYXBoLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIEBWaWV3Q2hpbGQoJ2N5JykgY3lFbGVtZW50UmVmITogRWxlbWVudFJlZjtcblxuICAvKipcbiAgICogUmVwcmVzZW50cyBhIHN0YXRlIGluIHRoZSBbQW5ndWxhciBsaWZlY3ljbGVde0BsaW5rIGh0dHBzOi8vYW5ndWxhci5pby9ndWlkZS9saWZlY3ljbGUtaG9va3N9IGluZGljYXRpbmcsIHRoYXQgdGhlIHZpZXcgaGFzIGJlZW4gaW5pdGlhbGl6ZWQuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHJpdmF0ZSBpc1ZpZXdJbml0aWFsaXplZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBbQ3l0b3NjYXBlLmpzIGNvcmVde0BsaW5rIGh0dHBzOi8vanMuY3l0b3NjYXBlLm9yZy8jY29yZX0gdGhhdCBpcyByZW5kZXJlZC5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwcml2YXRlIGNvcmUhOiBDb3JlO1xuXG4gIC8qKlxuICAgKiBTZXJ2ZXMgYXMgYW4gaW5kaWNhdG9yLCB3aGVuIHRoZSBjb21wb25lbnQgaGFzIGJlZW4gZGVzdHJveWVkLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByaXZhdGUgZGVzdHJveSQ6IFN1YmplY3Q8Ym9vbGVhbj4gPSBuZXcgU3ViamVjdDxib29sZWFuPigpO1xuXG4gIC8qKlxuICAgKiBTZXJ2aWNlIHJlc3BvbnNpYmxlIGZvciBjb252ZXJzaW9uXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHJpdmF0ZSBjeFNlcnZpY2UgPSBpbmplY3QoQ3hTZXJ2aWNlKTtcblxuICAvKipcbiAgICogW0FuZ3VsYXIgbGlmZWN5Y2xlXXtAbGluayBodHRwczovL2FuZ3VsYXIuaW8vZ3VpZGUvbGlmZWN5Y2xlLWhvb2tzfSB3aGljaCBpcyBjYWxsZWQgYXMgc29vbiBhcyB0aGUgdmlldyBoYXMgYmVlbiBpbml0aWFsaXplZC5cbiAgICogVXNlZCB0byBzdWJzY3JpYmUgdG8gYW55IHdpbmRvdyByZXNpemUgZXZlbnQuIFRyaWdnZXJzIGluaXRpYWwgcmVuZGVyaW5nLlxuICAgKi9cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIGZyb21FdmVudCh3aW5kb3csICdyZXNpemUnKVxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpLCBkZWJvdW5jZVRpbWUoMzAwKSlcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5maXQoKSk7XG5cbiAgICB0aGlzLmlzVmlld0luaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB0aGlzLnByZVJlbmRlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFtBbmd1bGFyIGxpZmVjeWNsZV17QGxpbmsgaHR0cHM6Ly9hbmd1bGFyLmlvL2d1aWRlL2xpZmVjeWNsZS1ob29rc30gd2hpY2ggaXMgY2FsbGVkIGV2ZXJ5IHRpbWUsIGFuIGlucHV0IHByb3BlcnR5IGNoYW5nZXMgaXRzIHZhbHVlLlxuICAgKiBVc2VkIHRvIHVwZGF0ZSB0aGUgZ3JhcGgncyB2aXN1YWxpemF0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0ge1NpbXBsZUNoYW5nZXN9IGNoYW5nZXMgT2JqZWN0IGNvbnRhaW5pbmcgYWxsIGNoYW5nZXNcbiAgICovXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBjb25zdCB7IGN5dG9zY2FwZU9wdGlvbnMsIGN4RGF0YSwgYXV0b0ZpdCB9ID0gY2hhbmdlcztcblxuICAgIGlmIChjeXRvc2NhcGVPcHRpb25zIHx8IGN4RGF0YSkge1xuICAgICAgdGhpcy5wcmVSZW5kZXIoKTtcbiAgICB9XG5cbiAgICBpZiAoYXV0b0ZpdCkge1xuICAgICAgdGhpcy5maXQoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogW0FuZ3VsYXIgbGlmZWN5Y2xlXXtAbGluayBodHRwczovL2FuZ3VsYXIuaW8vZ3VpZGUvbGlmZWN5Y2xlLWhvb2tzfSB3aGljaCBpcyBjYWxsZWQgYXMgc29vbiBhcyB0aGUgY29tcG9uZW50IGlzIGRlc3Ryb3llZC5cbiAgICogVXNlZCB0byB1bnN1YnNjcmliZSBmcm9tIHdpbmRvdyByZXNpemUgZXZlbnRzLlxuICAgKi9cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KHRydWUpO1xuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCYXNlZCBvbiB0aGUgdXNlcidzIGlucHV0LCB0aGlzIG1ldGhvZCBkZWNpZGVzLCBpZiByZW5kZXJpbmcgY2FuIGhhcHBlbiBhbmQgd2hpY2ggaW5wdXQgaXMgdG8gYmUgdXNlZC5cbiAgICovXG4gIHByaXZhdGUgcHJlUmVuZGVyKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pc1ZpZXdJbml0aWFsaXplZCB8fCAoIXRoaXMuY3l0b3NjYXBlT3B0aW9ucyAmJiAhdGhpcy5jeERhdGEpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY3l0b3NjYXBlT3B0aW9ucykge1xuICAgICAgdGhpcy5yZW5kZXIodGhpcy5jeXRvc2NhcGVPcHRpb25zKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuY3hEYXRhKSB7XG4gICAgICBjb25zdCBjb252ZXJzaW9uID0gdGhpcy5jeFNlcnZpY2UuY29udmVydCh0aGlzLmN4RGF0YSwgdGhpcy5jeENvbnZlcnRlcnMpO1xuXG4gICAgICBpZiAoY29udmVyc2lvbikge1xuICAgICAgICBjb25zdCB7IG9wdGlvbnMsIGF0dHJpYnV0ZU5hbWVNYXAsIGJhY2tncm91bmRDb2xvciB9ID0gY29udmVyc2lvbjtcblxuICAgICAgICBpZiAodGhpcy5jeUVsZW1lbnRSZWYgJiYgdGhpcy5jeUVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCkge1xuICAgICAgICAgIGNvbnN0IGh0bWxFbGVtZW50OiBIVE1MRWxlbWVudCA9IHRoaXMuY3lFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG5cbiAgICAgICAgICBpZiAodGhpcy5hcHBseUN4QmFja2dyb3VuZENvbG9yICYmIGJhY2tncm91bmRDb2xvcikge1xuICAgICAgICAgICAgaHRtbEVsZW1lbnQuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gYmFja2dyb3VuZENvbG9yO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBodG1sRWxlbWVudC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAnJztcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmN4QXR0cmlidXRlTmFtZU1hcENoYW5nZWQuZW1pdChhdHRyaWJ1dGVOYW1lTWFwKTtcblxuICAgICAgICBpZiAob3B0aW9ucykge1xuICAgICAgICAgIHRoaXMucmVuZGVyKG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbmRlcnMgdGhlIGdyYXBoIHVzaW5nIFtDeXRvc2NhcGVPcHRpb25zXXtAbGluayBodHRwczovL2dpdGh1Yi5jb20vRGVmaW5pdGVseVR5cGVkL0RlZmluaXRlbHlUeXBlZC9ibG9iL21hc3Rlci90eXBlcy9jeXRvc2NhcGUvaW5kZXguZC50c30uXG4gICAqXG4gICAqIEBwYXJhbSB7Q3l0b3NjYXBlT3B0aW9uc30gb3B0aW9ucyBPYmplY3QgY29udGFpbmluZyBncmFwaCBpbmZvcm1hdGlvblxuICAgKi9cbiAgcHJpdmF0ZSByZW5kZXIob3B0aW9uczogQ3l0b3NjYXBlT3B0aW9ucyk6IHZvaWQge1xuICAgIGlmIChvcHRpb25zKSB7XG4gICAgICB0aGlzLmNvcmUgPSBjeXRvc2NhcGUoe1xuICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICBjb250YWluZXI6IHRoaXMuY3lFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuY29yZS5maXQoKTtcbiAgICAgIHRoaXMuY29yZUNoYW5nZWQuZW1pdCh0aGlzLmNvcmUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNpemVzIGFuZCByZXBvc2l0aW9ucyB0aGUgZ3JhcGggdG8gZml0IHRoZSBjdXJyZW50IHdpbmRvdyBzaXplLlxuICAgKi9cbiAgcHJpdmF0ZSBmaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuYXV0b0ZpdCAmJiB0aGlzLmNvcmUpIHtcbiAgICAgIHRoaXMuY29yZS5maXQoKTtcbiAgICB9XG4gIH1cbn1cbiIsIjxkaXYgaWQ9XCJjeVwiICNjeT48L2Rpdj5cbiJdfQ==