/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD if you want to view the source, please visit the github repository of this plugin */ var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/main.ts var main_exports = {}; __export(main_exports, { default: () => FileNameHistoryPlugin }); module.exports = __toCommonJS(main_exports); var import_obsidian3 = require("obsidian"); // src/settings.ts var DEFAULT_SETTINGS = { historyPropertyName: "aliases", ignoreRegexes: ["^_", "^Untitled$", "^Untitled \\d+$"], timeoutSeconds: 5, caseSensitive: false, autoCreateFrontmatter: true, includeFolders: [], excludeFolders: [], fileExtensions: ["md"], trackFolderRenames: "", excludePropertyName: "" }; // src/ui/settings-tab.ts var import_obsidian = require("obsidian"); var FileNameHistorySettingTab = class extends import_obsidian.PluginSettingTab { constructor(app, plugin) { super(app, plugin); this.icon = "lucide-forward"; this.plugin = plugin; } display() { const { containerEl } = this; containerEl.empty(); const saveSettings = () => { void this.plugin.saveSettings(); }; const generalGroup = new import_obsidian.SettingGroup(containerEl); generalGroup.addSetting((setting) => { setting.setName("History property name").setDesc("The list property to store file name history.").addText( (text) => text.setPlaceholder("aliases").setValue(this.plugin.settings.historyPropertyName).onChange((value) => { this.plugin.settings.historyPropertyName = value || "aliases"; saveSettings(); }) ); }); generalGroup.addSetting((setting) => { setting.setName("Timeout seconds").setDesc("Time in seconds the name must be stable before adding to the configured property.").addSlider( (slider) => slider.setLimits(1, 20, 1).setValue(this.plugin.settings.timeoutSeconds).setDynamicTooltip().onChange((value) => { this.plugin.settings.timeoutSeconds = value; saveSettings(); }) ); }); generalGroup.addSetting((setting) => { setting.setName("Case-sensitive uniqueness").setDesc("If enabled, treat case differences as unique values in the configured property.").addToggle( (toggle) => toggle.setValue(this.plugin.settings.caseSensitive).onChange((value) => { this.plugin.settings.caseSensitive = value; saveSettings(); }) ); }); generalGroup.addSetting((setting) => { setting.setName("Auto-create history property").setDesc("Automatically create the configured property if missing.").addToggle( (toggle) => toggle.setValue(this.plugin.settings.autoCreateFrontmatter).onChange((value) => { this.plugin.settings.autoCreateFrontmatter = value; saveSettings(); }) ); }); generalGroup.addSetting((setting) => { setting.setName("File extensions").setDesc("Comma-separated list of file extensions to track.").addText( (text) => text.setPlaceholder("Md, txt").setValue(this.plugin.settings.fileExtensions.join(",")).onChange((value) => { this.plugin.settings.fileExtensions = value.split(",").map((s) => s.trim()).filter((s) => s); saveSettings(); }) ); }); const filteringGroup = new import_obsidian.SettingGroup(containerEl).setHeading("Filtering"); const foldersGroup = new import_obsidian.SettingGroup(containerEl).setHeading("Folders"); const advancedGroup = new import_obsidian.SettingGroup(containerEl).setHeading("Advanced"); filteringGroup.addSetting((setting) => { setting.setName("Ignore regex patterns").setDesc( "Comma-separated regex patterns for file names or immediate parent folder names to ignore (e.g., ^_ for underscore prefixes, ^untitled$ for untitled). Leave empty to disable." ).addText( (text) => text.setPlaceholder("^_, ^untitled$, ^untitled \\d+$").setValue(this.plugin.settings.ignoreRegexes.join(",")).onChange((value) => { this.plugin.settings.ignoreRegexes = value.split(",").map((s) => s.trim()).filter((s) => s); saveSettings(); }) ); }); filteringGroup.addSetting((setting) => { setting.setName("Exclude property name").setDesc( "Name of a boolean property to check in files. Files with this property set to true will be excluded from tracking. Takes priority over folder filtering." ).addText( (text) => text.setPlaceholder("Skip-rename-tracking").setValue(this.plugin.settings.excludePropertyName).onChange((value) => { this.plugin.settings.excludePropertyName = value; saveSettings(); }) ); }); foldersGroup.addSetting((setting) => { setting.setName("Include folders").setDesc( "Comma-separated list of folder paths to include. If empty, all folders are included. Use {vault} or {root} to include only files directly in the vault root (no subfolders)." ).addText( (text) => text.setValue(this.plugin.settings.includeFolders.join(",")).onChange((value) => { this.plugin.settings.includeFolders = value.split(",").map((s) => s.trim()).filter((s) => s); saveSettings(); }) ); }); foldersGroup.addSetting((setting) => { setting.setName("Exclude folders").setDesc( 'Comma-separated list of folder paths to exclude. Supports wildcards: use "folder/*" to exclude direct children, "folder/**" to exclude all descendants. Use {vault} or {root} to exclude files directly in the vault root.' ).addText( (text) => text.setValue(this.plugin.settings.excludeFolders.join(",")).onChange((value) => { this.plugin.settings.excludeFolders = value.split(",").map((s) => s.trim()).filter((s) => s); saveSettings(); }) ); }); advancedGroup.addSetting((setting) => { setting.setName("Track folder renames for specific file name").setDesc( "If a Markdown file matches this file name, store old immediate parent folder names in the configured property when parent folders are renamed." ).addText( (text) => text.setPlaceholder("Index").setValue(this.plugin.settings.trackFolderRenames).onChange((value) => { this.plugin.settings.trackFolderRenames = value; saveSettings(); }) ); }); } }; // src/utils/history-processor.ts var import_obsidian2 = require("obsidian"); var HistoryProcessor = class { constructor(app, settings) { this.app = app; this.settings = settings; } async processAliasesManually(path, queue) { const file = this.app.vault.getFileByPath(path); if (!file) { return; } const regexes = []; for (const regexStr of this.settings.ignoreRegexes) { try { regexes.push(new RegExp(regexStr)); } catch (e) { console.error(`Invalid ignore regex: ${regexStr}`, e); } } const toAdd = []; const currentBasename = file.basename; const currentBasenameLower = currentBasename.toLowerCase(); for (const name of queue) { if (regexes.some((re) => re.test(name))) { continue; } const nameLower = name.toLowerCase(); if (this.settings.caseSensitive && name === currentBasename || !this.settings.caseSensitive && nameLower === currentBasenameLower) { continue; } toAdd.push(name); } if (toAdd.length === 0) { return; } let content = await this.app.vault.read(file); const frontmatterRegex = /^---\n([\s\S]*?)\n---\n/; const match = content.match(frontmatterRegex); let frontmatter = {}; let frontmatterText = ""; let bodyContent = content; if (match) { frontmatterText = match[1]; bodyContent = content.slice(match[0].length); try { const parsed = (0, import_obsidian2.parseYaml)(frontmatterText); frontmatter = parsed && typeof parsed === "object" ? parsed : {}; } catch (e) { console.error(`Error parsing properties:`, e); frontmatter = {}; } } else { bodyContent = content; } let aliases = frontmatter[this.settings.historyPropertyName]; if (!Array.isArray(aliases)) { const hasFrontmatter = Object.keys(frontmatter).length > 0; if (hasFrontmatter && !this.settings.autoCreateFrontmatter) { return; } aliases = []; } const aliasesArray = aliases; const existing = new Set( this.settings.caseSensitive ? aliasesArray : aliasesArray.map((a) => a.toLowerCase()) ); let added = false; for (const name of toAdd) { const checkName = this.settings.caseSensitive ? name : name.toLowerCase(); if (!existing.has(checkName)) { aliasesArray.push(name); existing.add(checkName); added = true; } } if (!added) { return; } frontmatter[this.settings.historyPropertyName] = aliasesArray; const newFrontmatterText = (0, import_obsidian2.stringifyYaml)(frontmatter).trim(); const newContent = `--- ${newFrontmatterText} --- ${bodyContent}`; await this.app.vault.modify(file, newContent); } async processAliases(path, queue) { const file = this.app.vault.getFileByPath(path); if (!file) return; const regexes = []; for (const regexStr of this.settings.ignoreRegexes) { try { regexes.push(new RegExp(regexStr)); } catch (e) { console.error(`Invalid ignore regex: ${regexStr}`, e); } } const toAdd = []; const currentBasename = file.basename; const currentBasenameLower = currentBasename.toLowerCase(); for (const name of queue) { if (regexes.some((re) => re.test(name))) { continue; } const nameLower = name.toLowerCase(); if (this.settings.caseSensitive && name === currentBasename || !this.settings.caseSensitive && nameLower === currentBasenameLower) { continue; } toAdd.push(name); } if (toAdd.length === 0) { return; } if (file.extension !== "md") { await this.processAliasesManually(path, queue); return; } await this.app.fileManager.processFrontMatter(file, (fm) => { let aliases = fm[this.settings.historyPropertyName]; if (!Array.isArray(aliases)) { const hasFrontmatter = Object.keys(fm).length > 0; if (hasFrontmatter && !this.settings.autoCreateFrontmatter) { return; } aliases = []; fm[this.settings.historyPropertyName] = aliases; } const aliasesArray = aliases; const existing = new Set( this.settings.caseSensitive ? aliasesArray : aliasesArray.map((a) => a.toLowerCase()) ); for (const name of toAdd) { const checkName = this.settings.caseSensitive ? name : name.toLowerCase(); if (!existing.has(checkName)) { aliasesArray.push(name); existing.add(checkName); } } }); } }; // src/utils/path-utils.ts function getBasename(path) { const name = path.split("/").pop() || ""; return name.replace(/\.[^/.]+$/, ""); } function getImmediateParentName(path) { const parts = path.split("/"); parts.pop(); return parts.pop() || ""; } // src/main.ts var FileNameHistoryPlugin = class extends import_obsidian3.Plugin { constructor() { super(...arguments); this.debounceMap = /* @__PURE__ */ new Map(); } async onload() { await this.loadSettings(); this.historyProcessor = new HistoryProcessor(this.app, this.settings); this.addSettingTab(new FileNameHistorySettingTab(this.app, this)); this.registerEvent( this.app.vault.on("rename", (file, oldPath) => { this.handleRename(file, oldPath); }) ); } onunload() { for (const entry of this.debounceMap.values()) { if (entry.timeoutId !== 0) { window.clearTimeout(entry.timeoutId); } } this.debounceMap.clear(); } async loadSettings() { const loadedData = await this.loadData(); this.settings = Object.assign({}, DEFAULT_SETTINGS, loadedData); } async saveSettings() { await this.saveData(this.settings); } isPathInFolder(path, folder) { if (folder.includes("{vault}") || folder.includes("{root}")) { const resolvedFolder = folder.replace(/\{vault\}|\{root\}/g, ""); if (resolvedFolder === "" || resolvedFolder === "/") { const isVaultRoot = !path.includes("/"); return isVaultRoot; } return path.startsWith(resolvedFolder + "/") || path === resolvedFolder; } return path.startsWith(folder + "/") || path === folder; } isPathExcluded(path, excludePattern) { if (excludePattern.includes("{vault}") || excludePattern.includes("{root}")) { const resolvedPattern = excludePattern.replace(/\{vault\}|\{root\}/g, ""); if (resolvedPattern === "" || resolvedPattern === "/") { return !path.includes("/"); } excludePattern = resolvedPattern; } if (excludePattern.endsWith("/**")) { const baseFolder = excludePattern.slice(0, -3); return path.startsWith(baseFolder + "/") || path === baseFolder; } else if (excludePattern.endsWith("/*")) { const baseFolder = excludePattern.slice(0, -2); if (!path.startsWith(baseFolder + "/")) { return path === baseFolder; } const pathAfterBase = path.slice(baseFolder.length + 1); return pathAfterBase.includes("/"); } return path.startsWith(excludePattern + "/") || path === excludePattern; } handleRename(newFile, oldPath) { if (!(newFile instanceof import_obsidian3.TFile)) return; if (!this.settings.fileExtensions.includes(newFile.extension)) return; const oldBasename = getBasename(oldPath); const newBasename = newFile.basename; const oldImmediateParentName = getImmediateParentName(oldPath); const newImmediateParentName = getImmediateParentName(newFile.path); const isNameChange = this.settings.caseSensitive ? oldBasename !== newBasename : oldBasename.toLowerCase() !== newBasename.toLowerCase(); const isFolderChange = oldImmediateParentName !== newImmediateParentName && !isNameChange; if (!isNameChange && !isFolderChange) { return; } const path = newFile.path; if (this.settings.excludePropertyName && this.settings.excludePropertyName.trim() !== "") { const cache = this.app.metadataCache.getFileCache(newFile); const frontmatter = cache == null ? void 0 : cache.frontmatter; if (frontmatter && frontmatter[this.settings.excludePropertyName] === true) { return; } } if (this.settings.includeFolders.length > 0) { if (!this.settings.includeFolders.some((f) => this.isPathInFolder(path, f))) { return; } } const isIndexFileForFolderRename = isFolderChange && this.settings.trackFolderRenames && this.settings.trackFolderRenames.trim() !== "" && (this.settings.caseSensitive ? newFile.basename === this.settings.trackFolderRenames : newFile.basename.toLowerCase() === this.settings.trackFolderRenames.toLowerCase()); for (const excludePattern of this.settings.excludeFolders) { if (this.isPathExcluded(path, excludePattern)) { if (isIndexFileForFolderRename && excludePattern.endsWith("/*") && !excludePattern.endsWith("/**")) { const baseFolder = excludePattern.slice(0, -2); if (path.startsWith(baseFolder + "/")) { const pathAfterBase = path.slice(baseFolder.length + 1); const pathParts = pathAfterBase.split("/"); if (pathParts.length === 2) { continue; } } } return; } } const regexes = []; for (const regexStr of this.settings.ignoreRegexes) { try { regexes.push(new RegExp(regexStr)); } catch (e) { console.error(`Invalid ignore regex: ${regexStr}`, e); } } let toQueue = null; if (isNameChange) { if (regexes.some((re) => re.test(oldBasename) || re.test(newBasename))) { return; } toQueue = oldBasename; } else if (isFolderChange && this.settings.trackFolderRenames && this.settings.trackFolderRenames.trim() !== "") { const currentBasename = newFile.basename; const matchesFilename = this.settings.caseSensitive ? currentBasename === this.settings.trackFolderRenames : currentBasename.toLowerCase() === this.settings.trackFolderRenames.toLowerCase(); if (!matchesFilename) { return; } if (oldImmediateParentName === "" || newImmediateParentName === "") { return; } if (regexes.some((re) => re.test(oldImmediateParentName) || re.test(newImmediateParentName))) { return; } toQueue = oldImmediateParentName; } if (!toQueue) return; let existingEntry = this.debounceMap.get(newFile.path); if (!existingEntry) { existingEntry = this.debounceMap.get(oldPath); if (existingEntry) { this.debounceMap.delete(oldPath); } } if (existingEntry) { if (existingEntry.timeoutId !== 0) { window.clearTimeout(existingEntry.timeoutId); } toQueue = Array.from(existingEntry.queue)[0]; } const entry = { queue: /* @__PURE__ */ new Set([toQueue]), timeoutId: 0, currentPath: newFile.path }; entry.timeoutId = window.setTimeout(() => { void (async () => { try { await this.historyProcessor.processAliases(entry.currentPath, entry.queue); } catch (error) { console.error("Error processing aliases:", error); } this.debounceMap.delete(entry.currentPath); })(); }, this.settings.timeoutSeconds * 1e3); this.debounceMap.set(newFile.path, entry); } }; //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL21haW4udHMiLCAic3JjL3NldHRpbmdzLnRzIiwgInNyYy91aS9zZXR0aW5ncy10YWIudHMiLCAic3JjL3V0aWxzL2hpc3RvcnktcHJvY2Vzc29yLnRzIiwgInNyYy91dGlscy9wYXRoLXV0aWxzLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgeyBQbHVnaW4sIFRBYnN0cmFjdEZpbGUsIFRGaWxlIH0gZnJvbSAnb2JzaWRpYW4nO1xuaW1wb3J0IHsgRmlsZU5hbWVIaXN0b3J5U2V0dGluZ3MsIERFRkFVTFRfU0VUVElOR1MgfSBmcm9tICcuL3NldHRpbmdzJztcbmltcG9ydCB7IEZpbGVOYW1lSGlzdG9yeVNldHRpbmdUYWIgfSBmcm9tICcuL3VpL3NldHRpbmdzLXRhYic7XG5pbXBvcnQgeyBIaXN0b3J5UHJvY2Vzc29yIH0gZnJvbSAnLi91dGlscy9oaXN0b3J5LXByb2Nlc3Nvcic7XG5pbXBvcnQgeyBnZXRCYXNlbmFtZSwgZ2V0SW1tZWRpYXRlUGFyZW50TmFtZSB9IGZyb20gJy4vdXRpbHMvcGF0aC11dGlscyc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZpbGVOYW1lSGlzdG9yeVBsdWdpbiBleHRlbmRzIFBsdWdpbiB7XG4gIHNldHRpbmdzOiBGaWxlTmFtZUhpc3RvcnlTZXR0aW5ncztcbiAgcHJpdmF0ZSBkZWJvdW5jZU1hcDogTWFwPHN0cmluZywgeyBxdWV1ZTogU2V0PHN0cmluZz47IHRpbWVvdXRJZDogbnVtYmVyOyBjdXJyZW50UGF0aDogc3RyaW5nIH0+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIGhpc3RvcnlQcm9jZXNzb3I6IEhpc3RvcnlQcm9jZXNzb3I7XG5cbiAgYXN5bmMgb25sb2FkKCkge1xuICAgIGF3YWl0IHRoaXMubG9hZFNldHRpbmdzKCk7XG4gICAgdGhpcy5oaXN0b3J5UHJvY2Vzc29yID0gbmV3IEhpc3RvcnlQcm9jZXNzb3IodGhpcy5hcHAsIHRoaXMuc2V0dGluZ3MpO1xuICAgIHRoaXMuYWRkU2V0dGluZ1RhYihuZXcgRmlsZU5hbWVIaXN0b3J5U2V0dGluZ1RhYih0aGlzLmFwcCwgdGhpcykpO1xuICAgIHRoaXMucmVnaXN0ZXJFdmVudChcbiAgICAgIHRoaXMuYXBwLnZhdWx0Lm9uKCdyZW5hbWUnLCAoZmlsZTogVEFic3RyYWN0RmlsZSwgb2xkUGF0aDogc3RyaW5nKSA9PiB7XG4gICAgICAgIHRoaXMuaGFuZGxlUmVuYW1lKGZpbGUsIG9sZFBhdGgpO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgb251bmxvYWQoKSB7XG4gICAgLy8gQ2xlYXIgYW55IHBlbmRpbmcgdGltZW91dHNcbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIHRoaXMuZGVib3VuY2VNYXAudmFsdWVzKCkpIHtcbiAgICAgIGlmIChlbnRyeS50aW1lb3V0SWQgIT09IDApIHtcbiAgICAgICAgd2luZG93LmNsZWFyVGltZW91dChlbnRyeS50aW1lb3V0SWQpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLmRlYm91bmNlTWFwLmNsZWFyKCk7XG4gIH1cblxuICBhc3luYyBsb2FkU2V0dGluZ3MoKSB7XG4gICAgY29uc3QgbG9hZGVkRGF0YSA9IChhd2FpdCB0aGlzLmxvYWREYXRhKCkpIGFzIFBhcnRpYWw8RmlsZU5hbWVIaXN0b3J5U2V0dGluZ3M+IHwgbnVsbDtcbiAgICB0aGlzLnNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgREVGQVVMVF9TRVRUSU5HUywgbG9hZGVkRGF0YSk7XG4gIH1cblxuICBhc3luYyBzYXZlU2V0dGluZ3MoKSB7XG4gICAgYXdhaXQgdGhpcy5zYXZlRGF0YSh0aGlzLnNldHRpbmdzKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNQYXRoSW5Gb2xkZXIocGF0aDogc3RyaW5nLCBmb2xkZXI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIC8vIEhhbmRsZSB2YXVsdCByb290IHZhcmlhYmxlXG4gICAgaWYgKGZvbGRlci5pbmNsdWRlcygne3ZhdWx0fScpIHx8IGZvbGRlci5pbmNsdWRlcygne3Jvb3R9JykpIHtcbiAgICAgIGNvbnN0IHJlc29sdmVkRm9sZGVyID0gZm9sZGVyLnJlcGxhY2UoL1xce3ZhdWx0XFx9fFxce3Jvb3RcXH0vZywgJycpO1xuICAgICAgLy8gSWYgdGhlIGZvbGRlciBpcyBqdXN0IHRoZSB2YXJpYWJsZSwgaXQgbWVhbnMgaW5jbHVkZSBvbmx5IHZhdWx0IHJvb3QgZmlsZXNcbiAgICAgIGlmIChyZXNvbHZlZEZvbGRlciA9PT0gJycgfHwgcmVzb2x2ZWRGb2xkZXIgPT09ICcvJykge1xuICAgICAgICAvLyBJbmNsdWRlIG9ubHkgZmlsZXMgZGlyZWN0bHkgaW4gdGhlIHZhdWx0IHJvb3QgKG5vIHN1YmZvbGRlcnMpXG4gICAgICAgIGNvbnN0IGlzVmF1bHRSb290ID0gIXBhdGguaW5jbHVkZXMoJy8nKTtcbiAgICAgICAgcmV0dXJuIGlzVmF1bHRSb290O1xuICAgICAgfVxuICAgICAgLy8gT3RoZXJ3aXNlLCByZXBsYWNlIHRoZSB2YXJpYWJsZSBhbmQgY2hlY2sgbm9ybWFsbHlcbiAgICAgIHJldHVybiBwYXRoLnN0YXJ0c1dpdGgocmVzb2x2ZWRGb2xkZXIgKyAnLycpIHx8IHBhdGggPT09IHJlc29sdmVkRm9sZGVyO1xuICAgIH1cblxuICAgIC8vIE5vcm1hbCBmb2xkZXIgbWF0Y2hpbmdcbiAgICByZXR1cm4gcGF0aC5zdGFydHNXaXRoKGZvbGRlciArICcvJykgfHwgcGF0aCA9PT0gZm9sZGVyO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1BhdGhFeGNsdWRlZChwYXRoOiBzdHJpbmcsIGV4Y2x1ZGVQYXR0ZXJuOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAvLyBIYW5kbGUgdmF1bHQgcm9vdCB2YXJpYWJsZVxuICAgIGlmIChleGNsdWRlUGF0dGVybi5pbmNsdWRlcygne3ZhdWx0fScpIHx8IGV4Y2x1ZGVQYXR0ZXJuLmluY2x1ZGVzKCd7cm9vdH0nKSkge1xuICAgICAgY29uc3QgcmVzb2x2ZWRQYXR0ZXJuID0gZXhjbHVkZVBhdHRlcm4ucmVwbGFjZSgvXFx7dmF1bHRcXH18XFx7cm9vdFxcfS9nLCAnJyk7XG4gICAgICBpZiAocmVzb2x2ZWRQYXR0ZXJuID09PSAnJyB8fCByZXNvbHZlZFBhdHRlcm4gPT09ICcvJykge1xuICAgICAgICAvLyBFeGNsdWRlIG9ubHkgZmlsZXMgZGlyZWN0bHkgaW4gdGhlIHZhdWx0IHJvb3QgKG5vIHN1YmZvbGRlcnMpXG4gICAgICAgIHJldHVybiAhcGF0aC5pbmNsdWRlcygnLycpO1xuICAgICAgfVxuICAgICAgZXhjbHVkZVBhdHRlcm4gPSByZXNvbHZlZFBhdHRlcm47XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIHdpbGRjYXJkc1xuICAgIGlmIChleGNsdWRlUGF0dGVybi5lbmRzV2l0aCgnLyoqJykpIHtcbiAgICAgIC8vIFJlY3Vyc2l2ZSBleGNsdXNpb246IGRvY3MvKiogbWF0Y2hlcyBkb2NzIGFuZCBhbGwgc3ViZm9sZGVyc1xuICAgICAgY29uc3QgYmFzZUZvbGRlciA9IGV4Y2x1ZGVQYXR0ZXJuLnNsaWNlKDAsIC0zKTtcbiAgICAgIHJldHVybiBwYXRoLnN0YXJ0c1dpdGgoYmFzZUZvbGRlciArICcvJykgfHwgcGF0aCA9PT0gYmFzZUZvbGRlcjtcbiAgICB9IGVsc2UgaWYgKGV4Y2x1ZGVQYXR0ZXJuLmVuZHNXaXRoKCcvKicpKSB7XG4gICAgICAvLyBEaXJlY3QgY2hpbGRyZW4gb25seTogZG9jcy8qIG1hdGNoZXMgZG9jcy9zdWJmb2xkZXIgYnV0IG5vdCBkb2NzL3N1YmZvbGRlci9uZXN0ZWRcbiAgICAgIC8vIFNob3VsZCBleGNsdWRlIGZpbGVzIGluIHN1YmZvbGRlcnMsIGJ1dCBOT1QgZmlsZXMgZGlyZWN0bHkgaW4gdGhlIGJhc2UgZm9sZGVyXG4gICAgICBjb25zdCBiYXNlRm9sZGVyID0gZXhjbHVkZVBhdHRlcm4uc2xpY2UoMCwgLTIpO1xuICAgICAgaWYgKCFwYXRoLnN0YXJ0c1dpdGgoYmFzZUZvbGRlciArICcvJykpIHtcbiAgICAgICAgcmV0dXJuIHBhdGggPT09IGJhc2VGb2xkZXI7XG4gICAgICB9XG4gICAgICBjb25zdCBwYXRoQWZ0ZXJCYXNlID0gcGF0aC5zbGljZShiYXNlRm9sZGVyLmxlbmd0aCArIDEpO1xuICAgICAgLy8gRXhjbHVkZSBpZiBwYXRoIGlzIGluIGEgc3ViZm9sZGVyIChoYXMgYXQgbGVhc3Qgb25lIHNsYXNoKVxuICAgICAgLy8gRG9uJ3QgZXhjbHVkZSBmaWxlcyBkaXJlY3RseSBpbiB0aGUgYmFzZSBmb2xkZXIgKG5vIHNsYXNoKVxuICAgICAgcmV0dXJuIHBhdGhBZnRlckJhc2UuaW5jbHVkZXMoJy8nKTtcbiAgICB9XG5cbiAgICAvLyBOb3JtYWwgZm9sZGVyIG1hdGNoaW5nXG4gICAgcmV0dXJuIHBhdGguc3RhcnRzV2l0aChleGNsdWRlUGF0dGVybiArICcvJykgfHwgcGF0aCA9PT0gZXhjbHVkZVBhdHRlcm47XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZVJlbmFtZShuZXdGaWxlOiBUQWJzdHJhY3RGaWxlLCBvbGRQYXRoOiBzdHJpbmcpIHtcbiAgICBpZiAoIShuZXdGaWxlIGluc3RhbmNlb2YgVEZpbGUpKSByZXR1cm47XG4gICAgaWYgKCF0aGlzLnNldHRpbmdzLmZpbGVFeHRlbnNpb25zLmluY2x1ZGVzKG5ld0ZpbGUuZXh0ZW5zaW9uKSkgcmV0dXJuO1xuXG4gICAgY29uc3Qgb2xkQmFzZW5hbWUgPSBnZXRCYXNlbmFtZShvbGRQYXRoKTtcbiAgICBjb25zdCBuZXdCYXNlbmFtZSA9IG5ld0ZpbGUuYmFzZW5hbWU7XG4gICAgY29uc3Qgb2xkSW1tZWRpYXRlUGFyZW50TmFtZSA9IGdldEltbWVkaWF0ZVBhcmVudE5hbWUob2xkUGF0aCk7XG4gICAgY29uc3QgbmV3SW1tZWRpYXRlUGFyZW50TmFtZSA9IGdldEltbWVkaWF0ZVBhcmVudE5hbWUobmV3RmlsZS5wYXRoKTtcblxuICAgIGNvbnN0IGlzTmFtZUNoYW5nZSA9IHRoaXMuc2V0dGluZ3MuY2FzZVNlbnNpdGl2ZVxuICAgICAgPyBvbGRCYXNlbmFtZSAhPT0gbmV3QmFzZW5hbWVcbiAgICAgIDogb2xkQmFzZW5hbWUudG9Mb3dlckNhc2UoKSAhPT0gbmV3QmFzZW5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCBpc0ZvbGRlckNoYW5nZSA9IG9sZEltbWVkaWF0ZVBhcmVudE5hbWUgIT09IG5ld0ltbWVkaWF0ZVBhcmVudE5hbWUgJiYgIWlzTmFtZUNoYW5nZTtcblxuICAgIGlmICghaXNOYW1lQ2hhbmdlICYmICFpc0ZvbGRlckNoYW5nZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHBhdGggPSBuZXdGaWxlLnBhdGg7XG5cbiAgICAvLyBBcHBseSBmaWx0ZXJpbmcgY2hlY2tzIHRvIGJvdGggZmlsZSBuYW1lIGNoYW5nZXMgYW5kIGZvbGRlciByZW5hbWVzXG4gICAgLy8gUHJpb3JpdHk6IFByb3BlcnR5IGV4Y2x1c2lvbiAtPiBJbmNsdWRlIGZvbGRlcnMgLT4gRXhjbHVkZSBmb2xkZXJzXG5cbiAgICAvLyAxLiBDaGVjayBwcm9wZXJ0eS1iYXNlZCBleGNsdXNpb24gZmlyc3QgKGhpZ2hlc3QgcHJpb3JpdHkpXG4gICAgaWYgKHRoaXMuc2V0dGluZ3MuZXhjbHVkZVByb3BlcnR5TmFtZSAmJiB0aGlzLnNldHRpbmdzLmV4Y2x1ZGVQcm9wZXJ0eU5hbWUudHJpbSgpICE9PSAnJykge1xuICAgICAgY29uc3QgY2FjaGUgPSB0aGlzLmFwcC5tZXRhZGF0YUNhY2hlLmdldEZpbGVDYWNoZShuZXdGaWxlKTtcbiAgICAgIGNvbnN0IGZyb250bWF0dGVyID0gY2FjaGU/LmZyb250bWF0dGVyO1xuICAgICAgaWYgKGZyb250bWF0dGVyICYmIGZyb250bWF0dGVyW3RoaXMuc2V0dGluZ3MuZXhjbHVkZVByb3BlcnR5TmFtZV0gPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuOyAvLyBFeGNsdWRlIHRoaXMgZmlsZVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIDIuIENoZWNrIGluY2x1ZGUgZm9sZGVycyAoaWYgaW5jbHVkZUZvbGRlcnMgaXMgbm90IGVtcHR5LCBvbmx5IGluY2x1ZGUgdGhvc2UpXG4gICAgaWYgKHRoaXMuc2V0dGluZ3MuaW5jbHVkZUZvbGRlcnMubGVuZ3RoID4gMCkge1xuICAgICAgaWYgKCF0aGlzLnNldHRpbmdzLmluY2x1ZGVGb2xkZXJzLnNvbWUoZiA9PiB0aGlzLmlzUGF0aEluRm9sZGVyKHBhdGgsIGYpKSkge1xuICAgICAgICByZXR1cm47IC8vIE5vdCBpbiBhbnkgaW5jbHVkZWQgZm9sZGVyXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gMy4gQ2hlY2sgZXhjbHVkZSBmb2xkZXJzICh3aXRoIHdpbGRjYXJkIHN1cHBvcnQpXG4gICAgLy8gU3BlY2lhbCBjYXNlOiBpZiB0cmFja2luZyBmb2xkZXIgcmVuYW1lcyBmb3IgYSBzcGVjaWZpYyBmaWxlIG5hbWUsIGFsbG93IGl0IGV2ZW4gaW4gZXhjbHVkZWQgc3ViZm9sZGVyc1xuICAgIC8vIHVubGVzcyB1c2luZyByZWN1cnNpdmUgZXhjbHVzaW9uICgqKikgb3IgdGhlIGZpbGUgaXMgbmVzdGVkIGRlZXBlciB0aGFuIG9uZSBsZXZlbFxuICAgIGNvbnN0IGlzSW5kZXhGaWxlRm9yRm9sZGVyUmVuYW1lID0gaXNGb2xkZXJDaGFuZ2UgJiZcbiAgICAgIHRoaXMuc2V0dGluZ3MudHJhY2tGb2xkZXJSZW5hbWVzICYmXG4gICAgICB0aGlzLnNldHRpbmdzLnRyYWNrRm9sZGVyUmVuYW1lcy50cmltKCkgIT09ICcnICYmXG4gICAgICAodGhpcy5zZXR0aW5ncy5jYXNlU2Vuc2l0aXZlXG4gICAgICAgID8gbmV3RmlsZS5iYXNlbmFtZSA9PT0gdGhpcy5zZXR0aW5ncy50cmFja0ZvbGRlclJlbmFtZXNcbiAgICAgICAgOiBuZXdGaWxlLmJhc2VuYW1lLnRvTG93ZXJDYXNlKCkgPT09IHRoaXMuc2V0dGluZ3MudHJhY2tGb2xkZXJSZW5hbWVzLnRvTG93ZXJDYXNlKCkpO1xuXG4gICAgZm9yIChjb25zdCBleGNsdWRlUGF0dGVybiBvZiB0aGlzLnNldHRpbmdzLmV4Y2x1ZGVGb2xkZXJzKSB7XG4gICAgICBpZiAodGhpcy5pc1BhdGhFeGNsdWRlZChwYXRoLCBleGNsdWRlUGF0dGVybikpIHtcbiAgICAgICAgLy8gSWYgdGhpcyBpcyBhbiBpbmRleCBmaWxlIGZvciBmb2xkZXIgcmVuYW1lIHRyYWNraW5nLCBhbmQgdGhlIHBhdHRlcm4gaXMgLyogKG5vdCAvKiopLFxuICAgICAgICAvLyBhbGxvdyBpdCB0aHJvdWdoIG9ubHkgaWYgaXQncyBpbiBhIGRpcmVjdCBjaGlsZCBmb2xkZXIgKG9uZSBsZXZlbCBkZWVwKVxuICAgICAgICBpZiAoaXNJbmRleEZpbGVGb3JGb2xkZXJSZW5hbWUgJiYgZXhjbHVkZVBhdHRlcm4uZW5kc1dpdGgoJy8qJykgJiYgIWV4Y2x1ZGVQYXR0ZXJuLmVuZHNXaXRoKCcvKionKSkge1xuICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSBmaWxlIGlzIGluIGEgZGlyZWN0IGNoaWxkIChvbmx5IG9uZSBsZXZlbCBkZWVwKVxuICAgICAgICAgIGNvbnN0IGJhc2VGb2xkZXIgPSBleGNsdWRlUGF0dGVybi5zbGljZSgwLCAtMik7XG4gICAgICAgICAgaWYgKHBhdGguc3RhcnRzV2l0aChiYXNlRm9sZGVyICsgJy8nKSkge1xuICAgICAgICAgICAgY29uc3QgcGF0aEFmdGVyQmFzZSA9IHBhdGguc2xpY2UoYmFzZUZvbGRlci5sZW5ndGggKyAxKTtcbiAgICAgICAgICAgIGNvbnN0IHBhdGhQYXJ0cyA9IHBhdGhBZnRlckJhc2Uuc3BsaXQoJy8nKTtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlJ3Mgb25seSBvbmUgcGF0aCBwYXJ0IGJlZm9yZSB0aGUgZmlsZW5hbWUsIGl0J3MgYSBkaXJlY3QgY2hpbGRcbiAgICAgICAgICAgIC8vIHBhdGhQYXJ0cyB3aWxsIGJlIGxpa2UgWydzdWJmb2xkZXInLCAnZmlsZW5hbWUubWQnXSAtIHdlIHdhbnQgZXhhY3RseSAyIHBhcnRzXG4gICAgICAgICAgICBpZiAocGF0aFBhcnRzLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgICAgICBjb250aW51ZTsgLy8gU2tpcCB0aGlzIGV4Y2x1c2lvbiAtIGl0J3MgYSBkaXJlY3QgY2hpbGQgaW5kZXggZmlsZVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm47IC8vIEV4Y2x1ZGVkIGJ5IGZvbGRlciBwYXR0ZXJuXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWdub3JlIHJlZ2V4ZXNcbiAgICBjb25zdCByZWdleGVzOiBSZWdFeHBbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgcmVnZXhTdHIgb2YgdGhpcy5zZXR0aW5ncy5pZ25vcmVSZWdleGVzKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZWdleGVzLnB1c2gobmV3IFJlZ0V4cChyZWdleFN0cikpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBJbnZhbGlkIGlnbm9yZSByZWdleDogJHtyZWdleFN0cn1gLCBlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgdG9RdWV1ZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgaWYgKGlzTmFtZUNoYW5nZSkge1xuICAgICAgaWYgKHJlZ2V4ZXMuc29tZShyZSA9PiByZS50ZXN0KG9sZEJhc2VuYW1lKSB8fCByZS50ZXN0KG5ld0Jhc2VuYW1lKSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdG9RdWV1ZSA9IG9sZEJhc2VuYW1lO1xuICAgIH0gZWxzZSBpZiAoaXNGb2xkZXJDaGFuZ2UgJiYgdGhpcy5zZXR0aW5ncy50cmFja0ZvbGRlclJlbmFtZXMgJiYgdGhpcy5zZXR0aW5ncy50cmFja0ZvbGRlclJlbmFtZXMudHJpbSgpICE9PSAnJykge1xuICAgICAgLy8gQ2hlY2sgaWYgdGhlIGN1cnJlbnQgZmlsZSBuYW1lIG1hdGNoZXMgdGhlIHNwZWNpZmllZCBuYW1lICh3aXRob3V0IGV4dGVuc2lvbilcbiAgICAgIGNvbnN0IGN1cnJlbnRCYXNlbmFtZSA9IG5ld0ZpbGUuYmFzZW5hbWU7XG4gICAgICBjb25zdCBtYXRjaGVzRmlsZW5hbWUgPSB0aGlzLnNldHRpbmdzLmNhc2VTZW5zaXRpdmVcbiAgICAgICAgPyBjdXJyZW50QmFzZW5hbWUgPT09IHRoaXMuc2V0dGluZ3MudHJhY2tGb2xkZXJSZW5hbWVzXG4gICAgICAgIDogY3VycmVudEJhc2VuYW1lLnRvTG93ZXJDYXNlKCkgPT09IHRoaXMuc2V0dGluZ3MudHJhY2tGb2xkZXJSZW5hbWVzLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgIGlmICghbWF0Y2hlc0ZpbGVuYW1lKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKG9sZEltbWVkaWF0ZVBhcmVudE5hbWUgPT09ICcnIHx8IG5ld0ltbWVkaWF0ZVBhcmVudE5hbWUgPT09ICcnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChyZWdleGVzLnNvbWUocmUgPT4gcmUudGVzdChvbGRJbW1lZGlhdGVQYXJlbnROYW1lKSB8fCByZS50ZXN0KG5ld0ltbWVkaWF0ZVBhcmVudE5hbWUpKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0b1F1ZXVlID0gb2xkSW1tZWRpYXRlUGFyZW50TmFtZTtcbiAgICB9XG5cbiAgICBpZiAoIXRvUXVldWUpIHJldHVybjtcblxuICAgIC8vIENoZWNrIGlmIHRoZXJlJ3MgYWxyZWFkeSBhIHBlbmRpbmcgdGltZW91dCBmb3IgdGhpcyBmaWxlXG4gICAgLy8gV2UgbmVlZCB0byBjaGVjayBib3RoIHRoZSBuZXcgcGF0aCBhbmQgdGhlIG9sZCBwYXRoIHNpbmNlIHRoZSBmaWxlIHdhcyBqdXN0IHJlbmFtZWRcbiAgICBsZXQgZXhpc3RpbmdFbnRyeSA9IHRoaXMuZGVib3VuY2VNYXAuZ2V0KG5ld0ZpbGUucGF0aCk7XG4gICAgaWYgKCFleGlzdGluZ0VudHJ5KSB7XG4gICAgICAvLyBDaGVjayBpZiB0aGVyZSdzIGEgdGltZW91dCBmb3IgdGhlIG9sZCBwYXRoICh0aGUgZmlsZSB3YXMganVzdCByZW5hbWVkIGZyb20gdGhlcmUpXG4gICAgICBleGlzdGluZ0VudHJ5ID0gdGhpcy5kZWJvdW5jZU1hcC5nZXQob2xkUGF0aCk7XG4gICAgICBpZiAoZXhpc3RpbmdFbnRyeSkge1xuICAgICAgICAvLyBSZW1vdmUgdGhlIG9sZCBlbnRyeSBzaW5jZSB3ZSdyZSB1cGRhdGluZyBpdCB3aXRoIHRoZSBuZXcgcGF0aFxuICAgICAgICB0aGlzLmRlYm91bmNlTWFwLmRlbGV0ZShvbGRQYXRoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZXhpc3RpbmdFbnRyeSkge1xuICAgICAgLy8gRmlsZSB3YXMgcmVuYW1lZCBhZ2FpbiBiZWZvcmUgdGltZW91dCBleHBpcmVkIC0gY2FuY2VsIHRoZSBwcmV2aW91cyB0aW1lb3V0XG4gICAgICBpZiAoZXhpc3RpbmdFbnRyeS50aW1lb3V0SWQgIT09IDApIHtcbiAgICAgICAgd2luZG93LmNsZWFyVGltZW91dChleGlzdGluZ0VudHJ5LnRpbWVvdXRJZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIFVzZSB0aGUgb3JpZ2luYWwgc3RhYmxlIG5hbWUgZnJvbSB0aGUgcHJldmlvdXMgdGltZW91dCwgbm90IHRoZSB0ZW1wb3JhcnkgbmFtZVxuICAgICAgdG9RdWV1ZSA9IEFycmF5LmZyb20oZXhpc3RpbmdFbnRyeS5xdWV1ZSlbMF07IC8vIFVzZSB0aGUgb3JpZ2luYWwgc3RhYmxlIG5hbWVcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgZW50cnkgdG8gdHJhY2sgdGhlIHRpbWVvdXRcbiAgICBjb25zdCBlbnRyeSA9IHtcbiAgICAgIHF1ZXVlOiBuZXcgU2V0PHN0cmluZz4oW3RvUXVldWVdKSxcbiAgICAgIHRpbWVvdXRJZDogMCxcbiAgICAgIGN1cnJlbnRQYXRoOiBuZXdGaWxlLnBhdGhcbiAgICB9O1xuXG4gICAgLy8gU2V0IHRpbWVvdXQgdG8gYWN0dWFsbHkgc3RvcmUgdGhlIGFsaWFzIGFmdGVyIHRoZSBkZWJvdW5jZSBwZXJpb2RcbiAgICBlbnRyeS50aW1lb3V0SWQgPSB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB2b2lkIChhc3luYyAoKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5oaXN0b3J5UHJvY2Vzc29yLnByb2Nlc3NBbGlhc2VzKGVudHJ5LmN1cnJlbnRQYXRoLCBlbnRyeS5xdWV1ZSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgcHJvY2Vzc2luZyBhbGlhc2VzOicsIGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRlYm91bmNlTWFwLmRlbGV0ZShlbnRyeS5jdXJyZW50UGF0aCk7XG4gICAgICB9KSgpO1xuICAgIH0sIHRoaXMuc2V0dGluZ3MudGltZW91dFNlY29uZHMgKiAxMDAwKTtcblxuICAgIHRoaXMuZGVib3VuY2VNYXAuc2V0KG5ld0ZpbGUucGF0aCwgZW50cnkpO1xuICB9XG59XG4iLCAiZXhwb3J0IGludGVyZmFjZSBGaWxlTmFtZUhpc3RvcnlTZXR0aW5ncyB7XHJcbiAgaGlzdG9yeVByb3BlcnR5TmFtZTogc3RyaW5nO1xyXG4gIGlnbm9yZVJlZ2V4ZXM6IHN0cmluZ1tdO1xyXG4gIHRpbWVvdXRTZWNvbmRzOiBudW1iZXI7XHJcbiAgY2FzZVNlbnNpdGl2ZTogYm9vbGVhbjtcclxuICBhdXRvQ3JlYXRlRnJvbnRtYXR0ZXI6IGJvb2xlYW47XHJcbiAgaW5jbHVkZUZvbGRlcnM6IHN0cmluZ1tdO1xyXG4gIGV4Y2x1ZGVGb2xkZXJzOiBzdHJpbmdbXTtcclxuICBmaWxlRXh0ZW5zaW9uczogc3RyaW5nW107XHJcbiAgdHJhY2tGb2xkZXJSZW5hbWVzOiBzdHJpbmc7XHJcbiAgZXhjbHVkZVByb3BlcnR5TmFtZTogc3RyaW5nO1xyXG59XHJcblxyXG5leHBvcnQgY29uc3QgREVGQVVMVF9TRVRUSU5HUzogRmlsZU5hbWVIaXN0b3J5U2V0dGluZ3MgPSB7XHJcbiAgaGlzdG9yeVByb3BlcnR5TmFtZTogJ2FsaWFzZXMnLFxyXG4gIGlnbm9yZVJlZ2V4ZXM6IFsnXl8nLCAnXlVudGl0bGVkJCcsICdeVW50aXRsZWQgXFxcXGQrJCddLFxyXG4gIHRpbWVvdXRTZWNvbmRzOiA1LFxyXG4gIGNhc2VTZW5zaXRpdmU6IGZhbHNlLFxyXG4gIGF1dG9DcmVhdGVGcm9udG1hdHRlcjogdHJ1ZSxcclxuICBpbmNsdWRlRm9sZGVyczogW10sXHJcbiAgZXhjbHVkZUZvbGRlcnM6IFtdLFxyXG4gIGZpbGVFeHRlbnNpb25zOiBbJ21kJ10sXHJcbiAgdHJhY2tGb2xkZXJSZW5hbWVzOiAnJyxcclxuICBleGNsdWRlUHJvcGVydHlOYW1lOiAnJyxcclxufTsiLCAiaW1wb3J0IHsgQXBwLCBQbHVnaW4sIFBsdWdpblNldHRpbmdUYWIgLCBTZXR0aW5nR3JvdXB9IGZyb20gJ29ic2lkaWFuJztcclxuaW1wb3J0IHsgRmlsZU5hbWVIaXN0b3J5U2V0dGluZ3MgfSBmcm9tICcuLi9zZXR0aW5ncyc7XHJcblxyXG5cclxuaW50ZXJmYWNlIEZpbGVOYW1lSGlzdG9yeVBsdWdpbiBleHRlbmRzIFBsdWdpbiB7XHJcbiAgc2V0dGluZ3M6IEZpbGVOYW1lSGlzdG9yeVNldHRpbmdzO1xyXG4gIHNhdmVTZXR0aW5ncygpOiBQcm9taXNlPHZvaWQ+O1xyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgRmlsZU5hbWVIaXN0b3J5U2V0dGluZ1RhYiBleHRlbmRzIFBsdWdpblNldHRpbmdUYWIge1xyXG4gIHBsdWdpbjogRmlsZU5hbWVIaXN0b3J5UGx1Z2luO1xyXG4gIHB1YmxpYyBpY29uID0gJ2x1Y2lkZS1mb3J3YXJkJztcclxuXHJcbiAgY29uc3RydWN0b3IoYXBwOiBBcHAsIHBsdWdpbjogRmlsZU5hbWVIaXN0b3J5UGx1Z2luKSB7XHJcbiAgICBzdXBlcihhcHAsIHBsdWdpbik7XHJcbiAgICB0aGlzLnBsdWdpbiA9IHBsdWdpbjtcclxuICB9XHJcblxyXG4gIGRpc3BsYXkoKTogdm9pZCB7XHJcbiAgICBjb25zdCB7IGNvbnRhaW5lckVsIH0gPSB0aGlzO1xyXG4gICAgY29udGFpbmVyRWwuZW1wdHkoKTtcclxuXHJcbiAgICAvLyBIZWxwZXIgdG8gc2F2ZSBzZXR0aW5ncyB3aXRob3V0IHJldHVybmluZyBhIHByb21pc2VcclxuICAgIGNvbnN0IHNhdmVTZXR0aW5ncyA9ICgpOiB2b2lkID0+IHtcclxuICAgICAgdm9pZCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuICAgIH07XHJcblxyXG4gICAgY29uc3QgZ2VuZXJhbEdyb3VwID0gbmV3IFNldHRpbmdHcm91cChjb250YWluZXJFbCk7XHJcblxyXG4gICAgLy8gR2VuZXJhbCBiZWhhdmlvciBzZXR0aW5ncyAoZ3JvdXBlZCwgbm8gaGVhZGluZylcclxuICAgIGdlbmVyYWxHcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG4gICAgICBzZXR0aW5nXHJcbiAgICAgICAgLnNldE5hbWUoJ0hpc3RvcnkgcHJvcGVydHkgbmFtZScpXHJcbiAgICAgICAgLnNldERlc2MoJ1RoZSBsaXN0IHByb3BlcnR5IHRvIHN0b3JlIGZpbGUgbmFtZSBoaXN0b3J5LicpXHJcbiAgICAgICAgLmFkZFRleHQodGV4dCA9PlxyXG4gICAgICAgICAgdGV4dFxyXG4gICAgICAgICAgICAuc2V0UGxhY2Vob2xkZXIoJ2FsaWFzZXMnKVxyXG4gICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuaGlzdG9yeVByb3BlcnR5TmFtZSlcclxuICAgICAgICAgICAgLm9uQ2hhbmdlKHZhbHVlID0+IHtcclxuICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5oaXN0b3J5UHJvcGVydHlOYW1lID0gdmFsdWUgfHwgJ2FsaWFzZXMnO1xyXG4gICAgICAgICAgICAgIHNhdmVTZXR0aW5ncygpO1xyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgICk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBnZW5lcmFsR3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuICAgICAgc2V0dGluZ1xyXG4gICAgICAgIC5zZXROYW1lKCdUaW1lb3V0IHNlY29uZHMnKVxyXG4gICAgICAgIC5zZXREZXNjKCdUaW1lIGluIHNlY29uZHMgdGhlIG5hbWUgbXVzdCBiZSBzdGFibGUgYmVmb3JlIGFkZGluZyB0byB0aGUgY29uZmlndXJlZCBwcm9wZXJ0eS4nKVxyXG4gICAgICAgIC5hZGRTbGlkZXIoc2xpZGVyID0+XHJcbiAgICAgICAgICBzbGlkZXJcclxuICAgICAgICAgICAgLnNldExpbWl0cygxLCAyMCwgMSlcclxuICAgICAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnRpbWVvdXRTZWNvbmRzKVxyXG4gICAgICAgICAgICAuc2V0RHluYW1pY1Rvb2x0aXAoKVxyXG4gICAgICAgICAgICAub25DaGFuZ2UodmFsdWUgPT4ge1xyXG4gICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLnRpbWVvdXRTZWNvbmRzID0gdmFsdWU7XHJcbiAgICAgICAgICAgICAgc2F2ZVNldHRpbmdzKCk7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGdlbmVyYWxHcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG4gICAgICBzZXR0aW5nXHJcbiAgICAgICAgLnNldE5hbWUoJ0Nhc2Utc2Vuc2l0aXZlIHVuaXF1ZW5lc3MnKVxyXG5cclxuICAgICAgICAuc2V0RGVzYygnSWYgZW5hYmxlZCwgdHJlYXQgY2FzZSBkaWZmZXJlbmNlcyBhcyB1bmlxdWUgdmFsdWVzIGluIHRoZSBjb25maWd1cmVkIHByb3BlcnR5LicpXHJcbiAgICAgICAgLmFkZFRvZ2dsZSh0b2dnbGUgPT5cclxuICAgICAgICAgIHRvZ2dsZVxyXG4gICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuY2FzZVNlbnNpdGl2ZSlcclxuICAgICAgICAgICAgLm9uQ2hhbmdlKHZhbHVlID0+IHtcclxuICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5jYXNlU2Vuc2l0aXZlID0gdmFsdWU7XHJcbiAgICAgICAgICAgICAgc2F2ZVNldHRpbmdzKCk7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGdlbmVyYWxHcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG4gICAgICBzZXR0aW5nXHJcbiAgICAgICAgLnNldE5hbWUoJ0F1dG8tY3JlYXRlIGhpc3RvcnkgcHJvcGVydHknKVxyXG4gICAgICAgIC5zZXREZXNjKCdBdXRvbWF0aWNhbGx5IGNyZWF0ZSB0aGUgY29uZmlndXJlZCBwcm9wZXJ0eSBpZiBtaXNzaW5nLicpXHJcbiAgICAgICAgLmFkZFRvZ2dsZSh0b2dnbGUgPT5cclxuICAgICAgICAgIHRvZ2dsZVxyXG4gICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuYXV0b0NyZWF0ZUZyb250bWF0dGVyKVxyXG4gICAgICAgICAgICAub25DaGFuZ2UodmFsdWUgPT4ge1xyXG4gICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmF1dG9DcmVhdGVGcm9udG1hdHRlciA9IHZhbHVlO1xyXG4gICAgICAgICAgICAgIHNhdmVTZXR0aW5ncygpO1xyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgICk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBnZW5lcmFsR3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuICAgICAgc2V0dGluZ1xyXG4gICAgICAgIC5zZXROYW1lKCdGaWxlIGV4dGVuc2lvbnMnKVxyXG4gICAgICAgIC5zZXREZXNjKCdDb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiBmaWxlIGV4dGVuc2lvbnMgdG8gdHJhY2suJylcclxuICAgICAgICAuYWRkVGV4dCh0ZXh0ID0+XHJcbiAgICAgICAgICB0ZXh0XHJcblxyXG4gICAgICAgICAgICAuc2V0UGxhY2Vob2xkZXIoJ01kLCB0eHQnKVxyXG4gICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZmlsZUV4dGVuc2lvbnMuam9pbignLCcpKVxyXG4gICAgICAgICAgICAub25DaGFuZ2UodmFsdWUgPT4ge1xyXG4gICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmZpbGVFeHRlbnNpb25zID0gdmFsdWVcclxuICAgICAgICAgICAgICAgIC5zcGxpdCgnLCcpXHJcbiAgICAgICAgICAgICAgICAubWFwKHMgPT4gcy50cmltKCkpXHJcbiAgICAgICAgICAgICAgICAuZmlsdGVyKHMgPT4gcyk7XHJcbiAgICAgICAgICAgICAgc2F2ZVNldHRpbmdzKCk7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IGZpbHRlcmluZ0dyb3VwID0gbmV3IFNldHRpbmdHcm91cChjb250YWluZXJFbCkuc2V0SGVhZGluZygnRmlsdGVyaW5nJyk7XHJcbiAgICBjb25zdCBmb2xkZXJzR3JvdXAgPSBuZXcgU2V0dGluZ0dyb3VwKGNvbnRhaW5lckVsKS5zZXRIZWFkaW5nKCdGb2xkZXJzJyk7XHJcbiAgICBjb25zdCBhZHZhbmNlZEdyb3VwID0gbmV3IFNldHRpbmdHcm91cChjb250YWluZXJFbCkuc2V0SGVhZGluZygnQWR2YW5jZWQnKTtcclxuXHJcbiAgICAvLyBGaWx0ZXJpbmcgc2V0dGluZ3NcclxuICAgIGZpbHRlcmluZ0dyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcbiAgICAgIHNldHRpbmdcclxuICAgICAgICAuc2V0TmFtZSgnSWdub3JlIHJlZ2V4IHBhdHRlcm5zJylcclxuICAgICAgICAuc2V0RGVzYyhcclxuICAgICAgICAgICdDb21tYS1zZXBhcmF0ZWQgcmVnZXggcGF0dGVybnMgZm9yIGZpbGUgbmFtZXMgb3IgaW1tZWRpYXRlIHBhcmVudCBmb2xkZXIgbmFtZXMgdG8gaWdub3JlIChlLmcuLCBeXyBmb3IgdW5kZXJzY29yZSBwcmVmaXhlcywgXnVudGl0bGVkJCBmb3IgdW50aXRsZWQpLiBMZWF2ZSBlbXB0eSB0byBkaXNhYmxlLidcclxuICAgICAgICApXHJcbiAgICAgICAgLmFkZFRleHQodGV4dCA9PlxyXG4gICAgICAgICAgdGV4dFxyXG4gICAgICAgICAgICAuc2V0UGxhY2Vob2xkZXIoJ15fLCBedW50aXRsZWQkLCBedW50aXRsZWQgXFxcXGQrJCcpXHJcbiAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5pZ25vcmVSZWdleGVzLmpvaW4oJywnKSlcclxuICAgICAgICAgICAgLm9uQ2hhbmdlKHZhbHVlID0+IHtcclxuICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5pZ25vcmVSZWdleGVzID0gdmFsdWVcclxuICAgICAgICAgICAgICAgIC5zcGxpdCgnLCcpXHJcbiAgICAgICAgICAgICAgICAubWFwKHMgPT4gcy50cmltKCkpXHJcbiAgICAgICAgICAgICAgICAuZmlsdGVyKHMgPT4gcyk7XHJcbiAgICAgICAgICAgICAgc2F2ZVNldHRpbmdzKCk7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGZpbHRlcmluZ0dyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcbiAgICAgIHNldHRpbmdcclxuICAgICAgICAuc2V0TmFtZSgnRXhjbHVkZSBwcm9wZXJ0eSBuYW1lJylcclxuICAgICAgICAuc2V0RGVzYyhcclxuICAgICAgICAgICdOYW1lIG9mIGEgYm9vbGVhbiBwcm9wZXJ0eSB0byBjaGVjayBpbiBmaWxlcy4gRmlsZXMgd2l0aCB0aGlzIHByb3BlcnR5IHNldCB0byB0cnVlIHdpbGwgYmUgZXhjbHVkZWQgZnJvbSB0cmFja2luZy4gVGFrZXMgcHJpb3JpdHkgb3ZlciBmb2xkZXIgZmlsdGVyaW5nLidcclxuICAgICAgICApXHJcbiAgICAgICAgLmFkZFRleHQodGV4dCA9PlxyXG4gICAgICAgICAgdGV4dFxyXG5cclxuICAgICAgICAgICAgLnNldFBsYWNlaG9sZGVyKCdTa2lwLXJlbmFtZS10cmFja2luZycpXHJcbiAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5leGNsdWRlUHJvcGVydHlOYW1lKVxyXG4gICAgICAgICAgICAub25DaGFuZ2UodmFsdWUgPT4ge1xyXG4gICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmV4Y2x1ZGVQcm9wZXJ0eU5hbWUgPSB2YWx1ZTtcclxuICAgICAgICAgICAgICBzYXZlU2V0dGluZ3MoKTtcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICApO1xyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gRm9sZGVyIGluY2x1ZGUvZXhjbHVkZSBzZXR0aW5nc1xyXG4gICAgZm9sZGVyc0dyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcbiAgICAgIHNldHRpbmdcclxuICAgICAgICAuc2V0TmFtZSgnSW5jbHVkZSBmb2xkZXJzJylcclxuICAgICAgICAuc2V0RGVzYyhcclxuICAgICAgICAgICdDb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiBmb2xkZXIgcGF0aHMgdG8gaW5jbHVkZS4gSWYgZW1wdHksIGFsbCBmb2xkZXJzIGFyZSBpbmNsdWRlZC4gVXNlIHt2YXVsdH0gb3Ige3Jvb3R9IHRvIGluY2x1ZGUgb25seSBmaWxlcyBkaXJlY3RseSBpbiB0aGUgdmF1bHQgcm9vdCAobm8gc3ViZm9sZGVycykuJ1xyXG4gICAgICAgIClcclxuICAgICAgICAuYWRkVGV4dCh0ZXh0ID0+XHJcbiAgICAgICAgICB0ZXh0XHJcbiAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5pbmNsdWRlRm9sZGVycy5qb2luKCcsJykpXHJcbiAgICAgICAgICAgIC5vbkNoYW5nZSh2YWx1ZSA9PiB7XHJcbiAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuaW5jbHVkZUZvbGRlcnMgPSB2YWx1ZVxyXG4gICAgICAgICAgICAgICAgLnNwbGl0KCcsJylcclxuICAgICAgICAgICAgICAgIC5tYXAocyA9PiBzLnRyaW0oKSlcclxuICAgICAgICAgICAgICAgIC5maWx0ZXIocyA9PiBzKTtcclxuICAgICAgICAgICAgICBzYXZlU2V0dGluZ3MoKTtcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICApO1xyXG4gICAgfSk7XHJcblxyXG4gICAgZm9sZGVyc0dyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcbiAgICAgIHNldHRpbmdcclxuICAgICAgICAuc2V0TmFtZSgnRXhjbHVkZSBmb2xkZXJzJylcclxuICAgICAgICAuc2V0RGVzYyhcclxuICAgICAgICAgICdDb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiBmb2xkZXIgcGF0aHMgdG8gZXhjbHVkZS4gU3VwcG9ydHMgd2lsZGNhcmRzOiB1c2UgXCJmb2xkZXIvKlwiIHRvIGV4Y2x1ZGUgZGlyZWN0IGNoaWxkcmVuLCBcImZvbGRlci8qKlwiIHRvIGV4Y2x1ZGUgYWxsIGRlc2NlbmRhbnRzLiBVc2Uge3ZhdWx0fSBvciB7cm9vdH0gdG8gZXhjbHVkZSBmaWxlcyBkaXJlY3RseSBpbiB0aGUgdmF1bHQgcm9vdC4nXHJcbiAgICAgICAgKVxyXG4gICAgICAgIC5hZGRUZXh0KHRleHQgPT5cclxuICAgICAgICAgIHRleHRcclxuICAgICAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmV4Y2x1ZGVGb2xkZXJzLmpvaW4oJywnKSlcclxuICAgICAgICAgICAgLm9uQ2hhbmdlKHZhbHVlID0+IHtcclxuICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5leGNsdWRlRm9sZGVycyA9IHZhbHVlXHJcbiAgICAgICAgICAgICAgICAuc3BsaXQoJywnKVxyXG4gICAgICAgICAgICAgICAgLm1hcChzID0+IHMudHJpbSgpKVxyXG4gICAgICAgICAgICAgICAgLmZpbHRlcihzID0+IHMpO1xyXG4gICAgICAgICAgICAgIHNhdmVTZXR0aW5ncygpO1xyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgICk7XHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyBBZHZhbmNlZCAvIG5pY2hlIG9wdGlvbnNcclxuICAgIGFkdmFuY2VkR3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuICAgICAgc2V0dGluZ1xyXG4gICAgICAgIC5zZXROYW1lKCdUcmFjayBmb2xkZXIgcmVuYW1lcyBmb3Igc3BlY2lmaWMgZmlsZSBuYW1lJylcclxuICAgICAgICAuc2V0RGVzYyhcclxuXHJcbiAgICAgICAgICAnSWYgYSBNYXJrZG93biBmaWxlIG1hdGNoZXMgdGhpcyBmaWxlIG5hbWUsIHN0b3JlIG9sZCBpbW1lZGlhdGUgcGFyZW50IGZvbGRlciBuYW1lcyBpbiB0aGUgY29uZmlndXJlZCBwcm9wZXJ0eSB3aGVuIHBhcmVudCBmb2xkZXJzIGFyZSByZW5hbWVkLidcclxuICAgICAgICApXHJcbiAgICAgICAgLmFkZFRleHQodGV4dCA9PlxyXG4gICAgICAgICAgdGV4dFxyXG5cclxuICAgICAgICAgICAgLnNldFBsYWNlaG9sZGVyKCdJbmRleCcpXHJcbiAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy50cmFja0ZvbGRlclJlbmFtZXMpXHJcbiAgICAgICAgICAgIC5vbkNoYW5nZSh2YWx1ZSA9PiB7XHJcbiAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MudHJhY2tGb2xkZXJSZW5hbWVzID0gdmFsdWU7XHJcbiAgICAgICAgICAgICAgc2F2ZVNldHRpbmdzKCk7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgIH0pO1xyXG5cclxuICB9XHJcbn1cclxuIiwgImltcG9ydCB7IEFwcCwgc3RyaW5naWZ5WWFtbCwgcGFyc2VZYW1sIH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5pbXBvcnQgeyBGaWxlTmFtZUhpc3RvcnlTZXR0aW5ncyB9IGZyb20gJy4uL3NldHRpbmdzJztcclxuXHJcbmV4cG9ydCBjbGFzcyBIaXN0b3J5UHJvY2Vzc29yIHtcclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgYXBwOiBBcHAsXHJcbiAgICBwcml2YXRlIHNldHRpbmdzOiBGaWxlTmFtZUhpc3RvcnlTZXR0aW5nc1xyXG4gICkgeyB9XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgcHJvY2Vzc0FsaWFzZXNNYW51YWxseShwYXRoOiBzdHJpbmcsIHF1ZXVlOiBTZXQ8c3RyaW5nPik6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgY29uc3QgZmlsZSA9IHRoaXMuYXBwLnZhdWx0LmdldEZpbGVCeVBhdGgocGF0aCk7XHJcbiAgICBpZiAoIWZpbGUpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHJlZ2V4ZXM6IFJlZ0V4cFtdID0gW107XHJcbiAgICBmb3IgKGNvbnN0IHJlZ2V4U3RyIG9mIHRoaXMuc2V0dGluZ3MuaWdub3JlUmVnZXhlcykge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIHJlZ2V4ZXMucHVzaChuZXcgUmVnRXhwKHJlZ2V4U3RyKSk7XHJcbiAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICBjb25zb2xlLmVycm9yKGBJbnZhbGlkIGlnbm9yZSByZWdleDogJHtyZWdleFN0cn1gLCBlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHRvQWRkOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgY29uc3QgY3VycmVudEJhc2VuYW1lID0gZmlsZS5iYXNlbmFtZTtcclxuICAgIGNvbnN0IGN1cnJlbnRCYXNlbmFtZUxvd2VyID0gY3VycmVudEJhc2VuYW1lLnRvTG93ZXJDYXNlKCk7XHJcblxyXG4gICAgZm9yIChjb25zdCBuYW1lIG9mIHF1ZXVlKSB7XHJcbiAgICAgIGlmIChyZWdleGVzLnNvbWUocmUgPT4gcmUudGVzdChuYW1lKSkpIHtcclxuICAgICAgICBjb250aW51ZTtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCBuYW1lTG93ZXIgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XHJcbiAgICAgIGlmIChcclxuICAgICAgICAodGhpcy5zZXR0aW5ncy5jYXNlU2Vuc2l0aXZlICYmIG5hbWUgPT09IGN1cnJlbnRCYXNlbmFtZSkgfHxcclxuICAgICAgICAoIXRoaXMuc2V0dGluZ3MuY2FzZVNlbnNpdGl2ZSAmJiBuYW1lTG93ZXIgPT09IGN1cnJlbnRCYXNlbmFtZUxvd2VyKVxyXG4gICAgICApIHtcclxuICAgICAgICBjb250aW51ZTtcclxuICAgICAgfVxyXG4gICAgICB0b0FkZC5wdXNoKG5hbWUpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0b0FkZC5sZW5ndGggPT09IDApIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFJlYWQgZmlsZSBjb250ZW50XHJcbiAgICBsZXQgY29udGVudCA9IGF3YWl0IHRoaXMuYXBwLnZhdWx0LnJlYWQoZmlsZSk7XHJcblxyXG4gICAgLy8gUGFyc2UgZnJvbnRtYXR0ZXJcclxuICAgIGNvbnN0IGZyb250bWF0dGVyUmVnZXggPSAvXi0tLVxcbihbXFxzXFxTXSo/KVxcbi0tLVxcbi87XHJcbiAgICBjb25zdCBtYXRjaCA9IGNvbnRlbnQubWF0Y2goZnJvbnRtYXR0ZXJSZWdleCk7XHJcblxyXG4gICAgbGV0IGZyb250bWF0dGVyOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xyXG4gICAgbGV0IGZyb250bWF0dGVyVGV4dCA9ICcnO1xyXG4gICAgbGV0IGJvZHlDb250ZW50ID0gY29udGVudDtcclxuXHJcbiAgICBpZiAobWF0Y2gpIHtcclxuICAgICAgZnJvbnRtYXR0ZXJUZXh0ID0gbWF0Y2hbMV07XHJcbiAgICAgIGJvZHlDb250ZW50ID0gY29udGVudC5zbGljZShtYXRjaFswXS5sZW5ndGgpO1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlWWFtbChmcm9udG1hdHRlclRleHQpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgbnVsbCB8IHVuZGVmaW5lZDtcclxuICAgICAgICBmcm9udG1hdHRlciA9IHBhcnNlZCAmJiB0eXBlb2YgcGFyc2VkID09PSAnb2JqZWN0JyA/IHBhcnNlZCA6IHt9O1xyXG4gICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgcGFyc2luZyBwcm9wZXJ0aWVzOmAsIGUpO1xyXG4gICAgICAgIGZyb250bWF0dGVyID0ge307XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGJvZHlDb250ZW50ID0gY29udGVudDtcclxuICAgIH1cclxuXHJcbiAgICAvLyBHZXQgb3IgY3JlYXRlIGFsaWFzZXMgYXJyYXlcclxuICAgIGxldCBhbGlhc2VzID0gZnJvbnRtYXR0ZXJbdGhpcy5zZXR0aW5ncy5oaXN0b3J5UHJvcGVydHlOYW1lXTtcclxuICAgIGlmICghQXJyYXkuaXNBcnJheShhbGlhc2VzKSkge1xyXG4gICAgICBjb25zdCBoYXNGcm9udG1hdHRlciA9IE9iamVjdC5rZXlzKGZyb250bWF0dGVyKS5sZW5ndGggPiAwO1xyXG4gICAgICBpZiAoaGFzRnJvbnRtYXR0ZXIgJiYgIXRoaXMuc2V0dGluZ3MuYXV0b0NyZWF0ZUZyb250bWF0dGVyKSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIGFsaWFzZXMgPSBbXTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBhbGlhc2VzQXJyYXkgPSBhbGlhc2VzIGFzIHN0cmluZ1tdO1xyXG4gICAgY29uc3QgZXhpc3RpbmcgPSBuZXcgU2V0PHN0cmluZz4oXHJcbiAgICAgIHRoaXMuc2V0dGluZ3MuY2FzZVNlbnNpdGl2ZSA/IGFsaWFzZXNBcnJheSA6IGFsaWFzZXNBcnJheS5tYXAoKGE6IHN0cmluZykgPT4gYS50b0xvd2VyQ2FzZSgpKVxyXG4gICAgKTtcclxuXHJcbiAgICBsZXQgYWRkZWQgPSBmYWxzZTtcclxuICAgIGZvciAoY29uc3QgbmFtZSBvZiB0b0FkZCkge1xyXG4gICAgICBjb25zdCBjaGVja05hbWUgPSB0aGlzLnNldHRpbmdzLmNhc2VTZW5zaXRpdmUgPyBuYW1lIDogbmFtZS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICBpZiAoIWV4aXN0aW5nLmhhcyhjaGVja05hbWUpKSB7XHJcbiAgICAgICAgYWxpYXNlc0FycmF5LnB1c2gobmFtZSk7XHJcbiAgICAgICAgZXhpc3RpbmcuYWRkKGNoZWNrTmFtZSk7XHJcbiAgICAgICAgYWRkZWQgPSB0cnVlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFhZGRlZCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gVXBkYXRlIGZyb250bWF0dGVyXHJcbiAgICBmcm9udG1hdHRlclt0aGlzLnNldHRpbmdzLmhpc3RvcnlQcm9wZXJ0eU5hbWVdID0gYWxpYXNlc0FycmF5O1xyXG5cclxuICAgIC8vIFN0cmluZ2lmeSBmcm9udG1hdHRlclxyXG4gICAgY29uc3QgbmV3RnJvbnRtYXR0ZXJUZXh0ID0gc3RyaW5naWZ5WWFtbChmcm9udG1hdHRlcikudHJpbSgpO1xyXG5cclxuICAgIC8vIFJlY29uc3RydWN0IGZpbGUgY29udGVudFxyXG4gICAgY29uc3QgbmV3Q29udGVudCA9IGAtLS1cXG4ke25ld0Zyb250bWF0dGVyVGV4dH1cXG4tLS1cXG4ke2JvZHlDb250ZW50fWA7XHJcblxyXG4gICAgLy8gV3JpdGUgYmFjayB0byBmaWxlXHJcbiAgICBhd2FpdCB0aGlzLmFwcC52YXVsdC5tb2RpZnkoZmlsZSwgbmV3Q29udGVudCk7XHJcbiAgfVxyXG5cclxuICBhc3luYyBwcm9jZXNzQWxpYXNlcyhwYXRoOiBzdHJpbmcsIHF1ZXVlOiBTZXQ8c3RyaW5nPik6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgY29uc3QgZmlsZSA9IHRoaXMuYXBwLnZhdWx0LmdldEZpbGVCeVBhdGgocGF0aCk7XHJcbiAgICBpZiAoIWZpbGUpIHJldHVybjtcclxuXHJcbiAgICBjb25zdCByZWdleGVzOiBSZWdFeHBbXSA9IFtdO1xyXG4gICAgZm9yIChjb25zdCByZWdleFN0ciBvZiB0aGlzLnNldHRpbmdzLmlnbm9yZVJlZ2V4ZXMpIHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICByZWdleGVzLnB1c2gobmV3IFJlZ0V4cChyZWdleFN0cikpO1xyXG4gICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihgSW52YWxpZCBpZ25vcmUgcmVnZXg6ICR7cmVnZXhTdHJ9YCwgZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB0b0FkZDogc3RyaW5nW10gPSBbXTtcclxuICAgIGNvbnN0IGN1cnJlbnRCYXNlbmFtZSA9IGZpbGUuYmFzZW5hbWU7XHJcbiAgICBjb25zdCBjdXJyZW50QmFzZW5hbWVMb3dlciA9IGN1cnJlbnRCYXNlbmFtZS50b0xvd2VyQ2FzZSgpO1xyXG5cclxuICAgIGZvciAoY29uc3QgbmFtZSBvZiBxdWV1ZSkge1xyXG4gICAgICBpZiAocmVnZXhlcy5zb21lKHJlID0+IHJlLnRlc3QobmFtZSkpKSB7XHJcbiAgICAgICAgY29udGludWU7XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgbmFtZUxvd2VyID0gbmFtZS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgKHRoaXMuc2V0dGluZ3MuY2FzZVNlbnNpdGl2ZSAmJiBuYW1lID09PSBjdXJyZW50QmFzZW5hbWUpIHx8XHJcbiAgICAgICAgKCF0aGlzLnNldHRpbmdzLmNhc2VTZW5zaXRpdmUgJiYgbmFtZUxvd2VyID09PSBjdXJyZW50QmFzZW5hbWVMb3dlcilcclxuICAgICAgKSB7XHJcbiAgICAgICAgY29udGludWU7XHJcbiAgICAgIH1cclxuICAgICAgdG9BZGQucHVzaChuYW1lKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodG9BZGQubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBVc2UgbWFudWFsIHByb2Nlc3NpbmcgZm9yIG5vbi1tZCBmaWxlcywgb3IgYXMgZmFsbGJhY2tcclxuICAgIGlmIChmaWxlLmV4dGVuc2lvbiAhPT0gJ21kJykge1xyXG4gICAgICBhd2FpdCB0aGlzLnByb2Nlc3NBbGlhc2VzTWFudWFsbHkocGF0aCwgcXVldWUpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgYXdhaXQgdGhpcy5hcHAuZmlsZU1hbmFnZXIucHJvY2Vzc0Zyb250TWF0dGVyKGZpbGUsIChmbTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHtcclxuICAgICAgbGV0IGFsaWFzZXMgPSBmbVt0aGlzLnNldHRpbmdzLmhpc3RvcnlQcm9wZXJ0eU5hbWVdO1xyXG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkoYWxpYXNlcykpIHtcclxuICAgICAgICAvLyBJZiB0aGVyZSdzIG5vIGZyb250bWF0dGVyIGF0IGFsbCwgd2UgbmVlZCB0byBjcmVhdGUgaXQgdG8gYWRkIGFsaWFzZXNcclxuICAgICAgICAvLyBJZiB0aGVyZSdzIGZyb250bWF0dGVyIGJ1dCBubyBhbGlhc2VzIHByb3BlcnR5LCByZXNwZWN0IHRoZSBhdXRvQ3JlYXRlRnJvbnRtYXR0ZXIgc2V0dGluZ1xyXG4gICAgICAgIGNvbnN0IGhhc0Zyb250bWF0dGVyID0gT2JqZWN0LmtleXMoZm0pLmxlbmd0aCA+IDA7XHJcbiAgICAgICAgaWYgKGhhc0Zyb250bWF0dGVyICYmICF0aGlzLnNldHRpbmdzLmF1dG9DcmVhdGVGcm9udG1hdHRlcikge1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICBhbGlhc2VzID0gW107XHJcbiAgICAgICAgZm1bdGhpcy5zZXR0aW5ncy5oaXN0b3J5UHJvcGVydHlOYW1lXSA9IGFsaWFzZXM7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IGFsaWFzZXNBcnJheSA9IGFsaWFzZXMgYXMgc3RyaW5nW107XHJcbiAgICAgIGNvbnN0IGV4aXN0aW5nID0gbmV3IFNldDxzdHJpbmc+KFxyXG4gICAgICAgIHRoaXMuc2V0dGluZ3MuY2FzZVNlbnNpdGl2ZSA/IGFsaWFzZXNBcnJheSA6IGFsaWFzZXNBcnJheS5tYXAoKGE6IHN0cmluZykgPT4gYS50b0xvd2VyQ2FzZSgpKVxyXG4gICAgICApO1xyXG5cclxuICAgICAgZm9yIChjb25zdCBuYW1lIG9mIHRvQWRkKSB7XHJcbiAgICAgICAgY29uc3QgY2hlY2tOYW1lID0gdGhpcy5zZXR0aW5ncy5jYXNlU2Vuc2l0aXZlID8gbmFtZSA6IG5hbWUudG9Mb3dlckNhc2UoKTtcclxuICAgICAgICBpZiAoIWV4aXN0aW5nLmhhcyhjaGVja05hbWUpKSB7XHJcbiAgICAgICAgICBhbGlhc2VzQXJyYXkucHVzaChuYW1lKTtcclxuICAgICAgICAgIGV4aXN0aW5nLmFkZChjaGVja05hbWUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG59XHJcbiIsICJleHBvcnQgZnVuY3Rpb24gZ2V0QmFzZW5hbWUocGF0aDogc3RyaW5nKTogc3RyaW5nIHtcclxuICBjb25zdCBuYW1lID0gcGF0aC5zcGxpdCgnLycpLnBvcCgpIHx8ICcnO1xyXG4gIHJldHVybiBuYW1lLnJlcGxhY2UoL1xcLlteLy5dKyQvLCAnJyk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRJbW1lZGlhdGVQYXJlbnROYW1lKHBhdGg6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgY29uc3QgcGFydHMgPSBwYXRoLnNwbGl0KCcvJyk7XHJcbiAgcGFydHMucG9wKCk7IC8vIFJlbW92ZSBmaWxlIG5hbWVcclxuICByZXR1cm4gcGFydHMucG9wKCkgfHwgJyc7IC8vIEdldCBpbW1lZGlhdGUgcGFyZW50IGZvbGRlciBuYW1lIG9yICcnIGlmIHJvb3RcclxufVxyXG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFB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QUFNLGtCQUFrQixLQUFLLFNBQVMsZ0JBQ2xDLG9CQUFvQixLQUFLLFNBQVMscUJBQ2xDLGdCQUFnQixZQUFZLE1BQU0sS0FBSyxTQUFTLG1CQUFtQixZQUFZO0FBRW5GLFVBQUksQ0FBQyxpQkFBaUI7QUFDcEI7QUFBQSxNQUNGO0FBRUEsVUFBSSwyQkFBMkIsTUFBTSwyQkFBMkIsSUFBSTtBQUNsRTtBQUFBLE1BQ0Y7QUFDQSxVQUFJLFFBQVEsS0FBSyxRQUFNLEdBQUcsS0FBSyxzQkFBc0IsS0FBSyxHQUFHLEtBQUssc0JBQXNCLENBQUMsR0FBRztBQUMxRjtBQUFBLE1BQ0Y7QUFDQSxnQkFBVTtBQUFBLElBQ1o7QUFFQSxRQUFJLENBQUMsUUFBUztBQUlkLFFBQUksZ0JBQWdCLEtBQUssWUFBWSxJQUFJLFFBQVEsSUFBSTtBQUNyRCxRQUFJLENBQUMsZUFBZTtBQUVsQixzQkFBZ0IsS0FBSyxZQUFZLElBQUksT0FBTztBQUM1QyxVQUFJLGVBQWU7QUFFakIsYUFBSyxZQUFZLE9BQU8sT0FBTztBQUFBLE1BQ2pDO0FBQUEsSUFDRjtBQUVBLFFBQUksZUFBZTtBQUVqQixVQUFJLGNBQWMsY0FBYyxHQUFHO0FBQ2pDLGVBQU8sYUFBYSxjQUFjLFNBQVM7QUFBQSxNQUM3QztBQUdBLGdCQUFVLE1BQU0sS0FBSyxjQUFjLEtBQUssRUFBRSxDQUFDO0FBQUEsSUFDN0M7QUFHQSxVQUFNLFFBQVE7QUFBQSxNQUNaLE9BQU8sb0JBQUksSUFBWSxDQUFDLE9BQU8sQ0FBQztBQUFBLE1BQ2hDLFdBQVc7QUFBQSxNQUNYLGFBQWEsUUFBUTtBQUFBLElBQ3ZCO0FBR0EsVUFBTSxZQUFZLE9BQU8sV0FBVyxNQUFNO0FBQ3hDLFlBQU0sWUFBWTtBQUNoQixZQUFJO0FBQ0YsZ0JBQU0sS0FBSyxpQkFBaUIsZUFBZSxNQUFNLGFBQWEsTUFBTSxLQUFLO0FBQUEsUUFDM0UsU0FBUyxPQUFPO0FBQ2Qsa0JBQVEsTUFBTSw2QkFBNkIsS0FBSztBQUFBLFFBQ2xEO0FBQ0EsYUFBSyxZQUFZLE9BQU8sTUFBTSxXQUFXO0FBQUEsTUFDM0MsR0FBRztBQUFBLElBQ0wsR0FBRyxLQUFLLFNBQVMsaUJBQWlCLEdBQUk7QUFFdEMsU0FBSyxZQUFZLElBQUksUUFBUSxNQUFNLEtBQUs7QUFBQSxFQUMxQztBQUNGOyIsCiAgIm5hbWVzIjogWyJpbXBvcnRfb2JzaWRpYW4iLCAiaW1wb3J0X29ic2lkaWFuIl0KfQo=