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

var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

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

// src/settings.ts
var DEFAULT_SETTINGS = {
  historyPropertyName: "aliases",
  ignoreRegexes: ["^_", "^Untitled$", "^Untitled \\d+$"],
  timeoutSeconds: 5,
  caseSensitive: false,
  autoCreateFrontmatter: true,
  includeFolders: [],
  excludeFolders: [],
  fileExtensions: ["md"],
  trackFolderRenames: "",
  excludePropertyName: ""
};

// src/ui/settings-tab.ts
var import_obsidian2 = require("obsidian");

// src/utils/settings-compat.ts
var import_obsidian = require("obsidian");
var Obsidian = __toESM(require("obsidian"), 1);
function createSettingsGroup(containerEl, heading, manifestId) {
  if ((0, import_obsidian.requireApiVersion)("1.11.0")) {
    const ObsidianTyped = Obsidian;
    const SettingGroupCtor = ObsidianTyped.SettingGroup;
    const group = new SettingGroupCtor(containerEl);
    if (heading) {
      group.setHeading(heading);
    }
    return {
      addSetting(cb) {
        group.addSetting(cb);
      }
    };
  } else {
    if (manifestId) {
      containerEl.addClass(`${manifestId}-settings-compat`);
    }
    const groupEl = containerEl.createDiv("setting-group");
    if (heading) {
      const headingEl = groupEl.createDiv("setting-group-heading");
      headingEl.createEl("h3", { text: heading });
    }
    return {
      addSetting(cb) {
        const setting = new import_obsidian.Setting(groupEl);
        cb(setting);
      }
    };
  }
}

