UNPKG

@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).

141 lines 28 kB
import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core'; 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.size = DsfrSizeConst.MD; /** * Si l'input 'route' est renseigné, sa valeur sera émise lorsque le lien est sélectionné. */ this.linkSelect = new EventEmitter(); } /** @deprecated @since 1.5 utiliser `linkTarget` à la place. */ get targetLink() { return this.linkTarget; } /** @deprecated @since 1.5 utiliser `linkTarget` à la place. */ set targetLink(value) { this.linkTarget = value; } /** * @deprecated (@since 1.11.5) utiliser `routePath` à la place. * routerLink provoque un bug accessibilité sur la navigation au clavier (ajout d'un tabindex=0) **/ 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; } /** @internal */ /* * 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', ...) */ 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.size === DsfrSizeConst.SM, 'fr-link--lg': this.size === DsfrSizeConst.LG, }; } /** @internal */ getButtonClasses() { const classes = ['fr-btn', 'fr-btn--tertiary-no-outline']; if (this.customClass) classes.push(this.customClass); 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); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DsfrLinkComponent, deps: [{ token: i1.I18nService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DsfrLinkComponent, 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", size: "size", tooltipMessage: "tooltipMessage", mode: "mode", targetLink: "targetLink", routerLink: "routerLink" }, outputs: { linkSelect: "linkSelect" }, ngImport: i0, template: "<!-- Lien externe ou g\u00E9r\u00E9 programmatiquement -->\n<a\n *ngIf=\"!hasRouterLink() && mode !== 'button'\"\n class=\"{{ customClass ? customClass : '' }}\"\n [className]=\"icon ? icon : ''\"\n [ngClass]=\"getClass()\"\n [attr.aria-current]=\"ariaCurrent || null\"\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.role]=\"disabled ? 'link' : null\"\n [attr.id]=\"linkId || null\"\n [attr.href]=\"getHref() || null\"\n [attr.target]=\"targetLink || null\"\n [attr.title]=\"tooltipMessage || null\"\n [attr.rel]=\"linkTarget === '_blank' ? 'noopener external' : null\"\n [attr.data-fr-opened]=\"ariaControls ? false : null\"\n (click)=\"onLink($event)\">\n <div *ngIf=\"label\" [outerHTML]=\"label\"></div>\n <ng-container *ngIf=\"!label\" [ngTemplateOutlet]=\"slot\"></ng-container>\n</a>\n\n<!-- Directive router link-->\n<a\n *ngIf=\"hasRouterLink() && mode !== 'button'\"\n [attr.id]=\"linkId || null\"\n class=\"{{ customClass ? customClass : '' }}\"\n [className]=\"icon ? icon : ''\"\n [ngClass]=\"getClass()\"\n [ariaCurrentWhenActive]=\"'page'\"\n [attr.aria-current]=\"ariaCurrent || null\"\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.role]=\"disabled ? 'link' : null\"\n [routerLink]=\"routePath\"\n [routerLinkActive]=\"routerLinkActive ?? ''\"\n [routerLinkActiveOptions]=\"routerLinkActiveOptions ? routerLinkActiveOptions : { exact: false }\"\n [queryParams]=\"routerLinkExtras?.queryParams\"\n [fragment]=\"routerLinkExtras?.fragment\"\n [queryParamsHandling]=\"routerLinkExtras?.queryParamsHandling\"\n [preserveFragment]=\"routerLinkExtras?.preserveFragment\"\n [skipLocationChange]=\"routerLinkExtras?.skipLocationChange\"\n [replaceUrl]=\"routerLinkExtras?.replaceUrl\"\n [state]=\"routerLinkExtras?.state\"\n [attr.target]=\"targetLink || null\"\n [attr.title]=\"tooltipMessage || null\"\n (click)=\"onLink($event)\">\n <div *ngIf=\"label\" [outerHTML]=\"label\"></div>\n <ng-container *ngIf=\"!label\" [ngTemplateOutlet]=\"slot\"> </ng-container>\n</a>\n\n<!-- Bouton en apparence de lien-->\n<button\n *ngIf=\"mode === 'button'\"\n type=\"button\"\n [ngClass]=\"getButtonClasses()\"\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 (click)=\"onLink($event)\">\n <div *ngIf=\"label\" [outerHTML]=\"label\"></div>\n <ng-container *ngIf=\"!label\" [ngTemplateOutlet]=\"slot\"> </ng-container>\n</button>\n\n<ng-template #slot>\n <ng-content></ng-content>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "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: "16.2.12", ngImport: i0, type: DsfrLinkComponent, decorators: [{ type: Component, args: [{ selector: 'dsfr-link', encapsulation: ViewEncapsulation.None, template: "<!-- Lien externe ou g\u00E9r\u00E9 programmatiquement -->\n<a\n *ngIf=\"!hasRouterLink() && mode !== 'button'\"\n class=\"{{ customClass ? customClass : '' }}\"\n [className]=\"icon ? icon : ''\"\n [ngClass]=\"getClass()\"\n [attr.aria-current]=\"ariaCurrent || null\"\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.role]=\"disabled ? 'link' : null\"\n [attr.id]=\"linkId || null\"\n [attr.href]=\"getHref() || null\"\n [attr.target]=\"targetLink || null\"\n [attr.title]=\"tooltipMessage || null\"\n [attr.rel]=\"linkTarget === '_blank' ? 'noopener external' : null\"\n [attr.data-fr-opened]=\"ariaControls ? false : null\"\n (click)=\"onLink($event)\">\n <div *ngIf=\"label\" [outerHTML]=\"label\"></div>\n <ng-container *ngIf=\"!label\" [ngTemplateOutlet]=\"slot\"></ng-container>\n</a>\n\n<!-- Directive router link-->\n<a\n *ngIf=\"hasRouterLink() && mode !== 'button'\"\n [attr.id]=\"linkId || null\"\n class=\"{{ customClass ? customClass : '' }}\"\n [className]=\"icon ? icon : ''\"\n [ngClass]=\"getClass()\"\n [ariaCurrentWhenActive]=\"'page'\"\n [attr.aria-current]=\"ariaCurrent || null\"\n [attr.aria-controls]=\"ariaControls || null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.role]=\"disabled ? 'link' : null\"\n [routerLink]=\"routePath\"\n [routerLinkActive]=\"routerLinkActive ?? ''\"\n [routerLinkActiveOptions]=\"routerLinkActiveOptions ? routerLinkActiveOptions : { exact: false }\"\n [queryParams]=\"routerLinkExtras?.queryParams\"\n [fragment]=\"routerLinkExtras?.fragment\"\n [queryParamsHandling]=\"routerLinkExtras?.queryParamsHandling\"\n [preserveFragment]=\"routerLinkExtras?.preserveFragment\"\n [skipLocationChange]=\"routerLinkExtras?.skipLocationChange\"\n [replaceUrl]=\"routerLinkExtras?.replaceUrl\"\n [state]=\"routerLinkExtras?.state\"\n [attr.target]=\"targetLink || null\"\n [attr.title]=\"tooltipMessage || null\"\n (click)=\"onLink($event)\">\n <div *ngIf=\"label\" [outerHTML]=\"label\"></div>\n <ng-container *ngIf=\"!label\" [ngTemplateOutlet]=\"slot\"> </ng-container>\n</a>\n\n<!-- Bouton en apparence de lien-->\n<button\n *ngIf=\"mode === 'button'\"\n type=\"button\"\n [ngClass]=\"getButtonClasses()\"\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 (click)=\"onLink($event)\">\n <div *ngIf=\"label\" [outerHTML]=\"label\"></div>\n <ng-container *ngIf=\"!label\" [ngTemplateOutlet]=\"slot\"> </ng-container>\n</button>\n\n<ng-template #slot>\n <ng-content></ng-content>\n</ng-template>\n" }] }], ctorParameters: function () { return [{ type: i1.I18nService }]; }, 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 }], size: [{ type: Input }], tooltipMessage: [{ type: Input }], mode: [{ type: Input }], linkSelect: [{ type: Output }], targetLink: [{ type: Input }], routerLink: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGluay5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZHNmci1jb21wb25lbnRzL3NyYy9saWIvY29tcG9uZW50cy9saW5rL2xpbmsuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWRzZnItY29tcG9uZW50cy9zcmMvbGliL2NvbXBvbmVudHMvbGluay9saW5rLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFbEcsT0FBTyxFQUdMLG1CQUFtQixFQUVuQixpQkFBaUIsRUFFakIsYUFBYSxHQUVkLE1BQU0sY0FBYyxDQUFDOzs7OztBQU90QixNQUFNLE9BQU8saUJBQWlCO0lBbUU1QixZQUFvQixJQUFpQjtRQUFqQixTQUFJLEdBQUosSUFBSSxDQUFhO1FBdERyQzs7V0FFRztRQUNNLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFLMUIsZ0RBQWdEO1FBQ3ZDLGlCQUFZLEdBQTZCLGlCQUFpQixDQUFDLEtBQUssQ0FBQztRQStCMUUsc0JBQXNCO1FBQ2IsU0FBSSxHQUFhLGFBQWEsQ0FBQyxFQUFFLENBQUM7UUFRM0M7O1dBRUc7UUFDTyxlQUFVLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztJQUVWLENBQUM7SUFFekMsK0RBQStEO0lBQy9ELElBQUksVUFBVTtRQUNaLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUN6QixDQUFDO0lBRUQsK0RBQStEO0lBQy9ELElBQWEsVUFBVSxDQUFDLEtBQWlDO1FBQ3ZELElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO0lBQzFCLENBQUM7SUFFRDs7O1FBR0k7SUFDSixJQUFhLFVBQVUsQ0FBQyxLQUFvQztRQUMxRCxJQUFJLEtB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QUs7Z0JBR0csWUFBWTtzQkFBcEIsS0FBSztnQkFHRyxXQUFXO3NCQUFuQixLQUFLO2dCQUtHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBR0csSUFBSTtzQkFBWixLQUFLO2dCQUdHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBR0csTUFBTTtzQkFBZCxLQUFLO2dCQUdHLEtBQUs7c0JBQWIsS0FBSztnQkFHRyxJQUFJO3NCQUFaLEtBQUs7Z0JBS0csVUFBVTtzQkFBbEIsS0FBSztnQkFHRyxLQUFLO3NCQUFiLEtBQUs7Z0JBR0csU0FBUztzQkFBakIsS0FBSztnQkFHRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBR0csdUJBQXVCO3NCQUEvQixLQUFLO2dCQUdHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFHRyxJQUFJO3NCQUFaLEtBQUs7Z0JBR0csY0FBYztzQkFBdEIsS0FBSztnQkFHRyxJQUFJO3NCQUFaLEtBQUs7Z0JBS0ksVUFBVTtzQkFBbkIsTUFBTTtnQkFVTSxVQUFVO3NCQUF0QixLQUFLO2dCQVFPLFVBQVU7c0JBQXRCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uSW5pdCwgT3V0cHV0LCBWaWV3RW5jYXBzdWxhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSXNBY3RpdmVNYXRjaE9wdGlvbnMsIE5hdmlnYXRpb25FeHRyYXMgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHtcbiAgRHNmckxpbmssXG4gIERzZnJMaW5rVGFyZ2V0LFxuICBEc2ZyTGlua1RhcmdldENvbnN0LFxuICBEc2ZyUG9zaXRpb24sXG4gIERzZnJQb3NpdGlvbkNvbnN0LFxuICBEc2ZyU2l6ZSxcbiAgRHNmclNpemVDb25zdCxcbiAgSTE4blNlcnZpY2UsXG59IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2RzZnItbGluaycsXG4gIHRlbXBsYXRlVXJsOiAnLi9saW5rLmNvbXBvbmVudC5odG1sJyxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbn0pXG5leHBvcnQgY2xhc3MgRHNmckxpbmtDb21wb25lbnQgaW1wbGVtZW50cyBPbWl0PERzZnJMaW5rLCAnYWN0aXZlJyB8ICd0YXJnZXQnPiwgT25Jbml0IHtcbiAgLyoqIFBlcm1ldCBkJ2Fqb3V0ZXIgdW4gYXR0cmlidXQgYGFyaWEtY3VycmVudGAgc3VyIGxlIGxpZW4uKi9cbiAgQElucHV0KCkgYXJpYUN1cnJlbnQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAvKiogQHNpbmNlIDEuNC4wIExhIHByb3ByacOpdMOpIGFyaWFMYWJlbCBkw6lmaW5pdCB1bmUgdmFsZXVyIGRlIGNoYcOubmUgcXVpIMOpdGlxdWV0dGUgdW4gw6lsw6ltZW50IGludGVyYWN0aWYuICovXG4gIEBJbnB1dCgpIGFyaWFMYWJlbDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBAc2luY2UgMS43IElkZW50aWZpZSBsJ8OpbMOpbWVudCAob3UgbGVzIMOpbMOpbWVudHMpIGNvbnRyw7Rsw6kgcGFyIGNldCDDqWzDqW1lbnQuICovXG4gIEBJbnB1dCgpIGFyaWFDb250cm9sczogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBQb3VyIGFqb3V0ZXIgZGVzIGNsYXNzZXMgQ1NTIGN1c3RvbS4gKi9cbiAgQElucHV0KCkgY3VzdG9tQ2xhc3M6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogUGVybWV0IGRlIGTDqXNhY3RpdmVyIGxlIGNvbXBvc2FudC5cbiAgICovXG4gIEBJbnB1dCgpIGRpc2FibGVkID0gZmFsc2U7XG5cbiAgLyoqIENsYXNzZSBkZSBsJ2ljw7RuZS4gKi9cbiAgQElucHV0KCkgaWNvbjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBQb3NpdGlvbiBkZSBsJ2ljw7RuZS4gw4AgZHJvaXRlIHBhciBkw6lmYXV0LiAqL1xuICBASW5wdXQoKSBpY29uUG9zaXRpb246IERzZnJQb3NpdGlvbiB8IHVuZGVmaW5lZCA9IERzZnJQb3NpdGlvbkNvbnN0LlJJR0hUO1xuXG4gIC8qKiBAc2luY2UgMS42ICovXG4gIEBJbnB1dCgpIGxpbmtJZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBUZXh0ZSBkdSBsaWVuLiAqL1xuICBASW5wdXQoKSBsYWJlbDogc3RyaW5nO1xuXG4gIC8qKiBMaWVuIGhyZWYgZXh0ZXJuZSwgZXhjbHVzaWYgYXZlYyByb3V0ZSBldCByb3V0ZVBhdGguICovXG4gIEBJbnB1dCgpIGxpbms6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAvKiogQXR0cmlidXQgdGFyZ2V0IGR1IGxpZW4uICovXG4gIC8vIExlIG5vbSAndGFyZ2V0JyBjcsOpZSB1biBwcm9ibMOobWUgYXZlYyBsZSBDU1MgRFNGUiwgcHVpc3F1ZSBkdSBjb3VwLCBvbiBhIHRhcmdldD1cIl9ibGFua1wiIGRhbnMgbGUgaG9zdCBldCB1blxuICAvLyBzdHlsZSBzJ2FwcGxpcXVlLCBjZSBxdWkgcHJvdm9xdWUgdW4gZG91YmxlbWVudCBkZSBsJ2ljw7RuZSBsaWVuIGV4dGVybmUuXG4gIEBJbnB1dCgpIGxpbmtUYXJnZXQ6IERzZnJMaW5rVGFyZ2V0IHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBQYXRoIGludGVybmUuIEV4Y2x1c2lmIGF2ZWMgbGluayBldCByb3V0ZVBhdGgsIHByaW9yaXRhaXJlIHN1ciBsaW5rLiAqL1xuICBASW5wdXQoKSByb3V0ZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBQYXRoIGFuZ3VsYXIgZ8OpcsOpIGVuIHRhbnQgcXVlIGRpcmVjdGl2ZSByb3V0ZXJMaW5rLiBQcmlvcml0YWlyZSBldCBleGNsdXNpZiBhdmVjIGxpbmsgZXQgcm91dGUuICovXG4gIEBJbnB1dCgpIHJvdXRlUGF0aDogc3RyaW5nIHwgc3RyaW5nW10gfCB1bmRlZmluZWQ7XG5cbiAgLyoqIENsYXNzZSBDU1MgdXRpbGlzw6llIHBvdXIgbGEgZGlyZWN0aXZlIHJvdXRlckxpbmsgYWN0aXZlLiAqL1xuICBASW5wdXQoKSByb3V0ZXJMaW5rQWN0aXZlOiBzdHJpbmcgfCBzdHJpbmdbXSB8IHVuZGVmaW5lZDtcblxuICAvKiogUm91dGVyTGluayA6IG9wdGlvbnMgYWRkaXRpb25uZWxsZXMgcG91ciBsZSByb3V0ZXJMaW5rQWN0aXZlIChleGFjdCkuICovXG4gIEBJbnB1dCgpIHJvdXRlckxpbmtBY3RpdmVPcHRpb25zOiB7IGV4YWN0OiBib29sZWFuIH0gfCBJc0FjdGl2ZU1hdGNoT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAvKiogUm91dGVyTGluayA6IG9wdGlvbnMgYWRkaXRpb25uZWxsZXMgcHBvdXIgbGUgcm91dGVyTGluayAocXVlcnlQYXJhbXMsIHN0YXRlLCBldGMuKSAqL1xuICBASW5wdXQoKSByb3V0ZXJMaW5rRXh0cmFzOiBOYXZpZ2F0aW9uRXh0cmFzIHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBUYWlsbGUgZHUgbGllbi4gKi9cbiAgQElucHV0KCkgc2l6ZTogRHNmclNpemUgPSBEc2ZyU2l6ZUNvbnN0Lk1EO1xuXG4gIC8qKiBNZXNzYWdlIGR1IHRvb2x0aXAgKGF0dHJpYnV0IHRpdGxlKS4gQHNpbmNlIDEuMy4wICovXG4gIEBJbnB1dCgpIHRvb2x0aXBNZXNzYWdlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgLyoqIEBzaW5jZSAxLjcuMCBUcmFuc2Zvcm1lIHVuIGxpZW4gZW4gYm91dG9uIHNpIGBidXR0b25gLCBgbGlua2AgcGFyIGTDqWZhdXQuICovXG4gIEBJbnB1dCgpIG1vZGU6ICdsaW5rJyB8ICdidXR0b24nIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBTaSBsJ2lucHV0ICdyb3V0ZScgZXN0IHJlbnNlaWduw6ksIHNhIHZhbGV1ciBzZXJhIMOpbWlzZSBsb3JzcXVlIGxlIGxpZW4gZXN0IHPDqWxlY3Rpb25uw6kuXG4gICAqL1xuICBAT3V0cHV0KCkgbGlua1NlbGVjdCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaTE4bjogSTE4blNlcnZpY2UpIHt9XG5cbiAgLyoqIEBkZXByZWNhdGVkIEBzaW5jZSAxLjUgdXRpbGlzZXIgYGxpbmtUYXJnZXRgIMOgIGxhIHBsYWNlLiAqL1xuICBnZXQgdGFyZ2V0TGluaygpOiBEc2ZyTGlua1RhcmdldCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMubGlua1RhcmdldDtcbiAgfVxuXG4gIC8qKiBAZGVwcmVjYXRlZCBAc2luY2UgMS41IHV0aWxpc2VyIGBsaW5rVGFyZ2V0YCDDoCBsYSBwbGFjZS4gKi9cbiAgQElucHV0KCkgc2V0IHRhcmdldExpbmsodmFsdWU6IERzZnJMaW5rVGFyZ2V0IHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5saW5rVGFyZ2V0ID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgKEBzaW5jZSAxLjExLjUpIHV0aWxpc2VyIGByb3V0ZVBhdGhgIMOgIGxhIHBsYWNlLlxuICAgKiByb3V0ZXJMaW5rIHByb3ZvcXVlIHVuIGJ1ZyBhY2Nlc3NpYmlsaXTDqSBzdXIgbGEgbmF2aWdhdGlvbiBhdSBjbGF2aWVyIChham91dCBkJ3VuIHRhYmluZGV4PTApXG4gICAqKi9cbiAgQElucHV0KCkgc2V0IHJvdXRlckxpbmsodmFsdWU6IHN0cmluZyB8IHN0cmluZ1tdIHwgdW5kZWZpbmVkKSB7XG4gICAgaWYgKHZhbHVlKSB0aGlzLnJvdXRlUGF0aCA9IHZhbHVlO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMubGlua1RhcmdldCA9PT0gRHNmckxpbmtUYXJnZXRDb25zdC5CTEFOSykge1xuICAgICAgdGhpcy50b29sdGlwTWVzc2FnZSA9IHRoaXMudG9vbHRpcE1lc3NhZ2VcbiAgICAgICAgPyBgICR7dGhpcy50b29sdGlwTWVzc2FnZX0gLSAke3RoaXMuaTE4bi50KCdsaW5rLm5ld1dpbmRvdycpfWBcbiAgICAgICAgOiBgJHt0aGlzLmkxOG4udCgnbGluay5uZXdXaW5kb3cnKX1gO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgZ2V0SHJlZigpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmRpc2FibGVkID8gdW5kZWZpbmVkIDogdGhpcy5saW5rIHx8IHRoaXMucm91dGU7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIGhhc1JvdXRlckxpbmsoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICF0aGlzLmRpc2FibGVkICYmICEhdGhpcy5yb3V0ZVBhdGg7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIC8qXG4gICAqIERzZnJMaW5rIGVzdCBwYXJ0YWfDqSBwYXIgcGx1c2lldXJzIGNvbXBvc2FudHMsICd0YWcnLCAnY2FyZCcgZXQgJ3RpbGUnIMOgIGxhIHBsYWNlIGQndW4gc2ltcGxlIGxpZW4uXG4gICAqIENlbGEgcGVybWV0IGRlIGLDqW7DqWZpY2llciBkZXMgbm9tYnJldXNlcyBjYXJhY3TDqXJpc3RpcXVlcyBkdSBjb21wb3NhbnQgRHNmckxpbmsuXG4gICAqIEBzaW5jZSAxLjUgQ2VwZW5kYW50LCBsYSBjbGFzc2UgJ2ZyLWxpbmsnIG5lIGRvaXQgcGFzIGNvaGFiaXRlciBsZXMgY2xhc3NlcyBkZSBjZXMgY29tcG9zYW50cyAoJ2ZyLXRhZycsIC4uLilcbiAgICovXG4gIGdldENsYXNzKCkge1xuICAgIHJldHVybiB7XG4gICAgICAnZnItbGluayc6ICF0aGlzLmN1c3RvbUNsYXNzICYmICF0aGlzLmRpc2FibGVkLFxuICAgICAgJ2ZyLWxpbmstLWljb24tcmlnaHQnOiB0aGlzLmljb24gJiYgdGhpcy5pY29uUG9zaXRpb24gPT09IERzZnJQb3NpdGlvbkNvbnN0LlJJR0hULFxuICAgICAgJ2ZyLWxpbmstLWljb24tbGVmdCc6IHRoaXMuaWNvbiAmJiB0aGlzLmljb25Qb3NpdGlvbiA9PT0gRHNmclBvc2l0aW9uQ29uc3QuTEVGVCxcbiAgICAgICdmci1saW5rLS1zbSc6IHRoaXMuc2l6ZSA9PT0gRHNmclNpemVDb25zdC5TTSxcbiAgICAgICdmci1saW5rLS1sZyc6IHRoaXMuc2l6ZSA9PT0gRHNmclNpemVDb25zdC5MRyxcbiAgICB9O1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBnZXRCdXR0b25DbGFzc2VzKCk6IHN0cmluZyB7XG4gICAgY29uc3QgY2xhc3NlcyA9IFsnZnItYnRuJywgJ2ZyLWJ0bi0tdGVydGlhcnktbm8tb3V0bGluZSddO1xuICAgIGlmICh0aGlzLmN1c3RvbUNsYXNzKSBjbGFzc2VzLnB1c2godGhpcy5jdXN0b21DbGFzcyk7XG5cbiAgICBpZiAodGhpcy5pY29uKSB7XG4gICAgICBjbGFzc2VzLnB1c2godGhpcy5pY29uKTtcbiAgICAgIGNsYXNzZXMucHVzaCh0aGlzLmljb25Qb3NpdGlvbiA9PT0gRHNmclBvc2l0aW9uQ29uc3QuUklHSFQgPyAnZnItYnRuLS1pY29uLXJpZ2h0JyA6ICdmci1idG4tLWljb24tbGVmdCcpO1xuICAgIH1cblxuICAgIHJldHVybiBjbGFzc2VzLmpvaW4oJyAnKTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgb25MaW5rKGV2ZW50OiBFdmVudCkge1xuICAgIGlmICh0aGlzLnJvdXRlICYmICF0aGlzLnJvdXRlUGF0aCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHRoaXMubGlua1NlbGVjdC5lbWl0KHRoaXMucm91dGUpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5saW5rKSB7XG4gICAgICB0aGlzLmxpbmtTZWxlY3QuZW1pdCh0aGlzLmxpbmspO1xuICAgIH1cbiAgfVxufVxuIiwiPCEtLSBMaWVuIGV4dGVybmUgb3UgZ8OpcsOpIHByb2dyYW1tYXRpcXVlbWVudCAtLT5cbjxhXG4gICpuZ0lmPVwiIWhhc1JvdXRlckxpbmsoKSAmJiBtb2RlICE9PSAnYnV0dG9uJ1wiXG4gIGNsYXNzPVwie3sgY3VzdG9tQ2xhc3MgPyBjdXN0b21DbGFzcyA6ICcnIH19XCJcbiAgW2NsYXNzTmFtZV09XCJpY29uID8gaWNvbiA6ICcnXCJcbiAgW25nQ2xhc3NdPVwiZ2V0Q2xhc3MoKVwiXG4gIFthdHRyLmFyaWEtY3VycmVudF09XCJhcmlhQ3VycmVudCB8fCBudWxsXCJcbiAgW2F0dHIuYXJpYS1jb250cm9sc109XCJhcmlhQ29udHJvbHMgfHwgbnVsbFwiXG4gIFthdHRyLmFyaWEtZGlzYWJsZWRdPVwiZGlzYWJsZWQgfHwgbnVsbFwiXG4gIFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsIHx8IG51bGxcIlxuICBbYXR0ci5yb2xlXT1cImRpc2FibGVkID8gJ2xpbmsnIDogbnVsbFwiXG4gIFthdHRyLmlkXT1cImxpbmtJZCB8fCBudWxsXCJcbiAgW2F0dHIuaHJlZl09XCJnZXRIcmVmKCkgfHwgbnVsbFwiXG4gIFthdHRyLnRhcmdldF09XCJ0YXJnZXRMaW5rIHx8IG51bGxcIlxuICBbYXR0ci50aXRsZV09XCJ0b29sdGlwTWVzc2FnZSB8fCBudWxsXCJcbiAgW2F0dHIucmVsXT1cImxpbmtUYXJnZXQgPT09ICdfYmxhbmsnID8gJ25vb3BlbmVyIGV4dGVybmFsJyA6IG51bGxcIlxuICBbYXR0ci5kYXRhLWZyLW9wZW5lZF09XCJhcmlhQ29udHJvbHMgPyBmYWxzZSA6IG51bGxcIlxuICAoY2xpY2spPVwib25MaW5rKCRldmVudClcIj5cbiAgPGRpdiAqbmdJZj1cImxhYmVsXCIgW291dGVySFRNTF09XCJsYWJlbFwiPjwvZGl2PlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWxhYmVsXCIgW25nVGVtcGxhdGVPdXRsZXRdPVwic2xvdFwiPjwvbmctY29udGFpbmVyPlxuPC9hPlxuXG48IS0tIERpcmVjdGl2ZSByb3V0ZXIgbGluay0tPlxuPGFcbiAgKm5nSWY9XCJoYXNSb3V0ZXJMaW5rKCkgJiYgbW9kZSAhPT0gJ2J1dHRvbidcIlxuICBbYXR0ci5pZF09XCJsaW5rSWQgfHwgbnVsbFwiXG4gIGNsYXNzPVwie3sgY3VzdG9tQ2xhc3MgPyBjdXN0b21DbGFzcyA6ICcnIH19XCJcbiAgW2NsYXNzTmFtZV09XCJpY29uID8gaWNvbiA6ICcnXCJcbiAgW25nQ2xhc3NdPVwiZ2V0Q2xhc3MoKVwiXG4gIFthcmlhQ3VycmVudFdoZW5BY3RpdmVdPVwiJ3BhZ2UnXCJcbiAgW2F0dHIuYXJpYS1jdXJyZW50XT1cImFyaWFDdXJyZW50IHx8IG51bGxcIlxuICBbYXR0ci5hcmlhLWNvbnRyb2xzXT1cImFyaWFDb250cm9scyB8fCBudWxsXCJcbiAgW2F0dHIuYXJpYS1kaXNhYmxlZF09XCJkaXNhYmxlZCB8fCBudWxsXCJcbiAgW2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWwgfHwgbnVsbFwiXG4gIFthdHRyLnJvbGVdPVwiZGlzYWJsZWQgPyAnbGluaycgOiBudWxsXCJcbiAgW3JvdXRlckxpbmtdPVwicm91dGVQYXRoXCJcbiAgW3JvdXRlckxpbmtBY3RpdmVdPVwicm91dGVyTGlua0FjdGl2ZSA/PyAnJ1wiXG4gIFtyb3V0ZXJMaW5rQWN0aXZlT3B0aW9uc109XCJyb3V0ZXJMaW5rQWN0aXZlT3B0aW9ucyA/IHJvdXRlckxpbmtBY3RpdmVPcHRpb25zIDogeyBleGFjdDogZmFsc2UgfVwiXG4gIFtxdWVyeVBhcmFtc109XCJyb3V0ZXJMaW5rRXh0cmFzPy5xdWVyeVBhcmFtc1wiXG4gIFtmcmFnbWVudF09XCJyb3V0ZXJMaW5rRXh0cmFzPy5mcmFnbWVudFwiXG4gIFtxdWVyeVBhcmFtc0hhbmRsaW5nXT1cInJvdXRlckxpbmtFeHRyYXM/LnF1ZXJ5UGFyYW1zSGFuZGxpbmdcIlxuICBbcHJlc2VydmVGcmFnbWVudF09XCJyb3V0ZXJMaW5rRXh0cmFzPy5wcmVzZXJ2ZUZyYWdtZW50XCJcbiAgW3NraXBMb2NhdGlvbkNoYW5nZV09XCJyb3V0ZXJMaW5rRXh0cmFzPy5za2lwTG9jYXRpb25DaGFuZ2VcIlxuICBbcmVwbGFjZVVybF09XCJyb3V0ZXJMaW5rRXh0cmFzPy5yZXBsYWNlVXJsXCJcbiAgW3N0YXRlXT1cInJvdXRlckxpbmtFeHRyYXM/LnN0YXRlXCJcbiAgW2F0dHIudGFyZ2V0XT1cInRhcmdldExpbmsgfHwgbnVsbFwiXG4gIFthdHRyLnRpdGxlXT1cInRvb2x0aXBNZXNzYWdlIHx8IG51bGxcIlxuICAoY2xpY2spPVwib25MaW5rKCRldmVudClcIj5cbiAgPGRpdiAqbmdJZj1cImxhYmVsXCIgW291dGVySFRNTF09XCJsYWJlbFwiPjwvZGl2PlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWxhYmVsXCIgW25nVGVtcGxhdGVPdXRsZXRdPVwic2xvdFwiPiA8L25nLWNvbnRhaW5lcj5cbjwvYT5cblxuPCEtLSBCb3V0b24gZW4gYXBwYXJlbmNlIGRlIGxpZW4tLT5cbjxidXR0b25cbiAgKm5nSWY9XCJtb2RlID09PSAnYnV0dG9uJ1wiXG4gIHR5cGU9XCJidXR0b25cIlxuICBbbmdDbGFzc109XCJnZXRCdXR0b25DbGFzc2VzKClcIlxuICBbYXR0ci5hcmlhLWNvbnRyb2xzXT1cImFyaWFDb250cm9scyB8fCBudWxsXCJcbiAgW2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWwgfHwgbnVsbFwiXG4gIFthdHRyLmRhdGEtZnItb3BlbmVkXT1cImFyaWFDb250cm9scyA/IGZhbHNlIDogbnVsbFwiXG4gIFthdHRyLnRpdGxlXT1cInRvb2x0aXBNZXNzYWdlIHx8IG51bGxcIlxuICAoY2xpY2spPVwib25MaW5rKCRldmVudClcIj5cbiAgPGRpdiAqbmdJZj1cImxhYmVsXCIgW291dGVySFRNTF09XCJsYWJlbFwiPjwvZGl2PlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWxhYmVsXCIgW25nVGVtcGxhdGVPdXRsZXRdPVwic2xvdFwiPiA8L25nLWNvbnRhaW5lcj5cbjwvYnV0dG9uPlxuXG48bmctdGVtcGxhdGUgI3Nsb3Q+XG4gIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbjwvbmctdGVtcGxhdGU+XG4iXX0=