@angular/material
Version:
Angular Material
445 lines • 37.7 kB
JavaScript
/**
* @fileoverview added by tsickle
* Generated from: src/material/paginator/paginator.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coercion';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output, ViewEncapsulation, } from '@angular/core';
import { MatPaginatorIntl } from './paginator-intl';
import { mixinInitialized, mixinDisabled, } from '@angular/material/core';
/**
* The default page size if there is no page size and there are no provided page size options.
* @type {?}
*/
const DEFAULT_PAGE_SIZE = 50;
/**
* Change event object that is emitted when the user selects a
* different page size or navigates to another page.
*/
export class PageEvent {
}
if (false) {
/**
* The current page index.
* @type {?}
*/
PageEvent.prototype.pageIndex;
/**
* Index of the page that was selected previously.
* \@breaking-change 8.0.0 To be made into a required property.
* @type {?}
*/
PageEvent.prototype.previousPageIndex;
/**
* The current page size
* @type {?}
*/
PageEvent.prototype.pageSize;
/**
* The current total number of items being paged
* @type {?}
*/
PageEvent.prototype.length;
}
// Boilerplate for applying mixins to MatPaginator.
/**
* \@docs-private
*/
class MatPaginatorBase {
}
/** @type {?} */
const _MatPaginatorBase = mixinDisabled(mixinInitialized(MatPaginatorBase));
/**
* Component to provide navigation between paged information. Displays the size of the current
* page, user-selectable options to change that size, what items are being shown, and
* navigational button to go to the previous or next page.
*/
export class MatPaginator extends _MatPaginatorBase {
/**
* @param {?} _intl
* @param {?} _changeDetectorRef
*/
constructor(_intl, _changeDetectorRef) {
super();
this._intl = _intl;
this._changeDetectorRef = _changeDetectorRef;
this._pageIndex = 0;
this._length = 0;
this._pageSizeOptions = [];
this._hidePageSize = false;
this._showFirstLastButtons = false;
/**
* Event emitted when the paginator changes the page size or page index.
*/
this.page = new EventEmitter();
this._intlChanges = _intl.changes.subscribe((/**
* @return {?}
*/
() => this._changeDetectorRef.markForCheck()));
}
/**
* The zero-based page index of the displayed list of items. Defaulted to 0.
* @return {?}
*/
get pageIndex() { return this._pageIndex; }
/**
* @param {?} value
* @return {?}
*/
set pageIndex(value) {
this._pageIndex = Math.max(coerceNumberProperty(value), 0);
this._changeDetectorRef.markForCheck();
}
/**
* The length of the total number of items that are being paginated. Defaulted to 0.
* @return {?}
*/
get length() { return this._length; }
/**
* @param {?} value
* @return {?}
*/
set length(value) {
this._length = coerceNumberProperty(value);
this._changeDetectorRef.markForCheck();
}
/**
* Number of items to display on a page. By default set to 50.
* @return {?}
*/
get pageSize() { return this._pageSize; }
/**
* @param {?} value
* @return {?}
*/
set pageSize(value) {
this._pageSize = Math.max(coerceNumberProperty(value), 0);
this._updateDisplayedPageSizeOptions();
}
/**
* The set of provided page size options to display to the user.
* @return {?}
*/
get pageSizeOptions() { return this._pageSizeOptions; }
/**
* @param {?} value
* @return {?}
*/
set pageSizeOptions(value) {
this._pageSizeOptions = (value || []).map((/**
* @param {?} p
* @return {?}
*/
p => coerceNumberProperty(p)));
this._updateDisplayedPageSizeOptions();
}
/**
* Whether to hide the page size selection UI from the user.
* @return {?}
*/
get hidePageSize() { return this._hidePageSize; }
/**
* @param {?} value
* @return {?}
*/
set hidePageSize(value) {
this._hidePageSize = coerceBooleanProperty(value);
}
/**
* Whether to show the first/last buttons UI to the user.
* @return {?}
*/
get showFirstLastButtons() { return this._showFirstLastButtons; }
/**
* @param {?} value
* @return {?}
*/
set showFirstLastButtons(value) {
this._showFirstLastButtons = coerceBooleanProperty(value);
}
/**
* @return {?}
*/
ngOnInit() {
this._initialized = true;
this._updateDisplayedPageSizeOptions();
this._markInitialized();
}
/**
* @return {?}
*/
ngOnDestroy() {
this._intlChanges.unsubscribe();
}
/**
* Advances to the next page if it exists.
* @return {?}
*/
nextPage() {
if (!this.hasNextPage()) {
return;
}
/** @type {?} */
const previousPageIndex = this.pageIndex;
this.pageIndex++;
this._emitPageEvent(previousPageIndex);
}
/**
* Move back to the previous page if it exists.
* @return {?}
*/
previousPage() {
if (!this.hasPreviousPage()) {
return;
}
/** @type {?} */
const previousPageIndex = this.pageIndex;
this.pageIndex--;
this._emitPageEvent(previousPageIndex);
}
/**
* Move to the first page if not already there.
* @return {?}
*/
firstPage() {
// hasPreviousPage being false implies at the start
if (!this.hasPreviousPage()) {
return;
}
/** @type {?} */
const previousPageIndex = this.pageIndex;
this.pageIndex = 0;
this._emitPageEvent(previousPageIndex);
}
/**
* Move to the last page if not already there.
* @return {?}
*/
lastPage() {
// hasNextPage being false implies at the end
if (!this.hasNextPage()) {
return;
}
/** @type {?} */
const previousPageIndex = this.pageIndex;
this.pageIndex = this.getNumberOfPages() - 1;
this._emitPageEvent(previousPageIndex);
}
/**
* Whether there is a previous page.
* @return {?}
*/
hasPreviousPage() {
return this.pageIndex >= 1 && this.pageSize != 0;
}
/**
* Whether there is a next page.
* @return {?}
*/
hasNextPage() {
/** @type {?} */
const maxPageIndex = this.getNumberOfPages() - 1;
return this.pageIndex < maxPageIndex && this.pageSize != 0;
}
/**
* Calculate the number of pages
* @return {?}
*/
getNumberOfPages() {
if (!this.pageSize) {
return 0;
}
return Math.ceil(this.length / this.pageSize);
}
/**
* Changes the page size so that the first item displayed on the page will still be
* displayed using the new page size.
*
* For example, if the page size is 10 and on the second page (items indexed 10-19) then
* switching so that the page size is 5 will set the third page as the current page so
* that the 10th item will still be displayed.
* @param {?} pageSize
* @return {?}
*/
_changePageSize(pageSize) {
// Current page needs to be updated to reflect the new page size. Navigate to the page
// containing the previous page's first item.
/** @type {?} */
const startIndex = this.pageIndex * this.pageSize;
/** @type {?} */
const previousPageIndex = this.pageIndex;
this.pageIndex = Math.floor(startIndex / pageSize) || 0;
this.pageSize = pageSize;
this._emitPageEvent(previousPageIndex);
}
/**
* Checks whether the buttons for going forwards should be disabled.
* @return {?}
*/
_nextButtonsDisabled() {
return this.disabled || !this.hasNextPage();
}
/**
* Checks whether the buttons for going backwards should be disabled.
* @return {?}
*/
_previousButtonsDisabled() {
return this.disabled || !this.hasPreviousPage();
}
/**
* Updates the list of page size options to display to the user. Includes making sure that
* the page size is an option and that the list is sorted.
* @private
* @return {?}
*/
_updateDisplayedPageSizeOptions() {
if (!this._initialized) {
return;
}
// If no page size is provided, use the first page size option or the default page size.
if (!this.pageSize) {
this._pageSize = this.pageSizeOptions.length != 0 ?
this.pageSizeOptions[0] :
DEFAULT_PAGE_SIZE;
}
this._displayedPageSizeOptions = this.pageSizeOptions.slice();
if (this._displayedPageSizeOptions.indexOf(this.pageSize) === -1) {
this._displayedPageSizeOptions.push(this.pageSize);
}
// Sort the numbers using a number-specific sort function.
this._displayedPageSizeOptions.sort((/**
* @param {?} a
* @param {?} b
* @return {?}
*/
(a, b) => a - b));
this._changeDetectorRef.markForCheck();
}
/**
* Emits an event notifying that a change of the paginator's properties has been triggered.
* @private
* @param {?} previousPageIndex
* @return {?}
*/
_emitPageEvent(previousPageIndex) {
this.page.emit({
previousPageIndex,
pageIndex: this.pageIndex,
pageSize: this.pageSize,
length: this.length
});
}
}
MatPaginator.decorators = [
{ type: Component, args: [{
selector: 'mat-paginator',
exportAs: 'matPaginator',
template: "<div class=\"mat-paginator-outer-container\">\n <div class=\"mat-paginator-container\">\n <div class=\"mat-paginator-page-size\" *ngIf=\"!hidePageSize\">\n <div class=\"mat-paginator-page-size-label\">\n {{_intl.itemsPerPageLabel}}\n </div>\n\n <mat-form-field\n *ngIf=\"_displayedPageSizeOptions.length > 1\"\n [color]=\"color\"\n class=\"mat-paginator-page-size-select\">\n <mat-select\n [value]=\"pageSize\"\n [disabled]=\"disabled\"\n [aria-label]=\"_intl.itemsPerPageLabel\"\n (selectionChange)=\"_changePageSize($event.value)\">\n <mat-option *ngFor=\"let pageSizeOption of _displayedPageSizeOptions\" [value]=\"pageSizeOption\">\n {{pageSizeOption}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n\n <div\n class=\"mat-paginator-page-size-value\"\n *ngIf=\"_displayedPageSizeOptions.length <= 1\">{{pageSize}}</div>\n </div>\n\n <div class=\"mat-paginator-range-actions\">\n <div class=\"mat-paginator-range-label\">\n {{_intl.getRangeLabel(pageIndex, pageSize, length)}}\n </div>\n\n <button mat-icon-button type=\"button\"\n class=\"mat-paginator-navigation-first\"\n (click)=\"firstPage()\"\n [attr.aria-label]=\"_intl.firstPageLabel\"\n [matTooltip]=\"_intl.firstPageLabel\"\n [matTooltipDisabled]=\"_previousButtonsDisabled()\"\n [matTooltipPosition]=\"'above'\"\n [disabled]=\"_previousButtonsDisabled()\"\n *ngIf=\"showFirstLastButtons\">\n <svg class=\"mat-paginator-icon\" viewBox=\"0 0 24 24\" focusable=\"false\">\n <path d=\"M18.41 16.59L13.82 12l4.59-4.59L17 6l-6 6 6 6zM6 6h2v12H6z\"/>\n </svg>\n </button>\n <button mat-icon-button type=\"button\"\n class=\"mat-paginator-navigation-previous\"\n (click)=\"previousPage()\"\n [attr.aria-label]=\"_intl.previousPageLabel\"\n [matTooltip]=\"_intl.previousPageLabel\"\n [matTooltipDisabled]=\"_previousButtonsDisabled()\"\n [matTooltipPosition]=\"'above'\"\n [disabled]=\"_previousButtonsDisabled()\">\n <svg class=\"mat-paginator-icon\" viewBox=\"0 0 24 24\" focusable=\"false\">\n <path d=\"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z\"/>\n </svg>\n </button>\n <button mat-icon-button type=\"button\"\n class=\"mat-paginator-navigation-next\"\n (click)=\"nextPage()\"\n [attr.aria-label]=\"_intl.nextPageLabel\"\n [matTooltip]=\"_intl.nextPageLabel\"\n [matTooltipDisabled]=\"_nextButtonsDisabled()\"\n [matTooltipPosition]=\"'above'\"\n [disabled]=\"_nextButtonsDisabled()\">\n <svg class=\"mat-paginator-icon\" viewBox=\"0 0 24 24\" focusable=\"false\">\n <path d=\"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z\"/>\n </svg>\n </button>\n <button mat-icon-button type=\"button\"\n class=\"mat-paginator-navigation-last\"\n (click)=\"lastPage()\"\n [attr.aria-label]=\"_intl.lastPageLabel\"\n [matTooltip]=\"_intl.lastPageLabel\"\n [matTooltipDisabled]=\"_nextButtonsDisabled()\"\n [matTooltipPosition]=\"'above'\"\n [disabled]=\"_nextButtonsDisabled()\"\n *ngIf=\"showFirstLastButtons\">\n <svg class=\"mat-paginator-icon\" viewBox=\"0 0 24 24\" focusable=\"false\">\n <path d=\"M5.59 7.41L10.18 12l-4.59 4.59L7 18l6-6-6-6zM16 6h2v12h-2z\"/>\n </svg>\n </button>\n </div>\n </div>\n</div>\n",
inputs: ['disabled'],
host: {
'class': 'mat-paginator',
},
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
styles: [".mat-paginator{display:block}.mat-paginator-outer-container{display:flex}.mat-paginator-container{display:flex;align-items:center;justify-content:flex-end;min-height:56px;padding:0 8px;flex-wrap:wrap-reverse;width:100%}.mat-paginator-page-size{display:flex;align-items:baseline;margin-right:8px}[dir=rtl] .mat-paginator-page-size{margin-right:0;margin-left:8px}.mat-paginator-page-size-label{margin:0 4px}.mat-paginator-page-size-select{margin:6px 4px 0 4px;width:56px}.mat-paginator-page-size-select.mat-form-field-appearance-outline{width:64px}.mat-paginator-page-size-select.mat-form-field-appearance-fill{width:64px}.mat-paginator-range-label{margin:0 32px 0 24px}.mat-paginator-range-actions{display:flex;align-items:center}.mat-paginator-icon{width:28px;fill:currentColor}[dir=rtl] .mat-paginator-icon{transform:rotate(180deg)}\n"]
}] }
];
/** @nocollapse */
MatPaginator.ctorParameters = () => [
{ type: MatPaginatorIntl },
{ type: ChangeDetectorRef }
];
MatPaginator.propDecorators = {
color: [{ type: Input }],
pageIndex: [{ type: Input }],
length: [{ type: Input }],
pageSize: [{ type: Input }],
pageSizeOptions: [{ type: Input }],
hidePageSize: [{ type: Input }],
showFirstLastButtons: [{ type: Input }],
page: [{ type: Output }]
};
if (false) {
/** @type {?} */
MatPaginator.ngAcceptInputType_pageIndex;
/** @type {?} */
MatPaginator.ngAcceptInputType_length;
/** @type {?} */
MatPaginator.ngAcceptInputType_pageSize;
/** @type {?} */
MatPaginator.ngAcceptInputType_hidePageSize;
/** @type {?} */
MatPaginator.ngAcceptInputType_showFirstLastButtons;
/** @type {?} */
MatPaginator.ngAcceptInputType_disabled;
/**
* @type {?}
* @private
*/
MatPaginator.prototype._initialized;
/**
* @type {?}
* @private
*/
MatPaginator.prototype._intlChanges;
/**
* Theme color to be used for the underlying form controls.
* @type {?}
*/
MatPaginator.prototype.color;
/**
* @type {?}
* @private
*/
MatPaginator.prototype._pageIndex;
/**
* @type {?}
* @private
*/
MatPaginator.prototype._length;
/**
* @type {?}
* @private
*/
MatPaginator.prototype._pageSize;
/**
* @type {?}
* @private
*/
MatPaginator.prototype._pageSizeOptions;
/**
* @type {?}
* @private
*/
MatPaginator.prototype._hidePageSize;
/**
* @type {?}
* @private
*/
MatPaginator.prototype._showFirstLastButtons;
/**
* Event emitted when the paginator changes the page size or page index.
* @type {?}
*/
MatPaginator.prototype.page;
/**
* Displayed set of page size options. Will be sorted and include current page size.
* @type {?}
*/
MatPaginator.prototype._displayedPageSizeOptions;
/** @type {?} */
MatPaginator.prototype._intl;
/**
* @type {?}
* @private
*/
MatPaginator.prototype._changeDetectorRef;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL21hdGVyaWFsL3BhZ2luYXRvci9wYWdpbmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBUUEsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixxQkFBcUIsRUFHdEIsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQixPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEVBQ04saUJBQWlCLEdBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBQ2xELE9BQU8sRUFHTCxnQkFBZ0IsRUFFaEIsYUFBYSxHQUdkLE1BQU0sd0JBQXdCLENBQUM7Ozs7O01BRzFCLGlCQUFpQixHQUFHLEVBQUU7Ozs7O0FBTTVCLE1BQU0sT0FBTyxTQUFTO0NBZXJCOzs7Ozs7SUFiQyw4QkFBa0I7Ozs7OztJQU1sQixzQ0FBMkI7Ozs7O0lBRzNCLDZCQUFpQjs7Ozs7SUFHakIsMkJBQWU7Ozs7OztBQUtqQixNQUFNLGdCQUFnQjtDQUFHOztNQUNuQixpQkFBaUIsR0FDbkIsYUFBYSxDQUFDLGdCQUFnQixDQUFDLGdCQUFnQixDQUFDLENBQUM7Ozs7OztBQW1CckQsTUFBTSxPQUFPLFlBQWEsU0FBUSxpQkFBaUI7Ozs7O0lBbUVqRCxZQUFtQixLQUF1QixFQUN0QixrQkFBcUM7UUFDdkQsS0FBSyxFQUFFLENBQUM7UUFGUyxVQUFLLEdBQUwsS0FBSyxDQUFrQjtRQUN0Qix1QkFBa0IsR0FBbEIsa0JBQWtCLENBQW1CO1FBckRqRCxlQUFVLEdBQUcsQ0FBQyxDQUFDO1FBU2YsWUFBTyxHQUFHLENBQUMsQ0FBQztRQWtCWixxQkFBZ0IsR0FBYSxFQUFFLENBQUM7UUFRaEMsa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFT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O0lBQzdDLHdDQUErQzs7SUFDL0MsNENBQW9EOztJQUNwRCxvREFBNEQ7O0lBQzVELHdDQUFnRDs7Ozs7SUFqTmhELG9DQUE4Qjs7Ozs7SUFDOUIsb0NBQW1DOzs7OztJQUduQyw2QkFBNkI7Ozs7O0lBUzdCLGtDQUF1Qjs7Ozs7SUFTdkIsK0JBQW9COzs7OztJQVNwQixpQ0FBMEI7Ozs7O0lBUzFCLHdDQUF3Qzs7Ozs7SUFReEMscUNBQThCOzs7OztJQVM5Qiw2Q0FBc0M7Ozs7O0lBR3RDLDRCQUFpRjs7Ozs7SUFHakYsaURBQW9DOztJQUV4Qiw2QkFBOEI7Ozs7O0lBQzlCLDBDQUE2QyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQge1xuICBjb2VyY2VOdW1iZXJQcm9wZXJ0eSxcbiAgY29lcmNlQm9vbGVhblByb3BlcnR5LFxuICBCb29sZWFuSW5wdXQsXG4gIE51bWJlcklucHV0XG59IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XG5pbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtTdWJzY3JpcHRpb259IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtNYXRQYWdpbmF0b3JJbnRsfSBmcm9tICcuL3BhZ2luYXRvci1pbnRsJztcbmltcG9ydCB7XG4gIEhhc0luaXRpYWxpemVkLFxuICBIYXNJbml0aWFsaXplZEN0b3IsXG4gIG1peGluSW5pdGlhbGl6ZWQsXG4gIFRoZW1lUGFsZXR0ZSxcbiAgbWl4aW5EaXNhYmxlZCxcbiAgQ2FuRGlzYWJsZUN0b3IsXG4gIENhbkRpc2FibGUsXG59IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NvcmUnO1xuXG4vKiogVGhlIGRlZmF1bHQgcGFnZSBzaXplIGlmIHRoZXJlIGlzIG5vIHBhZ2Ugc2l6ZSBhbmQgdGhlcmUgYXJlIG5vIHByb3ZpZGVkIHBhZ2Ugc2l6ZSBvcHRpb25zLiAqL1xuY29uc3QgREVGQVVMVF9QQUdFX1NJWkUgPSA1MDtcblxuLyoqXG4gKiBDaGFuZ2UgZXZlbnQgb2JqZWN0IHRoYXQgaXMgZW1pdHRlZCB3aGVuIHRoZSB1c2VyIHNlbGVjdHMgYVxuICogZGlmZmVyZW50IHBhZ2Ugc2l6ZSBvciBuYXZpZ2F0ZXMgdG8gYW5vdGhlciBwYWdlLlxuICovXG5leHBvcnQgY2xhc3MgUGFnZUV2ZW50IHtcbiAgLyoqIFRoZSBjdXJyZW50IHBhZ2UgaW5kZXguICovXG4gIHBhZ2VJbmRleDogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBJbmRleCBvZiB0aGUgcGFnZSB0aGF0IHdhcyBzZWxlY3RlZCBwcmV2aW91c2x5LlxuICAgKiBAYnJlYWtpbmctY2hhbmdlIDguMC4wIFRvIGJlIG1hZGUgaW50byBhIHJlcXVpcmVkIHByb3BlcnR5LlxuICAgKi9cbiAgcHJldmlvdXNQYWdlSW5kZXg/OiBudW1iZXI7XG5cbiAgLyoqIFRoZSBjdXJyZW50IHBhZ2Ugc2l6ZSAqL1xuICBwYWdlU2l6ZTogbnVtYmVyO1xuXG4gIC8qKiBUaGUgY3VycmVudCB0b3RhbCBudW1iZXIgb2YgaXRlbXMgYmVpbmcgcGFnZWQgKi9cbiAgbGVuZ3RoOiBudW1iZXI7XG59XG5cbi8vIEJvaWxlcnBsYXRlIGZvciBhcHBseWluZyBtaXhpbnMgdG8gTWF0UGFnaW5hdG9yLlxuLyoqIEBkb2NzLXByaXZhdGUgKi9cbmNsYXNzIE1hdFBhZ2luYXRvckJhc2Uge31cbmNvbnN0IF9NYXRQYWdpbmF0b3JCYXNlOiBDYW5EaXNhYmxlQ3RvciAmIEhhc0luaXRpYWxpemVkQ3RvciAmIHR5cGVvZiBNYXRQYWdpbmF0b3JCYXNlID1cbiAgICBtaXhpbkRpc2FibGVkKG1peGluSW5pdGlhbGl6ZWQoTWF0UGFnaW5hdG9yQmFzZSkpO1xuXG4vKipcbiAqIENvbXBvbmVudCB0byBwcm92aWRlIG5hdmlnYXRpb24gYmV0d2VlbiBwYWdlZCBpbmZvcm1hdGlvbi4gRGlzcGxheXMgdGhlIHNpemUgb2YgdGhlIGN1cnJlbnRcbiAqIHBhZ2UsIHVzZXItc2VsZWN0YWJsZSBvcHRpb25zIHRvIGNoYW5nZSB0aGF0IHNpemUsIHdoYXQgaXRlbXMgYXJlIGJlaW5nIHNob3duLCBhbmRcbiAqIG5hdmlnYXRpb25hbCBidXR0b24gdG8gZ28gdG8gdGhlIHByZXZpb3VzIG9yIG5leHQgcGFnZS5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbWF0LXBhZ2luYXRvcicsXG4gIGV4cG9ydEFzOiAnbWF0UGFnaW5hdG9yJyxcbiAgdGVtcGxhdGVVcmw6ICdwYWdpbmF0b3IuaHRtbCcsXG4gIHN0eWxlVXJsczogWydwYWdpbmF0b3IuY3NzJ10sXG4gIGlucHV0czogWydkaXNhYmxlZCddLFxuICBob3N0OiB7XG4gICAgJ2NsYXNzJzogJ21hdC1wYWdpbmF0b3InLFxuICB9LFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbn0pXG5leHBvcnQgY2xhc3MgTWF0UGFnaW5hdG9yIGV4dGVuZHMgX01hdFBhZ2luYXRvckJhc2UgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSwgQ2FuRGlzYWJsZSxcbiAgSGFzSW5pdGlhbGl6ZWQge1xuICBwcml2YXRlIF9pbml0aWFsaXplZDogYm9vbGVhbjtcbiAgcHJpdmF0ZSBfaW50bENoYW5nZXM6IFN1YnNjcmlwdGlvbjtcblxuICAvKiogVGhlbWUgY29sb3IgdG8gYmUgdXNlZCBmb3IgdGhlIHVuZGVybHlpbmcgZm9ybSBjb250cm9scy4gKi9cbiAgQElucHV0KCkgY29sb3I6IFRoZW1lUGFsZXR0ZTtcblxuICAvKiogVGhlIHplcm8tYmFzZWQgcGFnZSBpbmRleCBvZiB0aGUgZGlzcGxheWVkIGxpc3Qgb2YgaXRlbXMuIERlZmF1bHRlZCB0byAwLiAqL1xuICBASW5wdXQoKVxuICBnZXQgcGFnZUluZGV4KCk6IG51bWJlciB7IHJldHVybiB0aGlzLl9wYWdlSW5kZXg7IH1cbiAgc2V0IHBhZ2VJbmRleCh2YWx1ZTogbnVtYmVyKSB7XG4gICAgdGhpcy5fcGFnZUluZGV4ID0gTWF0aC5tYXgoY29lcmNlTnVtYmVyUHJvcGVydHkodmFsdWUpLCAwKTtcbiAgICB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuICBwcml2YXRlIF9wYWdlSW5kZXggPSAwO1xuXG4gIC8qKiBUaGUgbGVuZ3RoIG9mIHRoZSB0b3RhbCBudW1iZXIgb2YgaXRlbXMgdGhhdCBhcmUgYmVpbmcgcGFnaW5hdGVkLiBEZWZhdWx0ZWQgdG8gMC4gKi9cbiAgQElucHV0KClcbiAgZ2V0IGxlbmd0aCgpOiBudW1iZXIgeyByZXR1cm4gdGhpcy5fbGVuZ3RoOyB9XG4gIHNldCBsZW5ndGgodmFsdWU6IG51bWJlcikge1xuICAgIHRoaXMuX2xlbmd0aCA9IGNvZXJjZU51bWJlclByb3BlcnR5KHZhbHVlKTtcbiAgICB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuICBwcml2YXRlIF9sZW5ndGggPSAwO1xuXG4gIC8qKiBOdW1iZXIgb2YgaXRlbXMgdG8gZGlzcGxheSBvbiBhIHBhZ2UuIEJ5IGRlZmF1bHQgc2V0IHRvIDUwLiAqL1xuICBASW5wdXQoKVxuICBnZXQgcGFnZVNpemUoKTogbnVtYmVyIHsgcmV0dXJuIHRoaXMuX3BhZ2VTaXplOyB9XG4gIHNldCBwYWdlU2l6ZSh2YWx1ZTogbnVtYmVyKSB7XG4gICAgdGhpcy5fcGFnZVNpemUgPSBNYXRoLm1heChjb2VyY2VOdW1iZXJQcm9wZXJ0eSh2YWx1ZSksIDApO1xuICAgIHRoaXMuX3VwZGF0ZURpc3BsYXllZFBhZ2VTaXplT3B0aW9ucygpO1xuICB9XG4gIHByaXZhdGUgX3BhZ2VTaXplOiBudW1iZXI7XG5cbiAgLyoqIFRoZSBzZXQgb2YgcHJvdmlkZWQgcGFnZSBzaXplIG9wdGlvbnMgdG8gZGlzcGxheSB0byB0aGUgdXNlci4gKi9cbiAgQElucHV0KClcbiAgZ2V0IHBhZ2VTaXplT3B0aW9ucygpOiBudW1iZXJbXSB7IHJldHVybiB0aGlzLl9wYWdlU2l6ZU9wdGlvbnM7IH1cbiAgc2V0IHBhZ2VTaXplT3B0aW9ucyh2YWx1ZTogbnVtYmVyW10pIHtcbiAgICB0aGlzLl9wYWdlU2l6ZU9wdGlvbnMgPSAodmFsdWUgfHwgW10pLm1hcChwID0+IGNvZXJjZU51bWJlclByb3BlcnR5KHApKTtcbiAgICB0aGlzLl91cGRhdGVEaXNwbGF5ZWRQYWdlU2l6ZU9wdGlvbnMoKTtcbiAgfVxuICBwcml2YXRlIF9wYWdlU2l6ZU9wdGlvbnM6IG51bWJlcltdID0gW107XG5cbiAgLyoqIFdoZXRoZXIgdG8gaGlkZSB0aGUgcGFnZSBzaXplIHNlbGVjdGlvbiBVSSBmcm9tIHRoZSB1c2VyLiAqL1xuICBASW5wdXQoKVxuICBnZXQgaGlkZVBhZ2VTaXplKCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5faGlkZVBhZ2VTaXplOyB9XG4gIHNldCBoaWRlUGFnZVNpemUodmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9oaWRlUGFnZVNpemUgPSBjb2VyY2VCb29sZWFuUHJvcGVydHkodmFsdWUpO1xuICB9XG4gIHByaXZhdGUgX2hpZGVQYWdlU2l6ZSA9IGZhbHNlO1xuXG5cbiAgLyoqIFdoZXRoZXIgdG8gc2hvdyB0aGUgZmlyc3QvbGFzdCBidXR0b25zIFVJIHRvIHRoZSB1c2VyLiAqL1xuICBASW5wdXQoKVxuICBnZXQgc2hvd0ZpcnN0TGFzdEJ1dHRvbnMoKTogYm9vbGVhbiB7IHJldHVybiB0aGlzLl9zaG93Rmlyc3RMYXN0QnV0dG9uczsgfVxuICBzZXQgc2hvd0ZpcnN0TGFzdEJ1dHRvbnModmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9zaG93Rmlyc3RMYXN0QnV0dG9ucyA9IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSh2YWx1ZSk7XG4gIH1cbiAgcHJpdmF0ZSBfc2hvd0ZpcnN0TGFzdEJ1dHRvbnMgPSBmYWxzZTtcblxuICAvKiogRXZlbnQgZW1pdHRlZCB3aGVuIHRoZSBwYWdpbmF0b3IgY2hhbmdlcyB0aGUgcGFnZSBzaXplIG9yIHBhZ2UgaW5kZXguICovXG4gIEBPdXRwdXQoKSByZWFkb25seSBwYWdlOiBFdmVudEVtaXR0ZXI8UGFnZUV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8UGFnZUV2ZW50PigpO1xuXG4gIC8qKiBEaXNwbGF5ZWQgc2V0IG9mIHBhZ2Ugc2l6ZSBvcHRpb25zLiBXaWxsIGJlIHNvcnRlZCBhbmQgaW5jbHVkZSBjdXJyZW50IHBhZ2Ugc2l6ZS4gKi9cbiAgX2Rpc3BsYXllZFBhZ2VTaXplT3B0aW9uczogbnVtYmVyW107XG5cbiAgY29uc3RydWN0b3IocHVibGljIF9pbnRsOiBNYXRQYWdpbmF0b3JJbnRsLFxuICAgICAgICAgICAgICBwcml2YXRlIF9jaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYpIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMuX2ludGxDaGFuZ2VzID0gX2ludGwuY2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4gdGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCkpO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5faW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIHRoaXMuX3VwZGF0ZURpc3BsYXllZFBhZ2VTaXplT3B0aW9ucygpO1xuICAgIHRoaXMuX21hcmtJbml0aWFsaXplZCgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5faW50bENoYW5nZXMudW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIC8qKiBBZHZhbmNlcyB0byB0aGUgbmV4dCBwYWdlIGlmIGl0IGV4aXN0cy4gKi9cbiAgbmV4dFBhZ2UoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmhhc05leHRQYWdlKCkpIHsgcmV0dXJuOyB9XG5cbiAgICBjb25zdCBwcmV2aW91c1BhZ2VJbmRleCA9IHRoaXMucGFnZUluZGV4O1xuICAgIHRoaXMucGFnZUluZGV4Kys7XG4gICAgdGhpcy5fZW1pdFBhZ2VFdmVudChwcmV2aW91c1BhZ2VJbmRleCk7XG4gIH1cblxuICAvKiogTW92ZSBiYWNrIHRvIHRoZSBwcmV2aW91cyBwYWdlIGlmIGl0IGV4aXN0cy4gKi9cbiAgcHJldmlvdXNQYWdlKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5oYXNQcmV2aW91c1BhZ2UoKSkgeyByZXR1cm47IH1cblxuICAgIGNvbnN0IHByZXZpb3VzUGFnZUluZGV4ID0gdGhpcy5wYWdlSW5kZXg7XG4gICAgdGhpcy5wYWdlSW5kZXgtLTtcbiAgICB0aGlzLl9lbWl0UGFnZUV2ZW50KHByZXZpb3VzUGFnZUluZGV4KTtcbiAgfVxuXG4gIC8qKiBNb3ZlIHRvIHRoZSBmaXJzdCBwYWdlIGlmIG5vdCBhbHJlYWR5IHRoZXJlLiAqL1xuICBmaXJzdFBhZ2UoKTogdm9pZCB7XG4gICAgLy8gaGFzUHJldmlvdXNQYWdlIGJlaW5nIGZhbHNlIGltcGxpZXMgYXQgdGhlIHN0YXJ0XG4gICAgaWYgKCF0aGlzLmhhc1ByZXZpb3VzUGFnZSgpKSB7IHJldHVybjsgfVxuXG4gICAgY29uc3QgcHJldmlvdXNQYWdlSW5kZXggPSB0aGlzLnBhZ2VJbmRleDtcbiAgICB0aGlzLnBhZ2VJbmRleCA9IDA7XG4gICAgdGhpcy5fZW1pdFBhZ2VFdmVudChwcmV2aW91c1BhZ2VJbmRleCk7XG4gIH1cblxuICAvKiogTW92ZSB0byB0aGUgbGFzdCBwYWdlIGlmIG5vdCBhbHJlYWR5IHRoZXJlLiAqL1xuICBsYXN0UGFnZSgpOiB2b2lkIHtcbiAgICAvLyBoYXNOZXh0UGFnZSBiZWluZyBmYWxzZSBpbXBsaWVzIGF0IHRoZSBlbmRcbiAgICBpZiAoIXRoaXMuaGFzTmV4dFBhZ2UoKSkgeyByZXR1cm47IH1cblxuICAgIGNvbnN0IHByZXZpb3VzUGFnZUluZGV4ID0gdGhpcy5wYWdlSW5kZXg7XG4gICAgdGhpcy5wYWdlSW5kZXggPSB0aGlzLmdldE51bWJlck9mUGFnZXMoKSAtIDE7XG4gICAgdGhpcy5fZW1pdFBhZ2VFdmVudChwcmV2aW91c1BhZ2VJbmRleCk7XG4gIH1cblxuICAvKiogV2hldGhlciB0aGVyZSBpcyBhIHByZXZpb3VzIHBhZ2UuICovXG4gIGhhc1ByZXZpb3VzUGFnZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5wYWdlSW5kZXggPj0gMSAmJiB0aGlzLnBhZ2VTaXplICE9IDA7XG4gIH1cblxuICAvKiogV2hldGhlciB0aGVyZSBpcyBhIG5leHQgcGFnZS4gKi9cbiAgaGFzTmV4dFBhZ2UoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgbWF4UGFnZUluZGV4ID0gdGhpcy5nZXROdW1iZXJPZlBhZ2VzKCkgLSAxO1xuICAgIHJldHVybiB0aGlzLnBhZ2VJbmRleCA8IG1heFBhZ2VJbmRleCAmJiB0aGlzLnBhZ2VTaXplICE9IDA7XG4gIH1cblxuICAvKiogQ2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgcGFnZXMgKi9cbiAgZ2V0TnVtYmVyT2ZQYWdlcygpOiBudW1iZXIge1xuICAgIGlmICghdGhpcy5wYWdlU2l6ZSkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIE1hdGguY2VpbCh0aGlzLmxlbmd0aCAvIHRoaXMucGFnZVNpemUpO1xuICB9XG5cblxuICAvKipcbiAgICogQ2hhbmdlcyB0aGUgcGFnZSBzaXplIHNvIHRoYXQgdGhlIGZpcnN0IGl0ZW0gZGlzcGxheWVkIG9uIHRoZSBwYWdlIHdpbGwgc3RpbGwgYmVcbiAgICogZGlzcGxheWVkIHVzaW5nIHRoZSBuZXcgcGFnZSBzaXplLlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZSwgaWYgdGhlIHBhZ2Ugc2l6ZSBpcyAxMCBhbmQgb24gdGhlIHNlY29uZCBwYWdlIChpdGVtcyBpbmRleGVkIDEwLTE5KSB0aGVuXG4gICAqIHN3aXRjaGluZyBzbyB0aGF0IHRoZSBwYWdlIHNpemUgaXMgNSB3aWxsIHNldCB0aGUgdGhpcmQgcGFnZSBhcyB0aGUgY3VycmVudCBwYWdlIHNvXG4gICAqIHRoYXQgdGhlIDEwdGggaXRlbSB3aWxsIHN0aWxsIGJlIGRpc3BsYXllZC5cbiAgICovXG4gIF9jaGFuZ2VQYWdlU2l6ZShwYWdlU2l6ZTogbnVtYmVyKSB7XG4gICAgLy8gQ3VycmVudCBwYWdlIG5lZWRzIHRvIGJlIHVwZGF0ZWQgdG8gcmVmbGVjdCB0aGUgbmV3IHBhZ2Ugc2l6ZS4gTmF2aWdhdGUgdG8gdGhlIHBhZ2VcbiAgICAvLyBjb250YWluaW5nIHRoZSBwcmV2aW91cyBwYWdlJ3MgZmlyc3QgaXRlbS5cbiAgICBjb25zdCBzdGFydEluZGV4ID0gdGhpcy5wYWdlSW5kZXggKiB0aGlzLnBhZ2VTaXplO1xuICAgIGNvbnN0IHByZXZpb3VzUGFnZUluZGV4ID0gdGhpcy5wYWdlSW5kZXg7XG5cbiAgICB0aGlzLnBhZ2VJbmRleCA9IE1hdGguZmxvb3Ioc3RhcnRJbmRleCAvIHBhZ2VTaXplKSB8fCAwO1xuICAgIHRoaXMucGFnZVNpemUgPSBwYWdlU2l6ZTtcbiAgICB0aGlzLl9lbWl0UGFnZUV2ZW50KHByZXZpb3VzUGFnZUluZGV4KTtcbiAgfVxuXG4gIC8qKiBDaGVja3Mgd2hldGhlciB0aGUgYnV0dG9ucyBmb3IgZ29pbmcgZm9yd2FyZHMgc2hvdWxkIGJlIGRpc2FibGVkLiAqL1xuICBfbmV4dEJ1dHRvbnNEaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5kaXNhYmxlZCB8fCAhdGhpcy5oYXNOZXh0UGFnZSgpO1xuICB9XG5cbiAgLyoqIENoZWNrcyB3aGV0aGVyIHRoZSBidXR0b25zIGZvciBnb2luZyBiYWNrd2FyZHMgc2hvdWxkIGJlIGRpc2FibGVkLiAqL1xuICBfcHJldmlvdXNCdXR0b25zRGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuZGlzYWJsZWQgfHwgIXRoaXMuaGFzUHJldmlvdXNQYWdlKCk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgbGlzdCBvZiBwYWdlIHNpemUgb3B0aW9ucyB0byBkaXNwbGF5IHRvIHRoZSB1c2VyLiBJbmNsdWRlcyBtYWtpbmcgc3VyZSB0aGF0XG4gICAqIHRoZSBwYWdlIHNpemUgaXMgYW4gb3B0aW9uIGFuZCB0aGF0IHRoZSBsaXN0IGlzIHNvcnRlZC5cbiAgICovXG4gIHByaXZhdGUgX3VwZGF0ZURpc3BsYXllZFBhZ2VTaXplT3B0aW9ucygpIHtcbiAgICBpZiAoIXRoaXMuX2luaXRpYWxpemVkKSB7IHJldHVybjsgfVxuXG4gICAgLy8gSWYgbm8gcGFnZSBzaXplIGlzIHByb3ZpZGVkLCB1c2UgdGhlIGZpcnN0IHBhZ2Ugc2l6ZSBvcHRpb24gb3IgdGhlIGRlZmF1bHQgcGFnZSBzaXplLlxuICAgIGlmICghdGhpcy5wYWdlU2l6ZSkge1xuICAgICAgdGhpcy5fcGFnZVNpemUgPSB0aGlzLnBhZ2VTaXplT3B0aW9ucy5sZW5ndGggIT0gMCA/XG4gICAgICAgICAgdGhpcy5wYWdlU2l6ZU9wdGlvbnNbMF0gOlxuICAgICAgICAgIERFRkFVTFRfUEFHRV9TSVpFO1xuICAgIH1cblxuICAgIHRoaXMuX2Rpc3BsYXllZFBhZ2VTaXplT3B0aW9ucyA9IHRoaXMucGFnZVNpemVPcHRpb25zLnNsaWNlKCk7XG5cbiAgICBpZiAodGhpcy5fZGlzcGxheWVkUGFnZVNpemVPcHRpb25zLmluZGV4T2YodGhpcy5wYWdlU2l6ZSkgPT09IC0xKSB7XG4gICAgICB0aGlzLl9kaXNwbGF5ZWRQYWdlU2l6ZU9wdGlvbnMucHVzaCh0aGlzLnBhZ2VTaXplKTtcbiAgICB9XG5cbiAgICAvLyBTb3J0IHRoZSBudW1iZXJzIHVzaW5nIGEgbnVtYmVyLXNwZWNpZmljIHNvcnQgZnVuY3Rpb24uXG4gICAgdGhpcy5fZGlzcGxheWVkUGFnZVNpemVPcHRpb25zLnNvcnQoKGEsIGIpID0+IGEgLSBiKTtcbiAgICB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIC8qKiBFbWl0cyBhbiBldmVudCBub3RpZnlpbmcgdGhhdCBhIGNoYW5nZSBvZiB0aGUgcGFnaW5hdG9yJ3MgcHJvcGVydGllcyBoYXMgYmVlbiB0cmlnZ2VyZWQuICovXG4gIHByaXZhdGUgX2VtaXRQYWdlRXZlbnQocHJldmlvdXNQYWdlSW5kZXg6IG51bWJlcikge1xuICAgIHRoaXMucGFnZS5lbWl0KHtcbiAgICAgIHByZXZpb3VzUGFnZUluZGV4LFxuICAgICAgcGFnZUluZGV4OiB0aGlzLnBhZ2VJbmRleCxcbiAgICAgIHBhZ2VTaXplOiB0aGlzLnBhZ2VTaXplLFxuICAgICAgbGVuZ3RoOiB0aGlzLmxlbmd0aFxuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX3BhZ2VJbmRleDogTnVtYmVySW5wdXQ7XG4gIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9sZW5ndGg6IE51bWJlcklucHV0O1xuICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfcGFnZVNpemU6IE51bWJlcklucHV0O1xuICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfaGlkZVBhZ2VTaXplOiBCb29sZWFuSW5wdXQ7XG4gIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9zaG93Rmlyc3RMYXN0QnV0dG9uczogQm9vbGVhbklucHV0O1xuICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfZGlzYWJsZWQ6IEJvb2xlYW5JbnB1dDtcbn1cbiJdfQ==