@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).
90 lines • 22.5 kB
JavaScript
import { Component, forwardRef, HostListener, ViewEncapsulation } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { DsfrFormInputComponent, DsfrInputTypeConst } from '../form-input';
import { isEmailValid } from './email-utils';
import * as i0 from "@angular/core";
import * as i1 from "../../shared";
import * as i2 from "@angular/common";
import * as i3 from "@angular/forms";
import * as i4 from "../../shared/components/input-group/input-group.component";
import * as i5 from "../../components/button/button.component";
/*
* Saisie d'une adresse email, si la valeur est validée en sortie de champ, elle est passée en minuscules.
*/
export class DsfrFormEmailComponent extends DsfrFormInputComponent {
/** @internal */
constructor(i18n) {
super();
this.i18n = i18n;
/** @internal */ this.errorMessage = this.i18n.t('email.error');
}
/**
* Au fil de la saisie, on ne vérifie le mail que s'il y avait déjà une erreur
*/
/** @internal */
onValueChange() {
if (this.error)
this.validate();
}
/**
* Vérification quand on sort du champ
*/
/** @internal */
onFocusOut() {
if (this.validate())
this.value = this.value?.toLowerCase();
}
/**
* Vrai si l'email est validé.
*/
/** @internal */
isValid() {
this._isValid ??= this.validate();
return this._isValid;
}
/** @internal*/
ngOnInit() {
super.ngOnInit();
this.type = DsfrInputTypeConst.EMAIL;
this.spellCheck = false;
this.label ??= this.i18n.t('email.label');
this.hint ??= this.i18n.t('email.hint');
this.autocomplete = 'email'; // @since 1.6
this.autoCorrect = false; // @since 1.6
}
/**
* Méthode validation, positionne la propriété error s'il y a lieu.
*/
validate() {
// Validators.email ne marche pas très bien dans la version 14, en effet 'nom@d' est validé
// TODO Vérifier le validator d'email d'Angular 15
this._isValid = isEmailValid(this.value, this.pattern);
this.error = this._isValid ? '' : this.errorMessage;
return this._isValid;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DsfrFormEmailComponent, deps: [{ token: i1.I18nService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DsfrFormEmailComponent, selector: "dsfr-form-email", host: { listeners: { "input": "onValueChange()", "change": "onFocusOut()" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DsfrFormEmailComponent),
multi: true,
},
], usesInheritance: true, ngImport: i0, template: "<edu-input-group\n [inputId]=\"inputId\"\n [label]=\"label\"\n [hint]=\"hint\"\n [messagesGroupId]=\"messagesGroupId\"\n [disabled]=\"disabled\"\n [message]=\"message\"\n [severity]=\"severity\">\n <label class=\"fr-label\" [for]=\"inputId\">\n <ng-container *ngIf=\"label\">{{ label }}</ng-container>\n <ng-content *ngIf=\"!label\" select=\"[label]\"></ng-content>\n <span *ngIf=\"hint\" class=\"fr-hint-text\">{{ hint }}</span>\n </label>\n <ng-container *ngIf=\"!isTextArea(); else textareaTemplate\">\n <ng-container *ngIf=\"!hasInputWrap(); else inputWrapTemplate\" [ngTemplateOutlet]=\"inputTemplate\"></ng-container>\n </ng-container>\n</edu-input-group>\n\n<!-- Templates -------------------------------------------------------------------------------------------------------->\n\n<!-- Template input -->\n<ng-template #inputTemplate>\n <input\n class=\"fr-input\"\n [ngClass]=\"customClass || null\"\n [attr.autocomplete]=\"autocomplete || null\"\n [attr.aria-autocomplete]=\"ariaAutocomplete || null\"\n [attr.aria-describedby]=\"messagesGroupId\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-expanded]=\"ariaExpanded !== undefined ? ariaExpanded : null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-required]=\"required || null\"\n [attr.role]=\"role || null\"\n [attr.inputmode]=\"inputMode || null\"\n [attr.autocorrect]=\"autoCorrect ? null : 'off'\"\n [(ngModel)]=\"value\"\n [id]=\"inputId\"\n [attr.name]=\"name || null\"\n [attr.type]=\"type || null\"\n [disabled]=\"disabled ?? false\"\n [required]=\"required ?? false\"\n [attr.pattern]=\"pattern || null\"\n [attr.placeholder]=\"placeHolder || null\"\n [attr.min]=\"min || null\"\n [attr.max]=\"max || null\"\n [attr.maxLength]=\"maxLength || null\"\n [attr.minLength]=\"minLength || null\"\n [attr.spellcheck]=\"spellCheck || null\"\n [ngStyle]=\"width ? { width: width } : {}\" />\n</ng-template>\n\n<!-- Template input wrap -->\n<ng-template #inputWrapTemplate>\n <div [ngClass]=\"getWrapClasses()\">\n <ng-container *ngTemplateOutlet=\"inputTemplate\"></ng-container>\n <dsfr-button\n *ngIf=\"hasButton()\"\n [ariaLabel]=\"buttonAriaLabel\"\n [disabled]=\"buttonDisabled\"\n [icon]=\"buttonIcon\"\n [label]=\"buttonLabel\"\n [tooltipMessage]=\"buttonTooltipMessage\"\n [type]=\"buttonType\"\n [variant]=\"buttonVariant\"\n (click)=\"onButtonClick($event)\"></dsfr-button>\n </div>\n</ng-template>\n\n<!-- Template textarea -->\n<ng-template #textareaTemplate>\n <textarea\n class=\"fr-input\"\n [ngClass]=\"customClass || null\"\n [id]=\"inputId\"\n [attr.name]=\"name || null\"\n [disabled]=\"disabled ?? false\"\n [attr.required]=\"required || null\"\n [attr.placeholder]=\"placeHolder || null\"\n [attr.min]=\"min || null\"\n [attr.max]=\"max || null\"\n [attr.maxLength]=\"maxLength || null\"\n [attr.minLength]=\"minLength || null\"\n [attr.autocomplete]=\"autocomplete || null\"\n [attr.aria-describedby]=\"messagesGroupId\"\n [(ngModel)]=\"value\"\n [ngStyle]=\"width ? { width: width } : {}\"\n [attr.rows]=\"rows || null\"></textarea>\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: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.InputGroupComponent, selector: "edu-input-group", inputs: ["label", "inputId", "hint", "disabled", "message", "severity", "messagesGroupId"] }, { kind: "component", type: i5.DsfrButtonComponent, selector: "dsfr-button", inputs: ["label", "type", "tooltipMessage", "variant", "size", "icon", "iconPosition", "disabled", "uppercase", "loader", "ariaLabel", "invertedOutlineContrast", "id", "ariaControls", "customClass"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DsfrFormEmailComponent, decorators: [{
type: Component,
args: [{ selector: 'dsfr-form-email', encapsulation: ViewEncapsulation.None, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DsfrFormEmailComponent),
multi: true,
},
], template: "<edu-input-group\n [inputId]=\"inputId\"\n [label]=\"label\"\n [hint]=\"hint\"\n [messagesGroupId]=\"messagesGroupId\"\n [disabled]=\"disabled\"\n [message]=\"message\"\n [severity]=\"severity\">\n <label class=\"fr-label\" [for]=\"inputId\">\n <ng-container *ngIf=\"label\">{{ label }}</ng-container>\n <ng-content *ngIf=\"!label\" select=\"[label]\"></ng-content>\n <span *ngIf=\"hint\" class=\"fr-hint-text\">{{ hint }}</span>\n </label>\n <ng-container *ngIf=\"!isTextArea(); else textareaTemplate\">\n <ng-container *ngIf=\"!hasInputWrap(); else inputWrapTemplate\" [ngTemplateOutlet]=\"inputTemplate\"></ng-container>\n </ng-container>\n</edu-input-group>\n\n<!-- Templates -------------------------------------------------------------------------------------------------------->\n\n<!-- Template input -->\n<ng-template #inputTemplate>\n <input\n class=\"fr-input\"\n [ngClass]=\"customClass || null\"\n [attr.autocomplete]=\"autocomplete || null\"\n [attr.aria-autocomplete]=\"ariaAutocomplete || null\"\n [attr.aria-describedby]=\"messagesGroupId\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-expanded]=\"ariaExpanded !== undefined ? ariaExpanded : null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-required]=\"required || null\"\n [attr.role]=\"role || null\"\n [attr.inputmode]=\"inputMode || null\"\n [attr.autocorrect]=\"autoCorrect ? null : 'off'\"\n [(ngModel)]=\"value\"\n [id]=\"inputId\"\n [attr.name]=\"name || null\"\n [attr.type]=\"type || null\"\n [disabled]=\"disabled ?? false\"\n [required]=\"required ?? false\"\n [attr.pattern]=\"pattern || null\"\n [attr.placeholder]=\"placeHolder || null\"\n [attr.min]=\"min || null\"\n [attr.max]=\"max || null\"\n [attr.maxLength]=\"maxLength || null\"\n [attr.minLength]=\"minLength || null\"\n [attr.spellcheck]=\"spellCheck || null\"\n [ngStyle]=\"width ? { width: width } : {}\" />\n</ng-template>\n\n<!-- Template input wrap -->\n<ng-template #inputWrapTemplate>\n <div [ngClass]=\"getWrapClasses()\">\n <ng-container *ngTemplateOutlet=\"inputTemplate\"></ng-container>\n <dsfr-button\n *ngIf=\"hasButton()\"\n [ariaLabel]=\"buttonAriaLabel\"\n [disabled]=\"buttonDisabled\"\n [icon]=\"buttonIcon\"\n [label]=\"buttonLabel\"\n [tooltipMessage]=\"buttonTooltipMessage\"\n [type]=\"buttonType\"\n [variant]=\"buttonVariant\"\n (click)=\"onButtonClick($event)\"></dsfr-button>\n </div>\n</ng-template>\n\n<!-- Template textarea -->\n<ng-template #textareaTemplate>\n <textarea\n class=\"fr-input\"\n [ngClass]=\"customClass || null\"\n [id]=\"inputId\"\n [attr.name]=\"name || null\"\n [disabled]=\"disabled ?? false\"\n [attr.required]=\"required || null\"\n [attr.placeholder]=\"placeHolder || null\"\n [attr.min]=\"min || null\"\n [attr.max]=\"max || null\"\n [attr.maxLength]=\"maxLength || null\"\n [attr.minLength]=\"minLength || null\"\n [attr.autocomplete]=\"autocomplete || null\"\n [attr.aria-describedby]=\"messagesGroupId\"\n [(ngModel)]=\"value\"\n [ngStyle]=\"width ? { width: width } : {}\"\n [attr.rows]=\"rows || null\"></textarea>\n</ng-template>\n" }]
}], ctorParameters: function () { return [{ type: i1.I18nService }]; }, propDecorators: { onValueChange: [{
type: HostListener,
args: ['input']
}], onFocusOut: [{
type: HostListener,
args: ['change']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS1lbWFpbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZHNmci1jb21wb25lbnRzL3NyYy9saWIvZm9ybXMvZm9ybS1lbWFpbC9mb3JtLWVtYWlsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1kc2ZyLWNvbXBvbmVudHMvc3JjL2xpYi9mb3Jtcy9mb3JtLWlucHV0L2Zvcm0taW5wdXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFVLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9GLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRW5ELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDOzs7Ozs7O0FBYzdDOztHQUVHO0FBQ0gsTUFBTSxPQUFPLHNCQUF1QixTQUFRLHNCQUFzQjtJQUtoRSxnQkFBZ0I7SUFDaEIsWUFBb0IsSUFBaUI7UUFDbkMsS0FBSyxFQUFFLENBQUM7UUFEVSxTQUFJLEdBQUosSUFBSSxDQUFhO1FBTHJDLGdCQUFnQixDQUFVLGlCQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUM7SUFPcEUsQ0FBQztJQUVEOztPQUVHO0lBQ0gsZ0JBQWdCO0lBRWhCLGFBQWE7UUFDWCxJQUFJLElBQUksQ0FBQyxLQUFLO1lBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2xDLENBQUM7SUFFRDs7T0FFRztJQUNILGdCQUFnQjtJQUVoQixVQUFVO1FBQ1IsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQUUsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLFdBQVcsRUFBRSxDQUFDO0lBQzlELENBQUM7SUFFRDs7T0FFRztJQUNILGdCQUFnQjtJQUNoQixPQUFPO1FBQ0wsSUFBSSxDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDbEMsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxlQUFlO0lBQ2YsUUFBUTtRQUNOLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNqQixJQUFJLENBQUMsSUFBSSxHQUFHLGtCQUFrQixDQUFDLEtBQUssQ0FBQztRQUNyQyxJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUN4QixJQUFJLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzFDLElBQUksQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDeEMsSUFBSSxDQUFDLFlBQVksR0FBRyxPQUFPLENBQUMsQ0FBQyxhQUFhO1FBQzFDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLENBQUMsYUFBYTtJQUN6QyxDQUFDO0lBRUQ7O09BRUc7SUFDSyxRQUFRO1FBQ2QsMkZBQTJGO1FBQzNGLGtEQUFrRDtRQUNsRCxJQUFJLENBQUMsUUFBUSxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN2RCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQztRQUNwRCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDdkIsQ0FBQzsrR0F6RFUsc0JBQXNCO21HQUF0QixzQkFBc0IseUhBWHRCO1lBQ1Q7Z0JBQ0UsT0FBTyxFQUFFLGlCQUFpQjtnQkFDMUIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQztnQkFDckQsS0FBSyxFQUFFLElBQUk7YUFDWjtTQUNGLGlEQ2hCSCxpc0dBd0ZBOzs0RkRuRWEsc0JBQXNCO2tCQWZsQyxTQUFTOytCQUNFLGlCQUFpQixpQkFFWixpQkFBaUIsQ0FBQyxJQUFJLGFBQzFCO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLHVCQUF1QixDQUFDOzRCQUNyRCxLQUFLLEVBQUUsSUFBSTt5QkFDWjtxQkFDRjtrR0FvQkQsYUFBYTtzQkFEWixZQUFZO3VCQUFDLE9BQU87Z0JBVXJCLFVBQVU7c0JBRFQsWUFBWTt1QkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBmb3J3YXJkUmVmLCBIb3N0TGlzdGVuZXIsIE9uSW5pdCwgVmlld0VuY2Fwc3VsYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgSTE4blNlcnZpY2UgfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuaW1wb3J0IHsgRHNmckZvcm1JbnB1dENvbXBvbmVudCwgRHNmcklucHV0VHlwZUNvbnN0IH0gZnJvbSAnLi4vZm9ybS1pbnB1dCc7XG5pbXBvcnQgeyBpc0VtYWlsVmFsaWQgfSBmcm9tICcuL2VtYWlsLXV0aWxzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZHNmci1mb3JtLWVtYWlsJyxcbiAgdGVtcGxhdGVVcmw6ICcuLi9mb3JtLWlucHV0L2Zvcm0taW5wdXQuY29tcG9uZW50Lmh0bWwnLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IERzZnJGb3JtRW1haWxDb21wb25lbnQpLFxuICAgICAgbXVsdGk6IHRydWUsXG4gICAgfSxcbiAgXSxcbn0pXG4vKlxuICogU2Fpc2llIGQndW5lIGFkcmVzc2UgZW1haWwsIHNpIGxhIHZhbGV1ciBlc3QgdmFsaWTDqWUgZW4gc29ydGllIGRlIGNoYW1wLCBlbGxlIGVzdCBwYXNzw6llIGVuIG1pbnVzY3VsZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBEc2ZyRm9ybUVtYWlsQ29tcG9uZW50IGV4dGVuZHMgRHNmckZvcm1JbnB1dENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIC8qKiBAaW50ZXJuYWwgKi8gcmVhZG9ubHkgZXJyb3JNZXNzYWdlID0gdGhpcy5pMThuLnQoJ2VtYWlsLmVycm9yJyk7XG5cbiAgcHJpdmF0ZSBfaXNWYWxpZDogYm9vbGVhbjtcblxuICAvKiogQGludGVybmFsICovXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaTE4bjogSTE4blNlcnZpY2UpIHtcbiAgICBzdXBlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEF1IGZpbCBkZSBsYSBzYWlzaWUsIG9uIG5lIHbDqXJpZmllIGxlIG1haWwgcXVlIHMnaWwgeSBhdmFpdCBkw6lqw6AgdW5lIGVycmV1clxuICAgKi9cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBASG9zdExpc3RlbmVyKCdpbnB1dCcpXG4gIG9uVmFsdWVDaGFuZ2UoKSB7XG4gICAgaWYgKHRoaXMuZXJyb3IpIHRoaXMudmFsaWRhdGUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWw6lyaWZpY2F0aW9uIHF1YW5kIG9uIHNvcnQgZHUgY2hhbXBcbiAgICovXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgQEhvc3RMaXN0ZW5lcignY2hhbmdlJylcbiAgb25Gb2N1c091dCgpIHtcbiAgICBpZiAodGhpcy52YWxpZGF0ZSgpKSB0aGlzLnZhbHVlID0gdGhpcy52YWx1ZT8udG9Mb3dlckNhc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWcmFpIHNpIGwnZW1haWwgZXN0IHZhbGlkw6kuXG4gICAqL1xuICAvKiogQGludGVybmFsICovXG4gIGlzVmFsaWQoKTogYm9vbGVhbiB7XG4gICAgdGhpcy5faXNWYWxpZCA/Pz0gdGhpcy52YWxpZGF0ZSgpO1xuICAgIHJldHVybiB0aGlzLl9pc1ZhbGlkO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCovXG4gIG5nT25Jbml0KCkge1xuICAgIHN1cGVyLm5nT25Jbml0KCk7XG4gICAgdGhpcy50eXBlID0gRHNmcklucHV0VHlwZUNvbnN0LkVNQUlMO1xuICAgIHRoaXMuc3BlbGxDaGVjayA9IGZhbHNlO1xuICAgIHRoaXMubGFiZWwgPz89IHRoaXMuaTE4bi50KCdlbWFpbC5sYWJlbCcpO1xuICAgIHRoaXMuaGludCA/Pz0gdGhpcy5pMThuLnQoJ2VtYWlsLmhpbnQnKTtcbiAgICB0aGlzLmF1dG9jb21wbGV0ZSA9ICdlbWFpbCc7IC8vIEBzaW5jZSAxLjZcbiAgICB0aGlzLmF1dG9Db3JyZWN0ID0gZmFsc2U7IC8vIEBzaW5jZSAxLjZcbiAgfVxuXG4gIC8qKlxuICAgKiBNw6l0aG9kZSB2YWxpZGF0aW9uLCBwb3NpdGlvbm5lIGxhIHByb3ByacOpdMOpIGVycm9yIHMnaWwgeSBhIGxpZXUuXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlKCk6IGJvb2xlYW4ge1xuICAgIC8vIFZhbGlkYXRvcnMuZW1haWwgbmUgbWFyY2hlIHBhcyB0csOocyBiaWVuIGRhbnMgbGEgdmVyc2lvbiAxNCwgZW4gZWZmZXQgJ25vbUBkJyBlc3QgdmFsaWTDqVxuICAgIC8vIFRPRE8gVsOpcmlmaWVyIGxlIHZhbGlkYXRvciBkJ2VtYWlsIGQnQW5ndWxhciAxNVxuICAgIHRoaXMuX2lzVmFsaWQgPSBpc0VtYWlsVmFsaWQodGhpcy52YWx1ZSwgdGhpcy5wYXR0ZXJuKTtcbiAgICB0aGlzLmVycm9yID0gdGhpcy5faXNWYWxpZCA/ICcnIDogdGhpcy5lcnJvck1lc3NhZ2U7XG4gICAgcmV0dXJuIHRoaXMuX2lzVmFsaWQ7XG4gIH1cbn1cbiIsIjxlZHUtaW5wdXQtZ3JvdXBcbiAgW2lucHV0SWRdPVwiaW5wdXRJZFwiXG4gIFtsYWJlbF09XCJsYWJlbFwiXG4gIFtoaW50XT1cImhpbnRcIlxuICBbbWVzc2FnZXNHcm91cElkXT1cIm1lc3NhZ2VzR3JvdXBJZFwiXG4gIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gIFttZXNzYWdlXT1cIm1lc3NhZ2VcIlxuICBbc2V2ZXJpdHldPVwic2V2ZXJpdHlcIj5cbiAgPGxhYmVsIGNsYXNzPVwiZnItbGFiZWxcIiBbZm9yXT1cImlucHV0SWRcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwibGFiZWxcIj57eyBsYWJlbCB9fTwvbmctY29udGFpbmVyPlxuICAgIDxuZy1jb250ZW50ICpuZ0lmPVwiIWxhYmVsXCIgc2VsZWN0PVwiW2xhYmVsXVwiPjwvbmctY29udGVudD5cbiAgICA8c3BhbiAqbmdJZj1cImhpbnRcIiBjbGFzcz1cImZyLWhpbnQtdGV4dFwiPnt7IGhpbnQgfX08L3NwYW4+XG4gIDwvbGFiZWw+XG4gIDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNUZXh0QXJlYSgpOyBlbHNlIHRleHRhcmVhVGVtcGxhdGVcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWhhc0lucHV0V3JhcCgpOyBlbHNlIGlucHV0V3JhcFRlbXBsYXRlXCIgW25nVGVtcGxhdGVPdXRsZXRdPVwiaW5wdXRUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICA8L25nLWNvbnRhaW5lcj5cbjwvZWR1LWlucHV0LWdyb3VwPlxuXG48IS0tIFRlbXBsYXRlcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT5cblxuPCEtLSBUZW1wbGF0ZSBpbnB1dCAtLT5cbjxuZy10ZW1wbGF0ZSAjaW5wdXRUZW1wbGF0ZT5cbiAgPGlucHV0XG4gICAgY2xhc3M9XCJmci1pbnB1dFwiXG4gICAgW25nQ2xhc3NdPVwiY3VzdG9tQ2xhc3MgfHwgbnVsbFwiXG4gICAgW2F0dHIuYXV0b2NvbXBsZXRlXT1cImF1dG9jb21wbGV0ZSB8fCBudWxsXCJcbiAgICBbYXR0ci5hcmlhLWF1dG9jb21wbGV0ZV09XCJhcmlhQXV0b2NvbXBsZXRlIHx8IG51bGxcIlxuICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwibWVzc2FnZXNHcm91cElkXCJcbiAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cImRpc2FibGVkIHx8IG51bGxcIlxuICAgIFthdHRyLmFyaWEtZXhwYW5kZWRdPVwiYXJpYUV4cGFuZGVkICE9PSB1bmRlZmluZWQgPyBhcmlhRXhwYW5kZWQgOiBudWxsXCJcbiAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbCB8fCBudWxsXCJcbiAgICBbYXR0ci5hcmlhLXJlcXVpcmVkXT1cInJlcXVpcmVkIHx8IG51bGxcIlxuICAgIFthdHRyLnJvbGVdPVwicm9sZSB8fCBudWxsXCJcbiAgICBbYXR0ci5pbnB1dG1vZGVdPVwiaW5wdXRNb2RlIHx8IG51bGxcIlxuICAgIFthdHRyLmF1dG9jb3JyZWN0XT1cImF1dG9Db3JyZWN0ID8gbnVsbCA6ICdvZmYnXCJcbiAgICBbKG5nTW9kZWwpXT1cInZhbHVlXCJcbiAgICBbaWRdPVwiaW5wdXRJZFwiXG4gICAgW2F0dHIubmFtZV09XCJuYW1lIHx8IG51bGxcIlxuICAgIFthdHRyLnR5cGVdPVwidHlwZSB8fCBudWxsXCJcbiAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWQgPz8gZmFsc2VcIlxuICAgIFtyZXF1aXJlZF09XCJyZXF1aXJlZCA/PyBmYWxzZVwiXG4gICAgW2F0dHIucGF0dGVybl09XCJwYXR0ZXJuIHx8IG51bGxcIlxuICAgIFthdHRyLnBsYWNlaG9sZGVyXT1cInBsYWNlSG9sZGVyIHx8IG51bGxcIlxuICAgIFthdHRyLm1pbl09XCJtaW4gfHwgbnVsbFwiXG4gICAgW2F0dHIubWF4XT1cIm1heCB8fCBudWxsXCJcbiAgICBbYXR0ci5tYXhMZW5ndGhdPVwibWF4TGVuZ3RoIHx8IG51bGxcIlxuICAgIFthdHRyLm1pbkxlbmd0aF09XCJtaW5MZW5ndGggfHwgbnVsbFwiXG4gICAgW2F0dHIuc3BlbGxjaGVja109XCJzcGVsbENoZWNrIHx8IG51bGxcIlxuICAgIFtuZ1N0eWxlXT1cIndpZHRoID8geyB3aWR0aDogd2lkdGggfSA6IHt9XCIgLz5cbjwvbmctdGVtcGxhdGU+XG5cbjwhLS0gVGVtcGxhdGUgaW5wdXQgd3JhcCAtLT5cbjxuZy10ZW1wbGF0ZSAjaW5wdXRXcmFwVGVtcGxhdGU+XG4gIDxkaXYgW25nQ2xhc3NdPVwiZ2V0V3JhcENsYXNzZXMoKVwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJpbnB1dFRlbXBsYXRlXCI+PC9uZy1jb250YWluZXI+XG4gICAgPGRzZnItYnV0dG9uXG4gICAgICAqbmdJZj1cImhhc0J1dHRvbigpXCJcbiAgICAgIFthcmlhTGFiZWxdPVwiYnV0dG9uQXJpYUxhYmVsXCJcbiAgICAgIFtkaXNhYmxlZF09XCJidXR0b25EaXNhYmxlZFwiXG4gICAgICBbaWNvbl09XCJidXR0b25JY29uXCJcbiAgICAgIFtsYWJlbF09XCJidXR0b25MYWJlbFwiXG4gICAgICBbdG9vbHRpcE1lc3NhZ2VdPVwiYnV0dG9uVG9vbHRpcE1lc3NhZ2VcIlxuICAgICAgW3R5cGVdPVwiYnV0dG9uVHlwZVwiXG4gICAgICBbdmFyaWFudF09XCJidXR0b25WYXJpYW50XCJcbiAgICAgIChjbGljayk9XCJvbkJ1dHRvbkNsaWNrKCRldmVudClcIj48L2RzZnItYnV0dG9uPlxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjwhLS0gVGVtcGxhdGUgdGV4dGFyZWEgLS0+XG48bmctdGVtcGxhdGUgI3RleHRhcmVhVGVtcGxhdGU+XG4gIDx0ZXh0YXJlYVxuICAgIGNsYXNzPVwiZnItaW5wdXRcIlxuICAgIFtuZ0NsYXNzXT1cImN1c3RvbUNsYXNzIHx8IG51bGxcIlxuICAgIFtpZF09XCJpbnB1dElkXCJcbiAgICBbYXR0ci5uYW1lXT1cIm5hbWUgfHwgbnVsbFwiXG4gICAgW2Rpc2FibGVkXT1cImRpc2FibGVkID8/IGZhbHNlXCJcbiAgICBbYXR0ci5yZXF1aXJlZF09XCJyZXF1aXJlZCB8fCBudWxsXCJcbiAgICBbYXR0ci5wbGFjZWhvbGRlcl09XCJwbGFjZUhvbGRlciB8fCBudWxsXCJcbiAgICBbYXR0ci5taW5dPVwibWluIHx8IG51bGxcIlxuICAgIFthdHRyLm1heF09XCJtYXggfHwgbnVsbFwiXG4gICAgW2F0dHIubWF4TGVuZ3RoXT1cIm1heExlbmd0aCB8fCBudWxsXCJcbiAgICBbYXR0ci5taW5MZW5ndGhdPVwibWluTGVuZ3RoIHx8IG51bGxcIlxuICAgIFthdHRyLmF1dG9jb21wbGV0ZV09XCJhdXRvY29tcGxldGUgfHwgbnVsbFwiXG4gICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJtZXNzYWdlc0dyb3VwSWRcIlxuICAgIFsobmdNb2RlbCldPVwidmFsdWVcIlxuICAgIFtuZ1N0eWxlXT1cIndpZHRoID8geyB3aWR0aDogd2lkdGggfSA6IHt9XCJcbiAgICBbYXR0ci5yb3dzXT1cInJvd3MgfHwgbnVsbFwiPjwvdGV4dGFyZWE+XG48L25nLXRlbXBsYXRlPlxuIl19