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.
211 lines • 29.4 kB
JavaScript
import { Injectable, reflectComponentType } from '@angular/core';
import { TextSelectorHookParser } from '../../parsers/selector/text/textSelectorHookParser';
import { ElementSelectorHookParser } from '../../parsers/selector/element/elementSelectorHookParser';
import * as i0 from "@angular/core";
import * as i1 from "../../parsers/selector/selectorHookParserConfigResolver";
import * as i2 from "../platform/autoPlatformService";
import * as i3 from "../../parsers/selector/text/tagHookFinder";
import * as i4 from "../../parsers/selector/bindingsValueManager";
import * as i5 from "../utils/logger";
/**
* A helper class for resolving HookParserEntries
*/
export class ParserEntryResolver {
constructor(injector, parserResolver, platformService, tagHookFinder, bindingsValueManager, logger) {
this.injector = injector;
this.parserResolver = parserResolver;
this.platformService = platformService;
this.tagHookFinder = tagHookFinder;
this.bindingsValueManager = bindingsValueManager;
this.logger = logger;
}
/**
* Takes a list of HookParserEntries and transforms them into a list of loaded HookParsers
*
* @param parserEntries - The list of HookParserEntries to process
* @param injector - The injector to use for resolving parsers
* @param blacklist - (optional) Which parsers to blacklist by name
* @param whitelist - (optional) Which parsers to whitelist by name
* @param options - The current ParseOptions
*/
resolve(parserEntries, injector, blacklist, whitelist, options) {
// Load all requested parsers
const parsers = [];
for (const parser of parserEntries) {
const resolvedParser = this.resolveEntry(parser, injector, options);
if (resolvedParser) {
parsers.push(resolvedParser);
}
}
// Check parser functions
const validParsers = this.validateParserFunctions(parsers, options);
// Check parser names
this.checkParserNames(validParsers, options);
// If no need to filter, return resolved parsers
if (!blacklist && !whitelist) {
return validParsers;
}
// Check black/whitelist
this.checkBlackAndWhitelist(validParsers, blacklist, whitelist, options);
// Filter parsers
const filteredParsers = [];
for (const validParser of validParsers) {
if (validParser.hasOwnProperty('name') && typeof validParser.name === 'string') {
if (blacklist && blacklist.includes(validParser.name)) {
continue;
}
if (whitelist && !whitelist.includes(validParser.name)) {
continue;
}
}
filteredParsers.push(validParser);
}
return filteredParsers;
}
/**
* Figures out what kind of config type the HookParserEntry is and loads it appropriately.
*
* The potential types are:
* - 1. a component class (shorthand for nr. 5)
* - 2. a parser service
* - 3. a parser class
* - 4. a parser instance
* - 5. an object literal to configure SelectorHookParser with
*
* @param parserEntry - The HookParserEntry to process
* @param injector - The injector to use for resolving this parser
* @param options - The current ParseOptions
*/
resolveEntry(parserEntry, injector, options) {
// Check if class
if (parserEntry.hasOwnProperty('prototype')) {
// Check if component class
const componentMeta = reflectComponentType(parserEntry);
if (componentMeta) {
return this.createSelectorHookParser({ component: parserEntry });
// Else must be parser class
}
else {
// Check if service
try {
return injector.get(parserEntry);
// Otherwise instantiate manually
}
catch (e) {
return new parserEntry();
}
}
}
// Check if object
else if (typeof parserEntry === 'object') {
// Is instance
if (parserEntry.constructor.name !== 'Object') {
return parserEntry;
// Is object literal
}
else {
try {
return this.createSelectorHookParser(parserEntry);
}
catch (e) {
this.logger.error(['Invalid parser config - ' + e.message, parserEntry], options);
return null;
}
}
}
this.logger.error(['Invalid parser config - ', parserEntry], options);
return null;
}
/**
* Depending on the config, load either string or element SelectorHookParser
*
* @param config - The selectorHookParserConfig
*/
createSelectorHookParser(config) {
if ((config.hasOwnProperty('parseWithRegex') && config.parseWithRegex) ||
(config.hasOwnProperty('enclosing') && !config.enclosing) ||
(config.hasOwnProperty('bracketStyle') && config.bracketStyle)) {
return new TextSelectorHookParser(config, this.parserResolver, this.tagHookFinder, this.bindingsValueManager);
}
else {
return new ElementSelectorHookParser(config, this.parserResolver, this.platformService, this.bindingsValueManager);
}
}
/**
* Makes sure that the parsers have all required functions
*
* @param parsers - The parsers in question
* @param options - The current ParseOptions
*/
validateParserFunctions(parsers, options) {
const validParsers = [];
for (const parser of parsers) {
if (typeof parser.findHooks !== 'function' && typeof parser.findHookElements !== 'function') {
this.logger.error(['Submitted parser neither implements "findHooks()" nor "findHookElements()". One is required. Removing from list of active parsers:', parser], options);
continue;
}
if (typeof parser.loadComponent !== 'function') {
this.logger.error(['Submitted parser does not implement "loadComponent()". Removing from list of active parsers:', parser], options);
continue;
}
if (typeof parser.getBindings !== 'function') {
this.logger.error(['Submitted parser does not implement "getBindings()". Removing from list of active parsers:', parser], options);
continue;
}
validParsers.push(parser);
}
return validParsers;
}
/**
* Makes sure that all parser names are unique
*
* @param parsers - The parsers in question
* @param options - The current ParseOptions
*/
checkParserNames(parsers, options) {
const parserNames = parsers.map(entry => entry.name).filter(entry => entry !== undefined);
const previousNames = [];
const alreadyWarnedNames = [];
for (const parserName of parserNames) {
if (previousNames.includes(parserName) && !alreadyWarnedNames.includes(parserName)) {
this.logger.warn(['Parser name "' + parserName + '" is not unique and appears multiple times in the list of active parsers.'], options);
alreadyWarnedNames.push(parserName);
}
previousNames.push(parserName);
}
}
/**
* A black/whitelist validation function for the benefit of the user. Outputs warnings in the console if something is off.
*
* @param parsers - The parsers in question
* @param blacklist - The blacklist in question
* @param whitelist - The whitelist in question
* @param options - The current ParseOptions
*/
checkBlackAndWhitelist(parsers, blacklist, whitelist, options) {
const parserNames = parsers.map(entry => entry.name).filter(entry => entry !== undefined);
if (blacklist) {
for (const blacklistedParser of blacklist) {
if (!parserNames.includes(blacklistedParser)) {
this.logger.warn(['Blacklisted parser name "' + blacklistedParser + '" does not appear in the list of global parsers names. Make sure both spellings are identical.'], options);
}
}
}
if (whitelist) {
for (const whitelistedParser of whitelist) {
if (!parserNames.includes(whitelistedParser)) {
this.logger.warn(['Whitelisted parser name "' + whitelistedParser + '" does not appear in the list of global parsers names. Make sure both spellings are identical.'], options);
}
}
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ParserEntryResolver, deps: [{ token: i0.Injector }, { token: i1.SelectorHookParserConfigResolver }, { token: i2.AutoPlatformService }, { token: i3.TagHookFinder }, { token: i4.BindingsValueManager }, { token: i5.Logger }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ParserEntryResolver, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ParserEntryResolver, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i0.Injector }, { type: i1.SelectorHookParserConfigResolver }, { type: i2.AutoPlatformService }, { type: i3.TagHookFinder }, { type: i4.BindingsValueManager }, { type: i5.Logger }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VyRW50cnlSZXNvbHZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1keW5hbWljLWhvb2tzL3NyYy9saWIvc2VydmljZXMvc2V0dGluZ3MvcGFyc2VyRW50cnlSZXNvbHZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFZLG9CQUFvQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTNFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLG9EQUFvRCxDQUFDO0FBTTVGLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLDBEQUEwRCxDQUFDOzs7Ozs7O0FBS3JHOztHQUVHO0FBSUgsTUFBTSxPQUFPLG1CQUFtQjtJQUU5QixZQUNVLFFBQWtCLEVBQ2xCLGNBQWdELEVBQ2hELGVBQW9DLEVBQ3BDLGFBQTRCLEVBQzVCLG9CQUEwQyxFQUMxQyxNQUFjO1FBTGQsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUNsQixtQkFBYyxHQUFkLGNBQWMsQ0FBa0M7UUFDaEQsb0JBQWUsR0FBZixlQUFlLENBQXFCO1FBQ3BDLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBQzVCLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBc0I7UUFDMUMsV0FBTSxHQUFOLE1BQU0sQ0FBUTtJQUV4QixDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSCxPQUFPLENBQUMsYUFBZ0MsRUFBRSxRQUFrQixFQUFFLFNBQXdCLEVBQUUsU0FBd0IsRUFBRSxPQUFxQjtRQUVySSw2QkFBNkI7UUFDN0IsTUFBTSxPQUFPLEdBQWlCLEVBQUUsQ0FBQztRQUNqQyxLQUFLLE1BQU0sTUFBTSxJQUFJLGFBQWEsRUFBRSxDQUFDO1lBQ25DLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNwRSxJQUFJLGNBQWMsRUFBRSxDQUFDO2dCQUNuQixPQUFPLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQy9CLENBQUM7UUFDSCxDQUFDO1FBRUQseUJBQXlCO1FBQ3pCLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFcEUscUJBQXFCO1FBQ3JCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFN0MsZ0RBQWdEO1FBQ2hELElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUMzQixPQUFPLFlBQVksQ0FBQztRQUN4QixDQUFDO1FBRUQsd0JBQXdCO1FBQ3hCLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxZQUFZLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUV6RSxpQkFBaUI7UUFDakIsTUFBTSxlQUFlLEdBQUcsRUFBRSxDQUFDO1FBQzNCLEtBQUssTUFBTSxXQUFXLElBQUksWUFBWSxFQUFFLENBQUM7WUFDdkMsSUFBSSxXQUFXLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxJQUFJLE9BQU8sV0FBVyxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDL0UsSUFBSSxTQUFTLElBQUksU0FBUyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztvQkFDdEQsU0FBUztnQkFDWCxDQUFDO2dCQUNELElBQUksU0FBUyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztvQkFDdkQsU0FBUztnQkFDWCxDQUFDO1lBQ0gsQ0FBQztZQUNELGVBQWUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDcEMsQ0FBQztRQUVELE9BQU8sZUFBZSxDQUFDO0lBQ3pCLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7OztPQWFHO0lBQ0gsWUFBWSxDQUFDLFdBQTRCLEVBQUUsUUFBa0IsRUFBRSxPQUFxQjtRQUNsRixpQkFBaUI7UUFDakIsSUFBSSxXQUFXLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUM7WUFDNUMsMkJBQTJCO1lBQzNCLE1BQU0sYUFBYSxHQUFHLG9CQUFvQixDQUFDLFdBQWtCLENBQUMsQ0FBQztZQUMvRCxJQUFJLGFBQWEsRUFBRSxDQUFDO2dCQUNsQixPQUFPLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxFQUFDLFNBQVMsRUFBRSxXQUFrQixFQUFDLENBQUMsQ0FBQztnQkFDeEUsNEJBQTRCO1lBQzVCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixtQkFBbUI7Z0JBQ25CLElBQUksQ0FBQztvQkFDSCxPQUFPLFFBQVEsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7b0JBQ25DLGlDQUFpQztnQkFDakMsQ0FBQztnQkFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO29CQUNYLE9BQU8sSUFBSyxXQUEwQyxFQUFFLENBQUM7Z0JBQzNELENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUVELGtCQUFrQjthQUNiLElBQUksT0FBTyxXQUFXLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDekMsY0FBYztZQUNkLElBQUksV0FBVyxDQUFDLFdBQVcsQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQzlDLE9BQU8sV0FBeUIsQ0FBQztnQkFDbkMsb0JBQW9CO1lBQ3BCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUM7b0JBQ0gsT0FBTyxJQUFJLENBQUMsd0JBQXdCLENBQUMsV0FBdUMsQ0FBQyxDQUFDO2dCQUNoRixDQUFDO2dCQUFDLE9BQU8sQ0FBTSxFQUFHLENBQUM7b0JBQ2pCLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsMEJBQTBCLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztvQkFDbEYsT0FBTyxJQUFJLENBQUM7Z0JBQ2QsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQywwQkFBMEIsRUFBRSxXQUFXLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQTtRQUNyRSxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssd0JBQXdCLENBQUMsTUFBZ0M7UUFDL0QsSUFDRSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxNQUFNLENBQUMsY0FBYyxDQUFDO1lBQ2xFLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUM7WUFDekQsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxZQUFZLENBQUMsRUFDOUQsQ0FBQztZQUNELE9BQU8sSUFBSSxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ2hILENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxJQUFJLHlCQUF5QixDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxlQUFlLEVBQUUsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDckgsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILHVCQUF1QixDQUFDLE9BQXFCLEVBQUUsT0FBcUI7UUFDbEUsTUFBTSxZQUFZLEdBQUcsRUFBRSxDQUFDO1FBQ3hCLEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxFQUFFLENBQUM7WUFDN0IsSUFBSSxPQUFPLE1BQU0sQ0FBQyxTQUFTLEtBQUssVUFBVSxJQUFJLE9BQU8sTUFBTSxDQUFDLGdCQUFnQixLQUFLLFVBQVUsRUFBRSxDQUFDO2dCQUM1RixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLG9JQUFvSSxFQUFFLE1BQU0sQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUMzSyxTQUFTO1lBQ1gsQ0FBQztZQUNELElBQUksT0FBTyxNQUFNLENBQUMsYUFBYSxLQUFLLFVBQVUsRUFBRSxDQUFDO2dCQUMvQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLDhGQUE4RixFQUFFLE1BQU0sQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUNySSxTQUFTO1lBQ1gsQ0FBQztZQUNELElBQUksT0FBTyxNQUFNLENBQUMsV0FBVyxLQUFLLFVBQVUsRUFBRSxDQUFDO2dCQUM3QyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLDRGQUE0RixFQUFFLE1BQU0sQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUNuSSxTQUFTO1lBQ1gsQ0FBQztZQUNELFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDNUIsQ0FBQztRQUNELE9BQU8sWUFBWSxDQUFDO0lBQ3RCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILGdCQUFnQixDQUFDLE9BQXFCLEVBQUUsT0FBcUI7UUFDM0QsTUFBTSxXQUFXLEdBQWEsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFhLENBQUM7UUFDaEgsTUFBTSxhQUFhLEdBQWEsRUFBRSxDQUFDO1FBQ25DLE1BQU0sa0JBQWtCLEdBQWEsRUFBRSxDQUFDO1FBQ3hDLEtBQUssTUFBTSxVQUFVLElBQUksV0FBVyxFQUFFLENBQUM7WUFDckMsSUFBSSxhQUFhLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7Z0JBQ25GLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsZUFBZSxHQUFHLFVBQVUsR0FBRywyRUFBMkUsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUN4SSxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDdEMsQ0FBQztZQUNELGFBQWEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDakMsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsc0JBQXNCLENBQUMsT0FBcUIsRUFBRSxTQUF3QixFQUFFLFNBQXdCLEVBQUUsT0FBcUI7UUFDckgsTUFBTSxXQUFXLEdBQWEsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFhLENBQUM7UUFDaEgsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNkLEtBQUssTUFBTSxpQkFBaUIsSUFBSSxTQUFTLEVBQUUsQ0FBQztnQkFDMUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUFDO29CQUM3QyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLDJCQUEyQixHQUFHLGlCQUFpQixHQUFHLGdHQUFnRyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBQ2xMLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksU0FBUyxFQUFFLENBQUM7WUFDZCxLQUFLLE1BQU0saUJBQWlCLElBQUksU0FBUyxFQUFFLENBQUM7Z0JBQzFDLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsQ0FBQztvQkFDN0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQywyQkFBMkIsR0FBRyxpQkFBaUIsR0FBRyxnR0FBZ0csQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUNsTCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDOytHQTFNVSxtQkFBbUI7bUhBQW5CLG1CQUFtQixjQUZsQixNQUFNOzs0RkFFUCxtQkFBbUI7a0JBSC9CLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgSW5qZWN0b3IsIHJlZmxlY3RDb21wb25lbnRUeXBlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBIb29rUGFyc2VyIH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlc1B1YmxpYyc7XG5pbXBvcnQgeyBUZXh0U2VsZWN0b3JIb29rUGFyc2VyIH0gZnJvbSAnLi4vLi4vcGFyc2Vycy9zZWxlY3Rvci90ZXh0L3RleHRTZWxlY3Rvckhvb2tQYXJzZXInO1xuaW1wb3J0IHsgU2VsZWN0b3JIb29rUGFyc2VyQ29uZmlnIH0gZnJvbSAnLi4vLi4vcGFyc2Vycy9zZWxlY3Rvci9zZWxlY3Rvckhvb2tQYXJzZXJDb25maWcnO1xuaW1wb3J0IHsgU2VsZWN0b3JIb29rUGFyc2VyQ29uZmlnUmVzb2x2ZXIgfSBmcm9tICcuLi8uLi9wYXJzZXJzL3NlbGVjdG9yL3NlbGVjdG9ySG9va1BhcnNlckNvbmZpZ1Jlc29sdmVyJztcbmltcG9ydCB7IFRhZ0hvb2tGaW5kZXIgfSBmcm9tICcuLi8uLi9wYXJzZXJzL3NlbGVjdG9yL3RleHQvdGFnSG9va0ZpbmRlcic7XG5pbXBvcnQgeyBCaW5kaW5nc1ZhbHVlTWFuYWdlciB9IGZyb20gJy4uLy4uL3BhcnNlcnMvc2VsZWN0b3IvYmluZGluZ3NWYWx1ZU1hbmFnZXInO1xuaW1wb3J0IHsgSG9va1BhcnNlckVudHJ5IH0gZnJvbSAnLi9wYXJzZXJFbnRyeSc7XG5pbXBvcnQgeyBFbGVtZW50U2VsZWN0b3JIb29rUGFyc2VyIH0gZnJvbSAnLi4vLi4vcGFyc2Vycy9zZWxlY3Rvci9lbGVtZW50L2VsZW1lbnRTZWxlY3Rvckhvb2tQYXJzZXInO1xuaW1wb3J0IHsgQXV0b1BsYXRmb3JtU2VydmljZSB9IGZyb20gJy4uL3BsYXRmb3JtL2F1dG9QbGF0Zm9ybVNlcnZpY2UnO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyJztcbmltcG9ydCB7IFBhcnNlT3B0aW9ucyB9IGZyb20gJy4uL3NldHRpbmdzL29wdGlvbnMnO1xuXG4vKipcbiAqIEEgaGVscGVyIGNsYXNzIGZvciByZXNvbHZpbmcgSG9va1BhcnNlckVudHJpZXNcbiAqL1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgUGFyc2VyRW50cnlSZXNvbHZlciB7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBpbmplY3RvcjogSW5qZWN0b3IsIFxuICAgIHByaXZhdGUgcGFyc2VyUmVzb2x2ZXI6IFNlbGVjdG9ySG9va1BhcnNlckNvbmZpZ1Jlc29sdmVyLCBcbiAgICBwcml2YXRlIHBsYXRmb3JtU2VydmljZTogQXV0b1BsYXRmb3JtU2VydmljZSwgXG4gICAgcHJpdmF0ZSB0YWdIb29rRmluZGVyOiBUYWdIb29rRmluZGVyLCBcbiAgICBwcml2YXRlIGJpbmRpbmdzVmFsdWVNYW5hZ2VyOiBCaW5kaW5nc1ZhbHVlTWFuYWdlcixcbiAgICBwcml2YXRlIGxvZ2dlcjogTG9nZ2VyXG4gICkge1xuICB9XG5cbiAgLyoqXG4gICAqIFRha2VzIGEgbGlzdCBvZiBIb29rUGFyc2VyRW50cmllcyBhbmQgdHJhbnNmb3JtcyB0aGVtIGludG8gYSBsaXN0IG9mIGxvYWRlZCBIb29rUGFyc2Vyc1xuICAgKlxuICAgKiBAcGFyYW0gcGFyc2VyRW50cmllcyAtIFRoZSBsaXN0IG9mIEhvb2tQYXJzZXJFbnRyaWVzIHRvIHByb2Nlc3NcbiAgICogQHBhcmFtIGluamVjdG9yIC0gVGhlIGluamVjdG9yIHRvIHVzZSBmb3IgcmVzb2x2aW5nIHBhcnNlcnNcbiAgICogQHBhcmFtIGJsYWNrbGlzdCAtIChvcHRpb25hbCkgV2hpY2ggcGFyc2VycyB0byBibGFja2xpc3QgYnkgbmFtZVxuICAgKiBAcGFyYW0gd2hpdGVsaXN0IC0gKG9wdGlvbmFsKSBXaGljaCBwYXJzZXJzIHRvIHdoaXRlbGlzdCBieSBuYW1lXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIGN1cnJlbnQgUGFyc2VPcHRpb25zXG4gICAqL1xuICByZXNvbHZlKHBhcnNlckVudHJpZXM6IEhvb2tQYXJzZXJFbnRyeVtdLCBpbmplY3RvcjogSW5qZWN0b3IsIGJsYWNrbGlzdDogc3RyaW5nW118bnVsbCwgd2hpdGVsaXN0OiBzdHJpbmdbXXxudWxsLCBvcHRpb25zOiBQYXJzZU9wdGlvbnMpOiBIb29rUGFyc2VyW10ge1xuXG4gICAgLy8gTG9hZCBhbGwgcmVxdWVzdGVkIHBhcnNlcnNcbiAgICBjb25zdCBwYXJzZXJzOiBIb29rUGFyc2VyW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IHBhcnNlciBvZiBwYXJzZXJFbnRyaWVzKSB7XG4gICAgICBjb25zdCByZXNvbHZlZFBhcnNlciA9IHRoaXMucmVzb2x2ZUVudHJ5KHBhcnNlciwgaW5qZWN0b3IsIG9wdGlvbnMpO1xuICAgICAgaWYgKHJlc29sdmVkUGFyc2VyKSB7XG4gICAgICAgIHBhcnNlcnMucHVzaChyZXNvbHZlZFBhcnNlcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgcGFyc2VyIGZ1bmN0aW9uc1xuICAgIGNvbnN0IHZhbGlkUGFyc2VycyA9IHRoaXMudmFsaWRhdGVQYXJzZXJGdW5jdGlvbnMocGFyc2Vycywgb3B0aW9ucyk7XG5cbiAgICAvLyBDaGVjayBwYXJzZXIgbmFtZXNcbiAgICB0aGlzLmNoZWNrUGFyc2VyTmFtZXModmFsaWRQYXJzZXJzLCBvcHRpb25zKTtcblxuICAgIC8vIElmIG5vIG5lZWQgdG8gZmlsdGVyLCByZXR1cm4gcmVzb2x2ZWQgcGFyc2Vyc1xuICAgIGlmICghYmxhY2tsaXN0ICYmICF3aGl0ZWxpc3QpIHtcbiAgICAgICAgcmV0dXJuIHZhbGlkUGFyc2VycztcbiAgICB9XG5cbiAgICAvLyBDaGVjayBibGFjay93aGl0ZWxpc3RcbiAgICB0aGlzLmNoZWNrQmxhY2tBbmRXaGl0ZWxpc3QodmFsaWRQYXJzZXJzLCBibGFja2xpc3QsIHdoaXRlbGlzdCwgb3B0aW9ucyk7XG5cbiAgICAvLyBGaWx0ZXIgcGFyc2Vyc1xuICAgIGNvbnN0IGZpbHRlcmVkUGFyc2VycyA9IFtdO1xuICAgIGZvciAoY29uc3QgdmFsaWRQYXJzZXIgb2YgdmFsaWRQYXJzZXJzKSB7XG4gICAgICBpZiAodmFsaWRQYXJzZXIuaGFzT3duUHJvcGVydHkoJ25hbWUnKSAmJiB0eXBlb2YgdmFsaWRQYXJzZXIubmFtZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYgKGJsYWNrbGlzdCAmJiBibGFja2xpc3QuaW5jbHVkZXModmFsaWRQYXJzZXIubmFtZSkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAod2hpdGVsaXN0ICYmICF3aGl0ZWxpc3QuaW5jbHVkZXModmFsaWRQYXJzZXIubmFtZSkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZmlsdGVyZWRQYXJzZXJzLnB1c2godmFsaWRQYXJzZXIpO1xuICAgIH1cblxuICAgIHJldHVybiBmaWx0ZXJlZFBhcnNlcnM7XG4gIH1cblxuICAvKipcbiAgICogRmlndXJlcyBvdXQgd2hhdCBraW5kIG9mIGNvbmZpZyB0eXBlIHRoZSBIb29rUGFyc2VyRW50cnkgaXMgYW5kIGxvYWRzIGl0IGFwcHJvcHJpYXRlbHkuXG4gICAqXG4gICAqIFRoZSBwb3RlbnRpYWwgdHlwZXMgYXJlOlxuICAgKiAtIDEuIGEgY29tcG9uZW50IGNsYXNzIChzaG9ydGhhbmQgZm9yIG5yLiA1KVxuICAgKiAtIDIuIGEgcGFyc2VyIHNlcnZpY2VcbiAgICogLSAzLiBhIHBhcnNlciBjbGFzc1xuICAgKiAtIDQuIGEgcGFyc2VyIGluc3RhbmNlXG4gICAqIC0gNS4gYW4gb2JqZWN0IGxpdGVyYWwgdG8gY29uZmlndXJlIFNlbGVjdG9ySG9va1BhcnNlciB3aXRoXG4gICAqXG4gICAqIEBwYXJhbSBwYXJzZXJFbnRyeSAtIFRoZSBIb29rUGFyc2VyRW50cnkgdG8gcHJvY2Vzc1xuICAgKiBAcGFyYW0gaW5qZWN0b3IgLSBUaGUgaW5qZWN0b3IgdG8gdXNlIGZvciByZXNvbHZpbmcgdGhpcyBwYXJzZXJcbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgY3VycmVudCBQYXJzZU9wdGlvbnNcbiAgICovXG4gIHJlc29sdmVFbnRyeShwYXJzZXJFbnRyeTogSG9va1BhcnNlckVudHJ5LCBpbmplY3RvcjogSW5qZWN0b3IsIG9wdGlvbnM6IFBhcnNlT3B0aW9ucyk6IEhvb2tQYXJzZXJ8bnVsbCB7XG4gICAgLy8gQ2hlY2sgaWYgY2xhc3NcbiAgICBpZiAocGFyc2VyRW50cnkuaGFzT3duUHJvcGVydHkoJ3Byb3RvdHlwZScpKSB7XG4gICAgICAvLyBDaGVjayBpZiBjb21wb25lbnQgY2xhc3NcbiAgICAgIGNvbnN0IGNvbXBvbmVudE1ldGEgPSByZWZsZWN0Q29tcG9uZW50VHlwZShwYXJzZXJFbnRyeSBhcyBhbnkpO1xuICAgICAgaWYgKGNvbXBvbmVudE1ldGEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlU2VsZWN0b3JIb29rUGFyc2VyKHtjb21wb25lbnQ6IHBhcnNlckVudHJ5IGFzIGFueX0pO1xuICAgICAgLy8gRWxzZSBtdXN0IGJlIHBhcnNlciBjbGFzc1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgc2VydmljZVxuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBpbmplY3Rvci5nZXQocGFyc2VyRW50cnkpO1xuICAgICAgICAvLyBPdGhlcndpc2UgaW5zdGFudGlhdGUgbWFudWFsbHlcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHJldHVybiBuZXcgKHBhcnNlckVudHJ5IGFzIG5ldyguLi5hcmdzOiBhbnlbXSkgPT4gYW55KSgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgb2JqZWN0XG4gICAgZWxzZSBpZiAodHlwZW9mIHBhcnNlckVudHJ5ID09PSAnb2JqZWN0Jykge1xuICAgICAgLy8gSXMgaW5zdGFuY2VcbiAgICAgIGlmIChwYXJzZXJFbnRyeS5jb25zdHJ1Y3Rvci5uYW1lICE9PSAnT2JqZWN0Jykge1xuICAgICAgICByZXR1cm4gcGFyc2VyRW50cnkgYXMgSG9va1BhcnNlcjtcbiAgICAgIC8vIElzIG9iamVjdCBsaXRlcmFsXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZVNlbGVjdG9ySG9va1BhcnNlcihwYXJzZXJFbnRyeSBhcyBTZWxlY3Rvckhvb2tQYXJzZXJDb25maWcpO1xuICAgICAgICB9IGNhdGNoIChlOiBhbnkpICB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoWydJbnZhbGlkIHBhcnNlciBjb25maWcgLSAnICsgZS5tZXNzYWdlLCBwYXJzZXJFbnRyeV0sIG9wdGlvbnMpO1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIHRoaXMubG9nZ2VyLmVycm9yKFsnSW52YWxpZCBwYXJzZXIgY29uZmlnIC0gJywgcGFyc2VyRW50cnldLCBvcHRpb25zKVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIERlcGVuZGluZyBvbiB0aGUgY29uZmlnLCBsb2FkIGVpdGhlciBzdHJpbmcgb3IgZWxlbWVudCBTZWxlY3Rvckhvb2tQYXJzZXJcbiAgICpcbiAgICogQHBhcmFtIGNvbmZpZyAtIFRoZSBzZWxlY3Rvckhvb2tQYXJzZXJDb25maWdcbiAgICovXG4gIHByaXZhdGUgY3JlYXRlU2VsZWN0b3JIb29rUGFyc2VyKGNvbmZpZzogU2VsZWN0b3JIb29rUGFyc2VyQ29uZmlnKTogSG9va1BhcnNlciB7XG4gICAgaWYgKFxuICAgICAgKGNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgncGFyc2VXaXRoUmVnZXgnKSAmJiBjb25maWcucGFyc2VXaXRoUmVnZXgpIHx8IFxuICAgICAgKGNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgnZW5jbG9zaW5nJykgJiYgIWNvbmZpZy5lbmNsb3NpbmcpIHx8IFxuICAgICAgKGNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgnYnJhY2tldFN0eWxlJykgJiYgY29uZmlnLmJyYWNrZXRTdHlsZSlcbiAgICApIHtcbiAgICAgIHJldHVybiBuZXcgVGV4dFNlbGVjdG9ySG9va1BhcnNlcihjb25maWcsIHRoaXMucGFyc2VyUmVzb2x2ZXIsIHRoaXMudGFnSG9va0ZpbmRlciwgdGhpcy5iaW5kaW5nc1ZhbHVlTWFuYWdlcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBuZXcgRWxlbWVudFNlbGVjdG9ySG9va1BhcnNlcihjb25maWcsIHRoaXMucGFyc2VyUmVzb2x2ZXIsIHRoaXMucGxhdGZvcm1TZXJ2aWNlLCB0aGlzLmJpbmRpbmdzVmFsdWVNYW5hZ2VyKTtcbiAgICB9ICAgIFxuICB9XG5cbiAgLyoqXG4gICAqIE1ha2VzIHN1cmUgdGhhdCB0aGUgcGFyc2VycyBoYXZlIGFsbCByZXF1aXJlZCBmdW5jdGlvbnNcbiAgICpcbiAgICogQHBhcmFtIHBhcnNlcnMgLSBUaGUgcGFyc2VycyBpbiBxdWVzdGlvblxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBjdXJyZW50IFBhcnNlT3B0aW9uc1xuICAgKi9cbiAgdmFsaWRhdGVQYXJzZXJGdW5jdGlvbnMocGFyc2VyczogSG9va1BhcnNlcltdLCBvcHRpb25zOiBQYXJzZU9wdGlvbnMpOiBIb29rUGFyc2VyW10ge1xuICAgIGNvbnN0IHZhbGlkUGFyc2VycyA9IFtdO1xuICAgIGZvciAoY29uc3QgcGFyc2VyIG9mIHBhcnNlcnMpIHtcbiAgICAgIGlmICh0eXBlb2YgcGFyc2VyLmZpbmRIb29rcyAhPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgcGFyc2VyLmZpbmRIb29rRWxlbWVudHMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoWydTdWJtaXR0ZWQgcGFyc2VyIG5laXRoZXIgaW1wbGVtZW50cyBcImZpbmRIb29rcygpXCIgbm9yIFwiZmluZEhvb2tFbGVtZW50cygpXCIuIE9uZSBpcyByZXF1aXJlZC4gUmVtb3ZpbmcgZnJvbSBsaXN0IG9mIGFjdGl2ZSBwYXJzZXJzOicsIHBhcnNlcl0sIG9wdGlvbnMpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgcGFyc2VyLmxvYWRDb21wb25lbnQgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoWydTdWJtaXR0ZWQgcGFyc2VyIGRvZXMgbm90IGltcGxlbWVudCBcImxvYWRDb21wb25lbnQoKVwiLiBSZW1vdmluZyBmcm9tIGxpc3Qgb2YgYWN0aXZlIHBhcnNlcnM6JywgcGFyc2VyXSwgb3B0aW9ucyk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiBwYXJzZXIuZ2V0QmluZGluZ3MgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoWydTdWJtaXR0ZWQgcGFyc2VyIGRvZXMgbm90IGltcGxlbWVudCBcImdldEJpbmRpbmdzKClcIi4gUmVtb3ZpbmcgZnJvbSBsaXN0IG9mIGFjdGl2ZSBwYXJzZXJzOicsIHBhcnNlcl0sIG9wdGlvbnMpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHZhbGlkUGFyc2Vycy5wdXNoKHBhcnNlcik7XG4gICAgfVxuICAgIHJldHVybiB2YWxpZFBhcnNlcnM7XG4gIH1cblxuICAvKipcbiAgICogTWFrZXMgc3VyZSB0aGF0IGFsbCBwYXJzZXIgbmFtZXMgYXJlIHVuaXF1ZVxuICAgKlxuICAgKiBAcGFyYW0gcGFyc2VycyAtIFRoZSBwYXJzZXJzIGluIHF1ZXN0aW9uXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIGN1cnJlbnQgUGFyc2VPcHRpb25zXG4gICAqL1xuICBjaGVja1BhcnNlck5hbWVzKHBhcnNlcnM6IEhvb2tQYXJzZXJbXSwgb3B0aW9uczogUGFyc2VPcHRpb25zKTogdm9pZCB7XG4gICAgY29uc3QgcGFyc2VyTmFtZXM6IHN0cmluZ1tdID0gcGFyc2Vycy5tYXAoZW50cnkgPT4gZW50cnkubmFtZSkuZmlsdGVyKGVudHJ5ID0+IGVudHJ5ICE9PSB1bmRlZmluZWQpIGFzIHN0cmluZ1tdO1xuICAgIGNvbnN0IHByZXZpb3VzTmFtZXM6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3QgYWxyZWFkeVdhcm5lZE5hbWVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgcGFyc2VyTmFtZSBvZiBwYXJzZXJOYW1lcykge1xuICAgICAgaWYgKHByZXZpb3VzTmFtZXMuaW5jbHVkZXMocGFyc2VyTmFtZSkgJiYgIWFscmVhZHlXYXJuZWROYW1lcy5pbmNsdWRlcyhwYXJzZXJOYW1lKSkge1xuICAgICAgICB0aGlzLmxvZ2dlci53YXJuKFsnUGFyc2VyIG5hbWUgXCInICsgcGFyc2VyTmFtZSArICdcIiBpcyBub3QgdW5pcXVlIGFuZCBhcHBlYXJzIG11bHRpcGxlIHRpbWVzIGluIHRoZSBsaXN0IG9mIGFjdGl2ZSBwYXJzZXJzLiddLCBvcHRpb25zKTtcbiAgICAgICAgYWxyZWFkeVdhcm5lZE5hbWVzLnB1c2gocGFyc2VyTmFtZSk7XG4gICAgICB9XG4gICAgICBwcmV2aW91c05hbWVzLnB1c2gocGFyc2VyTmFtZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEEgYmxhY2svd2hpdGVsaXN0IHZhbGlkYXRpb24gZnVuY3Rpb24gZm9yIHRoZSBiZW5lZml0IG9mIHRoZSB1c2VyLiBPdXRwdXRzIHdhcm5pbmdzIGluIHRoZSBjb25zb2xlIGlmIHNvbWV0aGluZyBpcyBvZmYuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJzZXJzIC0gVGhlIHBhcnNlcnMgaW4gcXVlc3Rpb25cbiAgICogQHBhcmFtIGJsYWNrbGlzdCAtIFRoZSBibGFja2xpc3QgaW4gcXVlc3Rpb25cbiAgICogQHBhcmFtIHdoaXRlbGlzdCAtIFRoZSB3aGl0ZWxpc3QgaW4gcXVlc3Rpb25cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgY3VycmVudCBQYXJzZU9wdGlvbnNcbiAgICovXG4gIGNoZWNrQmxhY2tBbmRXaGl0ZWxpc3QocGFyc2VyczogSG9va1BhcnNlcltdLCBibGFja2xpc3Q6IHN0cmluZ1tdfG51bGwsIHdoaXRlbGlzdDogc3RyaW5nW118bnVsbCwgb3B0aW9uczogUGFyc2VPcHRpb25zKTogdm9pZCB7XG4gICAgY29uc3QgcGFyc2VyTmFtZXM6IHN0cmluZ1tdID0gcGFyc2Vycy5tYXAoZW50cnkgPT4gZW50cnkubmFtZSkuZmlsdGVyKGVudHJ5ID0+IGVudHJ5ICE9PSB1bmRlZmluZWQpIGFzIHN0cmluZ1tdO1xuICAgIGlmIChibGFja2xpc3QpIHtcbiAgICAgIGZvciAoY29uc3QgYmxhY2tsaXN0ZWRQYXJzZXIgb2YgYmxhY2tsaXN0KSB7XG4gICAgICAgIGlmICghcGFyc2VyTmFtZXMuaW5jbHVkZXMoYmxhY2tsaXN0ZWRQYXJzZXIpKSB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIud2FybihbJ0JsYWNrbGlzdGVkIHBhcnNlciBuYW1lIFwiJyArIGJsYWNrbGlzdGVkUGFyc2VyICsgJ1wiIGRvZXMgbm90IGFwcGVhciBpbiB0aGUgbGlzdCBvZiBnbG9iYWwgcGFyc2VycyBuYW1lcy4gTWFrZSBzdXJlIGJvdGggc3BlbGxpbmdzIGFyZSBpZGVudGljYWwuJ10sIG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmICh3aGl0ZWxpc3QpIHtcbiAgICAgIGZvciAoY29uc3Qgd2hpdGVsaXN0ZWRQYXJzZXIgb2Ygd2hpdGVsaXN0KSB7XG4gICAgICAgIGlmICghcGFyc2VyTmFtZXMuaW5jbHVkZXMod2hpdGVsaXN0ZWRQYXJzZXIpKSB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIud2FybihbJ1doaXRlbGlzdGVkIHBhcnNlciBuYW1lIFwiJyArIHdoaXRlbGlzdGVkUGFyc2VyICsgJ1wiIGRvZXMgbm90IGFwcGVhciBpbiB0aGUgbGlzdCBvZiBnbG9iYWwgcGFyc2VycyBuYW1lcy4gTWFrZSBzdXJlIGJvdGggc3BlbGxpbmdzIGFyZSBpZGVudGljYWwuJ10sIG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbn1cbiJdfQ==