@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).
177 lines • 42.2 kB
JavaScript
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
import { RouterModule } from '@angular/router';
import { DsfrLinkTargetConst, DsfrPositionConst, DsfrSizeConst, } from '../../shared';
import * as i0 from "@angular/core";
import * as i1 from "../../shared";
import * as i2 from "@angular/common";
import * as i3 from "@angular/router";
export class DsfrLinkComponent {
constructor(i18n) {
this.i18n = i18n;
/**
* Permet de désactiver le composant.
*/
this.disabled = false;
/** Position de l'icône. À droite par défaut. */
this.iconPosition = DsfrPositionConst.RIGHT;
/**
* Taille du lien.
*/
this.linkSize = DsfrSizeConst.MD;
/**
* Si l'input 'route' est renseigné, sa valeur sera émise lorsque le lien est sélectionné.
*/
this.linkSelect = new EventEmitter();
}
/**
* Taille du lien.
*
* @deprecated since(1.15.0) utiliser 'linkSize' à la place
*/
get size() {
return this.linkSize;
}
/** @deprecated (since 1.5) utiliser `linkTarget` à la place. */
get targetLink() {
return this.linkTarget;
}
/**
* Taille du lien.
*
* @deprecated since(1.15.0) utiliser 'linkSize' à la place
*/
set size(value) {
this.linkSize = value;
}
/** @deprecated (since 1.5) utiliser `linkTarget` à la place. */
set targetLink(value) {
this.linkTarget = value;
}
/**
* Activation du router Angular.
*
* L'usage de routerLink provoque un bug accessibilité sur la navigation au clavier (ajout d'un tabindex=0).
*
* @deprecated (since 1.11.5) utiliser `routePath` à la place.
*/
set routerLink(value) {
if (value)
this.routePath = value;
}
ngOnInit() {
if (this.linkTarget === DsfrLinkTargetConst.BLANK) {
this.tooltipMessage = this.tooltipMessage
? `${this.tooltipMessage} - ${this.i18n.t('link.newWindow')}`
: `${this.i18n.t('link.newWindow')}`;
}
}
/** @internal */
getHref() {
return this.disabled ? undefined : this.link || this.route;
}
/** @internal */
hasRouterLink() {
return !this.disabled && !!this.routePath;
}
/**
* DsfrLink est partagé par plusieurs composants, 'tag', 'card' et 'tile' à la place d'un simple lien.
* Cela permet de bénéficier des nombreuses caractéristiques du composant DsfrLink.
*
* @since 1.5 Cependant, la classe 'fr-link' ne doit pas cohabiter les classes de ces composants ('fr-tag', ...)
*
* @internal
*/
getClass() {
return {
'fr-link': !this.customClass && !this.disabled,
'fr-link--icon-right': this.icon && this.iconPosition === DsfrPositionConst.RIGHT,
'fr-link--icon-left': this.icon && this.iconPosition === DsfrPositionConst.LEFT,
'fr-link--sm': this.linkSize === DsfrSizeConst.SM,
'fr-link--lg': this.linkSize === DsfrSizeConst.LG,
};
}
/** @internal */
getButtonClasses() {
const classes = ['fr-btn', 'fr-btn--tertiary-no-outline'];
if (this.customClass)
classes.push(this.customClass);
if (this.linkSize === DsfrSizeConst.SM)
classes.push('fr-btn--sm');
if (this.linkSize === DsfrSizeConst.LG)
classes.push('fr-btn--lg');
if (this.icon) {
classes.push(this.icon);
classes.push(this.iconPosition === DsfrPositionConst.RIGHT ? 'fr-btn--icon-right' : 'fr-btn--icon-left');
}
return classes.join(' ');
}
/** @internal */
onLink(event) {
if (this.route && !this.routePath) {
event.preventDefault();
this.linkSelect.emit(this.route);
}
else if (this.link) {
this.linkSelect.emit(this.link);
}
else if (this.mode === 'button') {
this.linkSelect.emit(this.linkId ?? this.label);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DsfrLinkComponent, deps: [{ token: i1.DsfrI18nService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DsfrLinkComponent, isStandalone: true, selector: "dsfr-link", inputs: { ariaCurrent: "ariaCurrent", ariaLabel: "ariaLabel", ariaControls: "ariaControls", customClass: "customClass", disabled: "disabled", icon: "icon", iconPosition: "iconPosition", linkId: "linkId", label: "label", link: "link", linkTarget: "linkTarget", route: "route", routePath: "routePath", routerLinkActive: "routerLinkActive", routerLinkActiveOptions: "routerLinkActiveOptions", routerLinkExtras: "routerLinkExtras", linkSize: "linkSize", tooltipMessage: "tooltipMessage", mode: "mode", ariaCurrentWhenActive: "ariaCurrentWhenActive", size: "size", targetLink: "targetLink", routerLink: "routerLink" }, outputs: { linkSelect: "linkSelect" }, ngImport: i0, template: "<!-- Lien externe ou g\u00E9r\u00E9 programmatiquement -->\n<!--FIXME : obligation de dupliquer ici pour g\u00E9rer a la fois innerHTML (/!\\ pas de outerHTML!) et la pr\u00E9sence du slot.\n voir pour fix en angular 19 d\u00E9tection d'un contenu dans le slot ou suppression de innerHTML en v2 -->\n@if (!hasRouterLink() && mode !== 'button') {\n @if (label) {\n <!-- Lien externe et label en innerHTML-->\n <a\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-current]=\"ariaCurrent || null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.data-fr-opened]=\"ariaControls ? false : null\"\n [attr.href]=\"getHref() || null\"\n [attr.id]=\"linkId || null\"\n [attr.rel]=\"linkTarget === '_blank' ? 'noopener external' : null\"\n [attr.role]=\"disabled ? 'link' : null\"\n [attr.target]=\"targetLink || null\"\n [attr.title]=\"tooltipMessage || null\"\n class=\"{{ customClass ? customClass : '' }}\"\n [className]=\"icon ? icon : ''\"\n [ngClass]=\"getClass()\"\n (click)=\"onLink($event)\"\n [innerHTML]=\"label\">\n </a>\n } @else {\n <!-- Lien externe et slot pour le label -->\n <a\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-current]=\"ariaCurrent || null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.data-fr-opened]=\"ariaControls ? false : null\"\n [attr.href]=\"getHref() || null\"\n [attr.id]=\"linkId || null\"\n [attr.rel]=\"linkTarget === '_blank' ? 'noopener external' : null\"\n [attr.role]=\"disabled ? 'link' : null\"\n [attr.target]=\"targetLink || null\"\n [attr.title]=\"tooltipMessage || null\"\n class=\"{{ customClass ? customClass : '' }}\"\n [className]=\"icon ? icon : ''\"\n [ngClass]=\"getClass()\"\n (click)=\"onLink($event)\">\n <ng-container [ngTemplateOutlet]=\"slot\"> </ng-container>\n </a>\n }\n} @else if (hasRouterLink() && mode !== 'button') {\n @if (label) {\n <!-- Routerlink et label en innerHTML-->\n <a\n [ariaCurrentWhenActive]=\"ariaCurrentWhenActive ?? 'page'\"\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-current]=\"ariaCurrent || null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.id]=\"linkId || null\"\n [attr.role]=\"disabled ? 'link' : null\"\n [attr.target]=\"targetLink || null\"\n [attr.title]=\"tooltipMessage || null\"\n class=\"{{ customClass ? customClass : '' }}\"\n [className]=\"icon ? icon : ''\"\n [fragment]=\"routerLinkExtras?.fragment\"\n [ngClass]=\"getClass()\"\n [preserveFragment]=\"routerLinkExtras?.preserveFragment\"\n [queryParams]=\"routerLinkExtras?.queryParams\"\n [queryParamsHandling]=\"routerLinkExtras?.queryParamsHandling\"\n [replaceUrl]=\"routerLinkExtras?.replaceUrl\"\n [routerLink]=\"routePath\"\n [routerLinkActive]=\"routerLinkActive ?? ''\"\n [routerLinkActiveOptions]=\"routerLinkActiveOptions ? routerLinkActiveOptions : { exact: false }\"\n [skipLocationChange]=\"routerLinkExtras?.skipLocationChange\"\n [state]=\"routerLinkExtras?.state\"\n (click)=\"onLink($event)\"\n [innerHTML]=\"label\">\n </a>\n } @else {\n <!-- Routerlink et slot pour le label -->\n <a\n [ariaCurrentWhenActive]=\"ariaCurrentWhenActive ?? 'page'\"\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-current]=\"ariaCurrent || null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.id]=\"linkId || null\"\n [attr.role]=\"disabled ? 'link' : null\"\n [attr.target]=\"targetLink || null\"\n [attr.title]=\"tooltipMessage || null\"\n class=\"{{ customClass ? customClass : '' }}\"\n [className]=\"icon ? icon : ''\"\n [fragment]=\"routerLinkExtras?.fragment\"\n [ngClass]=\"getClass()\"\n [preserveFragment]=\"routerLinkExtras?.preserveFragment\"\n [queryParams]=\"routerLinkExtras?.queryParams\"\n [queryParamsHandling]=\"routerLinkExtras?.queryParamsHandling\"\n [replaceUrl]=\"routerLinkExtras?.replaceUrl\"\n [routerLink]=\"routePath\"\n [routerLinkActive]=\"routerLinkActive ?? ''\"\n [routerLinkActiveOptions]=\"routerLinkActiveOptions ? routerLinkActiveOptions : { exact: false }\"\n [skipLocationChange]=\"routerLinkExtras?.skipLocationChange\"\n [state]=\"routerLinkExtras?.state\"\n (click)=\"onLink($event)\">\n <ng-container [ngTemplateOutlet]=\"slot\"> </ng-container>\n </a>\n }\n} @else if (mode === 'button') {\n @if (label) {\n <!-- Bouton et label en innerHTML-->\n <button\n type=\"button\"\n [attr.id]=\"linkId\"\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.data-fr-opened]=\"ariaControls ? false : null\"\n [attr.title]=\"tooltipMessage || null\"\n [disabled]=\"disabled\"\n [ngClass]=\"getButtonClasses()\"\n (click)=\"onLink($event)\"\n [innerHTML]=\"label\"></button>\n } @else {\n <!-- Bouton et slot pour le label-->\n <button\n type=\"button\"\n [attr.id]=\"linkId\"\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.data-fr-opened]=\"ariaControls ? false : null\"\n [attr.title]=\"tooltipMessage || null\"\n [disabled]=\"disabled\"\n [ngClass]=\"getButtonClasses()\"\n (click)=\"onLink($event)\">\n <ng-container [ngTemplateOutlet]=\"slot\"> </ng-container>\n </button>\n }\n}\n\n<!-- D\u00E9clar\u00E9 dans un template : le ng-content ne doit \u00EAtre pr\u00E9sent qu'une seule fois -->\n<ng-template #slot>\n <ng-content></ng-content>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i3.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DsfrLinkComponent, decorators: [{
type: Component,
args: [{ selector: 'dsfr-link', encapsulation: ViewEncapsulation.None, standalone: true, imports: [CommonModule, RouterModule], template: "<!-- Lien externe ou g\u00E9r\u00E9 programmatiquement -->\n<!--FIXME : obligation de dupliquer ici pour g\u00E9rer a la fois innerHTML (/!\\ pas de outerHTML!) et la pr\u00E9sence du slot.\n voir pour fix en angular 19 d\u00E9tection d'un contenu dans le slot ou suppression de innerHTML en v2 -->\n@if (!hasRouterLink() && mode !== 'button') {\n @if (label) {\n <!-- Lien externe et label en innerHTML-->\n <a\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-current]=\"ariaCurrent || null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.data-fr-opened]=\"ariaControls ? false : null\"\n [attr.href]=\"getHref() || null\"\n [attr.id]=\"linkId || null\"\n [attr.rel]=\"linkTarget === '_blank' ? 'noopener external' : null\"\n [attr.role]=\"disabled ? 'link' : null\"\n [attr.target]=\"targetLink || null\"\n [attr.title]=\"tooltipMessage || null\"\n class=\"{{ customClass ? customClass : '' }}\"\n [className]=\"icon ? icon : ''\"\n [ngClass]=\"getClass()\"\n (click)=\"onLink($event)\"\n [innerHTML]=\"label\">\n </a>\n } @else {\n <!-- Lien externe et slot pour le label -->\n <a\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-current]=\"ariaCurrent || null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.data-fr-opened]=\"ariaControls ? false : null\"\n [attr.href]=\"getHref() || null\"\n [attr.id]=\"linkId || null\"\n [attr.rel]=\"linkTarget === '_blank' ? 'noopener external' : null\"\n [attr.role]=\"disabled ? 'link' : null\"\n [attr.target]=\"targetLink || null\"\n [attr.title]=\"tooltipMessage || null\"\n class=\"{{ customClass ? customClass : '' }}\"\n [className]=\"icon ? icon : ''\"\n [ngClass]=\"getClass()\"\n (click)=\"onLink($event)\">\n <ng-container [ngTemplateOutlet]=\"slot\"> </ng-container>\n </a>\n }\n} @else if (hasRouterLink() && mode !== 'button') {\n @if (label) {\n <!-- Routerlink et label en innerHTML-->\n <a\n [ariaCurrentWhenActive]=\"ariaCurrentWhenActive ?? 'page'\"\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-current]=\"ariaCurrent || null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.id]=\"linkId || null\"\n [attr.role]=\"disabled ? 'link' : null\"\n [attr.target]=\"targetLink || null\"\n [attr.title]=\"tooltipMessage || null\"\n class=\"{{ customClass ? customClass : '' }}\"\n [className]=\"icon ? icon : ''\"\n [fragment]=\"routerLinkExtras?.fragment\"\n [ngClass]=\"getClass()\"\n [preserveFragment]=\"routerLinkExtras?.preserveFragment\"\n [queryParams]=\"routerLinkExtras?.queryParams\"\n [queryParamsHandling]=\"routerLinkExtras?.queryParamsHandling\"\n [replaceUrl]=\"routerLinkExtras?.replaceUrl\"\n [routerLink]=\"routePath\"\n [routerLinkActive]=\"routerLinkActive ?? ''\"\n [routerLinkActiveOptions]=\"routerLinkActiveOptions ? routerLinkActiveOptions : { exact: false }\"\n [skipLocationChange]=\"routerLinkExtras?.skipLocationChange\"\n [state]=\"routerLinkExtras?.state\"\n (click)=\"onLink($event)\"\n [innerHTML]=\"label\">\n </a>\n } @else {\n <!-- Routerlink et slot pour le label -->\n <a\n [ariaCurrentWhenActive]=\"ariaCurrentWhenActive ?? 'page'\"\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-current]=\"ariaCurrent || null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.id]=\"linkId || null\"\n [attr.role]=\"disabled ? 'link' : null\"\n [attr.target]=\"targetLink || null\"\n [attr.title]=\"tooltipMessage || null\"\n class=\"{{ customClass ? customClass : '' }}\"\n [className]=\"icon ? icon : ''\"\n [fragment]=\"routerLinkExtras?.fragment\"\n [ngClass]=\"getClass()\"\n [preserveFragment]=\"routerLinkExtras?.preserveFragment\"\n [queryParams]=\"routerLinkExtras?.queryParams\"\n [queryParamsHandling]=\"routerLinkExtras?.queryParamsHandling\"\n [replaceUrl]=\"routerLinkExtras?.replaceUrl\"\n [routerLink]=\"routePath\"\n [routerLinkActive]=\"routerLinkActive ?? ''\"\n [routerLinkActiveOptions]=\"routerLinkActiveOptions ? routerLinkActiveOptions : { exact: false }\"\n [skipLocationChange]=\"routerLinkExtras?.skipLocationChange\"\n [state]=\"routerLinkExtras?.state\"\n (click)=\"onLink($event)\">\n <ng-container [ngTemplateOutlet]=\"slot\"> </ng-container>\n </a>\n }\n} @else if (mode === 'button') {\n @if (label) {\n <!-- Bouton et label en innerHTML-->\n <button\n type=\"button\"\n [attr.id]=\"linkId\"\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.data-fr-opened]=\"ariaControls ? false : null\"\n [attr.title]=\"tooltipMessage || null\"\n [disabled]=\"disabled\"\n [ngClass]=\"getButtonClasses()\"\n (click)=\"onLink($event)\"\n [innerHTML]=\"label\"></button>\n } @else {\n <!-- Bouton et slot pour le label-->\n <button\n type=\"button\"\n [attr.id]=\"linkId\"\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.data-fr-opened]=\"ariaControls ? false : null\"\n [attr.title]=\"tooltipMessage || null\"\n [disabled]=\"disabled\"\n [ngClass]=\"getButtonClasses()\"\n (click)=\"onLink($event)\">\n <ng-container [ngTemplateOutlet]=\"slot\"> </ng-container>\n </button>\n }\n}\n\n<!-- D\u00E9clar\u00E9 dans un template : le ng-content ne doit \u00EAtre pr\u00E9sent qu'une seule fois -->\n<ng-template #slot>\n <ng-content></ng-content>\n</ng-template>\n" }]
}], ctorParameters: () => [{ type: i1.DsfrI18nService }], propDecorators: { ariaCurrent: [{
type: Input
}], ariaLabel: [{
type: Input
}], ariaControls: [{
type: Input
}], customClass: [{
type: Input
}], disabled: [{
type: Input
}], icon: [{
type: Input
}], iconPosition: [{
type: Input
}], linkId: [{
type: Input
}], label: [{
type: Input
}], link: [{
type: Input
}], linkTarget: [{
type: Input
}], route: [{
type: Input
}], routePath: [{
type: Input
}], routerLinkActive: [{
type: Input
}], routerLinkActiveOptions: [{
type: Input
}], routerLinkExtras: [{
type: Input
}], linkSize: [{
type: Input
}], tooltipMessage: [{
type: Input
}], mode: [{
type: Input
}], ariaCurrentWhenActive: [{
type: Input
}], linkSelect: [{
type: Output
}], size: [{
type: Input
}], targetLink: [{
type: Input
}], routerLink: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGluay5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZHNmci1jb21wb25lbnRzL3NyYy9saWIvY29tcG9uZW50cy9saW5rL2xpbmsuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWRzZnItY29tcG9uZW50cy9zcmMvbGliL2NvbXBvbmVudHMvbGluay9saW5rLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQVUsTUFBTSxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2xHLE9BQU8sRUFBMEMsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDdkYsT0FBTyxFQUlMLG1CQUFtQixFQUVuQixpQkFBaUIsRUFFakIsYUFBYSxHQUNkLE1BQU0sY0FBYyxDQUFDOzs7OztBQVN0QixNQUFNLE9BQU8saUJBQWlCO0lBd0Y1QixZQUFvQixJQUFxQjtRQUFyQixTQUFJLEdBQUosSUFBSSxDQUFpQjtRQW5FekM7O1dBRUc7UUFDTSxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBSzFCLGdEQUFnRDtRQUN2QyxpQkFBWSxHQUE2QixpQkFBaUIsQ0FBQyxLQUFLLENBQUM7UUErQjFFOztXQUVHO1FBQ00sYUFBUSxHQUFhLGFBQWEsQ0FBQyxFQUFFLENBQUM7UUFtQi9DOztXQUVHO1FBQ08sZUFBVSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7SUFFTixDQUFDO0lBRTdDOzs7O09BSUc7SUFDSCxJQUFJLElBQUk7UUFDTixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDdkIsQ0FBQztJQUVELGdFQUFnRTtJQUNoRSxJQUFJLFVBQVU7UUFDWixPQUFPLElBQUksQ0FBQyxV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QkFHRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBR0csdUJBQXVCO3NCQUEvQixLQUFLO2dCQUdHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFLRyxRQUFRO3NCQUFoQixLQUFLO2dCQUdHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBT0csSUFBSTtzQkFBWixLQUFLO2dCQU9HLHFCQUFxQjtzQkFBN0IsS0FBSztnQkFLSSxVQUFVO3NCQUFuQixNQUFNO2dCQXVCTSxJQUFJO3NCQUFoQixLQUFLO2dCQUtPLFVBQVU7c0JBQXRCLEtBQUs7Z0JBV08sVUFBVTtzQkFBdEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uSW5pdCwgT3V0cHV0LCBWaWV3RW5jYXBzdWxhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSXNBY3RpdmVNYXRjaE9wdGlvbnMsIE5hdmlnYXRpb25FeHRyYXMsIFJvdXRlck1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQge1xuICBEc2ZySTE4blNlcnZpY2UsXG4gIERzZnJMaW5rLFxuICBEc2ZyTGlua1RhcmdldCxcbiAgRHNmckxpbmtUYXJnZXRDb25zdCxcbiAgRHNmclBvc2l0aW9uLFxuICBEc2ZyUG9zaXRpb25Db25zdCxcbiAgRHNmclNpemUsXG4gIERzZnJTaXplQ29uc3QsXG59IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2RzZnItbGluaycsXG4gIHRlbXBsYXRlVXJsOiAnLi9saW5rLmNvbXBvbmVudC5odG1sJyxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgUm91dGVyTW9kdWxlXSxcbn0pXG5leHBvcnQgY2xhc3MgRHNmckxpbmtDb21wb25lbnQgaW1wbGVtZW50cyBPbWl0PERzZnJMaW5rLCAnYWN0aXZlJyB8ICd0YXJnZXQnPiwgT25Jbml0IHtcbiAgLyoqIFBlcm1ldCBkJ2Fqb3V0ZXIgdW4gYXR0cmlidXQgYGFyaWEtY3VycmVudGAgc3VyIGxlIGxpZW4uKi9cbiAgQElucHV0KCkgYXJpYUN1cnJlbnQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogTGEgcHJvcHJpw6l0w6kgYXJpYUxhYmVsIGTDqWZpbml0IHVuZSB2YWxldXIgZGUgY2hhw65uZSBxdWkgw6l0aXF1ZXR0ZSB1biDDqWzDqW1lbnQgaW50ZXJhY3RpZi5cbiAgICpcbiAgICogQHNpbmNlIDEuNC4wXG4gICAqL1xuICBASW5wdXQoKSBhcmlhTGFiZWw6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogSWRlbnRpZmllIGwnw6lsw6ltZW50IChvdSBsZXMgw6lsw6ltZW50cykgY29udHLDtGzDqSBwYXIgY2V0IMOpbMOpbWVudC5cbiAgICpcbiAgICogQHNpbmNlIDEuNy4wXG4gICAqL1xuICBASW5wdXQoKSBhcmlhQ29udHJvbHM6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAvKiogUG91ciBham91dGVyIGRlcyBjbGFzc2VzIENTUyBjdXN0b20uIFN1cHByaW1lcmEgbGEgY2xhc3NlIHBhciBkw6lmYXV0ICdmci1saW5rJyAqL1xuICBASW5wdXQoKSBjdXN0b21DbGFzczogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBQZXJtZXQgZGUgZMOpc2FjdGl2ZXIgbGUgY29tcG9zYW50LlxuICAgKi9cbiAgQElucHV0KCkgZGlzYWJsZWQgPSBmYWxzZTtcblxuICAvKiogQ2xhc3NlIGRlIGwnaWPDtG5lLiAqL1xuICBASW5wdXQoKSBpY29uOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgLyoqIFBvc2l0aW9uIGRlIGwnaWPDtG5lLiDDgCBkcm9pdGUgcGFyIGTDqWZhdXQuICovXG4gIEBJbnB1dCgpIGljb25Qb3NpdGlvbjogRHNmclBvc2l0aW9uIHwgdW5kZWZpbmVkID0gRHNmclBvc2l0aW9uQ29uc3QuUklHSFQ7XG5cbiAgLyoqIEBzaW5jZSAxLjYgKi9cbiAgQElucHV0KCkgbGlua0lkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgLyoqIFRleHRlIGR1IGxpZW4gc2ltcGxlLiBTaW5vbiB1dGlsaXNlciB1biBzbG90IFtsYWJlbF0uKi9cbiAgQElucHV0KCkgbGFiZWw6IHN0cmluZztcblxuICAvKiogTGllbiBocmVmIGV4dGVybmUsIGV4Y2x1c2lmIGF2ZWMgcm91dGUgZXQgcm91dGVQYXRoLiAqL1xuICBASW5wdXQoKSBsaW5rOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgLyoqIEF0dHJpYnV0IHRhcmdldCBkdSBsaWVuLiAqL1xuICAvLyBMZSBub20gJ3RhcmdldCcgY3LDqWUgdW4gcHJvYmzDqG1lIGF2ZWMgbGUgQ1NTIERTRlIsIHB1aXNxdWUgZHUgY291cCwgb24gYSB0YXJnZXQ9XCJfYmxhbmtcIiBkYW5zIGxlIGhvc3QgZXQgdW5cbiAgLy8gc3R5bGUgcydhcHBsaXF1ZSwgY2UgcXVpIHByb3ZvcXVlIHVuIGRvdWJsZW1lbnQgZGUgbCdpY8O0bmUgbGllbiBleHRlcm5lLlxuICBASW5wdXQoKSBsaW5rVGFyZ2V0OiBEc2ZyTGlua1RhcmdldCB8IHVuZGVmaW5lZDtcblxuICAvKiogUGF0aCBpbnRlcm5lLiBFeGNsdXNpZiBhdmVjIGxpbmsgZXQgcm91dGVQYXRoLCBwcmlvcml0YWlyZSBzdXIgbGluay4gKi9cbiAgQElucHV0KCkgcm91dGU6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAvKiogUGF0aCBhbmd1bGFyIGfDqXLDqSBlbiB0YW50IHF1ZSBkaXJlY3RpdmUgcm91dGVyTGluay4gUHJpb3JpdGFpcmUgZXQgZXhjbHVzaWYgYXZlYyBsaW5rIGV0IHJvdXRlLiAqL1xuICBASW5wdXQoKSByb3V0ZVBhdGg6IHN0cmluZyB8IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBDbGFzc2UgQ1NTIHV0aWxpc8OpZSBwb3VyIGxhIGRpcmVjdGl2ZSByb3V0ZXJMaW5rIGFjdGl2ZS4gKi9cbiAgQElucHV0KCkgcm91dGVyTGlua0FjdGl2ZTogc3RyaW5nIHwgc3RyaW5nW10gfCB1bmRlZmluZWQ7XG5cbiAgLyoqIFJvdXRlckxpbmsgOiBvcHRpb25zIGFkZGl0aW9ubmVsbGVzIHBvdXIgbGUgcm91dGVyTGlua0FjdGl2ZSAoZXhhY3QpLiAqL1xuICBASW5wdXQoKSByb3V0ZXJMaW5rQWN0aXZlT3B0aW9uczogeyBleGFjdDogYm9vbGVhbiB9IHwgSXNBY3RpdmVNYXRjaE9wdGlvbnMgfCB1bmRlZmluZWQ7XG5cbiAgLyoqIFJvdXRlckxpbmsgOiBvcHRpb25zIGFkZGl0aW9ubmVsbGVzIHBwb3VyIGxlIHJvdXRlckxpbmsgKHF1ZXJ5UGFyYW1zLCBzdGF0ZSwgZXRjLikgKi9cbiAgQElucHV0KCkgcm91dGVyTGlua0V4dHJhczogTmF2aWdhdGlvbkV4dHJhcyB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogVGFpbGxlIGR1IGxpZW4uXG4gICAqL1xuICBASW5wdXQoKSBsaW5rU2l6ZTogRHNmclNpemUgPSBEc2ZyU2l6ZUNvbnN0Lk1EO1xuXG4gIC8qKiBNZXNzYWdlIGR1IHRvb2x0aXAgKGF0dHJpYnV0IHRpdGxlKS4gQHNpbmNlIDEuMy4wICovXG4gIEBJbnB1dCgpIHRvb2x0aXBNZXNzYWdlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIFRyYW5zZm9ybWUgdW4gbGllbiBlbiBib3V0b24gc2kgYGJ1dHRvbmAsIGBsaW5rYCBwYXIgZMOpZmF1dC5cbiAgICpcbiAgICogQHNpbmNlIDEuNy4wXG4gICAqL1xuICBASW5wdXQoKSBtb2RlOiAnbGluaycgfCAnYnV0dG9uJyB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogU3VyY2hhcmdlciBsZSBjb21wb3J0ZW1lbnQgYXJpYUN1cnJlbnRXaGVuQWN0aXZlIChyb3V0ZXJMaW5rKS4gUGFyIGTDqWZhdXQgXCJwYWdlXCIgc2kgbGEgcm91dGUgZXN0IGFjdGl2ZSAuXG4gICAqXG4gICAqIEBzaW5jZSAxLjEzLjBcbiAgICovXG4gIEBJbnB1dCgpIGFyaWFDdXJyZW50V2hlbkFjdGl2ZTogJ3BhZ2UnIHwgJ3N0ZXAnIHwgJ2xvY2F0aW9uJyB8ICdkYXRlJyB8ICd0aW1lJyB8IHRydWUgfCBmYWxzZSB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogU2kgbCdpbnB1dCAncm91dGUnIGVzdCByZW5zZWlnbsOpLCBzYSB2YWxldXIgc2VyYSDDqW1pc2UgbG9yc3F1ZSBsZSBsaWVuIGVzdCBzw6lsZWN0aW9ubsOpLlxuICAgKi9cbiAgQE91dHB1dCgpIGxpbmtTZWxlY3QgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGkxOG46IERzZnJJMThuU2VydmljZSkge31cblxuICAvKipcbiAgICogVGFpbGxlIGR1IGxpZW4uXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHNpbmNlKDEuMTUuMCkgdXRpbGlzZXIgJ2xpbmtTaXplJyDDoCBsYSBwbGFjZVxuICAgKi9cbiAgZ2V0IHNpemUoKTogRHNmclNpemUge1xuICAgIHJldHVybiB0aGlzLmxpbmtTaXplO1xuICB9XG5cbiAgLyoqIEBkZXByZWNhdGVkIChzaW5jZSAxLjUpIHV0aWxpc2VyIGBsaW5rVGFyZ2V0YCDDoCBsYSBwbGFjZS4gKi9cbiAgZ2V0IHRhcmdldExpbmsoKTogRHNmckxpbmtUYXJnZXQgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmxpbmtUYXJnZXQ7XG4gIH1cblxuICAvKipcbiAgICogVGFpbGxlIGR1IGxpZW4uXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHNpbmNlKDEuMTUuMCkgdXRpbGlzZXIgJ2xpbmtTaXplJyDDoCBsYSBwbGFjZVxuICAgKi9cbiAgQElucHV0KCkgc2V0IHNpemUodmFsdWU6IERzZnJTaXplKSB7XG4gICAgdGhpcy5saW5rU2l6ZSA9IHZhbHVlO1xuICB9XG5cbiAgLyoqIEBkZXByZWNhdGVkIChzaW5jZSAxLjUpIHV0aWxpc2VyIGBsaW5rVGFyZ2V0YCDDoCBsYSBwbGFjZS4gKi9cbiAgQElucHV0KCkgc2V0IHRhcmdldExpbmsodmFsdWU6IERzZnJMaW5rVGFyZ2V0IHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5saW5rVGFyZ2V0ID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogQWN0aXZhdGlvbiBkdSByb3V0ZXIgQW5ndWxhci5cbiAgICpcbiAgICogTCd1c2FnZSBkZSByb3V0ZXJMaW5rIHByb3ZvcXVlIHVuIGJ1ZyBhY2Nlc3NpYmlsaXTDqSBzdXIgbGEgbmF2aWdhdGlvbiBhdSBjbGF2aWVyIChham91dCBkJ3VuIHRhYmluZGV4PTApLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCAoc2luY2UgMS4xMS41KSB1dGlsaXNlciBgcm91dGVQYXRoYCDDoCBsYSBwbGFjZS5cbiAgICovXG4gIEBJbnB1dCgpIHNldCByb3V0ZXJMaW5rKHZhbHVlOiBzdHJpbmcgfCBzdHJpbmdbXSB8IHVuZGVmaW5lZCkge1xuICAgIGlmICh2YWx1ZSkgdGhpcy5yb3V0ZVBhdGggPSB2YWx1ZTtcbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmxpbmtUYXJnZXQgPT09IERzZnJMaW5rVGFyZ2V0Q29uc3QuQkxBTkspIHtcbiAgICAgIHRoaXMudG9vbHRpcE1lc3NhZ2UgPSB0aGlzLnRvb2x0aXBNZXNzYWdlXG4gICAgICAgID8gYCR7dGhpcy50b29sdGlwTWVzc2FnZX0gLSAke3RoaXMuaTE4bi50KCdsaW5rLm5ld1dpbmRvdycpfWBcbiAgICAgICAgOiBgJHt0aGlzLmkxOG4udCgnbGluay5uZXdXaW5kb3cnKX1gO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgZ2V0SHJlZigpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmRpc2FibGVkID8gdW5kZWZpbmVkIDogdGhpcy5saW5rIHx8IHRoaXMucm91dGU7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIGhhc1JvdXRlckxpbmsoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICF0aGlzLmRpc2FibGVkICYmICEhdGhpcy5yb3V0ZVBhdGg7XG4gIH1cblxuICAvKipcbiAgICogRHNmckxpbmsgZXN0IHBhcnRhZ8OpIHBhciBwbHVzaWV1cnMgY29tcG9zYW50cywgJ3RhZycsICdjYXJkJyBldCAndGlsZScgw6AgbGEgcGxhY2UgZCd1biBzaW1wbGUgbGllbi5cbiAgICogQ2VsYSBwZXJtZXQgZGUgYsOpbsOpZmljaWVyIGRlcyBub21icmV1c2VzIGNhcmFjdMOpcmlzdGlxdWVzIGR1IGNvbXBvc2FudCBEc2ZyTGluay5cbiAgICpcbiAgICogQHNpbmNlIDEuNSBDZXBlbmRhbnQsIGxhIGNsYXNzZSAnZnItbGluaycgbmUgZG9pdCBwYXMgY29oYWJpdGVyIGxlcyBjbGFzc2VzIGRlIGNlcyBjb21wb3NhbnRzICgnZnItdGFnJywgLi4uKVxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIGdldENsYXNzKCkge1xuICAgIHJldHVybiB7XG4gICAgICAnZnItbGluayc6ICF0aGlzLmN1c3RvbUNsYXNzICYmICF0aGlzLmRpc2FibGVkLFxuICAgICAgJ2ZyLWxpbmstLWljb24tcmlnaHQnOiB0aGlzLmljb24gJiYgdGhpcy5pY29uUG9zaXRpb24gPT09IERzZnJQb3NpdGlvbkNvbnN0LlJJR0hULFxuICAgICAgJ2ZyLWxpbmstLWljb24tbGVmdCc6IHRoaXMuaWNvbiAmJiB0aGlzLmljb25Qb3NpdGlvbiA9PT0gRHNmclBvc2l0aW9uQ29uc3QuTEVGVCxcbiAgICAgICdmci1saW5rLS1zbSc6IHRoaXMubGlua1NpemUgPT09IERzZnJTaXplQ29uc3QuU00sXG4gICAgICAnZnItbGluay0tbGcnOiB0aGlzLmxpbmtTaXplID09PSBEc2ZyU2l6ZUNvbnN0LkxHLFxuICAgIH07XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIGdldEJ1dHRvbkNsYXNzZXMoKTogc3RyaW5nIHtcbiAgICBjb25zdCBjbGFzc2VzID0gWydmci1idG4nLCAnZnItYnRuLS10ZXJ0aWFyeS1uby1vdXRsaW5lJ107XG4gICAgaWYgKHRoaXMuY3VzdG9tQ2xhc3MpIGNsYXNzZXMucHVzaCh0aGlzLmN1c3RvbUNsYXNzKTtcbiAgICBpZiAodGhpcy5saW5rU2l6ZSA9PT0gRHNmclNpemVDb25zdC5TTSkgY2xhc3Nlcy5wdXNoKCdmci1idG4tLXNtJyk7XG4gICAgaWYgKHRoaXMubGlua1NpemUgPT09IERzZnJTaXplQ29uc3QuTEcpIGNsYXNzZXMucHVzaCgnZnItYnRuLS1sZycpO1xuXG4gICAgaWYgKHRoaXMuaWNvbikge1xuICAgICAgY2xhc3Nlcy5wdXNoKHRoaXMuaWNvbik7XG4gICAgICBjbGFzc2VzLnB1c2godGhpcy5pY29uUG9zaXRpb24gPT09IERzZnJQb3NpdGlvbkNvbnN0LlJJR0hUID8gJ2ZyLWJ0bi0taWNvbi1yaWdodCcgOiAnZnItYnRuLS1pY29uLWxlZnQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2xhc3Nlcy5qb2luKCcgJyk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIG9uTGluayhldmVudDogRXZlbnQpIHtcbiAgICBpZiAodGhpcy5yb3V0ZSAmJiAhdGhpcy5yb3V0ZVBhdGgpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB0aGlzLmxpbmtTZWxlY3QuZW1pdCh0aGlzLnJvdXRlKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMubGluaykge1xuICAgICAgdGhpcy5saW5rU2VsZWN0LmVtaXQodGhpcy5saW5rKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMubW9kZSA9PT0gJ2J1dHRvbicpIHtcbiAgICAgIHRoaXMubGlua1NlbGVjdC5lbWl0KHRoaXMubGlua0lkID8/IHRoaXMubGFiZWwpO1xuICAgIH1cbiAgfVxufVxuIiwiPCEtLSBMaWVuIGV4dGVybmUgb3UgZ8OpcsOpIHByb2dyYW1tYXRpcXVlbWVudCAtLT5cbjwhLS1GSVhNRSA6IG9ibGlnYXRpb24gZGUgZHVwbGlxdWVyIGljaSBwb3VyIGfDqXJlciBhIGxhIGZvaXMgaW5uZXJIVE1MICgvIVxcIHBhcyBkZSBvdXRlckhUTUwhKSBldCBsYSBwcsOpc2VuY2UgZHUgc2xvdC5cbiB2b2lyIHBvdXIgZml4IGVuIGFuZ3VsYXIgMTkgZMOpdGVjdGlvbiBkJ3VuIGNvbnRlbnUgZGFucyBsZSBzbG90IG91IHN1cHByZXNzaW9uIGRlIGlubmVySFRNTCBlbiB2MiAtLT5cbkBpZiAoIWhhc1JvdXRlckxpbmsoKSAmJiBtb2RlICE9PSAnYnV0dG9uJykge1xuICBAaWYgKGxhYmVsKSB7XG4gICAgPCEtLSBMaWVuIGV4dGVybmUgZXQgbGFiZWwgZW4gaW5uZXJIVE1MLS0+XG4gICAgPGFcbiAgICAgIFthdHRyLmFyaWEtY29udHJvbHNdPVwiYXJpYUNvbnRyb2xzIHx8IG51bGxcIlxuICAgICAgW2F0dHIuYXJpYS1jdXJyZW50XT1cImFyaWFDdXJyZW50IHx8IG51bGxcIlxuICAgICAgW2F0dHIuYXJpYS1kaXNhYmxlZF09XCJkaXNhYmxlZCB8fCBudWxsXCJcbiAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsIHx8IG51bGxcIlxuICAgICAgW2F0dHIuZGF0YS1mci1vcGVuZWRdPVwiYXJpYUNvbnRyb2xzID8gZmFsc2UgOiBudWxsXCJcbiAgICAgIFthdHRyLmhyZWZdPVwiZ2V0SHJlZigpIHx8IG51bGxcIlxuICAgICAgW2F0dHIuaWRdPVwibGlua0lkIHx8IG51bGxcIlxuICAgICAgW2F0dHIucmVsXT1cImxpbmtUYXJnZXQgPT09ICdfYmxhbmsnID8gJ25vb3BlbmVyIGV4dGVybmFsJyA6IG51bGxcIlxuICAgICAgW2F0dHIucm9sZV09XCJkaXNhYmxlZCA/ICdsaW5rJyA6IG51bGxcIlxuICAgICAgW2F0dHIudGFyZ2V0XT1cInRhcmdldExpbmsgfHwgbnVsbFwiXG4gICAgICBbYXR0ci50aXRsZV09XCJ0b29sdGlwTWVzc2FnZSB8fCBudWxsXCJcbiAgICAgIGNsYXNzPVwie3sgY3VzdG9tQ2xhc3MgPyBjdXN0b21DbGFzcyA6ICcnIH19XCJcbiAgICAgIFtjbGFzc05hbWVdPVwiaWNvbiA/IGljb24gOiAnJ1wiXG4gICAgICBbbmdDbGFzc109XCJnZXRDbGFzcygpXCJcbiAgICAgIChjbGljayk9XCJvbkxpbmsoJGV2ZW50KVwiXG4gICAgICBbaW5uZXJIVE1MXT1cImxhYmVsXCI+XG4gICAgPC9hPlxuICB9IEBlbHNlIHtcbiAgICA8IS0tIExpZW4gZXh0ZXJuZSBldCBzbG90IHBvdXIgbGUgbGFiZWwgLS0+XG4gICAgPGFcbiAgICAgIFthdHRyLmFyaWEtY29udHJvbHNdPVwiYXJpYUNvbnRyb2xzIHx8IG51bGxcIlxuICAgICAgW2F0dHIuYXJpYS1jdXJyZW50XT1cImFyaWFDdXJyZW50IHx8IG51bGxcIlxuICAgICAgW2F0dHIuYXJpYS1kaXNhYmxlZF09XCJkaXNhYmxlZCB8fCBudWxsXCJcbiAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsIHx8IG51bGxcIlxuICAgICAgW2F0dHIuZGF0YS1mci1vcGVuZWRdPVwiYXJpYUNvbnRyb2xzID8gZmFsc2UgOiBudWxsXCJcbiAgICAgIFthdHRyLmhyZWZdPVwiZ2V0SHJlZigpIHx8IG51bGxcIlxuICAgICAgW2F0dHIuaWRdPVwibGlua0lkIHx8IG51bGxcIlxuICAgICAgW2F0dHIucmVsXT1cImxpbmtUYXJnZXQgPT09ICdfYmxhbmsnID8gJ25vb3BlbmVyIGV4dGVybmFsJyA6IG51bGxcIlxuICAgICAgW2F0dHIucm9sZV09XCJkaXNhYmxlZCA/ICdsaW5rJyA6IG51bGxcIlxuICAgICAgW2F0dHIudGFyZ2V0XT1cInRhcmdldExpbmsgfHwgbnVsbFwiXG4gICAgICBbYXR0ci50aXRsZV09XCJ0b29sdGlwTWVzc2FnZSB8fCBudWxsXCJcbiAgICAgIGNsYXNzPVwie3sgY3VzdG9tQ2xhc3MgPyBjdXN0b21DbGFzcyA6ICcnIH19XCJcbiAgICAgIFtjbGFzc05hbWVdPVwiaWNvbiA/IGljb24gOiAnJ1wiXG4gICAgICBbbmdDbGFzc109XCJnZXRDbGFzcygpXCJcbiAgICAgIChjbGljayk9XCJvbkxpbmsoJGV2ZW50KVwiPlxuICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJzbG90XCI+IDwvbmctY29udGFpbmVyPlxuICAgIDwvYT5cbiAgfVxufSBAZWxzZSBpZiAoaGFzUm91dGVyTGluaygpICYmIG1vZGUgIT09ICdidXR0b24nKSB7XG4gIEBpZiAobGFiZWwpIHtcbiAgICA8IS0tIFJvdXRlcmxpbmsgIGV0IGxhYmVsIGVuIGlubmVySFRNTC0tPlxuICAgIDxhXG4gICAgICBbYXJpYUN1cnJlbnRXaGVuQWN0aXZlXT1cImFyaWFDdXJyZW50V2hlbkFjdGl2ZSA/PyAncGFnZSdcIlxuICAgICAgW2F0dHIuYXJpYS1jb250cm9sc109XCJhcmlhQ29udHJvbHMgfHwgbnVsbFwiXG4gICAgICBbYXR0ci5hcmlhLWN1cnJlbnRdPVwiYXJpYUN1cnJlbnQgfHwgbnVsbFwiXG4gICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cImRpc2FibGVkIHx8IG51bGxcIlxuICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWwgfHwgbnVsbFwiXG4gICAgICBbYXR0ci5pZF09XCJsaW5rSWQgfHwgbnVsbFwiXG4gICAgICBbYXR0ci5yb2xlXT1cImRpc2FibGVkID8gJ2xpbmsnIDogbnVsbFwiXG4gICAgICBbYXR0ci50YXJnZXRdPVwidGFyZ2V0TGluayB8fCBudWxsXCJcbiAgICAgIFthdHRyLnRpdGxlXT1cInRvb2x0aXBNZXNzYWdlIHx8IG51bGxcIlxuICAgICAgY2xhc3M9XCJ7eyBjdXN0b21DbGFzcyA/IGN1c3RvbUNsYXNzIDogJycgfX1cIlxuICAgICAgW2NsYXNzTmFtZV09XCJpY29uID8gaWNvbiA6ICcnXCJcbiAgICAgIFtmcmFnbWVudF09XCJyb3V0ZXJMaW5rRXh0cmFzPy5mcmFnbWVudFwiXG4gICAgICBbbmdDbGFzc109XCJnZXRDbGFzcygpXCJcbiAgICAgIFtwcmVzZXJ2ZUZyYWdtZW50XT1cInJvdXRlckxpbmtFeHRyYXM/LnByZXNlcnZlRnJhZ21lbnRcIlxuICAgICAgW3F1ZXJ5UGFyYW1zXT1cInJvdXRlckxpbmtFeHRyYXM/LnF1ZXJ5UGFyYW1zXCJcbiAgICAgIFtxdWVyeVBhcmFtc0hhbmRsaW5nXT1cInJvdXRlckxpbmtFeHRyYXM/LnF1ZXJ5UGFyYW1zSGFuZGxpbmdcIlxuICAgICAgW3JlcGxhY2VVcmxdPVwicm91dGVyTGlua0V4dHJhcz8ucmVwbGFjZVVybFwiXG4gICAgICBbcm91dGVyTGlua109XCJyb3V0ZVBhdGhcIlxuICAgICAgW3JvdXRlckxpbmtBY3RpdmVdPVwicm91dGVyTGlua0FjdGl2ZSA/PyAnJ1wiXG4gICAgICBbcm91dGVyTGlua0FjdGl2ZU9wdGlvbnNdPVwicm91dGVyTGlua0FjdGl2ZU9wdGlvbnMgPyByb3V0ZXJMaW5rQWN0aXZlT3B0aW9ucyA6IHsgZXhhY3Q6IGZhbHNlIH1cIlxuICAgICAgW3NraXBMb2NhdGlvbkNoYW5nZV09XCJyb3V0ZXJMaW5rRXh0cmFzPy5za2lwTG9jYXRpb25DaGFuZ2VcIlxuICAgICAgW3N0YXRlXT1cInJvdXRlckxpbmtFeHRyYXM/LnN0YXRlXCJcbiAgICAgIChjbGljayk9XCJvbkxpbmsoJGV2ZW50KVwiXG4gICAgICBbaW5uZXJIVE1MXT1cImxhYmVsXCI+XG4gICAgPC9hPlxuICB9IEBlbHNlIHtcbiAgICA8IS0tIFJvdXRlcmxpbmsgIGV0IHNsb3QgcG91ciBsZSBsYWJlbCAtLT5cbiAgICA8YVxuICAgICAgW2FyaWFDdXJyZW50V2hlbkFjdGl2ZV09XCJhcmlhQ3VycmVudFdoZW5BY3RpdmUgPz8gJ3BhZ2UnXCJcbiAgICAgIFthdHRyLmFyaWEtY29udHJvbHNdPVwiYXJpYUNvbnRyb2xzIHx8IG51bGxcIlxuICAgICAgW2F0dHIuYXJpYS1jdXJyZW50XT1cImFyaWFDdXJyZW50IHx8IG51bGxcIlxuICAgICAgW2F0dHIuYXJpYS1kaXNhYmxlZF09XCJkaXNhYmxlZCB8fCBudWxsXCJcbiAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsIHx8IG51bGxcIlxuICAgICAgW2F0dHIuaWRdPVwibGlua0lkIHx8IG51bGxcIlxuICAgICAgW2F0dHIucm9sZV09XCJkaXNhYmxlZCA/ICdsaW5rJyA6IG51bGxcIlxuICAgICAgW2F0dHIudGFyZ2V0XT1cInRhcmdldExpbmsgfHwgbnVsbFwiXG4gICAgICBbYXR0ci50aXRsZV09XCJ0b29sdGlwTWVzc2FnZSB8fCBudWxsXCJcbiAgICAgIGNsYXNzPVwie3sgY3VzdG9tQ2xhc3MgPyBjdXN0b21DbGFzcyA6ICcnIH19XCJcbiAgICAgIFtjbGFzc05hbWVdPVwiaWNvbiA/IGljb24gOiAnJ1wiXG4gICAgICBbZnJhZ21lbnRdPVwicm91dGVyTGlua0V4dHJhcz8uZnJhZ21lbnRcIlxuICAgICAgW25nQ2xhc3NdPVwiZ2V0Q2xhc3MoKVwiXG4gICAgICBbcHJlc2VydmVGcmFnbWVudF09XCJyb3V0ZXJMaW5rRXh0cmFzPy5wcmVzZXJ2ZUZyYWdtZW50XCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJyb3V0ZXJMaW5rRXh0cmFzPy5xdWVyeVBhcmFtc1wiXG4gICAgICBbcXVlcnlQYXJhbXNIYW5kbGluZ109XCJyb3V0ZXJMaW5rRXh0cmFzPy5xdWVyeVBhcmFtc0hhbmRsaW5nXCJcbiAgICAgIFtyZXBsYWNlVXJsXT1cInJvdXRlckxpbmtFeHRyYXM/LnJlcGxhY2VVcmxcIlxuICAgICAgW3JvdXRlckxpbmtdPVwicm91dGVQYXRoXCJcbiAgICAgIFtyb3V0ZXJMaW5rQWN0aXZlXT1cInJvdXRlckxpbmtBY3RpdmUgPz8gJydcIlxuICAgICAgW3JvdXRlckxpbmtBY3RpdmVPcHRpb25zXT1cInJvdXRlckxpbmtBY3RpdmVPcHRpb25zID8gcm91dGVyTGlua0FjdGl2ZU9wdGlvbnMgOiB7IGV4YWN0OiBmYWxzZSB9XCJcbiAgICAgIFtza2lwTG9jYXRpb25DaGFuZ2VdPVwicm91dGVyTGlua0V4dHJhcz8uc2tpcExvY2F0aW9uQ2hhbmdlXCJcbiAgICAgIFtzdGF0ZV09XCJyb3V0ZXJMaW5rRXh0cmFzPy5zdGF0ZVwiXG4gICAgICAoY2xpY2spPVwib25MaW5rKCRldmVudClcIj5cbiAgICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwic2xvdFwiPiA8L25nLWNvbnRhaW5lcj5cbiAgICA8L2E+XG4gIH1cbn0gQGVsc2UgaWYgKG1vZGUgPT09ICdidXR0b24nKSB7XG4gIEBpZiAobGFiZWwpIHtcbiAgICA8IS0tIEJvdXRvbiAgZXQgbGFiZWwgZW4gaW5uZXJIVE1MLS0+XG4gICAgPGJ1dHRvblxuICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICBbYXR0ci5pZF09XCJsaW5rSWRcIlxuICAgICAgW2F0dHIuYXJpYS1jb250cm9sc109XCJhcmlhQ29udHJvbHMgfHwgbnVsbFwiXG4gICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbCB8fCBudWxsXCJcbiAgICAgIFthdHRyLmRhdGEtZnItb3BlbmVkXT1cImFyaWFDb250cm9scyA/IGZhbHNlIDogbnVsbFwiXG4gICAgICBbYXR0ci50aXRsZV09XCJ0b29sdGlwTWVzc2FnZSB8fCBudWxsXCJcbiAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICBbbmdDbGFzc109XCJnZXRCdXR0b25DbGFzc2VzKClcIlxuICAgICAgKGNsaWNrKT1cIm9uTGluaygkZXZlbnQpXCJcbiAgICAgIFtpbm5lckhUTUxdPVwibGFiZWxcIj48L2J1dHRvbj5cbiAgfSBAZWxzZSB7XG4gICAgPCEtLSBCb3V0b24gIGV0IHNsb3QgcG91ciBsZSBsYWJlbC0tPlxuICAgIDxidXR0b25cbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgW2F0dHIuaWRdPVwibGlua0lkXCJcbiAgICAgIFthdHRyLmFyaWEtY29udHJvbHNdPVwiYXJpYUNvbnRyb2xzIHx8IG51bGxcIlxuICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWwgfHwgbnVsbFwiXG4gICAgICBbYXR0ci5kYXRhLWZyLW9wZW5lZF09XCJhcmlhQ29udHJvbHMgPyBmYWxzZSA6IG51bGxcIlxuICAgICAgW2F0dHIudGl0bGVdPVwidG9vbHRpcE1lc3NhZ2UgfHwgbnVsbFwiXG4gICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgW25nQ2xhc3NdPVwiZ2V0QnV0dG9uQ2xhc3NlcygpXCJcbiAgICAgIChjbGljayk9XCJvbkxpbmsoJGV2ZW50KVwiPlxuICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJzbG90XCI+IDwvbmctY29udGFpbmVyPlxuICAgIDwvYnV0dG9uPlxuICB9XG59XG5cbjwhLS0gRMOpY2xhcsOpIGRhbnMgdW4gdGVtcGxhdGUgOiBsZSBuZy1jb250ZW50IG5lIGRvaXQgw6p0cmUgcHLDqXNlbnQgcXUndW5lIHNldWxlIGZvaXMgLS0+XG48bmctdGVtcGxhdGUgI3Nsb3Q+XG4gIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbjwvbmctdGVtcGxhdGU+XG4iXX0=