// src/ui/settings-tab.ts
var FileNameHistorySettingTab = class extends import_obsidian2.PluginSettingTab {
  constructor(app, plugin) {
    super(app, plugin);
    this.icon = "lucide-forward";
    this.plugin = plugin;
  }
  display() {
    const { containerEl } = this;
    containerEl.empty();
    const saveSettings = () => {
      void this.plugin.saveSettings();
    };
    const generalGroup = createSettingsGroup(containerEl, void 0, "file-name-history");
    generalGroup.addSetting((setting) => {
      setting.setName("History property name").setDesc("The list property to store file name history.").addText(
        (text) => text.setPlaceholder("aliases").setValue(this.plugin.settings.historyPropertyName).onChange((value) => {
          this.plugin.settings.historyPropertyName = value || "aliases";
          saveSettings();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("Timeout seconds").setDesc("Time in seconds the name must be stable before adding to the configured property.").addSlider(
        (slider) => slider.setLimits(1, 20, 1).setValue(this.plugin.settings.timeoutSeconds).setDynamicTooltip().onChange((value) => {
          this.plugin.settings.timeoutSeconds = value;
          saveSettings();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("Case-sensitive uniqueness").setDesc("If enabled, treat case differences as unique values in the configured property.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.caseSensitive).onChange((value) => {
          this.plugin.settings.caseSensitive = value;
          saveSettings();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("Auto-create history property").setDesc("Automatically create the configured property if missing.").addToggle(
        (toggle) => toggle.setValue(this.plugin.settings.autoCreateFrontmatter).onChange((value) => {
          this.plugin.settings.autoCreateFrontmatter = value;
          saveSettings();
        })
      );
    });
    generalGroup.addSetting((setting) => {
      setting.setName("File extensions").setDesc("Comma-separated list of file extensions to track.").addText(
        (text) => text.setPlaceholder("Md, txt").setValue(this.plugin.settings.fileExtensions.join(",")).onChange((value) => {
          this.plugin.settings.fileExtensions = value.split(",").map((s) => s.trim()).filter((s) => s);
          saveSettings();
        })
      );
    });
    const filteringGroup = createSettingsGroup(containerEl, "Filtering", "file-name-history");
    const foldersGroup = createSettingsGroup(containerEl, "Folders", "file-name-history");
    const advancedGroup = createSettingsGroup(containerEl, "Advanced", "file-name-history");
    filteringGroup.addSetting((setting) => {
      setting.setName("Ignore regex patterns").setDesc(
        "Comma-separated regex patterns for file names or immediate parent folder names to ignore (e.g., ^_ for underscore prefixes, ^untitled$ for untitled). Leave empty to disable."
      ).addText(
        (text) => text.setPlaceholder("^_, ^untitled$, ^untitled \\d+$").setValue(this.plugin.settings.ignoreRegexes.join(",")).onChange((value) => {
          this.plugin.settings.ignoreRegexes = value.split(",").map((s) => s.trim()).filter((s) => s);
          saveSettings();
        })
      );
    });
    filteringGroup.addSetting((setting) => {
      setting.setName("Exclude property name").setDesc(
        "Name of a boolean property to check in files. Files with this property set to true will be excluded from tracking. Takes priority over folder filtering."
      ).addText(
        (text) => text.setPlaceholder("Skip-rename-tracking").setValue(this.plugin.settings.excludePropertyName).onChange((value) => {
          this.plugin.settings.excludePropertyName = value;
          saveSettings();
        })
      );
    });
    foldersGroup.addSetting((setting) => {
      setting.setName("Include folders").setDesc(
        "Comma-separated list of folder paths to include. If empty, all folders are included. Use {vault} or {root} to include only files directly in the vault root (no subfolders)."
      ).addText(
        (text) => text.setValue(this.plugin.settings.includeFolders.join(",")).onChange((value) => {
          this.plugin.settings.includeFolders = value.split(",").map((s) => s.trim()).filter((s) => s);
          saveSettings();
        })
      );
    });
    foldersGroup.addSetting((setting) => {
      setting.setName("Exclude folders").setDesc(
        'Comma-separated list of folder paths to exclude. Supports wildcards: use "folder/*" to exclude direct children, "folder/**" to exclude all descendants. Use {vault} or {root} to exclude files directly in the vault root.'
      ).addText(
        (text) => text.setValue(this.plugin.settings.excludeFolders.join(",")).onChange((value) => {
          this.plugin.settings.excludeFolders = value.split(",").map((s) => s.trim()).filter((s) => s);
          saveSettings();
        })
      );
    });
    advancedGroup.addSetting((setting) => {
      setting.setName("Track folder renames for specific file name").setDesc(
        "If a Markdown file matches this file name, store old immediate parent folder names in the configured property when parent folders are renamed."
      ).addText(
        (text) => text.setPlaceholder("Index").setValue(this.plugin.settings.trackFolderRenames).onChange((value) => {
          this.plugin.settings.trackFolderRenames = value;
          saveSettings();
        })
      );
    });
  }
};

// src/utils/history-processor.ts
var import_obsidian3 = require("obsidian");
var HistoryProcessor = class {
  constructor(app, settings) {
    this.app = app;
    this.settings = settings;
  }
  async processAliasesManually(path, queue) {
    const file = this.app.vault.getFileByPath(path);
    if (!file) {
      return;
    }
    const regexes = [];
    for (const regexStr of this.settings.ignoreRegexes) {
      try {
        regexes.push(new RegExp(regexStr));
      } catch (e) {
        console.error(`Invalid ignore regex: ${regexStr}`, e);
      }
    }
    const toAdd = [];
    const currentBasename = file.basename;
    const currentBasenameLower = currentBasename.toLowerCase();
    for (const name of queue) {
      if (regexes.some((re) => re.test(name))) {
        continue;
      }
      const nameLower = name.toLowerCase();
      if (this.settings.caseSensitive && name === currentBasename || !this.settings.caseSensitive && nameLower === currentBasenameLower) {
        continue;
      }
      toAdd.push(name);
    }
    if (toAdd.length === 0) {
      return;
    }
    let content = await this.app.vault.read(file);
    const frontmatterRegex = /^---\n([\s\S]*?)\n---\n/;
    const match = content.match(frontmatterRegex);
    let frontmatter = {};
    let frontmatterText = "";
    let bodyContent = content;
    if (match) {
      frontmatterText = match[1];
      bodyContent = content.slice(match[0].length);
      try {
        const parsed = (0, import_obsidian3.parseYaml)(frontmatterText);
        frontmatter = parsed && typeof parsed === "object" ? parsed : {};
      } catch (e) {
        console.error(`Error parsing properties:`, e);
        frontmatter = {};
      }
    } else {
      bodyContent = content;
    }
    let aliases = frontmatter[this.settings.historyPropertyName];
    if (!Array.isArray(aliases)) {
      const hasFrontmatter = Object.keys(frontmatter).length > 0;
      if (hasFrontmatter && !this.settings.autoCreateFrontmatter) {
        return;
      }
      aliases = [];
    }
    const aliasesArray = aliases;
    const existing = new Set(
      this.settings.caseSensitive ? aliasesArray : aliasesArray.map((a) => a.toLowerCase())
    );
    let added = false;
    for (const name of toAdd) {
      const checkName = this.settings.caseSensitive ? name : name.toLowerCase();
      if (!existing.has(checkName)) {
        aliasesArray.push(name);
        existing.add(checkName);
        added = true;
      }
    }
    if (!added) {
      return;
    }
    frontmatter[this.settings.historyPropertyName] = aliasesArray;
    const newFrontmatterText = (0, import_obsidian3.stringifyYaml)(frontmatter).trim();
    const newContent = `---
${newFrontmatterText}
---
${bodyContent}`;
    await this.app.vault.modify(file, newContent);
  }
  async processAliases(path, queue) {
    const file = this.app.vault.getFileByPath(path);
    if (!file) return;
    const regexes = [];
    for (const regexStr of this.settings.ignoreRegexes) {
      try {
        regexes.push(new RegExp(regexStr));
      } catch (e) {
        console.error(`Invalid ignore regex: ${regexStr}`, e);
      }
    }
    const toAdd = [];
    const currentBasename = file.basename;
    const currentBasenameLower = currentBasename.toLowerCase();
    for (const name of queue) {
      if (regexes.some((re) => re.test(name))) {
        continue;
      }
      const nameLower = name.toLowerCase();
      if (this.settings.caseSensitive && name === currentBasename || !this.settings.caseSensitive && nameLower === currentBasenameLower) {
        continue;
      }
      toAdd.push(name);
    }
    if (toAdd.length === 0) {
      return;
    }
    if (file.extension !== "md") {
      await this.processAliasesManually(path, queue);
      return;
    }
    await this.app.fileManager.processFrontMatter(file, (fm) => {
      let aliases = fm[this.settings.historyPropertyName];
      if (!Array.isArray(aliases)) {
        const hasFrontmatter = Object.keys(fm).length > 0;
        if (hasFrontmatter && !this.settings.autoCreateFrontmatter) {
          return;
        }
        aliases = [];
        fm[this.settings.historyPropertyName] = aliases;
      }
      const aliasesArray = aliases;
      const existing = new Set(
        this.settings.caseSensitive ? aliasesArray : aliasesArray.map((a) => a.toLowerCase())
      );
      for (const name of toAdd) {
        const checkName = this.settings.caseSensitive ? name : name.toLowerCase();
        if (!existing.has(checkName)) {
          aliasesArray.push(name);
          existing.add(checkName);
        }
      }
    });
  }
};

// src/utils/path-utils.ts
function getBasename(path) {
  const name = path.split("/").pop() || "";
  return name.replace(/\.[^/.]+$/, "");
}
function getImmediateParentName(path) {
  const parts = path.split("/");
  parts.pop();
  return parts.pop() || "";
}

// src/main.ts
var FileNameHistoryPlugin = class extends import_obsidian4.Plugin {
  constructor() {
    super(...arguments);
    this.debounceMap = /* @__PURE__ */ new Map();
  }
  async onload() {
    await this.loadSettings();
    this.historyProcessor = new HistoryProcessor(this.app, this.settings);
    this.addSettingTab(new FileNameHistorySettingTab(this.app, this));
    this.registerEvent(
      this.app.vault.on("rename", (file, oldPath) => {
        this.handleRename(file, oldPath);
      })
    );
  }
  onunload() {
    for (const entry of this.debounceMap.values()) {
      if (entry.timeoutId !== 0) {
        window.clearTimeout(entry.timeoutId);
      }
    }
    this.debounceMap.clear();
  }
  async loadSettings() {
    const loadedData = await this.loadData();
    this.settings = Object.assign({}, DEFAULT_SETTINGS, loadedData);
  }
  async saveSettings() {
    await this.saveData(this.settings);
  }
  isPathInFolder(path, folder) {
    if (folder.includes("{vault}") || folder.includes("{root}")) {
      const resolvedFolder = folder.replace(/\{vault\}|\{root\}/g, "");
      if (resolvedFolder === "" || resolvedFolder === "/") {
        const isVaultRoot = !path.includes("/");
        return isVaultRoot;
      }
      return path.startsWith(resolvedFolder + "/") || path === resolvedFolder;
    }
    return path.startsWith(folder + "/") || path === folder;
  }
  isPathExcluded(path, excludePattern) {
    if (excludePattern.includes("{vault}") || excludePattern.includes("{root}")) {
      const resolvedPattern = excludePattern.replace(/\{vault\}|\{root\}/g, "");
      if (resolvedPattern === "" || resolvedPattern === "/") {
        return !path.includes("/");
      }
      excludePattern = resolvedPattern;
    }
    if (excludePattern.endsWith("/**")) {
      const baseFolder = excludePattern.slice(0, -3);
      return path.startsWith(baseFolder + "/") || path === baseFolder;
    } else if (excludePattern.endsWith("/*")) {
      const baseFolder = excludePattern.slice(0, -2);
      if (!path.startsWith(baseFolder + "/")) {
        return path === baseFolder;
      }
      const pathAfterBase = path.slice(baseFolder.length + 1);
      return pathAfterBase.includes("/");
    }
    return path.startsWith(excludePattern + "/") || path === excludePattern;
  }
  handleRename(newFile, oldPath) {
    if (!(newFile instanceof import_obsidian4.TFile)) return;
    if (!this.settings.fileExtensions.includes(newFile.extension)) return;
    const oldBasename = getBasename(oldPath);
    const newBasename = newFile.basename;
    const oldImmediateParentName = getImmediateParentName(oldPath);
    const newImmediateParentName = getImmediateParentName(newFile.path);
    const isNameChange = this.settings.caseSensitive ? oldBasename !== newBasename : oldBasename.toLowerCase() !== newBasename.toLowerCase();
    const isFolderChange = oldImmediateParentName !== newImmediateParentName && !isNameChange;
    if (!isNameChange && !isFolderChange) {
      return;
    }
    const path = newFile.path;
    if (this.settings.excludePropertyName && this.settings.excludePropertyName.trim() !== "") {
      const cache = this.app.metadataCache.getFileCache(newFile);
      const frontmatter = cache == null ? void 0 : cache.frontmatter;
      if (frontmatter && frontmatter[this.settings.excludePropertyName] === true) {
        return;
      }
    }
    if (this.settings.includeFolders.length > 0) {
      if (!this.settings.includeFolders.some((f) => this.isPathInFolder(path, f))) {
        return;
      }
    }
    const isIndexFileForFolderRename = isFolderChange && this.settings.trackFolderRenames && this.settings.trackFolderRenames.trim() !== "" && (this.settings.caseSensitive ? newFile.basename === this.settings.trackFolderRenames : newFile.basename.toLowerCase() === this.settings.trackFolderRenames.toLowerCase());
    for (const excludePattern of this.settings.excludeFolders) {
      if (this.isPathExcluded(path, excludePattern)) {
        if (isIndexFileForFolderRename && excludePattern.endsWith("/*") && !excludePattern.endsWith("/**")) {
          const baseFolder = excludePattern.slice(0, -2);
          if (path.startsWith(baseFolder + "/")) {
            const pathAfterBase = path.slice(baseFolder.length + 1);
            const pathParts = pathAfterBase.split("/");
            if (pathParts.length === 2) {
              continue;
            }
          }
        }
        return;
      }
    }
    const regexes = [];
    for (const regexStr of this.settings.ignoreRegexes) {
      try {
        regexes.push(new RegExp(regexStr));
      } catch (e) {
        console.error(`Invalid ignore regex: ${regexStr}`, e);
      }
    }
    let toQueue = null;
    if (isNameChange) {
      if (regexes.some((re) => re.test(oldBasename) || re.test(newBasename))) {
        return;
      }
      toQueue = oldBasename;
    } else if (isFolderChange && this.settings.trackFolderRenames && this.settings.trackFolderRenames.trim() !== "") {
      const currentBasename = newFile.basename;
      const matchesFilename = this.settings.caseSensitive ? currentBasename === this.settings.trackFolderRenames : currentBasename.toLowerCase() === this.settings.trackFolderRenames.toLowerCase();
      if (!matchesFilename) {
        return;
      }
      if (oldImmediateParentName === "" || newImmediateParentName === "") {
        return;
      }
      if (regexes.some((re) => re.test(oldImmediateParentName) || re.test(newImmediateParentName))) {
        return;
      }
      toQueue = oldImmediateParentName;
    }
    if (!toQueue) return;
    let existingEntry = this.debounceMap.get(newFile.path);
    if (!existingEntry) {
      existingEntry = this.debounceMap.get(oldPath);
      if (existingEntry) {
        this.debounceMap.delete(oldPath);
      }
    }
    if (existingEntry) {
      if (existingEntry.timeoutId !== 0) {
        window.clearTimeout(existingEntry.timeoutId);
      }
      toQueue = Array.from(existingEntry.queue)[0];
    }
    const entry = {
      queue: /* @__PURE__ */ new Set([toQueue]),
      timeoutId: 0,
      currentPath: newFile.path
    };
    entry.timeoutId = window.setTimeout(() => {
      void (async () => {
        try {
          await this.historyProcessor.processAliases(entry.currentPath, entry.queue);
        } catch (error) {
          console.error("Error processing aliases:", error);
        }
        this.debounceMap.delete(entry.currentPath);
      })();
    }, this.settings.timeoutSeconds * 1e3);
    this.debounceMap.set(newFile.path, entry);
  }
};
//# sourceMappingURL=data:application/json;base64,[encoded data, 53644 characters]
