cax-design-system 2.6.0 → 2.7.0

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.
Files changed (51) hide show
  1. package/README.md +1 -1
  2. package/commentbox/commentbox.d.ts +111 -0
  3. package/commentbox/commentbox.module.d.ts +17 -0
  4. package/commentbox/index.d.ts +5 -0
  5. package/commentbox/public_api.d.ts +2 -0
  6. package/esm2022/card/card.mjs +2 -2
  7. package/esm2022/commentbox/cax-design-system-commentbox.mjs +5 -0
  8. package/esm2022/commentbox/commentbox.mjs +541 -0
  9. package/esm2022/commentbox/commentbox.module.mjs +27 -0
  10. package/esm2022/commentbox/public_api.mjs +3 -0
  11. package/esm2022/inputtext/inputtext.component.mjs +13 -4
  12. package/esm2022/inputtextarea/inputtextarea.component.mjs +8 -4
  13. package/esm2022/navigation/navigation.mjs +18 -5
  14. package/esm2022/table/components/column-filter/column-filter.mjs +52 -11
  15. package/esm2022/table/components/sort-icon/sort-icon.mjs +10 -7
  16. package/esm2022/table/table.mjs +123 -98
  17. package/esm2022/upload/cax-design-system-upload.mjs +5 -0
  18. package/esm2022/upload/public_api.mjs +3 -0
  19. package/esm2022/upload/upload.component.mjs +355 -0
  20. package/esm2022/upload/upload.component.module.mjs +21 -0
  21. package/fesm2022/cax-design-system-card.mjs +2 -2
  22. package/fesm2022/cax-design-system-card.mjs.map +1 -1
  23. package/fesm2022/cax-design-system-commentbox.mjs +572 -0
  24. package/fesm2022/cax-design-system-commentbox.mjs.map +1 -0
  25. package/fesm2022/cax-design-system-inputtext.mjs +12 -3
  26. package/fesm2022/cax-design-system-inputtext.mjs.map +1 -1
  27. package/fesm2022/cax-design-system-inputtextarea.mjs +7 -3
  28. package/fesm2022/cax-design-system-inputtextarea.mjs.map +1 -1
  29. package/fesm2022/cax-design-system-navigation.mjs +17 -4
  30. package/fesm2022/cax-design-system-navigation.mjs.map +1 -1
  31. package/fesm2022/cax-design-system-table.mjs +181 -113
  32. package/fesm2022/cax-design-system-table.mjs.map +1 -1
  33. package/fesm2022/cax-design-system-upload.mjs +380 -0
  34. package/fesm2022/cax-design-system-upload.mjs.map +1 -0
  35. package/inputtext/inputtext.component.d.ts +4 -1
  36. package/inputtextarea/inputtextarea.component.d.ts +2 -2
  37. package/navigation/navigation.d.ts +3 -1
  38. package/package.json +174 -162
  39. package/resources/cax.min.scss +1 -1
  40. package/resources/cax.scss +305 -254
  41. package/resources/components/card/card.scss +1 -1
  42. package/resources/components/commentbox/commentbox.scss +604 -0
  43. package/resources/components/table/table.scss +12 -4
  44. package/resources/components/upload/upload.component.scss +147 -0
  45. package/table/components/column-filter/column-filter.d.ts +6 -1
  46. package/table/components/sort-icon/sort-icon.d.ts +2 -1
  47. package/table/table.d.ts +6 -4
  48. package/upload/index.d.ts +5 -0
  49. package/upload/public_api.d.ts +2 -0
  50. package/upload/upload.component.d.ts +61 -0
  51. package/upload/upload.component.module.d.ts +11 -0
