mirror of
https://github.com/lostpaul/obsidian-folder-overview.git
synced 2026-07-22 05:35:07 +00:00
7735 lines
324 KiB
JavaScript
7735 lines
324 KiB
JavaScript
/*
|
|
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 __commonJS = (cb, mod) => function __require() {
|
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
};
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
|
|
// node_modules/front-matter-plugin-api-provider/lib/contracts/Api.js
|
|
var require_Api = __commonJS({
|
|
"node_modules/front-matter-plugin-api-provider/lib/contracts/Api.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
}
|
|
});
|
|
|
|
// node_modules/front-matter-plugin-api-provider/lib/contracts/EventDispatcher.js
|
|
var require_EventDispatcher = __commonJS({
|
|
"node_modules/front-matter-plugin-api-provider/lib/contracts/EventDispatcher.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
}
|
|
});
|
|
|
|
// node_modules/front-matter-plugin-api-provider/lib/contracts/Resolver.js
|
|
var require_Resolver = __commonJS({
|
|
"node_modules/front-matter-plugin-api-provider/lib/contracts/Resolver.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
}
|
|
});
|
|
|
|
// node_modules/front-matter-plugin-api-provider/lib/index.js
|
|
var require_lib = __commonJS({
|
|
"node_modules/front-matter-plugin-api-provider/lib/index.js"(exports) {
|
|
"use strict";
|
|
var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
if (k2 === void 0)
|
|
k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() {
|
|
return m[k];
|
|
} };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
} : function(o, m, k, k2) {
|
|
if (k2 === void 0)
|
|
k2 = k;
|
|
o[k2] = m[k];
|
|
});
|
|
var __exportStar = exports && exports.__exportStar || function(m, exports2) {
|
|
for (var p in m)
|
|
if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p))
|
|
__createBinding(exports2, m, p);
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.getApiSafe = exports.getDefer = exports.isPluginEnabled = exports.PluginNotEnabledError = exports.pluginId = void 0;
|
|
__exportStar(require_Api(), exports);
|
|
__exportStar(require_EventDispatcher(), exports);
|
|
__exportStar(require_Resolver(), exports);
|
|
exports.pluginId = "obsidian-front-matter-title-plugin";
|
|
var PluginNotEnabledError = class extends Error {
|
|
};
|
|
exports.PluginNotEnabledError = PluginNotEnabledError;
|
|
function isPluginEnabled(app) {
|
|
var _a, _b, _c;
|
|
return (_c = (_b = (_a = app === null || app === void 0 ? void 0 : app.plugins) === null || _a === void 0 ? void 0 : _a.enabledPlugins) === null || _b === void 0 ? void 0 : _b.has(exports.pluginId)) !== null && _c !== void 0 ? _c : false;
|
|
}
|
|
exports.isPluginEnabled = isPluginEnabled;
|
|
function getDefer3(app) {
|
|
var _a, _b, _c, _d;
|
|
const plugin = (_b = (_a = app === null || app === void 0 ? void 0 : app.plugins) === null || _a === void 0 ? void 0 : _a.getPlugin(exports.pluginId)) !== null && _b !== void 0 ? _b : null;
|
|
const defer = (_d = (_c = plugin === null || plugin === void 0 ? void 0 : plugin.getDefer) === null || _c === void 0 ? void 0 : _c.call(plugin)) !== null && _d !== void 0 ? _d : null;
|
|
if (defer === null) {
|
|
throw new PluginNotEnabledError(`Plugin ${exports.pluginId} is not enabled or old version`);
|
|
}
|
|
return defer;
|
|
}
|
|
exports.getDefer = getDefer3;
|
|
function getApiSafe(app) {
|
|
return new ApiWrapper(null, app);
|
|
}
|
|
exports.getApiSafe = getApiSafe;
|
|
var ApiWrapper = class {
|
|
constructor(api, app) {
|
|
this.api = api;
|
|
this.app = app;
|
|
}
|
|
before() {
|
|
if (this.api !== null) {
|
|
return;
|
|
}
|
|
const defer = this.getDeffer();
|
|
if (defer === null) {
|
|
return;
|
|
}
|
|
const api = defer.getApi();
|
|
if (api === null) {
|
|
return defer.awaitPlugin().then(() => {
|
|
this.api = defer.getApi();
|
|
});
|
|
} else {
|
|
this.api = api;
|
|
}
|
|
}
|
|
getDeffer() {
|
|
try {
|
|
return getDefer3(this.app);
|
|
} catch (e) {
|
|
if (e instanceof PluginNotEnabledError) {
|
|
return null;
|
|
}
|
|
throw e;
|
|
}
|
|
}
|
|
getResolverFactory() {
|
|
var _a, _b;
|
|
this.before();
|
|
return (_b = (_a = this.api) === null || _a === void 0 ? void 0 : _a.getResolverFactory()) !== null && _b !== void 0 ? _b : null;
|
|
}
|
|
getEventDispatcher() {
|
|
var _a, _b;
|
|
this.before();
|
|
return (_b = (_a = this.api) === null || _a === void 0 ? void 0 : _a.getEventDispatcher()) !== null && _b !== void 0 ? _b : null;
|
|
}
|
|
getEnabledFeatures() {
|
|
var _a, _b;
|
|
this.before();
|
|
return (_b = (_a = this.api) === null || _a === void 0 ? void 0 : _a.getEnabledFeatures()) !== null && _b !== void 0 ? _b : [];
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// src/obsidian-folder-overview/src/main.ts
|
|
var main_exports = {};
|
|
__export(main_exports, {
|
|
default: () => FolderOverviewPlugin,
|
|
updateOverviewView: () => updateOverviewView,
|
|
updateViewDropdown: () => updateViewDropdown
|
|
});
|
|
module.exports = __toCommonJS(main_exports);
|
|
var import_obsidian51 = require("obsidian");
|
|
|
|
// src/obsidian-folder-overview/src/view.ts
|
|
var import_obsidian50 = require("obsidian");
|
|
|
|
// src/obsidian-folder-overview/src/FolderOverview.ts
|
|
var import_obsidian49 = require("obsidian");
|
|
|
|
// src/obsidian-folder-overview/src/modals/Settings.ts
|
|
var import_obsidian45 = require("obsidian");
|
|
|
|
// src/obsidian-folder-overview/src/utils/LinkList.ts
|
|
var import_obsidian43 = require("obsidian");
|
|
|
|
// src/main.ts
|
|
var import_obsidian42 = require("obsidian");
|
|
|
|
// src/settings/SettingsTab.ts
|
|
var import_obsidian32 = require("obsidian");
|
|
|
|
// src/modals/ExistingNote.ts
|
|
var import_obsidian = require("obsidian");
|
|
var ExistingFolderNoteModal = class extends import_obsidian.Modal {
|
|
constructor(app, plugin, file, folder, folderNote) {
|
|
super(app);
|
|
this.plugin = plugin;
|
|
this.app = app;
|
|
this.file = file;
|
|
this.folder = folder;
|
|
this.folderNote = folderNote;
|
|
}
|
|
onOpen() {
|
|
var _a;
|
|
const { contentEl } = this;
|
|
contentEl.createEl("h2", { text: "A folder note for this folder already exists" });
|
|
const setting = new import_obsidian.Setting(contentEl);
|
|
setting.infoEl.createEl("p", { text: "Are you sure you want to turn the note into a folder note and rename the existing folder note?" });
|
|
(_a = setting.infoEl.parentElement) == null ? void 0 : _a.classList.add("fn-delete-confirmation-modal");
|
|
const buttonContainer = setting.infoEl.createEl("div", { cls: "fn-delete-confirmation-modal-buttons" });
|
|
if (import_obsidian.Platform.isMobileApp) {
|
|
const confirmButton = buttonContainer.createEl("button", {
|
|
text: "Rename and don't ask again"
|
|
});
|
|
confirmButton.classList.add("mod-warning", "fn-confirmation-modal-button");
|
|
confirmButton.addEventListener("click", () => {
|
|
this.plugin.settings.showRenameConfirmation = false;
|
|
void this.plugin.saveSettings();
|
|
this.close();
|
|
turnIntoFolderNote(this.plugin, this.file, this.folder, this.folderNote, true);
|
|
});
|
|
} else {
|
|
const checkbox = buttonContainer.createEl("input", { type: "checkbox" });
|
|
checkbox.addEventListener("change", (e) => {
|
|
const target = e.target;
|
|
if (target.checked) {
|
|
this.plugin.settings.showRenameConfirmation = false;
|
|
} else {
|
|
this.plugin.settings.showRenameConfirmation = true;
|
|
}
|
|
});
|
|
const checkBoxText = buttonContainer.createEl("span", { text: "Don't ask again" });
|
|
checkBoxText.addEventListener("click", () => {
|
|
checkbox.click();
|
|
});
|
|
}
|
|
const button = buttonContainer.createEl("button", { text: "Rename" });
|
|
button.classList.add("mod-warning", "fn-confirmation-modal-button");
|
|
button.addEventListener("click", () => {
|
|
void this.plugin.saveSettings();
|
|
this.close();
|
|
turnIntoFolderNote(this.plugin, this.file, this.folder, this.folderNote, true);
|
|
});
|
|
button.focus();
|
|
const cancelButton = buttonContainer.createEl("button", { text: "Cancel" });
|
|
cancelButton.addEventListener("click", () => {
|
|
this.close();
|
|
});
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/template.ts
|
|
var import_obsidian2 = require("obsidian");
|
|
async function applyTemplate(plugin, file, leaf, templatePath) {
|
|
const fileContent = await plugin.app.vault.read(file).catch((err) => {
|
|
console.error(`Error reading file ${file.path}:`, err);
|
|
});
|
|
if (fileContent !== "")
|
|
return;
|
|
const templateFile = templatePath ? plugin.app.vault.getAbstractFileByPath(templatePath) : null;
|
|
if (templateFile && templateFile instanceof import_obsidian2.TFile) {
|
|
try {
|
|
const {
|
|
templatesEnabled,
|
|
templaterEnabled,
|
|
templatesPlugin,
|
|
templaterPlugin
|
|
} = getTemplatePlugins(plugin.app);
|
|
const templateContent = await plugin.app.vault.read(templateFile);
|
|
if (templateContent.includes("==\u26A0 Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this activeDocument. \u26A0==")) {
|
|
return;
|
|
}
|
|
if (templaterEnabled && templaterPlugin) {
|
|
return await templaterPlugin.write_template_to_file(templateFile, file);
|
|
} else if (templatesEnabled && templatesPlugin) {
|
|
if (leaf instanceof import_obsidian2.WorkspaceLeaf) {
|
|
await leaf.openFile(file);
|
|
}
|
|
return await templatesPlugin.instance.insertTemplate(templateFile);
|
|
}
|
|
await plugin.app.vault.modify(file, templateContent);
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
}
|
|
function getTemplatePlugins(app) {
|
|
var _a, _b, _c;
|
|
const appAsUnknown = app;
|
|
const templatesPlugin = appAsUnknown.internalPlugins.plugins.templates;
|
|
const templatesEnabled = (_a = templatesPlugin == null ? void 0 : templatesPlugin.enabled) != null ? _a : false;
|
|
const templaterPlugin = appAsUnknown.plugins.plugins["templater-obsidian"];
|
|
const templaterEnabled = appAsUnknown.plugins.enabledPlugins.has("templater-obsidian");
|
|
const templaterEmptyFileTemplate = templaterPlugin && ((_b = templaterPlugin.settings) == null ? void 0 : _b.empty_file_template);
|
|
const templateFolder = templatesEnabled ? templatesPlugin.instance.options.folder : (_c = templaterPlugin == null ? void 0 : templaterPlugin.settings) == null ? void 0 : _c.template_folder;
|
|
return {
|
|
templatesPlugin: templatesPlugin || null,
|
|
templatesEnabled,
|
|
templaterPlugin: (templaterPlugin == null ? void 0 : templaterPlugin.templater) || null,
|
|
templaterEnabled,
|
|
templaterEmptyFileTemplate,
|
|
templateFolder
|
|
};
|
|
}
|
|
|
|
// src/functions/folderNoteFunctions.ts
|
|
var import_obsidian16 = require("obsidian");
|
|
|
|
// src/modals/DeleteConfirmation.ts
|
|
var import_obsidian3 = require("obsidian");
|
|
var DeleteConfirmationModal = class extends import_obsidian3.Modal {
|
|
constructor(app, plugin, file) {
|
|
super(app);
|
|
this.plugin = plugin;
|
|
this.app = app;
|
|
this.file = file;
|
|
}
|
|
onOpen() {
|
|
const { contentEl, plugin } = this;
|
|
const modalTitle = contentEl.createDiv({ cls: "fn-modal-title" });
|
|
const modalContent = contentEl.createDiv({ cls: "fn-modal-content" });
|
|
modalTitle.createEl("h2", { text: "Delete folder note" });
|
|
modalContent.createEl("p", { text: `Are you sure you want to delete the folder note '${this.file.name}' ?` });
|
|
switch (plugin.settings.deleteFilesAction) {
|
|
case "trash":
|
|
modalContent.createEl("p", { text: "It will be moved to your system trash." });
|
|
break;
|
|
case "obsidianTrash":
|
|
modalContent.createEl("p", { text: 'It will be moved to your Obsidian trash, which is located in the ".trash" hidden folder in your vault.' });
|
|
break;
|
|
case "delete":
|
|
modalContent.createEl("p", { text: "It will be permanently deleted." }).setCssStyles({ color: "red" });
|
|
break;
|
|
}
|
|
const buttonContainer = contentEl.createEl("div", { cls: "modal-button-container" });
|
|
if (!import_obsidian3.Platform.isMobile) {
|
|
const checkbox = buttonContainer.createEl("label", { cls: "mod-checkbox" });
|
|
checkbox.tabIndex = -1;
|
|
const input = checkbox.createEl("input", { type: "checkbox" });
|
|
checkbox.appendText("Don't ask again");
|
|
input.addEventListener("change", (e) => {
|
|
const target = e.target;
|
|
if (target.checked) {
|
|
plugin.settings.showDeleteConfirmation = false;
|
|
} else {
|
|
plugin.settings.showDeleteConfirmation = true;
|
|
}
|
|
plugin.saveSettings();
|
|
});
|
|
} else {
|
|
const confirmButton = buttonContainer.createEl("button", {
|
|
text: "Delete and don't ask again",
|
|
cls: "mod-destructive"
|
|
});
|
|
confirmButton.addEventListener("click", async () => {
|
|
plugin.settings.showDeleteConfirmation = false;
|
|
plugin.saveSettings();
|
|
this.close();
|
|
deleteFolderNote(plugin, this.file, false);
|
|
});
|
|
}
|
|
const deleteButton = buttonContainer.createEl("button", {
|
|
text: "Delete",
|
|
cls: "mod-warning"
|
|
});
|
|
deleteButton.addEventListener("click", async () => {
|
|
this.close();
|
|
deleteFolderNote(plugin, this.file, false);
|
|
});
|
|
deleteButton.focus();
|
|
const cancelButton = buttonContainer.createEl("button", {
|
|
text: "Cancel",
|
|
cls: "mod-cancel"
|
|
});
|
|
cancelButton.addEventListener("click", async () => {
|
|
this.close();
|
|
});
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/functions/utils.ts
|
|
var import_obsidian4 = require("obsidian");
|
|
function isFileExplorerWorkspaceLeaf(leaf) {
|
|
var _a;
|
|
const tabHeaderEl = leaf == null ? void 0 : leaf.tabHeaderEl;
|
|
return ((_a = tabHeaderEl == null ? void 0 : tabHeaderEl.dataset) == null ? void 0 : _a.type) === "file-explorer";
|
|
}
|
|
function getFileNameFromPathString(path) {
|
|
return path.substring(path.lastIndexOf("/") >= 0 ? path.lastIndexOf("/") + 1 : 0);
|
|
}
|
|
function getFolderNameFromPathString(path) {
|
|
const PARENT_FOLDER_INDEX = -2;
|
|
const LAST_FOLDER_INDEX = -1;
|
|
if (path.endsWith(".md") || path.endsWith(".canvas")) {
|
|
return path.split("/").slice(PARENT_FOLDER_INDEX)[0];
|
|
}
|
|
return path.split("/").slice(LAST_FOLDER_INDEX)[0];
|
|
}
|
|
function removeExtension(name) {
|
|
return name.replace(/\.[^/.]+$/, "");
|
|
}
|
|
function getFolderPathFromString(path) {
|
|
const subString = path.lastIndexOf("/") >= 0 ? path.lastIndexOf("/") : 0;
|
|
const folderPath = path.substring(0, subString);
|
|
if (folderPath === "") {
|
|
return "/";
|
|
}
|
|
return folderPath;
|
|
}
|
|
function getFileExplorer(plugin) {
|
|
var _a, _b, _c;
|
|
let leaf = plugin.app.workspace.getLeavesOfType("file-explorer")[0];
|
|
if (!leaf) {
|
|
return void 0;
|
|
}
|
|
if (((_c = (_b = (_a = leaf.containerEl) == null ? void 0 : _a.lastChild) == null ? void 0 : _b.dataset) == null ? void 0 : _c.type) === "mk-path-view") {
|
|
plugin.app.workspace.iterateAllLeaves((x) => {
|
|
if (isFileExplorerWorkspaceLeaf(x)) {
|
|
leaf = x;
|
|
}
|
|
});
|
|
}
|
|
return isFileExplorerWorkspaceLeaf(leaf) ? leaf : void 0;
|
|
}
|
|
function getFileExplorerActiveFolder(plugin) {
|
|
var _a, _b, _c;
|
|
const view = plugin.app.workspace.getActiveViewOfType(import_obsidian4.View);
|
|
if ((view == null ? void 0 : view.getViewType()) !== "file-explorer")
|
|
return null;
|
|
const fe = view;
|
|
const activeFileOrFolder = (_c = (_a = fe.tree.focusedItem) == null ? void 0 : _a.file) != null ? _c : (_b = fe.activeDom) == null ? void 0 : _b.file;
|
|
if (!(activeFileOrFolder instanceof import_obsidian4.TFolder))
|
|
return null;
|
|
return activeFileOrFolder;
|
|
}
|
|
function getAttachmentFolderPath(plugin) {
|
|
const attachmentFolderPath = plugin.app.vault.getConfig("attachmentFolderPath");
|
|
const cleanAttachmentFolderPath = (attachmentFolderPath == null ? void 0 : attachmentFolderPath.replace("./", "")) || "";
|
|
return cleanAttachmentFolderPath;
|
|
}
|
|
function isFileInAttachmentFolder(plugin, file) {
|
|
const attachmentFolderPath = getAttachmentFolderPath(plugin);
|
|
if (!attachmentFolderPath)
|
|
return false;
|
|
return file.path.startsWith(attachmentFolderPath + "/") || file.path.includes("/" + attachmentFolderPath + "/");
|
|
}
|
|
|
|
// src/ExcludeFolders/ExcludePattern.ts
|
|
var ExcludePattern = class {
|
|
constructor(pattern, position, id, plugin) {
|
|
this.detached = false;
|
|
this.type = "pattern";
|
|
this.id = id || crypto.randomUUID();
|
|
this.string = pattern;
|
|
this.position = position;
|
|
this.subFolders = plugin.settings.excludePatternDefaultSettings.subFolders;
|
|
this.disableSync = plugin.settings.excludePatternDefaultSettings.disableSync;
|
|
this.disableAutoCreate = plugin.settings.excludePatternDefaultSettings.disableAutoCreate;
|
|
this.disableFolderNote = plugin.settings.excludePatternDefaultSettings.disableFolderNote;
|
|
this.enableCollapsing = plugin.settings.excludePatternDefaultSettings.enableCollapsing;
|
|
this.excludeFromFolderOverview = plugin.settings.excludePatternDefaultSettings.excludeFromFolderOverview;
|
|
this.path = "";
|
|
this.hideInSettings = false;
|
|
this.showFolderNote = plugin.settings.excludePatternDefaultSettings.showFolderNote;
|
|
}
|
|
};
|
|
|
|
// src/ExcludeFolders/functions/folderFunctions.ts
|
|
var import_obsidian14 = require("obsidian");
|
|
|
|
// src/suggesters/FolderSuggester.ts
|
|
var import_obsidian5 = require("obsidian");
|
|
var FolderSuggest = class extends import_obsidian5.AbstractInputSuggest {
|
|
constructor(inputEl, plugin, whitelistSuggester, folder) {
|
|
super(plugin.app, inputEl);
|
|
this.inputEl = inputEl;
|
|
this.whitelistSuggester = whitelistSuggester;
|
|
this.folder = folder;
|
|
this.plugin = plugin;
|
|
}
|
|
get_error_msg(mode) {
|
|
switch (mode) {
|
|
case 0 /* TemplateFiles */:
|
|
return "Templates folder doesn't exist";
|
|
case 1 /* ScriptFiles */:
|
|
return "User Scripts folder doesn't exist";
|
|
}
|
|
}
|
|
getSuggestions(input_str) {
|
|
const folders = [];
|
|
const lower_input_str = input_str.toLowerCase();
|
|
let files = [];
|
|
if (this.folder) {
|
|
files = this.folder.children;
|
|
} else {
|
|
const MAX_FILE_SUGGESTIONS = 100;
|
|
files = this.plugin.app.vault.getAllLoadedFiles().slice(0, MAX_FILE_SUGGESTIONS);
|
|
}
|
|
files.forEach((folder) => {
|
|
if (folder instanceof import_obsidian5.TFolder && folder.path.toLowerCase().contains(lower_input_str) && (!this.plugin.settings.excludeFolders.find((f) => f.path === folder.path) || this.whitelistSuggester)) {
|
|
folders.push(folder);
|
|
}
|
|
});
|
|
return folders;
|
|
}
|
|
renderSuggestion(folder, el) {
|
|
el.setText(folder.path);
|
|
}
|
|
selectSuggestion(folder) {
|
|
this.inputEl.value = folder.path;
|
|
this.inputEl.trigger("input");
|
|
this.close();
|
|
}
|
|
};
|
|
|
|
// src/ExcludeFolders/modals/ExcludeFolderSettings.ts
|
|
var import_obsidian7 = require("obsidian");
|
|
|
|
// src/functions/styleFunctions.ts
|
|
var import_obsidian6 = require("obsidian");
|
|
|
|
// src/ExcludeFolders/ExcludeFolder.ts
|
|
var ExcludedFolder = class {
|
|
constructor(path, position, id, plugin) {
|
|
this.detached = false;
|
|
this.type = "folder";
|
|
this.id = id || crypto.randomUUID();
|
|
this.path = path;
|
|
this.subFolders = plugin.settings.excludeFolderDefaultSettings.subFolders;
|
|
this.disableSync = plugin.settings.excludeFolderDefaultSettings.disableSync;
|
|
this.disableAutoCreate = plugin.settings.excludeFolderDefaultSettings.disableAutoCreate;
|
|
this.disableFolderNote = plugin.settings.excludeFolderDefaultSettings.disableFolderNote;
|
|
this.enableCollapsing = plugin.settings.excludeFolderDefaultSettings.enableCollapsing;
|
|
this.position = position;
|
|
this.excludeFromFolderOverview = plugin.settings.excludeFolderDefaultSettings.excludeFromFolderOverview;
|
|
this.string = "";
|
|
this.hideInSettings = false;
|
|
this.showFolderNote = plugin.settings.excludeFolderDefaultSettings.showFolderNote;
|
|
}
|
|
};
|
|
|
|
// src/functions/styleFunctions.ts
|
|
function refreshAllFolderStyles(forceReload = false, plugin) {
|
|
const fileExplorer = getFileExplorer(plugin);
|
|
if (!fileExplorer) {
|
|
return;
|
|
}
|
|
if (plugin.activeFileExplorer === fileExplorer && !forceReload) {
|
|
return;
|
|
}
|
|
plugin.activeFileExplorer = fileExplorer;
|
|
plugin.app.vault.getAllLoadedFiles().forEach(async (file) => {
|
|
if (file instanceof import_obsidian6.TFolder) {
|
|
await updateCSSClassesForFolder(file.path, plugin);
|
|
}
|
|
});
|
|
}
|
|
async function updateCSSClassesForFolder(folderPath, plugin) {
|
|
const folder = plugin.app.vault.getAbstractFileByPath(folderPath);
|
|
if (!folder || !(folder instanceof import_obsidian6.TFolder)) {
|
|
return;
|
|
}
|
|
const folderNote = getFolderNote(plugin, folder.path);
|
|
const detachedFolderNote = getDetachedFolder(plugin, folder.path);
|
|
if (folder.children.length === 0) {
|
|
addCSSClassToFileExplorerEl(folder.path, "fn-empty-folder", false, plugin);
|
|
}
|
|
if (!folderNote || detachedFolderNote) {
|
|
removeCSSClassFromFileExplorerEL(folder == null ? void 0 : folder.path, "has-folder-note", false, plugin);
|
|
removeCSSClassFromFileExplorerEL(folder == null ? void 0 : folder.path, "only-has-folder-note", true, plugin);
|
|
removeCSSClassFromFileExplorerEL(folderNote == null ? void 0 : folderNote.path, "is-folder-note", false, plugin);
|
|
return;
|
|
}
|
|
const excludedFolder = getExcludedFolder(plugin, folder.path, true);
|
|
if (excludedFolder == null ? void 0 : excludedFolder.disableFolderNote) {
|
|
removeCSSClassFromFileExplorerEL(folderNote.path, "is-folder-note", false, plugin);
|
|
removeCSSClassFromFileExplorerEL(folder.path, "has-folder-note", false, plugin);
|
|
removeCSSClassFromFileExplorerEL(folder == null ? void 0 : folder.path, "only-has-folder-note", true, plugin);
|
|
} else {
|
|
markFolderWithFolderNoteClasses(folder, plugin);
|
|
if (excludedFolder == null ? void 0 : excludedFolder.showFolderNote) {
|
|
addCSSClassToFileExplorerEl(folder.path, "show-folder-note-in-explorer", true, plugin);
|
|
unmarkFileAsFolderNote(folderNote, plugin);
|
|
return;
|
|
}
|
|
if (plugin.isEmptyFolderNoteFolder(folder) && getFolderNote(plugin, folder.path)) {
|
|
addCSSClassToFileExplorerEl(folder.path, "only-has-folder-note", true, plugin);
|
|
} else {
|
|
removeCSSClassFromFileExplorerEL(folder.path, "only-has-folder-note", true, plugin);
|
|
}
|
|
}
|
|
markFolderAndNoteWithClasses(folderNote, folder, plugin);
|
|
}
|
|
async function updateCSSClassesForFolderNote(filePath, plugin) {
|
|
const file = plugin.app.vault.getAbstractFileByPath(filePath);
|
|
if (!file || !(file instanceof import_obsidian6.TFile)) {
|
|
return;
|
|
}
|
|
const folder = getFolder(plugin, file);
|
|
if (!folder || !(folder instanceof import_obsidian6.TFolder)) {
|
|
return;
|
|
}
|
|
updateCSSClassesForFolder(folder.path, plugin);
|
|
}
|
|
function markFolderAndNoteWithClasses(file, folder, plugin) {
|
|
markFileAsFolderNote(file, plugin);
|
|
markFolderWithFolderNoteClasses(folder, plugin);
|
|
}
|
|
function markFolderWithFolderNoteClasses(folder, plugin) {
|
|
addCSSClassToFileExplorerEl(folder.path, "has-folder-note", false, plugin);
|
|
if (plugin.isEmptyFolderNoteFolder(folder) && getFolderNote(plugin, folder.path)) {
|
|
addCSSClassToFileExplorerEl(folder.path, "only-has-folder-note", true, plugin);
|
|
} else {
|
|
removeCSSClassFromFileExplorerEL(folder.path, "only-has-folder-note", true, plugin);
|
|
}
|
|
}
|
|
function markFileAsFolderNote(file, plugin) {
|
|
addCSSClassToFileExplorerEl(file.path, "is-folder-note", false, plugin);
|
|
}
|
|
function unmarkFileAsFolderNote(file, plugin) {
|
|
removeCSSClassFromFileExplorerEL(file.path, "is-folder-note", false, plugin);
|
|
}
|
|
function unmarkFolderAsFolderNote(folder, plugin) {
|
|
removeCSSClassFromFileExplorerEL(folder.path, "has-folder-note", false, plugin);
|
|
removeCSSClassFromFileExplorerEL(folder.path, "only-has-folder-note", true, plugin);
|
|
}
|
|
async function addCSSClassToFileExplorerEl(path, cssClass, parent = false, plugin, waitForCreate = false, count = 0) {
|
|
const fileExplorerItem = getFileExplorerElement(path, plugin);
|
|
const MAX_RETRIES = 5;
|
|
const RETRY_DELAY = 500;
|
|
if (!fileExplorerItem) {
|
|
if (waitForCreate && count < MAX_RETRIES) {
|
|
await new Promise((r) => window.setTimeout(r, RETRY_DELAY));
|
|
addCSSClassToFileExplorerEl(path, cssClass, parent, plugin, waitForCreate, count + 1);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
if (parent) {
|
|
const parentElement = fileExplorerItem == null ? void 0 : fileExplorerItem.parentElement;
|
|
if (parentElement) {
|
|
parentElement.addClass(cssClass);
|
|
}
|
|
} else {
|
|
fileExplorerItem.addClass(cssClass);
|
|
activeDocument.querySelectorAll(`[data-path='${CSS.escape(path)}']`).forEach((item) => {
|
|
item.addClass(cssClass);
|
|
});
|
|
}
|
|
}
|
|
function removeCSSClassFromFileExplorerEL(path, cssClass, parent, plugin) {
|
|
if (!path)
|
|
return;
|
|
const fileExplorerItem = getFileExplorerElement(path, plugin);
|
|
activeDocument.querySelectorAll(`[data-path='${CSS.escape(path)}']`).forEach((item) => {
|
|
item.removeClass(cssClass);
|
|
});
|
|
if (!fileExplorerItem) {
|
|
return;
|
|
}
|
|
if (parent) {
|
|
const parentElement = fileExplorerItem == null ? void 0 : fileExplorerItem.parentElement;
|
|
if (parentElement) {
|
|
parentElement.removeClass(cssClass);
|
|
}
|
|
return;
|
|
}
|
|
fileExplorerItem.removeClass(cssClass);
|
|
}
|
|
function getFileExplorerElement(path, plugin) {
|
|
var _a, _b, _c, _d;
|
|
const fileExplorer = getFileExplorer(plugin);
|
|
if (!((_a = fileExplorer == null ? void 0 : fileExplorer.view) == null ? void 0 : _a.fileItems)) {
|
|
return null;
|
|
}
|
|
const fileExplorerItem = (_b = fileExplorer.view.fileItems) == null ? void 0 : _b[path];
|
|
return (_d = (_c = fileExplorerItem == null ? void 0 : fileExplorerItem.selfEl) != null ? _c : fileExplorerItem == null ? void 0 : fileExplorerItem.titleEl) != null ? _d : null;
|
|
}
|
|
function showFolderNoteInFileExplorer(path, plugin) {
|
|
const excludedFolder = new ExcludedFolder(path, plugin.settings.excludeFolders.length, void 0, plugin);
|
|
excludedFolder.subFolders = false;
|
|
excludedFolder.disableSync = false;
|
|
excludedFolder.disableAutoCreate = false;
|
|
excludedFolder.disableFolderNote = false;
|
|
excludedFolder.enableCollapsing = false;
|
|
excludedFolder.excludeFromFolderOverview = false;
|
|
excludedFolder.hideInSettings = true;
|
|
excludedFolder.showFolderNote = true;
|
|
addExcludedFolder(plugin, excludedFolder, false);
|
|
addCSSClassToFileExplorerEl(path, "show-folder-note-in-explorer", true, plugin);
|
|
updateCSSClassesForFolder(path, plugin);
|
|
}
|
|
function hideFolderNoteInFileExplorer(folderPath, plugin) {
|
|
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.path !== folderPath || !folder.showFolderNote);
|
|
plugin.saveSettings(false);
|
|
removeCSSClassFromFileExplorerEL(folderPath, "show-folder-note-in-explorer", true, plugin);
|
|
updateCSSClassesForFolder(folderPath, plugin);
|
|
}
|
|
function setActiveFolder(folderPath, plugin) {
|
|
const fileExplorerItem = getFileExplorerElement(folderPath, plugin);
|
|
if (fileExplorerItem) {
|
|
fileExplorerItem.addClass("fn-is-active");
|
|
plugin.activeFolderDom = fileExplorerItem;
|
|
}
|
|
}
|
|
function removeActiveFolder(plugin) {
|
|
var _a;
|
|
if (plugin.activeFolderDom) {
|
|
plugin.activeFolderDom.removeClass("fn-is-active");
|
|
(_a = plugin.activeFolderDom) == null ? void 0 : _a.removeClass("has-focus");
|
|
plugin.activeFolderDom = null;
|
|
}
|
|
}
|
|
|
|
// src/ExcludeFolders/modals/ExcludeFolderSettings.ts
|
|
var ExcludedFolderSettings = class extends import_obsidian7.Modal {
|
|
constructor(app, plugin, excludedFolder) {
|
|
super(app);
|
|
this.plugin = plugin;
|
|
this.app = app;
|
|
this.excludedFolder = excludedFolder;
|
|
}
|
|
onOpen() {
|
|
this.display();
|
|
}
|
|
display() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
contentEl.createEl("h2", { text: "Excluded folder settings" });
|
|
new import_obsidian7.Setting(contentEl).setName("Include subfolders").setDesc("Choose if the subfolders of the folder should also be excluded").addToggle((toggle) => toggle.setValue(this.excludedFolder.subFolders).onChange(async (value) => {
|
|
this.excludedFolder.subFolders = value;
|
|
await this.plugin.saveSettings(true);
|
|
}));
|
|
new import_obsidian7.Setting(contentEl).setName("Disable folder name sync").setDesc("Choose if the folder note should be renamed when the folder name is changed").addToggle((toggle) => toggle.setValue(this.excludedFolder.disableSync).onChange(async (value) => {
|
|
this.excludedFolder.disableSync = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian7.Setting(contentEl).setName("Don't show folder in folder overview").setDesc("Choose if the folder should be shown in the folder overview").addToggle((toggle) => toggle.setValue(this.excludedFolder.excludeFromFolderOverview).onChange(async (value) => {
|
|
this.excludedFolder.excludeFromFolderOverview = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian7.Setting(contentEl).setName("Show folder note in the file explorer").setDesc("Choose if the folder note should be shown in the file explorer").addToggle((toggle) => toggle.setValue(this.excludedFolder.showFolderNote).onChange(async (value) => {
|
|
this.excludedFolder.showFolderNote = value;
|
|
updateCSSClassesForFolder(this.excludedFolder.path, this.plugin);
|
|
await this.plugin.saveSettings();
|
|
this.display();
|
|
}));
|
|
new import_obsidian7.Setting(contentEl).setName("Disable auto creation of folder notes in this folder").setDesc("Choose if a folder note should be created when a new folder is created").addToggle((toggle) => toggle.setValue(this.excludedFolder.disableAutoCreate).onChange(async (value) => {
|
|
this.excludedFolder.disableAutoCreate = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian7.Setting(contentEl).setName("Disable open folder note").setDesc("Choose if the folder note should be opened when the folder is opened").addToggle((toggle) => toggle.setValue(this.excludedFolder.disableFolderNote).onChange(async (value) => {
|
|
this.excludedFolder.disableFolderNote = value;
|
|
await this.plugin.saveSettings(true);
|
|
this.display();
|
|
}));
|
|
if (!this.excludedFolder.disableFolderNote) {
|
|
new import_obsidian7.Setting(contentEl).setName("Collapse folder when opening folder note").setDesc("Choose if the folder should be collapsed when the folder note is opened").addToggle((toggle) => toggle.setValue(this.excludedFolder.enableCollapsing).onChange(async (value) => {
|
|
this.excludedFolder.enableCollapsing = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
}
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/ExcludeFolders/functions/patternFunctions.ts
|
|
var import_obsidian9 = require("obsidian");
|
|
|
|
// src/ExcludeFolders/modals/PatternSettings.ts
|
|
var import_obsidian8 = require("obsidian");
|
|
var PatternSettings = class extends import_obsidian8.Modal {
|
|
constructor(app, plugin, pattern) {
|
|
super(app);
|
|
this.plugin = plugin;
|
|
this.app = app;
|
|
this.pattern = pattern;
|
|
}
|
|
onOpen() {
|
|
this.display();
|
|
}
|
|
display() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
contentEl.createEl("h2", { text: "Pattern settings" });
|
|
new import_obsidian8.Setting(contentEl).setName("Disable folder name sync").setDesc("Choose if the folder name should be renamed when the file name has been changed").addToggle((toggle) => toggle.setValue(this.pattern.disableSync).onChange(async (value) => {
|
|
this.pattern.disableSync = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian8.Setting(contentEl).setName("Disable auto creation of folder notes in this folder").setDesc("Choose if a folder note should be created when a new folder is created that matches this pattern").addToggle((toggle) => toggle.setValue(this.pattern.disableAutoCreate).onChange(async (value) => {
|
|
this.pattern.disableAutoCreate = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian8.Setting(contentEl).setName("Don't show folder in folder overview").setDesc("Choose if the folder should be shown in the folder overview").addToggle((toggle) => toggle.setValue(this.pattern.excludeFromFolderOverview).onChange(async (value) => {
|
|
this.pattern.excludeFromFolderOverview = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian8.Setting(contentEl).setName("Show folder note in the file explorer").setDesc("Choose if the folder note should be shown in the file explorer").addToggle((toggle) => toggle.setValue(this.pattern.showFolderNote).onChange(async (value) => {
|
|
this.pattern.showFolderNote = value;
|
|
await this.plugin.saveSettings();
|
|
refreshAllFolderStyles(true, this.plugin);
|
|
this.display();
|
|
}));
|
|
new import_obsidian8.Setting(contentEl).setName("Disable open folder note").setDesc("Choose if the folder note should be opened when the folder is opened").addToggle((toggle) => toggle.setValue(this.pattern.disableFolderNote).onChange(async (value) => {
|
|
this.pattern.disableFolderNote = value;
|
|
await this.plugin.saveSettings(true);
|
|
this.display();
|
|
}));
|
|
if (!this.pattern.disableFolderNote) {
|
|
new import_obsidian8.Setting(contentEl).setName("Collapse folder when opening folder note").setDesc("Choose if the folder should be collapsed when the folder note is opened").addToggle((toggle) => toggle.setValue(this.pattern.enableCollapsing).onChange(async (value) => {
|
|
this.pattern.enableCollapsing = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
}
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/ExcludeFolders/functions/patternFunctions.ts
|
|
var REGEX_PREFIX = "{regex}";
|
|
var STAR = "*";
|
|
var INDEX_START = 0;
|
|
var SLICE_START_ONE = 1;
|
|
var SLICE_EXCLUDE_LAST = -1;
|
|
function matchesPatternSpec(raw, folderName) {
|
|
if (!raw)
|
|
return false;
|
|
const string = raw.trim();
|
|
const isRegex = string.startsWith(REGEX_PREFIX);
|
|
const hasStartStar = string.startsWith(STAR);
|
|
const hasEndStar = string.endsWith(STAR);
|
|
if (!isRegex && !(hasStartStar || hasEndStar))
|
|
return false;
|
|
if (isRegex) {
|
|
const body = string.replace(REGEX_PREFIX, "").trim();
|
|
if (body === "")
|
|
return false;
|
|
try {
|
|
return new RegExp(body).test(folderName);
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
if (hasStartStar && hasEndStar) {
|
|
const inner = string.slice(SLICE_START_ONE, SLICE_EXCLUDE_LAST);
|
|
return folderName.includes(inner);
|
|
}
|
|
if (hasStartStar) {
|
|
const suffix = string.slice(SLICE_START_ONE);
|
|
return folderName.endsWith(suffix);
|
|
}
|
|
if (hasEndStar) {
|
|
const prefix = string.slice(INDEX_START, SLICE_EXCLUDE_LAST);
|
|
return folderName.startsWith(prefix);
|
|
}
|
|
return false;
|
|
}
|
|
function updatePattern(plugin, pattern, newPattern) {
|
|
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.id !== pattern.id);
|
|
addExcludedFolder(plugin, newPattern);
|
|
}
|
|
async function deletePattern(plugin, pattern) {
|
|
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.id !== pattern.id || folder.type === "folder");
|
|
await plugin.saveSettings(true);
|
|
resyncArray(plugin);
|
|
}
|
|
function getExcludedFoldersByPattern(plugin, folderName) {
|
|
return plugin.settings.excludeFolders.filter((s) => s.type === "pattern").filter((pattern) => matchesPatternSpec(pattern.string, folderName));
|
|
}
|
|
function addExcludePatternListItem(settings, containerEl, pattern) {
|
|
const { plugin } = settings;
|
|
const setting = new import_obsidian9.Setting(containerEl);
|
|
setting.setClass("fn-exclude-folder-list");
|
|
setting.addSearch((cb) => {
|
|
cb.containerEl.addClass("fn-exclude-folder-path");
|
|
cb.setPlaceholder("Pattern");
|
|
cb.setValue(pattern.string);
|
|
cb.onChange((value) => {
|
|
pattern.string = value;
|
|
updatePattern(plugin, pattern, pattern);
|
|
});
|
|
});
|
|
setting.addButton((cb) => {
|
|
cb.setIcon("edit");
|
|
cb.setTooltip("Edit pattern");
|
|
cb.onClick(() => {
|
|
new PatternSettings(plugin.app, plugin, pattern).open();
|
|
});
|
|
});
|
|
if (import_obsidian9.Platform.isDesktop || import_obsidian9.Platform.isTablet) {
|
|
setting.addButton((cb) => {
|
|
cb.setIcon("up-chevron-glyph");
|
|
cb.setTooltip("Move up");
|
|
cb.onClick(() => {
|
|
if (pattern.position === 0) {
|
|
return;
|
|
}
|
|
pattern.position -= 1;
|
|
updatePattern(plugin, pattern, pattern);
|
|
const oldPattern = plugin.settings.excludeFolders.find((folder) => folder.position === pattern.position);
|
|
if (oldPattern) {
|
|
oldPattern.position += 1;
|
|
if (oldPattern.type === "pattern") {
|
|
const pat = oldPattern;
|
|
updatePattern(plugin, pat, pat);
|
|
} else {
|
|
updateExcludedFolder(plugin, oldPattern, oldPattern);
|
|
}
|
|
}
|
|
settings.display();
|
|
});
|
|
});
|
|
setting.addButton((cb) => {
|
|
cb.setIcon("down-chevron-glyph");
|
|
cb.setTooltip("Move down");
|
|
cb.onClick(() => {
|
|
if (pattern.position === plugin.settings.excludeFolders.length - 1) {
|
|
return;
|
|
}
|
|
pattern.position += 1;
|
|
updatePattern(plugin, pattern, pattern);
|
|
const oldPattern = plugin.settings.excludeFolders.find((folder) => folder.position === pattern.position);
|
|
if (oldPattern) {
|
|
oldPattern.position -= 1;
|
|
if (oldPattern.type === "pattern") {
|
|
const pat = oldPattern;
|
|
updatePattern(plugin, pat, pat);
|
|
} else {
|
|
updateExcludedFolder(plugin, oldPattern, oldPattern);
|
|
}
|
|
}
|
|
settings.display();
|
|
});
|
|
});
|
|
}
|
|
setting.addButton((cb) => {
|
|
cb.setIcon("trash-2");
|
|
cb.setTooltip("Delete pattern");
|
|
cb.onClick(() => {
|
|
void deletePattern(plugin, pattern);
|
|
setting.clear();
|
|
setting.settingEl.remove();
|
|
});
|
|
});
|
|
}
|
|
|
|
// src/ExcludeFolders/WhitelistPattern.ts
|
|
var WhitelistedPattern = class {
|
|
constructor(pattern, position, id, plugin) {
|
|
this.enableSync = false;
|
|
this.enableAutoCreate = false;
|
|
this.enableFolderNote = false;
|
|
this.disableCollapsing = false;
|
|
this.showInFolderOverview = false;
|
|
this.hideInFileExplorer = false;
|
|
this.hideInSettings = false;
|
|
this.type = "pattern";
|
|
this.id = id || crypto.randomUUID();
|
|
this.subFolders = plugin.settings.excludePatternDefaultSettings.subFolders;
|
|
this.position = position;
|
|
this.string = pattern;
|
|
this.path = "";
|
|
}
|
|
};
|
|
|
|
// src/ExcludeFolders/functions/whitelistFolderFunctions.ts
|
|
var import_obsidian13 = require("obsidian");
|
|
|
|
// src/ExcludeFolders/modals/WhitelistFolderSettings.ts
|
|
var import_obsidian10 = require("obsidian");
|
|
var WhitelistFolderSettings = class extends import_obsidian10.Modal {
|
|
constructor(app, plugin, whitelistedFolder) {
|
|
super(app);
|
|
this.plugin = plugin;
|
|
this.app = app;
|
|
this.whitelistedFolder = whitelistedFolder;
|
|
}
|
|
onOpen() {
|
|
this.display();
|
|
}
|
|
display() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
contentEl.createEl("h2", { text: "Whitelisted folder settings" });
|
|
new import_obsidian10.Setting(contentEl).setName("Include subfolders").setDesc("Choose if the subfolders of the folder should also be whitelisted").addToggle((toggle) => toggle.setValue(this.whitelistedFolder.subFolders).onChange(async (value) => {
|
|
this.whitelistedFolder.subFolders = value;
|
|
await this.plugin.saveSettings(true);
|
|
}));
|
|
new import_obsidian10.Setting(contentEl).setName("Enable folder name sync").setDesc("Choose if the name of a folder note should be renamed when the folder name is changed").addToggle((toggle) => toggle.setValue(this.whitelistedFolder.enableSync).onChange(async (value) => {
|
|
this.whitelistedFolder.enableSync = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian10.Setting(contentEl).setName("Show folder in folder overview").setDesc("Choose if the folder should be shown in the folder overview").addToggle((toggle) => toggle.setValue(this.whitelistedFolder.showInFolderOverview).onChange(async (value) => {
|
|
this.whitelistedFolder.showInFolderOverview = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian10.Setting(contentEl).setName("Hide folder note in file explorer").setDesc("Choose if the folder note should be hidden in the file explorer").addToggle((toggle) => toggle.setValue(this.whitelistedFolder.hideInFileExplorer).onChange(async (value) => {
|
|
this.whitelistedFolder.hideInFileExplorer = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian10.Setting(contentEl).setName("Allow auto creation of folder notes in this folder").addToggle((toggle) => toggle.setValue(this.whitelistedFolder.enableAutoCreate).onChange(async (value) => {
|
|
this.whitelistedFolder.enableAutoCreate = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian10.Setting(contentEl).setName("Open folder note when clicking on the folder").setDesc("Choose if the folder note should be opened when the folder is opened").addToggle((toggle) => toggle.setValue(this.whitelistedFolder.enableFolderNote).onChange(async (value) => {
|
|
this.whitelistedFolder.enableFolderNote = value;
|
|
await this.plugin.saveSettings(true);
|
|
this.display();
|
|
}));
|
|
if (this.whitelistedFolder.enableFolderNote) {
|
|
new import_obsidian10.Setting(contentEl).setName("Don't collapse folder when opening folder note").setDesc("Choose if the folder should be collapsed when the folder note is opened").addToggle((toggle) => toggle.setValue(this.whitelistedFolder.disableCollapsing).onChange(async (value) => {
|
|
this.whitelistedFolder.disableCollapsing = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
}
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/ExcludeFolders/functions/whitelistPatternFunctions.ts
|
|
var import_obsidian12 = require("obsidian");
|
|
|
|
// src/ExcludeFolders/modals/WhitelistPatternSettings.ts
|
|
var import_obsidian11 = require("obsidian");
|
|
var WhitelistPatternSettings = class extends import_obsidian11.Modal {
|
|
constructor(app, plugin, pattern) {
|
|
super(app);
|
|
this.plugin = plugin;
|
|
this.app = app;
|
|
this.pattern = pattern;
|
|
}
|
|
onOpen() {
|
|
this.display();
|
|
}
|
|
display() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
contentEl.createEl("h2", { text: "Whitelisted pattern settings" });
|
|
new import_obsidian11.Setting(contentEl).setName("Enable folder name sync").setDesc("Choose if the name of a folder note should be renamed when the folder name is changed").addToggle((toggle) => toggle.setValue(this.pattern.enableSync).onChange(async (value) => {
|
|
this.pattern.enableSync = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian11.Setting(contentEl).setName("Allow auto creation of folder notes in this folder").addToggle((toggle) => toggle.setValue(this.pattern.enableAutoCreate).onChange(async (value) => {
|
|
this.pattern.enableAutoCreate = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian11.Setting(contentEl).setName("Show folder in folder overview").setDesc("Choose if the folder should be shown in the folder overview").addToggle((toggle) => toggle.setValue(this.pattern.showInFolderOverview).onChange(async (value) => {
|
|
this.pattern.showInFolderOverview = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian11.Setting(contentEl).setName("Open folder note when clicking on the folder").setDesc("Choose if the folder note should be opened when you click on the folder").addToggle((toggle) => toggle.setValue(this.pattern.enableFolderNote).onChange(async (value) => {
|
|
this.pattern.enableFolderNote = value;
|
|
await this.plugin.saveSettings(true);
|
|
this.display();
|
|
}));
|
|
if (this.pattern.enableFolderNote) {
|
|
new import_obsidian11.Setting(contentEl).setName("Don't collapse folder when opening folder note").setDesc("Choose if the folder should be collapsed when the folder note is opened").addToggle((toggle) => toggle.setValue(this.pattern.disableCollapsing).onChange(async (value) => {
|
|
this.pattern.disableCollapsing = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
}
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/ExcludeFolders/functions/whitelistPatternFunctions.ts
|
|
var REGEX_PREFIX2 = "{regex}";
|
|
var STAR2 = "*";
|
|
var SLICE_START_ONE2 = 1;
|
|
var SLICE_EXCLUDE_LAST2 = -1;
|
|
function matchesPatternSpec2(raw, folderName) {
|
|
if (!raw)
|
|
return false;
|
|
const string = raw.trim();
|
|
const isRegex = string.startsWith(REGEX_PREFIX2);
|
|
const hasStartStar = string.startsWith(STAR2);
|
|
const hasEndStar = string.endsWith(STAR2);
|
|
if (!isRegex && !(hasStartStar || hasEndStar))
|
|
return false;
|
|
if (isRegex) {
|
|
const body = string.replace(REGEX_PREFIX2, "").trim();
|
|
if (body === "")
|
|
return false;
|
|
try {
|
|
return new RegExp(body).test(folderName);
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
if (hasStartStar && hasEndStar) {
|
|
const inner = string.slice(SLICE_START_ONE2, SLICE_EXCLUDE_LAST2);
|
|
return folderName.includes(inner);
|
|
}
|
|
if (hasStartStar) {
|
|
const suffix = string.slice(SLICE_START_ONE2);
|
|
return folderName.endsWith(suffix);
|
|
}
|
|
if (hasEndStar) {
|
|
const prefix = string.slice(0, SLICE_EXCLUDE_LAST2);
|
|
return folderName.startsWith(prefix);
|
|
}
|
|
return false;
|
|
}
|
|
function updateWhitelistedPattern(plugin, pattern, newPattern) {
|
|
plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter((folder) => folder.id !== pattern.id);
|
|
addWhitelistedFolder(plugin, newPattern);
|
|
}
|
|
async function deletePattern2(plugin, pattern) {
|
|
plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter((folder) => folder.id !== pattern.id || folder.type === "folder");
|
|
await plugin.saveSettings(true);
|
|
resyncArray(plugin);
|
|
}
|
|
function getWhitelistedFoldersByPattern(plugin, folderName) {
|
|
return plugin.settings.whitelistFolders.filter((s) => s.type === "pattern").filter((pattern) => matchesPatternSpec2(pattern.string, folderName));
|
|
}
|
|
function addWhitelistedPatternListItem(settings, containerEl, pattern) {
|
|
const { plugin } = settings;
|
|
const setting = new import_obsidian12.Setting(containerEl);
|
|
setting.setClass("fn-exclude-folder-list");
|
|
setting.addSearch((cb) => {
|
|
cb.containerEl.addClass("fn-exclude-folder-path");
|
|
cb.setPlaceholder("Pattern");
|
|
cb.setValue(pattern.string);
|
|
cb.onChange((value) => {
|
|
const exists = plugin.settings.whitelistFolders.some((folder) => folder.string === value);
|
|
if (exists) {
|
|
return;
|
|
}
|
|
pattern.string = value;
|
|
updateWhitelistedPattern(plugin, pattern, pattern);
|
|
});
|
|
});
|
|
setting.addButton((cb) => {
|
|
cb.setIcon("edit");
|
|
cb.setTooltip("Edit pattern");
|
|
cb.onClick(() => {
|
|
new WhitelistPatternSettings(plugin.app, plugin, pattern).open();
|
|
});
|
|
});
|
|
setting.addButton((cb) => {
|
|
cb.setIcon("up-chevron-glyph");
|
|
cb.setTooltip("Move up");
|
|
cb.onClick(() => {
|
|
if (pattern.position === 0) {
|
|
return;
|
|
}
|
|
pattern.position -= 1;
|
|
updateWhitelistedPattern(plugin, pattern, pattern);
|
|
const oldPattern = plugin.settings.whitelistFolders.find((folder) => folder.position === pattern.position);
|
|
if (oldPattern) {
|
|
oldPattern.position += 1;
|
|
if (oldPattern.type === "pattern") {
|
|
updateWhitelistedPattern(plugin, oldPattern, oldPattern);
|
|
} else {
|
|
updateWhitelistedFolder(plugin, oldPattern, oldPattern);
|
|
}
|
|
}
|
|
settings.display();
|
|
});
|
|
});
|
|
setting.addButton((cb) => {
|
|
cb.setIcon("down-chevron-glyph");
|
|
cb.setTooltip("Move down");
|
|
cb.onClick(() => {
|
|
if (pattern.position === plugin.settings.whitelistFolders.length - 1) {
|
|
return;
|
|
}
|
|
pattern.position += 1;
|
|
updateWhitelistedPattern(plugin, pattern, pattern);
|
|
const oldPattern = plugin.settings.whitelistFolders.find((folder) => folder.position === pattern.position);
|
|
if (oldPattern) {
|
|
oldPattern.position -= 1;
|
|
if (oldPattern.type === "pattern") {
|
|
updateWhitelistedPattern(plugin, oldPattern, oldPattern);
|
|
} else {
|
|
updateWhitelistedFolder(plugin, oldPattern, oldPattern);
|
|
}
|
|
}
|
|
settings.display();
|
|
});
|
|
});
|
|
setting.addButton((cb) => {
|
|
cb.setIcon("trash-2");
|
|
cb.setTooltip("Delete pattern");
|
|
cb.onClick(() => {
|
|
void deletePattern2(plugin, pattern);
|
|
setting.clear();
|
|
setting.settingEl.remove();
|
|
});
|
|
});
|
|
}
|
|
|
|
// src/ExcludeFolders/functions/whitelistFolderFunctions.ts
|
|
function getWhitelistedFolder(plugin, path) {
|
|
let whitelistedFolder = {};
|
|
const folderName = getFolderNameFromPathString(path);
|
|
const matchedPatterns = getWhitelistedFoldersByPattern(plugin, folderName);
|
|
const whitelistedFolders = getWhitelistedFoldersByPath(plugin, path);
|
|
const combinedWhitelistedFolders = [...matchedPatterns, ...whitelistedFolders];
|
|
const propertiesToCopy = [
|
|
"enableAutoCreate",
|
|
"enableFolderNote",
|
|
"enableSync",
|
|
"showInFolderOverview"
|
|
];
|
|
if (combinedWhitelistedFolders.length > 0) {
|
|
for (const matchedFolder of combinedWhitelistedFolders) {
|
|
propertiesToCopy.forEach((property) => {
|
|
const value = matchedFolder[property];
|
|
if (value === true) {
|
|
whitelistedFolder[property] = true;
|
|
} else if (!value) {
|
|
whitelistedFolder[property] = false;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
if (whitelistedFolder && Object.keys(whitelistedFolder).length === 0) {
|
|
whitelistedFolder = void 0;
|
|
}
|
|
return whitelistedFolder;
|
|
}
|
|
function getWhitelistedFoldersByPath(plugin, path) {
|
|
return plugin.settings.whitelistFolders.filter((whitelistedFolder) => {
|
|
if (whitelistedFolder.path === path) {
|
|
return true;
|
|
}
|
|
if (!whitelistedFolder.subFolders) {
|
|
return false;
|
|
}
|
|
return getFolderPathFromString(path).startsWith(whitelistedFolder.path);
|
|
});
|
|
}
|
|
function addWhitelistedFolder(plugin, whitelistedFolder) {
|
|
plugin.settings.whitelistFolders.push(whitelistedFolder);
|
|
void plugin.saveSettings(true);
|
|
}
|
|
async function deleteWhitelistedFolder(plugin, whitelistedFolder) {
|
|
plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter((folder) => folder.id !== whitelistedFolder.id || folder.type === "pattern");
|
|
await plugin.saveSettings(true);
|
|
resyncArray2(plugin);
|
|
}
|
|
function updateWhitelistedFolder(plugin, whitelistedFolder, newWhitelistFolder) {
|
|
plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter((folder) => folder.id !== whitelistedFolder.id);
|
|
addWhitelistedFolder(plugin, newWhitelistFolder);
|
|
}
|
|
function resyncArray2(plugin) {
|
|
plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.sort((a, b) => a.position - b.position);
|
|
plugin.settings.whitelistFolders.forEach((folder, index) => {
|
|
folder.position = index;
|
|
});
|
|
void plugin.saveSettings();
|
|
}
|
|
function addWhitelistFolderListItem(settings, containerEl, whitelistedFolder) {
|
|
const { plugin } = settings;
|
|
const setting = new import_obsidian13.Setting(containerEl);
|
|
setting.setClass("fn-exclude-folder-list");
|
|
const inputContainer = setting.settingEl.createDiv({
|
|
cls: "fn-whitelist-folder-input-container"
|
|
});
|
|
const SearchComponent = new import_obsidian13.Setting(inputContainer);
|
|
SearchComponent.addSearch((cb) => {
|
|
new FolderSuggest(cb.inputEl, plugin, true);
|
|
cb.containerEl.addClass("fn-exclude-folder-path");
|
|
cb.setPlaceholder("Folder path");
|
|
cb.setValue(whitelistedFolder.path);
|
|
cb.onChange((value) => {
|
|
if (value.startsWith("{regex}") || value.includes("*")) {
|
|
void deleteWhitelistedFolder(plugin, whitelistedFolder);
|
|
const pattern = new WhitelistedPattern(value, plugin.settings.whitelistFolders.length, void 0, plugin);
|
|
addWhitelistedFolder(plugin, pattern);
|
|
addWhitelistedPatternListItem(settings, containerEl, pattern);
|
|
setting.clear();
|
|
setting.settingEl.remove();
|
|
}
|
|
if (!plugin.app.vault.getAbstractFileByPath(value))
|
|
return;
|
|
whitelistedFolder.path = value;
|
|
updateWhitelistedFolder(plugin, whitelistedFolder, whitelistedFolder);
|
|
});
|
|
});
|
|
const buttonContainer = setting.settingEl.createDiv({ cls: "fn-whitelist-folder-buttons" });
|
|
new import_obsidian13.ButtonComponent(buttonContainer).setIcon("edit").setTooltip("Edit folder note").onClick(() => {
|
|
new WhitelistFolderSettings(plugin.app, plugin, whitelistedFolder).open();
|
|
});
|
|
new import_obsidian13.ButtonComponent(buttonContainer).setIcon("up-chevron-glyph").setTooltip("Move up").onClick(() => {
|
|
if (whitelistedFolder.position === 0) {
|
|
return;
|
|
}
|
|
whitelistedFolder.position -= 1;
|
|
updateWhitelistedFolder(plugin, whitelistedFolder, whitelistedFolder);
|
|
const oldWhitelistedFolder = plugin.settings.whitelistFolders.find((folder) => folder.position === whitelistedFolder.position);
|
|
if (oldWhitelistedFolder) {
|
|
oldWhitelistedFolder.position += 1;
|
|
if (oldWhitelistedFolder.type === "pattern") {
|
|
updateWhitelistedPattern(plugin, oldWhitelistedFolder, oldWhitelistedFolder);
|
|
} else {
|
|
updateWhitelistedFolder(plugin, oldWhitelistedFolder, oldWhitelistedFolder);
|
|
}
|
|
}
|
|
settings.display();
|
|
});
|
|
new import_obsidian13.ButtonComponent(buttonContainer).setIcon("down-chevron-glyph").setTooltip("Move down").onClick(() => {
|
|
if (whitelistedFolder.position === plugin.settings.whitelistFolders.length - 1) {
|
|
return;
|
|
}
|
|
whitelistedFolder.position += 1;
|
|
updateWhitelistedFolder(plugin, whitelistedFolder, whitelistedFolder);
|
|
const oldWhitelistedFolder = plugin.settings.whitelistFolders.find((folder) => folder.position === whitelistedFolder.position);
|
|
if (oldWhitelistedFolder) {
|
|
oldWhitelistedFolder.position -= 1;
|
|
if (oldWhitelistedFolder.type === "pattern") {
|
|
updateWhitelistedPattern(plugin, oldWhitelistedFolder, oldWhitelistedFolder);
|
|
} else {
|
|
updateWhitelistedFolder(plugin, oldWhitelistedFolder, oldWhitelistedFolder);
|
|
}
|
|
}
|
|
settings.display();
|
|
});
|
|
new import_obsidian13.ButtonComponent(buttonContainer).setIcon("trash-2").setTooltip("Delete excluded folder").onClick(() => {
|
|
void deleteWhitelistedFolder(plugin, whitelistedFolder);
|
|
setting.clear();
|
|
setting.settingEl.remove();
|
|
});
|
|
}
|
|
|
|
// src/ExcludeFolders/functions/folderFunctions.ts
|
|
function combineExcluded(plugin, path, includeDetached, pathOnly) {
|
|
const folderName = getFolderNameFromPathString(path);
|
|
const matchedPatterns = pathOnly ? [] : getExcludedFoldersByPattern(plugin, folderName);
|
|
const excludedByPath = getExcludedFoldersByPath(plugin, path);
|
|
let combined = [...matchedPatterns, ...excludedByPath];
|
|
if (!includeDetached)
|
|
combined = combined.filter((f) => !f.detached);
|
|
return combined;
|
|
}
|
|
function aggregateFlags(combinedExcludedFolders) {
|
|
if (combinedExcludedFolders.length === 0)
|
|
return void 0;
|
|
const result = {};
|
|
const propertiesToCopy = [
|
|
"disableAutoCreate",
|
|
"disableFolderNote",
|
|
"disableSync",
|
|
"enableCollapsing",
|
|
"excludeFromFolderOverview",
|
|
"detached",
|
|
"hideInSettings",
|
|
"id",
|
|
"showFolderNote"
|
|
];
|
|
for (const matchedFolder of combinedExcludedFolders) {
|
|
for (const property of propertiesToCopy) {
|
|
const value = matchedFolder[property];
|
|
if (value === true) {
|
|
result[property] = true;
|
|
} else if (!value) {
|
|
result[property] = false;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function applyWhitelistOverrides(excluded, whitelisted) {
|
|
const out = { ...excluded };
|
|
if (out.disableAutoCreate !== void 0) {
|
|
out.disableAutoCreate = !whitelisted.enableAutoCreate;
|
|
}
|
|
if (out.disableFolderNote !== void 0) {
|
|
out.disableFolderNote = !whitelisted.enableFolderNote;
|
|
}
|
|
if (out.disableSync !== void 0) {
|
|
out.disableSync = !whitelisted.enableSync;
|
|
}
|
|
out.enableCollapsing = !whitelisted.disableCollapsing;
|
|
if (out.excludeFromFolderOverview !== void 0) {
|
|
out.excludeFromFolderOverview = !whitelisted.showInFolderOverview;
|
|
}
|
|
out.showFolderNote = !whitelisted.hideInFileExplorer;
|
|
return out;
|
|
}
|
|
function defaultExcludedIfEmpty(value) {
|
|
if (value && Object.keys(value).length === 0) {
|
|
return {
|
|
type: "folder",
|
|
id: "",
|
|
path: "",
|
|
string: "",
|
|
subFolders: false,
|
|
disableSync: false,
|
|
disableAutoCreate: false,
|
|
disableFolderNote: false,
|
|
enableCollapsing: false,
|
|
position: 0,
|
|
excludeFromFolderOverview: false,
|
|
hideInSettings: false,
|
|
detached: false,
|
|
showFolderNote: false
|
|
};
|
|
}
|
|
return value;
|
|
}
|
|
function getExcludedFolder(plugin, path, includeDetached, pathOnly, ignoreWhitelist) {
|
|
const combined = combineExcluded(plugin, path, includeDetached, pathOnly);
|
|
let excluded = aggregateFlags(combined);
|
|
const whitelist = getWhitelistedFolder(plugin, path);
|
|
let skipWhitelist = ignoreWhitelist != null ? ignoreWhitelist : false;
|
|
if (excluded == null ? void 0 : excluded.detached)
|
|
skipWhitelist = true;
|
|
if (whitelist && excluded && !skipWhitelist) {
|
|
excluded = applyWhitelistOverrides(excluded, whitelist);
|
|
}
|
|
return defaultExcludedIfEmpty(excluded);
|
|
}
|
|
function getDetachedFolder(plugin, path) {
|
|
return plugin.settings.excludeFolders.find((f) => f.path === path && f.detached);
|
|
}
|
|
function getExcludedFoldersByPath(plugin, path) {
|
|
return plugin.settings.excludeFolders.filter((excludedFolder) => {
|
|
if (path.trim() === "" || !excludedFolder.path) {
|
|
return false;
|
|
}
|
|
if (excludedFolder.path === path) {
|
|
return true;
|
|
}
|
|
if (!excludedFolder.subFolders) {
|
|
return false;
|
|
}
|
|
const excludedFolderPath = excludedFolder.path.includes("/") ? excludedFolder.path : `${excludedFolder.path}/`;
|
|
let folderPath = getFolderPathFromString(path);
|
|
folderPath = folderPath.includes("/") ? folderPath : `${folderPath}/`;
|
|
if (folderPath.includes("/") || folderPath.includes("\\")) {
|
|
return folderPath.startsWith(excludedFolderPath) || folderPath === excludedFolderPath;
|
|
}
|
|
return folderPath === excludedFolderPath;
|
|
});
|
|
}
|
|
function addExcludedFolder(plugin, excludedFolder, reloadStyles = true) {
|
|
plugin.settings.excludeFolders.push(excludedFolder);
|
|
void plugin.saveSettings(reloadStyles);
|
|
}
|
|
async function deleteExcludedFolder(plugin, excludedFolder) {
|
|
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.id !== excludedFolder.id || folder.type === "pattern");
|
|
await plugin.saveSettings(true);
|
|
resyncArray(plugin);
|
|
}
|
|
function updateExcludedFolder(plugin, excludedFolder, newExcludeFolder) {
|
|
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.id !== excludedFolder.id);
|
|
addExcludedFolder(plugin, newExcludeFolder);
|
|
}
|
|
function resyncArray(plugin) {
|
|
plugin.settings.excludeFolders = plugin.settings.excludeFolders.sort((a, b) => a.position - b.position);
|
|
plugin.settings.excludeFolders.forEach((folder, index) => {
|
|
folder.position = index;
|
|
});
|
|
void plugin.saveSettings();
|
|
}
|
|
function addExcludeFolderListItem(settings, containerEl, excludedFolder) {
|
|
const { plugin } = settings;
|
|
const setting = new import_obsidian14.Setting(containerEl);
|
|
setting.setClass("fn-exclude-folder-list");
|
|
setting.addSearch((cb) => {
|
|
new FolderSuggest(cb.inputEl, plugin, false);
|
|
cb.containerEl.addClass("fn-exclude-folder-path");
|
|
cb.setPlaceholder("Folder path");
|
|
cb.setValue(excludedFolder.path || "");
|
|
cb.onChange((value) => {
|
|
if (value.startsWith("{regex}") || value.includes("*")) {
|
|
deleteExcludedFolder(plugin, excludedFolder);
|
|
const pattern = new ExcludePattern(value, plugin.settings.excludeFolders.length, void 0, plugin);
|
|
addExcludedFolder(plugin, pattern);
|
|
addExcludePatternListItem(settings, containerEl, pattern);
|
|
setting.clear();
|
|
setting.settingEl.remove();
|
|
}
|
|
if (!plugin.app.vault.getAbstractFileByPath(value))
|
|
return;
|
|
excludedFolder.path = value;
|
|
updateExcludedFolder(plugin, excludedFolder, excludedFolder);
|
|
});
|
|
});
|
|
setting.addButton((cb) => {
|
|
cb.setIcon("edit");
|
|
cb.setTooltip("Edit folder note");
|
|
cb.onClick(() => {
|
|
new ExcludedFolderSettings(plugin.app, plugin, excludedFolder).open();
|
|
});
|
|
});
|
|
if (import_obsidian14.Platform.isDesktop || import_obsidian14.Platform.isTablet) {
|
|
setting.addButton((cb) => {
|
|
cb.setIcon("up-chevron-glyph");
|
|
cb.setTooltip("Move up");
|
|
cb.onClick(() => {
|
|
if (excludedFolder.position === 0) {
|
|
return;
|
|
}
|
|
excludedFolder.position -= 1;
|
|
updateExcludedFolder(plugin, excludedFolder, excludedFolder);
|
|
const oldExcludedFolder = plugin.settings.excludeFolders.find((folder) => folder.position === excludedFolder.position);
|
|
if (oldExcludedFolder) {
|
|
oldExcludedFolder.position += 1;
|
|
if (oldExcludedFolder.type === "pattern") {
|
|
updatePattern(plugin, oldExcludedFolder, oldExcludedFolder);
|
|
} else {
|
|
updateExcludedFolder(plugin, oldExcludedFolder, oldExcludedFolder);
|
|
}
|
|
}
|
|
settings.display();
|
|
});
|
|
});
|
|
setting.addButton((cb) => {
|
|
cb.setIcon("down-chevron-glyph");
|
|
cb.setTooltip("Move down");
|
|
cb.onClick(() => {
|
|
if (excludedFolder.position === plugin.settings.excludeFolders.length - 1) {
|
|
return;
|
|
}
|
|
excludedFolder.position += 1;
|
|
updateExcludedFolder(plugin, excludedFolder, excludedFolder);
|
|
const oldExcludedFolder = plugin.settings.excludeFolders.find((folder) => folder.position === excludedFolder.position);
|
|
if (oldExcludedFolder) {
|
|
oldExcludedFolder.position -= 1;
|
|
if (oldExcludedFolder.type === "pattern") {
|
|
updatePattern(plugin, oldExcludedFolder, oldExcludedFolder);
|
|
} else {
|
|
updateExcludedFolder(plugin, oldExcludedFolder, oldExcludedFolder);
|
|
}
|
|
}
|
|
settings.display();
|
|
});
|
|
});
|
|
}
|
|
setting.addButton((cb) => {
|
|
cb.setIcon("trash-2");
|
|
cb.setTooltip("Delete excluded folder");
|
|
cb.onClick(() => {
|
|
deleteExcludedFolder(plugin, excludedFolder);
|
|
setting.clear();
|
|
setting.settingEl.remove();
|
|
});
|
|
});
|
|
}
|
|
|
|
// src/functions/excalidraw.ts
|
|
async function openExcalidrawView(app, file) {
|
|
const { excalidraw, excalidrawEnabled } = await getExcalidrawPlugin(app);
|
|
if (excalidrawEnabled && excalidraw) {
|
|
excalidraw.openDrawing(file);
|
|
}
|
|
}
|
|
async function getDefaultTemplate(app) {
|
|
const { excalidraw, excalidrawEnabled } = await getExcalidrawPlugin(app);
|
|
if (excalidrawEnabled && excalidraw) {
|
|
return excalidraw.getBlankDrawing();
|
|
}
|
|
return "";
|
|
}
|
|
async function getExcalidrawPlugin(app) {
|
|
const { plugins: pluginManager } = app;
|
|
const excalidraw = pluginManager.plugins["obsidian-excalidraw-plugin"];
|
|
const excalidrawEnabled = pluginManager.enabledPlugins.has("obsidian-excalidraw-plugin");
|
|
return {
|
|
excalidraw: excalidraw != null ? excalidraw : null,
|
|
excalidrawEnabled
|
|
};
|
|
}
|
|
|
|
// src/modals/AskForExtension.ts
|
|
var import_obsidian15 = require("obsidian");
|
|
var AskForExtensionModal = class extends import_obsidian15.FuzzySuggestModal {
|
|
constructor(plugin, folderPath, openFile, extension, useModal, existingNote) {
|
|
super(plugin.app);
|
|
this.plugin = plugin;
|
|
this.folderPath = folderPath;
|
|
this.extension = extension;
|
|
this.openFile = openFile;
|
|
this.useModal = useModal;
|
|
this.existingNote = existingNote;
|
|
plugin.askModalCurrentlyOpen = true;
|
|
}
|
|
getItems() {
|
|
return this.plugin.settings.supportedFileTypes.filter((item) => item.toLowerCase() !== ".ask");
|
|
}
|
|
getItemText(item) {
|
|
return item;
|
|
}
|
|
onChooseItem(item, _evt) {
|
|
this.plugin.askModalCurrentlyOpen = false;
|
|
this.extension = "." + item;
|
|
void createFolderNote(this.plugin, this.folderPath, this.openFile, this.extension, this.useModal, this.existingNote);
|
|
this.close();
|
|
}
|
|
};
|
|
|
|
// src/functions/folderNoteFunctions.ts
|
|
async function createFolderNote(plugin, folderPath, openFile, extension, displayModal, preexistingNote) {
|
|
var _a;
|
|
let {
|
|
leaf,
|
|
fileName,
|
|
folderNote,
|
|
folderNoteType,
|
|
detachedFolder,
|
|
path
|
|
} = getArgs(plugin, folderPath, extension, preexistingNote);
|
|
if (folderNoteType === ".excalidraw") {
|
|
folderNoteType = ".md";
|
|
extension = ".excalidraw";
|
|
} else if (folderNoteType === ".ask") {
|
|
if (plugin.askModalCurrentlyOpen)
|
|
return;
|
|
return new AskForExtensionModal(plugin, folderPath, openFile, folderNoteType, displayModal, preexistingNote).open();
|
|
}
|
|
if (plugin.settings.storageLocation === "parentFolder") {
|
|
const parentFolderPath = getFolderPathFromString(folderPath);
|
|
if (parentFolderPath.trim() === "") {
|
|
path = `${fileName}${folderNoteType}`;
|
|
} else {
|
|
path = `${parentFolderPath}/${fileName}${folderNoteType}`;
|
|
}
|
|
} else if (plugin.settings.storageLocation === "vaultFolder") {
|
|
path = `${fileName}${folderNoteType}`;
|
|
} else {
|
|
path = `${folderPath}/${fileName}${folderNoteType}`;
|
|
}
|
|
if (detachedFolder && (folderNote == null ? void 0 : folderNote.extension) !== extension && folderNote) {
|
|
await handleTurnNoteIntoFolderNote(plugin, folderNote, detachedFolder, folderPath, fileName);
|
|
}
|
|
if (!extension) {
|
|
extension = folderNoteType;
|
|
}
|
|
if (!folderNote) {
|
|
folderNote = await handleCreateFolderNote(plugin, folderNoteType, openFile, leaf, folderNote, path, extension);
|
|
} else {
|
|
await plugin.app.fileManager.renameFile(folderNote, path);
|
|
}
|
|
if (openFile) {
|
|
if (((_a = plugin.app.workspace.getActiveFile()) == null ? void 0 : _a.path) === path) {
|
|
removeActiveFolder(plugin);
|
|
const folder2 = getFolder(plugin, folderNote);
|
|
if (!folder2) {
|
|
return;
|
|
}
|
|
setActiveFolder(folder2.path, plugin);
|
|
}
|
|
await leaf.openFile(folderNote);
|
|
if (plugin.settings.folderNoteType === ".excalidraw" || extension === ".excalidraw") {
|
|
openExcalidrawView(plugin.app, folderNote);
|
|
}
|
|
}
|
|
const matchingExtension = (extension == null ? void 0 : extension.split(".").pop()) === plugin.settings.templatePath.split(".").pop();
|
|
if (folderNote && matchingExtension && plugin.settings.folderNoteType !== ".excalidraw") {
|
|
applyTemplate(plugin, folderNote, leaf, plugin.settings.templatePath);
|
|
}
|
|
const folder = plugin.app.vault.getAbstractFileByPath(folderPath);
|
|
if (!(folder instanceof import_obsidian16.TFolder))
|
|
return;
|
|
addCSSClassToFileExplorerEl(path, "is-folder-note", false, plugin, true);
|
|
addCSSClassToFileExplorerEl(folder.path, "has-folder-note", false, plugin);
|
|
}
|
|
function getArgs(plugin, folderPath, extension, preexistingNote) {
|
|
const leaf = plugin.app.workspace.getLeaf(false);
|
|
const folderName = getFolderNameFromPathString(folderPath);
|
|
const fileName = plugin.settings.folderNoteName.replace("{{folder_name}}", folderName);
|
|
let folderNote = getFolderNote(plugin, folderPath);
|
|
if (preexistingNote) {
|
|
folderNote = preexistingNote;
|
|
}
|
|
let folderNoteType = extension != null ? extension : plugin.settings.folderNoteType;
|
|
const detachedFolder = getDetachedFolder(plugin, folderPath);
|
|
let path = "";
|
|
return {
|
|
leaf,
|
|
fileName,
|
|
folderNote,
|
|
folderNoteType,
|
|
detachedFolder,
|
|
path
|
|
};
|
|
}
|
|
async function handleCreateFolderNote(plugin, folderNoteType, openFile, leaf, folderNote, path, extension) {
|
|
let content = "";
|
|
if (extension !== ".md" && extension) {
|
|
if (plugin.settings.templatePath && folderNoteType.split(".").pop() === plugin.settings.templatePath.split(".").pop()) {
|
|
const templateFile = plugin.app.vault.getAbstractFileByPath(plugin.settings.templatePath);
|
|
if (templateFile instanceof import_obsidian16.TFile) {
|
|
if (["md", "canvas", "txt"].includes(templateFile.extension)) {
|
|
content = await plugin.app.vault.read(templateFile);
|
|
if (extension === ".excalidraw" && !content.includes("==\u26A0 Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this activeDocument. \u26A0==")) {
|
|
content = await getDefaultTemplate(plugin.app);
|
|
}
|
|
} else {
|
|
plugin.app.vault.readBinary(templateFile).then(async (data) => {
|
|
folderNote = await plugin.app.vault.createBinary(path, data);
|
|
if (openFile) {
|
|
await leaf.openFile(folderNote);
|
|
}
|
|
return folderNote;
|
|
});
|
|
}
|
|
}
|
|
} else if (plugin.settings.folderNoteType === ".excalidraw" || extension === ".excalidraw") {
|
|
content = await getDefaultTemplate(plugin.app);
|
|
} else if (plugin.settings.folderNoteType === ".canvas") {
|
|
content = "{}";
|
|
}
|
|
}
|
|
folderNote = await plugin.app.vault.create(path, content);
|
|
return folderNote;
|
|
}
|
|
async function handleTurnNoteIntoFolderNote(plugin, folderNote, detachedFolder, folderPath, fileName) {
|
|
deleteExcludedFolder(plugin, detachedFolder);
|
|
removeCSSClassFromFileExplorerEL(folderNote == null ? void 0 : folderNote.path, "is-folder-note", false, plugin);
|
|
const folder = plugin.app.vault.getAbstractFileByPath(folderPath);
|
|
if (!(folder instanceof import_obsidian16.TFolder))
|
|
return;
|
|
if (!folderNote || folderNote.basename !== fileName)
|
|
return;
|
|
let count = 1;
|
|
const baseName = removeExtension(folderNote.path);
|
|
const ext = folderNote.path.split(".").pop();
|
|
let newName = `${baseName} (${count}).${ext}`;
|
|
const MAX_FOLDER_NOTE_RENAME_ATTEMPTS = 100;
|
|
while (count < MAX_FOLDER_NOTE_RENAME_ATTEMPTS && plugin.app.vault.getAbstractFileByPath(newName)) {
|
|
count++;
|
|
newName = `${baseName} (${count}).${ext}`;
|
|
}
|
|
const [
|
|
excludedFolder,
|
|
excludedFolderExisted,
|
|
disabledSync
|
|
] = await tempDisableSync(plugin, folder);
|
|
await plugin.app.fileManager.renameFile(folderNote, newName).then(() => {
|
|
if (!excludedFolder)
|
|
return;
|
|
if (!excludedFolderExisted) {
|
|
deleteExcludedFolder(plugin, excludedFolder);
|
|
} else if (!disabledSync) {
|
|
excludedFolder.disableSync = false;
|
|
updateExcludedFolder(plugin, excludedFolder, excludedFolder);
|
|
}
|
|
});
|
|
}
|
|
async function turnIntoFolderNote(plugin, file, folder, folderNote, skipConfirmation) {
|
|
var _a;
|
|
const { extension } = file;
|
|
const detachedExcludedFolder = getDetachedFolder(plugin, folder.path);
|
|
if (folderNote) {
|
|
if (plugin.settings.showRenameConfirmation && !skipConfirmation && !detachedExcludedFolder) {
|
|
return new ExistingFolderNoteModal(plugin.app, plugin, file, folder, folderNote).open();
|
|
}
|
|
removeCSSClassFromFileExplorerEL(folderNote.path, "is-folder-note", false, plugin);
|
|
const [
|
|
excludedFolder,
|
|
excludedFolderExisted,
|
|
disabledSync
|
|
] = await tempDisableSync(plugin, folder);
|
|
const CTIME_SLICE_START = 10;
|
|
const RANDOM_SUFFIX_MAX = 1e3;
|
|
const randomSuffix = Math.floor(Math.random() * RANDOM_SUFFIX_MAX);
|
|
const ctimeSuffix = file.stat.ctime.toString().slice(CTIME_SLICE_START);
|
|
const newPath = `${folder.path}/${folder.name} (${ctimeSuffix}${randomSuffix}).${extension}`;
|
|
plugin.app.fileManager.renameFile(folderNote, newPath).then(() => {
|
|
if (!excludedFolder)
|
|
return;
|
|
if (!excludedFolderExisted) {
|
|
deleteExcludedFolder(plugin, excludedFolder);
|
|
} else if (!disabledSync) {
|
|
excludedFolder.disableSync = false;
|
|
updateExcludedFolder(plugin, excludedFolder, excludedFolder);
|
|
}
|
|
});
|
|
}
|
|
const folderName = folder.name;
|
|
const fileName = plugin.settings.folderNoteName.replace("{{folder_name}}", folderName);
|
|
let path = `${folder.path}/${fileName}.${extension}`;
|
|
if (plugin.settings.storageLocation === "parentFolder") {
|
|
const parentFolderPath = (_a = folder.parent) == null ? void 0 : _a.path;
|
|
if (!parentFolderPath)
|
|
return;
|
|
if (parentFolderPath.trim() === "") {
|
|
path = `${fileName}.${extension}`;
|
|
} else {
|
|
path = `${parentFolderPath}/${fileName}.${extension}`;
|
|
}
|
|
}
|
|
if (detachedExcludedFolder) {
|
|
void deleteExcludedFolder(plugin, detachedExcludedFolder);
|
|
}
|
|
await plugin.app.fileManager.renameFile(file, path);
|
|
void addCSSClassToFileExplorerEl(path, "is-folder-note", false, plugin, true);
|
|
void addCSSClassToFileExplorerEl(folder.path, "has-folder-note", false, plugin);
|
|
removeActiveFolder(plugin);
|
|
setActiveFolder(folder.path, plugin);
|
|
}
|
|
async function tempDisableSync(plugin, folder) {
|
|
let excludedFolder = getExcludedFolder(plugin, folder.path, false);
|
|
let excludedFolderExisted = true;
|
|
let disabledSync = false;
|
|
if (!excludedFolder) {
|
|
excludedFolderExisted = false;
|
|
excludedFolder = new ExcludedFolder(folder.path, plugin.settings.excludeFolders.length, void 0, plugin);
|
|
excludedFolder.disableSync = true;
|
|
addExcludedFolder(plugin, excludedFolder);
|
|
} else if (!excludedFolder.disableSync) {
|
|
disabledSync = false;
|
|
excludedFolder.disableSync = true;
|
|
updateExcludedFolder(plugin, excludedFolder, excludedFolder);
|
|
}
|
|
return [excludedFolder, excludedFolderExisted, disabledSync];
|
|
}
|
|
async function openFolderNote(plugin, file, evt) {
|
|
var _a;
|
|
const { path } = file;
|
|
const focusExistingTab = plugin.settings.focusExistingTab && plugin.settings.openInNewTab;
|
|
const activeFilePath = (_a = plugin.app.workspace.getActiveFile()) == null ? void 0 : _a.path;
|
|
if (activeFilePath === path && !(import_obsidian16.Keymap.isModEvent(evt) === "tab")) {
|
|
return;
|
|
}
|
|
let foundLeaf = null;
|
|
if (focusExistingTab && file instanceof import_obsidian16.TFile) {
|
|
plugin.app.workspace.iterateAllLeaves((leaf) => {
|
|
var _a2;
|
|
if (leaf.getViewState().type === "markdown" && ((_a2 = leaf.view.file) == null ? void 0 : _a2.path) === path) {
|
|
foundLeaf = leaf;
|
|
}
|
|
});
|
|
}
|
|
if (foundLeaf) {
|
|
plugin.app.workspace.setActiveLeaf(foundLeaf, { focus: true });
|
|
} else {
|
|
const shouldOpenInNewTab = import_obsidian16.Keymap.isModEvent(evt) || plugin.settings.openInNewTab;
|
|
const leaf = plugin.app.workspace.getLeaf(shouldOpenInNewTab);
|
|
if (file instanceof import_obsidian16.TFile) {
|
|
await leaf.openFile(file);
|
|
}
|
|
}
|
|
}
|
|
async function deleteFolderNote(plugin, file, displayModal) {
|
|
if (plugin.settings.showDeleteConfirmation && displayModal) {
|
|
return new DeleteConfirmationModal(plugin.app, plugin, file).open();
|
|
}
|
|
const folder = getFolder(plugin, file);
|
|
if (!folder)
|
|
return;
|
|
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((excludedFolder) => excludedFolder.path !== folder.path || !excludedFolder.showFolderNote);
|
|
plugin.saveSettings(false);
|
|
removeCSSClassFromFileExplorerEL(folder.path, "has-folder-note", false, plugin);
|
|
switch (plugin.settings.deleteFilesAction) {
|
|
case "trash":
|
|
await plugin.app.vault.trash(file, true);
|
|
break;
|
|
case "obsidianTrash":
|
|
await plugin.app.vault.trash(file, false);
|
|
break;
|
|
case "delete":
|
|
await plugin.app.vault.delete(file);
|
|
break;
|
|
}
|
|
}
|
|
function extractFolderName(template, changedFileName) {
|
|
const [prefix, suffix] = template.split("{{folder_name}}");
|
|
if (prefix.trim() === "" && suffix.trim() === "") {
|
|
return changedFileName;
|
|
}
|
|
if (!changedFileName.startsWith(prefix) || !changedFileName.endsWith(suffix)) {
|
|
return null;
|
|
}
|
|
if (changedFileName.startsWith(prefix) && prefix.trim() !== "") {
|
|
return changedFileName.slice(prefix.length).replace(suffix, "");
|
|
} else if (changedFileName.endsWith(suffix) && suffix.trim() !== "") {
|
|
return changedFileName.slice(0, -suffix.length);
|
|
}
|
|
return null;
|
|
}
|
|
function findFolderNoteFile(plugin, path, primaryType) {
|
|
let folderNote = plugin.app.vault.getAbstractFileByPath(path + primaryType);
|
|
if (folderNote instanceof import_obsidian16.TFile && plugin.settings.supportedFileTypes.includes(primaryType.replace(".", ""))) {
|
|
return folderNote;
|
|
}
|
|
const supportedFileTypes = plugin.settings.supportedFileTypes.filter((type) => type !== primaryType.replace(".", ""));
|
|
for (let type of supportedFileTypes) {
|
|
if (type === "excalidraw" || type === ".excalidraw") {
|
|
type = ".md";
|
|
}
|
|
if (!type.startsWith(".")) {
|
|
type = "." + type;
|
|
}
|
|
folderNote = plugin.app.vault.getAbstractFileByPath(path + type);
|
|
if (folderNote instanceof import_obsidian16.TFile) {
|
|
return folderNote;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
function getFolderNote(plugin, folderPath, storageLocation, file, oldFolderNoteName) {
|
|
const folder = getFolderInfo(folderPath);
|
|
if (!folder)
|
|
return null;
|
|
let fileName = resolveFileName(plugin, folder, file, oldFolderNoteName);
|
|
if (!fileName)
|
|
return null;
|
|
adjustFolderPathForStorage(folder, folderPath, plugin, storageLocation);
|
|
const path = buildFullPath(folder, fileName);
|
|
const primaryType = normalizeFolderNoteType(plugin.settings.folderNoteType);
|
|
return findFolderNoteFile(plugin, path, primaryType);
|
|
}
|
|
function detachFolderNote(plugin, file) {
|
|
const folder = getFolder(plugin, file);
|
|
if (!folder)
|
|
return;
|
|
const excludedFolder = new ExcludedFolder(folder.path, plugin.settings.excludeFolders.length, void 0, plugin);
|
|
excludedFolder.showFolderNote = true;
|
|
excludedFolder.hideInSettings = true;
|
|
excludedFolder.disableFolderNote = true;
|
|
excludedFolder.disableSync = true;
|
|
excludedFolder.subFolders = false;
|
|
excludedFolder.excludeFromFolderOverview = false;
|
|
excludedFolder.detached = true;
|
|
excludedFolder.detachedFilePath = file.path;
|
|
addExcludedFolder(plugin, excludedFolder);
|
|
void updateCSSClassesForFolderNote(file.path, plugin);
|
|
}
|
|
function getFolder(plugin, file, storageLocation) {
|
|
var _a, _b;
|
|
if (!file)
|
|
return null;
|
|
let folderName = extractFolderName(plugin.settings.folderNoteName, file.basename);
|
|
if (plugin.settings.folderNoteName === file.basename && plugin.settings.storageLocation === "insideFolder") {
|
|
folderName = (_b = (_a = file.parent) == null ? void 0 : _a.name) != null ? _b : "";
|
|
}
|
|
if (!folderName)
|
|
return null;
|
|
let folderPath = getFolderPathFromString(file.path);
|
|
let folder = null;
|
|
if ((plugin.settings.storageLocation === "parentFolder" || storageLocation === "parentFolder") && storageLocation !== "insideFolder") {
|
|
if (folderPath.trim() === "" || folderPath === "/") {
|
|
folderPath = folderName;
|
|
} else {
|
|
folderPath = `${folderPath}/${folderName}`;
|
|
}
|
|
folder = plugin.app.vault.getAbstractFileByPath(folderPath);
|
|
} else {
|
|
folder = plugin.app.vault.getAbstractFileByPath(folderPath);
|
|
}
|
|
if (!folder) {
|
|
return null;
|
|
}
|
|
return folder;
|
|
}
|
|
function getFolderNoteFolder(plugin, folderNote, fileName) {
|
|
if (!folderNote)
|
|
return null;
|
|
let filePath = "";
|
|
if (typeof folderNote === "string") {
|
|
filePath = folderNote;
|
|
} else {
|
|
fileName = folderNote.basename;
|
|
filePath = folderNote.path;
|
|
}
|
|
const folderName = extractFolderName(plugin.settings.folderNoteName, fileName);
|
|
if (!plugin.settings.folderNoteName.includes("{{folder_name}}") && plugin.settings.storageLocation === "insideFolder") {
|
|
if (folderNote instanceof import_obsidian16.TFile) {
|
|
return folderNote.parent;
|
|
}
|
|
const file = plugin.app.vault.getAbstractFileByPath(filePath);
|
|
return file instanceof import_obsidian16.TFile ? file.parent : null;
|
|
}
|
|
if (!folderName)
|
|
return null;
|
|
let folderPath = getFolderPathFromString(filePath);
|
|
if (plugin.settings.storageLocation === "parentFolder") {
|
|
if (folderPath.trim() === "") {
|
|
folderPath = folderName;
|
|
} else {
|
|
folderPath = `${folderPath}/${folderName}`;
|
|
}
|
|
} else {
|
|
folderPath = getFolderPathFromString(filePath);
|
|
}
|
|
const folder = plugin.app.vault.getAbstractFileByPath(folderPath);
|
|
if (!folder) {
|
|
return null;
|
|
}
|
|
return folder;
|
|
}
|
|
function getFolderInfo(folderPath) {
|
|
if (!folderPath)
|
|
return null;
|
|
return {
|
|
path: folderPath,
|
|
name: getFolderNameFromPathString(folderPath)
|
|
};
|
|
}
|
|
function resolveFileName(plugin, folder, file, oldFolderNoteName) {
|
|
const templateName = oldFolderNoteName != null ? oldFolderNoteName : plugin.settings.folderNoteName;
|
|
if (!templateName)
|
|
return null;
|
|
const nameSource = file ? file.basename : folder.name;
|
|
return templateName.replace("{{folder_name}}", nameSource);
|
|
}
|
|
function adjustFolderPathForStorage(folder, folderPath, plugin, storageLocation) {
|
|
if ((plugin.settings.storageLocation === "parentFolder" || storageLocation === "parentFolder") && storageLocation !== "insideFolder") {
|
|
folder.path = getFolderPathFromString(folderPath);
|
|
}
|
|
}
|
|
function buildFullPath(folder, fileName) {
|
|
return folder.path === "/" ? fileName : `${folder.path}/${fileName}`;
|
|
}
|
|
function normalizeFolderNoteType(type) {
|
|
return type === ".excalidraw" ? ".md" : type;
|
|
}
|
|
|
|
// src/settings/GeneralSettings.ts
|
|
var import_obsidian23 = require("obsidian");
|
|
|
|
// src/events/EventEmitter.ts
|
|
var CustomEventEmitter = class {
|
|
constructor() {
|
|
this.events = {};
|
|
}
|
|
on(event, listener) {
|
|
if (!this.events[event]) {
|
|
this.events[event] = [];
|
|
}
|
|
this.events[event].push(listener);
|
|
}
|
|
off(event, listener) {
|
|
if (!this.events[event])
|
|
return;
|
|
this.events[event] = this.events[event].filter((l) => l !== listener);
|
|
}
|
|
emit(event, data) {
|
|
if (!this.events[event])
|
|
return;
|
|
this.events[event].forEach((listener) => listener(data));
|
|
}
|
|
};
|
|
|
|
// src/functions/ListComponent.ts
|
|
var ListComponent = class {
|
|
constructor(containerEl, values = [], defaultValues = []) {
|
|
this.emitter = new CustomEventEmitter();
|
|
this.containerEl = containerEl;
|
|
this.controlEl = containerEl.querySelector(".setting-item-control") || containerEl;
|
|
this.listEl = this.controlEl.createDiv("setting-command-hotkeys");
|
|
this.addResetButton();
|
|
this.setValues(values);
|
|
this.defaultValues = defaultValues;
|
|
}
|
|
on(event, listener) {
|
|
this.emitter.on(event, listener);
|
|
}
|
|
off(event, listener) {
|
|
this.emitter.off(event, listener);
|
|
}
|
|
emit(event, data) {
|
|
this.emitter.emit(event, data);
|
|
}
|
|
setValues(values) {
|
|
this.removeElements();
|
|
this.values = values;
|
|
if (values.length !== 0) {
|
|
values.forEach((value) => {
|
|
this.addElement(value);
|
|
});
|
|
}
|
|
this.emit("update", this.values);
|
|
}
|
|
removeElements() {
|
|
this.listEl.empty();
|
|
}
|
|
addElement(value) {
|
|
this.listEl.createSpan("setting-hotkey", (span) => {
|
|
if (value.toLocaleLowerCase() === "md") {
|
|
const markdown = "markdown";
|
|
span.innerText = markdown;
|
|
} else {
|
|
span.innerText = value;
|
|
}
|
|
span.setAttribute("extension", value);
|
|
const removeSpan = span.createEl("span", { cls: "ofn-list-item-remove setting-hotkey-icon" });
|
|
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
|
|
const svgElement = removeSpan.createEl("span", { cls: "ofn-list-item-remove-icon" });
|
|
const parser = new DOMParser();
|
|
const svgDoc = parser.parseFromString(svg, "image/svg+xml");
|
|
const svgNode = svgDoc.documentElement;
|
|
if (svgNode) {
|
|
svgElement.appendChild(activeDocument.importNode(svgNode, true));
|
|
}
|
|
removeSpan.onClickEvent(() => {
|
|
this.removeValue(value);
|
|
span.remove();
|
|
});
|
|
});
|
|
}
|
|
async addValue(value) {
|
|
this.values.push(value);
|
|
this.addElement(value);
|
|
this.emit("add", value);
|
|
this.emit("update", this.values);
|
|
}
|
|
addResetButton() {
|
|
const resetButton = this.controlEl.createEl("span", { cls: "clickable-icon setting-restore-hotkey-button" });
|
|
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-rotate-ccw"><path d="M3 2v6h6"></path><path d="M3 13a9 9 0 1 0 3-7.7L3 8"></path></svg>';
|
|
const svgElement = resetButton.createEl("span", { cls: "ofn-list-item-remove-icon" });
|
|
const parser = new DOMParser();
|
|
const svgDoc = parser.parseFromString(svg, "image/svg+xml");
|
|
const svgNode = svgDoc.documentElement;
|
|
if (svgNode) {
|
|
svgElement.appendChild(activeDocument.importNode(svgNode, true));
|
|
}
|
|
resetButton.onClickEvent(() => {
|
|
this.setValues(this.defaultValues);
|
|
});
|
|
return this;
|
|
}
|
|
removeValue(value) {
|
|
this.values = this.values.filter((v) => v !== value);
|
|
this.listEl.find(`[extension='${value}']`).remove();
|
|
this.emit("remove", value);
|
|
this.emit("update", this.values);
|
|
}
|
|
};
|
|
|
|
// src/modals/AddSupportedFileType.ts
|
|
var import_obsidian17 = require("obsidian");
|
|
var AddSupportedFileModal = class extends import_obsidian17.Modal {
|
|
constructor(app, plugin, settingsTab, list) {
|
|
super(app);
|
|
this.plugin = plugin;
|
|
this.app = app;
|
|
this.name = "";
|
|
this.list = list;
|
|
this.settingsTab = settingsTab;
|
|
}
|
|
onOpen() {
|
|
const { contentEl } = this;
|
|
contentEl.addEventListener("keydown", (e) => {
|
|
if (e.key === "Enter") {
|
|
this.close();
|
|
}
|
|
});
|
|
contentEl.createEl("h2", { text: "Extension name" });
|
|
new import_obsidian17.Setting(contentEl).setName('Enter the name of the extension (only the short form, e.g. "md")').addText((text) => text.setValue("").onChange(async (value) => {
|
|
if (value.trim() !== "") {
|
|
this.name = value.trim();
|
|
}
|
|
}));
|
|
}
|
|
onClose() {
|
|
if (this.name.toLocaleLowerCase() === "markdown") {
|
|
this.name = "md";
|
|
}
|
|
const { contentEl } = this;
|
|
if (this.name === "") {
|
|
contentEl.empty();
|
|
this.settingsTab.display();
|
|
} else if (this.plugin.settings.supportedFileTypes.includes(this.name.toLowerCase())) {
|
|
new import_obsidian17.Notice("This extension is already supported");
|
|
return;
|
|
} else {
|
|
void (async () => {
|
|
await this.list.addValue(this.name.toLowerCase());
|
|
this.settingsTab.display();
|
|
await this.plugin.saveSettings();
|
|
contentEl.empty();
|
|
})();
|
|
}
|
|
}
|
|
};
|
|
|
|
// src/events/FrontMatterTitle.ts
|
|
var import_front_matter_plugin_api_provider = __toESM(require_lib());
|
|
var import_obsidian18 = require("obsidian");
|
|
var FrontMatterTitlePluginHandler = class {
|
|
constructor(plugin) {
|
|
this.api = null;
|
|
this.deffer = null;
|
|
this.modifiedFolders = /* @__PURE__ */ new Map();
|
|
this.eventRef = null;
|
|
this.dispatcher = null;
|
|
this.plugin = plugin;
|
|
this.app = plugin.app;
|
|
(async () => {
|
|
var _a;
|
|
this.deffer = (0, import_front_matter_plugin_api_provider.getDefer)(this.app);
|
|
if (this.deffer.isPluginReady()) {
|
|
this.api = this.deffer.getApi();
|
|
} else {
|
|
await this.deffer.awaitPlugin();
|
|
this.api = this.deffer.getApi();
|
|
if (!this.deffer.isFeaturesReady()) {
|
|
await this.deffer.awaitFeatures();
|
|
}
|
|
}
|
|
if (plugin.settings.frontMatterTitle.enabled) {
|
|
const dispatcher = (_a = this.api) == null ? void 0 : _a.getEventDispatcher();
|
|
if (dispatcher) {
|
|
this.dispatcher = dispatcher;
|
|
}
|
|
const event = {
|
|
name: "manager:update",
|
|
cb: (data) => {
|
|
this.fmptUpdateFileName(data, true);
|
|
}
|
|
};
|
|
const ref = dispatcher == null ? void 0 : dispatcher.addListener(event);
|
|
if (ref) {
|
|
this.eventRef = ref;
|
|
}
|
|
plugin.updateAllBreadcrumbs();
|
|
}
|
|
})();
|
|
}
|
|
deleteEvent() {
|
|
if (this.eventRef && this.dispatcher) {
|
|
this.dispatcher.removeListener(this.eventRef);
|
|
}
|
|
}
|
|
async fmptUpdateFileName(data, isEvent) {
|
|
var _a, _b, _c;
|
|
const hasNestedData = "data" in data;
|
|
const actualData = hasNestedData ? data.data : data;
|
|
const file = this.app.vault.getAbstractFileByPath(actualData.path);
|
|
if (!(file instanceof import_obsidian18.TFile)) {
|
|
return;
|
|
}
|
|
const resolver = (_b = (_a = this.api) == null ? void 0 : _a.getResolverFactory()) == null ? void 0 : _b.createResolver("#feature-id#");
|
|
const newName = resolver == null ? void 0 : resolver.resolve((_c = file == null ? void 0 : file.path) != null ? _c : "");
|
|
const folder = getFolder(this.plugin, file);
|
|
if (!(folder instanceof import_obsidian18.TFolder)) {
|
|
return;
|
|
}
|
|
const folderNote = getFolderNote(this.plugin, folder.path);
|
|
if (!folderNote) {
|
|
return;
|
|
}
|
|
if (folderNote !== file) {
|
|
return;
|
|
}
|
|
if (!actualData.pathOnly) {
|
|
this.plugin.changeFolderNameInExplorer(folder, newName);
|
|
}
|
|
const { breadcrumb } = actualData;
|
|
if (breadcrumb) {
|
|
this.plugin.changeFolderNameInPath(folder, newName, breadcrumb);
|
|
}
|
|
if (isEvent) {
|
|
this.plugin.updateAllBreadcrumbs();
|
|
}
|
|
if (newName) {
|
|
folder.newName = newName;
|
|
this.modifiedFolders.set(folder.path, folder);
|
|
} else {
|
|
folder.newName = null;
|
|
this.modifiedFolders.delete(folder.path);
|
|
}
|
|
}
|
|
async fmptUpdateFolderName(data, _replacePath) {
|
|
var _a, _b, _c;
|
|
const hasNestedData = "data" in data;
|
|
const actualData = hasNestedData ? data.data : data;
|
|
const folder = this.app.vault.getAbstractFileByPath(actualData.path);
|
|
if (!(folder instanceof import_obsidian18.TFolder)) {
|
|
return;
|
|
}
|
|
const folderNote = getFolderNote(this.plugin, folder.path);
|
|
if (!folderNote) {
|
|
return;
|
|
}
|
|
const resolver = (_b = (_a = this.api) == null ? void 0 : _a.getResolverFactory()) == null ? void 0 : _b.createResolver("#feature-id#");
|
|
const newName = resolver == null ? void 0 : resolver.resolve((_c = folderNote == null ? void 0 : folderNote.path) != null ? _c : "");
|
|
if (!newName)
|
|
return;
|
|
if (!actualData.pathOnly) {
|
|
this.plugin.changeFolderNameInExplorer(folder, newName);
|
|
}
|
|
const { breadcrumb } = actualData;
|
|
if (breadcrumb) {
|
|
this.plugin.changeFolderNameInPath(folder, newName, breadcrumb);
|
|
}
|
|
folder.newName = newName;
|
|
this.modifiedFolders.set(folder.path, folder);
|
|
}
|
|
async getNewFolderName(folder) {
|
|
var _a, _b, _c, _d;
|
|
if (this.modifiedFolders.has(folder.path)) {
|
|
const modifiedFolder = this.modifiedFolders.get(folder.path);
|
|
if (modifiedFolder) {
|
|
return modifiedFolder.newName;
|
|
}
|
|
}
|
|
const folderNote = getFolderNote(this.plugin, folder.path);
|
|
if (!folderNote)
|
|
return null;
|
|
const resolver = (_b = (_a = this.api) == null ? void 0 : _a.getResolverFactory()) == null ? void 0 : _b.createResolver("#feature-id#");
|
|
return (_d = resolver == null ? void 0 : resolver.resolve((_c = folderNote == null ? void 0 : folderNote.path) != null ? _c : "")) != null ? _d : null;
|
|
}
|
|
async getNewFileName(file) {
|
|
var _a, _b, _c;
|
|
const resolver = (_b = (_a = this.api) == null ? void 0 : _a.getResolverFactory()) == null ? void 0 : _b.createResolver("#feature-id#");
|
|
const changedName = resolver == null ? void 0 : resolver.resolve((_c = file == null ? void 0 : file.path) != null ? _c : "");
|
|
return changedName != null ? changedName : null;
|
|
}
|
|
};
|
|
|
|
// src/settings/modals/CreateFnForEveryFolder.ts
|
|
var import_obsidian19 = require("obsidian");
|
|
var ConfirmationModal = class extends import_obsidian19.Modal {
|
|
constructor(app, plugin) {
|
|
super(app);
|
|
this.plugin = plugin;
|
|
this.app = app;
|
|
this.extension = plugin.settings.folderNoteType;
|
|
}
|
|
onOpen() {
|
|
var _a, _b, _c;
|
|
this.modalEl.addClass("fn-confirmation-modal");
|
|
let templateFolderPath;
|
|
const { templateFolder, templaterPlugin } = getTemplatePlugins(this.plugin.app);
|
|
if ((!templateFolder || (templateFolder == null ? void 0 : templateFolder.trim()) === "") && !templaterPlugin) {
|
|
templateFolderPath = "";
|
|
}
|
|
if (templaterPlugin) {
|
|
templateFolderPath = (_b = (_a = templaterPlugin.plugin) == null ? void 0 : _a.settings) == null ? void 0 : _b.templates_folder;
|
|
} else if (templateFolder) {
|
|
templateFolderPath = templateFolder;
|
|
}
|
|
const { contentEl } = this;
|
|
contentEl.createEl("h2", { text: "Create folder note for every folder" });
|
|
const setting = new import_obsidian19.Setting(contentEl);
|
|
setting.infoEl.createEl("p", { text: "Make sure to backup your vault before using this feature." }).addClass("fn-warning-text");
|
|
setting.infoEl.createEl("p", { text: "This feature will create a folder note for every folder in your vault." });
|
|
setting.infoEl.createEl("p", { text: "Every folder that already has a folder note will be ignored." });
|
|
setting.infoEl.createEl("p", { text: "Every excluded folder will be ignored." });
|
|
if (!this.plugin.settings.templatePath || ((_c = this.plugin.settings.templatePath) == null ? void 0 : _c.trim()) === "") {
|
|
new import_obsidian19.Setting(contentEl).setName("Folder note file extension").setDesc("Choose the file extension for the folder notes.").addDropdown((cb) => {
|
|
this.plugin.settings.supportedFileTypes.forEach((extension) => {
|
|
cb.addOption("." + extension, extension);
|
|
});
|
|
cb.setValue(this.extension);
|
|
cb.onChange(async (value) => {
|
|
this.extension = value;
|
|
});
|
|
});
|
|
}
|
|
new import_obsidian19.Setting(contentEl).addButton((cb) => {
|
|
cb.setButtonText("Create");
|
|
cb.setCta();
|
|
cb.buttonEl.focus();
|
|
cb.onClick(async () => {
|
|
if (this.plugin.settings.templatePath && this.plugin.settings.templatePath.trim() !== "") {
|
|
this.extension = "." + this.plugin.settings.templatePath.split(".").pop();
|
|
}
|
|
if (this.extension === ".ask") {
|
|
return new import_obsidian19.Notice("Please choose a file extension");
|
|
}
|
|
this.close();
|
|
const folders = this.app.vault.getAllLoadedFiles().filter((file) => file.parent instanceof import_obsidian19.TFolder);
|
|
for (const folder of folders) {
|
|
if (folder instanceof import_obsidian19.TFolder) {
|
|
const excludedFolder = getExcludedFolder(this.plugin, folder.path, true);
|
|
if (excludedFolder)
|
|
continue;
|
|
if (folder.path === templateFolderPath)
|
|
continue;
|
|
const folderNote = getFolderNote(this.plugin, folder.path);
|
|
if (folderNote)
|
|
continue;
|
|
await createFolderNote(this.plugin, folder.path, false, this.extension);
|
|
}
|
|
}
|
|
});
|
|
}).addButton((cb) => {
|
|
cb.setButtonText("Cancel");
|
|
cb.onClick(async () => {
|
|
this.close();
|
|
});
|
|
});
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/suggesters/TemplateSuggester.ts
|
|
var import_obsidian20 = require("obsidian");
|
|
var TemplateSuggest = class extends import_obsidian20.AbstractInputSuggest {
|
|
constructor(inputEl, plugin) {
|
|
super(plugin.app, inputEl);
|
|
this.inputEl = inputEl;
|
|
this.plugin = plugin;
|
|
}
|
|
get_error_msg(mode) {
|
|
switch (mode) {
|
|
case 0 /* TemplateFiles */:
|
|
return "Templates folder doesn't exist";
|
|
case 1 /* ScriptFiles */:
|
|
return "User Scripts folder doesn't exist";
|
|
}
|
|
}
|
|
getSuggestions(input_str) {
|
|
var _a, _b;
|
|
const { templateFolder, templaterPlugin } = getTemplatePlugins(this.app);
|
|
let files = [];
|
|
const lower_input_str = input_str.toLowerCase();
|
|
if ((!templateFolder || templateFolder.trim() === "") && !templaterPlugin) {
|
|
files = this.plugin.app.vault.getFiles().filter((file) => file.path.toLowerCase().includes(lower_input_str));
|
|
} else {
|
|
let folder = null;
|
|
if (templaterPlugin) {
|
|
folder = this.plugin.app.vault.getAbstractFileByPath((_b = (_a = templaterPlugin.plugin) == null ? void 0 : _a.settings) == null ? void 0 : _b.templates_folder);
|
|
if (!(folder instanceof import_obsidian20.TFolder)) {
|
|
return [
|
|
{
|
|
path: "",
|
|
name: "You need to set the Templates folder in the Templater settings first."
|
|
}
|
|
];
|
|
}
|
|
} else if (templateFolder) {
|
|
folder = this.plugin.app.vault.getAbstractFileByPath(templateFolder);
|
|
}
|
|
if (!(folder instanceof import_obsidian20.TFolder)) {
|
|
return [];
|
|
}
|
|
import_obsidian20.Vault.recurseChildren(folder, (file) => {
|
|
if (file instanceof import_obsidian20.TFile && file.path.toLowerCase().includes(lower_input_str)) {
|
|
files.push(file);
|
|
}
|
|
});
|
|
}
|
|
return files;
|
|
}
|
|
renderSuggestion(file, el) {
|
|
var _a, _b;
|
|
const { templateFolder, templaterPlugin } = getTemplatePlugins(this.app);
|
|
if ((!templateFolder || templateFolder.trim() === "") && !templaterPlugin) {
|
|
el.setText(`${((_a = file.parent) == null ? void 0 : _a.path) !== "/" ? ((_b = file.parent) == null ? void 0 : _b.path) + "/" : ""}${file.name}`);
|
|
} else {
|
|
el.setText(file.name);
|
|
}
|
|
}
|
|
selectSuggestion(file) {
|
|
this.inputEl.value = file.name.replace(".md", "");
|
|
this.inputEl.trigger("input");
|
|
this.plugin.settings.templatePath = file.path;
|
|
void this.plugin.saveSettings();
|
|
this.close();
|
|
}
|
|
};
|
|
|
|
// src/settings/modals/BackupWarning.ts
|
|
var import_obsidian21 = require("obsidian");
|
|
var BackupWarningModal = class extends import_obsidian21.Modal {
|
|
constructor(plugin, title, description, callback, args) {
|
|
super(plugin.app);
|
|
this.plugin = plugin;
|
|
this.title = title;
|
|
this.callback = callback;
|
|
this.args = args;
|
|
this.desc = description;
|
|
}
|
|
onOpen() {
|
|
this.modalEl.addClass("fn-backup-warning-modal");
|
|
const { contentEl } = this;
|
|
contentEl.createEl("h2", { text: this.title });
|
|
contentEl.createEl("p", { text: this.desc });
|
|
contentEl.createEl("p", { text: "Make sure to backup your vault before using this feature." }).addClass("fn-warning-text");
|
|
const buttonContainer = contentEl.createDiv({ cls: "fn-modal-button-container" });
|
|
const confirmButton = new import_obsidian21.ButtonComponent(buttonContainer);
|
|
confirmButton.setButtonText("Confirm").setCta().onClick(() => {
|
|
this.callback(...this.args);
|
|
this.close();
|
|
});
|
|
const cancelButton = new import_obsidian21.ButtonComponent(buttonContainer);
|
|
cancelButton.setButtonText("Cancel").onClick(() => {
|
|
this.close();
|
|
});
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/settings/modals/RenameFns.ts
|
|
var import_obsidian22 = require("obsidian");
|
|
var RenameFolderNotesModal = class extends BackupWarningModal {
|
|
constructor(plugin, title, description, callback, args) {
|
|
super(plugin, title, description, callback, args);
|
|
}
|
|
insertCustomHtml() {
|
|
const { contentEl } = this;
|
|
new import_obsidian22.Setting(contentEl).setName("Old folder note name").setDesc("Every folder note that matches this name will be renamed to the new folder note name.").addText((text) => text.setPlaceholder("Enter the old folder note name").setValue(this.plugin.settings.oldFolderNoteName || "").onChange(async (value) => {
|
|
this.plugin.settings.oldFolderNoteName = value;
|
|
}));
|
|
new import_obsidian22.Setting(contentEl).setName("New folder note name").setDesc("Every folder note that matches the old folder note name will be renamed to this name.").addText((text) => text.setPlaceholder("Enter the new folder note name").setValue(this.plugin.settings.folderNoteName || "").onChange(async (value) => {
|
|
this.plugin.settings.folderNoteName = value;
|
|
this.plugin.settingsTab.display();
|
|
}));
|
|
}
|
|
};
|
|
|
|
// src/settings/GeneralSettings.ts
|
|
var debounceTimer;
|
|
async function renderGeneral(settingsTab) {
|
|
const containerEl = settingsTab.settingsPage;
|
|
const nameSetting = new import_obsidian23.Setting(containerEl).setName("Folder note name template").setDesc("All folder notes will use this name. Use {{folder_name}} to insert the folder\u2019s name. Existing notes won\u2019t update automatically; click on the button to apply the new name.").addText((text) => text.setValue(settingsTab.plugin.settings.folderNoteName).onChange(async (value) => {
|
|
if (value.trim() === "") {
|
|
return;
|
|
}
|
|
settingsTab.plugin.settings.folderNoteName = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
window.clearTimeout(debounceTimer);
|
|
const FOLDER_NOTE_NAME_DEBOUNCE_MS = 2e3;
|
|
debounceTimer = window.setTimeout(() => {
|
|
if (!value.includes("{{folder_name}}")) {
|
|
if (!settingsTab.showFolderNameInTabTitleSetting) {
|
|
settingsTab.display();
|
|
settingsTab.showFolderNameInTabTitleSetting = true;
|
|
}
|
|
} else {
|
|
if (settingsTab.showFolderNameInTabTitleSetting) {
|
|
settingsTab.display();
|
|
settingsTab.showFolderNameInTabTitleSetting = false;
|
|
}
|
|
}
|
|
}, FOLDER_NOTE_NAME_DEBOUNCE_MS);
|
|
})).addButton((button) => button.setButtonText("Rename existing folder notes").setCta().onClick(async () => {
|
|
var _a;
|
|
new RenameFolderNotesModal(settingsTab.plugin, "Rename all existing folder notes", 'When you click on "Confirm" all existing folder notes will be renamed to the new folder note name.', settingsTab.renameFolderNotes, [(_a = settingsTab.plugin.settings.oldFolderNoteName) != null ? _a : "{{folder_name}}"]).open();
|
|
}));
|
|
nameSetting.infoEl.appendText("Requires a restart to take effect");
|
|
nameSetting.infoEl.style.color = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
|
|
if (!settingsTab.plugin.settings.folderNoteName.includes("{{folder_name}}")) {
|
|
new import_obsidian23.Setting(containerEl).setName("Display folder name in tab title").setDesc('Use the actual folder name in the tab title instead of the custom folder note name (e.g., "folder note").').addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.tabManagerEnabled).onChange(async (value) => {
|
|
if (!value) {
|
|
settingsTab.plugin.tabManager.resetTabs();
|
|
} else {
|
|
settingsTab.plugin.settings.tabManagerEnabled = value;
|
|
settingsTab.plugin.tabManager.updateTabs();
|
|
}
|
|
settingsTab.plugin.settings.tabManagerEnabled = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
}
|
|
new import_obsidian23.Setting(containerEl).setName("Default file type for new folder notes").setDesc("Choose the default file type (canvas, Markdown, ...) used when creating new folder notes.").addDropdown((dropdown) => {
|
|
dropdown.addOption(".ask", "Ask for file type");
|
|
settingsTab.plugin.settings.supportedFileTypes.forEach((type) => {
|
|
if (type === ".md" || type === "md") {
|
|
dropdown.addOption(".md", "Markdown");
|
|
} else {
|
|
dropdown.addOption("." + type, type);
|
|
}
|
|
});
|
|
if (!settingsTab.plugin.settings.supportedFileTypes.includes(settingsTab.plugin.settings.folderNoteType.replace(".", "")) && settingsTab.plugin.settings.folderNoteType !== ".ask") {
|
|
settingsTab.plugin.settings.folderNoteType = ".md";
|
|
void settingsTab.plugin.saveSettings();
|
|
}
|
|
let defaultType = settingsTab.plugin.settings.folderNoteType.startsWith(".") ? settingsTab.plugin.settings.folderNoteType : "." + settingsTab.plugin.settings.folderNoteType;
|
|
if (!settingsTab.plugin.settings.supportedFileTypes.includes(defaultType.replace(".", ""))) {
|
|
defaultType = ".ask";
|
|
settingsTab.plugin.settings.folderNoteType = defaultType;
|
|
}
|
|
dropdown.setValue(defaultType).onChange(async (value) => {
|
|
settingsTab.plugin.settings.folderNoteType = value;
|
|
void settingsTab.plugin.saveSettings();
|
|
void settingsTab.display();
|
|
});
|
|
});
|
|
const setting0 = new import_obsidian23.Setting(containerEl);
|
|
setting0.setName("Supported file types");
|
|
const desc0 = document.createDocumentFragment();
|
|
desc0.append("Specify which file types are allowed as folder notes. Applies to both new and existing folders. Adding many types may affect performance.");
|
|
setting0.setDesc(desc0);
|
|
const list = new ListComponent(setting0.settingEl, settingsTab.plugin.settings.supportedFileTypes || [], ["md", "canvas"]);
|
|
list.on("update", (values) => {
|
|
settingsTab.plugin.settings.supportedFileTypes = values;
|
|
void settingsTab.plugin.saveSettings();
|
|
void settingsTab.display();
|
|
});
|
|
if (!settingsTab.plugin.settings.supportedFileTypes.includes("md") || !settingsTab.plugin.settings.supportedFileTypes.includes("canvas") || !settingsTab.plugin.settings.supportedFileTypes.includes("excalidraw")) {
|
|
setting0.addDropdown((dropdown) => {
|
|
const options = [
|
|
{ value: "md", label: "Markdown" },
|
|
{ value: "canvas", label: "Canvas" },
|
|
{ value: "base", label: "Bases" },
|
|
{ value: "excalidraw", label: "Excalidraw" },
|
|
{ value: "custom", label: "Custom extension" }
|
|
];
|
|
options.forEach((option) => {
|
|
var _a;
|
|
if (!((_a = settingsTab.plugin.settings.supportedFileTypes) == null ? void 0 : _a.includes(option.value))) {
|
|
dropdown.addOption(option.value, option.label);
|
|
}
|
|
});
|
|
dropdown.addOption("+", "+");
|
|
dropdown.setValue("+");
|
|
dropdown.onChange(async (value) => {
|
|
if (value === "custom") {
|
|
return new AddSupportedFileModal(settingsTab.app, settingsTab.plugin, settingsTab, list).open();
|
|
}
|
|
await list.addValue(value.toLowerCase());
|
|
void settingsTab.display();
|
|
void settingsTab.plugin.saveSettings();
|
|
});
|
|
});
|
|
} else {
|
|
setting0.addButton((button) => button.setButtonText("Add custom file type").setCta().onClick(async () => {
|
|
new AddSupportedFileModal(settingsTab.app, settingsTab.plugin, settingsTab, list).open();
|
|
}));
|
|
}
|
|
const templateSetting = new import_obsidian23.Setting(containerEl).setDesc("Can be used with templater/templates plugin. If you add the location of the templates there.").setName("Template path").addSearch((cb) => {
|
|
new TemplateSuggest(cb.inputEl, settingsTab.plugin);
|
|
cb.setPlaceholder("Template path");
|
|
const templateFile = settingsTab.plugin.app.vault.getAbstractFileByPath(settingsTab.plugin.settings.templatePath);
|
|
const templateName = (templateFile == null ? void 0 : templateFile.name.replace(".md", "")) || "";
|
|
cb.setValue(templateName);
|
|
cb.onChange(async (value) => {
|
|
if (value.trim() === "") {
|
|
settingsTab.plugin.settings.templatePath = "";
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
return;
|
|
}
|
|
});
|
|
});
|
|
templateSetting.infoEl.appendText("Requires a restart to take effect");
|
|
templateSetting.infoEl.style.color = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
|
|
const storageLocation = new import_obsidian23.Setting(containerEl).setName("Storage location").setDesc("Choose where to store the folder notes").addDropdown((dropdown) => dropdown.addOption("insideFolder", "Inside the folder").addOption("parentFolder", "In the parent folder").setValue(settingsTab.plugin.settings.storageLocation).onChange(async (value) => {
|
|
if (value !== "insideFolder" && value !== "parentFolder" && value !== "vaultFolder") {
|
|
return;
|
|
}
|
|
settingsTab.plugin.settings.storageLocation = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
refreshAllFolderStyles(void 0, settingsTab.plugin);
|
|
})).addButton((button) => button.setButtonText("Switch").setCta().onClick(async () => {
|
|
let oldStorageLocation = settingsTab.plugin.settings.storageLocation;
|
|
if (settingsTab.plugin.settings.storageLocation === "parentFolder") {
|
|
oldStorageLocation = "insideFolder";
|
|
} else if (settingsTab.plugin.settings.storageLocation === "insideFolder") {
|
|
oldStorageLocation = "parentFolder";
|
|
}
|
|
new BackupWarningModal(settingsTab.plugin, "Switch storage location", 'When you click on "Confirm" all folder notes will be moved to the new storage location.', settingsTab.switchStorageLocation, [oldStorageLocation]).open();
|
|
}));
|
|
storageLocation.infoEl.appendText("Requires a restart to take effect");
|
|
storageLocation.infoEl.style.color = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
|
|
if (settingsTab.plugin.settings.storageLocation === "parentFolder") {
|
|
new import_obsidian23.Setting(containerEl).setName("Delete folder notes when deleting the folder").setDesc("Delete the folder note when deleting the folder").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.syncDelete).onChange(async (value) => {
|
|
settingsTab.plugin.settings.syncDelete = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian23.Setting(containerEl).setName("Move folder notes when moving the folder").setDesc("Move the folder note file along with the folder when it is moved").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.syncMove).onChange(async (value) => {
|
|
settingsTab.plugin.settings.syncMove = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
}
|
|
if (import_obsidian23.Platform.isDesktopApp) {
|
|
settingsTab.settingsPage.createEl("h3", { text: "Keyboard shortcuts" });
|
|
new import_obsidian23.Setting(containerEl).setName("Key for creating folder note").setDesc("The key combination to create a folder note").addDropdown((dropdown) => {
|
|
if (!import_obsidian23.Platform.isMacOS) {
|
|
dropdown.addOption("ctrl", "Ctrl + Click");
|
|
dropdown.addOption("alt", "Alt + Click");
|
|
} else {
|
|
dropdown.addOption("ctrl", "Cmd + Click");
|
|
dropdown.addOption("alt", "Option + Click");
|
|
}
|
|
dropdown.setValue(settingsTab.plugin.settings.ctrlKey ? "ctrl" : "alt");
|
|
dropdown.onChange(async (value) => {
|
|
settingsTab.plugin.settings.ctrlKey = value === "ctrl";
|
|
settingsTab.plugin.settings.altKey = value === "alt";
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
});
|
|
});
|
|
new import_obsidian23.Setting(containerEl).setName("Key for opening folder note").setDesc("Select the combination to open a folder note").addDropdown((dropdown) => {
|
|
dropdown.addOption("click", "Mouse click");
|
|
if (!import_obsidian23.Platform.isMacOS) {
|
|
dropdown.addOption("ctrl", "Ctrl + Click");
|
|
dropdown.addOption("alt", "Alt + Click");
|
|
} else {
|
|
dropdown.addOption("ctrl", "Cmd + Click");
|
|
dropdown.addOption("alt", "Option + Click");
|
|
}
|
|
if (settingsTab.plugin.settings.openByClick) {
|
|
dropdown.setValue("click");
|
|
} else if (settingsTab.plugin.settings.openWithCtrl) {
|
|
dropdown.setValue("ctrl");
|
|
} else {
|
|
dropdown.setValue("alt");
|
|
}
|
|
dropdown.onChange(async (value) => {
|
|
settingsTab.plugin.settings.openByClick = value === "click";
|
|
settingsTab.plugin.settings.openWithCtrl = value === "ctrl";
|
|
settingsTab.plugin.settings.openWithAlt = value === "alt";
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
});
|
|
});
|
|
}
|
|
settingsTab.settingsPage.createEl("h3", { text: "Folder note behavior" });
|
|
new import_obsidian23.Setting(containerEl).setName("Confirm folder note deletion").setDesc("Ask for confirmation before deleting a folder note").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.showDeleteConfirmation).onChange(async (value) => {
|
|
settingsTab.plugin.settings.showDeleteConfirmation = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
new import_obsidian23.Setting(containerEl).setName("Deleted folder notes").setDesc("What happens to the folder note after you delete it").addDropdown((dropdown) => {
|
|
dropdown.addOption("trash", "Move to system trash");
|
|
dropdown.addOption("obsidianTrash", "Move to Obsidian trash (.trash folder)");
|
|
dropdown.addOption("delete", "Delete permanently");
|
|
dropdown.setValue(settingsTab.plugin.settings.deleteFilesAction);
|
|
dropdown.onChange(async (value) => {
|
|
const v = value;
|
|
settingsTab.plugin.settings.deleteFilesAction = v;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
});
|
|
});
|
|
if (import_obsidian23.Platform.isDesktop) {
|
|
const setting3 = new import_obsidian23.Setting(containerEl);
|
|
setting3.setName("Open folder note in a new tab by default");
|
|
setting3.setDesc("Always open folder notes in a new tab unless the note is already open in the current tab.");
|
|
setting3.addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.openInNewTab).onChange(async (value) => {
|
|
settingsTab.plugin.settings.openInNewTab = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
setting3.infoEl.appendText("Requires a restart to take effect");
|
|
setting3.infoEl.style.color = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
|
|
}
|
|
if (settingsTab.plugin.settings.openInNewTab) {
|
|
new import_obsidian23.Setting(containerEl).setName("Focus existing tab instead of creating a new one").setDesc("If a folder note is already open in a tab, focus that tab instead of creating a new one.").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.focusExistingTab).onChange(async (value) => {
|
|
settingsTab.plugin.settings.focusExistingTab = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
}
|
|
new import_obsidian23.Setting(containerEl).setName("Sync folder name").setDesc("Automatically rename the folder note when the folder name is changed").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.syncFolderName).onChange(async (value) => {
|
|
settingsTab.plugin.settings.syncFolderName = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
settingsTab.settingsPage.createEl("h4", { text: "Automation settings" });
|
|
new import_obsidian23.Setting(containerEl).setName("Create folder notes for all folders").setDesc("Generate folder notes for every folder in the vault.").addButton((cb) => {
|
|
cb.setIcon("plus");
|
|
cb.setTooltip("Create folder notes");
|
|
cb.onClick(async () => {
|
|
new ConfirmationModal(settingsTab.app, settingsTab.plugin).open();
|
|
});
|
|
});
|
|
new import_obsidian23.Setting(containerEl).setName("Auto-create on folder creation").setDesc("Automatically create a folder note whenever a new folder is added.").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.autoCreate).onChange(async (value) => {
|
|
settingsTab.plugin.settings.autoCreate = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
if (settingsTab.plugin.settings.autoCreate) {
|
|
new import_obsidian23.Setting(containerEl).setName("Auto-open after creation").setDesc("Open the folder note immediately after it\u2019s created automatically.").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.autoCreateFocusFiles).onChange(async (value) => {
|
|
settingsTab.plugin.settings.autoCreateFocusFiles = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
new import_obsidian23.Setting(containerEl).setName("Auto-create for attachment folders").setDesc('Also automatically create folder notes for attachment folders (e.g., "attachments", "media", etc.).').addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.autoCreateForAttachmentFolder).onChange(async (value) => {
|
|
settingsTab.plugin.settings.autoCreateForAttachmentFolder = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
}
|
|
new import_obsidian23.Setting(containerEl).setName("Auto-create when creating notes").setDesc("Automatically create a folder note when a regular note is created inside a folder. Works for supported file types only.").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.autoCreateForFiles).onChange(async (value) => {
|
|
settingsTab.plugin.settings.autoCreateForFiles = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
settingsTab.settingsPage.createEl("h3", { text: "Integration & compatibility" });
|
|
const desc1 = document.createDocumentFragment();
|
|
const link = activeDocument.createElement("a");
|
|
link.href = "https://github.com/snezhig/obsidian-front-matter-title";
|
|
link.textContent = "Front matter title plugin";
|
|
link.target = "_blank";
|
|
desc1.append("Allows you to use the ", link, " with folder notes. It allows you to set the folder name to some name you set in the front matter.");
|
|
const fmtpSetting = new import_obsidian23.Setting(containerEl).setName("Enable front matter title plugin integration").setDesc(desc1).addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.frontMatterTitle.enabled).onChange(async (value) => {
|
|
var _a;
|
|
settingsTab.plugin.settings.frontMatterTitle.enabled = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
if (value) {
|
|
settingsTab.plugin.fmtpHandler = new FrontMatterTitlePluginHandler(settingsTab.plugin);
|
|
} else {
|
|
if (settingsTab.plugin.fmtpHandler) {
|
|
settingsTab.plugin.updateAllBreadcrumbs(true);
|
|
}
|
|
settingsTab.plugin.app.vault.getFiles().forEach((file) => {
|
|
var _a2;
|
|
void ((_a2 = settingsTab.plugin.fmtpHandler) == null ? void 0 : _a2.fmptUpdateFileName({
|
|
id: "",
|
|
result: false,
|
|
path: file.path,
|
|
pathOnly: false
|
|
}, false));
|
|
});
|
|
(_a = settingsTab.plugin.fmtpHandler) == null ? void 0 : _a.deleteEvent();
|
|
settingsTab.plugin.fmtpHandler = new FrontMatterTitlePluginHandler(settingsTab.plugin);
|
|
}
|
|
settingsTab.display();
|
|
}));
|
|
fmtpSetting.infoEl.appendText("Requires a restart to take effect");
|
|
fmtpSetting.infoEl.style.color = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
|
|
settingsTab.settingsPage.createEl("h3", { text: "Session & persistence" });
|
|
new import_obsidian23.Setting(containerEl).setName("Persist tab after restart").setDesc("Restore the same settings tab after restarting Obsidian.").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.persistentSettingsTab.afterRestart).onChange(async (value) => {
|
|
settingsTab.plugin.settings.persistentSettingsTab.afterRestart = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
new import_obsidian23.Setting(containerEl).setName("Persist tab during session only").setDesc("Keep the current settings tab open during the session, but reset it after a restart or reload.").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.persistentSettingsTab.afterChangingTab).onChange(async (value) => {
|
|
settingsTab.plugin.settings.persistentSettingsTab.afterChangingTab = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
}
|
|
|
|
// src/settings/FileExplorerSettings.ts
|
|
var import_obsidian24 = require("obsidian");
|
|
async function renderFileExplorer(settingsTab) {
|
|
const containerEl = settingsTab.settingsPage;
|
|
new import_obsidian24.Setting(containerEl).setName("Hide folder note").setDesc("Hide the folder note file from appearing in the file explorer").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.hideFolderNote).onChange(async (value) => {
|
|
settingsTab.plugin.settings.hideFolderNote = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
if (value) {
|
|
activeDocument.body.classList.add("hide-folder-note");
|
|
} else {
|
|
activeDocument.body.classList.remove("hide-folder-note");
|
|
}
|
|
settingsTab.display();
|
|
}));
|
|
const setting2 = new import_obsidian24.Setting(containerEl).setName("Disable click-to-open folder note on mobile").setDesc("Prevents folder notes from opening when tapping the folder name or surrounding area on mobile devices. They can now only be opened via the context menu or a command.").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.disableOpenFolderNoteOnClick).onChange(async (value) => {
|
|
settingsTab.plugin.settings.disableOpenFolderNoteOnClick = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
setting2.infoEl.appendText("Requires a restart to take effect");
|
|
const setting2AccentColor = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
|
|
setting2.infoEl.style.color = setting2AccentColor;
|
|
new import_obsidian24.Setting(containerEl).setName("Open folder notes by only clicking directly on the folder name").setDesc("Only allow folder notes to open when clicking directly on the folder name in the file explorer").addToggle((toggle) => toggle.setValue(!settingsTab.plugin.settings.stopWhitespaceCollapsing).onChange(async (value) => {
|
|
if (!value) {
|
|
activeDocument.body.classList.add("fn-whitespace-stop-collapsing");
|
|
} else {
|
|
activeDocument.body.classList.remove("fn-whitespace-stop-collapsing");
|
|
}
|
|
settingsTab.plugin.settings.stopWhitespaceCollapsing = !value;
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
const disableSetting = new import_obsidian24.Setting(containerEl);
|
|
disableSetting.setName("Disable folder collapsing");
|
|
disableSetting.setDesc("When enabled, folders in the file explorer will only collapse when clicking the collapse icon next to the folder name, not when clicking near a folder name when it has a folder note.");
|
|
disableSetting.addToggle((toggle) => toggle.setValue(!settingsTab.plugin.settings.enableCollapsing).onChange(async (value) => {
|
|
settingsTab.plugin.settings.enableCollapsing = !value;
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
disableSetting.infoEl.appendText("Requires a restart to take effect");
|
|
const accentColor = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
|
|
disableSetting.infoEl.style.color = accentColor;
|
|
new import_obsidian24.Setting(containerEl).setName("Use submenus").setDesc("Use submenus for file/folder commands").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.useSubmenus).onChange(async (value) => {
|
|
settingsTab.plugin.settings.useSubmenus = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
if (settingsTab.plugin.settings.frontMatterTitle.enabled) {
|
|
new import_obsidian24.Setting(containerEl).setName("Auto update folder name in the file explorer (front matter title plugin only)").setDesc("Automatically update the folder name in the file explorer when the front matter title plugin is enabled and the title for a folder note is changed in the front matter. This will not change the file name, only the displayed name in the file explorer.").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.frontMatterTitle.explorer).onChange(async (value) => {
|
|
settingsTab.plugin.settings.frontMatterTitle.explorer = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.plugin.app.vault.getFiles().forEach((file) => {
|
|
var _a;
|
|
(_a = settingsTab.plugin.fmtpHandler) == null ? void 0 : _a.fmptUpdateFileName({
|
|
id: "",
|
|
result: false,
|
|
path: file.path,
|
|
pathOnly: false
|
|
}, false);
|
|
});
|
|
}));
|
|
}
|
|
settingsTab.settingsPage.createEl("h3", { text: "Style settings" });
|
|
new import_obsidian24.Setting(containerEl).setName("Highlight folder in the file explorer").setDesc("Highlight the folder in the file explorer when it has a folder note and the folder note is open in the editor").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.highlightFolder).onChange(async (value) => {
|
|
settingsTab.plugin.settings.highlightFolder = value;
|
|
if (!value) {
|
|
activeDocument.body.classList.add("disable-folder-highlight");
|
|
} else {
|
|
activeDocument.body.classList.remove("disable-folder-highlight");
|
|
}
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian24.Setting(containerEl).setName("Hide collapse icon").setDesc("Hide the collapse icon in the file explorer next to the name of a folder when a folder only contains a folder note").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.hideCollapsingIcon).onChange(async (value) => {
|
|
settingsTab.plugin.settings.hideCollapsingIcon = value;
|
|
if (value) {
|
|
activeDocument.body.classList.add("fn-hide-collapse-icon");
|
|
} else {
|
|
activeDocument.body.classList.remove("fn-hide-collapse-icon");
|
|
}
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
new import_obsidian24.Setting(containerEl).setName("Hide collapse icon for every empty folder").setDesc("Hide the collapse icon in the file explorer next to the name of a folder when a folder is empty").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.hideCollapsingIconForEmptyFolders).onChange(async (value) => {
|
|
settingsTab.plugin.settings.hideCollapsingIconForEmptyFolders = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
if (value) {
|
|
activeDocument.body.classList.add("fn-hide-empty-collapse-icon");
|
|
} else {
|
|
activeDocument.body.classList.remove("fn-hide-empty-collapse-icon");
|
|
}
|
|
settingsTab.display();
|
|
}));
|
|
if (settingsTab.plugin.settings.hideCollapsingIcon) {
|
|
new import_obsidian24.Setting(containerEl).setName("Hide collapse icon also when only the attachment folder is in the same folder").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.ignoreAttachmentFolder).onChange(async (value) => {
|
|
if (value) {
|
|
activeDocument.body.classList.add("fn-ignore-attachment-folder");
|
|
} else {
|
|
activeDocument.body.classList.remove("fn-ignore-attachment-folder");
|
|
}
|
|
settingsTab.plugin.settings.ignoreAttachmentFolder = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
}
|
|
new import_obsidian24.Setting(containerEl).setName("Underline the name of folder notes").setDesc("Add an underline to folders that have a folder note in the file explorer").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.underlineFolder).onChange(async (value) => {
|
|
settingsTab.plugin.settings.underlineFolder = value;
|
|
if (value) {
|
|
activeDocument.body.classList.add("folder-note-underline");
|
|
} else {
|
|
activeDocument.body.classList.remove("folder-note-underline");
|
|
}
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian24.Setting(containerEl).setName("Bold the name of folder notes").setDesc("Make the folder name bold in the file explorer when it has a folder note").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.boldName).onChange(async (value) => {
|
|
settingsTab.plugin.settings.boldName = value;
|
|
if (value) {
|
|
activeDocument.body.classList.add("folder-note-bold");
|
|
} else {
|
|
activeDocument.body.classList.remove("folder-note-bold");
|
|
}
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian24.Setting(containerEl).setName("Cursive the name of folder notes").setDesc("Make the folder name cursive in the file explorer when it has a folder note").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.cursiveName).onChange(async (value) => {
|
|
settingsTab.plugin.settings.cursiveName = value;
|
|
if (value) {
|
|
activeDocument.body.classList.add("folder-note-cursive");
|
|
} else {
|
|
activeDocument.body.classList.remove("folder-note-cursive");
|
|
}
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
}
|
|
|
|
// src/settings/PathSettings.ts
|
|
var import_obsidian25 = require("obsidian");
|
|
async function renderPath(settingsTab) {
|
|
const containerEl = settingsTab.settingsPage;
|
|
new import_obsidian25.Setting(containerEl).setName("Open folder note through path").setDesc("Open a folder note when clicking on a folder name in the path if it is a folder note").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.openFolderNoteOnClickInPath).onChange(async (value) => {
|
|
settingsTab.plugin.settings.openFolderNoteOnClickInPath = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
settingsTab.display();
|
|
}));
|
|
if (settingsTab.plugin.settings.openFolderNoteOnClickInPath) {
|
|
new import_obsidian25.Setting(containerEl).setName("Open sidebar when opening a folder note through path (mobile only)").setDesc("Open the sidebar when opening a folder note through the path on mobile").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.openSidebar.mobile).onChange(async (value) => {
|
|
settingsTab.plugin.settings.openSidebar.mobile = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian25.Setting(containerEl).setName("Open sidebar when opening a folder note through path (desktop only)").setDesc("Open the sidebar when opening a folder note through the path on desktop").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.openSidebar.desktop).onChange(async (value) => {
|
|
settingsTab.plugin.settings.openSidebar.desktop = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
}
|
|
if (settingsTab.plugin.settings.frontMatterTitle.enabled) {
|
|
new import_obsidian25.Setting(containerEl).setName("Auto update folder name in the path (front matter title plugin only)").setDesc("Automatically update the folder name in the path when the front matter title plugin is enabled and the title for a folder note is changed in the front matter. This will not change the file name, only the displayed name in the path.").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.frontMatterTitle.path).onChange(async (value) => {
|
|
settingsTab.plugin.settings.frontMatterTitle.path = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
if (value) {
|
|
settingsTab.plugin.updateAllBreadcrumbs();
|
|
} else {
|
|
settingsTab.plugin.updateAllBreadcrumbs(true);
|
|
}
|
|
}));
|
|
}
|
|
settingsTab.settingsPage.createEl("h3", { text: "Style settings" });
|
|
new import_obsidian25.Setting(containerEl).setName("Underline folders in the path").setDesc("Add an underline to folders that have a folder note in the path above a note").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.underlineFolderInPath).onChange(async (value) => {
|
|
settingsTab.plugin.settings.underlineFolderInPath = value;
|
|
if (value) {
|
|
activeDocument.body.classList.add("folder-note-underline-path");
|
|
} else {
|
|
activeDocument.body.classList.remove("folder-note-underline-path");
|
|
}
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian25.Setting(containerEl).setName("Bold folders in the path").setDesc("Make the folder name bold in the path above a note when it has a folder note").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.boldNameInPath).onChange(async (value) => {
|
|
settingsTab.plugin.settings.boldNameInPath = value;
|
|
if (value) {
|
|
activeDocument.body.classList.add("folder-note-bold-path");
|
|
} else {
|
|
activeDocument.body.classList.remove("folder-note-bold-path");
|
|
}
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian25.Setting(containerEl).setName("Cursive the name of folder notes in the path").setDesc("Make the folder name cursive in the path above a note when it has a folder note").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.cursiveNameInPath).onChange(async (value) => {
|
|
settingsTab.plugin.settings.cursiveNameInPath = value;
|
|
if (value) {
|
|
activeDocument.body.classList.add("folder-note-cursive-path");
|
|
} else {
|
|
activeDocument.body.classList.remove("folder-note-cursive-path");
|
|
}
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian25.Setting(containerEl).setName("Hide folder note name in the path").setDesc("Only show the folder name in the path and hide the folder note name.").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.hideFolderNoteNameInPath).onChange(async (value) => {
|
|
activeDocument.body.classList.toggle("folder-note-hide-name-path", value);
|
|
settingsTab.plugin.settings.hideFolderNoteNameInPath = value;
|
|
await settingsTab.plugin.saveSettings();
|
|
}));
|
|
}
|
|
|
|
// src/settings/FolderOverviewSettings.ts
|
|
var import_obsidian29 = require("obsidian");
|
|
|
|
// src/obsidian-folder-overview/src/settings.ts
|
|
var import_obsidian28 = require("obsidian");
|
|
|
|
// src/obsidian-folder-overview/src/suggesters/FolderSuggester.ts
|
|
var import_obsidian26 = require("obsidian");
|
|
var MAX_LOADED_FILES = 100;
|
|
var FolderSuggest2 = class extends import_obsidian26.AbstractInputSuggest {
|
|
constructor(inputEl, plugin, whitelistSuggester, folder) {
|
|
super(plugin.app, inputEl);
|
|
this.inputEl = inputEl;
|
|
this.whitelistSuggester = whitelistSuggester;
|
|
this.folder = folder;
|
|
this.plugin = plugin;
|
|
}
|
|
getSuggestions(input_str) {
|
|
const folders = [];
|
|
const lower_input_str = input_str.toLowerCase();
|
|
let files = [];
|
|
if (this.folder) {
|
|
files = this.folder.children.slice(0, MAX_LOADED_FILES);
|
|
} else {
|
|
files = this.plugin.app.vault.getAllLoadedFiles().slice(0, MAX_LOADED_FILES);
|
|
}
|
|
folders.push({ path: "File\u2019s parent folder path" });
|
|
if (this.plugin instanceof FolderNotesPlugin) {
|
|
folders.push({ path: "Path of folder linked to the file" });
|
|
}
|
|
files.forEach((folder) => {
|
|
if (folder instanceof import_obsidian26.TFolder && folder.path.toLowerCase().contains(lower_input_str) && (this.plugin instanceof FolderNotesPlugin ? !this.plugin.settings.excludeFolders.find((f) => f.path === folder.path) || this.whitelistSuggester : true)) {
|
|
folders.push(folder);
|
|
}
|
|
});
|
|
return folders;
|
|
}
|
|
renderSuggestion(folder, el) {
|
|
el.setText(folder.path);
|
|
}
|
|
selectSuggestion(folder) {
|
|
this.inputEl.value = folder.path;
|
|
this.inputEl.trigger("input");
|
|
this.close();
|
|
}
|
|
};
|
|
|
|
// src/obsidian-folder-overview/src/utils/ListComponent.ts
|
|
var import_obsidian27 = require("obsidian");
|
|
|
|
// src/obsidian-folder-overview/src/utils/EventEmitter.ts
|
|
var CustomEventEmitter2 = class {
|
|
constructor() {
|
|
this.events = {};
|
|
}
|
|
on(event, listener) {
|
|
if (!this.events[event]) {
|
|
this.events[event] = [];
|
|
}
|
|
this.events[event].push(listener);
|
|
}
|
|
off(event, listener) {
|
|
if (!this.events[event])
|
|
return;
|
|
this.events[event] = this.events[event].filter((l) => l !== listener);
|
|
}
|
|
emit(event, data) {
|
|
if (!this.events[event])
|
|
return;
|
|
this.events[event].forEach((listener) => listener(data));
|
|
}
|
|
};
|
|
|
|
// src/obsidian-folder-overview/src/utils/ListComponent.ts
|
|
var ListComponent2 = class {
|
|
constructor(containerEl, values = [], defaultValues = []) {
|
|
this.values = [];
|
|
this.emitter = new CustomEventEmitter2();
|
|
this.containerEl = containerEl;
|
|
this.controlEl = containerEl.querySelector(".setting-item-control") || containerEl;
|
|
this.listEl = this.controlEl.createDiv("setting-command-hotkeys");
|
|
this.addResetButton();
|
|
this.setValues(values);
|
|
this.defaultValues = defaultValues;
|
|
}
|
|
on(event, listener) {
|
|
this.emitter.on(event, listener);
|
|
}
|
|
off(event, listener) {
|
|
this.emitter.off(event, listener);
|
|
}
|
|
emit(event, data) {
|
|
this.emitter.emit(event, data);
|
|
}
|
|
setValues(values) {
|
|
this.removeElements();
|
|
this.values = values;
|
|
if (values.length !== 0) {
|
|
values.forEach((value) => {
|
|
this.addElement(value);
|
|
});
|
|
}
|
|
this.emit("update", this.values);
|
|
}
|
|
removeElements() {
|
|
this.listEl.empty();
|
|
}
|
|
addElement(value) {
|
|
this.listEl.createSpan("setting-hotkey", (span) => {
|
|
if (value.toLocaleLowerCase() === "md") {
|
|
span.innerText = "markdown";
|
|
} else {
|
|
span.innerText = value;
|
|
}
|
|
span.setAttribute("extension", value);
|
|
const removeSpan = span.createEl("span", {
|
|
cls: "ofn-list-item-remove setting-hotkey-icon"
|
|
});
|
|
const svgElement = removeSpan.createEl("span", { cls: "ofn-list-item-remove-icon" });
|
|
(0, import_obsidian27.setIcon)(svgElement, "x");
|
|
removeSpan.onClickEvent(() => {
|
|
this.removeValue(value);
|
|
span.remove();
|
|
});
|
|
});
|
|
}
|
|
async addValue(value) {
|
|
this.values.push(value);
|
|
this.addElement(value);
|
|
this.emit("add", value);
|
|
this.emit("update", this.values);
|
|
}
|
|
addResetButton() {
|
|
const resetButton = this.controlEl.createEl("span", {
|
|
cls: "clickable-icon setting-restore-hotkey-button"
|
|
});
|
|
(0, import_obsidian27.setIcon)(resetButton, "rotate-ccw");
|
|
resetButton.onClickEvent(() => {
|
|
this.setValues(this.defaultValues);
|
|
});
|
|
return this;
|
|
}
|
|
removeValue(value) {
|
|
this.values = this.values.filter((v) => v !== value);
|
|
this.listEl.find(`[extension='${value}']`).remove();
|
|
this.emit("remove", value);
|
|
this.emit("update", this.values);
|
|
}
|
|
};
|
|
|
|
// src/obsidian-folder-overview/src/settings.ts
|
|
var OVERVIEW_SETTINGS = {
|
|
id: "",
|
|
folderPath: "",
|
|
title: "{{folderName}} overview",
|
|
showTitle: false,
|
|
depth: 3,
|
|
includeTypes: ["folder", "markdown"],
|
|
style: "list",
|
|
disableFileTag: false,
|
|
sortBy: "name",
|
|
sortByAsc: true,
|
|
showEmptyFolders: false,
|
|
onlyIncludeSubfolders: false,
|
|
storeFolderCondition: true,
|
|
showFolderNotes: false,
|
|
disableCollapseIcon: true,
|
|
alwaysCollapse: false,
|
|
autoSync: true,
|
|
allowDragAndDrop: true,
|
|
hideLinkList: true,
|
|
hideFolderOverview: false,
|
|
useActualLinks: false,
|
|
fmtpIntegration: false,
|
|
titleSize: 1,
|
|
isInCallout: false,
|
|
useWikilinks: true
|
|
};
|
|
var GLOBAL_SETTINGS = {
|
|
autoUpdateLinks: false
|
|
};
|
|
var DEFAULT_SETTINGS = {
|
|
defaultOverviewSettings: OVERVIEW_SETTINGS,
|
|
globalSettings: GLOBAL_SETTINGS,
|
|
firstTimeInsertOverview: false
|
|
};
|
|
var MAX_INCLUDE_TYPES_FOR_DROPDOWN = 8;
|
|
var SettingsTab = class extends import_obsidian28.PluginSettingTab {
|
|
constructor(plugin) {
|
|
super(plugin.app, plugin);
|
|
this.plugin = plugin;
|
|
}
|
|
display() {
|
|
const { containerEl } = this;
|
|
containerEl.createEl("h3", { text: "Global settings" });
|
|
new import_obsidian28.Setting(containerEl).setName("Auto-update links without opening the overview").setDesc("If enabled, the links that appear in the graph view will be updated even when you don't have the overview open somewhere.").addToggle((toggle) => toggle.setValue(this.plugin.settings.globalSettings.autoUpdateLinks).onChange(async (value) => {
|
|
this.plugin.settings.globalSettings.autoUpdateLinks = value;
|
|
await this.plugin.saveSettings();
|
|
if (value) {
|
|
this.plugin.fvIndexDB.init(true);
|
|
} else {
|
|
this.plugin.fvIndexDB.active = false;
|
|
}
|
|
}));
|
|
containerEl.createEl("h3", { text: "Overviews default settings" });
|
|
const pEl = containerEl.createEl("p", {
|
|
text: "Edit the default settings for new folder overviews, ",
|
|
cls: "setting-item-description"
|
|
});
|
|
const span = createSpan({
|
|
text: "this won't apply to already existing overviews.",
|
|
cls: ""
|
|
});
|
|
const accentColor = this.plugin.app.vault.getConfig("accentColor") || "#7d5bed";
|
|
span.setAttr("style", `color: ${accentColor};`);
|
|
pEl.appendChild(span);
|
|
this.display = this.display.bind(this);
|
|
createOverviewSettings(containerEl, this.plugin.settings.defaultOverviewSettings, this.plugin, this.plugin.settings.defaultOverviewSettings, this.display, void 0, void 0, void 0, this);
|
|
}
|
|
};
|
|
var createOrReplaceSetting = (container, section, changedSection, renderSetting) => {
|
|
let sectionContainer = container.querySelector(`.setting-${section}`);
|
|
if (sectionContainer) {
|
|
if (changedSection === section || changedSection === "all") {
|
|
sectionContainer.empty();
|
|
renderSetting(sectionContainer);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
sectionContainer = container.createDiv({
|
|
cls: `setting-${section} overview-setting-item-fv`
|
|
});
|
|
renderSetting(sectionContainer);
|
|
};
|
|
async function createOverviewSettings(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal, changedSection) {
|
|
changedSection = changedSection != null ? changedSection : null;
|
|
createOrReplaceSetting(contentEl, "auto-sync", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Auto sync").setDesc("Choose if the overview should automatically update when you delete, create or rename a file/folder").addToggle((toggle) => toggle.setValue(yaml.autoSync).onChange(async (value) => {
|
|
yaml.autoSync = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal);
|
|
}));
|
|
});
|
|
createOrReplaceSetting(contentEl, "allow-drag-and-drop", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Allow drag and drop").setDesc("Choose if you want to allow drag and drop in the overview").addToggle((toggle) => toggle.setValue(yaml.allowDragAndDrop).onChange(async (value) => {
|
|
yaml.allowDragAndDrop = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal);
|
|
}));
|
|
});
|
|
createOrReplaceSetting(contentEl, "showTitle", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Show the title").setDesc("Choose if the title above the folder overview should be shown").addToggle((toggle) => toggle.setValue(yaml.showTitle).onChange(async (value) => {
|
|
yaml.showTitle = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal);
|
|
}));
|
|
});
|
|
createOrReplaceSetting(contentEl, "title-container-fn", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Title").setDesc(createFragment((frag) => {
|
|
const link = frag.createEl("a", {
|
|
text: "Find more information about the title in the documentation. There is also a list of variables you can use",
|
|
href: "https://lostpaul.github.io/obsidian-folder-notes/Folder%20overview/#title"
|
|
});
|
|
link.target = "_blank";
|
|
})).addText((text) => text.setValue((yaml == null ? void 0 : yaml.title) || "{{folderName}} overview").onChange(async (value) => {
|
|
yaml.title = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
}));
|
|
});
|
|
createOrReplaceSetting(contentEl, "title-size", changedSection, (settingEl) => {
|
|
const MIN_TITLE_SIZE = 1;
|
|
const MAX_TITLE_SIZE = 6;
|
|
new import_obsidian28.Setting(settingEl).setName("Title size").setDesc("The larger the number, the smaller the title will be displayed.").addSlider((slider) => slider.setValue(yaml.titleSize).setLimits(MIN_TITLE_SIZE, MAX_TITLE_SIZE, 1).setDynamicTooltip().onChange(async (value) => {
|
|
yaml.titleSize = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal);
|
|
}));
|
|
});
|
|
createOrReplaceSetting(contentEl, "folder-path", changedSection, (settingEl) => {
|
|
const folderPathSetting = new import_obsidian28.Setting(settingEl).setName("Folder path for the overview").setDesc(createFragment((frag) => {
|
|
frag.appendText("The overview will show the subfolders and files of the folder you choose here. ");
|
|
const link = frag.createEl("a", {
|
|
text: "Find more information about this setting in the documentation.",
|
|
href: "https://lostpaul.github.io/obsidian-folder-notes/Folder%20overview/#folder-path"
|
|
});
|
|
link.target = "_blank";
|
|
})).addSearch((search) => {
|
|
new FolderSuggest2(search.inputEl, plugin, false);
|
|
search.setPlaceholder("Folder path").setValue((yaml == null ? void 0 : yaml.folderPath) || "").onChange(async (value) => {
|
|
const whiteList = [
|
|
"File's parent folder path",
|
|
"Path of folder linked to the file"
|
|
];
|
|
if (value.trim() !== "" && !whiteList.includes(value.trim())) {
|
|
value = (0, import_obsidian28.normalizePath)(value);
|
|
}
|
|
if (!whiteList.includes(value.trim())) {
|
|
const abstractFile = plugin.app.vault.getAbstractFileByPath(value);
|
|
const isFolder = abstractFile instanceof import_obsidian28.TFolder;
|
|
if (!isFolder && value !== "") {
|
|
return;
|
|
}
|
|
}
|
|
yaml.folderPath = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
});
|
|
});
|
|
folderPathSetting.settingEl.classList.add("fn-overview-folder-path");
|
|
});
|
|
createOrReplaceSetting(contentEl, "use-actual-links", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Use actual links").setDesc("Choose if the links in the overview should be showed in the graph view. This requires a second list under the actual overview and which is hidden by default.").addToggle((toggle) => toggle.setValue(yaml.useActualLinks).onChange(async (value) => {
|
|
yaml.useActualLinks = value;
|
|
updateSettings(contentEl, yaml, plugin, yaml.useActualLinks, defaultSettings, el, ctx, file);
|
|
refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal);
|
|
}));
|
|
});
|
|
createOrReplaceSetting(contentEl, "use-wikilinks", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Use wikilinks").setDesc("Choose if the links in the link list should be in wikilink format or markdown link format (e.g., [[link]] vs [link](url)).").addToggle((toggle) => toggle.setValue(yaml.useWikilinks).onChange(async (value) => {
|
|
yaml.useWikilinks = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal);
|
|
}));
|
|
});
|
|
createOrReplaceSetting(contentEl, "hide-folder-overview", changedSection, (settingEl) => {
|
|
const hideOverviewSeting = new import_obsidian28.Setting(settingEl).setName("Hide folder overview").setDesc("Choose if the folder overview should be hidden and instead only the link list should be shown").addToggle((toggle) => toggle.setValue(yaml.hideFolderOverview).onChange(async (value) => {
|
|
yaml.hideFolderOverview = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal);
|
|
}));
|
|
hideOverviewSeting.settingEl.classList.add("fn-hide-overview-setting");
|
|
});
|
|
createOrReplaceSetting(contentEl, "hide-link-list", changedSection, (settingEl) => {
|
|
const hideLinkListSetting = new import_obsidian28.Setting(settingEl).setName("Hide link list").setDesc("Choose if only link list under the folder overview should be shown").addToggle((toggle) => toggle.setValue(yaml.hideLinkList).onChange(async (value) => {
|
|
yaml.hideLinkList = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal);
|
|
}));
|
|
hideLinkListSetting.settingEl.classList.add("fn-hide-link-list-setting");
|
|
});
|
|
createOrReplaceSetting(contentEl, "overview-style", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Overview style").setDesc("Choose the style of the overview (grid style soon)").addDropdown((dropdown) => dropdown.addOption("list", "List").addOption("explorer", "Explorer").setValue((yaml == null ? void 0 : yaml.style) || "list").onChange((value) => {
|
|
yaml.style = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal);
|
|
}));
|
|
});
|
|
createOrReplaceSetting(contentEl, "include-types", changedSection, (settingEl) => {
|
|
var _a, _b;
|
|
const setting = new import_obsidian28.Setting(settingEl);
|
|
setting.setName("Include types");
|
|
const list = new ListComponent2(setting.settingEl, yaml.includeTypes || [], ["markdown", "folder"]);
|
|
list.on("update", (values) => {
|
|
yaml.includeTypes = values;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal, "include-types");
|
|
});
|
|
if ((((_a = yaml == null ? void 0 : yaml.includeTypes) == null ? void 0 : _a.length) || 0) < MAX_INCLUDE_TYPES_FOR_DROPDOWN && !((_b = yaml.includeTypes) == null ? void 0 : _b.includes("all"))) {
|
|
setting.addDropdown((dropdown) => {
|
|
if (!yaml.includeTypes) {
|
|
yaml.includeTypes = plugin instanceof FolderNotesPlugin ? plugin.settings.defaultOverview.includeTypes : plugin.settings.defaultOverviewSettings.includeTypes || [];
|
|
}
|
|
yaml.includeTypes = yaml.includeTypes.map((type) => type.toLowerCase());
|
|
const options = [
|
|
{ value: "markdown", label: "Markdown" },
|
|
{ value: "folder", label: "Folder" },
|
|
{ value: "canvas", label: "Canvas" },
|
|
{ value: "pdf", label: "PDF" },
|
|
{ value: "image", label: "Image" },
|
|
{ value: "audio", label: "Audio" },
|
|
{ value: "video", label: "Video" },
|
|
{ value: "other", label: "All other file types" },
|
|
{ value: "all", label: "All file types" }
|
|
];
|
|
options.forEach((option) => {
|
|
var _a2;
|
|
if (!((_a2 = yaml.includeTypes) == null ? void 0 : _a2.includes(option.value))) {
|
|
dropdown.addOption(option.value, option.label);
|
|
}
|
|
});
|
|
dropdown.addOption("+", "+");
|
|
dropdown.setValue("+");
|
|
dropdown.onChange(async (value) => {
|
|
var _a2;
|
|
if (value === "all") {
|
|
yaml.includeTypes = (_a2 = yaml.includeTypes) == null ? void 0 : _a2.filter((type) => type === "folder");
|
|
list.setValues(yaml.includeTypes);
|
|
}
|
|
await list.addValue(value.toLowerCase());
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal, "include-types");
|
|
});
|
|
});
|
|
}
|
|
});
|
|
createOrReplaceSetting(contentEl, "file-tag", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Disable file tag").setDesc("Choose if the file tag should be shown after the file name").addToggle((toggle) => {
|
|
toggle.setValue(yaml.disableFileTag).onChange(async (value) => {
|
|
yaml.disableFileTag = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
});
|
|
});
|
|
});
|
|
createOrReplaceSetting(contentEl, "show-folder-notes", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Show folder notes").setDesc("Choose if folder notes (the note itself and not the folder name) should be shown in the overview").addToggle((toggle) => toggle.setValue(yaml.showFolderNotes).onChange(async (value) => {
|
|
yaml.showFolderNotes = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
}));
|
|
});
|
|
createOrReplaceSetting(contentEl, "file-depth", changedSection, (settingEl) => {
|
|
const DEFAULT_DEPTH = 2;
|
|
const MAX_DEPTH = 10;
|
|
new import_obsidian28.Setting(settingEl).setName("File depth").setDesc("File & folder = +1 depth").addSlider((slider) => slider.setValue((yaml == null ? void 0 : yaml.depth) || DEFAULT_DEPTH).setLimits(1, MAX_DEPTH, 1).setDynamicTooltip().onChange(async (value) => {
|
|
yaml.depth = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
}));
|
|
});
|
|
createOrReplaceSetting(contentEl, "sort-files", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Sort files by").setDesc("Choose how the files should be sorted").addDropdown((dropdown) => dropdown.addOption("name", "Name").addOption("created", "Created").addOption("modified", "Modified").setValue((yaml == null ? void 0 : yaml.sortBy) || "name").onChange(async (value) => {
|
|
yaml.sortBy = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
})).addDropdown((dropdown) => {
|
|
dropdown.addOption("desc", "Descending").addOption("asc", "Ascending");
|
|
if (yaml.sortByAsc) {
|
|
dropdown.setValue("asc");
|
|
} else {
|
|
dropdown.setValue("desc");
|
|
}
|
|
dropdown.onChange(async (value) => {
|
|
yaml.sortByAsc = value === "asc";
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
});
|
|
});
|
|
});
|
|
createOrReplaceSetting(contentEl, "show-empty-folders", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Show folder names of folders that appear empty in the folder overview").setDesc("Show the names of folders that appear to have no files/folders in the folder overview. That's mostly the case when you set the file depth to 1.").addToggle((toggle) => {
|
|
toggle.setValue(yaml.showEmptyFolders).onChange(async (value) => {
|
|
yaml.showEmptyFolders = value;
|
|
yaml.onlyIncludeSubfolders = false;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal);
|
|
});
|
|
});
|
|
});
|
|
createOrReplaceSetting(contentEl, "show-empty-folders-only-first-level", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Only show empty folders which are on the first level of the folder overview").addToggle((toggle) => {
|
|
toggle.setValue(yaml.onlyIncludeSubfolders).onChange(async (value) => {
|
|
yaml.onlyIncludeSubfolders = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
});
|
|
});
|
|
});
|
|
createOrReplaceSetting(contentEl, "disable-collapse-icon", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Disable collapse icon for folder notes").setDesc("Remove the collapse icon next to the folder name for folder notes when they only contain the folder note itself").addToggle((toggle) => {
|
|
toggle.setValue(yaml.disableCollapseIcon).onChange(async (value) => {
|
|
yaml.disableCollapseIcon = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
});
|
|
});
|
|
});
|
|
createOrReplaceSetting(contentEl, "store-collapse-condition", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Store collapsed condition").setDesc("Choose if the collapsed condition should be stored until you restart Obsidian").addToggle((toggle) => toggle.setValue(yaml.storeFolderCondition).onChange(async (value) => {
|
|
yaml.storeFolderCondition = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
}));
|
|
});
|
|
createOrReplaceSetting(contentEl, "collapse-all-by-default", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Collapse all in the tree by default").setDesc("Collapse every folder in the file explorer in the overview by default").addToggle((toggle) => {
|
|
toggle.setValue(yaml.alwaysCollapse).onChange(async (value) => {
|
|
yaml.alwaysCollapse = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
});
|
|
});
|
|
});
|
|
createOrReplaceSetting(contentEl, "fmtp-integration", changedSection, (settingEl) => {
|
|
new import_obsidian28.Setting(settingEl).setName("Front Matter Title Plugin integration").setDesc("Replace the folder/file name with the title from the Front Matter Title Plugin. This requires the plugin to be installed and enabled.").addToggle((toggle) => toggle.setValue(yaml.fmtpIntegration).onChange(async (value) => {
|
|
yaml.fmtpIntegration = value;
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
}));
|
|
});
|
|
updateSettings(contentEl, yaml, plugin, false, defaultSettings, el, ctx, file);
|
|
}
|
|
function determineVisibleSections(yaml, plugin) {
|
|
var _a;
|
|
let showDisableFileTag = false;
|
|
(_a = yaml.includeTypes) == null ? void 0 : _a.forEach((type) => {
|
|
if (type !== "markdown" && type !== "folder") {
|
|
showDisableFileTag = true;
|
|
}
|
|
});
|
|
if (yaml.includeTypes.length === 0) {
|
|
showDisableFileTag = false;
|
|
}
|
|
return {
|
|
"setting-title-container-fn": yaml.showTitle,
|
|
"setting-title-size": yaml.showTitle,
|
|
"setting-store-collapse-condition": yaml.style === "explorer",
|
|
"setting-file-tag": showDisableFileTag,
|
|
"setting-show-empty-folders": yaml.style === "list",
|
|
"setting-show-empty-folders-only-first-level": yaml.showEmptyFolders && yaml.style === "list",
|
|
"setting-disable-collapse-icon": yaml.style === "explorer",
|
|
"setting-collapse-all-by-default": yaml.style === "explorer",
|
|
"setting-allow-drag-and-drop": yaml.style === "explorer",
|
|
"setting-hide-folder-overview": !yaml.hideLinkList && yaml.useActualLinks,
|
|
"setting-hide-link-list": !yaml.hideFolderOverview && yaml.useActualLinks,
|
|
"setting-use-wikilinks": yaml.useActualLinks,
|
|
"setting-fmtp-integration": !!plugin.app.plugins.getPlugin("obsidian-front-matter-title-plugin")
|
|
};
|
|
}
|
|
async function updateSettings(contentEl, yaml, plugin, addLinkList, defaultSettings, el, ctx, file) {
|
|
const visibleSections = determineVisibleSections(yaml, plugin);
|
|
toggleSections(contentEl, visibleSections);
|
|
if (!yaml.id) {
|
|
plugin.saveSettings();
|
|
if (file === void 0) {
|
|
plugin.updateOverviewView(plugin);
|
|
}
|
|
return;
|
|
}
|
|
if (el && ctx) {
|
|
await updateYaml(plugin, ctx, el, yaml, addLinkList);
|
|
}
|
|
if (file) {
|
|
await updateYamlById(plugin, yaml.id, file, yaml, addLinkList, yaml.isInCallout);
|
|
}
|
|
}
|
|
function refresh(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal, changedSection) {
|
|
if (file) {
|
|
contentEl = contentEl.parentElement;
|
|
}
|
|
display(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal, changedSection);
|
|
}
|
|
function toggleSections(contentEl, sections) {
|
|
Object.entries(sections).forEach(([sectionClass, shouldShow]) => {
|
|
const sectionElements = contentEl.querySelectorAll(`.${sectionClass}`);
|
|
sectionElements.forEach((section) => {
|
|
if (shouldShow && section) {
|
|
section.classList.remove("hide");
|
|
} else {
|
|
section == null ? void 0 : section.classList.add("hide");
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// src/settings/FolderOverviewSettings.ts
|
|
async function renderFolderOverview(settingsTab) {
|
|
const { plugin } = settingsTab;
|
|
const defaultOverviewSettings = plugin.settings.defaultOverview;
|
|
const containerEl = settingsTab.settingsPage;
|
|
containerEl.createEl("h3", { text: "Global settings" });
|
|
new import_obsidian29.Setting(containerEl).setName("Auto-update links without opening the overview").setDesc("If enabled, the links that appear in the graph view will be updated even when you don't have the overview open somewhere.").addToggle((toggle) => toggle.setValue(plugin.settings.fvGlobalSettings.autoUpdateLinks).onChange(async (value) => {
|
|
plugin.settings.fvGlobalSettings.autoUpdateLinks = value;
|
|
await plugin.saveSettings();
|
|
if (value) {
|
|
plugin.fvIndexDB.init(true);
|
|
} else {
|
|
plugin.fvIndexDB.active = false;
|
|
}
|
|
}));
|
|
containerEl.createEl("h3", { text: "Overviews default settings" });
|
|
const pEl = containerEl.createEl("p", {
|
|
text: "Edit the default settings for new folder overviews, ",
|
|
cls: "setting-item-description"
|
|
});
|
|
const span = createSpan({ text: "this won't apply to already existing overviews.", cls: "" });
|
|
const accentColor = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
|
|
span.setAttr("style", `color: ${accentColor};`);
|
|
pEl.appendChild(span);
|
|
void createOverviewSettings(containerEl, defaultOverviewSettings, plugin, plugin.settings.defaultOverview, settingsTab.display, void 0, void 0, void 0, settingsTab);
|
|
}
|
|
|
|
// src/settings/ExcludedFoldersSettings.ts
|
|
var import_obsidian31 = require("obsidian");
|
|
|
|
// src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts
|
|
var import_obsidian30 = require("obsidian");
|
|
|
|
// src/ExcludeFolders/WhitelistFolder.ts
|
|
var WhitelistedFolder = class {
|
|
constructor(path, position, id, plugin) {
|
|
this.enableSync = false;
|
|
this.enableAutoCreate = false;
|
|
this.enableFolderNote = false;
|
|
this.disableCollapsing = false;
|
|
this.showInFolderOverview = false;
|
|
this.hideInFileExplorer = false;
|
|
this.hideInSettings = false;
|
|
this.type = "folder";
|
|
this.id = id || crypto.randomUUID();
|
|
this.path = path;
|
|
this.subFolders = plugin.settings.excludeFolderDefaultSettings.subFolders;
|
|
this.position = position;
|
|
this.string = "";
|
|
}
|
|
};
|
|
|
|
// src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts
|
|
var WhitelistedFoldersSettings = class extends import_obsidian30.Modal {
|
|
constructor(settingsTab) {
|
|
super(settingsTab.app);
|
|
this.plugin = settingsTab.plugin;
|
|
this.settingsTab = settingsTab;
|
|
this.app = settingsTab.app;
|
|
}
|
|
onOpen() {
|
|
const { contentEl } = this;
|
|
contentEl.createEl("h2", { text: "Manage whitelisted folders" });
|
|
new import_obsidian30.Setting(contentEl).setName("Add whitelisted folder").setClass("add-exclude-folder-item").addButton((cb) => {
|
|
cb.setIcon("plus");
|
|
cb.setClass("add-exclude-folder");
|
|
cb.setTooltip("Add whitelisted folder");
|
|
cb.onClick(() => {
|
|
const whitelistedFolder = new WhitelistedFolder("", this.plugin.settings.whitelistFolders.length, void 0, this.plugin);
|
|
addWhitelistFolderListItem(this.plugin.settingsTab, contentEl, whitelistedFolder);
|
|
addWhitelistedFolder(this.plugin, whitelistedFolder);
|
|
this.settingsTab.renderSettingsPage(this.settingsTab.plugin.settings.settingsTab);
|
|
});
|
|
});
|
|
this.plugin.settings.whitelistFolders.sort((a, b) => a.position - b.position).forEach((whitelistedFolder) => {
|
|
var _a, _b;
|
|
if (((_a = whitelistedFolder.string) == null ? void 0 : _a.trim()) !== "" && ((_b = whitelistedFolder.path) == null ? void 0 : _b.trim()) === "") {
|
|
addWhitelistedPatternListItem(this.settingsTab, contentEl, whitelistedFolder);
|
|
} else {
|
|
addWhitelistFolderListItem(this.settingsTab, contentEl, whitelistedFolder);
|
|
}
|
|
});
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/settings/ExcludedFoldersSettings.ts
|
|
async function renderExcludeFolders(settingsTab) {
|
|
const containerEl = settingsTab.settingsPage;
|
|
const manageExcluded = new import_obsidian31.Setting(containerEl).setHeading().setClass("fn-excluded-folder-heading").setName("Manage excluded folders");
|
|
const desc3 = document.createDocumentFragment();
|
|
desc3.append("Add {regex} at the beginning of the folder name to use a regex pattern.", desc3.createEl("br"), "Use * before and after to exclude folders that include the name between the *s.", desc3.createEl("br"), "Use * before the folder name to exclude folders that end with the folder name.", desc3.createEl("br"), "Use * after the folder name to exclude folders that start with the folder name.");
|
|
manageExcluded.setDesc(desc3);
|
|
manageExcluded.infoEl.appendText("The regexes and wildcards are only for the folder name, not the path.");
|
|
manageExcluded.infoEl.createEl("br");
|
|
manageExcluded.infoEl.appendText("If you want to switch to a folder path delete the pattern first.");
|
|
manageExcluded.infoEl.style.color = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
|
|
new import_obsidian31.Setting(containerEl).setName("Whitelisted folders").setDesc("Folders that override the excluded folders/patterns").addButton((cb) => {
|
|
cb.setButtonText("Manage");
|
|
cb.setCta();
|
|
cb.onClick(async () => {
|
|
new WhitelistedFoldersSettings(settingsTab).open();
|
|
});
|
|
});
|
|
new import_obsidian31.Setting(containerEl).setName("Exclude folder default settings").addButton((cb) => {
|
|
cb.setButtonText("Manage");
|
|
cb.setCta();
|
|
cb.onClick(async () => {
|
|
new ExcludedFolderSettings(settingsTab.app, settingsTab.plugin, settingsTab.plugin.settings.excludeFolderDefaultSettings).open();
|
|
});
|
|
});
|
|
new import_obsidian31.Setting(containerEl).setName("Exclude pattern default settings").addButton((cb) => {
|
|
cb.setButtonText("Manage");
|
|
cb.setCta();
|
|
cb.onClick(async () => {
|
|
new PatternSettings(settingsTab.app, settingsTab.plugin, settingsTab.plugin.settings.excludePatternDefaultSettings).open();
|
|
});
|
|
});
|
|
new import_obsidian31.Setting(containerEl).setName("Add excluded folder").setClass("add-exclude-folder-item").addButton((cb) => {
|
|
cb.setIcon("plus");
|
|
cb.setClass("add-exclude-folder");
|
|
cb.setTooltip("Add excluded folder");
|
|
cb.onClick(() => {
|
|
const excludedFolder = new ExcludedFolder("", settingsTab.plugin.settings.excludeFolders.length, void 0, settingsTab.plugin);
|
|
addExcludeFolderListItem(settingsTab, containerEl, excludedFolder);
|
|
addExcludedFolder(settingsTab.plugin, excludedFolder);
|
|
settingsTab.renderSettingsPage(settingsTab.plugin.settings.settingsTab);
|
|
});
|
|
});
|
|
settingsTab.plugin.settings.excludeFolders.filter((folder) => !folder.hideInSettings).sort((a, b) => a.position - b.position).forEach((excludedFolder) => {
|
|
var _a, _b;
|
|
if (((_a = excludedFolder.string) == null ? void 0 : _a.trim()) !== "" && ((_b = excludedFolder.path) == null ? void 0 : _b.trim()) === "") {
|
|
addExcludePatternListItem(settingsTab, containerEl, excludedFolder);
|
|
} else {
|
|
addExcludeFolderListItem(settingsTab, containerEl, excludedFolder);
|
|
}
|
|
});
|
|
}
|
|
|
|
// src/settings/SettingsTab.ts
|
|
var DEFAULT_SETTINGS2 = {
|
|
syncFolderName: true,
|
|
ctrlKey: true,
|
|
altKey: false,
|
|
hideFolderNote: true,
|
|
templatePath: "",
|
|
autoCreate: false,
|
|
autoCreateFocusFiles: true,
|
|
autoCreateForAttachmentFolder: false,
|
|
autoCreateForFiles: false,
|
|
enableCollapsing: false,
|
|
excludeFolders: [],
|
|
whitelistFolders: [],
|
|
showDeleteConfirmation: true,
|
|
underlineFolder: true,
|
|
stopWhitespaceCollapsing: true,
|
|
underlineFolderInPath: true,
|
|
openFolderNoteOnClickInPath: true,
|
|
openInNewTab: false,
|
|
focusExistingTab: false,
|
|
oldFolderNoteName: void 0,
|
|
folderNoteName: "{{folder_name}}",
|
|
folderNoteType: ".md",
|
|
disableFolderHighlighting: false,
|
|
newFolderNoteName: "{{folder_name}}",
|
|
storageLocation: "insideFolder",
|
|
syncDelete: false,
|
|
showRenameConfirmation: true,
|
|
defaultOverview: {
|
|
id: "",
|
|
folderPath: "",
|
|
title: "{{folderName}} overview",
|
|
showTitle: false,
|
|
depth: 3,
|
|
includeTypes: ["folder", "markdown"],
|
|
style: "list",
|
|
disableFileTag: false,
|
|
sortBy: "name",
|
|
sortByAsc: true,
|
|
showEmptyFolders: false,
|
|
onlyIncludeSubfolders: false,
|
|
storeFolderCondition: true,
|
|
showFolderNotes: false,
|
|
disableCollapseIcon: true,
|
|
alwaysCollapse: false,
|
|
autoSync: true,
|
|
allowDragAndDrop: true,
|
|
hideLinkList: true,
|
|
hideFolderOverview: false,
|
|
useActualLinks: false,
|
|
fmtpIntegration: false,
|
|
titleSize: 1,
|
|
isInCallout: false,
|
|
useWikilinks: true
|
|
},
|
|
useSubmenus: true,
|
|
syncMove: true,
|
|
frontMatterTitle: {
|
|
enabled: false,
|
|
explorer: true,
|
|
path: true
|
|
},
|
|
settingsTab: "general",
|
|
supportedFileTypes: ["md", "canvas", "base"],
|
|
boldName: false,
|
|
boldNameInPath: false,
|
|
cursiveName: false,
|
|
cursiveNameInPath: false,
|
|
disableOpenFolderNoteOnClick: false,
|
|
openByClick: true,
|
|
openWithCtrl: false,
|
|
openWithAlt: false,
|
|
excludeFolderDefaultSettings: {
|
|
type: "folder",
|
|
path: "",
|
|
id: crypto.randomUUID(),
|
|
subFolders: true,
|
|
disableSync: true,
|
|
disableAutoCreate: true,
|
|
disableFolderNote: false,
|
|
enableCollapsing: false,
|
|
position: 0,
|
|
excludeFromFolderOverview: false,
|
|
string: "",
|
|
hideInSettings: false,
|
|
detached: false,
|
|
showFolderNote: false
|
|
},
|
|
excludePatternDefaultSettings: {
|
|
type: "pattern",
|
|
path: "",
|
|
id: crypto.randomUUID(),
|
|
subFolders: true,
|
|
disableSync: true,
|
|
disableAutoCreate: true,
|
|
disableFolderNote: false,
|
|
enableCollapsing: false,
|
|
position: 0,
|
|
excludeFromFolderOverview: false,
|
|
string: "",
|
|
hideInSettings: false,
|
|
detached: false,
|
|
showFolderNote: false
|
|
},
|
|
hideCollapsingIcon: false,
|
|
hideCollapsingIconForEmptyFolders: false,
|
|
tabManagerEnabled: true,
|
|
ignoreAttachmentFolder: true,
|
|
deleteFilesAction: "trash",
|
|
openSidebar: {
|
|
mobile: false,
|
|
desktop: true
|
|
},
|
|
highlightFolder: true,
|
|
persistentSettingsTab: {
|
|
afterRestart: true,
|
|
afterChangingTab: true
|
|
},
|
|
firstTimeInsertOverview: true,
|
|
fvGlobalSettings: {
|
|
autoUpdateLinks: false
|
|
},
|
|
hideFolderNoteNameInPath: false
|
|
};
|
|
var SettingsTab2 = class extends import_obsidian32.PluginSettingTab {
|
|
constructor(app, plugin) {
|
|
super(app, plugin);
|
|
this.TABS = {
|
|
GENERAL: {
|
|
name: "General",
|
|
id: "general"
|
|
},
|
|
FOLDER_OVERVIEW: {
|
|
name: "Folder overview",
|
|
id: "folder_overview"
|
|
},
|
|
EXCLUDE_FOLDERS: {
|
|
name: "Exclude folders",
|
|
id: "exclude_folders"
|
|
},
|
|
FILE_EXPLORER: {
|
|
name: "File explorer",
|
|
id: "file_explorer"
|
|
},
|
|
PATH: {
|
|
name: "Path",
|
|
id: "path"
|
|
}
|
|
};
|
|
}
|
|
renderSettingsPage(tabId) {
|
|
this.settingsPage.empty();
|
|
switch (tabId.toLocaleLowerCase()) {
|
|
case this.TABS.GENERAL.id:
|
|
void renderGeneral(this);
|
|
break;
|
|
case this.TABS.FOLDER_OVERVIEW.id:
|
|
void renderFolderOverview(this);
|
|
break;
|
|
case this.TABS.EXCLUDE_FOLDERS.id:
|
|
void renderExcludeFolders(this);
|
|
break;
|
|
case this.TABS.FILE_EXPLORER.id:
|
|
void renderFileExplorer(this);
|
|
break;
|
|
case this.TABS.PATH.id:
|
|
void renderPath(this);
|
|
break;
|
|
}
|
|
}
|
|
display(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab) {
|
|
var _a;
|
|
plugin = (_a = this == null ? void 0 : this.plugin) != null ? _a : plugin;
|
|
if (plugin) {
|
|
plugin.settingsOpened = true;
|
|
}
|
|
settingsTab = this != null ? this : settingsTab;
|
|
const { containerEl } = settingsTab;
|
|
if (plugin && !plugin.settings.persistentSettingsTab.afterChangingTab) {
|
|
plugin.settings.settingsTab = this.TABS.GENERAL.id;
|
|
}
|
|
containerEl.empty();
|
|
const tabBar = containerEl.createEl("nav", { cls: "fn-settings-tab-bar" });
|
|
for (const [tabId, tabInfo] of Object.entries(settingsTab.TABS)) {
|
|
const tabEl = tabBar.createEl("div", { cls: "fn-settings-tab" });
|
|
tabEl.createEl("div", { cls: "fn-settings-tab-name", text: tabInfo.name });
|
|
if (plugin && plugin.settings.settingsTab.toLocaleLowerCase() === tabId.toLocaleLowerCase()) {
|
|
tabEl.addClass("fn-settings-tab-active");
|
|
}
|
|
tabEl.addEventListener("click", () => {
|
|
for (const child of Array.from(tabBar.children)) {
|
|
child.classList.remove("fn-settings-tab-active");
|
|
if (!plugin) {
|
|
return;
|
|
}
|
|
plugin.settings.settingsTab = tabId.toLocaleLowerCase();
|
|
void plugin.saveSettings();
|
|
}
|
|
tabEl.addClass("fn-settings-tab-active");
|
|
if (!settingsTab) {
|
|
return;
|
|
}
|
|
settingsTab.renderSettingsPage(tabId);
|
|
});
|
|
}
|
|
settingsTab.settingsPage = containerEl.createDiv({ cls: "fn-settings-page" });
|
|
if (plugin) {
|
|
if (plugin.settings.persistentSettingsTab) {
|
|
settingsTab.renderSettingsPage(plugin.settings.settingsTab);
|
|
} else {
|
|
settingsTab.renderSettingsPage(this.TABS.GENERAL.id);
|
|
}
|
|
}
|
|
}
|
|
renameFolderNotes() {
|
|
var _a, _b, _c;
|
|
new import_obsidian32.Notice("Starting to update folder notes...");
|
|
const oldTemplate = (_a = this.plugin.settings.oldFolderNoteName) != null ? _a : "{{folder_name}}";
|
|
for (const folder of this.app.vault.getAllLoadedFiles()) {
|
|
if (folder instanceof import_obsidian32.TFolder) {
|
|
const folderNote = getFolderNote(this.plugin, folder.path, void 0, void 0, oldTemplate);
|
|
if (!(folderNote instanceof import_obsidian32.TFile)) {
|
|
continue;
|
|
}
|
|
const folderName = (_b = extractFolderName(oldTemplate, folderNote.basename)) != null ? _b : "";
|
|
const newFolderNoteName = this.plugin.settings.folderNoteName.replace("{{folder_name}}", folderName);
|
|
let newPath = "";
|
|
if (this.plugin.settings.storageLocation === "parentFolder") {
|
|
if (getFolderPathFromString(folder.path).trim() === "/") {
|
|
newPath = `${newFolderNoteName}.${folderNote.extension}`;
|
|
} else {
|
|
newPath = `${(_c = folderNote.parent) == null ? void 0 : _c.path}/${newFolderNoteName}.${folderNote.extension}`;
|
|
}
|
|
} else if (this.plugin.settings.storageLocation === "insideFolder") {
|
|
newPath = `${folder.path}/${newFolderNoteName}.${folderNote.extension}`;
|
|
}
|
|
void this.app.fileManager.renameFile(folderNote, newPath);
|
|
}
|
|
}
|
|
this.plugin.settings.oldFolderNoteName = this.plugin.settings.folderNoteName;
|
|
void this.plugin.saveSettings();
|
|
new import_obsidian32.Notice("Finished updating folder notes");
|
|
}
|
|
switchStorageLocation(oldMethod) {
|
|
new import_obsidian32.Notice("Starting to switch storage location...");
|
|
this.app.vault.getAllLoadedFiles().forEach((file) => {
|
|
if (file instanceof import_obsidian32.TFolder) {
|
|
const folderNote = getFolderNote(this.plugin, file.path, oldMethod);
|
|
if (folderNote instanceof import_obsidian32.TFile) {
|
|
if (this.plugin.settings.storageLocation === "parentFolder") {
|
|
let newPath = "";
|
|
if (getFolderPathFromString(file.path).trim() === "") {
|
|
newPath = `${folderNote.name}`;
|
|
} else {
|
|
newPath = `${getFolderPathFromString(file.path)}/${folderNote.name}`;
|
|
}
|
|
void this.plugin.app.fileManager.renameFile(folderNote, newPath);
|
|
} else if (this.plugin.settings.storageLocation === "insideFolder") {
|
|
if (getFolderPathFromString(folderNote.path) === file.path) {
|
|
return;
|
|
}
|
|
const newPath = `${file.path}/${folderNote.name}`;
|
|
void this.plugin.app.fileManager.renameFile(folderNote, newPath);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
new import_obsidian32.Notice("Finished switching storage location");
|
|
}
|
|
onClose() {
|
|
this.plugin.settingsOpened = false;
|
|
}
|
|
};
|
|
|
|
// src/Commands.ts
|
|
var import_obsidian33 = require("obsidian");
|
|
var Commands = class {
|
|
constructor(app, plugin) {
|
|
this.plugin = plugin;
|
|
this.app = app;
|
|
}
|
|
registerCommands() {
|
|
this.editorCommands();
|
|
this.fileCommands();
|
|
this.regularCommands();
|
|
}
|
|
regularCommands() {
|
|
this.plugin.addCommand({
|
|
id: "turn-into-folder-note",
|
|
name: "Use this file as the folder note for its parent folder",
|
|
checkCallback: (checking) => {
|
|
const file = this.app.workspace.getActiveFile();
|
|
if (!(file instanceof import_obsidian33.TFile))
|
|
return false;
|
|
const folder = file.parent;
|
|
if (!folder || !(folder instanceof import_obsidian33.TFolder))
|
|
return false;
|
|
if (folder.path === "" || folder.path === "/")
|
|
return false;
|
|
const folderNote = getFolderNote(this.plugin, folder.path);
|
|
if (folderNote instanceof import_obsidian33.TFile && folderNote === file)
|
|
return false;
|
|
if (checking)
|
|
return true;
|
|
void turnIntoFolderNote(this.plugin, file, folder, folderNote);
|
|
}
|
|
});
|
|
this.plugin.addCommand({
|
|
id: "create-folder-note",
|
|
name: "Make a folder with this file as its folder note",
|
|
callback: async () => {
|
|
var _a, _b, _c;
|
|
const file = this.app.workspace.getActiveFile();
|
|
if (!(file instanceof import_obsidian33.TFile))
|
|
return;
|
|
let newPath = ((_a = file.parent) == null ? void 0 : _a.path) + "/" + file.basename;
|
|
if (((_b = file.parent) == null ? void 0 : _b.path) === "" || ((_c = file.parent) == null ? void 0 : _c.path) === "/") {
|
|
newPath = file.basename;
|
|
}
|
|
if (this.plugin.app.vault.getAbstractFileByPath(newPath)) {
|
|
return new import_obsidian33.Notice("Folder already exists");
|
|
}
|
|
const automaticallyCreateFolderNote = this.plugin.settings.autoCreate;
|
|
this.plugin.settings.autoCreate = false;
|
|
void this.plugin.saveSettings();
|
|
await this.plugin.app.vault.createFolder(newPath);
|
|
const folder = this.plugin.app.vault.getAbstractFileByPath(newPath);
|
|
if (!(folder instanceof import_obsidian33.TFolder))
|
|
return;
|
|
await createFolderNote(this.plugin, folder.path, true, "." + file.extension, false, file);
|
|
this.plugin.settings.autoCreate = automaticallyCreateFolderNote;
|
|
void this.plugin.saveSettings();
|
|
}
|
|
});
|
|
this.plugin.addCommand({
|
|
id: "create-folder-note-for-current-folder",
|
|
name: "Create Markdown folder note for this folder",
|
|
checkCallback: (checking) => {
|
|
const file = this.app.workspace.getActiveFile();
|
|
if (!(file instanceof import_obsidian33.TFile))
|
|
return false;
|
|
const folder = file.parent;
|
|
if (!(folder instanceof import_obsidian33.TFolder))
|
|
return false;
|
|
if (folder.path === "" || folder.path === "/")
|
|
return false;
|
|
if (checking)
|
|
return true;
|
|
void createFolderNote(this.plugin, folder.path, true, ".md", false);
|
|
}
|
|
});
|
|
this.plugin.settings.supportedFileTypes.forEach((fileType) => {
|
|
if (fileType === "md")
|
|
return;
|
|
this.plugin.addCommand({
|
|
id: `create-${fileType}-folder-note-for-current-folder`,
|
|
name: `Create ${fileType} folder note for this folder`,
|
|
checkCallback: (checking) => {
|
|
const file = this.app.workspace.getActiveFile();
|
|
if (!(file instanceof import_obsidian33.TFile))
|
|
return false;
|
|
const folder = file.parent;
|
|
if (!(folder instanceof import_obsidian33.TFolder))
|
|
return false;
|
|
if (folder.path === "" || folder.path === "/")
|
|
return false;
|
|
if (checking)
|
|
return true;
|
|
void createFolderNote(this.plugin, folder.path, true, "." + fileType, false);
|
|
}
|
|
});
|
|
});
|
|
this.plugin.settings.supportedFileTypes.forEach((fileType) => {
|
|
const type = fileType === "md" ? "markdown" : fileType;
|
|
this.plugin.addCommand({
|
|
id: `create-${type}-folder-note-for-active-file-explorer-folder`,
|
|
name: `Create ${type} folder note for current active folder in file explorer`,
|
|
checkCallback: (checking) => {
|
|
const folder = getFileExplorerActiveFolder(this.plugin);
|
|
if (!folder)
|
|
return false;
|
|
const folderNote = getFolderNote(this.plugin, folder.path);
|
|
if (folderNote instanceof import_obsidian33.TFile)
|
|
return false;
|
|
if (checking)
|
|
return true;
|
|
const ext = "." + fileType;
|
|
const { path } = folder;
|
|
void createFolderNote(this.plugin, path, true, ext, false);
|
|
}
|
|
});
|
|
});
|
|
this.plugin.addCommand({
|
|
id: "delete-folder-note-for-current-folder",
|
|
name: "Delete this folder's linked note",
|
|
checkCallback: (checking) => {
|
|
const file = this.app.workspace.getActiveFile();
|
|
if (!(file instanceof import_obsidian33.TFile))
|
|
return false;
|
|
const folder = file.parent;
|
|
if (!(folder instanceof import_obsidian33.TFolder))
|
|
return false;
|
|
const folderNote = getFolderNote(this.plugin, folder.path);
|
|
if (!(folderNote instanceof import_obsidian33.TFile))
|
|
return false;
|
|
if (checking)
|
|
return true;
|
|
void deleteFolderNote(this.plugin, folderNote, true);
|
|
}
|
|
});
|
|
this.plugin.addCommand({
|
|
id: "delete-folder-note-of-active-file-explorer-folder",
|
|
name: "Delete folder note of current active folder in file explorer",
|
|
checkCallback: (checking) => {
|
|
const folder = getFileExplorerActiveFolder(this.plugin);
|
|
if (!folder)
|
|
return false;
|
|
const folderNote = getFolderNote(this.plugin, folder.path);
|
|
if (!(folderNote instanceof import_obsidian33.TFile))
|
|
return false;
|
|
if (checking)
|
|
return true;
|
|
void deleteFolderNote(this.plugin, folderNote, true);
|
|
}
|
|
});
|
|
this.plugin.addCommand({
|
|
id: "open-folder-note-for-current-folder",
|
|
name: "Open this folder's linked note",
|
|
checkCallback: (checking) => {
|
|
const file = this.app.workspace.getActiveFile();
|
|
if (!(file instanceof import_obsidian33.TFile))
|
|
return false;
|
|
const folder = file.parent;
|
|
if (!(folder instanceof import_obsidian33.TFolder))
|
|
return false;
|
|
const folderNote = getFolderNote(this.plugin, folder.path);
|
|
if (!(folderNote instanceof import_obsidian33.TFile))
|
|
return false;
|
|
if (checking)
|
|
return true;
|
|
void openFolderNote(this.plugin, folderNote);
|
|
}
|
|
});
|
|
this.plugin.addCommand({
|
|
id: "open-folder-note-of-active-file-explorer-folder",
|
|
name: "Open folder note of current active folder in file explorer",
|
|
checkCallback: (checking) => {
|
|
const folder = getFileExplorerActiveFolder(this.plugin);
|
|
if (!folder)
|
|
return false;
|
|
const folderNote = getFolderNote(this.plugin, folder.path);
|
|
if (!(folderNote instanceof import_obsidian33.TFile))
|
|
return false;
|
|
if (checking)
|
|
return true;
|
|
void openFolderNote(this.plugin, folderNote);
|
|
}
|
|
});
|
|
this.plugin.addCommand({
|
|
id: "create-folder-note-from-selected-text",
|
|
name: "Create folder note from selection",
|
|
editorCheckCallback: (checking, editor, view) => {
|
|
const text = editor.getSelection().trim();
|
|
const { file } = view;
|
|
if (!(file instanceof import_obsidian33.TFile))
|
|
return false;
|
|
if (text && text.trim() !== "") {
|
|
if (checking) {
|
|
return true;
|
|
}
|
|
const blacklist = ["*", "\\", '"', "/", "<", ">", "?", "|", ":"];
|
|
for (const char of blacklist) {
|
|
if (text.includes(char)) {
|
|
new import_obsidian33.Notice('File name cannot contain any of the following characters: * " \\ / < > : | ?');
|
|
return false;
|
|
}
|
|
}
|
|
if (text.endsWith(".")) {
|
|
new import_obsidian33.Notice("File name cannot end with a dot");
|
|
return;
|
|
}
|
|
let folder;
|
|
const folderPath = getFolderPathFromString(file.path);
|
|
if (folderPath === "") {
|
|
folder = this.plugin.app.vault.getAbstractFileByPath(text);
|
|
if (folder instanceof import_obsidian33.TFolder) {
|
|
new import_obsidian33.Notice("Folder note already exists");
|
|
return false;
|
|
}
|
|
void this.plugin.app.vault.createFolder(text);
|
|
void createFolderNote(this.plugin, text, false);
|
|
} else {
|
|
const folderFullPath = folderPath + "/" + text;
|
|
folder = this.plugin.app.vault.getAbstractFileByPath(folderFullPath);
|
|
if (folder instanceof import_obsidian33.TFolder) {
|
|
new import_obsidian33.Notice("Folder note already exists");
|
|
return false;
|
|
}
|
|
if (this.plugin.settings.storageLocation === "parentFolder") {
|
|
if (this.app.vault.getAbstractFileByPath(folderPath + "/" + text + this.plugin.settings.folderNoteType)) {
|
|
new import_obsidian33.Notice("File already exists");
|
|
return false;
|
|
}
|
|
}
|
|
void this.plugin.app.vault.createFolder(folderPath + "/" + text);
|
|
void createFolderNote(this.plugin, folderPath + "/" + text, false);
|
|
}
|
|
const { folderNoteName } = this.plugin.settings;
|
|
const fileName = folderNoteName.replace("{{folder_name}}", text);
|
|
if (fileName !== text) {
|
|
editor.replaceSelection(`[[${fileName}]]`);
|
|
} else {
|
|
editor.replaceSelection(`[[${fileName}|${text}]]`);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
fileCommands() {
|
|
this.plugin.registerEvent(this.app.workspace.on("file-menu", (menu, file) => {
|
|
var _a, _b, _c;
|
|
let folder = file.parent;
|
|
if (file instanceof import_obsidian33.TFile) {
|
|
if (this.plugin.settings.storageLocation === "insideFolder") {
|
|
folder = file.parent;
|
|
} else {
|
|
const { folderNoteName } = this.plugin.settings;
|
|
const fileName = extractFolderName(folderNoteName, file.basename);
|
|
if (fileName) {
|
|
if (((_a = file.parent) == null ? void 0 : _a.path) === "" || ((_b = file.parent) == null ? void 0 : _b.path) === "/") {
|
|
folder = this.plugin.app.vault.getAbstractFileByPath(fileName);
|
|
} else {
|
|
folder = this.plugin.app.vault.getAbstractFileByPath(((_c = file.parent) == null ? void 0 : _c.path) + "/" + fileName);
|
|
}
|
|
}
|
|
}
|
|
if (folder instanceof import_obsidian33.TFolder) {
|
|
const folderNote = getFolderNote(this.plugin, folder.path);
|
|
const excludedFolder = getExcludedFolder(this.plugin, folder.path, true);
|
|
if ((folderNote == null ? void 0 : folderNote.path) === file.path && !(excludedFolder == null ? void 0 : excludedFolder.detached)) {
|
|
return;
|
|
}
|
|
} else if (file.parent instanceof import_obsidian33.TFolder) {
|
|
folder = file.parent;
|
|
}
|
|
}
|
|
const addFolderNoteActions = (folderMenu) => {
|
|
if (file instanceof import_obsidian33.TFile) {
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Create folder note");
|
|
item.setIcon("edit");
|
|
item.onClick(async () => {
|
|
if (!folder)
|
|
return;
|
|
let newPath = folder.path + "/" + file.basename;
|
|
if (folder.path === "" || folder.path === "/") {
|
|
newPath = file.basename;
|
|
}
|
|
if (this.plugin.app.vault.getAbstractFileByPath(newPath)) {
|
|
return new import_obsidian33.Notice("Folder already exists");
|
|
}
|
|
const automaticallyCreateFolderNote = this.plugin.settings.autoCreate;
|
|
this.plugin.settings.autoCreate = false;
|
|
void this.plugin.saveSettings();
|
|
await this.plugin.app.vault.createFolder(newPath);
|
|
const newFolder = this.plugin.app.vault.getAbstractFileByPath(newPath);
|
|
if (!(newFolder instanceof import_obsidian33.TFolder))
|
|
return;
|
|
await createFolderNote(this.plugin, newFolder.path, true, "." + file.extension, false, file);
|
|
this.plugin.settings.autoCreate = automaticallyCreateFolderNote;
|
|
void this.plugin.saveSettings();
|
|
});
|
|
});
|
|
if (getFolderPathFromString(file.path) === "")
|
|
return;
|
|
if (!(folder instanceof import_obsidian33.TFolder))
|
|
return;
|
|
if (folder.path === "" || folder.path === "/")
|
|
return;
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle(`Turn into folder note for ${folder == null ? void 0 : folder.name}`);
|
|
item.setIcon("edit");
|
|
item.onClick(() => {
|
|
if (!folder || !(folder instanceof import_obsidian33.TFolder))
|
|
return;
|
|
const folderNote2 = getFolderNote(this.plugin, folder.path);
|
|
void turnIntoFolderNote(this.plugin, file, folder, folderNote2);
|
|
});
|
|
});
|
|
}
|
|
if (!(file instanceof import_obsidian33.TFolder))
|
|
return;
|
|
const excludedFolder = getExcludedFolder(this.plugin, file.path, false);
|
|
const detachedExcludedFolder = getDetachedFolder(this.plugin, file.path);
|
|
if (excludedFolder && !excludedFolder.hideInSettings) {
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Remove folder from excluded folders");
|
|
item.setIcon("trash");
|
|
item.onClick(() => {
|
|
this.plugin.settings.excludeFolders = this.plugin.settings.excludeFolders.filter((excluded) => excluded.path !== file.path || excluded.detached);
|
|
void this.plugin.saveSettings(true);
|
|
new import_obsidian33.Notice("Successfully removed folder from excluded folders");
|
|
});
|
|
});
|
|
return;
|
|
}
|
|
if (detachedExcludedFolder) {
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Remove folder from detached folders");
|
|
item.setIcon("trash");
|
|
item.onClick(() => {
|
|
void deleteExcludedFolder(this.plugin, detachedExcludedFolder);
|
|
});
|
|
});
|
|
}
|
|
if (detachedExcludedFolder) {
|
|
return;
|
|
}
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Exclude folder from folder notes");
|
|
item.setIcon("x-circle");
|
|
item.onClick(() => {
|
|
const newExcludedFolder = new ExcludedFolder(file.path, this.plugin.settings.excludeFolders.length, void 0, this.plugin);
|
|
this.plugin.settings.excludeFolders.push(newExcludedFolder);
|
|
void this.plugin.saveSettings(true);
|
|
new import_obsidian33.Notice("Successfully excluded folder from folder notes");
|
|
});
|
|
});
|
|
if (!(file instanceof import_obsidian33.TFolder))
|
|
return;
|
|
const folderNote = getFolderNote(this.plugin, file.path);
|
|
if (folderNote instanceof import_obsidian33.TFile && !detachedExcludedFolder) {
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Delete folder note");
|
|
item.setIcon("trash");
|
|
item.onClick(() => {
|
|
void deleteFolderNote(this.plugin, folderNote, true);
|
|
});
|
|
});
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Open folder note");
|
|
item.setIcon("chevron-right-square");
|
|
item.onClick(() => {
|
|
void openFolderNote(this.plugin, folderNote);
|
|
});
|
|
});
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Detach folder note");
|
|
item.setIcon("unlink");
|
|
item.onClick(() => {
|
|
detachFolderNote(this.plugin, folderNote);
|
|
});
|
|
});
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Copy Obsidian URL");
|
|
item.setIcon("link");
|
|
item.onClick(() => {
|
|
this.app.copyObsidianUrl(folderNote);
|
|
});
|
|
});
|
|
if (this.plugin.settings.hideFolderNote) {
|
|
if (excludedFolder == null ? void 0 : excludedFolder.showFolderNote) {
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Hide folder note in explorer");
|
|
item.setIcon("eye-off");
|
|
item.onClick(() => {
|
|
hideFolderNoteInFileExplorer(file.path, this.plugin);
|
|
});
|
|
});
|
|
} else {
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Show folder note in explorer");
|
|
item.setIcon("eye");
|
|
item.onClick(() => {
|
|
showFolderNoteInFileExplorer(file.path, this.plugin);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Create Markdown folder note");
|
|
item.setIcon("edit");
|
|
item.onClick(() => {
|
|
void createFolderNote(this.plugin, file.path, true, ".md");
|
|
});
|
|
});
|
|
this.plugin.settings.supportedFileTypes.forEach((fileType) => {
|
|
if (fileType === "md")
|
|
return;
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle(`Create ${fileType} folder note`);
|
|
item.setIcon("edit");
|
|
item.onClick(() => {
|
|
void createFolderNote(this.plugin, file.path, true, "." + fileType);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
};
|
|
if (import_obsidian33.Platform.isDesktop && !import_obsidian33.Platform.isTablet && this.plugin.settings.useSubmenus) {
|
|
menu.addItem(async (item) => {
|
|
item.setTitle("Folder note commands").setIcon("folder-edit");
|
|
let subMenu = item.setSubmenu();
|
|
addFolderNoteActions(subMenu);
|
|
});
|
|
} else {
|
|
addFolderNoteActions(menu);
|
|
}
|
|
}));
|
|
}
|
|
editorCommands() {
|
|
this.plugin.registerEvent(this.plugin.app.workspace.on("editor-menu", (menu, editor, view) => {
|
|
const text = editor.getSelection().trim();
|
|
if (!text || text.trim() === "")
|
|
return;
|
|
menu.addItem((item) => {
|
|
item.setTitle("Create folder note").setIcon("edit").onClick(() => {
|
|
const { file } = view;
|
|
if (!(file instanceof import_obsidian33.TFile))
|
|
return;
|
|
const blacklist = ["*", "\\", '"', "/", "<", ">", "?", "|", ":"];
|
|
for (const char of blacklist) {
|
|
if (text.includes(char)) {
|
|
new import_obsidian33.Notice('File name cannot contain any of the following characters: * " \\ / < > : | ?');
|
|
return;
|
|
}
|
|
}
|
|
if (text.endsWith(".")) {
|
|
new import_obsidian33.Notice("File name cannot end with a dot");
|
|
return;
|
|
}
|
|
let folder;
|
|
const folderPath = getFolderPathFromString(file.path);
|
|
const { folderNoteName } = this.plugin.settings;
|
|
const fileName = folderNoteName.replace("{{folder_name}}", text);
|
|
if (folderPath === "") {
|
|
folder = this.plugin.app.vault.getAbstractFileByPath(text);
|
|
if (folder instanceof import_obsidian33.TFolder) {
|
|
return new import_obsidian33.Notice("Folder note already exists");
|
|
}
|
|
void this.plugin.app.vault.createFolder(text);
|
|
void createFolderNote(this.plugin, text, false);
|
|
} else {
|
|
folder = this.plugin.app.vault.getAbstractFileByPath(folderPath + "/" + text);
|
|
if (folder instanceof import_obsidian33.TFolder) {
|
|
return new import_obsidian33.Notice("Folder note already exists");
|
|
}
|
|
if (this.plugin.settings.storageLocation === "parentFolder") {
|
|
if (this.app.vault.getAbstractFileByPath(folderPath + "/" + fileName + this.plugin.settings.folderNoteType)) {
|
|
return new import_obsidian33.Notice("File already exists");
|
|
}
|
|
}
|
|
void this.plugin.app.vault.createFolder(folderPath + "/" + text);
|
|
void createFolderNote(this.plugin, folderPath + "/" + text, false);
|
|
}
|
|
if (fileName !== text) {
|
|
editor.replaceSelection(`[[${fileName}]]`);
|
|
} else {
|
|
editor.replaceSelection(`[[${fileName}|${text}]]`);
|
|
}
|
|
});
|
|
});
|
|
}));
|
|
}
|
|
};
|
|
|
|
// src/events/MutationObserver.ts
|
|
var import_obsidian35 = require("obsidian");
|
|
|
|
// src/events/handleClick.ts
|
|
var import_obsidian34 = require("obsidian");
|
|
async function handleViewHeaderClick(event, plugin) {
|
|
if (!plugin.settings.openFolderNoteOnClickInPath)
|
|
return;
|
|
event.stopImmediatePropagation();
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
if (!(event.target instanceof HTMLElement))
|
|
return;
|
|
const folderPath = event.target.getAttribute("data-path");
|
|
if (!folderPath) {
|
|
return;
|
|
}
|
|
if (await isExcludedFolder(event, plugin, folderPath))
|
|
return;
|
|
const folderNote = getFolderNote(plugin, folderPath);
|
|
if (folderNote) {
|
|
await openFolderNote(plugin, folderNote, event).then(() => handleFolderNoteReveal(plugin, folderNote));
|
|
return;
|
|
} else if (event.altKey || import_obsidian34.Keymap.isModEvent(event) === "tab") {
|
|
if (await handleFolderNoteCreation(event, plugin, folderPath))
|
|
return;
|
|
}
|
|
event.target.onclick = null;
|
|
event.target.click();
|
|
}
|
|
async function isExcludedFolder(event, plugin, folderPath) {
|
|
const excludedFolder = getExcludedFolder(plugin, folderPath, true);
|
|
if (excludedFolder == null ? void 0 : excludedFolder.disableFolderNote) {
|
|
event.target.onclick = null;
|
|
event.target.click();
|
|
return true;
|
|
} else if ((excludedFolder == null ? void 0 : excludedFolder.enableCollapsing) || plugin.settings.enableCollapsing) {
|
|
event.target.onclick = null;
|
|
event.target.click();
|
|
}
|
|
return false;
|
|
}
|
|
async function handleFolderNoteReveal(plugin, folderNote) {
|
|
const fileExplorerPlugin = plugin.app.internalPlugins.getEnabledPluginById("file-explorer");
|
|
if (fileExplorerPlugin && import_obsidian34.Platform.isMobile && plugin.settings.openSidebar.mobile) {
|
|
const OPEN_SIDEBAR_DELAY = 200;
|
|
window.setTimeout(() => {
|
|
fileExplorerPlugin.revealInFolder(folderNote);
|
|
}, OPEN_SIDEBAR_DELAY);
|
|
} else if (fileExplorerPlugin && import_obsidian34.Platform.isDesktop && plugin.settings.openSidebar.desktop) {
|
|
fileExplorerPlugin.revealInFolder(folderNote);
|
|
}
|
|
}
|
|
async function handleFolderNoteCreation(event, plugin, folderPath) {
|
|
const usedCtrl = import_obsidian34.Platform.isMacOS ? event.metaKey : event.ctrlKey;
|
|
if (plugin.settings.altKey && event.altKey || usedCtrl && import_obsidian34.Keymap.isModEvent(event) === "tab") {
|
|
await createFolderNote(plugin, folderPath, true, void 0, true);
|
|
addCSSClassToFileExplorerEl(folderPath, "has-folder-note", false, plugin);
|
|
removeCSSClassFromFileExplorerEL(folderPath, "has-not-folder-note", false, plugin);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// src/events/MutationObserver.ts
|
|
var fileExplorerMutationObserver = null;
|
|
function registerFileExplorerObserver(plugin) {
|
|
plugin.app.workspace.onLayoutReady(() => {
|
|
initializeFolderNoteFeatures(plugin);
|
|
initializeBreadcrumbs(plugin);
|
|
});
|
|
plugin.registerEvent(plugin.app.workspace.on("layout-change", () => {
|
|
var _a;
|
|
initializeFolderNoteFeatures(plugin);
|
|
const activeLeaf = (_a = plugin.app.workspace.getActiveFileView()) == null ? void 0 : _a.containerEl;
|
|
if (!activeLeaf)
|
|
return;
|
|
const titleContainer = activeLeaf.querySelector(".view-header-title-container");
|
|
if (!(titleContainer instanceof HTMLElement))
|
|
return;
|
|
updateFolderNamesInPath(plugin, titleContainer);
|
|
}));
|
|
}
|
|
function unregisterFileExplorerObserver() {
|
|
if (fileExplorerMutationObserver) {
|
|
fileExplorerMutationObserver.disconnect();
|
|
fileExplorerMutationObserver = null;
|
|
}
|
|
}
|
|
function initializeFolderNoteFeatures(plugin) {
|
|
initializeAllFolderTitles(plugin);
|
|
observeFolderTitleMutations(plugin);
|
|
}
|
|
function initializeBreadcrumbs(plugin) {
|
|
const titleContainers = activeDocument.querySelectorAll(".view-header-title-container");
|
|
if (!titleContainers.length)
|
|
return;
|
|
titleContainers.forEach((container) => {
|
|
if (!container.instanceOf(HTMLElement))
|
|
return;
|
|
scheduleIdle(() => updateFolderNamesInPath(plugin, container), { timeout: 1e3 });
|
|
});
|
|
}
|
|
function observeFolderTitleMutations(plugin) {
|
|
if (fileExplorerMutationObserver) {
|
|
fileExplorerMutationObserver.disconnect();
|
|
}
|
|
fileExplorerMutationObserver = new MutationObserver((mutations) => {
|
|
for (const mutation of mutations) {
|
|
for (const node of Array.from(mutation.addedNodes)) {
|
|
if (!node.instanceOf(HTMLElement))
|
|
continue;
|
|
processAddedFolders(node, plugin);
|
|
}
|
|
}
|
|
});
|
|
fileExplorerMutationObserver.observe(document, { childList: true, subtree: true });
|
|
}
|
|
function initializeAllFolderTitles(plugin) {
|
|
const allTitles = activeDocument.querySelectorAll(".nav-folder-title-content");
|
|
for (const title of Array.from(allTitles)) {
|
|
const folderTitle = title;
|
|
const folderEl = folderTitle.closest(".nav-folder-title");
|
|
if (!folderEl)
|
|
continue;
|
|
const folderPath = folderEl.getAttribute("data-path") || "";
|
|
setupFolderTitle(folderTitle, plugin, folderPath);
|
|
}
|
|
}
|
|
function processAddedFolders(node, plugin) {
|
|
const titles = [];
|
|
if (node.matches(".nav-folder-title-content")) {
|
|
titles.push(node);
|
|
}
|
|
node.querySelectorAll(".nav-folder-title-content").forEach((el) => {
|
|
titles.push(el);
|
|
});
|
|
titles.forEach((folderTitle) => {
|
|
const folderEl = folderTitle.closest(".nav-folder-title");
|
|
const folderPath = (folderEl == null ? void 0 : folderEl.getAttribute("data-path")) || "";
|
|
const RETRY_TIMEOUT = 50;
|
|
if (!folderEl || !folderPath) {
|
|
window.setTimeout(() => {
|
|
const retryFolderEl = folderTitle.closest(".nav-folder-title");
|
|
const retryFolderPath = (retryFolderEl == null ? void 0 : retryFolderEl.getAttribute("data-path")) || "";
|
|
if (retryFolderEl && retryFolderPath) {
|
|
setupFolderTitle(folderTitle, plugin, retryFolderPath);
|
|
}
|
|
}, RETRY_TIMEOUT);
|
|
return;
|
|
}
|
|
setupFolderTitle(folderTitle, plugin, folderPath);
|
|
});
|
|
}
|
|
async function setupFolderTitle(folderTitle, plugin, folderPath) {
|
|
var _a;
|
|
if (folderTitle.dataset.initialized === "true")
|
|
return;
|
|
if (!folderPath)
|
|
return;
|
|
folderTitle.dataset.initialized = "true";
|
|
await updateCSSClassesForFolder(folderPath, plugin);
|
|
if (plugin.settings.frontMatterTitle.enabled) {
|
|
(_a = plugin.fmtpHandler) == null ? void 0 : _a.fmptUpdateFolderName({ id: "", result: false, path: folderPath, pathOnly: false }, false);
|
|
}
|
|
if (import_obsidian35.Platform.isMobile && plugin.settings.disableOpenFolderNoteOnClick)
|
|
return;
|
|
plugin.registerDomEvent(folderTitle, "pointerover", (event) => {
|
|
plugin.hoveredElement = folderTitle;
|
|
plugin.mouseEvent = event;
|
|
if (!import_obsidian35.Keymap.isModEvent(event))
|
|
return;
|
|
if (!(event.target instanceof HTMLElement))
|
|
return;
|
|
const folderNote = getFolderNote(plugin, folderPath);
|
|
if (!folderNote)
|
|
return;
|
|
plugin.app.workspace.trigger("hover-link", {
|
|
event,
|
|
source: "preview",
|
|
hoverParent: { file: folderNote },
|
|
targetEl: event.target,
|
|
linktext: folderNote.basename,
|
|
sourcePath: folderNote.path
|
|
});
|
|
plugin.hoverLinkTriggered = true;
|
|
});
|
|
plugin.registerDomEvent(folderTitle, "pointerout", () => {
|
|
plugin.hoveredElement = null;
|
|
plugin.mouseEvent = null;
|
|
plugin.hoverLinkTriggered = false;
|
|
});
|
|
}
|
|
async function updateFolderNamesInPath(plugin, titleContainer) {
|
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
const titleParent = titleContainer.querySelector(".view-header-title-parent");
|
|
let path = "";
|
|
const TRAILING_SLASH_LENGTH = 1;
|
|
if ((titleParent == null ? void 0 : titleParent.childNodes.length) === 0) {
|
|
titleContainer.classList.remove("hide-folder-note-title-in-path");
|
|
}
|
|
for (const breadcrumb of Array.from((_a = titleParent == null ? void 0 : titleParent.childNodes) != null ? _a : [])) {
|
|
if (!(breadcrumb instanceof HTMLElement))
|
|
continue;
|
|
if (breadcrumb.classList.contains("view-header-breadcrumb-separator")) {
|
|
if (breadcrumb.nextSibling === null) {
|
|
breadcrumb.classList.add("is-last-separator");
|
|
}
|
|
continue;
|
|
}
|
|
path += (_b = breadcrumb.getAttribute("old-name")) != null ? _b : breadcrumb.innerText.trim();
|
|
path += "/";
|
|
const folderPath = path.slice(0, -TRAILING_SLASH_LENGTH);
|
|
const excludedFolder = getExcludedFolder(plugin, folderPath, true);
|
|
if (excludedFolder == null ? void 0 : excludedFolder.disableFolderNote)
|
|
return;
|
|
const folderNote = getFolderNote(plugin, folderPath);
|
|
const viewHeaderTitle = titleContainer.querySelector(".view-header-title");
|
|
if (viewHeaderTitle && folderNote) {
|
|
const filePath = path + viewHeaderTitle.innerText.trim() + ".md";
|
|
const file = plugin.app.vault.getAbstractFileByPath(filePath);
|
|
const folder = getFolderNoteFolder(plugin, folderNote, (_c = file == null ? void 0 : file.name) != null ? _c : "");
|
|
if (folder && file && file.path === (folderNote == null ? void 0 : folderNote.path) && ((_d = file.parent) == null ? void 0 : _d.path) !== "/") {
|
|
(_e = viewHeaderTitle.parentElement) == null ? void 0 : _e.classList.add("hide-folder-note-title-in-path");
|
|
viewHeaderTitle.classList.add("path-is-folder-note");
|
|
} else {
|
|
(_f = viewHeaderTitle.parentElement) == null ? void 0 : _f.classList.remove("hide-folder-note-title-in-path");
|
|
viewHeaderTitle.classList.remove("path-is-folder-note");
|
|
}
|
|
}
|
|
if (!folderNote)
|
|
return;
|
|
if (folderNote)
|
|
breadcrumb.classList.add("has-folder-note");
|
|
breadcrumb == null ? void 0 : breadcrumb.setAttribute("data-path", path.slice(0, -TRAILING_SLASH_LENGTH));
|
|
if (!breadcrumb.onclick) {
|
|
breadcrumb.addEventListener("click", (e) => {
|
|
handleViewHeaderClick(e, plugin);
|
|
}, { capture: true });
|
|
}
|
|
if (plugin.settings.frontMatterTitle.enabled) {
|
|
(_g = plugin.fmtpHandler) == null ? void 0 : _g.fmptUpdateFolderName({ id: "", result: false, path: folderPath, pathOnly: true, breadcrumb }, true);
|
|
}
|
|
}
|
|
}
|
|
function scheduleIdle(callback, options) {
|
|
const DEFAULT_IDLE_TIMEOUT = 200;
|
|
if ("requestIdleCallback" in window) {
|
|
const windowWithIdle = window;
|
|
windowWithIdle.requestIdleCallback(callback, options);
|
|
} else {
|
|
globalThis.setTimeout(callback, (options == null ? void 0 : options.timeout) || DEFAULT_IDLE_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
// src/events/handleRename.ts
|
|
var import_obsidian36 = require("obsidian");
|
|
function handleRename(file, oldPath, plugin) {
|
|
let folder = file.parent;
|
|
const oldFolder = plugin.app.vault.getAbstractFileByPath(getFolderPathFromString(oldPath));
|
|
if (folder instanceof import_obsidian36.TFolder) {
|
|
if (plugin.isEmptyFolderNoteFolder(folder) && getFolderNote(plugin, folder.path)) {
|
|
addCSSClassToFileExplorerEl(folder.path, "only-has-folder-note", true, plugin);
|
|
} else {
|
|
removeCSSClassFromFileExplorerEL(folder.path, "only-has-folder-note", true, plugin);
|
|
}
|
|
}
|
|
if (oldFolder instanceof import_obsidian36.TFolder) {
|
|
if (plugin.isEmptyFolderNoteFolder(oldFolder) && getFolderNote(plugin, oldFolder.path)) {
|
|
addCSSClassToFileExplorerEl(oldFolder.path, "only-has-folder-note", true, plugin);
|
|
} else {
|
|
removeCSSClassFromFileExplorerEL(oldFolder.path, "only-has-folder-note", true, plugin);
|
|
}
|
|
}
|
|
if (file instanceof import_obsidian36.TFolder) {
|
|
folder = file;
|
|
plugin.tabManager.updateTab(folder.path);
|
|
updateExcludedFolderPath(folder, oldPath, plugin);
|
|
if (isFolderRename(folder, oldPath)) {
|
|
handleFolderRename(folder, oldPath, plugin);
|
|
return;
|
|
}
|
|
return handleFolderMove(folder, oldPath, plugin);
|
|
} else if (file instanceof import_obsidian36.TFile) {
|
|
if (isFileRename(file, oldPath)) {
|
|
handleFileRename(file, oldPath, plugin);
|
|
return;
|
|
}
|
|
handleFileMove(file, oldPath, plugin);
|
|
return;
|
|
}
|
|
}
|
|
function isFileRename(file, oldPath) {
|
|
var _a;
|
|
const oldFolderPath = getFolderPathFromString(oldPath);
|
|
const newFolderPath = (_a = file.parent) == null ? void 0 : _a.path;
|
|
const oldName = getFileNameFromPathString(oldPath);
|
|
const newName = file.name;
|
|
return oldFolderPath === newFolderPath && oldName !== newName;
|
|
}
|
|
function isFolderRename(folder, oldPath) {
|
|
var _a;
|
|
const oldName = getFileNameFromPathString(oldPath);
|
|
const newName = folder.name;
|
|
const oldParent = getFolderPathFromString(oldPath);
|
|
const newParent = (_a = folder.parent) == null ? void 0 : _a.path;
|
|
return oldParent === newParent && oldName !== newName;
|
|
}
|
|
function handleFolderMove(file, oldPath, plugin) {
|
|
var _a;
|
|
if (plugin.settings.storageLocation === "insideFolder") {
|
|
return;
|
|
}
|
|
if (!plugin.settings.syncMove) {
|
|
return;
|
|
}
|
|
const folderNote = getFolderNote(plugin, oldPath, plugin.settings.storageLocation);
|
|
if (!(file instanceof import_obsidian36.TFolder) || !folderNote)
|
|
return;
|
|
const newFolder = plugin.app.vault.getAbstractFileByPath(file.path);
|
|
if (!(newFolder instanceof import_obsidian36.TFolder))
|
|
return;
|
|
let newPath = folderNote.path;
|
|
if (newFolder.path === "/") {
|
|
newPath = folderNote.name;
|
|
} else {
|
|
newPath = `${(_a = newFolder.parent) == null ? void 0 : _a.path}/${folderNote.name}`;
|
|
}
|
|
plugin.app.fileManager.renameFile(folderNote, newPath);
|
|
}
|
|
async function handleFileMove(file, oldPath, plugin) {
|
|
var _a;
|
|
const { folderName, oldFileName, newFolder, excludedFolder, oldFolder, folderNote } = getArgs2(plugin, file, oldPath);
|
|
const isFolderNoteInNewFolder = folderName === (newFolder == null ? void 0 : newFolder.name);
|
|
const fileMovedFromOldFolderNote = oldFolder && oldFolder.name === oldFileName && (newFolder == null ? void 0 : newFolder.path) !== oldFolder.path;
|
|
const isFileWithExistingNote = folderName === (newFolder == null ? void 0 : newFolder.name) && folderNote;
|
|
if (isFileWithExistingNote) {
|
|
renameExistingFolderNote(file, oldPath, plugin, excludedFolder, oldFolder);
|
|
} else if (isFolderNoteInNewFolder) {
|
|
if (excludedFolder == null ? void 0 : excludedFolder.disableFolderNote) {
|
|
return;
|
|
}
|
|
markFileAsFolderNote(file, plugin);
|
|
if (newFolder instanceof import_obsidian36.TFolder) {
|
|
markFolderWithFolderNoteClasses(newFolder, plugin);
|
|
if (((_a = plugin.app.workspace.getActiveFile()) == null ? void 0 : _a.path) === file.path) {
|
|
removeActiveFolder(plugin);
|
|
setActiveFolder(newFolder.path, plugin);
|
|
}
|
|
}
|
|
if (oldFolder instanceof import_obsidian36.TFolder) {
|
|
hideFolderNoteInFileExplorer(oldFolder.path, plugin);
|
|
unmarkFolderAsFolderNote(oldFolder, plugin);
|
|
}
|
|
} else if (fileMovedFromOldFolderNote) {
|
|
unmarkFileAsFolderNote(file, plugin);
|
|
if (oldFolder instanceof import_obsidian36.TFolder) {
|
|
removeActiveFolder(plugin);
|
|
hideFolderNoteInFileExplorer(oldFolder.path, plugin);
|
|
unmarkFolderAsFolderNote(oldFolder, plugin);
|
|
}
|
|
}
|
|
}
|
|
function getArgs2(plugin, file, oldPath) {
|
|
const folderName = extractFolderName(plugin.settings.folderNoteName, file.basename) || file.basename;
|
|
const oldFileName = removeExtension(getFileNameFromPathString(oldPath));
|
|
const newFolder = getFolderNoteFolder(plugin, file, file.basename);
|
|
let excludedFolder = getExcludedFolder(plugin, (newFolder == null ? void 0 : newFolder.path) || "", true);
|
|
const oldFolder = getFolderNoteFolder(plugin, oldPath, oldFileName);
|
|
const folderNote = getFolderNote(plugin, oldPath, plugin.settings.storageLocation, file);
|
|
return {
|
|
folderName,
|
|
oldFileName,
|
|
newFolder,
|
|
excludedFolder,
|
|
oldFolder,
|
|
folderNote
|
|
};
|
|
}
|
|
function renameExistingFolderNote(file, oldPath, plugin, excludedFolder, oldFolder) {
|
|
let excludedFolderExisted = true;
|
|
let disabledSync = false;
|
|
if (!excludedFolder) {
|
|
excludedFolderExisted = false;
|
|
excludedFolder = new ExcludedFolder((oldFolder == null ? void 0 : oldFolder.path) || "", plugin.settings.excludeFolders.length, void 0, plugin);
|
|
addExcludedFolder(plugin, excludedFolder);
|
|
} else if (!excludedFolder.disableSync) {
|
|
disabledSync = false;
|
|
excludedFolder.disableSync = true;
|
|
updateExcludedFolder(plugin, excludedFolder, excludedFolder);
|
|
}
|
|
plugin.app.fileManager.renameFile(file, oldPath).then(() => {
|
|
if (!excludedFolder) {
|
|
return;
|
|
}
|
|
if (!excludedFolderExisted) {
|
|
deleteExcludedFolder(plugin, excludedFolder);
|
|
} else if (!disabledSync) {
|
|
excludedFolder.disableSync = false;
|
|
updateExcludedFolder(plugin, excludedFolder, excludedFolder);
|
|
}
|
|
});
|
|
}
|
|
async function handleFolderRename(file, oldPath, plugin) {
|
|
const fileName = plugin.settings.folderNoteName.replace("{{folder_name}}", file.name);
|
|
const oldFileName = plugin.settings.folderNoteName.replace("{{folder_name}}", getFileNameFromPathString(oldPath));
|
|
if (fileName === oldFileName) {
|
|
return;
|
|
}
|
|
const folderNote = getFolderNote(plugin, oldPath);
|
|
if (!(folderNote instanceof import_obsidian36.TFile))
|
|
return;
|
|
const excludedFolder = getExcludedFolder(plugin, file.path, true);
|
|
if ((excludedFolder == null ? void 0 : excludedFolder.disableSync) && !folderNote) {
|
|
return removeCSSClassFromFileExplorerEL(file.path, "has-folder-note", false, plugin);
|
|
}
|
|
if (!plugin.settings.syncFolderName) {
|
|
return;
|
|
}
|
|
let newPath = "";
|
|
if (plugin.settings.storageLocation === "parentFolder") {
|
|
const parentFolderPath = getFolderPathFromString(file.path);
|
|
const oldParentFolderPath = getFolderPathFromString(oldPath);
|
|
if (parentFolderPath !== oldParentFolderPath) {
|
|
if (!plugin.settings.syncMove) {
|
|
return;
|
|
}
|
|
newPath = `${parentFolderPath}/${fileName}.${folderNote.extension}`;
|
|
} else if (parentFolderPath.trim() === "") {
|
|
folderNote.path = `${folderNote.name}`;
|
|
newPath = `${fileName}.${folderNote.extension}`;
|
|
} else {
|
|
folderNote.path = `${parentFolderPath}/${folderNote.name}`;
|
|
newPath = `${parentFolderPath}/${fileName}.${folderNote.extension}`;
|
|
}
|
|
} else {
|
|
folderNote.path = `${file.path}/${folderNote.name}`;
|
|
newPath = `${file.path}/${fileName}.${folderNote.extension}`;
|
|
}
|
|
plugin.app.fileManager.renameFile(folderNote, newPath);
|
|
}
|
|
async function handleFileRename(file, oldPath, plugin) {
|
|
const oldFileName = removeExtension(getFileNameFromPathString(oldPath));
|
|
const newFileName = file.basename;
|
|
if (oldFileName === newFileName) {
|
|
return;
|
|
}
|
|
const oldFolder = getFolderNoteFolder(plugin, oldPath, oldFileName);
|
|
const folderName = extractFolderName(plugin.settings.folderNoteName, file.basename) || file.basename;
|
|
const oldFolderName = extractFolderName(plugin.settings.folderNoteName, oldFileName) || oldFileName;
|
|
const newFolder = getFolderNoteFolder(plugin, file, file.basename);
|
|
const excludedFolder = getExcludedFolder(plugin, (newFolder == null ? void 0 : newFolder.path) || "", true);
|
|
const detachedExcludedFolder = getDetachedFolder(plugin, (newFolder == null ? void 0 : newFolder.path) || "");
|
|
const folderNote = getFolderNote(plugin, oldPath, plugin.settings.storageLocation, file);
|
|
if (shouldCreateFolderNote(excludedFolder, folderName, newFolder, detachedExcludedFolder)) {
|
|
if (newFolder) {
|
|
handleFolderNoteCreation2(file, newFolder, plugin);
|
|
}
|
|
return;
|
|
}
|
|
if (shouldRemoveFolderNoteClasses(excludedFolder, folderName, newFolder)) {
|
|
handleFolderNoteRemoval(file, newFolder, plugin);
|
|
}
|
|
if ((excludedFolder == null ? void 0 : excludedFolder.disableSync) || !plugin.settings.syncFolderName) {
|
|
return;
|
|
}
|
|
if (folderName === (newFolder == null ? void 0 : newFolder.name) && newFolder) {
|
|
handleSameFolderRename(file, newFolder, oldFolder, plugin);
|
|
return;
|
|
}
|
|
if (shouldRenameFolderOnFileRename(oldFolderName, oldFolder, newFolder, folderNote)) {
|
|
return renameFolderOnFileRename(file, oldPath, oldFolder, plugin);
|
|
}
|
|
}
|
|
async function renameFolderOnFileRename(file, oldPath, oldFolder, plugin) {
|
|
var _a, _b;
|
|
const newFolderName = extractFolderName(plugin.settings.folderNoteName, file.basename);
|
|
if (!newFolderName) {
|
|
removeCSSClassFromFileExplorerEL(oldFolder.path, "has-folder-note", false, plugin);
|
|
removeCSSClassFromFileExplorerEL(file.path, "is-folder-note", false, plugin);
|
|
return;
|
|
} else if (newFolderName === oldFolder.name) {
|
|
addCSSClassToFileExplorerEl(oldFolder.path, "has-folder-note", false, plugin);
|
|
addCSSClassToFileExplorerEl(file.path, "is-folder-note", false, plugin);
|
|
return;
|
|
}
|
|
let newFolderPath = "";
|
|
if (plugin.settings.storageLocation === "insideFolder") {
|
|
if (((_a = oldFolder.parent) == null ? void 0 : _a.path) === "/") {
|
|
newFolderPath = `${newFolderName}`;
|
|
} else {
|
|
newFolderPath = ((_b = oldFolder.parent) == null ? void 0 : _b.path) + "/" + newFolderName;
|
|
}
|
|
} else {
|
|
const parentFolderPath = getFolderPathFromString(file.path);
|
|
if (parentFolderPath.trim() === "" || parentFolderPath.trim() === "/") {
|
|
newFolderPath = `${newFolderName}`;
|
|
} else {
|
|
newFolderPath = `${parentFolderPath}/${newFolderName}`;
|
|
}
|
|
}
|
|
if (plugin.app.vault.getAbstractFileByPath(newFolderPath)) {
|
|
await plugin.app.fileManager.renameFile(file, oldPath);
|
|
new import_obsidian36.Notice("A folder with the same name already exists");
|
|
return;
|
|
}
|
|
plugin.app.fileManager.renameFile(oldFolder, newFolderPath);
|
|
}
|
|
function updateExcludedFolderPath(folder, oldPath, plugin) {
|
|
const excludedFolders = plugin.settings.excludeFolders.filter((excludedFolder) => {
|
|
var _a;
|
|
return (_a = excludedFolder.path) == null ? void 0 : _a.includes(oldPath);
|
|
});
|
|
excludedFolders.forEach((excludedFolder) => {
|
|
if (excludedFolder.path === oldPath) {
|
|
excludedFolder.path = folder.path;
|
|
return;
|
|
}
|
|
if (!excludedFolder.path)
|
|
return;
|
|
const folders = excludedFolder.path.split("/");
|
|
if (folders.length < 1) {
|
|
folders.push(excludedFolder.path);
|
|
}
|
|
folders[folders.indexOf(folder.name)] = folder.name;
|
|
excludedFolder.path = folders.join("/");
|
|
});
|
|
plugin.saveSettings();
|
|
}
|
|
function shouldCreateFolderNote(excludedFolder, folderName, newFolder, detachedExcludedFolder) {
|
|
return !(excludedFolder == null ? void 0 : excludedFolder.disableFolderNote) && folderName === (newFolder == null ? void 0 : newFolder.name) && !detachedExcludedFolder;
|
|
}
|
|
function shouldRemoveFolderNoteClasses(excludedFolder, folderName, newFolder) {
|
|
return (excludedFolder == null ? void 0 : excludedFolder.disableFolderNote) || folderName !== (newFolder == null ? void 0 : newFolder.name);
|
|
}
|
|
function handleFolderNoteCreation2(file, newFolder, plugin) {
|
|
addCSSClassToFileExplorerEl(file.path, "is-folder-note", false, plugin);
|
|
addCSSClassToFileExplorerEl(newFolder.path, "has-folder-note", false, plugin);
|
|
}
|
|
function handleFolderNoteRemoval(file, newFolder, plugin) {
|
|
removeCSSClassFromFileExplorerEL(file.path, "is-folder-note", false, plugin);
|
|
removeCSSClassFromFileExplorerEL((newFolder == null ? void 0 : newFolder.path) || "", "has-folder-note", false, plugin);
|
|
}
|
|
function handleSameFolderRename(file, newFolder, oldFolder, plugin) {
|
|
addCSSClassToFileExplorerEl(file.path, "is-folder-note", false, plugin);
|
|
removeCSSClassFromFileExplorerEL(oldFolder == null ? void 0 : oldFolder.path, "has-folder-note", false, plugin);
|
|
addCSSClassToFileExplorerEl(newFolder.path, "has-folder-note", false, plugin);
|
|
}
|
|
function shouldRenameFolderOnFileRename(oldFolderName, oldFolder, newFolder, folderNote) {
|
|
if (!oldFolder)
|
|
return false;
|
|
const oldFolderAsFolder = oldFolder;
|
|
const newFolderAsFolder = newFolder;
|
|
return oldFolderName === oldFolderAsFolder.name && (newFolderAsFolder == null ? void 0 : newFolderAsFolder.path) === oldFolderAsFolder.path || folderNote !== null && oldFolderName === oldFolderAsFolder.name;
|
|
}
|
|
|
|
// src/events/handleCreate.ts
|
|
var import_obsidian37 = require("obsidian");
|
|
async function handleCreate(file, plugin) {
|
|
if (!plugin.app.workspace.layoutReady)
|
|
return;
|
|
const folder = file.parent;
|
|
if (folder instanceof import_obsidian37.TFolder) {
|
|
if (plugin.isEmptyFolderNoteFolder(folder) && getFolderNote(plugin, folder.path)) {
|
|
addCSSClassToFileExplorerEl(folder.path, "only-has-folder-note", true, plugin);
|
|
} else {
|
|
removeCSSClassFromFileExplorerEL(folder.path, "only-has-folder-note", true, plugin);
|
|
}
|
|
}
|
|
if (file instanceof import_obsidian37.TFile) {
|
|
handleFileCreation(file, plugin);
|
|
} else if (file instanceof import_obsidian37.TFolder && plugin.settings.autoCreate) {
|
|
handleFolderCreation(file, plugin);
|
|
}
|
|
}
|
|
async function handleFileCreation(file, plugin) {
|
|
const folder = getFolder(plugin, file);
|
|
if (!(folder instanceof import_obsidian37.TFolder) && plugin.settings.autoCreateForFiles) {
|
|
if (!file.parent) {
|
|
return;
|
|
}
|
|
const newFolder = await plugin.app.fileManager.createNewFolder(file.parent);
|
|
turnIntoFolderNote(plugin, file, newFolder);
|
|
} else if (folder instanceof import_obsidian37.TFolder) {
|
|
if (folder.children.length >= 1) {
|
|
removeCSSClassFromFileExplorerEL(folder.path, "fn-empty-folder", false, plugin);
|
|
}
|
|
const detachedFolder = getExcludedFolder(plugin, folder.path, true);
|
|
if (detachedFolder) {
|
|
return;
|
|
}
|
|
const folderNote = getFolderNote(plugin, folder.path);
|
|
if (folderNote && folderNote.path === file.path) {
|
|
addCSSClassToFileExplorerEl(folder.path, "has-folder-note", false, plugin);
|
|
addCSSClassToFileExplorerEl(file.path, "is-folder-note", false, plugin);
|
|
} else if (plugin.settings.autoCreateForFiles && !isFileInAttachmentFolder(plugin, file)) {
|
|
if (!plugin.settings.supportedFileTypes.includes(file.extension)) {
|
|
return;
|
|
}
|
|
if (!file.parent) {
|
|
return;
|
|
}
|
|
const newFolder = await plugin.app.fileManager.createNewFolder(file.parent);
|
|
turnIntoFolderNote(plugin, file, newFolder);
|
|
}
|
|
}
|
|
}
|
|
async function handleFolderCreation(folder, plugin) {
|
|
let openFile = plugin.settings.autoCreateFocusFiles;
|
|
const attachmentFolderPath = plugin.app.vault.getConfig("attachmentFolderPath");
|
|
const cleanAttachmentFolderPath = (attachmentFolderPath == null ? void 0 : attachmentFolderPath.replace("./", "")) || "";
|
|
const attachmentsAreInRootFolder = attachmentFolderPath === "./" || attachmentFolderPath === "";
|
|
addCSSClassToFileExplorerEl(folder.path, "fn-empty-folder", false, plugin);
|
|
if (!plugin.settings.autoCreateForAttachmentFolder) {
|
|
if (!attachmentsAreInRootFolder && cleanAttachmentFolderPath === folder.name)
|
|
return;
|
|
} else if (!attachmentsAreInRootFolder && cleanAttachmentFolderPath === folder.name) {
|
|
openFile = false;
|
|
}
|
|
const excludedFolder = getExcludedFolder(plugin, folder.path, true);
|
|
if (excludedFolder == null ? void 0 : excludedFolder.disableAutoCreate)
|
|
return;
|
|
const folderNote = getFolderNote(plugin, folder.path);
|
|
if (folderNote)
|
|
return;
|
|
void createFolderNote(plugin, folder.path, openFile, void 0, true);
|
|
addCSSClassToFileExplorerEl(folder.path, "has-folder-note", false, plugin);
|
|
}
|
|
|
|
// src/events/TabManager.ts
|
|
var import_obsidian38 = require("obsidian");
|
|
var TabManager = class {
|
|
constructor(plugin) {
|
|
this.plugin = plugin;
|
|
this.app = plugin.app;
|
|
}
|
|
resetTabs() {
|
|
if (!this.isEnabled())
|
|
return;
|
|
this.app.workspace.iterateAllLeaves((leaf) => {
|
|
var _a;
|
|
if (!(leaf.view instanceof import_obsidian38.EditableFileView))
|
|
return;
|
|
const file = (_a = leaf.view) == null ? void 0 : _a.file;
|
|
if (!file)
|
|
return;
|
|
leaf.tabHeaderInnerTitleEl.setText(file.basename);
|
|
});
|
|
}
|
|
updateTabs() {
|
|
if (!this.isEnabled())
|
|
return;
|
|
this.app.workspace.iterateAllLeaves((leaf) => {
|
|
var _a;
|
|
if (!(leaf.view instanceof import_obsidian38.EditableFileView))
|
|
return;
|
|
const file = (_a = leaf.view) == null ? void 0 : _a.file;
|
|
if (!file)
|
|
return;
|
|
const folder = getFolder(this.plugin, file);
|
|
if (!folder)
|
|
return;
|
|
leaf.tabHeaderInnerTitleEl.setText(folder.name);
|
|
});
|
|
}
|
|
updateTab(folderPath) {
|
|
if (!this.isEnabled())
|
|
return;
|
|
const folder = this.app.vault.getAbstractFileByPath(folderPath);
|
|
if (!(folder instanceof import_obsidian38.TFolder))
|
|
return;
|
|
const folderNote = getFolderNote(this.plugin, folder.path);
|
|
if (!folderNote)
|
|
return;
|
|
this.app.workspace.iterateAllLeaves((leaf) => {
|
|
var _a;
|
|
if (!(leaf.view instanceof import_obsidian38.EditableFileView))
|
|
return;
|
|
const file = (_a = leaf.view) == null ? void 0 : _a.file;
|
|
if (!file)
|
|
return;
|
|
if (file.path === folderNote.path) {
|
|
leaf.tabHeaderInnerTitleEl.setText(folder.name);
|
|
}
|
|
});
|
|
}
|
|
isEnabled() {
|
|
if (this.plugin.settings.folderNoteName === "{{folder_name}}")
|
|
return false;
|
|
return this.plugin.settings.tabManagerEnabled;
|
|
}
|
|
};
|
|
|
|
// src/events/handleDelete.ts
|
|
var import_obsidian39 = require("obsidian");
|
|
function handleDelete(file, plugin) {
|
|
const folder = plugin.app.vault.getAbstractFileByPath(getFolderPathFromString(file.path));
|
|
if (folder instanceof import_obsidian39.TFolder) {
|
|
if (plugin.isEmptyFolderNoteFolder(folder) && getFolderNote(plugin, folder.path)) {
|
|
addCSSClassToFileExplorerEl(folder.path, "only-has-folder-note", true, plugin);
|
|
} else {
|
|
removeCSSClassFromFileExplorerEL(folder.path, "only-has-folder-note", true, plugin);
|
|
}
|
|
}
|
|
if (file instanceof import_obsidian39.TFile) {
|
|
const folderNoteFolder = getFolder(plugin, file);
|
|
if (!folderNoteFolder) {
|
|
return;
|
|
}
|
|
const folderNote2 = getFolderNote(plugin, folderNoteFolder.path);
|
|
if (folderNote2) {
|
|
return;
|
|
}
|
|
removeCSSClassFromFileExplorerEL(folderNoteFolder.path, "has-folder-note", false, plugin);
|
|
removeCSSClassFromFileExplorerEL(folderNoteFolder.path, "only-has-folder-note", true, plugin);
|
|
hideFolderNoteInFileExplorer(folderNoteFolder.path, plugin);
|
|
}
|
|
if (!(file instanceof import_obsidian39.TFolder)) {
|
|
return;
|
|
}
|
|
const folderNote = getFolderNote(plugin, file.path);
|
|
if (!folderNote) {
|
|
return;
|
|
}
|
|
removeCSSClassFromFileExplorerEL(folderNote.path, "is-folder-note", false, plugin);
|
|
if (!plugin.settings.syncDelete) {
|
|
return;
|
|
}
|
|
deleteFolderNote(plugin, folderNote, false);
|
|
}
|
|
|
|
// src/obsidian-folder-overview/src/Commands.ts
|
|
var import_obsidian40 = require("obsidian");
|
|
function registerOverviewCommands(plugin) {
|
|
plugin.addCommand({
|
|
id: "open-folder-overview-settings",
|
|
name: "Edit folder overview",
|
|
callback: () => {
|
|
plugin.activateOverviewView();
|
|
}
|
|
});
|
|
plugin.addCommand({
|
|
id: "insert-folder-overview",
|
|
name: "Insert folder overview",
|
|
editorCheckCallback: (checking, editor) => {
|
|
const line = editor.getCursor().line;
|
|
const lineText = editor.getLine(line);
|
|
if (lineText.trim() === "" || lineText.trim() === ">") {
|
|
if (!checking) {
|
|
insertOverview(editor, plugin);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
plugin.registerEvent(plugin.app.workspace.on("editor-menu", (menu, editor, _view) => {
|
|
const { line } = editor.getCursor();
|
|
const lineText = editor.getLine(line);
|
|
if (lineText.trim() === "" || lineText.trim() === ">") {
|
|
menu.addItem((item) => {
|
|
item.setTitle("Insert folder overview").setIcon("edit").onClick(() => {
|
|
if (plugin.settings.firstTimeInsertOverview) {
|
|
plugin.settings.firstTimeInsertOverview = false;
|
|
plugin.saveSettings();
|
|
const frag = document.createDocumentFragment();
|
|
const text = document.createTextNode('You can edit the overview using the "Edit folder overview" command from the command palette. To find more about folder overview, check the plugin documentation: ');
|
|
const link = document.createElement("a");
|
|
link.href = "https://lostpaul.github.io/obsidian-folder-notes/Folder%20overview/";
|
|
link.textContent = "https://lostpaul.github.io/obsidian-folder-notes/Folder%20overview/";
|
|
frag.appendChild(text);
|
|
frag.appendChild(link);
|
|
new import_obsidian40.Notice(frag);
|
|
}
|
|
insertOverview(editor, plugin);
|
|
});
|
|
});
|
|
}
|
|
}));
|
|
}
|
|
function insertOverview(editor, plugin) {
|
|
const { line: cursorLine } = editor.getCursor();
|
|
const currentLineText = editor.getLine(cursorLine);
|
|
const json = getDefaultOverviewJson(plugin);
|
|
json.id = crypto.randomUUID();
|
|
const yaml = (0, import_obsidian40.stringifyYaml)(json);
|
|
let overviewBlock = getOverviewBlock(yaml);
|
|
if (shouldUseActualLinks(plugin)) {
|
|
overviewBlock = addLinkSpans(overviewBlock, json.id);
|
|
}
|
|
if (currentLineText.trim() === "") {
|
|
editor.replaceSelection(overviewBlock);
|
|
} else if (currentLineText.trim() === ">") {
|
|
const yamlLines = yaml.split("\n");
|
|
const quotedLines = yamlLines.map((yamlLine) => `> ${yamlLine}`);
|
|
let quotedBlock = `\`\`\`folder-overview
|
|
${quotedLines.join("\n")}\`\`\`
|
|
`;
|
|
if (shouldUseActualLinks(plugin)) {
|
|
quotedBlock = addLinkSpans(quotedBlock, json.id);
|
|
}
|
|
editor.replaceSelection(quotedBlock);
|
|
}
|
|
if (plugin.fvIndexDB.active) {
|
|
const activeFile = plugin.app.workspace.getActiveFile();
|
|
if (activeFile) {
|
|
plugin.fvIndexDB.addNote(activeFile);
|
|
}
|
|
}
|
|
}
|
|
function getDefaultOverviewJson(plugin) {
|
|
const isOverviewPlugin = plugin instanceof FolderOverviewPlugin;
|
|
const defaultSettings = isOverviewPlugin ? plugin.settings.defaultOverviewSettings : plugin.settings.defaultOverview;
|
|
return Object.assign({}, defaultSettings);
|
|
}
|
|
function shouldUseActualLinks(plugin) {
|
|
if (plugin instanceof FolderOverviewPlugin) {
|
|
return plugin.settings.defaultOverviewSettings.useActualLinks;
|
|
}
|
|
return plugin.settings.defaultOverview.useActualLinks;
|
|
}
|
|
function getOverviewBlock(yaml) {
|
|
return `\`\`\`folder-overview
|
|
${yaml}\`\`\`
|
|
`;
|
|
}
|
|
function addLinkSpans(block, id) {
|
|
return `${block}<span class="fv-link-list-start" id="${id}"></span>
|
|
<span class="fv-link-list-end" id="${id}"></span>
|
|
`;
|
|
}
|
|
|
|
// src/obsidian-folder-overview/src/utils/IndexDB.ts
|
|
var import_obsidian41 = require("obsidian");
|
|
var FvIndexDB = class {
|
|
constructor(plugin) {
|
|
this.name = "fn-folder-overview";
|
|
this.version = 1;
|
|
this.storeName = "files";
|
|
this.keyPath = "sourcePath";
|
|
this.active = false;
|
|
this.indexDB = null;
|
|
this.plugin = plugin;
|
|
}
|
|
init(showNotice) {
|
|
this.active = true;
|
|
const openRequest = indexedDB.open(this.name, this.version);
|
|
openRequest.onupgradeneeded = (event) => {
|
|
const target = event.target;
|
|
if (!target)
|
|
return;
|
|
const db = target.result;
|
|
if (!db.objectStoreNames.contains(this.storeName)) {
|
|
db.createObjectStore(this.storeName, { keyPath: this.keyPath });
|
|
}
|
|
this.indexDB = db;
|
|
this.indexFiles(showNotice);
|
|
};
|
|
openRequest.onsuccess = (event) => {
|
|
const target = event.target;
|
|
if (!target)
|
|
return;
|
|
this.indexDB = target.result;
|
|
openRequest.onblocked = (blockedEvent) => {
|
|
console.warn("IndexedDB is blocked:", blockedEvent);
|
|
};
|
|
this.indexDB.onclose = () => {
|
|
this.indexDB = null;
|
|
};
|
|
this.resetDatabase();
|
|
this.indexFiles(showNotice);
|
|
};
|
|
openRequest.onerror = (event) => {
|
|
const target = event.target;
|
|
const error = target == null ? void 0 : target.error;
|
|
if (error && error.name === "VersionError") {
|
|
const deleteRequest = indexedDB.deleteDatabase(this.name);
|
|
deleteRequest.onsuccess = () => {
|
|
this.init(showNotice);
|
|
};
|
|
}
|
|
};
|
|
}
|
|
async indexFiles(showNotice) {
|
|
if (showNotice)
|
|
new import_obsidian41.Notice("Indexing files for folder overview plugin...");
|
|
const files = this.plugin.app.vault.getMarkdownFiles();
|
|
for (const file of files) {
|
|
if (!await hasOverviewYaml(this.plugin, file))
|
|
continue;
|
|
this.addNote(file);
|
|
}
|
|
if (showNotice)
|
|
new import_obsidian41.Notice("Indexed files for folder overview plugin.");
|
|
}
|
|
addNote(note) {
|
|
if (!this.active || !this.indexDB)
|
|
return;
|
|
const transaction = this.indexDB.transaction([this.storeName], "readwrite");
|
|
const store = transaction.objectStore(this.storeName);
|
|
store.put({ sourcePath: note.path });
|
|
}
|
|
removeNote(notePath) {
|
|
if (!this.active || !this.indexDB)
|
|
return;
|
|
const transaction = this.indexDB.transaction([this.storeName], "readwrite");
|
|
const store = transaction.objectStore(this.storeName);
|
|
store.delete(notePath);
|
|
}
|
|
getNote(path) {
|
|
if (!this.active)
|
|
return Promise.resolve(null);
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.indexDB)
|
|
return resolve(null);
|
|
const transaction = this.indexDB.transaction([this.storeName], "readonly");
|
|
const store = transaction.objectStore(this.storeName);
|
|
const request = store.get(path);
|
|
request.onsuccess = (event) => {
|
|
var _a;
|
|
const target = event.target;
|
|
resolve((_a = target == null ? void 0 : target.result) != null ? _a : null);
|
|
};
|
|
request.onerror = (event) => {
|
|
reject(event);
|
|
};
|
|
});
|
|
}
|
|
getAllNotes() {
|
|
if (!this.active)
|
|
return Promise.resolve([]);
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.indexDB)
|
|
return resolve([]);
|
|
const transaction = this.indexDB.transaction([this.storeName], "readonly");
|
|
const store = transaction.objectStore(this.storeName);
|
|
const request = store.getAll();
|
|
request.onsuccess = (event) => {
|
|
var _a;
|
|
const target = event.target;
|
|
const result = (_a = target == null ? void 0 : target.result) != null ? _a : [];
|
|
resolve(result.map((data) => data.sourcePath));
|
|
};
|
|
request.onerror = (event) => {
|
|
reject(event);
|
|
};
|
|
});
|
|
}
|
|
resetDatabase() {
|
|
if (!this.indexDB)
|
|
return;
|
|
const transaction = this.indexDB.transaction([this.storeName], "readwrite");
|
|
const store = transaction.objectStore(this.storeName);
|
|
store.clear();
|
|
}
|
|
};
|
|
|
|
// src/main.ts
|
|
var FolderNotesPlugin = class extends import_obsidian42.Plugin {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.fmtpHandler = null;
|
|
this.hoveredElement = null;
|
|
this.mouseEvent = null;
|
|
this.hoverLinkTriggered = false;
|
|
this.settingsOpened = false;
|
|
this.askModalCurrentlyOpen = false;
|
|
this.updateOverviewView = updateOverviewView;
|
|
this.updateViewDropdown = updateViewDropdown;
|
|
}
|
|
async onload() {
|
|
console.debug("loading folder notes plugin");
|
|
await this.loadSettings();
|
|
this.settingsTab = new SettingsTab2(this.app, this);
|
|
this.addSettingTab(this.settingsTab);
|
|
await this.saveSettings();
|
|
this.fvIndexDB = new FvIndexDB(this);
|
|
this.addSettingCssClasses();
|
|
new Commands(this.app, this).registerCommands();
|
|
registerOverviewCommands(this);
|
|
this.app.workspace.onLayoutReady(() => this.onLayoutReady());
|
|
if (!this.settings.persistentSettingsTab.afterRestart) {
|
|
this.settings.settingsTab = "general";
|
|
}
|
|
this.registerDomEvent(window, "keydown", (event) => {
|
|
var _a;
|
|
const { hoveredElement } = this;
|
|
if (this.hoverLinkTriggered)
|
|
return;
|
|
if (!hoveredElement)
|
|
return;
|
|
if (!import_obsidian42.Keymap.isModEvent(event))
|
|
return;
|
|
const folderPath = ((_a = hoveredElement == null ? void 0 : hoveredElement.parentElement) == null ? void 0 : _a.getAttribute("data-path")) || "";
|
|
const folderNote = getFolderNote(this, folderPath);
|
|
if (!folderNote)
|
|
return;
|
|
this.app.workspace.trigger("hover-link", {
|
|
event: this.mouseEvent,
|
|
source: "preview",
|
|
hoverParent: {
|
|
file: folderNote
|
|
},
|
|
targetEl: hoveredElement,
|
|
linktext: folderNote == null ? void 0 : folderNote.basename,
|
|
sourcePath: folderNote == null ? void 0 : folderNote.path
|
|
});
|
|
this.hoverLinkTriggered = true;
|
|
});
|
|
this.registerEvent(this.app.workspace.on("file-open", (openFile) => {
|
|
removeActiveFolder(this);
|
|
if (!openFile || !openFile.basename) {
|
|
return;
|
|
}
|
|
const folder = getFolder(this, openFile);
|
|
if (!folder) {
|
|
return;
|
|
}
|
|
const excludedFolder = getExcludedFolder(this, folder.path, true);
|
|
if (excludedFolder == null ? void 0 : excludedFolder.disableFolderNote)
|
|
return;
|
|
const folderNote = getFolderNote(this, folder.path);
|
|
if (!folderNote) {
|
|
return;
|
|
}
|
|
if (folderNote.path !== openFile.path) {
|
|
return;
|
|
}
|
|
setActiveFolder(folder.path, this);
|
|
}));
|
|
this.registerEvent(this.app.vault.on("create", (file) => {
|
|
handleCreate(file, this).catch((err) => {
|
|
console.error(err);
|
|
new import_obsidian42.Notice("Error handling file creation");
|
|
});
|
|
this.handleVaultChange();
|
|
}));
|
|
this.registerEvent(this.app.vault.on("rename", (file, oldPath) => {
|
|
handleRename(file, oldPath, this);
|
|
this.handleVaultChange();
|
|
}));
|
|
this.registerEvent(this.app.vault.on("delete", (file) => {
|
|
handleDelete(file, this);
|
|
this.handleVaultChange();
|
|
}));
|
|
this.registerMarkdownCodeBlockProcessor("folder-overview", (source, el, ctx) => {
|
|
this.handleOverviewBlock(source, el, ctx);
|
|
});
|
|
}
|
|
addSettingCssClasses() {
|
|
activeDocument.body.classList.add("folder-notes-plugin");
|
|
if (this.settings.hideFolderNote) {
|
|
activeDocument.body.classList.add("hide-folder-note");
|
|
}
|
|
if (this.settings.hideCollapsingIconForEmptyFolders) {
|
|
activeDocument.body.classList.add("fn-hide-empty-collapse-icon");
|
|
}
|
|
if (this.settings.hideFolderNoteNameInPath) {
|
|
activeDocument.body.classList.add("folder-note-hide-name-path");
|
|
}
|
|
if (this.settings.underlineFolder) {
|
|
activeDocument.body.classList.add("folder-note-underline");
|
|
}
|
|
if (this.settings.boldName) {
|
|
activeDocument.body.classList.add("folder-note-bold");
|
|
}
|
|
if (this.settings.cursiveName) {
|
|
activeDocument.body.classList.add("folder-note-cursive");
|
|
}
|
|
if (this.settings.boldNameInPath) {
|
|
activeDocument.body.classList.add("folder-note-bold-path");
|
|
}
|
|
if (this.settings.cursiveNameInPath) {
|
|
activeDocument.body.classList.add("folder-note-cursive-path");
|
|
}
|
|
if (this.settings.underlineFolderInPath) {
|
|
activeDocument.body.classList.add("folder-note-underline-path");
|
|
}
|
|
if (this.settings.stopWhitespaceCollapsing) {
|
|
activeDocument.body.classList.add("fn-whitespace-stop-collapsing");
|
|
}
|
|
if (this.settings.hideCollapsingIcon) {
|
|
activeDocument.body.classList.add("fn-hide-collapse-icon");
|
|
}
|
|
if (this.settings.ignoreAttachmentFolder) {
|
|
activeDocument.body.classList.add("fn-ignore-attachment-folder");
|
|
}
|
|
if (!this.settings.highlightFolder) {
|
|
activeDocument.body.classList.add("disable-folder-highlight");
|
|
}
|
|
if ((0, import_obsidian42.requireApiVersion)("1.7.2")) {
|
|
activeDocument.body.classList.add("version-1-7-2");
|
|
}
|
|
}
|
|
onLayoutReady() {
|
|
var _a, _b;
|
|
if (!this._loaded) {
|
|
return;
|
|
}
|
|
registerFileExplorerObserver(this);
|
|
const fileExplorer = getFileExplorer(this);
|
|
if (fileExplorer) {
|
|
fileExplorer.view.tree.infinityScroll.rootMargin = 1.5;
|
|
}
|
|
this.registerView(FOLDER_OVERVIEW_VIEW, (leaf2) => {
|
|
return new FolderOverviewView(leaf2, this);
|
|
});
|
|
this.app.workspace.on("layout-change", () => {
|
|
this.tabManager.updateTabs();
|
|
});
|
|
if (this.app.plugins.getPlugin("obsidian-front-matter-title-plugin")) {
|
|
this.fmtpHandler = new FrontMatterTitlePluginHandler(this);
|
|
}
|
|
this.tabManager = new TabManager(this);
|
|
this.tabManager.updateTabs();
|
|
this.registerDomEvent(activeDocument, "click", (evt) => {
|
|
this.handleFileExplorerClick(evt);
|
|
}, true);
|
|
this.registerDomEvent(activeDocument, "auxclick", (evt) => {
|
|
const rightClick = 2;
|
|
if (evt.button === rightClick)
|
|
return;
|
|
this.handleFileExplorerClick(evt);
|
|
}, true);
|
|
const fileExplorerPlugin = this.app.internalPlugins.getEnabledPluginById("file-explorer");
|
|
if (fileExplorerPlugin) {
|
|
const fileExplorer2 = fileExplorerPlugin;
|
|
const originalRevealInFolder = fileExplorer2.revealInFolder.bind(fileExplorer2);
|
|
fileExplorer2.revealInFolder = (file) => {
|
|
if (file instanceof import_obsidian42.TFile) {
|
|
const folder = getFolder(this, file);
|
|
if (folder instanceof import_obsidian42.TFolder) {
|
|
const folderNote = getFolderNote(this, folder.path);
|
|
if (!folderNote || folderNote.path !== file.path) {
|
|
originalRevealInFolder(file);
|
|
return;
|
|
}
|
|
activeDocument.body.classList.remove("hide-folder-note");
|
|
originalRevealInFolder(folder);
|
|
const FOLDER_REVEAL_DELAY = 100;
|
|
window.setTimeout(() => {
|
|
activeDocument.body.classList.add("hide-folder-note");
|
|
}, FOLDER_REVEAL_DELAY);
|
|
return;
|
|
}
|
|
}
|
|
if (file instanceof import_obsidian42.TFolder || file instanceof import_obsidian42.TFile) {
|
|
originalRevealInFolder(file);
|
|
return;
|
|
}
|
|
};
|
|
}
|
|
const leaf = this.app.workspace.getLeavesOfType("markdown").first();
|
|
const view = leaf == null ? void 0 : leaf.view;
|
|
if (!view) {
|
|
return;
|
|
}
|
|
const viewWithEditModes = view;
|
|
const activeEditor = this.app.workspace.activeEditor;
|
|
const editMode = (_b = (_a = viewWithEditModes.editMode) != null ? _a : viewWithEditModes.sourceMode) != null ? _b : activeEditor == null ? void 0 : activeEditor.editMode;
|
|
if (!editMode) {
|
|
return;
|
|
}
|
|
const { clipboardManager } = editMode;
|
|
const clipboardProto = Object.getPrototypeOf(clipboardManager);
|
|
const originalHandleDragOver = clipboardProto.handleDragOver;
|
|
const originalHandleDrop = clipboardProto.handleDrop;
|
|
clipboardProto.handleDragOver = (evt, ...args) => {
|
|
const { dragManager } = clipboardManager.app;
|
|
const draggable = dragManager == null ? void 0 : dragManager.draggable;
|
|
if ((draggable == null ? void 0 : draggable.file) instanceof import_obsidian42.TFolder) {
|
|
const folderNote = getFolderNote(this, draggable.file.path);
|
|
if (folderNote) {
|
|
dragManager.setAction(window.i18next.t("interface.drag-and-drop.insert-link-here"));
|
|
return;
|
|
}
|
|
}
|
|
originalHandleDragOver(evt, ...args);
|
|
};
|
|
clipboardProto.handleDrop = (evt, ...args) => {
|
|
const { dragManager } = clipboardManager.app;
|
|
const draggable = dragManager == null ? void 0 : dragManager.draggable;
|
|
if ((draggable == null ? void 0 : draggable.file) instanceof import_obsidian42.TFolder) {
|
|
const folderNote = getFolderNote(this, draggable.file.path);
|
|
if (folderNote) {
|
|
draggable.file = folderNote;
|
|
draggable.type = "file";
|
|
}
|
|
}
|
|
originalHandleDrop(evt, ...args);
|
|
};
|
|
if (this.settings.fvGlobalSettings.autoUpdateLinks) {
|
|
this.fvIndexDB.init(false);
|
|
}
|
|
}
|
|
handleVaultChange() {
|
|
if (!this.settings.fvGlobalSettings.autoUpdateLinks)
|
|
return;
|
|
const DEBOUNCE_DELAY = 2e3;
|
|
(0, import_obsidian42.debounce)(() => {
|
|
void updateAllOverviews(this);
|
|
}, DEBOUNCE_DELAY, true)();
|
|
}
|
|
handleFileExplorerClick(evt) {
|
|
const target = evt.target;
|
|
if (evt.shiftKey)
|
|
return;
|
|
if (this.isMobileClickDisabled())
|
|
return;
|
|
const { folderTitleEl, onlyClickedOnFolderTitle } = this.getFolderTitleInfo(target);
|
|
if (!folderTitleEl)
|
|
return;
|
|
if (this.shouldIgnoreClickByWhitespaceOrCollapse(target, onlyClickedOnFolderTitle))
|
|
return;
|
|
const folderPath = this.getValidFolderPath(folderTitleEl);
|
|
if (!folderPath)
|
|
return;
|
|
const usedCtrl = this.isCtrlUsed(evt);
|
|
const folderNote = getFolderNote(this, folderPath);
|
|
if (!folderNote && this.shouldCreateNote(evt, usedCtrl)) {
|
|
this.createNoteAndMark(folderPath);
|
|
return;
|
|
}
|
|
if (!(folderNote instanceof import_obsidian42.TFile))
|
|
return;
|
|
if (!this.shouldOpenNote(usedCtrl, evt))
|
|
return;
|
|
if (!this.settings.enableCollapsing || usedCtrl) {
|
|
evt.preventDefault();
|
|
evt.stopImmediatePropagation();
|
|
}
|
|
void openFolderNote(this, folderNote, evt);
|
|
}
|
|
isMobileClickDisabled() {
|
|
return import_obsidian42.Platform.isMobile && this.settings.disableOpenFolderNoteOnClick;
|
|
}
|
|
getFolderTitleInfo(target) {
|
|
const folderTitleEl = target.closest(".nav-folder-title");
|
|
const onlyClickedOnFolderTitle = !!target.closest(".nav-folder-title-content");
|
|
return {
|
|
folderTitleEl: folderTitleEl instanceof HTMLElement ? folderTitleEl : null,
|
|
onlyClickedOnFolderTitle
|
|
};
|
|
}
|
|
shouldIgnoreClickByWhitespaceOrCollapse(target, onlyClickedOnFolderTitle) {
|
|
if (!this.settings.stopWhitespaceCollapsing && !onlyClickedOnFolderTitle)
|
|
return true;
|
|
if (target.closest(".collapse-icon"))
|
|
return true;
|
|
return false;
|
|
}
|
|
getValidFolderPath(folderTitleEl) {
|
|
const folderPath = folderTitleEl.getAttribute("data-path");
|
|
if (!folderPath)
|
|
return null;
|
|
const excludedFolder = getExcludedFolder(this, folderPath, true);
|
|
if (excludedFolder == null ? void 0 : excludedFolder.disableFolderNote)
|
|
return null;
|
|
return folderPath;
|
|
}
|
|
isCtrlUsed(evt) {
|
|
return import_obsidian42.Platform.isMacOS ? evt.metaKey : evt.ctrlKey;
|
|
}
|
|
shouldCreateNote(evt, usedCtrl) {
|
|
const isTabMod = import_obsidian42.Keymap.isModEvent(evt) === "tab";
|
|
if (!(evt.altKey || isTabMod))
|
|
return false;
|
|
return this.settings.altKey && evt.altKey || usedCtrl && this.settings.ctrlKey;
|
|
}
|
|
createNoteAndMark(folderPath) {
|
|
void createFolderNote(this, folderPath, true, void 0, true);
|
|
void addCSSClassToFileExplorerEl(folderPath, "has-folder-note", false, this);
|
|
void removeCSSClassFromFileExplorerEL(folderPath, "has-not-folder-note", false, this);
|
|
}
|
|
shouldOpenNote(usedCtrl, evt) {
|
|
if (this.settings.openWithCtrl && !usedCtrl)
|
|
return false;
|
|
if (this.settings.openWithAlt && !evt.altKey)
|
|
return false;
|
|
return true;
|
|
}
|
|
handleOverviewBlock(source, el, ctx) {
|
|
const observer = new MutationObserver(() => {
|
|
var _a;
|
|
const editButton = (_a = el.parentElement) == null ? void 0 : _a.childNodes.item(1);
|
|
if (editButton) {
|
|
editButton.addEventListener("click", (e) => {
|
|
e.stopImmediatePropagation();
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
new FolderOverviewSettings(this.app, this, (0, import_obsidian42.parseYaml)(source), ctx, el, this.settings.defaultOverview).open();
|
|
}, { capture: true });
|
|
}
|
|
});
|
|
observer.observe(el, {
|
|
childList: true,
|
|
subtree: true
|
|
});
|
|
try {
|
|
if (this.app.workspace.layoutReady) {
|
|
const { defaultOverview } = this.settings;
|
|
const folderOverview = new FolderOverview(this, ctx, source, el, defaultOverview);
|
|
void folderOverview.create(this, el, ctx);
|
|
} else {
|
|
this.app.workspace.onLayoutReady(() => {
|
|
const folderOverview = new FolderOverview(this, ctx, source, el, this.settings.defaultOverview);
|
|
void folderOverview.create(this, el, ctx);
|
|
});
|
|
}
|
|
} catch (e) {
|
|
new import_obsidian42.Notice("Error creating folder overview (folder notes plugin) - check console for more details");
|
|
console.error(e);
|
|
}
|
|
}
|
|
async activateOverviewView() {
|
|
const { workspace } = this.app;
|
|
let leaf = null;
|
|
const leaves = workspace.getLeavesOfType(FOLDER_OVERVIEW_VIEW);
|
|
if (leaves.length > 0) {
|
|
leaf = leaves[0];
|
|
} else {
|
|
leaf = workspace.getRightLeaf(false);
|
|
await (leaf == null ? void 0 : leaf.setViewState({ type: FOLDER_OVERVIEW_VIEW, active: true }));
|
|
}
|
|
if (!leaf)
|
|
return;
|
|
void workspace.revealLeaf(leaf);
|
|
}
|
|
isEmptyFolderNoteFolder(folder) {
|
|
let attachmentFolderPath = this.app.vault.getConfig("attachmentFolderPath");
|
|
const cleanAttachmentFolderPath = (attachmentFolderPath == null ? void 0 : attachmentFolderPath.replace("./", "")) || "";
|
|
const attachmentsAreInRootFolder = attachmentFolderPath === "./" || attachmentFolderPath === "";
|
|
const threshold = this.settings.storageLocation === "insideFolder" ? 1 : 0;
|
|
if (folder.children.length === 0) {
|
|
void addCSSClassToFileExplorerEl(folder.path, "fn-empty-folder", false, this);
|
|
}
|
|
attachmentFolderPath = `${folder.path}/${cleanAttachmentFolderPath}`;
|
|
if (folder.children.length === threshold) {
|
|
void addCSSClassToFileExplorerEl(folder.path, "fn-empty-folder", false, this);
|
|
return true;
|
|
} else if (folder.children.length > threshold) {
|
|
if (attachmentsAreInRootFolder) {
|
|
return false;
|
|
} else if (this.app.vault.getAbstractFileByPath(attachmentFolderPath) instanceof import_obsidian42.TFolder) {
|
|
const attachmentFolder = this.app.vault.getAbstractFileByPath(attachmentFolderPath);
|
|
if (attachmentFolder instanceof import_obsidian42.TFolder && folder.children.length <= threshold + 1) {
|
|
void addCSSClassToFileExplorerEl(folder.path, "fn-empty-folder", false, this);
|
|
void addCSSClassToFileExplorerEl(folder.path, "fn-has-attachment-folder", false, this);
|
|
void addCSSClassToFileExplorerEl(folder.path, "fn-has-attachment-folder", true, this);
|
|
}
|
|
return folder.children.length <= threshold + 1;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
async changeFolderNameInExplorer(folder, newName, waitForCreate = false, count = 0) {
|
|
const MAX_RETRY_COUNT = 5;
|
|
const RETRY_DELAY_MS = 500;
|
|
if (!newName)
|
|
newName = folder.name;
|
|
let fileExplorerItem = getFileExplorerElement(folder.path, this);
|
|
if (!fileExplorerItem) {
|
|
if (waitForCreate && count < MAX_RETRY_COUNT) {
|
|
await new Promise((resolve) => window.setTimeout(resolve, RETRY_DELAY_MS));
|
|
void this.changeFolderNameInExplorer(folder, newName, waitForCreate, count + 1);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
fileExplorerItem = fileExplorerItem == null ? void 0 : fileExplorerItem.querySelector("div.nav-folder-title-content");
|
|
if (!fileExplorerItem) {
|
|
return;
|
|
}
|
|
if (this.settings.frontMatterTitle.explorer && this.settings.frontMatterTitle.enabled) {
|
|
fileExplorerItem.innerText = newName;
|
|
fileExplorerItem.setAttribute("old-name", folder.name);
|
|
} else {
|
|
fileExplorerItem.innerText = folder.name;
|
|
fileExplorerItem.removeAttribute("old-name");
|
|
}
|
|
}
|
|
async changeFolderNameInPath(folder, newName, breadcrumb) {
|
|
if (!newName)
|
|
newName = folder.name;
|
|
breadcrumb.textContent = folder.newName || folder.name;
|
|
breadcrumb.setAttribute("old-name", folder.name);
|
|
breadcrumb.setAttribute("data-path", folder.path);
|
|
}
|
|
updateAllBreadcrumbs(remove) {
|
|
if (!this.settings.frontMatterTitle.path && !remove) {
|
|
return;
|
|
}
|
|
const viewHeaderItems = activeDocument.querySelectorAll("span.view-header-breadcrumb");
|
|
const files = this.app.vault.getAllLoadedFiles().filter((file) => file instanceof import_obsidian42.TFolder);
|
|
viewHeaderItems.forEach((item) => {
|
|
if (!item.hasAttribute("data-path")) {
|
|
return;
|
|
}
|
|
const path = item.getAttribute("data-path");
|
|
const folder = files.find((file) => file.path === path);
|
|
if (!(folder instanceof import_obsidian42.TFolder)) {
|
|
return;
|
|
}
|
|
if (remove) {
|
|
item.textContent = folder.name;
|
|
item.removeAttribute("old-name");
|
|
} else {
|
|
item.textContent = folder.newName || folder.name;
|
|
item.setAttribute("old-name", folder.name);
|
|
item.setAttribute("data-path", folder.path);
|
|
}
|
|
});
|
|
}
|
|
onunload() {
|
|
unregisterFileExplorerObserver();
|
|
activeDocument.body.classList.remove("folder-notes-plugin");
|
|
activeDocument.body.classList.remove("folder-note-underline");
|
|
activeDocument.body.classList.remove("hide-folder-note");
|
|
activeDocument.body.classList.remove("fn-whitespace-stop-collapsing");
|
|
removeActiveFolder(this);
|
|
if (this.fmtpHandler) {
|
|
this.fmtpHandler.deleteEvent();
|
|
}
|
|
}
|
|
async loadSettings() {
|
|
const data = await this.loadData();
|
|
if (data) {
|
|
if (data.allowWhitespaceCollapsing === true) {
|
|
data.stopWhitespaceCollapsing = false;
|
|
delete data.allowWhitespaceCollapsing;
|
|
} else if (data.allowWhitespaceCollapsing === false) {
|
|
data.stopWhitespaceCollapsing = true;
|
|
delete data.allowWhitespaceCollapsing;
|
|
}
|
|
}
|
|
this.settings = Object.assign({}, DEFAULT_SETTINGS2, data);
|
|
if (!this.settings.oldFolderNoteName) {
|
|
this.settings.oldFolderNoteName = this.settings.folderNoteName;
|
|
}
|
|
if (!data) {
|
|
return;
|
|
}
|
|
const overview = data.defaultOverview;
|
|
if (!overview) {
|
|
return;
|
|
}
|
|
this.settings.defaultOverview = Object.assign({}, DEFAULT_SETTINGS2.defaultOverview, overview);
|
|
}
|
|
async saveSettings(reloadStyles) {
|
|
await this.saveData(this.settings);
|
|
if ((!this.settingsOpened || reloadStyles === true) && reloadStyles !== false) {
|
|
refreshAllFolderStyles(true, this);
|
|
}
|
|
}
|
|
};
|
|
|
|
// src/obsidian-folder-overview/src/utils/LinkList.ts
|
|
function buildLinkListBlock(id, calloutFlag) {
|
|
if (calloutFlag) {
|
|
return '\n> <span class="fv-link-list-start" id="' + id + '"></span>\n> <span class="fv-link-list-end" id="' + id + '"></span>';
|
|
}
|
|
return '\n<span class="fv-link-list-start" id="' + id + '"></span>\n<span class="fv-link-list-end" id="' + id + '"></span>';
|
|
}
|
|
function updateLinkList(files = [], plugin, yaml, pathBlacklist, sourceFile) {
|
|
buildLinkList(files, plugin, yaml, pathBlacklist, sourceFile).then((fileLinks) => {
|
|
plugin.app.vault.process(sourceFile, (text) => {
|
|
const lines = text.split("\n");
|
|
const linkListStart = `${yaml.isInCallout ? "> " : ""}<span class="fv-link-list-start" id="${yaml.id}"></span>`;
|
|
const linkListEnd = `${yaml.isInCallout ? "> " : ""}<span class="fv-link-list-end" id="${yaml.id}"></span>`;
|
|
const startIdx = lines.findIndex((l) => l.trim() === linkListStart);
|
|
const endIdx = lines.findIndex((l) => l.trim() === linkListEnd);
|
|
const NOT_FOUND = -1;
|
|
const linkListExists = startIdx !== NOT_FOUND && endIdx !== NOT_FOUND;
|
|
const isInvalidLinkList = endIdx < startIdx;
|
|
if (!linkListExists || isInvalidLinkList) {
|
|
return text;
|
|
}
|
|
lines.splice(startIdx, endIdx - startIdx + 1);
|
|
const newBlock = [
|
|
linkListStart,
|
|
...fileLinks,
|
|
linkListEnd
|
|
];
|
|
lines.splice(startIdx, 0, ...newBlock);
|
|
return lines.join("\n");
|
|
});
|
|
});
|
|
}
|
|
async function buildLinkList(items, plugin, yaml, pathBlacklist, sourceFile, indent = 0) {
|
|
const result = [];
|
|
const filtered = (await filterFiles(items, plugin, yaml.folderPath, yaml.depth, pathBlacklist, yaml, sourceFile)).filter((file) => file !== null);
|
|
const sorted = sortFiles(filtered, yaml, plugin);
|
|
for (const item of sorted) {
|
|
const indentStr = " ".repeat(indent);
|
|
if (item instanceof import_obsidian43.TFile) {
|
|
result.push(buildFileLinkListLine(item, yaml, indentStr));
|
|
} else if (item instanceof import_obsidian43.TFolder) {
|
|
const folderLines = await buildFolderLinkListLines(item, plugin, yaml, pathBlacklist, sourceFile, indentStr, indent);
|
|
result.push(...folderLines);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function buildFileLinkListLine(item, yaml, indentStr) {
|
|
const prefix = yaml.isInCallout ? "> " : "";
|
|
let base;
|
|
if (yaml.useWikilinks) {
|
|
base = `${prefix}${indentStr}- [[${item.path}|${item.basename}]]`;
|
|
} else {
|
|
base = `${prefix}${indentStr}- [${item.basename}](${encodeURI(item.path)})`;
|
|
}
|
|
if (yaml.hideLinkList) {
|
|
return base + ' <span class="fv-link-list-item"></span>';
|
|
}
|
|
return base;
|
|
}
|
|
async function buildFolderLinkListLines(item, plugin, yaml, pathBlacklist, sourceFile, indentStr, indent) {
|
|
const lines = [];
|
|
const prefix = yaml.isInCallout ? "> " : "";
|
|
let line = `${prefix}${indentStr}- ${item.name}`;
|
|
let folderNote = null;
|
|
if (plugin instanceof FolderNotesPlugin) {
|
|
folderNote = getFolderNote(plugin, item.path);
|
|
}
|
|
if (folderNote) {
|
|
if (yaml.useWikilinks) {
|
|
line = `${prefix}${indentStr}- [[${folderNote.path}|${item.name}]]`;
|
|
} else {
|
|
line = `${prefix}${indentStr}- [${item.name}](${encodeURI(folderNote.path)})`;
|
|
}
|
|
}
|
|
if (yaml.hideLinkList) {
|
|
line += ' <span class="fv-link-list-item"></span>';
|
|
}
|
|
lines.push(line);
|
|
const children = item.children.filter((child) => !(child instanceof import_obsidian43.TFile && folderNote && child.path === folderNote.path));
|
|
if (children.length > 0) {
|
|
const childLinks = await buildLinkList(children, plugin, yaml, pathBlacklist, sourceFile, indent + 1);
|
|
lines.push(...childLinks);
|
|
}
|
|
return lines;
|
|
}
|
|
function removeLinkList(plugin, sourceFile, yaml) {
|
|
if (sourceFile) {
|
|
plugin.app.vault.process(sourceFile, (text) => {
|
|
const lines = text.split("\n");
|
|
const linkListStart = `${yaml.isInCallout ? "> " : ""}<span class="fv-link-list-start" id="${yaml.id}"></span>`;
|
|
const linkListEnd = `${yaml.isInCallout ? "> " : ""}<span class="fv-link-list-end" id="${yaml.id}"></span>`;
|
|
const startIdx = lines.findIndex((l) => l.trim() === linkListStart);
|
|
const endIdx = lines.findIndex((l) => l.trim() === linkListEnd);
|
|
const NOT_FOUND = -1;
|
|
const linkListExists = startIdx !== NOT_FOUND && endIdx !== NOT_FOUND;
|
|
const isInvalidLinkList = endIdx < startIdx;
|
|
if (!linkListExists || isInvalidLinkList) {
|
|
return text;
|
|
}
|
|
lines.splice(startIdx, endIdx - startIdx + 1);
|
|
return lines.join("\n");
|
|
});
|
|
}
|
|
}
|
|
|
|
// src/obsidian-folder-overview/src/utils/functions.ts
|
|
var import_obsidian44 = require("obsidian");
|
|
function getFolderPathFromString2(path) {
|
|
const subString = path.lastIndexOf("/") >= 0 ? path.lastIndexOf("/") : 0;
|
|
const folderPath = path.substring(0, subString);
|
|
if (folderPath === "") {
|
|
return "/";
|
|
}
|
|
return folderPath;
|
|
}
|
|
var CODE_BLOCK_END_NOT_FOUND = -1;
|
|
var MAX_CODE_BLOCK_SEARCH_COUNT = 50;
|
|
function getCodeBlockEndLine(text, startLine, count = 1) {
|
|
let line = startLine + 1;
|
|
const lines = text.split("\n");
|
|
while (line < lines.length) {
|
|
if (count > MAX_CODE_BLOCK_SEARCH_COUNT) {
|
|
return CODE_BLOCK_END_NOT_FOUND;
|
|
}
|
|
if (lines[line].startsWith("```")) {
|
|
return line;
|
|
}
|
|
line++;
|
|
count++;
|
|
}
|
|
return line;
|
|
}
|
|
async function updateAllOverviews(plugin) {
|
|
const filePaths = await plugin.fvIndexDB.getAllNotes();
|
|
if (filePaths.length === 0)
|
|
return;
|
|
filePaths.forEach(async (filePath) => {
|
|
const file = plugin.app.vault.getAbstractFileByPath(filePath);
|
|
if (!(file instanceof import_obsidian44.TFile)) {
|
|
plugin.fvIndexDB.removeNote(filePath);
|
|
return;
|
|
}
|
|
if (!hasOverviewYaml(plugin, file)) {
|
|
plugin.fvIndexDB.removeNote(file.path);
|
|
return;
|
|
}
|
|
const overviews = await getOverviews(plugin, file);
|
|
overviews.forEach(async (overview) => {
|
|
if (!overview.useActualLinks)
|
|
return;
|
|
let files = [];
|
|
let sourceFolderPath = overview.folderPath.trim();
|
|
if (!sourceFolderPath.includes("/")) {
|
|
sourceFolderPath = "/";
|
|
}
|
|
const sourceFolder = plugin.app.vault.getAbstractFileByPath(sourceFolderPath);
|
|
if (!(sourceFolder instanceof import_obsidian44.TFolder) && sourceFolderPath !== "/") {
|
|
return;
|
|
}
|
|
if ((sourceFolder == null ? void 0 : sourceFolder.path) === "/") {
|
|
const rootFiles = [];
|
|
plugin.app.vault.getAllLoadedFiles().filter((f) => {
|
|
var _a;
|
|
return ((_a = f.parent) == null ? void 0 : _a.path) === "/";
|
|
}).forEach((f) => {
|
|
if (!f.path.includes("/")) {
|
|
rootFiles.push(f);
|
|
}
|
|
});
|
|
files = rootFiles;
|
|
} else if (sourceFolder instanceof import_obsidian44.TFolder) {
|
|
files = sourceFolder.children;
|
|
}
|
|
files = getAllFiles(files, sourceFolderPath, overview.depth);
|
|
const filteredFiles = await filterFiles(files, plugin, sourceFolderPath, overview.depth, [], overview, file);
|
|
files = filteredFiles.filter((f) => f !== null);
|
|
if (!overview.includeTypes.includes("folder")) {
|
|
files = getAllFiles(files, sourceFolderPath, overview.depth);
|
|
}
|
|
files = sortFiles(files, overview, plugin);
|
|
updateLinkList(files, plugin, overview, [], file);
|
|
});
|
|
});
|
|
}
|
|
function buildYamlConfig(yaml, defaultSettings, ctx, includeTypesParam) {
|
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
|
|
return {
|
|
id: (_a = yaml == null ? void 0 : yaml.id) != null ? _a : crypto.randomUUID(),
|
|
folderPath: (_c = (_b = yaml == null ? void 0 : yaml.folderPath) == null ? void 0 : _b.trim()) != null ? _c : getFolderPathFromString2(ctx.sourcePath),
|
|
title: (_d = yaml == null ? void 0 : yaml.title) != null ? _d : defaultSettings.title,
|
|
showTitle: (_e = yaml == null ? void 0 : yaml.showTitle) != null ? _e : defaultSettings.showTitle,
|
|
depth: (_f = yaml == null ? void 0 : yaml.depth) != null ? _f : defaultSettings.depth,
|
|
style: (_g = yaml == null ? void 0 : yaml.style) != null ? _g : "list",
|
|
includeTypes: includeTypesParam.map((type) => type.toLowerCase()),
|
|
disableFileTag: (_h = yaml == null ? void 0 : yaml.disableFileTag) != null ? _h : defaultSettings.disableFileTag,
|
|
sortBy: (_i = yaml == null ? void 0 : yaml.sortBy) != null ? _i : defaultSettings.sortBy,
|
|
sortByAsc: (_j = yaml == null ? void 0 : yaml.sortByAsc) != null ? _j : defaultSettings.sortByAsc,
|
|
showEmptyFolders: (_k = yaml == null ? void 0 : yaml.showEmptyFolders) != null ? _k : defaultSettings.showEmptyFolders,
|
|
onlyIncludeSubfolders: (_l = yaml == null ? void 0 : yaml.onlyIncludeSubfolders) != null ? _l : defaultSettings.onlyIncludeSubfolders,
|
|
storeFolderCondition: (_m = yaml == null ? void 0 : yaml.storeFolderCondition) != null ? _m : defaultSettings.storeFolderCondition,
|
|
showFolderNotes: (_n = yaml == null ? void 0 : yaml.showFolderNotes) != null ? _n : defaultSettings.showFolderNotes,
|
|
disableCollapseIcon: (_o = yaml == null ? void 0 : yaml.disableCollapseIcon) != null ? _o : defaultSettings.disableCollapseIcon,
|
|
alwaysCollapse: (_p = yaml == null ? void 0 : yaml.alwaysCollapse) != null ? _p : defaultSettings.alwaysCollapse,
|
|
autoSync: (_q = yaml == null ? void 0 : yaml.autoSync) != null ? _q : defaultSettings.autoSync,
|
|
allowDragAndDrop: (_r = yaml == null ? void 0 : yaml.allowDragAndDrop) != null ? _r : defaultSettings.allowDragAndDrop,
|
|
hideLinkList: (_s = yaml == null ? void 0 : yaml.hideLinkList) != null ? _s : defaultSettings.hideLinkList,
|
|
hideFolderOverview: (_t = yaml == null ? void 0 : yaml.hideFolderOverview) != null ? _t : defaultSettings.hideFolderOverview,
|
|
useActualLinks: (_u = yaml == null ? void 0 : yaml.useActualLinks) != null ? _u : defaultSettings.useActualLinks,
|
|
fmtpIntegration: (_v = yaml == null ? void 0 : yaml.fmtpIntegration) != null ? _v : defaultSettings.fmtpIntegration,
|
|
titleSize: (_w = yaml == null ? void 0 : yaml.titleSize) != null ? _w : defaultSettings.titleSize,
|
|
isInCallout: (_x = yaml == null ? void 0 : yaml.isInCallout) != null ? _x : false,
|
|
useWikilinks: (_z = (_y = yaml == null ? void 0 : yaml.useWikilinks) != null ? _y : defaultSettings.useWikilinks) != null ? _z : true
|
|
};
|
|
}
|
|
async function updateYamlById(plugin, overviewId, file, newYaml, addLinkList, isCallout = false) {
|
|
await plugin.app.vault.process(file, (text) => {
|
|
const yamlBlocks = getYamlBlocks(text, isCallout);
|
|
if (!yamlBlocks)
|
|
return text;
|
|
for (const block of yamlBlocks) {
|
|
const cleanedBlock = cleanYamlBlock(block, isCallout);
|
|
const yaml = (0, import_obsidian44.parseYaml)(cleanedBlock);
|
|
if (!yaml)
|
|
continue;
|
|
if (yaml.id === overviewId) {
|
|
let stringYaml = (0, import_obsidian44.stringifyYaml)(newYaml);
|
|
if (stringYaml[stringYaml.length - 1] !== "\n") {
|
|
stringYaml += "\n";
|
|
}
|
|
let newBlock = buildNewBlock(stringYaml, isCallout);
|
|
if (addLinkList && !isCallout) {
|
|
newBlock += buildLinkListBlock(newYaml.id, false);
|
|
} else if (addLinkList && isCallout) {
|
|
newBlock += buildLinkListBlock(newYaml.id, true);
|
|
}
|
|
text = text.replace(block, newBlock);
|
|
}
|
|
}
|
|
return text;
|
|
});
|
|
function getYamlBlocks(text, callout) {
|
|
return callout ? text.match(/^> ```folder-overview\n([\s\S]*?)```/gm) : text.match(/^(?!>).*```folder-overview\n(?:^(?!>).*[\r\n]*)*?^```$/gm);
|
|
}
|
|
function cleanYamlBlock(block, calloutFlag) {
|
|
if (calloutFlag) {
|
|
let cleaned = block.replace("> ```folder-overview\n", "").replace("```", "");
|
|
return cleaned.replace(/^> ?/gm, "");
|
|
}
|
|
return block.replace("```folder-overview\n", "").replace("```", "");
|
|
}
|
|
function buildNewBlock(stringYaml, calloutFlag) {
|
|
if (calloutFlag) {
|
|
const yamlLines = stringYaml.split("\n").map((line) => `> ${line}`).join("\n");
|
|
return "> ```folder-overview\n" + yamlLines + "\n> ```";
|
|
}
|
|
return "```folder-overview\n" + stringYaml + "\n```";
|
|
}
|
|
}
|
|
function parseOverviewTitle(overview, plugin, sourceFolder, sourceFolderPath, sourceFile) {
|
|
var _a, _b, _c, _d;
|
|
let { title } = overview;
|
|
const variables = {
|
|
folderName: (sourceFolder == null ? void 0 : sourceFolder.path) === "/" || sourceFolderPath === "/" ? "Vault" : (_a = sourceFolder == null ? void 0 : sourceFolder.name) != null ? _a : "",
|
|
folderPath: (_c = (_b = sourceFolder == null ? void 0 : sourceFolder.path) != null ? _b : sourceFolderPath) != null ? _c : "",
|
|
filePath: sourceFile.path,
|
|
fileName: sourceFile instanceof import_obsidian44.TFile ? sourceFile.basename : ""
|
|
};
|
|
const fileCache = plugin.app.metadataCache.getFileCache(sourceFile);
|
|
const frontmatter = (_d = fileCache == null ? void 0 : fileCache.frontmatter) != null ? _d : {};
|
|
title = replacePropertiesInTitle(title, frontmatter);
|
|
title = replaceVariablesInTitle(title, variables);
|
|
return title;
|
|
}
|
|
function replacePropertiesInTitle(title, frontmatter) {
|
|
const propertyRegex = /\{\{properties\.([\w-]+)\}\}/g;
|
|
return title.replace(propertyRegex, (_, prop) => {
|
|
const value = frontmatter[prop];
|
|
return value !== void 0 ? String(value) : "";
|
|
});
|
|
}
|
|
function replaceVariablesInTitle(title, variables) {
|
|
return title.replace(/\{\{(\w+)\}\}/g, (_, key) => {
|
|
var _a;
|
|
return (_a = variables[key]) != null ? _a : "";
|
|
});
|
|
}
|
|
|
|
// src/obsidian-folder-overview/src/modals/Settings.ts
|
|
var FolderOverviewSettings = class extends import_obsidian45.Modal {
|
|
constructor(app, plugin, yaml, ctx, el, defaultSettings) {
|
|
super(app);
|
|
this.plugin = plugin;
|
|
this.app = app;
|
|
this.defaultSettings = defaultSettings;
|
|
this.yaml = this.initializeYaml(yaml, ctx, defaultSettings);
|
|
this.ctx = ctx != null ? ctx : void 0;
|
|
this.el = el != null ? el : void 0;
|
|
updateYaml(this.plugin, this.ctx, this.el, this.yaml, false);
|
|
}
|
|
initializeYaml(yaml, ctx, defaultSettings) {
|
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
|
|
if (!yaml) {
|
|
return this.defaultSettings;
|
|
}
|
|
if (ctx) {
|
|
const includeTypes = (yaml == null ? void 0 : yaml.includeTypes) || defaultSettings.includeTypes || ["folder", "markdown"];
|
|
return {
|
|
id: (_a = yaml == null ? void 0 : yaml.id) != null ? _a : crypto.randomUUID(),
|
|
folderPath: (_b = yaml == null ? void 0 : yaml.folderPath) != null ? _b : getFolderPathFromString2(ctx.sourcePath),
|
|
title: (_c = yaml == null ? void 0 : yaml.title) != null ? _c : defaultSettings.title,
|
|
showTitle: (_d = yaml == null ? void 0 : yaml.showTitle) != null ? _d : defaultSettings.showTitle,
|
|
depth: (_e = yaml == null ? void 0 : yaml.depth) != null ? _e : defaultSettings.depth,
|
|
style: (_f = yaml == null ? void 0 : yaml.style) != null ? _f : "list",
|
|
includeTypes: includeTypes.map((type) => type.toLowerCase()),
|
|
disableFileTag: (_g = yaml == null ? void 0 : yaml.disableFileTag) != null ? _g : defaultSettings.disableFileTag,
|
|
sortBy: (_h = yaml == null ? void 0 : yaml.sortBy) != null ? _h : defaultSettings.sortBy,
|
|
sortByAsc: (_i = yaml == null ? void 0 : yaml.sortByAsc) != null ? _i : defaultSettings.sortByAsc,
|
|
showEmptyFolders: (_j = yaml == null ? void 0 : yaml.showEmptyFolders) != null ? _j : defaultSettings.showEmptyFolders,
|
|
onlyIncludeSubfolders: (_k = yaml == null ? void 0 : yaml.onlyIncludeSubfolders) != null ? _k : defaultSettings.onlyIncludeSubfolders,
|
|
storeFolderCondition: (_l = yaml == null ? void 0 : yaml.storeFolderCondition) != null ? _l : defaultSettings.storeFolderCondition,
|
|
showFolderNotes: (_m = yaml == null ? void 0 : yaml.showFolderNotes) != null ? _m : defaultSettings.showFolderNotes,
|
|
disableCollapseIcon: (_n = yaml == null ? void 0 : yaml.disableCollapseIcon) != null ? _n : defaultSettings.disableCollapseIcon,
|
|
alwaysCollapse: (_o = yaml == null ? void 0 : yaml.alwaysCollapse) != null ? _o : defaultSettings.alwaysCollapse,
|
|
autoSync: (_p = yaml == null ? void 0 : yaml.autoSync) != null ? _p : defaultSettings.autoSync,
|
|
allowDragAndDrop: (_q = yaml == null ? void 0 : yaml.allowDragAndDrop) != null ? _q : defaultSettings.allowDragAndDrop,
|
|
hideLinkList: (_r = yaml == null ? void 0 : yaml.hideLinkList) != null ? _r : defaultSettings.hideLinkList,
|
|
hideFolderOverview: (_s = yaml == null ? void 0 : yaml.hideFolderOverview) != null ? _s : defaultSettings.hideFolderOverview,
|
|
useActualLinks: (_t = yaml == null ? void 0 : yaml.useActualLinks) != null ? _t : defaultSettings.useActualLinks,
|
|
fmtpIntegration: (_u = yaml == null ? void 0 : yaml.fmtpIntegration) != null ? _u : defaultSettings.fmtpIntegration,
|
|
titleSize: (_v = yaml == null ? void 0 : yaml.titleSize) != null ? _v : defaultSettings.titleSize,
|
|
isInCallout: (_w = yaml == null ? void 0 : yaml.isInCallout) != null ? _w : false,
|
|
useWikilinks: (_y = (_x = yaml == null ? void 0 : yaml.useWikilinks) != null ? _x : defaultSettings.useWikilinks) != null ? _y : true
|
|
};
|
|
}
|
|
return yaml;
|
|
}
|
|
onOpen() {
|
|
const { contentEl } = this;
|
|
this.display(contentEl, this.yaml, this.plugin, this.defaultSettings, this.display, this.el, this.ctx);
|
|
}
|
|
display(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal, changedSection) {
|
|
modal = this != null ? this : modal;
|
|
contentEl.empty();
|
|
contentEl.addEventListener("keydown", (e) => {
|
|
if (e.key === "Enter") {
|
|
if (!modal) {
|
|
return;
|
|
}
|
|
modal.close();
|
|
}
|
|
});
|
|
if (!modal.defaultSettings) {
|
|
contentEl.createEl("h2", { text: "Folder overview settings" });
|
|
} else {
|
|
contentEl.createEl("h2", { text: "Default folder overview settings" });
|
|
}
|
|
createOverviewSettings(contentEl, yaml, plugin, defaultSettings, display, el, ctx, void 0, void 0, modal, changedSection);
|
|
}
|
|
onClose() {
|
|
this.plugin.updateOverviewView(this.plugin, this.yaml);
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/obsidian-folder-overview/src/styles/FileExplorer.ts
|
|
var import_obsidian46 = require("obsidian");
|
|
var FileExplorerOverview = class {
|
|
constructor(plugin, ctx, root, yaml, pathBlacklist, folderOverview) {
|
|
this.eventListeners = [];
|
|
this.plugin = plugin;
|
|
this.folderOverview = folderOverview;
|
|
this.pathBlacklist = pathBlacklist;
|
|
this.source = ctx.sourcePath;
|
|
this.yaml = yaml;
|
|
this.root = root;
|
|
}
|
|
disconnectListeners() {
|
|
this.eventListeners.forEach((unregister) => {
|
|
unregister();
|
|
});
|
|
this.eventListeners = [];
|
|
}
|
|
async renderFileExplorer() {
|
|
this.disconnectListeners();
|
|
const { plugin, ctx, root, yaml, folderOverview } = {
|
|
plugin: this.plugin,
|
|
ctx: this.folderOverview.ctx,
|
|
root: this.folderOverview.root,
|
|
yaml: this.folderOverview.yaml,
|
|
folderOverview: this.folderOverview
|
|
};
|
|
let folder = null;
|
|
if (plugin instanceof FolderNotesPlugin) {
|
|
folder = getFileExplorerElement(yaml.folderPath, plugin);
|
|
}
|
|
let folderElement = folder == null ? void 0 : folder.parentElement;
|
|
const overviewList = folderOverview.listEl;
|
|
overviewList == null ? void 0 : overviewList.empty();
|
|
if (!overviewList)
|
|
return;
|
|
let tFolder = plugin.app.vault.getAbstractFileByPath(yaml.folderPath);
|
|
if (!tFolder && yaml.folderPath.trim() === "") {
|
|
if (ctx.sourcePath.includes("/")) {
|
|
const folderPath = getFolderPathFromString(ctx.sourcePath);
|
|
tFolder = plugin.app.vault.getAbstractFileByPath(folderPath);
|
|
} else {
|
|
yaml.folderPath = "/";
|
|
tFolder = plugin.app.vault.getAbstractFileByPath("/");
|
|
}
|
|
}
|
|
if (!folderElement && !tFolder)
|
|
return;
|
|
const sourceFolderPath = (tFolder == null ? void 0 : tFolder.path) || "";
|
|
folderElement = document.querySelectorAll(".nav-files-container")[0];
|
|
if (!folderElement && root) {
|
|
folderElement = root.createDiv({
|
|
cls: "nav-files-container"
|
|
});
|
|
}
|
|
const newFolderElement = folderElement.cloneNode(true);
|
|
newFolderElement.querySelectorAll("div.nav-folder-title").forEach((el) => {
|
|
var _a;
|
|
const folderItem = plugin.app.vault.getAbstractFileByPath(el.getAttribute("data-path") || "");
|
|
if (!(folderItem instanceof import_obsidian46.TFolder))
|
|
return;
|
|
if (yaml.alwaysCollapse) {
|
|
folderItem.collapsed = true;
|
|
el.classList.add("is-collapsed");
|
|
} else {
|
|
if (yaml.storeFolderCondition) {
|
|
if (folderItem.collapsed) {
|
|
el.classList.add("is-collapsed");
|
|
} else {
|
|
el.classList.remove("is-collapsed");
|
|
}
|
|
} else {
|
|
if ((_a = el.parentElement) == null ? void 0 : _a.classList.contains("is-collapsed")) {
|
|
folderItem.collapsed = true;
|
|
} else {
|
|
folderItem.collapsed = false;
|
|
}
|
|
}
|
|
}
|
|
if (el.classList.contains("has-folder-note")) {
|
|
if (plugin instanceof FolderNotesPlugin) {
|
|
const folderNote = getFolderNote(plugin, folderItem.path);
|
|
if (folderNote) {
|
|
folderOverview.pathBlacklist.push(folderNote.path);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
const DEBOUNCE_DELAY_MS = 300;
|
|
const debouncedRenderFileExplorer = (0, import_obsidian46.debounce)(() => this.renderFileExplorer(), DEBOUNCE_DELAY_MS);
|
|
const handleVaultChange = () => {
|
|
debouncedRenderFileExplorer();
|
|
};
|
|
this.eventListeners.push(() => {
|
|
folderOverview.off("vault-change", handleVaultChange);
|
|
});
|
|
folderOverview.on("vault-change", handleVaultChange);
|
|
if (tFolder instanceof import_obsidian46.TFolder) {
|
|
await this.addFiles(tFolder.children, overviewList, folderOverview, sourceFolderPath);
|
|
}
|
|
newFolderElement.querySelectorAll("div.tree-item-icon").forEach((el) => {
|
|
if (el instanceof HTMLElement) {
|
|
el.onclick = () => {
|
|
var _a;
|
|
const path = (_a = el.parentElement) == null ? void 0 : _a.getAttribute("data-path");
|
|
if (!path)
|
|
return;
|
|
const targetFolder = plugin.app.vault.getAbstractFileByPath(path);
|
|
this.handleCollapseClick(el, plugin, yaml, this.pathBlacklist, sourceFolderPath, folderOverview, targetFolder);
|
|
};
|
|
}
|
|
});
|
|
}
|
|
async addFiles(files, childrenElement, folderOverview, sourceFolderPath) {
|
|
const { plugin } = folderOverview;
|
|
const allFiles = await filterFiles(files, plugin, sourceFolderPath, folderOverview.yaml.depth, folderOverview.pathBlacklist, folderOverview.yaml, folderOverview.sourceFile);
|
|
const sortedFiles = sortFiles((allFiles != null ? allFiles : []).filter((file) => file !== null), folderOverview.yaml, folderOverview.plugin);
|
|
const folders = sortedFiles.filter((child) => child instanceof import_obsidian46.TFolder);
|
|
const otherFiles = sortedFiles.filter((child) => child instanceof import_obsidian46.TFile);
|
|
for (const child of folders) {
|
|
if (!(child instanceof import_obsidian46.TFolder))
|
|
continue;
|
|
await this.createFolderEL(plugin, child, folderOverview, childrenElement, sourceFolderPath);
|
|
}
|
|
for (const child of otherFiles) {
|
|
if (!(child instanceof import_obsidian46.TFile))
|
|
continue;
|
|
await this.createFileEL(plugin, child, folderOverview, childrenElement);
|
|
}
|
|
}
|
|
async handleCollapseClick(el, plugin, yaml, pathBlacklist, sourceFolderPath, folderOverview, folder) {
|
|
var _a, _b, _c, _d;
|
|
el.classList.toggle("is-collapsed");
|
|
if (el.classList.contains("is-collapsed")) {
|
|
if (!(folder instanceof import_obsidian46.TFolder))
|
|
return;
|
|
folder.collapsed = true;
|
|
(_c = (_b = (_a = el.parentElement) == null ? void 0 : _a.parentElement) == null ? void 0 : _b.childNodes[1]) == null ? void 0 : _c.remove();
|
|
} else {
|
|
if (!(folder instanceof import_obsidian46.TFolder))
|
|
return;
|
|
folder.collapsed = false;
|
|
const folderElement = (_d = el.parentElement) == null ? void 0 : _d.parentElement;
|
|
if (!folderElement)
|
|
return;
|
|
const childrenElement = folderElement.createDiv({
|
|
cls: "tree-item-children nav-folder-children"
|
|
});
|
|
const files = sortFiles(folder.children, yaml, plugin);
|
|
const filteredFilesResult = await filterFiles(files, plugin, folder.path, yaml.depth || 1, pathBlacklist, yaml, folderOverview.sourceFile);
|
|
const filteredFiles = (filteredFilesResult != null ? filteredFilesResult : []).filter((file) => file !== null);
|
|
await this.addFiles(filteredFiles, childrenElement, folderOverview, sourceFolderPath);
|
|
}
|
|
}
|
|
async createFolderEL(plugin, child, folderOverview, childrenElement, sourceFolderPath) {
|
|
const folderNote = this.getFolderNoteIfExists(plugin, child);
|
|
if (folderNote) {
|
|
folderOverview.pathBlacklist.push(folderNote.path);
|
|
}
|
|
if (this.shouldExcludeFolder(plugin, child)) {
|
|
return;
|
|
}
|
|
const { folderElement, folderTitle } = this.createFolderElements(plugin, child, folderOverview, childrenElement, folderNote);
|
|
await this.handleFolderChildren(child, folderOverview, folderElement, folderTitle, childrenElement, sourceFolderPath);
|
|
this.setupFolderStyles(folderNote, child, folderTitle, folderOverview.yaml);
|
|
this.createCollapseIcon(folderTitle, child, plugin, folderOverview, sourceFolderPath);
|
|
}
|
|
getFolderNoteIfExists(plugin, child) {
|
|
if (plugin instanceof FolderNotesPlugin) {
|
|
return getFolderNote(plugin, child.path);
|
|
}
|
|
return void 0;
|
|
}
|
|
shouldExcludeFolder(plugin, child) {
|
|
var _a;
|
|
if (plugin instanceof FolderNotesPlugin) {
|
|
const excludedFolder = getExcludedFolder(plugin, child.path, true);
|
|
return (_a = excludedFolder == null ? void 0 : excludedFolder.excludeFromFolderOverview) != null ? _a : false;
|
|
}
|
|
return false;
|
|
}
|
|
createFolderElements(plugin, child, folderOverview, childrenElement, folderNote) {
|
|
var _a;
|
|
const { yaml } = folderOverview;
|
|
if (!yaml.includeTypes.includes("folder")) {
|
|
return { folderElement: null, folderTitle: null };
|
|
}
|
|
(_a = folderOverview.el.parentElement) == null ? void 0 : _a.classList.add("fv-remove-edit-button");
|
|
const folderElement = childrenElement.createDiv({
|
|
cls: "tree-item nav-folder"
|
|
});
|
|
const folderTitle = folderElement.createDiv({
|
|
cls: "tree-item-self is-clickable nav-folder-title",
|
|
attr: {
|
|
"data-path": child.path
|
|
}
|
|
});
|
|
this.setupFolderTitle(plugin, child, folderOverview, folderTitle, folderNote);
|
|
return { folderElement, folderTitle };
|
|
}
|
|
async setupFolderTitle(plugin, child, folderOverview, folderTitle, folderNote) {
|
|
var _a, _b;
|
|
const { yaml, pathBlacklist } = folderOverview;
|
|
let folderName = child.name;
|
|
if (yaml.fmtpIntegration && plugin instanceof FolderNotesPlugin && folderNote) {
|
|
folderName = (_b = await ((_a = plugin.fmtpHandler) == null ? void 0 : _a.getNewFileName(folderNote))) != null ? _b : child.name;
|
|
}
|
|
const folderTitleText = folderTitle.createDiv({
|
|
cls: "tree-item-inner nav-folder-title-content",
|
|
text: folderName
|
|
});
|
|
if (!folderNote) {
|
|
folderTitleText.onclick = () => {
|
|
const collapseIcon = folderTitle.querySelectorAll(".tree-item-icon")[0];
|
|
if (collapseIcon) {
|
|
this.handleCollapseClick(collapseIcon, plugin, yaml, pathBlacklist, "", folderOverview, child);
|
|
}
|
|
};
|
|
}
|
|
if (yaml.allowDragAndDrop) {
|
|
this.handleDragAndDrop(folderTitle, folderTitle.parentElement, child);
|
|
}
|
|
folderTitle.oncontextmenu = (e) => {
|
|
folderOverview.folderMenu(child, e);
|
|
};
|
|
}
|
|
async handleFolderChildren(child, folderOverview, folderElement, folderTitle, childrenElement, sourceFolderPath) {
|
|
const { yaml } = folderOverview;
|
|
if (!child.collapsed || !yaml.includeTypes.includes("folder")) {
|
|
if (yaml.alwaysCollapse) {
|
|
child.collapsed = true;
|
|
}
|
|
if (yaml.includeTypes.includes("folder")) {
|
|
folderTitle == null ? void 0 : folderTitle.classList.remove("is-collapsed");
|
|
const folderChildren = folderElement == null ? void 0 : folderElement.createDiv({
|
|
cls: "tree-item-children nav-folder-children"
|
|
});
|
|
if (folderChildren) {
|
|
await this.addFiles(child.children, folderChildren, folderOverview, sourceFolderPath);
|
|
}
|
|
} else {
|
|
await this.addFiles(child.children, childrenElement, folderOverview, sourceFolderPath);
|
|
}
|
|
} else {
|
|
folderTitle == null ? void 0 : folderTitle.classList.add("is-collapsed");
|
|
}
|
|
}
|
|
setupFolderStyles(folderNote, child, folderTitle, yaml) {
|
|
if (folderNote) {
|
|
folderTitle == null ? void 0 : folderTitle.classList.add("has-folder-note");
|
|
}
|
|
if (folderNote && child.children.length === 1 && yaml.disableCollapseIcon) {
|
|
folderTitle == null ? void 0 : folderTitle.classList.add("fn-has-no-files");
|
|
}
|
|
}
|
|
createCollapseIcon(folderTitle, child, plugin, folderOverview, sourceFolderPath) {
|
|
var _a;
|
|
const collapseIcon = folderTitle == null ? void 0 : folderTitle.createDiv({
|
|
cls: "tree-item-icon collapse-icon nav-folder-collapse-indicator fn-folder-overview-collapse-icon"
|
|
});
|
|
if (child.collapsed) {
|
|
collapseIcon == null ? void 0 : collapseIcon.classList.add("is-collapsed");
|
|
}
|
|
if (collapseIcon) {
|
|
(0, import_obsidian46.setIcon)(collapseIcon, "chevron-down");
|
|
(_a = collapseIcon.querySelector("path")) == null ? void 0 : _a.setAttribute("d", "M3 8L12 17L21 8");
|
|
collapseIcon.onclick = () => {
|
|
this.handleCollapseClick(collapseIcon, plugin, folderOverview.yaml, folderOverview.pathBlacklist, sourceFolderPath, folderOverview, child);
|
|
};
|
|
}
|
|
}
|
|
handleDragAndDrop(folderTitle, folderElement, child) {
|
|
folderTitle.draggable = true;
|
|
folderTitle.addEventListener("dragstart", (e) => {
|
|
const { dragManager } = this.plugin.app;
|
|
if (dragManager && typeof dragManager.dragFolder === "function") {
|
|
const dragData = dragManager.dragFolder(e, child);
|
|
if (typeof dragManager.onDragStart === "function") {
|
|
dragManager.onDragStart(e, dragData);
|
|
}
|
|
folderTitle == null ? void 0 : folderTitle.classList.add("is-being-dragged");
|
|
}
|
|
});
|
|
folderTitle.addEventListener("dragend", () => {
|
|
folderTitle == null ? void 0 : folderTitle.classList.remove("is-being-dragged");
|
|
});
|
|
folderTitle.addEventListener("dragover", (e) => {
|
|
e.preventDefault();
|
|
const { draggable } = this.plugin.app.dragManager;
|
|
if (draggable) {
|
|
folderElement == null ? void 0 : folderElement.classList.add("is-being-dragged-over");
|
|
this.plugin.app.dragManager.setAction(window.i18next.t("interface.drag-and-drop.move-into-folder", { folder: child.name }));
|
|
}
|
|
});
|
|
folderTitle.addEventListener("dragleave", () => {
|
|
folderElement == null ? void 0 : folderElement.classList.remove("is-being-dragged-over");
|
|
});
|
|
folderTitle.addEventListener("drop", () => {
|
|
const { draggable } = this.plugin.app.dragManager;
|
|
if (draggable && draggable.file) {
|
|
const newPath = child.path + "/" + draggable.file.name;
|
|
this.plugin.app.fileManager.renameFile(draggable.file, newPath);
|
|
}
|
|
});
|
|
}
|
|
async createFileEL(plugin, child, folderOverview, childrenElement) {
|
|
var _a, _b, _c;
|
|
const { yaml } = folderOverview;
|
|
const { pathBlacklist } = folderOverview;
|
|
if (pathBlacklist.includes(child.path) && !yaml.showFolderNotes) {
|
|
return;
|
|
}
|
|
(_a = folderOverview.el.parentElement) == null ? void 0 : _a.classList.add("fv-remove-edit-button");
|
|
const fileElement = childrenElement.createDiv({
|
|
cls: "tree-item nav-file"
|
|
});
|
|
const fileTitle = fileElement.createDiv({
|
|
cls: "tree-item-self is-clickable nav-file-title pointer-cursor",
|
|
attr: {
|
|
"data-path": child.path
|
|
}
|
|
});
|
|
if (yaml.allowDragAndDrop) {
|
|
fileTitle.draggable = true;
|
|
fileTitle.addEventListener("dragstart", (e) => {
|
|
const { dragManager } = plugin.app;
|
|
if (dragManager && typeof dragManager.dragFile === "function") {
|
|
const dragData = dragManager.dragFile(e, child);
|
|
if (typeof dragManager.onDragStart === "function") {
|
|
dragManager.onDragStart(e, dragData);
|
|
}
|
|
fileTitle.classList.add("is-being-dragged");
|
|
}
|
|
});
|
|
fileTitle.addEventListener("dragend", () => {
|
|
fileTitle.classList.remove("is-being-dragged");
|
|
});
|
|
fileTitle.addEventListener("dragover", (e) => {
|
|
var _a2, _b2, _c2;
|
|
e.preventDefault();
|
|
const { draggable } = plugin.app.dragManager;
|
|
if (draggable) {
|
|
const folderName = ((_a2 = child.parent) == null ? void 0 : _a2.name) || plugin.app.vault.getName();
|
|
plugin.app.dragManager.setAction(window.i18next.t("interface.drag-and-drop.move-into-folder", { folder: folderName }));
|
|
(_c2 = (_b2 = fileElement.parentElement) == null ? void 0 : _b2.parentElement) == null ? void 0 : _c2.classList.add("is-being-dragged-over");
|
|
}
|
|
});
|
|
fileTitle.addEventListener("dragleave", () => {
|
|
var _a2, _b2;
|
|
(_b2 = (_a2 = fileElement.parentElement) == null ? void 0 : _a2.parentElement) == null ? void 0 : _b2.classList.remove("is-being-dragged-over");
|
|
});
|
|
fileTitle.addEventListener("drop", (e) => {
|
|
var _a2, _b2, _c2;
|
|
e.preventDefault();
|
|
const { draggable } = plugin.app.dragManager;
|
|
if (draggable == null ? void 0 : draggable.file) {
|
|
const targetFolder = ((_a2 = child.parent) == null ? void 0 : _a2.path) || "";
|
|
if (targetFolder) {
|
|
const newPath = `${targetFolder}/${draggable.file.name}`;
|
|
plugin.app.fileManager.renameFile(draggable.file, newPath);
|
|
}
|
|
(_c2 = (_b2 = fileElement.parentElement) == null ? void 0 : _b2.parentElement) == null ? void 0 : _c2.classList.remove("is-being-dragged-over");
|
|
}
|
|
});
|
|
}
|
|
fileTitle.onclick = () => {
|
|
plugin.app.workspace.openLinkText(child.path, child.path, true);
|
|
};
|
|
fileTitle.oncontextmenu = (e) => {
|
|
folderOverview.fileMenu(child, e);
|
|
};
|
|
let fileName = child.basename;
|
|
if (yaml.fmtpIntegration) {
|
|
fileName = (_c = await ((_b = plugin.fmtpHandler) == null ? void 0 : _b.getNewFileName(child))) != null ? _c : child.basename;
|
|
}
|
|
fileTitle.createDiv({
|
|
cls: "tree-item-inner nav-file-title-content",
|
|
text: fileName
|
|
});
|
|
if (child.extension !== "md" && !yaml.disableFileTag) {
|
|
fileTitle.createDiv({
|
|
cls: "nav-file-tag",
|
|
text: child.extension
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
// src/obsidian-folder-overview/src/styles/List.ts
|
|
var import_obsidian47 = require("obsidian");
|
|
async function renderListOverview(plugin, ctx, root, yaml, pathBlacklist, folderOverview) {
|
|
const overviewList = folderOverview.listEl;
|
|
const { app } = plugin;
|
|
overviewList == null ? void 0 : overviewList.empty();
|
|
let tFolder = app.vault.getAbstractFileByPath(yaml.folderPath);
|
|
if (!tFolder && yaml.folderPath.trim() === "") {
|
|
if (ctx.sourcePath.includes("/")) {
|
|
tFolder = app.vault.getAbstractFileByPath(getFolderPathFromString(ctx.sourcePath));
|
|
} else {
|
|
yaml.folderPath = "/";
|
|
tFolder = app.vault.getAbstractFileByPath("/");
|
|
}
|
|
}
|
|
if (!(tFolder instanceof import_obsidian47.TFolder)) {
|
|
return;
|
|
}
|
|
let files = tFolder.children;
|
|
if (!files) {
|
|
return;
|
|
}
|
|
const ul = folderOverview.listEl;
|
|
const sourceFolderPath = tFolder.path;
|
|
files = await filterFiles(files, plugin, sourceFolderPath, yaml.depth, folderOverview.pathBlacklist, yaml, folderOverview.sourceFile);
|
|
const folders = sortFiles(files.filter((f) => f instanceof import_obsidian47.TFolder), folderOverview.yaml, plugin);
|
|
files = sortFiles(files.filter((f) => f instanceof import_obsidian47.TFile), folderOverview.yaml, plugin);
|
|
if (!ul) {
|
|
return;
|
|
}
|
|
folders.forEach(async (file) => {
|
|
if (file instanceof import_obsidian47.TFolder) {
|
|
if (yaml.includeTypes.includes("folder")) {
|
|
const folderItem = await addFolderList(plugin, ul, folderOverview.pathBlacklist, file, folderOverview);
|
|
if (!folderItem) {
|
|
return;
|
|
}
|
|
goThroughFolders(plugin, folderItem, file, folderOverview.yaml.depth, sourceFolderPath, ctx, folderOverview.yaml, folderOverview.pathBlacklist, folderOverview.yaml.includeTypes, folderOverview.yaml.disableFileTag, folderOverview);
|
|
} else {
|
|
goThroughFolders(plugin, ul, file, folderOverview.yaml.depth, sourceFolderPath, ctx, folderOverview.yaml, folderOverview.pathBlacklist, folderOverview.yaml.includeTypes, folderOverview.yaml.disableFileTag, folderOverview);
|
|
}
|
|
}
|
|
});
|
|
files.forEach((file) => {
|
|
if (file instanceof import_obsidian47.TFile) {
|
|
addFileList(plugin, ul, folderOverview.pathBlacklist, file, folderOverview.yaml.includeTypes, folderOverview.yaml.disableFileTag, folderOverview);
|
|
}
|
|
});
|
|
const DEBOUNCE_DELAY = 300;
|
|
const debouncedRenderListOverview = debounce3(() => renderListOverview(plugin, ctx, root, yaml, pathBlacklist, folderOverview), DEBOUNCE_DELAY);
|
|
const handleVaultChange = () => {
|
|
debouncedRenderListOverview();
|
|
};
|
|
folderOverview.on("vault-change", handleVaultChange);
|
|
}
|
|
function debounce3(func, wait) {
|
|
let timeout;
|
|
return (...args) => {
|
|
clearTimeout(timeout);
|
|
timeout = window.setTimeout(() => func(...args), wait);
|
|
};
|
|
}
|
|
async function addFolderList(plugin, list, pathBlacklist, folder, folderOverview) {
|
|
var _a, _b, _c;
|
|
(_a = folderOverview.el.parentElement) == null ? void 0 : _a.classList.add("fv-remove-edit-button");
|
|
const folderDepth = folder.path.split("/").length;
|
|
const sourceFolderDepth = folderOverview.yaml.folderPath.split("/").length;
|
|
const isFirstLevelSub = folderDepth === sourceFolderDepth + 1;
|
|
if (!folderOverview.yaml.showEmptyFolders && folder.children.length === 0 && !folderOverview.yaml.onlyIncludeSubfolders) {
|
|
return;
|
|
} else if (folderOverview.yaml.onlyIncludeSubfolders && !isFirstLevelSub && folder.children.length === 0) {
|
|
return;
|
|
}
|
|
const folderItem = list.createEl("li", { cls: "folder-overview-list folder-list" });
|
|
if (plugin instanceof FolderNotesPlugin) {
|
|
const folderNote = getFolderNote(plugin, folder.path);
|
|
if (folderNote instanceof import_obsidian47.TFile) {
|
|
const folderNoteLink = folderItem.createEl("a", {
|
|
cls: "folder-overview-list-item folder-name-item internal-link",
|
|
href: folderNote.path
|
|
});
|
|
if (folderOverview.yaml.fmtpIntegration) {
|
|
folderNoteLink.innerText = (_c = await ((_b = plugin.fmtpHandler) == null ? void 0 : _b.getNewFileName(folderNote))) != null ? _c : folder.name;
|
|
} else {
|
|
folderNoteLink.innerText = folder.name;
|
|
}
|
|
pathBlacklist.push(folderNote.path);
|
|
folderNoteLink.oncontextmenu = (e) => {
|
|
e.stopImmediatePropagation();
|
|
folderOverview.fileMenu(folderNote, e);
|
|
};
|
|
} else {
|
|
const folderName = folderItem.createEl("span", {
|
|
cls: "folder-overview-list-item folder-name-item"
|
|
});
|
|
folderName.innerText = folder.name;
|
|
folderName.oncontextmenu = (e) => {
|
|
folderOverview.folderMenu(folder, e);
|
|
};
|
|
}
|
|
} else {
|
|
const folderName = folderItem.createEl("span", {
|
|
cls: "folder-overview-list-item folder-name-item"
|
|
});
|
|
folderName.innerText = folder.name;
|
|
folderName.oncontextmenu = (e) => {
|
|
folderOverview.folderMenu(folder, e);
|
|
};
|
|
}
|
|
return folderItem;
|
|
}
|
|
async function goThroughFolders(plugin, list, folder, depth, sourceFolderPath, ctx, yaml, pathBlacklist, includeTypes, disableFileTag, folderOverview) {
|
|
if (sourceFolderPath === "") {
|
|
depth--;
|
|
}
|
|
const allFiles = await filterFiles(folder.children, plugin, sourceFolderPath, depth, pathBlacklist, yaml, folderOverview.sourceFile);
|
|
const files = sortFiles(allFiles.filter((file) => !(file instanceof import_obsidian47.TFolder) && file !== null), yaml, plugin);
|
|
const folders = sortFiles(allFiles.filter((file) => file instanceof import_obsidian47.TFolder && file !== null), yaml, plugin);
|
|
const ul = list.createEl("ul", { cls: "folder-overview-list" });
|
|
folders.forEach(async (file) => {
|
|
if (file instanceof import_obsidian47.TFolder) {
|
|
if (yaml.includeTypes.includes("folder")) {
|
|
const folderItem = await addFolderList(plugin, ul, pathBlacklist, file, folderOverview);
|
|
if (!folderItem) {
|
|
return;
|
|
}
|
|
goThroughFolders(plugin, folderItem, file, depth, sourceFolderPath, ctx, yaml, pathBlacklist, includeTypes, disableFileTag, folderOverview);
|
|
} else {
|
|
goThroughFolders(plugin, list, file, depth, sourceFolderPath, ctx, yaml, pathBlacklist, includeTypes, disableFileTag, folderOverview);
|
|
}
|
|
}
|
|
});
|
|
files.forEach((file) => {
|
|
if (file instanceof import_obsidian47.TFile) {
|
|
if (yaml.includeTypes.includes("folder")) {
|
|
addFileList(plugin, ul, pathBlacklist, file, includeTypes, disableFileTag, folderOverview);
|
|
} else {
|
|
addFileList(plugin, list, pathBlacklist, file, includeTypes, disableFileTag, folderOverview);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
async function addFileList(plugin, list, pathBlacklist, file, includeTypes, disableFileTag, folderOverview) {
|
|
var _a, _b, _c, _d;
|
|
if (!folderOverview.yaml.showFolderNotes) {
|
|
if (pathBlacklist.includes(file.path))
|
|
return;
|
|
if (plugin instanceof FolderNotesPlugin && extractFolderName(plugin.settings.folderNoteName, file.basename) === ((_a = file.parent) == null ? void 0 : _a.name)) {
|
|
return;
|
|
}
|
|
}
|
|
(_b = folderOverview.el.parentElement) == null ? void 0 : _b.classList.add("fv-remove-edit-button");
|
|
const listItem = list.createEl("li", { cls: "folder-overview-list file-link" });
|
|
listItem.oncontextmenu = (e) => {
|
|
e.stopImmediatePropagation();
|
|
folderOverview.fileMenu(file, e);
|
|
};
|
|
const nameItem = listItem.createEl("div", { cls: "folder-overview-list-item" });
|
|
const link = nameItem.createEl("a", { cls: "internal-link", href: file.path });
|
|
if (folderOverview.yaml.fmtpIntegration) {
|
|
link.innerText = (_d = await ((_c = plugin.fmtpHandler) == null ? void 0 : _c.getNewFileName(file))) != null ? _d : file.basename;
|
|
} else {
|
|
link.innerText = file.basename;
|
|
}
|
|
if (file.extension !== "md" && !disableFileTag) {
|
|
nameItem.createDiv({ cls: "nav-file-tag" }).innerText = file.extension;
|
|
}
|
|
}
|
|
|
|
// src/modals/NewFolderName.ts
|
|
var import_obsidian48 = require("obsidian");
|
|
var NewFolderNameModal = class extends import_obsidian48.Modal {
|
|
constructor(app, plugin, folder) {
|
|
super(app);
|
|
this.plugin = plugin;
|
|
this.app = app;
|
|
this.folder = folder;
|
|
}
|
|
onOpen() {
|
|
const { contentEl } = this;
|
|
contentEl.addEventListener("keydown", (e) => {
|
|
if (e.key === "Enter") {
|
|
this.saveFolderName();
|
|
this.close();
|
|
}
|
|
});
|
|
this.modalEl.classList.add("mod-file-rename");
|
|
const modalTitle = this.modalEl.querySelector("div.modal-title");
|
|
if (modalTitle) {
|
|
modalTitle.textContent = "Folder title";
|
|
}
|
|
const textarea = contentEl.createEl("textarea", {
|
|
text: this.folder.name.replace(this.plugin.settings.folderNoteType, ""),
|
|
attr: {
|
|
placeholder: "Enter the name of the folder",
|
|
rows: "1",
|
|
spellcheck: "false",
|
|
class: "rename-textarea"
|
|
}
|
|
});
|
|
textarea.addEventListener("focus", function() {
|
|
this.select();
|
|
});
|
|
textarea.focus();
|
|
const buttonContainer = this.modalEl.createDiv({ cls: "modal-button-container" });
|
|
const saveButton = buttonContainer.createEl("button", { text: "Save", cls: "mod-cta" });
|
|
saveButton.addEventListener("click", async () => {
|
|
this.saveFolderName();
|
|
this.close();
|
|
});
|
|
const cancelButton = buttonContainer.createEl("button", {
|
|
text: "Cancel",
|
|
cls: "mod-cancel"
|
|
});
|
|
cancelButton.addEventListener("click", () => {
|
|
this.close();
|
|
});
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
saveFolderName() {
|
|
const textarea = this.contentEl.querySelector("textarea");
|
|
if (textarea) {
|
|
const newName = textarea.value.trim();
|
|
if (newName.trim() !== "") {
|
|
const folderBasePath = this.folder.path.slice(0, this.folder.path.lastIndexOf("/") + 1);
|
|
const newFolderPath = folderBasePath + newName.trim();
|
|
if (!this.app.vault.getAbstractFileByPath(newFolderPath)) {
|
|
this.plugin.app.fileManager.renameFile(this.folder, newFolderPath);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// src/obsidian-folder-overview/src/FolderOverview.ts
|
|
var FolderOverview = class {
|
|
constructor(plugin, ctx, source, el, defaultSettings) {
|
|
this.pathBlacklist = [];
|
|
this.folders = [];
|
|
this.counter = 0;
|
|
this.LINK_LIST_UPDATE_DELAY_MS = 1e3;
|
|
this.eventListeners = [];
|
|
this.plugin = plugin;
|
|
this.emitter = new CustomEventEmitter2();
|
|
const yaml = this.parseYamlOrUseDefault(source);
|
|
const includeTypes = (yaml == null ? void 0 : yaml.includeTypes) || defaultSettings.includeTypes || ["folder", "markdown"];
|
|
this.ctx = ctx;
|
|
this.source = source;
|
|
this.el = el;
|
|
this.sourceFile = this.getSourceFile(ctx);
|
|
this.yaml = buildYamlConfig(yaml, defaultSettings, ctx, includeTypes);
|
|
this.setSourceFolder();
|
|
this.defaultSettings = defaultSettings;
|
|
const customChild = new CustomMarkdownRenderChild(el, this);
|
|
ctx.addChild(customChild);
|
|
}
|
|
async create(plugin, el, ctx) {
|
|
var _a, _b, _c;
|
|
el.empty();
|
|
if (!(this.sourceFile instanceof import_obsidian49.TFile))
|
|
return;
|
|
(_a = el.parentElement) == null ? void 0 : _a.classList.add("folder-overview-container");
|
|
if (this.yaml.hideFolderOverview) {
|
|
if (this.yaml.isInCallout) {
|
|
el == null ? void 0 : el.classList.add("fv-hide-overview");
|
|
} else {
|
|
(_b = el.parentElement) == null ? void 0 : _b.classList.add("fv-hide-overview");
|
|
}
|
|
}
|
|
(_c = el.parentElement) == null ? void 0 : _c.addEventListener("contextmenu", (e) => this.editOverviewContextMenu(e), { capture: true });
|
|
this.root = el.createEl("div", { cls: "folder-overview" });
|
|
const headingTag = `h${this.yaml.titleSize}`;
|
|
const titleEl = this.root.createEl(headingTag, { cls: "folder-overview-title" });
|
|
this.listEl = this.root.createEl("ul", { cls: "folder-overview-list" });
|
|
if (this.hasNoIncludedTypes(this.root))
|
|
return;
|
|
let sourceFolderPath = this.yaml.folderPath.trim() || getFolderPathFromString(ctx.sourcePath) || "/";
|
|
this.registerListeners();
|
|
await this.renderTitle(this.sourceFolder, sourceFolderPath, this.sourceFile, titleEl);
|
|
if (!this.validateSourceFolder(this.sourceFolder, sourceFolderPath)) {
|
|
this.addEditButton(this.root);
|
|
return;
|
|
}
|
|
let files = this.getInitialFiles(plugin, this.sourceFolder);
|
|
files = await this.filterAndProcessFiles(files, plugin, sourceFolderPath, this.yaml, this.sourceFile);
|
|
if (files.length === 0) {
|
|
updateLinkList(files, this.plugin, this.yaml, this.pathBlacklist, this.sourceFile);
|
|
this.addEditButton(this.root);
|
|
return;
|
|
}
|
|
files = sortFiles(files, this.yaml, this.plugin);
|
|
this.renderOverviewStyle(plugin, ctx, this.root);
|
|
this.handleLinkList(files);
|
|
this.addEditButton(this.root);
|
|
}
|
|
parseYamlOrUseDefault(source) {
|
|
let yaml = (0, import_obsidian49.parseYaml)(source);
|
|
if (!yaml) {
|
|
yaml = {};
|
|
}
|
|
return yaml;
|
|
}
|
|
getSourceFile(ctx) {
|
|
const sourceFile = this.plugin.app.vault.getAbstractFileByPath(ctx.sourcePath);
|
|
if (sourceFile instanceof import_obsidian49.TFile) {
|
|
return sourceFile;
|
|
}
|
|
return void 0;
|
|
}
|
|
on(event, listener) {
|
|
this.emitter.on(event, listener);
|
|
}
|
|
off(event, listener) {
|
|
this.emitter.off(event, listener);
|
|
}
|
|
emit(event, data) {
|
|
this.emitter.emit(event, data);
|
|
}
|
|
handleVaultChange(eventType) {
|
|
if (this.yaml.autoSync) {
|
|
this.emit("vault-change", eventType);
|
|
}
|
|
}
|
|
disconnectListeners() {
|
|
this.eventListeners.forEach((unregister) => unregister());
|
|
this.eventListeners = [];
|
|
}
|
|
registerListeners() {
|
|
const { plugin } = this;
|
|
const handleRename2 = () => this.handleVaultChange("renamed");
|
|
const handleCreate2 = () => this.handleVaultChange("created");
|
|
const handleDelete2 = () => this.handleVaultChange("deleted");
|
|
plugin.app.vault.on("rename", handleRename2);
|
|
plugin.app.vault.on("create", handleCreate2);
|
|
plugin.app.vault.on("delete", handleDelete2);
|
|
this.eventListeners.push(() => plugin.app.vault.off("rename", handleRename2));
|
|
this.eventListeners.push(() => plugin.app.vault.off("create", handleCreate2));
|
|
this.eventListeners.push(() => plugin.app.vault.off("delete", handleDelete2));
|
|
}
|
|
setSourceFolder() {
|
|
var _a;
|
|
switch ((_a = this.yaml) == null ? void 0 : _a.folderPath.trim()) {
|
|
case "":
|
|
case "File\u2019s parent folder path": {
|
|
const folderPath = getFolderPathFromString(this.ctx.sourcePath);
|
|
const sourceFolder = this.plugin.app.vault.getAbstractFileByPath(folderPath);
|
|
if (sourceFolder instanceof import_obsidian49.TFolder) {
|
|
this.yaml.folderPath = sourceFolder.path;
|
|
this.sourceFolder = sourceFolder;
|
|
}
|
|
break;
|
|
}
|
|
case "Path of folder linked to the file": {
|
|
if (this.plugin instanceof FolderNotesPlugin && this.sourceFile instanceof import_obsidian49.TFile) {
|
|
const folderNoteFolder = getFolder(this.plugin, this.sourceFile);
|
|
if (folderNoteFolder instanceof import_obsidian49.TFolder) {
|
|
this.sourceFolder = folderNoteFolder;
|
|
this.yaml.folderPath = folderNoteFolder.path;
|
|
} else {
|
|
this.yaml.folderPath = "";
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
const sourceFolder = this.plugin.app.vault.getAbstractFileByPath(this.yaml.folderPath);
|
|
if (sourceFolder instanceof import_obsidian49.TFolder) {
|
|
this.sourceFolder = sourceFolder;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
async filterAndProcessFiles(files, plugin, sourceFolderPath, yaml, sourceFile) {
|
|
let filteredFiles = await filterFiles(files, plugin, sourceFolderPath, yaml.depth, this.pathBlacklist, yaml, sourceFile);
|
|
if (!yaml.includeTypes.includes("folder")) {
|
|
filteredFiles = getAllFiles(filteredFiles, sourceFolderPath, yaml.depth);
|
|
}
|
|
return filteredFiles;
|
|
}
|
|
hasNoIncludedTypes(root) {
|
|
if (this.yaml.includeTypes.length === 0) {
|
|
this.addEditButton(root);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
handleLinkList(files) {
|
|
if (this.yaml.useActualLinks) {
|
|
setTimeout(() => {
|
|
if (this.sourceFile instanceof import_obsidian49.TFile) {
|
|
updateLinkList(files, this.plugin, this.yaml, this.pathBlacklist, this.sourceFile);
|
|
}
|
|
}, this.LINK_LIST_UPDATE_DELAY_MS);
|
|
} else {
|
|
removeLinkList(this.plugin, this.sourceFile, this.yaml);
|
|
}
|
|
}
|
|
async renderTitle(sourceFolder, sourceFolderPath, sourceFile, titleEl) {
|
|
var _a, _b, _c, _d, _e, _f;
|
|
if (!this.yaml.showTitle)
|
|
return;
|
|
const variables = {
|
|
folderName: (sourceFolder == null ? void 0 : sourceFolder.path) === "/" || sourceFolderPath === "/" ? "Vault" : (_a = sourceFolder == null ? void 0 : sourceFolder.name) != null ? _a : "",
|
|
folderPath: (_c = (_b = sourceFolder == null ? void 0 : sourceFolder.path) != null ? _b : sourceFolderPath) != null ? _c : "",
|
|
filePath: sourceFile.path,
|
|
fileName: sourceFile instanceof import_obsidian49.TFile ? sourceFile.basename : "",
|
|
fmtpFileName: (_e = await ((_d = this.plugin.fmtpHandler) == null ? void 0 : _d.getNewFileName(sourceFile))) != null ? _e : ""
|
|
};
|
|
const fileCache = this.plugin.app.metadataCache.getFileCache(sourceFile);
|
|
const frontmatter = (_f = fileCache == null ? void 0 : fileCache.frontmatter) != null ? _f : {};
|
|
let { title } = this.yaml;
|
|
title = replacePropertiesInTitle(title, frontmatter);
|
|
title = replaceVariablesInTitle(title, variables);
|
|
titleEl.innerText = title;
|
|
}
|
|
validateSourceFolder(sourceFolder, sourceFolderPath) {
|
|
if (!sourceFolder && sourceFolderPath !== "/" && sourceFolderPath !== "") {
|
|
new import_obsidian49.Notice("Folder overview: Couldn't find the folder");
|
|
return false;
|
|
}
|
|
if (!sourceFolder && sourceFolderPath === "") {
|
|
sourceFolderPath = "/";
|
|
}
|
|
if (!(sourceFolder instanceof import_obsidian49.TFolder) && sourceFolderPath !== "/") {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
getInitialFiles(plugin, sourceFolder) {
|
|
if ((sourceFolder == null ? void 0 : sourceFolder.path) === "/") {
|
|
const rootFiles = [];
|
|
plugin.app.vault.getAllLoadedFiles().filter((f) => {
|
|
var _a;
|
|
return ((_a = f.parent) == null ? void 0 : _a.path) === "/";
|
|
}).forEach((file) => {
|
|
if (!file.path.includes("/")) {
|
|
rootFiles.push(file);
|
|
}
|
|
});
|
|
return rootFiles;
|
|
} else if (sourceFolder instanceof import_obsidian49.TFolder) {
|
|
return sourceFolder.children;
|
|
}
|
|
return [];
|
|
}
|
|
renderOverviewStyle(plugin, ctx, root) {
|
|
if (this.yaml.style === "grid") {
|
|
} else if (this.yaml.style === "list") {
|
|
renderListOverview(plugin, ctx, root, this.yaml, this.pathBlacklist, this);
|
|
} else if (this.yaml.style === "explorer") {
|
|
const fileExplorerOverview = new FileExplorerOverview(plugin, ctx, root, this.yaml, this.pathBlacklist, this);
|
|
this.plugin.app.workspace.onLayoutReady(async () => {
|
|
await fileExplorerOverview.renderFileExplorer();
|
|
});
|
|
}
|
|
}
|
|
addEditButton(root) {
|
|
const editButton = root.createEl("button", { cls: "folder-overview-edit-button" });
|
|
editButton.innerText = "Edit overview";
|
|
editButton.addEventListener("click", (e) => {
|
|
e.stopImmediatePropagation();
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
new FolderOverviewSettings(this.plugin.app, this.plugin, this.yaml, this.ctx, this.el, this.plugin instanceof FolderNotesPlugin ? this.plugin.settings.defaultOverview : this.plugin.settings.defaultOverviewSettings).open();
|
|
}, { capture: true });
|
|
}
|
|
fileMenu(file, e) {
|
|
const { plugin } = this;
|
|
const fileMenu = new import_obsidian49.Menu();
|
|
fileMenu.addItem((item) => {
|
|
item.setTitle("Edit folder overview");
|
|
item.setIcon("pencil");
|
|
item.onClick(async () => {
|
|
new FolderOverviewSettings(plugin.app, plugin, this.yaml, this.ctx, this.el, plugin instanceof FolderNotesPlugin ? plugin.settings.defaultOverview : plugin.settings.defaultOverviewSettings).open();
|
|
});
|
|
});
|
|
fileMenu.addSeparator();
|
|
fileMenu.addItem((item) => {
|
|
item.setTitle(window.i18next.t("plugins.file-explorer.menu-opt-rename"));
|
|
item.setIcon("pencil");
|
|
item.onClick(async () => {
|
|
plugin.app.fileManager.promptForFileRename(file);
|
|
});
|
|
});
|
|
fileMenu.addItem((item) => {
|
|
item.setTitle(window.i18next.t("plugins.file-explorer.menu-opt-delete"));
|
|
item.setIcon("trash");
|
|
item.dom.addClass("is-warning");
|
|
item.dom.setAttribute("data-section", "danger");
|
|
item.onClick(() => {
|
|
plugin.app.fileManager.promptForDeletion(file);
|
|
});
|
|
});
|
|
fileMenu.addSeparator();
|
|
plugin.app.workspace.trigger("file-menu", fileMenu, file, "folder-overview-file-context-menu", null);
|
|
fileMenu.showAtPosition({ x: e.pageX, y: e.pageY });
|
|
}
|
|
folderMenu(folder, e) {
|
|
const { plugin } = this;
|
|
const folderMenu = new import_obsidian49.Menu();
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Edit folder overview");
|
|
item.setIcon("pencil");
|
|
item.onClick(async () => {
|
|
new FolderOverviewSettings(plugin.app, plugin, this.yaml, this.ctx, this.el, plugin instanceof FolderNotesPlugin ? plugin.settings.defaultOverview : plugin.settings.defaultOverviewSettings).open();
|
|
});
|
|
});
|
|
folderMenu.addSeparator();
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Rename");
|
|
item.setIcon("pencil");
|
|
item.onClick(async () => {
|
|
if (plugin instanceof FolderNotesPlugin) {
|
|
new NewFolderNameModal(plugin.app, plugin, folder).open();
|
|
}
|
|
});
|
|
});
|
|
folderMenu.addItem((item) => {
|
|
item.setTitle("Delete");
|
|
item.setIcon("trash");
|
|
item.dom.addClass("is-warning");
|
|
item.dom.setAttribute("data-section", "danger");
|
|
item.onClick(() => {
|
|
plugin.app.fileManager.promptForFolderDeletion(folder);
|
|
});
|
|
});
|
|
folderMenu.addSeparator();
|
|
plugin.app.workspace.trigger("file-menu", folderMenu, folder, "folder-overview-folder-context-menu", null);
|
|
folderMenu.showAtPosition({ x: e.pageX, y: e.pageY });
|
|
}
|
|
editOverviewContextMenu(e) {
|
|
const { plugin } = this;
|
|
const menu = new import_obsidian49.Menu();
|
|
menu.addItem((item) => {
|
|
item.setTitle("Edit folder overview");
|
|
item.setIcon("pencil");
|
|
item.onClick(async () => {
|
|
new FolderOverviewSettings(plugin.app, plugin, this.yaml, this.ctx, this.el, plugin instanceof FolderNotesPlugin ? plugin.settings.defaultOverview : plugin.settings.defaultOverviewSettings).open();
|
|
});
|
|
});
|
|
menu.showAtPosition({ x: e.pageX, y: e.pageY });
|
|
}
|
|
getElFromOverview(path) {
|
|
const selector = `[data-path='${CSS.escape(path)}']`;
|
|
if (!this.listEl)
|
|
return null;
|
|
const el = this.listEl.querySelector(selector);
|
|
return el;
|
|
}
|
|
};
|
|
async function updateYaml(plugin, ctx, el, yaml, addLinkList) {
|
|
const NO_CODEBLOCK_END = -1;
|
|
const file = plugin.app.vault.getAbstractFileByPath(ctx.sourcePath);
|
|
if (!(file instanceof import_obsidian49.TFile))
|
|
return;
|
|
let stringYaml = (0, import_obsidian49.stringifyYaml)(yaml);
|
|
plugin.app.vault.process(file, (text) => {
|
|
const info = ctx.getSectionInfo(el);
|
|
if (stringYaml[stringYaml.length - 1] !== "\n") {
|
|
stringYaml += "\n";
|
|
}
|
|
if (info) {
|
|
const { lineStart } = info;
|
|
const lineEnd = getCodeBlockEndLine(text, lineStart);
|
|
if (lineEnd === NO_CODEBLOCK_END || !lineEnd)
|
|
return text;
|
|
const lineLength = lineEnd - lineStart;
|
|
const lines = text.split("\n");
|
|
let overviewBlock = `\`\`\`folder-overview
|
|
${stringYaml}\`\`\``;
|
|
overviewBlock += addLinkList ? `
|
|
<span class="fv-link-list-start" id="${yaml.id}"></span>
|
|
<span class="fv-link-list-end" id="${yaml.id}"></span>` : "";
|
|
lines.splice(lineStart, lineLength + 1, overviewBlock);
|
|
return lines.join("\n");
|
|
}
|
|
getOverviews(plugin, file).then((overviews) => {
|
|
overviews.forEach((overview) => {
|
|
if (overview.id !== yaml.id)
|
|
return;
|
|
const isInCallout = typeof overview.isInCallout === "boolean" ? overview.isInCallout : false;
|
|
updateYamlById(plugin, yaml.id, file, yaml, addLinkList, isInCallout);
|
|
});
|
|
});
|
|
return text;
|
|
});
|
|
}
|
|
async function getOverviews(plugin, file) {
|
|
if (!file)
|
|
return [];
|
|
const overviews = [];
|
|
const content = await plugin.app.vault.read(file);
|
|
if (!content)
|
|
return overviews;
|
|
const yamlBlocks = content.match(/^(?!>).*```folder-overview\n(?:^(?!>).*[\r\n]*)*?^```$/gm);
|
|
const calloutYamlBlocks = content.match(/^> ```folder-overview\n([\s\S]*?)```/gm);
|
|
if (calloutYamlBlocks) {
|
|
for (const block of calloutYamlBlocks) {
|
|
const cleanedBlock = block.replace(/^> ```folder-overview\n/, "").replace(/```$/, "").replace(/^> ?/gm, "");
|
|
const yaml = (0, import_obsidian49.parseYaml)(cleanedBlock);
|
|
if (yaml) {
|
|
yaml.isInCallout = true;
|
|
overviews.push(yaml);
|
|
}
|
|
}
|
|
}
|
|
if (!yamlBlocks)
|
|
return overviews;
|
|
for (const block of yamlBlocks) {
|
|
const yaml = (0, import_obsidian49.parseYaml)(block.replace("```folder-overview\n", "").replace("```", ""));
|
|
if (!yaml)
|
|
continue;
|
|
overviews.push(yaml);
|
|
}
|
|
return overviews;
|
|
}
|
|
async function hasOverviewYaml(plugin, file) {
|
|
const content = await plugin.app.vault.read(file);
|
|
if (!content)
|
|
return false;
|
|
const yamlBlocks = content.match(/```folder-overview\n([\s\S]*?)```/g);
|
|
return !!yamlBlocks;
|
|
}
|
|
var CustomMarkdownRenderChild = class extends import_obsidian49.MarkdownRenderChild {
|
|
constructor(el, folderOverview) {
|
|
super(el);
|
|
this.folderOverview = folderOverview;
|
|
}
|
|
onunload() {
|
|
this.folderOverview.disconnectListeners();
|
|
}
|
|
};
|
|
function sortFiles(files, yaml, plugin) {
|
|
var _a, _b;
|
|
if (!(yaml == null ? void 0 : yaml.sortBy)) {
|
|
const defaultSettings = plugin instanceof FolderNotesPlugin ? plugin.settings.defaultOverview : plugin.settings.defaultOverviewSettings;
|
|
yaml.sortBy = (_a = defaultSettings.sortBy) != null ? _a : "name";
|
|
yaml.sortByAsc = (_b = defaultSettings.sortByAsc) != null ? _b : false;
|
|
}
|
|
const collator = new Intl.Collator(void 0, { numeric: true, sensitivity: "base" });
|
|
const FOLDER_FIRST = -1;
|
|
const FILE_FIRST = 1;
|
|
const EQUAL = 0;
|
|
function compareFilesAndFolders(a, b) {
|
|
const a_IsFolder = a instanceof import_obsidian49.TFolder;
|
|
const b_IsFolder = b instanceof import_obsidian49.TFolder;
|
|
const a_IsFile = a instanceof import_obsidian49.TFile;
|
|
const b_IsFile = b instanceof import_obsidian49.TFile;
|
|
if (a_IsFolder && !b_IsFolder) {
|
|
return FOLDER_FIRST;
|
|
}
|
|
if (!a_IsFolder && b_IsFolder) {
|
|
return FILE_FIRST;
|
|
}
|
|
if (a_IsFolder && b_IsFolder) {
|
|
return yaml.sortByAsc ? collator.compare(a.name, b.name) : collator.compare(b.name, a.name);
|
|
}
|
|
if (a_IsFile && b_IsFile) {
|
|
return compareFiles(a, b);
|
|
}
|
|
return EQUAL;
|
|
}
|
|
function compareFiles(a, b) {
|
|
if (yaml.sortBy === "created") {
|
|
return yaml.sortByAsc ? a.stat.ctime - b.stat.ctime : b.stat.ctime - a.stat.ctime;
|
|
} else if (yaml.sortBy === "modified") {
|
|
return yaml.sortByAsc ? a.stat.mtime - b.stat.mtime : b.stat.mtime - a.stat.mtime;
|
|
} else if (yaml.sortBy === "name") {
|
|
return yaml.sortByAsc ? collator.compare(a.basename, b.basename) : collator.compare(b.basename, a.basename);
|
|
}
|
|
return 0;
|
|
}
|
|
files.sort(compareFilesAndFolders);
|
|
return files;
|
|
}
|
|
async function filterFiles(files, plugin, sourceFolderPath, depth, pathBlacklist, yaml, sourceFile) {
|
|
const filteredFiles = await Promise.all(files.map(async (file) => filterSingleFile(file, plugin, sourceFolderPath, depth, pathBlacklist, yaml, sourceFile)));
|
|
return filteredFiles.filter((file) => file !== null);
|
|
}
|
|
async function filterSingleFile(file, plugin, sourceFolderPath, depth, pathBlacklist, yaml, sourceFile) {
|
|
const folderPath = getFolderPathFromString(file.path);
|
|
const dontShowFolderNote = pathBlacklist.includes(file.path);
|
|
const isSubfolder = isFileInSubfolder(sourceFolderPath, folderPath);
|
|
const isSourceFile = sourceFile ? file.path === sourceFile.path : false;
|
|
const isFile = file instanceof import_obsidian49.TFile;
|
|
const includeTypes = yaml.includeTypes || [];
|
|
const extension = isFile ? file.extension.toLowerCase() : "";
|
|
const imageTypes = ["jpg", "jpeg", "png", "gif", "svg", "webp"];
|
|
const videoTypes = ["mp4", "webm", "ogv", "mov", "mkv"];
|
|
const audioTypes = [
|
|
"mp3",
|
|
"wav",
|
|
"m4a",
|
|
"3gp",
|
|
"flac",
|
|
"ogg",
|
|
"oga",
|
|
"opus"
|
|
];
|
|
if (isFile && !isFileTypeIncluded(extension, includeTypes, imageTypes, videoTypes, audioTypes)) {
|
|
return null;
|
|
}
|
|
const isExcludedFromOverview = await getIsExcludedFromOverview(plugin, file);
|
|
if (shouldExcludeFile(dontShowFolderNote, yaml.showFolderNotes, isSubfolder, isSourceFile, isExcludedFromOverview)) {
|
|
return null;
|
|
}
|
|
const fileDepth = getFileDepth(file.path, sourceFolderPath);
|
|
return fileDepth <= depth ? file : null;
|
|
}
|
|
function isFileTypeIncluded(extension, includeTypes, imageTypes, videoTypes, audioTypes) {
|
|
if (includeTypes.length === 0 || includeTypes.includes("all"))
|
|
return true;
|
|
if ((extension === "md" || extension === "markdown") && includeTypes.includes("markdown"))
|
|
return true;
|
|
if (extension === "canvas" && includeTypes.includes("canvas"))
|
|
return true;
|
|
if (extension === "pdf" && includeTypes.includes("pdf"))
|
|
return true;
|
|
if (imageTypes.includes(extension) && includeTypes.includes("image"))
|
|
return true;
|
|
if (videoTypes.includes(extension) && includeTypes.includes("video"))
|
|
return true;
|
|
if (audioTypes.includes(extension) && includeTypes.includes("audio"))
|
|
return true;
|
|
return false;
|
|
}
|
|
function isFileInSubfolder(sourceFolderPath, folderPath) {
|
|
return sourceFolderPath === "/" || folderPath.startsWith(sourceFolderPath);
|
|
}
|
|
async function getIsExcludedFromOverview(plugin, file) {
|
|
var _a;
|
|
if (plugin instanceof FolderNotesPlugin) {
|
|
const excluded = getExcludedFolder(plugin, file.path, true);
|
|
return (_a = excluded == null ? void 0 : excluded.excludeFromFolderOverview) != null ? _a : false;
|
|
}
|
|
return false;
|
|
}
|
|
function shouldExcludeFile(dontShowFolderNote, showFolderNotes, isSubfolder, isSourceFile, isExcludedFromOverview) {
|
|
return dontShowFolderNote && !showFolderNotes || !isSubfolder || isSourceFile || isExcludedFromOverview;
|
|
}
|
|
function getFileDepth(filePath, sourceFolderPath) {
|
|
return filePath.split("/").length - (sourceFolderPath === "/" ? 0 : sourceFolderPath.split("/").length);
|
|
}
|
|
function getAllFiles(files, sourceFolderPath, depth) {
|
|
const allFiles = [];
|
|
const getDepth = (filePath) => {
|
|
return filePath.split("/").length - sourceFolderPath.split("/").length;
|
|
};
|
|
files.forEach((file) => {
|
|
const fileDepth = getDepth(file.path);
|
|
if (file instanceof import_obsidian49.TFolder) {
|
|
if (fileDepth < depth) {
|
|
allFiles.push(...getAllFiles(file.children, sourceFolderPath, depth));
|
|
}
|
|
} else {
|
|
allFiles.push(file);
|
|
}
|
|
});
|
|
return allFiles;
|
|
}
|
|
|
|
// src/obsidian-folder-overview/src/view.ts
|
|
var FOLDER_OVERVIEW_VIEW = "folder-overview-view";
|
|
var FolderOverviewView = class extends import_obsidian50.ItemView {
|
|
constructor(leaf, plugin) {
|
|
super(leaf);
|
|
this.contentEl = this.containerEl.children[1];
|
|
this.plugin = plugin;
|
|
this.display = this.display.bind(this);
|
|
if (plugin instanceof FolderOverviewPlugin) {
|
|
this.defaultSettings = plugin.settings.defaultOverviewSettings;
|
|
} else if (plugin instanceof FolderNotesPlugin) {
|
|
this.defaultSettings = plugin.settings.defaultOverview;
|
|
} else {
|
|
throw new Error("Plugin must be an instance of FolderOverviewPlugin or FolderNotesPlugin");
|
|
}
|
|
this.yaml = this.defaultSettings;
|
|
this.registerEvent(this.plugin.app.workspace.on("file-open", (file) => {
|
|
this.activeFile = file;
|
|
this.display(this.contentEl, this.yaml, this.plugin, this.defaultSettings, this.display, void 0, void 0, file, void 0, void 0, "all");
|
|
}));
|
|
}
|
|
getViewType() {
|
|
return FOLDER_OVERVIEW_VIEW;
|
|
}
|
|
getDisplayText() {
|
|
return "Folder Overview settings";
|
|
}
|
|
getIcon() {
|
|
return "settings";
|
|
}
|
|
async onOpen() {
|
|
this.display(this.contentEl, this.yaml, this.plugin, this.defaultSettings, this.display, void 0, void 0, this.activeFile);
|
|
}
|
|
async display(contentEl, yaml, plugin, defaultSettings, display, el, ctx, file, settingsTab, modal, changedSection) {
|
|
this.contentEl = contentEl;
|
|
this.yaml = yaml;
|
|
this.defaultSettings = defaultSettings;
|
|
this.changedSection = changedSection;
|
|
if (file) {
|
|
this.activeFile = file;
|
|
}
|
|
let header = contentEl.querySelector(".fn-folder-overview-header");
|
|
if (!header) {
|
|
header = contentEl.createEl("h4", {
|
|
cls: "fn-folder-overview-header",
|
|
text: "Folder Overview settings"
|
|
});
|
|
}
|
|
const activeFile = plugin.app.workspace.getActiveFile();
|
|
const overviews = await getOverviews(plugin, activeFile);
|
|
let settingsContainer = contentEl.querySelector(".fn-settings-container");
|
|
if (!settingsContainer) {
|
|
settingsContainer = contentEl.createDiv({ cls: "fn-settings-container" });
|
|
}
|
|
let dropdown = settingsContainer.querySelector(".fn-select-overview-setting");
|
|
if (!dropdown || changedSection === "all" || changedSection === "dropdown") {
|
|
if (dropdown) {
|
|
settingsContainer.empty();
|
|
}
|
|
dropdown = settingsContainer.createDiv({ cls: "fn-select-overview-setting" });
|
|
const overviewSetting = new import_obsidian50.Setting(dropdown);
|
|
overviewSetting.setName("Select overview").setClass("fn-select-overview-setting").addDropdown((cb) => {
|
|
var _a;
|
|
if (activeFile) {
|
|
const titleCounts = {};
|
|
const options = overviews.reduce((acc, overview) => {
|
|
var _a2;
|
|
const title = parseOverviewTitle(overview, plugin, activeFile.parent, ((_a2 = activeFile.parent) == null ? void 0 : _a2.path) || "", activeFile);
|
|
const count = (titleCounts[title] || 0) + 1;
|
|
titleCounts[title] = count;
|
|
acc[overview.id] = count > 1 ? `${title} (${count})` : title;
|
|
return acc;
|
|
}, {});
|
|
cb.addOptions(options);
|
|
}
|
|
cb.addOption("default", "Default");
|
|
cb.setValue((_a = yaml == null ? void 0 : yaml.id) != null ? _a : "default");
|
|
const isDefault = cb.getValue() === "default";
|
|
const isYamlIdEmpty = !(yaml == null ? void 0 : yaml.id.trim());
|
|
const isCbValueEmpty = cb.getValue().trim() === "";
|
|
if (isDefault || isYamlIdEmpty || isCbValueEmpty) {
|
|
yaml = defaultSettings;
|
|
cb.setValue("default");
|
|
} else {
|
|
const foundOverview = overviews.find((overview) => overview.id === yaml.id);
|
|
yaml = foundOverview;
|
|
}
|
|
cb.onChange(async (value) => {
|
|
if (value === "default") {
|
|
yaml = defaultSettings;
|
|
} else {
|
|
const foundOverview = overviews.find((overview) => overview.id === value);
|
|
yaml = foundOverview;
|
|
}
|
|
await display(contentEl, yaml, plugin, defaultSettings, display, void 0, void 0, activeFile, void 0, void 0, "all");
|
|
});
|
|
});
|
|
}
|
|
this.yaml = yaml;
|
|
await createOverviewSettings(settingsContainer, yaml, plugin, defaultSettings, display, void 0, void 0, activeFile, void 0, void 0, changedSection);
|
|
}
|
|
};
|
|
|
|
// src/obsidian-folder-overview/src/utils/FmtpHandler.ts
|
|
var import_front_matter_plugin_api_provider2 = __toESM(require_lib());
|
|
var FrontMatterTitlePluginHandler2 = class {
|
|
constructor(plugin) {
|
|
this.api = null;
|
|
this.deffer = null;
|
|
this.modifiedFolders = /* @__PURE__ */ new Map();
|
|
this.eventRef = null;
|
|
this.dispatcher = null;
|
|
this.plugin = plugin;
|
|
this.app = plugin.app;
|
|
(async () => {
|
|
var _a;
|
|
this.deffer = (0, import_front_matter_plugin_api_provider2.getDefer)(this.app);
|
|
if (this.deffer.isPluginReady()) {
|
|
this.api = this.deffer.getApi();
|
|
} else {
|
|
await this.deffer.awaitPlugin();
|
|
this.api = this.deffer.getApi();
|
|
if (!this.deffer.isFeaturesReady()) {
|
|
await this.deffer.awaitFeatures();
|
|
}
|
|
}
|
|
const dispatcher = (_a = this.api) == null ? void 0 : _a.getEventDispatcher();
|
|
if (dispatcher) {
|
|
this.dispatcher = dispatcher;
|
|
}
|
|
})();
|
|
}
|
|
deleteEvent() {
|
|
var _a;
|
|
if (this.eventRef) {
|
|
(_a = this.dispatcher) == null ? void 0 : _a.removeListener(this.eventRef);
|
|
}
|
|
}
|
|
async getNewFileName(file) {
|
|
var _a, _b, _c;
|
|
const resolver = (_b = (_a = this.api) == null ? void 0 : _a.getResolverFactory()) == null ? void 0 : _b.createResolver("#feature-id#");
|
|
const changedName = resolver == null ? void 0 : resolver.resolve((_c = file == null ? void 0 : file.path) != null ? _c : "");
|
|
return changedName != null ? changedName : null;
|
|
}
|
|
};
|
|
|
|
// src/obsidian-folder-overview/src/main.ts
|
|
var FolderOverviewPlugin = class extends import_obsidian51.Plugin {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.settings = DEFAULT_SETTINGS;
|
|
this.settingsTab = new SettingsTab(this);
|
|
this.fvIndexDB = new FvIndexDB(this);
|
|
this.updateOverviewView = updateOverviewView;
|
|
this.updateViewDropdown = updateViewDropdown;
|
|
}
|
|
async onload() {
|
|
await this.loadSettings();
|
|
this.addSettingTab(this.settingsTab);
|
|
this.settingsTab.display();
|
|
registerOverviewCommands(this);
|
|
this.app.workspace.onLayoutReady(async () => {
|
|
this.registerView(FOLDER_OVERVIEW_VIEW, (leaf) => {
|
|
return new FolderOverviewView(leaf, this);
|
|
});
|
|
if (this.app.plugins.getPlugin("obsidian-front-matter-title-plugin")) {
|
|
this.fmtpHandler = new FrontMatterTitlePluginHandler2(this);
|
|
}
|
|
if (this.settings.globalSettings.autoUpdateLinks) {
|
|
this.fvIndexDB.init(false);
|
|
}
|
|
});
|
|
this.app.vault.on("rename", () => this.handleVaultChange());
|
|
this.app.vault.on("create", () => this.handleVaultChange());
|
|
this.app.vault.on("delete", () => this.handleVaultChange());
|
|
this.registerMarkdownCodeBlockProcessor("folder-overview", (source, el, ctx) => {
|
|
this.handleOverviewBlock(source, el, ctx);
|
|
});
|
|
console.debug("loading Folder Overview plugin");
|
|
}
|
|
handleVaultChange() {
|
|
const DEBOUNCE_DELAY_MS = 2e3;
|
|
if (!this.settings.globalSettings.autoUpdateLinks)
|
|
return;
|
|
(0, import_obsidian51.debounce)(() => {
|
|
updateAllOverviews(this);
|
|
}, DEBOUNCE_DELAY_MS, true)();
|
|
}
|
|
async handleOverviewBlock(source, el, ctx) {
|
|
const observer = new MutationObserver(() => {
|
|
var _a;
|
|
const editButton = (_a = el.parentElement) == null ? void 0 : _a.childNodes.item(1);
|
|
if (editButton) {
|
|
editButton.addEventListener("click", (e) => {
|
|
e.stopImmediatePropagation();
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
new FolderOverviewSettings(this.app, this, (0, import_obsidian51.parseYaml)(source), ctx, el, this.settings.defaultOverviewSettings).open();
|
|
}, { capture: true });
|
|
}
|
|
});
|
|
observer.observe(el, {
|
|
childList: true,
|
|
subtree: true
|
|
});
|
|
try {
|
|
this.app.workspace.onLayoutReady(async () => {
|
|
const folderOverview = new FolderOverview(this, ctx, source, el, this.settings.defaultOverviewSettings);
|
|
await folderOverview.create(this, el, ctx);
|
|
this.updateOverviewView(this);
|
|
});
|
|
} catch (e) {
|
|
new import_obsidian51.Notice("Error creating folder overview (folder notes plugin) - check console for more details");
|
|
console.error(e);
|
|
}
|
|
}
|
|
async onunload() {
|
|
console.debug("Unloading Folder Overview plugin");
|
|
}
|
|
async loadSettings() {
|
|
var _a;
|
|
const data = await this.loadData();
|
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, data);
|
|
if (!this.settings.defaultOverviewSettings) {
|
|
this.settings.defaultOverviewSettings = {
|
|
...DEFAULT_SETTINGS.defaultOverviewSettings,
|
|
...(_a = data == null ? void 0 : data.defaultOverviewSettings) != null ? _a : {}
|
|
};
|
|
}
|
|
if ((data == null ? void 0 : data.firstTimeInsertOverview) === void 0) {
|
|
this.settings.firstTimeInsertOverview = true;
|
|
}
|
|
}
|
|
async saveSettings() {
|
|
await this.saveData(this.settings);
|
|
}
|
|
async activateOverviewView() {
|
|
const { workspace } = this.app;
|
|
let leaf = null;
|
|
const leaves = workspace.getLeavesOfType(FOLDER_OVERVIEW_VIEW);
|
|
if (leaves.length > 0) {
|
|
leaf = leaves[0];
|
|
} else {
|
|
leaf = workspace.getRightLeaf(false);
|
|
await (leaf == null ? void 0 : leaf.setViewState({ type: FOLDER_OVERVIEW_VIEW, active: true }));
|
|
}
|
|
if (!leaf)
|
|
return;
|
|
workspace.revealLeaf(leaf);
|
|
}
|
|
};
|
|
async function updateOverviewView(plugin, newYaml) {
|
|
const { workspace } = plugin.app;
|
|
const leaf = workspace.getLeavesOfType(FOLDER_OVERVIEW_VIEW)[0];
|
|
if (!leaf)
|
|
return;
|
|
const view = leaf.view;
|
|
if (!view)
|
|
return;
|
|
if (!view.yaml)
|
|
return;
|
|
const yaml = view.yaml.id === "" ? view.yaml : newYaml;
|
|
view.display(view.contentEl, yaml != null ? yaml : view.yaml, plugin, view.defaultSettings, view.display, void 0, void 0, view.activeFile, plugin.settingsTab, view.modal, "all");
|
|
}
|
|
async function updateViewDropdown(plugin) {
|
|
const { workspace } = plugin.app;
|
|
const leaf = workspace.getLeavesOfType(FOLDER_OVERVIEW_VIEW)[0];
|
|
if (!leaf)
|
|
return;
|
|
const view = leaf.view;
|
|
view.display(view.contentEl, view.yaml, plugin, view.defaultSettings, view.display, void 0, void 0, view.activeFile, plugin.settingsTab, view.modal, "dropdown");
|
|
}
|