diff --git a/.obsidian/plugins/waypoint/main.js b/.obsidian/plugins/waypoint/main.js new file mode 100644 index 0000000..390ba4a --- /dev/null +++ b/.obsidian/plugins/waypoint/main.js @@ -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); + } +}; diff --git a/.obsidian/plugins/waypoint/manifest.json b/.obsidian/plugins/waypoint/manifest.json new file mode 100644 index 0000000..bb92187 --- /dev/null +++ b/.obsidian/plugins/waypoint/manifest.json @@ -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 +} \ No newline at end of file