@cqa-lib/cqa-ui 1.1.486 → 1.1.487

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.
@@ -0,0 +1,307 @@
1
+ import { ChangeDetectionStrategy, Component, EventEmitter, HostListener, Input, Output, ViewChild } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ import * as i1 from "@angular/common";
4
+ const VAR_NAME_REGEX = /^[A-Za-z_][A-Za-z0-9_]*$/;
5
+ const VAR_TOKEN_REGEX = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
6
+ export class MixedVariableInputComponent {
7
+ constructor(cdr, hostRef) {
8
+ this.cdr = cdr;
9
+ this.hostRef = hostRef;
10
+ this.value = '';
11
+ this.placeholder = 'Text Input';
12
+ this.disabled = false;
13
+ this.valueChange = new EventEmitter();
14
+ this.showSuggestion = false;
15
+ this.pendingWord = '';
16
+ this.lastEmitted = '';
17
+ }
18
+ onDocumentMouseDown(event) {
19
+ if (!this.showSuggestion)
20
+ return;
21
+ const target = event.target;
22
+ if (this.hostRef.nativeElement.contains(target))
23
+ return;
24
+ this.hideSuggestion();
25
+ }
26
+ ngOnChanges(changes) {
27
+ if (changes['value'] && this.editorRef) {
28
+ const incoming = changes['value'].currentValue ?? '';
29
+ if (incoming !== this.lastEmitted) {
30
+ this.render(incoming);
31
+ }
32
+ }
33
+ }
34
+ ngAfterViewInit() {
35
+ this.render(this.value || '');
36
+ }
37
+ onInput() {
38
+ const str = this.serialize();
39
+ this.lastEmitted = str;
40
+ this.valueChange.emit(str);
41
+ this.autoChipify();
42
+ this.refreshSuggestion();
43
+ }
44
+ onKeyDown(event) {
45
+ if (event.key === 'Enter') {
46
+ event.preventDefault();
47
+ return;
48
+ }
49
+ if (event.key === 'Escape') {
50
+ if (this.showSuggestion) {
51
+ event.preventDefault();
52
+ this.hideSuggestion();
53
+ }
54
+ return;
55
+ }
56
+ if (event.key === 'Backspace') {
57
+ const node = this.getNodeBeforeCaret();
58
+ if (node && node.classList?.contains('cqa-var-chip')) {
59
+ event.preventDefault();
60
+ node.remove();
61
+ this.onInput();
62
+ }
63
+ }
64
+ }
65
+ onEditorBlur() {
66
+ // Small timeout so clicks on suggestion buttons register before hiding.
67
+ setTimeout(() => this.hideSuggestion(), 150);
68
+ }
69
+ addAsText() {
70
+ this.hideSuggestion();
71
+ this.editorRef.nativeElement.focus();
72
+ }
73
+ addAsVariable() {
74
+ const name = (this.pendingWord || '').trim();
75
+ if (!name || !VAR_NAME_REGEX.test(name)) {
76
+ this.hideSuggestion();
77
+ return;
78
+ }
79
+ this.insertChipReplacingCurrentWord(name);
80
+ this.hideSuggestion();
81
+ const str = this.serialize();
82
+ this.lastEmitted = str;
83
+ this.valueChange.emit(str);
84
+ }
85
+ refreshSuggestion() {
86
+ const word = this.getCurrentWord();
87
+ if (word && VAR_NAME_REGEX.test(word)) {
88
+ this.pendingWord = word;
89
+ this.showSuggestion = true;
90
+ }
91
+ else {
92
+ this.pendingWord = '';
93
+ this.showSuggestion = false;
94
+ }
95
+ this.cdr.markForCheck();
96
+ }
97
+ hideSuggestion() {
98
+ if (!this.showSuggestion && !this.pendingWord)
99
+ return;
100
+ this.showSuggestion = false;
101
+ this.pendingWord = '';
102
+ this.cdr.markForCheck();
103
+ }
104
+ autoChipify() {
105
+ const editor = this.editorRef.nativeElement;
106
+ const textNodes = [];
107
+ editor.childNodes.forEach((n) => {
108
+ if (n.nodeType === Node.TEXT_NODE)
109
+ textNodes.push(n);
110
+ });
111
+ for (const tn of textNodes) {
112
+ const text = tn.nodeValue || '';
113
+ VAR_TOKEN_REGEX.lastIndex = 0;
114
+ if (!VAR_TOKEN_REGEX.test(text))
115
+ continue;
116
+ VAR_TOKEN_REGEX.lastIndex = 0;
117
+ const parent = tn.parentNode;
118
+ if (!parent)
119
+ continue;
120
+ const frag = document.createDocumentFragment();
121
+ let lastIndex = 0;
122
+ let m;
123
+ while ((m = VAR_TOKEN_REGEX.exec(text)) !== null) {
124
+ if (m.index > lastIndex) {
125
+ frag.appendChild(document.createTextNode(text.slice(lastIndex, m.index)));
126
+ }
127
+ frag.appendChild(this.buildChip(m[1]));
128
+ lastIndex = m.index + m[0].length;
129
+ }
130
+ if (lastIndex < text.length) {
131
+ frag.appendChild(document.createTextNode(text.slice(lastIndex)));
132
+ }
133
+ parent.replaceChild(frag, tn);
134
+ this.placeCaretAtEnd();
135
+ const str = this.serialize();
136
+ this.lastEmitted = str;
137
+ this.valueChange.emit(str);
138
+ return;
139
+ }
140
+ }
141
+ render(value) {
142
+ const editor = this.editorRef.nativeElement;
143
+ editor.innerHTML = '';
144
+ if (!value)
145
+ return;
146
+ VAR_TOKEN_REGEX.lastIndex = 0;
147
+ let lastIndex = 0;
148
+ let m;
149
+ while ((m = VAR_TOKEN_REGEX.exec(value)) !== null) {
150
+ if (m.index > lastIndex) {
151
+ editor.appendChild(document.createTextNode(value.slice(lastIndex, m.index)));
152
+ }
153
+ editor.appendChild(this.buildChip(m[1]));
154
+ lastIndex = m.index + m[0].length;
155
+ }
156
+ if (lastIndex < value.length) {
157
+ editor.appendChild(document.createTextNode(value.slice(lastIndex)));
158
+ }
159
+ }
160
+ serialize() {
161
+ const editor = this.editorRef.nativeElement;
162
+ let out = '';
163
+ editor.childNodes.forEach((n) => {
164
+ if (n.nodeType === Node.TEXT_NODE) {
165
+ out += (n.nodeValue || '').replace(/\u00a0/g, ' ');
166
+ }
167
+ else if (n.nodeType === Node.ELEMENT_NODE) {
168
+ const el = n;
169
+ if (el.classList.contains('cqa-var-chip')) {
170
+ const name = el.getAttribute('data-var') || '';
171
+ if (name)
172
+ out += '${' + name + '}';
173
+ }
174
+ else {
175
+ out += el.textContent || '';
176
+ }
177
+ }
178
+ });
179
+ return out;
180
+ }
181
+ buildChip(name) {
182
+ const chip = document.createElement('span');
183
+ chip.className = 'cqa-var-chip';
184
+ chip.setAttribute('contenteditable', 'false');
185
+ chip.setAttribute('data-var', name);
186
+ const label = document.createElement('span');
187
+ label.className = 'cqa-var-chip__label';
188
+ label.textContent = '${' + name + '}';
189
+ const remove = document.createElement('span');
190
+ remove.className = 'cqa-var-chip__remove';
191
+ remove.textContent = '×';
192
+ remove.addEventListener('mousedown', (e) => e.preventDefault());
193
+ remove.addEventListener('click', (e) => {
194
+ e.preventDefault();
195
+ e.stopPropagation();
196
+ chip.remove();
197
+ this.onInput();
198
+ });
199
+ chip.appendChild(label);
200
+ chip.appendChild(remove);
201
+ return chip;
202
+ }
203
+ getSelectionRange() {
204
+ const sel = window.getSelection();
205
+ if (!sel || sel.rangeCount === 0)
206
+ return null;
207
+ const range = sel.getRangeAt(0);
208
+ if (!this.editorRef.nativeElement.contains(range.startContainer))
209
+ return null;
210
+ return range;
211
+ }
212
+ getNodeBeforeCaret() {
213
+ const range = this.getSelectionRange();
214
+ if (!range || !range.collapsed)
215
+ return null;
216
+ const { startContainer, startOffset } = range;
217
+ if (startContainer.nodeType === Node.TEXT_NODE) {
218
+ if (startOffset > 0)
219
+ return null;
220
+ return startContainer.previousSibling;
221
+ }
222
+ return startContainer.childNodes[startOffset - 1] || null;
223
+ }
224
+ getCurrentWord() {
225
+ const range = this.getSelectionRange();
226
+ if (!range)
227
+ return '';
228
+ const node = range.startContainer;
229
+ if (node.nodeType !== Node.TEXT_NODE)
230
+ return '';
231
+ const text = node.nodeValue || '';
232
+ const before = text.slice(0, range.startOffset);
233
+ const match = before.match(/([A-Za-z_][A-Za-z0-9_]*)$/);
234
+ return match ? match[1] : '';
235
+ }
236
+ insertChipReplacingCurrentWord(name) {
237
+ const range = this.getSelectionRange();
238
+ const chip = this.buildChip(name);
239
+ if (!range) {
240
+ this.editorRef.nativeElement.appendChild(chip);
241
+ this.placeCaretAfter(chip);
242
+ return;
243
+ }
244
+ const node = range.startContainer;
245
+ if (node.nodeType === Node.TEXT_NODE) {
246
+ const text = node.nodeValue || '';
247
+ const before = text.slice(0, range.startOffset);
248
+ const after = text.slice(range.startOffset);
249
+ const wordMatch = before.match(/([A-Za-z_][A-Za-z0-9_]*)$/);
250
+ const beforeKept = wordMatch ? before.slice(0, before.length - wordMatch[1].length) : before;
251
+ const parent = node.parentNode;
252
+ const frag = document.createDocumentFragment();
253
+ if (beforeKept)
254
+ frag.appendChild(document.createTextNode(beforeKept));
255
+ frag.appendChild(chip);
256
+ if (after)
257
+ frag.appendChild(document.createTextNode(after));
258
+ parent.replaceChild(frag, node);
259
+ }
260
+ else {
261
+ range.insertNode(chip);
262
+ }
263
+ this.placeCaretAfter(chip);
264
+ }
265
+ placeCaretAfter(node) {
266
+ const sel = window.getSelection();
267
+ if (!sel)
268
+ return;
269
+ const range = document.createRange();
270
+ range.setStartAfter(node);
271
+ range.collapse(true);
272
+ sel.removeAllRanges();
273
+ sel.addRange(range);
274
+ }
275
+ placeCaretAtEnd() {
276
+ const editor = this.editorRef.nativeElement;
277
+ const sel = window.getSelection();
278
+ if (!sel)
279
+ return;
280
+ const range = document.createRange();
281
+ range.selectNodeContents(editor);
282
+ range.collapse(false);
283
+ sel.removeAllRanges();
284
+ sel.addRange(range);
285
+ }
286
+ }
287
+ MixedVariableInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MixedVariableInputComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
288
+ MixedVariableInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: MixedVariableInputComponent, selector: "cqa-mixed-variable-input", inputs: { value: "value", placeholder: "placeholder", disabled: "disabled" }, outputs: { valueChange: "valueChange" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)" }, classAttribute: "cqa-ui-root" }, viewQueries: [{ propertyName: "editorRef", first: true, predicate: ["editor"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-mixed-var-wrapper\">\n <div\n #editor\n class=\"cqa-mixed-var-editor\"\n role=\"textbox\"\n spellcheck=\"false\"\n [attr.contenteditable]=\"!disabled\"\n [attr.data-placeholder]=\"placeholder\"\n (input)=\"onInput()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onEditorBlur()\">\n </div>\n\n <div\n *ngIf=\"showSuggestion\"\n class=\"cqa-mixed-var-suggest\"\n (mousedown)=\"$event.preventDefault()\">\n <button type=\"button\" class=\"cqa-mixed-var-suggest__item\" (click)=\"addAsText()\">\n Add as Text <span class=\"cqa-mixed-var-suggest__hint\">\"{{ pendingWord }}\"</span>\n </button>\n <button type=\"button\" class=\"cqa-mixed-var-suggest__item cqa-mixed-var-suggest__item--primary\" (click)=\"addAsVariable()\">\n Add as local variable <span class=\"cqa-mixed-var-suggest__hint\">${{ '{' }}{{ pendingWord }}{{ '}' }}</span>\n </button>\n </div>\n</div>\n", styles: [":host{display:block;width:100%;position:relative}.cqa-mixed-var-wrapper{position:relative;width:100%}.cqa-mixed-var-editor{width:100%;box-sizing:border-box;min-height:38px;border:1px solid #d1d5db;border-radius:8px;padding:8px 12px;font-size:14px;color:#111827;background:#fff;line-height:22px;outline:none;white-space:nowrap;overflow-x:auto;overflow-y:hidden;word-break:normal}.cqa-mixed-var-editor:focus{border-color:#6366f1;box-shadow:0 0 0 1px #6366f1}.cqa-mixed-var-editor:empty:before{content:attr(data-placeholder);color:#9ca3af;pointer-events:none}:host ::ng-deep .cqa-var-chip{display:inline-flex;align-items:center;gap:4px;margin:0 4px;padding:2px 4px 2px 8px;border-radius:6px;background-color:#eef0ff;border:1px solid #8a8cf4;color:#3730a3;font-size:12px;line-height:18px;-webkit-user-select:none;user-select:none;vertical-align:baseline;white-space:nowrap}:host ::ng-deep .cqa-var-chip__label{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-weight:500}:host ::ng-deep .cqa-var-chip__remove{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:50%;background:transparent;color:#6366f1;font-size:13px;line-height:1;cursor:pointer;transition:background-color .12s ease,color .12s ease}:host ::ng-deep .cqa-var-chip__remove:hover{background:#c7d2fe;color:#312e81}.cqa-mixed-var-suggest{position:absolute;z-index:50;top:calc(100% + 4px);left:0;right:0;background:#fff;border:1px solid #e5e7eb;border-radius:8px;box-shadow:0 8px 24px #00000014;padding:4px;display:flex;flex-direction:column}.cqa-mixed-var-suggest__item{display:flex;align-items:center;justify-content:flex-start;gap:8px;width:100%;min-width:0;padding:8px 10px;font-size:13px;color:#374151;background:#fff;border:none;border-radius:6px;cursor:pointer;text-align:left;white-space:nowrap}.cqa-mixed-var-suggest__item:hover{background:#f3f4f6}.cqa-mixed-var-suggest__item--primary{color:#4338ca;font-weight:500}.cqa-mixed-var-suggest__hint{flex:1 1 auto;min-width:0;color:#9ca3af;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], directives: [{ type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
289
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MixedVariableInputComponent, decorators: [{
290
+ type: Component,
291
+ args: [{ selector: 'cqa-mixed-variable-input', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-mixed-var-wrapper\">\n <div\n #editor\n class=\"cqa-mixed-var-editor\"\n role=\"textbox\"\n spellcheck=\"false\"\n [attr.contenteditable]=\"!disabled\"\n [attr.data-placeholder]=\"placeholder\"\n (input)=\"onInput()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onEditorBlur()\">\n </div>\n\n <div\n *ngIf=\"showSuggestion\"\n class=\"cqa-mixed-var-suggest\"\n (mousedown)=\"$event.preventDefault()\">\n <button type=\"button\" class=\"cqa-mixed-var-suggest__item\" (click)=\"addAsText()\">\n Add as Text <span class=\"cqa-mixed-var-suggest__hint\">\"{{ pendingWord }}\"</span>\n </button>\n <button type=\"button\" class=\"cqa-mixed-var-suggest__item cqa-mixed-var-suggest__item--primary\" (click)=\"addAsVariable()\">\n Add as local variable <span class=\"cqa-mixed-var-suggest__hint\">${{ '{' }}{{ pendingWord }}{{ '}' }}</span>\n </button>\n </div>\n</div>\n", styles: [":host{display:block;width:100%;position:relative}.cqa-mixed-var-wrapper{position:relative;width:100%}.cqa-mixed-var-editor{width:100%;box-sizing:border-box;min-height:38px;border:1px solid #d1d5db;border-radius:8px;padding:8px 12px;font-size:14px;color:#111827;background:#fff;line-height:22px;outline:none;white-space:nowrap;overflow-x:auto;overflow-y:hidden;word-break:normal}.cqa-mixed-var-editor:focus{border-color:#6366f1;box-shadow:0 0 0 1px #6366f1}.cqa-mixed-var-editor:empty:before{content:attr(data-placeholder);color:#9ca3af;pointer-events:none}:host ::ng-deep .cqa-var-chip{display:inline-flex;align-items:center;gap:4px;margin:0 4px;padding:2px 4px 2px 8px;border-radius:6px;background-color:#eef0ff;border:1px solid #8a8cf4;color:#3730a3;font-size:12px;line-height:18px;-webkit-user-select:none;user-select:none;vertical-align:baseline;white-space:nowrap}:host ::ng-deep .cqa-var-chip__label{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-weight:500}:host ::ng-deep .cqa-var-chip__remove{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:50%;background:transparent;color:#6366f1;font-size:13px;line-height:1;cursor:pointer;transition:background-color .12s ease,color .12s ease}:host ::ng-deep .cqa-var-chip__remove:hover{background:#c7d2fe;color:#312e81}.cqa-mixed-var-suggest{position:absolute;z-index:50;top:calc(100% + 4px);left:0;right:0;background:#fff;border:1px solid #e5e7eb;border-radius:8px;box-shadow:0 8px 24px #00000014;padding:4px;display:flex;flex-direction:column}.cqa-mixed-var-suggest__item{display:flex;align-items:center;justify-content:flex-start;gap:8px;width:100%;min-width:0;padding:8px 10px;font-size:13px;color:#374151;background:#fff;border:none;border-radius:6px;cursor:pointer;text-align:left;white-space:nowrap}.cqa-mixed-var-suggest__item:hover{background:#f3f4f6}.cqa-mixed-var-suggest__item--primary{color:#4338ca;font-weight:500}.cqa-mixed-var-suggest__hint{flex:1 1 auto;min-width:0;color:#9ca3af;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
292
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { value: [{
293
+ type: Input
294
+ }], placeholder: [{
295
+ type: Input
296
+ }], disabled: [{
297
+ type: Input
298
+ }], valueChange: [{
299
+ type: Output
300
+ }], editorRef: [{
301
+ type: ViewChild,
302
+ args: ['editor', { static: true }]
303
+ }], onDocumentMouseDown: [{
304
+ type: HostListener,
305
+ args: ['document:mousedown', ['$event']]
306
+ }] } });
307
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWl4ZWQtdmFyaWFibGUtaW5wdXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9taXhlZC12YXJpYWJsZS1pbnB1dC9taXhlZC12YXJpYWJsZS1pbnB1dC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL21peGVkLXZhcmlhYmxlLWlucHV0L21peGVkLXZhcmlhYmxlLWlucHV0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBaUIsdUJBQXVCLEVBQXFCLFNBQVMsRUFBYyxZQUFZLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBYSxNQUFNLEVBQWlCLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7O0FBT2pNLE1BQU0sY0FBYyxHQUFHLDBCQUEwQixDQUFDO0FBQ2xELE1BQU0sZUFBZSxHQUFHLGlDQUFpQyxDQUFDO0FBUzFELE1BQU0sT0FBTywyQkFBMkI7SUFjdEMsWUFDVSxHQUFzQixFQUN0QixPQUFnQztRQURoQyxRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQUN0QixZQUFPLEdBQVAsT0FBTyxDQUF5QjtRQWZqQyxVQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ1gsZ0JBQVcsR0FBRyxZQUFZLENBQUM7UUFDM0IsYUFBUSxHQUFHLEtBQUssQ0FBQztRQUVoQixnQkFBVyxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFJbkQsbUJBQWMsR0FBRyxLQUFLLENBQUM7UUFDdkIsZ0JBQVcsR0FBRyxFQUFFLENBQUM7UUFFVCxnQkFBVyxHQUFHLEVBQUUsQ0FBQztJQUt0QixDQUFDO0lBR0osbUJBQW1CLENBQUMsS0FBaUI7UUFDbkMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjO1lBQUUsT0FBTztRQUNqQyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBYyxDQUFDO1FBQ3BDLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMs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QUFDO1FBQ2pDLEtBQUssQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdEIsR0FBRyxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3RCLEdBQUcsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdEIsQ0FBQzs7d0hBNVJVLDJCQUEyQjs0R0FBM0IsMkJBQTJCLDRhQ2pCeEMsZzdCQXlCQTsyRkRSYSwyQkFBMkI7a0JBUHZDLFNBQVM7K0JBQ0UsMEJBQTBCLG1CQUduQix1QkFBdUIsQ0FBQyxNQUFNLFFBQ3pDLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRTtpSUFHckIsS0FBSztzQkFBYixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFFSSxXQUFXO3NCQUFwQixNQUFNO2dCQUVnQyxTQUFTO3NCQUEvQyxTQUFTO3VCQUFDLFFBQVEsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBYXJDLG1CQUFtQjtzQkFEbEIsWUFBWTt1QkFBQyxvQkFBb0IsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIEhvc3RMaXN0ZW5lciwgSW5wdXQsIE9uQ2hhbmdlcywgT3V0cHV0LCBTaW1wbGVDaGFuZ2VzLCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuZXhwb3J0IGludGVyZmFjZSBNaXhlZFNlZ21lbnQge1xuICB0eXBlOiAndGV4dCcgfCAndmFyaWFibGUnO1xuICB2YWx1ZTogc3RyaW5nO1xufVxuXG5jb25zdCBWQVJfTkFNRV9SRUdFWCA9IC9eW0EtWmEtel9dW0EtWmEtejAtOV9dKiQvO1xuY29uc3QgVkFSX1RPS0VOX1JFR0VYID0gL1xcJFxceyhbQS1aYS16X11bQS1aYS16MC05X10qKVxcfS9nO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjcWEtbWl4ZWQtdmFyaWFibGUtaW5wdXQnLFxuICB0ZW1wbGF0ZVVybDogJy4vbWl4ZWQtdmFyaWFibGUtaW5wdXQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9taXhlZC12YXJpYWJsZS1pbnB1dC5jb21wb25lbnQuY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBob3N0OiB7IGNsYXNzOiAnY3FhLXVpLXJvb3QnIH0sXG59KVxuZXhwb3J0IGNsYXNzIE1peGVkVmFyaWFibGVJbnB1dENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgQWZ0ZXJWaWV3SW5pdCB7XG4gIEBJbnB1dCgpIHZhbHVlID0gJyc7XG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyID0gJ1RleHQgSW5wdXQnO1xuICBASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuXG4gIEBPdXRwdXQoKSB2YWx1ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIEBWaWV3Q2hpbGQoJ2VkaXRvcicsIHsgc3RhdGljOiB0cnVlIH0pIGVkaXRvclJlZiE6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+O1xuXG4gIHNob3dTdWdnZXN0aW9uID0gZmFsc2U7XG4gIHBlbmRpbmdXb3JkID0gJyc7XG5cbiAgcHJpdmF0ZSBsYXN0RW1pdHRlZCA9ICcnO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZiwgXG4gICAgcHJpdmF0ZSBob3N0UmVmOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PlxuICApIHt9XG5cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6bW91c2Vkb3duJywgWyckZXZlbnQnXSlcbiAgb25Eb2N1bWVudE1vdXNlRG93bihldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5zaG93U3VnZ2VzdGlvbikgcmV0dXJuO1xuICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldCBhcyBOb2RlO1xuICAgIGlmICh0aGlzLmhvc3RSZWYubmF0aXZlRWxlbWVudC5jb250YWlucyh0YXJnZXQpKSByZXR1cm47XG4gICAgdGhpcy5oaWRlU3VnZ2VzdGlvbigpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzWyd2YWx1ZSddICYmIHRoaXMuZWRpdG9yUmVmKSB7XG4gICAgICBjb25zdCBpbmNvbWluZyA9IGNoYW5nZXNbJ3ZhbHVlJ10uY3VycmVudFZhbHVlID8/ICcnO1xuICAgICAgaWYgKGluY29taW5nICE9PSB0aGlzLmxhc3RFbWl0dGVkKSB7XG4gICAgICAgIHRoaXMucmVuZGVyKGluY29taW5nKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy5yZW5kZXIodGhpcy52YWx1ZSB8fCAnJyk7XG4gIH1cblxuICBvbklucHV0KCk6IHZvaWQge1xuICAgIGNvbnN0IHN0ciA9IHRoaXMuc2VyaWFsaXplKCk7XG4gICAgdGhpcy5sYXN0RW1pdHRlZCA9IHN0cjtcbiAgICB0aGlzLnZhbHVlQ2hhbmdlLmVtaXQoc3RyKTtcbiAgICB0aGlzLmF1dG9DaGlwaWZ5KCk7XG4gICAgdGhpcy5yZWZyZXNoU3VnZ2VzdGlvbigpO1xuICB9XG5cbiAgb25LZXlEb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ0VudGVyJykge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ0VzY2FwZScpIHtcbiAgICAgIGlmICh0aGlzLnNob3dTdWdnZXN0aW9uKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMuaGlkZVN1Z2dlc3Rpb24oKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ0JhY2tzcGFjZScpIHtcbiAgICAgIGNvbnN0IG5vZGUgPSB0aGlzLmdldE5vZGVCZWZvcmVDYXJldCgpO1xuICAgICAgaWYgKG5vZGUgJiYgKG5vZGUgYXMgSFRNTEVsZW1lbnQpLmNsYXNzTGlzdD8uY29udGFpbnMoJ2NxYS12YXItY2hpcCcpKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIChub2RlIGFzIEhUTUxFbGVtZW50KS5yZW1vdmUoKTtcbiAgICAgICAgdGhpcy5vbklucHV0KCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgb25FZGl0b3JCbHVyKCk6IHZvaWQge1xuICAgIC8vIFNtYWxsIHRpbWVvdXQgc28gY2xpY2tzIG9uIHN1Z2dlc3Rpb24gYnV0dG9ucyByZWdpc3RlciBiZWZvcmUgaGlkaW5nLlxuICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5oaWRlU3VnZ2VzdGlvbigpLCAxNTApO1xuICB9XG5cbiAgYWRkQXNUZXh0KCk6IHZvaWQge1xuICAgIHRoaXMuaGlkZVN1Z2dlc3Rpb24oKTtcbiAgICB0aGlzLmVkaXRvclJlZi5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gIH1cblxuICBhZGRBc1ZhcmlhYmxlKCk6IHZvaWQge1xuICAgIGNvbnN0IG5hbWUgPSAodGhpcy5wZW5kaW5nV29yZCB8fCAnJykudHJpbSgpO1xuICAgIGlmICghbmFtZSB8fCAhVkFSX05BTUVfUkVHRVgudGVzdChuYW1lKSkge1xuICAgICAgdGhpcy5oaWRlU3VnZ2VzdGlvbigpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmluc2VydENoaXBSZXBsYWNpbmdDdXJyZW50V29yZChuYW1lKTtcbiAgICB0aGlzLmhpZGVTdWdnZXN0aW9uKCk7XG4gICAgY29uc3Qgc3RyID0gdGhpcy5zZXJpYWxpemUoKTtcbiAgICB0aGlzLmxhc3RFbWl0dGVkID0gc3RyO1xuICAgIHRoaXMudmFsdWVDaGFuZ2UuZW1pdChzdHIpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWZyZXNoU3VnZ2VzdGlvbigpOiB2b2lkIHtcbiAgICBjb25zdCB3b3JkID0gdGhpcy5nZXRDdXJyZW50V29yZCgpO1xuICAgIGlmICh3b3JkICYmIFZBUl9OQU1FX1JFR0VYLnRlc3Qod29yZCkpIHtcbiAgICAgIHRoaXMucGVuZGluZ1dvcmQgPSB3b3JkO1xuICAgICAgdGhpcy5zaG93U3VnZ2VzdGlvbiA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucGVuZGluZ1dvcmQgPSAnJztcbiAgICAgIHRoaXMuc2hvd1N1Z2dlc3Rpb24gPSBmYWxzZTtcbiAgICB9XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBwcml2YXRlIGhpZGVTdWdnZXN0aW9uKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5zaG93U3VnZ2VzdGlvbiAmJiAhdGhpcy5wZW5kaW5nV29yZCkgcmV0dXJuO1xuICAgIHRoaXMuc2hvd1N1Z2dlc3Rpb24gPSBmYWxzZTtcbiAgICB0aGlzLnBlbmRpbmdXb3JkID0gJyc7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBwcml2YXRlIGF1dG9DaGlwaWZ5KCk6IHZvaWQge1xuICAgIGNvbnN0IGVkaXRvciA9IHRoaXMuZWRpdG9yUmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgY29uc3QgdGV4dE5vZGVzOiBUZXh0W10gPSBbXTtcbiAgICBlZGl0b3IuY2hpbGROb2Rlcy5mb3JFYWNoKChuKSA9PiB7XG4gICAgICBpZiAobi5ub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHRleHROb2Rlcy5wdXNoKG4gYXMgVGV4dCk7XG4gICAgfSk7XG4gICAgZm9yIChjb25zdCB0biBvZiB0ZXh0Tm9kZXMpIHtcbiAgICAgIGNvbnN0IHRleHQgPSB0bi5ub2RlVmFsdWUgfHwgJyc7XG4gICAgICBWQVJfVE9LRU5fUkVHRVgubGFzdEluZGV4ID0gMDtcbiAgICAgIGlmICghVkFSX1RPS0VOX1JFR0VYLnRlc3QodGV4dCkpIGNvbnRpbnVlO1xuICAgICAgVkFSX1RPS0VOX1JFR0VYLmxhc3RJbmRleCA9IDA7XG4gICAgICBjb25zdCBwYXJlbnQgPSB0bi5wYXJlbnROb2RlO1xuICAgICAgaWYgKCFwYXJlbnQpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgZnJhZyA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcbiAgICAgIGxldCBsYXN0SW5kZXggPSAwO1xuICAgICAgbGV0IG06IFJlZ0V4cEV4ZWNBcnJheSB8IG51bGw7XG4gICAgICB3aGlsZSAoKG0gPSBWQVJfVE9LRU5fUkVHRVguZXhlYyh0ZXh0KSkgIT09IG51bGwpIHtcbiAgICAgICAgaWYgKG0uaW5kZXggPiBsYXN0SW5kZXgpIHtcbiAgICAgICAgICBmcmFnLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHRleHQuc2xpY2UobGFzdEluZGV4LCBtLmluZGV4KSkpO1xuICAgICAgICB9XG4gICAgICAgIGZyYWcuYXBwZW5kQ2hpbGQodGhpcy5idWlsZENoaXAobVsxXSkpO1xuICAgICAgICBsYXN0SW5kZXggPSBtLmluZGV4ICsgbVswXS5sZW5ndGg7XG4gICAgICB9XG4gICAgICBpZiAobGFzdEluZGV4IDwgdGV4dC5sZW5ndGgpIHtcbiAgICAgICAgZnJhZy5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSh0ZXh0LnNsaWNlKGxhc3RJbmRleCkpKTtcbiAgICAgIH1cbiAgICAgIHBhcmVudC5yZXBsYWNlQ2hpbGQoZnJhZywgdG4pO1xuICAgICAgdGhpcy5wbGFjZUNhcmV0QXRFbmQoKTtcbiAgICAgIGNvbnN0IHN0ciA9IHRoaXMuc2VyaWFsaXplKCk7XG4gICAgICB0aGlzLmxhc3RFbWl0dGVkID0gc3RyO1xuICAgICAgdGhpcy52YWx1ZUNoYW5nZS5lbWl0KHN0cik7XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXIodmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGVkaXRvciA9IHRoaXMuZWRpdG9yUmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgZWRpdG9yLmlubmVySFRNTCA9ICcnO1xuICAgIGlmICghdmFsdWUpIHJldHVybjtcbiAgICBWQVJfVE9LRU5fUkVHRVgubGFzdEluZGV4ID0gMDtcbiAgICBsZXQgbGFzdEluZGV4ID0gMDtcbiAgICBsZXQgbTogUmVnRXhwRXhlY0FycmF5IHwgbnVsbDtcbiAgICB3aGlsZSAoKG0gPSBWQVJfVE9LRU5fUkVHRVguZXhlYyh2YWx1ZSkpICE9PSBudWxsKSB7XG4gICAgICBpZiAobS5pbmRleCA+IGxhc3RJbmRleCkge1xuICAgICAgICBlZGl0b3IuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUodmFsdWUuc2xpY2UobGFzdEluZGV4LCBtLmluZGV4KSkpO1xuICAgICAgfVxuICAgICAgZWRpdG9yLmFwcGVuZENoaWxkKHRoaXMuYnVpbGRDaGlwKG1bMV0pKTtcbiAgICAgIGxhc3RJbmRleCA9IG0uaW5kZXggKyBtWzBdLmxlbmd0aDtcbiAgICB9XG4gICAgaWYgKGxhc3RJbmRleCA8IHZhbHVlLmxlbmd0aCkge1xuICAgICAgZWRpdG9yLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHZhbHVlLnNsaWNlKGxhc3RJbmRleCkpKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNlcmlhbGl6ZSgpOiBzdHJpbmcge1xuICAgIGNvbnN0IGVkaXRvciA9IHRoaXMuZWRpdG9yUmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgbGV0IG91dCA9ICcnO1xuICAgIGVkaXRvci5jaGlsZE5vZGVzLmZvckVhY2goKG4pID0+IHtcbiAgICAgIGlmIChuLm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSkge1xuICAgICAgICBvdXQgKz0gKG4ubm9kZVZhbHVlIHx8ICcnKS5yZXBsYWNlKC9cXHUwMGEwL2csICcgJyk7XG4gICAgICB9IGVsc2UgaWYgKG4ubm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFKSB7XG4gICAgICAgIGNvbnN0IGVsID0gbiBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgaWYgKGVsLmNsYXNzTGlzdC5jb250YWlucygnY3FhLXZhci1jaGlwJykpIHtcbiAgICAgICAgICBjb25zdCBuYW1lID0gZWwuZ2V0QXR0cmlidXRlKCdkYXRhLXZhcicpIHx8ICcnO1xuICAgICAgICAgIGlmIChuYW1lKSBvdXQgKz0gJyR7JyArIG5hbWUgKyAnfSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb3V0ICs9IGVsLnRleHRDb250ZW50IHx8ICcnO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG91dDtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRDaGlwKG5hbWU6IHN0cmluZyk6IEhUTUxFbGVtZW50IHtcbiAgICBjb25zdCBjaGlwID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuICAgIGNoaXAuY2xhc3NOYW1lID0gJ2NxYS12YXItY2hpcCc7XG4gICAgY2hpcC5zZXRBdHRyaWJ1dGUoJ2NvbnRlbnRlZGl0YWJsZScsICdmYWxzZScpO1xuICAgIGNoaXAuc2V0QXR0cmlidXRlKCdkYXRhLXZhcicsIG5hbWUpO1xuICAgIGNvbnN0IGxhYmVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuICAgIGxhYmVsLmNsYXNzTmFtZSA9ICdjcWEtdmFyLWNoaXBfX2xhYmVsJztcbiAgICBsYWJlbC50ZXh0Q29udGVudCA9ICckeycgKyBuYW1lICsgJ30nO1xuICAgIGNvbnN0IHJlbW92ZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgICByZW1vdmUuY2xhc3NOYW1lID0gJ2NxYS12YXItY2hpcF9fcmVtb3ZlJztcbiAgICByZW1vdmUudGV4dENvbnRlbnQgPSAnw5cnO1xuICAgIHJlbW92ZS5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCAoZSkgPT4gZS5wcmV2ZW50RGVmYXVsdCgpKTtcbiAgICByZW1vdmUuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoZSkgPT4ge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIGNoaXAucmVtb3ZlKCk7XG4gICAgICB0aGlzLm9uSW5wdXQoKTtcbiAgICB9KTtcbiAgICBjaGlwLmFwcGVuZENoaWxkKGxhYmVsKTtcbiAgICBjaGlwLmFwcGVuZENoaWxkKHJlbW92ZSk7XG4gICAgcmV0dXJuIGNoaXA7XG4gIH1cblxuICBwcml2YXRlIGdldFNlbGVjdGlvblJhbmdlKCk6IFJhbmdlIHwgbnVsbCB7XG4gICAgY29uc3Qgc2VsID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgIGlmICghc2VsIHx8IHNlbC5yYW5nZUNvdW50ID09PSAwKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCByYW5nZSA9IHNlbC5nZXRSYW5nZUF0KDApO1xuICAgIGlmICghdGhpcy5lZGl0b3JSZWYubmF0aXZlRWxlbWVudC5jb250YWlucyhyYW5nZS5zdGFydENvbnRhaW5lcikpIHJldHVybiBudWxsO1xuICAgIHJldHVybiByYW5nZTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Tm9kZUJlZm9yZUNhcmV0KCk6IE5vZGUgfCBudWxsIHtcbiAgICBjb25zdCByYW5nZSA9IHRoaXMuZ2V0U2VsZWN0aW9uUmFuZ2UoKTtcbiAgICBpZiAoIXJhbmdlIHx8ICFyYW5nZS5jb2xsYXBzZWQpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHsgc3RhcnRDb250YWluZXIsIHN0YXJ0T2Zmc2V0IH0gPSByYW5nZTtcbiAgICBpZiAoc3RhcnRDb250YWluZXIubm9kZVR5cGUgPT09IE5vZGUuVEVYVF9OT0RFKSB7XG4gICAgICBpZiAoc3RhcnRPZmZzZXQgPiAwKSByZXR1cm4gbnVsbDtcbiAgICAgIHJldHVybiBzdGFydENvbnRhaW5lci5wcmV2aW91c1NpYmxpbmc7XG4gICAgfVxuICAgIHJldHVybiBzdGFydENvbnRhaW5lci5jaGlsZE5vZGVzW3N0YXJ0T2Zmc2V0IC0gMV0gfHwgbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q3VycmVudFdvcmQoKTogc3RyaW5nIHtcbiAgICBjb25zdCByYW5nZSA9IHRoaXMuZ2V0U2VsZWN0aW9uUmFuZ2UoKTtcbiAgICBpZiAoIXJhbmdlKSByZXR1cm4gJyc7XG4gICAgY29uc3Qgbm9kZSA9IHJhbmdlLnN0YXJ0Q29udGFpbmVyO1xuICAgIGlmIChub2RlLm5vZGVUeXBlICE9PSBOb2RlLlRFWFRfTk9ERSkgcmV0dXJuICcnO1xuICAgIGNvbnN0IHRleHQgPSBub2RlLm5vZGVWYWx1ZSB8fCAnJztcbiAgICBjb25zdCBiZWZvcmUgPSB0ZXh0LnNsaWNlKDAsIHJhbmdlLnN0YXJ0T2Zmc2V0KTtcbiAgICBjb25zdCBtYXRjaCA9IGJlZm9yZS5tYXRjaCgvKFtBLVphLXpfXVtBLVphLXowLTlfXSopJC8pO1xuICAgIHJldHVybiBtYXRjaCA/IG1hdGNoWzFdIDogJyc7XG4gIH1cblxuICBwcml2YXRlIGluc2VydENoaXBSZXBsYWNpbmdDdXJyZW50V29yZChuYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCByYW5nZSA9IHRoaXMuZ2V0U2VsZWN0aW9uUmFuZ2UoKTtcbiAgICBjb25zdCBjaGlwID0gdGhpcy5idWlsZENoaXAobmFtZSk7XG4gICAgaWYgKCFyYW5nZSkge1xuICAgICAgdGhpcy5lZGl0b3JSZWYubmF0aXZlRWxlbWVudC5hcHBlbmRDaGlsZChjaGlwKTtcbiAgICAgIHRoaXMucGxhY2VDYXJldEFmdGVyKGNoaXApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBub2RlID0gcmFuZ2Uuc3RhcnRDb250YWluZXI7XG4gICAgaWYgKG5vZGUubm9kZVR5cGUgPT09IE5vZGUuVEVYVF9OT0RFKSB7XG4gICAgICBjb25zdCB0ZXh0ID0gbm9kZS5ub2RlVmFsdWUgfHwgJyc7XG4gICAgICBjb25zdCBiZWZvcmUgPSB0ZXh0LnNsaWNlKDAsIHJhbmdlLnN0YXJ0T2Zmc2V0KTtcbiAgICAgIGNvbnN0IGFmdGVyID0gdGV4dC5zbGljZShyYW5nZS5zdGFydE9mZnNldCk7XG4gICAgICBjb25zdCB3b3JkTWF0Y2ggPSBiZWZvcmUubWF0Y2goLyhbQS1aYS16X11bQS1aYS16MC05X10qKSQvKTtcbiAgICAgIGNvbnN0IGJlZm9yZUtlcHQgPSB3b3JkTWF0Y2ggPyBiZWZvcmUuc2xpY2UoMCwgYmVmb3JlLmxlbmd0aCAtIHdvcmRNYXRjaFsxXS5sZW5ndGgpIDogYmVmb3JlO1xuICAgICAgY29uc3QgcGFyZW50ID0gbm9kZS5wYXJlbnROb2RlITtcbiAgICAgIGNvbnN0IGZyYWcgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG4gICAgICBpZiAoYmVmb3JlS2VwdCkgZnJhZy5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShiZWZvcmVLZXB0KSk7XG4gICAgICBmcmFnLmFwcGVuZENoaWxkKGNoaXApO1xuICAgICAgaWYgKGFmdGVyKSBmcmFnLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGFmdGVyKSk7XG4gICAgICBwYXJlbnQucmVwbGFjZUNoaWxkKGZyYWcsIG5vZGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICByYW5nZS5pbnNlcnROb2RlKGNoaXApO1xuICAgIH1cbiAgICB0aGlzLnBsYWNlQ2FyZXRBZnRlcihjaGlwKTtcbiAgfVxuXG4gIHByaXZhdGUgcGxhY2VDYXJldEFmdGVyKG5vZGU6IE5vZGUpOiB2b2lkIHtcbiAgICBjb25zdCBzZWwgPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgaWYgKCFzZWwpIHJldHVybjtcbiAgICBjb25zdCByYW5nZSA9IGRvY3VtZW50LmNyZWF0ZVJhbmdlKCk7XG4gICAgcmFuZ2Uuc2V0U3RhcnRBZnRlcihub2RlKTtcbiAgICByYW5nZS5jb2xsYXBzZSh0cnVlKTtcbiAgICBzZWwucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgc2VsLmFkZFJhbmdlKHJhbmdlKTtcbiAgfVxuXG4gIHByaXZhdGUgcGxhY2VDYXJldEF0RW5kKCk6IHZvaWQge1xuICAgIGNvbnN0IGVkaXRvciA9IHRoaXMuZWRpdG9yUmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgY29uc3Qgc2VsID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgIGlmICghc2VsKSByZXR1cm47XG4gICAgY29uc3QgcmFuZ2UgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpO1xuICAgIHJhbmdlLnNlbGVjdE5vZGVDb250ZW50cyhlZGl0b3IpO1xuICAgIHJhbmdlLmNvbGxhcHNlKGZhbHNlKTtcbiAgICBzZWwucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgc2VsLmFkZFJhbmdlKHJhbmdlKTtcbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImNxYS1taXhlZC12YXItd3JhcHBlclwiPlxuICA8ZGl2XG4gICAgI2VkaXRvclxuICAgIGNsYXNzPVwiY3FhLW1peGVkLXZhci1lZGl0b3JcIlxuICAgIHJvbGU9XCJ0ZXh0Ym94XCJcbiAgICBzcGVsbGNoZWNrPVwiZmFsc2VcIlxuICAgIFthdHRyLmNvbnRlbnRlZGl0YWJsZV09XCIhZGlzYWJsZWRcIlxuICAgIFthdHRyLmRhdGEtcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICAgIChpbnB1dCk9XCJvbklucHV0KClcIlxuICAgIChrZXlkb3duKT1cIm9uS2V5RG93bigkZXZlbnQpXCJcbiAgICAoYmx1cik9XCJvbkVkaXRvckJsdXIoKVwiPlxuICA8L2Rpdj5cblxuICA8ZGl2XG4gICAgKm5nSWY9XCJzaG93U3VnZ2VzdGlvblwiXG4gICAgY2xhc3M9XCJjcWEtbWl4ZWQtdmFyLXN1Z2dlc3RcIlxuICAgIChtb3VzZWRvd24pPVwiJGV2ZW50LnByZXZlbnREZWZhdWx0KClcIj5cbiAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImNxYS1taXhlZC12YXItc3VnZ2VzdF9faXRlbVwiIChjbGljayk9XCJhZGRBc1RleHQoKVwiPlxuICAgICAgQWRkIGFzIFRleHQgPHNwYW4gY2xhc3M9XCJjcWEtbWl4ZWQtdmFyLXN1Z2dlc3RfX2hpbnRcIj5cInt7IHBlbmRpbmdXb3JkIH19XCI8L3NwYW4+XG4gICAgPC9idXR0b24+XG4gICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJjcWEtbWl4ZWQtdmFyLXN1Z2dlc3RfX2l0ZW0gY3FhLW1peGVkLXZhci1zdWdnZXN0X19pdGVtLS1wcmltYXJ5XCIgKGNsaWNrKT1cImFkZEFzVmFyaWFibGUoKVwiPlxuICAgICAgQWRkIGFzIGxvY2FsIHZhcmlhYmxlIDxzcGFuIGNsYXNzPVwiY3FhLW1peGVkLXZhci1zdWdnZXN0X19oaW50XCI+JHt7ICd7JyB9fXt7IHBlbmRpbmdXb3JkIH19e3sgJ30nIH19PC9zcGFuPlxuICAgIDwvYnV0dG9uPlxuICA8L2Rpdj5cbjwvZGl2PlxuIl19