/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD */
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (__hasOwnProp.call(b, prop))
      __defNormalProp(a, prop, b[prop]);
  if (__getOwnPropSymbols)
    for (var prop of __getOwnPropSymbols(b)) {
      if (__propIsEnum.call(b, prop))
        __defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __commonJS = (cb, mod) => function __require() {
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __async = (__this, __arguments, generator) => {
  return new Promise((resolve, reject) => {
    var fulfilled = (value) => {
      try {
        step(generator.next(value));
      } catch (e) {
        reject(e);
      }
    };
    var rejected = (value) => {
      try {
        step(generator.throw(value));
      } catch (e) {
        reject(e);
      }
    };
    var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
    step((generator = generator.apply(__this, __arguments)).next());
  });
};

// package.json
var require_package = __commonJS({
  "package.json"(exports, module2) {
    module2.exports = {
      name: "obsidian-paste-image-rename",
      version: "1.6.1",
      main: "main.js",
      scripts: {
        start: "node esbuild.config.mjs",
        build: "tsc -noEmit -skipLibCheck && BUILD_ENV=production node esbuild.config.mjs && cp manifest.json build",
        version: "node version-bump.mjs && git add manifest.json versions.json",
        release: "npm run build && gh release create ${npm_package_version} build/*"
      },
      keywords: [],
      author: "Reorx",
      license: "MIT",
      devDependencies: {
        "@types/node": "^18.11.18",
        "@typescript-eslint/eslint-plugin": "^5.49.0",
        "@typescript-eslint/parser": "^5.49.0",
        "builtin-modules": "^3.3.0",
        esbuild: "0.16.17",
        obsidian: "^1.1.1",
        tslib: "2.5.0",
        typescript: "4.9.4"
      },
      dependencies: {
        "cash-dom": "^8.1.2"
      }
    };
  }
});

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

// src/batch.ts
var import_obsidian = require("obsidian");

// src/utils.ts
var DEBUG = false;
if (DEBUG)
  console.log("DEBUG is enabled");
function debugLog(...args) {
  if (DEBUG) {
    console.log(new Date().toISOString().slice(11, 23), ...args);
  }
}
function createElementTree(rootEl, opts) {
  const result = {
    el: rootEl.createEl(opts.tag, opts),
    children: []
  };
  const children = opts.children || [];
  for (const child of children) {
    result.children.push(createElementTree(result.el, child));
  }
  return result;
}
var path = {
  // Credit: @creationix/path.js
  join(...partSegments) {
    let parts = [];
    for (let i = 0, l = partSegments.length; i < l; i++) {
      parts = parts.concat(partSegments[i].split("/"));
    }
    const newParts = [];
    for (let i = 0, l = parts.length; i < l; i++) {
      const part = parts[i];
      if (!part || part === ".")
        continue;
      else
        newParts.push(part);
    }
    if (parts[0] === "")
      newParts.unshift("");
    return newParts.join("/");
  },
  // returns the last part of a path, e.g. 'foo.jpg'
  basename(fullpath) {
    const sp = fullpath.split("/");
    return sp[sp.length - 1];
  },
  // return extension without dot, e.g. 'jpg'
  extension(fullpath) {
    const positions = [...fullpath.matchAll(new RegExp("\\.", "gi"))].map((a) => a.index);
    return fullpath.slice(positions[positions.length - 1] + 1);
  }
};
var filenameNotAllowedChars = /[^\p{L}0-9~`!@$&*()\-_=+{};'",<.>? ]/ug;
var sanitizer = {
  filename(s) {
    return s.replace(filenameNotAllowedChars, "").trim();
  },
  delimiter(s) {
    s = this.filename(s);
    if (!s)
      s = "-";
    return s;
  }
};
function escapeRegExp(s) {
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function lockInputMethodComposition(el) {
  const state = {
    lock: false
  };
  el.addEventListener("compositionstart", () => {
    state.lock = true;
  });
  el.addEventListener("compositionend", () => {
    state.lock = false;
  });
  return state;
}

// src/batch.ts
var ImageBatchRenameModal = class extends import_obsidian.Modal {
  constructor(app, activeFile, renameFunc, onClose) {
    super(app);
    this.activeFile = activeFile;
    this.renameFunc = renameFunc;
    this.onCloseExtra = onClose;
    this.state = {
      namePattern: "",
      extPattern: "",
      nameReplace: "",
      renameTasks: []
    };
  }
  onOpen() {
    this.containerEl.addClass("image-rename-modal");
    const { contentEl, titleEl } = this;
    titleEl.setText("Batch rename embeded files");
    const namePatternSetting = new import_obsidian.Setting(contentEl).setName("Name pattern").setDesc("Please input the name pattern to match files (regex)").addText((text) => text.setValue(this.state.namePattern).onChange(
      (value) => __async(this, null, function* () {
        this.state.namePattern = value;
      })
    ));
    const npInputEl = namePatternSetting.controlEl.children[0];
    npInputEl.focus();
    const npInputState = lockInputMethodComposition(npInputEl);
    npInputEl.addEventListener("keydown", (e) => __async(this, null, function* () {
      if (e.key === "Enter" && !npInputState.lock) {
        e.preventDefault();
        if (!this.state.namePattern) {
          errorEl.innerText = 'Error: "Name pattern" could not be empty';
          errorEl.style.display = "block";
          return;
        }
        this.matchImageNames(tbodyEl);
      }
    }));
    const extPatternSetting = new import_obsidian.Setting(contentEl).setName("Extension pattern").setDesc("Please input the extension pattern to match files (regex)").addText((text) => text.setValue(this.state.extPattern).onChange(
      (value) => __async(this, null, function* () {
        this.state.extPattern = value;
      })
    ));
    const extInputEl = extPatternSetting.controlEl.children[0];
    extInputEl.addEventListener("keydown", (e) => __async(this, null, function* () {
      if (e.key === "Enter") {
        e.preventDefault();
        this.matchImageNames(tbodyEl);
      }
    }));
    const nameReplaceSetting = new import_obsidian.Setting(contentEl).setName("Name replace").setDesc("Please input the string to replace the matched name (use $1, $2 for regex groups)").addText((text) => text.setValue(this.state.nameReplace).onChange(
      (value) => __async(this, null, function* () {
        this.state.nameReplace = value;
      })
    ));
    const nrInputEl = nameReplaceSetting.controlEl.children[0];
    const nrInputState = lockInputMethodComposition(nrInputEl);
    nrInputEl.addEventListener("keydown", (e) => __async(this, null, function* () {
      if (e.key === "Enter" && !nrInputState.lock) {
        e.preventDefault();
        this.matchImageNames(tbodyEl);
      }
    }));
    const matchedContainer = contentEl.createDiv({
      cls: "matched-container"
    });
    const tableET = createElementTree(matchedContainer, {
      tag: "table",
      children: [
        {
          tag: "thead",
          children: [
            {
              tag: "tr",
              children: [
                {
                  tag: "td",
                  text: "Original path"
                },
                {
                  tag: "td",
                  text: "Renamed Name"
                }
              ]
            }
          ]
        },
        {
          tag: "tbody"
        }
      ]
    });
    const tbodyEl = tableET.children[1].el;
    const errorEl = contentEl.createDiv({
      cls: "error",
      attr: {
        style: "display: none;"
      }
    });
    new import_obsidian.Setting(contentEl).addButton((button) => {
      button.setButtonText("Rename all").setClass("mod-cta").onClick(() => {
        new ConfirmModal(
          this.app,
          "Confirm rename all",
          `Are you sure? This will rename all the ${this.state.renameTasks.length} images matched the pattern.`,
          () => {
            this.renameAll();
            this.close();
          }
        ).open();
      });
    }).addButton((button) => {
      button.setButtonText("Cancel").onClick(() => {
        this.close();
      });
    });
  }
  onClose() {
    const { contentEl } = this;
    contentEl.empty();
    this.onCloseExtra();
  }
  renameAll() {
    return __async(this, null, function* () {
      debugLog("renameAll", this.state);
      for (const task of this.state.renameTasks) {
        yield this.renameFunc(task.file, task.name);
      }
    });
  }
  matchImageNames(tbodyEl) {
    const { state } = this;
    const renameTasks = [];
    tbodyEl.empty();
    const fileCache = this.app.metadataCache.getFileCache(this.activeFile);
    if (!fileCache || !fileCache.embeds)
      return;
    const namePatternRegex = new RegExp(state.namePattern, "g");
    const extPatternRegex = new RegExp(state.extPattern);
    fileCache.embeds.forEach((embed) => {
      const file = this.app.metadataCache.getFirstLinkpathDest(embed.link, this.activeFile.path);
      if (!file) {
        console.warn("file not found", embed.link);
        return;
      }
      if (state.extPattern) {
        const m0 = extPatternRegex.exec(file.extension);
        if (!m0)
          return;
      }
      const stem = file.basename;
      namePatternRegex.lastIndex = 0;
      const m1 = namePatternRegex.exec(stem);
      if (!m1)
        return;
      let renamedName = file.name;
      if (state.nameReplace) {
        namePatternRegex.lastIndex = 0;
        renamedName = stem.replace(namePatternRegex, state.nameReplace);
        renamedName = `${renamedName}.${file.extension}`;
      }
      renameTasks.push({
        file,
        name: renamedName
      });
      createElementTree(tbodyEl, {
        tag: "tr",
        children: [
          {
            tag: "td",
            children: [
              {
                tag: "span",
                text: file.name
              },
              {
                tag: "div",
                text: file.path,
                attr: {
                  class: "file-path"
                }
              }
            ]
          },
          {
            tag: "td",
            children: [
              {
                tag: "span",
                text: renamedName
              },
              {
                tag: "div",
                text: path.join(file.parent.path, renamedName),
                attr: {
                  class: "file-path"
                }
              }
            ]
          }
        ]
      });
    });
    debugLog("new renameTasks", renameTasks);
    state.renameTasks = renameTasks;
  }
};
var ConfirmModal = class extends import_obsidian.Modal {
  constructor(app, title, message, onConfirm) {
    super(app);
    this.title = title;
    this.message = message;
    this.onConfirm = onConfirm;
  }
  onOpen() {
    const { contentEl, titleEl } = this;
    titleEl.setText(this.title);
    contentEl.createEl("p", {
      text: this.message
    });
    new import_obsidian.Setting(contentEl).addButton((button) => {
      button.setButtonText("Yes").setClass("mod-warning").onClick(() => {
        this.onConfirm();
        this.close();
      });
    }).addButton((button) => {
      button.setButtonText("No").onClick(() => {
        this.close();
      });
    });
  }
};

// src/template.ts
var dateTmplRegex = /{{DATE:([^}]+)}}/gm;
var frontmatterTmplRegex = /{{frontmatter:([^}]+)}}/gm;
var replaceDateVar = (s, date) => {
  const m = dateTmplRegex.exec(s);
  if (!m)
    return s;
  return s.replace(m[0], date.format(m[1]));
};
var replaceFrontmatterVar = (s, frontmatter) => {
  if (!frontmatter)
    return s;
  const m = frontmatterTmplRegex.exec(s);
  if (!m)
    return s;
  return s.replace(m[0], frontmatter[m[1]] || "");
};
var renderTemplate = (tmpl, data, frontmatter) => {
  const now = window.moment();
  let text = tmpl;
  let newtext;
  while ((newtext = replaceDateVar(text, now)) != text) {
    text = newtext;
  }
  while ((newtext = replaceFrontmatterVar(text, frontmatter)) != text) {
    text = newtext;
  }
  text = text.replace(/{{imageNameKey}}/gm, data.imageNameKey).replace(/{{fileName}}/gm, data.fileName).replace(/{{dirName}}/gm, data.dirName).replace(/{{firstHeading}}/gm, data.firstHeading);
  return text;
};

// src/main.ts
var DEFAULT_SETTINGS = {
  imageNamePattern: "{{fileName}}",
  dupNumberAtStart: false,
  dupNumberDelimiter: "-",
  dupNumberAlways: false,
  autoRename: false,
  handleAllAttachments: false,
  excludeExtensionPattern: "",
  disableRenameNotice: false
};
var PASTED_IMAGE_PREFIX = "Pasted image ";
var PasteImageRenamePlugin = class extends import_obsidian2.Plugin {
  constructor() {
    super(...arguments);
    this.modals = [];
  }
  onload() {
    return __async(this, null, function* () {
      const pkg = require_package();
      console.log(`Plugin loading: ${pkg.name} ${pkg.version} BUILD_ENV=${"production"}`);
      yield this.loadSettings();
      this.registerEvent(
        this.app.vault.on("create", (file) => {
          if (!(file instanceof import_obsidian2.TFile))
            return;
          const timeGapMs = new Date().getTime() - file.stat.ctime;
          if (timeGapMs > 1e3)
            return;
          if (isMarkdownFile(file))
            return;
          if (isPastedImage(file)) {
            debugLog("pasted image created", file);
            this.startRenameProcess(file, this.settings.autoRename);
          } else {
            if (this.settings.handleAllAttachments) {
              debugLog("handleAllAttachments for file", file);
              if (this.testExcludeExtension(file)) {
                debugLog("excluded file by ext", file);
                return;
              }
              this.startRenameProcess(file, this.settings.autoRename);
            }
          }
        })
      );
      const startBatchRenameProcess = () => {
        this.openBatchRenameModal();
      };
      this.addCommand({
        id: "batch-rename-embeded-files",
        name: "Batch rename embeded files (in the current file)",
        callback: startBatchRenameProcess
      });
      if (DEBUG) {
        this.addRibbonIcon("wand-glyph", "Batch rename embeded files", startBatchRenameProcess);
      }
      const batchRenameAllImages = () => {
        this.batchRenameAllImages();
      };
      this.addCommand({
        id: "batch-rename-all-images",
        name: "Batch rename all images instantly (in the current file)",
        callback: batchRenameAllImages
      });
      if (DEBUG) {
        this.addRibbonIcon("wand-glyph", "Batch rename all images instantly (in the current file)", batchRenameAllImages);
      }
      this.addSettingTab(new SettingTab(this.app, this));
    });
  }
  startRenameProcess(file, autoRename = false) {
    return __async(this, null, function* () {
      const activeFile = this.getActiveFile();
      if (!activeFile) {
        new import_obsidian2.Notice("Error: No active file found.");
        return;
      }
      const { stem, newName, isMeaningful } = this.generateNewName(file, activeFile);
      debugLog("generated newName:", newName, isMeaningful);
      if (!isMeaningful || !autoRename) {
        this.openRenameModal(file, isMeaningful ? stem : "", activeFile.path);
        return;
      }
      this.renameFile(file, newName, activeFile.path, true);
    });
  }
  renameFile(file, inputNewName, sourcePath, replaceCurrentLine) {
    return __async(this, null, function* () {
      const { name: newName } = yield this.deduplicateNewName(inputNewName, file);
      debugLog("deduplicated newName:", newName);
      const originName = file.name;
      const linkText = this.app.fileManager.generateMarkdownLink(file, sourcePath);
      const newPath = path.join(file.parent.path, newName);
      try {
        yield this.app.fileManager.renameFile(file, newPath);
      } catch (err) {
        new import_obsidian2.Notice(`Failed to rename ${newName}: ${err}`);
        throw err;
      }
      if (!replaceCurrentLine) {
        return;
      }
      const newLinkText = this.app.fileManager.generateMarkdownLink(file, sourcePath);
      debugLog("replace text", linkText, newLinkText);
      const editor = this.getActiveEditor();
      if (!editor) {
        new import_obsidian2.Notice(`Failed to rename ${newName}: no active editor`);
        return;
      }
      const cursor = editor.getCursor();
      const line = editor.getLine(cursor.line);
      const replacedLine = line.replace(linkText, newLinkText);
      debugLog("current line -> replaced line", line, replacedLine);
      editor.transaction({
        changes: [
          {
            from: __spreadProps(__spreadValues({}, cursor), { ch: 0 }),
            to: __spreadProps(__spreadValues({}, cursor), { ch: line.length }),
            text: replacedLine
          }
        ]
      });
      if (!this.settings.disableRenameNotice) {
        new import_obsidian2.Notice(`Renamed ${originName} to ${newName}`);
      }
    });
  }
  openRenameModal(file, newName, sourcePath) {
    const modal = new ImageRenameModal(
      this.app,
      file,
      newName,
      (confirmedName) => {
        debugLog("confirmedName:", confirmedName);
        this.renameFile(file, confirmedName, sourcePath, true);
      },
      () => {
        this.modals.splice(this.modals.indexOf(modal), 1);
      }
    );
    this.modals.push(modal);
    modal.open();
    debugLog("modals count", this.modals.length);
  }
  openBatchRenameModal() {
    const activeFile = this.getActiveFile();
    const modal = new ImageBatchRenameModal(
      this.app,
      activeFile,
      (file, name) => __async(this, null, function* () {
        yield this.renameFile(file, name, activeFile.path);
      }),
      () => {
        this.modals.splice(this.modals.indexOf(modal), 1);
      }
    );
    this.modals.push(modal);
    modal.open();
  }
  batchRenameAllImages() {
    return __async(this, null, function* () {
      const activeFile = this.getActiveFile();
      const fileCache = this.app.metadataCache.getFileCache(activeFile);
      if (!fileCache || !fileCache.embeds)
        return;
      const extPatternRegex = /jpe?g|png|gif|tiff|webp/i;
      for (const embed of fileCache.embeds) {
        const file = this.app.metadataCache.getFirstLinkpathDest(embed.link, activeFile.path);
        if (!file) {
          console.warn("file not found", embed.link);
          return;
        }
        const m0 = extPatternRegex.exec(file.extension);
        if (!m0)
          return;
        const { newName, isMeaningful } = this.generateNewName(file, activeFile);
        debugLog("generated newName:", newName, isMeaningful);
        if (!isMeaningful) {
          new import_obsidian2.Notice("Failed to batch rename images: the generated name is not meaningful");
          break;
        }
        yield this.renameFile(file, newName, activeFile.path, false);
      }
    });
  }
  // returns a new name for the input file, with extension
  generateNewName(file, activeFile) {
    let imageNameKey = "";
    let firstHeading = "";
    let frontmatter;
    const fileCache = this.app.metadataCache.getFileCache(activeFile);
    if (fileCache) {
      debugLog("frontmatter", fileCache.frontmatter);
      frontmatter = fileCache.frontmatter;
      imageNameKey = (frontmatter == null ? void 0 : frontmatter.imageNameKey) || "";
      firstHeading = getFirstHeading(fileCache.headings);
    } else {
      console.warn("could not get file cache from active file", activeFile.name);
    }
    const stem = renderTemplate(
      this.settings.imageNamePattern,
      {
        imageNameKey,
        fileName: activeFile.basename,
        dirName: activeFile.parent.name,
        firstHeading
      },
      frontmatter
    );
    const meaninglessRegex = new RegExp(`[${this.settings.dupNumberDelimiter}\\s]`, "gm");
    return {
      stem,
      newName: stem + "." + file.extension,
      isMeaningful: stem.replace(meaninglessRegex, "") !== ""
    };
  }
  // newName: foo.ext
  deduplicateNewName(newName, file) {
    return __async(this, null, function* () {
      const dir = file.parent.path;
      const listed = yield this.app.vault.adapter.list(dir);
      debugLog("sibling files", listed);
      const newNameExt = path.extension(newName), newNameStem = newName.slice(0, newName.length - newNameExt.length - 1), newNameStemEscaped = escapeRegExp(newNameStem), delimiter = this.settings.dupNumberDelimiter, delimiterEscaped = escapeRegExp(delimiter);
      let dupNameRegex;
      if (this.settings.dupNumberAtStart) {
        dupNameRegex = new RegExp(
          `^(?<number>\\d+)${delimiterEscaped}(?<name>${newNameStemEscaped})\\.${newNameExt}$`
        );
      } else {
        dupNameRegex = new RegExp(
          `^(?<name>${newNameStemEscaped})${delimiterEscaped}(?<number>\\d+)\\.${newNameExt}$`
        );
      }
      debugLog("dupNameRegex", dupNameRegex);
      const dupNameNumbers = [];
      let isNewNameExist = false;
      for (let sibling of listed.files) {
        sibling = path.basename(sibling);
        if (sibling == newName) {
          isNewNameExist = true;
          continue;
        }
        const m = dupNameRegex.exec(sibling);
        if (!m)
          continue;
        dupNameNumbers.push(parseInt(m.groups.number));
      }
      if (isNewNameExist || this.settings.dupNumberAlways) {
        const newNumber = dupNameNumbers.length > 0 ? Math.max(...dupNameNumbers) + 1 : 1;
        if (this.settings.dupNumberAtStart) {
          newName = `${newNumber}${delimiter}${newNameStem}.${newNameExt}`;
        } else {
          newName = `${newNameStem}${delimiter}${newNumber}.${newNameExt}`;
        }
      }
      return {
        name: newName,
        stem: newName.slice(0, newName.length - newNameExt.length - 1),
        extension: newNameExt
      };
    });
  }
  getActiveFile() {
    const view = this.app.workspace.getActiveViewOfType(import_obsidian2.MarkdownView);
    const file = view == null ? void 0 : view.file;
    debugLog("active file", file == null ? void 0 : file.path);
    return file;
  }
  getActiveEditor() {
    const view = this.app.workspace.getActiveViewOfType(import_obsidian2.MarkdownView);
    return view == null ? void 0 : view.editor;
  }
  onunload() {
    this.modals.map((modal) => modal.close());
  }
  testExcludeExtension(file) {
    const pattern = this.settings.excludeExtensionPattern;
    if (!pattern)
      return false;
    return new RegExp(pattern).test(file.extension);
  }
  loadSettings() {
    return __async(this, null, function* () {
      this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
    });
  }
  saveSettings() {
    return __async(this, null, function* () {
      yield this.saveData(this.settings);
    });
  }
};
function getFirstHeading(headings) {
  if (headings && headings.length > 0) {
    for (const heading of headings) {
      if (heading.level === 1) {
        return heading.heading;
      }
    }
  }
  return "";
}
function isPastedImage(file) {
  if (file instanceof import_obsidian2.TFile) {
    if (file.name.startsWith(PASTED_IMAGE_PREFIX)) {
      return true;
    }
  }
  return false;
}
function isMarkdownFile(file) {
  if (file instanceof import_obsidian2.TFile) {
    if (file.extension === "md") {
      return true;
    }
  }
  return false;
}
var ImageRenameModal = class extends import_obsidian2.Modal {
  constructor(app, src, stem, renameFunc, onClose) {
    super(app);
    this.src = src;
    this.stem = stem;
    this.renameFunc = renameFunc;
    this.onCloseExtra = onClose;
  }
  onOpen() {
    this.containerEl.addClass("image-rename-modal");
    const { contentEl, titleEl } = this;
    titleEl.setText("Rename image");
    const imageContainer = contentEl.createDiv({
      cls: "image-container"
    });
    imageContainer.createEl("img", {
      attr: {
        src: this.app.vault.getResourcePath(this.src)
      }
    });
    let stem = this.stem;
    const ext = this.src.extension;
    const getNewName = (stem2) => stem2 + "." + ext;
    const getNewPath = (stem2) => path.join(this.src.parent.path, getNewName(stem2));
    const infoET = createElementTree(contentEl, {
      tag: "ul",
      cls: "info",
      children: [
        {
          tag: "li",
          children: [
            {
              tag: "span",
              text: "Origin path"
            },
            {
              tag: "span",
              text: this.src.path
            }
          ]
        },
        {
          tag: "li",
          children: [
            {
              tag: "span",
              text: "New path"
            },
            {
              tag: "span",
              text: getNewPath(stem)
            }
          ]
        }
      ]
    });
    const doRename = () => __async(this, null, function* () {
      debugLog("doRename", `stem=${stem}`);
      this.renameFunc(getNewName(stem));
    });
    const nameSetting = new import_obsidian2.Setting(contentEl).setName("New name").setDesc("Please input the new name for the image (without extension)").addText((text) => text.setValue(stem).onChange(
      (value) => __async(this, null, function* () {
        stem = sanitizer.filename(value);
        infoET.children[1].children[1].el.innerText = getNewPath(stem);
      })
    ));
    const nameInputEl = nameSetting.controlEl.children[0];
    nameInputEl.focus();
    const nameInputState = lockInputMethodComposition(nameInputEl);
    nameInputEl.addEventListener("keydown", (e) => __async(this, null, function* () {
      if (e.key === "Enter" && !nameInputState.lock) {
        e.preventDefault();
        if (!stem) {
          errorEl.innerText = 'Error: "New name" could not be empty';
          errorEl.style.display = "block";
          return;
        }
        doRename();
        this.close();
      }
    }));
    const errorEl = contentEl.createDiv({
      cls: "error",
      attr: {
        style: "display: none;"
      }
    });
    new import_obsidian2.Setting(contentEl).addButton((button) => {
      button.setButtonText("Rename").onClick(() => {
        doRename();
        this.close();
      });
    }).addButton((button) => {
      button.setButtonText("Cancel").onClick(() => {
        this.close();
      });
    });
  }
  onClose() {
    const { contentEl } = this;
    contentEl.empty();
    this.onCloseExtra();
  }
};
var imageNamePatternDesc = `
The pattern indicates how the new name should be generated.

Available variables:
- {{fileName}}: name of the active file, without ".md" extension.
- {{imageNameKey}}: this variable is read from the markdown file's frontmatter, from the same key "imageNameKey".
- {{DATE:$FORMAT}}: use "$FORMAT" to format the current date, "$FORMAT" must be a Moment.js format string, e.g. {{DATE:YYYY-MM-DD}}.

Here are some examples from pattern to image names (repeat in sequence), variables: fileName = "My note", imageNameKey = "foo":
- {{fileName}}: My note, My note-1, My note-2
- {{imageNameKey}}: foo, foo-1, foo-2
- {{imageNameKey}}-{{DATE:YYYYMMDD}}: foo-20220408, foo-20220408-1, foo-20220408-2
`;
var SettingTab = class extends import_obsidian2.PluginSettingTab {
  constructor(app, plugin) {
    super(app, plugin);
    this.plugin = plugin;
  }
  display() {
    const { containerEl } = this;
    containerEl.empty();
    new import_obsidian2.Setting(containerEl).setName("Image name pattern").setDesc(imageNamePatternDesc).setClass("long-description-setting-item").addText((text) => text.setPlaceholder("{{imageNameKey}}").setValue(this.plugin.settings.imageNamePattern).onChange(
      (value) => __async(this, null, function* () {
        this.plugin.settings.imageNamePattern = value;
        yield this.plugin.saveSettings();
      })
    ));
    new import_obsidian2.Setting(containerEl).setName("Duplicate number at start (or end)").setDesc(`If enabled, duplicate number will be added at the start as prefix for the image name, otherwise it will be added at the end as suffix for the image name.`).addToggle((toggle) => toggle.setValue(this.plugin.settings.dupNumberAtStart).onChange(
      (value) => __async(this, null, function* () {
        this.plugin.settings.dupNumberAtStart = value;
        yield this.plugin.saveSettings();
      })
    ));
    new import_obsidian2.Setting(containerEl).setName("Duplicate number delimiter").setDesc(`The delimiter to generate the number prefix/suffix for duplicated names. For example, if the value is "-", the suffix will be like "-1", "-2", "-3", and the prefix will be like "1-", "2-", "3-". Only characters that are valid in file names are allowed.`).addText((text) => text.setValue(this.plugin.settings.dupNumberDelimiter).onChange(
      (value) => __async(this, null, function* () {
        this.plugin.settings.dupNumberDelimiter = sanitizer.delimiter(value);
        yield this.plugin.saveSettings();
      })
    ));
    new import_obsidian2.Setting(containerEl).setName("Always add duplicate number").setDesc(`If enabled, duplicate number will always be added to the image name. Otherwise, it will only be added when the name is duplicated.`).addToggle((toggle) => toggle.setValue(this.plugin.settings.dupNumberAlways).onChange(
      (value) => __async(this, null, function* () {
        this.plugin.settings.dupNumberAlways = value;
        yield this.plugin.saveSettings();
      })
    ));
    new import_obsidian2.Setting(containerEl).setName("Auto rename").setDesc(`By default, the rename modal will always be shown to confirm before renaming, if this option is set, the image will be auto renamed after pasting.`).addToggle((toggle) => toggle.setValue(this.plugin.settings.autoRename).onChange(
      (value) => __async(this, null, function* () {
        this.plugin.settings.autoRename = value;
        yield this.plugin.saveSettings();
      })
    ));
    new import_obsidian2.Setting(containerEl).setName("Handle all attachments").setDesc(`By default, the plugin only handles images that starts with "Pasted image " in name,
			which is the prefix Obsidian uses to create images from pasted content.
			If this option is set, the plugin will handle all attachments that are created in the vault.`).addToggle((toggle) => toggle.setValue(this.plugin.settings.handleAllAttachments).onChange(
      (value) => __async(this, null, function* () {
        this.plugin.settings.handleAllAttachments = value;
        yield this.plugin.saveSettings();
      })
    ));
    new import_obsidian2.Setting(containerEl).setName("Exclude extension pattern").setDesc(`This option is only useful when "Handle all attachments" is enabled.
			Write a Regex pattern to exclude certain extensions from being handled. Only the first line will be used.`).setClass("single-line-textarea").addTextArea((text) => text.setPlaceholder("docx?|xlsx?|pptx?|zip|rar").setValue(this.plugin.settings.excludeExtensionPattern).onChange(
      (value) => __async(this, null, function* () {
        this.plugin.settings.excludeExtensionPattern = value;
        yield this.plugin.saveSettings();
      })
    ));
    new import_obsidian2.Setting(containerEl).setName("Disable rename notice").setDesc(`Turn off this option if you don't want to see the notice when renaming images.
			Note that Obsidian may display a notice when a link has changed, this option cannot disable that.`).addToggle((toggle) => toggle.setValue(this.plugin.settings.disableRenameNotice).onChange(
      (value) => __async(this, null, function* () {
        this.plugin.settings.disableRenameNotice = value;
        yield this.plugin.saveSettings();
      })
    ));
  }
};
