mirror of
https://github.com/mildeveloper/obsidian-date-range-expander.git
synced 2026-07-22 12:20:32 +00:00
642 lines
83 KiB
JavaScript
642 lines
83 KiB
JavaScript
/*
|
|
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: () => DateRangeExpanderPlugin
|
|
});
|
|
module.exports = __toCommonJS(main_exports);
|
|
var import_obsidian4 = require("obsidian");
|
|
|
|
// src/dateInputModal.ts
|
|
var import_obsidian = require("obsidian");
|
|
|
|
// src/dateUtils.ts
|
|
var DateUtils = class {
|
|
getStartAndEndDates(modalResponse) {
|
|
let startDate = modalResponse.startDate;
|
|
let endDate;
|
|
if (modalResponse.rangeType === "EndDate") {
|
|
endDate = modalResponse.endDate;
|
|
} else {
|
|
endDate = new Date(startDate);
|
|
const duration = modalResponse.duration;
|
|
const unit = modalResponse.durationUnit;
|
|
switch (unit) {
|
|
case "Days":
|
|
endDate.setDate(startDate.getDate() + duration - 1);
|
|
break;
|
|
case "Weeks":
|
|
endDate.setDate(startDate.getDate() + duration * 7 - 1);
|
|
break;
|
|
case "Months":
|
|
endDate = this.addMonthsToDate(startDate, duration);
|
|
break;
|
|
}
|
|
}
|
|
if (startDate > endDate) {
|
|
return null;
|
|
}
|
|
const dateStartAndEnd = {
|
|
startDate,
|
|
endDate
|
|
};
|
|
return dateStartAndEnd;
|
|
}
|
|
// Assuming string date is in format: YYYYMMDD
|
|
parseDateFromString(dateString) {
|
|
if (!this.isValidNumericDate(dateString)) {
|
|
return null;
|
|
}
|
|
const year = parseInt(dateString.substring(0, 4));
|
|
const month = parseInt(dateString.substring(4, 6)) - 1;
|
|
const day = parseInt(dateString.substring(6, 8));
|
|
const date = new Date(Date.UTC(year, month, day));
|
|
return date;
|
|
}
|
|
// Returns true if string date is in format: YYYYMMDD
|
|
isValidNumericDate(dateString) {
|
|
if (!/^\d{8}$/.test(dateString))
|
|
return false;
|
|
const year = parseInt(dateString.substring(0, 4));
|
|
const month = parseInt(dateString.substring(4, 6)) - 1;
|
|
const day = parseInt(dateString.substring(6, 8));
|
|
if (year < 1900)
|
|
return false;
|
|
if (month < 0 || month > 11)
|
|
return false;
|
|
if (day < 1 || day > 31)
|
|
return false;
|
|
const dateObj = new Date(year, month, day);
|
|
return dateObj.getFullYear() === year && dateObj.getMonth() === month && dateObj.getDate() === day;
|
|
}
|
|
formatDateToString(date, settingsFormat, defaultFormat) {
|
|
const year = date.getFullYear();
|
|
const month = date.getMonth();
|
|
const day = date.getDate();
|
|
const weekday = date.getDay();
|
|
const dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
const dayAbbreviations = dayNames.map((day2) => day2.slice(0, 3));
|
|
const monthAbbreviations = monthNames.map((month2) => month2.slice(0, 3));
|
|
const formatDate = (format) => {
|
|
return format.replace(/YYYY|YYY|YY|Y|MMMM|MMM|MM|M|DDDD|DDD|DD|D/g, (match) => {
|
|
switch (match) {
|
|
case "YYYY":
|
|
return year.toString();
|
|
case "YYY":
|
|
return year.toString().slice(-3);
|
|
case "YY":
|
|
return year.toString().slice(-2);
|
|
case "Y":
|
|
return year.toString().slice(-1);
|
|
case "MMMM":
|
|
return monthNames[month];
|
|
case "MMM":
|
|
return monthAbbreviations[month];
|
|
case "MM":
|
|
return (month + 1).toString().padStart(2, "0");
|
|
case "M":
|
|
return (month + 1).toString();
|
|
case "DDDD":
|
|
return dayNames[weekday];
|
|
case "DDD":
|
|
return dayAbbreviations[weekday];
|
|
case "DD":
|
|
return day.toString().padStart(2, "0");
|
|
case "D":
|
|
return day.toString();
|
|
default:
|
|
return match;
|
|
}
|
|
});
|
|
};
|
|
try {
|
|
return formatDate(settingsFormat);
|
|
} catch (error) {
|
|
return formatDate(defaultFormat);
|
|
}
|
|
}
|
|
addMonthsToDate(date, months) {
|
|
if (months === 0) {
|
|
return date;
|
|
}
|
|
const newDate = new Date(date);
|
|
const currentDay = date.getDate();
|
|
newDate.setMonth(newDate.getMonth() + months);
|
|
newDate.setDate(newDate.getDate() - 1);
|
|
if (newDate.getMonth() !== date.getMonth() && newDate.getDate() !== currentDay - 1) {
|
|
newDate.setDate(0);
|
|
}
|
|
return newDate;
|
|
}
|
|
calculateDaysInRange(startDate, endDate) {
|
|
const millisecondsInDay = 1e3 * 60 * 60 * 24;
|
|
const differenceMilliseconds = endDate.getTime() - startDate.getTime();
|
|
const differenceDays = Math.floor(differenceMilliseconds / millisecondsInDay) + 1;
|
|
return Math.max(0, differenceDays);
|
|
}
|
|
};
|
|
|
|
// src/dateInputModal.ts
|
|
var DateInputModal = class extends import_obsidian.Modal {
|
|
constructor(app, onSubmit) {
|
|
super(app);
|
|
this.startDateValue = "";
|
|
this.endDateValue = "";
|
|
this.durationValue = "";
|
|
this.durationTypeValue = "Days";
|
|
this.useCalloutValue = true;
|
|
this.rangeTypeValue = "EndDate";
|
|
this.submitButton = null;
|
|
this.onSubmit = onSubmit;
|
|
this.dateUtils = new DateUtils();
|
|
this.setTitle("Enter date range");
|
|
}
|
|
onOpen() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
this.addStyles();
|
|
this.setupKeyboardListener();
|
|
this.createStartDateInput();
|
|
this.createRangeOptions();
|
|
this.createCalloutToggle();
|
|
this.createSubmitButton();
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
if (this.keyboardListener) {
|
|
contentEl.removeEventListener("keydown", this.keyboardListener);
|
|
}
|
|
contentEl.empty();
|
|
}
|
|
validateInput() {
|
|
const startDateObj = this.dateUtils.parseDateFromString(this.startDateValue);
|
|
if (!startDateObj) {
|
|
return false;
|
|
}
|
|
if (this.rangeTypeValue === "EndDate") {
|
|
const endDateObj = this.dateUtils.parseDateFromString(this.endDateValue);
|
|
return !!endDateObj && this.dateUtils.isValidNumericDate(this.endDateValue) && endDateObj >= startDateObj;
|
|
} else {
|
|
return this.durationValue !== "" && parseInt(this.durationValue) > 0 && ["Days", "Weeks", "Months"].includes(this.durationTypeValue);
|
|
}
|
|
}
|
|
calculateDateCount() {
|
|
const startDate = this.dateUtils.parseDateFromString(this.startDateValue);
|
|
if (!startDate) {
|
|
return 0;
|
|
}
|
|
let endDate;
|
|
if (this.rangeTypeValue === "EndDate") {
|
|
endDate = this.dateUtils.parseDateFromString(this.endDateValue) || startDate;
|
|
} else {
|
|
endDate = new Date(startDate);
|
|
const duration = parseInt(this.durationValue) || 0;
|
|
if (this.durationTypeValue === "Days") {
|
|
endDate.setDate(endDate.getDate() + duration - 1);
|
|
} else if (this.durationTypeValue === "Weeks") {
|
|
endDate.setDate(endDate.getDate() + duration * 7 - 1);
|
|
} else if (this.durationTypeValue === "Months") {
|
|
endDate = this.dateUtils.addMonthsToDate(startDate, duration);
|
|
}
|
|
}
|
|
const dateCount = this.dateUtils.calculateDaysInRange(startDate, endDate);
|
|
return dateCount;
|
|
}
|
|
addStyles() {
|
|
const styleEl = document.createElement("style");
|
|
styleEl.textContent = `
|
|
.date-option-container {
|
|
margin-bottom: 15px;
|
|
}
|
|
.date-input-row {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 10px;
|
|
}
|
|
.date-input-row input[type="radio"] {
|
|
margin-right: 8px;
|
|
}
|
|
.date-input-row input[type="text"],
|
|
.date-input-row input[type="number"] {
|
|
margin-left: 5px;
|
|
}
|
|
.date-input-row select {
|
|
margin-left: 5px;
|
|
}
|
|
`;
|
|
this.contentEl.appendChild(styleEl);
|
|
}
|
|
setupKeyboardListener() {
|
|
this.keyboardListener = (event) => {
|
|
if (event.key === "Enter" && this.validateInput()) {
|
|
this.submit();
|
|
}
|
|
};
|
|
this.contentEl.addEventListener("keydown", this.keyboardListener);
|
|
}
|
|
createStartDateInput() {
|
|
new import_obsidian.Setting(this.contentEl).setName("Start date").addText((text) => {
|
|
text.setPlaceholder("YYYYMMDD").setValue(this.startDateValue);
|
|
text.inputEl.setAttribute("pattern", "[0-9]*");
|
|
text.inputEl.setAttribute("maxlength", "8");
|
|
text.inputEl.addEventListener("input", (e) => {
|
|
const input = e.target;
|
|
input.value = input.value.replace(/\D/g, "").slice(0, 8);
|
|
this.startDateValue = input.value;
|
|
this.updateSubmitButton();
|
|
});
|
|
});
|
|
}
|
|
createRangeOptions() {
|
|
const optionContainer = this.contentEl.createEl("div", { cls: "date-option-container" });
|
|
this.createEndDateOption(optionContainer);
|
|
this.createDurationOption(optionContainer);
|
|
this.updateInputStates();
|
|
}
|
|
createEndDateOption(container) {
|
|
const endDateRow = container.createEl("div", { cls: "date-input-row" });
|
|
const endDateLabel = endDateRow.createEl("label");
|
|
endDateLabel.appendText("End date");
|
|
const endDateRadio = endDateLabel.createEl("input", {
|
|
type: "radio",
|
|
attr: { name: "dateOption" }
|
|
});
|
|
endDateRadio.checked = this.rangeTypeValue === "EndDate";
|
|
this.endDateInput = endDateRow.createEl("input", {
|
|
type: "text",
|
|
placeholder: "YYYYMMDD",
|
|
value: this.endDateValue,
|
|
attr: {
|
|
pattern: "[0-9]*",
|
|
maxlength: "8"
|
|
}
|
|
});
|
|
this.endDateInput.addEventListener("input", (e) => {
|
|
const input = e.target;
|
|
input.value = input.value.replace(/\D/g, "").slice(0, 8);
|
|
this.endDateValue = input.value;
|
|
this.updateSubmitButton();
|
|
});
|
|
endDateRadio.addEventListener("change", () => {
|
|
this.rangeTypeValue = "EndDate";
|
|
this.updateInputStates();
|
|
this.updateSubmitButton();
|
|
});
|
|
}
|
|
createDurationOption(container) {
|
|
const durationRow = container.createEl("div", { cls: "date-input-row" });
|
|
const durationLabel = durationRow.createEl("label");
|
|
durationLabel.appendText("Duration");
|
|
const durationRadio = durationLabel.createEl("input", {
|
|
type: "radio",
|
|
attr: { name: "dateOption" }
|
|
});
|
|
durationRadio.checked = this.rangeTypeValue === "Duration";
|
|
this.durationInput = durationRow.createEl("input", {
|
|
type: "number",
|
|
attr: {
|
|
min: "1",
|
|
max: "100"
|
|
},
|
|
placeholder: "1-100",
|
|
value: this.durationValue
|
|
});
|
|
this.durationTypeSelect = durationRow.createEl("select");
|
|
this.populateDurationTypes();
|
|
durationRadio.addEventListener("change", () => {
|
|
this.rangeTypeValue = "Duration";
|
|
this.updateInputStates();
|
|
this.updateSubmitButton();
|
|
});
|
|
this.durationInput.addEventListener("input", (e) => {
|
|
const input = e.target;
|
|
let value = parseInt(input.value);
|
|
if (value > 100) {
|
|
value = 100;
|
|
input.value = "100";
|
|
}
|
|
this.durationValue = value.toString();
|
|
this.updateSubmitButton();
|
|
});
|
|
this.durationTypeSelect.addEventListener("change", (e) => {
|
|
this.durationTypeValue = e.target.value;
|
|
this.updateSubmitButton();
|
|
});
|
|
}
|
|
populateDurationTypes() {
|
|
["Days", "Weeks", "Months"].forEach((type) => {
|
|
const option = this.durationTypeSelect.createEl("option", {
|
|
value: type,
|
|
text: type
|
|
});
|
|
option.selected = type === this.durationTypeValue;
|
|
});
|
|
}
|
|
updateInputStates() {
|
|
const isEndDateMode = this.rangeTypeValue === "EndDate";
|
|
this.endDateInput.disabled = !isEndDateMode;
|
|
this.durationInput.disabled = isEndDateMode;
|
|
this.durationTypeSelect.disabled = isEndDateMode;
|
|
}
|
|
createCalloutToggle() {
|
|
new import_obsidian.Setting(this.contentEl).setName("Add to callout").setDesc("Insert dates inside a collapsed callout").addToggle(
|
|
(toggle) => toggle.setValue(this.useCalloutValue).onChange((value) => {
|
|
this.useCalloutValue = value;
|
|
})
|
|
);
|
|
}
|
|
createSubmitButton() {
|
|
this.submitButton = new import_obsidian.Setting(this.contentEl).addButton(
|
|
(btn) => btn.setButtonText("Insert").setCta().onClick(() => this.submit())
|
|
).settingEl.querySelector("button");
|
|
if (this.submitButton) {
|
|
this.submitButton.disabled = true;
|
|
}
|
|
}
|
|
updateSubmitButton() {
|
|
if (this.submitButton) {
|
|
const validInput = this.validateInput();
|
|
this.submitButton.disabled = !validInput;
|
|
if (validInput) {
|
|
const dateCount = this.calculateDateCount();
|
|
this.submitButton.textContent = `Insert ${dateCount} Date${dateCount !== 1 ? "s" : ""}`;
|
|
} else {
|
|
this.submitButton.textContent = "Insert";
|
|
}
|
|
}
|
|
}
|
|
submit() {
|
|
if (!this.validateInput()) {
|
|
return;
|
|
}
|
|
const startDateObj = this.dateUtils.parseDateFromString(this.startDateValue);
|
|
if (!startDateObj) {
|
|
return;
|
|
}
|
|
const dateRangeValues = {
|
|
startDate: startDateObj,
|
|
rangeType: this.rangeTypeValue,
|
|
useCallout: this.useCalloutValue
|
|
};
|
|
if (this.rangeTypeValue === "EndDate") {
|
|
const endDateObj = this.dateUtils.parseDateFromString(this.endDateValue);
|
|
if (endDateObj)
|
|
dateRangeValues.endDate = endDateObj;
|
|
} else {
|
|
dateRangeValues.duration = parseInt(this.durationValue);
|
|
dateRangeValues.durationUnit = this.durationTypeValue;
|
|
}
|
|
this.close();
|
|
if (this.onSubmit) {
|
|
this.onSubmit(dateRangeValues);
|
|
}
|
|
}
|
|
};
|
|
|
|
// src/types.ts
|
|
var DEFAULT_SETTINGS = {
|
|
outputDateFormat: "YYYY.MM.DD",
|
|
friendlyDateFormat: "DDD D MMM YYYY",
|
|
dateSeparator: ", ",
|
|
createWikiLinks: true,
|
|
createNonExistentFiles: "same-folder",
|
|
customFolderPath: ""
|
|
};
|
|
|
|
// src/settingsTab.ts
|
|
var import_obsidian2 = require("obsidian");
|
|
var DateRangeExpanderSettingTab = class extends import_obsidian2.PluginSettingTab {
|
|
constructor(app, plugin) {
|
|
super(app, plugin);
|
|
this.plugin = plugin;
|
|
}
|
|
display() {
|
|
const { containerEl } = this;
|
|
containerEl.empty();
|
|
this.createDateFormatSettings();
|
|
this.createWikiLinkSettings();
|
|
}
|
|
createDateFormatSettings() {
|
|
new import_obsidian2.Setting(this.containerEl).setName("Output date format").setDesc(`Format for output dates (e.g., ${DEFAULT_SETTINGS.outputDateFormat})`).addText((text) => text.setPlaceholder(DEFAULT_SETTINGS.outputDateFormat).setValue(this.plugin.settings.outputDateFormat).onChange(async (value) => {
|
|
this.plugin.settings.outputDateFormat = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian2.Setting(this.containerEl).setName("Friendly date format").setDesc(`Format for friendly date display (e.g., ${DEFAULT_SETTINGS.friendlyDateFormat}). Supports D, DD, DDD, DDDD, M, MM, MMM, MMMM, Y, YY, YYY, YYYYM.`).addText((text) => text.setPlaceholder(DEFAULT_SETTINGS.friendlyDateFormat).setValue(this.plugin.settings.friendlyDateFormat).onChange(async (value) => {
|
|
this.plugin.settings.friendlyDateFormat = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian2.Setting(this.containerEl).setName("Date separator").setDesc(`Separator between dates (e.g., "${DEFAULT_SETTINGS.dateSeparator}")`).addText((text) => text.setPlaceholder(DEFAULT_SETTINGS.dateSeparator).setValue(this.plugin.settings.dateSeparator).onChange(async (value) => {
|
|
this.plugin.settings.dateSeparator = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
}
|
|
createWikiLinkSettings() {
|
|
new import_obsidian2.Setting(this.containerEl).setName("Create wiki links").setDesc("Create wiki links for inserted dates").addToggle((toggle) => toggle.setValue(this.plugin.settings.createWikiLinks).onChange(async (value) => {
|
|
this.plugin.settings.createWikiLinks = value;
|
|
await this.plugin.saveSettings();
|
|
this.display();
|
|
}));
|
|
if (this.plugin.settings.createWikiLinks) {
|
|
this.createNonExistentFilesSettings();
|
|
}
|
|
}
|
|
createNonExistentFilesSettings() {
|
|
new import_obsidian2.Setting(this.containerEl).setName("Create non-existent files").setDesc("What to do if a wiki linked file does not exist").addDropdown((dropdown) => dropdown.addOption("do-not-create", "Do not create").addOption("same-folder", "Create in same folder").addOption("custom-folder", "Create in custom folder").setValue(this.plugin.settings.createNonExistentFiles).onChange(async (value) => {
|
|
this.plugin.settings.createNonExistentFiles = value;
|
|
await this.plugin.saveSettings();
|
|
this.display();
|
|
}));
|
|
if (this.plugin.settings.createNonExistentFiles === "custom-folder") {
|
|
this.createCustomFolderPathSetting();
|
|
}
|
|
}
|
|
createCustomFolderPathSetting() {
|
|
new import_obsidian2.Setting(this.containerEl).setName("Custom folder path").setDesc('Path to the folder where new files should be created (e.g., "Daily Notes/2025")').addText((text) => {
|
|
text.setPlaceholder("Enter folder path").setValue(this.plugin.settings.customFolderPath || "").onChange(async (value) => {
|
|
this.plugin.settings.customFolderPath = value;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/dateRangeExpander.ts
|
|
var import_obsidian3 = require("obsidian");
|
|
var DateRangeExpander = class {
|
|
constructor(app, settings, dateUtils) {
|
|
this.app = app;
|
|
this.settings = settings;
|
|
this.dateUtils = dateUtils;
|
|
}
|
|
wrapInCallout(dateStartAndEnd, insertedDateRange) {
|
|
const [startDateFormat, endDateFormat] = this.getFormatedStartAndEndDates(dateStartAndEnd);
|
|
return `
|
|
> [!SUMMARY]- Date range: ${startDateFormat} to ${endDateFormat}
|
|
> ${insertedDateRange}
|
|
`;
|
|
}
|
|
expandDateRange(dateStartAndEnd) {
|
|
let totalDates = 0;
|
|
let createdFiles = 0;
|
|
let existingFiles = 0;
|
|
let customFolderExists = true;
|
|
let dates = [];
|
|
let current = new Date(dateStartAndEnd.startDate);
|
|
const customFolder = this.app.vault.getAbstractFileByPath(this.settings.customFolderPath);
|
|
if (this.settings.createNonExistentFiles === "custom-folder" && !(customFolder instanceof import_obsidian3.TFolder)) {
|
|
customFolderExists = false;
|
|
}
|
|
while (current <= dateStartAndEnd.endDate) {
|
|
let formattedDate = this.dateUtils.formatDateToString(current, this.settings.outputDateFormat, DEFAULT_SETTINGS.outputDateFormat);
|
|
if (this.settings.createWikiLinks) {
|
|
dates.push(`[[${formattedDate}]]`);
|
|
const fileCreationResult = this.createFileIfNeeded(formattedDate, customFolderExists);
|
|
if (fileCreationResult === "created")
|
|
createdFiles++;
|
|
else if (fileCreationResult === "exists")
|
|
existingFiles++;
|
|
} else {
|
|
dates.push(formattedDate);
|
|
}
|
|
totalDates++;
|
|
current.setDate(current.getDate() + 1);
|
|
}
|
|
if (createdFiles > 0 && !customFolderExists) {
|
|
new import_obsidian3.Notice(`Folder "${this.settings.customFolderPath}" does not exist. Using parent folder to current note instead.`);
|
|
}
|
|
const [startDateFormat, endDateFormat] = this.getFormatedStartAndEndDates(dateStartAndEnd);
|
|
const commonNoticeText = `Inserted ${totalDates} dates from ${startDateFormat} to ${endDateFormat}`;
|
|
if (this.settings.createNonExistentFiles !== "do-not-create") {
|
|
new import_obsidian3.Notice(`${commonNoticeText}
|
|
|
|
\u2022 Files created: ${createdFiles}
|
|
\u2022 Files skipped: ${existingFiles}`, 8e3);
|
|
} else {
|
|
new import_obsidian3.Notice(commonNoticeText, 8e3);
|
|
}
|
|
return dates.join(this.settings.dateSeparator);
|
|
}
|
|
createFileIfNeeded(formattedDate, customFolderExists) {
|
|
const currentFile = this.app.workspace.getActiveFile();
|
|
if (!currentFile || !currentFile.parent) {
|
|
return "failed";
|
|
}
|
|
const fileName = `${formattedDate}.md`;
|
|
const fileExists = this.fileExistsInVault(formattedDate);
|
|
if (!fileExists) {
|
|
let filePath = "";
|
|
switch (this.settings.createNonExistentFiles) {
|
|
case "same-folder":
|
|
const currentDir = currentFile.parent.path;
|
|
filePath = currentDir ? `${currentDir}/${fileName}` : fileName;
|
|
break;
|
|
case "custom-folder":
|
|
if (customFolderExists) {
|
|
filePath = `${this.settings.customFolderPath}/${fileName}`;
|
|
} else {
|
|
const currentDir2 = currentFile.parent.path;
|
|
filePath = currentDir2 ? `${currentDir2}/${fileName}` : fileName;
|
|
}
|
|
break;
|
|
case "do-not-create":
|
|
return "failed";
|
|
default:
|
|
return "failed";
|
|
}
|
|
if (filePath) {
|
|
this.app.vault.create(filePath, "");
|
|
return "created";
|
|
}
|
|
return "failed";
|
|
} else {
|
|
return "exists";
|
|
}
|
|
}
|
|
fileExistsInVault(formattedDate) {
|
|
return this.app.metadataCache.getFirstLinkpathDest(formattedDate, "") !== null;
|
|
}
|
|
getFormatedStartAndEndDates(dateStartAndEnd) {
|
|
const startDateFormat = this.dateUtils.formatDateToString(dateStartAndEnd.startDate, this.settings.friendlyDateFormat, DEFAULT_SETTINGS.friendlyDateFormat);
|
|
const endDateFormat = this.dateUtils.formatDateToString(dateStartAndEnd.endDate, this.settings.friendlyDateFormat, DEFAULT_SETTINGS.friendlyDateFormat);
|
|
return [startDateFormat, endDateFormat];
|
|
}
|
|
};
|
|
|
|
// src/main.ts
|
|
var DateRangeExpanderPlugin = class extends import_obsidian4.Plugin {
|
|
async onload() {
|
|
console.log("DateRangeExpander loaded");
|
|
await this.loadSettings();
|
|
this.dateUtils = new DateUtils();
|
|
this.dateRangeExpander = new DateRangeExpander(this.app, this.settings, this.dateUtils);
|
|
this.addSettingTab(new DateRangeExpanderSettingTab(this.app, this));
|
|
this.addCommand({
|
|
id: "insert-expanded-date-range",
|
|
name: "Insert",
|
|
checkCallback: (checking) => {
|
|
const markdownView = this.app.workspace.getActiveViewOfType(import_obsidian4.MarkdownView);
|
|
if (markdownView) {
|
|
if (!checking) {
|
|
new DateInputModal(this.app, (rangeInput) => {
|
|
const dateStartAndEnd = this.dateUtils.getStartAndEndDates(rangeInput);
|
|
if (dateStartAndEnd) {
|
|
const editor = this.getActiveEditor();
|
|
if (editor) {
|
|
const cursor = editor.getCursor();
|
|
let insertedDateRange = this.dateRangeExpander.expandDateRange(dateStartAndEnd) + " ";
|
|
if (rangeInput.useCallout) {
|
|
insertedDateRange = this.dateRangeExpander.wrapInCallout(dateStartAndEnd, insertedDateRange);
|
|
}
|
|
editor.replaceRange(insertedDateRange, { line: cursor.line, ch: cursor.ch }, cursor);
|
|
const endPos = { line: cursor.line, ch: cursor.ch + insertedDateRange.length };
|
|
editor.setCursor(endPos);
|
|
}
|
|
}
|
|
}).open();
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
async loadSettings() {
|
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
|
}
|
|
async saveSettings() {
|
|
await this.saveData(this.settings);
|
|
}
|
|
onunload() {
|
|
console.log("DateRangeExpander unloaded");
|
|
}
|
|
getActiveEditor() {
|
|
const activeLeaf = this.app.workspace.getActiveViewOfType(import_obsidian4.MarkdownView);
|
|
if (activeLeaf) {
|
|
return activeLeaf.editor;
|
|
}
|
|
return null;
|
|
}
|
|
};
|
|
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL21haW4udHMiLCAic3JjL2RhdGVJbnB1dE1vZGFsLnRzIiwgInNyYy9kYXRlVXRpbHMudHMiLCAic3JjL3R5cGVzLnRzIiwgInNyYy9zZXR0aW5nc1RhYi50cyIsICJzcmMvZGF0ZVJhbmdlRXhwYW5kZXIudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IE1hcmtkb3duVmlldywgUGx1Z2luIH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5pbXBvcnQgeyBEYXRlSW5wdXRNb2RhbCB9IGZyb20gJy4vZGF0ZUlucHV0TW9kYWwnO1xyXG5pbXBvcnQgeyBERUZBVUxUX1NFVFRJTkdTLCBQbHVnaW5TZXR0aW5ncyB9IGZyb20gJy4vdHlwZXMnO1xyXG5pbXBvcnQgeyBEYXRlUmFuZ2VFeHBhbmRlclNldHRpbmdUYWIgfSBmcm9tICcuL3NldHRpbmdzVGFiJztcclxuaW1wb3J0IHsgRGF0ZVV0aWxzIH0gZnJvbSAnLi9kYXRlVXRpbHMnO1xyXG5pbXBvcnQgeyBEYXRlUmFuZ2VFeHBhbmRlciB9IGZyb20gJy4vZGF0ZVJhbmdlRXhwYW5kZXInO1xyXG5cclxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRGF0ZVJhbmdlRXhwYW5kZXJQbHVnaW4gZXh0ZW5kcyBQbHVnaW4ge1xyXG5cdHNldHRpbmdzOiBQbHVnaW5TZXR0aW5ncztcclxuXHRkYXRlUmFuZ2VFeHBhbmRlcjogRGF0ZVJhbmdlRXhwYW5kZXI7XHJcblx0ZGF0ZVV0aWxzOiBEYXRlVXRpbHM7XHJcblxyXG5cdGFzeW5jIG9ubG9hZCgpIHtcclxuXHRcdGNvbnNvbGUubG9nKCdEYXRlUmFuZ2VFeHBhbmRlciBsb2FkZWQnKTtcclxuXHRcdFxyXG5cdFx0YXdhaXQgdGhpcy5sb2FkU2V0dGluZ3MoKTtcclxuXHJcblx0XHR0aGlzLmRhdGVVdGlscyA9IG5ldyBEYXRlVXRpbHMoKTtcclxuXHRcdHRoaXMuZGF0ZVJhbmdlRXhwYW5kZXIgPSBuZXcgRGF0ZVJhbmdlRXhwYW5kZXIodGhpcy5hcHAsIHRoaXMuc2V0dGluZ3MsIHRoaXMuZGF0ZVV0aWxzKTtcclxuXHJcblx0XHR0aGlzLmFkZFNldHRpbmdUYWIobmV3IERhdGVSYW5nZUV4cGFuZGVyU2V0dGluZ1RhYih0aGlzLmFwcCwgdGhpcykpO1xyXG5cclxuXHRcdHRoaXMuYWRkQ29tbWFuZCh7XHJcblx0XHRcdGlkOiAnaW5zZXJ0LWV4cGFuZGVkLWRhdGUtcmFuZ2UnLFxyXG5cdFx0XHRuYW1lOiAnSW5zZXJ0JyxcclxuXHRcdFx0Y2hlY2tDYWxsYmFjazogKGNoZWNraW5nOiBib29sZWFuKSA9PiB7XHJcblx0XHRcdFx0Y29uc3QgbWFya2Rvd25WaWV3ID0gdGhpcy5hcHAud29ya3NwYWNlLmdldEFjdGl2ZVZpZXdPZlR5cGUoTWFya2Rvd25WaWV3KTtcclxuXHRcdFx0XHRpZiAobWFya2Rvd25WaWV3KSB7XHJcblx0XHRcdFx0XHRpZiAoIWNoZWNraW5nKSB7XHJcblx0XHRcdFx0XHRcdG5ldyBEYXRlSW5wdXRNb2RhbCh0aGlzLmFwcCwgKHJhbmdlSW5wdXQpID0+IHtcclxuXHRcdFx0XHRcdFx0XHRjb25zdCBkYXRlU3RhcnRBbmRFbmQgPSB0aGlzLmRhdGVVdGlscy5nZXRTdGFydEFuZEVuZERhdGVzKHJhbmdlSW5wdXQpO1xyXG5cclxuXHRcdFx0XHRcdFx0XHRpZiAoZGF0ZVN0YXJ0QW5kRW5kKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRjb25zdCBlZGl0b3IgPSB0aGlzLmdldEFjdGl2ZUVkaXRvcigpO1xyXG5cdFx0XHRcdFx0XHRcdFx0aWYgKGVkaXRvcikge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRjb25zdCBjdXJzb3IgPSBlZGl0b3IuZ2V0Q3Vyc29yKCk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGxldCBpbnNlcnRlZERhdGVSYW5nZSA9IHRoaXMuZGF0ZVJhbmdlRXhwYW5kZXIuZXhwYW5kRGF0ZVJhbmdlKGRhdGVTdGFydEFuZEVuZCkgKyAnICc7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGlmIChyYW5nZUlucHV0LnVzZUNhbGxvdXQpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRpbnNlcnRlZERhdGVSYW5nZSA9IHRoaXMuZGF0ZVJhbmdlRXhwYW5kZXIud3JhcEluQ2FsbG91dChkYXRlU3RhcnRBbmRFbmQsIGluc2VydGVkRGF0ZVJhbmdlKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRlZGl0b3IucmVwbGFjZVJhbmdlKGluc2VydGVkRGF0ZVJhbmdlLCB7IGxpbmU6IGN1cnNvci5saW5lLCBjaDogY3Vyc29yLmNoIH0sIGN1cnNvcik7XHJcblxyXG5cdFx0XHRcdFx0XHRcdFx0XHRjb25zdCBlbmRQb3MgPSB7IGxpbmU6IGN1cnNvci5saW5lLCBjaDogY3Vyc29yLmNoICsgaW5zZXJ0ZWREYXRlUmFuZ2UubGVuZ3RoIH07XHJcblx0XHRcdFx0XHRcdFx0XHRcdGVkaXRvci5zZXRDdXJzb3IoZW5kUG9zKTtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdH0pLm9wZW4oKTtcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH0pO1xyXG5cdH1cclxuXHJcblx0YXN5bmMgbG9hZFNldHRpbmdzKCkgeyB0aGlzLnNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgREVGQVVMVF9TRVRUSU5HUywgYXdhaXQgdGhpcy5sb2FkRGF0YSgpKTsgfVxyXG5cclxuXHRhc3luYyBzYXZlU2V0dGluZ3MoKSB7IGF3YWl0IHRoaXMuc2F2ZURhdGEodGhpcy5zZXR0aW5ncyk7IH1cclxuXHJcblx0b251bmxvYWQoKSB7XHJcbiAgICAgICAgY29uc29sZS5sb2coJ0RhdGVSYW5nZUV4cGFuZGVyIHVubG9hZGVkJyk7XHJcbiAgICB9XHJcblxyXG5cdGdldEFjdGl2ZUVkaXRvcigpIHtcclxuXHRcdGNvbnN0IGFjdGl2ZUxlYWYgPSB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlVmlld09mVHlwZShNYXJrZG93blZpZXcpO1xyXG5cdFx0aWYgKGFjdGl2ZUxlYWYpIHtcclxuXHRcdFx0cmV0dXJuIGFjdGl2ZUxlYWYuZWRpdG9yO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIG51bGw7XHJcblx0fVxyXG59IiwgImltcG9ydCB7IEFwcCwgTW9kYWwsIFNldHRpbmcgfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCB7IERhdGVJbnB1dE1vZGFsUmVzcG9uc2UgfSBmcm9tICcuL3R5cGVzJztcclxuaW1wb3J0IHsgRGF0ZVV0aWxzIH0gZnJvbSAnLi9kYXRlVXRpbHMnO1xyXG5cclxuZXhwb3J0IGNsYXNzIERhdGVJbnB1dE1vZGFsIGV4dGVuZHMgTW9kYWwge1xyXG4gICAgcHJpdmF0ZSBzdGFydERhdGVWYWx1ZTogc3RyaW5nID0gJyc7XHJcbiAgICBwcml2YXRlIGVuZERhdGVWYWx1ZTogc3RyaW5nID0gJyc7XHJcbiAgICBwcml2YXRlIGR1cmF0aW9uVmFsdWU6IHN0cmluZyA9ICcnO1xyXG4gICAgcHJpdmF0ZSBkdXJhdGlvblR5cGVWYWx1ZTogJ0RheXMnIHwgJ1dlZWtzJyB8ICdNb250aHMnID0gJ0RheXMnO1xyXG4gICAgcHJpdmF0ZSB1c2VDYWxsb3V0VmFsdWU6IGJvb2xlYW4gPSB0cnVlO1xyXG4gICAgcHJpdmF0ZSByYW5nZVR5cGVWYWx1ZTogJ0VuZERhdGUnIHwgJ0R1cmF0aW9uJyA9ICdFbmREYXRlJztcclxuXHJcbiAgICBwcml2YXRlIG9uU3VibWl0OiAoZGF0ZVJhbmdlVmFsdWVzOiBEYXRlSW5wdXRNb2RhbFJlc3BvbnNlKSA9PiB2b2lkO1xyXG4gICAgcHJpdmF0ZSBzdWJtaXRCdXR0b246IEhUTUxCdXR0b25FbGVtZW50IHwgbnVsbCA9IG51bGw7XHJcbiAgICBwcml2YXRlIGVuZERhdGVJbnB1dDogSFRNTElucHV0RWxlbWVudDtcclxuICAgIHByaXZhdGUgZHVyYXRpb25JbnB1dDogSFRNTElucHV0RWxlbWVudDtcclxuICAgIHByaXZhdGUgZHVyYXRpb25UeXBlU2VsZWN0OiBIVE1MU2VsZWN0RWxlbWVudDtcclxuICAgIHByaXZhdGUgZGF0ZVV0aWxzOiBEYXRlVXRpbHM7XHJcbiAgICBwcml2YXRlIGtleWJvYXJkTGlzdGVuZXI6IChldmVudDogS2V5Ym9hcmRFdmVudCkgPT4gdm9pZDtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihhcHA6IEFwcCwgb25TdWJtaXQ6IChkYXRlUmFuZ2VWYWx1ZXM6IERhdGVJbnB1dE1vZGFsUmVzcG9uc2UpID0+IHZvaWQpIHtcclxuICAgICAgICBzdXBlcihhcHApO1xyXG4gICAgICAgIHRoaXMub25TdWJtaXQgPSBvblN1Ym1pdDtcclxuICAgICAgICB0aGlzLmRhdGVVdGlscyA9IG5ldyBEYXRlVXRpbHMoKTtcclxuICAgICAgICB0aGlzLnNldFRpdGxlKCdFbnRlciBkYXRlIHJhbmdlJyk7XHJcbiAgICB9XHJcblxyXG4gICAgb25PcGVuKCkge1xyXG4gICAgICAgIGNvbnN0IHsgY29udGVudEVsIH0gPSB0aGlzO1xyXG4gICAgICAgIGNvbnRlbnRFbC5lbXB0eSgpO1xyXG5cclxuICAgICAgICB0aGlzLmFkZFN0eWxlcygpO1xyXG4gICAgICAgIHRoaXMuc2V0dXBLZXlib2FyZExpc3RlbmVyKCk7XHJcbiAgICAgICAgdGhpcy5jcmVhdGVTdGFydERhdGVJbnB1dCgpO1xyXG4gICAgICAgIHRoaXMuY3JlYXRlUmFuZ2VPcHRpb25zKCk7XHJcbiAgICAgICAgdGhpcy5jcmVhdGVDYWxsb3V0VG9nZ2xlKCk7XHJcbiAgICAgICAgdGhpcy5jcmVhdGVTdWJtaXRCdXR0b24oKTtcclxuICAgIH1cclxuXHJcbiAgICBvbkNsb3NlKCkge1xyXG4gICAgICAgIGNvbnN0IHsgY29udGVudEVsIH0gPSB0aGlzO1xyXG4gICAgICAgIC8vIENsZWFuIHVwIHRoZSBrZXlib2FyZCBldmVudCBsaXN0ZW5lclxyXG4gICAgICAgIGlmICh0aGlzLmtleWJvYXJkTGlzdGVuZXIpIHtcclxuICAgICAgICAgICAgY29udGVudEVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLmtleWJvYXJkTGlzdGVuZXIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBDbGVhciB0aGUgY29udGVudFxyXG4gICAgICAgIGNvbnRlbnRFbC5lbXB0eSgpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgdmFsaWRhdGVJbnB1dCgpOiBib29sZWFuIHtcclxuICAgICAgICBjb25zdCBzdGFydERhdGVPYmogPSB0aGlzLmRhdGVVdGlscy5wYXJzZURhdGVGcm9tU3RyaW5nKHRoaXMuc3RhcnREYXRlVmFsdWUpO1xyXG5cclxuICAgICAgICBpZiAoIXN0YXJ0RGF0ZU9iail7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLnJhbmdlVHlwZVZhbHVlID09PSAnRW5kRGF0ZScpIHtcclxuICAgICAgICAgICAgY29uc3QgZW5kRGF0ZU9iaiA9IHRoaXMuZGF0ZVV0aWxzLnBhcnNlRGF0ZUZyb21TdHJpbmcodGhpcy5lbmREYXRlVmFsdWUpO1xyXG4gICAgICAgICAgICByZXR1cm4gISFlbmREYXRlT2JqICYmXHJcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGVVdGlscy5pc1ZhbGlkTnVtZXJpY0RhdGUodGhpcy5lbmREYXRlVmFsdWUpICYmXHJcbiAgICAgICAgICAgICAgICBlbmREYXRlT2JqID49IHN0YXJ0RGF0ZU9iajtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kdXJhdGlvblZhbHVlICE9PSAnJyAmJlxyXG4gICAgICAgICAgICAgICAgcGFyc2VJbnQodGhpcy5kdXJhdGlvblZhbHVlKSA+IDAgJiZcclxuICAgICAgICAgICAgICAgIFsnRGF5cycsICdXZWVrcycsICdNb250aHMnXS5pbmNsdWRlcyh0aGlzLmR1cmF0aW9uVHlwZVZhbHVlKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBjYWxjdWxhdGVEYXRlQ291bnQoKTogbnVtYmVyIHtcclxuICAgICAgICBjb25zdCBzdGFydERhdGUgPSB0aGlzLmRhdGVVdGlscy5wYXJzZURhdGVGcm9tU3RyaW5nKHRoaXMuc3RhcnREYXRlVmFsdWUpO1xyXG4gICAgICAgIGlmICghc3RhcnREYXRlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAwO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IGVuZERhdGU6IERhdGU7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLnJhbmdlVHlwZVZhbHVlID09PSAnRW5kRGF0ZScpIHtcclxuICAgICAgICAgICAgZW5kRGF0ZSA9IHRoaXMuZGF0ZVV0aWxzLnBhcnNlRGF0ZUZyb21TdHJpbmcodGhpcy5lbmREYXRlVmFsdWUpIHx8IHN0YXJ0RGF0ZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBlbmREYXRlID0gbmV3IERhdGUoc3RhcnREYXRlKTtcclxuICAgICAgICAgICAgY29uc3QgZHVyYXRpb24gPSBwYXJzZUludCh0aGlzLmR1cmF0aW9uVmFsdWUpIHx8IDA7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5kdXJhdGlvblR5cGVWYWx1ZSA9PT0gJ0RheXMnKSB7XHJcbiAgICAgICAgICAgICAgICBlbmREYXRlLnNldERhdGUoZW5kRGF0ZS5nZXREYXRlKCkgKyBkdXJhdGlvbiAtIDEpOyAvLyAtMSBiZWNhdXNlIHdlIGluY2x1ZGUgdGhlIHN0YXJ0IGRhdGVcclxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLmR1cmF0aW9uVHlwZVZhbHVlID09PSAnV2Vla3MnKSB7XHJcbiAgICAgICAgICAgICAgICBlbmREYXRlLnNldERhdGUoZW5kRGF0ZS5nZXREYXRlKCkgKyAoZHVyYXRpb24gKiA3KSAtIDEpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZHVyYXRpb25UeXBlVmFsdWUgPT09ICdNb250aHMnKSB7XHJcbiAgICAgICAgICAgICAgICBlbmREYXRlID0gdGhpcy5kYXRlVXRpbHMuYWRkTW9udGhzVG9EYXRlKHN0YXJ0RGF0ZSwgZHVyYXRpb24pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBkYXRlQ291bnQgPSB0aGlzLmRhdGVVdGlscy5jYWxjdWxhdGVEYXlzSW5SYW5nZShzdGFydERhdGUsIGVuZERhdGUpO1xyXG4gICAgICAgIHJldHVybiBkYXRlQ291bnQ7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBhZGRTdHlsZXMoKSB7XHJcbiAgICAgICAgY29uc3Qgc3R5bGVFbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N0eWxlJyk7XHJcbiAgICAgICAgc3R5bGVFbC50ZXh0Q29udGVudCA9IGBcclxuXHRcdFx0LmRhdGUtb3B0aW9uLWNvbnRhaW5lciB7XHJcblx0XHRcdFx0bWFyZ2luLWJvdHRvbTogMTVweDtcclxuXHRcdFx0fVxyXG5cdFx0XHQuZGF0ZS1pbnB1dC1yb3cge1xyXG5cdFx0XHRcdGRpc3BsYXk6IGZsZXg7XHJcblx0XHRcdFx0YWxpZ24taXRlbXM6IGNlbnRlcjtcclxuXHRcdFx0XHRtYXJnaW4tYm90dG9tOiAxMHB4O1xyXG5cdFx0XHR9XHJcblx0XHRcdC5kYXRlLWlucHV0LXJvdyBpbnB1dFt0eXBlPVwicmFkaW9cIl0ge1xyXG5cdFx0XHRcdG1hcmdpbi1yaWdodDogOHB4O1xyXG5cdFx0XHR9XHJcblx0XHRcdC5kYXRlLWlucHV0LXJvdyBpbnB1dFt0eXBlPVwidGV4dFwiXSxcclxuXHRcdFx0LmRhdGUtaW5wdXQtcm93IGlucHV0W3R5cGU9XCJudW1iZXJcIl0ge1xyXG5cdFx0XHRcdG1hcmdpbi1sZWZ0OiA1cHg7XHJcblx0XHRcdH1cclxuXHRcdFx0LmRhdGUtaW5wdXQtcm93IHNlbGVjdCB7XHJcblx0XHRcdFx0bWFyZ2luLWxlZnQ6IDVweDtcclxuXHRcdFx0fVxyXG5cdFx0YDtcclxuXHJcbiAgICAgICAgdGhpcy5jb250ZW50RWwuYXBwZW5kQ2hpbGQoc3R5bGVFbCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzZXR1cEtleWJvYXJkTGlzdGVuZXIoKSB7XHJcbiAgICAgICAgdGhpcy5rZXlib2FyZExpc3RlbmVyID0gKGV2ZW50OiBLZXlib2FyZEV2ZW50KSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChldmVudC5rZXkgPT09ICdFbnRlcicgJiYgdGhpcy52YWxpZGF0ZUlucHV0KCkpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc3VibWl0KCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG4gICAgICAgIHRoaXMuY29udGVudEVsLmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLmtleWJvYXJkTGlzdGVuZXIpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgY3JlYXRlU3RhcnREYXRlSW5wdXQoKSB7XHJcbiAgICAgICAgbmV3IFNldHRpbmcodGhpcy5jb250ZW50RWwpXHJcbiAgICAgICAgICAgIC5zZXROYW1lKCdTdGFydCBkYXRlJylcclxuICAgICAgICAgICAgLmFkZFRleHQodGV4dCA9PiB7XHJcbiAgICAgICAgICAgICAgICB0ZXh0LnNldFBsYWNlaG9sZGVyKCdZWVlZTU1ERCcpXHJcbiAgICAgICAgICAgICAgICAgICAgLnNldFZhbHVlKHRoaXMuc3RhcnREYXRlVmFsdWUpO1xyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICB0ZXh0LmlucHV0RWwuc2V0QXR0cmlidXRlKCdwYXR0ZXJuJywgJ1swLTldKicpO1xyXG4gICAgICAgICAgICAgICAgdGV4dC5pbnB1dEVsLnNldEF0dHJpYnV0ZSgnbWF4bGVuZ3RoJywgJzgnKTtcclxuICAgICAgICAgICAgICAgIHRleHQuaW5wdXRFbC5hZGRFdmVudExpc3RlbmVyKCdpbnB1dCcsIChlOiBJbnB1dEV2ZW50KSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5wdXQgPSBlLnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50O1xyXG4gICAgICAgICAgICAgICAgICAgIGlucHV0LnZhbHVlID0gaW5wdXQudmFsdWUucmVwbGFjZSgvXFxEL2csICcnKS5zbGljZSgwLCA4KTtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0RGF0ZVZhbHVlID0gaW5wdXQudmFsdWU7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51cGRhdGVTdWJtaXRCdXR0b24oKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGNyZWF0ZVJhbmdlT3B0aW9ucygpIHtcclxuICAgICAgICBjb25zdCBvcHRpb25Db250YWluZXIgPSB0aGlzLmNvbnRlbnRFbC5jcmVhdGVFbCgnZGl2JywgeyBjbHM6ICdkYXRlLW9wdGlvbi1jb250YWluZXInIH0pO1xyXG4gICAgICAgIHRoaXMuY3JlYXRlRW5kRGF0ZU9wdGlvbihvcHRpb25Db250YWluZXIpO1xyXG4gICAgICAgIHRoaXMuY3JlYXRlRHVyYXRpb25PcHRpb24ob3B0aW9uQ29udGFpbmVyKTtcclxuICAgICAgICB0aGlzLnVwZGF0ZUlucHV0U3RhdGVzKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBjcmVhdGVFbmREYXRlT3B0aW9uKGNvbnRhaW5lcjogSFRNTEVsZW1lbnQpIHtcclxuICAgICAgICBjb25zdCBlbmREYXRlUm93ID0gY29udGFpbmVyLmNyZWF0ZUVsKCdkaXYnLCB7IGNsczogJ2RhdGUtaW5wdXQtcm93JyB9KTtcclxuICAgICAgICBjb25zdCBlbmREYXRlTGFiZWwgPSBlbmREYXRlUm93LmNyZWF0ZUVsKCdsYWJlbCcpO1xyXG4gICAgICAgIGVuZERhdGVMYWJlbC5hcHBlbmRUZXh0KCdFbmQgZGF0ZScpO1xyXG5cclxuICAgICAgICBjb25zdCBlbmREYXRlUmFkaW8gPSBlbmREYXRlTGFiZWwuY3JlYXRlRWwoJ2lucHV0Jywge1xyXG4gICAgICAgICAgICB0eXBlOiAncmFkaW8nLFxyXG4gICAgICAgICAgICBhdHRyOiB7IG5hbWU6ICdkYXRlT3B0aW9uJyB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgZW5kRGF0ZVJhZGlvLmNoZWNrZWQgPSB0aGlzLnJhbmdlVHlwZVZhbHVlID09PSAnRW5kRGF0ZSc7XHJcblxyXG4gICAgICAgIHRoaXMuZW5kRGF0ZUlucHV0ID0gZW5kRGF0ZVJvdy5jcmVhdGVFbCgnaW5wdXQnLCB7XHJcbiAgICAgICAgICAgIHR5cGU6ICd0ZXh0JyxcclxuICAgICAgICAgICAgcGxhY2Vob2xkZXI6ICdZWVlZTU1ERCcsXHJcbiAgICAgICAgICAgIHZhbHVlOiB0aGlzLmVuZERhdGVWYWx1ZSxcclxuICAgICAgICAgICAgYXR0cjoge1xyXG4gICAgICAgICAgICAgICAgcGF0dGVybjogJ1swLTldKicsXHJcbiAgICAgICAgICAgICAgICBtYXhsZW5ndGg6ICc4J1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoaXMuZW5kRGF0ZUlucHV0LmFkZEV2ZW50TGlzdGVuZXIoJ2lucHV0JywgKGUpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgaW5wdXQgPSBlLnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50O1xyXG4gICAgICAgICAgICBpbnB1dC52YWx1ZSA9IGlucHV0LnZhbHVlLnJlcGxhY2UoL1xcRC9nLCAnJykuc2xpY2UoMCwgOCk7XHJcbiAgICAgICAgICAgIHRoaXMuZW5kRGF0ZVZhbHVlID0gaW5wdXQudmFsdWU7XHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlU3VibWl0QnV0dG9uKCk7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIGVuZERhdGVSYWRpby5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCAoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMucmFuZ2VUeXBlVmFsdWUgPSAnRW5kRGF0ZSc7XHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlSW5wdXRTdGF0ZXMoKTtcclxuICAgICAgICAgICAgdGhpcy51cGRhdGVTdWJtaXRCdXR0b24oKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGNyZWF0ZUR1cmF0aW9uT3B0aW9uKGNvbnRhaW5lcjogSFRNTEVsZW1lbnQpIHtcclxuICAgICAgICBjb25zdCBkdXJhdGlvblJvdyA9IGNvbnRhaW5lci5jcmVhdGVFbCgnZGl2JywgeyBjbHM6ICdkYXRlLWlucHV0LXJvdycgfSk7XHJcbiAgICAgICAgY29uc3QgZHVyYXRpb25MYWJlbCA9IGR1cmF0aW9uUm93LmNyZWF0ZUVsKCdsYWJlbCcpO1xyXG4gICAgICAgIGR1cmF0aW9uTGFiZWwuYXBwZW5kVGV4dCgnRHVyYXRpb24nKTtcclxuXHJcbiAgICAgICAgY29uc3QgZHVyYXRpb25SYWRpbyA9IGR1cmF0aW9uTGFiZWwuY3JlYXRlRWwoJ2lucHV0Jywge1xyXG4gICAgICAgICAgICB0eXBlOiAncmFkaW8nLFxyXG4gICAgICAgICAgICBhdHRyOiB7IG5hbWU6ICdkYXRlT3B0aW9uJyB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgZHVyYXRpb25SYWRpby5jaGVja2VkID0gdGhpcy5yYW5nZVR5cGVWYWx1ZSA9PT0gJ0R1cmF0aW9uJztcclxuXHJcbiAgICAgICAgdGhpcy5kdXJhdGlvbklucHV0ID0gZHVyYXRpb25Sb3cuY3JlYXRlRWwoJ2lucHV0Jywge1xyXG4gICAgICAgICAgICB0eXBlOiAnbnVtYmVyJyxcclxuICAgICAgICAgICAgYXR0cjogeyBcclxuICAgICAgICAgICAgICAgIG1pbjogJzEnLFxyXG4gICAgICAgICAgICAgICAgbWF4OiAnMTAwJ1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBwbGFjZWhvbGRlcjogJzEtMTAwJyxcclxuICAgICAgICAgICAgdmFsdWU6IHRoaXMuZHVyYXRpb25WYWx1ZVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICB0aGlzLmR1cmF0aW9uVHlwZVNlbGVjdCA9IGR1cmF0aW9uUm93LmNyZWF0ZUVsKCdzZWxlY3QnKTtcclxuICAgICAgICB0aGlzLnBvcHVsYXRlRHVyYXRpb25UeXBlcygpO1xyXG5cclxuICAgICAgICBkdXJhdGlvblJhZGlvLmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsICgpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5yYW5nZVR5cGVWYWx1ZSA9ICdEdXJhdGlvbic7XHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlSW5wdXRTdGF0ZXMoKTtcclxuICAgICAgICAgICAgdGhpcy51cGRhdGVTdWJtaXRCdXR0b24oKTtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5kdXJhdGlvbklucHV0LmFkZEV2ZW50TGlzdGVuZXIoJ2lucHV0JywgKGUpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgaW5wdXQgPSBlLnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50O1xyXG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBwYXJzZUludChpbnB1dC52YWx1ZSk7XHJcbiAgICAgICAgICAgIGlmICh2YWx1ZSA+IDEwMCkge1xyXG4gICAgICAgICAgICAgICAgdmFsdWUgPSAxMDA7XHJcbiAgICAgICAgICAgICAgICBpbnB1dC52YWx1ZSA9ICcxMDAnO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMuZHVyYXRpb25WYWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlU3VibWl0QnV0dG9uKCk7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoaXMuZHVyYXRpb25UeXBlU2VsZWN0LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIChlKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuZHVyYXRpb25UeXBlVmFsdWUgPSAoZS50YXJnZXQgYXMgSFRNTFNlbGVjdEVsZW1lbnQpLnZhbHVlIGFzICdEYXlzJyB8ICdXZWVrcycgfCAnTW9udGhzJztcclxuICAgICAgICAgICAgdGhpcy51cGRhdGVTdWJtaXRCdXR0b24oKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHBvcHVsYXRlRHVyYXRpb25UeXBlcygpIHtcclxuICAgICAgICBbJ0RheXMnLCAnV2Vla3MnLCAnTW9udGhzJ10uZm9yRWFjaCh0eXBlID0+IHtcclxuICAgICAgICAgICAgY29uc3Qgb3B0aW9uID0gdGhpcy5kdXJhdGlvblR5cGVTZWxlY3QuY3JlYXRlRWwoJ29wdGlvbicsIHtcclxuICAgICAgICAgICAgICAgIHZhbHVlOiB0eXBlLFxyXG4gICAgICAgICAgICAgICAgdGV4dDogdHlwZVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgb3B0aW9uLnNlbGVjdGVkID0gdHlwZSA9PT0gdGhpcy5kdXJhdGlvblR5cGVWYWx1ZTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHVwZGF0ZUlucHV0U3RhdGVzKCkge1xyXG4gICAgICAgIGNvbnN0IGlzRW5kRGF0ZU1vZGUgPSB0aGlzLnJhbmdlVHlwZVZhbHVlID09PSAnRW5kRGF0ZSc7XHJcbiAgICAgICAgdGhpcy5lbmREYXRlSW5wdXQuZGlzYWJsZWQgPSAhaXNFbmREYXRlTW9kZTtcclxuICAgICAgICB0aGlzLmR1cmF0aW9uSW5wdXQuZGlzYWJsZWQgPSBpc0VuZERhdGVNb2RlO1xyXG4gICAgICAgIHRoaXMuZHVyYXRpb25UeXBlU2VsZWN0LmRpc2FibGVkID0gaXNFbmREYXRlTW9kZTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGNyZWF0ZUNhbGxvdXRUb2dnbGUoKSB7XHJcbiAgICAgICAgbmV3IFNldHRpbmcodGhpcy5jb250ZW50RWwpXHJcbiAgICAgICAgICAgIC5zZXROYW1lKCdBZGQgdG8gY2FsbG91dCcpXHJcbiAgICAgICAgICAgIC5zZXREZXNjKCdJbnNlcnQgZGF0ZXMgaW5zaWRlIGEgY29sbGFwc2VkIGNhbGxvdXQnKVxyXG4gICAgICAgICAgICAuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB0b2dnbGVcclxuICAgICAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLnVzZUNhbGxvdXRWYWx1ZSlcclxuICAgICAgICAgICAgICAgIC5vbkNoYW5nZSh2YWx1ZSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51c2VDYWxsb3V0VmFsdWUgPSB2YWx1ZTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBjcmVhdGVTdWJtaXRCdXR0b24oKSB7XHJcbiAgICAgICAgdGhpcy5zdWJtaXRCdXR0b24gPSBuZXcgU2V0dGluZyh0aGlzLmNvbnRlbnRFbClcclxuICAgICAgICAgICAgLmFkZEJ1dHRvbihidG4gPT4gYnRuXHJcbiAgICAgICAgICAgICAgICAuc2V0QnV0dG9uVGV4dCgnSW5zZXJ0JylcclxuICAgICAgICAgICAgICAgIC5zZXRDdGEoKVxyXG4gICAgICAgICAgICAgICAgLm9uQ2xpY2soKCkgPT4gdGhpcy5zdWJtaXQoKSlcclxuICAgICAgICAgICAgKS5zZXR0aW5nRWwucXVlcnlTZWxlY3RvcignYnV0dG9uJyk7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLnN1Ym1pdEJ1dHRvbikge1xyXG4gICAgICAgICAgICB0aGlzLnN1Ym1pdEJ1dHRvbi5kaXNhYmxlZCA9IHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgdXBkYXRlU3VibWl0QnV0dG9uKCkge1xyXG4gICAgICAgIGlmICh0aGlzLnN1Ym1pdEJ1dHRvbikge1xyXG4gICAgICAgICAgICBjb25zdCB2YWxpZElucHV0ID0gdGhpcy52YWxpZGF0ZUlucHV0KCk7XHJcbiAgICAgICAgICAgIHRoaXMuc3VibWl0QnV0dG9uLmRpc2FibGVkID0gIXZhbGlkSW5wdXQ7XHJcblxyXG4gICAgICAgICAgICBpZiAodmFsaWRJbnB1dCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZGF0ZUNvdW50ID0gdGhpcy5jYWxjdWxhdGVEYXRlQ291bnQoKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuc3VibWl0QnV0dG9uLnRleHRDb250ZW50ID0gYEluc2VydCAke2RhdGVDb3VudH0gRGF0ZSR7ZGF0ZUNvdW50ICE9PSAxID8gJ3MnIDogJyd9YDtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc3VibWl0QnV0dG9uLnRleHRDb250ZW50ID0gJ0luc2VydCc7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdWJtaXQoKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLnZhbGlkYXRlSW5wdXQoKSkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBzdGFydERhdGVPYmogPSB0aGlzLmRhdGVVdGlscy5wYXJzZURhdGVGcm9tU3RyaW5nKHRoaXMuc3RhcnREYXRlVmFsdWUpO1xyXG4gICAgICAgIGlmICghc3RhcnREYXRlT2JqKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGRhdGVSYW5nZVZhbHVlczogRGF0ZUlucHV0TW9kYWxSZXNwb25zZSA9IHtcclxuICAgICAgICAgICAgc3RhcnREYXRlOiBzdGFydERhdGVPYmosXHJcbiAgICAgICAgICAgIHJhbmdlVHlwZTogdGhpcy5yYW5nZVR5cGVWYWx1ZSxcclxuICAgICAgICAgICAgdXNlQ2FsbG91dDogdGhpcy51c2VDYWxsb3V0VmFsdWVcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBpZiAodGhpcy5yYW5nZVR5cGVWYWx1ZSA9PT0gJ0VuZERhdGUnKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGVuZERhdGVPYmogPSB0aGlzLmRhdGVVdGlscy5wYXJzZURhdGVGcm9tU3RyaW5nKHRoaXMuZW5kRGF0ZVZhbHVlKTtcclxuICAgICAgICAgICAgaWYgKGVuZERhdGVPYmopXHJcbiAgICAgICAgICAgICAgICBkYXRlUmFuZ2VWYWx1ZXMuZW5kRGF0ZSA9IGVuZERhdGVPYmo7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgZGF0ZVJhbmdlVmFsdWVzLmR1cmF0aW9uID0gcGFyc2VJbnQodGhpcy5kdXJhdGlvblZhbHVlKTtcclxuICAgICAgICAgICAgZGF0ZVJhbmdlVmFsdWVzLmR1cmF0aW9uVW5pdCA9IHRoaXMuZHVyYXRpb25UeXBlVmFsdWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmNsb3NlKCk7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLm9uU3VibWl0KSB7XHJcbiAgICAgICAgICAgIHRoaXMub25TdWJtaXQoZGF0ZVJhbmdlVmFsdWVzKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn0iLCAiaW1wb3J0IHsgRGF0ZUlucHV0TW9kYWxSZXNwb25zZSwgRGF0ZVJhbmdlIH0gZnJvbSAnLi90eXBlcyc7XHJcblxyXG5leHBvcnQgY2xhc3MgRGF0ZVV0aWxzIHtcclxuICAgIGdldFN0YXJ0QW5kRW5kRGF0ZXMobW9kYWxSZXNwb25zZTogRGF0ZUlucHV0TW9kYWxSZXNwb25zZSk6IERhdGVSYW5nZSB8IG51bGwge1xyXG4gICAgICAgIGxldCBzdGFydERhdGU6IERhdGUgPSBtb2RhbFJlc3BvbnNlLnN0YXJ0RGF0ZTtcclxuICAgICAgICBsZXQgZW5kRGF0ZTogRGF0ZTtcclxuXHJcbiAgICAgICAgaWYgKG1vZGFsUmVzcG9uc2UucmFuZ2VUeXBlID09PSAnRW5kRGF0ZScpIHtcclxuICAgICAgICAgICAgZW5kRGF0ZSA9IG1vZGFsUmVzcG9uc2UuZW5kRGF0ZSE7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgZW5kRGF0ZSA9IG5ldyBEYXRlKHN0YXJ0RGF0ZSk7XHJcbiAgICAgICAgICAgIGNvbnN0IGR1cmF0aW9uID0gbW9kYWxSZXNwb25zZS5kdXJhdGlvbiE7XHJcbiAgICAgICAgICAgIGNvbnN0IHVuaXQgPSBtb2RhbFJlc3BvbnNlLmR1cmF0aW9uVW5pdCE7XHJcblxyXG4gICAgICAgICAgICBzd2l0Y2ggKHVuaXQpIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgJ0RheXMnOlxyXG4gICAgICAgICAgICAgICAgICAgIGVuZERhdGUuc2V0RGF0ZShzdGFydERhdGUuZ2V0RGF0ZSgpICsgZHVyYXRpb24gLSAxKTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgJ1dlZWtzJzpcclxuICAgICAgICAgICAgICAgICAgICBlbmREYXRlLnNldERhdGUoc3RhcnREYXRlLmdldERhdGUoKSArIChkdXJhdGlvbiAqIDcpIC0gMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlICdNb250aHMnOlxyXG4gICAgICAgICAgICAgICAgICAgIGVuZERhdGUgPSB0aGlzLmFkZE1vbnRoc1RvRGF0ZShzdGFydERhdGUsIGR1cmF0aW9uKTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHN0YXJ0RGF0ZSA+IGVuZERhdGUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBkYXRlU3RhcnRBbmRFbmQ6IERhdGVSYW5nZSA9IHtcclxuICAgICAgICAgICAgc3RhcnREYXRlOiBzdGFydERhdGUsXHJcbiAgICAgICAgICAgIGVuZERhdGU6IGVuZERhdGVcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICByZXR1cm4gZGF0ZVN0YXJ0QW5kRW5kO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEFzc3VtaW5nIHN0cmluZyBkYXRlIGlzIGluIGZvcm1hdDogWVlZWU1NRERcclxuICAgIHBhcnNlRGF0ZUZyb21TdHJpbmcoZGF0ZVN0cmluZzogc3RyaW5nKTogRGF0ZSB8IG51bGwge1xyXG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkTnVtZXJpY0RhdGUoZGF0ZVN0cmluZykpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCB5ZWFyID0gcGFyc2VJbnQoZGF0ZVN0cmluZy5zdWJzdHJpbmcoMCwgNCkpO1xyXG4gICAgICAgIGNvbnN0IG1vbnRoID0gcGFyc2VJbnQoZGF0ZVN0cmluZy5zdWJzdHJpbmcoNCwgNikpIC0gMTtcclxuICAgICAgICBjb25zdCBkYXkgPSBwYXJzZUludChkYXRlU3RyaW5nLnN1YnN0cmluZyg2LCA4KSk7XHJcblxyXG4gICAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZShEYXRlLlVUQyh5ZWFyLCBtb250aCwgZGF5KSk7XHJcbiAgICAgICAgcmV0dXJuIGRhdGU7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0dXJucyB0cnVlIGlmIHN0cmluZyBkYXRlIGlzIGluIGZvcm1hdDogWVlZWU1NRERcclxuICAgIGlzVmFsaWROdW1lcmljRGF0ZShkYXRlU3RyaW5nOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAoIS9eXFxkezh9JC8udGVzdChkYXRlU3RyaW5nKSlcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG5cclxuICAgICAgICBjb25zdCB5ZWFyID0gcGFyc2VJbnQoZGF0ZVN0cmluZy5zdWJzdHJpbmcoMCwgNCkpO1xyXG4gICAgICAgIGNvbnN0IG1vbnRoID0gcGFyc2VJbnQoZGF0ZVN0cmluZy5zdWJzdHJpbmcoNCwgNikpIC0gMTsgLy8gSmF2YVNjcmlwdCBtb250aHMgYXJlIDAtaW5kZXhlZFxyXG4gICAgICAgIGNvbnN0IGRheSA9IHBhcnNlSW50KGRhdGVTdHJpbmcuc3Vic3RyaW5nKDYsIDgpKTtcclxuXHJcbiAgICAgICAgLy8gQWRkaXRpb25hbCB2YWxpZGF0aW9uXHJcbiAgICAgICAgaWYgKHllYXIgPCAxOTAwKVxyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgaWYgKG1vbnRoIDwgMCB8fCBtb250aCA+IDExKVxyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgaWYgKGRheSA8IDEgfHwgZGF5ID4gMzEpXHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuXHJcbiAgICAgICAgY29uc3QgZGF0ZU9iaiA9IG5ldyBEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xyXG5cclxuICAgICAgICByZXR1cm4gZGF0ZU9iai5nZXRGdWxsWWVhcigpID09PSB5ZWFyICYmXHJcbiAgICAgICAgICAgIGRhdGVPYmouZ2V0TW9udGgoKSA9PT0gbW9udGggJiZcclxuICAgICAgICAgICAgZGF0ZU9iai5nZXREYXRlKCkgPT09IGRheTtcclxuICAgIH1cclxuXHJcbiAgICBmb3JtYXREYXRlVG9TdHJpbmcoZGF0ZTogRGF0ZSwgc2V0dGluZ3NGb3JtYXQ6IHN0cmluZywgZGVmYXVsdEZvcm1hdDogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICBjb25zdCB5ZWFyID0gZGF0ZS5nZXRGdWxsWWVhcigpO1xyXG4gICAgICAgIGNvbnN0IG1vbnRoID0gZGF0ZS5nZXRNb250aCgpO1xyXG4gICAgICAgIGNvbnN0IGRheSA9IGRhdGUuZ2V0RGF0ZSgpO1xyXG4gICAgICAgIGNvbnN0IHdlZWtkYXkgPSBkYXRlLmdldERheSgpO1xyXG5cclxuICAgICAgICBjb25zdCBkYXlOYW1lcyA9IFsnU3VuZGF5JywgJ01vbmRheScsICdUdWVzZGF5JywgJ1dlZG5lc2RheScsICdUaHVyc2RheScsICdGcmlkYXknLCAnU2F0dXJkYXknXTtcclxuICAgICAgICBjb25zdCBtb250aE5hbWVzID0gWydKYW51YXJ5JywgJ0ZlYnJ1YXJ5JywgJ01hcmNoJywgJ0FwcmlsJywgJ01heScsICdKdW5lJywgJ0p1bHknLCAnQXVndXN0JywgJ1NlcHRlbWJlcicsICdPY3RvYmVyJywgJ05vdmVtYmVyJywgJ0RlY2VtYmVyJ107XHJcblxyXG4gICAgICAgIGNvbnN0IGRheUFiYnJldmlhdGlvbnMgPSBkYXlOYW1lcy5tYXAoZGF5ID0+IGRheS5zbGljZSgwLCAzKSk7XHJcbiAgICAgICAgY29uc3QgbW9udGhBYmJyZXZpYXRpb25zID0gbW9udGhOYW1lcy5tYXAobW9udGggPT4gbW9udGguc2xpY2UoMCwgMykpO1xyXG5cclxuICAgICAgICBjb25zdCBmb3JtYXREYXRlID0gKGZvcm1hdDogc3RyaW5nKTogc3RyaW5nID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdC5yZXBsYWNlKC9ZWVlZfFlZWXxZWXxZfE1NTU18TU1NfE1NfE18RERERHxERER8RER8RC9nLCAobWF0Y2gpID0+IHtcclxuICAgICAgICAgICAgICAgIHN3aXRjaCAobWF0Y2gpIHtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdZWVlZJzogcmV0dXJuIHllYXIudG9TdHJpbmcoKTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdZWVknOiByZXR1cm4geWVhci50b1N0cmluZygpLnNsaWNlKC0zKTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdZWSc6IHJldHVybiB5ZWFyLnRvU3RyaW5nKCkuc2xpY2UoLTIpO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ1knOiByZXR1cm4geWVhci50b1N0cmluZygpLnNsaWNlKC0xKTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdNTU1NJzogcmV0dXJuIG1vbnRoTmFtZXNbbW9udGhdO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ01NTSc6IHJldHVybiBtb250aEFiYnJldmlhdGlvbnNbbW9udGhdO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ01NJzogcmV0dXJuIChtb250aCArIDEpLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgJzAnKTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdNJzogcmV0dXJuIChtb250aCArIDEpLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnRERERCc6IHJldHVybiBkYXlOYW1lc1t3ZWVrZGF5XTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdEREQnOiByZXR1cm4gZGF5QWJicmV2aWF0aW9uc1t3ZWVrZGF5XTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdERCc6IHJldHVybiBkYXkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAnMCcpO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ0QnOiByZXR1cm4gZGF5LnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDogcmV0dXJuIG1hdGNoO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0RGF0ZShzZXR0aW5nc0Zvcm1hdCk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICAgICAgLy8gRmFsbGJhY2sgdG8gZGVmYXVsdCBmb3JtYXQgaWYgYW55dGhpbmcgZ29lcyB3cm9uZ1xyXG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0RGF0ZShkZWZhdWx0Rm9ybWF0KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgYWRkTW9udGhzVG9EYXRlKGRhdGU6IERhdGUsIG1vbnRoczogbnVtYmVyKTogRGF0ZSB7XHJcbiAgICAgICAgaWYgKG1vbnRocyA9PT0gMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gZGF0ZTtcclxuICAgICAgICB9ICAgXHJcblxyXG4gICAgICAgIGNvbnN0IG5ld0RhdGUgPSBuZXcgRGF0ZShkYXRlKTtcclxuXHJcbiAgICAgICAgY29uc3QgY3VycmVudERheSA9IGRhdGUuZ2V0RGF0ZSgpO1xyXG5cclxuICAgICAgICBuZXdEYXRlLnNldE1vbnRoKG5ld0RhdGUuZ2V0TW9udGgoKSArIG1vbnRocyk7XHJcbiAgICAgICAgbmV3RGF0ZS5zZXREYXRlKG5ld0RhdGUuZ2V0RGF0ZSgpIC0gMSk7XHJcblxyXG4gICAgICAgIC8vIENoZWNrIGlmIHRoZSBkYXkgY2hhbmdlZCAod2hpY2ggbWVhbnMgd2Ugd2VudCBpbnRvIHRoZSBuZXh0IG1vbnRoKVxyXG4gICAgICAgIGlmIChuZXdEYXRlLmdldE1vbnRoKCkgIT09IGRhdGUuZ2V0TW9udGgoKSAmJiBuZXdEYXRlLmdldERhdGUoKSAhPT0gKGN1cnJlbnREYXkgLSAxKSkge1xyXG4gICAgICAgICAgICAvLyBJZiB0aGUgZGF5IGNoYW5nZWQsIGl0IG1lYW5zIHdlIGxhbmRlZCBvbiB0aGUgd3JvbmcgZGF5XHJcbiAgICAgICAgICAgIC8vIFNldCB0byB0aGUgbGFzdCBkYXkgb2YgdGhlIHByZXZpb3VzIG1vbnRoXHJcbiAgICAgICAgICAgIG5ld0RhdGUuc2V0RGF0ZSgwKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBuZXdEYXRlO1xyXG4gICAgfVxyXG5cclxuICAgIGNhbGN1bGF0ZURheXNJblJhbmdlKHN0YXJ0RGF0ZTogRGF0ZSwgZW5kRGF0ZTogRGF0ZSk6IG51bWJlciB7XHJcbiAgICAgICAgY29uc3QgbWlsbGlzZWNvbmRzSW5EYXkgPSAxMDAwICogNjAgKiA2MCAqIDI0O1xyXG5cclxuICAgICAgICBjb25zdCBkaWZmZXJlbmNlTWlsbGlzZWNvbmRzID0gZW5kRGF0ZS5nZXRUaW1lKCkgLSBzdGFydERhdGUuZ2V0VGltZSgpO1xyXG4gICAgICAgIGNvbnN0IGRpZmZlcmVuY2VEYXlzID0gTWF0aC5mbG9vcihkaWZmZXJlbmNlTWlsbGlzZWNvbmRzIC8gbWlsbGlzZWNvbmRzSW5EYXkpICsgMTsgLy8gKzEgdG8gaW5jbHVkZSBib3RoIHN0YXJ0IGFuZCBlbmQgZGF0ZXNcclxuXHJcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KDAsIGRpZmZlcmVuY2VEYXlzKTtcclxuICAgIH1cclxufSIsICJleHBvcnQgaW50ZXJmYWNlIFBsdWdpblNldHRpbmdzIHtcbiAgICBvdXRwdXREYXRlRm9ybWF0OiBzdHJpbmc7XG4gICAgZnJpZW5kbHlEYXRlRm9ybWF0OiBzdHJpbmc7XG4gICAgZGF0ZVNlcGFyYXRvcjogc3RyaW5nO1xuICAgIGNyZWF0ZVdpa2lMaW5rczogYm9vbGVhbjtcbiAgICBjcmVhdGVOb25FeGlzdGVudEZpbGVzOiAnZG8tbm90LWNyZWF0ZScgfCAnc2FtZS1mb2xkZXInIHwgJ2N1c3RvbS1mb2xkZXInO1xuICAgIGN1c3RvbUZvbGRlclBhdGg6IHN0cmluZztcbn1cblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfU0VUVElOR1M6IFBsdWdpblNldHRpbmdzID0ge1xuICAgIG91dHB1dERhdGVGb3JtYXQ6ICdZWVlZLk1NLkREJyxcbiAgICBmcmllbmRseURhdGVGb3JtYXQ6ICdEREQgRCBNTU0gWVlZWScsXG4gICAgZGF0ZVNlcGFyYXRvcjogJywgJyxcbiAgICBjcmVhdGVXaWtpTGlua3M6IHRydWUsXG4gICAgY3JlYXRlTm9uRXhpc3RlbnRGaWxlczogJ3NhbWUtZm9sZGVyJyxcbiAgICBjdXN0b21Gb2xkZXJQYXRoOiAnJ1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERhdGVSYW5nZSB7XG4gICAgc3RhcnREYXRlOiBEYXRlO1xuICAgIGVuZERhdGU6IERhdGU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGF0ZUlucHV0TW9kYWxSZXNwb25zZSB7XG4gICAgc3RhcnREYXRlOiBEYXRlO1xuICAgIHJhbmdlVHlwZTogJ0VuZERhdGUnIHwgJ0R1cmF0aW9uJztcbiAgICBlbmREYXRlPzogRGF0ZTtcbiAgICBkdXJhdGlvbj86IG51bWJlcjtcbiAgICBkdXJhdGlvblVuaXQ/OiAnRGF5cycgfCAnV2Vla3MnIHwgJ01vbnRocyc7XG4gICAgdXNlQ2FsbG91dDogYm9vbGVhbjtcbn0iLCAiaW1wb3J0IHsgQXBwLCBQbHVnaW5TZXR0aW5nVGFiLCBTZXR0aW5nIH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5pbXBvcnQgRGF0ZVJhbmdlRXhwYW5kZXJQbHVnaW4gZnJvbSAnLi9tYWluJztcclxuaW1wb3J0IHsgREVGQVVMVF9TRVRUSU5HUyB9IGZyb20gJy4vdHlwZXMnO1xyXG5cclxuZXhwb3J0IGNsYXNzIERhdGVSYW5nZUV4cGFuZGVyU2V0dGluZ1RhYiBleHRlbmRzIFBsdWdpblNldHRpbmdUYWIge1xyXG4gICAgcGx1Z2luOiBEYXRlUmFuZ2VFeHBhbmRlclBsdWdpbjtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihhcHA6IEFwcCwgcGx1Z2luOiBEYXRlUmFuZ2VFeHBhbmRlclBsdWdpbikge1xyXG4gICAgICAgIHN1cGVyKGFwcCwgcGx1Z2luKTtcclxuICAgICAgICB0aGlzLnBsdWdpbiA9IHBsdWdpbjtcclxuICAgIH1cclxuXHJcbiAgICBkaXNwbGF5KCk6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IHsgY29udGFpbmVyRWwgfSA9IHRoaXM7XHJcbiAgICAgICAgY29udGFpbmVyRWwuZW1wdHkoKTtcclxuXHJcbiAgICAgICAgdGhpcy5jcmVhdGVEYXRlRm9ybWF0U2V0dGluZ3MoKTtcclxuICAgICAgICB0aGlzLmNyZWF0ZVdpa2lMaW5rU2V0dGluZ3MoKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGNyZWF0ZURhdGVGb3JtYXRTZXR0aW5ncygpIHtcclxuICAgICAgICBuZXcgU2V0dGluZyh0aGlzLmNvbnRhaW5lckVsKVxyXG4gICAgICAgICAgICAuc2V0TmFtZSgnT3V0cHV0IGRhdGUgZm9ybWF0JylcclxuICAgICAgICAgICAgLnNldERlc2MoYEZvcm1hdCBmb3Igb3V0cHV0IGRhdGVzIChlLmcuLCAke0RFRkFVTFRfU0VUVElOR1Mub3V0cHV0RGF0ZUZvcm1hdH0pYClcclxuICAgICAgICAgICAgLmFkZFRleHQodGV4dCA9PiB0ZXh0XHJcbiAgICAgICAgICAgICAgICAuc2V0UGxhY2Vob2xkZXIoREVGQVVMVF9TRVRUSU5HUy5vdXRwdXREYXRlRm9ybWF0KVxyXG4gICAgICAgICAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLm91dHB1dERhdGVGb3JtYXQpXHJcbiAgICAgICAgICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3Mub3V0cHV0RGF0ZUZvcm1hdCA9IHZhbHVlO1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG5cclxuICAgICAgICBuZXcgU2V0dGluZyh0aGlzLmNvbnRhaW5lckVsKVxyXG4gICAgICAgICAgICAuc2V0TmFtZSgnRnJpZW5kbHkgZGF0ZSBmb3JtYXQnKVxyXG4gICAgICAgICAgICAuc2V0RGVzYyhgRm9ybWF0IGZvciBmcmllbmRseSBkYXRlIGRpc3BsYXkgKGUuZy4sICR7REVGQVVMVF9TRVRUSU5HUy5mcmllbmRseURhdGVGb3JtYXR9KS4gU3VwcG9ydHMgRCwgREQsIERERCwgRERERCwgTSwgTU0sIE1NTSwgTU1NTSwgWSwgWVksIFlZWSwgWVlZWU0uYClcclxuICAgICAgICAgICAgLmFkZFRleHQodGV4dCA9PiB0ZXh0XHJcbiAgICAgICAgICAgICAgICAuc2V0UGxhY2Vob2xkZXIoREVGQVVMVF9TRVRUSU5HUy5mcmllbmRseURhdGVGb3JtYXQpXHJcbiAgICAgICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZnJpZW5kbHlEYXRlRm9ybWF0KVxyXG4gICAgICAgICAgICAgICAgLm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmZyaWVuZGx5RGF0ZUZvcm1hdCA9IHZhbHVlO1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG5cclxuICAgICAgICBuZXcgU2V0dGluZyh0aGlzLmNvbnRhaW5lckVsKVxyXG4gICAgICAgICAgICAuc2V0TmFtZSgnRGF0ZSBzZXBhcmF0b3InKVxyXG4gICAgICAgICAgICAuc2V0RGVzYyhgU2VwYXJhdG9yIGJldHdlZW4gZGF0ZXMgKGUuZy4sIFwiJHtERUZBVUxUX1NFVFRJTkdTLmRhdGVTZXBhcmF0b3J9XCIpYClcclxuICAgICAgICAgICAgLmFkZFRleHQodGV4dCA9PiB0ZXh0XHJcbiAgICAgICAgICAgICAgICAuc2V0UGxhY2Vob2xkZXIoREVGQVVMVF9TRVRUSU5HUy5kYXRlU2VwYXJhdG9yKVxyXG4gICAgICAgICAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmRhdGVTZXBhcmF0b3IpXHJcbiAgICAgICAgICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuZGF0ZVNlcGFyYXRvciA9IHZhbHVlO1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgY3JlYXRlV2lraUxpbmtTZXR0aW5ncygpIHtcclxuICAgICAgICBuZXcgU2V0dGluZyh0aGlzLmNvbnRhaW5lckVsKVxyXG4gICAgICAgICAgICAuc2V0TmFtZSgnQ3JlYXRlIHdpa2kgbGlua3MnKVxyXG4gICAgICAgICAgICAuc2V0RGVzYygnQ3JlYXRlIHdpa2kgbGlua3MgZm9yIGluc2VydGVkIGRhdGVzJylcclxuICAgICAgICAgICAgLmFkZFRvZ2dsZSh0b2dnbGUgPT4gdG9nZ2xlXHJcbiAgICAgICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuY3JlYXRlV2lraUxpbmtzKVxyXG4gICAgICAgICAgICAgICAgLm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmNyZWF0ZVdpa2lMaW5rcyA9IHZhbHVlO1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGxheSgpO1xyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5wbHVnaW4uc2V0dGluZ3MuY3JlYXRlV2lraUxpbmtzKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlTm9uRXhpc3RlbnRGaWxlc1NldHRpbmdzKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgY3JlYXRlTm9uRXhpc3RlbnRGaWxlc1NldHRpbmdzKCkge1xyXG4gICAgICAgIG5ldyBTZXR0aW5nKHRoaXMuY29udGFpbmVyRWwpXHJcbiAgICAgICAgICAgIC5zZXROYW1lKCdDcmVhdGUgbm9uLWV4aXN0ZW50IGZpbGVzJylcclxuICAgICAgICAgICAgLnNldERlc2MoJ1doYXQgdG8gZG8gaWYgYSB3aWtpIGxpbmtlZCBmaWxlIGRvZXMgbm90IGV4aXN0JylcclxuICAgICAgICAgICAgLmFkZERyb3Bkb3duKGRyb3Bkb3duID0+IGRyb3Bkb3duXHJcbiAgICAgICAgICAgICAgICAuYWRkT3B0aW9uKCdkby1ub3QtY3JlYXRlJywgJ0RvIG5vdCBjcmVhdGUnKVxyXG4gICAgICAgICAgICAgICAgLmFkZE9wdGlvbignc2FtZS1mb2xkZXInLCAnQ3JlYXRlIGluIHNhbWUgZm9sZGVyJylcclxuICAgICAgICAgICAgICAgIC5hZGRPcHRpb24oJ2N1c3RvbS1mb2xkZXInLCAnQ3JlYXRlIGluIGN1c3RvbSBmb2xkZXInKVxyXG4gICAgICAgICAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmNyZWF0ZU5vbkV4aXN0ZW50RmlsZXMpXHJcbiAgICAgICAgICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiAnZG8tbm90LWNyZWF0ZScgfCAnc2FtZS1mb2xkZXInIHwgJ2N1c3RvbS1mb2xkZXInKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuY3JlYXRlTm9uRXhpc3RlbnRGaWxlcyA9IHZhbHVlO1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGxheSgpO1xyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5wbHVnaW4uc2V0dGluZ3MuY3JlYXRlTm9uRXhpc3RlbnRGaWxlcyA9PT0gJ2N1c3RvbS1mb2xkZXInKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlQ3VzdG9tRm9sZGVyUGF0aFNldHRpbmcoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBjcmVhdGVDdXN0b21Gb2xkZXJQYXRoU2V0dGluZygpIHtcclxuICAgICAgICBuZXcgU2V0dGluZyh0aGlzLmNvbnRhaW5lckVsKVxyXG4gICAgICAgICAgICAuc2V0TmFtZSgnQ3VzdG9tIGZvbGRlciBwYXRoJylcclxuICAgICAgICAgICAgLnNldERlc2MoJ1BhdGggdG8gdGhlIGZvbGRlciB3aGVyZSBuZXcgZmlsZXMgc2hvdWxkIGJlIGNyZWF0ZWQgKGUuZy4sIFwiRGFpbHkgTm90ZXMvMjAyNVwiKScpXHJcbiAgICAgICAgICAgIC5hZGRUZXh0KHRleHQgPT4ge1xyXG4gICAgICAgICAgICAgICAgdGV4dC5zZXRQbGFjZWhvbGRlcignRW50ZXIgZm9sZGVyIHBhdGgnKVxyXG4gICAgICAgICAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5jdXN0b21Gb2xkZXJQYXRoIHx8ICcnKVxyXG4gICAgICAgICAgICAgICAgICAgIC5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuY3VzdG9tRm9sZGVyUGF0aCA9IHZhbHVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICB9XHJcbn0iLCAiaW1wb3J0IHsgQXBwLCBOb3RpY2UsIFRGb2xkZXIgfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCB7IFBsdWdpblNldHRpbmdzLCBEYXRlUmFuZ2UsIERFRkFVTFRfU0VUVElOR1MgfSBmcm9tICcuL3R5cGVzJztcclxuaW1wb3J0IHsgRGF0ZVV0aWxzIH0gZnJvbSAnLi9kYXRlVXRpbHMnO1xyXG5cclxuZXhwb3J0IGNsYXNzIERhdGVSYW5nZUV4cGFuZGVyIHtcclxuICAgIGFwcDogQXBwO1xyXG4gICAgc2V0dGluZ3M6IFBsdWdpblNldHRpbmdzO1xyXG4gICAgZGF0ZVV0aWxzOiBEYXRlVXRpbHM7XHJcblxyXG4gICAgY29uc3RydWN0b3IoYXBwOiBBcHAsIHNldHRpbmdzOiBQbHVnaW5TZXR0aW5ncywgZGF0ZVV0aWxzOiBEYXRlVXRpbHMpIHtcclxuICAgICAgICB0aGlzLmFwcCA9IGFwcDtcclxuICAgICAgICB0aGlzLnNldHRpbmdzID0gc2V0dGluZ3M7XHJcbiAgICAgICAgdGhpcy5kYXRlVXRpbHMgPSBkYXRlVXRpbHM7XHJcbiAgICB9XHJcblxyXG4gICAgd3JhcEluQ2FsbG91dChkYXRlU3RhcnRBbmRFbmQ6IERhdGVSYW5nZSwgaW5zZXJ0ZWREYXRlUmFuZ2U6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgY29uc3QgW3N0YXJ0RGF0ZUZvcm1hdCwgZW5kRGF0ZUZvcm1hdF0gPSB0aGlzLmdldEZvcm1hdGVkU3RhcnRBbmRFbmREYXRlcyhkYXRlU3RhcnRBbmRFbmQpO1xyXG4gICAgICAgIHJldHVybiBgXFxuPiBbIVNVTU1BUlldLSBEYXRlIHJhbmdlOiAke3N0YXJ0RGF0ZUZvcm1hdH0gdG8gJHtlbmREYXRlRm9ybWF0fVxcbj4gJHtpbnNlcnRlZERhdGVSYW5nZX1cXG5gO1xyXG4gICAgfVxyXG5cclxuICAgIGV4cGFuZERhdGVSYW5nZShkYXRlU3RhcnRBbmRFbmQ6IERhdGVSYW5nZSk6IHN0cmluZyB8IG51bGx7XHJcbiAgICAgICAgbGV0IHRvdGFsRGF0ZXMgPSAwO1xyXG4gICAgICAgIGxldCBjcmVhdGVkRmlsZXMgPSAwO1xyXG4gICAgICAgIGxldCBleGlzdGluZ0ZpbGVzID0gMDtcclxuICAgICAgICBsZXQgY3VzdG9tRm9sZGVyRXhpc3RzID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgbGV0IGRhdGVzID0gW107XHJcbiAgICAgICAgbGV0IGN1cnJlbnQgPSBuZXcgRGF0ZShkYXRlU3RhcnRBbmRFbmQuc3RhcnREYXRlKTtcclxuXHJcbiAgICAgICAgY29uc3QgY3VzdG9tRm9sZGVyID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKHRoaXMuc2V0dGluZ3MuY3VzdG9tRm9sZGVyUGF0aCk7XHJcbiAgICAgICAgXHJcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3JlYXRlTm9uRXhpc3RlbnRGaWxlcyA9PT0gJ2N1c3RvbS1mb2xkZXInICYmICEoY3VzdG9tRm9sZGVyIGluc3RhbmNlb2YgVEZvbGRlcikpIHtcclxuICAgICAgICAgICAgY3VzdG9tRm9sZGVyRXhpc3RzID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB3aGlsZSAoY3VycmVudCA8PSBkYXRlU3RhcnRBbmRFbmQuZW5kRGF0ZSkge1xyXG4gICAgICAgICAgICBsZXQgZm9ybWF0dGVkRGF0ZSA9IHRoaXMuZGF0ZVV0aWxzLmZvcm1hdERhdGVUb1N0cmluZyhjdXJyZW50LCB0aGlzLnNldHRpbmdzLm91dHB1dERhdGVGb3JtYXQsIERFRkFVTFRfU0VUVElOR1Mub3V0cHV0RGF0ZUZvcm1hdCk7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jcmVhdGVXaWtpTGlua3MpIHtcclxuICAgICAgICAgICAgICAgIGRhdGVzLnB1c2goYFtbJHtmb3JtYXR0ZWREYXRlfV1dYCk7XHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgZmlsZUNyZWF0aW9uUmVzdWx0ID0gdGhpcy5jcmVhdGVGaWxlSWZOZWVkZWQoZm9ybWF0dGVkRGF0ZSwgY3VzdG9tRm9sZGVyRXhpc3RzKTtcclxuICAgICAgICAgICAgICAgIGlmIChmaWxlQ3JlYXRpb25SZXN1bHQgPT09ICdjcmVhdGVkJylcclxuICAgICAgICAgICAgICAgICAgICBjcmVhdGVkRmlsZXMrKztcclxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGZpbGVDcmVhdGlvblJlc3VsdCA9PT0gJ2V4aXN0cycpXHJcbiAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmdGaWxlcysrO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgZGF0ZXMucHVzaChmb3JtYXR0ZWREYXRlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB0b3RhbERhdGVzKys7XHJcblxyXG4gICAgICAgICAgICBjdXJyZW50LnNldERhdGUoY3VycmVudC5nZXREYXRlKCkgKyAxKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChjcmVhdGVkRmlsZXMgPiAwICYmICFjdXN0b21Gb2xkZXJFeGlzdHMpIHtcclxuICAgICAgICAgICAgbmV3IE5vdGljZShgRm9sZGVyIFwiJHt0aGlzLnNldHRpbmdzLmN1c3RvbUZvbGRlclBhdGh9XCIgZG9lcyBub3QgZXhpc3QuIFVzaW5nIHBhcmVudCBmb2xkZXIgdG8gY3VycmVudCBub3RlIGluc3RlYWQuYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBbc3RhcnREYXRlRm9ybWF0LCBlbmREYXRlRm9ybWF0XSA9IHRoaXMuZ2V0Rm9ybWF0ZWRTdGFydEFuZEVuZERhdGVzKGRhdGVTdGFydEFuZEVuZCk7XHJcblxyXG4gICAgICAgIGNvbnN0IGNvbW1vbk5vdGljZVRleHQgPSBgSW5zZXJ0ZWQgJHt0b3RhbERhdGVzfSBkYXRlcyBmcm9tICR7c3RhcnREYXRlRm9ybWF0fSB0byAke2VuZERhdGVGb3JtYXR9YDtcclxuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jcmVhdGVOb25FeGlzdGVudEZpbGVzICE9PSAnZG8tbm90LWNyZWF0ZScpIHtcclxuICAgICAgICAgICAgbmV3IE5vdGljZShgJHtjb21tb25Ob3RpY2VUZXh0fVxcblxcblx1MjAyMiBGaWxlcyBjcmVhdGVkOiAke2NyZWF0ZWRGaWxlc31cXG5cdTIwMjIgRmlsZXMgc2tpcHBlZDogJHtleGlzdGluZ0ZpbGVzfWAsIDgwMDApO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIG5ldyBOb3RpY2UoY29tbW9uTm90aWNlVGV4dCwgODAwMCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gZGF0ZXMuam9pbih0aGlzLnNldHRpbmdzLmRhdGVTZXBhcmF0b3IpO1xyXG4gICAgfVxyXG5cclxuICAgIGNyZWF0ZUZpbGVJZk5lZWRlZChmb3JtYXR0ZWREYXRlOiBzdHJpbmcsIGN1c3RvbUZvbGRlckV4aXN0czogYm9vbGVhbik6ICdjcmVhdGVkJyB8ICdleGlzdHMnIHwgJ2ZhaWxlZCcge1xyXG4gICAgICAgIGNvbnN0IGN1cnJlbnRGaWxlID0gdGhpcy5hcHAud29ya3NwYWNlLmdldEFjdGl2ZUZpbGUoKTtcclxuICAgICAgICBpZiAoIWN1cnJlbnRGaWxlIHx8ICFjdXJyZW50RmlsZS5wYXJlbnQpIHtcclxuICAgICAgICAgICAgcmV0dXJuICdmYWlsZWQnO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgZmlsZU5hbWUgPSBgJHtmb3JtYXR0ZWREYXRlfS5tZGA7XHJcbiAgICAgICAgY29uc3QgZmlsZUV4aXN0cyA9IHRoaXMuZmlsZUV4aXN0c0luVmF1bHQoZm9ybWF0dGVkRGF0ZSk7XHJcblxyXG4gICAgICAgIGlmICghZmlsZUV4aXN0cykge1xyXG4gICAgICAgICAgICBsZXQgZmlsZVBhdGggPSAnJztcclxuXHJcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5jcmVhdGVOb25FeGlzdGVudEZpbGVzKSB7XHJcbiAgICAgICAgICAgICAgICBjYXNlICdzYW1lLWZvbGRlcic6XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudERpciA9IGN1cnJlbnRGaWxlLnBhcmVudC5wYXRoO1xyXG4gICAgICAgICAgICAgICAgICAgIGZpbGVQYXRoID0gY3VycmVudERpciA/IGAke2N1cnJlbnREaXJ9LyR7ZmlsZU5hbWV9YCA6IGZpbGVOYW1lO1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSAnY3VzdG9tLWZvbGRlcic6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1c3RvbUZvbGRlckV4aXN0cykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlUGF0aCA9IGAke3RoaXMuc2V0dGluZ3MuY3VzdG9tRm9sZGVyUGF0aH0vJHtmaWxlTmFtZX1gO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZhbGxiYWNrIHRvIHNhbWUgZm9sZGVyIGlmIGN1c3RvbSBwYXRoIGlzIGVtcHR5IG9yIG5vdCBmb3VuZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50RGlyID0gY3VycmVudEZpbGUucGFyZW50LnBhdGg7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVQYXRoID0gY3VycmVudERpciA/IGAke2N1cnJlbnREaXJ9LyR7ZmlsZU5hbWV9YCA6IGZpbGVOYW1lO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgJ2RvLW5vdC1jcmVhdGUnOlxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnZmFpbGVkJztcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdmYWlsZWQnO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoZmlsZVBhdGgpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuYXBwLnZhdWx0LmNyZWF0ZShmaWxlUGF0aCwgXCJcIik7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2NyZWF0ZWQnO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiAnZmFpbGVkJztcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gJ2V4aXN0cyc7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGZpbGVFeGlzdHNJblZhdWx0KGZvcm1hdHRlZERhdGU6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmFwcC5tZXRhZGF0YUNhY2hlLmdldEZpcnN0TGlua3BhdGhEZXN0KGZvcm1hdHRlZERhdGUsICcnKSAhPT0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGdldEZvcm1hdGVkU3RhcnRBbmRFbmREYXRlcyhkYXRlU3RhcnRBbmRFbmQ6IERhdGVSYW5nZSk6IFtzdHJpbmcsIHN0cmluZ10ge1xyXG4gICAgICAgIGNvbnN0IHN0YXJ0RGF0ZUZvcm1hdCA9IHRoaXMuZGF0ZVV0aWxzLmZvcm1hdERhdGVUb1N0cmluZyhkYXRlU3RhcnRBbmRFbmQuc3RhcnREYXRlLCB0aGlzLnNldHRpbmdzLmZyaWVuZGx5RGF0ZUZvcm1hdCwgREVGQVVMVF9TRVRUSU5HUy5mcmllbmRseURhdGVGb3JtYXQpO1xyXG4gICAgICAgIGNvbnN0IGVuZERhdGVGb3JtYXQgPSB0aGlzLmRhdGVVdGlscy5mb3JtYXREYXRlVG9TdHJpbmcoZGF0ZVN0YXJ0QW5kRW5kLmVuZERhdGUsIHRoaXMuc2V0dGluZ3MuZnJpZW5kbHlEYXRlRm9ybWF0LCBERUZBVUxUX1NFVFRJTkdTLmZyaWVuZGx5RGF0ZUZvcm1hdCk7XHJcblxyXG4gICAgICAgIHJldHVybiBbc3RhcnREYXRlRm9ybWF0LCBlbmREYXRlRm9ybWF0XTtcclxuICAgIH1cclxufSJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQUFBQSxtQkFBcUM7OztBQ0FyQyxzQkFBb0M7OztBQ0U3QixJQUFNLFlBQU4sTUFBZ0I7QUFBQSxFQUNuQixvQkFBb0IsZUFBeUQ7QUFDekUsUUFBSSxZQUFrQixjQUFjO0FBQ3BDLFFBQUk7QUFFSixRQUFJLGNBQWMsY0FBYyxXQUFXO0FBQ3ZDLGdCQUFVLGNBQWM7QUFBQSxJQUM1QixPQUFPO0FBQ0gsZ0JBQVUsSUFBSSxLQUFLLFNBQVM7QUFDNUIsWUFBTSxXQUFXLGNBQWM7QUFDL0IsWUFBTSxPQUFPLGNBQWM7QUFFM0IsY0FBUSxNQUFNO0FBQUEsUUFDVixLQUFLO0FBQ0Qsa0JBQVEsUUFBUSxVQUFVLFFBQVEsSUFBSSxXQUFXLENBQUM7QUFDbEQ7QUFBQSxRQUNKLEtBQUs7QUFDRCxrQkFBUSxRQUFRLFVBQVUsUUFBUSxJQUFLLFdBQVcsSUFBSyxDQUFDO0FBQ3hEO0FBQUEsUUFDSixLQUFLO0FBQ0Qsb0JBQVUsS0FBSyxnQkFBZ0IsV0FBVyxRQUFRO0FBQ2xEO0FBQUEsTUFDUjtBQUFBLElBQ0o7QUFFQSxRQUFJLFlBQVksU0FBUztBQUNyQixhQUFPO0FBQUEsSUFDWDtBQUVBLFVBQU0sa0JBQTZCO0FBQUEsTUFDL0I7QUFBQSxNQUNBO0FBQUEsSUFDSjtBQUVBLFdBQU87QUFBQSxFQUNYO0FBQUE7QUFBQSxFQUdBLG9CQUFvQixZQUFpQztBQUNqRCxRQUFJLENBQUMsS0FBSyxtQkFBbUIsVUFBVSxHQUFHO0FBQ3RDLGFBQU87QUFBQSxJQUNY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
|