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

113 lines 26.1 kB
import { CommonModule } from '@angular/common'; import { Component, ElementRef, forwardRef, HostListener, inject, ViewEncapsulation, } from '@angular/core'; import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; import { DsfrButtonComponent } from '../../components'; import { DsfrI18nService, DsfrSeverityConst, InputGroupComponent } from '../../shared'; import { DsfrFormInputComponent, DsfrInputTypeConst } from '../form-input'; import { isEmailValid } from './email-utils'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@angular/forms"; /** * Saisie d'une adresse email, si la valeur saisie est validée, elle est transformée en minuscules. */ export class DsfrFormEmailComponent extends DsfrFormInputComponent { constructor() { super(...arguments); this.elementRef = inject(ElementRef); this.i18n = inject(DsfrI18nService); } /** * Au fil de la saisie, on ne vérifie le mail que s'il y avait déjà une erreur. * Ce qui permet de ne pas mettre en erreur le champ au cours de la saisie intiale mais si le champ est en erreur * suite focusout et que l'utilisateur corrige, le message d'erreur disparaîtra dès la correction. * * @internal */ onValueChange() { if (this.message && this.isValid()) { this.clearErrorMessage(); } } /** * La mise à jour du modèle interne n'est effectuée que lorsque l'utilisateur quitte le champ, de même pour la mise * en erreur le cass échéant. * * @internal */ onFocusOut() { if (this.isValid()) { this.value = this.value?.toLowerCase(); } else { this.showErrorMessage(); } } /** * Vrai si l'email est valide. * * @internal */ isValid() { return isEmailValid(this.value, this.pattern); } /** @internal*/ ngOnInit() { super.ngOnInit(); this._invalidMessage = this.i18n.t('email.error'); this.type = DsfrInputTypeConst.EMAIL; this.spellCheck = false; this.hint ??= this.i18n.t('email.hint'); this.autocomplete = 'email'; // @since 1.6 this.autoCorrect = false; // @since 1.6 } /** * Fix: appliquer le label par défaut uniquement si le slot label n'est pas renseigné * slot label non renseigné => le label 'fr-label' ne possede aucun enfant ou seulement la description additionnelle */ ngAfterViewInit() { const firstElementChild = this.elementRef.nativeElement?.querySelector('.fr-label').firstElementChild; if (!firstElementChild || [...firstElementChild.classList].includes('fr-hint-text')) { this.label ??= this.i18n.t('email.label'); } } /** * Affiche le message d'erreur interne. */ showErrorMessage() { this.messageSeverity = DsfrSeverityConst.ERROR; this.message = this._invalidMessage; } /** * Reset du message d'erreur interne. */ clearErrorMessage() { this.messageSeverity = DsfrSeverityConst.INFO; this.message = undefined; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DsfrFormEmailComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DsfrFormEmailComponent, isStandalone: true, 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]=\"messageSeverity\">\n <label class=\"fr-label\" [ngClass]=\"{ 'fr-sr-only': labelSrOnly }\" [for]=\"inputId\">\n @if (label) {\n {{ label }}\n } @else {\n <ng-content select=\"[label]\"></ng-content>\n }\n @if (hint) {\n <span class=\"fr-hint-text\">{{ hint }}</span>\n }\n </label>\n @if (!isTextArea()) {\n @if (!hasInputWrap()) {\n <ng-container [ngTemplateOutlet]=\"inputTemplate\"></ng-container>\n } @else {\n <div [ngClass]=\"getWrapClasses()\">\n <ng-container *ngTemplateOutlet=\"inputTemplate\"></ng-container>\n @if (hasButton()) {\n <dsfr-button\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 }\n </div>\n }\n } @else {\n <textarea\n class=\"fr-input\"\n [ngClass]=\"customClass || null\"\n [id]=\"inputId\"\n [attr.name]=\"name || null\"\n [disabled]=\"disabled\"\n [required]=\"required\"\n [attr.placeholder]=\"placeHolder || null\"\n [attr.maxLength]=\"maxLength || null\"\n [attr.minLength]=\"minLength || null\"\n [attr.autocomplete]=\"autocomplete || null\"\n [attr.aria-describedby]=\"message ? messagesGroupId : null\"\n [attr.aria-invalid]=\"ariaInvalid || null\"\n [(ngModel)]=\"value\"\n [ngStyle]=\"width ? { width: width } : {}\"\n [attr.rows]=\"rows || null\"></textarea>\n }\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]=\"message ? messagesGroupId : null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-expanded]=\"ariaExpanded !== undefined ? ariaExpanded : null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-invalid]=\"ariaInvalid || null\"\n [readOnly]=\"readonly\"\n [attr.aria-required]=\"required || null\"\n [attr.role]=\"inputRole || 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\"\n [required]=\"required\"\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 (blur)=\"onBlur()\"\n [attr.minLength]=\"minLength || null\"\n [attr.spellcheck]=\"spellCheck || null\"\n [ngStyle]=\"width ? { width: width } : {}\" />\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: InputGroupComponent, selector: "edu-input-group", inputs: ["label", "inputId", "hint", "disabled", "message", "severity", "messagesGroupId"] }, { kind: "component", type: DsfrButtonComponent, selector: "dsfr-button", inputs: ["label", "type", "tooltipMessage", "variant", "buttonSize", "icon", "iconPosition", "disabled", "uppercase", "loader", "ariaLabel", "invertedOutlineContrast", "id", "buttonId", "ariaControls", "ariaPressed", "ariaHasPopup", "ariaExpanded", "tabIndex", "customClass", "buttonRole", "labelSrOnly", "size"] }], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", 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, }, ], standalone: true, imports: [CommonModule, FormsModule, InputGroupComponent, DsfrButtonComponent], template: "<edu-input-group\n [inputId]=\"inputId\"\n [label]=\"label\"\n [hint]=\"hint\"\n [messagesGroupId]=\"messagesGroupId\"\n [disabled]=\"disabled\"\n [message]=\"message\"\n [severity]=\"messageSeverity\">\n <label class=\"fr-label\" [ngClass]=\"{ 'fr-sr-only': labelSrOnly }\" [for]=\"inputId\">\n @if (label) {\n {{ label }}\n } @else {\n <ng-content select=\"[label]\"></ng-content>\n }\n @if (hint) {\n <span class=\"fr-hint-text\">{{ hint }}</span>\n }\n </label>\n @if (!isTextArea()) {\n @if (!hasInputWrap()) {\n <ng-container [ngTemplateOutlet]=\"inputTemplate\"></ng-container>\n } @else {\n <div [ngClass]=\"getWrapClasses()\">\n <ng-container *ngTemplateOutlet=\"inputTemplate\"></ng-container>\n @if (hasButton()) {\n <dsfr-button\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 }\n </div>\n }\n } @else {\n <textarea\n class=\"fr-input\"\n [ngClass]=\"customClass || null\"\n [id]=\"inputId\"\n [attr.name]=\"name || null\"\n [disabled]=\"disabled\"\n [required]=\"required\"\n [attr.placeholder]=\"placeHolder || null\"\n [attr.maxLength]=\"maxLength || null\"\n [attr.minLength]=\"minLength || null\"\n [attr.autocomplete]=\"autocomplete || null\"\n [attr.aria-describedby]=\"message ? messagesGroupId : null\"\n [attr.aria-invalid]=\"ariaInvalid || null\"\n [(ngModel)]=\"value\"\n [ngStyle]=\"width ? { width: width } : {}\"\n [attr.rows]=\"rows || null\"></textarea>\n }\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]=\"message ? messagesGroupId : null\"\n [attr.aria-disabled]=\"disabled || null\"\n [attr.aria-expanded]=\"ariaExpanded !== undefined ? ariaExpanded : null\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-invalid]=\"ariaInvalid || null\"\n [readOnly]=\"readonly\"\n [attr.aria-required]=\"required || null\"\n [attr.role]=\"inputRole || 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\"\n [required]=\"required\"\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 (blur)=\"onBlur()\"\n [attr.minLength]=\"minLength || null\"\n [attr.spellcheck]=\"spellCheck || null\"\n [ngStyle]=\"width ? { width: width } : {}\" />\n</ng-template>\n" }] }], propDecorators: { onValueChange: [{ type: HostListener, args: ['input'] }], onFocusOut: [{ type: HostListener, args: ['change'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS1lbWFpbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZHNmci1jb21wb25lbnRzL3NyYy9saWIvZm9ybXMvZm9ybS1lbWFpbC9mb3JtLWVtYWlsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1kc2ZyLWNvbXBvbmVudHMvc3JjL2xpYi9mb3Jtcy9mb3JtLWlucHV0L2Zvcm0taW5wdXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFFTCxTQUFTLEVBQ1QsVUFBVSxFQUNWLFVBQVUsRUFDVixZQUFZLEVBQ1osTUFBTSxFQUVOLGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN2RixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0UsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQzs7OztBQUU3Qzs7R0FFRztBQWVILE1BQU0sT0FBTyxzQkFBdUIsU0FBUSxzQkFBc0I7SUFkbEU7O1FBaUJtQixlQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2hDLFNBQUksR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUM7S0E4RWpEO0lBNUVDOzs7Ozs7T0FNRztJQUVILGFBQWE7UUFDWCxJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxD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VUFBVTtzQkFEVCxZQUFZO3VCQUFDLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBmb3J3YXJkUmVmLFxuICBIb3N0TGlzdGVuZXIsXG4gIGluamVjdCxcbiAgT25Jbml0LFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3Jtc01vZHVsZSwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBEc2ZyQnV0dG9uQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cyc7XG5pbXBvcnQgeyBEc2ZySTE4blNlcnZpY2UsIERzZnJTZXZlcml0eUNvbnN0LCBJbnB1dEdyb3VwQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcbmltcG9ydCB7IERzZnJGb3JtSW5wdXRDb21wb25lbnQsIERzZnJJbnB1dFR5cGVDb25zdCB9IGZyb20gJy4uL2Zvcm0taW5wdXQnO1xuaW1wb3J0IHsgaXNFbWFpbFZhbGlkIH0gZnJvbSAnLi9lbWFpbC11dGlscyc7XG5cbi8qKlxuICogU2Fpc2llIGQndW5lIGFkcmVzc2UgZW1haWwsIHNpIGxhIHZhbGV1ciBzYWlzaWUgZXN0IHZhbGlkw6llLCBlbGxlIGVzdCB0cmFuc2Zvcm3DqWUgZW4gbWludXNjdWxlcy5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZHNmci1mb3JtLWVtYWlsJyxcbiAgdGVtcGxhdGVVcmw6ICcuLi9mb3JtLWlucHV0L2Zvcm0taW5wdXQuY29tcG9uZW50Lmh0bWwnLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IERzZnJGb3JtRW1haWxDb21wb25lbnQpLFxuICAgICAgbXVsdGk6IHRydWUsXG4gICAgfSxcbiAgXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRm9ybXNNb2R1bGUsIElucHV0R3JvdXBDb21wb25lbnQsIERzZnJCdXR0b25Db21wb25lbnRdLFxufSlcbmV4cG9ydCBjbGFzcyBEc2ZyRm9ybUVtYWlsQ29tcG9uZW50IGV4dGVuZHMgRHNmckZvcm1JbnB1dENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG4gIHByb3RlY3RlZCBfaW52YWxpZE1lc3NhZ2U6IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IGVsZW1lbnRSZWYgPSBpbmplY3QoRWxlbWVudFJlZik7XG4gIHByaXZhdGUgcmVhZG9ubHkgaTE4biA9IGluamVjdChEc2ZySTE4blNlcnZpY2UpO1xuXG4gIC8qKlxuICAgKiBBdSBmaWwgZGUgbGEgc2Fpc2llLCBvbiBuZSB2w6lyaWZpZSBsZSBtYWlsIHF1ZSBzJ2lsIHkgYXZhaXQgZMOpasOgIHVuZSBlcnJldXIuXG4gICAqIENlIHF1aSBwZXJtZXQgZGUgbmUgcGFzIG1ldHRyZSBlbiBlcnJldXIgbGUgY2hhbXAgYXUgY291cnMgZGUgbGEgc2Fpc2llIGludGlhbGUgbWFpcyBzaSBsZSBjaGFtcCBlc3QgZW4gZXJyZXVyXG4gICAqIHN1aXRlIGZvY3Vzb3V0IGV0IHF1ZSBsJ3V0aWxpc2F0ZXVyIGNvcnJpZ2UsIGxlIG1lc3NhZ2UgZCdlcnJldXIgZGlzcGFyYcOudHJhIGTDqHMgbGEgY29ycmVjdGlvbi5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBASG9zdExpc3RlbmVyKCdpbnB1dCcpXG4gIG9uVmFsdWVDaGFuZ2UoKSB7XG4gICAgaWYgKHRoaXMubWVzc2FnZSAmJiB0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgdGhpcy5jbGVhckVycm9yTWVzc2FnZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMYSBtaXNlIMOgIGpvdXIgZHUgbW9kw6hsZSBpbnRlcm5lIG4nZXN0IGVmZmVjdHXDqWUgcXVlIGxvcnNxdWUgbCd1dGlsaXNhdGV1ciBxdWl0dGUgbGUgY2hhbXAsIGRlIG3Dqm1lIHBvdXIgbGEgbWlzZVxuICAgKiBlbiBlcnJldXIgbGUgY2FzcyDDqWNow6lhbnQuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgQEhvc3RMaXN0ZW5lcignY2hhbmdlJylcbiAgb25Gb2N1c091dCgpIHtcbiAgICBpZiAodGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgIHRoaXMudmFsdWUgPSB0aGlzLnZhbHVlPy50b0xvd2VyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnNob3dFcnJvck1lc3NhZ2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVnJhaSBzaSBsJ2VtYWlsIGVzdCB2YWxpZGUuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgaXNWYWxpZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gaXNFbWFpbFZhbGlkKHRoaXMudmFsdWUsIHRoaXMucGF0dGVybik7XG4gIH1cblxuICAvKiogQGludGVybmFsKi9cbiAgbmdPbkluaXQoKSB7XG4gICAgc3VwZXIubmdPbkluaXQoKTtcbiAgICB0aGlzLl9pbnZhbGlkTWVzc2FnZSA9IHRoaXMuaTE4bi50KCdlbWFpbC5lcnJvcicpO1xuICAgIHRoaXMudHlwZSA9IERzZnJJbnB1dFR5cGVDb25zdC5FTUFJTDtcbiAgICB0aGlzLnNwZWxsQ2hlY2sgPSBmYWxzZTtcbiAgICB0aGlzLmhpbnQgPz89IHRoaXMuaTE4bi50KCdlbWFpbC5oaW50Jyk7XG4gICAgdGhpcy5hdXRvY29tcGxldGUgPSAnZW1haWwnOyAvLyBAc2luY2UgMS42XG4gICAgdGhpcy5hdXRvQ29ycmVjdCA9IGZhbHNlOyAvLyBAc2luY2UgMS42XG4gIH1cblxuICAvKipcbiAgICogRml4OiBhcHBsaXF1ZXIgbGUgbGFiZWwgcGFyIGTDqWZhdXQgdW5pcXVlbWVudCBzaSBsZSBzbG90IGxhYmVsIG4nZXN0IHBhcyByZW5zZWlnbsOpXG4gICAqIHNsb3QgbGFiZWwgbm9uIHJlbnNlaWduw6kgPT4gbGUgbGFiZWwgJ2ZyLWxhYmVsJyBuZSBwb3NzZWRlIGF1Y3VuIGVuZmFudCBvdSBzZXVsZW1lbnQgbGEgZGVzY3JpcHRpb24gYWRkaXRpb25uZWxsZVxuICAgKi9cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIGNvbnN0IGZpcnN0RWxlbWVudENoaWxkID0gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ/LnF1ZXJ5U2VsZWN0b3IoJy5mci1sYWJlbCcpLmZpcnN0RWxlbWVudENoaWxkO1xuXG4gICAgaWYgKCFmaXJzdEVsZW1lbnRDaGlsZCB8fCBbLi4uZmlyc3RFbGVtZW50Q2hpbGQuY2xhc3NMaXN0XS5pbmNsdWRlcygnZnItaGludC10ZXh0JykpIHtcbiAgICAgIHRoaXMubGFiZWwgPz89IHRoaXMuaTE4bi50KCdlbWFpbC5sYWJlbCcpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBZmZpY2hlIGxlIG1lc3NhZ2UgZCdlcnJldXIgaW50ZXJuZS5cbiAgICovXG4gIHByaXZhdGUgc2hvd0Vycm9yTWVzc2FnZSgpOiB2b2lkIHtcbiAgICB0aGlzLm1lc3NhZ2VTZXZlcml0eSA9IERzZnJTZXZlcml0eUNvbnN0LkVSUk9SO1xuICAgIHRoaXMubWVzc2FnZSA9IHRoaXMuX2ludmFsaWRNZXNzYWdlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IGR1IG1lc3NhZ2UgZCdlcnJldXIgaW50ZXJuZS5cbiAgICovXG4gIHByaXZhdGUgY2xlYXJFcnJvck1lc3NhZ2UoKTogdm9pZCB7XG4gICAgdGhpcy5tZXNzYWdlU2V2ZXJpdHkgPSBEc2ZyU2V2ZXJpdHlDb25zdC5JTkZPO1xuICAgIHRoaXMubWVzc2FnZSA9IHVuZGVmaW5lZDtcbiAgfVxufVxuIiwiPGVkdS1pbnB1dC1ncm91cFxuICBbaW5wdXRJZF09XCJpbnB1dElkXCJcbiAgW2xhYmVsXT1cImxhYmVsXCJcbiAgW2hpbnRdPVwiaGludFwiXG4gIFttZXNzYWdlc0dyb3VwSWRdPVwibWVzc2FnZXNHcm91cElkXCJcbiAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgW21lc3NhZ2VdPVwibWVzc2FnZVwiXG4gIFtzZXZlcml0eV09XCJtZXNzYWdlU2V2ZXJpdHlcIj5cbiAgPGxhYmVsIGNsYXNzPVwiZnItbGFiZWxcIiBbbmdDbGFzc109XCJ7ICdmci1zci1vbmx5JzogbGFiZWxTck9ubHkgfVwiIFtmb3JdPVwiaW5wdXRJZFwiPlxuICAgIEBpZiAobGFiZWwpIHtcbiAgICAgIHt7IGxhYmVsIH19XG4gICAgfSBAZWxzZSB7XG4gICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJbbGFiZWxdXCI+PC9uZy1jb250ZW50PlxuICAgIH1cbiAgICBAaWYgKGhpbnQpIHtcbiAgICAgIDxzcGFuIGNsYXNzPVwiZnItaGludC10ZXh0XCI+e3sgaGludCB9fTwvc3Bhbj5cbiAgICB9XG4gIDwvbGFiZWw+XG4gIEBpZiAoIWlzVGV4dEFyZWEoKSkge1xuICAgIEBpZiAoIWhhc0lucHV0V3JhcCgpKSB7XG4gICAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImlucHV0VGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbiAgICB9IEBlbHNlIHtcbiAgICAgIDxkaXYgW25nQ2xhc3NdPVwiZ2V0V3JhcENsYXNzZXMoKVwiPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiaW5wdXRUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICBAaWYgKGhhc0J1dHRvbigpKSB7XG4gICAgICAgICAgPGRzZnItYnV0dG9uXG4gICAgICAgICAgICBbYXJpYUxhYmVsXT1cImJ1dHRvbkFyaWFMYWJlbFwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiYnV0dG9uRGlzYWJsZWRcIlxuICAgICAgICAgICAgW2ljb25dPVwiYnV0dG9uSWNvblwiXG4gICAgICAgICAgICBbbGFiZWxdPVwiYnV0dG9uTGFiZWxcIlxuICAgICAgICAgICAgW3Rvb2x0aXBNZXNzYWdlXT1cImJ1dHRvblRvb2x0aXBNZXNzYWdlXCJcbiAgICAgICAgICAgIFt0eXBlXT1cImJ1dHRvblR5cGVcIlxuICAgICAgICAgICAgW3ZhcmlhbnRdPVwiYnV0dG9uVmFyaWFudFwiXG4gICAgICAgICAgICAoY2xpY2spPVwib25CdXR0b25DbGljaygkZXZlbnQpXCI+PC9kc2ZyLWJ1dHRvbj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgfVxuICB9IEBlbHNlIHtcbiAgICA8dGV4dGFyZWFcbiAgICAgIGNsYXNzPVwiZnItaW5wdXRcIlxuICAgICAgW25nQ2xhc3NdPVwiY3VzdG9tQ2xhc3MgfHwgbnVsbFwiXG4gICAgICBbaWRdPVwiaW5wdXRJZFwiXG4gICAgICBbYXR0ci5uYW1lXT1cIm5hbWUgfHwgbnVsbFwiXG4gICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgW3JlcXVpcmVkXT1cInJlcXVpcmVkXCJcbiAgICAgIFthdHRyLnBsYWNlaG9sZGVyXT1cInBsYWNlSG9sZGVyIHx8IG51bGxcIlxuICAgICAgW2F0dHIubWF4TGVuZ3RoXT1cIm1heExlbmd0aCB8fCBudWxsXCJcbiAgICAgIFthdHRyLm1pbkxlbmd0aF09XCJtaW5MZW5ndGggfHwgbnVsbFwiXG4gICAgICBbYXR0ci5hdXRvY29tcGxldGVdPVwiYXV0b2NvbXBsZXRlIHx8IG51bGxcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJtZXNzYWdlID8gbWVzc2FnZXNHcm91cElkIDogbnVsbFwiXG4gICAgICBbYXR0ci5hcmlhLWludmFsaWRdPVwiYXJpYUludmFsaWQgfHwgbnVsbFwiXG4gICAgICBbKG5nTW9kZWwpXT1cInZhbHVlXCJcbiAgICAgIFtuZ1N0eWxlXT1cIndpZHRoID8geyB3aWR0aDogd2lkdGggfSA6IHt9XCJcbiAgICAgIFthdHRyLnJvd3NdPVwicm93cyB8fCBudWxsXCI+PC90ZXh0YXJlYT5cbiAgfVxuPC9lZHUtaW5wdXQtZ3JvdXA+XG5cbjwhLS0gVGVtcGxhdGVzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuXG48IS0tIFRlbXBsYXRlIGlucHV0IC0tPlxuPG5nLXRlbXBsYXRlICNpbnB1dFRlbXBsYXRlPlxuICA8aW5wdXRcbiAgICBjbGFzcz1cImZyLWlucHV0XCJcbiAgICBbbmdDbGFzc109XCJjdXN0b21DbGFzcyB8fCBudWxsXCJcbiAgICBbYXR0ci5hdXRvY29tcGxldGVdPVwiYXV0b2NvbXBsZXRlIHx8IG51bGxcIlxuICAgIFthdHRyLmFyaWEtYXV0b2NvbXBsZXRlXT1cImFyaWFBdXRvY29tcGxldGUgfHwgbnVsbFwiXG4gICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJtZXNzYWdlID8gbWVzc2FnZXNHcm91cElkIDogbnVsbFwiXG4gICAgW2F0dHIuYXJpYS1kaXNhYmxlZF09XCJkaXNhYmxlZCB8fCBudWxsXCJcbiAgICBbYXR0ci5hcmlhLWV4cGFuZGVkXT1cImFyaWFFeHBhbmRlZCAhPT0gdW5kZWZpbmVkID8gYXJpYUV4cGFuZGVkIDogbnVsbFwiXG4gICAgW2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWwgfHwgbnVsbFwiXG4gICAgW2F0dHIuYXJpYS1pbnZhbGlkXT1cImFyaWFJbnZhbGlkIHx8IG51bGxcIlxuICAgIFtyZWFkT25seV09XCJyZWFkb25seVwiXG4gICAgW2F0dHIuYXJpYS1yZXF1aXJlZF09XCJyZXF1aXJlZCB8fCBudWxsXCJcbiAgICBbYXR0ci5yb2xlXT1cImlucHV0Um9sZSB8fCBudWxsXCJcbiAgICBbYXR0ci5pbnB1dG1vZGVdPVwiaW5wdXRNb2RlIHx8IG51bGxcIlxuICAgIFthdHRyLmF1dG9jb3JyZWN0XT1cImF1dG9Db3JyZWN0ID8gbnVsbCA6ICdvZmYnXCJcbiAgICBbKG5nTW9kZWwpXT1cInZhbHVlXCJcbiAgICBbaWRdPVwiaW5wdXRJZFwiXG4gICAgW2F0dHIubmFtZV09XCJuYW1lIHx8IG51bGxcIlxuICAgIFthdHRyLnR5cGVdPVwidHlwZSB8fCBudWxsXCJcbiAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgIFtyZXF1aXJlZF09XCJyZXF1aXJlZFwiXG4gICAgW2F0dHIucGF0dGVybl09XCJwYXR0ZXJuIHx8IG51bGxcIlxuICAgIFthdHRyLnBsYWNlaG9sZGVyXT1cInBsYWNlSG9sZGVyIHx8IG51bGxcIlxuICAgIFthdHRyLm1pbl09XCJtaW4gfHwgbnVsbFwiXG4gICAgW2F0dHIubWF4XT1cIm1heCB8fCBudWxsXCJcbiAgICBbYXR0ci5tYXhMZW5ndGhdPVwibWF4TGVuZ3RoIHx8IG51bGxcIlxuICAgIChibHVyKT1cIm9uQmx1cigpXCJcbiAgICBbYXR0ci5taW5MZW5ndGhdPVwibWluTGVuZ3RoIHx8IG51bGxcIlxuICAgIFthdHRyLnNwZWxsY2hlY2tdPVwic3BlbGxDaGVjayB8fCBudWxsXCJcbiAgICBbbmdTdHlsZV09XCJ3aWR0aCA/IHsgd2lkdGg6IHdpZHRoIH0gOiB7fVwiIC8+XG48L25nLXRlbXBsYXRlPlxuIl19