/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD */ var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; 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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/main.ts var main_exports = {}; __export(main_exports, { default: () => ZeroQoLModulesPlugin }); module.exports = __toCommonJS(main_exports); var import_obsidian4 = require("obsidian"); // src/modules/attachment-clean-paste/index.ts var import_obsidian = require("obsidian"); // src/modules/base-module.ts var BaseModule = class { constructor() { this.cleanupFns = []; } get defaultSettings() { return {}; } onunload(_plugin) { for (const fn of this.cleanupFns) { fn(); } this.cleanupFns = []; } renderInlineSettings(_containerEl, _settings, _saveSettings) { } registerCleanup(fn) { this.cleanupFns.push(fn); } }; // src/locales/en.ts var en = { settings: { title: "ZeroQ QoL Modules", description: "Enable or disable modules as you wish." }, modules: { "attachment-clean-paste": { name: "Attachment Clean Paste", description: "Replaces ![[embed]] with [[path/file|name]] for configured file extensions on paste/drop", descriptionShort: "Replaces ![[embed]] with [[path/file|name]] for specified file extensions.", extensionsLabel: "File extensions", extensionsDesc: "Comma-separated extensions (e.g.: png, jpg, pdf, mp3). Files with these extensions will be inserted as [[path/file|name]] instead of ![[path/file]].", extensionsPlaceholder: "png, jpg, jpeg, gif, svg, webp, pdf" }, "preserve-link-aliases": { name: "Preserve Link Aliases", description: "Preserves original link aliases when attachments are renamed", processEmbedsLabel: "Process embed links", processEmbedsDesc: "Also process ![[embed]] links (disabled by default)", processCanvasLabel: "Process Canvas files", processCanvasDesc: "Also process links in Canvas (.canvas) files" } } }; // src/locales/ru.ts var ru = { settings: { title: "ZeroQ QoL Modules", description: "\u0412\u043A\u043B\u044E\u0447\u0430\u0439\u0442\u0435 \u0438 \u043E\u0442\u043A\u043B\u044E\u0447\u0430\u0439\u0442\u0435 \u043C\u043E\u0434\u0443\u043B\u0438 \u043F\u043E \u0441\u0432\u043E\u0435\u043C\u0443 \u0443\u0441\u043C\u043E\u0442\u0440\u0435\u043D\u0438\u044E." }, modules: { "attachment-clean-paste": { name: "Attachment Clean Paste", description: "\u0417\u0430\u043C\u0435\u043D\u044F\u0435\u0442 ![[\u0432\u043B\u043E\u0436\u0435\u043D\u0438\u0435]] \u043D\u0430 [[\u0432\u043B\u043E\u0436\u0435\u043D\u0438\u0435|\u0438\u043C\u044F]] \u0434\u043B\u044F \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u044B\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u0439 \u043F\u0440\u0438 \u0432\u0441\u0442\u0430\u0432\u043A\u0435/\u043F\u0435\u0440\u0435\u0442\u0430\u0441\u043A\u0438\u0432\u0430\u043D\u0438\u0438", descriptionShort: "\u0417\u0430\u043C\u0435\u043D\u044F\u0435\u0442 ![[\u0432\u043B\u043E\u0436\u0435\u043D\u0438\u0435]] \u043D\u0430 [[\u0432\u043B\u043E\u0436\u0435\u043D\u0438\u0435|\u0438\u043C\u044F]] \u0434\u043B\u044F \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u044B\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u0439.", extensionsLabel: "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F \u0444\u0430\u0439\u043B\u043E\u0432", extensionsDesc: "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E (\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: png, jpg, pdf, mp3). \u0424\u0430\u0439\u043B\u044B \u0441 \u044D\u0442\u0438\u043C\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F\u043C\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432\u0441\u0442\u0430\u0432\u043B\u044F\u0442\u044C\u0441\u044F \u043A\u0430\u043A [[path/file|name]] \u0432\u043C\u0435\u0441\u0442\u043E ![[path/file]].", extensionsPlaceholder: "png, jpg, jpeg, gif, svg, webp, pdf" }, "preserve-link-aliases": { name: "\u0421\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u0435 \u0430\u043B\u0438\u0430\u0441\u043E\u0432 \u0441\u0441\u044B\u043B\u043E\u043A", description: "\u0421\u043E\u0445\u0440\u0430\u043D\u044F\u0435\u0442 \u043E\u0440\u0438\u0433\u0438\u043D\u0430\u043B\u044C\u043D\u044B\u0435 \u0430\u043B\u0438\u0430\u0441\u044B \u0441\u0441\u044B\u043B\u043E\u043A \u043F\u0440\u0438 \u043F\u0435\u0440\u0435\u0438\u043C\u0435\u043D\u043E\u0432\u0430\u043D\u0438\u0438 \u0432\u043B\u043E\u0436\u0435\u043D\u0438\u0439", processEmbedsLabel: "\u041E\u0431\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u0442\u044C embed-\u0441\u0441\u044B\u043B\u043A\u0438", processEmbedsDesc: "\u0422\u0430\u043A\u0436\u0435 \u043E\u0431\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u0442\u044C ![[embed]] \u0441\u0441\u044B\u043B\u043A\u0438 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E \u0432\u044B\u043A\u043B\u044E\u0447\u0435\u043D\u043E)", processCanvasLabel: "\u041E\u0431\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u0442\u044C Canvas-\u0444\u0430\u0439\u043B\u044B", processCanvasDesc: "\u0422\u0430\u043A\u0436\u0435 \u043E\u0431\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u0442\u044C \u0441\u0441\u044B\u043B\u043A\u0438 \u0432 Canvas (.canvas) \u0444\u0430\u0439\u043B\u0430\u0445" } } }; // src/locales/index.ts var locales = { en, ru }; function detectLocale() { const lang = (document.documentElement.lang || "en").slice(0, 2); return locales[lang] || en; } var locale = detectLocale(); // src/modules/attachment-clean-paste/index.ts var MODULE_ID = "attachment-clean-paste"; var AttachmentCleanPasteModule = class extends BaseModule { constructor() { super(...arguments); this.id = MODULE_ID; this.name = locale.modules["attachment-clean-paste"].name; this.description = locale.modules["attachment-clean-paste"].description; } get defaultSettings() { return { extensions: "png, jpg, jpeg, gif, svg, webp, bmp, pdf" }; } onload(plugin, moduleSettings) { this.app = plugin.app; const rawSettings = moduleSettings; const pasteRef = plugin.app.workspace.on( "editor-paste", this.createPasteHandler(rawSettings) ); this.registerCleanup(() => plugin.app.workspace.offref(pasteRef)); const dropRef = plugin.app.workspace.on( "editor-drop", this.createDropHandler(rawSettings) ); this.registerCleanup(() => plugin.app.workspace.offref(dropRef)); } renderInlineSettings(containerEl, settings, saveSettings) { const loc = locale.modules["attachment-clean-paste"]; const extSettings = settings; new import_obsidian.Setting(containerEl).setName(loc.extensionsLabel).setDesc(loc.extensionsDesc).addTextArea((textarea) => { var _a; textarea.setPlaceholder(loc.extensionsPlaceholder).setValue((_a = extSettings == null ? void 0 : extSettings.extensions) != null ? _a : "").onChange(async (value) => { settings.extensions = value; await saveSettings(); }); textarea.inputEl.rows = 4; textarea.inputEl.style.width = "100%"; }); } async processAll(files, editor, settings, evt) { const matchingFiles = Array.from(files).filter( (f) => this.shouldProcess(f.name, settings) ); if (matchingFiles.length === 0) return; evt.preventDefault(); evt.stopPropagation(); const links = []; for (const file of matchingFiles) { const link = await this.processFile(file, settings); if (link) links.push(link); } if (links.length === 0) return; editor.replaceSelection(links.join("\n\n")); } createPasteHandler(settings) { return async (evt, editor, _info) => { var _a; const files = (_a = evt.clipboardData) == null ? void 0 : _a.files; if (!files || files.length === 0) return; await this.processAll(files, editor, settings, evt); }; } createDropHandler(settings) { return async (evt, editor, _info) => { var _a; const files = (_a = evt.dataTransfer) == null ? void 0 : _a.files; if (!files || files.length === 0) return; await this.processAll(files, editor, settings, evt); }; } shouldProcess(filename, settings) { const dotIndex = filename.lastIndexOf("."); if (dotIndex === -1) return false; const ext = filename.slice(dotIndex + 1).toLowerCase(); const exts = settings.extensions.split(",").map((e) => e.trim().toLowerCase()).filter((e) => e.length > 0); return exts.some((e) => { const cleanExt = e.startsWith(".") ? e.slice(1) : e; return cleanExt === ext; }); } async processFile(file, _settings) { try { const arrayBuffer = await file.arrayBuffer(); const filename = file.name; const nameWithoutExt = filename.replace(/\.[^/.]+$/, ""); let attachmentFolder = this.app.vault.getConfig( "attachmentFolderPath" ); if (!attachmentFolder) attachmentFolder = "attachments"; const folderPath = (0, import_obsidian.normalizePath)(attachmentFolder); if (!await this.app.vault.adapter.exists(folderPath)) { await this.app.vault.createFolder(folderPath); } const ext = filename.slice(filename.lastIndexOf(".") + 1); const basePath = (0, import_obsidian.normalizePath)(`${folderPath}/${nameWithoutExt}`); const availablePath = await this.app.vault.getAvailablePath( basePath, ext ); await this.app.vault.createBinary(availablePath, arrayBuffer); return `[[${availablePath}|${nameWithoutExt}]]`; } catch (e) { new import_obsidian.Notice(`Clean Paste error: ${e.message}`); console.error("Attachment Clean Paste:", e); } return null; } }; // src/modules/preserve-link-aliases/index.ts var import_obsidian2 = require("obsidian"); var MODULE_ID2 = "preserve-link-aliases"; var PreserveLinkAliasesModule = class extends BaseModule { constructor() { super(...arguments); this.id = MODULE_ID2; this.name = locale.modules["preserve-link-aliases"].name; this.description = locale.modules["preserve-link-aliases"].description; } get defaultSettings() { return { processEmbeds: false, processCanvas: false }; } onload(plugin, moduleSettings) { this.vault = plugin.app.vault; const rawSettings = moduleSettings; const renameRef = plugin.app.vault.on( "rename", (file, oldPath) => this.handleRename(file, oldPath, rawSettings) ); this.registerCleanup(() => plugin.app.vault.offref(renameRef)); } renderInlineSettings(containerEl, settings, saveSettings) { const loc = locale.modules["preserve-link-aliases"]; const s = settings; new import_obsidian2.Setting(containerEl).setName(loc.processEmbedsLabel).setDesc(loc.processEmbedsDesc).addToggle( (toggle) => toggle.setValue(s.processEmbeds).onChange(async (value) => { s.processEmbeds = value; await saveSettings(); }) ); new import_obsidian2.Setting(containerEl).setName(loc.processCanvasLabel).setDesc(loc.processCanvasDesc).addToggle( (toggle) => toggle.setValue(s.processCanvas).onChange(async (value) => { s.processCanvas = value; await saveSettings(); }) ); } async handleRename(file, oldPath, settings) { var _a; const oldName = (_a = oldPath.split("/").pop()) != null ? _a : ""; const newName = file.name; const oldBasename = oldName.replace(/\.[^/.]+$/, ""); const newBasename = newName.replace(/\.[^/.]+$/, ""); if (oldBasename === newBasename) return; const files = this.getFilesToProcess(settings); for (const f of files) { const content = await this.vault.read(f); const updated = this.processContent(content, newName, newBasename, oldBasename, settings); if (updated !== content) { await this.vault.modify(f, updated); } } } getFilesToProcess(settings) { const files = []; for (const file of this.vault.getMarkdownFiles()) { files.push(file); } if (settings.processCanvas) { const abstractFiles = this.vault.getFiles(); for (const file of abstractFiles) { if (file.extension === "canvas") { files.push(file); } } } return files; } processContent(content, newFileName, newBasename, oldBasename, settings) { const wikiLinkRe = /(!?)\[\[([^\]]*?)]]/g; return content.replace(wikiLinkRe, (fullMatch, prefix, inner) => { if (prefix === "!" && !settings.processEmbeds) { return fullMatch; } const pipeIndex = inner.indexOf("|"); if (pipeIndex === -1) return fullMatch; const linkPath = inner.slice(0, pipeIndex); const alias = inner.slice(pipeIndex + 1); if (alias !== newBasename) return fullMatch; const linkFilename = linkPath.split("/").pop(); if (linkFilename !== newFileName) return fullMatch; return `${prefix}[[${linkPath}|${oldBasename}]]`; }); } }; // src/modules/index.ts var MODULES = [ new AttachmentCleanPasteModule(), new PreserveLinkAliasesModule() ]; // src/settings.ts var import_obsidian3 = require("obsidian"); var MODULE_DEFAULTS = MODULES.reduce( (acc, mod) => { acc[mod.id] = { enabled: true, settings: { ...mod.defaultSettings } }; return acc; }, {} ); var DEFAULT_SETTINGS = { modules: MODULE_DEFAULTS }; function getModuleSettings(settings, moduleId) { var _a, _b; return (_b = (_a = settings.modules[moduleId]) == null ? void 0 : _a.settings) != null ? _b : {}; } var ZeroQSettingTab = class extends import_obsidian3.PluginSettingTab { constructor(app, plugin) { super(app, plugin); this.plugin = plugin; } display() { const { containerEl } = this; containerEl.empty(); containerEl.createEl("h1", { text: locale.settings.title }); containerEl.createEl("p", { text: locale.settings.description, attr: { style: "color: var(--text-muted); margin-bottom: 20px;" } }); for (const module2 of MODULES) { const moduleCfg = this.plugin.settings.modules[module2.id]; new import_obsidian3.Setting(containerEl).setName(module2.name).setDesc(module2.description).addToggle( (toggle) => { var _a; return toggle.setValue((_a = moduleCfg == null ? void 0 : moduleCfg.enabled) != null ? _a : true).onChange(async (value) => { if (!this.plugin.settings.modules[module2.id]) { this.plugin.settings.modules[module2.id] = { enabled: value, settings: { ...module2.defaultSettings } }; } else { this.plugin.settings.modules[module2.id].enabled = value; } await this.plugin.saveSettings(); if (value) { this.plugin.loadModule(module2); } else { this.plugin.unloadModule(module2); } }); } ); if (moduleCfg) { module2.renderInlineSettings( containerEl, moduleCfg.settings, () => this.plugin.saveSettings() ); } } } }; // src/main.ts var ZeroQoLModulesPlugin = class extends import_obsidian4.Plugin { constructor() { super(...arguments); this.loadedModules = /* @__PURE__ */ new Set(); } async onload() { await this.loadSettings(); this.addSettingTab(new ZeroQSettingTab(this.app, this)); for (const module2 of MODULES) { const moduleCfg = this.settings.modules[module2.id]; if (moduleCfg == null ? void 0 : moduleCfg.enabled) { this.loadModule(module2); } } } onunload() { for (const module2 of MODULES) { this.unloadModule(module2); } } async loadSettings() { this.settings = Object.assign( {}, DEFAULT_SETTINGS, await this.loadData() ); for (const module2 of MODULES) { if (!this.settings.modules[module2.id]) { this.settings.modules[module2.id] = { enabled: true, settings: { ...module2.defaultSettings } }; } } } async saveSettings() { await this.saveData(this.settings); } loadModule(module2) { if (this.loadedModules.has(module2.id)) return; const moduleSettings = getModuleSettings(this.settings, module2.id); module2.onload(this, moduleSettings); this.loadedModules.add(module2.id); } unloadModule(module2) { if (!this.loadedModules.has(module2.id)) return; module2.onunload(this); this.loadedModules.delete(module2.id); } };