@bnsights/bbsf-controls 1.0.194-beta.9 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1315 -1245
- package/fesm2022/bnsights-bbsf-controls.mjs +375 -345
- package/fesm2022/bnsights-bbsf-controls.mjs.map +1 -1
- package/lib/Shared/Models/DropdownOptions.d.ts +3 -0
- package/lib/Shared/Models/RepeaterOptions.d.ts +2 -0
- package/lib/controls/ConfirmationModal/ConfirmationModal.component.d.ts +0 -1
- package/lib/controls/MapAutoComplete/MapAutoComplete.component.d.ts +0 -1
- package/lib/controls/MultiLingualTextBox/MultiLingualTextBox.component.d.ts +1 -1
- package/lib/controls/Repeater/repeater/repeater.component.d.ts +7 -0
- package/lib/controls/Repeater/repeater-table/repeater-table.component.d.ts +7 -0
- package/lib/modules/bbsf-editors.module.d.ts +6 -7
- package/package.json +34 -37
- package/src/lib/assets/Style.scss +2 -0
- package/src/lib/assets/ace-builds/ace.js +1 -1
- package/src/lib/assets/ace-builds/mode-markdown.js +1 -1
- package/esm2022/bnsights-bbsf-controls.mjs +0 -5
- package/esm2022/lib/Shared/Components/app-base-component.mjs +0 -226
- package/esm2022/lib/Shared/Components/ng-tag-input.mjs +0 -336
- package/esm2022/lib/Shared/Directives/appPreventDoubleClick.directive.mjs +0 -39
- package/esm2022/lib/Shared/Directives/template-name.directive.mjs +0 -19
- package/esm2022/lib/Shared/Enums/CalendarView.mjs +0 -8
- package/esm2022/lib/Shared/Enums/ControlLayout.mjs +0 -6
- package/esm2022/lib/Shared/Enums/Countries.mjs +0 -247
- package/esm2022/lib/Shared/Enums/Enums.mjs +0 -36
- package/esm2022/lib/Shared/Enums/FileType.mjs +0 -29
- package/esm2022/lib/Shared/Enums/FilterType.mjs +0 -11
- package/esm2022/lib/Shared/Enums/FontSize.mjs +0 -7
- package/esm2022/lib/Shared/Enums/ForceDirection.mjs +0 -6
- package/esm2022/lib/Shared/Enums/IconPosition.mjs +0 -6
- package/esm2022/lib/Shared/Enums/ImageType.mjs +0 -10
- package/esm2022/lib/Shared/Enums/InputType.mjs +0 -10
- package/esm2022/lib/Shared/Enums/Insert.mjs +0 -9
- package/esm2022/lib/Shared/Enums/LanguageMode.mjs +0 -11
- package/esm2022/lib/Shared/Enums/LanguageValidation.mjs +0 -6
- package/esm2022/lib/Shared/Enums/Markdown.mjs +0 -20
- package/esm2022/lib/Shared/Enums/Misc.mjs +0 -7
- package/esm2022/lib/Shared/Enums/PagingActionMode.mjs +0 -6
- package/esm2022/lib/Shared/Enums/Para.mjs +0 -9
- package/esm2022/lib/Shared/Enums/PickerType.mjs +0 -7
- package/esm2022/lib/Shared/Enums/SelectMode.mjs +0 -6
- package/esm2022/lib/Shared/Enums/StartView.mjs +0 -7
- package/esm2022/lib/Shared/Enums/Style.mjs +0 -8
- package/esm2022/lib/Shared/Enums/StyleConfirmationMode.mjs +0 -7
- package/esm2022/lib/Shared/Enums/TagInputView.mjs +0 -7
- package/esm2022/lib/Shared/Enums/ToolbarButtons.mjs +0 -33
- package/esm2022/lib/Shared/Enums/map-enums.mjs +0 -15
- package/esm2022/lib/Shared/Enums/menu-list-enum.mjs +0 -6
- package/esm2022/lib/Shared/Models/Attribute.mjs +0 -3
- package/esm2022/lib/Shared/Models/AutocompleteDTO.mjs +0 -8
- package/esm2022/lib/Shared/Models/AutocompleteOptions.mjs +0 -39
- package/esm2022/lib/Shared/Models/CalendarDTO.mjs +0 -3
- package/esm2022/lib/Shared/Models/CalendarEventDTO.mjs +0 -3
- package/esm2022/lib/Shared/Models/CalendarOptions.mjs +0 -19
- package/esm2022/lib/Shared/Models/CancelDTO.mjs +0 -7
- package/esm2022/lib/Shared/Models/CaptchaStyle.mjs +0 -3
- package/esm2022/lib/Shared/Models/CheckBoxOptions.mjs +0 -11
- package/esm2022/lib/Shared/Models/ConfirmationModalOptions.mjs +0 -39
- package/esm2022/lib/Shared/Models/ControlOptionsBase.mjs +0 -17
- package/esm2022/lib/Shared/Models/CustomValidation.mjs +0 -14
- package/esm2022/lib/Shared/Models/DatePickerOptions.mjs +0 -40
- package/esm2022/lib/Shared/Models/DropdownListItem.mjs +0 -3
- package/esm2022/lib/Shared/Models/DropdownOptions.mjs +0 -38
- package/esm2022/lib/Shared/Models/EditPersonalImage.mjs +0 -7
- package/esm2022/lib/Shared/Models/EnglishArabicDTO.mjs +0 -10
- package/esm2022/lib/Shared/Models/FileDTO.mjs +0 -24
- package/esm2022/lib/Shared/Models/FileOptions.mjs +0 -15
- package/esm2022/lib/Shared/Models/FileUploadModel.mjs +0 -3
- package/esm2022/lib/Shared/Models/FileUploadOptions.mjs +0 -13
- package/esm2022/lib/Shared/Models/FilterItem.mjs +0 -8
- package/esm2022/lib/Shared/Models/FormOptions.mjs +0 -32
- package/esm2022/lib/Shared/Models/HtmlEditorOptions.mjs +0 -12
- package/esm2022/lib/Shared/Models/ImageUploadOptions.mjs +0 -14
- package/esm2022/lib/Shared/Models/MapAutoCompleteOptions.mjs +0 -12
- package/esm2022/lib/Shared/Models/MapAutocompleteDTO.mjs +0 -6
- package/esm2022/lib/Shared/Models/MarkdownEditorOptions.mjs +0 -24
- package/esm2022/lib/Shared/Models/MultiLingualHtmlEditorOptions.mjs +0 -9
- package/esm2022/lib/Shared/Models/MultiLingualTextAreaOptions.mjs +0 -9
- package/esm2022/lib/Shared/Models/MultiLingualTextBoxOptions.mjs +0 -17
- package/esm2022/lib/Shared/Models/MultilingualControlOptionsBase.mjs +0 -21
- package/esm2022/lib/Shared/Models/MultipleFileUploadModel.mjs +0 -9
- package/esm2022/lib/Shared/Models/PagingDTO.mjs +0 -13
- package/esm2022/lib/Shared/Models/PagingOptions.mjs +0 -49
- package/esm2022/lib/Shared/Models/PagingPayload.mjs +0 -3
- package/esm2022/lib/Shared/Models/PhoneOptions.mjs +0 -16
- package/esm2022/lib/Shared/Models/ProfileImageUploadOptions.mjs +0 -11
- package/esm2022/lib/Shared/Models/ProfilePictureDTO.mjs +0 -3
- package/esm2022/lib/Shared/Models/RadioButtonItem.mjs +0 -3
- package/esm2022/lib/Shared/Models/RadioButtonOptions.mjs +0 -7
- package/esm2022/lib/Shared/Models/RangeNumber.mjs +0 -3
- package/esm2022/lib/Shared/Models/Recaptcha.mjs +0 -6
- package/esm2022/lib/Shared/Models/RecaptchaOptions.mjs +0 -22
- package/esm2022/lib/Shared/Models/RepeaterField.mjs +0 -3
- package/esm2022/lib/Shared/Models/RepeaterOptions.mjs +0 -14
- package/esm2022/lib/Shared/Models/SaveDTO.mjs +0 -7
- package/esm2022/lib/Shared/Models/TagsInputDTO.mjs +0 -3
- package/esm2022/lib/Shared/Models/TagsInputOptions.mjs +0 -56
- package/esm2022/lib/Shared/Models/TextAreaOptions.mjs +0 -19
- package/esm2022/lib/Shared/Models/TextBoxOptions.mjs +0 -27
- package/esm2022/lib/Shared/Models/ToggleSlideOptions.mjs +0 -9
- package/esm2022/lib/Shared/Models/UploadPersonalImage.mjs +0 -7
- package/esm2022/lib/Shared/Models/bread-crumb.mjs +0 -8
- package/esm2022/lib/Shared/Models/control-filter-Item.mjs +0 -6
- package/esm2022/lib/Shared/Models/filter-options.mjs +0 -9
- package/esm2022/lib/Shared/Models/index.mjs +0 -58
- package/esm2022/lib/Shared/Models/page-header-options.mjs +0 -78
- package/esm2022/lib/Shared/Pipes/bbsf-date-time.pipe.mjs +0 -22
- package/esm2022/lib/Shared/Pipes/bbsf-date.pipe.mjs +0 -22
- package/esm2022/lib/Shared/config/environment.mjs +0 -12
- package/esm2022/lib/Shared/default_intl.mjs +0 -29
- package/esm2022/lib/Shared/services/ControlUtility.mjs +0 -162
- package/esm2022/lib/Shared/services/GlobalSettings.service.mjs +0 -30
- package/esm2022/lib/Shared/services/OnPagingFiltersChange.service.mjs +0 -24
- package/esm2022/lib/Shared/services/file-upload.service.mjs +0 -29
- package/esm2022/lib/Shared/services/index.mjs +0 -7
- package/esm2022/lib/Shared/services/render-component-service.service.mjs +0 -32
- package/esm2022/lib/Shared/services/validationErrorMassage.service.mjs +0 -125
- package/esm2022/lib/Shared/utils/date-formatter.mjs +0 -48
- package/esm2022/lib/controls/AutocompleteTextBox/AutocompleteTextBox.component.mjs +0 -299
- package/esm2022/lib/controls/Calendar/Calendar.component.mjs +0 -179
- package/esm2022/lib/controls/CheckBox/CheckBox.component.mjs +0 -121
- package/esm2022/lib/controls/ConfirmationModal/ConfirmationModal.component.mjs +0 -143
- package/esm2022/lib/controls/DateTimePicker/DateTimePicker.component.mjs +0 -240
- package/esm2022/lib/controls/DropdownList/DropdownList.component.mjs +0 -296
- package/esm2022/lib/controls/FileUpload/FileUpload.component.mjs +0 -741
- package/esm2022/lib/controls/Form/Form.component.mjs +0 -117
- package/esm2022/lib/controls/HtmlEditor/HtmlEditor.component.mjs +0 -185
- package/esm2022/lib/controls/ImageUpload/ImageUpload.component.mjs +0 -360
- package/esm2022/lib/controls/MapAutoComplete/MapAutoComplete.component.mjs +0 -502
- package/esm2022/lib/controls/MarkdownEditor/markdown-editor.component.mjs +0 -243
- package/esm2022/lib/controls/MultiLingualHtmlEditor/MultiLingualHtmlEditor.component.mjs +0 -456
- package/esm2022/lib/controls/MultiLingualTextArea/MultiLingualTextArea.component.mjs +0 -441
- package/esm2022/lib/controls/MultiLingualTextBox/MultiLingualTextBox.component.mjs +0 -500
- package/esm2022/lib/controls/Paging/JwPagination.component.mjs +0 -160
- package/esm2022/lib/controls/Paging/Paging.component.mjs +0 -626
- package/esm2022/lib/controls/Phone/Phone.component.mjs +0 -134
- package/esm2022/lib/controls/ProfileImageUploader/ProfileImageUploader.component.mjs +0 -390
- package/esm2022/lib/controls/RadioButton/RadioButton.component.mjs +0 -113
- package/esm2022/lib/controls/Recaptcha/Recaptcha.component.mjs +0 -134
- package/esm2022/lib/controls/Repeater/repeater/repeater.component.mjs +0 -135
- package/esm2022/lib/controls/Repeater/repeater-field-builder/repeater-field-builder.component.mjs +0 -1291
- package/esm2022/lib/controls/Repeater/repeater-item-field/repeater-item-field.component.mjs +0 -22
- package/esm2022/lib/controls/Repeater/repeater-table/repeater-table.component.mjs +0 -118
- package/esm2022/lib/controls/TagsInput/TagsInput.component.mjs +0 -308
- package/esm2022/lib/controls/TextArea/TextArea.component.mjs +0 -581
- package/esm2022/lib/controls/TextBox/TextBox.component.mjs +0 -357
- package/esm2022/lib/controls/Toggleslide/Toggleslide.component.mjs +0 -96
- package/esm2022/lib/controls/bbsf-controls.module.mjs +0 -92
- package/esm2022/lib/controls/page-header-component/page-header-component.component.mjs +0 -42
- package/esm2022/lib/modules/bbsf-core.module.mjs +0 -210
- package/esm2022/lib/modules/bbsf-datetime.module.mjs +0 -90
- package/esm2022/lib/modules/bbsf-dropdown.module.mjs +0 -57
- package/esm2022/lib/modules/bbsf-editors.module.mjs +0 -97
- package/esm2022/lib/modules/bbsf-forms-basic.module.mjs +0 -79
- package/esm2022/lib/modules/bbsf-multilingual.module.mjs +0 -60
- package/esm2022/lib/modules/bbsf-phone.module.mjs +0 -57
- package/esm2022/lib/modules/bbsf-specialized.module.mjs +0 -160
- package/esm2022/lib/modules/bbsf-uploads.module.mjs +0 -106
- package/esm2022/lib/modules/bbsf-utility.module.mjs +0 -103
- package/esm2022/public-api.mjs +0 -169
|
@@ -1,581 +0,0 @@
|
|
|
1
|
-
import { Component, Input, Optional, Output, EventEmitter, SkipSelf } from '@angular/core';
|
|
2
|
-
import { CommonModule } from '@angular/common';
|
|
3
|
-
import { FormControl, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
4
|
-
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
|
5
|
-
import { InlineSVGModule } from 'ng-inline-svg-2';
|
|
6
|
-
import * as i0 from "@angular/core";
|
|
7
|
-
import * as i1 from "../../Shared/services";
|
|
8
|
-
import * as i2 from "@angular/forms";
|
|
9
|
-
import * as i3 from "@bnsights/bbsf-utilities/ui";
|
|
10
|
-
import * as i4 from "@bnsights/bbsf-utilities/translate";
|
|
11
|
-
import * as i5 from "@angular/common";
|
|
12
|
-
import * as i6 from "@ng-bootstrap/ng-bootstrap";
|
|
13
|
-
import * as i7 from "ng-inline-svg-2";
|
|
14
|
-
export class TextAreaComponent {
|
|
15
|
-
constructor(controlUtility, controlContainer, textAreaControlHost, utilityService, controlValidationService, globalSettings, speechRecognitionService, languageService) {
|
|
16
|
-
this.controlUtility = controlUtility;
|
|
17
|
-
this.controlContainer = controlContainer;
|
|
18
|
-
this.textAreaControlHost = textAreaControlHost;
|
|
19
|
-
this.utilityService = utilityService;
|
|
20
|
-
this.controlValidationService = controlValidationService;
|
|
21
|
-
this.globalSettings = globalSettings;
|
|
22
|
-
this.speechRecognitionService = speechRecognitionService;
|
|
23
|
-
this.languageService = languageService;
|
|
24
|
-
this.onChange = new EventEmitter();
|
|
25
|
-
this.wordCount = 0;
|
|
26
|
-
this.wordCountArray = 0;
|
|
27
|
-
this.isShowWordCount = false;
|
|
28
|
-
this.markAllAsTouched = false;
|
|
29
|
-
this.validationRules = [];
|
|
30
|
-
this.validationRulesasync = [];
|
|
31
|
-
//For Show warning message of max length limit
|
|
32
|
-
this.currentCharsCount = 0;
|
|
33
|
-
this.showCharsLimitMsg = false;
|
|
34
|
-
this.hasCharsLimitValidationError = false;
|
|
35
|
-
this.minCharsLimit = -1; //To disable chars limit feature by default
|
|
36
|
-
this.maxLimitWarningMsg = '';
|
|
37
|
-
this.isMicOn = false;
|
|
38
|
-
this.selectedSpeechLanguageDisplayText = '';
|
|
39
|
-
this.isLanguageSelectFocusVisible = false;
|
|
40
|
-
this.isMicFocusVisible = false;
|
|
41
|
-
// Accessibility properties
|
|
42
|
-
this.ariaDescribedBy = '';
|
|
43
|
-
this.errorMessageId = '';
|
|
44
|
-
this.characterCountId = '';
|
|
45
|
-
this.wordCountId = '';
|
|
46
|
-
this.resetError = () => {
|
|
47
|
-
this.controlValidationService.removeGlobalError();
|
|
48
|
-
};
|
|
49
|
-
//External Method
|
|
50
|
-
this.removeRequiredValidation = () => {
|
|
51
|
-
this.controlUtility.removeRequiredValidation(this.textAreaFormControl, this.validationRules, this.options);
|
|
52
|
-
};
|
|
53
|
-
//External Method
|
|
54
|
-
this.addRequiredValidation = () => {
|
|
55
|
-
this.controlUtility.addRequiredValidation(this.textAreaFormControl, this.validationRules, this.options);
|
|
56
|
-
};
|
|
57
|
-
//External Method
|
|
58
|
-
this.removeCustomValidation = (customValidation) => {
|
|
59
|
-
this.controlUtility.removeCustomValidation(this.textAreaFormControl, this.validationRules, customValidation);
|
|
60
|
-
};
|
|
61
|
-
//External Method
|
|
62
|
-
this.addCustomValidation = (customValidation) => {
|
|
63
|
-
this.controlUtility.addCustomValidation(this.textAreaFormControl, this.validationRules, customValidation);
|
|
64
|
-
};
|
|
65
|
-
//External Method
|
|
66
|
-
this.isValid = () => {
|
|
67
|
-
this.controlUtility.isValid(this.textAreaFormControl);
|
|
68
|
-
};
|
|
69
|
-
this.currentLanguage = localStorage.getItem('language');
|
|
70
|
-
}
|
|
71
|
-
ngOnInit() {
|
|
72
|
-
// Initialize accessibility IDs
|
|
73
|
-
this.errorMessageId = `${this.options.name}-error`;
|
|
74
|
-
this.characterCountId = `${this.options.name}-char-count`;
|
|
75
|
-
this.wordCountId = `${this.options.name}-word-count`;
|
|
76
|
-
this.updateAriaDescribedBy();
|
|
77
|
-
// Initialize speech recognition properties only if enabled
|
|
78
|
-
if (this.options.enableSpeechRecognition) {
|
|
79
|
-
this.isMicOn = false;
|
|
80
|
-
this.selectedSpeechLanguageDisplayText = '';
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
// Reset speech-related properties when disabled
|
|
84
|
-
this.resetSpeechProperties();
|
|
85
|
-
}
|
|
86
|
-
if (this.options.isReadonly && !this.options.value)
|
|
87
|
-
this.options.value = this.utilityService.getResourceValue('NA');
|
|
88
|
-
if (this.options.forceDirection)
|
|
89
|
-
this.textDir = this.options.forceDirection == 2 ? 'rtl' : 'ltr';
|
|
90
|
-
else
|
|
91
|
-
this.textDir = localStorage.getItem('language') == 'ar' ? 'rtl' : 'ltr';
|
|
92
|
-
this.controlValidationService.isCreatedBefor = false;
|
|
93
|
-
this.group.addControl(this.options.name, new FormControl(''));
|
|
94
|
-
this.textAreaFormControl = this.group.controls[this.options.name]; // new FormControl('',validationRules);
|
|
95
|
-
if (!this.options.maxLength)
|
|
96
|
-
this.options.maxLength = this.globalSettings.maxLengthTextArea;
|
|
97
|
-
if (!this.options.viewType)
|
|
98
|
-
this.options.viewType = this.globalSettings.viewType;
|
|
99
|
-
if (this.options.labelKey != null && this.options.labelKey != '')
|
|
100
|
-
this.options.labelValue = this.utilityService.getResourceValue(this.options.labelKey);
|
|
101
|
-
if (this.options.enableSpeechRecognition) {
|
|
102
|
-
// Initialize language form control
|
|
103
|
-
const languageControlName = 'Language_' + this.options.name;
|
|
104
|
-
this.group.addControl(languageControlName, new FormControl(this.options.selectedSpeechLanguage || ''));
|
|
105
|
-
//Get all languages if not set
|
|
106
|
-
if (!this.options.speechLanguages) {
|
|
107
|
-
this.languageService.getLanguages().subscribe((result) => {
|
|
108
|
-
this.options.speechLanguages = result;
|
|
109
|
-
this.setSpeechLanguage();
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
this.setSpeechLanguage();
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
this.textAreaFormControl.setValue(this.options.value);
|
|
117
|
-
if (this.options.customValidation.length > 0) {
|
|
118
|
-
let Validations = this.options.customValidation;
|
|
119
|
-
for (let index = 0; index < Validations.length; index++) {
|
|
120
|
-
const Validation = Validations[index];
|
|
121
|
-
this.validationRules.push(Validation.functionBody);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
if (this.options.minLength > 0) {
|
|
125
|
-
this.validationRules.push(Validators.minLength(this.options.minLength));
|
|
126
|
-
}
|
|
127
|
-
if (this.options.maxLength > 0) {
|
|
128
|
-
this.validationRules.push(Validators.maxLength(this.options.maxLength));
|
|
129
|
-
if (!this.options.maxLengthWarningLimit)
|
|
130
|
-
this.options.maxLengthWarningLimit = this.globalSettings.maxLengthWarningLimit;
|
|
131
|
-
this.minCharsLimit = this.options.maxLength - this.options.maxLengthWarningLimit;
|
|
132
|
-
}
|
|
133
|
-
if (this.options.isRequired) {
|
|
134
|
-
this.validationRules.push(Validators.required);
|
|
135
|
-
}
|
|
136
|
-
this.textAreaFormControl.setValidators(this.validationRules);
|
|
137
|
-
this.textAreaFormControl.setAsyncValidators(this.validationRulesasync);
|
|
138
|
-
if (this.options.isDisabled) {
|
|
139
|
-
this.textAreaFormControl.disable();
|
|
140
|
-
}
|
|
141
|
-
// Only subscribe to ngSubmit if FormGroupDirective is available
|
|
142
|
-
if (this.textAreaControlHost) {
|
|
143
|
-
this.textAreaControlHost.ngSubmit.subscribe((value) => {
|
|
144
|
-
this.group.markAllAsTouched();
|
|
145
|
-
this.markAllAsTouched = true;
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
// Subscribe to value changes to ensure warning messages are properly reset
|
|
149
|
-
this.valueChangesSubscription = this.textAreaFormControl.valueChanges.subscribe((value) => {
|
|
150
|
-
// Reset warning message when control is empty or null
|
|
151
|
-
if (!value || value.trim().length === 0) {
|
|
152
|
-
this.showCharsLimitMsg = false;
|
|
153
|
-
this.hasCharsLimitValidationError = false;
|
|
154
|
-
this.maxLimitWarningMsg = '';
|
|
155
|
-
this.currentCharsCount = 0;
|
|
156
|
-
this.wordCount = 0;
|
|
157
|
-
this.wordCountArray = 0;
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
ngAfterViewInit() {
|
|
162
|
-
this.controlUtility.setAttributeForControl(this.options);
|
|
163
|
-
}
|
|
164
|
-
showGlobalError() {
|
|
165
|
-
this.controlUtility.showGlobalError();
|
|
166
|
-
}
|
|
167
|
-
getErrorValidation(ErrorList) {
|
|
168
|
-
if (this.markAllAsTouched && this.group.invalid) {
|
|
169
|
-
this.showGlobalError();
|
|
170
|
-
this.markAllAsTouched = false;
|
|
171
|
-
}
|
|
172
|
-
return this.controlUtility.getErrorValidationMassage(ErrorList, this.group, this.options);
|
|
173
|
-
}
|
|
174
|
-
getInputType(type) {
|
|
175
|
-
return this.controlUtility.getInputType(type);
|
|
176
|
-
}
|
|
177
|
-
// Accessibility helper methods
|
|
178
|
-
updateAriaDescribedBy() {
|
|
179
|
-
const describedByIds = [];
|
|
180
|
-
if (this.options.labelDescription) {
|
|
181
|
-
describedByIds.push(`${this.options.name}-description`);
|
|
182
|
-
}
|
|
183
|
-
if (this.options.maxWordCount > 0) {
|
|
184
|
-
describedByIds.push(this.wordCountId);
|
|
185
|
-
}
|
|
186
|
-
if (this.showCharsLimitMsg) {
|
|
187
|
-
describedByIds.push(this.characterCountId);
|
|
188
|
-
}
|
|
189
|
-
if (this.textAreaFormControl?.invalid && this.textAreaFormControl?.touched) {
|
|
190
|
-
describedByIds.push(this.errorMessageId);
|
|
191
|
-
}
|
|
192
|
-
// Only add speech-related descriptions if speech recognition is enabled
|
|
193
|
-
if (this.options.enableSpeechRecognition && this.selectedSpeechLanguageDisplayText) {
|
|
194
|
-
describedByIds.push(`${this.options.name}-language-display`);
|
|
195
|
-
}
|
|
196
|
-
this.ariaDescribedBy = describedByIds.join(' ');
|
|
197
|
-
}
|
|
198
|
-
announceToScreenReader(message) {
|
|
199
|
-
// Create temporary element for screen reader announcement
|
|
200
|
-
const announcement = document.createElement('div');
|
|
201
|
-
announcement.setAttribute('aria-live', 'polite');
|
|
202
|
-
announcement.setAttribute('aria-atomic', 'true');
|
|
203
|
-
announcement.className = 'sr-only';
|
|
204
|
-
announcement.textContent = message;
|
|
205
|
-
document.body.appendChild(announcement);
|
|
206
|
-
// Remove after announcement
|
|
207
|
-
setTimeout(() => {
|
|
208
|
-
document.body.removeChild(announcement);
|
|
209
|
-
}, 1000);
|
|
210
|
-
}
|
|
211
|
-
resetSpeechProperties() {
|
|
212
|
-
// Reset all speech-related properties when speech recognition is disabled
|
|
213
|
-
this.isMicOn = false;
|
|
214
|
-
this.selectedSpeechLanguageDisplayText = '';
|
|
215
|
-
// Clean up any active speech recognition subscriptions
|
|
216
|
-
if (this.subscription) {
|
|
217
|
-
this.subscription.unsubscribe();
|
|
218
|
-
this.subscription = null;
|
|
219
|
-
}
|
|
220
|
-
// Remove speech language form control if it exists
|
|
221
|
-
const languageControlName = 'Language_' + this.options.name;
|
|
222
|
-
if (this.group?.get(languageControlName)) {
|
|
223
|
-
this.group.removeControl(languageControlName);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
trimControlValue() {
|
|
227
|
-
let originalValue = this.controlUtility.trimControlValue(this.textAreaFormControl.value);
|
|
228
|
-
this.textAreaFormControl.patchValue(originalValue);
|
|
229
|
-
if (this.options.patchFunction && this.options.patchPath && this.textAreaFormControl.valid) {
|
|
230
|
-
this.controlUtility.patchControlValue(originalValue, this.options.patchFunction, this.options.patchPath);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
onKeyDown(event) {
|
|
234
|
-
const textarea = event.target;
|
|
235
|
-
const currentValue = textarea.value || '';
|
|
236
|
-
const key = event.key;
|
|
237
|
-
// Allow navigation keys (arrows, home, end, etc.)
|
|
238
|
-
const allowedKeys = ['Backspace', 'Delete', 'Tab', 'Escape', 'Enter', 'Home', 'End', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
|
|
239
|
-
// Allow Ctrl/Cmd + keys (copy, paste, select all, etc.)
|
|
240
|
-
if (event.ctrlKey || event.metaKey) {
|
|
241
|
-
return; // Allow all Ctrl/Cmd combinations
|
|
242
|
-
}
|
|
243
|
-
// If it's a navigation key, allow it
|
|
244
|
-
if (allowedKeys.includes(key)) {
|
|
245
|
-
// Special handling for word count on Backspace
|
|
246
|
-
if (key === 'Backspace' && this.options.maxWordCount > 0) {
|
|
247
|
-
return; // Always allow backspace for word count correction
|
|
248
|
-
}
|
|
249
|
-
return;
|
|
250
|
-
}
|
|
251
|
-
// Check word count limit
|
|
252
|
-
if (this.options.maxWordCount > 0) {
|
|
253
|
-
const currentWordCount = currentValue.trim() ? currentValue.trim().split(/\s+/).length : 0;
|
|
254
|
-
if (currentWordCount >= this.options.maxWordCount && key !== 'Backspace' && key !== 'Delete') {
|
|
255
|
-
// Check if adding this character would create a new word
|
|
256
|
-
const cursorPosition = textarea.selectionStart;
|
|
257
|
-
const charBefore = cursorPosition > 0 ? currentValue[cursorPosition - 1] : '';
|
|
258
|
-
const charAfter = cursorPosition < currentValue.length ? currentValue[cursorPosition] : '';
|
|
259
|
-
// If we're typing a space or the character before/after is a space, this might create a new word
|
|
260
|
-
if (key === ' ' || (/\s/.test(charBefore) && !(/\s/.test(key)))) {
|
|
261
|
-
event.preventDefault();
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
// Check character count limit
|
|
267
|
-
if (this.options.maxLength && currentValue.length >= this.options.maxLength) {
|
|
268
|
-
// Only allow if we have selected text (which will be replaced) or navigation keys
|
|
269
|
-
const hasSelection = textarea.selectionStart !== textarea.selectionEnd;
|
|
270
|
-
if (!hasSelection && !allowedKeys.includes(key)) {
|
|
271
|
-
event.preventDefault();
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
copyInputMessage(inputElement) {
|
|
277
|
-
this.controlUtility.CopyInputMessage(inputElement);
|
|
278
|
-
// Announce to screen readers
|
|
279
|
-
this.announceToScreenReader('Text copied to clipboard');
|
|
280
|
-
}
|
|
281
|
-
onTextChange() {
|
|
282
|
-
if (this.textAreaFormControl.value == '') {
|
|
283
|
-
this.wordCountArray = 0;
|
|
284
|
-
this.wordCount = 0;
|
|
285
|
-
}
|
|
286
|
-
else {
|
|
287
|
-
this.wordCountArray = this.textAreaFormControl.value.split(' ').length;
|
|
288
|
-
if (this.wordCountArray > 0) {
|
|
289
|
-
if (this.wordCountArray > this.options.maxWordCount) {
|
|
290
|
-
this.wordCount = this.options.maxWordCount;
|
|
291
|
-
this.textAreaFormControl.setErrors({
|
|
292
|
-
errorMessage: `Word count must be less than or equal to ${this.options.maxWordCount}`
|
|
293
|
-
});
|
|
294
|
-
this.textAreaFormControl.markAsTouched();
|
|
295
|
-
this.textAreaFormControl.invalid;
|
|
296
|
-
}
|
|
297
|
-
else {
|
|
298
|
-
this.wordCount = this.wordCountArray;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
//Check for maxlength limit count
|
|
303
|
-
//MaxLength should be greater than or equals chars limit so that minCharsLimit would be >= 0
|
|
304
|
-
if (this.options.maxLength && this.minCharsLimit >= 0) {
|
|
305
|
-
// Check if value exists and is not empty
|
|
306
|
-
const controlValue = this.textAreaFormControl.value;
|
|
307
|
-
if (controlValue && controlValue.trim().length > 0) {
|
|
308
|
-
this.currentCharsCount = controlValue.length;
|
|
309
|
-
if (this.currentCharsCount > this.minCharsLimit) {
|
|
310
|
-
this.showCharsLimitMsg = true;
|
|
311
|
-
this.hasCharsLimitValidationError = true;
|
|
312
|
-
if (this.currentCharsCount == this.options.maxLength)
|
|
313
|
-
this.charsLimitMsgClass = 'danger';
|
|
314
|
-
else
|
|
315
|
-
this.charsLimitMsgClass = 'warning';
|
|
316
|
-
// Only generate warning message when we actually want to show it
|
|
317
|
-
let max = this.options.maxLength;
|
|
318
|
-
let current = this.currentCharsCount;
|
|
319
|
-
let msg = this.utilityService.getResourceValue('MaxLengthLimitWarning');
|
|
320
|
-
this.maxLimitWarningMsg = msg
|
|
321
|
-
.replace('${max}', max.toString())
|
|
322
|
-
.replace('${current}', current.toString());
|
|
323
|
-
}
|
|
324
|
-
else {
|
|
325
|
-
this.showCharsLimitMsg = false;
|
|
326
|
-
this.hasCharsLimitValidationError = false;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
// Reset everything when value is empty
|
|
331
|
-
this.currentCharsCount = 0;
|
|
332
|
-
this.showCharsLimitMsg = false;
|
|
333
|
-
this.hasCharsLimitValidationError = false;
|
|
334
|
-
this.maxLimitWarningMsg = '';
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
this.onChange.emit(this.textAreaFormControl.value);
|
|
338
|
-
// Update accessibility attributes
|
|
339
|
-
this.updateAriaDescribedBy();
|
|
340
|
-
// Announce character limit warnings to screen readers
|
|
341
|
-
if (this.showCharsLimitMsg && this.charsLimitMsgClass === 'danger') {
|
|
342
|
-
this.announceToScreenReader(`Character limit reached: ${this.maxLimitWarningMsg}`);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
onFocus(isFocus) {
|
|
346
|
-
this.isShowWordCount = isFocus;
|
|
347
|
-
//onFocus
|
|
348
|
-
if (isFocus) {
|
|
349
|
-
if (this.hasCharsLimitValidationError)
|
|
350
|
-
//check if there was previous validation error
|
|
351
|
-
this.showCharsLimitMsg = true;
|
|
352
|
-
} //onFocusOut
|
|
353
|
-
else
|
|
354
|
-
this.showCharsLimitMsg = false;
|
|
355
|
-
}
|
|
356
|
-
//region Speech Recognition
|
|
357
|
-
setSpeechLanguage() {
|
|
358
|
-
// Guard: Only execute if speech recognition is enabled
|
|
359
|
-
if (!this.options.enableSpeechRecognition) {
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
const languageControlName = 'Language_' + this.options.name;
|
|
363
|
-
if (this.options.autoSaveSpeechLanguagetoLocalStorage) {
|
|
364
|
-
let savedLanguage = localStorage.getItem('speechLanguage');
|
|
365
|
-
if (savedLanguage) {
|
|
366
|
-
this.options.selectedSpeechLanguage = savedLanguage;
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
this.loadSelectedSpeechLanguage();
|
|
370
|
-
localStorage.setItem('speechLanguage', this.options.selectedSpeechLanguage);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
else {
|
|
374
|
-
this.loadSelectedSpeechLanguage();
|
|
375
|
-
}
|
|
376
|
-
this.group.get(languageControlName).setValue(this.options.selectedSpeechLanguage);
|
|
377
|
-
const language = this.options.speechLanguages?.find((l) => l.dialect == this.options.selectedSpeechLanguage);
|
|
378
|
-
this.selectedSpeechLanguageDisplayText = language?.prefix || '';
|
|
379
|
-
}
|
|
380
|
-
loadSelectedSpeechLanguage() {
|
|
381
|
-
// Guard: Only execute if speech recognition is enabled
|
|
382
|
-
if (!this.options.enableSpeechRecognition) {
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
if (!this.options.selectedSpeechLanguage) {
|
|
386
|
-
if (this.currentLanguage == 'en' &&
|
|
387
|
-
this.options.speechLanguages.some((language) => language.englishName === 'English')) {
|
|
388
|
-
this.options.selectedSpeechLanguage = this.options.speechLanguages.find((language) => language.englishName === 'English').dialect;
|
|
389
|
-
}
|
|
390
|
-
else if (this.currentLanguage == 'ar' &&
|
|
391
|
-
this.options.speechLanguages.some((language) => language.englishName === 'Arabic')) {
|
|
392
|
-
this.options.selectedSpeechLanguage = this.options.speechLanguages.find((language) => language.englishName === 'Arabic').dialect;
|
|
393
|
-
}
|
|
394
|
-
else {
|
|
395
|
-
this.options.selectedSpeechLanguage = this.options.speechLanguages[0].dialect;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
startSpeechRecognition() {
|
|
400
|
-
// Guard: Only execute if speech recognition is enabled
|
|
401
|
-
if (!this.options.enableSpeechRecognition) {
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
404
|
-
if (!this.speechRecognitionService.isSupported) {
|
|
405
|
-
const errorMessage = this.utilityService.getResourceValue('BrowserNotSupportSpeechRecognition');
|
|
406
|
-
this.utilityService.notifyErrorMessage(errorMessage);
|
|
407
|
-
this.announceToScreenReader(errorMessage);
|
|
408
|
-
return;
|
|
409
|
-
}
|
|
410
|
-
//Disable Select Language
|
|
411
|
-
this.enableOrDisableLanguageSelect(false);
|
|
412
|
-
this.isMicOn = true;
|
|
413
|
-
// Announce to screen readers
|
|
414
|
-
this.announceToScreenReader('Speech recognition started. Speak now.');
|
|
415
|
-
this.subscription = this.speechRecognitionService
|
|
416
|
-
.startListening(this.options.selectedSpeechLanguage)
|
|
417
|
-
.subscribe({
|
|
418
|
-
next: (transcript) => {
|
|
419
|
-
if (transcript) {
|
|
420
|
-
if (this.options.value) {
|
|
421
|
-
this.options.value += ' ';
|
|
422
|
-
this.fireOnChange(this.options.value);
|
|
423
|
-
}
|
|
424
|
-
let charIndex = 0;
|
|
425
|
-
const interval = setInterval(() => {
|
|
426
|
-
this.options.value += transcript[charIndex];
|
|
427
|
-
this.fireOnChange(this.options.value);
|
|
428
|
-
charIndex++;
|
|
429
|
-
if (charIndex === transcript.length) {
|
|
430
|
-
clearInterval(interval);
|
|
431
|
-
}
|
|
432
|
-
}, 10);
|
|
433
|
-
}
|
|
434
|
-
},
|
|
435
|
-
error: (error) => {
|
|
436
|
-
console.error(error);
|
|
437
|
-
this.stopSpeechRecognition();
|
|
438
|
-
},
|
|
439
|
-
complete: () => {
|
|
440
|
-
//Enable Select Language
|
|
441
|
-
this.enableOrDisableLanguageSelect();
|
|
442
|
-
this.isMicOn = false;
|
|
443
|
-
this.announceToScreenReader('Speech recognition stopped.');
|
|
444
|
-
}
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
stopSpeechRecognition() {
|
|
448
|
-
// Guard: Only execute if speech recognition is enabled
|
|
449
|
-
if (!this.options.enableSpeechRecognition) {
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
this.enableOrDisableLanguageSelect();
|
|
453
|
-
if (!this.speechRecognitionService.isSupported) {
|
|
454
|
-
return;
|
|
455
|
-
}
|
|
456
|
-
this.isMicOn = false;
|
|
457
|
-
this.speechRecognitionService.stopListening();
|
|
458
|
-
if (this.subscription) {
|
|
459
|
-
this.subscription.unsubscribe();
|
|
460
|
-
}
|
|
461
|
-
// Announce to screen readers
|
|
462
|
-
this.announceToScreenReader('Speech recognition stopped.');
|
|
463
|
-
}
|
|
464
|
-
fireOnChange(text) {
|
|
465
|
-
if (this.onChange) {
|
|
466
|
-
this.onChange.emit(text);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
ngOnDestroy() {
|
|
470
|
-
// Always clean up subscriptions
|
|
471
|
-
if (this.subscription) {
|
|
472
|
-
this.subscription.unsubscribe();
|
|
473
|
-
}
|
|
474
|
-
if (this.valueChangesSubscription) {
|
|
475
|
-
this.valueChangesSubscription.unsubscribe();
|
|
476
|
-
}
|
|
477
|
-
// Only call speech recognition cleanup if it was enabled
|
|
478
|
-
if (this.options.enableSpeechRecognition) {
|
|
479
|
-
this.stopSpeechRecognition();
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
// Keyboard accessibility for speech recognition controls
|
|
483
|
-
onMicKeydown(event, action) {
|
|
484
|
-
// Guard: Only execute if speech recognition is enabled
|
|
485
|
-
if (!this.options.enableSpeechRecognition) {
|
|
486
|
-
return;
|
|
487
|
-
}
|
|
488
|
-
if (event.key === 'Enter' || event.key === ' ') {
|
|
489
|
-
event.preventDefault();
|
|
490
|
-
if (action === 'start') {
|
|
491
|
-
this.startSpeechRecognition();
|
|
492
|
-
}
|
|
493
|
-
else {
|
|
494
|
-
this.stopSpeechRecognition();
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
onLanguageSelectFocus(isFocused) {
|
|
499
|
-
if (!this.options.enableSpeechRecognition) {
|
|
500
|
-
return;
|
|
501
|
-
}
|
|
502
|
-
this.isLanguageSelectFocusVisible = isFocused;
|
|
503
|
-
}
|
|
504
|
-
onLanguageSelectKeydown(event) {
|
|
505
|
-
if (!this.options.enableSpeechRecognition) {
|
|
506
|
-
return;
|
|
507
|
-
}
|
|
508
|
-
if (event.key === 'Tab') {
|
|
509
|
-
this.isLanguageSelectFocusVisible = true;
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
onMicFocus(isFocused) {
|
|
513
|
-
if (!this.options.enableSpeechRecognition) {
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
516
|
-
this.isMicFocusVisible = isFocused;
|
|
517
|
-
}
|
|
518
|
-
onCopyKeydown(event, inputElement) {
|
|
519
|
-
if (event.key === 'Enter' || event.key === ' ') {
|
|
520
|
-
event.preventDefault();
|
|
521
|
-
this.copyInputMessage(inputElement);
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
onSpeechLanguageChange(event) {
|
|
525
|
-
// Guard: Only execute if speech recognition is enabled
|
|
526
|
-
if (!this.options.enableSpeechRecognition) {
|
|
527
|
-
return;
|
|
528
|
-
}
|
|
529
|
-
let selectedLang_Dialect = event.target.value;
|
|
530
|
-
const language = this.options.speechLanguages?.find((l) => l.dialect == selectedLang_Dialect);
|
|
531
|
-
this.selectedSpeechLanguageDisplayText = language?.prefix || '';
|
|
532
|
-
this.options.selectedSpeechLanguage = selectedLang_Dialect;
|
|
533
|
-
const languageControlName = 'Language_' + this.options.name;
|
|
534
|
-
let select = this.group.get(languageControlName);
|
|
535
|
-
select.setValue(selectedLang_Dialect);
|
|
536
|
-
if (this.options.autoSaveSpeechLanguagetoLocalStorage) {
|
|
537
|
-
localStorage.setItem('speechLanguage', selectedLang_Dialect);
|
|
538
|
-
}
|
|
539
|
-
// Announce language change to screen readers
|
|
540
|
-
this.announceToScreenReader(`Speech recognition language changed to ${language?.name || selectedLang_Dialect}`);
|
|
541
|
-
}
|
|
542
|
-
enableOrDisableLanguageSelect(isEnabled = true) {
|
|
543
|
-
// Guard: Only execute if speech recognition is enabled
|
|
544
|
-
if (!this.options.enableSpeechRecognition) {
|
|
545
|
-
return;
|
|
546
|
-
}
|
|
547
|
-
const languageControlName = 'Language_' + this.options.name;
|
|
548
|
-
let select = this.group.get(languageControlName);
|
|
549
|
-
if (isEnabled) {
|
|
550
|
-
select.enable();
|
|
551
|
-
}
|
|
552
|
-
else {
|
|
553
|
-
select.disable();
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextAreaComponent, deps: [{ token: i1.ControlUtility }, { token: i2.ControlContainer, optional: true, skipSelf: true }, { token: i2.FormGroupDirective, optional: true }, { token: i3.UtilityService }, { token: i3.ControlValidationService }, { token: i1.GlobalSettings }, { token: i3.SpeechRecognitionService }, { token: i4.LanguageService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
557
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TextAreaComponent, isStandalone: true, selector: "BBSF-TextArea", inputs: { group: "group", options: "options" }, outputs: { onChange: "onChange" }, ngImport: i0, template: "<div class=\"form-group bbsf-control bbsf-textarea\" [formGroup]=\"group\">\r\n <div [ngClass]=\"(options.viewType==1)?'bbsf-vertical':'bbsf-horizontal'\">\r\n <!--label-->\r\n <label *ngIf=\"!options.hideLabel\" class=\"bbsf-label {{options.labelExtraClasses}}\">\r\n {{options.labelValue}}\r\n <!--Asterisk-->\r\n <span *ngIf=\"((options.showAsterisk&&options.isRequired)||(options.isRequired))&&!options.isReadonly\"\r\n class=\"text-danger\">*</span>\r\n </label>\r\n <div *ngIf=\"!options.isReadonly\" class=\"bbsf-input-container\" [ngClass]=\"{\r\n 'p-120px': options.enableSpeechRecognition && options.enableCopyToClipboard,\r\n 'p-80px': options.enableSpeechRecognition && !options.enableCopyToClipboard,\r\n 'p-40px': !options.enableSpeechRecognition && options.enableCopyToClipboard\r\n }\">\r\n <!--input-->\r\n <textarea class=\"form-control {{options.extraClasses}}\" (focus)=\"onFocus(true)\" (focusout)=\"onFocus(false)\"\r\n [dir]=\"textDir\" [attr.aria-invalid]=\"textAreaFormControl.invalid && textAreaFormControl.touched\"\r\n [attr.aria-describedby]=\"ariaDescribedBy\" [attr.aria-label]=\"options.labelValue || options.placeholder\"\r\n formControlName=\"{{options.name}}\"\r\n [class.is-invalid]=\"textAreaFormControl.invalid && textAreaFormControl.touched\"\r\n placeholder=\"{{options.placeholder}}\" id=\"{{options.name}}\" autocomplete=\"{{options.autoComplete}}\"\r\n (change)=\"trimControlValue()\" rows=\"{{options.rows}}\" (keyup)=\"onTextChange()\" cols=\"{{options.cols}}\"\r\n [attr.minlength]=\"options.minLength\" [(ngModel)]=\"options.value\" (keydown)=\"onKeyDown($event)\"\r\n [attr.maxlength]=\"options.maxLength\" role=\"textbox\" [attr.aria-multiline]=\"true\" #TextAreainput></textarea>\r\n <!--CopyToClipboard-->\r\n <button type=\"button\" class=\"copy-clipboard\" *ngIf=\"options.enableCopyToClipboard\"\r\n (click)=\"copyInputMessage(TextAreainput)\" (keydown)=\"onCopyKeydown($event, TextAreainput)\"\r\n [attr.aria-label]=\"utilityService.getResourceValue('CopyTextToClipboard')\" [ngbTooltip]=\"utilityService.getResourceValue('CopyTextToClipboard')\" tabindex=\"0\">\r\n <i class=\"fas fa-copy\" aria-hidden=\"true\"></i>\r\n </button>\r\n <div [ngClass]=\"{'expanded': isFocused}\" class=\"language-container {{options.extraClassMicLanguage}}\"\r\n *ngIf=\"options.enableSpeechRecognition\" role=\"region\">\r\n\r\n <!-- Start Speech Recognition Button -->\r\n <button type=\"button\" class=\"svg-icon svg-icon-5 speech-control-btn\" [class.focus-visible]=\"isMicFocusVisible\"\r\n [inlineSVG]=\"options.iconMic || 'assets/bbsf-controls/images/mic.svg'\" (click)=\"startSpeechRecognition()\"\r\n (keydown)=\"onMicKeydown($event, 'start')\" (focus)=\"onMicFocus(true)\" (blur)=\"onMicFocus(false)\"\r\n *ngIf=\"options.enableSpeechRecognition && !isMicOn\"\r\n [attr.aria-label]=\"utilityService.getResourceValue('StartSpeechRecognition')\" [ngbTooltip]=\"utilityService.getResourceValue('StartSpeechRecognition')\" tabindex=\"0\"\r\n [attr.aria-pressed]=\"false\">\r\n </button>\r\n\r\n <!-- Stop Speech Recognition Button -->\r\n <button type=\"button\" class=\"svg-icon svg-icon-5 speech-control-btn\" [class.focus-visible]=\"isMicFocusVisible\"\r\n [inlineSVG]=\"options.iconMicOff || 'assets/bbsf-controls/images/mic-off.svg'\"\r\n (click)=\"stopSpeechRecognition()\" (keydown)=\"onMicKeydown($event, 'stop')\"\r\n (focus)=\"onMicFocus(true)\" (blur)=\"onMicFocus(false)\"\r\n *ngIf=\"options.enableSpeechRecognition && isMicOn\" [attr.aria-label]=\"utilityService.getResourceValue('StopSpeechRecognition')\"\r\n [ngbTooltip]=\"utilityService.getResourceValue('StopSpeechRecognition')\" tabindex=\"0\" [attr.aria-pressed]=\"true\">\r\n </button>\r\n\r\n <div class=\"language-controls\" [class.focus-visible]=\"isLanguageSelectFocusVisible\">\r\n <span class=\"language-text\" [attr.id]=\"options.name + '-language-display'\"\r\n aria-live=\"polite\">{{ options.enableSpeechRecognition ? selectedSpeechLanguageDisplayText : '' }}</span>\r\n\r\n <label [for]=\"'Language_'+options.name\" class=\"sr-only\">\r\n Select speech recognition language\r\n </label>\r\n <select class=\"language-select\" [formControlName]=\"'Language_'+options.name\" [id]=\"'Language_'+options.name\"\r\n (change)=\"onSpeechLanguageChange($event)\" (focus)=\"onLanguageSelectFocus(true)\"\r\n (blur)=\"onLanguageSelectFocus(false)\" (keydown)=\"onLanguageSelectKeydown($event)\"\r\n [attr.aria-describedby]=\"options.name + '-language-display'\" [attr.aria-label]=\"utilityService.getResourceValue('SelectSpeechRecognitionLanguage')\"\r\n [ngbTooltip]=\"utilityService.getResourceValue('SelectSpeechRecognitionLanguage')\"\r\n triggers=\"focus:blur\">\r\n <option *ngFor=\"let language of options.speechLanguages\" [value]=\"language.dialect\">\r\n {{language.name}}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n </div>\r\n <!-- readonly -->\r\n <div *ngIf=\"options.isReadonly\"><span class=\"readonly-view\">{{options.value}}</span>\r\n </div>\r\n <div class=\"subtext-container\">\r\n <!--wordCount-->\r\n <div class=\"bbsf-word-count\" *ngIf=\"options.maxWordCount>0&&isShowWordCount\" [attr.id]=\"wordCountId\"\r\n aria-live=\"polite\" [attr.aria-label]=\"'Word count: ' + wordCount + ' of ' + options.maxWordCount + ' words'\">\r\n {{wordCount}}/{{options.maxWordCount}} Words\r\n </div>\r\n\r\n <!-- CharsLimitMsg-->\r\n <div class=\"bbsf-character-count\" *ngIf=\"showCharsLimitMsg\" [attr.id]=\"characterCountId\" aria-live=\"polite\"\r\n [attr.aria-atomic]=\"true\"\r\n [ngClass]=\"{'badge-light-warning': charsLimitMsgClass === 'warning', 'badge-light-danger' : charsLimitMsgClass === 'danger' }\">\r\n {{maxLimitWarningMsg}}\r\n </div>\r\n\r\n <!-- LabelDescription-->\r\n <div class=\"bbsf-control-desc\" *ngIf=\"options.labelDescription!=null\" [attr.id]=\"options.name + '-description'\">\r\n {{options.labelDescription}}\r\n </div>\r\n\r\n <!-- requiredText-->\r\n <div class=\"bbsf-validation\" [dir]=\"textDir\" *ngIf=\"(textAreaFormControl.invalid && textAreaFormControl.touched)\"\r\n [attr.id]=\"errorMessageId\" role=\"alert\" aria-live=\"assertive\" [attr.aria-atomic]=\"true\">\r\n {{getErrorValidation(textAreaFormControl.errors|keyvalue)}}\r\n </div>\r\n </div>\r\n <div *ngIf=\"(group.valid&&group.dirty&&group.touched )||(group.untouched&&group.invalid&&group.dirty) \">\r\n {{resetError()}}</div>\r\n </div>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i5.KeyValuePipe, name: "keyvalue" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: NgbModule }, { kind: "directive", type: i6.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "ngmodule", type: InlineSVGModule }, { kind: "directive", type: i7.InlineSVGDirective, selector: "[inlineSVG]", inputs: ["inlineSVG", "resolveSVGUrl", "replaceContents", "prepend", "injectComponent", "cacheSVG", "setSVGAttributes", "removeSVGAttributes", "forceEvalStyles", "evalScripts", "fallbackImgUrl", "fallbackSVG", "onSVGLoaded"], outputs: ["onSVGInserted", "onSVGFailed"] }] }); }
|
|
558
|
-
}
|
|
559
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextAreaComponent, decorators: [{
|
|
560
|
-
type: Component,
|
|
561
|
-
args: [{ selector: 'BBSF-TextArea', standalone: true, imports: [
|
|
562
|
-
CommonModule,
|
|
563
|
-
FormsModule,
|
|
564
|
-
ReactiveFormsModule,
|
|
565
|
-
NgbModule,
|
|
566
|
-
InlineSVGModule
|
|
567
|
-
], template: "<div class=\"form-group bbsf-control bbsf-textarea\" [formGroup]=\"group\">\r\n <div [ngClass]=\"(options.viewType==1)?'bbsf-vertical':'bbsf-horizontal'\">\r\n <!--label-->\r\n <label *ngIf=\"!options.hideLabel\" class=\"bbsf-label {{options.labelExtraClasses}}\">\r\n {{options.labelValue}}\r\n <!--Asterisk-->\r\n <span *ngIf=\"((options.showAsterisk&&options.isRequired)||(options.isRequired))&&!options.isReadonly\"\r\n class=\"text-danger\">*</span>\r\n </label>\r\n <div *ngIf=\"!options.isReadonly\" class=\"bbsf-input-container\" [ngClass]=\"{\r\n 'p-120px': options.enableSpeechRecognition && options.enableCopyToClipboard,\r\n 'p-80px': options.enableSpeechRecognition && !options.enableCopyToClipboard,\r\n 'p-40px': !options.enableSpeechRecognition && options.enableCopyToClipboard\r\n }\">\r\n <!--input-->\r\n <textarea class=\"form-control {{options.extraClasses}}\" (focus)=\"onFocus(true)\" (focusout)=\"onFocus(false)\"\r\n [dir]=\"textDir\" [attr.aria-invalid]=\"textAreaFormControl.invalid && textAreaFormControl.touched\"\r\n [attr.aria-describedby]=\"ariaDescribedBy\" [attr.aria-label]=\"options.labelValue || options.placeholder\"\r\n formControlName=\"{{options.name}}\"\r\n [class.is-invalid]=\"textAreaFormControl.invalid && textAreaFormControl.touched\"\r\n placeholder=\"{{options.placeholder}}\" id=\"{{options.name}}\" autocomplete=\"{{options.autoComplete}}\"\r\n (change)=\"trimControlValue()\" rows=\"{{options.rows}}\" (keyup)=\"onTextChange()\" cols=\"{{options.cols}}\"\r\n [attr.minlength]=\"options.minLength\" [(ngModel)]=\"options.value\" (keydown)=\"onKeyDown($event)\"\r\n [attr.maxlength]=\"options.maxLength\" role=\"textbox\" [attr.aria-multiline]=\"true\" #TextAreainput></textarea>\r\n <!--CopyToClipboard-->\r\n <button type=\"button\" class=\"copy-clipboard\" *ngIf=\"options.enableCopyToClipboard\"\r\n (click)=\"copyInputMessage(TextAreainput)\" (keydown)=\"onCopyKeydown($event, TextAreainput)\"\r\n [attr.aria-label]=\"utilityService.getResourceValue('CopyTextToClipboard')\" [ngbTooltip]=\"utilityService.getResourceValue('CopyTextToClipboard')\" tabindex=\"0\">\r\n <i class=\"fas fa-copy\" aria-hidden=\"true\"></i>\r\n </button>\r\n <div [ngClass]=\"{'expanded': isFocused}\" class=\"language-container {{options.extraClassMicLanguage}}\"\r\n *ngIf=\"options.enableSpeechRecognition\" role=\"region\">\r\n\r\n <!-- Start Speech Recognition Button -->\r\n <button type=\"button\" class=\"svg-icon svg-icon-5 speech-control-btn\" [class.focus-visible]=\"isMicFocusVisible\"\r\n [inlineSVG]=\"options.iconMic || 'assets/bbsf-controls/images/mic.svg'\" (click)=\"startSpeechRecognition()\"\r\n (keydown)=\"onMicKeydown($event, 'start')\" (focus)=\"onMicFocus(true)\" (blur)=\"onMicFocus(false)\"\r\n *ngIf=\"options.enableSpeechRecognition && !isMicOn\"\r\n [attr.aria-label]=\"utilityService.getResourceValue('StartSpeechRecognition')\" [ngbTooltip]=\"utilityService.getResourceValue('StartSpeechRecognition')\" tabindex=\"0\"\r\n [attr.aria-pressed]=\"false\">\r\n </button>\r\n\r\n <!-- Stop Speech Recognition Button -->\r\n <button type=\"button\" class=\"svg-icon svg-icon-5 speech-control-btn\" [class.focus-visible]=\"isMicFocusVisible\"\r\n [inlineSVG]=\"options.iconMicOff || 'assets/bbsf-controls/images/mic-off.svg'\"\r\n (click)=\"stopSpeechRecognition()\" (keydown)=\"onMicKeydown($event, 'stop')\"\r\n (focus)=\"onMicFocus(true)\" (blur)=\"onMicFocus(false)\"\r\n *ngIf=\"options.enableSpeechRecognition && isMicOn\" [attr.aria-label]=\"utilityService.getResourceValue('StopSpeechRecognition')\"\r\n [ngbTooltip]=\"utilityService.getResourceValue('StopSpeechRecognition')\" tabindex=\"0\" [attr.aria-pressed]=\"true\">\r\n </button>\r\n\r\n <div class=\"language-controls\" [class.focus-visible]=\"isLanguageSelectFocusVisible\">\r\n <span class=\"language-text\" [attr.id]=\"options.name + '-language-display'\"\r\n aria-live=\"polite\">{{ options.enableSpeechRecognition ? selectedSpeechLanguageDisplayText : '' }}</span>\r\n\r\n <label [for]=\"'Language_'+options.name\" class=\"sr-only\">\r\n Select speech recognition language\r\n </label>\r\n <select class=\"language-select\" [formControlName]=\"'Language_'+options.name\" [id]=\"'Language_'+options.name\"\r\n (change)=\"onSpeechLanguageChange($event)\" (focus)=\"onLanguageSelectFocus(true)\"\r\n (blur)=\"onLanguageSelectFocus(false)\" (keydown)=\"onLanguageSelectKeydown($event)\"\r\n [attr.aria-describedby]=\"options.name + '-language-display'\" [attr.aria-label]=\"utilityService.getResourceValue('SelectSpeechRecognitionLanguage')\"\r\n [ngbTooltip]=\"utilityService.getResourceValue('SelectSpeechRecognitionLanguage')\"\r\n triggers=\"focus:blur\">\r\n <option *ngFor=\"let language of options.speechLanguages\" [value]=\"language.dialect\">\r\n {{language.name}}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n </div>\r\n <!-- readonly -->\r\n <div *ngIf=\"options.isReadonly\"><span class=\"readonly-view\">{{options.value}}</span>\r\n </div>\r\n <div class=\"subtext-container\">\r\n <!--wordCount-->\r\n <div class=\"bbsf-word-count\" *ngIf=\"options.maxWordCount>0&&isShowWordCount\" [attr.id]=\"wordCountId\"\r\n aria-live=\"polite\" [attr.aria-label]=\"'Word count: ' + wordCount + ' of ' + options.maxWordCount + ' words'\">\r\n {{wordCount}}/{{options.maxWordCount}} Words\r\n </div>\r\n\r\n <!-- CharsLimitMsg-->\r\n <div class=\"bbsf-character-count\" *ngIf=\"showCharsLimitMsg\" [attr.id]=\"characterCountId\" aria-live=\"polite\"\r\n [attr.aria-atomic]=\"true\"\r\n [ngClass]=\"{'badge-light-warning': charsLimitMsgClass === 'warning', 'badge-light-danger' : charsLimitMsgClass === 'danger' }\">\r\n {{maxLimitWarningMsg}}\r\n </div>\r\n\r\n <!-- LabelDescription-->\r\n <div class=\"bbsf-control-desc\" *ngIf=\"options.labelDescription!=null\" [attr.id]=\"options.name + '-description'\">\r\n {{options.labelDescription}}\r\n </div>\r\n\r\n <!-- requiredText-->\r\n <div class=\"bbsf-validation\" [dir]=\"textDir\" *ngIf=\"(textAreaFormControl.invalid && textAreaFormControl.touched)\"\r\n [attr.id]=\"errorMessageId\" role=\"alert\" aria-live=\"assertive\" [attr.aria-atomic]=\"true\">\r\n {{getErrorValidation(textAreaFormControl.errors|keyvalue)}}\r\n </div>\r\n </div>\r\n <div *ngIf=\"(group.valid&&group.dirty&&group.touched )||(group.untouched&&group.invalid&&group.dirty) \">\r\n {{resetError()}}</div>\r\n </div>" }]
|
|
568
|
-
}], ctorParameters: () => [{ type: i1.ControlUtility }, { type: i2.ControlContainer, decorators: [{
|
|
569
|
-
type: Optional
|
|
570
|
-
}, {
|
|
571
|
-
type: SkipSelf
|
|
572
|
-
}] }, { type: i2.FormGroupDirective, decorators: [{
|
|
573
|
-
type: Optional
|
|
574
|
-
}] }, { type: i3.UtilityService }, { type: i3.ControlValidationService }, { type: i1.GlobalSettings }, { type: i3.SpeechRecognitionService }, { type: i4.LanguageService }], propDecorators: { group: [{
|
|
575
|
-
type: Input
|
|
576
|
-
}], options: [{
|
|
577
|
-
type: Input
|
|
578
|
-
}], onChange: [{
|
|
579
|
-
type: Output
|
|
580
|
-
}] } });
|
|
581
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVGV4dEFyZWEuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYmJzZi1jb250cm9scy9zcmMvbGliL2NvbnRyb2xzL1RleHRBcmVhL1RleHRBcmVhLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Jic2YtY29udHJvbHMvc3JjL2xpYi9jb250cm9scy9UZXh0QXJlYS9UZXh0QXJlYS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFxQixLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzlHLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBb0UsV0FBVyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFJN0osT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7Ozs7O0FBZ0JsRCxNQUFNLE9BQU8saUJBQWlCO0lBQzVCLFlBQ1UsY0FBOEIsRUFDTixnQkFBa0MsRUFDL0MsbUJBQXVDLEVBQ25ELGNBQThCLEVBQzdCLHdCQUFrRCxFQUNsRCxjQUE4QixFQUM5Qix3QkFBa0QsRUFDbEQsZUFBZ0M7UUFQaEMsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBQ04scUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUMvQyx3QkFBbUIsR0FBbkIsbUJBQW1CLENBQW9CO1FBQ25ELG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUM3Qiw2QkFBd0IsR0FBeEIsd0JBQXdCLENBQTBCO1FBQ2xELG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUM5Qiw2QkFB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QUFDLElBQUksQ0FBQztRQUM1RCxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQ2pELElBQUksU0FBUyxFQUFFO1lBQ2IsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQ2pCO2FBQU07WUFDTCxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDbEI7SUFDSCxDQUFDOytHQXBvQlUsaUJBQWlCO21HQUFqQixpQkFBaUIsNEpDdkI5QixvMU5BcUdRLDJDRHJGSixZQUFZLHdaQUNaLFdBQVcsNjhCQUNYLG1CQUFtQiwrVUFDbkIsU0FBUyxzV0FDVCxlQUFlOzs0RkFHTixpQkFBaUI7a0JBWjdCLFNBQVM7K0JBQ0UsZUFBZSxjQUViLElBQUksV0FDUDt3QkFDUCxZQUFZO3dCQUNaLFdBQVc7d0JBQ1gsbUJBQW1CO3dCQUNuQixTQUFTO3dCQUNULGVBQWU7cUJBQ2hCOzswQkFLRSxRQUFROzswQkFBSSxRQUFROzswQkFDcEIsUUFBUTsrTUFTRixLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csT0FBTztzQkFBZixLQUFLO2dCQUNJLFFBQVE7c0JBQWpCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgT25EZXN0cm95LCBJbnB1dCwgT3B0aW9uYWwsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBTa2lwU2VsZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBGb3JtQ29udHJvbCwgVmFsaWRhdG9ycywgRm9ybUdyb3VwLCBBYnN0cmFjdENvbnRyb2wsIENvbnRyb2xDb250YWluZXIsIEZvcm1Hcm91cERpcmVjdGl2ZSwgRm9ybXNNb2R1bGUsIFJlYWN0aXZlRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IExhbmd1YWdlU2VydmljZSB9IGZyb20gJ0BibnNpZ2h0cy9iYnNmLXV0aWxpdGllcy90cmFuc2xhdGUnO1xyXG5pbXBvcnQgeyBDb250cm9sVmFsaWRhdGlvblNlcnZpY2UsIFV0aWxpdHlTZXJ2aWNlLCBTcGVlY2hSZWNvZ25pdGlvblNlcnZpY2UgfSBmcm9tICdAYm5zaWdodHMvYmJzZi11dGlsaXRpZXMvdWknO1xyXG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgTmdiTW9kdWxlIH0gZnJvbSAnQG5nLWJvb3RzdHJhcC9uZy1ib290c3RyYXAnO1xyXG5pbXBvcnQgeyBJbmxpbmVTVkdNb2R1bGUgfSBmcm9tICduZy1pbmxpbmUtc3ZnLTInO1xyXG5pbXBvcnQgeyBDb250cm9sVXRpbGl0eSwgR2xvYmFsU2V0dGluZ3MgfSBmcm9tICcuLi8uLi9TaGFyZWQvc2VydmljZXMnO1xyXG5pbXBvcnQgeyBUZXh0QXJlYU9wdGlvbnMgfSBmcm9tICcuLi8uLi9TaGFyZWQvTW9kZWxzJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnQkJTRi1UZXh0QXJlYScsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL1RleHRBcmVhLmNvbXBvbmVudC5odG1sJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtcclxuICAgIENvbW1vbk1vZHVsZSxcclxuICAgIEZvcm1zTW9kdWxlLFxyXG4gICAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcclxuICAgIE5nYk1vZHVsZSxcclxuICAgIElubGluZVNWR01vZHVsZVxyXG4gIF1cclxufSlcclxuZXhwb3J0IGNsYXNzIFRleHRBcmVhQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBjb250cm9sVXRpbGl0eTogQ29udHJvbFV0aWxpdHksXHJcbiAgICBAT3B0aW9uYWwoKSBAU2tpcFNlbGYoKSBwcml2YXRlIGNvbnRyb2xDb250YWluZXI6IENvbnRyb2xDb250YWluZXIsXHJcbiAgICBAT3B0aW9uYWwoKSBwdWJsaWMgdGV4dEFyZWFDb250cm9sSG9zdDogRm9ybUdyb3VwRGlyZWN0aXZlLFxyXG4gICAgcHVibGljIHV0aWxpdHlTZXJ2aWNlOiBVdGlsaXR5U2VydmljZSxcclxuICAgIHByaXZhdGUgY29udHJvbFZhbGlkYXRpb25TZXJ2aWNlOiBDb250cm9sVmFsaWRhdGlvblNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGdsb2JhbFNldHRpbmdzOiBHbG9iYWxTZXR0aW5ncyxcclxuICAgIHByaXZhdGUgc3BlZWNoUmVjb2duaXRpb25TZXJ2aWNlOiBTcGVlY2hSZWNvZ25pdGlvblNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGxhbmd1YWdlU2VydmljZTogTGFuZ3VhZ2VTZXJ2aWNlXHJcbiAgKSB7XHJcbiAgICB0aGlzLmN1cnJlbnRMYW5ndWFnZSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdsYW5ndWFnZScpO1xyXG4gIH1cclxuICBASW5wdXQoKSBncm91cDogRm9ybUdyb3VwO1xyXG4gIEBJbnB1dCgpIG9wdGlvbnM6IFRleHRBcmVhT3B0aW9ucztcclxuICBAT3V0cHV0KCkgb25DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcblxyXG4gIHRleHRBcmVhRm9ybUNvbnRyb2w6IEFic3RyYWN0Q29udHJvbDtcclxuICB3b3JkQ291bnQ6IG51bWJlciA9IDA7XHJcbiAgd29yZENvdW50QXJyYXk6IG51bWJlciA9IDA7XHJcbiAgaXNTaG93V29yZENvdW50OiBib29sZWFuID0gZmFsc2U7XHJcbiAgbWFya0FsbEFzVG91Y2hlZDogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIHZhbGlkYXRpb25SdWxlcyA9IFtdO1xyXG4gIHZhbGlkYXRpb25SdWxlc2FzeW5jID0gW107XHJcbiAgLy9Gb3IgU2hvdyB3YXJuaW5nIG1lc3NhZ2Ugb2YgbWF4IGxlbmd0aCBsaW1pdFxyXG4gIGN1cnJlbnRDaGFyc0NvdW50OiBudW1iZXIgPSAwO1xyXG4gIHNob3dDaGFyc0xpbWl0TXNnOiBib29sZWFuID0gZmFsc2U7XHJcbiAgaGFzQ2hhcnNMaW1pdFZhbGlkYXRpb25FcnJvcjogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIGNoYXJzTGltaXRNc2dDbGFzczogc3RyaW5nO1xyXG4gIG1pbkNoYXJzTGltaXQ6IG51bWJlciA9IC0xOyAvL1RvIGRpc2FibGUgY2hhcnMgbGltaXQgZmVhdHVyZSBieSBkZWZhdWx0XHJcbiAgbWF4TGltaXRXYXJuaW5nTXNnOiBzdHJpbmcgPSAnJztcclxuICBpc01pY09uOiBib29sZWFuID0gZmFsc2U7XHJcbiAgcHVibGljIHRleHREaXI7XHJcbiAgaXNGb2N1c2VkOiBib29sZWFuO1xyXG4gIGN1cnJlbnRMYW5ndWFnZTogU3RyaW5nO1xyXG4gIHN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xyXG4gIHZhbHVlQ2hhbmdlc1N1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xyXG4gIHNlbGVjdGVkU3BlZWNoTGFuZ3VhZ2VEaXNwbGF5VGV4dDogc3RyaW5nID0gJyc7XHJcbiAgaXNMYW5ndWFnZVNlbGVjdEZvY3VzVmlzaWJsZSA9IGZhbHNlO1xyXG4gIGlzTWljRm9jdXNWaXNpYmxlID0gZmFsc2U7XHJcblxyXG4gIC8vIEFjY2Vzc2liaWxpdHkgcHJvcGVydGllc1xyXG4gIGFyaWFEZXNjcmliZWRCeTogc3RyaW5nID0gJyc7XHJcbiAgZXJyb3JNZXNzYWdlSWQ6IHN0cmluZyA9ICcnO1xyXG4gIGNoYXJhY3RlckNvdW50SWQ6IHN0cmluZyA9ICcnO1xyXG4gIHdvcmRDb3VudElkOiBzdHJpbmcgPSAnJztcclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICAvLyBJbml0aWFsaXplIGFjY2Vzc2liaWxpdHkgSURzXHJcbiAgICB0aGlzLmVycm9yTWVzc2FnZUlkID0gYCR7dGhpcy5vcHRpb25zLm5hbWV9LWVycm9yYDtcclxuICAgIHRoaXMuY2hhcmFjdGVyQ291bnRJZCA9IGAke3RoaXMub3B0aW9ucy5uYW1lfS1jaGFyLWNvdW50YDtcclxuICAgIHRoaXMud29yZENvdW50SWQgPSBgJHt0aGlzLm9wdGlvbnMubmFtZX0td29yZC1jb3VudGA7XHJcbiAgICB0aGlzLnVwZGF0ZUFyaWFEZXNjcmliZWRCeSgpO1xyXG5cclxuICAgIC8vIEluaXRpYWxpemUgc3BlZWNoIHJlY29nbml0aW9uIHByb3BlcnRpZXMgb25seSBpZiBlbmFibGVkXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmVuYWJsZVNwZWVjaFJlY29nbml0aW9uKSB7XHJcbiAgICAgIHRoaXMuaXNNaWNPbiA9IGZhbHNlO1xyXG4gICAgICB0aGlzLnNlbGVjdGVkU3BlZWNoTGFuZ3VhZ2VEaXNwbGF5VGV4dCA9ICcnO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gUmVzZXQgc3BlZWNoLXJlbGF0ZWQgcHJvcGVydGllcyB3aGVuIGRpc2FibGVkXHJcbiAgICAgIHRoaXMucmVzZXRTcGVlY2hQcm9wZXJ0aWVzKCk7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmlzUmVhZG9ubHkgJiYgIXRoaXMub3B0aW9ucy52YWx1ZSlcclxuICAgICAgdGhpcy5vcHRpb25zLnZhbHVlID0gdGhpcy51dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdOQScpO1xyXG5cclxuICAgIGlmICh0aGlzLm9wdGlvbnMuZm9yY2VEaXJlY3Rpb24pXHJcbiAgICAgIHRoaXMudGV4dERpciA9IHRoaXMub3B0aW9ucy5mb3JjZURpcmVjdGlvbiA9PSAyID8gJ3J0bCcgOiAnbHRyJztcclxuICAgIGVsc2UgdGhpcy50ZXh0RGlyID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2xhbmd1YWdlJykgPT0gJ2FyJyA/ICdydGwnIDogJ2x0cic7XHJcblxyXG4gICAgdGhpcy5jb250cm9sVmFsaWRhdGlvblNlcnZpY2UuaXNDcmVhdGVkQmVmb3IgPSBmYWxzZTtcclxuXHJcbiAgICB0aGlzLmdyb3VwLmFkZENvbnRyb2wodGhpcy5vcHRpb25zLm5hbWUsIG5ldyBGb3JtQ29udHJvbCgnJykpO1xyXG4gICAgdGhpcy50ZXh0QXJlYUZvcm1Db250cm9sID0gdGhpcy5ncm91cC5jb250cm9sc1t0aGlzLm9wdGlvbnMubmFtZV07IC8vICBuZXcgRm9ybUNvbnRyb2woJycsdmFsaWRhdGlvblJ1bGVzKTtcclxuXHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5tYXhMZW5ndGgpIHRoaXMub3B0aW9ucy5tYXhMZW5ndGggPSB0aGlzLmdsb2JhbFNldHRpbmdzLm1heExlbmd0aFRleHRBcmVhO1xyXG5cclxuICAgIGlmICghdGhpcy5vcHRpb25zLnZpZXdUeXBlKSB0aGlzLm9wdGlvbnMudmlld1R5cGUgPSB0aGlzLmdsb2JhbFNldHRpbmdzLnZpZXdUeXBlO1xyXG5cclxuICAgIGlmICh0aGlzLm9wdGlvbnMubGFiZWxLZXkgIT0gbnVsbCAmJiB0aGlzLm9wdGlvbnMubGFiZWxLZXkgIT0gJycpXHJcbiAgICAgIHRoaXMub3B0aW9ucy5sYWJlbFZhbHVlID0gdGhpcy51dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKHRoaXMub3B0aW9ucy5sYWJlbEtleSk7XHJcblxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5lbmFibGVTcGVlY2hSZWNvZ25pdGlvbikge1xyXG4gICAgICAvLyBJbml0aWFsaXplIGxhbmd1YWdlIGZvcm0gY29udHJvbFxyXG4gICAgICBjb25zdCBsYW5ndWFnZUNvbnRyb2xOYW1lID0gJ0xhbmd1YWdlXycgKyB0aGlzLm9wdGlvbnMubmFtZTtcclxuICAgICAgdGhpcy5ncm91cC5hZGRDb250cm9sKFxyXG4gICAgICAgIGxhbmd1YWdlQ29udHJvbE5hbWUsXHJcbiAgICAgICAgbmV3IEZvcm1Db250cm9sKHRoaXMub3B0aW9ucy5zZWxlY3RlZFNwZWVjaExhbmd1YWdlIHx8ICcnKVxyXG4gICAgICApO1xyXG4gICAgICAvL0dldCBhbGwgbGFuZ3VhZ2VzIGlmIG5vdCBzZXRcclxuICAgICAgaWYgKCF0aGlzLm9wdGlvbnMuc3BlZWNoTGFuZ3VhZ2VzKSB7XHJcbiAgICAgICAgdGhpcy5sYW5ndWFnZVNlcnZpY2UuZ2V0TGFuZ3VhZ2VzKCkuc3Vic2NyaWJlKChyZXN1bHQpID0+IHtcclxuICAgICAgICAgIHRoaXMub3B0aW9ucy5zcGVlY2hMYW5ndWFnZXMgPSByZXN1bHQ7XHJcbiAgICAgICAgICB0aGlzLnNldFNwZWVjaExhbmd1YWdlKCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hMYW5ndWFnZSgpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICB0aGlzLnRleHRBcmVhRm9ybUNvbnRyb2wuc2V0VmFsdWUodGhpcy5vcHRpb25zLnZhbHVlKTtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMuY3VzdG9tVmFsaWRhdGlvbi5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGxldCBWYWxpZGF0aW9ucyA9IHRoaXMub3B0aW9ucy5jdXN0b21WYWxpZGF0aW9uO1xyXG4gICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgVmFsaWRhdGlvbnMubGVuZ3RoOyBpbmRleCsrKSB7XHJcbiAgICAgICAgY29uc3QgVmFsaWRhdGlvbiA9IFZhbGlkYXRpb25zW2luZGV4XTtcclxuICAgICAgICB0aGlzLnZhbGlkYXRpb25SdWxlcy5wdXNoKFZhbGlkYXRpb24uZnVuY3Rpb25Cb2R5KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5taW5MZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMudmFsaWRhdGlvblJ1bGVzLnB1c2goVmFsaWRhdG9ycy5taW5MZW5ndGgodGhpcy5vcHRpb25zLm1pbkxlbmd0aCkpO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5tYXhMZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMudmFsaWRhdGlvblJ1bGVzLnB1c2goVmFsaWRhdG9ycy5tYXhMZW5ndGgodGhpcy5vcHRpb25zLm1heExlbmd0aCkpO1xyXG5cclxuICAgICAgaWYgKCF0aGlzLm9wdGlvbnMubWF4TGVuZ3RoV2FybmluZ0xpbWl0KVxyXG4gICAgICAgIHRoaXMub3B0aW9ucy5tYXhMZW5ndGhXYXJuaW5nTGltaXQgPSB0aGlzLmdsb2JhbFNldHRpbmdzLm1heExlbmd0aFdhcm5pbmdMaW1pdDtcclxuXHJcbiAgICAgIHRoaXMubWluQ2hhcnNMaW1pdCA9IHRoaXMub3B0aW9ucy5tYXhMZW5ndGggLSB0aGlzLm9wdGlvbnMubWF4TGVuZ3RoV2FybmluZ0xpbWl0O1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pc1JlcXVpcmVkKSB7XHJcbiAgICAgIHRoaXMudmFsaWRhdGlvblJ1bGVzLnB1c2goVmFsaWRhdG9ycy5yZXF1aXJlZCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLnRleHRBcmVhRm9ybUNvbnRyb2wuc2V0VmFsaWRhdG9ycyh0aGlzLnZhbGlkYXRpb25SdWxlcyk7XHJcbiAgICB0aGlzLnRleHRBcmVhRm9ybUNvbnRyb2wuc2V0QXN5bmNWYWxpZGF0b3JzKHRoaXMudmFsaWRhdGlvblJ1bGVzYXN5bmMpO1xyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pc0Rpc2FibGVkKSB7XHJcbiAgICAgIHRoaXMudGV4dEFyZWFGb3JtQ29udHJvbC5kaXNhYmxlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gT25seSBzdWJzY3JpYmUgdG8gbmdTdWJtaXQgaWYgRm9ybUdyb3VwRGlyZWN0aXZlIGlzIGF2YWlsYWJsZVxyXG4gICAgaWYgKHRoaXMudGV4dEFyZWFDb250cm9sSG9zdCkge1xyXG4gICAgICB0aGlzLnRleHRBcmVhQ29udHJvbEhvc3QubmdTdWJtaXQuc3Vic2NyaWJlKCh2YWx1ZSkgPT4ge1xyXG4gICAgICAgIHRoaXMuZ3JvdXAubWFya0FsbEFzVG91Y2hlZCgpO1xyXG4gICAgICAgIHRoaXMubWFya0FsbEFzVG91Y2hlZCA9IHRydWU7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFN1YnNjcmliZSB0byB2YWx1ZSBjaGFuZ2VzIHRvIGVuc3VyZSB3YXJuaW5nIG1lc3NhZ2VzIGFyZSBwcm9wZXJseSByZXNldFxyXG4gICAgdGhpcy52YWx1ZUNoYW5nZXNTdWJzY3JpcHRpb24gPSB0aGlzLnRleHRBcmVhRm9ybUNvbnRyb2wudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSgodmFsdWUpID0+IHtcclxuICAgICAgLy8gUmVzZXQgd2FybmluZyBtZXNzYWdlIHdoZW4gY29udHJvbCBpcyBlbXB0eSBvciBudWxsXHJcbiAgICAgIGlmICghdmFsdWUgfHwgdmFsdWUudHJpbSgpLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgIHRoaXMuc2hvd0NoYXJzTGltaXRNc2cgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLmhhc0NoYXJzTGltaXRWYWxpZGF0aW9uRXJyb3IgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLm1heExpbWl0V2FybmluZ01zZyA9ICcnO1xyXG4gICAgICAgIHRoaXMuY3VycmVudENoYXJzQ291bnQgPSAwO1xyXG4gICAgICAgIHRoaXMud29yZENvdW50ID0gMDtcclxuICAgICAgICB0aGlzLndvcmRDb3VudEFycmF5ID0gMDtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XHJcbiAgICB0aGlzLmNvbnRyb2xVdGlsaXR5LnNldEF0dHJpYnV0ZUZvckNvbnRyb2wodGhpcy5vcHRpb25zKTtcclxuICB9XHJcblxyXG4gIHJlc2V0RXJyb3IgPSAoKSA9PiB7XHJcbiAgICB0aGlzLmNvbnRyb2xWYWxpZGF0aW9uU2VydmljZS5yZW1vdmVHbG9iYWxFcnJvcigpO1xyXG4gIH07XHJcblxyXG4gIHNob3dHbG9iYWxFcnJvcigpIHtcclxuICAgIHRoaXMuY29udHJvbFV0aWxpdHkuc2hvd0dsb2JhbEVycm9yKCk7XHJcbiAgfVxyXG5cclxuICBnZXRFcnJvclZhbGlkYXRpb24oRXJyb3JMaXN0KSB7XHJcbiAgICBpZiAodGhpcy5tYXJrQWxsQXNUb3VjaGVkICYmIHRoaXMuZ3JvdXAuaW52YWxpZCkge1xyXG4gICAgICB0aGlzLnNob3dHbG9iYWxFcnJvcigpO1xyXG4gICAgICB0aGlzLm1hcmtBbGxBc1RvdWNoZWQgPSBmYWxzZTtcclxuICAgIH1cclxuICAgIHJldHVybiB0aGlzLmNvbnRyb2xVdGlsaXR5LmdldEVycm9yVmFsaWRhdGlvbk1hc3NhZ2UoRXJyb3JMaXN0LCB0aGlzLmdyb3VwLCB0aGlzLm9wdGlvbnMpO1xyXG4gIH1cclxuICBnZXRJbnB1dFR5cGUodHlwZTogbnVtYmVyKSB7XHJcbiAgICByZXR1cm4gdGhpcy5jb250cm9sVXRpbGl0eS5nZXRJbnB1dFR5cGUodHlwZSk7XHJcbiAgfVxyXG5cclxuICAvLyBBY2Nlc3NpYmlsaXR5IGhlbHBlciBtZXRob2RzXHJcbiAgdXBkYXRlQXJpYURlc2NyaWJlZEJ5KCkge1xyXG4gICAgY29uc3QgZGVzY3JpYmVkQnlJZHMgPSBbXTtcclxuXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmxhYmVsRGVzY3JpcHRpb24pIHtcclxuICAgICAgZGVzY3JpYmVkQnlJZHMucHVzaChgJHt0aGlzLm9wdGlvbnMubmFtZX0tZGVzY3JpcHRpb25gKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLm1heFdvcmRDb3VudCA+IDApIHtcclxuICAgICAgZGVzY3JpYmVkQnlJZHMucHVzaCh0aGlzLndvcmRDb3VudElkKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5zaG93Q2hhcnNMaW1pdE1zZykge1xyXG4gICAgICBkZXNjcmliZWRCeUlkcy5wdXNoKHRoaXMuY2hhcmFjdGVyQ291bnRJZCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMudGV4dEFyZWFGb3JtQ29udHJvbD8uaW52YWxpZCAmJiB0aGlzLnRleHRBcmVhRm9ybUNvbnRyb2w/LnRvdWNoZWQpIHtcclxuICAgICAgZGVzY3JpYmVkQnlJZHMucHVzaCh0aGlzLmVycm9yTWVzc2FnZUlkKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBPbmx5IGFkZCBzcGVlY2gtcmVsYXRlZCBkZXNjcmlwdGlvbnMgaWYgc3BlZWNoIHJlY29nbml0aW9uIGlzIGVuYWJsZWRcclxuICAgIGlmICh0aGlzLm9wdGlvbnMuZW5hYmxlU3BlZWNoUmVjb2duaXRpb24gJiYgdGhpcy5zZWxlY3RlZFNwZWVjaExhbmd1YWdlRGlzcGxheVRleHQpIHtcclxuICAgICAgZGVzY3JpYmVkQnlJZHMucHVzaChgJHt0aGlzLm9wdGlvbnMubmFtZX0tbGFuZ3VhZ2UtZGlzcGxheWApO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuYXJpYURlc2NyaWJlZEJ5ID0gZGVzY3JpYmVkQnlJZHMuam9pbignICcpO1xyXG4gIH1cclxuXHJcbiAgYW5ub3VuY2VUb1NjcmVlblJlYWRlcihtZXNzYWdlOiBzdHJpbmcpIHtcclxuICAgIC8vIENyZWF0ZSB0ZW1wb3JhcnkgZWxlbWVudCBmb3Igc2NyZWVuIHJlYWRlciBhbm5vdW5jZW1lbnRcclxuICAgIGNvbnN0IGFubm91bmNlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG4gICAgYW5ub3VuY2VtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1saXZlJywgJ3BvbGl0ZScpO1xyXG4gICAgYW5ub3VuY2VtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1hdG9taWMnLCAndHJ1ZScpO1xyXG4gICAgYW5ub3VuY2VtZW50LmNsYXNzTmFtZSA9ICdzci1vbmx5JztcclxuICAgIGFubm91bmNlbWVudC50ZXh0Q29udGVudCA9IG1lc3NhZ2U7XHJcblxyXG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhbm5vdW5jZW1lbnQpO1xyXG5cclxuICAgIC8vIFJlbW92ZSBhZnRlciBhbm5vdW5jZW1lbnRcclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGFubm91bmNlbWVudCk7XHJcbiAgICB9LCAxMDAwKTtcclxuICB9XHJcblxyXG4gIHJlc2V0U3BlZWNoUHJvcGVydGllcygpIHtcclxuICAgIC8vIFJlc2V0IGFsbCBzcGVlY2gtcmVsYXRlZCBwcm9wZXJ0aWVzIHdoZW4gc3BlZWNoIHJlY29nbml0aW9uIGlzIGRpc2FibGVkXHJcbiAgICB0aGlzLmlzTWljT24gPSBmYWxzZTtcclxuICAgIHRoaXMuc2VsZWN0ZWRTcGVlY2hMYW5ndWFnZURpc3BsYXlUZXh0ID0gJyc7XHJcblxyXG4gICAgLy8gQ2xlYW4gdXAgYW55IGFjdGl2ZSBzcGVlY2ggcmVjb2duaXRpb24gc3Vic2NyaXB0aW9uc1xyXG4gICAgaWYgKHRoaXMuc3Vic2NyaXB0aW9uKSB7XHJcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XHJcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9uID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZW1vdmUgc3BlZWNoIGxhbmd1YWdlIGZvcm0gY29udHJvbCBpZiBpdCBleGlzdHNcclxuICAgIGNvbnN0IGxhbmd1YWdlQ29udHJvbE5hbWUgPSAnTGFuZ3VhZ2VfJyArIHRoaXMub3B0aW9ucy5uYW1lO1xyXG4gICAgaWYgKHRoaXMuZ3JvdXA/LmdldChsYW5ndWFnZUNvbnRyb2xOYW1lKSkge1xyXG4gICAgICB0aGlzLmdyb3VwLnJlbW92ZUNvbnRyb2wobGFuZ3VhZ2VDb250cm9sTmFtZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB0cmltQ29udHJvbFZhbHVlKCkge1xyXG4gICAgbGV0IG9yaWdpbmFsVmFsdWUgPSB0aGlzLmNvbnRyb2xVdGlsaXR5LnRyaW1Db250cm9sVmFsdWUodGhpcy50ZXh0QXJlYUZvcm1Db250cm9sLnZhbHVlKTtcclxuICAgIHRoaXMudGV4dEFyZWFGb3JtQ29udHJvbC5wYXRjaFZhbHVlKG9yaWdpbmFsVmFsdWUpO1xyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5wYXRjaEZ1bmN0aW9uICYmIHRoaXMub3B0aW9ucy5wYXRjaFBhdGggJiYgdGhpcy50ZXh0QXJlYUZvcm1Db250cm9sLnZhbGlkKSB7XHJcbiAgICAgIHRoaXMuY29udHJvbFV0aWxpdHkucGF0Y2hDb250cm9sVmFsdWUoXHJcbiAgICAgICAgb3JpZ2luYWxWYWx1ZSxcclxuICAgICAgICB0aGlzLm9wdGlvbnMucGF0Y2hGdW5jdGlvbixcclxuICAgICAgICB0aGlzLm9wdGlvbnMucGF0Y2hQYXRoXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBvbktleURvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcclxuICAgIGNvbnN0IHRleHRhcmVhID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxUZXh0QXJlYUVsZW1lbnQ7XHJcbiAgICBjb25zdCBjdXJyZW50VmFsdWUgPSB0ZXh0YXJlYS52YWx1ZSB8fCAnJztcclxuICAgIGNvbnN0IGtleSA9IGV2ZW50LmtleTtcclxuXHJcbiAgICAvLyBBbGxvdyBuYXZpZ2F0aW9uIGtleXMgKGFycm93cywgaG9tZSwgZW5kLCBldGMuKVxyXG4gICAgY29uc3QgYWxsb3dlZEtleXMgPSBbJ0JhY2tzcGFjZScsICdEZWxldGUnLCAnVGFiJywgJ0VzY2FwZScsICdFbnRlcicsICdIb21lJywgJ0VuZCcsICdBcnJvd0xlZnQnLCAnQXJyb3dSaWdodCcsICdBcnJvd1VwJywgJ0Fycm93RG93biddO1xyXG5cclxuICAgIC8vIEFsbG93IEN0cmwvQ21kICsga2V5cyAoY29weSwgcGFzdGUsIHNlbGVjdCBhbGwsIGV0Yy4pXHJcbiAgICBpZiAoZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5KSB7XHJcbiAgICAgIHJldHVybjsgLy8gQWxsb3cgYWxsIEN0cmwvQ21kIGNvbWJpbmF0aW9uc1xyXG4gICAgfVxyXG5cclxuICAgIC8vIElmIGl0J3MgYSBuYXZpZ2F0aW9uIGtleSwgYWxsb3cgaXRcclxuICAgIGlmIChhbGxvd2VkS2V5cy5pbmNsdWRlcyhrZXkpKSB7XHJcbiAgICAgIC8vIFNwZWNpYWwgaGFuZGxpbmcgZm9yIHdvcmQgY291bnQgb24gQmFja3NwYWNlXHJcbiAgICAgIGlmIChrZXkgPT09ICdCYWNrc3BhY2UnICYmIHRoaXMub3B0aW9ucy5tYXhXb3JkQ291bnQgPiAwKSB7XHJcbiAgICAgICAgcmV0dXJuOyAvLyBBbHdheXMgYWxsb3cgYmFja3NwYWNlIGZvciB3b3JkIGNvdW50IGNvcnJlY3Rpb25cclxuICAgICAgfVxyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2hlY2sgd29yZCBjb3VudCBsaW1pdFxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5tYXhXb3JkQ291bnQgPiAwKSB7XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRXb3JkQ291bnQgPSBjdXJyZW50VmFsdWUudHJpbSgpID8gY3VycmVudFZhbHVlLnRyaW0oKS5zcGxpdCgvXFxzKy8pLmxlbmd0aCA6IDA7XHJcbiAgICAgIGlmIChjdXJyZW50V29yZENvdW50ID49IHRoaXMub3B0aW9ucy5tYXhXb3JkQ291bnQgJiYga2V5ICE9PSAnQmFja3NwYWNlJyAmJiBrZXkgIT09ICdEZWxldGUnKSB7XHJcbiAgICAgICAgLy8gQ2hlY2sgaWYgYWRkaW5nIHRoaXMgY2hhcmFjdGVyIHdvdWxkIGNyZWF0ZSBhIG5ldyB3b3JkXHJcbiAgICAgICAgY29uc3QgY3Vyc29yUG9zaXRpb24gPSB0ZXh0YXJlYS5zZWxlY3Rpb25TdGFydDtcclxuICAgICAgICBjb25zdCBjaGFyQmVmb3JlID0gY3Vyc29yUG9zaXRpb24gPiAwID8gY3VycmVudFZhbHVlW2N1cnNvclBvc2l0aW9uIC0gMV0gOiAnJztcclxuICAgICAgICBjb25zdCBjaGFyQWZ0ZXIgPSBjdXJzb3JQb3NpdGlvbiA8IGN1cnJlbnRWYWx1ZS5sZW5ndGggPyBjdXJyZW50VmFsdWVbY3Vyc29yUG9zaXRpb25dIDogJyc7XHJcblxyXG4gICAgICAgIC8vIElmIHdlJ3JlIHR5cGluZyBhIHNwYWNlIG9yIHRoZSBjaGFyYWN0ZXIgYmVmb3JlL2FmdGVyIGlzIGEgc3BhY2UsIHRoaXMgbWlnaHQgY3JlYXRlIGEgbmV3IHdvcmRcclxuICAgICAgICBpZiAoa2V5ID09PSAnICcgfHwgKC9cXHMvLnRlc3QoY2hhckJlZm9yZSkgJiYgISgvXFxzLy50ZXN0KGtleSkpKSkge1xyXG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBDaGVjayBjaGFyYWN0ZXIgY291bnQgbGltaXRcclxuICAgIGlmICh0aGlzLm9wdGlvbnMubWF4TGVuZ3RoICYmIGN1cnJlbnRWYWx1ZS5sZW5ndGggPj0gdGhpcy5vcHRpb25zLm1heExlbmd0aCkge1xyXG4gICAgICAvLyBPbmx5IGFsbG93IGlmIHdlIGhhdmUgc2VsZWN0ZWQgdGV4dCAod2hpY2ggd2lsbCBiZSByZXBsYWNlZCkgb3IgbmF2aWdhdGlvbiBrZXlzXHJcbiAgICAgIGNvbnN0IGhhc1NlbGVjdGlvbiA9IHRleHRhcmVhLnNlbGVjdGlvblN0YXJ0ICE9PSB0ZXh0YXJlYS5zZWxlY3Rpb25FbmQ7XHJcbiAgICAgIGlmICghaGFzU2VsZWN0aW9uICYmICFhbGxvd2VkS2V5cy5pbmNsdWRlcyhrZXkpKSB7XHJcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvcHlJbnB1dE1lc3NhZ2UoaW5wdXRFbGVtZW50KSB7XHJcbiAgICB0aGlzLmNvbnRyb2xVdGlsaXR5LkNvcHlJbnB1dE1lc3NhZ2UoaW5wdXRFbGVtZW50KTtcclxuICAgIC8vIEFubm91bmNlIHRvIHNjcmVlbiByZWFkZXJzXHJcbiAgICB0aGlzLmFubm91bmNlVG9TY3JlZW5SZWFkZXIoJ1RleHQgY29waWVkIHRvIGNsaXBib2FyZCcpO1xyXG4gIH1cclxuXHJcbiAgb25UZXh0Q2hhbmdlKCkge1xyXG4gICAgaWYgKHRoaXMudGV4dEFyZWFGb3JtQ29udHJvbC52YWx1ZSA9PSAnJykge1xyXG4gICAgICB0aGlzLndvcmRDb3VudEFycmF5ID0gMDtcclxuICAgICAgdGhpcy53b3JkQ291bnQgPSAwO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy53b3JkQ291bnRBcnJheSA9IHRoaXMudGV4dEFyZWFGb3JtQ29udHJvbC52YWx1ZS5zcGxpdCgnICcpLmxlbmd0aDtcclxuICAgICAgaWYgKHRoaXMud29yZENvdW50QXJyYXkgPiAwKSB7XHJcbiAgICAgICAgaWYgKHRoaXMud29yZENvdW50QXJyYXkgPiB0aGlzLm9wdGlvbnMubWF4V29yZENvdW50KSB7XHJcbiAgICAgICAgICB0aGlzLndvcmRDb3VudCA9IHRoaXMub3B0aW9ucy5tYXhXb3JkQ291bnQ7XHJcbiAgICAgICAgICB0aGlzLnRleHRBcmVhRm9ybUNvbnRyb2wuc2V0RXJyb3JzKHtcclxuICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBgV29yZCBjb3VudCBtdXN0IGJlIGxlc3MgdGhhbiBvciBlcXVhbCB0byAke3RoaXMub3B0aW9ucy5tYXhXb3JkQ291bnR9YFxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgICB0aGlzLnRleHRBcmVhRm9ybUNvbnRyb2wubWFya0FzVG91Y2hlZCgpO1xyXG4gICAgICAgICAgdGhpcy50ZXh0QXJlYUZvcm1Db250cm9sLmludmFsaWQ7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoaXMud29yZENvdW50ID0gdGhpcy53b3JkQ291bnRBcnJheTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vQ2hlY2sgZm9yIG1heGxlbmd0aCBsaW1pdCBjb3VudFxyXG4gICAgLy9NYXhMZW5ndGggc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbHMgY2hhcnMgbGltaXQgc28gdGhhdCBtaW5DaGFyc0xpbWl0IHdvdWxkIGJlID49IDBcclxuICAgIGlmICh0aGlzLm9wdGlvbnMubWF4TGVuZ3RoICYmIHRoaXMubWluQ2hhcnNMaW1pdCA+PSAwKSB7XHJcbiAgICAgIC8vIENoZWNrIGlmIHZhbHVlIGV4aXN0cyBhbmQgaXMgbm90IGVtcHR5XHJcbiAgICAgIGNvbnN0IGNvbnRyb2xWYWx1ZSA9IHRoaXMudGV4dEFyZWFGb3JtQ29udHJvbC52YWx1ZTtcclxuICAgICAgaWYgKGNvbnRyb2xWYWx1ZSAmJiBjb250cm9sVmFsdWUudHJpbSgpLmxlbmd0aCA+IDApIHtcclxuICAgICAgICB0aGlzLmN1cnJlbnRDaGFyc0NvdW50ID0gY29udHJvbFZhbHVlLmxlbmd0aDtcclxuICAgICAgICBpZiAodGhpcy5jdXJyZW50Q2hhcnNDb3VudCA+IHRoaXMubWluQ2hhcnNMaW1pdCkge1xyXG4gICAgICAgICAgdGhpcy5zaG93Q2hhcnNMaW1pdE1zZyA9IHRydWU7XHJcbiAgICAgICAgICB0aGlzLmhhc0NoYXJzTGltaXRWYWxpZGF0aW9uRXJyb3IgPSB0cnVlO1xyXG5cclxuICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRDaGFyc0NvdW50ID09IHRoaXMub3B0aW9ucy5tYXhMZW5ndGgpIHRoaXMuY2hhcnNMaW1pdE1zZ0NsYXNzID0gJ2Rhbmdlcic7XHJcbiAgICAgICAgICBlbHNlIHRoaXMuY2hhcnNMaW1pdE1zZ0NsYXNzID0gJ3dhcm5pbmcnO1xyXG5cclxuICAgICAgICAgIC8vIE9ubHkgZ2VuZXJhdGUgd2FybmluZyBtZXNzYWdlIHdoZW4gd2UgYWN0dWFsbHkgd2FudCB0byBzaG93IGl0XHJcbiAgICAgICAgICBsZXQgbWF4OiBudW1iZXIgPSB0aGlzLm9wdGlvbnMubWF4TGVuZ3RoO1xyXG4gICAgICAgICAgbGV0IGN1cnJlbnQ6IG51bWJlciA9IHRoaXMuY3VycmVudENoYXJzQ291bnQ7XHJcbiAgICAgICAgICBsZXQgbXNnOiBzdHJpbmcgPSB0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ01heExlbmd0aExpbWl0V2FybmluZycpO1xyXG5cclxuICAgICAgICAgIHRoaXMubWF4TGltaXRXYXJuaW5nTXNnID0gbXNnXHJcbiAgICAgICAgICAgIC5yZXBsYWNlKCcke21heH0nLCBtYXgudG9TdHJpbmcoKSlcclxuICAgICAgICAgICAgLnJlcGxhY2UoJyR7Y3VycmVudH0nLCBjdXJyZW50LnRvU3RyaW5nKCkpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGlzLnNob3dDaGFyc0xpbWl0TXNnID0gZmFsc2U7XHJcbiAgICAgICAgICB0aGlzLmhhc0NoYXJzTGltaXRWYWxpZGF0aW9uRXJyb3IgPSBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gUmVzZXQgZXZlcnl0aGluZyB3aGVuIHZhbHVlIGlzIGVtcHR5XHJcbiAgICAgICAgdGhpcy5jdXJyZW50Q2hhcnNDb3VudCA9IDA7XHJcbiAgICAgICAgdGhpcy5zaG93Q2hhcnNMaW1pdE1zZyA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMuaGFzQ2hhcnNMaW1pdFZhbGlkYXRpb25FcnJvciA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMubWF4TGltaXRXYXJuaW5nTXNnID0gJyc7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHRoaXMub25DaGFuZ2UuZW1pdCh0aGlzLnRleHRBcmVhRm9ybUNvbnRyb2wudmFsdWUpO1xyXG5cclxuICAgIC8vIFVwZGF0ZSBhY2Nlc3NpYmlsaXR5IGF0dHJpYnV0ZXNcclxuICAgIHRoaXMudXBkYXRlQXJpYURlc2NyaWJlZEJ5KCk7XHJcblxyXG4gICAgLy8gQW5ub3VuY2UgY2hhcmFjdGVyIGxpbWl0IHdhcm5pbmdzIHRvIHNjcmVlbiByZWFkZXJzXHJcbiAgICBpZiAodGhpcy5zaG93Q2hhcnNMaW1pdE1zZyAmJiB0aGlzLmNoYXJzTGltaXRNc2dDbGFzcyA9PT0gJ2RhbmdlcicpIHtcclxuICAgICAgdGhpcy5hbm5vdW5jZVRvU2NyZWVuUmVhZGVyKGBDaGFyYWN0ZXIgbGltaXQgcmVhY2hlZDogJHt0aGlzLm1heExpbWl0V2FybmluZ01zZ31gKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG9uRm9jdXMoaXNGb2N1czogYm9vbGVhbikge1xyXG4gICAgdGhpcy5pc1Nob3dXb3JkQ291bnQgPSBpc0ZvY3VzO1xyXG5cclxuICAgIC8vb25Gb2N1c1xyXG4gICAgaWYgKGlzRm9jdXMpIHtcclxuICAgICAgaWYgKHRoaXMuaGFzQ2hhcnNMaW1pdFZhbGlkYXRpb25FcnJvcilcclxuICAgICAgICAvL2NoZWNrIGlmIHRoZXJlIHdhcyBwcmV2aW91cyB2YWxpZGF0aW9uIGVycm9yXHJcbiAgICAgICAgdGhpcy5zaG93Q2hhcnNMaW1pdE1zZyA9IHRydWU7XHJcbiAgICB9IC8vb25Gb2N1c091dFxyXG4gICAgZWxzZSB0aGlzLnNob3dDaGFyc0xpbWl0TXNnID0gZmFsc2U7XHJcbiAgfVxyXG5cclxuICAvL0V4dGVybmFsIE1ldGhvZFxyXG4gIHJlbW92ZVJlcXVpcmVkVmFsaWRhdGlvbiA9ICgpID0+IHtcclxuICAgIHRoaXMuY29udHJvbFV0aWxpdHkucmVtb3ZlUmVxdWlyZWRWYWxpZGF0aW9uKFxyXG4gICAgICB0aGlzLnRleHRBcmVhRm9ybUNvbnRyb2wsXHJcbiAgICAgIHRoaXMudmFsaWRhdGlvblJ1bGVzLFxyXG4gICAgICB0aGlzLm9wdGlvbnNcclxuICAgICk7XHJcbiAgfTtcclxuICAvL0V4dGVybmFsIE1ldGhvZFxyXG4gIGFkZFJlcXVpcmVkVmFsaWRhdGlvbiA9ICgpID0+IHtcclxuICAgIHRoaXMuY29udHJvbFV0aWxpdHkuYWRkUmVxdWlyZWRWYWxpZGF0aW9uKFxyXG4gICAgICB0aGlzLnRleHRBcmVhRm9ybUNvbnRyb2wsXHJcbiAgICAgIHRoaXMudmFsaWRhdGlvblJ1bGVzLFxyXG4gICAgICB0aGlzLm9wdGlvbnNcclxuICAgICk7XHJcbiAgfTtcclxuXHJcbiAgLy9FeHRlcm5hbCBNZXRob2RcclxuICByZW1vdmVDdXN0b21WYWxpZGF0aW9uID0gKGN1c3RvbVZhbGlkYXRpb24pID0+IHtcclxuICAgIHRoaXMuY29udHJvbFV0aWxpdHkucmVtb3ZlQ3VzdG9tVmFsaWRhdGlvbihcclxuICAgICAgdGhpcy50ZXh0QXJlYUZvcm1Db250cm9sLFxyXG4gICAgICB0aGlzLnZhbGlkYXRpb25SdWxlcyxcclxuICAgICAgY3VzdG9tVmFsaWRhdGlvblxyXG4gICAgKTtcclxuICB9O1xyXG4gIC8vRXh0ZXJuYWwgTWV0aG9kXHJcbiAgYWRkQ3VzdG9tVmFsaWRhdGlvbiA9IChjdXN0b21WYWxpZGF0aW9uKSA9PiB7XHJcbiAgICB0aGlzLmNvbnRyb2xVdGlsaXR5LmFkZEN1c3RvbVZhbGlkYXRpb24oXHJcbiAgICAgIHRoaXMudGV4dEFyZWFGb3JtQ29udHJvbCxcclxuICAgICAgdGhpcy52YWxpZGF0aW9uUnVsZXMsXHJcbiAgICAgIGN1c3RvbVZhbGlkYXRpb25cclxuICAgICk7XHJcbiAgfTtcclxuICAvL0V4dGVybmFsIE1ldGhvZFxyXG4gIGlzVmFsaWQgPSAoKSA9PiB7XHJcbiAgICB0aGlzLmNvbnRyb2xVdGlsaXR5LmlzVmFsaWQodGhpcy50ZXh0QXJlYUZvcm1Db250cm9sKTtcclxuICB9O1xyXG4gIC8vcmVnaW9uIFNwZWVjaCBSZWNvZ25pdGlvblxyXG4gIHNldFNwZWVjaExhbmd1YWdlKCkge1xyXG4gICAgLy8gR3VhcmQ6IE9ubHkgZXhlY3V0ZSBpZiBzcGVlY2ggcmVjb2duaXRpb24gaXMgZW5hYmxlZFxyXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuZW5hYmxlU3BlZWNoUmVjb2duaXRpb24pIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGxhbmd1YWdlQ29udHJvbE5hbWUgPSAnTGFuZ3VhZ2VfJyArIHRoaXMub3B0aW9ucy5uYW1lO1xyXG5cclxuICAgIGlmICh0aGlzLm9wdGlvbnMuYXV0b1NhdmVTcGVlY2hMYW5ndWFnZXRvTG9jYWxTdG9yYWdlKSB7XHJcbiAgICAgIGxldCBzYXZlZExhbmd1YWdlID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3NwZWVjaExhbmd1YWdlJyk7XHJcbiAgICAgIGlmIChzYXZlZExhbmd1YWdlKSB7XHJcbiAgICAgICAgdGhpcy5vcHRpb25zLnNlbGVjdGVkU3BlZWNoTGFuZ3VhZ2UgPSBzYXZlZExhbmd1YWdlO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMubG9hZFNlbGVjdGVkU3BlZWNoTGFuZ3VhZ2UoKTtcclxuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnc3BlZWNoTGFuZ3VhZ2UnLCB0aGlzLm9wdGlvbnMuc2VsZWN0ZWRTcGVlY2hMYW5ndWFnZSk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMubG9hZFNlbGVjdGVkU3BlZWNoTGFuZ3VhZ2UoKTtcclxuICAgIH1cclxuICAgIHRoaXMuZ3JvdXAuZ2V0KGxhbmd1YWdlQ29udHJvbE5hbWUpLnNldFZhbHVlKHRoaXMub3B0aW9ucy5zZWxlY3RlZFNwZWVjaExhbmd1YWdlKTtcclxuXHJcbiAgICBjb25zdCBsYW5ndWFnZSA9IHRoaXMub3B0aW9ucy5zcGVlY2hMYW5ndWFnZXM/LmZpbmQoXHJcbiAgICAgIChsKSA9PiBsLmRpYWxlY3QgPT0gdGhpcy5vcHRpb25zLnNlbGVjdGVkU3BlZWNoTGFuZ3VhZ2VcclxuICAgICk7XHJcbiAgICB0aGlzLnNlbGVjdGVkU3BlZWNoTGFuZ3VhZ2VEaXNwbGF5VGV4dCA9IGxhbmd1YWdlPy5wcmVmaXggfHwgJyc7XHJcbiAgfVxyXG4gIGxvYWRTZWxlY3RlZFNwZWVjaExhbmd1YWdlKCkge1xyXG4gICAgLy8gR3VhcmQ6IE9ubHkgZXhlY3V0ZSBpZiBzcGVlY2ggcmVjb2duaXRpb24gaXMgZW5hYmxlZFxyXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuZW5hYmxlU3BlZWNoUmVjb2duaXRpb24pIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghdGhpcy5vcHRpb25zLnNlbGVjdGVkU3BlZWNoTGFuZ3VhZ2UpIHtcclxuICAgICAgaWYgKFxyXG4gICAgICAgIHRoaXMuY3VycmVudExhbmd1YWdlID09ICdlbicgJiZcclxuICAgICAgICB0aGlzLm9wdGlvbnMuc3BlZWNoTGFuZ3VhZ2VzLnNvbWUoKGxhbmd1YWdlKSA9PiBsYW5ndWFnZS5lbmdsaXNoTmFtZSA9PT0gJ0VuZ2xpc2gnKVxyXG4gICAgICApIHtcclxuICAgICAgICB0aGlzLm9wdGlvbnMuc2VsZWN0ZWRTcGVlY2hMYW5ndWFnZSA9IHRoaXMub3B0aW9ucy5zcGVlY2hMYW5ndWFnZXMuZmluZChcclxuICAgICAgICAgIChsYW5ndWFnZSkgPT4gbGFuZ3VhZ2UuZW5nbGlzaE5hbWUgPT09ICdFbmdsaXNoJ1xyXG4gICAgICAgICkuZGlhbGVjdDtcclxuICAgICAgfSBlbHNlIGlmIChcclxuICAgICAgICB0aGlzLmN1cnJlbnRMYW5ndWFnZSA9PSAnYXInICYmXHJcbiAgICAgICAgdGhpcy5vcHRpb25zLnNwZWVjaExhbmd1YWdlcy5zb21lKChsYW5ndWFnZSkgPT4gbGFuZ3VhZ2UuZW5nbGlzaE5hbWUgPT09ICdBcmFiaWMnKVxyXG4gICAgICApIHtcclxuICAgICAgICB0aGlzLm9wdGlvbnMuc2VsZWN0ZWRTcGVlY2hMYW5ndWFnZSA9IHRoaXMub3B0aW9ucy5zcGVlY2hMYW5ndWFnZXMuZmluZChcclxuICAgICAgICAgIChsYW5ndWFnZSkgPT4gbGFuZ3VhZ2UuZW5nbGlzaE5hbWUgPT09ICdBcmFiaWMnXHJcbiAgICAgICAgKS5kaWFsZWN0O1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMub3B0aW9ucy5zZWxlY3RlZFNwZWVjaExhbmd1YWdlID0gdGhpcy5vcHRpb25zLnNwZWVjaExhbmd1YWdlc1swXS5kaWFsZWN0O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG4gIHN0YXJ0U3BlZWNoUmVjb2duaXRpb24oKTogdm9pZCB7XHJcbiAgICAvLyBHdWFyZDogT25seSBleGVjdXRlIGlmIHNwZWVjaCByZWNvZ25pdGlvbiBpcyBlbmFibGVkXHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5lbmFibGVTcGVlY2hSZWNvZ25pdGlvbikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCF0aGlzLnNwZWVjaFJlY29nbml0aW9uU2VydmljZS5pc1N1cHBvcnRlZCkge1xyXG4gICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSB0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ0Jyb3dzZXJOb3RTdXBwb3J0U3BlZWNoUmVjb2duaXRpb24nKTtcclxuICAgICAgdGhpcy51dGlsaXR5U2VydmljZS5ub3RpZnlFcnJvck1lc3NhZ2UoZXJyb3JNZXNzYWdlKTtcclxuICAgICAgdGhpcy5hbm5vdW5jZVRvU2NyZWVuUmVhZGVyKGVycm9yTWVzc2FnZSk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIC8vRGlzYWJsZSBTZWxlY3QgTGFuZ3VhZ2VcclxuICAgIHRoaXMuZW5hYmxlT3JEaXNhYmxlTGFuZ3VhZ2VTZWxlY3QoZmFsc2UpO1xyXG4gICAgdGhpcy5pc01pY09uID0gdHJ1ZTtcclxuXHJcbiAgICAvLyBBbm5vdW5jZSB0byBzY3JlZW4gcmVhZGVyc1xyXG4gICAgdGhpcy5hbm5vdW5jZVRvU2NyZWVuUmVhZGVyKCdTcGVlY2ggcmVjb2duaXRpb24gc3RhcnRlZC4gU3BlYWsgbm93LicpO1xyXG4gICAgdGhpcy5zdWJzY3JpcHRpb24gPSB0aGlzLnNwZWVjaFJlY29nbml0aW9uU2VydmljZVxyXG4gICAgICAuc3RhcnRMaXN0ZW5pbmcodGhpcy5vcHRpb25zLnNlbGVjdGVkU3BlZWNoTGFuZ3VhZ2UpXHJcbiAgICAgIC5zdWJzY3JpYmUoe1xyXG4gICAgICAgIG5leHQ6ICh0cmFuc2NyaXB0OiBzdHJpbmcpID0+IHtcclxuICAgICAgICAgIGlmICh0cmFuc2NyaXB0KSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMudmFsdWUpIHtcclxuICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMudmFsdWUgKz0gJyAnO1xyXG4gICAgICAgICAgICAgIHRoaXMuZmlyZU9uQ2hhbmdlKHRoaXMub3B0aW9ucy52YWx1ZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgbGV0IGNoYXJJbmRleCA9IDA7XHJcbiAgICAgICAgICAgIGNvbnN0IGludGVydmFsID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xyXG4gICAgICAgICAgICAgIHRoaXMub3B0aW9ucy52YWx1ZSArPSB0cmFuc2NyaXB0W2NoYXJJbmRleF07XHJcbiAgICAgICAgICAgICAgdGhpcy5maXJlT25DaGFuZ2UodGhpcy5vcHRpb25zLnZhbHVlKTtcclxuICAgICAgICAgICAgICBjaGFySW5kZXgrKztcclxuICAgICAgICAgICAgICBpZiAoY2hhckluZGV4ID09PSB0cmFuc2NyaXB0Lmxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgY2xlYXJJbnRlcnZhbChpbnRlcnZhbCk7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LCAxMCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuICAgICAgICBlcnJvcjogKGVycm9yOiBhbnkpID0+IHtcclxuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xyXG4gICAgICAgICAgdGhpcy5zdG9wU3BlZWNoUmVjb2duaXRpb24oKTtcclxuICAgICAgICB9LFxyXG4gICAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgICAvL0VuYWJsZSBTZWxlY3QgTGFuZ3VhZ2VcclxuICAgICAgICAgIHRoaXMuZW5hYmxlT3JEaXNhYmxlTGFuZ3VhZ2VTZWxlY3QoKTtcclxuICAgICAgICAgIHRoaXMuaXNNaWNPbiA9IGZhbHNlO1xyXG4gICAgICAgICAgdGhpcy5hbm5vdW5jZVRvU2NyZWVuUmVhZGVyKCdTcGVlY2ggcmVjb2duaXRpb24gc3RvcHBlZC4nKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgc3RvcFNwZWVjaFJlY29nbml0aW9uKCk6IHZvaWQge1xyXG4gICAgLy8gR3VhcmQ6IE9ubHkgZXhlY3V0ZSBpZiBzcGVlY2ggcmVjb2duaXRpb24gaXMgZW5hYmxlZFxyXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuZW5hYmxlU3BlZWNoUmVjb2duaXRpb24pIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuZW5hYmxlT3JEaXNhYmxlTGFuZ3VhZ2VTZWxlY3QoKTtcclxuICAgIGlmICghdGhpcy5zcGVlY2hSZWNvZ25pdGlvblNlcnZpY2UuaXNTdXBwb3J0ZWQpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdGhpcy5pc01pY09uID0gZmFsc2U7XHJcbiAgICB0aGlzLnNwZWVjaFJlY29nbml0aW9uU2VydmljZS5zdG9wTGlzdGVuaW5nKCk7XHJcbiAgICBpZiAodGhpcy5zdWJzY3JpcHRpb24pIHtcclxuICAgICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBbm5vdW5jZSB0byBzY3JlZW4gcmVhZGVyc1xyXG4gICAgdGhpcy5hbm5vdW5jZVRvU2NyZWVuUmVhZGVyKCdTcGVlY2ggcmVjb2duaXRpb24gc3RvcHBlZC4nKTtcclxuICB9XHJcbiAgZmlyZU9uQ2hhbmdlKHRleHQpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLm9uQ2hhbmdlKSB7XHJcbiAgICAgIHRoaXMub25DaGFuZ2UuZW1pdCh0ZXh0KTtcclxuICAgIH1cclxuICB9XHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICAvLyBBbHdheXMgY2xlYW4gdXAgc3Vic2NyaXB0aW9uc1xyXG4gICAgaWYgKHRoaXMuc3Vic2NyaXB0aW9uKSB7XHJcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy52YWx1ZUNoYW5nZXNTdWJzY3JpcHRpb24pIHtcclxuICAgICAgdGhpcy52YWx1ZUNoYW5nZXNTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBPbmx5IGNhbGwgc3BlZWNoIHJlY29nbml0aW9uIGNsZWFudXAgaWYgaXQgd2FzIGVuYWJsZWRcclxuICAgIGlmICh0aGlzLm9wdGlvbnMuZW5hYmxlU3BlZWNoUmVjb2duaXRpb24pIHtcclxuICAgICAgdGhpcy5zdG9wU3BlZWNoUmVjb2duaXRpb24oKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIEtleWJvYXJkIGFjY2Vzc2liaWxpdHkgZm9yIHNwZWVjaCByZWNvZ25pdGlvbiBjb250cm9sc1xyXG4gIG9uTWljS2V5ZG93bihldmVudDogS2V5Ym9hcmRFdmVudCwgYWN0aW9uOiAnc3RhcnQnIHwgJ3N0b3AnKTogdm9pZCB7XHJcbiAgICAvLyBHdWFyZDogT25seSBleGVjdXRlIGlmIHNwZWVjaCByZWNvZ25pdGlvbiBpcyBlbmFibGVkXHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5lbmFibGVTcGVlY2hSZWNvZ25pdGlvbikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ0VudGVyJyB8fCBldmVudC5rZXkgPT09ICcgJykge1xyXG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICBpZiAoYWN0aW9uID09PSAnc3RhcnQnKSB7XHJcbiAgICAgICAgdGhpcy5zdGFydFNwZWVjaFJlY29nbml0aW9uKCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5zdG9wU3BlZWNoUmVjb2duaXRpb24oKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25MYW5ndWFnZVNlbGVjdEZvY3VzKGlzRm9jdXNlZDogYm9vbGVhbik6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuZW5hYmxlU3BlZWNoUmVjb2duaXRpb24pIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuaXNMYW5ndWFnZVNlbGVjdEZvY3VzVmlzaWJsZSA9IGlzRm9jdXNlZDtcclxuICB9XHJcblxyXG4gIG9uTGFuZ3VhZ2VTZWxlY3RLZXlkb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5lbmFibGVTcGVlY2hSZWNvZ25pdGlvbikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ1RhYicpIHtcclxuICAgICAgdGhpcy5pc0xhbmd1YWdlU2VsZWN0Rm9jdXNWaXNpYmxlID0gdHJ1ZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG9uTWljRm9jdXMoaXNGb2N1c2VkOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5lbmFibGVTcGVlY2hSZWNvZ25pdGlvbikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5pc01pY0ZvY3VzVmlzaWJsZSA9IGlzRm9jdXNlZDtcclxuICB9XHJcblxyXG4gIG9uQ29weUtleWRvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQsIGlucHV0RWxlbWVudDogSFRNTFRleHRBcmVhRWxlbWVudCk6IHZvaWQge1xyXG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ0VudGVyJyB8fCBldmVudC5rZXkgPT09ICcgJykge1xyXG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICB0aGlzLmNvcHlJbnB1dE1lc3NhZ2UoaW5wdXRFbGVtZW50KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG9uU3BlZWNoTGFuZ3VhZ2VDaGFuZ2UoZXZlbnQ6IEV2ZW50KSB7XHJcbiAgICAvLyBHdWFyZDogT25seSBleGVjdXRlIGlmIHNwZWVjaCByZWNvZ25pdGlvbiBpcyBlbmFibGVkXHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5lbmFibGVTcGVlY2hSZWNvZ25pdGlvbikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHNlbGVjdGVkTGFuZ19EaWFsZWN0ID0gKGV2ZW50LnRhcmdldCBhcyBIVE1MU2VsZWN0RWxlbWVudCkudmFsdWU7XHJcbiAgICBjb25zdCBsYW5ndWFnZSA9IHRoaXMub3B0aW9ucy5zcGVlY2hMYW5ndWFnZXM/LmZpbmQoXHJcbiAgICAgIChsKSA9PiBsLmRpYWxlY3QgPT0gc2VsZWN0ZWRMYW5nX0RpYWxlY3RcclxuICAgICk7XHJcbiAgICB0aGlzLnNlbGVjdGVkU3BlZWNoTGFuZ3VhZ2VEaXNwbGF5VGV4dCA9IGxhbmd1YWdlPy5wcmVmaXggfHwgJyc7XHJcbiAgICB0aGlzLm9wdGlvbnMuc2VsZWN0ZWRTcGVlY2hMYW5ndWFnZSA9IHNlbGVjdGVkTGFuZ19EaWFsZWN0O1xyXG5cclxuICAgIGNvbnN0IGxhbmd1YWdlQ29udHJvbE5hbWUgPSAnTGFuZ3VhZ2VfJyArIHRoaXMub3B0aW9ucy5uYW1lO1xyXG4gICAgbGV0IHNlbGVjdCA9IHRoaXMuZ3JvdXAuZ2V0KGxhbmd1YWdlQ29udHJvbE5hbWUpO1xyXG4gICAgc2VsZWN0LnNldFZhbHVlKHNlbGVjdGVkTGFuZ19EaWFsZWN0KTtcclxuXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmF1dG9TYXZlU3BlZWNoTGFuZ3VhZ2V0b0xvY2FsU3RvcmFnZSkge1xyXG4gICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnc3BlZWNoTGFuZ3VhZ2UnLCBzZWxlY3RlZExhbmdfRGlhbGVjdCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQW5ub3VuY2UgbGFuZ3VhZ2UgY2hhbmdlIHRvIHNjcmVlbiByZWFkZXJzXHJcbiAgICB0aGlzLmFubm91bmNlVG9TY3JlZW5SZWFkZXIoYFNwZWVjaCByZWNvZ25pdGlvbiBsYW5ndWFnZSBjaGFuZ2VkIHRvICR7bGFuZ3VhZ2U/Lm5hbWUgfHwgc2VsZWN0ZWRMYW5nX0RpYWxlY3R9YCk7XHJcbiAgfVxyXG4gIGVuYWJsZU9yRGlzYWJsZUxhbmd1YWdlU2VsZWN0KGlzRW5hYmxlZDogYm9vbGVhbiA9IHRydWUpIHtcclxuICAgIC8vIEd1YXJkOiBPbmx5IGV4ZWN1dGUgaWYgc3BlZWNoIHJlY29nbml0aW9uIGlzIGVuYWJsZWRcclxuICAgIGlmICghdGhpcy5vcHRpb25zLmVuYWJsZVNwZWVjaFJlY29nbml0aW9uKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBsYW5ndWFnZUNvbnRyb2xOYW1lID0gJ0xhbmd1YWdlXycgKyB0aGlzLm9wdGlvbnMubmFtZTtcclxuICAgIGxldCBzZWxlY3QgPSB0aGlzLmdyb3VwLmdldChsYW5ndWFnZUNvbnRyb2xOYW1lKTtcclxuICAgIGlmIChpc0VuYWJsZWQpIHtcclxuICAgICAgc2VsZWN0LmVuYWJsZSgpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgc2VsZWN0LmRpc2FibGUoKTtcclxuICAgIH1cclxuICB9XHJcbiAgLy8jZW5kUmVnaW9uXHJcbn1cclxuXHJcblxyXG4iLCI8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cCBiYnNmLWNvbnRyb2wgYmJzZi10ZXh0YXJlYVwiIFtmb3JtR3JvdXBdPVwiZ3JvdXBcIj5cclxuICA8ZGl2IFtuZ0NsYXNzXT1cIihvcHRpb25zLnZpZXdUeXBlPT0xKT8nYmJzZi12ZXJ0aWNhbCc6J2Jic2YtaG9yaXpvbnRhbCdcIj5cclxuICAgIDwhLS1sYWJlbC0tPlxyXG4gICAgPGxhYmVsICpuZ0lmPVwiIW9wdGlvbnMuaGlkZUxhYmVsXCIgY2xhc3M9XCJiYnNmLWxhYmVsIHt7b3B0aW9ucy5sYWJlbEV4dHJhQ2xhc3Nlc319XCI+XHJcbiAgICAgIHt7b3B0aW9ucy5sYWJlbFZhbHVlfX1cclxuICAgICAgPCEtLUFzdGVyaXNrLS0+XHJcbiAgICAgIDxzcGFuICpuZ0lmPVwiKChvcHRpb25zLnNob3dBc3RlcmlzayYmb3B0aW9ucy5pc1JlcXVpcmVkKXx8KG9wdGlvbnMuaXNSZXF1aXJlZCkpJiYhb3B0aW9ucy5pc1JlYWRvbmx5XCJcclxuICAgICAgICBjbGFzcz1cInRleHQtZGFuZ2VyXCI+Kjwvc3Bhbj5cclxuICAgIDwvbGFiZWw+XHJcbiAgICA8ZGl2ICpuZ0lmPVwiIW9wdGlvbnMuaXNSZWFkb25seVwiIGNsYXNzPVwiYmJzZi1pbnB1dC1jb250YWluZXJcIiBbbmdDbGFzc109XCJ7XHJcbiAgICAgICdwLTEyMHB4Jzogb3B0aW9ucy5lbmFibGVTcGVlY2hSZWNvZ25pdGlvbiAmJiBvcHRpb25zLmVuYWJsZUNvcHlUb0NsaXBib2FyZCxcclxuICAgICAgJ3AtODBweCc6IG9wdGlvbnMuZW5hYmxlU3BlZWNoUmVjb2duaXRpb24gJiYgIW9wdGlvbnMuZW5hYmxlQ29weVRvQ2xpcGJvYXJkLFxyXG4gICAgICAncC00MHB4JzogIW9wdGlvbnMuZW5hYmxlU3BlZWNoUmVjb2duaXRpb24gJiYgb3B0aW9ucy5lbmFibGVDb3B5VG9DbGlwYm9hcmRcclxuICAgIH1cIj5cclxuICAgICAgPCEtLWlucHV0LS0+XHJcbiAgICAgIDx0ZXh0YXJlYSBjbGFzcz1cImZvcm0tY29udHJvbCB7e29wdGlvbnMuZXh0cmFDbGFzc2VzfX1cIiAoZm9jdXMpPVwib25Gb2N1cyh0cnVlKVwiIChmb2N1c291dCk9XCJvbkZvY3VzKGZhbHNlKVwiXHJcbiAgICAgICAgW2Rpcl09XCJ0ZXh0RGlyXCIgW2F0dHIuYXJpYS1pbnZhbGlkXT1cInRleHRBcmVhRm9ybUNvbnRyb2wuaW52YWxpZCAmJiB0ZXh0QXJlYUZvcm1Db250cm9sLnRvdWNoZWRcIlxyXG4gICAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiYXJpYURlc2NyaWJlZEJ5XCIgW2F0dHIuYXJpYS1sYWJlbF09XCJvcHRpb25zLmxhYmVsVmFsdWUgfHwgb3B0aW9ucy5wbGFjZWhvbGRlclwiXHJcbiAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwie3tvcHRpb25zLm5hbWV9fVwiXHJcbiAgICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwidGV4dEFyZWFGb3JtQ29udHJvbC5pbnZhbGlkICYmIHRleHRBcmVhRm9ybUNvbnRyb2wudG91Y2hlZFwiXHJcbiAgICAgICAgcGxhY2Vob2xkZXI9XCJ7e29wdGlvbnMucGxhY2Vob2xkZXJ9fVwiIGlkPVwie3tvcHRpb25zLm5hbWV9fVwiIGF1dG9jb21wbGV0ZT1cInt7b3B0aW9ucy5hdXRvQ29tcGxldGV9fVwiXHJcbiAgICAgICAgKGNoYW5nZSk9XCJ0cmltQ29udHJvbFZhbHVlKClcIiByb3dzPVwie3tvcHRpb25zLnJvd3N9fVwiIChrZXl1cCk9XCJvblRleHRDaGFuZ2UoKVwiIGNvbHM9XCJ7e29wdGlvbnMuY29sc319XCJcclxuICAgICAgICBbYXR0ci5taW5sZW5ndGhdPVwib3B0aW9ucy5taW5MZW5ndGhcIiBbKG5nTW9kZWwpXT1cIm9wdGlvbnMudmFsdWVcIiAoa2V5ZG93bik9XCJvbktleURvd24oJGV2ZW50KVwiXHJcbiAgICAgICAgW2F0dHIubWF4bGVuZ3RoXT1cIm9wdGlvbnMubWF4TGVuZ3RoXCIgcm9sZT1cInRleHRib3hcIiBbYXR0ci5hcmlhLW11bHRpbGluZV09XCJ0cnVlXCIgI1RleHRBcmVhaW5wdXQ+PC90ZXh0YXJlYT5cclxuICAgICAgPCEtLUNvcHlUb0NsaXBib2FyZC0tPlxyXG4gICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImNvcHktY2xpcGJvYXJkXCIgKm5nSWY9XCJvcHRpb25zLmVuYWJsZUNvcHlUb0NsaXBib2FyZFwiXHJcbiAgICAgICAgKGNsaWNrKT1cImNvcHlJbnB1dE1lc3NhZ2UoVGV4dEFyZWFpbnB1dClcIiAoa2V5ZG93bik9XCJvbkNvcHlLZXlkb3duKCRldmVudCwgVGV4dEFyZWFpbnB1dClcIlxyXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwidXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnQ29weVRleHRUb0NsaXBib2FyZCcpXCIgW25nYlRvb2x0aXBdPVwidXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnQ29weVRleHRUb0NsaXBib2FyZCcpXCIgdGFiaW5kZXg9XCIwXCI+XHJcbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtY29weVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cclxuICAgICAgPC9idXR0b24+XHJcbiAgICAgIDxkaXYgW25nQ2xhc3NdPVwieydleHBhbmRlZCc6IGlzRm9jdXNlZH1cIiBjbGFzcz1cImxhbmd1YWdlLWNvbnRhaW5lciB7e29wdGlvbnMuZXh0cmFDbGFzc01pY0xhbmd1YWdlfX1cIlxyXG4gICAgICAgICpuZ0lmPVwib3B0aW9ucy5lbmFibGVTcGVlY2hSZWNvZ25pdGlvblwiIHJvbGU9XCJyZWdpb25cIj5cclxuXHJcbiAgICAgICAgPCEtLSBTdGFydCBTcGVlY2ggUmVjb2duaXRpb24gQnV0dG9uIC0tPlxyXG4gICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwic3ZnLWljb24gc3ZnLWljb24tNSBzcGVlY2gtY29udHJvbC1idG5cIiBbY2xhc3MuZm9jdXMtdmlzaWJsZV09XCJpc01pY0ZvY3VzVmlzaWJsZVwiXHJcbiAgICAgICAgICBbaW5saW5lU1ZHXT1cIm9wdGlvbnMuaWNvbk1pYyB8fCAnYXNzZXRzL2Jic2YtY29udHJvbHMvaW1hZ2VzL21pYy5zdmcnXCIgKGNsaWNrKT1cInN0YXJ0U3BlZWNoUmVjb2duaXRpb24oKVwiXHJcbiAgICAgICAgICAoa2V5ZG93bik9XCJvbk1pY0tleWRvd24oJGV2ZW50LCAnc3RhcnQnKVwiIChmb2N1cyk9XCJvbk1pY0ZvY3VzKHRydWUpXCIgKGJsdXIpPVwib25NaWNGb2N1cyhmYWxzZSlcIlxyXG4gICAgICAgICAgKm5nSWY9XCJvcHRpb25zLmVuYWJsZVNwZWVjaFJlY29nbml0aW9uICYmICFpc01pY09uXCJcclxuICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwidXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnU3RhcnRTcGVlY2hSZWNvZ25pdGlvbicpXCIgW25nYlRvb2x0aXBdPVwidXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnU3RhcnRTcGVlY2hSZWNvZ25pdGlvbicpXCIgdGFiaW5kZXg9XCIwXCJcclxuICAgICAgICAgIFthdHRyLmFyaWEtcHJlc3NlZF09XCJmYWxzZVwiPlxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG5cclxuICAgICAgICA8IS0tIFN0b3AgU3BlZWNoIFJlY29nbml0aW9uIEJ1dHRvbiAtLT5cclxuICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cInN2Zy1pY29uIHN2Zy1pY29uLTUgc3BlZWNoLWNvbnRyb2wtYnRuXCIgW2NsYXNzLmZvY3VzLXZpc2libGVdPVwiaXNNaWNGb2N1c1Zpc2libGVcIlxyXG4gICAgICAgICAgW2lubGluZVNWR109XCJvcHRpb25zLmljb25NaWNPZmYgfHwgJ2Fzc2V0cy9iYnNmLWNvbnRyb2xzL2ltYWdlcy9taWMtb2ZmLnN2ZydcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cInN0b3BTcGVlY2hSZWNvZ25pdGlvbigpXCIgKGtleWRvd24pPVwib25NaWNLZXlkb3duKCRldmVudCwgJ3N0b3AnKVwiXHJcbiAgICAgICAgICAoZm9jdXMpPVwib25NaWNGb2N1cyh0cnVlKVwiIChibHVyKT1cIm9uTWljRm9jdXMoZmFsc2UpXCJcclxuICAgICAgICAgICpuZ0lmPVwib3B0aW9ucy5lbmFibGVTcGVlY2hSZWNvZ25pdGlvbiAmJiBpc01pY09uXCIgW2F0dHIuYXJpYS1sYWJlbF09XCJ1dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdTdG9wU3BlZWNoUmVjb2duaXRpb24nKVwiXHJcbiAgICAgICAgICBbbmdiVG9vbHRpcF09XCJ1dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdTdG9wU3BlZWNoUmVjb2duaXRpb24nKVwiIHRhYmluZGV4PVwiMFwiIFthdHRyLmFyaWEtcHJlc3NlZF09XCJ0cnVlXCI+XHJcbiAgICAgICAgPC9idXR0b24+XHJcblxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJsYW5ndWFnZS1jb250cm9sc1wiIFtjbGFzcy5mb2N1cy12aXNpYmxlXT1cImlzTGFuZ3VhZ2VTZWxlY3RGb2N1c1Zpc2libGVcIj5cclxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGFuZ3VhZ2UtdGV4dFwiIFthdHRyLmlkXT1cIm9wdGlvbnMubmFtZSArICctbGFuZ3VhZ2UtZGlzcGxheSdcIlxyXG4gICAgICAgICAgICBhcmlhLWxpdmU9XCJwb2xpdGVcIj57eyBvcHRpb25zLmVuYWJsZVNwZWVjaFJlY29nbml0aW9uID8gc2VsZWN0ZWRTcGVlY2hMYW5ndWFnZURpc3BsYXlUZXh0IDogJycgfX08L3NwYW4+XHJcblxyXG4gICAgICAgICAgPGxhYmVsIFtmb3JdPVwiJ0xhbmd1YWdlXycrb3B0aW9ucy5uYW1lXCIgY2xhc3M9XCJzci1vbmx5XCI+XHJcbiAgICAgICAgICAgIFNlbGVjdCBzcGVlY2ggcmVjb2duaXRpb24gbGFuZ3VhZ2VcclxuICAgICAgICAgIDwvbGFiZWw+XHJcbiAgICAgICAgICA8c2VsZWN0IGNsYXNzPVwibGFuZ3VhZ2Utc2VsZWN0XCIgW2Zvcm1Db250cm9sTmFtZV09XCInTGFuZ3VhZ2VfJytvcHRpb25zLm5hbWVcIiBbaWRdPVwiJ0xhbmd1YWdlXycrb3B0aW9ucy5uYW1lXCJcclxuICAgICAgICAgICAgKGNoYW5nZSk9XCJvblNwZWVjaExhbmd1YWdlQ2hhbmdlKCRldmVudClcIiAoZm9jdXMpPVwib25MYW5ndWFnZVNlbGVjdEZvY3VzKHRydWUpXCJcclxuICAgICAgICAgICAgKGJsdXIpPVwib25MYW5ndWFnZVNlbGVjdEZvY3VzKGZhbHNlKVwiIChrZXlkb3duKT1cIm9uTGFuZ3VhZ2VTZWxlY3RLZXlkb3duKCRldmVudClcIlxyXG4gICAgICAgICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cIm9wdGlvbnMubmFtZSArICctbGFuZ3VhZ2UtZGlzcGxheSdcIiBbYXR0ci5hcmlhLWxhYmVsXT1cInV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ1NlbGVjdFNwZWVjaFJlY29nbml0aW9uTGFuZ3VhZ2UnKVwiXHJcbiAgICAgICAgICAgIFtuZ2JUb29sdGlwXT1cInV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ1NlbGVjdFNwZWVjaFJlY29nbml0aW9uTGFuZ3VhZ2UnKVwiXHJcbiAgICAgICAgICAgIHRyaWdnZXJzPVwiZm9jdXM6Ymx1clwiPlxyXG4gICAgICAgICAgICA8b3B0aW9uICpuZ0Zvcj1cImxldCBsYW5ndWFnZSBvZiBvcHRpb25zLnNwZWVjaExhbmd1YWdlc1wiIFt2YWx1ZV09XCJsYW5ndWFnZS5kaWFsZWN0XCI+XHJcbiAgICAgICAgICAgICAge3tsYW5ndWFnZS5uYW1lfX1cclxuICAgICAgICAgICAgPC9vcHRpb24+XHJcbiAgICAgICAgICA8L3NlbGVjdD5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuICAgIDwhLS0gcmVhZG9ubHkgLS0+XHJcbiAgICA8ZGl2ICpuZ0lmPVwib3B0aW9ucy5pc1JlYWRvbmx5XCI+PHNwYW4gY2xhc3M9XCJyZWFkb25seS12aWV3XCI+e3tvcHRpb25zLnZhbHVlfX08L3NwYW4+XHJcbiAgICA8L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJzdWJ0ZXh0LWNvbnRhaW5lclwiPlxyXG4gICAgICA8IS0td29yZENvdW50LS0+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJiYnNmLXdvcmQtY291bnRcIiAqbmdJZj1cIm9wdGlvbnMubWF4V29yZENvdW50PjAmJmlzU2hvd1dvcmRDb3VudFwiIFthdHRyLmlkXT1cIndvcmRDb3VudElkXCJcclxuICAgICAgICBhcmlhLWxpdmU9XCJwb2xpdGVcIiBbYXR0ci5hcmlhLWxhYmVsXT1cIidXb3JkIGNvdW50OiAnICsgd29yZENvdW50ICsgJyBvZiAnICsgb3B0aW9ucy5tYXhXb3JkQ291bnQgKyAnIHdvcmRzJ1wiPlxyXG4gICAgICAgIHt7d29yZENvdW50fX0ve3tvcHRpb25zLm1heFdvcmRDb3VudH19IFdvcmRzXHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPCEtLSBDaGFyc0xpbWl0TXNnLS0+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJiYnNmLWNoYXJhY3Rlci1jb3VudFwiICpuZ0lmPVwic2hvd0NoYXJzTGltaXRNc2dcIiBbYXR0ci5pZF09XCJjaGFyYWN0ZXJDb3VudElkXCIgYXJpYS1saXZlPVwicG9saXRlXCJcclxuICAgICAgICBbYXR0ci5hcmlhLWF0b21pY109XCJ0cnVlXCJcclxuICAgICAgICBbbmdDbGFzc109XCJ7J2JhZGdlLWxpZ2h0LXdhcm5pbmcnOiBjaGFyc0xpbWl0TXNnQ2xhc3MgPT09ICd3YXJuaW5nJywgJ2JhZGdlLWxpZ2h0LWRhbmdlcicgOiBjaGFyc0xpbWl0TXNnQ2xhc3MgPT09ICdkYW5nZXInIH1cIj5cclxuICAgICAgICB7e21heExpbWl0V2FybmluZ01zZ319XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPCEtLSBMYWJlbERlc2NyaXB0aW9uLS0+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJiYnNmLWNvbnRyb2wtZGVzY1wiICpuZ0lmPVwib3B0aW9ucy5sYWJlbERlc2NyaXB0aW9uIT1udWxsXCIgW2F0dHIuaWRdPVwib3B0aW9ucy5uYW1lICsgJy1kZXNjcmlwdGlvbidcIj5cclxuICAgICAgICB7e29wdGlvbnMubGFiZWxEZXNjcmlwdGlvbn19XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPCEtLSByZXF1aXJlZFRleHQtLT5cclxuICAgICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvblwiIFtkaXJdPVwidGV4dERpclwiICpuZ0lmPVwiKHRleHRBcmVhRm9ybUNvbnRyb2wuaW52YWxpZCAmJiB0ZXh0QXJlYUZvcm1Db250cm9sLnRvdWNoZWQpXCJcclxuICAgICAgICBbYXR0ci5pZF09XCJlcnJvck1lc3NhZ2VJZFwiIHJvbGU9XCJhbGVydFwiIGFyaWEtbGl2ZT1cImFzc2VydGl2ZVwiIFthdHRyLmFyaWEtYXRvbWljXT1cInRydWVcIj5cclxuICAgICAgICB7e2dldEVycm9yVmFsaWRhdGlvbih0ZXh0QXJlYUZvcm1Db250cm9sLmVycm9yc3xrZXl2YWx1ZSl9fVxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdiAqbmdJZj1cIihncm91cC52YWxpZCYmZ3JvdXAuZGlydHkmJmdyb3VwLnRvdWNoZWQgKXx8KGdyb3VwLnVudG91Y2hlZCYmZ3JvdXAuaW52YWxpZCYmZ3JvdXAuZGlydHkpIFwiPlxyXG4gICAgICB7e3Jlc2V0RXJyb3IoKX19PC9kaXY+XHJcbiAgPC9kaXY+Il19
|