/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/

"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __esm = (fn, res) => function __init() {
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
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/utils/frontmatter.ts
var frontmatter_exports = {};
__export(frontmatter_exports, {
  getFrontmatter: () => getFrontmatter,
  getFrontmatterSync: () => getFrontmatterSync,
  isFileTypeSupported: () => isFileTypeSupported
});
async function getFrontmatter(app, file, settings) {
  if (file.extension === "md") {
    const fileCache = app.metadataCache.getFileCache(file);
    return (fileCache == null ? void 0 : fileCache.frontmatter) || null;
  }
  if (file.extension === "mdx" && settings.enableMdxSupport) {
    try {
      const content = await app.vault.read(file);
      const frontmatterRegex = /^---\n([\s\S]*?)\n---/;
      const match = content.match(frontmatterRegex);
      if (match && match[1]) {
        const frontmatterText = match[1];
        try {
          const parsed = (0, import_obsidian.parseYaml)(frontmatterText);
          return parsed && typeof parsed === "object" ? parsed : null;
        } catch (parseError) {
          console.error("MDX YAML parse error:", parseError);
          return null;
        }
      }
      return null;
    } catch (readError) {
      console.error("Error reading MDX file:", readError);
      return null;
    }
  }
  return null;
}
function getFrontmatterSync(app, file, settings) {
  if (file.extension === "md") {
    const fileCache = app.metadataCache.getFileCache(file);
    return (fileCache == null ? void 0 : fileCache.frontmatter) || null;
  }
  if (file.extension === "mdx" && settings.enableMdxSupport) {
    return null;
  }
  return null;
}
function isFileTypeSupported(extension, settings) {
  if (extension === "md") {
    return true;
  }
  if (extension === "mdx") {
    return settings.enableMdxSupport;
  }
  return false;
}
var import_obsidian;
var init_frontmatter = __esm({
  "src/utils/frontmatter.ts"() {
    "use strict";
    import_obsidian = require("obsidian");
  }
});

// src/utils/search.ts
async function buildFileCache(files, metadataCache, app, propertyKey, settings) {
  const cache = /* @__PURE__ */ new Map();
  const { getFrontmatter: getFrontmatter2 } = await Promise.resolve().then(() => (init_frontmatter(), frontmatter_exports));
  await Promise.all(files.map(async (file) => {
    if (!isFileTypeSupported(file.extension, settings)) {
      return;
    }
    let frontmatter;
    if (file.extension === "md") {
      const fileCache = app.metadataCache.getFileCache(file);
      frontmatter = (fileCache == null ? void 0 : fileCache.frontmatter) || null;
    } else {
      frontmatter = await getFrontmatter2(app, file, settings);
    }
    let displayName = file.basename;
    let isCustomDisplay = false;
    let aliases = [];
    if (frontmatter && frontmatter[propertyKey] !== void 0 && frontmatter[propertyKey] !== null) {
      const propertyValueRaw = frontmatter[propertyKey];
      let propertyValue;
      if (typeof propertyValueRaw === "string") {
        propertyValue = propertyValueRaw.trim();
      } else if (typeof propertyValueRaw === "number" || typeof propertyValueRaw === "boolean") {
        propertyValue = String(propertyValueRaw).trim();
      } else {
        propertyValue = "";
      }
      if (propertyValue && propertyValue !== "") {
        displayName = propertyValue;
        isCustomDisplay = true;
      }
    }
    if (frontmatter == null ? void 0 : frontmatter.aliases) {
      const aliasesRaw = frontmatter.aliases;
      aliases = Array.isArray(aliasesRaw) ? aliasesRaw.map((a) => String(a)) : [String(aliasesRaw)];
      aliases = aliases.map((alias) => alias.trim()).filter((alias) => alias !== "");
    }
    cache.set(file.path, {
      file,
      displayName,
      aliases,
      lastModified: file.stat.mtime,
      isCustomDisplay
    });
  }));
  return cache;
}
function isExcluded(file, app) {
  var _a;
  const metadataCache = app.metadataCache;
  if (typeof metadataCache.isExcludedFile === "function") {
    try {
      if (metadataCache.isExcludedFile(file)) return true;
      if (metadataCache.isExcludedFile(file.path)) return true;
    } catch (e) {
    }
  }
  try {
    const vault = app.vault;
    const filters = (_a = vault.getConfig) == null ? void 0 : _a.call(vault, "userIgnoreFilters");
    if (Array.isArray(filters)) {
      const path = file.path;
      for (const filter of filters) {
        if (!filter) continue;
        if (typeof filter === "string" && filter.endsWith("/")) {
          if (path.startsWith(filter)) return true;
        } else if (typeof filter === "string") {
          if (path === filter || path.startsWith(filter + "/")) return true;
        }
      }
    }
  } catch (e) {
  }
  return false;
}
var init_search = __esm({
  "src/utils/search.ts"() {
    "use strict";
    init_frontmatter();
  }
});

// src/ui/QuickSwitchModal.ts
var QuickSwitchModal_exports = {};
__export(QuickSwitchModal_exports, {
  QuickSwitchModal: () => QuickSwitchModal
});
var import_obsidian4, QuickSwitchModal;
var init_QuickSwitchModal = __esm({
  "src/ui/QuickSwitchModal.ts"() {
    "use strict";
    import_obsidian4 = require("obsidian");
    init_search();
    init_frontmatter();
    QuickSwitchModal = class extends import_obsidian4.FuzzySuggestModal {
      constructor(app, plugin) {
        super(app);
        this.fileCache = /* @__PURE__ */ new Map();
        this.recentFiles = [];
        this.searchTimeout = null;
        this.matchReasons = /* @__PURE__ */ new Map();
        this.plugin = plugin;
        this.limit = 8;
        if (this.plugin.settings.enableForQuickSwitcher) {
          this.setPlaceholder("Type to search notes by title or file name...");
        } else {
          this.setPlaceholder("Type to search files...");
        }
        void this.buildFileCache();
        this.updateRecentFiles();
        this.addKeyboardNavigation();
        this.addFooter();
        if (this.plugin.settings.enableForQuickSwitcher) {
          this.containerEl.addClass("property-over-filename-modal");
        }
      }
      addKeyboardNavigation() {
        this.inputEl.addEventListener("keydown", (e) => {
          if (e.key === "Escape") {
            this.close();
            e.preventDefault();
            e.stopPropagation();
          }
        });
      }
      addFooter() {
        const promptContainer = this.containerEl.querySelector(".prompt");
        if (promptContainer) {
          const footer = promptContainer.createDiv({ cls: "prompt-instructions" });
          const instructions = [
            { command: "\u2191\u2193", action: "to navigate" },
            { command: "\u21B5", action: "to open" },
            { command: "ctrl \u21B5", action: "to open in new tab" },
            { command: "ctrl alt \u21B5", action: "to open to the right" },
            { command: "shift \u21B5", action: "to create" },
            { command: "esc", action: "to dismiss" }
          ];
          instructions.forEach(({ command, action }) => {
            const instruction = footer.createDiv({ cls: "prompt-instruction" });
            instruction.createSpan({ cls: "prompt-instruction-command", text: command });
            instruction.createSpan({ text: action });
          });
        }
      }
      async buildFileCache() {
        const files = this.getFilteredFiles();
        this.fileCache = await buildFileCache(
          files,
          this.app.metadataCache,
          this.app,
          this.plugin.settings.propertyKey,
          this.plugin.settings
        );
      }
      async updateFileCache(file) {
        const { getFrontmatter: getFrontmatter2, isFileTypeSupported: isFileTypeSupported2 } = await Promise.resolve().then(() => (init_frontmatter(), frontmatter_exports));
        if (!isFileTypeSupported2(file.extension, this.plugin.settings)) {
          return;
        }
        const frontmatter = await getFrontmatter2(this.app, file, this.plugin.settings);
        let displayName = file.basename;
        let isCustomDisplay = false;
        let aliases = [];
        if (frontmatter && frontmatter[this.plugin.settings.propertyKey] !== void 0 && frontmatter[this.plugin.settings.propertyKey] !== null) {
          const propertyValue = String(frontmatter[this.plugin.settings.propertyKey]).trim();
          if (propertyValue !== "") {
            displayName = propertyValue;
            isCustomDisplay = true;
          }
        }
        if (frontmatter == null ? void 0 : frontmatter.aliases) {
          const aliasesRaw = frontmatter.aliases;
          aliases = Array.isArray(aliasesRaw) ? aliasesRaw.map((a) => String(a)) : [String(aliasesRaw)];
          aliases = aliases.map((alias) => alias.trim()).filter((alias) => alias !== "");
        }
        this.fileCache.set(file.path, {
          file,
          displayName,
          aliases,
          lastModified: file.stat.mtime,
          isCustomDisplay
        });
      }
      updateRecentFiles() {
        var _a, _b;
        let recentFiles = [];
        const workspace = this.app.workspace;
        const quickSwitcherOptions = this.getQuickSwitcherOptions();
        const showAttachments = (_a = quickSwitcherOptions == null ? void 0 : quickSwitcherOptions.showAttachments) != null ? _a : true;
        if ((_b = workspace.recentFileTracker) == null ? void 0 : _b.getLastOpenFiles) {
          const lastOpenFiles = workspace.recentFileTracker.getLastOpenFiles();
          recentFiles = lastOpenFiles.map((filePath) => this.app.vault.getAbstractFileByPath(filePath)).filter((file) => file instanceof import_obsidian4.TFile);
        }
        if (recentFiles.length === 0) {
          const openFiles = this.app.workspace.getLeavesOfType("markdown").map((leaf) => leaf.view).filter((view) => view instanceof import_obsidian4.MarkdownView).map((view) => view.file).filter((file) => file !== null).filter((file, index, self) => self.indexOf(file) === index);
          recentFiles = [...openFiles];
        }
        const behavior = this.plugin.settings.quickSwitcherExcludedBehavior;
        if (behavior !== "ignore") {
          recentFiles = recentFiles.filter((file) => !isExcluded(file, this.app));
        }
        if (!showAttachments) {
          recentFiles = recentFiles.filter(
            (file) => file.extension === "md" || file.extension === "mdx" && this.plugin.settings.enableMdxSupport
          );
        }
        const targetCount = 8;
        const existingPaths = new Set(recentFiles.map((f) => f.path));
        if (recentFiles.length < targetCount) {
          if (showAttachments) {
            const allFiles = this.app.vault.getFiles().filter((file) => file instanceof import_obsidian4.TFile);
            const additionalFiles = allFiles.filter((file) => !existingPaths.has(file.path)).slice(0, targetCount - recentFiles.length);
            recentFiles.push(...additionalFiles);
          } else {
            const allMarkdownFiles = this.app.vault.getMarkdownFiles();
            const mdxFiles = this.plugin.settings.enableMdxSupport ? this.app.vault.getFiles().filter(
              (f) => f instanceof import_obsidian4.TFile && f.extension === "mdx"
            ) : [];
            const allSupportedFiles = [...allMarkdownFiles, ...mdxFiles];
            const behavior2 = this.plugin.settings.quickSwitcherExcludedBehavior;
            const additionalFiles = allSupportedFiles.filter((file) => !existingPaths.has(file.path)).filter((file) => behavior2 === "ignore" || !isExcluded(file, this.app)).slice(0, targetCount - recentFiles.length);
            recentFiles.push(...additionalFiles);
          }
        }
        this.recentFiles = recentFiles.slice(0, targetCount);
      }
      getItems() {
        return this.getFilteredFiles();
      }
      getFilteredFiles() {
        const quickSwitcherOptions = this.getQuickSwitcherOptions();
        let files = this.app.vault.getMarkdownFiles();
        if (this.plugin.settings.enableMdxSupport) {
          const mdxFiles = this.app.vault.getFiles().filter(
            (f) => f instanceof import_obsidian4.TFile && f.extension === "mdx"
          );
          files = [...files, ...mdxFiles];
        }
        if (quickSwitcherOptions == null ? void 0 : quickSwitcherOptions.showAttachments) {
          const allFiles = this.app.vault.getFiles().filter((file) => file instanceof import_obsidian4.TFile);
          files = allFiles.filter(
            (file) => file instanceof import_obsidian4.TFile && (file.extension === "md" || file.extension === "mdx" && this.plugin.settings.enableMdxSupport || this.isAttachment(file))
          );
        }
        return files;
      }
      isAttachment(file) {
        const attachmentExtensions = ["png", "jpg", "jpeg", "gif", "svg", "webp", "pdf", "mp4", "mp3", "wav", "ogg", "webm"];
        return attachmentExtensions.includes(file.extension.toLowerCase());
      }
      getQuickSwitcherOptions() {
        var _a;
        try {
          const internalPlugins = this.app.internalPlugins;
          if (!internalPlugins) return null;
          const switcherPlugin = (_a = internalPlugins.getPluginById) == null ? void 0 : _a.call(internalPlugins, "switcher");
          if (!switcherPlugin || !switcherPlugin.instance) {
            return null;
          }
          return switcherPlugin.instance.options || null;
        } catch (e) {
          return null;
        }
      }
      getItemText(item) {
        if ("isNewNote" in item) {
          return item.newName;
        }
        if ("isUnresolved" in item) {
          return item.unresolvedText;
        }
        if (!this.plugin.settings.enableForQuickSwitcher) {
          return item.basename;
        }
        const display = this.getDisplayName(item);
        return display;
      }
      getDisplayName(file) {
        const cached = this.fileCache.get(file.path);
        if (cached) {
          return cached.displayName;
        }
        const frontmatter = getFrontmatterSync(this.app, file, this.plugin.settings);
        if (frontmatter) {
          const propertyValue = frontmatter[this.plugin.settings.propertyKey];
          if (propertyValue !== void 0 && propertyValue !== null) {
            const trimmed = typeof propertyValue === "string" ? propertyValue.trim() : (typeof propertyValue === "number" || typeof propertyValue === "boolean" ? String(propertyValue) : "").trim();
            if (trimmed !== "") {
              return trimmed;
            }
          }
        }
        return file.basename;
      }
      getSuggestions(query) {
        var _a;
        if (!this.plugin.settings.enableForQuickSwitcher) {
          const searchQuery2 = query.trim();
          if (!searchQuery2) {
            return this.getRecentFilesResults();
          }
          const files = this.getFilteredFiles();
          const search = this.plugin.settings.useSimpleSearch ? (0, import_obsidian4.prepareSimpleSearch)(searchQuery2) : (0, import_obsidian4.prepareFuzzySearch)(searchQuery2);
          const results = [];
          for (const file of files) {
            const match = (_a = search(file.basename)) != null ? _a : { score: 0, matches: [] };
            if (match.matches.length > 0) {
              results.push({ item: file, match });
            }
          }
          (0, import_obsidian4.sortSearchResults)(results);
          if (results.length === 0) {
            const newItem = { isNewNote: true, newName: searchQuery2 };
            results.push({
              item: newItem,
              match: { score: 1e3, matches: [[0, searchQuery2.length]] }
            });
          }
          return results.slice(0, this.limit);
        }
        const searchQuery = query.trim();
        if (this.searchTimeout) {
          clearTimeout(this.searchTimeout);
        }
        if (!searchQuery) {
          return this.getRecentFilesResults();
        }
        return this.performSearch(searchQuery);
      }
      getRecentFilesResults() {
        this.updateRecentFiles();
        this.matchReasons.clear();
        return this.recentFiles.map((file) => ({
          item: file,
          match: { score: 1e3, matches: [] }
        }));
      }
      performSearch(searchQuery) {
        var _a;
        const search = this.plugin.settings.useSimpleSearch ? (0, import_obsidian4.prepareSimpleSearch)(searchQuery) : (0, import_obsidian4.prepareFuzzySearch)(searchQuery);
        const results = [];
        this.matchReasons.clear();
        for (const cachedData of this.fileCache.values()) {
          const { file, displayName, aliases, isCustomDisplay } = cachedData;
          const matchReason = {
            matchedInTitle: false,
            matchedInFilename: false,
            matchedInAlias: false
          };
          let primaryMatch = null;
          let bestMatch = null;
          let matchType = null;
          if (isCustomDisplay) {
            primaryMatch = search(displayName);
            if (primaryMatch && primaryMatch.matches.length > 0) {
              matchReason.matchedInTitle = true;
              bestMatch = primaryMatch;
              matchType = "title";
            }
          }
          if (!matchType) {
            if (this.plugin.settings.includeFilenameInSearch && file.basename !== displayName) {
              const filenameMatch = search(file.basename);
              if (filenameMatch && filenameMatch.matches.length > 0) {
                matchReason.matchedInFilename = true;
                bestMatch = { ...filenameMatch, score: filenameMatch.score - 1 };
                matchType = "filename";
              }
            } else if (!isCustomDisplay) {
              const filenameMatch = search(file.basename);
              if (filenameMatch && filenameMatch.matches.length > 0) {
                matchReason.matchedInFilename = true;
                bestMatch = filenameMatch;
                matchType = "filename";
              }
            }
          }
          if (!matchType && this.plugin.settings.includeAliasesInSearch && aliases.length > 0) {
            for (const alias of aliases) {
              const aliasMatch = search(alias);
              if (aliasMatch && aliasMatch.matches.length > 0) {
                matchReason.matchedInAlias = true;
                matchReason.matchedAliasText = alias;
                bestMatch = { ...aliasMatch, score: aliasMatch.score - 1 };
                matchType = "alias";
                break;
              }
            }
          }
          if (bestMatch && bestMatch.matches.length > 0) {
            if (!searchQuery) {
              const behavior = this.plugin.settings.quickSwitcherExcludedBehavior;
              if (behavior !== "ignore" && isExcluded(file, this.app)) {
                continue;
              }
            }
            results.push({ item: file, match: bestMatch });
            this.matchReasons.set(file.path, matchReason);
          }
        }
        const quickSwitcherOptions = this.getQuickSwitcherOptions();
        const showExistingOnly = (_a = quickSwitcherOptions == null ? void 0 : quickSwitcherOptions.showExistingOnly) != null ? _a : false;
        if (!showExistingOnly) {
          const { unresolvedLinks } = this.app.metadataCache;
          const unresolvedSet = /* @__PURE__ */ new Set();
          for (const sourcePath in unresolvedLinks) {
            const links = Object.keys(unresolvedLinks[sourcePath]);
            links.forEach((link) => unresolvedSet.add(link));
          }
          for (const unresolved of unresolvedSet) {
            const unresolvedMatch = search(unresolved);
            if (unresolvedMatch && unresolvedMatch.matches.length > 0) {
              const unresolvedItem = { isUnresolved: true, unresolvedText: unresolved };
              results.push({
                item: unresolvedItem,
                match: unresolvedMatch
              });
            }
          }
        }
        try {
          (0, import_obsidian4.sortSearchResults)(results);
          const behavior = this.plugin.settings.quickSwitcherExcludedBehavior;
          if (behavior !== "ignore") {
            results.sort((a, b) => {
              const aFile = a.item instanceof import_obsidian4.TFile ? a.item : null;
              const bFile = b.item instanceof import_obsidian4.TFile ? b.item : null;
              const aExcluded = aFile ? isExcluded(aFile, this.app) : false;
              const bExcluded = bFile ? isExcluded(bFile, this.app) : false;
              if (aExcluded && !bExcluded) return 1;
              if (!aExcluded && bExcluded) return -1;
              return 0;
            });
          }
          let filteredResults = results;
          if (behavior === "hide") {
            filteredResults = filteredResults.filter((r) => {
              return !(r.item instanceof import_obsidian4.TFile && isExcluded(r.item, this.app));
            });
          }
          if (showExistingOnly) {
            filteredResults = filteredResults.filter((r) => {
              return r.item instanceof import_obsidian4.TFile || "isNewNote" in r.item && r.item.isNewNote === true;
            });
          }
          const lowerQuery = searchQuery.toLowerCase();
          let exactMatch = filteredResults.some(
            (r) => {
              var _a2;
              return r.item instanceof import_obsidian4.TFile && (this.getDisplayName(r.item).toLowerCase() === lowerQuery || this.plugin.settings.includeFilenameInSearch && r.item.basename.toLowerCase() === lowerQuery || this.plugin.settings.includeAliasesInSearch && ((_a2 = this.fileCache.get(r.item.path)) == null ? void 0 : _a2.aliases.some((alias) => alias.toLowerCase() === lowerQuery)));
            }
          );
          if (!showExistingOnly && !exactMatch) {
            const { unresolvedLinks } = this.app.metadataCache;
            const unresolvedSet = /* @__PURE__ */ new Set();
            for (const sourcePath in unresolvedLinks) {
              const links = Object.keys(unresolvedLinks[sourcePath]);
              links.forEach((link) => unresolvedSet.add(link));
            }
            exactMatch = Array.from(unresolvedSet).some((link) => link.toLowerCase() === lowerQuery);
          }
          if (filteredResults.length === 0 && searchQuery) {
            const newItem = { isNewNote: true, newName: searchQuery };
            filteredResults.push({
              item: newItem,
              match: { score: 1e3, matches: [[0, searchQuery.length]] }
            });
          }
          return filteredResults.slice(0, this.limit);
        } catch (e) {
          new import_obsidian4.Notice("Error updating quick switcher suggestions. Please check console for details.");
          return [];
        }
      }
      renderSuggestion(suggestion, el) {
        var _a;
        const { item } = suggestion;
        if (item instanceof import_obsidian4.TFile && this.plugin.settings.quickSwitcherExcludedBehavior === "deemphasize" && isExcluded(item, this.app)) {
          el.addClass("mod-excluded");
        }
        if ("isUnresolved" in item && item.isUnresolved) {
          const unresolvedText = item.unresolvedText;
          el.empty();
          el.addClass("mod-complex");
          const suggestionContent = el.createDiv({ cls: "suggestion-content" });
          const suggestionTitle = suggestionContent.createDiv({ cls: "suggestion-title" });
          suggestionTitle.setText(unresolvedText);
          const suggestionAux = el.createDiv({ cls: "suggestion-aux" });
          const suggestionFlair = suggestionAux.createSpan({
            cls: "suggestion-flair",
            attr: { "aria-label": "Unresolved link - Enter to create" }
          });
          this.createFilePlusIcon(suggestionFlair);
          return;
        }
        const text = this.getItemText(item);
        if ("isNewNote" in item) {
          el.empty();
          el.addClass("mod-complex");
          const suggestionContent = el.createDiv({ cls: "suggestion-content" });
          const suggestionTitle = suggestionContent.createDiv({ cls: "suggestion-title" });
          suggestionTitle.setText(text);
          const suggestionAux = el.createDiv({ cls: "suggestion-aux" });
          const suggestionAction = suggestionAux.createSpan({ cls: "suggestion-action" });
          suggestionAction.setText("Enter to create");
          return;
        }
        if (!this.plugin.settings.enableForQuickSwitcher) {
          if (item instanceof import_obsidian4.TFile) {
            el.setText(item.path.replace(".md", ""));
          } else {
            el.setText(text);
          }
        } else {
          if (!(item instanceof import_obsidian4.TFile)) {
            el.setText(text);
            return;
          }
          const cachedData = this.fileCache.get(item.path);
          const isCustomDisplay = (_a = cachedData == null ? void 0 : cachedData.isCustomDisplay) != null ? _a : false;
          const matchReason = this.matchReasons.get(item.path);
          if (!isCustomDisplay && (matchReason == null ? void 0 : matchReason.matchedInAlias) && matchReason.matchedAliasText) {
            el.addClass("mod-complex");
            const suggestionContent = el.createDiv({ cls: "suggestion-content" });
            const titleEl = suggestionContent.createDiv({ cls: "suggestion-title" });
            titleEl.setText(matchReason.matchedAliasText);
            const pathEl = suggestionContent.createDiv({ cls: "suggestion-note" });
            pathEl.setText(item.path.replace(".md", ""));
            const suggestionAux = el.createDiv({ cls: "suggestion-aux" });
            const suggestionFlair = suggestionAux.createSpan({
              cls: "suggestion-flair",
              attr: { "aria-label": "Alias Match" }
            });
            this.createForwardIcon(suggestionFlair);
          } else if (isCustomDisplay) {
            const shouldShowIcon = matchReason && (matchReason.matchedInTitle || matchReason.matchedInFilename || matchReason.matchedInAlias);
            if (shouldShowIcon) {
              el.addClass("mod-complex");
              const suggestionContent = el.createDiv({ cls: "suggestion-content" });
              const titleEl = suggestionContent.createDiv({ cls: "suggestion-title" });
              titleEl.setText(text);
              const pathEl = suggestionContent.createDiv({ cls: "suggestion-note" });
              pathEl.setText(item.path.replace(".md", ""));
              const suggestionAux = el.createDiv({ cls: "suggestion-aux" });
              const suggestionFlair = suggestionAux.createSpan({
                cls: "suggestion-flair",
                attr: { "aria-label": this.getIconLabel(matchReason) }
              });
              if (matchReason.matchedInTitle) {
                this.createTypeIcon(suggestionFlair);
              } else if (matchReason.matchedInFilename) {
                this.createFileIcon(suggestionFlair);
              } else if (matchReason.matchedInAlias) {
                this.createForwardIcon(suggestionFlair);
              }
            } else {
              el.addClass("mod-complex");
              const suggestionContent = el.createDiv({ cls: "suggestion-content" });
              const titleEl = suggestionContent.createDiv({ cls: "suggestion-title" });
              titleEl.setText(text);
              const pathEl = suggestionContent.createDiv({ cls: "suggestion-note" });
              pathEl.setText(item.path.replace(".md", ""));
              const suggestionAux = el.createDiv({ cls: "suggestion-aux" });
              const suggestionFlair = suggestionAux.createSpan({
                cls: "suggestion-flair",
                attr: { "aria-label": "Property-based title" }
              });
              this.createTypeIcon(suggestionFlair);
            }
          } else {
            el.setText(text);
          }
        }
      }
      getIconLabel(matchReason) {
        if (matchReason.matchedInTitle) {
          return "Title/Property Match";
        } else if (matchReason.matchedInFilename) {
          return "File Name Match";
        } else if (matchReason.matchedInAlias) {
          return "Alias Match";
        }
        return "Match";
      }
      createTypeIcon(container) {
        const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        svg.setAttribute("width", "24");
        svg.setAttribute("height", "24");
        svg.setAttribute("viewBox", "0 0 24 24");
        svg.setAttribute("fill", "none");
        svg.setAttribute("stroke", "currentColor");
        svg.setAttribute("stroke-width", "2");
        svg.setAttribute("stroke-linecap", "round");
        svg.setAttribute("stroke-linejoin", "round");
        svg.classList.add("svg-icon", "lucide-type");
        const polyline1 = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
        polyline1.setAttribute("points", "4 7 4 4 20 4 20 7");
        svg.appendChild(polyline1);
        const line1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
        line1.setAttribute("x1", "9");
        line1.setAttribute("y1", "20");
        line1.setAttribute("x2", "15");
        line1.setAttribute("y2", "20");
        svg.appendChild(line1);
        const line2 = document.createElementNS("http://www.w3.org/2000/svg", "line");
        line2.setAttribute("x1", "12");
        line2.setAttribute("y1", "4");
        line2.setAttribute("x2", "12");
        line2.setAttribute("y2", "20");
        svg.appendChild(line2);
        container.appendChild(svg);
      }
      createFileIcon(container) {
        const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        svg.setAttribute("width", "24");
        svg.setAttribute("height", "24");
        svg.setAttribute("viewBox", "0 0 24 24");
        svg.setAttribute("fill", "none");
        svg.setAttribute("stroke", "currentColor");
        svg.setAttribute("stroke-width", "2");
        svg.setAttribute("stroke-linecap", "round");
        svg.setAttribute("stroke-linejoin", "round");
        svg.classList.add("svg-icon", "lucide-file-text");
        const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
        path.setAttribute("d", "M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z");
        svg.appendChild(path);
        const polyline1 = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
        polyline1.setAttribute("points", "14,2 14,8 20,8");
        svg.appendChild(polyline1);
        const line1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
        line1.setAttribute("x1", "16");
        line1.setAttribute("y1", "13");
        line1.setAttribute("x2", "8");
        line1.setAttribute("y2", "13");
        svg.appendChild(line1);
        const line2 = document.createElementNS("http://www.w3.org/2000/svg", "line");
        line2.setAttribute("x1", "16");
        line2.setAttribute("y1", "17");
        line2.setAttribute("x2", "8");
        line2.setAttribute("y2", "17");
        svg.appendChild(line2);
        const polyline2 = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
        polyline2.setAttribute("points", "10,9 9,9 8,9");
        svg.appendChild(polyline2);
        container.appendChild(svg);
      }
      createForwardIcon(container) {
        const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        svg.setAttribute("width", "24");
        svg.setAttribute("height", "24");
        svg.setAttribute("viewBox", "0 0 24 24");
        svg.setAttribute("fill", "none");
        svg.setAttribute("stroke", "currentColor");
        svg.setAttribute("stroke-width", "2");
        svg.setAttribute("stroke-linecap", "round");
        svg.setAttribute("stroke-linejoin", "round");
        svg.classList.add("svg-icon", "lucide-forward");
        const polyline = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
        polyline.setAttribute("points", "15 17 20 12 15 7");
        svg.appendChild(polyline);
        const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
        path.setAttribute("d", "M4 18v-2a4 4 0 0 1 4-4h12");
        svg.appendChild(path);
        container.appendChild(svg);
      }
      createFilePlusIcon(container) {
        const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        svg.setAttribute("width", "24");
        svg.setAttribute("height", "24");
        svg.setAttribute("viewBox", "0 0 24 24");
        svg.setAttribute("fill", "none");
        svg.setAttribute("stroke", "currentColor");
        svg.setAttribute("stroke-width", "2");
        svg.setAttribute("stroke-linecap", "round");
        svg.setAttribute("stroke-linejoin", "round");
        svg.classList.add("svg-icon", "lucide-file-plus");
        const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
        path.setAttribute("d", "M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z");
        svg.appendChild(path);
        const polyline = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
        polyline.setAttribute("points", "14,2 14,8 20,8");
        svg.appendChild(polyline);
        const line1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
        line1.setAttribute("x1", "12");
        line1.setAttribute("y1", "18");
        line1.setAttribute("x2", "12");
        line1.setAttribute("y2", "12");
        svg.appendChild(line1);
        const line2 = document.createElementNS("http://www.w3.org/2000/svg", "line");
        line2.setAttribute("x1", "9");
        line2.setAttribute("y1", "15");
        line2.setAttribute("x2", "15");
        line2.setAttribute("y2", "15");
        svg.appendChild(line2);
        container.appendChild(svg);
      }
      isUsingCustomProperty(file) {
        const cache = this.app.metadataCache.getFileCache(file);
        const frontmatter = cache == null ? void 0 : cache.frontmatter;
        const propertyValue = frontmatter == null ? void 0 : frontmatter[this.plugin.settings.propertyKey];
        if (propertyValue === void 0 || propertyValue === null) {
          return false;
        }
        const strValue = typeof propertyValue === "string" ? propertyValue : typeof propertyValue === "number" || typeof propertyValue === "boolean" ? String(propertyValue) : "";
        return strValue.trim() !== "";
      }
      isUsingAlias(file) {
        const cache = this.app.metadataCache.getFileCache(file);
        const frontmatter = cache == null ? void 0 : cache.frontmatter;
        const aliases = frontmatter == null ? void 0 : frontmatter.aliases;
        if (!aliases) return false;
        const isUsingCustomProperty = this.isUsingCustomProperty(file);
        return !isUsingCustomProperty && Boolean(aliases);
      }
      onChooseItem(item, evt) {
        var _a, _b, _c;
        if ("isUnresolved" in item && item.isUnresolved) {
          const unresolvedText = item.unresolvedText;
          const activeView = this.app.workspace.getActiveViewOfType(import_obsidian4.MarkdownView);
          const sourcePath = ((_a = activeView == null ? void 0 : activeView.file) == null ? void 0 : _a.path) || "";
          void this.app.workspace.openLinkText(unresolvedText, sourcePath).catch((err) => {
            const message = err instanceof Error ? err.message : String(err);
            new import_obsidian4.Notice(`Error creating note: ${message}`);
          });
          return;
        }
        if ("isNewNote" in item) {
          const activeView = this.app.workspace.getActiveViewOfType(import_obsidian4.MarkdownView);
          const sourcePath = ((_b = activeView == null ? void 0 : activeView.file) == null ? void 0 : _b.path) || "";
          void this.app.workspace.openLinkText(item.newName, sourcePath).catch((err) => {
            const message = err instanceof Error ? err.message : String(err);
            new import_obsidian4.Notice(`Error creating note: ${message}`);
          });
        } else if (item instanceof import_obsidian4.TFile) {
          if (evt instanceof KeyboardEvent) {
            if (evt.ctrlKey && evt.altKey) {
              const leaf = this.app.workspace.getLeaf(true);
              void leaf.openFile(item);
            } else if (evt.ctrlKey) {
              void this.app.workspace.getLeaf().openFile(item);
            } else if (evt.shiftKey) {
              const activeView = this.app.workspace.getActiveViewOfType(import_obsidian4.MarkdownView);
              const sourcePath = ((_c = activeView == null ? void 0 : activeView.file) == null ? void 0 : _c.path) || "";
              const currentQuery = this.inputEl.value.trim();
              if (currentQuery) {
                void this.app.workspace.openLinkText(currentQuery, sourcePath).catch((err) => {
                  const message = err instanceof Error ? err.message : String(err);
                  new import_obsidian4.Notice(`Error creating note: ${message}`);
                });
              } else {
                void this.app.workspace.getLeaf().openFile(item);
              }
            } else {
              void this.app.workspace.getLeaf().openFile(item);
            }
          } else {
            void this.app.workspace.getLeaf().openFile(item);
          }
        }
      }
    };
  }
});

// src/main.ts
var main_exports = {};
__export(main_exports, {
  default: () => PropertyOverFileNamePlugin
});
module.exports = __toCommonJS(main_exports);
var import_obsidian12 = require("obsidian");

// src/settings.ts
var DEFAULT_SETTINGS = {
  propertyKey: "title",
  enableForLinking: true,
  enableForQuickSwitcher: true,
  includeFilenameInSearch: true,
  includeAliasesInSearch: true,
  enableForDragDrop: true,
  useSimpleSearch: false,
  enableForGraphView: true,
  enableForBacklinks: true,
  hideUnlinkedMentionsInBacklinks: false,
  enableForTabs: true,
  enableForExplorer: false,
  folderNoteFilename: "",
  enableForWindowFrame: true,
  enableForBookmarks: true,
  enableMdxSupport: false,
  quickSwitcherExcludedBehavior: "deemphasize",
  linkSuggesterExcludedBehavior: "deemphasize"
};

// src/ui/LinkTitleSuggest.ts
var import_obsidian2 = require("obsidian");
init_search();
var LinkTitleSuggest = class extends import_obsidian2.EditorSuggest {
  constructor(plugin) {
    super(plugin.app);
    this.fileCache = /* @__PURE__ */ new Map();
    this.searchTimeout = null;
    this.matchReasons = /* @__PURE__ */ new Map();
    this.plugin = plugin;
    void this.buildFileCache();
  }
  open() {
    super.open();
    const el = this.suggestEl;
    if (el) {
      el.addClass("property-over-filename-suggestion");
      if (!el.querySelector(".prompt-instructions")) {
        const instructions = el.createDiv({ cls: "prompt-instructions" });
        instructions.createDiv({ cls: "prompt-instruction" }).setText("Type # to link heading");
        instructions.createDiv({ cls: "prompt-instruction" }).setText("Type ^ to link blocks");
        instructions.createDiv({ cls: "prompt-instruction" }).setText("Type | to change display text");
      }
    }
    this.addKeyboardNavigation();
  }
  addKeyboardNavigation() {
    const el = this.suggestEl;
    if (!el) return;
    el.addEventListener("keydown", (e) => {
      if (e.key === "Escape") {
        this.close();
        e.preventDefault();
        e.stopPropagation();
      }
    });
  }
  onTrigger(cursor, editor, file) {
    if (!this.plugin.settings.enableForLinking) return null;
    const line = editor.getLine(cursor.line).substring(0, cursor.ch);
    const match = /\[\[([^#^|\]]*)$/.exec(line);
    if (match) {
      return {
        start: { line: cursor.line, ch: line.lastIndexOf("[[") },
        end: cursor,
        query: match[1]
      };
    }
    return null;
  }
  async buildFileCache() {
    const mdFiles = this.app.vault.getMarkdownFiles();
    const allFiles = [...mdFiles];
    if (this.plugin.settings.enableMdxSupport) {
      const mdxFiles = this.app.vault.getFiles().filter(
        (f) => f instanceof import_obsidian2.TFile && f.extension === "mdx"
      );
      allFiles.push(...mdxFiles);
    }
    this.fileCache = await buildFileCache(
      allFiles,
      this.app.metadataCache,
      this.app,
      this.plugin.settings.propertyKey,
      this.plugin.settings
    );
  }
  async updateFileCache(file) {
    const { getFrontmatter: getFrontmatter2, isFileTypeSupported: isFileTypeSupported2 } = await Promise.resolve().then(() => (init_frontmatter(), frontmatter_exports));
    if (!isFileTypeSupported2(file.extension, this.plugin.settings)) {
      return;
    }
    const frontmatter = await getFrontmatter2(this.app, file, this.plugin.settings);
    let displayName = file.basename;
    let isCustomDisplay = false;
    let aliases = [];
    if (frontmatter && frontmatter[this.plugin.settings.propertyKey] !== void 0 && frontmatter[this.plugin.settings.propertyKey] !== null) {
      const propertyValue = String(frontmatter[this.plugin.settings.propertyKey]).trim();
      if (propertyValue !== "") {
        displayName = propertyValue;
        isCustomDisplay = true;
      }
    }
    if (frontmatter == null ? void 0 : frontmatter.aliases) {
      const aliasesRaw = frontmatter.aliases;
      aliases = Array.isArray(aliasesRaw) ? aliasesRaw.map((a) => String(a)) : [String(aliasesRaw)];
      aliases = aliases.map((alias) => alias.trim()).filter((alias) => alias !== "");
    }
    this.fileCache.set(file.path, {
      file,
      displayName,
      aliases,
      lastModified: file.stat.mtime,
      isCustomDisplay
    });
  }
  getSuggestions(context) {
    const query = context.query.trim();
    return this.performSearch(query);
  }
  performSearch(query) {
    var _a;
    if (!query || query.trim() === "") {
      const behavior2 = this.plugin.settings.linkSuggesterExcludedBehavior;
      const suggestions2 = Array.from(this.fileCache.values()).filter((cached) => behavior2 === "ignore" || !isExcluded(cached.file, this.app)).sort((a, b) => b.lastModified - a.lastModified).slice(0, 10).map((cached) => ({
        file: cached.file,
        display: cached.displayName,
        isCustomDisplay: cached.isCustomDisplay
      }));
      return suggestions2;
    }
    const search = this.plugin.settings.useSimpleSearch ? (0, import_obsidian2.prepareSimpleSearch)(query) : (0, import_obsidian2.prepareFuzzySearch)(query);
    const searchableSuggestions = [];
    this.matchReasons.clear();
    for (const cachedData of this.fileCache.values()) {
      const { file, displayName, aliases, isCustomDisplay } = cachedData;
      const matchReason = {
        matchedInTitle: false,
        matchedInFilename: false,
        matchedInAlias: false
      };
      let primaryMatch = null;
      let bestMatch = null;
      let matchType = null;
      if (isCustomDisplay) {
        primaryMatch = search(displayName);
        if (primaryMatch && primaryMatch.matches.length > 0) {
          matchReason.matchedInTitle = true;
          bestMatch = primaryMatch;
          matchType = "title";
        }
      }
      if (!matchType) {
        if (this.plugin.settings.includeFilenameInSearch && file.basename !== displayName) {
          const filenameMatch = search(file.basename);
          if (filenameMatch && filenameMatch.matches.length > 0) {
            matchReason.matchedInFilename = true;
            bestMatch = { ...filenameMatch, score: filenameMatch.score - 1 };
            matchType = "filename";
          }
        } else if (!isCustomDisplay) {
          const filenameMatch = search(file.basename);
          if (filenameMatch && filenameMatch.matches.length > 0) {
            matchReason.matchedInFilename = true;
            bestMatch = filenameMatch;
            matchType = "filename";
          }
        }
      }
      if (!matchType && this.plugin.settings.includeAliasesInSearch && aliases.length > 0) {
        for (const alias of aliases) {
          const aliasMatch = search(alias);
          if (aliasMatch && aliasMatch.matches.length > 0) {
            matchReason.matchedInAlias = true;
            matchReason.matchedAliasText = alias;
            bestMatch = { ...aliasMatch, score: aliasMatch.score - 1 };
            matchType = "alias";
            break;
          }
        }
      }
      if (bestMatch && bestMatch.matches.length > 0) {
        if (!query) {
          const behavior2 = this.plugin.settings.linkSuggesterExcludedBehavior;
          if (behavior2 !== "ignore" && isExcluded(file, this.app)) {
            continue;
          }
        }
        const suggestion = {
          file,
          display: displayName,
          isCustomDisplay
        };
        searchableSuggestions.push({ item: suggestion, match: bestMatch });
        this.matchReasons.set(file.path, matchReason);
      }
    }
    const quickSwitcherOptions = this.getQuickSwitcherOptions();
    const showExistingOnly = (_a = quickSwitcherOptions == null ? void 0 : quickSwitcherOptions.showExistingOnly) != null ? _a : false;
    if (!showExistingOnly) {
      const { unresolvedLinks } = this.app.metadataCache;
      const unresolvedSet = /* @__PURE__ */ new Set();
      for (const sourcePath in unresolvedLinks) {
        const links = Object.keys(unresolvedLinks[sourcePath]);
        links.forEach((link) => unresolvedSet.add(link));
      }
      for (const unresolved of unresolvedSet) {
        const unresolvedMatch = search(unresolved);
        if (unresolvedMatch && unresolvedMatch.matches.length > 0) {
          searchableSuggestions.push({
            item: {
              display: unresolved,
              isCustomDisplay: false
              // No file property means it's unresolved
            },
            match: unresolvedMatch
          });
        }
      }
    }
    const behavior = this.plugin.settings.linkSuggesterExcludedBehavior;
    if (behavior !== "ignore") {
      searchableSuggestions.sort((a, b) => {
        const aFile = a.item.file;
        const bFile = b.item.file;
        const aExcluded = aFile ? isExcluded(aFile, this.app) : false;
        const bExcluded = bFile ? isExcluded(bFile, this.app) : false;
        if (aExcluded && !bExcluded) return 1;
        if (!aExcluded && bExcluded) return -1;
        return 0;
      });
    }
    let suggestions = searchableSuggestions.map((s) => s.item);
    if (behavior === "hide") {
      suggestions = suggestions.filter((s) => {
        return !(s.file && isExcluded(s.file, this.app));
      });
    }
    if (showExistingOnly) {
      suggestions = suggestions.filter((s) => s.file !== void 0);
    }
    if (suggestions.length === 0 && query) {
      suggestions.push({
        display: "No match found",
        isCustomDisplay: false,
        isNoMatch: true
      });
    }
    return suggestions;
  }
  renderSuggestion(suggestion, el) {
    el.empty();
    if (suggestion.file && this.plugin.settings.linkSuggesterExcludedBehavior === "deemphasize" && isExcluded(suggestion.file, this.app)) {
      el.addClass("mod-excluded");
    }
    if (suggestion.isNoMatch) {
      el.setText(suggestion.display);
      return;
    }
    if (suggestion.file) {
      const matchReason = this.matchReasons.get(suggestion.file.path);
      if (!suggestion.isCustomDisplay && (matchReason == null ? void 0 : matchReason.matchedInAlias) && matchReason.matchedAliasText) {
        el.addClass("mod-complex");
        const suggestionContent = el.createDiv({ cls: "suggestion-content" });
        const titleEl = suggestionContent.createDiv({ cls: "suggestion-title" });
        titleEl.setText(matchReason.matchedAliasText);
        const pathEl = suggestionContent.createDiv({ cls: "suggestion-note" });
        pathEl.setText(suggestion.file.path.replace(".md", ""));
        const suggestionAux = el.createDiv({ cls: "suggestion-aux" });
        const suggestionFlair = suggestionAux.createSpan({
          cls: "suggestion-flair",
          attr: { "aria-label": "Alias Match" }
        });
        this.createForwardIcon(suggestionFlair);
      } else if (suggestion.isCustomDisplay) {
        const shouldShowIcon = matchReason && (matchReason.matchedInTitle || matchReason.matchedInFilename || matchReason.matchedInAlias);
        if (shouldShowIcon) {
          el.addClass("mod-complex");
          const suggestionContent = el.createDiv({ cls: "suggestion-content" });
          const titleEl = suggestionContent.createDiv({ cls: "suggestion-title" });
          titleEl.setText(suggestion.display);
          const pathEl = suggestionContent.createDiv({ cls: "suggestion-note" });
          pathEl.setText(suggestion.file.path.replace(".md", ""));
          const suggestionAux = el.createDiv({ cls: "suggestion-aux" });
          const suggestionFlair = suggestionAux.createSpan({
            cls: "suggestion-flair",
            attr: { "aria-label": this.getIconLabel(matchReason) }
          });
          if (matchReason.matchedInTitle) {
            this.createTypeIcon(suggestionFlair);
          } else if (matchReason.matchedInFilename) {
            this.createFileIcon(suggestionFlair);
          } else if (matchReason.matchedInAlias) {
            this.createForwardIcon(suggestionFlair);
          }
        } else {
          el.setText(suggestion.display);
        }
      } else {
        el.setText(suggestion.display);
      }
    }
  }
  getIconLabel(matchReason) {
    if (matchReason.matchedInTitle) {
      return "Title/Property Match";
    } else if (matchReason.matchedInFilename) {
      return "File Name Match";
    } else if (matchReason.matchedInAlias) {
      return "Alias Match";
    }
    return "Match";
  }
  createTypeIcon(container) {
    const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
    svg.setAttribute("width", "24");
    svg.setAttribute("height", "24");
    svg.setAttribute("viewBox", "0 0 24 24");
    svg.setAttribute("fill", "none");
    svg.setAttribute("stroke", "currentColor");
    svg.setAttribute("stroke-width", "2");
    svg.setAttribute("stroke-linecap", "round");
    svg.setAttribute("stroke-linejoin", "round");
    svg.classList.add("svg-icon", "lucide-type");
    const polyline1 = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
    polyline1.setAttribute("points", "4 7 4 4 20 4 20 7");
    svg.appendChild(polyline1);
    const line1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
    line1.setAttribute("x1", "9");
    line1.setAttribute("y1", "20");
    line1.setAttribute("x2", "15");
    line1.setAttribute("y2", "20");
    svg.appendChild(line1);
    const line2 = document.createElementNS("http://www.w3.org/2000/svg", "line");
    line2.setAttribute("x1", "12");
    line2.setAttribute("y1", "4");
    line2.setAttribute("x2", "12");
    line2.setAttribute("y2", "20");
    svg.appendChild(line2);
    container.appendChild(svg);
  }
  createFileIcon(container) {
    const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
    svg.setAttribute("width", "24");
    svg.setAttribute("height", "24");
    svg.setAttribute("viewBox", "0 0 24 24");
    svg.setAttribute("fill", "none");
    svg.setAttribute("stroke", "currentColor");
    svg.setAttribute("stroke-width", "2");
    svg.setAttribute("stroke-linecap", "round");
    svg.setAttribute("stroke-linejoin", "round");
    svg.classList.add("svg-icon", "lucide-file-text");
    const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
    path.setAttribute("d", "M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z");
    svg.appendChild(path);
    const polyline1 = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
    polyline1.setAttribute("points", "14,2 14,8 20,8");
    svg.appendChild(polyline1);
    const line1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
    line1.setAttribute("x1", "16");
    line1.setAttribute("y1", "13");
    line1.setAttribute("x2", "8");
    line1.setAttribute("y2", "13");
    svg.appendChild(line1);
    const line2 = document.createElementNS("http://www.w3.org/2000/svg", "line");
    line2.setAttribute("x1", "16");
    line2.setAttribute("y1", "17");
    line2.setAttribute("x2", "8");
    line2.setAttribute("y2", "17");
    svg.appendChild(line2);
    const polyline2 = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
    polyline2.setAttribute("points", "10,9 9,9 8,9");
    svg.appendChild(polyline2);
    container.appendChild(svg);
  }
  createForwardIcon(container) {
    const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
    svg.setAttribute("width", "24");
    svg.setAttribute("height", "24");
    svg.setAttribute("viewBox", "0 0 24 24");
    svg.setAttribute("fill", "none");
    svg.setAttribute("stroke", "currentColor");
    svg.setAttribute("stroke-width", "2");
    svg.setAttribute("stroke-linecap", "round");
    svg.setAttribute("stroke-linejoin", "round");
    svg.classList.add("svg-icon", "lucide-forward");
    const polyline = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
    polyline.setAttribute("points", "15 17 20 12 15 7");
    svg.appendChild(polyline);
    const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
    path.setAttribute("d", "M4 18v-2a4 4 0 0 1 4-4h12");
    svg.appendChild(path);
    container.appendChild(svg);
  }
  isUsingCustomProperty(file) {
    const cache = this.app.metadataCache.getFileCache(file);
    const frontmatter = cache == null ? void 0 : cache.frontmatter;
    const propertyValue = frontmatter == null ? void 0 : frontmatter[this.plugin.settings.propertyKey];
    if (propertyValue === void 0 || propertyValue === null) {
      return false;
    }
    const strValue = typeof propertyValue === "string" ? propertyValue : typeof propertyValue === "number" || typeof propertyValue === "boolean" ? String(propertyValue) : "";
    return strValue.trim() !== "";
  }
  isUsingAlias(file) {
    const cache = this.app.metadataCache.getFileCache(file);
    const frontmatter = cache == null ? void 0 : cache.frontmatter;
    const aliases = frontmatter == null ? void 0 : frontmatter.aliases;
    if (!aliases) return false;
    const isUsingCustomProperty = this.isUsingCustomProperty(file);
    return !isUsingCustomProperty && Boolean(aliases);
  }
  selectSuggestion(suggestion, evt) {
    var _a, _b;
    if (suggestion.isNoMatch) {
      return;
    }
    const activeView = this.app.workspace.getActiveViewOfType(import_obsidian2.MarkdownView);
    if (!activeView || !this.context) return;
    const editor = activeView.editor;
    const { start, end } = this.context;
    const line = editor.getLine(start.line);
    let endPos = end;
    if (line.slice(end.ch, end.ch + 2) === "]]") {
      endPos = { line: end.line, ch: end.ch + 2 };
    }
    if (!suggestion.file) {
      return;
    }
    const vault = this.app.vault;
    const useMarkdownLinks = (_b = (_a = vault.getConfig) == null ? void 0 : _a.call(vault, "useMarkdownLinks")) != null ? _b : false;
    let linkText;
    if (suggestion.isCustomDisplay) {
      if (useMarkdownLinks) {
        linkText = `[${suggestion.display}](${encodeURI(suggestion.file.path)})`;
      } else {
        const linkPath = suggestion.file.path.replace(".md", "");
        linkText = `[[${linkPath}|${suggestion.display}]]`;
      }
    } else {
      if (useMarkdownLinks) {
        linkText = `[${suggestion.file.path.replace(".md", "")}](${encodeURI(suggestion.file.path)})`;
      } else {
        const linkPath = suggestion.file.path.replace(".md", "");
        linkText = `[[${linkPath}]]`;
      }
    }
    editor.replaceRange(linkText, { line: start.line, ch: start.ch }, endPos);
    const newCursorPos = start.ch + linkText.length;
    try {
      editor.setCursor({ line: start.line, ch: newCursorPos });
    } catch (e) {
      new import_obsidian2.Notice("Error setting cursor position. Please check console for details.");
    }
  }
  getQuickSwitcherOptions() {
    var _a;
    try {
      const internalPlugins = this.app.internalPlugins;
      if (!internalPlugins) return null;
      const switcherPlugin = (_a = internalPlugins.getPluginById) == null ? void 0 : _a.call(internalPlugins, "switcher");
      if (!switcherPlugin || !switcherPlugin.instance) {
        return null;
      }
      return switcherPlugin.instance.options || null;
    } catch (e) {
      return null;
    }
  }
};

// src/ui/SettingTab.ts
var import_obsidian3 = require("obsidian");
var SettingTab = class extends import_obsidian3.PluginSettingTab {
  constructor(app, plugin) {
    super(app, plugin);
    this.icon = "lucide-type";
    this.plugin = plugin;
  }
  display() {
    const { containerEl } = this;
    containerEl.empty();
    containerEl.addClass("property-over-filename-settings");
    const generalGroup = new import_obsidian3.SettingGroup(containerEl);
    generalGroup.addSetting((setting) => {
      setting.setName("Property key").setDesc("The property to use as the display title. Falls back to the file name when no property is set for that item.").addText(
        (text) => text.setPlaceholder("Title").setValue(this.plugin.settings.propertyKey).onChange(async (value) => {
          this.plugin.settings.propertyKey = value.trim() || "title";
          await this.plugin.saveData(this.plugin.settings);
          this.plugin.updateLinkSuggester();
          this.plugin.updateGraphView();
          this.plugin.updateBacklinks();
          this.plugin.updateTabs();
          this.plugin.updateExplorer();
          this.plugin.updateWindowFrame();
          this.plugin.updateBookmarks();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("When linking notes").setDesc("Enable property-based titles in the link suggester.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.enableForLinking).onChange(async (value) => {
          this.plugin.settings.enableForLinking = value;
          await this.plugin.saveData(this.plugin.settings);
          this.plugin.updateLinkSuggester();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("In quick switcher").setDesc("Enable property-based titles in the quick switcher.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.enableForQuickSwitcher).onChange(async (value) => {
          const prevQuickSwitcherState = this.plugin.settings.enableForQuickSwitcher;
          this.plugin.settings.enableForQuickSwitcher = value;
          await this.plugin.saveSettings(prevQuickSwitcherState);
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("Include file name in fuzzy searches").setDesc("Include note file names in fuzzy search results for link suggester and quick switcher.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.includeFilenameInSearch).onChange(async (value) => {
          this.plugin.settings.includeFilenameInSearch = value;
          await this.plugin.saveData(this.plugin.settings);
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("Include aliases in fuzzy searches").setDesc("Include property aliases in fuzzy search results for link suggester and quick switcher.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.includeAliasesInSearch).onChange(async (value) => {
          this.plugin.settings.includeAliasesInSearch = value;
          await this.plugin.saveData(this.plugin.settings);
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("When dragging notes").setDesc("Use property-based titles when dragging notes from the file explorer.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.enableForDragDrop).onChange(async (value) => {
          this.plugin.settings.enableForDragDrop = value;
          await this.plugin.saveData(this.plugin.settings);
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("When naming bookmarks").setDesc("Automatically use the configured property value as the default name when creating a bookmark.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.enableForBookmarks).onChange(async (value) => {
          this.plugin.settings.enableForBookmarks = value;
          await this.plugin.saveData(this.plugin.settings);
          this.plugin.updateBookmarks();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("In graph view").setDesc("Use the property instead of the file name as the note's title in graph view.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.enableForGraphView).onChange(async (value) => {
          this.plugin.settings.enableForGraphView = value;
          await this.plugin.saveSettings();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("In backlinks and outgoing links").setDesc("Use the property instead of the file name in the linked mentions footer, dedicated backlinks panel, and outgoing links.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.enableForBacklinks).onChange(async (value) => {
          this.plugin.settings.enableForBacklinks = value;
          await this.plugin.saveData(this.plugin.settings);
          this.plugin.updateBacklinks();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("Hide unlinked mentions (backlinks panel)").setDesc("Hide the \u201CUnlinked mentions\u201D section in the backlinks panel and skip processing it. Useful for folder-note setups where file names like `index` make unlinked mentions noisy.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.hideUnlinkedMentionsInBacklinks).onChange(async (value) => {
          this.plugin.settings.hideUnlinkedMentionsInBacklinks = value;
          await this.plugin.saveData(this.plugin.settings);
          this.plugin.updateBacklinks();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("In tab titles").setDesc("Use the property instead of the file name in tab titles.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.enableForTabs).onChange(async (value) => {
          const prevTabState = this.plugin.settings.enableForTabs;
          this.plugin.settings.enableForTabs = value;
          await this.plugin.saveSettings(void 0, prevTabState);
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("In window frame title").setDesc("Use the property instead of the file name in the browser window title bar.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.enableForWindowFrame).onChange(async (value) => {
          this.plugin.settings.enableForWindowFrame = value;
          await this.plugin.saveData(this.plugin.settings);
          this.plugin.updateWindowFrame();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("In file explorer").setDesc("Use the property instead of the file name in the file explorer.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.enableForExplorer).onChange(async (value) => {
          this.plugin.settings.enableForExplorer = value;
          await this.plugin.saveData(this.plugin.settings);
          this.plugin.updateExplorer();
          this.display();
        })
      );
    });
    if (this.plugin.settings.enableForExplorer) {
      generalGroup.addSetting((setting) => {
        setting.setName("Folder note file name").setDesc("If a folder contains a file with this name that has the configured property, the folder will display that property value instead. This ensures compatibility with folder notes plugins. Leave blank to disable.").addText(
          (text) => text.setPlaceholder("Index").setValue(this.plugin.settings.folderNoteFilename).onChange(async (value) => {
            this.plugin.settings.folderNoteFilename = value.trim();
            await this.plugin.saveData(this.plugin.settings);
            this.plugin.updateExplorer();
          })
        );
      });
    }
    generalGroup.addSetting((setting) => {
      setting.setName("Use simple search").setDesc("Instead of using fuzzy search, simple search provides better performance with very large vaults (thousands of files).").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.useSimpleSearch).onChange(async (value) => {
          this.plugin.settings.useSimpleSearch = value;
          await this.plugin.saveData(this.plugin.settings);
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("Excluded files in quick switcher").setDesc(`How files in Obsidian's "excluded files" list should behave in the quick switcher.`).addDropdown(
        (dropdown) => dropdown.addOptions({
          deemphasize: "Deemphasize (move to bottom & gray out)",
          hide: "Hide entirely",
          ignore: "Ignore (treat as normal files)"
        }).setValue(this.plugin.settings.quickSwitcherExcludedBehavior).onChange(async (value) => {
          this.plugin.settings.quickSwitcherExcludedBehavior = value;
          await this.plugin.saveData(this.plugin.settings);
          this.plugin.updateQuickSwitcher();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("Excluded files in link suggester").setDesc(`How files in Obsidian's "excluded files" list should behave in the link suggester.`).addDropdown(
        (dropdown) => dropdown.addOptions({
          deemphasize: "Deemphasize (move to bottom & gray out)",
          hide: "Hide entirely",
          ignore: "Ignore (treat as normal files)"
        }).setValue(this.plugin.settings.linkSuggesterExcludedBehavior).onChange(async (value) => {
          this.plugin.settings.linkSuggesterExcludedBehavior = value;
          await this.plugin.saveData(this.plugin.settings);
          this.plugin.updateLinkSuggester();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("Enable mdx file support").setDesc("Enable support for .mdx files. When enabled, the plugin will read properties from mdx files manually (Obsidian's metadata cache only works for .md files).").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.enableMdxSupport).onChange(async (value) => {
          this.plugin.settings.enableMdxSupport = value;
          await this.plugin.saveSettings();
          this.plugin.rebuildCache();
          this.plugin.updateLinkSuggester();
          this.plugin.updateQuickSwitcher();
          this.plugin.updateGraphView();
          this.plugin.updateBacklinks();
          this.plugin.updateTabs();
          this.plugin.updateExplorer();
          this.plugin.updateWindowFrame();
          this.plugin.updateBookmarks();
        })
      );
    });
  }
};

// src/commands/index.ts
var import_obsidian5 = require("obsidian");
function registerCommands(plugin) {
  plugin.addCommand({
    id: "open-quick-switcher",
    name: "Open quick switcher (property-based)",
    callback: async () => {
      const { QuickSwitchModal: QuickSwitchModal2 } = await Promise.resolve().then(() => (init_QuickSwitchModal(), QuickSwitchModal_exports));
      new QuickSwitchModal2(plugin.app, plugin).open();
    }
  });
  plugin.addCommand({
    id: "toggle-linking",
    name: "Toggle property-based linking",
    callback: async () => {
      plugin.settings.enableForLinking = !plugin.settings.enableForLinking;
      await plugin.saveData(plugin.settings);
      plugin.updateLinkSuggester();
      new import_obsidian5.Notice(`Property-based linking ${plugin.settings.enableForLinking ? "enabled" : "disabled"}`);
    }
  });
  plugin.addCommand({
    id: "toggle-quick-switcher",
    name: "Toggle property-based quick switcher",
    callback: async () => {
      const prevState = plugin.settings.enableForQuickSwitcher;
      plugin.settings.enableForQuickSwitcher = !plugin.settings.enableForQuickSwitcher;
      await plugin.saveSettings(prevState);
      new import_obsidian5.Notice(`Property-based Quick Switcher ${plugin.settings.enableForQuickSwitcher ? "enabled" : "disabled"}`);
    }
  });
  plugin.addCommand({
    id: "rebuild-cache",
    name: "Rebuild file cache",
    callback: () => {
      plugin.rebuildCache();
      new import_obsidian5.Notice("File cache rebuilt");
    }
  });
  plugin.addCommand({
    id: "toggle-drag-drop",
    name: "Toggle property-based drag and drop",
    callback: async () => {
      plugin.settings.enableForDragDrop = !plugin.settings.enableForDragDrop;
      await plugin.saveData(plugin.settings);
      new import_obsidian5.Notice(`Property-based drag and drop ${plugin.settings.enableForDragDrop ? "enabled" : "disabled"}`);
    }
  });
}

// src/services/QuickSwitcherService.ts
var QuickSwitcherService = class {
  constructor(plugin) {
    this.isCommandOverridden = false;
    this.plugin = plugin;
  }
  updateQuickSwitcher() {
    if (this.plugin.settings.enableForQuickSwitcher && !this.isCommandOverridden) {
      this.overrideQuickSwitcherCommand();
    } else if (!this.plugin.settings.enableForQuickSwitcher && this.isCommandOverridden) {
      this.restoreOriginalCommand();
    }
  }
  overrideQuickSwitcherCommand() {
    var _a;
    const commands = this.plugin.app.commands.commands;
    if (commands["switcher:open"] && !this.originalSwitcherCommand) {
      const originalCmd = commands["switcher:open"];
      this.originalSwitcherCommand = {
        id: originalCmd.id || "switcher:open",
        name: originalCmd.name || "Quick Switcher",
        icon: originalCmd.icon,
        hotkeys: originalCmd.hotkeys ? [...originalCmd.hotkeys] : [],
        callback: originalCmd.callback
      };
    }
    if (commands["switcher:open"]) {
      delete commands["switcher:open"];
    }
    const customCommand = {
      id: "switcher:open",
      name: "Quick Switcher",
      icon: (_a = this.originalSwitcherCommand) == null ? void 0 : _a.icon,
      hotkeys: [{ modifiers: ["Mod"], key: "o" }],
      callback: () => {
        const workspace = this.plugin.app.workspace;
        if (workspace.switcher && typeof workspace.switcher.close === "function") {
          workspace.switcher.close();
        }
        const existingModals = document.querySelectorAll(".modal");
        existingModals.forEach((modal) => {
          if (modal instanceof HTMLElement && !modal.classList.contains("hidden")) {
            modal.addClass("hidden");
          }
        });
        try {
          Promise.resolve().then(() => (init_QuickSwitchModal(), QuickSwitchModal_exports)).then(({ QuickSwitchModal: QuickSwitchModal2 }) => {
            const modal = new QuickSwitchModal2(this.plugin.app, this.plugin);
            modal.open();
          }).catch(() => {
            if (this.originalSwitcherCommand && this.originalSwitcherCommand.callback) {
              this.originalSwitcherCommand.callback();
            }
          });
        } catch (e) {
          if (this.originalSwitcherCommand && this.originalSwitcherCommand.callback) {
            this.originalSwitcherCommand.callback();
          }
        }
      }
    };
    commands["switcher:open"] = customCommand;
    this.isCommandOverridden = true;
  }
  restoreOriginalCommand() {
    if (!this.originalSwitcherCommand) {
      return;
    }
    const commands = this.plugin.app.commands.commands;
    if (commands["switcher:open"]) {
      delete commands["switcher:open"];
    }
    commands["switcher:open"] = {
      id: this.originalSwitcherCommand.id,
      name: this.originalSwitcherCommand.name,
      icon: this.originalSwitcherCommand.icon,
      hotkeys: this.originalSwitcherCommand.hotkeys,
      callback: this.originalSwitcherCommand.callback
    };
    this.isCommandOverridden = false;
  }
};

// src/services/DragDropService.ts
var import_obsidian6 = require("obsidian");
init_frontmatter();
var DragDropService = class {
  // Prevent duplicate processing within 100ms
  constructor(plugin) {
    this.lastDropTime = 0;
    this.lastDropData = null;
    this.DROP_DEBOUNCE_MS = 100;
    this.plugin = plugin;
  }
  handleDragDrop(event, editor) {
    const dataTransfer = event.dataTransfer;
    if (!dataTransfer) {
      return;
    }
    const filePath = dataTransfer.getData("text/plain");
    if (!filePath || !filePath.endsWith(".md") && !(filePath.endsWith(".mdx") && this.plugin.settings.enableMdxSupport)) {
      return;
    }
    const now = Date.now();
    if (now - this.lastDropTime < this.DROP_DEBOUNCE_MS && this.lastDropData === filePath) {
      return;
    }
    this.lastDropTime = now;
    this.lastDropData = filePath;
    const file = this.plugin.app.vault.getAbstractFileByPath(filePath);
    if (!file || !(file instanceof import_obsidian6.TFile)) {
      return;
    }
    if (file.extension === "md") {
      const displayName = this.getDisplayNameSync(file);
      if (displayName !== null) {
        setTimeout(() => {
          this.replaceLastInsertedLink(file, displayName, editor);
        }, 50);
      }
    } else if (file.extension === "mdx" && this.plugin.settings.enableMdxSupport) {
      void (async () => {
        const displayName = await this.getDisplayName(file);
        if (displayName !== null) {
          let attempts = 0;
          const maxAttempts = 5;
          const attemptReplace = () => {
            attempts++;
            const replaced = this.replaceLastInsertedLink(file, displayName, editor);
            if (!replaced && attempts < maxAttempts) {
              setTimeout(attemptReplace, 50 * attempts);
            }
          };
          setTimeout(attemptReplace, 150);
        }
      })();
    }
  }
  handleDOMDrop(event) {
    const target = event.target;
    const editorElement = target == null ? void 0 : target.closest(".cm-editor");
    const activeView = this.plugin.app.workspace.getActiveViewOfType(import_obsidian6.MarkdownView);
    const hasActiveEditor = activeView && activeView.editor;
    if (!editorElement && !hasActiveEditor) {
      return;
    }
    const dataTransfer = event.dataTransfer;
    if (!dataTransfer) {
      return;
    }
    const filePath = dataTransfer.getData("text/plain");
    if (!filePath) {
      return;
    }
    let actualFilePath = filePath;
    if (filePath.startsWith("obsidian://open?")) {
      try {
        const url = new URL(filePath);
        const fileParam = url.searchParams.get("file");
        if (fileParam) {
          const decodedPath = decodeURIComponent(fileParam);
          if (decodedPath.endsWith(".mdx")) {
            actualFilePath = decodedPath;
          } else if (decodedPath.endsWith(".md")) {
            actualFilePath = decodedPath;
          } else {
            if (this.plugin.settings.enableMdxSupport) {
              const mdxFile = this.plugin.app.vault.getAbstractFileByPath(decodedPath + ".mdx");
              if (mdxFile) {
                actualFilePath = decodedPath + ".mdx";
              } else {
                actualFilePath = decodedPath + ".md";
              }
            } else {
              actualFilePath = decodedPath + ".md";
            }
          }
        } else {
          return;
        }
      } catch (e) {
        return;
      }
    } else if (!filePath.endsWith(".md") && !(filePath.endsWith(".mdx") && this.plugin.settings.enableMdxSupport)) {
      return;
    }
    const now = Date.now();
    if (now - this.lastDropTime < this.DROP_DEBOUNCE_MS && this.lastDropData === actualFilePath) {
      return;
    }
    this.lastDropTime = now;
    this.lastDropData = actualFilePath;
    const file = this.plugin.app.vault.getAbstractFileByPath(actualFilePath);
    if (!file || !(file instanceof import_obsidian6.TFile)) {
      return;
    }
    (() => {
      if (file.extension === "md") {
        const displayName = this.getDisplayNameSync(file);
        if (displayName !== null) {
          setTimeout(() => {
            const activeView2 = this.plugin.app.workspace.getActiveViewOfType(import_obsidian6.MarkdownView);
            if (activeView2 && activeView2.editor) {
              this.replaceLastInsertedLink(file, displayName, activeView2.editor);
            }
          }, 50);
        }
      } else if (file.extension === "mdx" && this.plugin.settings.enableMdxSupport) {
        void (async () => {
          const displayName = await this.getDisplayName(file);
          if (displayName !== null) {
            let attempts = 0;
            const maxAttempts = 5;
            const attemptReplace = () => {
              attempts++;
              const activeView2 = this.plugin.app.workspace.getActiveViewOfType(import_obsidian6.MarkdownView);
              if (activeView2 && activeView2.editor) {
                const replaced = this.replaceLastInsertedLink(file, displayName, activeView2.editor);
                if (!replaced && attempts < maxAttempts) {
                  setTimeout(attemptReplace, 50 * attempts);
                }
              } else if (attempts < maxAttempts) {
                setTimeout(attemptReplace, 50 * attempts);
              }
            };
            setTimeout(attemptReplace, 150);
          }
        })();
      }
    })();
  }
  /**
   * Synchronous version for .md files (fast, immediate)
   */
  getDisplayNameSync(file) {
    if (file.extension !== "md") {
      return null;
    }
    const frontmatter = getFrontmatterSync(this.plugin.app, file, this.plugin.settings);
    if (frontmatter && frontmatter[this.plugin.settings.propertyKey] !== void 0 && frontmatter[this.plugin.settings.propertyKey] !== null) {
      const propertyValue = String(frontmatter[this.plugin.settings.propertyKey]).trim();
      if (propertyValue !== "") {
        return propertyValue;
      }
    }
    return null;
  }
  /**
   * Async version for .mdx files (needs file reading)
   */
  async getDisplayName(file) {
    const { getFrontmatter: getFrontmatter2, isFileTypeSupported: isFileTypeSupported2 } = await Promise.resolve().then(() => (init_frontmatter(), frontmatter_exports));
    if (!isFileTypeSupported2(file.extension, this.plugin.settings)) {
      return null;
    }
    const frontmatter = await getFrontmatter2(this.plugin.app, file, this.plugin.settings);
    if (frontmatter && frontmatter[this.plugin.settings.propertyKey] !== void 0 && frontmatter[this.plugin.settings.propertyKey] !== null) {
      const propertyValue = String(frontmatter[this.plugin.settings.propertyKey]).trim();
      if (propertyValue !== "") {
        return propertyValue;
      }
    }
    return null;
  }
  replaceLastInsertedLink(file, displayName, editor) {
    var _a, _b;
    const content = editor.getValue();
    const cursor = editor.getCursor();
    const lines = content.split("\n");
    const currentLine = lines[cursor.line];
    const wikiLinkRegex = /\[\[([^\]]+)\]\]/g;
    const markdownLinkRegex = /\[([^\]]*)\]\(([^)]+)\)/g;
    let match;
    let lastMatch = null;
    while ((match = wikiLinkRegex.exec(currentLine)) !== null) {
      lastMatch = match;
    }
    if (lastMatch) {
      const linkPath = lastMatch[1];
      const filePathWithoutExt = file.path.replace(/\.(md|mdx)$/, "");
      const linkPathWithoutExt = linkPath.replace(/\.(md|mdx)$/, "");
      if (filePathWithoutExt === linkPathWithoutExt || file.path === linkPath || file.path.replace(/\.mdx$/, ".md") === linkPath) {
        const newLinkText = `[[${linkPath}|${displayName}]]`;
        const startPos = { line: cursor.line, ch: lastMatch.index };
        const endPos = { line: cursor.line, ch: lastMatch.index + lastMatch[0].length };
        editor.replaceRange(newLinkText, startPos, endPos);
        return true;
      }
    }
    markdownLinkRegex.lastIndex = 0;
    lastMatch = null;
    while ((match = markdownLinkRegex.exec(currentLine)) !== null) {
      lastMatch = match;
    }
    if (lastMatch) {
      const linkUrl = lastMatch[2];
      const linkUrlDecoded = decodeURIComponent(linkUrl);
      const filePathEncoded = encodeURI(file.path);
      const filePathWithoutExt = file.path.replace(/\.(md|mdx)$/, "");
      const linkUrlWithoutExt = linkUrlDecoded.replace(/\.(md|mdx)$/, "");
      const matches = file.path === linkUrlDecoded || filePathEncoded === linkUrl || filePathWithoutExt === linkUrlWithoutExt || file.path.replace(/\.mdx$/, ".md") === linkUrlDecoded || file.path.replace(/\.md$/, ".mdx") === linkUrlDecoded || // Handle relative paths - check if link URL matches file basename
      file.basename === linkUrlDecoded.replace(/\.(md|mdx)$/, "") || file.basename + ".mdx" === linkUrlDecoded || file.basename + ".md" === linkUrlDecoded || // Handle paths with directory
      file.path.endsWith(linkUrlDecoded) || linkUrlDecoded.endsWith(file.path);
      if (matches) {
        const newLinkText = `[${displayName}](${linkUrl})`;
        const startPos = { line: cursor.line, ch: lastMatch.index };
        const endPos = { line: cursor.line, ch: lastMatch.index + lastMatch[0].length };
        editor.replaceRange(newLinkText, startPos, endPos);
        return true;
      }
    } else {
      const searchRange = 3;
      for (let i = Math.max(0, cursor.line - searchRange); i <= Math.min(lines.length - 1, cursor.line + searchRange); i++) {
        const line = lines[i];
        const wikiMatches = [...line.matchAll(/\[\[([^\]]+)\]\]/g)];
        const markdownMatches = [...line.matchAll(/\[([^\]]*)\]\(([^)]+)\)/g)];
        for (const wikiMatch of wikiMatches) {
          const linkPath = wikiMatch[1];
          const filePathWithoutExt = file.path.replace(/\.(md|mdx)$/, "");
          const linkPathWithoutExt = linkPath.replace(/\.(md|mdx)$/, "");
          if (filePathWithoutExt === linkPathWithoutExt || file.path === linkPath || file.path.replace(/\.mdx$/, ".md") === linkPath) {
            const newLinkText = `[[${linkPath}|${displayName}]]`;
            const matchIndex = (_a = wikiMatch.index) != null ? _a : 0;
            const startPos = { line: i, ch: matchIndex };
            const endPos = { line: i, ch: matchIndex + wikiMatch[0].length };
            editor.replaceRange(newLinkText, startPos, endPos);
            return true;
          }
        }
        for (const mdMatch of markdownMatches) {
          const linkUrl = mdMatch[2];
          const linkUrlDecoded = decodeURIComponent(linkUrl);
          const filePathWithoutExt = file.path.replace(/\.(md|mdx)$/, "");
          const linkUrlWithoutExt = linkUrlDecoded.replace(/\.(md|mdx)$/, "");
          const matches = file.path === linkUrlDecoded || encodeURI(file.path) === linkUrl || file.path.replace(/\.mdx$/, ".md") === linkUrlDecoded || file.path.replace(/\.md$/, ".mdx") === linkUrlDecoded || filePathWithoutExt === linkUrlWithoutExt || // Handle relative paths - check if link URL matches file basename
          file.basename === linkUrlDecoded.replace(/\.(md|mdx)$/, "") || file.basename + ".mdx" === linkUrlDecoded || file.basename + ".md" === linkUrlDecoded || // Handle paths with directory
          file.path.endsWith(linkUrlDecoded) || linkUrlDecoded.endsWith(file.path);
          if (matches) {
            const newLinkText = `[${displayName}](${linkUrl})`;
            const matchIndex = (_b = mdMatch.index) != null ? _b : 0;
            const startPos = { line: i, ch: matchIndex };
            const endPos = { line: i, ch: matchIndex + mdMatch[0].length };
            editor.replaceRange(newLinkText, startPos, endPos);
            return true;
          }
        }
      }
    }
    return false;
  }
};

// src/services/CacheService.ts
var CacheService = class {
  constructor(plugin) {
    this.plugin = plugin;
  }
  setSuggest(suggest) {
    this.suggest = suggest;
  }
  invalidateCache(file) {
    if (this.suggest) {
      void this.suggest.updateFileCache(file);
    }
  }
  rebuildCache() {
    if (this.suggest) {
      void this.suggest.buildFileCache();
    }
  }
};

// src/services/GraphViewService.ts
var import_obsidian7 = require("obsidian");

// src/utils/frontmatter-cache.ts
init_frontmatter();
var FrontmatterCache = class {
  constructor() {
    this.cache = /* @__PURE__ */ new Map();
    this.pending = /* @__PURE__ */ new Map();
  }
  async get(app, file, settings) {
    var _a;
    const key = file.path;
    if (this.cache.has(key)) {
      return (_a = this.cache.get(key)) != null ? _a : null;
    }
    if (this.pending.has(key)) {
      return await this.pending.get(key);
    }
    const promise = getFrontmatter(app, file, settings);
    this.pending.set(key, promise);
    try {
      const result = await promise;
      this.cache.set(key, result);
      return result;
    } finally {
      this.pending.delete(key);
    }
  }
  getSync(key) {
    return this.cache.get(key);
  }
  invalidate(key) {
    this.cache.delete(key);
    this.pending.delete(key);
  }
  clear() {
    this.cache.clear();
    this.pending.clear();
  }
};
var frontmatterCache = new FrontmatterCache();

// src/services/GraphViewService.ts
function isNonEmptyString(value) {
  return typeof value === "string" && value.trim().length > 0;
}
function coerceFrontmatterValueToLabel(value) {
  if (isNonEmptyString(value)) return value.trim();
  if (typeof value === "number" && Number.isFinite(value)) return String(value);
  if (typeof value === "boolean") return value ? "true" : "false";
  return null;
}
function getLeafKey(leafType, leafId) {
  return `${leafType}:${leafId}`;
}
function asLeafLike(value) {
  if (!value || typeof value !== "object") return null;
  return value;
}
function isGraphNode(value) {
  var _a;
  if (!value || typeof value !== "object") return false;
  const v = value;
  return typeof v.id === "string" || typeof ((_a = v.text) == null ? void 0 : _a.text) === "string";
}
function isNodeTextCarrier(node) {
  return !!node.text && typeof node.text.text === "string";
}
function iterateGraphNodes(nodes, cb) {
  if (!nodes) return;
  try {
    if (nodes instanceof Map) {
      for (const v of nodes.values()) if (isGraphNode(v)) cb(v);
      return;
    }
    if (nodes instanceof Set) {
      for (const v of nodes.values()) if (isGraphNode(v)) cb(v);
      return;
    }
    if (Array.isArray(nodes)) {
      for (const v of nodes) if (isGraphNode(v)) cb(v);
      return;
    }
    const maybeIterable = nodes;
    if (typeof maybeIterable[Symbol.iterator] === "function") {
      for (const v of nodes) if (isGraphNode(v)) cb(v);
      return;
    }
    if (typeof nodes === "object" && nodes) {
      for (const v of Object.values(nodes)) if (isGraphNode(v)) cb(v);
    }
  } catch (e) {
  }
}
var GraphViewService = class {
  constructor(plugin) {
    this.retryTimers = /* @__PURE__ */ new Set();
    this.pendingMdxRefreshPaths = /* @__PURE__ */ new Set();
    this.installed = false;
    this.originalsByPrototype = /* @__PURE__ */ new Map();
    this.originalNodeText = /* @__PURE__ */ new WeakMap();
    // Track which leaves we've already attempted to patch (best-effort identity).
    this.seenLeaves = /* @__PURE__ */ new Set();
    this.basenameIndex = /* @__PURE__ */ new Map();
    this.basenameIndexBuiltForMdxSupport = null;
    this.plugin = plugin;
  }
  onLayoutChange() {
    this.updateGraphView();
  }
  updateGraphView() {
    if (!this.plugin.settings.enableForGraphView) {
      this.teardown();
      return;
    }
    this.ensureObserver();
    this.ensurePatchedForOpenLeaves();
    this.refreshGraphView();
  }
  refreshGraphView() {
    if (!this.plugin.settings.enableForGraphView) return;
    this.ensurePatchedForOpenLeaves();
    this.triggerRenderOnAllGraphViewsWithRetry();
  }
  onunload() {
    this.teardown();
  }
  // --- Patch management ---
  ensurePatchedForOpenLeaves() {
    if (!this.plugin.settings.enableForGraphView) return;
    const leaves = this.getGraphLeaves();
    for (const { leafType, leaf } of leaves) {
      const leafLike = asLeafLike(leaf);
      const leafId = leafLike == null ? void 0 : leafLike.id;
      const leafKey = getLeafKey(leafType, isNonEmptyString(leafId) ? leafId : String(leaf));
      if (!this.seenLeaves.has(leafKey)) this.seenLeaves.add(leafKey);
      this.tryInstallPatchFromLeaf(leaf);
    }
  }
  tryInstallPatchFromLeaf(leaf) {
    var _a;
    const view = (_a = asLeafLike(leaf)) == null ? void 0 : _a.view;
    const renderer = view == null ? void 0 : view.renderer;
    if (!renderer) return;
    const nodes = renderer.nodes;
    if (!nodes) return;
    const sampleNode = this.pickAnyNode(nodes);
    if (!sampleNode) return;
    const protoUnknown = Object.getPrototypeOf(sampleNode);
    if (!protoUnknown || typeof protoUnknown !== "object") return;
    const proto = protoUnknown;
    const protoWithMethod = proto;
    const current = protoWithMethod.getDisplayText;
    if (typeof current !== "function") return;
    if (this.originalsByPrototype.has(proto)) {
      this.installed = true;
      return;
    }
    const original = current;
    this.originalsByPrototype.set(proto, original);
    const resolveLabel = (node) => {
      const fallback = safeCall(original, node);
      const label = this.computeNodeLabel(node);
      return label != null ? label : fallback;
    };
    protoWithMethod.getDisplayText = function patchedGetDisplayText() {
      return resolveLabel(this);
    };
    this.installed = true;
  }
  teardown() {
    this.disconnectObserver();
    this.clearAllTimers();
    this.restoreNodeTextsFromOpenLeaves();
    this.restoreAllPatches();
    this.seenLeaves.clear();
    this.pendingMdxRefreshPaths.clear();
    this.originalNodeText = /* @__PURE__ */ new WeakMap();
  }
  restoreNodeTextsFromOpenLeaves() {
    var _a, _b;
    const leaves = this.getGraphLeaves();
    for (const { leaf } of leaves) {
      const view = (_a = asLeafLike(leaf)) == null ? void 0 : _a.view;
      const nodes = (_b = view == null ? void 0 : view.renderer) == null ? void 0 : _b.nodes;
      if (!nodes) continue;
      iterateGraphNodes(nodes, (node) => {
        if (!node || typeof node !== "object") return;
        if (!isNodeTextCarrier(node)) return;
        const original = this.originalNodeText.get(node);
        if (original !== void 0) node.text.text = original;
      });
    }
  }
  restoreAllPatches() {
    for (const [proto, original] of this.originalsByPrototype.entries()) {
      try {
        proto.getDisplayText = original;
      } catch (e) {
      }
    }
    this.originalsByPrototype.clear();
    this.installed = false;
  }
  // --- Observer / refresh ---
  ensureObserver() {
    if (this.observer) return;
    this.observer = new MutationObserver(() => {
      if (!this.plugin.settings.enableForGraphView) return;
      if (this.refreshTimer) window.clearTimeout(this.refreshTimer);
      this.refreshTimer = window.setTimeout(() => {
        this.refreshTimer = void 0;
        this.ensurePatchedForOpenLeaves();
        this.triggerRenderOnAllGraphViewsWithRetry();
      }, 150);
    });
    this.observer.observe(document.body, { childList: true, subtree: true });
  }
  disconnectObserver() {
    if (!this.observer) return;
    try {
      this.observer.disconnect();
    } finally {
      this.observer = void 0;
    }
  }
  triggerRenderOnAllGraphViewsWithRetry() {
    const leaves = this.getGraphLeaves();
    for (const { leaf } of leaves) {
      this.triggerRenderWithRetry(leaf);
    }
  }
  triggerRenderWithRetry(leaf) {
    const maxAttempts = 8;
    const baseDelayMs = 80;
    const attempt = (n) => {
      var _a;
      const view = (_a = asLeafLike(leaf)) == null ? void 0 : _a.view;
      const renderer = view == null ? void 0 : view.renderer;
      const changed = renderer == null ? void 0 : renderer.changed;
      const nodes = renderer == null ? void 0 : renderer.nodes;
      if (!renderer || typeof changed !== "function" || !nodes) {
        if (n >= maxAttempts) return;
        const delay = Math.min(1500, baseDelayMs * Math.pow(2, n));
        const t = window.setTimeout(() => {
          this.retryTimers.delete(t);
          attempt(n + 1);
        }, delay);
        this.retryTimers.add(t);
        return;
      }
      this.tryInstallPatchFromLeaf(leaf);
      this.applyLabelsToOpenNodes(renderer, leaf);
      try {
        changed.call(renderer);
      } catch (e) {
      }
    };
    attempt(0);
  }
  applyLabelsToOpenNodes(renderer, leaf) {
    const nodes = renderer.nodes;
    if (!nodes) return;
    iterateGraphNodes(nodes, (node) => {
      if (!isNodeTextCarrier(node)) return;
      if (!this.plugin.settings.enableForGraphView) return;
      const label = this.computeNodeLabel(node);
      if (label === null) return;
      const nodeObj = node;
      if (!this.originalNodeText.has(nodeObj)) {
        this.originalNodeText.set(nodeObj, node.text.text);
      }
      node.text.text = label;
    });
  }
  clearAllTimers() {
    if (this.refreshTimer) window.clearTimeout(this.refreshTimer);
    this.refreshTimer = void 0;
    for (const t of this.retryTimers) window.clearTimeout(t);
    this.retryTimers.clear();
    if (this.pendingMdxRefreshTimer) window.clearTimeout(this.pendingMdxRefreshTimer);
    this.pendingMdxRefreshTimer = void 0;
  }
  // --- Label computation ---
  computeNodeLabel(node) {
    var _a, _b, _c, _d;
    if (!this.plugin.settings.enableForGraphView) return null;
    const propertyKey = ((_a = this.plugin.settings.propertyKey) == null ? void 0 : _a.trim()) || "title";
    const fileFromId = this.resolveFileFromNodeId(node.id);
    const nodeObj = node;
    const nodeTextForResolution = (_c = this.originalNodeText.get(nodeObj)) != null ? _c : (_b = node.text) == null ? void 0 : _b.text;
    const file = fileFromId != null ? fileFromId : this.resolveFileFromNodeLabel(nodeTextForResolution);
    if (!(file instanceof import_obsidian7.TFile)) return null;
    if (file.extension !== "md" && (file.extension !== "mdx" || !this.plugin.settings.enableMdxSupport)) return null;
    if (file.extension === "md") {
      const fm = (_d = this.plugin.app.metadataCache.getFileCache(file)) == null ? void 0 : _d.frontmatter;
      const fmRecord = fm && typeof fm === "object" ? fm : void 0;
      const label2 = coerceFrontmatterValueToLabel(fmRecord == null ? void 0 : fmRecord[propertyKey]);
      return label2;
    }
    const cached = frontmatterCache.getSync(file.path);
    if (cached === void 0) {
      this.scheduleMdxLoadAndRefresh(file, propertyKey);
      return null;
    }
    const cachedRecord = cached && typeof cached === "object" ? cached : void 0;
    const label = coerceFrontmatterValueToLabel(cachedRecord == null ? void 0 : cachedRecord[propertyKey]);
    return label;
  }
  ensureBasenameIndex() {
    const mdxEnabled = this.plugin.settings.enableMdxSupport;
    if (this.basenameIndexBuiltForMdxSupport === mdxEnabled && this.basenameIndex.size > 0) return;
    this.basenameIndexBuiltForMdxSupport = mdxEnabled;
    this.basenameIndex.clear();
    const files = this.plugin.app.vault.getFiles();
    for (const file of files) {
      if (!(file instanceof import_obsidian7.TFile)) continue;
      if (file.extension === "md") {
        if (!this.basenameIndex.has(file.basename)) this.basenameIndex.set(file.basename, file);
        continue;
      }
      if (file.extension === "mdx" && mdxEnabled) {
        if (!this.basenameIndex.has(file.basename)) this.basenameIndex.set(file.basename, file);
      }
    }
  }
  resolveFileFromNodeLabel(labelText) {
    var _a;
    if (typeof labelText !== "string") return null;
    const base = cleanLabelToBasename(labelText);
    if (!isNonEmptyString(base)) return null;
    this.ensureBasenameIndex();
    return (_a = this.basenameIndex.get(base)) != null ? _a : null;
  }
  resolveFileFromNodeId(nodeId) {
    var _a, _b;
    if (typeof nodeId !== "string") return null;
    const normalizedId = normalizeVaultPath(nodeId);
    if (!isNonEmptyString(normalizedId)) return null;
    const enableMdx = this.plugin.settings.enableMdxSupport;
    const lower = normalizedId.toLowerCase();
    const candidates = /* @__PURE__ */ new Set();
    candidates.add(normalizedId);
    if (lower.endsWith(".mdx")) {
      if (!enableMdx) return null;
      candidates.add(normalizedId);
      candidates.add(normalizedId.slice(0, -4) + ".md");
    } else if (lower.endsWith(".md")) {
      candidates.add(normalizedId);
      if (enableMdx) candidates.add(normalizedId.slice(0, -3) + ".mdx");
    } else {
      candidates.add(normalizedId + ".md");
      if (enableMdx) candidates.add(normalizedId + ".mdx");
    }
    for (const candidate of candidates) {
      const file = this.plugin.app.vault.getAbstractFileByPath(candidate);
      if (!(file instanceof import_obsidian7.TFile)) continue;
      if (file.extension === "md") return file;
      if (file.extension === "mdx" && enableMdx) return file;
    }
    const cleaned = (_a = normalizedId.split(/[/\\]/).pop()) != null ? _a : normalizedId;
    const base = stripMdExtension(cleaned);
    if (!isNonEmptyString(base)) return null;
    this.ensureBasenameIndex();
    return (_b = this.basenameIndex.get(base)) != null ? _b : null;
  }
  scheduleMdxLoadAndRefresh(file, _key) {
    if (this.pendingMdxRefreshPaths.has(file.path)) return;
    this.pendingMdxRefreshPaths.add(file.path);
    void frontmatterCache.get(this.plugin.app, file, this.plugin.settings).catch(() => null).finally(() => {
      if (this.pendingMdxRefreshTimer) return;
      this.pendingMdxRefreshTimer = window.setTimeout(() => {
        this.pendingMdxRefreshTimer = void 0;
        this.pendingMdxRefreshPaths.clear();
        this.refreshGraphView();
      }, 200);
    });
  }
  // --- Leaf helpers ---
  getGraphLeaves() {
    var _a, _b;
    const out = [];
    const workspace = this.plugin.app.workspace;
    const graphLeavesUnknown = (_a = workspace.getLeavesOfType) == null ? void 0 : _a.call(workspace, "graph");
    const graphLeaves = Array.isArray(graphLeavesUnknown) ? graphLeavesUnknown : [];
    for (const leaf of graphLeaves) out.push({ leafType: "graph", leaf });
    const localGraphLeavesUnknown = (_b = workspace.getLeavesOfType) == null ? void 0 : _b.call(workspace, "localgraph");
    const localGraphLeaves = Array.isArray(localGraphLeavesUnknown) ? localGraphLeavesUnknown : [];
    for (const leaf of localGraphLeaves) out.push({ leafType: "localgraph", leaf });
    return out;
  }
  pickAnyNode(nodes) {
    try {
      if (nodes instanceof Map) {
        for (const v of nodes.values()) {
          if (isGraphNode(v)) return v;
        }
      }
      if (nodes instanceof Set) {
        for (const v of nodes.values()) {
          if (isGraphNode(v)) return v;
        }
      }
      if (Array.isArray(nodes)) {
        const first = nodes[0];
        return isGraphNode(first) ? first : null;
      }
      if (typeof nodes === "object" && nodes) {
        const values = Object.values(nodes);
        const first = values[0];
        return isGraphNode(first) ? first : null;
      }
    } catch (e) {
    }
    return null;
  }
};
function normalizeVaultPath(raw) {
  let v = raw.trim();
  if (v.startsWith("file://")) v = v.slice("file://".length);
  if (v.startsWith("vault://")) v = v.slice("vault://".length);
  if (v.startsWith("obsidian://")) v = v.slice("obsidian://".length);
  return v;
}
function stripMdExtension(path) {
  const lower = path.toLowerCase();
  if (lower.endsWith(".mdx")) return path.slice(0, -4);
  if (lower.endsWith(".md")) return path.slice(0, -3);
  return path;
}
function cleanLabelToBasename(label) {
  var _a;
  const trimmed = label.trim();
  const lastSegment = (_a = trimmed.split(/[/\\]/).pop()) != null ? _a : trimmed;
  return stripMdExtension(lastSegment);
}
function safeCall(fn, self) {
  var _a;
  try {
    return fn.call(self);
  } catch (e) {
    const direct = (_a = self == null ? void 0 : self.text) == null ? void 0 : _a.text;
    return isNonEmptyString(direct) ? direct : "";
  }
}

// src/services/BacklinkService.ts
var import_obsidian8 = require("obsidian");
var BacklinkService = class {
  constructor(plugin) {
    this.processedElements = /* @__PURE__ */ new WeakSet();
    this.modifiedElements = /* @__PURE__ */ new WeakSet();
    this.originalTextContentDescriptors = /* @__PURE__ */ new Map();
    this.linkedTitleAssignedSourcePath = /* @__PURE__ */ new WeakMap();
    this.linkedTitlesForTargetPath = null;
    this.plugin = plugin;
  }
  /**
   * Get display name from file's frontmatter property
   */
  async getDisplayName(file) {
    if (!this.plugin.settings.enableForBacklinks) {
      return null;
    }
    const { getFrontmatter: getFrontmatter2, isFileTypeSupported: isFileTypeSupported2 } = await Promise.resolve().then(() => (init_frontmatter(), frontmatter_exports));
    if (!isFileTypeSupported2(file.extension, this.plugin.settings)) {
      return null;
    }
    const frontmatter = await getFrontmatter2(this.plugin.app, file, this.plugin.settings);
    if (frontmatter && frontmatter[this.plugin.settings.propertyKey] !== void 0 && frontmatter[this.plugin.settings.propertyKey] !== null) {
      const propertyValue = String(frontmatter[this.plugin.settings.propertyKey]).trim();
      if (propertyValue !== "") {
        return propertyValue;
      }
    }
    return null;
  }
  /**
   * Update all backlink displays
   */
  updateBacklinks() {
    if (!this.plugin.settings.enableForBacklinks) {
      this.stopObserving();
      return;
    }
    this.updateEmbeddedBacklinks();
    void this.updateDedicatedBacklinksPanel();
    this.startObserving();
  }
  /**
   * Update embedded backlinks in markdown views
   */
  updateEmbeddedBacklinks() {
    for (const leaf of this.plugin.app.workspace.getLeavesOfType("markdown")) {
      if (!(leaf.view instanceof import_obsidian8.MarkdownView)) {
        continue;
      }
      const embeddedBacklinks = leaf.view.containerEl.querySelector(".embedded-backlinks");
      if (embeddedBacklinks) {
        this.updateBacklinkContainer(embeddedBacklinks);
      }
    }
  }
  /**
   * Update dedicated backlinks panel
   */
  async updateDedicatedBacklinksPanel() {
    const backlinksLeaves = this.plugin.app.workspace.getLeavesOfType("backlink");
    for (const leaf of backlinksLeaves) {
      await leaf.loadIfDeferred();
      if (leaf.view) {
        const container = leaf.view.containerEl;
        if (container) {
          const backlinksContainer = container.querySelector(".backlinks-pane") || container.querySelector(".backlink-pane");
          if (backlinksContainer) {
            this.updateBacklinkContainer(backlinksContainer);
          }
          const outgoingLinksContainer = container.querySelector(".outgoing-link-pane") || container.querySelector(".outgoing-links");
          if (outgoingLinksContainer) {
            this.updateBacklinkContainer(outgoingLinksContainer);
          }
        }
      }
    }
  }
  /**
   * Extract file path from an element or its parent link
   */
  extractFilePathFromElement(element) {
    var _a, _b, _c, _d;
    const resolveFileFromPathLike = (rawPathLike) => {
      var _a2, _b2;
      let value = rawPathLike.trim();
      if (!value) return null;
      value = (_b2 = (_a2 = value.split("#")[0]) == null ? void 0 : _a2.split("?")[0]) != null ? _b2 : value;
      if (value.startsWith("file://")) value = value.slice("file://".length);
      if (value.startsWith("vault://")) value = value.slice("vault://".length);
      if (value.startsWith("app://") || value.startsWith("http://") || value.startsWith("https://")) {
        try {
          const url = new URL(value);
          const fileParam = url.searchParams.get("file");
          if (fileParam) {
            try {
              value = decodeURIComponent(fileParam);
            } catch (e) {
              value = fileParam;
            }
          } else if (url.pathname) {
            value = url.pathname;
          }
        } catch (e) {
        }
      }
      try {
        value = decodeURIComponent(value);
      } catch (e) {
      }
      value = value.replace(/^\/+/, "");
      const lower = value.toLowerCase();
      const candidates = [];
      candidates.push(value);
      if (!lower.endsWith(".md") && !lower.endsWith(".mdx")) {
        candidates.push(`${value}.md`);
        if (this.plugin.settings.enableMdxSupport) {
          candidates.push(`${value}.mdx`);
        }
      }
      for (const candidate of candidates) {
        const file = this.plugin.app.vault.getAbstractFileByPath(candidate);
        if (file instanceof import_obsidian8.TFile) return file;
      }
      return null;
    };
    const directDataPath = element.getAttribute("data-path");
    if (directDataPath) {
      const file = resolveFileFromPathLike(directDataPath);
      if (file) return file;
    }
    const ancestorWithDataPath = element.closest("[data-path]");
    if (ancestorWithDataPath) {
      const dataPath = ancestorWithDataPath.getAttribute("data-path");
      if (dataPath) {
        const file = resolveFileFromPathLike(dataPath);
        if (file) return file;
      }
    }
    const descendantWithDataPath = element.querySelector("[data-path]");
    if (descendantWithDataPath instanceof HTMLElement) {
      const dataPath = descendantWithDataPath.getAttribute("data-path");
      if (dataPath) {
        const file = resolveFileFromPathLike(dataPath);
        if (file) return file;
      }
    }
    const searchResult = element.closest(".search-result");
    if (searchResult) {
      const rowDataPathEl = searchResult.querySelector("[data-path]");
      if (rowDataPathEl instanceof HTMLElement) {
        const dataPath = rowDataPathEl.getAttribute("data-path");
        if (dataPath) {
          const file = resolveFileFromPathLike(dataPath);
          if (file) return file;
        }
      }
      const anchors = Array.from(searchResult.querySelectorAll("a[href], a[data-href]"));
      for (const a of anchors) {
        const dataHref = a.getAttribute("data-href");
        if (dataHref) {
          const file = resolveFileFromPathLike(dataHref);
          if (file) return file;
        }
        const href = a.getAttribute("href");
        if (href) {
          const file = resolveFileFromPathLike(href);
          if (file) return file;
        }
      }
    }
    const link = element.closest("a") || element.querySelector("a");
    if (link) {
      const href = (_a = link.getAttribute("href")) != null ? _a : link instanceof HTMLAnchorElement ? link.href : null;
      const dataHref = link.getAttribute("data-href");
      if (dataHref) {
        const file = resolveFileFromPathLike(dataHref);
        if (file) return file;
      }
      if (href) {
        if (href.startsWith("obsidian://")) {
          try {
            const url = new URL(href);
            const fileParam = url.searchParams.get("file");
            if (fileParam) {
              const decodedPath = (() => {
                try {
                  return decodeURIComponent(fileParam);
                } catch (e) {
                  return fileParam;
                }
              })();
              const file2 = resolveFileFromPathLike(decodedPath);
              if (file2) return file2;
            }
          } catch (e) {
          }
        }
        const internalLinkMatch = href.match(/#file\/([^?#]+)/);
        if (internalLinkMatch) {
          const filePath = (() => {
            try {
              return decodeURIComponent(internalLinkMatch[1]);
            } catch (e) {
              return internalLinkMatch[1];
            }
          })();
          const file2 = resolveFileFromPathLike(filePath);
          if (file2) return file2;
        }
        const file = resolveFileFromPathLike(href);
        if (file) return file;
      }
    }
    const textContent = (_b = element.textContent) == null ? void 0 : _b.trim();
    if (textContent) {
      if (textContent.includes("/") || textContent.includes("\\")) {
        const resolved = resolveFileFromPathLike(textContent);
        if (resolved) return resolved;
      }
      const cleaned = (_c = textContent.replace(/\.(mdx|md)$/i, "").split(/[/\\]/).pop()) != null ? _c : textContent;
      const basename = cleaned.trim();
      if (basename) {
        const allFiles = this.plugin.app.vault.getFiles().filter((f) => {
          if (!(f instanceof import_obsidian8.TFile)) return false;
          if (f.extension === "md") return true;
          return this.plugin.settings.enableMdxSupport && f.extension === "mdx";
        });
        const matchingFiles = allFiles.filter((f) => f.basename === basename);
        if (matchingFiles.length === 1) return matchingFiles[0];
      }
    }
    const searchResultRow = element.closest(".search-result");
    if (searchResultRow) {
      const rowText = (_d = searchResultRow.textContent) != null ? _d : "";
      const mdParenPathRegex = /\(([^)]*?\.(?:md|mdx)(?:[#?][^)]*)?)\)/gi;
      let match = null;
      while ((match = mdParenPathRegex.exec(rowText)) !== null) {
        const candidate = match[1];
        if (!candidate) continue;
        if (candidate.includes("://")) continue;
        const resolved = resolveFileFromPathLike(candidate);
        if (resolved) return resolved;
      }
    }
    return null;
  }
  /**
   * Update a backlink container by replacing file names with property titles
   */
  updateBacklinkContainer(container) {
    void (async () => {
      const activeFile = this.plugin.app.workspace.getActiveFile();
      if (!(activeFile instanceof import_obsidian8.TFile)) return;
      if (this.linkedTitlesForTargetPath !== activeFile.path) {
        this.linkedTitlesForTargetPath = activeFile.path;
        this.linkedTitleAssignedSourcePath = /* @__PURE__ */ new WeakMap();
      }
      const resolvedLinks = this.plugin.app.metadataCache.resolvedLinks;
      const sources = [];
      for (const [sourcePath, dests] of Object.entries(resolvedLinks)) {
        if (!dests || typeof dests !== "object") continue;
        if (Object.prototype.hasOwnProperty.call(dests, activeFile.path)) {
          sources.push(sourcePath);
        }
      }
      if (sources.length === 0) return;
      sources.sort((a, b) => a.localeCompare(b));
      const linkedHeaders = Array.from(container.querySelectorAll(".tree-item-self")).filter((h) => {
        var _a, _b;
        return ((_b = (_a = h.querySelector(".tree-item-inner")) == null ? void 0 : _a.textContent) != null ? _b : "").trim() === "Linked mentions";
      });
      for (const header of linkedHeaders) {
        const sibling = header.nextElementSibling;
        if (!(sibling instanceof HTMLElement)) continue;
        if (!sibling.classList.contains("search-result-container")) continue;
        const titleEls = Array.from(
          sibling.querySelectorAll(".search-result-file-title .tree-item-inner")
        );
        if (titleEls.length === 0) continue;
        let nextIdx = 0;
        for (const el of titleEls) {
          const already = this.linkedTitleAssignedSourcePath.get(el);
          const sourcePath = already != null ? already : sources[nextIdx++];
          if (!sourcePath) continue;
          if (!already) this.linkedTitleAssignedSourcePath.set(el, sourcePath);
          const file = this.plugin.app.vault.getAbstractFileByPath(sourcePath);
          if (!(file instanceof import_obsidian8.TFile)) continue;
          const displayName = await this.getDisplayName(file);
          if (displayName === null) continue;
          el.textContent = displayName;
        }
      }
    })();
    const applyUnlinkedVisibility = (hide) => {
      const previouslyHidden = container.querySelectorAll('[data-pov-unlinked-hidden="true"]');
      previouslyHidden.forEach((el) => {
        el.style.removeProperty("display");
        el.removeAttribute("data-pov-unlinked-hidden");
      });
      if (!hide) return;
      const headers = Array.from(container.querySelectorAll(".tree-item-self")).filter((h) => {
        var _a, _b;
        return ((_b = (_a = h.querySelector(".tree-item-inner")) == null ? void 0 : _a.textContent) != null ? _b : "").trim() === "Unlinked mentions";
      });
      for (const header of headers) {
        header.style.setProperty("display", "none", "important");
        header.setAttribute("data-pov-unlinked-hidden", "true");
        const sibling = header.nextElementSibling;
        if (sibling instanceof HTMLElement && sibling.classList.contains("search-result-container")) {
          sibling.style.setProperty("display", "none", "important");
          sibling.setAttribute("data-pov-unlinked-hidden", "true");
        }
      }
    };
    applyUnlinkedVisibility(this.plugin.settings.hideUnlinkedMentionsInBacklinks);
    const selectors = [
      ".tree-item-inner",
      ".backlink-title",
      ".backlink-file-link",
      ".outgoing-link-file-link",
      ".tree-item-self",
      ".nav-file-title",
      "[data-path]",
      "a.internal-link"
    ];
    const fileElements = /* @__PURE__ */ new Set();
    selectors.forEach((selector) => {
      try {
        container.querySelectorAll(selector).forEach((el) => {
          fileElements.add(el);
        });
      } catch (e) {
      }
    });
    fileElements.forEach((element) => {
      if (this.processedElements.has(element)) {
        return;
      }
      if (this.plugin.settings.hideUnlinkedMentionsInBacklinks) {
        const hiddenContainer = element.closest(".search-result-container");
        if (hiddenContainer && hiddenContainer.style.display === "none") return;
      }
      const file = this.extractFilePathFromElement(element);
      if (file && file instanceof import_obsidian8.TFile) {
        this.updateElementWithFile(element, file);
      }
    });
  }
  /**
   * Update an element with file's display name
   */
  updateElementWithFile(element, file) {
    void (async () => {
      var _a;
      const displayName = await this.getDisplayName(file);
      if (displayName === null) {
        return;
      }
      this.processedElements.add(element);
      element.setAttribute("data-pov-processed", "true");
      const currentText = ((_a = element.textContent) == null ? void 0 : _a.trim()) || "";
      const basename = file.basename;
      const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
      const escapedBasename = escapeRegExp(basename);
      const escapedFileName = escapeRegExp(file.name);
      const bareBasenameTest = new RegExp(`(^|[^A-Za-z0-9])${escapedBasename}(?!\\\\.)(?=([^A-Za-z0-9]|$))`, "i");
      const bareBasenameGlobal = new RegExp(`(^|[^A-Za-z0-9])${escapedBasename}(?!\\\\.)([^A-Za-z0-9]|$)`, "gi");
      const fileNameGlobal = new RegExp(escapedFileName, "g");
      const shouldUpdate = currentText.includes(file.name) || bareBasenameTest.test(currentText) || currentText.includes(`${basename}.md`) || currentText.includes(`${basename}.mdx`);
      if (!shouldUpdate) return;
      const link = element.closest("a") || element.querySelector("a");
      const targetElement = link || element;
      const updateTextInElement = (el) => {
        var _a2;
        if (!el) return false;
        let changed = false;
        try {
          const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
          let n = walker.nextNode();
          while (n) {
            const textNode = n;
            const before = (_a2 = textNode.textContent) != null ? _a2 : "";
            if (!before) {
              n = walker.nextNode();
              continue;
            }
            let after = before;
            if (after.includes(file.name)) {
              after = after.replace(fileNameGlobal, displayName);
            }
            after = after.replace(bareBasenameGlobal, (_match, p1, p2) => {
              return `${p1}${displayName}${p2 != null ? p2 : ""}`;
            });
            if (after !== before) {
              textNode.textContent = after;
              changed = true;
            }
            n = walker.nextNode();
          }
        } catch (e) {
          return false;
        }
        return changed;
      };
      updateTextInElement(targetElement);
    })();
  }
  /**
   * Start observing DOM changes for backlinks
   */
  startObserving() {
    if (this.observer) {
      return;
    }
    this.overrideBacklinkElements();
    let updateTimeout = null;
    this.observer = new MutationObserver((mutations) => {
      let shouldUpdate = false;
      const newElements = [];
      for (const mutation of mutations) {
        if (mutation.type === "childList") {
          for (const node of Array.from(mutation.addedNodes)) {
            if (node instanceof HTMLElement) {
              const embeddedBacklinks = node.closest(".embedded-backlinks");
              const backlinksPanel = node.closest(".backlinks-pane, .backlink-pane, .outgoing-link-pane, .outgoing-links, .backlink-container");
              if (embeddedBacklinks || backlinksPanel) {
                shouldUpdate = true;
                const selectors = [".tree-item-inner", ".backlink-title", ".backlink-file-link", ".outgoing-link-file-link", ".tree-item-self", ".nav-file-title", "[data-path]", "a.internal-link"];
                selectors.forEach((selector) => {
                  var _a;
                  try {
                    const elements = (_a = node.querySelectorAll) == null ? void 0 : _a.call(node, selector);
                    elements == null ? void 0 : elements.forEach((el) => {
                      if (el instanceof HTMLElement) {
                        newElements.push(el);
                      }
                    });
                  } catch (e) {
                  }
                });
              }
            }
          }
        } else if (mutation.type === "characterData") {
          const target = mutation.target;
          if (target instanceof HTMLElement) {
            const embeddedBacklinks = target.closest(".embedded-backlinks");
            const backlinksPanel = target.closest(".backlinks-pane, .backlink-pane, .outgoing-link-pane, .outgoing-links, .backlink-container");
            if (embeddedBacklinks || backlinksPanel) {
              shouldUpdate = true;
            }
          } else if (target.parentElement) {
            const embeddedBacklinks = target.parentElement.closest(".embedded-backlinks");
            const backlinksPanel = target.parentElement.closest(".backlinks-pane, .backlink-pane, .outgoing-link-pane, .outgoing-links, .backlink-container");
            if (embeddedBacklinks || backlinksPanel) {
              shouldUpdate = true;
            }
          }
        }
      }
      newElements.forEach((el) => {
        this.overrideElementTextContent(el);
        const file = this.extractFilePathFromElement(el);
        if (file && file instanceof import_obsidian8.TFile) {
          this.updateElementWithFile(el, file);
        }
      });
      if (shouldUpdate) {
        this.processedElements = /* @__PURE__ */ new WeakSet();
        if (updateTimeout) {
          clearTimeout(updateTimeout);
        }
        updateTimeout = setTimeout(() => {
          this.updateBacklinks();
          this.overrideBacklinkElements();
          updateTimeout = null;
        }, 10);
      }
    });
    this.observer.observe(document.body, {
      childList: true,
      subtree: true,
      characterData: true
    });
  }
  /**
   * Override textContent on all backlink elements
   */
  overrideBacklinkElements() {
    const selectors = [
      ".tree-item-inner",
      ".backlink-title",
      ".backlink-file-link",
      ".outgoing-link-file-link",
      ".tree-item-self",
      ".nav-file-title",
      "[data-path]",
      "a.internal-link"
    ];
    const containers = [
      ...Array.from(document.querySelectorAll(".embedded-backlinks")),
      ...Array.from(document.querySelectorAll(".backlinks-pane")),
      ...Array.from(document.querySelectorAll(".backlink-pane")),
      ...Array.from(document.querySelectorAll(".outgoing-link-pane")),
      ...Array.from(document.querySelectorAll(".outgoing-links")),
      ...Array.from(document.querySelectorAll(".backlink-container"))
    ];
    containers.forEach((container) => {
      selectors.forEach((selector) => {
        try {
          container.querySelectorAll(selector).forEach((el) => {
            if (el instanceof HTMLElement) {
              this.overrideElementTextContent(el);
            }
          });
        } catch (e) {
        }
      });
    });
  }
  /**
   * Override textContent setter on an element to intercept Obsidian's updates
   */
  overrideElementTextContent(element) {
    if (this.modifiedElements.has(element)) {
      return;
    }
    const proto = Object.getPrototypeOf(element);
    const originalDescriptor = Object.getOwnPropertyDescriptor(proto, "textContent");
    if (originalDescriptor && originalDescriptor.set) {
      this.originalTextContentDescriptors.set(element, originalDescriptor);
      try {
        Object.defineProperty(element, "textContent", {
          set: (value) => {
            const file = this.extractFilePathFromElement(element);
            if (file && file instanceof import_obsidian8.TFile) {
              void (async () => {
                const displayName = await this.getDisplayName(file);
                if (displayName && (value === file.basename || value === file.name || value.endsWith(file.basename))) {
                  originalDescriptor.set.call(element, displayName);
                  element.setAttribute("data-pov-processed", "true");
                  this.processedElements.add(element);
                  return;
                }
                originalDescriptor.set.call(element, value);
              })();
              return;
            }
            originalDescriptor.set.call(element, value);
            element.setAttribute("data-pov-processed", "true");
          },
          // eslint-disable-next-line @typescript-eslint/unbound-method -- accessing property descriptor original setter
          get: originalDescriptor.get || (() => {
            var _a, _b;
            return ((_b = (_a = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "textContent")) == null ? void 0 : _a.get) == null ? void 0 : _b.call(element)) || "";
          }),
          configurable: true,
          enumerable: true
        });
      } catch (e) {
        element.setAttribute("data-pov-processed", "true");
      }
    } else {
      element.setAttribute("data-pov-processed", "true");
    }
    this.modifiedElements.add(element);
  }
  /**
   * Stop observing DOM changes
   */
  stopObserving() {
    if (this.observer) {
      this.observer.disconnect();
      this.observer = void 0;
    }
  }
  /**
   * Handle layout changes
   */
  onLayoutChange() {
    if (this.plugin.settings.enableForBacklinks) {
      setTimeout(() => {
        this.updateBacklinks();
      }, 100);
    } else {
      this.stopObserving();
    }
  }
  /**
   * Handle file open events
   */
  onFileOpen() {
    if (this.plugin.settings.enableForBacklinks) {
      setTimeout(() => {
        this.updateEmbeddedBacklinks();
      }, 200);
    }
  }
  /**
   * Clean up on unload
   */
  onunload() {
    this.stopObserving();
    this.originalTextContentDescriptors.forEach((descriptor, element) => {
      try {
        Object.defineProperty(element, "textContent", descriptor);
      } catch (e) {
      }
    });
    this.originalTextContentDescriptors.clear();
    this.modifiedElements = /* @__PURE__ */ new WeakSet();
  }
};

// src/services/TabService.ts
init_frontmatter();
var TabService = class {
  constructor(plugin) {
    this.leafEventRefs = /* @__PURE__ */ new Map();
    this.plugin = plugin;
  }
  /**
   * Renames all markdown tabs to use the configured property value
   * Falls back to file basename if property is not found
   * EXACT copy of the working implementation from obsidian-title-only-tab
   */
  renameTabs() {
    const leaves = this.plugin.app.workspace.getLeavesOfType("markdown");
    leaves.forEach((leaf) => {
      var _a;
      const view = leaf.view;
      const state = leaf.getViewState();
      if (((_a = state.state) == null ? void 0 : _a.file) && !(view == null ? void 0 : view.file)) {
        void leaf.setViewState({ type: state.type, state: state.state });
      }
      if (view == null ? void 0 : view.file) {
        const file = view.file;
        void (async () => {
          const frontmatter = await getFrontmatter(this.plugin.app, file, this.plugin.settings);
          const propertyValue = frontmatter == null ? void 0 : frontmatter[this.plugin.settings.propertyKey];
          const tabHeaderEl = leaf.tabHeaderEl;
          if (tabHeaderEl) {
            tabHeaderEl.setAttribute("data-pov-title-set", "true");
            if (this.plugin.settings.enableForTabs) {
              const titleEl = tabHeaderEl.querySelector(".workspace-tab-header-inner-title");
              const displayText = propertyValue ? String(propertyValue) : file.basename;
              if (titleEl) {
                titleEl.setText(displayText);
              }
              tabHeaderEl.setAttribute("aria-label", displayText);
              tabHeaderEl.setAttribute("title", displayText);
            }
          }
        })();
      }
    });
  }
  /**
   * Register pinned-change event listeners on all markdown leaves
   * This ensures tab titles are re-applied when tabs are pinned/unpinned
   */
  registerLeafListeners() {
    const currentLeaves = this.plugin.app.workspace.getLeavesOfType("markdown");
    const currentLeafSet = new Set(currentLeaves);
    currentLeaves.forEach((leaf) => {
      if (!this.leafEventRefs.has(leaf)) {
        const eventRef = leaf.on("pinned-change", () => {
          requestAnimationFrame(() => {
            setTimeout(() => {
              void this.renameTabs();
            }, 50);
          });
        });
        this.leafEventRefs.set(leaf, eventRef);
      }
    });
    for (const [leaf, eventRef] of this.leafEventRefs.entries()) {
      if (!currentLeafSet.has(leaf)) {
        leaf.offref(eventRef);
        this.leafEventRefs.delete(leaf);
      }
    }
  }
  /**
   * Register event listeners for tab renaming
   * EXACT copy of the working implementation from obsidian-title-only-tab
   */
  registerEvents() {
    this.renameTabs();
    this.registerLeafListeners();
    this.plugin.registerEvent(
      this.plugin.app.workspace.on("layout-change", () => {
        void this.renameTabs();
        this.registerLeafListeners();
      })
    );
    this.plugin.registerEvent(
      this.plugin.app.workspace.on("active-leaf-change", () => this.renameTabs())
    );
    this.plugin.registerEvent(
      this.plugin.app.workspace.on("file-open", () => this.renameTabs())
    );
    this.plugin.registerEvent(
      this.plugin.app.vault.on("rename", () => this.renameTabs())
    );
    this.plugin.registerEvent(
      this.plugin.app.metadataCache.on("changed", () => this.renameTabs())
    );
  }
  /**
   * Update tabs (public method for manual updates)
   */
  updateTabs() {
    void this.renameTabs();
  }
  /**
   * Cleanup on unload
   */
  onunload() {
    for (const [leaf, eventRef] of this.leafEventRefs.entries()) {
      leaf.offref(eventRef);
    }
    this.leafEventRefs.clear();
  }
};

// src/services/ExplorerService.ts
var import_obsidian9 = require("obsidian");
var ExplorerService = class {
  constructor(plugin) {
    // Public so ExplorerFileItemMutator can access it
    this.explorerView = null;
    this.modified = /* @__PURE__ */ new WeakMap();
    this.plugin = plugin;
  }
  /**
   * Get the file explorer view
   */
  getExplorerView() {
    if (this.explorerView === null) {
      const leaves = this.plugin.app.workspace.getLeavesOfType("file-explorer");
      if (leaves.length === 0) {
        return null;
      }
      const leaf = leaves[0];
      if (leaf && leaf.view) {
        this.explorerView = leaf.view;
      }
    }
    return this.explorerView;
  }
  /**
   * Get folder note title for a folder
   * Returns the frontmatter title property from the folder note file if it exists
   */
  getFolderNoteTitle(folder) {
    var _a;
    if (!this.plugin.settings.folderNoteFilename || this.plugin.settings.folderNoteFilename.trim() === "") {
      return null;
    }
    const folderNoteFilename = this.plugin.settings.folderNoteFilename.trim();
    const folderNotePath = `${folder.path}/${folderNoteFilename}.md`;
    const folderNoteFile = this.plugin.app.vault.getAbstractFileByPath(folderNotePath);
    if (folderNoteFile instanceof import_obsidian9.TFile) {
      const cache = this.plugin.app.metadataCache.getFileCache(folderNoteFile);
      const propertyValue = (_a = cache == null ? void 0 : cache.frontmatter) == null ? void 0 : _a[this.plugin.settings.propertyKey];
      if (propertyValue) {
        return String(propertyValue);
      }
    }
    return null;
  }
  /**
   * Resolve title for a file or folder
   * Public so ExplorerFileItemMutator can access it
   */
  async resolveTitle(item) {
    if (item.file instanceof import_obsidian9.TFile) {
      const { getFrontmatter: getFrontmatter2, isFileTypeSupported: isFileTypeSupported2 } = await Promise.resolve().then(() => (init_frontmatter(), frontmatter_exports));
      if (!isFileTypeSupported2(item.file.extension, this.plugin.settings)) {
        return null;
      }
      const frontmatter = await getFrontmatter2(this.plugin.app, item.file, this.plugin.settings);
      const propertyValue = frontmatter == null ? void 0 : frontmatter[this.plugin.settings.propertyKey];
      return propertyValue ? String(propertyValue) : null;
    } else if (item.file instanceof import_obsidian9.TFolder) {
      return this.getFolderNoteTitle(item.file);
    }
    return null;
  }
  /**
   * Update all file explorer items
   */
  updateAllItems() {
    const view = this.getExplorerView();
    if (!view || !view.fileItems) {
      return;
    }
    const items = Object.values(view.fileItems);
    for (const item of items) {
      if (!this.modified.has(item)) {
        this.modified.set(item, new ExplorerFileItemMutator(item, this));
      }
      item.updateTitle();
    }
  }
  /**
   * Restore all original titles
   */
  restoreAllItems() {
    const view = this.getExplorerView();
    if (!view || !view.fileItems) {
      return;
    }
    const items = Object.values(view.fileItems);
    for (const item of items) {
      if (this.modified.has(item)) {
        const mutator = this.modified.get(item);
        mutator == null ? void 0 : mutator.destroy();
        this.modified.delete(item);
        item.updateTitle();
      }
    }
  }
  /**
   * Register events and initialize
   */
  registerEvents() {
    if (!this.plugin.settings.enableForExplorer) {
      return;
    }
    this.plugin.app.workspace.onLayoutReady(() => {
      this.explorerView = null;
      this.updateAllItems();
    });
    this.plugin.registerEvent(
      this.plugin.app.workspace.on("layout-change", () => {
        this.explorerView = null;
        if (this.plugin.settings.enableForExplorer) {
          this.updateAllItems();
        }
      })
    );
    this.plugin.registerEvent(
      this.plugin.app.metadataCache.on("changed", () => {
        if (this.plugin.settings.enableForExplorer) {
          this.updateAllItems();
        }
      })
    );
    this.plugin.registerEvent(
      this.plugin.app.vault.on("rename", () => {
        if (this.plugin.settings.enableForExplorer) {
          this.explorerView = null;
          setTimeout(() => this.updateAllItems(), 100);
        }
      })
    );
  }
  /**
   * Update explorer when settings change
   */
  updateExplorer() {
    if (this.plugin.settings.enableForExplorer) {
      this.explorerView = null;
      this.registerEvents();
      setTimeout(() => this.updateAllItems(), 100);
    } else {
      this.restoreAllItems();
    }
  }
  /**
   * Cleanup on unload
   */
  onunload() {
    this.restoreAllItems();
    this.explorerView = null;
  }
};
var ExplorerFileItemMutator = class {
  constructor(item, service) {
    this.item = item;
    this.service = service;
    const proto = Object.getPrototypeOf(item);
    this.originalUpdateTitle = proto.updateTitle.bind(item);
    this.originalStartRename = proto.startRename ? proto.startRename.bind(item) : void 0;
    item.updateTitle = this.updateTitle.bind(this);
    if (proto.startRename) {
      item.startRename = this.startRename.bind(this);
    }
  }
  updateTitle() {
    this.originalUpdateTitle();
    if (this.service.plugin.settings.enableForExplorer) {
      void (async () => {
        const title = await this.service.resolveTitle(this.item);
        if (title && title.length > 0) {
          this.item.innerEl.setText(title);
        }
      })();
    }
  }
  startRename() {
    var _a;
    this.item.innerEl.setText(this.item.getTitle());
    return (_a = this.originalStartRename) == null ? void 0 : _a.call(this);
  }
  destroy() {
    const proto = Object.getPrototypeOf(this.item);
    this.item.updateTitle = this.originalUpdateTitle;
    if (proto.startRename && this.originalStartRename) {
      this.item.startRename = this.originalStartRename;
    }
  }
};

// src/services/WindowFrameService.ts
var import_obsidian10 = require("obsidian");
init_frontmatter();
var WindowFrameService = class {
  constructor(plugin) {
    this.originalUpdateTitle = null;
    this.enabled = false;
    this.plugin = plugin;
  }
  /**
   * Get the title for the active file
   */
  getActiveFileTitle() {
    var _a;
    const activeFile = this.plugin.app.workspace.getActiveFile();
    if (activeFile instanceof import_obsidian10.TFile) {
      if (activeFile.extension === "md") {
        const fileCache = this.plugin.app.metadataCache.getFileCache(activeFile);
        const propertyValue = (_a = fileCache == null ? void 0 : fileCache.frontmatter) == null ? void 0 : _a[this.plugin.settings.propertyKey];
        if (propertyValue) {
          return String(propertyValue);
        }
        return activeFile.basename;
      }
      if (activeFile.extension === "mdx" && this.plugin.settings.enableMdxSupport) {
        void (async () => {
          const frontmatter = await getFrontmatter(this.plugin.app, activeFile, this.plugin.settings);
          const propertyValue = frontmatter == null ? void 0 : frontmatter[this.plugin.settings.propertyKey];
          if (propertyValue) {
            const app = this.plugin.app;
            if (typeof app.getAppTitle === "function") {
              document.title = app.getAppTitle(String(propertyValue));
            } else {
              const vaultName = this.plugin.app.vault.getName();
              document.title = `${String(propertyValue)} - ${vaultName}`;
            }
          }
        })();
        return activeFile.basename;
      }
      return activeFile.basename;
    }
    return "";
  }
  /**
   * Override updateTitle to use property-based title
   */
  updateTitle() {
    if (!this.enabled) {
      if (this.originalUpdateTitle) {
        this.originalUpdateTitle();
      }
      return;
    }
    const title = this.getActiveFileTitle();
    if (title) {
      const app = this.plugin.app;
      if (typeof app.getAppTitle === "function") {
        document.title = app.getAppTitle(title);
      } else {
        const vaultName = this.plugin.app.vault.getName();
        document.title = `${title} - ${vaultName}`;
      }
    } else {
      if (this.originalUpdateTitle) {
        this.originalUpdateTitle();
      }
    }
  }
  /**
   * Enable the window frame feature
   */
  enable() {
    if (this.enabled) {
      return;
    }
    const workspace = this.plugin.app.workspace;
    if (workspace.updateTitle) {
      this.originalUpdateTitle = workspace.updateTitle.bind(workspace);
      workspace.updateTitle = this.updateTitle.bind(this);
      this.updateTitle();
      this.enabled = true;
    }
  }
  /**
   * Disable the window frame feature
   */
  disable() {
    if (!this.enabled) {
      return;
    }
    const workspace = this.plugin.app.workspace;
    if (workspace.updateTitle && this.originalUpdateTitle) {
      workspace.updateTitle = this.originalUpdateTitle;
      workspace.updateTitle();
      this.originalUpdateTitle = null;
      this.enabled = false;
    }
  }
  /**
   * Register events for window frame updates
   */
  registerEvents() {
    if (!this.plugin.settings.enableForWindowFrame) {
      return;
    }
    this.plugin.registerEvent(
      this.plugin.app.workspace.on("file-open", () => {
        if (this.enabled) {
          this.updateTitle();
        }
      })
    );
    this.plugin.registerEvent(
      this.plugin.app.metadataCache.on("changed", () => {
        if (this.enabled) {
          this.updateTitle();
        }
      })
    );
  }
  /**
   * Update window frame when settings change
   */
  updateWindowFrame() {
    if (this.plugin.settings.enableForWindowFrame) {
      this.enable();
      this.registerEvents();
    } else {
      this.disable();
    }
  }
  /**
   * Cleanup on unload
   */
  onunload() {
    this.disable();
  }
};

// src/services/BookmarkService.ts
var import_obsidian11 = require("obsidian");
init_frontmatter();
var BookmarkService = class {
  constructor(plugin) {
    this.isHooked = false;
    this.plugin = plugin;
  }
  /**
   * Update bookmarks hook based on settings
   */
  updateBookmarks() {
    if (this.plugin.settings.enableForBookmarks && !this.isHooked) {
      this.hookBookmarks();
    } else if (!this.plugin.settings.enableForBookmarks && this.isHooked) {
      this.unhookBookmarks();
    }
  }
  /**
   * Hook into bookmark functionality using DOM observation
   */
  hookBookmarks() {
    const existingModal = document.querySelector(".modal");
    if (existingModal instanceof HTMLElement) {
      this.handleModalAppearance(existingModal);
    }
    this.mutationObserver = new MutationObserver((mutations) => {
      for (const mutation of mutations) {
        mutation.addedNodes.forEach((node) => {
          if (node instanceof HTMLElement) {
            const modalEl = node.classList.contains("modal") ? node : node.querySelector(".modal");
            if (modalEl) {
              this.handleModalAppearance(modalEl);
            }
          }
        });
      }
    });
    this.mutationObserver.observe(document.body, {
      childList: true,
      subtree: true
    });
    this.isHooked = true;
  }
  /**
   * Handle when a modal appears
   */
  handleModalAppearance(modalEl) {
    let attempts = 0;
    const maxAttempts = 30;
    const tryIdentifyAndPopulate = async () => {
      var _a;
      const titleEl = modalEl.querySelector(".modal-title");
      const titleText = ((_a = titleEl == null ? void 0 : titleEl.textContent) == null ? void 0 : _a.toLowerCase()) || "";
      const isBookmarkModal = titleText.includes("bookmark") || modalEl.querySelector('input[placeholder*="bookmark"]') !== null || modalEl.querySelector('input[placeholder*="Bookmark"]') !== null;
      if (isBookmarkModal) {
        const settingItems = modalEl.querySelectorAll(".setting-item");
        let titleInput = null;
        let pathInput = null;
        settingItems.forEach((item) => {
          var _a2;
          const nameEl = item.querySelector(".setting-item-name");
          const nameText = ((_a2 = nameEl == null ? void 0 : nameEl.textContent) == null ? void 0 : _a2.toLowerCase().trim()) || "";
          if (nameText === "title") {
            titleInput = item.querySelector('input[type="text"]');
          } else if (nameText === "path") {
            pathInput = item.querySelector('input[type="text"]');
          }
        });
        if (!titleInput) {
          const allInputs = modalEl.querySelectorAll('input[type="text"]');
          if (allInputs.length >= 2) {
            pathInput = allInputs[0];
            titleInput = allInputs[1];
          }
        }
        if (titleInput) {
          let file = this.plugin.app.workspace.getActiveFile();
          if (pathInput && pathInput.value) {
            const path = pathInput.value;
            const abstractFile = this.plugin.app.vault.getAbstractFileByPath(path) || this.plugin.app.vault.getAbstractFileByPath(path + ".md") || this.plugin.app.vault.getAbstractFileByPath(path + ".mdx");
            if (abstractFile instanceof import_obsidian11.TFile) {
              file = abstractFile;
            }
          }
          if (file) {
            const frontmatter = await getFrontmatter(this.plugin.app, file, this.plugin.settings);
            const propertyValue = frontmatter == null ? void 0 : frontmatter[this.plugin.settings.propertyKey];
            if (propertyValue !== void 0 && propertyValue !== null) {
              let displayValue = "";
              if (typeof propertyValue === "string") {
                displayValue = propertyValue;
              } else if (typeof propertyValue === "number" || typeof propertyValue === "boolean") {
                displayValue = String(propertyValue);
              }
              if (displayValue && displayValue.trim() !== "") {
                const currentValue = titleInput.value;
                const isDefault = currentValue === "" || currentValue === file.basename || currentValue === file.name;
                if (isDefault) {
                  titleInput.value = displayValue;
                  titleInput.dispatchEvent(new Event("input", { bubbles: true }));
                  titleInput.select();
                  return true;
                }
              }
            }
          }
        }
      }
      attempts++;
      if (attempts < maxAttempts) {
        setTimeout(() => void tryIdentifyAndPopulate(), 50);
      }
      return false;
    };
    void tryIdentifyAndPopulate();
  }
  /**
   * Stop observing for bookmark modals
   */
  unhookBookmarks() {
    if (this.mutationObserver) {
      this.mutationObserver.disconnect();
      this.mutationObserver = void 0;
    }
    this.isHooked = false;
  }
  /**
   * Cleanup on unload
   */
  onunload() {
    this.unhookBookmarks();
  }
};

// src/main.ts
var PropertyOverFileNamePlugin = class extends import_obsidian12.Plugin {
  constructor(app, manifest) {
    super(app, manifest);
    try {
      this.registerExtensions(["mdx"], "markdown");
    } catch (error) {
      const errorMsg = error.message;
      if (!errorMsg.includes("existing file extension")) {
        console.error("[POV] Unexpected MDX registration error in constructor:", errorMsg);
      }
    }
  }
  async onload() {
    await this.loadSettings();
    if (this.settings.enableMdxSupport) {
      try {
        this.registerExtensions(["mdx"], "markdown");
      } catch (error) {
        const errorMsg = error.message;
        if (!errorMsg.includes("existing file extension")) {
          console.error("Unexpected MDX registration error:", errorMsg);
          this.settings.enableMdxSupport = false;
        }
      }
      const mdxFiles = this.app.vault.getFiles().filter((f) => f.extension === "mdx");
      for (const file of mdxFiles) {
        this.app.metadataCache.trigger("changed", file);
      }
    }
    this.quickSwitcherService = new QuickSwitcherService(this);
    this.dragDropService = new DragDropService(this);
    this.cacheService = new CacheService(this);
    this.graphViewService = new GraphViewService(this);
    this.backlinkService = new BacklinkService(this);
    this.tabService = new TabService(this);
    this.explorerService = new ExplorerService(this);
    this.windowFrameService = new WindowFrameService(this);
    this.bookmarkService = new BookmarkService(this);
    this.tabService.registerEvents();
    this.explorerService.registerEvents();
    this.windowFrameService.registerEvents();
    this.bookmarkService.updateBookmarks();
    if (this.settings.enableMdxSupport) {
      (() => {
        const mdxFiles = this.app.vault.getFiles().filter(
          (f) => f instanceof import_obsidian12.TFile && f.extension === "mdx"
        );
        for (const file of mdxFiles) {
          void frontmatterCache.get(this.app, file, this.settings);
        }
      })();
    }
    setTimeout(() => {
      this.updateLinkSuggester();
      this.updateQuickSwitcher();
      this.updateGraphView();
      this.updateBacklinks();
      this.updateTabs();
      this.updateExplorer();
      this.updateWindowFrame();
      this.updateBookmarks();
    }, 1e3);
    this.app.workspace.onLayoutReady(() => {
      this.graphViewService.onLayoutChange();
      this.backlinkService.onLayoutChange();
      void this.tabService.renameTabs();
      this.updateExplorer();
      this.updateWindowFrame();
      this.updateBookmarks();
      setTimeout(() => {
        this.graphViewService.refreshGraphView();
      }, 500);
    });
    this.registerEvent(
      this.app.workspace.on("layout-change", () => {
        this.graphViewService.onLayoutChange();
        this.backlinkService.onLayoutChange();
      })
    );
    this.registerEvent(
      this.app.workspace.on("file-open", () => {
        this.backlinkService.onFileOpen();
      })
    );
    this.registerEvent(
      this.app.vault.on("modify", (file) => {
        if (file instanceof import_obsidian12.TFile && (file.extension === "md" || file.extension === "mdx" && this.settings.enableMdxSupport)) {
          this.cacheService.invalidateCache(file);
          frontmatterCache.invalidate(file.path);
        }
      })
    );
    this.registerEvent(
      this.app.vault.on("rename", (file, oldPath) => {
        if (file instanceof import_obsidian12.TFile && (file.extension === "md" || file.extension === "mdx" && this.settings.enableMdxSupport)) {
          this.cacheService.invalidateCache(file);
          frontmatterCache.invalidate(file.path);
        }
      })
    );
    this.registerEvent(
      this.app.vault.on("delete", (file) => {
        if (file instanceof import_obsidian12.TFile && (file.extension === "md" || file.extension === "mdx" && this.settings.enableMdxSupport)) {
          this.cacheService.invalidateCache(file);
          frontmatterCache.invalidate(file.path);
        }
      })
    );
    this.registerEvent(
      this.app.metadataCache.on("changed", (file) => {
        if (file instanceof import_obsidian12.TFile && (file.extension === "md" || file.extension === "mdx" && this.settings.enableMdxSupport)) {
          this.cacheService.rebuildCache();
          if (this.settings.enableForGraphView) {
            this.graphViewService.refreshGraphView();
          }
          if (this.settings.enableForBacklinks) {
            this.backlinkService.updateBacklinks();
          }
          if (this.settings.enableForExplorer) {
            this.explorerService.updateExplorer();
          }
          if (this.settings.enableForWindowFrame) {
            this.windowFrameService.updateWindowFrame();
          }
          if (this.settings.enableForBookmarks) {
            this.updateBookmarks();
          }
        }
      })
    );
    this.registerEvent(
      this.app.metadataCache.on("resolved", () => {
        this.cacheService.rebuildCache();
      })
    );
    this.registerEvent(
      this.app.workspace.on("editor-drop", (event, editor) => {
        if (this.settings.enableForDragDrop) {
          this.dragDropService.handleDragDrop(event, editor);
        }
      })
    );
    this.registerDomEvent(document, "drop", (event) => {
      if (this.settings.enableForDragDrop) {
        this.dragDropService.handleDOMDrop(event);
      }
    });
    registerCommands(this);
    this.addSettingTab(new SettingTab(this.app, this));
  }
  updateLinkSuggester() {
    const editorSuggest = this.app.workspace.editorSuggest;
    if (!editorSuggest) return;
    if (this.suggest) {
      editorSuggest.suggests = editorSuggest.suggests.filter((s) => s !== this.suggest);
      this.suggest = void 0;
    }
    if (this.settings.enableForLinking) {
      this.suggest = new LinkTitleSuggest(this);
      this.registerEditorSuggest(this.suggest);
      this.cacheService.setSuggest(this.suggest);
      editorSuggest.suggests = editorSuggest.suggests.filter((s) => !s.constructor.name.includes("LinkSuggest"));
      editorSuggest.suggests.unshift(this.suggest);
    }
  }
  updateQuickSwitcher() {
    this.quickSwitcherService.updateQuickSwitcher();
  }
  updateGraphView() {
    this.graphViewService.updateGraphView();
  }
  updateBacklinks() {
    this.backlinkService.updateBacklinks();
  }
  updateTabs() {
    this.tabService.updateTabs();
  }
  updateExplorer() {
    this.explorerService.updateExplorer();
  }
  updateWindowFrame() {
    this.windowFrameService.updateWindowFrame();
  }
  updateBookmarks() {
    this.bookmarkService.updateBookmarks();
  }
  rebuildCache() {
    this.cacheService.rebuildCache();
  }
  onunload() {
    const editorSuggest = this.app.workspace.editorSuggest;
    if (editorSuggest && this.suggest) {
      editorSuggest.suggests = editorSuggest.suggests.filter((s) => s !== this.suggest);
    }
    this.quickSwitcherService.restoreOriginalCommand();
    this.graphViewService.onunload();
    this.backlinkService.onunload();
    this.tabService.onunload();
    this.explorerService.onunload();
    this.windowFrameService.onunload();
    this.bookmarkService.onunload();
  }
  async loadSettings() {
    const loadedData = await this.loadData();
    this.settings = Object.assign({}, DEFAULT_SETTINGS, loadedData != null ? loadedData : {});
  }
  async saveSettings(prevQuickSwitcherState, prevTabState) {
    await this.saveData(this.settings);
    if (prevQuickSwitcherState !== void 0 && prevQuickSwitcherState !== this.settings.enableForQuickSwitcher) {
      this.updateQuickSwitcher();
    }
    if (prevTabState !== void 0 && prevTabState !== this.settings.enableForTabs) {
      void this.tabService.registerEvents();
      this.updateTabs();
    }
    this.updateGraphView();
  }
};
//# sourceMappingURL=data:application/json;base64,[encoded data, 391876 characters]
