Created
March 12, 2022 11:26
-
-
Save Mara-Li/e8f8181055658c33c5979304b07abe19 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP | |
if you want to view the source visit the plugins github repository | |
*/ | |
'use strict'; | |
var obsidian = require('obsidian'); | |
/*! ***************************************************************************** | |
Copyright (c) Microsoft Corporation. | |
Permission to use, copy, modify, and/or distribute this software for any | |
purpose with or without fee is hereby granted. | |
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | |
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | |
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | |
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | |
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | |
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |
PERFORMANCE OF THIS SOFTWARE. | |
***************************************************************************** */ | |
function __awaiter(thisArg, _arguments, P, generator) { | |
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | |
return new (P || (P = Promise))(function (resolve, reject) { | |
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | |
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | |
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | |
step((generator = generator.apply(thisArg, _arguments || [])).next()); | |
}); | |
} | |
const path = '.obsidian/plugins/obsidian-icon-folder/icons'; | |
let iconPacks = []; | |
const createIconPackDirectory = (plugin, dir) => __awaiter(void 0, void 0, void 0, function* () { | |
yield createDirectory(plugin, dir); | |
iconPacks.push({ name: dir, icons: [] }); | |
}); | |
const deleteIconPack = (plugin, dir) => __awaiter(void 0, void 0, void 0, function* () { | |
const newIconPacks = iconPacks.filter((iconPack) => iconPack.name !== dir); | |
iconPacks = newIconPacks; | |
yield plugin.app.vault.adapter.rmdir(`${path}/${dir}`, true); | |
}); | |
const createDirectory = (plugin, dir) => __awaiter(void 0, void 0, void 0, function* () { | |
const doesDirExist = yield plugin.app.vault.adapter.exists(`${path}/${dir}`); | |
if (!doesDirExist) { | |
yield plugin.app.vault.adapter.mkdir(`${path}/${dir}`); | |
} | |
}); | |
const createFile = (plugin, iconPackName, filename, content) => __awaiter(void 0, void 0, void 0, function* () { | |
yield plugin.app.vault.adapter.write(`${path}/${iconPackName}/${filename}`, content); | |
}); | |
const createDefaultDirectory = (plugin) => __awaiter(void 0, void 0, void 0, function* () { | |
yield createDirectory(plugin, ''); | |
}); | |
const getAllIconPacks = () => { | |
return iconPacks; | |
}; | |
const getFilesInDirectory = (plugin, dir) => __awaiter(void 0, void 0, void 0, function* () { | |
return (yield plugin.app.vault.adapter.list(dir)).files; | |
}); | |
const svgPathRegex = /<path\s([^>]*)>/g; | |
const svgAttrRegex = /(?:\s*|^)([^= ]*)="([^"]*)"/g; | |
const extractPaths = (content) => { | |
const allPaths = []; | |
while (true) { | |
const svgPathMatches = svgPathRegex.exec(content); | |
const svgPath = svgPathMatches && svgPathMatches[1]; | |
if (!svgPath) { | |
break; | |
} | |
const attrs = {}; | |
while (true) { | |
const svgAttrMatches = svgAttrRegex.exec(svgPath); | |
if (!svgAttrMatches) { | |
break; | |
} | |
attrs[svgAttrMatches[1]] = svgAttrMatches[2]; | |
} | |
if (attrs.fill === 'none') { | |
continue; | |
} | |
allPaths.push(attrs); | |
} | |
return allPaths; | |
}; | |
const validIconName = /^[A-Z]/; | |
const svgViewboxRegex = /viewBox="([^"]*)"/g; | |
const svgContentRegex = /<svg.*>(.*?)<\/svg>/g; | |
const generateIcon = (iconPackName, iconName, content) => { | |
const normalizedName = iconName | |
.split(/[ -]/g) | |
.map((part) => part.charAt(0).toUpperCase() + part.slice(1)) | |
.join(''); | |
if (!validIconName.exec(normalizedName)) { | |
console.log(`skipping icon with invalid name: ${iconName}`); | |
return; | |
} | |
let svgPaths; | |
try { | |
svgPaths = extractPaths(content); | |
} | |
catch (err) { | |
console.log(err); | |
return; | |
} | |
const svgViewbox = content.match(svgViewboxRegex)[0]; | |
const svgContentMatch = content.match(svgContentRegex); | |
const svgContent = svgContentMatch.map((val) => val.replace(/<\/?svg>/g, ''))[0]; | |
const iconPackPrefix = iconPackName.substring(0, 2); | |
const icon = { | |
name: normalizedName.split('.svg')[0], | |
prefix: iconPackPrefix, | |
filename: iconName, | |
svgPath: svgPaths.length === 1 ? svgPaths[0].d : svgPaths, | |
svgContent, | |
svgViewbox, | |
}; | |
return icon; | |
}; | |
const initIconPacks = (plugin) => __awaiter(void 0, void 0, void 0, function* () { | |
yield createDefaultDirectory(plugin); | |
// Load all the custom generated icon packs. | |
const loadedIconPacks = yield plugin.app.vault.adapter.list(path); | |
for (let i = 0; i < loadedIconPacks.folders.length; i++) { | |
const folder = loadedIconPacks.folders[i]; | |
const iconPackRegex = folder.match(new RegExp(path + '/(.*)')); | |
if (iconPackRegex.length > 1) { | |
const iconPackName = iconPackRegex[1]; | |
const icons = yield getFilesInDirectory(plugin, folder); | |
const loadedIcons = []; | |
// Convert files into loaded svgs. | |
for (let j = 0; j < icons.length; j++) { | |
const iconNameRegex = icons[j].match(new RegExp(path + '/' + iconPackName + '/(.*)')); | |
const iconName = iconNameRegex[1]; | |
const iconContent = yield plugin.app.vault.adapter.read(icons[j]); | |
const icon = generateIcon(iconPackName, iconName, iconContent); | |
if (icon) { | |
loadedIcons.push(icon); | |
} | |
} | |
iconPacks.push({ name: iconPackName, icons: loadedIcons }); | |
} | |
} | |
}); | |
const addIconToIconPack = (iconPackName, iconName, iconContent) => { | |
const icon = generateIcon(iconPackName, iconName, iconContent); | |
const iconPack = iconPacks.find((iconPack) => iconPack.name === iconPackName); | |
iconPack.icons.push(icon); | |
}; | |
const getAllLoadedIconNames = () => { | |
return iconPacks.reduce((total, iconPack) => { | |
total.push(...iconPack.icons); | |
return total; | |
}, []); | |
}; | |
const getSvgFromLoadedIcon = (iconName) => { | |
let icon = ''; | |
iconPacks.forEach((iconPack) => { | |
const foundIcon = iconPack.icons.find((icon) => icon.name.toLowerCase() === iconName.toLowerCase()); | |
if (foundIcon) { | |
let fileContent = ''; | |
if (typeof foundIcon.svgPath === 'object') { | |
const svgContent = foundIcon.svgPath.reduce((total, current) => { | |
total += `<path fill="${current.fill}" d="${current.d}" />`; | |
return total; | |
}, ''); | |
fileContent = `<svg width="16" height="16" ${foundIcon.svgViewbox}>${svgContent}</svg>`; | |
} | |
else { | |
fileContent = `<svg width="16" height="16" ${foundIcon.svgPath.includes('fill=') ? '' : 'fill="currentColor"'} ${foundIcon.svgViewbox}><path d="${foundIcon.svgPath}" /></svg>`; | |
} | |
icon = fileContent; | |
return; | |
} | |
}); | |
return icon; | |
}; | |
class ColorPickerComponent extends obsidian.ValueComponent { | |
constructor(containerEl) { | |
super(); | |
this.value = '#000000'; | |
this.containerEl = containerEl; | |
this.inputEl = containerEl.createEl('input'); | |
this.inputEl.type = 'color'; | |
this.inputEl.ariaLabel = 'Click to change the color'; | |
} | |
onChange(callback) { | |
this.inputEl.addEventListener('input', () => { | |
this.setValue(this.inputEl.value); | |
callback(this.getValue()); | |
}); | |
return this; | |
} | |
getValue() { | |
return this.value; | |
} | |
setValue(value) { | |
this.value = value; | |
this.inputEl.value = value; | |
return this; | |
} | |
build() { | |
this.containerEl.appendChild(this.inputEl); | |
return this; | |
} | |
} | |
const DEFAULT_SETTINGS = { | |
fontSize: 16, | |
iconColor: null, | |
recentlyUsedIcons: [], | |
recentlyUsedIconsSize: 5, | |
extraPadding: { | |
top: 2, | |
right: 2, | |
bottom: 2, | |
left: 2, | |
}, | |
}; | |
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; | |
var location = commonjsGlobal.location || {}; | |
/*jslint indent: 2, browser: true, bitwise: true, plusplus: true */ | |
var twemoji = (function ( | |
/*! Copyright Twitter Inc. and other contributors. Licensed under MIT *//* | |
https://github.com/twitter/twemoji/blob/gh-pages/LICENSE | |
*/ | |
// WARNING: this file is generated automatically via | |
// `node scripts/build.js` | |
// please update its `createTwemoji` function | |
// at the bottom of the same file instead. | |
) { | |
/*jshint maxparams:4 */ | |
var | |
// the exported module object | |
twemoji = { | |
///////////////////////// | |
// properties // | |
///////////////////////// | |
// default assets url, by default will be Twitter Inc. CDN | |
base: 'https://twemoji.maxcdn.com/v/13.1.0/', | |
// default assets file extensions, by default '.png' | |
ext: '.png', | |
// default assets/folder size, by default "72x72" | |
// available via Twitter CDN: 72 | |
size: '72x72', | |
// default class name, by default 'emoji' | |
className: 'emoji', | |
// basic utilities / helpers to convert code points | |
// to JavaScript surrogates and vice versa | |
convert: { | |
/** | |
* Given an HEX codepoint, returns UTF16 surrogate pairs. | |
* | |
* @param string generic codepoint, i.e. '1F4A9' | |
* @return string codepoint transformed into utf16 surrogates pair, | |
* i.e. \uD83D\uDCA9 | |
* | |
* @example | |
* twemoji.convert.fromCodePoint('1f1e8'); | |
* // "\ud83c\udde8" | |
* | |
* '1f1e8-1f1f3'.split('-').map(twemoji.convert.fromCodePoint).join('') | |
* // "\ud83c\udde8\ud83c\uddf3" | |
*/ | |
fromCodePoint: fromCodePoint, | |
/** | |
* Given UTF16 surrogate pairs, returns the equivalent HEX codepoint. | |
* | |
* @param string generic utf16 surrogates pair, i.e. \uD83D\uDCA9 | |
* @param string optional separator for double code points, default='-' | |
* @return string utf16 transformed into codepoint, i.e. '1F4A9' | |
* | |
* @example | |
* twemoji.convert.toCodePoint('\ud83c\udde8\ud83c\uddf3'); | |
* // "1f1e8-1f1f3" | |
* | |
* twemoji.convert.toCodePoint('\ud83c\udde8\ud83c\uddf3', '~'); | |
* // "1f1e8~1f1f3" | |
*/ | |
toCodePoint: toCodePoint | |
}, | |
///////////////////////// | |
// methods // | |
///////////////////////// | |
/** | |
* User first: used to remove missing images | |
* preserving the original text intent when | |
* a fallback for network problems is desired. | |
* Automatically added to Image nodes via DOM | |
* It could be recycled for string operations via: | |
* $('img.emoji').on('error', twemoji.onerror) | |
*/ | |
onerror: function onerror() { | |
if (this.parentNode) { | |
this.parentNode.replaceChild(createText(this.alt, false), this); | |
} | |
}, | |
/** | |
* Main method/logic to generate either <img> tags or HTMLImage nodes. | |
* "emojify" a generic text or DOM Element. | |
* | |
* @overloads | |
* | |
* String replacement for `innerHTML` or server side operations | |
* twemoji.parse(string); | |
* twemoji.parse(string, Function); | |
* twemoji.parse(string, Object); | |
* | |
* HTMLElement tree parsing for safer operations over existing DOM | |
* twemoji.parse(HTMLElement); | |
* twemoji.parse(HTMLElement, Function); | |
* twemoji.parse(HTMLElement, Object); | |
* | |
* @param string|HTMLElement the source to parse and enrich with emoji. | |
* | |
* string replace emoji matches with <img> tags. | |
* Mainly used to inject emoji via `innerHTML` | |
* It does **not** parse the string or validate it, | |
* it simply replaces found emoji with a tag. | |
* NOTE: be sure this won't affect security. | |
* | |
* HTMLElement walk through the DOM tree and find emoji | |
* that are inside **text node only** (nodeType === 3) | |
* Mainly used to put emoji in already generated DOM | |
* without compromising surrounding nodes and | |
* **avoiding** the usage of `innerHTML`. | |
* NOTE: Using DOM elements instead of strings should | |
* improve security without compromising too much | |
* performance compared with a less safe `innerHTML`. | |
* | |
* @param Function|Object [optional] | |
* either the callback that will be invoked or an object | |
* with all properties to use per each found emoji. | |
* | |
* Function if specified, this will be invoked per each emoji | |
* that has been found through the RegExp except | |
* those follwed by the invariant \uFE0E ("as text"). | |
* Once invoked, parameters will be: | |
* | |
* iconId:string the lower case HEX code point | |
* i.e. "1f4a9" | |
* | |
* options:Object all info for this parsing operation | |
* | |
* variant:char the optional \uFE0F ("as image") | |
* variant, in case this info | |
* is anyhow meaningful. | |
* By default this is ignored. | |
* | |
* If such callback will return a falsy value instead | |
* of a valid `src` to use for the image, nothing will | |
* actually change for that specific emoji. | |
* | |
* | |
* Object if specified, an object containing the following properties | |
* | |
* callback Function the callback to invoke per each found emoji. | |
* base string the base url, by default twemoji.base | |
* ext string the image extension, by default twemoji.ext | |
* size string the assets size, by default twemoji.size | |
* | |
* @example | |
* | |
* twemoji.parse("I \u2764\uFE0F emoji!"); | |
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"/> emoji! | |
* | |
* | |
* twemoji.parse("I \u2764\uFE0F emoji!", function(iconId, options) { | |
* return '/assets/' + iconId + '.gif'; | |
* }); | |
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"/> emoji! | |
* | |
* | |
* twemoji.parse("I \u2764\uFE0F emoji!", { | |
* size: 72, | |
* callback: function(iconId, options) { | |
* return '/assets/' + options.size + '/' + iconId + options.ext; | |
* } | |
* }); | |
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/72x72/2764.png"/> emoji! | |
* | |
*/ | |
parse: parse, | |
/** | |
* Given a string, invokes the callback argument | |
* per each emoji found in such string. | |
* This is the most raw version used by | |
* the .parse(string) method itself. | |
* | |
* @param string generic string to parse | |
* @param Function a generic callback that will be | |
* invoked to replace the content. | |
* This callback will receive standard | |
* String.prototype.replace(str, callback) | |
* arguments such: | |
* callback( | |
* rawText, // the emoji match | |
* ); | |
* | |
* and others commonly received via replace. | |
*/ | |
replace: replace, | |
/** | |
* Simplify string tests against emoji. | |
* | |
* @param string some text that might contain emoji | |
* @return boolean true if any emoji was found, false otherwise. | |
* | |
* @example | |
* | |
* if (twemoji.test(someContent)) { | |
* console.log("emoji All The Things!"); | |
* } | |
*/ | |
test: test | |
}, | |
// used to escape HTML special chars in attributes | |
escaper = { | |
'&': '&', | |
'<': '<', | |
'>': '>', | |
"'": ''', | |
'"': '"' | |
}, | |
// RegExp based on emoji's official Unicode standards | |
// http://www.unicode.org/Public/UNIDATA/EmojiSources.txt | |
re = /(?:\ud83d\udc68\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffc-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb\udffd-\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb\udffc\udffe\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb-\udffd\udfff]|\ud83e\uddd1\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb-\udffe]|\ud83d\udc68\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc68\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc68\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffe]|\ud83e\uddd1\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffc-\udfff]|\ud83e\uddd1\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb\udffd-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb\udffc\udffe\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb-\udffd\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb-\udffe]|\ud83e\uddd1\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d[\udc68\udc69]|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d[\udc68\udc69]|\ud83e\uddd1\u200d\ud83e\udd1d\u200d\ud83e\uddd1|\ud83d\udc6b\ud83c[\udffb-\udfff]|\ud83d\udc6c\ud83c[\udffb-\udfff]|\ud83d\udc6d\ud83c[\udffb-\udfff]|\ud83d\udc8f\ud83c[\udffb-\udfff]|\ud83d\udc91\ud83c[\udffb-\udfff]|\ud83d[\udc6b-\udc6d\udc8f\udc91])|(?:\ud83d[\udc68\udc69]|\ud83e\uddd1)(?:\ud83c[\udffb-\udfff])?\u200d(?:\u2695\ufe0f|\u2696\ufe0f|\u2708\ufe0f|\ud83c[\udf3e\udf73\udf7c\udf84\udf93\udfa4\udfa8\udfeb\udfed]|\ud83d[\udcbb\udcbc\udd27\udd2c\ude80\ude92]|\ud83e[\uddaf-\uddb3\uddbc\uddbd])|(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75]|\u26f9)((?:\ud83c[\udffb-\udfff]|\ufe0f)\u200d[\u2640\u2642]\ufe0f)|(?:\ud83c[\udfc3\udfc4\udfca]|\ud83d[\udc6e\udc70\udc71\udc73\udc77\udc81\udc82\udc86\udc87\ude45-\ude47\ude4b\ude4d\ude4e\udea3\udeb4-\udeb6]|\ud83e[\udd26\udd35\udd37-\udd39\udd3d\udd3e\uddb8\uddb9\uddcd-\uddcf\uddd4\uddd6-\udddd])(?:\ud83c[\udffb-\udfff])?\u200d[\u2640\u2642]\ufe0f|(?:\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f|\ud83c\udff3\ufe0f\u200d\ud83c\udf08|\ud83d\ude36\u200d\ud83c\udf2b\ufe0f|\u2764\ufe0f\u200d\ud83d\udd25|\u2764\ufe0f\u200d\ud83e\ude79|\ud83c\udff4\u200d\u2620\ufe0f|\ud83d\udc15\u200d\ud83e\uddba|\ud83d\udc3b\u200d\u2744\ufe0f|\ud83d\udc41\u200d\ud83d\udde8|\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc6f\u200d\u2640\ufe0f|\ud83d\udc6f\u200d\u2642\ufe0f|\ud83d\ude2e\u200d\ud83d\udca8|\ud83d\ude35\u200d\ud83d\udcab|\ud83e\udd3c\u200d\u2640\ufe0f|\ud83e\udd3c\u200d\u2642\ufe0f|\ud83e\uddde\u200d\u2640\ufe0f|\ud83e\uddde\u200d\u2642\ufe0f|\ud83e\udddf\u200d\u2640\ufe0f|\ud83e\udddf\u200d\u2642\ufe0f|\ud83d\udc08\u200d\u2b1b)|[#*0-9]\ufe0f?\u20e3|(?:[©®\u2122\u265f]\ufe0f)|(?:\ud83c[\udc04\udd70\udd71\udd7e\udd7f\ude02\ude1a\ude2f\ude37\udf21\udf24-\udf2c\udf36\udf7d\udf96\udf97\udf99-\udf9b\udf9e\udf9f\udfcd\udfce\udfd4-\udfdf\udff3\udff5\udff7]|\ud83d[\udc3f\udc41\udcfd\udd49\udd4a\udd6f\udd70\udd73\udd76-\udd79\udd87\udd8a-\udd8d\udda5\udda8\uddb1\uddb2\uddbc\uddc2-\uddc4\uddd1-\uddd3\udddc-\uddde\udde1\udde3\udde8\uddef\uddf3\uddfa\udecb\udecd-\udecf\udee0-\udee5\udee9\udef0\udef3]|[\u203c\u2049\u2139\u2194-\u2199\u21a9\u21aa\u231a\u231b\u2328\u23cf\u23ed-\u23ef\u23f1\u23f2\u23f8-\u23fa\u24c2\u25aa\u25ab\u25b6\u25c0\u25fb-\u25fe\u2600-\u2604\u260e\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262a\u262e\u262f\u2638-\u263a\u2640\u2642\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267b\u267f\u2692-\u2697\u2699\u269b\u269c\u26a0\u26a1\u26a7\u26aa\u26ab\u26b0\u26b1\u26bd\u26be\u26c4\u26c5\u26c8\u26cf\u26d1\u26d3\u26d4\u26e9\u26ea\u26f0-\u26f5\u26f8\u26fa\u26fd\u2702\u2708\u2709\u270f\u2712\u2714\u2716\u271d\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u2764\u27a1\u2934\u2935\u2b05-\u2b07\u2b1b\u2b1c\u2b50\u2b55\u3030\u303d\u3297\u3299])(?:\ufe0f|(?!\ufe0e))|(?:(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75\udd90]|[\u261d\u26f7\u26f9\u270c\u270d])(?:\ufe0f|(?!\ufe0e))|(?:\ud83c[\udf85\udfc2-\udfc4\udfc7\udfca]|\ud83d[\udc42\udc43\udc46-\udc50\udc66-\udc69\udc6e\udc70-\udc78\udc7c\udc81-\udc83\udc85-\udc87\udcaa\udd7a\udd95\udd96\ude45-\ude47\ude4b-\ude4f\udea3\udeb4-\udeb6\udec0\udecc]|\ud83e[\udd0c\udd0f\udd18-\udd1c\udd1e\udd1f\udd26\udd30-\udd39\udd3d\udd3e\udd77\uddb5\uddb6\uddb8\uddb9\uddbb\uddcd-\uddcf\uddd1-\udddd]|[\u270a\u270b]))(?:\ud83c[\udffb-\udfff])?|(?:\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f|\ud83c\udde6\ud83c[\udde8-\uddec\uddee\uddf1\uddf2\uddf4\uddf6-\uddfa\uddfc\uddfd\uddff]|\ud83c\udde7\ud83c[\udde6\udde7\udde9-\uddef\uddf1-\uddf4\uddf6-\uddf9\uddfb\uddfc\uddfe\uddff]|\ud83c\udde8\ud83c[\udde6\udde8\udde9\uddeb-\uddee\uddf0-\uddf5\uddf7\uddfa-\uddff]|\ud83c\udde9\ud83c[\uddea\uddec\uddef\uddf0\uddf2\uddf4\uddff]|\ud83c\uddea\ud83c[\udde6\udde8\uddea\uddec\udded\uddf7-\uddfa]|\ud83c\uddeb\ud83c[\uddee-\uddf0\uddf2\uddf4\uddf7]|\ud83c\uddec\ud83c[\udde6\udde7\udde9-\uddee\uddf1-\uddf3\uddf5-\uddfa\uddfc\uddfe]|\ud83c\udded\ud83c[\uddf0\uddf2\uddf3\uddf7\uddf9\uddfa]|\ud83c\uddee\ud83c[\udde8-\uddea\uddf1-\uddf4\uddf6-\uddf9]|\ud83c\uddef\ud83c[\uddea\uddf2\uddf4\uddf5]|\ud83c\uddf0\ud83c[\uddea\uddec-\uddee\uddf2\uddf3\uddf5\uddf7\uddfc\uddfe\uddff]|\ud83c\uddf1\ud83c[\udde6-\udde8\uddee\uddf0\uddf7-\uddfb\uddfe]|\ud83c\uddf2\ud83c[\udde6\udde8-\udded\uddf0-\uddff]|\ud83c\uddf3\ud83c[\udde6\udde8\uddea-\uddec\uddee\uddf1\uddf4\uddf5\uddf7\uddfa\uddff]|\ud83c\uddf4\ud83c\uddf2|\ud83c\uddf5\ud83c[\udde6\uddea-\udded\uddf0-\uddf3\uddf7-\uddf9\uddfc\uddfe]|\ud83c\uddf6\ud83c\udde6|\ud83c\uddf7\ud83c[\uddea\uddf4\uddf8\uddfa\uddfc]|\ud83c\uddf8\ud83c[\udde6-\uddea\uddec-\uddf4\uddf7-\uddf9\uddfb\uddfd-\uddff]|\ud83c\uddf9\ud83c[\udde6\udde8\udde9\uddeb-\udded\uddef-\uddf4\uddf7\uddf9\uddfb\uddfc\uddff]|\ud83c\uddfa\ud83c[\udde6\uddec\uddf2\uddf3\uddf8\uddfe\uddff]|\ud83c\uddfb\ud83c[\udde6\udde8\uddea\uddec\uddee\uddf3\uddfa]|\ud83c\uddfc\ud83c[\uddeb\uddf8]|\ud83c\uddfd\ud83c\uddf0|\ud83c\uddfe\ud83c[\uddea\uddf9]|\ud83c\uddff\ud83c[\udde6\uddf2\uddfc]|\ud83c[\udccf\udd8e\udd91-\udd9a\udde6-\uddff\ude01\ude32-\ude36\ude38-\ude3a\ude50\ude51\udf00-\udf20\udf2d-\udf35\udf37-\udf7c\udf7e-\udf84\udf86-\udf93\udfa0-\udfc1\udfc5\udfc6\udfc8\udfc9\udfcf-\udfd3\udfe0-\udff0\udff4\udff8-\udfff]|\ud83d[\udc00-\udc3e\udc40\udc44\udc45\udc51-\udc65\udc6a\udc6f\udc79-\udc7b\udc7d-\udc80\udc84\udc88-\udc8e\udc90\udc92-\udca9\udcab-\udcfc\udcff-\udd3d\udd4b-\udd4e\udd50-\udd67\udda4\uddfb-\ude44\ude48-\ude4a\ude80-\udea2\udea4-\udeb3\udeb7-\udebf\udec1-\udec5\uded0-\uded2\uded5-\uded7\udeeb\udeec\udef4-\udefc\udfe0-\udfeb]|\ud83e[\udd0d\udd0e\udd10-\udd17\udd1d\udd20-\udd25\udd27-\udd2f\udd3a\udd3c\udd3f-\udd45\udd47-\udd76\udd78\udd7a-\uddb4\uddb7\uddba\uddbc-\uddcb\uddd0\uddde-\uddff\ude70-\ude74\ude78-\ude7a\ude80-\ude86\ude90-\udea8\udeb0-\udeb6\udec0-\udec2\uded0-\uded6]|[\u23e9-\u23ec\u23f0\u23f3\u267e\u26ce\u2705\u2728\u274c\u274e\u2753-\u2755\u2795-\u2797\u27b0\u27bf\ue50a])|\ufe0f/g, | |
// avoid runtime RegExp creation for not so smart, | |
// not JIT based, and old browsers / engines | |
UFE0Fg = /\uFE0F/g, | |
// avoid using a string literal like '\u200D' here because minifiers expand it inline | |
U200D = String.fromCharCode(0x200D), | |
// used to find HTML special chars in attributes | |
rescaper = /[&<>'"]/g, | |
// nodes with type 1 which should **not** be parsed | |
shouldntBeParsed = /^(?:iframe|noframes|noscript|script|select|style|textarea)$/, | |
// just a private shortcut | |
fromCharCode = String.fromCharCode; | |
return twemoji; | |
///////////////////////// | |
// private functions // | |
// declaration // | |
///////////////////////// | |
/** | |
* Shortcut to create text nodes | |
* @param string text used to create DOM text node | |
* @return Node a DOM node with that text | |
*/ | |
function createText(text, clean) { | |
return document.createTextNode(clean ? text.replace(UFE0Fg, '') : text); | |
} | |
/** | |
* Utility function to escape html attribute text | |
* @param string text use in HTML attribute | |
* @return string text encoded to use in HTML attribute | |
*/ | |
function escapeHTML(s) { | |
return s.replace(rescaper, replacer); | |
} | |
/** | |
* Default callback used to generate emoji src | |
* based on Twitter CDN | |
* @param string the emoji codepoint string | |
* @param string the default size to use, i.e. "36x36" | |
* @return string the image source to use | |
*/ | |
function defaultImageSrcGenerator(icon, options) { | |
return ''.concat(options.base, options.size, '/', icon, options.ext); | |
} | |
/** | |
* Given a generic DOM nodeType 1, walk through all children | |
* and store every nodeType 3 (#text) found in the tree. | |
* @param Element a DOM Element with probably some text in it | |
* @param Array the list of previously discovered text nodes | |
* @return Array same list with new discovered nodes, if any | |
*/ | |
function grabAllTextNodes(node, allText) { | |
var | |
childNodes = node.childNodes, | |
length = childNodes.length, | |
subnode, | |
nodeType; | |
while (length--) { | |
subnode = childNodes[length]; | |
nodeType = subnode.nodeType; | |
// parse emoji only in text nodes | |
if (nodeType === 3) { | |
// collect them to process emoji later | |
allText.push(subnode); | |
} | |
// ignore all nodes that are not type 1, that are svg, or that | |
// should not be parsed as script, style, and others | |
else if (nodeType === 1 && !('ownerSVGElement' in subnode) && | |
!shouldntBeParsed.test(subnode.nodeName.toLowerCase())) { | |
grabAllTextNodes(subnode, allText); | |
} | |
} | |
return allText; | |
} | |
/** | |
* Used to both remove the possible variant | |
* and to convert utf16 into code points. | |
* If there is a zero-width-joiner (U+200D), leave the variants in. | |
* @param string the raw text of the emoji match | |
* @return string the code point | |
*/ | |
function grabTheRightIcon(rawText) { | |
// if variant is present as \uFE0F | |
return toCodePoint(rawText.indexOf(U200D) < 0 ? | |
rawText.replace(UFE0Fg, '') : | |
rawText | |
); | |
} | |
/** | |
* DOM version of the same logic / parser: | |
* emojify all found sub-text nodes placing images node instead. | |
* @param Element generic DOM node with some text in some child node | |
* @param Object options containing info about how to parse | |
* | |
* .callback Function the callback to invoke per each found emoji. | |
* .base string the base url, by default twemoji.base | |
* .ext string the image extension, by default twemoji.ext | |
* .size string the assets size, by default twemoji.size | |
* | |
* @return Element same generic node with emoji in place, if any. | |
*/ | |
function parseNode(node, options) { | |
var | |
allText = grabAllTextNodes(node, []), | |
length = allText.length, | |
attrib, | |
attrname, | |
modified, | |
fragment, | |
subnode, | |
text, | |
match, | |
i, | |
index, | |
img, | |
rawText, | |
iconId, | |
src; | |
while (length--) { | |
modified = false; | |
fragment = document.createDocumentFragment(); | |
subnode = allText[length]; | |
text = subnode.nodeValue; | |
i = 0; | |
while ((match = re.exec(text))) { | |
index = match.index; | |
if (index !== i) { | |
fragment.appendChild( | |
createText(text.slice(i, index), true) | |
); | |
} | |
rawText = match[0]; | |
iconId = grabTheRightIcon(rawText); | |
i = index + rawText.length; | |
src = options.callback(iconId, options); | |
if (iconId && src) { | |
img = new Image(); | |
img.onerror = options.onerror; | |
img.setAttribute('draggable', 'false'); | |
attrib = options.attributes(rawText, iconId); | |
for (attrname in attrib) { | |
if ( | |
attrib.hasOwnProperty(attrname) && | |
// don't allow any handlers to be set + don't allow overrides | |
attrname.indexOf('on') !== 0 && | |
!img.hasAttribute(attrname) | |
) { | |
img.setAttribute(attrname, attrib[attrname]); | |
} | |
} | |
img.className = options.className; | |
img.alt = rawText; | |
img.src = src; | |
modified = true; | |
fragment.appendChild(img); | |
} | |
if (!img) fragment.appendChild(createText(rawText, false)); | |
img = null; | |
} | |
// is there actually anything to replace in here ? | |
if (modified) { | |
// any text left to be added ? | |
if (i < text.length) { | |
fragment.appendChild( | |
createText(text.slice(i), true) | |
); | |
} | |
// replace the text node only, leave intact | |
// anything else surrounding such text | |
subnode.parentNode.replaceChild(fragment, subnode); | |
} | |
} | |
return node; | |
} | |
/** | |
* String/HTML version of the same logic / parser: | |
* emojify a generic text placing images tags instead of surrogates pair. | |
* @param string generic string with possibly some emoji in it | |
* @param Object options containing info about how to parse | |
* | |
* .callback Function the callback to invoke per each found emoji. | |
* .base string the base url, by default twemoji.base | |
* .ext string the image extension, by default twemoji.ext | |
* .size string the assets size, by default twemoji.size | |
* | |
* @return the string with <img tags> replacing all found and parsed emoji | |
*/ | |
function parseString(str, options) { | |
return replace(str, function (rawText) { | |
var | |
ret = rawText, | |
iconId = grabTheRightIcon(rawText), | |
src = options.callback(iconId, options), | |
attrib, | |
attrname; | |
if (iconId && src) { | |
// recycle the match string replacing the emoji | |
// with its image counter part | |
ret = '<img '.concat( | |
'class="', options.className, '" ', | |
'draggable="false" ', | |
// needs to preserve user original intent | |
// when variants should be copied and pasted too | |
'alt="', | |
rawText, | |
'"', | |
' src="', | |
src, | |
'"' | |
); | |
attrib = options.attributes(rawText, iconId); | |
for (attrname in attrib) { | |
if ( | |
attrib.hasOwnProperty(attrname) && | |
// don't allow any handlers to be set + don't allow overrides | |
attrname.indexOf('on') !== 0 && | |
ret.indexOf(' ' + attrname + '=') === -1 | |
) { | |
ret = ret.concat(' ', attrname, '="', escapeHTML(attrib[attrname]), '"'); | |
} | |
} | |
ret = ret.concat('/>'); | |
} | |
return ret; | |
}); | |
} | |
/** | |
* Function used to actually replace HTML special chars | |
* @param string HTML special char | |
* @return string encoded HTML special char | |
*/ | |
function replacer(m) { | |
return escaper[m]; | |
} | |
/** | |
* Default options.attribute callback | |
* @return null | |
*/ | |
function returnNull() { | |
return null; | |
} | |
/** | |
* Given a generic value, creates its squared counterpart if it's a number. | |
* As example, number 36 will return '36x36'. | |
* @param any a generic value. | |
* @return any a string representing asset size, i.e. "36x36" | |
* only in case the value was a number. | |
* Returns initial value otherwise. | |
*/ | |
function toSizeSquaredAsset(value) { | |
return typeof value === 'number' ? | |
value + 'x' + value : | |
value; | |
} | |
///////////////////////// | |
// exported functions // | |
// declaration // | |
///////////////////////// | |
function fromCodePoint(codepoint) { | |
var code = typeof codepoint === 'string' ? | |
parseInt(codepoint, 16) : codepoint; | |
if (code < 0x10000) { | |
return fromCharCode(code); | |
} | |
code -= 0x10000; | |
return fromCharCode( | |
0xD800 + (code >> 10), | |
0xDC00 + (code & 0x3FF) | |
); | |
} | |
function parse(what, how) { | |
if (!how || typeof how === 'function') { | |
how = {callback: how}; | |
} | |
// if first argument is string, inject html <img> tags | |
// otherwise use the DOM tree and parse text nodes only | |
return (typeof what === 'string' ? parseString : parseNode)(what, { | |
callback: how.callback || defaultImageSrcGenerator, | |
attributes: typeof how.attributes === 'function' ? how.attributes : returnNull, | |
base: typeof how.base === 'string' ? how.base : twemoji.base, | |
ext: how.ext || twemoji.ext, | |
size: how.folder || toSizeSquaredAsset(how.size || twemoji.size), | |
className: how.className || twemoji.className, | |
onerror: how.onerror || twemoji.onerror | |
}); | |
} | |
function replace(text, callback) { | |
return String(text).replace(re, callback); | |
} | |
function test(text) { | |
// IE6 needs a reset before too | |
re.lastIndex = 0; | |
var result = re.test(text); | |
re.lastIndex = 0; | |
return result; | |
} | |
function toCodePoint(unicodeSurrogates, sep) { | |
var | |
r = [], | |
c = 0, | |
p = 0, | |
i = 0; | |
while (i < unicodeSurrogates.length) { | |
c = unicodeSurrogates.charCodeAt(i++); | |
if (p) { | |
r.push((0x10000 + ((p - 0xD800) << 10) + (c - 0xDC00)).toString(16)); | |
p = 0; | |
} else if (0xD800 <= c && c <= 0xDBFF) { | |
p = c; | |
} else { | |
r.push(c.toString(16)); | |
} | |
} | |
return r.join(sep || '-'); | |
} | |
}()); | |
if (!location.protocol) { | |
twemoji.base = twemoji.base.replace(/^http:/, ""); | |
} | |
var twemoji_npm = twemoji; | |
/** | |
* This function returns all enabled icons. | |
* | |
* For example: if `Remixicons Fill` and `Fontawesome Fill` is activated, it will return all these icons. | |
* | |
* @public | |
* @param {IconFolderPlugin} plugin - The main plugin file. | |
* @returns {string[]} The enabled icons. | |
*/ | |
const getEnabledIcons = (plugin) => { | |
plugin.getSettings(); | |
/*const icons = transformedIcons.remixIcons.filter((key) => { | |
return mapRemixicons(key, settings); | |
}); | |
if (settings.enableFontawesomeFill) { | |
icons.push(...transformedIcons.faFill); | |
} | |
if (settings.enableFontawesomeLine) { | |
icons.push(...transformedIcons.faLine); | |
} | |
if (settings.enableFontawesomeBrands) { | |
icons.push(...transformedIcons.faBrands); | |
} | |
if (settings.enableDevicons) { | |
icons.push(...transformedIcons.deviconIcons); | |
}*/ | |
return getAllLoadedIconNames(); | |
}; | |
/** | |
* This function transforms an icon that includes a prefix and returns the correct svg string. | |
* | |
* For example: This input: `RiAB` will return only `AB` as a svg. | |
* | |
* @public | |
* @param {string} name - The icon name. | |
* @returns {string | null} The transformed svg or null if it cannot find any iconpack. | |
*/ | |
const getIcon = (name) => { | |
return getSvgFromLoadedIcon(name); | |
}; | |
/** | |
* This function returns the svg string with the user defined css settings. | |
* It handles from the settings the `padding`, `color`, and `size`. | |
* | |
* In addition, this function manipulates the passed element with the user defined setting `padding`. | |
* | |
* @public | |
* @param {IconFolderPlugin} plugin - The main plugin. | |
* @param {string} icon - The to be styled icon. | |
* @param {HTMLElement} el - The element that will include the padding from the user settings. | |
* @returns {string} The svg with the customized css settings. | |
*/ | |
const customizeIconStyle = (plugin, icon, el) => { | |
var _a, _b, _c, _d; | |
// Allow custom font size | |
const sizeRe = new RegExp(/width="\d+" height="\d+"/g); | |
if (icon.match(sizeRe)) { | |
icon = icon.replace(sizeRe, `width="${plugin.getSettings().fontSize}" height="${plugin.getSettings().fontSize}"`); | |
} | |
else { | |
// If match is null, it should be an image. | |
const sizeRe = new RegExp(/width="\d+px" height="\d+px"/g); | |
icon = icon.replace(sizeRe, `width="${plugin.getSettings().fontSize}px" height="${plugin.getSettings().fontSize}px"`); | |
} | |
// Allow custom icon color | |
const colorRe = new RegExp(/fill="(\w|#)+"/g); | |
const colorMatch = icon.match(colorRe); | |
if (colorMatch) { | |
colorMatch.forEach((color) => { | |
var _a; | |
if (color.contains('currentColor')) { | |
icon = icon.replace(color, `fill="${(_a = plugin.getSettings().iconColor) !== null && _a !== void 0 ? _a : 'currentColor'}"`); | |
} | |
}); | |
} | |
// Change padding of icon | |
if (plugin.getSettings().extraPadding) { | |
el.style.padding = `${(_a = plugin.getSettings().extraPadding.top) !== null && _a !== void 0 ? _a : 2}px ${(_b = plugin.getSettings().extraPadding.right) !== null && _b !== void 0 ? _b : 2}px ${(_c = plugin.getSettings().extraPadding.bottom) !== null && _c !== void 0 ? _c : 2}px ${(_d = plugin.getSettings().extraPadding.left) !== null && _d !== void 0 ? _d : 2}px`; | |
} | |
return icon; | |
}; | |
/** | |
* This function adds the icons to the DOM. | |
* For that, it will create a `div` element with the class `obsidian-icon-folder-icon` that will be customized based on the user settings. | |
* | |
* @public | |
* @param {IconFolderPlugin} plugin - The main plugin. | |
* @param {[string, string | FolderIconObject][]} data - The data that includes the icons. | |
* @param {WeakMap<ExplorerLeaf, boolean>} registeredFileExplorers - The already registered file explorers. | |
*/ | |
const addIconsToDOM = (plugin, data, registeredFileExplorers, callback) => { | |
const fileExplorers = plugin.app.workspace.getLeavesOfType('file-explorer'); | |
fileExplorers.forEach((fileExplorer) => { | |
if (registeredFileExplorers.has(fileExplorer.view)) { | |
return; | |
} | |
registeredFileExplorers.add(fileExplorer.view); | |
// create a map with registered file paths to have constant look up time | |
const registeredFilePaths = {}; | |
data.forEach(([path]) => { | |
registeredFilePaths[path] = true; | |
}); | |
data.forEach(([dataPath, value]) => { | |
const fileItem = fileExplorer.view.fileItems[dataPath]; | |
if (fileItem) { | |
const titleEl = fileItem.titleEl; | |
const titleInnerEl = fileItem.titleInnerEl; | |
// needs to check because of the refreshing the plugin will duplicate all the icons | |
if (titleEl.children.length === 2 || titleEl.children.length === 1) { | |
const iconName = typeof value === 'string' ? value : value.iconName; | |
if (iconName) { | |
const existingIcon = titleEl.querySelector('.obsidian-icon-folder-icon'); | |
if (existingIcon) { | |
existingIcon.remove(); | |
} | |
const iconNode = titleEl.createDiv(); | |
iconNode.classList.add('obsidian-icon-folder-icon'); | |
insertIconToNode(plugin, iconName, iconNode); | |
titleEl.insertBefore(iconNode, titleInnerEl); | |
} | |
if (typeof value === 'object' && value.inheritanceIcon) { | |
const files = plugin.app.vault.getFiles().filter((f) => f.path.includes(dataPath)); | |
const inheritanceIconName = value.inheritanceIcon; | |
files.forEach((f) => { | |
if (!registeredFilePaths[f.path]) { | |
const inheritanceFileItem = fileExplorer.view.fileItems[f.path]; | |
const iconNode = inheritanceFileItem.titleEl.createDiv(); | |
iconNode.classList.add('obsidian-icon-folder-icon'); | |
insertIconToNode(plugin, inheritanceIconName, iconNode); | |
inheritanceFileItem.titleEl.insertBefore(iconNode, inheritanceFileItem.titleInnerEl); | |
} | |
}); | |
} | |
} | |
} | |
}); | |
if (callback) { | |
callback(); | |
} | |
}); | |
}; | |
const addInheritanceIconToFile = (plugin, registeredFileExplorers, filePath, iconName) => { | |
const fileExplorers = plugin.app.workspace.getLeavesOfType('file-explorer'); | |
fileExplorers.forEach((fileExplorer) => { | |
if (registeredFileExplorers.has(fileExplorer.view)) { | |
const fileItem = fileExplorer.view.fileItems[filePath]; | |
if (fileItem) { | |
const iconNode = fileItem.titleEl.createDiv(); | |
iconNode.classList.add('obsidian-icon-folder-icon'); | |
insertIconToNode(plugin, iconName, iconNode); | |
fileItem.titleEl.insertBefore(iconNode, fileItem.titleInnerEl); | |
} | |
} | |
}); | |
}; | |
/** | |
* This function refreshes the icon style. | |
* For that, it will manipulate the `innerHTML` of the icon and will customize the style. | |
* | |
* @public | |
* @param {IconFolderPlugin} plugin - The main plugin. | |
*/ | |
const refreshIconStyle = (plugin) => { | |
const data = Object.entries(plugin.getData()); | |
const fileExplorers = plugin.app.workspace.getLeavesOfType('file-explorer'); | |
fileExplorers.forEach((fileExplorer) => { | |
data.forEach(([key]) => { | |
const fileItem = fileExplorer.view.fileItems[key]; | |
if (fileItem) { | |
const titleEl = fileItem.titleEl; | |
const iconNode = titleEl.querySelector('.obsidian-icon-folder-icon'); | |
iconNode.innerHTML = customizeIconStyle(plugin, iconNode.innerHTML, iconNode); | |
} | |
}); | |
}); | |
}; | |
/** | |
* This function removes the icon node from the DOM based on the passed in path. | |
* | |
* @public | |
* @param {string} path - The path toe the to be removed DOM element. | |
*/ | |
const removeFromDOM = (path) => { | |
const node = document.querySelector(`[data-path="${path}"]`); | |
if (!node) { | |
console.error('element with data path not found', path); | |
return; | |
} | |
const iconNode = node.querySelector('.obsidian-icon-folder-icon'); | |
if (!iconNode) { | |
return; | |
} | |
iconNode.remove(); | |
}; | |
/** | |
* This function adds an icon to the DOM based on a specific path. | |
* In addition, before added to the DOM, it will customize the icon style. | |
* | |
* @public | |
* @param {IconFolderPlugin} plugin - The main plugin. | |
* @param {string} path - The path in the DOM where the icon will be added. | |
* @param {string} icon - The icon that will be added to the DOM - can be an icon id or codepoint for twemoji. | |
*/ | |
const addToDOM = (plugin, path, icon) => { | |
if (plugin.getData()[path]) { | |
removeFromDOM(path); | |
} | |
const node = document.querySelector(`[data-path="${path}"]`); | |
if (!node) { | |
console.error('element with data path not found', path); | |
return; | |
} | |
let titleNode = node.querySelector('.nav-folder-title-content'); | |
if (!titleNode) { | |
titleNode = node.querySelector('.nav-file-title-content'); | |
if (!titleNode) { | |
console.error('element with title not found'); | |
return; | |
} | |
} | |
// check if there is a possible inheritance icon in the DOM | |
const possibleInheritanceIcon = node.querySelector('.obsidian-icon-folder-icon'); | |
if (possibleInheritanceIcon) { | |
possibleInheritanceIcon.remove(); | |
} | |
const iconNode = document.createElement('div'); | |
iconNode.classList.add('obsidian-icon-folder-icon'); | |
insertIconToNode(plugin, icon, iconNode); | |
node.insertBefore(iconNode, titleNode); | |
}; | |
/** | |
* This function inserts a specific icon into the specified node. | |
* | |
* @param {IconFolderPlugin} plugin - The main plugin. | |
* @param {string} icon - The icon string (can be an icon id or a unicode for twemoji). | |
* @param {HTMLElement} node - The element where the icon will be inserted. | |
*/ | |
const insertIconToNode = (plugin, icon, node) => { | |
const possibleIcon = getIcon(icon); | |
if (possibleIcon) { | |
node.innerHTML = customizeIconStyle(plugin, possibleIcon, node); | |
} | |
else { | |
const emoji = twemoji_npm.parse(icon, { | |
folder: 'svg', | |
ext: '.svg', | |
attributes: () => ({ | |
width: '16px', | |
height: '16px', | |
}), | |
}); | |
node.innerHTML = customizeIconStyle(plugin, emoji, node); | |
} | |
}; | |
/** | |
* This function will add inheritance functionality to a specific folder. | |
* It will add the inheritance icon to all child files. | |
* | |
* @param {IconFolderPlugin} plugin - The main plugin. | |
* @param {string} folderPath - The path in the DOM where the icon will be added. | |
*/ | |
const addInheritanceForFolder = (plugin, folderPath) => { | |
const folder = plugin.getData()[folderPath]; | |
if (!folder || typeof folder !== 'object') { | |
return; | |
} | |
// add icons for all the child files | |
const files = plugin.app.vault.getFiles().filter((f) => f.path.includes(folderPath)); | |
files.forEach((f) => { | |
if (plugin.getData()[f.path]) { | |
removeFromDOM(f.path); | |
plugin.removeFolderIcon(f.path); | |
} | |
addToDOM(plugin, f.path, folder.inheritanceIcon); | |
}); | |
}; | |
/** | |
* This function removes inheritance from a folder. | |
* It will delete all the icons in the sub files of this folder. | |
* | |
* @param {IconFolderPlugin} plugin - The main plugin. | |
* @param {string} folderPath - The path in the DOM where the icon will be added. | |
*/ | |
const removeInheritanceForFolder = (plugin, folderPath) => { | |
const folder = plugin.getData()[folderPath]; | |
if (!folder || typeof folder !== 'object') { | |
return; | |
} | |
// remove icons from all the child files | |
const files = plugin.app.vault.getFiles().filter((f) => f.path.includes(folderPath)); | |
files.forEach((f) => { | |
// when the file path is not registered in the data it should remove the icon | |
if (!plugin.getData()[f.path]) { | |
removeFromDOM(f.path); | |
} | |
}); | |
}; | |
const isEmoji = (str) => { | |
const ranges = [ | |
'(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32-\ude3a]|[\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])', // U+1F680 to U+1F6FF | |
]; | |
if (str.match(ranges.join('|'))) { | |
return true; | |
} | |
else { | |
return false; | |
} | |
}; | |
class IconFolderSettingsTab extends obsidian.PluginSettingTab { | |
constructor(app, plugin) { | |
super(app, plugin); | |
this.plugin = plugin; | |
this.dragOverElement = document.createElement('div'); | |
this.dragOverElement.addClass('obsidian-icon-folder-dragover-el'); | |
this.dragOverElement.style.display = 'hidden'; | |
this.dragOverElement.innerHTML = '<p>Drop to add icon.</p>'; | |
} | |
normalizeIconPackName(value) { | |
return value.toLowerCase().replace(/\s/g, '-'); | |
} | |
display() { | |
var _a, _b, _c; | |
const { containerEl } = this; | |
containerEl.empty(); | |
containerEl.createEl('h2', { text: 'Icon Folder Settings' }); | |
new obsidian.Setting(containerEl) | |
.setName('Recently used Icons limit') | |
.setDesc('Change the limit for the recently used icons displayed in the icon modal.') | |
.addSlider((slider) => { | |
var _a; | |
slider | |
.setLimits(1, 15, 1) | |
.setDynamicTooltip() | |
.setValue((_a = this.plugin.getSettings().recentlyUsedIconsSize) !== null && _a !== void 0 ? _a : DEFAULT_SETTINGS.recentlyUsedIconsSize) | |
.onChange((val) => __awaiter(this, void 0, void 0, function* () { | |
this.plugin.getSettings().recentlyUsedIconsSize = val; | |
yield this.plugin.checkRecentlyUsedIcons(); | |
yield this.plugin.saveIconFolderData(); | |
})); | |
}); | |
containerEl.createEl('h3', { text: 'Icon Packs' }); | |
new obsidian.Setting(containerEl) | |
.setName('Add custom icon pack') | |
.setDesc('Add a custom icon pack') | |
.addText((text) => { | |
text.setPlaceholder('Your icon pack name'); | |
this.textComponent = text; | |
}) | |
.addButton((btn) => { | |
btn.setButtonText('Add icon pack'); | |
btn.buttonEl.style.marginLeft = '12px'; | |
btn.onClick(() => __awaiter(this, void 0, void 0, function* () { | |
const name = this.textComponent.getValue(); | |
if (name.length === 0) { | |
return; | |
} | |
yield createIconPackDirectory(this.plugin, this.normalizeIconPackName(this.textComponent.getValue())); | |
this.textComponent.setValue(''); | |
this.display(); | |
new obsidian.Notice('Icon pack successfully created.'); | |
})); | |
}); | |
getAllIconPacks().forEach((iconPack) => { | |
const iconPackSetting = new obsidian.Setting(containerEl) | |
.setName(iconPack.name) | |
.setDesc(`Total icons: ${iconPack.icons.length}`); | |
iconPackSetting.addButton((btn) => { | |
btn.setIcon('create-new'); | |
btn.setTooltip('Add an icon'); | |
btn.onClick(() => { | |
const fileSelector = document.createElement('input'); | |
fileSelector.setAttribute('type', 'file'); | |
fileSelector.setAttribute('multiple', 'multiple'); | |
fileSelector.setAttribute('accept', '.svg'); | |
fileSelector.click(); | |
fileSelector.onchange = (e) => { | |
const target = e.target; | |
for (let i = 0; i < target.files.length; i++) { | |
const file = target.files[i]; | |
this.readFile(file, (content) => __awaiter(this, void 0, void 0, function* () { | |
yield createFile(this.plugin, iconPack.name, file.name, content); | |
addIconToIconPack(iconPack.name, file.name, content); | |
iconPackSetting.setDesc(`Total icons: ${iconPack.icons.length} (added: ${file.name})`); | |
})); | |
} | |
new obsidian.Notice('Icons successfully added.'); | |
}; | |
}); | |
}); | |
iconPackSetting.addButton((btn) => { | |
btn.setIcon('trash'); | |
btn.setTooltip('Remove the icon pack'); | |
btn.onClick(() => __awaiter(this, void 0, void 0, function* () { | |
yield deleteIconPack(this.plugin, iconPack.name); | |
this.display(); | |
new obsidian.Notice('Icon pack successfully deleted.'); | |
})); | |
}); | |
['dragenter', 'dragover', 'dragleave', 'drop'].forEach((event) => { | |
iconPackSetting.settingEl.addEventListener(event, this.preventDefaults, false); | |
}); | |
['dragenter', 'dragover'].forEach((event) => { | |
iconPackSetting.settingEl.addEventListener(event, (event) => this.highlight(event.currentTarget, iconPackSetting.settingEl), false); | |
}); | |
['dragleave', 'drop'].forEach((event) => { | |
iconPackSetting.settingEl.addEventListener(event, (event) => this.unhighlight(event.currentTarget, iconPackSetting.settingEl), false); | |
}); | |
iconPackSetting.settingEl.addEventListener('drop', (event) => { | |
const files = event.dataTransfer.files; | |
let successful = false; | |
for (let i = 0; i < files.length; i++) { | |
const file = files[i]; | |
if (file.type !== 'image/svg+xml') { | |
new obsidian.Notice(`File ${file.name} is not a XML file.`); | |
continue; | |
} | |
successful = true; | |
this.readFile(file, (content) => __awaiter(this, void 0, void 0, function* () { | |
yield createFile(this.plugin, iconPack.name, file.name, content); | |
addIconToIconPack(iconPack.name, file.name, content); | |
iconPackSetting.setDesc(`Total icons: ${iconPack.icons.length} (added: ${file.name})`); | |
})); | |
} | |
if (successful) { | |
new obsidian.Notice('Icons successfully added.'); | |
} | |
}, false); | |
}); | |
containerEl.createEl('h3', { text: 'Icon Folder Customization' }); | |
new obsidian.Setting(containerEl) | |
.setName('Icon font size (in pixels)') | |
.setDesc('Change the font size of the displayed icons.') | |
.addSlider((slider) => { | |
var _a; | |
slider | |
.setLimits(10, 24, 1) | |
.setDynamicTooltip() | |
.setValue((_a = this.plugin.getSettings().fontSize) !== null && _a !== void 0 ? _a : DEFAULT_SETTINGS.fontSize) | |
.onChange((val) => __awaiter(this, void 0, void 0, function* () { | |
this.plugin.getSettings().fontSize = val; | |
yield this.plugin.saveIconFolderData(); | |
refreshIconStyle(this.plugin); | |
})); | |
}); | |
const colorCustomization = new obsidian.Setting(containerEl) | |
.setName('Icon color') | |
.setDesc('Change the color of the displayed icons.'); | |
const colorPicker = new ColorPickerComponent(colorCustomization.controlEl) | |
.setValue((_a = this.plugin.getSettings().iconColor) !== null && _a !== void 0 ? _a : '#000000') | |
.onChange((value) => __awaiter(this, void 0, void 0, function* () { | |
this.plugin.getSettings().iconColor = value; | |
yield this.plugin.saveIconFolderData(); | |
refreshIconStyle(this.plugin); | |
})); | |
colorCustomization.addButton((button) => { | |
button | |
.setButtonText('Default') | |
.setTooltip('Set color to the default one') | |
.onClick(() => __awaiter(this, void 0, void 0, function* () { | |
colorPicker.setValue('#000000'); | |
this.plugin.getSettings().iconColor = null; | |
yield this.plugin.saveIconFolderData(); | |
refreshIconStyle(this.plugin); | |
})); | |
}); | |
colorCustomization.components.push(colorPicker.build()); | |
const extraPaddingSetting = new obsidian.Setting(containerEl) | |
.setName('Top Extrapadding (in pixels)') | |
.setDesc('Change the top padding of the icons.') | |
.setClass('obsidian-icon-folder-setting'); | |
const extraPaddingDropdown = new obsidian.DropdownComponent(extraPaddingSetting.controlEl).addOptions({ | |
top: 'Top', | |
right: 'Right', | |
bottom: 'Bottom', | |
left: 'Left', | |
}); | |
const extraPaddingSlider = new obsidian.SliderComponent(extraPaddingSetting.controlEl) | |
.setLimits(0, 24, 1) | |
.setDynamicTooltip() | |
.setValue((_c = (_b = this.plugin.getSettings().extraPadding) === null || _b === void 0 ? void 0 : _b.top) !== null && _c !== void 0 ? _c : 2) | |
.onChange((val) => __awaiter(this, void 0, void 0, function* () { | |
const dropdownValue = extraPaddingDropdown.getValue(); | |
if (this.plugin.getSettings().extraPadding) { | |
this.plugin.getSettings().extraPadding[dropdownValue] = val; | |
} | |
else { | |
this.plugin.getSettings().extraPadding = { | |
[dropdownValue]: val, | |
}; | |
} | |
yield this.plugin.saveIconFolderData(); | |
refreshIconStyle(this.plugin); | |
})); | |
extraPaddingDropdown.onChange((val) => { | |
var _a; | |
if (this.plugin.getSettings().extraPadding) { | |
extraPaddingSlider.setValue((_a = this.plugin.getSettings().extraPadding[val]) !== null && _a !== void 0 ? _a : 2); | |
} | |
else { | |
extraPaddingSlider.setValue(2); | |
} | |
}); | |
extraPaddingSetting.components.push(extraPaddingDropdown, extraPaddingSlider); | |
} | |
readFile(file, callback) { | |
const reader = new FileReader(); | |
reader.readAsText(file, 'UTF-8'); | |
reader.onload = (readerEvent) => __awaiter(this, void 0, void 0, function* () { | |
const content = readerEvent.target.result; | |
callback(content); | |
}); | |
} | |
preventDefaults(event) { | |
event.preventDefault(); | |
event.stopPropagation(); | |
} | |
highlight(target, el) { | |
clearTimeout(this.closeTimer); | |
if (!this.dragTargetElement) { | |
el.appendChild(this.dragOverElement); | |
el.classList.add('obsidian-icon-folder-dragover'); | |
this.dragTargetElement = el; | |
} | |
} | |
unhighlight(target, el) { | |
if (this.dragTargetElement && this.dragTargetElement !== target) { | |
this.dragTargetElement.removeChild(this.dragOverElement); | |
this.dragTargetElement.classList.remove('obsidian-icon-folder-dragover'); | |
this.dragTargetElement = undefined; | |
} | |
clearTimeout(this.closeTimer); | |
this.closeTimer = setTimeout(() => { | |
if (this.dragTargetElement) { | |
el.removeChild(this.dragOverElement); | |
el.classList.remove('obsidian-icon-folder-dragover'); | |
this.dragTargetElement = undefined; | |
} | |
}, 100); | |
} | |
} | |
class IconsPickerModal extends obsidian.FuzzySuggestModal { | |
constructor(app, plugin, path) { | |
super(app); | |
this.renderIndex = 0; | |
this.plugin = plugin; | |
this.path = path; | |
this.limit = 150; | |
this.recentlyUsedItems = plugin.getSettings().recentlyUsedIcons; | |
this.resultContainerEl.classList.add('obsidian-icon-folder-modal'); | |
this.oldEnterFunc = this.scope.keys.find((e) => e.key === 'Enter').func; | |
} | |
onNoSuggestion() { | |
super.onNoSuggestion(); | |
const inputVal = this.inputEl.value; | |
if (isEmoji(inputVal)) { | |
this.resultContainerEl.empty(); | |
const suggestionItem = this.resultContainerEl.createDiv(); | |
suggestionItem.className = 'suggestion-item suggestion-item__center is-selected'; | |
suggestionItem.textContent = 'Use twemoji Emoji'; | |
suggestionItem.innerHTML += `<div class="obsidian-icon-folder-icon-preview">${twemoji_npm.parse(inputVal)}</div>`; | |
this.setEnterScope(() => { | |
this.selectTwemoji(inputVal); | |
}); | |
suggestionItem.addEventListener('click', () => { | |
this.selectTwemoji(inputVal); | |
}); | |
this.resultContainerEl.appendChild(suggestionItem); | |
} | |
} | |
selectTwemoji(inputVal) { | |
this.onChooseItem(inputVal); | |
this.close(); | |
} | |
onOpen() { | |
super.onOpen(); | |
} | |
onClose() { | |
const { contentEl } = this; | |
contentEl.empty(); | |
} | |
getItemText(item) { | |
return `${item.name} (${item.prefix})`; | |
} | |
getItems() { | |
const iconKeys = []; | |
if (this.inputEl.value.length === 0) { | |
this.renderIndex = 0; | |
this.recentlyUsedItems.forEach((iconName) => { | |
iconKeys.push({ | |
name: iconName, | |
prefix: iconName.substring(0, 2), | |
}); | |
}); | |
} | |
for (const icon of getEnabledIcons(this.plugin)) { | |
iconKeys.push({ | |
name: icon.name, | |
prefix: icon.prefix, | |
}); | |
} | |
return iconKeys; | |
} | |
onChooseItem(item) { | |
if (typeof item === 'object') { | |
addToDOM(this.plugin, this.path, item.name); | |
} | |
else { | |
addToDOM(this.plugin, this.path, item); | |
} | |
this.plugin.addFolderIcon(this.path, item); | |
} | |
renderSuggestion(item, el) { | |
super.renderSuggestion(item, el); | |
if (getAllIconPacks().length === 0) { | |
this.inputEl.disabled = true; | |
this.resultContainerEl.style.display = 'block'; | |
this.resultContainerEl.innerHTML = '<div class="suggestion-empty">You need to create an icon pack.</div>'; | |
return; | |
} | |
// Render subheadlines for modal. | |
if (this.recentlyUsedItems.length !== 0 && this.inputEl.value.length === 0) { | |
if (this.renderIndex === 0) { | |
const subheadline = this.resultContainerEl.createDiv(); | |
subheadline.classList.add('obsidian-icon-folder-subheadline'); | |
subheadline.innerText = 'Recently used Icons:'; | |
this.resultContainerEl.prepend(subheadline); | |
} | |
else if (this.renderIndex === this.recentlyUsedItems.length) { | |
const subheadline = this.containerEl.createDiv(); | |
subheadline.classList.add('obsidian-icon-folder-subheadline'); | |
subheadline.innerText = 'All Icons:'; | |
subheadline.insertAfter(this.lastRenderedRecentlyIcon); | |
} | |
} | |
if (this.getEnterScope() !== this.oldEnterFunc) { | |
this.setEnterScope(this.oldEnterFunc); | |
} | |
if (item.item.name !== 'default') { | |
const possibleEmoji = el.innerHTML.trim().replace(/\(|\)/gi, ''); | |
if (isEmoji(possibleEmoji)) { | |
el.innerHTML = `<div>Twemoji</div><div class="obsidian-icon-folder-icon-preview">${twemoji_npm.parse(possibleEmoji)}</div>`; | |
} | |
else { | |
el.innerHTML = `<div>${el.innerHTML}</div><div class="obsidian-icon-folder-icon-preview">${getIcon(item.item.name)}</div>`; | |
} | |
} | |
this.lastRenderedRecentlyIcon = el; | |
this.renderIndex++; | |
} | |
setEnterScope(func) { | |
this.scope.keys.find((e) => e.key === 'Enter').func = func; | |
} | |
getEnterScope() { | |
return this.scope.keys.find((e) => e.key === 'Enter').func; | |
} | |
} | |
class IconFolderPlugin extends obsidian.Plugin { | |
constructor() { | |
super(...arguments); | |
this.registeredFileExplorers = new WeakSet(); | |
} | |
onload() { | |
return __awaiter(this, void 0, void 0, function* () { | |
console.log('loading obsidian-icon-folder'); | |
yield initIconPacks(this); | |
yield this.loadIconFolderData(); | |
yield this.checkRecentlyUsedIcons(); | |
this.app.workspace.onLayoutReady(() => this.handleChangeLayout()); | |
this.registerEvent(this.app.workspace.on('layout-change', () => this.handleChangeLayout())); | |
this.registerEvent(this.app.workspace.on('file-menu', (menu, file) => { | |
const addIconMenuItem = (item) => { | |
item.setTitle('Change icon'); | |
item.setIcon('hashtag'); | |
item.onClick(() => { | |
const modal = new IconsPickerModal(this.app, this, file.path); | |
modal.open(); | |
}); | |
}; | |
const removeIconMenuItem = (item) => { | |
item.setTitle('Remove icon'); | |
item.setIcon('trash'); | |
item.onClick(() => { | |
this.removeFolderIcon(file.path); | |
removeFromDOM(file.path); | |
}); | |
}; | |
menu.addItem(addIconMenuItem); | |
const node = document.querySelector(`[data-path="${file.path}"]`); | |
const iconNode = node.querySelector('.obsidian-icon-folder-icon'); | |
if (iconNode) { | |
menu.addItem(removeIconMenuItem); | |
} | |
const inheritIcon = (item) => { | |
if (typeof this.data[file.path] === 'object') { | |
item.setTitle('Remove inherit icon'); | |
item.onClick(() => { | |
removeInheritanceForFolder(this, file.path); | |
this.saveInheritanceData(file.path, null); | |
}); | |
} | |
else { | |
item.setTitle('Inherit icon'); | |
item.onClick(() => { | |
const modal = new IconsPickerModal(this.app, this, file.path); | |
modal.open(); | |
// manipulate `onChooseItem` method to get custom functioanlity for inheriting icons | |
modal.onChooseItem = (icon) => { | |
this.saveInheritanceData(file.path, icon); | |
addInheritanceForFolder(this, file.path); | |
}; | |
}); | |
} | |
item.setIcon('vertical-three-dots'); | |
}; | |
menu.addItem(inheritIcon); | |
})); | |
// deleting event | |
this.registerEvent(this.app.vault.on('delete', (file) => { | |
const path = file.path; | |
this.removeFolderIcon(path); | |
})); | |
// renaming event | |
this.registerEvent(this.app.vault.on('rename', (file, oldPath) => { | |
this.renameFolder(file.path, oldPath); | |
})); | |
this.addSettingTab(new IconFolderSettingsTab(this.app, this)); | |
}); | |
} | |
getSearchLeave() { | |
return this.app.workspace.getLeavesOfType('search')[0].view; | |
} | |
addIconsToSearch() { | |
console.log(this.app.workspace.getLeavesOfType('backlink')); | |
const searchLeaveDom = this.getSearchLeave().dom; | |
searchLeaveDom.children.forEach((child) => { | |
const file = child.file; | |
const collapseEl = child.collapseEl; | |
const existingIcon = child.containerEl.querySelector('.obsidian-icon-folder-icon'); | |
if (existingIcon) { | |
existingIcon.remove(); | |
} | |
const iconName = this.data[file.path]; | |
if (iconName) { | |
const iconNode = child.containerEl.createDiv(); | |
iconNode.classList.add('obsidian-icon-folder-icon'); | |
insertIconToNode(this, this.data[file.path], iconNode); | |
iconNode.insertAfter(collapseEl); | |
} | |
}); | |
} | |
handleChangeLayout() { | |
// transform data that are objects to single strings | |
const data = Object.entries(this.data); | |
addIconsToDOM(this, data, this.registeredFileExplorers, () => { | |
const searchLeaveDom = this.getSearchLeave().dom; | |
searchLeaveDom.changed = () => this.addIconsToSearch(); | |
// register create event for checking inheritance functionality | |
this.registerEvent(this.app.vault.on('create', (file) => { | |
const inheritanceFolders = Object.entries(this.data).filter(([k, v]) => k !== 'settings' && typeof v === 'object'); | |
if (file.parent.path === '/') | |
return; | |
inheritanceFolders.forEach(([path, obj]) => { | |
if (file.parent.path.includes(path)) { | |
addInheritanceIconToFile(this, this.registeredFileExplorers, file.path, obj.inheritanceIcon); | |
} | |
}); | |
})); | |
}); | |
} | |
saveInheritanceData(folderPath, icon) { | |
const currentValue = this.data[folderPath]; | |
// if icon is null, it will remove the inheritance icon from the data | |
if (icon === null && currentValue && typeof currentValue === 'object') { | |
const folderObject = currentValue; | |
if (folderObject.iconName) { | |
this.data[folderPath] = folderObject.iconName; | |
} | |
else { | |
delete this.data[folderPath]; | |
} | |
} | |
// icon is not null, so it will add inheritance data | |
else { | |
// check if data already exists | |
if (currentValue) { | |
// check if current value is already an icon name | |
if (typeof currentValue === 'string') { | |
this.data[folderPath] = { | |
iconName: currentValue, | |
inheritanceIcon: typeof icon === 'object' ? icon.name : icon, | |
}; | |
} | |
// check if it has already a inheritance icon | |
else if (folderPath !== 'settings') { | |
this.data[folderPath] = Object.assign(Object.assign({}, currentValue), { inheritanceIcon: typeof icon === 'object' ? icon.name : icon }); | |
} | |
} | |
else { | |
this.data[folderPath] = { | |
iconName: null, | |
inheritanceIcon: typeof icon === 'object' ? icon.name : icon, | |
}; | |
} | |
} | |
this.saveIconFolderData(); | |
} | |
onunload() { | |
console.log('unloading obsidian-icon-folder'); | |
} | |
renameFolder(newPath, oldPath) { | |
if (!this.data[oldPath] || newPath === oldPath) { | |
return; | |
} | |
Object.defineProperty(this.data, newPath, Object.getOwnPropertyDescriptor(this.data, oldPath)); | |
delete this.data[oldPath]; | |
this.saveIconFolderData(); | |
} | |
removeFolderIcon(path) { | |
if (!this.data[path]) { | |
return; | |
} | |
if (typeof this.data[path] === 'object') { | |
const currentValue = this.data[path]; | |
this.data[path] = Object.assign(Object.assign({}, currentValue), { iconName: null }); | |
} | |
else { | |
delete this.data[path]; | |
} | |
this.addIconsToSearch(); | |
this.saveIconFolderData(); | |
} | |
addFolderIcon(path, icon) { | |
const iconName = typeof icon === 'object' ? icon.name : icon; | |
this.data[path] = iconName; | |
if (!this.getSettings().recentlyUsedIcons.includes(iconName)) { | |
if (this.getSettings().recentlyUsedIcons.length >= this.getSettings().recentlyUsedIconsSize) { | |
this.getSettings().recentlyUsedIcons.pop(); | |
} | |
this.getSettings().recentlyUsedIcons.unshift(iconName); | |
this.checkRecentlyUsedIcons(); | |
} | |
this.addIconsToSearch(); | |
this.saveIconFolderData(); | |
} | |
getSettings() { | |
return this.data.settings; | |
} | |
loadIconFolderData() { | |
return __awaiter(this, void 0, void 0, function* () { | |
const data = yield this.loadData(); | |
if (data) { | |
Object.entries(DEFAULT_SETTINGS).forEach(([k, v]) => { | |
if (!data.settings[k]) { | |
data.settings[k] = v; | |
} | |
}); | |
} | |
this.data = Object.assign({ settings: Object.assign({}, DEFAULT_SETTINGS) }, {}, data); | |
}); | |
} | |
saveIconFolderData() { | |
return __awaiter(this, void 0, void 0, function* () { | |
yield this.saveData(this.data); | |
}); | |
} | |
checkRecentlyUsedIcons() { | |
return __awaiter(this, void 0, void 0, function* () { | |
if (this.getSettings().recentlyUsedIcons.length > this.getSettings().recentlyUsedIconsSize) { | |
this.getSettings().recentlyUsedIcons = this.getSettings().recentlyUsedIcons.slice(0, this.getSettings().recentlyUsedIconsSize); | |
yield this.saveIconFolderData(); | |
} | |
}); | |
} | |
getData() { | |
return this.data; | |
} | |
} | |
module.exports = IconFolderPlugin; | |
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInNyYy9pY29uUGFja01hbmFnZXIudHMiLCJzcmMvY29sb3JQaWNrZXJDb21wb25lbnQudHMiLCJzcmMvc2V0dGluZ3MudHMiLCJub2RlX21vZHVsZXMvdHdlbW9qaS9kaXN0L3R3ZW1vamkubnBtLmpzIiwic3JjL3V0aWwudHMiLCJzcmMvaWNvbkZvbGRlclNldHRpbmdzVGFiLnRzIiwic3JjL2ljb25zUGlja2VyTW9kYWwudHMiLCJzcmMvbWFpbi50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uXHJcblxyXG5QZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZvciBhbnlcclxucHVycG9zZSB3aXRoIG9yIHdpdGhvdXQgZmVlIGlzIGhlcmVieSBncmFudGVkLlxyXG5cclxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiBBTkQgVEhFIEFVVEhPUiBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSFxyXG5SRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFlcclxuQU5EIEZJVE5FU1MuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgRElSRUNULFxyXG5JTkRJUkVDVCwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST01cclxuTE9TUyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1JcclxuT1RIRVIgVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUlxyXG5QRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSAqL1xyXG5cclxudmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbihkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XHJcbiAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4dGVuZHMoZCwgYikge1xyXG4gICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcclxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XHJcbiAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbn1cclxuXHJcbmV4cG9ydCB2YXIgX19hc3NpZ24gPSBmdW5jdGlvbigpIHtcclxuICAgIF9fYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBfX2Fzc2lnbih0KSB7XHJcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XHJcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdFtwXSA9IHNbcF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3Jlc3QocywgZSkge1xyXG4gICAgdmFyIHQgPSB7fTtcclxuICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKVxyXG4gICAgICAgIHRbcF0gPSBzW3BdO1xyXG4gICAgaWYgKHMgIT0gbnVsbCAmJiB0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgaWYgKGUuaW5kZXhPZihwW2ldKSA8IDAgJiYgT2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKHMsIHBbaV0pKVxyXG4gICAgICAgICAgICAgICAgdFtwW2ldXSA9IHNbcFtpXV07XHJcbiAgICAgICAgfVxyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2RlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XHJcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcclxuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XHJcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19wYXJhbShwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHsgZGVjb3JhdG9yKHRhcmdldCwga2V5LCBwYXJhbUluZGV4KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSkge1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0Lm1ldGFkYXRhID09PSBcImZ1bmN0aW9uXCIpIHJldHVybiBSZWZsZWN0Lm1ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXRlcih0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcclxuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxyXG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XHJcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XHJcbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2dlbmVyYXRvcih0aGlzQXJnLCBib2R5KSB7XHJcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xyXG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcclxuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XHJcbiAgICAgICAgd2hpbGUgKF8pIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcclxuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xyXG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XHJcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcclxuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cclxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2NyZWF0ZUJpbmRpbmcgPSBPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XHJcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH0pO1xyXG59KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xyXG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcclxuICAgIG9bazJdID0gbVtrXTtcclxufSk7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIG8pIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobywgcCkpIF9fY3JlYXRlQmluZGluZyhvLCBtLCBwKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBzID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIFN5bWJvbC5pdGVyYXRvciwgbSA9IHMgJiYgb1tzXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIGlmIChvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHtcclxuICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XHJcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihzID8gXCJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLlwiIDogXCJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcclxuICAgIGlmICghbSkgcmV0dXJuIG87XHJcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cclxuICAgIH1cclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5cygpIHtcclxuICAgIGZvciAodmFyIHMgPSAwLCBpID0gMCwgaWwgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgaWw7IGkrKykgcyArPSBhcmd1bWVudHNbaV0ubGVuZ3RoO1xyXG4gICAgZm9yICh2YXIgciA9IEFycmF5KHMpLCBrID0gMCwgaSA9IDA7IGkgPCBpbDsgaSsrKVxyXG4gICAgICAgIGZvciAodmFyIGEgPSBhcmd1bWVudHNbaV0sIGogPSAwLCBqbCA9IGEubGVuZ3RoOyBqIDwgamw7IGorKywgaysrKVxyXG4gICAgICAgICAgICByW2tdID0gYVtqXTtcclxuICAgIHJldHVybiByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWRBcnJheSh0bywgZnJvbSwgcGFjaykge1xyXG4gICAgaWYgKHBhY2sgfHwgYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgZm9yICh2YXIgaSA9IDAsIGwgPSBmcm9tLmxlbmd0aCwgYXI7IGkgPCBsOyBpKyspIHtcclxuICAgICAgICBpZiAoYXIgfHwgIShpIGluIGZyb20pKSB7XHJcbiAgICAgICAgICAgIGlmICghYXIpIGFyID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSwgMCwgaSk7XHJcbiAgICAgICAgICAgIGFyW2ldID0gZnJvbVtpXTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdG8uY29uY2F0KGFyIHx8IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb20pKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xyXG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jR2VuZXJhdG9yKHRoaXNBcmcsIF9hcmd1bWVudHMsIGdlbmVyYXRvcikge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaWYgKGdbbl0pIGlbbl0gPSBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKGEsIGIpIHsgcS5wdXNoKFtuLCB2LCBhLCBiXSkgPiAxIHx8IHJlc3VtZShuLCB2KTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHJlc3VtZShuLCB2KSB7IHRyeSB7IHN0ZXAoZ1tuXSh2KSk7IH0gY2F0Y2ggKGUpIHsgc2V0dGxlKHFbMF1bM10sIGUpOyB9IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAocikgeyByLnZhbHVlIGluc3RhbmNlb2YgX19hd2FpdCA/IFByb21pc2UucmVzb2x2ZShyLnZhbHVlLnYpLnRoZW4oZnVsZmlsbCwgcmVqZWN0KSA6IHNldHRsZShxWzBdWzJdLCByKTsgfVxyXG4gICAgZnVuY3Rpb24gZnVsZmlsbCh2YWx1ZSkgeyByZXN1bWUoXCJuZXh0XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gcmVqZWN0KHZhbHVlKSB7IHJlc3VtZShcInRocm93XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKGYsIHYpIHsgaWYgKGYodiksIHEuc2hpZnQoKSwgcS5sZW5ndGgpIHJlc3VtZShxWzBdWzBdLCBxWzBdWzFdKTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0RlbGVnYXRvcihvKSB7XHJcbiAgICB2YXIgaSwgcDtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiwgZnVuY3Rpb24gKGUpIHsgdGhyb3cgZTsgfSksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4sIGYpIHsgaVtuXSA9IG9bbl0gPyBmdW5jdGlvbiAodikgeyByZXR1cm4gKHAgPSAhcCkgPyB7IHZhbHVlOiBfX2F3YWl0KG9bbl0odikpLCBkb25lOiBuID09PSBcInJldHVyblwiIH0gOiBmID8gZih2KSA6IHY7IH0gOiBmOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgbSA9IG9bU3ltYm9sLmFzeW5jSXRlcmF0b3JdLCBpO1xyXG4gICAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiAobyA9IHR5cGVvZiBfX3ZhbHVlcyA9PT0gXCJmdW5jdGlvblwiID8gX192YWx1ZXMobykgOiBvW1N5bWJvbC5pdGVyYXRvcl0oKSwgaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGkpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlbbl0gPSBvW25dICYmIGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHYgPSBvW25dKHYpLCBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCB2LmRvbmUsIHYudmFsdWUpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgZCwgdikgeyBQcm9taXNlLnJlc29sdmUodikudGhlbihmdW5jdGlvbih2KSB7IHJlc29sdmUoeyB2YWx1ZTogdiwgZG9uZTogZCB9KTsgfSwgcmVqZWN0KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tYWtlVGVtcGxhdGVPYmplY3QoY29va2VkLCByYXcpIHtcclxuICAgIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XHJcbiAgICByZXR1cm4gY29va2VkO1xyXG59O1xyXG5cclxudmFyIF9fc2V0TW9kdWxlRGVmYXVsdCA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgdikge1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIFwiZGVmYXVsdFwiLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2IH0pO1xyXG59KSA6IGZ1bmN0aW9uKG8sIHYpIHtcclxuICAgIG9bXCJkZWZhdWx0XCJdID0gdjtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydFN0YXIobW9kKSB7XHJcbiAgICBpZiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSByZXR1cm4gbW9kO1xyXG4gICAgdmFyIHJlc3VsdCA9IHt9O1xyXG4gICAgaWYgKG1vZCAhPSBudWxsKSBmb3IgKHZhciBrIGluIG1vZCkgaWYgKGsgIT09IFwiZGVmYXVsdFwiICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2QsIGspKSBfX2NyZWF0ZUJpbmRpbmcocmVzdWx0LCBtb2QsIGspO1xyXG4gICAgX19zZXRNb2R1bGVEZWZhdWx0KHJlc3VsdCwgbW9kKTtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydERlZmF1bHQobW9kKSB7XHJcbiAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IGRlZmF1bHQ6IG1vZCB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZEdldChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcclxuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcclxuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xyXG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRTZXQocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xyXG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xyXG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xyXG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcclxuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xyXG59XHJcbiIsImltcG9ydCB7IFBsdWdpbiB9IGZyb20gJ29ic2lkaWFuJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgSWNvbiB7XHJcbiAgbmFtZTogc3RyaW5nO1xyXG4gIHByZWZpeDogc3RyaW5nO1xyXG4gIGZpbGVuYW1lOiBzdHJpbmc7XHJcbiAgc3ZnUGF0aDogc3RyaW5nIHwgeyBmaWxsOiBzdHJpbmc7IGQ6IHN0cmluZyB9W107XHJcbiAgc3ZnQ29udGVudDogc3RyaW5nO1xyXG4gIHN2Z1ZpZXdib3g6IHN0cmluZztcclxufVxyXG5cclxuY29uc3QgcGF0aCA9ICcub2JzaWRpYW4vcGx1Z2lucy9vYnNpZGlhbi1pY29uLWZvbGRlci9pY29ucyc7XHJcbmxldCBpY29uUGFja3M6IHtcclxuICBuYW1lOiBzdHJpbmc7XHJcbiAgaWNvbnM6IEljb25bXTtcclxufVtdID0gW107XHJcblxyXG5leHBvcnQgY29uc3QgY3JlYXRlSWNvblBhY2tEaXJlY3RvcnkgPSBhc3luYyAocGx1Z2luOiBQbHVnaW4sIGRpcjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiA9PiB7XHJcbiAgYXdhaXQgY3JlYXRlRGlyZWN0b3J5KHBsdWdpbiwgZGlyKTtcclxuICBpY29uUGFja3MucHVzaCh7IG5hbWU6IGRpciwgaWNvbnM6IFtdIH0pO1xyXG59O1xyXG5cclxuZXhwb3J0IGNvbnN0IGRlbGV0ZUljb25QYWNrID0gYXN5bmMgKHBsdWdpbjogUGx1Z2luLCBkaXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD4gPT4ge1xyXG4gIGNvbnN0IG5ld0ljb25QYWNrcyA9IGljb25QYWNrcy5maWx0ZXIoKGljb25QYWNrKSA9PiBpY29uUGFjay5uYW1lICE9PSBkaXIpO1xyXG4gIGljb25QYWNrcyA9IG5ld0ljb25QYWNrcztcclxuICBhd2FpdCBwbHVnaW4uYXBwLnZhdWx0LmFkYXB0ZXIucm1kaXIoYCR7cGF0aH0vJHtkaXJ9YCwgdHJ1ZSk7XHJcbn07XHJcblxyXG5jb25zdCBjcmVhdGVEaXJlY3RvcnkgPSBhc3luYyAocGx1Z2luOiBQbHVnaW4sIGRpcjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiA9PiB7XHJcbiAgY29uc3QgZG9lc0RpckV4aXN0ID0gYXdhaXQgcGx1Z2luLmFwcC52YXVsdC5hZGFwdGVyLmV4aXN0cyhgJHtwYXRofS8ke2Rpcn1gKTtcclxuICBpZiAoIWRvZXNEaXJFeGlzdCkge1xyXG4gICAgYXdhaXQgcGx1Z2luLmFwcC52YXVsdC5hZGFwdGVyLm1rZGlyKGAke3BhdGh9LyR7ZGlyfWApO1xyXG4gIH1cclxufTtcclxuXHJcbmV4cG9ydCBjb25zdCBjcmVhdGVGaWxlID0gYXN5bmMgKFxyXG4gIHBsdWdpbjogUGx1Z2luLFxyXG4gIGljb25QYWNrTmFtZTogc3RyaW5nLFxyXG4gIGZpbGVuYW1lOiBzdHJpbmcsXHJcbiAgY29udGVudDogc3RyaW5nLFxyXG4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcclxuICBhd2FpdCBwbHVnaW4uYXBwLnZhdWx0LmFkYXB0ZXIud3JpdGUoYCR7cGF0aH0vJHtpY29uUGFja05hbWV9LyR7ZmlsZW5hbWV9YCwgY29udGVudCk7XHJcbn07XHJcblxyXG5leHBvcnQgY29uc3QgY3JlYXRlRGVmYXVsdERpcmVjdG9yeSA9IGFzeW5jIChwbHVnaW46IFBsdWdpbik6IFByb21pc2U8dm9pZD4gPT4ge1xyXG4gIGF3YWl0IGNyZWF0ZURpcmVjdG9yeShwbHVnaW4sICcnKTtcclxufTtcclxuXHJcbmV4cG9ydCBjb25zdCBnZXRBbGxJY29uUGFja3MgPSAoKSA9PiB7XHJcbiAgcmV0dXJuIGljb25QYWNrcztcclxufTtcclxuXHJcbmNvbnN0IGdldEZpbGVzSW5EaXJlY3RvcnkgPSBhc3luYyAocGx1Z2luOiBQbHVnaW4sIGRpcjogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmdbXT4gPT4ge1xyXG4gIHJldHVybiAoYXdhaXQgcGx1Z2luLmFwcC52YXVsdC5hZGFwdGVyLmxpc3QoZGlyKSkuZmlsZXM7XHJcbn07XHJcblxyXG5jb25zdCBzdmdQYXRoUmVnZXggPSAvPHBhdGhcXHMoW14+XSopPi9nO1xyXG5jb25zdCBzdmdBdHRyUmVnZXggPSAvKD86XFxzKnxeKShbXj0gXSopPVwiKFteXCJdKilcIi9nO1xyXG5jb25zdCBleHRyYWN0UGF0aHMgPSAoY29udGVudDogc3RyaW5nKSA9PiB7XHJcbiAgY29uc3QgYWxsUGF0aHMgPSBbXTtcclxuICB3aGlsZSAodHJ1ZSkge1xyXG4gICAgY29uc3Qgc3ZnUGF0aE1hdGNoZXMgPSBzdmdQYXRoUmVnZXguZXhlYyhjb250ZW50KTtcclxuICAgIGNvbnN0IHN2Z1BhdGggPSBzdmdQYXRoTWF0Y2hlcyAmJiBzdmdQYXRoTWF0Y2hlc1sxXTtcclxuICAgIGlmICghc3ZnUGF0aCkge1xyXG4gICAgICBicmVhaztcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBhdHRyczogYW55ID0ge307XHJcbiAgICB3aGlsZSAodHJ1ZSkge1xyXG4gICAgICBjb25zdCBzdmdBdHRyTWF0Y2hlcyA9IHN2Z0F0dHJSZWdleC5leGVjKHN2Z1BhdGgpO1xyXG4gICAgICBpZiAoIXN2Z0F0dHJNYXRjaGVzKSB7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgICAgYXR0cnNbc3ZnQXR0ck1hdGNoZXNbMV1dID0gc3ZnQXR0ck1hdGNoZXNbMl07XHJcbiAgICB9XHJcbiAgICBpZiAoYXR0cnMuZmlsbCA9PT0gJ25vbmUnKSB7XHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG4gICAgYWxsUGF0aHMucHVzaChhdHRycyk7XHJcbiAgfVxyXG5cclxuICByZXR1cm4gYWxsUGF0aHM7XHJcbn07XHJcblxyXG5jb25zdCB2YWxpZEljb25OYW1lID0gL15bQS1aXS87XHJcbmNvbnN0IHN2Z1ZpZXdib3hSZWdleCA9IC92aWV3Qm94PVwiKFteXCJdKilcIi9nO1xyXG5jb25zdCBzdmdDb250ZW50UmVnZXggPSAvPHN2Zy4qPiguKj8pPFxcL3N2Zz4vZztcclxuY29uc3QgZ2VuZXJhdGVJY29uID0gKGljb25QYWNrTmFtZTogc3RyaW5nLCBpY29uTmFtZTogc3RyaW5nLCBjb250ZW50OiBzdHJpbmcpOiBJY29uID0+IHtcclxuICBjb25zdCBub3JtYWxpemVkTmFtZSA9IGljb25OYW1lXHJcbiAgICAuc3BsaXQoL1sgLV0vZylcclxuICAgIC5tYXAoKHBhcnQpID0+IHBhcnQuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBwYXJ0LnNsaWNlKDEpKVxyXG4gICAgLmpvaW4oJycpO1xyXG5cclxuICBpZiAoIXZhbGlkSWNvbk5hbWUuZXhlYyhub3JtYWxpemVkTmFtZSkpIHtcclxuICAgIGNvbnNvbGUubG9nKGBza2lwcGluZyBpY29uIHdpdGggaW52YWxpZCBuYW1lOiAke2ljb25OYW1lfWApO1xyXG4gICAgcmV0dXJuO1xyXG4gIH1cclxuXHJcbiAgbGV0IHN2Z1BhdGhzO1xyXG4gIHRyeSB7XHJcbiAgICBzdmdQYXRocyA9IGV4dHJhY3RQYXRocyhjb250ZW50KTtcclxuICB9IGNhdGNoIChlcnIpIHtcclxuICAgIGNvbnNvbGUubG9nKGVycik7XHJcbiAgICByZXR1cm47XHJcbiAgfVxyXG5cclxuICBjb25zdCBzdmdWaWV3Ym94ID0gY29udGVudC5tYXRjaChzdmdWaWV3Ym94UmVnZXgpWzBdO1xyXG4gIGNvbnN0IHN2Z0NvbnRlbnRNYXRjaCA9IGNvbnRlbnQubWF0Y2goc3ZnQ29udGVudFJlZ2V4KTtcclxuICBjb25zdCBzdmdDb250ZW50ID0gc3ZnQ29udGVudE1hdGNoLm1hcCgodmFsKSA9PiB2YWwucmVwbGFjZSgvPFxcLz9zdmc+L2csICcnKSlbMF07XHJcblxyXG4gIGNvbnN0IGljb25QYWNrUHJlZml4ID0gaWNvblBhY2tOYW1lLnN1YnN0cmluZygwLCAyKTtcclxuXHJcbiAgY29uc3QgaWNvbjogSWNvbiA9IHtcclxuICAgIG5hbWU6IG5vcm1hbGl6ZWROYW1lLnNwbGl0KCcuc3ZnJylbMF0sXHJcbiAgICBwcmVmaXg6IGljb25QYWNrUHJlZml4LFxyXG4gICAgZmlsZW5hbWU6IGljb25OYW1lLFxyXG4gICAgc3ZnUGF0aDogc3ZnUGF0aHMubGVuZ3RoID09PSAxID8gc3ZnUGF0aHNbMF0uZCA6IHN2Z1BhdGhzLFxyXG4gICAgc3ZnQ29udGVudCxcclxuICAgIHN2Z1ZpZXdib3gsXHJcbiAgfTtcclxuXHJcbiAgcmV0dXJuIGljb247XHJcbn07XHJcblxyXG5leHBvcnQgY29uc3QgaW5pdEljb25QYWNrcyA9IGFzeW5jIChwbHVnaW46IFBsdWdpbik6IFByb21pc2U8dm9pZD4gPT4ge1xyXG4gIGF3YWl0IGNyZWF0ZURlZmF1bHREaXJlY3RvcnkocGx1Z2luKTtcclxuXHJcbiAgLy8gTG9hZCBhbGwgdGhlIGN1c3RvbSBnZW5lcmF0ZWQgaWNvbiBwYWNrcy5cclxuICBjb25zdCBsb2FkZWRJY29uUGFja3MgPSBhd2FpdCBwbHVnaW4uYXBwLnZhdWx0LmFkYXB0ZXIubGlzdChwYXRoKTtcclxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxvYWRlZEljb25QYWNrcy5mb2xkZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICBjb25zdCBmb2xkZXIgPSBsb2FkZWRJY29uUGFja3MuZm9sZGVyc1tpXTtcclxuICAgIGNvbnN0IGljb25QYWNrUmVnZXggPSBmb2xkZXIubWF0Y2gobmV3IFJlZ0V4cChwYXRoICsgJy8oLiopJykpO1xyXG4gICAgaWYgKGljb25QYWNrUmVnZXgubGVuZ3RoID4gMSkge1xyXG4gICAgICBjb25zdCBpY29uUGFja05hbWUgPSBpY29uUGFja1JlZ2V4WzFdO1xyXG4gICAgICBjb25zdCBpY29ucyA9IGF3YWl0IGdldEZpbGVzSW5EaXJlY3RvcnkocGx1Z2luLCBmb2xkZXIpO1xyXG5cclxuICAgICAgY29uc3QgbG9hZGVkSWNvbnM6IEljb25bXSA9IFtdO1xyXG4gICAgICAvLyBDb252ZXJ0IGZpbGVzIGludG8gbG9hZGVkIHN2Z3MuXHJcbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgaWNvbnMubGVuZ3RoOyBqKyspIHtcclxuICAgICAgICBjb25zdCBpY29uTmFtZVJlZ2V4ID0gaWNvbnNbal0ubWF0Y2gobmV3IFJlZ0V4cChwYXRoICsgJy8nICsgaWNvblBhY2tOYW1lICsgJy8oLiopJykpO1xyXG4gICAgICAgIGNvbnN0IGljb25OYW1lID0gaWNvbk5hbWVSZWdleFsxXTtcclxuICAgICAgICBjb25zdCBpY29uQ29udGVudCA9IGF3YWl0IHBsdWdpbi5hcHAudmF1bHQuYWRhcHRlci5yZWFkKGljb25zW2pdKTtcclxuICAgICAgICBjb25zdCBpY29uID0gZ2VuZXJhdGVJY29uKGljb25QYWNrTmFtZSwgaWNvbk5hbWUsIGljb25Db250ZW50KTtcclxuICAgICAgICBpZiAoaWNvbikge1xyXG4gICAgICAgICAgbG9hZGVkSWNvbnMucHVzaChpY29uKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGljb25QYWNrcy5wdXNoKHsgbmFtZTogaWNvblBhY2tOYW1lLCBpY29uczogbG9hZGVkSWNvbnMgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG59O1xyXG5cclxuZXhwb3J0IGNvbnN0IGFkZEljb25Ub0ljb25QYWNrID0gKGljb25QYWNrTmFtZTogc3RyaW5nLCBpY29uTmFtZTogc3RyaW5nLCBpY29uQ29udGVudDogc3RyaW5nKTogdm9pZCA9PiB7XHJcbiAgY29uc3QgaWNvbiA9IGdlbmVyYXRlSWNvbihpY29uUGFja05hbWUsIGljb25OYW1lLCBpY29uQ29udGVudCk7XHJcbiAgY29uc3QgaWNvblBhY2sgPSBpY29uUGFja3MuZmluZCgoaWNvblBhY2spID0+IGljb25QYWNrLm5hbWUgPT09IGljb25QYWNrTmFtZSk7XHJcbiAgaWNvblBhY2suaWNvbnMucHVzaChpY29uKTtcclxufTtcclxuXHJcbmV4cG9ydCBjb25zdCBnZXRBbGxMb2FkZWRJY29uTmFtZXMgPSAoKTogSWNvbltdID0+IHtcclxuICByZXR1cm4gaWNvblBhY2tzLnJlZHVjZSgodG90YWw6IEljb25bXSwgaWNvblBhY2spID0+IHtcclxuICAgIHRvdGFsLnB1c2goLi4uaWNvblBhY2suaWNvbnMpO1xyXG4gICAgcmV0dXJuIHRvdGFsO1xyXG4gIH0sIFtdKTtcclxufTtcclxuXHJcbmV4cG9ydCBjb25zdCBnZXRTdmdGcm9tTG9hZGVkSWNvbiA9IChpY29uTmFtZTogc3RyaW5nKTogc3RyaW5nID0+IHtcclxuICBsZXQgaWNvbiA9ICcnO1xyXG4gIGljb25QYWNrcy5mb3JFYWNoKChpY29uUGFjaykgPT4ge1xyXG4gICAgY29uc3QgZm91bmRJY29uID0gaWNvblBhY2suaWNvbnMuZmluZCgoaWNvbikgPT4gaWNvbi5uYW1lLnRvTG93ZXJDYXNlKCkgPT09IGljb25OYW1lLnRvTG93ZXJDYXNlKCkpO1xyXG4gICAgaWYgKGZvdW5kSWNvbikge1xyXG4gICAgICBsZXQgZmlsZUNvbnRlbnQgPSAnJztcclxuICAgICAgaWYgKHR5cGVvZiBmb3VuZEljb24uc3ZnUGF0aCA9PT0gJ29iamVjdCcpIHtcclxuICAgICAgICBjb25zdCBzdmdDb250ZW50ID0gZm91bmRJY29uLnN2Z1BhdGgucmVkdWNlKCh0b3RhbCwgY3VycmVudCkgPT4ge1xyXG4gICAgICAgICAgdG90YWwgKz0gYDxwYXRoIGZpbGw9XCIke2N1cnJlbnQuZmlsbH1cIiBkPVwiJHtjdXJyZW50LmR9XCIgLz5gO1xyXG4gICAgICAgICAgcmV0dXJuIHRvdGFsO1xyXG4gICAgICAgIH0sICcnKTtcclxuXHJcbiAgICAgICAgZmlsZUNvbnRlbnQgPSBgPHN2ZyB3aWR0aD1cIjE2XCIgaGVpZ2h0PVwiMTZcIiAke2ZvdW5kSWNvbi5zdmdWaWV3Ym94fT4ke3N2Z0NvbnRlbnR9PC9zdmc+YDtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBmaWxlQ29udGVudCA9IGA8c3ZnIHdpZHRoPVwiMTZcIiBoZWlnaHQ9XCIxNlwiICR7XHJcbiAgICAgICAgICBmb3VuZEljb24uc3ZnUGF0aC5pbmNsdWRlcygnZmlsbD0nKSA/ICcnIDogJ2ZpbGw9XCJjdXJyZW50Q29sb3JcIidcclxuICAgICAgICB9ICR7Zm91bmRJY29uLnN2Z1ZpZXdib3h9PjxwYXRoIGQ9XCIke2ZvdW5kSWNvbi5zdmdQYXRofVwiIC8+PC9zdmc+YDtcclxuICAgICAgfVxyXG4gICAgICBpY29uID0gZmlsZUNvbnRlbnQ7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICB9KTtcclxuXHJcbiAgcmV0dXJuIGljb247XHJcbn07XHJcbiIsImltcG9ydCB7IFZhbHVlQ29tcG9uZW50IH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5cclxuZXhwb3J0IGNsYXNzIENvbG9yUGlja2VyQ29tcG9uZW50IGV4dGVuZHMgVmFsdWVDb21wb25lbnQ8c3RyaW5nPiB7XHJcbiAgcHJpdmF0ZSB2YWx1ZTogc3RyaW5nID0gJyMwMDAwMDAnO1xyXG4gIHByaXZhdGUgY29udGFpbmVyRWw6IEhUTUxFbGVtZW50O1xyXG4gIHByaXZhdGUgaW5wdXRFbDogSFRNTElucHV0RWxlbWVudDtcclxuXHJcbiAgY29uc3RydWN0b3IoY29udGFpbmVyRWw6IEhUTUxFbGVtZW50KSB7XHJcbiAgICBzdXBlcigpO1xyXG4gICAgdGhpcy5jb250YWluZXJFbCA9IGNvbnRhaW5lckVsO1xyXG5cclxuICAgIHRoaXMuaW5wdXRFbCA9IGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdpbnB1dCcpO1xyXG4gICAgdGhpcy5pbnB1dEVsLnR5cGUgPSAnY29sb3InO1xyXG4gICAgdGhpcy5pbnB1dEVsLmFyaWFMYWJlbCA9ICdDbGljayB0byBjaGFuZ2UgdGhlIGNvbG9yJztcclxuICB9XHJcblxyXG4gIG9uQ2hhbmdlKGNhbGxiYWNrOiAodmFsdWU6IHN0cmluZykgPT4gdm9pZCk6IHRoaXMge1xyXG4gICAgdGhpcy5pbnB1dEVsLmFkZEV2ZW50TGlzdGVuZXIoJ2lucHV0JywgKCkgPT4ge1xyXG4gICAgICB0aGlzLnNldFZhbHVlKHRoaXMuaW5wdXRFbC52YWx1ZSk7XHJcbiAgICAgIGNhbGxiYWNrKHRoaXMuZ2V0VmFsdWUoKSk7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiB0aGlzO1xyXG4gIH1cclxuXHJcbiAgZ2V0VmFsdWUoKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLnZhbHVlO1xyXG4gIH1cclxuXHJcbiAgc2V0VmFsdWUodmFsdWU6IHN0cmluZyk6IHRoaXMge1xyXG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xyXG4gICAgdGhpcy5pbnB1dEVsLnZhbHVlID0gdmFsdWU7XHJcbiAgICByZXR1cm4gdGhpcztcclxuICB9XHJcblxyXG4gIGJ1aWxkKCk6IHRoaXMge1xyXG4gICAgdGhpcy5jb250YWluZXJFbC5hcHBlbmRDaGlsZCh0aGlzLmlucHV0RWwpO1xyXG4gICAgcmV0dXJuIHRoaXM7XHJcbiAgfVxyXG59XHJcbiIsImV4cG9ydCBpbnRlcmZhY2UgRXh0cmFQYWRkaW5nU2V0dGluZ3Mge1xyXG4gIHRvcD86IG51bWJlcjtcclxuICByaWdodD86IG51bWJlcjtcclxuICBib3R0b20/OiBudW1iZXI7XHJcbiAgbGVmdD86IG51bWJlcjtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBJY29uRm9sZGVyU2V0dGluZ3Mge1xyXG4gIGZvbnRTaXplOiBudW1iZXI7XHJcbiAgaWNvbkNvbG9yOiBzdHJpbmcgfCBudWxsO1xyXG4gIGV4dHJhUGFkZGluZzogRXh0cmFQYWRkaW5nU2V0dGluZ3M7XHJcbiAgcmVjZW50bHlVc2VkSWNvbnM6IHN0cmluZ1tdO1xyXG4gIHJlY2VudGx5VXNlZEljb25zU2l6ZTogbnVtYmVyO1xyXG59XHJcblxyXG5leHBvcnQgY29uc3QgREVGQVVMVF9TRVRUSU5HUzogSWNvbkZvbGRlclNldHRpbmdzID0ge1xyXG4gIGZvbnRTaXplOiAxNixcclxuICBpY29uQ29sb3I6IG51bGwsXHJcbiAgcmVjZW50bHlVc2VkSWNvbnM6IFtdLFxyXG4gIHJlY2VudGx5VXNlZEljb25zU2l6ZTogNSxcclxuICBleHRyYVBhZGRpbmc6IHtcclxuICAgIHRvcDogMixcclxuICAgIHJpZ2h0OiAyLFxyXG4gICAgYm90dG9tOiAyLFxyXG4gICAgbGVmdDogMixcclxuICB9LFxyXG59O1xyXG4iLCJ2YXIgbG9jYXRpb24gPSBnbG9iYWwubG9jYXRpb24gfHwge307XG4vKmpzbGludCBpbmRlbnQ6IDIsIGJyb3dzZXI6IHRydWUsIGJpdHdpc2U6IHRydWUsIHBsdXNwbHVzOiB0cnVlICovXG52YXIgdHdlbW9qaSA9IChmdW5jdGlvbiAoXG4gIC8qISBDb3B5cmlnaHQgVHdpdHRlciBJbmMuIGFuZCBvdGhlciBjb250cmlidXRvcnMuIExpY2Vuc2VkIHVuZGVyIE1JVCAqLy8qXG4gICAgaHR0cHM6Ly9naXRodWIuY29tL3R3aXR0ZXIvdHdlbW9qaS9ibG9iL2doLXBhZ2VzL0xJQ0VOU0VcbiAgKi9cblxuICAvLyBXQVJOSU5HOiAgIHRoaXMgZmlsZSBpcyBnZW5lcmF0ZWQgYXV0b21hdGljYWxseSB2aWFcbiAgLy8gICAgICAgICAgICBgbm9kZSBzY3JpcHRzL2J1aWxkLmpzYFxuICAvLyAgICAgICAgICAgIHBsZWFzZSB1cGRhdGUgaXRzIGBjcmVhdGVUd2Vtb2ppYCBmdW5jdGlvblxuICAvLyAgICAgICAgICAgIGF0IHRoZSBib3R0b20gb2YgdGhlIHNhbWUgZmlsZSBpbnN0ZWFkLlxuXG4pIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8qanNoaW50IG1heHBhcmFtczo0ICovXG5cbiAgdmFyXG4gICAgLy8gdGhlIGV4cG9ydGVkIG1vZHVsZSBvYmplY3RcbiAgICB0d2Vtb2ppID0ge1xuXG5cbiAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gICAgICBwcm9wZXJ0aWVzICAgICAvL1xuICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICAgICAgLy8gZGVmYXVsdCBhc3NldHMgdXJsLCBieSBkZWZhdWx0IHdpbGwgYmUgVHdpdHRlciBJbmMuIENETlxuICAgICAgYmFzZTogJ2h0dHBzOi8vdHdlbW9qaS5tYXhjZG4uY29tL3YvMTMuMS4wLycsXG5cbiAgICAgIC8vIGRlZmF1bHQgYXNzZXRzIGZpbGUgZXh0ZW5zaW9ucywgYnkgZGVmYXVsdCAnLnBuZydcbiAgICAgIGV4dDogJy5wbmcnLFxuXG4gICAgICAvLyBkZWZhdWx0IGFzc2V0cy9mb2xkZXIgc2l6ZSwgYnkgZGVmYXVsdCBcIjcyeDcyXCJcbiAgICAgIC8vIGF2YWlsYWJsZSB2aWEgVHdpdHRlciBDRE46IDcyXG4gICAgICBzaXplOiAnNzJ4NzInLFxuXG4gICAgICAvLyBkZWZhdWx0IGNsYXNzIG5hbWUsIGJ5IGRlZmF1bHQgJ2Vtb2ppJ1xuICAgICAgY2xhc3NOYW1lOiAnZW1vamknLFxuXG4gICAgICAvLyBiYXNpYyB1dGlsaXRpZXMgLyBoZWxwZXJzIHRvIGNvbnZlcnQgY29kZSBwb2ludHNcbiAgICAgIC8vIHRvIEphdmFTY3JpcHQgc3Vycm9nYXRlcyBhbmQgdmljZSB2ZXJzYVxuICAgICAgY29udmVydDoge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHaXZlbiBhbiBIRVggY29kZXBvaW50LCByZXR1cm5zIFVURjE2IHN1cnJvZ2F0ZSBwYWlycy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtICAgc3RyaW5nICBnZW5lcmljIGNvZGVwb2ludCwgaS5lLiAnMUY0QTknXG4gICAgICAgICAqIEByZXR1cm4gIHN0cmluZyAgY29kZXBvaW50IHRyYW5zZm9ybWVkIGludG8gdXRmMTYgc3Vycm9nYXRlcyBwYWlyLFxuICAgICAgICAgKiAgICAgICAgICBpLmUuIFxcdUQ4M0RcXHVEQ0E5XG4gICAgICAgICAqXG4gICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAqICB0d2Vtb2ppLmNvbnZlcnQuZnJvbUNvZGVQb2ludCgnMWYxZTgnKTtcbiAgICAgICAgICogIC8vIFwiXFx1ZDgzY1xcdWRkZThcIlxuICAgICAgICAgKlxuICAgICAgICAgKiAgJzFmMWU4LTFmMWYzJy5zcGxpdCgnLScpLm1hcCh0d2Vtb2ppLmNvbnZlcnQuZnJvbUNvZGVQb2ludCkuam9pbignJylcbiAgICAgICAgICogIC8vIFwiXFx1ZDgzY1xcdWRkZThcXHVkODNjXFx1ZGRmM1wiXG4gICAgICAgICAqL1xuICAgICAgICBmcm9tQ29kZVBvaW50OiBmcm9tQ29kZVBvaW50LFxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHaXZlbiBVVEYxNiBzdXJyb2dhdGUgcGFpcnMsIHJldHVybnMgdGhlIGVxdWl2YWxlbnQgSEVYIGNvZGVwb2ludC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtICAgc3RyaW5nICBnZW5lcmljIHV0ZjE2IHN1cnJvZ2F0ZXMgcGFpciwgaS5lLiBcXHVEODNEXFx1RENBOVxuICAgICAgICAgKiBAcGFyYW0gICBzdHJpbmcgIG9wdGlvbmFsIHNlcGFyYXRvciBmb3IgZG91YmxlIGNvZGUgcG9pbnRzLCBkZWZhdWx0PSctJ1xuICAgICAgICAgKiBAcmV0dXJuICBzdHJpbmcgIHV0ZjE2IHRyYW5zZm9ybWVkIGludG8gY29kZXBvaW50LCBpLmUuICcxRjRBOSdcbiAgICAgICAgICpcbiAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICogIHR3ZW1vamkuY29udmVydC50b0NvZGVQb2ludCgnXFx1ZDgzY1xcdWRkZThcXHVkODNjXFx1ZGRmMycpO1xuICAgICAgICAgKiAgLy8gXCIxZjFlOC0xZjFmM1wiXG4gICAgICAgICAqXG4gICAgICAgICAqICB0d2Vtb2ppLmNvbnZlcnQudG9Db2RlUG9pbnQoJ1xcdWQ4M2NcXHVkZGU4XFx1ZDgzY1xcdWRkZjMnLCAnficpO1xuICAgICAgICAgKiAgLy8gXCIxZjFlOH4xZjFmM1wiXG4gICAgICAgICAqL1xuICAgICAgICB0b0NvZGVQb2ludDogdG9Db2RlUG9pbnRcbiAgICAgIH0sXG5cblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICAvLyAgICAgICBtZXRob2RzICAgICAgIC8vXG4gICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gICAgICAvKipcbiAgICAgICAqIFVzZXIgZmlyc3Q6IHVzZWQgdG8gcmVtb3ZlIG1pc3NpbmcgaW1hZ2VzXG4gICAgICAgKiBwcmVzZXJ2aW5nIHRoZSBvcmlnaW5hbCB0ZXh0IGludGVudCB3aGVuXG4gICAgICAgKiBhIGZhbGxiYWNrIGZvciBuZXR3b3JrIHByb2JsZW1zIGlzIGRlc2lyZWQuXG4gICAgICAgKiBBdXRvbWF0aWNhbGx5IGFkZGVkIHRvIEltYWdlIG5vZGVzIHZpYSBET01cbiAgICAgICAqIEl0IGNvdWxkIGJlIHJlY3ljbGVkIGZvciBzdHJpbmcgb3BlcmF0aW9ucyB2aWE6XG4gICAgICAgKiAgJCgnaW1nLmVtb2ppJykub24oJ2Vycm9yJywgdHdlbW9qaS5vbmVycm9yKVxuICAgICAgICovXG4gICAgICBvbmVycm9yOiBmdW5jdGlvbiBvbmVycm9yKCkge1xuICAgICAgICBpZiAodGhpcy5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgdGhpcy5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChjcmVhdGVUZXh0KHRoaXMuYWx0LCBmYWxzZSksIHRoaXMpO1xuICAgICAgICB9XG4gICAgICB9LFxuXG4gICAgICAvKipcbiAgICAgICAqIE1haW4gbWV0aG9kL2xvZ2ljIHRvIGdlbmVyYXRlIGVpdGhlciA8aW1nPiB0YWdzIG9yIEhUTUxJbWFnZSBub2Rlcy5cbiAgICAgICAqICBcImVtb2ppZnlcIiBhIGdlbmVyaWMgdGV4dCBvciBET00gRWxlbWVudC5cbiAgICAgICAqXG4gICAgICAgKiBAb3ZlcmxvYWRzXG4gICAgICAgKlxuICAgICAgICogU3RyaW5nIHJlcGxhY2VtZW50IGZvciBgaW5uZXJIVE1MYCBvciBzZXJ2ZXIgc2lkZSBvcGVyYXRpb25zXG4gICAgICAgKiAgdHdlbW9qaS5wYXJzZShzdHJpbmcpO1xuICAgICAgICogIHR3ZW1vamkucGFyc2Uoc3RyaW5nLCBGdW5jdGlvbik7XG4gICAgICAgKiAgdHdlbW9qaS5wYXJzZShzdHJpbmcsIE9iamVjdCk7XG4gICAgICAgKlxuICAgICAgICogSFRNTEVsZW1lbnQgdHJlZSBwYXJzaW5nIGZvciBzYWZlciBvcGVyYXRpb25zIG92ZXIgZXhpc3RpbmcgRE9NXG4gICAgICAgKiAgdHdlbW9qaS5wYXJzZShIVE1MRWxlbWVudCk7XG4gICAgICAgKiAgdHdlbW9qaS5wYXJzZShIVE1MRWxlbWVudCwgRnVuY3Rpb24pO1xuICAgICAgICogIHR3ZW1vamkucGFyc2UoSFRNTEVsZW1lbnQsIE9iamVjdCk7XG4gICAgICAgKlxuICAgICAgICogQHBhcmFtICAgc3RyaW5nfEhUTUxFbGVtZW50ICB0aGUgc291cmNlIHRvIHBhcnNlIGFuZCBlbnJpY2ggd2l0aCBlbW9qaS5cbiAgICAgICAqXG4gICAgICAgKiAgICAgICAgICBzdHJpbmcgICAgICAgICAgICAgIHJlcGxhY2UgZW1vamkgbWF0Y2hlcyB3aXRoIDxpbWc+IHRhZ3MuXG4gICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1haW5seSB1c2VkIHRvIGluamVjdCBlbW9qaSB2aWEgYGlubmVySFRNTGBcbiAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSXQgZG9lcyAqKm5vdCoqIHBhcnNlIHRoZSBzdHJpbmcgb3IgdmFsaWRhdGUgaXQsXG4gICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0IHNpbXBseSByZXBsYWNlcyBmb3VuZCBlbW9qaSB3aXRoIGEgdGFnLlxuICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOT1RFOiBiZSBzdXJlIHRoaXMgd29uJ3QgYWZmZWN0IHNlY3VyaXR5LlxuICAgICAgICpcbiAgICAgICAqICAgICAgICAgIEhUTUxFbGVtZW50ICAgICAgICAgd2FsayB0aHJvdWdoIHRoZSBET00gdHJlZSBhbmQgZmluZCBlbW9qaVxuICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGF0IGFyZSBpbnNpZGUgKip0ZXh0IG5vZGUgb25seSoqIChub2RlVHlwZSA9PT0gMylcbiAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWFpbmx5IHVzZWQgdG8gcHV0IGVtb2ppIGluIGFscmVhZHkgZ2VuZXJhdGVkIERPTVxuICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aXRob3V0IGNvbXByb21pc2luZyBzdXJyb3VuZGluZyBub2RlcyBhbmRcbiAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiphdm9pZGluZyoqIHRoZSB1c2FnZSBvZiBgaW5uZXJIVE1MYC5cbiAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogVXNpbmcgRE9NIGVsZW1lbnRzIGluc3RlYWQgb2Ygc3RyaW5ncyBzaG91bGRcbiAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1wcm92ZSBzZWN1cml0eSB3aXRob3V0IGNvbXByb21pc2luZyB0b28gbXVjaFxuICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJmb3JtYW5jZSBjb21wYXJlZCB3aXRoIGEgbGVzcyBzYWZlIGBpbm5lckhUTUxgLlxuICAgICAgICpcbiAgICAgICAqIEBwYXJhbSAgIEZ1bmN0aW9ufE9iamVjdCAgW29wdGlvbmFsXVxuICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlaXRoZXIgdGhlIGNhbGxiYWNrIHRoYXQgd2lsbCBiZSBpbnZva2VkIG9yIGFuIG9iamVjdFxuICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aXRoIGFsbCBwcm9wZXJ0aWVzIHRvIHVzZSBwZXIgZWFjaCBmb3VuZCBlbW9qaS5cbiAgICAgICAqXG4gICAgICAgKiAgICAgICAgICBGdW5jdGlvbiAgICAgICAgICAgIGlmIHNwZWNpZmllZCwgdGhpcyB3aWxsIGJlIGludm9rZWQgcGVyIGVhY2ggZW1vamlcbiAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhhdCBoYXMgYmVlbiBmb3VuZCB0aHJvdWdoIHRoZSBSZWdFeHAgZXhjZXB0XG4gICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRob3NlIGZvbGx3ZWQgYnkgdGhlIGludmFyaWFudCBcXHVGRTBFIChcImFzIHRleHRcIikuXG4gICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9uY2UgaW52b2tlZCwgcGFyYW1ldGVycyB3aWxsIGJlOlxuICAgICAgICpcbiAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpY29uSWQ6c3RyaW5nICAgICB0aGUgbG93ZXIgY2FzZSBIRVggY29kZSBwb2ludFxuICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGkuZS4gXCIxZjRhOVwiXG4gICAgICAgKlxuICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnM6T2JqZWN0ICAgIGFsbCBpbmZvIGZvciB0aGlzIHBhcnNpbmcgb3BlcmF0aW9uXG4gICAgICAgKlxuICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcmlhbnQ6Y2hhciAgICAgIHRoZSBvcHRpb25hbCBcXHVGRTBGIChcImFzIGltYWdlXCIpXG4gICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFudCwgaW4gY2FzZSB0aGlzIGluZm9cbiAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcyBhbnlob3cgbWVhbmluZ2Z1bC5cbiAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCeSBkZWZhdWx0IHRoaXMgaXMgaWdub3JlZC5cbiAgICAgICAqXG4gICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIElmIHN1Y2ggY2FsbGJhY2sgd2lsbCByZXR1cm4gYSBmYWxzeSB2YWx1ZSBpbnN0ZWFkXG4gICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mIGEgdmFsaWQgYHNyY2AgdG8gdXNlIGZvciB0aGUgaW1hZ2UsIG5vdGhpbmcgd2lsbFxuICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3R1YWxseSBjaGFuZ2UgZm9yIHRoYXQgc3BlY2lmaWMgZW1vamkuXG4gICAgICAgKlxuICAgICAgICpcbiAgICAgICAqICAgICAgICAgIE9iamVjdCAgICAgICAgICAgICAgaWYgc3BlY2lmaWVkLCBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXNcbiAgICAgICAqXG4gICAgICAgKiAgICAgICAgICAgIGNhbGxiYWNrICAgRnVuY3Rpb24gIHRoZSBjYWxsYmFjayB0byBpbnZva2UgcGVyIGVhY2ggZm91bmQgZW1vamkuXG4gICAgICAgKiAgICAgICAgICAgIGJhc2UgICAgICAgc3RyaW5nICAgIHRoZSBiYXNlIHVybCwgYnkgZGVmYXVsdCB0d2Vtb2ppLmJhc2VcbiAgICAgICAqICAgICAgICAgICAgZXh0ICAgICAgICBzdHJpbmcgICAgdGhlIGltYWdlIGV4dGVuc2lvbiwgYnkgZGVmYXVsdCB0d2Vtb2ppLmV4dFxuICAgICAgICogICAgICAgICAgICBzaXplICAgICAgIHN0cmluZyAgICB0aGUgYXNzZXRzIHNpemUsIGJ5IGRlZmF1bHQgdHdlbW9qaS5zaXplXG4gICAgICAgKlxuICAgICAgICogQGV4YW1wbGVcbiAgICAgICAqXG4gICAgICAgKiAgdHdlbW9qaS5wYXJzZShcIkkgXFx1Mjc2NFxcdUZFMEYgZW1vamkhXCIpO1xuICAgICAgICogIC8vIEkgPGltZyBjbGFzcz1cImVtb2ppXCIgZHJhZ2dhYmxlPVwiZmFsc2VcIiBhbHQ9XCLinaTvuI9cIiBzcmM9XCIvYXNzZXRzLzI3NjQuZ2lmXCIvPiBlbW9qaSFcbiAgICAgICAqXG4gICAgICAgKlxuICAgICAgICogIHR3ZW1vamkucGFyc2UoXCJJIFxcdTI3NjRcXHVGRTBGIGVtb2ppIVwiLCBmdW5jdGlvbihpY29uSWQsIG9wdGlvbnMpIHtcbiAgICAgICAqICAgIHJldHVybiAnL2Fzc2V0cy8nICsgaWNvbklkICsgJy5naWYnO1xuICAgICAgICogIH0pO1xuICAgICAgICogIC8vIEkgPGltZyBjbGFzcz1cImVtb2ppXCIgZHJhZ2dhYmxlPVwiZmFsc2VcIiBhbHQ9XCLinaTvuI9cIiBzcmM9XCIvYXNzZXRzLzI3NjQuZ2lmXCIvPiBlbW9qaSFcbiAgICAgICAqXG4gICAgICAgKlxuICAgICAgICogdHdlbW9qaS5wYXJzZShcIkkgXFx1Mjc2NFxcdUZFMEYgZW1vamkhXCIsIHtcbiAgICAgICAqICAgc2l6ZTogNzIsXG4gICAgICAgKiAgIGNhbGxiYWNrOiBmdW5jdGlvbihpY29uSWQsIG9wdGlvbnMpIHtcbiAgICAgICAqICAgICByZXR1cm4gJy9hc3NldHMvJyArIG9wdGlvbnMuc2l6ZSArICcvJyArIGljb25JZCArIG9wdGlvbnMuZXh0O1xuICAgICAgICogICB9XG4gICAgICAgKiB9KTtcbiAgICAgICAqICAvLyBJIDxpbWcgY2xhc3M9XCJlbW9qaVwiIGRyYWdnYWJsZT1cImZhbHNlXCIgYWx0PVwi4p2k77iPXCIgc3JjPVwiL2Fzc2V0cy83Mng3Mi8yNzY0LnBuZ1wiLz4gZW1vamkhXG4gICAgICAgKlxuICAgICAgICovXG4gICAgICBwYXJzZTogcGFyc2UsXG5cbiAgICAgIC8qKlxuICAgICAgICogR2l2ZW4gYSBzdHJpbmcsIGludm9rZXMgdGhlIGNhbGxiYWNrIGFyZ3VtZW50XG4gICAgICAgKiAgcGVyIGVhY2ggZW1vamkgZm91bmQgaW4gc3VjaCBzdHJpbmcuXG4gICAgICAgKiBUaGlzIGlzIHRoZSBtb3N0IHJhdyB2ZXJzaW9uIHVzZWQgYnlcbiAgICAgICAqICB0aGUgLnBhcnNlKHN0cmluZykgbWV0aG9kIGl0c2VsZi5cbiAgICAgICAqXG4gICAgICAgKiBAcGFyYW0gICBzdHJpbmcgICAgZ2VuZXJpYyBzdHJpbmcgdG8gcGFyc2VcbiAgICAgICAqIEBwYXJhbSAgIEZ1bmN0aW9uICBhIGdlbmVyaWMgY2FsbGJhY2sgdGhhdCB3aWxsIGJlXG4gICAgICAgKiAgICAgICAgICAgICAgICAgICAgaW52b2tlZCB0byByZXBsYWNlIHRoZSBjb250ZW50LlxuICAgICAgICogICAgICAgICAgICAgICAgICAgIFRoaXMgY2FsbGJhY2sgd2lsbCByZWNlaXZlIHN0YW5kYXJkXG4gICAgICAgKiAgICAgICAgICAgICAgICAgICAgU3RyaW5nLnByb3RvdHlwZS5yZXBsYWNlKHN0ciwgY2FsbGJhY2spXG4gICAgICAgKiAgICAgICAgICAgICAgICAgICAgYXJndW1lbnRzIHN1Y2g6XG4gICAgICAgKiAgY2FsbGJhY2soXG4gICAgICAgKiAgICByYXdUZXh0LCAgLy8gdGhlIGVtb2ppIG1hdGNoXG4gICAgICAgKiAgKTtcbiAgICAgICAqXG4gICAgICAgKiAgICAgICAgICAgICAgICAgICAgYW5kIG90aGVycyBjb21tb25seSByZWNlaXZlZCB2aWEgcmVwbGFjZS5cbiAgICAgICAqL1xuICAgICAgcmVwbGFjZTogcmVwbGFjZSxcblxuICAgICAgLyoqXG4gICAgICAgKiBTaW1wbGlmeSBzdHJpbmcgdGVzdHMgYWdhaW5zdCBlbW9qaS5cbiAgICAgICAqXG4gICAgICAgKiBAcGFyYW0gICBzdHJpbmcgIHNvbWUgdGV4dCB0aGF0IG1pZ2h0IGNvbnRhaW4gZW1vamlcbiAgICAgICAqIEByZXR1cm4gIGJvb2xlYW4gdHJ1ZSBpZiBhbnkgZW1vamkgd2FzIGZvdW5kLCBmYWxzZSBvdGhlcndpc2UuXG4gICAgICAgKlxuICAgICAgICogQGV4YW1wbGVcbiAgICAgICAqXG4gICAgICAgKiAgaWYgKHR3ZW1vamkudGVzdChzb21lQ29udGVudCkpIHtcbiAgICAgICAqICAgIGNvbnNvbGUubG9nKFwiZW1vamkgQWxsIFRoZSBUaGluZ3MhXCIpO1xuICAgICAgICogIH1cbiAgICAgICAqL1xuICAgICAgdGVzdDogdGVzdFxuICAgIH0sXG5cbiAgICAvLyB1c2VkIHRvIGVzY2FwZSBIVE1MIHNwZWNpYWwgY2hhcnMgaW4gYXR0cmlidXRlc1xuICAgIGVzY2FwZXIgPSB7XG4gICAgICAnJic6ICcmYW1wOycsXG4gICAgICAnPCc6ICcmbHQ7JyxcbiAgICAgICc+JzogJyZndDsnLFxuICAgICAgXCInXCI6ICcmIzM5OycsXG4gICAgICAnXCInOiAnJnF1b3Q7J1xuICAgIH0sXG5cbiAgICAvLyBSZWdFeHAgYmFzZWQgb24gZW1vamkncyBvZmZpY2lhbCBVbmljb2RlIHN0YW5kYXJkc1xuICAgIC8vIGh0dHA6Ly93d3cudW5pY29kZS5vcmcvUHVibGljL1VOSURBVEEvRW1vamlTb3VyY2VzLnR4dFxuICAgIHJlID0gLyg/OlxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1xcdWRmZmJcXHUyMDBkXFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZFxcdWRjOGJcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjhcXHVkODNjXFx1ZGZmY1xcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM4YlxcdTIwMGRcXHVkODNkXFx1ZGM2OFxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXXxcXHVkODNkXFx1ZGM2OFxcdWQ4M2NcXHVkZmZkXFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzhiXFx1MjAwZFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1xcdWRmZmVcXHUyMDBkXFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZFxcdWRjOGJcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjhcXHVkODNjXFx1ZGZmZlxcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM4YlxcdTIwMGRcXHVkODNkXFx1ZGM2OFxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXXxcXHVkODNkXFx1ZGM2OVxcdWQ4M2NcXHVkZmZiXFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzhiXFx1MjAwZFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1xcdWRmZmJcXHUyMDBkXFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZFxcdWRjOGJcXHUyMDBkXFx1ZDgzZFxcdWRjNjlcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjlcXHVkODNjXFx1ZGZmY1xcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM4YlxcdTIwMGRcXHVkODNkXFx1ZGM2OFxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXXxcXHVkODNkXFx1ZGM2OVxcdWQ4M2NcXHVkZmZjXFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzhiXFx1MjAwZFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1xcdWRmZmRcXHUyMDBkXFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZFxcdWRjOGJcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjlcXHVkODNjXFx1ZGZmZFxcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM4YlxcdTIwMGRcXHVkODNkXFx1ZGM2OVxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXXxcXHVkODNkXFx1ZGM2OVxcdWQ4M2NcXHVkZmZlXFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzhiXFx1MjAwZFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1xcdWRmZmVcXHUyMDBkXFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZFxcdWRjOGJcXHUyMDBkXFx1ZDgzZFxcdWRjNjlcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjlcXHVkODNjXFx1ZGZmZlxcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM4YlxcdTIwMGRcXHVkODNkXFx1ZGM2OFxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXXxcXHVkODNkXFx1ZGM2OVxcdWQ4M2NcXHVkZmZmXFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzhiXFx1MjAwZFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2VcXHVkZGQxXFx1ZDgzY1xcdWRmZmJcXHUyMDBkXFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZFxcdWRjOGJcXHUyMDBkXFx1ZDgzZVxcdWRkZDFcXHVkODNjW1xcdWRmZmMtXFx1ZGZmZl18XFx1ZDgzZVxcdWRkZDFcXHVkODNjXFx1ZGZmY1xcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM4YlxcdTIwMGRcXHVkODNlXFx1ZGRkMVxcdWQ4M2NbXFx1ZGZmYlxcdWRmZmQtXFx1ZGZmZl18XFx1ZDgzZVxcdWRkZDFcXHVkODNjXFx1ZGZmZFxcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM4YlxcdTIwMGRcXHVkODNlXFx1ZGRkMVxcdWQ4M2NbXFx1ZGZmYlxcdWRmZmNcXHVkZmZlXFx1ZGZmZl18XFx1ZDgzZVxcdWRkZDFcXHVkODNjXFx1ZGZmZVxcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM4YlxcdTIwMGRcXHVkODNlXFx1ZGRkMVxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZkXFx1ZGZmZl18XFx1ZDgzZVxcdWRkZDFcXHVkODNjXFx1ZGZmZlxcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM4YlxcdTIwMGRcXHVkODNlXFx1ZGRkMVxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZlXXxcXHVkODNkXFx1ZGM2OFxcdWQ4M2NcXHVkZmZiXFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1xcdWRmZmJcXHUyMDBkXFx1ZDgzZVxcdWRkMWRcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHVkODNjW1xcdWRmZmMtXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjhcXHVkODNjXFx1ZGZmY1xcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM2OFxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXXxcXHVkODNkXFx1ZGM2OFxcdWQ4M2NcXHVkZmZjXFx1MjAwZFxcdWQ4M2VcXHVkZDFkXFx1MjAwZFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1tcXHVkZmZiXFx1ZGZmZC1cXHVkZmZmXXxcXHVkODNkXFx1ZGM2OFxcdWQ4M2NcXHVkZmZkXFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1xcdWRmZmRcXHUyMDBkXFx1ZDgzZVxcdWRkMWRcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHVkODNjW1xcdWRmZmJcXHVkZmZjXFx1ZGZmZVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1xcdWRmZmVcXHUyMDBkXFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjhcXHVkODNjXFx1ZGZmZVxcdTIwMGRcXHVkODNlXFx1ZGQxZFxcdTIwMGRcXHVkODNkXFx1ZGM2OFxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZkXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjhcXHVkODNjXFx1ZGZmZlxcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM2OFxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXXxcXHVkODNkXFx1ZGM2OFxcdWQ4M2NcXHVkZmZmXFx1MjAwZFxcdWQ4M2VcXHVkZDFkXFx1MjAwZFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmVdfFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1xcdWRmZmJcXHUyMDBkXFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjlcXHVkODNjXFx1ZGZmYlxcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM2OVxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXXxcXHVkODNkXFx1ZGM2OVxcdWQ4M2NcXHVkZmZiXFx1MjAwZFxcdWQ4M2VcXHVkZDFkXFx1MjAwZFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1tcXHVkZmZjLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1xcdWRmZmJcXHUyMDBkXFx1ZDgzZVxcdWRkMWRcXHUyMDBkXFx1ZDgzZFxcdWRjNjlcXHVkODNjW1xcdWRmZmMtXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjlcXHVkODNjXFx1ZGZmY1xcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM2OFxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXXxcXHVkODNkXFx1ZGM2OVxcdWQ4M2NcXHVkZmZjXFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1xcdWRmZmNcXHUyMDBkXFx1ZDgzZVxcdWRkMWRcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHVkODNjW1xcdWRmZmJcXHVkZmZkLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1xcdWRmZmNcXHUyMDBkXFx1ZDgzZVxcdWRkMWRcXHUyMDBkXFx1ZDgzZFxcdWRjNjlcXHVkODNjW1xcdWRmZmJcXHVkZmZkLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1xcdWRmZmRcXHUyMDBkXFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjlcXHVkODNjXFx1ZGZmZFxcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM2OVxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXXxcXHVkODNkXFx1ZGM2OVxcdWQ4M2NcXHVkZmZkXFx1MjAwZFxcdWQ4M2VcXHVkZDFkXFx1MjAwZFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1tcXHVkZmZiXFx1ZGZmY1xcdWRmZmVcXHVkZmZmXXxcXHVkODNkXFx1ZGM2OVxcdWQ4M2NcXHVkZmZkXFx1MjAwZFxcdWQ4M2VcXHVkZDFkXFx1MjAwZFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1tcXHVkZmZiXFx1ZGZmY1xcdWRmZmVcXHVkZmZmXXxcXHVkODNkXFx1ZGM2OVxcdWQ4M2NcXHVkZmZlXFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzY4XFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1xcdWRmZmVcXHUyMDBkXFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZFxcdWRjNjlcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjlcXHVkODNjXFx1ZGZmZVxcdTIwMGRcXHVkODNlXFx1ZGQxZFxcdTIwMGRcXHVkODNkXFx1ZGM2OFxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZkXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjlcXHVkODNjXFx1ZGZmZVxcdTIwMGRcXHVkODNlXFx1ZGQxZFxcdTIwMGRcXHVkODNkXFx1ZGM2OVxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZkXFx1ZGZmZl18XFx1ZDgzZFxcdWRjNjlcXHVkODNjXFx1ZGZmZlxcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNkXFx1ZGM2OFxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXXxcXHVkODNkXFx1ZGM2OVxcdWQ4M2NcXHVkZmZmXFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY5XFx1ZDgzY1xcdWRmZmZcXHUyMDBkXFx1ZDgzZVxcdWRkMWRcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHVkODNjW1xcdWRmZmItXFx1ZGZmZV18XFx1ZDgzZFxcdWRjNjlcXHVkODNjXFx1ZGZmZlxcdTIwMGRcXHVkODNlXFx1ZGQxZFxcdTIwMGRcXHVkODNkXFx1ZGM2OVxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZlXXxcXHVkODNlXFx1ZGRkMVxcdWQ4M2NcXHVkZmZiXFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2VcXHVkZGQxXFx1ZDgzY1tcXHVkZmZjLVxcdWRmZmZdfFxcdWQ4M2VcXHVkZGQxXFx1ZDgzY1xcdWRmZmJcXHUyMDBkXFx1ZDgzZVxcdWRkMWRcXHUyMDBkXFx1ZDgzZVxcdWRkZDFcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl18XFx1ZDgzZVxcdWRkZDFcXHVkODNjXFx1ZGZmY1xcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNlXFx1ZGRkMVxcdWQ4M2NbXFx1ZGZmYlxcdWRmZmQtXFx1ZGZmZl18XFx1ZDgzZVxcdWRkZDFcXHVkODNjXFx1ZGZmY1xcdTIwMGRcXHVkODNlXFx1ZGQxZFxcdTIwMGRcXHVkODNlXFx1ZGRkMVxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXXxcXHVkODNlXFx1ZGRkMVxcdWQ4M2NcXHVkZmZkXFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2VcXHVkZGQxXFx1ZDgzY1tcXHVkZmZiXFx1ZGZmY1xcdWRmZmVcXHVkZmZmXXxcXHVkODNlXFx1ZGRkMVxcdWQ4M2NcXHVkZmZkXFx1MjAwZFxcdWQ4M2VcXHVkZDFkXFx1MjAwZFxcdWQ4M2VcXHVkZGQxXFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2VcXHVkZGQxXFx1ZDgzY1xcdWRmZmVcXHUyMDBkXFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZVxcdWRkZDFcXHVkODNjW1xcdWRmZmItXFx1ZGZmZFxcdWRmZmZdfFxcdWQ4M2VcXHVkZGQxXFx1ZDgzY1xcdWRmZmVcXHUyMDBkXFx1ZDgzZVxcdWRkMWRcXHUyMDBkXFx1ZDgzZVxcdWRkZDFcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl18XFx1ZDgzZVxcdWRkZDFcXHVkODNjXFx1ZGZmZlxcdTIwMGRcXHUyNzY0XFx1ZmUwZlxcdTIwMGRcXHVkODNlXFx1ZGRkMVxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZlXXxcXHVkODNlXFx1ZGRkMVxcdWQ4M2NcXHVkZmZmXFx1MjAwZFxcdWQ4M2VcXHVkZDFkXFx1MjAwZFxcdWQ4M2VcXHVkZGQxXFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzY4XFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzhiXFx1MjAwZFxcdWQ4M2RcXHVkYzY4fFxcdWQ4M2RcXHVkYzY5XFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzhiXFx1MjAwZFxcdWQ4M2RbXFx1ZGM2OFxcdWRjNjldfFxcdWQ4M2RcXHVkYzY4XFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RcXHVkYzY4fFxcdWQ4M2RcXHVkYzY5XFx1MjAwZFxcdTI3NjRcXHVmZTBmXFx1MjAwZFxcdWQ4M2RbXFx1ZGM2OFxcdWRjNjldfFxcdWQ4M2VcXHVkZGQxXFx1MjAwZFxcdWQ4M2VcXHVkZDFkXFx1MjAwZFxcdWQ4M2VcXHVkZGQxfFxcdWQ4M2RcXHVkYzZiXFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzZjXFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzZkXFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzhmXFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RcXHVkYzkxXFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdfFxcdWQ4M2RbXFx1ZGM2Yi1cXHVkYzZkXFx1ZGM4ZlxcdWRjOTFdKXwoPzpcXHVkODNkW1xcdWRjNjhcXHVkYzY5XXxcXHVkODNlXFx1ZGRkMSkoPzpcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl0pP1xcdTIwMGQoPzpcXHUyNjk1XFx1ZmUwZnxcXHUyNjk2XFx1ZmUwZnxcXHUyNzA4XFx1ZmUwZnxcXHVkODNjW1xcdWRmM2VcXHVkZjczXFx1ZGY3Y1xcdWRmODRcXHVkZjkzXFx1ZGZhNFxcdWRmYThcXHVkZmViXFx1ZGZlZF18XFx1ZDgzZFtcXHVkY2JiXFx1ZGNiY1xcdWRkMjdcXHVkZDJjXFx1ZGU4MFxcdWRlOTJdfFxcdWQ4M2VbXFx1ZGRhZi1cXHVkZGIzXFx1ZGRiY1xcdWRkYmRdKXwoPzpcXHVkODNjW1xcdWRmY2JcXHVkZmNjXXxcXHVkODNkW1xcdWRkNzRcXHVkZDc1XXxcXHUyNmY5KSgoPzpcXHVkODNjW1xcdWRmZmItXFx1ZGZmZl18XFx1ZmUwZilcXHUyMDBkW1xcdTI2NDBcXHUyNjQyXVxcdWZlMGYpfCg/OlxcdWQ4M2NbXFx1ZGZjM1xcdWRmYzRcXHVkZmNhXXxcXHVkODNkW1xcdWRjNmVcXHVkYzcwXFx1ZGM3MVxcdWRjNzNcXHVkYzc3XFx1ZGM4MVxcdWRjODJcXHVkYzg2XFx1ZGM4N1xcdWRlNDUtXFx1ZGU0N1xcdWRlNGJcXHVkZTRkXFx1ZGU0ZVxcdWRlYTNcXHVkZWI0LVxcdWRlYjZdfFxcdWQ4M2VbXFx1ZGQyNlxcdWRkMzVcXHVkZDM3LVxcdWRkMzlcXHVkZDNkXFx1ZGQzZVxcdWRkYjhcXHVkZGI5XFx1ZGRjZC1cXHVkZGNmXFx1ZGRkNFxcdWRkZDYtXFx1ZGRkZF0pKD86XFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdKT9cXHUyMDBkW1xcdTI2NDBcXHUyNjQyXVxcdWZlMGZ8KD86XFx1ZDgzZFxcdWRjNjhcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHUyMDBkXFx1ZDgzZFxcdWRjNjZcXHUyMDBkXFx1ZDgzZFxcdWRjNjZ8XFx1ZDgzZFxcdWRjNjhcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHUyMDBkXFx1ZDgzZFxcdWRjNjdcXHUyMDBkXFx1ZDgzZFtcXHVkYzY2XFx1ZGM2N118XFx1ZDgzZFxcdWRjNjhcXHUyMDBkXFx1ZDgzZFxcdWRjNjlcXHUyMDBkXFx1ZDgzZFxcdWRjNjZcXHUyMDBkXFx1ZDgzZFxcdWRjNjZ8XFx1ZDgzZFxcdWRjNjhcXHUyMDBkXFx1ZDgzZFxcdWRjNjlcXHUyMDBkXFx1ZDgzZFxcdWRjNjdcXHUyMDBkXFx1ZDgzZFtcXHVkYzY2XFx1ZGM2N118XFx1ZDgzZFxcdWRjNjlcXHUyMDBkXFx1ZDgzZFxcdWRjNjlcXHUyMDBkXFx1ZDgzZFxcdWRjNjZcXHUyMDBkXFx1ZDgzZFxcdWRjNjZ8XFx1ZDgzZFxcdWRjNjlcXHUyMDBkXFx1ZDgzZFxcdWRjNjlcXHUyMDBkXFx1ZDgzZFxcdWRjNjdcXHUyMDBkXFx1ZDgzZFtcXHVkYzY2XFx1ZGM2N118XFx1ZDgzZFxcdWRjNjhcXHUyMDBkXFx1ZDgzZFxcdWRjNjZcXHUyMDBkXFx1ZDgzZFxcdWRjNjZ8XFx1ZDgzZFxcdWRjNjhcXHUyMDBkXFx1ZDgzZFxcdWRjNjdcXHUyMDBkXFx1ZDgzZFtcXHVkYzY2XFx1ZGM2N118XFx1ZDgzZFxcdWRjNjhcXHUyMDBkXFx1ZDgzZFxcdWRjNjhcXHUyMDBkXFx1ZDgzZFtcXHVkYzY2XFx1ZGM2N118XFx1ZDgzZFxcdWRjNjhcXHUyMDBkXFx1ZDgzZFxcdWRjNjlcXHUyMDBkXFx1ZDgzZFtcXHVkYzY2XFx1ZGM2N118XFx1ZDgzZFxcdWRjNjlcXHUyMDBkXFx1ZDgzZFxcdWRjNjZcXHUyMDBkXFx1ZDgzZFxcdWRjNjZ8XFx1ZDgzZFxcdWRjNjlcXHUyMDBkXFx1ZDgzZFxcdWRjNjdcXHUyMDBkXFx1ZDgzZFtcXHVkYzY2XFx1ZGM2N118XFx1ZDgzZFxcdWRjNjlcXHUyMDBkXFx1ZDgzZFxcdWRjNjlcXHUyMDBkXFx1ZDgzZFtcXHVkYzY2XFx1ZGM2N118XFx1ZDgzY1xcdWRmZjNcXHVmZTBmXFx1MjAwZFxcdTI2YTdcXHVmZTBmfFxcdWQ4M2NcXHVkZmYzXFx1ZmUwZlxcdTIwMGRcXHVkODNjXFx1ZGYwOHxcXHVkODNkXFx1ZGUzNlxcdTIwMGRcXHVkODNjXFx1ZGYyYlxcdWZlMGZ8XFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZFxcdWRkMjV8XFx1Mjc2NFxcdWZlMGZcXHUyMDBkXFx1ZDgzZVxcdWRlNzl8XFx1ZDgzY1xcdWRmZjRcXHUyMDBkXFx1MjYyMFxcdWZlMGZ8XFx1ZDgzZFxcdWRjMTVcXHUyMDBkXFx1ZDgzZVxcdWRkYmF8XFx1ZDgzZFxcdWRjM2JcXHUyMDBkXFx1Mjc0NFxcdWZlMGZ8XFx1ZDgzZFxcdWRjNDFcXHUyMDBkXFx1ZDgzZFxcdWRkZTh8XFx1ZDgzZFxcdWRjNjhcXHUyMDBkXFx1ZDgzZFtcXHVkYzY2XFx1ZGM2N118XFx1ZDgzZFxcdWRjNjlcXHUyMDBkXFx1ZDgzZFtcXHVkYzY2XFx1ZGM2N118XFx1ZDgzZFxcdWRjNmZcXHUyMDBkXFx1MjY0MFxcdWZlMGZ8XFx1ZDgzZFxcdWRjNmZcXHUyMDBkXFx1MjY0MlxcdWZlMGZ8XFx1ZDgzZFxcdWRlMmVcXHUyMDBkXFx1ZDgzZFxcdWRjYTh8XFx1ZDgzZFxcdWRlMzVcXHUyMDBkXFx1ZDgzZFxcdWRjYWJ8XFx1ZDgzZVxcdWRkM2NcXHUyMDBkXFx1MjY0MFxcdWZlMGZ8XFx1ZDgzZVxcdWRkM2NcXHUyMDBkXFx1MjY0MlxcdWZlMGZ8XFx1ZDgzZVxcdWRkZGVcXHUyMDBkXFx1MjY0MFxcdWZlMGZ8XFx1ZDgzZVxcdWRkZGVcXHUyMDBkXFx1MjY0MlxcdWZlMGZ8XFx1ZDgzZVxcdWRkZGZcXHUyMDBkXFx1MjY0MFxcdWZlMGZ8XFx1ZDgzZVxcdWRkZGZcXHUyMDBkXFx1MjY0MlxcdWZlMGZ8XFx1ZDgzZFxcdWRjMDhcXHUyMDBkXFx1MmIxYil8WyMqMC05XVxcdWZlMGY/XFx1MjBlM3woPzpbwqnCrlxcdTIxMjJcXHUyNjVmXVxcdWZlMGYpfCg/OlxcdWQ4M2NbXFx1ZGMwNFxcdWRkNzBcXHVkZDcxXFx1ZGQ3ZVxcdWRkN2ZcXHVkZTAyXFx1ZGUxYVxcdWRlMmZcXHVkZTM3XFx1ZGYyMVxcdWRmMjQtXFx1ZGYyY1xcdWRmMzZcXHVkZjdkXFx1ZGY5NlxcdWRmOTdcXHVkZjk5LVxcdWRmOWJcXHVkZjllXFx1ZGY5ZlxcdWRmY2RcXHVkZmNlXFx1ZGZkNC1cXHVkZmRmXFx1ZGZmM1xcdWRmZjVcXHVkZmY3XXxcXHVkODNkW1xcdWRjM2ZcXHVkYzQxXFx1ZGNmZFxcdWRkNDlcXHVkZDRhXFx1ZGQ2ZlxcdWRkNzBcXHVkZDczXFx1ZGQ3Ni1cXHVkZDc5XFx1ZGQ4N1xcdWRkOGEtXFx1ZGQ4ZFxcdWRkYTVcXHVkZGE4XFx1ZGRiMVxcdWRkYjJcXHVkZGJjXFx1ZGRjMi1cXHVkZGM0XFx1ZGRkMS1cXHVkZGQzXFx1ZGRkYy1cXHVkZGRlXFx1ZGRlMVxcdWRkZTNcXHVkZGU4XFx1ZGRlZlxcdWRkZjNcXHVkZGZhXFx1ZGVjYlxcdWRlY2QtXFx1ZGVjZlxcdWRlZTAtXFx1ZGVlNVxcdWRlZTlcXHVkZWYwXFx1ZGVmM118W1xcdTIwM2NcXHUyMDQ5XFx1MjEzOVxcdTIxOTQtXFx1MjE5OVxcdTIxYTlcXHUyMWFhXFx1MjMxYVxcdTIzMWJcXHUyMzI4XFx1MjNjZlxcdTIzZWQtXFx1MjNlZlxcdTIzZjFcXHUyM2YyXFx1MjNmOC1cXHUyM2ZhXFx1MjRjMlxcdTI1YWFcXHUyNWFiXFx1MjViNlxcdTI1YzBcXHUyNWZiLVxcdTI1ZmVcXHUyNjAwLVxcdTI2MDRcXHUyNjBlXFx1MjYxMVxcdTI2MTRcXHUyNjE1XFx1MjYxOFxcdTI2MjBcXHUyNjIyXFx1MjYyM1xcdTI2MjZcXHUyNjJhXFx1MjYyZVxcdTI2MmZcXHUyNjM4LVxcdTI2M2FcXHUyNjQwXFx1MjY0MlxcdTI2NDgtXFx1MjY1M1xcdTI2NjBcXHUyNjYzXFx1MjY2NVxcdTI2NjZcXHUyNjY4XFx1MjY3YlxcdTI2N2ZcXHUyNjkyLVxcdTI2OTdcXHUyNjk5XFx1MjY5YlxcdTI2OWNcXHUyNmEwXFx1MjZhMVxcdTI2YTdcXHUyNmFhXFx1MjZhYlxcdTI2YjBcXHUyNmIxXFx1MjZiZFxcdTI2YmVcXHUyNmM0XFx1MjZjNVxcdTI2YzhcXHUyNmNmXFx1MjZkMVxcdTI2ZDNcXHUyNmQ0XFx1MjZlOVxcdTI2ZWFcXHUyNmYwLVxcdTI2ZjVcXHUyNmY4XFx1MjZmYVxcdTI2ZmRcXHUyNzAyXFx1MjcwOFxcdTI3MDlcXHUyNzBmXFx1MjcxMlxcdTI3MTRcXHUyNzE2XFx1MjcxZFxcdTI3MjFcXHUyNzMzXFx1MjczNFxcdTI3NDRcXHUyNzQ3XFx1Mjc1N1xcdTI3NjNcXHUyNzY0XFx1MjdhMVxcdTI5MzRcXHUyOTM1XFx1MmIwNS1cXHUyYjA3XFx1MmIxYlxcdTJiMWNcXHUyYjUwXFx1MmI1NVxcdTMwMzBcXHUzMDNkXFx1MzI5N1xcdTMyOTldKSg/OlxcdWZlMGZ8KD8hXFx1ZmUwZSkpfCg/Oig/OlxcdWQ4M2NbXFx1ZGZjYlxcdWRmY2NdfFxcdWQ4M2RbXFx1ZGQ3NFxcdWRkNzVcXHVkZDkwXXxbXFx1MjYxZFxcdTI2ZjdcXHUyNmY5XFx1MjcwY1xcdTI3MGRdKSg/OlxcdWZlMGZ8KD8hXFx1ZmUwZSkpfCg/OlxcdWQ4M2NbXFx1ZGY4NVxcdWRmYzItXFx1ZGZjNFxcdWRmYzdcXHVkZmNhXXxcXHVkODNkW1xcdWRjNDJcXHVkYzQzXFx1ZGM0Ni1cXHVkYzUwXFx1ZGM2Ni1cXHVkYzY5XFx1ZGM2ZVxcdWRjNzAtXFx1ZGM3OFxcdWRjN2NcXHVkYzgxLVxcdWRjODNcXHVkYzg1LVxcdWRjODdcXHVkY2FhXFx1ZGQ3YVxcdWRkOTVcXHVkZDk2XFx1ZGU0NS1cXHVkZTQ3XFx1ZGU0Yi1cXHVkZTRmXFx1ZGVhM1xcdWRlYjQtXFx1ZGViNlxcdWRlYzBcXHVkZWNjXXxcXHVkODNlW1xcdWRkMGNcXHVkZDBmXFx1ZGQxOC1cXHVkZDFjXFx1ZGQxZVxcdWRkMWZcXHVkZDI2XFx1ZGQzMC1cXHVkZDM5XFx1ZGQzZFxcdWRkM2VcXHVkZDc3XFx1ZGRiNVxcdWRkYjZcXHVkZGI4XFx1ZGRiOVxcdWRkYmJcXHVkZGNkLVxcdWRkY2ZcXHVkZGQxLVxcdWRkZGRdfFtcXHUyNzBhXFx1MjcwYl0pKSg/OlxcdWQ4M2NbXFx1ZGZmYi1cXHVkZmZmXSk/fCg/OlxcdWQ4M2NcXHVkZmY0XFx1ZGI0MFxcdWRjNjdcXHVkYjQwXFx1ZGM2MlxcdWRiNDBcXHVkYzY1XFx1ZGI0MFxcdWRjNmVcXHVkYjQwXFx1ZGM2N1xcdWRiNDBcXHVkYzdmfFxcdWQ4M2NcXHVkZmY0XFx1ZGI0MFxcdWRjNjdcXHVkYjQwXFx1ZGM2MlxcdWRiNDBcXHVkYzczXFx1ZGI0MFxcdWRjNjNcXHVkYjQwXFx1ZGM3NFxcdWRiNDBcXHVkYzdmfFxcdWQ4M2NcXHVkZmY0XFx1ZGI0MFxcdWRjNjdcXHVkYjQwXFx1ZGM2MlxcdWRiNDBcXHVkYzc3XFx1ZGI0MFxcdWRjNmNcXHVkYjQwXFx1ZGM3M1xcdWRiNDBcXHVkYzdmfFxcdWQ4M2NcXHVkZGU2XFx1ZDgzY1tcXHVkZGU4LVxcdWRkZWNcXHVkZGVlXFx1ZGRmMVxcdWRkZjJcXHVkZGY0XFx1ZGRmNi1cXHVkZGZhXFx1ZGRmY1xcdWRkZmRcXHVkZGZmXXxcXHVkODNjXFx1ZGRlN1xcdWQ4M2NbXFx1ZGRlNlxcdWRkZTdcXHVkZGU5LVxcdWRkZWZcXHVkZGYxLVxcdWRkZjRcXHVkZGY2LVxcdWRkZjlcXHVkZGZiXFx1ZGRmY1xcdWRkZmVcXHVkZGZmXXxcXHVkODNjXFx1ZGRlOFxcdWQ4M2NbXFx1ZGRlNlxcdWRkZThcXHVkZGU5XFx1ZGRlYi1cXHVkZGVlXFx1ZGRmMC1cXHVkZGY1XFx1ZGRmN1xcdWRkZmEtXFx1ZGRmZl18XFx1ZDgzY1xcdWRkZTlcXHVkODNjW1xcdWRkZWFcXHVkZGVjXFx1ZGRlZlxcdWRkZjBcXHVkZGYyXFx1ZGRmNFxcdWRkZmZdfFxcdWQ4M2NcXHVkZGVhXFx1ZDgzY1tcXHVkZGU2XFx1ZGRlOFxcdWRkZWFcXHVkZGVjXFx1ZGRlZFxcdWRkZjctXFx1ZGRmYV18XFx1ZDgzY1xcdWRkZWJcXHVkODNjW1xcdWRkZWUtXFx1ZGRmMFxcdWRkZjJcXHVkZGY0XFx1ZGRmN118XFx1ZDgzY1xcdWRkZWNcXHVkODNjW1xcdWRkZTZcXHVkZGU3XFx1ZGRlOS1cXHVkZGVlXFx1ZGRmMS1cXHVkZGYzXFx1ZGRmNS1cXHVkZGZhXFx1ZGRmY1xcdWRkZmVdfFxcdWQ4M2NcXHVkZGVkXFx1ZDgzY1tcXHVkZGYwXFx1ZGRmMlxcdWRkZjNcXHVkZGY3XFx1ZGRmOVxcdWRkZmFdfFxcdWQ4M2NcXHVkZGVlXFx1ZDgzY1tcXHVkZGU4LVxcdWRkZWFcXHVkZGYxLVxcdWRkZjRcXHVkZGY2LVxcdWRkZjldfFxcdWQ4M2NcXHVkZGVmXFx1ZDgzY1tcXHVkZGVhXFx1ZGRmMlxcdWRkZjRcXHVkZGY1XXxcXHVkODNjXFx1ZGRmMFxcdWQ4M2NbXFx1ZGRlYVxcdWRkZWMtXFx1ZGRlZVxcdWRkZjJcXHVkZGYzXFx1ZGRmNVxcdWRkZjdcXHVkZGZjXFx1ZGRmZVxcdWRkZmZdfFxcdWQ4M2NcXHVkZGYxXFx1ZDgzY1tcXHVkZGU2LVxcdWRkZThcXHVkZGVlXFx1ZGRmMFxcdWRkZjctXFx1ZGRmYlxcdWRkZmVdfFxcdWQ4M2NcXHVkZGYyXFx1ZDgzY1tcXHVkZGU2XFx1ZGRlOC1cXHVkZGVkXFx1ZGRmMC1cXHVkZGZmXXxcXHVkODNjXFx1ZGRmM1xcdWQ4M2NbXFx1ZGRlNlxcdWRkZThcXHVkZGVhLVxcdWRkZWNcXHVkZGVlXFx1ZGRmMVxcdWRkZjRcXHVkZGY1XFx1ZGRmN1xcdWRkZmFcXHVkZGZmXXxcXHVkODNjXFx1ZGRmNFxcdWQ4M2NcXHVkZGYyfFxcdWQ4M2NcXHVkZGY1XFx1ZDgzY1tcXHVkZGU2XFx1ZGRlYS1cXHVkZGVkXFx1ZGRmMC1cXHVkZGYzXFx1ZGRmNy1cXHVkZGY5XFx1ZGRmY1xcdWRkZmVdfFxcdWQ4M2NcXHVkZGY2XFx1ZDgzY1xcdWRkZTZ8XFx1ZDgzY1xcdWRkZjdcXHVkODNjW1xcdWRkZWFcXHVkZGY0XFx1ZGRmOFxcdWRkZmFcXHVkZGZjXXxcXHVkODNjXFx1ZGRmOFxcdWQ4M2NbXFx1ZGRlNi1cXHVkZGVhXFx1ZGRlYy1cXHVkZGY0XFx1ZGRmNy1cXHVkZGY5XFx1ZGRmYlxcdWRkZmQtXFx1ZGRmZl18XFx1ZDgzY1xcdWRkZjlcXHVkODNjW1xcdWRkZTZcXHVkZGU4XFx1ZGRlOVxcdWRkZWItXFx1ZGRlZFxcdWRkZWYtXFx1ZGRmNFxcdWRkZjdcXHVkZGY5XFx1ZGRmYlxcdWRkZmNcXHVkZGZmXXxcXHVkODNjXFx1ZGRmYVxcdWQ4M2NbXFx1ZGRlNlxcdWRkZWNcXHVkZGYyXFx1ZGRmM1xcdWRkZjhcXHVkZGZlXFx1ZGRmZl18XFx1ZDgzY1xcdWRkZmJcXHVkODNjW1xcdWRkZTZcXHVkZGU4XFx1ZGRlYVxcdWRkZWNcXHVkZGVlXFx1ZGRmM1xcdWRkZmFdfFxcdWQ4M2NcXHVkZGZjXFx1ZDgzY1tcXHVkZGViXFx1ZGRmOF18XFx1ZDgzY1xcdWRkZmRcXHVkODNjXFx1ZGRmMHxcXHVkODNjXFx1ZGRmZVxcdWQ4M2NbXFx1ZGRlYVxcdWRkZjldfFxcdWQ4M2NcXHVkZGZmXFx1ZDgzY1tcXHVkZGU2XFx1ZGRmMlxcdWRkZmNdfFxcdWQ4M2NbXFx1ZGNjZlxcdWRkOGVcXHVkZDkxLVxcdWRkOWFcXHVkZGU2LVxcdWRkZmZcXHVkZTAxXFx1ZGUzMi1cXHVkZTM2XFx1ZGUzOC1cXHVkZTNhXFx1ZGU1MFxcdWRlNTFcXHVkZjAwLVxcdWRmMjBcXHVkZjJkLVxcdWRmMzVcXHVkZjM3LVxcdWRmN2NcXHVkZjdlLVxcdWRmODRcXHVkZjg2LVxcdWRmOTNcXHVkZmEwLVxcdWRmYzFcXHVkZmM1XFx1ZGZjNlxcdWRmYzhcXHVkZmM5XFx1ZGZjZi1cXHVkZmQzXFx1ZGZlMC1cXHVkZmYwXFx1ZGZmNFxcdWRmZjgtXFx1ZGZmZl18XFx1ZDgzZFtcXHVkYzAwLVxcdWRjM2VcXHVkYzQwXFx1ZGM0NFxcdWRjNDVcXHVkYzUxLVxcdWRjNjVcXHVkYzZhXFx1ZGM2ZlxcdWRjNzktXFx1ZGM3YlxcdWRjN2QtXFx1ZGM4MFxcdWRjODRcXHVkYzg4LVxcdWRjOGVcXHVkYzkwXFx1ZGM5Mi1cXHVkY2E5XFx1ZGNhYi1cXHVkY2ZjXFx1ZGNmZi1cXHVkZDNkXFx1ZGQ0Yi1cXHVkZDRlXFx1ZGQ1MC1cXHVkZDY3XFx1ZGRhNFxcdWRkZmItXFx1ZGU0NFxcdWRlNDgtXFx1ZGU0YVxcdWRlODAtXFx1ZGVhMlxcdWRlYTQtXFx1ZGViM1xcdWRlYjctXFx1ZGViZlxcdWRlYzEtXFx1ZGVjNVxcdWRlZDAtXFx1ZGVkMlxcdWRlZDUtXFx1ZGVkN1xcdWRlZWJcXHVkZWVjXFx1ZGVmNC1cXHVkZWZjXFx1ZGZlMC1cXHVkZmViXXxcXHVkODNlW1xcdWRkMGRcXHVkZDBlXFx1ZGQxMC1cXHVkZDE3XFx1ZGQxZFxcdWRkMjAtXFx1ZGQyNVxcdWRkMjctXFx1ZGQyZlxcdWRkM2FcXHVkZDNjXFx1ZGQzZi1cXHVkZDQ1XFx1ZGQ0Ny1cXHVkZDc2XFx1ZGQ3OFxcdWRkN2EtXFx1ZGRiNFxcdWRkYjdcXHVkZGJhXFx1ZGRiYy1cXHVkZGNiXFx1ZGRkMFxcdWRkZGUtXFx1ZGRmZlxcdWRlNzAtXFx1ZGU3NFxcdWRlNzgtXFx1ZGU3YVxcdWRlODAtXFx1ZGU4NlxcdWRlOTAtXFx1ZGVhOFxcdWRlYjAtXFx1ZGViNlxcdWRlYzAtXFx1ZGVjMlxcdWRlZDAtXFx1ZGVkNl18W1xcdTIzZTktXFx1MjNlY1xcdTIzZjBcXHUyM2YzXFx1MjY3ZVxcdTI2Y2VcXHUyNzA1XFx1MjcyOFxcdTI3NGNcXHUyNzRlXFx1Mjc1My1cXHUyNzU1XFx1Mjc5NS1cXHUyNzk3XFx1MjdiMFxcdTI3YmZcXHVlNTBhXSl8XFx1ZmUwZi9nLFxuXG4gICAgLy8gYXZvaWQgcnVudGltZSBSZWdFeHAgY3JlYXRpb24gZm9yIG5vdCBzbyBzbWFydCxcbiAgICAvLyBub3QgSklUIGJhc2VkLCBhbmQgb2xkIGJyb3dzZXJzIC8gZW5naW5lc1xuICAgIFVGRTBGZyA9IC9cXHVGRTBGL2csXG5cbiAgICAvLyBhdm9pZCB1c2luZyBhIHN0cmluZyBsaXRlcmFsIGxpa2UgJ1xcdTIwMEQnIGhlcmUgYmVjYXVzZSBtaW5pZmllcnMgZXhwYW5kIGl0IGlubGluZVxuICAgIFUyMDBEID0gU3RyaW5nLmZyb21DaGFyQ29kZSgweDIwMEQpLFxuXG4gICAgLy8gdXNlZCB0byBmaW5kIEhUTUwgc3BlY2lhbCBjaGFycyBpbiBhdHRyaWJ1dGVzXG4gICAgcmVzY2FwZXIgPSAvWyY8PidcIl0vZyxcblxuICAgIC8vIG5vZGVzIHdpdGggdHlwZSAxIHdoaWNoIHNob3VsZCAqKm5vdCoqIGJlIHBhcnNlZFxuICAgIHNob3VsZG50QmVQYXJzZWQgPSAvXig/OmlmcmFtZXxub2ZyYW1lc3xub3NjcmlwdHxzY3JpcHR8c2VsZWN0fHN0eWxlfHRleHRhcmVhKSQvLFxuXG4gICAgLy8ganVzdCBhIHByaXZhdGUgc2hvcnRjdXRcbiAgICBmcm9tQ2hhckNvZGUgPSBTdHJpbmcuZnJvbUNoYXJDb2RlO1xuXG4gIHJldHVybiB0d2Vtb2ppO1xuXG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAvLyAgcHJpdmF0ZSBmdW5jdGlvbnMgIC8vXG4gIC8vICAgICBkZWNsYXJhdGlvbiAgICAgLy9cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gIC8qKlxuICAgKiBTaG9ydGN1dCB0byBjcmVhdGUgdGV4dCBub2Rlc1xuICAgKiBAcGFyYW0gICBzdHJpbmcgIHRleHQgdXNlZCB0byBjcmVhdGUgRE9NIHRleHQgbm9kZVxuICAgKiBAcmV0dXJuICBOb2RlICBhIERPTSBub2RlIHdpdGggdGhhdCB0ZXh0XG4gICAqL1xuICBmdW5jdGlvbiBjcmVhdGVUZXh0KHRleHQsIGNsZWFuKSB7XG4gICAgcmV0dXJuIGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGNsZWFuID8gdGV4dC5yZXBsYWNlKFVGRTBGZywgJycpIDogdGV4dCk7XG4gIH1cblxuICAvKipcbiAgICogVXRpbGl0eSBmdW5jdGlvbiB0byBlc2NhcGUgaHRtbCBhdHRyaWJ1dGUgdGV4dFxuICAgKiBAcGFyYW0gICBzdHJpbmcgIHRleHQgdXNlIGluIEhUTUwgYXR0cmlidXRlXG4gICAqIEByZXR1cm4gIHN0cmluZyAgdGV4dCBlbmNvZGVkIHRvIHVzZSBpbiBIVE1MIGF0dHJpYnV0ZVxuICAgKi9cbiAgZnVuY3Rpb24gZXNjYXBlSFRNTChzKSB7XG4gICAgcmV0dXJuIHMucmVwbGFjZShyZXNjYXBlciwgcmVwbGFjZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlZmF1bHQgY2FsbGJhY2sgdXNlZCB0byBnZW5lcmF0ZSBlbW9qaSBzcmNcbiAgICogIGJhc2VkIG9uIFR3aXR0ZXIgQ0ROXG4gICAqIEBwYXJhbSAgIHN0cmluZyAgICB0aGUgZW1vamkgY29kZXBvaW50IHN0cmluZ1xuICAgKiBAcGFyYW0gICBzdHJpbmcgICAgdGhlIGRlZmF1bHQgc2l6ZSB0byB1c2UsIGkuZS4gXCIzNngzNlwiXG4gICAqIEByZXR1cm4gIHN0cmluZyAgICB0aGUgaW1hZ2Ugc291cmNlIHRvIHVzZVxuICAgKi9cbiAgZnVuY3Rpb24gZGVmYXVsdEltYWdlU3JjR2VuZXJhdG9yKGljb24sIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gJycuY29uY2F0KG9wdGlvbnMuYmFzZSwgb3B0aW9ucy5zaXplLCAnLycsIGljb24sIG9wdGlvbnMuZXh0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIGdlbmVyaWMgRE9NIG5vZGVUeXBlIDEsIHdhbGsgdGhyb3VnaCBhbGwgY2hpbGRyZW5cbiAgICogYW5kIHN0b3JlIGV2ZXJ5IG5vZGVUeXBlIDMgKCN0ZXh0KSBmb3VuZCBpbiB0aGUgdHJlZS5cbiAgICogQHBhcmFtICAgRWxlbWVudCBhIERPTSBFbGVtZW50IHdpdGggcHJvYmFibHkgc29tZSB0ZXh0IGluIGl0XG4gICAqIEBwYXJhbSAgIEFycmF5IHRoZSBsaXN0IG9mIHByZXZpb3VzbHkgZGlzY292ZXJlZCB0ZXh0IG5vZGVzXG4gICAqIEByZXR1cm4gIEFycmF5IHNhbWUgbGlzdCB3aXRoIG5ldyBkaXNjb3ZlcmVkIG5vZGVzLCBpZiBhbnlcbiAgICovXG4gIGZ1bmN0aW9uIGdyYWJBbGxUZXh0Tm9kZXMobm9kZSwgYWxsVGV4dCkge1xuICAgIHZhclxuICAgICAgY2hpbGROb2RlcyA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoLFxuICAgICAgc3Vibm9kZSxcbiAgICAgIG5vZGVUeXBlO1xuICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgc3Vibm9kZSA9IGNoaWxkTm9kZXNbbGVuZ3RoXTtcbiAgICAgIG5vZGVUeXBlID0gc3Vibm9kZS5ub2RlVHlwZTtcbiAgICAgIC8vIHBhcnNlIGVtb2ppIG9ubHkgaW4gdGV4dCBub2Rlc1xuICAgICAgaWYgKG5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgIC8vIGNvbGxlY3QgdGhlbSB0byBwcm9jZXNzIGVtb2ppIGxhdGVyXG4gICAgICAgIGFsbFRleHQucHVzaChzdWJub2RlKTtcbiAgICAgIH1cbiAgICAgIC8vIGlnbm9yZSBhbGwgbm9kZXMgdGhhdCBhcmUgbm90IHR5cGUgMSwgdGhhdCBhcmUgc3ZnLCBvciB0aGF0XG4gICAgICAvLyBzaG91bGQgbm90IGJlIHBhcnNlZCBhcyBzY3JpcHQsIHN0eWxlLCBhbmQgb3RoZXJzXG4gICAgICBlbHNlIGlmIChub2RlVHlwZSA9PT0gMSAmJiAhKCdvd25lclNWR0VsZW1lbnQnIGluIHN1Ym5vZGUpICYmXG4gICAgICAgICAgIXNob3VsZG50QmVQYXJzZWQudGVzdChzdWJub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkpKSB7XG4gICAgICAgIGdyYWJBbGxUZXh0Tm9kZXMoc3Vibm9kZSwgYWxsVGV4dCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhbGxUZXh0O1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gYm90aCByZW1vdmUgdGhlIHBvc3NpYmxlIHZhcmlhbnRcbiAgICogIGFuZCB0byBjb252ZXJ0IHV0ZjE2IGludG8gY29kZSBwb2ludHMuXG4gICAqICBJZiB0aGVyZSBpcyBhIHplcm8td2lkdGgtam9pbmVyIChVKzIwMEQpLCBsZWF2ZSB0aGUgdmFyaWFudHMgaW4uXG4gICAqIEBwYXJhbSAgIHN0cmluZyAgICB0aGUgcmF3IHRleHQgb2YgdGhlIGVtb2ppIG1hdGNoXG4gICAqIEByZXR1cm4gIHN0cmluZyAgICB0aGUgY29kZSBwb2ludFxuICAgKi9cbiAgZnVuY3Rpb24gZ3JhYlRoZVJpZ2h0SWNvbihyYXdUZXh0KSB7XG4gICAgLy8gaWYgdmFyaWFudCBpcyBwcmVzZW50IGFzIFxcdUZFMEZcbiAgICByZXR1cm4gdG9Db2RlUG9pbnQocmF3VGV4dC5pbmRleE9mKFUyMDBEKSA8IDAgP1xuICAgICAgcmF3VGV4dC5yZXBsYWNlKFVGRTBGZywgJycpIDpcbiAgICAgIHJhd1RleHRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIERPTSB2ZXJzaW9uIG9mIHRoZSBzYW1lIGxvZ2ljIC8gcGFyc2VyOlxuICAgKiAgZW1vamlmeSBhbGwgZm91bmQgc3ViLXRleHQgbm9kZXMgcGxhY2luZyBpbWFnZXMgbm9kZSBpbnN0ZWFkLlxuICAgKiBAcGFyYW0gICBFbGVtZW50ICAgZ2VuZXJpYyBET00gbm9kZSB3aXRoIHNvbWUgdGV4dCBpbiBzb21lIGNoaWxkIG5vZGVcbiAgICogQHBhcmFtICAgT2JqZWN0ICAgIG9wdGlvbnMgIGNvbnRhaW5pbmcgaW5mbyBhYm91dCBob3cgdG8gcGFyc2VcbiAgICAqXG4gICAgKiAgICAgICAgICAgIC5jYWxsYmFjayAgIEZ1bmN0aW9uICB0aGUgY2FsbGJhY2sgdG8gaW52b2tlIHBlciBlYWNoIGZvdW5kIGVtb2ppLlxuICAgICogICAgICAgICAgICAuYmFzZSAgICAgICBzdHJpbmcgICAgdGhlIGJhc2UgdXJsLCBieSBkZWZhdWx0IHR3ZW1vamkuYmFzZVxuICAgICogICAgICAgICAgICAuZXh0ICAgICAgICBzdHJpbmcgICAgdGhlIGltYWdlIGV4dGVuc2lvbiwgYnkgZGVmYXVsdCB0d2Vtb2ppLmV4dFxuICAgICogICAgICAgICAgICAuc2l6ZSAgICAgICBzdHJpbmcgICAgdGhlIGFzc2V0cyBzaXplLCBieSBkZWZhdWx0IHR3ZW1vamkuc2l6ZVxuICAgICpcbiAgICogQHJldHVybiAgRWxlbWVudCBzYW1lIGdlbmVyaWMgbm9kZSB3aXRoIGVtb2ppIGluIHBsYWNlLCBpZiBhbnkuXG4gICAqL1xuICBmdW5jdGlvbiBwYXJzZU5vZGUobm9kZSwgb3B0aW9ucykge1xuICAgIHZhclxuICAgICAgYWxsVGV4dCA9IGdyYWJBbGxUZXh0Tm9kZXMobm9kZSwgW10pLFxuICAgICAgbGVuZ3RoID0gYWxsVGV4dC5sZW5ndGgsXG4gICAgICBhdHRyaWIsXG4gICAgICBhdHRybmFtZSxcbiAgICAgIG1vZGlmaWVkLFxuICAgICAgZnJhZ21lbnQsXG4gICAgICBzdWJub2RlLFxuICAgICAgdGV4dCxcbiAgICAgIG1hdGNoLFxuICAgICAgaSxcbiAgICAgIGluZGV4LFxuICAgICAgaW1nLFxuICAgICAgcmF3VGV4dCxcbiAgICAgIGljb25JZCxcbiAgICAgIHNyYztcbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIG1vZGlmaWVkID0gZmFsc2U7XG4gICAgICBmcmFnbWVudCA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcbiAgICAgIHN1Ym5vZGUgPSBhbGxUZXh0W2xlbmd0aF07XG4gICAgICB0ZXh0ID0gc3Vibm9kZS5ub2RlVmFsdWU7XG4gICAgICBpID0gMDtcbiAgICAgIHdoaWxlICgobWF0Y2ggPSByZS5leGVjKHRleHQpKSkge1xuICAgICAgICBpbmRleCA9IG1hdGNoLmluZGV4O1xuICAgICAgICBpZiAoaW5kZXggIT09IGkpIHtcbiAgICAgICAgICBmcmFnbWVudC5hcHBlbmRDaGlsZChcbiAgICAgICAgICAgIGNyZWF0ZVRleHQodGV4dC5zbGljZShpLCBpbmRleCksIHRydWUpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByYXdUZXh0ID0gbWF0Y2hbMF07XG4gICAgICAgIGljb25JZCA9IGdyYWJUaGVSaWdodEljb24ocmF3VGV4dCk7XG4gICAgICAgIGkgPSBpbmRleCArIHJhd1RleHQubGVuZ3RoO1xuICAgICAgICBzcmMgPSBvcHRpb25zLmNhbGxiYWNrKGljb25JZCwgb3B0aW9ucyk7XG4gICAgICAgIGlmIChpY29uSWQgJiYgc3JjKSB7XG4gICAgICAgICAgaW1nID0gbmV3IEltYWdlKCk7XG4gICAgICAgICAgaW1nLm9uZXJyb3IgPSBvcHRpb25zLm9uZXJyb3I7XG4gICAgICAgICAgaW1nLnNldEF0dHJpYnV0ZSgnZHJhZ2dhYmxlJywgJ2ZhbHNlJyk7XG4gICAgICAgICAgYXR0cmliID0gb3B0aW9ucy5hdHRyaWJ1dGVzKHJhd1RleHQsIGljb25JZCk7XG4gICAgICAgICAgZm9yIChhdHRybmFtZSBpbiBhdHRyaWIpIHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgYXR0cmliLmhhc093blByb3BlcnR5KGF0dHJuYW1lKSAmJlxuICAgICAgICAgICAgICAvLyBkb24ndCBhbGxvdyBhbnkgaGFuZGxlcnMgdG8gYmUgc2V0ICsgZG9uJ3QgYWxsb3cgb3ZlcnJpZGVzXG4gICAgICAgICAgICAgIGF0dHJuYW1lLmluZGV4T2YoJ29uJykgIT09IDAgJiZcbiAgICAgICAgICAgICAgIWltZy5oYXNBdHRyaWJ1dGUoYXR0cm5hbWUpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgaW1nLnNldEF0dHJpYnV0ZShhdHRybmFtZSwgYXR0cmliW2F0dHJuYW1lXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGltZy5jbGFzc05hbWUgPSBvcHRpb25zLmNsYXNzTmFtZTtcbiAgICAgICAgICBpbWcuYWx0ID0gcmF3VGV4dDtcbiAgICAgICAgICBpbWcuc3JjID0gc3JjO1xuICAgICAgICAgIG1vZGlmaWVkID0gdHJ1ZTtcbiAgICAgICAgICBmcmFnbWVudC5hcHBlbmRDaGlsZChpbWcpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaW1nKSBmcmFnbWVudC5hcHBlbmRDaGlsZChjcmVhdGVUZXh0KHJhd1RleHQsIGZhbHNlKSk7XG4gICAgICAgIGltZyA9IG51bGw7XG4gICAgICB9XG4gICAgICAvLyBpcyB0aGVyZSBhY3R1YWxseSBhbnl0aGluZyB0byByZXBsYWNlIGluIGhlcmUgP1xuICAgICAgaWYgKG1vZGlmaWVkKSB7XG4gICAgICAgIC8vIGFueSB0ZXh0IGxlZnQgdG8gYmUgYWRkZWQgP1xuICAgICAgICBpZiAoaSA8IHRleHQubGVuZ3RoKSB7XG4gICAgICAgICAgZnJhZ21lbnQuYXBwZW5kQ2hpbGQoXG4gICAgICAgICAgICBjcmVhdGVUZXh0KHRleHQuc2xpY2UoaSksIHRydWUpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICAvLyByZXBsYWNlIHRoZSB0ZXh0IG5vZGUgb25seSwgbGVhdmUgaW50YWN0XG4gICAgICAgIC8vIGFueXRoaW5nIGVsc2Ugc3Vycm91bmRpbmcgc3VjaCB0ZXh0XG4gICAgICAgIHN1Ym5vZGUucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQoZnJhZ21lbnQsIHN1Ym5vZGUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdHJpbmcvSFRNTCB2ZXJzaW9uIG9mIHRoZSBzYW1lIGxvZ2ljIC8gcGFyc2VyOlxuICAgKiAgZW1vamlmeSBhIGdlbmVyaWMgdGV4dCBwbGFjaW5nIGltYWdlcyB0YWdzIGluc3RlYWQgb2Ygc3Vycm9nYXRlcyBwYWlyLlxuICAgKiBAcGFyYW0gICBzdHJpbmcgICAgZ2VuZXJpYyBzdHJpbmcgd2l0aCBwb3NzaWJseSBzb21lIGVtb2ppIGluIGl0XG4gICAqIEBwYXJhbSAgIE9iamVjdCAgICBvcHRpb25zICBjb250YWluaW5nIGluZm8gYWJvdXQgaG93IHRvIHBhcnNlXG4gICAqXG4gICAqICAgICAgICAgICAgLmNhbGxiYWNrICAgRnVuY3Rpb24gIHRoZSBjYWxsYmFjayB0byBpbnZva2UgcGVyIGVhY2ggZm91bmQgZW1vamkuXG4gICAqICAgICAgICAgICAgLmJhc2UgICAgICAgc3RyaW5nICAgIHRoZSBiYXNlIHVybCwgYnkgZGVmYXVsdCB0d2Vtb2ppLmJhc2VcbiAgICogICAgICAgICAgICAuZXh0ICAgICAgICBzdHJpbmcgICAgdGhlIGltYWdlIGV4dGVuc2lvbiwgYnkgZGVmYXVsdCB0d2Vtb2ppLmV4dFxuICAgKiAgICAgICAgICAgIC5zaXplICAgICAgIHN0cmluZyAgICB0aGUgYXNzZXRzIHNpemUsIGJ5IGRlZmF1bHQgdHdlbW9qaS5zaXplXG4gICAqXG4gICAqIEByZXR1cm4gIHRoZSBzdHJpbmcgd2l0aCA8aW1nIHRhZ3M+IHJlcGxhY2luZyBhbGwgZm91bmQgYW5kIHBhcnNlZCBlbW9qaVxuICAgKi9cbiAgZnVuY3Rpb24gcGFyc2VTdHJpbmcoc3RyLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIHJlcGxhY2Uoc3RyLCBmdW5jdGlvbiAocmF3VGV4dCkge1xuICAgICAgdmFyXG4gICAgICAgIHJldCA9IHJhd1RleHQsXG4gICAgICAgIGljb25JZCA9IGdyYWJUaGVSaWdodEljb24ocmF3VGV4dCksXG4gICAgICAgIHNyYyA9IG9wdGlvbnMuY2FsbGJhY2soaWNvbklkLCBvcHRpb25zKSxcbiAgICAgICAgYXR0cmliLFxuICAgICAgICBhdHRybmFtZTtcbiAgICAgIGlmIChpY29uSWQgJiYgc3JjKSB7XG4gICAgICAgIC8vIHJlY3ljbGUgdGhlIG1hdGNoIHN0cmluZyByZXBsYWNpbmcgdGhlIGVtb2ppXG4gICAgICAgIC8vIHdpdGggaXRzIGltYWdlIGNvdW50ZXIgcGFydFxuICAgICAgICByZXQgPSAnPGltZyAnLmNvbmNhdChcbiAgICAgICAgICAnY2xhc3M9XCInLCBvcHRpb25zLmNsYXNzTmFtZSwgJ1wiICcsXG4gICAgICAgICAgJ2RyYWdnYWJsZT1cImZhbHNlXCIgJyxcbiAgICAgICAgICAvLyBuZWVkcyB0byBwcmVzZXJ2ZSB1c2VyIG9yaWdpbmFsIGludGVudFxuICAgICAgICAgIC8vIHdoZW4gdmFyaWFudHMgc2hvdWxkIGJlIGNvcGllZCBhbmQgcGFzdGVkIHRvb1xuICAgICAgICAgICdhbHQ9XCInLFxuICAgICAgICAgIHJhd1RleHQsXG4gICAgICAgICAgJ1wiJyxcbiAgICAgICAgICAnIHNyYz1cIicsXG4gICAgICAgICAgc3JjLFxuICAgICAgICAgICdcIidcbiAgICAgICAgKTtcbiAgICAgICAgYXR0cmliID0gb3B0aW9ucy5hdHRyaWJ1dGVzKHJhd1RleHQsIGljb25JZCk7XG4gICAgICAgIGZvciAoYXR0cm5hbWUgaW4gYXR0cmliKSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgYXR0cmliLmhhc093blByb3BlcnR5KGF0dHJuYW1lKSAmJlxuICAgICAgICAgICAgLy8gZG9uJ3QgYWxsb3cgYW55IGhhbmRsZXJzIHRvIGJlIHNldCArIGRvbid0IGFsbG93IG92ZXJyaWRlc1xuICAgICAgICAgICAgYXR0cm5hbWUuaW5kZXhPZignb24nKSAhPT0gMCAmJlxuICAgICAgICAgICAgcmV0LmluZGV4T2YoJyAnICsgYXR0cm5hbWUgKyAnPScpID09PSAtMVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgcmV0ID0gcmV0LmNvbmNhdCgnICcsIGF0dHJuYW1lLCAnPVwiJywgZXNjYXBlSFRNTChhdHRyaWJbYXR0cm5hbWVdKSwgJ1wiJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldCA9IHJldC5jb25jYXQoJy8+Jyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEZ1bmN0aW9uIHVzZWQgdG8gYWN0dWFsbHkgcmVwbGFjZSBIVE1MIHNwZWNpYWwgY2hhcnNcbiAgICogQHBhcmFtICAgc3RyaW5nICBIVE1MIHNwZWNpYWwgY2hhclxuICAgKiBAcmV0dXJuICBzdHJpbmcgIGVuY29kZWQgSFRNTCBzcGVjaWFsIGNoYXJcbiAgICovXG4gIGZ1bmN0aW9uIHJlcGxhY2VyKG0pIHtcbiAgICByZXR1cm4gZXNjYXBlclttXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWZhdWx0IG9wdGlvbnMuYXR0cmlidXRlIGNhbGxiYWNrXG4gICAqIEByZXR1cm4gIG51bGxcbiAgICovXG4gIGZ1bmN0aW9uIHJldHVybk51bGwoKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBnZW5lcmljIHZhbHVlLCBjcmVhdGVzIGl0cyBzcXVhcmVkIGNvdW50ZXJwYXJ0IGlmIGl0J3MgYSBudW1iZXIuXG4gICAqICBBcyBleGFtcGxlLCBudW1iZXIgMzYgd2lsbCByZXR1cm4gJzM2eDM2Jy5cbiAgICogQHBhcmFtICAgYW55ICAgICBhIGdlbmVyaWMgdmFsdWUuXG4gICAqIEByZXR1cm4gIGFueSAgICAgYSBzdHJpbmcgcmVwcmVzZW50aW5nIGFzc2V0IHNpemUsIGkuZS4gXCIzNngzNlwiXG4gICAqICAgICAgICAgICAgICAgICAgb25seSBpbiBjYXNlIHRoZSB2YWx1ZSB3YXMgYSBudW1iZXIuXG4gICAqICAgICAgICAgICAgICAgICAgUmV0dXJucyBpbml0aWFsIHZhbHVlIG90aGVyd2lzZS5cbiAgICovXG4gIGZ1bmN0aW9uIHRvU2l6ZVNxdWFyZWRBc3NldCh2YWx1ZSkge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInID9cbiAgICAgIHZhbHVlICsgJ3gnICsgdmFsdWUgOlxuICAgICAgdmFsdWU7XG4gIH1cblxuXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgLy8gIGV4cG9ydGVkIGZ1bmN0aW9ucyAvL1xuICAvLyAgICAgZGVjbGFyYXRpb24gICAgIC8vXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICBmdW5jdGlvbiBmcm9tQ29kZVBvaW50KGNvZGVwb2ludCkge1xuICAgIHZhciBjb2RlID0gdHlwZW9mIGNvZGVwb2ludCA9PT0gJ3N0cmluZycgP1xuICAgICAgICAgIHBhcnNlSW50KGNvZGVwb2ludCwgMTYpIDogY29kZXBvaW50O1xuICAgIGlmIChjb2RlIDwgMHgxMDAwMCkge1xuICAgICAgcmV0dXJuIGZyb21DaGFyQ29kZShjb2RlKTtcbiAgICB9XG4gICAgY29kZSAtPSAweDEwMDAwO1xuICAgIHJldHVybiBmcm9tQ2hhckNvZGUoXG4gICAgICAweEQ4MDAgKyAoY29kZSA+PiAxMCksXG4gICAgICAweERDMDAgKyAoY29kZSAmIDB4M0ZGKVxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZSh3aGF0LCBob3cpIHtcbiAgICBpZiAoIWhvdyB8fCB0eXBlb2YgaG93ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBob3cgPSB7Y2FsbGJhY2s6IGhvd307XG4gICAgfVxuICAgIC8vIGlmIGZpcnN0IGFyZ3VtZW50IGlzIHN0cmluZywgaW5qZWN0IGh0bWwgPGltZz4gdGFnc1xuICAgIC8vIG90aGVyd2lzZSB1c2UgdGhlIERPTSB0cmVlIGFuZCBwYXJzZSB0ZXh0IG5vZGVzIG9ubHlcbiAgICByZXR1cm4gKHR5cGVvZiB3aGF0ID09PSAnc3RyaW5nJyA/IHBhcnNlU3RyaW5nIDogcGFyc2VOb2RlKSh3aGF0LCB7XG4gICAgICBjYWxsYmFjazogICBob3cuY2FsbGJhY2sgfHwgZGVmYXVsdEltYWdlU3JjR2VuZXJhdG9yLFxuICAgICAgYXR0cmlidXRlczogdHlwZW9mIGhvdy5hdHRyaWJ1dGVzID09PSAnZnVuY3Rpb24nID8gaG93LmF0dHJpYnV0ZXMgOiByZXR1cm5OdWxsLFxuICAgICAgYmFzZTogICAgICAgdHlwZW9mIGhvdy5iYXNlID09PSAnc3RyaW5nJyA/IGhvdy5iYXNlIDogdHdlbW9qaS5iYXNlLFxuICAgICAgZXh0OiAgICAgICAgaG93LmV4dCB8fCB0d2Vtb2ppLmV4dCxcbiAgICAgIHNpemU6ICAgICAgIGhvdy5mb2xkZXIgfHwgdG9TaXplU3F1YXJlZEFzc2V0KGhvdy5zaXplIHx8IHR3ZW1vamkuc2l6ZSksXG4gICAgICBjbGFzc05hbWU6ICBob3cuY2xhc3NOYW1lIHx8IHR3ZW1vamkuY2xhc3NOYW1lLFxuICAgICAgb25lcnJvcjogICAgaG93Lm9uZXJyb3IgfHwgdHdlbW9qaS5vbmVycm9yXG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiByZXBsYWNlKHRleHQsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIFN0cmluZyh0ZXh0KS5yZXBsYWNlKHJlLCBjYWxsYmFjayk7XG4gIH1cblxuICBmdW5jdGlvbiB0ZXN0KHRleHQpIHtcbiAgICAvLyBJRTYgbmVlZHMgYSByZXNldCBiZWZvcmUgdG9vXG4gICAgcmUubGFzdEluZGV4ID0gMDtcbiAgICB2YXIgcmVzdWx0ID0gcmUudGVzdCh0ZXh0KTtcbiAgICByZS5sYXN0SW5kZXggPSAwO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiB0b0NvZGVQb2ludCh1bmljb2RlU3Vycm9nYXRlcywgc2VwKSB7XG4gICAgdmFyXG4gICAgICByID0gW10sXG4gICAgICBjID0gMCxcbiAgICAgIHAgPSAwLFxuICAgICAgaSA9IDA7XG4gICAgd2hpbGUgKGkgPCB1bmljb2RlU3Vycm9nYXRlcy5sZW5ndGgpIHtcbiAgICAgIGMgPSB1bmljb2RlU3Vycm9nYXRlcy5jaGFyQ29kZUF0KGkrKyk7XG4gICAgICBpZiAocCkge1xuICAgICAgICByLnB1c2goKDB4MTAwMDAgKyAoKHAgLSAweEQ4MDApIDw8IDEwKSArIChjIC0gMHhEQzAwKSkudG9TdHJpbmcoMTYpKTtcbiAgICAgICAgcCA9IDA7XG4gICAgICB9IGVsc2UgaWYgKDB4RDgwMCA8PSBjICYmIGMgPD0gMHhEQkZGKSB7XG4gICAgICAgIHAgPSBjO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgci5wdXNoKGMudG9TdHJpbmcoMTYpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHIuam9pbihzZXAgfHwgJy0nKTtcbiAgfVxuXG59KCkpO1xuaWYgKCFsb2NhdGlvbi5wcm90b2NvbCkge1xuICB0d2Vtb2ppLmJhc2UgPSB0d2Vtb2ppLmJhc2UucmVwbGFjZSgvXmh0dHA6LywgXCJcIik7XG59XG5tb2R1bGUuZXhwb3J0cyA9IHR3ZW1vamk7IiwiaW1wb3J0IHR3ZW1vamkgZnJvbSAndHdlbW9qaSc7XHJcbmltcG9ydCBJY29uRm9sZGVyUGx1Z2luLCB7IEZvbGRlckljb25PYmplY3QgfSBmcm9tICcuL21haW4nO1xyXG5pbXBvcnQgdHlwZSB7IEV4cGxvcmVyVmlldyB9IGZyb20gJy4vQHR5cGVzL29ic2lkaWFuJztcclxuaW1wb3J0IHsgZ2V0QWxsTG9hZGVkSWNvbk5hbWVzLCBnZXRTdmdGcm9tTG9hZGVkSWNvbiwgSWNvbiB9IGZyb20gJy4vaWNvblBhY2tNYW5hZ2VyJztcclxuXHJcbi8qKlxyXG4gKiBUaGlzIGZ1bmN0aW9uIHJldHVybnMgYWxsIGVuYWJsZWQgaWNvbnMuXHJcbiAqXHJcbiAqIEZvciBleGFtcGxlOiBpZiBgUmVtaXhpY29ucyBGaWxsYCBhbmQgYEZvbnRhd2Vzb21lIEZpbGxgIGlzIGFjdGl2YXRlZCwgaXQgd2lsbCByZXR1cm4gYWxsIHRoZXNlIGljb25zLlxyXG4gKlxyXG4gKiBAcHVibGljXHJcbiAqIEBwYXJhbSB7SWNvbkZvbGRlclBsdWdpbn0gcGx1Z2luIC0gVGhlIG1haW4gcGx1Z2luIGZpbGUuXHJcbiAqIEByZXR1cm5zIHtzdHJpbmdbXX0gVGhlIGVuYWJsZWQgaWNvbnMuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgZ2V0RW5hYmxlZEljb25zID0gKHBsdWdpbjogSWNvbkZvbGRlclBsdWdpbik6IEljb25bXSA9PiB7XHJcbiAgY29uc3Qgc2V0dGluZ3MgPSBwbHVnaW4uZ2V0U2V0dGluZ3MoKTtcclxuICAvKmNvbnN0IGljb25zID0gdHJhbnNmb3JtZWRJY29ucy5yZW1peEljb25zLmZpbHRlcigoa2V5KSA9PiB7XHJcbiAgICByZXR1cm4gbWFwUmVtaXhpY29ucyhrZXksIHNldHRpbmdzKTtcclxuICB9KTtcclxuXHJcbiAgaWYgKHNldHRpbmdzLmVuYWJsZUZvbnRhd2Vzb21lRmlsbCkge1xyXG4gICAgaWNvbnMucHVzaCguLi50cmFuc2Zvcm1lZEljb25zLmZhRmlsbCk7XHJcbiAgfVxyXG4gIGlmIChzZXR0aW5ncy5lbmFibGVGb250YXdlc29tZUxpbmUpIHtcclxuICAgIGljb25zLnB1c2goLi4udHJhbnNmb3JtZWRJY29ucy5mYUxpbmUpO1xyXG4gIH1cclxuICBpZiAoc2V0dGluZ3MuZW5hYmxlRm9udGF3ZXNvbWVCcmFuZHMpIHtcclxuICAgIGljb25zLnB1c2goLi4udHJhbnNmb3JtZWRJY29ucy5mYUJyYW5kcyk7XHJcbiAgfVxyXG5cclxuICBpZiAoc2V0dGluZ3MuZW5hYmxlRGV2aWNvbnMpIHtcclxuICAgIGljb25zLnB1c2goLi4udHJhbnNmb3JtZWRJY29ucy5kZXZpY29uSWNvbnMpO1xyXG4gIH0qL1xyXG5cclxuICByZXR1cm4gZ2V0QWxsTG9hZGVkSWNvbk5hbWVzKCk7XHJcbn07XHJcblxyXG4vKipcclxuICogVGhpcyBmdW5jdGlvbiB0cmFuc2Zvcm1zIGFuIGljb24gdGhhdCBpbmNsdWRlcyBhIHByZWZpeCBhbmQgcmV0dXJucyB0aGUgY29ycmVjdCBzdmcgc3RyaW5nLlxyXG4gKlxyXG4gKiBGb3IgZXhhbXBsZTogVGhpcyBpbnB1dDogYFJpQUJgIHdpbGwgcmV0dXJuIG9ubHkgYEFCYCBhcyBhIHN2Zy5cclxuICpcclxuICogQHB1YmxpY1xyXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBpY29uIG5hbWUuXHJcbiAqIEByZXR1cm5zIHtzdHJpbmcgfCBudWxsfSBUaGUgdHJhbnNmb3JtZWQgc3ZnIG9yIG51bGwgaWYgaXQgY2Fubm90IGZpbmQgYW55IGljb25wYWNrLlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IGdldEljb24gPSAobmFtZTogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCA9PiB7XHJcbiAgcmV0dXJuIGdldFN2Z0Zyb21Mb2FkZWRJY29uKG5hbWUpO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRoaXMgZnVuY3Rpb24gcmV0dXJucyB0aGUgc3ZnIHN0cmluZyB3aXRoIHRoZSB1c2VyIGRlZmluZWQgY3NzIHNldHRpbmdzLlxyXG4gKiBJdCBoYW5kbGVzIGZyb20gdGhlIHNldHRpbmdzIHRoZSBgcGFkZGluZ2AsIGBjb2xvcmAsIGFuZCBgc2l6ZWAuXHJcbiAqXHJcbiAqIEluIGFkZGl0aW9uLCB0aGlzIGZ1bmN0aW9uIG1hbmlwdWxhdGVzIHRoZSBwYXNzZWQgZWxlbWVudCB3aXRoIHRoZSB1c2VyIGRlZmluZWQgc2V0dGluZyBgcGFkZGluZ2AuXHJcbiAqXHJcbiAqIEBwdWJsaWNcclxuICogQHBhcmFtIHtJY29uRm9sZGVyUGx1Z2lufSBwbHVnaW4gLSBUaGUgbWFpbiBwbHVnaW4uXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBpY29uIC0gVGhlIHRvIGJlIHN0eWxlZCBpY29uLlxyXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbCAtIFRoZSBlbGVtZW50IHRoYXQgd2lsbCBpbmNsdWRlIHRoZSBwYWRkaW5nIGZyb20gdGhlIHVzZXIgc2V0dGluZ3MuXHJcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBzdmcgd2l0aCB0aGUgY3VzdG9taXplZCBjc3Mgc2V0dGluZ3MuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgY3VzdG9taXplSWNvblN0eWxlID0gKHBsdWdpbjogSWNvbkZvbGRlclBsdWdpbiwgaWNvbjogc3RyaW5nLCBlbDogSFRNTEVsZW1lbnQpOiBzdHJpbmcgPT4ge1xyXG4gIC8vIEFsbG93IGN1c3RvbSBmb250IHNpemVcclxuICBjb25zdCBzaXplUmUgPSBuZXcgUmVnRXhwKC93aWR0aD1cIlxcZCtcIiBoZWlnaHQ9XCJcXGQrXCIvZyk7XHJcbiAgaWYgKGljb24ubWF0Y2goc2l6ZVJlKSkge1xyXG4gICAgaWNvbiA9IGljb24ucmVwbGFjZShzaXplUmUsIGB3aWR0aD1cIiR7cGx1Z2luLmdldFNldHRpbmdzKCkuZm9udFNpemV9XCIgaGVpZ2h0PVwiJHtwbHVnaW4uZ2V0U2V0dGluZ3MoKS5mb250U2l6ZX1cImApO1xyXG4gIH0gZWxzZSB7XHJcbiAgICAvLyBJZiBtYXRjaCBpcyBudWxsLCBpdCBzaG91bGQgYmUgYW4gaW1hZ2UuXHJcbiAgICBjb25zdCBzaXplUmUgPSBuZXcgUmVnRXhwKC93aWR0aD1cIlxcZCtweFwiIGhlaWdodD1cIlxcZCtweFwiL2cpO1xyXG4gICAgaWNvbiA9IGljb24ucmVwbGFjZShcclxuICAgICAgc2l6ZVJlLFxyXG4gICAgICBgd2lkdGg9XCIke3BsdWdpbi5nZXRTZXR0aW5ncygpLmZvbnRTaXplfXB4XCIgaGVpZ2h0PVwiJHtwbHVnaW4uZ2V0U2V0dGluZ3MoKS5mb250U2l6ZX1weFwiYCxcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICAvLyBBbGxvdyBjdXN0b20gaWNvbiBjb2xvclxyXG4gIGNvbnN0IGNvbG9yUmUgPSBuZXcgUmVnRXhwKC9maWxsPVwiKFxcd3wjKStcIi9nKTtcclxuICBjb25zdCBjb2xvck1hdGNoID0gaWNvbi5tYXRjaChjb2xvclJlKTtcclxuICBpZiAoY29sb3JNYXRjaCkge1xyXG4gICAgY29sb3JNYXRjaC5mb3JFYWNoKChjb2xvcikgPT4ge1xyXG4gICAgICBpZiAoY29sb3IuY29udGFpbnMoJ2N1cnJlbnRDb2xvcicpKSB7XHJcbiAgICAgICAgaWNvbiA9IGljb24ucmVwbGFjZShjb2xvciwgYGZpbGw9XCIke3BsdWdpbi5nZXRTZXR0aW5ncygpLmljb25Db2xvciA/PyAnY3VycmVudENvbG9yJ31cImApO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vIENoYW5nZSBwYWRkaW5nIG9mIGljb25cclxuICBpZiAocGx1Z2luLmdldFNldHRpbmdzKCkuZXh0cmFQYWRkaW5nKSB7XHJcbiAgICBlbC5zdHlsZS5wYWRkaW5nID0gYCR7cGx1Z2luLmdldFNldHRpbmdzKCkuZXh0cmFQYWRkaW5nLnRvcCA/PyAyfXB4ICR7XHJcbiAgICAgIHBsdWdpbi5nZXRTZXR0aW5ncygpLmV4dHJhUGFkZGluZy5yaWdodCA/PyAyXHJcbiAgICB9cHggJHtwbHVnaW4uZ2V0U2V0dGluZ3MoKS5leHRyYVBhZGRpbmcuYm90dG9tID8/IDJ9cHggJHtwbHVnaW4uZ2V0U2V0dGluZ3MoKS5leHRyYVBhZGRpbmcubGVmdCA/PyAyfXB4YDtcclxuICB9XHJcblxyXG4gIHJldHVybiBpY29uO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRoaXMgZnVuY3Rpb24gYWRkcyB0aGUgaWNvbnMgdG8gdGhlIERPTS5cclxuICogRm9yIHRoYXQsIGl0IHdpbGwgY3JlYXRlIGEgYGRpdmAgZWxlbWVudCB3aXRoIHRoZSBjbGFzcyBgb2JzaWRpYW4taWNvbi1mb2xkZXItaWNvbmAgdGhhdCB3aWxsIGJlIGN1c3RvbWl6ZWQgYmFzZWQgb24gdGhlIHVzZXIgc2V0dGluZ3MuXHJcbiAqXHJcbiAqIEBwdWJsaWNcclxuICogQHBhcmFtIHtJY29uRm9sZGVyUGx1Z2lufSBwbHVnaW4gLSBUaGUgbWFpbiBwbHVnaW4uXHJcbiAqIEBwYXJhbSB7W3N0cmluZywgc3RyaW5nIHwgRm9sZGVySWNvbk9iamVjdF1bXX0gZGF0YSAtIFRoZSBkYXRhIHRoYXQgaW5jbHVkZXMgdGhlIGljb25zLlxyXG4gKiBAcGFyYW0ge1dlYWtNYXA8RXhwbG9yZXJMZWFmLCBib29sZWFuPn0gcmVnaXN0ZXJlZEZpbGVFeHBsb3JlcnMgLSBUaGUgYWxyZWFkeSByZWdpc3RlcmVkIGZpbGUgZXhwbG9yZXJzLlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IGFkZEljb25zVG9ET00gPSAoXHJcbiAgcGx1Z2luOiBJY29uRm9sZGVyUGx1Z2luLFxyXG4gIGRhdGE6IFtzdHJpbmcsIHN0cmluZyB8IEZvbGRlckljb25PYmplY3RdW10sXHJcbiAgcmVnaXN0ZXJlZEZpbGVFeHBsb3JlcnM6IFdlYWtTZXQ8RXhwbG9yZXJWaWV3PixcclxuICBjYWxsYmFjaz86ICgpID0+IHZvaWQsXHJcbik6IHZvaWQgPT4ge1xyXG4gIGNvbnN0IGZpbGVFeHBsb3JlcnMgPSBwbHVnaW4uYXBwLndvcmtzcGFjZS5nZXRMZWF2ZXNPZlR5cGUoJ2ZpbGUtZXhwbG9yZXInKTtcclxuICBmaWxlRXhwbG9yZXJzLmZvckVhY2goKGZpbGVFeHBsb3JlcikgPT4ge1xyXG4gICAgaWYgKHJlZ2lzdGVyZWRGaWxlRXhwbG9yZXJzLmhhcyhmaWxlRXhwbG9yZXIudmlldykpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHJlZ2lzdGVyZWRGaWxlRXhwbG9yZXJzLmFkZChmaWxlRXhwbG9yZXIudmlldyk7XHJcblxyXG4gICAgLy8gY3JlYXRlIGEgbWFwIHdpdGggcmVnaXN0ZXJlZCBmaWxlIHBhdGhzIHRvIGhhdmUgY29uc3RhbnQgbG9vayB1cCB0aW1lXHJcbiAgICBjb25zdCByZWdpc3RlcmVkRmlsZVBhdGhzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiA9IHt9O1xyXG4gICAgZGF0YS5mb3JFYWNoKChbcGF0aF0pID0+IHtcclxuICAgICAgcmVnaXN0ZXJlZEZpbGVQYXRoc1twYXRoXSA9IHRydWU7XHJcbiAgICB9KTtcclxuXHJcbiAgICBkYXRhLmZvckVhY2goKFtkYXRhUGF0aCwgdmFsdWVdKSA9PiB7XHJcbiAgICAgIGNvbnN0IGZpbGVJdGVtID0gZmlsZUV4cGxvcmVyLnZpZXcuZmlsZUl0ZW1zW2RhdGFQYXRoXTtcclxuICAgICAgaWYgKGZpbGVJdGVtKSB7XHJcbiAgICAgICAgY29uc3QgdGl0bGVFbCA9IGZpbGVJdGVtLnRpdGxlRWw7XHJcbiAgICAgICAgY29uc3QgdGl0bGVJbm5lckVsID0gZmlsZUl0ZW0udGl0bGVJbm5lckVsO1xyXG5cclxuICAgICAgICAvLyBuZWVkcyB0byBjaGVjayBiZWNhdXNlIG9mIHRoZSByZWZyZXNoaW5nIHRoZSBwbHVnaW4gd2lsbCBkdXBsaWNhdGUgYWxsIHRoZSBpY29uc1xyXG4gICAgICAgIGlmICh0aXRsZUVsLmNoaWxkcmVuLmxlbmd0aCA9PT0gMiB8fCB0aXRsZUVsLmNoaWxkcmVuLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgY29uc3QgaWNvbk5hbWUgPSB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnID8gdmFsdWUgOiB2YWx1ZS5pY29uTmFtZTtcclxuICAgICAgICAgIGlmIChpY29uTmFtZSkge1xyXG4gICAgICAgICAgICBjb25zdCBleGlzdGluZ0ljb24gPSB0aXRsZUVsLnF1ZXJ5U2VsZWN0b3IoJy5vYnNpZGlhbi1pY29uLWZvbGRlci1pY29uJyk7XHJcbiAgICAgICAgICAgIGlmIChleGlzdGluZ0ljb24pIHtcclxuICAgICAgICAgICAgICBleGlzdGluZ0ljb24ucmVtb3ZlKCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGljb25Ob2RlID0gdGl0bGVFbC5jcmVhdGVEaXYoKTtcclxuICAgICAgICAgICAgaWNvbk5vZGUuY2xhc3NMaXN0LmFkZCgnb2JzaWRpYW4taWNvbi1mb2xkZXItaWNvbicpO1xyXG5cclxuICAgICAgICAgICAgaW5zZXJ0SWNvblRvTm9kZShwbHVnaW4sIGljb25OYW1lLCBpY29uTm9kZSk7XHJcblxyXG4gICAgICAgICAgICB0aXRsZUVsLmluc2VydEJlZm9yZShpY29uTm9kZSwgdGl0bGVJbm5lckVsKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZS5pbmhlcml0YW5jZUljb24pIHtcclxuICAgICAgICAgICAgY29uc3QgZmlsZXMgPSBwbHVnaW4uYXBwLnZhdWx0LmdldEZpbGVzKCkuZmlsdGVyKChmKSA9PiBmLnBhdGguaW5jbHVkZXMoZGF0YVBhdGgpKTtcclxuICAgICAgICAgICAgY29uc3QgaW5oZXJpdGFuY2VJY29uTmFtZSA9IHZhbHVlLmluaGVyaXRhbmNlSWNvbjtcclxuICAgICAgICAgICAgZmlsZXMuZm9yRWFjaCgoZikgPT4ge1xyXG4gICAgICAgICAgICAgIGlmICghcmVnaXN0ZXJlZEZpbGVQYXRoc1tmLnBhdGhdKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBpbmhlcml0YW5jZUZpbGVJdGVtID0gZmlsZUV4cGxvcmVyLnZpZXcuZmlsZUl0ZW1zW2YucGF0aF07XHJcbiAgICAgICAgICAgICAgICBjb25zdCBpY29uTm9kZSA9IGluaGVyaXRhbmNlRmlsZUl0ZW0udGl0bGVFbC5jcmVhdGVEaXYoKTtcclxuICAgICAgICAgICAgICAgIGljb25Ob2RlLmNsYXNzTGlzdC5hZGQoJ29ic2lkaWFuLWljb24tZm9sZGVyLWljb24nKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpbnNlcnRJY29uVG9Ob2RlKHBsdWdpbiwgaW5oZXJpdGFuY2VJY29uTmFtZSwgaWNvbk5vZGUpO1xyXG5cclxuICAgICAgICAgICAgICAgIGluaGVyaXRhbmNlRmlsZUl0ZW0udGl0bGVFbC5pbnNlcnRCZWZvcmUoaWNvbk5vZGUsIGluaGVyaXRhbmNlRmlsZUl0ZW0udGl0bGVJbm5lckVsKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKGNhbGxiYWNrKSB7XHJcbiAgICAgIGNhbGxiYWNrKCk7XHJcbiAgICB9XHJcbiAgfSk7XHJcbn07XHJcblxyXG5leHBvcnQgY29uc3QgYWRkSW5oZXJpdGFuY2VJY29uVG9GaWxlID0gKFxyXG4gIHBsdWdpbjogSWNvbkZvbGRlclBsdWdpbixcclxuICByZWdpc3RlcmVkRmlsZUV4cGxvcmVyczogV2Vha1NldDxFeHBsb3JlclZpZXc+LFxyXG4gIGZpbGVQYXRoOiBzdHJpbmcsXHJcbiAgaWNvbk5hbWU6IHN0cmluZyxcclxuKTogdm9pZCA9PiB7XHJcbiAgY29uc3QgZmlsZUV4cGxvcmVycyA9IHBsdWdpbi5hcHAud29ya3NwYWNlLmdldExlYXZlc09mVHlwZSgnZmlsZS1leHBsb3JlcicpO1xyXG4gIGZpbGVFeHBsb3JlcnMuZm9yRWFjaCgoZmlsZUV4cGxvcmVyKSA9PiB7XHJcbiAgICBpZiAocmVnaXN0ZXJlZEZpbGVFeHBsb3JlcnMuaGFzKGZpbGVFeHBsb3Jlci52aWV3KSkge1xyXG4gICAgICBjb25zdCBmaWxlSXRlbSA9IGZpbGVFeHBsb3Jlci52aWV3LmZpbGVJdGVtc1tmaWxlUGF0aF07XHJcbiAgICAgIGlmIChmaWxlSXRlbSkge1xyXG4gICAgICAgIGNvbnN0IGljb25Ob2RlID0gZmlsZUl0ZW0udGl0bGVFbC5jcmVhdGVEaXYoKTtcclxuICAgICAgICBpY29uTm9kZS5jbGFzc0xpc3QuYWRkKCdvYnNpZGlhbi1pY29uLWZvbGRlci1pY29uJyk7XHJcblxyXG4gICAgICAgIGluc2VydEljb25Ub05vZGUocGx1Z2luLCBpY29uTmFtZSwgaWNvbk5vZGUpO1xyXG5cclxuICAgICAgICBmaWxlSXRlbS50aXRsZUVsLmluc2VydEJlZm9yZShpY29uTm9kZSwgZmlsZUl0ZW0udGl0bGVJbm5lckVsKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH0pO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRoaXMgZnVuY3Rpb24gcmVmcmVzaGVzIHRoZSBpY29uIHN0eWxlLlxyXG4gKiBGb3IgdGhhdCwgaXQgd2lsbCBtYW5pcHVsYXRlIHRoZSBgaW5uZXJIVE1MYCBvZiB0aGUgaWNvbiBhbmQgd2lsbCBjdXN0b21pemUgdGhlIHN0eWxlLlxyXG4gKlxyXG4gKiBAcHVibGljXHJcbiAqIEBwYXJhbSB7SWNvbkZvbGRlclBsdWdpbn0gcGx1Z2luIC0gVGhlIG1haW4gcGx1Z2luLlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IHJlZnJlc2hJY29uU3R5bGUgPSAocGx1Z2luOiBJY29uRm9sZGVyUGx1Z2luKTogdm9pZCA9PiB7XHJcbiAgY29uc3QgZGF0YSA9IE9iamVjdC5lbnRyaWVzKHBsdWdpbi5nZXREYXRhKCkpIGFzIFtzdHJpbmcsIHN0cmluZ107XHJcbiAgY29uc3QgZmlsZUV4cGxvcmVycyA9IHBsdWdpbi5hcHAud29ya3NwYWNlLmdldExlYXZlc09mVHlwZSgnZmlsZS1leHBsb3JlcicpO1xyXG4gIGZpbGVFeHBsb3JlcnMuZm9yRWFjaCgoZmlsZUV4cGxvcmVyKSA9PiB7XHJcbiAgICBkYXRhLmZvckVhY2goKFtrZXldKSA9PiB7XHJcbiAgICAgIGNvbnN0IGZpbGVJdGVtID0gZmlsZUV4cGxvcmVyLnZpZXcuZmlsZUl0ZW1zW2tleV07XHJcbiAgICAgIGlmIChmaWxlSXRlbSkge1xyXG4gICAgICAgIGNvbnN0IHRpdGxlRWwgPSBmaWxlSXRlbS50aXRsZUVsO1xyXG4gICAgICAgIGNvbnN0IGljb25Ob2RlID0gdGl0bGVFbC5xdWVyeVNlbGVjdG9yKCcub2JzaWRpYW4taWNvbi1mb2xkZXItaWNvbicpIGFzIEhUTUxFbGVtZW50O1xyXG4gICAgICAgIGljb25Ob2RlLmlubmVySFRNTCA9IGN1c3RvbWl6ZUljb25TdHlsZShwbHVnaW4sIGljb25Ob2RlLmlubmVySFRNTCwgaWNvbk5vZGUpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9KTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBUaGlzIGZ1bmN0aW9uIHJlbW92ZXMgdGhlIGljb24gbm9kZSBmcm9tIHRoZSBET00gYmFzZWQgb24gdGhlIHBhc3NlZCBpbiBwYXRoLlxyXG4gKlxyXG4gKiBAcHVibGljXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gVGhlIHBhdGggdG9lIHRoZSB0byBiZSByZW1vdmVkIERPTSBlbGVtZW50LlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IHJlbW92ZUZyb21ET00gPSAocGF0aDogc3RyaW5nKTogdm9pZCA9PiB7XHJcbiAgY29uc3Qgbm9kZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYFtkYXRhLXBhdGg9XCIke3BhdGh9XCJdYCk7XHJcbiAgaWYgKCFub2RlKSB7XHJcbiAgICBjb25zb2xlLmVycm9yKCdlbGVtZW50IHdpdGggZGF0YSBwYXRoIG5vdCBmb3VuZCcsIHBhdGgpO1xyXG4gICAgcmV0dXJuO1xyXG4gIH1cclxuXHJcbiAgY29uc3QgaWNvbk5vZGUgPSBub2RlLnF1ZXJ5U2VsZWN0b3IoJy5vYnNpZGlhbi1pY29uLWZvbGRlci1pY29uJyk7XHJcbiAgaWYgKCFpY29uTm9kZSkge1xyXG4gICAgcmV0dXJuO1xyXG4gIH1cclxuXHJcbiAgaWNvbk5vZGUucmVtb3ZlKCk7XHJcbn07XHJcblxyXG4vKipcclxuICogVGhpcyBmdW5jdGlvbiBhZGRzIGFuIGljb24gdG8gdGhlIERPTSBiYXNlZCBvbiBhIHNwZWNpZmljIHBhdGguXHJcbiAqIEluIGFkZGl0aW9uLCBiZWZvcmUgYWRkZWQgdG8gdGhlIERPTSwgaXQgd2lsbCBjdXN0b21pemUgdGhlIGljb24gc3R5bGUuXHJcbiAqXHJcbiAqIEBwdWJsaWNcclxuICogQHBhcmFtIHtJY29uRm9sZGVyUGx1Z2lufSBwbHVnaW4gLSBUaGUgbWFpbiBwbHVnaW4uXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gVGhlIHBhdGggaW4gdGhlIERPTSB3aGVyZSB0aGUgaWNvbiB3aWxsIGJlIGFkZGVkLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gaWNvbiAtIFRoZSBpY29uIHRoYXQgd2lsbCBiZSBhZGRlZCB0byB0aGUgRE9NIC0gY2FuIGJlIGFuIGljb24gaWQgb3IgY29kZXBvaW50IGZvciB0d2Vtb2ppLlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IGFkZFRvRE9NID0gKHBsdWdpbjogSWNvbkZvbGRlclBsdWdpbiwgcGF0aDogc3RyaW5nLCBpY29uOiBzdHJpbmcpOiB2b2lkID0+IHtcclxuICBpZiAocGx1Z2luLmdldERhdGEoKVtwYXRoXSkge1xyXG4gICAgcmVtb3ZlRnJvbURPTShwYXRoKTtcclxuICB9XHJcblxyXG4gIGNvbnN0IG5vZGUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGBbZGF0YS1wYXRoPVwiJHtwYXRofVwiXWApO1xyXG4gIGlmICghbm9kZSkge1xyXG4gICAgY29uc29sZS5lcnJvcignZWxlbWVudCB3aXRoIGRhdGEgcGF0aCBub3QgZm91bmQnLCBwYXRoKTtcclxuICAgIHJldHVybjtcclxuICB9XHJcblxyXG4gIGxldCB0aXRsZU5vZGUgPSBub2RlLnF1ZXJ5U2VsZWN0b3IoJy5uYXYtZm9sZGVyLXRpdGxlLWNvbnRlbnQnKTtcclxuICBpZiAoIXRpdGxlTm9kZSkge1xyXG4gICAgdGl0bGVOb2RlID0gbm9kZS5xdWVyeVNlbGVjdG9yKCcubmF2LWZpbGUtdGl0bGUtY29udGVudCcpO1xyXG5cclxuICAgIGlmICghdGl0bGVOb2RlKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ2VsZW1lbnQgd2l0aCB0aXRsZSBub3QgZm91bmQnKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gY2hlY2sgaWYgdGhlcmUgaXMgYSBwb3NzaWJsZSBpbmhlcml0YW5jZSBpY29uIGluIHRoZSBET01cclxuICBjb25zdCBwb3NzaWJsZUluaGVyaXRhbmNlSWNvbiA9IG5vZGUucXVlcnlTZWxlY3RvcignLm9ic2lkaWFuLWljb24tZm9sZGVyLWljb24nKTtcclxuICBpZiAocG9zc2libGVJbmhlcml0YW5jZUljb24pIHtcclxuICAgIHBvc3NpYmxlSW5oZXJpdGFuY2VJY29uLnJlbW92ZSgpO1xyXG4gIH1cclxuXHJcbiAgY29uc3QgaWNvbk5vZGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICBpY29uTm9kZS5jbGFzc0xpc3QuYWRkKCdvYnNpZGlhbi1pY29uLWZvbGRlci1pY29uJyk7XHJcblxyXG4gIGluc2VydEljb25Ub05vZGUocGx1Z2luLCBpY29uLCBpY29uTm9kZSk7XHJcblxyXG4gIG5vZGUuaW5zZXJ0QmVmb3JlKGljb25Ob2RlLCB0aXRsZU5vZGUpO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRoaXMgZnVuY3Rpb24gaW5zZXJ0cyBhIHNwZWNpZmljIGljb24gaW50byB0aGUgc3BlY2lmaWVkIG5vZGUuXHJcbiAqXHJcbiAqIEBwYXJhbSB7SWNvbkZvbGRlclBsdWdpbn0gcGx1Z2luIC0gVGhlIG1haW4gcGx1Z2luLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gaWNvbiAtIFRoZSBpY29uIHN0cmluZyAoY2FuIGJlIGFuIGljb24gaWQgb3IgYSB1bmljb2RlIGZvciB0d2Vtb2ppKS5cclxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gbm9kZSAtIFRoZSBlbGVtZW50IHdoZXJlIHRoZSBpY29uIHdpbGwgYmUgaW5zZXJ0ZWQuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgaW5zZXJ0SWNvblRvTm9kZSA9IChwbHVnaW46IEljb25Gb2xkZXJQbHVnaW4sIGljb246IHN0cmluZywgbm9kZTogSFRNTEVsZW1lbnQpOiB2b2lkID0+IHtcclxuICBjb25zdCBwb3NzaWJsZUljb24gPSBnZXRJY29uKGljb24pO1xyXG5cclxuICBpZiAocG9zc2libGVJY29uKSB7XHJcbiAgICBub2RlLmlubmVySFRNTCA9IGN1c3RvbWl6ZUljb25TdHlsZShwbHVnaW4sIHBvc3NpYmxlSWNvbiwgbm9kZSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIGNvbnN0IGVtb2ppID0gdHdlbW9qaS5wYXJzZShpY29uLCB7XHJcbiAgICAgIGZvbGRlcjogJ3N2ZycsXHJcbiAgICAgIGV4dDogJy5zdmcnLFxyXG4gICAgICBhdHRyaWJ1dGVzOiAoKSA9PiAoe1xyXG4gICAgICAgIHdpZHRoOiAnMTZweCcsXHJcbiAgICAgICAgaGVpZ2h0OiAnMTZweCcsXHJcbiAgICAgIH0pLFxyXG4gICAgfSk7XHJcbiAgICBub2RlLmlubmVySFRNTCA9IGN1c3RvbWl6ZUljb25TdHlsZShwbHVnaW4sIGVtb2ppLCBub2RlKTtcclxuICB9XHJcbn07XHJcblxyXG4vKipcclxuICogVGhpcyBmdW5jdGlvbiB3aWxsIGFkZCBpbmhlcml0YW5jZSBmdW5jdGlvbmFsaXR5IHRvIGEgc3BlY2lmaWMgZm9sZGVyLlxyXG4gKiBJdCB3aWxsIGFkZCB0aGUgaW5oZXJpdGFuY2UgaWNvbiB0byBhbGwgY2hpbGQgZmlsZXMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7SWNvbkZvbGRlclBsdWdpbn0gcGx1Z2luIC0gVGhlIG1haW4gcGx1Z2luLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZm9sZGVyUGF0aCAtIFRoZSBwYXRoIGluIHRoZSBET00gd2hlcmUgdGhlIGljb24gd2lsbCBiZSBhZGRlZC5cclxuICovXHJcbmV4cG9ydCBjb25zdCBhZGRJbmhlcml0YW5jZUZvckZvbGRlciA9IChwbHVnaW46IEljb25Gb2xkZXJQbHVnaW4sIGZvbGRlclBhdGg6IHN0cmluZyk6IHZvaWQgPT4ge1xyXG4gIGNvbnN0IGZvbGRlciA9IHBsdWdpbi5nZXREYXRhKClbZm9sZGVyUGF0aF07XHJcbiAgaWYgKCFmb2xkZXIgfHwgdHlwZW9mIGZvbGRlciAhPT0gJ29iamVjdCcpIHtcclxuICAgIHJldHVybjtcclxuICB9XHJcblxyXG4gIC8vIGFkZCBpY29ucyBmb3IgYWxsIHRoZSBjaGlsZCBmaWxlc1xyXG4gIGNvbnN0IGZpbGVzID0gcGx1Z2luLmFwcC52YXVsdC5nZXRGaWxlcygpLmZpbHRlcigoZikgPT4gZi5wYXRoLmluY2x1ZGVzKGZvbGRlclBhdGgpKTtcclxuICBmaWxlcy5mb3JFYWNoKChmKSA9PiB7XHJcbiAgICBpZiAocGx1Z2luLmdldERhdGEoKVtmLnBhdGhdKSB7XHJcbiAgICAgIHJlbW92ZUZyb21ET00oZi5wYXRoKTtcclxuICAgICAgcGx1Z2luLnJlbW92ZUZvbGRlckljb24oZi5wYXRoKTtcclxuICAgIH1cclxuXHJcbiAgICBhZGRUb0RPTShwbHVnaW4sIGYucGF0aCwgKGZvbGRlciBhcyBhbnkpLmluaGVyaXRhbmNlSWNvbik7XHJcbiAgfSk7XHJcbn07XHJcblxyXG4vKipcclxuICogVGhpcyBmdW5jdGlvbiByZW1vdmVzIGluaGVyaXRhbmNlIGZyb20gYSBmb2xkZXIuXHJcbiAqIEl0IHdpbGwgZGVsZXRlIGFsbCB0aGUgaWNvbnMgaW4gdGhlIHN1YiBmaWxlcyBvZiB0aGlzIGZvbGRlci5cclxuICpcclxuICogQHBhcmFtIHtJY29uRm9sZGVyUGx1Z2lufSBwbHVnaW4gLSBUaGUgbWFpbiBwbHVnaW4uXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBmb2xkZXJQYXRoIC0gVGhlIHBhdGggaW4gdGhlIERPTSB3aGVyZSB0aGUgaWNvbiB3aWxsIGJlIGFkZGVkLlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IHJlbW92ZUluaGVyaXRhbmNlRm9yRm9sZGVyID0gKHBsdWdpbjogSWNvbkZvbGRlclBsdWdpbiwgZm9sZGVyUGF0aDogc3RyaW5nKTogdm9pZCA9PiB7XHJcbiAgY29uc3QgZm9sZGVyID0gcGx1Z2luLmdldERhdGEoKVtmb2xkZXJQYXRoXTtcclxuICBpZiAoIWZvbGRlciB8fCB0eXBlb2YgZm9sZGVyICE9PSAnb2JqZWN0Jykge1xyXG4gICAgcmV0dXJuO1xyXG4gIH1cclxuXHJcbiAgLy8gcmVtb3ZlIGljb25zIGZyb20gYWxsIHRoZSBjaGlsZCBmaWxlc1xyXG4gIGNvbnN0IGZpbGVzID0gcGx1Z2luLmFwcC52YXVsdC5nZXRGaWxlcygpLmZpbHRlcigoZikgPT4gZi5wYXRoLmluY2x1ZGVzKGZvbGRlclBhdGgpKTtcclxuICBmaWxlcy5mb3JFYWNoKChmKSA9PiB7XHJcbiAgICAvLyB3aGVuIHRoZSBmaWxlIHBhdGggaXMgbm90IHJlZ2lzdGVyZWQgaW4gdGhlIGRhdGEgaXQgc2hvdWxkIHJlbW92ZSB0aGUgaWNvblxyXG4gICAgaWYgKCFwbHVnaW4uZ2V0RGF0YSgpW2YucGF0aF0pIHtcclxuICAgICAgcmVtb3ZlRnJvbURPTShmLnBhdGgpO1xyXG4gICAgfVxyXG4gIH0pO1xyXG59O1xyXG5cclxuZXhwb3J0IGNvbnN0IGlzRW1vamkgPSAoc3RyOiBzdHJpbmcpOiBib29sZWFuID0+IHtcclxuICBjb25zdCByYW5nZXMgPSBbXHJcbiAgICAnKD86W1xcdTI3MDAtXFx1MjdiZl18KD86XFx1ZDgzY1tcXHVkZGU2LVxcdWRkZmZdKXsyfXxbXFx1ZDgwMC1cXHVkYmZmXVtcXHVkYzAwLVxcdWRmZmZdfFtcXHUwMDIzLVxcdTAwMzldXFx1ZmUwZj9cXHUyMGUzfFxcdTMyOTl8XFx1MzI5N3xcXHUzMDNkfFxcdTMwMzB8XFx1MjRjMnxcXHVkODNjW1xcdWRkNzAtXFx1ZGQ3MV18XFx1ZDgzY1tcXHVkZDdlLVxcdWRkN2ZdfFxcdWQ4M2NcXHVkZDhlfFxcdWQ4M2NbXFx1ZGQ5MS1cXHVkZDlhXXxcXHVkODNjW1xcdWRkZTYtXFx1ZGRmZl18W1xcdWQ4M2NbXFx1ZGUwMS1cXHVkZTAyXXxcXHVkODNjXFx1ZGUxYXxcXHVkODNjXFx1ZGUyZnxbXFx1ZDgzY1tcXHVkZTMyLVxcdWRlM2FdfFtcXHVkODNjW1xcdWRlNTAtXFx1ZGU1MV18XFx1MjAzY3xcXHUyMDQ5fFtcXHUyNWFhLVxcdTI1YWJdfFxcdTI1YjZ8XFx1MjVjMHxbXFx1MjVmYi1cXHUyNWZlXXxcXHUwMGE5fFxcdTAwYWV8XFx1MjEyMnxcXHUyMTM5fFxcdWQ4M2NcXHVkYzA0fFtcXHUyNjAwLVxcdTI2RkZdfFxcdTJiMDV8XFx1MmIwNnxcXHUyYjA3fFxcdTJiMWJ8XFx1MmIxY3xcXHUyYjUwfFxcdTJiNTV8XFx1MjMxYXxcXHUyMzFifFxcdTIzMjh8XFx1MjNjZnxbXFx1MjNlOS1cXHUyM2YzXXxbXFx1MjNmOC1cXHUyM2ZhXXxcXHVkODNjXFx1ZGNjZnxcXHUyOTM0fFxcdTI5MzV8W1xcdTIxOTAtXFx1MjFmZl0pJywgLy8gVSsxRjY4MCB0byBVKzFGNkZGXHJcbiAgXTtcclxuXHJcbiAgaWYgKHN0ci5tYXRjaChyYW5nZXMuam9pbignfCcpKSkge1xyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfSBlbHNlIHtcclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcbn07XHJcbiIsImltcG9ydCB7IEFwcCwgRHJvcGRvd25Db21wb25lbnQsIE5vdGljZSwgUGx1Z2luU2V0dGluZ1RhYiwgU2V0dGluZywgU2xpZGVyQ29tcG9uZW50LCBUZXh0Q29tcG9uZW50IH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5pbXBvcnQgeyBDb2xvclBpY2tlckNvbXBvbmVudCB9IGZyb20gJy4vY29sb3JQaWNrZXJDb21wb25lbnQnO1xyXG5pbXBvcnQge1xyXG4gIGFkZEljb25Ub0ljb25QYWNrLFxyXG4gIGNyZWF0ZUZpbGUsXHJcbiAgY3JlYXRlSWNvblBhY2tEaXJlY3RvcnksXHJcbiAgZGVsZXRlSWNvblBhY2ssXHJcbiAgZ2V0QWxsSWNvblBhY2tzLFxyXG59IGZyb20gJy4vaWNvblBhY2tNYW5hZ2VyJztcclxuaW1wb3J0IEljb25Gb2xkZXJQbHVnaW4gZnJvbSAnLi9tYWluJztcclxuaW1wb3J0IHsgREVGQVVMVF9TRVRUSU5HUywgRXh0cmFQYWRkaW5nU2V0dGluZ3MgfSBmcm9tICcuL3NldHRpbmdzJztcclxuaW1wb3J0IHsgcmVmcmVzaEljb25TdHlsZSB9IGZyb20gJy4vdXRpbCc7XHJcblxyXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJY29uRm9sZGVyU2V0dGluZ3NUYWIgZXh0ZW5kcyBQbHVnaW5TZXR0aW5nVGFiIHtcclxuICBwcml2YXRlIHBsdWdpbjogSWNvbkZvbGRlclBsdWdpbjtcclxuICBwcml2YXRlIHRleHRDb21wb25lbnQ6IFRleHRDb21wb25lbnQ7XHJcblxyXG4gIHByaXZhdGUgZHJhZ092ZXJFbGVtZW50OiBIVE1MRWxlbWVudDtcclxuICBwcml2YXRlIGNsb3NlVGltZXI6IGFueTtcclxuICBwcml2YXRlIGRyYWdUYXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudDtcclxuXHJcbiAgY29uc3RydWN0b3IoYXBwOiBBcHAsIHBsdWdpbjogSWNvbkZvbGRlclBsdWdpbikge1xyXG4gICAgc3VwZXIoYXBwLCBwbHVnaW4pO1xyXG5cclxuICAgIHRoaXMucGx1Z2luID0gcGx1Z2luO1xyXG4gICAgdGhpcy5kcmFnT3ZlckVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICAgIHRoaXMuZHJhZ092ZXJFbGVtZW50LmFkZENsYXNzKCdvYnNpZGlhbi1pY29uLWZvbGRlci1kcmFnb3Zlci1lbCcpO1xyXG4gICAgdGhpcy5kcmFnT3ZlckVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdoaWRkZW4nO1xyXG4gICAgdGhpcy5kcmFnT3ZlckVsZW1lbnQuaW5uZXJIVE1MID0gJzxwPkRyb3AgdG8gYWRkIGljb24uPC9wPic7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIG5vcm1hbGl6ZUljb25QYWNrTmFtZSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB2YWx1ZS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL1xccy9nLCAnLScpO1xyXG4gIH1cclxuXHJcbiAgZGlzcGxheSgpOiB2b2lkIHtcclxuICAgIGNvbnN0IHsgY29udGFpbmVyRWwgfSA9IHRoaXM7XHJcblxyXG4gICAgY29udGFpbmVyRWwuZW1wdHkoKTtcclxuICAgIGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdoMicsIHsgdGV4dDogJ0ljb24gRm9sZGVyIFNldHRpbmdzJyB9KTtcclxuXHJcbiAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcclxuICAgICAgLnNldE5hbWUoJ1JlY2VudGx5IHVzZWQgSWNvbnMgbGltaXQnKVxyXG4gICAgICAuc2V0RGVzYygnQ2hhbmdlIHRoZSBsaW1pdCBmb3IgdGhlIHJlY2VudGx5IHVzZWQgaWNvbnMgZGlzcGxheWVkIGluIHRoZSBpY29uIG1vZGFsLicpXHJcbiAgICAgIC5hZGRTbGlkZXIoKHNsaWRlcikgPT4ge1xyXG4gICAgICAgIHNsaWRlclxyXG4gICAgICAgICAgLnNldExpbWl0cygxLCAxNSwgMSlcclxuICAgICAgICAgIC5zZXREeW5hbWljVG9vbHRpcCgpXHJcbiAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uZ2V0U2V0dGluZ3MoKS5yZWNlbnRseVVzZWRJY29uc1NpemUgPz8gREVGQVVMVF9TRVRUSU5HUy5yZWNlbnRseVVzZWRJY29uc1NpemUpXHJcbiAgICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLnBsdWdpbi5nZXRTZXR0aW5ncygpLnJlY2VudGx5VXNlZEljb25zU2l6ZSA9IHZhbDtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uY2hlY2tSZWNlbnRseVVzZWRJY29ucygpO1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlSWNvbkZvbGRlckRhdGEoKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICBjb250YWluZXJFbC5jcmVhdGVFbCgnaDMnLCB7IHRleHQ6ICdJY29uIFBhY2tzJyB9KTtcclxuXHJcbiAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcclxuICAgICAgLnNldE5hbWUoJ0FkZCBjdXN0b20gaWNvbiBwYWNrJylcclxuICAgICAgLnNldERlc2MoJ0FkZCBhIGN1c3RvbSBpY29uIHBhY2snKVxyXG4gICAgICAuYWRkVGV4dCgodGV4dCkgPT4ge1xyXG4gICAgICAgIHRleHQuc2V0UGxhY2Vob2xkZXIoJ1lvdXIgaWNvbiBwYWNrIG5hbWUnKTtcclxuICAgICAgICB0aGlzLnRleHRDb21wb25lbnQgPSB0ZXh0O1xyXG4gICAgICB9KVxyXG4gICAgICAuYWRkQnV0dG9uKChidG4pID0+IHtcclxuICAgICAgICBidG4uc2V0QnV0dG9uVGV4dCgnQWRkIGljb24gcGFjaycpO1xyXG4gICAgICAgIGJ0bi5idXR0b25FbC5zdHlsZS5tYXJnaW5MZWZ0ID0gJzEycHgnO1xyXG4gICAgICAgIGJ0bi5vbkNsaWNrKGFzeW5jICgpID0+IHtcclxuICAgICAgICAgIGNvbnN0IG5hbWUgPSB0aGlzLnRleHRDb21wb25lbnQuZ2V0VmFsdWUoKTtcclxuICAgICAgICAgIGlmIChuYW1lLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgYXdhaXQgY3JlYXRlSWNvblBhY2tEaXJlY3RvcnkodGhpcy5wbHVnaW4sIHRoaXMubm9ybWFsaXplSWNvblBhY2tOYW1lKHRoaXMudGV4dENvbXBvbmVudC5nZXRWYWx1ZSgpKSk7XHJcbiAgICAgICAgICB0aGlzLnRleHRDb21wb25lbnQuc2V0VmFsdWUoJycpO1xyXG4gICAgICAgICAgdGhpcy5kaXNwbGF5KCk7XHJcbiAgICAgICAgICBuZXcgTm90aWNlKCdJY29uIHBhY2sgc3VjY2Vzc2Z1bGx5IGNyZWF0ZWQuJyk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgIGdldEFsbEljb25QYWNrcygpLmZvckVhY2goKGljb25QYWNrKSA9PiB7XHJcbiAgICAgIGNvbnN0IGljb25QYWNrU2V0dGluZyA9IG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxyXG4gICAgICAgIC5zZXROYW1lKGljb25QYWNrLm5hbWUpXHJcbiAgICAgICAgLnNldERlc2MoYFRvdGFsIGljb25zOiAke2ljb25QYWNrLmljb25zLmxlbmd0aH1gKTtcclxuICAgICAgaWNvblBhY2tTZXR0aW5nLmFkZEJ1dHRvbigoYnRuKSA9PiB7XHJcbiAgICAgICAgYnRuLnNldEljb24oJ2NyZWF0ZS1uZXcnKTtcclxuICAgICAgICBidG4uc2V0VG9vbHRpcCgnQWRkIGFuIGljb24nKTtcclxuICAgICAgICBidG4ub25DbGljaygoKSA9PiB7XHJcbiAgICAgICAgICBjb25zdCBmaWxlU2VsZWN0b3IgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbnB1dCcpO1xyXG4gICAgICAgICAgZmlsZVNlbGVjdG9yLnNldEF0dHJpYnV0ZSgndHlwZScsICdmaWxlJyk7XHJcbiAgICAgICAgICBmaWxlU2VsZWN0b3Iuc2V0QXR0cmlidXRlKCdtdWx0aXBsZScsICdtdWx0aXBsZScpO1xyXG4gICAgICAgICAgZmlsZVNlbGVjdG9yLnNldEF0dHJpYnV0ZSgnYWNjZXB0JywgJy5zdmcnKTtcclxuICAgICAgICAgIGZpbGVTZWxlY3Rvci5jbGljaygpO1xyXG4gICAgICAgICAgZmlsZVNlbGVjdG9yLm9uY2hhbmdlID0gKGUpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0ID0gZS50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0YXJnZXQuZmlsZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICBjb25zdCBmaWxlID0gdGFyZ2V0LmZpbGVzW2ldIGFzIEZpbGU7XHJcbiAgICAgICAgICAgICAgdGhpcy5yZWFkRmlsZShmaWxlLCBhc3luYyAoY29udGVudCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgYXdhaXQgY3JlYXRlRmlsZSh0aGlzLnBsdWdpbiwgaWNvblBhY2submFtZSwgZmlsZS5uYW1lLCBjb250ZW50KTtcclxuICAgICAgICAgICAgICAgIGFkZEljb25Ub0ljb25QYWNrKGljb25QYWNrLm5hbWUsIGZpbGUubmFtZSwgY29udGVudCk7XHJcbiAgICAgICAgICAgICAgICBpY29uUGFja1NldHRpbmcuc2V0RGVzYyhgVG90YWwgaWNvbnM6ICR7aWNvblBhY2suaWNvbnMubGVuZ3RofSAoYWRkZWQ6ICR7ZmlsZS5uYW1lfSlgKTtcclxuICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBuZXcgTm90aWNlKCdJY29ucyBzdWNjZXNzZnVsbHkgYWRkZWQuJyk7XHJcbiAgICAgICAgICB9O1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9KTtcclxuICAgICAgaWNvblBhY2tTZXR0aW5nLmFkZEJ1dHRvbigoYnRuKSA9PiB7XHJcbiAgICAgICAgYnRuLnNldEljb24oJ3RyYXNoJyk7XHJcbiAgICAgICAgYnRuLnNldFRvb2x0aXAoJ1JlbW92ZSB0aGUgaWNvbiBwYWNrJyk7XHJcbiAgICAgICAgYnRuLm9uQ2xpY2soYXN5bmMgKCkgPT4ge1xyXG4gICAgICAgICAgYXdhaXQgZGVsZXRlSWNvblBhY2sodGhpcy5wbHVnaW4sIGljb25QYWNrLm5hbWUpO1xyXG4gICAgICAgICAgdGhpcy5kaXNwbGF5KCk7XHJcbiAgICAgICAgICBuZXcgTm90aWNlKCdJY29uIHBhY2sgc3VjY2Vzc2Z1bGx5IGRlbGV0ZWQuJyk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgWydkcmFnZW50ZXInLCAnZHJhZ292ZXInLCAnZHJhZ2xlYXZlJywgJ2Ryb3AnXS5mb3JFYWNoKChldmVudCkgPT4ge1xyXG4gICAgICAgIGljb25QYWNrU2V0dGluZy5zZXR0aW5nRWwuYWRkRXZlbnRMaXN0ZW5lcihldmVudCwgdGhpcy5wcmV2ZW50RGVmYXVsdHMsIGZhbHNlKTtcclxuICAgICAgfSk7XHJcbiAgICAgIFsnZHJhZ2VudGVyJywgJ2RyYWdvdmVyJ10uZm9yRWFjaCgoZXZlbnQpID0+IHtcclxuICAgICAgICBpY29uUGFja1NldHRpbmcuc2V0dGluZ0VsLmFkZEV2ZW50TGlzdGVuZXIoXHJcbiAgICAgICAgICBldmVudCxcclxuICAgICAgICAgIChldmVudCkgPT4gdGhpcy5oaWdobGlnaHQoZXZlbnQuY3VycmVudFRhcmdldCBhcyBIVE1MRWxlbWVudCwgaWNvblBhY2tTZXR0aW5nLnNldHRpbmdFbCksXHJcbiAgICAgICAgICBmYWxzZSxcclxuICAgICAgICApO1xyXG4gICAgICB9KTtcclxuICAgICAgWydkcmFnbGVhdmUnLCAnZHJvcCddLmZvckVhY2goKGV2ZW50KSA9PiB7XHJcbiAgICAgICAgaWNvblBhY2tTZXR0aW5nLnNldHRpbmdFbC5hZGRFdmVudExpc3RlbmVyKFxyXG4gICAgICAgICAgZXZlbnQsXHJcbiAgICAgICAgICAoZXZlbnQpID0+IHRoaXMudW5oaWdobGlnaHQoZXZlbnQuY3VycmVudFRhcmdldCBhcyBIVE1MRWxlbWVudCwgaWNvblBhY2tTZXR0aW5nLnNldHRpbmdFbCksXHJcbiAgICAgICAgICBmYWxzZSxcclxuICAgICAgICApO1xyXG4gICAgICB9KTtcclxuICAgICAgaWNvblBhY2tTZXR0aW5nLnNldHRpbmdFbC5hZGRFdmVudExpc3RlbmVyKFxyXG4gICAgICAgICdkcm9wJyxcclxuICAgICAgICAoZXZlbnQpID0+IHtcclxuICAgICAgICAgIGNvbnN0IGZpbGVzID0gZXZlbnQuZGF0YVRyYW5zZmVyLmZpbGVzO1xyXG4gICAgICAgICAgbGV0IHN1Y2Nlc3NmdWwgPSBmYWxzZTtcclxuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgY29uc3QgZmlsZSA9IGZpbGVzW2ldO1xyXG4gICAgICAgICAgICBpZiAoZmlsZS50eXBlICE9PSAnaW1hZ2Uvc3ZnK3htbCcpIHtcclxuICAgICAgICAgICAgICBuZXcgTm90aWNlKGBGaWxlICR7ZmlsZS5uYW1lfSBpcyBub3QgYSBYTUwgZmlsZS5gKTtcclxuICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgc3VjY2Vzc2Z1bCA9IHRydWU7XHJcbiAgICAgICAgICAgIHRoaXMucmVhZEZpbGUoZmlsZSwgYXN5bmMgKGNvbnRlbnQpID0+IHtcclxuICAgICAgICAgICAgICBhd2FpdCBjcmVhdGVGaWxlKHRoaXMucGx1Z2luLCBpY29uUGFjay5uYW1lLCBmaWxlLm5hbWUsIGNvbnRlbnQpO1xyXG4gICAgICAgICAgICAgIGFkZEljb25Ub0ljb25QYWNrKGljb25QYWNrLm5hbWUsIGZpbGUubmFtZSwgY29udGVudCk7XHJcbiAgICAgICAgICAgICAgaWNvblBhY2tTZXR0aW5nLnNldERlc2MoYFRvdGFsIGljb25zOiAke2ljb25QYWNrLmljb25zLmxlbmd0aH0gKGFkZGVkOiAke2ZpbGUubmFtZX0pYCk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIGlmIChzdWNjZXNzZnVsKSB7XHJcbiAgICAgICAgICAgIG5ldyBOb3RpY2UoJ0ljb25zIHN1Y2Nlc3NmdWxseSBhZGRlZC4nKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG4gICAgICAgIGZhbHNlLFxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcblxyXG4gICAgY29udGFpbmVyRWwuY3JlYXRlRWwoJ2gzJywgeyB0ZXh0OiAnSWNvbiBGb2xkZXIgQ3VzdG9taXphdGlvbicgfSk7XHJcblxyXG4gICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXHJcbiAgICAgIC5zZXROYW1lKCdJY29uIGZvbnQgc2l6ZSAoaW4gcGl4ZWxzKScpXHJcbiAgICAgIC5zZXREZXNjKCdDaGFuZ2UgdGhlIGZvbnQgc2l6ZSBvZiB0aGUgZGlzcGxheWVkIGljb25zLicpXHJcbiAgICAgIC5hZGRTbGlkZXIoKHNsaWRlcikgPT4ge1xyXG4gICAgICAgIHNsaWRlclxyXG4gICAgICAgICAgLnNldExpbWl0cygxMCwgMjQsIDEpXHJcbiAgICAgICAgICAuc2V0RHluYW1pY1Rvb2x0aXAoKVxyXG4gICAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLmdldFNldHRpbmdzKCkuZm9udFNpemUgPz8gREVGQVVMVF9TRVRUSU5HUy5mb250U2l6ZSlcclxuICAgICAgICAgIC5vbkNoYW5nZShhc3luYyAodmFsKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMucGx1Z2luLmdldFNldHRpbmdzKCkuZm9udFNpemUgPSB2YWw7XHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVJY29uRm9sZGVyRGF0YSgpO1xyXG5cclxuICAgICAgICAgICAgcmVmcmVzaEljb25TdHlsZSh0aGlzLnBsdWdpbik7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgY29uc3QgY29sb3JDdXN0b21pemF0aW9uID0gbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXHJcbiAgICAgIC5zZXROYW1lKCdJY29uIGNvbG9yJylcclxuICAgICAgLnNldERlc2MoJ0NoYW5nZSB0aGUgY29sb3Igb2YgdGhlIGRpc3BsYXllZCBpY29ucy4nKTtcclxuICAgIGNvbnN0IGNvbG9yUGlja2VyID0gbmV3IENvbG9yUGlja2VyQ29tcG9uZW50KGNvbG9yQ3VzdG9taXphdGlvbi5jb250cm9sRWwpXHJcbiAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5nZXRTZXR0aW5ncygpLmljb25Db2xvciA/PyAnIzAwMDAwMCcpXHJcbiAgICAgIC5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcclxuICAgICAgICB0aGlzLnBsdWdpbi5nZXRTZXR0aW5ncygpLmljb25Db2xvciA9IHZhbHVlO1xyXG4gICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVJY29uRm9sZGVyRGF0YSgpO1xyXG5cclxuICAgICAgICByZWZyZXNoSWNvblN0eWxlKHRoaXMucGx1Z2luKTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgY29sb3JDdXN0b21pemF0aW9uLmFkZEJ1dHRvbigoYnV0dG9uKSA9PiB7XHJcbiAgICAgIGJ1dHRvblxyXG4gICAgICAgIC5zZXRCdXR0b25UZXh0KCdEZWZhdWx0JylcclxuICAgICAgICAuc2V0VG9vbHRpcCgnU2V0IGNvbG9yIHRvIHRoZSBkZWZhdWx0IG9uZScpXHJcbiAgICAgICAgLm9uQ2xpY2soYXN5bmMgKCkgPT4ge1xyXG4gICAgICAgICAgY29sb3JQaWNrZXIuc2V0VmFsdWUoJyMwMDAwMDAnKTtcclxuICAgICAgICAgIHRoaXMucGx1Z2luLmdldFNldHRpbmdzKCkuaWNvbkNvbG9yID0gbnVsbDtcclxuICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVJY29uRm9sZGVyRGF0YSgpO1xyXG5cclxuICAgICAgICAgIHJlZnJlc2hJY29uU3R5bGUodGhpcy5wbHVnaW4pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfSk7XHJcblxyXG4gICAgY29sb3JDdXN0b21pemF0aW9uLmNvbXBvbmVudHMucHVzaChjb2xvclBpY2tlci5idWlsZCgpKTtcclxuXHJcbiAgICBjb25zdCBleHRyYVBhZGRpbmdTZXR0aW5nID0gbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXHJcbiAgICAgIC5zZXROYW1lKCdUb3AgRXh0cmFwYWRkaW5nIChpbiBwaXhlbHMpJylcclxuICAgICAgLnNldERlc2MoJ0NoYW5nZSB0aGUgdG9wIHBhZGRpbmcgb2YgdGhlIGljb25zLicpXHJcbiAgICAgIC5zZXRDbGFzcygnb2JzaWRpYW4taWNvbi1mb2xkZXItc2V0dGluZycpO1xyXG4gICAgY29uc3QgZXh0cmFQYWRkaW5nRHJvcGRvd24gPSBuZXcgRHJvcGRvd25Db21wb25lbnQoZXh0cmFQYWRkaW5nU2V0dGluZy5jb250cm9sRWwpLmFkZE9wdGlvbnMoe1xyXG4gICAgICB0b3A6ICdUb3AnLFxyXG4gICAgICByaWdodDogJ1JpZ2h0JyxcclxuICAgICAgYm90dG9tOiAnQm90dG9tJyxcclxuICAgICAgbGVmdDogJ0xlZnQnLFxyXG4gICAgfSBhcyBSZWNvcmQ8a2V5b2YgRXh0cmFQYWRkaW5nU2V0dGluZ3MsIHN0cmluZz4pO1xyXG4gICAgY29uc3QgZXh0cmFQYWRkaW5nU2xpZGVyID0gbmV3IFNsaWRlckNvbXBvbmVudChleHRyYVBhZGRpbmdTZXR0aW5nLmNvbnRyb2xFbClcclxuICAgICAgLnNldExpbWl0cygwLCAyNCwgMSlcclxuICAgICAgLnNldER5bmFtaWNUb29sdGlwKClcclxuICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLmdldFNldHRpbmdzKCkuZXh0cmFQYWRkaW5nPy50b3AgPz8gMilcclxuICAgICAgLm9uQ2hhbmdlKGFzeW5jICh2YWwpID0+IHtcclxuICAgICAgICBjb25zdCBkcm9wZG93blZhbHVlID0gZXh0cmFQYWRkaW5nRHJvcGRvd24uZ2V0VmFsdWUoKSBhcyBrZXlvZiBFeHRyYVBhZGRpbmdTZXR0aW5ncztcclxuICAgICAgICBpZiAodGhpcy5wbHVnaW4uZ2V0U2V0dGluZ3MoKS5leHRyYVBhZGRpbmcpIHtcclxuICAgICAgICAgIHRoaXMucGx1Z2luLmdldFNldHRpbmdzKCkuZXh0cmFQYWRkaW5nW2Ryb3Bkb3duVmFsdWVdID0gdmFsO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGlzLnBsdWdpbi5nZXRTZXR0aW5ncygpLmV4dHJhUGFkZGluZyA9IHtcclxuICAgICAgICAgICAgW2Ryb3Bkb3duVmFsdWVdOiB2YWwsXHJcbiAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlSWNvbkZvbGRlckRhdGEoKTtcclxuXHJcbiAgICAgICAgcmVmcmVzaEljb25TdHlsZSh0aGlzLnBsdWdpbik7XHJcbiAgICAgIH0pO1xyXG4gICAgZXh0cmFQYWRkaW5nRHJvcGRvd24ub25DaGFuZ2UoKHZhbDoga2V5b2YgRXh0cmFQYWRkaW5nU2V0dGluZ3MpID0+IHtcclxuICAgICAgaWYgKHRoaXMucGx1Z2luLmdldFNldHRpbmdzKCkuZXh0cmFQYWRkaW5nKSB7XHJcbiAgICAgICAgZXh0cmFQYWRkaW5nU2xpZGVyLnNldFZhbHVlKHRoaXMucGx1Z2luLmdldFNldHRpbmdzKCkuZXh0cmFQYWRkaW5nW3ZhbF0gPz8gMik7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgZXh0cmFQYWRkaW5nU2xpZGVyLnNldFZhbHVlKDIpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIGV4dHJhUGFkZGluZ1NldHRpbmcuY29tcG9uZW50cy5wdXNoKGV4dHJhUGFkZGluZ0Ryb3Bkb3duLCBleHRyYVBhZGRpbmdTbGlkZXIpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSByZWFkRmlsZShmaWxlOiBGaWxlLCBjYWxsYmFjazogKGNvbnRlbnQ6IHN0cmluZykgPT4gdm9pZCk6IHZvaWQge1xyXG4gICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcclxuICAgIHJlYWRlci5yZWFkQXNUZXh0KGZpbGUsICdVVEYtOCcpO1xyXG4gICAgcmVhZGVyLm9ubG9hZCA9IGFzeW5jIChyZWFkZXJFdmVudCkgPT4ge1xyXG4gICAgICBjb25zdCBjb250ZW50ID0gcmVhZGVyRXZlbnQudGFyZ2V0LnJlc3VsdCBhcyBzdHJpbmc7XHJcbiAgICAgIGNhbGxiYWNrKGNvbnRlbnQpO1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJldmVudERlZmF1bHRzKGV2ZW50OiBFdmVudCk6IHZvaWQge1xyXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoaWdobGlnaHQodGFyZ2V0OiBIVE1MRWxlbWVudCwgZWw6IEhUTUxFbGVtZW50KTogdm9pZCB7XHJcbiAgICBjbGVhclRpbWVvdXQodGhpcy5jbG9zZVRpbWVyKTtcclxuXHJcbiAgICBpZiAoIXRoaXMuZHJhZ1RhcmdldEVsZW1lbnQpIHtcclxuICAgICAgZWwuYXBwZW5kQ2hpbGQodGhpcy5kcmFnT3ZlckVsZW1lbnQpO1xyXG4gICAgICBlbC5jbGFzc0xpc3QuYWRkKCdvYnNpZGlhbi1pY29uLWZvbGRlci1kcmFnb3ZlcicpO1xyXG4gICAgICB0aGlzLmRyYWdUYXJnZXRFbGVtZW50ID0gZWw7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVuaGlnaGxpZ2h0KHRhcmdldDogSFRNTEVsZW1lbnQsIGVsOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuZHJhZ1RhcmdldEVsZW1lbnQgJiYgdGhpcy5kcmFnVGFyZ2V0RWxlbWVudCAhPT0gdGFyZ2V0KSB7XHJcbiAgICAgIHRoaXMuZHJhZ1RhcmdldEVsZW1lbnQucmVtb3ZlQ2hpbGQodGhpcy5kcmFnT3ZlckVsZW1lbnQpO1xyXG4gICAgICB0aGlzLmRyYWdUYXJnZXRFbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoJ29ic2lkaWFuLWljb24tZm9sZGVyLWRyYWdvdmVyJyk7XHJcbiAgICAgIHRoaXMuZHJhZ1RhcmdldEVsZW1lbnQgPSB1bmRlZmluZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgY2xlYXJUaW1lb3V0KHRoaXMuY2xvc2VUaW1lcik7XHJcbiAgICB0aGlzLmNsb3NlVGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgaWYgKHRoaXMuZHJhZ1RhcmdldEVsZW1lbnQpIHtcclxuICAgICAgICBlbC5yZW1vdmVDaGlsZCh0aGlzLmRyYWdPdmVyRWxlbWVudCk7XHJcbiAgICAgICAgZWwuY2xhc3NMaXN0LnJlbW92ZSgnb2JzaWRpYW4taWNvbi1mb2xkZXItZHJhZ292ZXInKTtcclxuICAgICAgICB0aGlzLmRyYWdUYXJnZXRFbGVtZW50ID0gdW5kZWZpbmVkO1xyXG4gICAgICB9XHJcbiAgICB9LCAxMDApO1xyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgdHdlbW9qaSBmcm9tICd0d2Vtb2ppJztcclxuaW1wb3J0IHsgQXBwLCBGdXp6eU1hdGNoLCBGdXp6eVN1Z2dlc3RNb2RhbCB9IGZyb20gJ29ic2lkaWFuJztcclxuaW1wb3J0IEljb25Gb2xkZXJQbHVnaW4gZnJvbSAnLi9tYWluJztcclxuaW1wb3J0IHsgYWRkVG9ET00sIGdldEVuYWJsZWRJY29ucywgZ2V0SWNvbiwgaXNFbW9qaSB9IGZyb20gJy4vdXRpbCc7XHJcbmltcG9ydCB7IGdldEFsbEljb25QYWNrcyB9IGZyb20gJy4vaWNvblBhY2tNYW5hZ2VyJztcclxuXHJcbnR5cGUgRW50ZXJTY29wZSA9ICgoKSA9PiB2b2lkKSB8ICgoZTogS2V5Ym9hcmRFdmVudCkgPT4gdm9pZCk7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIEljb24ge1xyXG4gIG5hbWU6IHN0cmluZztcclxuICBwcmVmaXg6IHN0cmluZztcclxufVxyXG5cclxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSWNvbnNQaWNrZXJNb2RhbCBleHRlbmRzIEZ1enp5U3VnZ2VzdE1vZGFsPGFueT4ge1xyXG4gIHByaXZhdGUgcGx1Z2luOiBJY29uRm9sZGVyUGx1Z2luO1xyXG4gIHByaXZhdGUgcGF0aDogc3RyaW5nO1xyXG5cclxuICBwcml2YXRlIG9sZEVudGVyRnVuYzogKGU6IEtleWJvYXJkRXZlbnQpID0+IHZvaWQ7XHJcblxyXG4gIHByaXZhdGUgcmVuZGVySW5kZXg6IG51bWJlciA9IDA7XHJcbiAgcHJpdmF0ZSBsYXN0UmVuZGVyZWRSZWNlbnRseUljb246IEhUTUxFbGVtZW50O1xyXG5cclxuICBwcml2YXRlIHJlY2VudGx5VXNlZEl0ZW1zOiBzdHJpbmdbXTtcclxuXHJcbiAgY29uc3RydWN0b3IoYXBwOiBBcHAsIHBsdWdpbjogSWNvbkZvbGRlclBsdWdpbiwgcGF0aDogc3RyaW5nKSB7XHJcbiAgICBzdXBlcihhcHApO1xyXG4gICAgdGhpcy5wbHVnaW4gPSBwbHVnaW47XHJcbiAgICB0aGlzLnBhdGggPSBwYXRoO1xyXG4gICAgdGhpcy5saW1pdCA9IDE1MDtcclxuICAgIHRoaXMucmVjZW50bHlVc2VkSXRlbXMgPSBwbHVnaW4uZ2V0U2V0dGluZ3MoKS5yZWNlbnRseVVzZWRJY29ucztcclxuXHJcbiAgICB0aGlzLnJlc3VsdENvbnRhaW5lckVsLmNsYXNzTGlzdC5hZGQoJ29ic2lkaWFuLWljb24tZm9sZGVyLW1vZGFsJyk7XHJcblxyXG4gICAgdGhpcy5vbGRFbnRlckZ1bmMgPSAodGhpcy5zY29wZSBhcyBhbnkpLmtleXMuZmluZCgoZTogYW55KSA9PiBlLmtleSA9PT0gJ0VudGVyJykuZnVuYztcclxuICB9XHJcblxyXG4gIG9uTm9TdWdnZXN0aW9uKCk6IHZvaWQge1xyXG4gICAgc3VwZXIub25Ob1N1Z2dlc3Rpb24oKTtcclxuICAgIGNvbnN0IGlucHV0VmFsID0gdGhpcy5pbnB1dEVsLnZhbHVlO1xyXG4gICAgaWYgKGlzRW1vamkoaW5wdXRWYWwpKSB7XHJcbiAgICAgIHRoaXMucmVzdWx0Q29udGFpbmVyRWwuZW1wdHkoKTtcclxuXHJcbiAgICAgIGNvbnN0IHN1Z2dlc3Rpb25JdGVtID0gdGhpcy5yZXN1bHRDb250YWluZXJFbC5jcmVhdGVEaXYoKTtcclxuICAgICAgc3VnZ2VzdGlvbkl0ZW0uY2xhc3NOYW1lID0gJ3N1Z2dlc3Rpb24taXRlbSBzdWdnZXN0aW9uLWl0ZW1fX2NlbnRlciBpcy1zZWxlY3RlZCc7XHJcbiAgICAgIHN1Z2dlc3Rpb25JdGVtLnRleHRDb250ZW50ID0gJ1VzZSB0d2Vtb2ppIEVtb2ppJztcclxuICAgICAgc3VnZ2VzdGlvbkl0ZW0uaW5uZXJIVE1MICs9IGA8ZGl2IGNsYXNzPVwib2JzaWRpYW4taWNvbi1mb2xkZXItaWNvbi1wcmV2aWV3XCI+JHt0d2Vtb2ppLnBhcnNlKGlucHV0VmFsKX08L2Rpdj5gO1xyXG5cclxuICAgICAgdGhpcy5zZXRFbnRlclNjb3BlKCgpID0+IHtcclxuICAgICAgICB0aGlzLnNlbGVjdFR3ZW1vamkoaW5wdXRWYWwpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHN1Z2dlc3Rpb25JdGVtLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4ge1xyXG4gICAgICAgIHRoaXMuc2VsZWN0VHdlbW9qaShpbnB1dFZhbCk7XHJcbiAgICAgIH0pO1xyXG4gICAgICB0aGlzLnJlc3VsdENvbnRhaW5lckVsLmFwcGVuZENoaWxkKHN1Z2dlc3Rpb25JdGVtKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2VsZWN0VHdlbW9qaShpbnB1dFZhbDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLm9uQ2hvb3NlSXRlbShpbnB1dFZhbCk7XHJcbiAgICB0aGlzLmNsb3NlKCk7XHJcbiAgfVxyXG5cclxuICBvbk9wZW4oKSB7XHJcbiAgICBzdXBlci5vbk9wZW4oKTtcclxuICB9XHJcblxyXG4gIG9uQ2xvc2UoKSB7XHJcbiAgICBjb25zdCB7IGNvbnRlbnRFbCB9ID0gdGhpcztcclxuICAgIGNvbnRlbnRFbC5lbXB0eSgpO1xyXG4gIH1cclxuXHJcbiAgZ2V0SXRlbVRleHQoaXRlbTogSWNvbik6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gYCR7aXRlbS5uYW1lfSAoJHtpdGVtLnByZWZpeH0pYDtcclxuICB9XHJcblxyXG4gIGdldEl0ZW1zKCk6IEljb25bXSB7XHJcbiAgICBjb25zdCBpY29uS2V5czogSWNvbltdID0gW107XHJcblxyXG4gICAgaWYgKHRoaXMuaW5wdXRFbC52YWx1ZS5sZW5ndGggPT09IDApIHtcclxuICAgICAgdGhpcy5yZW5kZXJJbmRleCA9IDA7XHJcbiAgICAgIHRoaXMucmVjZW50bHlVc2VkSXRlbXMuZm9yRWFjaCgoaWNvbk5hbWUpID0+IHtcclxuICAgICAgICBpY29uS2V5cy5wdXNoKHtcclxuICAgICAgICAgIG5hbWU6IGljb25OYW1lLFxyXG4gICAgICAgICAgcHJlZml4OiBpY29uTmFtZS5zdWJzdHJpbmcoMCwgMiksXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGZvciAoY29uc3QgaWNvbiBvZiBnZXRFbmFibGVkSWNvbnModGhpcy5wbHVnaW4pKSB7XHJcbiAgICAgIGljb25LZXlzLnB1c2goe1xyXG4gICAgICAgIG5hbWU6IGljb24ubmFtZSxcclxuICAgICAgICBwcmVmaXg6IGljb24ucHJlZml4LFxyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gaWNvbktleXM7XHJcbiAgfVxyXG5cclxuICBvbkNob29zZUl0ZW0oaXRlbTogSWNvbiB8IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKHR5cGVvZiBpdGVtID09PSAnb2JqZWN0Jykge1xyXG4gICAgICBhZGRUb0RPTSh0aGlzLnBsdWdpbiwgdGhpcy5wYXRoLCBpdGVtLm5hbWUpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgYWRkVG9ET00odGhpcy5wbHVnaW4sIHRoaXMucGF0aCwgaXRlbSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLnBsdWdpbi5hZGRGb2xkZXJJY29uKHRoaXMucGF0aCwgaXRlbSk7XHJcbiAgfVxyXG5cclxuICByZW5kZXJTdWdnZXN0aW9uKGl0ZW06IEZ1enp5TWF0Y2g8SWNvbj4sIGVsOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG4gICAgc3VwZXIucmVuZGVyU3VnZ2VzdGlvbihpdGVtLCBlbCk7XHJcblxyXG4gICAgaWYgKGdldEFsbEljb25QYWNrcygpLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICB0aGlzLmlucHV0RWwuZGlzYWJsZWQgPSB0cnVlO1xyXG4gICAgICB0aGlzLnJlc3VsdENvbnRhaW5lckVsLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xyXG4gICAgICB0aGlzLnJlc3VsdENvbnRhaW5lckVsLmlubmVySFRNTCA9ICc8ZGl2IGNsYXNzPVwic3VnZ2VzdGlvbi1lbXB0eVwiPllvdSBuZWVkIHRvIGNyZWF0ZSBhbiBpY29uIHBhY2suPC9kaXY+JztcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFJlbmRlciBzdWJoZWFkbGluZXMgZm9yIG1vZGFsLlxyXG4gICAgaWYgKHRoaXMucmVjZW50bHlVc2VkSXRlbXMubGVuZ3RoICE9PSAwICYmIHRoaXMuaW5wdXRFbC52YWx1ZS5sZW5ndGggPT09IDApIHtcclxuICAgICAgaWYgKHRoaXMucmVuZGVySW5kZXggPT09IDApIHtcclxuICAgICAgICBjb25zdCBzdWJoZWFkbGluZSA9IHRoaXMucmVzdWx0Q29udGFpbmVyRWwuY3JlYXRlRGl2KCk7XHJcbiAgICAgICAgc3ViaGVhZGxpbmUuY2xhc3NMaXN0LmFkZCgnb2JzaWRpYW4taWNvbi1mb2xkZXItc3ViaGVhZGxpbmUnKTtcclxuICAgICAgICBzdWJoZWFkbGluZS5pbm5lclRleHQgPSAnUmVjZW50bHkgdXNlZCBJY29uczonO1xyXG4gICAgICAgIHRoaXMucmVzdWx0Q29udGFpbmVyRWwucHJlcGVuZChzdWJoZWFkbGluZSk7XHJcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5yZW5kZXJJbmRleCA9PT0gdGhpcy5yZWNlbnRseVVzZWRJdGVtcy5sZW5ndGgpIHtcclxuICAgICAgICBjb25zdCBzdWJoZWFkbGluZSA9IHRoaXMuY29udGFpbmVyRWwuY3JlYXRlRGl2KCk7XHJcbiAgICAgICAgc3ViaGVhZGxpbmUuY2xhc3NMaXN0LmFkZCgnb2JzaWRpYW4taWNvbi1mb2xkZXItc3ViaGVhZGxpbmUnKTtcclxuICAgICAgICBzdWJoZWFkbGluZS5pbm5lclRleHQgPSAnQWxsIEljb25zOic7XHJcbiAgICAgICAgc3ViaGVhZGxpbmUuaW5zZXJ0QWZ0ZXIodGhpcy5sYXN0UmVuZGVyZWRSZWNlbnRseUljb24pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuZ2V0RW50ZXJTY29wZSgpICE9PSB0aGlzLm9sZEVudGVyRnVuYykge1xyXG4gICAgICB0aGlzLnNldEVudGVyU2NvcGUodGhpcy5vbGRFbnRlckZ1bmMpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChpdGVtLml0ZW0ubmFtZSAhPT0gJ2RlZmF1bHQnKSB7XHJcbiAgICAgIGNvbnN0IHBvc3NpYmxlRW1vamkgPSBlbC5pbm5lckhUTUwudHJpbSgpLnJlcGxhY2UoL1xcKHxcXCkvZ2ksICcnKTtcclxuICAgICAgaWYgKGlzRW1vamkocG9zc2libGVFbW9qaSkpIHtcclxuICAgICAgICBlbC5pbm5lckhUTUwgPSBgPGRpdj5Ud2Vtb2ppPC9kaXY+PGRpdiBjbGFzcz1cIm9ic2lkaWFuLWljb24tZm9sZGVyLWljb24tcHJldmlld1wiPiR7dHdlbW9qaS5wYXJzZShcclxuICAgICAgICAgIHBvc3NpYmxlRW1vamksXHJcbiAgICAgICAgKX08L2Rpdj5gO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGVsLmlubmVySFRNTCA9IGA8ZGl2PiR7ZWwuaW5uZXJIVE1MfTwvZGl2PjxkaXYgY2xhc3M9XCJvYnNpZGlhbi1pY29uLWZvbGRlci1pY29uLXByZXZpZXdcIj4ke2dldEljb24oXHJcbiAgICAgICAgICBpdGVtLml0ZW0ubmFtZSxcclxuICAgICAgICApfTwvZGl2PmA7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmxhc3RSZW5kZXJlZFJlY2VudGx5SWNvbiA9IGVsO1xyXG4gICAgdGhpcy5yZW5kZXJJbmRleCsrO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXRFbnRlclNjb3BlKGZ1bmM6IEVudGVyU2NvcGUpOiB2b2lkIHtcclxuICAgICh0aGlzLnNjb3BlIGFzIGFueSkua2V5cy5maW5kKChlOiBhbnkpID0+IGUua2V5ID09PSAnRW50ZXInKS5mdW5jID0gZnVuYztcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0RW50ZXJTY29wZSgpOiBFbnRlclNjb3BlIHtcclxuICAgIHJldHVybiAodGhpcy5zY29wZSBhcyBhbnkpLmtleXMuZmluZCgoZTogYW55KSA9PiBlLmtleSA9PT0gJ0VudGVyJykuZnVuYztcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgUGx1Z2luLCBNZW51SXRlbSwgVEZpbGUgfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCB7IEV4cGxvcmVyVmlldyB9IGZyb20gJy4vQHR5cGVzL29ic2lkaWFuJztcclxuaW1wb3J0IHsgaW5pdEljb25QYWNrcyB9IGZyb20gJy4vaWNvblBhY2tNYW5hZ2VyJztcclxuaW1wb3J0IEljb25Gb2xkZXJTZXR0aW5nc1RhYiBmcm9tICcuL2ljb25Gb2xkZXJTZXR0aW5nc1RhYic7XHJcbmltcG9ydCBJY29uc1BpY2tlck1vZGFsLCB7IEljb24gfSBmcm9tICcuL2ljb25zUGlja2VyTW9kYWwnO1xyXG5pbXBvcnQgeyBERUZBVUxUX1NFVFRJTkdTLCBJY29uRm9sZGVyU2V0dGluZ3MgfSBmcm9tICcuL3NldHRpbmdzJztcclxuaW1wb3J0IHtcclxuICBpbnNlcnRJY29uVG9Ob2RlLFxyXG4gIGFkZEljb25zVG9ET00sXHJcbiAgYWRkSW5oZXJpdGFuY2VGb3JGb2xkZXIsXHJcbiAgYWRkSW5oZXJpdGFuY2VJY29uVG9GaWxlLFxyXG4gIHJlbW92ZUZyb21ET00sXHJcbiAgcmVtb3ZlSW5oZXJpdGFuY2VGb3JGb2xkZXIsXHJcbn0gZnJvbSAnLi91dGlsJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgRm9sZGVySWNvbk9iamVjdCB7XHJcbiAgaWNvbk5hbWU6IHN0cmluZyB8IG51bGw7XHJcbiAgaW5oZXJpdGFuY2VJY29uOiBzdHJpbmc7XHJcbn1cclxuXHJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEljb25Gb2xkZXJQbHVnaW4gZXh0ZW5kcyBQbHVnaW4ge1xyXG4gIHByaXZhdGUgZGF0YTogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgSWNvbkZvbGRlclNldHRpbmdzIHwgRm9sZGVySWNvbk9iamVjdD47XHJcbiAgcHJpdmF0ZSByZWdpc3RlcmVkRmlsZUV4cGxvcmVycyA9IG5ldyBXZWFrU2V0PEV4cGxvcmVyVmlldz4oKTtcclxuXHJcbiAgYXN5bmMgb25sb2FkKCkge1xyXG4gICAgY29uc29sZS5sb2coJ2xvYWRpbmcgb2JzaWRpYW4taWNvbi1mb2xkZXInKTtcclxuXHJcbiAgICBhd2FpdCBpbml0SWNvblBhY2tzKHRoaXMpO1xyXG5cclxuICAgIGF3YWl0IHRoaXMubG9hZEljb25Gb2xkZXJEYXRhKCk7XHJcbiAgICBhd2FpdCB0aGlzLmNoZWNrUmVjZW50bHlVc2VkSWNvbnMoKTtcclxuXHJcbiAgICB0aGlzLmFwcC53b3Jrc3BhY2Uub25MYXlvdXRSZWFkeSgoKSA9PiB0aGlzLmhhbmRsZUNoYW5nZUxheW91dCgpKTtcclxuICAgIHRoaXMucmVnaXN0ZXJFdmVudCh0aGlzLmFwcC53b3Jrc3BhY2Uub24oJ2xheW91dC1jaGFuZ2UnLCAoKSA9PiB0aGlzLmhhbmRsZUNoYW5nZUxheW91dCgpKSk7XHJcblxyXG4gICAgdGhpcy5yZWdpc3RlckV2ZW50KFxyXG4gICAgICB0aGlzLmFwcC53b3Jrc3BhY2Uub24oJ2ZpbGUtbWVudScsIChtZW51LCBmaWxlKSA9PiB7XHJcbiAgICAgICAgY29uc3QgYWRkSWNvbk1lbnVJdGVtID0gKGl0ZW06IE1lbnVJdGVtKSA9PiB7XHJcbiAgICAgICAgICBpdGVtLnNldFRpdGxlKCdDaGFuZ2UgaWNvbicpO1xyXG4gICAgICAgICAgaXRlbS5zZXRJY29uKCdoYXNodGFnJyk7XHJcbiAgICAgICAgICBpdGVtLm9uQ2xpY2soKCkgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBtb2RhbCA9IG5ldyBJY29uc1BpY2tlck1vZGFsKHRoaXMuYXBwLCB0aGlzLCBmaWxlLnBhdGgpO1xyXG4gICAgICAgICAgICBtb2RhbC5vcGVuKCk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBjb25zdCByZW1vdmVJY29uTWVudUl0ZW0gPSAoaXRlbTogTWVudUl0ZW0pID0+IHtcclxuICAgICAgICAgIGl0ZW0uc2V0VGl0bGUoJ1JlbW92ZSBpY29uJyk7XHJcbiAgICAgICAgICBpdGVtLnNldEljb24oJ3RyYXNoJyk7XHJcbiAgICAgICAgICBpdGVtLm9uQ2xpY2soKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLnJlbW92ZUZvbGRlckljb24oZmlsZS5wYXRoKTtcclxuICAgICAgICAgICAgcmVtb3ZlRnJvbURPTShmaWxlLnBhdGgpO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgbWVudS5hZGRJdGVtKGFkZEljb25NZW51SXRlbSk7XHJcblxyXG4gICAgICAgIGNvbnN0IG5vZGUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGBbZGF0YS1wYXRoPVwiJHtmaWxlLnBhdGh9XCJdYCk7XHJcbiAgICAgICAgY29uc3QgaWNvbk5vZGUgPSBub2RlLnF1ZXJ5U2VsZWN0b3IoJy5vYnNpZGlhbi1pY29uLWZvbGRlci1pY29uJyk7XHJcblxyXG4gICAgICAgIGlmIChpY29uTm9kZSkge1xyXG4gICAgICAgICAgbWVudS5hZGRJdGVtKHJlbW92ZUljb25NZW51SXRlbSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBpbmhlcml0SWNvbiA9IChpdGVtOiBNZW51SXRlbSkgPT4ge1xyXG4gICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmRhdGFbZmlsZS5wYXRoXSA9PT0gJ29iamVjdCcpIHtcclxuICAgICAgICAgICAgaXRlbS5zZXRUaXRsZSgnUmVtb3ZlIGluaGVyaXQgaWNvbicpO1xyXG4gICAgICAgICAgICBpdGVtLm9uQ2xpY2soKCkgPT4ge1xyXG4gICAgICAgICAgICAgIHJlbW92ZUluaGVyaXRhbmNlRm9yRm9sZGVyKHRoaXMsIGZpbGUucGF0aCk7XHJcbiAgICAgICAgICAgICAgdGhpcy5zYXZlSW5oZXJpdGFuY2VEYXRhKGZpbGUucGF0aCwgbnVsbCk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgaXRlbS5zZXRUaXRsZSgnSW5oZXJpdCBpY29uJyk7XHJcbiAgICAgICAgICAgIGl0ZW0ub25DbGljaygoKSA9PiB7XHJcbiAgICAgICAgICAgICAgY29uc3QgbW9kYWwgPSBuZXcgSWNvbnNQaWNrZXJNb2RhbCh0aGlzLmFwcCwgdGhpcywgZmlsZS5wYXRoKTtcclxuICAgICAgICAgICAgICBtb2RhbC5vcGVuKCk7XHJcbiAgICAgICAgICAgICAgLy8gbWFuaXB1bGF0ZSBgb25DaG9vc2VJdGVtYCBtZXRob2QgdG8gZ2V0IGN1c3RvbSBmdW5jdGlvYW5saXR5IGZvciBpbmhlcml0aW5nIGljb25zXHJcbiAgICAgICAgICAgICAgbW9kYWwub25DaG9vc2VJdGVtID0gKGljb246IEljb24gfCBzdHJpbmcpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2F2ZUluaGVyaXRhbmNlRGF0YShmaWxlLnBhdGgsIGljb24pO1xyXG4gICAgICAgICAgICAgICAgYWRkSW5oZXJpdGFuY2VGb3JGb2xkZXIodGhpcywgZmlsZS5wYXRoKTtcclxuICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGl0ZW0uc2V0SWNvbigndmVydGljYWwtdGhyZWUtZG90cycpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIG1lbnUuYWRkSXRlbShpbmhlcml0SWNvbik7XHJcbiAgICAgIH0pLFxyXG4gICAgKTtcclxuXHJcbiAgICAvLyBkZWxldGluZyBldmVudFxyXG4gICAgdGhpcy5yZWdpc3RlckV2ZW50KFxyXG4gICAgICB0aGlzLmFwcC52YXVsdC5vbignZGVsZXRlJywgKGZpbGUpID0+IHtcclxuICAgICAgICBjb25zdCBwYXRoID0gZmlsZS5wYXRoO1xyXG4gICAgICAgIHRoaXMucmVtb3ZlRm9sZGVySWNvbihwYXRoKTtcclxuICAgICAgfSksXHJcbiAgICApO1xyXG5cclxuICAgIC8vIHJlbmFtaW5nIGV2ZW50XHJcbiAgICB0aGlzLnJlZ2lzdGVyRXZlbnQoXHJcbiAgICAgIHRoaXMuYXBwLnZhdWx0Lm9uKCdyZW5hbWUnLCAoZmlsZSwgb2xkUGF0aCkgPT4ge1xyXG4gICAgICAgIHRoaXMucmVuYW1lRm9sZGVyKGZpbGUucGF0aCwgb2xkUGF0aCk7XHJcbiAgICAgIH0pLFxyXG4gICAgKTtcclxuXHJcbiAgICB0aGlzLmFkZFNldHRpbmdUYWIobmV3IEljb25Gb2xkZXJTZXR0aW5nc1RhYih0aGlzLmFwcCwgdGhpcykpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRTZWFyY2hMZWF2ZSgpOiBFeHBsb3JlclZpZXcge1xyXG4gICAgcmV0dXJuIHRoaXMuYXBwLndvcmtzcGFjZS5nZXRMZWF2ZXNPZlR5cGUoJ3NlYXJjaCcpWzBdLnZpZXc7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFkZEljb25zVG9TZWFyY2goKTogdm9pZCB7XHJcbiAgICBjb25zb2xlLmxvZyh0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0TGVhdmVzT2ZUeXBlKCdiYWNrbGluaycpKTtcclxuICAgIGNvbnN0IHNlYXJjaExlYXZlRG9tID0gdGhpcy5nZXRTZWFyY2hMZWF2ZSgpLmRvbTtcclxuICAgIHNlYXJjaExlYXZlRG9tLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkKSA9PiB7XHJcbiAgICAgIGNvbnN0IGZpbGUgPSBjaGlsZC5maWxlIGFzIFRGaWxlO1xyXG4gICAgICBjb25zdCBjb2xsYXBzZUVsID0gY2hpbGQuY29sbGFwc2VFbCBhcyBIVE1MRWxlbWVudDtcclxuXHJcbiAgICAgIGNvbnN0IGV4aXN0aW5nSWNvbiA9IGNoaWxkLmNvbnRhaW5lckVsLnF1ZXJ5U2VsZWN0b3IoJy5vYnNpZGlhbi1pY29uLWZvbGRlci1pY29uJyk7XHJcbiAgICAgIGlmIChleGlzdGluZ0ljb24pIHtcclxuICAgICAgICBleGlzdGluZ0ljb24ucmVtb3ZlKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IGljb25OYW1lID0gdGhpcy5kYXRhW2ZpbGUucGF0aF0gYXMgc3RyaW5nIHwgdW5kZWZpbmVkO1xyXG4gICAgICBpZiAoaWNvbk5hbWUpIHtcclxuICAgICAgICBjb25zdCBpY29uTm9kZSA9IGNoaWxkLmNvbnRhaW5lckVsLmNyZWF0ZURpdigpO1xyXG4gICAgICAgIGljb25Ob2RlLmNsYXNzTGlzdC5hZGQoJ29ic2lkaWFuLWljb24tZm9sZGVyLWljb24nKTtcclxuXHJcbiAgICAgICAgaW5zZXJ0SWNvblRvTm9kZSh0aGlzLCB0aGlzLmRhdGFbZmlsZS5wYXRoXSBhcyBzdHJpbmcsIGljb25Ob2RlKTtcclxuXHJcbiAgICAgICAgaWNvbk5vZGUuaW5zZXJ0QWZ0ZXIoY29sbGFwc2VFbCk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVDaGFuZ2VMYXlvdXQoKTogdm9pZCB7XHJcbiAgICAvLyB0cmFuc2Zvcm0gZGF0YSB0aGF0IGFyZSBvYmplY3RzIHRvIHNpbmdsZSBzdHJpbmdzXHJcbiAgICBjb25zdCBkYXRhID0gT2JqZWN0LmVudHJpZXModGhpcy5kYXRhKSBhcyBbc3RyaW5nLCBzdHJpbmcgfCBGb2xkZXJJY29uT2JqZWN0XVtdO1xyXG5cclxuICAgIGFkZEljb25zVG9ET00odGhpcywgZGF0YSwgdGhpcy5yZWdpc3RlcmVkRmlsZUV4cGxvcmVycywgKCkgPT4ge1xyXG4gICAgICBjb25zdCBzZWFyY2hMZWF2ZURvbSA9IHRoaXMuZ2V0U2VhcmNoTGVhdmUoKS5kb207XHJcbiAgICAgIHNlYXJjaExlYXZlRG9tLmNoYW5nZWQgPSAoKSA9PiB0aGlzLmFkZEljb25zVG9TZWFyY2goKTtcclxuXHJcbiAgICAgIC8vIHJlZ2lzdGVyIGNyZWF0ZSBldmVudCBmb3IgY2hlY2tpbmcgaW5oZXJpdGFuY2UgZnVuY3Rpb25hbGl0eVxyXG4gICAgICB0aGlzLnJlZ2lzdGVyRXZlbnQoXHJcbiAgICAgICAgdGhpcy5hcHAudmF1bHQub24oJ2NyZWF0ZScsIChmaWxlKSA9PiB7XHJcbiAgICAgICAgICBjb25zdCBpbmhlcml0YW5jZUZvbGRlcnMgPSBPYmplY3QuZW50cmllcyh0aGlzLmRhdGEpLmZpbHRlcihcclxuICAgICAgICAgICAgKFtrLCB2XSkgPT4gayAhPT0gJ3NldHRpbmdzJyAmJiB0eXBlb2YgdiA9PT0gJ29iamVjdCcsXHJcbiAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgIGlmIChmaWxlLnBhcmVudC5wYXRoID09PSAnLycpIHJldHVybjtcclxuXHJcbiAgICAgICAgICBpbmhlcml0YW5jZUZvbGRlcnMuZm9yRWFjaCgoW3BhdGgsIG9ial06IFtzdHJpbmcsIEZvbGRlckljb25PYmplY3RdKSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChmaWxlLnBhcmVudC5wYXRoLmluY2x1ZGVzKHBhdGgpKSB7XHJcbiAgICAgICAgICAgICAgYWRkSW5oZXJpdGFuY2VJY29uVG9GaWxlKHRoaXMsIHRoaXMucmVnaXN0ZXJlZEZpbGVFeHBsb3JlcnMsIGZpbGUucGF0aCwgb2JqLmluaGVyaXRhbmNlSWNvbik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pLFxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNhdmVJbmhlcml0YW5jZURhdGEoZm9sZGVyUGF0aDogc3RyaW5nLCBpY29uOiBJY29uIHwgc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xyXG4gICAgY29uc3QgY3VycmVudFZhbHVlID0gdGhpcy5kYXRhW2ZvbGRlclBhdGhdO1xyXG4gICAgLy8gaWYgaWNvbiBpcyBudWxsLCBpdCB3aWxsIHJlbW92ZSB0aGUgaW5oZXJpdGFuY2UgaWNvbiBmcm9tIHRoZSBkYXRhXHJcbiAgICBpZiAoaWNvbiA9PT0gbnVsbCAmJiBjdXJyZW50VmFsdWUgJiYgdHlwZW9mIGN1cnJlbnRWYWx1ZSA9PT0gJ29iamVjdCcpIHtcclxuICAgICAgY29uc3QgZm9sZGVyT2JqZWN0ID0gY3VycmVudFZhbHVlIGFzIEZvbGRlckljb25PYmplY3Q7XHJcblxyXG4gICAgICBpZiAoZm9sZGVyT2JqZWN0Lmljb25OYW1lKSB7XHJcbiAgICAgICAgdGhpcy5kYXRhW2ZvbGRlclBhdGhdID0gZm9sZGVyT2JqZWN0Lmljb25OYW1lO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGRlbGV0ZSB0aGlzLmRhdGFbZm9sZGVyUGF0aF07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vIGljb24gaXMgbm90IG51bGwsIHNvIGl0IHdpbGwgYWRkIGluaGVyaXRhbmNlIGRhdGFcclxuICAgIGVsc2Uge1xyXG4gICAgICAvLyBjaGVjayBpZiBkYXRhIGFscmVhZHkgZXhpc3RzXHJcbiAgICAgIGlmIChjdXJyZW50VmFsdWUpIHtcclxuICAgICAgICAvLyBjaGVjayBpZiBjdXJyZW50IHZhbHVlIGlzIGFscmVhZHkgYW4gaWNvbiBuYW1lXHJcbiAgICAgICAgaWYgKHR5cGVvZiBjdXJyZW50VmFsdWUgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICB0aGlzLmRhdGFbZm9sZGVyUGF0aF0gPSB7XHJcbiAgICAgICAgICAgIGljb25OYW1lOiBjdXJyZW50VmFsdWUgYXMgc3RyaW5nLFxyXG4gICAgICAgICAgICBpbmhlcml0YW5jZUljb246IHR5cGVvZiBpY29uID09PSAnb2JqZWN0JyA/IGljb24ubmFtZSA6IGljb24sXHJcbiAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBjaGVjayBpZiBpdCBoYXMgYWxyZWFkeSBhIGluaGVyaXRhbmNlIGljb25cclxuICAgICAgICBlbHNlIGlmIChmb2xkZXJQYXRoICE9PSAnc2V0dGluZ3MnKSB7XHJcbiAgICAgICAgICB0aGlzLmRhdGFbZm9sZGVyUGF0aF0gPSB7XHJcbiAgICAgICAgICAgIC4uLihjdXJyZW50VmFsdWUgYXMgRm9sZGVySWNvbk9iamVjdCksXHJcbiAgICAgICAgICAgIGluaGVyaXRhbmNlSWNvbjogdHlwZW9mIGljb24gPT09ICdvYmplY3QnID8gaWNvbi5uYW1lIDogaWNvbixcclxuICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuZGF0YVtmb2xkZXJQYXRoXSA9IHtcclxuICAgICAgICAgIGljb25OYW1lOiBudWxsLFxyXG4gICAgICAgICAgaW5oZXJpdGFuY2VJY29uOiB0eXBlb2YgaWNvbiA9PT0gJ29iamVjdCcgPyBpY29uLm5hbWUgOiBpY29uLFxyXG4gICAgICAgIH07XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnNhdmVJY29uRm9sZGVyRGF0YSgpO1xyXG4gIH1cclxuXHJcbiAgb251bmxvYWQoKSB7XHJcbiAgICBjb25zb2xlLmxvZygndW5sb2FkaW5nIG9ic2lkaWFuLWljb24tZm9sZGVyJyk7XHJcbiAgfVxyXG5cclxuICByZW5hbWVGb2xkZXIobmV3UGF0aDogc3RyaW5nLCBvbGRQYXRoOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5kYXRhW29sZFBhdGhdIHx8IG5ld1BhdGggPT09IG9sZFBhdGgpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLmRhdGEsIG5ld1BhdGgsIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGhpcy5kYXRhLCBvbGRQYXRoKSk7XHJcbiAgICBkZWxldGUgdGhpcy5kYXRhW29sZFBhdGhdO1xyXG4gICAgdGhpcy5zYXZlSWNvbkZvbGRlckRhdGEoKTtcclxuICB9XHJcblxyXG4gIHJlbW92ZUZvbGRlckljb24ocGF0aDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuZGF0YVtwYXRoXSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGVvZiB0aGlzLmRhdGFbcGF0aF0gPT09ICdvYmplY3QnKSB7XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IHRoaXMuZGF0YVtwYXRoXSBhcyBGb2xkZXJJY29uT2JqZWN0O1xyXG4gICAgICB0aGlzLmRhdGFbcGF0aF0gPSB7XHJcbiAgICAgICAgLi4uY3VycmVudFZhbHVlLFxyXG4gICAgICAgIGljb25OYW1lOiBudWxsLFxyXG4gICAgICB9O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgZGVsZXRlIHRoaXMuZGF0YVtwYXRoXTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmFkZEljb25zVG9TZWFyY2goKTtcclxuICAgIHRoaXMuc2F2ZUljb25Gb2xkZXJEYXRhKCk7XHJcbiAgfVxyXG5cclxuICBhZGRGb2xkZXJJY29uKHBhdGg6IHN0cmluZywgaWNvbjogSWNvbiB8IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3QgaWNvbk5hbWUgPSB0eXBlb2YgaWNvbiA9PT0gJ29iamVjdCcgPyBpY29uLm5hbWUgOiBpY29uO1xyXG4gICAgdGhpcy5kYXRhW3BhdGhdID0gaWNvbk5hbWU7XHJcbiAgICBpZiAoIXRoaXMuZ2V0U2V0dGluZ3MoKS5yZWNlbnRseVVzZWRJY29ucy5pbmNsdWRlcyhpY29uTmFtZSkpIHtcclxuICAgICAgaWYgKHRoaXMuZ2V0U2V0dGluZ3MoKS5yZWNlbnRseVVzZWRJY29ucy5sZW5ndGggPj0gdGhpcy5nZXRTZXR0aW5ncygpLnJlY2VudGx5VXNlZEljb25zU2l6ZSkge1xyXG4gICAgICAgIHRoaXMuZ2V0U2V0dGluZ3MoKS5yZWNlbnRseVVzZWRJY29ucy5wb3AoKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5nZXRTZXR0aW5ncygpLnJlY2VudGx5VXNlZEljb25zLnVuc2hpZnQoaWNvbk5hbWUpO1xyXG4gICAgICB0aGlzLmNoZWNrUmVjZW50bHlVc2VkSWNvbnMoKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmFkZEljb25zVG9TZWFyY2goKTtcclxuICAgIHRoaXMuc2F2ZUljb25Gb2xkZXJEYXRhKCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgZ2V0U2V0dGluZ3MoKTogSWNvbkZvbGRlclNldHRpbmdzIHtcclxuICAgIHJldHVybiB0aGlzLmRhdGEuc2V0dGluZ3MgYXMgSWNvbkZvbGRlclNldHRpbmdzO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgbG9hZEljb25Gb2xkZXJEYXRhKCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMubG9hZERhdGEoKTtcclxuICAgIGlmIChkYXRhKSB7XHJcbiAgICAgIE9iamVjdC5lbnRyaWVzKERFRkFVTFRfU0VUVElOR1MpLmZvckVhY2goKFtrLCB2XSkgPT4ge1xyXG4gICAgICAgIGlmICghZGF0YS5zZXR0aW5nc1trXSkge1xyXG4gICAgICAgICAgZGF0YS5zZXR0aW5nc1trXSA9IHY7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIHRoaXMuZGF0YSA9IE9iamVjdC5hc3NpZ24oeyBzZXR0aW5nczogeyAuLi5ERUZBVUxUX1NFVFRJTkdTIH0gfSwge30sIGRhdGEpO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgc2F2ZUljb25Gb2xkZXJEYXRhKCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgYXdhaXQgdGhpcy5zYXZlRGF0YSh0aGlzLmRhdGEpO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgY2hlY2tSZWNlbnRseVVzZWRJY29ucygpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGlmICh0aGlzLmdldFNldHRpbmdzKCkucmVjZW50bHlVc2VkSWNvbnMubGVuZ3RoID4gdGhpcy5nZXRTZXR0aW5ncygpLnJlY2VudGx5VXNlZEljb25zU2l6ZSkge1xyXG4gICAgICB0aGlzLmdldFNldHRpbmdzKCkucmVjZW50bHlVc2VkSWNvbnMgPSB0aGlzLmdldFNldHRpbmdzKCkucmVjZW50bHlVc2VkSWNvbnMuc2xpY2UoXHJcbiAgICAgICAgMCxcclxuICAgICAgICB0aGlzLmdldFNldHRpbmdzKCkucmVjZW50bHlVc2VkSWNvbnNTaXplLFxyXG4gICAgICApO1xyXG4gICAgICBhd2FpdCB0aGlzLnNhdmVJY29uRm9sZGVyRGF0YSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZ2V0RGF0YSgpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBJY29uRm9sZGVyU2V0dGluZ3MgfCBGb2xkZXJJY29uT2JqZWN0PiB7XHJcbiAgICByZXR1cm4gdGhpcy5kYXRhO1xyXG4gIH1cclxufVxyXG4iXSwibmFtZXMiOlsiVmFsdWVDb21wb25lbnQiLCJnbG9iYWwiLCJ0d2Vtb2ppIiwiUGx1Z2luU2V0dGluZ1RhYiIsIlNldHRpbmciLCJOb3RpY2UiLCJEcm9wZG93bkNvbXBvbmVudCIsIlNsaWRlckNvbXBvbmVudCIsIkZ1enp5U3VnZ2VzdE1vZGFsIiwiUGx1Z2luIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBdURBO0FBQ08sU0FBUyxTQUFTLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFO0FBQzdELElBQUksU0FBUyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsT0FBTyxLQUFLLFlBQVksQ0FBQyxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxVQUFVLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFO0FBQ2hILElBQUksT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFO0FBQy9ELFFBQVEsU0FBUyxTQUFTLENBQUMsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtBQUNuRyxRQUFRLFNBQVMsUUFBUSxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtBQUN0RyxRQUFRLFNBQVMsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUMsRUFBRTtBQUN0SCxRQUFRLElBQUksQ0FBQyxDQUFDLFNBQVMsR0FBRyxTQUFT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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUSxhQUFhLEVBQUUsYUFBYTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRLFdBQVcsRUFBRSxXQUFXO0FBQ2hDLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTSxPQUFPLEVBQUUsU0FBUyxPQUFPLEdBQUc7QUFDbEMsUUFBUSxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7QUFDN0IsVUFBVSxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUMxRSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNLEtBQUssRUFBRSxL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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment