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.
160 lines • 25.9 kB
JavaScript
import { regexes } from '../../../constants/regexes';
import { matchAll } from '../../../services/utils/utils';
/**
* A text parser to load components with their bindings like in Angular templates.
*/
export class TextSelectorHookParser {
constructor(config, configResolver, tagHookFinder, bindingsValueManager) {
this.configResolver = configResolver;
this.tagHookFinder = tagHookFinder;
this.bindingsValueManager = bindingsValueManager;
this.savedBindings = {};
this.config = this.configResolver.processConfig(config);
this.name = this.config.name;
}
findHooks(content, context, options) {
let hookPositions = this.config.enclosing ?
this.tagHookFinder.findEnclosingTags(content, this.config.selector, this.config.bracketStyle, options) :
this.tagHookFinder.findSingleTags(content, this.config.selector, this.config.bracketStyle, options);
if (this.config.allowSelfClosing) {
hookPositions = [
...hookPositions,
...this.tagHookFinder.findSelfClosingTags(content, this.config.selector, this.config.bracketStyle, options)
];
hookPositions.sort((a, b) => a.openingTagStartIndex - b.openingTagStartIndex);
}
return hookPositions;
}
loadComponent(hookId, hookValue, context, childNodes, options) {
return {
component: this.config.component,
hostElementTag: this.config.hostElementTag || this.config.selector, // If no hostElementTag specified, use selector (which in the case of TextSelectorHookParser is only allowed to be tag name)
injector: this.config.injector,
environmentInjector: this.config.environmentInjector
};
}
getBindings(hookId, hookValue, context, options) {
let hookBindings = this.savedBindings[hookId];
// Parse bindings once from hookValue, then reuse on subsequent runs
if (hookBindings === undefined) {
hookBindings = this.createBindings(hookValue.openingTag);
this.savedBindings[hookId] = hookBindings;
}
// (Re)evaluate if needed
this.bindingsValueManager.checkInputBindings(hookBindings.inputs, context, this.config, options);
this.bindingsValueManager.checkOutputBindings(hookBindings.outputs, this.config, options);
return {
inputs: this.getValuesFromSavedBindings(hookBindings.inputs),
outputs: this.getValuesFromSavedBindings(hookBindings.outputs)
};
}
// Bindings
// --------------------------------------------------------------------------
/**
* Returns RichBindingData for Angular-style inputs & output attrs from an openingTag
*
* @param openingTag - The openingTag to inspect
*/
createBindings(openingTag) {
const rawInputs = this.collectRawInputs(openingTag);
const inputBindings = {};
for (const [rawInputKey, rawInputValue] of Object.entries(rawInputs)) {
inputBindings[rawInputKey] = { raw: rawInputValue, parsed: false, value: null, boundContextVariables: {} };
}
const rawOutputs = this.collectRawOutputs(openingTag);
const outputBindings = {};
for (const [rawOutputKey, rawOutputValue] of Object.entries(rawOutputs)) {
outputBindings[rawOutputKey] = { raw: rawOutputValue, parsed: false, value: null, boundContextVariables: {} };
}
return {
inputs: inputBindings,
outputs: outputBindings
};
}
/**
* Collects Angular-style inputs from an openingTag
*
* @param openingTag - The openingTag to inspect
*/
collectRawInputs(openingTag) {
const rawNoBracketInputs = this.getBindingsFromOpeningTag(openingTag, 'noBracketInputs', this.config.inputsBlacklist || null, this.config.inputsWhitelist || null);
const rawBracketInputs = this.getBindingsFromOpeningTag(openingTag, 'bracketInputs', this.config.inputsBlacklist || null, this.config.inputsWhitelist || null);
// NoBracketInputs are to be interpreted as plain strings, so wrap them in quotes
for (const [noBracketInputName, noBracketInputValue] of Object.entries(rawNoBracketInputs)) {
rawNoBracketInputs[noBracketInputName] = "'" + noBracketInputValue + "'";
}
// Merge both input objects
return { ...rawNoBracketInputs, ...rawBracketInputs };
}
/**
* Collects Angular-style outputs from an openingTag
*
* @param openingTag - The openingTag to inspect
*/
collectRawOutputs(openingTag) {
return this.getBindingsFromOpeningTag(openingTag, 'outputs', this.config.outputsBlacklist || null, this.config.outputsWhitelist || null);
}
/**
* Collects Angular-style inputs or outputs from an openingTag
*
* @param type - What kind of bindings to extract
* @param openingTag - The opening tag to inspect
* @param blacklist - A list of inputs/outputs to blacklist
* @param whitelist - A list of inputs/outputs to whitelist
*/
getBindingsFromOpeningTag(openingTag, type, blacklist, whitelist) {
const bindings = {};
// Examples: https://regex101.com/r/17x3cc/16
const attributeValuesOR = '(?:' + regexes.attributeValueDoubleQuotesRegex + '|' + regexes.attributeValueSingleQuotesRegex + ')';
let attributeNameRegex;
switch (type) {
case 'noBracketInputs':
attributeNameRegex = regexes.attributeNameNoBracketsRegex;
break;
case 'bracketInputs':
attributeNameRegex = regexes.attributeNameBracketsRegex;
break;
case 'outputs':
attributeNameRegex = regexes.attributeNameRoundBracketsRegex;
break;
}
const attributeRegex = attributeNameRegex + '\=' + attributeValuesOR;
const attributePattern = new RegExp(attributeRegex, 'gim');
const attributeMatches = matchAll(openingTag, attributePattern);
// Collect raw bindings
for (const match of attributeMatches) {
// Could be either of the attribute value capturing groups
let rawBindingValue = match[2] || match[3];
// If value is empty (someInput=""), it will return undefined for it. When using noBracketInputs, return empty string instead.
if (rawBindingValue === undefined && type === 'noBracketInputs') {
rawBindingValue = '';
}
bindings[match[1]] = rawBindingValue;
}
// Filter bindings
const filteredBindings = {};
for (const [bindingName, bindingValue] of Object.entries(bindings)) {
if (blacklist && blacklist.includes(bindingName)) {
continue;
}
if (whitelist && !whitelist.includes(bindingName)) {
continue;
}
filteredBindings[bindingName] = bindingValue;
}
return filteredBindings;
}
/**
* Transforms a RichBindingData object into a normal bindings object
*
* @param richBindingsObject - The object containing the RichBindingData
*/
getValuesFromSavedBindings(richBindingsObject) {
const result = {};
for (const [key, value] of Object.entries(richBindingsObject)) {
result[key] = value.value;
}
return result;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dFNlbGVjdG9ySG9va1BhcnNlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1keW5hbWljLWhvb2tzL3NyYy9saWIvcGFyc2Vycy9zZWxlY3Rvci90ZXh0L3RleHRTZWxlY3Rvckhvb2tQYXJzZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBTUEsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUd6RDs7R0FFRztBQUNILE1BQU0sT0FBTyxzQkFBc0I7SUFLakMsWUFBWSxNQUFnQyxFQUFVLGNBQWdELEVBQVUsYUFBNEIsRUFBVSxvQkFBMEM7UUFBMUksbUJBQWMsR0FBZCxjQUFjLENBQWtDO1FBQVUsa0JBQWEsR0FBYixhQUFhLENBQWU7UUFBVSx5QkFBb0IsR0FBcEIsb0JBQW9CLENBQXNCO1FBRmhNLGtCQUFhLEdBQW1DLEVBQUUsQ0FBQztRQUdqRCxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUM7SUFDL0IsQ0FBQztJQUVNLFNBQVMsQ0FBQyxPQUFlLEVBQUUsT0FBWSxFQUFFLE9BQXFCO1FBQ25FLElBQUksYUFBYSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDekMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFTLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUN6RyxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsSUFB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TyxNQUFNLENBQUM7SUFDaEIsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUmljaEJpbmRpbmdEYXRhLCBTYXZlZEJpbmRpbmdzIH0gZnJvbSAnLi4vLi4vLi4vaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBIb29rUGFyc2VyLCBIb29rUG9zaXRpb24sIEhvb2tWYWx1ZSwgSG9va0NvbXBvbmVudERhdGEsIEhvb2tCaW5kaW5ncyB9IGZyb20gJy4uLy4uLy4uL2ludGVyZmFjZXNQdWJsaWMnO1xuaW1wb3J0IHsgVGFnSG9va0ZpbmRlciB9IGZyb20gJy4vdGFnSG9va0ZpbmRlcic7XG5pbXBvcnQgeyBCaW5kaW5nc1ZhbHVlTWFuYWdlciB9IGZyb20gJy4uL2JpbmRpbmdzVmFsdWVNYW5hZ2VyJztcbmltcG9ydCB7IFNlbGVjdG9ySG9va1BhcnNlckNvbmZpZyB9IGZyb20gJy4uL3NlbGVjdG9ySG9va1BhcnNlckNvbmZpZyc7XG5pbXBvcnQgeyBTZWxlY3Rvckhvb2tQYXJzZXJDb25maWdSZXNvbHZlciB9IGZyb20gJy4uL3NlbGVjdG9ySG9va1BhcnNlckNvbmZpZ1Jlc29sdmVyJztcbmltcG9ydCB7IHJlZ2V4ZXMgfSBmcm9tICcuLi8uLi8uLi9jb25zdGFudHMvcmVnZXhlcyc7XG5pbXBvcnQgeyBtYXRjaEFsbCB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL3V0aWxzL3V0aWxzJztcbmltcG9ydCB7IFBhcnNlT3B0aW9ucyB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL3NldHRpbmdzL29wdGlvbnMnO1xuXG4vKipcbiAqIEEgdGV4dCBwYXJzZXIgdG8gbG9hZCBjb21wb25lbnRzIHdpdGggdGhlaXIgYmluZGluZ3MgbGlrZSBpbiBBbmd1bGFyIHRlbXBsYXRlcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFRleHRTZWxlY3Rvckhvb2tQYXJzZXIgaW1wbGVtZW50cyBIb29rUGFyc2VyIHtcbiAgbmFtZTogc3RyaW5nfHVuZGVmaW5lZDtcbiAgY29uZmlnOiBTZWxlY3Rvckhvb2tQYXJzZXJDb25maWc7XG4gIHNhdmVkQmluZGluZ3M6IHtba2V5OiBudW1iZXJdOiBTYXZlZEJpbmRpbmdzfSA9IHt9O1xuXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogU2VsZWN0b3JIb29rUGFyc2VyQ29uZmlnLCBwcml2YXRlIGNvbmZpZ1Jlc29sdmVyOiBTZWxlY3Rvckhvb2tQYXJzZXJDb25maWdSZXNvbHZlciwgcHJpdmF0ZSB0YWdIb29rRmluZGVyOiBUYWdIb29rRmluZGVyLCBwcml2YXRlIGJpbmRpbmdzVmFsdWVNYW5hZ2VyOiBCaW5kaW5nc1ZhbHVlTWFuYWdlcikge1xuICAgIHRoaXMuY29uZmlnID0gdGhpcy5jb25maWdSZXNvbHZlci5wcm9jZXNzQ29uZmlnKGNvbmZpZyk7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25maWcubmFtZTtcbiAgfVxuXG4gIHB1YmxpYyBmaW5kSG9va3MoY29udGVudDogc3RyaW5nLCBjb250ZXh0OiBhbnksIG9wdGlvbnM6IFBhcnNlT3B0aW9ucyk6IEhvb2tQb3NpdGlvbltdIHtcbiAgICBsZXQgaG9va1Bvc2l0aW9ucyA9IHRoaXMuY29uZmlnLmVuY2xvc2luZyA/XG4gICAgICB0aGlzLnRhZ0hvb2tGaW5kZXIuZmluZEVuY2xvc2luZ1RhZ3MoY29udGVudCwgdGhpcy5jb25maWcuc2VsZWN0b3IhLCB0aGlzLmNvbmZpZy5icmFja2V0U3R5bGUsIG9wdGlvbnMpIDpcbiAgICAgIHRoaXMudGFnSG9va0ZpbmRlci5maW5kU2luZ2xlVGFncyhjb250ZW50LCB0aGlzLmNvbmZpZy5zZWxlY3RvciEsIHRoaXMuY29uZmlnLmJyYWNrZXRTdHlsZSwgb3B0aW9ucyk7XG5cbiAgICBpZiAodGhpcy5jb25maWcuYWxsb3dTZWxmQ2xvc2luZykge1xuICAgICAgaG9va1Bvc2l0aW9ucyA9IFtcbiAgICAgICAgLi4uaG9va1Bvc2l0aW9ucywgXG4gICAgICAgIC4uLnRoaXMudGFnSG9va0ZpbmRlci5maW5kU2VsZkNsb3NpbmdUYWdzKGNvbnRlbnQsIHRoaXMuY29uZmlnLnNlbGVjdG9yISwgdGhpcy5jb25maWcuYnJhY2tldFN0eWxlLCBvcHRpb25zKVxuICAgICAgXTtcbiAgICAgIGhvb2tQb3NpdGlvbnMuc29ydCgoYSwgYikgPT4gYS5vcGVuaW5nVGFnU3RhcnRJbmRleCAtIGIub3BlbmluZ1RhZ1N0YXJ0SW5kZXgpO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gaG9va1Bvc2l0aW9ucztcbiAgfVxuXG4gIHB1YmxpYyBsb2FkQ29tcG9uZW50KGhvb2tJZDogbnVtYmVyLCBob29rVmFsdWU6IEhvb2tWYWx1ZSwgY29udGV4dDogYW55LCBjaGlsZE5vZGVzOiBhbnlbXSwgb3B0aW9uczogUGFyc2VPcHRpb25zKTogSG9va0NvbXBvbmVudERhdGEge1xuICAgIHJldHVybiB7XG4gICAgICBjb21wb25lbnQ6IHRoaXMuY29uZmlnLmNvbXBvbmVudCxcbiAgICAgIGhvc3RFbGVtZW50VGFnOiB0aGlzLmNvbmZpZy5ob3N0RWxlbWVudFRhZyB8fCB0aGlzLmNvbmZpZy5zZWxlY3RvciwgLy8gSWYgbm8gaG9zdEVsZW1lbnRUYWcgc3BlY2lmaWVkLCB1c2Ugc2VsZWN0b3IgKHdoaWNoIGluIHRoZSBjYXNlIG9mIFRleHRTZWxlY3Rvckhvb2tQYXJzZXIgaXMgb25seSBhbGxvd2VkIHRvIGJlIHRhZyBuYW1lKVxuICAgICAgaW5qZWN0b3I6IHRoaXMuY29uZmlnLmluamVjdG9yLFxuICAgICAgZW52aXJvbm1lbnRJbmplY3RvcjogdGhpcy5jb25maWcuZW52aXJvbm1lbnRJbmplY3RvclxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgZ2V0QmluZGluZ3MoaG9va0lkOiBudW1iZXIsIGhvb2tWYWx1ZTogSG9va1ZhbHVlLCBjb250ZXh0OiBhbnksIG9wdGlvbnM6IFBhcnNlT3B0aW9ucyk6IEhvb2tCaW5kaW5ncyB7XG4gICAgbGV0IGhvb2tCaW5kaW5ncyA9IHRoaXMuc2F2ZWRCaW5kaW5nc1tob29rSWRdO1xuXG4gICAgLy8gUGFyc2UgYmluZGluZ3Mgb25jZSBmcm9tIGhvb2tWYWx1ZSwgdGhlbiByZXVzZSBvbiBzdWJzZXF1ZW50IHJ1bnNcbiAgICBpZiAoaG9va0JpbmRpbmdzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGhvb2tCaW5kaW5ncyA9IHRoaXMuY3JlYXRlQmluZGluZ3MoaG9va1ZhbHVlLm9wZW5pbmdUYWchKTtcbiAgICAgIHRoaXMuc2F2ZWRCaW5kaW5nc1tob29rSWRdID0gaG9va0JpbmRpbmdzO1xuICAgIH1cblxuICAgIC8vIChSZSlldmFsdWF0ZSBpZiBuZWVkZWRcbiAgICB0aGlzLmJpbmRpbmdzVmFsdWVNYW5hZ2VyLmNoZWNrSW5wdXRCaW5kaW5ncyhob29rQmluZGluZ3MuaW5wdXRzISwgY29udGV4dCwgdGhpcy5jb25maWcsIG9wdGlvbnMpO1xuICAgIHRoaXMuYmluZGluZ3NWYWx1ZU1hbmFnZXIuY2hlY2tPdXRwdXRCaW5kaW5ncyhob29rQmluZGluZ3Mub3V0cHV0cyEsIHRoaXMuY29uZmlnLCBvcHRpb25zKTtcblxuICAgIHJldHVybiB7XG4gICAgICBpbnB1dHM6IHRoaXMuZ2V0VmFsdWVzRnJvbVNhdmVkQmluZGluZ3MoaG9va0JpbmRpbmdzLmlucHV0cyEpLFxuICAgICAgb3V0cHV0czogdGhpcy5nZXRWYWx1ZXNGcm9tU2F2ZWRCaW5kaW5ncyhob29rQmluZGluZ3Mub3V0cHV0cyEpXG4gICAgfTtcbiAgfVxuXG4gIC8vIEJpbmRpbmdzXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLyoqXG4gICAqIFJldHVybnMgUmljaEJpbmRpbmdEYXRhIGZvciBBbmd1bGFyLXN0eWxlIGlucHV0cyAmIG91dHB1dCBhdHRycyBmcm9tIGFuIG9wZW5pbmdUYWdcbiAgICogXG4gICAqIEBwYXJhbSBvcGVuaW5nVGFnIC0gVGhlIG9wZW5pbmdUYWcgdG8gaW5zcGVjdFxuICAgKi9cbiAgY3JlYXRlQmluZGluZ3Mob3BlbmluZ1RhZzogc3RyaW5nKTogU2F2ZWRCaW5kaW5ncyB7XG4gICAgY29uc3QgcmF3SW5wdXRzID0gdGhpcy5jb2xsZWN0UmF3SW5wdXRzKG9wZW5pbmdUYWchKTtcbiAgICBjb25zdCBpbnB1dEJpbmRpbmdzOiB7W2tleTogc3RyaW5nXTogUmljaEJpbmRpbmdEYXRhfSA9IHt9O1xuICAgIGZvciAoY29uc3QgW3Jhd0lucHV0S2V5LCByYXdJbnB1dFZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhyYXdJbnB1dHMpKSB7XG4gICAgICBpbnB1dEJpbmRpbmdzW3Jhd0lucHV0S2V5XSA9IHtyYXc6IHJhd0lucHV0VmFsdWUsIHBhcnNlZDogZmFsc2UsIHZhbHVlOiBudWxsLCBib3VuZENvbnRleHRWYXJpYWJsZXM6IHt9fTtcbiAgICB9XG5cbiAgICBjb25zdCByYXdPdXRwdXRzID0gdGhpcy5jb2xsZWN0UmF3T3V0cHV0cyhvcGVuaW5nVGFnISk7XG4gICAgY29uc3Qgb3V0cHV0QmluZGluZ3M6IHtba2V5OiBzdHJpbmddOiBSaWNoQmluZGluZ0RhdGF9ID0ge307XG4gICAgZm9yIChjb25zdCBbcmF3T3V0cHV0S2V5LCByYXdPdXRwdXRWYWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMocmF3T3V0cHV0cykpIHtcbiAgICAgIG91dHB1dEJpbmRpbmdzW3Jhd091dHB1dEtleV0gPSB7cmF3OiByYXdPdXRwdXRWYWx1ZSwgcGFyc2VkOiBmYWxzZSwgdmFsdWU6IG51bGwsIGJvdW5kQ29udGV4dFZhcmlhYmxlczoge319O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBpbnB1dHM6IGlucHV0QmluZGluZ3MsXG4gICAgICBvdXRwdXRzOiBvdXRwdXRCaW5kaW5nc1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ29sbGVjdHMgQW5ndWxhci1zdHlsZSBpbnB1dHMgZnJvbSBhbiBvcGVuaW5nVGFnXG4gICAqXG4gICAqIEBwYXJhbSBvcGVuaW5nVGFnIC0gVGhlIG9wZW5pbmdUYWcgdG8gaW5zcGVjdFxuICAgKi9cbiAgY29sbGVjdFJhd0lucHV0cyAob3BlbmluZ1RhZzogc3RyaW5nKToge1trZXk6IHN0cmluZ106IGFueX0ge1xuICAgIGNvbnN0IHJhd05vQnJhY2tldElucHV0cyA9IHRoaXMuZ2V0QmluZGluZ3NGcm9tT3BlbmluZ1RhZyhvcGVuaW5nVGFnLCAnbm9CcmFja2V0SW5wdXRzJywgdGhpcy5jb25maWcuaW5wdXRzQmxhY2tsaXN0IHx8IG51bGwsIHRoaXMuY29uZmlnLmlucHV0c1doaXRlbGlzdCB8fCBudWxsKTtcbiAgICBjb25zdCByYXdCcmFja2V0SW5wdXRzID0gdGhpcy5nZXRCaW5kaW5nc0Zyb21PcGVuaW5nVGFnKG9wZW5pbmdUYWcsICdicmFja2V0SW5wdXRzJywgdGhpcy5jb25maWcuaW5wdXRzQmxhY2tsaXN0IHx8IG51bGwsIHRoaXMuY29uZmlnLmlucHV0c1doaXRlbGlzdCB8fCBudWxsKTtcblxuICAgIC8vIE5vQnJhY2tldElucHV0cyBhcmUgdG8gYmUgaW50ZXJwcmV0ZWQgYXMgcGxhaW4gc3RyaW5ncywgc28gd3JhcCB0aGVtIGluIHF1b3Rlc1xuICAgIGZvciAoY29uc3QgW25vQnJhY2tldElucHV0TmFtZSwgbm9CcmFja2V0SW5wdXRWYWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMocmF3Tm9CcmFja2V0SW5wdXRzKSkge1xuICAgICAgcmF3Tm9CcmFja2V0SW5wdXRzW25vQnJhY2tldElucHV0TmFtZV0gPSBcIidcIiArIG5vQnJhY2tldElucHV0VmFsdWUgKyBcIidcIjtcbiAgICB9XG5cbiAgICAvLyBNZXJnZSBib3RoIGlucHV0IG9iamVjdHNcbiAgICByZXR1cm4gey4uLnJhd05vQnJhY2tldElucHV0cywgLi4ucmF3QnJhY2tldElucHV0c307XG4gIH1cblxuICAvKipcbiAgICogQ29sbGVjdHMgQW5ndWxhci1zdHlsZSBvdXRwdXRzIGZyb20gYW4gb3BlbmluZ1RhZ1xuICAgKlxuICAgKiBAcGFyYW0gb3BlbmluZ1RhZyAtIFRoZSBvcGVuaW5nVGFnIHRvIGluc3BlY3RcbiAgICovXG4gIGNvbGxlY3RSYXdPdXRwdXRzKG9wZW5pbmdUYWc6IHN0cmluZyk6IHtba2V5OiBzdHJpbmddOiBhbnl9IHtcbiAgICByZXR1cm4gdGhpcy5nZXRCaW5kaW5nc0Zyb21PcGVuaW5nVGFnKG9wZW5pbmdUYWchLCAnb3V0cHV0cycsIHRoaXMuY29uZmlnLm91dHB1dHNCbGFja2xpc3QgfHwgbnVsbCwgdGhpcy5jb25maWcub3V0cHV0c1doaXRlbGlzdCB8fCBudWxsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBBbmd1bGFyLXN0eWxlIGlucHV0cyBvciBvdXRwdXRzIGZyb20gYW4gb3BlbmluZ1RhZ1xuICAgKlxuICAgKiBAcGFyYW0gdHlwZSAtIFdoYXQga2luZCBvZiBiaW5kaW5ncyB0byBleHRyYWN0XG4gICAqIEBwYXJhbSBvcGVuaW5nVGFnIC0gVGhlIG9wZW5pbmcgdGFnIHRvIGluc3BlY3RcbiAgICogQHBhcmFtIGJsYWNrbGlzdCAtIEEgbGlzdCBvZiBpbnB1dHMvb3V0cHV0cyB0byBibGFja2xpc3RcbiAgICogQHBhcmFtIHdoaXRlbGlzdCAtIEEgbGlzdCBvZiBpbnB1dHMvb3V0cHV0cyB0byB3aGl0ZWxpc3RcbiAgICovXG4gICAgcHJpdmF0ZSBnZXRCaW5kaW5nc0Zyb21PcGVuaW5nVGFnKG9wZW5pbmdUYWc6IHN0cmluZywgdHlwZTogJ25vQnJhY2tldElucHV0cyd8J2JyYWNrZXRJbnB1dHMnfCdvdXRwdXRzJywgYmxhY2tsaXN0OiBzdHJpbmdbXXxudWxsLCB3aGl0ZWxpc3Q6IHN0cmluZ1tdfG51bGwpOiB7W2tleTogc3RyaW5nXTogYW55fSB7XG4gICAgICBjb25zdCBiaW5kaW5nczoge1trZXk6IHN0cmluZ106IGFueX0gPSB7fTtcbiAgXG4gICAgICAvLyBFeGFtcGxlczogaHR0cHM6Ly9yZWdleDEwMS5jb20vci8xN3gzY2MvMTZcbiAgICAgIGNvbnN0IGF0dHJpYnV0ZVZhbHVlc09SID0gJyg/OicgKyByZWdleGVzLmF0dHJpYnV0ZVZhbHVlRG91YmxlUXVvdGVzUmVnZXggKyAnfCcgKyByZWdleGVzLmF0dHJpYnV0ZVZhbHVlU2luZ2xlUXVvdGVzUmVnZXggKyAnKSc7XG4gICAgICBsZXQgYXR0cmlidXRlTmFtZVJlZ2V4O1xuICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgIGNhc2UgJ25vQnJhY2tldElucHV0cyc6IGF0dHJpYnV0ZU5hbWVSZWdleCA9IHJlZ2V4ZXMuYXR0cmlidXRlTmFtZU5vQnJhY2tldHNSZWdleDsgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2JyYWNrZXRJbnB1dHMnOiBhdHRyaWJ1dGVOYW1lUmVnZXggPSByZWdleGVzLmF0dHJpYnV0ZU5hbWVCcmFja2V0c1JlZ2V4OyBicmVhaztcbiAgICAgICAgY2FzZSAnb3V0cHV0cyc6IGF0dHJpYnV0ZU5hbWVSZWdleCA9IHJlZ2V4ZXMuYXR0cmlidXRlTmFtZVJvdW5kQnJhY2tldHNSZWdleDsgYnJlYWs7XG4gICAgICB9XG4gICAgICBjb25zdCBhdHRyaWJ1dGVSZWdleCA9IGF0dHJpYnV0ZU5hbWVSZWdleCArICdcXD0nICsgYXR0cmlidXRlVmFsdWVzT1I7XG4gICAgICBjb25zdCBhdHRyaWJ1dGVQYXR0ZXJuID0gbmV3IFJlZ0V4cChhdHRyaWJ1dGVSZWdleCwgJ2dpbScpO1xuICAgICAgY29uc3QgYXR0cmlidXRlTWF0Y2hlcyA9IG1hdGNoQWxsKG9wZW5pbmdUYWcsIGF0dHJpYnV0ZVBhdHRlcm4pO1xuICBcbiAgICAgIC8vIENvbGxlY3QgcmF3IGJpbmRpbmdzXG4gICAgICBmb3IgKGNvbnN0IG1hdGNoIG9mIGF0dHJpYnV0ZU1hdGNoZXMpIHtcbiAgICAgICAgLy8gQ291bGQgYmUgZWl0aGVyIG9mIHRoZSBhdHRyaWJ1dGUgdmFsdWUgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICBsZXQgcmF3QmluZGluZ1ZhbHVlID0gbWF0Y2hbMl0gfHwgbWF0Y2hbM107XG4gICAgICAgIC8vIElmIHZhbHVlIGlzIGVtcHR5IChzb21lSW5wdXQ9XCJcIiksIGl0IHdpbGwgcmV0dXJuIHVuZGVmaW5lZCBmb3IgaXQuIFdoZW4gdXNpbmcgbm9CcmFja2V0SW5wdXRzLCByZXR1cm4gZW1wdHkgc3RyaW5nIGluc3RlYWQuXG4gICAgICAgIGlmIChyYXdCaW5kaW5nVmFsdWUgPT09IHVuZGVmaW5lZCAmJiB0eXBlID09PSAnbm9CcmFja2V0SW5wdXRzJykge1xuICAgICAgICAgIHJhd0JpbmRpbmdWYWx1ZSA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIGJpbmRpbmdzW21hdGNoWzFdXSA9IHJhd0JpbmRpbmdWYWx1ZTtcbiAgICAgIH1cbiAgXG4gICAgICAvLyBGaWx0ZXIgYmluZGluZ3NcbiAgICAgIGNvbnN0IGZpbHRlcmVkQmluZGluZ3M6IHtba2V5OiBzdHJpbmddOiBhbnl9ID0ge307XG4gICAgICBmb3IgKGNvbnN0IFtiaW5kaW5nTmFtZSwgYmluZGluZ1ZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhiaW5kaW5ncykpIHtcbiAgICAgICAgaWYgKGJsYWNrbGlzdCAmJiBibGFja2xpc3QuaW5jbHVkZXMoYmluZGluZ05hbWUpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHdoaXRlbGlzdCAmJiAhd2hpdGVsaXN0LmluY2x1ZGVzKGJpbmRpbmdOYW1lKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGZpbHRlcmVkQmluZGluZ3NbYmluZGluZ05hbWVdID0gYmluZGluZ1ZhbHVlO1xuICAgICAgfVxuICBcbiAgICAgIHJldHVybiBmaWx0ZXJlZEJpbmRpbmdzO1xuICAgIH1cblxuICAvKipcbiAgICogVHJhbnNmb3JtcyBhIFJpY2hCaW5kaW5nRGF0YSBvYmplY3QgaW50byBhIG5vcm1hbCBiaW5kaW5ncyBvYmplY3RcbiAgICpcbiAgICogQHBhcmFtIHJpY2hCaW5kaW5nc09iamVjdCAtIFRoZSBvYmplY3QgY29udGFpbmluZyB0aGUgUmljaEJpbmRpbmdEYXRhXG4gICAqL1xuICBwcml2YXRlIGdldFZhbHVlc0Zyb21TYXZlZEJpbmRpbmdzKHJpY2hCaW5kaW5nc09iamVjdDoge1trZXk6IHN0cmluZ106IFJpY2hCaW5kaW5nRGF0YX0pOiB7W2tleTogc3RyaW5nXTogYW55fSB7XG4gICAgY29uc3QgcmVzdWx0OiB7W2tleTogc3RyaW5nXTogYW55fSA9IHt9O1xuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHJpY2hCaW5kaW5nc09iamVjdCkpIHtcbiAgICAgIHJlc3VsdFtrZXldID0gdmFsdWUudmFsdWU7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cbiJdfQ==