@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 • 24 kB
JavaScript
import { CommonModule } from '@angular/common';
import { Component, ElementRef, forwardRef, HostListener, inject } from '@angular/core';
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import { DsfrButtonComponent } from '../../components';
import { DsfrI18nService, InputGroupComponent } from '../../shared';
import { DsfrFormInputComponent } from '../form-input';
import { DsfrInputTypeConst } from '../form-input/form-input.model';
import { formatPhoneNumber, isPhoneNumberValid } from './phone-number-utils';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/forms";
/**
* Saisie d'un n° de téléphone et reformatage (sauf dans le cas d'utilisation d'un pattern)
* @since 1.3.0
*/
export class DsfrFormTelComponent extends DsfrFormInputComponent {
constructor() {
super(...arguments);
this.elementRef = inject(ElementRef);
this.i18n = inject(DsfrI18nService);
}
/**
* Au fil de la saisie, on ne vérifie le n° de téléphone que s'il y avait déjà une erreur.
*/
onInput() {
if (this.error)
this.validate();
}
/**
* Vérification au commit de la valeur.
*
* cf. https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event
*/
onChange() {
const isValid = this.validate();
if (isValid && !this.pattern)
this.value = formatPhoneNumber(this.value);
}
/** @internal*/
ngOnInit() {
super.ngOnInit();
this.errorMessage = this.i18n.t('tel.error');
this.type = DsfrInputTypeConst.TEL;
this.spellCheck = false;
this.hint ??= this.i18n.t('tel.hint');
}
/**
* 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('tel.label');
}
}
/**
* Méthode validation, positionne la propriété error s'il y a lieu.
*/
validate() {
const isValid = isPhoneNumberValid(this.value, this.pattern);
this.error = isValid ? '' : this.errorMessage;
return isValid;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DsfrFormTelComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DsfrFormTelComponent, isStandalone: true, selector: "dsfr-form-tel", host: { listeners: { "input": "onInput()", "change": "onChange()" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DsfrFormTelComponent),
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"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DsfrFormTelComponent, decorators: [{
type: Component,
args: [{ selector: 'dsfr-form-tel', standalone: true, imports: [CommonModule, FormsModule, InputGroupComponent, DsfrButtonComponent], providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DsfrFormTelComponent),
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]=\"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: { onInput: [{
type: HostListener,
args: ['input']
}], onChange: [{
type: HostListener,
args: ['change']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS10ZWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWRzZnItY29tcG9uZW50cy9zcmMvbGliL2Zvcm1zL2Zvcm0tdGVsL2Zvcm0tdGVsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1kc2ZyLWNvbXBvbmVudHMvc3JjL2xpYi9mb3Jtcy9mb3JtLWlucHV0L2Zvcm0taW5wdXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBaUIsU0FBUyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBVSxNQUFNLGVBQWUsQ0FBQztBQUMvRyxPQUFPLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGVBQWUsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNwRSxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdkQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7Ozs7QUFnQjdFOzs7R0FHRztBQUNILE1BQU0sT0FBTyxvQkFBcUIsU0FBUSxzQkFBc0I7SUFsQmhFOztRQXFCbUIsZUFBVSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNoQyxTQUFJLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0tBaURqRDtJQS9DQzs7T0FFRztJQUNvQixPQUFPO1FBQzVCLElBQUksSUFBSSxDQUFDLEtBQUs7WUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDbEMsQ0FBQztJQUVEOzs7O09BSUc7SUFDcUIsUUFBUTtRQUM5QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDaEMsSUFBSSxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTztZQUFFLElBQUksQ0FBQyxLQUFLLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzNFLENBQUM7SUFFRCxlQUFlO0lBQ2YsUUFBUTtRQUNOLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNqQixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzdDLElBQUksQ0FBQyxJQUFJLEdBQUcsa0JBQWtCLENBQUMsR0FBRyxDQUFDO1FBQ25DLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVEOzs7T0FHRztJQUNILGVBQWU7UUFDYixNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUFFLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQztRQUV0RyxJQUFJLENBQUMsaUJBQWlCLElBQUksQ0FBQyxHQUFHLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO1lBQ3BGLElBQUksQ0FBQyxLQUFLLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDMUMsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNPLFFBQVE7UUFDaEIsTUFBTSxPQUFPLEdBQUcsa0JBQWtCLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDN0QsSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQztRQUU5QyxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDOytHQXBEVSxvQkFBb0I7bUdBQXBCLG9CQUFvQixtSUFicEI7WUFDVDtnQkFDRSxPQUFPLEVBQUUsaUJBQWlCO2dCQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLG9CQUFvQixDQUFDO2dCQUNuRCxLQUFLLEVBQUUsSUFBSTthQUNaO1NBQ0YsaURDcEJILDR1R0E0RkEsMkNEL0VZLFlBQVksd1hBQUUsV0FBVyw0MEJBQUUsbUJBQW1CLHdKQUFFLG1CQUFtQjs7NEZBY2xFLG9CQUFvQjtrQkFsQmhDLFNBQVM7K0JBQ0UsZUFBZSxjQUViLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxXQUFXLEVBQUUsbUJBQW1CLEVBQUUsbUJBQW1CLENBQUMsYUFDbkU7d0JBQ1Q7NEJBQ0UsT0FBTyxFQUFFLGlCQUFpQjs0QkFDMUIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUscUJBQXFCLENBQUM7NEJBQ25ELEtBQUssRUFBRSxJQUFJO3lCQUNaO3FCQUNGOzhCQWdCc0IsT0FBTztzQkFBN0IsWUFBWTt1QkFBQyxPQUFPO2dCQVNHLFFBQVE7c0JBQS9CLFlBQVk7dUJBQUMsUUFBUSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBBZnRlclZpZXdJbml0LCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIGZvcndhcmRSZWYsIEhvc3RMaXN0ZW5lciwgaW5qZWN0LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IERzZnJCdXR0b25Db21wb25lbnQgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzJztcbmltcG9ydCB7IERzZnJJMThuU2VydmljZSwgSW5wdXRHcm91cENvbXBvbmVudCB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBEc2ZyRm9ybUlucHV0Q29tcG9uZW50IH0gZnJvbSAnLi4vZm9ybS1pbnB1dCc7XG5pbXBvcnQgeyBEc2ZySW5wdXRUeXBlQ29uc3QgfSBmcm9tICcuLi9mb3JtLWlucHV0L2Zvcm0taW5wdXQubW9kZWwnO1xuaW1wb3J0IHsgZm9ybWF0UGhvbmVOdW1iZXIsIGlzUGhvbmVOdW1iZXJWYWxpZCB9IGZyb20gJy4vcGhvbmUtbnVtYmVyLXV0aWxzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZHNmci1mb3JtLXRlbCcsXG4gIHRlbXBsYXRlVXJsOiAnLi4vZm9ybS1pbnB1dC9mb3JtLWlucHV0LmNvbXBvbmVudC5odG1sJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRm9ybXNNb2R1bGUsIElucHV0R3JvdXBDb21wb25lbnQsIERzZnJCdXR0b25Db21wb25lbnRdLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IERzZnJGb3JtVGVsQ29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgIH0sXG4gIF0sXG59KVxuXG4vKipcbiAqIFNhaXNpZSBkJ3VuIG7CsCBkZSB0w6lsw6lwaG9uZSBldCByZWZvcm1hdGFnZSAoc2F1ZiBkYW5zIGxlIGNhcyBkJ3V0aWxpc2F0aW9uIGQndW4gcGF0dGVybilcbiAqIEBzaW5jZSAxLjMuMFxuICovXG5leHBvcnQgY2xhc3MgRHNmckZvcm1UZWxDb21wb25lbnQgZXh0ZW5kcyBEc2ZyRm9ybUlucHV0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0IHtcbiAgcHJvdGVjdGVkIGVycm9yTWVzc2FnZTogc3RyaW5nO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgZWxlbWVudFJlZiA9IGluamVjdChFbGVtZW50UmVmKTtcbiAgcHJpdmF0ZSByZWFkb25seSBpMThuID0gaW5qZWN0KERzZnJJMThuU2VydmljZSk7XG5cbiAgLyoqXG4gICAqIEF1IGZpbCBkZSBsYSBzYWlzaWUsIG9uIG5lIHbDqXJpZmllIGxlIG7CsCBkZSB0w6lsw6lwaG9uZSBxdWUgcydpbCB5IGF2YWl0IGTDqWrDoCB1bmUgZXJyZXVyLlxuICAgKi9cbiAgQEhvc3RMaXN0ZW5lcignaW5wdXQnKSBvbklucHV0KCkge1xuICAgIGlmICh0aGlzLmVycm9yKSB0aGlzLnZhbGlkYXRlKCk7XG4gIH1cblxuICAvKipcbiAgICogVsOpcmlmaWNhdGlvbiBhdSBjb21taXQgZGUgbGEgdmFsZXVyLlxuICAgKlxuICAgKiBjZi4gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0hUTUxFbGVtZW50L2NoYW5nZV9ldmVudFxuICAgKi9cbiAgQEhvc3RMaXN0ZW5lcignY2hhbmdlJykgb25DaGFuZ2UoKSB7XG4gICAgY29uc3QgaXNWYWxpZCA9IHRoaXMudmFsaWRhdGUoKTtcbiAgICBpZiAoaXNWYWxpZCAmJiAhdGhpcy5wYXR0ZXJuKSB0aGlzLnZhbHVlID0gZm9ybWF0UGhvbmVOdW1iZXIodGhpcy52YWx1ZSk7XG4gIH1cblxuICAvKiogQGludGVybmFsKi9cbiAgbmdPbkluaXQoKSB7XG4gICAgc3VwZXIubmdPbkluaXQoKTtcbiAgICB0aGlzLmVycm9yTWVzc2FnZSA9IHRoaXMuaTE4bi50KCd0ZWwuZXJyb3InKTtcbiAgICB0aGlzLnR5cGUgPSBEc2ZySW5wdXRUeXBlQ29uc3QuVEVMO1xuICAgIHRoaXMuc3BlbGxDaGVjayA9IGZhbHNlO1xuICAgIHRoaXMuaGludCA/Pz0gdGhpcy5pMThuLnQoJ3RlbC5oaW50Jyk7XG4gIH1cblxuICAvKipcbiAgICogRml4OiBhcHBsaXF1ZXIgbGUgbGFiZWwgcGFyIGTDqWZhdXQgdW5pcXVlbWVudCBzaSBsZSBzbG90IGxhYmVsIG4nZXN0IHBhcyByZW5zZWlnbsOpXG4gICAqIHNsb3QgbGFiZWwgbm9uIHJlbnNlaWduw6kgPT4gbGUgbGFiZWwgJ2ZyLWxhYmVsJyBuZSBwb3NzZWRlIGF1Y3VuIGVuZmFudCBvdSBzZXVsZW1lbnQgbGEgZGVzY3JpcHRpb24gYWRkaXRpb25uZWxsZVxuICAgKi9cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIGNvbnN0IGZpcnN0RWxlbWVudENoaWxkID0gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ/LnF1ZXJ5U2VsZWN0b3IoJy5mci1sYWJlbCcpLmZpcnN0RWxlbWVudENoaWxkO1xuXG4gICAgaWYgKCFmaXJzdEVsZW1lbnRDaGlsZCB8fCBbLi4uZmlyc3RFbGVtZW50Q2hpbGQuY2xhc3NMaXN0XS5pbmNsdWRlcygnZnItaGludC10ZXh0JykpIHtcbiAgICAgIHRoaXMubGFiZWwgPz89IHRoaXMuaTE4bi50KCd0ZWwubGFiZWwnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTcOpdGhvZGUgdmFsaWRhdGlvbiwgcG9zaXRpb25uZSBsYSBwcm9wcmnDqXTDqSBlcnJvciBzJ2lsIHkgYSBsaWV1LlxuICAgKi9cbiAgcHJvdGVjdGVkIHZhbGlkYXRlKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGlzVmFsaWQgPSBpc1Bob25lTnVtYmVyVmFsaWQodGhpcy52YWx1ZSwgdGhpcy5wYXR0ZXJuKTtcbiAgICB0aGlzLmVycm9yID0gaXNWYWxpZCA/ICcnIDogdGhpcy5lcnJvck1lc3NhZ2U7XG5cbiAgICByZXR1cm4gaXNWYWxpZDtcbiAgfVxufVxuIiwiPGVkdS1pbnB1dC1ncm91cFxuICBbaW5wdXRJZF09XCJpbnB1dElkXCJcbiAgW2xhYmVsXT1cImxhYmVsXCJcbiAgW2hpbnRdPVwiaGludFwiXG4gIFttZXNzYWdlc0dyb3VwSWRdPVwibWVzc2FnZXNHcm91cElkXCJcbiAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgW21lc3NhZ2VdPVwibWVzc2FnZVwiXG4gIFtzZXZlcml0eV09XCJtZXNzYWdlU2V2ZXJpdHlcIj5cbiAgPGxhYmVsIGNsYXNzPVwiZnItbGFiZWxcIiBbbmdDbGFzc109XCJ7ICdmci1zci1vbmx5JzogbGFiZWxTck9ubHkgfVwiIFtmb3JdPVwiaW5wdXRJZFwiPlxuICAgIEBpZiAobGFiZWwpIHtcbiAgICAgIHt7IGxhYmVsIH19XG4gICAgfSBAZWxzZSB7XG4gICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJbbGFiZWxdXCI+PC9uZy1jb250ZW50PlxuICAgIH1cbiAgICBAaWYgKGhpbnQpIHtcbiAgICAgIDxzcGFuIGNsYXNzPVwiZnItaGludC10ZXh0XCI+e3sgaGludCB9fTwvc3Bhbj5cbiAgICB9XG4gIDwvbGFiZWw+XG4gIEBpZiAoIWlzVGV4dEFyZWEoKSkge1xuICAgIEBpZiAoIWhhc0lucHV0V3JhcCgpKSB7XG4gICAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImlucHV0VGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbiAgICB9IEBlbHNlIHtcbiAgICAgIDxkaXYgW25nQ2xhc3NdPVwiZ2V0V3JhcENsYXNzZXMoKVwiPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiaW5wdXRUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICBAaWYgKGhhc0J1dHRvbigpKSB7XG4gICAgICAgICAgPGRzZnItYnV0dG9uXG4gICAgICAgICAgICBbYXJpYUxhYmVsXT1cImJ1dHRvbkFyaWFMYWJlbFwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiYnV0dG9uRGlzYWJsZWRcIlxuICAgICAgICAgICAgW2ljb25dPVwiYnV0dG9uSWNvblwiXG4gICAgICAgICAgICBbbGFiZWxdPVwiYnV0dG9uTGFiZWxcIlxuICAgICAgICAgICAgW3Rvb2x0aXBNZXNzYWdlXT1cImJ1dHRvblRvb2x0aXBNZXNzYWdlXCJcbiAgICAgICAgICAgIFt0eXBlXT1cImJ1dHRvblR5cGVcIlxuICAgICAgICAgICAgW3ZhcmlhbnRdPVwiYnV0dG9uVmFyaWFudFwiXG4gICAgICAgICAgICAoY2xpY2spPVwib25CdXR0b25DbGljaygkZXZlbnQpXCI+PC9kc2ZyLWJ1dHRvbj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgfVxuICB9IEBlbHNlIHtcbiAgICA8dGV4dGFyZWFcbiAgICAgIGNsYXNzPVwiZnItaW5wdXRcIlxuICAgICAgW25nQ2xhc3NdPVwiY3VzdG9tQ2xhc3MgfHwgbnVsbFwiXG4gICAgICBbaWRdPVwiaW5wdXRJZFwiXG4gICAgICBbYXR0ci5uYW1lXT1cIm5hbWUgfHwgbnVsbFwiXG4gICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgW3JlcXVpcmVkXT1cInJlcXVpcmVkXCJcbiAgICAgIFthdHRyLnBsYWNlaG9sZGVyXT1cInBsYWNlSG9sZGVyIHx8IG51bGxcIlxuICAgICAgW2F0dHIubWF4TGVuZ3RoXT1cIm1heExlbmd0aCB8fCBudWxsXCJcbiAgICAgIFthdHRyLm1pbkxlbmd0aF09XCJtaW5MZW5ndGggfHwgbnVsbFwiXG4gICAgICBbYXR0ci5hdXRvY29tcGxldGVdPVwiYXV0b2NvbXBsZXRlIHx8IG51bGxcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJtZXNzYWdlID8gbWVzc2FnZXNHcm91cElkIDogbnVsbFwiXG4gICAgICBbYXR0ci5hcmlhLWludmFsaWRdPVwiYXJpYUludmFsaWQgfHwgbnVsbFwiXG4gICAgICBbKG5nTW9kZWwpXT1cInZhbHVlXCJcbiAgICAgIFtuZ1N0eWxlXT1cIndpZHRoID8geyB3aWR0aDogd2lkdGggfSA6IHt9XCJcbiAgICAgIFthdHRyLnJvd3NdPVwicm93cyB8fCBudWxsXCI+PC90ZXh0YXJlYT5cbiAgfVxuPC9lZHUtaW5wdXQtZ3JvdXA+XG5cbjwhLS0gVGVtcGxhdGVzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuXG48IS0tIFRlbXBsYXRlIGlucHV0IC0tPlxuPG5nLXRlbXBsYXRlICNpbnB1dFRlbXBsYXRlPlxuICA8aW5wdXRcbiAgICBjbGFzcz1cImZyLWlucHV0XCJcbiAgICBbbmdDbGFzc109XCJjdXN0b21DbGFzcyB8fCBudWxsXCJcbiAgICBbYXR0ci5hdXRvY29tcGxldGVdPVwiYXV0b2NvbXBsZXRlIHx8IG51bGxcIlxuICAgIFthdHRyLmFyaWEtYXV0b2NvbXBsZXRlXT1cImFyaWFBdXRvY29tcGxldGUgfHwgbnVsbFwiXG4gICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJtZXNzYWdlID8gbWVzc2FnZXNHcm91cElkIDogbnVsbFwiXG4gICAgW2F0dHIuYXJpYS1kaXNhYmxlZF09XCJkaXNhYmxlZCB8fCBudWxsXCJcbiAgICBbYXR0ci5hcmlhLWV4cGFuZGVkXT1cImFyaWFFeHBhbmRlZCAhPT0gdW5kZWZpbmVkID8gYXJpYUV4cGFuZGVkIDogbnVsbFwiXG4gICAgW2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWwgfHwgbnVsbFwiXG4gICAgW2F0dHIuYXJpYS1pbnZhbGlkXT1cImFyaWFJbnZhbGlkIHx8IG51bGxcIlxuICAgIFtyZWFkT25seV09XCJyZWFkb25seVwiXG4gICAgW2F0dHIuYXJpYS1yZXF1aXJlZF09XCJyZXF1aXJlZCB8fCBudWxsXCJcbiAgICBbYXR0ci5yb2xlXT1cImlucHV0Um9sZSB8fCBudWxsXCJcbiAgICBbYXR0ci5pbnB1dG1vZGVdPVwiaW5wdXRNb2RlIHx8IG51bGxcIlxuICAgIFthdHRyLmF1dG9jb3JyZWN0XT1cImF1dG9Db3JyZWN0ID8gbnVsbCA6ICdvZmYnXCJcbiAgICBbKG5nTW9kZWwpXT1cInZhbHVlXCJcbiAgICBbaWRdPVwiaW5wdXRJZFwiXG4gICAgW2F0dHIubmFtZV09XCJuYW1lIHx8IG51bGxcIlxuICAgIFthdHRyLnR5cGVdPVwidHlwZSB8fCBudWxsXCJcbiAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgIFtyZXF1aXJlZF09XCJyZXF1aXJlZFwiXG4gICAgW2F0dHIucGF0dGVybl09XCJwYXR0ZXJuIHx8IG51bGxcIlxuICAgIFthdHRyLnBsYWNlaG9sZGVyXT1cInBsYWNlSG9sZGVyIHx8IG51bGxcIlxuICAgIFthdHRyLm1pbl09XCJtaW4gfHwgbnVsbFwiXG4gICAgW2F0dHIubWF4XT1cIm1heCB8fCBudWxsXCJcbiAgICBbYXR0ci5tYXhMZW5ndGhdPVwibWF4TGVuZ3RoIHx8IG51bGxcIlxuICAgIChibHVyKT1cIm9uQmx1cigpXCJcbiAgICBbYXR0ci5taW5MZW5ndGhdPVwibWluTGVuZ3RoIHx8IG51bGxcIlxuICAgIFthdHRyLnNwZWxsY2hlY2tdPVwic3BlbGxDaGVjayB8fCBudWxsXCJcbiAgICBbbmdTdHlsZV09XCJ3aWR0aCA/IHsgd2lkdGg6IHdpZHRoIH0gOiB7fVwiIC8+XG48L25nLXRlbXBsYXRlPlxuIl19