@skyux/text-editor 11.30.1 → 12.0.0-alpha.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 (35) hide show
  1. package/documentation.json +295 -292
  2. package/fesm2022/skyux-text-editor.mjs +44 -44
  3. package/fesm2022/skyux-text-editor.mjs.map +1 -1
  4. package/package.json +18 -20
  5. package/esm2022/index.mjs +0 -10
  6. package/esm2022/lib/modules/rich-text-display/rich-text-display.component.mjs +0 -43
  7. package/esm2022/lib/modules/rich-text-display/rich-text-display.module.mjs +0 -16
  8. package/esm2022/lib/modules/shared/sky-text-editor-resources.module.mjs +0 -97
  9. package/esm2022/lib/modules/text-editor/defaults/font-list-defaults.mjs +0 -42
  10. package/esm2022/lib/modules/text-editor/defaults/font-size-list-defaults.mjs +0 -7
  11. package/esm2022/lib/modules/text-editor/defaults/link-window-options-defaults.mjs +0 -2
  12. package/esm2022/lib/modules/text-editor/defaults/menu-defaults.mjs +0 -5
  13. package/esm2022/lib/modules/text-editor/defaults/style-state-defaults.mjs +0 -15
  14. package/esm2022/lib/modules/text-editor/defaults/toolbar-action-defaults.mjs +0 -12
  15. package/esm2022/lib/modules/text-editor/menubar/text-editor-menubar.component.mjs +0 -195
  16. package/esm2022/lib/modules/text-editor/services/text-editor-adapter.service.mjs +0 -482
  17. package/esm2022/lib/modules/text-editor/services/text-editor-selection.service.mjs +0 -74
  18. package/esm2022/lib/modules/text-editor/services/text-editor.service.mjs +0 -65
  19. package/esm2022/lib/modules/text-editor/services/text-sanitization.service.mjs +0 -38
  20. package/esm2022/lib/modules/text-editor/text-editor.component.mjs +0 -514
  21. package/esm2022/lib/modules/text-editor/text-editor.module.mjs +0 -17
  22. package/esm2022/lib/modules/text-editor/toolbar/text-editor-toolbar.component.mjs +0 -223
  23. package/esm2022/lib/modules/text-editor/types/editor-command.mjs +0 -2
  24. package/esm2022/lib/modules/text-editor/types/editor-setting.mjs +0 -2
  25. package/esm2022/lib/modules/text-editor/types/font-state.mjs +0 -2
  26. package/esm2022/lib/modules/text-editor/types/link-window-options-type.mjs +0 -2
  27. package/esm2022/lib/modules/text-editor/types/menu-type.mjs +0 -2
  28. package/esm2022/lib/modules/text-editor/types/style-state.mjs +0 -2
  29. package/esm2022/lib/modules/text-editor/types/text-editor-merge-field.mjs +0 -2
  30. package/esm2022/lib/modules/text-editor/types/toolbar-action-type.mjs +0 -2
  31. package/esm2022/lib/modules/text-editor/url-modal/text-editor-url-modal-context.mjs +0 -6
  32. package/esm2022/lib/modules/text-editor/url-modal/text-editor-url-modal-result.mjs +0 -2
  33. package/esm2022/lib/modules/text-editor/url-modal/text-editor-url-modal.component.mjs +0 -147
  34. package/esm2022/lib/modules/text-editor/url-modal/text-editor-url-target.mjs +0 -9
  35. package/esm2022/skyux-text-editor.mjs +0 -5
