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