UNPKG

ngx-dynamic-hooks

Version:

Automatically insert live Angular components into a dynamic string of content (based on their selector or any pattern of your choice) and render the result in the DOM.

123 lines 21.1 kB
import { Injectable } from '@angular/core'; import * as i0 from "@angular/core"; import * as i1 from "../../services/utils/dataTypeParser"; import * as i2 from "../../services/utils/logger"; /** * A helper service for the SelectorHookParsers that evaluates bindings and only updates them when needed so references are retained when possible */ export class BindingsValueManager { constructor(dataTypeParser, logger) { this.dataTypeParser = dataTypeParser; this.logger = logger; } // Inputs // ------------------------------------------------------------------------------------- /** * Checks input bindings and evaluates/updates them as needed * * @param bindings - A list of @Input() bindings * @param context - The current context object * @param parserConfig - The parser config * @param options - The current ParseOptions */ checkInputBindings(bindings, context, parserConfig, options) { for (const [inputName, inputBinding] of Object.entries(bindings)) { // If no need to parse, use raw as value if (!parserConfig.parseInputs) { inputBinding.value = inputBinding.raw; } else { // If not yet parsed, do so if (!inputBinding.parsed) { try { inputBinding.value = this.dataTypeParser.evaluate(inputBinding.raw, parserConfig.allowContextInBindings ? context : {}, undefined, parserConfig.unescapeStrings, inputBinding.boundContextVariables, parserConfig.allowContextFunctionCalls, options); inputBinding.parsed = true; } catch (e) { this.logger.error([`Hook input parsing error\nselector: ` + parserConfig.selector + `\ninput: ` + inputName + `\nvalue: "` + inputBinding.value + `"`], options); this.logger.error([e.stack], options); // If binding could not be parsed at all due to syntax error, remove from list of inputs. // No amount of calls to updateInputBindings() will fix this kind of error. delete bindings[inputName]; } // Otherwise check if needs an update } else { this.updateInputBindingIfStale(inputBinding, context, parserConfig); } } } } /** * We can detect if a binding needs to be reevaluated via the bound context variables. There are three cases to consider: * * a) If a binding does not use context vars, don't reevaluate (binding is static and won't ever need to be updated) * b) If a binding does use context vars, but context vars haven't changed, don't reevaluate either (would evalute the same) * c) If a binding uses context vars and they have changed, reevaluate the binding from scratch to get the new version * * This is in line with the standard Angular behavior when evaluating template vars like [input]="{prop: this.something}". * When 'this.something' changes so that it returns false on a === comparison with its previous value, Angular does not * simply replace the reference bound to 'prop', but recreates the whole object literal and passes a new reference into the * input, triggering ngOnChanges. * * @param binding - The previous bindings * @param context - The current context object * @param parserConfig - The current parser config */ updateInputBindingIfStale(binding, context, parserConfig) { if (Object.keys(binding.boundContextVariables).length > 0) { // Check if bound context vars have changed let boundContextVarHasChanged = false; for (const [contextVarName, contextVarValue] of Object.entries(binding.boundContextVariables)) { const encodedContextVarName = this.dataTypeParser.encodeDataTypeString(contextVarName); // Compare with previous value const newContextVarValue = this.dataTypeParser.loadContextVariable(encodedContextVarName, context, undefined, parserConfig.unescapeStrings, {}, parserConfig.allowContextFunctionCalls); if (newContextVarValue !== contextVarValue) { boundContextVarHasChanged = true; break; } } // Bound context var has changed! Reevaluate whole binding (which may include more than one context var, or point to some child property) if (boundContextVarHasChanged) { binding.boundContextVariables = {}; binding.value = this.dataTypeParser.evaluate(binding.raw, parserConfig.allowContextInBindings ? context : {}, undefined, parserConfig.unescapeStrings, binding.boundContextVariables, parserConfig.allowContextFunctionCalls); } } } // Outputs // ------------------------------------------------------------------------------------- /** * Checks output bindings and evaluates/updates them as needed * * @param bindings - A list of @Output() bindings * @param parserConfig - The current parser config * @param options - The current ParseOptions */ checkOutputBindings(bindings, parserConfig, options) { for (const [outputName, outputBinding] of Object.entries(bindings)) { // Unlike inputs, outputs only need to be created once by the parser, never updated, as you only create a wrapper function around the logic to execute. // As this logic is run fresh whenever the output triggers, there is no need to replace this wrapper function on updates. if (!outputBinding.parsed) { outputBinding.value = (event, context) => { try { this.dataTypeParser.evaluate(outputBinding.raw, parserConfig.allowContextInBindings ? context : {}, event, parserConfig.unescapeStrings, outputBinding.boundContextVariables, parserConfig.allowContextFunctionCalls); } catch (e) { this.logger.error([`Hook output parsing error\nselector: ` + parserConfig.selector + `\noutput: ` + outputName + `\nvalue: "` + outputBinding.value + `"`], options); this.logger.error([e.stack], options); } }; outputBinding.parsed = true; } } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BindingsValueManager, deps: [{ token: i1.DataTypeParser }, { token: i2.Logger }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BindingsValueManager, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BindingsValueManager, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.DataTypeParser }, { type: i2.Logger }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmluZGluZ3NWYWx1ZU1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZHluYW1pYy1ob29rcy9zcmMvbGliL3BhcnNlcnMvc2VsZWN0b3IvYmluZGluZ3NWYWx1ZU1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7OztBQVMzQzs7R0FFRztBQUlILE1BQU0sT0FBTyxvQkFBb0I7SUFFL0IsWUFBb0IsY0FBOEIsRUFBVSxNQUFjO1FBQXRELG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUFVLFdBQU0sR0FBTixNQUFNLENBQVE7SUFDMUUsQ0FBQztJQUVELFNBQVM7SUFDVCx3RkFBd0Y7SUFFeEY7Ozs7Ozs7T0FPRztJQUNILGtCQUFrQixDQUFDLFFBQTBDLEVBQUUsT0FBWSxFQUFFLFlBQXNDLEVBQUUsT0FBcUI7UUFDeEksS0FBSyxNQUFNLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztZQUNqRSx3Q0FBd0M7WUFDeEMsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDOUIsWUFBWSxDQUFDLEtBQUssR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDO1lBRXhDLENBQUM7aUJBQU0sQ0FBQztnQkFDTiwyQkFBMkI7Z0JBQzNCLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLENBQUM7b0JBQ3pCLElBQUksQ0FBQzt3QkFDSCxZQUFZLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUMvQyxZQUFZLENBQUMsR0FBRyxFQUNoQixZQUFZLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUNsRCxTQUFTLEVBQ1QsWUFBWSxDQUFDLGVB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QUFhLENBQUMsS0FBSyxHQUFHLENBQUMsS0FBVSxFQUFFLE9BQVksRUFBRSxFQUFFO29CQUNqRCxJQUFJLENBQUM7d0JBQ0gsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQzFCLGFBQWEsQ0FBQyxHQUFHLEVBQ2pCLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQ2xELEtBQUssRUFDTCxZQUFZLENBQUMsZUFBZSxFQUM1QixhQUFhLENBQUMscUJBQXFCLEVBQ25DLFlBQVksQ0FBQyx5QkFBeUIsQ0FDdkMsQ0FBQztvQkFDSixDQUFDO29CQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7d0JBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsdUNBQXVDLEdBQUcsWUFBWSxDQUFDLFFBQVEsR0FBSSxZQUFZLEdBQUcsVUFBVSxHQUFHLFlBQVksR0FBRyxhQUFhLENBQUMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO3dCQUN0SyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztvQkFDeEMsQ0FBQztnQkFDSCxDQUFDLENBQUM7Z0JBQ0YsYUFBYSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7WUFDOUIsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDOytHQW5JVSxvQkFBb0I7bUhBQXBCLG9CQUFvQixjQUZuQixNQUFNOzs0RkFFUCxvQkFBb0I7a0JBSGhDLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBEYXRhVHlwZVBhcnNlciB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3V0aWxzL2RhdGFUeXBlUGFyc2VyJztcbmltcG9ydCB7IFNlbGVjdG9ySG9va1BhcnNlckNvbmZpZyB9IGZyb20gJy4vc2VsZWN0b3JIb29rUGFyc2VyQ29uZmlnJztcbmltcG9ydCB7IFJpY2hCaW5kaW5nRGF0YSB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvdXRpbHMvbG9nZ2VyJztcbmltcG9ydCB7IFBhcnNlT3B0aW9ucyB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3NldHRpbmdzL29wdGlvbnMnO1xuXG5cbi8qKlxuICogQSBoZWxwZXIgc2VydmljZSBmb3IgdGhlIFNlbGVjdG9ySG9va1BhcnNlcnMgdGhhdCBldmFsdWF0ZXMgYmluZGluZ3MgYW5kIG9ubHkgdXBkYXRlcyB0aGVtIHdoZW4gbmVlZGVkIHNvIHJlZmVyZW5jZXMgYXJlIHJldGFpbmVkIHdoZW4gcG9zc2libGVcbiAqL1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgQmluZGluZ3NWYWx1ZU1hbmFnZXIge1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZGF0YVR5cGVQYXJzZXI6IERhdGFUeXBlUGFyc2VyLCBwcml2YXRlIGxvZ2dlcjogTG9nZ2VyKSB7XG4gIH1cblxuICAvLyBJbnB1dHNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaW5wdXQgYmluZGluZ3MgYW5kIGV2YWx1YXRlcy91cGRhdGVzIHRoZW0gYXMgbmVlZGVkXG4gICAqXG4gICAqIEBwYXJhbSBiaW5kaW5ncyAtIEEgbGlzdCBvZiBASW5wdXQoKSBiaW5kaW5nc1xuICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjdXJyZW50IGNvbnRleHQgb2JqZWN0XG4gICAqIEBwYXJhbSBwYXJzZXJDb25maWcgLSBUaGUgcGFyc2VyIGNvbmZpZ1xuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBjdXJyZW50IFBhcnNlT3B0aW9uc1xuICAgKi9cbiAgY2hlY2tJbnB1dEJpbmRpbmdzKGJpbmRpbmdzOiB7W2tleTogc3RyaW5nXTogUmljaEJpbmRpbmdEYXRhfSwgY29udGV4dDogYW55LCBwYXJzZXJDb25maWc6IFNlbGVjdG9ySG9va1BhcnNlckNvbmZpZywgb3B0aW9uczogUGFyc2VPcHRpb25zKSB7XG4gICAgZm9yIChjb25zdCBbaW5wdXROYW1lLCBpbnB1dEJpbmRpbmddIG9mIE9iamVjdC5lbnRyaWVzKGJpbmRpbmdzKSkge1xuICAgICAgLy8gSWYgbm8gbmVlZCB0byBwYXJzZSwgdXNlIHJhdyBhcyB2YWx1ZVxuICAgICAgaWYgKCFwYXJzZXJDb25maWcucGFyc2VJbnB1dHMpIHtcbiAgICAgICAgaW5wdXRCaW5kaW5nLnZhbHVlID0gaW5wdXRCaW5kaW5nLnJhdztcbiAgICBcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIElmIG5vdCB5ZXQgcGFyc2VkLCBkbyBzb1xuICAgICAgICBpZiAoIWlucHV0QmluZGluZy5wYXJzZWQpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgaW5wdXRCaW5kaW5nLnZhbHVlID0gdGhpcy5kYXRhVHlwZVBhcnNlci5ldmFsdWF0ZShcbiAgICAgICAgICAgICAgaW5wdXRCaW5kaW5nLnJhdyxcbiAgICAgICAgICAgICAgcGFyc2VyQ29uZmlnLmFsbG93Q29udGV4dEluQmluZGluZ3MgPyBjb250ZXh0IDoge30sXG4gICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgcGFyc2VyQ29uZmlnLnVuZXNjYXBlU3RyaW5ncyxcbiAgICAgICAgICAgICAgaW5wdXRCaW5kaW5nLmJvdW5kQ29udGV4dFZhcmlhYmxlcyxcbiAgICAgICAgICAgICAgcGFyc2VyQ29uZmlnLmFsbG93Q29udGV4dEZ1bmN0aW9uQ2FsbHMsXG4gICAgICAgICAgICAgIG9wdGlvbnNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpbnB1dEJpbmRpbmcucGFyc2VkID0gdHJ1ZTtcbiAgICAgICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKFtgSG9vayBpbnB1dCBwYXJzaW5nIGVycm9yXFxuc2VsZWN0b3I6IGAgKyBwYXJzZXJDb25maWcuc2VsZWN0b3IgKyAgYFxcbmlucHV0OiBgICsgaW5wdXROYW1lICsgYFxcbnZhbHVlOiBcImAgKyBpbnB1dEJpbmRpbmcudmFsdWUgKyBgXCJgXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihbZS5zdGFja10sIG9wdGlvbnMpO1xuICAgICAgICAgICAgLy8gSWYgYmluZGluZyBjb3VsZCBub3QgYmUgcGFyc2VkIGF0IGFsbCBkdWUgdG8gc3ludGF4IGVycm9yLCByZW1vdmUgZnJvbSBsaXN0IG9mIGlucHV0cy5cbiAgICAgICAgICAgIC8vIE5vIGFtb3VudCBvZiBjYWxscyB0byB1cGRhdGVJbnB1dEJpbmRpbmdzKCkgd2lsbCBmaXggdGhpcyBraW5kIG9mIGVycm9yLlxuICAgICAgICAgICAgZGVsZXRlIGJpbmRpbmdzW2lucHV0TmFtZV07XG4gICAgICAgICAgfVxuXG4gICAgICAgIC8vIE90aGVyd2lzZSBjaGVjayBpZiBuZWVkcyBhbiB1cGRhdGVcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnVwZGF0ZUlucHV0QmluZGluZ0lmU3RhbGUoaW5wdXRCaW5kaW5nLCBjb250ZXh0LCBwYXJzZXJDb25maWcpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFdlIGNhbiBkZXRlY3QgaWYgYSBiaW5kaW5nIG5lZWRzIHRvIGJlIHJlZXZhbHVhdGVkIHZpYSB0aGUgYm91bmQgY29udGV4dCB2YXJpYWJsZXMuIFRoZXJlIGFyZSB0aHJlZSBjYXNlcyB0byBjb25zaWRlcjpcbiAgICpcbiAgICogYSkgSWYgYSBiaW5kaW5nIGRvZXMgbm90IHVzZSBjb250ZXh0IHZhcnMsIGRvbid0IHJlZXZhbHVhdGUgKGJpbmRpbmcgaXMgc3RhdGljIGFuZCB3b24ndCBldmVyIG5lZWQgdG8gYmUgdXBkYXRlZClcbiAgICogYikgSWYgYSBiaW5kaW5nIGRvZXMgdXNlIGNvbnRleHQgdmFycywgYnV0IGNvbnRleHQgdmFycyBoYXZlbid0IGNoYW5nZWQsIGRvbid0IHJlZXZhbHVhdGUgZWl0aGVyICh3b3VsZCBldmFsdXRlIHRoZSBzYW1lKVxuICAgKiBjKSBJZiBhIGJpbmRpbmcgdXNlcyBjb250ZXh0IHZhcnMgYW5kIHRoZXkgaGF2ZSBjaGFuZ2VkLCByZWV2YWx1YXRlIHRoZSBiaW5kaW5nIGZyb20gc2NyYXRjaCB0byBnZXQgdGhlIG5ldyB2ZXJzaW9uXG4gICAqXG4gICAqIFRoaXMgaXMgaW4gbGluZSB3aXRoIHRoZSBzdGFuZGFyZCBBbmd1bGFyIGJlaGF2aW9yIHdoZW4gZXZhbHVhdGluZyB0ZW1wbGF0ZSB2YXJzIGxpa2UgW2lucHV0XT1cIntwcm9wOiB0aGlzLnNvbWV0aGluZ31cIi5cbiAgICogV2hlbiAndGhpcy5zb21ldGhpbmcnIGNoYW5nZXMgc28gdGhhdCBpdCByZXR1cm5zIGZhbHNlIG9uIGEgPT09IGNvbXBhcmlzb24gd2l0aCBpdHMgcHJldmlvdXMgdmFsdWUsIEFuZ3VsYXIgZG9lcyBub3RcbiAgICogc2ltcGx5IHJlcGxhY2UgdGhlIHJlZmVyZW5jZSBib3VuZCB0byAncHJvcCcsIGJ1dCByZWNyZWF0ZXMgdGhlIHdob2xlIG9iamVjdCBsaXRlcmFsIGFuZCBwYXNzZXMgYSBuZXcgcmVmZXJlbmNlIGludG8gdGhlXG4gICAqIGlucHV0LCB0cmlnZ2VyaW5nIG5nT25DaGFuZ2VzLlxuICAgKlxuICAgKiBAcGFyYW0gYmluZGluZyAtIFRoZSBwcmV2aW91cyBiaW5kaW5nc1xuICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjdXJyZW50IGNvbnRleHQgb2JqZWN0XG4gICAqIEBwYXJhbSBwYXJzZXJDb25maWcgLSBUaGUgY3VycmVudCBwYXJzZXIgY29uZmlnXG4gICAqL1xuICBwcml2YXRlIHVwZGF0ZUlucHV0QmluZGluZ0lmU3RhbGUoYmluZGluZzogUmljaEJpbmRpbmdEYXRhLCBjb250ZXh0OiBhbnksIHBhcnNlckNvbmZpZzogU2VsZWN0b3JIb29rUGFyc2VyQ29uZmlnKTogdm9pZCB7XG5cbiAgICBpZiAoT2JqZWN0LmtleXMoYmluZGluZy5ib3VuZENvbnRleHRWYXJpYWJsZXMpLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIENoZWNrIGlmIGJvdW5kIGNvbnRleHQgdmFycyBoYXZlIGNoYW5nZWRcbiAgICAgIGxldCBib3VuZENvbnRleHRWYXJIYXNDaGFuZ2VkID0gZmFsc2U7XG4gICAgICBmb3IgKGNvbnN0IFtjb250ZXh0VmFyTmFtZSwgY29udGV4dFZhclZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhiaW5kaW5nLmJvdW5kQ29udGV4dFZhcmlhYmxlcykpIHtcbiAgICAgICAgY29uc3QgZW5jb2RlZENvbnRleHRWYXJOYW1lID0gdGhpcy5kYXRhVHlwZVBhcnNlci5lbmNvZGVEYXRhVHlwZVN0cmluZyhjb250ZXh0VmFyTmFtZSk7XG4gICAgICAgIC8vIENvbXBhcmUgd2l0aCBwcmV2aW91cyB2YWx1ZVxuICAgICAgICBjb25zdCBuZXdDb250ZXh0VmFyVmFsdWUgPSB0aGlzLmRhdGFUeXBlUGFyc2VyLmxvYWRDb250ZXh0VmFyaWFibGUoZW5jb2RlZENvbnRleHRWYXJOYW1lLCBjb250ZXh0LCB1bmRlZmluZWQsIHBhcnNlckNvbmZpZy51bmVzY2FwZVN0cmluZ3MsIHt9LCBwYXJzZXJDb25maWcuYWxsb3dDb250ZXh0RnVuY3Rpb25DYWxscyk7XG4gICAgICAgIGlmIChuZXdDb250ZXh0VmFyVmFsdWUgIT09IGNvbnRleHRWYXJWYWx1ZSkge1xuICAgICAgICAgIGJvdW5kQ29udGV4dFZhckhhc0NoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIEJvdW5kIGNvbnRleHQgdmFyIGhhcyBjaGFuZ2VkISBSZWV2YWx1YXRlIHdob2xlIGJpbmRpbmcgKHdoaWNoIG1heSBpbmNsdWRlIG1vcmUgdGhhbiBvbmUgY29udGV4dCB2YXIsIG9yIHBvaW50IHRvIHNvbWUgY2hpbGQgcHJvcGVydHkpXG4gICAgICBpZiAoYm91bmRDb250ZXh0VmFySGFzQ2hhbmdlZCkge1xuICAgICAgICBiaW5kaW5nLmJvdW5kQ29udGV4dFZhcmlhYmxlcyA9IHt9O1xuICAgICAgICBiaW5kaW5nLnZhbHVlID0gdGhpcy5kYXRhVHlwZVBhcnNlci5ldmFsdWF0ZShcbiAgICAgICAgICBiaW5kaW5nLnJhdyxcbiAgICAgICAgICBwYXJzZXJDb25maWcuYWxsb3dDb250ZXh0SW5CaW5kaW5ncyA/IGNvbnRleHQgOiB7fSxcbiAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgcGFyc2VyQ29uZmlnLnVuZXNjYXBlU3RyaW5ncyxcbiAgICAgICAgICBiaW5kaW5nLmJvdW5kQ29udGV4dFZhcmlhYmxlcyxcbiAgICAgICAgICBwYXJzZXJDb25maWcuYWxsb3dDb250ZXh0RnVuY3Rpb25DYWxsc1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIE91dHB1dHNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8qKlxuICAgKiBDaGVja3Mgb3V0cHV0IGJpbmRpbmdzIGFuZCBldmFsdWF0ZXMvdXBkYXRlcyB0aGVtIGFzIG5lZWRlZFxuICAgKlxuICAgKiBAcGFyYW0gYmluZGluZ3MgLSBBIGxpc3Qgb2YgQE91dHB1dCgpIGJpbmRpbmdzXG4gICAqIEBwYXJhbSBwYXJzZXJDb25maWcgLSBUaGUgY3VycmVudCBwYXJzZXIgY29uZmlnXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIGN1cnJlbnQgUGFyc2VPcHRpb25zXG4gICAqL1xuICBjaGVja091dHB1dEJpbmRpbmdzKGJpbmRpbmdzOiB7W2tleTogc3RyaW5nXTogUmljaEJpbmRpbmdEYXRhfSwgcGFyc2VyQ29uZmlnOiBTZWxlY3Rvckhvb2tQYXJzZXJDb25maWcsIG9wdGlvbnM6IFBhcnNlT3B0aW9ucykge1xuICAgIGZvciAoY29uc3QgW291dHB1dE5hbWUsIG91dHB1dEJpbmRpbmddIG9mIE9iamVjdC5lbnRyaWVzKGJpbmRpbmdzKSkge1xuICAgICAgLy8gVW5saWtlIGlucHV0cywgb3V0cHV0cyBvbmx5IG5lZWQgdG8gYmUgY3JlYXRlZCBvbmNlIGJ5IHRoZSBwYXJzZXIsIG5ldmVyIHVwZGF0ZWQsIGFzIHlvdSBvbmx5IGNyZWF0ZSBhIHdyYXBwZXIgZnVuY3Rpb24gYXJvdW5kIHRoZSBsb2dpYyB0byBleGVjdXRlLlxuICAgICAgLy8gQXMgdGhpcyBsb2dpYyBpcyBydW4gZnJlc2ggd2hlbmV2ZXIgdGhlIG91dHB1dCB0cmlnZ2VycywgdGhlcmUgaXMgbm8gbmVlZCB0byByZXBsYWNlIHRoaXMgd3JhcHBlciBmdW5jdGlvbiBvbiB1cGRhdGVzLlxuICAgICAgaWYgKCFvdXRwdXRCaW5kaW5nLnBhcnNlZCkge1xuICAgICAgICBvdXRwdXRCaW5kaW5nLnZhbHVlID0gKGV2ZW50OiBhbnksIGNvbnRleHQ6IGFueSkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLmRhdGFUeXBlUGFyc2VyLmV2YWx1YXRlKFxuICAgICAgICAgICAgICBvdXRwdXRCaW5kaW5nLnJhdyxcbiAgICAgICAgICAgICAgcGFyc2VyQ29uZmlnLmFsbG93Q29udGV4dEluQmluZGluZ3MgPyBjb250ZXh0IDoge30sXG4gICAgICAgICAgICAgIGV2ZW50LFxuICAgICAgICAgICAgICBwYXJzZXJDb25maWcudW5lc2NhcGVTdHJpbmdzLFxuICAgICAgICAgICAgICBvdXRwdXRCaW5kaW5nLmJvdW5kQ29udGV4dFZhcmlhYmxlcyxcbiAgICAgICAgICAgICAgcGFyc2VyQ29uZmlnLmFsbG93Q29udGV4dEZ1bmN0aW9uQ2FsbHNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihbYEhvb2sgb3V0cHV0IHBhcnNpbmcgZXJyb3JcXG5zZWxlY3RvcjogYCArIHBhcnNlckNvbmZpZy5zZWxlY3RvciArICBgXFxub3V0cHV0OiBgICsgb3V0cHV0TmFtZSArIGBcXG52YWx1ZTogXCJgICsgb3V0cHV0QmluZGluZy52YWx1ZSArIGBcImBdLCBvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKFtlLnN0YWNrXSwgb3B0aW9ucyk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBvdXRwdXRCaW5kaW5nLnBhcnNlZCA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbn1cbiJdfQ==