@@ -1,482 +0,0 @@
1
- import { Injectable, inject } from '@angular/core';
2
- import { SkyLibResourcesService } from '@skyux/i18n';
3
- import { Subject, take } from 'rxjs';
4
- import { STYLE_STATE_DEFAULTS } from '../defaults/style-state-defaults';
5
- import { UrlTarget } from '../url-modal/text-editor-url-target';
6
- import * as i0 from "@angular/core";
7
- import * as i1 from "./text-editor-selection.service";
8
- import * as i2 from "./text-editor.service";
9
- import * as i3 from "@skyux/core";
10
- /**
11
- * @internal
12
- */
13
- export class SkyTextEditorAdapterService {
14
- #resourceSvc = inject(SkyLibResourcesService);
15
- #selectionService;
16
- #textEditorService;
17
- #windowRef;
18
- constructor(selectionService, textEditorService, windowService) {
19
- this.#selectionService = selectionService;
20
- this.#textEditorService = textEditorService;
21
- this.#windowRef = windowService;
22
- }
23
- /**
24
- * Creates a text editor inside the supplied iframe element.
25
- */
26
- initEditor(id, iframeElement, styleState, placeholder) {
27
- this.#textEditorService.editor = this.#createObservers(iframeElement);
28
- const documentEl = this.#getIframeDocumentEl();
29
- const styleEl = documentEl.createElement('style');
30
- styleEl.innerHTML = `.editor:empty:before {
31
- content: attr(data-placeholder);
32
- font-family: "Blackbaud Sans", Arial, sans-serif;
33
- color: #686c73;
34
- font-weight: 400;
35
- font-size: 15px;
36
- font-style: italic;
37
- }`;
38
- documentEl.head.appendChild(styleEl);
39
- const style = {
40
- ...STYLE_STATE_DEFAULTS,
41
- ...styleState,
42
- };
43
- const bodyStyle = `background-color: ${style.backColor};
44
- color: ${style.fontColor};
45
- font-family: ${style.font};
46
- font-size: ${style.fontSize}px`;
47
- documentEl.querySelector('html')?.setAttribute('lang', 'en');
48
- documentEl.body.setAttribute('contenteditable', 'true');
49
- documentEl.body.setAttribute('id', id);
50
- documentEl.body.setAttribute('role', 'main');
51
- documentEl.body.setAttribute('class', 'editor');
52
- documentEl.body.setAttribute('style', bodyStyle);
53
- documentEl.body.setAttribute('data-placeholder', placeholder || '');
54
- }
55
- disableEditor(focusableChildren, textEditorNativeElement) {
56
- this.#setEditorDisabled(focusableChildren, textEditorNativeElement, true);
57
- }
58
- enableEditor(focusableChildren, textEditorNativeElement) {
59
- this.#setEditorDisabled(focusableChildren, textEditorNativeElement, false);
60
- }
61
- /**
62
- * Executes a command on the text editor with the corresponding id.
63
- */
64
- async execCommand(editorCommand) {
65
- /* istanbul ignore else */
66
- if (this.#textEditorService.editor) {
67
- const documentEl = this.#getIframeDocumentEl();
68
- if (editorCommand.command === 'paste') {
69
- // Firefox does not support the clipboard API's `readText` as of 3/24. We are ok with just firing an alert when the paste button is used in Firefox.
70
- if (!navigator.clipboard.readText) {
71
- this.#resourceSvc
72
- .getString('skyux_text_editor_paste_incompatibility_error')
73
- .pipe(take(1))
74
- .subscribe((errorString) => alert(errorString));
75
- }
76
- else {
77
- await navigator.clipboard.readText().then((clipText) => {
78
- /* istanbul ignore else */
79
- if (this.editorSelected()) {
80
- documentEl.execCommand('insertHTML', false, clipText);
81
- this.focusEditor();
82
- this.#textEditorService.editor.commandChangeObservable.next();
83
- }
84
- });
85
- }
86
- }
87
- else {
88
- /* istanbul ignore else */
89
- if (this.editorSelected()) {
90
- documentEl.execCommand(editorCommand.command, false, editorCommand.value);
91
- this.focusEditor();
92
- this.#textEditorService.editor.commandChangeObservable.next();
93
- }
94
- }
95
- }
96
- }
97
- getCurrentSelection() {
98
- return this.#selectionService.getCurrentSelection(this.#getIframeDocumentEl());
99
- }
100
- /**
101
- * Returns a data URI using the provided text string.
102
- * Used to display a merge field inside a string of text.
103
- */
104
- getMergeFieldDataURI(text) {
105
- const documentEl = this.#windowRef.nativeWindow.document;
106
- let textToUse = text;
107
- if (text.length > 18) {
108
- textToUse = text.substr(0, 15) + '...';
109
- }
110
- const canvasElement = documentEl.createElement('canvas');
111
- canvasElement.setAttribute('height', '20');
112
- canvasElement.setAttribute('width', '100');
113
- canvasElement.style.backgroundColor = 'tan';
114
- canvasElement.style.border = '1px solid #000000';
115
- canvasElement.style.borderRadius = '5px';
116
- const context = canvasElement.getContext('2d');
117
- context.font = '12px Arial';
118
- context.textAlign = 'center';
119
- context.fillText(textToUse, 50, 15);
120
- context.globalCompositeOperation = 'destination-over';
121
- context.fillStyle = '#00FFFF';
122
- context.fillRect(0, 0, 100, 20);
123
- context.globalCompositeOperation = 'source-over';
124
- context.lineWidth = 2;
125
- context.strokeStyle = '#FF0000';
126
- context.strokeRect(0, 0, 100, 20);
127
- const result = canvasElement.toDataURL('image/png', 1.0);
128
- return result;
129
- }
130
- getStyleState() {
131
- const documentEl = this.#getIframeDocumentEl();
132
- /* istanbul ignore else */
133
- if (this.editorSelected()) {
134
- return {
135
- backColor: this.#getColor(documentEl, 'BackColor'),
136
- fontColor: this.#getColor(documentEl, 'ForeColor'),
137
- fontSize: parseInt(this.#getFontSize(), undefined),
138
- font: documentEl.queryCommandValue('fontname'),
139
- boldState: documentEl.queryCommandState('Bold'),
140
- italicState: documentEl.queryCommandState('Italic'),
141
- underlineState: documentEl.queryCommandState('Underline'),
142
- linkState: this.#hasLink(),
143
- };
144
- }
145
- /* istanbul ignore next */
146
- return {};
147
- }
148
- getEditorInnerHtml() {
149
- const documentEl = this.#getIframeDocumentEl();
150
- if (documentEl) {
151
- return this.#replaceHtmlCodes(documentEl.body.innerHTML);
152
- }
153
- return '';
154
- }
155
- setEditorInnerHtml(value) {
156
- const documentEl = this.#getIframeDocumentEl();
157
- const editorContent = documentEl.body;
158
- /* istanbul ignore else */
159
- if (editorContent.innerHTML !== value) {
160
- editorContent.innerHTML = value;
161
- }
162
- }
163
- focusEditor() {
164
- /* istanbul ignore else */
165
- if (this.#textEditorService.editor) {
166
- const windowEl = this.#getContentWindowEl();
167
- const iframeDocumentEl = this.#getIframeDocumentEl();
168
- const currentSelection = this.#selectionService.getCurrentSelectionRange(iframeDocumentEl, windowEl);
169
- const cursorIsNotActiveAndHasReset = currentSelection &&
170
- currentSelection.startOffset === 0 &&
171
- currentSelection.endOffset === 0;
172
- if (!this.editorSelected() || cursorIsNotActiveAndHasReset) {
173
- // focus the end of the editor
174
- const documentEl = this.#windowRef.nativeWindow.document;
175
- const editor = iframeDocumentEl.body;
176
- const range = documentEl.createRange();
177
- this.#textEditorService.editor.iframeElementRef.focus();
178
- editor.focus();
179
- if (windowEl.getSelection && documentEl.createRange) {
180
- range.selectNodeContents(editor);
181
- range.collapse(false);
182
- const sel = windowEl.getSelection();
183
- sel?.removeAllRanges();
184
- sel?.addRange(range);
185
- }
186
- }
187
- else {
188
- // Cursor may not be active, restore it
189
- this.#textEditorService.editor.iframeElementRef.focus();
190
- iframeDocumentEl.body.focus();
191
- }
192
- }
193
- }
194
- getLink() {
195
- let link;
196
- const anchorEl = this.getSelectedAnchorTag();
197
- if (anchorEl && anchorEl.href) {
198
- link = {
199
- target: anchorEl.getAttribute('target') === '_blank'
200
- ? UrlTarget.NewWindow
201
- : UrlTarget.None,
202
- url: anchorEl.href,
203
- };
204
- }
205
- return link;
206
- }
207
- getSelectedAnchorTag() {
208
- const selectedEl = this.#getCurrentSelectionParentElement();
209
- if (selectedEl) {
210
- return this.#getParent(selectedEl, 'a');
211
- }
212
- /* istanbul ignore next */
213
- return undefined;
214
- }
215
- saveSelection() {
216
- return this.#selectionService.getCurrentSelectionRange(this.#getIframeDocumentEl(), this.#getContentWindowEl());
217
- }
218
- selectElement(element) {
219
- this.#selectionService.selectElement(this.#getIframeDocumentEl(), this.#getContentWindowEl(), element);
220
- }
221
- setErrorAttributes(errorId, errors) {
222
- const documentEl = this.#getIframeDocumentEl();
223
- documentEl.body.setAttribute('aria-invalid', (!!errors).toString());
224
- if (errors && errorId) {
225
- documentEl.body.setAttribute('aria-errormessage', errorId);
226
- }
227
- else {
228
- documentEl.body.removeAttribute('aria-errormessage');
229
- }
230
- }
231
- setLabelAttribute(label) {
232
- if (label) {
233
- const documentEl = this.#getIframeDocumentEl();
234
- documentEl.body.setAttribute('aria-label', label);
235
- }
236
- }
237
- setPlaceholder(placeholder) {
238
- const documentEl = this.#getIframeDocumentEl();
239
- documentEl.body.setAttribute('data-placeholder', placeholder || '');
240
- }
241
- setRequiredAttribute(required) {
242
- const documentEl = this.#getIframeDocumentEl();
243
- documentEl.body.setAttribute('aria-required', required.toString());
244
- }
245
- async setFontSize(fontSize) {
246
- const doc = this.#getIframeDocumentEl();
247
- await this.execCommand({ command: 'fontSize', value: '1' });
248
- const fontElements = Array.from(doc.querySelectorAll('font[size="1"]'));
249
- for (const element of fontElements) {
250
- element.removeAttribute('size');
251
- element.style.fontSize = fontSize + 'px';
252
- }
253
- this.#cleanUpBlankStyleTags(doc);
254
- this.focusEditor();
255
- this.#textEditorService.editor.commandChangeObservable.next();
256
- }
257
- removeObservers(setting) {
258
- /* istanbul ignore next */
259
- const documentEl = setting.iframeElementRef.contentWindow
260
- ? setting.iframeElementRef.contentWindow.document
261
- : setting.iframeElementRef.contentDocument;
262
- setting.selectionChangeObservable.complete();
263
- setting.clickObservable.complete();
264
- setting.commandChangeObservable.complete();
265
- if (documentEl) {
266
- documentEl.removeEventListener('selectionchange', setting.selectionListener);
267
- documentEl.removeEventListener('input', setting.selectionListener);
268
- documentEl.removeEventListener('mousedown', setting.clickListener);
269
- documentEl.body.removeEventListener('paste', setting.pasteListener);
270
- }
271
- }
272
- #getContentWindowEl() {
273
- return this.#textEditorService.editor.iframeElementRef
274
- .contentWindow;
275
- }
276
- #getChildSelectedAnchorTags() {
277
- const selectedRange = this.getCurrentSelection()?.getRangeAt(0);
278
- if (selectedRange && selectedRange.toString().length <= 0) {
279
- return [];
280
- }
281
- const parentElement = this.#getCurrentSelectionParentElement();
282
- let childElements = [];
283
- /* istanbul ignore else */
284
- if (parentElement) {
285
- childElements = Array.from(parentElement.querySelectorAll('a'));
286
- }
287
- /* istanbul ignore next */
288
- return childElements.filter((element) => {
289
- // IE specific
290
- if (selectedRange) {
291
- if (!selectedRange.intersectsNode) {
292
- if (!element || !element.href) {
293
- return false;
294
- }
295
- const tempRange = document.createRange();
296
- tempRange.selectNodeContents(element);
297
- return ((selectedRange.compareBoundaryPoints(Range.START_TO_START, tempRange) !== -1 &&
298
- selectedRange.compareBoundaryPoints(Range.START_TO_END, tempRange) !== 1) ||
299
- (selectedRange.compareBoundaryPoints(Range.END_TO_START, tempRange) !== -1 &&
300
- selectedRange.compareBoundaryPoints(Range.END_TO_END, tempRange) !== 1));
301
- }
302
- }
303
- // Normal non-IE
304
- return (!!element && !!element.href && selectedRange?.intersectsNode(element));
305
- });
306
- }
307
- #getIframeDocumentEl() {
308
- const contentWindowEl = this.#getContentWindowEl();
309
- /* istanbul ignore else */
310
- if (contentWindowEl) {
311
- return contentWindowEl.document;
312
- }
313
- /* istanbul ignore next */
314
- return this.#textEditorService.editor.iframeElementRef
315
- .contentDocument;
316
- }
317
- #getFontSize() {
318
- let fontSize = STYLE_STATE_DEFAULTS.fontSize.toString();
319
- const selection = this.getCurrentSelection();
320
- /* istanbul ignore else */
321
- if (selection &&
322
- selection.anchorNode &&
323
- selection.anchorNode.parentElement) {
324
- let element = selection.anchorNode;
325
- if (element?.nodeType !== 1) {
326
- element = element?.parentElement;
327
- }
328
- const computedStyle = window.getComputedStyle(element);
329
- /* istanbul ignore else */
330
- if (computedStyle) {
331
- fontSize = computedStyle.getPropertyValue('font-size');
332
- }
333
- }
334
- return fontSize;
335
- }
336
- #createObservers(element) {
337
- /* istanbul ignore next */
338
- const documentEl = element.contentWindow
339
- ? element.contentWindow.document
340
- : element.contentDocument;
341
- // Firefox bug where we need to open/close to cancel load so it doesn't overwrite attrs
342
- documentEl.open();
343
- documentEl.close();
344
- const selectionObservable = new Subject();
345
- const selectionListener = () => selectionObservable.next();
346
- const clickObservable = new Subject();
347
- const clickListener = () => clickObservable.next();
348
- const pasteListener = this.#getPasteOverride();
349
- const blurObservable = new Subject();
350
- const blurListener = () => blurObservable.next();
351
- const focusObservable = new Subject();
352
- const focusListener = () => focusObservable.next();
353
- const inputObservable = new Subject();
354
- const inputListener = () => inputObservable.next();
355
- documentEl.addEventListener('selectionchange', selectionListener);
356
- documentEl.addEventListener('input', inputListener);
357
- documentEl.addEventListener('mousedown', clickListener);
358
- documentEl.body.addEventListener('paste', pasteListener);
359
- documentEl.body.addEventListener('blur', blurListener);
360
- documentEl.body.addEventListener('focusin', focusListener);
361
- return {
362
- blurObservable,
363
- clickObservable,
364
- focusObservable,
365
- commandChangeObservable: new Subject(),
366
- iframeElementRef: element,
367
- inputObservable,
368
- selectionChangeObservable: selectionObservable,
369
- blurListener,
370
- focusListener,
371
- clickListener,
372
- inputListener,
373
- pasteListener,
374
- selectionListener,
375
- };
376
- }
377
- #getPasteOverride() {
378
- /* istanbul ignore next */
379
- return (e) => {
380
- e.preventDefault();
381
- const text = e.clipboardData?.getData('text/plain');
382
- if (text !== undefined) {
383
- void this.execCommand({
384
- command: 'insertHTML',
385
- value: text.toString(),
386
- });
387
- }
388
- };
389
- }
390
- #getCurrentSelectionParentElement() {
391
- return this.#selectionService.getCurrentSelectionParentElement(this.#getIframeDocumentEl());
392
- }
393
- #getColor(documentEl, selector) {
394
- const commandValue = documentEl.queryCommandValue(selector);
395
- // Edge is weird and returns numbers
396
- /* istanbul ignore if */
397
- if (typeof commandValue === 'number') {
398
- /* istanbul ignore next */
399
- return ('rgb(' +
400
- (commandValue & 0xff) +
401
- ', ' +
402
- ((commandValue & 0xff00) >> 8) +
403
- ', ' +
404
- ((commandValue & 0xff0000) >> 16) +
405
- ')');
406
- }
407
- // Firefox uses 'Transparent' instead of a color value
408
- /* istanbul ignore next */
409
- if (commandValue.toString().toLowerCase() === 'transparent') {
410
- return STYLE_STATE_DEFAULTS.backColor;
411
- }
412
- return commandValue;
413
- }
414
- #hasLink() {
415
- const anchorEl = this.getSelectedAnchorTag();
416
- const childAnchorEls = this.#getChildSelectedAnchorTags();
417
- /* istanbul ignore next */
418
- return childAnchorEls.length > 0 || (!!anchorEl && !!anchorEl.href);
419
- }
420
- #getParent(element, tag) {
421
- let currentNode = element;
422
- while (currentNode && currentNode.tagName.toUpperCase() !== 'BODY') {
423
- if (currentNode.tagName.toUpperCase() === tag.toUpperCase()) {
424
- return currentNode;
425
- }
426
- currentNode = currentNode.parentElement;
427
- }
428
- return undefined;
429
- }
430
- editorSelected() {
431
- const documentEl = this.#getIframeDocumentEl();
432
- return this.#selectionService.isElementSelected(documentEl, documentEl.body);
433
- }
434
- #cleanUpBlankStyleTags(doc) {
435
- const orphanElements = Array.from(doc.querySelectorAll('font,span,*[style=""]'));
436
- for (const element of orphanElements) {
437
- if (!element.getAttribute('style')) {
438
- element.removeAttribute('style');
439
- }
440
- }
441
- const removableElements = orphanElements.filter((element) => {
442
- const tagName = element.tagName.toUpperCase();
443
- return ((tagName === 'FONT' || tagName === 'SPAN') &&
444
- (element.attributes.length === 0 || !element.hasChildNodes));
445
- });
446
- for (const element of removableElements) {
447
- const parent = element.parentNode;
448
- /* istanbul ignore else */
449
- if (parent) {
450
- while (element.firstChild) {
451
- parent.insertBefore(element.firstChild, element);
452
- }
453
- parent.removeChild(element);
454
- }
455
- }
456
- }
457
- // Certain values are encoded in html and need to be decoded
458
- #replaceHtmlCodes(str) {
459
- return str
460
- .replace(/&nbsp;/, String.fromCharCode(160))
461
- .replace(/&lt;/g, '<')
462
- .replace(/&gt;/g, '>')
463
- .replace(/&amp;/g, '&');
464
- }
465
- #setEditorDisabled(focusableChildren, textEditorNativeElement, disabled) {
466
- textEditorNativeElement.style.pointerEvents = disabled ? 'none' : 'auto';
467
- textEditorNativeElement.setAttribute('aria-disabled', disabled ? 'true' : 'false');
468
- /* istanbul ignore else */
469
- if (focusableChildren.length > 0) {
470
- focusableChildren.forEach((aFocusableChild) => {
471
- aFocusableChild.tabIndex = disabled ? -1 : 0;
472
- });
473
- }
474
- this.#getIframeDocumentEl().body.setAttribute('contenteditable', disabled ? 'false' : 'true');
475
- }
476
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SkyTextEditorAdapterService, deps: [{ token: i1.SkyTextEditorSelectionService }, { token: i2.SkyTextEditorService }, { token: i3.SkyAppWindowRef }], target: i0.ɵɵFactoryTarget.Injectable }); }
477
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SkyTextEditorAdapterService }); }
478
- }
479
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SkyTextEditorAdapterService, decorators: [{
480
- type: Injectable
481
- }], ctorParameters: () => [{ type: i1.SkyTextEditorSelectionService }, { type: i2.SkyTextEditorService }, { type: i3.SkyAppWindowRef }] });
482
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC1lZGl0b3ItYWRhcHRlci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbGlicy9jb21wb25lbnRzL3RleHQtZWRpdG9yL3NyYy9saWIvbW9kdWxlcy90ZXh0LWVkaXRvci9zZXJ2aWNlcy90ZXh0LWVkaXRvci1hZGFwdGVyLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFHbkQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXJELE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRXJDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBS3hFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQzs7Ozs7QUFLaEU7O0dBRUc7QUFFSCxNQUFNLE9BQU8sMkJBQTJCO0lBQzdCLFlBQVksR0FBRyxNQUFNLENBQUMsc0JBQXNCLENBQUMsQ0FBQztJQUN2RCxpQkFBaUIsQ0FBZ0M7SUFDakQsa0JBQWtCLENBQXVCO0lBQ3pDLFVBQVUsQ0FBa0I7SUFFNUIsWUFDRSxnQkFBK0MsRUFDL0MsaUJBQXVDLEVBQ3ZDLGFBQThCO1FBRTlCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxnQkFBZ0IsQ0FBQztRQUMxQyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsaUJBQWlCLENBQUM7UUFDNUMsSUFBSSxDQUFDLFVBQVUsR0FBRyxhQUFhLENBQUM7SUFDbEMsQ0FBQztJQUVEOztPQUVHO0lBQ0ksVUFBVSxDQUNmLEVBQVUsRUFDVixhQUFnQyxFQUNoQyxVQUFtQyxFQUNuQyxXQUFvQjtRQUVwQixJQUFJLENBQUMsa0JBQWtCLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxhQUFhLENB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bXBvcnQgeyBJbmplY3RhYmxlLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFZhbGlkYXRpb25FcnJvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBTa3lBcHBXaW5kb3dSZWYgfSBmcm9tICdAc2t5dXgvY29yZSc7XG5pbXBvcnQgeyBTa3lMaWJSZXNvdXJjZXNTZXJ2aWNlIH0gZnJvbSAnQHNreXV4L2kxOG4nO1xuXG5pbXBvcnQgeyBTdWJqZWN0LCB0YWtlIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFNUWUxFX1NUQVRFX0RFRkFVTFRTIH0gZnJvbSAnLi4vZGVmYXVsdHMvc3R5bGUtc3RhdGUtZGVmYXVsdHMnO1xuaW1wb3J0IHsgRWRpdG9yQ29tbWFuZCB9IGZyb20gJy4uL3R5cGVzL2VkaXRvci1jb21tYW5kJztcbmltcG9ydCB7IEVkaXRvclNldHRpbmcgfSBmcm9tICcuLi90eXBlcy9lZGl0b3Itc2V0dGluZyc7XG5pbXBvcnQgeyBTa3lUZXh0RWRpdG9yU3R5bGVTdGF0ZSB9IGZyb20gJy4uL3R5cGVzL3N0eWxlLXN0YXRlJztcbmltcG9ydCB7IFVybE1vZGFsUmVzdWx0IH0gZnJvbSAnLi4vdXJsLW1vZGFsL3RleHQtZWRpdG9yLXVybC1tb2RhbC1yZXN1bHQnO1xuaW1wb3J0IHsgVXJsVGFyZ2V0IH0gZnJvbSAnLi4vdXJsLW1vZGFsL3RleHQtZWRpdG9yLXVybC10YXJnZXQnO1xuXG5pbXBvcnQgeyBTa3lUZXh0RWRpdG9yU2VsZWN0aW9uU2VydmljZSB9IGZyb20gJy4vdGV4dC1lZGl0b3Itc2VsZWN0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgU2t5VGV4dEVkaXRvclNlcnZpY2UgfSBmcm9tICcuL3RleHQtZWRpdG9yLnNlcnZpY2UnO1xuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgU2t5VGV4dEVkaXRvckFkYXB0ZXJTZXJ2aWNlIHtcbiAgcmVhZG9ubHkgI3Jlc291cmNlU3ZjID0gaW5qZWN0KFNreUxpYlJlc291cmNlc1NlcnZpY2UpO1xuICAjc2VsZWN0aW9uU2VydmljZTogU2t5VGV4dEVkaXRvclNlbGVjdGlvblNlcnZpY2U7XG4gICN0ZXh0RWRpdG9yU2VydmljZTogU2t5VGV4dEVkaXRvclNlcnZpY2U7XG4gICN3aW5kb3dSZWY6IFNreUFwcFdpbmRvd1JlZjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBzZWxlY3Rpb25TZXJ2aWNlOiBTa3lUZXh0RWRpdG9yU2VsZWN0aW9uU2VydmljZSxcbiAgICB0ZXh0RWRpdG9yU2VydmljZTogU2t5VGV4dEVkaXRvclNlcnZpY2UsXG4gICAgd2luZG93U2VydmljZTogU2t5QXBwV2luZG93UmVmLFxuICApIHtcbiAgICB0aGlzLiNzZWxlY3Rpb25TZXJ2aWNlID0gc2VsZWN0aW9uU2VydmljZTtcbiAgICB0aGlzLiN0ZXh0RWRpdG9yU2VydmljZSA9IHRleHRFZGl0b3JTZXJ2aWNlO1xuICAgIHRoaXMuI3dpbmRvd1JlZiA9IHdpbmRvd1NlcnZpY2U7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHRleHQgZWRpdG9yIGluc2lkZSB0aGUgc3VwcGxpZWQgaWZyYW1lIGVsZW1lbnQuXG4gICAqL1xuICBwdWJsaWMgaW5pdEVkaXRvcihcbiAgICBpZDogc3RyaW5nLFxuICAgIGlmcmFtZUVsZW1lbnQ6IEhUTUxJRnJhbWVFbGVtZW50LFxuICAgIHN0eWxlU3RhdGU6IFNreVRleHRFZGl0b3JTdHlsZVN0YXRlLFxuICAgIHBsYWNlaG9sZGVyPzogc3RyaW5nLFxuICApOiB2b2lkIHtcbiAgICB0aGlzLiN0ZXh0RWRpdG9yU2VydmljZS5lZGl0b3IgPSB0aGlzLiNjcmVhdGVPYnNlcnZlcnMoaWZyYW1lRWxlbWVudCk7XG5cbiAgICBjb25zdCBkb2N1bWVudEVsID0gdGhpcy4jZ2V0SWZyYW1lRG9jdW1lbnRFbCgpO1xuXG4gICAgY29uc3Qgc3R5bGVFbCA9IGRvY3VtZW50RWwuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcbiAgICBzdHlsZUVsLmlubmVySFRNTCA9IGAuZWRpdG9yOmVtcHR5OmJlZm9yZSB7XG4gICAgICBjb250ZW50OiBhdHRyKGRhdGEtcGxhY2Vob2xkZXIpO1xuICAgICAgZm9udC1mYW1pbHk6IFwiQmxhY2tiYXVkIFNhbnNcIiwgQXJpYWwsIHNhbnMtc2VyaWY7XG4gICAgICBjb2xvcjogIzY4NmM3MztcbiAgICAgIGZvbnQtd2VpZ2h0OiA0MDA7XG4gICAgICBmb250LXNpemU6IDE1cHg7XG4gICAgICBmb250LXN0eWxlOiBpdGFsaWM7XG4gICAgfWA7XG4gICAgZG9jdW1lbnRFbC5oZWFkLmFwcGVuZENoaWxkKHN0eWxlRWwpO1xuXG4gICAgY29uc3Qgc3R5bGU6IFNreVRleHRFZGl0b3JTdHlsZVN0YXRlID0ge1xuICAgICAgLi4uU1RZTEVfU1RBVEVfREVGQVVMVFMsXG4gICAgICAuLi5zdHlsZVN0YXRlLFxuICAgIH07XG4gICAgY29uc3QgYm9keVN0eWxlID0gYGJhY2tncm91bmQtY29sb3I6ICR7c3R5bGUuYmFja0NvbG9yfTtcbiAgICAgIGNvbG9yOiAke3N0eWxlLmZvbnRDb2xvcn07XG4gICAgICBmb250LWZhbWlseTogJHtzdHlsZS5mb250fTtcbiAgICAgIGZvbnQtc2l6ZTogJHtzdHlsZS5mb250U2l6ZX1weGA7XG4gICAgZG9jdW1lbnRFbC5xdWVyeVNlbGVjdG9yKCdodG1sJyk/LnNldEF0dHJpYnV0ZSgnbGFuZycsICdlbicpO1xuICAgIGRvY3VtZW50RWwuYm9keS5zZXRBdHRyaWJ1dGUoJ2NvbnRlbnRlZGl0YWJsZScsICd0cnVlJyk7XG4gICAgZG9jdW1lbnRFbC5ib2R5LnNldEF0dHJpYnV0ZSgnaWQnLCBpZCk7XG4gICAgZG9jdW1lbnRFbC5ib2R5LnNldEF0dHJpYnV0ZSgncm9sZScsICdtYWluJyk7XG4gICAgZG9jdW1lbnRFbC5ib2R5LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnZWRpdG9yJyk7XG4gICAgZG9jdW1lbnRFbC5ib2R5LnNldEF0dHJpYnV0ZSgnc3R5bGUnLCBib2R5U3R5bGUpO1xuICAgIGRvY3VtZW50RWwuYm9keS5zZXRBdHRyaWJ1dGUoJ2RhdGEtcGxhY2Vob2xkZXInLCBwbGFjZWhvbGRlciB8fCAnJyk7XG4gIH1cblxuICBwdWJsaWMgZGlzYWJsZUVkaXRvcihcbiAgICBmb2N1c2FibGVDaGlsZHJlbjogSFRNTEVsZW1lbnRbXSxcbiAgICB0ZXh0RWRpdG9yTmF0aXZlRWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICk6IHZvaWQge1xuICAgIHRoaXMuI3NldEVkaXRvckRpc2FibGVkKGZvY3VzYWJsZUNoaWxkcmVuLCB0ZXh0RWRpdG9yTmF0aXZlRWxlbWVudCwgdHJ1ZSk7XG4gIH1cblxuICBwdWJsaWMgZW5hYmxlRWRpdG9yKFxuICAgIGZvY3VzYWJsZUNoaWxkcmVuOiBIVE1MRWxlbWVudFtdLFxuICAgIHRleHRFZGl0b3JOYXRpdmVFbGVtZW50OiBIVE1MRWxlbWVudCxcbiAgKTogdm9pZCB7XG4gICAgdGhpcy4jc2V0RWRpdG9yRGlzYWJsZWQoZm9jdXNhYmxlQ2hpbGRyZW4sIHRleHRFZGl0b3JOYXRpdmVFbGVtZW50LCBmYWxzZSk7XG4gIH1cblxuICAvKipcbiAgICogRXhlY3V0ZXMgYSBjb21tYW5kIG9uIHRoZSB0ZXh0IGVkaXRvciB3aXRoIHRoZSBjb3JyZXNwb25kaW5nIGlkLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGV4ZWNDb21tYW5kKGVkaXRvckNvbW1hbmQ6IEVkaXRvckNvbW1hbmQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgIGlmICh0aGlzLiN0ZXh0RWRpdG9yU2VydmljZS5lZGl0b3IpIHtcbiAgICAgIGNvbnN0IGRvY3VtZW50RWwgPSB0aGlzLiNnZXRJZnJhbWVEb2N1bWVudEVsKCk7XG5cbiAgICAgIGlmIChlZGl0b3JDb21tYW5kLmNvbW1hbmQgPT09ICdwYXN0ZScpIHtcbiAgICAgICAgLy8gRmlyZWZveCBkb2VzIG5vdCBzdXBwb3J0IHRoZSBjbGlwYm9hcmQgQVBJJ3MgYHJlYWRUZXh0YCBhcyBvZiAzLzI0LiBXZSBhcmUgb2sgd2l0aCBqdXN0IGZpcmluZyBhbiBhbGVydCB3aGVuIHRoZSBwYXN0ZSBidXR0b24gaXMgdXNlZCBpbiBGaXJlZm94LlxuICAgICAgICBpZiAoIW5hdmlnYXRvci5jbGlwYm9hcmQucmVhZFRleHQpIHtcbiAgICAgICAgICB0aGlzLiNyZXNvdXJjZVN2Y1xuICAgICAgICAgICAgLmdldFN0cmluZygnc2t5dXhfdGV4dF9lZGl0b3JfcGFzdGVfaW5jb21wYXRpYmlsaXR5X2Vycm9yJylcbiAgICAgICAgICAgIC5waXBlKHRha2UoMSkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKChlcnJvclN0cmluZykgPT4gYWxlcnQoZXJyb3JTdHJpbmcpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhd2FpdCBuYXZpZ2F0b3IuY2xpcGJvYXJkLnJlYWRUZXh0KCkudGhlbigoY2xpcFRleHQpID0+IHtcbiAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgICAgICAgICBpZiAodGhpcy5lZGl0b3JTZWxlY3RlZCgpKSB7XG4gICAgICAgICAgICAgIGRvY3VtZW50RWwuZXhlY0NvbW1hbmQoJ2luc2VydEhUTUwnLCBmYWxzZSwgY2xpcFRleHQpO1xuXG4gICAgICAgICAgICAgIHRoaXMuZm9jdXNFZGl0b3IoKTtcbiAgICAgICAgICAgICAgdGhpcy4jdGV4dEVkaXRvclNlcnZpY2UuZWRpdG9yLmNvbW1hbmRDaGFuZ2VPYnNlcnZhYmxlLm5leHQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICAgICAgaWYgKHRoaXMuZWRpdG9yU2VsZWN0ZWQoKSkge1xuICAgICAgICAgIGRvY3VtZW50RWwuZXhlY0NvbW1hbmQoXG4gICAgICAgICAgICBlZGl0b3JDb21tYW5kLmNvbW1hbmQsXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgIGVkaXRvckNvbW1hbmQudmFsdWUsXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHRoaXMuZm9jdXNFZGl0b3IoKTtcbiAgICAgICAgICB0aGlzLiN0ZXh0RWRpdG9yU2VydmljZS5lZGl0b3IuY29tbWFuZENoYW5nZU9ic2VydmFibGUubmV4dCgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGdldEN1cnJlbnRTZWxlY3Rpb24oKTogU2VsZWN0aW9uIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuI3NlbGVjdGlvblNlcnZpY2UuZ2V0Q3VycmVudFNlbGVjdGlvbihcbiAgICAgIHRoaXMuI2dldElmcmFtZURvY3VtZW50RWwoKSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBkYXRhIFVSSSB1c2luZyB0aGUgcHJvdmlkZWQgdGV4dCBzdHJpbmcuXG4gICAqIFVzZWQgdG8gZGlzcGxheSBhIG1lcmdlIGZpZWxkIGluc2lkZSBhIHN0cmluZyBvZiB0ZXh0LlxuICAgKi9cbiAgcHVibGljIGdldE1lcmdlRmllbGREYXRhVVJJKHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgZG9jdW1lbnRFbCA9IHRoaXMuI3dpbmRvd1JlZi5uYXRpdmVXaW5kb3cuZG9jdW1lbnQ7XG4gICAgbGV0IHRleHRUb1VzZSA9IHRleHQ7XG4gICAgaWYgKHRleHQubGVuZ3RoID4gMTgpIHtcbiAgICAgIHRleHRUb1VzZSA9IHRleHQuc3Vic3RyKDAsIDE1KSArICcuLi4nO1xuICAgIH1cblxuICAgIGNvbnN0IGNhbnZhc0VsZW1lbnQgPSBkb2N1bWVudEVsLmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgIGNhbnZhc0VsZW1lbnQuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCAnMjAnKTtcbiAgICBjYW52YXNFbGVtZW50LnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnMTAwJyk7XG4gICAgY2FudmFzRWxlbWVudC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAndGFuJztcbiAgICBjYW52YXNFbGVtZW50LnN0eWxlLmJvcmRlciA9ICcxcHggc29saWQgIzAwMDAwMCc7XG4gICAgY2FudmFzRWxlbWVudC5zdHlsZS5ib3JkZXJSYWRpdXMgPSAnNXB4JztcblxuICAgIGNvbnN0IGNvbnRleHQgPSBjYW52YXNFbGVtZW50LmdldENvbnRleHQoJzJkJyk7XG4gICAgY29udGV4dC5mb250ID0gJzEycHggQXJpYWwnO1xuICAgIGNvbnRleHQudGV4dEFsaWduID0gJ2NlbnRlcic7XG4gICAgY29udGV4dC5maWxsVGV4dCh0ZXh0VG9Vc2UsIDUwLCAxNSk7XG5cbiAgICBjb250ZXh0Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbiA9ICdkZXN0aW5hdGlvbi1vdmVyJztcbiAgICBjb250ZXh0LmZpbGxTdHlsZSA9ICcjMDBGRkZGJztcbiAgICBjb250ZXh0LmZpbGxSZWN0KDAsIDAsIDEwMCwgMjApO1xuXG4gICAgY29udGV4dC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb24gPSAnc291cmNlLW92ZXInO1xuICAgIGNvbnRleHQubGluZVdpZHRoID0gMjtcbiAgICBjb250ZXh0LnN0cm9rZVN0eWxlID0gJyNGRjAwMDAnO1xuICAgIGNvbnRleHQuc3Ryb2tlUmVjdCgwLCAwLCAxMDAsIDIwKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGNhbnZhc0VsZW1lbnQudG9EYXRhVVJMKCdpbWFnZS9wbmcnLCAxLjApO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwdWJsaWMgZ2V0U3R5bGVTdGF0ZSgpOiBQYXJ0aWFsPFNreVRleHRFZGl0b3JTdHlsZVN0YXRlPiB7XG4gICAgY29uc3QgZG9jdW1lbnRFbCA9IHRoaXMuI2dldElmcmFtZURvY3VtZW50RWwoKTtcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgaWYgKHRoaXMuZWRpdG9yU2VsZWN0ZWQoKSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYmFja0NvbG9yOiB0aGlzLiNnZXRDb2xvcihkb2N1bWVudEVsLCAnQmFja0NvbG9yJyksXG4gICAgICAgIGZvbnRDb2xvcjogdGhpcy4jZ2V0Q29sb3IoZG9jdW1lbnRFbCwgJ0ZvcmVDb2xvcicpLFxuICAgICAgICBmb250U2l6ZTogcGFyc2VJbnQodGhpcy4jZ2V0Rm9udFNpemUoKSwgdW5kZWZpbmVkKSxcbiAgICAgICAgZm9udDogZG9jdW1lbnRFbC5xdWVyeUNvbW1hbmRWYWx1ZSgnZm9udG5hbWUnKSxcbiAgICAgICAgYm9sZFN0YXRlOiBkb2N1bWVudEVsLnF1ZXJ5Q29tbWFuZFN0YXRlKCdCb2xkJyksXG4gICAgICAgIGl0YWxpY1N0YXRlOiBkb2N1bWVudEVsLnF1ZXJ5Q29tbWFuZFN0YXRlKCdJdGFsaWMnKSxcbiAgICAgICAgdW5kZXJsaW5lU3RhdGU6IGRvY3VtZW50RWwucXVlcnlDb21tYW5kU3RhdGUoJ1VuZGVybGluZScpLFxuICAgICAgICBsaW5rU3RhdGU6IHRoaXMuI2hhc0xpbmsoKSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICByZXR1cm4ge307XG4gIH1cblxuICBwdWJsaWMgZ2V0RWRpdG9ySW5uZXJIdG1sKCk6IHN0cmluZyB7XG4gICAgY29uc3QgZG9jdW1lbnRFbCA9IHRoaXMuI2dldElmcmFtZURvY3VtZW50RWwoKTtcbiAgICBpZiAoZG9jdW1lbnRFbCkge1xuICAgICAgcmV0dXJuIHRoaXMuI3JlcGxhY2VIdG1sQ29kZXMoZG9jdW1lbnRFbC5ib2R5LmlubmVySFRNTCk7XG4gICAgfVxuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIHB1YmxpYyBzZXRFZGl0b3JJbm5lckh0bWwodmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGRvY3VtZW50RWwgPSB0aGlzLiNnZXRJZnJhbWVEb2N1bWVudEVsKCk7XG4gICAgY29uc3QgZWRpdG9yQ29udGVudCA9IGRvY3VtZW50RWwuYm9keTtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgIGlmIChlZGl0b3JDb250ZW50LmlubmVySFRNTCAhPT0gdmFsdWUpIHtcbiAgICAgIGVkaXRvckNvbnRlbnQuaW5uZXJIVE1MID0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGZvY3VzRWRpdG9yKCk6IHZvaWQge1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgaWYgKHRoaXMuI3RleHRFZGl0b3JTZXJ2aWNlLmVkaXRvcikge1xuICAgICAgY29uc3Qgd2luZG93RWwgPSB0aGlzLiNnZXRDb250ZW50V2luZG93RWwoKTtcbiAgICAgIGNvbnN0IGlmcmFtZURvY3VtZW50RWwgPSB0aGlzLiNnZXRJZnJhbWVEb2N1bWVudEVsKCk7XG4gICAgICBjb25zdCBjdXJyZW50U2VsZWN0aW9uID0gdGhpcy4jc2VsZWN0aW9uU2VydmljZS5nZXRDdXJyZW50U2VsZWN0aW9uUmFuZ2UoXG4gICAgICAgIGlmcmFtZURvY3VtZW50RWwsXG4gICAgICAgIHdpbmRvd0VsLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IGN1cnNvcklzTm90QWN0aXZlQW5kSGFzUmVzZXQgPVxuICAgICAgICBjdXJyZW50U2VsZWN0aW9uICYmXG4gICAgICAgIGN1cnJlbnRTZWxlY3Rpb24uc3RhcnRPZmZzZXQgPT09IDAgJiZcbiAgICAgICAgY3VycmVudFNlbGVjdGlvbi5lbmRPZmZzZXQgPT09IDA7XG5cbiAgICAgIGlmICghdGhpcy5lZGl0b3JTZWxlY3RlZCgpIHx8IGN1cnNvcklzTm90QWN0aXZlQW5kSGFzUmVzZXQpIHtcbiAgICAgICAgLy8gZm9jdXMgdGhlIGVuZCBvZiB0aGUgZWRpdG9yXG4gICAgICAgIGNvbnN0IGRvY3VtZW50RWwgPSB0aGlzLiN3aW5kb3dSZWYubmF0aXZlV2luZG93LmRvY3VtZW50O1xuICAgICAgICBjb25zdCBlZGl0b3IgPSBpZnJhbWVEb2N1bWVudEVsLmJvZHkgYXMgSFRNTEJvZHlFbGVtZW50O1xuICAgICAgICBjb25zdCByYW5nZSA9IGRvY3VtZW50RWwuY3JlYXRlUmFuZ2UoKTtcblxuICAgICAgICB0aGlzLiN0ZXh0RWRpdG9yU2VydmljZS5lZGl0b3IuaWZyYW1lRWxlbWVudFJlZi5mb2N1cygpO1xuICAgICAgICBlZGl0b3IuZm9jdXMoKTtcblxuICAgICAgICBpZiAod2luZG93RWwuZ2V0U2VsZWN0aW9uICYmIGRvY3VtZW50RWwuY3JlYXRlUmFuZ2UpIHtcbiAgICAgICAgICByYW5nZS5zZWxlY3ROb2RlQ29udGVudHMoZWRpdG9yKTtcbiAgICAgICAgICByYW5nZS5jb2xsYXBzZShmYWxzZSk7XG4gICAgICAgICAgY29uc3Qgc2VsID0gd2luZG93RWwuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICAgICAgc2VsPy5yZW1vdmVBbGxSYW5nZXMoKTtcbiAgICAgICAgICBzZWw/LmFkZFJhbmdlKHJhbmdlKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQ3Vyc29yIG1heSBub3QgYmUgYWN0aXZlLCByZXN0b3JlIGl0XG4gICAgICAgIHRoaXMuI3RleHRFZGl0b3JTZXJ2aWNlLmVkaXRvci5pZnJhbWVFbGVtZW50UmVmLmZvY3VzKCk7XG4gICAgICAgIGlmcmFtZURvY3VtZW50RWwuYm9keS5mb2N1cygpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXRMaW5rKCk6IFVybE1vZGFsUmVzdWx0IHwgdW5kZWZpbmVkIHtcbiAgICBsZXQgbGluazogVXJsTW9kYWxSZXN1bHQgfCB1bmRlZmluZWQ7XG4gICAgY29uc3QgYW5jaG9yRWwgPSB0aGlzLmdldFNlbGVjdGVkQW5jaG9yVGFnKCk7XG4gICAgaWYgKGFuY2hvckVsICYmIGFuY2hvckVsLmhyZWYpIHtcbiAgICAgIGxpbmsgPSB7XG4gICAgICAgIHRhcmdldDpcbiAgICAgICAgICBhbmNob3JFbC5nZXRBdHRyaWJ1dGUoJ3RhcmdldCcpID09PSAnX2JsYW5rJ1xuICAgICAgICAgICAgPyBVcmxUYXJnZXQuTmV3V2luZG93XG4gICAgICAgICAgICA6IFVybFRhcmdldC5Ob25lLFxuICAgICAgICB1cmw6IGFuY2hvckVsLmhyZWYsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBsaW5rO1xuICB9XG5cbiAgcHVibGljIGdldFNlbGVjdGVkQW5jaG9yVGFnKCk6IEhUTUxBbmNob3JFbGVtZW50IHwgbnVsbCB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3Qgc2VsZWN0ZWRFbCA9IHRoaXMuI2dldEN1cnJlbnRTZWxlY3Rpb25QYXJlbnRFbGVtZW50KCk7XG5cbiAgICBpZiAoc2VsZWN0ZWRFbCkge1xuICAgICAgcmV0dXJuIHRoaXMuI2dldFBhcmVudChzZWxlY3RlZEVsLCAnYScpIGFzIEhUTUxBbmNob3JFbGVtZW50O1xuICAgIH1cblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHB1YmxpYyBzYXZlU2VsZWN0aW9uKCk6IFJhbmdlIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy4jc2VsZWN0aW9uU2VydmljZS5nZXRDdXJyZW50U2VsZWN0aW9uUmFuZ2UoXG4gICAgICB0aGlzLiNnZXRJZnJhbWVEb2N1bWVudEVsKCksXG4gICAgICB0aGlzLiNnZXRDb250ZW50V2luZG93RWwoKSxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIHNlbGVjdEVsZW1lbnQoZWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcbiAgICB0aGlzLiNzZWxlY3Rpb25TZXJ2aWNlLnNlbGVjdEVsZW1lbnQoXG4gICAgICB0aGlzLiNnZXRJZnJhbWVEb2N1bWVudEVsKCksXG4gICAgICB0aGlzLiNnZXRDb250ZW50V2luZG93RWwoKSxcbiAgICAgIGVsZW1lbnQsXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRFcnJvckF0dHJpYnV0ZXMoXG4gICAgZXJyb3JJZDogc3RyaW5nLFxuICAgIGVycm9yczogVmFsaWRhdGlvbkVycm9ycyB8IG51bGwsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGRvY3VtZW50RWwgPSB0aGlzLiNnZXRJZnJhbWVEb2N1bWVudEVsKCk7XG4gICAgZG9jdW1lbnRFbC5ib2R5LnNldEF0dHJpYnV0ZSgnYXJpYS1pbnZhbGlkJywgKCEhZXJyb3JzKS50b1N0cmluZygpKTtcbiAgICBpZiAoZXJyb3JzICYmIGVycm9ySWQpIHtcbiAgICAgIGRvY3VtZW50RWwuYm9keS5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXJyb3JtZXNzYWdlJywgZXJyb3JJZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRvY3VtZW50RWwuYm9keS5yZW1vdmVBdHRyaWJ1dGUoJ2FyaWEtZXJyb3JtZXNzYWdlJyk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHNldExhYmVsQXR0cmlidXRlKGxhYmVsOiBzdHJpbmcgfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICBpZiAobGFiZWwpIHtcbiAgICAgIGNvbnN0IGRvY3VtZW50RWwgPSB0aGlzLiNnZXRJZnJhbWVEb2N1bWVudEVsKCk7XG4gICAgICBkb2N1bWVudEVsLmJvZHkuc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgbGFiZWwpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBzZXRQbGFjZWhvbGRlcihwbGFjZWhvbGRlcj86IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGRvY3VtZW50RWwgPSB0aGlzLiNnZXRJZnJhbWVEb2N1bWVudEVsKCk7XG4gICAgZG9jdW1lbnRFbC5ib2R5LnNldEF0dHJpYnV0ZSgnZGF0YS1wbGFjZWhvbGRlcicsIHBsYWNlaG9sZGVyIHx8ICcnKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRSZXF1aXJlZEF0dHJpYnV0ZShyZXF1aXJlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIGNvbnN0IGRvY3VtZW50RWwgPSB0aGlzLiNnZXRJZnJhbWVEb2N1bWVudEVsKCk7XG4gICAgZG9jdW1lbnRFbC5ib2R5LnNldEF0dHJpYnV0ZSgnYXJpYS1yZXF1aXJlZCcsIHJlcXVpcmVkLnRvU3RyaW5nKCkpO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHNldEZvbnRTaXplKGZvbnRTaXplOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBkb2MgPSB0aGlzLiNnZXRJZnJhbWVEb2N1bWVudEVsKCk7XG4gICAgYXdhaXQgdGhpcy5leGVjQ29tbWFuZCh7IGNvbW1hbmQ6ICdmb250U2l6ZScsIHZhbHVlOiAnMScgfSk7XG4gICAgY29uc3QgZm9udEVsZW1lbnRzOiBIVE1MRWxlbWVudFtdID0gQXJyYXkuZnJvbShcbiAgICAgIGRvYy5xdWVyeVNlbGVjdG9yQWxsKCdmb250W3NpemU9XCIxXCJdJyksXG4gICAgKTtcbiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZm9udEVsZW1lbnRzKSB7XG4gICAgICBlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnc2l6ZScpO1xuICAgICAgZWxlbWVudC5zdHlsZS5mb250U2l6ZSA9IGZvbnRTaXplICsgJ3B4JztcbiAgICB9XG4gICAgdGhpcy4jY2xlYW5VcEJsYW5rU3R5bGVUYWdzKGRvYyk7XG5cbiAgICB0aGlzLmZvY3VzRWRpdG9yKCk7XG4gICAgdGhpcy4jdGV4dEVkaXRvclNlcnZpY2UuZWRpdG9yLmNvbW1hbmRDaGFuZ2VPYnNlcnZhYmxlLm5leHQoKTtcbiAgfVxuXG4gIHB1YmxpYyByZW1vdmVPYnNlcnZlcnMoc2V0dGluZzogRWRpdG9yU2V0dGluZyk6IHZvaWQge1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgY29uc3QgZG9jdW1lbnRFbCA9IHNldHRpbmcuaWZyYW1lRWxlbWVudFJlZi5jb250ZW50V2luZG93XG4gICAgICA/IHNldHRpbmcuaWZyYW1lRWxlbWVudFJlZi5jb250ZW50V2luZG93LmRvY3VtZW50XG4gICAgICA6IHNldHRpbmcuaWZyYW1lRWxlbWVudFJlZi5jb250ZW50RG9jdW1lbnQ7XG4gICAgc2V0dGluZy5zZWxlY3Rpb25DaGFuZ2VPYnNlcnZhYmxlLmNvbXBsZXRlKCk7XG4gICAgc2V0dGluZy5jbGlja09ic2VydmFibGUuY29tcGxldGUoKTtcbiAgICBzZXR0aW5nLmNvbW1hbmRDaGFuZ2VPYnNlcnZhYmxlLmNvbXBsZXRlKCk7XG4gICAgaWYgKGRvY3VtZW50RWwpIHtcbiAgICAgIGRvY3VtZW50RWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgJ3NlbGVjdGlvbmNoYW5nZScsXG4gICAgICAgIHNldHRpbmcuc2VsZWN0aW9uTGlzdGVuZXIsXG4gICAgICApO1xuICAgICAgZG9jdW1lbnRFbC5yZW1vdmVFdmVudExpc3RlbmVyKCdpbnB1dCcsIHNldHRpbmcuc2VsZWN0aW9uTGlzdGVuZXIpO1xuICAgICAgZG9jdW1lbnRFbC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBzZXR0aW5nLmNsaWNrTGlzdGVuZXIpO1xuICAgICAgZG9jdW1lbnRFbC5ib2R5LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Bhc3RlJywgc2V0dGluZy5wYXN0ZUxpc3RlbmVyKTtcbiAgICB9XG4gIH1cblxuICAjZ2V0Q29udGVudFdpbmRvd0VsKCk6IFdpbmRvdyB7XG4gICAgcmV0dXJuIHRoaXMuI3RleHRFZGl0b3JTZXJ2aWNlLmVkaXRvci5pZnJhbWVFbGVtZW50UmVmXG4gICAgICAuY29udGVudFdpbmRvdyBhcyBXaW5kb3c7XG4gIH1cblxuICAjZ2V0Q2hpbGRTZWxlY3RlZEFuY2hvclRhZ3MoKTogRWxlbWVudFtdIHtcbiAgICBjb25zdCBzZWxlY3RlZFJhbmdlID0gdGhpcy5nZXRDdXJyZW50U2VsZWN0aW9uKCk/LmdldFJhbmdlQXQoMCk7XG4gICAgaWYgKHNlbGVjdGVkUmFuZ2UgJiYgc2VsZWN0ZWRSYW5nZS50b1N0cmluZygpLmxlbmd0aCA8PSAwKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgY29uc3QgcGFyZW50RWxlbWVudCA9IHRoaXMuI2dldEN1cnJlbnRTZWxlY3Rpb25QYXJlbnRFbGVtZW50KCk7XG5cbiAgICBsZXQgY2hpbGRFbGVtZW50czogSFRNTEFuY2hvckVsZW1lbnRbXSA9IFtdO1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgaWYgKHBhcmVudEVsZW1lbnQpIHtcbiAgICAgIGNoaWxkRWxlbWVudHMgPSBBcnJheS5mcm9tKHBhcmVudEVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCgnYScpKTtcbiAgICB9XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHJldHVybiBjaGlsZEVsZW1lbnRzLmZpbHRlcigoZWxlbWVudCkgPT4ge1xuICAgICAgLy8gSUUgc3BlY2lmaWNcbiAgICAgIGlmIChzZWxlY3RlZFJhbmdlKSB7XG4gICAgICAgIGlmICghc2VsZWN0ZWRSYW5nZS5pbnRlcnNlY3RzTm9kZSkge1xuICAgICAgICAgIGlmICghZWxlbWVudCB8fCAhZWxlbWVudC5ocmVmKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHRlbXBSYW5nZSA9IGRvY3VtZW50LmNyZWF0ZVJhbmdlKCk7XG4gICAgICAgICAgdGVtcFJhbmdlLnNlbGVjdE5vZGVDb250ZW50cyhlbGVtZW50KTtcbiAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgKHNlbGVjdGVkUmFuZ2UuY29tcGFyZUJvdW5kYXJ5UG9pbnRzKFxuICAgICAgICAgICAgICBSYW5nZS5TVEFSVF9UT19TVEFSVCxcbiAgICAgICAgICAgICAgdGVtcFJhbmdlLFxuICAgICAgICAgICAgKSAhPT0gLTEgJiZcbiAgICAgICAgICAgICAgc2VsZWN0ZWRSYW5nZS5jb21wYXJlQm91bmRhcnlQb2ludHMoXG4gICAgICAgICAgICAgICAgUmFuZ2UuU1RBUlRfVE9fRU5ELFxuICAgICAgICAgICAgICAgIHRlbXBSYW5nZSxcbiAgICAgICAgICAgICAgKSAhPT0gMSkgfHxcbiAgICAgICAgICAgIChzZWxlY3RlZFJhbmdlLmNvbXBhcmVCb3VuZGFyeVBvaW50cyhcbiAgICAgICAgICAgICAgUmFuZ2UuRU5EX1RPX1NUQVJULFxuICAgICAgICAgICAgICB0ZW1wUmFuZ2UsXG4gICAgICAgICAgICApICE9PSAtMSAmJlxuICAgICAgICAgICAgICBzZWxlY3RlZFJhbmdlLmNvbXBhcmVCb3VuZGFyeVBvaW50cyhcbiAgICAgICAgICAgICAgICBSYW5nZS5FTkRfVE9fRU5ELFxuICAgICAgICAgICAgICAgIHRlbXBSYW5nZSxcbiAgICAgICAgICAgICAgKSAhPT0gMSlcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIE5vcm1hbCBub24tSUVcbiAgICAgIHJldHVybiAoXG4gICAgICAgICEhZWxlbWVudCAmJiAhIWVsZW1lbnQuaHJlZiAmJiBzZWxlY3RlZFJhbmdlPy5pbnRlcnNlY3RzTm9kZShlbGVtZW50KVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gICNnZXRJZnJhbWVEb2N1bWVudEVsKCk6IERvY3VtZW50IHtcbiAgICBjb25zdCBjb250ZW50V2luZG93RWwgPSB0aGlzLiNnZXRDb250ZW50V2luZG93RWwoKTtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgIGlmIChjb250ZW50V2luZG93RWwpIHtcbiAgICAgIHJldHVybiBjb250ZW50V2luZG93RWwuZG9jdW1lbnQ7XG4gICAgfVxuXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICByZXR1cm4gdGhpcy4jdGV4dEVkaXRvclNlcnZpY2UuZWRpdG9yLmlmcmFtZUVsZW1lbnRSZWZcbiAgICAgIC5jb250ZW50RG9jdW1lbnQgYXMgRG9jdW1lbnQ7XG4gIH1cblxuICAjZ2V0Rm9udFNpemUoKTogc3RyaW5nIHtcbiAgICBsZXQgZm9udFNpemUgPSBTVFlMRV9TVEFURV9ERUZBVUxUUy5mb250U2l6ZS50b1N0cmluZygpO1xuICAgIGNvbnN0IHNlbGVjdGlvbiA9IHRoaXMuZ2V0Q3VycmVudFNlbGVjdGlvbigpO1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgaWYgKFxuICAgICAgc2VsZWN0aW9uICYmXG4gICAgICBzZWxlY3Rpb24uYW5jaG9yTm9kZSAmJlxuICAgICAgc2VsZWN0aW9uLmFuY2hvck5vZGUucGFyZW50RWxlbWVudFxuICAgICkge1xuICAgICAgbGV0IGVsZW1lbnQgPSBzZWxlY3Rpb24uYW5jaG9yTm9kZSBhcyBIVE1MRWxlbWVudCB8IG51bGwgfCB1bmRlZmluZWQ7XG4gICAgICBpZiAoZWxlbWVudD8ubm9kZVR5cGUgIT09IDEpIHtcbiAgICAgICAgZWxlbWVudCA9IGVsZW1lbnQ/LnBhcmVudEVsZW1lbnQ7XG4gICAgICB9XG4gICAgICBjb25zdCBjb21wdXRlZFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCBhcyBFbGVtZW50KTtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgICBpZiAoY29tcHV0ZWRTdHlsZSkge1xuICAgICAgICBmb250U2l6ZSA9IGNvbXB1dGVkU3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgnZm9udC1zaXplJyk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmb250U2l6ZTtcbiAgfVxuXG4gICNjcmVhdGVPYnNlcnZlcnMoZWxlbWVudDogSFRNTElGcmFtZUVsZW1lbnQpOiBFZGl0b3JTZXR0aW5nIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGNvbnN0IGRvY3VtZW50RWwgPSBlbGVtZW50LmNvbnRlbnRXaW5kb3dcbiAgICAgID8gZWxlbWVudC5jb250ZW50V2luZG93LmRvY3VtZW50XG4gICAgICA6IChlbGVtZW50LmNvbnRlbnREb2N1bWVudCBhcyBEb2N1bWVudCk7XG5cbiAgICAvLyBGaXJlZm94IGJ1ZyB3aGVyZSB3ZSBuZWVkIHRvIG9wZW4vY2xvc2UgdG8gY2FuY2VsIGxvYWQgc28gaXQgZG9lc24ndCBvdmVyd3JpdGUgYXR0cnNcbiAgICBkb2N1bWVudEVsLm9wZW4oKTtcbiAgICBkb2N1bWVudEVsLmNsb3NlKCk7XG5cbiAgICBjb25zdCBzZWxlY3Rpb25PYnNlcnZhYmxlID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgICBjb25zdCBzZWxlY3Rpb25MaXN0ZW5lciA9ICgpOiB2b2lkID0+IHNlbGVjdGlvbk9ic2VydmFibGUubmV4dCgpO1xuICAgIGNvbnN0IGNsaWNrT2JzZXJ2YWJsZSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gICAgY29uc3QgY2xpY2tMaXN0ZW5lciA9ICgpOiB2b2lkID0+IGNsaWNrT2JzZXJ2YWJsZS5uZXh0KCk7XG4gICAgY29uc3QgcGFzdGVMaXN0ZW5lciA9IHRoaXMuI2dldFBhc3RlT3ZlcnJpZGUoKTtcbiAgICBjb25zdCBibHVyT2JzZXJ2YWJsZSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gICAgY29uc3QgYmx1ckxpc3RlbmVyID0gKCk6IHZvaWQgPT4gYmx1ck9ic2VydmFibGUubmV4dCgpO1xuICAgIGNvbnN0IGZvY3VzT2JzZXJ2YWJsZSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gICAgY29uc3QgZm9jdXNMaXN0ZW5lciA9ICgpOiB2b2lkID0+IGZvY3VzT2JzZXJ2YWJsZS5uZXh0KCk7XG4gICAgY29uc3QgaW5wdXRPYnNlcnZhYmxlID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgICBjb25zdCBpbnB1dExpc3RlbmVyID0gKCk6IHZvaWQgPT4gaW5wdXRPYnNlcnZhYmxlLm5leHQoKTtcblxuICAgIGRvY3VtZW50RWwuYWRkRXZlbnRMaXN0ZW5lcignc2VsZWN0aW9uY2hhbmdlJywgc2VsZWN0aW9uTGlzdGVuZXIpO1xuICAgIGRvY3VtZW50RWwuYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLCBpbnB1dExpc3RlbmVyKTtcbiAgICBkb2N1bWVudEVsLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIGNsaWNrTGlzdGVuZXIpO1xuICAgIGRvY3VtZW50RWwuYm9keS5hZGRFdmVudExpc3RlbmVyKCdwYXN0ZScsIHBhc3RlTGlzdGVuZXIpO1xuICAgIGRvY3VtZW50RWwuYm9keS5hZGRFdmVudExpc3RlbmVyKCdibHVyJywgYmx1ckxpc3RlbmVyKTtcbiAgICBkb2N1bWVudEVsLmJvZHkuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXNpbicsIGZvY3VzTGlzdGVuZXIpO1xuICAgIHJldHVybiB7XG4gICAgICBibHVyT2JzZXJ2YWJsZSxcbiAgICAgIGNsaWNrT2JzZXJ2YWJsZSxcbiAgICAgIGZvY3VzT2JzZXJ2YWJsZSxcbiAgICAgIGNvbW1hbmRDaGFuZ2VPYnNlcnZhYmxlOiBuZXcgU3ViamVjdCgpLFxuICAgICAgaWZyYW1lRWxlbWVudFJlZjogZWxlbWVudCxcbiAgICAgIGlucHV0T2JzZXJ2YWJsZSxcbiAgICAgIHNlbGVjdGlvbkNoYW5nZU9ic2VydmFibGU6IHNlbGVjdGlvbk9ic2VydmFibGUsXG4gICAgICBibHVyTGlzdGVuZXIsXG4gICAgICBmb2N1c0xpc3RlbmVyLFxuICAgICAgY2xpY2tMaXN0ZW5lcixcbiAgICAgIGlucHV0TGlzdGVuZXIsXG4gICAgICBwYXN0ZUxpc3RlbmVyLFxuICAgICAgc2VsZWN0aW9uTGlzdGVuZXIsXG4gICAgfTtcbiAgfVxuXG4gICNnZXRQYXN0ZU92ZXJyaWRlKCk6IChlOiBDbGlwYm9hcmRFdmVudCkgPT4gdm9pZCB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICByZXR1cm4gKGU6IENsaXBib2FyZEV2ZW50KTogdm9pZCA9PiB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBjb25zdCB0ZXh0ID0gZS5jbGlwYm9hcmREYXRhPy5nZXREYXRhKCd0ZXh0L3BsYWluJyk7XG5cbiAgICAgIGlmICh0ZXh0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdm9pZCB0aGlzLmV4ZWNDb21tYW5kKHtcbiAgICAgICAgICBjb21tYW5kOiAnaW5zZXJ0SFRNTCcsXG4gICAgICAgICAgdmFsdWU6IHRleHQudG9TdHJpbmcoKSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gICNnZXRDdXJyZW50U2VsZWN0aW9uUGFyZW50RWxlbWVudCgpOiBFbGVtZW50IHwgbnVsbCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuI3NlbGVjdGlvblNlcnZpY2UuZ2V0Q3VycmVudFNlbGVjdGlvblBhcmVudEVsZW1lbnQoXG4gICAgICB0aGlzLiNnZXRJZnJhbWVEb2N1bWVudEVsKCksXG4gICAgKTtcbiAgfVxuXG4gICNnZXRDb2xvcihkb2N1bWVudEVsOiBEb2N1bWVudCwgc2VsZWN0b3I6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgY29tbWFuZFZhbHVlID0gZG9jdW1lbnRFbC5xdWVyeUNvbW1hbmRWYWx1ZShzZWxlY3Rvcik7XG5cbiAgICAvLyBFZGdlIGlzIHdlaXJkIGFuZCByZXR1cm5zIG51bWJlcnNcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAodHlwZW9mIGNvbW1hbmRWYWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICByZXR1cm4gKFxuICAgICAgICAncmdiKCcgK1xuICAgICAgICAoY29tbWFuZFZhbHVlICYgMHhmZikgK1xuICAgICAgICAnLCAnICtcbiAgICAgICAgKChjb21tYW5kVmFsdWUgJiAweGZmMDApID4+IDgpICtcbiAgICAgICAgJywgJyArXG4gICAgICAgICgoY29tbWFuZFZhbHVlICYgMHhmZjAwMDApID4+IDE2KSArXG4gICAgICAgICcpJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBGaXJlZm94IHVzZXMgJ1RyYW5zcGFyZW50JyBpbnN0ZWFkIG9mIGEgY29sb3IgdmFsdWVcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmIChjb21tYW5kVmFsdWUudG9TdHJpbmcoKS50b0xvd2VyQ2FzZSgpID09PSAndHJhbnNwYXJlbnQnKSB7XG4gICAgICByZXR1cm4gU1RZTEVfU1RBVEVfREVGQVVMVFMuYmFja0NvbG9yO1xuICAgIH1cbiAgICByZXR1cm4gY29tbWFuZFZhbHVlO1xuICB9XG5cbiAgI2hhc0xpbmsoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgYW5jaG9yRWwgPSB0aGlzLmdldFNlbGVjdGVkQW5jaG9yVGFnKCk7XG4gICAgY29uc3QgY2hpbGRBbmNob3JFbHMgPSB0aGlzLiNnZXRDaGlsZFNlbGVjdGVkQW5jaG9yVGFncygpO1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgcmV0dXJuIGNoaWxkQW5jaG9yRWxzLmxlbmd0aCA+IDAgfHwgKCEhYW5jaG9yRWwgJiYgISFhbmNob3JFbC5ocmVmKTtcbiAgfVxuXG4gICNnZXRQYXJlbnQoZWxlbWVudDogRWxlbWVudCwgdGFnOiBzdHJpbmcpOiBFbGVtZW50IHwgdW5kZWZpbmVkIHtcbiAgICBsZXQgY3VycmVudE5vZGU6IEVsZW1lbnQgfCBudWxsID0gZWxlbWVudDtcbiAgICB3aGlsZSAoY3VycmVudE5vZGUgJiYgY3VycmVudE5vZGUudGFnTmFtZS50b1VwcGVyQ2FzZSgpICE9PSAnQk9EWScpIHtcbiAgICAgIGlmIChjdXJyZW50Tm9kZS50YWdOYW1lLnRvVXBwZXJDYXNlKCkgPT09IHRhZy50b1VwcGVyQ2FzZSgpKSB7XG4gICAgICAgIHJldHVybiBjdXJyZW50Tm9kZTtcbiAgICAgIH1cbiAgICAgIGN1cnJlbnROb2RlID0gY3VycmVudE5vZGUucGFyZW50RWxlbWVudDtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHB1YmxpYyBlZGl0b3JTZWxlY3RlZCgpOiBib29sZWFuIHtcbiAgICBjb25zdCBkb2N1bWVudEVsID0gdGhpcy4jZ2V0SWZyYW1lRG9jdW1lbnRFbCgpO1xuICAgIHJldHVybiB0aGlzLiNzZWxlY3Rpb25TZXJ2aWNlLmlzRWxlbWVudFNlbGVjdGVkKFxuICAgICAgZG9jdW1lbnRFbCxcbiAgICAgIGRvY3VtZW50RWwuYm9keSxcbiAgICApO1xuICB9XG5cbiAgI2NsZWFuVXBCbGFua1N0eWxlVGFncyhkb2M6IERvY3VtZW50KTogdm9pZCB7XG4gICAgY29uc3Qgb3JwaGFuRWxlbWVudHM6IEhUTUxFbGVtZW50W10gPSBBcnJheS5mcm9tKFxuICAgICAgZG9jLnF1ZXJ5U2VsZWN0b3JBbGwoJ2ZvbnQsc3BhbiwqW3N0eWxlPVwiXCJdJyksXG4gICAgKTtcbiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2Ygb3JwaGFuRWxlbWVudHMpIHtcbiAgICAgIGlmICghZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3N0eWxlJykpIHtcbiAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ3N0eWxlJyk7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IHJlbW92YWJsZUVsZW1lbnRzID0gb3JwaGFuRWxlbWVudHMuZmlsdGVyKChlbGVtZW50KSA9PiB7XG4gICAgICBjb25zdCB0YWdOYW1lID0gZWxlbWVudC50YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICByZXR1cm4gKFxuICAgICAgICAodGFnTmFtZSA9PT0gJ0ZPTlQnIHx8IHRhZ05hbWUgPT09ICdTUEFOJykgJiZcbiAgICAgICAgKGVsZW1lbnQuYXR0cmlidXRlcy5sZW5ndGggPT09IDAgfHwgIWVsZW1lbnQuaGFzQ2hpbGROb2RlcylcbiAgICAgICk7XG4gICAgfSk7XG4gICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHJlbW92YWJsZUVsZW1lbnRzKSB7XG4gICAgICBjb25zdCBwYXJlbnQgPSBlbGVtZW50LnBhcmVudE5vZGU7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgaWYgKHBhcmVudCkge1xuICAgICAgICB3aGlsZSAoZWxlbWVudC5maXJzdENoaWxkKSB7XG4gICAgICAgICAgcGFyZW50Lmluc2VydEJlZm9yZShlbGVtZW50LmZpcnN0Q2hpbGQsIGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICAgIHBhcmVudC5yZW1vdmVDaGlsZChlbGVtZW50KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBDZXJ0YWluIHZhbHVlcyBhcmUgZW5jb2RlZCBpbiBodG1sIGFuZCBuZWVkIHRvIGJlIGRlY29kZWRcbiAgI3JlcGxhY2VIdG1sQ29kZXMoc3RyOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBzdHJcbiAgICAgIC5yZXBsYWNlKC8mbmJzcDsvLCBTdHJpbmcuZnJvbUNoYXJDb2RlKDE2MCkpXG4gICAgICAucmVwbGFjZSgvJmx0Oy9nLCAnPCcpXG4gICAgICAucmVwbGFjZSgvJmd0Oy9nLCAnPicpXG4gICAgICAucmVwbGFjZSgvJmFtcDsvZywgJyYnKTtcbiAgfVxuXG4gICNzZXRFZGl0b3JEaXNhYmxlZChcbiAgICBmb2N1c2FibGVDaGlsZHJlbjogSFRNTEVsZW1lbnRbXSxcbiAgICB0ZXh0RWRpdG9yTmF0aXZlRWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICAgZGlzYWJsZWQ6IGJvb2xlYW4sXG4gICk6IHZvaWQge1xuICAgIHRleHRFZGl0b3JOYXRpdmVFbGVtZW50LnN0eWxlLnBvaW50ZXJFdmVudHMgPSBkaXNhYmxlZCA/ICdub25lJyA6ICdhdXRvJztcbiAgICB0ZXh0RWRpdG9yTmF0aXZlRWxlbWVudC5zZXRBdHRyaWJ1dGUoXG4gICAgICAnYXJpYS1kaXNhYmxlZCcsXG4gICAgICBkaXNhYmxlZCA/ICd0cnVlJyA6ICdmYWxzZScsXG4gICAgKTtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgIGlmIChmb2N1c2FibGVDaGlsZHJlbi5sZW5ndGggPiAwKSB7XG4gICAgICBmb2N1c2FibGVDaGlsZHJlbi5mb3JFYWNoKChhRm9jdXNhYmxlQ2hpbGQpID0+IHtcbiAgICAgICAgYUZvY3VzYWJsZUNoaWxkLnRhYkluZGV4ID0gZGlzYWJsZWQgPyAtMSA6IDA7XG4gICAgICB9KTtcbiAgICB9XG4gICAgdGhpcy4jZ2V0SWZyYW1lRG9jdW1lbnRFbCgpLmJvZHkuc2V0QXR0cmlidXRlKFxuICAgICAgJ2NvbnRlbnRlZGl0YWJsZScsXG4gICAgICBkaXNhYmxlZCA/ICdmYWxzZScgOiAndHJ1ZScsXG4gICAgKTtcbiAgfVxufVxuIl19