@greg-md/ng-facebook
Version:
Using Facebook SDK with Angular.
649 lines (634 loc) • 72.8 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('rxjs'), require('rxjs/operators')) :
typeof define === 'function' && define.amd ? define('@greg-md/ng-facebook', ['exports', '@angular/core', '@angular/common', 'rxjs', 'rxjs/operators'], factory) :
(factory((global['greg-md'] = global['greg-md'] || {}, global['greg-md']['ng-facebook'] = {}),global.ng.core,global.ng.common,global.rxjs,global.rxjs.operators));
}(this, (function (exports,i0,common,rxjs,operators) { 'use strict';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var /** @type {?} */ FACEBOOK_DEFAULTS = {
xfbml: false,
version: 'v3.0'
};
var FacebookService = (function () {
function FacebookService(ngZone, platformId) {
this.ngZone = ngZone;
this.platformId = platformId;
this.sdk = new rxjs.ReplaySubject(1);
}
/**
* @param {?=} locale
* @return {?}
*/
FacebookService.prototype.load = /**
* @param {?=} locale
* @return {?}
*/
function (locale) {
var _this = this;
if (locale === void 0) {
locale = 'en_US';
}
return rxjs.Observable.create(function (subscriber) {
if (common.isPlatformServer(_this.platformId)) {
return;
}
_this.ngZone.runOutsideAngular(function () {
delete window.FB;
var /** @type {?} */ jsSdk, /** @type {?} */ fbRoot;
if (jsSdk = document.getElementById('facebook-jssdk')) {
jsSdk.parentNode.removeChild(jsSdk);
}
if (fbRoot = document.getElementById('fb-root')) {
fbRoot.parentNode.removeChild(fbRoot);
}
var /** @type {?} */ script = document.createElement('script');
script.id = 'facebook-jssdk';
script.src = '//connect.facebook.net/' + (locale || 'en_US') + '/sdk.js';
script.onload = function () {
_this.ngZone.run(function () {
subscriber.next(FB);
subscriber.complete();
});
};
script.onerror = function () {
_this.ngZone.run(function () {
subscriber.error('Facebook SDK could not be loaded.');
subscriber.complete();
});
};
document.head.appendChild(script);
});
}).pipe(operators.map(function (sdk) {
_this.sdk.next(sdk);
return sdk;
}));
};
/**
* @param {?=} params
* @param {?=} locale
* @return {?}
*/
FacebookService.prototype.init = /**
* @param {?=} params
* @param {?=} locale
* @return {?}
*/
function (params, locale) {
var _this = this;
if (params === void 0) {
params = {};
}
if (locale === void 0) {
locale = 'en_US';
}
return this.load(locale).pipe(operators.tap(function (sdk) {
params = Object.assign({}, FACEBOOK_DEFAULTS, params);
sdk.init(params);
_this.reloadRenderedElements().subscribe();
}));
};
/**
* @param {?=} options
* @return {?}
*/
FacebookService.prototype.login = /**
* @param {?=} options
* @return {?}
*/
function (options) {
var _this = this;
return rxjs.Observable.create(function (subscriber) {
_this.sdk.subscribe(function (sdk) {
_this.ngZone.runOutsideAngular(function () {
sdk.login(function (response) {
_this.ngZone.run(function () {
if (response.authResponse) {
subscriber.next(response.authResponse);
}
else {
subscriber.error(response);
}
subscriber.complete();
});
}, options);
});
});
});
};
/**
* @param {?} path
* @param {?=} method
* @param {?=} params
* @return {?}
*/
FacebookService.prototype.api = /**
* @param {?} path
* @param {?=} method
* @param {?=} params
* @return {?}
*/
function (path, method, params) {
var _this = this;
return rxjs.Observable.create(function (subscriber) {
_this.sdk.subscribe(function (sdk) {
_this.ngZone.runOutsideAngular(function () {
sdk.api(path, method, params, function (response) {
_this.ngZone.run(function () {
if (response && !response.error) {
subscriber.next(response);
}
else {
subscriber.error(response ? response.error : null);
}
subscriber.complete();
});
});
});
});
});
};
/**
* @param {?} element
* @return {?}
*/
FacebookService.prototype.parse = /**
* @param {?} element
* @return {?}
*/
function (element) {
var _this = this;
return rxjs.Observable.create(function (subscriber) {
_this.sdk.subscribe(function (sdk) {
_this.ngZone.runOutsideAngular(function () {
sdk.XFBML.parse(element, function () {
_this.ngZone.run(function () {
subscriber.next(element);
subscriber.complete();
});
});
});
});
});
};
/**
* @return {?}
*/
FacebookService.prototype.reloadRenderedElements = /**
* @return {?}
*/
function () {
var _this = this;
return rxjs.Observable.create(function (subscriber) {
_this.sdk.subscribe(function (sdk) {
var /** @type {?} */ elements = document.querySelectorAll('[fb-xfbml-state="rendered"]');
var /** @type {?} */ processing = elements.length;
Array.from(elements).forEach(function (node) {
_this.ngZone.runOutsideAngular(function () {
sdk.XFBML.parse(node.parentElement, function () {
_this.ngZone.run(function () {
--processing;
subscriber.next(node.parentElement);
if (processing <= 0) {
subscriber.complete();
}
});
});
});
});
});
});
};
FacebookService.decorators = [
{ type: i0.Injectable, args: [{
providedIn: 'root'
},] },
];
/** @nocollapse */
FacebookService.ctorParameters = function () {
return [
{ type: i0.NgZone, },
{ type: undefined, decorators: [{ type: i0.Inject, args: [i0.PLATFORM_ID,] },] },
];
};
/** @nocollapse */ FacebookService.ngInjectableDef = i0.defineInjectable({ factory: function FacebookService_Factory() { return new FacebookService(i0.inject(i0.NgZone), i0.inject(i0.PLATFORM_ID)); }, token: FacebookService, providedIn: "root" });
return FacebookService;
}());
/*! *****************************************************************************
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 = 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]; };
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @param {?} element
* @return {?}
*/
function offset(element) {
// Support: IE <=11 only
// Running getBoundingClientRect on a
// disconnected node in IE throws an error
if (!element || !element.getClientRects().length) {
return { top: 0, left: 0 };
}
var /** @type {?} */ docElem, /** @type {?} */ rect, /** @type {?} */ doc;
rect = element.getBoundingClientRect();
// Make sure element is not hidden (display: none)
if (rect.width || rect.height) {
doc = element.ownerDocument;
docElem = doc.documentElement;
return {
top: rect.top + window.pageYOffset - docElem.clientTop,
left: rect.left + window.pageXOffset - docElem.clientLeft
};
}
// Return zeros for disconnected and hidden elements (gh-2310)
return rect;
}
/**
* @param {?} element
* @param {?=} settings
* @return {?}
*/
function aboveTheTop(element, settings) {
if (settings === void 0) {
settings = {};
}
if (!element) {
return false;
}
var /** @type {?} */ fold;
var /** @type {?} */ container = settings.container || window, /** @type {?} */ threshold = settings.threshold || 0;
if (container instanceof HTMLElement) {
fold = offset(container).top;
}
else {
fold = window.scrollY;
}
return fold >= (offset(element).top + threshold + element.offsetHeight);
}
/**
* @param {?} element
* @param {?=} settings
* @return {?}
*/
function rightOfFold(element, settings) {
if (settings === void 0) {
settings = {};
}
if (!element) {
return false;
}
var /** @type {?} */ fold;
var /** @type {?} */ container = settings.container || window, /** @type {?} */ threshold = settings.threshold || 0;
if (container instanceof HTMLElement) {
fold = offset(container).left + container.offsetWidth;
}
else {
fold = window.innerWidth + window.scrollX;
}
return fold <= offset(element).left - threshold;
}
/**
* @param {?} element
* @param {?=} settings
* @return {?}
*/
function belowTheFold(element, settings) {
if (settings === void 0) {
settings = {};
}
if (!element) {
return false;
}
var /** @type {?} */ fold;
var /** @type {?} */ container = settings.container || window, /** @type {?} */ threshold = settings.threshold || 0;
if (container instanceof HTMLElement) {
fold = offset(container).top + container.offsetHeight;
}
else {
fold = window.innerHeight + window.scrollY;
}
return fold <= offset(element).top - threshold;
}
/**
* @param {?} element
* @param {?=} settings
* @return {?}
*/
function leftOfBegin(element, settings) {
if (settings === void 0) {
settings = {};
}
if (!element) {
return false;
}
var /** @type {?} */ fold;
var /** @type {?} */ container = settings.container || window, /** @type {?} */ threshold = settings.threshold || 0;
if (container instanceof HTMLElement) {
fold = offset(container).left;
}
else {
fold = window.scrollX;
}
return fold >= offset(element).left + threshold + element.offsetWidth;
}
/**
* @param {?} element
* @param {?=} settings
* @return {?}
*/
function inViewport(element, settings) {
if (settings === void 0) {
settings = {};
}
return !belowTheFold(element, settings)
&& !aboveTheTop(element, settings)
&& !leftOfBegin(element, settings)
&& !rightOfFold(element, settings);
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var /** @type {?} */ FB_PARSE_LAZY_LOAD = new i0.InjectionToken('fb_parse_lazy_load');
var FacebookParseDirective = (function () {
function FacebookParseDirective(elementRef, facebook, renderer, platformId, threshold) {
this.elementRef = elementRef;
this.facebook = facebook;
this.renderer = renderer;
this.platformId = platformId;
this.threshold = threshold;
}
Object.defineProperty(FacebookParseDirective.prototype, "lazyLoad", {
set: /**
* @param {?} threshold
* @return {?}
*/ function (threshold) {
this.threshold = threshold;
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
FacebookParseDirective.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
if (this.threshold === null) {
this.load();
}
else {
this.initListeners();
this.tryLoading();
}
};
/**
* @return {?}
*/
FacebookParseDirective.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.unloadListeners();
};
/**
* @return {?}
*/
FacebookParseDirective.prototype.initListeners = /**
* @return {?}
*/
function () {
var _this = this;
this.scrollUnload = this.renderer.listen('window', 'scroll', function () {
_this.tryLoading();
});
this.resizeUnload = this.renderer.listen('window', 'resize', function () {
_this.tryLoading();
});
};
/**
* @return {?}
*/
FacebookParseDirective.prototype.tryLoading = /**
* @return {?}
*/
function () {
if (common.isPlatformBrowser(this.platformId) && inViewport(this.elementRef.nativeElement, {
threshold: this.threshold,
container: this.container
})) {
this.load();
this.unloadListeners();
}
};
/**
* @return {?}
*/
FacebookParseDirective.prototype.load = /**
* @return {?}
*/
function () {
this.facebook.parse(this.elementRef.nativeElement).subscribe();
};
/**
* @return {?}
*/
FacebookParseDirective.prototype.unloadListeners = /**
* @return {?}
*/
function () {
if (this.scrollUnload) {
this.scrollUnload();
}
if (this.resizeUnload) {
this.resizeUnload();
}
};
FacebookParseDirective.decorators = [
{ type: i0.Directive, args: [{
selector: '[fbParse]',
},] },
];
/** @nocollapse */
FacebookParseDirective.ctorParameters = function () {
return [
{ type: i0.ElementRef, },
{ type: FacebookService, },
{ type: i0.Renderer2, },
{ type: Object, decorators: [{ type: i0.Inject, args: [i0.PLATFORM_ID,] },] },
{ type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [FB_PARSE_LAZY_LOAD,] },] },
];
};
FacebookParseDirective.propDecorators = {
"lazyLoad": [{ type: i0.Input },],
"container": [{ type: i0.Input },],
};
return FacebookParseDirective;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var FacebookLikeComponent = (function (_super) {
__extends(FacebookLikeComponent, _super);
function FacebookLikeComponent(elementRef, facebook, renderer, platformId, threshold) {
var _this = _super.call(this, elementRef, facebook, renderer, platformId, threshold) || this;
_this.action = 'like';
_this.colorscheme = 'light';
_this.kidDirectedSite = false;
_this.layout = 'standard';
_this.share = false;
_this.showFaces = false;
_this.size = 'small';
return _this;
}
FacebookLikeComponent.decorators = [
{ type: i0.Component, args: [{
selector: 'fb-like',
styles: [],
template: "\n <div class=\"fb-like\"\n [attr.data-action]=\"action\"\n [attr.data-colorscheme]=\"colorscheme\"\n [attr.data-href]=\"href\"\n [attr.data-kid-directed-site]=\"kidDirectedSite\"\n [attr.data-layout]=\"layout\"\n [attr.data-ref]=\"ref\"\n [attr.data-share]=\"share\"\n [attr.data-show-faces]=\"showFaces\"\n [attr.data-size]=\"size\"\n [attr.data-width]=\"width\"\n >\n <ng-content></ng-content>\n </div>\n ",
changeDetection: i0.ChangeDetectionStrategy.OnPush,
},] },
];
/** @nocollapse */
FacebookLikeComponent.ctorParameters = function () {
return [
{ type: i0.ElementRef, },
{ type: FacebookService, },
{ type: i0.Renderer2, },
{ type: Object, decorators: [{ type: i0.Inject, args: [i0.PLATFORM_ID,] },] },
{ type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [FB_PARSE_LAZY_LOAD,] },] },
];
};
FacebookLikeComponent.propDecorators = {
"action": [{ type: i0.Input },],
"colorscheme": [{ type: i0.Input },],
"href": [{ type: i0.Input },],
"kidDirectedSite": [{ type: i0.Input },],
"layout": [{ type: i0.Input },],
"ref": [{ type: i0.Input },],
"share": [{ type: i0.Input },],
"showFaces": [{ type: i0.Input },],
"size": [{ type: i0.Input },],
"width": [{ type: i0.Input },],
};
return FacebookLikeComponent;
}(FacebookParseDirective));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var FacebookPageComponent = (function (_super) {
__extends(FacebookPageComponent, _super);
function FacebookPageComponent(elementRef, facebook, renderer, platformId, threshold) {
var _this = _super.call(this, elementRef, facebook, renderer, platformId, threshold) || this;
_this.width = 340;
_this.height = 500;
_this.tabs = 'timeline';
_this.hideCover = false;
_this.showFacepile = true;
_this.hideCta = false;
_this.smallHeader = false;
_this.adaptContainerWidth = true;
return _this;
}
FacebookPageComponent.decorators = [
{ type: i0.Component, args: [{
selector: 'fb-page',
styles: [],
template: "\n <div class=\"fb-page\"\n [attr.data-href]=\"href\"\n [attr.data-width]=\"width\"\n [attr.data-height]=\"height\"\n [attr.data-tabs]=\"tabs\"\n [attr.data-hide-cover]=\"hideCover\"\n [attr.data-show-facepile]=\"showFacepile\"\n [attr.data-hide-cta]=\"hideCta\"\n [attr.data-small-header]=\"smallHeader\"\n [attr.data-adapt-container-width]=\"adaptContainerWidth\"\n >\n <blockquote [attr.cite]=\"href\" class=\"fb-xfbml-parse-ignore\">\n <a [href]=\"href\">\n <ng-content></ng-content>\n </a>\n </blockquote>\n </div>\n ",
changeDetection: i0.ChangeDetectionStrategy.OnPush,
},] },
];
/** @nocollapse */
FacebookPageComponent.ctorParameters = function () {
return [
{ type: i0.ElementRef, },
{ type: FacebookService, },
{ type: i0.Renderer2, },
{ type: Object, decorators: [{ type: i0.Inject, args: [i0.PLATFORM_ID,] },] },
{ type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [FB_PARSE_LAZY_LOAD,] },] },
];
};
FacebookPageComponent.propDecorators = {
"href": [{ type: i0.Input },],
"width": [{ type: i0.Input },],
"height": [{ type: i0.Input },],
"tabs": [{ type: i0.Input },],
"hideCover": [{ type: i0.Input },],
"showFacepile": [{ type: i0.Input },],
"hideCta": [{ type: i0.Input },],
"smallHeader": [{ type: i0.Input },],
"adaptContainerWidth": [{ type: i0.Input },],
};
return FacebookPageComponent;
}(FacebookParseDirective));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var FacebookModule = (function () {
function FacebookModule() {
}
FacebookModule.decorators = [
{ type: i0.NgModule, args: [{
imports: [
common.CommonModule,
],
declarations: [
FacebookParseDirective,
FacebookPageComponent,
FacebookLikeComponent,
],
exports: [
FacebookParseDirective,
FacebookPageComponent,
FacebookLikeComponent,
],
},] },
];
return FacebookModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
exports.FACEBOOK_DEFAULTS = FACEBOOK_DEFAULTS;
exports.FacebookService = FacebookService;
exports.FacebookLikeComponent = FacebookLikeComponent;
exports.FacebookPageComponent = FacebookPageComponent;
exports.FB_PARSE_LAZY_LOAD = FB_PARSE_LAZY_LOAD;
exports.FacebookParseDirective = FacebookParseDirective;
exports.FacebookModule = FacebookModule;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JlZy1tZC1uZy1mYWNlYm9vay51bWQuanMubWFwIiwic291cmNlcyI6WyJuZzovL0BncmVnLW1kL25nLWZhY2Vib29rL2xpYi9mYWNlYm9vay5zZXJ2aWNlLnRzIixudWxsLCJuZzovL0BncmVnLW1kL25nLWZhY2Vib29rL2xpYi9kb20udHMiLCJuZzovL0BncmVnLW1kL25nLWZhY2Vib29rL2xpYi9wYXJzZS5kaXJlY3RpdmUudHMiLCJuZzovL0BncmVnLW1kL25nLWZhY2Vib29rL2xpYi9saWtlLmNvbXBvbmVudC50cyIsIm5nOi8vQGdyZWctbWQvbmctZmFjZWJvb2svbGliL3BhZ2UuY29tcG9uZW50LnRzIiwibmc6Ly9AZ3JlZy1tZC9uZy1mYWNlYm9vay9saWIvZmFjZWJvb2subW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSwgTmdab25lLCBQTEFURk9STV9JRCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaXNQbGF0Zm9ybVNlcnZlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBSZXBsYXlTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YXAsIG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuZXhwb3J0IGludGVyZmFjZSBGYWNlYm9va0luaXRQYXJhbXMge1xuICBhcHBJZD86IHN0cmluZztcbiAgc3RhdHVzPzogYm9vbGVhbjtcbiAgeGZibWw/OiBib29sZWFuO1xuICB2ZXJzaW9uPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZhY2Vib29rQXV0aCB7XG4gIGFjY2Vzc1Rva2VuOiBzdHJpbmc7XG4gIGV4cGlyZXNJbjogbnVtYmVyO1xuICBzaWduZWRSZXF1ZXN0OiBzdHJpbmc7XG4gIHVzZXJJRDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZhY2Vib29rTG9naW5SZXNwb25zZSB7XG4gIHN0YXR1czogc3RyaW5nO1xuICBhdXRoUmVzcG9uc2U6IEZhY2Vib29rQXV0aDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGYWNlYm9va0xvZ2luT3B0aW9ucyB7XG4gIGF1dGhfdHlwZT86ICdyZXJlcXVlc3QnO1xuICBzY29wZT86IHN0cmluZztcbiAgcmV0dXJuX3Njb3Blcz86IGJvb2xlYW47XG4gIGVuYWJsZV9wcm9maWxlX3NlbGVjdG9yPzogYm9vbGVhbjtcbiAgcHJvZmlsZV9zZWxlY3Rvcl9pZHM/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmFjZWJvb2tBcGlFcnJvciB7XG4gIG1lc3NhZ2U6IHN0cmluZztcbn1cblxuZXhwb3J0IGNvbnN0IGVudW0gRmFjZWJvb2tBcGlNZXRob2Qge1xuICBHZXQgPSAnZ2V0JyxcbiAgUG9zdCA9ICdwb3N0JyxcbiAgRGVsZXRlID0gJ2RlbGV0ZScsXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmFjZWJvb2tBcGlQYXJhbXMge1xuICBbcHJvcE5hbWU6IHN0cmluZ106IGFueTtcbn1cblxuZXhwb3J0IHR5cGUgRmFjZWJvb2tBcGlDYWxsYmFjayA9IChyZXNwb25zZT86IHtcbiAgICBlcnJvcj86IEZhY2Vib29rQXBpRXJyb3I7XG4gICAgW3Byb3BOYW1lOiBzdHJpbmddOiBhbnk7XG4gIH0pID0+IHZvaWQ7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmFjZWJvb2sge1xuICBYRkJNTDoge1xuICAgIHBhcnNlOiAoZWxlbWVudDogSFRNTEVsZW1lbnQsIGNiPzogKCkgPT4gdm9pZCkgPT4gdm9pZDtcbiAgfTtcblxuICBpbml0OiAocGFyYW1zOiBGYWNlYm9va0luaXRQYXJhbXMpID0+IHZvaWQ7XG5cbiAgbG9naW46IChjYWxsYmFjaz86IChyZXNwb25zZTogRmFjZWJvb2tMb2dpblJlc3BvbnNlKSA9PiB2b2lkLCBvcHRpb25zPzogRmFjZWJvb2tMb2dpbk9wdGlvbnMpID0+IHZvaWQ7XG5cbiAgYXBpOiAoXG4gICAgcGF0aDogc3RyaW5nLFxuICAgIG1ldGhvZD86IEZhY2Vib29rQXBpTWV0aG9kIHwgRmFjZWJvb2tBcGlQYXJhbXMgfCBGYWNlYm9va0FwaUNhbGxiYWNrLFxuICAgIHBhcmFtcz86IEZhY2Vib29rQXBpUGFyYW1zIHwgRmFjZWJvb2tBcGlDYWxsYmFjayxcbiAgICBjYWxsYmFjaz86IEZhY2Vib29rQXBpQ2FsbGJhY2tcbiAgKSA9PiB2b2lkO1xufVxuXG5leHBvcnQgY29uc3QgRkFDRUJPT0tfREVGQVVMVFM6IEZhY2Vib29rSW5pdFBhcmFtcyA9IHtcbiAgeGZibWw6IGZhbHNlLFxuICB2ZXJzaW9uOiAndjMuMCdcbn07XG5cbmRlY2xhcmUgY29uc3QgRkI6IEZhY2Vib29rO1xuXG5kZWNsYXJlIGNvbnN0IHdpbmRvdzoge1xuICBGQjogRmFjZWJvb2s7XG59O1xuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBGYWNlYm9va1NlcnZpY2Uge1xuICBzZGsgPSBuZXcgUmVwbGF5U3ViamVjdDxGYWNlYm9vaz4oMSk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSxcbiAgICBASW5qZWN0KFBMQVRGT1JNX0lEKSBwcml2YXRlIHBsYXRmb3JtSWQ6IHN0cmluZyxcbiAgKSB7XG4gIH1cblxuICBsb2FkKGxvY2FsZTogc3RyaW5nID0gJ2VuX1VTJyk6IE9ic2VydmFibGU8RmFjZWJvb2s+IHtcbiAgICByZXR1cm4gT2JzZXJ2YWJsZS5jcmVhdGUoc3Vic2NyaWJlciA9PiB7XG4gICAgICBpZiAoaXNQbGF0Zm9ybVNlcnZlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgICBkZWxldGUgd2luZG93LkZCO1xuXG4gICAgICAgIGxldCBqc1NkazogSFRNTEVsZW1lbnQsIGZiUm9vdDogSFRNTEVsZW1lbnQ7XG5cbiAgICAgICAgaWYgKGpzU2RrID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZhY2Vib29rLWpzc2RrJykpIHtcbiAgICAgICAgICBqc1Nkay5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGpzU2RrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmYlJvb3QgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmItcm9vdCcpKSB7XG4gICAgICAgICAgZmJSb290LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZmJSb290KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuXG4gICAgICAgIHNjcmlwdC5pZCA9ICdmYWNlYm9vay1qc3Nkayc7XG5cbiAgICAgICAgc2NyaXB0LnNyYyA9ICcvL2Nvbm5lY3QuZmFjZWJvb2submV0LycgKyAobG9jYWxlIHx8ICdlbl9VUycpICsgJy9zZGsuanMnO1xuXG4gICAgICAgIHNjcmlwdC5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgIHN1YnNjcmliZXIubmV4dChGQik7XG5cbiAgICAgICAgICAgIHN1YnNjcmliZXIuY29tcGxldGUoKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBzY3JpcHQub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgc3Vic2NyaWJlci5lcnJvcignRmFjZWJvb2sgU0RLIGNvdWxkIG5vdCBiZSBsb2FkZWQuJyk7XG5cbiAgICAgICAgICAgIHN1YnNjcmliZXIuY29tcGxldGUoKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHNjcmlwdCk7XG4gICAgICB9KTtcbiAgICB9KS5waXBlKG1hcCgoc2RrOiBGYWNlYm9vaykgPT4ge1xuICAgICAgdGhpcy5zZGsubmV4dChzZGspO1xuXG4gICAgICByZXR1cm4gc2RrO1xuICAgIH0pKTtcbiAgfVxuXG4gIGluaXQocGFyYW1zOiBGYWNlYm9va0luaXRQYXJhbXMgPSB7fSwgbG9jYWxlOiBzdHJpbmcgPSAnZW5fVVMnKSB7XG4gICAgcmV0dXJuIHRoaXMubG9hZChsb2NhbGUpLnBpcGU8RmFjZWJvb2s+KHRhcDxGYWNlYm9vaz4oc2RrID0+IHtcbiAgICAgIHBhcmFtcyA9IE9iamVjdC5hc3NpZ24oe30sIEZBQ0VCT09LX0RFRkFVTFRTLCBwYXJhbXMpO1xuXG4gICAgICBzZGsuaW5pdChwYXJhbXMpO1xuXG4gICAgICB0aGlzLnJlbG9hZFJlbmRlcmVkRWxlbWVudHMoKS5zdWJzY3JpYmUoKTtcbiAgICB9KSk7XG4gIH1cblxuICBsb2dpbihvcHRpb25zPzogRmFjZWJvb2tMb2dpbk9wdGlvbnMpOiBPYnNlcnZhYmxlPEZhY2Vib29rQXV0aD4ge1xuICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZShzdWJzY3JpYmVyID0+IHtcbiAgICAgIHRoaXMuc2RrLnN1YnNjcmliZShzZGsgPT4ge1xuICAgICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgc2RrLmxvZ2luKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChyZXNwb25zZS5hdXRoUmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLm5leHQocmVzcG9uc2UuYXV0aFJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLmVycm9yKHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHN1YnNjcmliZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sIG9wdGlvbnMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgYXBpKHBhdGg6IHN0cmluZywgbWV0aG9kPzogRmFjZWJvb2tBcGlNZXRob2QgfCBGYWNlYm9va0FwaVBhcmFtcywgcGFyYW1zPzogRmFjZWJvb2tBcGlQYXJhbXMpOiBPYnNlcnZhYmxlPE9iamVjdD4ge1xuICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZShzdWJzY3JpYmVyID0+IHtcbiAgICAgIHRoaXMuc2RrLnN1YnNjcmliZShzZGsgPT4ge1xuICAgICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgc2RrLmFwaShwYXRoLCBtZXRob2QsIHBhcmFtcywgcmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlICYmICFyZXNwb25zZS5lcnJvcikge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIubmV4dChyZXNwb25zZSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5lcnJvcihyZXNwb25zZSA/IHJlc3BvbnNlLmVycm9yIDogbnVsbCk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBzdWJzY3JpYmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHBhcnNlKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogT2JzZXJ2YWJsZTxIVE1MRWxlbWVudD4ge1xuICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZShzdWJzY3JpYmVyID0+IHtcbiAgICAgIHRoaXMuc2RrLnN1YnNjcmliZShzZGsgPT4ge1xuICAgICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgc2RrLlhGQk1MLnBhcnNlKGVsZW1lbnQsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICAgIHN1YnNjcmliZXIubmV4dChlbGVtZW50KTtcblxuICAgICAgICAgICAgICBzdWJzY3JpYmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHJlbG9hZFJlbmRlcmVkRWxlbWVudHMoKTogT2JzZXJ2YWJsZTxIVE1MRWxlbWVudD4ge1xuICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZShzdWJzY3JpYmVyID0+IHtcbiAgICAgIHRoaXMuc2RrLnN1YnNjcmliZShzZGsgPT4ge1xuICAgICAgICBjb25zdCBlbGVtZW50cyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ1tmYi14ZmJtbC1zdGF0ZT1cInJlbmRlcmVkXCJdJyk7XG5cbiAgICAgICAgbGV0IHByb2Nlc3NpbmcgPSBlbGVtZW50cy5sZW5ndGg7XG5cbiAgICAgICAgQXJyYXkuZnJvbShlbGVtZW50cykuZm9yRWFjaChub2RlID0+IHtcbiAgICAgICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICBzZGsuWEZCTUwucGFyc2Uobm9kZS5wYXJlbnRFbGVtZW50LCAoKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICAgICAgLS1wcm9jZXNzaW5nO1xuXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5uZXh0KG5vZGUucGFyZW50RWxlbWVudCk7XG5cbiAgICAgICAgICAgICAgICBpZiAocHJvY2Vzc2luZyA8PSAwKSB7XG4gICAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG59XG4iLCIvKiEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZVxyXG50aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS4gWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZVxyXG5MaWNlbnNlIGF0IGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxyXG5cclxuVEhJUyBDT0RFIElTIFBST1ZJREVEIE9OIEFOICpBUyBJUyogQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWVxyXG5LSU5ELCBFSVRIRVIgRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgV0lUSE9VVCBMSU1JVEFUSU9OIEFOWSBJTVBMSUVEXHJcbldBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBUSVRMRSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UsXHJcbk1FUkNIQU5UQUJMSVRZIE9SIE5PTi1JTkZSSU5HRU1FTlQuXHJcblxyXG5TZWUgdGhlIEFwYWNoZSBWZXJzaW9uIDIuMCBMaWNlbnNlIGZvciBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnNcclxuYW5kIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSAqL1xyXG5cclxudmFyIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbn1cclxuXHJcbmV4cG9ydCB2YXIgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgIHMgPSBhcmd1bWVudHNbaV07XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgIH1cclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHtcclxuICAgIHZhciB0ID0ge307XHJcbiAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcclxuICAgICAgICB0W3BdID0gc1twXTtcclxuICAgIGlmIChzICE9IG51bGwgJiYgdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPT09IFwiZnVuY3Rpb25cIilcclxuICAgICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMClcclxuICAgICAgICAgICAgdFtwW2ldXSA9IHNbcFtpXV07XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcclxuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xyXG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcclxuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3BhcmFtKHBhcmFtSW5kZXgsIGRlY29yYXRvcikge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkgeyBkZWNvcmF0b3IodGFyZ2V0LCBrZXksIHBhcmFtSW5kZXgpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIFJlZmxlY3QubWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xyXG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XHJcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZShyZXN1bHQudmFsdWUpOyB9KS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XHJcbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2dlbmVyYXRvcih0aGlzQXJnLCBib2R5KSB7XHJcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xyXG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcclxuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XHJcbiAgICAgICAgd2hpbGUgKF8pIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcclxuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xyXG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XHJcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcclxuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cclxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXhwb3J0U3RhcihtLCBleHBvcnRzKSB7XHJcbiAgICBmb3IgKHZhciBwIGluIG0pIGlmICghZXhwb3J0cy5oYXNPd25Qcm9wZXJ0eShwKSkgZXhwb3J0c1twXSA9IG1bcF07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3ZhbHVlcyhvKSB7XHJcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl0sIGkgPSAwO1xyXG4gICAgaWYgKG0pIHJldHVybiBtLmNhbGwobyk7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkgbyA9IHZvaWQgMDtcclxuICAgICAgICAgICAgcmV0dXJuIHsgdmFsdWU6IG8gJiYgb1tpKytdLCBkb25lOiAhbyB9O1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3JlYWQobywgbikge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xyXG4gICAgaWYgKCFtKSByZXR1cm4gbztcclxuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcclxuICAgIH1cclxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxyXG4gICAgZmluYWxseSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWQoKSB7XHJcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKylcclxuICAgICAgICBhciA9IGFyLmNvbmNhdChfX3JlYWQoYXJndW1lbnRzW2ldKSk7XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0KHYpIHtcclxuICAgIHJldHVybiB0aGlzIGluc3RhbmNlb2YgX19hd2FpdCA/ICh0aGlzLnYgPSB2LCB0aGlzKSA6IG5ldyBfX2F3YWl0KHYpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0dlbmVyYXRvcih0aGlzQXJnLCBfYXJndW1lbnRzLCBnZW5lcmF0b3IpIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgZyA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSwgaSwgcSA9IFtdO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiKSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlmIChnW25dKSBpW25dID0gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChhLCBiKSB7IHEucHVzaChbbiwgdiwgYSwgYl0pID4gMSB8fCByZXN1bWUobiwgdik7IH0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiByZXN1bWUobiwgdikgeyB0cnkgeyBzdGVwKGdbbl0odikpOyB9IGNhdGNoIChlKSB7IHNldHRsZShxWzBdWzNdLCBlKTsgfSB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKHIpIHsgci52YWx1ZSBpbnN0YW5jZW9mIF9fYXdhaXQgPyBQcm9taXNlLnJlc29sdmUoci52YWx1ZS52KS50aGVuKGZ1bGZpbGwsIHJlamVjdCkgOiBzZXR0bGUocVswXVsyXSwgcik7IH1cclxuICAgIGZ1bmN0aW9uIGZ1bGZpbGwodmFsdWUpIHsgcmVzdW1lKFwibmV4dFwiLCB2YWx1ZSk7IH1cclxuICAgIGZ1bmN0aW9uIHJlamVjdCh2YWx1ZSkgeyByZXN1bWUoXCJ0aHJvd1wiLCB2YWx1ZSk7IH1cclxuICAgIGZ1bmN0aW9uIHNldHRsZShmLCB2KSB7IGlmIChmKHYpLCBxLnNoaWZ0KCksIHEubGVuZ3RoKSByZXN1bWUocVswXVswXSwgcVswXVsxXSk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNEZWxlZ2F0b3Iobykge1xyXG4gICAgdmFyIGksIHA7XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIsIGZ1bmN0aW9uIChlKSB7IHRocm93IGU7IH0pLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuLCBmKSB7IGlbbl0gPSBvW25dID8gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIChwID0gIXApID8geyB2YWx1ZTogX19hd2FpdChvW25dKHYpKSwgZG9uZTogbiA9PT0gXCJyZXR1cm5cIiB9IDogZiA/IGYodikgOiB2OyB9IDogZjsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY1ZhbHVlcyhvKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIG0gPSBvW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSwgaTtcclxuICAgIHJldHVybiBtID8gbS5jYWxsKG8pIDogKG8gPSB0eXBlb2YgX192YWx1ZXMgPT09IFwiZnVuY3Rpb25cIiA/IF9fdmFsdWVzKG8pIDogb1tTeW1ib2wuaXRlcmF0b3JdKCksIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiKSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpKTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpW25dID0gb1tuXSAmJiBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgeyB2ID0gb1tuXSh2KSwgc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgdi5kb25lLCB2LnZhbHVlKTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHNldHRsZShyZXNvbHZlLCByZWplY3QsIGQsIHYpIHsgUHJvbWlzZS5yZXNvbHZlKHYpLnRoZW4oZnVuY3Rpb24odikgeyByZXNvbHZlKHsgdmFsdWU6IHYsIGRvbmU6IGQgfSk7IH0sIHJlamVjdCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWFrZVRlbXBsYXRlT2JqZWN0KGNvb2tlZCwgcmF3KSB7XHJcbiAgICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSB7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb29rZWQsIFwicmF3XCIsIHsgdmFsdWU6IHJhdyB9KTsgfSBlbHNlIHsgY29va2VkLnJhdyA9IHJhdzsgfVxyXG4gICAgcmV0dXJuIGNvb2tlZDtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydFN0YXIobW9kKSB7XHJcbiAgICBpZiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSByZXR1cm4gbW9kO1xyXG4gICAgdmFyIHJlc3VsdCA9IHt9O1xyXG4gICAgaWYgKG1vZCAhPSBudWxsKSBmb3IgKHZhciBrIGluIG1vZCkgaWYgKE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZCwgaykpIHJlc3VsdFtrXSA9IG1vZFtrXTtcclxuICAgIHJlc3VsdC5kZWZhdWx0ID0gbW9kO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0RGVmYXVsdChtb2QpIHtcclxuICAgIHJldHVybiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSA/IG1vZCA6IHsgZGVmYXVsdDogbW9kIH07XHJcbn1cclxuIiwiZXhwb3J0IGZ1bmN0aW9uIG9mZnNldChlbGVtZW50OiBIVE1MRWxlbWVudCkge1xuICAvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcbiAgLy8gUnVubmluZyBnZXRCb3VuZGluZ0NsaWVudFJlY3Qgb24gYVxuICAvLyBkaXNjb25uZWN0ZWQgbm9kZSBpbiBJRSB0aHJvd3MgYW4gZXJyb3JcbiAgaWYgKCFlbGVtZW50IHx8ICFlbGVtZW50LmdldENsaWVudFJlY3RzKCkubGVuZ3RoKSB7XG4gICAgcmV0dXJuIHt0b3A6IDAsIGxlZnQ6IDB9O1xuICB9XG5cbiAgbGV0IGRvY0VsZW06IEhUTUxFbGVtZW50LCByZWN0OiBDbGllbnRSZWN0LCBkb2M6IERvY3VtZW50O1xuXG4gIHJlY3QgPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gIC8vIE1ha2Ugc3VyZSBlbGVtZW50IGlzIG5vdCBoaWRkZW4gKGRpc3BsYXk6IG5vbmUpXG4gIGlmIChyZWN0LndpZHRoIHx8IHJlY3QuaGVpZ2h0KSB7XG4gICAgZG9jID0gZWxlbWVudC5vd25lckRvY3VtZW50O1xuICAgIGRvY0VsZW0gPSBkb2MuZG9jdW1lbnRFbGVtZW50O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRvcDogcmVjdC50b3AgKyB3aW5kb3cucGFnZVlPZmZzZXQgLSBkb2NFbGVtLmNsaWVudFRvcCxcbiAgICAgIGxlZnQ6IHJlY3QubGVmdCArIHdpbmRvdy5wYWdlWE9mZnNldCAtIGRvY0VsZW0uY2xpZW50TGVmdFxuICAgIH07XG4gIH1cblxuICAvLyBSZXR1cm4gemVyb3MgZm9yIGRpc2Nvbm5lY3RlZCBhbmQgaGlkZGVuIGVsZW1lbnRzIChnaC0yMzEwKVxuICByZXR1cm4gcmVjdDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBWaWV3cG9ydFNldHRpbmdzIHtcbiAgY29udGFpbmVyPzogSFRNTEVsZW1lbnQgfCBXaW5kb3c7XG4gIHRocmVzaG9sZD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFib3ZlVGhlVG9wKGVsZW1lbnQ6IEhUTUxFbGVtZW50LCBzZXR0aW5nczogVmlld3BvcnRTZXR0aW5ncyA9IHt9KSB7XG4gIGlmICghZWxlbWVudCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGxldCBmb2xkOiBudW1iZXI7XG5cbiAgY29uc3QgY29udGFpbmVyID0gc2V0dGluZ3MuY29udGFpbmVyIHx8IHdpbmRvdyxcbiAgICB0aHJlc2hvbGQgPSBzZXR0aW5ncy50aHJlc2hvbGQgfHwgMDtcblxuICBpZiAoY29udGFpbmVyIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICBmb2xkID0gb2Zmc2V0KGNvbnRhaW5lcikudG9wO1xuICB9IGVsc2Uge1xuICAgIGZvbGQgPSB3aW5kb3cuc2Nyb2xsWTtcbiAgfVxuXG4gIHJldHVybiBmb2xkID49IChvZmZzZXQoZWxlbWVudCkudG9wICsgdGhyZXNob2xkICsgZWxlbWVudC5vZmZzZXRIZWlnaHQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmlnaHRPZkZvbGQoZWxlbWVudDogSFRNTEVsZW1lbnQsIHNldHRpbmdzOiBWaWV3cG9ydFNldHRpbmdzID0ge30pIHtcbiAgaWYgKCFlbGVtZW50KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IGZvbGQ6IG51bWJlcjtcblxuICBjb25zdCBjb250YWluZXIgPSBzZXR0aW5ncy5jb250YWluZXIgfHwgd2luZG93LFxuICAgIHRocmVzaG9sZCA9IHNldHRpbmdzLnRocmVzaG9sZCB8fCAwO1xuXG4gIGlmIChjb250YWluZXIgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgIGZvbGQgPSBvZmZzZXQoY29udGFpbmVyKS5sZWZ0ICsgY29udGFpbmVyLm9mZnNldFdpZHRoO1xuICB9IGVsc2Uge1xuICAgIGZvbGQgPSB3aW5kb3cuaW5uZXJXaWR0aCArIHdpbmRvdy5zY3JvbGxYO1xuICB9XG5cbiAgcmV0dXJuIGZvbGQgPD0gb2Zmc2V0KGVsZW1lbnQpLmxlZnQgLSB0aHJlc2hvbGQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBiZWxvd1RoZUZvbGQoZWxlbWVudDogSFRNTEVsZW1lbnQsIHNldHRpbmdzOiBWaWV3cG9ydFNldHRpbmdzID0ge30pIHtcbiAgaWYgKCFlbGVtZW50KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IGZvbGQ6IG51bWJlcjtcblxuICBjb25zdCBjb250YWluZXIgPSBzZXR0aW5ncy5jb250YWluZXIgfHwgd2luZG93LFxuICAgIHRocmVzaG9sZCA9IHNldHRpbmdzLnRocmVzaG9sZCB8fCAwO1xuXG4gIGlmIChjb250YWluZXIgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgIGZvbGQgPSBvZmZzZXQoY29udGFpbmVyKS50b3AgKyBjb250YWluZXIub2Zmc2V0SGVpZ2h0O1xuICB9IGVsc2Uge1xuICAgIGZvbGQgPSB3aW5kb3cuaW5uZXJIZWlnaHQgKyB3aW5kb3cuc2Nyb2xsWTtcbiAgfVxuXG4gIHJldHVybiBmb2xkIDw9IG9mZnNldChlbGVtZW50KS50b3AgLSB0aHJlc2hvbGQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsZWZ0T2ZCZWdpbihlbGVtZW50OiBIVE1MRWxlbWVudCwgc2V0dGluZ3M6IFZpZXdwb3J0U2V0dGluZ3MgPSB7fSkge1xuICBpZiAoIWVsZW1lbnQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsZXQgZm9sZDogbnVtYmVyO1xuXG4gIGNvbnN0IGNvbnRhaW5lciA9IHNldHRpbmdzLmNvbnRhaW5lciB8fCB3aW5kb3csXG4