@fullcalendar/angular
Version:
The official Angular component for FullCalendar
198 lines • 30.6 kB
JavaScript
import { Component, ContentChild, Input, ViewEncapsulation, } from '@angular/core';
import { Calendar } from '@fullcalendar/core';
import { CustomRenderingStore } from '@fullcalendar/core/internal';
import { OPTION_INPUT_NAMES, OPTION_IS_DEEP } from './options';
import { deepCopy, shallowCopy, mapHash } from './utils/obj';
import { deepEqual } from './utils/fast-deep-equal';
import * as i0 from "@angular/core";
import * as i1 from "./utils/offscreen-fragment.component";
import * as i2 from "./utils/transport-container.component";
import * as i3 from "@angular/common";
export class FullCalendarComponent {
constructor(element, changeDetector) {
this.element = element;
this.calendar = null;
this.optionSnapshot = {}; // for diffing
this.customRenderingMap = new Map();
this.templateMap = {};
const customRenderingStore = new CustomRenderingStore();
customRenderingStore.subscribe((customRenderingMap) => {
this.customRenderingMap = customRenderingMap;
this.customRenderingArray = undefined; // clear cache
changeDetector.detectChanges();
});
this.handleCustomRendering = customRenderingStore.handle.bind(customRenderingStore);
this.templateMap = this; // alias to this
}
ngAfterViewInit() {
const { deepChangeDetection } = this;
const options = {
...this.options,
...this.buildInputOptions(),
};
// initialize snapshot
this.optionSnapshot = mapHash(options, (optionVal, optionName) => ((deepChangeDetection && OPTION_IS_DEEP[optionName])
? deepCopy(optionVal)
: optionVal));
this.calendar = new Calendar(this.element.nativeElement, {
...options,
...this.buildExtraOptions(),
});
this.calendar.render();
}
/*
allows us to manually detect complex input changes, internal mutations to certain options.
called before ngOnChanges. called much more often than ngOnChanges.
*/
ngDoCheck() {
if (this.calendar) { // not the initial render
const { deepChangeDetection, optionSnapshot } = this;
const newOptions = {
...this.options,
...this.buildInputOptions(),
};
const newProcessedOptions = {};
let anyChanges = false;
// detect adds and updates (and update snapshot)
for (const optionName in newOptions) {
if (newOptions.hasOwnProperty(optionName)) {
let optionVal = newOptions[optionName];
if (deepChangeDetection && OPTION_IS_DEEP[optionName]) {
if (!deepEqual(optionSnapshot[optionName], optionVal)) {
optionSnapshot[optionName] = deepCopy(optionVal);
anyChanges = true;
// trick FC into knowing about a nested change.
// TODO: future versions won't need this.
// can't use the previously-made deep copy because it blows away prototype-association.
optionVal = shallowCopy(optionVal);
}
}
else {
if (optionSnapshot[optionName] !== optionVal) {
optionSnapshot[optionName] = optionVal;
anyChanges = true;
}
}
newProcessedOptions[optionName] = optionVal;
}
}
const oldOptionNames = Object.keys(optionSnapshot);
// detect removals (and update snapshot)
for (const optionName of oldOptionNames) {
if (!(optionName in newOptions)) { // doesn't exist in new options?
delete optionSnapshot[optionName];
anyChanges = true;
}
}
if (anyChanges) {
this.calendar.pauseRendering();
this.calendar.resetOptions({
...newProcessedOptions,
...this.buildExtraOptions(),
});
}
}
}
ngAfterContentChecked() {
if (this.calendar) { // too defensive?
this.calendar.resumeRendering();
}
}
ngOnDestroy() {
if (this.calendar) { // too defensive?
this.calendar.destroy();
this.calendar = null;
}
}
get customRenderings() {
return this.customRenderingArray ||
(this.customRenderingArray = [...this.customRenderingMap.values()]);
}
getApi() {
return this.calendar;
}
buildInputOptions() {
const options = {};
for (const inputName of OPTION_INPUT_NAMES) {
const inputValue = this[inputName];
if (inputValue != null) { // exclude both null and undefined
options[inputName] = inputValue;
}
}
return options;
}
buildExtraOptions() {
return {
handleCustomRendering: this.handleCustomRendering,
customRenderingMetaMap: this.templateMap,
customRenderingReplacesEl: true,
};
}
// for `trackBy` in loop
trackCustomRendering(index, customRendering) {
return customRendering.id;
}
}
FullCalendarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FullCalendarComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
FullCalendarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: FullCalendarComponent, selector: "full-calendar", inputs: { options: "options", deepChangeDetection: "deepChangeDetection", events: "events", eventSources: "eventSources", resources: "resources" }, queries: [{ propertyName: "dayHeaderContent", first: true, predicate: ["dayHeaderContent"], descendants: true, static: true }, { propertyName: "dayCellContent", first: true, predicate: ["dayCellContent"], descendants: true, static: true }, { propertyName: "weekNumberContent", first: true, predicate: ["weekNumberContent"], descendants: true, static: true }, { propertyName: "nowIndicatorContent", first: true, predicate: ["nowIndicatorContent"], descendants: true, static: true }, { propertyName: "eventContent", first: true, predicate: ["eventContent"], descendants: true, static: true }, { propertyName: "slotLaneContent", first: true, predicate: ["slotLaneContent"], descendants: true, static: true }, { propertyName: "slotLabelContent", first: true, predicate: ["slotLabelContent"], descendants: true, static: true }, { propertyName: "allDayContent", first: true, predicate: ["allDayContent"], descendants: true, static: true }, { propertyName: "moreLinkContent", first: true, predicate: ["moreLinkContent"], descendants: true, static: true }, { propertyName: "noEventsContent", first: true, predicate: ["noEventsContent"], descendants: true, static: true }, { propertyName: "resourceAreaHeaderContent", first: true, predicate: ["resourceAreaHeaderContent"], descendants: true, static: true }, { propertyName: "resourceGroupLabelContent", first: true, predicate: ["resourceGroupLabelContent"], descendants: true, static: true }, { propertyName: "resourceLabelContent", first: true, predicate: ["resourceLabelContent"], descendants: true, static: true }, { propertyName: "resourceLaneContent", first: true, predicate: ["resourceLaneContent"], descendants: true, static: true }, { propertyName: "resourceGroupLaneContent", first: true, predicate: ["resourceGroupLaneContent"], descendants: true, static: true }], ngImport: i0, template: "<offscreen-fragment>\n <transport-container *ngFor=\"let customRendering of customRenderings; trackBy:trackCustomRendering\"\n [inPlaceOf]=\"customRendering.containerEl\"\n [reportEl]=\"customRendering.reportNewContainerEl\"\n [elTag]=\"customRendering.elTag\"\n [elClasses]=\"customRendering.elClasses\"\n [elStyle]=\"customRendering.elStyle\"\n [elAttrs]=\"customRendering.elAttrs\"\n [template]=\"templateMap[customRendering.generatorName]!\"\n [renderProps]=\"customRendering.renderProps\"\n ></transport-container>\n</offscreen-fragment>\n", components: [{ type: i1.OffscreenFragmentComponent, selector: "offscreen-fragment" }, { type: i2.TransportContainerComponent, selector: "transport-container", inputs: ["inPlaceOf", "reportEl", "elTag", "elClasses", "elStyle", "elAttrs", "template", "renderProps"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], encapsulation: i0.ViewEncapsulation.None });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FullCalendarComponent, decorators: [{
type: Component,
args: [{ selector: 'full-calendar', encapsulation: ViewEncapsulation.None // the styles are root-level, not scoped within the component
, template: "<offscreen-fragment>\n <transport-container *ngFor=\"let customRendering of customRenderings; trackBy:trackCustomRendering\"\n [inPlaceOf]=\"customRendering.containerEl\"\n [reportEl]=\"customRendering.reportNewContainerEl\"\n [elTag]=\"customRendering.elTag\"\n [elClasses]=\"customRendering.elClasses\"\n [elStyle]=\"customRendering.elStyle\"\n [elAttrs]=\"customRendering.elAttrs\"\n [template]=\"templateMap[customRendering.generatorName]!\"\n [renderProps]=\"customRendering.renderProps\"\n ></transport-container>\n</offscreen-fragment>\n" }]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { options: [{
type: Input
}], deepChangeDetection: [{
type: Input
}], events: [{
type: Input
}], eventSources: [{
type: Input
}], resources: [{
type: Input
}], dayHeaderContent: [{
type: ContentChild,
args: ['dayHeaderContent', { static: true }]
}], dayCellContent: [{
type: ContentChild,
args: ['dayCellContent', { static: true }]
}], weekNumberContent: [{
type: ContentChild,
args: ['weekNumberContent', { static: true }]
}], nowIndicatorContent: [{
type: ContentChild,
args: ['nowIndicatorContent', { static: true }]
}], eventContent: [{
type: ContentChild,
args: ['eventContent', { static: true }]
}], slotLaneContent: [{
type: ContentChild,
args: ['slotLaneContent', { static: true }]
}], slotLabelContent: [{
type: ContentChild,
args: ['slotLabelContent', { static: true }]
}], allDayContent: [{
type: ContentChild,
args: ['allDayContent', { static: true }]
}], moreLinkContent: [{
type: ContentChild,
args: ['moreLinkContent', { static: true }]
}], noEventsContent: [{
type: ContentChild,
args: ['noEventsContent', { static: true }]
}], resourceAreaHeaderContent: [{
type: ContentChild,
args: ['resourceAreaHeaderContent', { static: true }]
}], resourceGroupLabelContent: [{
type: ContentChild,
args: ['resourceGroupLabelContent', { static: true }]
}], resourceLabelContent: [{
type: ContentChild,
args: ['resourceLabelContent', { static: true }]
}], resourceLaneContent: [{
type: ContentChild,
args: ['resourceLaneContent', { static: true }]
}], resourceGroupLaneContent: [{
type: ContentChild,
args: ['resourceGroupLaneContent', { static: true }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVsbC1jYWxlbmRhci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9saWIvc3JjL2Z1bGwtY2FsZW5kYXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vbGliL3NyYy9mdWxsLWNhbGVuZGFyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUdaLEtBQUssRUFLTCxpQkFBaUIsR0FFbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFFBQVEsRUFBbUIsTUFBTSxvQkFBb0IsQ0FBQztBQUMvRCxPQUFPLEVBQW1CLG9CQUFvQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDcEYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGNBQWMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUUvRCxPQUFPLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDN0QsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDOzs7OztBQU9wRCxNQUFNLE9BQU8scUJBQXFCO0lBc0NoQyxZQUNVLE9BQW1CLEVBQzNCLGNBQWlDO1FBRHpCLFlBQU8sR0FBUCxPQUFPLENBQVk7UUFSckIsYUFBUSxHQUFvQixJQUFJLENBQUM7UUFDakMsbUJBQWMsR0FBd0IsRUFBRSxDQUFDLENBQUMsY0FBYztRQUV4RCx1QkFBa0IsR0FBRyxJQUFJLEdBQUcsRUFBZ0MsQ0FBQTtRQUU3RCxnQkFBVyxHQUFpRCxFQUFFLENBQUE7UUFNbkUsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLG9CQUFvQixFQUFFLENBQUM7UUFFeEQsb0JBQW9CLENBQUMsU0FBUyxDQUFDLENBQUMsa0JBQWtCLEVBQUUsRUFBRTtZQUNwRCxJQUFJLENBQUMsa0JBQWtCLEdBQUcsa0JBQWtCLENBQUM7WUFDN0MsSUFBSSxDQUFDLG9CQUFvQixHQUFHLFNBQVMsQ0FBQyxDQUFDLGNBQWM7WUFDckQsY0FBYyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLHFCQUFxQixHQUFHLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUNwRixJQUFJLENBQUMsV0FBVyxHQUFHLElBQVcsQ0FBQyxDQUFDLGdCQUFnQjtJQUNsRCxDQUFDO0lBRUQsZUFBZTtRQUNiLE1BQU0sRUFBRSxtQkFBbUIsRUFBRSxHQUFHLElBQUksQ0FBQztRQUNyQyxNQUFNLE9BQU8sR0FBRztZQUNkLEdBQUcsSUFBSSxDQUFDLE9BQU87WUFDZixHQUFHLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtTQUM1QixDQUFDO1FBRUYsc0JBQXNCO1FBQ3RCLElBQUksQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLFNBQWMsRUFBRSxVQUFrQixFQUFFLEVBQUUsQ0FBQyxDQUM3RSxDQUFDLG1CQUFtQixJQUFJLGNBQWMsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNqRCxDQUFDLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQztZQUNyQixDQUFDLENBQUMsU0FBUyxDQUNkLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUU7WUFDdkQsR0FBRyxPQUFPO1lBQ1YsR0FBRyxJQUFJLENBQUMsaUJBQWlCLEVBQUU7U0FDNUIsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRUQ7OztNQUdFO0lBQ0YsU0FBUztRQUNQLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFFLHlCQUF5QjtZQUM1QyxNQUFNLEVBQUUsbUJBQW1CLEVBQUUsY0FBYyxFQUFFLEdBQUcsSUFBSSxDQUFDO1lBQ3JELE1BQU0sVUFBVSxHQUFHO2dCQUNqQixHQUFHLElBQUksQ0FBQyxPQUFPO2dCQUNmLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixFQUFFO2FBQzVCLENBQUM7WUFDRixNQUFNLG1CQUFtQixHQUF3QixFQUFFLENBQUM7WUFDcEQsSUFBSSxVQUFVLEdBQUcsS0FBSyxDQUFDO1lBRXZCLGdEQUFnRDtZQUNoRCxLQUFLLE1BQU0sVUFBVSxJQUFJLFVBQVUsRUFBRTtnQkFDbkMsSUFBSSxVQUFVLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxFQUFFO29CQUN6QyxJQUFJLFNBQVMsR0FBRyxVQUFVLENBQUMsVUFBbUMsQ0FBQyxDQUFDO29CQUVoRSxJQUFJLG1CQUFtQixJQUFJLGNBQWMsQ0FBQyxVQUFVLENBQUMsRUFBRTt3QkFDckQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLEVBQUUsU0FBUyxDQUFDLEVBQUU7NEJBQ3JELGNBQWMsQ0FBQyxVQUFVLENBQUMsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUM7NEJBQ2pELFVBQVUsR0FBRyxJQUFJLENBQUM7NEJBRWxCLCtDQUErQzs0QkFDL0MseUNBQXlDOzRCQUN6Qyx1RkFBdUY7NEJBQ3ZGLFNBQVMsR0FBRyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUM7eUJBQ3BDO3FCQUNGO3lCQUFNO3dCQUNMLElBQUksY0FBYyxDQUFDLFVBQVUsQ0FBQyxLQUFLLFNBQVMsRUFBRTs0QkFDNUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxHQUFHLFNBQVMsQ0FBQzs0QkFDdkMsVUFBVSxHQUFHLElBQUksQ0FBQzt5QkFDbkI7cUJBQ0Y7b0JBRUQsbUJBQW1CLENBQUMsVUFBVSxDQUFDLEdBQUcsU0FBUyxDQUFDO2lCQUM3QzthQUNGO1lBRUQsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUVuRCx3Q0FBd0M7WUFDeEMsS0FBSyxNQUFNLFVBQVUsSUFBSSxjQUFjLEVBQUU7Z0JBQ3ZDLElBQUksQ0FBQyxDQUFDLFVBQVUsSUFBSSxVQUFVLENBQUMsRUFBRSxFQUFFLGdDQUFnQztvQkFDakUsT0FBTyxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQ2xDLFVBQVUsR0FBRyxJQUFJLENBQUM7aUJBQ25CO2FBQ0Y7WUFFRCxJQUFJLFVBQVUsRUFBRTtnQkFDZCxJQUFJLENBQUMsUUFBUSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUMvQixJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQztvQkFDekIsR0FBRyxtQkFBbUI7b0JBQ3RCLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixFQUFFO2lCQUM1QixDQUFDLENBQUM7YUFDSjtTQUNGO0lBQ0gsQ0FBQztJQUVELHFCQUFxQjtRQUNuQixJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxpQkFBaUI7WUFDcEMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxlQUFlLEVBQUUsQ0FBQztTQUNqQztJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsaUJBQWlCO1lBQ3BDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDeEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7U0FDdEI7SUFDSCxDQUFDO0lBRUQsSUFBSSxnQkFBZ0I7UUFDbEIsT0FBTyxJQUFJLENBQUMsb0JBQW9CO1lBQzlCLENBQUMsSUFBSSxDQUFDLG9CQUFvQixHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFFTSxNQUFNO1FBQ1gsT0FBTyxJQUFJLENBQUMsUUFBUyxDQUFDO0lBQ3hCLENBQUM7SUFFTyxpQkFBaUI7UUFDdkIsTUFBTSxPQUFPLEdBQW9CLEVBQUUsQ0FBQTtRQUVuQyxLQUFLLE1BQU0sU0FBUyxJQUFJLGtCQUFrQixFQUFFO1lBQzFDLE1BQU0sVUFBVSxHQUFJLElBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUU1QyxJQUFJLFVBQVUsSUFBSSxJQUFJLEVBQUUsRUFBRSxrQ0FBa0M7Z0JBQ3pELE9BQWUsQ0FBQyxTQUFTLENBQUMsR0FBRyxVQUFVLENBQUM7YUFDMUM7U0FDRjtRQUVELE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFTyxpQkFBaUI7UUFDdkIsT0FBTztZQUNMLHFCQUFxQixFQUFFLElBQUksQ0FBQyxxQkFBcUI7WUFDakQsc0JBQXNCLEVBQUUsSUFBSSxDQUFDLFdBQVc7WUFDeEMseUJBQXlCLEVBQUUsSUFBSTtTQUNoQyxDQUFDO0lBQ0osQ0FBQztJQUVELHdCQUF3QjtJQUN4QixvQkFBb0IsQ0FBQyxLQUFhLEVBQUUsZUFBcUM7UUFDdkUsT0FBTyxlQUFlLENBQUMsRUFBRSxDQUFBO0lBQzNCLENBQUM7O21IQXRMVSxxQkFBcUI7dUdBQXJCLHFCQUFxQixpK0RDekJsQyw0akJBWUE7NEZEYWEscUJBQXFCO2tCQUxqQyxTQUFTOytCQUNFLGVBQWUsaUJBRVYsaUJBQWlCLENBQUMsSUFBSSxDQUFDLDZEQUE2RDs7aUlBRzFGLE9BQU87c0JBQWYsS0FBSztnQkFDRyxtQkFBbUI7c0JBQTNCLEtBQUs7Z0JBTUcsTUFBTTtzQkFBZCxLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFLOEMsZ0JBQWdCO3NCQUFuRSxZQUFZO3VCQUFDLGtCQUFrQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFDQSxjQUFjO3NCQUEvRCxZQUFZO3VCQUFDLGdCQUFnQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFDSyxpQkFBaUI7c0JBQXJFLFlBQVk7dUJBQUMsbUJBQW1CLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNJLG1CQUFtQjtzQkFBekUsWUFBWTt1QkFBQyxxQkFBcUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBQ0wsWUFBWTtzQkFBM0QsWUFBWTt1QkFBQyxjQUFjLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNLLGVBQWU7c0JBQWpFLFlBQVk7dUJBQUMsaUJBQWlCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNHLGdCQUFnQjtzQkFBbkUsWUFBWTt1QkFBQyxrQkFBa0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBQ0QsYUFBYTtzQkFBN0QsWUFBWTt1QkFBQyxlQUFlLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNJLGVBQWU7c0JBQWpFLFlBQVk7dUJBQUMsaUJBQWlCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNFLGVBQWU7c0JBQWpFLFlBQVk7dUJBQUMsaUJBQWlCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNZLHlCQUF5QjtzQkFBckYsWUFBWTt1QkFBQywyQkFBMkIsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBQ0UseUJBQXlCO3NCQUFyRixZQUFZO3VCQUFDLDJCQUEyQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFDSCxvQkFBb0I7c0JBQTNFLFlBQVk7dUJBQUMsc0JBQXNCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNDLG1CQUFtQjtzQkFBekUsWUFBWTt1QkFBQyxxQkFBcUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBQ08sd0JBQXdCO3NCQUFuRixZQUFZO3VCQUFDLDBCQUEwQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkLFxuICBUZW1wbGF0ZVJlZixcbiAgRWxlbWVudFJlZixcbiAgSW5wdXQsXG4gIEFmdGVyVmlld0luaXQsXG4gIERvQ2hlY2ssXG4gIEFmdGVyQ29udGVudENoZWNrZWQsXG4gIE9uRGVzdHJveSxcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG4gIENoYW5nZURldGVjdG9yUmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENhbGVuZGFyLCBDYWxlbmRhck9wdGlvbnMgfSBmcm9tICdAZnVsbGNhbGVuZGFyL2NvcmUnO1xuaW1wb3J0IHsgQ3VzdG9tUmVuZGVyaW5nLCBDdXN0b21SZW5kZXJpbmdTdG9yZSB9IGZyb20gJ0BmdWxsY2FsZW5kYXIvY29yZS9pbnRlcm5hbCc7XG5pbXBvcnQgeyBPUFRJT05fSU5QVVRfTkFNRVMsIE9QVElPTl9JU19ERUVQIH0gZnJvbSAnLi9vcHRpb25zJztcbmltcG9ydCB7IENhbGVuZGFyT3B0aW9uLCBDYWxlbmRhclRlbXBsYXRlUmVmIH0gZnJvbSAnLi9wcml2YXRlLXR5cGVzJztcbmltcG9ydCB7IGRlZXBDb3B5LCBzaGFsbG93Q29weSwgbWFwSGFzaCB9IGZyb20gJy4vdXRpbHMvb2JqJztcbmltcG9ydCB7IGRlZXBFcXVhbCB9IGZyb20gJy4vdXRpbHMvZmFzdC1kZWVwLWVxdWFsJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZnVsbC1jYWxlbmRhcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9mdWxsLWNhbGVuZGFyLmNvbXBvbmVudC5odG1sJyxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSAvLyB0aGUgc3R5bGVzIGFyZSByb290LWxldmVsLCBub3Qgc2NvcGVkIHdpdGhpbiB0aGUgY29tcG9uZW50XG59KVxuZXhwb3J0IGNsYXNzIEZ1bGxDYWxlbmRhckNvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIERvQ2hlY2ssIEFmdGVyQ29udGVudENoZWNrZWQsIE9uRGVzdHJveSB7XG4gIEBJbnB1dCgpIG9wdGlvbnM/OiBDYWxlbmRhck9wdGlvbnM7XG4gIEBJbnB1dCgpIGRlZXBDaGFuZ2VEZXRlY3Rpb24/OiBib29sZWFuO1xuXG4gIC8qXG4gIE9wdGlvbnMgYXMgaW5kaXZpZHVhbCBJbnB1dHNcbiAgTk9URToga2VlcCBpbiBzeW5jIHdpdGggT1BUSU9OX0lOUFVUX05BTUVTXG4gICovXG4gIEBJbnB1dCgpIGV2ZW50cz86IENhbGVuZGFyT3B0aW9uPCdldmVudHMnPiB8IG51bGwgfCB1bmRlZmluZWQ7XG4gIEBJbnB1dCgpIGV2ZW50U291cmNlcz86IENhbGVuZGFyT3B0aW9uPCdldmVudFNvdXJjZXMnPiB8IG51bGwgfCB1bmRlZmluZWQ7XG4gIEBJbnB1dCgpIHJlc291cmNlcz86IENhbGVuZGFyT3B0aW9uPCdyZXNvdXJjZXMnPiB8IG51bGwgfCB1bmRlZmluZWQ7XG5cbiAgLypcbiAgVGVtcGxhdGVzXG4gICovXG4gIEBDb250ZW50Q2hpbGQoJ2RheUhlYWRlckNvbnRlbnQnLCB7IHN0YXRpYzogdHJ1ZSB9KSBkYXlIZWFkZXJDb250ZW50PzogQ2FsZW5kYXJUZW1wbGF0ZVJlZjwnZGF5SGVhZGVyQ29udGVudCc+O1xuICBAQ29udGVudENoaWxkKCdkYXlDZWxsQ29udGVudCcsIHsgc3RhdGljOiB0cnVlIH0pIGRheUNlbGxDb250ZW50PzogQ2FsZW5kYXJUZW1wbGF0ZVJlZjwnZGF5Q2VsbENvbnRlbnQnPjtcbiAgQENvbnRlbnRDaGlsZCgnd2Vla051bWJlckNvbnRlbnQnLCB7IHN0YXRpYzogdHJ1ZSB9KSB3ZWVrTnVtYmVyQ29udGVudD86IENhbGVuZGFyVGVtcGxhdGVSZWY8J3dlZWtOdW1iZXJDb250ZW50Jz47XG4gIEBDb250ZW50Q2hpbGQoJ25vd0luZGljYXRvckNvbnRlbnQnLCB7IHN0YXRpYzogdHJ1ZSB9KSBub3dJbmRpY2F0b3JDb250ZW50PzogQ2FsZW5kYXJUZW1wbGF0ZVJlZjwnbm93SW5kaWNhdG9yQ29udGVudCc+O1xuICBAQ29udGVudENoaWxkKCdldmVudENvbnRlbnQnLCB7IHN0YXRpYzogdHJ1ZSB9KSBldmVudENvbnRlbnQ/OiBDYWxlbmRhclRlbXBsYXRlUmVmPCdldmVudENvbnRlbnQnPjtcbiAgQENvbnRlbnRDaGlsZCgnc2xvdExhbmVDb250ZW50JywgeyBzdGF0aWM6IHRydWUgfSkgc2xvdExhbmVDb250ZW50PzogQ2FsZW5kYXJUZW1wbGF0ZVJlZjwnc2xvdExhbmVDb250ZW50Jz47XG4gIEBDb250ZW50Q2hpbGQoJ3Nsb3RMYWJlbENvbnRlbnQnLCB7IHN0YXRpYzogdHJ1ZSB9KSBzbG90TGFiZWxDb250ZW50PzogQ2FsZW5kYXJUZW1wbGF0ZVJlZjwnc2xvdExhYmVsQ29udGVudCc+O1xuICBAQ29udGVudENoaWxkKCdhbGxEYXlDb250ZW50JywgeyBzdGF0aWM6IHRydWUgfSkgYWxsRGF5Q29udGVudD86IENhbGVuZGFyVGVtcGxhdGVSZWY8J2FsbERheUNvbnRlbnQnPjtcbiAgQENvbnRlbnRDaGlsZCgnbW9yZUxpbmtDb250ZW50JywgeyBzdGF0aWM6IHRydWUgfSkgbW9yZUxpbmtDb250ZW50PzogQ2FsZW5kYXJUZW1wbGF0ZVJlZjwnbW9yZUxpbmtDb250ZW50Jz47XG4gIEBDb250ZW50Q2hpbGQoJ25vRXZlbnRzQ29udGVudCcsIHsgc3RhdGljOiB0cnVlIH0pIG5vRXZlbnRzQ29udGVudD86IENhbGVuZGFyVGVtcGxhdGVSZWY8J25vRXZlbnRzQ29udGVudCc+O1xuICBAQ29udGVudENoaWxkKCdyZXNvdXJjZUFyZWFIZWFkZXJDb250ZW50JywgeyBzdGF0aWM6IHRydWUgfSkgcmVzb3VyY2VBcmVhSGVhZGVyQ29udGVudD86IENhbGVuZGFyVGVtcGxhdGVSZWY8J3Jlc291cmNlQXJlYUhlYWRlckNvbnRlbnQnPjtcbiAgQENvbnRlbnRDaGlsZCgncmVzb3VyY2VHcm91cExhYmVsQ29udGVudCcsIHsgc3RhdGljOiB0cnVlIH0pIHJlc291cmNlR3JvdXBMYWJlbENvbnRlbnQ/OiBDYWxlbmRhclRlbXBsYXRlUmVmPCdyZXNvdXJjZUdyb3VwTGFiZWxDb250ZW50Jz47XG4gIEBDb250ZW50Q2hpbGQoJ3Jlc291cmNlTGFiZWxDb250ZW50JywgeyBzdGF0aWM6IHRydWUgfSkgcmVzb3VyY2VMYWJlbENvbnRlbnQ/OiBDYWxlbmRhclRlbXBsYXRlUmVmPCdyZXNvdXJjZUxhYmVsQ29udGVudCc+O1xuICBAQ29udGVudENoaWxkKCdyZXNvdXJjZUxhbmVDb250ZW50JywgeyBzdGF0aWM6IHRydWUgfSkgcmVzb3VyY2VMYW5lQ29udGVudD86IENhbGVuZGFyVGVtcGxhdGVSZWY8J3Jlc291cmNlTGFuZUNvbnRlbnQnPjtcbiAgQENvbnRlbnRDaGlsZCgncmVzb3VyY2VHcm91cExhbmVDb250ZW50JywgeyBzdGF0aWM6IHRydWUgfSkgcmVzb3VyY2VHcm91cExhbmVDb250ZW50PzogQ2FsZW5kYXJUZW1wbGF0ZVJlZjwncmVzb3VyY2VHcm91cExhbmVDb250ZW50Jz47XG5cbiAgcHJpdmF0ZSBjYWxlbmRhcjogQ2FsZW5kYXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBvcHRpb25TbmFwc2hvdDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9OyAvLyBmb3IgZGlmZmluZ1xuICBwcml2YXRlIGhhbmRsZUN1c3RvbVJlbmRlcmluZzogKGN1c3RvbVJlbmRlcmluZzogQ3VzdG9tUmVuZGVyaW5nPGFueT4pID0+IHZvaWRcbiAgcHJpdmF0ZSBjdXN0b21SZW5kZXJpbmdNYXAgPSBuZXcgTWFwPHN0cmluZywgQ3VzdG9tUmVuZGVyaW5nPGFueT4+KClcbiAgcHJpdmF0ZSBjdXN0b21SZW5kZXJpbmdBcnJheT86IEN1c3RvbVJlbmRlcmluZzxhbnk+W11cbiAgcHVibGljIHRlbXBsYXRlTWFwOiB7IFt0ZW1wbGF0ZU5hbWU6IHN0cmluZ106IFRlbXBsYXRlUmVmPGFueT4gfSA9IHt9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBlbGVtZW50OiBFbGVtZW50UmVmLFxuICAgIGNoYW5nZURldGVjdG9yOiBDaGFuZ2VEZXRlY3RvclJlZlxuICApIHtcbiAgICBjb25zdCBjdXN0b21SZW5kZXJpbmdTdG9yZSA9IG5ldyBDdXN0b21SZW5kZXJpbmdTdG9yZSgpO1xuXG4gICAgY3VzdG9tUmVuZGVyaW5nU3RvcmUuc3Vic2NyaWJlKChjdXN0b21SZW5kZXJpbmdNYXApID0+IHtcbiAgICAgIHRoaXMuY3VzdG9tUmVuZGVyaW5nTWFwID0gY3VzdG9tUmVuZGVyaW5nTWFwO1xuICAgICAgdGhpcy5jdXN0b21SZW5kZXJpbmdBcnJheSA9IHVuZGVmaW5lZDsgLy8gY2xlYXIgY2FjaGVcbiAgICAgIGNoYW5nZURldGVjdG9yLmRldGVjdENoYW5nZXMoKTtcbiAgICB9KTtcblxuICAgIHRoaXMuaGFuZGxlQ3VzdG9tUmVuZGVyaW5nID0gY3VzdG9tUmVuZGVyaW5nU3RvcmUuaGFuZGxlLmJpbmQoY3VzdG9tUmVuZGVyaW5nU3RvcmUpO1xuICAgIHRoaXMudGVtcGxhdGVNYXAgPSB0aGlzIGFzIGFueTsgLy8gYWxpYXMgdG8gdGhpc1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIGNvbnN0IHsgZGVlcENoYW5nZURldGVjdGlvbiB9ID0gdGhpcztcbiAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgLi4udGhpcy5vcHRpb25zLFxuICAgICAgLi4udGhpcy5idWlsZElucHV0T3B0aW9ucygpLFxuICAgIH07XG5cbiAgICAvLyBpbml0aWFsaXplIHNuYXBzaG90XG4gICAgdGhpcy5vcHRpb25TbmFwc2hvdCA9IG1hcEhhc2gob3B0aW9ucywgKG9wdGlvblZhbDogYW55LCBvcHRpb25OYW1lOiBzdHJpbmcpID0+IChcbiAgICAgIChkZWVwQ2hhbmdlRGV0ZWN0aW9uICYmIE9QVElPTl9JU19ERUVQW29wdGlvbk5hbWVdKVxuICAgICAgICA/IGRlZXBDb3B5KG9wdGlvblZhbClcbiAgICAgICAgOiBvcHRpb25WYWxcbiAgICApKTtcblxuICAgIHRoaXMuY2FsZW5kYXIgPSBuZXcgQ2FsZW5kYXIodGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQsIHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAuLi50aGlzLmJ1aWxkRXh0cmFPcHRpb25zKCksXG4gICAgfSk7XG4gICAgdGhpcy5jYWxlbmRhci5yZW5kZXIoKTtcbiAgfVxuXG4gIC8qXG4gIGFsbG93cyB1cyB0byBtYW51YWxseSBkZXRlY3QgY29tcGxleCBpbnB1dCBjaGFuZ2VzLCBpbnRlcm5hbCBtdXRhdGlvbnMgdG8gY2VydGFpbiBvcHRpb25zLlxuICBjYWxsZWQgYmVmb3JlIG5nT25DaGFuZ2VzLiBjYWxsZWQgbXVjaCBtb3JlIG9mdGVuIHRoYW4gbmdPbkNoYW5nZXMuXG4gICovXG4gIG5nRG9DaGVjaygpIHtcbiAgICBpZiAodGhpcy5jYWxlbmRhcikgeyAvLyBub3QgdGhlIGluaXRpYWwgcmVuZGVyXG4gICAgICBjb25zdCB7IGRlZXBDaGFuZ2VEZXRlY3Rpb24sIG9wdGlvblNuYXBzaG90IH0gPSB0aGlzO1xuICAgICAgY29uc3QgbmV3T3B0aW9ucyA9IHtcbiAgICAgICAgLi4udGhpcy5vcHRpb25zLFxuICAgICAgICAuLi50aGlzLmJ1aWxkSW5wdXRPcHRpb25zKCksXG4gICAgICB9O1xuICAgICAgY29uc3QgbmV3UHJvY2Vzc2VkT3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgICAgbGV0IGFueUNoYW5nZXMgPSBmYWxzZTtcblxuICAgICAgLy8gZGV0ZWN0IGFkZHMgYW5kIHVwZGF0ZXMgKGFuZCB1cGRhdGUgc25hcHNob3QpXG4gICAgICBmb3IgKGNvbnN0IG9wdGlvbk5hbWUgaW4gbmV3T3B0aW9ucykge1xuICAgICAgICBpZiAobmV3T3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShvcHRpb25OYW1lKSkge1xuICAgICAgICAgIGxldCBvcHRpb25WYWwgPSBuZXdPcHRpb25zW29wdGlvbk5hbWUgYXMga2V5b2YgQ2FsZW5kYXJPcHRpb25zXTtcblxuICAgICAgICAgIGlmIChkZWVwQ2hhbmdlRGV0ZWN0aW9uICYmIE9QVElPTl9JU19ERUVQW29wdGlvbk5hbWVdKSB7XG4gICAgICAgICAgICBpZiAoIWRlZXBFcXVhbChvcHRpb25TbmFwc2hvdFtvcHRpb25OYW1lXSwgb3B0aW9uVmFsKSkge1xuICAgICAgICAgICAgICBvcHRpb25TbmFwc2hvdFtvcHRpb25OYW1lXSA9IGRlZXBDb3B5KG9wdGlvblZhbCk7XG4gICAgICAgICAgICAgIGFueUNoYW5nZXMgPSB0cnVlO1xuXG4gICAgICAgICAgICAgIC8vIHRyaWNrIEZDIGludG8ga25vd2luZyBhYm91dCBhIG5lc3RlZCBjaGFuZ2UuXG4gICAgICAgICAgICAgIC8vIFRPRE86IGZ1dHVyZSB2ZXJzaW9ucyB3b24ndCBuZWVkIHRoaXMuXG4gICAgICAgICAgICAgIC8vIGNhbid0IHVzZSB0aGUgcHJldmlvdXNseS1tYWRlIGRlZXAgY29weSBiZWNhdXNlIGl0IGJsb3dzIGF3YXkgcHJvdG90eXBlLWFzc29jaWF0aW9uLlxuICAgICAgICAgICAgICBvcHRpb25WYWwgPSBzaGFsbG93Q29weShvcHRpb25WYWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAob3B0aW9uU25hcHNob3Rbb3B0aW9uTmFtZV0gIT09IG9wdGlvblZhbCkge1xuICAgICAgICAgICAgICBvcHRpb25TbmFwc2hvdFtvcHRpb25OYW1lXSA9IG9wdGlvblZhbDtcbiAgICAgICAgICAgICAgYW55Q2hhbmdlcyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbmV3UHJvY2Vzc2VkT3B0aW9uc1tvcHRpb25OYW1lXSA9IG9wdGlvblZhbDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBvbGRPcHRpb25OYW1lcyA9IE9iamVjdC5rZXlzKG9wdGlvblNuYXBzaG90KTtcblxuICAgICAgLy8gZGV0ZWN0IHJlbW92YWxzIChhbmQgdXBkYXRlIHNuYXBzaG90KVxuICAgICAgZm9yIChjb25zdCBvcHRpb25OYW1lIG9mIG9sZE9wdGlvbk5hbWVzKSB7XG4gICAgICAgIGlmICghKG9wdGlvbk5hbWUgaW4gbmV3T3B0aW9ucykpIHsgLy8gZG9lc24ndCBleGlzdCBpbiBuZXcgb3B0aW9ucz9cbiAgICAgICAgICBkZWxldGUgb3B0aW9uU25hcHNob3Rbb3B0aW9uTmFtZV07XG4gICAgICAgICAgYW55Q2hhbmdlcyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGFueUNoYW5nZXMpIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhci5wYXVzZVJlbmRlcmluZygpO1xuICAgICAgICB0aGlzLmNhbGVuZGFyLnJlc2V0T3B0aW9ucyh7XG4gICAgICAgICAgLi4ubmV3UHJvY2Vzc2VkT3B0aW9ucyxcbiAgICAgICAgICAuLi50aGlzLmJ1aWxkRXh0cmFPcHRpb25zKCksXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG5nQWZ0ZXJDb250ZW50Q2hlY2tlZCgpIHtcbiAgICBpZiAodGhpcy5jYWxlbmRhcikgeyAvLyB0b28gZGVmZW5zaXZlP1xuICAgICAgdGhpcy5jYWxlbmRhci5yZXN1bWVSZW5kZXJpbmcoKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy5jYWxlbmRhcikgeyAvLyB0b28gZGVmZW5zaXZlP1xuICAgICAgdGhpcy5jYWxlbmRhci5kZXN0cm95KCk7XG4gICAgICB0aGlzLmNhbGVuZGFyID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBnZXQgY3VzdG9tUmVuZGVyaW5ncygpOiBDdXN0b21SZW5kZXJpbmc8YW55PltdIHtcbiAgICByZXR1cm4gdGhpcy5jdXN0b21SZW5kZXJpbmdBcnJheSB8fFxuICAgICAgKHRoaXMuY3VzdG9tUmVuZGVyaW5nQXJyYXkgPSBbLi4udGhpcy5jdXN0b21SZW5kZXJpbmdNYXAudmFsdWVzKCldKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRBcGkoKTogQ2FsZW5kYXIge1xuICAgIHJldHVybiB0aGlzLmNhbGVuZGFyITtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRJbnB1dE9wdGlvbnMoKTogQ2FsZW5kYXJPcHRpb25zIHtcbiAgICBjb25zdCBvcHRpb25zOiBDYWxlbmRhck9wdGlvbnMgPSB7fVxuXG4gICAgZm9yIChjb25zdCBpbnB1dE5hbWUgb2YgT1BUSU9OX0lOUFVUX05BTUVTKSB7XG4gICAgICBjb25zdCBpbnB1dFZhbHVlID0gKHRoaXMgYXMgYW55KVtpbnB1dE5hbWVdO1xuXG4gICAgICBpZiAoaW5wdXRWYWx1ZSAhPSBudWxsKSB7IC8vIGV4Y2x1ZGUgYm90aCBudWxsIGFuZCB1bmRlZmluZWRcbiAgICAgICAgKG9wdGlvbnMgYXMgYW55KVtpbnB1dE5hbWVdID0gaW5wdXRWYWx1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3B0aW9ucztcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRFeHRyYU9wdGlvbnMoKTogQ2FsZW5kYXJPcHRpb25zIHtcbiAgICByZXR1cm4ge1xuICAgICAgaGFuZGxlQ3VzdG9tUmVuZGVyaW5nOiB0aGlzLmhhbmRsZUN1c3RvbVJlbmRlcmluZyxcbiAgICAgIGN1c3RvbVJlbmRlcmluZ01ldGFNYXA6IHRoaXMudGVtcGxhdGVNYXAsXG4gICAgICBjdXN0b21SZW5kZXJpbmdSZXBsYWNlc0VsOiB0cnVlLFxuICAgIH07XG4gIH1cblxuICAvLyBmb3IgYHRyYWNrQnlgIGluIGxvb3BcbiAgdHJhY2tDdXN0b21SZW5kZXJpbmcoaW5kZXg6IG51bWJlciwgY3VzdG9tUmVuZGVyaW5nOiBDdXN0b21SZW5kZXJpbmc8YW55Pik6IGFueSB7XG4gICAgcmV0dXJuIGN1c3RvbVJlbmRlcmluZy5pZFxuICB9XG59XG4iLCI8b2Zmc2NyZWVuLWZyYWdtZW50PlxuICA8dHJhbnNwb3J0LWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgY3VzdG9tUmVuZGVyaW5nIG9mIGN1c3RvbVJlbmRlcmluZ3M7IHRyYWNrQnk6dHJhY2tDdXN0b21SZW5kZXJpbmdcIlxuICAgIFtpblBsYWNlT2ZdPVwiY3VzdG9tUmVuZGVyaW5nLmNvbnRhaW5lckVsXCJcbiAgICBbcmVwb3J0RWxdPVwiY3VzdG9tUmVuZGVyaW5nLnJlcG9ydE5ld0NvbnRhaW5lckVsXCJcbiAgICBbZWxUYWddPVwiY3VzdG9tUmVuZGVyaW5nLmVsVGFnXCJcbiAgICBbZWxDbGFzc2VzXT1cImN1c3RvbVJlbmRlcmluZy5lbENsYXNzZXNcIlxuICAgIFtlbFN0eWxlXT1cImN1c3RvbVJlbmRlcmluZy5lbFN0eWxlXCJcbiAgICBbZWxBdHRyc109XCJjdXN0b21SZW5kZXJpbmcuZWxBdHRyc1wiXG4gICAgW3RlbXBsYXRlXT1cInRlbXBsYXRlTWFwW2N1c3RvbVJlbmRlcmluZy5nZW5lcmF0b3JOYW1lXSFcIlxuICAgIFtyZW5kZXJQcm9wc109XCJjdXN0b21SZW5kZXJpbmcucmVuZGVyUHJvcHNcIlxuICA+PC90cmFuc3BvcnQtY29udGFpbmVyPlxuPC9vZmZzY3JlZW4tZnJhZ21lbnQ+XG4iXX0=