@ng-bootstrap/ng-bootstrap
Version:
Angular powered Bootstrap
599 lines • 56.5 kB
JavaScript
import { ChangeDetectionStrategy, Component, ContentChild, Directive, EventEmitter, inject, Input, Output, TemplateRef, } from '@angular/core';
import { getValueInRange, isNumber } from '../util/util';
import { NgbPaginationConfig } from './pagination-config';
import { NgTemplateOutlet } from '@angular/common';
import * as i0 from "@angular/core";
/**
* A directive to match the 'ellipsis' link template
*
* @since 4.1.0
*/
export class NgbPaginationEllipsis {
constructor() {
this.templateRef = inject((TemplateRef));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationEllipsis, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbPaginationEllipsis, isStandalone: true, selector: "ng-template[ngbPaginationEllipsis]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationEllipsis, decorators: [{
type: Directive,
args: [{ selector: 'ng-template[ngbPaginationEllipsis]', standalone: true }]
}] });
/**
* A directive to match the 'first' link template
*
* @since 4.1.0
*/
export class NgbPaginationFirst {
constructor() {
this.templateRef = inject((TemplateRef));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationFirst, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbPaginationFirst, isStandalone: true, selector: "ng-template[ngbPaginationFirst]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationFirst, decorators: [{
type: Directive,
args: [{ selector: 'ng-template[ngbPaginationFirst]', standalone: true }]
}] });
/**
* A directive to match the 'last' link template
*
* @since 4.1.0
*/
export class NgbPaginationLast {
constructor() {
this.templateRef = inject((TemplateRef));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationLast, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbPaginationLast, isStandalone: true, selector: "ng-template[ngbPaginationLast]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationLast, decorators: [{
type: Directive,
args: [{ selector: 'ng-template[ngbPaginationLast]', standalone: true }]
}] });
/**
* A directive to match the 'next' link template
*
* @since 4.1.0
*/
export class NgbPaginationNext {
constructor() {
this.templateRef = inject((TemplateRef));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationNext, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbPaginationNext, isStandalone: true, selector: "ng-template[ngbPaginationNext]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationNext, decorators: [{
type: Directive,
args: [{ selector: 'ng-template[ngbPaginationNext]', standalone: true }]
}] });
/**
* A directive to match the page 'number' link template
*
* @since 4.1.0
*/
export class NgbPaginationNumber {
constructor() {
this.templateRef = inject((TemplateRef));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationNumber, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbPaginationNumber, isStandalone: true, selector: "ng-template[ngbPaginationNumber]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationNumber, decorators: [{
type: Directive,
args: [{ selector: 'ng-template[ngbPaginationNumber]', standalone: true }]
}] });
/**
* A directive to match the 'previous' link template
*
* @since 4.1.0
*/
export class NgbPaginationPrevious {
constructor() {
this.templateRef = inject((TemplateRef));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationPrevious, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbPaginationPrevious, isStandalone: true, selector: "ng-template[ngbPaginationPrevious]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationPrevious, decorators: [{
type: Directive,
args: [{ selector: 'ng-template[ngbPaginationPrevious]', standalone: true }]
}] });
/**
* A directive to match the 'pages' whole content
*
* @since 9.1.0
*/
export class NgbPaginationPages {
constructor() {
this.templateRef = inject((TemplateRef));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationPages, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbPaginationPages, isStandalone: true, selector: "ng-template[ngbPaginationPages]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPaginationPages, decorators: [{
type: Directive,
args: [{ selector: 'ng-template[ngbPaginationPages]', standalone: true }]
}] });
/**
* A component that displays page numbers and allows to customize them in several ways.
*/
export class NgbPagination {
constructor() {
this._config = inject(NgbPaginationConfig);
this.pageCount = 0;
this.pages = [];
/**
* If `true`, pagination links will be disabled.
*/
this.disabled = this._config.disabled;
/**
* If `true`, the "First" and "Last" page links are shown.
*/
this.boundaryLinks = this._config.boundaryLinks;
/**
* If `true`, the "Next" and "Previous" page links are shown.
*/
this.directionLinks = this._config.directionLinks;
/**
* If `true`, the ellipsis symbols and first/last page numbers will be shown when `maxSize` > number of pages.
*/
this.ellipses = this._config.ellipses;
/**
* Whether to rotate pages when `maxSize` > number of pages.
*
* The current page always stays in the middle if `true`.
*/
this.rotate = this._config.rotate;
/**
* The maximum number of pages to display.
*/
this.maxSize = this._config.maxSize;
/**
* The current page.
*
* Page numbers start with `1`.
*/
this.page = 1;
/**
* The number of items per page.
*/
this.pageSize = this._config.pageSize;
/**
* An event fired when the page is changed. Will fire only if collection size is set and all values are valid.
*
* Event payload is the number of the newly selected page.
*
* Page numbers start with `1`.
*/
this.pageChange = new EventEmitter(true);
/**
* The pagination display size.
*
* Bootstrap currently supports small and large sizes.
*
* If the passed value is a string (ex. 'custom'), it will just add the `pagination-custom` css class
*/
this.size = this._config.size;
}
hasPrevious() {
return this.page > 1;
}
hasNext() {
return this.page < this.pageCount;
}
nextDisabled() {
return !this.hasNext() || this.disabled;
}
previousDisabled() {
return !this.hasPrevious() || this.disabled;
}
selectPage(pageNumber) {
this._updatePages(pageNumber);
}
ngOnChanges(changes) {
this._updatePages(this.page);
}
isEllipsis(pageNumber) {
return pageNumber === -1;
}
/**
* Appends ellipses and first/last page number to the displayed pages
*/
_applyEllipses(start, end) {
if (this.ellipses) {
if (start > 0) {
// The first page will always be included. If the displayed range
// starts after the third page, then add ellipsis. But if the range
// starts on the third page, then add the second page instead of
// an ellipsis, because the ellipsis would only hide a single page.
if (start > 2) {
this.pages.unshift(-1);
}
else if (start === 2) {
this.pages.unshift(2);
}
this.pages.unshift(1);
}
if (end < this.pageCount) {
// The last page will always be included. If the displayed range
// ends before the third-last page, then add ellipsis. But if the range
// ends on third-last page, then add the second-last page instead of
// an ellipsis, because the ellipsis would only hide a single page.
if (end < this.pageCount - 2) {
this.pages.push(-1);
}
else if (end === this.pageCount - 2) {
this.pages.push(this.pageCount - 1);
}
this.pages.push(this.pageCount);
}
}
}
/**
* Rotates page numbers based on maxSize items visible.
* Currently selected page stays in the middle:
*
* Ex. for selected page = 6:
* [5,*6*,7] for maxSize = 3
* [4,5,*6*,7] for maxSize = 4
*/
_applyRotation() {
let start = 0;
let end = this.pageCount;
let leftOffset = Math.floor(this.maxSize / 2);
let rightOffset = this.maxSize % 2 === 0 ? leftOffset - 1 : leftOffset;
if (this.page <= leftOffset) {
// very beginning, no rotation -> [0..maxSize]
end = this.maxSize;
}
else if (this.pageCount - this.page < leftOffset) {
// very end, no rotation -> [len-maxSize..len]
start = this.pageCount - this.maxSize;
}
else {
// rotate
start = this.page - leftOffset - 1;
end = this.page + rightOffset;
}
return [start, end];
}
/**
* Paginates page numbers based on maxSize items per page.
*/
_applyPagination() {
let page = Math.ceil(this.page / this.maxSize) - 1;
let start = page * this.maxSize;
let end = start + this.maxSize;
return [start, end];
}
_setPageInRange(newPageNo) {
const prevPageNo = this.page;
this.page = getValueInRange(newPageNo, this.pageCount, 1);
if (this.page !== prevPageNo && isNumber(this.collectionSize)) {
this.pageChange.emit(this.page);
}
}
_updatePages(newPage) {
this.pageCount = Math.ceil(this.collectionSize / this.pageSize);
if (!isNumber(this.pageCount)) {
this.pageCount = 0;
}
// fill-in model needed to render pages
this.pages.length = 0;
for (let i = 1; i <= this.pageCount; i++) {
this.pages.push(i);
}
// set page within 1..max range
this._setPageInRange(newPage);
// apply maxSize if necessary
if (this.maxSize > 0 && this.pageCount > this.maxSize) {
let start = 0;
let end = this.pageCount;
// either paginating or rotating page numbers
if (this.rotate) {
[start, end] = this._applyRotation();
}
else {
[start, end] = this._applyPagination();
}
this.pages = this.pages.slice(start, end);
// adding ellipses
this._applyEllipses(start, end);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPagination, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.0.0", type: NgbPagination, isStandalone: true, selector: "ngb-pagination", inputs: { disabled: "disabled", boundaryLinks: "boundaryLinks", directionLinks: "directionLinks", ellipses: "ellipses", rotate: "rotate", collectionSize: "collectionSize", maxSize: "maxSize", page: "page", pageSize: "pageSize", size: "size" }, outputs: { pageChange: "pageChange" }, host: { attributes: { "role": "navigation" } }, queries: [{ propertyName: "tplEllipsis", first: true, predicate: NgbPaginationEllipsis, descendants: true }, { propertyName: "tplFirst", first: true, predicate: NgbPaginationFirst, descendants: true }, { propertyName: "tplLast", first: true, predicate: NgbPaginationLast, descendants: true }, { propertyName: "tplNext", first: true, predicate: NgbPaginationNext, descendants: true }, { propertyName: "tplNumber", first: true, predicate: NgbPaginationNumber, descendants: true }, { propertyName: "tplPrevious", first: true, predicate: NgbPaginationPrevious, descendants: true }, { propertyName: "tplPages", first: true, predicate: NgbPaginationPages, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
<ng-template #first><span aria-hidden="true" i18n="@@ngb.pagination.first">««</span></ng-template>
<ng-template #previous><span aria-hidden="true" i18n="@@ngb.pagination.previous">«</span></ng-template>
<ng-template #next><span aria-hidden="true" i18n="@@ngb.pagination.next">»</span></ng-template>
<ng-template #last><span aria-hidden="true" i18n="@@ngb.pagination.last">»»</span></ng-template>
<ng-template #ellipsis>...</ng-template>
<ng-template #defaultNumber let-page let-currentPage="currentPage">{{ page }}</ng-template>
<ng-template #defaultPages let-page let-pages="pages" let-disabled="disabled">
@for (pageNumber of pages; track pageNumber) {
<li
class="page-item"
[class.active]="pageNumber === page"
[class.disabled]="isEllipsis(pageNumber) || disabled"
[attr.aria-current]="pageNumber === page ? 'page' : null"
>
@if (isEllipsis(pageNumber)) {
<a class="page-link" tabindex="-1" aria-disabled="true">
<ng-template
[ngTemplateOutlet]="tplEllipsis?.templateRef || ellipsis"
[ngTemplateOutletContext]="{ disabled: true, currentPage: page }"
/>
</a>
} @else {
<a
class="page-link"
href
(click)="selectPage(pageNumber); $event.preventDefault()"
[attr.tabindex]="disabled ? '-1' : null"
[attr.aria-disabled]="disabled ? 'true' : null"
>
<ng-template
[ngTemplateOutlet]="tplNumber?.templateRef || defaultNumber"
[ngTemplateOutletContext]="{ disabled: disabled, $implicit: pageNumber, currentPage: page }"
/>
</a>
}
</li>
}
</ng-template>
<ul [class]="'pagination' + (size ? ' pagination-' + size : '')">
@if (boundaryLinks) {
<li class="page-item" [class.disabled]="previousDisabled()">
<a
aria-label="First"
i18n-aria-label="@@ngb.pagination.first-aria"
class="page-link"
href
(click)="selectPage(1); $event.preventDefault()"
[attr.tabindex]="previousDisabled() ? '-1' : null"
[attr.aria-disabled]="previousDisabled() ? 'true' : null"
>
<ng-template
[ngTemplateOutlet]="tplFirst?.templateRef || first"
[ngTemplateOutletContext]="{ disabled: previousDisabled(), currentPage: page }"
/>
</a>
</li>
}
@if (directionLinks) {
<li class="page-item" [class.disabled]="previousDisabled()">
<a
aria-label="Previous"
i18n-aria-label="@@ngb.pagination.previous-aria"
class="page-link"
href
(click)="selectPage(page - 1); $event.preventDefault()"
[attr.tabindex]="previousDisabled() ? '-1' : null"
[attr.aria-disabled]="previousDisabled() ? 'true' : null"
>
<ng-template
[ngTemplateOutlet]="tplPrevious?.templateRef || previous"
[ngTemplateOutletContext]="{ disabled: previousDisabled() }"
/>
</a>
</li>
}
<ng-template
[ngTemplateOutlet]="tplPages?.templateRef || defaultPages"
[ngTemplateOutletContext]="{ $implicit: page, pages: pages, disabled: disabled }"
/>
@if (directionLinks) {
<li class="page-item" [class.disabled]="nextDisabled()">
<a
aria-label="Next"
i18n-aria-label="@@ngb.pagination.next-aria"
class="page-link"
href
(click)="selectPage(page + 1); $event.preventDefault()"
[attr.tabindex]="nextDisabled() ? '-1' : null"
[attr.aria-disabled]="nextDisabled() ? 'true' : null"
>
<ng-template
[ngTemplateOutlet]="tplNext?.templateRef || next"
[ngTemplateOutletContext]="{ disabled: nextDisabled(), currentPage: page }"
/>
</a>
</li>
}
@if (boundaryLinks) {
<li class="page-item" [class.disabled]="nextDisabled()">
<a
aria-label="Last"
i18n-aria-label="@@ngb.pagination.last-aria"
class="page-link"
href
(click)="selectPage(pageCount); $event.preventDefault()"
[attr.tabindex]="nextDisabled() ? '-1' : null"
[attr.aria-disabled]="nextDisabled() ? 'true' : null"
>
<ng-template
[ngTemplateOutlet]="tplLast?.templateRef || last"
[ngTemplateOutletContext]="{ disabled: nextDisabled(), currentPage: page }"
/>
</a>
</li>
}
</ul>
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbPagination, decorators: [{
type: Component,
args: [{
selector: 'ngb-pagination',
standalone: true,
imports: [NgTemplateOutlet],
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
role: 'navigation',
},
template: `
<ng-template #first><span aria-hidden="true" i18n="@@ngb.pagination.first">««</span></ng-template>
<ng-template #previous><span aria-hidden="true" i18n="@@ngb.pagination.previous">«</span></ng-template>
<ng-template #next><span aria-hidden="true" i18n="@@ngb.pagination.next">»</span></ng-template>
<ng-template #last><span aria-hidden="true" i18n="@@ngb.pagination.last">»»</span></ng-template>
<ng-template #ellipsis>...</ng-template>
<ng-template #defaultNumber let-page let-currentPage="currentPage">{{ page }}</ng-template>
<ng-template #defaultPages let-page let-pages="pages" let-disabled="disabled">
@for (pageNumber of pages; track pageNumber) {
<li
class="page-item"
[class.active]="pageNumber === page"
[class.disabled]="isEllipsis(pageNumber) || disabled"
[attr.aria-current]="pageNumber === page ? 'page' : null"
>
@if (isEllipsis(pageNumber)) {
<a class="page-link" tabindex="-1" aria-disabled="true">
<ng-template
[ngTemplateOutlet]="tplEllipsis?.templateRef || ellipsis"
[ngTemplateOutletContext]="{ disabled: true, currentPage: page }"
/>
</a>
} @else {
<a
class="page-link"
href
(click)="selectPage(pageNumber); $event.preventDefault()"
[attr.tabindex]="disabled ? '-1' : null"
[attr.aria-disabled]="disabled ? 'true' : null"
>
<ng-template
[ngTemplateOutlet]="tplNumber?.templateRef || defaultNumber"
[ngTemplateOutletContext]="{ disabled: disabled, $implicit: pageNumber, currentPage: page }"
/>
</a>
}
</li>
}
</ng-template>
<ul [class]="'pagination' + (size ? ' pagination-' + size : '')">
@if (boundaryLinks) {
<li class="page-item" [class.disabled]="previousDisabled()">
<a
aria-label="First"
i18n-aria-label="@@ngb.pagination.first-aria"
class="page-link"
href
(click)="selectPage(1); $event.preventDefault()"
[attr.tabindex]="previousDisabled() ? '-1' : null"
[attr.aria-disabled]="previousDisabled() ? 'true' : null"
>
<ng-template
[ngTemplateOutlet]="tplFirst?.templateRef || first"
[ngTemplateOutletContext]="{ disabled: previousDisabled(), currentPage: page }"
/>
</a>
</li>
}
@if (directionLinks) {
<li class="page-item" [class.disabled]="previousDisabled()">
<a
aria-label="Previous"
i18n-aria-label="@@ngb.pagination.previous-aria"
class="page-link"
href
(click)="selectPage(page - 1); $event.preventDefault()"
[attr.tabindex]="previousDisabled() ? '-1' : null"
[attr.aria-disabled]="previousDisabled() ? 'true' : null"
>
<ng-template
[ngTemplateOutlet]="tplPrevious?.templateRef || previous"
[ngTemplateOutletContext]="{ disabled: previousDisabled() }"
/>
</a>
</li>
}
<ng-template
[ngTemplateOutlet]="tplPages?.templateRef || defaultPages"
[ngTemplateOutletContext]="{ $implicit: page, pages: pages, disabled: disabled }"
/>
@if (directionLinks) {
<li class="page-item" [class.disabled]="nextDisabled()">
<a
aria-label="Next"
i18n-aria-label="@@ngb.pagination.next-aria"
class="page-link"
href
(click)="selectPage(page + 1); $event.preventDefault()"
[attr.tabindex]="nextDisabled() ? '-1' : null"
[attr.aria-disabled]="nextDisabled() ? 'true' : null"
>
<ng-template
[ngTemplateOutlet]="tplNext?.templateRef || next"
[ngTemplateOutletContext]="{ disabled: nextDisabled(), currentPage: page }"
/>
</a>
</li>
}
@if (boundaryLinks) {
<li class="page-item" [class.disabled]="nextDisabled()">
<a
aria-label="Last"
i18n-aria-label="@@ngb.pagination.last-aria"
class="page-link"
href
(click)="selectPage(pageCount); $event.preventDefault()"
[attr.tabindex]="nextDisabled() ? '-1' : null"
[attr.aria-disabled]="nextDisabled() ? 'true' : null"
>
<ng-template
[ngTemplateOutlet]="tplLast?.templateRef || last"
[ngTemplateOutletContext]="{ disabled: nextDisabled(), currentPage: page }"
/>
</a>
</li>
}
</ul>
`,
}]
}], propDecorators: { tplEllipsis: [{
type: ContentChild,
args: [NgbPaginationEllipsis, { static: false }]
}], tplFirst: [{
type: ContentChild,
args: [NgbPaginationFirst, { static: false }]
}], tplLast: [{
type: ContentChild,
args: [NgbPaginationLast, { static: false }]
}], tplNext: [{
type: ContentChild,
args: [NgbPaginationNext, { static: false }]
}], tplNumber: [{
type: ContentChild,
args: [NgbPaginationNumber, { static: false }]
}], tplPrevious: [{
type: ContentChild,
args: [NgbPaginationPrevious, { static: false }]
}], tplPages: [{
type: ContentChild,
args: [NgbPaginationPages, { static: false }]
}], disabled: [{
type: Input
}], boundaryLinks: [{
type: Input
}], directionLinks: [{
type: Input
}], ellipses: [{
type: Input
}], rotate: [{
type: Input
}], collectionSize: [{
type: Input,
args: [{ required: true }]
}], maxSize: [{
type: Input
}], page: [{
type: Input
}], pageSize: [{
type: Input
}], pageChange: [{
type: Output
}], size: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9wYWdpbmF0aW9uL3BhZ2luYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNOLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsWUFBWSxFQUNaLFNBQVMsRUFDVCxZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFFTCxNQUFNLEVBRU4sV0FBVyxHQUNYLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxlQUFlLEVBQUUsUUFBUSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3pELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzFELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDOztBQWdFbkQ7Ozs7R0FJRztBQUVILE1BQU0sT0FBTyxxQkFBcUI7SUFEbEM7UUFFQyxnQkFBVyxHQUFHLE1BQU0sQ0FBQyxDQUFBLFdBQXFDLENBQUEsQ0FBQyxDQUFDO0tBQzVEOzhHQUZZLHFCQUFxQjtrR0FBckIscUJBQXFCOzsyRkFBckIscUJBQXFCO2tCQURqQyxTQUFTO21CQUFDLEVBQUUsUUFBUSxFQUFFLG9DQUFvQyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUU7O0FBSy9FOzs7O0dBSUc7QUFFSCxNQUFNLE9BQU8sa0JBQWtCO0lBRC9CO1FBRUMsZ0JBQVcsR0FBRyxNQUFNLENBQUMsQ0FBQSxXQUFxQyxDQUFBLENBQUMsQ0FBQztLQUM1RDs4R0FGWSxrQkFBa0I7a0dBQWxCLGtCQUFrQjs7MkZBQWxCLGtCQUFrQjtrQkFEOUIsU0FBUzttQkFBQyxFQUFFLFFBQVEsRUFBRSxpQ0FBaUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFOztBQUs1RTs7OztHQUlHO0FBRUgsTUFBTSxPQUFPLGlCQUFpQjtJQUQ5QjtRQUVDLGdCQUFXLEdBQUcsTUFBTSxDQUFDLENBQUEsV0FBcUMsQ0FBQSxDQUFD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QixLQUFLO2dCQUtHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBS0csY0FBYztzQkFBdEIsS0FBSztnQkFLRyxRQUFRO3NCQUFoQixLQUFLO2dCQU9HLE1BQU07c0JBQWQsS0FBSztnQkFTcUIsY0FBYztzQkFBeEMsS0FBSzt1QkFBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7Z0JBS2hCLE9BQU87c0JBQWYsS0FBSztnQkFPRyxJQUFJO3NCQUFaLEtBQUs7Z0JBS0csUUFBUTtzQkFBaEIsS0FBSztnQkFTSSxVQUFVO3NCQUFuQixNQUFNO2dCQVNFLElBQUk7c0JBQVosS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuXHRDb21wb25lbnQsXG5cdENvbnRlbnRDaGlsZCxcblx0RGlyZWN0aXZlLFxuXHRFdmVudEVtaXR0ZXIsXG5cdGluamVjdCxcblx0SW5wdXQsXG5cdE9uQ2hhbmdlcyxcblx0T3V0cHV0LFxuXHRTaW1wbGVDaGFuZ2VzLFxuXHRUZW1wbGF0ZVJlZixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBnZXRWYWx1ZUluUmFuZ2UsIGlzTnVtYmVyIH0gZnJvbSAnLi4vdXRpbC91dGlsJztcbmltcG9ydCB7IE5nYlBhZ2luYXRpb25Db25maWcgfSBmcm9tICcuL3BhZ2luYXRpb24tY29uZmlnJztcbmltcG9ydCB7IE5nVGVtcGxhdGVPdXRsZXQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuXG4vKipcbiAqIEEgY29udGV4dCBmb3IgdGhlXG4gKiAqIGBOZ2JQYWdpbmF0aW9uRmlyc3RgXG4gKiAqIGBOZ2JQYWdpbmF0aW9uUHJldmlvdXNgXG4gKiAqIGBOZ2JQYWdpbmF0aW9uTmV4dGBcbiAqICogYE5nYlBhZ2luYXRpb25MYXN0YFxuICogKiBgTmdiUGFnaW5hdGlvbkVsbGlwc2lzYFxuICogKiBgTmdiUGFnaW5hdGlvblBhZ2VzYFxuICpcbiAqIGxpbmsgdGVtcGxhdGVzIGluIGNhc2UgeW91IHdhbnQgdG8gb3ZlcnJpZGUgb25lLlxuICpcbiAqIEBzaW5jZSA0LjEuMFxuICovXG5leHBvcnQgaW50ZXJmYWNlIE5nYlBhZ2luYXRpb25MaW5rQ29udGV4dCB7XG5cdC8qKlxuXHQgKiBQYWdlIG51bWJlciBkaXNwbGF5ZWQgYnkgdGhlIGN1cnJlbnQgbGluay5cblx0ICovXG5cdGN1cnJlbnRQYWdlOiBudW1iZXI7XG5cblx0LyoqXG5cdCAqIElmIGB0cnVlYCwgdGhlIGN1cnJlbnQgbGluayBpcyBkaXNhYmxlZC5cblx0ICovXG5cdGRpc2FibGVkOiBib29sZWFuO1xufVxuXG4vKipcbiAqIEEgY29udGV4dCBmb3IgdGhlIGBOZ2JQYWdpbmF0aW9uTnVtYmVyYCBsaW5rIHRlbXBsYXRlIGluIGNhc2UgeW91IHdhbnQgdG8gb3ZlcnJpZGUgb25lLlxuICpcbiAqIEV4dGVuZHMgYE5nYlBhZ2luYXRpb25MaW5rQ29udGV4dGAuXG4gKlxuICogQHNpbmNlIDQuMS4wXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTmdiUGFnaW5hdGlvbk51bWJlckNvbnRleHQgZXh0ZW5kcyBOZ2JQYWdpbmF0aW9uTGlua0NvbnRleHQge1xuXHQvKipcblx0ICogVGhlIHBhZ2UgbnVtYmVyLCBkaXNwbGF5ZWQgYnkgdGhlIGN1cnJlbnQgcGFnZSBsaW5rLlxuXHQgKi9cblx0JGltcGxpY2l0OiBudW1iZXI7XG59XG5cbi8qKlxuICogQSBjb250ZXh0IGZvciB0aGUgYE5nYlBhZ2luYXRpb25QYWdlc2AgcGFnZXMgdGVtcGxhdGUgaW4gY2FzZSB5b3Ugd2FudCB0byBvdmVycmlkZVxuICogdGhlIHdheSBhbGwgcGFnZXMgYXJlIGRpc3BsYXllZC5cbiAqXG4gKiBAc2luY2UgOS4xLjBcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBOZ2JQYWdpbmF0aW9uUGFnZXNDb250ZXh0IHtcblx0LyoqXG5cdCAqIFRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgcGFnZSBudW1iZXIuXG5cdCAqL1xuXHQkaW1wbGljaXQ6IG51bWJlcjtcblxuXHQvKipcblx0ICogSWYgYHRydWVgLCBwYWdpbmF0aW9uIGlzIGRpc2FibGVkLlxuXHQgKi9cblx0ZGlzYWJsZWQ6IGJvb2xlYW47XG5cblx0LyoqXG5cdCAqIFBhZ2VzIG51bWJlcnMgdGhhdCBzaG91bGQgYmUgcmVuZGVyZWQgc3RhcnRpbmcgd2l0aCAxLlxuXHQgKi9cblx0cGFnZXM6IG51bWJlcltdO1xufVxuXG4vKipcbiAqIEEgZGlyZWN0aXZlIHRvIG1hdGNoIHRoZSAnZWxsaXBzaXMnIGxpbmsgdGVtcGxhdGVcbiAqXG4gKiBAc2luY2UgNC4xLjBcbiAqL1xuQERpcmVjdGl2ZSh7IHNlbGVjdG9yOiAnbmctdGVtcGxhdGVbbmdiUGFnaW5hdGlvbkVsbGlwc2lzXScsIHN0YW5kYWxvbmU6IHRydWUgfSlcbmV4cG9ydCBjbGFzcyBOZ2JQYWdpbmF0aW9uRWxsaXBzaXMge1xuXHR0ZW1wbGF0ZVJlZiA9IGluamVjdChUZW1wbGF0ZVJlZjxOZ2JQYWdpbmF0aW9uTGlua0NvbnRleHQ+KTtcbn1cblxuLyoqXG4gKiBBIGRpcmVjdGl2ZSB0byBtYXRjaCB0aGUgJ2ZpcnN0JyBsaW5rIHRlbXBsYXRlXG4gKlxuICogQHNpbmNlIDQuMS4wXG4gKi9cbkBEaXJlY3RpdmUoeyBzZWxlY3RvcjogJ25nLXRlbXBsYXRlW25nYlBhZ2luYXRpb25GaXJzdF0nLCBzdGFuZGFsb25lOiB0cnVlIH0pXG5leHBvcnQgY2xhc3MgTmdiUGFnaW5hdGlvbkZpcnN0IHtcblx0dGVtcGxhdGVSZWYgPSBpbmplY3QoVGVtcGxhdGVSZWY8TmdiUGFnaW5hdGlvbkxpbmtDb250ZXh0Pik7XG59XG5cbi8qKlxuICogQSBkaXJlY3RpdmUgdG8gbWF0Y2ggdGhlICdsYXN0JyBsaW5rIHRlbXBsYXRlXG4gKlxuICogQHNpbmNlIDQuMS4wXG4gKi9cbkBEaXJlY3RpdmUoeyBzZWxlY3RvcjogJ25nLXRlbXBsYXRlW25nYlBhZ2luYXRpb25MYXN0XScsIHN0YW5kYWxvbmU6IHRydWUgfSlcbmV4cG9ydCBjbGFzcyBOZ2JQYWdpbmF0aW9uTGFzdCB7XG5cdHRlbXBsYXRlUmVmID0gaW5qZWN0KFRlbXBsYXRlUmVmPE5nYlBhZ2luYXRpb25MaW5rQ29udGV4dD4pO1xufVxuXG4vKipcbiAqIEEgZGlyZWN0aXZlIHRvIG1hdGNoIHRoZSAnbmV4dCcgbGluayB0ZW1wbGF0ZVxuICpcbiAqIEBzaW5jZSA0LjEuMFxuICovXG5ARGlyZWN0aXZlKHsgc2VsZWN0b3I6ICduZy10ZW1wbGF0ZVtuZ2JQYWdpbmF0aW9uTmV4dF0nLCBzdGFuZGFsb25lOiB0cnVlIH0pXG5leHBvcnQgY2xhc3MgTmdiUGFnaW5hdGlvbk5leHQge1xuXHR0ZW1wbGF0ZVJlZiA9IGluamVjdChUZW1wbGF0ZVJlZjxOZ2JQYWdpbmF0aW9uTGlua0NvbnRleHQ+KTtcbn1cblxuLyoqXG4gKiBBIGRpcmVjdGl2ZSB0byBtYXRjaCB0aGUgcGFnZSAnbnVtYmVyJyBsaW5rIHRlbXBsYXRlXG4gKlxuICogQHNpbmNlIDQuMS4wXG4gKi9cbkBEaXJlY3RpdmUoeyBzZWxlY3RvcjogJ25nLXRlbXBsYXRlW25nYlBhZ2luYXRpb25OdW1iZXJdJywgc3RhbmRhbG9uZTogdHJ1ZSB9KVxuZXhwb3J0IGNsYXNzIE5nYlBhZ2luYXRpb25OdW1iZXIge1xuXHR0ZW1wbGF0ZVJlZiA9IGluamVjdChUZW1wbGF0ZVJlZjxOZ2JQYWdpbmF0aW9uTnVtYmVyQ29udGV4dD4pO1xufVxuXG4vKipcbiAqIEEgZGlyZWN0aXZlIHRvIG1hdGNoIHRoZSAncHJldmlvdXMnIGxpbmsgdGVtcGxhdGVcbiAqXG4gKiBAc2luY2UgNC4xLjBcbiAqL1xuQERpcmVjdGl2ZSh7IHNlbGVjdG9yOiAnbmctdGVtcGxhdGVbbmdiUGFnaW5hdGlvblByZXZpb3VzXScsIHN0YW5kYWxvbmU6IHRydWUgfSlcbmV4cG9ydCBjbGFzcyBOZ2JQYWdpbmF0aW9uUHJldmlvdXMge1xuXHR0ZW1wbGF0ZVJlZiA9IGluamVjdChUZW1wbGF0ZVJlZjxOZ2JQYWdpbmF0aW9uTGlua0NvbnRleHQ+KTtcbn1cblxuLyoqXG4gKiBBIGRpcmVjdGl2ZSB0byBtYXRjaCB0aGUgJ3BhZ2VzJyB3aG9sZSBjb250ZW50XG4gKlxuICogQHNpbmNlIDkuMS4wXG4gKi9cbkBEaXJlY3RpdmUoeyBzZWxlY3RvcjogJ25nLXRlbXBsYXRlW25nYlBhZ2luYXRpb25QYWdlc10nLCBzdGFuZGFsb25lOiB0cnVlIH0pXG5leHBvcnQgY2xhc3MgTmdiUGFnaW5hdGlvblBhZ2VzIHtcblx0dGVtcGxhdGVSZWYgPSBpbmplY3QoVGVtcGxhdGVSZWY8TmdiUGFnaW5hdGlvblBhZ2VzQ29udGV4dD4pO1xufVxuXG4vKipcbiAqIEEgY29tcG9uZW50IHRoYXQgZGlzcGxheXMgcGFnZSBudW1iZXJzIGFuZCBhbGxvd3MgdG8gY3VzdG9taXplIHRoZW0gaW4gc2V2ZXJhbCB3YXlzLlxuICovXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6ICduZ2ItcGFnaW5hdGlvbicsXG5cdHN0YW5kYWxvbmU6IHRydWUsXG5cdGltcG9ydHM6IFtOZ1RlbXBsYXRlT3V0bGV0XSxcblx0Y2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG5cdGhvc3Q6IHtcblx0XHRyb2xlOiAnbmF2aWdhdGlvbicsXG5cdH0sXG5cdHRlbXBsYXRlOiBgXG5cdFx0PG5nLXRlbXBsYXRlICNmaXJzdD48c3BhbiBhcmlhLWhpZGRlbj1cInRydWVcIiBpMThuPVwiQEBuZ2IucGFnaW5hdGlvbi5maXJzdFwiPiZsYXF1bzsmbGFxdW87PC9zcGFuPjwvbmctdGVtcGxhdGU+XG5cdFx0PG5nLXRlbXBsYXRlICNwcmV2aW91cz48c3BhbiBhcmlhLWhpZGRlbj1cInRydWVcIiBpMThuPVwiQEBuZ2IucGFnaW5hdGlvbi5wcmV2aW91c1wiPiZsYXF1bzs8L3NwYW4+PC9uZy10ZW1wbGF0ZT5cblx0XHQ8bmctdGVtcGxhdGUgI25leHQ+PHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCIgaTE4bj1cIkBAbmdiLnBhZ2luYXRpb24ubmV4dFwiPiZyYXF1bzs8L3NwYW4+PC9uZy10ZW1wbGF0ZT5cblx0XHQ8bmctdGVtcGxhdGUgI2xhc3Q+PHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCIgaTE4bj1cIkBAbmdiLnBhZ2luYXRpb24ubGFzdFwiPiZyYXF1bzsmcmFxdW87PC9zcGFuPjwvbmctdGVtcGxhdGU+XG5cdFx0PG5nLXRlbXBsYXRlICNlbGxpcHNpcz4uLi48L25nLXRlbXBsYXRlPlxuXHRcdDxuZy10ZW1wbGF0ZSAjZGVmYXVsdE51bWJlciBsZXQtcGFnZSBsZXQtY3VycmVudFBhZ2U9XCJjdXJyZW50UGFnZVwiPnt7IHBhZ2UgfX08L25nLXRlbXBsYXRlPlxuXHRcdDxuZy10ZW1wbGF0ZSAjZGVmYXVsdFBhZ2VzIGxldC1wYWdlIGxldC1wYWdlcz1cInBhZ2VzXCIgbGV0LWRpc2FibGVkPVwiZGlzYWJsZWRcIj5cblx0XHRcdEBmb3IgKHBhZ2VOdW1iZXIgb2YgcGFnZXM7IHRyYWNrIHBhZ2VOdW1iZXIpIHtcblx0XHRcdFx0PGxpXG5cdFx0XHRcdFx0Y2xhc3M9XCJwYWdlLWl0ZW1cIlxuXHRcdFx0XHRcdFtjbGFzcy5hY3RpdmVdPVwicGFnZU51bWJlciA9PT0gcGFnZVwiXG5cdFx0XHRcdFx0W2NsYXNzLmRpc2FibGVkXT1cImlzRWxsaXBzaXMocGFnZU51bWJlcikgfHwgZGlzYWJsZWRcIlxuXHRcdFx0XHRcdFthdHRyLmFyaWEtY3VycmVudF09XCJwYWdlTnVtYmVyID09PSBwYWdlID8gJ3BhZ2UnIDogbnVsbFwiXG5cdFx0XHRcdD5cblx0XHRcdFx0XHRAaWYgKGlzRWxsaXBzaXMocGFnZU51bWJlcikpIHtcblx0XHRcdFx0XHRcdDxhIGNsYXNzPVwicGFnZS1saW5rXCIgdGFiaW5kZXg9XCItMVwiIGFyaWEtZGlzYWJsZWQ9XCJ0cnVlXCI+XG5cdFx0XHRcdFx0XHRcdDxuZy10ZW1wbGF0ZVxuXHRcdFx0XHRcdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0XT1cInRwbEVsbGlwc2lzPy50ZW1wbGF0ZVJlZiB8fCBlbGxpcHNpc1wiXG5cdFx0XHRcdFx0XHRcdFx0W25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgZGlzYWJsZWQ6IHRydWUsIGN1cnJlbnRQYWdlOiBwYWdlIH1cIlxuXHRcdFx0XHRcdFx0XHQvPlxuXHRcdFx0XHRcdFx0PC9hPlxuXHRcdFx0XHRcdH0gQGVsc2Uge1xuXHRcdFx0XHRcdFx0PGFcblx0XHRcdFx0XHRcdFx0Y2xhc3M9XCJwYWdlLWxpbmtcIlxuXHRcdFx0XHRcdFx0XHRocmVmXG5cdFx0XHRcdFx0XHRcdChjbGljayk9XCJzZWxlY3RQYWdlKHBhZ2VOdW1iZXIpOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVwiXG5cdFx0XHRcdFx0XHRcdFthdHRyLnRhYmluZGV4XT1cImRpc2FibGVkID8gJy0xJyA6IG51bGxcIlxuXHRcdFx0XHRcdFx0XHRbYXR0ci5hcmlhLWRpc2FibGVkXT1cImRpc2FibGVkID8gJ3RydWUnIDogbnVsbFwiXG5cdFx0XHRcdFx0XHQ+XG5cdFx0XHRcdFx0XHRcdDxuZy10ZW1wbGF0ZVxuXHRcdFx0XHRcdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0XT1cInRwbE51bWJlcj8udGVtcGxhdGVSZWYgfHwgZGVmYXVsdE51bWJlclwiXG5cdFx0XHRcdFx0XHRcdFx0W25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgZGlzYWJsZWQ6IGRpc2FibGVkLCAkaW1wbGljaXQ6IHBhZ2VOdW1iZXIsIGN1cnJlbnRQYWdlOiBwYWdlIH1cIlxuXHRcdFx0XHRcdFx0XHQvPlxuXHRcdFx0XHRcdFx0PC9hPlxuXHRcdFx0XHRcdH1cblx0XHRcdFx0PC9saT5cblx0XHRcdH1cblx0XHQ8L25nLXRlbXBsYXRlPlxuXHRcdDx1bCBbY2xhc3NdPVwiJ3BhZ2luYXRpb24nICsgKHNpemUgPyAnIHBhZ2luYXRpb24tJyArIHNpemUgOiAnJylcIj5cblx0XHRcdEBpZiAoYm91bmRhcnlMaW5rcykge1xuXHRcdFx0XHQ8bGkgY2xhc3M9XCJwYWdlLWl0ZW1cIiBbY2xhc3MuZGlzYWJsZWRdPVwicHJldmlvdXNEaXNhYmxlZCgpXCI+XG5cdFx0XHRcdFx0PGFcblx0XHRcdFx0XHRcdGFyaWEtbGFiZWw9XCJGaXJzdFwiXG5cdFx0XHRcdFx0XHRpMThuLWFyaWEtbGFiZWw9XCJAQG5nYi5wYWdpbmF0aW9uLmZpcnN0LWFyaWFcIlxuXHRcdFx0XHRcdFx0Y2xhc3M9XCJwYWdlLWxpbmtcIlxuXHRcdFx0XHRcdFx0aHJlZlxuXHRcdFx0XHRcdFx0KGNsaWNrKT1cInNlbGVjdFBhZ2UoMSk7ICRldmVudC5wcmV2ZW50RGVmYXVsdCgpXCJcblx0XHRcdFx0XHRcdFthdHRyLnRhYmluZGV4XT1cInByZXZpb3VzRGlzYWJsZWQoKSA/ICctMScgOiBudWxsXCJcblx0XHRcdFx0XHRcdFthdHRyLmFyaWEtZGlzYWJsZWRdPVwicHJldmlvdXNEaXNhYmxlZCgpID8gJ3RydWUnIDogbnVsbFwiXG5cdFx0XHRcdFx0PlxuXHRcdFx0XHRcdFx0PG5nLXRlbXBsYXRlXG5cdFx0XHRcdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0XT1cInRwbEZpcnN0Py50ZW1wbGF0ZVJlZiB8fCBmaXJzdFwiXG5cdFx0XHRcdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IGRpc2FibGVkOiBwcmV2aW91c0Rpc2FibGVkKCksIGN1cnJlbnRQYWdlOiBwYWdlIH1cIlxuXHRcdFx0XHRcdFx0Lz5cblx0XHRcdFx0XHQ8L2E+XG5cdFx0XHRcdDwvbGk+XG5cdFx0XHR9XG5cdFx0XHRAaWYgKGRpcmVjdGlvbkxpbmtzKSB7XG5cdFx0XHRcdDxsaSBjbGFzcz1cInBhZ2UtaXRlbVwiIFtjbGFzcy5kaXNhYmxlZF09XCJwcmV2aW91c0Rpc2FibGVkKClcIj5cblx0XHRcdFx0XHQ8YVxuXHRcdFx0XHRcdFx0YXJpYS1sYWJlbD1cIlByZXZpb3VzXCJcblx0XHRcdFx0XHRcdGkxOG4tYXJpYS1sYWJlbD1cIkBAbmdiLnBhZ2luYXRpb24ucHJldmlvdXMtYXJpYVwiXG5cdFx0XHRcdFx0XHRjbGFzcz1cInBhZ2UtbGlua1wiXG5cdFx0XHRcdFx0XHRocmVmXG5cdFx0XHRcdFx0XHQoY2xpY2spPVwic2VsZWN0UGFnZShwYWdlIC0gMSk7ICRldmVudC5wcmV2ZW50RGVmYXVsdCgpXCJcblx0XHRcdFx0XHRcdFthdHRyLnRhYmluZGV4XT1cInByZXZpb3VzRGlzYWJsZWQoKSA/ICctMScgOiBudWxsXCJcblx0XHRcdFx0XHRcdFthdHRyLmFyaWEtZGlzYWJsZWRdPVwicHJldmlvdXNEaXNhYmxlZCgpID8gJ3RydWUnIDogbnVsbFwiXG5cdFx0XHRcdFx0PlxuXHRcdFx0XHRcdFx0PG5nLXRlbXBsYXRlXG5cdFx0XHRcdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0XT1cInRwbFByZXZpb3VzPy50ZW1wbGF0ZVJlZiB8fCBwcmV2aW91c1wiXG5cdFx0XHRcdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IGRpc2FibGVkOiBwcmV2aW91c0Rpc2FibGVkKCkgfVwiXG5cdFx0XHRcdFx0XHQvPlxuXHRcdFx0XHRcdDwvYT5cblx0XHRcdFx0PC9saT5cblx0XHRcdH1cblx0XHRcdDxuZy10ZW1wbGF0ZVxuXHRcdFx0XHRbbmdUZW1wbGF0ZU91dGxldF09XCJ0cGxQYWdlcz8udGVtcGxhdGVSZWYgfHwgZGVmYXVsdFBhZ2VzXCJcblx0XHRcdFx0W25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiBwYWdlLCBwYWdlczogcGFnZXMsIGRpc2FibGVkOiBkaXNhYmxlZCB9XCJcblx0XHRcdC8+XG5cdFx0XHRAaWYgKGRpcmVjdGlvbkxpbmtzKSB7XG5cdFx0XHRcdDxsaSBjbGFzcz1cInBhZ2UtaXRlbVwiIFtjbGFzcy5kaXNhYmxlZF09XCJuZXh0RGlzYWJsZWQoKVwiPlxuXHRcdFx0XHRcdDxhXG5cdFx0XHRcdFx0XHRhcmlhLWxhYmVsPVwiTmV4dFwiXG5cdFx0XHRcdFx0XHRpMThuLWFyaWEtbGFiZWw9XCJAQG5nYi5wYWdpbmF0aW9uLm5leHQtYXJpYVwiXG5cdFx0XHRcdFx0XHRjbGFzcz1cInBhZ2UtbGlua1wiXG5cdFx0XHRcdFx0XHRocmVmXG5cdFx0XHRcdFx0XHQoY2xpY2spPVwic2VsZWN0UGFnZShwYWdlICsgMSk7ICRldmVudC5wcmV2ZW50RGVmYXVsdCgpXCJcblx0XHRcdFx0XHRcdFthdHRyLnRhYmluZGV4XT1cIm5leHREaXNhYmxlZCgpID8gJy0xJyA6IG51bGxcIlxuXHRcdFx0XHRcdFx0W2F0dHIuYXJpYS1kaXNhYmxlZF09XCJuZXh0RGlzYWJsZWQoKSA/ICd0cnVlJyA6IG51bGxcIlxuXHRcdFx0XHRcdD5cblx0XHRcdFx0XHRcdDxuZy10ZW1wbGF0ZVxuXHRcdFx0XHRcdFx0XHRbbmdUZW1wbGF0ZU91dGxldF09XCJ0cGxOZXh0Py50ZW1wbGF0ZVJlZiB8fCBuZXh0XCJcblx0XHRcdFx0XHRcdFx0W25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgZGlzYWJsZWQ6IG5leHREaXNhYmxlZCgpLCBjdXJyZW50UGFnZTogcGFnZSB9XCJcblx0XHRcdFx0XHRcdC8+XG5cdFx0XHRcdFx0PC9hPlxuXHRcdFx0XHQ8L2xpPlxuXHRcdFx0fVxuXHRcdFx0QGlmIChib3VuZGFyeUxpbmtzKSB7XG5cdFx0XHRcdDxsaSBjbGFzcz1cInBhZ2UtaXRlbVwiIFtjbGFzcy5kaXNhYmxlZF09XCJuZXh0RGlzYWJsZWQoKVwiPlxuXHRcdFx0XHRcdDxhXG5cdFx0XHRcdFx0XHRhcmlhLWxhYmVsPVwiTGFzdFwiXG5cdFx0XHRcdFx0XHRpMThuLWFyaWEtbGFiZWw9XCJAQG5nYi5wYWdpbmF0aW9uLmxhc3QtYXJpYVwiXG5cdFx0XHRcdFx0XHRjbGFzcz1cInBhZ2UtbGlua1wiXG5cdFx0XHRcdFx0XHRocmVmXG5cdFx0XHRcdFx0XHQoY2xpY2spPVwic2VsZWN0UGFnZShwYWdlQ291bnQpOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVwiXG5cdFx0XHRcdFx0XHRbYXR0ci50YWJpbmRleF09XCJuZXh0RGlzYWJsZWQoKSA/ICctMScgOiBudWxsXCJcblx0XHRcdFx0XHRcdFthdHRyLmFyaWEtZGlzYWJsZWRdPVwibmV4dERpc2FibGVkKCkgPyAndHJ1ZScgOiBudWxsXCJcblx0XHRcdFx0XHQ+XG5cdFx0XHRcdFx0XHQ8bmctdGVtcGxhdGVcblx0XHRcdFx0XHRcdFx0W25nVGVtcGxhdGVPdXRsZXRdPVwidHBsTGFzdD8udGVtcGxhdGVSZWYgfHwgbGFzdFwiXG5cdFx0XHRcdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IGRpc2FibGVkOiBuZXh0RGlzYWJsZWQoKSwgY3VycmVudFBhZ2U6IHBhZ2UgfVwiXG5cdFx0XHRcdFx0XHQvPlxuXHRcdFx0XHRcdDwvYT5cblx0XHRcdFx0PC9saT5cblx0XHRcdH1cblx0XHQ8L3VsPlxuXHRgLFxufSlcbmV4cG9ydCBjbGFzcyBOZ2JQYWdpbmF0aW9uIGltcGxlbWVudHMgT25DaGFuZ2VzIHtcblx0cHJpdmF0ZSBfY29uZmlnID0gaW5qZWN0KE5nYlBhZ2luYXRpb25Db25maWcpO1xuXG5cdHBhZ2VDb3VudCA9IDA7XG5cdHBhZ2VzOiBudW1iZXJbXSA9IFtdO1xuXG5cdEBDb250ZW50Q2hpbGQoTmdiUGFnaW5hdGlvbkVsbGlwc2lzLCB7IHN0YXRpYzogZmFsc2UgfSkgdHBsRWxsaXBzaXM/OiBOZ2JQYWdpbmF0aW9uRWxsaXBzaXM7XG5cdEBDb250ZW50Q2hpbGQoTmdiUGFnaW5hdGlvbkZpcnN0LCB7IHN0YXRpYzogZmFsc2UgfSkgdHBsRmlyc3Q/OiBOZ2JQYWdpbmF0aW9uRmlyc3Q7XG5cdEBDb250ZW50Q2hpbGQoTmdiUGFnaW5hdGlvbkxhc3QsIHsgc3RhdGljOiBmYWxzZSB9KSB0cGxMYXN0PzogTmdiUGFnaW5hdGlvbkxhc3Q7XG5cdEBDb250ZW50Q2hpbGQoTmdiUGFnaW5hdGlvbk5leHQsIHsgc3RhdGljOiBmYWxzZSB9KSB0cGxOZXh0PzogTmdiUGFnaW5hdGlvbk5leHQ7XG5cdEBDb250ZW50Q2hpbGQoTmdiUGFnaW5hdGlvbk51bWJlciwgeyBzdGF0aWM6IGZhbHNlIH0pIHRwbE51bWJlcj86IE5nYlBhZ2luYXRpb25OdW1iZXI7XG5cdEBDb250ZW50Q2hpbGQoTmdiUGFnaW5hdGlvblByZXZpb3VzLCB7IHN0YXRpYzogZmFsc2UgfSkgdHBsUHJldmlvdXM/OiBOZ2JQYWdpbmF0aW9uUHJldmlvdXM7XG5cdEBDb250ZW50Q2hpbGQoTmdiUGFnaW5hdGlvblBhZ2VzLCB7IHN0YXRpYzogZmFsc2UgfSkgdHBsUGFnZXM/OiBOZ2JQYWdpbmF0aW9uUGFnZXM7XG5cblx0LyoqXG5cdCAqIElmIGB0cnVlYCwgcGFnaW5hdGlvbiBsaW5rcyB3aWxsIGJlIGRpc2FibGVkLlxuXHQgKi9cblx0QElucHV0KCkgZGlzYWJsZWQgPSB0aGlzLl9jb25maWcuZGlzYWJsZWQ7XG5cblx0LyoqXG5cdCAqIElmIGB0cnVlYCwgdGhlIFwiRmlyc3RcIiBhbmQgXCJMYXN0XCIgcGFnZSBsaW5rcyBhcmUgc2hvd24uXG5cdCAqL1xuXHRASW5wdXQoKSBib3VuZGFyeUxpbmtzID0gdGhpcy5fY29uZmlnLmJvdW5kYXJ5TGlua3M7XG5cblx0LyoqXG5cdCAqIElmIGB0cnVlYCwgdGhlIFwiTmV4dFwiIGFuZCBcIlByZXZpb3VzXCIgcGFnZSBsaW5rcyBhcmUgc2hvd24uXG5cdCAqL1xuXHRASW5wdXQoKSBkaXJlY3Rpb25MaW5rcyA9IHRoaXMuX2NvbmZpZy5kaXJlY3Rpb25MaW5rcztcblxuXHQvKipcblx0ICogSWYgYHRydWVgLCB0aGUgZWxsaXBzaXMgc3ltYm9scyBhbmQgZmlyc3QvbGFzdCBwYWdlIG51bWJlcnMgd2lsbCBiZSBzaG93biB3aGVuIGBtYXhTaXplYCA+IG51bWJlciBvZiBwYWdlcy5cblx0ICovXG5cdEBJbnB1dCgpIGVsbGlwc2VzID0gdGhpcy5fY29uZmlnLmVsbGlwc2VzO1xuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHRvIHJvdGF0ZSBwYWdlcyB3aGVuIGBtYXhTaXplYCA+IG51bWJlciBvZiBwYWdlcy5cblx0ICpcblx0ICogVGhlIGN1cnJlbnQgcGFnZSBhbHdheXMgc3RheXMgaW4gdGhlIG1pZGRsZSBpZiBgdHJ1ZWAuXG5cdCAqL1xuXHRASW5wdXQoKSByb3RhdGUgPSB0aGlzLl9jb25maWcucm90YXRlO1xuXG5cdC8qKlxuXHQgKiAgVGhlIG51bWJlciBvZiBpdGVtcyBpbiB5b3VyIHBhZ2luYXRlZCBjb2xsZWN0aW9uLlxuXHQgKlxuXHQgKiAgTm90ZSwgdGhhdCB0aGlzIGlzIG5vdCB0aGUgbnVtYmVyIG9mIHBhZ2VzLiBQYWdlIG51bWJlcnMgYXJlIGNhbGN1bGF0ZWQgZHluYW1pY2FsbHkgYmFzZWQgb25cblx0ICogIGBjb2xsZWN0aW9uU2l6ZWAgYW5kIGBwYWdlU2l6ZWAuIEV4LiBpZiB5b3UgaGF2ZSAxMDAgaXRlbXMgaW4geW91ciBjb2xsZWN0aW9uIGFuZCBkaXNwbGF5aW5nIDIwIGl0ZW1zIHBlciBwYWdlLFxuXHQgKiAgeW91J2xsIGVuZCB1cCB3aXRoIDUgcGFnZXMuXG5cdCAqL1xuXHRASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KSBjb2xsZWN0aW9uU2l6ZTogbnVtYmVyO1xuXG5cdC8qKlxuXHQgKiAgVGhlIG1heGltdW0gbnVtYmVyIG9mIHBhZ2VzIHRvIGRpc3BsYXkuXG5cdCAqL1xuXHRASW5wdXQoKSBtYXhTaXplID0gdGhpcy5fY29uZmlnLm1heFNpemU7XG5cblx0LyoqXG5cdCAqICBUaGUgY3VycmVudCBwYWdlLlxuXHQgKlxuXHQgKiAgUGFnZSBudW1iZXJzIHN0YXJ0IHdpdGggYDFgLlxuXHQgKi9cblx0QElucHV0KCkgcGFnZSA9IDE7XG5cblx0LyoqXG5cdCAqICBUaGUgbnVtYmVyIG9mIGl0ZW1zIHBlciBwYWdlLlxuXHQgKi9cblx0QElucHV0KCkgc