You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2029 lines
283 KiB

3 years ago
'use strict';
var obsidian = require('obsidian');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var obsidian__default = /*#__PURE__*/_interopDefaultLegacy(obsidian);
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
function __spreadArray(to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
}
function createCommonjsModule(fn, basedir, module) {
return module = {
path: basedir,
exports: {},
require: function (path, base) {
return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
}
}, fn(module, module.exports), module.exports;
}
function commonjsRequire () {
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
}
var main = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, '__esModule', { value: true });
const DEFAULT_DAILY_NOTE_FORMAT = "YYYY-MM-DD";
const DEFAULT_WEEKLY_NOTE_FORMAT = "gggg-[W]ww";
const DEFAULT_MONTHLY_NOTE_FORMAT = "YYYY-MM";
const DEFAULT_QUARTERLY_NOTE_FORMAT = "YYYY-[Q]Q";
const DEFAULT_YEARLY_NOTE_FORMAT = "YYYY";
function shouldUsePeriodicNotesSettings(periodicity) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const periodicNotes = window.app.plugins.getPlugin("periodic-notes");
return periodicNotes && periodicNotes.settings?.[periodicity]?.enabled;
}
/**
* Read the user settings for the `daily-notes` plugin
* to keep behavior of creating a new note in-sync.
*/
function getDailyNoteSettings() {
try {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { internalPlugins, plugins } = window.app;
if (shouldUsePeriodicNotesSettings("daily")) {
const { format, folder, template } = plugins.getPlugin("periodic-notes")?.settings?.daily || {};
return {
format: format || DEFAULT_DAILY_NOTE_FORMAT,
folder: folder?.trim() || "",
template: template?.trim() || "",
};
}
const { folder, format, template } = internalPlugins.getPluginById("daily-notes")?.instance?.options || {};
return {
format: format || DEFAULT_DAILY_NOTE_FORMAT,
folder: folder?.trim() || "",
template: template?.trim() || "",
};
}
catch (err) {
console.info("No custom daily note settings found!", err);
}
}
/**
* Read the user settings for the `weekly-notes` plugin
* to keep behavior of creating a new note in-sync.
*/
function getWeeklyNoteSettings() {
try {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const pluginManager = window.app.plugins;
const calendarSettings = pluginManager.getPlugin("calendar")?.options;
const periodicNotesSettings = pluginManager.getPlugin("periodic-notes")?.settings?.weekly;
if (shouldUsePeriodicNotesSettings("weekly")) {
return {
format: periodicNotesSettings.format || DEFAULT_WEEKLY_NOTE_FORMAT,
folder: periodicNotesSettings.folder?.trim() || "",
template: periodicNotesSettings.template?.trim() || "",
};
}
const settings = calendarSettings || {};
return {
format: settings.weeklyNoteFormat || DEFAULT_WEEKLY_NOTE_FORMAT,
folder: settings.weeklyNoteFolder?.trim() || "",
template: settings.weeklyNoteTemplate?.trim() || "",
};
}
catch (err) {
console.info("No custom weekly note settings found!", err);
}
}
/**
* Read the user settings for the `periodic-notes` plugin
* to keep behavior of creating a new note in-sync.
*/
function getMonthlyNoteSettings() {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const pluginManager = window.app.plugins;
try {
const settings = (shouldUsePeriodicNotesSettings("monthly") &&
pluginManager.getPlugin("periodic-notes")?.settings?.monthly) ||
{};
return {
format: settings.format || DEFAULT_MONTHLY_NOTE_FORMAT,
folder: settings.folder?.trim() || "",
template: settings.template?.trim() || "",
};
}
catch (err) {
console.info("No custom monthly note settings found!", err);
}
}
/**
* Read the user settings for the `periodic-notes` plugin
* to keep behavior of creating a new note in-sync.
*/
function getQuarterlyNoteSettings() {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const pluginManager = window.app.plugins;
try {
const settings = (shouldUsePeriodicNotesSettings("quarterly") &&
pluginManager.getPlugin("periodic-notes")?.settings?.quarterly) ||
{};
return {
format: settings.format || DEFAULT_QUARTERLY_NOTE_FORMAT,
folder: settings.folder?.trim() || "",
template: settings.template?.trim() || "",
};
}
catch (err) {
console.info("No custom quarterly note settings found!", err);
}
}
/**
* Read the user settings for the `periodic-notes` plugin
* to keep behavior of creating a new note in-sync.
*/
function getYearlyNoteSettings() {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const pluginManager = window.app.plugins;
try {
const settings = (shouldUsePeriodicNotesSettings("yearly") &&
pluginManager.getPlugin("periodic-notes")?.settings?.yearly) ||
{};
return {
format: settings.format || DEFAULT_YEARLY_NOTE_FORMAT,
folder: settings.folder?.trim() || "",
template: settings.template?.trim() || "",
};
}
catch (err) {
console.info("No custom yearly note settings found!", err);
}
}
// Credit: @creationix/path.js
function join(...partSegments) {
// Split the inputs into a list of path commands.
let parts = [];
for (let i = 0, l = partSegments.length; i < l; i++) {
parts = parts.concat(partSegments[i].split("/"));
}
// Interpret the path commands to get the new resolved path.
const newParts = [];
for (let i = 0, l = parts.length; i < l; i++) {
const part = parts[i];
// Remove leading and trailing slashes
// Also remove "." segments
if (!part || part === ".")
continue;
// Push new path segments.
else
newParts.push(part);
}
// Preserve the initial slash if there was one.
if (parts[0] === "")
newParts.unshift("");
// Turn back into a single string path.
return newParts.join("/");
}
function basename(fullPath) {
let base = fullPath.substring(fullPath.lastIndexOf("/") + 1);
if (base.lastIndexOf(".") != -1)
base = base.substring(0, base.lastIndexOf("."));
return base;
}
async function ensureFolderExists(path) {
const dirs = path.replace(/\\/g, "/").split("/");
dirs.pop(); // remove basename
if (dirs.length) {
const dir = join(...dirs);
if (!window.app.vault.getAbstractFileByPath(dir)) {
await window.app.vault.createFolder(dir);
}
}
}
async function getNotePath(directory, filename) {
if (!filename.endsWith(".md")) {
filename += ".md";
}
const path = obsidian__default["default"].normalizePath(join(directory, filename));
await ensureFolderExists(path);
return path;
}
async function getTemplateInfo(template) {
const { metadataCache, vault } = window.app;
const templatePath = obsidian__default["default"].normalizePath(template);
if (templatePath === "/") {
return Promise.resolve(["", null]);
}
try {
const templateFile = metadataCache.getFirstLinkpathDest(templatePath, "");
const contents = await vault.cachedRead(templateFile);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const IFoldInfo = window.app.foldManager.load(templateFile);
return [contents, IFoldInfo];
}
catch (err) {
console.error(`Failed to read the daily note template '${templatePath}'`, err);
new obsidian__default["default"].Notice("Failed to read the daily note template");
return ["", null];
}
}
/**
* dateUID is a way of weekly identifying daily/weekly/monthly notes.
* They are prefixed with the granularity to avoid ambiguity.
*/
function getDateUID(date, granularity = "day") {
const ts = date.clone().startOf(granularity).format();
return `${granularity}-${ts}`;
}
function removeEscapedCharacters(format) {
return format.replace(/\[[^\]]*\]/g, ""); // remove everything within brackets
}
/**
* XXX: When parsing dates that contain both week numbers and months,
* Moment choses to ignore the week numbers. For the week dateUID, we
* want the opposite behavior. Strip the MMM from the format to patch.
*/
function isFormatAmbiguous(format, granularity) {
if (granularity === "week") {
const cleanFormat = removeEscapedCharacters(format);
return (/w{1,2}/i.test(cleanFormat) &&
(/M{1,4}/.test(cleanFormat) || /D{1,4}/.test(cleanFormat)));
}
return false;
}
function getDateFromFile(file, granularity) {
return getDateFromFilename(file.basename, granularity);
}
function getDateFromPath(path, granularity) {
return getDateFromFilename(basename(path), granularity);
}
function getDateFromFilename(filename, granularity) {
const getSettings = {
day: getDailyNoteSettings,
week: getWeeklyNoteSettings,
month: getMonthlyNoteSettings,
quarter: getQuarterlyNoteSettings,
year: getYearlyNoteSettings,
};
const format = getSettings[granularity]().format.split("/").pop();
const noteDate = window.moment(filename, format, true);
if (!noteDate.isValid()) {
return null;
}
if (isFormatAmbiguous(format, granularity)) {
if (granularity === "week") {
const cleanFormat = removeEscapedCharacters(format);
if (/w{1,2}/i.test(cleanFormat)) {
return window.moment(filename,
// If format contains week, remove day & month formatting
format.replace(/M{1,4}/g, "").replace(/D{1,4}/g, ""), false);
}
}
}
return noteDate;
}
class DailyNotesFolderMissingError extends Error {
}
/**
* This function mimics the behavior of the daily-notes plugin
* so it will replace {{date}}, {{title}}, and {{time}} with the
* formatted timestamp.
*
* Note: it has an added bonus that it's not 'today' specific.
*/
async function createDailyNote(date) {
const app = window.app;
const { vault } = app;
const moment = window.moment;
const { template, format, folder } = getDailyNoteSettings();
const [templateContents, IFoldInfo] = await getTemplateInfo(template);
const filename = date.format(format);
const normalizedPath = await getNotePath(folder, filename);
try {
const createdFile = await vault.create(normalizedPath, templateContents
.replace(/{{\s*date\s*}}/gi, filename)
.replace(/{{\s*time\s*}}/gi, moment().format("HH:mm"))
.replace(/{{\s*title\s*}}/gi, filename)
.replace(/{{\s*(date|time)\s*(([+-]\d+)([yqmwdhs]))?\s*(:.+?)?}}/gi, (_, _timeOrDate, calc, timeDelta, unit, momentFormat) => {
const now = moment();
const currentDate = date.clone().set({
hour: now.get("hour"),
minute: now.get("minute"),
second: now.get("second"),
});
if (calc) {
currentDate.add(parseInt(timeDelta, 10), unit);
}
if (momentFormat) {
return currentDate.format(momentFormat.substring(1).trim());
}
return currentDate.format(format);
})
.replace(/{{\s*yesterday\s*}}/gi, date.clone().subtract(1, "day").format(format))
.replace(/{{\s*tomorrow\s*}}/gi, date.clone().add(1, "d").format(format)));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
app.foldManager.save(createdFile, IFoldInfo);
return createdFile;
}
catch (err) {
console.error(`Failed to create file: '${normalizedPath}'`, err);
new obsidian__default["default"].Notice("Unable to create new file.");
}
}
function getDailyNote(date, dailyNotes) {
return dailyNotes[getDateUID(date, "day")] ?? null;
}
function getAllDailyNotes() {
/**
* Find all daily notes in the daily note folder
*/
const { vault } = window.app;
const { folder } = getDailyNoteSettings();
const dailyNotesFolder = vault.getAbstractFileByPath(obsidian__default["default"].normalizePath(folder));
if (!dailyNotesFolder) {
throw new DailyNotesFolderMissingError("Failed to find daily notes folder");
}
const dailyNotes = {};
obsidian__default["default"].Vault.recurseChildren(dailyNotesFolder, (note) => {
if (note instanceof obsidian__default["default"].TFile) {
const date = getDateFromFile(note, "day");
if (date) {
const dateString = getDateUID(date, "day");
dailyNotes[dateString] = note;
}
}
});
return dailyNotes;
}
class WeeklyNotesFolderMissingError extends Error {
}
function getDaysOfWeek() {
const { moment } = window;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let weekStart = moment.localeData()._week.dow;
const daysOfWeek = [
"sunday",
"monday",
"tuesday",
"wednesday",
"thursday",
"friday",
"saturday",
];
while (weekStart) {
daysOfWeek.push(daysOfWeek.shift());
weekStart--;
}
return daysOfWeek;
}
function getDayOfWeekNumericalValue(dayOfWeekName) {
return getDaysOfWeek().indexOf(dayOfWeekName.toLowerCase());
}
async function createWeeklyNote(date) {
const { vault } = window.app;
const { template, format, folder } = getWeeklyNoteSettings();
const [templateContents, IFoldInfo] = await getTemplateInfo(template);
const filename = date.format(format);
const normalizedPath = await getNotePath(folder, filename);
try {
const createdFile = await vault.create(normalizedPath, templateContents
.replace(/{{\s*(date|time)\s*(([+-]\d+)([yqmwdhs]))?\s*(:.+?)?}}/gi, (_, _timeOrDate, calc, timeDelta, unit, momentFormat) => {
const now = window.moment();
const currentDate = date.clone().set({
hour: now.get("hour"),
minute: now.get("minute"),
second: now.get("second"),
});
if (calc) {
currentDate.add(parseInt(timeDelta, 10), unit);
}
if (momentFormat) {
return currentDate.format(momentFormat.substring(1).trim());
}
return currentDate.format(format);
})
.replace(/{{\s*title\s*}}/gi, filename)
.replace(/{{\s*time\s*}}/gi, window.moment().format("HH:mm"))
.replace(/{{\s*(sunday|monday|tuesday|wednesday|thursday|friday|saturday)\s*:(.*?)}}/gi, (_, dayOfWeek, momentFormat) => {
const day = getDayOfWeekNumericalValue(dayOfWeek);
return date.weekday(day).format(momentFormat.trim());
}));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
window.app.foldManager.save(createdFile, IFoldInfo);
return createdFile;
}
catch (err) {
console.error(`Failed to create file: '${normalizedPath}'`, err);
new obsidian__default["default"].Notice("Unable to create new file.");
}
}
function getWeeklyNote(date, weeklyNotes) {
return weeklyNotes[getDateUID(date, "week")] ?? null;
}
function getAllWeeklyNotes() {
const weeklyNotes = {};
if (!appHasWeeklyNotesPluginLoaded()) {
return weeklyNotes;
}
const { vault } = window.app;
const { folder } = getWeeklyNoteSettings();
const weeklyNotesFolder = vault.getAbstractFileByPath(obsidian__default["default"].normalizePath(folder));
if (!weeklyNotesFolder) {
throw new WeeklyNotesFolderMissingError("Failed to find weekly notes folder");
}
obsidian__default["default"].Vault.recurseChildren(weeklyNotesFolder, (note) => {
if (note instanceof obsidian__default["default"].TFile) {
const date = getDateFromFile(note, "week");
if (date) {
const dateString = getDateUID(date, "week");
weeklyNotes[dateString] = note;
}
}
});
return weeklyNotes;
}
class MonthlyNotesFolderMissingError extends Error {
}
/**
* This function mimics the behavior of the daily-notes plugin
* so it will replace {{date}}, {{title}}, and {{time}} with the
* formatted timestamp.
*
* Note: it has an added bonus that it's not 'today' specific.
*/
async function createMonthlyNote(date) {
const { vault } = window.app;
const { template, format, folder } = getMonthlyNoteSettings();
const [templateContents, IFoldInfo] = await getTemplateInfo(template);
const filename = date.format(format);
const normalizedPath = await getNotePath(folder, filename);
try {
const createdFile = await vault.create(normalizedPath, templateContents
.replace(/{{\s*(date|time)\s*(([+-]\d+)([yqmwdhs]))?\s*(:.+?)?}}/gi, (_, _timeOrDate, calc, timeDelta, unit, momentFormat) => {
const now = window.moment();
const currentDate = date.clone().set({
hour: now.get("hour"),
minute: now.get("minute"),
second: now.get("second"),
});
if (calc) {
currentDate.add(parseInt(timeDelta, 10), unit);
}
if (momentFormat) {
return currentDate.format(momentFormat.substring(1).trim());
}
return currentDate.format(format);
})
.replace(/{{\s*date\s*}}/gi, filename)
.replace(/{{\s*time\s*}}/gi, window.moment().format("HH:mm"))
.replace(/{{\s*title\s*}}/gi, filename));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
window.app.foldManager.save(createdFile, IFoldInfo);
return createdFile;
}
catch (err) {
console.error(`Failed to create file: '${normalizedPath}'`, err);
new obsidian__default["default"].Notice("Unable to create new file.");
}
}
function getMonthlyNote(date, monthlyNotes) {
return monthlyNotes[getDateUID(date, "month")] ?? null;
}
function getAllMonthlyNotes() {
const monthlyNotes = {};
if (!appHasMonthlyNotesPluginLoaded()) {
return monthlyNotes;
}
const { vault } = window.app;
const { folder } = getMonthlyNoteSettings();
const monthlyNotesFolder = vault.getAbstractFileByPath(obsidian__default["default"].normalizePath(folder));
if (!monthlyNotesFolder) {
throw new MonthlyNotesFolderMissingError("Failed to find monthly notes folder");
}
obsidian__default["default"].Vault.recurseChildren(monthlyNotesFolder, (note) => {
if (note instanceof obsidian__default["default"].TFile) {
const date = getDateFromFile(note, "month");
if (date) {
const dateString = getDateUID(date, "month");
monthlyNotes[dateString] = note;
}
}
});
return monthlyNotes;
}
class QuarterlyNotesFolderMissingError extends Error {
}
/**
* This function mimics the behavior of the daily-notes plugin
* so it will replace {{date}}, {{title}}, and {{time}} with the
* formatted timestamp.
*
* Note: it has an added bonus that it's not 'today' specific.
*/
async function createQuarterlyNote(date) {
const { vault } = window.app;
const { template, format, folder } = getQuarterlyNoteSettings();
const [templateContents, IFoldInfo] = await getTemplateInfo(template);
const filename = date.format(format);
const normalizedPath = await getNotePath(folder, filename);
try {
const createdFile = await vault.create(normalizedPath, templateContents
.replace(/{{\s*(date|time)\s*(([+-]\d+)([yqmwdhs]))?\s*(:.+?)?}}/gi, (_, _timeOrDate, calc, timeDelta, unit, momentFormat) => {
const now = window.moment();
const currentDate = date.clone().set({
hour: now.get("hour"),
minute: now.get("minute"),
second: now.get("second"),
});
if (calc) {
currentDate.add(parseInt(timeDelta, 10), unit);
}
if (momentFormat) {
return currentDate.format(momentFormat.substring(1).trim());
}
return currentDate.format(format);
})
.replace(/{{\s*date\s*}}/gi, filename)
.replace(/{{\s*time\s*}}/gi, window.moment().format("HH:mm"))
.replace(/{{\s*title\s*}}/gi, filename));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
window.app.foldManager.save(createdFile, IFoldInfo);
return createdFile;
}
catch (err) {
console.error(`Failed to create file: '${normalizedPath}'`, err);
new obsidian__default["default"].Notice("Unable to create new file.");
}
}
function getQuarterlyNote(date, quarterly) {
return quarterly[getDateUID(date, "quarter")] ?? null;
}
function getAllQuarterlyNotes() {
const quarterly = {};
if (!appHasQuarterlyNotesPluginLoaded()) {
return quarterly;
}
const { vault } = window.app;
const { folder } = getQuarterlyNoteSettings();
const quarterlyFolder = vault.getAbstractFileByPath(obsidian__default["default"].normalizePath(folder));
if (!quarterlyFolder) {
throw new QuarterlyNotesFolderMissingError("Failed to find quarterly notes folder");
}
obsidian__default["default"].Vault.recurseChildren(quarterlyFolder, (note) => {
if (note instanceof obsidian__default["default"].TFile) {
const date = getDateFromFile(note, "quarter");
if (date) {
const dateString = getDateUID(date, "quarter");
quarterly[dateString] = note;
}
}
});
return quarterly;
}
class YearlyNotesFolderMissingError extends Error {
}
/**
* This function mimics the behavior of the daily-notes plugin
* so it will replace {{date}}, {{title}}, and {{time}} with the
* formatted timestamp.
*
* Note: it has an added bonus that it's not 'today' specific.
*/
async function createYearlyNote(date) {
const { vault } = window.app;
const { template, format, folder } = getYearlyNoteSettings();
const [templateContents, IFoldInfo] = await getTemplateInfo(template);
const filename = date.format(format);
const normalizedPath = await getNotePath(folder, filename);
try {
const createdFile = await vault.create(normalizedPath, templateContents
.replace(/{{\s*(date|time)\s*(([+-]\d+)([yqmwdhs]))?\s*(:.+?)?}}/gi, (_, _timeOrDate, calc, timeDelta, unit, momentFormat) => {
const now = window.moment();
const currentDate = date.clone().set({
hour: now.get("hour"),
minute: now.get("minute"),
second: now.get("second"),
});
if (calc) {
currentDate.add(parseInt(timeDelta, 10), unit);
}
if (momentFormat) {
return currentDate.format(momentFormat.substring(1).trim());
}
return currentDate.format(format);
})
.replace(/{{\s*date\s*}}/gi, filename)
.replace(/{{\s*time\s*}}/gi, window.moment().format("HH:mm"))
.replace(/{{\s*title\s*}}/gi, filename));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
window.app.foldManager.save(createdFile, IFoldInfo);
return createdFile;
}
catch (err) {
console.error(`Failed to create file: '${normalizedPath}'`, err);
new obsidian__default["default"].Notice("Unable to create new file.");
}
}
function getYearlyNote(date, yearlyNotes) {
return yearlyNotes[getDateUID(date, "year")] ?? null;
}
function getAllYearlyNotes() {
const yearlyNotes = {};
if (!appHasYearlyNotesPluginLoaded()) {
return yearlyNotes;
}
const { vault } = window.app;
const { folder } = getYearlyNoteSettings();
const yearlyNotesFolder = vault.getAbstractFileByPath(obsidian__default["default"].normalizePath(folder));
if (!yearlyNotesFolder) {
throw new YearlyNotesFolderMissingError("Failed to find yearly notes folder");
}
obsidian__default["default"].Vault.recurseChildren(yearlyNotesFolder, (note) => {
if (note instanceof obsidian__default["default"].TFile) {
const date = getDateFromFile(note, "year");
if (date) {
const dateString = getDateUID(date, "year");
yearlyNotes[dateString] = note;
}
}
});
return yearlyNotes;
}
function appHasDailyNotesPluginLoaded() {
const { app } = window;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const dailyNotesPlugin = app.internalPlugins.plugins["daily-notes"];
if (dailyNotesPlugin && dailyNotesPlugin.enabled) {
return true;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const periodicNotes = app.plugins.getPlugin("periodic-notes");
return periodicNotes && periodicNotes.settings?.daily?.enabled;
}
/**
* XXX: "Weekly Notes" live in either the Calendar plugin or the periodic-notes plugin.
* Check both until the weekly notes feature is removed from the Calendar plugin.
*/
function appHasWeeklyNotesPluginLoaded() {
const { app } = window;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (app.plugins.getPlugin("calendar")) {
return true;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const periodicNotes = app.plugins.getPlugin("periodic-notes");
return periodicNotes && periodicNotes.settings?.weekly?.enabled;
}
function appHasMonthlyNotesPluginLoaded() {
const { app } = window;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const periodicNotes = app.plugins.getPlugin("periodic-notes");
return periodicNotes && periodicNotes.settings?.monthly?.enabled;
}
function appHasQuarterlyNotesPluginLoaded() {
const { app } = window;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const periodicNotes = app.plugins.getPlugin("periodic-notes");
return periodicNotes && periodicNotes.settings?.quarterly?.enabled;
}
function appHasYearlyNotesPluginLoaded() {
const { app } = window;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const periodicNotes = app.plugins.getPlugin("periodic-notes");
return periodicNotes && periodicNotes.settings?.yearly?.enabled;
}
function getPeriodicNoteSettings(granularity) {
const getSettings = {
day: getDailyNoteSettings,
week: getWeeklyNoteSettings,
month: getMonthlyNoteSettings,
quarter: getQuarterlyNoteSettings,
year: getYearlyNoteSettings,
}[granularity];
return getSettings();
}
function createPeriodicNote(granularity, date) {
const createFn = {
day: createDailyNote,
month: createMonthlyNote,
week: createWeeklyNote,
};
return createFn[granularity](date);
}
exports.DEFAULT_DAILY_NOTE_FORMAT = DEFAULT_DAILY_NOTE_FORMAT;
exports.DEFAULT_MONTHLY_NOTE_FORMAT = DEFAULT_MONTHLY_NOTE_FORMAT;
exports.DEFAULT_QUARTERLY_NOTE_FORMAT = DEFAULT_QUARTERLY_NOTE_FORMAT;
exports.DEFAULT_WEEKLY_NOTE_FORMAT = DEFAULT_WEEKLY_NOTE_FORMAT;
exports.DEFAULT_YEARLY_NOTE_FORMAT = DEFAULT_YEARLY_NOTE_FORMAT;
exports.appHasDailyNotesPluginLoaded = appHasDailyNotesPluginLoaded;
exports.appHasMonthlyNotesPluginLoaded = appHasMonthlyNotesPluginLoaded;
exports.appHasQuarterlyNotesPluginLoaded = appHasQuarterlyNotesPluginLoaded;
exports.appHasWeeklyNotesPluginLoaded = appHasWeeklyNotesPluginLoaded;
exports.appHasYearlyNotesPluginLoaded = appHasYearlyNotesPluginLoaded;
exports.createDailyNote = createDailyNote;
exports.createMonthlyNote = createMonthlyNote;
exports.createPeriodicNote = createPeriodicNote;
exports.createQuarterlyNote = createQuarterlyNote;
exports.createWeeklyNote = createWeeklyNote;
exports.createYearlyNote = createYearlyNote;
exports.getAllDailyNotes = getAllDailyNotes;
exports.getAllMonthlyNotes = getAllMonthlyNotes;
exports.getAllQuarterlyNotes = getAllQuarterlyNotes;
exports.getAllWeeklyNotes = getAllWeeklyNotes;
exports.getAllYearlyNotes = getAllYearlyNotes;
exports.getDailyNote = getDailyNote;
exports.getDailyNoteSettings = getDailyNoteSettings;
exports.getDateFromFile = getDateFromFile;
exports.getDateFromPath = getDateFromPath;
exports.getDateUID = getDateUID;
exports.getMonthlyNote = getMonthlyNote;
exports.getMonthlyNoteSettings = getMonthlyNoteSettings;
exports.getPeriodicNoteSettings = getPeriodicNoteSettings;
exports.getQuarterlyNote = getQuarterlyNote;
exports.getQuarterlyNoteSettings = getQuarterlyNoteSettings;
exports.getTemplateInfo = getTemplateInfo;
exports.getWeeklyNote = getWeeklyNote;
exports.getWeeklyNoteSettings = getWeeklyNoteSettings;
exports.getYearlyNote = getYearlyNote;
exports.getYearlyNoteSettings = getYearlyNoteSettings;
});
// Unique ID creation requires a high quality random # generator. In the browser we therefore
// require the crypto API and do not support built-in fallback to lower quality random number
// generators (like Math.random()).
var getRandomValues;
var rnds8 = new Uint8Array(16);
function rng() {
// lazy load so that environments that need to polyfill have a chance to do so
if (!getRandomValues) {
// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also,
// find the complete implementation of crypto (msCrypto) on IE11.
getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto);
if (!getRandomValues) {
throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
}
}
return getRandomValues(rnds8);
}
var REGEX = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
function validate(uuid) {
return typeof uuid === 'string' && REGEX.test(uuid);
}
/**
* Convert array of 16 byte values to UUID string format of the form:
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
*/
var byteToHex = [];
for (var i = 0; i < 256; ++i) {
byteToHex.push((i + 0x100).toString(16).substr(1));
}
function stringify(arr) {
var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
// Note: Be careful editing this code! It's been tuned for performance
// and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
var uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one
// of the following:
// - One or more input array values don't map to a hex octet (leading to
// "undefined" in the uuid)
// - Invalid input values for the RFC `version` or `variant` fields
if (!validate(uuid)) {
throw TypeError('Stringified UUID is invalid');
}
return uuid;
}
function v4(options, buf, offset) {
options = options || {};
var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
rnds[6] = rnds[6] & 0x0f | 0x40;
rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
if (buf) {
offset = offset || 0;
for (var i = 0; i < 16; ++i) {
buf[offset + i] = rnds[i];
}
return buf;
}
return stringify(rnds);
}
//! All of these methods are taken from https://www.npmjs.com/package/obsidian-daily-notes-interface.
function join() {
var partSegments = [];
for (var _i = 0; _i < arguments.length; _i++) {
partSegments[_i] = arguments[_i];
}
// Split the inputs into a list of path commands.
var parts = [];
for (var i = 0, l = partSegments.length; i < l; i++) {
parts = parts.concat(partSegments[i].split("/"));
}
// Interpret the path commands to get the new resolved path.
var newParts = [];
for (var i = 0, l = parts.length; i < l; i++) {
var part = parts[i];
// Remove leading and trailing slashes
// Also remove "." segments
if (!part || part === ".")
continue;
// Push new path segments.
else
newParts.push(part);
}
// Preserve the initial slash if there was one.
if (parts[0] === "")
newParts.unshift("");
// Turn back into a single string path.
return newParts.join("/");
}
function getNotePath(directory, filename) {
return __awaiter(this, void 0, void 0, function () {
var path;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!filename.endsWith(".md")) {
filename += ".md";
}
path = obsidian.normalizePath(join(directory, filename));
return [4 /*yield*/, ensureFolderExists(path)];
case 1:
_a.sent();
return [2 /*return*/, path];
}
});
});
}
function ensureFolderExists(path) {
return __awaiter(this, void 0, void 0, function () {
var dirs, dir;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
dirs = path.replace(/\\/g, "/").split("/");
dirs.pop(); // remove basename
if (!dirs.length) return [3 /*break*/, 2];
dir = join.apply(void 0, dirs);
if (!!window.app.vault.getAbstractFileByPath(dir)) return [3 /*break*/, 2];
return [4 /*yield*/, window.app.vault.createFolder(dir)];
case 1:
_a.sent();
_a.label = 2;
case 2: return [2 /*return*/];
}
});
});
}
function getDailyNotePath(date) {
return __awaiter(this, void 0, void 0, function () {
var _a, format, folder, filename, normalizedPath;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = main.getDailyNoteSettings(), format = _a.format, folder = _a.folder;
filename = date.format(format);
return [4 /*yield*/, getNotePath(folder, filename)];
case 1:
normalizedPath = _b.sent();
return [2 /*return*/, normalizedPath];
}
});
});
}
var DEFAULT_SETTINGS = {
openFileOnWrite: true,
openDailyInNewPane: false,
openFileOnWriteInNewPane: false,
openFileWithoutWriteInNewPane: false,
idField: "id",
useUID: false,
};
var AdvancedURI = /** @class */ (function (_super) {
__extends(AdvancedURI, _super);
function AdvancedURI() {
return _super !== null && _super.apply(this, arguments) || this;
}
AdvancedURI.prototype.onload = function () {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.loadSettings()];
case 1:
_a.sent();
this.addSettingTab(new SettingsTab(this.app, this));
this.addCommand({
id: "copy-uri-current-file",
name: "copy URI for file",
callback: function () { return _this.handleCopyFileURI(); }
});
this.addCommand({
id: "copy-uri-daily",
name: "copy URI for daily note",
callback: function () { return new EnterDataModal(_this).open(); }
});
this.addCommand({
id: "copy-uri-search-and-replace",
name: "copy URI for search and replace",
callback: function () {
var fileModal = new FileModal(_this, "Used file for search and replace");
fileModal.open();
fileModal.onChooseItem = function (filePath) {
var searchModal = new SearchModal(_this);
searchModal.open();
searchModal.onChooseSuggestion = function (item) {
new ReplaceModal(_this, item, filePath === null || filePath === void 0 ? void 0 : filePath.source).open();
};
};
},
});
this.addCommand({
id: "copy-uri-command",
name: "copy URI for command",
callback: function () {
var fileModal = new FileModal(_this, "Select a file to be opened before executing the command");
fileModal.open();
fileModal.onChooseItem = function (item) {
new CommandModal(_this, item === null || item === void 0 ? void 0 : item.source).open();
};
}
});
this.registerObsidianProtocolHandler("advanced-uri", function (e) { return __awaiter(_this, void 0, void 0, function () {
var parameters, createdDailyNote, parameter, file, index, extension, moment_1, allDailyNotes, dailyNote, _a;
var _this = this;
var _b, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
parameters = e;
createdDailyNote = false;
for (parameter in parameters) {
parameters[parameter] = decodeURIComponent(parameters[parameter]);
}
if (!parameters.uid) return [3 /*break*/, 1];
parameters.filepath = (_b = this.getFileFromUID(parameters.uid)) === null || _b === void 0 ? void 0 : _b.path;
return [3 /*break*/, 8];
case 1:
if (!parameters.filename) return [3 /*break*/, 2];
file = this.app.metadataCache.getFirstLinkpathDest(parameters.filename, "");
if (!file) {
file = this.app.vault.getMarkdownFiles().find(function (file) { var _a; return (_a = obsidian.parseFrontMatterAliases(_this.app.metadataCache.getFileCache(file).frontmatter)) === null || _a === void 0 ? void 0 : _a.includes(parameters.filename); });
}
parameters.filepath = (_c = file === null || file === void 0 ? void 0 : file.path) !== null && _c !== void 0 ? _c : obsidian.normalizePath(parameters.filename);
return [3 /*break*/, 8];
case 2:
if (!parameters.filepath) return [3 /*break*/, 3];
parameters.filepath = obsidian.normalizePath(parameters.filepath);
index = parameters.filepath.lastIndexOf(".");
extension = parameters.filepath.substring(index < 0 ? parameters.filepath.length : index);
if (extension === "") {
parameters.filepath = parameters.filepath + ".md";
}
return [3 /*break*/, 8];
case 3:
if (!(parameters.daily === "true")) return [3 /*break*/, 8];
if (!main.appHasDailyNotesPluginLoaded()) {
new obsidian.Notice("Daily notes plugin is not loaded");
return [2 /*return*/];
}
moment_1 = window.moment(Date.now());
allDailyNotes = main.getAllDailyNotes();
dailyNote = main.getDailyNote(moment_1, allDailyNotes);
if (!!dailyNote) return [3 /*break*/, 7];
if (!(parameters.exists === "true")) return [3 /*break*/, 5];
_a = parameters;
return [4 /*yield*/, getDailyNotePath(moment_1)];
case 4:
_a.filepath = _d.sent();
return [3 /*break*/, 7];
case 5: return [4 /*yield*/, main.createDailyNote(moment_1)];
case 6:
dailyNote = _d.sent();
createdDailyNote = true;
_d.label = 7;
case 7:
if (dailyNote !== undefined) {
parameters.filepath = dailyNote.path;
}
_d.label = 8;
case 8:
if (parameters.workspace || parameters.saveworkspace == "true") {
this.handleWorkspace(parameters);
}
else if (parameters.commandname || parameters.commandid) {
this.handleCommand(parameters);
}
else if (parameters.filepath && parameters.exists === "true") {
this.handleDoesFileExist(parameters);
}
else if (parameters.filepath && parameters.data) {
this.handleWrite(parameters, createdDailyNote);
}
else if (parameters.filepath && parameters.heading) {
this.handleOpen(parameters);
}
else if (parameters.filepath && parameters.block) {
this.handleOpen(parameters);
}
else if ((parameters.search || parameters.searchregex) && parameters.replace != undefined) {
this.handleSearchAndReplace(parameters);
}
else if (parameters.filepath) {
this.handleOpen(parameters);
}
else if (parameters.settingid) {
this.handleOpenSettings(parameters);
}
else if (parameters.updateplugins) {
this.handleUpdatePlugins(parameters);
}
return [2 /*return*/];
}
});
}); });
this.registerEvent(this.app.workspace.on('file-menu', function (menu, _, source) {
if (source !== "pane-more-options") {
return;
}
var view = _this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
if (!view) {
return;
}
menu.addItem(function (item) {
item.setTitle("Copy Advanced URI").setIcon('link')
.onClick(function (_) { return _this.handleCopyFileURI(); });
});
}));
return [2 /*return*/];
}
});
});
};
AdvancedURI.prototype.success = function (parameters) {
if (parameters["x-success"])
obsidian.request({ url: parameters["x-success"], });
};
AdvancedURI.prototype.failure = function (parameters) {
if (parameters["x-error"])
obsidian.request({ url: parameters["x-error"] });
};
AdvancedURI.prototype.getFileFromUID = function (uid) {
var _this = this;
var files = this.app.vault.getFiles();
var idKey = this.settings.idField;
return files.find(function (file) { var _a; return obsidian.parseFrontMatterEntry((_a = _this.app.metadataCache.getFileCache(file)) === null || _a === void 0 ? void 0 : _a.frontmatter, idKey) == uid; });
};
AdvancedURI.prototype.handleWorkspace = function (parameters) {
var _a, _b, _c;
var workspaces = (_c = (_b = (_a = this.app) === null || _a === void 0 ? void 0 : _a.internalPlugins) === null || _b === void 0 ? void 0 : _b.plugins) === null || _c === void 0 ? void 0 : _c.workspaces;
if (!workspaces) {
new obsidian.Notice("Cannot find Workspaces plugin. Please file an issue.");
this.failure(parameters);
}
else if (workspaces.enabled) {
if (parameters.saveworkspace == "true") {
var active = workspaces.instance.activeWorkspace;
workspaces.instance.saveWorkspace(active);
new obsidian.Notice("Saved current workspace to " + active);
}
if (parameters.workspace != undefined) {
workspaces.instance.loadWorkspace(parameters.workspace);
}
this.success(parameters);
}
else {
new obsidian.Notice("Workspaces plugin is not enabled");
this.failure(parameters);
}
};
AdvancedURI.prototype.handleCommand = function (parameters) {
return __awaiter(this, void 0, void 0, function () {
var view, editor, data, lines, rawCommands, command;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!parameters.filepath) return [3 /*break*/, 4];
if (!parameters.mode) return [3 /*break*/, 2];
return [4 /*yield*/, this.app.workspace.openLinkText(parameters.filepath, "/", undefined, {
state: { mode: "source" }
})];
case 1:
_a.sent();
view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
if (view) {
editor = view.editor;
data = editor.getValue();
if (parameters.mode === "append") {
editor.setValue(data + "\n");
lines = editor.lineCount();
editor.setCursor({ ch: 0, line: lines });
}
else if (parameters.mode === "prepend") {
editor.setValue("\n" + data);
editor.setCursor({ ch: 0, line: 0 });
}
else if (parameters.mode === "overwrite") {
editor.setValue("");
}
}
return [3 /*break*/, 4];
case 2: return [4 /*yield*/, this.app.workspace.openLinkText(parameters.filepath, "/", this.settings.openFileWithoutWriteInNewPane, this.getViewStateFromMode(parameters))];
case 3:
_a.sent();
_a.label = 4;
case 4:
if (parameters.commandid) {
this.app.commands.executeCommandById(parameters.commandid);
}
else if (parameters.commandname) {
rawCommands = this.app.commands.commands;
for (command in rawCommands) {
if (rawCommands[command].name === parameters.commandname) {
if (rawCommands[command].callback) {
rawCommands[command].callback();
}
else {
rawCommands[command].checkCallback();
}
break;
}
}
}
this.success(parameters);
return [2 /*return*/];
}
});
});
};
AdvancedURI.prototype.handleDoesFileExist = function (parameters) {
return __awaiter(this, void 0, void 0, function () {
var exists;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.app.vault.adapter.exists(parameters.filepath)];
case 1:
exists = _a.sent();
this.copyText((exists ? 1 : 0).toString());
this.success(parameters);
return [2 /*return*/];
}
});
});
};
AdvancedURI.prototype.handleSearchAndReplace = function (parameters) {
return __awaiter(this, void 0, void 0, function () {
var file, abstractFile, data, _a, pattern, flags, regex;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (parameters.filepath) {
abstractFile = this.app.vault.getAbstractFileByPath(parameters.filepath);
if (abstractFile instanceof obsidian.TFile) {
file = abstractFile;
}
}
else {
file = this.app.workspace.getActiveFile();
}
if (!file) return [3 /*break*/, 3];
return [4 /*yield*/, this.app.vault.read(file)];
case 1:
data = _b.sent();
if (parameters.searchregex) {
try {
_a = parameters.searchregex.match(/(\/?)(.+)\1([a-z]*)/i), pattern = _a[2], flags = _a[3];
regex = new RegExp(pattern, flags);
data = data.replace(regex, parameters.replace);
this.success(parameters);
}
catch (error) {
new obsidian.Notice("Can't parse " + parameters.searchregex + " as RegEx");
this.failure(parameters);
}
}
else {
data = data.replaceAll(parameters.search, parameters.replace);
this.success(parameters);
}
return [4 /*yield*/, this.writeAndOpenFile(file.path, data, parameters)];
case 2:
_b.sent();
return [3 /*break*/, 4];
case 3:
new obsidian.Notice("Cannot find file");
this.failure(parameters);
_b.label = 4;
case 4: return [2 /*return*/];
}
});
});
};
AdvancedURI.prototype.handleWrite = function (parameters, createdDailyNote) {
if (createdDailyNote === void 0) { createdDailyNote = false; }
return __awaiter(this, void 0, void 0, function () {
var path, file;
return __generator(this, function (_a) {
path = parameters.filepath;
file = this.app.vault.getAbstractFileByPath(path);
if (parameters.mode === "overwrite") {
this.writeAndOpenFile(path, parameters.data, parameters);
this.success(parameters);
}
else if (parameters.mode === "prepend") {
if (file instanceof obsidian.TFile) {
this.prepend(file, parameters);
}
else {
this.prepend(path, parameters);
}
this.success(parameters);
}
else if (parameters.mode === "append") {
if (file instanceof obsidian.TFile) {
this.append(file, parameters);
}
else {
this.append(path, parameters);
}
this.success(parameters);
}
else if (!createdDailyNote && file instanceof obsidian.TFile) {
new obsidian.Notice("File already exists");
this.failure(parameters);
}
else {
this.writeAndOpenFile(path, parameters.data, parameters);
this.success(parameters);
}
return [2 /*return*/];
});
});
};
AdvancedURI.prototype.handleOpen = function (parameters) {
return __awaiter(this, void 0, void 0, function () {
var fileIsAlreadyOpened, leaf, viewState, view, cache, heading, view, cache, block, view, line;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
fileIsAlreadyOpened = false;
this.app.workspace.iterateAllLeaves(function (leaf) {
var _a;
if (((_a = leaf.view.file) === null || _a === void 0 ? void 0 : _a.path) === parameters.filepath) {
fileIsAlreadyOpened = true;
_this.app.workspace.setActiveLeaf(leaf, true, true);
}
});
if (!fileIsAlreadyOpened) return [3 /*break*/, 2];
leaf = this.app.workspace.activeLeaf;
if (!(parameters.viewmode != undefined)) return [3 /*break*/, 2];
viewState = leaf.getViewState();
viewState.state.mode = parameters.viewmode;
return [4 /*yield*/, leaf.setViewState(viewState)];
case 1:
_a.sent();
_a.label = 2;
case 2:
if (!(parameters.heading != undefined)) return [3 /*break*/, 4];
return [4 /*yield*/, this.app.workspace.openLinkText(parameters.filepath + "#" + parameters.heading, "", this.settings.openFileWithoutWriteInNewPane, this.getViewStateFromMode(parameters))];
case 3:
_a.sent();
view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
if (!view)
return [2 /*return*/];
cache = this.app.metadataCache.getFileCache(view.file);
heading = cache.headings.find(function (e) { return e.heading === parameters.heading; });
view.editor.focus();
view.editor.setCursor({ line: heading.position.start.line + 1, ch: 0 });
return [3 /*break*/, 9];
case 4:
if (!(parameters.block != undefined)) return [3 /*break*/, 6];
return [4 /*yield*/, this.app.workspace.openLinkText(parameters.filepath + "#^" + parameters.block, "", this.settings.openFileWithoutWriteInNewPane, this.getViewStateFromMode(parameters))];
case 5:
_a.sent();
view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
if (!view)
return [2 /*return*/];
cache = this.app.metadataCache.getFileCache(view.file);
block = cache.blocks[parameters.block];
view.editor.focus();
view.editor.setCursor({ line: block.position.start.line, ch: 0 });
return [3 /*break*/, 9];
case 6:
if (!!fileIsAlreadyOpened) return [3 /*break*/, 8];
return [4 /*yield*/, this.app.workspace.openLinkText(parameters.filepath, "", this.settings.openFileWithoutWriteInNewPane, this.getViewStateFromMode(parameters))];
case 7:
_a.sent();
_a.label = 8;
case 8:
if (parameters.line != undefined) {
view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
if (!view)
return [2 /*return*/];
line = Math.min(parameters.line - 1, view.editor.lineCount() - 1);
view.editor.focus();
view.editor.setCursor({ line: line, ch: view.editor.getLine(line).length });
}
_a.label = 9;
case 9:
if (!(parameters.mode != undefined)) return [3 /*break*/, 11];
return [4 /*yield*/, this.setCursor(parameters.mode)];
case 10:
_a.sent();
_a.label = 11;
case 11:
this.success(parameters);
return [2 /*return*/];
}
});
});
};
AdvancedURI.prototype.append = function (file, parameters) {
var _a;
return __awaiter(this, void 0, void 0, function () {
var path, dataToWrite, line, data, lines, fileData;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!parameters.heading) return [3 /*break*/, 3];
if (!(file instanceof obsidian.TFile)) return [3 /*break*/, 2];
path = file.path;
line = (_a = this.getEndAndBeginningOfHeading(file, parameters.heading)) === null || _a === void 0 ? void 0 : _a.lastLine;
if (line === undefined)
return [2 /*return*/];
return [4 /*yield*/, this.app.vault.read(file)];
case 1:
data = _b.sent();
lines = data.split("\n");
lines.splice.apply(lines, __spreadArray([line, 0], parameters.data.split("\n")));
dataToWrite = lines.join("\n");
_b.label = 2;
case 2: return [3 /*break*/, 7];
case 3:
fileData = void 0;
if (!(file instanceof obsidian.TFile)) return [3 /*break*/, 5];
return [4 /*yield*/, this.app.vault.read(file)];
case 4:
fileData = _b.sent();
path = file.path;
return [3 /*break*/, 6];
case 5:
path = file;
fileData = "";
_b.label = 6;
case 6:
dataToWrite = fileData + "\n" + parameters.data;
_b.label = 7;
case 7:
this.writeAndOpenFile(path, dataToWrite, parameters);
return [2 /*return*/];
}
});
});
};
AdvancedURI.prototype.prepend = function (file, parameters) {
var _a;
return __awaiter(this, void 0, void 0, function () {
var path, dataToWrite, line, data, lines, fileData;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!parameters.heading) return [3 /*break*/, 3];
if (!(file instanceof obsidian.TFile)) return [3 /*break*/, 2];
path = file.path;
line = (_a = this.getEndAndBeginningOfHeading(file, parameters.heading)) === null || _a === void 0 ? void 0 : _a.firstLine;
if (line === undefined)
return [2 /*return*/];
return [4 /*yield*/, this.app.vault.read(file)];
case 1:
data = _b.sent();
lines = data.split("\n");
lines.splice.apply(lines, __spreadArray([line, 0], parameters.data.split("\n")));
dataToWrite = lines.join("\n");
_b.label = 2;
case 2: return [3 /*break*/, 7];
case 3:
fileData = void 0;
if (!(file instanceof obsidian.TFile)) return [3 /*break*/, 5];
return [4 /*yield*/, this.app.vault.read(file)];
case 4:
fileData = _b.sent();
path = file.path;
return [3 /*break*/, 6];
case 5:
path = file;
fileData = "";
_b.label = 6;
case 6:
dataToWrite = parameters.data + "\n" + fileData;
_b.label = 7;
case 7:
this.writeAndOpenFile(path, dataToWrite, parameters);
return [2 /*return*/];
}
});
});
};
AdvancedURI.prototype.writeAndOpenFile = function (outputFileName, text, parameters) {
return __awaiter(this, void 0, void 0, function () {
var fileIsAlreadyOpened_1;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.app.vault.adapter.write(outputFileName, text)];
case 1:
_a.sent();
if (this.settings.openFileOnWrite) {
fileIsAlreadyOpened_1 = false;
this.app.workspace.iterateAllLeaves(function (leaf) {
var _a;
if (((_a = leaf.view.file) === null || _a === void 0 ? void 0 : _a.path) === outputFileName) {
fileIsAlreadyOpened_1 = true;
_this.app.workspace.setActiveLeaf(leaf, true, true);
}
});
if (!fileIsAlreadyOpened_1)
this.app.workspace.openLinkText(outputFileName, "", this.settings.openFileOnWriteInNewPane, this.getViewStateFromMode(parameters));
}
return [2 /*return*/];
}
});
});
};
AdvancedURI.prototype.getEndAndBeginningOfHeading = function (file, heading) {
var _a, _b;
var cache = this.app.metadataCache.getFileCache(file);
var sections = cache.sections;
var foundHeading = (_a = cache.headings) === null || _a === void 0 ? void 0 : _a.find(function (e) { return e.heading === heading; });
if (foundHeading) {
var foundSectionIndex = sections.findIndex(function (section) { return section.type === "heading" && section.position.start.line === foundHeading.position.start.line; });
var restSections = sections.slice(foundSectionIndex + 1);
var nextHeadingIndex = restSections === null || restSections === void 0 ? void 0 : restSections.findIndex(function (e) { return e.type === "heading"; });
var lastSection = (_b = restSections[(nextHeadingIndex !== -1 ? nextHeadingIndex : restSections.length) - 1]) !== null && _b !== void 0 ? _b : sections[foundSectionIndex];
var lastLine = lastSection.position.end.line + 1;
return { "lastLine": lastLine, "firstLine": sections[foundSectionIndex].position.end.line + 1 };
}
else {
new obsidian.Notice("Can't find heading");
}
};
AdvancedURI.prototype.setCursor = function (mode) {
return __awaiter(this, void 0, void 0, function () {
var view, editor, viewState, lastLine, lastLineLength;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
if (!view) return [3 /*break*/, 4];
editor = view.editor;
viewState = view.leaf.getViewState();
viewState.state.mode = "source";
if (!(mode === "append")) return [3 /*break*/, 2];
lastLine = editor.lastLine();
lastLineLength = editor.getLine(lastLine).length;
return [4 /*yield*/, view.leaf.setViewState(viewState, { focus: true })];
case 1:
_a.sent();
editor.setCursor({ ch: lastLineLength, line: lastLine });
return [3 /*break*/, 4];
case 2:
if (!(mode === "prepend")) return [3 /*break*/, 4];
return [4 /*yield*/, view.leaf.setViewState(viewState, { focus: true })];
case 3:
_a.sent();
editor.setCursor({ ch: 0, line: 0 });
_a.label = 4;
case 4: return [2 /*return*/];
}
});
});
};
AdvancedURI.prototype.handleCopyFileURI = function () {
var _this = this;
var view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
if (!view)
return;
var pos = view.editor.getCursor();
var cache = this.app.metadataCache.getFileCache(view.file);
if (cache.headings) {
for (var _i = 0, _a = cache.headings; _i < _a.length; _i++) {
var heading = _a[_i];
if (heading.position.start.line <= pos.line && heading.position.end.line >= pos.line) {
this.copyURI({
filepath: view.file.path,
heading: heading.heading
});
return;
}
}
}
if (cache.blocks) {
for (var _b = 0, _c = Object.keys(cache.blocks); _b < _c.length; _b++) {
var blockID = _c[_b];
var block = cache.blocks[blockID];
if (block.position.start.line <= pos.line && block.position.end.line >= pos.line) {
this.copyURI({
filepath: view.file.path,
block: blockID
});
return;
}
}
}
var fileModal = new FileModal(this, "Choose a file", false);
fileModal.open();
fileModal.onChooseItem = function (item, _) {
new EnterDataModal(_this, item.source).open();
};
};
AdvancedURI.prototype.handleOpenSettings = function (parameters) {
if (this.app.setting.containerEl.parentElement === null) {
this.app.setting.open();
}
if (parameters.settingid == "plugin-browser") {
this.app.setting.openTabById("community-plugins");
this.app.setting.activeTab.containerEl.find(".mod-cta").click();
}
else if (parameters.settingid == "theme-browser") {
this.app.setting.openTabById("appearance");
this.app.setting.activeTab.containerEl.find(".mod-cta").click();
}
else {
this.app.setting.openTabById(parameters.settingid);
}
this.success(parameters);
};
AdvancedURI.prototype.handleUpdatePlugins = function (parameters) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
parameters.settingid = "community-plugins";
this.handleOpenSettings(parameters);
this.app.setting.activeTab.containerEl.findAll(".mod-cta").last().click();
new obsidian.Notice("Waiting 10 seconds");
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 10 * 1000); })];
case 1:
_a.sent();
if (Object.keys(this.app.plugins.updates).length !== 0) {
this.app.setting.activeTab.containerEl.findAll(".mod-cta").last().click();
}
this.success(parameters);
return [2 /*return*/];
}
});
});
};
AdvancedURI.prototype.copyURI = function (parameters) {
return __awaiter(this, void 0, void 0, function () {
var uri, file, _a, parameter;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
uri = "obsidian://advanced-uri?vault=" + this.app.vault.getName();
file = this.app.vault.getAbstractFileByPath(parameters.filepath);
if (!(this.settings.useUID && file instanceof obsidian.TFile)) return [3 /*break*/, 2];
parameters.filepath = undefined;
_a = parameters;
return [4 /*yield*/, this.getURIFromFile(file)];
case 1:
_a.uid = _b.sent();
_b.label = 2;
case 2:
for (parameter in parameters) {
if (parameters[parameter] != undefined) {
uri = uri + ("&" + parameter + "=" + encodeURIComponent(parameters[parameter]));
}
}
return [4 /*yield*/, this.copyText(encodeURI(uri))];
case 3:
_b.sent();
new obsidian.Notice("Advanced URI copied to your clipboard");
return [2 /*return*/];
}
});
});
};
AdvancedURI.prototype.copyText = function (text) {
return navigator.clipboard.writeText(text);
};
AdvancedURI.prototype.getURIFromFile = function (file) {
return __awaiter(this, void 0, void 0, function () {
var fileContent, frontmatter, uid, isYamlEmpty, splitContent, newFileContent;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.app.vault.read(file)];
case 1:
fileContent = _a.sent();
frontmatter = this.app.metadataCache.getFileCache(file).frontmatter;
uid = obsidian.parseFrontMatterEntry(frontmatter, this.settings.idField);
if (uid)
return [2 /*return*/, uid];
isYamlEmpty = ((!frontmatter || frontmatter.length === 0) && !fileContent.match(/^-{3}\s*\n*\r*-{3}/));
uid = v4();
splitContent = fileContent.split("\n");
if (isYamlEmpty) {
splitContent.unshift("---");
splitContent.unshift(this.settings.idField + ": " + uid);
splitContent.unshift("---");
}
else {
splitContent.splice(1, 0, this.settings.idField + ": " + uid);
}
newFileContent = splitContent.join("\n");
return [4 /*yield*/, this.app.vault.modify(file, newFileContent)];
case 2:
_a.sent();
return [2 /*return*/, uid];
}
});
});
};
AdvancedURI.prototype.getViewStateFromMode = function (parameters) {
return parameters.viewmode ? { state: { mode: parameters.viewmode } } : undefined;
};
AdvancedURI.prototype.loadSettings = function () {
return __awaiter(this, void 0, void 0, function () {
var _a, _b, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
_a = this;
_c = (_b = Object).assign;
_d = [DEFAULT_SETTINGS];
return [4 /*yield*/, this.loadData()];
case 1:
_a.settings = _c.apply(_b, _d.concat([_e.sent()]));
return [2 /*return*/];
}
});
});
};
AdvancedURI.prototype.saveSettings = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.saveData(this.settings)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
return AdvancedURI;
}(obsidian.Plugin));
var SettingsTab = /** @class */ (function (_super) {
__extends(SettingsTab, _super);
function SettingsTab(app, plugin) {
var _this = _super.call(this, app, plugin) || this;
_this.plugin = plugin;
return _this;
}
SettingsTab.prototype.display = function () {
var _this = this;
var containerEl = this.containerEl;
containerEl.empty();
containerEl.createEl("h2", { text: this.plugin.manifest.name });
new obsidian.Setting(containerEl)
.setName("Open file on write")
.addToggle(function (cb) { return cb.onChange(function (value) {
_this.plugin.settings.openFileOnWrite = value;
_this.plugin.saveSettings();
}).setValue(_this.plugin.settings.openFileOnWrite); });
new obsidian.Setting(containerEl)
.setName("Open file on write in a new pane")
.setDisabled(this.plugin.settings.openFileOnWrite)
.addToggle(function (cb) { return cb.onChange(function (value) {
_this.plugin.settings.openFileOnWriteInNewPane = value;
_this.plugin.saveSettings();
}).setValue(_this.plugin.settings.openFileOnWriteInNewPane); });
new obsidian.Setting(containerEl)
.setName("Open daily note in a new pane")
.addToggle(function (cb) { return cb.onChange(function (value) {
_this.plugin.settings.openDailyInNewPane = value;
_this.plugin.saveSettings();
}).setValue(_this.plugin.settings.openDailyInNewPane); });
new obsidian.Setting(containerEl)
.setName("Open file without write in new pane")
.addToggle(function (cb) { return cb.onChange(function (value) {
_this.plugin.settings.openFileWithoutWriteInNewPane = value;
_this.plugin.saveSettings();
}).setValue(_this.plugin.settings.openFileWithoutWriteInNewPane); });
new obsidian.Setting(containerEl)
.setName("Use UID instead of file paths")
.addToggle(function (cb) { return cb.onChange(function (value) {
_this.plugin.settings.useUID = value;
_this.plugin.saveSettings();
}).setValue(_this.plugin.settings.useUID); });
new obsidian.Setting(containerEl)
.setName("UID field in frontmatter")
.addText(function (cb) { return cb.onChange(function (value) {
_this.plugin.settings.idField = value;
_this.plugin.saveSettings();
}).setValue(_this.plugin.settings.idField); });
};
return SettingsTab;
}(obsidian.PluginSettingTab));
var EnterDataModal = /** @class */ (function (_super) {
__extends(EnterDataModal, _super);
function EnterDataModal(plugin, file) {
var _this = _super.call(this, plugin.app) || this;
//null if for normal write mode, its not associated with a special mode like "append" or "prepend"
_this.modes = [null, "overwrite", "append", "prepend"];
_this.plugin = plugin;
_this.setPlaceholder("Type your data to be written to the file or leave it empty to just open it");
_this.file = file;
return _this;
}
EnterDataModal.prototype.getSuggestions = function (query) {
var _this = this;
if (query == "")
query = null;
var suggestions = [];
var _loop_1 = function (mode) {
if (!(mode === "overwrite" && !query)) {
var display = void 0;
if (query) {
if (mode) {
display = "Write \"" + query + "\" in " + mode + " mode";
}
else {
display = "Write \"" + query + "\"";
}
}
else {
if (mode) {
display = "Open in " + mode + " mode";
}
else {
display = "Open";
}
}
suggestions.push({
data: query,
display: display,
mode: mode,
func: function () {
if (_this.file) {
_this.plugin.copyURI({
filepath: _this.file,
data: query,
mode: mode
});
}
else {
_this.plugin.copyURI({
daily: "true",
data: query,
mode: mode
});
}
}
});
}
};
for (var _i = 0, _a = this.modes; _i < _a.length; _i++) {
var mode = _a[_i];
_loop_1(mode);
}
return suggestions;
};
EnterDataModal.prototype.renderSuggestion = function (value, el) {
el.innerText = value.display;
};
EnterDataModal.prototype.onChooseSuggestion = function (item, _) {
item.func();
};
return EnterDataModal;
}(obsidian.SuggestModal));
var FileModal = /** @class */ (function (_super) {
__extends(FileModal, _super);
function FileModal(plugin, placeHolder, allowNoFile) {
if (allowNoFile === void 0) { allowNoFile = true; }
var _this = _super.call(this, plugin.app) || this;
_this.placeHolder = placeHolder;
_this.allowNoFile = allowNoFile;
_this.plugin = plugin;
_this.setPlaceholder(_this.placeHolder);
return _this;
}
FileModal.prototype.getItems = function () {
var specialItems = [];
if (this.allowNoFile) {
specialItems.push({ display: "<Don't specify a file>", source: undefined });
}
var file = this.app.workspace.getActiveFile();
if (file) {
specialItems.push({ display: "<Current file>", source: file.path });
}
return __spreadArray(__spreadArray([], specialItems), this.app.vault.getFiles().map(function (e) { return { display: e.path, source: e.path }; }));
};
FileModal.prototype.getItemText = function (item) {
return item.display;
};
FileModal.prototype.onChooseItem = function (item, evt) {
};
return FileModal;
}(obsidian.FuzzySuggestModal));
var CommandModal = /** @class */ (function (_super) {
__extends(CommandModal, _super);
function CommandModal(plugin, file) {
var _this = _super.call(this, plugin.app) || this;
_this.plugin = plugin;
_this.file = file;
return _this;
}
CommandModal.prototype.getItems = function () {
var rawCommands = this.app.commands.commands;
var commands = Object.keys(rawCommands).map(function (e) {
return { id: rawCommands[e].id, name: rawCommands[e].name };
});
return commands;
};
CommandModal.prototype.getItemText = function (item) {
return item.name;
};
CommandModal.prototype.onChooseItem = function (item, _) {
this.plugin.copyURI({
filepath: this.file,
commandid: item.id
});
};
return CommandModal;
}(obsidian.FuzzySuggestModal));
var SearchModal = /** @class */ (function (_super) {
__extends(SearchModal, _super);
function SearchModal(plugin) {
var _this = _super.call(this, plugin.app) || this;
_this.plugin = plugin;
_this.setPlaceholder("Searched text. RegEx is supported");
return _this;
}
SearchModal.prototype.getSuggestions = function (query) {
if (query === "") {
query = "...";
}
var regex;
try {
regex = new RegExp(query);
}
catch (error) { }
return [
{
source: query,
isRegEx: false,
display: query
},
{
source: query,
display: regex ? "As RegEx: " + query : "Can't parse RegEx",
isRegEx: true
}
];
};
SearchModal.prototype.renderSuggestion = function (value, el) {
el.innerText = value.display;
};
SearchModal.prototype.onChooseSuggestion = function (item, _) {
};
return SearchModal;
}(obsidian.SuggestModal));
var ReplaceModal = /** @class */ (function (_super) {
__extends(ReplaceModal, _super);
function ReplaceModal(plugin, search, filepath) {
var _this = _super.call(this, plugin.app) || this;
_this.search = search;
_this.filepath = filepath;
_this.emptyText = "Empty text (replace with nothing)";
_this.plugin = plugin;
_this.setPlaceholder("Replacement text");
return _this;
}
ReplaceModal.prototype.getSuggestions = function (query) {
if (query === "") {
query = this.emptyText;
}
return [query];
};
ReplaceModal.prototype.renderSuggestion = function (value, el) {
el.innerText = value;
};
ReplaceModal.prototype.onChooseSuggestion = function (item, _) {
if (this.search.isRegEx) {
this.plugin.copyURI({
filepath: this.filepath,
searchregex: this.search.source,
replace: item == this.emptyText ? "" : item
});
}
else {
this.plugin.copyURI({
filepath: this.filepath,
search: this.search.source,
replace: item == this.emptyText ? "" : item
});
}
};
return ReplaceModal;
}(obsidian.SuggestModal));
module.exports = AdvancedURI;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsIm5vZGVfbW9kdWxlcy9vYnNpZGlhbi1kYWlseS1ub3Rlcy1pbnRlcmZhY2UvZGlzdC9tYWluLmpzIiwibm9kZV9tb2R1bGVzL3V1aWQvZGlzdC9lc20tYnJvd3Nlci9ybmcuanMiLCJub2RlX21vZHVsZXMvdXVpZC9kaXN0L2VzbS1icm93c2VyL3JlZ2V4LmpzIiwibm9kZV9tb2R1bGVzL3V1aWQvZGlzdC9lc20tYnJvd3Nlci92YWxpZGF0ZS5qcyIsIm5vZGVfbW9kdWxlcy91dWlkL2Rpc3QvZXNtLWJyb3dzZXIvc3RyaW5naWZ5LmpzIiwibm9kZV9tb2R1bGVzL3V1aWQvZGlzdC9lc20tYnJvd3Nlci92NC5qcyIsInNyYy9kYWlseV9ub3RlX3V0aWxzLnRzIiwic3JjL21haW4udHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyohICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxyXG5cclxuUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kL29yIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZSBmb3IgYW55XHJcbnB1cnBvc2Ugd2l0aCBvciB3aXRob3V0IGZlZSBpcyBoZXJlYnkgZ3JhbnRlZC5cclxuXHJcblRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEhcclxuUkVHQVJEIFRPIFRISVMgU09GVFdBUkUgSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZXHJcbkFORCBGSVRORVNTLiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIERJUkVDVCxcclxuSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NXHJcbkxPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SXHJcbk9USEVSIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1JcclxuUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXHJcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH1cclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHtcclxuICAgIHZhciB0ID0ge307XHJcbiAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcclxuICAgICAgICB0W3BdID0gc1twXTtcclxuICAgIGlmIChzICE9IG51bGwgJiYgdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPT09IFwiZnVuY3Rpb25cIilcclxuICAgICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSlcclxuICAgICAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgICAgIH1cclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQