@edugouvfr/ngx-dsfr
Version:
NgxDsfr est un portage Angular des éléments d'interface du Système de Design de l'État Français (DSFR).
116 lines • 35.7 kB
JavaScript
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
import { RouterModule } from '@angular/router';
import { DsfrDisableRouterLinkDirective, DsfrPositionConst, newUniqueId } from '../../shared';
import { DsfrLinkComponent } from '../link';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/router";
export class DsfrSidemenuComponent {
constructor() {
/** Attribut aria-label du menu latéral. */
this.ariaLabel = 'Menu latéral';
/** Affiche le menu latéral en version fixe */
this.sticky = false;
/** Affiche le menu latéral en version fixe sur 100% de la hauteur de la page. */
this.stickyFullHeight = false;
/** Le menu latéral est affiché à gauche par défaut mais il est possible de l'afficher à droite. */
this.position = DsfrPositionConst.LEFT;
/** Activer la selection automatique des items et parents (si absence de routerLink) */
this.autoActive = true;
/** Evénement émis suite à la sélection d'un item avec lien */
this.itemSelect = new EventEmitter();
/** Duplication des items de menu pour ne pas modifier le modèle menu en entrée */
this.cloneMenuItems = [];
}
get menu() {
return this._menu;
}
/** Modèle de donnée du menu. */
set menu(value) {
this._menu = value;
if (this._menu && this._menu.items) {
this.cloneMenuItems = this._menu.items.map((item) => this.cloneMenuItem(item));
if (this._initialActiveItem && this.autoActive)
this.selectItem(this._initialActiveItem);
}
}
onSelectItem(item) {
if (this.autoActive && !item.routerLink) {
this.selectItem(item);
this.cloneMenuItems = [...this.cloneMenuItems];
}
this.itemSelect.emit(item);
}
/** Dupliquer les items de menu pour ne pas modifier le modèle en entrée */
cloneMenuItem(item) {
const clonedItem = {
...item,
active: this.autoActive ? !!(item.active && !item.subItems) : item.active,
controlId: item.controlId ?? newUniqueId(),
subItems: item.subItems ? item.subItems.map((sub) => this.cloneMenuItem(sub)) : undefined,
};
if (clonedItem.active && !clonedItem.subItems) {
this._initialActiveItem = clonedItem;
}
return clonedItem;
}
/** A la selection d'un item si autoActive :
* - on passe le précédent item sélectionné _prevItemSelected en désactivé ainsi que ses parents (trois niveaux potentiels)
* - nouvel item et ses parents en actif
* - mise a jour de _prevItemSelected
*/
selectItem(item) {
if (this._prevItemSelected) {
this.activateItem(this._prevItemSelected, false);
}
this.activateItem(item, true);
this._prevItemSelected = item;
}
/** Désactiver ou activer un item et ses noeuds parents */
activateItem(item, activate) {
item.active = activate;
const parent = this.findParent(item, this.cloneMenuItems);
if (parent) {
this.activateItem(parent, activate);
}
}
/**
* Parcours récursif du menu pour retrouver le parent direct d'un item
*/
findParent(item, items) {
for (const parent of items) {
if (parent.subItems?.includes(item)) {
return parent;
}
const foundParent = this.findParent(item, parent.subItems || []);
if (foundParent) {
return foundParent;
}
}
return undefined;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DsfrSidemenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DsfrSidemenuComponent, isStandalone: true, selector: "dsfr-sidemenu", inputs: { ariaLabel: "ariaLabel", controlId: "controlId", sticky: "sticky", stickyFullHeight: "stickyFullHeight", position: "position", autoActive: "autoActive", menu: "menu" }, outputs: { itemSelect: "itemSelect" }, ngImport: i0, template: "<nav\n class=\"fr-sidemenu\"\n [ngClass]=\"{\n 'fr-sidemenu--sticky': sticky,\n 'fr-sidemenu--sticky-full-height': stickyFullHeight,\n 'fr-sidemenu--right': position === 'right',\n }\"\n role=\"navigation\"\n [attr.aria-labelledBy]=\"menu.title ? 'sidemenu-title-' + controlId : null\"\n [attr.aria-label]=\"menu.title ? null : ariaLabel\">\n <div class=\"fr-sidemenu__inner\">\n <button type=\"button\" class=\"fr-sidemenu__btn\" [attr.aria-controls]=\"'sidemenu-' + controlId\" aria-expanded=\"false\">\n Dans cette rubrique\n </button>\n <div class=\"fr-collapse\" [id]=\"'sidemenu-' + controlId\">\n <!--Titre de rubrique optionnel-->\n @if (menu && menu.title) {\n <p class=\"fr-sidemenu__title\" [id]=\"'sidemenu-title-' + controlId\">{{ menu.title }}</p>\n }\n <!--Niveau 1-->\n <ul class=\"fr-sidemenu__list\">\n @for (item1 of cloneMenuItems; track item1) {\n @if (!item1.subItems) {\n <li class=\"fr-sidemenu__item\">\n <ng-container [ngTemplateOutlet]=\"linkMenu\" [ngTemplateOutletContext]=\"{ item: item1 }\"></ng-container>\n </li>\n } @else {\n <li class=\"fr-sidemenu__item\">\n <!--Niveau 2-->\n <ng-container [ngTemplateOutlet]=\"buttonMenu\" [ngTemplateOutletContext]=\"{ item: item1 }\"></ng-container>\n <div class=\"fr-collapse\" [id]=\"item1.controlId\">\n <!--Titre de rubrique optionnel-->\n @if (item1.title) {\n <div class=\"fr-sidemenu__title\">{{ item1.title }}</div>\n }\n <ul class=\"fr-sidemenu__list\">\n @for (item2 of item1.subItems; track item2) {\n @if (!item2.subItems) {\n <li class=\"fr-sidemenu__item\">\n <ng-container\n [ngTemplateOutlet]=\"linkMenu\"\n [ngTemplateOutletContext]=\"{ item: item2 }\"></ng-container>\n </li>\n } @else {\n <li class=\"fr-sidemenu__item\">\n <ng-container\n [ngTemplateOutlet]=\"buttonMenu\"\n [ngTemplateOutletContext]=\"{ item: item2 }\"></ng-container>\n\n <div class=\"fr-collapse\" [id]=\"item2.controlId\">\n @if (item2.title) {\n <div class=\"fr-sidemenu__title\">{{ item2.title }}</div>\n }\n <!--Niveau 3-->\n <ul class=\"fr-sidemenu__list\">\n @for (item3 of item2.subItems; track item3) {\n <li class=\"fr-sidemenu__item\" [attr.aria-current]=\"item3.active ? 'page' : null\">\n <ng-container\n [ngTemplateOutlet]=\"linkMenu\"\n [ngTemplateOutletContext]=\"{ item: item3 }\"></ng-container>\n </li>\n }\n </ul>\n </div>\n </li>\n }\n }\n </ul>\n </div>\n </li>\n }\n }\n </ul>\n </div>\n </div>\n</nav>\n\n<ng-template #buttonMenu let-item=\"item\" let-index=\"index\">\n <button\n type=\"button\"\n class=\"fr-sidemenu__btn\"\n aria-expanded=\"false\"\n [attr.aria-controls]=\"item.controlId\"\n [disableNavigation]=\"true\"\n [attr.aria-current]=\"item.active && !item.routerLink ? true : null\"\n [routerLink]=\"item.routerLink\"\n [routerLinkActive]=\"item.routerLinkActive ?? ''\"\n [routerLinkActiveOptions]=\"item.routerLinkActiveOptions ? item.routerLinkActiveOptions : { exact: false }\"\n [ariaCurrentWhenActive]=\"true\">\n <i *ngIf=\"item.icon\" class=\"edu-item-icon\" [class]=\"item.icon\" aria-hidden=\"true\"></i>\n {{ item.label }}\n </button>\n</ng-template>\n\n<ng-template #linkMenu let-item=\"item\" let-index=\"index\">\n <dsfr-link\n [ariaControls]=\"item.ariaControls\"\n [ariaCurrent]=\"item.active && !item.routerLink ? 'page' : undefined\"\n [ariaLabel]=\"item.ariaLabel ?? ''\"\n [customClass]=\"'fr-sidemenu__link ' + (item.customClass ?? '')\"\n [disabled]=\"item.disabled\"\n [link]=\"item.link\"\n [linkId]=\"item.linkId\"\n [linkTarget]=\"item.linkTarget\"\n [label]=\"item.icon ? null : item.label\"\n [route]=\"item.route\"\n [routePath]=\"item.routerLink\"\n [routerLinkActive]=\"item.routerLinkActive ?? ''\"\n [routerLinkActiveOptions]=\"item.routerLinkActiveOptions ? item.routerLinkActiveOptions : { exact: false }\"\n [routerLinkExtras]=\"item.routerLinkExtras\"\n [tooltipMessage]=\"item.tooltipMessage\"\n (linkSelect)=\"onSelectItem(item)\">\n @if (item.iconPosition === 'left') {\n <i class=\"edu-item-icon\" [class]=\"item.icon\" aria-hidden=\"true\"></i>\n }\n @if (item.icon) {\n <span label> {{ item.label }}</span>\n }\n @if (item.iconPosition === 'right') {\n <i class=\"edu-item-icon edu-item-icon--right\" [class]=\"item.icon\" aria-hidden=\"true\"></i>\n }\n </dsfr-link>\n</ng-template>\n", styles: ["dsfr-sidemenu .edu-item-icon:before{--icon-size: 1rem;margin-right:.5rem}dsfr-sidemenu .edu-item-icon--right:before{margin-left:.5rem;margin-right:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: DsfrDisableRouterLinkDirective, selector: "button[routerLink][disableNavigation]", inputs: ["disableNavigation"] }, { kind: "component", type: DsfrLinkComponent, selector: "dsfr-link", inputs: ["ariaCurrent", "ariaLabel", "ariaControls", "customClass", "disabled", "icon", "iconPosition", "linkId", "label", "link", "linkTarget", "route", "routePath", "routerLinkActive", "routerLinkActiveOptions", "routerLinkExtras", "linkSize", "tooltipMessage", "mode", "ariaCurrentWhenActive", "size", "targetLink", "routerLink"], outputs: ["linkSelect"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DsfrSidemenuComponent, decorators: [{
type: Component,
args: [{ selector: 'dsfr-sidemenu', encapsulation: ViewEncapsulation.None, standalone: true, imports: [CommonModule, RouterModule, DsfrDisableRouterLinkDirective, DsfrLinkComponent], template: "<nav\n class=\"fr-sidemenu\"\n [ngClass]=\"{\n 'fr-sidemenu--sticky': sticky,\n 'fr-sidemenu--sticky-full-height': stickyFullHeight,\n 'fr-sidemenu--right': position === 'right',\n }\"\n role=\"navigation\"\n [attr.aria-labelledBy]=\"menu.title ? 'sidemenu-title-' + controlId : null\"\n [attr.aria-label]=\"menu.title ? null : ariaLabel\">\n <div class=\"fr-sidemenu__inner\">\n <button type=\"button\" class=\"fr-sidemenu__btn\" [attr.aria-controls]=\"'sidemenu-' + controlId\" aria-expanded=\"false\">\n Dans cette rubrique\n </button>\n <div class=\"fr-collapse\" [id]=\"'sidemenu-' + controlId\">\n <!--Titre de rubrique optionnel-->\n @if (menu && menu.title) {\n <p class=\"fr-sidemenu__title\" [id]=\"'sidemenu-title-' + controlId\">{{ menu.title }}</p>\n }\n <!--Niveau 1-->\n <ul class=\"fr-sidemenu__list\">\n @for (item1 of cloneMenuItems; track item1) {\n @if (!item1.subItems) {\n <li class=\"fr-sidemenu__item\">\n <ng-container [ngTemplateOutlet]=\"linkMenu\" [ngTemplateOutletContext]=\"{ item: item1 }\"></ng-container>\n </li>\n } @else {\n <li class=\"fr-sidemenu__item\">\n <!--Niveau 2-->\n <ng-container [ngTemplateOutlet]=\"buttonMenu\" [ngTemplateOutletContext]=\"{ item: item1 }\"></ng-container>\n <div class=\"fr-collapse\" [id]=\"item1.controlId\">\n <!--Titre de rubrique optionnel-->\n @if (item1.title) {\n <div class=\"fr-sidemenu__title\">{{ item1.title }}</div>\n }\n <ul class=\"fr-sidemenu__list\">\n @for (item2 of item1.subItems; track item2) {\n @if (!item2.subItems) {\n <li class=\"fr-sidemenu__item\">\n <ng-container\n [ngTemplateOutlet]=\"linkMenu\"\n [ngTemplateOutletContext]=\"{ item: item2 }\"></ng-container>\n </li>\n } @else {\n <li class=\"fr-sidemenu__item\">\n <ng-container\n [ngTemplateOutlet]=\"buttonMenu\"\n [ngTemplateOutletContext]=\"{ item: item2 }\"></ng-container>\n\n <div class=\"fr-collapse\" [id]=\"item2.controlId\">\n @if (item2.title) {\n <div class=\"fr-sidemenu__title\">{{ item2.title }}</div>\n }\n <!--Niveau 3-->\n <ul class=\"fr-sidemenu__list\">\n @for (item3 of item2.subItems; track item3) {\n <li class=\"fr-sidemenu__item\" [attr.aria-current]=\"item3.active ? 'page' : null\">\n <ng-container\n [ngTemplateOutlet]=\"linkMenu\"\n [ngTemplateOutletContext]=\"{ item: item3 }\"></ng-container>\n </li>\n }\n </ul>\n </div>\n </li>\n }\n }\n </ul>\n </div>\n </li>\n }\n }\n </ul>\n </div>\n </div>\n</nav>\n\n<ng-template #buttonMenu let-item=\"item\" let-index=\"index\">\n <button\n type=\"button\"\n class=\"fr-sidemenu__btn\"\n aria-expanded=\"false\"\n [attr.aria-controls]=\"item.controlId\"\n [disableNavigation]=\"true\"\n [attr.aria-current]=\"item.active && !item.routerLink ? true : null\"\n [routerLink]=\"item.routerLink\"\n [routerLinkActive]=\"item.routerLinkActive ?? ''\"\n [routerLinkActiveOptions]=\"item.routerLinkActiveOptions ? item.routerLinkActiveOptions : { exact: false }\"\n [ariaCurrentWhenActive]=\"true\">\n <i *ngIf=\"item.icon\" class=\"edu-item-icon\" [class]=\"item.icon\" aria-hidden=\"true\"></i>\n {{ item.label }}\n </button>\n</ng-template>\n\n<ng-template #linkMenu let-item=\"item\" let-index=\"index\">\n <dsfr-link\n [ariaControls]=\"item.ariaControls\"\n [ariaCurrent]=\"item.active && !item.routerLink ? 'page' : undefined\"\n [ariaLabel]=\"item.ariaLabel ?? ''\"\n [customClass]=\"'fr-sidemenu__link ' + (item.customClass ?? '')\"\n [disabled]=\"item.disabled\"\n [link]=\"item.link\"\n [linkId]=\"item.linkId\"\n [linkTarget]=\"item.linkTarget\"\n [label]=\"item.icon ? null : item.label\"\n [route]=\"item.route\"\n [routePath]=\"item.routerLink\"\n [routerLinkActive]=\"item.routerLinkActive ?? ''\"\n [routerLinkActiveOptions]=\"item.routerLinkActiveOptions ? item.routerLinkActiveOptions : { exact: false }\"\n [routerLinkExtras]=\"item.routerLinkExtras\"\n [tooltipMessage]=\"item.tooltipMessage\"\n (linkSelect)=\"onSelectItem(item)\">\n @if (item.iconPosition === 'left') {\n <i class=\"edu-item-icon\" [class]=\"item.icon\" aria-hidden=\"true\"></i>\n }\n @if (item.icon) {\n <span label> {{ item.label }}</span>\n }\n @if (item.iconPosition === 'right') {\n <i class=\"edu-item-icon edu-item-icon--right\" [class]=\"item.icon\" aria-hidden=\"true\"></i>\n }\n </dsfr-link>\n</ng-template>\n", styles: ["dsfr-sidemenu .edu-item-icon:before{--icon-size: 1rem;margin-right:.5rem}dsfr-sidemenu .edu-item-icon--right:before{margin-left:.5rem;margin-right:0}\n"] }]
}], propDecorators: { ariaLabel: [{
type: Input
}], controlId: [{
type: Input
}], sticky: [{
type: Input
}], stickyFullHeight: [{
type: Input
}], position: [{
type: Input
}], autoActive: [{
type: Input
}], itemSelect: [{
type: Output
}], menu: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lkZW1lbnUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWRzZnItY29tcG9uZW50cy9zcmMvbGliL2NvbXBvbmVudHMvc2lkZW1lbnUvc2lkZW1lbnUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWRzZnItY29tcG9uZW50cy9zcmMvbGliL2NvbXBvbmVudHMvc2lkZW1lbnUvc2lkZW1lbnUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSw4QkFBOEIsRUFBZ0IsaUJBQWlCLEVBQUUsV0FBVyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzVHLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFNBQVMsQ0FBQzs7OztBQVc1QyxNQUFNLE9BQU8scUJBQXFCO0lBUmxDO1FBU0UsNENBQTRDO1FBQ25DLGNBQVMsR0FBRyxjQUFjLENBQUM7UUFLcEMsK0NBQStDO1FBQ3RDLFdBQU0sR0FBRyxLQUFLLENBQUM7UUFFeEIsaUZBQWlGO1FBQ3hFLHFCQUFnQixHQUFHLEtBQUssQ0FBQztRQUVsQyxtR0FBbUc7UUFDMUYsYUFBUSxHQUFpQixpQkFBaUIsQ0FBQyxJQUFJLENBQUM7UUFFekQsdUZBQXVGO1FBQzlFLGVBQVUsR0FBRyxJQUFJLENBQUM7UUFFM0IsOERBQThEO1FBQ3BELGVBQVUsR0FBRyxJQUFJLFlBQVksRUFBZ0IsQ0FBQztRQUV4RCxrRkFBa0Y7UUFDeEUsbUJBQWMsR0FBbUIsRUFBRSxD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QyxJQUFrQixFQUFFLEtBQXFCO1FBQzFELEtBQUssTUFBTSxNQUFNLElBQUksS0FBSyxFQUFFLENBQUM7WUFDM0IsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUNwQyxPQUFPLE1BQU0sQ0FBQztZQUNoQixDQUFDO1lBQ0QsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUNqRSxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNoQixPQUFPLFdBQVcsQ0FBQztZQUNyQixDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7K0dBMUdVLHFCQUFxQjttR0FBckIscUJBQXFCLGtTQ2ZsQyxneEtBMkhBLGdORDlHWSxZQUFZLHVZQUFFLFlBQVksaWZBQUUsOEJBQThCLGlIQUFFLGlCQUFpQjs7NEZBRTVFLHFCQUFxQjtrQkFSakMsU0FBUzsrQkFDRSxlQUFlLGlCQUdWLGlCQUFpQixDQUFDLElBQUksY0FDekIsSUFBSSxXQUNQLENBQUMsWUFBWSxFQUFFLFlBQVksRUFBRSw4QkFBOEIsRUFBRSxpQkFBaUIsQ0FBQzs4QkFJL0UsU0FBUztzQkFBakIsS0FBSztnQkFHRyxTQUFTO3NCQUFqQixLQUFLO2dCQUdHLE1BQU07c0JBQWQsS0FBSztnQkFHRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBR0csUUFBUTtzQkFBaEIsS0FBSztnQkFHRyxVQUFVO3NCQUFsQixLQUFLO2dCQUdJLFVBQVU7c0JBQW5CLE1BQU07Z0JBZ0JNLElBQUk7c0JBQWhCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgQ29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIElucHV0LCBPdXRwdXQsIFZpZXdFbmNhcHN1bGF0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBSb3V0ZXJNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgRHNmckRpc2FibGVSb3V0ZXJMaW5rRGlyZWN0aXZlLCBEc2ZyUG9zaXRpb24sIERzZnJQb3NpdGlvbkNvbnN0LCBuZXdVbmlxdWVJZCB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBEc2ZyTGlua0NvbXBvbmVudCB9IGZyb20gJy4uL2xpbmsnO1xuaW1wb3J0IHsgRHNmck1lbnUsIERzZnJNZW51SXRlbSB9IGZyb20gJy4vbWVudS5tb2RlbCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2RzZnItc2lkZW1lbnUnLFxuICB0ZW1wbGF0ZVVybDogJy4vc2lkZW1lbnUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9zaWRlbWVudS5jb21wb25lbnQuc2NzcyddLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBSb3V0ZXJNb2R1bGUsIERzZnJEaXNhYmxlUm91dGVyTGlua0RpcmVjdGl2ZSwgRHNmckxpbmtDb21wb25lbnRdLFxufSlcbmV4cG9ydCBjbGFzcyBEc2ZyU2lkZW1lbnVDb21wb25lbnQge1xuICAvKiogQXR0cmlidXQgYXJpYS1sYWJlbCBkdSBtZW51IGxhdMOpcmFsLiAgKi9cbiAgQElucHV0KCkgYXJpYUxhYmVsID0gJ01lbnUgbGF0w6lyYWwnO1xuXG4gIC8qKiBJZCBkdSBtZW51LCBnw6luw6lyw6kgcGFyIGTDqWZhdXQgc2kgbm9uIGFmZmVjdMOpLiAqL1xuICBASW5wdXQoKSBjb250cm9sSWQ6IHN0cmluZztcblxuICAvKiogQWZmaWNoZSBsZSBtZW51IGxhdMOpcmFsIGVuIHZlcnNpb24gZml4ZSAgKi9cbiAgQElucHV0KCkgc3RpY2t5ID0gZmFsc2U7XG5cbiAgLyoqIEFmZmljaGUgbGUgbWVudSBsYXTDqXJhbCBlbiB2ZXJzaW9uIGZpeGUgc3VyIDEwMCUgZGUgbGEgaGF1dGV1ciBkZSBsYSBwYWdlLiAqL1xuICBASW5wdXQoKSBzdGlja3lGdWxsSGVpZ2h0ID0gZmFsc2U7XG5cbiAgLyoqIExlIG1lbnUgbGF0w6lyYWwgZXN0IGFmZmljaMOpIMOgIGdhdWNoZSBwYXIgZMOpZmF1dCBtYWlzIGlsIGVzdCBwb3NzaWJsZSBkZSBsJ2FmZmljaGVyIMOgIGRyb2l0ZS4gKi9cbiAgQElucHV0KCkgcG9zaXRpb246IERzZnJQb3NpdGlvbiA9IERzZnJQb3NpdGlvbkNvbnN0LkxFRlQ7XG5cbiAgLyoqIEFjdGl2ZXIgbGEgc2VsZWN0aW9uIGF1dG9tYXRpcXVlIGRlcyBpdGVtcyBldCBwYXJlbnRzIChzaSBhYnNlbmNlIGRlIHJvdXRlckxpbmspICovXG4gIEBJbnB1dCgpIGF1dG9BY3RpdmUgPSB0cnVlO1xuXG4gIC8qKiBFdsOpbmVtZW50IMOpbWlzIHN1aXRlIMOgIGxhIHPDqWxlY3Rpb24gZCd1biBpdGVtIGF2ZWMgbGllbiAqL1xuICBAT3V0cHV0KCkgaXRlbVNlbGVjdCA9IG5ldyBFdmVudEVtaXR0ZXI8RHNmck1lbnVJdGVtPigpO1xuXG4gIC8qKiBEdXBsaWNhdGlvbiBkZXMgaXRlbXMgZGUgbWVudSBwb3VyIG5lIHBhcyBtb2RpZmllciBsZSBtb2TDqGxlIG1lbnUgZW4gZW50csOpZSAqL1xuICBwcm90ZWN0ZWQgY2xvbmVNZW51SXRlbXM6IERzZnJNZW51SXRlbVtdID0gW107XG5cbiAgLyoqIFBvaW50ZXVyIHN1ciBsZSBkZXJuaWVyIGl0ZW0gc8OpbGVjdGlvbm7DqSAocGVybWV0IGRlIGxlIGTDqXPDqWxlY3Rpb25uZXIgbG9ycyBkJ3VuZSBub3V2ZWxsZSBzw6lsZWN0aW9uKS4gKi9cbiAgcHJpdmF0ZSBfcHJldkl0ZW1TZWxlY3RlZDogRHNmck1lbnVJdGVtIHwgdW5kZWZpbmVkO1xuXG4gIHByaXZhdGUgX2luaXRpYWxBY3RpdmVJdGVtOiBEc2ZyTWVudUl0ZW07XG4gIHByaXZhdGUgX21lbnU6IERzZnJNZW51O1xuXG4gIGdldCBtZW51KCk6IERzZnJNZW51IHtcbiAgICByZXR1cm4gdGhpcy5fbWVudTtcbiAgfVxuXG4gIC8qKiBNb2TDqGxlIGRlIGRvbm7DqWUgZHUgbWVudS4gKi9cbiAgQElucHV0KCkgc2V0IG1lbnUodmFsdWU6IERzZnJNZW51KSB7XG4gICAgdGhpcy5fbWVudSA9IHZhbHVlO1xuICAgIGlmICh0aGlzLl9tZW51ICYmIHRoaXMuX21lbnUuaXRlbXMpIHtcbiAgICAgIHRoaXMuY2xvbmVNZW51SXRlbXMgPSB0aGlzLl9tZW51Lml0ZW1zLm1hcCgoaXRlbSkgPT4gdGhpcy5jbG9uZU1lbnVJdGVtKGl0ZW0pKTtcbiAgICAgIGlmICh0aGlzLl9pbml0aWFsQWN0aXZlSXRlbSAmJiB0aGlzLmF1dG9BY3RpdmUpIHRoaXMuc2VsZWN0SXRlbSh0aGlzLl9pbml0aWFsQWN0aXZlSXRlbSk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIG9uU2VsZWN0SXRlbShpdGVtOiBEc2ZyTWVudUl0ZW0pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5hdXRvQWN0aXZlICYmICFpdGVtLnJvdXRlckxpbmspIHtcbiAgICAgIHRoaXMuc2VsZWN0SXRlbShpdGVtKTtcbiAgICAgIHRoaXMuY2xvbmVNZW51SXRlbXMgPSBbLi4udGhpcy5jbG9uZU1lbnVJdGVtc107XG4gICAgfVxuXG4gICAgdGhpcy5pdGVtU2VsZWN0LmVtaXQoaXRlbSk7XG4gIH1cblxuICAvKiogRHVwbGlxdWVyIGxlcyBpdGVtcyBkZSBtZW51IHBvdXIgbmUgcGFzIG1vZGlmaWVyIGxlIG1vZMOobGUgZW4gZW50csOpZSAqL1xuICBwcml2YXRlIGNsb25lTWVudUl0ZW0oaXRlbTogRHNmck1lbnVJdGVtKTogRHNmck1lbnVJdGVtIHtcbiAgICBjb25zdCBjbG9uZWRJdGVtOiBEc2ZyTWVudUl0ZW0gPSB7XG4gICAgICAuLi5pdGVtLFxuICAgICAgYWN0aXZlOiB0aGlzLmF1dG9BY3RpdmUgPyAhIShpdGVtLmFjdGl2ZSAmJiAhaXRlbS5zdWJJdGVtcykgOiBpdGVtLmFjdGl2ZSxcbiAgICAgIGNvbnRyb2xJZDogaXRlbS5jb250cm9sSWQgPz8gbmV3VW5pcXVlSWQoKSxcbiAgICAgIHN1Ykl0ZW1zOiBpdGVtLnN1Ykl0ZW1zID8gaXRlbS5zdWJJdGVtcy5tYXAoKHN1YikgPT4gdGhpcy5jbG9uZU1lbnVJdGVtKHN1YikpIDogdW5kZWZpbmVkLFxuICAgIH07XG4gICAgaWYgKGNsb25lZEl0ZW0uYWN0aXZlICYmICFjbG9uZWRJdGVtLnN1Ykl0ZW1zKSB7XG4gICAgICB0aGlzLl9pbml0aWFsQWN0aXZlSXRlbSA9IGNsb25lZEl0ZW07XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsb25lZEl0ZW07XG4gIH1cblxuICAvKiogQSBsYSBzZWxlY3Rpb24gZCd1biBpdGVtIHNpIGF1dG9BY3RpdmUgOlxuICAgKiAtIG9uIHBhc3NlIGxlIHByw6ljw6lkZW50IGl0ZW0gIHPDqWxlY3Rpb25uw6kgX3ByZXZJdGVtU2VsZWN0ZWQgZW4gZMOpc2FjdGl2w6kgYWluc2kgcXVlIHNlcyBwYXJlbnRzICh0cm9pcyBuaXZlYXV4IHBvdGVudGllbHMpXG4gICAqIC0gbm91dmVsIGl0ZW0gZXQgc2VzIHBhcmVudHMgZW4gYWN0aWZcbiAgICogLSBtaXNlIGEgam91ciBkZSBfcHJldkl0ZW1TZWxlY3RlZFxuICAgKi9cbiAgcHJpdmF0ZSBzZWxlY3RJdGVtKGl0ZW06IERzZnJNZW51SXRlbSk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9wcmV2SXRlbVNlbGVjdGVkKSB7XG4gICAgICB0aGlzLmFjdGl2YXRlSXRlbSh0aGlzLl9wcmV2SXRlbVNlbGVjdGVkLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgdGhpcy5hY3RpdmF0ZUl0ZW0oaXRlbSwgdHJ1ZSk7XG4gICAgdGhpcy5fcHJldkl0ZW1TZWxlY3RlZCA9IGl0ZW07XG4gIH1cblxuICAvKiogRMOpc2FjdGl2ZXIgb3UgYWN0aXZlciB1biBpdGVtIGV0IHNlcyBub2V1ZHMgcGFyZW50cyAqL1xuICBwcml2YXRlIGFjdGl2YXRlSXRlbShpdGVtOiBEc2ZyTWVudUl0ZW0sIGFjdGl2YXRlOiBib29sZWFuKTogdm9pZCB7XG4gICAgaXRlbS5hY3RpdmUgPSBhY3RpdmF0ZTtcbiAgICBjb25zdCBwYXJlbnQgPSB0aGlzLmZpbmRQYXJlbnQoaXRlbSwgdGhpcy5jbG9uZU1lbnVJdGVtcyk7XG4gICAgaWYgKHBhcmVudCkge1xuICAgICAgdGhpcy5hY3RpdmF0ZUl0ZW0ocGFyZW50LCBhY3RpdmF0ZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBhcmNvdXJzIHLDqWN1cnNpZiBkdSBtZW51IHBvdXIgcmV0cm91dmVyIGxlIHBhcmVudCBkaXJlY3QgZCd1biBpdGVtXG4gICAqL1xuICBwcml2YXRlIGZpbmRQYXJlbnQoaXRlbTogRHNmck1lbnVJdGVtLCBpdGVtczogRHNmck1lbnVJdGVtW10pOiBEc2ZyTWVudUl0ZW0gfCB1bmRlZmluZWQge1xuICAgIGZvciAoY29uc3QgcGFyZW50IG9mIGl0ZW1zKSB7XG4gICAgICBpZiAocGFyZW50LnN1Ykl0ZW1zPy5pbmNsdWRlcyhpdGVtKSkge1xuICAgICAgICByZXR1cm4gcGFyZW50O1xuICAgICAgfVxuICAgICAgY29uc3QgZm91bmRQYXJlbnQgPSB0aGlzLmZpbmRQYXJlbnQoaXRlbSwgcGFyZW50LnN1Ykl0ZW1zIHx8IFtdKTtcbiAgICAgIGlmIChmb3VuZFBhcmVudCkge1xuICAgICAgICByZXR1cm4gZm91bmRQYXJlbnQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuIiwiPG5hdlxuICBjbGFzcz1cImZyLXNpZGVtZW51XCJcbiAgW25nQ2xhc3NdPVwie1xuICAgICdmci1zaWRlbWVudS0tc3RpY2t5Jzogc3RpY2t5LFxuICAgICdmci1zaWRlbWVudS0tc3RpY2t5LWZ1bGwtaGVpZ2h0Jzogc3RpY2t5RnVsbEhlaWdodCxcbiAgICAnZnItc2lkZW1lbnUtLXJpZ2h0JzogcG9zaXRpb24gPT09ICdyaWdodCcsXG4gIH1cIlxuICByb2xlPVwibmF2aWdhdGlvblwiXG4gIFthdHRyLmFyaWEtbGFiZWxsZWRCeV09XCJtZW51LnRpdGxlID8gJ3NpZGVtZW51LXRpdGxlLScgKyBjb250cm9sSWQgOiBudWxsXCJcbiAgW2F0dHIuYXJpYS1sYWJlbF09XCJtZW51LnRpdGxlID8gbnVsbCA6IGFyaWFMYWJlbFwiPlxuICA8ZGl2IGNsYXNzPVwiZnItc2lkZW1lbnVfX2lubmVyXCI+XG4gICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJmci1zaWRlbWVudV9fYnRuXCIgW2F0dHIuYXJpYS1jb250cm9sc109XCInc2lkZW1lbnUtJyArIGNvbnRyb2xJZFwiIGFyaWEtZXhwYW5kZWQ9XCJmYWxzZVwiPlxuICAgICAgRGFucyBjZXR0ZSBydWJyaXF1ZVxuICAgIDwvYnV0dG9uPlxuICAgIDxkaXYgY2xhc3M9XCJmci1jb2xsYXBzZVwiIFtpZF09XCInc2lkZW1lbnUtJyArIGNvbnRyb2xJZFwiPlxuICAgICAgPCEtLVRpdHJlIGRlIHJ1YnJpcXVlIG9wdGlvbm5lbC0tPlxuICAgICAgQGlmIChtZW51ICYmIG1lbnUudGl0bGUpIHtcbiAgICAgICAgPHAgY2xhc3M9XCJmci1zaWRlbWVudV9fdGl0bGVcIiBbaWRdPVwiJ3NpZGVtZW51LXRpdGxlLScgKyBjb250cm9sSWRcIj57eyBtZW51LnRpdGxlIH19PC9wPlxuICAgICAgfVxuICAgICAgPCEtLU5pdmVhdSAxLS0+XG4gICAgICA8dWwgY2xhc3M9XCJmci1zaWRlbWVudV9fbGlzdFwiPlxuICAgICAgICBAZm9yIChpdGVtMSBvZiBjbG9uZU1lbnVJdGVtczsgdHJhY2sgaXRlbTEpIHtcbiAgICAgICAgICBAaWYgKCFpdGVtMS5zdWJJdGVtcykge1xuICAgICAgICAgICAgPGxpIGNsYXNzPVwiZnItc2lkZW1lbnVfX2l0ZW1cIj5cbiAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJsaW5rTWVudVwiIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IGl0ZW06IGl0ZW0xIH1cIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICA8bGkgY2xhc3M9XCJmci1zaWRlbWVudV9faXRlbVwiPlxuICAgICAgICAgICAgICA8IS0tTml2ZWF1IDItLT5cbiAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJidXR0b25NZW51XCIgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgaXRlbTogaXRlbTEgfVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZnItY29sbGFwc2VcIiBbaWRdPVwiaXRlbTEuY29udHJvbElkXCI+XG4gICAgICAgICAgICAgICAgPCEtLVRpdHJlIGRlIHJ1YnJpcXVlIG9wdGlvbm5lbC0tPlxuICAgICAgICAgICAgICAgIEBpZiAoaXRlbTEudGl0bGUpIHtcbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmci1zaWRlbWVudV9fdGl0bGVcIj57eyBpdGVtMS50aXRsZSB9fTwvZGl2PlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA8dWwgY2xhc3M9XCJmci1zaWRlbWVudV9fbGlzdFwiPlxuICAgICAgICAgICAgICAgICAgQGZvciAoaXRlbTIgb2YgaXRlbTEuc3ViSXRlbXM7IHRyYWNrIGl0ZW0yKSB7XG4gICAgICAgICAgICAgICAgICAgIEBpZiAoIWl0ZW0yLnN1Ykl0ZW1zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwiZnItc2lkZW1lbnVfX2l0ZW1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwibGlua01lbnVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyBpdGVtOiBpdGVtMiB9XCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwiZnItc2lkZW1lbnVfX2l0ZW1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiYnV0dG9uTWVudVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IGl0ZW06IGl0ZW0yIH1cIj48L25nLWNvbnRhaW5lcj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZyLWNvbGxhcHNlXCIgW2lkXT1cIml0ZW0yLmNvbnRyb2xJZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKGl0ZW0yLnRpdGxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZyLXNpZGVtZW51X190aXRsZVwiPnt7IGl0ZW0yLnRpdGxlIH19PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLU5pdmVhdSAzLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDx1bCBjbGFzcz1cImZyLXNpZGVtZW51X19saXN0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQGZvciAoaXRlbTMgb2YgaXRlbTIuc3ViSXRlbXM7IHRyYWNrIGl0ZW0zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJmci1zaWRlbWVudV9faXRlbVwiIFthdHRyLmFyaWEtY3VycmVudF09XCJpdGVtMy5hY3RpdmUgPyAncGFnZScgOiBudWxsXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJsaW5rTWVudVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgaXRlbTogaXRlbTMgfVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvdWw+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPC91bD5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2xpPlxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgPC91bD5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L25hdj5cblxuPG5nLXRlbXBsYXRlICNidXR0b25NZW51IGxldC1pdGVtPVwiaXRlbVwiIGxldC1pbmRleD1cImluZGV4XCI+XG4gIDxidXR0b25cbiAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICBjbGFzcz1cImZyLXNpZGVtZW51X19idG5cIlxuICAgIGFyaWEtZXhwYW5kZWQ9XCJmYWxzZVwiXG4gICAgW2F0dHIuYXJpYS1jb250cm9sc109XCJpdGVtLmNvbnRyb2xJZFwiXG4gICAgW2Rpc2FibGVOYXZpZ2F0aW9uXT1cInRydWVcIlxuICAgIFthdHRyLmFyaWEtY3VycmVudF09XCJpdGVtLmFjdGl2ZSAmJiAhaXRlbS5yb3V0ZXJMaW5rID8gdHJ1ZSA6IG51bGxcIlxuICAgIFtyb3V0ZXJMaW5rXT1cIml0ZW0ucm91dGVyTGlua1wiXG4gICAgW3JvdXRlckxpbmtBY3RpdmVdPVwiaXRlbS5yb3V0ZXJMaW5rQWN0aXZlID8/ICcnXCJcbiAgICBbcm91dGVyTGlua0FjdGl2ZU9wdGlvbnNdPVwiaXRlbS5yb3V0ZXJMaW5rQWN0aXZlT3B0aW9ucyA/IGl0ZW0ucm91dGVyTGlua0FjdGl2ZU9wdGlvbnMgOiB7IGV4YWN0OiBmYWxzZSB9XCJcbiAgICBbYXJpYUN1cnJlbnRXaGVuQWN0aXZlXT1cInRydWVcIj5cbiAgICA8aSAqbmdJZj1cIml0ZW0uaWNvblwiIGNsYXNzPVwiZWR1LWl0ZW0taWNvblwiIFtjbGFzc109XCJpdGVtLmljb25cIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAge3sgaXRlbS5sYWJlbCB9fVxuICA8L2J1dHRvbj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjbGlua01lbnUgbGV0LWl0ZW09XCJpdGVtXCIgbGV0LWluZGV4PVwiaW5kZXhcIj5cbiAgPGRzZnItbGlua1xuICAgIFthcmlhQ29udHJvbHNdPVwiaXRlbS5hcmlhQ29udHJvbHNcIlxuICAgIFthcmlhQ3VycmVudF09XCJpdGVtLmFjdGl2ZSAmJiAhaXRlbS5yb3V0ZXJMaW5rID8gJ3BhZ2UnIDogdW5kZWZpbmVkXCJcbiAgICBbYXJpYUxhYmVsXT1cIml0ZW0uYXJpYUxhYmVsID8/ICcnXCJcbiAgICBbY3VzdG9tQ2xhc3NdPVwiJ2ZyLXNpZGVtZW51X19saW5rICcgKyAoaXRlbS5jdXN0b21DbGFzcyA/PyAnJylcIlxuICAgIFtkaXNhYmxlZF09XCJpdGVtLmRpc2FibGVkXCJcbiAgICBbbGlua109XCJpdGVtLmxpbmtcIlxuICAgIFtsaW5rSWRdPVwiaXRlbS5saW5rSWRcIlxuICAgIFtsaW5rVGFyZ2V0XT1cIml0ZW0ubGlua1RhcmdldFwiXG4gICAgW2xhYmVsXT1cIml0ZW0uaWNvbiA/IG51bGwgOiBpdGVtLmxhYmVsXCJcbiAgICBbcm91dGVdPVwiaXRlbS5yb3V0ZVwiXG4gICAgW3JvdXRlUGF0aF09XCJpdGVtLnJvdXRlckxpbmtcIlxuICAgIFtyb3V0ZXJMaW5rQWN0aXZlXT1cIml0ZW0ucm91dGVyTGlua0FjdGl2ZSA/PyAnJ1wiXG4gICAgW3JvdXRlckxpbmtBY3RpdmVPcHRpb25zXT1cIml0ZW0ucm91dGVyTGlua0FjdGl2ZU9wdGlvbnMgPyBpdGVtLnJvdXRlckxpbmtBY3RpdmVPcHRpb25zIDogeyBleGFjdDogZmFsc2UgfVwiXG4gICAgW3JvdXRlckxpbmtFeHRyYXNdPVwiaXRlbS5yb3V0ZXJMaW5rRXh0cmFzXCJcbiAgICBbdG9vbHRpcE1lc3NhZ2VdPVwiaXRlbS50b29sdGlwTWVzc2FnZVwiXG4gICAgKGxpbmtTZWxlY3QpPVwib25TZWxlY3RJdGVtKGl0ZW0pXCI+XG4gICAgQGlmIChpdGVtLmljb25Qb3NpdGlvbiA9PT0gJ2xlZnQnKSB7XG4gICAgICA8aSBjbGFzcz1cImVkdS1pdGVtLWljb25cIiBbY2xhc3NdPVwiaXRlbS5pY29uXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIH1cbiAgICBAaWYgKGl0ZW0uaWNvbikge1xuICAgICAgPHNwYW4gbGFiZWw+IHt7IGl0ZW0ubGFiZWwgfX08L3NwYW4+XG4gICAgfVxuICAgIEBpZiAoaXRlbS5pY29uUG9zaXRpb24gPT09ICdyaWdodCcpIHtcbiAgICAgIDxpIGNsYXNzPVwiZWR1LWl0ZW0taWNvbiBlZHUtaXRlbS1pY29uLS1yaWdodFwiIFtjbGFzc109XCJpdGVtLmljb25cIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgfVxuICA8L2RzZnItbGluaz5cbjwvbmctdGVtcGxhdGU+XG4iXX0=