@ng-bootstrap/ng-bootstrap
Version:
Angular powered Bootstrap
286 lines • 36.5 kB
JavaScript
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Directive, ElementRef, EventEmitter, inject, Input, NgZone, Output, ViewEncapsulation, } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { listenToTriggers } from '../util/triggers';
import { ngbAutoClose } from '../util/autoclose';
import { ngbPositioning } from '../util/positioning';
import { PopupService } from '../util/popup';
import { isString } from '../util/util';
import { NgbTooltipConfig } from './tooltip-config';
import { addPopperOffset } from '../util/positioning-util';
import * as i0 from "@angular/core";
let nextId = 0;
export class NgbTooltipWindow {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbTooltipWindow, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.0", type: NgbTooltipWindow, isStandalone: true, selector: "ngb-tooltip-window", inputs: { animation: "animation", id: "id", tooltipClass: "tooltipClass" }, host: { attributes: { "role": "tooltip" }, properties: { "class": "\"tooltip\" + (tooltipClass ? \" \" + tooltipClass : \"\")", "class.fade": "animation", "id": "id" } }, ngImport: i0, template: `
<div class="tooltip-arrow" data-popper-arrow></div>
<div class="tooltip-inner">
<ng-content />
</div>
`, isInline: true, styles: ["ngb-tooltip-window{pointer-events:none;position:absolute}ngb-tooltip-window .tooltip-inner{pointer-events:auto}ngb-tooltip-window.bs-tooltip-top,ngb-tooltip-window.bs-tooltip-bottom{padding-left:0;padding-right:0}ngb-tooltip-window.bs-tooltip-start,ngb-tooltip-window.bs-tooltip-end{padding-top:0;padding-bottom:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbTooltipWindow, decorators: [{
type: Component,
args: [{ selector: 'ngb-tooltip-window', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
'[class]': '"tooltip" + (tooltipClass ? " " + tooltipClass : "")',
'[class.fade]': 'animation',
role: 'tooltip',
'[id]': 'id',
}, template: `
<div class="tooltip-arrow" data-popper-arrow></div>
<div class="tooltip-inner">
<ng-content />
</div>
`, styles: ["ngb-tooltip-window{pointer-events:none;position:absolute}ngb-tooltip-window .tooltip-inner{pointer-events:auto}ngb-tooltip-window.bs-tooltip-top,ngb-tooltip-window.bs-tooltip-bottom{padding-left:0;padding-right:0}ngb-tooltip-window.bs-tooltip-start,ngb-tooltip-window.bs-tooltip-end{padding-top:0;padding-bottom:0}\n"] }]
}], propDecorators: { animation: [{
type: Input
}], id: [{
type: Input
}], tooltipClass: [{
type: Input
}] } });
/**
* A lightweight and extensible directive for fancy tooltip creation.
*/
export class NgbTooltip {
constructor() {
this._config = inject(NgbTooltipConfig);
/**
* If `true`, tooltip opening and closing will be animated.
*
* @since 8.0.0
*/
this.animation = this._config.animation;
/**
* Indicates whether the tooltip should be closed on `Escape` key and inside/outside clicks:
*
* * `true` - closes on both outside and inside clicks as well as `Escape` presses
* * `false` - disables the autoClose feature (NB: triggers still apply)
* * `"inside"` - closes on inside clicks as well as Escape presses
* * `"outside"` - closes on outside clicks (sometimes also achievable through triggers)
* as well as `Escape` presses
*
* @since 3.0.0
*/
this.autoClose = this._config.autoClose;
/**
* The preferred placement of the tooltip, among the [possible values](#/guides/positioning#api).
*
* The default order of preference is `"auto"`.
*
* Please see the [positioning overview](#/positioning) for more details.
*/
this.placement = this._config.placement;
/**
* Allows to change default Popper options when positioning the tooltip.
* Receives current popper options and returns modified ones.
*
* @since 13.1.0
*/
this.popperOptions = this._config.popperOptions;
/**
* Specifies events that should trigger the tooltip.
*
* Supports a space separated list of event names.
* For more details see the [triggers demo](#/components/tooltip/examples#triggers).
*/
this.triggers = this._config.triggers;
/**
* A selector specifying the element the tooltip should be appended to.
*
* Currently only supports `"body"`.
*/
this.container = this._config.container;
/**
* If `true`, tooltip is disabled and won't be displayed.
*
* @since 1.1.0
*/
this.disableTooltip = this._config.disableTooltip;
/**
* An optional class applied to the tooltip window element.
*
* @since 3.2.0
*/
this.tooltipClass = this._config.tooltipClass;
/**
* The opening delay in ms. Works only for "non-manual" opening triggers defined by the `triggers` input.
*
* @since 4.1.0
*/
this.openDelay = this._config.openDelay;
/**
* The closing delay in ms. Works only for "non-manual" opening triggers defined by the `triggers` input.
*
* @since 4.1.0
*/
this.closeDelay = this._config.closeDelay;
/**
* An event emitted when the tooltip opening animation has finished. Contains no payload.
*/
this.shown = new EventEmitter();
/**
* An event emitted when the tooltip closing animation has finished. Contains no payload.
*/
this.hidden = new EventEmitter();
this._nativeElement = inject(ElementRef).nativeElement;
this._ngZone = inject(NgZone);
this._document = inject(DOCUMENT);
this._changeDetector = inject(ChangeDetectorRef);
this._ngbTooltipWindowId = `ngb-tooltip-${nextId++}`;
this._popupService = new PopupService(NgbTooltipWindow);
this._windowRef = null;
this._positioning = ngbPositioning();
}
/**
* The string content or a `TemplateRef` for the content to be displayed in the tooltip.
*
* If the content if falsy, the tooltip won't open.
*/
set ngbTooltip(value) {
this._ngbTooltip = value;
if (!value && this._windowRef) {
this.close();
}
}
get ngbTooltip() {
return this._ngbTooltip;
}
/**
* Opens the tooltip.
*
* This is considered to be a "manual" triggering.
* The `context` is an optional value to be injected into the tooltip template when it is created.
*/
open(context) {
if (!this._windowRef && this._ngbTooltip && !this.disableTooltip) {
const { windowRef, transition$ } = this._popupService.open(this._ngbTooltip, context ?? this.tooltipContext, this.animation);
this._windowRef = windowRef;
this._windowRef.setInput('animation', this.animation);
this._windowRef.setInput('tooltipClass', this.tooltipClass);
this._windowRef.setInput('id', this._ngbTooltipWindowId);
this._getPositionTargetElement().setAttribute('aria-describedby', this._ngbTooltipWindowId);
if (this.container === 'body') {
this._document.body.appendChild(this._windowRef.location.nativeElement);
}
// We need to detect changes, because we don't know where .open() might be called from.
// Ex. opening tooltip from one of lifecycle hooks that run after the CD
// (say from ngAfterViewInit) will result in 'ExpressionHasChanged' exception
this._windowRef.changeDetectorRef.detectChanges();
// We need to mark for check, because tooltip won't work inside the OnPush component.
// Ex. when we use expression like `{{ tooltip.isOpen() : 'opened' : 'closed' }}`
// inside the template of an OnPush component and we change the tooltip from
// open -> closed, the expression in question won't be updated unless we explicitly
// mark the parent component to be checked.
this._windowRef.changeDetectorRef.markForCheck();
// Setting up popper and scheduling updates when zone is stable
this._ngZone.runOutsideAngular(() => {
this._positioning.createPopper({
hostElement: this._getPositionTargetElement(),
targetElement: this._windowRef.location.nativeElement,
placement: this.placement,
appendToBody: this.container === 'body',
baseClass: 'bs-tooltip',
updatePopperOptions: (options) => this.popperOptions(addPopperOffset([0, 6])(options)),
});
Promise.resolve().then(() => {
// This update is required for correct arrow placement
this._positioning.update();
this._zoneSubscription = this._ngZone.onStable.subscribe(() => this._positioning.update());
});
});
ngbAutoClose(this._ngZone, this._document, this.autoClose, () => this.close(), this.hidden, [this._windowRef.location.nativeElement], [this._nativeElement]);
transition$.subscribe(() => this.shown.emit());
}
}
/**
* Closes the tooltip.
*
* This is considered to be a "manual" triggering of the tooltip.
*/
close(animation = this.animation) {
if (this._windowRef != null) {
this._getPositionTargetElement().removeAttribute('aria-describedby');
this._popupService.close(animation).subscribe(() => {
this._windowRef = null;
this._positioning.destroy();
this._zoneSubscription?.unsubscribe();
this.hidden.emit();
this._changeDetector.markForCheck();
});
}
}
/**
* Toggles the tooltip.
*
* This is considered to be a "manual" triggering of the tooltip.
*/
toggle() {
if (this._windowRef) {
this.close();
}
else {
this.open();
}
}
/**
* Returns `true`, if the popover is currently shown.
*/
isOpen() {
return this._windowRef != null;
}
ngOnInit() {
this._unregisterListenersFn = listenToTriggers(this._nativeElement, this.triggers, this.isOpen.bind(this), this.open.bind(this), this.close.bind(this), +this.openDelay, +this.closeDelay);
}
ngOnChanges({ tooltipClass }) {
if (tooltipClass && this.isOpen()) {
this._windowRef.setInput('tooltipClass', tooltipClass.currentValue);
}
}
ngOnDestroy() {
this.close(false);
// This check is needed as it might happen that ngOnDestroy is called before ngOnInit
// under certain conditions, see: https://github.com/ng-bootstrap/ng-bootstrap/issues/2199
this._unregisterListenersFn?.();
}
_getPositionTargetElement() {
return ((isString(this.positionTarget) ? this._document.querySelector(this.positionTarget) : this.positionTarget) ||
this._nativeElement);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbTooltip, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbTooltip, isStandalone: true, selector: "[ngbTooltip]", inputs: { animation: "animation", autoClose: "autoClose", placement: "placement", popperOptions: "popperOptions", triggers: "triggers", positionTarget: "positionTarget", container: "container", disableTooltip: "disableTooltip", tooltipClass: "tooltipClass", tooltipContext: "tooltipContext", openDelay: "openDelay", closeDelay: "closeDelay", ngbTooltip: "ngbTooltip" }, outputs: { shown: "shown", hidden: "hidden" }, exportAs: ["ngbTooltip"], usesOnChanges: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbTooltip, decorators: [{
type: Directive,
args: [{ selector: '[ngbTooltip]', standalone: true, exportAs: 'ngbTooltip' }]
}], propDecorators: { animation: [{
type: Input
}], autoClose: [{
type: Input
}], placement: [{
type: Input
}], popperOptions: [{
type: Input
}], triggers: [{
type: Input
}], positionTarget: [{
type: Input
}], container: [{
type: Input
}], disableTooltip: [{
type: Input
}], tooltipClass: [{
type: Input
}], tooltipContext: [{
type: Input
}], openDelay: [{
type: Input
}], closeDelay: [{
type: Input
}], shown: [{
type: Output
}], hidden: [{
type: Output
}], ngbTooltip: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbHRpcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy90b29sdGlwL3Rvb2x0aXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNOLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUVULFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBQ0wsTUFBTSxFQUlOLE1BQU0sRUFHTixpQkFBaUIsR0FDakIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTNDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNqRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDckQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXhDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRXBELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7QUFFM0QsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0FBcUJmLE1BQU0sT0FBTyxnQkFBZ0I7OEdBQWhCLGdCQUFnQjtrR0FBaEIsZ0JBQWdCLHFVQVBsQjs7Ozs7RUFLVDs7MkZBRVcsZ0JBQWdCO2tCQW5CNUIsU0FBUzsrQkFDQyxvQkFBb0IsY0FDbEIsSUFBSSxtQkFDQyx1QkFBdUIsQ0FBQyxNQUFNLGlCQUNoQyxpQkFBaUIsQ0FBQyxJQUFJLFFBQy9CO3dCQUNMLFNBQVMsRUFBRSxzREFBc0Q7d0JBQ2pFLGNBQWMsRUFBRSxXQUFXO3dCQUMzQixJQUFJLEVBQUUsU0FBUzt3QkFDZixNQUFNLEVBQUUs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WUFBWSxDQUFDLENBQUM7U0FDckU7SUFDRixDQUFDO0lBRUQsV0FBVztRQUNWLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbEIscUZBQXFGO1FBQ3JGLDBGQUEwRjtRQUMxRixJQUFJLENBQUMsc0JBQXNCLEVBQUUsRUFBRSxDQUFDO0lBQ2pDLENBQUM7SUFFTyx5QkFBeUI7UUFDaEMsT0FBTyxDQUNOLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDO1lBQ3pHLElBQUksQ0FBQyxjQUFjLENBQ25CLENBQUM7SUFDSCxDQUFDOzhHQXBSVyxVQUFVO2tHQUFWLFVBQVU7OzJGQUFWLFVBQVU7a0JBRHRCLFNBQVM7bUJBQUMsRUFBRSxRQUFRLEVBQUUsY0FBYyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRTs4QkFXdkUsU0FBUztzQkFBakIsS0FBSztnQkFhRyxTQUFTO3NCQUFqQixLQUFLO2dCQVNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBUUcsYUFBYTtzQkFBckIsS0FBSztnQkFRRyxRQUFRO3NCQUFoQixLQUFLO2dCQVFHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBT0csU0FBUztzQkFBakIsS0FBSztnQkFPRyxjQUFjO3NCQUF0QixLQUFLO2dCQU9HLFlBQVk7c0JBQXBCLEtBQUs7Z0JBT0csY0FBYztzQkFBdEIsS0FBSztnQkFPRyxTQUFTO3NCQUFqQixLQUFLO2dCQU9HLFVBQVU7c0JBQWxCLEtBQUs7Z0JBS0ksS0FBSztzQkFBZCxNQUFNO2dCQUtHLE1BQU07c0JBQWYsTUFBTTtnQkFxQkgsVUFBVTtzQkFEYixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcblx0Q2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG5cdENoYW5nZURldGVjdG9yUmVmLFxuXHRDb21wb25lbnQsXG5cdENvbXBvbmVudFJlZixcblx0RGlyZWN0aXZlLFxuXHRFbGVtZW50UmVmLFxuXHRFdmVudEVtaXR0ZXIsXG5cdGluamVjdCxcblx0SW5wdXQsXG5cdE5nWm9uZSxcblx0T25DaGFuZ2VzLFxuXHRPbkRlc3Ryb3ksXG5cdE9uSW5pdCxcblx0T3V0cHV0LFxuXHRTaW1wbGVDaGFuZ2VzLFxuXHRUZW1wbGF0ZVJlZixcblx0Vmlld0VuY2Fwc3VsYXRpb24sXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuXG5pbXBvcnQgeyBsaXN0ZW5Ub1RyaWdnZXJzIH0gZnJvbSAnLi4vdXRpbC90cmlnZ2Vycyc7XG5pbXBvcnQgeyBuZ2JBdXRvQ2xvc2UgfSBmcm9tICcuLi91dGlsL2F1dG9jbG9zZSc7XG5pbXBvcnQgeyBuZ2JQb3NpdGlvbmluZyB9IGZyb20gJy4uL3V0aWwvcG9zaXRpb25pbmcnO1xuaW1wb3J0IHsgUG9wdXBTZXJ2aWNlIH0gZnJvbSAnLi4vdXRpbC9wb3B1cCc7XG5pbXBvcnQgeyBpc1N0cmluZyB9IGZyb20gJy4uL3V0aWwvdXRpbCc7XG5cbmltcG9ydCB7IE5nYlRvb2x0aXBDb25maWcgfSBmcm9tICcuL3Rvb2x0aXAtY29uZmlnJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgYWRkUG9wcGVyT2Zmc2V0IH0gZnJvbSAnLi4vdXRpbC9wb3NpdGlvbmluZy11dGlsJztcblxubGV0IG5leHRJZCA9IDA7XG5cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogJ25nYi10b29sdGlwLXdpbmRvdycsXG5cdHN0YW5kYWxvbmU6IHRydWUsXG5cdGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuXHRlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuXHRob3N0OiB7XG5cdFx0J1tjbGFzc10nOiAnXCJ0b29sdGlwXCIgKyAodG9vbHRpcENsYXNzID8gXCIgXCIgKyB0b29sdGlwQ2xhc3MgOiBcIlwiKScsXG5cdFx0J1tjbGFzcy5mYWRlXSc6ICdhbmltYXRpb24nLFxuXHRcdHJvbGU6ICd0b29sdGlwJyxcblx0XHQnW2lkXSc6ICdpZCcsXG5cdH0sXG5cdHN0eWxlVXJsOiAnLi90b29sdGlwLnNjc3MnLFxuXHR0ZW1wbGF0ZTogYFxuXHRcdDxkaXYgY2xhc3M9XCJ0b29sdGlwLWFycm93XCIgZGF0YS1wb3BwZXItYXJyb3c+PC9kaXY+XG5cdFx0PGRpdiBjbGFzcz1cInRvb2x0aXAtaW5uZXJcIj5cblx0XHRcdDxuZy1jb250ZW50IC8+XG5cdFx0PC9kaXY+XG5cdGAsXG59KVxuZXhwb3J0IGNsYXNzIE5nYlRvb2x0aXBXaW5kb3cge1xuXHRASW5wdXQoKSBhbmltYXRpb246IGJvb2xlYW47XG5cdEBJbnB1dCgpIGlkOiBzdHJpbmc7XG5cdEBJbnB1dCgpIHRvb2x0aXBDbGFzczogc3RyaW5nO1xufVxuXG4vKipcbiAqIEEgbGlnaHR3ZWlnaHQgYW5kIGV4dGVuc2libGUgZGlyZWN0aXZlIGZvciBmYW5jeSB0b29sdGlwIGNyZWF0aW9uLlxuICovXG5ARGlyZWN0aXZlKHsgc2VsZWN0b3I6ICdbbmdiVG9vbHRpcF0nLCBzdGFuZGFsb25lOiB0cnVlLCBleHBvcnRBczogJ25nYlRvb2x0aXAnIH0pXG5leHBvcnQgY2xhc3MgTmdiVG9vbHRpcCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95LCBPbkNoYW5nZXMge1xuXHRzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfYXV0b0Nsb3NlOiBib29sZWFuIHwgc3RyaW5nO1xuXG5cdHByaXZhdGUgX2NvbmZpZyA9IGluamVjdChOZ2JUb29sdGlwQ29uZmlnKTtcblxuXHQvKipcblx0ICogSWYgYHRydWVgLCB0b29sdGlwIG9wZW5pbmcgYW5kIGNsb3Npbmcgd2lsbCBiZSBhbmltYXRlZC5cblx0ICpcblx0ICogQHNpbmNlIDguMC4wXG5cdCAqL1xuXHRASW5wdXQoKSBhbmltYXRpb24gPSB0aGlzLl9jb25maWcuYW5pbWF0aW9uO1xuXG5cdC8qKlxuXHQgKiBJbmRpY2F0ZXMgd2hldGhlciB0aGUgdG9vbHRpcCBzaG91bGQgYmUgY2xvc2VkIG9uIGBFc2NhcGVgIGtleSBhbmQgaW5zaWRlL291dHNpZGUgY2xpY2tzOlxuXHQgKlxuXHQgKiAqIGB0cnVlYCAtIGNsb3NlcyBvbiBib3RoIG91dHNpZGUgYW5kIGluc2lkZSBjbGlja3MgYXMgd2VsbCBhcyBgRXNjYXBlYCBwcmVzc2VzXG5cdCAqICogYGZhbHNlYCAtIGRpc2FibGVzIHRoZSBhdXRvQ2xvc2UgZmVhdHVyZSAoTkI6IHRyaWdnZXJzIHN0aWxsIGFwcGx5KVxuXHQgKiAqIGBcImluc2lkZVwiYCAtIGNsb3NlcyBvbiBpbnNpZGUgY2xpY2tzIGFzIHdlbGwgYXMgRXNjYXBlIHByZXNzZXNcblx0ICogKiBgXCJvdXRzaWRlXCJgIC0gY2xvc2VzIG9uIG91dHNpZGUgY2xpY2tzIChzb21ldGltZXMgYWxzbyBhY2hpZXZhYmxlIHRocm91Z2ggdHJpZ2dlcnMpXG5cdCAqIGFzIHdlbGwgYXMgYEVzY2FwZWAgcHJlc3Nlc1xuXHQgKlxuXHQgKiBAc2luY2UgMy4wLjBcblx0ICovXG5cdEBJbnB1dCgpIGF1dG9DbG9zZSA9IHRoaXMuX2NvbmZpZy5hdXRvQ2xvc2U7XG5cblx0LyoqXG5cdCAqIFRoZSBwcmVmZXJyZWQgcGxhY2VtZW50IG9mIHRoZSB0b29sdGlwLCBhbW9uZyB0aGUgW3Bvc3NpYmxlIHZhbHVlc10oIy9ndWlkZXMvcG9zaXRpb25pbmcjYXBpKS5cblx0ICpcblx0ICogVGhlIGRlZmF1bHQgb3JkZXIgb2YgcHJlZmVyZW5jZSBpcyBgXCJhdXRvXCJgLlxuXHQgKlxuXHQgKiBQbGVhc2Ugc2VlIHRoZSBbcG9zaXRpb25pbmcgb3ZlcnZpZXddKCMvcG9zaXRpb25pbmcpIGZvciBtb3JlIGRldGFpbHMuXG5cdCAqL1xuXHRASW5wdXQoKSBwbGFjZW1lbnQgPSB0aGlzLl9jb25maWcucGxhY2VtZW50O1xuXG5cdC8qKlxuXHQgKiBBbGxvd3MgdG8gY2hhbmdlIGRlZmF1bHQgUG9wcGVyIG9wdGlvbnMgd2hlbiBwb3NpdGlvbmluZyB0aGUgdG9vbHRpcC5cblx0ICogUmVjZWl2ZXMgY3VycmVudCBwb3BwZXIgb3B0aW9ucyBhbmQgcmV0dXJucyBtb2RpZmllZCBvbmVzLlxuXHQgKlxuXHQgKiBAc2luY2UgMTMuMS4wXG5cdCAqL1xuXHRASW5wdXQoKSBwb3BwZXJPcHRpb25zID0gdGhpcy5fY29uZmlnLnBvcHBlck9wdGlvbnM7XG5cblx0LyoqXG5cdCAqIFNwZWNpZmllcyBldmVudHMgdGhhdCBzaG91bGQgdHJpZ2dlciB0aGUgdG9vbHRpcC5cblx0ICpcblx0ICogU3VwcG9ydHMgYSBzcGFjZSBzZXBhcmF0ZWQgbGlzdCBvZiBldmVudCBuYW1lcy5cblx0ICogRm9yIG1vcmUgZGV0YWlscyBzZWUgdGhlIFt0cmlnZ2VycyBkZW1vXSgjL2NvbXBvbmVudHMvdG9vbHRpcC9leGFtcGxlcyN0cmlnZ2VycykuXG5cdCAqL1xuXHRASW5wdXQoKSB0cmlnZ2VycyA9IHRoaXMuX2NvbmZpZy50cmlnZ2VycztcblxuXHQvKipcblx0ICogQSBjc3Mgc2VsZWN0b3Igb3IgaHRtbCBlbGVtZW50IHNwZWNpZnlpbmcgdGhlIGVsZW1lbnQgdGhlIHRvb2x0aXAgc2hvdWxkIGJlIHBvc2l0aW9uZWQgYWdhaW5zdC5cblx0ICogQnkgZGVmYXVsdCwgdGhlIGVsZW1lbnQgYG5nYlRvb2x0aXBgIGRpcmVjdGl2ZSBpcyBhcHBsaWVkIHRvIHdpbGwgYmUgc2V0IGFzIGEgdGFyZ2V0LlxuXHQgKlxuXHQgKiBAc2luY2UgMTMuMS4wXG5cdCAqL1xuXHRASW5wdXQoKSBwb3NpdGlvblRhcmdldD86IHN0cmluZyB8IEhUTUxFbGVtZW50O1xuXG5cdC8qKlxuXHQgKiBBIHNlbGVjdG9yIHNwZWNpZnlpbmcgdGhlIGVsZW1lbnQgdGhlIHRvb2x0aXAgc2hvdWxkIGJlIGFwcGVuZGVkIHRvLlxuXHQgKlxuXHQgKiBDdXJyZW50bHkgb25seSBzdXBwb3J0cyBgXCJib2R5XCJgLlxuXHQgKi9cblx0QElucHV0KCkgY29udGFpbmVyID0gdGhpcy5fY29uZmlnLmNvbnRhaW5lcjtcblxuXHQvKipcblx0ICogSWYgYHRydWVgLCB0b29sdGlwIGlzIGRpc2FibGVkIGFuZCB3b24ndCBiZSBkaXNwbGF5ZWQuXG5cdCAqXG5cdCAqIEBzaW5jZSAxLjEuMFxuXHQgKi9cblx0QElucHV0KCkgZGlzYWJsZVRvb2x0aXAgPSB0aGlzLl9jb25maWcuZGlzYWJsZVRvb2x0aXA7XG5cblx0LyoqXG5cdCAqIEFuIG9wdGlvbmFsIGNsYXNzIGFwcGxpZWQgdG8gdGhlIHRvb2x0aXAgd2luZG93IGVsZW1lbnQuXG5cdCAqXG5cdCAqIEBzaW5jZSAzLjIuMFxuXHQgKi9cblx0QElucHV0KCkgdG9vbHRpcENsYXNzID0gdGhpcy5fY29uZmlnLnRvb2x0aXBDbGFzcztcblxuXHQvKipcblx0ICogRGVmYXVsdCB0ZW1wbGF0ZSBjb250ZXh0IGZvciBgVGVtcGxhdGVSZWZgLCBjYW4gYmUgb3ZlcnJpZGRlbiB3aXRoIGBvcGVuYCBtZXRob2QuXG5cdCAqXG5cdCAqIEBzaW5jZSAxNS4xLjBcblx0ICovXG5cdEBJbnB1dCgpIHRvb2x0aXBDb250ZXh0OiBhbnk7XG5cblx0LyoqXG5cdCAqIFRoZSBvcGVuaW5nIGRlbGF5IGluIG1zLiBXb3JrcyBvbmx5IGZvciBcIm5vbi1tYW51YWxcIiBvcGVuaW5nIHRyaWdnZXJzIGRlZmluZWQgYnkgdGhlIGB0cmlnZ2Vyc2AgaW5wdXQuXG5cdCAqXG5cdCAqIEBzaW5jZSA0LjEuMFxuXHQgKi9cblx0QElucHV0KCkgb3BlbkRlbGF5ID0gdGhpcy5fY29uZmlnLm9wZW5EZWxheTtcblxuXHQvKipcblx0ICogVGhlIGNsb3NpbmcgZGVsYXkgaW4gbXMuIFdvcmtzIG9ubHkgZm9yIFwibm9uLW1hbnVhbFwiIG9wZW5pbmcgdHJpZ2dlcnMgZGVmaW5lZCBieSB0aGUgYHRyaWdnZXJzYCBpbnB1dC5cblx0ICpcblx0ICogQHNpbmNlIDQuMS4wXG5cdCAqL1xuXHRASW5wdXQoKSBjbG9zZURlbGF5ID0gdGhpcy5fY29uZmlnLmNsb3NlRGVsYXk7XG5cblx0LyoqXG5cdCAqIEFuIGV2ZW50IGVtaXR0ZWQgd2hlbiB0aGUgdG9vbHRpcCBvcGVuaW5nIGFuaW1hdGlvbiBoYXMgZmluaXNoZWQuIENvbnRhaW5zIG5vIHBheWxvYWQuXG5cdCAqL1xuXHRAT3V0cHV0KCkgc2hvd24gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cblx0LyoqXG5cdCAqIEFuIGV2ZW50IGVtaXR0ZWQgd2hlbiB0aGUgdG9vbHRpcCBjbG9zaW5nIGFuaW1hdGlvbiBoYXMgZmluaXNoZWQuIENvbnRhaW5zIG5vIHBheWxvYWQuXG5cdCAqL1xuXHRAT3V0cHV0KCkgaGlkZGVuID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG5cdHByaXZhdGUgX25hdGl2ZUVsZW1lbnQgPSBpbmplY3QoRWxlbWVudFJlZikubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudDtcblx0cHJpdmF0ZSBfbmdab25lID0gaW5qZWN0KE5nWm9uZSk7XG5cdHByaXZhdGUgX2RvY3VtZW50ID0gaW5qZWN0KERPQ1VNRU5UKTtcblx0cHJpdmF0ZSBfY2hhbmdlRGV0ZWN0b3IgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuXG5cdHByaXZhdGUgX25nYlRvb2x0aXA6IHN0cmluZyB8IFRlbXBsYXRlUmVmPGFueT4gfCBudWxsIHwgdW5kZWZpbmVkO1xuXHRwcml2YXRlIF9uZ2JUb29sdGlwV2luZG93SWQgPSBgbmdiLXRvb2x0aXAtJHtuZXh0SWQrK31gO1xuXHRwcml2YXRlIF9wb3B1cFNlcnZpY2UgPSBuZXcgUG9wdXBTZXJ2aWNlKE5nYlRvb2x0aXBXaW5kb3cpO1xuXHRwcml2YXRlIF93aW5kb3dSZWY6IENvbXBvbmVudFJlZjxOZ2JUb29sdGlwV2luZG93PiB8IG51bGwgPSBudWxsO1xuXHRwcml2YXRlIF91bnJlZ2lzdGVyTGlzdGVuZXJzRm47XG5cdHByaXZhdGUgX3Bvc2l0aW9uaW5nID0gbmdiUG9zaXRpb25pbmcoKTtcblx0cHJpdmF0ZSBfem9uZVN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuXG5cdC8qKlxuXHQgKiBUaGUgc3RyaW5nIGNvbnRlbnQgb3IgYSBgVGVtcGxhdGVSZWZgIGZvciB0aGUgY29udGVudCB0byBiZSBkaXNwbGF5ZWQgaW4gdGhlIHRvb2x0aXAuXG5cdCAqXG5cdCAqIElmIHRoZSBjb250ZW50IGlmIGZhbHN5LCB0aGUgdG9vbHRpcCB3b24ndCBvcGVuLlxuXHQgKi9cblx0QElucHV0KClcblx0c2V0IG5nYlRvb2x0aXAodmFsdWU6IHN0cmluZyB8IFRlbXBsYXRlUmVmPGFueT4gfCBudWxsIHwgdW5kZWZpbmVkKSB7XG5cdFx0dGhpcy5fbmdiVG9vbHRpcCA9IHZhbHVlO1xuXHRcdGlmICghdmFsdWUgJiYgdGhpcy5fd2luZG93UmVmKSB7XG5cdFx0XHR0aGlzLmNsb3NlKCk7XG5cdFx0fVxuXHR9XG5cblx0Z2V0IG5nYlRvb2x0aXAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX25nYlRvb2x0aXA7XG5cdH1cblxuXHQvKipcblx0ICogT3BlbnMgdGhlIHRvb2x0aXAuXG5cdCAqXG5cdCAqIFRoaXMgaXMgY29uc2lkZXJlZCB0byBiZSBhIFwibWFudWFsXCIgdHJpZ2dlcmluZy5cblx0ICogVGhlIGBjb250ZXh0YCBpcyBhbiBvcHRpb25hbCB2YWx1ZSB0byBiZSBpbmplY3RlZCBpbnRvIHRoZSB0b29sdGlwIHRlbXBsYXRlIHdoZW4gaXQgaXMgY3JlYXRlZC5cblx0ICovXG5cdG9wZW4oY29udGV4dD86IGFueSkge1xuXHRcdGlmICghdGhpcy5fd2luZG93UmVmICYmIHRoaXMuX25nYlRvb2x0aXAgJiYgIXRoaXMuZGlzYWJsZVRvb2x0aXApIHtcblx0XHRcdGNvbnN0IHsgd2luZG93UmVmLCB0cmFuc2l0aW9uJCB9ID0gdGhpcy5fcG9wdXBTZXJ2aWNlLm9wZW4oXG5cdFx0XHRcdHRoaXMuX25nYlRvb2x0aXAsXG5cdFx0XHRcdGNvbnRleHQgPz8gdGhpcy50b29sdGlwQ29udGV4dCxcblx0XHRcdFx0dGhpcy5hbmltYXRpb24sXG5cdFx0XHQpO1xuXHRcdFx0dGhpcy5fd2luZG93UmVmID0gd2luZG93UmVmO1xuXHRcdFx0dGhpcy5fd2luZG93UmVmLnNldElucHV0KCdhbmltYXRpb24nLCB0aGlzLmFuaW1hdGlvbik7XG5cdFx0XHR0aGlzLl93aW5kb3dSZWYuc2V0SW5wdXQoJ3Rvb2x0aXBDbGFzcycsIHRoaXMudG9vbHRpcENsYXNzKTtcblx0XHRcdHRoaXMuX3dpbmRvd1JlZi5zZXRJbnB1dCgnaWQnLCB0aGlzLl9uZ2JUb29sdGlwV2luZG93SWQpO1xuXG5cdFx0XHR0aGlzLl9nZXRQb3NpdGlvblRhcmdldEVsZW1lbnQoKS5zZXRBdHRyaWJ1dGUoJ2FyaWEtZGVzY3JpYmVkYnknLCB0aGlzLl9uZ2JUb29sdGlwV2luZG93SWQpO1xuXG5cdFx0XHRpZiAodGhpcy5jb250YWluZXIgPT09ICdib2R5Jykge1xuXHRcdFx0XHR0aGlzLl9kb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuX3dpbmRvd1JlZi5sb2NhdGlvbi5uYXRpdmVFbGVtZW50KTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gV2UgbmVlZCB0byBkZXRlY3QgY2hhbmdlcywgYmVjYXVzZSB3ZSBkb24ndCBrbm93IHdoZXJlIC5vcGVuKCkgbWlnaHQgYmUgY2FsbGVkIGZyb20uXG5cdFx0XHQvLyBFeC4gb3BlbmluZyB0b29sdGlwIGZyb20gb25lIG9mIGxpZmVjeWNsZSBob29rcyB0aGF0IHJ1biBhZnRlciB0aGUgQ0Rcblx0XHRcdC8vIChzYXkgZnJvbSBuZ0FmdGVyVmlld0luaXQpIHdpbGwgcmVzdWx0IGluICdFeHByZXNzaW9uSGFzQ2hhbmdlZCcgZXhjZXB0aW9uXG5cdFx0XHR0aGlzLl93aW5kb3dSZWYuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuXG5cdFx0XHQvLyBXZSBuZWVkIHRvIG1hcmsgZm9yIGNoZWNrLCBiZWNhdXNlIHRvb2x0aXAgd29uJ3Qgd29yayBpbnNpZGUgdGhlIE9uUHVzaCBjb21wb25lbnQuXG5cdFx0XHQvLyBFeC4gd2hlbiB3ZSB1c2UgZXhwcmVzc2lvbiBsaWtlIGB7eyB0b29sdGlwLmlzT3BlbigpIDogJ29wZW5lZCcgOiAnY2xvc2VkJyB9fWBcblx0XHRcdC8vIGluc2lkZSB0aGUgdGVtcGxhdGUgb2YgYW4gT25QdXNoIGNvbXBvbmVudCBhbmQgd2UgY2hhbmdlIHRoZSB0b29sdGlwIGZyb21cblx0XHRcdC8vIG9wZW4gLT4gY2xvc2VkLCB0aGUgZXhwcmVzc2lvbiBpbiBxdWVzdGlvbiB3b24ndCBiZSB1cGRhdGVkIHVubGVzcyB3ZSBleHBsaWNpdGx5XG5cdFx0XHQvLyBtYXJrIHRoZSBwYXJlbnQgY29tcG9uZW50IHRvIGJlIGNoZWNrZWQuXG5cdFx0XHR0aGlzLl93aW5kb3dSZWYuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG5cblx0XHRcdC8vIFNldHRpbmcgdXAgcG9wcGVyIGFuZCBzY2hlZHVsaW5nIHVwZGF0ZXMgd2hlbiB6b25lIGlzIHN0YWJsZVxuXHRcdFx0dGhpcy5fbmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcblx0XHRcdFx0dGhpcy5fcG9zaXRpb25pbmcuY3JlYXRlUG9wcGVyKHtcblx0XHRcdFx0XHRob3N0RWxlbWVudDogdGhpcy5fZ2V0UG9zaXRpb25UYXJnZXRFbGVtZW50KCksXG5cdFx0XHRcdFx0dGFyZ2V0RWxlbWVudDogdGhpcy5fd2luZG93UmVmIS5sb2NhdGlvbi5uYXRpdmVFbGVtZW50LFxuXHRcdFx0XHRcdHBsYWNlbWVudDogdGhpcy5wbGFjZW1lbnQsXG5cdFx0XHRcdFx0YXBwZW5kVG9Cb2R5OiB0aGlzLmNvbnRhaW5lciA9PT0gJ2JvZHknLFxuXHRcdFx0XHRcdGJhc2VDbGFzczogJ2JzLXRvb2x0aXAnLFxuXHRcdFx0XHRcdHVwZGF0ZVBvcHBlck9wdGlvbnM6IChvcHRpb25zKSA9PiB0aGlzLnBvcHBlck9wdGlvbnMoYWRkUG9wcGVyT2Zmc2V0KFswLCA2XSkob3B0aW9ucykpLFxuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHRQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcblx0XHRcdFx0XHQvLyBUaGlzIHVwZGF0ZSBpcyByZXF1aXJlZCBmb3IgY29ycmVjdCBhcnJvdyBwbGFjZW1lbnRcblx0XHRcdFx0XHR0aGlzLl9wb3NpdGlvbmluZy51cGRhdGUoKTtcblx0XHRcdFx0XHR0aGlzLl96b25lU3Vic2NyaXB0aW9uID0gdGhpcy5fbmdab25lLm9uU3RhYmxlLnN1YnNjcmliZSgoKSA9PiB0aGlzLl9wb3NpdGlvbmluZy51cGRhdGUoKSk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSk7XG5cblx0XHRcdG5nYkF1dG9DbG9zZShcblx0XHRcdFx0dGhpcy5fbmdab25lLFxuXHRcdFx0XHR0aGlzLl9kb2N1bWVudCxcblx0XHRcdFx0dGhpcy5hdXRvQ2xvc2UsXG5cdFx0XHRcdCgpID0+IHRoaXMuY2xvc2UoKSxcblx0XHRcdFx0dGhpcy5oaWRkZW4sXG5cdFx0XHRcdFt0aGlzLl93aW5kb3dSZWYubG9jYXRpb24ubmF0aXZlRWxlbWVudF0sXG5cdFx0XHRcdFt0aGlzLl9uYXRpdmVFbGVtZW50XSxcblx0XHRcdCk7XG5cblx0XHRcdHRyYW5zaXRpb24kLnN1YnNjcmliZSgoKSA9PiB0aGlzLnNob3duLmVtaXQoKSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENsb3NlcyB0aGUgdG9vbHRpcC5cblx0ICpcblx0ICogVGhpcyBpcyBjb25zaWRlcmVkIHRvIGJlIGEgXCJtYW51YWxcIiB0cmlnZ2VyaW5nIG9mIHRoZSB0b29sdGlwLlxuXHQgKi9cblx0Y2xvc2UoYW5pbWF0aW9uID0gdGhpcy5hbmltYXRpb24pOiB2b2lkIHtcblx0XHRpZiAodGhpcy5fd2luZG93UmVmICE9IG51bGwpIHtcblx0XHRcdHRoaXMuX2dldFBvc2l0aW9uVGFyZ2V0RWxlbWVudCgpLnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1kZXNjcmliZWRieScpO1xuXHRcdFx0dGhpcy5fcG9wdXBTZXJ2aWNlLmNsb3NlKGFuaW1hdGlvbikuc3Vic2NyaWJlKCgpID0+IHtcblx0XHRcdFx0dGhpcy5fd2luZG93UmVmID0gbnVsbDtcblx0XHRcdFx0dGhpcy5fcG9zaXRpb25pbmcuZGVzdHJveSgpO1xuXHRcdFx0XHR0aGlzLl96b25lU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuXHRcdFx0XHR0aGlzLmhpZGRlbi5lbWl0KCk7XG5cdFx0XHRcdHRoaXMuX2NoYW5nZURldGVjdG9yLm1hcmtGb3JDaGVjaygpO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFRvZ2dsZXMgdGhlIHRvb2x0aXAuXG5cdCAqXG5cdCAqIFRoaXMgaXMgY29uc2lkZXJlZCB0byBiZSBhIFwibWFudWFsXCIgdHJpZ2dlcmluZyBvZiB0aGUgdG9vbHRpcC5cblx0ICovXG5cdHRvZ2dsZSgpOiB2b2lkIHtcblx0XHRpZiAodGhpcy5fd2luZG93UmVmKSB7XG5cdFx0XHR0aGlzLmNsb3NlKCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMub3BlbigpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGB0cnVlYCwgaWYgdGhlIHBvcG92ZXIgaXMgY3VycmVudGx5IHNob3duLlxuXHQgKi9cblx0aXNPcGVuKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLl93aW5kb3dSZWYgIT0gbnVsbDtcblx0fVxuXG5cdG5nT25Jbml0KCkge1xuXHRcdHRoaXMuX3VucmVnaXN0ZXJMaXN0ZW5lcnNGbiA9IGxpc3RlblRvVHJpZ2dlcnMoXG5cdFx0XHR0aGlzLl9uYXRpdmVFbGVtZW50LFxuXHRcdFx0dGhpcy50cmlnZ2Vycyxcblx0XHRcdHRoaXMuaXNPcGVuLmJpbmQodGhpcyksXG5cdFx0XHR0aGlzLm9wZW4uYmluZCh0aGlzKSxcblx0XHRcdHRoaXMuY2xvc2UuYmluZCh0aGlzKSxcblx0XHRcdCt0aGlzLm9wZW5EZWxheSxcblx0XHRcdCt0aGlzLmNsb3NlRGVsYXksXG5cdFx0KTtcblx0fVxuXG5cdG5nT25DaGFuZ2VzKHsgdG9vbHRpcENsYXNzIH06IFNpbXBsZUNoYW5nZXMpIHtcblx0XHRpZiAodG9vbHRpcENsYXNzICYmIHRoaXMuaXNPcGVuKCkpIHtcblx0XHRcdHRoaXMuX3dpbmRvd1JlZiEuc2V0SW5wdXQoJ3Rvb2x0aXBDbGFzcycsIHRvb2x0aXBDbGFzcy5jdXJyZW50VmFsdWUpO1xuXHRcdH1cblx0fVxuXG5cdG5nT25EZXN0cm95KCkge1xuXHRcdHRoaXMuY2xvc2UoZmFsc2UpO1xuXHRcdC8vIFRoaXMgY2hlY2sgaXMgbmVlZGVkIGFzIGl0IG1pZ2h0IGhhcHBlbiB0aGF0IG5nT25EZXN0cm95IGlzIGNhbGxlZCBiZWZvcmUgbmdPbkluaXRcblx0XHQvLyB1bmRlciBjZXJ0YWluIGNvbmRpdGlvbnMsIHNlZTogaHR0cHM6Ly9naXRodWIuY29tL25nLWJvb3RzdHJhcC9uZy1ib290c3RyYXAvaXNzdWVzLzIxOTlcblx0XHR0aGlzLl91bnJlZ2lzdGVyTGlzdGVuZXJzRm4/LigpO1xuXHR9XG5cblx0cHJpdmF0ZSBfZ2V0UG9zaXRpb25UYXJnZXRFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcblx0XHRyZXR1cm4gKFxuXHRcdFx0KGlzU3RyaW5nKHRoaXMucG9zaXRpb25UYXJnZXQpID8gdGhpcy5fZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLnBvc2l0aW9uVGFyZ2V0KSA6IHRoaXMucG9zaXRpb25UYXJnZXQpIHx8XG5cdFx0XHR0aGlzLl9uYXRpdmVFbGVtZW50XG5cdFx0KTtcblx0fVxufVxuIl19