UNPKG

carbon-components-angular

Version:
477 lines (467 loc) 45.3 kB
import { Component, Input, Output, EventEmitter } from "@angular/core"; import { merge } from "carbon-components-angular/utils"; import * as i0 from "@angular/core"; import * as i1 from "carbon-components-angular/i18n"; import * as i2 from "carbon-components-angular/experimental"; import * as i3 from "@angular/common"; import * as i4 from "@angular/forms"; import * as i5 from "carbon-components-angular/icon"; import * as i6 from "carbon-components-angular/forms"; /** * Use pagination when you have multiple pages of data to handle. Get started with importing the module: * * ```typescript * import { PaginationModule } from 'carbon-components-angular'; * ``` * * ```html * <cds-pagination [model]="model" (selectPage)="selectPage($event)"></cds-pagination> * ``` * * In your `selectPage()` method set the `model.currentPage` to selected page, _after_ * you load the page. * * ```typescript * selectPage(page) { * // ... your code to load the page goes here * * this.model.currentPage = page; * * // ... anything you want to do after page selection changes goes here * } * ``` * * [See demo](../../?path=/story/components-pagination--basic) */ export class Pagination { constructor(i18n, experimental) { this.i18n = i18n; this.experimental = experimental; /** * Set to `true` for a loading pagination component. */ this.skeleton = false; /** * Set to `true` to disable the backward/forward buttons. */ this.disabled = false; /** * Set to `true` to disable the select box that changes the page. */ this.pageInputDisabled = false; /** * Controls wether or not to show the page selects */ this.showPageInput = true; /** * Set to `true` if the total number of items is unknown. */ this.pagesUnknown = false; this.pageSelectThreshold = 1000; /** * Options for items per page select * * A default array of options will be defined: [10, 20, 30, 40, 50] */ this.itemsPerPageOptions = [10, 20, 30, 40, 50]; /** * Emits the new page number. * * You should tie into this and update `model.currentPage` once the fresh * data is finally loaded. */ this.selectPage = new EventEmitter(); this.itemsPerPageSelectId = `pagination-select-items-per-page-${Pagination.paginationCounter}`; this.currentPageSelectId = `pagination-select-current-page-${Pagination.paginationCounter}`; this.itemsPerPageText = this.i18n.getOverridable("PAGINATION.ITEMS_PER_PAGE"); this.optionsListText = this.i18n.getOverridable("PAGINATION.OPEN_LIST_OF_OPTIONS"); this.backwardText = this.i18n.getOverridable("PAGINATION.BACKWARD"); this.forwardText = this.i18n.getOverridable("PAGINATION.FORWARD"); this.totalItemsText = this.i18n.getOverridable("PAGINATION.TOTAL_ITEMS"); this.totalItemText = this.i18n.getOverridable("PAGINATION.TOTAL_ITEM"); this.totalItemsUnknownText = this.i18n.getOverridable("PAGINATION.TOTAL_ITEMS_UNKNOWN"); this.pageText = this.i18n.getOverridable("PAGINATION.PAGE"); this.ofLastPagesText = this.i18n.getOverridable("PAGINATION.OF_LAST_PAGES"); this.ofLastPageText = this.i18n.getOverridable("PAGINATION.OF_LAST_PAGE"); this._pageOptions = []; Pagination.paginationCounter++; } /** * Expects an object that contains some or all of: * ``` * { * "ITEMS_PER_PAGE": "Items per page:", * "OPEN_LIST_OF_OPTIONS": "Open list of options", * "BACKWARD": "Backward", * "FORWARD": "Forward", * "TOTAL_ITEMS_UNKNOWN": "{{start}}-{{end}} items", * "TOTAL_ITEMS": "{{start}}-{{end}} of {{total}} items", * "TOTAL_ITEM": "{{start}}-{{end}} of {{total}} item", * "OF_LAST_PAGES": "of {{last}} pages", * "OF_LAST_PAGE": "of {{last}} page" * } * ``` */ set translations(value) { const valueWithDefaults = merge(this.i18n.getMultiple("PAGINATION"), value); this.itemsPerPageText.override(valueWithDefaults.ITEMS_PER_PAGE); this.optionsListText.override(valueWithDefaults.OPEN_LIST_OF_OPTIONS); this.backwardText.override(valueWithDefaults.BACKWARD); this.forwardText.override(valueWithDefaults.FORWARD); this.totalItemsText.override(valueWithDefaults.TOTAL_ITEMS); this.totalItemText.override(valueWithDefaults.TOTAL_ITEM); this.totalItemsUnknownText.override(valueWithDefaults.TOTAL_ITEMS_UNKNOWN); this.pageText.override(valueWithDefaults.PAGE); this.ofLastPagesText.override(valueWithDefaults.OF_LAST_PAGES); this.ofLastPageText.override(valueWithDefaults.OF_LAST_PAGE); } get itemsPerPage() { return this.model.pageLength; } set itemsPerPage(value) { this.model.pageLength = Number(value); this.currentPage = 1; // reset page } get currentPage() { return this.model.currentPage; } set currentPage(value) { value = Number(value); // emits the value to allow the user to update current page // in the model once the page is loaded this.selectPage.emit(value); } get totalDataLength() { return this.model.totalDataLength; } /** * The last page number to display in the pagination view. */ get lastPage() { const last = Math.ceil(this.totalDataLength / this.itemsPerPage); return last > 0 ? last : 1; } get startItemIndex() { return this.endItemIndex > 0 ? (this.currentPage - 1) * this.itemsPerPage + 1 : 0; } get endItemIndex() { const projectedEndItemIndex = this.currentPage * this.itemsPerPage; return projectedEndItemIndex < this.totalDataLength ? projectedEndItemIndex : this.totalDataLength; } /** * The previous page number to navigate to, from the current page. */ get previousPage() { return this.currentPage <= 1 ? 1 : this.currentPage - 1; } /** * The next page number to navigate to, from the current page. */ get nextPage() { const lastPage = this.lastPage; return this.currentPage >= lastPage ? lastPage : this.currentPage + 1; } get pageOptions() { if (this.totalDataLength && this._pageOptions.length !== this.totalDataLength) { this._pageOptions = Array(Math.ceil(this.totalDataLength / this.itemsPerPage)); } return this._pageOptions; } } Pagination.paginationCounter = 0; Pagination.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Pagination, deps: [{ token: i1.I18n }, { token: i2.ExperimentalService }], target: i0.ɵɵFactoryTarget.Component }); Pagination.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: Pagination, selector: "cds-pagination, ibm-pagination", inputs: { skeleton: "skeleton", model: "model", disabled: "disabled", pageInputDisabled: "pageInputDisabled", showPageInput: "showPageInput", pagesUnknown: "pagesUnknown", pageSelectThreshold: "pageSelectThreshold", translations: "translations", itemsPerPageOptions: "itemsPerPageOptions" }, outputs: { selectPage: "selectPage" }, ngImport: i0, template: ` <div class="cds--pagination" [ngClass]="{ 'cds--skeleton': skeleton }"> <!-- left skeleton div --> <div *ngIf="skeleton" class="cds--pagination__left"> <p class="cds--skeleton__text" style="width: 70px"></p> <p class="cds--skeleton__text" style="width: 35px"></p> <p class="cds--skeleton__text" style="width: 105px"></p> </div> <div *ngIf="!skeleton" class="cds--pagination__left"> <ng-container *ngIf="showPageInput"> <label class="cds--pagination__text" [for]="itemsPerPageSelectId"> {{itemsPerPageText.subject | async}} </label> <div class="cds--select cds--select--inline cds--select__item-count" [class.cds--select--disabled]="pageInputDisabled"> <select [id]="itemsPerPageSelectId" [(ngModel)]="itemsPerPage" [disabled]="pageInputDisabled" class="cds--select-input"> <option class="cds--select-option" *ngFor="let option of itemsPerPageOptions" [value]="option"> {{ option }} </option> </select> <svg cdsIcon="chevron--down" size="16" style="display: inherit" class="cds--select__arrow" aria-hidden="true" [attr.ariaLabel]="optionsListText.subject | async"> </svg> </div> </ng-container> <span *ngIf="!pagesUnknown && totalDataLength <= 1" class="cds--pagination__text cds--pagination__items-count" [ngStyle]="{'margin-left': showPageInput ? null : 0}"> {{totalItemText.subject | i18nReplace:{start: startItemIndex, end: endItemIndex, total: totalDataLength } | async}} </span> <span *ngIf="!pagesUnknown && totalDataLength > 1" class="cds--pagination__text cds--pagination__items-count" [ngStyle]="{'margin-left': showPageInput ? null : 0}"> {{totalItemsText.subject | i18nReplace:{start: startItemIndex, end: endItemIndex, total: totalDataLength } | async}} </span> <span *ngIf="pagesUnknown" class="cds--pagination__text cds--pagination__items-count" [ngStyle]="{'margin-left': showPageInput ? null : 0}"> {{totalItemsUnknownText.subject | i18nReplace:{start: startItemIndex, end: endItemIndex } | async}} </span> </div> <!-- right skeleton div --> <div *ngIf="skeleton" class="cds--pagination__right"> <p class="cds--skeleton__text" style="width: 70px"></p> </div> <div *ngIf="!skeleton" class="cds--pagination__right"> <span *ngIf="pagesUnknown" class="cds--pagination__text cds--pagination__page-text"> <ng-container *ngIf="!showPageInput">{{currentPage}}</ng-container> {{pageText.subject | async}} </span> <ng-container *ngIf="showPageInput"> <div class="cds--select cds--select--inline cds--select__page-number" [class.cds--select--disabled]="pageInputDisabled"> <label [for]="currentPageSelectId" class="cds--label cds--visually-hidden">{{pageText.subject | async}}</label> <input *ngIf="pageOptions.length > pageSelectThreshold" style="padding-right: 1rem; margin-right: 1rem;" [id]="currentPageSelectId" type="number" min="1" [max]="pageOptions.length" class="cds--select-input" [(ngModel)]="currentPage"> <select *ngIf="pageOptions.length <= pageSelectThreshold" [id]="currentPageSelectId" class="cds--select-input" [disabled]="pageInputDisabled" [(ngModel)]="currentPage"> <option *ngFor="let page of pageOptions; let i = index;" class="cds--select-option" [value]="i + 1">{{i + 1}}</option> </select> <svg *ngIf="pageOptions.length <= 1000" cdsIcon="chevron--down" size="16" style="display: inherit;" class="cds--select__arrow" [attr.ariaLabel]="optionsListText.subject | async"> </svg> </div> </ng-container> <span *ngIf="!pagesUnknown && lastPage <= 1" class="cds--pagination__text"> <ng-container *ngIf="!showPageInput">{{currentPage}}</ng-container> {{ofLastPageText.subject | i18nReplace: {last: lastPage} | async}} </span> <span *ngIf="!pagesUnknown && lastPage > 1" class="cds--pagination__text"> <ng-container *ngIf="!showPageInput">{{currentPage}}</ng-container> {{ofLastPagesText.subject | i18nReplace: {last: lastPage} | async}} </span> <div class="cds--pagination__control-buttons"> <button cdsButton="ghost" iconOnly="true" class="cds--pagination__button cds--pagination__button--backward" [ngClass]="{ 'cds--pagination__button--no-index': currentPage <= 1 || disabled }" tabindex="0" [attr.aria-label]="backwardText.subject | async" (click)="selectPage.emit(previousPage)" [disabled]="(currentPage <= 1 || disabled ? true : null)"> <svg cdsIcon="caret--left" size="16" class="cds--btn__icon"></svg> </button> <button cdsButton="ghost" iconOnly="true" class=" cds--pagination__button cds--pagination__button--forward" [ngClass]="{ 'cds--pagination__button--no-index': currentPage >= lastPage || disabled }" tabindex="0" [attr.aria-label]="forwardText.subject | async" (click)="selectPage.emit(nextPage)" [disabled]="(currentPage >= lastPage || disabled ? true : null)"> <svg cdsIcon="caret--right" size="16" class="cds--btn__icon"></svg> </button> </div> </div> </div> `, isInline: true, dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i4.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i4.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i4.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "directive", type: i6.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.ReplacePipe, name: "i18nReplace" }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Pagination, decorators: [{ type: Component, args: [{ selector: "cds-pagination, ibm-pagination", template: ` <div class="cds--pagination" [ngClass]="{ 'cds--skeleton': skeleton }"> <!-- left skeleton div --> <div *ngIf="skeleton" class="cds--pagination__left"> <p class="cds--skeleton__text" style="width: 70px"></p> <p class="cds--skeleton__text" style="width: 35px"></p> <p class="cds--skeleton__text" style="width: 105px"></p> </div> <div *ngIf="!skeleton" class="cds--pagination__left"> <ng-container *ngIf="showPageInput"> <label class="cds--pagination__text" [for]="itemsPerPageSelectId"> {{itemsPerPageText.subject | async}} </label> <div class="cds--select cds--select--inline cds--select__item-count" [class.cds--select--disabled]="pageInputDisabled"> <select [id]="itemsPerPageSelectId" [(ngModel)]="itemsPerPage" [disabled]="pageInputDisabled" class="cds--select-input"> <option class="cds--select-option" *ngFor="let option of itemsPerPageOptions" [value]="option"> {{ option }} </option> </select> <svg cdsIcon="chevron--down" size="16" style="display: inherit" class="cds--select__arrow" aria-hidden="true" [attr.ariaLabel]="optionsListText.subject | async"> </svg> </div> </ng-container> <span *ngIf="!pagesUnknown && totalDataLength <= 1" class="cds--pagination__text cds--pagination__items-count" [ngStyle]="{'margin-left': showPageInput ? null : 0}"> {{totalItemText.subject | i18nReplace:{start: startItemIndex, end: endItemIndex, total: totalDataLength } | async}} </span> <span *ngIf="!pagesUnknown && totalDataLength > 1" class="cds--pagination__text cds--pagination__items-count" [ngStyle]="{'margin-left': showPageInput ? null : 0}"> {{totalItemsText.subject | i18nReplace:{start: startItemIndex, end: endItemIndex, total: totalDataLength } | async}} </span> <span *ngIf="pagesUnknown" class="cds--pagination__text cds--pagination__items-count" [ngStyle]="{'margin-left': showPageInput ? null : 0}"> {{totalItemsUnknownText.subject | i18nReplace:{start: startItemIndex, end: endItemIndex } | async}} </span> </div> <!-- right skeleton div --> <div *ngIf="skeleton" class="cds--pagination__right"> <p class="cds--skeleton__text" style="width: 70px"></p> </div> <div *ngIf="!skeleton" class="cds--pagination__right"> <span *ngIf="pagesUnknown" class="cds--pagination__text cds--pagination__page-text"> <ng-container *ngIf="!showPageInput">{{currentPage}}</ng-container> {{pageText.subject | async}} </span> <ng-container *ngIf="showPageInput"> <div class="cds--select cds--select--inline cds--select__page-number" [class.cds--select--disabled]="pageInputDisabled"> <label [for]="currentPageSelectId" class="cds--label cds--visually-hidden">{{pageText.subject | async}}</label> <input *ngIf="pageOptions.length > pageSelectThreshold" style="padding-right: 1rem; margin-right: 1rem;" [id]="currentPageSelectId" type="number" min="1" [max]="pageOptions.length" class="cds--select-input" [(ngModel)]="currentPage"> <select *ngIf="pageOptions.length <= pageSelectThreshold" [id]="currentPageSelectId" class="cds--select-input" [disabled]="pageInputDisabled" [(ngModel)]="currentPage"> <option *ngFor="let page of pageOptions; let i = index;" class="cds--select-option" [value]="i + 1">{{i + 1}}</option> </select> <svg *ngIf="pageOptions.length <= 1000" cdsIcon="chevron--down" size="16" style="display: inherit;" class="cds--select__arrow" [attr.ariaLabel]="optionsListText.subject | async"> </svg> </div> </ng-container> <span *ngIf="!pagesUnknown && lastPage <= 1" class="cds--pagination__text"> <ng-container *ngIf="!showPageInput">{{currentPage}}</ng-container> {{ofLastPageText.subject | i18nReplace: {last: lastPage} | async}} </span> <span *ngIf="!pagesUnknown && lastPage > 1" class="cds--pagination__text"> <ng-container *ngIf="!showPageInput">{{currentPage}}</ng-container> {{ofLastPagesText.subject | i18nReplace: {last: lastPage} | async}} </span> <div class="cds--pagination__control-buttons"> <button cdsButton="ghost" iconOnly="true" class="cds--pagination__button cds--pagination__button--backward" [ngClass]="{ 'cds--pagination__button--no-index': currentPage <= 1 || disabled }" tabindex="0" [attr.aria-label]="backwardText.subject | async" (click)="selectPage.emit(previousPage)" [disabled]="(currentPage <= 1 || disabled ? true : null)"> <svg cdsIcon="caret--left" size="16" class="cds--btn__icon"></svg> </button> <button cdsButton="ghost" iconOnly="true" class=" cds--pagination__button cds--pagination__button--forward" [ngClass]="{ 'cds--pagination__button--no-index': currentPage >= lastPage || disabled }" tabindex="0" [attr.aria-label]="forwardText.subject | async" (click)="selectPage.emit(nextPage)" [disabled]="(currentPage >= lastPage || disabled ? true : null)"> <svg cdsIcon="caret--right" size="16" class="cds--btn__icon"></svg> </button> </div> </div> </div> ` }] }], ctorParameters: function () { return [{ type: i1.I18n }, { type: i2.ExperimentalService }]; }, propDecorators: { skeleton: [{ type: Input }], model: [{ type: Input }], disabled: [{ type: Input }], pageInputDisabled: [{ type: Input }], showPageInput: [{ type: Input }], pagesUnknown: [{ type: Input }], pageSelectThreshold: [{ type: Input }], translations: [{ type: Input }], itemsPerPageOptions: [{ type: Input }], selectPage: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdGlvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcGFnaW5hdGlvbi9wYWdpbmF0aW9uLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQ04sU0FBUyxFQUNULEtBQUssRUFDTCxNQUFNLEVBQ04sWUFBWSxFQUNaLE1BQU0sZUFBZSxDQUFDO0FBSXZCLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQzs7Ozs7Ozs7QUFjeEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5Qkc7QUErSUgsTUFBTSxPQUFPLFVBQVU7SUF3SnRCLFlBQXNCLElBQVUsRUFBWSxZQUFpQztRQUF2RCxTQUFJLEdBQUosSUFBSSxDQUFNO1FBQVksaUJBQVksR0FBWixZQUFZLENBQXFCO1FBcko3RTs7V0FFRztRQUNNLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFLMUI7O1dBRUc7UUFDTSxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQzFCOztXQUVHO1FBQ00sc0JBQWlCLEdBQUcsS0FBSyxDQUFDO1FBQ25DOztXQUVHO1FBQ00sa0JBQWEsR0FBRyxJQUFJLENBQUM7UUFDOUI7O1dBRUc7UUFDTSxpQkFBWSxHQUFHLEtBQUssQ0FBQztRQUNyQix3QkFBbUIsR0FBRyxJQUFJLENBQUM7UUFpQ3BDOzs7O1dBSUc7UUFDTSx3QkFBbUIsR0FBYSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUU5RDs7Ozs7V0FLRztRQUNPLGVBQVUsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBK0RsRCx5QkFBb0IsR0FBRyxvQ0FBb0MsVUFBVSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDMUYsd0JBQW1CLEdBQUcsa0NBQWtDLFVBQVUsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBRXZGLHFCQUFnQixHQUFHLElBQUksQ0FBQyxJ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QUFhO3NCQUFyQixLQUFLO2dCQUlHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csbUJBQW1CO3NCQUEzQixLQUFLO2dCQW1CRixZQUFZO3NCQURmLEtBQUs7Z0JBb0JHLG1CQUFtQjtzQkFBM0IsS0FBSztnQkFRSSxVQUFVO3NCQUFuQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFnaW5hdGlvbk1vZGVsIH0gZnJvbSBcIi4vcGFnaW5hdGlvbi1tb2RlbC5jbGFzc1wiO1xuaW1wb3J0IHtcblx0Q29tcG9uZW50LFxuXHRJbnB1dCxcblx0T3V0cHV0LFxuXHRFdmVudEVtaXR0ZXJcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcblxuaW1wb3J0IHsgSTE4biwgT3ZlcnJpZGFibGUgfSBmcm9tIFwiY2FyYm9uLWNvbXBvbmVudHMtYW5ndWxhci9pMThuXCI7XG5pbXBvcnQgeyBFeHBlcmltZW50YWxTZXJ2aWNlIH0gZnJvbSBcImNhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXIvZXhwZXJpbWVudGFsXCI7XG5pbXBvcnQgeyBtZXJnZSB9IGZyb20gXCJjYXJib24tY29tcG9uZW50cy1hbmd1bGFyL3V0aWxzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFnaW5hdGlvblRyYW5zbGF0aW9ucyB7XG5cdElURU1TX1BFUl9QQUdFOiBzdHJpbmc7XG5cdE9QRU5fTElTVF9PRl9PUFRJT05TOiBzdHJpbmc7XG5cdEJBQ0tXQVJEOiBzdHJpbmc7XG5cdEZPUldBUkQ6IHN0cmluZztcblx0VE9UQUxfSVRFTVNfVU5LTk9XTjogc3RyaW5nO1xuXHRUT1RBTF9JVEVNUzogc3RyaW5nO1xuXHRUT1RBTF9JVEVNOiBzdHJpbmc7XG5cdE9GX0xBU1RfUEFHRVM6IHN0cmluZztcblx0T0ZfTEFTVF9QQUdFOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVXNlIHBhZ2luYXRpb24gd2hlbiB5b3UgaGF2ZSBtdWx0aXBsZSBwYWdlcyBvZiBkYXRhIHRvIGhhbmRsZS4gR2V0IHN0YXJ0ZWQgd2l0aCBpbXBvcnRpbmcgdGhlIG1vZHVsZTpcbiAqXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBQYWdpbmF0aW9uTW9kdWxlIH0gZnJvbSAnY2FyYm9uLWNvbXBvbmVudHMtYW5ndWxhcic7XG4gKiBgYGBcbiAqXG4gKiBgYGBodG1sXG4gKlx0PGNkcy1wYWdpbmF0aW9uIFttb2RlbF09XCJtb2RlbFwiIChzZWxlY3RQYWdlKT1cInNlbGVjdFBhZ2UoJGV2ZW50KVwiPjwvY2RzLXBhZ2luYXRpb24+XG4gKiBgYGBcbiAqXG4gKiBJbiB5b3VyIGBzZWxlY3RQYWdlKClgIG1ldGhvZCBzZXQgdGhlIGBtb2RlbC5jdXJyZW50UGFnZWAgdG8gc2VsZWN0ZWQgcGFnZSwgX2FmdGVyX1xuICogeW91IGxvYWQgdGhlIHBhZ2UuXG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogc2VsZWN0UGFnZShwYWdlKSB7XG4gKiBcdC8vIC4uLiB5b3VyIGNvZGUgdG8gbG9hZCB0aGUgcGFnZSBnb2VzIGhlcmVcbiAqXG4gKiBcdHRoaXMubW9kZWwuY3VycmVudFBhZ2UgPSBwYWdlO1xuICpcbiAqIFx0Ly8gLi4uIGFueXRoaW5nIHlvdSB3YW50IHRvIGRvIGFmdGVyIHBhZ2Ugc2VsZWN0aW9uIGNoYW5nZXMgZ29lcyBoZXJlXG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBbU2VlIGRlbW9dKC4uLy4uLz9wYXRoPS9zdG9yeS9jb21wb25lbnRzLXBhZ2luYXRpb24tLWJhc2ljKVxuICovXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6IFwiY2RzLXBhZ2luYXRpb24sIGlibS1wYWdpbmF0aW9uXCIsXG5cdHRlbXBsYXRlOiBgXG5cdDxkaXZcblx0XHRjbGFzcz1cImNkcy0tcGFnaW5hdGlvblwiXG5cdFx0W25nQ2xhc3NdPVwie1xuXHRcdFx0J2Nkcy0tc2tlbGV0b24nOiBza2VsZXRvblxuXHRcdH1cIj5cblx0XHQ8IS0tIGxlZnQgc2tlbGV0b24gZGl2IC0tPlxuXHRcdDxkaXYgKm5nSWY9XCJza2VsZXRvblwiIGNsYXNzPVwiY2RzLS1wYWdpbmF0aW9uX19sZWZ0XCI+XG5cdFx0XHQ8cCBjbGFzcz1cImNkcy0tc2tlbGV0b25fX3RleHRcIiBzdHlsZT1cIndpZHRoOiA3MHB4XCI+PC9wPlxuXHRcdFx0PHAgY2xhc3M9XCJjZHMtLXNrZWxldG9uX190ZXh0XCIgc3R5bGU9XCJ3aWR0aDogMzVweFwiPjwvcD5cblx0XHRcdDxwIGNsYXNzPVwiY2RzLS1za2VsZXRvbl9fdGV4dFwiIHN0eWxlPVwid2lkdGg6IDEwNXB4XCI+PC9wPlxuXHRcdDwvZGl2PlxuXG5cdFx0PGRpdiAqbmdJZj1cIiFza2VsZXRvblwiIGNsYXNzPVwiY2RzLS1wYWdpbmF0aW9uX19sZWZ0XCI+XG5cdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwic2hvd1BhZ2VJbnB1dFwiPlxuXHRcdFx0XHQ8bGFiZWwgY2xhc3M9XCJjZHMtLXBhZ2luYXRpb25fX3RleHRcIiBbZm9yXT1cIml0ZW1zUGVyUGFnZVNlbGVjdElkXCI+XG5cdFx0XHRcdFx0e3tpdGVtc1BlclBhZ2VUZXh0LnN1YmplY3QgfCBhc3luY319XG5cdFx0XHRcdDwvbGFiZWw+XG5cdFx0XHRcdDxkaXZcblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tc2VsZWN0IGNkcy0tc2VsZWN0LS1pbmxpbmUgY2RzLS1zZWxlY3RfX2l0ZW0tY291bnRcIlxuXHRcdFx0XHRcdFtjbGFzcy5jZHMtLXNlbGVjdC0tZGlzYWJsZWRdPVwicGFnZUlucHV0RGlzYWJsZWRcIj5cblx0XHRcdFx0XHQ8c2VsZWN0XG5cdFx0XHRcdFx0XHRbaWRdPVwiaXRlbXNQZXJQYWdlU2VsZWN0SWRcIlxuXHRcdFx0XHRcdFx0WyhuZ01vZGVsKV09XCJpdGVtc1BlclBhZ2VcIlxuXHRcdFx0XHRcdFx0W2Rpc2FibGVkXT1cInBhZ2VJbnB1dERpc2FibGVkXCJcblx0XHRcdFx0XHRcdGNsYXNzPVwiY2RzLS1zZWxlY3QtaW5wdXRcIj5cblx0XHRcdFx0XHRcdDxvcHRpb25cblx0XHRcdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLXNlbGVjdC1vcHRpb25cIlxuXHRcdFx0XHRcdFx0XHQqbmdGb3I9XCJsZXQgb3B0aW9uIG9mIGl0ZW1zUGVyUGFnZU9wdGlvbnNcIlxuXHRcdFx0XHRcdFx0XHRbdmFsdWVdPVwib3B0aW9uXCI+XG5cdFx0XHRcdFx0XHRcdFx0e3sgb3B0aW9uIH19XG5cdFx0XHRcdFx0XHQ8L29wdGlvbj5cblx0XHRcdFx0XHQ8L3NlbGVjdD5cblx0XHRcdFx0XHQ8c3ZnXG5cdFx0XHRcdFx0XHRjZHNJY29uPVwiY2hldnJvbi0tZG93blwiXG5cdFx0XHRcdFx0XHRzaXplPVwiMTZcIlxuXHRcdFx0XHRcdFx0c3R5bGU9XCJkaXNwbGF5OiBpbmhlcml0XCJcblx0XHRcdFx0XHRcdGNsYXNzPVwiY2RzLS1zZWxlY3RfX2Fycm93XCJcblx0XHRcdFx0XHRcdGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG5cdFx0XHRcdFx0XHRbYXR0ci5hcmlhTGFiZWxdPVwib3B0aW9uc0xpc3RUZXh0LnN1YmplY3QgfCBhc3luY1wiPlxuXHRcdFx0XHRcdDwvc3ZnPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdDwvbmctY29udGFpbmVyPlxuXHRcdFx0PHNwYW4gKm5nSWY9XCIhcGFnZXNVbmtub3duICYmIHRvdGFsRGF0YUxlbmd0aCA8PSAxXCIgY2xhc3M9XCJjZHMtLXBhZ2luYXRpb25fX3RleHQgY2RzLS1wYWdpbmF0aW9uX19pdGVtcy1jb3VudFwiIFtuZ1N0eWxlXT1cInsnbWFyZ2luLWxlZnQnOiBzaG93UGFnZUlucHV0ID8gbnVsbCA6IDB9XCI+XG5cdFx0XHRcdHt7dG90YWxJdGVtVGV4dC5zdWJqZWN0IHwgaTE4blJlcGxhY2U6e3N0YXJ0OiBzdGFydEl0ZW1JbmRleCwgZW5kOiBlbmRJdGVtSW5kZXgsIHRvdGFsOiB0b3RhbERhdGFMZW5ndGggfSB8IGFzeW5jfX1cblx0XHRcdDwvc3Bhbj5cblx0XHRcdDxzcGFuICpuZ0lmPVwiIXBhZ2VzVW5rbm93biAmJiB0b3RhbERhdGFMZW5ndGggPiAxXCIgY2xhc3M9XCJjZHMtLXBhZ2luYXRpb25fX3RleHQgY2RzLS1wYWdpbmF0aW9uX19pdGVtcy1jb3VudFwiIFtuZ1N0eWxlXT1cInsnbWFyZ2luLWxlZnQnOiBzaG93UGFnZUlucHV0ID8gbnVsbCA6IDB9XCI+XG5cdFx0XHRcdHt7dG90YWxJdGVtc1RleHQuc3ViamVjdCB8IGkxOG5SZXBsYWNlOntzdGFydDogc3RhcnRJdGVtSW5kZXgsIGVuZDogZW5kSXRlbUluZGV4LCB0b3RhbDogdG90YWxEYXRhTGVuZ3RoIH0gfCBhc3luY319XG5cdFx0XHQ8L3NwYW4+XG5cdFx0XHQ8c3BhbiAqbmdJZj1cInBhZ2VzVW5rbm93blwiIGNsYXNzPVwiY2RzLS1wYWdpbmF0aW9uX190ZXh0IGNkcy0tcGFnaW5hdGlvbl9faXRlbXMtY291bnRcIiBbbmdTdHlsZV09XCJ7J21hcmdpbi1sZWZ0Jzogc2hvd1BhZ2VJbnB1dCA/IG51bGwgOiAwfVwiPlxuXHRcdFx0XHR7e3RvdGFsSXRlbXNVbmtub3duVGV4dC5zdWJqZWN0IHwgaTE4blJlcGxhY2U6e3N0YXJ0OiBzdGFydEl0ZW1JbmRleCwgZW5kOiBlbmRJdGVtSW5kZXggfSB8IGFzeW5jfX1cblx0XHRcdDwvc3Bhbj5cblx0XHQ8L2Rpdj5cblxuXHRcdDwhLS0gcmlnaHQgc2tlbGV0b24gZGl2IC0tPlxuXHRcdDxkaXYgKm5nSWY9XCJza2VsZXRvblwiIGNsYXNzPVwiY2RzLS1wYWdpbmF0aW9uX19yaWdodFwiPlxuXHRcdFx0PHAgY2xhc3M9XCJjZHMtLXNrZWxldG9uX190ZXh0XCIgc3R5bGU9XCJ3aWR0aDogNzBweFwiPjwvcD5cblx0XHQ8L2Rpdj5cblxuXHRcdDxkaXYgKm5nSWY9XCIhc2tlbGV0b25cIiBjbGFzcz1cImNkcy0tcGFnaW5hdGlvbl9fcmlnaHRcIj5cblx0XHRcdDxzcGFuICpuZ0lmPVwicGFnZXNVbmtub3duXCIgY2xhc3M9XCJjZHMtLXBhZ2luYXRpb25fX3RleHQgY2RzLS1wYWdpbmF0aW9uX19wYWdlLXRleHRcIj5cblx0XHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cIiFzaG93UGFnZUlucHV0XCI+e3tjdXJyZW50UGFnZX19PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdHt7cGFnZVRleHQuc3ViamVjdCB8IGFzeW5jfX1cblx0XHRcdDwvc3Bhbj5cblx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCJzaG93UGFnZUlucHV0XCI+XG5cdFx0XHRcdDxkaXZcblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tc2VsZWN0IGNkcy0tc2VsZWN0LS1pbmxpbmUgY2RzLS1zZWxlY3RfX3BhZ2UtbnVtYmVyXCJcblx0XHRcdFx0XHRbY2xhc3MuY2RzLS1zZWxlY3QtLWRpc2FibGVkXT1cInBhZ2VJbnB1dERpc2FibGVkXCI+XG5cdFx0XHRcdFx0PGxhYmVsIFtmb3JdPVwiY3VycmVudFBhZ2VTZWxlY3RJZFwiIGNsYXNzPVwiY2RzLS1sYWJlbCBjZHMtLXZpc3VhbGx5LWhpZGRlblwiPnt7cGFnZVRleHQuc3ViamVjdCB8IGFzeW5jfX08L2xhYmVsPlxuXHRcdFx0XHRcdDxpbnB1dFxuXHRcdFx0XHRcdFx0Km5nSWY9XCJwYWdlT3B0aW9ucy5sZW5ndGggPiBwYWdlU2VsZWN0VGhyZXNob2xkXCJcblx0XHRcdFx0XHRcdHN0eWxlPVwicGFkZGluZy1yaWdodDogMXJlbTsgbWFyZ2luLXJpZ2h0OiAxcmVtO1wiXG5cdFx0XHRcdFx0XHRbaWRdPVwiY3VycmVudFBhZ2VTZWxlY3RJZFwiXG5cdFx0XHRcdFx0XHR0eXBlPVwibnVtYmVyXCJcblx0XHRcdFx0XHRcdG1pbj1cIjFcIlxuXHRcdFx0XHRcdFx0W21heF09XCJwYWdlT3B0aW9ucy5sZW5ndGhcIlxuXHRcdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLXNlbGVjdC1pbnB1dFwiXG5cdFx0XHRcdFx0XHRbKG5nTW9kZWwpXT1cImN1cnJlbnRQYWdlXCI+XG5cdFx0XHRcdFx0PHNlbGVjdFxuXHRcdFx0XHRcdFx0Km5nSWY9XCJwYWdlT3B0aW9ucy5sZW5ndGggPD0gcGFnZVNlbGVjdFRocmVzaG9sZFwiXG5cdFx0XHRcdFx0XHRbaWRdPVwiY3VycmVudFBhZ2VTZWxlY3RJZFwiXG5cdFx0XHRcdFx0XHRjbGFzcz1cImNkcy0tc2VsZWN0LWlucHV0XCJcblx0XHRcdFx0XHRcdFtkaXNhYmxlZF09XCJwYWdlSW5wdXREaXNhYmxlZFwiXG5cdFx0XHRcdFx0XHRbKG5nTW9kZWwpXT1cImN1cnJlbnRQYWdlXCI+XG5cdFx0XHRcdFx0XHQ8b3B0aW9uICpuZ0Zvcj1cImxldCBwYWdlIG9mIHBhZ2VPcHRpb25zOyBsZXQgaSA9IGluZGV4O1wiIGNsYXNzPVwiY2RzLS1zZWxlY3Qtb3B0aW9uXCIgW3ZhbHVlXT1cImkgKyAxXCI+e3tpICsgMX19PC9vcHRpb24+XG5cdFx0XHRcdFx0PC9zZWxlY3Q+XG5cdFx0XHRcdFx0PHN2Z1xuXHRcdFx0XHRcdFx0Km5nSWY9XCJwYWdlT3B0aW9ucy5sZW5ndGggPD0gMTAwMFwiXG5cdFx0XHRcdFx0XHRjZHNJY29uPVwiY2hldnJvbi0tZG93blwiXG5cdFx0XHRcdFx0XHRzaXplPVwiMTZcIlxuXHRcdFx0XHRcdFx0c3R5bGU9XCJkaXNwbGF5OiBpbmhlcml0O1wiXG5cdFx0XHRcdFx0XHRjbGFzcz1cImNkcy0tc2VsZWN0X19hcnJvd1wiXG5cdFx0XHRcdFx0XHRbYXR0ci5hcmlhTGFiZWxdPVwib3B0aW9uc0xpc3RUZXh0LnN1YmplY3QgfCBhc3luY1wiPlxuXHRcdFx0XHRcdDwvc3ZnPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdDwvbmctY29udGFpbmVyPlxuXG5cdFx0XHQ8c3BhbiAqbmdJZj1cIiFwYWdlc1Vua25vd24gJiYgbGFzdFBhZ2UgPD0gMVwiIGNsYXNzPVwiY2RzLS1wYWdpbmF0aW9uX190ZXh0XCI+XG5cdFx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCIhc2hvd1BhZ2VJbnB1dFwiPnt7Y3VycmVudFBhZ2V9fTwvbmctY29udGFpbmVyPlxuXHRcdFx0XHR7e29mTGFzdFBhZ2VUZXh0LnN1YmplY3QgfCBpMThuUmVwbGFjZToge2xhc3Q6IGxhc3RQYWdlfSB8IGFzeW5jfX1cblx0XHRcdDwvc3Bhbj5cblx0XHRcdDxzcGFuICpuZ0lmPVwiIXBhZ2VzVW5rbm93biAmJiBsYXN0UGFnZSA+IDFcIiBjbGFzcz1cImNkcy0tcGFnaW5hdGlvbl9fdGV4dFwiPlxuXHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiIXNob3dQYWdlSW5wdXRcIj57e2N1cnJlbnRQYWdlfX08L25nLWNvbnRhaW5lcj5cblx0XHRcdFx0e3tvZkxhc3RQYWdlc1RleHQuc3ViamVjdCB8IGkxOG5SZXBsYWNlOiB7bGFzdDogbGFzdFBhZ2V9IHwgYXN5bmN9fVxuXHRcdFx0PC9zcGFuPlxuXHRcdFx0PGRpdiBjbGFzcz1cImNkcy0tcGFnaW5hdGlvbl9fY29udHJvbC1idXR0b25zXCI+XG5cdFx0XHRcdDxidXR0b25cblx0XHRcdFx0XHRjZHNCdXR0b249XCJnaG9zdFwiXG5cdFx0XHRcdFx0aWNvbk9ubHk9XCJ0cnVlXCJcblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tcGFnaW5hdGlvbl9fYnV0dG9uIGNkcy0tcGFnaW5hdGlvbl9fYnV0dG9uLS1iYWNrd2FyZFwiXG5cdFx0XHRcdFx0W25nQ2xhc3NdPVwie1xuXHRcdFx0XHRcdFx0J2Nkcy0tcGFnaW5hdGlvbl9fYnV0dG9uLS1uby1pbmRleCc6IGN1cnJlbnRQYWdlIDw9IDEgfHwgZGlzYWJsZWRcblx0XHRcdFx0XHR9XCJcblx0XHRcdFx0XHR0YWJpbmRleD1cIjBcIlxuXHRcdFx0XHRcdFthdHRyLmFyaWEtbGFiZWxdPVwiYmFja3dhcmRUZXh0LnN1YmplY3QgfCBhc3luY1wiXG5cdFx0XHRcdFx0KGNsaWNrKT1cInNlbGVjdFBhZ2UuZW1pdChwcmV2aW91c1BhZ2UpXCJcblx0XHRcdFx0XHRbZGlzYWJsZWRdPVwiKGN1cnJlbnRQYWdlIDw9IDEgfHwgZGlzYWJsZWQgPyB0cnVlIDogbnVsbClcIj5cblx0XHRcdFx0XHQ8c3ZnIGNkc0ljb249XCJjYXJldC0tbGVmdFwiIHNpemU9XCIxNlwiIGNsYXNzPVwiY2RzLS1idG5fX2ljb25cIj48L3N2Zz5cblx0XHRcdFx0PC9idXR0b24+XG5cblx0XHRcdFx0PGJ1dHRvblxuXHRcdFx0XHRcdGNkc0J1dHRvbj1cImdob3N0XCJcblx0XHRcdFx0XHRpY29uT25seT1cInRydWVcIlxuXHRcdFx0XHRcdGNsYXNzPVwiXG5cdFx0XHRcdFx0XHRjZHMtLXBhZ2luYXRpb25fX2J1dHRvblxuXHRcdFx0XHRcdFx0Y2RzLS1wYWdpbmF0aW9uX19idXR0b24tLWZvcndhcmRcIlxuXHRcdFx0XHRcdFtuZ0NsYXNzXT1cIntcblx0XHRcdFx0XHRcdCdjZHMtLXBhZ2luYXRpb25fX2J1dHRvbi0tbm8taW5kZXgnOiBjdXJyZW50UGFnZSA+PSBsYXN0UGFnZSB8fCBkaXNhYmxlZFxuXHRcdFx0XHRcdH1cIlxuXHRcdFx0XHRcdHRhYmluZGV4PVwiMFwiXG5cdFx0XHRcdFx0W2F0dHIuYXJpYS1sYWJlbF09XCJmb3J3YXJkVGV4dC5zdWJqZWN0IHwgYXN5bmNcIlxuXHRcdFx0XHRcdChjbGljayk9XCJzZWxlY3RQYWdlLmVtaXQobmV4dFBhZ2UpXCJcblx0XHRcdFx0XHRbZGlzYWJsZWRdPVwiKGN1cnJlbnRQYWdlID49IGxhc3RQYWdlIHx8IGRpc2FibGVkID8gdHJ1ZSA6IG51bGwpXCI+XG5cdFx0XHRcdFx0PHN2ZyBjZHNJY29uPVwiY2FyZXQtLXJpZ2h0XCIgc2l6ZT1cIjE2XCIgY2xhc3M9XCJjZHMtLWJ0bl9faWNvblwiPjwvc3ZnPlxuXHRcdFx0XHQ8L2J1dHRvbj5cblx0XHRcdDwvZGl2PlxuXHRcdDwvZGl2PlxuXHQ8L2Rpdj5cblx0YFxufSlcbmV4cG9ydCBjbGFzcyBQYWdpbmF0aW9uIHtcblx0c3RhdGljIHBhZ2luYXRpb25Db3VudGVyID0gMDtcblxuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCBmb3IgYSBsb2FkaW5nIHBhZ2luYXRpb24gY29tcG9uZW50LlxuXHQgKi9cblx0QElucHV0KCkgc2tlbGV0b24gPSBmYWxzZTtcblx0LyoqXG5cdCAqIGBQYWdpbmF0aW9uTW9kZWxgIHdpdGggdGhlIGluZm9ybWF0aW9uIGFib3V0IHBhZ2VzIHlvdSdyZSBjb250cm9sbGluZy5cblx0ICovXG5cdEBJbnB1dCgpIG1vZGVsOiBQYWdpbmF0aW9uTW9kZWw7XG5cdC8qKlxuIFx0ICogU2V0IHRvIGB0cnVlYCB0byBkaXNhYmxlIHRoZSBiYWNrd2FyZC9mb3J3YXJkIGJ1dHRvbnMuXG5cdCAqL1xuXHRASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCB0byBkaXNhYmxlIHRoZSBzZWxlY3QgYm94IHRoYXQgY2hhbmdlcyB0aGUgcGFnZS5cblx0ICovXG5cdEBJbnB1dCgpIHBhZ2VJbnB1dERpc2FibGVkID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBDb250cm9scyB3ZXRoZXIgb3Igbm90IHRvIHNob3cgdGhlIHBhZ2Ugc2VsZWN0c1xuXHQgKi9cblx0QElucHV0KCkgc2hvd1BhZ2VJbnB1dCA9IHRydWU7XG5cdC8qKlxuXHQgKiBTZXQgdG8gYHRydWVgIGlmIHRoZSB0b3RhbCBudW1iZXIgb2YgaXRlbXMgaXMgdW5rbm93bi5cblx0ICovXG5cdEBJbnB1dCgpIHBhZ2VzVW5rbm93biA9IGZhbHNlO1xuXHRASW5wdXQoKSBwYWdlU2VsZWN0VGhyZXNob2xkID0gMTAwMDtcblxuXHQvKipcblx0ICogRXhwZWN0cyBhbiBvYmplY3QgdGhhdCBjb250YWlucyBzb21lIG9yIGFsbCBvZjpcblx0ICogYGBgXG5cdCAqIHtcblx0ICpcdFx0XCJJVEVNU19QRVJfUEFHRVwiOiBcIkl0ZW1zIHBlciBwYWdlOlwiLFxuXHQgKlx0XHRcIk9QRU5fTElTVF9PRl9PUFRJT05TXCI6IFwiT3BlbiBsaXN0IG9mIG9wdGlvbnNcIixcblx0ICpcdFx0XCJCQUNLV0FSRFwiOiBcIkJhY2t3YXJkXCIsXG5cdCAqXHRcdFwiRk9SV0FSRFwiOiBcIkZvcndhcmRcIixcblx0ICpcdFx0XCJUT1RBTF9JVEVNU19VTktOT1dOXCI6IFwie3tzdGFydH19LXt7ZW5kfX0gaXRlbXNcIixcblx0ICpcdFx0XCJUT1RBTF9JVEVNU1wiOiBcInt7c3RhcnR9fS17e2VuZH19IG9mIHt7dG90YWx9fSBpdGVtc1wiLFxuXHQgKlx0XHRcIlRPVEFMX0lURU1cIjogXCJ7e3N0YXJ0fX0te3tlbmR9fSBvZiB7e3RvdGFsfX0gaXRlbVwiLFxuXHQgKlx0XHRcIk9GX0xBU1RfUEFHRVNcIjogXCJvZiB7e2xhc3R9fSBwYWdlc1wiLFxuXHQgKlx0XHRcIk9GX0xBU1RfUEFHRVwiOiBcIm9mIHt7bGFzdH19IHBhZ2VcIlxuXHQgKiB9XG5cdCAqIGBgYFxuXHQgKi9cblx0QElucHV0KClcblx0c2V0IHRyYW5zbGF0aW9ucyAodmFsdWU6IFBhZ2luYXRpb25UcmFuc2xhdGlvbnMpIHtcblx0XHRjb25zdCB2YWx1ZVdpdGhEZWZhdWx0cyA9IG1lcmdlKHRoaXMuaTE4bi5nZXRNdWx0aXBsZShcIlBBR0lOQVRJT05cIiksIHZhbHVlKTtcblx0XHR0aGlzLml0ZW1zUGVyUGFnZVRleHQub3ZlcnJpZGUodmFsdWVXaXRoRGVmYXVsdHMuSVRFTVNfUEVSX1BBR0UpO1xuXHRcdHRoaXMub3B0aW9uc0xpc3RUZXh0Lm92ZXJyaWRlKHZhbHVlV2l0aERlZmF1bHRzLk9QRU5fTElTVF9PRl9PUFRJT05TKTtcblx0XHR0aGlzLmJhY2t3YXJkVGV4dC5vdmVycmlkZSh2YWx1ZVdpdGhEZWZhdWx0cy5CQUNLV0FSRCk7XG5cdFx0dGhpcy5mb3J3YXJkVGV4dC5vdmVycmlkZSh2YWx1ZVdpdGhEZWZhdWx0cy5GT1JXQVJEKTtcblx0XHR0aGlzLnRvdGFsSXRlbXNUZXh0Lm92ZXJyaWRlKHZhbHVlV2l0aERlZmF1bHRzLlRPVEFMX0lURU1TKTtcblx0XHR0aGlzLnRvdGFsSXRlbVRleHQub3ZlcnJpZGUodmFsdWVXaXRoRGVmYXVsdHMuVE9UQUxfSVRFTSk7XG5cdFx0dGhpcy50b3RhbEl0ZW1zVW5rbm93blRleHQub3ZlcnJpZGUodmFsdWVXaXRoRGVmYXVsdHMuVE9UQUxfSVRFTVNfVU5LTk9XTik7XG5cdFx0dGhpcy5wYWdlVGV4dC5vdmVycmlkZSh2YWx1ZVdpdGhEZWZhdWx0cy5QQUdFKTtcblx0XHR0aGlzLm9mTGFzdFBhZ2VzVGV4dC5vdmVycmlkZSh2YWx1ZVdpdGhEZWZhdWx0cy5PRl9MQVNUX1BBR0VTKTtcblx0XHR0aGlzLm9mTGFzdFBhZ2VUZXh0Lm92ZXJyaWRlKHZhbHVlV2l0aERlZmF1bHRzLk9GX0xBU1RfUEFHRSk7XG5cdH1cblxuXHQvKipcblx0ICogT3B0aW9ucyBmb3IgaXRlbXMgcGVyIHBhZ2Ugc2VsZWN0XG5cdCAqXG5cdCAqIEEgZGVmYXVsdCBhcnJheSBvZiBvcHRpb25zIHdpbGwgYmUgZGVmaW5lZDogWzEwLCAyMCwgMzAsIDQwLCA1MF1cblx0ICovXG5cdEBJbnB1dCgpIGl0ZW1zUGVyUGFnZU9wdGlvbnM6IG51bWJlcltdID0gWzEwLCAyMCwgMzAsIDQwLCA1MF07XG5cblx0LyoqXG5cdCAqIEVtaXRzIHRoZSBuZXcgcGFnZSBudW1iZXIuXG5cdCAqXG5cdCAqIFlvdSBzaG91bGQgdGllIGludG8gdGhpcyBhbmQgdXBkYXRlIGBtb2RlbC5jdXJyZW50UGFnZWAgb25jZSB0aGUgZnJlc2hcblx0ICogZGF0YSBpcyBmaW5hbGx5IGxvYWRlZC5cblx0ICovXG5cdEBPdXRwdXQoKSBzZWxlY3RQYWdlID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XG5cblx0Z2V0IGl0ZW1zUGVyUGFnZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5tb2RlbC5wYWdlTGVuZ3RoO1xuXHR9XG5cdHNldCBpdGVtc1BlclBhZ2UodmFsdWUpIHtcblx0XHR0aGlzLm1vZGVsLnBhZ2VMZW5ndGggPSBOdW1iZXIodmFsdWUpO1xuXHRcdHRoaXMuY3VycmVudFBhZ2UgPSAxOyAvLyByZXNldCBwYWdlXG5cdH1cblxuXHRnZXQgY3VycmVudFBhZ2UoKSB7XG5cdFx0cmV0dXJuIHRoaXMubW9kZWwuY3VycmVudFBhZ2U7XG5cdH1cblx0c2V0IGN1cnJlbnRQYWdlKHZhbHVlKSB7XG5cdFx0dmFsdWUgPSBOdW1iZXIodmFsdWUpO1xuXHRcdC8vIGVtaXRzIHRoZSB2YWx1ZSB0byBhbGxvdyB0aGUgdXNlciB0byB1cGRhdGUgY3VycmVudCBwYWdlXG5cdFx0Ly8gaW4gdGhlIG1vZGVsIG9uY2UgdGhlIHBhZ2UgaXMgbG9hZGVkXG5cdFx0dGhpcy5zZWxlY3RQYWdlLmVtaXQodmFsdWUpO1xuXHR9XG5cblx0Z2V0IHRvdGFsRGF0YUxlbmd0aCgpIHtcblx0XHRyZXR1cm4gdGhpcy5tb2RlbC50b3RhbERhdGFMZW5ndGg7XG5cdH1cblx0LyoqXG5cdCAqIFRoZSBsYXN0IHBhZ2UgbnVtYmVyIHRvIGRpc3BsYXkgaW4gdGhlIHBhZ2luYXRpb24gdmlldy5cblx0ICovXG5cdGdldCBsYXN0UGFnZSgpOiBudW1iZXIge1xuXHRcdGNvbnN0IGxhc3QgPSBNYXRoLmNlaWwodGhpcy50b3RhbERhdGFMZW5ndGggLyB0aGlzLml0ZW1zUGVyUGFnZSk7XG5cdFx0cmV0dXJuIGxhc3QgPiAwID8gbGFzdCA6IDE7XG5cdH1cblxuXHRnZXQgc3RhcnRJdGVtSW5kZXgoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZW5kSXRlbUluZGV4ID4gMCA/ICh0aGlzLmN1cnJlbnRQYWdlIC0gMSkgKiB0aGlzLml0ZW1zUGVyUGFnZSArIDEgOiAwO1xuXHR9XG5cblx0Z2V0IGVuZEl0ZW1JbmRleCgpIHtcblx0XHRjb25zdCBwcm9qZWN0ZWRFbmRJdGVtSW5kZXggPSB0aGlzLmN1cnJlbnRQYWdlICogdGhpcy5pdGVtc1BlclBhZ2U7XG5cblx0XHRyZXR1cm4gcHJvamVjdGVkRW5kSXRlbUluZGV4IDwgdGhpcy50b3RhbERhdGFMZW5ndGggPyBwcm9qZWN0ZWRFbmRJdGVtSW5kZXggOiB0aGlzLnRvdGFsRGF0YUxlbmd0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgcHJldmlvdXMgcGFnZSBudW1iZXIgdG8gbmF2aWdhdGUgdG8sIGZyb20gdGhlIGN1cnJlbnQgcGFnZS5cblx0ICovXG5cdGdldCBwcmV2aW91c1BhZ2UoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5jdXJyZW50UGFnZSA8PSAxID8gMSA6IHRoaXMuY3VycmVudFBhZ2UgLSAxO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBuZXh0IHBhZ2UgbnVtYmVyIHRvIG5hdmlnYXRlIHRvLCBmcm9tIHRoZSBjdXJyZW50IHBhZ2UuXG5cdCAqL1xuXHRnZXQgbmV4dFBhZ2UoKTogbnVtYmVyIHtcblx0XHRjb25zdCBsYXN0UGFnZSA9IHRoaXMubGFzdFBhZ2U7XG5cdFx0cmV0dXJuIHRoaXMuY3VycmVudFBhZ2UgPj0gbGFzdFBhZ2UgPyBsYXN0UGFnZSA6IHRoaXMuY3VycmVudFBhZ2UgKyAxO1xuXHR9XG5cblx0Z2V0IHBhZ2VPcHRpb25zKCkge1xuXHRcdGlmICh0aGlzLnRvdGFsRGF0YUxlbmd0aCAmJiB0aGlzLl9wYWdlT3B0aW9ucy5sZW5ndGggIT09IHRoaXMudG90YWxEYXRhTGVuZ3RoKSB7XG5cdFx0XHR0aGlzLl9wYWdlT3B0aW9ucyA9IEFycmF5KE1hdGguY2VpbCh0aGlzLnRvdGFsRGF0YUxlbmd0aCAvIHRoaXMuaXRlbXNQZXJQYWdlKSk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLl9wYWdlT3B0aW9ucztcblx0fVxuXG5cdGl0ZW1zUGVyUGFnZVNlbGVjdElkID0gYHBhZ2luYXRpb24tc2VsZWN0LWl0ZW1zLXBlci1wYWdlLSR7UGFnaW5hdGlvbi5wYWdpbmF0aW9uQ291bnRlcn1gO1xuXHRjdXJyZW50UGFnZVNlbGVjdElkID0gYHBhZ2luYXRpb24tc2VsZWN0LWN1cnJlbnQtcGFnZS0ke1BhZ2luYXRpb24ucGFnaW5hdGlvbkNvdW50ZXJ9YDtcblxuXHRpdGVtc1BlclBhZ2VUZXh0ID0gdGhpcy5pMThuLmdldE92ZXJyaWRhYmxlKFwiUEFHSU5BVElPTi5JVEVNU19QRVJfUEFHRVwiKTtcblx0b3B0aW9uc0xpc3RUZXh0ID0gdGhpcy5pMThuLmdldE92ZXJyaWRhYmxlKFwiUEFHSU5BVElPTi5PUEVOX0xJU1RfT0ZfT1BUSU9OU1wiKTtcblx0YmFja3dhcmRUZXh0ID0gdGhpcy5pMThuLmdldE92ZXJyaWRhYmxlKFwiUEFHSU5BVElPTi5CQUNLV0FSRFwiKTtcblx0Zm9yd2FyZFRleHQgPSB0aGlzLmkxOG4uZ2V0T3ZlcnJpZGFibGUoXCJQQUdJTkFUSU9OLkZPUldBUkRcIik7XG5cdHRvdGFsSXRlbXNUZXh0ID0gdGhpcy5pMThuLmdldE92ZXJyaWRhYmxlKFwiUEFHSU5BVElPTi5UT1RBTF9JVEVNU1wiKTtcblx0dG90YWxJdGVtVGV4dCA9IHRoaXMuaTE4bi5nZXRPdmVycmlkYWJsZShcIlBBR0lOQVRJT04uVE9UQUxfSVRFTVwiKTtcblx0dG90YWxJdGVtc1Vua25vd25UZXh0ID0gdGhpcy5pMThuLmdldE92ZXJyaWRhYmxlKFwiUEFHSU5BVElPTi5UT1RBTF9JVEVNU19VTktOT1dOXCIpO1xuXHRwYWdlVGV4dCA9IHRoaXMuaTE4bi5nZXRPdmVycmlkYWJsZShcIlBBR0lOQVRJT04uUEFHRVwiKTtcblx0b2ZMYXN0UGFnZXNUZXh0ID0gdGhpcy5pMThuLmdldE92ZXJyaWRhYmxlKFwiUEFHSU5BVElPTi5PRl9MQVNUX1BBR0VTXCIpO1xuXHRvZkxhc3RQYWdlVGV4dCA9IHRoaXMuaTE4bi5nZXRPdmVycmlkYWJsZShcIlBBR0lOQVRJT04uT0ZfTEFTVF9QQUdFXCIpO1xuXG5cdHByb3RlY3RlZCBfcGFnZU9wdGlvbnMgPSBbXTtcblxuXHRjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgaTE4bjogSTE4biwgcHJvdGVjdGVkIGV4cGVyaW1lbnRhbDogRXhwZXJpbWVudGFsU2VydmljZSkge1xuXHRcdFBhZ2luYXRpb24ucGFnaW5hdGlvbkNvdW50ZXIrKztcblx0fVxufVxuIl19