@ng-bootstrap/ng-bootstrap
Version:
Angular powered Bootstrap
510 lines • 54.1 kB
JavaScript
import { ApplicationRef, ContentChild, ContentChildren, Directive, ElementRef, EventEmitter, forwardRef, inject, Inject, Input, Output, TemplateRef, } from '@angular/core';
import { NgbCollapse } from '../collapse/collapse';
import { isString } from '../util/util';
import * as i0 from "@angular/core";
import * as i1 from "../collapse/collapse";
import * as i2 from "./accordion-config";
let nextId = 0;
/**
* A directive that wraps the content of an accordion item's collapsible body.
*
* The actual content is provided in a child `ng-template` element.
* Depending on the state of the accordion, the template will be either inserted or removed from the DOM.
*
* @since 14.1.0
*/
class NgbAccordionBody {
constructor() {
this._appRef = inject(ApplicationRef);
this._element = inject((ElementRef)).nativeElement;
this._item = inject(NgbAccordionItem);
this._viewRef = null;
}
ngAfterContentChecked() {
if (this._bodyTpl) {
if (this._item.animatingBodyCollapse || !this._item.destroyOnHide) {
this._createViewIfNotExists();
}
else {
this._destroyViewIfExists();
}
}
}
ngOnDestroy() {
this._destroyViewIfExists();
}
_destroyViewIfExists() {
if (this._viewRef) {
this._appRef.detachView(this._viewRef);
this._viewRef.destroy();
this._viewRef = null;
}
}
_createViewIfNotExists() {
if (!this._viewRef) {
this._viewRef = this._bodyTpl.createEmbeddedView(null);
this._viewRef.detectChanges();
this._appRef.attachView(this._viewRef);
for (const node of this._viewRef.rootNodes) {
this._element.appendChild(node);
}
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionBody, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: NgbAccordionBody, isStandalone: true, selector: "[ngbAccordionBody]", host: { properties: { "class.accordion-body": "true" } }, queries: [{ propertyName: "_bodyTpl", first: true, predicate: TemplateRef, descendants: true, static: true }], ngImport: i0 }); }
}
export { NgbAccordionBody };
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionBody, decorators: [{
type: Directive,
args: [{
selector: '[ngbAccordionBody]',
standalone: true,
host: { '[class.accordion-body]': 'true' },
}]
}], propDecorators: { _bodyTpl: [{
type: ContentChild,
args: [TemplateRef, { static: true }]
}] } });
/**
* A directive that wraps the collapsible item's content of the accordion.
*
* Internally it reuses the [`NgbCollapse` directive](#/components/collapse)
*
* @since 14.1.0
*/
class NgbAccordionCollapse {
constructor(item, ngbCollapse) {
this.item = item;
this.ngbCollapse = ngbCollapse;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionCollapse, deps: [{ token: forwardRef(() => NgbAccordionItem) }, { token: i1.NgbCollapse }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: NgbAccordionCollapse, isStandalone: true, selector: "[ngbAccordionCollapse]", host: { attributes: { "role": "region" }, properties: { "class.accordion-collapse": "true", "id": "item.collapseId", "attr.aria-labelledby": "item.toggleId" } }, exportAs: ["ngbAccordionCollapse"], hostDirectives: [{ directive: i1.NgbCollapse }], ngImport: i0 }); }
}
export { NgbAccordionCollapse };
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionCollapse, decorators: [{
type: Directive,
args: [{
exportAs: 'ngbAccordionCollapse',
standalone: true,
selector: '[ngbAccordionCollapse]',
host: {
role: 'region',
'[class.accordion-collapse]': 'true',
'[id]': 'item.collapseId',
'[attr.aria-labelledby]': 'item.toggleId',
},
hostDirectives: [
{
directive: NgbCollapse,
},
],
}]
}], ctorParameters: function () { return [{ type: NgbAccordionItem, decorators: [{
type: Inject,
args: [forwardRef(() => NgbAccordionItem)]
}] }, { type: i1.NgbCollapse }]; } });
/**
* A directive to put on a toggling element inside the accordion item's header.
* It will register click handlers that toggle the associated panel and will handle accessibility attributes.
*
* This directive is used internally by the [`NgbAccordionButton` directive](#/components/accordion/api#NgbAccordionButton).
*
* @since 14.1.0
*/
class NgbAccordionToggle {
constructor(item, accordion) {
this.item = item;
this.accordion = accordion;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionToggle, deps: [{ token: forwardRef(() => NgbAccordionItem) }, { token: forwardRef(() => NgbAccordionDirective) }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: NgbAccordionToggle, isStandalone: true, selector: "[ngbAccordionToggle]", host: { listeners: { "click": "!item.disabled && accordion.toggle(item.id)" }, properties: { "id": "item.toggleId", "class.collapsed": "item.collapsed", "attr.aria-controls": "item.collapseId", "attr.aria-expanded": "!item.collapsed" } }, ngImport: i0 }); }
}
export { NgbAccordionToggle };
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionToggle, decorators: [{
type: Directive,
args: [{
selector: '[ngbAccordionToggle]',
standalone: true,
host: {
'[id]': 'item.toggleId',
'[class.collapsed]': 'item.collapsed',
'[attr.aria-controls]': 'item.collapseId',
'[attr.aria-expanded]': '!item.collapsed',
'(click)': '!item.disabled && accordion.toggle(item.id)',
},
}]
}], ctorParameters: function () { return [{ type: NgbAccordionItem, decorators: [{
type: Inject,
args: [forwardRef(() => NgbAccordionItem)]
}] }, { type: NgbAccordionDirective, decorators: [{
type: Inject,
args: [forwardRef(() => NgbAccordionDirective)]
}] }]; } });
/**
* A directive to put on a button element inside an accordion item's header.
*
* If you want a custom markup for the header, you can also use the [`NgbAccordionToggle` directive](#/components/accordion/api#NgbAccordionToggle).
*
* @since 14.1.0
*/
class NgbAccordionButton {
constructor(item) {
this.item = item;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionButton, deps: [{ token: forwardRef(() => NgbAccordionItem) }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: NgbAccordionButton, isStandalone: true, selector: "button[ngbAccordionButton]", host: { attributes: { "type": "button" }, properties: { "disabled": "item.disabled", "class.accordion-button": "true" } }, hostDirectives: [{ directive: NgbAccordionToggle }], ngImport: i0 }); }
}
export { NgbAccordionButton };
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionButton, decorators: [{
type: Directive,
args: [{
selector: 'button[ngbAccordionButton]',
standalone: true,
host: {
'[disabled]': 'item.disabled',
'[class.accordion-button]': 'true',
type: 'button',
},
hostDirectives: [
{
directive: NgbAccordionToggle,
},
],
}]
}], ctorParameters: function () { return [{ type: NgbAccordionItem, decorators: [{
type: Inject,
args: [forwardRef(() => NgbAccordionItem)]
}] }]; } });
/**
* A directive that wraps an accordion item's header.
*
* @since 14.1.0
*/
class NgbAccordionHeader {
constructor(item) {
this.item = item;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionHeader, deps: [{ token: forwardRef(() => NgbAccordionItem) }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: NgbAccordionHeader, isStandalone: true, selector: "[ngbAccordionHeader]", host: { attributes: { "role": "heading" }, properties: { "class.accordion-header": "true", "class.collapsed": "item.collapsed" } }, ngImport: i0 }); }
}
export { NgbAccordionHeader };
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionHeader, decorators: [{
type: Directive,
args: [{
selector: '[ngbAccordionHeader]',
standalone: true,
host: {
role: 'heading',
'[class.accordion-header]': 'true',
'[class.collapsed]': 'item.collapsed',
},
}]
}], ctorParameters: function () { return [{ type: NgbAccordionItem, decorators: [{
type: Inject,
args: [forwardRef(() => NgbAccordionItem)]
}] }]; } });
/**
* A directive that wraps an accordion item: a toggleable header + body that collapses.
*
* You can get hold of the `NgbAccordionItem` instance in the template with `#item="ngbAccordionItem"`.
* It allows to check if the item is collapsed or not, toggle the collapse state, etc.
*
* Every accordion item has a string ID that is automatically generated in the `ngb-accordion-item-XX` format, unless provided explicitly.
*
* @since 14.1.0
*/
class NgbAccordionItem {
constructor(_accordion, _cd) {
this._accordion = _accordion;
this._cd = _cd;
this._subscriptions = [];
this._collapsed = true;
this._id = `ngb-accordion-item-${nextId++}`;
this.animatingBodyCollapse = false;
/**
* If `true`, the content of the accordion item's body will be removed from the DOM. It will be just hidden otherwise.
*
* This property can also be set up on the parent [`NgbAccordion` directive](#/components/accordion/api#NgbAccordionDirective).
*/
this.destroyOnHide = this._accordion.destroyOnHide;
/**
* If `true`, the accordion item will be disabled.
* It won't react to user's clicks, but still will be toggelable programmatically.
*/
this.disabled = false;
/**
* Event emitted when the expanding animation is finished. It has no payload.
*/
this.shown = new EventEmitter();
/**
* Event emitted when the collapsing animation is finished and before the content is removed from DOM.
* It has no payload.
*/
this.hidden = new EventEmitter();
}
/**
* Sets the custom ID of the accordion item. It must be unique for the document.
*
* @param id The ID of the accordion item, must be a non-empty string
*/
set id(id) {
if (isString(id) && id !== '') {
this._id = id;
}
}
/**
* If `true`, the accordion item will be collapsed. Otherwise, it will be expanded.
*
* @param collapsed New state of the accordion item.
*/
set collapsed(collapsed) {
if (this.collapsed !== collapsed) {
// checking if accordion allows to expand the panel in respect to 'closeOthers' flag
if (this.collapsed && !this._accordion._ensureCanExpand(this)) {
return;
}
this._collapsed = collapsed;
this._cd.markForCheck(); // need if the accordion is used inside a component having OnPush change detection strategy
// we need force CD to get template into DOM before starting animation to calculate its height correctly
if (!this.collapsed) {
this.animatingBodyCollapse = true;
this._cd.detectChanges();
}
// we also need to make sure 'animation' flag is up-to- date
this._collapse.ngbCollapse.animation = this._accordion.animation;
this._collapse.ngbCollapse.collapsed = this.collapsed;
}
}
get collapsed() {
return this._collapsed;
}
get id() {
return `${this._id}`;
}
get toggleId() {
return `${this.id}-toggle`;
}
get collapseId() {
return `${this.id}-collapse`;
}
ngAfterContentInit() {
const { ngbCollapse } = this._collapse;
// we need to disable the animation for the first init
ngbCollapse.animation = false;
ngbCollapse.collapsed = this.collapsed;
// we set the animation to the default of the accordion
ngbCollapse.animation = this._accordion.animation;
// event forwarding from 'ngbCollapse' to 'ngbAccordion'
this._subscriptions.push(ngbCollapse.hidden.subscribe(() => {
// when the animation finishes we can remove the template from DOM
this.animatingBodyCollapse = false;
this.hidden.emit();
this._accordion.hidden.emit(this.id);
}), ngbCollapse.shown.subscribe(() => {
this.shown.emit();
this._accordion.shown.emit(this.id);
}));
}
ngOnDestroy() {
this._subscriptions.forEach((s) => s.unsubscribe());
}
/**
* Toggles an accordion item.
*/
toggle() {
this.collapsed = !this.collapsed;
}
/**
* Expands an accordion item.
*/
expand() {
this.collapsed = false;
}
/**
* Collapses an accordion item.
*/
collapse() {
this.collapsed = true;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionItem, deps: [{ token: forwardRef(() => NgbAccordionDirective) }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: NgbAccordionItem, isStandalone: true, selector: "[ngbAccordionItem]", inputs: { id: ["ngbAccordionItem", "id"], destroyOnHide: "destroyOnHide", disabled: "disabled", collapsed: "collapsed" }, outputs: { shown: "shown", hidden: "hidden" }, host: { properties: { "class.accordion-item": "true", "id": "id" } }, queries: [{ propertyName: "_collapse", first: true, predicate: NgbAccordionCollapse, descendants: true, static: true }], exportAs: ["ngbAccordionItem"], ngImport: i0 }); }
}
export { NgbAccordionItem };
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionItem, decorators: [{
type: Directive,
args: [{
selector: '[ngbAccordionItem]',
exportAs: 'ngbAccordionItem',
standalone: true,
host: {
'[class.accordion-item]': 'true',
'[id]': 'id',
},
}]
}], ctorParameters: function () { return [{ type: NgbAccordionDirective, decorators: [{
type: Inject,
args: [forwardRef(() => NgbAccordionDirective)]
}] }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { _collapse: [{
type: ContentChild,
args: [NgbAccordionCollapse, { static: true }]
}], id: [{
type: Input,
args: ['ngbAccordionItem']
}], destroyOnHide: [{
type: Input
}], disabled: [{
type: Input
}], collapsed: [{
type: Input
}], shown: [{
type: Output
}], hidden: [{
type: Output
}] } });
/**
* Accordion is a stack of cards that have a header and collapsible body.
*
* This directive is a container for these items and provides an API to handle them.
*
* @since 14.1.0
*/
class NgbAccordionDirective {
constructor(config) {
/**
* If `true`, the content of the accordion items body will be removed from the DOM. It will be just hidden otherwise.
*
* This property can be overwritten at the [`NgbAccordionItem`](#/components/accordion/api#NgbAccordionItem) level
*/
this.destroyOnHide = true;
/**
* Event emitted when the expanding animation is finished. The payload is the id of shown accordion item.
*/
this.shown = new EventEmitter();
/**
* Event emitted when the collapsing animation is finished and before the content is removed from DOM.
* The payload is the id of hidden accordion item.
*/
this.hidden = new EventEmitter();
this._anItemWasAlreadyExpandedDuringInitialisation = false;
this.animation = config.animation;
this.closeOthers = config.closeOthers;
}
/**
* Toggles an item with the given id.
*
* It will toggle an item, even if it is disabled.
*
* @param itemId The id of the item to toggle.
*/
toggle(itemId) {
this._getItem(itemId)?.toggle();
}
/**
* Expands an item with the given id.
*
* If `closeOthers` is `true`, it will collapse other panels.
*
* @param itemId The id of the item to expand.
*/
expand(itemId) {
this._getItem(itemId)?.expand();
}
/**
* Expands all items.
*
* If `closeOthers` is `true` and all items are closed, it will open the first one. Otherwise, it will keep the opened one.
*/
expandAll() {
if (this._items) {
if (this.closeOthers) {
// we check if there is an item open and if it is not we can expand the first item
// (otherwise we toggle nothing)
if (!this._items.find((item) => !item.collapsed)) {
this._items.first.expand();
}
}
else {
this._items.forEach((item) => item.expand());
}
}
}
/**
* Collapses an item with the given id.
*
* Has no effect if the `itemId` does not correspond to any item.
*
* @param itemId The id of the item to collapse.
*/
collapse(itemId) {
this._getItem(itemId)?.collapse();
}
/**
* Collapses all items.
*/
collapseAll() {
this._items?.forEach((item) => item.collapse());
}
/**
* Checks if an item with the given id is expanded.
*
* If the `itemId` does not correspond to any item, it returns `false`.
*
* @param itemId The id of the item to check.
*/
isExpanded(itemId) {
const item = this._getItem(itemId);
return item ? !item.collapsed : false;
}
/**
* It checks, if the item can be expanded in the current state of the accordion.
* With `closeOthers` there can be only one expanded item at a time.
*
* @internal
*/
_ensureCanExpand(toExpand) {
if (!this.closeOthers) {
return true;
}
// special case during the initialization of the [collapse]="false" inputs
// `this._items` QueryList is not yet initialized, but we need to ensure only one item can be expanded at a time
if (!this._items) {
if (!this._anItemWasAlreadyExpandedDuringInitialisation) {
this._anItemWasAlreadyExpandedDuringInitialisation = true;
return true;
}
return false;
}
// if there is an expanded item, we need to collapse it first
this._items.find((item) => !item.collapsed && toExpand !== item)?.collapse();
return true;
}
_getItem(itemId) {
return this._items?.find((item) => item.id === itemId);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionDirective, deps: [{ token: i2.NgbAccordionConfig }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: NgbAccordionDirective, isStandalone: true, selector: "[ngbAccordion]", inputs: { animation: "animation", closeOthers: "closeOthers", destroyOnHide: "destroyOnHide" }, outputs: { shown: "shown", hidden: "hidden" }, host: { properties: { "class.accordion": "true" } }, queries: [{ propertyName: "_items", predicate: NgbAccordionItem }], exportAs: ["ngbAccordion"], ngImport: i0 }); }
}
export { NgbAccordionDirective };
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgbAccordionDirective, decorators: [{
type: Directive,
args: [{
selector: '[ngbAccordion]',
standalone: true,
exportAs: 'ngbAccordion',
host: { '[class.accordion]': 'true' },
}]
}], ctorParameters: function () { return [{ type: i2.NgbAccordionConfig }]; }, propDecorators: { _items: [{
type: ContentChildren,
args: [NgbAccordionItem, { descendants: false }]
}], animation: [{
type: Input
}], closeOthers: [{
type: Input
}], destroyOnHide: [{
type: Input
}], shown: [{
type: Output
}], hidden: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNjb3JkaW9uLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hY2NvcmRpb24vYWNjb3JkaW9uLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBR04sY0FBYyxFQUVkLFlBQVksRUFDWixlQUFlLEVBQ2YsU0FBUyxFQUNULFVBQVUsRUFFVixZQUFZLEVBQ1osVUFBVSxFQUNWLE1BQU0sRUFDTixNQUFNLEVBQ04sS0FBSyxFQUVMLE1BQU0sRUFFTixXQUFXLEdBQ1gsTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxjQUFjLENBQUM7Ozs7QUFFeEMsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0FBRWY7Ozs7Ozs7R0FPRztBQUNILE1BS2EsZ0JBQWdCO0lBTDdCO1FBTVMsWUFBTyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNqQyxhQUFRLEdBQUcsTUFBTSxDQUFDLENBQUEsVUFBdUIsQ0FBQSxDQUFDLENBQUMsYUFBYSxDQUFDO1FBQ3pELFVBQUssR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUVqQyxhQUFRLEdBQWdDLElBQUksQ0FBQztLQW9DckQ7SUFoQ0EscUJBQXFCO1FBQ3BCLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUNsQixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMscUJBQXFCLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFBRTtnQkFDbEUsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7YUFDOUI7aUJBQU07Z0JBQ04sSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7YUFDNUI7U0FDRDtJQUNGLENBQUM7SUFFRCxXQUFXO1FBQ1YsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7SUFD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QkFBZCxNQUFNO2dCQU1HLE1BQU07c0JBQWYsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdEFmdGVyQ29udGVudENoZWNrZWQsXG5cdEFmdGVyQ29udGVudEluaXQsXG5cdEFwcGxpY2F0aW9uUmVmLFxuXHRDaGFuZ2VEZXRlY3RvclJlZixcblx0Q29udGVudENoaWxkLFxuXHRDb250ZW50Q2hpbGRyZW4sXG5cdERpcmVjdGl2ZSxcblx0RWxlbWVudFJlZixcblx0RW1iZWRkZWRWaWV3UmVmLFxuXHRFdmVudEVtaXR0ZXIsXG5cdGZvcndhcmRSZWYsXG5cdGluamVjdCxcblx0SW5qZWN0LFxuXHRJbnB1dCxcblx0T25EZXN0cm95LFxuXHRPdXRwdXQsXG5cdFF1ZXJ5TGlzdCxcblx0VGVtcGxhdGVSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBOZ2JBY2NvcmRpb25Db25maWcgfSBmcm9tICcuL2FjY29yZGlvbi1jb25maWcnO1xuaW1wb3J0IHsgTmdiQ29sbGFwc2UgfSBmcm9tICcuLi9jb2xsYXBzZS9jb2xsYXBzZSc7XG5pbXBvcnQgeyBpc1N0cmluZyB9IGZyb20gJy4uL3V0aWwvdXRpbCc7XG5cbmxldCBuZXh0SWQgPSAwO1xuXG4vKipcbiAqIEEgZGlyZWN0aXZlIHRoYXQgd3JhcHMgdGhlIGNvbnRlbnQgb2YgYW4gYWNjb3JkaW9uIGl0ZW0ncyBjb2xsYXBzaWJsZSBib2R5LlxuICpcbiAqIFRoZSBhY3R1YWwgY29udGVudCBpcyBwcm92aWRlZCBpbiBhIGNoaWxkIGBuZy10ZW1wbGF0ZWAgZWxlbWVudC5cbiAqIERlcGVuZGluZyBvbiB0aGUgc3RhdGUgb2YgdGhlIGFjY29yZGlvbiwgdGhlIHRlbXBsYXRlIHdpbGwgYmUgZWl0aGVyIGluc2VydGVkIG9yIHJlbW92ZWQgZnJvbSB0aGUgRE9NLlxuICpcbiAqIEBzaW5jZSAxNC4xLjBcbiAqL1xuQERpcmVjdGl2ZSh7XG5cdHNlbGVjdG9yOiAnW25nYkFjY29yZGlvbkJvZHldJyxcblx0c3RhbmRhbG9uZTogdHJ1ZSxcblx0aG9zdDogeyAnW2NsYXNzLmFjY29yZGlvbi1ib2R5XSc6ICd0cnVlJyB9LFxufSlcbmV4cG9ydCBjbGFzcyBOZ2JBY2NvcmRpb25Cb2R5IGltcGxlbWVudHMgQWZ0ZXJDb250ZW50Q2hlY2tlZCwgT25EZXN0cm95IHtcblx0cHJpdmF0ZSBfYXBwUmVmID0gaW5qZWN0KEFwcGxpY2F0aW9uUmVmKTtcblx0cHJpdmF0ZSBfZWxlbWVudCA9IGluamVjdChFbGVtZW50UmVmPEhUTUxFbGVtZW50PikubmF0aXZlRWxlbWVudDtcblx0cHJpdmF0ZSBfaXRlbSA9IGluamVjdChOZ2JBY2NvcmRpb25JdGVtKTtcblxuXHRwcml2YXRlIF92aWV3UmVmOiBFbWJlZGRlZFZpZXdSZWY8YW55PiB8IG51bGwgPSBudWxsO1xuXG5cdEBDb250ZW50Q2hpbGQoVGVtcGxhdGVSZWYsIHsgc3RhdGljOiB0cnVlIH0pIHByaXZhdGUgX2JvZHlUcGw6IFRlbXBsYXRlUmVmPGFueT47XG5cblx0bmdBZnRlckNvbnRlbnRDaGVja2VkKCk6IHZvaWQge1xuXHRcdGlmICh0aGlzLl9ib2R5VHBsKSB7XG5cdFx0XHRpZiAodGhpcy5faXRlbS5hbmltYXRpbmdCb2R5Q29sbGFwc2UgfHwgIXRoaXMuX2l0ZW0uZGVzdHJveU9uSGlkZSkge1xuXHRcdFx0XHR0aGlzLl9jcmVhdGVWaWV3SWZOb3RFeGlzdHMoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuX2Rlc3Ryb3lWaWV3SWZFeGlzdHMoKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRuZ09uRGVzdHJveSgpOiB2b2lkIHtcblx0XHR0aGlzLl9kZXN0cm95Vmlld0lmRXhpc3RzKCk7XG5cdH1cblxuXHRwcml2YXRlIF9kZXN0cm95Vmlld0lmRXhpc3RzKCk6IHZvaWQge1xuXHRcdGlmICh0aGlzLl92aWV3UmVmKSB7XG5cdFx0XHR0aGlzLl9hcHBSZWYuZGV0YWNoVmlldyh0aGlzLl92aWV3UmVmKTtcblx0XHRcdHRoaXMuX3ZpZXdSZWYuZGVzdHJveSgpO1xuXHRcdFx0dGhpcy5fdmlld1JlZiA9IG51bGw7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBfY3JlYXRlVmlld0lmTm90RXhpc3RzKCk6IHZvaWQge1xuXHRcdGlmICghdGhpcy5fdmlld1JlZikge1xuXHRcdFx0dGhpcy5fdmlld1JlZiA9IHRoaXMuX2JvZHlUcGwuY3JlYXRlRW1iZWRkZWRWaWV3KG51bGwpO1xuXHRcdFx0dGhpcy5fdmlld1JlZi5kZXRlY3RDaGFuZ2VzKCk7XG5cdFx0XHR0aGlzLl9hcHBSZWYuYXR0YWNoVmlldyh0aGlzLl92aWV3UmVmKTtcblx0XHRcdGZvciAoY29uc3Qgbm9kZSBvZiB0aGlzLl92aWV3UmVmLnJvb3ROb2Rlcykge1xuXHRcdFx0XHR0aGlzLl9lbGVtZW50LmFwcGVuZENoaWxkKG5vZGUpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIEEgZGlyZWN0aXZlIHRoYXQgd3JhcHMgdGhlIGNvbGxhcHNpYmxlIGl0ZW0ncyBjb250ZW50IG9mIHRoZSBhY2NvcmRpb24uXG4gKlxuICogSW50ZXJuYWxseSBpdCByZXVzZXMgdGhlIFtgTmdiQ29sbGFwc2VgIGRpcmVjdGl2ZV0oIy9jb21wb25lbnRzL2NvbGxhcHNlKVxuICpcbiAqIEBzaW5jZSAxNC4xLjBcbiAqL1xuQERpcmVjdGl2ZSh7XG5cdGV4cG9ydEFzOiAnbmdiQWNjb3JkaW9uQ29sbGFwc2UnLFxuXHRzdGFuZGFsb25lOiB0cnVlLFxuXHRzZWxlY3RvcjogJ1tuZ2JBY2NvcmRpb25Db2xsYXBzZV0nLFxuXHRob3N0OiB7XG5cdFx0cm9sZTogJ3JlZ2lvbicsXG5cdFx0J1tjbGFzcy5hY2NvcmRpb24tY29sbGFwc2VdJzogJ3RydWUnLFxuXHRcdCdbaWRdJzogJ2l0ZW0uY29sbGFwc2VJZCcsXG5cdFx0J1thdHRyLmFyaWEtbGFiZWxsZWRieV0nOiAnaXRlbS50b2dnbGVJZCcsXG5cdH0sXG5cdGhvc3REaXJlY3RpdmVzOiBbXG5cdFx0e1xuXHRcdFx0ZGlyZWN0aXZlOiBOZ2JDb2xsYXBzZSxcblx0XHR9LFxuXHRdLFxufSlcbmV4cG9ydCBjbGFzcyBOZ2JBY2NvcmRpb25Db2xsYXBzZSB7XG5cdGNvbnN0cnVjdG9yKFxuXHRcdEBJbmplY3QoZm9yd2FyZFJlZigoKSA9PiBOZ2JBY2NvcmRpb25JdGVtKSkgcHVibGljIGl0ZW06IE5nYkFjY29yZGlvbkl0ZW0sXG5cdFx0cHVibGljIG5nYkNvbGxhcHNlOiBOZ2JDb2xsYXBzZSxcblx0KSB7fVxufVxuXG4vKipcbiAqIEEgZGlyZWN0aXZlIHRvIHB1dCBvbiBhIHRvZ2dsaW5nIGVsZW1lbnQgaW5zaWRlIHRoZSBhY2NvcmRpb24gaXRlbSdzIGhlYWRlci5cbiAqIEl0IHdpbGwgcmVnaXN0ZXIgY2xpY2sgaGFuZGxlcnMgdGhhdCB0b2dnbGUgdGhlIGFzc29jaWF0ZWQgcGFuZWwgYW5kIHdpbGwgaGFuZGxlIGFjY2Vzc2liaWxpdHkgYXR0cmlidXRlcy5cbiAqXG4gKiBUaGlzIGRpcmVjdGl2ZSBpcyB1c2VkIGludGVybmFsbHkgYnkgdGhlIFtgTmdiQWNjb3JkaW9uQnV0dG9uYCBkaXJlY3RpdmVdKCMvY29tcG9uZW50cy9hY2NvcmRpb24vYXBpI05nYkFjY29yZGlvbkJ1dHRvbikuXG4gKlxuICogQHNpbmNlIDE0LjEuMFxuICovXG5ARGlyZWN0aXZlKHtcblx0c2VsZWN0b3I6ICdbbmdiQWNjb3JkaW9uVG9nZ2xlXScsXG5cdHN0YW5kYWxvbmU6IHRydWUsXG5cdGhvc3Q6IHtcblx0XHQnW2lkXSc6ICdpdGVtLnRvZ2dsZUlkJyxcblx0XHQnW2NsYXNzLmNvbGxhcHNlZF0nOiAnaXRlbS5jb2xsYXBzZWQnLFxuXHRcdCdbYXR0ci5hcmlhLWNvbnRyb2xzXSc6ICdpdGVtLmNvbGxhcHNlSWQnLFxuXHRcdCdbYXR0ci5hcmlhLWV4cGFuZGVkXSc6ICchaXRlbS5jb2xsYXBzZWQnLFxuXHRcdCcoY2xpY2spJzogJyFpdGVtLmRpc2FibGVkICYmIGFjY29yZGlvbi50b2dnbGUoaXRlbS5pZCknLFxuXHR9LFxufSlcbmV4cG9ydCBjbGFzcyBOZ2JBY2NvcmRpb25Ub2dnbGUge1xuXHRjb25zdHJ1Y3Rvcihcblx0XHRASW5qZWN0KGZvcndhcmRSZWYoKCkgPT4gTmdiQWNjb3JkaW9uSXRlbSkpIHB1YmxpYyBpdGVtOiBOZ2JBY2NvcmRpb25JdGVtLFxuXHRcdEBJbmplY3QoZm9yd2FyZFJlZigoKSA9PiBOZ2JBY2NvcmRpb25EaXJlY3RpdmUpKSBwdWJsaWMgYWNjb3JkaW9uOiBOZ2JBY2NvcmRpb25EaXJlY3RpdmUsXG5cdCkge31cbn1cblxuLyoqXG4gKiBBIGRpcmVjdGl2ZSB0byBwdXQgb24gYSBidXR0b24gZWxlbWVudCBpbnNpZGUgYW4gYWNjb3JkaW9uIGl0ZW0ncyBoZWFkZXIuXG4gKlxuICogSWYgeW91IHdhbnQgYSBjdXN0b20gbWFya3VwIGZvciB0aGUgaGVhZGVyLCB5b3UgY2FuIGFsc28gdXNlIHRoZSBbYE5nYkFjY29yZGlvblRvZ2dsZWAgZGlyZWN0aXZlXSgjL2NvbXBvbmVudHMvYWNjb3JkaW9uL2FwaSNOZ2JBY2NvcmRpb25Ub2dnbGUpLlxuICpcbiAqIEBzaW5jZSAxNC4xLjBcbiAqL1xuQERpcmVjdGl2ZSh7XG5cdHNlbGVjdG9yOiAnYnV0dG9uW25nYkFjY29yZGlvbkJ1dHRvbl0nLFxuXHRzdGFuZGFsb25lOiB0cnVlLFxuXHRob3N0OiB7XG5cdFx0J1tkaXNhYmxlZF0nOiAnaXRlbS5kaXNhYmxlZCcsXG5cdFx0J1tjbGFzcy5hY2NvcmRpb24tYnV0dG9uXSc6ICd0cnVlJyxcblx0XHR0eXBlOiAnYnV0dG9uJyxcblx0fSxcblx0aG9zdERpcmVjdGl2ZXM6IFtcblx0XHR7XG5cdFx0XHRkaXJlY3RpdmU6IE5nYkFjY29yZGlvblRvZ2dsZSxcblx0XHR9LFxuXHRdLFxufSlcbmV4cG9ydCBjbGFzcyBOZ2JBY2NvcmRpb25CdXR0b24ge1xuXHRjb25zdHJ1Y3RvcihASW5qZWN0KGZvcndhcmRSZWYoKCkgPT4gTmdiQWNjb3JkaW9uSXRlbSkpIHB1YmxpYyBpdGVtOiBOZ2JBY2NvcmRpb25JdGVtKSB7fVxufVxuXG4vKipcbiAqIEEgZGlyZWN0aXZlIHRoYXQgd3JhcHMgYW4gYWNjb3JkaW9uIGl0ZW0ncyBoZWFkZXIuXG4gKlxuICogQHNpbmNlIDE0LjEuMFxuICovXG5ARGlyZWN0aXZlKHtcblx0c2VsZWN0b3I6ICdbbmdiQWNjb3JkaW9uSGVhZGVyXScsXG5cdHN0YW5kYWxvbmU6IHRydWUsXG5cdGhvc3Q6IHtcblx0XHRyb2xlOiAnaGVhZGluZycsXG5cdFx0J1tjbGFzcy5hY2NvcmRpb24taGVhZGVyXSc6ICd0cnVlJyxcblx0XHQnW2NsYXNzLmNvbGxhcHNlZF0nOiAnaXRlbS5jb2xsYXBzZWQnLFxuXHR9LFxufSlcbmV4cG9ydCBjbGFzcyBOZ2JBY2NvcmRpb25IZWFkZXIge1xuXHRjb25zdHJ1Y3RvcihASW5qZWN0KGZvcndhcmRSZWYoKCkgPT4gTmdiQWNjb3JkaW9uSXRlbSkpIHB1YmxpYyBpdGVtOiBOZ2JBY2NvcmRpb25JdGVtKSB7fVxufVxuXG4vKipcbiAqIEEgZGlyZWN0aXZlIHRoYXQgd3JhcHMgYW4gYWNjb3JkaW9uIGl0ZW06IGEgdG9nZ2xlYWJsZSBoZWFkZXIgKyBib2R5IHRoYXQgY29sbGFwc2VzLlxuICpcbiAqIFlvdSBjYW4gZ2V0IGhvbGQgb2YgdGhlIGBOZ2JBY2NvcmRpb25JdGVtYCBpbnN0YW5jZSBpbiB0aGUgdGVtcGxhdGUgd2l0aCBgI2l0ZW09XCJuZ2JBY2NvcmRpb25JdGVtXCJgLlxuICogSXQgYWxsb3dzIHRvIGNoZWNrIGlmIHRoZSBpdGVtIGlzIGNvbGxhcHNlZCBvciBub3QsIHRvZ2dsZSB0aGUgY29sbGFwc2Ugc3RhdGUsIGV0Yy5cbiAqXG4gKiBFdmVyeSBhY2NvcmRpb24gaXRlbSBoYXMgYSBzdHJpbmcgSUQgdGhhdCBpcyBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBpbiB0aGUgYG5nYi1hY2NvcmRpb24taXRlbS1YWGAgZm9ybWF0LCB1bmxlc3MgcHJvdmlkZWQgZXhwbGljaXRseS5cbiAqXG4gKiBAc2luY2UgMTQuMS4wXG4gKi9cbkBEaXJlY3RpdmUoe1xuXHRzZWxlY3RvcjogJ1tuZ2JBY2NvcmRpb25JdGVtXScsXG5cdGV4cG9ydEFzOiAnbmdiQWNjb3JkaW9uSXRlbScsXG5cdHN0YW5kYWxvbmU6IHRydWUsXG5cdGhvc3Q6IHtcblx0XHQnW2NsYXNzLmFjY29yZGlvbi1pdGVtXSc6ICd0cnVlJyxcblx0XHQnW2lkXSc6ICdpZCcsXG5cdH0sXG59KVxuZXhwb3J0IGNsYXNzIE5nYkFjY29yZGlvbkl0ZW0gaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0LCBPbkRlc3Ryb3kge1xuXHRjb25zdHJ1Y3Rvcihcblx0XHRASW5qZWN0KGZvcndhcmRSZWYoKCkgPT4gTmdiQWNjb3JkaW9uRGlyZWN0aXZlKSkgcHJpdmF0ZSBfYWNjb3JkaW9uOiBOZ2JBY2NvcmRpb25EaXJlY3RpdmUsXG5cdFx0cHJpdmF0ZSBfY2Q6IENoYW5nZURldGVjdG9yUmVmLFxuXHQpIHt9XG5cblx0cHJpdmF0ZSBfc3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uW10gPSBbXTtcblx0cHJpdmF0ZSBfY29sbGFwc2VkID0gdHJ1ZTtcblx0cHJpdmF0ZSBfaWQgPSBgbmdiLWFjY29yZGlvbi1pdGVtLSR7bmV4dElkKyt9YDtcblxuXHRhbmltYXRpbmdCb2R5Q29sbGFwc2UgPSBmYWxzZTtcblxuXHRAQ29udGVudENoaWxkKE5nYkFjY29yZGlvbkNvbGxhcHNlLCB7IHN0YXRpYzogdHJ1ZSB9KSBwcml2YXRlIF9jb2xsYXBzZTogTmdiQWNjb3JkaW9uQ29sbGFwc2U7XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGN1c3RvbSBJRCBvZiB0aGUgYWNjb3JkaW9uIGl0ZW0uIEl0IG11c3QgYmUgdW5pcXVlIGZvciB0aGUgZG9jdW1lbnQuXG5cdCAqXG5cdCAqIEBwYXJhbSBpZCBUaGUgSUQgb2YgdGhlIGFjY29yZGlvbiBpdGVtLCBtdXN0IGJlIGEgbm9uLWVtcHR5IHN0cmluZ1xuXHQgKi9cblx0QElucHV0KCduZ2JBY2NvcmRpb25JdGVtJykgc2V0IGlkKGlkOiBzdHJpbmcpIHtcblx0XHRpZiAoaXNTdHJpbmcoaWQpICYmIGlkICE9PSAnJykge1xuXHRcdFx0dGhpcy5faWQgPSBpZDtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogSWYgYHRydWVgLCB0aGUgY29udGVudCBvZiB0aGUgYWNjb3JkaW9uIGl0ZW0ncyBib2R5IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBET00uIEl0IHdpbGwgYmUganVzdCBoaWRkZW4gb3RoZXJ3aXNlLlxuXHQgKlxuXHQgKiBUaGlzIHByb3BlcnR5IGNhbiBhbHNvIGJlIHNldCB1cCBvbiB0aGUgcGFyZW50IFtgTmdiQWNjb3JkaW9uYCBkaXJlY3RpdmVdKCMvY29tcG9uZW50cy9hY2NvcmRpb24vYXBpI05nYkFjY29yZGlvbkRpcmVjdGl2ZSkuXG5cdCAqL1xuXHRASW5wdXQoKSBkZXN0cm95T25IaWRlID0gdGhpcy5fYWNjb3JkaW9uLmRlc3Ryb3lPbkhpZGU7XG5cblx0LyoqXG5cdCAqIElmIGB0cnVlYCwgdGhlIGFjY29yZGlvbiBpdGVtIHdpbGwgYmUgZGlzYWJsZWQuXG5cdCAqIEl0IHdvbid0IHJlYWN0IHRvIHVzZXIncyBjbGlja3MsIGJ1dCBzdGlsbCB3aWxsIGJlIHRvZ2dlbGFibGUgcHJvZ3JhbW1hdGljYWxseS5cblx0ICovXG5cdEBJbnB1dCgpIGRpc2FibGVkID0gZmFsc2U7XG5cblx0LyoqXG5cdCAqXHRJZiBgdHJ1ZWAsIHRoZSBhY2NvcmRpb24gaXRlbSB3aWxsIGJlIGNvbGxhcHNlZC4gT3RoZXJ3aXNlLCBpdCB3aWxsIGJlIGV4cGFuZGVkLlxuXHQgKlxuXHQgKiBAcGFyYW0gY29sbGFwc2VkIE5ldyBzdGF0ZSBvZiB0aGUgYWNjb3JkaW9uIGl0ZW0uXG5cdCAqL1xuXHRASW5wdXQoKSBzZXQgY29sbGFwc2VkKGNvbGxhcHNlZDogYm9vbGVhbikge1xuXHRcdGlmICh0aGlzLmNvbGxhcHNlZCAhPT0gY29sbGFwc2VkKSB7XG5cdFx0XHQvLyBjaGVja2luZyBpZiBhY2NvcmRpb24gYWxsb3dzIHRvIGV4cGFuZCB0aGUgcGFuZWwgaW4gcmVzcGVjdCB0byAnY2xvc2VPdGhlcnMnIGZsYWdcblx0XHRcdGlmICh0aGlzLmNvbGxhcHNlZCAmJiAhdGhpcy5fYWNjb3JkaW9uLl9lbnN1cmVDYW5FeHBhbmQodGhpcykpIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLl9jb2xsYXBzZWQgPSBjb2xsYXBzZWQ7XG5cdFx0XHR0aGlzLl9jZC5tYXJrRm9yQ2hlY2soKTsgLy8gbmVlZCBpZiB0aGUgYWNjb3JkaW9uIGlzIHVzZWQgaW5zaWRlIGEgY29tcG9uZW50IGhhdmluZyBPblB1c2ggY2hhbmdlIGRldGVjdGlvbiBzdHJhdGVneVxuXHRcdFx0Ly8gd2UgbmVlZCBmb3JjZSBDRCB0byBnZXQgdGVtcGxhdGUgaW50byBET00gYmVmb3JlIHN0YXJ0aW5nIGFuaW1hdGlvbiB0byBjYWxjdWxhdGUgaXRzIGhlaWdodCBjb3JyZWN0bHlcblx0XHRcdGlmICghdGhpcy5jb2xsYXBzZWQpIHtcblx0XHRcdFx0dGhpcy5hbmltYXRpbmdCb2R5Q29sbGFwc2UgPSB0cnVlO1xuXHRcdFx0XHR0aGlzLl9jZC5kZXRlY3RDaGFuZ2VzKCk7XG5cdFx0XHR9XG5cdFx0XHQvLyB3ZSBhbHNvIG5lZWQgdG8gbWFrZSBzdXJlICdhbmltYXRpb24nIGZsYWcgaXMgdXAtdG8tIGRhdGVcblx0XHRcdHRoaXMuX2NvbGxhcHNlLm5nYkNvbGxhcHNlLmFuaW1hdGlvbiA9IHRoaXMuX2FjY29yZGlvbi5hbmltYXRpb247XG5cdFx0XHR0aGlzLl9jb2xsYXBzZS5uZ2JDb2xsYXBzZS5jb2xsYXBzZWQgPSB0aGlzLmNvbGxhcHNlZDtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogRXZlbnQgZW1pdHRlZCB3aGVuIHRoZSBleHBhbmRpbmcgYW5pbWF0aW9uIGlzIGZpbmlzaGVkLiBJdCBoYXMgbm8gcGF5bG9hZC5cblx0ICovXG5cdEBPdXRwdXQoKSBzaG93biA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuXHQvKipcblx0ICogRXZlbnQgZW1pdHRlZCB3aGVuIHRoZSBjb2xsYXBzaW5nIGFuaW1hdGlvbiBpcyBmaW5pc2hlZCBhbmQgYmVmb3JlIHRoZSBjb250ZW50IGlzIHJlbW92ZWQgZnJvbSBET00uXG5cdCAqIEl0IGhhcyBubyBwYXlsb2FkLlxuXHQgKi9cblx0QE91dHB1dCgpIGhpZGRlbiA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuXHRnZXQgY29sbGFwc2VkKCkge1xuXHRcdHJldHVybiB0aGlzLl9jb2xsYXBzZWQ7XG5cdH1cblxuXHRnZXQgaWQoKSB7XG5cdFx0cmV0dXJuIGAke3RoaXMuX2lkfWA7XG5cdH1cblxuXHRnZXQgdG9nZ2xlSWQoKSB7XG5cdFx0cmV0dXJuIGAke3RoaXMuaWR9LXRvZ2dsZWA7XG5cdH1cblxuXHRnZXQgY29sbGFwc2VJZCgpIHtcblx0XHRyZXR1cm4gYCR7dGhpcy5pZH0tY29sbGFwc2VgO1xuXHR9XG5cblx0bmdBZnRlckNvbnRlbnRJbml0KCkge1xuXHRcdGNvbnN0IHsgbmdiQ29sbGFwc2UgfSA9IHRoaXMuX2NvbGxhcHNlO1xuXHRcdC8vIHdlIG5lZWQgdG8gZGlzYWJsZSB0aGUgYW5pbWF0aW9uIGZvciB0aGUgZmlyc3QgaW5pdFxuXHRcdG5nYkNvbGxhcHNlLmFuaW1hdGlvbiA9IGZhbHNlO1xuXHRcdG5nYkNvbGxhcHNlLmNvbGxhcHNlZCA9IHRoaXMuY29sbGFwc2VkO1xuXHRcdC8vIHdlIHNldCB0aGUgYW5pbWF0aW9uIHRvIHRoZSBkZWZhdWx0IG9mIHRoZSBhY2NvcmRpb25cblx0XHRuZ2JDb2xsYXBzZS5hbmltYXRpb24gPSB0aGlzLl9hY2NvcmRpb24uYW5pbWF0aW9uO1xuXHRcdC8vIGV2ZW50IGZvcndhcmRpbmcgZnJvbSAnbmdiQ29sbGFwc2UnIHRvICduZ2JBY2NvcmRpb24nXG5cdFx0dGhpcy5fc3Vic2NyaXB0aW9ucy5wdXNoKFxuXHRcdFx0bmdiQ29sbGFwc2UuaGlkZGVuLnN1YnNjcmliZSgoKSA9PiB7XG5cdFx0XHRcdC8vIHdoZW4gdGhlIGFuaW1hdGlvbiBmaW5pc2hlcyB3ZSBjYW4gcmVtb3ZlIHRoZSB0ZW1wbGF0ZSBmcm9tIERPTVxuXHRcdFx0XHR0aGlzLmFuaW1hdGluZ0JvZHlDb2xsYXBzZSA9IGZhbHNlO1xuXHRcdFx0XHR0aGlzLmhpZGRlbi5lbWl0KCk7XG5cdFx0XHRcdHRoaXMuX2FjY29yZGlvbi5oaWRkZW4uZW1pdCh0aGlzLmlkKTtcblx0XHRcdH0pLFxuXHRcdFx0bmdiQ29sbGFwc2Uuc2hvd24uc3Vic2NyaWJlKCgpID0+IHtcblx0XHRcdFx0dGhpcy5zaG93bi5lbWl0KCk7XG5cdFx0XHRcdHRoaXMuX2FjY29yZGlvbi5zaG93bi5lbWl0KHRoaXMuaWQpO1xuXHRcdFx0fSksXG5cdFx0KTtcblx0fVxuXG5cdG5nT25EZXN0cm95KCkge1xuXHRcdHRoaXMuX3N1YnNjcmlwdGlvbnMuZm9yRWFjaCgocykgPT4gcy51bnN1YnNjcmliZSgpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUb2dnbGVzIGFuIGFjY29yZGlvbiBpdGVtLlxuXHQgKi9cblx0dG9nZ2xlKCkge1xuXHRcdHRoaXMuY29sbGFwc2VkID0gIXRoaXMuY29sbGFwc2VkO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4cGFuZHMgYW4gYWNjb3JkaW9uIGl0ZW0uXG5cdCAqL1xuXHRleHBhbmQoKSB7XG5cdFx0dGhpcy5jb2xsYXBzZWQgPSBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb2xsYXBzZXMgYW4gYWNjb3JkaW9uIGl0ZW0uXG5cdCAqL1xuXHRjb2xsYXBzZSgpIHtcblx0XHR0aGlzLmNvbGxhcHNlZCA9IHRydWU7XG5cdH1cbn1cblxuLyoqXG4gKiBBY2NvcmRpb24gaXMgYSBzdGFjayBvZiBjYXJkcyB0aGF0IGhhdmUgYSBoZWFkZXIgYW5kIGNvbGxhcHNpYmxlIGJvZHkuXG4gKlxuICogVGhpcyBkaXJlY3RpdmUgaXMgYSBjb250YWluZXIgZm9yIHRoZXNlIGl0ZW1zIGFuZCBwcm92aWRlcyBhbiBBUEkgdG8gaGFuZGxlIHRoZW0uXG4gKlxuICogQHNpbmNlIDE0LjEuMFxuICovXG5ARGlyZWN0aXZlKHtcblx0c2VsZWN0b3I6ICdbbmdiQWNjb3JkaW9uXScsXG5cdHN0YW5kYWxvbmU6IHRydWUsXG5cdGV4cG9ydEFzOiAnbmdiQWNjb3JkaW9uJyxcblx0aG9zdDogeyAnW2NsYXNzLmFjY29yZGlvbl0nOiAndHJ1ZScgfSxcbn0pXG5leHBvcnQgY2xhc3MgTmdiQWNjb3JkaW9uRGlyZWN0aXZlIHtcblx0QENvbnRlbnRDaGlsZHJlbihOZ2JBY2NvcmRpb25JdGVtLCB7IGRlc2NlbmRhbnRzOiBmYWxzZSB9KSBwcml2YXRlIF9pdGVtcz86IFF1ZXJ5TGlzdDxOZ2JBY2NvcmRpb25JdGVtPjtcblx0LyoqXG5cdCAqIElmIGB0cnVlYCwgYWNjb3JkaW9uIHdpbGwgYmUgYW5pbWF0ZWQuXG5cdCAqL1xuXHRASW5wdXQoKSBhbmltYXRpb246IGJvb2xlYW47XG5cblx0LyoqXG5cdCAqIElmIGB0cnVlYCwgb25seSBvbmUgaXRlbSBhdCB0aGUgdGltZSBjYW4gc3RheSBvcGVuLlxuXHQgKi9cblx0QElucHV0KCkgY2xvc2VPdGhlcnM6IGJvb2xlYW47XG5cblx0LyoqXG5cdCAqIElmIGB0cnVlYCwgdGhlIGNvbnRlbnQgb2YgdGhlIGFjY29yZGlvbiBpdGVtcyBib2R5IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBET00uIEl0IHdpbGwgYmUganVzdCBoaWRkZW4gb3RoZXJ3aXNlLlxuXHQgKlxuXHQgKiBUaGlzIHByb3BlcnR5IGNhbiBiZSBvdmVyd3JpdHRlbiBhdCB0aGUgW2BOZ2JBY2NvcmRpb25JdGVtYF0oIy9jb21wb25lbnRzL2FjY29yZGlvbi9hcGkjTmdiQWNjb3JkaW9uSXRlbSkgbGV2ZWxcblx0ICovXG5cdEBJbnB1dCgpIGRlc3Ryb3lPbkhpZGUgPSB0cnVlO1xuXG5cdC8qKlxuXHQgKiBFdmVudCBlbWl0dGVkIHdoZW4gdGhlIGV4cGFuZGluZyBhbmltYXRpb24gaXMgZmluaXNoZWQuIFRoZSBwYXlsb2FkIGlzIHRoZSBpZCBvZiBzaG93biBhY2NvcmRpb24gaXRlbS5cblx0ICovXG5cdEBPdXRwdXQoKSBzaG93biA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG5cdC8qKlxuXHQgKiBFdmVudCBlbWl0dGVkIHdoZW4gdGhlIGNvbGxhcHNpbmcgYW5pbWF0aW9uIGlzIGZpbmlzaGVkIGFuZCBiZWZvcmUgdGhlIGNvbnRlbnQgaXMgcmVtb3ZlZCBmcm9tIERPTS5cblx0ICogVGhlIHBheWxvYWQgaXMgdGhlIGlkIG9mIGhpZGRlbiBhY2NvcmRpb24gaXRlbS5cblx0ICovXG5cdEBPdXRwdXQoKSBoaWRkZW4gPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuXHRwcml2YXRlIF9hbkl0ZW1XYXNBbHJlYWR5RXhwYW5kZWREdXJpbmdJbml0aWFsaXNhdG