@kushki/ng-suka
Version:
<p align="center"> <h1 align="center">Suka Components Angular</h1> <p align="center"> An Angular implementation of the Suka Design System </p> </p>
656 lines • 52.9 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import * as tslib_1 from "tslib";
import { Component, Input, Output, EventEmitter, ViewEncapsulation, ElementRef, HostListener } from '@angular/core';
import rangePlugin from './sukaRangePlugin';
import flatpickr from 'flatpickr';
import { Spanish } from 'flatpickr/dist/l10n/es.js';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { sukaFlatpickrMonthSelectPlugin } from './sukaFlatpickrMonthSelectPlugin';
var DatePicker = /** @class */ (function () {
function DatePicker(elementRef) {
var _this = this;
this.elementRef = elementRef;
/**
* Select calendar range mode
*/
this.range = false;
/**
* Format of date
*
* For reference: https://flatpickr.js.org/formatting/
*/
this.dateFormat = 'd/m/Y';
/**
* Defines if time selector should be present. Please define dateFormat accordingly. i.e.: "d/m/Y H:i"
*
* For reference: https://flatpickr.js.org/formatting/
*/
this.hasTime = false;
/**
* Disables calendar input. Useful for time picker functionality. Pair it with a time related format accordingly. i.e.: "H:i"
*/
this.noCalendar = false;
/**
* Sets the placeholder text.
*/
this.placeholder = 'dd/mm/yyyy';
/**
* Sets the pattern to follow.
*/
this.pattern = '^\\d{1,2}/\\d{1,2}/\\d{4}$';
/**
* Date picker id.
*/
this.id = "datepicker-" + DatePicker.datePickerCount++;
/**
* Set to `true` to disable the `Datepicker`
*/
this.disabled = false;
/**
* Set to `true` to display invalid state.
*/
this.invalid = false;
/**
* Skeleton state.
*/
this.skeleton = false;
/**
* Array of date picker plugins.
*/
this.plugins = [];
/**
* Emits event notifying other classes of a change.
*/
this.valueChange = new EventEmitter();
this._value = [];
this._flatpickrOptions = {
allowInput: true
};
this.flatpickrBaseOptions = {
mode: 'single',
dateFormat: 'd/m/Y',
locale: Spanish,
plugins: this.plugins,
onOpen: (/**
* @return {?}
*/
function () { _this.updateClassNames(); }),
value: this.value
};
this.flatpickrInstance = null;
this.onTouched = (/**
* @return {?}
*/
function () { });
this.propagateChange = (/**
* @param {?} _
* @return {?}
*/
function (_) { });
}
Object.defineProperty(DatePicker.prototype, "value", {
get: /**
* @return {?}
*/
function () {
return this._value;
},
/**
* Sets the value.
*/
set: /**
* Sets the value.
* @param {?} v
* @return {?}
*/
function (v) {
if (!v) {
v = [];
}
this._value = v;
},
enumerable: true,
configurable: true
});
Object.defineProperty(DatePicker.prototype, "flatpickrOptions", {
get: /**
* @return {?}
*/
function () {
/** @type {?} */
var plugins = tslib_1.__spread(this.plugins, [sukaFlatpickrMonthSelectPlugin]);
if (this.range) {
plugins.push(rangePlugin({ input: "#" + this.id + "-rangeInput", position: 'left' }));
}
return Object.assign({}, this._flatpickrOptions, this.flatpickrBaseOptions, {
mode: this.range ? 'range' : 'single',
plugins: plugins,
dateFormat: this.dateFormat,
enableTime: this.hasTime,
noCalendar: this.noCalendar,
});
},
/**
* Flatpickr options
*/
set: /**
* Flatpickr options
* @param {?} options
* @return {?}
*/
function (options) {
this._flatpickrOptions = Object.assign({}, this._flatpickrOptions, options);
},
enumerable: true,
configurable: true
});
/**
* @param {?} changes
* @return {?}
*/
DatePicker.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
if (this.isFlatpickrLoaded()) {
/** @type {?} */
var dates = this.flatpickrInstance.selectedDates;
if (changes.value && this.didDateValueChange(changes.value.currentValue, changes.value.previousValue)) {
dates = changes.value.currentValue;
}
// only reset the flatpickr instance on Input changes
this.flatpickrInstance = flatpickr("#" + this.id, this.flatpickrOptions);
this.setDateValues(dates);
}
};
// because the actual view may be delayed in loading (think projection into a tab pane)
// and because we rely on a library that operates outside the Angular view of the world
// we need to keep trying to load the library, until the relevant DOM is actually live
// because the actual view may be delayed in loading (think projection into a tab pane)
// and because we rely on a library that operates outside the Angular view of the world
// we need to keep trying to load the library, until the relevant DOM is actually live
/**
* @return {?}
*/
DatePicker.prototype.ngAfterViewChecked =
// because the actual view may be delayed in loading (think projection into a tab pane)
// and because we rely on a library that operates outside the Angular view of the world
// we need to keep trying to load the library, until the relevant DOM is actually live
/**
* @return {?}
*/
function () {
if (!this.isFlatpickrLoaded()) {
this.flatpickrInstance = flatpickr("#" + this.id, this.flatpickrOptions);
// if (and only if) the initialization succeeded, we can set the date values
if (this.isFlatpickrLoaded()) {
if (this.value.length > 0) {
this.setDateValues(this.value);
}
}
}
};
/**
* @return {?}
*/
DatePicker.prototype.onFocus = /**
* @return {?}
*/
function () {
this.onTouched();
};
/**
* Writes a value from the model to the component. Expects the value to be `null` or `(Date | string)[]`
* @param value value received from the model
*/
/**
* Writes a value from the model to the component. Expects the value to be `null` or `(Date | string)[]`
* @param {?} value value received from the model
* @return {?}
*/
DatePicker.prototype.writeValue = /**
* Writes a value from the model to the component. Expects the value to be `null` or `(Date | string)[]`
* @param {?} value value received from the model
* @return {?}
*/
function (value) {
this.value = value;
if (this.isFlatpickrLoaded() && this.flatpickrInstance.config) {
this.setDateValues(this.value);
}
};
/**
* @param {?} fn
* @return {?}
*/
DatePicker.prototype.registerOnChange = /**
* @param {?} fn
* @return {?}
*/
function (fn) {
this.propagateChange = fn;
};
/**
* @param {?} fn
* @return {?}
*/
DatePicker.prototype.registerOnTouched = /**
* @param {?} fn
* @return {?}
*/
function (fn) {
this.onTouched = fn;
};
/**
* Cleans up our flatpickr instance
*/
/**
* Cleans up our flatpickr instance
* @return {?}
*/
DatePicker.prototype.ngOnDestroy = /**
* Cleans up our flatpickr instance
* @return {?}
*/
function () {
if (!this.isFlatpickrLoaded()) {
return;
}
this.flatpickrInstance.destroy();
};
/**
* Handles the `valueChange` event from the primary/single input
*/
/**
* Handles the `valueChange` event from the primary/single input
* @param {?} event
* @return {?}
*/
DatePicker.prototype.onValueChange = /**
* Handles the `valueChange` event from the primary/single input
* @param {?} event
* @return {?}
*/
function (event) {
if (this.isFlatpickrLoaded()) {
/** @type {?} */
var date = this.flatpickrInstance.parseDate(event, this.dateFormat);
if (this.range) {
this.setDateValues([date, this.flatpickrInstance.selectedDates[1]]);
}
else {
this.setDateValues([date]);
}
this.doSelect(this.flatpickrInstance.selectedDates);
}
};
/**
* Handles the `valueChange` event from the range input
*/
/**
* Handles the `valueChange` event from the range input
* @param {?} event
* @return {?}
*/
DatePicker.prototype.onRangeValueChange = /**
* Handles the `valueChange` event from the range input
* @param {?} event
* @return {?}
*/
function (event) {
if (this.isFlatpickrLoaded()) {
/** @type {?} */
var date = this.flatpickrInstance.parseDate(event, this.dateFormat);
this.setDateValues([this.flatpickrInstance.selectedDates[0], date]);
this.doSelect(this.flatpickrInstance.selectedDates);
}
};
/**
* Suka uses a number of specific classnames for parts of the flatpickr - this idempotent method applies them if needed.
*/
/**
* Suka uses a number of specific classnames for parts of the flatpickr - this idempotent method applies them if needed.
* @protected
* @return {?}
*/
DatePicker.prototype.updateClassNames = /**
* Suka uses a number of specific classnames for parts of the flatpickr - this idempotent method applies them if needed.
* @protected
* @return {?}
*/
function () {
var _this = this;
if (!this.elementRef) {
return;
}
// get all the possible flatpickrs in the document - we need to add classes to (potentially) all of them
/** @type {?} */
var calendarContainer = document.querySelectorAll('.flatpickr-calendar');
/** @type {?} */
var monthContainer = document.querySelectorAll('.flatpickr-month');
/** @type {?} */
var weekdaysContainer = document.querySelectorAll('.flatpickr-weekdays');
/** @type {?} */
var weekdayContainer = document.querySelectorAll('.flatpickr-weekday');
/** @type {?} */
var daysContainer = document.querySelectorAll('.flatpickr-days');
/** @type {?} */
var dayContainer = document.querySelectorAll('.flatpickr-day');
// add classes to lists of elements
/** @type {?} */
var addClassIfNotExists = (/**
* @param {?} classname
* @param {?} elementList
* @return {?}
*/
function (classname, elementList) {
Array.from(elementList).forEach((/**
* @param {?} element
* @return {?}
*/
function (element) {
if (!element.classList.contains(classname)) {
element.classList.add(classname);
}
}));
});
// add classes (but only if they don't exist, small perf win)
addClassIfNotExists('date-picker__calendar', calendarContainer);
addClassIfNotExists('date-picker__month', monthContainer);
addClassIfNotExists('date-picker__weekdays', weekdaysContainer);
addClassIfNotExists('date-picker__days', daysContainer);
// add weekday classes and format the text
Array.from(weekdayContainer).forEach((/**
* @param {?} element
* @return {?}
*/
function (element) {
element.innerHTML = element.innerHTML.replace(/\s+/g, '');
element.classList.add('date-picker__weekday');
}));
// add day classes and special case the "today" element based on `this.value`
Array.from(dayContainer).forEach((/**
* @param {?} element
* @return {?}
*/
function (element) {
element.classList.add('date-picker__day');
if (!_this.value) {
return;
}
if (element.classList.contains('today') && _this.value.length > 0) {
element.classList.add('no-border');
}
else if (element.classList.contains('today') && _this.value.length === 0) {
element.classList.remove('no-border');
}
}));
};
/**
* Applies the given date value array to both the flatpickr instance and the `input`(s)
* @param dates the date values to apply
*/
/**
* Applies the given date value array to both the flatpickr instance and the `input`(s)
* @protected
* @param {?} dates the date values to apply
* @return {?}
*/
DatePicker.prototype.setDateValues = /**
* Applies the given date value array to both the flatpickr instance and the `input`(s)
* @protected
* @param {?} dates the date values to apply
* @return {?}
*/
function (dates) {
if (this.isFlatpickrLoaded()) {
/** @type {?} */
var singleInput_1 = this.elementRef.nativeElement.querySelector("#" + this.id);
/** @type {?} */
var rangeInput_1 = this.elementRef.nativeElement.querySelector("#" + this.id + "-rangeInput");
// set the date on the instance
this.flatpickrInstance.setDate(dates);
// we can either set a date value or an empty string, so we start with an empty string
/** @type {?} */
var singleDate_1 = '';
// if date is a string, parse and format
if (typeof this.flatpickrInstance.selectedDates[0] === 'string') {
singleDate_1 = this.flatpickrInstance.parseDate(this.flatpickrInstance.selectedDates[0], this.dateFormat);
singleDate_1 = this.flatpickrInstance.formatDate(singleDate_1, this.dateFormat);
// if date is not a string we can assume it's a Date and we should format
}
else if (!!this.flatpickrInstance.selectedDates[0]) {
singleDate_1 = this.flatpickrInstance.formatDate(this.flatpickrInstance.selectedDates[0], this.dateFormat);
}
if (rangeInput_1) {
// we can either set a date value or an empty string, so we start with an empty string
/** @type {?} */
var rangeDate_1 = '';
// if date is a string, parse and format
if (typeof this.flatpickrInstance.selectedDates[1] === 'string') {
rangeDate_1 = this.flatpickrInstance.parseDate(this.flatpickrInstance.selectedDates[1].toString(), this.dateFormat);
rangeDate_1 = this.flatpickrInstance.formatDate(rangeDate_1, this.dateFormat);
// if date is not a string we can assume it's a Date and we should format
}
else if (!!this.flatpickrInstance.selectedDates[1]) {
rangeDate_1 = this.flatpickrInstance.formatDate(this.flatpickrInstance.selectedDates[1], this.dateFormat);
}
setTimeout((/**
* @return {?}
*/
function () {
// apply the values
rangeInput_1.value = rangeDate_1;
singleInput_1.value = singleDate_1;
}));
}
}
};
/**
* @protected
* @param {?} selectedValue
* @return {?}
*/
DatePicker.prototype.doSelect = /**
* @protected
* @param {?} selectedValue
* @return {?}
*/
function (selectedValue) {
this.valueChange.emit(selectedValue);
this.propagateChange(selectedValue);
};
/**
* @protected
* @param {?} currentValue
* @param {?} previousValue
* @return {?}
*/
DatePicker.prototype.didDateValueChange = /**
* @protected
* @param {?} currentValue
* @param {?} previousValue
* @return {?}
*/
function (currentValue, previousValue) {
return currentValue[0] !== previousValue[0] || currentValue[1] !== previousValue[1];
};
/**
* More advanced checking of the loaded state of flatpickr
*/
/**
* More advanced checking of the loaded state of flatpickr
* @protected
* @return {?}
*/
DatePicker.prototype.isFlatpickrLoaded = /**
* More advanced checking of the loaded state of flatpickr
* @protected
* @return {?}
*/
function () {
// cast the instance to a boolean, and some method that has to exist for the library to be loaded in this case `setDate`
return !!this.flatpickrInstance && !!this.flatpickrInstance.setDate;
};
DatePicker.datePickerCount = 0;
DatePicker.decorators = [
{ type: Component, args: [{
selector: 'suka-date-picker',
template: "\n <div class=\"form-item\">\n <div\n class=\"date-picker\"\n [ngClass]=\"{\n 'date-picker--range' : range,\n 'date-picker--single' : !range,\n 'date-picker--range-with-time' : range && hasTime,\n 'skeleton' : skeleton\n }\">\n <div class=\"date-picker-container\">\n <suka-date-picker-input\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [pattern]=\"pattern\"\n [id]=\"id\"\n [type]=\"(range ? 'range' : 'single')\"\n [hasIcon]=\"(range ? false : true)\"\n [disabled]=\"disabled\"\n [invalid]=\"invalid\"\n [invalidText]=\"invalidText\"\n [timePicker]=\"hasTime && noCalendar\"\n [skeleton]=\"skeleton\"\n (valueChange)=\"onValueChange($event)\">\n </suka-date-picker-input>\n </div>\n <div *ngIf=\"range\" class=\"date-picker-container\">\n <suka-date-picker-input\n [label]=\"rangeLabel\"\n [placeholder]=\"placeholder\"\n [pattern]=\"pattern\"\n [id]=\"id + '-rangeInput'\"\n [type]=\"(range ? 'range' : 'single')\"\n [hasIcon]=\"(range ? true : null)\"\n [disabled]=\"disabled\"\n [invalid]=\"invalid\"\n [invalidText]=\"invalidText\"\n [timePicker]=\"hasTime && noCalendar\"\n [skeleton]=\"skeleton\"\n (valueChange)=\"onRangeValueChange($event)\">\n </suka-date-picker-input>\n </div>\n </div>\n </div>\n ",
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: DatePicker,
multi: true
}
],
encapsulation: ViewEncapsulation.None
}] }
];
/** @nocollapse */
DatePicker.ctorParameters = function () { return [
{ type: ElementRef }
]; };
DatePicker.propDecorators = {
range: [{ type: Input }],
dateFormat: [{ type: Input }],
hasTime: [{ type: Input }],
noCalendar: [{ type: Input }],
label: [{ type: Input }],
rangeLabel: [{ type: Input }],
placeholder: [{ type: Input }],
pattern: [{ type: Input }],
id: [{ type: Input }],
value: [{ type: Input }],
disabled: [{ type: Input }],
invalid: [{ type: Input }],
invalidText: [{ type: Input }],
skeleton: [{ type: Input }],
plugins: [{ type: Input }],
flatpickrOptions: [{ type: Input }],
valueChange: [{ type: Output }],
onFocus: [{ type: HostListener, args: ['focusin',] }]
};
return DatePicker;
}());
export { DatePicker };
if (false) {
/**
* @type {?}
* @private
*/
DatePicker.datePickerCount;
/**
* Select calendar range mode
* @type {?}
*/
DatePicker.prototype.range;
/**
* Format of date
*
* For reference: https://flatpickr.js.org/formatting/
* @type {?}
*/
DatePicker.prototype.dateFormat;
/**
* Defines if time selector should be present. Please define dateFormat accordingly. i.e.: "d/m/Y H:i"
*
* For reference: https://flatpickr.js.org/formatting/
* @type {?}
*/
DatePicker.prototype.hasTime;
/**
* Disables calendar input. Useful for time picker functionality. Pair it with a time related format accordingly. i.e.: "H:i"
* @type {?}
*/
DatePicker.prototype.noCalendar;
/**
* Date picker label.
* @type {?}
*/
DatePicker.prototype.label;
/**
* Label for date range selector.
* @type {?}
*/
DatePicker.prototype.rangeLabel;
/**
* Sets the placeholder text.
* @type {?}
*/
DatePicker.prototype.placeholder;
/**
* Sets the pattern to follow.
* @type {?}
*/
DatePicker.prototype.pattern;
/**
* Date picker id.
* @type {?}
*/
DatePicker.prototype.id;
/**
* Set to `true` to disable the `Datepicker`
* @type {?}
*/
DatePicker.prototype.disabled;
/**
* Set to `true` to display invalid state.
* @type {?}
*/
DatePicker.prototype.invalid;
/**
* Feedback message to display when `Datepicker` is invalid.
* @type {?}
*/
DatePicker.prototype.invalidText;
/**
* Skeleton state.
* @type {?}
*/
DatePicker.prototype.skeleton;
/**
* Array of date picker plugins.
* @type {?}
*/
DatePicker.prototype.plugins;
/**
* Emits event notifying other classes of a change.
* @type {?}
*/
DatePicker.prototype.valueChange;
/**
* @type {?}
* @protected
*/
DatePicker.prototype._value;
/**
* @type {?}
* @protected
*/
DatePicker.prototype._flatpickrOptions;
/**
* @type {?}
* @protected
*/
DatePicker.prototype.flatpickrBaseOptions;
/**
* @type {?}
* @protected
*/
DatePicker.prototype.flatpickrInstance;
/** @type {?} */
DatePicker.prototype.onTouched;
/** @type {?} */
DatePicker.prototype.propagateChange;
/**
* @type {?}
* @protected
*/
DatePicker.prototype.elementRef;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9Aa3VzaGtpL25nLXN1a2EvIiwic291cmNlcyI6WyJsaWIvZGF0ZXBpY2tlci9kYXRlcGlja2VyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsS0FBSyxFQUNMLE1BQU0sRUFDTixZQUFZLEVBQ1osaUJBQWlCLEVBQ2pCLFVBQVUsRUFFVixZQUFZLEVBS2IsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxXQUFXLE1BQU0sbUJBQW1CLENBQUM7QUFDNUMsT0FBTyxTQUFTLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNuRCxPQUFPLEVBQUUsOEJBQThCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUdsRjtJQThMRSxvQkFBc0IsVUFBc0I7UUFBNUMsaUJBQWlEO1FBQTNCLGVBQVUsR0FBVixVQUFVLENBQVk7Ozs7UUFoSW5DLFVBQUssR0FBRyxLQUFLLENBQUM7Ozs7OztRQU9kLGVBQVUsR0FBRyxPQUFPLENBQUM7Ozs7OztRQU9yQixZQUFPLEdBQUcsS0FBSyxDQUFDOzs7O1FBS2hCLGVBQVUsR0FBRyxLQUFLLENBQUM7Ozs7UUFlbkIsZ0JBQVcsR0FBRyxZQUFZLENBQUM7Ozs7UUFLM0IsWUFBTyxHQUFHLDRCQUE0QixDQUFDOzs7O1FBS3ZDLE9BQUUsR0FBRyxnQkFBYyxVQUFVLENBQUMsZUFBZSxFQUFJLENBQUM7Ozs7UUFtQmxELGFBQVEsR0FBRyxLQUFLLENBQUM7Ozs7UUFLakIsWUFBTyxHQUFHLEtBQUssQ0FBQzs7OztRQVVoQixhQUFRLEdBQUcsS0FBSyxDQUFDOzs7O1FBS2pCLFlBQU8sR0FBRyxFQUFFLENBQUM7Ozs7UUEwQlosZ0JBQVcsR0FBc0IsSUFB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IHtcbiAgQ29tcG9uZW50LFxuICBJbnB1dCxcbiAgT3V0cHV0LFxuICBFdmVudEVtaXR0ZXIsXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxuICBFbGVtZW50UmVmLFxuICBPbkRlc3Ryb3ksXG4gIEhvc3RMaXN0ZW5lcixcbiAgVGVtcGxhdGVSZWYsXG4gIE9uQ2hhbmdlcyxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgQWZ0ZXJWaWV3Q2hlY2tlZFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCByYW5nZVBsdWdpbiBmcm9tICcuL3N1a2FSYW5nZVBsdWdpbic7XG5pbXBvcnQgZmxhdHBpY2tyIGZyb20gJ2ZsYXRwaWNrcic7XG5pbXBvcnQgeyBTcGFuaXNoIH0gZnJvbSAnZmxhdHBpY2tyL2Rpc3QvbDEwbi9lcy5qcyc7XG5pbXBvcnQgeyBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IHN1a2FGbGF0cGlja3JNb250aFNlbGVjdFBsdWdpbiB9IGZyb20gJy4vc3VrYUZsYXRwaWNrck1vbnRoU2VsZWN0UGx1Z2luJztcblxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzdWthLWRhdGUtcGlja2VyJyxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1pdGVtXCI+XG4gICAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwiZGF0ZS1waWNrZXJcIlxuICAgICAgICBbbmdDbGFzc109XCJ7XG4gICAgICAgICAgJ2RhdGUtcGlja2VyLS1yYW5nZScgOiByYW5nZSxcbiAgICAgICAgICAnZGF0ZS1waWNrZXItLXNpbmdsZScgOiAhcmFuZ2UsXG4gICAgICAgICAgJ2RhdGUtcGlja2VyLS1yYW5nZS13aXRoLXRpbWUnIDogcmFuZ2UgJiYgaGFzVGltZSxcbiAgICAgICAgICAnc2tlbGV0b24nIDogc2tlbGV0b25cbiAgICAgICAgfVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItY29udGFpbmVyXCI+XG4gICAgICAgICAgPHN1a2EtZGF0ZS1waWNrZXItaW5wdXRcbiAgICAgICAgICAgIFtsYWJlbF09XCJsYWJlbFwiXG4gICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICAgICAgICAgICAgW3BhdHRlcm5dPVwicGF0dGVyblwiXG4gICAgICAgICAgICBbaWRdPVwiaWRcIlxuICAgICAgICAgICAgW3R5cGVdPVwiKHJhbmdlID8gJ3JhbmdlJyA6ICdzaW5nbGUnKVwiXG4gICAgICAgICAgICBbaGFzSWNvbl09XCIocmFuZ2UgPyBmYWxzZSA6IHRydWUpXCJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICBbaW52YWxpZF09XCJpbnZhbGlkXCJcbiAgICAgICAgICAgIFtpbnZhbGlkVGV4dF09XCJpbnZhbGlkVGV4dFwiXG4gICAgICAgICAgICBbdGltZVBpY2tlcl09XCJoYXNUaW1lICYmIG5vQ2FsZW5kYXJcIlxuICAgICAgICAgICAgW3NrZWxldG9uXT1cInNrZWxldG9uXCJcbiAgICAgICAgICAgICh2YWx1ZUNoYW5nZSk9XCJvblZhbHVlQ2hhbmdlKCRldmVudClcIj5cbiAgICAgICAgICA8L3N1a2EtZGF0ZS1waWNrZXItaW5wdXQ+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2ICpuZ0lmPVwicmFuZ2VcIiBjbGFzcz1cImRhdGUtcGlja2VyLWNvbnRhaW5lclwiPlxuICAgICAgICAgIDxzdWthLWRhdGUtcGlja2VyLWlucHV0XG4gICAgICAgICAgICBbbGFiZWxdPVwicmFuZ2VMYWJlbFwiXG4gICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICAgICAgICAgICAgW3BhdHRlcm5dPVwicGF0dGVyblwiXG4gICAgICAgICAgICBbaWRdPVwiaWQgKyAnLXJhbmdlSW5wdXQnXCJcbiAgICAgICAgICAgIFt0eXBlXT1cIihyYW5nZSA/ICdyYW5nZScgOiAnc2luZ2xlJylcIlxuICAgICAgICAgICAgW2hhc0ljb25dPVwiKHJhbmdlID8gdHJ1ZSA6IG51bGwpXCJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICBbaW52YWxpZF09XCJpbnZhbGlkXCJcbiAgICAgICAgICAgIFtpbnZhbGlkVGV4dF09XCJpbnZhbGlkVGV4dFwiXG4gICAgICAgICAgICBbdGltZVBpY2tlcl09XCJoYXNUaW1lICYmIG5vQ2FsZW5kYXJcIlxuICAgICAgICAgICAgW3NrZWxldG9uXT1cInNrZWxldG9uXCJcbiAgICAgICAgICAgICh2YWx1ZUNoYW5nZSk9XCJvblJhbmdlVmFsdWVDaGFuZ2UoJGV2ZW50KVwiPlxuICAgICAgICAgIDwvc3VrYS1kYXRlLXBpY2tlci1pbnB1dD5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogRGF0ZVBpY2tlcixcbiAgICAgIG11bHRpOiB0cnVlXG4gICAgfVxuICBdLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lXG59KVxuZXhwb3J0IGNsYXNzIERhdGVQaWNrZXIgaW1wbGVtZW50cyBPbkRlc3Ryb3ksIE9uQ2hhbmdlcywgQWZ0ZXJWaWV3Q2hlY2tlZCB7XG4gIHByaXZhdGUgc3RhdGljIGRhdGVQaWNrZXJDb3VudCA9IDA7XG5cbiAgLyoqXG4gICAqIFNlbGVjdCBjYWxlbmRhciByYW5nZSBtb2RlXG4gICAqL1xuICBASW5wdXQoKSByYW5nZSA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBGb3JtYXQgb2YgZGF0ZVxuICAgKlxuICAgKiBGb3IgcmVmZXJlbmNlOiBodHRwczovL2ZsYXRwaWNrci5qcy5vcmcvZm9ybWF0dGluZy9cbiAgICovXG4gIEBJbnB1dCgpIGRhdGVGb3JtYXQgPSAnZC9tL1knO1xuXG4gIC8qKlxuICAgKiBEZWZpbmVzIGlmIHRpbWUgc2VsZWN0b3Igc2hvdWxkIGJlIHByZXNlbnQuIFBsZWFzZSBkZWZpbmUgZGF0ZUZvcm1hdCBhY2NvcmRpbmdseS4gaS5lLjogXCJkL20vWSBIOmlcIlxuICAgKlxuICAgKiBGb3IgcmVmZXJlbmNlOiBodHRwczovL2ZsYXRwaWNrci5qcy5vcmcvZm9ybWF0dGluZy9cbiAgICovXG4gIEBJbnB1dCgpIGhhc1RpbWUgPSBmYWxzZTtcblxuICAvKipcbiAgICogRGlzYWJsZXMgY2FsZW5kYXIgaW5wdXQuIFVzZWZ1bCBmb3IgdGltZSBwaWNrZXIgZnVuY3Rpb25hbGl0eS4gUGFpciBpdCB3aXRoIGEgdGltZSByZWxhdGVkIGZvcm1hdCBhY2NvcmRpbmdseS4gaS5lLjogXCJIOmlcIlxuICAgKi9cbiAgQElucHV0KCkgbm9DYWxlbmRhciA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBEYXRlIHBpY2tlciBsYWJlbC5cbiAgICovXG4gIEBJbnB1dCgpIGxhYmVsOiBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gIC8qKlxuICAgKiBMYWJlbCBmb3IgZGF0ZSByYW5nZSBzZWxlY3Rvci5cbiAgICovXG4gIEBJbnB1dCgpIHJhbmdlTGFiZWw6IHN0cmluZztcblxuICAvKipcbiAgICogU2V0cyB0aGUgcGxhY2Vob2xkZXIgdGV4dC5cbiAgICovXG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyID0gJ2RkL21tL3l5eXknO1xuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBwYXR0ZXJuIHRvIGZvbGxvdy5cbiAgICovXG4gIEBJbnB1dCgpIHBhdHRlcm4gPSAnXlxcXFxkezEsMn0vXFxcXGR7MSwyfS9cXFxcZHs0fSQnO1xuXG4gIC8qKlxuICAgKiBEYXRlIHBpY2tlciBpZC5cbiAgICovXG4gIEBJbnB1dCgpIGlkID0gYGRhdGVwaWNrZXItJHtEYXRlUGlja2VyLmRhdGVQaWNrZXJDb3VudCsrfWA7XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHZhbHVlLlxuICAgKi9cbiAgQElucHV0KCkgc2V0IHZhbHVlKHY6IChEYXRlIHwgc3RyaW5nKVtdKSB7XG4gICAgaWYgKCF2KSB7XG4gICAgICB2ID0gW107XG4gICAgfVxuICAgIHRoaXMuX3ZhbHVlID0gdjtcbiAgfVxuXG4gIGdldCB2YWx1ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRvIGB0cnVlYCB0byBkaXNhYmxlIHRoZSBgRGF0ZXBpY2tlcmBcbiAgICovXG4gIEBJbnB1dCgpIGRpc2FibGVkID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIFNldCB0byBgdHJ1ZWAgdG8gZGlzcGxheSBpbnZhbGlkIHN0YXRlLlxuICAgKi9cbiAgQElucHV0KCkgaW52YWxpZCA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBGZWVkYmFjayBtZXNzYWdlIHRvIGRpc3BsYXkgd2hlbiBgRGF0ZXBpY2tlcmAgaXMgaW52YWxpZC5cbiAgICovXG4gIEBJbnB1dCgpIGludmFsaWRUZXh0OiBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gIC8qKlxuICAgKiBTa2VsZXRvbiBzdGF0ZS5cbiAgICovXG4gIEBJbnB1dCgpIHNrZWxldG9uID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEFycmF5IG9mIGRhdGUgcGlja2VyIHBsdWdpbnMuXG4gICAqL1xuICBASW5wdXQoKSBwbHVnaW5zID0gW107XG5cbiAgLyoqXG4gICAqIEZsYXRwaWNrciBvcHRpb25zXG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgZmxhdHBpY2tyT3B0aW9ucyhvcHRpb25zKSB7XG4gICAgdGhpcy5fZmxhdHBpY2tyT3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuX2ZsYXRwaWNrck9wdGlvbnMsIG9wdGlvbnMpO1xuICB9XG4gIGdldCBmbGF0cGlja3JPcHRpb25zKCkge1xuICAgIGNvbnN0IHBsdWdpbnMgPSBbLi4udGhpcy5wbHVnaW5zLCBzdWthRmxhdHBpY2tyTW9udGhTZWxlY3RQbHVnaW5dO1xuICAgIGlmICh0aGlzLnJhbmdlKSB7XG4gICAgICBwbHVnaW5zLnB1c2gocmFuZ2VQbHVnaW4oeyBpbnB1dDogYCMke3RoaXMuaWR9LXJhbmdlSW5wdXRgLCBwb3NpdGlvbjogJ2xlZnQnIH0pKTtcbiAgICB9XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIHRoaXMuX2ZsYXRwaWNrck9wdGlvbnMsIHRoaXMuZmxhdHBpY2tyQmFzZU9wdGlvbnMsIHtcbiAgICAgIG1vZGU6IHRoaXMucmFuZ2UgPyAncmFuZ2UnIDogJ3NpbmdsZScsXG4gICAgICBwbHVnaW5zLFxuICAgICAgZGF0ZUZvcm1hdDogdGhpcy5kYXRlRm9ybWF0LFxuICAgICAgZW5hYmxlVGltZTogdGhpcy5oYXNUaW1lLFxuICAgICAgbm9DYWxlbmRhcjogdGhpcy5ub0NhbGVuZGFyLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEVtaXRzIGV2ZW50IG5vdGlmeWluZyBvdGhlciBjbGFzc2VzIG9mIGEgY2hhbmdlLlxuICAgKi9cbiAgQE91dHB1dCgpIHZhbHVlQ2hhbmdlOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBwcm90ZWN0ZWQgX3ZhbHVlID0gW107XG5cbiAgcHJvdGVjdGVkIF9mbGF0cGlja3JPcHRpb25zID0ge1xuICAgIGFsbG93SW5wdXQ6IHRydWVcbiAgfTtcblxuICBwcm90ZWN0ZWQgZmxhdHBpY2tyQmFzZU9wdGlvbnMgPSB7XG4gICAgbW9kZTogJ3NpbmdsZScsXG4gICAgZGF0ZUZvcm1hdDogJ2QvbS9ZJyxcbiAgICBsb2NhbGU6IFNwYW5pc2gsXG4gICAgcGx1Z2luczogdGhpcy5wbHVnaW5zLFxuICAgIG9uT3BlbjogKCkgPT4geyB0aGlzLnVwZGF0ZUNsYXNzTmFtZXMoKTsgfSxcbiAgICB2YWx1ZTogdGhpcy52YWx1ZVxuICB9O1xuXG4gIHByb3RlY3RlZCBmbGF0cGlja3JJbnN0YW5jZSA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYpIHsgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBpZiAodGhpcy5pc0ZsYXRwaWNrckxvYWRlZCgpKSB7XG4gICAgICBsZXQgZGF0ZXMgPSB0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNlbGVjdGVkRGF0ZXM7XG4gICAgICBpZiAoY2hhbmdlcy52YWx1ZSAmJiB0aGlzLmRpZERhdGVWYWx1ZUNoYW5nZShjaGFuZ2VzLnZhbHVlLmN1cnJlbnRWYWx1ZSwgY2hhbmdlcy52YWx1ZS5wcmV2aW91c1ZhbHVlKSkge1xuICAgICAgICBkYXRlcyA9IGNoYW5nZXMudmFsdWUuY3VycmVudFZhbHVlO1xuICAgICAgfVxuICAgICAgLy8gb25seSByZXNldCB0aGUgZmxhdHBpY2tyIGluc3RhbmNlIG9uIElucHV0IGNoYW5nZXNcbiAgICAgIHRoaXMuZmxhdHBpY2tySW5zdGFuY2UgPSBmbGF0cGlja3IoYCMke3RoaXMuaWR9YCwgdGhpcy5mbGF0cGlja3JPcHRpb25zKTtcbiAgICAgIHRoaXMuc2V0RGF0ZVZhbHVlcyhkYXRlcyk7XG4gICAgfVxuICB9XG5cbiAgLy8gYmVjYXVzZSB0aGUgYWN0dWFsIHZpZXcgbWF5IGJlIGRlbGF5ZWQgaW4gbG9hZGluZyAodGhpbmsgcHJvamVjdGlvbiBpbnRvIGEgdGFiIHBhbmUpXG4gIC8vIGFuZCBiZWNhdXNlIHdlIHJlbHkgb24gYSBsaWJyYXJ5IHRoYXQgb3BlcmF0ZXMgb3V0c2lkZSB0aGUgQW5ndWxhciB2aWV3IG9mIHRoZSB3b3JsZFxuICAvLyB3ZSBuZWVkIHRvIGtlZXAgdHJ5aW5nIHRvIGxvYWQgdGhlIGxpYnJhcnksIHVudGlsIHRoZSByZWxldmFudCBET00gaXMgYWN0dWFsbHkgbGl2ZVxuICBuZ0FmdGVyVmlld0NoZWNrZWQoKSB7XG4gICAgaWYgKCF0aGlzLmlzRmxhdHBpY2tyTG9hZGVkKCkpIHtcbiAgICAgIHRoaXMuZmxhdHBpY2tySW5zdGFuY2UgPSBmbGF0cGlja3IoYCMke3RoaXMuaWR9YCwgdGhpcy5mbGF0cGlja3JPcHRpb25zKTtcblxuICAgICAgLy8gaWYgKGFuZCBvbmx5IGlmKSB0aGUgaW5pdGlhbGl6YXRpb24gc3VjY2VlZGVkLCB3ZSBjYW4gc2V0IHRoZSBkYXRlIHZhbHVlc1xuICAgICAgaWYgKHRoaXMuaXNGbGF0cGlja3JMb2FkZWQoKSkge1xuICAgICAgICBpZiAodGhpcy52YWx1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdGhpcy5zZXREYXRlVmFsdWVzKHRoaXMudmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZm9jdXNpbicpXG4gIG9uRm9jdXMoKSB7XG4gICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXcml0ZXMgYSB2YWx1ZSBmcm9tIHRoZSBtb2RlbCB0byB0aGUgY29tcG9uZW50LiBFeHBlY3RzIHRoZSB2YWx1ZSB0byBiZSBgbnVsbGAgb3IgYChEYXRlIHwgc3RyaW5nKVtdYFxuICAgKiBAcGFyYW0gdmFsdWUgdmFsdWUgcmVjZWl2ZWQgZnJvbSB0aGUgbW9kZWxcbiAgICovXG4gIHdyaXRlVmFsdWUodmFsdWU6IChEYXRlIHwgc3RyaW5nKVtdKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgIGlmICh0aGlzLmlzRmxhdHBpY2tyTG9hZGVkKCkgJiYgdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5jb25maWcpIHtcbiAgICAgIHRoaXMuc2V0RGF0ZVZhbHVlcyh0aGlzLnZhbHVlKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpIHtcbiAgICB0aGlzLnByb3BhZ2F0ZUNoYW5nZSA9IGZuO1xuICB9XG5cbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSkge1xuICAgIHRoaXMub25Ub3VjaGVkID0gZm47XG4gIH1cblxuICBvblRvdWNoZWQ6ICgpID0+IGFueSA9ICgpID0+IHsgfTtcblxuICBwcm9wYWdhdGVDaGFuZ2UgPSAoXzogYW55KSA9PiB7IH07XG5cbiAgLyoqXG4gICAqIENsZWFucyB1cCBvdXIgZmxhdHBpY2tyIGluc3RhbmNlXG4gICAqL1xuICBuZ09uRGVzdHJveSgpIHtcbiAgICBpZiAoIXRoaXMuaXNGbGF0cGlja3JMb2FkZWQoKSkgeyByZXR1cm47IH1cbiAgICB0aGlzLmZsYXRwaWNrckluc3RhbmNlLmRlc3Ryb3koKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIHRoZSBgdmFsdWVDaGFuZ2VgIGV2ZW50IGZyb20gdGhlIHByaW1hcnkvc2luZ2xlIGlucHV0XG4gICAqL1xuICBvblZhbHVlQ2hhbmdlKGV2ZW50OiBzdHJpbmcpIHtcbiAgICBpZiAodGhpcy5pc0ZsYXRwaWNrckxvYWRlZCgpKSB7XG4gICAgICBjb25zdCBkYXRlID0gdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5wYXJzZURhdGUoZXZlbnQsIHRoaXMuZGF0ZUZvcm1hdCk7XG4gICAgICBpZiAodGhpcy5yYW5nZSkge1xuICAgICAgICB0aGlzLnNldERhdGVWYWx1ZXMoW2RhdGUsIHRoaXMuZmxhdHBpY2tySW5zdGFuY2Uuc2VsZWN0ZWREYXRlc1sxXV0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zZXREYXRlVmFsdWVzKFtkYXRlXSk7XG4gICAgICB9XG4gICAgICB0aGlzLmRvU2VsZWN0KHRoaXMuZmxhdHBpY2tySW5zdGFuY2Uuc2VsZWN0ZWREYXRlcyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgdGhlIGB2YWx1ZUNoYW5nZWAgZXZlbnQgZnJvbSB0aGUgcmFuZ2UgaW5wdXRcbiAgICovXG4gIG9uUmFuZ2VWYWx1ZUNoYW5nZShldmVudDogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuaXNGbGF0cGlja3JMb2FkZWQoKSkge1xuICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuZmxhdHBpY2tySW5zdGFuY2UucGFyc2VEYXRlKGV2ZW50LCB0aGlzLmRhdGVGb3JtYXQpO1xuICAgICAgdGhpcy5zZXREYXRlVmFsdWVzKFt0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNlbGVjdGVkRGF0ZXNbMF0sIGRhdGVdKTtcbiAgICAgIHRoaXMuZG9TZWxlY3QodGhpcy5mbGF0cGlja3JJbnN0YW5jZS5zZWxlY3RlZERhdGVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3VrYSB1c2VzIGEgbnVtYmVyIG9mIHNwZWNpZmljIGNsYXNzbmFtZXMgZm9yIHBhcnRzIG9mIHRoZSBmbGF0cGlja3IgLSB0aGlzIGlkZW1wb3RlbnQgbWV0aG9kIGFwcGxpZXMgdGhlbSBpZiBuZWVkZWQuXG4gICAqL1xuICBwcm90ZWN0ZWQgdXBkYXRlQ2xhc3NOYW1lcygpIHtcbiAgICBpZiAoIXRoaXMuZWxlbWVudFJlZikgeyByZXR1cm47IH1cblxuICAgIC8vIGdldCBhbGwgdGhlIHBvc3NpYmxlIGZsYXRwaWNrcnMgaW4gdGhlIGRvY3VtZW50IC0gd2UgbmVlZCB0byBhZGQgY2xhc3NlcyB0byAocG90ZW50aWFsbHkpIGFsbCBvZiB0aGVtXG4gICAgY29uc3QgY2FsZW5kYXJDb250YWluZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuZmxhdHBpY2tyLWNhbGVuZGFyJyk7XG4gICAgY29uc3QgbW9udGhDb250YWluZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuZmxhdHBpY2tyLW1vbnRoJyk7XG4gICAgY29uc3Qgd2Vla2RheXNDb250YWluZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuZmxhdHBpY2tyLXdlZWtkYXlzJyk7XG4gICAgY29uc3Qgd2Vla2RheUNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5mbGF0cGlja3Itd2Vla2RheScpO1xuICAgIGNvbnN0IGRheXNDb250YWluZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuZmxhdHBpY2tyLWRheXMnKTtcbiAgICBjb25zdCBkYXlDb250YWluZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuZmxhdHBpY2tyLWRheScpO1xuXG4gICAgLy8gYWRkIGNsYXNzZXMgdG8gbGlzdHMgb2YgZWxlbWVudHNcbiAgICBjb25zdCBhZGRDbGFzc0lmTm90RXhpc3RzID0gKGNsYXNzbmFtZTogc3RyaW5nLCBlbGVtZW50TGlzdDogTm9kZUxpc3RPZjxFbGVtZW50PikgPT4ge1xuICAgICAgQXJyYXkuZnJvbShlbGVtZW50TGlzdCkuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgaWYgKCFlbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhjbGFzc25hbWUpKSB7XG4gICAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKGNsYXNzbmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvLyBhZGQgY2xhc3NlcyAoYnV0IG9ubHkgaWYgdGhleSBkb24ndCBleGlzdCwgc21hbGwgcGVyZiB3aW4pXG4gICAgYWRkQ2xhc3NJZk5vdEV4aXN0cygnZGF0ZS1waWNrZXJfX2NhbGVuZGFyJywgY2FsZW5kYXJDb250YWluZXIpO1xuICAgIGFkZENsYXNzSWZOb3RFeGlzdHMoJ2RhdGUtcGlja2VyX19tb250aCcsIG1vbnRoQ29udGFpbmVyKTtcbiAgICBhZGRDbGFzc0lmTm90RXhpc3RzKCdkYXRlLXBpY2tlcl9fd2Vla2RheXMnLCB3ZWVrZGF5c0NvbnRhaW5lcik7XG4gICAgYWRkQ2xhc3NJZk5vdEV4aXN0cygnZGF0ZS1waWNrZXJfX2RheXMnLCBkYXlzQ29udGFpbmVyKTtcblxuICAgIC8vIGFkZCB3ZWVrZGF5IGNsYXNzZXMgYW5kIGZvcm1hdCB0aGUgdGV4dFxuICAgIEFycmF5LmZyb20od2Vla2RheUNvbnRhaW5lcikuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gZWxlbWVudC5pbm5lckhUTUwucmVwbGFjZSgvXFxzKy9nLCAnJyk7XG4gICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2RhdGUtcGlja2VyX193ZWVrZGF5Jyk7XG4gICAgfSk7XG5cbiAgICAvLyBhZGQgZGF5IGNsYXNzZXMgYW5kIHNwZWNpYWwgY2FzZSB0aGUgXCJ0b2RheVwiIGVsZW1lbnQgYmFzZWQgb24gYHRoaXMudmFsdWVgXG4gICAgQXJyYXkuZnJvbShkYXlDb250YWluZXIpLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2RhdGUtcGlja2VyX19kYXknKTtcbiAgICAgIGlmICghdGhpcy52YWx1ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ3RvZGF5JykgJiYgdGhpcy52YWx1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnbm8tYm9yZGVyJyk7XG4gICAgICB9IGVsc2UgaWYgKGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCd0b2RheScpICYmIHRoaXMudmFsdWUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgnbm8tYm9yZGVyJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyB0aGUgZ2l2ZW4gZGF0ZSB2YWx1ZSBhcnJheSB0byBib3RoIHRoZSBmbGF0cGlja3IgaW5zdGFuY2UgYW5kIHRoZSBgaW5wdXRgKHMpXG4gICAqIEBwYXJhbSBkYXRlcyB0aGUgZGF0ZSB2YWx1ZXMgdG8gYXBwbHlcbiAgICovXG4gIHByb3RlY3RlZCBzZXREYXRlVmFsdWVzKGRhdGVzOiAoRGF0ZSB8IHN0cmluZylbXSkge1xuICAgIGlmICh0aGlzLmlzRmxhdHBpY2tyTG9hZGVkKCkpIHtcbiAgICAgIGNvbnN0IHNpbmdsZUlucHV0ID0gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcihgIyR7dGhpcy5pZH1gKTtcbiAgICAgIGNvbnN0IHJhbmdlSW5wdXQgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKGAjJHt0aGlzLmlkfS1yYW5nZUlucHV0YCk7XG5cbiAgICAgIC8vIHNldCB0aGUgZGF0ZSBvbiB0aGUgaW5zdGFuY2VcbiAgICAgIHRoaXMuZmxhdHBpY2tySW5zdGFuY2Uuc2V0RGF0ZShkYXRlcyk7XG5cbiAgICAgIC8vIHdlIGNhbiBlaXRoZXIgc2V0IGEgZGF0ZSB2YWx1ZSBvciBhbiBlbXB0eSBzdHJpbmcsIHNvIHdlIHN0YXJ0IHdpdGggYW4gZW1wdHkgc3RyaW5nXG4gICAgICBsZXQgc2luZ2xlRGF0ZSA9ICcnO1xuICAgICAgLy8gaWYgZGF0ZSBpcyBh