slate-angular 18.0.1 → 19.0.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.
- package/fesm2022/slate-angular.mjs +120 -130
- package/fesm2022/slate-angular.mjs.map +1 -1
- package/package.json +1 -3
- package/view/base.d.ts +4 -4
- package/view/container-item.d.ts +1 -1
- package/view/container.d.ts +1 -1
- package/esm2022/components/block-card/block-card.component.mjs +0 -33
- package/esm2022/components/children/children-outlet.component.mjs +0 -22
- package/esm2022/components/children/children.component.mjs +0 -23
- package/esm2022/components/editable/editable.component.mjs +0 -1266
- package/esm2022/components/element/default-element.component.mjs +0 -19
- package/esm2022/components/element/default-element.component.token.mjs +0 -3
- package/esm2022/components/element/element.component.mjs +0 -19
- package/esm2022/components/leaf/default-leaf.component.mjs +0 -30
- package/esm2022/components/leaf/token.mjs +0 -3
- package/esm2022/components/leaves/leaves.component.mjs +0 -25
- package/esm2022/components/string/default-string.component.mjs +0 -75
- package/esm2022/components/string/string.component.mjs +0 -108
- package/esm2022/components/string/template.component.mjs +0 -20
- package/esm2022/components/text/default-text.component.mjs +0 -22
- package/esm2022/components/text/token.mjs +0 -4
- package/esm2022/components/text/void-text.component.mjs +0 -32
- package/esm2022/custom-event/BeforeInputEventPlugin.mjs +0 -251
- package/esm2022/custom-event/DOMTopLevelEventTypes.mjs +0 -13
- package/esm2022/custom-event/FallbackCompositionState.mjs +0 -62
- package/esm2022/custom-event/before-input-polyfill.mjs +0 -13
- package/esm2022/module.mjs +0 -69
- package/esm2022/plugins/angular-editor.mjs +0 -610
- package/esm2022/plugins/with-angular.mjs +0 -217
- package/esm2022/public-api.mjs +0 -20
- package/esm2022/slate-angular.mjs +0 -5
- package/esm2022/types/clipboard.mjs +0 -2
- package/esm2022/types/error.mjs +0 -12
- package/esm2022/types/feature.mjs +0 -2
- package/esm2022/types/index.mjs +0 -5
- package/esm2022/types/view.mjs +0 -2
- package/esm2022/utils/block-card.mjs +0 -25
- package/esm2022/utils/clipboard/clipboard.mjs +0 -78
- package/esm2022/utils/clipboard/common.mjs +0 -42
- package/esm2022/utils/clipboard/data-transfer.mjs +0 -44
- package/esm2022/utils/clipboard/index.mjs +0 -5
- package/esm2022/utils/clipboard/navigator-clipboard.mjs +0 -59
- package/esm2022/utils/constants.mjs +0 -2
- package/esm2022/utils/dom.mjs +0 -165
- package/esm2022/utils/environment.mjs +0 -34
- package/esm2022/utils/global-normalize.mjs +0 -11
- package/esm2022/utils/hotkeys.mjs +0 -99
- package/esm2022/utils/index.mjs +0 -12
- package/esm2022/utils/key.mjs +0 -14
- package/esm2022/utils/lines.mjs +0 -46
- package/esm2022/utils/range-list.mjs +0 -29
- package/esm2022/utils/restore-dom.mjs +0 -33
- package/esm2022/utils/throttle.mjs +0 -18
- package/esm2022/utils/view.mjs +0 -8
- package/esm2022/utils/weak-maps.mjs +0 -40
- package/esm2022/view/base.mjs +0 -273
- package/esm2022/view/container-item.mjs +0 -108
- package/esm2022/view/container.mjs +0 -22
- package/esm2022/view/context-change.mjs +0 -13
- package/esm2022/view/context.mjs +0 -2
- package/esm2022/view/render/leaves-render.mjs +0 -107
- package/esm2022/view/render/list-render.mjs +0 -302
- package/esm2022/view/render/utils.mjs +0 -110
|
@@ -1,610 +0,0 @@
|
|
|
1
|
-
import { Editor, Range, Transforms, Element } from 'slate';
|
|
2
|
-
import { EDITOR_TO_ELEMENT, ELEMENT_TO_NODE, IS_FOCUSED, IS_READONLY, NODE_TO_INDEX, NODE_TO_PARENT, NODE_TO_ELEMENT, NODE_TO_KEY, EDITOR_TO_WINDOW } from '../utils/weak-maps';
|
|
3
|
-
import { hasShadowRoot, isDOMElement, isDOMSelection, normalizeDOMPoint } from '../utils/dom';
|
|
4
|
-
import { Key } from '../utils/key';
|
|
5
|
-
import { IS_CHROME } from '../utils/environment';
|
|
6
|
-
import { FAKE_LEFT_BLOCK_CARD_OFFSET, FAKE_RIGHT_BLOCK_CARD_OFFSET, getCardTargetAttribute, isCardLeftByTargetAttr } from '../utils/block-card';
|
|
7
|
-
export const AngularEditor = {
|
|
8
|
-
/**
|
|
9
|
-
* Return the host window of the current editor.
|
|
10
|
-
*/
|
|
11
|
-
getWindow(editor) {
|
|
12
|
-
const window = EDITOR_TO_WINDOW.get(editor);
|
|
13
|
-
if (!window) {
|
|
14
|
-
throw new Error('Unable to find a host window element for this editor');
|
|
15
|
-
}
|
|
16
|
-
return window;
|
|
17
|
-
},
|
|
18
|
-
/**
|
|
19
|
-
* Find a key for a Slate node.
|
|
20
|
-
*/
|
|
21
|
-
findKey(editor, node) {
|
|
22
|
-
let key = NODE_TO_KEY.get(node);
|
|
23
|
-
if (!key) {
|
|
24
|
-
key = new Key();
|
|
25
|
-
NODE_TO_KEY.set(node, key);
|
|
26
|
-
}
|
|
27
|
-
return key;
|
|
28
|
-
},
|
|
29
|
-
/**
|
|
30
|
-
* handle editor error.
|
|
31
|
-
*/
|
|
32
|
-
onError(errorData) {
|
|
33
|
-
if (errorData.nativeError) {
|
|
34
|
-
throw errorData.nativeError;
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
/**
|
|
38
|
-
* Find the path of Slate node.
|
|
39
|
-
*/
|
|
40
|
-
findPath(editor, node) {
|
|
41
|
-
const path = [];
|
|
42
|
-
let child = node;
|
|
43
|
-
while (true) {
|
|
44
|
-
const parent = NODE_TO_PARENT.get(child);
|
|
45
|
-
if (parent == null) {
|
|
46
|
-
if (Editor.isEditor(child) && child === editor) {
|
|
47
|
-
return path;
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
break;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
const i = NODE_TO_INDEX.get(child);
|
|
54
|
-
if (i == null) {
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
|
-
path.unshift(i);
|
|
58
|
-
child = parent;
|
|
59
|
-
}
|
|
60
|
-
throw new Error(`Unable to find the path for Slate node: ${JSON.stringify(node)}`);
|
|
61
|
-
},
|
|
62
|
-
isNodeInEditor(editor, node) {
|
|
63
|
-
let child = node;
|
|
64
|
-
while (true) {
|
|
65
|
-
const parent = NODE_TO_PARENT.get(child);
|
|
66
|
-
if (parent == null) {
|
|
67
|
-
if (Editor.isEditor(child) && child === editor) {
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
const i = NODE_TO_INDEX.get(child);
|
|
75
|
-
if (i == null) {
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
child = parent;
|
|
79
|
-
}
|
|
80
|
-
return false;
|
|
81
|
-
},
|
|
82
|
-
/**
|
|
83
|
-
* Find the DOM node that implements DocumentOrShadowRoot for the editor.
|
|
84
|
-
*/
|
|
85
|
-
findDocumentOrShadowRoot(editor) {
|
|
86
|
-
const el = AngularEditor.toDOMNode(editor, editor);
|
|
87
|
-
const root = el.getRootNode();
|
|
88
|
-
if ((root instanceof Document || root instanceof ShadowRoot) && root.getSelection != null) {
|
|
89
|
-
return root;
|
|
90
|
-
}
|
|
91
|
-
return el.ownerDocument;
|
|
92
|
-
},
|
|
93
|
-
/**
|
|
94
|
-
* Check if the editor is focused.
|
|
95
|
-
*/
|
|
96
|
-
isFocused(editor) {
|
|
97
|
-
return !!IS_FOCUSED.get(editor);
|
|
98
|
-
},
|
|
99
|
-
/**
|
|
100
|
-
* Check if the editor is in read-only mode.
|
|
101
|
-
*/
|
|
102
|
-
isReadonly(editor) {
|
|
103
|
-
return !!IS_READONLY.get(editor);
|
|
104
|
-
},
|
|
105
|
-
/**
|
|
106
|
-
* Check if the editor is hanging right.
|
|
107
|
-
*/
|
|
108
|
-
isBlockHangingRight(editor) {
|
|
109
|
-
const { selection } = editor;
|
|
110
|
-
if (!selection) {
|
|
111
|
-
return false;
|
|
112
|
-
}
|
|
113
|
-
if (Range.isCollapsed(selection)) {
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
const [start, end] = Range.edges(selection);
|
|
117
|
-
const endBlock = Editor.above(editor, {
|
|
118
|
-
at: end,
|
|
119
|
-
match: node => Element.isElement(node) && Editor.isBlock(editor, node)
|
|
120
|
-
});
|
|
121
|
-
return Editor.isStart(editor, end, endBlock[1]);
|
|
122
|
-
},
|
|
123
|
-
/**
|
|
124
|
-
* Blur the editor.
|
|
125
|
-
*/
|
|
126
|
-
blur(editor) {
|
|
127
|
-
const el = AngularEditor.toDOMNode(editor, editor);
|
|
128
|
-
const root = AngularEditor.findDocumentOrShadowRoot(editor);
|
|
129
|
-
IS_FOCUSED.set(editor, false);
|
|
130
|
-
if (root.activeElement === el) {
|
|
131
|
-
el.blur();
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
/**
|
|
135
|
-
* Focus the editor.
|
|
136
|
-
*/
|
|
137
|
-
focus(editor) {
|
|
138
|
-
const el = AngularEditor.toDOMNode(editor, editor);
|
|
139
|
-
IS_FOCUSED.set(editor, true);
|
|
140
|
-
const window = AngularEditor.getWindow(editor);
|
|
141
|
-
if (window.document.activeElement !== el) {
|
|
142
|
-
el.focus({ preventScroll: true });
|
|
143
|
-
}
|
|
144
|
-
},
|
|
145
|
-
/**
|
|
146
|
-
* Deselect the editor.
|
|
147
|
-
*/
|
|
148
|
-
deselect(editor) {
|
|
149
|
-
const { selection } = editor;
|
|
150
|
-
const root = AngularEditor.findDocumentOrShadowRoot(editor);
|
|
151
|
-
const domSelection = root.getSelection();
|
|
152
|
-
if (domSelection && domSelection.rangeCount > 0) {
|
|
153
|
-
domSelection.removeAllRanges();
|
|
154
|
-
}
|
|
155
|
-
if (selection) {
|
|
156
|
-
Transforms.deselect(editor);
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
/**
|
|
160
|
-
* Check if a DOM node is within the editor.
|
|
161
|
-
*/
|
|
162
|
-
hasDOMNode(editor, target, options = {}) {
|
|
163
|
-
const { editable = false } = options;
|
|
164
|
-
const editorEl = AngularEditor.toDOMNode(editor, editor);
|
|
165
|
-
let targetEl;
|
|
166
|
-
// COMPAT: In Firefox, reading `target.nodeType` will throw an error if
|
|
167
|
-
// target is originating from an internal "restricted" element (e.g. a
|
|
168
|
-
// stepper arrow on a number input). (2018/05/04)
|
|
169
|
-
// https://github.com/ianstormtaylor/slate/issues/1819
|
|
170
|
-
try {
|
|
171
|
-
targetEl = (isDOMElement(target) ? target : target.parentElement);
|
|
172
|
-
}
|
|
173
|
-
catch (err) {
|
|
174
|
-
if (!err.message.includes('Permission denied to access property "nodeType"')) {
|
|
175
|
-
throw err;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (!targetEl) {
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
return (targetEl.closest(`[data-slate-editor]`) === editorEl &&
|
|
182
|
-
(!editable || targetEl.isContentEditable || !!targetEl.getAttribute('data-slate-zero-width')));
|
|
183
|
-
},
|
|
184
|
-
/**
|
|
185
|
-
* Insert data from a `DataTransfer` into the editor.
|
|
186
|
-
*/
|
|
187
|
-
insertData(editor, data) {
|
|
188
|
-
editor.insertData(data);
|
|
189
|
-
},
|
|
190
|
-
/**
|
|
191
|
-
* Insert fragment data from a `DataTransfer` into the editor.
|
|
192
|
-
*/
|
|
193
|
-
insertFragmentData(editor, data) {
|
|
194
|
-
return editor.insertFragmentData(data);
|
|
195
|
-
},
|
|
196
|
-
/**
|
|
197
|
-
* Insert text data from a `DataTransfer` into the editor.
|
|
198
|
-
*/
|
|
199
|
-
insertTextData(editor, data) {
|
|
200
|
-
return editor.insertTextData(data);
|
|
201
|
-
},
|
|
202
|
-
/**
|
|
203
|
-
* onKeydown hook.
|
|
204
|
-
*/
|
|
205
|
-
onKeydown(editor, data) {
|
|
206
|
-
editor.onKeydown(data);
|
|
207
|
-
},
|
|
208
|
-
/**
|
|
209
|
-
* onClick hook.
|
|
210
|
-
*/
|
|
211
|
-
onClick(editor, data) {
|
|
212
|
-
editor.onClick(data);
|
|
213
|
-
},
|
|
214
|
-
/**
|
|
215
|
-
* Sets data from the currently selected fragment on a `DataTransfer`.
|
|
216
|
-
*/
|
|
217
|
-
setFragmentData(editor, data, originEvent) {
|
|
218
|
-
editor.setFragmentData(data, originEvent);
|
|
219
|
-
},
|
|
220
|
-
deleteCutData(editor) {
|
|
221
|
-
editor.deleteCutData();
|
|
222
|
-
},
|
|
223
|
-
/**
|
|
224
|
-
* Find the native DOM element from a Slate node.
|
|
225
|
-
*/
|
|
226
|
-
toDOMNode(editor, node) {
|
|
227
|
-
const domNode = Editor.isEditor(node) ? EDITOR_TO_ELEMENT.get(editor) : NODE_TO_ELEMENT.get(node);
|
|
228
|
-
if (!domNode) {
|
|
229
|
-
throw new Error(`Cannot resolve a DOM node from Slate node: ${JSON.stringify(node)}`);
|
|
230
|
-
}
|
|
231
|
-
return domNode;
|
|
232
|
-
},
|
|
233
|
-
/**
|
|
234
|
-
* Find a native DOM selection point from a Slate point.
|
|
235
|
-
*/
|
|
236
|
-
toDOMPoint(editor, point, options) {
|
|
237
|
-
const [node] = Editor.node(editor, point.path);
|
|
238
|
-
const el = AngularEditor.toDOMNode(editor, node);
|
|
239
|
-
let domPoint;
|
|
240
|
-
// block card
|
|
241
|
-
const [parentNode] = Editor.parent(editor, point.path);
|
|
242
|
-
if (editor.isBlockCard(parentNode) || editor.isBlockCard(node)) {
|
|
243
|
-
if (point.offset < 0) {
|
|
244
|
-
if (point.offset === FAKE_LEFT_BLOCK_CARD_OFFSET) {
|
|
245
|
-
const cursorNode = AngularEditor.getCardCursorNode(editor, node, { direction: 'left' });
|
|
246
|
-
return [cursorNode, 1];
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
const cursorNode = AngularEditor.getCardCursorNode(editor, node, { direction: 'right' });
|
|
250
|
-
return [cursorNode, 1];
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
if (Range.isExpanded(options.range)) {
|
|
254
|
-
const [start, end] = Range.edges(options.range);
|
|
255
|
-
if (start === point) {
|
|
256
|
-
const cursorNode = AngularEditor.getCardCursorNode(editor, parentNode, { direction: 'left' });
|
|
257
|
-
return [cursorNode, 1];
|
|
258
|
-
}
|
|
259
|
-
else {
|
|
260
|
-
const cursorNode = AngularEditor.getCardCursorNode(editor, parentNode, { direction: 'right' });
|
|
261
|
-
return [cursorNode, 1];
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
// If we're inside a void node, force the offset to 0, otherwise the zero
|
|
266
|
-
// width spacing character will result in an incorrect offset of 1
|
|
267
|
-
if (Editor.void(editor, { at: point })) {
|
|
268
|
-
point = { path: point.path, offset: 0 };
|
|
269
|
-
}
|
|
270
|
-
// For each leaf, we need to isolate its content, which means filtering
|
|
271
|
-
// to its direct text and zero-width spans. (We have to filter out any
|
|
272
|
-
// other siblings that may have been rendered alongside them.)
|
|
273
|
-
const selector = `[data-slate-string], [data-slate-zero-width]`;
|
|
274
|
-
const texts = Array.from(el.querySelectorAll(selector));
|
|
275
|
-
let start = 0;
|
|
276
|
-
for (const text of texts) {
|
|
277
|
-
const domNode = text.childNodes[0];
|
|
278
|
-
if (domNode == null || domNode.textContent == null) {
|
|
279
|
-
continue;
|
|
280
|
-
}
|
|
281
|
-
const { length } = domNode.textContent;
|
|
282
|
-
const attr = text.getAttribute('data-slate-length');
|
|
283
|
-
const trueLength = attr == null ? length : parseInt(attr, 10);
|
|
284
|
-
const end = start + trueLength;
|
|
285
|
-
if (point.offset <= end) {
|
|
286
|
-
const offset = Math.min(length, Math.max(0, point.offset - start));
|
|
287
|
-
domPoint = [domNode, offset];
|
|
288
|
-
// fixed cursor position after zero width char
|
|
289
|
-
if (offset === 0 && length === 1 && domNode.textContent === '\uFEFF') {
|
|
290
|
-
domPoint = [domNode, offset + 1];
|
|
291
|
-
}
|
|
292
|
-
break;
|
|
293
|
-
}
|
|
294
|
-
start = end;
|
|
295
|
-
}
|
|
296
|
-
if (!domPoint) {
|
|
297
|
-
throw new Error(`Cannot resolve a DOM point from Slate point: ${JSON.stringify(point)}`);
|
|
298
|
-
}
|
|
299
|
-
return domPoint;
|
|
300
|
-
},
|
|
301
|
-
/**
|
|
302
|
-
* Find a native DOM range from a Slate `range`.
|
|
303
|
-
*/
|
|
304
|
-
toDOMRange(editor, range) {
|
|
305
|
-
const { anchor, focus } = range;
|
|
306
|
-
const isBackward = Range.isBackward(range);
|
|
307
|
-
const domAnchor = AngularEditor.toDOMPoint(editor, anchor, { range });
|
|
308
|
-
const domFocus = Range.isCollapsed(range) ? domAnchor : AngularEditor.toDOMPoint(editor, focus, { range });
|
|
309
|
-
const window = AngularEditor.getWindow(editor);
|
|
310
|
-
const domRange = window.document.createRange();
|
|
311
|
-
const [startNode, startOffset] = isBackward ? domFocus : domAnchor;
|
|
312
|
-
const [endNode, endOffset] = isBackward ? domAnchor : domFocus;
|
|
313
|
-
// A slate Point at zero-width Leaf always has an offset of 0 but a native DOM selection at
|
|
314
|
-
// zero-width node has an offset of 1 so we have to check if we are in a zero-width node and
|
|
315
|
-
// adjust the offset accordingly.
|
|
316
|
-
const startEl = (isDOMElement(startNode) ? startNode : startNode.parentElement);
|
|
317
|
-
const isStartAtZeroWidth = !!startEl.getAttribute('data-slate-zero-width');
|
|
318
|
-
const endEl = (isDOMElement(endNode) ? endNode : endNode.parentElement);
|
|
319
|
-
const isEndAtZeroWidth = !!endEl.getAttribute('data-slate-zero-width');
|
|
320
|
-
domRange.setStart(startNode, isStartAtZeroWidth ? 1 : startOffset);
|
|
321
|
-
domRange.setEnd(endNode, isEndAtZeroWidth ? 1 : endOffset);
|
|
322
|
-
return domRange;
|
|
323
|
-
},
|
|
324
|
-
/**
|
|
325
|
-
* Find a Slate node from a native DOM `element`.
|
|
326
|
-
*/
|
|
327
|
-
toSlateNode(editor, domNode, options) {
|
|
328
|
-
const { suppressThrow } = options || { suppressThrow: false };
|
|
329
|
-
let domEl = isDOMElement(domNode) ? domNode : domNode.parentElement;
|
|
330
|
-
if (domEl && !domEl.hasAttribute('data-slate-node')) {
|
|
331
|
-
domEl = domEl.closest(`[data-slate-node]`);
|
|
332
|
-
}
|
|
333
|
-
const node = domEl ? ELEMENT_TO_NODE.get(domEl) : null;
|
|
334
|
-
if (!node) {
|
|
335
|
-
if (suppressThrow) {
|
|
336
|
-
return null;
|
|
337
|
-
}
|
|
338
|
-
throw new Error(`Cannot resolve a Slate node from DOM node: ${domEl}`);
|
|
339
|
-
}
|
|
340
|
-
return node;
|
|
341
|
-
},
|
|
342
|
-
/**
|
|
343
|
-
* Get the target range from a DOM `event`.
|
|
344
|
-
*/
|
|
345
|
-
findEventRange(editor, event) {
|
|
346
|
-
if ('nativeEvent' in event) {
|
|
347
|
-
event = event.nativeEvent;
|
|
348
|
-
}
|
|
349
|
-
const { clientX: x, clientY: y, target } = event;
|
|
350
|
-
if (x == null || y == null) {
|
|
351
|
-
throw new Error(`Cannot resolve a Slate range from a DOM event: ${event}`);
|
|
352
|
-
}
|
|
353
|
-
const node = AngularEditor.toSlateNode(editor, event.target, { suppressThrow: false });
|
|
354
|
-
const path = AngularEditor.findPath(editor, node);
|
|
355
|
-
// If the drop target is inside a void node, move it into either the
|
|
356
|
-
// next or previous node, depending on which side the `x` and `y`
|
|
357
|
-
// coordinates are closest to.
|
|
358
|
-
if (Element.isElement(node) && Editor.isVoid(editor, node)) {
|
|
359
|
-
const rect = target.getBoundingClientRect();
|
|
360
|
-
const isPrev = editor.isInline(node) ? x - rect.left < rect.left + rect.width - x : y - rect.top < rect.top + rect.height - y;
|
|
361
|
-
const edge = Editor.point(editor, path, {
|
|
362
|
-
edge: isPrev ? 'start' : 'end'
|
|
363
|
-
});
|
|
364
|
-
const point = isPrev ? Editor.before(editor, edge) : Editor.after(editor, edge);
|
|
365
|
-
if (point) {
|
|
366
|
-
return Editor.range(editor, point);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
// Else resolve a range from the caret position where the drop occured.
|
|
370
|
-
let domRange;
|
|
371
|
-
const window = AngularEditor.getWindow(editor);
|
|
372
|
-
const { document } = window;
|
|
373
|
-
// COMPAT: In Firefox, `caretRangeFromPoint` doesn't exist. (2016/07/25)
|
|
374
|
-
if (document.caretRangeFromPoint) {
|
|
375
|
-
domRange = document.caretRangeFromPoint(x, y);
|
|
376
|
-
}
|
|
377
|
-
else {
|
|
378
|
-
const position = document.caretPositionFromPoint(x, y);
|
|
379
|
-
if (position) {
|
|
380
|
-
domRange = document.createRange();
|
|
381
|
-
domRange.setStart(position.offsetNode, position.offset);
|
|
382
|
-
domRange.setEnd(position.offsetNode, position.offset);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
if (!domRange) {
|
|
386
|
-
throw new Error(`Cannot resolve a Slate range from a DOM event: ${event}`);
|
|
387
|
-
}
|
|
388
|
-
// Resolve a Slate range from the DOM range.
|
|
389
|
-
const range = AngularEditor.toSlateRange(editor, domRange, { suppressThrow: false });
|
|
390
|
-
return range;
|
|
391
|
-
},
|
|
392
|
-
isLeafInEditor(editor, leafNode, options) {
|
|
393
|
-
const { suppressThrow } = options;
|
|
394
|
-
const textNode = leafNode.closest('[data-slate-node="text"]');
|
|
395
|
-
const node = AngularEditor.toSlateNode(editor, textNode, { suppressThrow });
|
|
396
|
-
if (node && AngularEditor.isNodeInEditor(editor, node)) {
|
|
397
|
-
return true;
|
|
398
|
-
}
|
|
399
|
-
else {
|
|
400
|
-
return false;
|
|
401
|
-
}
|
|
402
|
-
},
|
|
403
|
-
/**
|
|
404
|
-
* Find a Slate point from a DOM selection's `domNode` and `domOffset`.
|
|
405
|
-
*/
|
|
406
|
-
toSlatePoint(editor, domPoint, options) {
|
|
407
|
-
const { exactMatch, suppressThrow } = options;
|
|
408
|
-
const [domNode] = domPoint;
|
|
409
|
-
const [nearestNode, nearestOffset] = normalizeDOMPoint(domPoint);
|
|
410
|
-
let parentNode = nearestNode.parentNode;
|
|
411
|
-
let textNode = null;
|
|
412
|
-
let offset = 0;
|
|
413
|
-
// block card
|
|
414
|
-
const cardTargetAttr = getCardTargetAttribute(domNode);
|
|
415
|
-
if (cardTargetAttr) {
|
|
416
|
-
const domSelection = window.getSelection();
|
|
417
|
-
const isBackward = editor.selection && Range.isBackward(editor.selection);
|
|
418
|
-
const blockCardEntry = AngularEditor.toSlateCardEntry(editor, domNode) || AngularEditor.toSlateCardEntry(editor, nearestNode);
|
|
419
|
-
const [, blockPath] = blockCardEntry;
|
|
420
|
-
if (domSelection.isCollapsed) {
|
|
421
|
-
if (isCardLeftByTargetAttr(cardTargetAttr)) {
|
|
422
|
-
return { path: blockPath, offset: -1 };
|
|
423
|
-
}
|
|
424
|
-
else {
|
|
425
|
-
return { path: blockPath, offset: -2 };
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
if (isCardLeftByTargetAttr(cardTargetAttr)) {
|
|
429
|
-
return Editor.start(editor, blockPath);
|
|
430
|
-
}
|
|
431
|
-
else {
|
|
432
|
-
return Editor.end(editor, blockPath);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
if (parentNode) {
|
|
436
|
-
const voidNode = parentNode.closest('[data-slate-void="true"]');
|
|
437
|
-
let leafNode = parentNode.closest('[data-slate-leaf]');
|
|
438
|
-
let domNode = null;
|
|
439
|
-
// Calculate how far into the text node the `nearestNode` is, so that we
|
|
440
|
-
// can determine what the offset relative to the text node is.
|
|
441
|
-
if (leafNode && AngularEditor.isLeafInEditor(editor, leafNode, { suppressThrow: true })) {
|
|
442
|
-
textNode = leafNode.closest('[data-slate-node="text"]');
|
|
443
|
-
const window = AngularEditor.getWindow(editor);
|
|
444
|
-
const range = window.document.createRange();
|
|
445
|
-
range.setStart(textNode, 0);
|
|
446
|
-
range.setEnd(nearestNode, nearestOffset);
|
|
447
|
-
const contents = range.cloneContents();
|
|
448
|
-
const removals = [
|
|
449
|
-
...Array.prototype.slice.call(contents.querySelectorAll('[data-slate-zero-width]')),
|
|
450
|
-
...Array.prototype.slice.call(contents.querySelectorAll('[contenteditable=false]'))
|
|
451
|
-
];
|
|
452
|
-
removals.forEach(el => {
|
|
453
|
-
el.parentNode.removeChild(el);
|
|
454
|
-
});
|
|
455
|
-
// COMPAT: Edge has a bug where Range.prototype.toString() will
|
|
456
|
-
// convert \n into \r\n. The bug causes a loop when slate-react
|
|
457
|
-
// attempts to reposition its cursor to match the native position. Use
|
|
458
|
-
// textContent.length instead.
|
|
459
|
-
// https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/10291116/
|
|
460
|
-
offset = contents.textContent.length;
|
|
461
|
-
domNode = textNode;
|
|
462
|
-
}
|
|
463
|
-
else if (voidNode) {
|
|
464
|
-
// For void nodes, the element with the offset key will be a cousin, not an
|
|
465
|
-
// ancestor, so find it by going down from the nearest void parent.
|
|
466
|
-
const spacer = voidNode.querySelector('[data-slate-spacer="true"]');
|
|
467
|
-
leafNode = spacer.firstElementChild;
|
|
468
|
-
parentNode = leafNode.firstElementChild;
|
|
469
|
-
textNode = spacer;
|
|
470
|
-
domNode = leafNode;
|
|
471
|
-
offset = domNode.textContent.length;
|
|
472
|
-
}
|
|
473
|
-
// COMPAT: If the parent node is a Slate zero-width space, editor is
|
|
474
|
-
// because the text node should have no characters. However, during IME
|
|
475
|
-
// composition the ASCII characters will be prepended to the zero-width
|
|
476
|
-
// space, so subtract 1 from the offset to account for the zero-width
|
|
477
|
-
// space character.
|
|
478
|
-
if (domNode && offset === domNode.textContent.length && parentNode && parentNode.hasAttribute('data-slate-zero-width')) {
|
|
479
|
-
offset--;
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
if (!textNode) {
|
|
483
|
-
if (suppressThrow) {
|
|
484
|
-
return null;
|
|
485
|
-
}
|
|
486
|
-
throw new Error(`Cannot resolve a Slate point from DOM point: ${domPoint}`);
|
|
487
|
-
}
|
|
488
|
-
// COMPAT: If someone is clicking from one Slate editor into another,
|
|
489
|
-
// the select event fires twice, once for the old editor's `element`
|
|
490
|
-
// first, and then afterwards for the correct `element`. (2017/03/03)
|
|
491
|
-
const slateNode = AngularEditor.toSlateNode(editor, textNode, { suppressThrow });
|
|
492
|
-
if (!slateNode && suppressThrow) {
|
|
493
|
-
return null;
|
|
494
|
-
}
|
|
495
|
-
const path = AngularEditor.findPath(editor, slateNode);
|
|
496
|
-
return { path, offset };
|
|
497
|
-
},
|
|
498
|
-
/**
|
|
499
|
-
* Find a Slate range from a DOM range or selection.
|
|
500
|
-
*/
|
|
501
|
-
toSlateRange(editor, domRange, options) {
|
|
502
|
-
const { exactMatch, suppressThrow } = options || {};
|
|
503
|
-
const el = isDOMSelection(domRange) ? domRange.anchorNode : domRange.startContainer;
|
|
504
|
-
let anchorNode;
|
|
505
|
-
let anchorOffset;
|
|
506
|
-
let focusNode;
|
|
507
|
-
let focusOffset;
|
|
508
|
-
let isCollapsed;
|
|
509
|
-
if (el) {
|
|
510
|
-
if (isDOMSelection(domRange)) {
|
|
511
|
-
anchorNode = domRange.anchorNode;
|
|
512
|
-
anchorOffset = domRange.anchorOffset;
|
|
513
|
-
focusNode = domRange.focusNode;
|
|
514
|
-
focusOffset = domRange.focusOffset;
|
|
515
|
-
// COMPAT: There's a bug in chrome that always returns `true` for
|
|
516
|
-
// `isCollapsed` for a Selection that comes from a ShadowRoot.
|
|
517
|
-
// (2020/08/08)
|
|
518
|
-
// https://bugs.chromium.org/p/chromium/issues/detail?id=447523
|
|
519
|
-
if (IS_CHROME && hasShadowRoot()) {
|
|
520
|
-
isCollapsed = domRange.anchorNode === domRange.focusNode && domRange.anchorOffset === domRange.focusOffset;
|
|
521
|
-
}
|
|
522
|
-
else {
|
|
523
|
-
isCollapsed = domRange.isCollapsed;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
else {
|
|
527
|
-
anchorNode = domRange.startContainer;
|
|
528
|
-
anchorOffset = domRange.startOffset;
|
|
529
|
-
focusNode = domRange.endContainer;
|
|
530
|
-
focusOffset = domRange.endOffset;
|
|
531
|
-
isCollapsed = domRange.collapsed;
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
if (anchorNode == null || focusNode == null || anchorOffset == null || focusOffset == null) {
|
|
535
|
-
throw new Error(`Cannot resolve a Slate range from DOM range: ${domRange}`);
|
|
536
|
-
}
|
|
537
|
-
const anchor = AngularEditor.toSlatePoint(editor, [anchorNode, anchorOffset], { suppressThrow, exactMatch });
|
|
538
|
-
if (!anchor) {
|
|
539
|
-
return null;
|
|
540
|
-
}
|
|
541
|
-
const focus = isCollapsed ? anchor : AngularEditor.toSlatePoint(editor, [focusNode, focusOffset], { suppressThrow, exactMatch });
|
|
542
|
-
if (!focus) {
|
|
543
|
-
return null;
|
|
544
|
-
}
|
|
545
|
-
let range = { anchor: anchor, focus: focus };
|
|
546
|
-
// if the selection is a hanging range that ends in a void
|
|
547
|
-
// and the DOM focus is an Element
|
|
548
|
-
// (meaning that the selection ends before the element)
|
|
549
|
-
// unhang the range to avoid mistakenly including the void
|
|
550
|
-
if (Range.isExpanded(range) &&
|
|
551
|
-
Range.isForward(range) &&
|
|
552
|
-
isDOMElement(focusNode) &&
|
|
553
|
-
Editor.void(editor, { at: range.focus, mode: 'highest' })) {
|
|
554
|
-
range = Editor.unhangRange(editor, range, { voids: true });
|
|
555
|
-
}
|
|
556
|
-
return range;
|
|
557
|
-
},
|
|
558
|
-
isLeafBlock(editor, node) {
|
|
559
|
-
return Element.isElement(node) && !editor.isInline(node) && Editor.hasInlines(editor, node);
|
|
560
|
-
},
|
|
561
|
-
isBlockCardLeftCursor(editor) {
|
|
562
|
-
return (editor.selection?.anchor?.offset === FAKE_LEFT_BLOCK_CARD_OFFSET &&
|
|
563
|
-
editor.selection?.focus?.offset === FAKE_LEFT_BLOCK_CARD_OFFSET);
|
|
564
|
-
},
|
|
565
|
-
isBlockCardRightCursor(editor) {
|
|
566
|
-
return (editor.selection?.anchor?.offset === FAKE_RIGHT_BLOCK_CARD_OFFSET &&
|
|
567
|
-
editor.selection?.focus?.offset === FAKE_RIGHT_BLOCK_CARD_OFFSET);
|
|
568
|
-
},
|
|
569
|
-
getCardCursorNode(editor, blockCardNode, options) {
|
|
570
|
-
const blockCardElement = AngularEditor.toDOMNode(editor, blockCardNode);
|
|
571
|
-
const cardCenter = blockCardElement.parentElement;
|
|
572
|
-
return options.direction === 'left' ? cardCenter.previousElementSibling.firstChild : cardCenter.nextElementSibling.firstChild;
|
|
573
|
-
},
|
|
574
|
-
toSlateCardEntry(editor, node) {
|
|
575
|
-
const element = node.parentElement.closest('.slate-block-card')?.querySelector('[card-target="card-center"]').firstElementChild;
|
|
576
|
-
const slateNode = AngularEditor.toSlateNode(editor, element, { suppressThrow: false });
|
|
577
|
-
const path = AngularEditor.findPath(editor, slateNode);
|
|
578
|
-
return [slateNode, path];
|
|
579
|
-
},
|
|
580
|
-
/**
|
|
581
|
-
* move native selection to card-left or card-right
|
|
582
|
-
* @param editor
|
|
583
|
-
* @param blockCardNode
|
|
584
|
-
* @param options
|
|
585
|
-
*/
|
|
586
|
-
moveBlockCard(editor, blockCardNode, options) {
|
|
587
|
-
const cursorNode = AngularEditor.getCardCursorNode(editor, blockCardNode, options);
|
|
588
|
-
const window = AngularEditor.getWindow(editor);
|
|
589
|
-
const domSelection = window.getSelection();
|
|
590
|
-
domSelection.setBaseAndExtent(cursorNode, 1, cursorNode, 1);
|
|
591
|
-
},
|
|
592
|
-
/**
|
|
593
|
-
* move slate selection to card-left or card-right
|
|
594
|
-
* @param editor
|
|
595
|
-
* @param path
|
|
596
|
-
* @param options
|
|
597
|
-
*/
|
|
598
|
-
moveBlockCardCursor(editor, path, options) {
|
|
599
|
-
const cursor = {
|
|
600
|
-
path,
|
|
601
|
-
offset: options.direction === 'left' ? FAKE_LEFT_BLOCK_CARD_OFFSET : FAKE_RIGHT_BLOCK_CARD_OFFSET
|
|
602
|
-
};
|
|
603
|
-
Transforms.select(editor, { anchor: cursor, focus: cursor });
|
|
604
|
-
},
|
|
605
|
-
hasRange(editor, range) {
|
|
606
|
-
const { anchor, focus } = range;
|
|
607
|
-
return Editor.hasPath(editor, anchor.path) && Editor.hasPath(editor, focus.path);
|
|
608
|
-
}
|
|
609
|
-
};
|
|
610
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1lZGl0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9wYWNrYWdlcy9zcmMvcGx1Z2lucy9hbmd1bGFyLWVkaXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFxQixLQUFLLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBYyxNQUFNLE9BQU8sQ0FBQztBQUMxRixPQUFPLEVBQ0gsaUJBQWlCLEVBQ2pCLGVBQWUsRUFDZixVQUFVLEVBQ1YsV0FBVyxFQUNYLGFBQWEsRUFDYixjQUFjLEVBQ2QsZUFBZSxFQUNmLFdBQVcsRUFDWCxnQkFBZ0IsRUFDbkIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBT0gsYUFBYSxFQUNiLFlBQVksRUFDWixjQUFjLEVBQ2QsaUJBQWlCLEVBQ3BCLE1BQU0sY0FBYyxDQUFDO0FBSXRCLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDbkMsT0FBTyxFQUFFLFNBQVMsRUFBYyxNQUFNLHNCQUFzQixDQUFDO0FBQzdELE9BQU8sRUFDSCwyQkFBMkIsRUFDM0IsNEJBQTRCLEVBQzVCLHNCQUFzQixFQUV0QixzQkFBc0IsRUFFekIsTUFBTSxxQkFBcUIsQ0FBQztBQXVCN0IsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHO0lBQ3pCOztPQUVHO0lBRUgsU0FBUyxDQUFDLE1BQXFCO1FBQzNCLE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM1QyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDVixNQUFNLElBQUksS0FBSyxDQUFDLHNEQUFzRCxDQUFDLENBQUM7UUFDNUUsQ0FBQztRQUNELE9BQU8sTUFBTSxDQUFDO0lBQ2xCLENBQUM7SUFDRDs7T0FFRztJQUVILE9BQU8sQ0FBQyxNQUFxQixFQUFFLElBQVU7UUFDckMsSUFBSSxHQUFHLEdBQUcsV0FBVyxDQUFDLEdBQUcs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IEVsZW1lbnQsIEJhc2VFZGl0b3IgfSBmcm9tICdzbGF0ZSc7XG5pbXBvcnQge1xuICAgIEVESVRPUl9UT19FTEVNRU5ULFxuICAgIEVMRU1FTlRfVE9fTk9ERSxcbiAgICBJU19GT0NVU0VELFxuICAgIElTX1JFQURPTkxZLFxuICAgIE5PREVfVE9fSU5ERVgsXG4gICAgTk9ERV9UT19QQVJFTlQsXG4gICAgTk9ERV9UT19FTEVNRU5ULFxuICAgIE5PREVfVE9fS0VZLFxuICAgIEVESVRPUl9UT19XSU5ET1dcbn0gZnJvbSAnLi4vdXRpbHMvd2Vhay1tYXBzJztcbmltcG9ydCB7XG4gICAgRE9NRWxlbWVudCxcbiAgICBET01Ob2RlLFxuICAgIERPTVBvaW50LFxuICAgIERPTVJhbmdlLFxuICAgIERPTVNlbGVjdGlvbixcbiAgICBET01TdGF0aWNSYW5nZSxcbiAgICBoYXNTaGFkb3dSb290LFxuICAgIGlzRE9NRWxlbWVudCxcbiAgICBpc0RPTVNlbGVjdGlvbixcbiAgICBub3JtYWxpemVET01Qb2ludFxufSBmcm9tICcuLi91dGlscy9kb20nO1xuaW1wb3J0IHsgSW5qZWN0b3IgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5vZGVFbnRyeSB9IGZyb20gJ3NsYXRlJztcbmltcG9ydCB7IFNsYXRlRXJyb3IgfSBmcm9tICcuLi90eXBlcy9lcnJvcic7XG5pbXBvcnQgeyBLZXkgfSBmcm9tICcuLi91dGlscy9rZXknO1xuaW1wb3J0IHsgSVNfQ0hST01FLCBJU19GSVJFRk9YIH0gZnJvbSAnLi4vdXRpbHMvZW52aXJvbm1lbnQnO1xuaW1wb3J0IHtcbiAgICBGQUtFX0xFRlRfQkxPQ0tfQ0FSRF9PRkZTRVQsXG4gICAgRkFLRV9SSUdIVF9CTE9DS19DQVJEX09GRlNFVCxcbiAgICBnZXRDYXJkVGFyZ2V0QXR0cmlidXRlLFxuICAgIGlzQ2FyZENlbnRlckJ5VGFyZ2V0QXR0cixcbiAgICBpc0NhcmRMZWZ0QnlUYXJnZXRBdHRyLFxuICAgIGlzQ2FyZFJpZ2h0QnlUYXJnZXRBdHRyXG59IGZyb20gJy4uL3V0aWxzL2Jsb2NrLWNhcmQnO1xuaW1wb3J0IHsgU2FmZUFueSB9IGZyb20gJy4uL3R5cGVzJztcbmltcG9ydCB7IENsaXBib2FyZERhdGEsIE9yaWdpbkV2ZW50IH0gZnJvbSAnLi4vdHlwZXMvY2xpcGJvYXJkJztcblxuLyoqXG4gKiBBbiBBbmd1bGFyIGFuZCBET00tc3BlY2lmaWMgdmVyc2lvbiBvZiB0aGUgYEVkaXRvcmAgaW50ZXJmYWNlLlxuICovXG5cbmV4cG9ydCBpbnRlcmZhY2UgQW5ndWxhckVkaXRvciBleHRlbmRzIEJhc2VFZGl0b3Ige1xuICAgIGluc2VydERhdGE6IChkYXRhOiBEYXRhVHJhbnNmZXIpID0+IHZvaWQ7XG4gICAgaW5zZXJ0RnJhZ21lbnREYXRhOiAoZGF0YTogRGF0YVRyYW5zZmVyKSA9PiBQcm9taXNlPGJvb2xlYW4+O1xuICAgIGluc2VydFRleHREYXRhOiAoZGF0YTogRGF0YVRyYW5zZmVyKSA9PiBQcm9taXNlPGJvb2xlYW4+O1xuICAgIHNldEZyYWdtZW50RGF0YTogKGRhdGE6IERhdGFUcmFuc2Zlciwgb3JpZ2luRXZlbnQ/OiBPcmlnaW5FdmVudCkgPT4gdm9pZDtcbiAgICBkZWxldGVDdXREYXRhOiAoKSA9PiB2b2lkO1xuICAgIG9uS2V5ZG93bjogKGV2ZW50OiBLZXlib2FyZEV2ZW50KSA9PiB2b2lkO1xuICAgIG9uQ2xpY2s6IChldmVudDogTW91c2VFdmVudCkgPT4gdm9pZDtcbiAgICBpbmplY3RvcjogSW5qZWN0b3I7XG4gICAgaXNCbG9ja0NhcmQ6IChub2RlOiBOb2RlKSA9PiBib29sZWFuO1xuICAgIGlzRXhwYW5kZWQ6IChub2RlOiBFbGVtZW50KSA9PiBib29sZWFuO1xuICAgIG9uRXJyb3I6IChlcnJvckRhdGE6IFNsYXRlRXJyb3IpID0+IHZvaWQ7XG4gICAgaGFzUmFuZ2U6IChlZGl0b3I6IEFuZ3VsYXJFZGl0b3IsIHJhbmdlOiBSYW5nZSkgPT4gYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNvbnN0IEFuZ3VsYXJFZGl0b3IgPSB7XG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBob3N0IHdpbmRvdyBvZiB0aGUgY3VycmVudCBlZGl0b3IuXG4gICAgICovXG5cbiAgICBnZXRXaW5kb3coZWRpdG9yOiBBbmd1bGFyRWRpdG9yKTogV2luZG93IHtcbiAgICAgICAgY29uc3Qgd2luZG93ID0gRURJVE9SX1RPX1dJTkRPVy5nZXQoZWRpdG9yKTtcbiAgICAgICAgaWYgKCF3aW5kb3cpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGZpbmQgYSBob3N0IHdpbmRvdyBlbGVtZW50IGZvciB0aGlzIGVkaXRvcicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB3aW5kb3c7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBGaW5kIGEga2V5IGZvciBhIFNsYXRlIG5vZGUuXG4gICAgICovXG5cbiAgICBmaW5kS2V5KGVkaXRvcjogQW5ndWxhckVkaXRvciwgbm9kZTogTm9kZSk6IEtleSB7XG4gICAgICAgIGxldCBrZXkgPSBOT0RFX1RPX0tFWS5nZXQobm9kZSk7XG5cbiAgICAgICAgaWYgKCFrZXkpIHtcbiAgICAgICAgICAgIGtleSA9IG5ldyBLZXkoKTtcbiAgICAgICAgICAgIE5PREVfVE9fS0VZLnNldChub2RlLCBrZXkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGtleTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogaGFuZGxlIGVkaXRvciBlcnJvci5cbiAgICAgKi9cblxuICAgIG9uRXJyb3IoZXJyb3JEYXRhOiBTbGF0ZUVycm9yKSB7XG4gICAgICAgIGlmIChlcnJvckRhdGEubmF0aXZlRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGVycm9yRGF0YS5uYXRpdmVFcnJvcjtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGaW5kIHRoZSBwYXRoIG9mIFNsYXRlIG5vZGUuXG4gICAgICovXG5cbiAgICBmaW5kUGF0aChlZGl0b3I6IEFuZ3VsYXJFZGl0b3IsIG5vZGU6IE5vZGUpOiBQYXRoIHtcbiAgICAgICAgY29uc3QgcGF0aDogUGF0aCA9IFtdO1xuICAgICAgICBsZXQgY2hpbGQgPSBub2RlO1xuXG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJlbnQgPSBOT0RFX1RPX1BBUkVOVC5nZXQoY2hpbGQpO1xuXG4gICAgICAgICAgICBpZiAocGFyZW50ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAoRWRpdG9yLmlzRWRpdG9yKGNoaWxkKSAmJiBjaGlsZCA9PT0gZWRpdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRoO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgaSA9IE5PREVfVE9fSU5ERVguZ2V0KGNoaWxkKTtcblxuICAgICAgICAgICAgaWYgKGkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwYXRoLnVuc2hpZnQoaSk7XG4gICAgICAgICAgICBjaGlsZCA9IHBhcmVudDtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBmaW5kIHRoZSBwYXRoIGZvciBTbGF0ZSBub2RlOiAke0pTT04uc3RyaW5naWZ5KG5vZGUpfWApO1xuICAgIH0sXG5cbiAgICBpc05vZGVJbkVkaXRvcihlZGl0b3I6IEFuZ3VsYXJFZGl0b3IsIG5vZGU6IE5vZGUpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IGNoaWxkID0gbm9kZTtcblxuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgY29uc3QgcGFyZW50ID0gTk9ERV9UT19QQVJFTlQuZ2V0KGNoaWxkKTtcblxuICAgICAgICAgICAgaWYgKHBhcmVudCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKEVkaXRvci5pc0VkaXRvcihjaGlsZCkgJiYgY2hpbGQgPT09IGVkaXRvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGkgPSBOT0RFX1RPX0lOREVYLmdldChjaGlsZCk7XG5cbiAgICAgICAgICAgIGlmIChpID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2hpbGQgPSBwYXJlbnQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEZpbmQgdGhlIERPTSBub2RlIHRoYXQgaW1wbGVtZW50cyBEb2N1bWVudE9yU2hhZG93Um9vdCBmb3IgdGhlIGVkaXRvci5cbiAgICAgKi9cblxuICAgIGZpbmREb2N1bWVudE9yU2hhZG93Um9vdChlZGl0b3I6IEFuZ3VsYXJFZGl0b3IpOiBEb2N1bWVudCB8IFNoYWRvd1Jvb3Qge1xuICAgICAgICBjb25zdCBlbCA9IEFuZ3VsYXJFZGl0b3IudG9ET01Ob2RlKGVkaXRvciwgZWRpdG9yKTtcbiAgICAgICAgY29uc3Qgcm9vdCA9IGVsLmdldFJvb3ROb2RlKCk7XG4gICAgICAgIGlmICgocm9vdCBpbnN0YW5jZW9mIERvY3VtZW50IHx8IHJvb3QgaW5zdGFuY2VvZiBTaGFkb3dSb290KSAmJiAocm9vdCBhcyBEb2N1bWVudCkuZ2V0U2VsZWN0aW9uICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiByb290O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGVsLm93bmVyRG9jdW1lbnQ7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIHRoZSBlZGl0b3IgaXMgZm9jdXNlZC5cbiAgICAgKi9cblxuICAgIGlzRm9jdXNlZChlZGl0b3I6IEFuZ3VsYXJFZGl0b3IpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICEhSVNfRk9DVVNFRC5nZXQoZWRpdG9yKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgdGhlIGVkaXRvciBpcyBpbiByZWFkLW9ubHkgbW9kZS5cbiAgICAgKi9cblxuICAgIGlzUmVhZG9ubHkoZWRpdG9yOiBBbmd1bGFyRWRpdG9yKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAhIUlTX1JFQURPTkxZLmdldChlZGl0b3IpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiB0aGUgZWRpdG9yIGlzIGhhbmdpbmcgcmlnaHQuXG4gICAgICovXG4gICAgaXNCbG9ja0hhbmdpbmdSaWdodChlZGl0b3I6IEFuZ3VsYXJFZGl0b3IpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgeyBzZWxlY3Rpb24gfSA9IGVkaXRvcjtcbiAgICAgICAgaWYgKCFzZWxlY3Rpb24pIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoUmFuZ2UuaXNDb2xsYXBzZWQoc2VsZWN0aW9uKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IFtzdGFydCwgZW5kXSA9IFJhbmdlLmVkZ2VzKHNlbGVjdGlvbik7XG4gICAgICAgIGNvbnN0IGVuZEJsb2NrID0gRWRpdG9yLmFib3ZlKGVkaXRvciwge1xuICAgICAgICAgICAgYXQ6IGVuZCxcbiAgICAgICAgICAgIG1hdGNoOiBub2RlID0+IEVsZW1lbnQuaXNFbGVtZW50KG5vZGUpICYmIEVkaXRvci5pc0Jsb2NrKGVkaXRvciwgbm9kZSlcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBFZGl0b3IuaXNTdGFydChlZGl0b3IsIGVuZCwgZW5kQmxvY2tbMV0pO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBCbHVyIHRoZSBlZGl0b3IuXG4gICAgICovXG5cbiAgICBibHVyKGVkaXRvcjogQW5ndWxhckVkaXRvcik6IHZvaWQge1xuICAgICAgICBjb25zdCBlbCA9IEFuZ3VsYXJFZGl0b3IudG9ET01Ob2RlKGVkaXRvciwgZWRpdG9yKTtcbiAgICAgICAgY29uc3Qgcm9vdCA9IEFuZ3VsYXJFZGl0b3IuZmluZERvY3VtZW50T3JTaGFkb3dSb290KGVkaXRvcik7XG4gICAgICAgIElTX0ZPQ1VTRUQuc2V0KGVkaXRvciwgZmFsc2UpO1xuXG4gICAgICAgIGlmIChyb290LmFjdGl2ZUVsZW1lbnQgPT09IGVsKSB7XG4gICAgICAgICAgICBlbC5ibHVyKCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRm9jdXMgdGhlIGVkaXRvci5cbiAgICAgKi9cblxuICAgIGZvY3VzKGVkaXRvcjogQW5ndWxhckVkaXRvcik6IHZvaWQge1xuICAgICAgICBjb25zdCBlbCA9IEFuZ3VsYXJFZGl0b3IudG9ET01Ob2RlKGVkaXRvciwgZWRpdG9yKTtcbiAgICAgICAgSVNfRk9DVVNFRC5zZXQoZWRpdG9yLCB0cnVlKTtcblxuICAgICAgICBjb25zdCB3aW5kb3cgPSBBbmd1bGFyRWRpdG9yLmdldFdpbmRvdyhlZGl0b3IpO1xuICAgICAgICBpZiAod2luZG93LmRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgIT09IGVsKSB7XG4gICAgICAgICAgICBlbC5mb2N1cyh7IHByZXZlbnRTY3JvbGw6IHRydWUgfSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRGVzZWxlY3QgdGhlIGVkaXRvci5cbiAgICAgKi9cblxuICAgIGRlc2VsZWN0KGVkaXRvcjogQW5ndWxhckVkaXRvcik6IHZvaWQge1xuICAgICAgICBjb25zdCB7IHNlbGVjdGlvbiB9ID0gZWRpdG9yO1xuICAgICAgICBjb25zdCByb290ID0gQW5ndWxhckVkaXRvci5maW5kRG9jdW1lbnRPclNoYWRvd1Jvb3QoZWRpdG9yKTtcbiAgICAgICAgY29uc3QgZG9tU2VsZWN0aW9uID0gKHJvb3QgYXMgRG9jdW1lbnQpLmdldFNlbGVjdGlvbigpO1xuXG4gICAgICAgIGlmIChkb21TZWxlY3Rpb24gJiYgZG9tU2VsZWN0aW9uLnJhbmdlQ291bnQgPiAwKSB7XG4gICAgICAgICAgICBkb21TZWxlY3Rpb24ucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2VsZWN0aW9uKSB7XG4gICAgICAgICAgICBUcmFuc2Zvcm1zLmRlc2VsZWN0KGVkaXRvcik7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYSBET00gbm9kZSBpcyB3aXRoaW4gdGhlIGVkaXRvci5cbiAgICAgKi9cblxuICAgIGhhc0RPTU5vZGUoZWRpdG9yOiBBbmd1bGFyRWRpdG9yLCB0YXJnZXQ6IERPTU5vZGUsIG9wdGlvbnM6IHsgZWRpdGFibGU/OiBib29sZWFuIH0gPSB7fSk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCB7IGVkaXRhYmxlID0gZmFsc2UgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGVkaXRvckVsID0gQW5ndWxhckVkaXRvci50b0RPTU5vZGUoZWRpdG9yLCBlZGl0b3IpO1xuICAgICAgICBsZXQgdGFyZ2V0RWw7XG5cbiAgICAgICAgLy8gQ09NUEFUOiBJbiBGaXJlZm94LCByZWFkaW5nIGB0YXJnZXQubm9kZVR5cGVgIHdpbGwgdGhyb3cgYW4gZXJyb3IgaWZcbiAgICAgICAgLy8gdGFyZ2V0IGlzIG9yaWdpbmF0aW5nIGZyb20gYW4gaW50ZXJuYWwgXCJyZXN0cmljdGVkXCIgZWxlbWVudCAoZS5nLiBhXG4gICAgICAgIC8vIHN0ZXBwZXIgYXJyb3cgb24gYSBudW1iZXIgaW5wdXQpLiAoMjAxOC8wNS8wNClcbiAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2lhbnN0b3JtdGF5bG9yL3NsYXRlL2lzc3Vlcy8xODE5XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0YXJnZXRFbCA9IChpc0RPTUVsZW1lbnQodGFyZ2V0KSA/IHRhcmdldCA6IHRhcmdldC5wYXJlbnRFbGVtZW50KSBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoIWVyci5tZXNzYWdlLmluY2x1ZGVzKCdQZXJtaXNzaW9uIGRlbmllZCB0byBhY2Nlc3MgcHJvcGVydHkgXCJub2RlVHlwZVwiJykpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRhcmdldEVsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdGFyZ2V0RWwuY2xvc2VzdChgW2RhdGEtc2xhdGUtZWRpdG9yXWApID09PSBlZGl0b3JFbCAmJlxuICAgICAgICAgICAgKCFlZGl0YWJsZSB8fCB0YXJnZXRFbC5pc0NvbnRlbnRFZGl0YWJsZSB8fCAhIXRhcmdldEVsLmdldEF0dHJpYnV0ZSgnZGF0YS1zbGF0ZS16ZXJvLXdpZHRoJykpXG4gICAgICAgICk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEluc2VydCBkYXRhIGZyb20gYSBgRGF0YVRyYW5zZmVyYCBpbnRvIHRoZSBlZGl0b3IuXG4gICAgICovXG5cbiAgICBpbnNlcnREYXRhKGVkaXRvcjogQW5ndWxhckVkaXRvciwgZGF0YTogRGF0YVRyYW5zZmVyKTogdm9pZCB7XG4gICAgICAgIGVkaXRvci5pbnNlcnREYXRhKGRhdGEpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBJbnNlcnQgZnJhZ21lbnQgZGF0YSBmcm9tIGEgYERhdGFUcmFuc2ZlcmAgaW50byB0aGUgZWRpdG9yLlxuICAgICAqL1xuXG4gICAgaW5zZXJ0RnJhZ21lbnREYXRhKGVkaXRvcjogQW5ndWxhckVkaXRvciwgZGF0YTogRGF0YVRyYW5zZmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiBlZGl0b3IuaW5zZXJ0RnJhZ21lbnREYXRhKGRhdGEpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBJbnNlcnQgdGV4dCBkYXRhIGZyb20gYSBgRGF0YVRyYW5zZmVyYCBpbnRvIHRoZSBlZGl0b3IuXG4gICAgICovXG5cbiAgICBpbnNlcnRUZXh0RGF0YShlZGl0b3I6IEFuZ3VsYXJFZGl0b3IsIGRhdGE6IERhdGFUcmFuc2Zlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gZWRpdG9yLmluc2VydFRleHREYXRhKGRhdGEpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBvbktleWRvd24gaG9vay5cbiAgICAgKi9cbiAgICBvbktleWRvd24oZWRpdG9yOiBBbmd1bGFyRWRpdG9yLCBkYXRhOiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgICAgIGVkaXRvci5vbktleWRvd24oZGF0YSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIG9uQ2xpY2sgaG9vay5cbiAgICAgKi9cbiAgICBvbkNsaWNrKGVkaXRvcjogQW5ndWxhckVkaXRvciwgZGF0YTogTW91c2VFdmVudCk6IHZvaWQge1xuICAgICAgICBlZGl0b3Iub25DbGljayhkYXRhKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0cyBkYXRhIGZyb20gdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBmcmFnbWVudCBvbiBhIGBEYXRhVHJhbnNmZXJgLlxuICAgICAqL1xuXG4gICAgc2V0RnJhZ21lbnREYXRhKGVkaXRvcjogQW5ndWxhckVkaXRvciwgZGF0YTogRGF0YVRyYW5zZmVyLCBvcmlnaW5FdmVudD86IE9yaWdpbkV2ZW50KTogdm9pZCB7XG4gICAgICAgIGVkaXRvci5zZXRGcmFnbWVudERhdGEoZGF0YSwgb3JpZ2luRXZlbnQpO1xuICAgIH0sXG5cbiAgICBkZWxldGVDdXREYXRhKGVkaXRvcjogQW5ndWxhckVkaXRvcik6IHZvaWQge1xuICAgICAgICBlZGl0b3IuZGVsZXRlQ3V0RGF0YSgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGaW5kIHRoZSBuYXRpdmUgRE9NIGVsZW1lbnQgZnJvbSBhIFNsYXRlIG5vZGUuXG4gICAgICovXG5cbiAgICB0b0RPTU5vZGUoZWRpdG9yOiBBbmd1bGFyRWRpdG9yLCBub2RlOiBOb2RlKTogSFRNTEVsZW1lbnQge1xuICAgICAgICBjb25zdCBkb21Ob2RlID0gRWRpdG9yLmlzRWRpdG9yKG5vZGUpID8gRURJVE9SX1RPX0VMRU1FTlQuZ2V0KGVkaXRvcikgOiBOT0RFX1RPX0VMRU1FTlQuZ2V0KG5vZGUpO1xuXG4gICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgcmVzb2x2ZSBhIERPTSBub2RlIGZyb20gU2xhdGUgbm9kZTogJHtKU09OLnN0cmluZ2lmeShub2RlKX1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGaW5kIGEgbmF0aXZlIERPTSBzZWxlY3Rpb24gcG9pbnQgZnJvbSBhIFNsYXRlIHBvaW50LlxuICAgICAqL1xuICAgIHRvRE9NUG9pbnQoZWRpdG9yOiBBbmd1bGFyRWRpdG9yLCBwb2ludDogUG9pbnQsIG9wdGlvbnM6IHsgcmFuZ2U6IFJhbmdlIH0pOiBET01Qb2ludCB7XG4gICAgICAgIGNvbnN0IFtub2RlXSA9IEVkaXRvci5ub2RlKGVkaXRvciwgcG9pbnQucGF0aCk7XG4gICAgICAgIGNvbnN0IGVsID0gQW5ndWxhckVkaXRvci50b0RPTU5vZGUoZWRpdG9yLCBub2RlKTtcbiAgICAgICAgbGV0IGRvbVBvaW50OiBET01Qb2ludCB8IHVuZGVmaW5lZDtcbiAgICAgICAgLy8gYmxvY2sgY2FyZFxuICAgICAgICBjb25zdCBbcGFyZW50Tm9kZV0gPSBFZGl0b3IucGFyZW50KGVkaXRvciwgcG9pbnQucGF0aCk7XG4gICAgICAgIGlmIChlZGl0b3IuaXNCbG9ja0NhcmQocGFyZW50Tm9kZSkgfHwgZWRpdG9yLmlzQmxvY2tDYXJkKG5vZGUpKSB7XG4gICAgICAgICAgICBpZiAocG9pbnQub2Zmc2V0IDwgMCkge1xuICAgICAgICAgICAgICAgIGlmIChwb2ludC5vZmZzZXQgPT09IEZBS0VfTEVGVF9CTE9DS19DQVJEX09GRlNFVCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJzb3JOb2RlID0gQW5ndWxhckVkaXRvci5nZXRDYXJkQ3Vyc29yTm9kZShlZGl0b3IsIG5vZGUsIHsgZGlyZWN0aW9uOiAnbGVmdCcgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbY3Vyc29yTm9kZSwgMV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY3Vyc29yTm9kZSA9IEFuZ3VsYXJFZGl0b3IuZ2V0Q2FyZEN1cnNvck5vZGUoZWRpdG9yLCBub2RlLCB7IGRpcmVjdGlvbjogJ3JpZ2h0JyB9KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtjdXJzb3JOb2RlLCAxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoUmFuZ2UuaXNFeHBhbmRlZChvcHRpb25zLnJhbmdlKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtzdGFydCwgZW5kXSA9IFJhbmdlLmVkZ2VzKG9wdGlvbnMucmFuZ2UpO1xuICAgICAgICAgICAgICAgIGlmIChzdGFydCA9PT0gcG9pbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY3Vyc29yTm9kZSA9IEFuZ3VsYXJFZGl0b3IuZ2V0Q2FyZEN1cnNvck5vZGUoZWRpdG9yLCBwYXJlbnROb2RlLCB7IGRpcmVjdGlvbjogJ2xlZnQnIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gW2N1cnNvck5vZGUsIDFdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnNvck5vZGUgPSBBbmd1bGFyRWRpdG9yLmdldENhcmRDdXJzb3JOb2RlKGVkaXRvciwgcGFyZW50Tm9kZSwgeyBkaXJlY3Rpb246ICdyaWdodCcgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbY3Vyc29yTm9kZSwgMV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgd2UncmUgaW5zaWRlIGEgdm9pZCBub2RlLCBmb3JjZSB0aGUgb2Zmc2V0IHRvIDAsIG90aGVyd2lzZSB0aGUgemVyb1xuICAgICAgICAvLyB3aWR0aCBzcGFjaW5nIGNoYXJhY3RlciB3aWxsIHJlc3VsdCBpbiBhbiBpbmNvcnJlY3Qgb2Zmc2V0IG9mIDFcbiAgICAgICAgaWYgKEVkaXRvci52b2lkKGVkaXRvciwgeyBhdDogcG9pbnQgfSkpIHtcbiAgICAgICAgICAgIHBvaW50ID0geyBwYXRoOiBwb2ludC5wYXRoLCBvZmZzZXQ6IDAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZvciBlYWNoIGxlYWYsIHdlIG5lZWQgdG8gaXNvbGF0ZSBpdHMgY29udGVudCwgd2hpY2ggbWVhbnMgZmlsdGVyaW5nXG4gICAgICAgIC8vIHRvIGl0cyBkaXJlY3QgdGV4dCBhbmQgemVyby13aWR0aCBzcGFucy4gKFdlIGhhdmUgdG8gZmlsdGVyIG91dCBhbnlcbiAgICAgICAgLy8gb3RoZXIgc2libGluZ3MgdGhhdCBtYXkgaGF2ZSBiZWVuIHJlbmRlcmVkIGFsb25nc2lkZSB0aGVtLilcbiAgICAgICAgY29uc3Qgc2VsZWN0b3IgPSBgW2RhdGEtc2xhdGUtc3RyaW5nXSwgW2RhdGEtc2xhdGUtemVyby13aWR0aF1gO1xuICAgICAgICBjb25zdCB0ZXh0cyA9IEFycmF5LmZyb20oZWwucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikpO1xuICAgICAgICBsZXQgc3RhcnQgPSAwO1xuXG4gICAgICAgIGZvciAoY29uc3QgdGV4dCBvZiB0ZXh0cykge1xuICAgICAgICAgICAgY29uc3QgZG9tTm9kZSA9IHRleHQuY2hpbGROb2Rlc1swXSBhcyBIVE1MRWxlbWVudDtcblxuICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT0gbnVsbCB8fCBkb21Ob2RlLnRleHRDb250ZW50ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgeyBsZW5ndGggfSA9IGRvbU5vZGUudGV4dENvbnRlbnQ7XG4gICAgICAgICAgICBjb25zdCBhdHRyID0gdGV4dC5nZXRBdHRyaWJ1dGUoJ2RhdGEtc2xhdGUtbGVuZ3RoJyk7XG4gICAgICAgICAgICBjb25zdCB0cnVlTGVuZ3RoID0gYXR0ciA9PSBudWxsID8gbGVuZ3RoIDogcGFyc2VJbnQoYXR0ciwgMTApO1xuICAgICAgICAgICAgY29uc3QgZW5kID0gc3RhcnQgKyB0cnVlTGVuZ3RoO1xuXG4gICAgICAgICAgICBpZiAocG9pbnQub2Zmc2V0IDw9IGVuZCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IE1hdGgubWluKGxlbmd0aCwgTWF0aC5tYXgoMCwgcG9pbnQub2Zmc2V0IC0gc3RhcnQpKTtcbiAgICAgICAgICAgICAgICBkb21Qb2ludCA9IFtkb21Ob2RlLCBvZmZzZXRdO1xuICAgICAgICAgICAgICAgIC8vIGZpeGVkIGN1cnNvciBwb3NpdGlvbiBhZnRlciB6ZXJvIHdpZHRoIGNoYXJcbiAgICAgICAgICAgICAgICBpZiAob2Zmc2V0ID09PSAwICYmIGxlbmd0aCA9PT0gMSAmJiBkb21Ob2RlLnRleHRDb250ZW50ID09PSAnXFx1RkVGRicpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tUG9pbnQgPSBbZG9tTm9kZSwgb2Zmc2V0ICsgMV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzdGFydCA9IGVuZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghZG9tUG9pbnQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlc29sdmUgYSBET00gcG9pbnQgZnJvbSBTbGF0ZSBwb2ludDogJHtKU09OLnN0cmluZ2lmeShwb2ludCl9YCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZG9tUG9pbnQ7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEZpbmQgYSBuYXRpdmUgRE9NIHJhbmdlIGZyb20gYSBTbGF0ZSBgcmFuZ2VgLlxuICAgICAqL1xuXG4gICAgdG9ET01SYW5nZShlZGl0b3I6IEFuZ3VsYXJFZGl0b3IsIHJhbmdlOiBSYW5nZSk6IERPTVJhbmdlIHtcbiAgICAgICAgY29uc3QgeyBhbmNob3IsIGZvY3VzIH0gPSByYW5nZTtcbiAgICAgICAgY29uc3QgaXNCYWNrd2FyZCA9IFJhbmdlLmlzQmFja3dhcmQocmFuZ2UpO1xuICAgICAgICBjb25zdCBkb21BbmNob3IgPSBBbmd1bGFyRWRpdG9yLnRvRE9NUG9pbnQoZWRpdG9yLCBhbmNob3IsIHsgcmFuZ2UgfSk7XG4gICAgICAgIGNvbnN0IGRvbUZvY3VzID0gUmFuZ2UuaXNDb2xsYXBzZWQocmFuZ2UpID8gZG9tQW5jaG9yIDogQW5ndWxhckVkaXRvci50b0RPTVBvaW50KGVkaXRvciwgZm9jdXMsIHsgcmFuZ2UgfSk7XG5cbiAgICAgICAgY29uc3Qgd2luZG93ID0gQW5ndWxhckVkaXRvci5nZXRXaW5kb3coZWRpdG9yKTtcbiAgICAgICAgY29uc3QgZG9tUmFuZ2UgPSB3aW5kb3cuZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgICAgICAgY29uc3QgW3N0YXJ0Tm9kZSwgc3RhcnRPZmZzZXRdID0gaXNCYWNrd2FyZCA/IGRvbUZvY3VzIDogZG9tQW5jaG9yO1xuICAgICAgICBjb25zdCBbZW5kTm9kZSwgZW5kT2Zmc2V0XSA9IGlzQmFja3dhcmQgPyBkb21BbmNob3IgOiBkb21Gb2N1cztcblxuICAgICAgICAvLyBBIHNsYXRlIFBvaW50IGF0IHplcm8td2lkdGggTGVhZiBhbHdheXMgaGFzIGFuIG9mZnNldCBvZiAwIGJ1dCBhIG5hdGl2ZSBET00gc2VsZWN0aW9uIGF0XG4gICAgICAgIC8vIHplcm8td2lkdGggbm9kZSBoYXMgYW4gb2Zmc2V0IG9mIDEgc28gd2UgaGF2ZSB0byBjaGVjayBpZiB3ZSBhcmUgaW4gYSB6ZXJvLXdpZHRoIG5vZGUgYW5kXG4gICAgICAgIC8vIGFkanVzdCB0aGUgb2Zmc2V0IGFjY29yZGluZ2x5LlxuICAgICAgICBjb25zdCBzdGFydEVsID0gKGlzRE9NRWxlbWVudChzdGFydE5vZGUpID8gc3RhcnROb2RlIDogc3RhcnROb2RlLnBhcmVudEVsZW1lbnQpIGFzIEhUTUxFbGVtZW50O1xuICAgICAgICBjb25zdCBpc1N0YXJ0QXRaZXJvV2lkdGggPSAhIXN0YXJ0RWwuZ2V0QXR0cmlidXRlKCdkYXRhLXNsYXRlLXplcm8td2lkdGgnKTtcbiAgICAgICAgY29uc3QgZW5kRWwgPSAoaXNET01FbGVtZW50KGVuZE5vZGUpID8gZW5kTm9kZSA6IGVuZE5vZGUucGFyZW50RWxlbWVudCkgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgIGNvbnN0IGlzRW5kQXRaZXJvV2lkdGggPSAhIWVuZEVsLmdldEF0dHJpYnV0ZSgnZGF0YS1zbGF0ZS16ZXJvLXdpZHRoJyk7XG5cbiAgICAgICAgZG9tUmFuZ2Uuc2V0U3RhcnQoc3RhcnROb2RlLCBpc1N0YXJ0QXRaZXJvV2lkdGggPyAxIDogc3RhcnRPZmZzZXQpO1xuICAgICAgICBkb21SYW5nZS5zZXRFbmQoZW5kTm9kZSwgaXNFbmRBdFplcm9XaWR0aCA/IDEgOiBlbmRPZmZzZXQpO1xuICAgICAgICByZXR1cm4gZG9tUmFuZ2U7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEZpbmQgYSBTbGF0ZSBub2RlIGZyb20gYSBuYXRpdmUgRE9NIGBlbGVtZW50YC5cbiAgICAgKi9cblxuICAgIHRvU2xhdGVOb2RlPFQgZXh0ZW5kcyBib29sZWFuPihcbiAgICAgICAgZWRpdG9yOiBBbmd1bGFyRWRpdG9yLFxuICAgICAgICBkb21Ob2RlOiBET01Ob2RlLFxuICAgICAgICBvcHRpb25zPzoge1xuICAgICAgICAgICAgc3VwcHJlc3NUaHJvdzogVDtcbiAgICAgICAgfVxuICAgICk6IFQgZXh0ZW5kcyB0cnVlID8gTm9kZSB8IG51bGwgOiBOb2RlIHtcbiAgICAgICAgY29uc3QgeyBzdXBwcmVzc1Rocm93IH0gPSBvcHRpb25zIHx8IHsgc3VwcHJlc3NUaHJvdzogZmFsc2UgfTtcbiAgICAgICAgbGV0IGRvbUVsID0gaXNET01FbGVtZW50KGRvbU5vZGUpID8gZG9tTm9kZSA6IGRvbU5vZGUucGFyZW50RWxlbWVudDtcblxuICAgICAgICBpZiAoZG9tRWwgJiYgIWRvbUVsLmhhc0F0dHJpYnV0ZSgnZGF0YS1zbGF0ZS1ub2RlJykpIHtcbiAgICAgICAgICAgIGRvbUVsID0gZG9tRWwuY2xvc2VzdChgW2RhdGEtc2xhdGUtbm9kZV1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG5vZGUgPSBkb21FbCA/IEVMRU1FTlRfVE9fTk9ERS5nZXQoZG9tRWwgYXMgSFRNTEVsZW1lbnQpIDogbnVsbDtcblxuICAgICAgICBpZiAoIW5vZGUpIHtcbiAgICAgICAgICAgIGlmIChzdXBwcmVzc1Rocm93KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGwgYXMgVCBleHRlbmRzIHRydWUgPyBOb2RlIHwgbnVsbCA6IE5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXNvbHZlIGEgU2xhdGUgbm9kZSBmcm9tIERPTSBub2RlOiAke2RvbUVsfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgdGFyZ2V0IHJhbmdlIGZyb20gYSBET00gYGV2ZW50YC5cbiAgICAgKi9cblxuICAgIGZpbmRFdmVudFJhbmdlKGVkaXRvcjogQW5ndWxhckVkaXRvciwgZXZlbnQ6IGFueSk6IFJhbmdlIHtcbiAgICAgICAgaWYgKCduYXRpdmVFdmVudCcgaW4gZXZlbnQpIHtcbiAgICAgICAgICAgIGV2ZW50ID0gZXZlbnQubmF0aXZlRXZlbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB7IGNsaWVudFg6IHgsIGNsaWVudFk6IHksIHRhcmdldCB9ID0gZXZlbnQ7XG5cbiAgICAgICAgaWYgKHggPT0gbnVsbCB8fCB5ID09IG51bGwpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlc29sdmUgYSBTbGF0ZSByYW5nZSBmcm9tIGEgRE9NIGV2ZW50OiAke2V2ZW50fWApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgbm9kZSA9IEFuZ3VsYXJFZGl0b3IudG9TbGF0ZU5vZGUoZWRpdG9yLCBldmVudC50YXJnZXQsIHsgc3VwcHJlc3NUaHJvdzogZmFsc2UgfSk7XG4gICAgICAgIGNvbnN0IHBhdGggPSBBbmd1bGFyRWRpdG9yLmZpbmRQYXRoKGVkaXRvciwgbm9kZSk7XG5cbiAgICAgICAgLy8gSWYgdGhlIGRyb3AgdGFyZ2V0IGlzIGluc2lkZSBhIHZvaWQgbm9kZSwgbW92ZSBpdCBpbnRvIGVpdGhlciB0aGVcbiAgICAgICAgLy8gbmV4dCBvciBwcmV2aW91cyBub2RlLCBkZXBlbmRpbmcgb24gd2hpY2ggc2lkZSB0aGUgYHhgIGFuZCBgeWBcbiAgICAgICAgLy8gY29vcmRpbmF0ZXMgYXJlIGNsb3Nlc3QgdG8uXG4gICAgICAgIGlmIChFbGVtZW50LmlzRWxlbWVudChub2RlKSAmJiBFZGl0b3IuaXNWb2lkKGVkaXRvciwgbm9kZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlY3QgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICBjb25zdCBpc1ByZXYgPSBlZGl0b3IuaXNJbmxpbmUobm9kZSkgPyB4IC0gcmVjdC5sZWZ0IDwgcmVjdC5sZWZ0ICsgcmVjdC53aWR0aCAtIHggOiB5IC0gcmVjdC50b3AgPCByZWN0LnRvcCArIHJlY3QuaGVpZ2h0IC0geTtcblxuICAgICAgICAgICAgY29uc3QgZWRnZSA9IEVkaXRvci5wb2ludChlZGl0b3IsIHBhdGgsIHtcbiAgICAgICAgICAgICAgICBlZGdlOiBpc1ByZXYgPyAnc3RhcnQnIDogJ2VuZCdcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29uc3QgcG9pbnQgPSBpc1ByZXYgPyBFZGl0b3IuYmVmb3JlKGVkaXRvciwgZWRnZSkgOiBFZGl0b3IuYWZ0ZXIoZWRpdG9yLCBlZGdlKTtcblxuICAgICAgICAgICAgaWYgKHBvaW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEVkaXRvci5yYW5nZShlZGl0b3IsIHBvaW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEVsc2UgcmVzb2x2ZSBhIHJhbmdlIGZyb20gdGhlIGNhcmV0IHBvc2l0aW9uIHdoZXJlIHRoZSBkcm9wIG9jY3VyZWQuXG4gICAgICAgIGxldCBkb21SYW5nZTogRE9NUmFuZ2U7XG4gICAgICAgIGNvbnN0IHdpbmRvdyA9IEFuZ3VsYXJFZGl0b3IuZ2V0V2luZG93KGVkaXRvcik7XG4gICAgICAgIGNvbnN0IHsgZG9jdW1lbnQgfSA9IHdpbmRvdztcblxuICAgICAgICAvLyBDT01QQVQ6IEluIEZpcmVmb3gsIGBjYXJldFJhbmdlRnJvbVBvaW50YCBkb2Vzbid0IGV4aXN0LiAoMjAxNi8wNy8yNSlcbiAgICAgICAgaWYgKGRvY3VtZW50LmNhcmV0UmFuZ2VGcm9tUG9pbnQpIHtcbiAgICAgICAgICAgIGRvbVJhbmdlID0gZG9jdW1lbnQuY2FyZXRSYW5nZUZyb21Qb2ludCh4LCB5KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uID0gKGRvY3VtZW50IGFzIFNhZmVBbnkpLmNhcmV0UG9zaXRpb25Gcm9tUG9pbnQoeCwgeSk7XG5cbiAgICAgICAgICAgIGlmIChwb3NpdGlvbikge1xuICAgICAgICAgICAgICAgIGRvbVJhbmdlID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgICAgICAgICAgICAgICBkb21SYW5nZS5zZXRTdGFydChwb3NpdGlvbi5vZmZzZXROb2RlLCBwb3NpdGlvbi5vZmZzZXQpO1xuICAgICAgICAgICAgICAgIGRvbVJhbmdlLnNldEVuZChwb3NpdGlvbi5vZmZzZXROb2RlLCBwb3NpdGlvbi5vZmZzZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFkb21SYW5nZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgcmVzb2x2ZSBhIFNsYXRlIHJhbmdlIGZyb20gYSBET00gZXZlbnQ6ICR7ZXZlbnR9YCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXNvbHZlIGEgU2xhdGUgcmFuZ2UgZnJvbSB0aGUgRE9NIHJhbmdlLlxuICAgICAgICBjb25zdCByYW5nZSA9IEFuZ3VsYXJFZGl0b3IudG9TbGF0ZVJhbmdlKGVkaXRvciwgZG9tUmFuZ2UsIHsgc3VwcHJlc3NUaHJvdzogZmFsc2UgfSk7XG4gICAgICAgIHJldHVybiByYW5nZTtcbiAgICB9LFxuXG4gICAgaXNMZWFmSW5FZGl0b3IoXG4gICAgICAgIGVkaXRvcjogQW5ndWxhckVkaXRvcixcbiAgICAgICAgbGVhZk5vZGU6IERPTUVsZW1lbnQsXG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIHN1cHByZXNzVGhyb3c6IGJvb2xlYW47XG4gICAgICAgIH1cbiAgICApOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgeyBzdXBwcmVzc1Rocm93IH0gPSBvcHRpb25zO1xuICAgICAgICBjb25zdCB0ZXh0Tm9kZSA9IGxlYWZOb2RlLmNsb3Nlc3QoJ1tkYXRhLXNsYXRlLW5vZGU9XCJ0ZXh0XCJdJykhO1xuICAgICAgICBjb25zdCBub2RlID0gQW5ndWxhckVkaXRvci50b1NsYXRlTm9kZShlZGl0b3IsIHRleHROb2RlLCB7IHN1cHByZXNzVGhyb3cgfSk7XG4gICAgICAgIGlmIChub2RlICYmIEFuZ3VsYXJFZGl0b3IuaXNOb2RlSW5FZGl0b3IoZWRpdG9yLCBub2RlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRmluZCBhIFNsYXRlIHBvaW50IGZyb20gYSBET00gc2VsZWN0aW9uJ3MgYGRvbU5vZGVgIGFuZCBgZG9tT2Zmc2V0YC5cbiAgICAgKi9cblxuICAgIHRvU2xhdGVQb2ludDxUIGV4dGVuZHMgYm9vbGVhbj4oXG4gICAgICAgIGVkaXRvcjogQW5ndWxhckVkaXRvcixcbiAgICAgICAgZG9tUG9pbnQ6IERPTVBvaW50LFxuICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICBleGFjdE1hdGNoPzogYm9vbGVhbjtcbiAgICAgICAgICAgIHN1cHByZXNzVGhyb3c6IFQ7XG4gICAgICAgIH1cbiAgICApOiBUIGV4dGVuZHMgdHJ1ZSA/IFBvaW50IHwgbnVsbCA6IFBvaW50IHtcbiAgICAgICAgY29uc3QgeyBleGFjdE1hdGNoLCBzdXBwcmVzc1Rocm93IH0gPSBvcHRpb25zO1xuICAgICAgICBjb25zdCBbZG9tTm9kZV0gPSBkb21Qb2ludDtcbiAgICAgICAgY29uc3QgW25lYXJlc3ROb2RlLCBuZWFyZXN0T2Zmc2V0XSA9IG5vcm1hbGl6ZURPTVBvaW50KGRvbVBvaW50KTtcbiAgICAgICAgbGV0IHBhcmVudE5vZGUgPSBuZWFyZXN0Tm9kZS5wYXJlbnROb2RlIGFzIERPTUVsZW1lbnQ7XG4gICAgICAgIGxldCB0ZXh0Tm9kZTogRE9NRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICAgICAgICBsZXQgb2Zmc2V0ID0gMDtcblxuICAgICAgICAvLyBibG9jayBjYXJkXG4gICAgICAgIGNvbnN0IGNhcmRUYXJnZXRBdHRyID0gZ2V0Q2FyZFRhcmdldEF0dHJpYnV0ZShkb21Ob2RlKTtcbiAgICAgICAgaWYgKGNhcmRUYXJnZXRBdHRyKSB7XG4gICAgICAgICAgICBjb25zdCBkb21TZWxlY3Rpb24gPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICAgICAgICBjb25zdCBpc0JhY2t3YXJkID0gZWRpdG9yLnNlbGVjdGlvbiAmJiBSYW5nZS5pc0JhY2t3YXJkKGVkaXRvci5zZWxlY3Rpb24pO1xuICAgICAgICAgICAgY29uc3QgYmxvY2tDYXJkRW50cnkgPSBBbmd1bGFyRWRpdG9yLnRvU2xhdGVDYXJkRW50cnkoZWRpdG9yLCBkb21Ob2RlKSB8fCBBbmd1bGFyRWRpdG9yLnRvU2xhdGVDYXJkRW50cnkoZWRpdG9yLCBuZWFyZXN0Tm9kZSk7XG4gICAgICAgICAgICBjb25zdCBbLCBibG9ja1BhdGhdID0gYmxvY2tDYXJkRW50cnk7XG4gICAgICAgICAgICBpZiAoZG9tU2VsZWN0aW9uLmlzQ29sbGFwc2VkKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzQ2FyZExlZnRCeVRhcmdldEF0dHIoY2FyZFRhcmdldEF0dHIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IHBhdGg6IGJsb2NrUGF0aCwgb2Zmc2V0OiAtMSB9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IHBhdGg6IGJsb2NrUGF0aCwgb2Zmc2V0OiAtMiB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0NhcmRMZWZ0QnlUYXJnZXRBdHRyKGNhcmRUYXJnZXRBdHRyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBFZGl0b3Iuc3RhcnQoZWRpdG9yLCBibG9ja1BhdGgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRWRpdG9yLmVuZChlZGl0b3IsIGJsb2NrUGF0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgY29uc3Qgdm9pZE5vZGUgPSBwYXJlbnROb2RlLmNsb3Nlc3QoJ1tkYXRhLXNsYXRlLXZvaWQ9XCJ0cnVlXCJdJyk7XG4gICAgICAgICAgICBsZXQgbGVhZk5vZGUgPSBwYXJlbnROb2RlLmNsb3Nlc3QoJ1tkYXRhLXNsYXRlLWxlYWZdJyk7XG4gICAgICAgICAgICBsZXQgZG9tTm9kZTogRE9NRWxlbWVudCB8IG51bGwgPSBudWxsO1xuXG4gICAgICAgICAgICAvLyBDYWxjdWxhdGUgaG93IGZhciBpbnRvIHRoZSB0ZXh0IG5vZGUgdGhlIGBuZWFyZXN0Tm9kZWAgaXMsIHNvIHRoYXQgd2VcbiAgICAgICAgICAgIC8vIGNhbiBkZXRlcm1pbmUgd2hhdCB0aGUgb2Zmc2V0IHJlbGF0aXZlIHRvIHRoZSB0ZXh0IG5vZGUgaXMuXG4gICAgICAgICAgICBpZiAobGVhZk5vZGUgJiYgQW5ndWxhckVkaXRvci5pc0xlYWZJbkVkaXRvcihlZGl0b3IsIGxlYWZOb2RlLCB7IHN1cHByZXNzVGhyb3c6IHRydWUgfSkpIHtcbiAgICAgICAgICAgICAgICB0ZXh0Tm9kZSA9IGxlYWZOb2RlLmNsb3Nlc3QoJ1tkYXRhLXNsYXRlLW5vZGU9XCJ0ZXh0XCJdJykhO1xuICAgICAgICAgICAgICAgIGNvbnN0IHdpbmRvdyA9IEFuZ3VsYXJFZGl0b3IuZ2V0V2luZG93KGVkaXRvcik7XG4gICAgICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSB3aW5kb3cuZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgICAgICAgICAgICAgICByYW5nZS5zZXRTdGFydCh0ZXh0Tm9kZSwgMCk7XG4gICAgICAgICAgICAgICAgcmFuZ2Uuc2V0RW5kKG5lYXJlc3ROb2RlLCBuZWFyZXN0T2Zmc2V0KTtcbiAgICAgICAgICAgICAgICBjb25zdCBjb250ZW50cyA9IHJhbmdlLmNsb25lQ29udGVudHMoKTtcbiAgICAgICAgICAgICAgICBjb25zdCByZW1vdmFscyA9IFtcbiAgICAgICAgICAgICAgICAgICAgLi4uQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoY29udGVudHMucXVlcnlTZWxlY3RvckFsbCgnW2RhdGEtc2xhdGUtemVyby13aWR0aF0nKSksXG4gICAgICAgICAgICAgICAgICAgIC4uLkFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGNvbnRlbnRzLnF1ZXJ5U2VsZWN0b3JBbGwoJ1tjb250ZW50ZWRpdGFibGU9ZmFsc2VdJykpXG4gICAgICAgICAgICAgICAgXTtcblxuICAgICAgICAgICAgICAgIHJlbW92YWxzLmZvckVhY2goZWwgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlbCEucGFyZW50Tm9kZSEucmVtb3ZlQ2hpbGQoZWwpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgLy8gQ09NUEFUOiBFZGdlIGhhcyBhIGJ1ZyB3aGVyZSBSYW5nZS5wcm90b3R5cGUudG9TdHJpbmcoKSB3aWxsXG4gICAgICAgICAgICAgICAgLy8gY29udmVydCBcXG4gaW50byBcXHJcXG4uIFRoZSBidWcgY2F1c2VzIGEgbG9vcCB3aGVuIHNsYXRlLXJlYWN0XG4gICAgICAgICAgICAgICAgLy8gYXR0ZW1wdHMgdG8gcmVwb3NpdGlvbiBpdHMgY3Vyc29yIHRvIG1hdGNoIHRoZSBuYXRpdmUgcG9zaXRpb24uIFVzZVxuICAgICAgICAgICAgICAgIC8vIHRleHRDb250ZW50Lmxlbmd0aCBpbnN0ZWFkLlxuICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1pY3Jvc29mdC5jb20vZW4tdXMvbWljcm9zb2Z0LWVkZ2UvcGxhdGZvcm0vaXNzdWVzLzEwMjkxMTE2L1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IGNvbnRlbnRzLnRleHRDb250ZW50IS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZG9tTm9kZSA9IHRleHROb2RlO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh2b2lkTm9kZSkge1xuICAgICAgICAgICAgICAgIC8vIEZvciB2b2lkIG5vZGVzLCB0aGUgZWxlbWVudCB3aXRoIHRoZSBvZmZzZXQga2V5IHdpbGwgYmUgYSBjb3VzaW4sIG5vdCBhblxuICAgICAgICAgICAgICAgIC8vIGFuY2VzdG9yLCBzbyBmaW5kIGl0IGJ5IGdvaW5nIGRvd24gZnJvbSB0aGUgbmVhcmVzdCB2b2lkIHBhcmVudC5cbiAgICAgICAgICAgICAgICBjb25zdCBzcGFjZXIgPSB2b2lkTm9kZS5xdWVyeVNlbGVjdG9yKCdbZGF0YS1zbGF0ZS1zcGFjZXI9XCJ0cnVlXCJdJykhO1xuICAgICAgICAgICAgICAgIGxlYWZOb2RlID0gc3BhY2VyLmZpcnN0RWxlbWVudENoaWxkO1xuICAgICAgICAgICAgICAgIHBhcmVudE5vZGUgPSBsZWFmTm9kZS5maXJzdEVsZW1lbnRDaGlsZDtcbiAgICAgICAgICAgICAgICB0ZXh0Tm9kZSA9IHNwYWNlcjtcbiAgICAgICAgICAgICAgICBkb21Ob2RlID0gbGVhZk5vZGU7XG4gICAgICAgICAgICAgICAgb2Zmc2V0ID0gZG9tTm9kZS50ZXh0Q29udGVudCEubGVuZ3RoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDT01QQVQ6IElmIHRoZSBwYXJlbnQgbm9kZSBpcyBhIFNsYXRlIHplcm8td2lkdGggc3BhY2UsIGVkaXRvciBpc1xuICAgICAgICAgICAgLy8gYmVjYXVzZSB0aGUgdGV4dCBub2RlIHNob3VsZCBoYXZlIG5vIGNoYXJhY3RlcnMuIEhvd2V2ZXIsIGR1cmluZyBJTUVcbiAgICAgICAgICAgIC8vIGNvbXBvc2l0aW9uIHRoZSBBU0NJSSBjaGFyYWN0ZXJzIHdpbGwgYmUgcHJlcGVuZGVkIHRvIHRoZSB6ZXJvLXdpZHRoXG4gICAgICAgICAgICAvLyBzcGFjZSwgc28gc3VidHJhY3QgMSBmcm9tIHRoZSBvZmZzZXQgdG8gYWNjb3VudCBmb3IgdGhlIHplcm8td2lkdGhcbiAgICAgICAgICAgIC8vIHNwYWNlIGNoYXJhY3Rlci5cbiAgICAgICAgICAgIGlmIChkb21Ob2RlICYmIG9mZnNldCA9PT0gZG9tTm9kZS50ZXh0Q29udGVudCEubGVuZ3RoICYmIHBhcmVudE5vZGUgJiYgcGFyZW50Tm9kZS5oYXNBdHRyaWJ1dGUoJ2RhdGEtc2xhdGUtemVyby13aWR0aCcpKSB7XG4gICAgICAgICAgICAgICAgb2Zmc2V0LS07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRleHROb2RlKSB7XG4gICAgICAgICAgICBpZiAoc3VwcHJlc3NUaHJvdykge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsIGFzIFQgZXh0ZW5kcyB0cnVlID8gUG9pbnQgfCBudWxsIDogUG9pbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXNvbHZlIGEgU2xhdGUgcG9pbnQgZnJvbSBET00gcG9pbnQ6ICR7ZG9tUG9pbnR9YCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDT01QQVQ6IElmIHNvbWVvbmUgaXMgY2xpY2tpbmcgZnJvbSBvbmUgU2xhdGUgZWRpdG9yIGludG8gYW5vdGhlcixcbiAgICAgICAgLy8gdGhlIHNlbGVjdCBldmVudCBmaXJlcyB0d2ljZSwgb25jZSBmb3IgdGhlIG9sZCBlZGl0b3IncyBgZWxlbWVudGBcbiAgICAgICAgLy8gZmlyc3QsIGFuZCB0aGVuIGFmdGVyd2FyZHMgZm9yIHRoZSBjb3JyZWN0IGBlbGVtZW50YC4gKDIwMTcvMDMvMDMpXG4gICAgICAgIGNvbnN0IHNsYXRlTm9kZSA9IEFuZ3VsYXJFZGl0b3IudG9TbGF0ZU5vZGUoZWRpdG9yLCB0ZXh0Tm9kZSwgeyBzdXBwcmVzc1Rocm93IH0pO1xuICAgICAgICBpZiAoIXNsYXRlTm9kZSAmJiBzdXBwcmVzc1Rocm93KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbCBhcyBUIGV4dGVuZHMgdHJ1ZSA/IFBvaW50IHwgbnVsbCA6IFBvaW50O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhdGggPSBBbmd1bGFyRWRpdG9yLmZpbmRQYXRoKGVkaXRvciwgc2xhdGVOb2RlKTtcbiAgICAgICAgcmV0dXJuIHsgcGF0aCwgb2Zmc2V0IH07XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEZpbmQgYSBTbGF0ZSByYW5nZSBmcm9tIGEgRE9NIHJhbmdlIG9yIHNlbGVjdGlvbi5cbiAgICAgKi9cblxuICAgIHRvU2xhdGVSYW5nZTxUIGV4dGVuZHMgYm9vbGVhbj4oXG4gICAgICAgIGVkaXRvcjogQW5ndWxhckVkaXRvcixcbiAgICAgICAgZG9tUmFuZ2U6IERPTVJhbmdlIHwgRE9NU3RhdGljUmFuZ2UgfCBET01TZWxlY3Rpb24sXG4gICAgICAgIG9wdGlvbnM/OiB7XG4gICAgICAgICAgICBleGFjdE1hdGNoPzogYm9vbGVhbjtcbiAgICAgICAgICAgIHN1cHByZXNzVGhyb3c6IFQ7XG4gICAgICAgIH1cbiAgICApOiBUIGV4dGVuZHMgdHJ1ZSA/IFJhbmdlIHwgbnVsbCA6IFJhbmdlIHtcbiAgICAgICAgY29uc3QgeyBleGFjdE1hdGNoLCBzdXBwcmVzc1Rocm93IH0gPSBvcHRpb25zIHx8IHt9O1xuICAgICAgICBjb25zdCBlbCA9IGlzRE9NU2VsZWN0aW9uKGRvbVJhbmdlKSA/IGRvbVJhbmdlLmFuY2hvck5vZGUgOiBkb21SYW5nZS5zdGFydENvbnRhaW5lcjtcbiAgICAgICAgbGV0IGFuY2hvck5vZGU7XG4gICAgICAgIGxldCBhbmNob3JPZmZzZXQ7XG4gICAgICAgIGxldCBmb2N1c05vZGU7XG4gICAgICAgIGxldCBmb2N1c09mZnNldDtcbiAgICAgICAgbGV0IGlzQ29sbGFwc2VkO1xuXG4gICAgICAgIGlmIChlbCkge1xuICAgICAgICAgICAgaWYgKGlzRE9NU2VsZWN0aW9uKGRvbVJhbmdlKSkge1xuICAgICAgICAgICAgICAgIGFuY2hvck5vZGUgPSBkb21SYW5nZS5hbmNob3JOb2RlO1xuICAgICAgICAgICAgICAgIGFuY2hvck9mZnNldCA9IGRvbVJhbmdlLmFuY2hvck9mZnNldDtcbiAgICAgICAgICAgICAgICBmb2N1c05vZGUgPSBkb21SYW5nZS5mb2N1c05vZGU7XG4gICAgICAgICAgICAgICAgZm9jdXNPZmZzZXQgPSBkb21SYW5nZS5mb2N1c09mZnNldDtcbiAgICAgICAgICAgICAgICAvLyBDT01QQVQ6IFRoZXJlJ3MgYSBidWcgaW4gY2hyb21lIHRoYXQgYWx3YXlzIHJldHVybnMgYHRydWVgIGZvclxuICAgICAgICAgICAgICAgIC8vIGBpc0NvbGxhcHNlZGAgZm9yIGEgU2VsZWN0aW9uIHRoYXQgY29tZXMgZnJvbSBhIFNoYWRvd1Jvb3QuXG4gICAgICAgICAgICAgICAgLy8gKDIwMjAvMDgvMDgpXG4gICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQ3NTIzXG4gICAgICAgICAgICAgICAgaWYgKElTX0NIUk9NRSAmJiBoYXNTaGFkb3dSb290KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNDb2xsYXBzZWQgPSBkb21SYW5nZS5hbmNob3JOb2RlID09PSBkb21SYW5nZS5mb2N1c05vZGUgJiYgZG9tUmFuZ2UuYW5jaG9yT2Zmc2V0ID09PSBkb21SYW5nZS5mb2N1c09mZnNldDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpc0NvbGxhcHNlZCA9IGRvbVJhbmdlLmlzQ29sbGFwc2VkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYW5jaG9yTm9kZSA9IGRvbVJhbmdlLnN0YXJ0Q29udGFpbmVyO1xuICAgICAgICAgICAgICAgIGFuY2hvck9mZnNldCA9IGRvbVJhbmdlLnN0YXJ0T2Zmc2V0O1xuICAgICAgICAgICAgICAgIGZvY3VzTm9kZSA9IGRvbVJhbmdlLmVuZENvbnRhaW5lcjtcbiAgICAgICAgICAgICAgICBmb2N1c09mZnNldCA9IGRvbVJhbmdlLmVuZE9mZnNldDtcbiAgICAgICAgICAgICAgICBpc0NvbGxhcHNlZCA9IGRvbVJhbmdlLmNvbGxhcHNlZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhbmNob3JOb2RlID09IG51bGwgfHwgZm9jdXNOb2RlID09IG51bGwgfHwgYW5jaG9yT2Zmc2V0ID09IG51bGwgfHwgZm9jdXNPZmZzZXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgcmVzb2x2ZSBhIFNsYXRlIHJhbmdlIGZyb20gRE9NIHJhbmdlOiAke2RvbVJhbmdlfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYW5jaG9yID0gQW5ndWxhckVkaXRvci50b1NsYXRlUG9pbnQoZWRpdG9yLCBbYW5jaG9yTm9kZSwgYW5jaG9yT2Zmc2V0XSwgeyBzdXBwcmVzc1Rocm93LCBleGFjdE1hdGNoIH0pO1xuICAgICAgICBpZiAoIWFuY2hvcikge1xuICAgICAgICAgICAgcmV0dXJuIG51bGwgYXMgVCBleHRlbmRzIHRydWUgPyBSYW5nZSB8IG51bGwgOiBSYW5nZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZvY3VzID0gaXNDb2xsYXBzZWQgPyBhbmNob3IgOiBBbmd1bGFyRWRpdG9yLnRvU2xhdGVQb2ludChlZGl0b3IsIFtmb2N1c05vZGUsIGZvY3VzT2Zmc2V0XSwgeyBzdXBwcmVzc1Rocm93LCBleGFjdE1hdGNoIH0pO1xuICAgICAgICBpZiAoIWZvY3VzKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbCBhcyBUIGV4dGVuZHMgdHJ1ZSA/IFJhbmdlIHwgbnVsbCA6IFJhbmdlO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJhbmdlOiBSYW5nZSA9IHsgYW5jaG9yOiBhbmNob3IgYXMgUG9pbnQsIGZvY3VzOiBmb2N1cyBhcyBQb2ludCB9O1xuICAgICAgICAvLyBpZiB0aGUgc2VsZWN0aW9uIGlzIGEgaGFuZ2luZyByYW5nZSB0aGF0IGVuZHMgaW4gYSB2b2lkXG4gICAgICAgIC8vIGFuZCB0aGUgRE9NIGZvY3VzIGlzIGFuIEVsZW1lbnRcbiAgICAgICAgLy8gKG1lYW5pbmcgdGhhdCB0aGUgc2VsZWN0aW9uIGVuZHMgYmVmb3JlIHRoZSBlbGVtZW50KVxuICAgICAgICAvLyB1bmhhbmcgdGhlIHJhbmdlIHRvIGF2b2lkIG1pc3Rha2VubHkgaW5jbHVkaW5nIHRoZSB2b2lkXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIFJhbmdlLmlzRXhwYW5kZWQocmFuZ2UpICYmXG4gICAgICAgICAgICBSYW5nZS5pc0ZvcndhcmQocmFuZ2UpICYmXG4gICAgICAgICAgICBpc0RPTUVsZW1lbnQoZm9jdXNOb2RlKSAmJlxuICAgICAgICAgICAgRWRpdG9yLnZvaWQoZWRpdG9yLCB7IGF0OiByYW5nZS5mb2N1cywgbW9kZTogJ2hpZ2hlc3QnIH0pXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmFuZ2UgPSBFZGl0b3IudW5oYW5nUmFuZ2UoZWRpdG9yLCByYW5nZSwgeyB2b2lkczogdHJ1ZSB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByYW5nZTtcbiAgICB9LFxuXG4gICAgaXNMZWFmQmxvY2soZWRpdG9yOiBBbmd1bGFyRWRpdG9yLCBub2RlOiBOb2RlKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBFbGVtZW50LmlzRWxlbWVudChub2RlKSAmJiAhZWRpdG9yLmlzSW5saW5lKG5vZGUpICYmIEVkaXRvci5oYXNJbmxpbmVzKGVkaXRvciwgbm9kZSk7XG4gICAgfSxcblxuICAgIGlzQmxvY2tDYXJkTGVmdEN1cnNvcihlZGl0b3I6IEFuZ3VsYXJFZGl0b3IpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGVkaXRvci5zZWxlY3Rpb24/LmFuY2hvcj8ub2Zmc2V0ID09PSBGQUtFX0xFRlRfQkxPQ0tfQ0FSRF9PRkZTRVQgJiZcbiAgICAgICAgICAgIGVkaXRvci5zZWxlY3Rpb24/LmZvY3VzPy5vZmZzZXQgPT09IEZBS0VfTEVGVF9CTE9DS19DQVJEX09GRlNFVFxuICAgICAgICApO1xuICAgIH0sXG5cbiAgICBpc0Jsb2NrQ2FyZFJpZ2h0Q3Vyc29yKGVkaXRvcjogQW5ndWxhckVkaXRvcikge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgZWRpdG9yLnNlbGVjdGlvbj8uYW5jaG9yPy5vZmZzZXQgPT09IEZBS0VfUklHSFRfQkxPQ0tfQ0FSRF9PRkZTRVQgJiZcbiAgICAgICAgICAgIGVkaXRvci5zZWxlY3Rpb24/LmZvY3VzPy5vZmZzZXQgPT09IEZBS0VfUklHSFRfQkxPQ0tfQ0FSRF9PRkZTRVRcbiAgICAgICAgKTtcbiAgICB9LFxuXG4gICAgZ2V0Q2FyZEN1cnNvck5vZGUoXG4gICAgICAgIGVkaXRvcjogQW5ndWxhckVkaXRvcixcbiAgICAgICAgYmxvY2tDYXJkTm9kZTogTm9kZSxcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgZGlyZWN0aW9uOiAnbGVmdCcgfCAncmlnaHQnIHwgJ2NlbnRlcic7XG4gICAgICAgIH1cbiAgICApIHtcbiAgICAgICAgY29uc3QgYmxvY2tDYXJkRWxlbWVudCA9IEFuZ3VsYXJFZGl0b3IudG9ET01Ob2RlKGVkaXRvciwgYmxvY2tDYXJkTm9kZSk7XG4gICAgICAgIGNvbnN0IGNhcmRDZW50ZXIgPSBibG9ja0NhcmRFbGVtZW50LnBhcmVudEVsZW1lbnQ7XG4gICAgICAgIHJldHVybiBvcHRpb25zLmRpcmVjdGlvbiA9PT0gJ2xlZnQnID8gY2FyZENlbnRlci5wcmV2aW91c0VsZW1lbnRTaWJsaW5nLmZpcnN0Q2hpbGQgOiBjYXJkQ2VudGVyLm5leHRFbGVtZW50U2libGluZy5maXJzdENoaWxkO1xuICAgIH0sXG5cbiAgICB0b1NsYXRlQ2FyZEVudHJ5KGVkaXRvcjogQW5ndWxhckVkaXRvciwgbm9kZTogRE9NTm9kZSk6IE5vZGVFbnRyeSB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSBub2RlLnBhcmVudEVsZW1lbnQuY2xvc2VzdCgnLnNsYXRlLWJsb2NrLWNhcmQnKT8ucXVlcnlTZWxlY3RvcignW2NhcmQtdGFyZ2V0PVwiY2FyZC1jZW50ZXJcIl0nKS5maXJzdEVsZW1lbnRDaGlsZDtcbiAgICAgICAgY29uc3Qgc2xhdGVOb2RlID0gQW5ndWxhckVkaXRvci50b1NsYXRlTm9kZShlZGl0b3IsIGVsZW1lbnQsIHsgc3VwcHJlc3NUaHJvdzogZmFsc2UgfSk7XG4gICAgICAgIGNvbnN0IHBhdGggPSBBbmd1bGFyRWRpdG9yLmZpbmRQYXRoKGVkaXRvciwgc2xhdGVOb2RlKTtcbiAgICAgICAgcmV0dXJuIFtzbGF0ZU5vZGUsIHBhdGhdO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBtb3ZlIG5hdGl2ZSBzZWxlY3Rpb24gdG8gY2FyZC1sZWZ0IG9yIGNhcmQtcmlnaHRcbiAgICAgKiBAcGFyYW0gZWRpdG9yXG4gICAgICogQHBhcmFtIGJsb2NrQ2FyZE5vZGVcbiAgICAgKiBAcGFyYW0gb3B0aW9uc1xuICAgICAqL1xuICAgIG1vdmVCbG9ja0NhcmQoXG4gICAgICAgIGVkaXRvcjogQW5ndWxhckVkaXRvcixcbiAgICAgICAgYmxvY2tDYXJkTm9kZTogTm9kZSxcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgZGlyZWN0aW9uOiAnbGVmdCcgfCAncmlnaHQnO1xuICAgICAgICB9XG4gICAgKSB7XG4gICAgICAgIGNvbnN0IGN1cnNvck5vZGUgPSBBbmd1bGFyRWRpdG9yLmdldENhcmRDdXJzb3JOb2RlKGVkaXRvciwgYmxvY2tDYXJkTm9kZSwgb3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IHdpbmRvdyA9IEFuZ3VsYXJFZGl0b3IuZ2V0V2luZG93KGVkaXRvcik7XG4gICAgICAgIGNvbnN0IGRvbVNlbGVjdGlvbiA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgZG9tU2VsZWN0aW9uLnNldEJhc2VBbmRFeHRlbnQoY3Vyc29yTm9kZSwgMSwgY3Vyc29yTm9kZSwgMSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIG1vdmUgc2xhdGUgc2VsZWN0aW9uIHRvIGNhcmQtbGVmdCBvciBjYXJkLXJpZ2h0XG4gICAgICogQHBhcmFtIGVkaXRvclxuICAgICAqIEBwYXJhbSBwYXRoXG4gICAgICogQHBhcmFtIG9wdGlvbnNcbiAgICAgKi9cbiAgICBtb3ZlQmxvY2tDYXJkQ3Vyc29yKFxuICAgICAgICBlZGl0b3I6IEFuZ3VsYXJFZGl0b3IsXG4gICAgICAgIHBhdGg6IFBhdGgsXG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIGRpcmVjdGlvbjogJ2xlZnQnIHwgJ3JpZ2h0JztcbiAgICAgICAgfVxuICAgICkge1xuICAgICAgICBjb25zdCBjdXJzb3IgPSB7XG4gICAgICAgICAgICBwYXRoLFxuICAgICAgICAgICAgb2Zmc2V0OiBvcHRpb25zLmRpcmVjdGlvbiA9PT0gJ2xlZnQnID8gRkFLRV9MRUZUX0JMT0NLX0NBUkRfT0ZGU0VUIDogRkFLRV9SSUdIVF9CTE9DS19DQVJEX09GRlNFVFxuICAgICAgICB9O1xuICAgICAgICBUcmFuc2Zvcm1zLnNlbGVjdChlZGl0b3IsIHsgYW5jaG9yOiBjdXJzb3IsIGZvY3VzOiBjdXJzb3IgfSk7XG4gICAgfSxcblxuICAgIGhhc1JhbmdlKGVkaXRvcjogQW5ndWxhckVkaXRvciwgcmFuZ2U6IFJhbmdlKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IHsgYW5jaG9yLCBmb2N1cyB9ID0gcmFuZ2U7XG4gICAgICAgIHJldHVybiBFZGl0b3IuaGFzUGF0aChlZGl0b3IsIGFuY2hvci5wYXRoKSAmJiBFZGl0b3IuaGFzUGF0aChlZGl0b3IsIGZvY3VzLnBhdGgpO1xuICAgIH1cbn07XG4iXX0=
|