diff --git a/main.ts b/main.ts index 27d6c85..2933223 100644 --- a/main.ts +++ b/main.ts @@ -1,10 +1,12 @@ -import { App, debounce, Plugin, PluginSettingTab, Setting, TAbstractFile, TFile, TFolder } from 'obsidian'; +import {App, debounce, Plugin, PluginSettingTab, Setting, TAbstractFile, TFile, TFolder, Vault} from 'obsidian'; interface WaypointSettings { waypointFlag: string stopScanAtFolderNotes: boolean, showFolderNotes: boolean, debugLogging: boolean, + ignoredFolders: string[], + root: string useWikiLinks: boolean } @@ -13,7 +15,9 @@ const DEFAULT_SETTINGS: WaypointSettings = { stopScanAtFolderNotes: false, showFolderNotes: false, debugLogging: false, - useWikiLinks: true + useWikiLinks: true, + ignoredFolders: ["Templates"], + root: null } export default class Waypoint extends Plugin { @@ -29,7 +33,8 @@ export default class Waypoint extends Plugin { // Register events after layout is built to avoid initial wave of 'create' events this.registerEvent(this.app.vault.on("create", (file) => { this.log("create " + file.name); - this.foldersWithChanges.add(file.parent); + const folderParent = this.getParentFolder(file.path); + this.foldersWithChanges.add(folderParent); this.scheduleUpdate(); })); this.registerEvent(this.app.vault.on("delete", (file) => { @@ -42,7 +47,8 @@ export default class Waypoint extends Plugin { })); this.registerEvent(this.app.vault.on("rename", (file, oldPath) => { this.log("rename " + file.name); - this.foldersWithChanges.add(file.parent); + const parentFolderOrigin = this.getParentFolder(file.path); + this.foldersWithChanges.add(parentFolderOrigin); const parentFolder = this.getParentFolder(oldPath); if (parentFolder !== null) { this.foldersWithChanges.add(parentFolder); @@ -54,6 +60,17 @@ export default class Waypoint extends Plugin { // This adds a settings tab so the user can configure various aspects of the plugin this.addSettingTab(new WaypointSettingsTab(this.app, this)); + + // Add in a hotkey to update the waypoint + this.addCommand({ + id: "update-waypoint", + name: "Update waypoint in current file", + hotkeys: [{ + modifiers: ["Ctrl"], + key: "w" + }], + callback: () => { this.updateWaypoint(this.app.workspace.getActiveFile()) } + }) } onunload() { @@ -74,10 +91,16 @@ export default class Waypoint extends Plugin { this.log("Found waypoint flag in folder note!"); await this.updateWaypoint(file); await this.updateParentWaypoint(file.parent, false); - return; + return; + } else if (this.outsideFolderPath(file)) { + await this.updateWaypoint(file); + await this.updateParentWaypoint(this.outsideFolderPath(file), false); + 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) %%`); + this.settings.root = file.name; + await this.saveSettings(); + await this.updateWaypoint(file); return; } else { this.log("Found waypoint flag in invalid note."); @@ -89,6 +112,14 @@ export default class Waypoint extends Plugin { this.log("No waypoint flags found."); } + outsideFolderPath(file:TFile) { + const folderNotePath = this.app.vault.getAbstractFileByPath(file.path.replace('.md', '')); + if (folderNotePath && folderNotePath instanceof TFolder) { + return folderNotePath; + } + return null; + } + async printWaypointError(file: TFile, error: string) { this.log("Creating waypoint error in " + file.path); const text = await this.app.vault.read(file); @@ -114,7 +145,12 @@ export default class Waypoint extends Plugin { */ async updateWaypoint(file: TFile) { this.log("Updating waypoint in " + file.path); - const fileTree = await this.getFileTreeRepresentation(file.parent, 0, true); + const parentFolder = this.getParentFolder(file.path); + let fileTree = await this.getFileTreeRepresentation(parentFolder, 0, true); + if (parentFolder.isRoot()) { + const splitFileTree = fileTree.split("\n"); + fileTree = `- **[[${file.basename}]]**\n${splitFileTree.slice(1).join("\n")}` + } const waypoint = `${Waypoint.BEGIN_WAYPOINT}\n${fileTree}\n\n${Waypoint.END_WAYPOINT}`; const text = await this.app.vault.read(file); const lines: string[] = text.split("\n"); @@ -148,7 +184,8 @@ export default class Waypoint extends Plugin { async getFileTreeRepresentation(node: TAbstractFile, indentLevel: number, topLevel = false): Promise|null { const bullet = " ".repeat(indentLevel) + "-"; if (node instanceof TFile) { - if (node.path.endsWith(".md")) { + // Check for the parent being the root because otherwise the "root note" would be included in the tree + if (node.path.endsWith(".md") && !node.parent.isRoot()) { if (this.settings.useWikiLinks) { return `${bullet} [[${node.basename}]]`; } else { @@ -157,6 +194,7 @@ export default class Waypoint extends Plugin { } return null; } else if (node instanceof TFolder) { + if (this.settings.ignoredFolders.includes(node.path)) { return null } let text = `${bullet} **${node.name}**`; const folderNote = this.app.vault.getAbstractFileByPath(node.path + "/" + node.name + ".md"); if (folderNote instanceof TFile) { @@ -183,8 +221,8 @@ export default class Waypoint extends Plugin { }).filter(child => this.settings.showFolderNotes || child.name !== node.name + ".md"); if (children.length > 0) { text += "\n" + (await Promise.all(children.map(child => this.getFileTreeRepresentation(child, indentLevel + 1)))) - .filter(Boolean) - .join("\n"); + .filter(Boolean) + .join("\n"); } return text; } else { @@ -237,17 +275,29 @@ export default class Waypoint extends Plugin { async locateParentWaypoint(node: TAbstractFile, includeCurrentNode: boolean): Promise { this.log("Locating parent waypoint of " + node.name); let folder = includeCurrentNode ? node : node.parent; - while (folder) { - const folderNote = this.app.vault.getAbstractFileByPath(folder.path + "/" + folder.name + ".md"); - if (folderNote instanceof TFile) { - this.log("Found folder note: " + folderNote.path); - const text = await this.app.vault.cachedRead(folderNote); + if (node.parent.isRoot() && this.settings.root !== null) { + const file = this.app.vault.getAbstractFileByPath(this.settings.root) + if (file instanceof TFile) { + this.log("Found folder note: " + file.path); + const text = await this.app.vault.cachedRead(file); if (text.includes(Waypoint.BEGIN_WAYPOINT) || text.includes(this.settings.waypointFlag)) { this.log("Found parent waypoint!"); - return folderNote; + return file; } } - folder = folder.parent; + } else { + while (folder) { + const folderNote = this.app.vault.getAbstractFileByPath(folder.path + "/" + folder.name + ".md"); + if (folderNote instanceof TFile) { + this.log("Found folder note: " + folderNote.path); + const text = await 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; @@ -260,8 +310,11 @@ export default class Waypoint extends Plugin { */ getParentFolder(path: string): TFolder { const abstractFile = this.app.vault.getAbstractFileByPath(path.split("/").slice(0, -1).join("/")); + const abstractOutsideFolder = this.app.vault.getAbstractFileByPath(path.replace('.md', '')); if (abstractFile instanceof TFolder) { return abstractFile; + } else if (abstractOutsideFolder instanceof TFolder) { + return abstractOutsideFolder; } else { return null; } @@ -269,7 +322,7 @@ export default class Waypoint extends Plugin { log(message: string) { if (this.settings.debugLogging) { - console.log(message); + console.log(message); } } @@ -340,6 +393,28 @@ class WaypointSettingsTab extends PluginSettingTab { await this.plugin.saveSettings(); }) ); + new Setting(containerEl) + .setName("Ignored folders") + .setDesc("Folders that Waypoint should ignore") + .addText(text => text + .setPlaceholder(DEFAULT_SETTINGS.ignoredFolders.join(",")) + .setValue(this.plugin.settings.ignoredFolders.join(", ")) + .onChange(async (value) => { + const previous = this.plugin.settings.ignoredFolders; + this.plugin.settings.ignoredFolders = value.split(/\s*,\s*/); + await this.plugin.saveSettings(); + + // Get a list of all new and old folders that need updating + const allFolders = [...new Set([...previous, ...this.plugin.settings.ignoredFolders])] + for (let i = 0; i < allFolders.length; i++) { + const file = this.app.vault.getAbstractFileByPath(allFolders[i]); + if (file === null) { continue } + await this.plugin.locateParentWaypoint(file, false).then((file) => { + if (file !== null) { this.plugin.updateWaypoint(file) } + }) + } + }) + ); const postscriptElement = containerEl.createEl("div", { cls: "setting-item", }); diff --git a/package-lock.json b/package-lock.json index 88445a8..ef1964d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,20 @@ { "name": "waypoint", +<<<<<<< HEAD + "version": "1.2.0", +======= "version": "1.1.0", +>>>>>>> FolderRoot/Master "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "waypoint", +<<<<<<< HEAD + "version": "1.2.0", +======= "version": "1.1.0", +>>>>>>> FolderRoot/Master "license": "MIT", "devDependencies": { "@types/codemirror": "^5.60.5",