@spartacus/storefront
Version:
Spartacus Storefront is a package that you can include in your application, which allows you to add default storefront features.
305 lines • 36 kB
JavaScript
import { Injectable } from '@angular/core';
import { PaginationItemType, PaginationNavigationPosition, } from './pagination.model';
import * as i0 from "@angular/core";
import * as i1 from "./config/pagination.config";
const FALLBACK_PAGINATION_OPTIONS = {
rangeCount: 3,
dotsLabel: '...',
startLabel: '«',
previousLabel: '‹',
nextLabel: '›',
endLabel: '»',
};
/**
* Builds a pagination structures based on a pageCount and current page number.
* There are various {@link PaginationConfig} options which can be used to configure
* the behavior of the build. Alternatively, CSS can be used to further customize
* the pagination.
*
* Examples:
* The full blown pagination items contain the follow elements:
*
* `« ‹ 1 ... 4 (5) 6 ... 9 › »`
*
* This includes pagination items to the following pages:
* - start page
* - previous page
* - first page
* - page range
* - last page
* - next page
* - end page
*
* All of those links are configurable, including the size of the page range.
* The current page will always be centered in the page range to provide direct access
* to the previous and next page.
*/
export class PaginationBuilder {
constructor(paginationConfig) {
this.paginationConfig = paginationConfig;
}
/**
* Builds a list of `PaginationItem`. The give pageCount and current are used
* to build out the full pagination. There are various {@link PaginationConfig} options
* which can be used to configure the behavior of the build. Alternatively, CSS
* can be used to further specialize visibility of the pagination.
*
* @param pageCount The total number of pages
* @param current The current page number, 0-index based
* @returns An array of `PaginationItem`
*/
paginate(pageCount, current) {
const pages = [];
if (!pageCount || pageCount < 2) {
return pages;
}
this.addPages(pages, pageCount, current);
this.addDots(pages, pageCount);
this.addFirstLast(pages, pageCount);
this.addNavigation(pages, pageCount, current);
return pages;
}
/**
* Returns the current page with surrounding pages (based on the `config.rangeCount`).
* The current page is always centered to provide direct access to the previous and next page.
*
* @param pages The list of page items that is used to amend
* @param pageCount The total number of pages
* @param current The current page number, 0-index based
*/
addPages(pages, pageCount, current) {
const start = this.getStartOfRange(pageCount, current);
const max = Math.min(this.config.rangeCount, pageCount);
Array.from(Array(max)).forEach((_, i) => {
pages.push({
number: i + start,
label: String(i + start + 1),
type: PaginationItemType.PAGE,
});
});
}
/**
* Adds dots before and after the given pages, if configured (defaults to true).
* If the dots only represent a single page, the page number is added instead of
* the dots, unless the configuration requires dots always.
*
* @param pages The list of page items that is used to amend
* @param pageCount The total number of pages
*/
addDots(pages, pageCount) {
if (!this.config.addDots) {
return;
}
const addFirstGap = () => {
const firstItemNumber = pages[0].number;
const gapNumber = this.config.addFirst ? 1 : 0;
if (firstItemNumber > gapNumber) {
const isGap = !this.config.substituteDotsForSingularPage ||
firstItemNumber !== gapNumber + 1;
const isSubstituted = this.config.addFirst &&
this.config.substituteDotsForSingularPage &&
gapNumber === 0;
const type = isGap
? PaginationItemType.GAP
: isSubstituted
? PaginationItemType.FIRST
: PaginationItemType.PAGE;
return [
Object.assign({
label: isGap ? this.config.dotsLabel : String(gapNumber + 1),
type,
}, isGap ? null : { number: gapNumber }),
];
}
else
return [];
};
const addLastGap = () => {
const nextPageNumber = pages[pages.length - 1].number + 1;
const last = pageCount - (this.config.addLast ? 2 : 1);
if (nextPageNumber <= last) {
const isSubstituted = this.config.addLast &&
this.config.substituteDotsForSingularPage &&
nextPageNumber === last;
const isGap = nextPageNumber <
pageCount -
(this.config.substituteDotsForSingularPage ? 1 : 0) -
(this.config.addLast ? 1 : 0);
const type = isGap
? PaginationItemType.GAP
: isSubstituted
? PaginationItemType.LAST
: PaginationItemType.PAGE;
return [
Object.assign({
label: isGap ? this.config.dotsLabel : String(nextPageNumber + 1),
type,
}, isGap ? null : { number: nextPageNumber }),
];
}
else
return [];
};
pages.unshift(...addFirstGap());
pages.push(...addLastGap());
}
/**
* Add links to the first and last page, if configured to do so.
*
* @param pages The list of page items that is used to amend
* @param pageCount The total number of pages
*
*/
addFirstLast(pages, pageCount) {
if (this.config.addFirst && pages[0].number !== 0) {
pages.unshift({
number: 0,
label: '1',
type: PaginationItemType.FIRST,
});
}
if (this.config.addLast &&
pages[pages.length - 1].number !== pageCount - 1) {
pages.push({
number: pageCount - 1,
label: String(pageCount),
type: PaginationItemType.LAST,
});
}
}
/**
* Add links to the start, previous, next and last page, if configured to do so.
* The order of the links can be configured by using the {@link PaginationConfig},
* using the `PaginationNavigationPosition` (`BEFORE` or `AFTER`).
* The `PaginationNavigationPosition` allows for 3 flavours:
*
* - by default the pagination starts with start and previous and ends with the next and end links
* - BEFORE – all navigation links are added in the front of the pagination list
* - AFTER – all navigation links are pushed to the end of the pagination list
*
* @param pages The list of page items that is used to amend
* @param pageCount The total number of pages
* @param current The current page number, 0-index based
*
*/
addNavigation(pages, pageCount, current) {
const before = this.getBeforeLinks(current);
const after = this.getAfterLinks(pageCount, current);
const pos = this.config.navigationPosition;
if (!pos || pos === PaginationNavigationPosition.ASIDE) {
pages.unshift(...before);
pages.push(...after);
}
else {
if (pos === PaginationNavigationPosition.BEFORE) {
pages.unshift(...before, ...after);
}
if (pos === PaginationNavigationPosition.AFTER) {
pages.push(...before, ...after);
}
}
}
/**
* Returns the start and previous links, if applicable.
*/
getBeforeLinks(current) {
const list = [];
if (this.config.addStart) {
const start = () => {
return Object.assign({
label: this.config.startLabel,
type: PaginationItemType.START,
}, current > 0 ? { number: 0 } : null);
};
list.push(start());
}
if (this.config.addPrevious) {
const previous = () => {
return Object.assign({
label: this.config.previousLabel,
type: PaginationItemType.PREVIOUS,
}, current > 0 ? { number: current - 1 } : null);
};
list.push(previous());
}
return list;
}
/**
* Returns the next and end links, if applicable.
*/
getAfterLinks(pageCount, current) {
const list = [];
if (this.config.addNext) {
const next = () => {
return Object.assign({
label: this.config.nextLabel,
type: PaginationItemType.NEXT,
}, current < pageCount - 1 ? { number: current + 1 } : null);
};
list.push(next());
}
if (this.config.addEnd) {
const end = () => {
return Object.assign({
label: this.config.endLabel,
type: PaginationItemType.END,
}, current < pageCount - 1 ? { number: pageCount - 1 } : null);
};
list.push(end());
}
return list;
}
/**
* Resolves the first page of the range we need to build.
* This is the page that is leading up to the range of the
* current page.
*
* @param pageCount The total number of pages.
* @param current The current page number, 0-index based.
*/
getStartOfRange(pageCount, current) {
const count = this.config.rangeCount - 1;
// the least number of pages before and after the current
const delta = Math.round(count / 2);
// ensure that we start with at least the first page
const minStart = Math.max(0, current - delta);
// ensures that we start with at least 1 and do not pass the last range
const maxStart = Math.max(0, pageCount - count - 1);
// ensure that we get at least a full range at the end
return Math.min(maxStart, minStart);
}
/**
* Returns the pagination configuration. The configuration is driven by the
* (default) application configuration.
*
* The default application is limited to adding the start and end link:
* ```ts
* addStart: true,
* addEnd: true
* ```
*
* The application configuration is however merged into the following static configuration:
* ```ts
* {
* rangeCount: 3,
* dotsLabel: '...',
* startLabel: '«',
* previousLabel: '‹',
* nextLabel: '›',
* endLabel: '»'
* }
* ```
*/
get config() {
return Object.assign(FALLBACK_PAGINATION_OPTIONS, this.paginationConfig.pagination);
}
}
PaginationBuilder.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: PaginationBuilder, deps: [{ token: i1.PaginationConfig }], target: i0.ɵɵFactoryTarget.Injectable });
PaginationBuilder.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: PaginationBuilder, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: PaginationBuilder, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: function () { return [{ type: i1.PaginationConfig }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdGlvbi5idWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc3RvcmVmcm9udGxpYi9zaGFyZWQvY29tcG9uZW50cy9saXN0LW5hdmlnYXRpb24vcGFnaW5hdGlvbi9wYWdpbmF0aW9uLmJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUzQyxPQUFPLEVBRUwsa0JBQWtCLEVBQ2xCLDRCQUE0QixHQUU3QixNQUFNLG9CQUFvQixDQUFDOzs7QUFFNUIsTUFBTSwyQkFBMkIsR0FBc0I7SUFDckQsVUFBVSxFQUFFLENBQUM7SUFDYixTQUFTLEVBQUUsS0FBSztJQUNoQixVQUFVLEVBQUUsR0FBRztJQUNmLGFBQWEsRUFBRSxHQUFHO0lBQ2xCLFNBQVMsRUFBRSxHQUFHO0lBQ2QsUUFBUSxFQUFFLEdBQUc7Q0FDZCxDQUFDO0FBRUY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBdUJHO0FBSUgsTUFBTSxPQUFPLGlCQUFpQjtJQUM1QixZQUFzQixnQkFBa0M7UUFBbEMscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtJQUFHLENBQUM7SUFFNUQ7Ozs7Ozs7OztPQVNHO0lBQ0gsUUFBUSxDQUFDLFNBQWlCLEVBQUUsT0FBZTtRQUN6QyxNQUFNLEtBQUssR0FBcUIsRUFBRSxDQUFDO1FBQ25DLElBQUksQ0FBQyxTQUFTLElBQUksU0FBUyxHQUFHLENBQUMsRUFBRTtZQUMvQixPQUFPLEtBQUssQ0FBQztTQUNkO1FBQ0QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FB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RixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7U0FDbEI7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFDRDs7Ozs7OztPQU9HO0lBQ08sZUFBZSxDQUFDLFNBQWlCLEVBQUUsT0FBZTtRQUMxRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUM7UUFDekMseURBQXlEO1FBQ3pELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRXBDLG9EQUFvRDtRQUNwRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxPQUFPLEdBQUcsS0FBSyxDQUFDLENBQUM7UUFDOUMsdUVBQXVFO1FBQ3ZFLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFNBQVMsR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFcEQsc0RBQXNEO1FBQ3RELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FxQkc7SUFDSCxJQUFjLE1BQU07UUFDbEIsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUNsQiwyQkFBMkIsRUFDM0IsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsQ0FDakMsQ0FBQztJQUNKLENBQUM7OzhHQW5UVSxpQkFBaUI7a0hBQWpCLGlCQUFpQixjQUZoQixNQUFNOzJGQUVQLGlCQUFpQjtrQkFIN0IsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBQYWdpbmF0aW9uQ29uZmlnIH0gZnJvbSAnLi9jb25maWcvcGFnaW5hdGlvbi5jb25maWcnO1xuaW1wb3J0IHtcbiAgUGFnaW5hdGlvbkl0ZW0sXG4gIFBhZ2luYXRpb25JdGVtVHlwZSxcbiAgUGFnaW5hdGlvbk5hdmlnYXRpb25Qb3NpdGlvbixcbiAgUGFnaW5hdGlvbk9wdGlvbnMsXG59IGZyb20gJy4vcGFnaW5hdGlvbi5tb2RlbCc7XG5cbmNvbnN0IEZBTExCQUNLX1BBR0lOQVRJT05fT1BUSU9OUzogUGFnaW5hdGlvbk9wdGlvbnMgPSB7XG4gIHJhbmdlQ291bnQ6IDMsXG4gIGRvdHNMYWJlbDogJy4uLicsXG4gIHN0YXJ0TGFiZWw6ICfCqycsXG4gIHByZXZpb3VzTGFiZWw6ICfigLknLFxuICBuZXh0TGFiZWw6ICfigLonLFxuICBlbmRMYWJlbDogJ8K7Jyxcbn07XG5cbi8qKlxuICogQnVpbGRzIGEgcGFnaW5hdGlvbiBzdHJ1Y3R1cmVzIGJhc2VkIG9uIGEgcGFnZUNvdW50IGFuZCBjdXJyZW50IHBhZ2UgbnVtYmVyLlxuICogVGhlcmUgYXJlIHZhcmlvdXMge0BsaW5rIFBhZ2luYXRpb25Db25maWd9IG9wdGlvbnMgd2hpY2ggY2FuIGJlIHVzZWQgdG8gY29uZmlndXJlXG4gKiB0aGUgYmVoYXZpb3Igb2YgdGhlIGJ1aWxkLiBBbHRlcm5hdGl2ZWx5LCBDU1MgY2FuIGJlIHVzZWQgdG8gZnVydGhlciBjdXN0b21pemVcbiAqIHRoZSBwYWdpbmF0aW9uLlxuICpcbiAqIEV4YW1wbGVzOlxuICogVGhlIGZ1bGwgYmxvd24gcGFnaW5hdGlvbiBpdGVtcyBjb250YWluIHRoZSBmb2xsb3cgZWxlbWVudHM6XG4gKlxuICogYMKrIOKAuSAxIC4uLiA0ICg1KSA2IC4uLiA5IOKAuiDCu2BcbiAqXG4gKiBUaGlzIGluY2x1ZGVzIHBhZ2luYXRpb24gaXRlbXMgdG8gdGhlIGZvbGxvd2luZyBwYWdlczpcbiAqIC0gc3RhcnQgcGFnZVxuICogLSBwcmV2aW91cyBwYWdlXG4gKiAtIGZpcnN0IHBhZ2VcbiAqIC0gcGFnZSByYW5nZVxuICogLSBsYXN0IHBhZ2VcbiAqIC0gbmV4dCBwYWdlXG4gKiAtIGVuZCBwYWdlXG4gKlxuICogQWxsIG9mIHRob3NlIGxpbmtzIGFyZSBjb25maWd1cmFibGUsIGluY2x1ZGluZyB0aGUgc2l6ZSBvZiB0aGUgcGFnZSByYW5nZS5cbiAqIFRoZSBjdXJyZW50IHBhZ2Ugd2lsbCBhbHdheXMgYmUgY2VudGVyZWQgaW4gdGhlIHBhZ2UgcmFuZ2UgdG8gcHJvdmlkZSBkaXJlY3QgYWNjZXNzXG4gKiB0byB0aGUgcHJldmlvdXMgYW5kIG5leHQgcGFnZS5cbiAqL1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIFBhZ2luYXRpb25CdWlsZGVyIHtcbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIHBhZ2luYXRpb25Db25maWc6IFBhZ2luYXRpb25Db25maWcpIHt9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyBhIGxpc3Qgb2YgYFBhZ2luYXRpb25JdGVtYC4gVGhlIGdpdmUgcGFnZUNvdW50IGFuZCBjdXJyZW50IGFyZSB1c2VkXG4gICAqIHRvIGJ1aWxkIG91dCB0aGUgZnVsbCBwYWdpbmF0aW9uLiBUaGVyZSBhcmUgdmFyaW91cyB7QGxpbmsgUGFnaW5hdGlvbkNvbmZpZ30gb3B0aW9uc1xuICAgKiB3aGljaCBjYW4gYmUgdXNlZCB0byBjb25maWd1cmUgdGhlIGJlaGF2aW9yIG9mIHRoZSBidWlsZC4gQWx0ZXJuYXRpdmVseSwgQ1NTXG4gICAqIGNhbiBiZSB1c2VkIHRvIGZ1cnRoZXIgc3BlY2lhbGl6ZSB2aXNpYmlsaXR5IG9mIHRoZSBwYWdpbmF0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gcGFnZUNvdW50IFRoZSB0b3RhbCBudW1iZXIgb2YgcGFnZXNcbiAgICogQHBhcmFtIGN1cnJlbnQgVGhlIGN1cnJlbnQgcGFnZSBudW1iZXIsIDAtaW5kZXggYmFzZWRcbiAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgYFBhZ2luYXRpb25JdGVtYFxuICAgKi9cbiAgcGFnaW5hdGUocGFnZUNvdW50OiBudW1iZXIsIGN1cnJlbnQ6IG51bWJlcik6IFBhZ2luYXRpb25JdGVtW10ge1xuICAgIGNvbnN0IHBhZ2VzOiBQYWdpbmF0aW9uSXRlbVtdID0gW107XG4gICAgaWYgKCFwYWdlQ291bnQgfHwgcGFnZUNvdW50IDwgMikge1xuICAgICAgcmV0dXJuIHBhZ2VzO1xuICAgIH1cbiAgICB0aGlzLmFkZFBhZ2VzKHBhZ2VzLCBwYWdlQ291bnQsIGN1cnJlbnQpO1xuICAgIHRoaXMuYWRkRG90cyhwYWdlcywgcGFnZUNvdW50KTtcbiAgICB0aGlzLmFkZEZpcnN0TGFzdChwYWdlcywgcGFnZUNvdW50KTtcbiAgICB0aGlzLmFkZE5hdmlnYXRpb24ocGFnZXMsIHBhZ2VDb3VudCwgY3VycmVudCk7XG5cbiAgICByZXR1cm4gcGFnZXM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCBwYWdlIHdpdGggc3Vycm91bmRpbmcgcGFnZXMgKGJhc2VkIG9uIHRoZSBgY29uZmlnLnJhbmdlQ291bnRgKS5cbiAgICogVGhlIGN1cnJlbnQgcGFnZSBpcyBhbHdheXMgY2VudGVyZWQgdG8gcHJvdmlkZSBkaXJlY3QgYWNjZXNzIHRvIHRoZSBwcmV2aW91cyBhbmQgbmV4dCBwYWdlLlxuICAgKlxuICAgKiBAcGFyYW0gcGFnZXMgVGhlIGxpc3Qgb2YgcGFnZSBpdGVtcyB0aGF0IGlzIHVzZWQgdG8gYW1lbmRcbiAgICogQHBhcmFtIHBhZ2VDb3VudCBUaGUgdG90YWwgbnVtYmVyIG9mIHBhZ2VzXG4gICAqIEBwYXJhbSBjdXJyZW50IFRoZSBjdXJyZW50IHBhZ2UgbnVtYmVyLCAwLWluZGV4IGJhc2VkXG4gICAqL1xuICBwcm90ZWN0ZWQgYWRkUGFnZXMoXG4gICAgcGFnZXM6IFBhZ2luYXRpb25JdGVtW10sXG4gICAgcGFnZUNvdW50OiBudW1iZXIsXG4gICAgY3VycmVudDogbnVtYmVyXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5nZXRTdGFydE9mUmFuZ2UocGFnZUNvdW50LCBjdXJyZW50KTtcbiAgICBjb25zdCBtYXggPSBNYXRoLm1pbih0aGlzLmNvbmZpZy5yYW5nZUNvdW50LCBwYWdlQ291bnQpO1xuICAgIEFycmF5LmZyb20oQXJyYXkobWF4KSkuZm9yRWFjaCgoXywgaSkgPT4ge1xuICAgICAgcGFnZXMucHVzaCh7XG4gICAgICAgIG51bWJlcjogaSArIHN0YXJ0LFxuICAgICAgICBsYWJlbDogU3RyaW5nKGkgKyBzdGFydCArIDEpLFxuICAgICAgICB0eXBlOiBQYWdpbmF0aW9uSXRlbVR5cGUuUEFHRSxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgZG90cyBiZWZvcmUgYW5kIGFmdGVyIHRoZSBnaXZlbiBwYWdlcywgaWYgY29uZmlndXJlZCAoZGVmYXVsdHMgdG8gdHJ1ZSkuXG4gICAqIElmIHRoZSBkb3RzIG9ubHkgcmVwcmVzZW50IGEgc2luZ2xlIHBhZ2UsIHRoZSBwYWdlIG51bWJlciBpcyBhZGRlZCBpbnN0ZWFkIG9mXG4gICAqIHRoZSBkb3RzLCB1bmxlc3MgdGhlIGNvbmZpZ3VyYXRpb24gcmVxdWlyZXMgZG90cyBhbHdheXMuXG4gICAqXG4gICAqIEBwYXJhbSBwYWdlcyBUaGUgbGlzdCBvZiBwYWdlIGl0ZW1zIHRoYXQgaXMgdXNlZCB0byBhbWVuZFxuICAgKiBAcGFyYW0gcGFnZUNvdW50IFRoZSB0b3RhbCBudW1iZXIgb2YgcGFnZXNcbiAgICovXG4gIHByb3RlY3RlZCBhZGREb3RzKHBhZ2VzOiBQYWdpbmF0aW9uSXRlbVtdLCBwYWdlQ291bnQ6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICghdGhpcy5jb25maWcuYWRkRG90cykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGFkZEZpcnN0R2FwID0gKCkgPT4ge1xuICAgICAgY29uc3QgZmlyc3RJdGVtTnVtYmVyID0gcGFnZXNbMF0ubnVtYmVyO1xuICAgICAgY29uc3QgZ2FwTnVtYmVyID0gdGhpcy5jb25maWcuYWRkRmlyc3QgPyAxIDogMDtcbiAgICAgIGlmIChmaXJzdEl0ZW1OdW1iZXIgPiBnYXBOdW1iZXIpIHtcbiAgICAgICAgY29uc3QgaXNHYXAgPVxuICAgICAgICAgICF0aGlzLmNvbmZpZy5zdWJzdGl0dXRlRG90c0ZvclNpbmd1bGFyUGFnZSB8fFxuICAgICAgICAgIGZpcnN0SXRlbU51bWJlciAhPT0gZ2FwTnVtYmVyICsgMTtcbiAgICAgICAgY29uc3QgaXNTdWJzdGl0dXRlZCA9XG4gICAgICAgICAgdGhpcy5jb25maWcuYWRkRmlyc3QgJiZcbiAgICAgICAgICB0aGlzLmNvbmZpZy5zdWJzdGl0dXRlRG90c0ZvclNpbmd1bGFyUGFnZSAmJlxuICAgICAgICAgIGdhcE51bWJlciA9PT0gMDtcbiAgICAgICAgY29uc3QgdHlwZSA9IGlzR2FwXG4gICAgICAgICAgPyBQYWdpbmF0aW9uSXRlbVR5cGUuR0FQXG4gICAgICAgICAgOiBpc1N1YnN0aXR1dGVkXG4gICAgICAgICAgPyBQYWdpbmF0aW9uSXRlbVR5cGUuRklSU1RcbiAgICAgICAgICA6IFBhZ2luYXRpb25JdGVtVHlwZS5QQUdFO1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgIE9iamVjdC5hc3NpZ24oXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGxhYmVsOiBpc0dhcCA/IHRoaXMuY29uZmlnLmRvdHNMYWJlbCA6IFN0cmluZyhnYXBOdW1iZXIgKyAxKSxcbiAgICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpc0dhcCA/IG51bGwgOiB7IG51bWJlcjogZ2FwTnVtYmVyIH1cbiAgICAgICAgICApLFxuICAgICAgICBdO1xuICAgICAgfSBlbHNlIHJldHVybiBbXTtcbiAgICB9O1xuXG4gICAgY29uc3QgYWRkTGFzdEdhcCA9ICgpID0+IHtcbiAgICAgIGNvbnN0IG5leHRQYWdlTnVtYmVyID0gcGFnZXNbcGFnZXMubGVuZ3RoIC0gMV0ubnVtYmVyICsgMTtcbiAgICAgIGNvbnN0IGxhc3QgPSBwYWdlQ291bnQgLSAodGhpcy5jb25maWcuYWRkTGFzdCA/IDIgOiAxKTtcbiAgICAgIGlmIChuZXh0UGFnZU51bWJlciA8PSBsYXN0KSB7XG4gICAgICAgIGNvbnN0IGlzU3Vic3RpdHV0ZWQgPVxuICAgICAgICAgIHRoaXMuY29uZmlnLmFkZExhc3QgJiZcbiAgICAgICAgICB0aGlzLmNvbmZpZy5zdWJzdGl0dXRlRG90c0ZvclNpbmd1bGFyUGFnZSAmJlxuICAgICAgICAgIG5leHRQYWdlTnVtYmVyID09PSBsYXN0O1xuICAgICAgICBjb25zdCBpc0dhcCA9XG4gICAgICAgICAgbmV4dFBhZ2VOdW1iZXIgPFxuICAgICAgICAgIHBhZ2VDb3VudCAtXG4gICAgICAgICAgICAodGhpcy5jb25maWcuc3Vic3RpdHV0ZURvdHNGb3JTaW5ndWxhclBhZ2UgPyAxIDogMCkgLVxuICAgICAgICAgICAgKHRoaXMuY29uZmlnLmFkZExhc3QgPyAxIDogMCk7XG5cbiAgICAgICAgY29uc3QgdHlwZSA9IGlzR2FwXG4gICAgICAgICAgPyBQYWdpbmF0aW9uSXRlbVR5cGUuR0FQXG4gICAgICAgICAgOiBpc1N1YnN0aXR1dGVkXG4gICAgICAgICAgPyBQYWdpbmF0aW9uSXRlbVR5cGUuTEFTVFxuICAgICAgICAgIDogUGFnaW5hdGlvbkl0ZW1UeXBlLlBBR0U7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgT2JqZWN0LmFzc2lnbihcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbGFiZWw6IGlzR2FwID8gdGhpcy5jb25maWcuZG90c0xhYmVsIDogU3RyaW5nKG5leHRQYWdlTnVtYmVyICsgMSksXG4gICAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaXNHYXAgPyBudWxsIDogeyBudW1iZXI6IG5leHRQYWdlTnVtYmVyIH1cbiAgICAgICAgICApLFxuICAgICAgICBdO1xuICAgICAgfSBlbHNlIHJldHVybiBbXTtcbiAgICB9O1xuXG4gICAgcGFnZXMudW5zaGlmdCguLi5hZGRGaXJzdEdhcCgpKTtcbiAgICBwYWdlcy5wdXNoKC4uLmFkZExhc3RHYXAoKSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGxpbmtzIHRvIHRoZSBmaXJzdCBhbmQgbGFzdCBwYWdlLCBpZiBjb25maWd1cmVkIHRvIGRvIHNvLlxuICAgKlxuICAgKiBAcGFyYW0gcGFnZXMgVGhlIGxpc3Qgb2YgcGFnZSBpdGVtcyB0aGF0IGlzIHVzZWQgdG8gYW1lbmRcbiAgICogQHBhcmFtIHBhZ2VDb3VudCBUaGUgdG90YWwgbnVtYmVyIG9mIHBhZ2VzXG4gICAqXG4gICAqL1xuICBwcm90ZWN0ZWQgYWRkRmlyc3RMYXN0KHBhZ2VzOiBQYWdpbmF0aW9uSXRlbVtdLCBwYWdlQ291bnQ6IG51bWJlcikge1xuICAgIGlmICh0aGlzLmNvbmZpZy5hZGRGaXJzdCAmJiBwYWdlc1swXS5udW1iZXIgIT09IDApIHtcbiAgICAgIHBhZ2VzLnVuc2hpZnQoe1xuICAgICAgICBudW1iZXI6IDAsXG4gICAgICAgIGxhYmVsOiAnMScsXG4gICAgICAgIHR5cGU6IFBhZ2luYXRpb25JdGVtVHlwZS5GSVJTVCxcbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICB0aGlzLmNvbmZpZy5hZGRMYXN0ICYmXG4gICAgICBwYWdlc1twYWdlcy5sZW5ndGggLSAxXS5udW1iZXIgIT09IHBhZ2VDb3VudCAtIDFcbiAgICApIHtcbiAgICAgIHBhZ2VzLnB1c2goe1xuICAgICAgICBudW1iZXI6IHBhZ2VDb3VudCAtIDEsXG4gICAgICAgIGxhYmVsOiBTdHJpbmcocGFnZUNvdW50KSxcbiAgICAgICAgdHlwZTogUGFnaW5hdGlvbkl0ZW1UeXBlLkxBU1QsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkIGxpbmtzIHRvIHRoZSBzdGFydCwgcHJldmlvdXMsIG5leHQgYW5kIGxhc3QgcGFnZSwgaWYgY29uZmlndXJlZCB0byBkbyBzby5cbiAgICogVGhlIG9yZGVyIG9mIHRoZSBsaW5rcyBjYW4gYmUgY29uZmlndXJlZCBieSB1c2luZyB0aGUge0BsaW5rIFBhZ2luYXRpb25Db25maWd9LFxuICAgKiB1c2luZyB0aGUgYFBhZ2luYXRpb25OYXZpZ2F0aW9uUG9zaXRpb25gIChgQkVGT1JFYCBvciBgQUZURVJgKS5cbiAgICogVGhlIGBQYWdpbmF0aW9uTmF2aWdhdGlvblBvc2l0aW9uYCBhbGxvd3MgZm9yIDMgZmxhdm91cnM6XG4gICAqXG4gICAqIC0gYnkgZGVmYXVsdCB0aGUgcGFnaW5hdGlvbiBzdGFydHMgd2l0aCBzdGFydCBhbmQgcHJldmlvdXMgYW5kIGVuZHMgd2l0aCB0aGUgbmV4dCBhbmQgZW5kIGxpbmtzXG4gICAqIC0gQkVGT1JFIOKAk8KgYWxsIG5hdmlnYXRpb24gbGlua3MgYXJlIGFkZGVkIGluIHRoZSBmcm9udCBvZiB0aGUgcGFnaW5hdGlvbiBsaXN0XG4gICAqIC0gQUZURVIg4oCTwqBhbGwgbmF2aWdhdGlvbiBsaW5rcyBhcmUgcHVzaGVkIHRvIHRoZSBlbmQgb2YgdGhlIHBhZ2luYXRpb24gbGlzdFxuICAgKlxuICAgKiBAcGFyYW0gcGFnZXMgVGhlIGxpc3Qgb2YgcGFnZSBpdGVtcyB0aGF0IGlzIHVzZWQgdG8gYW1lbmRcbiAgICogQHBhcmFtIHBhZ2VDb3VudCBUaGUgdG90YWwgbnVtYmVyIG9mIHBhZ2VzXG4gICAqIEBwYXJhbSBjdXJyZW50IFRoZSBjdXJyZW50IHBhZ2UgbnVtYmVyLCAwLWluZGV4IGJhc2VkXG4gICAqXG4gICAqL1xuICBwcm90ZWN0ZWQgYWRkTmF2aWdhdGlvbihcbiAgICBwYWdlczogUGFnaW5hdGlvbkl0ZW1bXSxcbiAgICBwYWdlQ291bnQ6IG51bWJlcixcbiAgICBjdXJyZW50OiBudW1iZXJcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgYmVmb3JlID0gdGhpcy5nZXRCZWZvcmVMaW5rcyhjdXJyZW50KTtcbiAgICBjb25zdCBhZnRlciA9IHRoaXMuZ2V0QWZ0ZXJMaW5rcyhwYWdlQ291bnQsIGN1cnJlbnQpO1xuICAgIGNvbnN0IHBvcyA9IHRoaXMuY29uZmlnLm5hdmlnYXRpb25Qb3NpdGlvbjtcbiAgICBpZiAoIXBvcyB8fCBwb3MgPT09IFBhZ2luYXRpb25OYXZpZ2F0aW9uUG9zaXRpb24uQVNJREUpIHtcbiAgICAgIHBhZ2VzLnVuc2hpZnQoLi4uYmVmb3JlKTtcbiAgICAgIHBhZ2VzLnB1c2goLi4uYWZ0ZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAocG9zID09PSBQYWdpbmF0aW9uTmF2aWdhdGlvblBvc2l0aW9uLkJFRk9SRSkge1xuICAgICAgICBwYWdlcy51bnNoaWZ0KC4uLmJlZm9yZSwgLi4uYWZ0ZXIpO1xuICAgICAgfVxuICAgICAgaWYgKHBvcyA9PT0gUGFnaW5hdGlvbk5hdmlnYXRpb25Qb3NpdGlvbi5BRlRFUikge1xuICAgICAgICBwYWdlcy5wdXNoKC4uLmJlZm9yZSwgLi4uYWZ0ZXIpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzdGFydCBhbmQgcHJldmlvdXMgbGlua3MsIGlmIGFwcGxpY2FibGUuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0QmVmb3JlTGlua3MoY3VycmVudDogbnVtYmVyKTogUGFnaW5hdGlvbkl0ZW1bXSB7XG4gICAgY29uc3QgbGlzdCA9IFtdO1xuXG4gICAgaWYgKHRoaXMuY29uZmlnLmFkZFN0YXJ0KSB7XG4gICAgICBjb25zdCBzdGFydCA9ICgpID0+IHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oXG4gICAgICAgICAge1xuICAgICAgICAgICAgbGFiZWw6IHRoaXMuY29uZmlnLnN0YXJ0TGFiZWwsXG4gICAgICAgICAgICB0eXBlOiBQYWdpbmF0aW9uSXRlbVR5cGUuU1RBUlQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBjdXJyZW50ID4gMCA/IHsgbnVtYmVyOiAwIH0gOiBudWxsXG4gICAgICAgICk7XG4gICAgICB9O1xuICAgICAgbGlzdC5wdXNoKHN0YXJ0KCkpO1xuICAgIH1cbiAgICBpZiAodGhpcy5jb25maWcuYWRkUHJldmlvdXMpIHtcbiAgICAgIGNvbnN0IHByZXZpb3VzID0gKCkgPT4ge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihcbiAgICAgICAgICB7XG4gICAgICAgICAgICBsYWJlbDogdGhpcy5jb25maWcucHJldmlvdXNMYWJlbCxcbiAgICAgICAgICAgIHR5cGU6IFBhZ2luYXRpb25JdGVtVHlwZS5QUkVWSU9VUyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGN1cnJlbnQgPiAwID8geyBudW1iZXI6IGN1cnJlbnQgLSAxIH0gOiBudWxsXG4gICAgICAgICk7XG4gICAgICB9O1xuICAgICAgbGlzdC5wdXNoKHByZXZpb3VzKCkpO1xuICAgIH1cbiAgICByZXR1cm4gbGlzdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBuZXh0IGFuZCBlbmQgbGlua3MsIGlmIGFwcGxpY2FibGUuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0QWZ0ZXJMaW5rcyhcbiAgICBwYWdlQ291bnQ6IG51bWJlcixcbiAgICBjdXJyZW50OiBudW1iZXJcbiAgKTogUGFnaW5hdGlvbkl0ZW1bXSB7XG4gICAgY29uc3QgbGlzdCA9IFtdO1xuXG4gICAgaWYgKHRoaXMuY29uZmlnLmFkZE5leHQpIHtcbiAgICAgIGNvbnN0IG5leHQgPSAoKSA9PiB7XG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGxhYmVsOiB0aGlzLmNvbmZpZy5uZXh0TGFiZWwsXG4gICAgICAgICAgICB0eXBlOiBQYWdpbmF0aW9uSXRlbVR5cGUuTkVYVCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGN1cnJlbnQgPCBwYWdlQ291bnQgLSAxID8geyBudW1iZXI6IGN1cnJlbnQgKyAxIH0gOiBudWxsXG4gICAgICAgICk7XG4gICAgICB9O1xuICAgICAgbGlzdC5wdXNoKG5leHQoKSk7XG4gICAgfVxuICAgIGlmICh0aGlzLmNvbmZpZy5hZGRFbmQpIHtcbiAgICAgIGNvbnN0IGVuZCA9ICgpID0+IHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oXG4gICAgICAgICAge1xuICAgICAgICAgICAgbGFiZWw6IHRoaXMuY29uZmlnLmVuZExhYmVsLFxuICAgICAgICAgICAgdHlwZTogUGFnaW5hdGlvbkl0ZW1UeXBlLkVORCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGN1cnJlbnQgPCBwYWdlQ291bnQgLSAxID8geyBudW1iZXI6IHBhZ2VDb3VudCAtIDEgfSA6IG51bGxcbiAgICAgICAgKTtcbiAgICAgIH07XG4gICAgICBsaXN0LnB1c2goZW5kKCkpO1xuICAgIH1cblxuICAgIHJldHVybiBsaXN0O1xuICB9XG4gIC8qKlxuICAgKiBSZXNvbHZlcyB0aGUgZmlyc3QgcGFnZSBvZiB0aGUgcmFuZ2Ugd2UgbmVlZCB0byBidWlsZC5cbiAgICogVGhpcyBpcyB0aGUgcGFnZSB0aGF0IGlzIGxlYWRpbmcgdXAgdG8gdGhlIHJhbmdlIG9mIHRoZVxuICAgKiBjdXJyZW50IHBhZ2UuXG4gICAqXG4gICAqIEBwYXJhbSBwYWdlQ291bnQgVGhlIHRvdGFsIG51bWJlciBvZiBwYWdlcy5cbiAgICogQHBhcmFtIGN1cnJlbnQgVGhlIGN1cnJlbnQgcGFnZSBudW1iZXIsIDAtaW5kZXggYmFzZWQuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0U3RhcnRPZlJhbmdlKHBhZ2VDb3VudDogbnVtYmVyLCBjdXJyZW50OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IGNvdW50ID0gdGhpcy5jb25maWcucmFuZ2VDb3VudCAtIDE7XG4gICAgLy8gdGhlIGxlYXN0IG51bWJlciBvZiBwYWdlcyBiZWZvcmUgYW5kIGFmdGVyIHRoZSBjdXJyZW50XG4gICAgY29uc3QgZGVsdGEgPSBNYXRoLnJvdW5kKGNvdW50IC8gMik7XG5cbiAgICAvLyBlbnN1cmUgdGhhdCB3ZSBzdGFydCB3aXRoIGF0IGxlYXN0IHRoZSBmaXJzdCBwYWdlXG4gICAgY29uc3QgbWluU3RhcnQgPSBNYXRoLm1heCgwLCBjdXJyZW50IC0gZGVsdGEpO1xuICAgIC8vIGVuc3VyZXMgdGhhdCB3ZSBzdGFydCB3aXRoIGF0IGxlYXN0IDEgYW5kIGRvIG5vdCBwYXNzIHRoZSBsYXN0IHJhbmdlXG4gICAgY29uc3QgbWF4U3RhcnQgPSBNYXRoLm1heCgwLCBwYWdlQ291bnQgLSBjb3VudCAtIDEpO1xuXG4gICAgLy8gZW5zdXJlIHRoYXQgd2UgZ2V0IGF0IGxlYXN0IGEgZnVsbCByYW5nZSBhdCB0aGUgZW5kXG4gICAgcmV0dXJuIE1hdGgubWluKG1heFN0YXJ0LCBtaW5TdGFydCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgcGFnaW5hdGlvbiBjb25maWd1cmF0aW9uLiBUaGUgY29uZmlndXJhdGlvbiBpcyBkcml2ZW4gYnkgdGhlXG4gICAqIChkZWZhdWx0KSBhcHBsaWNhdGlvbiBjb25maWd1cmF0aW9uLlxuICAgKlxuICAgKiBUaGUgZGVmYXVsdCBhcHBsaWNhdGlvbiBpcyBsaW1pdGVkIHRvIGFkZGluZyB0aGUgc3RhcnQgYW5kIGVuZCBsaW5rOlxuICAgKiBgYGB0c1xuICAgKiAgIGFkZFN0YXJ0OiB0cnVlLFxuICAgKiAgIGFkZEVuZDogdHJ1ZVxuICAgKiBgYGBcbiAgICpcbiAgICogVGhlIGFwcGxpY2F0aW9uIGNvbmZpZ3VyYXRpb24gaXMgaG93ZXZlciBtZXJnZWQgaW50byB0aGUgZm9sbG93aW5nIHN0YXRpYyBjb25maWd1cmF0aW9uOlxuICAgKiBgYGB0c1xuICAgKiB7XG4gICAqICAgcmFuZ2VDb3VudDogMyxcbiAgICogICBkb3RzTGFiZWw6ICcuLi4nLFxuICAgKiAgIHN0YXJ0TGFiZWw6ICfCqycsXG4gICAqICAgcHJldmlvdXNMYWJlbDogJ+KAuScsXG4gICAqICAgbmV4dExhYmVsOiAn4oC6JyxcbiAgICogICBlbmRMYWJlbDogJ8K7J1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgcHJvdGVjdGVkIGdldCBjb25maWcoKTogUGFnaW5hdGlvbk9wdGlvbnMge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKFxuICAgICAgRkFMTEJBQ0tfUEFHSU5BVElPTl9PUFRJT05TLFxuICAgICAgdGhpcy5wYWdpbmF0aW9uQ29uZmlnLnBhZ2luYXRpb25cbiAgICApO1xuICB9XG59XG4iXX0=