fateforge/.obsidian/plugins/folder-notes/main.js
2024-01-18 11:52:41 +01:00

5613 lines
227 KiB
JavaScript

/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// node_modules/front-matter-plugin-api-provider/lib/contracts/Api.js
var require_Api = __commonJS({
"node_modules/front-matter-plugin-api-provider/lib/contracts/Api.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
}
});
// node_modules/front-matter-plugin-api-provider/lib/contracts/EventDispatcher.js
var require_EventDispatcher = __commonJS({
"node_modules/front-matter-plugin-api-provider/lib/contracts/EventDispatcher.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
}
});
// node_modules/front-matter-plugin-api-provider/lib/contracts/Resolver.js
var require_Resolver = __commonJS({
"node_modules/front-matter-plugin-api-provider/lib/contracts/Resolver.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
}
});
// node_modules/front-matter-plugin-api-provider/lib/index.js
var require_lib = __commonJS({
"node_modules/front-matter-plugin-api-provider/lib/index.js"(exports) {
"use strict";
var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
if (k2 === void 0)
k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() {
return m[k];
} };
}
Object.defineProperty(o, k2, desc);
} : function(o, m, k, k2) {
if (k2 === void 0)
k2 = k;
o[k2] = m[k];
});
var __exportStar = exports && exports.__exportStar || function(m, exports2) {
for (var p in m)
if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p))
__createBinding(exports2, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getApiSafe = exports.getDefer = exports.isPluginEnabled = exports.PluginNotEnabledError = exports.pluginId = void 0;
__exportStar(require_Api(), exports);
__exportStar(require_EventDispatcher(), exports);
__exportStar(require_Resolver(), exports);
exports.pluginId = "obsidian-front-matter-title-plugin";
var PluginNotEnabledError = class extends Error {
};
exports.PluginNotEnabledError = PluginNotEnabledError;
function isPluginEnabled(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 getDefer2(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 = getDefer2;
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 getDefer2(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_obsidian27 = require("obsidian");
// src/settings/SettingsTab.ts
var import_obsidian22 = 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 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 (templatesEnabled && templaterEnabled) {
if (/<%/.test(templateContent)) {
return await templaterPlugin.write_template_to_file(templateFile, file);
} else {
if (leaf instanceof import_obsidian2.WorkspaceLeaf) {
leaf.openFile(file).then(async () => {
return await templatesPlugin.instance.insertTemplate(templateFile, file);
});
}
}
}
if (templatesEnabled) {
if (leaf instanceof import_obsidian2.WorkspaceLeaf) {
leaf.openFile(file);
}
return await templatesPlugin.instance.insertTemplate(templateFile);
}
if (templaterEnabled) {
return await templaterPlugin.write_template_to_file(templateFile, file);
}
} 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 = this.app.plugins.plugins["templater-obsidian"].settings) == null ? void 0 : _a.empty_file_template);
const templateFolder = templatesEnabled ? templatesPlugin.instance.options.folder : templaterPlugin ? templaterPlugin.settings.template_folder : void 0;
return {
templatesPlugin,
templatesEnabled,
templaterPlugin: templaterPlugin == null ? void 0 : templaterPlugin.templater,
templaterEnabled,
templaterEmptyFileTemplate,
templateFolder
};
}
// src/functions/folderNoteFunctions.ts
var import_obsidian10 = 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() {
var _a;
const { contentEl } = this;
contentEl.createEl("h2", { text: "Delete folder note" });
const setting = new import_obsidian3.Setting(contentEl);
setting.infoEl.createEl("p", { text: `Are you sure you want to delete the folder note "${this.file.name}" ?` });
setting.infoEl.createEl("p", { text: "It will be moved to your system trash." });
(_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_obsidian3.Platform.isMobileApp) {
const confirmButton = buttonContainer.createEl("button", { text: "Delete and don't ask again" });
confirmButton.classList.add("mod-warning", "fn-confirmation-modal-button");
confirmButton.addEventListener("click", async () => {
this.plugin.settings.showDeleteConfirmation = false;
this.plugin.saveSettings();
this.close();
const folder = getFolder(this.plugin, this.file);
if (!folder)
return;
this.plugin.removeCSSClassFromEL(folder == null ? void 0 : folder.path, "has-folder-note");
this.app.vault.delete(this.file);
});
} else {
const checkbox = buttonContainer.createEl("input", { type: "checkbox" });
checkbox.addEventListener("change", (e) => {
const target = e.target;
if (target.checked) {
this.plugin.settings.showDeleteConfirmation = false;
} else {
this.plugin.settings.showDeleteConfirmation = true;
}
this.plugin.saveSettings();
});
const checkBoxText = buttonContainer.createEl("span", { text: "Don't ask again" });
checkBoxText.addEventListener("click", () => {
checkbox.click();
});
}
const button = buttonContainer.createEl("button", { text: "Delete" });
button.classList.add("mod-warning", "fn-confirmation-modal-button");
button.addEventListener("click", async () => {
this.close();
const folder = getFolder(this.plugin, this.file);
if (!folder)
return;
this.plugin.removeCSSClassFromEL(folder.path, "has-folder-note");
this.app.vault.delete(this.file);
});
button.focus();
const cancelButton = buttonContainer.createEl("button", { text: "Cancel" });
cancelButton.addEventListener("click", async () => {
this.close();
});
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
};
// src/excludedFolder.ts
var import_obsidian8 = require("obsidian");
// src/modals/ExcludeFolderSettings.ts
var import_obsidian4 = require("obsidian");
var ExcludedFolderSettings = class extends import_obsidian4.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_obsidian4.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();
}));
new import_obsidian4.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_obsidian4.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_obsidian4.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_obsidian4.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();
this.display();
}));
if (!this.excludedFolder.disableFolderNote) {
new import_obsidian4.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/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) {
this.inputEl = inputEl;
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) {
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() {
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, folder) {
super(inputEl);
this.inputEl = inputEl;
this.plugin = plugin;
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();
}
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)) {
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/modals/PatternSettings.ts
var import_obsidian7 = require("obsidian");
var PatternSettings = class extends import_obsidian7.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_obsidian7.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_obsidian7.Setting(contentEl).setName("Disable auto creation of folder notes in this folder").setDesc("Choose if a folder note should be created when a new folder is created that matches this pattern").addToggle((toggle) => toggle.setValue(this.pattern.disableAutoCreate).onChange(async (value) => {
this.pattern.disableAutoCreate = value;
await this.plugin.saveSettings();
}));
new import_obsidian7.Setting(contentEl).setName("Don't show folder in folder overview").setDesc("Choose if the folder should be shown in the folder overview").addToggle((toggle) => toggle.setValue(this.pattern.excludeFromFolderOverview).onChange(async (value) => {
this.pattern.excludeFromFolderOverview = value;
await this.plugin.saveSettings();
}));
new import_obsidian7.Setting(contentEl).setName("Disable open folder note").setDesc("Choose if the folder note should be opened when the folder is opened").addToggle((toggle) => toggle.setValue(this.pattern.disableFolderNote).onChange(async (value) => {
this.pattern.disableFolderNote = value;
await this.plugin.saveSettings();
this.display();
}));
if (!this.pattern.disableFolderNote) {
new import_obsidian7.Setting(contentEl).setName("Collapse folder when opening folder note").setDesc("Choose if the folder should be collapsed when the folder note is opened").addToggle((toggle) => toggle.setValue(this.pattern.enableCollapsing).onChange(async (value) => {
this.pattern.enableCollapsing = value;
await this.plugin.saveSettings();
}));
}
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
};
// src/excludedFolder.ts
var ExcludedFolder = class {
constructor(path, position, plugin) {
this.type = "folder";
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 = "";
}
};
var ExcludePattern = class {
constructor(pattern, position, plugin) {
this.type = "pattern";
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 = "";
}
};
function getExcludedFolder(plugin, path) {
const folderName = plugin.getFolderNameFromPathString(path);
const matchedPattern = getExcludedFolderByPattern(plugin, folderName);
if (matchedPattern) {
return matchedPattern;
}
const excludedFolder = getExcludedFolderByPath(plugin, path);
if ((excludedFolder == null ? void 0 : excludedFolder.path) === "") {
return;
}
return excludedFolder;
}
function getExcludedFolderByPattern(plugin, folderName) {
return plugin.settings.excludeFolders.filter((s) => s.type == "pattern").find((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 getExcludedFolderByPath(plugin, path) {
return plugin.settings.excludeFolders.find((excludedFolder) => {
if (excludedFolder.path === path) {
return true;
}
if (!excludedFolder.subFolders) {
return false;
}
return plugin.getFolderPathFromString(path).startsWith(excludedFolder.path);
});
}
function addExcludedFolder(plugin, excludedFolder) {
plugin.settings.excludeFolders.push(excludedFolder);
plugin.saveSettings();
}
function deleteExcludedFolder(plugin, excludedFolder) {
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.path !== excludedFolder.path || folder.type === "pattern");
plugin.saveSettings();
resyncArray(plugin);
}
function deletePattern(plugin, pattern) {
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.string !== pattern.string || folder.type === "folder");
plugin.saveSettings();
resyncArray(plugin);
}
function updateExcludedFolder(plugin, excludedFolder, newExcludeFolder) {
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.path !== excludedFolder.path);
addExcludedFolder(plugin, newExcludeFolder);
}
function updatePattern(plugin, pattern, newPattern) {
plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.string !== pattern.string);
addExcludedFolder(plugin, newPattern);
}
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 addExcludePatternListItem(settings, containerEl, pattern) {
const plugin = settings.plugin;
const setting = new import_obsidian8.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.excludeFolders.find((folder) => folder.string === value)) {
return;
}
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();
});
});
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();
});
});
}
function addExcludeFolderListItem(settings, containerEl, excludedFolder) {
const plugin = settings.plugin;
const setting = new import_obsidian8.Setting(containerEl);
setting.setClass("fn-exclude-folder-list");
setting.addSearch((cb) => {
new FolderSuggest(cb.inputEl, plugin);
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, 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();
});
});
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_obsidian9 = require("obsidian");
var AskForExtensionModal = class extends import_obsidian9.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;
}
getItems() {
return this.plugin.settings.supportedFileTypes.filter((item) => item.toLowerCase() !== ".ask");
}
getItemText(item) {
return item;
}
onChooseItem(item, evt) {
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, useModal, existingNote) {
const leaf = plugin.app.workspace.getLeaf(false);
const folderName = plugin.getFolderNameFromPathString(folderPath);
const fileName = plugin.settings.folderNoteName.replace("{{folder_name}}", folderName);
let folderNoteType = extension != null ? extension : plugin.settings.folderNoteType;
if (folderNoteType === ".excalidraw") {
folderNoteType = ".md";
extension = ".excalidraw";
} else if (folderNoteType === ".ask") {
return new AskForExtensionModal(plugin, folderPath, openFile, folderNoteType, useModal, existingNote).open();
}
let path = "";
if (plugin.settings.storageLocation === "parentFolder") {
const parentFolderPath = plugin.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}`;
}
let file;
if (!existingNote) {
let content = "";
if (extension !== ".md") {
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_obsidian10.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) => {
file = await plugin.app.vault.createBinary(path, data);
if (openFile) {
await leaf.openFile(file);
}
});
}
}
} else if (plugin.settings.folderNoteType === ".excalidraw" || extension === ".excalidraw") {
content = defaultExcalidrawTemplate;
} else if (plugin.settings.folderNoteType === ".canvas") {
content = "{}";
}
}
file = await plugin.app.vault.create(path, content);
} else {
file = existingNote;
plugin.app.fileManager.renameFile(existingNote, path);
}
if (openFile) {
await leaf.openFile(file);
if (plugin.settings.folderNoteType === ".excalidraw" || extension === ".excalidraw") {
openExcalidrawView(leaf);
}
}
if (file && !existingNote && plugin.settings.folderNoteType !== ".excalidraw" && (extension == null ? void 0 : extension.split(".").pop()) == plugin.settings.templatePath.split(".").pop()) {
applyTemplate(plugin, file, leaf, plugin.settings.templatePath);
}
const folder = plugin.app.vault.getAbstractFileByPath(folderPath);
if (!(folder instanceof import_obsidian10.TFolder))
return;
plugin.addCSSClassToTitleEL(path, "is-folder-note", true);
plugin.addCSSClassToTitleEL(folder.path, "has-folder-note");
}
async function turnIntoFolderNote(plugin, file, folder, folderNote, skipConfirmation) {
var _a;
const extension = file.extension;
if (folderNote) {
if (plugin.settings.showRenameConfirmation && !skipConfirmation) {
return new ExistingFolderNoteModal(plugin.app, plugin, file, folder, folderNote).open();
}
plugin.removeCSSClassFromEL(folderNote.path, "is-folder-note");
let excludedFolder = getExcludedFolder(plugin, folder.path);
let excludedFolderExisted = true;
let disabledSync = false;
if (!excludedFolder) {
excludedFolderExisted = false;
excludedFolder = new ExcludedFolder(folder.path, plugin.settings.excludeFolders.length, plugin);
addExcludedFolder(plugin, excludedFolder);
} else if (!excludedFolder.disableSync) {
disabledSync = false;
excludedFolder.disableSync = true;
updateExcludedFolder(plugin, excludedFolder, excludedFolder);
}
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}`;
}
}
await plugin.app.fileManager.renameFile(file, path);
plugin.addCSSClassToTitleEL(path, "is-folder-note", true);
plugin.addCSSClassToTitleEL(folder.path, "has-folder-note");
}
async function openFolderNote(plugin, file, evt) {
var _a;
const path = file.path;
if (((_a = plugin.app.workspace.getActiveFile()) == null ? void 0 : _a.path) === path && !(import_obsidian10.Keymap.isModEvent(evt) == "tab")) {
return;
}
const leaf = plugin.app.workspace.getLeaf(import_obsidian10.Keymap.isModEvent(evt) || plugin.settings.openInNewTab);
if (file instanceof import_obsidian10.TFile) {
await leaf.openFile(file);
}
}
async function deleteFolderNote(plugin, file) {
if (plugin.settings.showDeleteConfirmation) {
return new DeleteConfirmationModal(plugin.app, plugin, file).open();
}
const folder = getFolder(plugin, file);
if (!folder)
return;
plugin.removeCSSClassFromEL(folder.path, "has-folder-note");
await plugin.app.vault.delete(file);
}
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) {
if (!folderPath)
return null;
const folder = {
path: folderPath,
name: plugin.getFolderNameFromPathString(folderPath)
};
let fileName = plugin.settings.folderNoteName.replace("{{folder_name}}", folder.name);
if (file) {
fileName = plugin.settings.folderNoteName.replace("{{folder_name}}", file.basename);
}
if ((plugin.settings.storageLocation === "parentFolder" || storageLocation === "parentFolder") && storageLocation !== "insideFolder") {
folder.path = plugin.getFolderPathFromString(folderPath);
}
let path = `${folder.path}/${fileName}`;
if (folder.path.trim() === "") {
folder.path = fileName;
path = `${fileName}`;
}
let folderNoteType = plugin.settings.folderNoteType;
if (folderNoteType === ".excalidraw") {
folderNoteType = ".md";
}
let folderNote = plugin.app.vault.getAbstractFileByPath(path + folderNoteType);
if (folderNote instanceof import_obsidian10.TFile) {
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_obsidian10.TFile) {
return folderNote;
}
}
}
}
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 = plugin.getFolderPathFromString(file.path);
let folder = null;
if ((plugin.settings.storageLocation === "parentFolder" || storageLocation === "parentFolder") && storageLocation !== "insideFolder") {
if (folderPath.trim() === "") {
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 = plugin.getFolderPathFromString(filePath);
if (plugin.settings.storageLocation === "parentFolder") {
if (folderPath.trim() === "") {
folderPath = folderName;
} else {
folderPath = `${folderPath}/${folderName}`;
}
} else {
folderPath = plugin.getFolderPathFromString(filePath);
}
const folder = plugin.app.vault.getAbstractFileByPath(folderPath);
if (!folder) {
return null;
}
return folder;
}
// src/settings/GeneralSettings.ts
var import_obsidian15 = require("obsidian");
// src/modals/AddSupportedFileType.ts
var import_obsidian11 = require("obsidian");
var AddSupportedFileModal = class extends import_obsidian11.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_obsidian11.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_obsidian11.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_obsidian12 = 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();
}
}
const dispatcher = (_a = this.api) == null ? void 0 : _a.getEventDispatcher();
if (dispatcher) {
this.dispatcher = dispatcher;
}
const event = {
name: "manager:update",
cb: (data) => {
this.handleRename(data, true);
}
};
const ref = dispatcher == null ? void 0 : dispatcher.addListener(event);
if (ref) {
this.eventRef = ref;
}
this.plugin.app.vault.getFiles().forEach((file) => {
this.handleRename({ id: "", result: false, path: file.path }, false);
});
this.plugin.updateBreadcrumbs();
})();
}
deleteEvent() {
if (this.eventRef) {
this.dispatcher.removeListener(this.eventRef);
}
}
async handleRename(data, isEvent) {
var _a, _b, _c;
if (data.data)
data = data.data;
const file = this.app.vault.getAbstractFileByPath(data.path);
if (!(file instanceof import_obsidian12.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_obsidian12.TFolder)) {
return;
}
const folderNote = getFolderNote(this.plugin, folder.path);
if (!folderNote) {
return;
}
if (folderNote !== file) {
return;
}
if (isEvent) {
this.plugin.changeName(folder, newName, true);
} else {
this.plugin.changeName(folder, newName, false);
}
if (newName) {
folder.newName = newName;
this.modifiedFolders.set(folder.path, folder);
} else {
folder.newName = null;
this.modifiedFolders.delete(folder.path);
}
}
};
// src/modals/ConfirmCreation.ts
var import_obsidian13 = require("obsidian");
var ConfirmationModal = class extends import_obsidian13.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_obsidian13.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_obsidian13.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_obsidian13.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_obsidian13.Notice("Please choose a file extension");
}
this.close();
const folders = this.app.vault.getAllLoadedFiles().filter((file) => file.parent instanceof import_obsidian13.TFolder);
for (const folder of folders) {
if (folder instanceof import_obsidian13.TFolder) {
const excludedFolder = getExcludedFolder(this.plugin, folder.path);
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_obsidian14 = require("obsidian");
var TemplateSuggest = class extends TextInputSuggest {
constructor(inputEl, plugin) {
super(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.plugin.app);
if ((!templateFolder || (templateFolder == null ? void 0 : templateFolder.trim()) === "") && !templaterPlugin) {
this.plugin.settings.templatePath = "";
this.plugin.saveSettings();
return [];
}
let folder;
if (templaterPlugin) {
folder = this.plugin.app.vault.getAbstractFileByPath((_b = (_a = templaterPlugin.plugin) == null ? void 0 : _a.settings) == null ? void 0 : _b.templates_folder);
} else {
folder = this.plugin.app.vault.getAbstractFileByPath(templateFolder);
}
const files = [];
const lower_input_str = input_str.toLowerCase();
import_obsidian14.Vault.recurseChildren(folder, (file) => {
if (file instanceof import_obsidian14.TFile && file.path.toLowerCase().contains(lower_input_str)) {
files.push(file);
}
});
return files;
}
renderSuggestion(file, el) {
el.setText(file.name.replace(".md", ""));
}
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/GeneralSettings.ts
async function renderGeneral(settingsTab) {
settingsTab.settingsPage.createEl("h1", { text: "General settings" });
const containerEl = settingsTab.settingsPage;
const nameSetting = new import_obsidian15.Setting(containerEl).setName("Folder note name").setDesc("{{folder_name}} will be replaced with the name of the folder").addText((text) => text.setValue(settingsTab.plugin.settings.newFolderNoteName).onChange(async (value) => {
if (value.trim() === "") {
return;
}
settingsTab.plugin.settings.newFolderNoteName = value;
await settingsTab.plugin.saveSettings();
})).addButton((button) => button.setButtonText("Rename existing folder notes").setCta().onClick(async () => {
settingsTab.updateFolderNotes(settingsTab.plugin.settings.newFolderNoteName);
}));
nameSetting.infoEl.appendText("Make sure to back up your vault before renaming all folder notes and restart Obsidian after renaming them");
nameSetting.infoEl.style.color = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
new import_obsidian15.Setting(containerEl).setName("Default folder note type for new folder notes").setDesc("Choose the default file type for new folder notes. (canvas, markdown, ...)").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();
}
const defaultType = settingsTab.plugin.settings.folderNoteType.startsWith(".") ? settingsTab.plugin.settings.folderNoteType : "." + settingsTab.plugin.settings.folderNoteType;
dropdown.setValue(defaultType).onChange(async (value) => {
settingsTab.plugin.settings.folderNoteType = value;
settingsTab.plugin.saveSettings();
settingsTab.display();
});
});
const setting0 = new import_obsidian15.Setting(containerEl);
setting0.setName("Supported file types for folder notes");
const desc0 = document.createDocumentFragment();
desc0.append("Choose the file types that should be supported for folder notes. (e.g. if you click on a folder name it searches for all file extensions that are supported)", desc0.createEl("br"), "Adding more file types may cause performance issues becareful when adding more file types and don't add too many.");
setting0.setDesc(desc0);
const list = setting0.createList((list2) => {
list2.addSettings(settingsTab);
list2.setValues(settingsTab.plugin.settings.supportedFileTypes || ["md", "canvas"]);
list2.addResetButton();
});
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 setting = new import_obsidian15.Setting(containerEl);
const desc = document.createDocumentFragment();
desc.append("Restart after changing the template path");
setting.setName("Template path");
setting.setDesc(desc).descEl.style.color = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
setting.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;
}
});
});
const storageLocation = new import_obsidian15.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();
settingsTab.plugin.loadFileClasses();
}));
storageLocation.infoEl.appendText("Requires a restart to take effect");
storageLocation.infoEl.style.color = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
const switchLocation = new import_obsidian15.Setting(containerEl).setName("Switch to new storage location").setDesc("Move all folder notes to the new storage location").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";
}
settingsTab.switchStorageLocation(oldStorageLocation);
}));
switchLocation.infoEl.appendText("Requires a restart to take effect");
switchLocation.infoEl.style.color = settingsTab.app.vault.getConfig("accentColor") || "#7d5bed";
if (settingsTab.plugin.settings.storageLocation === "parentFolder") {
new import_obsidian15.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_obsidian15.Setting(containerEl).setName("Move folder notes when moving the folder").setDesc("Move the folder note when moving the folder").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.syncMove).onChange(async (value) => {
settingsTab.plugin.settings.syncMove = value;
await settingsTab.plugin.saveSettings();
}));
}
if (import_obsidian15.Platform.isDesktopApp) {
new import_obsidian15.Setting(containerEl).setName("Key for creating folder note").setDesc("The key combination to create a folder note").addDropdown((dropdown) => {
if (!import_obsidian15.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_obsidian15.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_obsidian15.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();
});
});
}
new import_obsidian15.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();
}));
if (import_obsidian15.Platform.isDesktop) {
const setting3 = new import_obsidian15.Setting(containerEl);
setting3.setName("Open folder note in a new tab by default");
setting3.setDesc("Always open folder notes in a new tab (except when you try to open the same note) instead of having to use ctrl/cmd + click to open in a new 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";
}
new import_obsidian15.Setting(containerEl).setName("Automatically create folder notes").setDesc("Automatically create a folder note when a new folder is created").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.autoCreate).onChange(async (value) => {
settingsTab.plugin.settings.autoCreate = value;
await settingsTab.plugin.saveSettings();
settingsTab.display();
}));
new import_obsidian15.Setting(containerEl).setName("Enable front matter title plugin integration").setDesc("Automatically rename a folder name when the folder note is renamed").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.updateBreadcrumbs(true);
}
settingsTab.plugin.app.vault.getFiles().forEach((file) => {
var _a2;
(_a2 = settingsTab.plugin.fmtpHandler) == null ? void 0 : _a2.handleRename({ id: "", result: false, path: file.path }, false);
});
(_a = settingsTab.plugin.fmtpHandler) == null ? void 0 : _a.deleteEvent();
settingsTab.plugin.fmtpHandler = null;
}
settingsTab.display();
}));
new import_obsidian15.Setting(containerEl).setName("Create folder note for every folder").setDesc("Create a folder note 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();
});
});
}
// src/settings/FileExplorerSettings.ts
var import_obsidian16 = require("obsidian");
async function renderFileExplorer(settingsTab) {
const containerEl = settingsTab.settingsPage;
settingsTab.settingsPage.createEl("h1", { text: "File explorer settings" });
new import_obsidian16.Setting(containerEl).setName("Hide folder note").setDesc("Hide the folder note 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_obsidian16.Setting(containerEl).setName("Don't open folder notes by clicking on the name (on mobile)").setDesc("Folder notes don't open when clicking on the name of the folder (on mobile)").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_obsidian16.Setting(containerEl).setName("Only open folder notes through the name").setDesc("Only open folder notes in the file explorer by clicking on the folder name").addToggle((toggle) => toggle.setValue(settingsTab.plugin.settings.allowWhitespaceCollapsing).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.allowWhitespaceCollapsing = value;
await settingsTab.plugin.saveSettings();
}));
const disableSetting = new import_obsidian16.Setting(containerEl);
disableSetting.setName("Disable folder collapsing");
disableSetting.setDesc("Disable the ability to collapse folders by clicking exactly on the folder name");
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_obsidian16.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_obsidian16.Setting(containerEl).setName("Change folder name in the file explorer").setDesc("Automatically rename a folder name in the file explorer when the folder note is renamed").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.handleRename({ id: "", result: false, path: file.path }, false);
});
}));
}
settingsTab.settingsPage.createEl("h3", { text: "Style settings" });
new import_obsidian16.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");
}
}));
new import_obsidian16.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_obsidian16.Setting(containerEl).setName("Bold the name of folder notes").setDesc("Make the folder name bold in the file explorer").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_obsidian16.Setting(containerEl).setName("Cursive the name of folder notes").setDesc("Make the folder name cursive in the file explorer").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_obsidian17 = require("obsidian");
async function renderPath(settingsTab) {
settingsTab.settingsPage.createEl("h1", { text: "Path settings" });
const containerEl = settingsTab.settingsPage;
new import_obsidian17.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_obsidian17.Setting(containerEl).setName("Change folder name in the path").setDesc("Automatically rename a folder name in the path above a note when the folder note is renamed").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.updateBreadcrumbs();
} else {
settingsTab.plugin.updateBreadcrumbs(true);
}
}));
settingsTab.settingsPage.createEl("h3", { text: "Style settings" });
if (settingsTab.plugin.settings.openFolderNoteOnClickInPath) {
new import_obsidian17.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_obsidian17.Setting(containerEl).setName("Bold folders in the path").setDesc("Make the folder name bold in the path above a 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_obsidian17.Setting(containerEl).setName("Cursive the name of folder notes in the path").setDesc("Make the folder name cursive in the path above a 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/settings/FolderOverviewSettings.ts
var import_obsidian20 = require("obsidian");
// src/folderOverview/ModalSettings.ts
var import_obsidian19 = require("obsidian");
// src/folderOverview/FolderOverview.ts
var import_obsidian18 = require("obsidian");
var FolderOverview = class {
constructor(plugin, ctx, source, el) {
this.pathBlacklist = [];
this.folders = [];
let yaml = (0, import_obsidian18.parseYaml)(source);
if (!yaml) {
yaml = {};
}
const includeTypes = (yaml == null ? void 0 : yaml.includeTypes) || plugin.settings.defaultOverview.includeTypes || ["folder", "markdown"];
this.plugin = plugin;
this.ctx = ctx;
this.source = source;
this.el = el;
this.sourceFilePath = this.ctx.sourcePath;
this.yaml = {
id: (yaml == null ? void 0 : yaml.id) || crypto.randomUUID(),
folderPath: (yaml == null ? void 0 : yaml.folderPath) === void 0 || (yaml == null ? void 0 : yaml.folderPath) === null ? plugin.getFolderPathFromString(ctx.sourcePath) : yaml == null ? void 0 : yaml.folderPath,
title: (yaml == null ? void 0 : yaml.title) || plugin.settings.defaultOverview.title,
showTitle: (yaml == null ? void 0 : yaml.showTitle) === void 0 || (yaml == null ? void 0 : yaml.showTitle) === null ? plugin.settings.defaultOverview.showTitle : yaml == null ? void 0 : yaml.showTitle,
depth: (yaml == null ? void 0 : yaml.depth) || plugin.settings.defaultOverview.depth,
style: (yaml == null ? void 0 : yaml.style) || "list",
includeTypes: includeTypes.map((type) => type.toLowerCase()),
disableFileTag: (yaml == null ? void 0 : yaml.disableFileTag) === void 0 || (yaml == null ? void 0 : yaml.disableFileTag) === null ? plugin.settings.defaultOverview.disableFileTag : yaml == null ? void 0 : yaml.disableFileTag,
sortBy: (yaml == null ? void 0 : yaml.sortBy) || plugin.settings.defaultOverview.sortBy,
sortByAsc: (yaml == null ? void 0 : yaml.sortByAsc) === void 0 || (yaml == null ? void 0 : yaml.sortByAsc) === null ? plugin.settings.defaultOverview.sortByAsc : yaml == null ? void 0 : yaml.sortByAsc,
showEmptyFolders: (yaml == null ? void 0 : yaml.showEmptyFolders) === void 0 || (yaml == null ? void 0 : yaml.showEmptyFolders) === null ? plugin.settings.defaultOverview.showEmptyFolders : yaml == null ? void 0 : yaml.showEmptyFolders,
onlyIncludeSubfolders: (yaml == null ? void 0 : yaml.onlyIncludeSubfolders) === void 0 || (yaml == null ? void 0 : yaml.onlyIncludeSubfolders) === null ? plugin.settings.defaultOverview.onlyIncludeSubfolders : yaml == null ? void 0 : yaml.onlyIncludeSubfolders,
storeFolderCondition: (yaml == null ? void 0 : yaml.storeFolderCondition) === void 0 || (yaml == null ? void 0 : yaml.storeFolderCondition) === null ? plugin.settings.defaultOverview.storeFolderCondition : yaml == null ? void 0 : yaml.storeFolderCondition,
showFolderNotes: (yaml == null ? void 0 : yaml.showFolderNotes) === void 0 || (yaml == null ? void 0 : yaml.showFolderNotes) === null ? plugin.settings.defaultOverview.showFolderNotes : yaml == null ? void 0 : yaml.showFolderNotes,
disableCollapseIcon: (yaml == null ? void 0 : yaml.disableCollapseIcon) === void 0 || (yaml == null ? void 0 : yaml.disableCollapseIcon) === null ? plugin.settings.defaultOverview.disableCollapseIcon : yaml == null ? void 0 : yaml.disableCollapseIcon
};
}
create(plugin, source, el, ctx) {
var _a;
el.empty();
(_a = el.parentElement) == null ? void 0 : _a.classList.add("folder-overview-container");
const root = el.createEl("div", { cls: "folder-overview" });
const titleEl = root.createEl("h1", { cls: "folder-overview-title" });
const ul = root.createEl("ul", { cls: "folder-overview-list" });
if (this.yaml.includeTypes.length === 0) {
return this.addEditButton(root);
}
let files = [];
const sourceFile = plugin.app.vault.getAbstractFileByPath(ctx.sourcePath);
if (!sourceFile)
return;
let sourceFolderPath = this.yaml.folderPath || plugin.getFolderPathFromString(ctx.sourcePath);
let sourceFolder;
if (sourceFolderPath !== "/") {
if (this.yaml.folderPath === "") {
sourceFolder = plugin.app.vault.getAbstractFileByPath(plugin.getFolderPathFromString(ctx.sourcePath));
} else {
sourceFolder = plugin.app.vault.getAbstractFileByPath(this.yaml.folderPath);
}
}
if (this.yaml.showTitle) {
if (sourceFolder && sourceFolderPath !== "/") {
titleEl.innerText = this.yaml.title.replace("{{folderName}}", sourceFolder.name);
} else if (sourceFolderPath == "/") {
titleEl.innerText = this.yaml.title.replace("{{folderName}}", "Vault");
} else {
titleEl.innerText = this.yaml.title.replace("{{folderName}}", "");
}
}
if (!sourceFolder && (sourceFolderPath !== "/" && sourceFolderPath !== "")) {
return new import_obsidian18.Notice("Folder overview: Couldn't find the folder");
}
if (!sourceFolder && sourceFolderPath == "") {
sourceFolderPath = "/";
}
if (sourceFolderPath == "/") {
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) {
files = sourceFolder.children;
}
files = this.filterFiles(files, plugin, sourceFolderPath, this.yaml.depth, this.pathBlacklist);
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_obsidian18.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_obsidian18.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") {
const folders = this.sortFiles(files.filter((f) => f instanceof import_obsidian18.TFolder));
files = this.sortFiles(files.filter((f) => f instanceof import_obsidian18.TFile));
folders.forEach((file) => {
if (file instanceof import_obsidian18.TFolder) {
const folderItem = this.addFolderList(plugin, ul, this.pathBlacklist, file);
if (!folderItem) {
return;
}
this.goThroughFolders(plugin, folderItem, file, this.yaml.depth, sourceFolderPath, ctx, this.yaml, this.pathBlacklist, this.yaml.includeTypes, this.yaml.disableFileTag);
}
});
files.forEach((file) => {
if (file instanceof import_obsidian18.TFile) {
this.addFileList(plugin, ul, this.pathBlacklist, file, this.yaml.includeTypes, this.yaml.disableFileTag);
}
});
} else if (this.yaml.style === "explorer") {
if (this.plugin.app.workspace.layoutReady) {
this.cloneFileExplorerView(plugin, ctx, root, this.yaml, this.pathBlacklist);
} else {
this.plugin.app.workspace.onLayoutReady(() => {
this.cloneFileExplorerView(plugin, ctx, root, this.yaml, this.pathBlacklist);
});
}
}
const overviewListEl = el.childNodes[0].childNodes[1];
if (overviewListEl && overviewListEl.childNodes.length === 0) {
if (this.yaml.style === "explorer") {
const overview = el.childNodes[0];
if (!overview.childNodes[2]) {
if (this.plugin.app.workspace.layoutReady) {
return this.addEditButton(root);
}
}
} else {
if (this.plugin.app.workspace.layoutReady) {
return this.addEditButton(root);
}
}
}
if (this.yaml.includeTypes.length > 1 && (!this.yaml.showEmptyFolders || this.yaml.onlyIncludeSubfolders) && this.yaml.style === "list") {
this.removeEmptyFolders(ul, 1, this.yaml);
}
}
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).open();
}, { capture: true });
}
cloneFileExplorerView(plugin, ctx, root, yaml, pathBlacklist) {
const folder = plugin.getEL(this.yaml.folderPath);
let folderElement = folder == null ? void 0 : folder.parentElement;
let tFolder = plugin.app.vault.getAbstractFileByPath(this.yaml.folderPath);
if (!tFolder && yaml.folderPath.trim() == "") {
tFolder = plugin.app.vault.getAbstractFileByPath(plugin.getFolderPathFromString(ctx.sourcePath));
}
if (!folderElement && yaml.folderPath.trim() !== "")
return;
folderElement = document.querySelector("div.nav-files-container");
if (!folderElement)
return;
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_obsidian18.TFolder))
return;
if (this.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")) {
const folderNote = getFolderNote(plugin, folder2.path);
if (folderNote) {
this.pathBlacklist.push(folderNote.path);
}
}
});
if (tFolder instanceof import_obsidian18.TFolder) {
this.addFiles(tFolder.children, root);
} else if (yaml.folderPath.trim() === "/") {
const rootFiles = [];
plugin.app.vault.getAllLoadedFiles().filter((f) => f instanceof import_obsidian18.TFolder).forEach((file) => {
if (!file.path.includes("/")) {
rootFiles.push(file);
}
});
this.addFiles(rootFiles, root);
}
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, pathBlacklist, this.source, folder2);
};
}
});
}
async addFiles(files, childrenElement) {
const folders = this.sortFiles(files.filter((file) => file instanceof import_obsidian18.TFolder));
const filesWithoutFolders = this.sortFiles(files.filter((file) => !(file instanceof import_obsidian18.TFolder)));
for (const child of folders) {
if (child instanceof import_obsidian18.TFolder) {
const folderNote = getFolderNote(this.plugin, child.path);
if (folderNote) {
this.pathBlacklist.push(folderNote.path);
}
const excludedFolder = getExcludedFolder(this.plugin, child.path);
if (excludedFolder == null ? void 0 : excludedFolder.excludeFromFolderOverview) {
continue;
}
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon right-triangle"><path d="M3 8L12 17L21 8"></path></svg>';
const folderElement = childrenElement.createDiv({
cls: "tree-item nav-folder"
});
const folderTitle = folderElement.createDiv({
cls: "tree-item-self is-clickable nav-folder-title",
attr: {
"data-path": child.path,
"draggable": "true"
}
});
if (!child.collapsed) {
folderTitle.classList.remove("is-collapsed");
const childrenElement2 = folderElement == null ? void 0 : folderElement.createDiv({ cls: "tree-item-children nav-folder-children" });
this.addFiles(child.children, childrenElement2);
} else {
folderTitle.classList.add("is-collapsed");
}
if (folderNote) {
folderTitle.classList.add("has-folder-note");
}
if (folderNote && child.children.length === 1 && this.yaml.disableCollapseIcon) {
folderTitle.classList.add("fn-has-no-files");
}
const collapseIcon = folderTitle.createDiv({
cls: "tree-item-icon collapse-icon nav-folder-collapse-indicator fn-folder-overview-collapse-icon"
});
if (child.collapsed) {
collapseIcon.classList.add("is-collapsed");
}
collapseIcon.innerHTML = svg;
collapseIcon.onclick = () => {
this.handleCollapseClick(collapseIcon, this.plugin, this.yaml, this.pathBlacklist, this.source, child);
};
folderTitle.createDiv({
cls: "tree-item-inner nav-folder-title-content",
text: child.name
});
}
}
for (const child of filesWithoutFolders) {
if (child instanceof import_obsidian18.TFile) {
if (this.pathBlacklist.includes(child.path) && !this.yaml.showFolderNotes) {
continue;
}
const extension = child.extension.toLowerCase() == "md" ? "markdown" : child.extension.toLowerCase();
const includeTypes = this.yaml.includeTypes;
if (includeTypes.length > 0 && !includeTypes.includes("all")) {
if ((extension === "md" || extension === "markdown") && !includeTypes.includes("markdown"))
continue;
if (extension === "canvas" && !includeTypes.includes("canvas"))
continue;
if (extension === "pdf" && !includeTypes.includes("pdf"))
continue;
const imageTypes = ["jpg", "jpeg", "png", "gif", "svg", "webp"];
if (imageTypes.includes(extension) && !includeTypes.includes("image"))
continue;
const videoTypes = ["mp4", "webm", "ogv", "mov", "mkv"];
if (videoTypes.includes(extension) && !includeTypes.includes("video"))
continue;
const audioTypes = ["mp3", "wav", "m4a", "3gp", "flac", "ogg", "oga", "opus"];
if (audioTypes.includes(extension) && includeTypes.includes("audio"))
continue;
const allTypes = ["markdown", "md", "canvas", "pdf", ...imageTypes, ...videoTypes, ...audioTypes];
if (!allTypes.includes(extension) && !includeTypes.includes("other"))
continue;
}
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,
"draggable": "true"
}
});
fileTitle.onclick = () => {
this.plugin.app.workspace.openLinkText(child.path, child.path, true);
};
fileTitle.createDiv({
cls: "tree-item-inner nav-file-title-content",
text: child.basename
});
if (child.extension !== "md") {
fileTitle.createDiv({
cls: "nav-file-tag",
text: child.extension
});
}
}
}
}
handleCollapseClick(el, plugin, yaml, pathBlacklist, sourcePath, folder) {
var _a, _b, _c, _d;
el.classList.toggle("is-collapsed");
if (el.classList.contains("is-collapsed")) {
if (!(folder instanceof import_obsidian18.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_obsidian18.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" });
let files = this.sortFiles(folder.children);
files = this.filterFiles(files, plugin, folder.path, this.yaml.depth || 1, pathBlacklist);
this.addFiles(files, childrenElement);
}
}
goThroughFolders(plugin, list, folder, depth, sourceFolderPath, ctx, yaml, pathBlacklist, includeTypes, disableFileTag) {
if (sourceFolderPath === "") {
depth--;
}
let files = this.filterFiles(folder.children, plugin, sourceFolderPath, depth, pathBlacklist);
files = this.sortFiles(files.filter((file) => !(file instanceof import_obsidian18.TFolder)));
if (this.yaml.sortByAsc) {
files = files.reverse();
}
const folders = this.sortFiles(files.filter((file) => file instanceof import_obsidian18.TFolder));
const ul = list.createEl("ul", { cls: "folder-overview-list" });
folders.forEach((file) => {
if (file instanceof import_obsidian18.TFolder) {
const folderItem = this.addFolderList(plugin, ul, pathBlacklist, file);
if (!folderItem)
return;
this.goThroughFolders(plugin, folderItem, file, depth, sourceFolderPath, ctx, yaml, pathBlacklist, includeTypes, disableFileTag);
}
});
files.forEach((file) => {
if (file instanceof import_obsidian18.TFile) {
this.addFileList(plugin, ul, pathBlacklist, file, includeTypes, disableFileTag);
}
});
}
filterFiles(files, plugin, sourceFolderPath, depth, pathBlacklist) {
return files.filter((file) => {
if (pathBlacklist.includes(file.path) && !this.yaml.showFolderNotes) {
return false;
}
const folderPath = plugin.getFolderPathFromString(file.path);
if (!folderPath.startsWith(sourceFolderPath) && sourceFolderPath !== "/") {
return false;
}
if (file.path === this.sourceFilePath) {
return false;
}
const excludedFolder = getExcludedFolder(plugin, file.path);
if (excludedFolder == null ? void 0 : excludedFolder.excludeFromFolderOverview) {
return false;
}
if (file.path.split("/").length - sourceFolderPath.split("/").length - 1 < depth) {
return true;
}
});
}
sortFiles(files) {
const yaml = this.yaml;
if (!(yaml == null ? void 0 : yaml.sortBy)) {
yaml.sortBy = this.plugin.settings.defaultOverview.sortBy || "name";
yaml.sortByAsc = this.plugin.settings.defaultOverview.sortByAsc || false;
}
files.sort((a, b) => {
if (a instanceof import_obsidian18.TFolder && !(b instanceof import_obsidian18.TFolder)) {
return -1;
}
if (!(a instanceof import_obsidian18.TFolder) && b instanceof import_obsidian18.TFolder) {
return 1;
}
if (a instanceof import_obsidian18.TFolder && b instanceof import_obsidian18.TFolder) {
if (a.name.localeCompare(b.name) < 0) {
return -1;
} else if (a.name.localeCompare(b.name) > 0) {
return 1;
}
}
if (!(a instanceof import_obsidian18.TFile) || !(b instanceof import_obsidian18.TFile)) {
return -1;
}
if (yaml.sortBy === "created") {
if (a.stat.ctime > b.stat.ctime) {
return -1;
} else if (a.stat.ctime < b.stat.ctime) {
return 1;
}
} else if (yaml.sortBy === "modified") {
if (a.stat.mtime > b.stat.mtime) {
return -1;
} else if (a.stat.mtime < b.stat.mtime) {
return 1;
}
} else if (yaml.sortBy === "name") {
if (a.basename.localeCompare(b.basename) < 0) {
return -1;
} else if (a.basename.localeCompare(b.basename) > 0) {
return 1;
}
}
return 0;
});
if (!(yaml == null ? void 0 : yaml.sortByAsc)) {
files = files.reverse();
}
return files;
}
removeEmptyFolders(ul, depth, yaml) {
const childrensToRemove = [];
ul.childNodes.forEach((el) => {
var _a, _b;
if (((_a = el.childNodes[0]) == null ? void 0 : _a.classList) && ((_b = el.childNodes[0]) == null ? void 0 : _b.classList.contains("internal-link"))) {
return;
}
const childrens = el.querySelector("ul");
if (!childrens || childrens === null) {
return;
}
if (childrens && !(childrens == null ? void 0 : childrens.hasChildNodes()) && !(el instanceof HTMLUListElement)) {
childrensToRemove.push(el);
} else if (el instanceof HTMLUListElement || el instanceof HTMLLIElement) {
this.removeEmptyFolders(el, depth + 1, yaml);
}
});
childrensToRemove.forEach((el) => {
if (yaml.onlyIncludeSubfolders && depth === 1) {
return;
}
el.remove();
});
}
addFolderList(plugin, list, pathBlacklist, folder) {
const folderItem = list.createEl("li", { cls: "folder-overview-list folder-list" });
const folderNote = getFolderNote(plugin, folder.path);
if (folderNote instanceof import_obsidian18.TFile) {
const folderNoteLink = folderItem.createEl("a", { cls: "folder-overview-list-item folder-name-item internal-link", href: folderNote.path });
folderNoteLink.innerText = folder.name;
pathBlacklist.push(folderNote.path);
} else {
const folderName = folderItem.createEl("span", { cls: "folder-overview-list-item folder-name-item" });
folderName.innerText = folder.name;
}
return folderItem;
}
addFileList(plugin, list, pathBlacklist, file, includeTypes, disableFileTag) {
if (includeTypes.length > 0 && !includeTypes.includes("all")) {
if (file.extension === "md" && !includeTypes.includes("markdown"))
return;
if (file.extension === "canvas" && !includeTypes.includes("canvas"))
return;
if (file.extension === "pdf" && !includeTypes.includes("pdf"))
return;
const imageTypes = ["jpg", "jpeg", "png", "gif", "svg", "webp"];
if (imageTypes.includes(file.extension) && !includeTypes.includes("image"))
return;
const videoTypes = ["mp4", "webm", "ogv", "mov", "mkv"];
if (videoTypes.includes(file.extension) && !includeTypes.includes("video"))
return;
const audioTypes = ["mp3", "wav", "m4a", "3gp", "flac", "ogg", "oga", "opus"];
if (audioTypes.includes(file.extension) && includeTypes.includes("audio"))
return;
const allTypes = ["md", "canvas", "pdf", ...imageTypes, ...videoTypes, ...audioTypes];
if (!allTypes.includes(file.extension) && !includeTypes.includes("other"))
return;
}
if (!this.yaml.showFolderNotes) {
if (pathBlacklist.includes(file.path))
return;
}
const listItem = list.createEl("li", { cls: "folder-overview-list file-link" });
const nameItem = listItem.createEl("div", { cls: "folder-overview-list-item" });
const link = nameItem.createEl("a", { cls: "internal-link", href: file.path });
link.innerText = file.basename;
if (file.extension !== "md" && !disableFileTag) {
nameItem.createDiv({ cls: "nav-file-tag" }).innerText = file.extension;
}
}
getAllFiles(files, sourceFolderPath, depth) {
const allFiles = [];
files.forEach((file) => {
if (file instanceof import_obsidian18.TFolder) {
if (file.path.split("/").length - sourceFolderPath.split("/").length - 1 < depth - 1) {
allFiles.push(...this.getAllFiles(file.children, sourceFolderPath, depth));
}
} else {
allFiles.push(file);
}
});
return allFiles;
}
};
async function updateYaml(plugin, ctx, el, yaml) {
const file = plugin.app.vault.getAbstractFileByPath(ctx.sourcePath);
if (!(file instanceof import_obsidian18.TFile))
return;
let stringYaml = (0, import_obsidian18.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");
lines.splice(lineStart, lineLength + 1, `\`\`\`folder-overview
${stringYaml}\`\`\``);
return lines.join("\n");
}
return `\`\`\`folder-overview
${stringYaml}\`\`\``;
});
}
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;
}
// src/folderOverview/ModalSettings.ts
var FolderOverviewSettings = class extends import_obsidian19.Modal {
constructor(app2, plugin, yaml, ctx, el, defaultSettings) {
super(app2);
this.plugin = plugin;
this.app = app2;
if (!yaml) {
this.yaml = this.plugin.settings.defaultOverview;
} else if (ctx) {
const includeTypes = (yaml == null ? void 0 : yaml.includeTypes) || plugin.settings.defaultOverview.includeTypes || ["folder", "markdown"];
this.yaml = {
id: (yaml == null ? void 0 : yaml.id) || crypto.randomUUID(),
folderPath: (yaml == null ? void 0 : yaml.folderPath) === void 0 || (yaml == null ? void 0 : yaml.folderPath) === null ? plugin.getFolderPathFromString(ctx.sourcePath) : yaml == null ? void 0 : yaml.folderPath,
title: (yaml == null ? void 0 : yaml.title) || plugin.settings.defaultOverview.title,
showTitle: (yaml == null ? void 0 : yaml.showTitle) === void 0 || (yaml == null ? void 0 : yaml.showTitle) === null ? plugin.settings.defaultOverview.showTitle : yaml == null ? void 0 : yaml.showTitle,
depth: (yaml == null ? void 0 : yaml.depth) || plugin.settings.defaultOverview.depth,
style: (yaml == null ? void 0 : yaml.style) || "list",
includeTypes: includeTypes.map((type) => type.toLowerCase()),
disableFileTag: (yaml == null ? void 0 : yaml.disableFileTag) === void 0 || (yaml == null ? void 0 : yaml.disableFileTag) === null ? plugin.settings.defaultOverview.disableFileTag : yaml == null ? void 0 : yaml.disableFileTag,
sortBy: (yaml == null ? void 0 : yaml.sortBy) || plugin.settings.defaultOverview.sortBy,
sortByAsc: (yaml == null ? void 0 : yaml.sortByAsc) === void 0 || (yaml == null ? void 0 : yaml.sortByAsc) === null ? plugin.settings.defaultOverview.sortByAsc : yaml == null ? void 0 : yaml.sortByAsc,
showEmptyFolders: (yaml == null ? void 0 : yaml.showEmptyFolders) === void 0 || (yaml == null ? void 0 : yaml.showEmptyFolders) === null ? plugin.settings.defaultOverview.showEmptyFolders : yaml == null ? void 0 : yaml.showEmptyFolders,
onlyIncludeSubfolders: (yaml == null ? void 0 : yaml.onlyIncludeSubfolders) === void 0 || (yaml == null ? void 0 : yaml.onlyIncludeSubfolders) === null ? plugin.settings.defaultOverview.onlyIncludeSubfolders : yaml == null ? void 0 : yaml.onlyIncludeSubfolders,
storeFolderCondition: (yaml == null ? void 0 : yaml.storeFolderCondition) === void 0 || (yaml == null ? void 0 : yaml.storeFolderCondition) === null ? plugin.settings.defaultOverview.storeFolderCondition : yaml == null ? void 0 : yaml.storeFolderCondition,
showFolderNotes: (yaml == null ? void 0 : yaml.showFolderNotes) === void 0 || (yaml == null ? void 0 : yaml.showFolderNotes) === null ? plugin.settings.defaultOverview.showFolderNotes : yaml == null ? void 0 : yaml.showFolderNotes,
disableCollapseIcon: (yaml == null ? void 0 : yaml.disableCollapseIcon) === void 0 || (yaml == null ? void 0 : yaml.disableCollapseIcon) === null ? plugin.settings.defaultOverview.disableCollapseIcon : yaml == null ? void 0 : yaml.disableCollapseIcon
};
}
if (ctx) {
this.ctx = ctx;
}
if (el) {
this.el = el;
}
if (defaultSettings) {
this.yaml = this.plugin.settings.defaultOverview;
this.defaultSettings = true;
return;
}
updateYaml(this.plugin, this.ctx, this.el, this.yaml);
}
onOpen() {
this.display();
}
display() {
var _a, _b, _c, _d;
const { contentEl } = this;
contentEl.empty();
contentEl.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
this.close();
}
});
if (!this.defaultSettings) {
contentEl.createEl("h2", { text: "Folder overview settings" });
} else {
contentEl.createEl("h2", { text: "Default folder overview settings" });
}
new import_obsidian19.Setting(contentEl).setName("Show the title").setDesc("Choose if the title should be shown").addToggle((toggle) => toggle.setValue(this.yaml.showTitle).onChange(async (value) => {
this.yaml.showTitle = value;
this.display();
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
;
}));
if (this.yaml.showTitle) {
new import_obsidian19.Setting(contentEl).setName("Title").setDesc("Choose the title of the folder overview").addText((text) => {
var _a2;
return text.setValue(((_a2 = this.yaml) == null ? void 0 : _a2.title) || "{{folderName}} overview").onChange(async (value) => {
this.yaml.title = value;
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
;
});
});
}
new import_obsidian19.Setting(contentEl).setName("Folder path for the overview").setDesc("Choose the folder path for the overview").addSearch((search) => {
var _a2;
new FolderSuggest(search.inputEl, this.plugin);
search.setPlaceholder("Folder path").setValue(((_a2 = this.yaml) == null ? void 0 : _a2.folderPath) || "").onChange(async (value) => {
if (!(this.app.vault.getAbstractFileByPath(value) instanceof import_obsidian19.TFolder) && value !== "")
return;
this.yaml.folderPath = value;
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
;
});
});
new import_obsidian19.Setting(contentEl).setName("Overview style").setDesc("Choose the style of the overview (grid style soon)").addDropdown((dropdown) => {
var _a2;
return dropdown.addOption("list", "List").addOption("explorer", "Explorer").setValue(((_a2 = this.yaml) == null ? void 0 : _a2.style) || "list").onChange(async (value) => {
this.yaml.style = value;
this.display();
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
});
});
if (this.yaml.style === "explorer") {
new import_obsidian19.Setting(contentEl).setName("Store collapsed condition").setDesc("Choose if the collapsed condition should be stored stored until you restart Obsidian").addToggle((toggle) => toggle.setValue(this.yaml.storeFolderCondition).onChange(async (value) => {
this.yaml.storeFolderCondition = value;
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
;
}));
}
const setting = new import_obsidian19.Setting(contentEl);
setting.setName("Include types");
const list = setting.createList((list2) => {
var _a2;
return list2.addModal(this).setValues(((_a2 = this.yaml) == null ? void 0 : _a2.includeTypes) || this.plugin.settings.defaultOverview.includeTypes || []).addResetButton();
});
if ((((_b = (_a = this.yaml) == null ? void 0 : _a.includeTypes) == null ? void 0 : _b.length) || 0) < 8 && !((_c = this.yaml.includeTypes) == null ? void 0 : _c.includes("all"))) {
setting.addDropdown((dropdown) => {
if (!this.yaml.includeTypes)
this.yaml.includeTypes = this.plugin.settings.defaultOverview.includeTypes || [];
this.yaml.includeTypes = this.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 = this.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") {
this.yaml.includeTypes = (_a2 = this.yaml.includeTypes) == null ? void 0 : _a2.filter((type) => type === "folder");
list.setValues(this.yaml.includeTypes);
}
await list.addValue(value.toLowerCase());
this.display();
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
});
});
}
let disableFileTag;
(_d = this.yaml.includeTypes) == null ? void 0 : _d.forEach((type) => {
type === "folder" || type === "markdown" ? disableFileTag = true : null;
});
if (disableFileTag) {
new import_obsidian19.Setting(contentEl).setName("Disable file tag").setDesc("Choose if the file tag should be shown after the file name").addToggle((toggle) => {
toggle.setValue(this.yaml.disableFileTag).onChange(async (value) => {
this.yaml.disableFileTag = value;
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
});
});
}
new import_obsidian19.Setting(contentEl).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(this.yaml.showFolderNotes).onChange(async (value) => {
this.yaml.showFolderNotes = value;
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
}));
if (this.yaml.style !== "explorer") {
new import_obsidian19.Setting(contentEl).setName("File depth").setDesc("File & folder = +1 depth").addSlider((slider) => {
var _a2;
return slider.setValue(((_a2 = this.yaml) == null ? void 0 : _a2.depth) || 2).setLimits(1, 10, 1).onChange(async (value) => {
this.yaml.depth = value;
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
});
});
}
new import_obsidian19.Setting(contentEl).setName("Sort files by").setDesc("Choose how the files should be sorted").addDropdown((dropdown) => {
var _a2;
return dropdown.addOption("name", "Name").addOption("created", "Created").addOption("modified", "Modified").setValue(((_a2 = this.yaml) == null ? void 0 : _a2.sortBy) || "name").onChange(async (value) => {
this.yaml.sortBy = value;
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
});
}).addDropdown((dropdown) => {
dropdown.addOption("desc", "Descending").addOption("asc", "Ascending");
if (this.yaml.sortByAsc) {
dropdown.setValue("asc");
} else {
dropdown.setValue("desc");
}
dropdown.onChange(async (value) => {
if (value === "desc") {
this.yaml.sortByAsc = false;
} else {
this.yaml.sortByAsc = true;
}
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
});
});
if (this.yaml.style === "list") {
new import_obsidian19.Setting(contentEl).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(this.yaml.showEmptyFolders).onChange(async (value) => {
this.yaml.showEmptyFolders = value;
this.yaml.onlyIncludeSubfolders = false;
this.display();
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
});
});
if (this.yaml.showEmptyFolders) {
new import_obsidian19.Setting(contentEl).setName("Only show first empty subfolders of current folder").addToggle((toggle) => {
toggle.setValue(this.yaml.onlyIncludeSubfolders).onChange(async (value) => {
this.yaml.onlyIncludeSubfolders = value;
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
});
});
}
}
if (this.yaml.style === "explorer") {
new import_obsidian19.Setting(contentEl).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(this.yaml.disableCollapseIcon).onChange(async (value) => {
this.yaml.disableCollapseIcon = value;
if (this.defaultSettings) {
return this.plugin.saveSettings();
}
await updateYaml(this.plugin, this.ctx, this.el, this.yaml);
});
});
}
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
};
// src/settings/FolderOverviewSettings.ts
async function renderFolderOverview(settingsTab) {
settingsTab.settingsPage.createEl("h1", { text: "Folder overview settings" });
const containerEl = settingsTab.settingsPage;
new import_obsidian20.Setting(containerEl).setName("Manage folder overview defaults").setDesc("Manage the default settings for the folder overview plugin").addButton((button) => button.setButtonText("Manage").setCta().onClick(async () => {
new FolderOverviewSettings(settingsTab.plugin.app, settingsTab.plugin, settingsTab.plugin.settings.defaultOverview, null, null, true).open();
}));
}
// src/settings/ExcludedFoldersSettings.ts
var import_obsidian21 = require("obsidian");
async function renderExcludeFolders(settingsTab) {
settingsTab.settingsPage.createEl("h1", { text: "Exclude folders settings" });
const containerEl = settingsTab.settingsPage;
const manageExcluded = new import_obsidian21.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_obsidian21.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_obsidian21.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_obsidian21.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, settingsTab.plugin);
addExcludeFolderListItem(settingsTab, containerEl, excludedFolder);
addExcludedFolder(settingsTab.plugin, excludedFolder);
settingsTab.display();
});
});
settingsTab.plugin.settings.excludeFolders.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_SETTINGS = {
syncFolderName: true,
ctrlKey: true,
altKey: false,
hideFolderNote: true,
templatePath: "",
autoCreate: false,
enableCollapsing: false,
excludeFolders: [],
showDeleteConfirmation: true,
underlineFolder: true,
allowWhitespaceCollapsing: false,
underlineFolderInPath: true,
openFolderNoteOnClickInPath: true,
openInNewTab: false,
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
},
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: "",
subFolders: true,
disableSync: true,
disableAutoCreate: true,
disableFolderNote: false,
enableCollapsing: false,
position: 0,
excludeFromFolderOverview: false,
string: ""
},
excludePatternDefaultSettings: {
type: "pattern",
path: "",
subFolders: true,
disableSync: true,
disableAutoCreate: true,
disableFolderNote: false,
enableCollapsing: false,
position: 0,
excludeFromFolderOverview: false,
string: ""
},
hideCollapsingIcon: false
};
var SettingsTab = class extends import_obsidian22.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() {
const { containerEl } = this;
containerEl.empty();
const tabBar = containerEl.createEl("nav", { cls: "fn-settings-tab-bar" });
for (const [tabId, tabInfo] of Object.entries(this.TABS)) {
const tabEl = tabBar.createEl("div", { cls: "fn-settings-tab" });
const tabName = tabEl.createEl("div", { cls: "fn-settings-tab-name", text: tabInfo.name });
if (this.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");
this.plugin.settings.settingsTab = tabId.toLocaleLowerCase();
this.plugin.saveSettings();
}
tabEl.addClass("fn-settings-tab-active");
this.renderSettingsPage(tabId);
});
}
this.settingsPage = containerEl.createDiv({ cls: "fn-settings-page" });
this.renderSettingsPage(this.plugin.settings.settingsTab);
}
updateFolderNotes(newTemplate) {
new import_obsidian22.Notice("Starting to update folder notes...");
for (const folder of this.app.vault.getAllLoadedFiles()) {
if (folder instanceof import_obsidian22.TFolder) {
const folderNote = getFolderNote(this.plugin, folder.path);
if (!(folderNote instanceof import_obsidian22.TFile)) {
continue;
}
const folderNoteName = newTemplate.replace("{{folder_name}}", folder.name);
const newPath = `${folder.path}/${folderNoteName}.${folderNote.extension}`;
if (this.plugin.app.vault.getAbstractFileByPath(newPath)) {
continue;
}
this.plugin.app.fileManager.renameFile(folderNote, newPath);
}
}
this.plugin.settings.folderNoteName = newTemplate;
this.plugin.saveSettings();
new import_obsidian22.Notice("Finished updating folder notes");
}
switchStorageLocation(oldMethod) {
new import_obsidian22.Notice("Starting to switch storage location...");
this.app.vault.getAllLoadedFiles().forEach((file) => {
if (file instanceof import_obsidian22.TFolder) {
const folderNote = getFolderNote(this.plugin, file.path, oldMethod);
if (folderNote instanceof import_obsidian22.TFile) {
if (this.plugin.settings.storageLocation === "parentFolder") {
let newPath = "";
if (this.plugin.getFolderPathFromString(file.path).trim() === "") {
newPath = `${folderNote.name}`;
} else {
newPath = `${this.plugin.getFolderPathFromString(file.path)}/${folderNote.name}`;
}
this.plugin.app.fileManager.renameFile(folderNote, newPath);
} else if (this.plugin.settings.storageLocation === "insideFolder") {
if (this.plugin.getFolderPathFromString(folderNote.path) === file.path) {
return;
} else {
const newPath = `${file.path}/${folderNote.name}`;
this.plugin.app.fileManager.renameFile(folderNote, newPath);
}
}
}
}
});
new import_obsidian22.Notice("Finished switching storage location");
}
};
// src/Commands.ts
var import_obsidian23 = 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: "Make current active note a folder note for the folder of the active note",
callback: () => {
const file = this.app.workspace.getActiveFile();
if (!(file instanceof import_obsidian23.TFile))
return;
const folder = file.parent;
if (!(folder instanceof import_obsidian23.TFolder))
return;
const folderNote = getFolderNote(this.plugin, folder.path);
turnIntoFolderNote(this.plugin, file, folder, folderNote);
}
});
this.plugin.addCommand({
id: "create-folder-note",
name: "Create folder note with a new folder for the active note in the current folder",
callback: async () => {
var _a, _b, _c;
const file = this.app.workspace.getActiveFile();
if (!(file instanceof import_obsidian23.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_obsidian23.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_obsidian23.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 current folder of active note",
callback: () => {
const file = this.app.workspace.getActiveFile();
if (!(file instanceof import_obsidian23.TFile))
return;
const folder = file.parent;
if (!(folder instanceof import_obsidian23.TFolder))
return;
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 current folder of active note`,
callback: () => {
const file = this.app.workspace.getActiveFile();
if (!(file instanceof import_obsidian23.TFile))
return;
const folder = file.parent;
if (!(folder instanceof import_obsidian23.TFolder))
return;
createFolderNote(this.plugin, folder.path, true, "." + fileType, false);
}
});
});
this.plugin.addCommand({
id: "delete-folder-note-for-current-folder",
name: "Delete folder note of current folder of active note",
callback: () => {
const file = this.app.workspace.getActiveFile();
if (!(file instanceof import_obsidian23.TFile))
return;
const folder = file.parent;
if (!(folder instanceof import_obsidian23.TFolder))
return;
const folderNote = getFolderNote(this.plugin, folder.path);
if (!(folderNote instanceof import_obsidian23.TFile))
return;
deleteFolderNote(this.plugin, folderNote);
}
});
this.plugin.addCommand({
id: "open-folder-note-for-current-folder",
name: "Open folder note of current folder of active note",
callback: () => {
const file = this.app.workspace.getActiveFile();
if (!(file instanceof import_obsidian23.TFile))
return;
const folder = file.parent;
if (!(folder instanceof import_obsidian23.TFolder))
return;
const folderNote = getFolderNote(this.plugin, folder.path);
if (!(folderNote instanceof import_obsidian23.TFile))
return;
openFolderNote(this.plugin, folderNote);
}
});
this.plugin.addCommand({
id: "insert-folder-overview-fn",
name: "Insert folder overview",
editorCheckCallback: (checking, editor) => {
const line = editor.getCursor().line;
const lineText = editor.getLine(line);
if (lineText.trim() === "" || lineText.trim() === ">") {
if (!checking) {
let json = Object.assign({}, this.plugin.settings.defaultOverview);
json.id = crypto.randomUUID();
const yaml = (0, import_obsidian23.stringifyYaml)(json);
if (lineText.trim() === "") {
editor.replaceSelection(`\`\`\`folder-overview
${yaml}\`\`\`
`);
} else if (lineText.trim() === ">") {
const lines = yaml.split("\n");
const newLines = lines.map((line2) => {
return `> ${line2}`;
});
editor.replaceSelection(`\`\`\`folder-overview
${newLines.join("\n")}\`\`\`
`);
}
}
return true;
}
return false;
}
});
this.plugin.addCommand({
id: "create-folder-note-from-selected-text",
name: "Create folder note from selected text",
editorCheckCallback: (checking, editor, view) => {
const text = editor.getSelection().trim();
const line = editor.getCursor().line;
const file = view.file;
if (!(file instanceof import_obsidian23.TFile))
return false;
if (text && text.trim() !== "") {
if (checking) {
return true;
}
const blacklist = ["*", "\\", '"', "/", "<", ">", "?", "|", ":"];
for (const char of blacklist) {
if (text.includes(char)) {
new import_obsidian23.Notice('File name cannot contain any of the following characters: * " \\ / < > : | ?');
return false;
}
}
if (text.endsWith(".")) {
new import_obsidian23.Notice("File name cannot end with a dot");
return;
}
let folder;
const folderPath = this.plugin.getFolderPathFromString(file.path);
if (folderPath === "") {
folder = this.plugin.app.vault.getAbstractFileByPath(text);
if (folder instanceof import_obsidian23.TFolder) {
new import_obsidian23.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_obsidian23.TFolder) {
new import_obsidian23.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_obsidian23.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_obsidian23.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_obsidian23.TFolder) {
const folderNote = getFolderNote(this.plugin, folder.path);
if ((folderNote == null ? void 0 : folderNote.path) === file.path) {
return;
}
} else if (file.parent instanceof import_obsidian23.TFolder) {
folder = file.parent;
}
}
menu.addItem((item) => {
if (import_obsidian23.Platform.isDesktop && !import_obsidian23.Platform.isTablet && this.plugin.settings.useSubmenus) {
item.setTitle("Folder Note Commands").setIcon("folder-edit");
}
let subMenu;
if (!import_obsidian23.Platform.isDesktopApp || !import_obsidian23.Platform.isDesktop || import_obsidian23.Platform.isTablet || !this.plugin.settings.useSubmenus) {
subMenu = menu;
item.setDisabled(true);
} else {
subMenu = item.setSubmenu();
}
if (file instanceof import_obsidian23.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_obsidian23.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_obsidian23.TFolder))
return;
await createFolderNote(this.plugin, newFolder.path, true, "." + file.extension, false, file);
this.plugin.settings.autoCreate = automaticallyCreateFolderNote;
this.plugin.saveSettings();
});
});
if (this.plugin.getFolderPathFromString(file.path) === "")
return;
if (!(folder instanceof import_obsidian23.TFolder))
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_obsidian23.TFolder))
return;
const folderNote2 = getFolderNote(this.plugin, folder.path);
turnIntoFolderNote(this.plugin, file, folder, folderNote2);
});
});
}
if (!(file instanceof import_obsidian23.TFolder))
return;
if (this.plugin.settings.excludeFolders.find((folder2) => folder2.path === file.path)) {
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);
this.plugin.saveSettings();
new import_obsidian23.Notice("Successfully removed folder from excluded folders");
});
});
return;
}
subMenu.addItem((item2) => {
item2.setTitle("Exclude folder from folder notes").setIcon("x-circle").onClick(() => {
const excludedFolder = new ExcludedFolder(file.path, this.plugin.settings.excludeFolders.length, this.plugin);
this.plugin.settings.excludeFolders.push(excludedFolder);
this.plugin.saveSettings();
new import_obsidian23.Notice("Successfully excluded folder from folder notes");
});
});
if (!(file instanceof import_obsidian23.TFolder))
return;
const folderNote = getFolderNote(this.plugin, file.path);
if (folderNote instanceof import_obsidian23.TFile) {
subMenu.addItem((item2) => {
item2.setTitle("Delete folder note").setIcon("trash").onClick(() => {
deleteFolderNote(this.plugin, folderNote);
});
});
subMenu.addItem((item2) => {
item2.setTitle("Open folder note").setIcon("chevron-right-square").onClick(() => {
openFolderNote(this.plugin, folderNote);
});
});
subMenu.addItem((item2) => {
item2.setTitle("Copy Obsidian URL").setIcon("link").onClick(() => {
this.app.copyObsidianUrl(folderNote);
});
});
} 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();
const line = editor.getCursor().line;
const lineText = editor.getLine(line);
if (lineText.trim() === "" || lineText.trim() === ">") {
menu.addItem((item) => {
item.setTitle("Create folder overview").setIcon("edit").onClick(() => {
let json = Object.assign({}, this.plugin.settings.defaultOverview);
json.id = crypto.randomUUID();
const yaml = (0, import_obsidian23.stringifyYaml)(json);
if (lineText.trim() === "") {
editor.replaceSelection(`\`\`\`folder-overview
${yaml}\`\`\`
`);
} else if (lineText.trim() === ">") {
const lines = yaml.split("\n");
const newLines = lines.map((line2) => {
return `> ${line2}`;
});
editor.replaceSelection(`\`\`\`folder-overview
${newLines.join("\n")}\`\`\`
`);
}
});
});
}
if (!text || text.trim() === "")
return;
menu.addItem((item) => {
item.setTitle("Create folder note").setIcon("edit").onClick(() => {
const file = view.file;
if (!(file instanceof import_obsidian23.TFile))
return;
const blacklist = ["*", "\\", '"', "/", "<", ">", "?", "|", ":"];
for (const char of blacklist) {
if (text.includes(char)) {
new import_obsidian23.Notice('File name cannot contain any of the following characters: * " \\ / < > : | ?');
return;
}
}
if (text.endsWith(".")) {
new import_obsidian23.Notice("File name cannot end with a dot");
return;
}
let folder;
const folderPath = this.plugin.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_obsidian23.TFolder) {
return new import_obsidian23.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_obsidian23.TFolder) {
return new import_obsidian23.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_obsidian23.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/handleClick.ts
var import_obsidian24 = require("obsidian");
async function handleViewHeaderClick(event, plugin) {
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);
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) {
return openFolderNote(plugin, folderNote, event);
} else if (event.altKey || import_obsidian24.Keymap.isModEvent(event) === "tab") {
if (plugin.settings.altKey && event.altKey || plugin.settings.ctrlKey && import_obsidian24.Keymap.isModEvent(event) === "tab") {
await createFolderNote(plugin, folderPath, true, void 0, true);
plugin.addCSSClassToTitleEL(folderPath, "has-folder-note");
plugin.removeCSSClassFromEL(folderPath, "has-not-folder-note");
return;
}
}
event.target.onclick = null;
event.target.click();
}
async function handleFolderClick(event, plugin) {
var _a, _b, _c;
if (!(event.target instanceof HTMLElement))
return;
if (!event || !event.target)
return;
event.stopImmediatePropagation();
const folderPath = (_a = event.target.parentElement) == null ? void 0 : _a.getAttribute("data-path");
if (!folderPath) {
return;
}
const excludedFolder = getExcludedFolder(plugin, folderPath);
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) {
if (plugin.settings.openByClick) {
return openFolderNote(plugin, folderNote, event);
} else if (plugin.settings.openWithCtrl && import_obsidian24.Keymap.isModEvent(event) === "tab") {
return openFolderNote(plugin, folderNote, event);
} else if (plugin.settings.openWithAlt && event.altKey) {
return openFolderNote(plugin, folderNote, event);
} else {
if (plugin.settings.enableCollapsing)
return;
(_b = event.target.parentElement) == null ? void 0 : _b.click();
return;
}
} else if (event.altKey || import_obsidian24.Keymap.isModEvent(event) === "tab") {
if (plugin.settings.altKey && event.altKey || plugin.settings.ctrlKey && import_obsidian24.Keymap.isModEvent(event) === "tab") {
await createFolderNote(plugin, folderPath, true, void 0, true);
plugin.addCSSClassToTitleEL(folderPath, "has-folder-note");
plugin.removeCSSClassFromEL(folderPath, "has-not-folder-note");
return;
}
} else if (!folderNote) {
if (plugin.settings.enableCollapsing)
return;
return (_c = event.target.parentElement) == null ? void 0 : _c.click();
}
event.target.onclick = null;
event.target.click();
}
// src/events/handleRename.ts
var import_obsidian25 = require("obsidian");
function handleFolderRename(file, oldPath, plugin) {
const fileName = plugin.settings.folderNoteName.replace("{{folder_name}}", file.name);
const folder = plugin.app.vault.getAbstractFileByPath(file.path);
const folderNote = getFolderNote(plugin, oldPath);
if (!(folderNote instanceof import_obsidian25.TFile))
return;
if (!(folder instanceof import_obsidian25.TFolder))
return;
const excludedFolders = plugin.settings.excludeFolders.filter((excludedFolder2) => excludedFolder2.path.includes(oldPath));
excludedFolders.forEach((excludedFolder2) => {
if (excludedFolder2.path === oldPath) {
excludedFolder2.path = folder.path;
return;
}
const folders = excludedFolder2.path.split("/");
if (folders.length < 1) {
folders.push(excludedFolder2.path);
}
folders[folders.indexOf(folder.name)] = folder.name;
excludedFolder2.path = folders.join("/");
});
plugin.saveSettings();
const excludedFolder = getExcludedFolder(plugin, file.path);
if ((excludedFolder == null ? void 0 : excludedFolder.disableSync) && !folderNote) {
return plugin.removeCSSClassFromEL(file.path, "has-folder-note");
}
let newPath = "";
if (plugin.settings.storageLocation === "parentFolder") {
const parentFolderPath = plugin.getFolderPathFromString(file.path);
const oldParentFolderPath = plugin.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);
}
function handleFileRename(file, oldPath, plugin) {
const oldFileName = plugin.removeExtension(plugin.getFileNameFromPathString(oldPath));
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);
let excludedFolder = getExcludedFolder(plugin, (newFolder == null ? void 0 : newFolder.path) || "");
const folderNote = getFolderNote(plugin, oldPath, plugin.settings.storageLocation, file);
if ((excludedFolder == null ? void 0 : excludedFolder.disableSync) && folderName === (newFolder == null ? void 0 : newFolder.name)) {
plugin.addCSSClassToTitleEL(file.path, "is-folder-note");
plugin.addCSSClassToTitleEL(newFolder.path, "has-folder-note");
return;
} else if (excludedFolder == null ? void 0 : excludedFolder.disableSync) {
plugin.removeCSSClassFromEL(file.path, "is-folder-note");
plugin.removeCSSClassFromEL((newFolder == null ? void 0 : newFolder.path) || "", "has-folder-note");
return;
}
if (folderName === (newFolder == null ? void 0 : newFolder.name) && folderNote) {
new import_obsidian25.Notice("Folder with same name already exists!");
let excludedFolderExisted = true;
let disabledSync = false;
if (!excludedFolder) {
excludedFolderExisted = false;
excludedFolder = new ExcludedFolder((oldFolder == null ? void 0 : oldFolder.path) || "", plugin.settings.excludeFolders.length, 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);
}
});
}
if (folderName === (newFolder == null ? void 0 : newFolder.name)) {
plugin.addCSSClassToTitleEL(file.path, "is-folder-note");
plugin.addCSSClassToTitleEL(newFolder.path, "has-folder-note");
plugin.removeCSSClassFromEL(oldFolder == null ? void 0 : oldFolder.path, "has-folder-note");
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);
}
if (oldFolder.name === oldFileName && (newFolder == null ? void 0 : newFolder.path) !== oldFolder.path) {
plugin.removeCSSClassFromEL(oldFolder.path, "has-folder-note");
plugin.removeCSSClassFromEL(file.path, "is-folder-note");
plugin.removeCSSClassFromEL(oldPath, "is-folder-note");
}
}
async function renameFolderOnFileRename(file, oldPath, oldFolder, plugin) {
var _a;
const newFolderName = extractFolderName(plugin.settings.folderNoteName, file.basename);
if (!newFolderName) {
plugin.removeCSSClassFromEL(oldFolder.path, "has-folder-note");
plugin.removeCSSClassFromEL(file.path, "is-folder-note");
return;
} else if (newFolderName === oldFolder.name) {
plugin.addCSSClassToTitleEL(oldFolder.path, "has-folder-note");
plugin.addCSSClassToTitleEL(file.path, "is-folder-note");
return;
}
let newFolderPath = "";
if (plugin.settings.storageLocation === "insideFolder") {
newFolderPath = ((_a = oldFolder.parent) == null ? void 0 : _a.path) + "/" + newFolderName;
} else {
const parentFolderPath = plugin.getFolderPathFromString(file.path);
if (parentFolderPath.trim() === "") {
newFolderPath = `${newFolderName}`;
} else {
newFolderPath = `${parentFolderPath}/${newFolderName}`;
}
}
if (plugin.app.vault.getAbstractFileByPath(newFolderPath) || plugin.app.vault.getAbstractFileByPath(newFolderName || "")) {
await plugin.app.fileManager.renameFile(file, oldPath);
return new import_obsidian25.Notice("A folder with the same name already exists");
}
plugin.app.fileManager.renameFile(oldFolder, newFolderPath);
}
// src/functions/ListComponent.ts
var import_obsidian26 = require("obsidian");
var ListComponent = class {
constructor(containerEl) {
this.containerEl = containerEl;
this.controlEl = containerEl.querySelector(".setting-item-control") || containerEl;
this.listEl = this.controlEl.createDiv("setting-command-hotkeys");
}
addModal(modal) {
this.modal = modal;
this.values = modal.yaml.includeTypes || [];
return this;
}
addSettings(settings) {
this.settings = settings;
return this;
}
setValues(values) {
this.listEl.empty();
this.values = values;
if (this.modal) {
this.modal.yaml.includeTypes = values;
}
if (values.length !== 0) {
values.forEach((value) => {
this.addElement(value);
});
}
if (this.modal && this.modal.defaultSettings) {
this.modal.plugin.saveSettings();
return this;
} else if (this.settings) {
this.settings.plugin.settings.supportedFileTypes = values;
this.settings.plugin.saveSettings();
return this;
}
if (!this.modal)
return this;
updateYaml(this.modal.plugin, this.modal.ctx, this.modal.el, this.modal.yaml);
return this;
}
addElement(value) {
this.listEl.createSpan("setting-hotkey", (span) => {
if (value.toLocaleLowerCase() === "md") {
span.innerText = "markdown";
} else {
span.innerText = value;
}
const removeSpan = span.createEl("span", { cls: "ofn-list-item-remove setting-hotkey-icon" });
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
const svgElement = removeSpan.createEl("span", { cls: "ofn-list-item-remove-icon" });
svgElement.innerHTML = svg;
removeSpan.onClickEvent((e) => {
this.removeValue(value);
span.remove();
});
});
}
async addValue(value) {
this.values.push(value);
this.addElement(value);
if (this.settings) {
this.settings.plugin.settings.supportedFileTypes = this.values;
this.settings.plugin.saveSettings();
}
if (!this.modal)
return this;
this.modal.yaml.includeTypes = this.values;
return this;
}
addResetButton() {
const resetButton = this.controlEl.createEl("span", { cls: "clickable-icon setting-restore-hotkey-button" });
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-rotate-ccw"><path d="M3 2v6h6"></path><path d="M3 13a9 9 0 1 0 3-7.7L3 8"></path></svg>';
resetButton.innerHTML = svg;
resetButton.onClickEvent((e) => {
if (this.modal) {
this.modal.plugin.loadSettings();
this.setValues(this.modal.plugin.settings.defaultOverview.includeTypes || []);
this.modal.display();
} else if (this.settings) {
this.setValues(["md", "canvas"]);
this.settings.display();
}
});
return this;
}
removeValue(value) {
if (value === "all") {
if (this.modal) {
this.modal.plugin.loadSettings();
this.setValues(this.modal.plugin.settings.defaultOverview.includeTypes || []);
this.modal.display();
} else if (this.settings) {
this.setValues(["md", "canvas"]);
this.settings.display();
}
} else {
this.values = this.values.filter((v) => v !== value);
this.setValues(this.values);
if (this.modal) {
this.modal.display();
} else if (this.settings) {
this.settings.display();
}
}
}
};
function createList(cb) {
const list = new ListComponent(this.settingEl);
cb(list);
return list;
}
import_obsidian26.Setting.prototype.createList = createList;
// src/main.ts
var FolderNotesPlugin = class extends import_obsidian27.Plugin {
constructor() {
super(...arguments);
this.fmtpHandler = null;
this.hoveredElement = null;
this.mouseEvent = null;
this.hoverLinkTriggered = false;
}
async onload() {
console.log("loading folder notes plugin");
await this.loadSettings();
this.settingsTab = new SettingsTab(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.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.allowWhitespaceCollapsing) {
document.body.classList.add("fn-whitespace-stop-collapsing");
}
if (this.settings.hideCollapsingIcon) {
document.body.classList.add("fn-hide-collapse-icon");
}
new Commands(this.app, this).registerCommands();
this.app.workspace.onLayoutReady(() => {
if (this.settings.frontMatterTitle.enabled) {
this.fmtpHandler = new FrontMatterTitlePluginHandler(this);
}
});
this.observer = new MutationObserver((mutations) => {
mutations.forEach((rec) => {
if (rec.type === "childList") {
rec.target.querySelectorAll("div.nav-folder-title-content").forEach((element) => {
if (element.onclick)
return;
if (import_obsidian27.Platform.isMobile && this.settings.disableOpenFolderNoteOnClick)
return;
element.addEventListener("auxclick", (event) => {
if (event.button == 1) {
handleFolderClick(event, this);
}
}, { capture: true });
element.onclick = (event) => handleFolderClick(event, this);
this.registerDomEvent(element, "pointerover", (event) => {
var _a, _b;
this.hoveredElement = element;
this.mouseEvent = event;
if (!import_obsidian27.Keymap.isModEvent(event))
return;
if (!(event.target instanceof HTMLElement))
return;
const folderPath = ((_b = (_a = event == null ? void 0 : event.target) == null ? void 0 : _a.parentElement) == null ? void 0 : _b.getAttribute("data-path")) || "";
const folderNote = getFolderNote(this, folderPath);
if (!folderNote)
return;
this.app.workspace.trigger("hover-link", {
event,
source: "preview",
hoverParent: {
file: folderNote
},
targetEl: event.target,
linktext: folderNote == null ? void 0 : folderNote.basename,
sourcePath: folderNote == null ? void 0 : folderNote.path
});
this.hoverLinkTriggered = true;
});
this.registerDomEvent(element, "pointerout", () => {
this.hoveredElement = null;
this.mouseEvent = null;
this.hoverLinkTriggered = false;
});
});
if (!this.settings.openFolderNoteOnClickInPath) {
return;
}
rec.target.querySelectorAll("span.view-header-breadcrumb").forEach((element) => {
var _a, _b;
const breadcrumbs = (_a = element.parentElement) == null ? void 0 : _a.querySelectorAll("span.view-header-breadcrumb");
if (!breadcrumbs)
return;
let path = "";
breadcrumbs.forEach((breadcrumb) => {
var _a2;
if (breadcrumb.hasAttribute("old-name")) {
path += breadcrumb.getAttribute("old-name") + "/";
} else {
path += breadcrumb.innerText.trim() + "/";
}
const folderPath = path.slice(0, -1);
breadcrumb.setAttribute("data-path", folderPath);
const folder = (_a2 = this.fmtpHandler) == null ? void 0 : _a2.modifiedFolders.get(folderPath);
if (folder && this.settings.frontMatterTitle.path && this.settings.frontMatterTitle.enabled) {
breadcrumb.setAttribute("old-name", folder.name || "");
breadcrumb.innerText = folder.newName || "";
}
const folderNote = getFolderNote(this, folderPath);
if (folderNote) {
breadcrumb.classList.add("has-folder-note");
}
});
(_b = element.parentElement) == null ? void 0 : _b.setAttribute("data-path", path.slice(0, -1));
if (breadcrumbs.length > 0) {
breadcrumbs.forEach((breadcrumb) => {
if (breadcrumb.onclick)
return;
breadcrumb.onclick = (event) => handleViewHeaderClick(event, this);
});
}
});
}
});
});
this.observer.observe(document.body, {
childList: true,
subtree: true
});
this.registerDomEvent(window, "keydown", (event) => {
var _a;
const hoveredElement = this.hoveredElement;
if (this.hoverLinkTriggered)
return;
if (!hoveredElement)
return;
if (!import_obsidian27.Keymap.isModEvent(event))
return;
const folderPath = ((_a = hoveredElement == null ? void 0 : hoveredElement.parentElement) == null ? void 0 : _a.getAttribute("data-path")) || "";
const folderNote = getFolderNote(this, folderPath);
if (!folderNote)
return;
this.app.workspace.trigger("hover-link", {
event: this.mouseEvent,
source: "preview",
hoverParent: {
file: folderNote
},
targetEl: hoveredElement,
linktext: folderNote == null ? void 0 : folderNote.basename,
sourcePath: folderNote == null ? void 0 : folderNote.path
});
this.hoverLinkTriggered = true;
});
this.registerEvent(this.app.workspace.on("layout-change", () => {
this.loadFileClasses();
}));
this.registerEvent(this.app.vault.on("delete", (file) => {
if (!(file instanceof import_obsidian27.TFile)) {
return;
}
const parentFolder = getFolder(this, file);
this.removeCSSClassFromEL(parentFolder == null ? void 0 : parentFolder.path, "has-folder-note");
}));
this.registerEvent(this.app.vault.on("create", (file) => {
if (file instanceof import_obsidian27.TFile) {
const folderName = extractFolderName(this.settings.folderNoteName, file.basename);
const folder = getFolder(this, file);
if (!folder) {
return;
}
if (folderName !== folder.name) {
return;
}
this.addCSSClassToTitleEL(folder.path, "has-folder-note");
this.addCSSClassToTitleEL(file.path, "is-folder-note");
}
if (!this.app.workspace.layoutReady)
return;
if (!this.settings.autoCreate)
return;
if (!(file instanceof import_obsidian27.TFolder))
return;
const excludedFolder = getExcludedFolder(this, file.path);
if (excludedFolder == null ? void 0 : excludedFolder.disableAutoCreate)
return;
const folderNote = getFolderNote(this, file.path);
if (folderNote)
return;
createFolderNote(this, file.path, true, void 0, true);
this.addCSSClassToTitleEL(file.path, "has-folder-note");
}));
this.registerEvent(this.app.workspace.on("file-open", (openFile) => {
if (this.activeFolderDom) {
this.activeFolderDom.removeClass("fn-is-active");
this.activeFolderDom = null;
}
if (!openFile || !openFile.basename) {
return;
}
const folder = getFolder(this, openFile);
if (!folder) {
return;
}
if (extractFolderName(this.settings.folderNoteName, openFile.basename) !== folder.name) {
return;
}
this.activeFolderDom = this.getEL(folder.path);
if (this.activeFolderDom)
this.activeFolderDom.addClass("fn-is-active");
}));
this.registerEvent(this.app.vault.on("rename", (file, oldPath) => {
if (!this.settings.syncFolderName) {
this.removeCSSClassFromEL(file.path, "has-folder-note");
this.removeCSSClassFromEL(file.path, "is-folder-note");
return;
}
if (file instanceof import_obsidian27.TFolder) {
return handleFolderRename(file, oldPath, this);
} else if (file instanceof import_obsidian27.TFile) {
return handleFileRename(file, oldPath, this);
}
}));
this.registerEvent(this.app.vault.on("delete", (file) => {
if (file instanceof import_obsidian27.TFile) {
const folder = getFolder(this, file);
if (!folder) {
return;
}
this.removeCSSClassFromEL(folder.path, "has-folder-note");
}
if (!(file instanceof import_obsidian27.TFolder)) {
return;
}
const folderNote = getFolderNote(this, file.path);
if (!folderNote) {
return;
}
this.removeCSSClassFromEL(folderNote.path, "is-folder-note");
if (!this.settings.syncDelete) {
return;
}
this.app.vault.delete(folderNote);
}));
this.registerMarkdownCodeBlockProcessor("folder-overview", (source, el, ctx) => {
this.handleOverviewBlock(source, el, ctx);
});
if (this.app.workspace.layoutReady) {
this.loadFileClasses();
} else {
this.app.workspace.onLayoutReady(async () => this.loadFileClasses());
}
}
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_obsidian27.parseYaml)(source), ctx, el).open();
}, { capture: true });
}
});
observer.observe(el, {
childList: true,
subtree: true
});
try {
const folderOverview = new FolderOverview(this, ctx, source, el);
folderOverview.create(this, (0, import_obsidian27.parseYaml)(source), el, ctx);
} catch (e) {
new import_obsidian27.Notice("Error creating folder overview (folder notes plugin) - check console for more details");
console.error(e);
}
}
getFileNameFromPathString(path) {
return path.substring(path.lastIndexOf("/") >= 0 ? path.lastIndexOf("/") + 1 : 0);
}
getFolderNameFromPathString(path) {
if (path.endsWith(".md") || path.endsWith(".canvas")) {
return path.split("/").slice(-2)[0];
} else {
return path.split("/").slice(-1)[0];
}
}
removeExtension(name) {
return name.replace(/\.[^/.]+$/, "");
}
getExtensionFromPathString(path) {
return path.slice(path.lastIndexOf(".") >= 0 ? path.lastIndexOf(".") : 0);
}
getFolderPathFromString(path) {
const subString = path.lastIndexOf("/") >= 0 ? path.lastIndexOf("/") : 0;
return path.substring(0, subString);
}
getParentFolderPath(path) {
return this.getFolderPathFromString(this.getFolderPathFromString(path));
}
getFileExplorer() {
return this.app.workspace.getLeavesOfType("file-explorer")[0];
}
getFileExplorerView() {
return this.getFileExplorer().view;
}
async addCSSClassToTitleEL(path, cssClass, waitForCreate = false, count = 0) {
const fileExplorerItem = this.getEL(path);
if (!fileExplorerItem) {
if (waitForCreate && count < 5) {
await new Promise((r) => setTimeout(r, 500));
this.addCSSClassToTitleEL(path, cssClass, waitForCreate, count + 1);
return;
}
return;
}
fileExplorerItem.addClass(cssClass);
const viewHeaderItems = document.querySelectorAll(`[data-path="${path}"]`);
viewHeaderItems.forEach((item) => {
item.addClass(cssClass);
});
}
async changeName(folder, name, replacePath, waitForCreate = false, count = 0) {
if (!name)
name = folder.name;
let fileExplorerItem = this.getEL(folder.path);
if (!fileExplorerItem) {
if (waitForCreate && count < 5) {
await new Promise((r) => setTimeout(r, 500));
this.changeName(folder, name, replacePath, waitForCreate, count + 1);
return;
}
return;
}
fileExplorerItem = fileExplorerItem.querySelector("div.nav-folder-title-content");
if (!fileExplorerItem) {
return;
}
if (this.settings.frontMatterTitle.explorer && this.settings.frontMatterTitle.enabled) {
fileExplorerItem.innerText = name;
fileExplorerItem.setAttribute("old-name", folder.name);
} else {
fileExplorerItem.innerText = folder.name;
fileExplorerItem.removeAttribute("old-name");
}
if (replacePath) {
this.updateBreadcrumbs();
}
}
updateBreadcrumbs(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_obsidian27.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_obsidian27.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);
}
});
}
removeCSSClassFromEL(path, cssClass) {
if (!path)
return;
const fileExplorerItem = this.getEL(path);
const viewHeaderItems = document.querySelectorAll(`[data-path="${path}"]`);
viewHeaderItems.forEach((item) => {
item.removeClass(cssClass);
});
if (!fileExplorerItem) {
return;
}
fileExplorerItem.removeClass(cssClass);
}
getEL(path) {
const fileExplorer = this.getFileExplorer();
if (!fileExplorer) {
return null;
}
const fileExplorerItem = fileExplorer.view.fileItems[path];
if (!fileExplorerItem) {
return null;
}
if (fileExplorerItem.selfEl)
return fileExplorerItem.selfEl;
return fileExplorerItem.titleEl;
}
loadFileClasses(forceReload = false) {
if (this.activeFileExplorer === this.getFileExplorer() && !forceReload) {
return;
}
this.activeFileExplorer = this.getFileExplorer();
this.app.vault.getAllLoadedFiles().forEach((file) => {
if (!(file instanceof import_obsidian27.TFolder)) {
return;
}
const folderNote = getFolderNote(this, file.path);
if (!folderNote) {
this.removeCSSClassFromEL(file == null ? void 0 : file.path, "has-folder-note");
this.removeCSSClassFromEL(file == null ? void 0 : file.path, "only-has-folder-note");
return;
}
const excludedFolder = getExcludedFolder(this, file.path);
if (excludedFolder == null ? void 0 : excludedFolder.disableFolderNote) {
this.removeCSSClassFromEL(folderNote.path, "is-folder-note");
this.removeCSSClassFromEL(file.path, "has-folder-note");
this.removeCSSClassFromEL(file == null ? void 0 : file.path, "only-has-folder-note");
} else {
this.addCSSClassToTitleEL(folderNote.path, "is-folder-note");
this.addCSSClassToTitleEL(file.path, "has-folder-note");
if (file.children.length == 1) {
this.addCSSClassToTitleEL(file.path, "only-has-folder-note");
}
}
});
}
reloadHandlers() {
document.querySelectorAll("div.nav-folder-title-content").forEach((element) => {
if (element.onclick)
return;
element.onclick = (event) => handleFolderClick(event, this);
});
}
onunload() {
console.log("unloading folder notes plugin");
this.observer.disconnect();
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");
if (this.activeFolderDom) {
this.activeFolderDom.removeClass("is-active");
}
if (this.fmtpHandler) {
this.fmtpHandler.deleteEvent();
}
}
async loadSettings() {
const data = await this.loadData();
this.settings = Object.assign({}, DEFAULT_SETTINGS, data);
if (!data) {
return;
}
const overview = data.defaultOverview;
if (!overview) {
return;
}
this.settings.defaultOverview = Object.assign({}, DEFAULT_SETTINGS.defaultOverview, overview);
}
async saveSettings() {
await this.saveData(this.settings);
this.loadFileClasses(true);
}
};