@greg-md/ng-facebook
Version:
Using Facebook SDK with Angular.
594 lines (584 loc) • 53.7 kB
JavaScript
import { Inject, Injectable, NgZone, PLATFORM_ID, Directive, Input, ElementRef, Renderer2, InjectionToken, Optional, NgModule, Component, ChangeDetectionStrategy, defineInjectable, inject } from '@angular/core';
import { isPlatformServer, isPlatformBrowser, CommonModule } from '@angular/common';
import { Observable, ReplaySubject } from 'rxjs';
import { tap, map } from 'rxjs/operators';
import { __extends } from 'tslib';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var /** @type {?} */ FACEBOOK_DEFAULTS = {
xfbml: false,
version: 'v3.0'
};
var FacebookService = /** @class */ (function () {
function FacebookService(ngZone, platformId) {
this.ngZone = ngZone;
this.platformId = platformId;
this.sdk = new ReplaySubject(1);
}
/**
* @param {?=} locale
* @return {?}
*/
FacebookService.prototype.load = /**
* @param {?=} locale
* @return {?}
*/
function (locale) {
var _this = this;
if (locale === void 0) { locale = 'en_US'; }
return Observable.create(function (subscriber) {
if (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(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(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 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 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 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 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: Injectable, args: [{
providedIn: 'root'
},] },
];
/** @nocollapse */
FacebookService.ctorParameters = function () { return [
{ type: NgZone, },
{ type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID,] },] },
]; };
/** @nocollapse */ FacebookService.ngInjectableDef = defineInjectable({ factory: function FacebookService_Factory() { return new FacebookService(inject(NgZone), inject(PLATFORM_ID)); }, token: FacebookService, providedIn: "root" });
return FacebookService;
}());
/**
* @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 InjectionToken('fb_parse_lazy_load');
var FacebookParseDirective = /** @class */ (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 (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: Directive, args: [{
selector: '[fbParse]',
},] },
];
/** @nocollapse */
FacebookParseDirective.ctorParameters = function () { return [
{ type: ElementRef, },
{ type: FacebookService, },
{ type: Renderer2, },
{ type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] },] },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [FB_PARSE_LAZY_LOAD,] },] },
]; };
FacebookParseDirective.propDecorators = {
"lazyLoad": [{ type: Input },],
"container": [{ type: Input },],
};
return FacebookParseDirective;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var FacebookLikeComponent = /** @class */ (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: 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: ChangeDetectionStrategy.OnPush,
},] },
];
/** @nocollapse */
FacebookLikeComponent.ctorParameters = function () { return [
{ type: ElementRef, },
{ type: FacebookService, },
{ type: Renderer2, },
{ type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] },] },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [FB_PARSE_LAZY_LOAD,] },] },
]; };
FacebookLikeComponent.propDecorators = {
"action": [{ type: Input },],
"colorscheme": [{ type: Input },],
"href": [{ type: Input },],
"kidDirectedSite": [{ type: Input },],
"layout": [{ type: Input },],
"ref": [{ type: Input },],
"share": [{ type: Input },],
"showFaces": [{ type: Input },],
"size": [{ type: Input },],
"width": [{ type: Input },],
};
return FacebookLikeComponent;
}(FacebookParseDirective));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var FacebookPageComponent = /** @class */ (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: 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: ChangeDetectionStrategy.OnPush,
},] },
];
/** @nocollapse */
FacebookPageComponent.ctorParameters = function () { return [
{ type: ElementRef, },
{ type: FacebookService, },
{ type: Renderer2, },
{ type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] },] },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [FB_PARSE_LAZY_LOAD,] },] },
]; };
FacebookPageComponent.propDecorators = {
"href": [{ type: Input },],
"width": [{ type: Input },],
"height": [{ type: Input },],
"tabs": [{ type: Input },],
"hideCover": [{ type: Input },],
"showFacepile": [{ type: Input },],
"hideCta": [{ type: Input },],
"smallHeader": [{ type: Input },],
"adaptContainerWidth": [{ type: Input },],
};
return FacebookPageComponent;
}(FacebookParseDirective));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var FacebookModule = /** @class */ (function () {
function FacebookModule() {
}
FacebookModule.decorators = [
{ type: NgModule, args: [{
imports: [
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
*/
export { FACEBOOK_DEFAULTS, FacebookService, FacebookLikeComponent, FacebookPageComponent, FB_PARSE_LAZY_LOAD, FacebookParseDirective, FacebookModule };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JlZy1tZC1uZy1mYWNlYm9vay5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQGdyZWctbWQvbmctZmFjZWJvb2svbGliL2ZhY2Vib29rLnNlcnZpY2UudHMiLCJuZzovL0BncmVnLW1kL25nLWZhY2Vib29rL2xpYi9kb20udHMiLCJuZzovL0BncmVnLW1kL25nLWZhY2Vib29rL2xpYi9wYXJzZS5kaXJlY3RpdmUudHMiLCJuZzovL0BncmVnLW1kL25nLWZhY2Vib29rL2xpYi9saWtlLmNvbXBvbmVudC50cyIsIm5nOi8vQGdyZWctbWQvbmctZmFjZWJvb2svbGliL3BhZ2UuY29tcG9uZW50LnRzIiwibmc6Ly9AZ3JlZy1tZC9uZy1mYWNlYm9vay9saWIvZmFjZWJvb2subW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSwgTmdab25lLCBQTEFURk9STV9JRCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaXNQbGF0Zm9ybVNlcnZlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBSZXBsYXlTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YXAsIG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuZXhwb3J0IGludGVyZmFjZSBGYWNlYm9va0luaXRQYXJhbXMge1xuICBhcHBJZD86IHN0cmluZztcbiAgc3RhdHVzPzogYm9vbGVhbjtcbiAgeGZibWw/OiBib29sZWFuO1xuICB2ZXJzaW9uPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZhY2Vib29rQXV0aCB7XG4gIGFjY2Vzc1Rva2VuOiBzdHJpbmc7XG4gIGV4cGlyZXNJbjogbnVtYmVyO1xuICBzaWduZWRSZXF1ZXN0OiBzdHJpbmc7XG4gIHVzZXJJRDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZhY2Vib29rTG9naW5SZXNwb25zZSB7XG4gIHN0YXR1czogc3RyaW5nO1xuICBhdXRoUmVzcG9uc2U6IEZhY2Vib29rQXV0aDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGYWNlYm9va0xvZ2luT3B0aW9ucyB7XG4gIGF1dGhfdHlwZT86ICdyZXJlcXVlc3QnO1xuICBzY29wZT86IHN0cmluZztcbiAgcmV0dXJuX3Njb3Blcz86IGJvb2xlYW47XG4gIGVuYWJsZV9wcm9maWxlX3NlbGVjdG9yPzogYm9vbGVhbjtcbiAgcHJvZmlsZV9zZWxlY3Rvcl9pZHM/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmFjZWJvb2tBcGlFcnJvciB7XG4gIG1lc3NhZ2U6IHN0cmluZztcbn1cblxuZXhwb3J0IGNvbnN0IGVudW0gRmFjZWJvb2tBcGlNZXRob2Qge1xuICBHZXQgPSAnZ2V0JyxcbiAgUG9zdCA9ICdwb3N0JyxcbiAgRGVsZXRlID0gJ2RlbGV0ZScsXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmFjZWJvb2tBcGlQYXJhbXMge1xuICBbcHJvcE5hbWU6IHN0cmluZ106IGFueTtcbn1cblxuZXhwb3J0IHR5cGUgRmFjZWJvb2tBcGlDYWxsYmFjayA9IChyZXNwb25zZT86IHtcbiAgICBlcnJvcj86IEZhY2Vib29rQXBpRXJyb3I7XG4gICAgW3Byb3BOYW1lOiBzdHJpbmddOiBhbnk7XG4gIH0pID0+IHZvaWQ7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmFjZWJvb2sge1xuICBYRkJNTDoge1xuICAgIHBhcnNlOiAoZWxlbWVudDogSFRNTEVsZW1lbnQsIGNiPzogKCkgPT4gdm9pZCkgPT4gdm9pZDtcbiAgfTtcblxuICBpbml0OiAocGFyYW1zOiBGYWNlYm9va0luaXRQYXJhbXMpID0+IHZvaWQ7XG5cbiAgbG9naW46IChjYWxsYmFjaz86IChyZXNwb25zZTogRmFjZWJvb2tMb2dpblJlc3BvbnNlKSA9PiB2b2lkLCBvcHRpb25zPzogRmFjZWJvb2tMb2dpbk9wdGlvbnMpID0+IHZvaWQ7XG5cbiAgYXBpOiAoXG4gICAgcGF0aDogc3RyaW5nLFxuICAgIG1ldGhvZD86IEZhY2Vib29rQXBpTWV0aG9kIHwgRmFjZWJvb2tBcGlQYXJhbXMgfCBGYWNlYm9va0FwaUNhbGxiYWNrLFxuICAgIHBhcmFtcz86IEZhY2Vib29rQXBpUGFyYW1zIHwgRmFjZWJvb2tBcGlDYWxsYmFjayxcbiAgICBjYWxsYmFjaz86IEZhY2Vib29rQXBpQ2FsbGJhY2tcbiAgKSA9PiB2b2lkO1xufVxuXG5leHBvcnQgY29uc3QgRkFDRUJPT0tfREVGQVVMVFM6IEZhY2Vib29rSW5pdFBhcmFtcyA9IHtcbiAgeGZibWw6IGZhbHNlLFxuICB2ZXJzaW9uOiAndjMuMCdcbn07XG5cbmRlY2xhcmUgY29uc3QgRkI6IEZhY2Vib29rO1xuXG5kZWNsYXJlIGNvbnN0IHdpbmRvdzoge1xuICBGQjogRmFjZWJvb2s7XG59O1xuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBGYWNlYm9va1NlcnZpY2Uge1xuICBzZGsgPSBuZXcgUmVwbGF5U3ViamVjdDxGYWNlYm9vaz4oMSk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSxcbiAgICBASW5qZWN0KFBMQVRGT1JNX0lEKSBwcml2YXRlIHBsYXRmb3JtSWQ6IHN0cmluZyxcbiAgKSB7XG4gIH1cblxuICBsb2FkKGxvY2FsZTogc3RyaW5nID0gJ2VuX1VTJyk6IE9ic2VydmFibGU8RmFjZWJvb2s+IHtcbiAgICByZXR1cm4gT2JzZXJ2YWJsZS5jcmVhdGUoc3Vic2NyaWJlciA9PiB7XG4gICAgICBpZiAoaXNQbGF0Zm9ybVNlcnZlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgICBkZWxldGUgd2luZG93LkZCO1xuXG4gICAgICAgIGxldCBqc1NkazogSFRNTEVsZW1lbnQsIGZiUm9vdDogSFRNTEVsZW1lbnQ7XG5cbiAgICAgICAgaWYgKGpzU2RrID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZhY2Vib29rLWpzc2RrJykpIHtcbiAgICAgICAgICBqc1Nkay5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGpzU2RrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmYlJvb3QgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmItcm9vdCcpKSB7XG4gICAgICAgICAgZmJSb290LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZmJSb290KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuXG4gICAgICAgIHNjcmlwdC5pZCA9ICdmYWNlYm9vay1qc3Nkayc7XG5cbiAgICAgICAgc2NyaXB0LnNyYyA9ICcvL2Nvbm5lY3QuZmFjZWJvb2submV0LycgKyAobG9jYWxlIHx8ICdlbl9VUycpICsgJy9zZGsuanMnO1xuXG4gICAgICAgIHNjcmlwdC5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgIHN1YnNjcmliZXIubmV4dChGQik7XG5cbiAgICAgICAgICAgIHN1YnNjcmliZXIuY29tcGxldGUoKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBzY3JpcHQub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgc3Vic2NyaWJlci5lcnJvcignRmFjZWJvb2sgU0RLIGNvdWxkIG5vdCBiZSBsb2FkZWQuJyk7XG5cbiAgICAgICAgICAgIHN1YnNjcmliZXIuY29tcGxldGUoKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHNjcmlwdCk7XG4gICAgICB9KTtcbiAgICB9KS5waXBlKG1hcCgoc2RrOiBGYWNlYm9vaykgPT4ge1xuICAgICAgdGhpcy5zZGsubmV4dChzZGspO1xuXG4gICAgICByZXR1cm4gc2RrO1xuICAgIH0pKTtcbiAgfVxuXG4gIGluaXQocGFyYW1zOiBGYWNlYm9va0luaXRQYXJhbXMgPSB7fSwgbG9jYWxlOiBzdHJpbmcgPSAnZW5fVVMnKSB7XG4gICAgcmV0dXJuIHRoaXMubG9hZChsb2NhbGUpLnBpcGU8RmFjZWJvb2s+KHRhcDxGYWNlYm9vaz4oc2RrID0+IHtcbiAgICAgIHBhcmFtcyA9IE9iamVjdC5hc3NpZ24oe30sIEZBQ0VCT09LX0RFRkFVTFRTLCBwYXJhbXMpO1xuXG4gICAgICBzZGsuaW5pdChwYXJhbXMpO1xuXG4gICAgICB0aGlzLnJlbG9hZFJlbmRlcmVkRWxlbWVudHMoKS5zdWJzY3JpYmUoKTtcbiAgICB9KSk7XG4gIH1cblxuICBsb2dpbihvcHRpb25zPzogRmFjZWJvb2tMb2dpbk9wdGlvbnMpOiBPYnNlcnZhYmxlPEZhY2Vib29rQXV0aD4ge1xuICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZShzdWJzY3JpYmVyID0+IHtcbiAgICAgIHRoaXMuc2RrLnN1YnNjcmliZShzZGsgPT4ge1xuICAgICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgc2RrLmxvZ2luKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChyZXNwb25zZS5hdXRoUmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLm5leHQocmVzcG9uc2UuYXV0aFJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLmVycm9yKHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHN1YnNjcmliZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sIG9wdGlvbnMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgYXBpKHBhdGg6IHN0cmluZywgbWV0aG9kPzogRmFjZWJvb2tBcGlNZXRob2QgfCBGYWNlYm9va0FwaVBhcmFtcywgcGFyYW1zPzogRmFjZWJvb2tBcGlQYXJhbXMpOiBPYnNlcnZhYmxlPE9iamVjdD4ge1xuICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZShzdWJzY3JpYmVyID0+IHtcbiAgICAgIHRoaXMuc2RrLnN1YnNjcmliZShzZGsgPT4ge1xuICAgICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgc2RrLmFwaShwYXRoLCBtZXRob2QsIHBhcmFtcywgcmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlICYmICFyZXNwb25zZS5lcnJvcikge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIubmV4dChyZXNwb25zZSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5lcnJvcihyZXNwb25zZSA/IHJlc3BvbnNlLmVycm9yIDogbnVsbCk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBzdWJzY3JpYmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHBhcnNlKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogT2JzZXJ2YWJsZTxIVE1MRWxlbWVudD4ge1xuICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZShzdWJzY3JpYmVyID0+IHtcbiAgICAgIHRoaXMuc2RrLnN1YnNjcmliZShzZGsgPT4ge1xuICAgICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgc2RrLlhGQk1MLnBhcnNlKGVsZW1lbnQsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICAgIHN1YnNjcmliZXIubmV4dChlbGVtZW50KTtcblxuICAgICAgICAgICAgICBzdWJzY3JpYmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHJlbG9hZFJlbmRlcmVkRWxlbWVudHMoKTogT2JzZXJ2YWJsZTxIVE1MRWxlbWVudD4ge1xuICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZShzdWJzY3JpYmVyID0+IHtcbiAgICAgIHRoaXMuc2RrLnN1YnNjcmliZShzZGsgPT4ge1xuICAgICAgICBjb25zdCBlbGVtZW50cyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ1tmYi14ZmJtbC1zdGF0ZT1cInJlbmRlcmVkXCJdJyk7XG5cbiAgICAgICAgbGV0IHByb2Nlc3NpbmcgPSBlbGVtZW50cy5sZW5ndGg7XG5cbiAgICAgICAgQXJyYXkuZnJvbShlbGVtZW50cykuZm9yRWFjaChub2RlID0+IHtcbiAgICAgICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICBzZGsuWEZCTUwucGFyc2Uobm9kZS5wYXJlbnRFbGVtZW50LCAoKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICAgICAgLS1wcm9jZXNzaW5nO1xuXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5uZXh0KG5vZGUucGFyZW50RWxlbWVudCk7XG5cbiAgICAgICAgICAgICAgICBpZiAocHJvY2Vzc2luZyA8PSAwKSB7XG4gICAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG59XG4iLCJleHBvcnQgZnVuY3Rpb24gb2Zmc2V0KGVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG4gIC8vIFN1cHBvcnQ6IElFIDw9MTEgb25seVxuICAvLyBSdW5uaW5nIGdldEJvdW5kaW5nQ2xpZW50UmVjdCBvbiBhXG4gIC8vIGRpc2Nvbm5lY3RlZCBub2RlIGluIElFIHRocm93cyBhbiBlcnJvclxuICBpZiAoIWVsZW1lbnQgfHwgIWVsZW1lbnQuZ2V0Q2xpZW50UmVjdHMoKS5sZW5ndGgpIHtcbiAgICByZXR1cm4ge3RvcDogMCwgbGVmdDogMH07XG4gIH1cblxuICBsZXQgZG9jRWxlbTogSFRNTEVsZW1lbnQsIHJlY3Q6IENsaWVudFJlY3QsIGRvYzogRG9jdW1lbnQ7XG5cbiAgcmVjdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgLy8gTWFrZSBzdXJlIGVsZW1lbnQgaXMgbm90IGhpZGRlbiAoZGlzcGxheTogbm9uZSlcbiAgaWYgKHJlY3Qud2lkdGggfHwgcmVjdC5oZWlnaHQpIHtcbiAgICBkb2MgPSBlbGVtZW50Lm93bmVyRG9jdW1lbnQ7XG4gICAgZG9jRWxlbSA9IGRvYy5kb2N1bWVudEVsZW1lbnQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdG9wOiByZWN0LnRvcCArIHdpbmRvdy5wYWdlWU9mZnNldCAtIGRvY0VsZW0uY2xpZW50VG9wLFxuICAgICAgbGVmdDogcmVjdC5sZWZ0ICsgd2luZG93LnBhZ2VYT2Zmc2V0IC0gZG9jRWxlbS5jbGllbnRMZWZ0XG4gICAgfTtcbiAgfVxuXG4gIC8vIFJldHVybiB6ZXJvcyBmb3IgZGlzY29ubmVjdGVkIGFuZCBoaWRkZW4gZWxlbWVudHMgKGdoLTIzMTApXG4gIHJldHVybiByZWN0O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFZpZXdwb3J0U2V0dGluZ3Mge1xuICBjb250YWluZXI/OiBIVE1MRWxlbWVudCB8IFdpbmRvdztcbiAgdGhyZXNob2xkPzogbnVtYmVyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYWJvdmVUaGVUb3AoZWxlbWVudDogSFRNTEVsZW1lbnQsIHNldHRpbmdzOiBWaWV3cG9ydFNldHRpbmdzID0ge30pIHtcbiAgaWYgKCFlbGVtZW50KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IGZvbGQ6IG51bWJlcjtcblxuICBjb25zdCBjb250YWluZXIgPSBzZXR0aW5ncy5jb250YWluZXIgfHwgd2luZG93LFxuICAgIHRocmVzaG9sZCA9IHNldHRpbmdzLnRocmVzaG9sZCB8fCAwO1xuXG4gIGlmIChjb250YWluZXIgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgIGZvbGQgPSBvZmZzZXQoY29udGFpbmVyKS50b3A7XG4gIH0gZWxzZSB7XG4gICAgZm9sZCA9IHdpbmRvdy5zY3JvbGxZO1xuICB9XG5cbiAgcmV0dXJuIGZvbGQgPj0gKG9mZnNldChlbGVtZW50KS50b3AgKyB0aHJlc2hvbGQgKyBlbGVtZW50Lm9mZnNldEhlaWdodCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByaWdodE9mRm9sZChlbGVtZW50OiBIVE1MRWxlbWVudCwgc2V0dGluZ3M6IFZpZXdwb3J0U2V0dGluZ3MgPSB7fSkge1xuICBpZiAoIWVsZW1lbnQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsZXQgZm9sZDogbnVtYmVyO1xuXG4gIGNvbnN0IGNvbnRhaW5lciA9IHNldHRpbmdzLmNvbnRhaW5lciB8fCB3aW5kb3csXG4gICAgdGhyZXNob2xkID0gc2V0dGluZ3MudGhyZXNob2xkIHx8IDA7XG5cbiAgaWYgKGNvbnRhaW5lciBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XG4gICAgZm9sZCA9IG9mZnNldChjb250YWluZXIpLmxlZnQgKyBjb250YWluZXIub2Zmc2V0V2lkdGg7XG4gIH0gZWxzZSB7XG4gICAgZm9sZCA9IHdpbmRvdy5pbm5lcldpZHRoICsgd2luZG93LnNjcm9sbFg7XG4gIH1cblxuICByZXR1cm4gZm9sZCA8PSBvZmZzZXQoZWxlbWVudCkubGVmdCAtIHRocmVzaG9sZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJlbG93VGhlRm9sZChlbGVtZW50OiBIVE1MRWxlbWVudCwgc2V0dGluZ3M6IFZpZXdwb3J0U2V0dGluZ3MgPSB7fSkge1xuICBpZiAoIWVsZW1lbnQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsZXQgZm9sZDogbnVtYmVyO1xuXG4gIGNvbnN0IGNvbnRhaW5lciA9IHNldHRpbmdzLmNvbnRhaW5lciB8fCB3aW5kb3csXG4gICAgdGhyZXNob2xkID0gc2V0dGluZ3MudGhyZXNob2xkIHx8IDA7XG5cbiAgaWYgKGNvbnRhaW5lciBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XG4gICAgZm9sZCA9IG9mZnNldChjb250YWluZXIpLnRvcCArIGNvbnRhaW5lci5vZmZzZXRIZWlnaHQ7XG4gIH0gZWxzZSB7XG4gICAgZm9sZCA9IHdpbmRvdy5pbm5lckhlaWdodCArIHdpbmRvdy5zY3JvbGxZO1xuICB9XG5cbiAgcmV0dXJuIGZvbGQgPD0gb2Zmc2V0KGVsZW1lbnQpLnRvcCAtIHRocmVzaG9sZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxlZnRPZkJlZ2luKGVsZW1lbnQ6IEhUTUxFbGVtZW50LCBzZXR0aW5nczogVmlld3BvcnRTZXR0aW5ncyA9IHt9KSB7XG4gIGlmICghZWxlbWVudCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGxldCBmb2xkOiBudW1iZXI7XG5cbiAgY29uc3QgY29udGFpbmVyID0gc2V0dGluZ3MuY29udGFpbmVyIHx8IHdpbmRvdyxcbiAgICB0aHJlc2hvbGQgPSBzZXR0aW5ncy50aHJlc2hvbGQgfHwgMDtcblxuICBpZiAoY29udGFpbmVyIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICBmb2xkID0gb2Zmc2V0KGNvbnRhaW5lcikubGVmdDtcbiAgfSBlbHNlIHtcbiAgICBmb2xkID0gd2luZG93LnNjcm9sbFg7XG4gIH1cblxuICByZXR1cm4gZm9sZCA+PSBvZmZzZXQoZWxlbWVudCkubGVmdCArIHRocmVzaG9sZCArIGVsZW1lbnQub2Zmc2V0V2lkdGg7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpblZpZXdwb3J0KGVsZW1lbnQ6IEhUTUxFbGVtZW50LCBzZXR0aW5nczogVmlld3BvcnRTZXR0aW5ncyA9IHt9KSB7XG4gIHJldHVybiAhYmVsb3dUaGVGb2xkKGVsZW1lbnQsIHNldHRpbmdzKVxuICAgICYmICFhYm92ZVRoZVRvcChlbGVtZW50LCBzZXR0aW5ncylcbiAgICAmJiAhbGVmdE9mQmVnaW4oZWxlbWVudCwgc2V0dGluZ3MpXG4gICAgJiYgIXJpZ2h0T2ZGb2xkKGVsZW1lbnQsIHNldHRpbmdzKTtcbn1cbiIsImltcG9ydCB7XG4gIERpcmVjdGl2ZSwgSW5wdXQsIEVsZW1lbnRSZWYsIEFmdGVyVmlld0luaXQsIFJlbmRlcmVyMiwgSW5qZWN0aW9uVG9rZW4sIEluamVjdCwgT3B0aW9uYWwsXG4gIFBMQVRGT1JNX0lELCBPbkRlc3Ryb3lcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5cbmltcG9ydCB7IGluVmlld3BvcnQgfSBmcm9tICcuL2RvbSc7XG5cbmltcG9ydCB7IEZhY2Vib29rU2VydmljZSB9IGZyb20gJy4vZmFjZWJvb2suc2VydmljZSc7XG5cbmV4cG9ydCBjb25zdCBGQl9QQVJTRV9MQVpZX0xPQUQgPSBuZXcgSW5qZWN0aW9uVG9rZW48c3RyaW5nPignZmJfcGFyc2VfbGF6eV9sb2FkJyk7XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tmYlBhcnNlXScsXG59KVxuZXhwb3J0IGNsYXNzIEZhY2Vib29rUGFyc2VEaXJlY3RpdmUgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuICBASW5wdXQoKVxuICBzZXQgbGF6eUxvYWQodGhyZXNob2xkOiBudW1iZXIpIHtcbiAgICB0aGlzLnRocmVzaG9sZCA9IHRocmVzaG9sZDtcbiAgfVxuXG4gIEBJbnB1dCgpXG4gIGNvbnRhaW5lcjogSFRNTEVsZW1lbnQgfCBXaW5kb3c7XG5cbiAgc2Nyb2xsVW5sb2FkOiAoKSA9PiB2b2lkO1xuICByZXNpemVVbmxvYWQ6ICgpID0+IHZvaWQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBlbGVtZW50UmVmOiBFbGVtZW50UmVmLFxuICAgIHByaXZhdGUgZmFjZWJvb2s6IEZhY2Vib29rU2VydmljZSxcbiAgICBwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBwbGF0Zm9ybUlkOiBPYmplY3QsXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChGQl9QQVJTRV9MQVpZX0xPQUQpIHByaXZhdGUgdGhyZXNob2xkOiBudW1iZXIsXG4gICkge1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIGlmICh0aGlzLnRocmVzaG9sZCA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5sb2FkKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaW5pdExpc3RlbmVycygpO1xuXG4gICAgICB0aGlzLnRyeUxvYWRpbmcoKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLnVubG9hZExpc3RlbmVycygpO1xuICB9XG5cbiAgaW5pdExpc3RlbmVycygpIHtcbiAgICB0aGlzLnNjcm9sbFVubG9hZCA9IHRoaXMucmVuZGVyZXIubGlzdGVuKCd3aW5kb3cnLCAnc2Nyb2xsJywgKCkgPT4ge1xuICAgICAgdGhpcy50cnlMb2FkaW5nKCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLnJlc2l6ZVVubG9hZCA9IHRoaXMucmVuZGVyZXIubGlzdGVuKCd3aW5kb3cnLCAncmVzaXplJywgKCkgPT4ge1xuICAgICAgdGhpcy50cnlMb2FkaW5nKCk7XG4gICAgfSk7XG4gIH1cblxuICB0cnlMb2FkaW5nKCkge1xuICAgIGlmIChcbiAgICAgIGlzUGxhdGZvcm1Ccm93c2VyKHRoaXMucGxhdGZvcm1JZCkgJiYgaW5WaWV3cG9ydCh0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwge1xuICAgICAgICB0aHJlc2hvbGQ6IHRoaXMudGhyZXNob2xkLFxuICAgICAgICBjb250YWluZXI6IHRoaXMuY29udGFpbmVyXG4gICAgICB9KVxuICAgICkge1xuICAgICAgdGhpcy5sb2FkKCk7XG5cbiAgICAgIHRoaXMudW5sb2FkTGlzdGVuZXJzKCk7XG4gICAgfVxuICB9XG5cbiAgbG9hZCgpIHtcbiAgICB0aGlzLmZhY2Vib29rLnBhcnNlKHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50KS5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHVubG9hZExpc3RlbmVycygpIHtcbiAgICBpZiAodGhpcy5zY3JvbGxVbmxvYWQpIHtcbiAgICAgIHRoaXMuc2Nyb2xsVW5sb2FkKCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucmVzaXplVW5sb2FkKSB7XG4gICAgICB0aGlzLnJlc2l6ZVVubG9hZCgpO1xuICAgIH1cbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgQ29tcG9uZW50LCBJbnB1dCwgRWxlbWVudFJlZiwgUmVuZGVyZXIyLCBJbmplY3QsIE9wdGlvbmFsLCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgUExBVEZPUk1fSURcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IEZhY2Vib29rU2VydmljZSB9IGZyb20gJy4vZmFjZWJvb2suc2VydmljZSc7XG5cbmltcG9ydCB7IEZhY2Vib29rUGFyc2VEaXJlY3RpdmUsIEZCX1BBUlNFX0xBWllfTE9BRCB9IGZyb20gJy4vcGFyc2UuZGlyZWN0aXZlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZmItbGlrZScsXG4gIHN0eWxlczogW10sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImZiLWxpa2VcIlxuICAgICAgICAgW2F0dHIuZGF0YS1hY3Rpb25dPVwiYWN0aW9uXCJcbiAgICAgICAgIFthdHRyLmRhdGEtY29sb3JzY2hlbWVdPVwiY29sb3JzY2hlbWVcIlxuICAgICAgICAgW2F0dHIuZGF0YS1ocmVmXT1cImhyZWZcIlxuICAgICAgICAgW2F0dHIuZGF0YS1raWQtZGlyZWN0ZWQtc2l0ZV09XCJraWREaXJlY3RlZFNpdGVcIlxuICAgICAgICAgW2F0dHIuZGF0YS1sYXlvdXRdPVwibGF5b3V0XCJcbiAgICAgICAgIFthdHRyLmRhdGEtcmVmXT1cInJlZlwiXG4gICAgICAgICBbYXR0ci5kYXRhLXNoYXJlXT1cInNoYXJlXCJcbiAgICAgICAgIFthdHRyLmRhdGEtc2hvdy1mYWNlc109XCJzaG93RmFjZXNcIlxuICAgICAgICAgW2F0dHIuZGF0YS1zaXplXT1cInNpemVcIlxuICAgICAgICAgW2F0dHIuZGF0YS13aWR0aF09XCJ3aWR0aFwiXG4gICAgPlxuICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICAgIDwvZGl2PlxuICBgLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgRmFjZWJvb2tMaWtlQ29tcG9uZW50IGV4dGVuZHMgRmFjZWJvb2tQYXJzZURpcmVjdGl2ZSB7XG4gIEBJbnB1dCgpIGFjdGlvbjogJ2xpa2UnIHwgJ3JlY29tbWVuZCcgPSAnbGlrZSc7XG4gIEBJbnB1dCgpIGNvbG9yc2NoZW1lOiAnbGlnaHQnIHwgJ2RhcmsnID0gJ2xpZ2h0JztcbiAgQElucHV0KCkgaHJlZjogc3RyaW5nO1xuICBASW5wdXQoKSBraWREaXJlY3RlZFNpdGUgPSBmYWxzZTtcbiAgQElucHV0KCkgbGF5b3V0OiAnc3RhbmRhcmQnIHwgJ2J1dHRvbl9jb3VudCcgfCAnYnV0dG9uJyB8ICdib3hfY291bnQnID0gJ3N0YW5kYXJkJztcbiAgQElucHV0KCkgcmVmOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHNoYXJlID0gZmFsc2U7XG4gIEBJbnB1dCgpIHNob3dGYWNlcyA9IGZhbHNlO1xuICBASW5wdXQoKSBzaXplOiAnbGFyZ2UnIHwgJ3NtYWxsJyA9ICdzbWFsbCc7XG4gIEBJbnB1dCgpIHdpZHRoOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICBmYWNlYm9vazogRmFjZWJvb2tTZXJ2aWNlLFxuICAgIHJlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgQEluamVjdChQTEFURk9STV9JRCkgcGxhdGZvcm1JZDogT2JqZWN0LFxuICAgIEBPcHRpb25hbCgpIEBJbmplY3QoRkJfUEFSU0VfTEFaWV9MT0FEKSB0aHJlc2hvbGQ6IG51bWJlclxuICApIHtcbiAgICBzdXBlcihlbGVtZW50UmVmLCBmYWNlYm9vaywgcmVuZGVyZXIsIHBsYXRmb3JtSWQsIHRocmVzaG9sZCk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIENvbXBvbmVudCwgSW5wdXQsIEVsZW1lbnRSZWYsIFJlbmRlcmVyMiwgSW5qZWN0LCBPcHRpb25hbCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIFBMQVRGT1JNX0lEXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBGYWNlYm9va1NlcnZpY2UgfSBmcm9tICcuL2ZhY2Vib29rLnNlcnZpY2UnO1xuXG5pbXBvcnQgeyBGYWNlYm9va1BhcnNlRGlyZWN0aXZlLCBGQl9QQVJTRV9MQVpZX0xPQUQgfSBmcm9tICcuL3BhcnNlLmRpcmVjdGl2ZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2ZiLXBhZ2UnLFxuICBzdHlsZXM6IFtdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJmYi1wYWdlXCJcbiAgICAgICAgIFthdHRyLmRhdGEtaHJlZl09XCJocmVmXCJcbiAgICAgICAgIFthdHRyLmRhdGEtd2lkdGhdPVwid2lkdGhcIlxuICAgICAgICAgW2F0dHIuZGF0YS1oZWlnaHRdPVwiaGVpZ2h0XCJcbiAgICAgICAgIFthdHRyLmRhdGEtdGFic109XCJ0YWJzXCJcbiAgICAgICAgIFthdHRyLmRhdGEtaGlkZS1jb3Zlcl09XCJoaWRlQ292ZXJcIlxuICAgICAgICAgW2F0dHIuZGF0YS1zaG93LWZhY2VwaWxlXT1cInNob3dGYWNlcGlsZVwiXG4gICAgICAgICBbYXR0ci5kYXRhLWhpZGUtY3RhXT1cImhpZGVDdGFcIlxuICAgICAgICAgW2F0dHIuZGF0YS1zbWFsbC1oZWFkZXJdPVwic21hbGxIZWFkZXJcIlxuICAgICAgICAgW2F0dHIuZGF0YS1hZGFwdC1jb250YWluZXItd2lkdGhdPVwiYWRhcHRDb250YWluZXJXaWR0aFwiXG4gICAgPlxuICAgICAgPGJsb2NrcXVvdGUgW2F0dHIuY2l0ZV09XCJocmVmXCIgY2xhc3M9XCJmYi14ZmJtbC1wYXJzZS1pZ25vcmVcIj5cbiAgICAgICAgPGEgW2hyZWZdPVwiaHJlZlwiPlxuICAgICAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICAgICAgPC9hPlxuICAgICAgPC9ibG9ja3F1b3RlPlxuICAgIDwvZGl2PlxuICBgLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgRmFjZWJvb2tQYWdlQ29tcG9uZW50IGV4dGVuZHMgRmFjZWJvb2tQYXJzZURpcmVjdGl2ZSB7XG4gIEBJbnB1dCgpIGhyZWY6IHN0cmluZztcbiAgQElucHV0KCkgd2lkdGggPSAzNDA7XG4gIEBJbnB1dCgpIGhlaWdodCA9IDUwMDtcbiAgQElucHV0KCkgdGFicyA9ICd0aW1lbGluZSc7XG4gIEBJbnB1dCgpIGhpZGVDb3ZlciA9IGZhbHNlO1xuICBASW5wdXQoKSBzaG93RmFjZXBpbGUgPSB0cnVlO1xuICBASW5wdXQoKSBoaWRlQ3RhID0gZmFsc2U7XG4gIEBJbnB1dCgpIHNtYWxsSGVhZGVyID0gZmFsc2U7XG4gIEBJbnB1dCgpIGFkYXB0Q29udGFpbmVyV2lkdGggPSB0cnVlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXG4gICAgZmFjZWJvb2s6IEZhY2Vib29rU2VydmljZSxcbiAgICByZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgIEBJbmplY3QoUExBVEZPUk1fSUQpIHBsYXRmb3JtSWQ6IE9iamVjdCxcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KEZCX1BBUlNFX0xBWllfTE9BRCkgdGhyZXNob2xkOiBudW1iZXJcbiAgKSB7XG4gICAgc3VwZXIoZWxlbWVudFJlZiwgZmFjZWJvb2ssIHJlbmRlcmVyLCBwbGF0Zm9ybUlkLCB0aHJlc2hvbGQpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuaW1wb3J0IHsgRmFjZWJvb2tQYXJzZURpcmVjdGl2ZSB9IGZyb20gJy4vcGFyc2UuZGlyZWN0aXZlJztcbmltcG9ydCB7IEZhY2Vib29rUGFnZUNvbXBvbmVudCB9IGZyb20gJy4vcGFnZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgRmFjZWJvb2tMaWtlQ29tcG9uZW50IH0gZnJvbSAnLi9saWtlLmNvbXBvbmVudCc7XG5cbkBOZ01vZHVsZSh7XG4gIGltcG9ydHM6IFtcbiAgICBDb21tb25Nb2R1bGUsXG4gIF0sXG4gIGRlY2xhcmF0aW9uczogW1xuICAgIEZhY2Vib29rUGFyc2VEaXJlY3RpdmUsXG4gICAgRmFjZWJvb2tQYWdlQ29tcG9uZW50LFxuICAgIEZhY2Vib29rTGlrZUNvbXBvbmVudCxcbiAgXSxcbiAgZXhwb3J0czogW1xuICAgIEZhY2Vib29rUGFyc2VEaXJlY3RpdmUsXG4gICAgRmFjZWJvb2tQYWdlQ29tcG9uZW50LFxuICAgIEZhY2Vib29rTGlrZUNvbXBvbmVudCxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgRmFjZWJvb2tNb2R1bGUgeyB9XG4iXSwibmFtZXMiOlsidHNsaWJfMS5fX2V4dGVu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