-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathArtistry.js
204 lines (204 loc) · 25.5 KB
/
Artistry.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
"use strict";
/**
*
*/
const globalSettings = {
spacesPerTab: 6,
spaceWidth: 0
};
/**
*
*/
const cssClasses = {
container: "view-lines",
line: "view-line",
comment: "mtk1"
};
/**
*
*/
function initialize() {
// We need to wait for the editor to initialize. There doesn't appear
// to be a callback for this, so we're just polling every 10ms to see
// if it's safe to proceed.
const viewLines = document.getElementsByClassName(cssClasses.container);
if (viewLines.length === 0)
return void setTimeout(() => initialize(), 10);
console.log("ARTISTRY: Initializing...");
globalSettings.spaceWidth = calculateSpaceWidth();
for (let i = -1; ++i < viewLines.length;) {
const el = viewLines[i];
if (el instanceof HTMLElement)
maybeConvertLine(el);
}
setTimeout(() => {
console.log("ARTISTRY: Initialized");
document.addEventListener("animationstart", evt => {
if (evt.animationName === "view-line-inserted") {
if (evt.target instanceof HTMLElement) {
maybeConvertLine(evt.target);
clearClosingCommentQueue();
}
}
});
});
}
/**
* Computes the width of one space, in em units.
*/
function calculateSpaceWidth() {
const viewLines = document.getElementsByClassName(cssClasses.container)[0];
const testLine = document.createElement("div");
testLine.style.top = "5000px";
testLine.style.height = "30px";
testLine.classList.add(cssClasses.line, "test-line");
testLine.style.pointerEvents = "none";
testLine.innerHTML = `
<span>
<span class="${cssClasses.comment}"> </span>
</span>`;
viewLines.append(testLine);
const span = testLine.getElementsByClassName("mtk1")[0];
const width = span.getBoundingClientRect().width;
viewLines.removeChild(testLine);
return width;
}
/**
*
*/
function maybeConvertLine(viewLine) {
const lineInfo = classifyLine(viewLine);
if (!lineInfo.isBlockCommentStart &&
!lineInfo.isBlockCommentMid &&
!lineInfo.isBlockCommentEnd &&
!lineInfo.isLineComment &&
!lineInfo.isDeadComment &&
!lineInfo.isAttentionComment &&
!lineInfo.isSectionComment)
return;
viewLine.setAttribute("data-comment", "");
let pxAdjust = globalSettings.spaceWidth * lineInfo.nbspCount;
if (lineInfo.isBlockCommentEnd || lineInfo.isBlockCommentMid)
pxAdjust -= globalSettings.spaceWidth;
viewLine.style.backgroundPositionX = pxAdjust + "px";
if (lineInfo.isBlockCommentStart ||
lineInfo.isBlockCommentMid ||
lineInfo.isBlockCommentEnd)
viewLine.setAttribute("data-block-comment", "");
if (lineInfo.isSectionComment)
viewLine.setAttribute("data-section-comment", "");
if (lineInfo.isLineComment)
viewLine.setAttribute("data-line-comment", "");
if (lineInfo.isDeadComment)
viewLine.setAttribute("data-dead-comment", "");
if (lineInfo.isAttentionComment)
viewLine.setAttribute("data-attention-comment", "");
}
/**
*
*/
function classifyLine(viewLine) {
const getMetrics = (viewLine) => {
const text = viewLine.textContent || "";
const trim = text.trim();
const trimLeft = text.trimLeft();
const nbspCount = text.length - trimLeft.length;
const tabCount = Math.floor(nbspCount / globalSettings.spacesPerTab);
const spaceCount = nbspCount % globalSettings.spacesPerTab;
return { trim, trimLeft, nbspCount, tabCount, spaceCount };
};
const getIsBlockCommentMid = (viewLine) => {
if (!(viewLine instanceof HTMLElement))
return false;
const m = getMetrics(viewLine);
return m.nbspCount > 0 &&
(m.trim === "*" || m.trimLeft.startsWith("* ") || m.trimLeft.startsWith("*" + s));
};
const m = getMetrics(viewLine);
const s = String.fromCodePoint(160);
const isBlockCommentStart = m.trim.startsWith("/**");
const isBlockCommentMid = getIsBlockCommentMid(viewLine);
const isBlockCommentEnd = (() => {
if (m.trim !== "*/")
return false;
const previousLine = findPreviousLine(viewLine);
if (!previousLine) {
closingCommentQueue.push(viewLine);
return false;
}
return m.trim === "*/" &&
getIsBlockCommentMid(previousLine);
})();
const isLineComment = m.trim === "//" ||
m.trimLeft.startsWith("// ") ||
m.trimLeft.startsWith("//" + s);
const isDeadComment = m.trimLeft.startsWith("///") &&
!m.trimLeft.startsWith("/// <reference ");
const isAttentionComment = m.trim === "//!" ||
m.trimLeft.startsWith("//! ") ||
m.trimLeft.startsWith("//!" + s) ||
m.trimLeft.startsWith(`//${s}eslint-disable-next-line` + s) ||
m.trimLeft.startsWith(`/*${s}eslint` + s);
const isSectionComment = m.trim === "//#" || m.trim.startsWith("//#" + s) || m.trim.startsWith("//# ");
return {
isBlockCommentStart,
isBlockCommentMid,
isBlockCommentEnd,
isLineComment,
isDeadComment,
isAttentionComment,
isSectionComment,
tabCount: m.tabCount,
spaceCount: m.spaceCount,
nbspCount: m.nbspCount
};
}
/**
* Finds the element that represents the previous line in the document.
* Note that this isn't as simple as a call to previousElementSibling,
* because the Monaco editor in VS Code does not necessarily order
* the underlying elements in document-order.
*/
function findPreviousLine(viewLine) {
const refTop = parseInt(viewLine.style.top || "", 10) || 0;
const lineHeight = parseInt(viewLine.style.height || "") || 30;
const target = refTop - lineHeight + "px";
// In most cases, the previous element is actually the one we're
// looking for, so it can be returned efficiently.
if (viewLine.previousElementSibling instanceof HTMLElement)
if (viewLine.previousElementSibling.style.top === target)
return viewLine.previousElementSibling;
// Otherwise, we need to search all lines.
const container = viewLine.parentElement;
if (!(container instanceof HTMLElement))
return null;
for (let i = container.childElementCount; i-- > 0;) {
const item = container.children.item(i);
if (item instanceof HTMLElement) {
if (item.style.top === target)
return item;
}
}
return null;
}
/**
* The coloring of closing block comments is dependent on
* the previous line. However, the previous line may not actually
* be rendered in the document. Therefore, the element is added
* to a queue, which we attempt to clear out when the next line
* is fed into the view (which is when the document is scrolled).
*/
function clearClosingCommentQueue() {
for (let i = closingCommentQueue.length; i-- > 0;) {
const viewLine = closingCommentQueue[i];
const hasPrevious = findPreviousLine(viewLine);
if (hasPrevious) {
closingCommentQueue.splice(i, 1);
maybeConvertLine(viewLine);
}
}
}
/** */
const closingCommentQueue = [];
setTimeout(() => initialize());
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXJ0aXN0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJBcnRpc3RyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQ0E7O0dBRUc7QUFDSCxNQUFNLGNBQWMsR0FBRztJQUN0QixZQUFZLEVBQUUsQ0FBQztJQUNmLFVBQVUsRUFBRSxDQUFDO0NBQ2IsQ0FBQztBQUVGOztHQUVHO0FBQ0gsTUFBTSxVQUFVLEdBQUc7SUFDbEIsU0FBUyxFQUFFLFlBQVk7SUFDdkIsSUFBSSxFQUFFLFdBQVc7SUFDakIsT0FBTyxFQUFFLE1BQU07Q0FDZixDQUFDO0FBRUY7O0dBRUc7QUFDSCxTQUFTLFVBQVU7SUFFbEIscUVBQXFFO0lBQ3JFLHFFQUFxRTtJQUNyRSwyQkFBMkI7SUFDM0IsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLHNCQUFzQixDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN4RSxJQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUN6QixPQUFPLEtBQUssVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLFVBQVUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRWhELE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLENBQUMsQ0FBQztJQUN6QyxjQUFjLENBQUMsVUFBVSxHQUFHLG1CQUFtQixFQUFFLENBQUM7SUFFbEQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxHQUN2QztRQUNDLE1BQU0sRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4QixJQUFJLEVBQUUsWUFBWSxXQUFXO1lBQzVCLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxDQUFDO0tBQ3RCO0lBRUQsVUFBVSxDQUFDLEdBQUcsRUFBRTtRQUVmLE9BQU8sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLENBQUMsQ0FBQztRQUVyQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLEVBQUU7WUFFakQsSUFBSSxHQUFHLENBQUMsYUFBYSxLQUFLLG9CQUFvQixFQUM5QztnQkFDQyxJQUFJLEdBQUcsQ0FBQyxNQUFNLFlBQVksV0FBVyxFQUNyQztvQkFDQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7b0JBQzdCLHdCQUF3QixFQUFFLENBQUM7aUJBQzNCO2FBQ0Q7UUFDRixDQUFDLENBQUMsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxtQkFBbUI7SUFFM0IsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLHNCQUFzQixDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUUzRSxNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQy9DLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLFFBQVEsQ0FBQztJQUM5QixRQUFRLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7SUFDL0IsUUFBUSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQztJQUNyRCxRQUFRLENBQUMsS0FBSyxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUM7SUFDdEMsUUFBUSxDQUFDLFNBQVMsR0FBRzs7a0JBRUosVUFBVSxDQUFDLE9BQU87VUFDMUIsQ0FBQztJQUVWLFNBQVMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFM0IsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLEtBQUssQ0FBQztJQUNqRCxTQUFTLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRWhDLE9BQU8sS0FBSyxDQUFDO0FBQ2QsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxnQkFBZ0IsQ0FBQyxRQUFxQjtJQUU5QyxNQUFNLFFBQVEsR0FBRyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFeEMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUI7UUFDaEMsQ0FBQyxRQUFRLENBQUMsaUJBQWlCO1FBQzNCLENBQUMsUUFBUSxDQUFDLGlCQUFpQjtRQUMzQixDQUFDLFFBQVEsQ0FBQyxhQUFhO1FBQ3ZCLENBQUMsUUFBUSxDQUFDLGFBQWE7UUFDdkIsQ0FBQyxRQUFRLENBQUMsa0JBQWtCO1FBQzVCLENBQUMsUUFBUSxDQUFDLGdCQUFnQjtRQUMxQixPQUFPO0lBRVIsUUFBUSxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFMUMsSUFBSSxRQUFRLEdBQUcsY0FBYyxDQUFDLFVBQVUsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDO0lBQzlELElBQUksUUFBUSxDQUFDLGlCQUFpQixJQUFJLFFBQVEsQ0FBQyxpQkFBaUI7UUFDM0QsUUFBUSxJQUFJLGNBQWMsQ0FBQyxVQUFVLENBQUM7SUFFdkMsUUFBUSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsR0FBRyxRQUFRLEdBQUcsSUFBSSxDQUFDO0lBRXJELElBQUksUUFBUSxDQUFDLG1CQUFtQjtRQUMvQixRQUFRLENBQUMsaUJBQWlCO1FBQzFCLFFBQVEsQ0FBQyxpQkFBaUI7UUFDMUIsUUFBUSxDQUFDLFlBQVksQ0FBQyxvQkFBb0IsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUVqRCxJQUFJLFFBQVEsQ0FBQyxnQkFBZ0I7UUFDNUIsUUFBUSxDQUFDLFlBQVksQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUVuRCxJQUFJLFFBQVEsQ0FBQyxhQUFhO1FBQ3pCLFFBQVEsQ0FBQyxZQUFZLENBQUMsbUJBQW1CLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFaEQsSUFBSSxRQUFRLENBQUMsYUFBYTtRQUN6QixRQUFRLENBQUMsWUFBWSxDQUFDLG1CQUFtQixFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRWhELElBQUksUUFBUSxDQUFDLGtCQUFrQjtRQUM5QixRQUFRLENBQUMsWUFBWSxDQUFDLHdCQUF3QixFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ3RELENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsWUFBWSxDQUFDLFFBQXFCO0lBRTFDLE1BQU0sVUFBVSxHQUFHLENBQUMsUUFBcUIsRUFBRSxFQUFFO1FBRTVDLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxXQUFXLElBQUksRUFBRSxDQUFDO1FBQ3hDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN6QixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDakMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE1BQU0sR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDO1FBQ2hELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLGNBQWMsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNyRSxNQUFNLFVBQVUsR0FBRyxTQUFTLEdBQUcsY0FBYyxDQUFDLFlBQVksQ0FBQztRQUUzRCxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxDQUFDO0lBQzVELENBQUMsQ0FBQTtJQUVELE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxRQUF3QixFQUFFLEVBQUU7UUFFekQsSUFBSSxDQUFDLENBQUMsUUFBUSxZQUFZLFdBQVcsQ0FBQztZQUNyQyxPQUFPLEtBQUssQ0FBQztRQUVkLE1BQU0sQ0FBQyxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUUvQixPQUFPLENBQUMsQ0FBQyxTQUFTLEdBQUcsQ0FBQztZQUNyQixDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BGLENBQUMsQ0FBQTtJQUVELE1BQU0sQ0FBQyxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMvQixNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRXBDLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDckQsTUFBTSxpQkFBaUIsR0FBRyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUV6RCxNQUFNLGlCQUFpQixHQUFHLENBQUMsR0FBRyxFQUFFO1FBRS9CLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJO1lBQ2xCLE9BQU8sS0FBSyxDQUFDO1FBRWQsTUFBTSxZQUFZLEdBQUcsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLFlBQVksRUFDakI7WUFDQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDbkMsT0FBTyxLQUFLLENBQUM7U0FDYjtRQUVELE9BQU8sQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJO1lBQ3JCLG9CQUFvQixDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ3JDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFFTCxNQUFNLGFBQWEsR0FDbEIsQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJO1FBQ2YsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDO1FBQzVCLENBQUMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQztJQUVqQyxNQUFNLGFBQWEsR0FDbEIsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDO1FBQzVCLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUUzQyxNQUFNLGtCQUFrQixHQUN2QixDQUFDLENBQUMsSUFBSSxLQUFLLEtBQUs7UUFDaEIsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDO1FBQzdCLENBQUMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUM7UUFDaEMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLDBCQUEwQixHQUFHLENBQUMsQ0FBQztRQUMzRCxDQUFDLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBRTNDLE1BQU0sZ0JBQWdCLEdBQ3JCLENBQUMsQ0FBQyxJQUFJLEtBQUssS0FBSyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUUvRSxPQUFPO1FBQ04sbUJBQW1CO1FBQ25CLGlCQUFpQjtRQUNqQixpQkFBaUI7UUFDakIsYUFBYTtRQUNiLGFBQWE7UUFDYixrQkFBa0I7UUFDbEIsZ0JBQWdCO1FBQ2hCLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUTtRQUNwQixVQUFVLEVBQUUsQ0FBQyxDQUFDLFVBQVU7UUFDeEIsU0FBUyxFQUFFLENBQUMsQ0FBQyxTQUFTO0tBQ3RCLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLGdCQUFnQixDQUFDLFFBQXFCO0lBRTlDLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzNELE1BQU0sVUFBVSxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDL0QsTUFBTSxNQUFNLEdBQUcsTUFBTSxHQUFHLFVBQVUsR0FBRyxJQUFJLENBQUM7SUFFMUMsZ0VBQWdFO0lBQ2hFLGtEQUFrRDtJQUNsRCxJQUFJLFFBQVEsQ0FBQyxzQkFBc0IsWUFBWSxXQUFXO1FBQ3pELElBQUksUUFBUSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxHQUFHLEtBQUssTUFBTTtZQUN2RCxPQUFPLFFBQVEsQ0FBQyxzQkFBc0IsQ0FBQztJQUV6QywwQ0FBMEM7SUFDMUMsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQztJQUN6QyxJQUFJLENBQUMsQ0FBQyxTQUFTLFlBQVksV0FBVyxDQUFDO1FBQ3RDLE9BQU8sSUFBSSxDQUFDO0lBRWIsS0FBSyxJQUFJLENBQUMsR0FBRyxTQUFTLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxHQUNqRDtRQUNDLE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3hDLElBQUksSUFBSSxZQUFZLFdBQVcsRUFDL0I7WUFDQyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLE1BQU07Z0JBQzVCLE9BQU8sSUFBSSxDQUFDO1NBQ2I7S0FDRDtJQUVELE9BQU8sSUFBSSxDQUFDO0FBQ2IsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQVMsd0JBQXdCO0lBRWhDLEtBQUssSUFBSSxDQUFDLEdBQUcsbUJBQW1CLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxHQUFHLENBQUMsR0FDaEQ7UUFDQyxNQUFNLFFBQVEsR0FBRyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4QyxNQUFNLFdBQVcsR0FBRyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMvQyxJQUFJLFdBQVcsRUFDZjtZQUNDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDakMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDM0I7S0FDRDtBQUNGLENBQUM7QUFFRCxNQUFNO0FBQ04sTUFBTSxtQkFBbUIsR0FBa0IsRUFBRSxDQUFDO0FBWTlDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiXG4vKipcbiAqIFxuICovXG5jb25zdCBnbG9iYWxTZXR0aW5ncyA9IHtcblx0c3BhY2VzUGVyVGFiOiA2LFxuXHRzcGFjZVdpZHRoOiAwXG59O1xuXG4vKipcbiAqIFxuICovXG5jb25zdCBjc3NDbGFzc2VzID0ge1xuXHRjb250YWluZXI6IFwidmlldy1saW5lc1wiLFxuXHRsaW5lOiBcInZpZXctbGluZVwiLFxuXHRjb21tZW50OiBcIm10azFcIlxufTtcblxuLyoqXG4gKiBcbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZSgpXG57XG5cdC8vIFdlIG5lZWQgdG8gd2FpdCBmb3IgdGhlIGVkaXRvciB0byBpbml0aWFsaXplLiBUaGVyZSBkb2Vzbid0IGFwcGVhclxuXHQvLyB0byBiZSBhIGNhbGxiYWNrIGZvciB0aGlzLCBzbyB3ZSdyZSBqdXN0IHBvbGxpbmcgZXZlcnkgMTBtcyB0byBzZWVcblx0Ly8gaWYgaXQncyBzYWZlIHRvIHByb2NlZWQuXG5cdGNvbnN0IHZpZXdMaW5lcyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoY3NzQ2xhc3Nlcy5jb250YWluZXIpO1xuXHRpZiAodmlld0xpbmVzLmxlbmd0aCA9PT0gMClcblx0XHRyZXR1cm4gdm9pZCBzZXRUaW1lb3V0KCgpID0+IGluaXRpYWxpemUoKSwgMTApO1xuXHRcdFxuXHRjb25zb2xlLmxvZyhcIkFSVElTVFJZOiBJbml0aWFsaXppbmcuLi5cIik7XG5cdGdsb2JhbFNldHRpbmdzLnNwYWNlV2lkdGggPSBjYWxjdWxhdGVTcGFjZVdpZHRoKCk7XG5cdFxuXHRmb3IgKGxldCBpID0gLTE7ICsraSA8IHZpZXdMaW5lcy5sZW5ndGg7KVxuXHR7XG5cdFx0Y29uc3QgZWwgPSB2aWV3TGluZXNbaV07XG5cdFx0aWYgKGVsIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpXG5cdFx0XHRtYXliZUNvbnZlcnRMaW5lKGVsKTtcblx0fVxuXHRcblx0c2V0VGltZW91dCgoKSA9PlxuXHR7XG5cdFx0Y29uc29sZS5sb2coXCJBUlRJU1RSWTogSW5pdGlhbGl6ZWRcIik7XG5cdFx0XG5cdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcImFuaW1hdGlvbnN0YXJ0XCIsIGV2dCA9PlxuXHRcdHtcblx0XHRcdGlmIChldnQuYW5pbWF0aW9uTmFtZSA9PT0gXCJ2aWV3LWxpbmUtaW5zZXJ0ZWRcIilcblx0XHRcdHtcblx0XHRcdFx0aWYgKGV2dC50YXJnZXQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdG1heWJlQ29udmVydExpbmUoZXZ0LnRhcmdldCk7XG5cdFx0XHRcdFx0Y2xlYXJDbG9zaW5nQ29tbWVudFF1ZXVlKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG59XG5cbi8qKlxuICogQ29tcHV0ZXMgdGhlIHdpZHRoIG9mIG9uZSBzcGFjZSwgaW4gZW0gdW5pdHMuXG4gKi9cbmZ1bmN0aW9uIGNhbGN1bGF0ZVNwYWNlV2lkdGgoKVxue1xuXHRjb25zdCB2aWV3TGluZXMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGNzc0NsYXNzZXMuY29udGFpbmVyKVswXTtcblx0XG5cdGNvbnN0IHRlc3RMaW5lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcblx0dGVzdExpbmUuc3R5bGUudG9wID0gXCI1MDAwcHhcIjtcblx0dGVzdExpbmUuc3R5bGUuaGVpZ2h0ID0gXCIzMHB4XCI7XG5cdHRlc3RMaW5lLmNsYXNzTGlzdC5hZGQoY3NzQ2xhc3Nlcy5saW5lLCBcInRlc3QtbGluZVwiKTtcblx0dGVzdExpbmUuc3R5bGUucG9pbnRlckV2ZW50cyA9IFwibm9uZVwiO1xuXHR0ZXN0TGluZS5pbm5lckhUTUwgPSBgXG5cdFx0PHNwYW4+XG5cdFx0XHQ8c3BhbiBjbGFzcz1cIiR7Y3NzQ2xhc3Nlcy5jb21tZW50fVwiPiZuYnNwOzwvc3Bhbj5cblx0XHQ8L3NwYW4+YDtcblx0XG5cdHZpZXdMaW5lcy5hcHBlbmQodGVzdExpbmUpO1xuXHRcblx0Y29uc3Qgc3BhbiA9IHRlc3RMaW5lLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJtdGsxXCIpWzBdO1xuXHRjb25zdCB3aWR0aCA9IHNwYW4uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGg7XG5cdHZpZXdMaW5lcy5yZW1vdmVDaGlsZCh0ZXN0TGluZSk7XG5cdFxuXHRyZXR1cm4gd2lkdGg7XG59XG5cbi8qKlxuICogXG4gKi9cbmZ1bmN0aW9uIG1heWJlQ29udmVydExpbmUodmlld0xpbmU6IEhUTUxFbGVtZW50KVxue1xuXHRjb25zdCBsaW5lSW5mbyA9IGNsYXNzaWZ5TGluZSh2aWV3TGluZSk7XG5cdFxuXHRpZiAoIWxpbmVJbmZvLmlzQmxvY2tDb21tZW50U3RhcnQgJiZcblx0XHQhbGluZUluZm8uaXNCbG9ja0NvbW1lbnRNaWQgJiZcblx0XHQhbGluZUluZm8uaXNCbG9ja0NvbW1lbnRFbmQgJiZcblx0XHQhbGluZUluZm8uaXNMaW5lQ29tbWVudCAmJlxuXHRcdCFsaW5lSW5mby5pc0RlYWRDb21tZW50ICYmXG5cdFx0IWxpbmVJbmZvLmlzQXR0ZW50aW9uQ29tbWVudCAmJlxuXHRcdCFsaW5lSW5mby5pc1NlY3Rpb25Db21tZW50KVxuXHRcdHJldHVybjtcblx0XG5cdHZpZXdMaW5lLnNldEF0dHJpYnV0ZShcImRhdGEtY29tbWVudFwiLCBcIlwiKTtcblx0XG5cdGxldCBweEFkanVzdCA9IGdsb2JhbFNldHRpbmdzLnNwYWNlV2lkdGggKiBsaW5lSW5mby5uYnNwQ291bnQ7XG5cdGlmIChsaW5lSW5mby5pc0Jsb2NrQ29tbWVudEVuZCB8fCBsaW5lSW5mby5pc0Jsb2NrQ29tbWVudE1pZClcblx0XHRweEFkanVzdCAtPSBnbG9iYWxTZXR0aW5ncy5zcGFjZVdpZHRoO1xuXHRcblx0dmlld0xpbmUuc3R5bGUuYmFja2dyb3VuZFBvc2l0aW9uWCA9IHB4QWRqdXN0ICsgXCJweFwiO1xuXHRcblx0aWYgKGxpbmVJbmZvLmlzQmxvY2tDb21tZW50U3RhcnQgfHxcblx0XHRsaW5lSW5mby5pc0Jsb2NrQ29tbWVudE1pZCB8fFxuXHRcdGxpbmVJbmZvLmlzQmxvY2tDb21tZW50RW5kKVxuXHRcdHZpZXdMaW5lLnNldEF0dHJpYnV0ZShcImRhdGEtYmxvY2stY29tbWVudFwiLCBcIlwiKTtcblx0XG5cdGlmIChsaW5lSW5mby5pc1NlY3Rpb25Db21tZW50KVxuXHRcdHZpZXdMaW5lLnNldEF0dHJpYnV0ZShcImRhdGEtc2VjdGlvbi1jb21tZW50XCIsIFwiXCIpO1xuXHRcblx0aWYgKGxpbmVJbmZvLmlzTGluZUNvbW1lbnQpXG5cdFx0dmlld0xpbmUuc2V0QXR0cmlidXRlKFwiZGF0YS1saW5lLWNvbW1lbnRcIiwgXCJcIik7XG5cdFxuXHRpZiAobGluZUluZm8uaXNEZWFkQ29tbWVudClcblx0XHR2aWV3TGluZS5zZXRBdHRyaWJ1dGUoXCJkYXRhLWRlYWQtY29tbWVudFwiLCBcIlwiKTtcblx0XG5cdGlmIChsaW5lSW5mby5pc0F0dGVudGlvbkNvbW1lbnQpXG5cdFx0dmlld0xpbmUuc2V0QXR0cmlidXRlKFwiZGF0YS1hdHRlbnRpb24tY29tbWVudFwiLCBcIlwiKTtcbn1cblxuLyoqXG4gKiBcbiAqL1xuZnVuY3Rpb24gY2xhc3NpZnlMaW5lKHZpZXdMaW5lOiBIVE1MRWxlbWVudClcbntcblx0Y29uc3QgZ2V0TWV0cmljcyA9ICh2aWV3TGluZTogSFRNTEVsZW1lbnQpID0+XG5cdHtcblx0XHRjb25zdCB0ZXh0ID0gdmlld0xpbmUudGV4dENvbnRlbnQgfHwgXCJcIjtcblx0XHRjb25zdCB0cmltID0gdGV4dC50cmltKCk7XG5cdFx0Y29uc3QgdHJpbUxlZnQgPSB0ZXh0LnRyaW1MZWZ0KCk7XG5cdFx0Y29uc3QgbmJzcENvdW50ID0gdGV4dC5sZW5ndGggLSB0cmltTGVmdC5sZW5ndGg7XG5cdFx0Y29uc3QgdGFiQ291bnQgPSBNYXRoLmZsb29yKG5ic3BDb3VudCAvIGdsb2JhbFNldHRpbmdzLnNwYWNlc1BlclRhYik7XG5cdFx0Y29uc3Qgc3BhY2VDb3VudCA9IG5ic3BDb3VudCAlIGdsb2JhbFNldHRpbmdzLnNwYWNlc1BlclRhYjtcblx0XHRcblx0XHRyZXR1cm4geyB0cmltLCB0cmltTGVmdCwgbmJzcENvdW50LCB0YWJDb3VudCwgc3BhY2VDb3VudCB9O1xuXHR9XG5cdFxuXHRjb25zdCBnZXRJc0Jsb2NrQ29tbWVudE1pZCA9ICh2aWV3TGluZTogRWxlbWVudCB8IG51bGwpID0+XG5cdHtcblx0XHRpZiAoISh2aWV3TGluZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSlcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcblx0XHRjb25zdCBtID0gZ2V0TWV0cmljcyh2aWV3TGluZSk7XG5cdFx0XG5cdFx0cmV0dXJuIG0ubmJzcENvdW50ID4gMCAmJlxuXHRcdFx0KG0udHJpbSA9PT0gXCIqXCIgfHwgbS50cmltTGVmdC5zdGFydHNXaXRoKFwiKiBcIikgfHwgbS50cmltTGVmdC5zdGFydHNXaXRoKFwiKlwiICsgcykpO1xuXHR9XG5cdFxuXHRjb25zdCBtID0gZ2V0TWV0cmljcyh2aWV3TGluZSk7XG5cdGNvbnN0IHMgPSBTdHJpbmcuZnJvbUNvZGVQb2ludCgxNjApO1xuXHRcblx0Y29uc3QgaXNCbG9ja0NvbW1lbnRTdGFydCA9IG0udHJpbS5zdGFydHNXaXRoKFwiLyoqXCIpO1xuXHRjb25zdCBpc0Jsb2NrQ29tbWVudE1pZCA9IGdldElzQmxvY2tDb21tZW50TWlkKHZpZXdMaW5lKTtcblx0XG5cdGNvbnN0IGlzQmxvY2tDb21tZW50RW5kID0gKCgpID0+XG5cdHtcblx0XHRpZiAobS50cmltICE9PSBcIiovXCIpXG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XG5cdFx0Y29uc3QgcHJldmlvdXNMaW5lID0gZmluZFByZXZpb3VzTGluZSh2aWV3TGluZSk7XG5cdFx0aWYgKCFwcmV2aW91c0xpbmUpXG5cdFx0e1xuXHRcdFx0Y2xvc2luZ0NvbW1lbnRRdWV1ZS5wdXNoKHZpZXdMaW5lKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0XG5cdFx0cmV0dXJuIG0udHJpbSA9PT0gXCIqL1wiICYmXG5cdFx0XHRnZXRJc0Jsb2NrQ29tbWVudE1pZChwcmV2aW91c0xpbmUpO1xuXHR9KSgpO1xuXHRcblx0Y29uc3QgaXNMaW5lQ29tbWVudCA9IFxuXHRcdG0udHJpbSA9PT0gXCIvL1wiIHx8IFxuXHRcdG0udHJpbUxlZnQuc3RhcnRzV2l0aChcIi8vIFwiKSB8fFxuXHRcdG0udHJpbUxlZnQuc3RhcnRzV2l0aChcIi8vXCIgKyBzKTtcblx0XG5cdGNvbnN0IGlzRGVhZENvbW1lbnQgPVxuXHRcdG0udHJpbUxlZnQuc3RhcnRzV2l0aChcIi8vL1wiKSAmJlxuXHRcdCFtLnRyaW1MZWZ0LnN0YXJ0c1dpdGgoXCIvLy8gPHJlZmVyZW5jZSBcIik7XG5cdFxuXHRjb25zdCBpc0F0dGVudGlvbkNvbW1lbnQgPSBcblx0XHRtLnRyaW0gPT09IFwiLy8hXCIgfHxcblx0XHRtLnRyaW1MZWZ0LnN0YXJ0c1dpdGgoXCIvLyEgXCIpIHx8XG5cdFx0bS50cmltTGVmdC5zdGFydHNXaXRoKFwiLy8hXCIgKyBzKSB8fFxuXHRcdG0udHJpbUxlZnQuc3RhcnRzV2l0aChgLy8ke3N9ZXNsaW50LWRpc2FibGUtbmV4dC1saW5lYCArIHMpIHx8XG5cdFx0bS50cmltTGVmdC5zdGFydHNXaXRoKGAvKiR7c31lc2xpbnRgICsgcyk7XG5cdFxuXHRjb25zdCBpc1NlY3Rpb25Db21tZW50ID1cblx0XHRtLnRyaW0gPT09IFwiLy8jXCIgfHwgbS50cmltLnN0YXJ0c1dpdGgoXCIvLyNcIiArIHMpIHx8IG0udHJpbS5zdGFydHNXaXRoKFwiLy8jIFwiKTtcblx0XG5cdHJldHVybiB7XG5cdFx0aXNCbG9ja0NvbW1lbnRTdGFydCxcblx0XHRpc0Jsb2NrQ29tbWVudE1pZCxcblx0XHRpc0Jsb2NrQ29tbWVudEVuZCxcblx0XHRpc0xpbmVDb21tZW50LFxuXHRcdGlzRGVhZENvbW1lbnQsXG5cdFx0aXNBdHRlbnRpb25Db21tZW50LFxuXHRcdGlzU2VjdGlvbkNvbW1lbnQsXG5cdFx0dGFiQ291bnQ6IG0udGFiQ291bnQsXG5cdFx0c3BhY2VDb3VudDogbS5zcGFjZUNvdW50LFxuXHRcdG5ic3BDb3VudDogbS5uYnNwQ291bnRcblx0fTtcbn1cblxuLyoqXG4gKiBGaW5kcyB0aGUgZWxlbWVudCB0aGF0IHJlcHJlc2VudHMgdGhlIHByZXZpb3VzIGxpbmUgaW4gdGhlIGRvY3VtZW50LlxuICogTm90ZSB0aGF0IHRoaXMgaXNuJ3QgYXMgc2ltcGxlIGFzIGEgY2FsbCB0byBwcmV2aW91c0VsZW1lbnRTaWJsaW5nLFxuICogYmVjYXVzZSB0aGUgTW9uYWNvIGVkaXRvciBpbiBWUyBDb2RlIGRvZXMgbm90IG5lY2Vzc2FyaWx5IG9yZGVyXG4gKiB0aGUgdW5kZXJseWluZyBlbGVtZW50cyBpbiBkb2N1bWVudC1vcmRlci5cbiAqL1xuZnVuY3Rpb24gZmluZFByZXZpb3VzTGluZSh2aWV3TGluZTogSFRNTEVsZW1lbnQpXG57XG5cdGNvbnN0IHJlZlRvcCA9IHBhcnNlSW50KHZpZXdMaW5lLnN0eWxlLnRvcCB8fCBcIlwiLCAxMCkgfHwgMDtcblx0Y29uc3QgbGluZUhlaWdodCA9IHBhcnNlSW50KHZpZXdMaW5lLnN0eWxlLmhlaWdodCB8fCBcIlwiKSB8fCAzMDtcblx0Y29uc3QgdGFyZ2V0ID0gcmVmVG9wIC0gbGluZUhlaWdodCArIFwicHhcIjtcblx0XG5cdC8vIEluIG1vc3QgY2FzZXMsIHRoZSBwcmV2aW91cyBlbGVtZW50IGlzIGFjdHVhbGx5IHRoZSBvbmUgd2UncmVcblx0Ly8gbG9va2luZyBmb3IsIHNvIGl0IGNhbiBiZSByZXR1cm5lZCBlZmZpY2llbnRseS5cblx0aWYgKHZpZXdMaW5lLnByZXZpb3VzRWxlbWVudFNpYmxpbmcgaW5zdGFuY2VvZiBIVE1MRWxlbWVudClcblx0XHRpZiAodmlld0xpbmUucHJldmlvdXNFbGVtZW50U2libGluZy5zdHlsZS50b3AgPT09IHRhcmdldClcblx0XHRcdHJldHVybiB2aWV3TGluZS5wcmV2aW91c0VsZW1lbnRTaWJsaW5nO1xuXHRcblx0Ly8gT3RoZXJ3aXNlLCB3ZSBuZWVkIHRvIHNlYXJjaCBhbGwgbGluZXMuXG5cdGNvbnN0IGNvbnRhaW5lciA9IHZpZXdMaW5lLnBhcmVudEVsZW1lbnQ7XG5cdGlmICghKGNvbnRhaW5lciBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSlcblx0XHRyZXR1cm4gbnVsbDtcblx0XG5cdGZvciAobGV0IGkgPSBjb250YWluZXIuY2hpbGRFbGVtZW50Q291bnQ7IGktLSA+IDA7KVxuXHR7XG5cdFx0Y29uc3QgaXRlbSA9IGNvbnRhaW5lci5jaGlsZHJlbi5pdGVtKGkpO1xuXHRcdGlmIChpdGVtIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpXG5cdFx0e1xuXHRcdFx0aWYgKGl0ZW0uc3R5bGUudG9wID09PSB0YXJnZXQpXG5cdFx0XHRcdHJldHVybiBpdGVtO1xuXHRcdH1cblx0fVxuXHRcblx0cmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogVGhlIGNvbG9yaW5nIG9mIGNsb3NpbmcgYmxvY2sgY29tbWVudHMgaXMgZGVwZW5kZW50IG9uXG4gKiB0aGUgcHJldmlvdXMgbGluZS4gSG93ZXZlciwgdGhlIHByZXZpb3VzIGxpbmUgbWF5IG5vdCBhY3R1YWxseVxuICogYmUgcmVuZGVyZWQgaW4gdGhlIGRvY3VtZW50LiBUaGVyZWZvcmUsIHRoZSBlbGVtZW50IGlzIGFkZGVkXG4gKiB0byBhIHF1ZXVlLCB3aGljaCB3ZSBhdHRlbXB0IHRvIGNsZWFyIG91dCB3aGVuIHRoZSBuZXh0IGxpbmVcbiAqIGlzIGZlZCBpbnRvIHRoZSB2aWV3ICh3aGljaCBpcyB3aGVuIHRoZSBkb2N1bWVudCBpcyBzY3JvbGxlZCkuXG4gKi9cbmZ1bmN0aW9uIGNsZWFyQ2xvc2luZ0NvbW1lbnRRdWV1ZSgpXG57XG5cdGZvciAobGV0IGkgPSBjbG9zaW5nQ29tbWVudFF1ZXVlLmxlbmd0aDsgaS0tID4gMDspXG5cdHtcblx0XHRjb25zdCB2aWV3TGluZSA9IGNsb3NpbmdDb21tZW50UXVldWVbaV07XG5cdFx0Y29uc3QgaGFzUHJldmlvdXMgPSBmaW5kUHJldmlvdXNMaW5lKHZpZXdMaW5lKTtcblx0XHRpZiAoaGFzUHJldmlvdXMpXG5cdFx0e1xuXHRcdFx0Y2xvc2luZ0NvbW1lbnRRdWV1ZS5zcGxpY2UoaSwgMSk7XG5cdFx0XHRtYXliZUNvbnZlcnRMaW5lKHZpZXdMaW5lKTtcblx0XHR9XG5cdH1cbn1cblxuLyoqICovXG5jb25zdCBjbG9zaW5nQ29tbWVudFF1ZXVlOiBIVE1MRWxlbWVudFtdID0gW107XG5cbi8qKiBOb2RlLmpzIEVTTkVYVCBzdHJpbmcgbWV0aG9kcyAqL1xuaW50ZXJmYWNlIFN0cmluZ1xue1xuXHQvKiogUmVtb3ZlcyB3aGl0ZXNwYWNlIGZyb20gdGhlIGxlZnQgZW5kIG9mIGEgc3RyaW5nLiAqL1xuXHR0cmltTGVmdCgpOiBzdHJpbmc7XG5cdFxuXHQvKiogUmVtb3ZlcyB3aGl0ZXNwYWNlIGZyb20gdGhlIHJpZ2h0IGVuZCBvZiBhIHN0cmluZy4gKi9cblx0dHJpbVJpZ2h0KCk6IHN0cmluZztcbn1cblxuc2V0VGltZW91dCgoKSA9PiBpbml0aWFsaXplKCkpO1xuIl19