Add waypoint plugin

Signed-off-by: baalajimaestro <me@baalajimaestro.me>
This commit is contained in:
baalajimaestro 2023-03-25 22:27:18 +05:30
parent 636c1ad7fd
commit fb3dbada97
Signed by: baalajimaestro
GPG key ID: F93C394FE9BBAFD5
2 changed files with 424 additions and 0 deletions

414
.obsidian/plugins/waypoint/main.js vendored Normal file
View file

@ -0,0 +1,414 @@
/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
var __export = (target, all) => {
__markAsModule(target);
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __reExport = (target, module2, desc) => {
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
for (let key of __getOwnPropNames(module2))
if (!__hasOwnProp.call(target, key) && key !== "default")
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
}
return target;
};
var __toModule = (module2) => {
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
};
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// main.ts
__export(exports, {
default: () => Waypoint
});
var import_obsidian = __toModule(require("obsidian"));
var FolderNoteType;
(function(FolderNoteType2) {
FolderNoteType2["InsideFolder"] = "INSIDE_FOLDER";
FolderNoteType2["OutsideFolder"] = "OUTSIDE_FOLDER";
})(FolderNoteType || (FolderNoteType = {}));
var DEFAULT_SETTINGS = {
waypointFlag: "%% Waypoint %%",
stopScanAtFolderNotes: false,
showFolderNotes: false,
showNonMarkdownFiles: false,
debugLogging: false,
useWikiLinks: true,
showEnclosingNote: false,
folderNoteType: FolderNoteType.InsideFolder
};
var _Waypoint = class extends import_obsidian.Plugin {
constructor() {
super(...arguments);
this.foldersWithChanges = new Set();
this.detectWaypointFlag = (file) => __async(this, null, function* () {
this.log("Modification on " + file.name);
this.log("Scanning for Waypoint flags...");
const text = yield this.app.vault.cachedRead(file);
const lines = text.split("\n");
for (let i = 0; i < lines.length; i++) {
if (lines[i].trim() === this.settings.waypointFlag) {
if (this.isFolderNote(file)) {
this.log("Found waypoint flag in folder note!");
yield this.updateWaypoint(file);
yield this.updateParentWaypoint(file.parent, this.settings.folderNoteType === FolderNoteType.OutsideFolder);
return;
} else if (file.parent.isRoot()) {
this.log("Found waypoint flag in root folder.");
this.printWaypointError(file, `%% Error: Cannot create a waypoint in the root folder of your vault. For more information, check the instructions [here](https://github.com/IdreesInc/Waypoint) %%`);
return;
} else {
this.log("Found waypoint flag in invalid note.");
this.printWaypointError(file, `%% Error: Cannot create a waypoint in a note that's not the folder note. For more information, check the instructions [here](https://github.com/IdreesInc/Waypoint) %%`);
return;
}
}
}
this.log("No waypoint flags found.");
});
this.updateChangedFolders = () => __async(this, null, function* () {
this.log("Updating changed folders...");
this.foldersWithChanges.forEach((folder) => {
this.log("Updating " + folder.path);
this.updateParentWaypoint(folder, true);
});
this.foldersWithChanges.clear();
});
this.scheduleUpdate = (0, import_obsidian.debounce)(this.updateChangedFolders.bind(this), 500, true);
this.updateParentWaypoint = (node, includeCurrentNode) => __async(this, null, function* () {
const parentWaypoint = yield this.locateParentWaypoint(node, includeCurrentNode);
if (parentWaypoint !== null) {
this.updateWaypoint(parentWaypoint);
}
});
}
onload() {
return __async(this, null, function* () {
yield this.loadSettings();
this.app.workspace.onLayoutReady(() => __async(this, null, function* () {
this.registerEvent(this.app.vault.on("create", (file) => {
this.log("create " + file.name);
this.foldersWithChanges.add(file.parent);
this.scheduleUpdate();
}));
this.registerEvent(this.app.vault.on("delete", (file) => {
this.log("delete " + file.name);
const parentFolder = this.getParentFolder(file.path);
if (parentFolder !== null) {
this.foldersWithChanges.add(parentFolder);
this.scheduleUpdate();
}
}));
this.registerEvent(this.app.vault.on("rename", (file, oldPath) => {
this.log("rename " + file.name);
this.foldersWithChanges.add(file.parent);
const parentFolder = this.getParentFolder(oldPath);
if (parentFolder !== null) {
this.foldersWithChanges.add(parentFolder);
}
this.scheduleUpdate();
}));
this.registerEvent(this.app.vault.on("modify", this.detectWaypointFlag));
}));
this.addSettingTab(new WaypointSettingsTab(this.app, this));
});
}
onunload() {
}
isFolderNote(file) {
if (this.settings.folderNoteType === FolderNoteType.InsideFolder) {
return file.basename == file.parent.name;
} else if (this.settings.folderNoteType === FolderNoteType.OutsideFolder) {
if (file.parent) {
return this.app.vault.getAbstractFileByPath(this.getCleanParentPath(file) + file.basename) instanceof import_obsidian.TFolder;
}
return false;
}
}
getCleanParentPath(node) {
if (node.parent instanceof import_obsidian.TFolder && node.parent.isRoot()) {
return "";
} else {
return node.parent.path + "/";
}
}
printWaypointError(file, error) {
return __async(this, null, function* () {
this.log("Creating waypoint error in " + file.path);
const text = yield this.app.vault.read(file);
const lines = text.split("\n");
let waypointIndex = -1;
for (let i = 0; i < lines.length; i++) {
const trimmed = lines[i].trim();
if (trimmed === this.settings.waypointFlag) {
waypointIndex = i;
}
}
if (waypointIndex === -1) {
console.error("Error: No waypoint flag found while trying to print error.");
return;
}
lines.splice(waypointIndex, 1, error);
yield this.app.vault.modify(file, lines.join("\n"));
});
}
updateWaypoint(file) {
return __async(this, null, function* () {
this.log("Updating waypoint in " + file.path);
let fileTree;
if (this.settings.folderNoteType === FolderNoteType.InsideFolder) {
fileTree = yield this.getFileTreeRepresentation(file.parent, file.parent, 0, true);
} else if (this.settings.folderNoteType === FolderNoteType.OutsideFolder) {
const folder = this.app.vault.getAbstractFileByPath(this.getCleanParentPath(file) + file.basename);
if (folder instanceof import_obsidian.TFolder) {
fileTree = yield this.getFileTreeRepresentation(file.parent, folder, 0, true);
}
}
const waypoint = `${_Waypoint.BEGIN_WAYPOINT}
${fileTree}
${_Waypoint.END_WAYPOINT}`;
const text = yield this.app.vault.read(file);
const lines = text.split("\n");
let waypointStart = -1;
let waypointEnd = -1;
for (let i = 0; i < lines.length; i++) {
const trimmed = lines[i].trim();
if (waypointStart === -1 && (trimmed === this.settings.waypointFlag || trimmed === _Waypoint.BEGIN_WAYPOINT)) {
waypointStart = i;
} else if (waypointStart !== -1 && trimmed === _Waypoint.END_WAYPOINT) {
waypointEnd = i;
break;
}
}
if (waypointStart === -1) {
console.error("Error: No waypoint found while trying to update " + file.path);
return;
}
this.log("Waypoint found at " + waypointStart + " to " + waypointEnd);
lines.splice(waypointStart, waypointEnd !== -1 ? waypointEnd - waypointStart + 1 : 1, waypoint);
yield this.app.vault.modify(file, lines.join("\n"));
});
}
getFileTreeRepresentation(rootNode, node, indentLevel, topLevel = false) {
return __async(this, null, function* () {
const bullet = " ".repeat(indentLevel) + "-";
if (node instanceof import_obsidian.TFile) {
console.log(node);
if (node.extension == "md") {
if (this.settings.useWikiLinks) {
return `${bullet} [[${node.basename}]]`;
} else {
return `${bullet} [${node.basename}](${this.getEncodedUri(rootNode, node)})`;
}
} else if (this.settings.showNonMarkdownFiles) {
if (this.settings.useWikiLinks) {
return `${bullet} [[${node.name}]]`;
} else {
return `${bullet} [${node.name}](${this.getEncodedUri(rootNode, node)})`;
}
}
return null;
} else if (node instanceof import_obsidian.TFolder) {
let text = "";
if (!topLevel || this.settings.showEnclosingNote) {
text = `${bullet} **${node.name}**`;
let folderNote;
if (this.settings.folderNoteType === FolderNoteType.InsideFolder) {
folderNote = this.app.vault.getAbstractFileByPath(node.path + "/" + node.name + ".md");
} else if (this.settings.folderNoteType === FolderNoteType.OutsideFolder) {
if (node.parent) {
folderNote = this.app.vault.getAbstractFileByPath(node.parent.path + "/" + node.name + ".md");
}
}
if (folderNote instanceof import_obsidian.TFile) {
if (this.settings.useWikiLinks) {
text = `${bullet} **[[${folderNote.basename}]]**`;
} else {
text = `${bullet} **[${folderNote.basename}](${this.getEncodedUri(rootNode, folderNote)})**`;
}
if (!topLevel) {
if (this.settings.stopScanAtFolderNotes) {
return text;
} else {
const content = yield this.app.vault.cachedRead(folderNote);
if (content.includes(_Waypoint.BEGIN_WAYPOINT) || content.includes(this.settings.waypointFlag)) {
return text;
}
}
}
}
}
if (node.children && node.children.length > 0) {
let children = node.children;
children = children.sort((a, b) => {
return a.name.localeCompare(b.name, void 0, { numeric: true, sensitivity: "base" });
});
if (!this.settings.showFolderNotes) {
if (this.settings.folderNoteType === FolderNoteType.InsideFolder) {
children = children.filter((child) => this.settings.showFolderNotes || child.name !== node.name + ".md");
} else if (this.settings.folderNoteType === FolderNoteType.OutsideFolder) {
const folderNames = new Set();
for (const element of children) {
if (element instanceof import_obsidian.TFolder) {
folderNames.add(element.name + ".md");
}
}
children = children.filter((child) => child instanceof import_obsidian.TFolder || !folderNames.has(child.name));
}
}
if (children.length > 0) {
const nextIndentLevel = topLevel && !this.settings.showEnclosingNote ? indentLevel : indentLevel + 1;
text += (text === "" ? "" : "\n") + (yield Promise.all(children.map((child) => this.getFileTreeRepresentation(rootNode, child, nextIndentLevel)))).filter(Boolean).join("\n");
}
return text;
} else {
return `${bullet} **${node.name}**`;
}
}
return null;
});
}
getEncodedUri(rootNode, node) {
if (rootNode.isRoot()) {
return `./${encodeURI(node.path)}`;
}
return `./${encodeURI(node.path.substring(rootNode.path.length + 1))}`;
}
locateParentWaypoint(node, includeCurrentNode) {
return __async(this, null, function* () {
this.log("Locating parent waypoint of " + node.name);
let folder = includeCurrentNode ? node : node.parent;
while (folder) {
let folderNote;
if (this.settings.folderNoteType === FolderNoteType.InsideFolder) {
folderNote = this.app.vault.getAbstractFileByPath(folder.path + "/" + folder.name + ".md");
} else if (this.settings.folderNoteType === FolderNoteType.OutsideFolder) {
if (folder.parent) {
folderNote = this.app.vault.getAbstractFileByPath(this.getCleanParentPath(folder) + folder.name + ".md");
}
}
if (folderNote instanceof import_obsidian.TFile) {
this.log("Found folder note: " + folderNote.path);
const text = yield this.app.vault.cachedRead(folderNote);
if (text.includes(_Waypoint.BEGIN_WAYPOINT) || text.includes(this.settings.waypointFlag)) {
this.log("Found parent waypoint!");
return folderNote;
}
}
folder = folder.parent;
}
this.log("No parent waypoint found.");
return null;
});
}
getParentFolder(path) {
const abstractFile = this.app.vault.getAbstractFileByPath(path.split("/").slice(0, -1).join("/"));
if (abstractFile instanceof import_obsidian.TFolder) {
return abstractFile;
} else {
return null;
}
}
log(message) {
if (this.settings.debugLogging) {
console.log(message);
}
}
loadSettings() {
return __async(this, null, function* () {
this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
});
}
saveSettings() {
return __async(this, null, function* () {
yield this.saveData(this.settings);
});
}
};
var Waypoint = _Waypoint;
Waypoint.BEGIN_WAYPOINT = "%% Begin Waypoint %%";
Waypoint.END_WAYPOINT = "%% End Waypoint %%";
var WaypointSettingsTab = class extends import_obsidian.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin);
this.plugin = plugin;
}
display() {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl("h2", { text: "Waypoint Settings" });
new import_obsidian.Setting(this.containerEl).setName("Folder Note Style").setDesc("Select the style of folder note used.").addDropdown((dropdown) => dropdown.addOption(FolderNoteType.InsideFolder, "Folder Name Inside").addOption(FolderNoteType.OutsideFolder, "Folder Name Outside").setValue(this.plugin.settings.folderNoteType).onChange((value) => __async(this, null, function* () {
this.plugin.settings.folderNoteType = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Show Folder Notes").setDesc("If enabled, folder notes will be listed alongside other notes in the generated waypoints.").addToggle((toggle) => toggle.setValue(this.plugin.settings.showFolderNotes).onChange((value) => __async(this, null, function* () {
this.plugin.settings.showFolderNotes = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Show Non-Markdown Files").setDesc("If enabled, non-Markdown files will be listed alongside other notes in the generated waypoints.").addToggle((toggle) => toggle.setValue(this.plugin.settings.showNonMarkdownFiles).onChange((value) => __async(this, null, function* () {
this.plugin.settings.showNonMarkdownFiles = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Show Enclosing Note").setDesc("If enabled, the name of the folder note containing the waypoint will be listed at the top of the generated waypoints.").addToggle((toggle) => toggle.setValue(this.plugin.settings.showEnclosingNote).onChange((value) => __async(this, null, function* () {
this.plugin.settings.showEnclosingNote = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Stop Scan at Folder Notes").setDesc("If enabled, the waypoint generator will stop scanning nested folders when it encounters a folder note. Otherwise, it will only stop if the folder note contains a waypoint.").addToggle((toggle) => toggle.setValue(this.plugin.settings.stopScanAtFolderNotes).onChange((value) => __async(this, null, function* () {
this.plugin.settings.stopScanAtFolderNotes = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Use WikiLinks").setDesc("If enabled, links will be generated like [[My Page]] instead of [My Page](../Folder/My%Page.md).").addToggle((toggle) => toggle.setValue(this.plugin.settings.useWikiLinks).onChange((value) => __async(this, null, function* () {
this.plugin.settings.useWikiLinks = value;
yield this.plugin.saveSettings();
})));
new import_obsidian.Setting(containerEl).setName("Waypoint Flag").setDesc("Text flag that triggers waypoint generation in a folder note. Must be surrounded by double-percent signs.").addText((text) => text.setPlaceholder(DEFAULT_SETTINGS.waypointFlag).setValue(this.plugin.settings.waypointFlag).onChange((value) => __async(this, null, function* () {
if (value && value.startsWith("%%") && value.endsWith("%%") && value !== "%%" && value !== "%%%" && value !== "%%%%") {
this.plugin.settings.waypointFlag = value;
} else {
this.plugin.settings.waypointFlag = DEFAULT_SETTINGS.waypointFlag;
console.error("Error: Waypoint flag must be surrounded by double-percent signs.");
}
yield this.plugin.saveSettings();
})));
const postscriptElement = containerEl.createEl("div", {
cls: "setting-item"
});
const descriptionElement = postscriptElement.createDiv({ cls: "setting-item-description" });
descriptionElement.createSpan({ text: "For instructions on how to use this plugin, check out the README on " });
descriptionElement.createEl("a", { attr: { "href": "https://github.com/IdreesInc/Waypoint" }, text: "GitHub" });
descriptionElement.createSpan({ text: " or get in touch with the author " });
descriptionElement.createEl("a", { attr: { "href": "https://twitter.com/IdreesInc" }, text: "@IdreesInc" });
postscriptElement.appendChild(descriptionElement);
}
};

View file

@ -0,0 +1,10 @@
{
"id": "waypoint",
"name": "Waypoint",
"version": "1.4.0",
"minAppVersion": "0.12.0",
"description": "Easily generate dynamic content maps in your folder notes. Enables folders to show up in the graph view and removes the need for messy tags!",
"author": "Idrees Hassan",
"authorUrl": "https://idreesinc.com",
"isDesktopOnly": false
}