/*
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(app2) {
var _a, _b, _c;
return (_c = (_b = (_a = app2 === null || app2 === void 0 ? void 0 : app2.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(app2) {
var _a, _b, _c, _d;
const plugin = (_b = (_a = app2 === null || app2 === void 0 ? void 0 : app2.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(app2) {
return new ApiWrapper(null, app2);
}
exports.getApiSafe = getApiSafe;
var ApiWrapper = class {
constructor(api, app2) {
this.api = api;
this.app = app2;
}
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/main.ts
var main_exports = {};
__export(main_exports, {
default: () => FolderNotesPlugin
});
module.exports = __toCommonJS(main_exports);
var import_obsidian48 = require("obsidian");
// src/settings/SettingsTab.ts
var import_obsidian37 = require("obsidian");
// src/modals/ExistingNote.ts
var import_obsidian = require("obsidian");
var ExistingFolderNoteModal = class extends import_obsidian.Modal {
constructor(app2, plugin, file, folder, folderNote) {
super(app2);
this.plugin = plugin;
this.app = app2;
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", async () => {
this.plugin.settings.showRenameConfirmation = false;
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", async () => {
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", async () => {
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 document. \u26A0==")) {
return;
}
if (templaterEnabled) {
return await templaterPlugin.write_template_to_file(templateFile, file);
} else if (templatesEnabled) {
if (leaf instanceof import_obsidian2.WorkspaceLeaf) {
await leaf.openFile(file);
}
return await templatesPlugin.instance.insertTemplate(templateFile);
} else {
await plugin.app.vault.modify(file, templateContent);
}
} catch (e) {
console.error(e);
}
}
}
function getTemplatePlugins(app2) {
var _a;
const templatesPlugin = app2.internalPlugins.plugins.templates;
const templatesEnabled = templatesPlugin.enabled;
const templaterPlugin = app2.plugins.plugins["templater-obsidian"];
const templaterEnabled = app2.plugins.enabledPlugins.has("templater-obsidian");
const templaterEmptyFileTemplate = templaterPlugin && ((_a = templaterPlugin.settings) == null ? void 0 : _a.empty_file_template);
const templateFolder = templatesEnabled ? templatesPlugin.instance.options.folder : templaterPlugin == null ? void 0 : templaterPlugin.settings.template_folder;
return {
templatesPlugin,
templatesEnabled,
templaterPlugin: templaterPlugin == null ? void 0 : templaterPlugin.templater,
templaterEnabled,
templaterEmptyFileTemplate,
templateFolder
};
}
// src/functions/folderNoteFunctions.ts
var import_obsidian17 = require("obsidian");
// src/modals/DeleteConfirmation.ts
var import_obsidian3 = require("obsidian");
var DeleteConfirmationModal = class extends import_obsidian3.Modal {
constructor(app2, plugin, file) {
super(app2);
this.plugin = plugin;
this.app = app2;
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 getFileNameFromPathString(path) {
return path.substring(path.lastIndexOf("/") >= 0 ? path.lastIndexOf("/") + 1 : 0);
}
function getFolderNameFromPathString(path) {
if (path.endsWith(".md") || path.endsWith(".canvas")) {
return path.split("/").slice(-2)[0];
} else {
return path.split("/").slice(-1)[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 "/";
} else {
return folderPath;
}
}
function getFileExplorer(plugin) {
return plugin.app.workspace.getLeavesOfType("file-explorer")[0];
}
function getFileExplorerActiveFolder() {
var _a, _b, _c;
const view = this.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;
}
// src/ExcludeFolders/ExcludePattern.ts
var ExcludePattern = class {
constructor(pattern, position, id, plugin) {
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_obsidian15 = require("obsidian");
// src/suggesters/FolderSuggester.ts
var import_obsidian6 = require("obsidian");
// src/suggesters/Suggest.ts
var import_obsidian5 = require("obsidian");
// node_modules/@popperjs/core/lib/enums.js
var top = "top";
var bottom = "bottom";
var right = "right";
var left = "left";
var auto = "auto";
var basePlacements = [top, bottom, right, left];
var start = "start";
var end = "end";
var clippingParents = "clippingParents";
var viewport = "viewport";
var popper = "popper";
var reference = "reference";
var variationPlacements = /* @__PURE__ */ basePlacements.reduce(function(acc, placement) {
return acc.concat([placement + "-" + start, placement + "-" + end]);
}, []);
var placements = /* @__PURE__ */ [].concat(basePlacements, [auto]).reduce(function(acc, placement) {
return acc.concat([placement, placement + "-" + start, placement + "-" + end]);
}, []);
var beforeRead = "beforeRead";
var read = "read";
var afterRead = "afterRead";
var beforeMain = "beforeMain";
var main = "main";
var afterMain = "afterMain";
var beforeWrite = "beforeWrite";
var write = "write";
var afterWrite = "afterWrite";
var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];
// node_modules/@popperjs/core/lib/dom-utils/getNodeName.js
function getNodeName(element) {
return element ? (element.nodeName || "").toLowerCase() : null;
}
// node_modules/@popperjs/core/lib/dom-utils/getWindow.js
function getWindow(node) {
if (node == null) {
return window;
}
if (node.toString() !== "[object Window]") {
var ownerDocument = node.ownerDocument;
return ownerDocument ? ownerDocument.defaultView || window : window;
}
return node;
}
// node_modules/@popperjs/core/lib/dom-utils/instanceOf.js
function isElement(node) {
var OwnElement = getWindow(node).Element;
return node instanceof OwnElement || node instanceof Element;
}
function isHTMLElement(node) {
var OwnElement = getWindow(node).HTMLElement;
return node instanceof OwnElement || node instanceof HTMLElement;
}
function isShadowRoot(node) {
if (typeof ShadowRoot === "undefined") {
return false;
}
var OwnElement = getWindow(node).ShadowRoot;
return node instanceof OwnElement || node instanceof ShadowRoot;
}
// node_modules/@popperjs/core/lib/modifiers/applyStyles.js
function applyStyles(_ref) {
var state = _ref.state;
Object.keys(state.elements).forEach(function(name) {
var style = state.styles[name] || {};
var attributes = state.attributes[name] || {};
var element = state.elements[name];
if (!isHTMLElement(element) || !getNodeName(element)) {
return;
}
Object.assign(element.style, style);
Object.keys(attributes).forEach(function(name2) {
var value = attributes[name2];
if (value === false) {
element.removeAttribute(name2);
} else {
element.setAttribute(name2, value === true ? "" : value);
}
});
});
}
function effect(_ref2) {
var state = _ref2.state;
var initialStyles = {
popper: {
position: state.options.strategy,
left: "0",
top: "0",
margin: "0"
},
arrow: {
position: "absolute"
},
reference: {}
};
Object.assign(state.elements.popper.style, initialStyles.popper);
state.styles = initialStyles;
if (state.elements.arrow) {
Object.assign(state.elements.arrow.style, initialStyles.arrow);
}
return function() {
Object.keys(state.elements).forEach(function(name) {
var element = state.elements[name];
var attributes = state.attributes[name] || {};
var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]);
var style = styleProperties.reduce(function(style2, property) {
style2[property] = "";
return style2;
}, {});
if (!isHTMLElement(element) || !getNodeName(element)) {
return;
}
Object.assign(element.style, style);
Object.keys(attributes).forEach(function(attribute) {
element.removeAttribute(attribute);
});
});
};
}
var applyStyles_default = {
name: "applyStyles",
enabled: true,
phase: "write",
fn: applyStyles,
effect,
requires: ["computeStyles"]
};
// node_modules/@popperjs/core/lib/utils/getBasePlacement.js
function getBasePlacement(placement) {
return placement.split("-")[0];
}
// node_modules/@popperjs/core/lib/utils/math.js
var max = Math.max;
var min = Math.min;
var round = Math.round;
// node_modules/@popperjs/core/lib/utils/userAgent.js
function getUAString() {
var uaData = navigator.userAgentData;
if (uaData != null && uaData.brands && Array.isArray(uaData.brands)) {
return uaData.brands.map(function(item) {
return item.brand + "/" + item.version;
}).join(" ");
}
return navigator.userAgent;
}
// node_modules/@popperjs/core/lib/dom-utils/isLayoutViewport.js
function isLayoutViewport() {
return !/^((?!chrome|android).)*safari/i.test(getUAString());
}
// node_modules/@popperjs/core/lib/dom-utils/getBoundingClientRect.js
function getBoundingClientRect(element, includeScale, isFixedStrategy) {
if (includeScale === void 0) {
includeScale = false;
}
if (isFixedStrategy === void 0) {
isFixedStrategy = false;
}
var clientRect = element.getBoundingClientRect();
var scaleX = 1;
var scaleY = 1;
if (includeScale && isHTMLElement(element)) {
scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1;
scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1;
}
var _ref = isElement(element) ? getWindow(element) : window, visualViewport = _ref.visualViewport;
var addVisualOffsets = !isLayoutViewport() && isFixedStrategy;
var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX;
var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY;
var width = clientRect.width / scaleX;
var height = clientRect.height / scaleY;
return {
width,
height,
top: y,
right: x + width,
bottom: y + height,
left: x,
x,
y
};
}
// node_modules/@popperjs/core/lib/dom-utils/getLayoutRect.js
function getLayoutRect(element) {
var clientRect = getBoundingClientRect(element);
var width = element.offsetWidth;
var height = element.offsetHeight;
if (Math.abs(clientRect.width - width) <= 1) {
width = clientRect.width;
}
if (Math.abs(clientRect.height - height) <= 1) {
height = clientRect.height;
}
return {
x: element.offsetLeft,
y: element.offsetTop,
width,
height
};
}
// node_modules/@popperjs/core/lib/dom-utils/contains.js
function contains(parent, child) {
var rootNode = child.getRootNode && child.getRootNode();
if (parent.contains(child)) {
return true;
} else if (rootNode && isShadowRoot(rootNode)) {
var next = child;
do {
if (next && parent.isSameNode(next)) {
return true;
}
next = next.parentNode || next.host;
} while (next);
}
return false;
}
// node_modules/@popperjs/core/lib/dom-utils/getComputedStyle.js
function getComputedStyle(element) {
return getWindow(element).getComputedStyle(element);
}
// node_modules/@popperjs/core/lib/dom-utils/isTableElement.js
function isTableElement(element) {
return ["table", "td", "th"].indexOf(getNodeName(element)) >= 0;
}
// node_modules/@popperjs/core/lib/dom-utils/getDocumentElement.js
function getDocumentElement(element) {
return ((isElement(element) ? element.ownerDocument : element.document) || window.document).documentElement;
}
// node_modules/@popperjs/core/lib/dom-utils/getParentNode.js
function getParentNode(element) {
if (getNodeName(element) === "html") {
return element;
}
return element.assignedSlot || element.parentNode || (isShadowRoot(element) ? element.host : null) || getDocumentElement(element);
}
// node_modules/@popperjs/core/lib/dom-utils/getOffsetParent.js
function getTrueOffsetParent(element) {
if (!isHTMLElement(element) || getComputedStyle(element).position === "fixed") {
return null;
}
return element.offsetParent;
}
function getContainingBlock(element) {
var isFirefox = /firefox/i.test(getUAString());
var isIE = /Trident/i.test(getUAString());
if (isIE && isHTMLElement(element)) {
var elementCss = getComputedStyle(element);
if (elementCss.position === "fixed") {
return null;
}
}
var currentNode = getParentNode(element);
if (isShadowRoot(currentNode)) {
currentNode = currentNode.host;
}
while (isHTMLElement(currentNode) && ["html", "body"].indexOf(getNodeName(currentNode)) < 0) {
var css = getComputedStyle(currentNode);
if (css.transform !== "none" || css.perspective !== "none" || css.contain === "paint" || ["transform", "perspective"].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === "filter" || isFirefox && css.filter && css.filter !== "none") {
return currentNode;
} else {
currentNode = currentNode.parentNode;
}
}
return null;
}
function getOffsetParent(element) {
var window2 = getWindow(element);
var offsetParent = getTrueOffsetParent(element);
while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === "static") {
offsetParent = getTrueOffsetParent(offsetParent);
}
if (offsetParent && (getNodeName(offsetParent) === "html" || getNodeName(offsetParent) === "body" && getComputedStyle(offsetParent).position === "static")) {
return window2;
}
return offsetParent || getContainingBlock(element) || window2;
}
// node_modules/@popperjs/core/lib/utils/getMainAxisFromPlacement.js
function getMainAxisFromPlacement(placement) {
return ["top", "bottom"].indexOf(placement) >= 0 ? "x" : "y";
}
// node_modules/@popperjs/core/lib/utils/within.js
function within(min2, value, max2) {
return max(min2, min(value, max2));
}
function withinMaxClamp(min2, value, max2) {
var v = within(min2, value, max2);
return v > max2 ? max2 : v;
}
// node_modules/@popperjs/core/lib/utils/getFreshSideObject.js
function getFreshSideObject() {
return {
top: 0,
right: 0,
bottom: 0,
left: 0
};
}
// node_modules/@popperjs/core/lib/utils/mergePaddingObject.js
function mergePaddingObject(paddingObject) {
return Object.assign({}, getFreshSideObject(), paddingObject);
}
// node_modules/@popperjs/core/lib/utils/expandToHashMap.js
function expandToHashMap(value, keys) {
return keys.reduce(function(hashMap, key) {
hashMap[key] = value;
return hashMap;
}, {});
}
// node_modules/@popperjs/core/lib/modifiers/arrow.js
var toPaddingObject = function toPaddingObject2(padding, state) {
padding = typeof padding === "function" ? padding(Object.assign({}, state.rects, {
placement: state.placement
})) : padding;
return mergePaddingObject(typeof padding !== "number" ? padding : expandToHashMap(padding, basePlacements));
};
function arrow(_ref) {
var _state$modifiersData$;
var state = _ref.state, name = _ref.name, options = _ref.options;
var arrowElement = state.elements.arrow;
var popperOffsets2 = state.modifiersData.popperOffsets;
var basePlacement = getBasePlacement(state.placement);
var axis = getMainAxisFromPlacement(basePlacement);
var isVertical = [left, right].indexOf(basePlacement) >= 0;
var len = isVertical ? "height" : "width";
if (!arrowElement || !popperOffsets2) {
return;
}
var paddingObject = toPaddingObject(options.padding, state);
var arrowRect = getLayoutRect(arrowElement);
var minProp = axis === "y" ? top : left;
var maxProp = axis === "y" ? bottom : right;
var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets2[axis] - state.rects.popper[len];
var startDiff = popperOffsets2[axis] - state.rects.reference[axis];
var arrowOffsetParent = getOffsetParent(arrowElement);
var clientSize = arrowOffsetParent ? axis === "y" ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;
var centerToReference = endDiff / 2 - startDiff / 2;
var min2 = paddingObject[minProp];
var max2 = clientSize - arrowRect[len] - paddingObject[maxProp];
var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;
var offset2 = within(min2, center, max2);
var axisProp = axis;
state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset2, _state$modifiersData$.centerOffset = offset2 - center, _state$modifiersData$);
}
function effect2(_ref2) {
var state = _ref2.state, options = _ref2.options;
var _options$element = options.element, arrowElement = _options$element === void 0 ? "[data-popper-arrow]" : _options$element;
if (arrowElement == null) {
return;
}
if (typeof arrowElement === "string") {
arrowElement = state.elements.popper.querySelector(arrowElement);
if (!arrowElement) {
return;
}
}
if (!contains(state.elements.popper, arrowElement)) {
return;
}
state.elements.arrow = arrowElement;
}
var arrow_default = {
name: "arrow",
enabled: true,
phase: "main",
fn: arrow,
effect: effect2,
requires: ["popperOffsets"],
requiresIfExists: ["preventOverflow"]
};
// node_modules/@popperjs/core/lib/utils/getVariation.js
function getVariation(placement) {
return placement.split("-")[1];
}
// node_modules/@popperjs/core/lib/modifiers/computeStyles.js
var unsetSides = {
top: "auto",
right: "auto",
bottom: "auto",
left: "auto"
};
function roundOffsetsByDPR(_ref, win) {
var x = _ref.x, y = _ref.y;
var dpr = win.devicePixelRatio || 1;
return {
x: round(x * dpr) / dpr || 0,
y: round(y * dpr) / dpr || 0
};
}
function mapToStyles(_ref2) {
var _Object$assign2;
var popper2 = _ref2.popper, popperRect = _ref2.popperRect, placement = _ref2.placement, variation = _ref2.variation, offsets = _ref2.offsets, position = _ref2.position, gpuAcceleration = _ref2.gpuAcceleration, adaptive = _ref2.adaptive, roundOffsets = _ref2.roundOffsets, isFixed = _ref2.isFixed;
var _offsets$x = offsets.x, x = _offsets$x === void 0 ? 0 : _offsets$x, _offsets$y = offsets.y, y = _offsets$y === void 0 ? 0 : _offsets$y;
var _ref3 = typeof roundOffsets === "function" ? roundOffsets({
x,
y
}) : {
x,
y
};
x = _ref3.x;
y = _ref3.y;
var hasX = offsets.hasOwnProperty("x");
var hasY = offsets.hasOwnProperty("y");
var sideX = left;
var sideY = top;
var win = window;
if (adaptive) {
var offsetParent = getOffsetParent(popper2);
var heightProp = "clientHeight";
var widthProp = "clientWidth";
if (offsetParent === getWindow(popper2)) {
offsetParent = getDocumentElement(popper2);
if (getComputedStyle(offsetParent).position !== "static" && position === "absolute") {
heightProp = "scrollHeight";
widthProp = "scrollWidth";
}
}
offsetParent = offsetParent;
if (placement === top || (placement === left || placement === right) && variation === end) {
sideY = bottom;
var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : offsetParent[heightProp];
y -= offsetY - popperRect.height;
y *= gpuAcceleration ? 1 : -1;
}
if (placement === left || (placement === top || placement === bottom) && variation === end) {
sideX = right;
var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : offsetParent[widthProp];
x -= offsetX - popperRect.width;
x *= gpuAcceleration ? 1 : -1;
}
}
var commonStyles = Object.assign({
position
}, adaptive && unsetSides);
var _ref4 = roundOffsets === true ? roundOffsetsByDPR({
x,
y
}, getWindow(popper2)) : {
x,
y
};
x = _ref4.x;
y = _ref4.y;
if (gpuAcceleration) {
var _Object$assign;
return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? "0" : "", _Object$assign[sideX] = hasX ? "0" : "", _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign));
}
return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : "", _Object$assign2[sideX] = hasX ? x + "px" : "", _Object$assign2.transform = "", _Object$assign2));
}
function computeStyles(_ref5) {
var state = _ref5.state, options = _ref5.options;
var _options$gpuAccelerat = options.gpuAcceleration, gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat, _options$adaptive = options.adaptive, adaptive = _options$adaptive === void 0 ? true : _options$adaptive, _options$roundOffsets = options.roundOffsets, roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets;
var commonStyles = {
placement: getBasePlacement(state.placement),
variation: getVariation(state.placement),
popper: state.elements.popper,
popperRect: state.rects.popper,
gpuAcceleration,
isFixed: state.options.strategy === "fixed"
};
if (state.modifiersData.popperOffsets != null) {
state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, {
offsets: state.modifiersData.popperOffsets,
position: state.options.strategy,
adaptive,
roundOffsets
})));
}
if (state.modifiersData.arrow != null) {
state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, {
offsets: state.modifiersData.arrow,
position: "absolute",
adaptive: false,
roundOffsets
})));
}
state.attributes.popper = Object.assign({}, state.attributes.popper, {
"data-popper-placement": state.placement
});
}
var computeStyles_default = {
name: "computeStyles",
enabled: true,
phase: "beforeWrite",
fn: computeStyles,
data: {}
};
// node_modules/@popperjs/core/lib/modifiers/eventListeners.js
var passive = {
passive: true
};
function effect3(_ref) {
var state = _ref.state, instance = _ref.instance, options = _ref.options;
var _options$scroll = options.scroll, scroll = _options$scroll === void 0 ? true : _options$scroll, _options$resize = options.resize, resize = _options$resize === void 0 ? true : _options$resize;
var window2 = getWindow(state.elements.popper);
var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);
if (scroll) {
scrollParents.forEach(function(scrollParent) {
scrollParent.addEventListener("scroll", instance.update, passive);
});
}
if (resize) {
window2.addEventListener("resize", instance.update, passive);
}
return function() {
if (scroll) {
scrollParents.forEach(function(scrollParent) {
scrollParent.removeEventListener("scroll", instance.update, passive);
});
}
if (resize) {
window2.removeEventListener("resize", instance.update, passive);
}
};
}
var eventListeners_default = {
name: "eventListeners",
enabled: true,
phase: "write",
fn: function fn() {
},
effect: effect3,
data: {}
};
// node_modules/@popperjs/core/lib/utils/getOppositePlacement.js
var hash = {
left: "right",
right: "left",
bottom: "top",
top: "bottom"
};
function getOppositePlacement(placement) {
return placement.replace(/left|right|bottom|top/g, function(matched) {
return hash[matched];
});
}
// node_modules/@popperjs/core/lib/utils/getOppositeVariationPlacement.js
var hash2 = {
start: "end",
end: "start"
};
function getOppositeVariationPlacement(placement) {
return placement.replace(/start|end/g, function(matched) {
return hash2[matched];
});
}
// node_modules/@popperjs/core/lib/dom-utils/getWindowScroll.js
function getWindowScroll(node) {
var win = getWindow(node);
var scrollLeft = win.pageXOffset;
var scrollTop = win.pageYOffset;
return {
scrollLeft,
scrollTop
};
}
// node_modules/@popperjs/core/lib/dom-utils/getWindowScrollBarX.js
function getWindowScrollBarX(element) {
return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;
}
// node_modules/@popperjs/core/lib/dom-utils/getViewportRect.js
function getViewportRect(element, strategy) {
var win = getWindow(element);
var html = getDocumentElement(element);
var visualViewport = win.visualViewport;
var width = html.clientWidth;
var height = html.clientHeight;
var x = 0;
var y = 0;
if (visualViewport) {
width = visualViewport.width;
height = visualViewport.height;
var layoutViewport = isLayoutViewport();
if (layoutViewport || !layoutViewport && strategy === "fixed") {
x = visualViewport.offsetLeft;
y = visualViewport.offsetTop;
}
}
return {
width,
height,
x: x + getWindowScrollBarX(element),
y
};
}
// node_modules/@popperjs/core/lib/dom-utils/getDocumentRect.js
function getDocumentRect(element) {
var _element$ownerDocumen;
var html = getDocumentElement(element);
var winScroll = getWindowScroll(element);
var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;
var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);
var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);
var x = -winScroll.scrollLeft + getWindowScrollBarX(element);
var y = -winScroll.scrollTop;
if (getComputedStyle(body || html).direction === "rtl") {
x += max(html.clientWidth, body ? body.clientWidth : 0) - width;
}
return {
width,
height,
x,
y
};
}
// node_modules/@popperjs/core/lib/dom-utils/isScrollParent.js
function isScrollParent(element) {
var _getComputedStyle = getComputedStyle(element), overflow = _getComputedStyle.overflow, overflowX = _getComputedStyle.overflowX, overflowY = _getComputedStyle.overflowY;
return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
}
// node_modules/@popperjs/core/lib/dom-utils/getScrollParent.js
function getScrollParent(node) {
if (["html", "body", "#document"].indexOf(getNodeName(node)) >= 0) {
return node.ownerDocument.body;
}
if (isHTMLElement(node) && isScrollParent(node)) {
return node;
}
return getScrollParent(getParentNode(node));
}
// node_modules/@popperjs/core/lib/dom-utils/listScrollParents.js
function listScrollParents(element, list) {
var _element$ownerDocumen;
if (list === void 0) {
list = [];
}
var scrollParent = getScrollParent(element);
var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body);
var win = getWindow(scrollParent);
var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;
var updatedList = list.concat(target);
return isBody ? updatedList : updatedList.concat(listScrollParents(getParentNode(target)));
}
// node_modules/@popperjs/core/lib/utils/rectToClientRect.js
function rectToClientRect(rect) {
return Object.assign({}, rect, {
left: rect.x,
top: rect.y,
right: rect.x + rect.width,
bottom: rect.y + rect.height
});
}
// node_modules/@popperjs/core/lib/dom-utils/getClippingRect.js
function getInnerBoundingClientRect(element, strategy) {
var rect = getBoundingClientRect(element, false, strategy === "fixed");
rect.top = rect.top + element.clientTop;
rect.left = rect.left + element.clientLeft;
rect.bottom = rect.top + element.clientHeight;
rect.right = rect.left + element.clientWidth;
rect.width = element.clientWidth;
rect.height = element.clientHeight;
rect.x = rect.left;
rect.y = rect.top;
return rect;
}
function getClientRectFromMixedType(element, clippingParent, strategy) {
return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element)));
}
function getClippingParents(element) {
var clippingParents2 = listScrollParents(getParentNode(element));
var canEscapeClipping = ["absolute", "fixed"].indexOf(getComputedStyle(element).position) >= 0;
var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;
if (!isElement(clipperElement)) {
return [];
}
return clippingParents2.filter(function(clippingParent) {
return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== "body";
});
}
function getClippingRect(element, boundary, rootBoundary, strategy) {
var mainClippingParents = boundary === "clippingParents" ? getClippingParents(element) : [].concat(boundary);
var clippingParents2 = [].concat(mainClippingParents, [rootBoundary]);
var firstClippingParent = clippingParents2[0];
var clippingRect = clippingParents2.reduce(function(accRect, clippingParent) {
var rect = getClientRectFromMixedType(element, clippingParent, strategy);
accRect.top = max(rect.top, accRect.top);
accRect.right = min(rect.right, accRect.right);
accRect.bottom = min(rect.bottom, accRect.bottom);
accRect.left = max(rect.left, accRect.left);
return accRect;
}, getClientRectFromMixedType(element, firstClippingParent, strategy));
clippingRect.width = clippingRect.right - clippingRect.left;
clippingRect.height = clippingRect.bottom - clippingRect.top;
clippingRect.x = clippingRect.left;
clippingRect.y = clippingRect.top;
return clippingRect;
}
// node_modules/@popperjs/core/lib/utils/computeOffsets.js
function computeOffsets(_ref) {
var reference2 = _ref.reference, element = _ref.element, placement = _ref.placement;
var basePlacement = placement ? getBasePlacement(placement) : null;
var variation = placement ? getVariation(placement) : null;
var commonX = reference2.x + reference2.width / 2 - element.width / 2;
var commonY = reference2.y + reference2.height / 2 - element.height / 2;
var offsets;
switch (basePlacement) {
case top:
offsets = {
x: commonX,
y: reference2.y - element.height
};
break;
case bottom:
offsets = {
x: commonX,
y: reference2.y + reference2.height
};
break;
case right:
offsets = {
x: reference2.x + reference2.width,
y: commonY
};
break;
case left:
offsets = {
x: reference2.x - element.width,
y: commonY
};
break;
default:
offsets = {
x: reference2.x,
y: reference2.y
};
}
var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;
if (mainAxis != null) {
var len = mainAxis === "y" ? "height" : "width";
switch (variation) {
case start:
offsets[mainAxis] = offsets[mainAxis] - (reference2[len] / 2 - element[len] / 2);
break;
case end:
offsets[mainAxis] = offsets[mainAxis] + (reference2[len] / 2 - element[len] / 2);
break;
default:
}
}
return offsets;
}
// node_modules/@popperjs/core/lib/utils/detectOverflow.js
function detectOverflow(state, options) {
if (options === void 0) {
options = {};
}
var _options = options, _options$placement = _options.placement, placement = _options$placement === void 0 ? state.placement : _options$placement, _options$strategy = _options.strategy, strategy = _options$strategy === void 0 ? state.strategy : _options$strategy, _options$boundary = _options.boundary, boundary = _options$boundary === void 0 ? clippingParents : _options$boundary, _options$rootBoundary = _options.rootBoundary, rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary, _options$elementConte = _options.elementContext, elementContext = _options$elementConte === void 0 ? popper : _options$elementConte, _options$altBoundary = _options.altBoundary, altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary, _options$padding = _options.padding, padding = _options$padding === void 0 ? 0 : _options$padding;
var paddingObject = mergePaddingObject(typeof padding !== "number" ? padding : expandToHashMap(padding, basePlacements));
var altContext = elementContext === popper ? reference : popper;
var popperRect = state.rects.popper;
var element = state.elements[altBoundary ? altContext : elementContext];
var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy);
var referenceClientRect = getBoundingClientRect(state.elements.reference);
var popperOffsets2 = computeOffsets({
reference: referenceClientRect,
element: popperRect,
strategy: "absolute",
placement
});
var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets2));
var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect;
var overflowOffsets = {
top: clippingClientRect.top - elementClientRect.top + paddingObject.top,
bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,
left: clippingClientRect.left - elementClientRect.left + paddingObject.left,
right: elementClientRect.right - clippingClientRect.right + paddingObject.right
};
var offsetData = state.modifiersData.offset;
if (elementContext === popper && offsetData) {
var offset2 = offsetData[placement];
Object.keys(overflowOffsets).forEach(function(key) {
var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;
var axis = [top, bottom].indexOf(key) >= 0 ? "y" : "x";
overflowOffsets[key] += offset2[axis] * multiply;
});
}
return overflowOffsets;
}
// node_modules/@popperjs/core/lib/utils/computeAutoPlacement.js
function computeAutoPlacement(state, options) {
if (options === void 0) {
options = {};
}
var _options = options, placement = _options.placement, boundary = _options.boundary, rootBoundary = _options.rootBoundary, padding = _options.padding, flipVariations = _options.flipVariations, _options$allowedAutoP = _options.allowedAutoPlacements, allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP;
var variation = getVariation(placement);
var placements2 = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function(placement2) {
return getVariation(placement2) === variation;
}) : basePlacements;
var allowedPlacements = placements2.filter(function(placement2) {
return allowedAutoPlacements.indexOf(placement2) >= 0;
});
if (allowedPlacements.length === 0) {
allowedPlacements = placements2;
}
var overflows = allowedPlacements.reduce(function(acc, placement2) {
acc[placement2] = detectOverflow(state, {
placement: placement2,
boundary,
rootBoundary,
padding
})[getBasePlacement(placement2)];
return acc;
}, {});
return Object.keys(overflows).sort(function(a, b) {
return overflows[a] - overflows[b];
});
}
// node_modules/@popperjs/core/lib/modifiers/flip.js
function getExpandedFallbackPlacements(placement) {
if (getBasePlacement(placement) === auto) {
return [];
}
var oppositePlacement = getOppositePlacement(placement);
return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];
}
function flip(_ref) {
var state = _ref.state, options = _ref.options, name = _ref.name;
if (state.modifiersData[name]._skip) {
return;
}
var _options$mainAxis = options.mainAxis, checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, _options$altAxis = options.altAxis, checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis, specifiedFallbackPlacements = options.fallbackPlacements, padding = options.padding, boundary = options.boundary, rootBoundary = options.rootBoundary, altBoundary = options.altBoundary, _options$flipVariatio = options.flipVariations, flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio, allowedAutoPlacements = options.allowedAutoPlacements;
var preferredPlacement = state.options.placement;
var basePlacement = getBasePlacement(preferredPlacement);
var isBasePlacement = basePlacement === preferredPlacement;
var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));
var placements2 = [preferredPlacement].concat(fallbackPlacements).reduce(function(acc, placement2) {
return acc.concat(getBasePlacement(placement2) === auto ? computeAutoPlacement(state, {
placement: placement2,
boundary,
rootBoundary,
padding,
flipVariations,
allowedAutoPlacements
}) : placement2);
}, []);
var referenceRect = state.rects.reference;
var popperRect = state.rects.popper;
var checksMap = /* @__PURE__ */ new Map();
var makeFallbackChecks = true;
var firstFittingPlacement = placements2[0];
for (var i = 0; i < placements2.length; i++) {
var placement = placements2[i];
var _basePlacement = getBasePlacement(placement);
var isStartVariation = getVariation(placement) === start;
var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;
var len = isVertical ? "width" : "height";
var overflow = detectOverflow(state, {
placement,
boundary,
rootBoundary,
altBoundary,
padding
});
var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;
if (referenceRect[len] > popperRect[len]) {
mainVariationSide = getOppositePlacement(mainVariationSide);
}
var altVariationSide = getOppositePlacement(mainVariationSide);
var checks = [];
if (checkMainAxis) {
checks.push(overflow[_basePlacement] <= 0);
}
if (checkAltAxis) {
checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);
}
if (checks.every(function(check) {
return check;
})) {
firstFittingPlacement = placement;
makeFallbackChecks = false;
break;
}
checksMap.set(placement, checks);
}
if (makeFallbackChecks) {
var numberOfChecks = flipVariations ? 3 : 1;
var _loop = function _loop2(_i2) {
var fittingPlacement = placements2.find(function(placement2) {
var checks2 = checksMap.get(placement2);
if (checks2) {
return checks2.slice(0, _i2).every(function(check) {
return check;
});
}
});
if (fittingPlacement) {
firstFittingPlacement = fittingPlacement;
return "break";
}
};
for (var _i = numberOfChecks; _i > 0; _i--) {
var _ret = _loop(_i);
if (_ret === "break")
break;
}
}
if (state.placement !== firstFittingPlacement) {
state.modifiersData[name]._skip = true;
state.placement = firstFittingPlacement;
state.reset = true;
}
}
var flip_default = {
name: "flip",
enabled: true,
phase: "main",
fn: flip,
requiresIfExists: ["offset"],
data: {
_skip: false
}
};
// node_modules/@popperjs/core/lib/modifiers/hide.js
function getSideOffsets(overflow, rect, preventedOffsets) {
if (preventedOffsets === void 0) {
preventedOffsets = {
x: 0,
y: 0
};
}
return {
top: overflow.top - rect.height - preventedOffsets.y,
right: overflow.right - rect.width + preventedOffsets.x,
bottom: overflow.bottom - rect.height + preventedOffsets.y,
left: overflow.left - rect.width - preventedOffsets.x
};
}
function isAnySideFullyClipped(overflow) {
return [top, right, bottom, left].some(function(side) {
return overflow[side] >= 0;
});
}
function hide(_ref) {
var state = _ref.state, name = _ref.name;
var referenceRect = state.rects.reference;
var popperRect = state.rects.popper;
var preventedOffsets = state.modifiersData.preventOverflow;
var referenceOverflow = detectOverflow(state, {
elementContext: "reference"
});
var popperAltOverflow = detectOverflow(state, {
altBoundary: true
});
var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);
var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);
var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);
var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);
state.modifiersData[name] = {
referenceClippingOffsets,
popperEscapeOffsets,
isReferenceHidden,
hasPopperEscaped
};
state.attributes.popper = Object.assign({}, state.attributes.popper, {
"data-popper-reference-hidden": isReferenceHidden,
"data-popper-escaped": hasPopperEscaped
});
}
var hide_default = {
name: "hide",
enabled: true,
phase: "main",
requiresIfExists: ["preventOverflow"],
fn: hide
};
// node_modules/@popperjs/core/lib/modifiers/offset.js
function distanceAndSkiddingToXY(placement, rects, offset2) {
var basePlacement = getBasePlacement(placement);
var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;
var _ref = typeof offset2 === "function" ? offset2(Object.assign({}, rects, {
placement
})) : offset2, skidding = _ref[0], distance = _ref[1];
skidding = skidding || 0;
distance = (distance || 0) * invertDistance;
return [left, right].indexOf(basePlacement) >= 0 ? {
x: distance,
y: skidding
} : {
x: skidding,
y: distance
};
}
function offset(_ref2) {
var state = _ref2.state, options = _ref2.options, name = _ref2.name;
var _options$offset = options.offset, offset2 = _options$offset === void 0 ? [0, 0] : _options$offset;
var data = placements.reduce(function(acc, placement) {
acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset2);
return acc;
}, {});
var _data$state$placement = data[state.placement], x = _data$state$placement.x, y = _data$state$placement.y;
if (state.modifiersData.popperOffsets != null) {
state.modifiersData.popperOffsets.x += x;
state.modifiersData.popperOffsets.y += y;
}
state.modifiersData[name] = data;
}
var offset_default = {
name: "offset",
enabled: true,
phase: "main",
requires: ["popperOffsets"],
fn: offset
};
// node_modules/@popperjs/core/lib/modifiers/popperOffsets.js
function popperOffsets(_ref) {
var state = _ref.state, name = _ref.name;
state.modifiersData[name] = computeOffsets({
reference: state.rects.reference,
element: state.rects.popper,
strategy: "absolute",
placement: state.placement
});
}
var popperOffsets_default = {
name: "popperOffsets",
enabled: true,
phase: "read",
fn: popperOffsets,
data: {}
};
// node_modules/@popperjs/core/lib/utils/getAltAxis.js
function getAltAxis(axis) {
return axis === "x" ? "y" : "x";
}
// node_modules/@popperjs/core/lib/modifiers/preventOverflow.js
function preventOverflow(_ref) {
var state = _ref.state, options = _ref.options, name = _ref.name;
var _options$mainAxis = options.mainAxis, checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, _options$altAxis = options.altAxis, checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis, boundary = options.boundary, rootBoundary = options.rootBoundary, altBoundary = options.altBoundary, padding = options.padding, _options$tether = options.tether, tether = _options$tether === void 0 ? true : _options$tether, _options$tetherOffset = options.tetherOffset, tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;
var overflow = detectOverflow(state, {
boundary,
rootBoundary,
padding,
altBoundary
});
var basePlacement = getBasePlacement(state.placement);
var variation = getVariation(state.placement);
var isBasePlacement = !variation;
var mainAxis = getMainAxisFromPlacement(basePlacement);
var altAxis = getAltAxis(mainAxis);
var popperOffsets2 = state.modifiersData.popperOffsets;
var referenceRect = state.rects.reference;
var popperRect = state.rects.popper;
var tetherOffsetValue = typeof tetherOffset === "function" ? tetherOffset(Object.assign({}, state.rects, {
placement: state.placement
})) : tetherOffset;
var normalizedTetherOffsetValue = typeof tetherOffsetValue === "number" ? {
mainAxis: tetherOffsetValue,
altAxis: tetherOffsetValue
} : Object.assign({
mainAxis: 0,
altAxis: 0
}, tetherOffsetValue);
var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null;
var data = {
x: 0,
y: 0
};
if (!popperOffsets2) {
return;
}
if (checkMainAxis) {
var _offsetModifierState$;
var mainSide = mainAxis === "y" ? top : left;
var altSide = mainAxis === "y" ? bottom : right;
var len = mainAxis === "y" ? "height" : "width";
var offset2 = popperOffsets2[mainAxis];
var min2 = offset2 + overflow[mainSide];
var max2 = offset2 - overflow[altSide];
var additive = tether ? -popperRect[len] / 2 : 0;
var minLen = variation === start ? referenceRect[len] : popperRect[len];
var maxLen = variation === start ? -popperRect[len] : -referenceRect[len];
var arrowElement = state.elements.arrow;
var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {
width: 0,
height: 0
};
var arrowPaddingObject = state.modifiersData["arrow#persistent"] ? state.modifiersData["arrow#persistent"].padding : getFreshSideObject();
var arrowPaddingMin = arrowPaddingObject[mainSide];
var arrowPaddingMax = arrowPaddingObject[altSide];
var arrowLen = within(0, referenceRect[len], arrowRect[len]);
var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis;
var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis;
var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);
var clientOffset = arrowOffsetParent ? mainAxis === "y" ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;
var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0;
var tetherMin = offset2 + minOffset - offsetModifierValue - clientOffset;
var tetherMax = offset2 + maxOffset - offsetModifierValue;
var preventedOffset = within(tether ? min(min2, tetherMin) : min2, offset2, tether ? max(max2, tetherMax) : max2);
popperOffsets2[mainAxis] = preventedOffset;
data[mainAxis] = preventedOffset - offset2;
}
if (checkAltAxis) {
var _offsetModifierState$2;
var _mainSide = mainAxis === "x" ? top : left;
var _altSide = mainAxis === "x" ? bottom : right;
var _offset = popperOffsets2[altAxis];
var _len = altAxis === "y" ? "height" : "width";
var _min = _offset + overflow[_mainSide];
var _max = _offset - overflow[_altSide];
var isOriginSide = [top, left].indexOf(basePlacement) !== -1;
var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0;
var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis;
var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max;
var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max);
popperOffsets2[altAxis] = _preventedOffset;
data[altAxis] = _preventedOffset - _offset;
}
state.modifiersData[name] = data;
}
var preventOverflow_default = {
name: "preventOverflow",
enabled: true,
phase: "main",
fn: preventOverflow,
requiresIfExists: ["offset"]
};
// node_modules/@popperjs/core/lib/dom-utils/getHTMLElementScroll.js
function getHTMLElementScroll(element) {
return {
scrollLeft: element.scrollLeft,
scrollTop: element.scrollTop
};
}
// node_modules/@popperjs/core/lib/dom-utils/getNodeScroll.js
function getNodeScroll(node) {
if (node === getWindow(node) || !isHTMLElement(node)) {
return getWindowScroll(node);
} else {
return getHTMLElementScroll(node);
}
}
// node_modules/@popperjs/core/lib/dom-utils/getCompositeRect.js
function isElementScaled(element) {
var rect = element.getBoundingClientRect();
var scaleX = round(rect.width) / element.offsetWidth || 1;
var scaleY = round(rect.height) / element.offsetHeight || 1;
return scaleX !== 1 || scaleY !== 1;
}
function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {
if (isFixed === void 0) {
isFixed = false;
}
var isOffsetParentAnElement = isHTMLElement(offsetParent);
var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent);
var documentElement = getDocumentElement(offsetParent);
var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed);
var scroll = {
scrollLeft: 0,
scrollTop: 0
};
var offsets = {
x: 0,
y: 0
};
if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
if (getNodeName(offsetParent) !== "body" || isScrollParent(documentElement)) {
scroll = getNodeScroll(offsetParent);
}
if (isHTMLElement(offsetParent)) {
offsets = getBoundingClientRect(offsetParent, true);
offsets.x += offsetParent.clientLeft;
offsets.y += offsetParent.clientTop;
} else if (documentElement) {
offsets.x = getWindowScrollBarX(documentElement);
}
}
return {
x: rect.left + scroll.scrollLeft - offsets.x,
y: rect.top + scroll.scrollTop - offsets.y,
width: rect.width,
height: rect.height
};
}
// node_modules/@popperjs/core/lib/utils/orderModifiers.js
function order(modifiers) {
var map = /* @__PURE__ */ new Map();
var visited = /* @__PURE__ */ new Set();
var result = [];
modifiers.forEach(function(modifier) {
map.set(modifier.name, modifier);
});
function sort(modifier) {
visited.add(modifier.name);
var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);
requires.forEach(function(dep) {
if (!visited.has(dep)) {
var depModifier = map.get(dep);
if (depModifier) {
sort(depModifier);
}
}
});
result.push(modifier);
}
modifiers.forEach(function(modifier) {
if (!visited.has(modifier.name)) {
sort(modifier);
}
});
return result;
}
function orderModifiers(modifiers) {
var orderedModifiers = order(modifiers);
return modifierPhases.reduce(function(acc, phase) {
return acc.concat(orderedModifiers.filter(function(modifier) {
return modifier.phase === phase;
}));
}, []);
}
// node_modules/@popperjs/core/lib/utils/debounce.js
function debounce(fn2) {
var pending;
return function() {
if (!pending) {
pending = new Promise(function(resolve) {
Promise.resolve().then(function() {
pending = void 0;
resolve(fn2());
});
});
}
return pending;
};
}
// node_modules/@popperjs/core/lib/utils/mergeByName.js
function mergeByName(modifiers) {
var merged = modifiers.reduce(function(merged2, current) {
var existing = merged2[current.name];
merged2[current.name] = existing ? Object.assign({}, existing, current, {
options: Object.assign({}, existing.options, current.options),
data: Object.assign({}, existing.data, current.data)
}) : current;
return merged2;
}, {});
return Object.keys(merged).map(function(key) {
return merged[key];
});
}
// node_modules/@popperjs/core/lib/createPopper.js
var DEFAULT_OPTIONS = {
placement: "bottom",
modifiers: [],
strategy: "absolute"
};
function areValidElements() {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return !args.some(function(element) {
return !(element && typeof element.getBoundingClientRect === "function");
});
}
function popperGenerator(generatorOptions) {
if (generatorOptions === void 0) {
generatorOptions = {};
}
var _generatorOptions = generatorOptions, _generatorOptions$def = _generatorOptions.defaultModifiers, defaultModifiers2 = _generatorOptions$def === void 0 ? [] : _generatorOptions$def, _generatorOptions$def2 = _generatorOptions.defaultOptions, defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;
return function createPopper2(reference2, popper2, options) {
if (options === void 0) {
options = defaultOptions;
}
var state = {
placement: "bottom",
orderedModifiers: [],
options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions),
modifiersData: {},
elements: {
reference: reference2,
popper: popper2
},
attributes: {},
styles: {}
};
var effectCleanupFns = [];
var isDestroyed = false;
var instance = {
state,
setOptions: function setOptions(setOptionsAction) {
var options2 = typeof setOptionsAction === "function" ? setOptionsAction(state.options) : setOptionsAction;
cleanupModifierEffects();
state.options = Object.assign({}, defaultOptions, state.options, options2);
state.scrollParents = {
reference: isElement(reference2) ? listScrollParents(reference2) : reference2.contextElement ? listScrollParents(reference2.contextElement) : [],
popper: listScrollParents(popper2)
};
var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers2, state.options.modifiers)));
state.orderedModifiers = orderedModifiers.filter(function(m) {
return m.enabled;
});
runModifierEffects();
return instance.update();
},
forceUpdate: function forceUpdate() {
if (isDestroyed) {
return;
}
var _state$elements = state.elements, reference3 = _state$elements.reference, popper3 = _state$elements.popper;
if (!areValidElements(reference3, popper3)) {
return;
}
state.rects = {
reference: getCompositeRect(reference3, getOffsetParent(popper3), state.options.strategy === "fixed"),
popper: getLayoutRect(popper3)
};
state.reset = false;
state.placement = state.options.placement;
state.orderedModifiers.forEach(function(modifier) {
return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);
});
for (var index = 0; index < state.orderedModifiers.length; index++) {
if (state.reset === true) {
state.reset = false;
index = -1;
continue;
}
var _state$orderedModifie = state.orderedModifiers[index], fn2 = _state$orderedModifie.fn, _state$orderedModifie2 = _state$orderedModifie.options, _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2, name = _state$orderedModifie.name;
if (typeof fn2 === "function") {
state = fn2({
state,
options: _options,
name,
instance
}) || state;
}
}
},
update: debounce(function() {
return new Promise(function(resolve) {
instance.forceUpdate();
resolve(state);
});
}),
destroy: function destroy() {
cleanupModifierEffects();
isDestroyed = true;
}
};
if (!areValidElements(reference2, popper2)) {
return instance;
}
instance.setOptions(options).then(function(state2) {
if (!isDestroyed && options.onFirstUpdate) {
options.onFirstUpdate(state2);
}
});
function runModifierEffects() {
state.orderedModifiers.forEach(function(_ref) {
var name = _ref.name, _ref$options = _ref.options, options2 = _ref$options === void 0 ? {} : _ref$options, effect4 = _ref.effect;
if (typeof effect4 === "function") {
var cleanupFn = effect4({
state,
name,
instance,
options: options2
});
var noopFn = function noopFn2() {
};
effectCleanupFns.push(cleanupFn || noopFn);
}
});
}
function cleanupModifierEffects() {
effectCleanupFns.forEach(function(fn2) {
return fn2();
});
effectCleanupFns = [];
}
return instance;
};
}
// node_modules/@popperjs/core/lib/popper.js
var defaultModifiers = [eventListeners_default, popperOffsets_default, computeStyles_default, applyStyles_default, offset_default, flip_default, preventOverflow_default, arrow_default, hide_default];
var createPopper = /* @__PURE__ */ popperGenerator({
defaultModifiers
});
// src/suggesters/Suggest.ts
var wrapAround = (value, size) => {
return (value % size + size) % size;
};
var Suggest = class {
constructor(owner, containerEl, scope) {
this.owner = owner;
this.containerEl = containerEl;
containerEl.on("click", ".suggestion-item", this.onSuggestionClick.bind(this));
containerEl.on("mousemove", ".suggestion-item", this.onSuggestionMouseover.bind(this));
scope.register([], "ArrowUp", (event) => {
if (!event.isComposing) {
this.setSelectedItem(this.selectedItem - 1, true);
return false;
}
});
scope.register([], "ArrowDown", (event) => {
if (!event.isComposing) {
this.setSelectedItem(this.selectedItem + 1, true);
return false;
}
});
scope.register([], "Enter", (event) => {
if (!event.isComposing) {
this.useSelectedItem(event);
return false;
}
});
}
onSuggestionClick(event, el) {
event.preventDefault();
const item = this.suggestions.indexOf(el);
this.setSelectedItem(item, false);
this.useSelectedItem(event);
}
onSuggestionMouseover(_event, el) {
const item = this.suggestions.indexOf(el);
this.setSelectedItem(item, false);
}
setSuggestions(values) {
this.containerEl.empty();
const suggestionEls = [];
values.forEach((value) => {
const suggestionEl = this.containerEl.createDiv("suggestion-item");
this.owner.renderSuggestion(value, suggestionEl);
suggestionEls.push(suggestionEl);
});
this.values = values;
this.suggestions = suggestionEls;
this.setSelectedItem(0, false);
}
useSelectedItem(event) {
const currentValue = this.values[this.selectedItem];
if (currentValue) {
this.owner.selectSuggestion(currentValue, event);
}
}
setSelectedItem(selectedIndex, scrollIntoView) {
const normalizedIndex = wrapAround(selectedIndex, this.suggestions.length);
const prevSelectedSuggestion = this.suggestions[this.selectedItem];
const selectedSuggestion = this.suggestions[normalizedIndex];
prevSelectedSuggestion == null ? void 0 : prevSelectedSuggestion.removeClass("is-selected");
selectedSuggestion == null ? void 0 : selectedSuggestion.addClass("is-selected");
this.selectedItem = normalizedIndex;
if (scrollIntoView) {
selectedSuggestion.scrollIntoView(false);
}
}
};
var TextInputSuggest = class {
constructor(inputEl, plugin) {
this.inputEl = inputEl;
this.plugin = plugin;
this.scope = new import_obsidian5.Scope();
this.suggestEl = createDiv("suggestion-container");
const suggestion = this.suggestEl.createDiv("suggestion");
this.suggest = new Suggest(this, suggestion, this.scope);
this.scope.register([], "Escape", this.close.bind(this));
this.inputEl.addEventListener("input", this.onInputChanged.bind(this));
this.inputEl.addEventListener("focus", this.onInputChanged.bind(this));
this.inputEl.addEventListener("blur", this.close.bind(this));
this.suggestEl.on("mousedown", ".suggestion-container", (event) => {
event.preventDefault();
});
}
onInputChanged() {
const inputStr = this.inputEl.value;
const suggestions = this.getSuggestions(inputStr);
if (!suggestions) {
this.close();
return;
}
if (suggestions.length > 0) {
this.suggest.setSuggestions(suggestions);
this.open(app.dom.appContainerEl, this.inputEl);
} else {
this.close();
}
}
open(container, inputEl) {
this.plugin.app.keymap.pushScope(this.scope);
container.appendChild(this.suggestEl);
this.popper = createPopper(inputEl, this.suggestEl, {
placement: "bottom-start",
modifiers: [
{
name: "sameWidth",
enabled: true,
fn: ({ state, instance }) => {
const targetWidth = `${state.rects.reference.width}px`;
if (state.styles.popper.width === targetWidth) {
return;
}
state.styles.popper.width = targetWidth;
instance.update();
},
phase: "beforeWrite",
requires: ["computeStyles"]
}
]
});
}
close() {
this.plugin.app.keymap.popScope(this.scope);
this.suggest.setSuggestions([]);
if (this.popper)
this.popper.destroy();
this.suggestEl.detach();
}
};
// src/suggesters/FolderSuggester.ts
var FolderSuggest = class extends TextInputSuggest {
constructor(inputEl, plugin, whitelistSuggester, folder) {
super(inputEl, plugin);
this.inputEl = inputEl;
this.whitelistSuggester = whitelistSuggester;
this.folder = folder;
}
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 {
files = this.plugin.app.vault.getAllLoadedFiles().slice(0, 100);
}
files.forEach((folder) => {
if (folder instanceof import_obsidian6.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_obsidian8 = require("obsidian");
// src/functions/styleFunctions.ts
var import_obsidian7 = require("obsidian");
// src/ExcludeFolders/ExcludeFolder.ts
var ExcludedFolder = class {
constructor(path, position, id, plugin) {
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) {
if (plugin.activeFileExplorer === getFileExplorer(plugin) && !forceReload) {
return;
}
plugin.activeFileExplorer = getFileExplorer(plugin);
plugin.app.vault.getAllLoadedFiles().forEach(async (file) => {
if (file instanceof import_obsidian7.TFolder) {
await updateCSSClassesForFolder(file.path, plugin);
}
});
}
async function updateCSSClassesForFolder(folderPath, plugin) {
const folder = plugin.app.vault.getAbstractFileByPath(folderPath);
if (!folder || !(folder instanceof import_obsidian7.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);
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);
}
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);
if (!fileExplorerItem) {
if (waitForCreate && count < 5) {
await new Promise((r) => setTimeout(r, 500));
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);
document.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);
document.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;
} else {
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_obsidian8.Modal {
constructor(app2, plugin, excludedFolder) {
super(app2);
this.plugin = plugin;
this.app = app2;
this.excludedFolder = excludedFolder;
}
onOpen() {
this.display();
}
display() {
const { contentEl } = this;
contentEl.empty();
contentEl.createEl("h2", { text: "Excluded folder settings" });
new import_obsidian8.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_obsidian8.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_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.excludedFolder.excludeFromFolderOverview).onChange(async (value) => {
this.excludedFolder.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.excludedFolder.showFolderNote).onChange(async (value) => {
this.excludedFolder.showFolderNote = value;
updateCSSClassesForFolder(this.excludedFolder.path, this.plugin);
await this.plugin.saveSettings();
this.display();
}));
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").addToggle((toggle) => toggle.setValue(this.excludedFolder.disableAutoCreate).onChange(async (value) => {
this.excludedFolder.disableAutoCreate = value;
await this.plugin.saveSettings();
}));
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.excludedFolder.disableFolderNote).onChange(async (value) => {
this.excludedFolder.disableFolderNote = value;
await this.plugin.saveSettings(true);
this.display();
}));
if (!this.excludedFolder.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.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_obsidian10 = require("obsidian");
// src/ExcludeFolders/modals/PatternSettings.ts
var import_obsidian9 = require("obsidian");
var PatternSettings = class extends import_obsidian9.Modal {
constructor(app2, plugin, pattern) {
super(app2);
this.plugin = plugin;
this.app = app2;
this.pattern = pattern;
}
onOpen() {
this.display();
}
display() {
const { contentEl } = this;
contentEl.empty();
contentEl.createEl("h2", { text: "Pattern settings" });
new import_obsidian9.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_obsidian9.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_obsidian9.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_obsidian9.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_obsidian9.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_obsidian9.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
function updatePattern(plugin, pattern, newPattern) {
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.id !== pattern.id);
addExcludedFolder(plugin, newPattern);
}
function deletePattern(plugin, pattern) {
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.id !== pattern.id || folder.type === "folder");
plugin.saveSettings(true);
resyncArray(plugin);
}
function getExcludedFoldersByPattern(plugin, folderName) {
return plugin.settings.excludeFolders.filter((s) => s.type === "pattern").filter((pattern) => {
if (!pattern.string) {
return false;
}
const string = pattern.string.trim();
if (!string.startsWith("{regex}") && !(string.startsWith("*") || string.endsWith("*"))) {
return false;
}
const regex = string.replace("{regex}", "").trim();
if (string.startsWith("{regex}") && regex === "") {
return false;
}
if (regex !== void 0 && string.startsWith("{regex}")) {
const match = new RegExp(regex).exec(folderName);
if (match) {
return true;
}
} else if (string.startsWith("*") && string.endsWith("*")) {
if (folderName.includes(string.slice(1, -1))) {
return true;
}
} else if (string.startsWith("*")) {
if (folderName.endsWith(string.slice(1))) {
return true;
}
} else if (string.endsWith("*")) {
if (folderName.startsWith(string.slice(0, -1))) {
return true;
}
}
});
}
function addExcludePatternListItem(settings, containerEl, pattern) {
const plugin = settings.plugin;
const setting = new import_obsidian10.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_obsidian10.Platform.isDesktop || import_obsidian10.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") {
updatePattern(plugin, oldPattern, oldPattern);
} 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") {
updatePattern(plugin, oldPattern, oldPattern);
} else {
updateExcludedFolder(plugin, oldPattern, oldPattern);
}
}
settings.display();
});
});
}
setting.addButton((cb) => {
cb.setIcon("trash-2");
cb.setTooltip("Delete pattern");
cb.onClick(() => {
deletePattern(plugin, pattern);
setting.clear();
setting.settingEl.remove();
});
});
}
// src/ExcludeFolders/WhitelistPattern.ts
var WhitelistedPattern = class {
constructor(pattern, position, id, plugin) {
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_obsidian14 = require("obsidian");
// src/ExcludeFolders/modals/WhitelistFolderSettings.ts
var import_obsidian11 = require("obsidian");
var WhitelistFolderSettings = class extends import_obsidian11.Modal {
constructor(app2, plugin, whitelistedFolder) {
super(app2);
this.plugin = plugin;
this.app = app2;
this.whitelistedFolder = whitelistedFolder;
}
onOpen() {
this.display();
}
display() {
const { contentEl } = this;
contentEl.empty();
contentEl.createEl("h2", { text: "Whitelisted folder settings" });
new import_obsidian11.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_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.whitelistedFolder.enableSync).onChange(async (value) => {
this.whitelistedFolder.enableSync = 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.whitelistedFolder.showInFolderOverview).onChange(async (value) => {
this.whitelistedFolder.showInFolderOverview = value;
await this.plugin.saveSettings();
}));
new import_obsidian11.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_obsidian11.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_obsidian11.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_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.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_obsidian13 = require("obsidian");
// src/ExcludeFolders/modals/WhitelistPatternSettings.ts
var import_obsidian12 = require("obsidian");
var WhitelistPatternSettings = class extends import_obsidian12.Modal {
constructor(app2, plugin, pattern) {
super(app2);
this.plugin = plugin;
this.app = app2;
this.pattern = pattern;
}
onOpen() {
this.display();
}
display() {
const { contentEl } = this;
contentEl.empty();
contentEl.createEl("h2", { text: "Whitelisted pattern settings" });
new import_obsidian12.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_obsidian12.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_obsidian12.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_obsidian12.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_obsidian12.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
function updateWhitelistedPattern(plugin, pattern, newPattern) {
plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter((folder) => folder.id !== pattern.id);
addWhitelistedFolder(plugin, newPattern);
}
function deletePattern2(plugin, pattern) {
plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter((folder) => folder.id !== pattern.id || folder.type === "folder");
plugin.saveSettings(true);
resyncArray(plugin);
}
function getWhitelistedFoldersByPattern(plugin, folderName) {
return plugin.settings.whitelistFolders.filter((s) => s.type === "pattern").filter((pattern) => {
if (!pattern.string) {
return false;
}
const string = pattern.string.trim();
if (!string.startsWith("{regex}") && !(string.startsWith("*") || string.endsWith("*"))) {
return false;
}
const regex = string.replace("{regex}", "").trim();
if (string.startsWith("{regex}") && regex === "") {
return false;
}
if (regex !== void 0 && string.startsWith("{regex}")) {
const match = new RegExp(regex).exec(folderName);
if (match) {
return true;
}
} else if (string.startsWith("*") && string.endsWith("*")) {
if (folderName.includes(string.slice(1, -1))) {
return true;
}
} else if (string.startsWith("*")) {
if (folderName.endsWith(string.slice(1))) {
return true;
}
} else if (string.endsWith("*")) {
if (folderName.startsWith(string.slice(0, -1))) {
return true;
}
}
});
}
function addWhitelistedPatternListItem(settings, containerEl, pattern) {
const plugin = settings.plugin;
const setting = new import_obsidian13.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) => {
if (plugin.settings.whitelistFolders.find((folder) => folder.string === value)) {
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(() => {
deletePattern2(plugin, pattern);
setting.clear();
setting.settingEl.remove();
});
});
}
// src/ExcludeFolders/functions/whitelistFolderFunctions.ts
import_obsidian14.Platform.isMobileApp;
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) => {
if (matchedFolder[property] === true) {
whitelistedFolder[property] = true;
} else if (!matchedFolder[property]) {
whitelistedFolder[property] = false;
}
});
}
}
if (whitelistedFolder instanceof Object && 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);
plugin.saveSettings(true);
}
function deleteWhitelistedFolder(plugin, whitelistedFolder) {
plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter((folder) => folder.id !== whitelistedFolder.id || folder.type === "pattern");
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;
});
plugin.saveSettings();
}
function addWhitelistFolderListItem(settings, containerEl, whitelistedFolder) {
const plugin = settings.plugin;
const setting = new import_obsidian14.Setting(containerEl);
setting.setClass("fn-exclude-folder-list");
const inputContainer = setting.settingEl.createDiv({ cls: "fn-whitelist-folder-input-container" });
const SearchComponent = new import_obsidian14.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("*")) {
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_obsidian14.ButtonComponent(buttonContainer).setIcon("edit").setTooltip("Edit folder note").onClick(() => {
new WhitelistFolderSettings(plugin.app, plugin, whitelistedFolder).open();
});
new import_obsidian14.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_obsidian14.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_obsidian14.ButtonComponent(buttonContainer).setIcon("trash-2").setTooltip("Delete excluded folder").onClick(() => {
deleteWhitelistedFolder(plugin, whitelistedFolder);
setting.clear();
setting.settingEl.remove();
});
}
// src/ExcludeFolders/functions/folderFunctions.ts
function getExcludedFolder(plugin, path, includeDetached, pathOnly, ignoreWhitelist) {
let excludedFolder = {};
const whitelistedFolder = getWhitelistedFolder(plugin, path);
const folderName = getFolderNameFromPathString(path);
let matchedPatterns = getExcludedFoldersByPattern(plugin, folderName);
const excludedFolders = getExcludedFoldersByPath(plugin, path);
if (pathOnly) {
matchedPatterns = [];
}
let combinedExcludedFolders = [...matchedPatterns, ...excludedFolders];
if (!includeDetached) {
combinedExcludedFolders = combinedExcludedFolders.filter((f) => !f.detached);
}
const propertiesToCopy = [
"disableAutoCreate",
"disableFolderNote",
"disableSync",
"enableCollapsing",
"excludeFromFolderOverview",
"detached",
"hideInSettings",
"id",
"showFolderNote"
];
if (combinedExcludedFolders.length > 0) {
for (const matchedFolder of combinedExcludedFolders) {
propertiesToCopy.forEach((property) => {
if (matchedFolder[property] === true) {
excludedFolder[property] = true;
} else if (!matchedFolder[property]) {
excludedFolder[property] = false;
}
});
}
} else {
excludedFolder = void 0;
}
if (excludedFolder == null ? void 0 : excludedFolder.detached) {
ignoreWhitelist = true;
}
if (whitelistedFolder && excludedFolder && !ignoreWhitelist) {
excludedFolder.disableAutoCreate ? excludedFolder.disableAutoCreate = !whitelistedFolder.enableAutoCreate : "";
excludedFolder.disableFolderNote ? excludedFolder.disableFolderNote = !whitelistedFolder.enableFolderNote : "";
excludedFolder.disableSync ? excludedFolder.disableSync = !whitelistedFolder.enableSync : "";
excludedFolder.enableCollapsing = !whitelistedFolder.disableCollapsing;
excludedFolder.excludeFromFolderOverview ? excludedFolder.excludeFromFolderOverview = !whitelistedFolder.showInFolderOverview : "";
excludedFolder.showFolderNote = !whitelistedFolder.hideInFileExplorer;
} else if (excludedFolder && Object.keys(excludedFolder).length === 0) {
excludedFolder = {
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 excludedFolder;
}
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;
} else {
return folderPath === excludedFolderPath;
}
});
}
function addExcludedFolder(plugin, excludedFolder, reloadStyles = true) {
plugin.settings.excludeFolders.push(excludedFolder);
plugin.saveSettings(reloadStyles);
}
async function deleteExcludedFolder(plugin, excludedFolder) {
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.id !== excludedFolder.id || folder.type === "pattern");
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;
});
plugin.saveSettings();
}
function addExcludeFolderListItem(settings, containerEl, excludedFolder) {
const plugin = settings.plugin;
const setting = new import_obsidian15.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_obsidian15.Platform.isDesktop || import_obsidian15.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(leaf) {
const { excalidraw, excalidrawEnabled } = await getExcalidrawPlugin(this.app);
if (excalidrawEnabled) {
excalidraw.setExcalidrawView(leaf);
}
}
async function getExcalidrawPlugin(app2) {
const excalidraw = app2.plugins.plugins["obsidian-excalidraw-plugin"];
const excalidrawEnabled = app2.plugins.enabledPlugins.has("obsidian-excalidraw-plugin");
return {
excalidraw,
excalidrawEnabled
};
}
// src/modals/AskForExtension.ts
var import_obsidian16 = require("obsidian");
var AskForExtensionModal = class extends import_obsidian16.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;
createFolderNote(this.plugin, this.folderPath, this.openFile, this.extension, this.useModal, this.existingNote);
this.close();
}
};
// src/functions/folderNoteFunctions.ts
var defaultExcalidrawTemplate = `---
excalidraw-plugin: parsed
tags: [excalidraw]
---
==\u26A0 Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. \u26A0==
%%
# Drawing
\`\`\`json
{'type":"excalidraw","version":2,"source":"https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/1.9.20","elements":[],"appState":{"gridSize":null,"viewBackgroundColor":"#ffffff'}}
\`\`\`
%%`;
async function createFolderNote(plugin, folderPath, openFile, extension, displayModal, preexistingNote) {
var _a;
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 = "";
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) {
deleteExcludedFolder(plugin, detachedFolder);
removeCSSClassFromFileExplorerEL(folderNote == null ? void 0 : folderNote.path, "is-folder-note", false, plugin);
const folder2 = plugin.app.vault.getAbstractFileByPath(folderPath);
if (!folderNote || folderNote.basename !== fileName)
return;
let count = 1;
let newName = removeExtension(folderNote.path) + ` (${count}).${folderNote.path.split(".").pop()}`;
while (count < 100 && plugin.app.vault.getAbstractFileByPath(newName)) {
count++;
newName = removeExtension(folderNote.path) + ` (${count}).${folderNote.path.split(".").pop()}`;
}
const [excludedFolder, excludedFolderExisted, disabledSync] = await tempDisableSync(plugin, folder2);
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);
}
});
}
if (!extension) {
extension = folderNoteType;
}
if (!folderNote) {
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_obsidian17.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 document. \u26A0==")) {
content = defaultExcalidrawTemplate;
}
} else {
return plugin.app.vault.readBinary(templateFile).then(async (data) => {
folderNote = await plugin.app.vault.createBinary(path, data);
if (openFile) {
await leaf.openFile(folderNote);
}
});
}
}
} else if (plugin.settings.folderNoteType === ".excalidraw" || extension === ".excalidraw") {
content = defaultExcalidrawTemplate;
} else if (plugin.settings.folderNoteType === ".canvas") {
content = "{}";
}
}
folderNote = await plugin.app.vault.create(path, content);
} 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(leaf);
}
}
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_obsidian17.TFolder))
return;
addCSSClassToFileExplorerEl(path, "is-folder-note", false, plugin, true);
addCSSClassToFileExplorerEl(folder.path, "has-folder-note", false, plugin);
}
async function turnIntoFolderNote(plugin, file, folder, folderNote, skipConfirmation) {
var _a;
const extension = file.extension;
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 newPath = `${folder.path}/${folder.name} (${file.stat.ctime.toString().slice(10) + Math.floor(Math.random() * 1e3)}).${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) {
deleteExcludedFolder(plugin, detachedExcludedFolder);
}
await plugin.app.fileManager.renameFile(file, path);
addCSSClassToFileExplorerEl(path, "is-folder-note", false, plugin, true);
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.path;
const focusExistingTab = plugin.settings.focusExistingTab && plugin.settings.openInNewTab;
const activeFilePath = (_a = plugin.app.workspace.getActiveFile()) == null ? void 0 : _a.path;
if (activeFilePath === path && !(import_obsidian17.Keymap.isModEvent(evt) === "tab")) {
return;
}
let foundLeaf = null;
if (focusExistingTab && file instanceof import_obsidian17.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 leaf = plugin.app.workspace.getLeaf(import_obsidian17.Keymap.isModEvent(evt) || plugin.settings.openInNewTab);
if (file instanceof import_obsidian17.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 getFolderNote(plugin, folderPath, storageLocation, file, oldFolderNoteName) {
if (!folderPath)
return null;
const folder = {
path: folderPath,
name: getFolderNameFromPathString(folderPath)
};
const folderNoteName = oldFolderNoteName != null ? oldFolderNoteName : plugin.settings.folderNoteName;
let fileName = folderNoteName.replace("{{folder_name}}", folder.name);
if (file) {
fileName = folderNoteName.replace("{{folder_name}}", file.basename);
}
if (!fileName)
return null;
if ((plugin.settings.storageLocation === "parentFolder" || storageLocation === "parentFolder") && storageLocation !== "insideFolder") {
folder.path = getFolderPathFromString(folderPath);
}
let path = `${folder.path}/${fileName}`;
folder.path === "/" ? path = fileName : path = `${folder.path}/${fileName}`;
let folderNoteType = plugin.settings.folderNoteType;
if (folderNoteType === ".excalidraw") {
folderNoteType = ".md";
}
let folderNote = plugin.app.vault.getAbstractFileByPath(path + folderNoteType);
if (folderNote instanceof import_obsidian17.TFile && plugin.settings.supportedFileTypes.includes(plugin.settings.folderNoteType.replace(".", ""))) {
return folderNote;
} else {
const supportedFileTypes = plugin.settings.supportedFileTypes.filter((type) => type !== plugin.settings.folderNoteType.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_obsidian17.TFile) {
return folderNote;
}
}
}
}
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.hideInSettings = true;
excludedFolder.disableFolderNote = true;
excludedFolder.disableSync = true;
excludedFolder.subFolders = false;
excludedFolder.excludeFromFolderOverview = false;
excludedFolder.detached = true;
excludedFolder.detachedFilePath = file.path;
addExcludedFolder(plugin, excludedFolder);
}
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 (!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;
}
// src/settings/GeneralSettings.ts
var import_obsidian24 = 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") {
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 = '';
const svgElement = removeSpan.createEl("span", { cls: "ofn-list-item-remove-icon" });
svgElement.innerHTML = svg;
removeSpan.onClickEvent((e) => {
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 = '';
resetButton.innerHTML = svg;
resetButton.onClickEvent((e) => {
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_obsidian18 = require("obsidian");
var AddSupportedFileModal = class extends import_obsidian18.Modal {
constructor(app2, plugin, settingsTab, list) {
super(app2);
this.plugin = plugin;
this.app = app2;
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_obsidian18.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();
}
}));
}
async 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())) {
return new import_obsidian18.Notice("This extension is already supported");
} else {
await this.list.addValue(this.name.toLowerCase());
this.settingsTab.display();
this.plugin.saveSettings();
contentEl.empty();
}
}
};
// src/events/FrontMatterTitle.ts
var import_front_matter_plugin_api_provider = __toESM(require_lib());
var import_obsidian19 = require("obsidian");
var FrontMatterTitlePluginHandler = class {
constructor(plugin) {
this.api = null;
this.deffer = null;
this.modifiedFolders = /* @__PURE__ */ new Map();
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;
}
this.plugin.updateAllBreadcrumbs();
}
})();
}
deleteEvent() {
if (this.eventRef) {
this.dispatcher.removeListener(this.eventRef);
}
}
async fmptUpdateFileName(data, isEvent) {
var _a, _b, _c;
if (data.data)
data = data.data;
const file = this.app.vault.getAbstractFileByPath(data.path);
if (!(file instanceof import_obsidian19.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_obsidian19.TFolder)) {
return;
}
const folderNote = getFolderNote(this.plugin, folder.path);
if (!folderNote) {
return;
}
if (folderNote !== file) {
return;
}
if (!data.pathOnly) {
this.plugin.changeFolderNameInExplorer(folder, newName);
}
const breadcrumb = data.breadcrumb;
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;
if (data.data)
data = data.data;
const folder = this.app.vault.getAbstractFileByPath(data.path);
if (!(folder instanceof import_obsidian19.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 (!data.pathOnly) {
this.plugin.changeFolderNameInExplorer(folder, newName);
}
const breadcrumb = data.breadcrumb;
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_obsidian20 = require("obsidian");
var ConfirmationModal = class extends import_obsidian20.Modal {
constructor(app2, plugin) {
super(app2);
this.plugin = plugin;
this.app = app2;
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 {
templateFolderPath = templateFolder;
}
const { contentEl } = this;
contentEl.createEl("h2", { text: "Create folder note for every folder" });
const setting = new import_obsidian20.Setting(contentEl);
setting.infoEl.createEl("p", { text: "Make sure to backup your vault before using this feature." }).style.color = "#fb464c";
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_obsidian20.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_obsidian20.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_obsidian20.Notice("Please choose a file extension");
}
this.close();
const folders = this.app.vault.getAllLoadedFiles().filter((file) => file.parent instanceof import_obsidian20.TFolder);
for (const folder of folders) {
if (folder instanceof import_obsidian20.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_obsidian21 = require("obsidian");
var TemplateSuggest = class extends import_obsidian21.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_obsidian21.TFolder)) {
return [{ path: "", name: "You need to set the Templates folder in the Templater settings first." }];
}
} else {
folder = this.plugin.app.vault.getAbstractFileByPath(templateFolder);
}
if (!(folder instanceof import_obsidian21.TFolder)) {
return [];
}
import_obsidian21.Vault.recurseChildren(folder, (file) => {
if (file instanceof import_obsidian21.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;
this.plugin.saveSettings();
this.close();
}
};
// src/settings/modals/BackupWarning.ts
var import_obsidian22 = require("obsidian");
var BackupWarningModal = class extends import_obsidian22.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 });
this.insertCustomHtml();
contentEl.createEl("p", { text: "Make sure to backup your vault before using this feature." }).style.color = "#fb464c";
const buttonContainer = contentEl.createDiv({ cls: "fn-modal-button-container" });
const confirmButton = new import_obsidian22.ButtonComponent(buttonContainer);
confirmButton.setButtonText("Confirm").setCta().onClick(() => {
this.callback(...this.args);
this.close();
});
const cancelButton = new import_obsidian22.ButtonComponent(buttonContainer);
cancelButton.setButtonText("Cancel").onClick(() => {
this.close();
});
}
insertCustomHtml() {
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
};
// src/settings/modals/RenameFns.ts
var import_obsidian23 = 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_obsidian23.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_obsidian23.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_obsidian24.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();
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
if (!value.includes("{{folder_name}}")) {
if (!settingsTab.showFolderNameInTabTitleSetting) {
settingsTab.display();
settingsTab.showFolderNameInTabTitleSetting = true;
}
} else {
if (settingsTab.showFolderNameInTabTitleSetting) {
settingsTab.display();
settingsTab.showFolderNameInTabTitleSetting = false;
}
}
}, 2e3);
})).addButton((button) => button.setButtonText("Rename existing folder notes").setCta().onClick(async () => {
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, []).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_obsidian24.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_obsidian24.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";
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;
settingsTab.plugin.saveSettings();
settingsTab.display();
});
});
const setting0 = new import_obsidian24.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", async (values) => {
settingsTab.plugin.settings.supportedFileTypes = values;
await settingsTab.plugin.saveSettings();
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: "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());
settingsTab.display();
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_obsidian24.Setting(containerEl).setDesc("Can be used with templater/templates plugin. If you add the location of the templates there.").setName("Template path").addSearch((cb) => {
var _a;
new TemplateSuggest(cb.inputEl, settingsTab.plugin);
cb.setPlaceholder("Template path");
cb.setValue(((_a = settingsTab.plugin.app.vault.getAbstractFileByPath(settingsTab.plugin.settings.templatePath)) == null ? void 0 : _a.name.replace(".md", "")) || "");
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_obsidian24.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) => {
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_obsidian24.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_obsidian24.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_obsidian24.Platform.isDesktopApp) {
settingsTab.settingsPage.createEl("h3", { text: "Keyboard Shortcuts" });
new import_obsidian24.Setting(containerEl).setName("Key for creating folder note").setDesc("The key combination to create a folder note").addDropdown((dropdown) => {
if (!import_obsidian24.Platform.isMacOS) {
dropdown.addOption("ctrl", "Ctrl + Click");
} else {
dropdown.addOption("ctrl", "Cmd + Click");
}
dropdown.addOption("alt", "Alt + 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_obsidian24.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_obsidian24.Platform.isMacOS) {
dropdown.addOption("ctrl", "Ctrl + Click");
} else {
dropdown.addOption("ctrl", "Cmd + Click");
}
dropdown.addOption("alt", "Alt + 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_obsidian24.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_obsidian24.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) => {
settingsTab.plugin.settings.deleteFilesAction = value;
await settingsTab.plugin.saveSettings();
settingsTab.display();
});
});
if (import_obsidian24.Platform.isDesktop) {
const setting3 = new import_obsidian24.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_obsidian24.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_obsidian24.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_obsidian24.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_obsidian24.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_obsidian24.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_obsidian24.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_obsidian24.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 = document.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_obsidian24.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;
(_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_obsidian24.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_obsidian24.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_obsidian25 = require("obsidian");
async function renderFileExplorer(settingsTab) {
const containerEl = settingsTab.settingsPage;
new import_obsidian25.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) {
document.body.classList.add("hide-folder-note");
} else {
document.body.classList.remove("hide-folder-note");
}
settingsTab.display();
}));
const setting2 = new import_obsidian25.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");
setting2.infoEl.style.color = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
new import_obsidian25.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) {
document.body.classList.add("fn-whitespace-stop-collapsing");
} else {
document.body.classList.remove("fn-whitespace-stop-collapsing");
}
settingsTab.plugin.settings.stopWhitespaceCollapsing = !value;
await settingsTab.plugin.saveSettings();
}));
const disableSetting = new import_obsidian25.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");
disableSetting.infoEl.style.color = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
new import_obsidian25.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_obsidian25.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_obsidian25.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) {
document.body.classList.add("disable-folder-highlight");
} else {
document.body.classList.remove("disable-folder-highlight");
}
await settingsTab.plugin.saveSettings();
}));
new import_obsidian25.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;
await settingsTab.plugin.saveSettings();
if (value) {
document.body.classList.add("fn-hide-collapse-icon");
} else {
document.body.classList.remove("fn-hide-collapse-icon");
}
settingsTab.display();
}));
new import_obsidian25.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) {
document.body.classList.add("fn-hide-empty-collapse-icon");
} else {
document.body.classList.remove("fn-hide-empty-collapse-icon");
}
settingsTab.display();
}));
if (settingsTab.plugin.settings.hideCollapsingIcon) {
new import_obsidian25.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) => {
settingsTab.plugin.settings.ignoreAttachmentFolder = value;
await settingsTab.plugin.saveSettings();
}));
}
new import_obsidian25.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) {
document.body.classList.add("folder-note-underline");
} else {
document.body.classList.remove("folder-note-underline");
}
await settingsTab.plugin.saveSettings();
}));
new import_obsidian25.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) {
document.body.classList.add("folder-note-bold");
} else {
document.body.classList.remove("folder-note-bold");
}
await settingsTab.plugin.saveSettings();
}));
new import_obsidian25.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) {
document.body.classList.add("folder-note-cursive");
} else {
document.body.classList.remove("folder-note-cursive");
}
await settingsTab.plugin.saveSettings();
}));
}
// src/settings/PathSettings.ts
var import_obsidian26 = require("obsidian");
async function renderPath(settingsTab) {
const containerEl = settingsTab.settingsPage;
new import_obsidian26.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();
}));
new import_obsidian26.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_obsidian26.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_obsidian26.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_obsidian26.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) {
document.body.classList.add("folder-note-underline-path");
} else {
document.body.classList.remove("folder-note-underline-path");
}
await settingsTab.plugin.saveSettings();
}));
new import_obsidian26.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) {
document.body.classList.add("folder-note-bold-path");
} else {
document.body.classList.remove("folder-note-bold-path");
}
await settingsTab.plugin.saveSettings();
}));
new import_obsidian26.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) {
document.body.classList.add("folder-note-cursive-path");
} else {
document.body.classList.remove("folder-note-cursive-path");
}
await settingsTab.plugin.saveSettings();
}));
}
// src/obsidian-folder-overview/src/settings.ts
var import_obsidian34 = require("obsidian");
// src/obsidian-folder-overview/src/FolderOverview.ts
var import_obsidian31 = require("obsidian");
// src/obsidian-folder-overview/src/modals/Settings.ts
var import_obsidian27 = require("obsidian");
// src/obsidian-folder-overview/src/utils/functions.ts
function getFolderPathFromString2(path) {
const subString = path.lastIndexOf("/") >= 0 ? path.lastIndexOf("/") : 0;
const folderPath = path.substring(0, subString);
if (folderPath === "") {
return "/";
} else {
return folderPath;
}
}
// src/obsidian-folder-overview/src/modals/Settings.ts
var FolderOverviewSettings = class extends import_obsidian27.Modal {
constructor(app2, plugin, yaml, ctx, el, defaultSettings) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
super(app2);
this.plugin = plugin;
this.app = app2;
if (!yaml) {
this.yaml = this.defaultSettings;
} else if (ctx) {
const includeTypes3 = (yaml == null ? void 0 : yaml.includeTypes) || defaultSettings.includeTypes || ["folder", "markdown"];
this.yaml = {
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: includeTypes3.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
};
}
if (ctx) {
this.ctx = ctx;
}
if (el) {
this.el = el;
}
updateYaml(this.plugin, this.ctx, this.el, this.yaml, false);
}
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/FileExplorer.ts
var import_obsidian28 = 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 = this.plugin;
const ctx = this.folderOverview.ctx;
const root = this.folderOverview.root;
const yaml = this.folderOverview.yaml;
const 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("/")) {
tFolder = plugin.app.vault.getAbstractFileByPath(getFolderPathFromString(ctx.sourcePath));
} 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) {
folderElement = root.createDiv({
cls: "nav-files-container"
});
}
const newFolderElement = folderElement.cloneNode(true);
newFolderElement.querySelectorAll("div.nav-folder-title").forEach((el) => {
var _a;
const folder2 = plugin.app.vault.getAbstractFileByPath(el.getAttribute("data-path") || "");
if (!(folder2 instanceof import_obsidian28.TFolder))
return;
if (yaml.alwaysCollapse) {
folder2.collapsed = true;
el.classList.add("is-collapsed");
} else {
if (yaml.storeFolderCondition) {
if (folder2.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")) {
folder2.collapsed = true;
} else {
folder2.collapsed = false;
}
}
}
if (el.classList.contains("has-folder-note")) {
if (plugin instanceof FolderNotesPlugin) {
const folderNote = getFolderNote(plugin, folder2.path);
if (folderNote) {
folderOverview.pathBlacklist.push(folderNote.path);
}
}
}
});
const debouncedRenderFileExplorer = this.debounce(() => this.renderFileExplorer(), 300);
const handleVaultChange = () => {
debouncedRenderFileExplorer();
};
this.eventListeners.push(() => {
folderOverview.off("vault-change", handleVaultChange);
});
folderOverview.on("vault-change", handleVaultChange);
if (tFolder instanceof import_obsidian28.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 folder2 = plugin.app.vault.getAbstractFileByPath(path);
this.handleCollapseClick(el, plugin, yaml, this.pathBlacklist, sourceFolderPath, folderOverview, folder2);
};
}
});
}
debounce(func, wait) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = window.setTimeout(() => func.apply(this, args), wait);
};
}
async addFiles(files, childrenElement, folderOverview, sourceFolderPath) {
const plugin = folderOverview.plugin;
const allFiles = await folderOverview.filterFiles(files, plugin, sourceFolderPath, folderOverview.yaml.depth, folderOverview.pathBlacklist);
const sortedFiles = folderOverview.sortFiles((allFiles != null ? allFiles : []).filter((file) => file !== null));
const folders = sortedFiles.filter((child) => child instanceof import_obsidian28.TFolder);
const otherFiles = sortedFiles.filter((child) => child instanceof import_obsidian28.TFile);
for (const child of folders) {
if (!(child instanceof import_obsidian28.TFolder))
continue;
await this.createFolderEL(plugin, child, folderOverview, childrenElement, sourceFolderPath);
}
for (const child of otherFiles) {
if (!(child instanceof import_obsidian28.TFile))
continue;
await this.createFileEL(plugin, child, folderOverview, childrenElement);
}
}
async handleCollapseClick(el, plugin, yaml, pathBlacklist, sourceFolderPath, folderOverview, folder) {
var _a, _b, _c, _d, _e;
el.classList.toggle("is-collapsed");
if (el.classList.contains("is-collapsed")) {
if (!(folder instanceof import_obsidian28.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_obsidian28.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 = folderOverview.sortFiles(folder.children);
const filteredFiles = ((_e = await folderOverview.filterFiles(files, plugin, folder.path, yaml.depth || 1, pathBlacklist)) != null ? _e : []).filter((file) => file !== null);
await this.addFiles(filteredFiles, childrenElement, folderOverview, sourceFolderPath);
}
}
async createFolderEL(plugin, child, folderOverview, childrenElement, sourceFolderPath) {
var _a, _b, _c, _d;
const pathBlacklist = folderOverview.pathBlacklist;
let folderNote = void 0;
if (plugin instanceof FolderNotesPlugin) {
folderNote = getFolderNote(plugin, child.path);
}
const yaml = folderOverview.yaml;
let folderTitle = null;
let folderElement = null;
if (folderNote) {
pathBlacklist.push(folderNote.path);
}
let excludedFolder = void 0;
if (plugin instanceof FolderNotesPlugin) {
excludedFolder = getExcludedFolder(plugin, child.path, true);
}
if (excludedFolder == null ? void 0 : excludedFolder.excludeFromFolderOverview) {
return;
}
if (yaml.includeTypes.includes("folder")) {
(_a = folderOverview.el.parentElement) == null ? void 0 : _a.classList.add("fv-remove-edit-button");
folderElement = childrenElement.createDiv({
cls: "tree-item nav-folder"
});
folderTitle = folderElement.createDiv({
cls: "tree-item-self is-clickable nav-folder-title",
attr: {
"data-path": child.path
}
});
let folderName = child.name;
if (yaml.fmtpIntegration && plugin instanceof FolderNotesPlugin && folderNote) {
folderName = (_c = await ((_b = plugin.fmtpHandler) == null ? void 0 : _b.getNewFileName(folderNote))) != null ? _c : child.name;
}
const folderTitleText = folderTitle == null ? void 0 : folderTitle.createDiv({
cls: "tree-item-inner nav-folder-title-content",
text: folderName
});
if (folderTitleText && !folderNote) {
folderTitleText.onclick = () => {
const collapseIcon2 = folderTitle == null ? void 0 : folderTitle.querySelectorAll(".tree-item-icon")[0];
if (collapseIcon2) {
this.handleCollapseClick(collapseIcon2, plugin, yaml, pathBlacklist, sourceFolderPath, folderOverview, child);
}
};
}
if (yaml.allowDragAndDrop) {
folderTitle.draggable = true;
folderTitle.addEventListener("dragstart", (e) => {
const dragManager = plugin.app.dragManager;
const dragData = dragManager.dragFolder(e, child);
dragManager.onDragStart(e, dragData);
folderTitle == null ? void 0 : folderTitle.classList.add("is-being-dragged");
});
folderTitle.addEventListener("dragend", (e) => {
folderTitle == null ? void 0 : folderTitle.classList.remove("is-being-dragged");
});
folderTitle.addEventListener("dragover", (e) => {
e.preventDefault();
const { draggable } = plugin.app.dragManager;
if (draggable) {
folderElement == null ? void 0 : folderElement.classList.add("is-being-dragged-over");
plugin.app.dragManager.setAction(window.i18next.t("interface.drag-and-drop.move-into-folder", { folder: child.name }));
}
});
folderTitle.addEventListener("dragleave", (e) => {
folderElement == null ? void 0 : folderElement.classList.remove("is-being-dragged-over");
});
folderTitle.addEventListener("drop", (e) => {
const { draggable } = plugin.app.dragManager;
if (draggable && draggable.file) {
plugin.app.fileManager.renameFile(draggable.file, child.path + "/" + draggable.file.name);
}
});
}
folderTitle.oncontextmenu = (e) => {
folderOverview.folderMenu(child, e);
};
}
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 childrenElement2 = folderElement == null ? void 0 : folderElement.createDiv({ cls: "tree-item-children nav-folder-children" });
if (childrenElement2) {
await this.addFiles(child.children, childrenElement2, folderOverview, sourceFolderPath);
}
} else {
await this.addFiles(child.children, childrenElement, folderOverview, sourceFolderPath);
}
} else {
folderTitle == null ? void 0 : folderTitle.classList.add("is-collapsed");
}
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");
}
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_obsidian28.setIcon)(collapseIcon, "chevron-down");
(_d = collapseIcon.querySelector("path")) == null ? void 0 : _d.setAttribute("d", "M3 8L12 17L21 8");
collapseIcon.onclick = () => {
this.handleCollapseClick(collapseIcon, plugin, yaml, pathBlacklist, sourceFolderPath, folderOverview, child);
};
}
}
async createFileEL(plugin, child, folderOverview, childrenElement) {
var _a, _b, _c;
const yaml = folderOverview.yaml;
const pathBlacklist = folderOverview.pathBlacklist;
if (pathBlacklist.includes(child.path) && !yaml.showFolderNotes) {
return;
}
const extension = child.extension.toLowerCase() === "md" ? "markdown" : child.extension.toLowerCase();
const includeTypes3 = yaml.includeTypes;
if (includeTypes3.length > 0 && !includeTypes3.includes("all")) {
if ((extension === "md" || extension === "markdown") && !includeTypes3.includes("markdown"))
return;
if (extension === "canvas" && !includeTypes3.includes("canvas"))
return;
if (extension === "pdf" && !includeTypes3.includes("pdf"))
return;
const imageTypes = ["jpg", "jpeg", "png", "gif", "svg", "webp"];
if (imageTypes.includes(extension) && !includeTypes3.includes("image"))
return;
const videoTypes = ["mp4", "webm", "ogv", "mov", "mkv"];
if (videoTypes.includes(extension) && !includeTypes3.includes("video"))
return;
const audioTypes = ["mp3", "wav", "m4a", "3gp", "flac", "ogg", "oga", "opus"];
if (audioTypes.includes(extension) && includeTypes3.includes("audio"))
return;
const allTypes = ["markdown", "md", "canvas", "pdf", ...imageTypes, ...videoTypes, ...audioTypes];
if (!allTypes.includes(extension) && !includeTypes3.includes("other"))
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.dragManager;
const dragData = dragManager.dragFile(e, child);
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) {
plugin.app.dragManager.setAction(window.i18next.t("interface.drag-and-drop.move-into-folder", { folder: ((_a2 = child.parent) == null ? void 0 : _a2.name) || plugin.app.vault.getName() }));
(_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) {
plugin.app.fileManager.renameFile(draggable.file, `${targetFolder}/${draggable.file.name}`);
}
(_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/ListStyle.ts
var import_obsidian29 = require("obsidian");
async function renderListOverview(plugin, ctx, root, yaml, pathBlacklist, folderOverview) {
const overviewList = folderOverview.listEl;
overviewList == null ? void 0 : overviewList.empty();
let tFolder = plugin.app.vault.getAbstractFileByPath(yaml.folderPath);
if (!tFolder && yaml.folderPath.trim() === "") {
if (ctx.sourcePath.includes("/")) {
tFolder = plugin.app.vault.getAbstractFileByPath(getFolderPathFromString(ctx.sourcePath));
} else {
yaml.folderPath = "/";
tFolder = plugin.app.vault.getAbstractFileByPath("/");
}
}
if (!(tFolder instanceof import_obsidian29.TFolder)) {
return;
}
let files = tFolder.children;
if (!files) {
return;
}
const ul = folderOverview.listEl;
const sourceFolderPath = tFolder.path;
files = await folderOverview.filterFiles(files, plugin, sourceFolderPath, yaml.depth, folderOverview.pathBlacklist);
const folders = folderOverview.sortFiles(files.filter((f) => f instanceof import_obsidian29.TFolder));
files = folderOverview.sortFiles(files.filter((f) => f instanceof import_obsidian29.TFile));
folders.forEach(async (file) => {
if (file instanceof import_obsidian29.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_obsidian29.TFile) {
addFileList(plugin, ul, folderOverview.pathBlacklist, file, folderOverview.yaml.includeTypes, folderOverview.yaml.disableFileTag, folderOverview);
}
});
const debouncedRenderListOverview = debounce2(() => renderListOverview(plugin, ctx, root, yaml, pathBlacklist, folderOverview), 300);
const handleVaultChange = () => {
debouncedRenderListOverview();
};
folderOverview.on("vault-change", handleVaultChange);
}
function debounce2(func, wait) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = window.setTimeout(() => func.apply(this, 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 isFirstLevelSub = folder.path.split("/").length === folderOverview.yaml.folderPath.split("/").length + 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_obsidian29.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, includeTypes3, disableFileTag, folderOverview) {
if (sourceFolderPath === "") {
depth--;
}
const allFiles = await folderOverview.filterFiles(folder.children, plugin, sourceFolderPath, depth, pathBlacklist);
const files = folderOverview.sortFiles(allFiles.filter((file) => !(file instanceof import_obsidian29.TFolder) && file !== null));
const folders = folderOverview.sortFiles(allFiles.filter((file) => file instanceof import_obsidian29.TFolder && file !== null));
const ul = list.createEl("ul", { cls: "folder-overview-list" });
folders.forEach(async (file) => {
if (file instanceof import_obsidian29.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, includeTypes3, disableFileTag, folderOverview);
} else {
goThroughFolders(plugin, list, file, depth, sourceFolderPath, ctx, yaml, pathBlacklist, includeTypes3, disableFileTag, folderOverview);
}
}
});
files.forEach((file) => {
if (file instanceof import_obsidian29.TFile) {
if (yaml.includeTypes.includes("folder")) {
addFileList(plugin, ul, pathBlacklist, file, includeTypes3, disableFileTag, folderOverview);
} else {
addFileList(plugin, list, pathBlacklist, file, includeTypes3, disableFileTag, folderOverview);
}
}
});
}
async function addFileList(plugin, list, pathBlacklist, file, includeTypes3, disableFileTag, folderOverview) {
var _a, _b, _c, _d;
if (includeTypes3.length > 0 && !includeTypes3.includes("all")) {
if (file.extension === "md" && !includeTypes3.includes("markdown"))
return;
if (file.extension === "canvas" && !includeTypes3.includes("canvas"))
return;
if (file.extension === "pdf" && !includeTypes3.includes("pdf"))
return;
const imageTypes = ["jpg", "jpeg", "png", "gif", "svg", "webp"];
if (imageTypes.includes(file.extension) && !includeTypes3.includes("image"))
return;
const videoTypes = ["mp4", "webm", "ogv", "mov", "mkv"];
if (videoTypes.includes(file.extension) && !includeTypes3.includes("video"))
return;
const audioTypes = ["mp3", "wav", "m4a", "3gp", "flac", "ogg", "oga", "opus"];
if (audioTypes.includes(file.extension) && includeTypes3.includes("audio"))
return;
const allTypes = ["md", "canvas", "pdf", ...imageTypes, ...videoTypes, ...audioTypes];
if (!allTypes.includes(file.extension) && !includeTypes3.includes("other"))
return;
}
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_obsidian30 = require("obsidian");
var NewFolderNameModal = class extends import_obsidian30.Modal {
constructor(app2, plugin, folder) {
super(app2);
this.plugin = plugin;
this.app = app2;
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() !== "") {
if (!this.app.vault.getAbstractFileByPath(this.folder.path.slice(0, this.folder.path.lastIndexOf("/") + 1) + newName.trim())) {
this.plugin.app.fileManager.renameFile(this.folder, this.folder.path.slice(0, this.folder.path.lastIndexOf("/") + 1) + newName.trim());
}
}
}
}
};
// 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/FolderOverview.ts
var FolderOverview = class {
constructor(plugin, ctx, source, el, defaultSettings) {
this.pathBlacklist = [];
this.folders = [];
this.eventListeners = [];
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
this.plugin = plugin;
this.emitter = new CustomEventEmitter2();
let yaml = (0, import_obsidian31.parseYaml)(source);
if (!yaml) {
yaml = {};
}
const includeTypes3 = (yaml == null ? void 0 : yaml.includeTypes) || defaultSettings.includeTypes || ["folder", "markdown"];
this.ctx = ctx;
this.source = source;
this.el = el;
this.sourceFilePath = this.ctx.sourcePath;
const sourceFile = this.plugin.app.vault.getAbstractFileByPath(ctx.sourcePath);
if (sourceFile instanceof import_obsidian31.TFile) {
this.sourceFile = sourceFile;
}
switch (yaml == null ? void 0 : yaml.folderPath.trim()) {
case "File\u2019s parent folder path": {
const sourceFolder = this.plugin.app.vault.getAbstractFileByPath(getFolderPathFromString(ctx.sourcePath));
if (sourceFolder instanceof import_obsidian31.TFolder) {
yaml.folderPath = sourceFolder.path;
this.sourceFolder = sourceFolder;
}
break;
}
case "Path of folder linked to the file": {
if (plugin instanceof FolderNotesPlugin && this.sourceFile instanceof import_obsidian31.TFile) {
const folderNoteFolder = getFolder(plugin, this.sourceFile);
if (folderNoteFolder instanceof import_obsidian31.TFolder) {
this.sourceFolder = folderNoteFolder;
yaml.folderPath = folderNoteFolder.path;
} else {
yaml.folderPath = "";
}
}
break;
}
case "": {
const sourceFolder = this.plugin.app.vault.getAbstractFileByPath(getFolderPathFromString(ctx.sourcePath));
if (sourceFolder instanceof import_obsidian31.TFolder) {
yaml.folderPath = sourceFolder.path;
this.sourceFolder = sourceFolder;
}
break;
}
default: {
const sourceFolder = this.plugin.app.vault.getAbstractFileByPath(yaml.folderPath.trim());
if (sourceFolder instanceof import_obsidian31.TFolder) {
yaml.folderPath = sourceFolder.path;
this.sourceFolder = sourceFolder;
}
break;
}
}
this.defaultSettings = defaultSettings;
this.yaml = {
id: (_a = yaml == null ? void 0 : yaml.id) != null ? _a : crypto.randomUUID(),
folderPath: (_b = yaml == null ? void 0 : yaml.folderPath.trim()) != null ? _b : getFolderPathFromString(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: includeTypes3.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
};
const customChild = new CustomMarkdownRenderChild(el, this);
ctx.addChild(customChild);
}
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.plugin;
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));
}
async create(plugin, source, el, ctx) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
el.empty();
(_a = el.parentElement) == null ? void 0 : _a.classList.add("folder-overview-container");
if (this.yaml.hideFolderOverview) {
(_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 });
const root = el.createEl("div", { cls: "folder-overview" });
this.root = root;
const titleEl = root.createEl("h1", { cls: "folder-overview-title" });
const ul = root.createEl("ul", { cls: "folder-overview-list" });
this.listEl = ul;
if (this.yaml.includeTypes.length === 0) {
return this.addEditButton(root);
}
let files = [];
const sourceFile = plugin.app.vault.getAbstractFileByPath(ctx.sourcePath);
if (!(sourceFile instanceof import_obsidian31.TFile))
return;
let sourceFolderPath = this.yaml.folderPath.trim() || getFolderPathFromString(ctx.sourcePath);
if (!ctx.sourcePath.includes("/")) {
sourceFolderPath = "/";
}
this.registerListeners();
const sourceFolder = this.sourceFolder;
if (this.yaml.showTitle) {
const variables = {
"folderName": (sourceFolder == null ? void 0 : sourceFolder.path) === "/" || sourceFolderPath === "/" ? "Vault" : (_d = sourceFolder == null ? void 0 : sourceFolder.name) != null ? _d : "",
"folderPath": (_f = (_e = sourceFolder == null ? void 0 : sourceFolder.path) != null ? _e : sourceFolderPath) != null ? _f : "",
"filePath": sourceFile.path,
"fileName": sourceFile instanceof import_obsidian31.TFile ? sourceFile.basename : "",
"fmtpFileName": (_h = await ((_g = this.plugin.fmtpHandler) == null ? void 0 : _g.getNewFileName(sourceFile))) != null ? _h : ""
};
const fileCache = this.plugin.app.metadataCache.getFileCache(sourceFile);
const frontmatter = (_i = fileCache == null ? void 0 : fileCache.frontmatter) != null ? _i : {};
const propertyRegex = /\{\{properties\.([\w-]+)\}\}/g;
let title = this.yaml.title;
title = title.replace(propertyRegex, (_, prop) => {
const value = frontmatter[prop];
return value !== void 0 ? String(value) : "";
});
title = title.replace(/\{\{(\w+)\}\}/g, (_, key) => {
var _a2;
return (_a2 = variables[key]) != null ? _a2 : "";
});
titleEl.innerText = title;
}
if (!sourceFolder && (sourceFolderPath !== "/" && sourceFolderPath !== "")) {
return new import_obsidian31.Notice("Folder overview: Couldn't find the folder");
}
if (!sourceFolder && sourceFolderPath === "") {
sourceFolderPath = "/";
}
if (!(sourceFolder instanceof import_obsidian31.TFolder) && sourceFolderPath !== "/") {
return;
}
if ((sourceFolder == null ? void 0 : sourceFolder.path) === "/") {
const rootFiles = [];
plugin.app.vault.getAllLoadedFiles().filter((f) => {
var _a2;
return ((_a2 = f.parent) == null ? void 0 : _a2.path) === "/";
}).forEach((file) => {
if (!file.path.includes("/")) {
rootFiles.push(file);
}
});
files = rootFiles;
} else if (sourceFolder instanceof import_obsidian31.TFolder) {
files = sourceFolder.children;
}
files = (await this.filterFiles(files, plugin, sourceFolderPath, this.yaml.depth, this.pathBlacklist)).filter((file) => file !== null);
if (!this.yaml.includeTypes.includes("folder")) {
files = this.getAllFiles(files, sourceFolderPath, this.yaml.depth);
}
if (files.length === 0) {
return this.addEditButton(root);
}
files = this.sortFiles(files);
if (this.yaml.style === "grid") {
const grid = root.createEl("div", { cls: "folder-overview-grid" });
files.forEach(async (file) => {
const gridItem = grid.createEl("div", { cls: "folder-overview-grid-item" });
const gridArticle = gridItem.createEl("article", { cls: "folder-overview-grid-item-article" });
if (file instanceof import_obsidian31.TFile) {
const fileContent = await plugin.app.vault.read(file);
const descriptionEl = gridArticle.createEl("p", { cls: "folder-overview-grid-item-description" });
let description = fileContent.split("\n")[0];
if (description.length > 64) {
description = description.slice(0, 64) + "...";
}
descriptionEl.innerText = description;
const link = gridArticle.createEl("a", { cls: "folder-overview-grid-item-link internal-link" });
const title = link.createEl("h1", { cls: "folder-overview-grid-item-link-title" });
title.innerText = file.name.replace(".md", "").replace(".canvas", "");
link.href = file.path;
} else if (file instanceof import_obsidian31.TFolder) {
const folderItem = gridArticle.createEl("div", { cls: "folder-overview-grid-item-folder" });
const folderName = folderItem.createEl("h1", { cls: "folder-overview-grid-item-folder-name" });
folderName.innerText = file.name;
}
});
} 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();
});
}
if (this.yaml.useActualLinks) {
setTimeout(() => {
this.updateLinkList(files);
}, 1e3);
} else {
this.removeLinkList();
}
this.addEditButton(root);
}
updateLinkList(files = []) {
this.buildLinkList(files).then((fileLinks) => {
this.plugin.app.vault.process(this.sourceFile, (text) => {
const lines = text.split("\n");
const linkListStart = ``;
const linkListEnd = ``;
const startIdx = lines.findIndex((l) => l.trim() === linkListStart);
const endIdx = lines.findIndex((l) => l.trim() === linkListEnd);
const linkListExists = startIdx !== -1 && endIdx !== -1;
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");
});
});
}
removeLinkList() {
this.plugin.app.vault.process(this.sourceFile, (text) => {
const lines = text.split("\n");
const linkListStart = ``;
const linkListEnd = ``;
const startIdx = lines.findIndex((l) => l.trim() === linkListStart);
const endIdx = lines.findIndex((l) => l.trim() === linkListEnd);
const linkListExists = startIdx !== -1 && endIdx !== -1;
const isInvalidLinkList = endIdx < startIdx;
if (!linkListExists || isInvalidLinkList) {
return text;
}
lines.splice(startIdx, endIdx - startIdx + 1);
return lines.join("\n");
});
}
async buildLinkList(items, indent = 0) {
const result = [];
const filtered = (await this.filterFiles(items, this.plugin, this.yaml.folderPath, this.yaml.depth, this.pathBlacklist)).filter((file) => file !== null);
const sorted = this.sortFiles(filtered);
for (const item of sorted) {
const indentStr = " ".repeat(indent);
if (item instanceof import_obsidian31.TFile) {
if (this.yaml.hideLinkList) {
result.push(`${indentStr}- [[${item.path}|${item.basename}]] `);
} else {
result.push(`${indentStr}- [[${item.path}|${item.basename}]]`);
}
} else if (item instanceof import_obsidian31.TFolder) {
const isFirstLevelSub = item.path.split("/").length === this.yaml.folderPath.split("/").length + 1;
if (!this.yaml.showEmptyFolders && item.children.length === 0 && !this.yaml.onlyIncludeSubfolders) {
continue;
} else if (this.yaml.onlyIncludeSubfolders && !isFirstLevelSub && item.children.length === 0) {
continue;
}
let line = `${indentStr}- ${item.name}`;
if (this.yaml.hideLinkList) {
line += ' ';
}
let folderNote = null;
if (this.plugin instanceof FolderNotesPlugin) {
folderNote = getFolderNote(this.plugin, item.path);
}
if (folderNote) {
line = `${indentStr}- [[${folderNote.path}|${item.name}]]`;
if (this.yaml.hideLinkList) {
line += ' ';
}
}
result.push(line);
const children = item.children.filter((child) => !(child instanceof import_obsidian31.TFile && folderNote && child.path === folderNote.path));
if (children.length > 0) {
const childLinks = await this.buildLinkList(children, indent + 1);
result.push(...childLinks);
}
}
}
return result;
}
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.settings).open();
}, { capture: true });
}
async filterFiles(files, plugin, sourceFolderPath, depth, pathBlacklist) {
const filteredFiles = await Promise.all(files.map(async (file) => {
var _a, _b;
const folderPath = getFolderPathFromString(file.path);
const dontShowFolderNote = pathBlacklist.includes(file.path);
const isSubfolder = sourceFolderPath === "/" || folderPath.startsWith(sourceFolderPath);
const isSourceFile = file.path === this.sourceFilePath;
let isExcludedFromOverview = false;
if (plugin instanceof FolderNotesPlugin) {
isExcludedFromOverview = (_b = (_a = getExcludedFolder(plugin, file.path, true)) == null ? void 0 : _a.excludeFromFolderOverview) != null ? _b : false;
}
if (dontShowFolderNote && !this.yaml.showFolderNotes || !isSubfolder || isSourceFile || isExcludedFromOverview) {
return null;
}
const fileDepth = file.path.split("/").length - (sourceFolderPath === "/" ? 0 : sourceFolderPath.split("/").length);
return fileDepth <= depth ? file : null;
}));
return filteredFiles.filter((file) => file !== null);
}
sortFiles(files) {
var _a, _b;
const yaml = this.yaml;
if (!(yaml == null ? void 0 : yaml.sortBy)) {
yaml.sortBy = (_a = this.defaultSettings.sortBy) != null ? _a : "name";
yaml.sortByAsc = (_b = this.defaultSettings.sortByAsc) != null ? _b : false;
}
const collator = new Intl.Collator(void 0, { numeric: true, sensitivity: "base" });
files.sort((a, b) => {
if (a instanceof import_obsidian31.TFolder && !(b instanceof import_obsidian31.TFolder)) {
return -1;
}
if (!(a instanceof import_obsidian31.TFolder) && b instanceof import_obsidian31.TFolder) {
return 1;
}
if (a instanceof import_obsidian31.TFolder && b instanceof import_obsidian31.TFolder) {
return yaml.sortByAsc ? collator.compare(a.name, b.name) : collator.compare(b.name, a.name);
}
if (a instanceof import_obsidian31.TFile && b instanceof import_obsidian31.TFile) {
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;
});
return files;
}
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_obsidian31.TFolder) {
if (fileDepth < depth) {
allFiles.push(...this.getAllFiles(file.children, sourceFolderPath, depth));
}
} else {
allFiles.push(file);
}
});
return allFiles;
}
fileMenu(file, e) {
const plugin = this.plugin;
const fileMenu = new import_obsidian31.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.settings).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.plugin;
const folderMenu = new import_obsidian31.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.settings).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.plugin;
const menu = new import_obsidian31.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.settings).open();
});
});
menu.showAtPosition({ x: e.pageX, y: e.pageY });
}
getElFromOverview(path) {
const el = this.listEl.querySelector(`[data-path='${CSS.escape(path)}']`);
return el;
}
};
async function updateYaml(plugin, ctx, el, yaml, addLinkList) {
const file = plugin.app.vault.getAbstractFileByPath(ctx.sourcePath);
if (!(file instanceof import_obsidian31.TFile))
return;
let stringYaml = (0, import_obsidian31.stringifyYaml)(yaml);
await 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 === -1 || !lineEnd)
return text;
const lineLength = lineEnd - lineStart;
const lines = text.split("\n");
let overviewBlock2 = `\`\`\`folder-overview
${stringYaml}\`\`\``;
overviewBlock2 += addLinkList ? `
` : "";
lines.splice(lineStart, lineLength + 1, overviewBlock2);
return lines.join("\n");
}
let overviewBlock = `\`\`\`folder-overview
${stringYaml}\`\`\``;
overviewBlock += addLinkList ? `
` : "";
return overviewBlock;
});
}
function getCodeBlockEndLine(text, startLine, count = 1) {
let line = startLine + 1;
const lines = text.split("\n");
while (line < lines.length) {
if (count > 50) {
return -1;
}
if (lines[line].startsWith("```")) {
return line;
}
line++;
count++;
}
return line;
}
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([\s\S]*?)```/g);
if (!yamlBlocks)
return overviews;
for (const block of yamlBlocks) {
const yaml = (0, import_obsidian31.parseYaml)(block.replace("```folder-overview\n", "").replace("```", ""));
if (!yaml)
continue;
overviews.push(yaml);
}
return overviews;
}
async function updateYamlById(plugin, overviewId, file, newYaml, addLinkList) {
await plugin.app.vault.process(file, (text) => {
const yamlBlocks = text.match(/```folder-overview\n([\s\S]*?)```/g);
if (!yamlBlocks)
return text;
for (const block of yamlBlocks) {
const yaml = (0, import_obsidian31.parseYaml)(block.replace("```folder-overview\n", "").replace("```", ""));
if (!yaml)
continue;
if (yaml.id === overviewId) {
let stringYaml = (0, import_obsidian31.stringifyYaml)(newYaml);
if (stringYaml[stringYaml.length - 1] !== "\n") {
stringYaml += "\n";
}
let newBlock = `\`\`\`folder-overview
${stringYaml}\`\`\``;
if (addLinkList) {
newBlock += `
`;
}
text = text.replace(block, newBlock);
}
}
return text;
});
}
function parseOverviewTitle(overview, plugin, folder, sourceFile) {
var _a, _b, _c, _d, _e;
const sourceFolderPath = overview.folderPath.trim();
let title = overview.title;
const variables = {
"folderName": (folder == null ? void 0 : folder.path) === "/" || sourceFolderPath === "/" ? "Vault" : (_a = folder == null ? void 0 : folder.name) != null ? _a : "",
"folderPath": (_c = (_b = folder == null ? void 0 : folder.path) != null ? _b : sourceFolderPath) != null ? _c : "",
"filePath": (_d = sourceFile == null ? void 0 : sourceFile.path) != null ? _d : "",
"fileName": sourceFile instanceof import_obsidian31.TFile ? sourceFile.basename : ""
};
if (sourceFile instanceof import_obsidian31.TFile) {
const fileCache = plugin.app.metadataCache.getFileCache(sourceFile);
const frontmatter = (_e = fileCache == null ? void 0 : fileCache.frontmatter) != null ? _e : {};
const propertyRegex = /\{\{properties\.([\w-]+)\}\}/g;
title = title.replace(propertyRegex, (_, prop) => {
const value = frontmatter[prop];
return value !== void 0 ? String(value) : "";
});
title = title.replace(/\{\{(\w+)\}\}/g, (_, key) => {
var _a2;
return (_a2 = variables[key]) != null ? _a2 : "";
});
}
return title;
}
var CustomMarkdownRenderChild = class extends import_obsidian31.MarkdownRenderChild {
constructor(el, folderOverview) {
super(el);
this.folderOverview = folderOverview;
}
onunload() {
this.folderOverview.disconnectListeners();
}
};
// src/obsidian-folder-overview/src/suggesters/FolderSuggester.ts
var import_obsidian32 = require("obsidian");
var FolderSuggest2 = class extends import_obsidian32.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;
} else {
files = this.plugin.app.vault.getAllLoadedFiles().slice(0, 100);
}
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_obsidian32.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_obsidian33 = require("obsidian");
var ListComponent2 = class {
constructor(containerEl, values = [], defaultValues = []) {
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_obsidian33.setIcon)(svgElement, "x");
removeSpan.onClickEvent((e) => {
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_obsidian33.setIcon)(resetButton, "rotate-ccw");
resetButton.onClickEvent((e) => {
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 DEFAULT_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
};
var SettingsTab = class extends import_obsidian34.PluginSettingTab {
constructor(plugin) {
super(plugin.app, plugin);
}
display() {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl("p", { text: "Edit the default settings of folder overviews", cls: "setting-item-description" });
this.display = this.display.bind(this);
createOverviewSettings(containerEl, this.plugin.settings, this.plugin, this.plugin.settings, 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;
} else {
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_obsidian34.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_obsidian34.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_obsidian34.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_obsidian34.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, "folder-path", changedSection, (settingEl) => {
const folderPathSetting = new import_obsidian34.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\u2019s parent folder path", "Path of folder linked to the file"];
if (value.trim() !== "" && !whiteList.includes(value.trim())) {
value = (0, import_obsidian34.normalizePath)(value);
}
if (!whiteList.includes(value.trim())) {
if (!(plugin.app.vault.getAbstractFileByPath(value) instanceof import_obsidian34.TFolder) && 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_obsidian34.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, "hide-folder-overview", changedSection, (settingEl) => {
const hideOverviewSeting = new import_obsidian34.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_obsidian34.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_obsidian34.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(async (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_obsidian34.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) < 8 && !((_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.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_obsidian34.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_obsidian34.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) => {
new import_obsidian34.Setting(settingEl).setName("File depth").setDesc("File & folder = +1 depth").addSlider((slider) => slider.setValue((yaml == null ? void 0 : yaml.depth) || 2).setLimits(1, 10, 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_obsidian34.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_obsidian34.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_obsidian34.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_obsidian34.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_obsidian34.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_obsidian34.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_obsidian34.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);
}
async function updateSettings(contentEl, yaml, plugin, addLinkList, defaultSettings, el, ctx, file) {
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;
}
toggleSections(contentEl, {
"setting-title-container-fn": 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-fmtp-integration": !!plugin.app.plugins.getPlugin("obsidian-front-matter-title-plugin")
});
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);
}
}
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 sections2 = contentEl.querySelectorAll(`.${sectionClass}`);
sections2.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 overviewSettings5 = plugin.settings.defaultOverview;
const containerEl = settingsTab.settingsPage;
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);
createOverviewSettings(containerEl, overviewSettings5, plugin, plugin.settings.defaultOverview, settingsTab.display, void 0, void 0, void 0, settingsTab);
}
// src/settings/ExcludedFoldersSettings.ts
var import_obsidian36 = require("obsidian");
// src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts
var import_obsidian35 = require("obsidian");
// src/ExcludeFolders/WhitelistFolder.ts
var WhitelistedFolder = class {
constructor(path, position, id, plugin) {
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_obsidian35.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_obsidian35.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.display();
});
});
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_obsidian36.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_obsidian36.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_obsidian36.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_obsidian36.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_obsidian36.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.display();
});
});
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
},
useSubmenus: true,
syncMove: true,
frontMatterTitle: {
enabled: false,
explorer: true,
path: true
},
settingsTab: "general",
supportedFileTypes: ["md", "canvas"],
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
};
var SettingsTab2 = class extends import_obsidian37.PluginSettingTab {
constructor(app2, plugin) {
super(app2, 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:
renderGeneral(this);
break;
case this.TABS.FOLDER_OVERVIEW.id:
renderFolderOverview(this);
break;
case this.TABS.EXCLUDE_FOLDERS.id:
renderExcludeFolders(this);
break;
case this.TABS.FILE_EXPLORER.id:
renderFileExplorer(this);
break;
case this.TABS.PATH.id:
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 tabEl2 of tabBar.children) {
tabEl2.removeClass("fn-settings-tab-active");
if (!plugin) {
return;
}
plugin.settings.settingsTab = tabId.toLocaleLowerCase();
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_obsidian37.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_obsidian37.TFolder) {
const folderNote = getFolderNote(this.plugin, folder.path, void 0, void 0, oldTemplate);
if (!(folderNote instanceof import_obsidian37.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}`;
}
this.app.fileManager.renameFile(folderNote, newPath);
}
}
this.plugin.settings.oldFolderNoteName = this.plugin.settings.folderNoteName;
this.plugin.saveSettings();
new import_obsidian37.Notice("Finished updating folder notes");
}
switchStorageLocation(oldMethod) {
new import_obsidian37.Notice("Starting to switch storage location...");
this.app.vault.getAllLoadedFiles().forEach((file) => {
if (file instanceof import_obsidian37.TFolder) {
const folderNote = getFolderNote(this.plugin, file.path, oldMethod);
if (folderNote instanceof import_obsidian37.TFile) {
if (this.plugin.settings.storageLocation === "parentFolder") {
let newPath = "";
if (getFolderPathFromString(file.path).trim() === "") {
newPath = `${folderNote.name}`;
} else {
newPath = `${getFolderPathFromString(file.path)}/${folderNote.name}`;
}
this.plugin.app.fileManager.renameFile(folderNote, newPath);
} else if (this.plugin.settings.storageLocation === "insideFolder") {
if (getFolderPathFromString(folderNote.path) === file.path) {
return;
} else {
const newPath = `${file.path}/${folderNote.name}`;
this.plugin.app.fileManager.renameFile(folderNote, newPath);
}
}
}
}
});
new import_obsidian37.Notice("Finished switching storage location");
}
onClose() {
this.plugin.settingsOpened = false;
}
};
// src/Commands.ts
var import_obsidian38 = require("obsidian");
var Commands = class {
constructor(app2, plugin) {
this.plugin = plugin;
this.app = app2;
}
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_obsidian38.TFile))
return false;
const folder = file.parent;
if (!folder || !(folder instanceof import_obsidian38.TFolder))
return false;
if (folder.path === "" || folder.path === "/")
return false;
const folderNote = getFolderNote(this.plugin, folder.path);
if (folderNote instanceof import_obsidian38.TFile && folderNote === file)
return false;
if (checking)
return true;
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_obsidian38.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_obsidian38.Notice("Folder already exists");
}
const automaticallyCreateFolderNote = this.plugin.settings.autoCreate;
this.plugin.settings.autoCreate = false;
this.plugin.saveSettings();
await this.plugin.app.vault.createFolder(newPath);
const folder = this.plugin.app.vault.getAbstractFileByPath(newPath);
if (!(folder instanceof import_obsidian38.TFolder))
return;
createFolderNote(this.plugin, folder.path, true, "." + file.extension, false, file);
this.plugin.settings.autoCreate = automaticallyCreateFolderNote;
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_obsidian38.TFile))
return false;
const folder = file.parent;
if (!(folder instanceof import_obsidian38.TFolder))
return false;
if (folder.path === "" || folder.path === "/")
return false;
if (checking)
return true;
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_obsidian38.TFile))
return false;
const folder = file.parent;
if (!(folder instanceof import_obsidian38.TFolder))
return false;
if (folder.path === "" || folder.path === "/")
return false;
if (checking)
return true;
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();
if (!folder)
return false;
const folderNote = getFolderNote(this.plugin, folder.path);
if (folderNote instanceof import_obsidian38.TFile)
return false;
if (checking)
return true;
const ext = "." + fileType;
const path = folder.path;
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_obsidian38.TFile))
return false;
const folder = file.parent;
if (!(folder instanceof import_obsidian38.TFolder))
return false;
const folderNote = getFolderNote(this.plugin, folder.path);
if (!(folderNote instanceof import_obsidian38.TFile))
return false;
if (checking)
return true;
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();
if (!folder)
return false;
const folderNote = getFolderNote(this.plugin, folder.path);
if (!(folderNote instanceof import_obsidian38.TFile))
return false;
if (checking)
return true;
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_obsidian38.TFile))
return false;
const folder = file.parent;
if (!(folder instanceof import_obsidian38.TFolder))
return false;
const folderNote = getFolderNote(this.plugin, folder.path);
if (!(folderNote instanceof import_obsidian38.TFile))
return false;
if (checking)
return true;
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();
if (!folder)
return false;
const folderNote = getFolderNote(this.plugin, folder.path);
if (!(folderNote instanceof import_obsidian38.TFile))
return false;
if (checking)
return true;
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.file;
if (!(file instanceof import_obsidian38.TFile))
return false;
if (text && text.trim() !== "") {
if (checking) {
return true;
}
const blacklist = ["*", "\\", '"', "/", "<", ">", "?", "|", ":"];
for (const char of blacklist) {
if (text.includes(char)) {
new import_obsidian38.Notice('File name cannot contain any of the following characters: * " \\ / < > : | ?');
return false;
}
}
if (text.endsWith(".")) {
new import_obsidian38.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_obsidian38.TFolder) {
new import_obsidian38.Notice("Folder note already exists");
return false;
} else {
this.plugin.app.vault.createFolder(text);
createFolderNote(this.plugin, text, false);
}
} else {
folder = this.plugin.app.vault.getAbstractFileByPath(folderPath + "/" + text);
if (folder instanceof import_obsidian38.TFolder) {
new import_obsidian38.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_obsidian38.Notice("File already exists");
return false;
}
}
this.plugin.app.vault.createFolder(folderPath + "/" + text);
createFolderNote(this.plugin, folderPath + "/" + text, false);
}
const fileName = this.plugin.settings.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_obsidian38.TFile) {
if (this.plugin.settings.storageLocation === "insideFolder") {
folder = file.parent;
} else {
const fileName = extractFolderName(this.plugin.settings.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_obsidian38.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_obsidian38.TFolder) {
folder = file.parent;
}
}
menu.addItem(async (item) => {
if (import_obsidian38.Platform.isDesktop && !import_obsidian38.Platform.isTablet && this.plugin.settings.useSubmenus) {
item.setTitle("Folder Note Commands").setIcon("folder-edit");
}
let subMenu;
if (!import_obsidian38.Platform.isDesktopApp || !import_obsidian38.Platform.isDesktop || import_obsidian38.Platform.isTablet || !this.plugin.settings.useSubmenus) {
subMenu = menu;
item.setDisabled(true);
} else {
subMenu = item.setSubmenu();
}
if (file instanceof import_obsidian38.TFile) {
subMenu.addItem((item2) => {
item2.setTitle("Create folder note").setIcon("edit").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_obsidian38.Notice("Folder already exists");
}
const automaticallyCreateFolderNote = this.plugin.settings.autoCreate;
this.plugin.settings.autoCreate = false;
this.plugin.saveSettings();
await this.plugin.app.vault.createFolder(newPath);
const newFolder = this.plugin.app.vault.getAbstractFileByPath(newPath);
if (!(newFolder instanceof import_obsidian38.TFolder))
return;
await createFolderNote(this.plugin, newFolder.path, true, "." + file.extension, false, file);
this.plugin.settings.autoCreate = automaticallyCreateFolderNote;
this.plugin.saveSettings();
});
});
if (getFolderPathFromString(file.path) === "")
return;
if (!(folder instanceof import_obsidian38.TFolder))
return;
if (folder.path === "" || folder.path === "/")
return;
subMenu.addItem((item2) => {
item2.setTitle(`Turn into folder note for ${folder == null ? void 0 : folder.name}`).setIcon("edit").onClick(() => {
if (!folder || !(folder instanceof import_obsidian38.TFolder))
return;
const folderNote2 = getFolderNote(this.plugin, folder.path);
turnIntoFolderNote(this.plugin, file, folder, folderNote2);
});
});
}
if (!(file instanceof import_obsidian38.TFolder))
return;
const excludedFolder = getExcludedFolder(this.plugin, file.path, false);
const detachedExcludedFolder = getDetachedFolder(this.plugin, file.path);
if (excludedFolder && !excludedFolder.hideInSettings) {
subMenu.addItem((item2) => {
item2.setTitle("Remove folder from excluded folders").setIcon("trash").onClick(() => {
this.plugin.settings.excludeFolders = this.plugin.settings.excludeFolders.filter((folder2) => folder2.path !== file.path || folder2.detached);
this.plugin.saveSettings(true);
new import_obsidian38.Notice("Successfully removed folder from excluded folders");
});
});
return;
}
if (detachedExcludedFolder) {
subMenu.addItem((item2) => {
item2.setTitle("Remove folder from detached folders").setIcon("trash").onClick(() => {
deleteExcludedFolder(this.plugin, detachedExcludedFolder);
});
});
}
if (detachedExcludedFolder) {
return;
}
subMenu.addItem((item2) => {
item2.setTitle("Exclude folder from folder notes").setIcon("x-circle").onClick(() => {
const excludedFolder2 = new ExcludedFolder(file.path, this.plugin.settings.excludeFolders.length, void 0, this.plugin);
this.plugin.settings.excludeFolders.push(excludedFolder2);
this.plugin.saveSettings(true);
new import_obsidian38.Notice("Successfully excluded folder from folder notes");
});
});
if (!(file instanceof import_obsidian38.TFolder))
return;
const folderNote = getFolderNote(this.plugin, file.path);
if (folderNote instanceof import_obsidian38.TFile && !detachedExcludedFolder) {
subMenu.addItem((item2) => {
item2.setTitle("Delete folder note").setIcon("trash").onClick(() => {
deleteFolderNote(this.plugin, folderNote, true);
});
});
subMenu.addItem((item2) => {
item2.setTitle("Open folder note").setIcon("chevron-right-square").onClick(() => {
openFolderNote(this.plugin, folderNote);
});
});
subMenu.addItem((item2) => {
item2.setTitle("Detach folder note").setIcon("unlink").onClick(() => {
detachFolderNote(this.plugin, folderNote);
});
});
subMenu.addItem((item2) => {
item2.setTitle("Copy Obsidian URL").setIcon("link").onClick(() => {
this.app.copyObsidianUrl(folderNote);
});
});
if (this.plugin.settings.hideFolderNote) {
if (excludedFolder == null ? void 0 : excludedFolder.showFolderNote) {
subMenu.addItem((item2) => {
item2.setTitle("Hide folder note in explorer").setIcon("eye-off").onClick(() => {
hideFolderNoteInFileExplorer(file.path, this.plugin);
});
});
} else {
subMenu.addItem((item2) => {
item2.setTitle("Show folder note in explorer").setIcon("eye").onClick(() => {
showFolderNoteInFileExplorer(file.path, this.plugin);
});
});
}
}
} else {
subMenu.addItem((item2) => {
item2.setTitle("Create markdown folder note").setIcon("edit").onClick(() => {
createFolderNote(this.plugin, file.path, true, ".md");
});
});
this.plugin.settings.supportedFileTypes.forEach((fileType) => {
if (fileType === "md")
return;
subMenu.addItem((item2) => {
item2.setTitle(`Create ${fileType} folder note`).setIcon("edit").onClick(() => {
createFolderNote(this.plugin, file.path, true, "." + fileType);
});
});
});
}
});
}));
}
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.file;
if (!(file instanceof import_obsidian38.TFile))
return;
const blacklist = ["*", "\\", '"', "/", "<", ">", "?", "|", ":"];
for (const char of blacklist) {
if (text.includes(char)) {
new import_obsidian38.Notice('File name cannot contain any of the following characters: * " \\ / < > : | ?');
return;
}
}
if (text.endsWith(".")) {
new import_obsidian38.Notice("File name cannot end with a dot");
return;
}
let folder;
const folderPath = getFolderPathFromString(file.path);
const fileName = this.plugin.settings.folderNoteName.replace("{{folder_name}}", text);
if (folderPath === "") {
folder = this.plugin.app.vault.getAbstractFileByPath(text);
if (folder instanceof import_obsidian38.TFolder) {
return new import_obsidian38.Notice("Folder note already exists");
} else {
this.plugin.app.vault.createFolder(text);
createFolderNote(this.plugin, text, false);
}
} else {
folder = this.plugin.app.vault.getAbstractFileByPath(folderPath + "/" + text);
if (folder instanceof import_obsidian38.TFolder) {
return new import_obsidian38.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_obsidian38.Notice("File already exists");
}
}
this.plugin.app.vault.createFolder(folderPath + "/" + text);
createFolderNote(this.plugin, folderPath + "/" + text, false);
}
if (fileName !== text) {
editor.replaceSelection(`[[${fileName}]]`);
} else {
editor.replaceSelection(`[[${fileName}|${text}]]`);
}
});
});
}));
}
};
// src/events/MutationObserver.ts
var import_obsidian40 = require("obsidian");
// src/events/handleClick.ts
var import_obsidian39 = require("obsidian");
async function handleViewHeaderClick(event, plugin) {
event.stopImmediatePropagation();
event.preventDefault();
event.stopPropagation();
if (!(event.target instanceof HTMLElement))
return;
if (!plugin.settings.openFolderNoteOnClickInPath)
return;
const folderPath = event.target.getAttribute("data-path");
if (!folderPath) {
return;
}
const excludedFolder = getExcludedFolder(plugin, folderPath, true);
if (excludedFolder == null ? void 0 : excludedFolder.disableFolderNote) {
event.target.onclick = null;
event.target.click();
return;
} else if ((excludedFolder == null ? void 0 : excludedFolder.enableCollapsing) || plugin.settings.enableCollapsing) {
event.target.onclick = null;
event.target.click();
}
const folderNote = getFolderNote(plugin, folderPath);
if (folderNote) {
await openFolderNote(plugin, folderNote, event).then(async () => {
const fileExplorerPlugin = plugin.app.internalPlugins.getEnabledPluginById("file-explorer");
if (fileExplorerPlugin && import_obsidian39.Platform.isMobile && plugin.settings.openSidebar.mobile) {
setTimeout(() => {
fileExplorerPlugin.revealInFolder(folderNote);
}, 200);
} else if (fileExplorerPlugin && import_obsidian39.Platform.isDesktop && plugin.settings.openSidebar.desktop) {
fileExplorerPlugin.revealInFolder(folderNote);
}
});
return;
} else if (event.altKey || import_obsidian39.Keymap.isModEvent(event) === "tab") {
if (plugin.settings.altKey && event.altKey || plugin.settings.ctrlKey && import_obsidian39.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;
}
}
event.target.onclick = null;
event.target.click();
}
// 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 = document.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 = document.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")) || "";
if (!folderEl || !folderPath) {
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);
}
}, 50);
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_obsidian40.Platform.isMobile && plugin.settings.disableOpenFolderNoteOnClick)
return;
plugin.registerDomEvent(folderTitle, "pointerover", (event) => {
plugin.hoveredElement = folderTitle;
plugin.mouseEvent = event;
if (!import_obsidian40.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) {
const headers = titleContainer.querySelectorAll("span.view-header-breadcrumb");
let path = "";
headers.forEach(async (breadcrumb) => {
var _a, _b;
path += (_a = breadcrumb.getAttribute("old-name")) != null ? _a : breadcrumb.innerText.trim();
path += "/";
const folderPath = path.slice(0, -1);
const excludedFolder = getExcludedFolder(plugin, folderPath, true);
if (excludedFolder == null ? void 0 : excludedFolder.disableFolderNote)
return;
const folderNote = getFolderNote(plugin, folderPath);
if (!folderNote)
return;
if (folderNote)
breadcrumb.classList.add("has-folder-note");
breadcrumb == null ? void 0 : breadcrumb.setAttribute("data-path", path.slice(0, -1));
if (!breadcrumb.onclick) {
breadcrumb.addEventListener("click", (e) => {
handleViewHeaderClick(e, plugin);
}, { capture: true });
}
if (plugin.settings.frontMatterTitle.enabled) {
(_b = plugin.fmtpHandler) == null ? void 0 : _b.fmptUpdateFolderName({ id: "", result: false, path: folderPath, pathOnly: true, breadcrumb }, true);
}
});
}
function scheduleIdle(callback, options) {
if ("requestIdleCallback" in window) {
window.requestIdleCallback(callback, options);
} else {
setTimeout(callback, (options == null ? void 0 : options.timeout) || 200);
}
}
// src/events/handleRename.ts
var import_obsidian41 = require("obsidian");
function handleRename(file, oldPath, plugin) {
const folder = file.parent;
const oldFolder = plugin.app.vault.getAbstractFileByPath(getFolderPathFromString(oldPath));
if (folder instanceof import_obsidian41.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_obsidian41.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_obsidian41.TFolder) {
const folder2 = file;
plugin.tabManager.updateTab(folder2.path);
updateExcludedFolderPath(folder2, oldPath, plugin);
if (isFolderRename(folder2, oldPath)) {
return handleFolderRename(folder2, oldPath, plugin);
} else {
return handleFolderMove(folder2, oldPath, plugin);
}
} else if (file instanceof import_obsidian41.TFile) {
if (isFileRename(file, oldPath)) {
return fmptUpdateFileName(file, oldPath, plugin);
} else {
return handleFileMove(file, oldPath, plugin);
}
}
}
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_obsidian41.TFolder) || !folderNote)
return;
const newFolder = plugin.app.vault.getAbstractFileByPath(file.path);
if (!(newFolder instanceof import_obsidian41.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 = 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);
const isFileNowFolderNoteInNewFolder = folderName === (newFolder == null ? void 0 : newFolder.name);
const isFileMovedFromOldFolderNote = oldFolder && oldFolder.name === oldFileName && (newFolder == null ? void 0 : newFolder.path) !== oldFolder.path;
const isFileNowFolderNoteWithExistingNote = folderName === (newFolder == null ? void 0 : newFolder.name) && folderNote;
if (isFileNowFolderNoteWithExistingNote) {
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);
}
return 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);
}
});
} else if (isFileNowFolderNoteInNewFolder) {
if (!(excludedFolder == null ? void 0 : excludedFolder.disableFolderNote)) {
markFileAsFolderNote(file, plugin);
if (newFolder instanceof import_obsidian41.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_obsidian41.TFolder) {
hideFolderNoteInFileExplorer(oldFolder.path, plugin);
unmarkFolderAsFolderNote(oldFolder, plugin);
}
}
} else if (isFileMovedFromOldFolderNote) {
unmarkFileAsFolderNote(file, plugin);
if (oldFolder instanceof import_obsidian41.TFolder) {
removeActiveFolder(plugin);
hideFolderNoteInFileExplorer(oldFolder.path, plugin);
unmarkFolderAsFolderNote(oldFolder, plugin);
}
}
}
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_obsidian41.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 fmptUpdateFileName(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 (!(excludedFolder == null ? void 0 : excludedFolder.disableFolderNote) && folderName === (newFolder == null ? void 0 : newFolder.name) && !detachedExcludedFolder) {
addCSSClassToFileExplorerEl(file.path, "is-folder-note", false, plugin);
addCSSClassToFileExplorerEl(newFolder.path, "has-folder-note", false, plugin);
return;
} else if ((excludedFolder == null ? void 0 : excludedFolder.disableFolderNote) || folderName !== (newFolder == null ? void 0 : newFolder.name)) {
removeCSSClassFromFileExplorerEL(file.path, "is-folder-note", false, plugin);
removeCSSClassFromFileExplorerEL((newFolder == null ? void 0 : newFolder.path) || "", "has-folder-note", false, plugin);
}
if ((excludedFolder == null ? void 0 : excludedFolder.disableSync) || !plugin.settings.syncFolderName) {
return;
}
if (folderName === (newFolder == null ? void 0 : newFolder.name)) {
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);
return;
}
if (!oldFolder)
return;
if (oldFolderName === oldFolder.name && (newFolder == null ? void 0 : newFolder.path) === oldFolder.path) {
return renameFolderOnFileRename(file, oldPath, oldFolder, plugin);
} else if (folderNote && oldFolderName === oldFolder.name) {
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);
return new import_obsidian41.Notice("A folder with the same name already exists");
}
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();
}
// src/events/handleCreate.ts
var import_obsidian42 = require("obsidian");
async function handleCreate(file, plugin) {
if (!plugin.app.workspace.layoutReady)
return;
const folder = file.parent;
if (folder instanceof import_obsidian42.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_obsidian42.TFile) {
handleFileCreation(file, plugin);
} else if (file instanceof import_obsidian42.TFolder && plugin.settings.autoCreate) {
handleFolderCreation(file, plugin);
}
}
async function handleFileCreation(file, plugin) {
const folder = getFolder(plugin, file);
if (!(folder instanceof import_obsidian42.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_obsidian42.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) {
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;
createFolderNote(plugin, folder.path, openFile, void 0, true);
addCSSClassToFileExplorerEl(folder.path, "has-folder-note", false, plugin);
}
// src/events/TabManager.ts
var import_obsidian43 = 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_obsidian43.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_obsidian43.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_obsidian43.TFolder))
return;
const folderNote = getFolderNote(this.plugin, folder.path);
if (!folderNote)
return;
this.app.workspace.iterateAllLeaves((leaf) => {
var _a;
if (!(leaf.view instanceof import_obsidian43.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_obsidian44 = require("obsidian");
function handleDelete(file, plugin) {
const folder = plugin.app.vault.getAbstractFileByPath(getFolderPathFromString(file.path));
if (folder instanceof import_obsidian44.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_obsidian44.TFile) {
const folder2 = getFolder(plugin, file);
if (!folder2) {
return;
}
const folderNote2 = getFolderNote(plugin, folder2.path);
if (folderNote2) {
return;
}
removeCSSClassFromFileExplorerEL(folder2.path, "has-folder-note", false, plugin);
removeCSSClassFromFileExplorerEL(folder2.path, "only-has-folder-note", true, plugin);
hideFolderNoteInFileExplorer(folder2.path, plugin);
}
if (!(file instanceof import_obsidian44.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/view.ts
var import_obsidian47 = require("obsidian");
// src/obsidian-folder-overview/src/main.ts
var import_obsidian46 = require("obsidian");
// src/obsidian-folder-overview/src/Commands.ts
var import_obsidian45 = 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) {
const json = Object.assign({}, plugin instanceof FolderOverviewPlugin ? plugin.settings : plugin.settings.defaultOverview);
json.id = crypto.randomUUID();
const yaml = (0, import_obsidian45.stringifyYaml)(json);
let overviewBlock = `\`\`\`folder-overview
${yaml}\`\`\`
`;
if (plugin instanceof FolderOverviewPlugin && plugin.settings.useActualLinks || plugin instanceof FolderNotesPlugin && plugin.settings.defaultOverview.useActualLinks) {
overviewBlock = `${overviewBlock}
`;
}
if (lineText.trim() === "") {
editor.replaceSelection(overviewBlock);
} else if (lineText.trim() === ">") {
const lines = yaml.split("\n");
const newLines = lines.map((line2) => {
return `> ${line2}`;
});
let quotedBlock = `\`\`\`folder-overview
${newLines.join("\n")}\`\`\`
`;
if (plugin instanceof FolderOverviewPlugin && plugin.settings.useActualLinks || plugin instanceof FolderNotesPlugin && plugin.settings.defaultOverview.useActualLinks) {
quotedBlock = `${overviewBlock}
`;
}
editor.replaceSelection(quotedBlock);
}
}
return true;
}
return false;
}
});
plugin.registerEvent(plugin.app.workspace.on("editor-menu", (menu, editor, view) => {
const line = editor.getCursor().line;
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_obsidian45.Notice(frag);
}
const json = Object.assign({}, plugin instanceof FolderOverviewPlugin ? plugin.settings : plugin.settings.defaultOverview);
json.id = crypto.randomUUID();
const yaml = (0, import_obsidian45.stringifyYaml)(json);
let overviewBlock = `\`\`\`folder-overview
${yaml}\`\`\`
`;
if (plugin instanceof FolderOverviewPlugin && plugin.settings.useActualLinks || plugin instanceof FolderNotesPlugin && plugin.settings.defaultOverview.useActualLinks) {
overviewBlock = `${overviewBlock}
`;
}
if (lineText.trim() === "") {
editor.replaceSelection(overviewBlock);
} else if (lineText.trim() === ">") {
const lines = yaml.split("\n");
const newLines = lines.map((line2) => {
return `> ${line2}`;
});
let quotedBlock = `\`\`\`folder-overview
${newLines.join("\n")}\`\`\`
`;
if (plugin instanceof FolderOverviewPlugin && plugin.settings.useActualLinks || plugin instanceof FolderNotesPlugin && plugin.settings.defaultOverview.useActualLinks) {
quotedBlock = `${overviewBlock}
`;
}
editor.replaceSelection(quotedBlock);
}
});
});
}
}));
}
// src/obsidian-folder-overview/src/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.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() {
if (this.eventRef) {
this.dispatcher.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_obsidian46.Plugin {
constructor() {
super(...arguments);
this.updateOverviewView = updateOverviewView;
this.updateViewDropdown = updateViewDropdown;
}
async onload() {
await this.loadSettings();
this.settingsTab = new SettingsTab(this);
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);
}
});
this.registerMarkdownCodeBlockProcessor("folder-overview", (source, el, ctx) => {
this.handleOverviewBlock(source, el, ctx);
});
console.log("loading Folder Overview plugin");
}
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_obsidian46.parseYaml)(source), ctx, el, this.settings).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);
await folderOverview.create(this, (0, import_obsidian46.parseYaml)(source), el, ctx);
this.updateOverviewView(this);
});
} catch (e) {
new import_obsidian46.Notice("Error creating folder overview (folder notes plugin) - check console for more details");
console.error(e);
}
}
async onunload() {
console.log("unloading Folder Overview plugin");
}
async loadSettings() {
const data = await this.loadData();
this.settings = Object.assign({}, DEFAULT_SETTINGS, data);
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");
}
// src/obsidian-folder-overview/src/view.ts
var FOLDER_OVERVIEW_VIEW = "folder-overview-view";
var FolderOverviewView = class extends import_obsidian47.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 = this.plugin.settings;
} else if (plugin instanceof FolderNotesPlugin) {
this.defaultSettings = plugin.settings.defaultOverview;
}
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_obsidian47.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) => {
const title = parseOverviewTitle(overview, plugin, activeFile.parent, 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");
if (cb.getValue() === "default" || !(yaml == null ? void 0 : yaml.id.trim()) || cb.getValue().trim() === "") {
yaml = defaultSettings;
cb.setValue("default");
} else {
yaml = overviews.find((overview) => overview.id === yaml.id);
}
cb.onChange(async (value) => {
if (value === "default") {
yaml = defaultSettings;
} else {
yaml = overviews.find((overview) => overview.id === value);
}
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/main.ts
var FolderNotesPlugin = class extends import_obsidian48.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.log("loading folder notes plugin");
await this.loadSettings();
this.settingsTab = new SettingsTab2(this.app, this);
this.addSettingTab(this.settingsTab);
this.saveSettings();
document.body.classList.add("folder-notes-plugin");
if (this.settings.hideFolderNote) {
document.body.classList.add("hide-folder-note");
}
if (this.settings.hideCollapsingIconForEmptyFolders) {
document.body.classList.add("fn-hide-empty-collapse-icon");
}
if (this.settings.underlineFolder) {
document.body.classList.add("folder-note-underline");
}
if (this.settings.boldName) {
document.body.classList.add("folder-note-bold");
}
if (this.settings.cursiveName) {
document.body.classList.add("folder-note-cursive");
}
if (this.settings.boldNameInPath) {
document.body.classList.add("folder-note-bold-path");
}
if (this.settings.cursiveNameInPath) {
document.body.classList.add("folder-note-cursive-path");
}
if (this.settings.underlineFolderInPath) {
document.body.classList.add("folder-note-underline-path");
}
if (this.settings.stopWhitespaceCollapsing) {
document.body.classList.add("fn-whitespace-stop-collapsing");
}
if (this.settings.hideCollapsingIcon) {
document.body.classList.add("fn-hide-collapse-icon");
}
if (!this.settings.highlightFolder) {
document.body.classList.add("disable-folder-highlight");
}
if ((0, import_obsidian48.requireApiVersion)("1.7.2")) {
document.body.classList.add("version-1-7-2");
}
new Commands(this.app, this).registerCommands();
registerOverviewCommands(this);
this.app.workspace.onLayoutReady(this.onLayoutReady.bind(this));
if (!this.settings.persistentSettingsTab.afterRestart) {
this.settings.settingsTab = "general";
}
this.registerDomEvent(window, "keydown", (event) => {
var _a;
const hoveredElement = this.hoveredElement;
if (this.hoverLinkTriggered)
return;
if (!hoveredElement)
return;
if (!import_obsidian48.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.vault.on("create", (file) => {
handleCreate(file, this);
}));
this.registerEvent(this.app.workspace.on("file-open", async (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("rename", (file, oldPath) => {
handleRename(file, oldPath, this);
}));
this.registerEvent(this.app.vault.on("delete", (file) => {
handleDelete(file, this);
}));
this.registerMarkdownCodeBlockProcessor("folder-overview", (source, el, ctx) => {
this.handleOverviewBlock(source, el, ctx);
});
}
onLayoutReady() {
var _a, _b, _c;
registerFileExplorerObserver(this);
this.registerView(FOLDER_OVERVIEW_VIEW, (leaf2) => {
return new FolderOverviewView(leaf2, this);
});
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(document, "click", (evt) => {
this.handleFileExplorerClick(evt);
}, true);
this.registerDomEvent(document, "auxclick", (evt) => {
this.handleFileExplorerClick(evt);
}, true);
const fileExplorerPlugin = this.app.internalPlugins.getEnabledPluginById("file-explorer");
if (fileExplorerPlugin) {
const originalRevealInFolder = fileExplorerPlugin.revealInFolder.bind(fileExplorerPlugin);
fileExplorerPlugin.revealInFolder = (file) => {
if (file instanceof import_obsidian48.TFile) {
const folder = getFolder(this, file);
if (folder instanceof import_obsidian48.TFolder) {
const folderNote = getFolderNote(this, folder.path);
if (!folderNote || folderNote.path !== file.path) {
return originalRevealInFolder.call(fileExplorerPlugin, file);
}
document.body.classList.remove("hide-folder-note");
originalRevealInFolder.call(fileExplorerPlugin, folder);
setTimeout(() => {
document.body.classList.add("hide-folder-note");
}, 100);
return;
}
}
return originalRevealInFolder.call(fileExplorerPlugin, file);
};
}
const leaf = this.app.workspace.getLeavesOfType("markdown").first();
const view = leaf == null ? void 0 : leaf.view;
if (!view) {
return;
}
const editMode = (_c = (_a = view.editMode) != null ? _a : view.sourceMode) != null ? _c : (_b = this.app.workspace.activeEditor) == null ? void 0 : _b.editMode;
const plugin = this;
if (!editMode) {
return;
}
const clipboardProto = editMode.clipboardManager.constructor.prototype;
const originalHandleDragOver = clipboardProto.handleDragOver;
const originalHandleDrop = clipboardProto.handleDrop;
clipboardProto.handleDragOver = function(evt, ...args) {
const dragManager = this.app.dragManager;
const draggable = dragManager == null ? void 0 : dragManager.draggable;
if ((draggable == null ? void 0 : draggable.file) instanceof import_obsidian48.TFolder) {
const folderNote = getFolderNote(plugin, draggable.file.path);
if (folderNote) {
dragManager.setAction(window.i18next.t("interface.drag-and-drop.insert-link-here"));
return;
}
}
return originalHandleDragOver.call(this, evt, ...args);
};
clipboardProto.handleDrop = function(evt, ...args) {
const dragManager = this.app.dragManager;
const draggable = dragManager == null ? void 0 : dragManager.draggable;
if ((draggable == null ? void 0 : draggable.file) instanceof import_obsidian48.TFolder) {
const folderNote = getFolderNote(plugin, draggable.file.path);
if (folderNote) {
draggable.file = folderNote;
draggable.type = "file";
}
}
return originalHandleDrop.call(this, evt, ...args);
};
}
handleFileExplorerClick(evt) {
const target = evt.target;
if (evt.shiftKey)
return;
if (import_obsidian48.Platform.isMobile && this.settings.disableOpenFolderNoteOnClick)
return;
const folderTitleEl = target.closest(".nav-folder-title");
if (!folderTitleEl)
return;
const onlyClickedOnFolderTitle = !!target.closest(".nav-folder-title-content");
if (!this.settings.stopWhitespaceCollapsing && !onlyClickedOnFolderTitle)
return;
if (target.closest(".collapse-icon"))
return;
const folderPath = folderTitleEl.getAttribute("data-path");
if (!folderPath)
return;
const excludedFolder = getExcludedFolder(this, folderPath, true);
if (excludedFolder == null ? void 0 : excludedFolder.disableFolderNote)
return;
const folderNote = getFolderNote(this, folderPath);
if (!folderNote && (evt.altKey || import_obsidian48.Keymap.isModEvent(evt) === "tab")) {
if (this.settings.altKey && evt.altKey || this.settings.ctrlKey && import_obsidian48.Keymap.isModEvent(evt) === "tab") {
createFolderNote(this, folderPath, true, void 0, true);
addCSSClassToFileExplorerEl(folderPath, "has-folder-note", false, this);
removeCSSClassFromFileExplorerEL(folderPath, "has-not-folder-note", false, this);
return;
}
}
if (!(folderNote instanceof import_obsidian48.TFile))
return;
if (this.settings.openWithCtrl && !evt.ctrlKey)
return;
if (this.settings.openWithAlt && !evt.altKey)
return;
if (!this.settings.enableCollapsing || evt.ctrlKey) {
evt.preventDefault();
evt.stopImmediatePropagation();
}
openFolderNote(this, folderNote, evt);
}
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_obsidian48.parseYaml)(source), ctx, el, this.settings.defaultOverview).open();
}, { capture: true });
}
});
observer.observe(el, {
childList: true,
subtree: true
});
try {
if (this.app.workspace.layoutReady) {
const folderOverview = new FolderOverview(this, ctx, source, el, this.settings.defaultOverview);
folderOverview.create(this, (0, import_obsidian48.parseYaml)(source), el, ctx);
} else {
this.app.workspace.onLayoutReady(() => {
const folderOverview = new FolderOverview(this, ctx, source, el, this.settings.defaultOverview);
folderOverview.create(this, (0, import_obsidian48.parseYaml)(source), el, ctx);
});
}
} catch (e) {
new import_obsidian48.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;
workspace.revealLeaf(leaf);
}
isEmptyFolderNoteFolder(folder) {
var _a;
const 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) {
addCSSClassToFileExplorerEl(folder.path, "fn-empty-folder", false, this);
}
if (folder.children.length === threshold) {
return true;
} else if (folder.children.length > threshold) {
if (attachmentsAreInRootFolder) {
return false;
} else if (this.settings.ignoreAttachmentFolder && this.app.vault.getAbstractFileByPath(`${folder.path}/${cleanAttachmentFolderPath}`)) {
const folderPath = `${folder.path}/${cleanAttachmentFolderPath}`;
const attachmentFolder = this.app.vault.getAbstractFileByPath(folderPath);
if (attachmentFolder instanceof import_obsidian48.TFolder && folder.children.length <= threshold + 1) {
if (!folder.collapsed) {
(_a = getFileExplorerElement(folder.path, this)) == null ? void 0 : _a.click();
}
}
return folder.children.length <= threshold + 1;
} else {
return false;
}
}
return true;
}
async changeFolderNameInExplorer(folder, newName, waitForCreate = false, count = 0) {
if (!newName)
newName = folder.name;
let fileExplorerItem = getFileExplorerElement(folder.path, this);
if (!fileExplorerItem) {
if (waitForCreate && count < 5) {
await new Promise((r) => setTimeout(r, 500));
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 = document.querySelectorAll("span.view-header-breadcrumb");
const files = this.app.vault.getAllLoadedFiles().filter((file) => file instanceof import_obsidian48.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_obsidian48.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();
document.body.classList.remove("folder-notes-plugin");
document.body.classList.remove("folder-note-underline");
document.body.classList.remove("hide-folder-note");
document.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);
}
}
};
/* nosourcemap */