UNPKG

@cisstech/nge

Version:

NG Essentials is a collection of libraries for Angular developers.

154 lines 23.2 kB
import { HttpClient } from '@angular/common/http'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector, ViewChild, ViewContainerRef, inject, } from '@angular/core'; import { CompilerService } from '@cisstech/nge/services'; import { firstValueFrom } from 'rxjs'; import { NGE_DOC_RENDERERS } from '../nge-doc'; import { NgeDocService } from '../nge-doc.service'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; export class NgeDocRendererComponent { constructor() { this.injector = inject(Injector); this.renderers = inject(NGE_DOC_RENDERERS); this.docService = inject(NgeDocService); this.compilerService = inject(CompilerService); this.changeDetectorRef = inject(ChangeDetectorRef); this.subscriptions = []; this.loading = false; this.noFound = false; this.componentRefByTypes = new Map(); } ngOnInit() { this.subscriptions.push(this.docService.stateChanges.subscribe(this.onChangeState.bind(this))); } ngOnDestroy() { this.clearViewContainer(); this.subscriptions.forEach((s) => s.unsubscribe()); } showLoading() { this.loading = true; // if loading is still true after 1s then we force change detection // This is useful to show the loading indicator only if the loading is not too fast // so that the loading indicator does not blink. setTimeout(() => { if (this.loading) { this.changeDetectorRef.markForCheck(); } }, 1000); } clearViewContainer() { const componentRefs = Array.from(this.componentRefByTypes.values()); if (this.componentRef && componentRefs.includes(this.componentRef)) { while (this.container.length > 0) { this.container.detach(); } } else { this.componentRef?.destroy(); this.componentRef = undefined; this.container.clear(); } } async onChangeState(state) { try { this.showLoading(); this.clearViewContainer(); if (state.currLink) { const renderer = await state.currLink.renderer; switch (typeof renderer) { case 'string': await this.renderMarkdown(renderer); break; case 'function': this.componentRef = await this.compilerService.render({ type: await renderer(), inputs: state.currLink.inputs, container: this.container, }); break; } } } catch (error) { console.error(error); } finally { this.loading = false; this.noFound = !this.componentRef; this.changeDetectorRef.markForCheck(); } } async renderMarkdown(data) { if (!this.renderers?.markdown) { throw new Error('[nge-doc]: missing markdown renderer.'); } const renderer = this.renderers.markdown; const type = await renderer.component(); const createInputs = async () => { let inputs = { data, // we assume that data is a markdown content. }; if (!data.includes('\n')) { // if data does not include at least two lines then it's an url const http = this.injector.get(HttpClient, null); if (!http) { throw new Error('[nge-doc] When using the `file` renderer you *have to* pass the `HttpClient` as a parameter of the `forRoot` method. See README for more information'); } inputs = { data: await firstValueFrom(http.get(data, { responseType: 'text' })), }; } let customInputs = {}; if (typeof renderer.inputs === 'function') { customInputs = await renderer.inputs(this.injector); } else if (typeof renderer.inputs === 'object') { customInputs = renderer.inputs; } return { ...customInputs, ...inputs }; }; const markdownComponent = this.componentRefByTypes.get(type); if (markdownComponent) { this.attachComponent(markdownComponent, await createInputs()); return; } const componentRef = await this.compilerService.render({ type, inputs: await createInputs(), container: this.container, }); this.componentRef = componentRef; this.componentRefByTypes.set(type, componentRef); } async attachComponent(componentRef, inputs) { this.container.insert(componentRef.hostView); this.componentRef = componentRef; // compute changes const changes = {}; const { instance, changeDetectorRef } = componentRef; Object.keys(inputs).forEach((key) => { changes[key] = { currentValue: inputs[key], previousValue: instance[key], firstChange: false, isFirstChange: () => false, }; instance[key] = inputs[key]; }); // call ngOnChanges if (instance.ngOnChanges) { await instance.ngOnChanges(changes); } changeDetectorRef.markForCheck(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: NgeDocRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.1", type: NgeDocRendererComponent, selector: "nge-doc-renderer", viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div class=\"loading-container\" *ngIf=\"loading\">\n <div class=\"loading-spinner\"></div>\n <div class=\"loading-text\">Loading...</div>\n</div>\n<div *ngIf=\"noFound\">\n <h1>Ooops!</h1>\n <hr />\n <p>It looks like this page doesn't exist.</p>\n</div>\n<div #container></div>\n", styles: [":host{display:block;width:100%;position:relative}.loading-container{display:flex;align-items:center;flex-direction:column;justify-content:center}.loading-spinner{border:4px solid rgba(0,0,0,.1);border-top:4px solid var(--nge-doc-primary-color);border-radius:50%;width:40px;height:40px;animation:spin 1s linear infinite;margin-bottom:20px}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.loading-text{font-family:Arial,sans-serif;font-size:18px;color:#333}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: NgeDocRendererComponent, decorators: [{ type: Component, args: [{ selector: 'nge-doc-renderer', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"loading-container\" *ngIf=\"loading\">\n <div class=\"loading-spinner\"></div>\n <div class=\"loading-text\">Loading...</div>\n</div>\n<div *ngIf=\"noFound\">\n <h1>Ooops!</h1>\n <hr />\n <p>It looks like this page doesn't exist.</p>\n</div>\n<div #container></div>\n", styles: [":host{display:block;width:100%;position:relative}.loading-container{display:flex;align-items:center;flex-direction:column;justify-content:center}.loading-spinner{border:4px solid rgba(0,0,0,.1);border-top:4px solid var(--nge-doc-primary-color);border-radius:50%;width:40px;height:40px;animation:spin 1s linear infinite;margin-bottom:20px}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.loading-text{font-family:Arial,sans-serif;font-size:18px;color:#333}\n"] }] }], propDecorators: { container: [{ type: ViewChild, args: ['container', { read: ViewContainerRef, static: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVuZGVyZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmdlL2RvYy9zcmMvcmVuZGVyZXIvcmVuZGVyZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmdlL2RvYy9zcmMvcmVuZGVyZXIvcmVuZGVyZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFBO0FBQ2pELE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFFVCxRQUFRLEVBS1IsU0FBUyxFQUNULGdCQUFnQixFQUNoQixNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUE7QUFDdEIsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFBO0FBQ3hELE9BQU8sRUFBZ0IsY0FBYyxFQUFFLE1BQU0sTUFBTSxDQUFBO0FBQ25ELE9BQU8sRUFBRSxpQkFBaUIsRUFBZSxNQUFNLFlBQVksQ0FBQTtBQUMzRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sb0JBQW9CLENBQUE7OztBQVFsRCxNQUFNLE9BQU8sdUJBQXVCO0lBTnBDO1FBT21CLGFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDM0IsY0FBUyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1FBQ3JDLGVBQVUsR0FBRyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUE7UUFDbEMsb0JBQWUsR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUE7UUFDekMsc0JBQWlCLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUE7UUFFdEQsa0JBQWEsR0FBbUIsRUFBRSxDQUFBO1FBQ2hDLFlBQU8sR0FBRyxLQUFLLENBQUE7UUFDZixZQUFPLEdBQUcsS0FBSyxDQUFBO1FBQ2Ysd0JBQW1CLEdB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WUFBWSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUM7Z0JBQ3pCLGFBQWEsRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDO2dCQUM1QixXQUFXLEVBQUUsS0FBSztnQkFDbEIsYUFBYSxFQUFFLEdBQUcsRUFBRSxDQUFDLEtBQUs7YUFDM0IsQ0FBQTtZQUNELFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDN0IsQ0FBQyxDQUFDLENBQUE7UUFFRixtQkFBbUI7UUFDbkIsSUFBSSxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDekIsTUFBTSxRQUFRLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQ3JDLENBQUM7UUFFRCxpQkFBaUIsQ0FBQyxZQUFZLEVBQUUsQ0FBQTtJQUNsQyxDQUFDOzhHQTdKVSx1QkFBdUI7a0dBQXZCLHVCQUF1QiwySUFjRixnQkFBZ0IsMkNDeENsRCwrUkFVQTs7MkZEZ0JhLHVCQUF1QjtrQkFObkMsU0FBUzsrQkFDRSxrQkFBa0IsbUJBR1gsdUJBQXVCLENBQUMsTUFBTTs4QkFpQi9DLFNBQVM7c0JBRFIsU0FBUzt1QkFBQyxXQUFXLEVBQUUsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCdcbmltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBDb21wb25lbnRSZWYsXG4gIEluamVjdG9yLFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVHlwZSxcbiAgVmlld0NoaWxkLFxuICBWaWV3Q29udGFpbmVyUmVmLFxuICBpbmplY3QsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnXG5pbXBvcnQgeyBDb21waWxlclNlcnZpY2UgfSBmcm9tICdAY2lzc3RlY2gvbmdlL3NlcnZpY2VzJ1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uLCBmaXJzdFZhbHVlRnJvbSB9IGZyb20gJ3J4anMnXG5pbXBvcnQgeyBOR0VfRE9DX1JFTkRFUkVSUywgTmdlRG9jU3RhdGUgfSBmcm9tICcuLi9uZ2UtZG9jJ1xuaW1wb3J0IHsgTmdlRG9jU2VydmljZSB9IGZyb20gJy4uL25nZS1kb2Muc2VydmljZSdcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmdlLWRvYy1yZW5kZXJlcicsXG4gIHRlbXBsYXRlVXJsOiAncmVuZGVyZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsncmVuZGVyZXIuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIE5nZURvY1JlbmRlcmVyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICBwcml2YXRlIHJlYWRvbmx5IGluamVjdG9yID0gaW5qZWN0KEluamVjdG9yKVxuICBwcml2YXRlIHJlYWRvbmx5IHJlbmRlcmVycyA9IGluamVjdChOR0VfRE9DX1JFTkRFUkVSUylcbiAgcHJpdmF0ZSByZWFkb25seSBkb2NTZXJ2aWNlID0gaW5qZWN0KE5nZURvY1NlcnZpY2UpXG4gIHByaXZhdGUgcmVhZG9ubHkgY29tcGlsZXJTZXJ2aWNlID0gaW5qZWN0KENvbXBpbGVyU2VydmljZSlcbiAgcHJpdmF0ZSByZWFkb25seSBjaGFuZ2VEZXRlY3RvclJlZiA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZilcblxuICBwcml2YXRlIHN1YnNjcmlwdGlvbnM6IFN1YnNjcmlwdGlvbltdID0gW11cbiAgcHJvdGVjdGVkIGxvYWRpbmcgPSBmYWxzZVxuICBwcm90ZWN0ZWQgbm9Gb3VuZCA9IGZhbHNlXG4gIHByb3RlY3RlZCBjb21wb25lbnRSZWZCeVR5cGVzID0gbmV3IE1hcDxUeXBlPGFueT4sIENvbXBvbmVudFJlZjxhbnk+PigpXG5cbiAgY29tcG9uZW50UmVmPzogQ29tcG9uZW50UmVmPGFueT5cblxuICBAVmlld0NoaWxkKCdjb250YWluZXInLCB7IHJlYWQ6IFZpZXdDb250YWluZXJSZWYsIHN0YXRpYzogdHJ1ZSB9KVxuICBjb250YWluZXIhOiBWaWV3Q29udGFpbmVyUmVmXG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2godGhpcy5kb2NTZXJ2aWNlLnN0YXRlQ2hhbmdlcy5zdWJzY3JpYmUodGhpcy5vbkNoYW5nZVN0YXRlLmJpbmQodGhpcykpKVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5jbGVhclZpZXdDb250YWluZXIoKVxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5mb3JFYWNoKChzKSA9PiBzLnVuc3Vic2NyaWJlKCkpXG4gIH1cblxuICBwcml2YXRlIHNob3dMb2FkaW5nKCk6IHZvaWQge1xuICAgIHRoaXMubG9hZGluZyA9IHRydWVcblxuICAgIC8vIGlmIGxvYWRpbmcgaXMgc3RpbGwgdHJ1ZSBhZnRlciAxcyB0aGVuIHdlIGZvcmNlIGNoYW5nZSBkZXRlY3Rpb25cbiAgICAvLyBUaGlzIGlzIHVzZWZ1bCB0byBzaG93IHRoZSBsb2FkaW5nIGluZGljYXRvciBvbmx5IGlmIHRoZSBsb2FkaW5nIGlzIG5vdCB0b28gZmFzdFxuICAgIC8vIHNvIHRoYXQgdGhlIGxvYWRpbmcgaW5kaWNhdG9yIGRvZXMgbm90IGJsaW5rLlxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMubG9hZGluZykge1xuICAgICAgICB0aGlzLmNoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpXG4gICAgICB9XG4gICAgfSwgMTAwMClcbiAgfVxuXG4gIHByaXZhdGUgY2xlYXJWaWV3Q29udGFpbmVyKCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbXBvbmVudFJlZnMgPSBBcnJheS5mcm9tKHRoaXMuY29tcG9uZW50UmVmQnlUeXBlcy52YWx1ZXMoKSlcbiAgICBpZiAodGhpcy5jb21wb25lbnRSZWYgJiYgY29tcG9uZW50UmVmcy5pbmNsdWRlcyh0aGlzLmNvbXBvbmVudFJlZikpIHtcbiAgICAgIHdoaWxlICh0aGlzLmNvbnRhaW5lci5sZW5ndGggPiAwKSB7XG4gICAgICAgIHRoaXMuY29udGFpbmVyLmRldGFjaCgpXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY29tcG9uZW50UmVmPy5kZXN0cm95KClcbiAgICAgIHRoaXMuY29tcG9uZW50UmVmID0gdW5kZWZpbmVkXG4gICAgICB0aGlzLmNvbnRhaW5lci5jbGVhcigpXG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBvbkNoYW5nZVN0YXRlKHN0YXRlOiBOZ2VEb2NTdGF0ZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLnNob3dMb2FkaW5nKClcbiAgICAgIHRoaXMuY2xlYXJWaWV3Q29udGFpbmVyKClcblxuICAgICAgaWYgKHN0YXRlLmN1cnJMaW5rKSB7XG4gICAgICAgIGNvbnN0IHJlbmRlcmVyID0gYXdhaXQgc3RhdGUuY3VyckxpbmsucmVuZGVyZXJcbiAgICAgICAgc3dpdGNoICh0eXBlb2YgcmVuZGVyZXIpIHtcbiAgICAgICAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgICAgICAgYXdhaXQgdGhpcy5yZW5kZXJNYXJrZG93bihyZW5kZXJlcilcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgY2FzZSAnZnVuY3Rpb24nOlxuICAgICAgICAgICAgdGhpcy5jb21wb25lbnRSZWYgPSBhd2FpdCB0aGlzLmNvbXBpbGVyU2VydmljZS5yZW5kZXIoe1xuICAgICAgICAgICAgICB0eXBlOiBhd2FpdCByZW5kZXJlcigpLFxuICAgICAgICAgICAgICBpbnB1dHM6IHN0YXRlLmN1cnJMaW5rLmlucHV0cyxcbiAgICAgICAgICAgICAgY29udGFpbmVyOiB0aGlzLmNvbnRhaW5lcixcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlXG4gICAgICB0aGlzLm5vRm91bmQgPSAhdGhpcy5jb21wb25lbnRSZWZcbiAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKClcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlbmRlck1hcmtkb3duKGRhdGE6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5yZW5kZXJlcnM/Lm1hcmtkb3duKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1tuZ2UtZG9jXTogbWlzc2luZyBtYXJrZG93biByZW5kZXJlci4nKVxuICAgIH1cblxuICAgIGNvbnN0IHJlbmRlcmVyID0gdGhpcy5yZW5kZXJlcnMubWFya2Rvd25cbiAgICBjb25zdCB0eXBlID0gYXdhaXQgcmVuZGVyZXIuY29tcG9uZW50KClcblxuICAgIGNvbnN0IGNyZWF0ZUlucHV0cyA9IGFzeW5jICgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+ID0+IHtcbiAgICAgIGxldCBpbnB1dHM6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7XG4gICAgICAgIGRhdGEsIC8vIHdlIGFzc3VtZSB0aGF0IGRhdGEgaXMgYSBtYXJrZG93biBjb250ZW50LlxuICAgICAgfVxuXG4gICAgICBpZiAoIWRhdGEuaW5jbHVkZXMoJ1xcbicpKSB7XG4gICAgICAgIC8vIGlmIGRhdGEgZG9lcyBub3QgaW5jbHVkZSBhdCBsZWFzdCB0d28gbGluZXMgdGhlbiBpdCdzIGFuIHVybFxuICAgICAgICBjb25zdCBodHRwID0gdGhpcy5pbmplY3Rvci5nZXQoSHR0cENsaWVudCwgbnVsbClcbiAgICAgICAgaWYgKCFodHRwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgJ1tuZ2UtZG9jXSBXaGVuIHVzaW5nIHRoZSBgZmlsZWAgcmVuZGVyZXIgeW91ICpoYXZlIHRvKiBwYXNzIHRoZSBgSHR0cENsaWVudGAgYXMgYSBwYXJhbWV0ZXIgb2YgdGhlIGBmb3JSb290YCBtZXRob2QuIFNlZSBSRUFETUUgZm9yIG1vcmUgaW5mb3JtYXRpb24nXG4gICAgICAgICAgKVxuICAgICAgICB9XG5cbiAgICAgICAgaW5wdXRzID0ge1xuICAgICAgICAgIGRhdGE6IGF3YWl0IGZpcnN0VmFsdWVGcm9tKGh0dHAuZ2V0KGRhdGEsIHsgcmVzcG9uc2VUeXBlOiAndGV4dCcgfSkpLFxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGxldCBjdXN0b21JbnB1dHM6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fVxuICAgICAgaWYgKHR5cGVvZiByZW5kZXJlci5pbnB1dHMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY3VzdG9tSW5wdXRzID0gYXdhaXQgcmVuZGVyZXIuaW5wdXRzKHRoaXMuaW5qZWN0b3IpXG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiByZW5kZXJlci5pbnB1dHMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGN1c3RvbUlucHV0cyA9IHJlbmRlcmVyLmlucHV0c1xuICAgICAgfVxuXG4gICAgICByZXR1cm4geyAuLi5jdXN0b21JbnB1dHMsIC4uLmlucHV0cyB9XG4gICAgfVxuXG4gICAgY29uc3QgbWFya2Rvd25Db21wb25lbnQgPSB0aGlzLmNvbXBvbmVudFJlZkJ5VHlwZXMuZ2V0KHR5cGUpXG4gICAgaWYgKG1hcmtkb3duQ29tcG9uZW50KSB7XG4gICAgICB0aGlzLmF0dGFjaENvbXBvbmVudChtYXJrZG93bkNvbXBvbmVudCwgYXdhaXQgY3JlYXRlSW5wdXRzKCkpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBjb25zdCBjb21wb25lbnRSZWYgPSBhd2FpdCB0aGlzLmNvbXBpbGVyU2VydmljZS5yZW5kZXIoe1xuICAgICAgdHlwZSxcbiAgICAgIGlucHV0czogYXdhaXQgY3JlYXRlSW5wdXRzKCksXG4gICAgICBjb250YWluZXI6IHRoaXMuY29udGFpbmVyLFxuICAgIH0pXG5cbiAgICB0aGlzLmNvbXBvbmVudFJlZiA9IGNvbXBvbmVudFJlZlxuICAgIHRoaXMuY29tcG9uZW50UmVmQnlUeXBlcy5zZXQodHlwZSwgY29tcG9uZW50UmVmKVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBhdHRhY2hDb21wb25lbnQoY29tcG9uZW50UmVmOiBDb21wb25lbnRSZWY8YW55PiwgaW5wdXRzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5jb250YWluZXIuaW5zZXJ0KGNvbXBvbmVudFJlZi5ob3N0VmlldylcbiAgICB0aGlzLmNvbXBvbmVudFJlZiA9IGNvbXBvbmVudFJlZlxuXG4gICAgLy8gY29tcHV0ZSBjaGFuZ2VzXG4gICAgY29uc3QgY2hhbmdlczogU2ltcGxlQ2hhbmdlcyA9IHt9XG4gICAgY29uc3QgeyBpbnN0YW5jZSwgY2hhbmdlRGV0ZWN0b3JSZWYgfSA9IGNvbXBvbmVudFJlZlxuICAgIE9iamVjdC5rZXlzKGlucHV0cykuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICBjaGFuZ2VzW2tleV0gPSB7XG4gICAgICAgIGN1cnJlbnRWYWx1ZTogaW5wdXRzW2tleV0sXG4gICAgICAgIHByZXZpb3VzVmFsdWU6IGluc3RhbmNlW2tleV0sXG4gICAgICAgIGZpcnN0Q2hhbmdlOiBmYWxzZSxcbiAgICAgICAgaXNGaXJzdENoYW5nZTogKCkgPT4gZmFsc2UsXG4gICAgICB9XG4gICAgICBpbnN0YW5jZVtrZXldID0gaW5wdXRzW2tleV1cbiAgICB9KVxuXG4gICAgLy8gY2FsbCBuZ09uQ2hhbmdlc1xuICAgIGlmIChpbnN0YW5jZS5uZ09uQ2hhbmdlcykge1xuICAgICAgYXdhaXQgaW5zdGFuY2UubmdPbkNoYW5nZXMoY2hhbmdlcylcbiAgICB9XG5cbiAgICBjaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKVxuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwibG9hZGluZy1jb250YWluZXJcIiAqbmdJZj1cImxvYWRpbmdcIj5cbiAgPGRpdiBjbGFzcz1cImxvYWRpbmctc3Bpbm5lclwiPjwvZGl2PlxuICA8ZGl2IGNsYXNzPVwibG9hZGluZy10ZXh0XCI+TG9hZGluZy4uLjwvZGl2PlxuPC9kaXY+XG48ZGl2ICpuZ0lmPVwibm9Gb3VuZFwiPlxuICA8aDE+T29vcHMhPC9oMT5cbiAgPGhyIC8+XG4gIDxwPkl0IGxvb2tzIGxpa2UgdGhpcyBwYWdlIGRvZXNuJ3QgZXhpc3QuPC9wPlxuPC9kaXY+XG48ZGl2ICNjb250YWluZXI+PC9kaXY+XG4iXX0=