@@ -0,0 +1,541 @@
1
+ import { Component, Input, Output, EventEmitter, ViewChild, HostListener } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ import * as i1 from "@angular/platform-browser";
4
+ import * as i2 from "@angular/common";
5
+ import * as i3 from "@angular/forms";
6
+ import * as i4 from "cax-design-system/sidebar";
7
+ import * as i5 from "cax-design-system/inputtext";
8
+ import * as i6 from "cax-design-system/button";
9
+ import * as i7 from "cax-design-system/api";
10
+ import * as i8 from "cax-design-system/chip";
11
+ import * as i9 from "cax-design-system/overlay";
12
+ import * as i10 from "cax-design-system/avatar";
13
+ export class CommentboxComponent {
14
+ sanitizer;
15
+ comments = [];
16
+ mentionSuggestions = [];
17
+ hashtagSuggestions = [];
18
+ sidebarHeader;
19
+ isAdmin = true;
20
+ commentAdded = new EventEmitter();
21
+ fileSelected = new EventEmitter();
22
+ fileDownload = new EventEmitter();
23
+ visibleChange = new EventEmitter();
24
+ newComment = '';
25
+ isMentioning = false;
26
+ isHashtagging = false;
27
+ suggestions = [];
28
+ selectedSuggestion = null;
29
+ selectedSuggestionIndex = -1;
30
+ filteredSuggestions = [];
31
+ currentTokenType = null;
32
+ cursorPosition = 0;
33
+ fileInput;
34
+ suggestionPanel;
35
+ inputText;
36
+ commentsList;
37
+ countChip;
38
+ selectedFiles = [];
39
+ selectedFilesMap = new Map();
40
+ today = new Date();
41
+ overlayVisible = false;
42
+ filesOverlayVisible = false;
43
+ overlayPosition = { top: 0, left: 0 };
44
+ dateUpdateInterval;
45
+ // Keep track of should auto scroll
46
+ shouldAutoScroll = true;
47
+ isUserScrolling = false;
48
+ // Add new property for mutation observer
49
+ observer;
50
+ constructor(sanitizer) {
51
+ this.sanitizer = sanitizer;
52
+ this.updateCurrentDate();
53
+ this.dateUpdateInterval = setInterval(() => this.updateCurrentDate(), 60000);
54
+ // Initialize observer
55
+ this.observer = new MutationObserver(() => this.forceScrollToBottom());
56
+ }
57
+ ngAfterViewInit() {
58
+ setTimeout(() => {
59
+ this.forceScrollToBottom();
60
+ }, 100);
61
+ // Set up observer to auto-scroll when content changes
62
+ if (this.commentsList?.nativeElement) {
63
+ this.observer.observe(this.commentsList.nativeElement, {
64
+ childList: true,
65
+ subtree: true,
66
+ characterData: true
67
+ });
68
+ }
69
+ }
70
+ ngOnDestroy() {
71
+ if (this.dateUpdateInterval) {
72
+ clearInterval(this.dateUpdateInterval);
73
+ }
74
+ // Disconnect the observer
75
+ this.observer.disconnect();
76
+ // Remove event listeners
77
+ document.removeEventListener('click', this.handleClickOutside);
78
+ }
79
+ updateCurrentDate() {
80
+ this.today = new Date();
81
+ }
82
+ formatDate(date) {
83
+ return date.toLocaleDateString(undefined, {
84
+ day: '2-digit',
85
+ month: '2-digit',
86
+ year: 'numeric',
87
+ timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
88
+ });
89
+ }
90
+ formatMessageWithTags(text) {
91
+ if (!text)
92
+ return '';
93
+ const sanitizedText = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
94
+ const htmlContent = sanitizedText.replace(/(@\w+|#\w+)/g, (match) => {
95
+ if (match.startsWith('@')) {
96
+ return `<span class="mention" style="color: #0C4AF3; font-weight: 600;">${match}</span>`;
97
+ }
98
+ else if (match.startsWith('#')) {
99
+ return `<span class="hashtag" style="color: #0C4AF3; font-weight: 600;">${match}</span>`;
100
+ }
101
+ return match;
102
+ });
103
+ return this.sanitizer.bypassSecurityTrustHtml(htmlContent);
104
+ }
105
+ addComment() {
106
+ if (this.newComment.trim() || this.selectedFiles.length > 0) {
107
+ const newComment = {
108
+ text: this.newComment,
109
+ date: new Date(),
110
+ files: this.selectedFiles.length > 0 ? [...this.selectedFiles] : undefined,
111
+ isAdmin: this.isAdmin,
112
+ sender: this.isAdmin ? 'System Admin' : 'User'
113
+ };
114
+ this.comments = [...this.comments, newComment];
115
+ this.commentAdded.emit(newComment);
116
+ this.newComment = '';
117
+ this.selectedFiles = [];
118
+ this.selectedFilesMap.clear();
119
+ this.filesOverlayVisible = false;
120
+ if (this.suggestionPanel?.nativeElement) {
121
+ this.suggestionPanel.nativeElement.style.display = 'none';
122
+ }
123
+ // Always scroll to bottom immediately
124
+ this.scrollToBottom(true);
125
+ }
126
+ }
127
+ forceScrollToBottom() {
128
+ if (!this.commentsList?.nativeElement)
129
+ return;
130
+ const element = this.commentsList.nativeElement;
131
+ requestAnimationFrame(() => {
132
+ try {
133
+ // Force immediate scroll
134
+ element.scrollTop = element.scrollHeight;
135
+ }
136
+ catch (err) {
137
+ console.error('Scroll error:', err);
138
+ }
139
+ });
140
+ }
141
+ scrollToBottom(force = false) {
142
+ if (force) {
143
+ this.forceScrollToBottom();
144
+ return;
145
+ }
146
+ if (!this.commentsList?.nativeElement)
147
+ return;
148
+ const element = this.commentsList.nativeElement;
149
+ // Use double RAF for reliable scrolling
150
+ requestAnimationFrame(() => {
151
+ requestAnimationFrame(() => {
152
+ try {
153
+ // Force immediate scroll for new comments
154
+ element.scrollTop = element.scrollHeight;
155
+ // Use smooth scrolling after initial jump
156
+ element.scrollTo({
157
+ top: element.scrollHeight,
158
+ behavior: 'smooth'
159
+ });
160
+ }
161
+ catch (err) {
162
+ element.scrollTop = element.scrollHeight;
163
+ }
164
+ });
165
+ });
166
+ }
167
+ set visible(value) {
168
+ if (this._visible !== value) {
169
+ this._visible = value;
170
+ this.visibleChange.emit(this._visible);
171
+ if (this._visible) {
172
+ this.shouldAutoScroll = true;
173
+ setTimeout(() => this.scrollToBottom(true), 300);
174
+ }
175
+ }
176
+ }
177
+ get visible() {
178
+ return this._visible;
179
+ }
180
+ _visible = false;
181
+ toggleComments() {
182
+ this.visible = !this.visible;
183
+ }
184
+ onSidebarHide() {
185
+ this._visible = false;
186
+ this.visibleChange.emit(false);
187
+ }
188
+ onDocumentClick(event) {
189
+ const target = event.target;
190
+ const isInputClick = this.inputText?.nativeElement?.contains(target);
191
+ const isPanelClick = this.suggestionPanel?.nativeElement?.contains(target);
192
+ if (!isInputClick && !isPanelClick) {
193
+ this.overlayVisible = false;
194
+ this.currentTokenType = null;
195
+ this.filteredSuggestions = [];
196
+ }
197
+ }
198
+ handleKeyUp(event) {
199
+ // Update cursor position on every key press
200
+ const input = event.target;
201
+ this.cursorPosition = input.selectionStart || 0;
202
+ if (event.key === 'Escape') {
203
+ this.overlayVisible = false;
204
+ this.currentTokenType = null;
205
+ this.filteredSuggestions = [];
206
+ return;
207
+ }
208
+ if (event.key === '@' || event.key === '#') {
209
+ this.currentTokenType = event.key === '@' ? 'mention' : 'hashtag';
210
+ this.filteredSuggestions = this.currentTokenType === 'mention' ? this.mentionSuggestions : this.hashtagSuggestions;
211
+ this.selectedSuggestionIndex = 0;
212
+ const rect = input.getBoundingClientRect();
213
+ const cursorPosition = this.getCursorPosition(input);
214
+ this.overlayVisible = true;
215
+ setTimeout(() => {
216
+ const panel = this.suggestionPanel?.nativeElement;
217
+ if (panel) {
218
+ panel.style.left = `${rect.left + cursorPosition.left}px`;
219
+ panel.style.top = `${rect.top - 10}px`;
220
+ }
221
+ });
222
+ }
223
+ if (this.currentTokenType) {
224
+ const token = this.getTokenAtCursor(input.value, this.cursorPosition);
225
+ if (token) {
226
+ const searchTerm = token.slice(1).toLowerCase();
227
+ this.filteredSuggestions = (this.currentTokenType === 'mention' ? this.mentionSuggestions : this.hashtagSuggestions).filter((item) => item.name.toLowerCase().includes(searchTerm) || item.id.toLowerCase().includes(searchTerm));
228
+ if (this.filteredSuggestions.length > 0) {
229
+ this.overlayVisible = true;
230
+ // Only reset selection index if we have new suggestions
231
+ if (this.selectedSuggestionIndex < 0 || this.selectedSuggestionIndex >= this.filteredSuggestions.length) {
232
+ this.selectedSuggestionIndex = 0;
233
+ }
234
+ }
235
+ else {
236
+ this.overlayVisible = false;
237
+ this.selectedSuggestionIndex = -1;
238
+ }
239
+ }
240
+ else {
241
+ this.overlayVisible = false;
242
+ this.currentTokenType = null;
243
+ }
244
+ }
245
+ }
246
+ getTokenAtCursor(text, cursorPos) {
247
+ const beforeCursor = text.slice(0, cursorPos);
248
+ const match = beforeCursor.match(/[@#][^\s]*$/);
249
+ return match ? match[0] : null;
250
+ }
251
+ getWordAtPosition(text, position) {
252
+ const left = text.slice(0, position).search(/[@#][^\s]*$/);
253
+ if (left === -1)
254
+ return '';
255
+ return text.slice(left, position);
256
+ }
257
+ selectSuggestion(suggestion) {
258
+ const input = this.newComment;
259
+ const wordStart = input.slice(0, this.cursorPosition).search(/[@#][^\s]*$/);
260
+ this.newComment = input.slice(0, wordStart) + suggestion.value + ' ' + input.slice(this.cursorPosition);
261
+ this.isMentioning = false;
262
+ this.isHashtagging = false;
263
+ }
264
+ onSuggestionSelect(item) {
265
+ const input = this.newComment;
266
+ const beforeCursor = input.slice(0, this.cursorPosition);
267
+ const afterCursor = input.slice(this.cursorPosition);
268
+ const lastTokenIndex = Math.max(beforeCursor.lastIndexOf('@'), beforeCursor.lastIndexOf('#'));
269
+ if (lastTokenIndex >= 0) {
270
+ // Insert the suggestion at the cursor position
271
+ this.newComment = beforeCursor.slice(0, lastTokenIndex) + item.id + ' ' + afterCursor;
272
+ }
273
+ this.suggestionPanel.nativeElement.style.display = 'none';
274
+ this.overlayVisible = false;
275
+ this.currentTokenType = null;
276
+ this.filteredSuggestions = [];
277
+ this.selectedSuggestionIndex = -1;
278
+ setTimeout(() => {
279
+ const inputEl = this.inputText.nativeElement.querySelector('input');
280
+ if (inputEl) {
281
+ inputEl.focus();
282
+ }
283
+ });
284
+ }
285
+ onSuggestionPanelHide() {
286
+ this.overlayVisible = false;
287
+ this.currentTokenType = null;
288
+ this.filteredSuggestions = [];
289
+ this.selectedSuggestionIndex = -1;
290
+ }
291
+ getCursorPosition(input) {
292
+ const selectionStart = input.selectionStart || 0;
293
+ const textBeforeCursor = input.value.substring(0, selectionStart);
294
+ const span = document.createElement('span');
295
+ span.textContent = textBeforeCursor;
296
+ span.style.cssText = window.getComputedStyle(input, null).cssText;
297
+ span.style.visibility = 'hidden';
298
+ document.body.appendChild(span);
299
+ const position = {
300
+ left: span.offsetWidth,
301
+ top: span.offsetHeight
302
+ };
303
+ document.body.removeChild(span);
304
+ return position;
305
+ }
306
+ onFileIconClick(event) {
307
+ event?.preventDefault();
308
+ event?.stopPropagation();
309
+ if (this.fileInput?.nativeElement) {
310
+ this.fileInput.nativeElement.click();
311
+ }
312
+ }
313
+ onFileSelect(event) {
314
+ const input = event.target;
315
+ if (input.files && input.files.length > 0) {
316
+ Array.from(input.files).forEach((file) => {
317
+ // Check if file already exists in selection
318
+ const fileExists = this.selectedFiles.some((existingFile) => existingFile.name === file.name && existingFile.size === this.formatFileSize(file.size));
319
+ if (!fileExists) {
320
+ const fileInfo = {
321
+ name: file.name,
322
+ size: this.formatFileSize(file.size)
323
+ };
324
+ this.selectedFiles.push(fileInfo);
325
+ this.selectedFilesMap.set(this.selectedFiles.length - 1, fileInfo);
326
+ this.fileSelected.emit(file);
327
+ }
328
+ });
329
+ input.value = '';
330
+ const inputEl = document.querySelector('.chat-input input');
331
+ if (inputEl instanceof HTMLElement) {
332
+ inputEl.focus();
333
+ }
334
+ }
335
+ }
336
+ updateFileState(index, fromChip = true) {
337
+ const actualIndex = fromChip ? index : index + 4;
338
+ this.selectedFiles = this.selectedFiles.filter((_, i) => i !== actualIndex);
339
+ this.selectedFilesMap.clear();
340
+ this.selectedFiles.forEach((file, i) => {
341
+ this.selectedFilesMap.set(i, file);
342
+ });
343
+ }
344
+ removeFile(index, fromChip = true) {
345
+ this.updateFileState(index, fromChip);
346
+ if (this.selectedFiles.length <= 4) {
347
+ this.hideFilesOverlay();
348
+ }
349
+ }
350
+ getOverflowCount() {
351
+ // Return count of files beyond the first 4
352
+ return Math.max(0, this.selectedFiles.length - 4);
353
+ }
354
+ showFilesOverlay(event) {
355
+ const target = event.currentTarget;
356
+ const rect = target.getBoundingClientRect();
357
+ // Position the overlay below the count chip
358
+ this.overlayPosition = {
359
+ top: rect.bottom + 5,
360
+ left: rect.left - 250 + rect.width / 2 // Center the overlay horizontally
361
+ };
362
+ this.filesOverlayVisible = true;
363
+ // Add a click outside listener to close the overlay
364
+ setTimeout(() => {
365
+ document.addEventListener('click', this.handleClickOutside);
366
+ });
367
+ }
368
+ hideFilesOverlay() {
369
+ this.filesOverlayVisible = false;
370
+ document.removeEventListener('click', this.handleClickOutside);
371
+ }
372
+ handleClickOutside = (event) => {
373
+ const target = event.target;
374
+ const overlay = document.querySelector('.files-overlay');
375
+ const countChip = document.querySelector('.count-chip');
376
+ if (overlay && !overlay.contains(target) && countChip && !countChip.contains(target)) {
377
+ this.hideFilesOverlay();
378
+ }
379
+ };
380
+ formatFileSize(bytes) {
381
+ if (bytes === 0)
382
+ return '0 Bytes';
383
+ const k = 1024;
384
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
385
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
386
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
387
+ }
388
+ showSuggestions(_event, type) {
389
+ this.currentTokenType = type;
390
+ this.filteredSuggestions = type === 'mention' ? this.mentionSuggestions : this.hashtagSuggestions;
391
+ if (this.suggestionPanel) {
392
+ this.suggestionPanel.nativeElement.style.display = 'block';
393
+ }
394
+ }
395
+ onKeyDown(event) {
396
+ // If suggestions are visible, handle keyboard navigation
397
+ if (this.overlayVisible && this.filteredSuggestions.length > 0) {
398
+ switch (event.key) {
399
+ case 'ArrowDown':
400
+ event.preventDefault();
401
+ this.selectedSuggestionIndex = Math.min(this.selectedSuggestionIndex + 1, this.filteredSuggestions.length - 1);
402
+ this.scrollSuggestionIntoView();
403
+ break;
404
+ case 'ArrowUp':
405
+ event.preventDefault();
406
+ this.selectedSuggestionIndex = Math.max(this.selectedSuggestionIndex - 1, 0);
407
+ this.scrollSuggestionIntoView();
408
+ break;
409
+ case 'Tab':
410
+ event.preventDefault();
411
+ if (event.shiftKey) {
412
+ // Shift+Tab - move up
413
+ this.selectedSuggestionIndex = Math.max(this.selectedSuggestionIndex - 1, 0);
414
+ }
415
+ else {
416
+ // Tab - move down
417
+ this.selectedSuggestionIndex = Math.min(this.selectedSuggestionIndex + 1, this.filteredSuggestions.length - 1);
418
+ }
419
+ this.scrollSuggestionIntoView();
420
+ break;
421
+ case 'Enter':
422
+ event.preventDefault();
423
+ if (this.selectedSuggestionIndex >= 0) {
424
+ this.onSuggestionSelect(this.filteredSuggestions[this.selectedSuggestionIndex]);
425
+ }
426
+ break;
427
+ case 'Escape':
428
+ event.preventDefault();
429
+ this.onSuggestionPanelHide();
430
+ break;
431
+ }
432
+ return;
433
+ }
434
+ // If no suggestions are visible, handle normal enter key press
435
+ if (event.key === 'Enter' && !event.shiftKey) {
436
+ event.preventDefault();
437
+ this.addComment();
438
+ }
439
+ }
440
+ // Helper method to scroll the selected suggestion into view
441
+ scrollSuggestionIntoView() {
442
+ setTimeout(() => {
443
+ const suggestionList = this.suggestionPanel?.nativeElement.querySelector('.suggestion-list');
444
+ const selectedItem = suggestionList?.querySelector('.suggestion-item.selected');
445
+ if (suggestionList && selectedItem) {
446
+ const listRect = suggestionList.getBoundingClientRect();
447
+ const itemRect = selectedItem.getBoundingClientRect();
448
+ // Check if the selected item is outside the visible area
449
+ if (itemRect.bottom > listRect.bottom) {
450
+ // Item is below the visible area
451
+ selectedItem.scrollIntoView({ block: 'end', behavior: 'smooth' });
452
+ }
453
+ else if (itemRect.top < listRect.top) {
454
+ // Item is above the visible area
455
+ selectedItem.scrollIntoView({ block: 'start', behavior: 'smooth' });
456
+ }
457
+ }
458
+ });
459
+ }
460
+ onFileDownload(file) {
461
+ this.fileDownload.emit(file);
462
+ }
463
+ get groupedComments() {
464
+ return this.comments
465
+ .reduce((groups, comment) => {
466
+ const commentDate = new Date(comment.date);
467
+ commentDate.setHours(0, 0, 0, 0);
468
+ const existingGroup = groups.find((group) => {
469
+ const groupDate = new Date(group.date);
470
+ groupDate.setHours(0, 0, 0, 0);
471
+ return groupDate.getTime() === commentDate.getTime();
472
+ });
473
+ if (existingGroup) {
474
+ existingGroup.items.push(comment);
475
+ }
476
+ else {
477
+ groups.push({
478
+ date: commentDate,
479
+ items: [comment]
480
+ });
481
+ }
482
+ return groups;
483
+ }, [])
484
+ .sort((a, b) => a.date.getTime() - b.date.getTime());
485
+ }
486
+ getShortFileName(filename) {
487
+ if (filename.length <= 4)
488
+ return filename;
489
+ // Get file extension
490
+ const lastDotIndex = filename.lastIndexOf('.');
491
+ const extension = lastDotIndex !== -1 ? filename.substring(lastDotIndex) : '';
492
+ // Truncate the name part and add the extension
493
+ const namePart = filename.substring(0, lastDotIndex !== -1 ? lastDotIndex : filename.length);
494
+ return namePart.substring(0, 4) + '..' + extension;
495
+ }
496
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CommentboxComponent, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
497
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: CommentboxComponent, selector: "cax-comments", inputs: { comments: "comments", mentionSuggestions: "mentionSuggestions", hashtagSuggestions: "hashtagSuggestions", sidebarHeader: "sidebarHeader", isAdmin: "isAdmin", visible: "visible" }, outputs: { commentAdded: "commentAdded", fileSelected: "fileSelected", fileDownload: "fileDownload", visibleChange: "visibleChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "suggestionPanel", first: true, predicate: ["suggestionPanel"], descendants: true }, { propertyName: "inputText", first: true, predicate: ["inputText"], descendants: true }, { propertyName: "commentsList", first: true, predicate: ["commentsList"], descendants: true }, { propertyName: "countChip", first: true, predicate: ["countChip"], descendants: true }], ngImport: i0, template: "<cax-sidebar [(visible)]=\"visible\" [position]=\"'right'\" [baseZIndex]=\"10000\" (onHide)=\"onSidebarHide()\" [headerText]=\"sidebarHeader\">\r\n <ng-template caxTemplate=\"content\">\r\n <div class=\"cax-comments-container\">\r\n <div class=\"cax-comments-list\" #commentsList>\r\n <ng-container *ngFor=\"let group of groupedComments\">\r\n <div class=\"cax-date-header\">{{ formatDate(group.date) }}</div>\r\n <div\r\n class=\"cax-comment-item\"\r\n *ngFor=\"let comment of group.items; let i = index\"\r\n [ngClass]=\"{\r\n 'cax-user-comment': !comment.isAdmin,\r\n 'cax-admin-comment': comment.isAdmin,\r\n 'consecutive-message': i > 0 && comment.isAdmin === group.items[i-1].isAdmin && comment.sender === group.items[i-1].sender,\r\n 'new-sender': i > 0 && comment.sender !== group.items[i-1].sender,\r\n 'new-date': i === 0 && group.items.length > 0\r\n }\"\r\n >\r\n <!-- User Message (Left Aligned) -->\r\n <ng-container *ngIf=\"!comment.isAdmin\">\r\n <div class=\"cax-commentbox-avatar-container\" *ngIf=\"i === 0 || group.items[i-1].sender !== comment.sender\">\r\n <cax-avatar [label]=\"comment.sender?.substring(0, 2).toUpperCase() || 'U'\" [avatarSize]=\"'xs'\" [shape]=\"'circle'\" styleclass=\"cax-commentbox-avatar\"> </cax-avatar>\r\n </div>\r\n <div class=\"cax-comment-content\" [class.no-avatar]=\"i > 0 && group.items[i-1].sender === comment.sender\">\r\n <div class=\"cax-comment-sender\" *ngIf=\"i === 0 || group.items[i-1].sender !== comment.sender\">{{comment.sender}}</div>\r\n <div class=\"cax-file-attachment\" *ngIf=\"comment.files?.length\">\r\n <div *ngFor=\"let file of comment.files\" class=\"file-item\">\r\n <div class=\"file-details\">\r\n <span class=\"file-name\">{{ file.name.slice(0, 20) }}{{ file.name.includes('.') ? '.' + file.name.split('.').pop() : '' }}</span>\r\n <span class=\"file-size\">{{file.size}}</span>\r\n </div>\r\n <i class=\"cax cax-download\" (click)=\"onFileDownload(file)\" role=\"button\" tabindex=\"0\"></i>\r\n </div>\r\n </div>\r\n <div class=\"cax-comment-text\" [innerHTML]=\"formatMessageWithTags(comment.text)\"></div>\r\n <span class=\"cax-comment-date\">{{ comment.date | date: 'shortTime' }}</span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Admin Message (Right Aligned) -->\r\n <ng-container *ngIf=\"comment.isAdmin\">\r\n <div class=\"cax-comment-content admin\">\r\n <div class=\"cax-file-attachment\" *ngIf=\"comment.files?.length\">\r\n <div *ngFor=\"let file of comment.files\" class=\"file-item\">\r\n <div class=\"file-details\">\r\n <span class=\"file-name\">{{ file.name.slice(0, 20) }}{{ file.name.includes('.') ? '.' + file.name.split('.').pop() : '' }}</span>\r\n <span class=\"file-size\">{{file.size}}</span>\r\n </div>\r\n <i class=\"cax cax-download\" (click)=\"onFileDownload(file)\" role=\"button\" tabindex=\"0\"></i>\r\n </div>\r\n </div>\r\n <div class=\"cax-comment-text\" [innerHTML]=\"formatMessageWithTags(comment.text)\"></div>\r\n <span class=\"cax-comment-date\">{{ comment.date | date: 'shortTime' }}</span>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <cax-overlay #suggestionPanel [(visible)]=\"overlayVisible\" [appendTo]=\"inputText\" (onHide)=\"onSuggestionPanelHide()\" [styleClass]=\"'suggestion-panel'\">\r\n <div class=\"suggestion-list\">\r\n <div *ngFor=\"let item of filteredSuggestions; let i = index\" class=\"suggestion-item\" [ngClass]=\"{'selected': selectedSuggestionIndex === i}\" (click)=\"onSuggestionSelect(item)\" (mouseenter)=\"selectedSuggestionIndex = i\">\r\n <span class=\"suggestion-label\">{{item.name}}</span>\r\n <small class=\"suggestion-id\" *ngIf=\"currentTokenType === 'mention'\">{{item.id}}</small>\r\n </div>\r\n </div>\r\n </cax-overlay>\r\n <cax-overlay\r\n [(visible)]=\"filesOverlayVisible\"\r\n [appendTo]=\"countChip\"\r\n [showTransitionOptions]=\"'0.12s ease-out'\"\r\n [hideTransitionOptions]=\"'0.1s ease-in'\"\r\n [style]=\"{ width: '224px', right: '5%' }\"\r\n styleClass=\"files-list-overlay\"\r\n (onHide)=\"hideFilesOverlay()\"\r\n >\r\n <div class=\"files-overlay-content\">\r\n <div *ngFor=\"let file of selectedFiles.slice(4); let i = index\" class=\"file-item\">\r\n <span class=\"file-name\">{{getShortFileName(file.name)}}</span>\r\n <i class=\"cax cax-close-circle\" (click)=\"removeFile(i + 4)\"></i>\r\n </div>\r\n </div>\r\n </cax-overlay>\r\n\r\n <ng-template caxTemplate=\"footer\">\r\n <div class=\"chat-footer\">\r\n <div class=\"selected-files\" *ngIf=\"selectedFiles.length > 0\">\r\n <cax-chip *ngFor=\"let file of selectedFiles.slice(0, 4); let i = index\" [label]=\"getShortFileName(file.name)\" [removable]=\"true\" [size]=\"'lg'\" (onRemove)=\"removeFile(i, true)\">\r\n <ng-template caxTemplate=\"content\">\r\n <i class=\"cax cax-paperclip\"></i>\r\n </ng-template>\r\n </cax-chip>\r\n <cax-chip #countChip *ngIf=\"selectedFiles.length > 4\" [label]=\"'+' + getOverflowCount()\" [size]=\"'lg'\" (mouseenter)=\"showFilesOverlay($event)\"> </cax-chip>\r\n </div>\r\n <div class=\"cax-chat-input-container\">\r\n <div class=\"input-wrapper\">\r\n <cax-inputtext\r\n [(ngModel)]=\"newComment\"\r\n [size]=\"'lg'\"\r\n [rightIcon]=\"true\"\r\n [clearIcon]=\"false\"\r\n [rightIconClass]=\"'cax cax-paperclip'\"\r\n [rightIconClickable]=\"true\"\r\n (rightIconClick)=\"onFileIconClick($event)\"\r\n placeholder=\"Comment or mention others with @, \u2018#\u2019 for columns\"\r\n (keyup)=\"handleKeyUp($event)\"\r\n (keydown)=\"onKeyDown($event)\"\r\n [class]=\"{'chat-input': true, 'admin-input': isAdminSender}\"\r\n [style]=\"{'border-radius': '8px', background: '#ffffff'}\"\r\n #inputText\r\n >\r\n </cax-inputtext>\r\n </div>\r\n\r\n <cax-button [icon]=\"'cax cax-plain'\" [severity]=\"'primary'\" [size]=\"'large'\" (click)=\"addComment()\" [disabled]=\"!newComment.trim() && selectedFiles.length === 0\" class=\"send-button\"> </cax-button>\r\n </div>\r\n\r\n <input #fileInput type=\"file\" (change)=\"onFileSelect($event)\" style=\"display: none\" accept=\"*/*\" multiple />\r\n </div>\r\n </ng-template>\r\n</cax-sidebar>\r\n", styles: ["@layer cax{.cax-comments-list{display:flex;flex-direction:column;gap:4px;flex:1;overflow-y:auto;overflow-x:hidden;height:100%;padding-bottom:0;will-change:transform;transform:translateZ(0);backface-visibility:hidden;-webkit-backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:rgba(94,92,92,.3) transparent}.cax-comments-list:after{content:\"\";display:block;min-height:20px;scroll-snap-align:end}.cax-comments-list::-webkit-scrollbar-track{background:transparent}.cax-comments-list::-webkit-scrollbar-thumb{background-color:#5553531a;border-radius:4px;border:2px solid transparent;background-clip:padding-box}.cax-comment-item{display:flex;align-items:flex-end;max-width:85%;gap:4px}.cax-comment-item.consecutive-message{margin-top:0}.cax-comment-item.new-sender{margin-top:12px}.cax-comment-item.new-date{margin-top:0}.cax-user-comment{align-self:flex-start;display:flex;flex-direction:row;text-align:left}.cax-user-comment .cax-commentbox-avatar-container{display:flex;align-items:flex-end}.cax-user-comment .cax-comment-content{margin-bottom:0;display:flex;flex-direction:column;border-radius:12px 12px 12px 0}.cax-user-comment .cax-comment-content.no-avatar{border-radius:12px;margin-left:25px}.cax-user-comment .cax-comment-content .cax-comment-sender{font-size:14px;font-weight:600;color:var(--neutral-900);margin-bottom:0;line-height:20px}.cax-user-comment.consecutive-message .cax-comment-content{border-radius:12px}.cax-admin-comment{align-self:flex-end;display:flex;flex-direction:row;justify-content:flex-end;text-align:right}.cax-admin-comment .cax-commentbox-avatar-container{display:flex;align-items:flex-end}.cax-admin-comment .cax-comment-content{margin-bottom:0;display:flex;flex-direction:column;border-radius:12px 12px 0;text-align:left}.cax-admin-comment .cax-comment-content .cax-comment-sender{font-size:14px;font-weight:600;color:var(--neutral-900);margin-bottom:0;line-height:20px}.cax-admin-comment.consecutive-message .cax-comment-content{border-radius:12px}.cax-commentbox-avatar{width:32px;height:32px;border-radius:50%;margin:0 8px}.cax-comment-content{background:var(--white-100);border-radius:12px 12px 12px 0;padding:8px;max-width:100%;word-wrap:break-word;display:flex;flex-direction:column;box-shadow:0 2px 4px #0000000d}.cax-comment-content .cax-comment-text{font-weight:400;font-size:14px;line-height:20px}.cax-comment-content .cax-comment-text ::ng-deep .mention{display:inline-block;font-weight:600;color:var(--primary-500)}.cax-comment-content .cax-comment-text ::ng-deep .hashtag{display:inline-block;font-weight:600;color:var(--primary-500)}.cax-comment-content .cax-comment-sender{font-size:14px;font-weight:600;color:var(--neutral-900);margin-bottom:0;line-height:20px}.cax-file-attachment{margin-bottom:12px}.cax-file-attachment .file-item{display:flex;align-items:center;gap:12px;border-color:1px solid var(--neutral-150);padding:10px 16px;background:var(--neutral-75);border-radius:8px;cursor:pointer;margin-bottom:8px}.cax-file-attachment .file-item .file-details{display:flex;flex:1;align-items:center;gap:12px}.cax-file-attachment .file-item .file-name{color:var(--neutral-900);font-weight:500;font-size:14px;line-height:20px;flex:1;white-space:nowrap;overflow:hidden}.cax-file-attachment .file-item .file-size{color:var(--neutral-600);font-weight:400;font-size:12px;line-height:18px;margin-right:8px}.cax-file-attachment .file-item i{color:var(--neutral-900);font-size:1.1rem;margin-left:auto;order:2}.cax-file-attachment .file-item i.cax-download{cursor:pointer;transition:color .2s ease}.cax-file-attachment .file-item i.cax-download:hover{color:var(--primary-600)}.cax-file-attachment .file-item i.cax-download:active{color:var(--primary-700)}.cax-file-attachment .file-item:last-child{margin-bottom:0}.cax-file-attachment:last-child{margin-bottom:0}.cax-comment-date{font-weight:400;font-size:12px;line-height:18px;color:var(--neutral-600);align-self:flex-end}.cax-chat-input-container{display:flex;gap:.5rem}.cax-chat-input-container .chat-input{flex:1}.cax-chat-input-container .send-button{cursor:pointer}.input-wrapper{position:relative;flex:1;display:flex;flex-direction:column}.cax-date-header{text-align:center;font-size:12px;font-weight:500;line-height:18px;color:var(--neutral-700);background:var(--neutral-100);align-self:center;width:fit-content;padding:4px 12px;border-radius:4px;margin:11px 0;position:relative;z-index:1}.cax-date-header:first-child{margin-top:0}.cax-comments-container{display:flex;flex-direction:column;height:calc(100vh - 200px);overflow:hidden;position:relative;transform:translateZ(0);backface-visibility:hidden}.selected-files{display:flex;flex-wrap:wrap;gap:.5rem;padding:0 0 5px;position:relative}.selected-files .cax-chip{background:var(--neutral-100)}.selected-files .cax-chip i{margin-right:.5rem}.selected-files .files-overlay{position:absolute;background:var(--white-100);border-radius:8px;box-shadow:0 4px 12px #00000026;width:300px;max-height:400px;z-index:1000;overflow:hidden;border:1px solid var(--neutral-200)}.selected-files .files-overlay .files-overlay-header{padding:12px 16px;font-weight:600;font-size:14px;border-bottom:1px solid var(--neutral-100);background:var(--neutral-50)}.selected-files .files-overlay .files-overlay-content{max-height:350px;overflow-y:auto;padding:8px 0}.selected-files .files-overlay .files-overlay-content .file-item{display:flex;align-items:center;padding:8px 16px;transition:background-color .2s ease}.selected-files .files-overlay .files-overlay-content .file-item:hover{background-color:var(--neutral-50)}.selected-files .files-overlay .files-overlay-content .file-item i.cax-paperclip{color:var(--neutral-600);margin-right:8px}.selected-files .files-overlay .files-overlay-content .file-item .file-name{flex:1;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:8px}.selected-files .files-overlay .files-overlay-content .file-item .file-size{color:var(--neutral-600);font-size:12px;margin-right:8px}.selected-files .files-overlay .files-overlay-content .file-item i.cax-times{color:var(--neutral-600);cursor:pointer;transition:color .2s ease}.selected-files .files-overlay .files-overlay-content .file-item i.cax-times:hover{color:var --error-500}.selected-files :deep(.file-chip){background:var(--neutral-50);border:1px solid var(--neutral-100)}.selected-files :deep(.file-chip) .file-details{display:flex;align-items:center;gap:8px}.selected-files :deep(.file-chip) i{color:var(--primary-500);margin-right:8px}.selected-files :deep(.file-chip) .file-name{font-weight:500}.selected-files :deep(.file-chip) .file-size{color:var(--neutral-600);font-size:.8rem}:host ::ng-deep .cax-sidebar{width:589px!important;border:1px solid var(--neutral-200)!important}:host ::ng-deep .cax-sidebar .cax-sidebar-content{display:flex;flex-direction:column;background:var(--neutral-25);padding:24px 8px!important}:host ::ng-deep .cax-sidebar .cax-sidebar-footer{padding:12px!important;background:var(--neutral-50);border-top:1px solid var(--neutral-200)}:host ::ng-deep .cax-sidebar .cax-sidebar-header{border-bottom:1px solid var(--neutral-200);background:var(--neutral-50);padding:16px 24px!important}:host ::ng-deep .cax-overlay{position:absolute;bottom:0!important;top:unset!important;left:unset!important}:host ::ng-deep .suggestion-panel{background:var(--white-100);box-shadow:0 2px 8px #0000001a;z-index:9999;padding:12px 4px;margin-left:20px;width:224px;border-radius:8px;border:1px solid var(--neutral-200)}:host ::ng-deep .suggestion-panel .suggestion-list{max-height:200px;overflow-y:auto;will-change:transform;transform:translateZ(0);backface-visibility:hidden;-webkit-backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:rgba(94,92,92,.3) transparent}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item{padding:6px 8px;cursor:pointer;display:flex;justify-content:space-between;transition:background-color .2s ease;align-items:center}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item:hover{background-color:var(--neutral-50)}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item.selected{background-color:var(--neutral-50)}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item .suggestion-label{font-weight:500}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item .suggestion-id{color:var(--neutral-600);font-size:.85em}:host ::ng-deep .suggestion-panel .suggestion-list:after{content:\"\";display:block;min-height:20px;scroll-snap-align:end}:host ::ng-deep .suggestion-panel .suggestion-list::-webkit-scrollbar-track{background:transparent}:host ::ng-deep .suggestion-panel .suggestion-list::-webkit-scrollbar-thumb{background-color:#5553531a;border-radius:4px;border:2px solid transparent;background-clip:padding-box}:host ::ng-deep .chat-footer{position:relative;z-index:1}:host ::ng-deep .cax-chat-input-container .chat-input .cax-paperclip{color:var(--neutral-900)!important}:host ::ng-deep .files-list-overlay{border:1px solid var(--neutral-200);background:var(--white-100);box-shadow:0 2px 8px #0000001a;z-index:9999;padding:12px 4px;width:224px;border-radius:8px}:host ::ng-deep .files-list-overlay.cax-overlay{transform-origin:right center!important}:host ::ng-deep .files-list-overlay .files-overlay-content{max-height:200px;overflow-y:auto}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item{transition:background-color .2s ease;padding:6px 8px;cursor:pointer;display:flex;justify-content:space-between;align-items:center;will-change:transform;transform:translateZ(0);backface-visibility:hidden;-webkit-backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:rgba(94,92,92,.3) transparent}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item:hover{background-color:var(--neutral-50)}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item .file-name{flex:1;font-size:14px;font-weight:500;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:8px}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item .file-size{color:var(--neutral-600);font-size:12px;margin-right:8px}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item i.cax-times{color:var(--neutral-600);cursor:pointer;border:1.1rem solid var(--neutral-200);transition:color .2s ease}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item:after{content:\"\";display:block;min-height:20px;scroll-snap-align:end}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item::-webkit-scrollbar-track{background:transparent}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item::-webkit-scrollbar-thumb{background-color:#5553531a;border-radius:4px;border:2px solid transparent;background-clip:padding-box}}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.Sidebar, selector: "cax-sidebar", inputs: ["headerText", "appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "contentTemplate", "headerTemplate", "headlessTemplate", "footerTemplate", "closeIconTemplate", "headerStyle"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "component", type: i5.InputTextComponent, selector: "cax-inputtext", inputs: ["value", "placeholder", "disabled", "maxlength", "successText", "errorText", "showLabel", "leftIcon", "rightIcon", "rightIconClickable", "clearIcon", "label", "iconPath", "disabledIcon", "showIcon", "iconClass", "leftIconClass", "rightIconClass", "invalid", "required", "style", "size", "styleClass"], outputs: ["valueChange", "rightIconClick"] }, { kind: "component", type: i6.Button, selector: "cax-button", inputs: ["type", "iconPos", "icon", "badge", "rightIcon", "leftIcon", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i7.CaxTemplate, selector: "[caxTemplate]", inputs: ["type", "caxTemplate"] }, { kind: "component", type: i8.Chip, selector: "cax-chip", inputs: ["label", "icon", "image", "alt", "style", "styleClass", "removable", "removeIcon", "size", "severity"], outputs: ["onRemove", "onImageError"] }, { kind: "component", type: i9.Overlay, selector: "cax-overlay", inputs: ["visible", "mode", "style", "styleClass", "contentStyle", "contentStyleClass", "target", "appendTo", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "listener", "responsive", "options"], outputs: ["visibleChange", "onBeforeShow", "onShow", "onBeforeHide", "onHide", "onAnimationStart", "onAnimationDone"] }, { kind: "component", type: i10.Avatar, selector: "cax-avatar", inputs: ["label", "icon", "image", "avatarSize", "shape", "style", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }] });
498
+ }
499
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CommentboxComponent, decorators: [{
500
+ type: Component,
501
+ args: [{ selector: 'cax-comments', template: "<cax-sidebar [(visible)]=\"visible\" [position]=\"'right'\" [baseZIndex]=\"10000\" (onHide)=\"onSidebarHide()\" [headerText]=\"sidebarHeader\">\r\n <ng-template caxTemplate=\"content\">\r\n <div class=\"cax-comments-container\">\r\n <div class=\"cax-comments-list\" #commentsList>\r\n <ng-container *ngFor=\"let group of groupedComments\">\r\n <div class=\"cax-date-header\">{{ formatDate(group.date) }}</div>\r\n <div\r\n class=\"cax-comment-item\"\r\n *ngFor=\"let comment of group.items; let i = index\"\r\n [ngClass]=\"{\r\n 'cax-user-comment': !comment.isAdmin,\r\n 'cax-admin-comment': comment.isAdmin,\r\n 'consecutive-message': i > 0 && comment.isAdmin === group.items[i-1].isAdmin && comment.sender === group.items[i-1].sender,\r\n 'new-sender': i > 0 && comment.sender !== group.items[i-1].sender,\r\n 'new-date': i === 0 && group.items.length > 0\r\n }\"\r\n >\r\n <!-- User Message (Left Aligned) -->\r\n <ng-container *ngIf=\"!comment.isAdmin\">\r\n <div class=\"cax-commentbox-avatar-container\" *ngIf=\"i === 0 || group.items[i-1].sender !== comment.sender\">\r\n <cax-avatar [label]=\"comment.sender?.substring(0, 2).toUpperCase() || 'U'\" [avatarSize]=\"'xs'\" [shape]=\"'circle'\" styleclass=\"cax-commentbox-avatar\"> </cax-avatar>\r\n </div>\r\n <div class=\"cax-comment-content\" [class.no-avatar]=\"i > 0 && group.items[i-1].sender === comment.sender\">\r\n <div class=\"cax-comment-sender\" *ngIf=\"i === 0 || group.items[i-1].sender !== comment.sender\">{{comment.sender}}</div>\r\n <div class=\"cax-file-attachment\" *ngIf=\"comment.files?.length\">\r\n <div *ngFor=\"let file of comment.files\" class=\"file-item\">\r\n <div class=\"file-details\">\r\n <span class=\"file-name\">{{ file.name.slice(0, 20) }}{{ file.name.includes('.') ? '.' + file.name.split('.').pop() : '' }}</span>\r\n <span class=\"file-size\">{{file.size}}</span>\r\n </div>\r\n <i class=\"cax cax-download\" (click)=\"onFileDownload(file)\" role=\"button\" tabindex=\"0\"></i>\r\n </div>\r\n </div>\r\n <div class=\"cax-comment-text\" [innerHTML]=\"formatMessageWithTags(comment.text)\"></div>\r\n <span class=\"cax-comment-date\">{{ comment.date | date: 'shortTime' }}</span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Admin Message (Right Aligned) -->\r\n <ng-container *ngIf=\"comment.isAdmin\">\r\n <div class=\"cax-comment-content admin\">\r\n <div class=\"cax-file-attachment\" *ngIf=\"comment.files?.length\">\r\n <div *ngFor=\"let file of comment.files\" class=\"file-item\">\r\n <div class=\"file-details\">\r\n <span class=\"file-name\">{{ file.name.slice(0, 20) }}{{ file.name.includes('.') ? '.' + file.name.split('.').pop() : '' }}</span>\r\n <span class=\"file-size\">{{file.size}}</span>\r\n </div>\r\n <i class=\"cax cax-download\" (click)=\"onFileDownload(file)\" role=\"button\" tabindex=\"0\"></i>\r\n </div>\r\n </div>\r\n <div class=\"cax-comment-text\" [innerHTML]=\"formatMessageWithTags(comment.text)\"></div>\r\n <span class=\"cax-comment-date\">{{ comment.date | date: 'shortTime' }}</span>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <cax-overlay #suggestionPanel [(visible)]=\"overlayVisible\" [appendTo]=\"inputText\" (onHide)=\"onSuggestionPanelHide()\" [styleClass]=\"'suggestion-panel'\">\r\n <div class=\"suggestion-list\">\r\n <div *ngFor=\"let item of filteredSuggestions; let i = index\" class=\"suggestion-item\" [ngClass]=\"{'selected': selectedSuggestionIndex === i}\" (click)=\"onSuggestionSelect(item)\" (mouseenter)=\"selectedSuggestionIndex = i\">\r\n <span class=\"suggestion-label\">{{item.name}}</span>\r\n <small class=\"suggestion-id\" *ngIf=\"currentTokenType === 'mention'\">{{item.id}}</small>\r\n </div>\r\n </div>\r\n </cax-overlay>\r\n <cax-overlay\r\n [(visible)]=\"filesOverlayVisible\"\r\n [appendTo]=\"countChip\"\r\n [showTransitionOptions]=\"'0.12s ease-out'\"\r\n [hideTransitionOptions]=\"'0.1s ease-in'\"\r\n [style]=\"{ width: '224px', right: '5%' }\"\r\n styleClass=\"files-list-overlay\"\r\n (onHide)=\"hideFilesOverlay()\"\r\n >\r\n <div class=\"files-overlay-content\">\r\n <div *ngFor=\"let file of selectedFiles.slice(4); let i = index\" class=\"file-item\">\r\n <span class=\"file-name\">{{getShortFileName(file.name)}}</span>\r\n <i class=\"cax cax-close-circle\" (click)=\"removeFile(i + 4)\"></i>\r\n </div>\r\n </div>\r\n </cax-overlay>\r\n\r\n <ng-template caxTemplate=\"footer\">\r\n <div class=\"chat-footer\">\r\n <div class=\"selected-files\" *ngIf=\"selectedFiles.length > 0\">\r\n <cax-chip *ngFor=\"let file of selectedFiles.slice(0, 4); let i = index\" [label]=\"getShortFileName(file.name)\" [removable]=\"true\" [size]=\"'lg'\" (onRemove)=\"removeFile(i, true)\">\r\n <ng-template caxTemplate=\"content\">\r\n <i class=\"cax cax-paperclip\"></i>\r\n </ng-template>\r\n </cax-chip>\r\n <cax-chip #countChip *ngIf=\"selectedFiles.length > 4\" [label]=\"'+' + getOverflowCount()\" [size]=\"'lg'\" (mouseenter)=\"showFilesOverlay($event)\"> </cax-chip>\r\n </div>\r\n <div class=\"cax-chat-input-container\">\r\n <div class=\"input-wrapper\">\r\n <cax-inputtext\r\n [(ngModel)]=\"newComment\"\r\n [size]=\"'lg'\"\r\n [rightIcon]=\"true\"\r\n [clearIcon]=\"false\"\r\n [rightIconClass]=\"'cax cax-paperclip'\"\r\n [rightIconClickable]=\"true\"\r\n (rightIconClick)=\"onFileIconClick($event)\"\r\n placeholder=\"Comment or mention others with @, \u2018#\u2019 for columns\"\r\n (keyup)=\"handleKeyUp($event)\"\r\n (keydown)=\"onKeyDown($event)\"\r\n [class]=\"{'chat-input': true, 'admin-input': isAdminSender}\"\r\n [style]=\"{'border-radius': '8px', background: '#ffffff'}\"\r\n #inputText\r\n >\r\n </cax-inputtext>\r\n </div>\r\n\r\n <cax-button [icon]=\"'cax cax-plain'\" [severity]=\"'primary'\" [size]=\"'large'\" (click)=\"addComment()\" [disabled]=\"!newComment.trim() && selectedFiles.length === 0\" class=\"send-button\"> </cax-button>\r\n </div>\r\n\r\n <input #fileInput type=\"file\" (change)=\"onFileSelect($event)\" style=\"display: none\" accept=\"*/*\" multiple />\r\n </div>\r\n </ng-template>\r\n</cax-sidebar>\r\n", styles: ["@layer cax{.cax-comments-list{display:flex;flex-direction:column;gap:4px;flex:1;overflow-y:auto;overflow-x:hidden;height:100%;padding-bottom:0;will-change:transform;transform:translateZ(0);backface-visibility:hidden;-webkit-backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:rgba(94,92,92,.3) transparent}.cax-comments-list:after{content:\"\";display:block;min-height:20px;scroll-snap-align:end}.cax-comments-list::-webkit-scrollbar-track{background:transparent}.cax-comments-list::-webkit-scrollbar-thumb{background-color:#5553531a;border-radius:4px;border:2px solid transparent;background-clip:padding-box}.cax-comment-item{display:flex;align-items:flex-end;max-width:85%;gap:4px}.cax-comment-item.consecutive-message{margin-top:0}.cax-comment-item.new-sender{margin-top:12px}.cax-comment-item.new-date{margin-top:0}.cax-user-comment{align-self:flex-start;display:flex;flex-direction:row;text-align:left}.cax-user-comment .cax-commentbox-avatar-container{display:flex;align-items:flex-end}.cax-user-comment .cax-comment-content{margin-bottom:0;display:flex;flex-direction:column;border-radius:12px 12px 12px 0}.cax-user-comment .cax-comment-content.no-avatar{border-radius:12px;margin-left:25px}.cax-user-comment .cax-comment-content .cax-comment-sender{font-size:14px;font-weight:600;color:var(--neutral-900);margin-bottom:0;line-height:20px}.cax-user-comment.consecutive-message .cax-comment-content{border-radius:12px}.cax-admin-comment{align-self:flex-end;display:flex;flex-direction:row;justify-content:flex-end;text-align:right}.cax-admin-comment .cax-commentbox-avatar-container{display:flex;align-items:flex-end}.cax-admin-comment .cax-comment-content{margin-bottom:0;display:flex;flex-direction:column;border-radius:12px 12px 0;text-align:left}.cax-admin-comment .cax-comment-content .cax-comment-sender{font-size:14px;font-weight:600;color:var(--neutral-900);margin-bottom:0;line-height:20px}.cax-admin-comment.consecutive-message .cax-comment-content{border-radius:12px}.cax-commentbox-avatar{width:32px;height:32px;border-radius:50%;margin:0 8px}.cax-comment-content{background:var(--white-100);border-radius:12px 12px 12px 0;padding:8px;max-width:100%;word-wrap:break-word;display:flex;flex-direction:column;box-shadow:0 2px 4px #0000000d}.cax-comment-content .cax-comment-text{font-weight:400;font-size:14px;line-height:20px}.cax-comment-content .cax-comment-text ::ng-deep .mention{display:inline-block;font-weight:600;color:var(--primary-500)}.cax-comment-content .cax-comment-text ::ng-deep .hashtag{display:inline-block;font-weight:600;color:var(--primary-500)}.cax-comment-content .cax-comment-sender{font-size:14px;font-weight:600;color:var(--neutral-900);margin-bottom:0;line-height:20px}.cax-file-attachment{margin-bottom:12px}.cax-file-attachment .file-item{display:flex;align-items:center;gap:12px;border-color:1px solid var(--neutral-150);padding:10px 16px;background:var(--neutral-75);border-radius:8px;cursor:pointer;margin-bottom:8px}.cax-file-attachment .file-item .file-details{display:flex;flex:1;align-items:center;gap:12px}.cax-file-attachment .file-item .file-name{color:var(--neutral-900);font-weight:500;font-size:14px;line-height:20px;flex:1;white-space:nowrap;overflow:hidden}.cax-file-attachment .file-item .file-size{color:var(--neutral-600);font-weight:400;font-size:12px;line-height:18px;margin-right:8px}.cax-file-attachment .file-item i{color:var(--neutral-900);font-size:1.1rem;margin-left:auto;order:2}.cax-file-attachment .file-item i.cax-download{cursor:pointer;transition:color .2s ease}.cax-file-attachment .file-item i.cax-download:hover{color:var(--primary-600)}.cax-file-attachment .file-item i.cax-download:active{color:var(--primary-700)}.cax-file-attachment .file-item:last-child{margin-bottom:0}.cax-file-attachment:last-child{margin-bottom:0}.cax-comment-date{font-weight:400;font-size:12px;line-height:18px;color:var(--neutral-600);align-self:flex-end}.cax-chat-input-container{display:flex;gap:.5rem}.cax-chat-input-container .chat-input{flex:1}.cax-chat-input-container .send-button{cursor:pointer}.input-wrapper{position:relative;flex:1;display:flex;flex-direction:column}.cax-date-header{text-align:center;font-size:12px;font-weight:500;line-height:18px;color:var(--neutral-700);background:var(--neutral-100);align-self:center;width:fit-content;padding:4px 12px;border-radius:4px;margin:11px 0;position:relative;z-index:1}.cax-date-header:first-child{margin-top:0}.cax-comments-container{display:flex;flex-direction:column;height:calc(100vh - 200px);overflow:hidden;position:relative;transform:translateZ(0);backface-visibility:hidden}.selected-files{display:flex;flex-wrap:wrap;gap:.5rem;padding:0 0 5px;position:relative}.selected-files .cax-chip{background:var(--neutral-100)}.selected-files .cax-chip i{margin-right:.5rem}.selected-files .files-overlay{position:absolute;background:var(--white-100);border-radius:8px;box-shadow:0 4px 12px #00000026;width:300px;max-height:400px;z-index:1000;overflow:hidden;border:1px solid var(--neutral-200)}.selected-files .files-overlay .files-overlay-header{padding:12px 16px;font-weight:600;font-size:14px;border-bottom:1px solid var(--neutral-100);background:var(--neutral-50)}.selected-files .files-overlay .files-overlay-content{max-height:350px;overflow-y:auto;padding:8px 0}.selected-files .files-overlay .files-overlay-content .file-item{display:flex;align-items:center;padding:8px 16px;transition:background-color .2s ease}.selected-files .files-overlay .files-overlay-content .file-item:hover{background-color:var(--neutral-50)}.selected-files .files-overlay .files-overlay-content .file-item i.cax-paperclip{color:var(--neutral-600);margin-right:8px}.selected-files .files-overlay .files-overlay-content .file-item .file-name{flex:1;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:8px}.selected-files .files-overlay .files-overlay-content .file-item .file-size{color:var(--neutral-600);font-size:12px;margin-right:8px}.selected-files .files-overlay .files-overlay-content .file-item i.cax-times{color:var(--neutral-600);cursor:pointer;transition:color .2s ease}.selected-files .files-overlay .files-overlay-content .file-item i.cax-times:hover{color:var --error-500}.selected-files :deep(.file-chip){background:var(--neutral-50);border:1px solid var(--neutral-100)}.selected-files :deep(.file-chip) .file-details{display:flex;align-items:center;gap:8px}.selected-files :deep(.file-chip) i{color:var(--primary-500);margin-right:8px}.selected-files :deep(.file-chip) .file-name{font-weight:500}.selected-files :deep(.file-chip) .file-size{color:var(--neutral-600);font-size:.8rem}:host ::ng-deep .cax-sidebar{width:589px!important;border:1px solid var(--neutral-200)!important}:host ::ng-deep .cax-sidebar .cax-sidebar-content{display:flex;flex-direction:column;background:var(--neutral-25);padding:24px 8px!important}:host ::ng-deep .cax-sidebar .cax-sidebar-footer{padding:12px!important;background:var(--neutral-50);border-top:1px solid var(--neutral-200)}:host ::ng-deep .cax-sidebar .cax-sidebar-header{border-bottom:1px solid var(--neutral-200);background:var(--neutral-50);padding:16px 24px!important}:host ::ng-deep .cax-overlay{position:absolute;bottom:0!important;top:unset!important;left:unset!important}:host ::ng-deep .suggestion-panel{background:var(--white-100);box-shadow:0 2px 8px #0000001a;z-index:9999;padding:12px 4px;margin-left:20px;width:224px;border-radius:8px;border:1px solid var(--neutral-200)}:host ::ng-deep .suggestion-panel .suggestion-list{max-height:200px;overflow-y:auto;will-change:transform;transform:translateZ(0);backface-visibility:hidden;-webkit-backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:rgba(94,92,92,.3) transparent}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item{padding:6px 8px;cursor:pointer;display:flex;justify-content:space-between;transition:background-color .2s ease;align-items:center}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item:hover{background-color:var(--neutral-50)}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item.selected{background-color:var(--neutral-50)}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item .suggestion-label{font-weight:500}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item .suggestion-id{color:var(--neutral-600);font-size:.85em}:host ::ng-deep .suggestion-panel .suggestion-list:after{content:\"\";display:block;min-height:20px;scroll-snap-align:end}:host ::ng-deep .suggestion-panel .suggestion-list::-webkit-scrollbar-track{background:transparent}:host ::ng-deep .suggestion-panel .suggestion-list::-webkit-scrollbar-thumb{background-color:#5553531a;border-radius:4px;border:2px solid transparent;background-clip:padding-box}:host ::ng-deep .chat-footer{position:relative;z-index:1}:host ::ng-deep .cax-chat-input-container .chat-input .cax-paperclip{color:var(--neutral-900)!important}:host ::ng-deep .files-list-overlay{border:1px solid var(--neutral-200);background:var(--white-100);box-shadow:0 2px 8px #0000001a;z-index:9999;padding:12px 4px;width:224px;border-radius:8px}:host ::ng-deep .files-list-overlay.cax-overlay{transform-origin:right center!important}:host ::ng-deep .files-list-overlay .files-overlay-content{max-height:200px;overflow-y:auto}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item{transition:background-color .2s ease;padding:6px 8px;cursor:pointer;display:flex;justify-content:space-between;align-items:center;will-change:transform;transform:translateZ(0);backface-visibility:hidden;-webkit-backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:rgba(94,92,92,.3) transparent}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item:hover{background-color:var(--neutral-50)}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item .file-name{flex:1;font-size:14px;font-weight:500;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:8px}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item .file-size{color:var(--neutral-600);font-size:12px;margin-right:8px}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item i.cax-times{color:var(--neutral-600);cursor:pointer;border:1.1rem solid var(--neutral-200);transition:color .2s ease}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item:after{content:\"\";display:block;min-height:20px;scroll-snap-align:end}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item::-webkit-scrollbar-track{background:transparent}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item::-webkit-scrollbar-thumb{background-color:#5553531a;border-radius:4px;border:2px solid transparent;background-clip:padding-box}}\n"] }]
502
+ }], ctorParameters: () => [{ type: i1.DomSanitizer }], propDecorators: { comments: [{
503
+ type: Input
504
+ }], mentionSuggestions: [{
505
+ type: Input
506
+ }], hashtagSuggestions: [{
507
+ type: Input
508
+ }], sidebarHeader: [{
509
+ type: Input
510
+ }], isAdmin: [{
511
+ type: Input
512
+ }], commentAdded: [{
513
+ type: Output
514
+ }], fileSelected: [{
515
+ type: Output
516
+ }], fileDownload: [{
517
+ type: Output
518
+ }], visibleChange: [{
519
+ type: Output
520
+ }], fileInput: [{
521
+ type: ViewChild,
522
+ args: ['fileInput']
523
+ }], suggestionPanel: [{
524
+ type: ViewChild,
525
+ args: ['suggestionPanel']
526
+ }], inputText: [{
527
+ type: ViewChild,
528
+ args: ['inputText']
529
+ }], commentsList: [{
530
+ type: ViewChild,
531
+ args: ['commentsList']
532
+ }], countChip: [{
533
+ type: ViewChild,
534
+ args: ['countChip']
535
+ }], visible: [{
536
+ type: Input
537
+ }], onDocumentClick: [{
538
+ type: HostListener,
539
+ args: ['document:click', ['$event']]
540
+ }] } });
541
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbWVudGJveC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcHAvY29tcG9uZW50cy9jb21tZW50Ym94L2NvbW1lbnRib3gudHMiLCIuLi8uLi8uLi9zcmMvYXBwL2NvbXBvbmVudHMvY29tbWVudGJveC9jb21tZW50Ym94Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQWMsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDOzs7Ozs7Ozs7Ozs7QUFzQjVHLE1BQU0sT0FBTyxtQkFBbUI7SUE0Q1I7SUEzQ1gsUUFBUSxHQUFjLEVBQUUsQ0FBQztJQUN6QixrQkFBa0IsR0FBVSxFQUFFLENBQUM7SUFDL0Isa0JBQWtCLEdBQVUsRUFBRSxDQUFDO0lBQy9CLGFBQWEsQ0FBUztJQUN0QixPQUFPLEdBQVksSUFBSSxDQUFDO0lBQ3ZCLFlBQVksR0FBRyxJQUFJLFlBQVksRUFBTyxDQUFDO0lBQ3ZDLFlBQVksR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO0lBQ3hDLFlBQVksR0FBRyxJQUFJLFlBQVksRUFBa0MsQ0FBQztJQUNsRSxhQUFhLEdBQUcsSUFBSSxZQUFZLEVBQVcsQ0FBQztJQUN0RCxVQUFVLEdBQVcsRUFBRSxDQUFDO0lBRXhCLFlBQVksR0FBWSxLQUFLLENBQUM7SUFDOUIsYUFBYSxHQUFZLEtBQUssQ0FBQztJQUMvQixXQUFXLEdBQVUsRUFBRSxDQUFDO0lBQ3hCLGtCQUFrQixHQUFRLElBQUksQ0FBQztJQUMvQix1QkFBdUIsR0FBVyxDQUFDLENBQUMsQ0FBQztJQUNyQyxtQkFBbUIsR0FBVSxFQUFFLENBQUM7SUFDaEMsZ0JBQWdCLEdBQWlDLElBQUksQ0FBQztJQUN0RCxjQUFjLEdBQVcsQ0FBQyxDQUFDO0lBRUgsU0FBUyxDQUFnQztJQUNuQyxlQUFlLENBQWM7SUFDbkMsU0FBUyxDQUFjO0lBQ1os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WTtzQkFBckIsTUFBTTtnQkFDRyxZQUFZO3NCQUFyQixNQUFNO2dCQUNHLFlBQVk7c0JBQXJCLE1BQU07Z0JBQ0csYUFBYTtzQkFBdEIsTUFBTTtnQkFZaUIsU0FBUztzQkFBaEMsU0FBUzt1QkFBQyxXQUFXO2dCQUNRLGVBQWU7c0JBQTVDLFNBQVM7dUJBQUMsaUJBQWlCO2dCQUNKLFNBQVM7c0JBQWhDLFNBQVM7dUJBQUMsV0FBVztnQkFDYSxZQUFZO3NCQUE5QyxTQUFTO3VCQUFDLGNBQWM7Z0JBQ0QsU0FBUztzQkFBaEMsU0FBUzt1QkFBQyxXQUFXO2dCQXFKVCxPQUFPO3NCQUFuQixLQUFLO2dCQTRCTixlQUFlO3NCQURkLFlBQVk7dUJBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgVmlld0NoaWxkLCBFbGVtZW50UmVmLCBIb3N0TGlzdGVuZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERvbVNhbml0aXplciwgU2FmZUh0bWwgfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcblxuLy8gQWRkIHRoaXMgaW50ZXJmYWNlIGF0IHRoZSB0b3Agb2YgdGhlIGZpbGVcbmludGVyZmFjZSBDb21tZW50IHtcbiAgICB0ZXh0OiBzdHJpbmc7XG4gICAgZGF0ZTogRGF0ZTtcbiAgICBmaWxlcz86IEFycmF5PHsgbmFtZTogc3RyaW5nOyBzaXplOiBzdHJpbmcgfT47XG4gICAgaXNBZG1pbj86IGJvb2xlYW47XG4gICAgc2VuZGVyPzogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgR3JvdXBlZENvbW1lbnRzIHtcbiAgICBkYXRlOiBEYXRlO1xuICAgIGl0ZW1zOiBDb21tZW50W107XG59XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnY2F4LWNvbW1lbnRzJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vY29tbWVudGJveC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9jb21tZW50Ym94LnNjc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBDb21tZW50Ym94Q29tcG9uZW50IHtcbiAgICBASW5wdXQoKSBjb21tZW50czogQ29tbWVudFtdID0gW107XG4gICAgQElucHV0KCkgbWVudGlvblN1Z2dlc3Rpb25zOiBhbnlbXSA9IFtdO1xuICAgIEBJbnB1dCgpIGhhc2h0YWdTdWdnZXN0aW9uczogYW55W10gPSBbXTtcbiAgICBASW5wdXQoKSBzaWRlYmFySGVhZGVyOiBzdHJpbmc7XG4gICAgQElucHV0KCkgaXNBZG1pbjogYm9vbGVhbiA9IHRydWU7XG4gICAgQE91dHB1dCgpIGNvbW1lbnRBZGRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuICAgIEBPdXRwdXQoKSBmaWxlU2VsZWN0ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPEZpbGU+KCk7XG4gICAgQE91dHB1dCgpIGZpbGVEb3dubG9hZCA9IG5ldyBFdmVudEVtaXR0ZXI8eyBuYW1lOiBzdHJpbmc7IHNpemU6IHN0cmluZyB9PigpO1xuICAgIEBPdXRwdXQoKSB2aXNpYmxlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuICAgIG5ld0NvbW1lbnQ6IHN0cmluZyA9ICcnO1xuXG4gICAgaXNNZW50aW9uaW5nOiBib29sZWFuID0gZmFsc2U7XG4gICAgaXNIYXNodGFnZ2luZzogYm9vbGVhbiA9IGZhbHNlO1xuICAgIHN1Z2dlc3Rpb25zOiBhbnlbXSA9IFtdO1xuICAgIHNlbGVjdGVkU3VnZ2VzdGlvbjogYW55ID0gbnVsbDtcbiAgICBzZWxlY3RlZFN1Z2dlc3Rpb25JbmRleDogbnVtYmVyID0gLTE7XG4gICAgZmlsdGVyZWRTdWdnZXN0aW9uczogYW55W10gPSBbXTtcbiAgICBjdXJyZW50VG9rZW5UeXBlOiAnbWVudGlvbicgfCAnaGFzaHRhZycgfCBudWxsID0gbnVsbDtcbiAgICBjdXJzb3JQb3NpdGlvbjogbnVtYmVyID0gMDtcblxuICAgIEBWaWV3Q2hpbGQoJ2ZpbGVJbnB1dCcpIGZpbGVJbnB1dCE6IEVsZW1lbnRSZWY8SFRNTElucHV0RWxlbWVudD47XG4gICAgQFZpZXdDaGlsZCgnc3VnZ2VzdGlvblBhbmVsJykgc3VnZ2VzdGlvblBhbmVsITogRWxlbWVudFJlZjtcbiAgICBAVmlld0NoaWxkKCdpbnB1dFRleHQnKSBpbnB1dFRleHQhOiBFbGVtZW50UmVmO1xuICAgIEBWaWV3Q2hpbGQoJ2NvbW1lbnRzTGlzdCcpIHByaXZhdGUgY29tbWVudHNMaXN0ITogRWxlbWVudFJlZjtcbiAgICBAVmlld0NoaWxkKCdjb3VudENoaXAnKSBjb3VudENoaXAhOiBFbGVtZW50UmVmO1xuICAgIHNlbGVjdGVkRmlsZXM6IEFycmF5PHsgbmFtZTogc3RyaW5nOyBzaXplOiBzdHJpbmcgfT4gPSBbXTtcbiAgICBzZWxlY3RlZEZpbGVzTWFwOiBNYXA8bnVtYmVyLCB7IG5hbWU6IHN0cmluZzsgc2l6ZTogc3RyaW5nIH0+ID0gbmV3IE1hcCgpO1xuXG4gICAgdG9kYXk6IERhdGUgPSBuZXcgRGF0ZSgpO1xuXG4gICAgb3ZlcmxheVZpc2libGU6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBmaWxlc092ZXJsYXlWaXNpYmxlOiBib29sZWFuID0gZmFsc2U7XG4gICAgb3ZlcmxheVBvc2l0aW9uID0geyB0b3A6IDAsIGxlZnQ6IDAgfTtcblxuICAgIHByaXZhdGUgZGF0ZVVwZGF0ZUludGVydmFsOiBhbnk7XG5cbiAgICAvLyBLZWVwIHRyYWNrIG9mIHNob3VsZCBhdXRvIHNjcm9sbFxuICAgIHByaXZhdGUgc2hvdWxkQXV0b1Njcm9sbCA9IHRydWU7XG4gICAgcHJpdmF0ZSBpc1VzZXJTY3JvbGxpbmcgPSBmYWxzZTtcblxuICAgIC8vIEFkZCBuZXcgcHJvcGVydHkgZm9yIG11dGF0aW9uIG9ic2VydmVyXG4gICAgcHJpdmF0ZSBvYnNlcnZlcjogTXV0YXRpb25PYnNlcnZlcjtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2FuaXRpemVyOiBEb21TYW5pdGl6ZXIpIHtcbiAgICAgICAgdGhpcy51cGRhdGVDdXJyZW50RGF0ZSgpO1xuICAgICAgICB0aGlzLmRhdGVVcGRhdGVJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHRoaXMudXBkYXRlQ3VycmVudERhdGUoKSwgNjAwMDApO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgb2JzZXJ2ZXJcbiAgICAgICAgdGhpcy5vYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKCgpID0+IHRoaXMuZm9yY2VTY3JvbGxUb0JvdHRvbSgpKTtcbiAgICB9XG5cbiAgICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5mb3JjZVNjcm9sbFRvQm90dG9tKCk7XG4gICAgICAgIH0sIDEwMCk7XG5cbiAgICAgICAgLy8gU2V0IHVwIG9ic2VydmVyIHRvIGF1dG8tc2Nyb2xsIHdoZW4gY29udGVudCBjaGFuZ2VzXG4gICAgICAgIGlmICh0aGlzLmNvbW1lbnRzTGlzdD8ubmF0aXZlRWxlbWVudCkge1xuICAgICAgICAgICAgdGhpcy5vYnNlcnZlci5vYnNlcnZlKHRoaXMuY29tbWVudHNMaXN0Lm5hdGl2ZUVsZW1lbnQsIHtcbiAgICAgICAgICAgICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICAgICAgICAgICAgc3VidHJlZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjaGFyYWN0ZXJEYXRhOiB0cnVlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCkge1xuICAgICAgICBpZiAodGhpcy5kYXRlVXBkYXRlSW50ZXJ2YWwpIHtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5kYXRlVXBkYXRlSW50ZXJ2YWwpO1xuICAgICAgICB9XG4gICAgICAgIC8vIERpc2Nvbm5lY3QgdGhlIG9ic2VydmVyXG4gICAgICAgIHRoaXMub2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuXG4gICAgICAgIC8vIFJlbW92ZSBldmVudCBsaXN0ZW5lcnNcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLmhhbmRsZUNsaWNrT3V0c2lkZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1cGRhdGVDdXJyZW50RGF0ZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy50b2RheSA9IG5ldyBEYXRlKCk7XG4gICAgfVxuXG4gICAgZm9ybWF0RGF0ZShkYXRlOiBEYXRlKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGRhdGUudG9Mb2NhbGVEYXRlU3RyaW5nKHVuZGVmaW5lZCwge1xuICAgICAgICAgICAgZGF5OiAnMi1kaWdpdCcsXG4gICAgICAgICAgICBtb250aDogJzItZGlnaXQnLFxuICAgICAgICAgICAgeWVhcjogJ251bWVyaWMnLFxuICAgICAgICAgICAgdGltZVpvbmU6IEludGwuRGF0ZVRpbWVGb3JtYXQoKS5yZXNvbHZlZE9wdGlvbnMoKS50aW1lWm9uZVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmb3JtYXRNZXNzYWdlV2l0aFRhZ3ModGV4dDogc3RyaW5nKTogU2FmZUh0bWwge1xuICAgICAgICBpZiAoIXRleHQpIHJldHVybiAnJztcbiAgICAgICAgY29uc3Qgc2FuaXRpemVkVGV4dCA9IHRleHQucmVwbGFjZSgvJi9nLCAnJmFtcDsnKS5yZXBsYWNlKC88L2csICcmbHQ7JykucmVwbGFjZSgvPi9nLCAnJmd0OycpO1xuICAgICAgICBjb25zdCBodG1sQ29udGVudCA9IHNhbml0aXplZFRleHQucmVwbGFjZSgvKEBcXHcrfCNcXHcrKS9nLCAobWF0Y2gpID0+IHtcbiAgICAgICAgICAgIGlmIChtYXRjaC5zdGFydHNXaXRoKCdAJykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYDxzcGFuIGNsYXNzPVwibWVudGlvblwiIHN0eWxlPVwiY29sb3I6ICMwQzRBRjM7IGZvbnQtd2VpZ2h0OiA2MDA7XCI+JHttYXRjaH08L3NwYW4+YDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWF0Y2guc3RhcnRzV2l0aCgnIycpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGA8c3BhbiBjbGFzcz1cImhhc2h0YWdcIiBzdHlsZT1cImNvbG9yOiAjMEM0QUYzOyBmb250LXdlaWdodDogNjAwO1wiPiR7bWF0Y2h9PC9zcGFuPmA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnNhbml0aXplci5ieXBhc3NTZWN1cml0eVRydXN0SHRtbChodG1sQ29udGVudCk7XG4gICAgfVxuXG4gICAgYWRkQ29tbWVudCgpIHtcbiAgICAgICAgaWYgKHRoaXMubmV3Q29tbWVudC50cmltKCkgfHwgdGhpcy5zZWxlY3RlZEZpbGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld0NvbW1lbnQ6IENvbW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgdGV4dDogdGhpcy5uZXdDb21tZW50LFxuICAgICAgICAgICAgICAgIGRhdGU6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICAgICAgZmlsZXM6IHRoaXMuc2VsZWN0ZWRGaWxlcy5sZW5ndGggPiAwID8gWy4uLnRoaXMuc2VsZWN0ZWRGaWxlc10gOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgaXNBZG1pbjogdGhpcy5pc0FkbWluLFxuICAgICAgICAgICAgICAgIHNlbmRlcjogdGhpcy5pc0FkbWluID8gJ1N5c3RlbSBBZG1pbicgOiAnVXNlcidcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuY29tbWVudHMgPSBbLi4udGhpcy5jb21tZW50cywgbmV3Q29tbWVudF07XG4gICAgICAgICAgICB0aGlzLmNvbW1lbnRBZGRlZC5lbWl0KG5ld0NvbW1lbnQpO1xuICAgICAgICAgICAgdGhpcy5uZXdDb21tZW50ID0gJyc7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRmlsZXMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlc01hcC5jbGVhcigpO1xuICAgICAgICAgICAgdGhpcy5maWxlc092ZXJsYXlWaXNpYmxlID0gZmFsc2U7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnN1Z2dlc3Rpb25QYW5lbD8ubmF0aXZlRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3VnZ2VzdGlvblBhbmVsLm5hdGl2ZUVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQWx3YXlzIHNjcm9sbCB0byBib3R0b20gaW1tZWRpYXRlbHlcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsVG9Cb3R0b20odHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGZvcmNlU2Nyb2xsVG9Cb3R0b20oKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5jb21tZW50c0xpc3Q/Lm5hdGl2ZUVsZW1lbnQpIHJldHVybjtcblxuICAgICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5jb21tZW50c0xpc3QubmF0aXZlRWxlbWVudDtcbiAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgLy8gRm9yY2UgaW1tZWRpYXRlIHNjcm9sbFxuICAgICAgICAgICAgICAgIGVsZW1lbnQuc2Nyb2xsVG9wID0gZWxlbWVudC5zY3JvbGxIZWlnaHQ7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdTY3JvbGwgZXJyb3I6JywgZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzY3JvbGxUb0JvdHRvbShmb3JjZSA9IGZhbHNlKTogdm9pZCB7XG4gICAgICAgIGlmIChmb3JjZSkge1xuICAgICAgICAgICAgdGhpcy5mb3JjZVNjcm9sbFRvQm90dG9tKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmNvbW1lbnRzTGlzdD8ubmF0aXZlRWxlbWVudCkgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLmNvbW1lbnRzTGlzdC5uYXRpdmVFbGVtZW50O1xuXG4gICAgICAgIC8vIFVzZSBkb3VibGUgUkFGIGZvciByZWxpYWJsZSBzY3JvbGxpbmdcbiAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRm9yY2UgaW1tZWRpYXRlIHNjcm9sbCBmb3IgbmV3IGNvbW1lbnRzXG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2Nyb2xsVG9wID0gZWxlbWVudC5zY3JvbGxIZWlnaHQ7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gVXNlIHNtb290aCBzY3JvbGxpbmcgYWZ0ZXIgaW5pdGlhbCBqdW1wXG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2Nyb2xsVG8oe1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9wOiBlbGVtZW50LnNjcm9sbEhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlaGF2aW9yOiAnc21vb3RoJ1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zY3JvbGxUb3AgPSBlbGVtZW50LnNjcm9sbEhlaWdodDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgQElucHV0KCkgc2V0IHZpc2libGUodmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgICAgaWYgKHRoaXMuX3Zpc2libGUgIT09IHZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLl92aXNpYmxlID0gdmFsdWU7XG4gICAgICAgICAgICB0aGlzLnZpc2libGVDaGFuZ2UuZW1pdCh0aGlzLl92aXNpYmxlKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX3Zpc2libGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3VsZEF1dG9TY3JvbGwgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5zY3JvbGxUb0JvdHRvbSh0cnVlKSwgMzAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldCB2aXNpYmxlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fdmlzaWJsZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF92aXNpYmxlOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICB0b2dnbGVDb21tZW50cygpIHtcbiAgICAgICAgdGhpcy52aXNpYmxlID0gIXRoaXMudmlzaWJsZTtcbiAgICB9XG5cbiAgICBvblNpZGViYXJIaWRlKCkge1xuICAgICAgICB0aGlzLl92aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHRoaXMudmlzaWJsZUNoYW5nZS5lbWl0KGZhbHNlKTtcbiAgICB9XG5cbiAgICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDpjbGljaycsIFsnJGV2ZW50J10pXG4gICAgb25Eb2N1bWVudENsaWNrKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgY29uc3QgaXNJbnB1dENsaWNrID0gdGhpcy5pbnB1dFRleHQ/Lm5hdGl2ZUVsZW1lbnQ/LmNvbnRhaW5zKHRhcmdldCk7XG4gICAgICAgIGNvbnN0IGlzUGFuZWxDbGljayA9IHRoaXMuc3VnZ2VzdGlvblBhbmVsPy5uYXRpdmVFbGVtZW50Py5jb250YWlucyh0YXJnZXQpO1xuXG4gICAgICAgIGlmICghaXNJbnB1dENsaWNrICYmICFpc1BhbmVsQ2xpY2spIHtcbiAgICAgICAgICAgIHRoaXMub3ZlcmxheVZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFRva2VuVHlwZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmZpbHRlcmVkU3VnZ2VzdGlvbnMgPSBbXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhhbmRsZUtleVVwKGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICAgICAgLy8gVXBkYXRlIGN1cnNvciBwb3NpdGlvbiBvbiBldmVyeSBrZXkgcHJlc3NcbiAgICAgICAgY29uc3QgaW5wdXQgPSBldmVudC50YXJnZXQ7XG4gICAgICAgIHRoaXMuY3Vyc29yUG9zaXRpb24gPSBpbnB1dC5zZWxlY3Rpb25TdGFydCB8fCAwO1xuXG4gICAgICAgIGlmIChldmVudC5rZXkgPT09ICdFc2NhcGUnKSB7XG4gICAgICAgICAgICB0aGlzLm92ZXJsYXlWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRUb2tlblR5cGUgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5maWx0ZXJlZFN1Z2dlc3Rpb25zID0gW107XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQua2V5ID09PSAnQCcgfHwgZXZlbnQua2V5ID09PSAnIycpIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFRva2VuVHlwZSA9IGV2ZW50LmtleSA9PT0gJ0AnID8gJ21lbnRpb24nIDogJ2hhc2h0YWcnO1xuICAgICAgICAgICAgdGhpcy5maWx0ZXJlZFN1Z2dlc3Rpb25zID0gdGhpcy5jdXJyZW50VG9rZW5UeXBlID09PSAnbWVudGlvbicgPyB0aGlzLm1lbnRpb25TdWdnZXN0aW9ucyA6IHRoaXMuaGFzaHRhZ1N1Z2dlc3Rpb25zO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZFN1Z2dlc3Rpb25JbmRleCA9IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlY3QgPSBpbnB1dC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIGNvbnN0IGN1cnNvclBvc2l0aW9uID0gdGhpcy5nZXRDdXJzb3JQb3NpdGlvbihpbnB1dCk7XG5cbiAgICAgICAgICAgIHRoaXMub3ZlcmxheVZpc2libGUgPSB0cnVlO1xuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGFuZWwgPSB0aGlzLnN1Z2dlc3Rpb25QYW5lbD8ubmF0aXZlRWxlbWVudDtcbiAgICAgICAgICAgICAgICBpZiAocGFuZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFuZWwuc3R5bGUubGVmdCA9IGAke3JlY3QubGVmdCArIGN1cnNvclBvc2l0aW9uLmxlZnR9cHhgO1xuICAgICAgICAgICAgICAgICAgICBwYW5lbC5zdHlsZS50b3AgPSBgJHtyZWN0LnRvcCAtIDEwfXB4YDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRUb2tlblR5cGUpIHtcbiAgICAgICAgICAgIGNvbnN0IHRva2VuID0gdGhpcy5nZXRUb2tlbkF0Q3Vyc29yKGlucHV0LnZhbHVlLCB0aGlzLmN1cnNvclBvc2l0aW9uKTtcbiAgICAgICAgICAgIGlmICh0b2tlbikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNlYXJjaFRlcm0gPSB0b2tlbi5zbGljZSgxKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyZWRTdWdnZXN0aW9ucyA9ICh0aGlzLmN1cnJlbnRUb2tlblR5cGUgPT09ICdtZW50aW9uJyA/IHRoaXMubWVudGlvblN1Z2dlc3Rpb25zIDogdGhpcy5oYXNodGFnU3VnZ2VzdGlvbnMpLmZpbHRlcigoaXRlbSkgPT4gaXRlbS5uYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoc2VhcmNoVGVybSkgfHwgaXRlbS5pZC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHNlYXJjaFRlcm0pKTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmZpbHRlcmVkU3VnZ2VzdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm92ZXJsYXlWaXNpYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgLy8gT25seSByZXNldCBzZWxlY3Rpb24gaW5kZXggaWYgd2UgaGF2ZSBuZXcgc3VnZ2VzdGlvbnNcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRTdWdnZXN0aW9uSW5kZXggPCAwIHx8IHRoaXMuc2VsZWN0ZWRTdWdnZXN0aW9uSW5kZXggPj0gdGhpcy5maWx0ZXJlZFN1Z2dlc3Rpb25zLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZFN1Z2dlc3Rpb25JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm92ZXJsYXlWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRTdWdnZXN0aW9uSW5kZXggPSAtMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMub3ZlcmxheVZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRUb2tlblR5cGUgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0VG9rZW5BdEN1cnNvcih0ZXh0OiBzdHJpbmcsIGN1cnNvclBvczogbnVtYmVyKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIGNvbnN0IGJlZm9yZUN1cnNvciA9IHRleHQuc2xpY2UoMCwgY3Vyc29yUG9zKTtcbiAgICAgICAgY29uc3QgbWF0Y2ggPSBiZWZvcmVDdXJzb3IubWF0Y2goL1tAI11bXlxcc10qJC8pO1xuICAgICAgICByZXR1cm4gbWF0Y2ggPyBtYXRjaFswXSA6IG51bGw7XG4gICAgfVxuXG4gICAgZ2V0V29yZEF0UG9zaXRpb24odGV4dDogc3RyaW5nLCBwb3NpdGlvbjogbnVtYmVyKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgbGVmdCA9IHRleHQuc2xpY2UoMCwgcG9zaXRpb24pLnNlYXJjaCgvW0AjXVteXFxzXSokLyk7XG4gICAgICAgIGlmIChsZWZ0ID09PSAtMSkgcmV0dXJuICcnO1xuICAgICAgICByZXR1cm4gdGV4dC5zbGljZShsZWZ0LCBwb3NpdGlvbik7XG4gICAgfVxuXG4gICAgc2VsZWN0U3VnZ2VzdGlvbihzdWdnZXN0aW9uOiBhbnkpIHtcbiAgICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLm5ld0NvbW1lbnQ7XG4gICAgICAgIGNvbnN0IHdvcmRTdGFydCA9IGlucHV0LnNsaWNlKDAsIHRoaXMuY3Vyc29yUG9zaXRpb24pLnNlYXJjaCgvW0AjXVteXFxzXSokLyk7XG5cbiAgICAgICAgdGhpcy5uZXdDb21tZW50ID0gaW5wdXQuc2xpY2UoMCwgd29yZFN0YXJ0KSArIHN1Z2dlc3Rpb24udmFsdWUgKyAnICcgKyBpbnB1dC5zbGljZSh0aGlzLmN1cnNvclBvc2l0aW9uKTtcblxuICAgICAgICB0aGlzLmlzTWVudGlvbmluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmlzSGFzaHRhZ2dpbmcgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBvblN1Z2dlc3Rpb25TZWxlY3QoaXRlbTogYW55KSB7XG4gICAgICAgIGNvbnN0IGlucHV0ID0gdGhpcy5uZXdDb21tZW50O1xuICAgICAgICBjb25zdCBiZWZvcmVDdXJzb3IgPSBpbnB1dC5zbGljZSgwLCB0aGlzLmN1cnNvclBvc2l0aW9uKTtcbiAgICAgICAgY29uc3QgYWZ0ZXJDdXJzb3IgPSBpbnB1dC5zbGljZSh0aGlzLmN1cnNvclBvc2l0aW9uKTtcbiAgICAgICAgY29uc3QgbGFzdFRva2VuSW5kZXggPSBNYXRoLm1heChiZWZvcmVDdXJzb3IubGFzdEluZGV4T2YoJ0AnKSwgYmVmb3JlQ3Vyc29yLmxhc3RJbmRleE9mKCcjJykpO1xuXG4gICAgICAgIGlmIChsYXN0VG9rZW5JbmRleCA+PSAwKSB7XG4gICAgICAgICAgICAvLyBJbnNlcnQgdGhlIHN1Z2dlc3Rpb24gYXQgdGhlIGN1cnNvciBwb3NpdGlvblxuICAgICAgICAgICAgdGhpcy5uZXdDb21tZW50ID0gYmVmb3JlQ3Vyc29yLnNsaWNlKDAsIGxhc3RUb2tlbkluZGV4KSArIGl0ZW0uaWQgKyAnICcgKyBhZnRlckN1cnNvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3VnZ2VzdGlvblBhbmVsLm5hdGl2ZUVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgdGhpcy5vdmVybGF5VmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLmN1cnJlbnRUb2tlblR5cGUgPSBudWxsO1xuICAgICAgICB0aGlzLmZpbHRlcmVkU3VnZ2VzdGlvbnMgPSBbXTtcbiAgICAgICAgdGhpcy5zZWxlY3RlZFN1Z2dlc3Rpb25JbmRleCA9IC0xO1xuXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgaW5wdXRFbCA9IHRoaXMuaW5wdXRUZXh0Lm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcignaW5wdXQnKTtcbiAgICAgICAgICAgIGlmIChpbnB1dEVsKSB7XG4gICAgICAgICAgICAgICAgaW5wdXRFbC5mb2N1cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBvblN1Z2dlc3Rpb25QYW5lbEhpZGUoKSB7XG4gICAgICAgIHRoaXMub3ZlcmxheVZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5jdXJyZW50VG9rZW5UeXBlID0gbnVsbDtcbiAgICAgICAgdGhpcy5maWx0ZXJlZFN1Z2dlc3Rpb25zID0gW107XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRTdWdnZXN0aW9uSW5kZXggPSAtMTtcbiAgICB9XG5cbiAgICBnZXRDdXJzb3JQb3NpdGlvbihpbnB1dDogSFRNTElucHV0RWxlbWVudCk6IHsgbGVmdDogbnVtYmVyOyB0b3A6IG51bWJlciB9IHtcbiAgICAgICAgY29uc3Qgc2VsZWN0aW9uU3RhcnQgPSBpbnB1dC5zZWxlY3Rpb25TdGFydCB8fCAwO1xuICAgICAgICBjb25zdCB0ZXh0QmVmb3JlQ3Vyc29yID0gaW5wdXQudmFsdWUuc3Vic3RyaW5nKDAsIHNlbGVjdGlvblN0YXJ0KTtcbiAgICAgICAgY29uc3Qgc3BhbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgICAgICAgc3Bhbi50ZXh0Q29udGVudCA9IHRleHRCZWZvcmVDdXJzb3I7XG4gICAgICAgIHNwYW4uc3R5bGUuY3NzVGV4dCA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGlucHV0LCBudWxsKS5jc3NUZXh0O1xuICAgICAgICBzcGFuLnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJztcbiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChzcGFuKTtcbiAgICAgICAgY29uc3QgcG9zaXRpb24gPSB7XG4gICAgICAgICAgICBsZWZ0OiBzcGFuLm9mZnNldFdpZHRoLFxuICAgICAgICAgICAgdG9wOiBzcGFuLm9mZnNldEhlaWdodFxuICAgICAgICB9O1xuICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKHNwYW4pO1xuICAgICAgICByZXR1cm4gcG9zaXRpb247XG4gICAgfVxuXG4gICAgb25GaWxlSWNvbkNsaWNrKGV2ZW50OiBFdmVudCk6IHZvaWQge1xuICAgICAgICBldmVudD8ucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZXZlbnQ/LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBpZiAodGhpcy5maWxlSW5wdXQ/Lm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRoaXMuZmlsZUlucHV0Lm5hdGl2ZUVsZW1lbnQuY2xpY2soKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9uRmlsZVNlbGVjdChldmVudDogRXZlbnQpIHtcbiAgICAgICAgY29uc3QgaW5wdXQgPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgICAgaWYgKGlucHV0LmZpbGVzICYmIGlucHV0LmZpbGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIEFycmF5LmZyb20oaW5wdXQuZmlsZXMpLmZvckVhY2goKGZpbGUpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBmaWxlIGFscmVhZHkgZXhpc3RzIGluIHNlbGVjdGlvblxuICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVFeGlzdHMgPSB0aGlzLnNlbGVjdGVkRmlsZXMuc29tZSgoZXhpc3RpbmdGaWxlKSA9PiBleGlzdGluZ0ZpbGUubmFtZSA9PT0gZmlsZS5uYW1lICYmIGV4aXN0aW5nRmlsZS5zaXplID09PSB0aGlzLmZvcm1hdEZpbGVTaXplKGZpbGUuc2l6ZSkpO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFmaWxlRXhpc3RzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVJbmZvID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogZmlsZS5uYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZTogdGhpcy5mb3JtYXRGaWxlU2l6ZShmaWxlLnNpemUpXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlcy5wdXNoKGZpbGVJbmZvKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEZpbGVzTWFwLnNldCh0aGlzLnNlbGVjdGVkRmlsZXMubGVuZ3RoIC0gMSwgZmlsZUluZm8pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbGVTZWxlY3RlZC5lbWl0KGZpbGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpbnB1dC52YWx1ZSA9ICcnO1xuICAgICAgICAgICAgY29uc3QgaW5wdXRFbCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5jaGF0LWlucHV0IGlucHV0Jyk7XG4gICAgICAgICAgICBpZiAoaW5wdXRFbCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgaW5wdXRFbC5mb2N1cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1cGRhdGVGaWxlU3RhdGUoaW5kZXg6IG51bWJlciwgZnJvbUNoaXA6IGJvb2xlYW4gPSB0cnVlKSB7XG4gICAgICAgIGNvbnN0IGFjdHVhbEluZGV4ID0gZnJvbUNoaXAgPyBpbmRleCA6IGluZGV4ICsgNDtcbiAgICAgICAgdGhpcy5zZWxlY3RlZEZpbGVzID0gdGhpcy5zZWxlY3RlZEZpbGVzLmZpbHRlcigoXywgaSkgPT4gaSAhPT0gYWN0dWFsSW5kZXgpO1xuICAgICAgICB0aGlzLnNlbGVjdGVkRmlsZXNNYXAuY2xlYXIoKTtcbiAgICAgICAgdGhpcy5zZWxlY3RlZEZpbGVzLmZvckVhY2goKGZpbGUsIGkpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlc01hcC5zZXQoaSwgZmlsZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHJlbW92ZUZpbGUoaW5kZXg6IG51bWJlciwgZnJvbUNoaXA6IGJvb2xlYW4gPSB0cnVlKSB7XG4gICAgICAgIHRoaXMudXBkYXRlRmlsZVN0YXRlKGluZGV4LCBmcm9tQ2hpcCk7XG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGVkRmlsZXMubGVuZ3RoIDw9IDQpIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZUZpbGVzT3ZlcmxheSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0T3ZlcmZsb3dDb3VudCgpOiBudW1iZXIge1xuICAgICAgICAvLyBSZXR1cm4gY291bnQgb2YgZmlsZXMgYmV5b25kIHRoZSBmaXJzdCA0XG4gICAgICAgIHJldHVybiBNYXRoLm1heCgwLCB0aGlzLnNlbGVjdGVkRmlsZXMubGVuZ3RoIC0gNCk7XG4gICAgfVxuXG4gICAgc2hvd0ZpbGVzT3ZlcmxheShldmVudDogTW91c2VFdmVudCkge1xuICAgICAgICBjb25zdCB0YXJnZXQgPSBldmVudC5jdXJyZW50VGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgICAgICBjb25zdCByZWN0ID0gdGFyZ2V0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgICAgIC8vIFBvc2l0aW9uIHRoZSBvdmVybGF5IGJlbG93IHRoZSBjb3VudCBjaGlwXG4gICAgICAgIHRoaXMub3ZlcmxheVBvc2l0aW9uID0ge1xuICAgICAgICAgICAgdG9wOiByZWN0LmJvdHRvbSArIDUsXG4gICAgICAgICAgICBsZWZ0OiByZWN0LmxlZnQgLSAyNTAgKyByZWN0LndpZHRoIC8gMiAvLyBDZW50ZXIgdGhlIG92ZXJsYXkgaG9yaXpvbnRhbGx5XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5maWxlc092ZXJsYXlWaXNpYmxlID0gdHJ1ZTtcblxuICAgICAgICAvLyBBZGQgYSBjbGljayBvdXRzaWRlIGxpc3RlbmVyIHRvIGNsb3NlIHRoZSBvdmVybGF5XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLmhhbmRsZUNsaWNrT3V0c2lkZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGhpZGVGaWxlc092ZXJsYXkoKSB7XG4gICAgICAgIHRoaXMuZmlsZXNPdmVybGF5VmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuaGFuZGxlQ2xpY2tPdXRzaWRlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZUNsaWNrT3V0c2lkZSA9IChldmVudDogTW91c2VFdmVudCkgPT4ge1xuICAgICAgICBjb25zdCB0YXJnZXQgPSBldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgIGNvbnN0IG92ZXJsYXkgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuZmlsZXMtb3ZlcmxheScpO1xuICAgICAgICBjb25zdCBjb3VudENoaXAgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuY291bnQtY2hpcCcpO1xuXG4gICAgICAgIGlmIChvdmVybGF5ICYmICFvdmVybGF5LmNvbnRhaW5zKHRhcmdldCkgJiYgY291bnRDaGlwICYmICFjb3VudENoaXAuY29udGFpbnModGFyZ2V0KSkge1xuICAgICAgICAgICAgdGhpcy5oaWRlRmlsZXNPdmVybGF5KCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZm9ybWF0RmlsZVNpemUoYnl0ZXM6IG51bWJlcik6IHN0cmluZyB7XG4gICAgICAgIGlmIChieXRlcyA9PT0gMCkgcmV0dXJuICcwIEJ5dGVzJztcbiAgICAgICAgY29uc3QgayA9IDEwMjQ7XG4gICAgICAgIGNvbnN0IHNpemVzID0gWydCeXRlcycsICdLQicsICdNQicsICdHQiddO1xuICAgICAgICBjb25zdCBpID0gTWF0aC5mbG9vcihNYXRoLmxvZyhieXRlcykgLyBNYXRoLmxvZyhrKSk7XG4gICAgICAgIHJldHVybiBwYXJzZUZsb2F0KChieXRlcyAvIE1hdGgucG93KGssIGkpKS50b0ZpeGVkKDIpKSArICcgJyArIHNpemVzW2ldO1xuICAgIH1cblxuICAgIHNob3dTdWdnZXN0aW9ucyhfZXZlbnQ6IGFueSwgdHlwZTogJ21lbnRpb24nIHwgJ2hhc2h0YWcnKSB7XG4gICAgICAgIHRoaXMuY3VycmVudFRva2VuVHlwZSA9IHR5cGU7XG4gICAgICAgIHRoaXMuZmlsdGVyZWRTdWdnZXN0aW9ucyA9IHR5cGUgPT09ICdtZW50aW9uJyA/IHRoaXMubWVudGlvblN1Z2dlc3Rpb25zIDogdGhpcy5oYXNodGFnU3VnZ2VzdGlvbnM7XG4gICAgICAgIGlmICh0aGlzLnN1Z2dlc3Rpb25QYW5lbCkge1xuICAgICAgICAgICAgdGhpcy5zdWdnZXN0aW9uUGFuZWwubmF0aXZlRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcbiAgICAgICAgfVxuICAgIH1cbiAgICBvbktleURvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcbiAgICAgICAgLy8gSWYgc3VnZ2VzdGlvbnMgYXJlIHZpc2libGUsIGhhbmRsZSBrZXlib2FyZCBuYXZpZ2F0aW9uXG4gICAgICAgIGlmICh0aGlzLm92ZXJsYXlWaXNpYmxlICYmIHRoaXMuZmlsdGVyZWRTdWdnZXN0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKGV2ZW50LmtleSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ0Fycm93RG93bic6XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRTdWdnZXN0aW9uSW5kZXggPSBNYXRoLm1pbih0aGlzLnNlbGVjdGVkU3VnZ2VzdGlvbkluZGV4ICsgMSwgdGhpcy5maWx0ZXJlZFN1Z2dlc3Rpb25zLmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbFN1Z2dlc3Rpb25JbnRvVmlldygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdBcnJvd1VwJzpcbiAgICAgICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZFN1Z2dlc3Rpb25JbmRleCA9IE1hdGgubWF4KHRoaXMuc2VsZWN0ZWRTdWdnZXN0aW9uSW5kZXggLSAxLCAwKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxTdWdnZXN0aW9uSW50b1ZpZXcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnVGFiJzpcbiAgICAgICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50LnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTaGlmdCtUYWIgLSBtb3ZlIHVwXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkU3VnZ2VzdGlvbkluZGV4ID0gTWF0aC5tYXgodGhpcy5zZWxlY3RlZFN1Z2dlc3Rpb25JbmRleCAtIDEsIDApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGFiIC0gbW92ZSBkb3duXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkU3VnZ2VzdGlvbkluZGV4ID0gTWF0aC5taW4odGhpcy5zZWxlY3RlZFN1Z2dlc3Rpb25JbmRleCArIDEsIHRoaXMuZmlsdGVyZWRTdWdnZXN0aW9ucy5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbFN1Z2dlc3Rpb25JbnRvVmlldygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdFbnRlcic6XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGVkU3VnZ2VzdGlvbkluZGV4ID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub25TdWdnZXN0aW9uU2VsZWN0KHRoaXMuZmlsdGVyZWRTdWdnZXN0aW9uc1t0aGlzLnNlbGVjdGVkU3VnZ2VzdGlvbkluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnRXNjYXBlJzpcbiAgICAgICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblN1Z2dlc3Rpb25QYW5lbEhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiBubyBzdWdnZXN0aW9ucyBhcmUgdmlzaWJsZSwgaGFuZGxlIG5vcm1hbCBlbnRlciBrZXkgcHJlc3NcbiAgICAgICAgaWYgKGV2ZW50LmtleSA9PT0gJ0VudGVyJyAmJiAhZXZlbnQuc2hpZnRLZXkpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB0aGlzLmFkZENvbW1lbnQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEhlbHBlciBtZXRob2QgdG8gc2Nyb2xsIHRoZSBzZWxlY3RlZCBzdWdnZXN0aW9uIGludG8gdmlld1xuICAgIHByaXZhdGUgc2Nyb2xsU3VnZ2VzdGlvbkludG9WaWV3KCk6IHZvaWQge1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN1Z2dlc3Rpb25MaXN0ID0gdGhpcy5zdWdnZXN0aW9uUGFuZWw/Lm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcignLnN1Z2dlc3Rpb24tbGlzdCcpO1xuICAgICAgICAgICAgY29uc3Qgc2VsZWN0ZWRJdGVtID0gc3VnZ2VzdGlvbkxpc3Q/LnF1ZXJ5U2VsZWN0b3IoJy5zdWdnZXN0aW9uLWl0ZW0uc2VsZWN0ZWQnKTtcblxuICAgICAgICAgICAgaWYgKHN1Z2dlc3Rpb25MaXN0ICYmIHNlbGVjdGVkSXRlbSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxpc3RSZWN0ID0gc3VnZ2VzdGlvbkxpc3QuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgaXRlbVJlY3QgPSBzZWxlY3RlZEl0ZW0uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgc2VsZWN0ZWQgaXRlbSBpcyBvdXRzaWRlIHRoZSB2aXNpYmxlIGFyZWFcbiAgICAgICAgICAgICAgICBpZiAoaXRlbVJlY3QuYm90dG9tID4gbGlzdFJlY3QuYm90dG9tKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEl0ZW0gaXMgYmVsb3cgdGhlIHZpc2libGUgYXJlYVxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZEl0ZW0uc2Nyb2xsSW50b1ZpZXcoeyBibG9jazogJ2VuZCcsIGJlaGF2aW9yOiAnc21vb3RoJyB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGl0ZW1SZWN0LnRvcCA8IGxpc3RSZWN0LnRvcCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJdGVtIGlzIGFib3ZlIHRoZSB2aXNpYmxlIGFyZWFcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRJdGVtLnNjcm9sbEludG9WaWV3KHsgYmxvY2s6ICdzdGFydCcsIGJlaGF2aW9yOiAnc21vb3RoJyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIG9uRmlsZURvd25sb2FkKGZpbGU6IHsgbmFtZTogc3RyaW5nOyBzaXplOiBzdHJpbmcgfSkge1xuICAgICAgICB0aGlzLmZpbGVEb3dubG9hZC5lbWl0KGZpbGUpO1xuICAgIH1cblxuICAgIGdldCBncm91cGVkQ29tbWVudHMoKTogR3JvdXBlZENvbW1lbnRzW10ge1xuICAgICAgICByZXR1cm4gdGhpcy5jb21tZW50c1xuICAgICAgICAgICAgLnJlZHVjZSgoZ3JvdXBzOiBHcm91cGVkQ29tbWVudHNbXSwgY29tbWVudDogQ29tbWVudCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbW1lbnREYXRlID0gbmV3IERhdGUoY29tbWVudC5kYXRlKTtcbiAgICAgICAgICAgICAgICBjb21tZW50RGF0ZS5zZXRIb3VycygwLCAwLCAwLCAwKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nR3JvdXAgPSBncm91cHMuZmluZCgoZ3JvdXApID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZ3JvdXBEYXRlID0gbmV3IERhdGUoZ3JvdXAuZGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgIGdyb3VwRGF0ZS5zZXRIb3VycygwLCAwLCAwLCAwKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGdyb3VwRGF0ZS5nZXRUaW1lKCkgPT09IGNvbW1lbnREYXRlLmdldFRpbWUoKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmIChleGlzdGluZ0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nR3JvdXAuaXRlbXMucHVzaChjb21tZW50KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBncm91cHMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRlOiBjb21tZW50RGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1zOiBbY29tbWVudF1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGdyb3VwcztcbiAgICAgICAgICAgIH0sIFtdKVxuICAgICAgICAgICAgLnNvcnQoKGEsIGIpID0+IGEuZGF0ZS5nZXRUaW1lKCkgLSBiLmRhdGUuZ2V0VGltZSgpKTtcbiAgICB9XG5cbiAgICBnZXRTaG9ydEZpbGVOYW1lKGZpbGVuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICBpZiAoZmlsZW5hbWUubGVuZ3RoIDw9IDQpIHJldHVybiBmaWxlbmFtZTtcblxuICAgICAgICAvLyBHZXQgZmlsZSBleHRlbnNpb25cbiAgICAgICAgY29uc3QgbGFzdERvdEluZGV4ID0gZmlsZW5hbWUubGFzdEluZGV4T2YoJy4nKTtcbiAgICAgICAgY29uc3QgZXh0ZW5zaW9uID0gbGFzdERvdEluZGV4ICE9PSAtMSA/IGZpbGVuYW1lLnN1YnN0cmluZyhsYXN0RG90SW5kZXgpIDogJyc7XG5cbiAgICAgICAgLy8gVHJ1bmNhdGUgdGhlIG5hbWUgcGFydCBhbmQgYWRkIHRoZSBleHRlbnNpb25cbiAgICAgICAgY29uc3QgbmFtZVBhcnQgPSBmaWxlbmFtZS5zdWJzdHJpbmcoMCwgbGFzdERvdEluZGV4ICE9PSAtMSA/IGxhc3REb3RJbmRleCA6IGZpbGVuYW1lLmxlbmd0aCk7XG4gICAgICAgIHJldHVybiBuYW1lUGFydC5zdWJzdHJpbmcoMCwgNCkgKyAnLi4nICsgZXh0ZW5zaW9uO1xuICAgIH1cbn1cbiIsIjxjYXgtc2lkZWJhciBbKHZpc2libGUpXT1cInZpc2libGVcIiBbcG9zaXRpb25dPVwiJ3JpZ2h0J1wiIFtiYXNlWkluZGV4XT1cIjEwMDAwXCIgKG9uSGlkZSk9XCJvblNpZGViYXJIaWRlKClcIiBbaGVhZGVyVGV4dF09XCJzaWRlYmFySGVhZGVyXCI+XHJcbiAgICA8bmctdGVtcGxhdGUgY2F4VGVtcGxhdGU9XCJjb250ZW50XCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImNheC1jb21tZW50cy1jb250YWluZXJcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNheC1jb21tZW50cy1saXN0XCIgI2NvbW1lbnRzTGlzdD5cclxuICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGdyb3VwIG9mIGdyb3VwZWRDb21tZW50c1wiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjYXgtZGF0ZS1oZWFkZXJcIj57eyBmb3JtYXREYXRlKGdyb3VwLmRhdGUpIH19PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImNheC1jb21tZW50LWl0ZW1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgY29tbWVudCBvZiBncm91cC5pdGVtczsgbGV0IGkgPSBpbmRleFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cIntcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjYXgtdXNlci1jb21tZW50JzogIWNvbW1lbnQuaXNBZG1pbixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjYXgtYWRtaW4tY29tbWVudCc6IGNvbW1lbnQuaXNBZG1pbixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb25zZWN1dGl2ZS1tZXNzYWdlJzogaSA+IDAgJiYgY29tbWVudC5pc0FkbWluID09PSBncm91cC5pdGVtc1tpLTFdLmlzQWRtaW4gJiYgY29tbWVudC5zZW5kZXIgPT09IGdyb3VwLml0ZW1zW2ktMV0uc2VuZGVyLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ25ldy1zZW5kZXInOiBpID4gMCAmJiBjb21tZW50LnNlbmRlciAhPT0gZ3JvdXAuaXRlbXNbaS0xXS5zZW5kZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbmV3LWRhdGUnOiBpID09PSAwICYmIGdyb3VwLml0ZW1zLmxlbmd0aCA+IDBcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVwiXHJcbiAgICAgICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8IS0tIFVzZXIgTWVzc2FnZSAoTGVmdCBBbGlnbmVkKSAtLT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFjb21tZW50LmlzQWRtaW5cIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjYXgtY29tbWVudGJveC1hdmF0YXItY29udGFpbmVyXCIgKm5nSWY9XCJpID09PSAwIHx8IGdyb3VwLml0ZW1zW2ktMV0uc2VuZGVyICE9PSBjb21tZW50LnNlbmRlclwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxjYXgtYXZhdGFyIFtsYWJlbF09XCJjb21tZW50LnNlbmRlcj8uc3Vic3RyaW5nKDAsIDIpLnRvVXBwZXJDYXNlKCkgfHwgJ1UnXCIgW2F2YXRhclNpemVdPVwiJ3hzJ1wiIFtzaGFwZV09XCInY2lyY2xlJ1wiIHN0eWxlY2xhc3M9XCJjYXgtY29tbWVudGJveC1hdmF0YXJcIj4gPC9jYXgtYXZhdGFyPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2F4LWNvbW1lbnQtY29udGVudFwiIFtjbGFzcy5uby1hdmF0YXJdPVwiaSA+IDAgJiYgZ3JvdXAuaXRlbXNbaS0xXS5zZW5kZXIgPT09IGNvbW1lbnQuc2VuZGVyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNheC1jb21tZW50LXNlbmRlclwiICpuZ0lmPVwiaSA9PT0gMCB8fCBncm91cC5pdGVtc1tpLTFdLnNlbmRlciAhPT0gY29tbWVudC5zZW5kZXJcIj57e2NvbW1lbnQuc2VuZGVyfX08L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2F4LWZpbGUtYXR0YWNobWVudFwiICpuZ0lmPVwiY29tbWVudC5maWxlcz8ubGVuZ3RoXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IGZpbGUgb2YgY29tbWVudC5maWxlc1wiIGNsYXNzPVwiZmlsZS1pdGVtXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmlsZS1kZXRhaWxzXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJmaWxlLW5hbWVcIj57eyBmaWxlLm5hbWUuc2xpY2UoMCwgMjApIH19e3sgZmlsZS5uYW1lLmluY2x1ZGVzKCcuJykgPyAnLicgKyBmaWxlLm5hbWUuc3BsaXQoJy4nKS5wb3AoKSA6ICcnIH19PC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZmlsZS1zaXplXCI+e3tmaWxlLnNpemV9fTwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJjYXggY2F4LWRvd25sb2FkXCIgKGNsaWNrKT1cIm9uRmlsZURvd25sb2FkKGZpbGUpXCIgcm9sZT1cImJ1dHRvblwiIHRhYmluZGV4PVwiMFwiPjwvaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNheC1jb21tZW50LXRleHRcIiBbaW5uZXJIVE1MXT1cImZvcm1hdE1lc3NhZ2VXaXRoVGFncyhjb21tZW50LnRleHQpXCI+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJjYXgtY29tbWVudC1kYXRlXCI+e3sgY29tbWVudC5kYXRlIHwgZGF0ZTogJ3Nob3J0VGltZScgfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8IS0tIEFkbWluIE1lc3NhZ2UgKFJpZ2h0IEFsaWduZWQpIC0tPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiY29tbWVudC5pc0FkbWluXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2F4LWNvbW1lbnQtY29udGVudCBhZG1pblwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjYXgtZmlsZS1hdHRhY2htZW50XCIgKm5nSWY9XCJjb21tZW50LmZpbGVzPy5sZW5ndGhcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgZmlsZSBvZiBjb21tZW50LmZpbGVzXCIgY2xhc3M9XCJmaWxlLWl0ZW1cIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWxlLWRldGFpbHNcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImZpbGUtbmFtZVwiPnt7IGZpbGUubmFtZS5zbGljZSgwLCAyMCkgfX17eyBmaWxlLm5hbWUuaW5jbHVkZXMoJy4nKSA/ICcuJyArIGZpbGUubmFtZS5zcGxpdCgnLicpLnBvcCgpIDogJycgfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJmaWxlLXNpemVcIj57e2ZpbGUuc2l6ZX19PC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImNheCBjYXgtZG93bmxvYWRcIiAoY2xpY2spPVwib25GaWxlRG93bmxvYWQoZmlsZSlcIiByb2xlPVwiYnV0dG9uXCIgdGFiaW5kZXg9XCIwXCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2F4LWNvbW1lbnQtdGV4dFwiIFtpbm5lckhUTUxdPVwiZm9ybWF0TWVzc2FnZVdpdGhUYWdzKGNvbW1lbnQudGV4dClcIj48L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImNheC1jb21tZW50LWRhdGVcIj57eyBjb21tZW50LmRhdGUgfCBkYXRlOiAnc2hvcnRUaW1lJyB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICA8Y2F4LW92ZXJsYXkgI3N1Z2dlc3Rpb25QYW5lbCBbKHZpc2libGUpXT1cIm92ZXJsYXlWaXNpYmxlXCIgW2FwcGVuZFRvXT1cImlucHV0VGV4dFwiIChvbkhpZGUpPVwib25TdWdnZXN0aW9uUGFuZWxIaWRlKClcIiBbc3R5bGVDbGFzc109XCInc3VnZ2VzdGlvbi1wYW5lbCdcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwic3VnZ2VzdGlvbi1saXN0XCI+XHJcbiAgICAgICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IGl0ZW0gb2YgZmlsdGVyZWRTdWdnZXN0aW9uczsgbGV0IGkgPSBpbmRleFwiIGNsYXNzPVwic3VnZ2VzdGlvbi1pdGVtXCIgW25nQ2xhc3NdPVwieydzZWxlY3RlZCc6IHNlbGVjdGVkU3VnZ2VzdGlvbkluZGV4ID09PSBpfVwiIChjbGljayk9XCJvblN1Z2dlc3Rpb25TZWxlY3QoaXRlbSlcIiAobW91c2VlbnRlcik9XCJzZWxlY3RlZFN1Z2dlc3Rpb25JbmRleCA9IGlcIj5cclxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwic3VnZ2VzdGlvbi1sYWJlbFwiPnt7aXRlbS5uYW1lfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9XCJzdWdnZXN0aW9uLWlkXCIgKm5nSWY9XCJjdXJyZW50VG9rZW5UeXBlID09PSAnbWVudGlvbidcIj57e2l0ZW0uaWR9fTwvc21hbGw+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9jYXgtb3ZlcmxheT5cclxuICAgIDxjYXgtb3ZlcmxheVxyXG4gICAgICAgIFsodmlzaWJsZSldPVwiZmlsZXNPdmVybGF5VmlzaWJsZVwiXHJcbiAgICAgICAgW2FwcGVuZFRvXT1cImNvdW50Q2hpcFwiXHJcbiAgICAgICAgW3Nob3dUcmFuc2l0aW9uT3B0aW9uc109XCInMC4xMnMgZWFzZS1vdXQnXCJcclxuICAgICAgICBbaGlkZVRyYW5zaXRpb25PcHRpb25zXT1cIicwLjFzIGVhc2UtaW4nXCJcclxuICAgICAgICBbc3R5bGVdPVwieyB3aWR0aDogJzIyNHB4JywgcmlnaHQ6ICc1JScgfVwiXHJcbiAgICAgICAgc3R5bGVDbGFzcz1cImZpbGVzLWxpc3Qtb3ZlcmxheVwiXHJcbiAgICAgICAgKG9uSGlkZSk9XCJoaWRlRmlsZXNPdmVybGF5KClcIlxyXG4gICAgPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmaWxlcy1vdmVybGF5LWNvbnRlbnRcIj5cclxuICAgICAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgZmlsZSBvZiBzZWxlY3RlZEZpbGVzLnNsaWNlKDQpOyBsZXQgaSA9IGluZGV4XCIgY2xhc3M9XCJmaWxlLWl0ZW1cIj5cclxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZmlsZS1uYW1lXCI+e3tnZXRTaG9ydEZpbGVOYW1lKGZpbGUubmFtZSl9fTwvc3Bhbj5cclxuICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiY2F4IGNheC1jbG9zZS1jaXJjbGVcIiAoY2xpY2spPVwicmVtb3ZlRmlsZShpICsgNClcIj48L2k+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9jYXgtb3ZlcmxheT5cclxuXHJcbiAgICA8bmctdGVtcGxhdGUgY2F4VGVtcGxhdGU9XCJmb290ZXJcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2hhdC1mb290ZXJcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlbGVjdGVkLWZpbGVzXCIgKm5nSWY9XCJzZWxlY3RlZEZpbGVzLmxlbmd0aCA+IDBcIj5cclxuICAgICAgICAgICAgICAgIDxjYXgtY2hpcCAqbmdGb3I9XCJsZXQgZmlsZSBvZiBzZWxlY3RlZEZpbGVzLnNsaWNlKDAsIDQpOyBsZXQgaSA9IGluZGV4XCIgW2xhYmVsXT1cImdldFNob3J0RmlsZU5hbWUoZmlsZS5uYW1lKVwiIFtyZW1vdmFibGVdPVwidHJ1ZVwiIFtzaXplXT1cIidsZydcIiAob25SZW1vdmUpPVwicmVtb3ZlRmlsZShpLCB0cnVlKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBjYXhUZW1wbGF0ZT1cImNvbnRlbnRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJjYXggY2F4LXBhcGVyY2xpcFwiPjwvaT5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgICAgICAgICAgPC9jYXgtY2hpcD5cclxuICAgICAgICAgICAgICAgIDxjYXgtY2hpcCAjY291bnRDaGlwICpuZ0lmPVwic2VsZWN0ZWRGaWxlcy5sZW5ndGggPiA0XCIgW2xhYmVsXT1cIicrJyArIGdldE92ZXJmbG93Q291bnQoKVwiIFtzaXplXT1cIidsZydcIiAobW91c2VlbnRlcik9XCJzaG93RmlsZXNPdmVybGF5KCRldmVudClcIj4gPC9jYXgtY2hpcD5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjYXgtY2hhdC1pbnB1dC1jb250YWluZXJcIj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC13cmFwcGVyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGNheC1pbnB1dHRleHRcclxuICAgICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJuZXdDb21tZW50XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW3NpemVdPVwiJ2xnJ1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtyaWdodEljb25dPVwidHJ1ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtjbGVhckljb25dPVwiZmFsc2VcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbcmlnaHRJY29uQ2xhc3NdPVwiJ2NheCBjYXgtcGFwZXJjbGlwJ1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtyaWdodEljb25DbGlja2FibGVdPVwidHJ1ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIChyaWdodEljb25DbGljayk9XCJvbkZpbGVJY29uQ2xpY2soJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiQ29tbWVudCBvciBtZW50aW9uIG90aGVycyB3aXRoIEAsIOKAmCPigJkgZm9yIGNvbHVtbnNcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAoa2V5dXApPVwiaGFuZGxlS2V5VXAoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIChrZXlkb3duKT1cIm9uS2V5RG93bigkZXZlbnQpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2NsYXNzXT1cInsnY2hhdC1pbnB1dCc6IHRydWUsICdhZG1pbi1pbnB1dCc6IGlzQWRtaW5TZW5kZXJ9XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlXT1cInsnYm9yZGVyLXJhZGl1cyc6ICc4cHgnLCBiYWNrZ3JvdW5kOiAnI2ZmZmZmZid9XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgI2lucHV0VGV4dFxyXG4gICAgICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgICA8L2NheC1pbnB1dHRleHQ+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgICAgICA8Y2F4LWJ1dHRvbiBbaWNvbl09XCInY2F4IGNheC1wbGFpbidcIiBbc2V2ZXJpdHldPVwiJ3ByaW1hcnknXCIgW3NpemVdPVwiJ2xhcmdlJ1wiIChjbGljayk9XCJhZGRDb21tZW50KClcIiBbZGlzYWJsZWRdPVwiIW5ld0NvbW1lbnQudHJpbSgpICYmIHNlbGVjdGVkRmlsZXMubGVuZ3RoID09PSAwXCIgY2xhc3M9XCJzZW5kLWJ1dHRvblwiPiA8L2NheC1idXR0b24+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgPGlucHV0ICNmaWxlSW5wdXQgdHlwZT1cImZpbGVcIiAoY2hhbmdlKT1cIm9uRmlsZVNlbGVjdCgkZXZlbnQpXCIgc3R5bGU9XCJkaXNwbGF5OiBub25lXCIgYWNjZXB0PVwiKi8qXCIgbXVsdGlwbGUgLz5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvbmctdGVtcGxhdGU+XHJcbjwvY2F4LXNpZGViYXI+XHJcbiJdfQ==