ngx-bootstrap
Version:
Angular Bootstrap
257 lines • 41.1 kB
JavaScript
import { ChangeDetectorRef, Component, ElementRef, EventEmitter, forwardRef, Input, Output, TemplateRef } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { PaginationConfig } from './pagination.config';
import * as i0 from "@angular/core";
import * as i1 from "./pagination.config";
import * as i2 from "@angular/common";
export const PAGINATION_CONTROL_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => PaginationComponent),
multi: true
};
export class PaginationComponent {
constructor(elementRef, paginationConfig, changeDetection) {
this.elementRef = elementRef;
this.changeDetection = changeDetection;
/** if `true` aligns each link to the sides of pager */
this.align = true;
/** if false first and last buttons will be hidden */
this.boundaryLinks = false;
/** if false previous and next buttons will be hidden */
this.directionLinks = true;
/** if true current page will in the middle of pages list */
this.rotate = true;
// css
/** add class to <code><li\></code> */
this.pageBtnClass = '';
/** if true pagination component will be disabled */
this.disabled = false;
/** fired when total pages count changes, $event:number equals to total pages count */
this.numPages = new EventEmitter();
/** fired when page was changed, $event:{page, itemsPerPage} equals to object
* with current page index and number of items per page
*/
this.pageChanged = new EventEmitter();
this.onChange = Function.prototype;
this.onTouched = Function.prototype;
this.classMap = '';
this.inited = false;
this._itemsPerPage = 10;
this._totalItems = 0;
this._totalPages = 0;
this._page = 1;
this.elementRef = elementRef;
if (!this.config) {
this.configureOptions(paginationConfig.main);
}
}
/** maximum number of items per page. If value less than 1 will display all items on one page */
get itemsPerPage() {
return this._itemsPerPage;
}
set itemsPerPage(v) {
this._itemsPerPage = v;
this.totalPages = this.calculateTotalPages();
}
/** total number of items in all pages */
get totalItems() {
return this._totalItems;
}
set totalItems(v) {
this._totalItems = v;
this.totalPages = this.calculateTotalPages();
}
get totalPages() {
return this._totalPages;
}
set totalPages(v) {
this._totalPages = v;
this.numPages.emit(v);
if (this.inited) {
this.selectPage(this.page);
}
}
get page() {
return this._page;
}
set page(value) {
const _previous = this._page;
this._page = value > this.totalPages ? this.totalPages : value || 1;
this.changeDetection.markForCheck();
if (_previous === this._page || typeof _previous === 'undefined') {
return;
}
this.pageChanged.emit({
page: this._page,
itemsPerPage: this.itemsPerPage
});
}
configureOptions(config) {
this.config = Object.assign({}, config);
}
ngOnInit() {
if (typeof window !== 'undefined') {
this.classMap = this.elementRef.nativeElement.getAttribute('class') || '';
}
// watch for maxSize
if (typeof this.maxSize === 'undefined') {
this.maxSize = this.config?.maxSize || 0;
}
if (typeof this.rotate === 'undefined') {
this.rotate = !!this.config?.rotate;
}
if (typeof this.boundaryLinks === 'undefined') {
this.boundaryLinks = !!this.config?.boundaryLinks;
}
if (typeof this.directionLinks === 'undefined') {
this.directionLinks = !!this.config?.directionLinks;
}
if (typeof this.pageBtnClass === 'undefined') {
this.pageBtnClass = this.config?.pageBtnClass || '';
}
// base class
if (typeof this.itemsPerPage === 'undefined') {
this.itemsPerPage = this.config?.itemsPerPage || 0;
}
this.totalPages = this.calculateTotalPages();
// this class
this.pages = this.getPages(this.page, this.totalPages);
this.inited = true;
}
writeValue(value) {
this.page = value;
this.pages = this.getPages(this.page, this.totalPages);
}
getText(key) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return this[`${key}Text`] || this.config[`${key}Text`];
}
noPrevious() {
return this.page === 1;
}
noNext() {
return this.page === this.totalPages;
}
registerOnChange(fn) {
this.onChange = fn;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
selectPage(page, event) {
if (event) {
event.preventDefault();
}
if (!this.disabled) {
if (event && event.target) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const target = event.target;
target.blur();
}
this.writeValue(page);
this.onChange(this.page);
}
}
// Create page object used in template
makePage(num, text, active) {
return { text, number: num, active };
}
getPages(currentPage, totalPages) {
const pages = [];
// Default page limits
let startPage = 1;
let endPage = totalPages;
const isMaxSized = typeof this.maxSize !== 'undefined' && this.maxSize < totalPages;
// recompute if maxSize
if (isMaxSized && this.maxSize) {
if (this.rotate) {
// Current page is displayed in the middle of the visible ones
startPage = Math.max(currentPage - Math.floor(this.maxSize / 2), 1);
endPage = startPage + this.maxSize - 1;
// Adjust if limit is exceeded
if (endPage > totalPages) {
endPage = totalPages;
startPage = endPage - this.maxSize + 1;
}
}
else {
// Visible pages are paginated with maxSize
startPage =
(Math.ceil(currentPage / this.maxSize) - 1) * this.maxSize + 1;
// Adjust last page if limit is exceeded
endPage = Math.min(startPage + this.maxSize - 1, totalPages);
}
}
// Add page number links
for (let num = startPage; num <= endPage; num++) {
const page = this.makePage(num, num.toString(), num === currentPage);
pages.push(page);
}
// Add links to move between page sets
if (isMaxSized && !this.rotate) {
if (startPage > 1) {
const previousPageSet = this.makePage(startPage - 1, '...', false);
pages.unshift(previousPageSet);
}
if (endPage < totalPages) {
const nextPageSet = this.makePage(endPage + 1, '...', false);
pages.push(nextPageSet);
}
}
return pages;
}
// base class
calculateTotalPages() {
const totalPages = this.itemsPerPage < 1
? 1
: Math.ceil(this.totalItems / this.itemsPerPage);
return Math.max(totalPages || 0, 1);
}
}
PaginationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: PaginationComponent, deps: [{ token: i0.ElementRef }, { token: i1.PaginationConfig }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
PaginationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: PaginationComponent, selector: "pagination", inputs: { align: "align", maxSize: "maxSize", boundaryLinks: "boundaryLinks", directionLinks: "directionLinks", firstText: "firstText", previousText: "previousText", nextText: "nextText", lastText: "lastText", rotate: "rotate", pageBtnClass: "pageBtnClass", disabled: "disabled", customPageTemplate: "customPageTemplate", customNextTemplate: "customNextTemplate", customPreviousTemplate: "customPreviousTemplate", customFirstTemplate: "customFirstTemplate", customLastTemplate: "customLastTemplate", itemsPerPage: "itemsPerPage", totalItems: "totalItems" }, outputs: { numPages: "numPages", pageChanged: "pageChanged" }, providers: [PAGINATION_CONTROL_VALUE_ACCESSOR], ngImport: i0, template: "<ul class=\"pagination\" [ngClass]=\"classMap\">\n <li class=\"pagination-first page-item\"\n *ngIf=\"boundaryLinks\"\n [class.disabled]=\"noPrevious() || disabled\">\n <a class=\"page-link\" href (click)=\"selectPage(1, $event)\">\n <ng-container [ngTemplateOutlet]=\"customFirstTemplate || defaultFirstTemplate\"\n [ngTemplateOutletContext]=\"{disabled: noPrevious() || disabled, currentPage: page}\">\n </ng-container>\n </a>\n </li>\n\n <li class=\"pagination-prev page-item\"\n *ngIf=\"directionLinks\"\n [class.disabled]=\"noPrevious() || disabled\">\n <a class=\"page-link\" href (click)=\"selectPage(page - 1, $event)\">\n <ng-container [ngTemplateOutlet]=\"customPreviousTemplate || defaultPreviousTemplate\"\n [ngTemplateOutletContext]=\"{disabled: noPrevious() || disabled, currentPage: page}\">\n </ng-container>\n </a>\n </li>\n\n <li *ngFor=\"let pg of pages\"\n [class.active]=\"pg.active\"\n [class.disabled]=\"disabled && !pg.active\"\n class=\"pagination-page page-item\">\n <a class=\"page-link\" href (click)=\"selectPage(pg.number, $event)\">\n <ng-container [ngTemplateOutlet]=\"customPageTemplate || defaultPageTemplate\"\n [ngTemplateOutletContext]=\"{disabled: disabled, $implicit: pg, currentPage: page}\">\n </ng-container>\n </a>\n </li>\n\n <li class=\"pagination-next page-item\"\n *ngIf=\"directionLinks\"\n [class.disabled]=\"noNext() || disabled\">\n <a class=\"page-link\" href (click)=\"selectPage(page + 1, $event)\">\n <ng-container [ngTemplateOutlet]=\"customNextTemplate || defaultNextTemplate\"\n [ngTemplateOutletContext]=\"{disabled: noNext() || disabled, currentPage: page}\">\n </ng-container>\n </a>\n </li>\n\n <li class=\"pagination-last page-item\"\n *ngIf=\"boundaryLinks\"\n [class.disabled]=\"noNext() || disabled\">\n <a class=\"page-link\" href (click)=\"selectPage(totalPages, $event)\">\n <ng-container [ngTemplateOutlet]=\"customLastTemplate || defaultLastTemplate\"\n [ngTemplateOutletContext]=\"{disabled: noNext() || disabled, currentPage: page}\">\n </ng-container>\n </a>\n </li>\n</ul>\n\n<ng-template #defaultPageTemplate let-page>{{ page.text }}</ng-template>\n\n<ng-template #defaultNextTemplate>{{ getText('next') }}</ng-template>\n\n<ng-template #defaultPreviousTemplate>{{ getText('previous') }}</ng-template>\n\n<ng-template #defaultFirstTemplate>{{ getText('first') }}</ng-template>\n\n<ng-template #defaultLastTemplate>{{ getText('last') }}</ng-template>\n", dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: PaginationComponent, decorators: [{
type: Component,
args: [{ selector: 'pagination', providers: [PAGINATION_CONTROL_VALUE_ACCESSOR], template: "<ul class=\"pagination\" [ngClass]=\"classMap\">\n <li class=\"pagination-first page-item\"\n *ngIf=\"boundaryLinks\"\n [class.disabled]=\"noPrevious() || disabled\">\n <a class=\"page-link\" href (click)=\"selectPage(1, $event)\">\n <ng-container [ngTemplateOutlet]=\"customFirstTemplate || defaultFirstTemplate\"\n [ngTemplateOutletContext]=\"{disabled: noPrevious() || disabled, currentPage: page}\">\n </ng-container>\n </a>\n </li>\n\n <li class=\"pagination-prev page-item\"\n *ngIf=\"directionLinks\"\n [class.disabled]=\"noPrevious() || disabled\">\n <a class=\"page-link\" href (click)=\"selectPage(page - 1, $event)\">\n <ng-container [ngTemplateOutlet]=\"customPreviousTemplate || defaultPreviousTemplate\"\n [ngTemplateOutletContext]=\"{disabled: noPrevious() || disabled, currentPage: page}\">\n </ng-container>\n </a>\n </li>\n\n <li *ngFor=\"let pg of pages\"\n [class.active]=\"pg.active\"\n [class.disabled]=\"disabled && !pg.active\"\n class=\"pagination-page page-item\">\n <a class=\"page-link\" href (click)=\"selectPage(pg.number, $event)\">\n <ng-container [ngTemplateOutlet]=\"customPageTemplate || defaultPageTemplate\"\n [ngTemplateOutletContext]=\"{disabled: disabled, $implicit: pg, currentPage: page}\">\n </ng-container>\n </a>\n </li>\n\n <li class=\"pagination-next page-item\"\n *ngIf=\"directionLinks\"\n [class.disabled]=\"noNext() || disabled\">\n <a class=\"page-link\" href (click)=\"selectPage(page + 1, $event)\">\n <ng-container [ngTemplateOutlet]=\"customNextTemplate || defaultNextTemplate\"\n [ngTemplateOutletContext]=\"{disabled: noNext() || disabled, currentPage: page}\">\n </ng-container>\n </a>\n </li>\n\n <li class=\"pagination-last page-item\"\n *ngIf=\"boundaryLinks\"\n [class.disabled]=\"noNext() || disabled\">\n <a class=\"page-link\" href (click)=\"selectPage(totalPages, $event)\">\n <ng-container [ngTemplateOutlet]=\"customLastTemplate || defaultLastTemplate\"\n [ngTemplateOutletContext]=\"{disabled: noNext() || disabled, currentPage: page}\">\n </ng-container>\n </a>\n </li>\n</ul>\n\n<ng-template #defaultPageTemplate let-page>{{ page.text }}</ng-template>\n\n<ng-template #defaultNextTemplate>{{ getText('next') }}</ng-template>\n\n<ng-template #defaultPreviousTemplate>{{ getText('previous') }}</ng-template>\n\n<ng-template #defaultFirstTemplate>{{ getText('first') }}</ng-template>\n\n<ng-template #defaultLastTemplate>{{ getText('last') }}</ng-template>\n" }]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.PaginationConfig }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { align: [{
type: Input
}], maxSize: [{
type: Input
}], boundaryLinks: [{
type: Input
}], directionLinks: [{
type: Input
}], firstText: [{
type: Input
}], previousText: [{
type: Input
}], nextText: [{
type: Input
}], lastText: [{
type: Input
}], rotate: [{
type: Input
}], pageBtnClass: [{
type: Input
}], disabled: [{
type: Input
}], customPageTemplate: [{
type: Input
}], customNextTemplate: [{
type: Input
}], customPreviousTemplate: [{
type: Input
}], customFirstTemplate: [{
type: Input
}], customLastTemplate: [{
type: Input
}], numPages: [{
type: Output
}], pageChanged: [{
type: Output
}], itemsPerPage: [{
type: Input
}], totalItems: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdGlvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvcGFnaW5hdGlvbi9wYWdpbmF0aW9uLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uL3NyYy9wYWdpbmF0aW9uL3BhZ2luYXRpb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixVQUFVLEVBQ1YsS0FBSyxFQUVMLE1BQU0sRUFFTixXQUFXLEVBQ1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUF3QixpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBR3pFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDOzs7O0FBT3ZELE1BQU0sQ0FBQyxNQUFNLGlDQUFpQyxHQUFhO0lBQ3pELE9BQU8sRUFBRSxpQkFBaUI7SUFDMUIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQztJQUNsRCxLQUFLLEVBQUUsSUFBSTtDQUNaLENBQUM7QUFPRixNQUFNLE9BQU8sbUJBQW1CO0lBaUQ5QixZQUNVLFVBQXNCLEVBQzlCLGdCQUFrQyxFQUMxQixlQUFrQztRQUZsQyxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBRXRCLG9CQUFlLEdBQWYsZUFBZSxDQUFtQjtRQWxENUMsdURBQXVEO1FBQzlDLFVBQUssR0FBRyxJQUFJLENBQUM7UUFHdEIscURBQXFEO1FBQzVDLGtCQUFhLEdBQUcsS0FBSyxDQUFDO1FBQy9CLHdEQUF3RDtRQUMvQyxtQkFBYyxHQUFHLElBQUksQ0FBQztRQVUvQiw0REFBNEQ7UUFDbkQsV0FBTSxHQUFHLElBQUksQ0FBQztRQUN2QixNQUFNO1FBQ04sc0NBQXNDO1FBQzdCLGlCQUFZLEdBQUcsRUFBRSxDQUFDO1FBQzNCLG9EQUFvRDtRQUMzQyxh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b21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgZm9yd2FyZFJlZixcbiAgSW5wdXQsXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBQcm92aWRlcixcbiAgVGVtcGxhdGVSZWZcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBDb25maWdNb2RlbCwgUGFnZXNNb2RlbCwgUGFnaW5hdGlvbkxpbmtDb250ZXh0LCBQYWdpbmF0aW9uTnVtYmVyTGlua0NvbnRleHQgfSBmcm9tICcuL21vZGVscyc7XG5cbmltcG9ydCB7IFBhZ2luYXRpb25Db25maWcgfSBmcm9tICcuL3BhZ2luYXRpb24uY29uZmlnJztcblxuZXhwb3J0IGludGVyZmFjZSBQYWdlQ2hhbmdlZEV2ZW50IHtcbiAgaXRlbXNQZXJQYWdlOiBudW1iZXI7XG4gIHBhZ2U6IG51bWJlcjtcbn1cblxuZXhwb3J0IGNvbnN0IFBBR0lOQVRJT05fQ09OVFJPTF9WQUxVRV9BQ0NFU1NPUjogUHJvdmlkZXIgPSB7XG4gIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBQYWdpbmF0aW9uQ29tcG9uZW50KSxcbiAgbXVsdGk6IHRydWVcbn07XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3BhZ2luYXRpb24nLFxuICB0ZW1wbGF0ZVVybDogJy4vcGFnaW5hdGlvbi5jb21wb25lbnQuaHRtbCcsXG4gIHByb3ZpZGVyczogW1BBR0lOQVRJT05fQ09OVFJPTF9WQUxVRV9BQ0NFU1NPUl1cbn0pXG5leHBvcnQgY2xhc3MgUGFnaW5hdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBPbkluaXQge1xuICBjb25maWc/OiBQYXJ0aWFsPENvbmZpZ01vZGVsPjtcbiAgLyoqIGlmIGB0cnVlYCBhbGlnbnMgZWFjaCBsaW5rIHRvIHRoZSBzaWRlcyBvZiBwYWdlciAqL1xuICBASW5wdXQoKSBhbGlnbiA9IHRydWU7XG4gIC8qKiBsaW1pdCBudW1iZXIgZm9yIHBhZ2UgbGlua3MgaW4gcGFnZXIgKi9cbiAgQElucHV0KCkgbWF4U2l6ZT86IG51bWJlcjtcbiAgLyoqIGlmIGZhbHNlIGZpcnN0IGFuZCBsYXN0IGJ1dHRvbnMgd2lsbCBiZSBoaWRkZW4gKi9cbiAgQElucHV0KCkgYm91bmRhcnlMaW5rcyA9IGZhbHNlO1xuICAvKiogaWYgZmFsc2UgcHJldmlvdXMgYW5kIG5leHQgYnV0dG9ucyB3aWxsIGJlIGhpZGRlbiAqL1xuICBASW5wdXQoKSBkaXJlY3Rpb25MaW5rcyA9IHRydWU7XG4gIC8vIGxhYmVsc1xuICAvKiogZmlyc3QgYnV0dG9uIHRleHQgKi9cbiAgQElucHV0KCkgZmlyc3RUZXh0Pzogc3RyaW5nO1xuICAvKiogcHJldmlvdXMgYnV0dG9uIHRleHQgKi9cbiAgQElucHV0KCkgcHJldmlvdXNUZXh0Pzogc3RyaW5nO1xuICAvKiogbmV4dCBidXR0b24gdGV4dCAqL1xuICBASW5wdXQoKSBuZXh0VGV4dD86IHN0cmluZztcbiAgLyoqIGxhc3QgYnV0dG9uIHRleHQgKi9cbiAgQElucHV0KCkgbGFzdFRleHQ/OiBzdHJpbmc7XG4gIC8qKiBpZiB0cnVlIGN1cnJlbnQgcGFnZSB3aWxsIGluIHRoZSBtaWRkbGUgb2YgcGFnZXMgbGlzdCAqL1xuICBASW5wdXQoKSByb3RhdGUgPSB0cnVlO1xuICAvLyBjc3NcbiAgLyoqIGFkZCBjbGFzcyB0byA8Y29kZT48bGlcXD48L2NvZGU+ICovXG4gIEBJbnB1dCgpIHBhZ2VCdG5DbGFzcyA9ICcnO1xuICAvKiogaWYgdHJ1ZSBwYWdpbmF0aW9uIGNvbXBvbmVudCB3aWxsIGJlIGRpc2FibGVkICovXG4gIEBJbnB1dCgpIGRpc2FibGVkID0gZmFsc2U7XG4gIC8qKiBjdXN0b20gdGVtcGxhdGUgZm9yIHBhZ2UgbGluayAqL1xuICBASW5wdXQoKSBjdXN0b21QYWdlVGVtcGxhdGU/OiBUZW1wbGF0ZVJlZjxQYWdpbmF0aW9uTnVtYmVyTGlua0NvbnRleHQ+O1xuICAvKiogY3VzdG9tIHRlbXBsYXRlIGZvciBuZXh0IGxpbmsgKi9cbiAgQElucHV0KCkgY3VzdG9tTmV4dFRlbXBsYXRlPzogVGVtcGxhdGVSZWY8UGFnaW5hdGlvbkxpbmtDb250ZXh0PjtcbiAgLyoqIGN1c3RvbSB0ZW1wbGF0ZSBmb3IgcHJldmlvdXMgbGluayAqL1xuICBASW5wdXQoKSBjdXN0b21QcmV2aW91c1RlbXBsYXRlPzogVGVtcGxhdGVSZWY8UGFnaW5hdGlvbkxpbmtDb250ZXh0PjtcbiAgLyoqIGN1c3RvbSB0ZW1wbGF0ZSBmb3IgZmlyc3QgbGluayAqL1xuICBASW5wdXQoKSBjdXN0b21GaXJzdFRlbXBsYXRlPzogVGVtcGxhdGVSZWY8UGFnaW5hdGlvbkxpbmtDb250ZXh0PjtcbiAgLyoqIGN1c3RvbSB0ZW1wbGF0ZSBmb3IgbGFzdCBsaW5rICovXG4gIEBJbnB1dCgpIGN1c3RvbUxhc3RUZW1wbGF0ZT86IFRlbXBsYXRlUmVmPFBhZ2luYXRpb25MaW5rQ29udGV4dD47XG5cbiAgLyoqIGZpcmVkIHdoZW4gdG90YWwgcGFnZXMgY291bnQgY2hhbmdlcywgJGV2ZW50Om51bWJlciBlcXVhbHMgdG8gdG90YWwgcGFnZXMgY291bnQgKi9cbiAgQE91dHB1dCgpIG51bVBhZ2VzID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XG4gIC8qKiBmaXJlZCB3aGVuIHBhZ2Ugd2FzIGNoYW5nZWQsICRldmVudDp7cGFnZSwgaXRlbXNQZXJQYWdlfSBlcXVhbHMgdG8gb2JqZWN0XG4gICAqIHdpdGggY3VycmVudCBwYWdlIGluZGV4IGFuZCBudW1iZXIgb2YgaXRlbXMgcGVyIHBhZ2VcbiAgICovXG4gIEBPdXRwdXQoKSBwYWdlQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8UGFnZUNoYW5nZWRFdmVudD4oKTtcbiAgb25DaGFuZ2UgPSBGdW5jdGlvbi5wcm90b3R5cGU7XG4gIG9uVG91Y2hlZCA9IEZ1bmN0aW9uLnByb3RvdHlwZTtcbiAgY2xhc3NNYXAgPSAnJztcbiAgcGFnZXM/OiBQYWdlc01vZGVsW107XG4gIHByb3RlY3RlZCBpbml0ZWQgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXG4gICAgcGFnaW5hdGlvbkNvbmZpZzogUGFnaW5hdGlvbkNvbmZpZyxcbiAgICBwcml2YXRlIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0b3JSZWZcbiAgKSB7XG4gICAgdGhpcy5lbGVtZW50UmVmID0gZWxlbWVudFJlZjtcbiAgICBpZiAoIXRoaXMuY29uZmlnKSB7XG4gICAgICB0aGlzLmNvbmZpZ3VyZU9wdGlvbnMocGFnaW5hdGlvbkNvbmZpZy5tYWluKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgX2l0ZW1zUGVyUGFnZSA9IDEwO1xuXG4gIC8qKiBtYXhpbXVtIG51bWJlciBvZiBpdGVtcyBwZXIgcGFnZS4gSWYgdmFsdWUgbGVzcyB0aGFuIDEgd2lsbCBkaXNwbGF5IGFsbCBpdGVtcyBvbiBvbmUgcGFnZSAqL1xuICBASW5wdXQoKVxuICBnZXQgaXRlbXNQZXJQYWdlKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX2l0ZW1zUGVyUGFnZTtcbiAgfVxuXG4gIHNldCBpdGVtc1BlclBhZ2UodjogbnVtYmVyKSB7XG4gICAgdGhpcy5faXRlbXNQZXJQYWdlID0gdjtcbiAgICB0aGlzLnRvdGFsUGFnZXMgPSB0aGlzLmNhbGN1bGF0ZVRvdGFsUGFnZXMoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBfdG90YWxJdGVtcyA9IDA7XG5cbiAgLyoqIHRvdGFsIG51bWJlciBvZiBpdGVtcyBpbiBhbGwgcGFnZXMgKi9cbiAgQElucHV0KClcbiAgZ2V0IHRvdGFsSXRlbXMoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fdG90YWxJdGVtcztcbiAgfVxuXG4gIHNldCB0b3RhbEl0ZW1zKHY6IG51bWJlcikge1xuICAgIHRoaXMuX3RvdGFsSXRlbXMgPSB2O1xuICAgIHRoaXMudG90YWxQYWdlcyA9IHRoaXMuY2FsY3VsYXRlVG90YWxQYWdlcygpO1xuICB9XG5cbiAgcHJvdGVjdGVkIF90b3RhbFBhZ2VzID0gMDtcblxuICBnZXQgdG90YWxQYWdlcygpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl90b3RhbFBhZ2VzO1xuICB9XG5cbiAgc2V0IHRvdGFsUGFnZXModjogbnVtYmVyKSB7XG4gICAgdGhpcy5fdG90YWxQYWdlcyA9IHY7XG4gICAgdGhpcy5udW1QYWdlcy5lbWl0KHYpO1xuICAgIGlmICh0aGlzLmluaXRlZCkge1xuICAgICAgdGhpcy5zZWxlY3RQYWdlKHRoaXMucGFnZSk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIF9wYWdlID0gMTtcblxuICBnZXQgcGFnZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9wYWdlO1xuICB9XG5cbiAgc2V0IHBhZ2UodmFsdWU6IG51bWJlcikge1xuICAgIGNvbnN0IF9wcmV2aW91cyA9IHRoaXMuX3BhZ2U7XG4gICAgdGhpcy5fcGFnZSA9IHZhbHVlID4gdGhpcy50b3RhbFBhZ2VzID8gdGhpcy50b3RhbFBhZ2VzIDogdmFsdWUgfHwgMTtcbiAgICB0aGlzLmNoYW5nZURldGVjdGlvbi5tYXJrRm9yQ2hlY2soKTtcblxuICAgIGlmIChfcHJldmlvdXMgPT09IHRoaXMuX3BhZ2UgfHwgdHlwZW9mIF9wcmV2aW91cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnBhZ2VDaGFuZ2VkLmVtaXQoe1xuICAgICAgcGFnZTogdGhpcy5fcGFnZSxcbiAgICAgIGl0ZW1zUGVyUGFnZTogdGhpcy5pdGVtc1BlclBhZ2VcbiAgICB9KTtcbiAgfVxuXG4gIGNvbmZpZ3VyZU9wdGlvbnMoY29uZmlnOiBQYXJ0aWFsPENvbmZpZ01vZGVsPik6IHZvaWQge1xuICAgIHRoaXMuY29uZmlnID0gT2JqZWN0LmFzc2lnbih7fSwgY29uZmlnKTtcbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy5jbGFzc01hcCA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmdldEF0dHJpYnV0ZSgnY2xhc3MnKSB8fCAnJztcbiAgICB9XG5cbiAgICAvLyB3YXRjaCBmb3IgbWF4U2l6ZVxuICAgIGlmICh0eXBlb2YgdGhpcy5tYXhTaXplID09PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy5tYXhTaXplID0gdGhpcy5jb25maWc/Lm1heFNpemUgfHwgMDtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIHRoaXMucm90YXRlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy5yb3RhdGUgPSAhIXRoaXMuY29uZmlnPy5yb3RhdGU7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiB0aGlzLmJvdW5kYXJ5TGlua3MgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLmJvdW5kYXJ5TGlua3MgPSAhIXRoaXMuY29uZmlnPy5ib3VuZGFyeUxpbmtzO1xuICAgIH1cblxuXG4gICAgaWYgKHR5cGVvZiB0aGlzLmRpcmVjdGlvbkxpbmtzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy5kaXJlY3Rpb25MaW5rcyA9ICEhdGhpcy5jb25maWc/LmRpcmVjdGlvbkxpbmtzO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgdGhpcy5wYWdlQnRuQ2xhc3MgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLnBhZ2VCdG5DbGFzcyA9IHRoaXMuY29uZmlnPy5wYWdlQnRuQ2xhc3MgfHwgJyc7XG4gICAgfVxuXG4gICAgLy8gYmFzZSBjbGFzc1xuICAgIGlmICh0eXBlb2YgdGhpcy5pdGVtc1BlclBhZ2UgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLml0ZW1zUGVyUGFnZSA9IHRoaXMuY29uZmlnPy5pdGVtc1BlclBhZ2UgfHwgMDtcbiAgICB9XG5cbiAgICB0aGlzLnRvdGFsUGFnZXMgPSB0aGlzLmNhbGN1bGF0ZVRvdGFsUGFnZXMoKTtcbiAgICAvLyB0aGlzIGNsYXNzXG4gICAgdGhpcy5wYWdlcyA9IHRoaXMuZ2V0UGFnZXModGhpcy5wYWdlLCB0aGlzLnRvdGFsUGFnZXMpO1xuICAgIHRoaXMuaW5pdGVkID0gdHJ1ZTtcbiAgfVxuXG4gIHdyaXRlVmFsdWUodmFsdWU6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMucGFnZSA9IHZhbHVlO1xuICAgIHRoaXMucGFnZXMgPSB0aGlzLmdldFBhZ2VzKHRoaXMucGFnZSwgdGhpcy50b3RhbFBhZ2VzKTtcbiAgfVxuXG4gIGdldFRleHQoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgcmV0dXJuICh0aGlzIGFzIGFueSlbYCR7a2V5fVRleHRgXSB8fCAodGhpcyBhcyBhbnkpLmNvbmZpZ1tgJHtrZXl9VGV4dGBdO1xuICB9XG5cbiAgbm9QcmV2aW91cygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5wYWdlID09PSAxO1xuICB9XG5cbiAgbm9OZXh0KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnBhZ2UgPT09IHRoaXMudG90YWxQYWdlcztcbiAgfVxuXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLm9uQ2hhbmdlID0gZm47XG4gIH1cblxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogKCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMub25Ub3VjaGVkID0gZm47XG4gIH1cblxuICBzZWxlY3RQYWdlKHBhZ2U6IG51bWJlciwgZXZlbnQ/OiBFdmVudCk6IHZvaWQge1xuICAgIGlmIChldmVudCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuZGlzYWJsZWQpIHtcbiAgICAgIGlmIChldmVudCAmJiBldmVudC50YXJnZXQpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgY29uc3QgdGFyZ2V0OiBhbnkgPSBldmVudC50YXJnZXQ7XG4gICAgICAgIHRhcmdldC5ibHVyKCk7XG4gICAgICB9XG4gICAgICB0aGlzLndyaXRlVmFsdWUocGFnZSk7XG4gICAgICB0aGlzLm9uQ2hhbmdlKHRoaXMucGFnZSk7XG4gICAgfVxuICB9XG5cbiAgLy8gQ3JlYXRlIHBhZ2Ugb2JqZWN0IHVzZWQgaW4gdGVtcGxhdGVcbiAgcHJvdGVjdGVkIG1ha2VQYWdlKFxuICAgIG51bTogbnVtYmVyLFxuICAgIHRleHQ6IHN0cmluZyxcbiAgICBhY3RpdmU6IGJvb2xlYW5cbiAgKTogeyBudW1iZXI6IG51bWJlcjsgdGV4dDogc3RyaW5nOyBhY3RpdmU6IGJvb2xlYW4gfSB7XG4gICAgcmV0dXJuIHsgdGV4dCwgbnVtYmVyOiBudW0sIGFjdGl2ZSB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldFBhZ2VzKGN1cnJlbnRQYWdlOiBudW1iZXIsIHRvdGFsUGFnZXM6IG51bWJlcik6IFBhZ2VzTW9kZWxbXSB7XG4gICAgY29uc3QgcGFnZXM6IFBhZ2VzTW9kZWxbXSA9IFtdO1xuXG4gICAgLy8gRGVmYXVsdCBwYWdlIGxpbWl0c1xuICAgIGxldCBzdGFydFBhZ2UgPSAxO1xuICAgIGxldCBlbmRQYWdlID0gdG90YWxQYWdlcztcbiAgICBjb25zdCBpc01heFNpemVkID1cbiAgICAgIHR5cGVvZiB0aGlzLm1heFNpemUgIT09ICd1bmRlZmluZWQnICYmIHRoaXMubWF4U2l6ZSA8IHRvdGFsUGFnZXM7XG5cbiAgICAvLyByZWNvbXB1dGUgaWYgbWF4U2l6ZVxuICAgIGlmIChpc01heFNpemVkICYmIHRoaXMubWF4U2l6ZSkge1xuICAgICAgaWYgKHRoaXMucm90YXRlKSB7XG4gICAgICAgIC8vIEN1cnJlbnQgcGFnZSBpcyBkaXNwbGF5ZWQgaW4gdGhlIG1pZGRsZSBvZiB0aGUgdmlzaWJsZSBvbmVzXG4gICAgICAgIHN0YXJ0UGFnZSA9IE1hdGgubWF4KGN1cnJlbnRQYWdlIC0gTWF0aC5mbG9vcih0aGlzLm1heFNpemUgLyAyKSwgMSk7XG4gICAgICAgIGVuZFBhZ2UgPSBzdGFydFBhZ2UgKyB0aGlzLm1heFNpemUgLSAxO1xuXG4gICAgICAgIC8vIEFkanVzdCBpZiBsaW1pdCBpcyBleGNlZWRlZFxuICAgICAgICBpZiAoZW5kUGFnZSA+IHRvdGFsUGFnZXMpIHtcbiAgICAgICAgICBlbmRQYWdlID0gdG90YWxQYWdlcztcbiAgICAgICAgICBzdGFydFBhZ2UgPSBlbmRQYWdlIC0gdGhpcy5tYXhTaXplICsgMTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVmlzaWJsZSBwYWdlcyBhcmUgcGFnaW5hdGVkIHdpdGggbWF4U2l6ZVxuICAgICAgICBzdGFydFBhZ2UgPVxuICAgICAgICAgIChNYXRoLmNlaWwoY3VycmVudFBhZ2UgLyB0aGlzLm1heFNpemUpIC0gMSkgKiB0aGlzLm1heFNpemUgKyAxO1xuXG4gICAgICAgIC8vIEFkanVzdCBsYXN0IHBhZ2UgaWYgbGltaXQgaXMgZXhjZWVkZWRcbiAgICAgICAgZW5kUGFnZSA9IE1hdGgubWluKHN0YXJ0UGFnZSArIHRoaXMubWF4U2l6ZSAtIDEsIHRvdGFsUGFnZXMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFkZCBwYWdlIG51bWJlciBsaW5rc1xuICAgIGZvciAobGV0IG51bSA9IHN0YXJ0UGFnZTsgbnVtIDw9IGVuZFBhZ2U7IG51bSsrKSB7XG4gICAgICBjb25zdCBwYWdlID0gdGhpcy5tYWtlUGFnZShudW0sIG51bS50b1N0cmluZygpLCBudW0gPT09IGN1cnJlbnRQYWdlKTtcbiAgICAgIHBhZ2VzLnB1c2gocGFnZSk7XG4gICAgfVxuXG4gICAgLy8gQWRkIGxpbmtzIHRvIG1vdmUgYmV0d2VlbiBwYWdlIHNldHNcbiAgICBpZiAoaXNNYXhTaXplZCAmJiAhdGhpcy5yb3RhdGUpIHtcbiAgICAgIGlmIChzdGFydFBhZ2UgPiAxKSB7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzUGFnZVNldCA9IHRoaXMubWFrZVBhZ2Uoc3RhcnRQYWdlIC0gMSwgJy4uLicsIGZhbHNlKTtcbiAgICAgICAgcGFnZXMudW5zaGlmdChwcmV2aW91c1BhZ2VTZXQpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZW5kUGFnZSA8IHRvdGFsUGFnZXMpIHtcbiAgICAgICAgY29uc3QgbmV4dFBhZ2VTZXQgPSB0aGlzLm1ha2VQYWdlKGVuZFBhZ2UgKyAxLCAnLi4uJywgZmFsc2UpO1xuICAgICAgICBwYWdlcy5wdXNoKG5leHRQYWdlU2V0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcGFnZXM7XG4gIH1cblxuICAvLyBiYXNlIGNsYXNzXG4gIHByb3RlY3RlZCBjYWxjdWxhdGVUb3RhbFBhZ2VzKCk6IG51bWJlciB7XG4gICAgY29uc3QgdG90YWxQYWdlcyA9XG4gICAgICB0aGlzLml0ZW1zUGVyUGFnZSA8IDFcbiAgICAgICAgPyAxXG4gICAgICAgIDogTWF0aC5jZWlsKHRoaXMudG90YWxJdGVtcyAvIHRoaXMuaXRlbXNQZXJQYWdlKTtcblxuICAgIHJldHVybiBNYXRoLm1heCh0b3RhbFBhZ2VzIHx8IDAsIDEpO1xuICB9XG59XG4iLCI8dWwgY2xhc3M9XCJwYWdpbmF0aW9uXCIgW25nQ2xhc3NdPVwiY2xhc3NNYXBcIj5cbiAgPGxpIGNsYXNzPVwicGFnaW5hdGlvbi1maXJzdCBwYWdlLWl0ZW1cIlxuICAgICAgKm5nSWY9XCJib3VuZGFyeUxpbmtzXCJcbiAgICAgIFtjbGFzcy5kaXNhYmxlZF09XCJub1ByZXZpb3VzKCkgfHwgZGlzYWJsZWRcIj5cbiAgICA8YSBjbGFzcz1cInBhZ2UtbGlua1wiIGhyZWYgKGNsaWNrKT1cInNlbGVjdFBhZ2UoMSwgJGV2ZW50KVwiPlxuICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJjdXN0b21GaXJzdFRlbXBsYXRlIHx8IGRlZmF1bHRGaXJzdFRlbXBsYXRlXCJcbiAgICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie2Rpc2FibGVkOiBub1ByZXZpb3VzKCkgfHwgZGlzYWJsZWQsIGN1cnJlbnRQYWdlOiBwYWdlfVwiPlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC9hPlxuICA8L2xpPlxuXG4gIDxsaSBjbGFzcz1cInBhZ2luYXRpb24tcHJldiBwYWdlLWl0ZW1cIlxuICAgICAgKm5nSWY9XCJkaXJlY3Rpb25MaW5rc1wiXG4gICAgICBbY2xhc3MuZGlzYWJsZWRdPVwibm9QcmV2aW91cygpIHx8IGRpc2FibGVkXCI+XG4gICAgPGEgY2xhc3M9XCJwYWdlLWxpbmtcIiBocmVmIChjbGljayk9XCJzZWxlY3RQYWdlKHBhZ2UgLSAxLCAkZXZlbnQpXCI+XG4gICAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImN1c3RvbVByZXZpb3VzVGVtcGxhdGUgfHwgZGVmYXVsdFByZXZpb3VzVGVtcGxhdGVcIlxuICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7ZGlzYWJsZWQ6IG5vUHJldmlvdXMoKSB8fCBkaXNhYmxlZCwgY3VycmVudFBhZ2U6IHBhZ2V9XCI+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8L2E+XG4gIDwvbGk+XG5cbiAgPGxpICpuZ0Zvcj1cImxldCBwZyBvZiBwYWdlc1wiXG4gICAgICBbY2xhc3MuYWN0aXZlXT1cInBnLmFjdGl2ZVwiXG4gICAgICBbY2xhc3MuZGlzYWJsZWRdPVwiZGlzYWJsZWQgJiYgIXBnLmFjdGl2ZVwiXG4gICAgICBjbGFzcz1cInBhZ2luYXRpb24tcGFnZSBwYWdlLWl0ZW1cIj5cbiAgICA8YSBjbGFzcz1cInBhZ2UtbGlua1wiIGhyZWYgKGNsaWNrKT1cInNlbGVjdFBhZ2UocGcubnVtYmVyLCAkZXZlbnQpXCI+XG4gICAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImN1c3RvbVBhZ2VUZW1wbGF0ZSB8fCBkZWZhdWx0UGFnZVRlbXBsYXRlXCJcbiAgICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie2Rpc2FibGVkOiBkaXNhYmxlZCwgJGltcGxpY2l0OiBwZywgY3VycmVudFBhZ2U6IHBhZ2V9XCI+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8L2E+XG4gIDwvbGk+XG5cbiAgPGxpIGNsYXNzPVwicGFnaW5hdGlvbi1uZXh0IHBhZ2UtaXRlbVwiXG4gICAgICAqbmdJZj1cImRpcmVjdGlvbkxpbmtzXCJcbiAgICAgIFtjbGFzcy5kaXNhYmxlZF09XCJub05leHQoKSB8fCBkaXNhYmxlZFwiPlxuICAgIDxhIGNsYXNzPVwicGFnZS1saW5rXCIgaHJlZiAoY2xpY2spPVwic2VsZWN0UGFnZShwYWdlICsgMSwgJGV2ZW50KVwiPlxuICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJjdXN0b21OZXh0VGVtcGxhdGUgfHwgZGVmYXVsdE5leHRUZW1wbGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cIntkaXNhYmxlZDogbm9OZXh0KCkgfHwgZGlzYWJsZWQsIGN1cnJlbnRQYWdlOiBwYWdlfVwiPlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC9hPlxuICA8L2xpPlxuXG4gIDxsaSBjbGFzcz1cInBhZ2luYXRpb24tbGFzdCBwYWdlLWl0ZW1cIlxuICAgICAgKm5nSWY9XCJib3VuZGFyeUxpbmtzXCJcbiAgICAgIFtjbGFzcy5kaXNhYmxlZF09XCJub05leHQoKSB8fCBkaXNhYmxlZFwiPlxuICAgIDxhIGNsYXNzPVwicGFnZS1saW5rXCIgaHJlZiAoY2xpY2spPVwic2VsZWN0UGFnZSh0b3RhbFBhZ2VzLCAkZXZlbnQpXCI+XG4gICAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImN1c3RvbUxhc3RUZW1wbGF0ZSB8fCBkZWZhdWx0TGFzdFRlbXBsYXRlXCJcbiAgICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie2Rpc2FibGVkOiBub05leHQoKSB8fCBkaXNhYmxlZCwgY3VycmVudFBhZ2U6IHBhZ2V9XCI+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8L2E+XG4gIDwvbGk+XG48L3VsPlxuXG48bmctdGVtcGxhdGUgI2RlZmF1bHRQYWdlVGVtcGxhdGUgbGV0LXBhZ2U+e3sgcGFnZS50ZXh0IH19PC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlICNkZWZhdWx0TmV4dFRlbXBsYXRlPnt7IGdldFRleHQoJ25leHQnKSB9fTwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjZGVmYXVsdFByZXZpb3VzVGVtcGxhdGU+e3sgZ2V0VGV4dCgncHJldmlvdXMnKSB9fTwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjZGVmYXVsdEZpcnN0VGVtcGxhdGU+e3sgZ2V0VGV4dCgnZmlyc3QnKSB9fTwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjZGVmYXVsdExhc3RUZW1wbGF0ZT57eyBnZXRUZXh0KCdsYXN0JykgfX08L25nLXRlbXBsYXRlPlxuIl19