UNPKG

@ng-bootstrap/ng-bootstrap

Version:
447 lines 51.4 kB
import { Attribute, ChangeDetectorRef, ContentChildren, DestroyRef, Directive, ElementRef, EventEmitter, forwardRef, inject, Input, Output, TemplateRef, } from '@angular/core'; import { DOCUMENT } from '@angular/common'; import { Subject } from 'rxjs'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { isDefined } from '../util/util'; import { NgbNavConfig } from './nav-config'; import { Key } from '../util/key'; import * as i0 from "@angular/core"; const isValidNavId = (id) => isDefined(id) && id !== ''; let navCounter = 0; /** * This directive must be used to wrap content to be displayed in the nav. * * @since 5.2.0 */ export class NgbNavContent { constructor() { this.templateRef = inject(TemplateRef); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNavContent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbNavContent, isStandalone: true, selector: "ng-template[ngbNavContent]", ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNavContent, decorators: [{ type: Directive, args: [{ selector: 'ng-template[ngbNavContent]', standalone: true }] }] }); /** * This directive applies a specific role on a non-container based ngbNavItem. * * @since 14.1.0 */ export class NgbNavItemRole { constructor(role) { this.role = role; this.nav = inject(NgbNav); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNavItemRole, deps: [{ token: 'role', attribute: true }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbNavItemRole, isStandalone: true, selector: "[ngbNavItem]:not(ng-container)", host: { properties: { "attr.role": "role ? role : nav.roles ? 'presentation' : undefined" } }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNavItemRole, decorators: [{ type: Directive, args: [{ selector: '[ngbNavItem]:not(ng-container)', standalone: true, host: { '[attr.role]': `role ? role : nav.roles ? 'presentation' : undefined`, }, }] }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Attribute, args: ['role'] }] }] }); /** * The directive used to group nav link and related nav content. As well as set nav identifier and some options. * * @since 5.2.0 */ export class NgbNavItem { constructor() { this._nav = inject(NgbNav); this._nativeElement = inject(ElementRef).nativeElement; /** * If `true`, the current nav item is disabled and can't be toggled by user. * * Nevertheless disabled nav can be selected programmatically via the `.select()` method and the `[activeId]` binding. */ this.disabled = false; /** * An event emitted when the fade in transition is finished on the related nav content * * @since 8.0.0 */ this.shown = new EventEmitter(); /** * An event emitted when the fade out transition is finished on the related nav content * * @since 8.0.0 */ this.hidden = new EventEmitter(); } ngAfterContentChecked() { // We are using @ContentChildren instead of @ContentChild as in the Angular version being used // only @ContentChildren allows us to specify the {descendants: false} option. // Without {descendants: false} we are hitting bugs described in: // https://github.com/ng-bootstrap/ng-bootstrap/issues/2240 this.contentTpl = this.contentTpls.first; } ngOnInit() { if (!isDefined(this.domId)) { this.domId = `ngb-nav-${navCounter++}`; } } get active() { return this._nav.activeId === this.id; } get id() { return isValidNavId(this._id) ? this._id : this.domId; } get panelDomId() { return `${this.domId}-panel`; } isPanelInDom() { return (isDefined(this.destroyOnHide) ? !this.destroyOnHide : !this._nav.destroyOnHide) || this.active; } /** * @internal */ isNgContainer() { return this._nativeElement.nodeType === Node.COMMENT_NODE; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNavItem, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbNavItem, isStandalone: true, selector: "[ngbNavItem]", inputs: { destroyOnHide: "destroyOnHide", disabled: "disabled", domId: "domId", _id: ["ngbNavItem", "_id"] }, outputs: { shown: "shown", hidden: "hidden" }, host: { properties: { "class.nav-item": "true" } }, queries: [{ propertyName: "contentTpls", predicate: NgbNavContent }], exportAs: ["ngbNavItem"], ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNavItem, decorators: [{ type: Directive, args: [{ selector: '[ngbNavItem]', exportAs: 'ngbNavItem', standalone: true, host: { '[class.nav-item]': 'true' } }] }], propDecorators: { destroyOnHide: [{ type: Input }], disabled: [{ type: Input }], domId: [{ type: Input }], _id: [{ type: Input, args: ['ngbNavItem'] }], shown: [{ type: Output }], hidden: [{ type: Output }], contentTpls: [{ type: ContentChildren, args: [NgbNavContent, { descendants: false }] }] } }); /** * A nav directive that helps with implementing tabbed navigation components. * * @since 5.2.0 */ export class NgbNav { constructor(role) { this.role = role; this._config = inject(NgbNavConfig); this._cd = inject(ChangeDetectorRef); this._document = inject(DOCUMENT); this._nativeElement = inject(ElementRef).nativeElement; this.destroyRef = inject(DestroyRef); this._navigatingWithKeyboard = false; /** * The event emitted after the active nav changes * The payload of the event is the newly active nav id * * If you want to prevent nav change, you should use `(navChange)` event */ this.activeIdChange = new EventEmitter(); /** * If `true`, nav change will be animated. * * @since 8.0.0 */ this.animation = this._config.animation; /** * If `true`, non-active nav content will be removed from DOM * Otherwise it will just be hidden */ this.destroyOnHide = this._config.destroyOnHide; /** * The orientation of navs. * * Using `vertical` will also add the `aria-orientation` attribute */ this.orientation = this._config.orientation; /** * Role attribute generating strategy: * - `false` - no role attributes will be generated * - `'tablist'` - 'tablist', 'tab' and 'tabpanel' will be generated (default) */ this.roles = this._config.roles; /** * Keyboard support for nav focus/selection using arrow keys. * * * `true` - navs will be focused using keyboard arrow keys * * `false` - no keyboard support * * `'changeWithArrows'` - nav will be selected using keyboard arrow keys * * See the [list of available keyboard shortcuts](#/components/nav/overview#keyboard-shortcuts). * * @since 6.1.0 */ this.keyboard = this._config.keyboard; /** * An event emitted when the fade in transition is finished for one of the items. * * Payload of the event is the nav id that was just shown. * * @since 8.0.0 */ this.shown = new EventEmitter(); /** * An event emitted when the fade out transition is finished for one of the items. * * Payload of the event is the nav id that was just hidden. * * @since 8.0.0 */ this.hidden = new EventEmitter(); this.navItemChange$ = new Subject(); /** * The nav change event emitted right before the nav change happens on user click. * * This event won't be emitted if nav is changed programmatically via `[activeId]` or `.select()`. * * See [`NgbNavChangeEvent`](#/components/nav/api#NgbNavChangeEvent) for payload details. */ this.navChange = new EventEmitter(); } click(item) { if (!item.disabled) { this._updateActiveId(item.id); } } onFocusout({ relatedTarget }) { if (!this._nativeElement.contains(relatedTarget)) { this._navigatingWithKeyboard = false; } } onKeyDown(event) { if (this.roles !== 'tablist' || !this.keyboard) { return; } /* eslint-disable-next-line deprecation/deprecation */ const key = event.which; const enabledLinks = this.links.filter((link) => !link.navItem.disabled); const { length } = enabledLinks; let position = -1; enabledLinks.forEach((link, index) => { if (link.nativeElement === this._document.activeElement) { position = index; } }); if (length) { switch (key) { case Key.ArrowUp: case Key.ArrowLeft: position = (position - 1 + length) % length; break; case Key.ArrowRight: case Key.ArrowDown: position = (position + 1) % length; break; case Key.Home: position = 0; break; case Key.End: position = length - 1; break; } if (this.keyboard === 'changeWithArrows') { this.select(enabledLinks[position].navItem.id); } enabledLinks[position].nativeElement.focus(); this._navigatingWithKeyboard = true; event.preventDefault(); } } /** * Selects the nav with the given id and shows its associated pane. * Any other nav that was previously selected becomes unselected and its associated pane is hidden. */ select(id) { this._updateActiveId(id, false); } ngAfterContentInit() { if (!isDefined(this.activeId)) { const nextId = this.items.first ? this.items.first.id : null; if (isValidNavId(nextId)) { this._updateActiveId(nextId, false); this._cd.detectChanges(); } } this.items.changes .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => this._notifyItemChanged(this.activeId)); } ngOnChanges({ activeId }) { if (activeId && !activeId.firstChange) { this._notifyItemChanged(activeId.currentValue); } } _updateActiveId(nextId, emitNavChange = true) { if (this.activeId !== nextId) { let defaultPrevented = false; if (emitNavChange) { this.navChange.emit({ activeId: this.activeId, nextId, preventDefault: () => { defaultPrevented = true; }, }); } if (!defaultPrevented) { this.activeId = nextId; this.activeIdChange.emit(nextId); this._notifyItemChanged(nextId); } } } _notifyItemChanged(nextItemId) { this.navItemChange$.next(this._getItemById(nextItemId)); } _getItemById(itemId) { return (this.items && this.items.find((item) => item.id === itemId)) || null; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNav, deps: [{ token: 'role', attribute: true }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbNav, isStandalone: true, selector: "[ngbNav]", inputs: { activeId: "activeId", animation: "animation", destroyOnHide: "destroyOnHide", orientation: "orientation", roles: "roles", keyboard: "keyboard" }, outputs: { activeIdChange: "activeIdChange", shown: "shown", hidden: "hidden", navChange: "navChange" }, host: { listeners: { "keydown.arrowLeft": "onKeyDown($event)", "keydown.arrowRight": "onKeyDown($event)", "keydown.arrowDown": "onKeyDown($event)", "keydown.arrowUp": "onKeyDown($event)", "keydown.Home": "onKeyDown($event)", "keydown.End": "onKeyDown($event)", "focusout": "onFocusout($event)" }, properties: { "class.nav": "true", "class.flex-column": "orientation === 'vertical'", "attr.aria-orientation": "orientation === 'vertical' && roles === 'tablist' ? 'vertical' : undefined", "attr.role": "role ? role : roles ? 'tablist' : undefined" } }, queries: [{ propertyName: "items", predicate: NgbNavItem }, { propertyName: "links", predicate: i0.forwardRef(() => NgbNavLinkBase), descendants: true }], exportAs: ["ngbNav"], usesOnChanges: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNav, decorators: [{ type: Directive, args: [{ selector: '[ngbNav]', exportAs: 'ngbNav', standalone: true, host: { '[class.nav]': 'true', '[class.flex-column]': `orientation === 'vertical'`, '[attr.aria-orientation]': `orientation === 'vertical' && roles === 'tablist' ? 'vertical' : undefined`, '[attr.role]': `role ? role : roles ? 'tablist' : undefined`, '(keydown.arrowLeft)': 'onKeyDown($event)', '(keydown.arrowRight)': 'onKeyDown($event)', '(keydown.arrowDown)': 'onKeyDown($event)', '(keydown.arrowUp)': 'onKeyDown($event)', '(keydown.Home)': 'onKeyDown($event)', '(keydown.End)': 'onKeyDown($event)', '(focusout)': 'onFocusout($event)', }, }] }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Attribute, args: ['role'] }] }], propDecorators: { activeId: [{ type: Input }], activeIdChange: [{ type: Output }], animation: [{ type: Input }], destroyOnHide: [{ type: Input }], orientation: [{ type: Input }], roles: [{ type: Input }], keyboard: [{ type: Input }], shown: [{ type: Output }], hidden: [{ type: Output }], items: [{ type: ContentChildren, args: [NgbNavItem] }], links: [{ type: ContentChildren, args: [forwardRef(() => NgbNavLinkBase), { descendants: true }] }], navChange: [{ type: Output }] } }); export class NgbNavLinkBase { constructor(role) { this.role = role; this.navItem = inject(NgbNavItem); this.nav = inject(NgbNav); this.nativeElement = inject(ElementRef).nativeElement; } get tabindex() { if (this.nav.keyboard === false) { return this.navItem.disabled ? -1 : undefined; } if (this.nav._navigatingWithKeyboard) { return -1; } return this.navItem.disabled || !this.navItem.active ? -1 : undefined; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNavLinkBase, deps: [{ token: 'role', attribute: true }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbNavLinkBase, isStandalone: true, selector: "[ngbNavLink]", host: { properties: { "id": "navItem.domId", "class.nav-link": "true", "class.nav-item": "navItem.isNgContainer()", "attr.role": "role ? role : nav.roles ? 'tab' : undefined", "class.active": "navItem.active", "class.disabled": "navItem.disabled", "attr.tabindex": "tabindex", "attr.aria-controls": "navItem.isPanelInDom() ? navItem.panelDomId : null", "attr.aria-selected": "navItem.active", "attr.aria-disabled": "navItem.disabled" } }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNavLinkBase, decorators: [{ type: Directive, args: [{ selector: '[ngbNavLink]', standalone: true, host: { '[id]': 'navItem.domId', '[class.nav-link]': 'true', '[class.nav-item]': 'navItem.isNgContainer()', '[attr.role]': `role ? role : nav.roles ? 'tab' : undefined`, '[class.active]': 'navItem.active', '[class.disabled]': 'navItem.disabled', '[attr.tabindex]': 'tabindex', '[attr.aria-controls]': 'navItem.isPanelInDom() ? navItem.panelDomId : null', '[attr.aria-selected]': 'navItem.active', '[attr.aria-disabled]': 'navItem.disabled', }, }] }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Attribute, args: ['role'] }] }] }); /** * A directive to mark the nav link when used on a button element. */ export class NgbNavLinkButton extends NgbNavLinkBase { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNavLinkButton, deps: null, target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbNavLinkButton, isStandalone: true, selector: "button[ngbNavLink]", host: { attributes: { "type": "button" }, listeners: { "click": "nav.click(navItem)" }, properties: { "disabled": "navItem.disabled" } }, usesInheritance: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNavLinkButton, decorators: [{ type: Directive, args: [{ selector: 'button[ngbNavLink]', standalone: true, host: { type: 'button', '[disabled]': 'navItem.disabled', '(click)': 'nav.click(navItem)', }, }] }] }); /** * A directive to mark the nav link when used on a link element. * * @since 5.2.0 */ export class NgbNavLink extends NgbNavLinkBase { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNavLink, deps: null, target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbNavLink, isStandalone: true, selector: "a[ngbNavLink]", host: { attributes: { "href": "" }, listeners: { "click": "nav.click(navItem); $event.preventDefault()" } }, usesInheritance: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbNavLink, decorators: [{ type: Directive, args: [{ selector: 'a[ngbNavLink]', standalone: true, host: { href: '', '(click)': 'nav.click(navItem); $event.preventDefault()', }, }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF2LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL25hdi9uYXYudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUdOLFNBQVMsRUFDVCxpQkFBaUIsRUFDakIsZUFBZSxFQUNmLFVBQVUsRUFDVixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixVQUFVLEVBQ1YsTUFBTSxFQUNOLEtBQUssRUFHTCxNQUFNLEVBR04sV0FBVyxHQUNYLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUUzQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRWhFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDekMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUM1QyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sYUFBYSxDQUFDOztBQUVsQyxNQUFNLFlBQVksR0FBRyxDQUFDLEVBQU8sRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUM7QUFFN0QsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0FBZ0JuQjs7OztHQUlHO0FBRUgsTUFBTSxPQUFPLGFBQWE7SUFEMUI7UUFFQyxnQkFBVyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztLQUNsQzs4R0FGWSxhQUFhO2tHQUFiLGFBQWE7OzJGQUFiLGFBQWE7a0JBRHpCLFNBQVM7bUJBQUMsRUFBRSxRQUFRLEVBQUUsNEJBQTRCLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRTs7QUFLdkU7Ozs7R0FJRztBQVFILE1BQU0sT0FBTyxjQUFjO0lBRzFCLFlBQXNDLElBQVk7UUFBWixTQUFJLEdBQUosSUFBSSxDQUFR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LGtCQUFrQixFQUFFLHlCQUF5Qjt3QkFDN0MsYUFBYSxFQUFFLDZDQUE2Qzt3QkFDNUQsZ0JBQWdCLEVBQUUsZ0JBQWdCO3dCQUNsQyxrQkFBa0IsRUFBRSxrQkFBa0I7d0JBQ3RDLGlCQUFpQixFQUFFLFVBQVU7d0JBQzdCLHNCQUFzQixFQUFFLG9EQUFvRDt3QkFDNUUsc0JBQXNCLEVBQUUsZ0JBQWdCO3dCQUN4QyxzQkFBc0IsRUFBRSxrQkFBa0I7cUJBQzFDO2lCQUNEOzswQkFNYSxTQUFTOzJCQUFDLE1BQU07O0FBYTlCOztHQUVHO0FBVUgsTUFBTSxPQUFPLGdCQUFpQixTQUFRLGNBQWM7OEdBQXZDLGdCQUFnQjtrR0FBaEIsZ0JBQWdCOzsyRkFBaEIsZ0JBQWdCO2tCQVQ1QixTQUFTO21CQUFDO29CQUNWLFFBQVEsRUFBRSxvQkFBb0I7b0JBQzlCLFVBQVUsRUFBRSxJQUFJO29CQUNoQixJQUFJLEVBQUU7d0JBQ0wsSUFBSSxFQUFFLFFBQVE7d0JBQ2QsWUFBWSxFQUFFLGtCQUFrQjt3QkFDaEMsU0FBUyxFQUFFLG9CQUFvQjtxQkFDL0I7aUJBQ0Q7O0FBR0Q7Ozs7R0FJRztBQVNILE1BQU0sT0FBTyxVQUFXLFNBQVEsY0FBYzs4R0FBakMsVUFBVTtrR0FBVixVQUFVOzsyRkFBVixVQUFVO2tCQVJ0QixTQUFTO21CQUFDO29CQUNWLFFBQVEsRUFBRSxlQUFlO29CQUN6QixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsSUFBSSxFQUFFO3dCQUNMLElBQUksRUFBRSxFQUFFO3dCQUNSLFNBQVMsRUFBRSw2Q0FBNkM7cUJBQ3hEO2lCQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcblx0QWZ0ZXJDb250ZW50Q2hlY2tlZCxcblx0QWZ0ZXJDb250ZW50SW5pdCxcblx0QXR0cmlidXRlLFxuXHRDaGFuZ2VEZXRlY3RvclJlZixcblx0Q29udGVudENoaWxkcmVuLFxuXHREZXN0cm95UmVmLFxuXHREaXJlY3RpdmUsXG5cdEVsZW1lbnRSZWYsXG5cdEV2ZW50RW1pdHRlcixcblx0Zm9yd2FyZFJlZixcblx0aW5qZWN0LFxuXHRJbnB1dCxcblx0T25DaGFuZ2VzLFxuXHRPbkluaXQsXG5cdE91dHB1dCxcblx0UXVlcnlMaXN0LFxuXHRTaW1wbGVDaGFuZ2VzLFxuXHRUZW1wbGF0ZVJlZixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5cbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcblxuaW1wb3J0IHsgaXNEZWZpbmVkIH0gZnJvbSAnLi4vdXRpbC91dGlsJztcbmltcG9ydCB7IE5nYk5hdkNvbmZpZyB9IGZyb20gJy4vbmF2LWNvbmZpZyc7XG5pbXBvcnQgeyBLZXkgfSBmcm9tICcuLi91dGlsL2tleSc7XG5cbmNvbnN0IGlzVmFsaWROYXZJZCA9IChpZDogYW55KSA9PiBpc0RlZmluZWQoaWQpICYmIGlkICE9PSAnJztcblxubGV0IG5hdkNvdW50ZXIgPSAwO1xuXG4vKipcbiAqIENvbnRleHQgcGFzc2VkIHRvIHRoZSBuYXYgY29udGVudCB0ZW1wbGF0ZS5cbiAqXG4gKiBTZWUgW3RoaXMgZGVtb10oIy9jb21wb25lbnRzL25hdi9leGFtcGxlcyNrZWVwLWNvbnRlbnQpIGFzIHRoZSBleGFtcGxlLlxuICpcbiAqIEBzaW5jZSA1LjIuMFxuICovXG5leHBvcnQgaW50ZXJmYWNlIE5nYk5hdkNvbnRlbnRDb250ZXh0IHtcblx0LyoqXG5cdCAqIElmIGB0cnVlYCwgY3VycmVudCBuYXYgY29udGVudCBpcyB2aXNpYmxlIGFuZCBhY3RpdmVcblx0ICovXG5cdCRpbXBsaWNpdDogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBUaGlzIGRpcmVjdGl2ZSBtdXN0IGJlIHVzZWQgdG8gd3JhcCBjb250ZW50IHRvIGJlIGRpc3BsYXllZCBpbiB0aGUgbmF2LlxuICpcbiAqIEBzaW5jZSA1LjIuMFxuICovXG5ARGlyZWN0aXZlKHsgc2VsZWN0b3I6ICduZy10ZW1wbGF0ZVtuZ2JOYXZDb250ZW50XScsIHN0YW5kYWxvbmU6IHRydWUgfSlcbmV4cG9ydCBjbGFzcyBOZ2JOYXZDb250ZW50IHtcblx0dGVtcGxhdGVSZWYgPSBpbmplY3QoVGVtcGxhdGVSZWYpO1xufVxuXG4vKipcbiAqIFRoaXMgZGlyZWN0aXZlIGFwcGxpZXMgYSBzcGVjaWZpYyByb2xlIG9uIGEgbm9uLWNvbnRhaW5lciBiYXNlZCBuZ2JOYXZJdGVtLlxuICpcbiAqIEBzaW5jZSAxNC4xLjBcbiAqL1xuQERpcmVjdGl2ZSh7XG5cdHNlbGVjdG9yOiAnW25nYk5hdkl0ZW1dOm5vdChuZy1jb250YWluZXIpJyxcblx0c3RhbmRhbG9uZTogdHJ1ZSxcblx0aG9zdDoge1xuXHRcdCdbYXR0ci5yb2xlXSc6IGByb2xlID8gcm9sZSA6IG5hdi5yb2xlcyA/ICdwcmVzZW50YXRpb24nIDogdW5kZWZpbmVkYCxcblx0fSxcbn0pXG5leHBvcnQgY2xhc3MgTmdiTmF2SXRlbVJvbGUge1xuXHRuYXYgPSBpbmplY3QoTmdiTmF2KTtcblxuXHRjb25zdHJ1Y3RvcihAQXR0cmlidXRlKCdyb2xlJykgcHVibGljIHJvbGU6IHN0cmluZykge31cbn1cblxuLyoqXG4gKiBUaGUgZGlyZWN0aXZlIHVzZWQgdG8gZ3JvdXAgbmF2IGxpbmsgYW5kIHJlbGF0ZWQgbmF2IGNvbnRlbnQuIEFzIHdlbGwgYXMgc2V0IG5hdiBpZGVudGlmaWVyIGFuZCBzb21lIG9wdGlvbnMuXG4gKlxuICogQHNpbmNlIDUuMi4wXG4gKi9cbkBEaXJlY3RpdmUoeyBzZWxlY3RvcjogJ1tuZ2JOYXZJdGVtXScsIGV4cG9ydEFzOiAnbmdiTmF2SXRlbScsIHN0YW5kYWxvbmU6IHRydWUsIGhvc3Q6IHsgJ1tjbGFzcy5uYXYtaXRlbV0nOiAndHJ1ZScgfSB9KVxuZXhwb3J0IGNsYXNzIE5nYk5hdkl0ZW0gaW1wbGVtZW50cyBBZnRlckNvbnRlbnRDaGVja2VkLCBPbkluaXQge1xuXHRwcml2YXRlIF9uYXYgPSBpbmplY3QoTmdiTmF2KTtcblx0cHJpdmF0ZSBfbmF0aXZlRWxlbWVudCA9IGluamVjdChFbGVtZW50UmVmKS5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50O1xuXG5cdC8qKlxuXHQgKiBJZiBgdHJ1ZWAsIG5vbi1hY3RpdmUgY3VycmVudCBuYXYgaXRlbSBjb250ZW50IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIERPTVxuXHQgKiBPdGhlcndpc2UgaXQgd2lsbCBqdXN0IGJlIGhpZGRlblxuXHQgKi9cblx0QElucHV0KCkgZGVzdHJveU9uSGlkZTtcblxuXHQvKipcblx0ICogSWYgYHRydWVgLCB0aGUgY3VycmVudCBuYXYgaXRlbSBpcyBkaXNhYmxlZCBhbmQgY2FuJ3QgYmUgdG9nZ2xlZCBieSB1c2VyLlxuXHQgKlxuXHQgKiBOZXZlcnRoZWxlc3MgZGlzYWJsZWQgbmF2IGNhbiBiZSBzZWxlY3RlZCBwcm9ncmFtbWF0aWNhbGx5IHZpYSB0aGUgYC5zZWxlY3QoKWAgbWV0aG9kIGFuZCB0aGUgYFthY3RpdmVJZF1gIGJpbmRpbmcuXG5cdCAqL1xuXHRASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuXG5cdC8qKlxuXHQgKiBUaGUgaWQgdXNlZCBmb3IgdGhlIERPTSBlbGVtZW50cy5cblx0ICogTXVzdCBiZSB1bmlxdWUgaW5zaWRlIHRoZSBkb2N1bWVudCBpbiBjYXNlIHlvdSBoYXZlIG11bHRpcGxlIGBuZ2JOYXZgcyBvbiB0aGUgcGFnZS5cblx0ICpcblx0ICogQXV0b2dlbmVyYXRlZCBhcyBgbmdiLW5hdi1YWFhgIGlmIG5vdCBwcm92aWRlZC5cblx0ICovXG5cdEBJbnB1dCgpIGRvbUlkOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFRoZSBpZCB1c2VkIGFzIGEgbW9kZWwgZm9yIGFjdGl2ZSBuYXYuXG5cdCAqIEl0IGNhbiBiZSBhbnl0aGluZywgYnV0IG11c3QgYmUgdW5pcXVlIGluc2lkZSBvbmUgYG5nYk5hdmAuXG5cdCAqXG5cdCAqIFRoZSBvbmx5IGxpbWl0YXRpb24gaXMgdGhhdCBpdCBpcyBub3QgcG9zc2libGUgdG8gaGF2ZSB0aGUgYCcnYCAoZW1wdHkgc3RyaW5nKSBhcyBpZCxcblx0ICogYmVjYXVzZSBgIG5nYk5hdkl0ZW0gYCwgYG5nYk5hdkl0ZW09JydgIGFuZCBgW25nYk5hdkl0ZW1dPVwiJydcImAgYXJlIGluZGlzdGluZ3Vpc2hhYmxlXG5cdCAqL1xuXHRASW5wdXQoJ25nYk5hdkl0ZW0nKSBfaWQ6IGFueTtcblxuXHQvKipcblx0ICogQW4gZXZlbnQgZW1pdHRlZCB3aGVuIHRoZSBmYWRlIGluIHRyYW5zaXRpb24gaXMgZmluaXNoZWQgb24gdGhlIHJlbGF0ZWQgbmF2IGNvbnRlbnRcblx0ICpcblx0ICogQHNpbmNlIDguMC4wXG5cdCAqL1xuXHRAT3V0cHV0KCkgc2hvd24gPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cblx0LyoqXG5cdCAqIEFuIGV2ZW50IGVtaXR0ZWQgd2hlbiB0aGUgZmFkZSBvdXQgdHJhbnNpdGlvbiBpcyBmaW5pc2hlZCBvbiB0aGUgcmVsYXRlZCBuYXYgY29udGVudFxuXHQgKlxuXHQgKiBAc2luY2UgOC4wLjBcblx0ICovXG5cdEBPdXRwdXQoKSBoaWRkZW4gPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cblx0Y29udGVudFRwbDogTmdiTmF2Q29udGVudCB8IG51bGw7XG5cblx0QENvbnRlbnRDaGlsZHJlbihOZ2JOYXZDb250ZW50LCB7IGRlc2NlbmRhbnRzOiBmYWxzZSB9KSBjb250ZW50VHBsczogUXVlcnlMaXN0PE5nYk5hdkNvbnRlbnQ+O1xuXG5cdG5nQWZ0ZXJDb250ZW50Q2hlY2tlZCgpIHtcblx0XHQvLyBXZSBhcmUgdXNpbmcgQENvbnRlbnRDaGlsZHJlbiBpbnN0ZWFkIG9mIEBDb250ZW50Q2hpbGQgYXMgaW4gdGhlIEFuZ3VsYXIgdmVyc2lvbiBiZWluZyB1c2VkXG5cdFx0Ly8gb25seSBAQ29udGVudENoaWxkcmVuIGFsbG93cyB1cyB0byBzcGVjaWZ5IHRoZSB7ZGVzY2VuZGFudHM6IGZhbHNlfSBvcHRpb24uXG5cdFx0Ly8gV2l0aG91dCB7ZGVzY2VuZGFudHM6IGZhbHNlfSB3ZSBhcmUgaGl0dGluZyBidWdzIGRlc2NyaWJlZCBpbjpcblx0XHQvLyBodHRwczovL2dpdGh1Yi5jb20vbmctYm9vdHN0cmFwL25nLWJvb3RzdHJhcC9pc3N1ZXMvMjI0MFxuXHRcdHRoaXMuY29udGVudFRwbCA9IHRoaXMuY29udGVudFRwbHMuZmlyc3Q7XG5cdH1cblxuXHRuZ09uSW5pdCgpIHtcblx0XHRpZiAoIWlzRGVmaW5lZCh0aGlzLmRvbUlkKSkge1xuXHRcdFx0dGhpcy5kb21JZCA9IGBuZ2ItbmF2LSR7bmF2Q291bnRlcisrfWA7XG5cdFx0fVxuXHR9XG5cblx0Z2V0IGFjdGl2ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fbmF2LmFjdGl2ZUlkID09PSB0aGlzLmlkO1xuXHR9XG5cblx0Z2V0IGlkKCkge1xuXHRcdHJldHVybiBpc1ZhbGlkTmF2SWQodGhpcy5faWQpID8gdGhpcy5faWQgOiB0aGlzLmRvbUlkO1xuXHR9XG5cblx0Z2V0IHBhbmVsRG9tSWQoKSB7XG5cdFx0cmV0dXJuIGAke3RoaXMuZG9tSWR9LXBhbmVsYDtcblx0fVxuXG5cdGlzUGFuZWxJbkRvbSgpIHtcblx0XHRyZXR1cm4gKGlzRGVmaW5lZCh0aGlzLmRlc3Ryb3lPbkhpZGUpID8gIXRoaXMuZGVzdHJveU9uSGlkZSA6ICF0aGlzLl9uYXYuZGVzdHJveU9uSGlkZSkgfHwgdGhpcy5hY3RpdmU7XG5cdH1cblxuXHQvKipcblx0ICogQGludGVybmFsXG5cdCAqL1xuXHRpc05nQ29udGFpbmVyKCkge1xuXHRcdHJldHVybiB0aGlzLl9uYXRpdmVFbGVtZW50Lm5vZGVUeXBlID09PSBOb2RlLkNPTU1FTlRfTk9ERTtcblx0fVxufVxuXG4vKipcbiAqIEEgbmF2IGRpcmVjdGl2ZSB0aGF0IGhlbHBzIHdpdGggaW1wbGVtZW50aW5nIHRhYmJlZCBuYXZpZ2F0aW9uIGNvbXBvbmVudHMuXG4gKlxuICogQHNpbmNlIDUuMi4wXG4gKi9cbkBEaXJlY3RpdmUoe1xuXHRzZWxlY3RvcjogJ1tuZ2JOYXZdJyxcblx0ZXhwb3J0QXM6ICduZ2JOYXYnLFxuXHRzdGFuZGFsb25lOiB0cnVlLFxuXHRob3N0OiB7XG5cdFx0J1tjbGFzcy5uYXZdJzogJ3RydWUnLFxuXHRcdCdbY2xhc3MuZmxleC1jb2x1bW5dJzogYG9yaWVudGF0aW9uID09PSAndmVydGljYWwnYCxcblx0XHQnW2F0dHIuYXJpYS1vcmllbnRhdGlvbl0nOiBgb3JpZW50YXRpb24gPT09ICd2ZXJ0aWNhbCcgJiYgcm9sZXMgPT09ICd0YWJsaXN0JyA/ICd2ZXJ0aWNhbCcgOiB1bmRlZmluZWRgLFxuXHRcdCdbYXR0ci5yb2xlXSc6IGByb2xlID8gcm9sZSA6IHJvbGVzID8gJ3RhYmxpc3QnIDogdW5kZWZpbmVkYCxcblx0XHQnKGtleWRvd24uYXJyb3dMZWZ0KSc6ICdvbktleURvd24oJGV2ZW50KScsXG5cdFx0JyhrZXlkb3duLmFycm93UmlnaHQpJzogJ29uS2V5RG93bigkZXZlbnQpJyxcblx0XHQnKGtleWRvd24uYXJyb3dEb3duKSc6ICdvbktleURvd24oJGV2ZW50KScsXG5cdFx0JyhrZXlkb3duLmFycm93VXApJzogJ29uS2V5RG93bigkZXZlbnQpJyxcblx0XHQnKGtleWRvd24uSG9tZSknOiAnb25LZXlEb3duKCRldmVudCknLFxuXHRcdCcoa2V5ZG93bi5FbmQpJzogJ29uS2V5RG93bigkZXZlbnQpJyxcblx0XHQnKGZvY3Vzb3V0KSc6ICdvbkZvY3Vzb3V0KCRldmVudCknLFxuXHR9LFxufSlcbmV4cG9ydCBjbGFzcyBOZ2JOYXYgaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0LCBPbkNoYW5nZXMge1xuXHRzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfb3JpZW50YXRpb246IHN0cmluZztcblx0c3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX3JvbGVzOiBib29sZWFuIHwgc3RyaW5nO1xuXG5cdHByaXZhdGUgX2NvbmZpZyA9IGluamVjdChOZ2JOYXZDb25maWcpO1xuXHRwcml2YXRlIF9jZCA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG5cdHByaXZhdGUgX2RvY3VtZW50ID0gaW5qZWN0KERPQ1VNRU5UKTtcblx0cHJpdmF0ZSBfbmF0aXZlRWxlbWVudCA9IGluamVjdChFbGVtZW50UmVmKS5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50O1xuXG5cdGRlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cblx0X25hdmlnYXRpbmdXaXRoS2V5Ym9hcmQgPSBmYWxzZTtcblxuXHQvKipcblx0ICogVGhlIGlkIG9mIHRoZSBuYXYgdGhhdCBzaG91bGQgYmUgYWN0aXZlXG5cdCAqXG5cdCAqIFlvdSBjb3VsZCBhbHNvIHVzZSB0aGUgYC5zZWxlY3QoKWAgbWV0aG9kIGFuZCB0aGUgYChuYXZDaGFuZ2UpYCBldmVudFxuXHQgKi9cblx0QElucHV0KCkgYWN0aXZlSWQ6IGFueTtcblxuXHQvKipcblx0ICogVGhlIGV2ZW50IGVtaXR0ZWQgYWZ0ZXIgdGhlIGFjdGl2ZSBuYXYgY2hhbmdlc1xuXHQgKiBUaGUgcGF5bG9hZCBvZiB0aGUgZXZlbnQgaXMgdGhlIG5ld2x5IGFjdGl2ZSBuYXYgaWRcblx0ICpcblx0ICogSWYgeW91IHdhbnQgdG8gcHJldmVudCBuYXYgY2hhbmdlLCB5b3Ugc2hvdWxkIHVzZSBgKG5hdkNoYW5nZSlgIGV2ZW50XG5cdCAqL1xuXHRAT3V0cHV0KCkgYWN0aXZlSWRDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuXHQvKipcblx0ICogSWYgYHRydWVgLCBuYXYgY2hhbmdlIHdpbGwgYmUgYW5pbWF0ZWQuXG5cdCAqXG5cdCAqIEBzaW5jZSA4LjAuMFxuXHQgKi9cblx0QElucHV0KCkgYW5pbWF0aW9uID0gdGhpcy5fY29uZmlnLmFuaW1hdGlvbjtcblxuXHQvKipcblx0ICogSWYgYHRydWVgLCBub24tYWN0aXZlIG5hdiBjb250ZW50IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIERPTVxuXHQgKiBPdGhlcndpc2UgaXQgd2lsbCBqdXN0IGJlIGhpZGRlblxuXHQgKi9cblx0QElucHV0KCkgZGVzdHJveU9uSGlkZSA9IHRoaXMuX2NvbmZpZy5kZXN0cm95T25IaWRlO1xuXG5cdC8qKlxuXHQgKiBUaGUgb3JpZW50YXRpb24gb2YgbmF2cy5cblx0ICpcblx0ICogVXNpbmcgYHZlcnRpY2FsYCB3aWxsIGFsc28gYWRkIHRoZSBgYXJpYS1vcmllbnRhdGlvbmAgYXR0cmlidXRlXG5cdCAqL1xuXHRASW5wdXQoKSBvcmllbnRhdGlvbiA9IHRoaXMuX2NvbmZpZy5vcmllbnRhdGlvbjtcblxuXHQvKipcblx0ICogUm9sZSBhdHRyaWJ1dGUgZ2VuZXJhdGluZyBzdHJhdGVneTpcblx0ICogLSBgZmFsc2VgIC0gbm8gcm9sZSBhdHRyaWJ1dGVzIHdpbGwgYmUgZ2VuZXJhdGVkXG5cdCAqIC0gYCd0YWJsaXN0J2AgLSAndGFibGlzdCcsICd0YWInIGFuZCAndGFicGFuZWwnIHdpbGwgYmUgZ2VuZXJhdGVkIChkZWZhdWx0KVxuXHQgKi9cblx0QElucHV0KCkgcm9sZXMgPSB0aGlzLl9jb25maWcucm9sZXM7XG5cblx0LyoqXG5cdCAqIEtleWJvYXJkIHN1cHBvcnQgZm9yIG5hdiBmb2N1cy9zZWxlY3Rpb24gdXNpbmcgYXJyb3cga2V5cy5cblx0ICpcblx0ICogKiBgdHJ1ZWAgLSBuYXZzIHdpbGwgYmUgZm9jdXNlZCB1c2luZyBrZXlib2FyZCBhcnJvdyBrZXlzXG5cdCAqICogYGZhbHNlYCAtIG5vIGtleWJvYXJkIHN1cHBvcnRcblx0ICogKiBgJ2NoYW5nZVdpdGhBcnJvd3MnYCAtICBuYXYgd2lsbCBiZSBzZWxlY3RlZCB1c2luZyBrZXlib2FyZCBhcnJvdyBrZXlzXG5cdCAqXG5cdCAqIFNlZSB0aGUgW2xpc3Qgb2YgYXZhaWxhYmxlIGtleWJvYXJkIHNob3J0Y3V0c10oIy9jb21wb25lbnRzL25hdi9vdmVydmlldyNrZXlib2FyZC1zaG9ydGN1dHMpLlxuXHQgKlxuXHQgKiBAc2luY2UgNi4xLjBcblx0ICovXG5cdEBJbnB1dCgpIGtleWJvYXJkID0gdGhpcy5fY29uZmlnLmtleWJvYXJkO1xuXG5cdC8qKlxuXHQgKiBBbiBldmVudCBlbWl0dGVkIHdoZW4gdGhlIGZhZGUgaW4gdHJhbnNpdGlvbiBpcyBmaW5pc2hlZCBmb3Igb25lIG9mIHRoZSBpdGVtcy5cblx0ICpcblx0ICogUGF5bG9hZCBvZiB0aGUgZXZlbnQgaXMgdGhlIG5hdiBpZCB0aGF0IHdhcyBqdXN0IHNob3duLlxuXHQgKlxuXHQgKiBAc2luY2UgOC4wLjBcblx0ICovXG5cdEBPdXRwdXQoKSBzaG93biA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG5cdC8qKlxuXHQgKiBBbiBldmVudCBlbWl0dGVkIHdoZW4gdGhlIGZhZGUgb3V0IHRyYW5zaXRpb24gaXMgZmluaXNoZWQgZm9yIG9uZSBvZiB0aGUgaXRlbXMuXG5cdCAqXG5cdCAqIFBheWxvYWQgb2YgdGhlIGV2ZW50IGlzIHRoZSBuYXYgaWQgdGhhdCB3YXMganVzdCBoaWRkZW4uXG5cdCAqXG5cdCAqIEBzaW5jZSA4LjAuMFxuXHQgKi9cblx0QE91dHB1dCgpIGhpZGRlbiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG5cdEBDb250ZW50Q2hpbGRyZW4oTmdiTmF2SXRlbSkgaXRlbXM6IFF1ZXJ5TGlzdDxOZ2JOYXZJdGVtPjtcblx0QENvbnRlbnRDaGlsZHJlbihmb3J3YXJkUmVmKCgpID0+IE5nYk5hdkxpbmtCYXNlKSwgeyBkZXNjZW5kYW50czogdHJ1ZSB9KSBsaW5rczogUXVlcnlMaXN0PE5nYk5hdkxpbmtCYXNlPjtcblxuXHRuYXZJdGVtQ2hhbmdlJCA9IG5ldyBTdWJqZWN0PE5nYk5hdkl0ZW0gfCBudWxsPigpO1xuXG5cdGNvbnN0cnVjdG9yKEBBdHRyaWJ1dGUoJ3JvbGUnKSBwdWJsaWMgcm9sZTogc3RyaW5nKSB7fVxuXG5cdC8qKlxuXHQgKiBUaGUgbmF2IGNoYW5nZSBldmVudCBlbWl0dGVkIHJpZ2h0IGJlZm9yZSB0aGUgbmF2IGNoYW5nZSBoYXBwZW5zIG9uIHVzZXIgY2xpY2suXG5cdCAqXG5cdCAqIFRoaXMgZXZlbnQgd29uJ3QgYmUgZW1pdHRlZCBpZiBuYXYgaXMgY2hhbmdlZCBwcm9ncmFtbWF0aWNhbGx5IHZpYSBgW2FjdGl2ZUlkXWAgb3IgYC5zZWxlY3QoKWAuXG5cdCAqXG5cdCAqIFNlZSBbYE5nYk5hdkNoYW5nZUV2ZW50YF0oIy9jb21wb25lbnRzL25hdi9hcGkjTmdiTmF2Q2hhbmdlRXZlbnQpIGZvciBwYXlsb2FkIGRldGFpbHMuXG5cdCAqL1xuXHRAT3V0cHV0KCkgbmF2Q2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxOZ2JOYXZDaGFuZ2VFdmVudD4oKTtcblxuXHRjbGljayhpdGVtOiBOZ2JOYXZJdGVtKSB7XG5cdFx0aWYgKCFpdGVtLmRpc2FibGVkKSB7XG5cdFx0XHR0aGlzLl91cGRhdGVBY3RpdmVJZChpdGVtLmlkKTtcblx0XHR9XG5cdH1cblxuXHRvbkZvY3Vzb3V0KHsgcmVsYXRlZFRhcmdldCB9OiBGb2N1c0V2ZW50KSB7XG5cdFx0aWYgKCF0aGlzLl9uYXRpdmVFbGVtZW50LmNvbnRhaW5zKHJlbGF0ZWRUYXJnZXQgYXMgSFRNTEVsZW1lbnQpKSB7XG5cdFx0XHR0aGlzLl9uYXZpZ2F0aW5nV2l0aEtleWJvYXJkID0gZmFsc2U7XG5cdFx0fVxuXHR9XG5cblx0b25LZXlEb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG5cdFx0aWYgKHRoaXMucm9sZXMgIT09ICd0YWJsaXN0JyB8fCAhdGhpcy5rZXlib2FyZCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHQvKiBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVwcmVjYXRpb24vZGVwcmVjYXRpb24gKi9cblx0XHRjb25zdCBrZXkgPSBldmVudC53aGljaDtcblx0XHRjb25zdCBlbmFibGVkTGlua3MgPSB0aGlzLmxpbmtzLmZpbHRlcigobGluaykgPT4gIWxpbmsubmF2SXRlbS5kaXNhYmxlZCk7XG5cdFx0Y29uc3QgeyBsZW5ndGggfSA9IGVuYWJsZWRMaW5rcztcblxuXHRcdGxldCBwb3NpdGlvbiA9IC0xO1xuXG5cdFx0ZW5hYmxlZExpbmtzLmZvckVhY2goKGxpbmssIGluZGV4KSA9PiB7XG5cdFx0XHRpZiAobGluay5uYXRpdmVFbGVtZW50ID09PSB0aGlzLl9kb2N1bWVudC5hY3RpdmVFbGVtZW50KSB7XG5cdFx0XHRcdHBvc2l0aW9uID0gaW5kZXg7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHRpZiAobGVuZ3RoKSB7XG5cdFx0XHRzd2l0Y2ggKGtleSkge1xuXHRcdFx0XHRjYXNlIEtleS5BcnJvd1VwOlxuXHRcdFx0XHRjYXNlIEtleS5BcnJvd0xlZnQ6XG5cdFx0XHRcdFx0cG9zaXRpb24gPSAocG9zaXRpb24gLSAxICsgbGVuZ3RoKSAlIGxlbmd0aDtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBLZXkuQXJyb3dSaWdodDpcblx0XHRcdFx0Y2FzZSBLZXkuQXJyb3dEb3duOlxuXHRcdFx0XHRcdHBvc2l0aW9uID0gKHBvc2l0aW9uICsgMSkgJSBsZW5ndGg7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgS2V5LkhvbWU6XG5cdFx0XHRcdFx0cG9zaXRpb24gPSAwO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIEtleS5FbmQ6XG5cdFx0XHRcdFx0cG9zaXRpb24gPSBsZW5ndGggLSAxO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHRoaXMua2V5Ym9hcmQgPT09ICdjaGFuZ2VXaXRoQXJyb3dzJykge1xuXHRcdFx0XHR0aGlzLnNlbGVjdChlbmFibGVkTGlua3NbcG9zaXRpb25dLm5hdkl0ZW0uaWQpO1xuXHRcdFx0fVxuXHRcdFx0ZW5hYmxlZExpbmtzW3Bvc2l0aW9uXS5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG5cdFx0XHR0aGlzLl9uYXZpZ2F0aW5nV2l0aEtleWJvYXJkID0gdHJ1ZTtcblxuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU2VsZWN0cyB0aGUgbmF2IHdpdGggdGhlIGdpdmVuIGlkIGFuZCBzaG93cyBpdHMgYXNzb2NpYXRlZCBwYW5lLlxuXHQgKiBBbnkgb3RoZXIgbmF2IHRoYXQgd2FzIHByZXZpb3VzbHkgc2VsZWN0ZWQgYmVjb21lcyB1bnNlbGVjdGVkIGFuZCBpdHMgYXNzb2NpYXRlZCBwYW5lIGlzIGhpZGRlbi5cblx0ICovXG5cdHNlbGVjdChpZDogYW55KSB7XG5cdFx0dGhpcy5fdXBkYXRlQWN0aXZlSWQoaWQsIGZhbHNlKTtcblx0fVxuXG5cdG5nQWZ0ZXJDb250ZW50SW5pdCgpIHtcblx0XHRpZiAoIWlzRGVmaW5lZCh0aGlzLmFjdGl2ZUlkKSkge1xuXHRcdFx0Y29uc3QgbmV4dElkID0gdGhpcy5pdGVtcy5maXJzdCA/IHRoaXMuaXRlbXMuZmlyc3QuaWQgOiBudWxsO1xuXHRcdFx0aWYgKGlzVmFsaWROYXZJZChuZXh0SWQpKSB7XG5cdFx0XHRcdHRoaXMuX3VwZGF0ZUFjdGl2ZUlkKG5leHRJZCwgZmFsc2UpO1xuXHRcdFx0XHR0aGlzLl9jZC5kZXRlY3RDaGFuZ2VzKCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5pdGVtcy5jaGFuZ2VzXG5cdFx0XHQucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSlcblx0XHRcdC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5fbm90aWZ5SXRlbUNoYW5nZWQodGhpcy5hY3RpdmVJZCkpO1xuXHR9XG5cblx0bmdPbkNoYW5nZXMoeyBhY3RpdmVJZCB9OiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG5cdFx0aWYgKGFjdGl2ZUlkICYmICFhY3RpdmVJZC5maXJzdENoYW5nZSkge1xuXHRcdFx0dGhpcy5fbm90aWZ5SXRlbUNoYW5nZWQoYWN0aXZlSWQuY3VycmVudFZhbHVlKTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIF91cGRhdGVBY3RpdmVJZChuZXh0SWQ6IGFueSwgZW1pdE5hdkNoYW5nZSA9IHRydWUpIHtcblx0XHRpZiAodGhpcy5hY3RpdmVJZCAhPT0gbmV4dElkKSB7XG5cdFx0XHRsZXQgZGVmYXVsdFByZXZlbnRlZCA9IGZhbHNlO1xuXG5cdFx0XHRpZiAoZW1pdE5hdkNoYW5nZSkge1xuXHRcdFx0XHR0aGlzLm5hdkNoYW5nZS5lbWl0KHtcblx0XHRcdFx0XHRhY3RpdmVJZDogdGhpcy5hY3RpdmVJZCxcblx0XHRcdFx0XHRuZXh0SWQsXG5cdFx0XHRcdFx0cHJldmVudERlZmF1bHQ6ICgpID0+IHtcblx0XHRcdFx0XHRcdGRlZmF1bHRQcmV2ZW50ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIWRlZmF1bHRQcmV2ZW50ZWQpIHtcblx0XHRcdFx0dGhpcy5hY3RpdmVJZCA9IG5leHRJZDtcblx0XHRcdFx0dGhpcy5hY3RpdmVJZENoYW5nZS5lbWl0KG5leHRJZCk7XG5cdFx0XHRcdHRoaXMuX25vdGlmeUl0ZW1DaGFuZ2VkKG5leHRJZCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBfbm90aWZ5SXRlbUNoYW5nZWQobmV4dEl0ZW1JZDogYW55KSB7XG5cdFx0dGhpcy5uYXZJdGVtQ2hhbmdlJC5uZXh0KHRoaXMuX2dldEl0ZW1CeUlkKG5leHRJdGVtSWQpKTtcblx0fVxuXG5cdHByaXZhdGUgX2dldEl0ZW1CeUlkKGl0ZW1JZDogYW55KTogTmdiTmF2SXRlbSB8IG51bGwge1xuXHRcdHJldHVybiAodGhpcy5pdGVtcyAmJiB0aGlzLml0ZW1zLmZpbmQoKGl0ZW0pID0+IGl0ZW0uaWQgPT09IGl0ZW1JZCkpIHx8IG51bGw7XG5cdH1cbn1cblxuQERpcmVjdGl2ZSh7XG5cdHNlbGVjdG9yOiAnW25nYk5hdkxpbmtdJyxcblx0c3RhbmRhbG9uZTogdHJ1ZSxcblx0aG9zdDoge1xuXHRcdCdbaWRdJzogJ25hdkl0ZW0uZG9tSWQnLFxuXHRcdCdbY2xhc3MubmF2LWxpbmtdJzogJ3RydWUnLFxuXHRcdCdbY2xhc3MubmF2LWl0ZW1dJzogJ25hdkl0ZW0uaXNOZ0NvbnRhaW5lcigpJyxcblx0XHQnW2F0dHIucm9sZV0nOiBgcm9sZSA/IHJvbGUgOiBuYXYucm9sZXMgPyAndGFiJyA6IHVuZGVmaW5lZGAsXG5cdFx0J1tjbGFzcy5hY3RpdmVdJzogJ25hdkl0ZW0uYWN0aXZlJyxcblx0XHQnW2NsYXNzLmRpc2FibGVkXSc6ICduYXZJdGVtLmRpc2FibGVkJyxcblx0XHQnW2F0dHIudGFiaW5kZXhdJzogJ3RhYmluZGV4Jyxcblx0XHQnW2F0dHIuYXJpYS1jb250cm9sc10nOiAnbmF2SXRlbS5pc1BhbmVsSW5Eb20oKSA/IG5hdkl0ZW0ucGFuZWxEb21JZCA6IG51bGwnLFxuXHRcdCdbYXR0ci5hcmlhLXNlbGVjdGVkXSc6ICduYXZJdGVtLmFjdGl2ZScsXG5cdFx0J1thdHRyLmFyaWEtZGlzYWJsZWRdJzogJ25hdkl0ZW0uZGlzYWJsZWQnLFxuXHR9LFxufSlcbmV4cG9ydCBjbGFzcyBOZ2JOYXZMaW5rQmFzZSB7XG5cdG5hdkl0ZW0gPSBpbmplY3QoTmdiTmF2SXRlbSk7XG5cdG5hdiA9IGluamVjdChOZ2JOYXYpO1xuXHRuYXRpdmVFbGVtZW50ID0gaW5qZWN0KEVsZW1lbnRSZWYpLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQ7XG5cblx0Y29uc3RydWN0b3IoQEF0dHJpYnV0ZSgncm9sZScpIHB1YmxpYyByb2xlOiBzdHJpbmcpIHt9XG5cblx0Z2V0IHRhYmluZGV4KCkge1xuXHRcdGlmICh0aGlzLm5hdi5rZXlib2FyZCA9PT0gZmFsc2UpIHtcblx0XHRcdHJldHVybiB0aGlzLm5hdkl0ZW0uZGlzYWJsZWQgPyAtMSA6IHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0aWYgKHRoaXMubmF2Ll9uYXZpZ2F0aW5nV2l0aEtleWJvYXJkKSB7XG5cdFx0XHRyZXR1cm4gLTE7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLm5hdkl0ZW0uZGlzYWJsZWQgfHwgIXRoaXMubmF2SXRlbS5hY3RpdmUgPyAtMSA6IHVuZGVmaW5lZDtcblx0fVxufVxuXG4vKipcbiAqIEEgZGlyZWN0aXZlIHRvIG1hcmsgdGhlIG5hdiBsaW5rIHdoZW4gdXNlZCBvbiBhIGJ1dHRvbiBlbGVtZW50LlxuICovXG5ARGlyZWN0aXZlKHtcblx0c2VsZWN0b3I6ICdidXR0b25bbmdiTmF2TGlua10nLFxuXHRzdGFuZGFsb25lOiB0cnVlLFxuXH