UNPKG

@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>

590 lines 48.3 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ 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'; export class DatePicker { /** * @param {?} elementRef */ constructor(elementRef) { 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 {?} */ () => { this.updateClassNames(); }), value: this.value }; this.flatpickrInstance = null; this.onTouched = (/** * @return {?} */ () => { }); this.propagateChange = (/** * @param {?} _ * @return {?} */ (_) => { }); } /** * Sets the value. * @param {?} v * @return {?} */ set value(v) { if (!v) { v = []; } this._value = v; } /** * @return {?} */ get value() { return this._value; } /** * Flatpickr options * @param {?} options * @return {?} */ set flatpickrOptions(options) { this._flatpickrOptions = Object.assign({}, this._flatpickrOptions, options); } /** * @return {?} */ get flatpickrOptions() { /** @type {?} */ const plugins = [...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, dateFormat: this.dateFormat, enableTime: this.hasTime, noCalendar: this.noCalendar, }); } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { if (this.isFlatpickrLoaded()) { /** @type {?} */ let 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 /** * @return {?} */ ngAfterViewChecked() { 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 {?} */ onFocus() { 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 * @return {?} */ writeValue(value) { this.value = value; if (this.isFlatpickrLoaded() && this.flatpickrInstance.config) { this.setDateValues(this.value); } } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.propagateChange = fn; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouched = fn; } /** * Cleans up our flatpickr instance * @return {?} */ ngOnDestroy() { if (!this.isFlatpickrLoaded()) { return; } this.flatpickrInstance.destroy(); } /** * Handles the `valueChange` event from the primary/single input * @param {?} event * @return {?} */ onValueChange(event) { if (this.isFlatpickrLoaded()) { /** @type {?} */ const 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 * @param {?} event * @return {?} */ onRangeValueChange(event) { if (this.isFlatpickrLoaded()) { /** @type {?} */ const 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. * @protected * @return {?} */ updateClassNames() { if (!this.elementRef) { return; } // get all the possible flatpickrs in the document - we need to add classes to (potentially) all of them /** @type {?} */ const calendarContainer = document.querySelectorAll('.flatpickr-calendar'); /** @type {?} */ const monthContainer = document.querySelectorAll('.flatpickr-month'); /** @type {?} */ const weekdaysContainer = document.querySelectorAll('.flatpickr-weekdays'); /** @type {?} */ const weekdayContainer = document.querySelectorAll('.flatpickr-weekday'); /** @type {?} */ const daysContainer = document.querySelectorAll('.flatpickr-days'); /** @type {?} */ const dayContainer = document.querySelectorAll('.flatpickr-day'); // add classes to lists of elements /** @type {?} */ const addClassIfNotExists = (/** * @param {?} classname * @param {?} elementList * @return {?} */ (classname, elementList) => { Array.from(elementList).forEach((/** * @param {?} element * @return {?} */ 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 {?} */ 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 {?} */ 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) * @protected * @param {?} dates the date values to apply * @return {?} */ setDateValues(dates) { if (this.isFlatpickrLoaded()) { /** @type {?} */ const singleInput = this.elementRef.nativeElement.querySelector(`#${this.id}`); /** @type {?} */ const rangeInput = 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 {?} */ let singleDate = ''; // if date is a string, parse and format if (typeof this.flatpickrInstance.selectedDates[0] === 'string') { singleDate = this.flatpickrInstance.parseDate(this.flatpickrInstance.selectedDates[0], this.dateFormat); singleDate = this.flatpickrInstance.formatDate(singleDate, 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 = this.flatpickrInstance.formatDate(this.flatpickrInstance.selectedDates[0], this.dateFormat); } if (rangeInput) { // we can either set a date value or an empty string, so we start with an empty string /** @type {?} */ let rangeDate = ''; // if date is a string, parse and format if (typeof this.flatpickrInstance.selectedDates[1] === 'string') { rangeDate = this.flatpickrInstance.parseDate(this.flatpickrInstance.selectedDates[1].toString(), this.dateFormat); rangeDate = this.flatpickrInstance.formatDate(rangeDate, 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 = this.flatpickrInstance.formatDate(this.flatpickrInstance.selectedDates[1], this.dateFormat); } setTimeout((/** * @return {?} */ () => { // apply the values rangeInput.value = rangeDate; singleInput.value = singleDate; })); } } } /** * @protected * @param {?} selectedValue * @return {?} */ doSelect(selectedValue) { this.valueChange.emit(selectedValue); this.propagateChange(selectedValue); } /** * @protected * @param {?} currentValue * @param {?} previousValue * @return {?} */ didDateValueChange(currentValue, previousValue) { return currentValue[0] !== previousValue[0] || currentValue[1] !== previousValue[1]; } /** * More advanced checking of the loaded state of flatpickr * @protected * @return {?} */ isFlatpickrLoaded() { // 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: ` <div class="form-item"> <div class="date-picker" [ngClass]="{ 'date-picker--range' : range, 'date-picker--single' : !range, 'date-picker--range-with-time' : range && hasTime, 'skeleton' : skeleton }"> <div class="date-picker-container"> <suka-date-picker-input [label]="label" [placeholder]="placeholder" [pattern]="pattern" [id]="id" [type]="(range ? 'range' : 'single')" [hasIcon]="(range ? false : true)" [disabled]="disabled" [invalid]="invalid" [invalidText]="invalidText" [timePicker]="hasTime && noCalendar" [skeleton]="skeleton" (valueChange)="onValueChange($event)"> </suka-date-picker-input> </div> <div *ngIf="range" class="date-picker-container"> <suka-date-picker-input [label]="rangeLabel" [placeholder]="placeholder" [pattern]="pattern" [id]="id + '-rangeInput'" [type]="(range ? 'range' : 'single')" [hasIcon]="(range ? true : null)" [disabled]="disabled" [invalid]="invalid" [invalidText]="invalidText" [timePicker]="hasTime && noCalendar" [skeleton]="skeleton" (valueChange)="onRangeValueChange($event)"> </suka-date-picker-input> </div> </div> </div> `, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: DatePicker, multi: true } ], encapsulation: ViewEncapsulation.None }] } ]; /** @nocollapse */ DatePicker.ctorParameters = () => [ { 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',] }] }; 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9Aa3VzaGtpL25nLXN1a2EvIiwic291cmNlcyI6WyJsaWIvZGF0ZXBpY2tlci9kYXRlcGlja2VyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksRUFDWixpQkFBaUIsRUFDakIsVUFBVSxFQUVWLFlBQVksRUFLYixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLFdBQVcsTUFBTSxtQkFBbUIsQ0FBQztBQUM1QyxPQUFPLFNBQVMsTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ25ELE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBMkRsRixNQUFNLE9BQU8sVUFBVTs7OztJQXNJckIsWUFBc0IsVUFBc0I7UUFBdEIsZUFBVSxHQUFWLFVBQVUsQ0FBWTs7OztRQWhJbkMsVUFBSyxHQUFHLEtBQUssQ0FBQzs7Ozs7O1FBT2QsZUFBVSxHQUFHLE9BQU8sQ0FBQzs7Ozs7O1FBT3JCLFlBQU8sR0FBRyxLQUFLLENBQUM7Ozs7UUFLaEIsZUFBVSxHQUFHLEtBQUssQ0FBQzs7OztRQWVuQixnQkFBVyxHQUFHLFlBQVksQ0FBQzs7OztRQUszQixZQUFPLEdBQUcsNEJBQTRCLENBQUM7Ozs7UUFLdkMsT0FBRSxHQUFHLGNBQWMsVUFBVSxDQUFDLGVBQWUsRUFBRSxFQUFFLENBQUM7Ozs7UUFtQmxELGFBQVEsR0FBRyxLQUFLLENBQUM7Ozs7UUFLakIsWUFBTyxHQUFHLEtBQUssQ0FBQzs7OztRQVVoQixhQUFRLEdBQUcsS0FBSyxDQUFDOzs7O1FBS2pCLFlBQU8sR0FBRyxFQUFFLENBQUM7Ozs7UUEwQlosZ0JBQVcs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QWEsRUFBRSxpQkFBaUIsQ0FBQyxJQUFJO2FBQ3RDOzs7O1lBdEVDLFVBQVU7OztvQkE2RVQsS0FBSzt5QkFPTCxLQUFLO3NCQU9MLEtBQUs7eUJBS0wsS0FBSztvQkFLTCxLQUFLO3lCQUtMLEtBQUs7MEJBS0wsS0FBSztzQkFLTCxLQUFLO2lCQUtMLEtBQUs7b0JBS0wsS0FBSzt1QkFjTCxLQUFLO3NCQUtMLEtBQUs7MEJBS0wsS0FBSzt1QkFLTCxLQUFLO3NCQUtMLEtBQUs7K0JBS0wsS0FBSzswQkFxQkwsTUFBTTtzQkFpRE4sWUFBWSxTQUFDLFNBQVM7Ozs7Ozs7SUFuS3ZCLDJCQUFtQzs7Ozs7SUFLbkMsMkJBQXVCOzs7Ozs7O0lBT3ZCLGdDQUE4Qjs7Ozs7OztJQU85Qiw2QkFBeUI7Ozs7O0lBS3pCLGdDQUE0Qjs7Ozs7SUFLNUIsMkJBQTBDOzs7OztJQUsxQyxnQ0FBNEI7Ozs7O0lBSzVCLGlDQUFvQzs7Ozs7SUFLcEMsNkJBQWdEOzs7OztJQUtoRCx3QkFBMkQ7Ozs7O0lBbUIzRCw4QkFBMEI7Ozs7O0lBSzFCLDZCQUF5Qjs7Ozs7SUFLekIsaUNBQWdEOzs7OztJQUtoRCw4QkFBMEI7Ozs7O0lBSzFCLDZCQUFzQjs7Ozs7SUEwQnRCLGlDQUE4RDs7Ozs7SUFFOUQsNEJBQXNCOzs7OztJQUV0Qix1Q0FFRTs7Ozs7SUFFRiwwQ0FPRTs7Ozs7SUFFRix1Q0FBbUM7O0lBd0RuQywrQkFBaUM7O0lBRWpDLHFDQUFrQzs7Ozs7SUF4RHRCLGdDQUFnQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgRWxlbWVudFJlZixcbiAgT25EZXN0cm95LFxuICBIb3N0TGlzdGVuZXIsXG4gIFRlbXBsYXRlUmVmLFxuICBPbkNoYW5nZXMsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIEFmdGVyVmlld0NoZWNrZWRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgcmFuZ2VQbHVnaW4gZnJvbSAnLi9zdWthUmFuZ2VQbHVnaW4nO1xuaW1wb3J0IGZsYXRwaWNrciBmcm9tICdmbGF0cGlja3InO1xuaW1wb3J0IHsgU3BhbmlzaCB9IGZyb20gJ2ZsYXRwaWNrci9kaXN0L2wxMG4vZXMuanMnO1xuaW1wb3J0IHsgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBzdWthRmxhdHBpY2tyTW9udGhTZWxlY3RQbHVnaW4gfSBmcm9tICcuL3N1a2FGbGF0cGlja3JNb250aFNlbGVjdFBsdWdpbic7XG5cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnc3VrYS1kYXRlLXBpY2tlcicsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImZvcm0taXRlbVwiPlxuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cImRhdGUtcGlja2VyXCJcbiAgICAgICAgW25nQ2xhc3NdPVwie1xuICAgICAgICAgICdkYXRlLXBpY2tlci0tcmFuZ2UnIDogcmFuZ2UsXG4gICAgICAgICAgJ2RhdGUtcGlja2VyLS1zaW5nbGUnIDogIXJhbmdlLFxuICAgICAgICAgICdkYXRlLXBpY2tlci0tcmFuZ2Utd2l0aC10aW1lJyA6IHJhbmdlICYmIGhhc1RpbWUsXG4gICAgICAgICAgJ3NrZWxldG9uJyA6IHNrZWxldG9uXG4gICAgICAgIH1cIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRhdGUtcGlja2VyLWNvbnRhaW5lclwiPlxuICAgICAgICAgIDxzdWthLWRhdGUtcGlja2VyLWlucHV0XG4gICAgICAgICAgICBbbGFiZWxdPVwibGFiZWxcIlxuICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyXCJcbiAgICAgICAgICAgIFtwYXR0ZXJuXT1cInBhdHRlcm5cIlxuICAgICAgICAgICAgW2lkXT1cImlkXCJcbiAgICAgICAgICAgIFt0eXBlXT1cIihyYW5nZSA/ICdyYW5nZScgOiAnc2luZ2xlJylcIlxuICAgICAgICAgICAgW2hhc0ljb25dPVwiKHJhbmdlID8gZmFsc2UgOiB0cnVlKVwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgW2ludmFsaWRdPVwiaW52YWxpZFwiXG4gICAgICAgICAgICBbaW52YWxpZFRleHRdPVwiaW52YWxpZFRleHRcIlxuICAgICAgICAgICAgW3RpbWVQaWNrZXJdPVwiaGFzVGltZSAmJiBub0NhbGVuZGFyXCJcbiAgICAgICAgICAgIFtza2VsZXRvbl09XCJza2VsZXRvblwiXG4gICAgICAgICAgICAodmFsdWVDaGFuZ2UpPVwib25WYWx1ZUNoYW5nZSgkZXZlbnQpXCI+XG4gICAgICAgICAgPC9zdWthLWRhdGUtcGlja2VyLWlucHV0PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiAqbmdJZj1cInJhbmdlXCIgY2xhc3M9XCJkYXRlLXBpY2tlci1jb250YWluZXJcIj5cbiAgICAgICAgICA8c3VrYS1kYXRlLXBpY2tlci1pbnB1dFxuICAgICAgICAgICAgW2xhYmVsXT1cInJhbmdlTGFiZWxcIlxuICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyXCJcbiAgICAgICAgICAgIFtwYXR0ZXJuXT1cInBhdHRlcm5cIlxuICAgICAgICAgICAgW2lkXT1cImlkICsgJy1yYW5nZUlucHV0J1wiXG4gICAgICAgICAgICBbdHlwZV09XCIocmFuZ2UgPyAncmFuZ2UnIDogJ3NpbmdsZScpXCJcbiAgICAgICAgICAgIFtoYXNJY29uXT1cIihyYW5nZSA/IHRydWUgOiBudWxsKVwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgW2ludmFsaWRdPVwiaW52YWxpZFwiXG4gICAgICAgICAgICBbaW52YWxpZFRleHRdPVwiaW52YWxpZFRleHRcIlxuICAgICAgICAgICAgW3RpbWVQaWNrZXJdPVwiaGFzVGltZSAmJiBub0NhbGVuZGFyXCJcbiAgICAgICAgICAgIFtza2VsZXRvbl09XCJza2VsZXRvblwiXG4gICAgICAgICAgICAodmFsdWVDaGFuZ2UpPVwib25SYW5nZVZhbHVlQ2hhbmdlKCRldmVudClcIj5cbiAgICAgICAgICA8L3N1a2EtZGF0ZS1waWNrZXItaW5wdXQ+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIGAsXG4gIHByb3ZpZGVyczogW1xuICAgIHtcbiAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgdXNlRXhpc3Rpbmc6IERhdGVQaWNrZXIsXG4gICAgICBtdWx0aTogdHJ1ZVxuICAgIH1cbiAgXSxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZVxufSlcbmV4cG9ydCBjbGFzcyBEYXRlUGlja2VyIGltcGxlbWVudHMgT25EZXN0cm95LCBPbkNoYW5nZXMsIEFmdGVyVmlld0NoZWNrZWQge1xuICBwcml2YXRlIHN0YXRpYyBkYXRlUGlja2VyQ291bnQgPSAwO1xuXG4gIC8qKlxuICAgKiBTZWxlY3QgY2FsZW5kYXIgcmFuZ2UgbW9kZVxuICAgKi9cbiAgQElucHV0KCkgcmFuZ2UgPSBmYWxzZTtcblxuICAvKipcbiAgICogRm9ybWF0IG9mIGRhdGVcbiAgICpcbiAgICogRm9yIHJlZmVyZW5jZTogaHR0cHM6Ly9mbGF0cGlja3IuanMub3JnL2Zvcm1hdHRpbmcvXG4gICAqL1xuICBASW5wdXQoKSBkYXRlRm9ybWF0ID0gJ2QvbS9ZJztcblxuICAvKipcbiAgICogRGVmaW5lcyBpZiB0aW1lIHNlbGVjdG9yIHNob3VsZCBiZSBwcmVzZW50LiBQbGVhc2UgZGVmaW5lIGRhdGVGb3JtYXQgYWNjb3JkaW5nbHkuIGkuZS46IFwiZC9tL1kgSDppXCJcbiAgICpcbiAgICogRm9yIHJlZmVyZW5jZTogaHR0cHM6Ly9mbGF0cGlja3IuanMub3JnL2Zvcm1hdHRpbmcvXG4gICAqL1xuICBASW5wdXQoKSBoYXNUaW1lID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIERpc2FibGVzIGNhbGVuZGFyIGlucHV0LiBVc2VmdWwgZm9yIHRpbWUgcGlja2VyIGZ1bmN0aW9uYWxpdHkuIFBhaXIgaXQgd2l0aCBhIHRpbWUgcmVsYXRlZCBmb3JtYXQgYWNjb3JkaW5nbHkuIGkuZS46IFwiSDppXCJcbiAgICovXG4gIEBJbnB1dCgpIG5vQ2FsZW5kYXIgPSBmYWxzZTtcblxuICAvKipcbiAgICogRGF0ZSBwaWNrZXIgbGFiZWwuXG4gICAqL1xuICBASW5wdXQoKSBsYWJlbDogc3RyaW5nIHwgVGVtcGxhdGVSZWY8YW55PjtcblxuICAvKipcbiAgICogTGFiZWwgZm9yIGRhdGUgcmFuZ2Ugc2VsZWN0b3IuXG4gICAqL1xuICBASW5wdXQoKSByYW5nZUxhYmVsOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHBsYWNlaG9sZGVyIHRleHQuXG4gICAqL1xuICBASW5wdXQoKSBwbGFjZWhvbGRlciA9ICdkZC9tbS95eXl5JztcblxuICAvKipcbiAgICogU2V0cyB0aGUgcGF0dGVybiB0byBmb2xsb3cuXG4gICAqL1xuICBASW5wdXQoKSBwYXR0ZXJuID0gJ15cXFxcZHsxLDJ9L1xcXFxkezEsMn0vXFxcXGR7NH0kJztcblxuICAvKipcbiAgICogRGF0ZSBwaWNrZXIgaWQuXG4gICAqL1xuICBASW5wdXQoKSBpZCA9IGBkYXRlcGlja2VyLSR7RGF0ZVBpY2tlci5kYXRlUGlja2VyQ291bnQrK31gO1xuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSB2YWx1ZS5cbiAgICovXG4gIEBJbnB1dCgpIHNldCB2YWx1ZSh2OiAoRGF0ZSB8IHN0cmluZylbXSkge1xuICAgIGlmICghdikge1xuICAgICAgdiA9IFtdO1xuICAgIH1cbiAgICB0aGlzLl92YWx1ZSA9IHY7XG4gIH1cblxuICBnZXQgdmFsdWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0byBgdHJ1ZWAgdG8gZGlzYWJsZSB0aGUgYERhdGVwaWNrZXJgXG4gICAqL1xuICBASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBTZXQgdG8gYHRydWVgIHRvIGRpc3BsYXkgaW52YWxpZCBzdGF0ZS5cbiAgICovXG4gIEBJbnB1dCgpIGludmFsaWQgPSBmYWxzZTtcblxuICAvKipcbiAgICogRmVlZGJhY2sgbWVzc2FnZSB0byBkaXNwbGF5IHdoZW4gYERhdGVwaWNrZXJgIGlzIGludmFsaWQuXG4gICAqL1xuICBASW5wdXQoKSBpbnZhbGlkVGV4dDogc3RyaW5nIHwgVGVtcGxhdGVSZWY8YW55PjtcblxuICAvKipcbiAgICogU2tlbGV0b24gc3RhdGUuXG4gICAqL1xuICBASW5wdXQoKSBza2VsZXRvbiA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBBcnJheSBvZiBkYXRlIHBpY2tlciBwbHVnaW5zLlxuICAgKi9cbiAgQElucHV0KCkgcGx1Z2lucyA9IFtdO1xuXG4gIC8qKlxuICAgKiBGbGF0cGlja3Igb3B0aW9uc1xuICAgKi9cbiAgQElucHV0KClcbiAgc2V0IGZsYXRwaWNrck9wdGlvbnMob3B0aW9ucykge1xuICAgIHRoaXMuX2ZsYXRwaWNrck9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLl9mbGF0cGlja3JPcHRpb25zLCBvcHRpb25zKTtcbiAgfVxuICBnZXQgZmxhdHBpY2tyT3B0aW9ucygpIHtcbiAgICBjb25zdCBwbHVnaW5zID0gWy4uLnRoaXMucGx1Z2lucywgc3VrYUZsYXRwaWNrck1vbnRoU2VsZWN0UGx1Z2luXTtcbiAgICBpZiAodGhpcy5yYW5nZSkge1xuICAgICAgcGx1Z2lucy5wdXNoKHJhbmdlUGx1Z2luKHsgaW5wdXQ6IGAjJHt0aGlzLmlkfS1yYW5nZUlucHV0YCwgcG9zaXRpb246ICdsZWZ0JyB9KSk7XG4gICAgfVxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCB0aGlzLl9mbGF0cGlja3JPcHRpb25zLCB0aGlzLmZsYXRwaWNrckJhc2VPcHRpb25zLCB7XG4gICAgICBtb2RlOiB0aGlzLnJhbmdlID8gJ3JhbmdlJyA6ICdzaW5nbGUnLFxuICAgICAgcGx1Z2lucyxcbiAgICAgIGRhdGVGb3JtYXQ6IHRoaXMuZGF0ZUZvcm1hdCxcbiAgICAgIGVuYWJsZVRpbWU6IHRoaXMuaGFzVGltZSxcbiAgICAgIG5vQ2FsZW5kYXI6IHRoaXMubm9DYWxlbmRhcixcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbWl0cyBldmVudCBub3RpZnlpbmcgb3RoZXIgY2xhc3NlcyBvZiBhIGNoYW5nZS5cbiAgICovXG4gIEBPdXRwdXQoKSB2YWx1ZUNoYW5nZTogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcHJvdGVjdGVkIF92YWx1ZSA9IFtdO1xuXG4gIHByb3RlY3RlZCBfZmxhdHBpY2tyT3B0aW9ucyA9IHtcbiAgICBhbGxvd0lucHV0OiB0cnVlXG4gIH07XG5cbiAgcHJvdGVjdGVkIGZsYXRwaWNrckJhc2VPcHRpb25zID0ge1xuICAgIG1vZGU6ICdzaW5nbGUnLFxuICAgIGRhdGVGb3JtYXQ6ICdkL20vWScsXG4gICAgbG9jYWxlOiBTcGFuaXNoLFxuICAgIHBsdWdpbnM6IHRoaXMucGx1Z2lucyxcbiAgICBvbk9wZW46ICgpID0+IHsgdGhpcy51cGRhdGVDbGFzc05hbWVzKCk7IH0sXG4gICAgdmFsdWU6IHRoaXMudmFsdWVcbiAgfTtcblxuICBwcm90ZWN0ZWQgZmxhdHBpY2tySW5zdGFuY2UgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCBlbGVtZW50UmVmOiBFbGVtZW50UmVmKSB7IH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKHRoaXMuaXNGbGF0cGlja3JMb2FkZWQoKSkge1xuICAgICAgbGV0IGRhdGVzID0gdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5zZWxlY3RlZERhdGVzO1xuICAgICAgaWYgKGNoYW5nZXMudmFsdWUgJiYgdGhpcy5kaWREYXRlVmFsdWVDaGFuZ2UoY2hhbmdlcy52YWx1ZS5jdXJyZW50VmFsdWUsIGNoYW5nZXMudmFsdWUucHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgZGF0ZXMgPSBjaGFuZ2VzLnZhbHVlLmN1cnJlbnRWYWx1ZTtcbiAgICAgIH1cbiAgICAgIC8vIG9ubHkgcmVzZXQgdGhlIGZsYXRwaWNrciBpbnN0YW5jZSBvbiBJbnB1dCBjaGFuZ2VzXG4gICAgICB0aGlzLmZsYXRwaWNrckluc3RhbmNlID0gZmxhdHBpY2tyKGAjJHt0aGlzLmlkfWAsIHRoaXMuZmxhdHBpY2tyT3B0aW9ucyk7XG4gICAgICB0aGlzLnNldERhdGVWYWx1ZXMoZGF0ZXMpO1xuICAgIH1cbiAgfVxuXG4gIC8vIGJlY2F1c2UgdGhlIGFjdHVhbCB2aWV3IG1heSBiZSBkZWxheWVkIGluIGxvYWRpbmcgKHRoaW5rIHByb2plY3Rpb24gaW50byBhIHRhYiBwYW5lKVxuICAvLyBhbmQgYmVjYXVzZSB3ZSByZWx5IG9uIGEgbGlicmFyeSB0aGF0IG9wZXJhdGVzIG91dHNpZGUgdGhlIEFuZ3VsYXIgdmlldyBvZiB0aGUgd29ybGRcbiAgLy8gd2UgbmVlZCB0byBrZWVwIHRyeWluZyB0byBsb2FkIHRoZSBsaWJyYXJ5LCB1bnRpbCB0aGUgcmVsZXZhbnQgRE9NIGlzIGFjdHVhbGx5IGxpdmVcbiAgbmdBZnRlclZpZXdDaGVja2VkKCkge1xuICAgIGlmICghdGhpcy5pc0ZsYXRwaWNrckxvYWRlZCgpKSB7XG4gICAgICB0aGlzLmZsYXRwaWNrckluc3RhbmNlID0gZmxhdHBpY2tyKGAjJHt0aGlzLmlkfWAsIHRoaXMuZmxhdHBpY2tyT3B0aW9ucyk7XG5cbiAgICAgIC8vIGlmIChhbmQgb25seSBpZikgdGhlIGluaXRpYWxpemF0aW9uIHN1Y2NlZWRlZCwgd2UgY2FuIHNldCB0aGUgZGF0ZSB2YWx1ZXNcbiAgICAgIGlmICh0aGlzLmlzRmxhdHBpY2tyTG9hZGVkKCkpIHtcbiAgICAgICAgaWYgKHRoaXMudmFsdWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHRoaXMuc2V0RGF0ZVZhbHVlcyh0aGlzLnZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2ZvY3VzaW4nKVxuICBvbkZvY3VzKCkge1xuICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gIH1cblxuICAvKipcbiAgICogV3JpdGVzIGEgdmFsdWUgZnJvbSB0aGUgbW9kZWwgdG8gdGhlIGNvbXBvbmVudC4gRXhwZWN0cyB0aGUgdmFsdWUgdG8gYmUgYG51bGxgIG9yIGAoRGF0ZSB8IHN0cmluZylbXWBcbiAgICogQHBhcmFtIHZhbHVlIHZhbHVlIHJlY2VpdmVkIGZyb20gdGhlIG1vZGVsXG4gICAqL1xuICB3cml0ZVZhbHVlKHZhbHVlOiAoRGF0ZSB8IHN0cmluZylbXSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICBpZiAodGhpcy5pc0ZsYXRwaWNrckxvYWRlZCgpICYmIHRoaXMuZmxhdHBpY2tySW5zdGFuY2UuY29uZmlnKSB7XG4gICAgICB0aGlzLnNldERhdGVWYWx1ZXModGhpcy52YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogYW55KSB7XG4gICAgdGhpcy5wcm9wYWdhdGVDaGFuZ2UgPSBmbjtcbiAgfVxuXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiBhbnkpIHtcbiAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICB9XG5cbiAgb25Ub3VjaGVkOiAoKSA9PiBhbnkgPSAoKSA9PiB7IH07XG5cbiAgcHJvcGFnYXRlQ2hhbmdlID0gKF86IGFueSkgPT4geyB9O1xuXG4gIC8qKlxuICAgKiBDbGVhbnMgdXAgb3VyIGZsYXRwaWNrciBpbnN0YW5jZVxuICAgKi9cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgaWYgKCF0aGlzLmlzRmxhdHBpY2tyTG9hZGVkKCkpIHsgcmV0dXJuOyB9XG4gICAgdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5kZXN0cm95KCk7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyB0aGUgYHZhbHVlQ2hhbmdlYCBldmVudCBmcm9tIHRoZSBwcmltYXJ5L3NpbmdsZSBpbnB1dFxuICAgKi9cbiAgb25WYWx1ZUNoYW5nZShldmVudDogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuaXNGbGF0cGlja3JMb2FkZWQoKSkge1xuICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuZmxhdHBpY2tySW5zdGFuY2UucGFyc2VEYXRlKGV2ZW50LCB0aGlzLmRhdGVGb3JtYXQpO1xuICAgICAgaWYgKHRoaXMucmFuZ2UpIHtcbiAgICAgICAgdGhpcy5zZXREYXRlVmFsdWVzKFtkYXRlLCB0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNlbGVjdGVkRGF0ZXNbMV1dKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc2V0RGF0ZVZhbHVlcyhbZGF0ZV0pO1xuICAgICAgfVxuICAgICAgdGhpcy5kb1NlbGVjdCh0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNlbGVjdGVkRGF0ZXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIHRoZSBgdmFsdWVDaGFuZ2VgIGV2ZW50IGZyb20gdGhlIHJhbmdlIGlucHV0XG4gICAqL1xuICBvblJhbmdlVmFsdWVDaGFuZ2UoZXZlbnQ6IHN0cmluZykge1xuICAgIGlmICh0aGlzLmlzRmxhdHBpY2tyTG9hZGVkKCkpIHtcbiAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLmZsYXRwaWNrckluc3RhbmNlLnBhcnNlRGF0ZShldmVudCwgdGhpcy5kYXRlRm9ybWF0KTtcbiAgICAgIHRoaXMuc2V0RGF0ZVZhbHVlcyhbdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5zZWxlY3RlZERhdGVzWzBdLCBkYXRlXSk7XG4gICAgICB0aGlzLmRvU2VsZWN0KHRoaXMuZmxhdHBpY2tySW5zdGFuY2Uuc2VsZWN0ZWREYXRlcyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFN1a2EgdXNlcyBhIG51bWJlciBvZiBzcGVjaWZpYyBjbGFzc25hbWVzIGZvciBwYXJ0cyBvZiB0aGUgZmxhdHBpY2tyIC0gdGhpcyBpZGVtcG90ZW50IG1ldGhvZCBhcHBsaWVzIHRoZW0gaWYgbmVlZGVkLlxuICAgKi9cbiAgcHJvdGVjdGVkIHVwZGF0ZUNsYXNzTmFtZXMoKSB7XG4gICAgaWYgKCF0aGlzLmVsZW1lbnRSZWYpIHsgcmV0dXJuOyB9XG5cbiAgICAvLyBnZXQgYWxsIHRoZSBwb3NzaWJsZSBmbGF0cGlja3JzIGluIHRoZSBkb2N1bWVudCAtIHdlIG5lZWQgdG8gYWRkIGNsYXNzZXMgdG8gKHBvdGVudGlhbGx5KSBhbGwgb2YgdGhlbVxuICAgIGNvbnN0IGNhbGVuZGFyQ29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmZsYXRwaWNrci1jYWxlbmRhcicpO1xuICAgIGNvbnN0IG1vbnRoQ29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmZsYXRwaWNrci1tb250aCcpO1xuICAgIGNvbnN0IHdlZWtkYXlzQ29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmZsYXRwaWNrci13ZWVrZGF5cycpO1xuICAgIGNvbnN0IHdlZWtkYXlDb250YWluZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuZmxhdHBpY2tyLXdlZWtkYXknKTtcbiAgICBjb25zdCBkYXlzQ29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmZsYXRwaWNrci1kYXlzJyk7XG4gICAgY29uc3QgZGF5Q29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmZsYXRwaWNrci1kYXknKTtcblxuICAgIC8vIGFkZCBjbGFzc2VzIHRvIGxpc3RzIG9mIGVsZW1lbnRzXG4gICAgY29uc3QgYWRkQ2xhc3NJZk5vdEV4aXN0cyA9IChjbGFzc25hbWU6IHN0cmluZywgZWxlbWVudExpc3Q6IE5vZGVMaXN0T2Y8RWxlbWVudD4pID0+IHtcbiAgICAgIEFycmF5LmZyb20oZWxlbWVudExpc3QpLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgIGlmICghZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoY2xhc3NuYW1lKSkge1xuICAgICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZChjbGFzc25hbWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgLy8gYWRkIGNsYXNzZXMgKGJ1dCBvbmx5IGlmIHRoZXkgZG9uJ3QgZXhpc3QsIHNtYWxsIHBlcmYgd2luKVxuICAgIGFkZENsYXNzSWZOb3RFeGlzdHMoJ2RhdGUtcGlja2VyX19jYWxlbmRhcicsIGNhbGVuZGFyQ29udGFpbmVyKTtcbiAgICBhZGRDbGFzc0lmTm90RXhpc3RzKCdkYXRlLXBpY2tlcl9fbW9udGgnLCBtb250aENvbnRhaW5lcik7XG4gICAgYWRkQ2xhc3NJZk5vdEV4aXN0cygnZGF0ZS1waWNrZXJfX3dlZWtkYXlzJywgd2Vla2RheXNDb250YWluZXIpO1xuICAgIGFkZENsYXNzSWZOb3RFeGlzdHMoJ2RhdGUtcGlja2VyX19kYXlzJywgZGF5c0NvbnRhaW5lcik7XG5cbiAgICAvLyBhZGQgd2Vla2RheSBjbGFzc2VzIGFuZCBmb3JtYXQgdGhlIHRleHRcbiAgICBBcnJheS5mcm9tKHdlZWtkYXlDb250YWluZXIpLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICBlbGVtZW50LmlubmVySFRNTCA9IGVsZW1lbnQuaW5uZXJIVE1MLnJlcGxhY2UoL1xccysvZywgJycpO1xuICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKCdkYXRlLXBpY2tlcl9fd2Vla2RheScpO1xuICAgIH0pO1xuXG4gICAgLy8gYWRkIGRheSBjbGFzc2VzIGFuZCBzcGVjaWFsIGNhc2UgdGhlIFwidG9kYXlcIiBlbGVtZW50IGJhc2VkIG9uIGB0aGlzLnZhbHVlYFxuICAgIEFycmF5LmZyb20oZGF5Q29udGFpbmVyKS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKCdkYXRlLXBpY2tlcl9fZGF5Jyk7XG4gICAgICBpZiAoIXRoaXMudmFsdWUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCd0b2RheScpICYmIHRoaXMudmFsdWUubGVuZ3RoID4gMCkge1xuICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoJ25vLWJvcmRlcicpO1xuICAgICAgfSBlbHNlIGlmIChlbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygndG9kYXknKSAmJiB0aGlzLnZhbHVlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoJ25vLWJvcmRlcicpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgdGhlIGdpdmVuIGRhdGUgdmFsdWUgYXJyYXkgdG8gYm90aCB0aGUgZmxhdHBpY2tyIGluc3RhbmNlIGFuZCB0aGUgYGlucHV0YChzKVxuICAgKiBAcGFyYW0gZGF0ZXMgdGhlIGRhdGUgdmFsdWVzIHRvIGFwcGx5XG4gICAqL1xuICBwcm90ZWN0ZWQgc2V0RGF0ZVZhbHVlcyhkYXRlczogKERhdGUgfCBzdHJpbmcpW10pIHtcbiAgICBpZiAodGhpcy5pc0ZsYXRwaWNrckxvYWRlZCgpKSB7XG4gICAgICBjb25zdCBzaW5nbGVJbnB1dCA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoYCMke3RoaXMuaWR9YCk7XG4gICAgICBjb25zdCByYW5nZUlucHV0ID0gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcihgIyR7dGhpcy5pZH0tcmFuZ2VJbnB1dGApO1xuXG4gICAgICAvLyBzZXQgdGhlIGRhdGUgb24gdGhlIGluc3RhbmNlXG4gICAgICB0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNldERhdGUoZGF0ZXMpO1xuXG4gICAgICAvLyB3ZSBjYW4gZWl0aGVyIHNldCBhIGRhdGUgdmFsdWUgb3IgYW4gZW1wdHkgc3RyaW5nLCBzbyB3ZSBzdGFydCB3aXRoIGFuIGVtcHR5IHN0cmluZ1xuICAgICAgbGV0IHNpbmdsZURhdGUgPSAnJztcbiAgICAgIC8vIGlmIGRhdGUgaXMgYSBzdHJpbmcsIHBhcnNlIGFuZCBmb3JtYXRcbiAgICAgIGlmICh0eXBlb2YgdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5zZWxlY3RlZERhdGVzWzBdID09PSAnc3RyaW5nJykge1xuICAgICAgICBzaW5nbGVEYXRlID0gdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5wYXJzZURhdGUodGhpcy5mbGF0cGlja3JJbnN0YW5jZS5zZWxlY3RlZERhdGVzWzBdLCB0aGlzLmRhdGVGb3JtYXQpO1xuICAgICAgICBzaW5nbGVEYXRlID0gdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5mb3JtYXREYXRlKHNpbmdsZURhdGUsIHRoaXMuZGF0ZUZvcm1hdCk7XG4gICAgICAgIC8vIGlmIGRhdGUgaXMgbm90IGEgc3RyaW5nIHdlIGNhbiBhc3N1bWUgaXQncyBhIERhdGUgYW5kIHdlIHNob3VsZCBmb3JtYXRcbiAgICAgIH0gZWxzZSBpZiAoISF0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNlbGVjdGVkRGF0ZXNbMF0pIHtcbiAgICAgICAgc2luZ2xlRGF0ZSA9IHRoaXMuZmxhdHBpY2tySW5zdGFuY2UuZm9ybWF0RGF0ZSh0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNlbGVjdGVkRGF0ZXNbMF0sIHRoaXMuZGF0ZUZvcm1hdCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChyYW5nZUlucHV0KSB7XG4gICAgICAgIC8vIHdlIGNhbiBlaXRoZXIgc2V0IGEgZGF0ZSB2YWx1ZSBvciBhbiBlbXB0eSBzdHJpbmcsIHNvIHdlIHN0YXJ0IHdpdGggYW4gZW1wdHkgc3RyaW5nXG4gICAgICAgIGxldCByYW5nZURhdGUgPSAnJztcbiAgICAgICAgLy8gaWYgZGF0ZSBpcyBhIHN0cmluZywgcGFyc2UgYW5kIGZvcm1hdFxuICAgICAgICBpZiAodHlwZW9mIHRoaXMuZmxhdHBpY2tySW5zdGFuY2Uuc2VsZWN0ZWREYXRlc1sxXSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICByYW5nZURhdGUgPSB0aGlzLmZsYXRwaWNrckluc3RhbmNlLnBhcnNlRGF0ZSh0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNlbGVjdGVkRGF0ZXNbMV0udG9TdHJpbmcoKSwgdGhpcy5kYXRlRm9ybWF0KTtcbiAgICAgICAgICByYW5nZURhdGUgPSB0aGlzLmZsYXRwaWNrckluc3RhbmNlLmZvcm1hdERhdGUocmFuZ2VEYXRlLCB0aGlzLmRhdGVGb3JtYXQpO1xuICAgICAgICAgIC8vIGlmIGRhdGUgaXMgbm90IGEgc3RyaW5nIHdlIGNhbiBhc3N1bWUgaXQncyBhIERhdGUgYW5kIHdlIHNob3VsZCBmb3JtYXRcbiAgICAgICAgfSBlbHNlIGlmICghIXRoaXMuZmxhdHBpY2tySW5zdGFuY2Uuc2VsZWN0ZWREYXRlc1sxXSkge1xuICAgICAgICAgIHJhbmdlRGF0ZSA9IHRoaXMuZmxhdHBpY2tySW5zdGFuY2UuZm9ybWF0RGF0ZSh0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNlbGVjdGVkRGF0ZXNbMV0sIHRoaXMuZGF0ZUZvcm1hdCk7XG4gICAgICAgIH1cbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgLy8gYXBwbHkgdGhlIHZhbHVlc1xuICAgICAgICAgIHJhbmdlSW5wdXQudmFsdWUgPSByYW5nZURhdGU7XG4gICAgICAgICAgc2luZ2xlSW5wdXQudmFsdWUgPSBzaW5nbGVEYXRlO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgZG9TZWxlY3Qoc2VsZWN0ZWRWYWx1ZTogKERhdGUgfCBzdHJpbmcpW10pIHtcbiAgICB0aGlzLnZhbHVlQ2hhbmdlLmVtaXQoc2VsZWN0ZWRWYWx1ZSk7XG4gICAgdGhpcy5wcm9wYWdhdGVDaGFuZ2Uoc2VsZWN0ZWRWYWx1ZSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZGlkRGF0ZVZhbHVlQ2hhbmdlKGN1cnJlbnRWYWx1ZSwgcHJldmlvdXNWYWx1ZSkge1xuICAgIHJldHVybiBjdXJyZW50VmFsdWVbMF0gIT09IHByZXZpb3VzVmFsdWVbMF0gfHwgY3VycmVudFZhbHVlWzFdICE9PSBwcmV2aW91c1ZhbHVlWzFdO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vcmUgYWR2YW5jZWQgY2hlY2tpbmcgb2YgdGhlIGxvYWRlZCBzdGF0ZSBvZiBmbGF0cGlja3JcbiAgICovXG4gIHByb3RlY3RlZCBpc0ZsYXRwaWNrckxvYWRlZCgpIHtcbiAgICAvLyBjYXN0IHRoZSBpbnN0YW5jZSB0byBhIGJvb2xlYW4sIGFuZCBzb21lIG1ldGhvZCB0aGF0IGhhcyB0byBleGlzdCBmb3IgdGhlIGxpYnJhcnkgdG8gYmUgbG9hZGVkIGluIHRoaXMgY2FzZSBgc2V0RGF0ZWBcbiAgICByZXR1cm4gISF0aGlzLmZsYXRwaWNrckluc3RhbmNlICYmICEhdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5zZXREYXRlO1xuICB9XG59XG4iXX0=