ngx-markdown
Version:
Angular library that uses marked to parse markdown to html combined with Prism.js for synthax highlights
541 lines (524 loc) • 57.8 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('@angular/common/http'), require('@angular/platform-browser'), require('marked'), require('rxjs/operators')) :
typeof define === 'function' && define.amd ? define('ngx-markdown', ['exports', '@angular/core', '@angular/common', '@angular/common/http', '@angular/platform-browser', 'marked', 'rxjs/operators'], factory) :
(factory((global['ngx-markdown'] = {}),global.ng.core,global.ng.common,global.ng.common.http,global.ng.platformBrowser,null,global.rxjs.operators));
}(this, (function (exports,core,common,http,platformBrowser,marked,operators) { 'use strict';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var LanguagePipe = /** @class */ (function () {
function LanguagePipe() {
}
/**
* @param {?} value
* @param {?} language
* @return {?}
*/
LanguagePipe.prototype.transform = /**
* @param {?} value
* @param {?} language
* @return {?}
*/
function (value, language) {
if (typeof value !== 'string') {
console.error("LanguagePipe has been invoked with an invalid value type [" + value + "]");
return value;
}
if (typeof language !== 'string') {
console.error("LanguagePipe has been invoked with an invalid parameter [" + language + "]");
return value;
}
return '```' + language + '\n' + value + '\n```';
};
LanguagePipe.decorators = [
{ type: core.Pipe, args: [{
name: 'language',
},] },
];
return LanguagePipe;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var MarkedOptions = /** @class */ (function () {
function MarkedOptions() {
}
return MarkedOptions;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/** @type {?} */
var errorSrcWithoutHttpClient = '[ngx-markdown] When using the [src] attribute you *have to* pass the `HttpClient` as a parameter of the `forRoot` method. See README for more information';
var MarkdownService = /** @class */ (function () {
function MarkdownService(platform, http$$1, domSanitizer, options) {
this.platform = platform;
this.http = http$$1;
this.domSanitizer = domSanitizer;
this.options = options;
if (!this.renderer) {
this.renderer = new marked.Renderer();
}
}
Object.defineProperty(MarkdownService.prototype, "renderer", {
get: /**
* @return {?}
*/ function () { return this.options.renderer; },
set: /**
* @param {?} value
* @return {?}
*/ function (value) {
this.options.renderer = value;
},
enumerable: true,
configurable: true
});
/**
* @param {?} markdown
* @param {?=} decodeHtml
* @param {?=} markedOptions
* @return {?}
*/
MarkdownService.prototype.compile = /**
* @param {?} markdown
* @param {?=} decodeHtml
* @param {?=} markedOptions
* @return {?}
*/
function (markdown, decodeHtml, markedOptions) {
if (decodeHtml === void 0) {
decodeHtml = false;
}
if (markedOptions === void 0) {
markedOptions = this.options;
}
/** @type {?} */
var precompiled = this.precompile(markdown);
/** @type {?} */
var compiled = marked.parse(decodeHtml ? this.decodeHtml(precompiled) : precompiled, markedOptions);
return markedOptions.sanitize && !markedOptions.sanitizer
? this.domSanitizer.sanitize(core.SecurityContext.HTML, compiled)
: compiled;
};
/**
* @param {?} src
* @return {?}
*/
MarkdownService.prototype.getSource = /**
* @param {?} src
* @return {?}
*/
function (src) {
var _this = this;
if (!this.http) {
throw new Error(errorSrcWithoutHttpClient);
}
return this.http
.get(src, { responseType: 'text' })
.pipe(operators.map(function (markdown) { return _this.handleExtension(src, markdown); }));
};
/**
* @return {?}
*/
MarkdownService.prototype.highlight = /**
* @return {?}
*/
function () {
if (common.isPlatformBrowser(this.platform) && typeof Prism !== 'undefined') {
Prism.highlightAll(false);
}
};
/**
* @param {?} html
* @return {?}
*/
MarkdownService.prototype.decodeHtml = /**
* @param {?} html
* @return {?}
*/
function (html) {
if (common.isPlatformBrowser(this.platform)) {
/** @type {?} */
var textarea = document.createElement('textarea');
textarea.innerHTML = html;
return textarea.value;
}
return html;
};
/**
* @param {?} src
* @param {?} markdown
* @return {?}
*/
MarkdownService.prototype.handleExtension = /**
* @param {?} src
* @param {?} markdown
* @return {?}
*/
function (src, markdown) {
/** @type {?} */
var extension = src
? src.split('.').splice(-1).join()
: null;
return extension !== 'md'
? '```' + extension + '\n' + markdown + '\n```'
: markdown;
};
/**
* @param {?} markdown
* @return {?}
*/
MarkdownService.prototype.precompile = /**
* @param {?} markdown
* @return {?}
*/
function (markdown) {
if (!markdown) {
return '';
}
/** @type {?} */
var indentStart;
return markdown
.split('\n')
.map(function (line) {
/** @type {?} */
var lineIdentStart = indentStart;
// find position of 1st non-whitespace character
// to determine the current line indentation start
if (line.length > 0) {
lineIdentStart = isNaN(lineIdentStart)
? line.search(/\S|$/)
: Math.min(line.search(/\S|$/), lineIdentStart);
}
// keep 1st non-whitespace line indentation
// as base reference for other lines
if (isNaN(indentStart)) {
indentStart = lineIdentStart;
}
// remove whitespaces before current line indentation
return !!lineIdentStart
? line.substring(lineIdentStart)
: line;
}).join('\n');
};
MarkdownService.decorators = [
{ type: core.Injectable },
];
/** @nocollapse */
MarkdownService.ctorParameters = function () {
return [
{ type: Object, decorators: [{ type: core.Inject, args: [core.PLATFORM_ID,] }] },
{ type: http.HttpClient, decorators: [{ type: core.Optional }] },
{ type: platformBrowser.DomSanitizer },
{ type: MarkedOptions }
];
};
return MarkdownService;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var MarkdownComponent = /** @class */ (function () {
function MarkdownComponent(element, markdownService) {
this.element = element;
this.markdownService = markdownService;
this.error = new core.EventEmitter();
this.load = new core.EventEmitter();
}
Object.defineProperty(MarkdownComponent.prototype, "_isTranscluded", {
get: /**
* @return {?}
*/ function () {
return !this._data && !this._src;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MarkdownComponent.prototype, "data", {
get: /**
* @return {?}
*/ function () { return this._data; },
set: /**
* @param {?} value
* @return {?}
*/ function (value) {
this._data = value;
this.render(value);
},
enumerable: true,
configurable: true
});
Object.defineProperty(MarkdownComponent.prototype, "src", {
get: /**
* @return {?}
*/ function () { return this._src; },
set: /**
* @param {?} value
* @return {?}
*/ function (value) {
var _this = this;
this._src = value;
this.markdownService
.getSource(value)
.subscribe(function (markdown) {
_this.render(markdown);
_this.load.emit(markdown);
}, function (error) { return _this.error.emit(error); });
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
MarkdownComponent.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
if (this._isTranscluded) {
this.render(this.element.nativeElement.innerHTML, true);
}
};
/**
* @param {?} markdown
* @param {?=} decodeHtml
* @return {?}
*/
MarkdownComponent.prototype.render = /**
* @param {?} markdown
* @param {?=} decodeHtml
* @return {?}
*/
function (markdown, decodeHtml) {
if (decodeHtml === void 0) {
decodeHtml = false;
}
this.element.nativeElement.innerHTML = this.markdownService.compile(markdown, decodeHtml);
this.markdownService.highlight();
};
MarkdownComponent.decorators = [
{ type: core.Component, args: [{
// tslint:disable-next-line:component-selector
selector: 'markdown, [markdown]',
template: '<ng-content></ng-content>',
},] },
];
/** @nocollapse */
MarkdownComponent.ctorParameters = function () {
return [
{ type: core.ElementRef },
{ type: MarkdownService }
];
};
MarkdownComponent.propDecorators = {
data: [{ type: core.Input }],
src: [{ type: core.Input }],
error: [{ type: core.Output }],
load: [{ type: core.Output }]
};
return MarkdownComponent;
}());
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b)
if (b.hasOwnProperty(p))
d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m)
return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
ar.push(r.value);
}
catch (error) {
e = { error: error };
}
finally {
try {
if (r && !r.done && (m = i["return"]))
m.call(i);
}
finally {
if (e)
throw e.error;
}
}
return ar;
}
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var MarkdownPipe = /** @class */ (function () {
function MarkdownPipe(markdownService, zone) {
this.markdownService = markdownService;
this.zone = zone;
}
/**
* @param {?} value
* @return {?}
*/
MarkdownPipe.prototype.transform = /**
* @param {?} value
* @return {?}
*/
function (value) {
var _this = this;
if (typeof value !== 'string') {
console.error("MarkdownPipe has been invoked with an invalid value type [" + value + "]");
return value;
}
/** @type {?} */
var markdown = this.markdownService.compile(value);
this.zone.onStable
.pipe(operators.first())
.subscribe(function () { return _this.markdownService.highlight(); });
return markdown;
};
MarkdownPipe.decorators = [
{ type: core.Pipe, args: [{
name: 'markdown',
},] },
];
/** @nocollapse */
MarkdownPipe.ctorParameters = function () {
return [
{ type: MarkdownService },
{ type: core.NgZone }
];
};
return MarkdownPipe;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/** @type {?} */
var initialMarkedOptions = {
provide: MarkedOptions,
useValue: {
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false,
},
};
/** @type {?} */
var sharedDeclarations = [
LanguagePipe,
MarkdownComponent,
MarkdownPipe,
];
var MarkdownModule = /** @class */ (function () {
function MarkdownModule() {
}
/**
* @param {?=} markdownModuleConfig
* @return {?}
*/
MarkdownModule.forRoot = /**
* @param {?=} markdownModuleConfig
* @return {?}
*/
function (markdownModuleConfig) {
return {
ngModule: MarkdownModule,
providers: __spread([
MarkdownService
], (markdownModuleConfig
? [
markdownModuleConfig.loader || [],
markdownModuleConfig.markedOptions || initialMarkedOptions,
]
: [initialMarkedOptions])),
};
};
/**
* @return {?}
*/
MarkdownModule.forChild = /**
* @return {?}
*/
function () {
return {
ngModule: MarkdownModule,
};
};
MarkdownModule.decorators = [
{ type: core.NgModule, args: [{
exports: __spread(sharedDeclarations),
declarations: __spread(sharedDeclarations),
},] },
];
return MarkdownModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var MarkedRenderer = /** @class */ (function (_super) {
__extends(MarkedRenderer, _super);
function MarkedRenderer() {
return _super !== null && _super.apply(this, arguments) || this;
}
return MarkedRenderer;
}(marked.Renderer));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
exports.LanguagePipe = LanguagePipe;
exports.MarkdownComponent = MarkdownComponent;
exports.initialMarkedOptions = initialMarkedOptions;
exports.MarkdownModule = MarkdownModule;
exports.MarkdownPipe = MarkdownPipe;
exports.errorSrcWithoutHttpClient = errorSrcWithoutHttpClient;
exports.MarkdownService = MarkdownService;
exports.MarkedOptions = MarkedOptions;
exports.MarkedRenderer = MarkedRenderer;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW1hcmtkb3duLnVtZC5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vbmd4LW1hcmtkb3duL3NyYy9sYW5ndWFnZS5waXBlLnRzIiwibmc6Ly9uZ3gtbWFya2Rvd24vc3JjL21hcmtlZC1vcHRpb25zLnRzIiwibmc6Ly9uZ3gtbWFya2Rvd24vc3JjL21hcmtkb3duLnNlcnZpY2UudHMiLCJuZzovL25neC1tYXJrZG93bi9zcmMvbWFya2Rvd24uY29tcG9uZW50LnRzIixudWxsLCJuZzovL25neC1tYXJrZG93bi9zcmMvbWFya2Rvd24ucGlwZS50cyIsIm5nOi8vbmd4LW1hcmtkb3duL3NyYy9tYXJrZG93bi5tb2R1bGUudHMiLCJuZzovL25neC1tYXJrZG93bi9zcmMvbWFya2VkLXJlbmRlcmVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBpcGUsIFBpcGVUcmFuc2Zvcm0gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbkBQaXBlKHtcclxuICBuYW1lOiAnbGFuZ3VhZ2UnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTGFuZ3VhZ2VQaXBlIGltcGxlbWVudHMgUGlwZVRyYW5zZm9ybSB7XHJcblxyXG4gIHRyYW5zZm9ybSh2YWx1ZTogc3RyaW5nLCBsYW5ndWFnZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoYExhbmd1YWdlUGlwZSBoYXMgYmVlbiBpbnZva2VkIHdpdGggYW4gaW52YWxpZCB2YWx1ZSB0eXBlIFske3ZhbHVlfV1gKTtcclxuICAgICAgcmV0dXJuIHZhbHVlO1xyXG4gICAgfVxyXG4gICAgaWYgKHR5cGVvZiBsYW5ndWFnZSAhPT0gJ3N0cmluZycpIHtcclxuICAgICAgY29uc29sZS5lcnJvcihgTGFuZ3VhZ2VQaXBlIGhhcyBiZWVuIGludm9rZWQgd2l0aCBhbiBpbnZhbGlkIHBhcmFtZXRlciBbJHtsYW5ndWFnZX1dYCk7XHJcbiAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgIH1cclxuICAgIHJldHVybiAnYGBgJyArIGxhbmd1YWdlICsgJ1xcbicgKyAgdmFsdWUgKyAnXFxuYGBgJztcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgUmVuZGVyZXIgfSBmcm9tICdtYXJrZWQnO1xyXG5cclxuZXhwb3J0IGNsYXNzIE1hcmtlZE9wdGlvbnMgaW1wbGVtZW50cyBtYXJrZWQuTWFya2VkT3B0aW9ucyB7XHJcbiAgLyoqXHJcbiAgICogQSBwcmVmaXggVVJMIGZvciBhbnkgcmVsYXRpdmUgbGluay5cclxuICAgKi9cclxuICBiYXNlVXJsPzogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBFbmFibGUgR0ZNIGxpbmUgYnJlYWtzLiBUaGlzIG9wdGlvbiByZXF1aXJlcyB0aGUgZ2ZtIG9wdGlvbiB0byBiZSB0cnVlLlxyXG4gICAqL1xyXG4gIGJyZWFrcz86IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIEVuYWJsZSBHaXRIdWIgZmxhdm9yZWQgbWFya2Rvd24uXHJcbiAgICovXHJcbiAgZ2ZtPzogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogSW5jbHVkZSBhbiBpZCBhdHRyaWJ1dGUgd2hlbiBlbWl0dGluZyBoZWFkaW5ncy5cclxuICAgKi9cclxuICBoZWFkZXJJZHM/OiBib29sZWFuO1xyXG5cclxuICAvKipcclxuICAgKiBTZXQgdGhlIHByZWZpeCBmb3IgaGVhZGVyIHRhZyBpZHMuXHJcbiAgICovXHJcbiAgaGVhZGVyUHJlZml4Pzogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBTZXQgdGhlIHByZWZpeCBmb3IgY29kZSBibG9jayBjbGFzc2VzLlxyXG4gICAqL1xyXG4gIGxhbmdQcmVmaXg/OiBzdHJpbmc7XHJcblxyXG4gIC8qKlxyXG4gICAqIE1hbmdsZSBhdXRvbGlua3MgKDxlbWFpbEBkb21haW4uY29tPikuXHJcbiAgICovXHJcbiAgbWFuZ2xlPzogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogQ29uZm9ybSB0byBvYnNjdXJlIHBhcnRzIG9mIG1hcmtkb3duLnBsIGFzIG11Y2ggYXMgcG9zc2libGUuIERvbid0IGZpeCBhbnkgb2YgdGhlIG9yaWdpbmFsIG1hcmtkb3duIGJ1Z3Mgb3IgcG9vciBiZWhhdmlvci5cclxuICAgKi9cclxuICBwZWRhbnRpYz86IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIFR5cGU6IG9iamVjdCBEZWZhdWx0OiBuZXcgUmVuZGVyZXIoKVxyXG4gICAqXHJcbiAgICogQW4gb2JqZWN0IGNvbnRhaW5pbmcgZnVuY3Rpb25zIHRvIHJlbmRlciB0b2tlbnMgdG8gSFRNTC5cclxuICAgKi9cclxuICByZW5kZXJlcj86IFJlbmRlcmVyO1xyXG5cclxuICAvKipcclxuICAgKiBTYW5pdGl6ZSB0aGUgb3V0cHV0LiBJZ25vcmUgYW55IEhUTUwgdGhhdCBoYXMgYmVlbiBpbnB1dC5cclxuICAgKi9cclxuICBzYW5pdGl6ZT86IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIFNob3dzIGFuIEhUTUwgZXJyb3IgbWVzc2FnZSB3aGVuIHJlbmRlcmluZyBmYWlscy5cclxuICAgKi9cclxuICBzaWxlbnQ/OiBib29sZWFuO1xyXG5cclxuICAvKipcclxuICAgKiBVc2Ugc21hcnRlciBsaXN0IGJlaGF2aW9yIHRoYW4gdGhlIG9yaWdpbmFsIG1hcmtkb3duLiBNYXkgZXZlbnR1YWxseSBiZSBkZWZhdWx0IHdpdGggdGhlIG9sZCBiZWhhdmlvciBtb3ZlZCBpbnRvIHBlZGFudGljLlxyXG4gICAqL1xyXG4gIHNtYXJ0TGlzdHM/OiBib29sZWFuO1xyXG5cclxuICAvKipcclxuICAgKiBVc2UgXCJzbWFydFwiIHR5cG9ncmFoaWMgcHVuY3R1YXRpb24gZm9yIHRoaW5ncyBsaWtlIHF1b3RlcyBhbmQgZGFzaGVzLlxyXG4gICAqL1xyXG4gIHNtYXJ0eXBhbnRzPzogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogRW5hYmxlIEdGTSB0YWJsZXMuIFRoaXMgb3B0aW9uIHJlcXVpcmVzIHRoZSBnZm0gb3B0aW9uIHRvIGJlIHRydWUuXHJcbiAgICovXHJcbiAgdGFibGVzPzogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogR2VuZXJhdGUgY2xvc2luZyBzbGFzaCBmb3Igc2VsZi1jbG9zaW5nIHRhZ3MgKDxici8+IGluc3RlYWQgb2YgPGJyPilcclxuICAgKi9cclxuICB4aHRtbD86IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIEEgZnVuY3Rpb24gdG8gaGlnaGxpZ2h0IGNvZGUgYmxvY2tzLiBUaGUgZnVuY3Rpb24gdGFrZXMgdGhyZWUgYXJndW1lbnRzOiBjb2RlLCBsYW5nLCBhbmQgY2FsbGJhY2suXHJcbiAgICovXHJcbiAgaGlnaGxpZ2h0Pyhjb2RlOiBzdHJpbmcsIGxhbmc6IHN0cmluZywgY2FsbGJhY2s/OiAoZXJyb3I6IGFueSB8IHVuZGVmaW5lZCwgY29kZTogc3RyaW5nKSA9PiB2b2lkKTogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBPcHRpb25hbGx5IHNhbml0aXplIGZvdW5kIEhUTUwgd2l0aCBhIHNhbml0aXplciBmdW5jdGlvbi5cclxuICAgKi9cclxuICBzYW5pdGl6ZXI/KGh0bWw6IHN0cmluZyk6IHN0cmluZztcclxufVxyXG4iLCJpbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcbmltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSwgT3B0aW9uYWwsIFBMQVRGT1JNX0lELCBTZWN1cml0eUNvbnRleHQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRG9tU2FuaXRpemVyIH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XHJcbmltcG9ydCB7IHBhcnNlLCBSZW5kZXJlciB9IGZyb20gJ21hcmtlZCc7XHJcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5cclxuaW1wb3J0IHsgTWFya2VkT3B0aW9ucyB9IGZyb20gJy4vbWFya2VkLW9wdGlvbnMnO1xyXG5cclxuZGVjbGFyZSB2YXIgUHJpc206IHtcclxuICBoaWdobGlnaHRBbGw6IChhc3luYzogYm9vbGVhbikgPT4gdm9pZDtcclxufTtcclxuXHJcbi8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTptYXgtbGluZS1sZW5ndGhcclxuZXhwb3J0IGNvbnN0IGVycm9yU3JjV2l0aG91dEh0dHBDbGllbnQgPSAnW25neC1tYXJrZG93bl0gV2hlbiB1c2luZyB0aGUgW3NyY10gYXR0cmlidXRlIHlvdSAqaGF2ZSB0byogcGFzcyB0aGUgYEh0dHBDbGllbnRgIGFzIGEgcGFyYW1ldGVyIG9mIHRoZSBgZm9yUm9vdGAgbWV0aG9kLiBTZWUgUkVBRE1FIGZvciBtb3JlIGluZm9ybWF0aW9uJztcclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIE1hcmtkb3duU2VydmljZSB7XHJcbiAgZ2V0IHJlbmRlcmVyKCk6IFJlbmRlcmVyIHsgcmV0dXJuIHRoaXMub3B0aW9ucy5yZW5kZXJlcjsgfVxyXG4gIHNldCByZW5kZXJlcih2YWx1ZTogbWFya2VkLlJlbmRlcmVyKSB7XHJcbiAgICB0aGlzLm9wdGlvbnMucmVuZGVyZXIgPSB2YWx1ZTtcclxuICB9XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBwbGF0Zm9ybTogT2JqZWN0LFxyXG4gICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50LFxyXG4gICAgcHJpdmF0ZSBkb21TYW5pdGl6ZXI6IERvbVNhbml0aXplcixcclxuICAgIHB1YmxpYyBvcHRpb25zOiBNYXJrZWRPcHRpb25zLFxyXG4gICkge1xyXG4gICAgaWYgKCF0aGlzLnJlbmRlcmVyKSB7XHJcbiAgICAgIHRoaXMucmVuZGVyZXIgPSBuZXcgUmVuZGVyZXIoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbXBpbGUobWFya2Rvd246IHN0cmluZywgZGVjb2RlSHRtbCA9IGZhbHNlLCBtYXJrZWRPcHRpb25zID0gdGhpcy5vcHRpb25zKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IHByZWNvbXBpbGVkID0gdGhpcy5wcmVjb21waWxlKG1hcmtkb3duKTtcclxuICAgIGNvbnN0IGNvbXBpbGVkID0gcGFyc2UoXHJcbiAgICAgIGRlY29kZUh0bWwgPyB0aGlzLmRlY29kZUh0bWwocHJlY29tcGlsZWQpIDogcHJlY29tcGlsZWQsXHJcbiAgICAgIG1hcmtlZE9wdGlvbnMpO1xyXG4gICAgcmV0dXJuIG1hcmtlZE9wdGlvbnMuc2FuaXRpemUgJiYgIW1hcmtlZE9wdGlvbnMuc2FuaXRpemVyXHJcbiAgICAgID8gdGhpcy5kb21TYW5pdGl6ZXIuc2FuaXRpemUoU2VjdXJpdHlDb250ZXh0LkhUTUwsIGNvbXBpbGVkKVxyXG4gICAgICA6IGNvbXBpbGVkO1xyXG4gIH1cclxuXHJcbiAgZ2V0U291cmNlKHNyYzogc3RyaW5nKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcclxuICAgIGlmICghdGhpcy5odHRwKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvclNyY1dpdGhvdXRIdHRwQ2xpZW50KTtcclxuICAgIH1cclxuICAgIHJldHVybiB0aGlzLmh0dHBcclxuICAgICAgLmdldChzcmMsIHsgcmVzcG9uc2VUeXBlOiAndGV4dCcgfSlcclxuICAgICAgLnBpcGUobWFwKG1hcmtkb3duID0+IHRoaXMuaGFuZGxlRXh0ZW5zaW9uKHNyYywgbWFya2Rvd24pKSk7XHJcbiAgfVxyXG5cclxuICBoaWdobGlnaHQoKSB7XHJcbiAgICBpZiAoaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5wbGF0Zm9ybSkgJiYgdHlwZW9mIFByaXNtICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgICBQcmlzbS5oaWdobGlnaHRBbGwoZmFsc2UpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBkZWNvZGVIdG1sKGh0bWw6IHN0cmluZykge1xyXG4gICAgaWYgKGlzUGxhdGZvcm1Ccm93c2VyKHRoaXMucGxhdGZvcm0pKSB7XHJcbiAgICAgIGNvbnN0IHRleHRhcmVhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndGV4dGFyZWEnKTtcclxuICAgICAgdGV4dGFyZWEuaW5uZXJIVE1MID0gaHRtbDtcclxuICAgICAgcmV0dXJuIHRleHRhcmVhLnZhbHVlO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGh0bWw7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGhhbmRsZUV4dGVuc2lvbihzcmM6IHN0cmluZywgbWFya2Rvd246IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBleHRlbnNpb24gPSBzcmNcclxuICAgICAgPyBzcmMuc3BsaXQoJy4nKS5zcGxpY2UoLTEpLmpvaW4oKVxyXG4gICAgICA6IG51bGw7XHJcbiAgICByZXR1cm4gZXh0ZW5zaW9uICE9PSAnbWQnXHJcbiAgICAgID8gJ2BgYCcgKyBleHRlbnNpb24gKyAnXFxuJyArIG1hcmtkb3duICsgJ1xcbmBgYCdcclxuICAgICAgOiBtYXJrZG93bjtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJlY29tcGlsZShtYXJrZG93bjogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGlmICghbWFya2Rvd24pIHtcclxuICAgICAgcmV0dXJuICcnO1xyXG4gICAgfVxyXG4gICAgbGV0IGluZGVudFN0YXJ0OiBudW1iZXI7XHJcbiAgICByZXR1cm4gbWFya2Rvd25cclxuICAgICAgLnNwbGl0KCdcXG4nKVxyXG4gICAgICAubWFwKGxpbmUgPT4ge1xyXG4gICAgICAgIC8vIHNldCBjdXJyZW50IGxpbmUgaWRlbnQgc3RhcnQgdG8gYmFzZSByZWZlcmVuY2UgaW5kZW50YXRpb25cclxuICAgICAgICBsZXQgbGluZUlkZW50U3RhcnQgPSBpbmRlbnRTdGFydDtcclxuICAgICAgICAvLyBmaW5kIHBvc2l0aW9uIG9mIDFzdCBub24td2hpdGVzcGFjZSBjaGFyYWN0ZXJcclxuICAgICAgICAvLyB0byBkZXRlcm1pbmUgdGhlIGN1cnJlbnQgbGluZSBpbmRlbnRhdGlvbiBzdGFydFxyXG4gICAgICAgIGlmIChsaW5lLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgIGxpbmVJZGVudFN0YXJ0ID0gaXNOYU4obGluZUlkZW50U3RhcnQpXHJcbiAgICAgICAgICAgID8gbGluZS5zZWFyY2goL1xcU3wkLylcclxuICAgICAgICAgICAgOiBNYXRoLm1pbihsaW5lLnNlYXJjaCgvXFxTfCQvKSwgbGluZUlkZW50U3RhcnQpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBrZWVwIDFzdCBub24td2hpdGVzcGFjZSBsaW5lIGluZGVudGF0aW9uXHJcbiAgICAgICAgLy8gYXMgYmFzZSByZWZlcmVuY2UgZm9yIG90aGVyIGxpbmVzXHJcbiAgICAgICAgaWYgKGlzTmFOKGluZGVudFN0YXJ0KSkge1xyXG4gICAgICAgICAgaW5kZW50U3RhcnQgPSBsaW5lSWRlbnRTdGFydDtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gcmVtb3ZlIHdoaXRlc3BhY2VzIGJlZm9yZSBjdXJyZW50IGxpbmUgaW5kZW50YXRpb25cclxuICAgICAgICByZXR1cm4gISFsaW5lSWRlbnRTdGFydFxyXG4gICAgICAgICAgPyBsaW5lLnN1YnN0cmluZyhsaW5lSWRlbnRTdGFydClcclxuICAgICAgICAgIDogbGluZTtcclxuICAgICAgfSkuam9pbignXFxuJyk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENvbXBvbmVudCwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcblxyXG5pbXBvcnQgeyBNYXJrZG93blNlcnZpY2UgfSBmcm9tICcuL21hcmtkb3duLnNlcnZpY2UnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmNvbXBvbmVudC1zZWxlY3RvclxyXG4gIHNlbGVjdG9yOiAnbWFya2Rvd24sIFttYXJrZG93bl0nLFxyXG4gIHRlbXBsYXRlOiAnPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PicsXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBNYXJrZG93bkNvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQge1xyXG4gIHByaXZhdGUgX2RhdGE6IHN0cmluZztcclxuICBwcml2YXRlIF9zcmM6IHN0cmluZztcclxuXHJcbiAgcHJpdmF0ZSBnZXQgX2lzVHJhbnNjbHVkZWQoKSB7XHJcbiAgICByZXR1cm4gIXRoaXMuX2RhdGEgJiYgIXRoaXMuX3NyYztcclxuICB9XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgZ2V0IGRhdGEoKTogc3RyaW5nIHsgcmV0dXJuIHRoaXMuX2RhdGE7IH1cclxuICBzZXQgZGF0YSh2YWx1ZTogc3RyaW5nKSB7XHJcbiAgICB0aGlzLl9kYXRhID0gdmFsdWU7XHJcbiAgICB0aGlzLnJlbmRlcih2YWx1ZSk7XHJcbiAgfVxyXG5cclxuICBASW5wdXQoKVxyXG4gIGdldCBzcmMoKTogc3RyaW5nIHsgcmV0dXJuIHRoaXMuX3NyYzsgfVxyXG4gIHNldCBzcmModmFsdWU6IHN0cmluZykge1xyXG4gICAgdGhpcy5fc3JjID0gdmFsdWU7XHJcbiAgICB0aGlzLm1hcmtkb3duU2VydmljZVxyXG4gICAgICAuZ2V0U291cmNlKHZhbHVlKVxyXG4gICAgICAuc3Vic2NyaWJlKFxyXG4gICAgICAgIG1hcmtkb3duID0+IHtcclxuICAgICAgICAgIHRoaXMucmVuZGVyKG1hcmtkb3duKTtcclxuICAgICAgICAgIHRoaXMubG9hZC5lbWl0KG1hcmtkb3duKTtcclxuICAgICAgICB9LFxyXG4gICAgICAgIGVycm9yID0+IHRoaXMuZXJyb3IuZW1pdChlcnJvciksXHJcbiAgICAgICk7XHJcbiAgfVxyXG5cclxuICBAT3V0cHV0KCkgZXJyb3IgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuICBAT3V0cHV0KCkgbG9hZCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHB1YmxpYyBlbGVtZW50OiBFbGVtZW50UmVmLFxyXG4gICAgcHVibGljIG1hcmtkb3duU2VydmljZTogTWFya2Rvd25TZXJ2aWNlLFxyXG4gICkgeyB9XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcclxuICAgIGlmICh0aGlzLl9pc1RyYW5zY2x1ZGVkKSB7XHJcbiAgICAgIHRoaXMucmVuZGVyKHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LmlubmVySFRNTCwgdHJ1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZW5kZXIobWFya2Rvd246IHN0cmluZywgZGVjb2RlSHRtbCA9IGZhbHNlKSB7XHJcbiAgICB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5pbm5lckhUTUwgPSB0aGlzLm1hcmtkb3duU2VydmljZS5jb21waWxlKG1hcmtkb3duLCBkZWNvZGVIdG1sKTtcclxuICAgIHRoaXMubWFya2Rvd25TZXJ2aWNlLmhpZ2hsaWdodCgpO1xyXG4gIH1cclxufVxyXG4iLCIvKiEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZVxyXG50aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS4gWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZVxyXG5MaWNlbnNlIGF0IGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxyXG5cclxuVEhJUyBDT0RFIElTIFBST1ZJREVEIE9OIEFOICpBUyBJUyogQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWVxyXG5LSU5ELCBFSVRIRVIgRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgV0lUSE9VVCBMSU1JVEFUSU9OIEFOWSBJTVBMSUVEXHJcbldBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBUSVRMRSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UsXHJcbk1FUkNIQU5UQUJMSVRZIE9SIE5PTi1JTkZSSU5HRU1FTlQuXHJcblxyXG5TZWUgdGhlIEFwYWNoZSBWZXJzaW9uIDIuMCBMaWNlbnNlIGZvciBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnNcclxuYW5kIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSAqL1xyXG5cclxudmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbihkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykgaWYgKGUuaW5kZXhPZihwW2ldKSA8IDApXHJcbiAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2RlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XHJcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcclxuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XHJcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19wYXJhbShwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHsgZGVjb3JhdG9yKHRhcmdldCwga2V5LCBwYXJhbUluZGV4KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSkge1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0Lm1ldGFkYXRhID09PSBcImZ1bmN0aW9uXCIpIHJldHVybiBSZWZsZWN0Lm1ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXRlcih0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcclxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUocmVzdWx0LnZhbHVlKTsgfSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxyXG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19nZW5lcmF0b3IodGhpc0FyZywgYm9keSkge1xyXG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcclxuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XHJcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xyXG4gICAgICAgIHdoaWxlIChfKSB0cnkge1xyXG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XHJcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcclxuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xyXG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xyXG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XHJcbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4cG9ydFN0YXIobSwgZXhwb3J0cykge1xyXG4gICAgZm9yICh2YXIgcCBpbiBtKSBpZiAoIWV4cG9ydHMuaGFzT3duUHJvcGVydHkocCkpIGV4cG9ydHNbcF0gPSBtW3BdO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX192YWx1ZXMobykge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdLCBpID0gMDtcclxuICAgIGlmIChtKSByZXR1cm4gbS5jYWxsKG8pO1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XHJcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcclxuICAgIGlmICghbSkgcmV0dXJuIG87XHJcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cclxuICAgIH1cclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkKCkge1xyXG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgYXIgPSBhci5jb25jYXQoX19yZWFkKGFyZ3VtZW50c1tpXSkpO1xyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdCh2KSB7XHJcbiAgICByZXR1cm4gdGhpcyBpbnN0YW5jZW9mIF9fYXdhaXQgPyAodGhpcy52ID0gdiwgdGhpcykgOiBuZXcgX19hd2FpdCh2KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNHZW5lcmF0b3IodGhpc0FyZywgX2FyZ3VtZW50cywgZ2VuZXJhdG9yKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIGcgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSksIGksIHEgPSBbXTtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpZiAoZ1tuXSkgaVtuXSA9IGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAoYSwgYikgeyBxLnB1c2goW24sIHYsIGEsIGJdKSA+IDEgfHwgcmVzdW1lKG4sIHYpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gcmVzdW1lKG4sIHYpIHsgdHJ5IHsgc3RlcChnW25dKHYpKTsgfSBjYXRjaCAoZSkgeyBzZXR0bGUocVswXVszXSwgZSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XHJcbiAgICBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7IHJlc3VtZShcIm5leHRcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiByZWplY3QodmFsdWUpIHsgcmVzdW1lKFwidGhyb3dcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcclxuICAgIHZhciBpLCBwO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiLCBmdW5jdGlvbiAoZSkgeyB0aHJvdyBlOyB9KSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpW25dID0gb1tuXSA/IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IG4gPT09IFwicmV0dXJuXCIgfSA6IGYgPyBmKHYpIDogdjsgfSA6IGY7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNWYWx1ZXMobykge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBtID0gb1tTeW1ib2wuYXN5bmNJdGVyYXRvcl0sIGk7XHJcbiAgICByZXR1cm4gbSA/IG0uY2FsbChvKSA6IChvID0gdHlwZW9mIF9fdmFsdWVzID09PSBcImZ1bmN0aW9uXCIgPyBfX3ZhbHVlcyhvKSA6IG9bU3ltYm9sLml0ZXJhdG9yXSgpLCBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaSk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaVtuXSA9IG9bbl0gJiYgZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsgdiA9IG9bbl0odiksIHNldHRsZShyZXNvbHZlLCByZWplY3QsIHYuZG9uZSwgdi52YWx1ZSk7IH0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCBkLCB2KSB7IFByb21pc2UucmVzb2x2ZSh2KS50aGVuKGZ1bmN0aW9uKHYpIHsgcmVzb2x2ZSh7IHZhbHVlOiB2LCBkb25lOiBkIH0pOyB9LCByZWplY3QpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ha2VUZW1wbGF0ZU9iamVjdChjb29rZWQsIHJhdykge1xyXG4gICAgaWYgKE9iamVjdC5kZWZpbmVQcm9wZXJ0eSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkoY29va2VkLCBcInJhd1wiLCB7IHZhbHVlOiByYXcgfSk7IH0gZWxzZSB7IGNvb2tlZC5yYXcgPSByYXc7IH1cclxuICAgIHJldHVybiBjb29rZWQ7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnRTdGFyKG1vZCkge1xyXG4gICAgaWYgKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgcmV0dXJuIG1vZDtcclxuICAgIHZhciByZXN1bHQgPSB7fTtcclxuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayBpbiBtb2QpIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChtb2QsIGspKSByZXN1bHRba10gPSBtb2Rba107XHJcbiAgICByZXN1bHQuZGVmYXVsdCA9IG1vZDtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydERlZmF1bHQobW9kKSB7XHJcbiAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IGRlZmF1bHQ6IG1vZCB9O1xyXG59XHJcbiIsImltcG9ydCB7IE5nWm9uZSwgUGlwZSwgUGlwZVRyYW5zZm9ybSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBmaXJzdCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuXHJcbmltcG9ydCB7IE1hcmtkb3duU2VydmljZSB9IGZyb20gJy4vbWFya2Rvd24uc2VydmljZSc7XHJcblxyXG5AUGlwZSh7XHJcbiAgbmFtZTogJ21hcmtkb3duJyxcclxufSlcclxuZXhwb3J0IGNsYXNzIE1hcmtkb3duUGlwZSBpbXBsZW1lbnRzIFBpcGVUcmFuc2Zvcm0ge1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgbWFya2Rvd25TZXJ2aWNlOiBNYXJrZG93blNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHpvbmU6IE5nWm9uZSxcclxuICApIHsgfVxyXG5cclxuICB0cmFuc2Zvcm0odmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJykge1xyXG4gICAgICBjb25zb2xlLmVycm9yKGBNYXJrZG93blBpcGUgaGFzIGJlZW4gaW52b2tlZCB3aXRoIGFuIGludmFsaWQgdmFsdWUgdHlwZSBbJHt2YWx1ZX1dYCk7XHJcbiAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBtYXJrZG93biA9IHRoaXMubWFya2Rvd25TZXJ2aWNlLmNvbXBpbGUodmFsdWUpO1xyXG5cclxuICAgIHRoaXMuem9uZS5vblN0YWJsZVxyXG4gICAgICAucGlwZShmaXJzdCgpKVxyXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMubWFya2Rvd25TZXJ2aWNlLmhpZ2hsaWdodCgpKTtcclxuXHJcbiAgICByZXR1cm4gbWFya2Rvd247XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IE1vZHVsZVdpdGhQcm92aWRlcnMsIE5nTW9kdWxlLCBQcm92aWRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuaW1wb3J0IHsgTGFuZ3VhZ2VQaXBlIH0gZnJvbSAnLi9sYW5ndWFnZS5waXBlJztcclxuaW1wb3J0IHsgTWFya2Rvd25Db21wb25lbnQgfSBmcm9tICcuL21hcmtkb3duLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IE1hcmtkb3duUGlwZSB9IGZyb20gJy4vbWFya2Rvd24ucGlwZSc7XHJcbmltcG9ydCB7IE1hcmtkb3duU2VydmljZSB9IGZyb20gJy4vbWFya2Rvd24uc2VydmljZSc7XHJcbmltcG9ydCB7IE1hcmtlZE9wdGlvbnMgfSBmcm9tICcuL21hcmtlZC1vcHRpb25zJztcclxuXHJcbi8vIGhhdmluZyBhIGRlcGVuZGVuY3kgb24gYEh0dHBDbGllbnRNb2R1bGVgIHdpdGhpbiBhIGxpYnJhcnlcclxuLy8gYnJlYWtzIGFsbCB0aGUgaW50ZXJjZXB0b3JzIGZyb20gdGhlIGFwcCBjb25zdW1pbmcgdGhlIGxpYnJhcnlcclxuLy8gaGVyZSwgd2UgZXhwbGljaXRlbHkgYXNrIHRoZSB1c2VyIHRvIHBhc3MgYSBwcm92aWRlciB3aXRoXHJcbi8vIHRoZWlyIG93biBpbnN0YW5jZSBvZiBgSHR0cENsaWVudE1vZHVsZWBcclxuZXhwb3J0IGludGVyZmFjZSBNYXJrZG93bk1vZHVsZUNvbmZpZyB7XHJcbiAgbG9hZGVyPzogUHJvdmlkZXI7XHJcbiAgbWFya2VkT3B0aW9ucz86IFByb3ZpZGVyO1xyXG59XHJcblxyXG5leHBvcnQgY29uc3QgaW5pdGlhbE1hcmtlZE9wdGlvbnM6IFByb3ZpZGVyID0ge1xyXG4gIHByb3ZpZGU6IE1hcmtlZE9wdGlvbnMsXHJcbiAgdXNlVmFsdWU6IHtcclxuICAgIGdmbTogdHJ1ZSxcclxuICAgIHRhYmxlczogdHJ1ZSxcclxuICAgIGJyZWFrczogZmFsc2UsXHJcbiAgICBwZWRhbnRpYzogZmFsc2UsXHJcbiAgICBzYW5pdGl6ZTogZmFsc2UsXHJcbiAgICBzbWFydExpc3RzOiB0cnVlLFxyXG4gICAgc21hcnR5cGFudHM6IGZhbHNlLFxyXG4gIH0sXHJcbn07XHJcblxyXG5jb25zdCBzaGFyZWREZWNsYXJhdGlvbnMgPSBbXHJcbiAgTGFuZ3VhZ2VQaXBlLFxyXG4gIE1hcmtkb3duQ29tcG9uZW50LFxyXG4gIE1hcmtkb3duUGlwZSxcclxuXTtcclxuXHJcbkBOZ01vZHVsZSh7XHJcbiAgZXhwb3J0czogW1xyXG4gICAgLi4uc2hhcmVkRGVjbGFyYXRpb25zLFxyXG4gIF0sXHJcbiAgZGVjbGFyYXRpb25zOiBbXHJcbiAgICAuLi5zaGFyZWREZWNsYXJhdGlvbnMsXHJcbiAgXSxcclxufSlcclxuZXhwb3J0IGNsYXNzIE1hcmtkb3duTW9kdWxlIHtcclxuICBzdGF0aWMgZm9yUm9vdChtYXJrZG93bk1vZHVsZUNvbmZpZz86IE1hcmtkb3duTW9kdWxlQ29uZmlnKTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBuZ01vZHVsZTogTWFya2Rvd25Nb2R1bGUsXHJcbiAgICAgIHByb3ZpZGVyczogW1xyXG4gICAgICAgIE1hcmtkb3duU2VydmljZSxcclxuICAgICAgICAuLi4obWFya2Rvd25Nb2R1bGVDb25maWdcclxuICAgICAgICAgID8gW1xyXG4gICAgICAgICAgICAgIG1hcmtkb3duTW9kdWxlQ29uZmlnLmxvYWRlciB8fCBbXSxcclxuICAgICAgICAgICAgICBtYXJrZG93bk1vZHVsZUNvbmZpZy5tYXJrZWRPcHRpb25zIHx8IGluaXRpYWxNYXJrZWRPcHRpb25zLFxyXG4gICAgICAgICAgICBdXHJcbiAgICAgICAgICA6IFtpbml0aWFsTWFya2VkT3B0aW9uc10pLFxyXG4gICAgICBdLFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHN0YXRpYyBmb3JDaGlsZCgpOiBNb2R1bGVXaXRoUHJvdmlkZXJzIHtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIG5nTW9kdWxlOiBNYXJrZG93bk1vZHVsZSxcclxuICAgIH07XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IFJlbmRlcmVyIH0gZnJvbSAnbWFya2VkJztcclxuXHJcbmV4cG9ydCBjbGFzcyBNYXJrZWRSZW5kZXJlciBleHRlbmRzIFJlbmRlcmVyIHsgfVxyXG4iXSwibmFtZXMiOlsiUGlwZSIsImh0dHAiLCJSZW5kZXJlciIsInBhcnNlIiwiU2VjdXJpdHlDb250ZXh0IiwibWFwIiwiaXNQbGF0Zm9ybUJyb3dzZXIiLCJJbmplY3RhYmxlIiwiSW5qZWN0IiwiUExBVEZPUk1fSUQiLCJIdHRwQ2xpZW50IiwiT3B0aW9uYWwiLCJEb21TYW5pdGl6ZXIiLCJFdmVudEVtaXR0ZXIiLCJDb21wb25lbnQiLCJFbGVtZW50UmVmIiwiSW5wdXQiLCJPdXRwdXQiLCJmaXJzdCIsIk5nWm9uZSIsIk5nTW9kdWxlIiwidHNsaWJfMS5fX2V4dGVuZHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTs7Ozs7Ozs7UUFPRSxnQ0FBUzs7Ozs7WUFBVCxVQUFVLEtBQWEsRUFBRSxRQUFnQjtnQkFDdkMsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUU7b0JBQzdCLE9BQU8sQ0FBQyxLQUFLLENBQUMsK0RBQTZELEtBQUssTUFBRyxDQUFDLENBQUM7b0JBQ3JGLE9BQU8sS0FBSyxDQUFDO2lCQUNkO2dCQUNELElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxFQUFFO29CQUNoQyxPQUFPLENBQUMsS0FBSyxDQUFDLDhEQUE0RCxRQUFRLE1BQUcsQ0FBQyxDQUFDO29CQUN2RixPQUFPLEtBQUssQ0FBQztpQkFDZDtnQkFDRCxPQUFPLEtBQUssR0FBRyxRQUFRLEdBQUcsSUFBSSxHQUFJLEtBQUssR0FBRyxPQUFPLENBQUM7YUFDbkQ7O29CQWZGQSxTQUFJLFNBQUM7d0JBQ0osSUFBSSxFQUFFLFVBQVU7cUJBQ2pCOzsyQkFKRDs7Ozs7OztBQ0VBLFFBQUE7Ozs0QkFGQTtRQXlGQzs7Ozs7O0FDekZEO0FBZUEsUUFBYSx5QkFBeUIsR0FBRywySkFBMkosQ0FBQzs7UUFTbk0seUJBQytCLFFBQWdCLEVBQ3pCQyxPQUFnQixFQUM1QixjQUNEO1lBSHNCLGFBQVEsR0FBUixRQUFRLENBQVE7WUFDekIsU0FBSSxHQUFKQSxPQUFJLENBQVk7WUFDNUIsaUJBQVksR0FBWixZQUFZO1lBQ2IsWUFBTyxHQUFQLE9BQU87WUFFZCxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRTtnQkFDbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJQyxlQUFRLEVBQUUsQ0FBQzthQUNoQztTQUNGO1FBZEQsc0JBQUkscUNBQVE7OztnQkFBWixjQUEyQixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUU7Ozs7Z0JBQzFELFVBQWEsS0FBc0I7Z0JBQ2pDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQzthQUMvQjs7O1dBSHlEOzs7Ozs7O1FBZ0IxRCxpQ0FBTzs7Ozs7O1lBQVAsVUFBUSxRQUFnQixFQUFFLFVBQWtCLEVBQUUsYUFBNEI7Z0JBQWhELDJCQUFBO29CQUFBLGtCQUFrQjs7Z0JBQUUsOEJBQUE7b0JBQUEsZ0JBQWdCLElBQUksQ0FBQyxPQUFPOzs7Z0JBQ3hFLElBQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7O2dCQUM5QyxJQUFNLFFBQVEsR0FBR0MsWUFBSyxDQUNwQixVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsR0FBRyxXQUFXLEVBQ3ZELGFBQWEsQ0FBQyxDQUFDO2dCQUNqQixPQUFPLGFBQWEsQ0FBQyxRQUFRLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUztzQkFDckQsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUNDLG9CQUFlLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQztzQkFDMUQsUUFBUSxDQUFDO2FBQ2Q7Ozs7O1FBRUQsbUNBQVM7Ozs7WUFBVCxVQUFVLEdBQVc7Z0JBQXJCLGlCQU9DO2dCQU5DLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFO29CQUNkLE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztpQkFDNUM7Z0JBQ0QsT0FBTyxJQUFJLENBQUMsSUFBSTtxQkFDYixHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxDQUFDO3FC