Add waypoint plugin
Signed-off-by: baalajimaestro <me@baalajimaestro.me>
This commit is contained in:
parent
636c1ad7fd
commit
fb3dbada97
2 changed files with 424 additions and 0 deletions
414
.obsidian/plugins/waypoint/main.js
vendored
Normal file
414
.obsidian/plugins/waypoint/main.js
vendored
Normal 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);
|
||||
}
|
||||
};
|
10
.obsidian/plugins/waypoint/manifest.json
vendored
Normal file
10
.obsidian/plugins/waypoint/manifest.json
vendored
Normal 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
|
||||
}
|
Loading…
Reference in a new issue