-
Notifications
You must be signed in to change notification settings - Fork 10
/
main.js
383 lines (381 loc) · 47.7 KB
/
main.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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
var __export = (target, all) => {
__markAsModule(target);
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __reExport = (target, module2, desc) => {
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
for (let key of __getOwnPropNames(module2))
if (!__hasOwnProp.call(target, key) && key !== "default")
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
}
return target;
};
var __toModule = (module2) => {
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
};
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// main.ts
__export(exports, {
BetterCodeBlocks: () => BetterCodeBlocks,
default: () => BetterCodeBlock
});
var import_obsidian = __toModule(require("obsidian"));
var DEFAULT_LANG = "";
var LANG_REG = /^language-/;
var LINE_SPLIT_MARK = "\n";
var titleRegExp = /TI:"([^"]*)"/i;
var highLightLinesRegExp = /HL:"([^"]*)"/i;
var foldRegExp = /"FOLD"/i;
var CB_PADDING_TOP = "35px";
var DEFAULT_SETTINGS = {
substitutionTokenForSpace: void 0,
titleBackgroundColor: "#00000020",
titleFontColor: void 0,
highLightColor: "#2d82cc20",
excludeLangs: [],
showLineNumber: true,
showDividingLine: false,
showLangNameInTopRight: true
};
var BetterCodeBlock = class extends import_obsidian.Plugin {
onload() {
return __async(this, null, function* () {
console.log("Loading Better Code Block Plugin");
yield this.loadSettings();
this.addSettingTab(new BetterCodeBlockTab(this.app, this));
this.registerMarkdownPostProcessor((el, ctx) => {
BetterCodeBlocks(el, ctx, this);
app.workspace.on("resize", () => {
resizeNumWrapAndHLWrap(el, ctx);
});
});
});
}
onunload() {
console.log("Unloading Better Code Block Plugin");
}
loadSettings() {
return __async(this, null, function* () {
this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
});
}
saveSettings() {
return __async(this, null, function* () {
yield this.saveData(this.settings);
});
}
};
var BetterCodeBlockTab = class extends import_obsidian.PluginSettingTab {
constructor(app2, plugin) {
super(app2, plugin);
this.plugin = plugin;
}
display() {
let { containerEl } = this;
containerEl.empty();
new import_obsidian.Setting(containerEl).setName("Exclude language list").setDesc("Title and line numbers do not apply in these languages, separate by `,`").addText((text) => text.setPlaceholder("like todoist,other,...").setValue(this.plugin.settings.excludeLangs.join(",")).onChange((value) => __async(this, null, function* () {
this.plugin.settings.excludeLangs = value.split(",");
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Font color of title").addText((tc) => tc.setPlaceholder("Enter a color").setValue(this.plugin.settings.titleFontColor).onChange((value) => __async(this, null, function* () {
this.plugin.settings.titleFontColor = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Background color of title").addText((tc) => tc.setPlaceholder("#00000020").setValue(this.plugin.settings.titleBackgroundColor).onChange((value) => __async(this, null, function* () {
this.plugin.settings.titleBackgroundColor = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("HighLight Color").addText((tc) => tc.setPlaceholder("#2d82cc20").setValue(this.plugin.settings.highLightColor).onChange((value) => __async(this, null, function* () {
this.plugin.settings.highLightColor = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Show line number").addToggle((tc) => tc.setValue(this.plugin.settings.showLineNumber).onChange((value) => __async(this, null, function* () {
this.plugin.settings.showLineNumber = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Show dividing line").addToggle((tc) => tc.setValue(this.plugin.settings.showDividingLine).onChange((value) => __async(this, null, function* () {
this.plugin.settings.showDividingLine = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Show language name in the top right").addToggle((tc) => tc.setValue(this.plugin.settings.showLangNameInTopRight).onChange((value) => __async(this, null, function* () {
this.plugin.settings.showLangNameInTopRight = value;
yield this.plugin.saveSettings();
})));
}
};
function BetterCodeBlocks(el, context, plugin) {
return __async(this, null, function* () {
var _a;
const settings = plugin.settings;
const codeElm = el.querySelector("pre > code");
if (!codeElm) {
return;
}
let lang = DEFAULT_LANG;
if (plugin.settings.excludeLangs.some((eLangName) => codeElm.classList.contains(`language-${eLangName}`))) {
return;
}
codeElm.classList.forEach((value, key, parent) => {
if (LANG_REG.test(value)) {
lang = value.replace("language-", "");
return;
}
});
if (lang == DEFAULT_LANG) {
return;
}
let codeBlock = context.getSectionInfo(codeElm);
let codeBlockFirstLine = "";
if (codeBlock) {
let view = app.workspace.getActiveViewOfType(import_obsidian.MarkdownView);
codeBlockFirstLine = view.editor.getLine(codeBlock.lineStart);
} else {
let file = app.vault.getAbstractFileByPath(context.sourcePath);
let cache = app.metadataCache.getCache(context.sourcePath);
let fileContent = yield app.vault.cachedRead(file);
let fileContentLines = fileContent.split(/\n/g);
let codeBlockFirstLines = [];
let codeBlockSections = [];
(_a = cache.sections) == null ? void 0 : _a.forEach((element) => __async(this, null, function* () {
if (element.type == "code") {
let lineStart = element.position.start.line;
codeBlockFirstLine = fileContentLines[lineStart];
codeBlockSections.push(element);
codeBlockFirstLines.push(codeBlockFirstLine);
}
}));
exportPDF(el, plugin, codeBlockFirstLines, codeBlockSections);
return;
}
let title = "";
let highLightLines = [];
if (codeBlockFirstLine.match(titleRegExp) != null) {
title = codeBlockFirstLine.match(titleRegExp)[1];
}
if (codeBlockFirstLine.match(highLightLinesRegExp) != null) {
let highLightLinesInfo = codeBlockFirstLine.match(highLightLinesRegExp)[1];
highLightLines = analyseHighLightLines(highLightLinesInfo);
}
let isCollapse = false;
if (foldRegExp.test(codeBlockFirstLine)) {
isCollapse = true;
}
const pre = codeElm.parentElement;
const div = pre.parentElement;
const contentList = codeElm.textContent.split(LINE_SPLIT_MARK);
const lineSize = codeBlock.lineEnd - codeBlock.lineStart - 1;
const cbMeta = { langName: lang, lineSize, pre, code: codeElm, title, isCollapse, div, contentList, highLightLines };
const { showLineNumber } = plugin.settings;
addCodeTitleWrapper(plugin, pre, cbMeta);
addCodeTitle(plugin, pre, cbMeta);
if (showLineNumber) {
addLineNumber(plugin, cbMeta);
}
addLineHighLight(plugin, pre, cbMeta);
resizeNumWrapAndHLWrap(el, context);
});
}
function createElement(tagName, defaultClassName) {
const element = document.createElement(tagName);
if (defaultClassName) {
element.className = defaultClassName;
}
return element;
}
function addCodeTitleWrapper(plugin, preElm, cbMeta) {
preElm.style.setProperty("position", "relative", "important");
preElm.style.setProperty("padding-top", CB_PADDING_TOP, "important");
let wrapper = document.createElement("pre");
if (cbMeta.isCollapse) {
wrapper.setAttribute("closed", "");
}
wrapper.className = "obsidian-embedded-code-title__code-block-title";
wrapper.style.backgroundColor = plugin.settings.titleBackgroundColor || "#00000020";
let collapser = createElement("div", "collapser");
let handle = createElement("div", "handle");
collapser.appendChild(handle);
wrapper.appendChild(collapser);
wrapper.addEventListener("click", function() {
if (wrapper.hasAttribute("closed")) {
wrapper.removeAttribute("closed");
} else {
wrapper.setAttribute("closed", "");
}
});
preElm.appendChild(wrapper);
}
function addCodeTitle(plugin, preElm, cbMeta) {
let wrapper = preElm.querySelector(".obsidian-embedded-code-title__code-block-title");
let titleElm = document.createElement("div");
titleElm.className = "title";
titleElm.appendText(cbMeta.title);
wrapper.appendChild(titleElm);
if (plugin.settings.titleFontColor) {
titleElm.style.setProperty("color", plugin.settings.titleFontColor, "important");
}
if (plugin.settings.showLangNameInTopRight) {
let langName = document.createElement("div");
let langNameString = cbMeta.langName;
langNameString = langNameString[0].toUpperCase() + langNameString.slice(1);
langName.appendText(langNameString);
langName.className = "langName";
wrapper.appendChild(langName);
}
preElm.prepend(wrapper);
}
function addLineNumber(plugin, cbMeta) {
const { lineSize, pre, div } = cbMeta;
div.classList.add("code-block-wrap");
const lineNumber = createElement("span", "code-block-linenum-wrap");
lineNumber.style.top = CB_PADDING_TOP;
Array.from({ length: lineSize }, (v, k) => k).forEach((i) => {
const singleLine = createElement("span", "code-block-linenum");
lineNumber.appendChild(singleLine);
});
if (plugin.settings.showDividingLine) {
lineNumber.style.borderRight = "1px currentColor solid";
}
pre.appendChild(lineNumber);
pre.classList.add("code-block-pre__has-linenum");
}
function addLineHighLight(plugin, preElm, cbMeta) {
if (cbMeta.highLightLines.length == 0)
return;
let highLightWrap = document.createElement("pre");
highLightWrap.className = "code-block-highlight-wrap";
for (let i = 0; i < cbMeta.lineSize; i++) {
const singleLine = createElement("span", "code-block-highlight");
if (cbMeta.highLightLines.contains(i + 1)) {
singleLine.style.backgroundColor = plugin.settings.highLightColor || "#2d82cc20";
}
highLightWrap.appendChild(singleLine);
}
preElm.appendChild(highLightWrap);
}
function analyseHighLightLines(str) {
str = str.replace(/\s*/g, "");
const result = [];
let strs = str.split(",");
strs.forEach((it) => {
if (/\w+-\w+/.test(it)) {
let left = Number(it.split("-")[0]);
let right = Number(it.split("-")[1]);
for (let i = left; i <= right; i++) {
result.push(i);
}
} else {
result.push(Number(it));
}
});
return result;
}
function resizeNumWrapAndHLWrap(el, context) {
setTimeout(function() {
return __async(this, null, function* () {
let codeBlockEl = el.querySelector("pre > code");
if (!codeBlockEl)
return;
let numWrap = el.querySelector(".code-block-linenum-wrap");
let highWrap = el.querySelector(".code-block-highlight-wrap");
let codeBlockInfo = context.getSectionInfo(codeBlockEl);
let view;
let codeBlockLineNum;
let lineStart = 0;
let lineEnd = 0;
if (codeBlockInfo) {
view = app.workspace.getActiveViewOfType(import_obsidian.MarkdownView);
codeBlockLineNum = codeBlockInfo.lineEnd - codeBlockInfo.lineStart - 1;
} else {
return;
}
let span = createElement("span");
for (let i = 0; i < codeBlockLineNum; i++) {
let oneLineText;
if (view) {
oneLineText = view.editor.getLine(codeBlockInfo.lineStart + i + 1);
} else {
}
span.innerHTML = oneLineText || "0";
codeBlockEl.appendChild(span);
span.style.display = "block";
let lineHeight = span.getBoundingClientRect().height + "px";
let numOneLine = numWrap ? numWrap.childNodes[i] : null;
let hlOneLine = highWrap ? highWrap.childNodes[i] : null;
if (numOneLine)
numOneLine.style.height = lineHeight;
if (hlOneLine)
hlOneLine.style.height = lineHeight;
span.remove();
}
});
}, 100);
}
function exportPDF(el, plugin, codeBlockFirstLines, codeBlockSections) {
let codeBlocks = el.querySelectorAll("pre > code");
codeBlocks.forEach((codeElm, key) => {
let langName = "", title = "", highLightLines = [];
codeElm.classList.forEach((value) => {
if (LANG_REG.test(value)) {
langName = value.replace("language-", "");
return;
}
});
if (codeBlockFirstLines[key].match(titleRegExp) != null) {
title = codeBlockFirstLines[key].match(titleRegExp)[1];
}
if (codeBlockFirstLines[key].match(highLightLinesRegExp) != null) {
let highLightLinesInfo = codeBlockFirstLines[key].match(highLightLinesRegExp)[1];
highLightLines = analyseHighLightLines(highLightLinesInfo);
}
let lineSize = codeBlockSections[key].position.end.line - codeBlockSections[key].position.start.line - 1;
let cbMeta = {
langName,
lineSize,
pre: codeElm.parentElement,
code: codeElm,
title,
isCollapse: false,
div: codeElm.parentElement.parentElement,
contentList: [],
highLightLines
};
addCodeTitleWrapper(plugin, codeElm.parentElement, cbMeta);
addCodeTitle(plugin, cbMeta.pre, cbMeta);
if (plugin.settings.showLineNumber) {
addLineNumber(plugin, cbMeta);
}
addLineHighLight(plugin, cbMeta.pre, cbMeta);
});
}
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsibWFpbi50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IHsgbGlua1N5bmMgfSBmcm9tICdmcyc7XG5pbXBvcnQgeyBBcHAsIEVkaXRvciwgTWFya2Rvd25WaWV3LCBNb2RhbCwgTm90aWNlLCBQbHVnaW4sIFBsdWdpblNldHRpbmdUYWIsIFNldHRpbmcsIE1hcmtkb3duUG9zdFByb2Nlc3NvckNvbnRleHQsIE1lbnUsIFNldHRpbmdUYWIsIFRBYnN0cmFjdEZpbGUsIFRGaWxlLCBTZWN0aW9uQ2FjaGUsIFZhdWx0IH0gZnJvbSAnb2JzaWRpYW4nO1xuaW1wb3J0IHsganNvbiB9IGZyb20gJ3N0cmVhbS9jb25zdW1lcnMnO1xuXG5jb25zdCBERUZBVUxUX0xBTkdfQVRUUiA9ICdsYW5ndWFnZS10ZXh0J1xuY29uc3QgREVGQVVMVF9MQU5HID0gJydcbmNvbnN0IExBTkdfUkVHID0gL15sYW5ndWFnZS0vXG5jb25zdCBMSU5FX1NQTElUX01BUksgPSAnXFxuJ1xuXG5jb25zdCB0aXRsZVJlZ0V4cCA9IC9USTpcIihbXlwiXSopXCIvaVxuY29uc3QgaGlnaExpZ2h0TGluZXNSZWdFeHAgPSAvSEw6XCIoW15cIl0qKVwiL2lcbmNvbnN0IGZvbGRSZWdFeHAgPSAvXCJGT0xEXCIvaVxuXG5jb25zdCBDQl9QQURESU5HX1RPUCA9IFwiMzVweFwiIC8vIFx1NEVFM1x1NzgwMVx1NTc1N1x1NEUwQVx1OEZCOVx1OERERFxuXG5pbnRlcmZhY2UgU2V0dGluZ3Mge1xuXHRzdWJzdGl0dXRpb25Ub2tlbkZvclNwYWNlOiBzdHJpbmc7XG5cdHRpdGxlQmFja2dyb3VuZENvbG9yOiBzdHJpbmc7XG5cdHRpdGxlRm9udENvbG9yOiBzdHJpbmc7XG5cdGhpZ2hMaWdodENvbG9yOiBzdHJpbmc7XG5cblx0ZXhjbHVkZUxhbmdzOiBzdHJpbmdbXTsgLy8gXHU5NzAwXHU4OTgxXHU2MzkyXHU5NjY0XHU3Njg0XHU4QkVEXHU4QTAwXG5cblx0c2hvd0xpbmVOdW1iZXI6IGJvb2xlYW47IC8vIFx1NjYzRVx1NzkzQVx1ODg0Q1x1NTNGN1xuXHRzaG93RGl2aWRpbmdMaW5lOiBib29sZWFuO1xuXHRzaG93TGFuZ05hbWVJblRvcFJpZ2h0OiBib29sZWFuO1xufVxuXG5jb25zdCBERUZBVUxUX1NFVFRJTkdTOiBTZXR0aW5ncyA9IHtcblx0c3Vic3RpdHV0aW9uVG9rZW5Gb3JTcGFjZTogdW5kZWZpbmVkLFxuXHR0aXRsZUJhY2tncm91bmRDb2xvcjogXCIjMDAwMDAwMjBcIixcblx0dGl0bGVGb250Q29sb3I6IHVuZGVmaW5lZCxcblx0aGlnaExpZ2h0Q29sb3I6IFwiIzJkODJjYzIwXCIsXG5cblx0ZXhjbHVkZUxhbmdzOiBbXSxcblxuXHRzaG93TGluZU51bWJlcjogdHJ1ZSxcblx0c2hvd0RpdmlkaW5nTGluZTogZmFsc2UsXG5cdHNob3dMYW5nTmFtZUluVG9wUmlnaHQ6IHRydWVcbn07XG5cbmludGVyZmFjZSBDb2RlQmxvY2tNZXRhIHtcblx0Ly8gTGFuZ3VhZ2UgbmFtZVxuXHRsYW5nTmFtZTogc3RyaW5nO1xuXG5cdC8vIENvZGUgYmxvY2sgdG90YWwgbGluZSBzaXplXG5cdGxpbmVTaXplOiBudW1iZXI7XG5cblx0Ly8gQ29kZSBibG9jayAncHJlJyBIVE1MRWxlbWVudFxuXHRwcmU6IEhUTUxFbGVtZW50O1xuXG5cdC8vIENvZGUgYmxvY2sgJ2NvZGUnIEhUTUxFbGVtZW50XG5cdGNvZGU6IEhUTUxFbGVtZW50O1xuXG5cdHRpdGxlOiBzdHJpbmc7IC8vIFx1NEVFM1x1NzgwMVx1NTc1N1x1NjgwN1x1OTg5OFxuXHRpc0NvbGxhcHNlOmJvb2xlYW47IC8vIFx1NjYyRlx1NTQyNlx1OUVEOFx1OEJBNFx1NjI5OFx1NTNFMFxuXG5cdC8vIENvZGUgYmxvY2sgd3JhcCBkaXZcblx0ZGl2OiBIVE1MRWxlbWVudDtcblx0Y29udGVudExpc3Q6IHN0cmluZ1tdO1xuXHRoaWdoTGlnaHRMaW5lczogbnVtYmVyW107XG59XG5cbi8vIFJlZmVyIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2phL2RvY3MvV2ViL0phdmFTY3JpcHQvR3VpZGUvUmVndWxhcl9FeHByZXNzaW9ucyNlc2NhcGluZ1xuZnVuY3Rpb24gZXNjYXBlUmVnRXhwKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcblx0cmV0dXJuIHN0ci5yZXBsYWNlKC9bLiorP149IToke30oKXxbXFxdXFwvXFxcXF0vZywgXCJcXFxcJCZcIik7IC8vIFx1NEUzQVx1NzI3OVx1NkI4QVx1N0IyNlx1NTNGN1x1NTJBMFx1NEUwQVx1OEY2Q1x1NEU0OVx1N0IyNlx1NTNGN1wiXFxcIlxufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCZXR0ZXJDb2RlQmxvY2sgZXh0ZW5kcyBQbHVnaW4ge1xuXHRzZXR0aW5nczogU2V0dGluZ3M7XG5cblx0YXN5bmMgb25sb2FkKCkge1xuXHRcdGNvbnNvbGUubG9nKFwiTG9hZGluZyBCZXR0ZXIgQ29kZSBCbG9jayBQbHVnaW5cIik7XG5cdFx0YXdhaXQgdGhpcy5sb2FkU2V0dGluZ3MoKTtcblx0XHR0aGlzLmFkZFNldHRpbmdUYWIobmV3IEJldHRlckNvZGVCbG9ja1RhYih0aGlzLmFwcCwgdGhpcykpO1xuXHRcdHRoaXMucmVnaXN0ZXJNYXJrZG93blBvc3RQcm9jZXNzb3IoKGVsLCBjdHgpID0+IHtcblx0XHRcdEJldHRlckNvZGVCbG9ja3MoZWwsIGN0eCwgdGhpcylcblx0XHRcdGFwcC53b3Jrc3BhY2Uub24oJ3Jlc2l6ZScsICgpID0+IHtcblx0XHRcdFx0cmVzaXplTnVtV3JhcEFuZEhMV3JhcChlbCwgY3R4KVxuXHRcdFx0fSlcblx0XHR9KVxuXG5cdH1cblxuXHRvbnVubG9hZCAoKSB7XG5cdFx0Y29uc29sZS5sb2coJ1VubG9hZGluZyBCZXR0ZXIgQ29kZSBCbG9jayBQbHVnaW4nKTtcblx0fVxuXHRcblx0YXN5bmMgbG9hZFNldHRpbmdzKCkge1xuXHRcdHRoaXMuc2V0dGluZ3MgPSBPYmplY3QuYXNzaWduKHt9LCBERUZBVUxUX1NFVFRJTkdTLCBhd2FpdCB0aGlzLmxvYWREYXRhKCkpO1xuXHR9XG5cdFxuXHRhc3luYyBzYXZlU2V0dGluZ3MoKSB7XG5cdFx0YXdhaXQgdGhpcy5zYXZlRGF0YSh0aGlzLnNldHRpbmdzKTtcblx0fVxufVxuXG5jbGFzcyBCZXR0ZXJDb2RlQmxvY2tUYWIgZXh0ZW5kcyBQbHVnaW5TZXR0aW5nVGFiIHtcblx0cGx1Z2luOiBCZXR0ZXJDb2RlQmxvY2s7XG4gIFxuXHRjb25zdHJ1Y3RvcihhcHA6IEFwcCwgcGx1Z2luOiBCZXR0ZXJDb2RlQmxvY2spIHtcblx0ICBzdXBlcihhcHAsIHBsdWdpbik7XG5cdCAgdGhpcy5wbHVnaW4gPSBwbHVnaW47XG5cdH1cbiAgXG5cdGRpc3BsYXkoKTogdm9pZCB7XG5cdCAgbGV0IHsgY29udGFpbmVyRWwgfSA9IHRoaXM7XG4gIFxuXHQgIGNvbnRhaW5lckVsLmVtcHR5KCk7XG5cdFxuXHQgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuXHRcdC5zZXROYW1lKFwiRXhjbHVkZSBsYW5ndWFnZSBsaXN0XCIpXG5cdFx0LnNldERlc2MoXCJUaXRsZSBhbmQgbGluZSBudW1iZXJzIGRvIG5vdCBhcHBseSBpbiB0aGVzZSBsYW5ndWFnZXMsIHNlcGFyYXRlIGJ5IGAsYFwiKVxuXHRcdC5hZGRUZXh0KHRleHQgPT4gdGV4dC5zZXRQbGFjZWhvbGRlcignbGlrZSB0b2RvaXN0LG90aGVyLC4uLicpXG5cdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmV4Y2x1ZGVMYW5ncy5qb2luKCcsJykpXG5cdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xuXHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuZXhjbHVkZUxhbmdzID0gdmFsdWUuc3BsaXQoJywnKTtcblx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdH0pXG5cdFx0KVxuICBcblx0ICBuZXcgU2V0dGluZyhjb250YWluZXJFbCkuc2V0TmFtZShcIkZvbnQgY29sb3Igb2YgdGl0bGVcIikuYWRkVGV4dCgodGMpID0+XG5cdFx0dGNcblx0XHQgIC5zZXRQbGFjZWhvbGRlcihcIkVudGVyIGEgY29sb3JcIilcblx0XHQgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy50aXRsZUZvbnRDb2xvcilcblx0XHQgIC5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcblx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnRpdGxlRm9udENvbG9yID0gdmFsdWU7XG5cdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHQgIH0pXG5cdCAgKTtcbiAgXG5cdCAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG5cdFx0LnNldE5hbWUoXCJCYWNrZ3JvdW5kIGNvbG9yIG9mIHRpdGxlXCIpXG5cdFx0LmFkZFRleHQoKHRjKSA9PlxuXHRcdCAgdGNcblx0XHRcdC5zZXRQbGFjZWhvbGRlcihcIiMwMDAwMDAyMFwiKVxuXHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnRpdGxlQmFja2dyb3VuZENvbG9yKVxuXHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xuXHRcdFx0ICB0aGlzLnBsdWdpbi5zZXR0aW5ncy50aXRsZUJhY2tncm91bmRDb2xvciA9IHZhbHVlO1xuXHRcdFx0ICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdH0pXG5cdFx0KTtcblxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuXHRcdC5zZXROYW1lKFwiSGlnaExpZ2h0IENvbG9yXCIpXG5cdFx0LmFkZFRleHQoKHRjKSA9PlxuXHRcdCAgdGNcblx0XHRcdC5zZXRQbGFjZWhvbGRlcihcIiMyZDgyY2MyMFwiKVxuXHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmhpZ2hMaWdodENvbG9yKVxuXHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xuXHRcdFx0ICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5oaWdoTGlnaHRDb2xvciA9IHZhbHVlO1xuXHRcdFx0ICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdH0pXG5cdFx0KTtcblxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuXHRcdC5zZXROYW1lKFwiU2hvdyBsaW5lIG51bWJlclwiKVxuXHRcdC5hZGRUb2dnbGUoKHRjKSA9PiBcblx0XHR0Yy5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5zaG93TGluZU51bWJlcilcblx0XHQub25DaGFuZ2UoYXN5bmModmFsdWUpID0+IHtcblx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnNob3dMaW5lTnVtYmVyID0gdmFsdWU7XG5cdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHR9KVxuXHRcdClcblxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuXHRcdC5zZXROYW1lKFwiU2hvdyBkaXZpZGluZyBsaW5lXCIpXG5cdFx0LmFkZFRvZ2dsZSgodGMpID0+XG5cdFx0dGMuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3Muc2hvd0RpdmlkaW5nTGluZSlcblx0XHQub25DaGFuZ2UoYXN5bmModmFsdWUpID0+IHtcblx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnNob3dEaXZpZGluZ0xpbmUgPSB2YWx1ZTtcblx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdH0pXG5cdFx0KVxuXG5cdFx0bmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG5cdFx0LnNldE5hbWUoXCJTaG93IGxhbmd1YWdlIG5hbWUgaW4gdGhlIHRvcCByaWdodFwiKVxuXHRcdC5hZGRUb2dnbGUoKHRjKSA9PlxuXHRcdHRjLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnNob3dMYW5nTmFtZUluVG9wUmlnaHQpXG5cdFx0Lm9uQ2hhbmdlKGFzeW5jKHZhbHVlKSA9PiB7XG5cdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5zaG93TGFuZ05hbWVJblRvcFJpZ2h0ID0gdmFsdWU7XG5cdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHR9KVxuXHRcdClcblx0fVxuICB9XG5cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIEJldHRlckNvZGVCbG9ja3MoZWw6IEhUTUxFbGVtZW50LCBjb250ZXh0OiBNYXJrZG93blBvc3RQcm9jZXNzb3JDb250ZXh0LCBwbHVnaW46IEJldHRlckNvZGVCbG9jaykge1xuXHRjb25zdCBzZXR0aW5ncyA9IHBsdWdpbi5zZXR0aW5nc1xuXHRjb25zdCBjb2RlRWxtOiBIVE1MRWxlbWVudCA9IGVsLnF1ZXJ5U2VsZWN0b3IoJ3ByZSA+IGNvZGUnKVxuXHQvLyBvbmx5IGNoYW5nZSBwcmU+Y29kZVxuXHRpZiAoIWNvZGVFbG0pIHsgcmV0dXJuIH1cblxuXHRsZXQgbGFuZyA9IERFRkFVTFRfTEFOR1xuXHQvLyByZXR1cm4gd2hlbiBsYW5nIGlzIGluIGV4Y2x1ZGUgbGlzdFxuXHRpZiAocGx1Z2luLnNldHRpbmdzLmV4Y2x1ZGVMYW5ncy5zb21lKGVMYW5nTmFtZSA9PiBjb2RlRWxtLmNsYXNzTGlzdC5jb250YWlucyhgbGFuZ3VhZ2UtJHtlTGFuZ05hbWV9YCkpKSB7XG5cdCAgcmV0dXJuXG5cdH1cblx0XG5cdGNvZGVFbG0uY2xhc3NMaXN0LmZvckVhY2goKHZhbHVlLCBrZXksIHBhcmVudCkgPT4ge1xuXHQgIGlmIChMQU5HX1JFRy50ZXN0KHZhbHVlKSkge1xuXHRcdGxhbmcgPSB2YWx1ZS5yZXBsYWNlKCdsYW5ndWFnZS0nLCAnJylcblx0XHRyZXR1cm5cblx0ICB9XG5cdH0pXG5cblx0Ly8gaWYgdGhlIGNvZGUgYmxvY2sgaXMgbm90IGRlc2NyaWJlZCwgcmV0dXJuXG5cdGlmKGxhbmcgPT0gREVGQVVMVF9MQU5HKSB7XG5cdFx0cmV0dXJuXG5cdH1cblxuXHRsZXQgY29kZUJsb2NrID0gY29udGV4dC5nZXRTZWN0aW9uSW5mbyhjb2RlRWxtKVxuXHRsZXQgY29kZUJsb2NrRmlyc3RMaW5lID0gXCJcIlxuXG5cdGlmKGNvZGVCbG9jaykge1xuXHRcdGxldCB2aWV3ID0gYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldylcblx0XHRjb2RlQmxvY2tGaXJzdExpbmUgPSB2aWV3LmVkaXRvci5nZXRMaW5lKGNvZGVCbG9jay5saW5lU3RhcnQpXG5cdH0gZWxzZSB7IFxuXHRcdGxldCBmaWxlID0gYXBwLnZhdWx0LmdldEFic3RyYWN0RmlsZUJ5UGF0aChjb250ZXh0LnNvdXJjZVBhdGgpXG5cdFx0bGV0IGNhY2hlID0gYXBwLm1ldGFkYXRhQ2FjaGUuZ2V0Q2FjaGUoY29udGV4dC5zb3VyY2VQYXRoKVxuXHRcdGxldCBmaWxlQ29udGVudCA9IGF3YWl0IGFwcC52YXVsdC5jYWNoZWRSZWFkKDxURmlsZT4gZmlsZSlcblx0XHRsZXQgZmlsZUNvbnRlbnRMaW5lcyA9IGZpbGVDb250ZW50LnNwbGl0KC9cXG4vZylcblxuXHRcdGxldCBjb2RlQmxvY2tGaXJzdExpbmVzOiBzdHJpbmdbXSA9IFtdXG5cdFx0bGV0IGNvZGVCbG9ja1NlY3Rpb25zOiBTZWN0aW9uQ2FjaGVbXSA9IFtdXG5cblx0XHRjYWNoZS5zZWN0aW9ucz8uZm9yRWFjaChhc3luYyBlbGVtZW50ID0+IHtcblx0XHRcdGlmKGVsZW1lbnQudHlwZSA9PSBcImNvZGVcIikge1xuXHRcdFx0XHRsZXQgbGluZVN0YXJ0ID0gZWxlbWVudC5wb3NpdGlvbi5zdGFydC5saW5lXG5cdFx0XHRcdGNvZGVCbG9ja0ZpcnN0TGluZSA9IGZpbGVDb250ZW50TGluZXNbbGluZVN0YXJ0XVxuXHRcdFx0XHRjb2RlQmxvY2tTZWN0aW9ucy5wdXNoKGVsZW1lbnQpXG5cdFx0XHRcdGNvZGVCbG9ja0ZpcnN0TGluZXMucHVzaChjb2RlQmxvY2tGaXJzdExpbmUpXG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0ZXhwb3J0UERGKGVsLCBwbHVnaW4sIGNvZGVCbG9ja0ZpcnN0TGluZXMsIGNvZGVCbG9ja1NlY3Rpb25zKVxuXHRcdHJldHVyblxuXHR9XG5cblx0bGV0IHRpdGxlOiBzdHJpbmcgPSBcIlwiXG5cdGxldCBoaWdoTGlnaHRMaW5lczogbnVtYmVyW10gPSBbXVxuXHRpZihjb2RlQmxvY2tGaXJzdExpbmUubWF0Y2godGl0bGVSZWdFeHApICE9IG51bGwpIHtcblx0XHR0aXRsZSA9IGNvZGVCbG9ja0ZpcnN0TGluZS5tYXRjaCh0aXRsZVJlZ0V4cClbMV1cblx0fVxuXHRpZihjb2RlQmxvY2tGaXJzdExpbmUubWF0Y2goaGlnaExpZ2h0TGluZXNSZWdFeHApICE9IG51bGwpIHtcblx0XHRsZXQgaGlnaExpZ2h0TGluZXNJbmZvID0gY29kZUJsb2NrRmlyc3RMaW5lLm1hdGNoKGhpZ2hMaWdodExpbmVzUmVnRXhwKVsxXVxuXHRcdGhpZ2hMaWdodExpbmVzID0gYW5hbHlzZUhpZ2hMaWdodExpbmVzKGhpZ2hMaWdodExpbmVzSW5mbylcblx0fVxuXG5cdGxldCBpc0NvbGxhcHNlID0gZmFsc2U7XG5cdGlmKGZvbGRSZWdFeHAudGVzdChjb2RlQmxvY2tGaXJzdExpbmUpKSB7XG5cdFx0aXNDb2xsYXBzZSA9IHRydWVcblx0fVxuXG5cdGNvbnN0IHByZSA9IGNvZGVFbG0ucGFyZW50RWxlbWVudCAvLyBjb2RlLWJsb2NrLXByZV9faGFzLWxpbmVudW1cblx0Y29uc3QgZGl2ID0gcHJlLnBhcmVudEVsZW1lbnQgLy8gY2xhc3MgY29kZS1ibG9jay13cmFwXG5cblx0LyogY29uc3QgeyBsaW5lU3RhcnQsIGxpbmVFbmQgfSA9IGN0eC5nZXRTZWN0aW9uSW5mbyhlbClcblx0Y29uc3QgbGluZVNpemUgPSBsaW5lRW5kIC0gbGluZVN0YXJ0IC0gMSAqL1xuXHRjb25zdCBjb250ZW50TGlzdDogc3RyaW5nW10gPSBjb2RlRWxtLnRleHRDb250ZW50LnNwbGl0KExJTkVfU1BMSVRfTUFSSylcblx0Ly8gY29uc3QgbGluZVNpemUgPSBjb250ZW50TGlzdC5sZW5ndGggLSAxXG5cdGNvbnN0IGxpbmVTaXplID0gY29kZUJsb2NrLmxpbmVFbmQgLSBjb2RlQmxvY2subGluZVN0YXJ0IC0gMVxuXG5cdGNvbnN0IGNiTWV0YSA9IHsgbGFuZ05hbWU6IGxhbmcsIGxpbmVTaXplLCBwcmUsIGNvZGU6IGNvZGVFbG0sIHRpdGxlLCBpc0NvbGxhcHNlLCBkaXYsIGNvbnRlbnRMaXN0LCBoaWdoTGlnaHRMaW5lc31cblxuXHRjb25zdCB7c2hvd0xpbmVOdW1iZXJ9ID0gcGx1Z2luLnNldHRpbmdzXG5cblx0YWRkQ29kZVRpdGxlV3JhcHBlcihwbHVnaW4sIHByZSwgY2JNZXRhKVxuXHQvL2FkZEljb25Ub1RpdGxlKHBsdWdpbiwgcHJlLCBjYk1ldGEpXG5cdGFkZENvZGVUaXRsZShwbHVnaW4sIHByZSwgY2JNZXRhKTtcblxuXHQvLyBhZGQgbGluZSBudW1iZXJcblx0aWYgKHNob3dMaW5lTnVtYmVyKSB7XG5cdFx0YWRkTGluZU51bWJlcihwbHVnaW4sIGNiTWV0YSlcblx0fVxuXG5cdGFkZExpbmVIaWdoTGlnaHQocGx1Z2luLCBwcmUsIGNiTWV0YSlcblxuXHRyZXNpemVOdW1XcmFwQW5kSExXcmFwKGVsLGNvbnRleHQpIC8vIFx1OEMwM1x1NzUyOFx1NEUwMFx1NkIyMVx1NEVFNVx1ODlFM1x1NTFCM1x1NjdEMFx1NEU5Qlx1NjVGNlx1NTAxOVx1NjI1M1x1NUYwMFx1NjU4N1x1NEVGNlx1ODg0Q1x1OUFEOFx1NjcyQVx1ODhBQlx1OTFDRFx1OEJCRVx1OUFEOFx1NUVBNlxufVxuXG5mdW5jdGlvbiBjcmVhdGVFbGVtZW50ICh0YWdOYW1lOiBzdHJpbmcsIGRlZmF1bHRDbGFzc05hbWU/OiBzdHJpbmcpIHtcblx0Y29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnTmFtZSlcblx0aWYgKGRlZmF1bHRDbGFzc05hbWUpIHtcblx0ICBlbGVtZW50LmNsYXNzTmFtZSA9IGRlZmF1bHRDbGFzc05hbWVcblx0fVxuXHRyZXR1cm4gZWxlbWVudFxufVxuXG5mdW5jdGlvbiBhZGRDb2RlVGl0bGVXcmFwcGVyKHBsdWdpbjogQmV0dGVyQ29kZUJsb2NrLCBwcmVFbG06IEhUTUxFbGVtZW50LCBjYk1ldGE6IENvZGVCbG9ja01ldGEpIHtcblx0cHJlRWxtLnN0eWxlLnNldFByb3BlcnR5KFwicG9zaXRpb25cIiwgXCJyZWxhdGl2ZVwiLCBcImltcG9ydGFudFwiKTtcblx0cHJlRWxtLnN0eWxlLnNldFByb3BlcnR5KFwicGFkZGluZy10b3BcIiwgQ0JfUEFERElOR19UT1AsIFwiaW1wb3J0YW50XCIpO1xuXG5cdGxldCB3cmFwcGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInByZVwiKVxuXHRpZihjYk1ldGEuaXNDb2xsYXBzZSkge1xuXHRcdHdyYXBwZXIuc2V0QXR0cmlidXRlKFwiY2xvc2VkXCIsXCJcIilcblx0fVxuXHR3cmFwcGVyLmNsYXNzTmFtZSA9IFwib2JzaWRpYW4tZW1iZWRkZWQtY29kZS10aXRsZV9fY29kZS1ibG9jay10aXRsZVwiXG5cblx0d3JhcHBlci5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBwbHVnaW4uc2V0dGluZ3MudGl0bGVCYWNrZ3JvdW5kQ29sb3IgfHwgXCIjMDAwMDAwMjBcIjtcblxuXHRsZXQgY29sbGFwc2VyID0gY3JlYXRlRWxlbWVudChcImRpdlwiLFwiY29sbGFwc2VyXCIpXG5cdGxldCBoYW5kbGUgPSBjcmVhdGVFbGVtZW50KFwiZGl2XCIsIFwiaGFuZGxlXCIpXG5cdGNvbGxhcHNlci5hcHBlbmRDaGlsZChoYW5kbGUpXG5cdHdyYXBwZXIuYXBwZW5kQ2hpbGQoY29sbGFwc2VyKVxuXG5cdHdyYXBwZXIuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLGZ1bmN0aW9uKHRoaXM6IGFueSkge1xuXHRcdGlmKHdyYXBwZXIuaGFzQXR0cmlidXRlKFwiY2xvc2VkXCIpKXtcblx0XHRcdHdyYXBwZXIucmVtb3ZlQXR0cmlidXRlKFwiY2xvc2VkXCIpXG5cdFx0fSBlbHNlIHtcblx0XHRcdHdyYXBwZXIuc2V0QXR0cmlidXRlKFwiY2xvc2VkXCIsJycpXG5cdFx0fVxuXHR9KVxuXG5cdHByZUVsbS5hcHBlbmRDaGlsZCh3cmFwcGVyKVxufVxuXG5mdW5jdGlvbiBhZGRDb2RlVGl0bGUgKHBsdWdpbjogQmV0dGVyQ29kZUJsb2NrLCBwcmVFbG06IEhUTUxFbGVtZW50LCBjYk1ldGE6IENvZGVCbG9ja01ldGEpIHtcblx0bGV0IHdyYXBwZXIgPSBwcmVFbG0ucXVlcnlTZWxlY3RvcihcIi5vYnNpZGlhbi1lbWJlZGRlZC1jb2RlLXRpdGxlX19jb2RlLWJsb2NrLXRpdGxlXCIpXG5cblx0bGV0IHRpdGxlRWxtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKVxuXHR0aXRsZUVsbS5jbGFzc05hbWUgPSBcInRpdGxlXCJcblxuXHR0aXRsZUVsbS5hcHBlbmRUZXh0KGNiTWV0YS50aXRsZSlcblx0d3JhcHBlci5hcHBlbmRDaGlsZCh0aXRsZUVsbSlcblxuXHRpZihwbHVnaW4uc2V0dGluZ3MudGl0bGVGb250Q29sb3IpIHtcblx0XHR0aXRsZUVsbS5zdHlsZS5zZXRQcm9wZXJ0eShcImNvbG9yXCIsIHBsdWdpbi5zZXR0aW5ncy50aXRsZUZvbnRDb2xvciwgXCJpbXBvcnRhbnRcIilcblx0fVxuXHRcblx0aWYocGx1Z2luLnNldHRpbmdzLnNob3dMYW5nTmFtZUluVG9wUmlnaHQpIHtcblx0XHRsZXQgbGFuZ05hbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpOyAvLyBcdTU3MjhcdTUzRjNcdTRGQTdcdTZERkJcdTUyQTBcdTRFRTNcdTc4MDFcdTdDN0JcdTU3OEJcblx0XHRsZXQgbGFuZ05hbWVTdHJpbmcgPSBjYk1ldGEubGFuZ05hbWVcblx0XHRsYW5nTmFtZVN0cmluZyA9IGxhbmdOYW1lU3RyaW5nWzBdLnRvVXBwZXJDYXNlKCkgKyBsYW5nTmFtZVN0cmluZy5zbGljZSgxKSAvLyBcdTk5OTZcdTVCNTdcdTZCQ0RcdTU5MjdcdTUxOTlcblx0XHRsYW5nTmFtZS5hcHBlbmRUZXh0KGxhbmdOYW1lU3RyaW5nKTtcblx0XHRsYW5nTmFtZS5jbGFzc05hbWUgPSBcImxhbmdOYW1lXCI7XG5cdFx0d3JhcHBlci5hcHBlbmRDaGlsZChsYW5nTmFtZSk7XG5cdH1cblxuXHRwcmVFbG0ucHJlcGVuZCh3cmFwcGVyKTtcblxufVxuXG5mdW5jdGlvbiBhZGRMaW5lTnVtYmVyIChwbHVnaW46IEJldHRlckNvZGVCbG9jaywgY2JNZXRhOiBDb2RlQmxvY2tNZXRhKSB7XG5cdGNvbnN0IHsgbGluZVNpemUsIHByZSwgZGl2IH0gPSBjYk1ldGFcblx0Ly8gbGV0IGRpdiBwb3NpdGlvbjogcmVsYXRpdmU7XG5cdGRpdi5jbGFzc0xpc3QuYWRkKCdjb2RlLWJsb2NrLXdyYXAnKVxuXG5cdC8vIGNvbnN0IHsgZm9udFNpemUsIGxpbmVIZWlnaHQgfSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGNiTWV0YS5jb2RlKVxuXHRjb25zdCBsaW5lTnVtYmVyID0gY3JlYXRlRWxlbWVudCgnc3BhbicsICdjb2RlLWJsb2NrLWxpbmVudW0td3JhcCcpXG5cdGxpbmVOdW1iZXIuc3R5bGUudG9wID0gQ0JfUEFERElOR19UT1A7XG5cdEFycmF5LmZyb20oeyBsZW5ndGg6IGxpbmVTaXplIH0sICh2LCBrKSA9PiBrKS5mb3JFYWNoKGkgPT4ge1xuXHQgIGNvbnN0IHNpbmdsZUxpbmUgPSBjcmVhdGVFbGVtZW50KCdzcGFuJywgJ2NvZGUtYmxvY2stbGluZW51bScpXG5cdCAgLy8gc2luZ2xlTGluZS5zdHlsZS5mb250U2l6ZSA9IGZvbnRTaXplXG5cdCAgLy8gc2luZ2xlTGluZS5zdHlsZS5saW5lSGVpZ2h0ID0gbGluZUhlaWdodFxuXHQgIGxpbmVOdW1iZXIuYXBwZW5kQ2hpbGQoc2luZ2xlTGluZSlcblx0fSlcblx0XG5cdGlmKHBsdWdpbi5zZXR0aW5ncy5zaG93RGl2aWRpbmdMaW5lKSB7XG5cdFx0bGluZU51bWJlci5zdHlsZS5ib3JkZXJSaWdodCA9IFwiMXB4IGN1cnJlbnRDb2xvciBzb2xpZFwiXG5cdH1cblxuXHRwcmUuYXBwZW5kQ2hpbGQobGluZU51bWJlcilcblx0cHJlLmNsYXNzTGlzdC5hZGQoJ2NvZGUtYmxvY2stcHJlX19oYXMtbGluZW51bScpXG59XG5cbmZ1bmN0aW9uIGFkZExpbmVIaWdoTGlnaHQocGx1Z2luOiBCZXR0ZXJDb2RlQmxvY2ssIHByZUVsbTogSFRNTEVsZW1lbnQsIGNiTWV0YTogQ29kZUJsb2NrTWV0YSkge1xuXHRpZihjYk1ldGEuaGlnaExpZ2h0TGluZXMubGVuZ3RoID09IDApIHJldHVyblxuXG5cdGxldCBoaWdoTGlnaHRXcmFwID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInByZVwiKVxuXHRoaWdoTGlnaHRXcmFwLmNsYXNzTmFtZSA9IFwiY29kZS1ibG9jay1oaWdobGlnaHQtd3JhcFwiXG5cdGZvcihsZXQgaSA9IDA7IGkgPCBjYk1ldGEubGluZVNpemU7IGkrKykge1xuXHRcdGNvbnN0IHNpbmdsZUxpbmUgPSBjcmVhdGVFbGVtZW50KFwic3BhblwiLCAnY29kZS1ibG9jay1oaWdobGlnaHQnKVxuXHRcdGlmKGNiTWV0YS5oaWdoTGlnaHRMaW5lcy5jb250YWlucyhpKzEpKSB7XG5cdFx0XHRzaW5nbGVMaW5lLnN0eWxlLmJhY2tncm91bmRDb2xvciA9IHBsdWdpbi5zZXR0aW5ncy5oaWdoTGlnaHRDb2xvciB8fCBcIiMyZDgyY2MyMFwiXG5cdFx0fVxuXHRcdGhpZ2hMaWdodFdyYXAuYXBwZW5kQ2hpbGQoc2luZ2xlTGluZSlcblx0fVxuXG5cdHByZUVsbS5hcHBlbmRDaGlsZChoaWdoTGlnaHRXcmFwKVxufVxuXG5mdW5jdGlvbiBhbmFseXNlSGlnaExpZ2h0TGluZXMoc3RyOiBzdHJpbmcpOiBudW1iZXJbXSB7XG5cdHN0ciA9IHN0ci5yZXBsYWNlKC9cXHMqL2csIFwiXCIpIC8vIFx1NTNCQlx1OTY2NFx1NUI1N1x1N0IyNlx1NEUzMlx1NEUyRFx1NjI0MFx1NjcwOVx1N0E3QVx1NjgzQ1xuXHRjb25zdCByZXN1bHQ6IG51bWJlcltdID0gW11cblxuXHRsZXQgc3RycyA9IHN0ci5zcGxpdChcIixcIilcblx0c3Rycy5mb3JFYWNoKGl0ID0+IHtcblx0XHRpZigvXFx3Ky1cXHcrLy50ZXN0KGl0KSkgeyAvLyBcdTU5ODJcdTY3OUNcdTUzMzlcdTkxNEQgMS0zIFx1OEZEOVx1NjgzN1x1NzY4NFx1NjgzQ1x1NUYwRlx1RkYwQ1x1NEY5RFx1NkIyMVx1NkRGQlx1NTJBMFx1NjU3MFx1NUI1N1xuXHRcdFx0bGV0IGxlZnQgPSBOdW1iZXIoaXQuc3BsaXQoJy0nKVswXSlcblx0XHRcdGxldCByaWdodCA9IE51bWJlcihpdC5zcGxpdCgnLScpWzFdKVxuXHRcdFx0Zm9yKGxldCBpID0gbGVmdDsgaSA8PSByaWdodDsgaSsrKSB7XG5cdFx0XHRcdHJlc3VsdC5wdXNoKGkpXG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlc3VsdC5wdXNoKE51bWJlcihpdCkpXG5cdFx0fVxuXHR9KVxuXG5cdHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gYWRkSWNvblRvVGl0bGUocGx1Z2luOiBCZXR0ZXJDb2RlQmxvY2ssIHByZUVsbTogSFRNTEVsZW1lbnQsIGNiTWV0YTogQ29kZUJsb2NrTWV0YSkge1xuXHRsZXQgdGl0bGUgPSBwcmVFbG0ucXVlcnlTZWxlY3RvckFsbChcIi5vYnNpZGlhbi1lbWJlZGRlZC1jb2RlLXRpdGxlX19jb2RlLWJsb2NrLXRpdGxlXCIpXG5cblx0dGl0bGUuZm9yRWFjaChpdCA9PiB7XG5cdFx0bGV0IGljb25XcmFwID0gY3JlYXRlRWxlbWVudChcImRpdlwiLFwiaWNvbi13cmFwXCIpXG5cdFx0bGV0IGljb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiaW1nXCIpXG5cdFx0aWNvbi5zcmMgPSBcIlwiXG5cdFx0aWNvbldyYXAuYXBwZW5kQ2hpbGQoaWNvbilcblx0XHRpdC5hcHBlbmRDaGlsZChpY29uV3JhcClcblx0fSlcblx0XG59XG5cbi8vIFx1NTcyOFx1ODFFQVx1NTJBOFx1NjM2Mlx1ODg0Q1x1NjVGNlx1NUJGOVx1NjU3MFx1NUI1N1x1NTQ4Q1x1OUFEOFx1NEVBRVx1ODg0Q1x1OTFDRFx1NjVCMFx1OEJCRVx1N0Y2RVx1OUFEOFx1NUVBNlxuLy8gVGhlc2UgY29kZXMgcmVmZXIgdG8gdGhlIGh0dHBzOi8vZ2l0aHViLmNvbS9saWp5emUvb2JzaWRpYW4tYWR2YW5jZWQtY29kZWJsb2NrXG5mdW5jdGlvbiByZXNpemVOdW1XcmFwQW5kSExXcmFwKGVsOiBIVE1MRWxlbWVudCwgY29udGV4dDogTWFya2Rvd25Qb3N0UHJvY2Vzc29yQ29udGV4dCkge1xuXHRzZXRUaW1lb3V0KGFzeW5jIGZ1bmN0aW9uKCl7IC8vIFx1NUVGNlx1NjVGNjEwMFx1NkJFQlx1NzlEMlx1NEVFNVx1ODlFM1x1NTFCM1x1NjdEMFx1NEU5Qlx1NjVGNlx1NTAxOVx1NjI1M1x1NUYwMFx1NjU4N1x1NEVGNlx1ODg0Q1x1OUFEOFx1NjcyQVx1ODhBQlx1OTFDRFx1OEJCRVx1OUFEOFx1NUVBNlxuXHRcdC8vIGNvbnNvbGUubG9nKCdvbiByZXNpemUnKVxuXHRcdGxldCBjb2RlQmxvY2tFbCA6IEhUTUxFbGVtZW50ID0gZWwucXVlcnlTZWxlY3RvcigncHJlID4gY29kZScpXG5cdFx0aWYoIWNvZGVCbG9ja0VsKSByZXR1cm5cblxuXHRcdGxldCBudW1XcmFwID0gZWwucXVlcnlTZWxlY3RvcignLmNvZGUtYmxvY2stbGluZW51bS13cmFwJylcblx0XHRsZXQgaGlnaFdyYXAgPSBlbC5xdWVyeVNlbGVjdG9yKCcuY29kZS1ibG9jay1oaWdobGlnaHQtd3JhcCcpXG5cblx0XHRsZXQgY29kZUJsb2NrSW5mbyA9IGNvbnRleHQuZ2V0U2VjdGlvbkluZm8oY29kZUJsb2NrRWwpXG5cdFx0Ly8gbGV0IHZpZXcgPSBhcHAud29ya3NwYWNlLmdldEFjdGl2ZVZpZXdPZlR5cGUoTWFya2Rvd25WaWV3KVxuXHRcdC8vIGxldCBjb2RlQmxvY2tMaW5lTnVtID0gY29kZUJsb2NrSW5mby5saW5lRW5kIC0gY29kZUJsb2NrSW5mby5saW5lU3RhcnQgLSAxIC8vIFx1OTY2NFx1NTNCQlx1OTk5Nlx1NUMzRVx1NEUyNFx1ODg0Q1xuXHRcdGxldCB2aWV3XG5cdFx0bGV0IGNvZGVCbG9ja0xpbmVOdW1cblxuXHRcdGxldCBsaW5lU3RhcnQgPSAwXG5cdFx0bGV0IGxpbmVFbmQgPSAwXG5cdFx0aWYoY29kZUJsb2NrSW5mbykge1xuXHRcdFx0dmlldyA9IGFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlVmlld09mVHlwZShNYXJrZG93blZpZXcpXG5cdFx0XHRjb2RlQmxvY2tMaW5lTnVtID0gY29kZUJsb2NrSW5mby5saW5lRW5kIC0gY29kZUJsb2NrSW5mby5saW5lU3RhcnQgLSAxIC8vIFx1OTY2NFx1NTNCQlx1OTk5Nlx1NUMzRVx1NEUyNFx1ODg0Q1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm5cblx0XHRcdC8vIGxldCBmaWxlID0gYXBwLnZhdWx0LmdldEFic3RyYWN0RmlsZUJ5UGF0aChjb250ZXh0LnNvdXJjZVBhdGgpXG5cdFx0XHQvLyBsZXQgY2FjaGUgPSBhcHAubWV0YWRhdGFDYWNoZS5nZXRDYWNoZShjb250ZXh0LnNvdXJjZVBhdGgpXG5cdFxuXHRcdFx0Ly8gY2FjaGUuc2VjdGlvbnM/LmZvckVhY2goYXN5bmMgZWxlbWVudCA9PiB7XG5cdFx0XHQvLyBcdGlmKGVsZW1lbnQudHlwZSA9PSBcImNvZGVcIikge1xuXHRcdFx0Ly8gXHRcdGxpbmVTdGFydCA9IGVsZW1lbnQucG9zaXRpb24uc3RhcnQubGluZVxuXHRcdFx0Ly8gXHRcdGxpbmVFbmQgPSBlbGVtZW50LnBvc2l0aW9uLmVuZC5saW5lXG5cdFx0XHQvLyBcdFx0Y29kZUJsb2NrTGluZU51bSA9IGxpbmVFbmQgLSBsaW5lU3RhcnQgLSAxXG5cdFx0XHQvLyBcdFx0cmV0dXJuXG5cdFx0XHQvLyBcdH1cblx0XHRcdC8vIH0pO1xuXHRcdFx0Ly8gbGV0IGZpbGUgPSBhcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKGNvbnRleHQuc291cmNlUGF0aClcblx0XHRcdC8vIGxldCBjYWNoZSA9IGFwcC5tZXRhZGF0YUNhY2hlLmdldENhY2hlKGNvbnRleHQuc291cmNlUGF0aClcblx0XHRcdC8vIGxldCBmaWxlQ29udGVudCA9IGF3YWl0IGFwcC52YXVsdC5jYWNoZWRSZWFkKDxURmlsZT4gZmlsZSlcblx0XHRcdC8vIGxldCBmaWxlQ29udGVudExpbmVzID0gZmlsZUNvbnRlbnQuc3BsaXQoL1xcbi9nKVxuXHRcdH1cblxuXHRcdGxldCBzcGFuID0gY3JlYXRlRWxlbWVudChcInNwYW5cIilcblxuXHRcdGZvcihsZXQgaSA9IDA7IGkgPCBjb2RlQmxvY2tMaW5lTnVtOyBpKyspIHtcblx0XHRcdGxldCBvbmVMaW5lVGV4dFxuXHRcdFx0aWYodmlldyl7XG5cdFx0XHRcdG9uZUxpbmVUZXh0ID0gdmlldy5lZGl0b3IuZ2V0TGluZShjb2RlQmxvY2tJbmZvLmxpbmVTdGFydCArIGkgKyAxKVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly8gb25lTGluZVRleHQgPSBmaWxlQ29udGVudExpbmVzW2xpbmVTdGFydCArIDEgKyBpXVxuXHRcdFx0XHQvLyBsZXQgZmlsZSA9IGFwcC52YXVsdC5nZXRBYnN0cmFjdEZpbGVCeVBhdGgoY29udGV4dC5zb3VyY2VQYXRoKVxuXHRcdFx0XHQvLyBsZXQgY2FjaGUgPSBhcHAubWV0YWRhdGFDYWNoZS5nZXRDYWNoZShjb250ZXh0LnNvdXJjZVBhdGgpXG5cdFx0XHRcdC8vIGxldCBmaWxlQ29udGVudCA9IGF3YWl0IGFwcC52YXVsdC5jYWNoZWRSZWFkKDxURmlsZT4gZmlsZSlcblx0XHRcdFx0Ly8gbGV0IGZpbGVDb250ZW50TGluZXMgPSBmaWxlQ29udGVudC5zcGxpdCgvXFxuL2cpXG5cdFx0XHRcdC8vIG9uZUxpbmVUZXh0ID0gZmlsZUNvbnRlbnRMaW5lc1tjYWNoZS5zZWN0aW9uc11cblx0XHRcdH1cblx0XHRcdHNwYW4uaW5uZXJIVE1MID0gb25lTGluZVRleHQgfHwgXCIwXCJcblxuXHRcdFx0Y29kZUJsb2NrRWwuYXBwZW5kQ2hpbGQoc3Bhbilcblx0XHRcdHNwYW4uc3R5bGUuZGlzcGxheSA9ICdibG9jaydcblxuXHRcdFx0bGV0IGxpbmVIZWlnaHQgPSBzcGFuLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodCArICdweCcgLy8gXHU2RDRCXHU5MUNGXHU2NzJDXHU4ODRDXHU2NTg3XHU1QjU3XHU3Njg0XHU5QUQ4XHU1RUE2XG5cblx0XHRcdC8vIGNvbnNvbGUubG9nKGxpbmVIZWlnaHQgKyAnICAgICcgKyBzcGFuLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoKTtcblx0XHRcdFxuXHRcdFx0bGV0IG51bU9uZUxpbmUgPSBudW1XcmFwPyBudW1XcmFwLmNoaWxkTm9kZXNbaV0gYXMgSFRNTEVsZW1lbnQgOiBudWxsXG5cdFx0XHRsZXQgaGxPbmVMaW5lID0gaGlnaFdyYXA/IGhpZ2hXcmFwLmNoaWxkTm9kZXNbaV0gYXMgSFRNTEVsZW1lbnQgOiBudWxsXG5cblx0XHRcdGlmKG51bU9uZUxpbmUpIG51bU9uZUxpbmUuc3R5bGUuaGVpZ2h0ID0gbGluZUhlaWdodDtcblx0XHRcdGlmKGhsT25lTGluZSkgaGxPbmVMaW5lLnN0eWxlLmhlaWdodCA9IGxpbmVIZWlnaHQ7XG5cblx0XHRcdHNwYW4ucmVtb3ZlKCkgLy8gXHU2RDRCXHU5MUNGXHU1QjhDXHU1NDBFXHU1MjIwXHU2Mzg5XG5cdFx0fVxuXHR9LCAxMDApXG59XG5cbmZ1bmN0aW9uIGV4cG9ydFBERihlbDogSFRNTEVsZW1lbnQsIHBsdWdpbjogQmV0dGVyQ29kZUJsb2NrLCBjb2RlQmxvY2tGaXJzdExpbmVzOiBzdHJpbmdbXSwgY29kZUJsb2NrU2VjdGlvbnM6IFNlY3Rpb25DYWNoZVtdKSB7XG5cdGxldCBjb2RlQmxvY2tzID0gZWwucXVlcnlTZWxlY3RvckFsbCgncHJlID4gY29kZScpXG5cdGNvZGVCbG9ja3MuZm9yRWFjaCgoY29kZUVsbSwga2V5KSA9PiB7XG5cdFx0bGV0IGxhbmdOYW1lID0gXCJcIiwgdGl0bGUgPSBcIlwiLCBoaWdoTGlnaHRMaW5lczogbnVtYmVyW10gPSBbXVxuXHRcdGNvZGVFbG0uY2xhc3NMaXN0LmZvckVhY2godmFsdWUgPT4ge1xuXHRcdFx0aWYoTEFOR19SRUcudGVzdCh2YWx1ZSkpIHtcblx0XHRcdFx0bGFuZ05hbWUgPSB2YWx1ZS5yZXBsYWNlKCdsYW5ndWFnZS0nLCAnJylcblx0XHRcdFx0cmV0dXJuXG5cdFx0XHR9XG5cdFx0fSlcblxuXHRcdGlmKGNvZGVCbG9ja0ZpcnN0TGluZXNba2V5XS5tYXRjaCh0aXRsZVJlZ0V4cCkgIT0gbnVsbCkge1xuXHRcdFx0dGl0bGUgPSBjb2RlQmxvY2tGaXJzdExpbmVzW2tleV0ubWF0Y2godGl0bGVSZWdFeHApWzFdXG5cdFx0fVxuXHRcdGlmKGNvZGVCbG9ja0ZpcnN0TGluZXNba2V5XS5tYXRjaChoaWdoTGlnaHRMaW5lc1JlZ0V4cCkgIT0gbnVsbCkge1xuXHRcdFx0bGV0IGhpZ2hMaWdodExpbmVzSW5mbyA9IGNvZGVCbG9ja0ZpcnN0TGluZXNba2V5XS5tYXRjaChoaWdoTGlnaHRMaW5lc1JlZ0V4cClbMV1cblx0XHRcdGhpZ2hMaWdodExpbmVzID0gYW5hbHlzZUhpZ2hMaWdodExpbmVzKGhpZ2hMaWdodExpbmVzSW5mbylcblx0XHR9XG5cblx0XHRsZXQgbGluZVNpemUgPSBjb2RlQmxvY2tTZWN0aW9uc1trZXldLnBvc2l0aW9uLmVuZC5saW5lIC0gY29kZUJsb2NrU2VjdGlvbnNba2V5XS5wb3NpdGlvbi5zdGFydC5saW5lIC0gMVxuXG5cdFx0bGV0IGNiTWV0YTogQ29kZUJsb2NrTWV0YSA9IHtcblx0XHRcdGxhbmdOYW1lOiBsYW5nTmFtZSxcblx0XHRcdGxpbmVTaXplOiBsaW5lU2l6ZSxcblx0XHRcdHByZTogY29kZUVsbS5wYXJlbnRFbGVtZW50LFxuXHRcdFx0Y29kZTogY29kZUVsbSBhcyBIVE1MRWxlbWVudCxcblx0XHRcdHRpdGxlOiB0aXRsZSxcblx0XHRcdGlzQ29sbGFwc2U6IGZhbHNlLFxuXHRcdFx0ZGl2OiBjb2RlRWxtLnBhcmVudEVsZW1lbnQucGFyZW50RWxlbWVudCxcblx0XHRcdGNvbnRlbnRMaXN0OiBbXSxcblx0XHRcdGhpZ2hMaWdodExpbmVzOiBoaWdoTGlnaHRMaW5lc1xuXHRcdH1cblx0XHRhZGRDb2RlVGl0bGVXcmFwcGVyKHBsdWdpbiwgY29kZUVsbS5wYXJlbnRFbGVtZW50LCBjYk1ldGEpIC8vIFx1NUJGQ1x1NTFGQVx1NTNENlx1NkQ4OFx1NEVFM1x1NzgwMVx1NTc1N1x1NjI5OFx1NTNFMFxuXHRcdGFkZENvZGVUaXRsZShwbHVnaW4sIGNiTWV0YS5wcmUsIGNiTWV0YSlcblx0XHRpZihwbHVnaW4uc2V0dGluZ3Muc2hvd0xpbmVOdW1iZXIpIHtcblx0XHRcdGFkZExpbmVOdW1iZXIocGx1Z2luLCBjYk1ldGEpXG5cdFx0fVxuXHRcdGFkZExpbmVIaWdoTGlnaHQocGx1Z2luLCBjYk1ldGEucHJlLCBjYk1ldGEpXG5cdH0pXG59Il0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBLHNCQUF1TDtBQUl2TCxJQUFNLGVBQWU7QUFDckIsSUFBTSxXQUFXO0FBQ2pCLElBQU0sa0JBQWtCO0FBRXhCLElBQU0sY0FBYztBQUNwQixJQUFNLHVCQUF1QjtBQUM3QixJQUFNLGFBQWE7QUFFbkIsSUFBTSxpQkFBaUI7QUFldkIsSUFBTSxtQkFBNkI7QUFBQSxFQUNsQywyQkFBMkI7QUFBQSxFQUMzQixzQkFBc0I7QUFBQSxFQUN0QixnQkFBZ0I7QUFBQSxFQUNoQixnQkFBZ0I7QUFBQSxFQUVoQixjQUFjO0FBQUEsRUFFZCxnQkFBZ0I7QUFBQSxFQUNoQixrQkFBa0I7QUFBQSxFQUNsQix3QkFBd0I7QUFBQTtBQThCekIsb0NBQTZDLHVCQUFPO0FBQUEsRUFHN0MsU0FBUztBQUFBO0FBQ2QsY0FBUSxJQUFJO0FBQ1osWUFBTSxLQUFLO0FBQ1gsV0FBSyxjQUFjLElBQUksbUJBQW1CLEtBQUssS0FBSztBQUNwRCxXQUFLLDhCQUE4QixDQUFDLElBQUksUUFBUTtBQUMvQyx5QkFBaUIsSUFB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