tech-tips/.obsidian/plugins/obsidian-paste-png-to-jpeg/main.js

359 lines
40 KiB
JavaScript

/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD */
var __create = Object.create;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[Object.keys(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
__markAsModule(target);
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __reExport = (target, module2, desc) => {
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
for (let key of __getOwnPropNames(module2))
if (!__hasOwnProp.call(target, key) && key !== "default")
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
}
return target;
};
var __toModule = (module2) => {
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
};
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// package.json
var require_package = __commonJS({
"package.json"(exports, module2) {
module2.exports = {
name: "obsidian-paste-png-to-jpeg",
version: "1.2.2",
main: "main.js",
scripts: {
dev: "node esbuild.config.mjs",
build: "tsc -noEmit -skipLibCheck && BUILD_ENV=production node esbuild.config.mjs && cp manifest.json build",
version: "node version-bump.mjs && git add manifest.json versions.json",
release: "yarn build && gh release create ${npm_package_version} build/*"
},
keywords: [],
author: "Reorx",
license: "MIT",
devDependencies: {
"@types/node": "^16.11.6",
"@typescript-eslint/eslint-plugin": "^5.2.0",
"@typescript-eslint/parser": "^5.2.0",
"builtin-modules": "^3.2.0",
esbuild: "0.13.12",
obsidian: "^0.13.26",
tslib: "2.3.1",
typescript: "4.4.4"
},
dependencies: {
"cash-dom": "^8.1.1"
}
};
}
});
// src/main.ts
__export(exports, {
default: () => PastePngToJpegPlugin
});
var import_obsidian = __toModule(require("obsidian"));
// src/utils.ts
var import_path = __toModule(require("path"));
var DEBUG = !(undefined === "production");
function debugLog(...args) {
if (DEBUG) {
console.log(new Date().toISOString().slice(11, 23), ...args);
}
}
var path = {
join(...partSegments) {
let parts = [];
for (let i = 0, l = partSegments.length; i < l; i++) {
parts = parts.concat(partSegments[i].split("/"));
}
const newParts = [];
for (let i = 0, l = parts.length; i < l; i++) {
const part = parts[i];
if (!part || part === ".")
continue;
else
newParts.push(part);
}
if (parts[0] === "")
newParts.unshift("");
return newParts.join("/");
},
basename(fullpath) {
const sp = fullpath.split("/");
return sp[sp.length - 1];
},
filename(fullpath) {
let filename = (0, import_path.basename)(fullpath);
return filename.substring(0, filename.indexOf("."));
},
extension(fullpath) {
const positions = [...fullpath.matchAll(new RegExp("\\.", "gi"))].map((a) => a.index);
return fullpath.slice(positions[positions.length - 1] + 1);
}
};
function ConvertImage(file, quality) {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.onloadend = function(e) {
let image = new Image();
image.onload = function() {
let canvas = document.createElement("canvas");
let context = canvas.getContext("2d");
let imageWidth = image.width;
let imageHeight = image.height;
let data = "";
canvas.width = imageWidth;
canvas.height = imageHeight;
context.fillStyle = "#fff";
context.fillRect(0, 0, imageWidth, imageHeight);
context.save();
context.translate(imageWidth / 2, imageHeight / 2);
context.drawImage(image, 0, 0, imageWidth, imageHeight, -imageWidth / 2, -imageHeight / 2, imageWidth, imageHeight);
context.restore();
data = canvas.toDataURL("image/jpeg", quality);
var arrayBuffer = base64ToArrayBuffer(data);
resolve(arrayBuffer);
};
image.src = e.target.result.toString();
};
reader.readAsDataURL(file);
});
}
function base64ToArrayBuffer(code) {
const parts = code.split(";base64,");
const contentType = parts[0].split(":")[1];
const fileExt = contentType.split("/")[1];
const raw = window.atob(parts[1]);
const rawLength = raw.length;
const uInt8Array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return uInt8Array.buffer;
}
// src/main.ts
var DEFAULT_SETTINGS = {
imageNamePattern: "{{fileName}}",
dupNumberAtStart: false,
dupNumberDelimiter: "-",
autoRename: true,
autoMove: true,
pngToJpeg: true,
quality: "0.6",
dirpath: "image/"
};
var PastePngToJpegPlugin = class extends import_obsidian.Plugin {
onload() {
return __async(this, null, function* () {
const pkg = require_package();
console.log(`Plugin loading: ${pkg.name} ${pkg.version}`);
yield this.loadSettings();
this.registerEvent(this.app.vault.on("create", (file) => {
if (!(file instanceof import_obsidian.TFile))
return;
const timeGapMs = Date.now() - file.stat.ctime;
if (timeGapMs > 1e3)
return;
if (isImage(file)) {
debugLog("pasted image created", file);
this.renameFile(file);
}
}));
this.addSettingTab(new SettingTab(this.app, this));
});
}
renameFile(file) {
return __async(this, null, function* () {
const activeFile = this.getActiveFile();
if (!activeFile) {
new import_obsidian.Notice("Error: No active file found.");
return;
}
let newName = yield this.keepOrgName(file, activeFile);
if (this.settings.autoRename) {
newName = yield this.generateNewName(file, activeFile);
}
const sourcePath = activeFile.path;
let newPath = "";
if (this.settings.autoMove) {
const imagePath = this.app.vault.getConfig("attachmentFolderPath") + "/" + this.settings.dirpath;
const isCreate = yield this.app.vault.adapter.exists(imagePath);
if (!isCreate) {
yield this.app.vault.createFolder(imagePath);
}
newPath = imagePath;
} else {
newPath = file.parent.path + +"/" + this.settings.dirpath;
}
const originName = file.name;
if (this.settings.pngToJpeg) {
let binary = yield this.app.vault.readBinary(file);
let imgBlob = new Blob([binary]);
let arrayBuffer = yield ConvertImage(imgBlob, Number(this.settings.quality));
yield this.app.vault.modifyBinary(file, arrayBuffer);
}
const linkText = this.makeLinkText(file, sourcePath);
newPath = path.join(newPath, newName);
try {
yield this.app.vault.rename(file, newPath);
} catch (err) {
new import_obsidian.Notice(`Failed to rename ${newName}: ${err}`);
throw err;
}
const newLinkText = this.makeLinkText(file, sourcePath);
debugLog("replace text", linkText, newLinkText);
const editor = this.getActiveEditor(sourcePath);
if (!editor) {
new import_obsidian.Notice(`Failed to rename ${newName}: no active editor`);
return;
}
const cursor = editor.getCursor();
const line = editor.getLine(cursor.line);
debugLog("current line", line);
editor.transaction({
changes: [
{
from: __spreadProps(__spreadValues({}, cursor), { ch: 0 }),
to: __spreadProps(__spreadValues({}, cursor), { ch: line.length }),
text: line.replace(linkText, newLinkText)
}
]
});
new import_obsidian.Notice(`Renamed ${originName} to ${newName}`);
});
}
makeLinkText(file, sourcePath, subpath) {
return this.app.fileManager.generateMarkdownLink(file, sourcePath, subpath);
}
generateNewName(file, activeFile) {
return __async(this, null, function* () {
const newName = activeFile.basename + "-" + Date.now();
const extension = this.settings.pngToJpeg ? "jpeg" : file.extension;
return `${newName}.${extension}`;
});
}
keepOrgName(file, activeFile) {
return __async(this, null, function* () {
const newName = file.basename;
const extension = this.settings.pngToJpeg ? "jpeg" : file.extension;
return `${newName}.${extension}`;
});
}
getActiveFile() {
const view = this.app.workspace.getActiveViewOfType(import_obsidian.MarkdownView);
const file = view == null ? void 0 : view.file;
debugLog("active file", file == null ? void 0 : file.path);
return file;
}
getActiveEditor(sourcePath) {
const view = this.app.workspace.getActiveViewOfType(import_obsidian.MarkdownView);
if (view) {
if (view.file.path == sourcePath) {
return view.editor;
}
}
return null;
}
loadSettings() {
return __async(this, null, function* () {
this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
});
}
saveSettings() {
return __async(this, null, function* () {
yield this.saveData(this.settings);
});
}
};
var IMAGE_EXTS = [
"jpg",
"jpeg",
"png"
];
function isImage(file) {
if (file instanceof import_obsidian.TFile) {
if (IMAGE_EXTS.contains(file.extension.toLowerCase())) {
return true;
}
}
return false;
}
var SettingTab = class extends import_obsidian.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin);
this.plugin = plugin;
}
display() {
const { containerEl } = this;
containerEl.empty();
new import_obsidian.Setting(containerEl).setName("Png to Jpeg").setDesc(`Paste images from ClipBoard to notes by copying them through various screenshot software,turn on this feature will automatically convert png to jpeg, and more quality compression volume.`).addToggle((toggle) => toggle.setValue(this.plugin.settings.pngToJpeg).onChange((value) => __async(this, null, function* () {
this.plugin.settings.pngToJpeg = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Quality").setDesc(`The smaller the Quality, the greater the compression ratio.`).addDropdown((toggle) => toggle.addOptions({ "0.1": "0.1", "0.2": "0.2", "0.3": "0.3", "0.4": "0.4", "0.5": "0.5", "0.6": "0.6", "0.7": "0.7", "0.8": "0.8", "0.9": "0.9", "1.0": "1.0" }).setValue(this.plugin.settings.quality).onChange((value) => __async(this, null, function* () {
this.plugin.settings.quality = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Auto Rename").setDesc(`Automatically names the image with the name of the previous note +'-'+ the current timestamp + '.' + file type, for example, the image in test.md will be named test-1652261724173.jpeg`).addToggle((toggle) => toggle.setValue(this.plugin.settings.autoRename).onChange((value) => __async(this, null, function* () {
this.plugin.settings.autoRename = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Auto Move Image").setDesc(`Automatically move images to the image directory,If you do not set the default directory for attachments, then it will be stored directly under the image/ folder in the same directory as the notes, if there is a default directory, then it will be stored under the image/ folder in the Magician directory`).addToggle((toggle) => toggle.setValue(this.plugin.settings.autoMove).onChange((value) => __async(this, null, function* () {
this.plugin.settings.autoMove = value;
yield this.plugin.saveSettings();
})));
}
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL21haW4udHMiLCAiLi4vc3JjL3V0aWxzLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQge1xyXG4gIEFwcCwgUGx1Z2luLCBQbHVnaW5TZXR0aW5nVGFiLCBTZXR0aW5nLCBURmlsZSwgVEFic3RyYWN0RmlsZSxcclxuXHRNYXJrZG93blZpZXcsIE5vdGljZSwgVmF1bHQsXHJcbn0gZnJvbSAnb2JzaWRpYW4nO1xyXG5cclxuaW1wb3J0IHtcclxuICAgZGVidWdMb2csIHBhdGgsIENvbnZlcnRJbWFnZVxyXG59IGZyb20gJy4vdXRpbHMnO1xyXG5cclxuaW50ZXJmYWNlIFBsdWdpblNldHRpbmdzIHtcclxuXHQvLyB7e2ltYWdlTmFtZUtleX19LXt7REFURTpZWVlZTU1ERH19XHJcblx0aW1hZ2VOYW1lUGF0dGVybjogc3RyaW5nXHJcblx0ZHVwTnVtYmVyQXRTdGFydDogYm9vbGVhblxyXG5cdGR1cE51bWJlckRlbGltaXRlcjogc3RyaW5nXHJcblx0YXV0b1JlbmFtZTogYm9vbGVhblxyXG5cdGF1dG9Nb3ZlOmJvb2xlYW5cclxuXHRwbmdUb0pwZWc6IGJvb2xlYW5cclxuXHRxdWFsaXR5OiBzdHJpbmdcclxuXHRkaXJwYXRoOiBzdHJpbmdcclxufVxyXG5cclxuY29uc3QgREVGQVVMVF9TRVRUSU5HUzogUGx1Z2luU2V0dGluZ3MgPSB7XHJcblx0aW1hZ2VOYW1lUGF0dGVybjogJ3t7ZmlsZU5hbWV9fScsXHJcblx0ZHVwTnVtYmVyQXRTdGFydDogZmFsc2UsXHJcblx0ZHVwTnVtYmVyRGVsaW1pdGVyOiAnLScsXHJcblx0YXV0b1JlbmFtZTogdHJ1ZSxcclxuXHRhdXRvTW92ZTp0cnVlLFxyXG5cdHBuZ1RvSnBlZzp0cnVlLFxyXG5cdHF1YWxpdHk6JzAuNicsXHJcblx0ZGlycGF0aDpcImltYWdlL1wiIFxyXG59XHJcblxyXG5jb25zdCBQQVNURURfSU1BR0VfUFJFRklYID0gJ1Bhc3RlZCBpbWFnZSAnXHJcblxyXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQYXN0ZVBuZ1RvSnBlZ1BsdWdpbiBleHRlbmRzIFBsdWdpbiB7XHJcblx0c2V0dGluZ3M6IFBsdWdpblNldHRpbmdzXHJcblxyXG5cdGFzeW5jIG9ubG9hZCgpIFxyXG5cdHtcclxuXHRcdGNvbnN0IHBrZyA9IHJlcXVpcmUoJy4uL3BhY2thZ2UuanNvbicpXHJcblx0XHRjb25zb2xlLmxvZyhgUGx1Z2luIGxvYWRpbmc6ICR7cGtnLm5hbWV9ICR7cGtnLnZlcnNpb259YClcclxuXHRcdGF3YWl0IHRoaXMubG9hZFNldHRpbmdzKCk7XHJcblxyXG5cdFx0dGhpcy5yZWdpc3RlckV2ZW50KFxyXG5cdFx0XHR0aGlzLmFwcC52YXVsdC5vbignY3JlYXRlJywgKGZpbGUpID0+IFxyXG5cdFx0XHR7XHJcblx0XHRcdFx0aWYgKCEoZmlsZSBpbnN0YW5jZW9mIFRGaWxlKSlcclxuXHRcdFx0XHRcdHJldHVyblxyXG5cclxuXHRcdFx0XHRjb25zdCB0aW1lR2FwTXMgPSBEYXRlLm5vdygpIC0gZmlsZS5zdGF0LmN0aW1lO1xyXG5cclxuXHRcdFx0XHQvLyBpZiB0aGUgcGFzdGVkIGltYWdlIGlzIGNyZWF0ZWQgbW9yZSB0aGFuIDEgc2Vjb25kIGFnbywgaWdub3JlIGl0XHJcblx0XHRcdFx0aWYgKHRpbWVHYXBNcyA+IDEwMDApXHJcblx0XHRcdFx0XHRyZXR1cm5cclxuXHJcblx0XHRcdFx0aWYgKGlzSW1hZ2UoZmlsZSkpIFxyXG5cdFx0XHRcdHtcclxuXHRcdFx0XHRcdGRlYnVnTG9nKCdwYXN0ZWQgaW1hZ2UgY3JlYXRlZCcsIGZpbGUpXHJcblx0XHRcdFx0XHR0aGlzLnJlbmFtZUZpbGUoZmlsZSk7XHJcblx0XHRcdFx0fSBcclxuXHRcdFx0fSlcclxuXHRcdClcclxuXHJcblx0XHQvLyBhZGQgc2V0dGluZ3MgdGFiXHJcblx0XHR0aGlzLmFkZFNldHRpbmdUYWIobmV3IFNldHRpbmdUYWIodGhpcy5hcHAsIHRoaXMpKTtcclxuXHR9XHJcblxyXG5cdGFzeW5jIHJlbmFtZUZpbGUoZmlsZTogVEZpbGUpIFxyXG5cdHtcclxuXHRcdGNvbnN0IGFjdGl2ZUZpbGUgPSB0aGlzLmdldEFjdGl2ZUZpbGUoKVxyXG5cdFx0aWYgKCFhY3RpdmVGaWxlKSBcclxuXHRcdHtcclxuXHRcdFx0bmV3IE5vdGljZSgnRXJyb3I6IE5vIGFjdGl2ZSBmaWxlIGZvdW5kLicpXHJcblx0XHRcdHJldHVyblxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIGRlZHVwbGljYXRlIG5hbWVcclxuXHRcdGxldCBuZXdOYW1lOnN0cmluZyA9IGF3YWl0IHRoaXMua2VlcE9yZ05hbWUoZmlsZSwgYWN0aXZlRmlsZSk7XHJcblx0XHRpZiAodGhpcy5zZXR0aW5ncy5hdXRvUmVuYW1lKSB7XHJcbiAgICAgICAgXHRuZXdOYW1lID0gYXdhaXQgdGhpcy5nZW5lcmF0ZU5ld05hbWUoZmlsZSwgYWN0aXZlRmlsZSk7XHJcbiAgICAgIFx0fVxyXG5cdFx0Y29uc3Qgc291cmNlUGF0aDpzdHJpbmcgPSBhY3RpdmVGaWxlLnBhdGg7XHJcblxyXG5cdFx0bGV0IG5ld1BhdGggPSBcIlwiO1xyXG5cdFx0aWYoIHRoaXMuc2V0dGluZ3MuYXV0b01vdmUgKVxyXG5cdFx0e1xyXG5cdFx0XHRjb25zdCBpbWFnZVBhdGggPSB0aGlzLmFwcC52YXVsdC5nZXRDb25maWcoXCJhdHRhY2htZW50Rm9sZGVyUGF0aFwiKSArIFwiL1wiICsgdGhpcy5zZXR0aW5ncy5kaXJwYXRoO1xyXG5cdFx0XHRjb25zdCBpc0NyZWF0ZSA9IGF3YWl0IHRoaXMuYXBwLnZhdWx0LmFkYXB0ZXIuZXhpc3RzKGltYWdlUGF0aCk7XHJcblx0XHRcdGlmKCAhaXNDcmVhdGUgKVxyXG5cdFx0XHR7XHJcblx0XHRcdFx0YXdhaXQgdGhpcy5hcHAudmF1bHQuY3JlYXRlRm9sZGVyKGltYWdlUGF0aCk7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdG5ld1BhdGggPSBpbWFnZVBhdGg7XHJcblx0XHR9XHJcblx0XHRlbHNlXHJcblx0XHR7XHJcblx0XHRcdG5ld1BhdGggPSBmaWxlLnBhcmVudC5wYXRoICsgKyBcIi9cIiArIHRoaXMuc2V0dGluZ3MuZGlycGF0aDtcclxuXHRcdH1cclxuXHRcdFxyXG5cdFx0Y29uc3Qgb3JpZ2luTmFtZSA9IGZpbGUubmFtZTtcclxuXHRcdGlmKCB0aGlzLnNldHRpbmdzLnBuZ1RvSnBlZylcclxuXHRcdHtcclxuXHRcdFx0bGV0IGJpbmFyeTpBcnJheUJ1ZmZlciA9IGF3YWl0IHRoaXMuYXBwLnZhdWx0LnJlYWRCaW5hcnkoZmlsZSk7XHJcblx0XHRcdGxldCBpbWdCbG9iOkJsb2IgPSBuZXcgQmxvYiggW2JpbmFyeV0gKTtcclxuXHRcdFx0bGV0IGFycmF5QnVmZmVyOkFycmF5QnVmZmVyID0gYXdhaXQgQ29udmVydEltYWdlKGltZ0Jsb2IsIE51bWJlciggdGhpcy5zZXR0aW5ncy5xdWFsaXR5ICkgKTtcclxuXHRcdFx0YXdhaXQgdGhpcy5hcHAudmF1bHQubW9kaWZ5QmluYXJ5KGZpbGUsYXJyYXlCdWZmZXIpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIGdldCBvcmlnaW4gZmlsZSBsaW5rIGJlZm9yZSByZW5hbWluZ1xyXG5cdFx0Y29uc3QgbGlua1RleHQgPSB0aGlzLm1ha2VMaW5rVGV4dChmaWxlLCBzb3VyY2VQYXRoKTtcclxuXHJcblx0XHQvLyBmaWxlIHN5c3RlbSBvcGVyYXRpb25cclxuXHRcdG5ld1BhdGggPXBhdGguam9pbihuZXdQYXRoLCBuZXdOYW1lKVxyXG5cdFx0dHJ5IFxyXG5cdFx0e1xyXG5cdFx0XHRhd2FpdCB0aGlzLmFwcC52YXVsdC5yZW5hbWUoZmlsZSwgbmV3UGF0aCk7XHJcblx0XHR9IFxyXG5cdFx0Y2F0Y2ggKGVycikgXHJcblx0XHR7XHJcblx0XHRcdG5ldyBOb3RpY2UoYEZhaWxlZCB0byByZW5hbWUgJHtuZXdOYW1lfTogJHtlcnJ9YClcclxuXHRcdFx0dGhyb3cgZXJyXHJcblx0XHR9XHJcblxyXG5cdFx0Y29uc3QgbmV3TGlua1RleHQgPSB0aGlzLm1ha2VMaW5rVGV4dChmaWxlLCBzb3VyY2VQYXRoKTtcclxuXHRcdGRlYnVnTG9nKCdyZXBsYWNlIHRleHQnLCBsaW5rVGV4dCwgbmV3TGlua1RleHQpXHJcblxyXG5cdFx0Ly8gaW4gY2FzZSBmaWxlTWFuYWdlci5yZW5hbWVGaWxlIG1heSBub3QgdXBkYXRlIHRoZSBpbnRlcm5hbCBsaW5rIGluIHRoZSBhY3RpdmUgZmlsZSxcclxuXHRcdC8vIHdlIG1hbnVhbGx5IHJlcGxhY2UgYnkgbWFuaXB1bGF0aW5nIHRoZSBlZGl0b3JcclxuXHRcdGNvbnN0IGVkaXRvciA9IHRoaXMuZ2V0QWN0aXZlRWRpdG9yKCBzb3VyY2VQYXRoICk7XHJcblx0XHRpZiAoIWVkaXRvcikgXHJcblx0XHR7XHJcblx0XHRcdG5ldyBOb3RpY2UoYEZhaWxlZCB0byByZW5hbWUgJHtuZXdOYW1lfTogbm8gYWN0aXZlIGVkaXRvcmApXHJcblx0XHRcdHJldHVyblxyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IGN1cnNvciA9IGVkaXRvci5nZXRDdXJzb3IoKVxyXG5cdFx0Y29uc3QgbGluZSA9IGVkaXRvci5nZXRMaW5lKGN1cnNvci5saW5lKVxyXG5cdFx0ZGVidWdMb2coJ2N1cnJlbnQgbGluZScsIGxpbmUpXHJcblx0XHQvLyBjb25zb2xlLmxvZygnZWRpdG9yIGNvbnRleHQnLCBjdXJzb3IsIClcclxuXHRcdGVkaXRvci50cmFuc2FjdGlvbih7XHJcblx0XHRcdGNoYW5nZXM6IFtcclxuXHRcdFx0XHR7XHJcblx0XHRcdFx0XHRmcm9tOiB7Li4uY3Vyc29yLCBjaDogMH0sXHJcblx0XHRcdFx0XHR0bzogey4uLmN1cnNvciwgY2g6IGxpbmUubGVuZ3RofSxcclxuXHRcdFx0XHRcdHRleHQ6IGxpbmUucmVwbGFjZShsaW5rVGV4dCwgbmV3TGlua1RleHQpLFxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XVxyXG5cdFx0fSlcclxuXHJcblx0XHRuZXcgTm90aWNlKGBSZW5hbWVkICR7b3JpZ2luTmFtZX0gdG8gJHtuZXdOYW1lfWApXHJcblx0fVxyXG5cclxuXHRtYWtlTGlua1RleHQoIGZpbGU6IFRGaWxlLCBzb3VyY2VQYXRoOiBzdHJpbmcsIHN1YnBhdGg/OnN0cmluZyk6IHN0cmluZyBcclxuXHR7XHJcblx0XHRyZXR1cm4gdGhpcy5hcHAuZmlsZU1hbmFnZXIuZ2VuZXJhdGVNYXJrZG93bkxpbmsoZmlsZSwgc291cmNlUGF0aCxzdWJwYXRoKVxyXG5cdH1cclxuXHJcblx0Ly8gcmV0dXJucyBhIG5ldyBuYW1lIGZvciB0aGUgaW5wdXQgZmlsZSwgd2l0aCBleHRlbnNpb25cclxuXHRhc3luYyBnZW5lcmF0ZU5ld05hbWUoZmlsZTogVEZpbGUsIGFjdGl2ZUZpbGU6IFRGaWxlKTpQcm9taXNlPHN0cmluZz5cclxuXHR7XHJcblx0XHRjb25zdCBuZXdOYW1lID0gYWN0aXZlRmlsZS5iYXNlbmFtZSArICctJyArIERhdGUubm93KCk7XHJcblx0XHRjb25zdCBleHRlbnNpb24gPSB0aGlzLnNldHRpbmdzLnBuZ1RvSnBlZyA/ICdqcGVnJyA6IGZpbGUuZXh0ZW5zaW9uO1xyXG5cdFx0XHJcblx0XHRyZXR1cm4gYCR7bmV3TmFtZX0uJHtleHRlbnNpb259YDtcclxuXHR9XHJcblx0XHJcblx0Ly8gY2hhbmdlcyBvbmx5IHRoZSBleHRlbnNpb25cclxuXHRhc3luYyBrZWVwT3JnTmFtZShmaWxlOiBURmlsZSwgYWN0aXZlRmlsZTogVEZpbGUpOlByb21pc2U8c3RyaW5nPlxyXG5cdHtcclxuXHRcdGNvbnN0IG5ld05hbWUgPSBmaWxlLmJhc2VuYW1lO1xyXG5cdFx0Y29uc3QgZXh0ZW5zaW9uID0gdGhpcy5zZXR0aW5ncy5wbmdUb0pwZWcgPyAnanBlZycgOiBmaWxlLmV4dGVuc2lvbjtcclxuXHRcdFxyXG5cdFx0cmV0dXJuIGAke25ld05hbWV9LiR7ZXh0ZW5zaW9ufWA7XHJcblx0fVxyXG5cclxuXHRnZXRBY3RpdmVGaWxlKCkgXHJcblx0e1xyXG5cdFx0Y29uc3QgdmlldyA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldylcclxuXHRcdGNvbnN0IGZpbGUgPSB2aWV3Py5maWxlXHJcblx0XHRkZWJ1Z0xvZygnYWN0aXZlIGZpbGUnLCBmaWxlPy5wYXRoKVxyXG5cdFx0cmV0dXJuIGZpbGVcclxuXHR9XHJcblxyXG5cdGdldEFjdGl2ZUVkaXRvcihzb3VyY2VQYXRoOnN0cmluZykgXHJcblx0e1xyXG5cdFx0Y29uc3QgdmlldyA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldylcclxuXHRcdGlmKCB2aWV3IClcclxuXHRcdHtcclxuXHRcdFx0aWYoIHZpZXcuZmlsZS5wYXRoID09IHNvdXJjZVBhdGggKVxyXG5cdFx0XHR7XHJcblx0XHRcdFx0cmV0dXJuIHZpZXcuZWRpdG9yXHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdHJldHVybiBudWxsXHJcblx0fVxyXG5cclxuXHRhc3luYyBsb2FkU2V0dGluZ3MoKSB7XHJcblx0XHR0aGlzLnNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgREVGQVVMVF9TRVRUSU5HUywgYXdhaXQgdGhpcy5sb2FkRGF0YSgpKTtcclxuXHR9XHJcblxyXG5cdGFzeW5jIHNhdmVTZXR0aW5ncygpIHtcclxuXHRcdGF3YWl0IHRoaXMuc2F2ZURhdGEodGhpcy5zZXR0aW5ncyk7XHJcblx0fVxyXG59XHJcblxyXG5mdW5jdGlvbiBpc1Bhc3RlZEltYWdlKGZpbGU6IFRBYnN0cmFjdEZpbGUpOiBib29sZWFuIHtcclxuXHRpZiAoZmlsZSBpbnN0YW5jZW9mIFRGaWxlKSB7XHJcblx0XHRpZiAoZmlsZS5uYW1lLnN0YXJ0c1dpdGgoUEFTVEVEX0lNQUdFX1BSRUZJWCkpIHtcclxuXHRcdFx0cmV0dXJuIHRydWVcclxuXHRcdH1cclxuXHR9XHJcblx0cmV0dXJuIGZhbHNlXHJcbn1cclxuXHJcbmNvbnN0IElNQUdFX0VYVFMgPSBbXHJcblx0J2pwZycsICdqcGVnJywgJ3BuZydcclxuXVxyXG5cclxuZnVuY3Rpb24gaXNJbWFnZShmaWxlOiBUQWJzdHJhY3RGaWxlKTogYm9vbGVhbiB7XHJcblx0aWYgKGZpbGUgaW5zdGFuY2VvZiBURmlsZSkge1xyXG5cdFx0aWYgKElNQUdFX0VYVFMuY29udGFpbnMoZmlsZS5leHRlbnNpb24udG9Mb3dlckNhc2UoKSkpIHtcclxuXHRcdFx0cmV0dXJuIHRydWVcclxuXHRcdH1cclxuXHR9XHJcblx0cmV0dXJuIGZhbHNlXHJcbn1cclxuXHJcbmNsYXNzIFNldHRpbmdUYWIgZXh0ZW5kcyBQbHVnaW5TZXR0aW5nVGFiIHtcclxuXHRwbHVnaW46IFBhc3RlUG5nVG9KcGVnUGx1Z2luO1xyXG5cclxuXHRjb25zdHJ1Y3RvcihhcHA6IEFwcCwgcGx1Z2luOiBQYXN0ZVBuZ1RvSnBlZ1BsdWdpbikge1xyXG5cdFx0c3VwZXIoYXBwLCBwbHVnaW4pO1xyXG5cdFx0dGhpcy5wbHVnaW4gPSBwbHVnaW47XHJcblx0fVxyXG5cclxuXHRkaXNwbGF5KCk6IHZvaWQge1xyXG5cdFx0Y29uc3QgeyBjb250YWluZXJFbCB9ID0gdGhpcztcclxuXHRcdGNvbnRhaW5lckVsLmVtcHR5KCk7XHJcblxyXG5cdFx0bmV3IFNldHRpbmcoY29udGFpbmVyRWwpXHJcblx0XHRcdC5zZXROYW1lKCdQbmcgdG8gSnBlZycpXHJcblx0XHRcdC5zZXREZXNjKGBQYXN0ZSBpbWFnZXMgZnJvbSBDbGlwQm9hcmQgdG8gbm90ZXMgYnkgY29weWluZyB0aGVtIHRocm91Z2ggdmFyaW91cyBzY3JlZW5zaG90IHNvZnR3YXJlLHR1cm4gb24gdGhpcyBmZWF0dXJlIHdpbGwgYXV0b21hdGljYWxseSBjb252ZXJ0IHBuZyB0byBqcGVnLCBhbmQgbW9yZSBxdWFsaXR5IGNvbXByZXNzaW9uIHZvbHVtZS5gKVxyXG5cdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB0b2dnbGVcclxuXHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MucG5nVG9KcGVnKVxyXG5cdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcclxuXHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnBuZ1RvSnBlZyA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHQpKTtcdFxyXG5cdFx0XHRcclxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxyXG5cdFx0XHQuc2V0TmFtZSgnUXVhbGl0eScpXHJcblx0XHRcdC5zZXREZXNjKGBUaGUgc21hbGxlciB0aGUgUXVhbGl0eSwgdGhlIGdyZWF0ZXIgdGhlIGNvbXByZXNzaW9uIHJhdGlvLmApXHJcblx0XHRcdC5hZGREcm9wZG93bih0b2dnbGUgPT4gdG9nZ2xlXHJcblx0XHRcdFx0LmFkZE9wdGlvbnMoeycwLjEnOicwLjEnLCcwLjInOicwLjInLCcwLjMnOicwLjMnLCcwLjQnOicwLjQnLCcwLjUnOicwLjUnLCcwLjYnOicwLjYnLCcwLjcnOicwLjcnLCcwLjgnOicwLjgnLCcwLjknOicwLjknLCcxLjAnOicxLjAnfSlcclxuXHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MucXVhbGl0eSlcclxuXHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XHJcblx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5xdWFsaXR5ID0gdmFsdWU7XHJcblx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdCkpO1x0XHJcblx0XHRcdFxyXG5cdFx0bmV3IFNldHRpbmcoY29udGFpbmVyRWwpXHJcblx0XHRcdC5zZXROYW1lKCdBdXRvIFJlbmFtZScpXHJcblx0XHRcdC5zZXREZXNjKGBBdXRvbWF0aWNhbGx5IG5hbWVzIHRoZSBpbWFnZSB3aXRoIHRoZSBuYW1lIG9mIHRoZSBwcmV2aW91cyBub3RlICsnLScrIHRoZSBjdXJyZW50IHRpbWVzdGFtcCArICcuJyArIGZpbGUgdHlwZSwgZm9yIGV4YW1wbGUsIHRoZSBpbWFnZSBpbiB0ZXN0Lm1kIHdpbGwgYmUgbmFtZWQgdGVzdC0xNjUyMjYxNzI0MTczLmpwZWdgKVxyXG5cdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB0b2dnbGVcclxuXHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuYXV0b1JlbmFtZSlcclxuXHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XHJcblx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5hdXRvUmVuYW1lID0gdmFsdWU7XHJcblx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdCkpO1x0XHJcblx0XHRcdFxyXG5cdFx0bmV3IFNldHRpbmcoY29udGFpbmVyRWwpXHJcblx0XHRcdC5zZXROYW1lKCdBdXRvIE1vdmUgSW1hZ2UnKVxyXG5cdFx0XHQuc2V0RGVzYyhgQXV0b21hdGljYWxseSBtb3ZlIGltYWdlcyB0byB0aGUgaW1hZ2UgZGlyZWN0b3J5LElmIHlvdSBkbyBub3Qgc2V0IHRoZSBkZWZhdWx0IGRpcmVjdG9yeSBmb3IgYXR0YWNobWVudHMsIHRoZW4gaXQgd2lsbCBiZSBzdG9yZWQgZGlyZWN0bHkgdW5kZXIgdGhlIGltYWdlLyBmb2xkZXIgaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFzIHRoZSBub3RlcywgaWYgdGhlcmUgaXMgYSBkZWZhdWx0IGRpcmVjdG9yeSwgdGhlbiBpdCB3aWxsIGJlIHN0b3JlZCB1bmRlciB0aGUgaW1hZ2UvIGZvbGRlciBpbiB0aGUgTWFnaWNpYW4gZGlyZWN0b3J5YClcclxuXHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT4gdG9nZ2xlXHJcblx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmF1dG9Nb3ZlKVxyXG5cdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcclxuXHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmF1dG9Nb3ZlID0gdmFsdWU7XHJcblx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdCkpO1x0XHRcdFx0XHJcblx0fVxyXG59XHJcbiIsICJpbXBvcnQgeyBBcHAsIFZhdWx0IH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5pbXBvcnQgeyBiYXNlbmFtZSB9IGZyb20gJ3BhdGgnO1xyXG5cclxuZXhwb3J0IGNvbnN0IERFQlVHID0gIShwcm9jZXNzLmVudi5CVUlMRF9FTlYgPT09ICdwcm9kdWN0aW9uJylcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBkZWJ1Z0xvZyguLi5hcmdzOiBhbnlbXSkge1xyXG5cdGlmIChERUJVRykge1xyXG5cdFx0Y29uc29sZS5sb2coKG5ldyBEYXRlKCkpLnRvSVNPU3RyaW5nKCkuc2xpY2UoMTEsIDIzKSwgLi4uYXJncylcclxuXHR9XHJcbn1cclxuXHJcbmludGVyZmFjZSBFbGVtZW50VHJlZU9wdGlvbnMgZXh0ZW5kcyBEb21FbGVtZW50SW5mbyB7XHJcblx0dGFnOiBrZXlvZiBIVE1MRWxlbWVudFRhZ05hbWVNYXBcclxuXHRjaGlsZHJlbj86IEVsZW1lbnRUcmVlT3B0aW9uc1tdXHJcbn1cclxuXHJcbmludGVyZmFjZSBFbGVtZW50VHJlZSB7XHJcblx0ZWw6IEhUTUxFbGVtZW50XHJcblx0Y2hpbGRyZW46IEVsZW1lbnRUcmVlW11cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnRUcmVlKHJvb3RFbDogSFRNTEVsZW1lbnQsIG9wdHM6IEVsZW1lbnRUcmVlT3B0aW9ucyk6IEVsZW1lbnRUcmVlIHtcclxuXHRjb25zdCByZXN1bHQ6IEVsZW1lbnRUcmVlID0ge1xyXG5cdFx0ZWw6IHJvb3RFbC5jcmVhdGVFbChvcHRzLnRhZywgb3B0cyBhcyBEb21FbGVtZW50SW5mbyksXHJcblx0XHRjaGlsZHJlbjogW10sXHJcblx0fVxyXG5cdGNvbnN0IGNoaWxkcmVuID0gb3B0cy5jaGlsZHJlbiB8fCBbXVxyXG5cdGZvciAoY29uc3QgY2hpbGQgb2YgY2hpbGRyZW4pIHtcclxuXHRcdHJlc3VsdC5jaGlsZHJlbi5wdXNoKGNyZWF0ZUVsZW1lbnRUcmVlKHJlc3VsdC5lbCwgY2hpbGQpKVxyXG5cdH1cclxuXHRyZXR1cm4gcmVzdWx0XHJcbn1cclxuXHJcbmV4cG9ydCBjb25zdCBwYXRoID0ge1xyXG5cdC8vIENyZWRpdDogQGNyZWF0aW9uaXgvcGF0aC5qc1xyXG5cdGpvaW4oLi4ucGFydFNlZ21lbnRzOiBzdHJpbmdbXSk6IHN0cmluZyB7XHJcblx0XHQvLyBTcGxpdCB0aGUgaW5wdXRzIGludG8gYSBsaXN0IG9mIHBhdGggY29tbWFuZHMuXHJcblx0XHRsZXQgcGFydHM6IHN0cmluZ1tdID0gW11cclxuXHRcdGZvciAobGV0IGkgPSAwLCBsID0gcGFydFNlZ21lbnRzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xyXG5cdFx0XHRwYXJ0cyA9IHBhcnRzLmNvbmNhdChwYXJ0U2VnbWVudHNbaV0uc3BsaXQoJy8nKSlcclxuXHRcdH1cclxuXHRcdC8vIEludGVycHJldCB0aGUgcGF0aCBjb21tYW5kcyB0byBnZXQgdGhlIG5ldyByZXNvbHZlZCBwYXRoLlxyXG5cdFx0Y29uc3QgbmV3UGFydHMgPSBbXVxyXG5cdFx0Zm9yIChsZXQgaSA9IDAsIGwgPSBwYXJ0cy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcclxuXHRcdFx0Y29uc3QgcGFydCA9IHBhcnRzW2ldXHJcblx0XHRcdC8vIFJlbW92ZSBsZWFkaW5nIGFuZCB0cmFpbGluZyBzbGFzaGVzXHJcblx0XHRcdC8vIEFsc28gcmVtb3ZlIFwiLlwiIHNlZ21lbnRzXHJcblx0XHRcdGlmICghcGFydCB8fCBwYXJ0ID09PSAnLicpIGNvbnRpbnVlXHJcblx0XHRcdC8vIFB1c2ggbmV3IHBhdGggc2VnbWVudHMuXHJcblx0XHRcdGVsc2UgbmV3UGFydHMucHVzaChwYXJ0KVxyXG5cdFx0fVxyXG5cdFx0Ly8gUHJlc2VydmUgdGhlIGluaXRpYWwgc2xhc2ggaWYgdGhlcmUgd2FzIG9uZS5cclxuXHRcdGlmIChwYXJ0c1swXSA9PT0gJycpIG5ld1BhcnRzLnVuc2hpZnQoJycpXHJcblx0XHQvLyBUdXJuIGJhY2sgaW50byBhIHNpbmdsZSBzdHJpbmcgcGF0aC5cclxuXHRcdHJldHVybiBuZXdQYXJ0cy5qb2luKCcvJylcclxuXHR9LFxyXG5cclxuXHQvLyByZXR1cm5zIHRoZSBsYXN0IHBhcnQgb2YgYSBwYXRoLCBlLmcuICdmb28uanBnJ1xyXG5cdGJhc2VuYW1lKGZ1bGxwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xyXG5cdFx0Y29uc3Qgc3AgPSBmdWxscGF0aC5zcGxpdCgnLycpXHJcblx0XHRyZXR1cm4gc3Bbc3AubGVuZ3RoIC0gMV1cclxuXHR9LFxyXG5cclxuXHRmaWxlbmFtZShmdWxscGF0aDpzdHJpbmcpOnN0cmluZ1xyXG5cdHtcclxuXHRcdGxldCBmaWxlbmFtZSA9IGJhc2VuYW1lKGZ1bGxwYXRoKTtcclxuXHJcblx0XHRyZXR1cm4gZmlsZW5hbWUuc3Vic3RyaW5nKDAsZmlsZW5hbWUuaW5kZXhPZignLicpIClcclxuXHR9LFxyXG5cclxuXHQvLyByZXR1cm4gZXh0ZW5zaW9uIHdpdGhvdXQgZG90LCBlLmcuICdqcGcnXHJcblx0ZXh0ZW5zaW9uKGZ1bGxwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xyXG5cdFx0Y29uc3QgcG9zaXRpb25zID0gWy4uLmZ1bGxwYXRoLm1hdGNoQWxsKG5ldyBSZWdFeHAoJ1xcXFwuJywgJ2dpJykpXS5tYXAoYSA9PiBhLmluZGV4KVxyXG5cdFx0cmV0dXJuIGZ1bGxwYXRoLnNsaWNlKHBvc2l0aW9uc1twb3NpdGlvbnMubGVuZ3RoIC0gMV0gKyAxKVxyXG5cdH0sXHJcbn1cclxuXHJcbmNvbnN0IGZpbGVuYW1lTm90QWxsb3dlZENoYXJzID0gL1teYS16QS1aMC05fmAhQCQmKigpXFwtXz0re307J1wiLDwuPj8gXS9nXHJcblxyXG5leHBvcnQgY29uc3Qgc2FuaXRpemVyID0ge1xyXG5cdGZpbGVuYW1lKHM6IHN0cmluZyk6IHN0cmluZyB7XHJcblx0XHRyZXR1cm4gcy5yZXBsYWNlKGZpbGVuYW1lTm90QWxsb3dlZENoYXJzLCAnJykudHJpbSgpXHJcblx0fSxcclxuXHJcblx0ZGVsaW1pdGVyKHM6IHN0cmluZyk6IHN0cmluZyB7XHJcblx0XHRzID0gdGhpcy5maWxlbmFtZShzKVxyXG5cdFx0Ly8gdXNlIGRlZmF1bHQgJy0nIGlmIG5vIHZhbGlkIGNoYXJzIGZvdW5kXHJcblx0XHRpZiAoIXMpIHMgPSAnLSdcclxuXHRcdHJldHVybiBzXHJcblx0fVxyXG59XHJcblxyXG4vLyByZWY6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS82OTY5NDg2LzU5NjIwNlxyXG5leHBvcnQgZnVuY3Rpb24gZXNjYXBlUmVnRXhwKHM6IHN0cmluZykge1xyXG4gICAgcmV0dXJuIHMucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xcXVxcXFxdL2csICdcXFxcJCYnKTtcclxufVxyXG5cclxuXHJcbmludGVyZmFjZSBDb21wb3NpdGlvblN0YXRlIHtcclxuXHRsb2NrOiBib29sZWFuXHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBsb2NrSW5wdXRNZXRob2RDb21wb3NpdGlvbihlbDogSFRNTElucHV0RWxlbWVudCk6IENvbXBvc2l0aW9uU3RhdGUge1xyXG5cdGNvbnN0IHN0YXRlOiBDb21wb3NpdGlvblN0YXRlID0ge1xyXG5cdFx0bG9jazogZmFsc2UsXHJcblx0fVxyXG5cdGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NvbXBvc2l0aW9uc3RhcnQnLCAoKSA9PiB7XHJcblx0XHRzdGF0ZS5sb2NrID0gdHJ1ZVxyXG5cdH0pXHJcblx0ZWwuYWRkRXZlbnRMaXN0ZW5lcignY29tcG9zaXRpb25lbmQnLCAoKSA9PiB7XHJcblx0XHRzdGF0ZS5sb2NrID0gZmFsc2VcclxuXHR9KVxyXG5cdHJldHVybiBzdGF0ZVxyXG59XHJcblxyXG5cclxuaW50ZXJmYWNlIFZhdWx0Q29uZmlnIHtcclxuXHR1c2VNYXJrZG93bkxpbmtzPzogYm9vbGVhblxyXG59XHJcblxyXG5pbnRlcmZhY2UgVmF1bHRXaXRoQ29uZmlnIGV4dGVuZHMgVmF1bHQge1xyXG5cdGNvbmZpZz86IFZhdWx0Q29uZmlnLFxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gZ2V0VmF1bHRDb25maWcoYXBwOiBBcHApOiBWYXVsdENvbmZpZ3xudWxsIHtcclxuXHRjb25zdCB2YXVsdCA9IGFwcC52YXVsdCBhcyBWYXVsdFdpdGhDb25maWdcclxuXHRyZXR1cm4gdmF1bHQuY29uZmlnXHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBDb252ZXJ0SW1hZ2UoZmlsZTpCbG9iLCBxdWFsaXR5Om51bWJlcik6UHJvbWlzZTxBcnJheUJ1ZmZlcj4ge1xyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IFxyXG5cdHtcclxuICAgICAgICBsZXQgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTsgLy9cdThCRkJcdTUzRDZmaWxlXHJcbiAgICAgICAgcmVhZGVyLm9ubG9hZGVuZCA9IGZ1bmN0aW9uIChlKSBcclxuXHRcdHtcclxuICAgICAgICAgICAgbGV0IGltYWdlID0gbmV3IEltYWdlKCkgLy9cdTY1QjBcdTVFRkFcdTRFMDBcdTRFMkFpbWdcdTY4MDdcdTdCN0VcdUZGMDhcdThGRDhcdTZDQTFcdTVENENcdTUxNjVET01cdTgyODJcdTcwQjkpXHJcbiAgICAgICAgICAgIGltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIFxyXG5cdFx0XHR7XHJcbiAgICAgICAgICAgICAgICBsZXQgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XHJcbiAgICAgICAgICAgICAgICBsZXQgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xyXG4gICAgICAgICAgICAgICAgbGV0IGltYWdlV2lkdGggPSBpbWFnZS53aWR0aDtcclxuICAgICAgICAgICAgICAgIGxldCBpbWFnZUhlaWdodCA9IGltYWdlLmhlaWdodDtcclxuICAgICAgICAgICAgICAgIGxldCBkYXRhID0gJyc7XHJcblxyXG4gICAgICAgICAgICAgICAgY2FudmFzLndpZHRoID0gaW1hZ2VXaWR0aDtcclxuICAgICAgICAgICAgICAgIGNhbnZhcy5oZWlnaHQgPSBpbWFnZUhlaWdodDtcclxuXHJcblx0XHRcdFx0Y29udGV4dC5maWxsU3R5bGUgPSAnI2ZmZic7XHJcblx0XHRcdFx0Y29udGV4dC5maWxsUmVjdCgwLCAwLCBpbWFnZVdpZHRoLCBpbWFnZUhlaWdodCk7XHJcblx0XHRcdFx0Y29udGV4dC5zYXZlKCk7XHJcblxyXG5cdFx0XHRcdGNvbnRleHQudHJhbnNsYXRlKGltYWdlV2lkdGggLyAyLCBpbWFnZUhlaWdodCAvIDIpO1xyXG4gICAgICAgICAgICAgICAgY29udGV4dC5kcmF3SW1hZ2UoaW1hZ2UsIDAsIDAsIGltYWdlV2lkdGgsIGltYWdlSGVpZ2h0LC1pbWFnZVdpZHRoLzIsLWltYWdlSGVpZ2h0LzIsaW1hZ2VXaWR0aCxpbWFnZUhlaWdodCk7XHJcblx0XHRcdFx0Y29udGV4dC5yZXN0b3JlKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgZGF0YSA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL2pwZWcnLHF1YWxpdHkpO1xyXG5cclxuICAgICAgICAgICAgICAgIHZhciBhcnJheUJ1ZmZlciA9IGJhc2U2NFRvQXJyYXlCdWZmZXIoZGF0YSk7XHJcbiAgICAgICAgICAgICAgICByZXNvbHZlKGFycmF5QnVmZmVyKVxyXG4gICAgICAgICAgICB9XHJcblxyXG5cdFx0XHRpbWFnZS5zcmMgPSBlLnRhcmdldC5yZXN1bHQudG9TdHJpbmcoKSAvL1x1NUMwNlx1NTZGRVx1NzI0N1x1NzY4NFx1OERFRlx1NUY4NFx1OEJCRVx1NjIxMGZpbGVcdThERUZcdTVGODRcclxuICAgICAgICB9XHJcblxyXG5cdFx0cmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZSk7XHJcbiAgICB9KVxyXG59XHJcblxyXG5mdW5jdGlvbiBiYXNlNjRUb0FycmF5QnVmZmVyIChjb2RlOnN0cmluZyk6QXJyYXlCdWZmZXJcclxue1xyXG4gICAgY29uc3QgcGFydHMgPSBjb2RlLnNwbGl0KFwiO2Jhc2U2NCxcIik7XHJcbiAgICBjb25zdCBjb250ZW50VHlwZSA9IHBhcnRzWzBdLnNwbGl0KFwiOlwiKVsxXTtcclxuICAgIGNvbnN0IGZpbGVFeHQgPSBjb250ZW50VHlwZS5zcGxpdChcIi9cIilbMV07XHJcbiAgICBjb25zdCByYXcgPSB3aW5kb3cuYXRvYihwYXJ0c1sxXSk7XHJcbiAgICBjb25zdCByYXdMZW5ndGggPSByYXcubGVuZ3RoO1xyXG5cclxuICAgIGNvbnN0IHVJbnQ4QXJyYXkgPSBuZXcgVWludDhBcnJheShyYXdMZW5ndGgpO1xyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmF3TGVuZ3RoOyArK2kpIFxyXG5cdHtcclxuICAgICAgICB1SW50OEFycmF5W2ldID0gcmF3LmNoYXJDb2RlQXQoaSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdUludDhBcnJheS5idWZmZXI7XHJcbn07Il0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUEsc0JBR087OztBQ0ZQLGtCQUF5QjtBQUVsQixJQUFNLFFBQVEsQ0FBRSxlQUEwQjtBQUUxQyxxQkFBcUIsTUFBYTtBQUN4QyxNQUFJLE9BQU87QUFDVixZQUFRLElBQUssSUFBSSxPQUFRLGNBQWMsTUFBTSxJQUFJLEtBQUssR0FBRztBQUFBO0FBQUE7QUEwQnBELElBQU0sT0FBTztBQUFBLEVBRW5CLFFBQVEsY0FBZ0M7QUFFdkMsUUFBSSxRQUFrQjtBQUN0QixhQUFTLElBQUksR0FBRyxJQUFJLGFBQWEsUUFBUSxJQUFJLEdBQUcsS0FBSztBQUNwRCxjQUFRLE1BQU0sT0FBTyxhQUFhLEdBQUcsTUFBTTtBQUFBO0FBRzVDLFVBQU0s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