/*
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/mdx-frontmatter.ts
function isMdxFile(file) {
  return file.extension === "mdx";
}
function parseMdxFrontmatter(content) {
  const frontmatterRegex = /^---\n([\s\S]*?)\n---\n/;
  const match = content.match(frontmatterRegex);
  if (!match) {
    return {
      frontmatter: {},
      body: content
    };
  }
  const frontmatterText = match[1];
  const bodyContent = content.slice(match[0].length);
  try {
    const parsed = (0, import_obsidian5.parseYaml)(frontmatterText);
    const frontmatter = parsed && typeof parsed === "object" ? parsed : {};
    return {
      frontmatter,
      body: bodyContent
    };
  } catch (e) {
    console.error("Error parsing MDX properties:", e);
    return {
      frontmatter: {},
      body: bodyContent
    };
  }
}
async function readMdxFrontmatter(app, file) {
  if (!isMdxFile(file)) {
    return null;
  }
  try {
    const content = await app.vault.read(file);
    const parsed = parseMdxFrontmatter(content);
    return parsed ? parsed.frontmatter : null;
  } catch (e) {
    console.error(`Error reading MDX properties from ${file.path}:`, e);
    return null;
  }
}
async function processMdxFrontMatter(app, file, callback) {
  if (!isMdxFile(file)) {
    throw new Error(`File ${file.path} is not an MDX file`);
  }
  try {
    const content = await app.vault.read(file);
    const parsed = parseMdxFrontmatter(content);
    if (!parsed) {
      throw new Error("Failed to parse existing frontmatter");
    }
    const frontmatter = { ...parsed.frontmatter };
    callback(frontmatter);
    const newFrontmatterText = (0, import_obsidian5.stringifyYaml)(frontmatter).trim();
    const newContent = `---
${newFrontmatterText}
---
${parsed.body}`;
    await app.vault.modify(file, newContent);
  } catch (e) {
    console.error(`Error processing MDX properties for ${file.path}:`, e);
    throw e;
  }
}
var import_obsidian5;
var init_mdx_frontmatter = __esm({
  "src/utils/mdx-frontmatter.ts"() {
    "use strict";
    import_obsidian5 = require("obsidian");
  }
});

// src/utils/frontmatter-helper.ts
async function getFileFrontmatter(app, file) {
  if (isMdxFile(file)) {
    return await readMdxFrontmatter(app, file);
  } else {
    const metadata = app.metadataCache.getFileCache(file);
    return (metadata == null ? void 0 : metadata.frontmatter) || null;
  }
}
async function processFileFrontMatter(app, file, callback) {
  if (isMdxFile(file)) {
    await processMdxFrontMatter(app, file, callback);
  } else {
    await app.fileManager.processFrontMatter(file, callback);
  }
}
var init_frontmatter_helper = __esm({
  "src/utils/frontmatter-helper.ts"() {
    "use strict";
    init_mdx_frontmatter();
  }
});

// src/shared/settings-schema.ts
var settings_schema_exports = {};
__export(settings_schema_exports, {
  getCMSViewOptions: () => getCMSViewOptions,
  readCMSSettings: () => readCMSSettings
});
function readCMSSettings(config, pluginSettings) {
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
  const getConfig = (key) => {
    var _a2;
    return (_a2 = config == null ? void 0 : config.get) == null ? void 0 : _a2.call(config, key);
  };
  return {
    titleProperty: getConfig("titleProperty") || "note.title",
    descriptionProperty: getConfig("descriptionProperty") || "",
    imageProperty: getConfig("imageProperty") || "",
    showTitle: true,
    // Always show title, defaulting to file name if no property set
    showDate: (_a = getConfig("showDate")) != null ? _a : false,
    dateProperty: getConfig("dateProperty") || "",
    dateIncludeTime: (_b = getConfig("dateIncludeTime")) != null ? _b : false,
    showTextPreview: (_c = getConfig("showTextPreview")) != null ? _c : true,
    fallbackToContent: (_d = getConfig("fallbackToContent")) != null ? _d : true,
    truncatePreviewProperty: (_e = getConfig("truncatePreviewProperty")) != null ? _e : false,
    fallbackToEmbeds: (() => {
      const value = getConfig("fallbackToEmbeds");
      if (value === "always" || value === "if-empty" || value === "never") {
        return value;
      }
      return value === false ? "never" : "if-empty";
    })(),
    propertyDisplay1: getConfig("propertyDisplay1") || "",
    propertyDisplay2: getConfig("propertyDisplay2") || "",
    propertyDisplay3: getConfig("propertyDisplay3") || "",
    propertyDisplay4: getConfig("propertyDisplay4") || "",
    propertyDisplay5: getConfig("propertyDisplay5") || "",
    propertyDisplay6: getConfig("propertyDisplay6") || "",
    propertyDisplay7: getConfig("propertyDisplay7") || "",
    propertyDisplay8: getConfig("propertyDisplay8") || "",
    propertyDisplay9: getConfig("propertyDisplay9") || "",
    propertyDisplay10: getConfig("propertyDisplay10") || "",
    propertyDisplay11: getConfig("propertyDisplay11") || "",
    propertyDisplay12: getConfig("propertyDisplay12") || "",
    propertyDisplay13: getConfig("propertyDisplay13") || "",
    propertyDisplay14: getConfig("propertyDisplay14") || "",
    propertyLayout12SideBySide: (_f = getConfig("propertyLayout12SideBySide")) != null ? _f : false,
    propertyLayout34SideBySide: (_g = getConfig("propertyLayout34SideBySide")) != null ? _g : false,
    propertyLayout56SideBySide: (_h = getConfig("propertyLayout56SideBySide")) != null ? _h : false,
    propertyLayout78SideBySide: (_i = getConfig("propertyLayout78SideBySide")) != null ? _i : false,
    propertyLayout910SideBySide: (_j = getConfig("propertyLayout910SideBySide")) != null ? _j : false,
    propertyLayout1112SideBySide: (_k = getConfig("propertyLayout1112SideBySide")) != null ? _k : false,
    propertyLayout1314SideBySide: (_l = getConfig("propertyLayout1314SideBySide")) != null ? _l : false,
    propertyGroup1Position: getConfig("propertyGroup1Position") || "bottom",
    propertyGroup2Position: getConfig("propertyGroup2Position") || "bottom",
    propertyGroup3Position: getConfig("propertyGroup3Position") || "bottom",
    propertyGroup4Position: getConfig("propertyGroup4Position") || "bottom",
    propertyGroup5Position: getConfig("propertyGroup5Position") || "bottom",
    propertyGroup6Position: getConfig("propertyGroup6Position") || "bottom",
    propertyGroup7Position: getConfig("propertyGroup7Position") || "bottom",
    imageFormat: getConfig("imageFormat") || "thumbnail",
    imagePosition: getConfig("imagePosition") || "right",
    propertyLabels: getConfig("propertyLabels") || "hide",
    showDraftStatus: (_m = getConfig("showDraftStatus")) != null ? _m : false,
    draftStatusProperty: getConfig("draftStatusProperty") || "",
    draftStatusReverse: (_n = getConfig("draftStatusReverse")) != null ? _n : false,
    draftStatusUseFilenamePrefix: (_o = getConfig("draftStatusUseFilenamePrefix")) != null ? _o : false,
    showTags: (_p = getConfig("showTags")) != null ? _p : false,
    tagsProperty: getConfig("tagsProperty") || "",
    maxTagsToShow: (_q = getConfig("maxTagsToShow")) != null ? _q : 3,
    customizeNewButton: (_r = getConfig("customizeNewButton")) != null ? _r : false,
    newNoteLocation: getConfig("newNoteLocation") || "",
    hideQuickEditIcon: (_s = getConfig("hideQuickEditIcon")) != null ? _s : false,
    cardSize: (_t = getConfig("cardSize")) != null ? _t : 250,
    imageAspectRatio: (_u = getConfig("imageAspectRatio")) != null ? _u : 0.55
  };
}
function getCMSViewOptions() {
  const options = [
    // Card size (standalone)
    {
      type: "slider",
      displayName: "Card size",
      key: "cardSize",
      min: 50,
      max: 1e3,
      step: 10,
      default: 250
    },
    // Title group
    {
      type: "group",
      displayName: "Title",
      items: [
        {
          type: "property",
          displayName: "Title property",
          key: "titleProperty",
          placeholder: "Select property",
          default: ""
        }
      ]
    },
    // Text preview group
    {
      type: "group",
      displayName: "Text preview",
      items: [
        {
          type: "toggle",
          displayName: "Show text preview",
          key: "showTextPreview",
          default: true
        },
        {
          type: "property",
          displayName: "Text preview property",
          key: "descriptionProperty",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "toggle",
          displayName: "Use note content if text preview property unavailable",
          key: "fallbackToContent",
          default: true
        },
        {
          type: "toggle",
          displayName: "Truncate preview property",
          key: "truncatePreviewProperty",
          default: false
        }
      ]
    },
    // Image group
    {
      type: "group",
      displayName: "Image",
      items: [
        {
          type: "dropdown",
          displayName: "Image format",
          key: "imageFormat",
          options: {
            "none": "No image",
            "thumbnail": "Thumbnail",
            "cover": "Cover"
          },
          default: "thumbnail"
        },
        {
          type: "property",
          displayName: "Image property",
          key: "imageProperty",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "dropdown",
          displayName: "Show image embeds",
          key: "fallbackToEmbeds",
          options: {
            "always": "Always",
            "if-empty": "If image property missing or empty",
            "never": "Never"
          },
          default: "if-empty"
        },
        {
          type: "slider",
          displayName: "Image aspect ratio",
          key: "imageAspectRatio",
          min: 0.1,
          max: 2,
          step: 0.05,
          default: 0.55,
          showWhen: {
            key: "imageFormat",
            value: "cover"
          }
        }
      ]
    },
    // Date group
    {
      type: "group",
      displayName: "Date",
      items: [
        {
          type: "toggle",
          displayName: "Show date",
          key: "showDate",
          default: false
        },
        {
          type: "property",
          displayName: "Date property",
          key: "dateProperty",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "toggle",
          displayName: "Include time",
          description: "When enabled, displays both date and time using your system locale settings",
          key: "dateIncludeTime",
          default: false
        }
      ]
    },
    // Draft status group
    {
      type: "group",
      displayName: "Draft status",
      items: [
        {
          type: "toggle",
          displayName: "Show draft status",
          key: "showDraftStatus",
          default: false
        },
        {
          type: "property",
          displayName: "Draft status property",
          key: "draftStatusProperty",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "toggle",
          displayName: "Reverse logic",
          key: "draftStatusReverse",
          default: false
        },
        {
          type: "toggle",
          displayName: "Filename underscore prefix as draft indicator",
          key: "draftStatusUseFilenamePrefix",
          default: false
        }
      ]
    },
    // Tags group
    {
      type: "group",
      displayName: "Tags",
      items: [
        {
          type: "toggle",
          displayName: "Show tags",
          key: "showTags",
          default: false
        },
        {
          type: "property",
          displayName: "Tags property",
          key: "tagsProperty",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "slider",
          displayName: "Maximum tags to show",
          key: "maxTagsToShow",
          min: 1,
          max: 50,
          step: 1,
          default: 3,
          showWhen: {
            key: "showTags",
            value: true
          }
        }
      ]
    },
    // Properties group
    {
      type: "group",
      displayName: "Properties",
      items: [
        {
          type: "dropdown",
          displayName: "Show property labels",
          key: "propertyLabels",
          options: {
            "hide": "Hide",
            "inline": "Inline",
            "above": "On top"
          },
          default: "hide"
        }
      ]
    },
    // Property group 1
    {
      type: "group",
      displayName: "Property group 1",
      items: [
        {
          type: "property",
          displayName: "First property",
          key: "propertyDisplay1",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "property",
          displayName: "Second property",
          key: "propertyDisplay2",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "toggle",
          displayName: "Show side-by-side",
          key: "propertyLayout12SideBySide",
          default: false
        },
        {
          type: "dropdown",
          displayName: "Position",
          key: "propertyGroup1Position",
          options: {
            "top": "Top",
            "bottom": "Bottom"
          },
          default: "bottom"
        }
      ]
    },
    // Property group 2
    {
      type: "group",
      displayName: "Property group 2",
      items: [
        {
          type: "property",
          displayName: "Third property",
          key: "propertyDisplay3",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "property",
          displayName: "Fourth property",
          key: "propertyDisplay4",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "toggle",
          displayName: "Show side-by-side",
          key: "propertyLayout34SideBySide",
          default: false
        },
        {
          type: "dropdown",
          displayName: "Position",
          key: "propertyGroup2Position",
          options: {
            "top": "Top",
            "bottom": "Bottom"
          },
          default: "bottom"
        }
      ]
    },
    // Property group 3
    {
      type: "group",
      displayName: "Property group 3",
      items: [
        {
          type: "property",
          displayName: "First property",
          key: "propertyDisplay5",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "property",
          displayName: "Second property",
          key: "propertyDisplay6",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "toggle",
          displayName: "Show side-by-side",
          key: "propertyLayout56SideBySide",
          default: false
        },
        {
          type: "dropdown",
          displayName: "Position",
          key: "propertyGroup3Position",
          options: {
            "top": "Top",
            "bottom": "Bottom"
          },
          default: "bottom"
        }
      ]
    },
    // Property group 4
    {
      type: "group",
      displayName: "Property group 4",
      items: [
        {
          type: "property",
          displayName: "First property",
          key: "propertyDisplay7",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "property",
          displayName: "Second property",
          key: "propertyDisplay8",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "toggle",
          displayName: "Show side-by-side",
          key: "propertyLayout78SideBySide",
          default: false
        },
        {
          type: "dropdown",
          displayName: "Position",
          key: "propertyGroup4Position",
          options: {
            "top": "Top",
            "bottom": "Bottom"
          },
          default: "bottom"
        }
      ]
    },
    // Property group 5
    {
      type: "group",
      displayName: "Property group 5",
      items: [
        {
          type: "property",
          displayName: "First property",
          key: "propertyDisplay9",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "property",
          displayName: "Second property",
          key: "propertyDisplay10",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "toggle",
          displayName: "Show side-by-side",
          key: "propertyLayout910SideBySide",
          default: false
        },
        {
          type: "dropdown",
          displayName: "Position",
          key: "propertyGroup5Position",
          options: {
            "top": "Top",
            "bottom": "Bottom"
          },
          default: "bottom"
        }
      ]
    },
    // Property group 6
    {
      type: "group",
      displayName: "Property group 6",
      items: [
        {
          type: "property",
          displayName: "First property",
          key: "propertyDisplay11",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "property",
          displayName: "Second property",
          key: "propertyDisplay12",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "toggle",
          displayName: "Show side-by-side",
          key: "propertyLayout1112SideBySide",
          default: false
        },
        {
          type: "dropdown",
          displayName: "Position",
          key: "propertyGroup6Position",
          options: {
            "top": "Top",
            "bottom": "Bottom"
          },
          default: "bottom"
        }
      ]
    },
    // Property group 7
    {
      type: "group",
      displayName: "Property group 7",
      items: [
        {
          type: "property",
          displayName: "First property",
          key: "propertyDisplay13",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "property",
          displayName: "Second property",
          key: "propertyDisplay14",
          placeholder: "Select property",
          default: ""
        },
        {
          type: "toggle",
          displayName: "Show side-by-side",
          key: "propertyLayout1314SideBySide",
          default: false
        },
        {
          type: "dropdown",
          displayName: "Position",
          key: "propertyGroup7Position",
          options: {
            "top": "Top",
            "bottom": "Bottom"
          },
          default: "bottom"
        }
      ]
    },
    // Behavior group
    {
      type: "group",
      displayName: "Behavior",
      items: [
        {
          type: "toggle",
          displayName: "Open new notes directly",
          description: "Skip the Bases modal and create notes directly (like the file explorer). When disabled, uses normal Bases behavior with the property popup.",
          key: "customizeNewButton",
          default: false
        },
        {
          type: "text",
          displayName: "Location for new notes",
          description: 'Folder path where new notes will be created. Use / for vault root, or specify a folder path. Works independently of "Open new notes directly".',
          key: "newNoteLocation",
          placeholder: "Simply use / for vault folder",
          default: ""
        },
        {
          type: "toggle",
          displayName: "Hide quick edit icon",
          key: "hideQuickEditIcon",
          default: false
        }
      ]
    }
  ];
  return options;
}
var init_settings_schema = __esm({
  "src/shared/settings-schema.ts"() {
    "use strict";
  }
});

// src/utils/attachment-detection.ts
async function getAttachmentsInNote(app, file) {
  var _a;
  const attachments = [];
  const content = app.vault.getAbstractFileByPath(file.path);
  if (content instanceof import_obsidian17.TFile) {
    if (file.extension === "md") {
      const metadata = app.metadataCache.getFileCache(content);
      const embeds = (metadata == null ? void 0 : metadata.embeds) || [];
      for (const embed of embeds) {
        const embedFile = app.metadataCache.getFirstLinkpathDest(embed.link, file.path);
        if (embedFile instanceof import_obsidian17.TFile) {
          attachments.push(embedFile);
        }
      }
    }
    const frontmatter = await getFileFrontmatter(app, file);
    if (frontmatter) {
      const imagePropertyNames = ["image", "imageOG", "cover", "thumbnail"];
      const validImageExtensions = ["avif", "bmp", "gif", "jpeg", "jpg", "png", "svg", "webp"];
      for (const propName of imagePropertyNames) {
        const propValue = frontmatter[propName];
        if (!propValue) continue;
        const imagePaths = Array.isArray(propValue) ? propValue : [propValue];
        for (const imagePath of imagePaths) {
          if (typeof imagePath !== "string") continue;
          const cleanPath = imagePath.replace(/^!?\[\[([^\]]+)\]\]$/, "$1").trim();
          if (!cleanPath) continue;
          if (cleanPath.startsWith("http://") || cleanPath.startsWith("https://")) {
            continue;
          }
          let imageFile = app.metadataCache.getFirstLinkpathDest(cleanPath, file.path);
          if (!imageFile && cleanPath.startsWith("./")) {
            const relativePath = cleanPath.substring(2);
            const fullPath = ((_a = file.parent) == null ? void 0 : _a.path) ? `${file.parent.path}/${relativePath}` : relativePath;
            const resolvedFile = app.vault.getAbstractFileByPath(fullPath);
            if (resolvedFile instanceof import_obsidian17.TFile) {
              imageFile = resolvedFile;
            }
          }
          if (!imageFile) {
            const absoluteFile = app.vault.getAbstractFileByPath(cleanPath);
            if (absoluteFile instanceof import_obsidian17.TFile) {
              imageFile = absoluteFile;
            }
          }
          if (imageFile && validImageExtensions.includes(imageFile.extension)) {
            attachments.push(imageFile);
          }
        }
      }
    }
  }
  return attachments;
}
async function getAttachmentsInFolder(app, folder) {
  const attachments = [];
  for (const child of folder.children) {
    if (child instanceof import_obsidian17.TFile && (child.extension === "md" || child.extension === "mdx")) {
      attachments.push(...await getAttachmentsInNote(app, child));
    } else if (child instanceof import_obsidian17.TFolder) {
      attachments.push(...await getAttachmentsInFolder(app, child));
    }
  }
  return attachments;
}
async function isAttachmentUsedInOtherNotes(app, attachment, excludedNote, excludedFolder) {
  const allNotes = app.vault.getMarkdownFiles().filter(
    (file) => file.path !== excludedNote.path
  );
  const attachmentPath = attachment.path;
  const attachmentName = attachment.name;
  const attachmentBasename = attachment.basename;
  for (const note of allNotes) {
    if (excludedFolder && note.path.startsWith(excludedFolder.path + "/")) {
      continue;
    }
    const content = await app.vault.read(note);
    if (content.includes(attachmentPath) || content.includes(attachmentName) || content.includes(attachmentBasename) || content.includes(`![[${attachmentName}]]`) || content.includes(`[[${attachmentName}]]`) || content.includes(`(${attachmentName})`) || content.includes(`(${attachmentPath})`)) {
      return true;
    }
  }
  return false;
}
async function findUniqueAttachments(app, deletedNote, deletedFolder) {
  const attachments = [];
  attachments.push(...await getAttachmentsInNote(app, deletedNote));
  if (deletedFolder) {
    attachments.push(...await getAttachmentsInFolder(app, deletedFolder));
  }
  const uniqueAttachments = Array.from(new Set(attachments.map((a) => a.path))).map((path) => app.vault.getAbstractFileByPath(path)).filter((file) => file instanceof import_obsidian17.TFile);
  const result = [];
  for (const attachment of uniqueAttachments) {
    const isUsedElsewhere = await isAttachmentUsedInOtherNotes(
      app,
      attachment,
      deletedNote,
      deletedFolder
    );
    if (!isUsedElsewhere) {
      result.push(attachment);
    }
  }
  return result;
}
var import_obsidian17;
var init_attachment_detection = __esm({
  "src/utils/attachment-detection.ts"() {
    "use strict";
    import_obsidian17 = require("obsidian");
    init_frontmatter_helper();
  }
});

// src/utils/smart-deletion.ts
var smart_deletion_exports = {};
__export(smart_deletion_exports, {
  executeSmartDeletion: () => executeSmartDeletion,
  isFolderBasedContent: () => isFolderBasedContent,
  prepareDeletionPreview: () => prepareDeletionPreview,
  shouldDeleteParentFolder: () => shouldDeleteParentFolder
});
function isFolderBasedContent(file, config) {
  const configuredFilename = config.deleteParentFolderFilename || "index";
  return file.basename === configuredFilename && file.parent !== null;
}
function shouldDeleteParentFolder(file, config) {
  return config.deleteParentFolder && isFolderBasedContent(file, config);
}
async function prepareDeletionPreview(app, files, config) {
  const filesToDelete = [];
  const foldersToDelete = [];
  const attachmentsToDelete = [];
  for (const filePath of files) {
    const file = app.vault.getAbstractFileByPath(filePath);
    if (!(file instanceof import_obsidian18.TFile)) continue;
    if (shouldDeleteParentFolder(file, config)) {
      const parentFolder = file.parent;
      if (parentFolder && !foldersToDelete.includes(parentFolder)) {
        foldersToDelete.push(parentFolder);
        const folderFiles = parentFolder.children.filter(
          (child) => child instanceof import_obsidian18.TFile
        );
        filesToDelete.push(...folderFiles);
      }
    } else {
      filesToDelete.push(file);
    }
    if (config.deleteUniqueAttachments) {
      const parentFolder = shouldDeleteParentFolder(file, config) ? file.parent || void 0 : void 0;
      const uniqueAttachments2 = await findUniqueAttachments(
        app,
        file,
        parentFolder
      );
      attachmentsToDelete.push(...uniqueAttachments2);
    }
  }
  const uniqueFiles = Array.from(new Set(filesToDelete.map((f) => f.path))).map((path) => app.vault.getAbstractFileByPath(path)).filter((file) => file instanceof import_obsidian18.TFile);
  const uniqueAttachments = Array.from(new Set(attachmentsToDelete.map((a) => a.path))).map((path) => app.vault.getAbstractFileByPath(path)).filter((file) => file instanceof import_obsidian18.TFile);
  return {
    filesToDelete: uniqueFiles,
    foldersToDelete: Array.from(new Set(foldersToDelete)),
    attachmentsToDelete: uniqueAttachments
  };
}
async function executeSmartDeletion(app, preview) {
  let deletedCount = 0;
  let errorCount = 0;
  for (const file of preview.filesToDelete) {
    try {
      await app.fileManager.trashFile(file);
      deletedCount++;
    } catch (error) {
      console.error(`Error deleting file ${file.path}:`, error);
      errorCount++;
    }
  }
  for (const attachment of preview.attachmentsToDelete) {
    try {
      await app.fileManager.trashFile(attachment);
      deletedCount++;
    } catch (error) {
      console.error(`Error deleting attachment ${attachment.path}:`, error);
      errorCount++;
    }
  }
  for (const folder of preview.foldersToDelete) {
    try {
      await app.fileManager.trashFile(folder);
      deletedCount++;
    } catch (error) {
      console.error(`Error deleting folder ${folder.path}:`, error);
      errorCount++;
    }
  }
  if (errorCount > 0) {
    new import_obsidian18.Notice(`Deleted ${deletedCount} items, ${errorCount} errors occurred`);
  } else {
    new import_obsidian18.Notice(`Successfully deleted ${deletedCount} item${deletedCount !== 1 ? "s" : ""}`);
  }
}
var import_obsidian18;
var init_smart_deletion = __esm({
  "src/utils/smart-deletion.ts"() {
    "use strict";
    import_obsidian18 = require("obsidian");
    init_attachment_detection();
  }
});

// src/components/deletion-preview.ts
var deletion_preview_exports = {};
__export(deletion_preview_exports, {
  DeletionPreviewModal: () => DeletionPreviewModal
});
var import_obsidian19, DeletionPreviewModal;
var init_deletion_preview = __esm({
  "src/components/deletion-preview.ts"() {
    "use strict";
    import_obsidian19 = require("obsidian");
    init_smart_deletion();
    DeletionPreviewModal = class extends import_obsidian19.Modal {
      constructor(app, preview, onConfirm) {
        super(app);
        this.preview = preview;
        this.onConfirm = onConfirm;
      }
      onOpen() {
        const { contentEl } = this;
        contentEl.empty();
        new import_obsidian19.Setting(contentEl).setName("Confirm deletion").setHeading();
        contentEl.createEl("p", {
          text: "The following items will be deleted:",
          cls: "bases-cms-deletion-warning"
        });
        if (this.preview.filesToDelete.length > 0) {
          contentEl.createEl("h3", { text: `Files (${this.preview.filesToDelete.length})` });
          const filesList = contentEl.createEl("ul", { cls: "bases-cms-deletion-list" });
          for (const file of this.preview.filesToDelete.slice(0, 20)) {
            const li = filesList.createEl("li");
            li.setText(file.path);
          }
          if (this.preview.filesToDelete.length > 20) {
            filesList.createEl("li", {
              text: `... and ${this.preview.filesToDelete.length - 20} more files`
            });
          }
        }
        if (this.preview.foldersToDelete.length > 0) {
          contentEl.createEl("h3", { text: `Folders (${this.preview.foldersToDelete.length})` });
          const foldersList = contentEl.createEl("ul", { cls: "bases-cms-deletion-list" });
          for (const folder of this.preview.foldersToDelete) {
            const li = foldersList.createEl("li");
            li.setText(folder.path);
          }
        }
        if (this.preview.attachmentsToDelete.length > 0) {
          contentEl.createEl("h3", { text: `Attachments (${this.preview.attachmentsToDelete.length})` });
          const attachmentsList = contentEl.createEl("ul", { cls: "bases-cms-deletion-list" });
          for (const attachment of this.preview.attachmentsToDelete.slice(0, 20)) {
            const li = attachmentsList.createEl("li");
            li.setText(attachment.path);
          }
          if (this.preview.attachmentsToDelete.length > 20) {
            attachmentsList.createEl("li", {
              text: `... and ${this.preview.attachmentsToDelete.length - 20} more attachments`
            });
          }
        }
        contentEl.createEl("p", {
          text: "This action cannot be undone.",
          cls: "bases-cms-deletion-warning"
        });
        const buttonContainer = contentEl.createDiv();
        buttonContainer.addClass("bases-cms-modal-button-container");
        const cancelBtn = buttonContainer.createEl("button");
        cancelBtn.setText("Cancel");
        cancelBtn.addEventListener("click", () => this.close());
        const deleteBtn = buttonContainer.createEl("button");
        deleteBtn.setText("Delete");
        deleteBtn.addClass("mod-cta");
        deleteBtn.addClass("destructive");
        deleteBtn.addEventListener("click", () => {
          void (async () => {
            await executeSmartDeletion(this.app, this.preview);
            this.onConfirm();
            this.close();
          })();
        });
      }
      onClose() {
        const { contentEl } = this;
        contentEl.empty();
      }
    };
  }
});

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

// src/settings.ts
var import_obsidian4 = require("obsidian");

// src/components/command-picker-modal.ts
var import_obsidian = require("obsidian");
var CommandPickerModal = class extends import_obsidian.FuzzySuggestModal {
  constructor(app, onSelect) {
    super(app);
    this.onSelect = onSelect;
  }
  getItems() {
    const commandRegistry = this.app.commands;
    const commandMap = /* @__PURE__ */ new Map();
    if (commandRegistry && typeof commandRegistry.listCommands === "function") {
      try {
        const commands = commandRegistry.listCommands();
        for (const command of commands) {
          if (command && command.id && command.name && !commandMap.has(command.id)) {
            commandMap.set(command.id, {
              id: command.id,
              name: command.name
            });
          }
        }
      } catch (e) {
        console.warn("[Bases CMS] Error getting commands via listCommands():", e);
      }
    }
    try {
      const registry = commandRegistry == null ? void 0 : commandRegistry.commands;
      if (registry && typeof registry === "object") {
        const allCommands = Object.values(registry);
        for (const command of allCommands) {
          if (command && command.id && command.name && !commandMap.has(command.id)) {
            commandMap.set(command.id, {
              id: command.id,
              name: command.name
            });
          }
        }
      }
    } catch (e) {
      console.warn("[Bases CMS] Error getting commands via registry:", e);
    }
    try {
      const internalRegistry = commandRegistry == null ? void 0 : commandRegistry.commandRegistry;
      if (internalRegistry && typeof internalRegistry === "object") {
        const allCommands = Object.values(internalRegistry);
        for (const command of allCommands) {
          if (command && command.id && command.name && !commandMap.has(command.id)) {
            commandMap.set(command.id, {
              id: command.id,
              name: command.name
            });
          }
        }
      }
    } catch (e) {
      console.warn("[Bases CMS] Error getting commands via internal registry:", e);
    }
    const commandOptions = Array.from(commandMap.values());
    commandOptions.sort((a, b) => a.name.localeCompare(b.name));
    return commandOptions;
  }
  getItemText(item) {
    return item.name;
  }
  onChooseItem(item, evt) {
    this.onSelect(item.id);
  }
  // Override to show command name only
  renderSuggestion(match, el) {
    const item = match.item;
    el.createDiv({ cls: "suggestion-title", text: item.name });
  }
};

// src/components/icon-picker-modal.ts
var import_obsidian2 = require("obsidian");
var getIconList = () => {
  if (import_obsidian2.requireApiVersion && (0, import_obsidian2.requireApiVersion)("1.7.3") && import_obsidian2.getIconIds) {
    try {
      return (0, import_obsidian2.getIconIds)();
    } catch (e) {
      console.warn("[Bases CMS] Error getting icon IDs from Obsidian:", e);
    }
  }
  return [
    "settings-2",
    "settings",
    "help-circle",
    "info",
    "star",
    "heart",
    "bookmark",
    "home",
    "search",
    "bell",
    "mail",
    "user",
    "users",
    "folder",
    "file",
    "file-text",
    "image",
    "video",
    "music",
    "calendar",
    "clock",
    "edit",
    "pencil",
    "trash",
    "copy",
    "cut",
    "paste",
    "download",
    "upload",
    "save",
    "share",
    "link",
    "external-link",
    "lock",
    "unlock",
    "eye",
    "eye-off",
    "key",
    "shield",
    "check",
    "x",
    "plus",
    "minus",
    "arrow-left",
    "arrow-right",
    "arrow-up",
    "arrow-down",
    "chevron-left",
    "chevron-right",
    "chevron-up",
    "chevron-down",
    "menu",
    "more-horizontal",
    "more-vertical",
    "grid",
    "list",
    "layout",
    "columns",
    "rows",
    "maximize",
    "minimize",
    "zoom-in",
    "zoom-out",
    "refresh-cw",
    "play",
    "pause",
    "stop",
    "sun",
    "moon",
    "cloud",
    "zap",
    "wand-2",
    "wand",
    "wand-sparkles",
    "palette",
    "brush",
    "sliders",
    "power",
    "wifi",
    "bluetooth",
    "monitor",
    "laptop",
    "smartphone",
    "camera",
    "mic",
    "headphones",
    "code",
    "terminal",
    "terminal-square",
    "github",
    "gitlab",
    "git-branch",
    "git-commit",
    "database",
    "server",
    "cloud-download",
    "cloud-upload",
    "tag",
    "tags",
    "flag",
    "pin",
    "map-pin",
    "compass",
    "globe",
    "rocket",
    "car",
    "bike",
    "robot",
    "apple",
    "windows",
    "linux",
    "chrome",
    "firefox",
    "safari",
    "credit-card",
    "wallet",
    "coins",
    "book",
    "book-open",
    "award",
    "trophy",
    "badge",
    "wrench",
    "tool",
    "package",
    "box",
    "archive",
    "send",
    "reply",
    "forward",
    "mail-open",
    "tag-plus",
    "tag-minus",
    "flag-off",
    "pin-off",
    "map-pin-off",
    "navigation",
    "map",
    "earth",
    "plane",
    "ship",
    "anchor",
    "helicopter",
    "drone",
    "android",
    "keyhole",
    "keys",
    "fingerprint",
    "scan",
    "qr-code",
    "barcode",
    "receipt",
    "piggy-bank",
    "banknote",
    "pencil-line",
    "edit-2",
    "edit-3"
  ];
};
var LUCIDE_ICONS = getIconList().map((id) => ({
  id,
  name: id.replace(/^lucide-/, "").replace(/-/g, " ").replace(/(^\w{1})|(\s+\w{1})/g, (letter) => letter.toUpperCase())
})).sort((a, b) => a.name.localeCompare(b.name));
var IconPickerModal = class extends import_obsidian2.FuzzySuggestModal {
  constructor(app, onSelect) {
    super(app);
    this.onSelect = onSelect;
  }
  getItems() {
    return LUCIDE_ICONS;
  }
  getItemText(item) {
    return item.name;
  }
  onChooseItem(item, evt) {
    this.onSelect(item.id);
  }
  // Override to show icon preview
  renderSuggestion(match, el) {
    const item = match.item;
    el.addClass("mod-complex");
    const content = el.createDiv({ cls: "suggestion-content" });
    content.createDiv({ cls: "suggestion-title", text: item.name });
    const aux = el.createDiv({ cls: "suggestion-aux" });
    (0, import_obsidian2.setIcon)(aux.createSpan({ cls: "suggestion-flair" }), item.id);
  }
};

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

// src/settings.ts
var BasesCMSSettingTab = class extends import_obsidian4.PluginSettingTab {
  constructor(app, plugin) {
    super(app, plugin);
    this.icon = "lucide-blocks";
    this.plugin = plugin;
  }
  /**
   * Refresh toolbars in all active CMS views when settings change
   */
  refreshActiveToolbars() {
    const pluginWithMethod = this.plugin;
    if (pluginWithMethod && typeof pluginWithMethod.refreshAllToolbars === "function") {
      pluginWithMethod.refreshAllToolbars();
    }
  }
  display() {
    const { containerEl } = this;
    containerEl.empty();
    new import_obsidian4.Setting(containerEl).setName("Confirm bulk operations").setDesc("Show confirmation dialogs before performing bulk operations.").addToggle((toggle) => toggle.setValue(this.plugin.settings.confirmBulkOperations).onChange((value) => {
      void (async () => {
        this.plugin.settings.confirmBulkOperations = value;
        await this.plugin.saveData(this.plugin.settings);
      })();
    }));
    const toolbarButtonsGroup = createSettingsGroup(containerEl, "Toolbar buttons", "bases-cms");
    toolbarButtonsGroup.addSetting((setting) => {
      setting.setName("Show select all button").setDesc("Display the select all button in the CMS toolbar.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.showToolbarSelectAll);
        toggle.onChange(async (value) => {
          this.plugin.settings.showToolbarSelectAll = value;
          await this.plugin.saveData(this.plugin.settings);
          this.refreshActiveToolbars();
        });
      });
    });
    toolbarButtonsGroup.addSetting((setting) => {
      setting.setName("Show clear button").setDesc("Display the clear selection button in the CMS toolbar.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.showToolbarClear);
        toggle.onChange(async (value) => {
          this.plugin.settings.showToolbarClear = value;
          await this.plugin.saveData(this.plugin.settings);
          this.refreshActiveToolbars();
        });
      });
    });
    toolbarButtonsGroup.addSetting((setting) => {
      setting.setName("Show publish button").setDesc("Display the publish button in the CMS toolbar.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.showToolbarPublish);
        toggle.onChange(async (value) => {
          this.plugin.settings.showToolbarPublish = value;
          await this.plugin.saveData(this.plugin.settings);
          this.refreshActiveToolbars();
        });
      });
    });
    toolbarButtonsGroup.addSetting((setting) => {
      setting.setName("Show draft button").setDesc("Display the draft button in the CMS toolbar.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.showToolbarDraft);
        toggle.onChange(async (value) => {
          this.plugin.settings.showToolbarDraft = value;
          await this.plugin.saveData(this.plugin.settings);
          this.refreshActiveToolbars();
        });
      });
    });
    toolbarButtonsGroup.addSetting((setting) => {
      setting.setName("Show tags button").setDesc("Display the tags button in the CMS toolbar.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.showToolbarTags);
        toggle.onChange(async (value) => {
          this.plugin.settings.showToolbarTags = value;
          await this.plugin.saveData(this.plugin.settings);
          this.refreshActiveToolbars();
        });
      });
    });
    toolbarButtonsGroup.addSetting((setting) => {
      setting.setName("Show set button").setDesc("Display the set property button in the CMS toolbar.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.showToolbarSet);
        toggle.onChange(async (value) => {
          this.plugin.settings.showToolbarSet = value;
          await this.plugin.saveData(this.plugin.settings);
          this.refreshActiveToolbars();
        });
      });
    });
    toolbarButtonsGroup.addSetting((setting) => {
      setting.setName("Show remove button").setDesc("Display the remove property button in the CMS toolbar.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.showToolbarRemove);
        toggle.onChange(async (value) => {
          this.plugin.settings.showToolbarRemove = value;
          await this.plugin.saveData(this.plugin.settings);
          this.refreshActiveToolbars();
        });
      });
    });
    toolbarButtonsGroup.addSetting((setting) => {
      setting.setName("Show delete button").setDesc("Display the delete button in the CMS toolbar.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.showToolbarDelete);
        toggle.onChange(async (value) => {
          this.plugin.settings.showToolbarDelete = value;
          await this.plugin.saveData(this.plugin.settings);
          this.refreshActiveToolbars();
        });
      });
    });
    const deletionsGroup = createSettingsGroup(containerEl, "Deletions", "bases-cms");
    deletionsGroup.addSetting((setting) => {
      setting.setName("Delete parent folder for specific file name").setDesc("When enabled, deleting a note will delete its parent folder and all its contents if the note file name matches the specified name.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.deleteParentFolder);
        toggle.onChange(async (value) => {
          this.plugin.settings.deleteParentFolder = value;
          await this.plugin.saveData(this.plugin.settings);
        });
      });
    });
    deletionsGroup.addSetting((setting) => {
      setting.setName("Folder deletion file name").setDesc("File name that triggers parent folder deletion.").addText((text) => {
        text.setPlaceholder("index");
        text.setValue(this.plugin.settings.deleteParentFolderFilename);
        text.onChange(async (value) => {
          this.plugin.settings.deleteParentFolderFilename = value;
          await this.plugin.saveData(this.plugin.settings);
        });
      }).setDisabled(!this.plugin.settings.deleteParentFolder);
    });
    deletionsGroup.addSetting((setting) => {
      setting.setName("Delete associated unique attachments").setDesc("When deleting a note, automatically delete attachments that are only used by that note. Attachments used by other notes will be preserved.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.deleteUniqueAttachments);
        toggle.onChange(async (value) => {
          this.plugin.settings.deleteUniqueAttachments = value;
          await this.plugin.saveData(this.plugin.settings);
        });
      });
    });
    deletionsGroup.addSetting((setting) => {
      setting.setName("Confirm deletions").setDesc("Show confirmation dialog before deleting files.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.confirmDeletions);
        toggle.onChange(async (value) => {
          this.plugin.settings.confirmDeletions = value;
          await this.plugin.saveData(this.plugin.settings);
        });
      });
    });
    const appearanceGroup = createSettingsGroup(containerEl, "Appearance", "bases-cms");
    appearanceGroup.addSetting((setting) => {
      setting.setName("Use home icon for CMS view").setDesc("Use the home icon instead of blocks icon for the CMS view in the Bases view selector. Restart Obsidian for this change to take effect.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.useHomeIcon);
        toggle.onChange(async (value) => {
          this.plugin.settings.useHomeIcon = value;
          await this.plugin.saveData(this.plugin.settings);
        });
      });
    });
    appearanceGroup.addSetting((setting) => {
      setting.setName("Force static image for animated GIFs").setDesc("When enabled, animated GIFs will display only the first frame when used as card covers or thumbnails.").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.forceStaticGifImages);
        toggle.onChange(async (value) => {
          this.plugin.settings.forceStaticGifImages = value;
          await this.plugin.saveData(this.plugin.settings);
          const pluginWithMethod = this.plugin;
          if (pluginWithMethod.activeViews) {
            pluginWithMethod.activeViews.forEach((view) => {
              if (view.onDataUpdated) {
                view.onDataUpdated();
              }
            });
          }
        });
      });
    });
    const performanceGroup = createSettingsGroup(containerEl, "Performance", "bases-cms");
    performanceGroup.addSetting((setting) => {
      setting.setName("Embedded view refresh debounce (ms)").setDesc("Delay in milliseconds before refreshing embedded views when switching files. Higher values reduce CPU usage but may make views feel less responsive. Range: 50-500ms.").addSlider((slider) => {
        slider.setLimits(50, 500, 25);
        slider.setValue(this.plugin.settings.embeddedViewRefreshDebounceMs);
        slider.setDynamicTooltip();
        slider.onChange(async (value) => {
          this.plugin.settings.embeddedViewRefreshDebounceMs = value;
          await this.plugin.saveData(this.plugin.settings);
        });
      });
    });
    performanceGroup.addSetting((setting) => {
      setting.setName("Virtual scrolling threshold").setDesc("Number of cards above which virtual scrolling is enabled. Virtual scrolling only renders cards in the viewport, improving performance for large collections. Set to 0 to always enable, or a high value to disable.").addSlider((slider) => {
        slider.setLimits(0, 500, 25);
        slider.setValue(this.plugin.settings.virtualScrollThreshold);
        slider.setDynamicTooltip();
        slider.onChange(async (value) => {
          this.plugin.settings.virtualScrollThreshold = value;
          await this.plugin.saveData(this.plugin.settings);
        });
      });
    });
    performanceGroup.addSetting((setting) => {
      setting.setName("Virtual scroll buffer").setDesc("Number of cards to render above and below the visible viewport when virtual scrolling is active. Higher values reduce visual glitches when scrolling fast but use more memory.").addSlider((slider) => {
        slider.setLimits(5, 50, 5);
        slider.setValue(this.plugin.settings.virtualScrollBuffer);
        slider.setDynamicTooltip();
        slider.onChange(async (value) => {
          this.plugin.settings.virtualScrollBuffer = value;
          await this.plugin.saveData(this.plugin.settings);
        });
      });
    });
    const quickEditGroup = createSettingsGroup(containerEl, "Quick edit", "bases-cms");
    let quickEditCommandSetting;
    let quickEditIconSetting;
    let quickEditOpenFileSetting;
    quickEditGroup.addSetting((setting) => {
      setting.setName("Enable quick edit").setDesc("Show an icon on card titles that launches a command when clicked.").addToggle((toggle) => toggle.setValue(this.plugin.settings.enableQuickEdit).onChange((value) => {
        void (async () => {
          this.plugin.settings.enableQuickEdit = value;
          await this.plugin.saveData(this.plugin.settings);
          const shouldHide = !value;
          const commandEl = quickEditCommandSetting == null ? void 0 : quickEditCommandSetting.settingEl;
          const iconEl = quickEditIconSetting == null ? void 0 : quickEditIconSetting.settingEl;
          const openFileEl = quickEditOpenFileSetting == null ? void 0 : quickEditOpenFileSetting.settingEl;
          if (commandEl) {
            commandEl.toggleClass("bases-cms-setting-hidden", shouldHide);
          }
          if (iconEl) {
            iconEl.toggleClass("bases-cms-setting-hidden", shouldHide);
          }
          if (openFileEl) {
            openFileEl.toggleClass("bases-cms-setting-hidden", shouldHide);
          }
        })();
      }));
    });
    quickEditGroup.addSetting((setting) => {
      quickEditCommandSetting = setting;
      setting.setName("Quick edit command").setDesc("The command to execute when clicking the quick edit icon on a card title.").addButton((button) => {
        var _a;
        const currentCommandName = this.plugin.settings.quickEditCommandName || (this.plugin.settings.quickEditCommand ? "Select command..." : "No command selected");
        button.setButtonText(currentCommandName).onClick(() => {
          const modal = new CommandPickerModal(this.app, (commandId) => {
            void (async () => {
              const commandRegistry = this.app.commands;
              let commandName = "";
              if (commandRegistry) {
                if (typeof commandRegistry.listCommands === "function") {
                  const commands = commandRegistry.listCommands();
                  const command = commands.find((cmd) => cmd.id === commandId);
                  if (command) {
                    commandName = command.name;
                  }
                }
                if (!commandName) {
                  const registry = commandRegistry.commands;
                  if (registry && registry[commandId]) {
                    commandName = registry[commandId].name || "";
                  }
                }
              }
              this.plugin.settings.quickEditCommand = commandId;
              this.plugin.settings.quickEditCommandName = commandName;
              await this.plugin.saveData(this.plugin.settings);
              this.display();
            })();
          });
          modal.open();
        });
        if (this.plugin.settings.quickEditCommand) {
          const clearButton = (_a = button.buttonEl.parentElement) == null ? void 0 : _a.createEl("button", {
            text: "Clear",
            attr: { style: "margin-left: 8px;" }
          });
          clearButton == null ? void 0 : clearButton.addEventListener("click", () => {
            void (async () => {
              this.plugin.settings.quickEditCommand = "";
              this.plugin.settings.quickEditCommandName = "";
              await this.plugin.saveData(this.plugin.settings);
              this.display();
            })();
          });
        }
      });
      setting.settingEl.toggleClass("bases-cms-setting-hidden", !this.plugin.settings.enableQuickEdit);
    });
    quickEditGroup.addSetting((setting) => {
      quickEditIconSetting = setting;
      setting.setName("Quick edit icon").setDesc("Select the icon to display for the quick edit button on card titles.").addButton((button) => {
        const iconName = this.getIconName(this.plugin.settings.quickEditIcon || "pencil-line");
        button.setButtonText(iconName || "Select icon...").onClick(() => {
          const modal = new IconPickerModal(this.app, (iconId) => {
            void (async () => {
              this.plugin.settings.quickEditIcon = iconId;
              await this.plugin.saveData(this.plugin.settings);
              this.display();
            })();
          });
          modal.open();
        });
      });
      setting.settingEl.toggleClass("bases-cms-setting-hidden", !this.plugin.settings.enableQuickEdit);
    });
    quickEditGroup.addSetting((setting) => {
      quickEditOpenFileSetting = setting;
      setting.setName("Attempt to open file and execute quick edit command").setDesc("For commands that don't have special handling, attempt to open the file and execute the command. Some commands may not work properly this way.").addToggle((toggle) => toggle.setValue(this.plugin.settings.quickEditOpenFile).onChange((value) => {
        void (async () => {
          this.plugin.settings.quickEditOpenFile = value;
          await this.plugin.saveData(this.plugin.settings);
        })();
      }));
      setting.settingEl.toggleClass("bases-cms-setting-hidden", !this.plugin.settings.enableQuickEdit);
    });
  }
  getIconName(iconId) {
    if (!iconId) return "";
    return iconId.replace(/^lucide-/, "").split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
  }
};

// src/views/cms-view.ts
var import_obsidian23 = require("obsidian");

// src/utils/css-props.ts
function setCssProps(element, props) {
  for (const [key, value] of Object.entries(props)) {
    if (key.startsWith("--")) {
      element.style.setProperty(key, String(value));
    } else {
      const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
      element.style.setProperty(cssKey, String(value));
    }
  }
}

// src/shared/data-transform.ts
var import_obsidian7 = require("obsidian");

// src/utils/property.ts
var import_obsidian6 = require("obsidian");
init_frontmatter_helper();
async function getFirstBasesPropertyValue(entry, propertyString, app) {
  if (!propertyString || !propertyString.trim()) return null;
  const properties = propertyString.split(",").map((p) => p.trim()).filter((p) => p);
  for (const prop of properties) {
    const value = entry.getValue(prop);
    const valueObj = value;
    const propertyExists = valueObj && ("date" in valueObj && valueObj.date instanceof Date || "data" in valueObj && valueObj.data != null);
    if (propertyExists) {
      return value;
    }
    if (!propertyExists && app) {
      const file = app.vault.getAbstractFileByPath(entry.file.path);
      if (file instanceof import_obsidian6.TFile && file.extension === "mdx") {
        const frontmatter = await getFileFrontmatter(app, file);
        if (frontmatter) {
          const cleanProp = prop.startsWith("note.") ? prop.substring(5) : prop;
          const frontmatterValue = frontmatter[cleanProp];
          if (frontmatterValue != null) {
            return { data: frontmatterValue };
          }
        }
      }
    }
  }
  return null;
}
async function getAllBasesImagePropertyValues(entry, propertyString, app) {
  if (!propertyString || !propertyString.trim()) return [];
  const prop = propertyString.split(",")[0].trim();
  if (!prop) return [];
  const value = entry.getValue(prop);
  let data = null;
  if (value && "data" in value) {
    data = value.data;
  } else if (app) {
    const file = app.vault.getAbstractFileByPath(entry.file.path);
    if (file instanceof import_obsidian6.TFile && file.extension === "mdx") {
      const frontmatter = await getFileFrontmatter(app, file);
      if (frontmatter) {
        const cleanProp = prop.startsWith("note.") ? prop.substring(5) : prop;
        data = frontmatter[cleanProp];
      }
    }
  }
  if (data == null) return [];
  const images = [];
  if (Array.isArray(data)) {
    for (const item of data) {
      if (typeof item === "string" || typeof item === "number") {
        const str = String(item);
        if (str && str.trim()) {
          images.push(str);
        }
      }
    }
  } else if (data !== "") {
    if (typeof data === "string" || typeof data === "number") {
      const str = String(data);
      if (str.trim()) {
        images.push(str);
      }
    }
  }
  return images;
}
function getPropertyLabel(propertyName, app, basesConfig, basesController) {
  if (!propertyName || propertyName === "") return "";
  if (basesConfig) {
    const configWithDisplayName = basesConfig;
    if (typeof configWithDisplayName.getDisplayName === "function") {
      try {
        const displayName = configWithDisplayName.getDisplayName(propertyName);
        if (displayName && typeof displayName === "string" && displayName.trim() !== "") {
          return displayName;
        }
      } catch (e) {
      }
    }
  }
  return propertyName;
}

// src/utils/style-settings.ts
function hasBodyClass(className) {
  return document.body.classList.contains(className);
}
function getListSeparator() {
  let value = getComputedStyle(document.body).getPropertyValue(
    "--bases-cms-list-separator"
  );
  if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
    value = value.slice(1, -1);
  }
  return value || ", ";
}
function getEmptyValueMarker() {
  let value = getComputedStyle(document.body).getPropertyValue(
    "--bases-cms-empty-value-marker"
  );
  if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
    value = value.slice(1, -1);
  }
  return value || "\u2014";
}
function shouldHideMissingProperties() {
  return hasBodyClass("bases-cms-hide-missing-properties");
}
function shouldHideEmptyProperties() {
  const hasClass = hasBodyClass("bases-cms-hide-empty-properties");
  if (hasClass) return true;
  return false;
}
function getTagStyle() {
  if (hasBodyClass("bases-cms-tag-style-minimal")) return "minimal";
  if (hasBodyClass("bases-cms-tag-style-theme")) return "theme";
  return "plain";
}
function showTagHashPrefix() {
  return hasBodyClass("bases-cms-show-tag-hash");
}

// src/shared/data-transform.ts
init_frontmatter_helper();
function removeDuplication(str) {
  if (str.length === 0) return str;
  for (let len = 1; len <= Math.floor(str.length / 2); len++) {
    const prefix = str.substring(0, len);
    const repeatCount = Math.floor(str.length / len);
    if (repeatCount < 2) continue;
    let isCompleteDuplication = true;
    for (let i = 1; i < repeatCount; i++) {
      const segment = str.substring(i * len, (i + 1) * len);
      if (segment !== prefix) {
        isCompleteDuplication = false;
        break;
      }
    }
    const remainder = str.length % len;
    if (remainder > 0) {
      const lastSegment = str.substring(repeatCount * len);
      if (lastSegment !== prefix.substring(0, remainder)) {
        isCompleteDuplication = false;
      }
    }
    if (isCompleteDuplication) {
      return prefix;
    }
  }
  return str;
}
async function basesEntryToCardData(entry, settings, sortMethod, isShuffled, snippet, imageUrl, hasImageAvailable, app, mdxFrontmatterCache) {
  var _a;
  const fileName = entry.file.basename || entry.file.name;
  let titleValue = null;
  if (app) {
    const file = app.vault.getAbstractFileByPath(entry.file.path);
    if (file instanceof import_obsidian7.TFile && file.extension === "mdx" && mdxFrontmatterCache) {
      const frontmatter = mdxFrontmatterCache[entry.file.path];
      if (frontmatter) {
        const cleanProp = settings.titleProperty.startsWith("note.") ? settings.titleProperty.substring(5) : settings.titleProperty;
        const frontmatterValue = frontmatter[cleanProp];
        if (frontmatterValue != null) {
          titleValue = { data: frontmatterValue };
        }
      }
    }
  }
  if (!titleValue) {
    titleValue = await getFirstBasesPropertyValue(entry, settings.titleProperty, app);
  }
  const titleData = titleValue == null ? void 0 : titleValue.data;
  let title;
  if (titleData != null && titleData !== "") {
    if (Array.isArray(titleData)) {
      const items = titleData.map((item) => {
        if (item && typeof item === "object" && "data" in item) {
          return String(item.data);
        }
        return String(item);
      }).filter((s) => s.trim().length > 0);
      title = items.length > 0 ? items.join(", ") : fileName;
    } else if (typeof titleData === "string" || typeof titleData === "number") {
      title = String(titleData);
    } else {
      title = fileName;
    }
  } else {
    title = fileName;
  }
  const path = entry.file.path;
  const folderPath = path.split("/").slice(0, -1).join("/");
  let yamlTagsValue = entry.getValue("note.tags");
  let yamlTags = [];
  if (!yamlTagsValue && app) {
    const file = app.vault.getAbstractFileByPath(entry.file.path);
    if (file instanceof import_obsidian7.TFile && file.extension === "mdx") {
      let frontmatter = (_a = mdxFrontmatterCache == null ? void 0 : mdxFrontmatterCache[entry.file.path]) != null ? _a : null;
      if (frontmatter === void 0) {
        frontmatter = await getFileFrontmatter(app, file);
      }
      if (frontmatter == null ? void 0 : frontmatter.tags) {
        const tagData = frontmatter.tags;
        const rawTags = Array.isArray(tagData) ? tagData.map((t) => {
          if (t && typeof t === "object" && t !== null) {
            return JSON.stringify(t);
          }
          if (typeof t === "string" || typeof t === "number") {
            return String(t);
          }
          return t ? JSON.stringify(t) : "";
        }) : (() => {
          if (tagData && typeof tagData === "object" && tagData !== null) {
            return [JSON.stringify(tagData)];
          }
          if (typeof tagData === "string" || typeof tagData === "number") {
            return [String(tagData)];
          }
          return tagData ? [JSON.stringify(tagData)] : [""];
        })();
        yamlTags = rawTags.map((tag) => tag.replace(/^#/, ""));
      }
    }
  }
  if (yamlTagsValue && yamlTagsValue.data != null) {
    const tagData = yamlTagsValue.data;
    const rawTags = Array.isArray(tagData) ? tagData.map((t) => {
      if (t && typeof t === "object" && "data" in t) {
        return String(t.data);
      }
      return typeof t === "string" || typeof t === "number" ? String(t) : "";
    }).filter((t) => t) : typeof tagData === "string" || typeof tagData === "number" ? [String(tagData)] : [];
    yamlTags = rawTags.map((tag) => tag.replace(/^#/, ""));
  }
  let allTagsValue = entry.getValue("file.tags");
  let tags = [];
  if (allTagsValue && allTagsValue.data != null) {
    const tagData = allTagsValue.data;
    const rawTags = Array.isArray(tagData) ? tagData.map((t) => {
      if (t && typeof t === "object" && t !== null && "data" in t) {
        const itemData = t.data;
        if (itemData && typeof itemData === "object" && itemData !== null) {
          return JSON.stringify(itemData);
        }
        return String(itemData);
      }
      if (t && typeof t === "object" && t !== null) {
        return JSON.stringify(t);
      }
      return typeof t === "string" || typeof t === "number" ? String(t) : "";
    }).filter((t) => typeof t === "string" && t.length > 0) : (() => {
      if (tagData && typeof tagData === "object" && tagData !== null) {
        return [JSON.stringify(tagData)];
      }
      return typeof tagData === "string" || typeof tagData === "number" ? [String(tagData)] : [];
    })();
    tags = rawTags.map((tag) => tag.replace(/^#/, ""));
  } else if (!allTagsValue && app) {
    const file = app.vault.getAbstractFileByPath(entry.file.path);
    if (file instanceof import_obsidian7.TFile && file.extension === "mdx") {
      tags = [...yamlTags];
    }
  }
  const ctime = entry.file.stat.ctime;
  const mtime = entry.file.stat.mtime;
  let displayTags = [];
  if (settings.showTags && settings.tagsProperty) {
    const tagsValue = await getFirstBasesPropertyValue(entry, settings.tagsProperty, app);
    if (tagsValue && tagsValue.data != null) {
      const tagData = tagsValue.data;
      if (Array.isArray(tagData)) {
        displayTags = tagData.map((t) => {
          if (t && typeof t === "object" && "data" in t) {
            return String(t.data);
          }
          return typeof t === "string" || typeof t === "number" ? String(t) : "";
        }).filter((t) => typeof t === "string" && t.length > 0);
      } else if (typeof tagData === "string" || typeof tagData === "number") {
        displayTags = [String(tagData)];
      }
    }
  }
  const cardData = {
    path,
    name: fileName,
    title,
    tags,
    yamlTags,
    ctime,
    mtime,
    folderPath,
    snippet,
    imageUrl,
    hasImageAvailable: hasImageAvailable || false,
    displayTags: displayTags.length > 0 ? displayTags : void 0
  };
  const props = [
    settings.propertyDisplay1,
    settings.propertyDisplay2,
    settings.propertyDisplay3,
    settings.propertyDisplay4,
    settings.propertyDisplay5,
    settings.propertyDisplay6,
    settings.propertyDisplay7,
    settings.propertyDisplay8,
    settings.propertyDisplay9,
    settings.propertyDisplay10,
    settings.propertyDisplay11,
    settings.propertyDisplay12,
    settings.propertyDisplay13,
    settings.propertyDisplay14
  ];
  const seen = /* @__PURE__ */ new Set();
  const effectiveProps = props.map((prop) => {
    if (!prop || prop === "") return "";
    if (seen.has(prop)) return "";
    seen.add(prop);
    return prop;
  });
  cardData.propertyName1 = effectiveProps[0] || void 0;
  cardData.propertyName2 = effectiveProps[1] || void 0;
  cardData.propertyName3 = effectiveProps[2] || void 0;
  cardData.propertyName4 = effectiveProps[3] || void 0;
  cardData.propertyName5 = effectiveProps[4] || void 0;
  cardData.propertyName6 = effectiveProps[5] || void 0;
  cardData.propertyName7 = effectiveProps[6] || void 0;
  cardData.propertyName8 = effectiveProps[7] || void 0;
  cardData.propertyName9 = effectiveProps[8] || void 0;
  cardData.propertyName10 = effectiveProps[9] || void 0;
  cardData.propertyName11 = effectiveProps[10] || void 0;
  cardData.propertyName12 = effectiveProps[11] || void 0;
  cardData.propertyName13 = effectiveProps[12] || void 0;
  cardData.propertyName14 = effectiveProps[13] || void 0;
  cardData.property1 = effectiveProps[0] ? await resolveBasesPropertyAsync(effectiveProps[0], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property2 = effectiveProps[1] ? await resolveBasesPropertyAsync(effectiveProps[1], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property3 = effectiveProps[2] ? await resolveBasesPropertyAsync(effectiveProps[2], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property4 = effectiveProps[3] ? await resolveBasesPropertyAsync(effectiveProps[3], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property5 = effectiveProps[4] ? await resolveBasesPropertyAsync(effectiveProps[4], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property6 = effectiveProps[5] ? await resolveBasesPropertyAsync(effectiveProps[5], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property7 = effectiveProps[6] ? await resolveBasesPropertyAsync(effectiveProps[6], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property8 = effectiveProps[7] ? await resolveBasesPropertyAsync(effectiveProps[7], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property9 = effectiveProps[8] ? await resolveBasesPropertyAsync(effectiveProps[8], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property10 = effectiveProps[9] ? await resolveBasesPropertyAsync(effectiveProps[9], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property11 = effectiveProps[10] ? await resolveBasesPropertyAsync(effectiveProps[10], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property12 = effectiveProps[11] ? await resolveBasesPropertyAsync(effectiveProps[11], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property13 = effectiveProps[12] ? await resolveBasesPropertyAsync(effectiveProps[12], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  cardData.property14 = effectiveProps[13] ? await resolveBasesPropertyAsync(effectiveProps[13], entry, cardData, settings, app, mdxFrontmatterCache) : null;
  return cardData;
}
async function transformBasesEntries(entries, settings, sortMethod, isShuffled, snippets, images, hasImageAvailable, app, mdxFrontmatterCache) {
  return Promise.all(entries.map((entry) => basesEntryToCardData(
    entry,
    settings,
    sortMethod,
    isShuffled,
    snippets[entry.file.path],
    images[entry.file.path],
    hasImageAvailable[entry.file.path],
    app,
    mdxFrontmatterCache
  )));
}
async function resolveBasesPropertyAsync(propertyName, entry, cardData, settings, app, mdxFrontmatterCache) {
  if (!propertyName || propertyName === "") {
    return null;
  }
  if (propertyName === "file.path" || propertyName === "file path") {
    return cardData.folderPath || null;
  }
  if (propertyName === "tags" || propertyName === "note.tags") {
    return cardData.yamlTags.length > 0 ? "tags" : null;
  }
  if (propertyName === "file.tags" || propertyName === "file tags") {
    return cardData.tags.length > 0 ? "tags" : null;
  }
  if (propertyName === "file.ctime" || propertyName === "created time") {
    return new Date(cardData.ctime).toLocaleDateString();
  }
  if (propertyName === "file.mtime" || propertyName === "modified time") {
    return new Date(cardData.mtime).toLocaleDateString();
  }
  let value = null;
  if (app) {
    const file = app.vault.getAbstractFileByPath(entry.file.path);
    if (file instanceof import_obsidian7.TFile && file.extension === "mdx" && mdxFrontmatterCache) {
      const frontmatter = mdxFrontmatterCache[entry.file.path];
      if (frontmatter) {
        const cleanProp = propertyName.startsWith("note.") ? propertyName.substring(5) : propertyName;
        const frontmatterValue = frontmatter[cleanProp];
        if (frontmatterValue != null) {
          value = { data: frontmatterValue };
        }
      }
    }
  }
  if (!value) {
    value = await getFirstBasesPropertyValue(entry, propertyName, app);
  }
  if (!value) return null;
  const valueObj = value;
  if (!valueObj) return null;
  if ("date" in valueObj && valueObj.date instanceof Date) {
    return valueObj.date.toLocaleDateString();
  }
  const data = valueObj.data;
  if (data == null) {
    return null;
  }
  if (data === "") {
    return "";
  }
  if (typeof data === "string") {
    const trimmed = data.trim();
    if (trimmed.length === 0) {
      return "";
    }
    return removeDuplication(trimmed);
  }
  if (Array.isArray(data)) {
    if (data.length === 0) {
      return "";
    }
    const uniqueItems = /* @__PURE__ */ new Set();
    const result = [];
    for (const item of data) {
      let str;
      if (item && typeof item === "object" && "data" in item) {
        const itemData = item.data;
        if (itemData && typeof itemData === "object" && !Array.isArray(itemData) && "data" in itemData) {
          str = String(itemData.data);
        } else {
          str = String(itemData);
        }
      } else if (item && typeof item === "object" && item !== null) {
        str = String(item);
      } else {
        str = String(item);
      }
      const trimmed = str.trim();
      if (trimmed && trimmed !== "") {
        const deduplicated = removeDuplication(trimmed);
        if (deduplicated && deduplicated !== "" && !uniqueItems.has(deduplicated)) {
          uniqueItems.add(deduplicated);
          result.push(deduplicated);
        }
      }
    }
    if (result.length > 0) {
      return result.join(getListSeparator());
    }
    return null;
  }
  if (typeof data === "string") {
    let str = data.trim();
    if (str.length === 0) {
      return null;
    }
    return removeDuplication(str);
  }
  if (typeof data === "number" || typeof data === "boolean") {
    return String(data);
  }
  return null;
}

// src/views/cms-view.ts
init_settings_schema();

// src/utils/image.ts
var import_obsidian8 = require("obsidian");
function isExternalUrl(url) {
  return /^https?:\/\//i.test(url);
}
function hasValidImageExtension(path) {
  return /\.(avif|bmp|gif|jpe?g|png|svg|webp)$/i.test(path);
}
function validateImageUrl(url) {
  return new Promise((resolve) => {
    const img = new Image();
    img.onload = () => resolve(true);
    img.onerror = () => resolve(false);
    setTimeout(() => resolve(false), 5e3);
    img.src = url;
  });
}
function stripWikilinkSyntax(path) {
  const wikilinkMatch = path.match(/^!?\[\[([^\]|]+)(?:\|[^\]]*)?\]\]$/);
  return wikilinkMatch ? wikilinkMatch[1].trim() : path;
}
async function processImagePaths(imagePaths) {
  const internalPaths = [];
  const externalUrlCandidates = [];
  for (const imgPath of imagePaths) {
    const cleanPath = stripWikilinkSyntax(imgPath);
    if (cleanPath.length === 0) continue;
    if (isExternalUrl(cleanPath)) {
      externalUrlCandidates.push(cleanPath);
    } else {
      if (hasValidImageExtension(cleanPath)) {
        internalPaths.push(cleanPath);
      }
    }
  }
  const validationPromises = externalUrlCandidates.map(
    (url) => validateImageUrl(url).then((isValid) => isValid ? url : null)
  );
  const validatedUrls = await Promise.all(validationPromises);
  const externalUrls = validatedUrls.filter((url) => url !== null);
  return { internalPaths, externalUrls };
}
function resolveInternalImagePaths(internalPaths, sourcePath, app) {
  const validImageExtensions = ["avif", "bmp", "gif", "jpeg", "jpg", "png", "svg", "webp"];
  const resourcePaths = [];
  for (const propPath of internalPaths) {
    let imageFile = app.metadataCache.getFirstLinkpathDest(propPath, sourcePath);
    if (!imageFile && propPath.startsWith("./")) {
      const sourceFile = app.vault.getAbstractFileByPath(sourcePath);
      if (sourceFile && sourceFile.parent) {
        const relativePath = propPath.substring(2);
        const fullPath = sourceFile.parent.path ? `${sourceFile.parent.path}/${relativePath}` : relativePath;
        const resolvedFile = app.vault.getAbstractFileByPath(fullPath);
        if (resolvedFile instanceof import_obsidian8.TFile) {
          imageFile = resolvedFile;
        }
      }
    }
    if (!imageFile) {
      const absoluteFile = app.vault.getAbstractFileByPath(propPath);
      if (absoluteFile instanceof import_obsidian8.TFile) {
        imageFile = absoluteFile;
      }
    }
    if (imageFile && validImageExtensions.includes(imageFile.extension)) {
      const resourcePath = app.vault.getResourcePath(imageFile);
      resourcePaths.push(resourcePath);
    }
  }
  return resourcePaths;
}
async function extractEmbedImages(file, app) {
  const validImageExtensions = ["avif", "bmp", "gif", "jpeg", "jpg", "png", "svg", "webp"];
  const metadata = app.metadataCache.getFileCache(file);
  const bodyResourcePaths = [];
  const bodyExternalUrlCandidates = /* @__PURE__ */ new Set();
  if (metadata == null ? void 0 : metadata.embeds) {
    for (const embed of metadata.embeds) {
      const embedLink = embed.link;
      if (isExternalUrl(embedLink)) {
        if (hasValidImageExtension(embedLink) || !embedLink.includes(".")) {
          bodyExternalUrlCandidates.add(embedLink);
        }
      } else {
        const targetFile = app.metadataCache.getFirstLinkpathDest(embedLink, file.path);
        if (targetFile && validImageExtensions.includes(targetFile.extension)) {
          const resourcePath = app.vault.getResourcePath(targetFile);
          bodyResourcePaths.push(resourcePath);
        }
      }
    }
  }
  if (file.extension === "md" || file.extension === "mdx") {
    try {
      const content = await app.vault.cachedRead(file);
      const markdownImageRegex = /!\[([^\]]*)\]\((https?:\/\/[^\s)]+)/gi;
      let match;
      while ((match = markdownImageRegex.exec(content)) !== null) {
        const url = match[2].trim();
        const cleanUrl = url.replace(/["')\s]+$/, "");
        if (isExternalUrl(cleanUrl) && (hasValidImageExtension(cleanUrl) || !cleanUrl.includes("."))) {
          bodyExternalUrlCandidates.add(cleanUrl);
        }
      }
      const htmlImgRegex = /<img[^>]+src\s*=\s*["']?(https?:\/\/[^\s"'<>]+)/gi;
      while ((match = htmlImgRegex.exec(content)) !== null) {
        const url = match[1].trim();
        const cleanUrl = url.replace(/["'\s>]+$/, "");
        if (isExternalUrl(cleanUrl) && (hasValidImageExtension(cleanUrl) || !cleanUrl.includes("."))) {
          bodyExternalUrlCandidates.add(cleanUrl);
        }
      }
    } catch (error) {
      console.warn(`Failed to read file content for image extraction: ${file.path}`, error);
    }
  }
  const externalUrlArray = Array.from(bodyExternalUrlCandidates);
  const validationPromises = externalUrlArray.map(
    (url) => validateImageUrl(url).then((isValid) => isValid ? url : null)
  );
  const validatedUrls = await Promise.all(validationPromises);
  const bodyExternalUrls = validatedUrls.filter((url) => url !== null);
  return [...bodyResourcePaths, ...bodyExternalUrls];
}
function isGifUrl(url) {
  return /\.gif(\?|#|$)/i.test(url) || /\.gif$/i.test(url);
}
async function convertGifToStatic(url, forceStatic) {
  if (!forceStatic || !isGifUrl(url)) {
    return url;
  }
  return new Promise((resolve) => {
    const img = new Image();
    img.crossOrigin = "anonymous";
    img.onload = () => {
      try {
        const canvas = document.createElement("canvas");
        canvas.width = img.width;
        canvas.height = img.height;
        const ctx = canvas.getContext("2d");
        if (ctx) {
          ctx.drawImage(img, 0, 0);
          const dataUrl = canvas.toDataURL("image/png");
          resolve(dataUrl);
        } else {
          resolve(url);
        }
      } catch (error) {
        console.warn("Failed to convert GIF to static image:", error);
        resolve(url);
      }
    };
    img.onerror = () => {
      resolve(url);
    };
    setTimeout(() => {
      resolve(url);
    }, 5e3);
    img.src = url;
  });
}

// src/utils/preview.ts
var markdownPatterns = [
  /`([^`]+)`/g,
  /\*\*\*((?:(?!\*\*\*).)+)\*\*\*/g,
  /___((?:(?!___).)+)___/g,
  /\*\*((?:(?!\*\*).)+)\*\*/g,
  /__((?:(?!__).)+)__/g,
  /\*((?:(?!\*).)+)\*/g,
  /_((?:(?!_).)+)_/g,
  /~~((?:(?!~~).)+)~~/g,
  /==((?:(?!==).)+)==/g,
  /\[([^\]]+)\]\([^)]+\)/g,
  /!\[\[[^\]]+\]\]/g,
  /\[\[[^\]|]+\|[^\]]+\]\]/g,
  /\[\[[^\]]+\]\]/g,
  /#[a-zA-Z0-9_\-/]+/g,
  /^[-*+]\s*\[[ xX]\]\s+/gm,
  /^(\d+\.\s*)\[[ xX]\]\s+/gm,
  /^(\d+\)\s*)\[[ xX]\]\s+/gm,
  /^[-*+]\s+/gm,
  /^#{1,6}\s+.+$/gm,
  /^\s*(?:[-_*])\s*(?:[-_*])\s*(?:[-_*])[\s\-_*]*$/gm,
  /^\s*\|.*\|.*$/gm,
  /\^\[[^\]]*?]/g,
  /\[\^[^\]]+]/g,
  /^\s*\[\^[^\]]+]:.*$/gm,
  /<([a-z][a-z0-9]*)\b[^>]*>(.*?)<\/\1>/gi,
  /<[^>]+>/g
];
function protectEscapedChars(text) {
  const map = /* @__PURE__ */ new Map();
  let counter = 0;
  const result = text.replace(/\\(.)/g, (match, char) => {
    const placeholder = `\xA7\xA7ESCAPED${counter}\xA7\xA7`;
    map.set(placeholder, char);
    counter++;
    return placeholder;
  });
  return { text: result, map };
}
function restoreEscapedChars(text, map) {
  let result = text;
  map.forEach((char, placeholder) => {
    result = result.split(placeholder).join(char);
  });
  return result;
}
function removeCodeBlocks(text) {
  let result = text;
  let changed = true;
  while (changed) {
    changed = false;
    const openMatch = result.match(/^([`~]{3,})/m);
    if (!openMatch) break;
    const fenceChar = openMatch[1][0];
    const fenceLength = openMatch[1].length;
    const openIndex = openMatch.index;
    const escapedChar = fenceChar.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
    const closePattern = new RegExp(`^${escapedChar}{${fenceLength}}\\s*$`, "m");
    const afterOpen = result.substring(openIndex + openMatch[1].length);
    const closeMatch = afterOpen.match(closePattern);
    if (closeMatch) {
      const closeIndex = openIndex + openMatch[1].length + closeMatch.index;
      const blockEnd = closeIndex + closeMatch[0].length;
      result = result.substring(0, openIndex) + result.substring(blockEnd);
      changed = true;
    } else {
      const lineEnd = result.indexOf("\n", openIndex);
      if (lineEnd === -1) {
        result = result.substring(0, openIndex);
      } else {
        result = result.substring(0, openIndex) + result.substring(lineEnd + 1);
      }
      changed = true;
    }
  }
  return result;
}
function stripMarkdownSyntax(text) {
  if (!text || text.trim().length === 0) return "";
  text = text.replace(/^>\s*\[![\w-]+\][+-]?.*$/gm, "");
  text = text.replace(/^>\s?/gm, "");
  const { text: protectedText, map: escapedCharsMap } = protectEscapedChars(text);
  let result = removeCodeBlocks(protectedText);
  markdownPatterns.forEach((pattern) => {
    result = result.replace(pattern, (match, ...groups) => {
      if (match.match(/<[a-z][a-z0-9]*\b[^>]*>.*?<\//i)) {
        return groups[1] || "";
      }
      if (groups.length > 0 && groups[0] !== void 0) {
        for (let i = 0; i < groups.length - 2; i++) {
          if (typeof groups[i] === "string") {
            return groups[i];
          }
        }
      }
      return "";
    });
  });
  result = restoreEscapedChars(result, escapedCharsMap);
  return result;
}
function sanitizeForPreview(content, omitFirstLine = false, filename, titleValue) {
  const cleaned = content.replace(/^---[\s\S]*?---/, "").trim();
  let stripped = stripMarkdownSyntax(cleaned);
  const firstLineEnd = stripped.indexOf("\n");
  const firstLine = (firstLineEnd !== -1 ? stripped.substring(0, firstLineEnd) : stripped).trim();
  if (omitFirstLine || filename && firstLine === filename || titleValue && firstLine === titleValue) {
    stripped = firstLineEnd !== -1 ? stripped.substring(firstLineEnd + 1).trim() : "";
  }
  const normalized = stripped.replace(/\^[a-zA-Z0-9-]+/g, "").split(/\s+/).filter((word) => word).join(" ").trim().replace(/\.{2,}/g, (match) => match.replace(/\./g, "\u2024"));
  const wasTruncated = normalized.length > 500;
  let preview = normalized.substring(0, 500);
  if (wasTruncated) {
    preview += "\u2026";
  }
  return preview;
}
async function loadFilePreview(file, app, propertyValue, settings, fileName, titleValue) {
  let result = null;
  if (propertyValue != null) {
    if (Array.isArray(propertyValue)) {
      const items = propertyValue.map((item) => {
        if (item && typeof item === "object" && "data" in item) {
          return String(item.data);
        }
        return String(item);
      }).filter((s) => s.trim().length > 0);
      result = items.length > 0 ? items.join(", ") : null;
    } else if (typeof propertyValue === "string" || typeof propertyValue === "number") {
      const str = String(propertyValue).trim();
      result = str.length > 0 ? str : null;
    }
  }
  if (result) {
    if (settings.truncatePreviewProperty) {
      const wasTruncated = result.length > 500;
      result = result.substring(0, 500);
      if (wasTruncated) {
        result += "\u2026";
      }
    }
    return result;
  }
  if (settings.fallbackToContent) {
    const content = await app.vault.cachedRead(file);
    return sanitizeForPreview(
      content,
      settings.omitFirstLine,
      fileName,
      titleValue
    );
  }
  return "";
}

// src/shared/content-loader.ts
async function loadImageForEntry(path, file, app, imagePropertyValues, fallbackToEmbeds, imageCache, hasImageCache) {
  const hasPropertyValues = imagePropertyValues && Array.isArray(imagePropertyValues) && imagePropertyValues.length > 0;
  const shouldFallback = fallbackToEmbeds === true || fallbackToEmbeds === "always" || fallbackToEmbeds === "if-empty" && !hasPropertyValues;
  if (!shouldFallback && path in imageCache) {
    delete imageCache[path];
    delete hasImageCache[path];
  }
  if (path in imageCache && !hasPropertyValues && shouldFallback) {
    return;
  }
  try {
    const { internalPaths, externalUrls } = await processImagePaths(imagePropertyValues);
    let validImages = [
      ...resolveInternalImagePaths(internalPaths, path, app),
      ...externalUrls
      // External URLs already validated by processImagePaths
    ];
    if (validImages.length === 0 && !hasPropertyValues && shouldFallback) {
      validImages = await extractEmbedImages(file, app);
    }
    if (validImages.length > 0) {
      imageCache[path] = validImages.length > 1 ? validImages : validImages[0];
      hasImageCache[path] = true;
    } else if (hasPropertyValues) {
      delete imageCache[path];
      hasImageCache[path] = true;
    } else if (!shouldFallback) {
      delete imageCache[path];
      delete hasImageCache[path];
    }
  } catch (error) {
    console.error(`Failed to load image for ${path}:`, error);
  }
}
async function loadImagesForEntries(entries, fallbackToEmbeds, app, imageCache, hasImageCache) {
  const entriesToProcess = entries.filter((entry) => {
    const hasPropertyValues = entry.imagePropertyValues && Array.isArray(entry.imagePropertyValues) && entry.imagePropertyValues.length > 0;
    return !(entry.path in imageCache) || hasPropertyValues;
  });
  const BATCH_SIZE = 50;
  for (let i = 0; i < entriesToProcess.length; i += BATCH_SIZE) {
    const batch = entriesToProcess.slice(i, i + BATCH_SIZE);
    await Promise.all(
      batch.map(async (entry) => {
        await loadImageForEntry(
          entry.path,
          entry.file,
          app,
          entry.imagePropertyValues,
          fallbackToEmbeds,
          imageCache,
          hasImageCache
        );
      })
    );
  }
}
async function loadSnippetsForEntries(entries, fallbackToContent, omitFirstLine, app, snippetCache, truncatePreviewProperty) {
  await Promise.all(
    entries.map(async (entry) => {
      if (entry.path in snippetCache) {
        return;
      }
      try {
        if (entry.file.extension === "md" || entry.file.extension === "mdx") {
          snippetCache[entry.path] = await loadFilePreview(
            entry.file,
            app,
            entry.descriptionData,
            {
              fallbackToContent,
              omitFirstLine,
              truncatePreviewProperty
            },
            entry.fileName,
            entry.titleString
          );
        } else {
          snippetCache[entry.path] = "";
        }
      } catch (error) {
        console.error(`Failed to load snippet for ${entry.path}:`, error);
        snippetCache[entry.path] = "";
      }
    })
  );
}

// src/views/shared-renderer.ts
var import_obsidian12 = require("obsidian");

// src/utils/draft-status-badge.ts
var import_obsidian9 = require("obsidian");
init_frontmatter_helper();
async function calculateDraftStatusAsync(entry, settings, app, mdxFrontmatterCache) {
  var _a;
  let booleanValue = null;
  let isDraft = false;
  if (settings.draftStatusUseFilenamePrefix && entry.file && entry.file.name) {
    const fileName = entry.file.name;
    const startsWithUnderscore = fileName.startsWith("_");
    booleanValue = startsWithUnderscore;
    isDraft = settings.draftStatusReverse ? !booleanValue : booleanValue;
  } else if (settings.draftStatusProperty) {
    const draftValue = entry.getValue(settings.draftStatusProperty);
    if (draftValue && "data" in draftValue && typeof draftValue.data === "boolean") {
      booleanValue = draftValue.data;
      isDraft = settings.draftStatusReverse ? !booleanValue : booleanValue;
    } else {
      const file = app.vault.getAbstractFileByPath(entry.file.path);
      if (file instanceof import_obsidian9.TFile && file.extension === "mdx") {
        let frontmatter = null;
        if (mdxFrontmatterCache) {
          frontmatter = (_a = mdxFrontmatterCache[entry.file.path]) != null ? _a : null;
        }
        if (frontmatter === void 0) {
          frontmatter = await getFileFrontmatter(app, file);
        }
        if (frontmatter) {
          const cleanProp = settings.draftStatusProperty.startsWith("note.") ? settings.draftStatusProperty.substring(5) : settings.draftStatusProperty;
          const frontmatterValue = frontmatter[cleanProp];
          if (typeof frontmatterValue === "boolean") {
            booleanValue = frontmatterValue;
            isDraft = settings.draftStatusReverse ? !booleanValue : booleanValue;
          }
        }
      }
    }
  }
  return { booleanValue, isDraft };
}
function calculateDraftStatus(entry, settings) {
  let booleanValue = null;
  let isDraft = false;
  if (settings.draftStatusUseFilenamePrefix && entry.file && entry.file.name) {
    const fileName = entry.file.name;
    const startsWithUnderscore = fileName.startsWith("_");
    booleanValue = startsWithUnderscore;
    isDraft = settings.draftStatusReverse ? !booleanValue : booleanValue;
  } else if (settings.draftStatusProperty) {
    const draftValue = entry.getValue(settings.draftStatusProperty);
    if (draftValue && "data" in draftValue && typeof draftValue.data === "boolean") {
      booleanValue = draftValue.data;
      isDraft = settings.draftStatusReverse ? !booleanValue : booleanValue;
    }
  }
  return { booleanValue, isDraft };
}
function renderDraftStatusBadge(container, entry, cardPath, settings, onPropertyToggle, app, mdxFrontmatterCache) {
  if (!settings.showDraftStatus) {
    return;
  }
  const { booleanValue: syncValue, isDraft: syncIsDraft } = calculateDraftStatus(entry, settings);
  if (syncValue !== null) {
    renderBadge(container, syncValue, syncIsDraft, onPropertyToggle, cardPath);
  } else if (app) {
    const file = app.vault.getAbstractFileByPath(entry.file.path);
    if (file instanceof import_obsidian9.TFile && file.extension === "mdx" && mdxFrontmatterCache) {
      const frontmatter = mdxFrontmatterCache[entry.file.path];
      if (frontmatter && settings.draftStatusProperty) {
        const cleanProp = settings.draftStatusProperty.startsWith("note.") ? settings.draftStatusProperty.substring(5) : settings.draftStatusProperty;
        const frontmatterValue = frontmatter[cleanProp];
        if (typeof frontmatterValue === "boolean") {
          const booleanValue = frontmatterValue;
          const isDraft = settings.draftStatusReverse ? !booleanValue : booleanValue;
          renderBadge(container, booleanValue, isDraft, onPropertyToggle, cardPath);
          return;
        }
      }
    }
    void (async () => {
      const { booleanValue, isDraft } = await calculateDraftStatusAsync(entry, settings, app, mdxFrontmatterCache);
      if (booleanValue !== null && container.isConnected) {
        renderBadge(container, booleanValue, isDraft, onPropertyToggle, cardPath);
      }
    })();
  }
}
function renderBadge(container, booleanValue, isDraft, onPropertyToggle, cardPath) {
  if (container.querySelector(".card-status-badge")) {
    return;
  }
  const statusBadge = container.createDiv("card-status-badge");
  if (isDraft) {
    statusBadge.addClass("status-draft");
    statusBadge.appendText("Draft");
  } else {
    statusBadge.addClass("status-published");
    statusBadge.appendText("Published");
  }
  if (onPropertyToggle) {
    statusBadge.addClass("bases-cms-cursor-pointer");
    statusBadge.addEventListener("click", (e) => {
      e.stopPropagation();
      const newValue = !booleanValue;
      void onPropertyToggle(cardPath, "draft", newValue);
    });
  }
}

// src/utils/quick-edit-icon.ts
var import_obsidian10 = require("obsidian");
function showRenameDialog(app, file) {
  const modal = new import_obsidian10.Modal(app);
  modal.titleEl.setText("Rename file");
  const inputContainer = modal.contentEl.createDiv();
  setCssProps(inputContainer, {
    width: "100%"
  });
  const input = new import_obsidian10.TextComponent(inputContainer);
  input.setValue(file.basename);
  setCssProps(input.inputEl, {
    width: "100%",
    boxSizing: "border-box"
  });
  input.inputEl.focus();
  input.inputEl.select();
  const buttonContainer = modal.contentEl.createDiv({ cls: "modal-button-container" });
  const cancelButton = buttonContainer.createEl("button", { text: "Cancel" });
  cancelButton.addEventListener("click", () => modal.close());
  const renameButton = buttonContainer.createEl("button", {
    text: "Rename",
    cls: "mod-cta"
  });
  const handleRename = async () => {
    const newName = input.getValue().trim();
    if (!newName || newName === file.basename) {
      modal.close();
      return;
    }
    const pathParts = file.path.split("/");
    pathParts[pathParts.length - 1] = newName + (file.extension ? `.${file.extension}` : "");
    const newPath = pathParts.join("/");
    try {
      await app.fileManager.renameFile(file, newPath);
      modal.close();
    } catch (error) {
      console.error("[Bases CMS] Error renaming file:", error);
      modal.close();
    }
  };
  renameButton.addEventListener("click", () => {
    void handleRename();
  });
  input.inputEl.addEventListener("keydown", (e) => {
    if (e.key === "Enter") {
      e.preventDefault();
      void handleRename();
    } else if (e.key === "Escape") {
      e.preventDefault();
      modal.close();
    }
  });
  modal.open();
}
function isObsidianRenameCommand(commandId) {
  const lowerId = commandId.toLowerCase();
  return commandId === "file-explorer:rename-file" || commandId === "rename-file" || commandId === "file:rename-file" || lowerId.includes("rename") && lowerId.includes("file") && !lowerId.includes(":");
}
function isProblematicCommand(commandId, commandName) {
  const lowerId = commandId.toLowerCase();
  const lowerName = commandName.toLowerCase();
  const problematicPatterns = [
    "add tag",
    "add-tag",
    "insert-template",
    "insert-template",
    "editor:",
    "markdown:"
  ];
  return problematicPatterns.some(
    (pattern) => lowerId.includes(pattern) || lowerName.includes(pattern)
  );
}
function setupQuickEditIcon(app, plugin, titleEl, cardEl, cardPath, settings) {
  if (!plugin.settings.enableQuickEdit || !plugin.settings.quickEditCommand || plugin.settings.quickEditCommand === "" || settings.hideQuickEditIcon) {
    return;
  }
  const quickEditIcon = titleEl.createSpan("bases-cms-quick-edit-icon");
  quickEditIcon.addClass("bases-cms-cursor-default");
  (0, import_obsidian10.setIcon)(quickEditIcon, plugin.settings.quickEditIcon || "pencil-line");
  titleEl.addEventListener("click", (e) => {
    if (quickEditIcon.contains(e.target)) {
      e.stopPropagation();
      e.stopImmediatePropagation();
    }
  }, true);
  cardEl.addEventListener("click", (e) => {
    void (async () => {
      var _a, _b, _c, _d;
      const target = e.target;
      if (!quickEditIcon.contains(target) && !target.closest(".bases-cms-quick-edit-icon")) {
        return;
      }
      e.stopPropagation();
      e.stopImmediatePropagation();
      e.preventDefault();
      const file = app.vault.getAbstractFileByPath(cardPath);
      if (file instanceof import_obsidian10.TFile) {
        const commandId = plugin.settings.quickEditCommand;
        const commandRegistry = app.commands;
        const command = (_a = commandRegistry == null ? void 0 : commandRegistry.commands) == null ? void 0 : _a[commandId];
        const commandName = (command == null ? void 0 : command.name) || "";
        const lowerCommandName = commandName.toLowerCase();
        if (isObsidianRenameCommand(commandId) || lowerCommandName.includes("rename") && lowerCommandName.includes("file")) {
          showRenameDialog(app, file);
          return;
        }
        if (isProblematicCommand(commandId, commandName)) {
          if (plugin.settings.quickEditOpenFile) {
          } else {
            new import_obsidian10.Notice(`The "${commandName}" command requires the file to be open in an editor. Enable "Attempt to open file and execute quick edit command" in settings to try anyway.`, 5e3);
            return;
          }
        }
        let helperCalled = false;
        try {
          let pluginId = null;
          let baseCommandId = commandId;
          if (commandId.includes(":")) {
            const parts = commandId.split(":");
            pluginId = parts[0];
            baseCommandId = parts.slice(1).join(":");
          } else {
            const appWithCommands = app;
            const commandRegistry2 = appWithCommands.commands;
            const command2 = (_b = commandRegistry2 == null ? void 0 : commandRegistry2.commands) == null ? void 0 : _b[commandId];
            if (command2) {
              const sourcePlugin = command2.plugin || command2.sourcePlugin;
              if (sourcePlugin) {
                pluginId = ((_c = sourcePlugin.manifest) == null ? void 0 : _c.id) || sourcePlugin.pluginId || null;
              }
            }
          }
          if (pluginId) {
            const plugins = app.plugins;
            const sourcePlugin = (_d = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _d[pluginId];
            if (sourcePlugin) {
              const methodName = baseCommandId.split("-").map(
                (part, index) => index === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1)
              ).join("") + "ByPath";
              if (sourcePlugin && typeof sourcePlugin[methodName] === "function") {
                await sourcePlugin[methodName](cardPath);
                helperCalled = true;
                return;
              }
            }
          }
        } catch (e2) {
        }
        if (!helperCalled) {
          if (!plugin.settings.quickEditOpenFile) {
            new import_obsidian10.Notice(`This command doesn't have special handling. Enable "Attempt to open file and execute quick edit command" in settings to try executing it.`, 5e3);
            return;
          }
          const leaf = app.workspace.getLeaf(false);
          await leaf.openFile(file);
          app.workspace.setActiveLeaf(leaf, { focus: true });
          let attempts = 0;
          const maxAttempts = 30;
          const executeCommand = () => {
            const finalActiveFile = app.workspace.getActiveFile();
            if (finalActiveFile === file) {
              void (async () => {
                var _a2, _b2;
                try {
                  await ((_b2 = (_a2 = app.commands) == null ? void 0 : _a2.executeCommandById) == null ? void 0 : _b2.call(_a2, plugin.settings.quickEditCommand));
                } catch (e2) {
                }
              })();
            }
          };
          const checkEditorReady = () => {
            const view = leaf.view;
            const viewWithEditor = view;
            const activeFile = app.workspace.getActiveFile();
            if (view && "editor" in view && viewWithEditor.editor && activeFile === file) {
              requestAnimationFrame(() => {
                requestAnimationFrame(() => {
                  setTimeout(() => {
                    executeCommand();
                  }, 200);
                });
              });
            } else if (attempts < maxAttempts) {
              attempts++;
              setTimeout(checkEditorReady, 50);
            }
          };
          checkEditorReady();
        }
      }
    })();
  }, true);
  quickEditIcon.addEventListener("mousedown", (e) => {
    e.stopPropagation();
    e.stopImmediatePropagation();
    e.preventDefault();
  }, true);
}

// src/utils/property-renderer.ts
var import_obsidian11 = require("obsidian");
var PropertyRenderer = class {
  constructor(app, getBasesConfig, getBasesController) {
    this.app = app;
    this.getBasesConfig = getBasesConfig;
    this.getBasesController = getBasesController;
  }
  /**
   * Renders property fields for a card
   * @param position - 'top' to render only top-positioned groups, 'bottom' to render only bottom-positioned groups, undefined to render all
   */
  renderProperties(cardEl, card, entry, settings, onPropertyToggle, position) {
    const props = [
      settings.propertyDisplay1,
      settings.propertyDisplay2,
      settings.propertyDisplay3,
      settings.propertyDisplay4,
      settings.propertyDisplay5,
      settings.propertyDisplay6,
      settings.propertyDisplay7,
      settings.propertyDisplay8,
      settings.propertyDisplay9,
      settings.propertyDisplay10,
      settings.propertyDisplay11,
      settings.propertyDisplay12,
      settings.propertyDisplay13,
      settings.propertyDisplay14
    ];
    const seen = /* @__PURE__ */ new Set();
    const effectiveProps = props.map((prop) => {
      if (!prop || prop === "") return "";
      if (seen.has(prop)) return "";
      seen.add(prop);
      return prop;
    });
    const values = effectiveProps.map((prop, index) => {
      if (!prop) return null;
      const cardProperty = `property${index + 1}`;
      const cardValue = card[cardProperty];
      if (cardValue !== void 0 && cardValue !== null) {
        return cardValue;
      }
      try {
        const value = entry.getValue(prop);
        if (!value) return null;
        if ("date" in value && value.date instanceof Date) {
          return value.date.toLocaleDateString();
        }
        if ("data" in value && value.data != null) {
          const data = value.data;
          if (Array.isArray(data)) {
            return data.map((item) => {
              if (item && typeof item === "object" && item !== null && !Array.isArray(item)) {
                return JSON.stringify(item);
              }
              return String(item);
            }).join(", ");
          }
          if (data && typeof data === "object" && data !== null && !Array.isArray(data)) {
            return JSON.stringify(data);
          }
          if (typeof data === "string" || typeof data === "number" || typeof data === "boolean") {
            return String(data);
          }
          return data ? JSON.stringify(data) : "";
        }
      } catch (e) {
      }
      return null;
    });
    const propertyGroups = [
      {
        props: [effectiveProps[0], effectiveProps[1]],
        values: [values[0], values[1]],
        sideBySide: settings.propertyLayout12SideBySide,
        position: settings.propertyGroup1Position
      },
      {
        props: [effectiveProps[2], effectiveProps[3]],
        values: [values[2], values[3]],
        sideBySide: settings.propertyLayout34SideBySide,
        position: settings.propertyGroup2Position
      },
      {
        props: [effectiveProps[4], effectiveProps[5]],
        values: [values[4], values[5]],
        sideBySide: settings.propertyLayout56SideBySide,
        position: settings.propertyGroup3Position
      },
      {
        props: [effectiveProps[6], effectiveProps[7]],
        values: [values[6], values[7]],
        sideBySide: settings.propertyLayout78SideBySide,
        position: settings.propertyGroup4Position
      },
      {
        props: [effectiveProps[8], effectiveProps[9]],
        values: [values[8], values[9]],
        sideBySide: settings.propertyLayout910SideBySide,
        position: settings.propertyGroup5Position
      },
      {
        props: [effectiveProps[10], effectiveProps[11]],
        values: [values[10], values[11]],
        sideBySide: settings.propertyLayout1112SideBySide,
        position: settings.propertyGroup6Position
      },
      {
        props: [effectiveProps[12], effectiveProps[13]],
        values: [values[12], values[13]],
        sideBySide: settings.propertyLayout1314SideBySide,
        position: settings.propertyGroup7Position
      }
    ];
    const topGroups = [];
    const bottomGroups = [];
    propertyGroups.forEach((group, index) => {
      const hasContent = group.props[0] !== "" || group.props[1] !== "";
      if (hasContent) {
        if (group.position === "top") {
          topGroups.push(group);
        } else {
          bottomGroups.push(group);
        }
      }
    });
    const shouldHideProperty = (propName, propValue) => {
      var _a, _b, _c;
      if (!propName || propName === "") return true;
      const isEmptyValue = propValue === null || propValue === "" || typeof propValue === "string" && propValue.trim() === "";
      let propertyExists = false;
      try {
        const filePath = (_a = entry == null ? void 0 : entry.file) == null ? void 0 : _a.path;
        if (filePath && ((_b = this.app) == null ? void 0 : _b.vault) && ((_c = this.app) == null ? void 0 : _c.metadataCache)) {
          const file = this.app.vault.getAbstractFileByPath(filePath);
          if (file instanceof import_obsidian11.TFile) {
            if (file.extension === "mdx") {
              propertyExists = !isEmptyValue;
            } else {
              const metadata = this.app.metadataCache.getFileCache(file);
              if (metadata && metadata.frontmatter) {
                const propertyNames = propName.split(",").map((p) => p.trim()).filter((p) => p);
                for (const prop of propertyNames) {
                  const propKey = prop.replace(/^(note|formula|file)\./, "");
                  if (propKey in metadata.frontmatter) {
                    propertyExists = true;
                    break;
                  }
                }
              }
            }
          }
        }
      } catch (e) {
      }
      if (shouldHideMissingProperties() && !propertyExists) {
        return true;
      }
      if (shouldHideEmptyProperties() && propertyExists && isEmptyValue) {
        return true;
      }
      if (shouldHideEmptyProperties() && isEmptyValue) {
        return true;
      }
      return false;
    };
    if ((position === "top" || position === void 0) && topGroups.length > 0) {
      const topMetaEl = cardEl.createDiv("card-properties properties-top");
      topGroups.forEach((group, groupIndex) => {
        const prop1ShouldRender = group.props[0] && !shouldHideProperty(group.props[0], group.values[0]);
        const prop2ShouldRender = group.props[1] && !shouldHideProperty(group.props[1], group.values[1]);
        if (!prop1ShouldRender && !prop2ShouldRender) {
          return;
        }
        const rowEl = topMetaEl.createDiv(`property-row property-row-group-${groupIndex + 1}`);
        if (group.sideBySide) {
          rowEl.addClass("property-row-side-by-side");
        }
        const field1El = rowEl.createDiv("property-field property-field-1");
        if (prop1ShouldRender) {
          this.renderPropertyContent(field1El, group.props[0], group.values[0], card, entry, settings, onPropertyToggle);
        }
        const field2El = rowEl.createDiv("property-field property-field-2");
        if (prop2ShouldRender) {
          this.renderPropertyContent(field2El, group.props[1], group.values[1], card, entry, settings, onPropertyToggle);
        }
      });
    }
    if ((position === "bottom" || position === void 0) && bottomGroups.length > 0) {
      const bottomMetaEl = cardEl.createDiv("card-properties properties-bottom");
      bottomGroups.forEach((group, groupIndex) => {
        const prop1ShouldRender = group.props[0] && !shouldHideProperty(group.props[0], group.values[0]);
        const prop2ShouldRender = group.props[1] && !shouldHideProperty(group.props[1], group.values[1]);
        if (!prop1ShouldRender && !prop2ShouldRender) {
          return;
        }
        const rowEl = bottomMetaEl.createDiv(`property-row property-row-group-${groupIndex + 1}`);
        if (group.sideBySide) {
          rowEl.addClass("property-row-side-by-side");
        }
        const field1El = rowEl.createDiv("property-field property-field-1");
        if (prop1ShouldRender) {
          this.renderPropertyContent(field1El, group.props[0], group.values[0], card, entry, settings, onPropertyToggle);
        }
        const field2El = rowEl.createDiv("property-field property-field-2");
        if (prop2ShouldRender) {
          this.renderPropertyContent(field2El, group.props[1], group.values[1], card, entry, settings, onPropertyToggle);
        }
      });
    }
  }
  /**
   * Renders individual property content
   */
  renderPropertyContent(container, propertyName, resolvedValue, card, entry, settings, onPropertyToggle) {
    if (propertyName === "") return;
    if (resolvedValue === null && shouldHideMissingProperties()) {
      return;
    }
    if (resolvedValue === "" && shouldHideEmptyProperties()) {
      return;
    }
    if (!resolvedValue && settings.propertyLabels === "hide") {
      return;
    }
    if (settings.propertyLabels === "hide") {
      if ((propertyName === "tags" || propertyName === "note.tags") && card.yamlTags.length === 0) {
        return;
      }
      if ((propertyName === "file.tags" || propertyName === "file tags") && card.tags.length === 0) {
        return;
      }
    }
    const basesConfig = this.getBasesConfig ? this.getBasesConfig() : void 0;
    const basesController = this.getBasesController ? this.getBasesController() : void 0;
    const propertyLabel = getPropertyLabel(propertyName, this.app, basesConfig, basesController);
    const isCustomLabel = propertyLabel.toLowerCase() !== propertyName.toLowerCase();
    if (settings.propertyLabels === "above") {
      const labelEl = container.createDiv("property-label");
      if (isCustomLabel) {
        labelEl.addClass("property-label-custom");
      }
      labelEl.textContent = propertyLabel;
    }
    const metaContent = container.createDiv("property-content");
    if (settings.propertyLabels === "inline") {
      metaContent.addClass("property-content-inline");
    }
    if (settings.propertyLabels === "inline") {
      const labelSpan = metaContent.createSpan("property-label-inline");
      labelSpan.textContent = propertyLabel + ": ";
    }
    if (!resolvedValue) {
      const emptyMarker = metaContent.createSpan("property-empty-marker");
      emptyMarker.textContent = getEmptyValueMarker();
      return;
    }
    const isKnownTimestampProperty = propertyName === "file.mtime" || propertyName === "file.ctime" || propertyName === "modified time" || propertyName === "created time";
    if (isKnownTimestampProperty) {
      const timestampWrapper = metaContent.createSpan();
      timestampWrapper.appendText(resolvedValue);
    } else if ((propertyName === "tags" || propertyName === "note.tags") && card.yamlTags.length > 0) {
      const tagsWrapper = metaContent.createDiv("tags-wrapper");
      const tagStyle = getTagStyle();
      if (tagStyle !== "plain") {
        tagsWrapper.addClass(`tag-style-${tagStyle}`);
      }
      card.yamlTags.forEach((tag) => {
        const tagEl = tagsWrapper.createEl("a", {
          cls: "tag",
          text: showTagHashPrefix() ? `#${tag}` : tag,
          href: "#"
        });
        tagEl.addEventListener("click", (e) => {
          var _a, _b, _c;
          e.preventDefault();
          const searchPlugin = (_b = (_a = this.app.internalPlugins) == null ? void 0 : _a.plugins) == null ? void 0 : _b["global-search"];
          if ((_c = searchPlugin == null ? void 0 : searchPlugin.instance) == null ? void 0 : _c.openGlobalSearch) {
            searchPlugin.instance.openGlobalSearch("tag:" + tag);
          }
        });
      });
    } else if ((propertyName === "file.tags" || propertyName === "file tags") && card.tags.length > 0) {
      const tagsWrapper = metaContent.createDiv("tags-wrapper");
      const tagStyle = getTagStyle();
      if (tagStyle !== "plain") {
        tagsWrapper.addClass(`tag-style-${tagStyle}`);
      }
      card.tags.forEach((tag) => {
        const tagEl = tagsWrapper.createEl("a", {
          cls: "tag",
          text: showTagHashPrefix() ? `#${tag}` : tag,
          href: "#"
        });
        tagEl.addEventListener("click", (e) => {
          var _a, _b, _c;
          e.preventDefault();
          const searchPlugin = (_b = (_a = this.app.internalPlugins) == null ? void 0 : _a.plugins) == null ? void 0 : _b["global-search"];
          if ((_c = searchPlugin == null ? void 0 : searchPlugin.instance) == null ? void 0 : _c.openGlobalSearch) {
            searchPlugin.instance.openGlobalSearch("tag:" + tag);
          }
        });
      });
    } else {
      if (!this.app || !this.app.metadataCache) {
        const textWrapper = metaContent.createDiv("text-wrapper");
        this.renderPropertyValueWithLinks(textWrapper, resolvedValue, card.path, propertyName);
        return;
      }
      let propInfo = void 0;
      try {
        const metadataCache = this.app.metadataCache;
        const getAllPropertyInfos = metadataCache.getAllPropertyInfos;
        if (typeof getAllPropertyInfos === "function") {
          const propertyInfos = getAllPropertyInfos();
          propInfo = propertyInfos[propertyName.toLowerCase()];
        }
      } catch (e) {
      }
      let entryValue = null;
      try {
        if (entry && typeof entry.getValue === "function") {
          entryValue = entry.getValue(propertyName);
        }
      } catch (e) {
      }
      const isCheckbox = (propInfo == null ? void 0 : propInfo.widget) === "checkbox" || entryValue && "data" in entryValue && typeof entryValue.data === "boolean";
      if (isCheckbox && onPropertyToggle) {
        const checkbox = metaContent.createEl("input", { type: "checkbox" });
        checkbox.checked = entryValue && "data" in entryValue ? Boolean(entryValue.data) : false;
        metaContent.createSpan({ text: propertyLabel });
        checkbox.addEventListener("change", (e) => {
          e.stopPropagation();
          const checked = checkbox.checked;
          void (async () => {
            try {
              const cleanProperty = propertyName.startsWith("note.") ? propertyName.substring(5) : propertyName;
              await onPropertyToggle(card.path, cleanProperty, checked);
            } catch (e2) {
              checkbox.checked = !checked;
            }
          })();
        });
        checkbox.addEventListener("click", (e) => {
          e.stopPropagation();
        });
      } else {
        const textWrapper = metaContent.createDiv("text-wrapper");
        this.renderPropertyValueWithLinks(textWrapper, resolvedValue, card.path, propertyName);
      }
    }
    if (!metaContent.textContent || metaContent.textContent.trim().length === 0) {
      metaContent.remove();
    }
  }
  /**
   * Renders property value with clickable links
   * Detects wikilinks [[...]], markdown links [...](...), and URLs
   * For image properties, also makes file paths clickable (like Obsidian does)
   */
  renderPropertyValueWithLinks(container, value, sourcePath, propertyName) {
    if (!value) {
      container.appendText(getEmptyValueMarker());
      return;
    }
    const trimmedValue = value.trim();
    if ((trimmedValue.startsWith("http://") || trimmedValue.startsWith("https://")) && !trimmedValue.includes(" ")) {
      const linkEl = container.createEl("a", {
        cls: "external-link",
        href: trimmedValue
      });
      linkEl.textContent = trimmedValue;
      linkEl.setAttr("target", "_blank");
      linkEl.setAttr("rel", "noopener");
      linkEl.addEventListener("click", (e) => {
        e.stopPropagation();
      });
      return;
    }
    const isImageProperty = propertyName && (propertyName.toLowerCase().includes("image") || propertyName.toLowerCase() === "cover" || propertyName.toLowerCase() === "thumbnail");
    if (isImageProperty && !trimmedValue.includes(" ") && !trimmedValue.startsWith("http://") && !trimmedValue.startsWith("https://") && (trimmedValue.includes("/") || trimmedValue.includes("\\") || trimmedValue.match(/\.(png|jpg|jpeg|gif|svg|webp|mp4|mov|avi)$/i))) {
      const linkEl = container.createEl("a", {
        cls: "internal-link",
        href: trimmedValue
      });
      linkEl.textContent = trimmedValue;
      linkEl.addEventListener("click", (e) => {
        e.stopPropagation();
        e.preventDefault();
        const newLeaf = e.metaKey || e.ctrlKey;
        void this.app.workspace.openLinkText(trimmedValue, sourcePath, newLeaf);
      });
      return;
    }
    const wikilinkRegex = /\[\[([^\]]+)\]\]/g;
    const markdownLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
    const matches = [];
    for (const m of value.matchAll(wikilinkRegex)) {
      if (m.index !== void 0) {
        matches.push({ index: m.index, type: "wikilink", match: m });
      }
    }
    for (const m of value.matchAll(markdownLinkRegex)) {
      if (m.index !== void 0) {
        matches.push({ index: m.index, type: "markdown", match: m });
      }
    }
    matches.sort((a, b) => a.index - b.index);
    let lastIndex = 0;
    for (const { index, type, match } of matches) {
      if (index > lastIndex) {
        container.appendText(value.substring(lastIndex, index));
      }
      if (type === "wikilink") {
        const linkContent = match[1];
        const parts = linkContent.split("|");
        const linkPath = parts[0].trim();
        const displayText = parts.length > 1 ? parts[1].trim() : linkPath;
        const linkEl = container.createEl("a", {
          cls: "internal-link",
          href: linkPath
        });
        linkEl.textContent = displayText;
        linkEl.addEventListener("click", (e) => {
          e.stopPropagation();
          e.preventDefault();
          const newLeaf = e.metaKey || e.ctrlKey;
          void this.app.workspace.openLinkText(linkPath, sourcePath, newLeaf);
        });
      } else if (type === "markdown") {
        const linkText = match[1];
        const linkUrl = match[2];
        if (linkUrl.startsWith("http://") || linkUrl.startsWith("https://")) {
          const linkEl = container.createEl("a", {
            cls: "external-link",
            href: linkUrl
          });
          linkEl.textContent = linkText;
          linkEl.setAttr("target", "_blank");
          linkEl.setAttr("rel", "noopener");
          linkEl.addEventListener("click", (e) => {
            e.stopPropagation();
          });
        } else {
          const linkEl = container.createEl("a", {
            cls: "internal-link",
            href: linkUrl
          });
          linkEl.textContent = linkText;
          linkEl.addEventListener("click", (e) => {
            e.stopPropagation();
            e.preventDefault();
            const newLeaf = e.metaKey || e.ctrlKey;
            void this.app.workspace.openLinkText(linkUrl, sourcePath, newLeaf);
          });
        }
      }
      lastIndex = index + match[0].length;
    }
    if (lastIndex < value.length) {
      container.appendText(value.substring(lastIndex));
    } else if (matches.length === 0) {
      container.appendText(value);
    }
  }
};

// src/views/shared-renderer.ts
init_frontmatter_helper();
var SharedCardRenderer = class {
  constructor(app, plugin, propertyObservers, updateLayoutRef, basesConfig, basesController) {
    this.app = app;
    this.plugin = plugin;
    this.propertyObservers = propertyObservers;
    this.updateLayoutRef = updateLayoutRef;
    this.basesConfig = basesConfig;
    this.basesController = basesController;
    this.propertyRenderer = new PropertyRenderer(
      this.app,
      () => this.basesConfig,
      // Pass a getter function so it always gets the latest config
      () => this.basesController
      // Pass a getter function so it always gets the latest controller
    );
  }
  /**
   * Set MDX frontmatter cache for synchronous access during rendering
   */
  setMdxFrontmatterCache(cache) {
    this.mdxFrontmatterCache = cache;
  }
  /**
   * Renders a complete card with CMS features
   */
  renderCard(container, card, entry, settings, hoverParent, isSelected, onSelect, onPropertyToggle, toolbarActions) {
    const cardEl = container.createDiv("card bases-cms-card");
    setCssProps(cardEl, {
      display: "block",
      position: "relative"
    });
    if (settings.imageFormat === "cover") {
      cardEl.classList.add("image-format-cover");
    } else if (settings.imageFormat === "thumbnail") {
      cardEl.classList.add("image-format-thumbnail");
      cardEl.classList.add(`thumbnail-${settings.imagePosition}`);
    }
    cardEl.setAttribute("data-path", card.path);
    cardEl.setAttribute("data-href", card.path);
    cardEl.addClass("bases-cms-cursor-pointer");
    const checkboxEl = cardEl.createDiv("bases-cms-select-checkbox");
    const checkbox = checkboxEl.createEl("input", { type: "checkbox", cls: "selection-checkbox" });
    checkbox.checked = isSelected;
    checkboxEl.addEventListener("click", (e) => {
      e.stopPropagation();
      e.stopImmediatePropagation();
      if (e.target !== checkbox) {
        checkbox.checked = !checkbox.checked;
      }
      onSelect(card.path, checkbox.checked, e.shiftKey);
    });
    if (settings.showDraftStatus) {
      renderDraftStatusBadge(cardEl, entry, card.path, settings, onPropertyToggle, this.app, this.mdxFrontmatterCache);
    }
    cardEl.addEventListener("click", (e) => {
      const target = e.target;
      const quickEditIcon = target.closest(".bases-cms-quick-edit-icon");
      if (quickEditIcon) {
        e.stopPropagation();
        e.stopImmediatePropagation();
        e.preventDefault();
        return;
      }
      if (checkboxEl.contains(target) || target.tagName === "INPUT" || target.closest("input") || target.closest(".bases-cms-property") || target.closest(".card-status-badge")) {
        return;
      }
      if (e.shiftKey) {
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
        const newSelectedState = !checkbox.checked;
        onSelect(card.path, newSelectedState, true);
        return;
      }
      const newLeaf = e.metaKey || e.ctrlKey;
      void this.app.workspace.openLinkText(card.path, "", newLeaf);
    });
    cardEl.addEventListener("contextmenu", (e) => {
      const target = e.target;
      if (checkboxEl.contains(target) || target.tagName === "INPUT" || target.closest("input") || target.closest(".bases-cms-property") || target.closest(".card-status-badge") || target.closest(".bases-cms-quick-edit-icon")) {
        return;
      }
      const file = this.app.vault.getAbstractFileByPath(card.path);
      if (file && file instanceof import_obsidian12.TFile) {
        e.stopPropagation();
        const menu = new import_obsidian12.Menu();
        const currentlySelected = checkbox.checked;
        if (currentlySelected) {
          menu.addItem((item) => {
            item.setTitle("Unselect");
            item.setIcon("square");
            item.onClick(() => {
              onSelect(card.path, false, false);
            });
          });
        } else {
          menu.addItem((item) => {
            item.setTitle("Select");
            item.setIcon("copy-check");
            item.onClick(() => {
              onSelect(card.path, true, false);
            });
          });
        }
        menu.addSeparator();
        this.app.workspace.trigger("file-menu", menu, file, "bases");
        menu.addSeparator();
        menu.addItem((item) => {
          item.setTitle("Delete");
          item.setIcon("trash-2");
          item.onClick(async () => {
            if (toolbarActions) {
              await toolbarActions.handleDelete();
            }
          });
        });
        menu.showAtMouseEvent(e);
        setTimeout(() => {
          const menuEl = document.querySelector(".menu");
          if (!menuEl) return;
          const menuItems = Array.from(menuEl.querySelectorAll(".menu-item"));
          const deleteItem = menuItems.find((item) => {
            var _a;
            const title = (_a = item.textContent) == null ? void 0 : _a.trim();
            return title === "Delete";
          });
          if (deleteItem) {
            deleteItem.addClass("is-danger");
            const icon = deleteItem.querySelector("svg");
            if (icon) {
              setCssProps(icon, {
                color: "var(--text-error)",
                stroke: "var(--text-error)"
              });
            }
            const title = deleteItem.querySelector(".menu-item-title");
            if (title) {
              setCssProps(title, {
                color: "var(--text-error)"
              });
            }
          }
        }, 0);
      }
    });
    const titleEl = cardEl.createDiv("card-title");
    titleEl.appendText(card.title);
    setupQuickEditIcon(this.app, this.plugin, titleEl, cardEl, card.path, settings);
    if (settings.showDate && settings.dateProperty) {
      let dateValue = entry.getValue(settings.dateProperty);
      const hasValidDate = dateValue && ("date" in dateValue && dateValue.date instanceof Date || "data" in dateValue && dateValue.data != null);
      if (!hasValidDate) {
        const file = this.app.vault.getAbstractFileByPath(entry.file.path);
        if (file instanceof import_obsidian12.TFile && file.extension === "mdx") {
          void (async () => {
            const frontmatter = await getFileFrontmatter(this.app, file);
            if (frontmatter) {
              const cleanProp = settings.dateProperty.startsWith("note.") ? settings.dateProperty.substring(5) : settings.dateProperty;
              const frontmatterValue = frontmatter[cleanProp];
              if (frontmatterValue != null) {
                let date = null;
                if (frontmatterValue instanceof Date) {
                  date = frontmatterValue;
                } else if (frontmatterValue && typeof frontmatterValue === "object" && "getTime" in frontmatterValue) {
                  const dateLike = frontmatterValue;
                  try {
                    const timestamp = dateLike.getTime();
                    if (typeof timestamp === "number" && !isNaN(timestamp)) {
                      date = new Date(timestamp);
                    }
                  } catch (e) {
                  }
                }
                if (!date && typeof frontmatterValue === "string") {
                  const dateStr = frontmatterValue.trim();
                  const isoDateStr = dateStr.includes("T") ? dateStr : `${dateStr}T00:00:00`;
                  const parsedDate = new Date(isoDateStr);
                  if (!isNaN(parsedDate.getTime())) {
                    date = parsedDate;
                  } else {
                    const fallbackDate = new Date(dateStr);
                    if (!isNaN(fallbackDate.getTime())) {
                      date = fallbackDate;
                    }
                  }
                }
                if (!date && typeof frontmatterValue === "number") {
                  const parsedDate = new Date(frontmatterValue);
                  if (!isNaN(parsedDate.getTime())) {
                    date = parsedDate;
                  }
                }
                if (date) {
                  requestAnimationFrame(() => {
                    if (cardEl.isConnected) {
                      let dateString;
                      if (settings.dateIncludeTime) {
                        const datePart = date.toLocaleDateString();
                        const timePart = date.toLocaleTimeString(void 0, {
                          hour: "numeric",
                          minute: "2-digit",
                          hour12: true
                        });
                        dateString = `${datePart}, ${timePart}`;
                      } else {
                        dateString = date.toLocaleDateString();
                      }
                      let dateEl = cardEl.querySelector(".card-date");
                      if (!dateEl) {
                        const titleEl2 = cardEl.querySelector(".card-title");
                        if (titleEl2 && titleEl2.parentElement) {
                          dateEl = titleEl2.parentElement.createDiv("card-date");
                          titleEl2.parentElement.insertBefore(dateEl, titleEl2.nextSibling);
                        } else {
                          dateEl = cardEl.createDiv("card-date");
                        }
                      }
                      dateEl.setText(dateString);
                    }
                  });
                }
              }
            }
          })();
        }
      }
      if (hasValidDate && dateValue) {
        const dateObj = dateValue;
        let date = null;
        if (dateObj && "date" in dateObj && dateObj.date instanceof Date) {
          date = dateObj.date;
        } else if (dateObj && "data" in dateObj && dateObj.data) {
          const data = dateObj.data;
          if (data instanceof Date) {
            date = data;
          } else if (typeof data === "string" || typeof data === "number") {
            const parsedDate = new Date(data);
            if (!isNaN(parsedDate.getTime())) {
              date = parsedDate;
            }
          }
        }
        if (date) {
          let dateString;
          if (settings.dateIncludeTime) {
            const datePart = date.toLocaleDateString();
            const timePart = date.toLocaleTimeString(void 0, {
              hour: "numeric",
              minute: "2-digit",
              hour12: true
            });
            dateString = `${datePart}, ${timePart}`;
          } else {
            dateString = date.toLocaleDateString();
          }
          const dateEl = cardEl.createDiv("card-date");
          dateEl.appendText(dateString);
        }
      }
    }
    this.propertyRenderer.renderProperties(cardEl, card, entry, settings, onPropertyToggle, "top");
    if (settings.showTextPreview || settings.showTags && card.displayTags && card.displayTags.length > 0 || settings.imageFormat === "thumbnail" || settings.imageFormat === "cover" || settings.imageFormat !== "none" && (card.imageUrl || card.hasImageAvailable)) {
      const contentContainer = cardEl.createDiv("card-content");
      if (settings.imageFormat === "thumbnail" && card.imageUrl) {
        const rawUrls = Array.isArray(card.imageUrl) ? card.imageUrl : [card.imageUrl];
        const imageUrls = rawUrls.filter((url) => url && typeof url === "string" && url.trim().length > 0);
        if (imageUrls.length > 0) {
          const imageEl = contentContainer.createDiv("card-thumbnail");
          const imageEmbedContainer = imageEl.createDiv("image-embed");
          const originalUrl = imageUrls[0];
          void (async () => {
            const finalUrl = await convertGifToStatic(originalUrl, this.plugin.settings.forceStaticGifImages);
            imageEmbedContainer.style.backgroundImage = `url("${finalUrl}")`;
          })();
          imageEmbedContainer.style.backgroundImage = `url("${originalUrl}")`;
          setCssProps(imageEmbedContainer, {
            backgroundSize: "cover",
            backgroundPosition: "center center",
            backgroundRepeat: "no-repeat"
          });
        }
      }
      if (settings.imageFormat === "thumbnail") {
        const textWrapper = contentContainer.createDiv("card-text-wrapper");
        if (settings.showTextPreview) {
          const textPreviewEl = textWrapper.createDiv("card-text-preview");
          if (card.snippet) {
            textPreviewEl.setText(card.snippet);
          }
          cardEl.__textPreviewEl = textPreviewEl;
          cardEl.__cardPath = card.path;
        }
        if (settings.showTags && card.displayTags && card.displayTags.length > 0) {
          const tagsContainer = textWrapper.createDiv("card-tags");
          const tagStyle = getTagStyle();
          if (tagStyle !== "plain") {
            tagsContainer.addClass(`tag-style-${tagStyle}`);
          }
          const maxTags = settings.maxTagsToShow;
          const tagsToShow = card.displayTags.slice(0, maxTags);
          const remainingCount = card.displayTags.length - maxTags;
          tagsToShow.forEach((tag) => {
            const tagEl = tagsContainer.createSpan("card-tag");
            tagEl.appendText(showTagHashPrefix() ? `#${tag}` : tag);
          });
          if (remainingCount > 0) {
            const moreEl = tagsContainer.createSpan("card-tag-more");
            moreEl.appendText(`+${remainingCount} more`);
          }
        }
      } else {
        if (settings.showTextPreview) {
          const textPreviewEl = contentContainer.createDiv("card-text-preview");
          if (card.snippet) {
            textPreviewEl.setText(card.snippet);
          }
          cardEl.__textPreviewEl = textPreviewEl;
          cardEl.__cardPath = card.path;
        }
        if (settings.showTags && card.displayTags && card.displayTags.length > 0) {
          const tagsContainer = contentContainer.createDiv("card-tags");
          const tagStyle = getTagStyle();
          if (tagStyle !== "plain") {
            tagsContainer.addClass(`tag-style-${tagStyle}`);
          }
          const maxTags = settings.maxTagsToShow;
          const tagsToShow = card.displayTags.slice(0, maxTags);
          const remainingCount = card.displayTags.length - maxTags;
          tagsToShow.forEach((tag) => {
            const tagEl = tagsContainer.createSpan("card-tag");
            tagEl.appendText(showTagHashPrefix() ? `#${tag}` : tag);
          });
          if (remainingCount > 0) {
            const moreEl = tagsContainer.createSpan("card-tag-more");
            moreEl.appendText(`+${remainingCount} more`);
          }
        }
      }
      if (settings.imageFormat === "cover") {
        if (card.imageUrl) {
          const rawUrls = Array.isArray(card.imageUrl) ? card.imageUrl : [card.imageUrl];
          const imageUrls = rawUrls.filter((url) => url && typeof url === "string" && url.trim().length > 0);
          if (imageUrls.length > 0) {
            const imageEl = contentContainer.createDiv("card-cover");
            const imageEmbedContainer = imageEl.createDiv("image-embed");
            const originalUrl = imageUrls[0];
            void (async () => {
              const finalUrl = await convertGifToStatic(originalUrl, this.plugin.settings.forceStaticGifImages);
              imageEmbedContainer.style.backgroundImage = `url("${finalUrl}")`;
            })();
            imageEmbedContainer.style.backgroundImage = `url("${originalUrl}")`;
            setCssProps(imageEmbedContainer, {
              backgroundSize: "cover",
              backgroundPosition: "center center",
              backgroundRepeat: "no-repeat"
            });
            this.propertyRenderer.renderProperties(cardEl, card, entry, settings, onPropertyToggle, "bottom");
            return;
          }
        }
        if (card.hasImageAvailable && !card.imageUrl) {
          const placeholderEl = contentContainer.createDiv("card-cover-placeholder");
        } else if (!card.imageUrl) {
          const placeholderEl = contentContainer.createDiv("card-cover-placeholder");
        }
      }
    }
    this.propertyRenderer.renderProperties(cardEl, card, entry, settings, onPropertyToggle, "bottom");
    return;
  }
};

// src/components/bulk-toolbar.ts
var import_obsidian21 = require("obsidian");

// src/utils/bulk-operations.ts
var import_obsidian13 = require("obsidian");

// src/utils/frontmatter.ts
init_frontmatter_helper();
async function addProperties(app, file, props, overwrite) {
  await processFileFrontMatter(app, file, (frontmatter) => {
    for (const [key, value] of props) {
      if (key === "tags" && !Object.prototype.hasOwnProperty.call(frontmatter, "tags") && !Array.isArray(value.data)) {
        frontmatter[key] = [value.data];
        continue;
      }
      if (!frontmatter[key] || overwrite) {
        frontmatter[key] = value.data;
        continue;
      }
      const type1 = value.type;
      const existingValue = frontmatter[key];
      const type2 = Array.isArray(existingValue) ? "list" : typeof existingValue === "number" ? "number" : typeof existingValue === "boolean" ? "checkbox" : "text";
      if (canBeAppended(type1, type2)) {
        if (frontmatter[key] === value.data) continue;
        if (!value.data) continue;
        const arr = mergeIntoArrays(frontmatter[key], value.data);
        frontmatter[key] = arr;
        continue;
      } else {
        frontmatter[key] = value.data;
        continue;
      }
    }
  });
}
async function removeProperties(app, file, props) {
  await processFileFrontMatter(app, file, (frontmatter) => {
    for (const prop of props) {
      frontmatter[prop] = void 0;
    }
  });
}
function canBeAppended(str1, str2) {
  const arr = ["number", "date", "datetime", "checkbox"];
  if (arr.includes(str1) || arr.includes(str2)) return false;
  return true;
}
function mergeIntoArrays(...args) {
  const arrays = args.map((arg) => Array.isArray(arg) ? arg : [arg]);
  const flattened = arrays.flat();
  const unique = [...new Set(flattened)];
  return unique;
}

// src/utils/bulk-operations.ts
init_frontmatter_helper();
var BulkOperations = class {
  constructor(app) {
    this.app = app;
  }
  /**
   * Set draft status for multiple files
   * Respects filename prefix mode and reverse logic settings
   */
  async setDraft(files, draft, settings) {
    await this.batchProcessFiles(files, async (file) => {
      if (settings) {
        if (settings.draftStatusUseFilenamePrefix) {
          const fileName = file.basename;
          const startsWithUnderscore = fileName.startsWith("_");
          const currentPath = file.path;
          const pathParts = currentPath.split("/");
          let targetValue = draft;
          if (settings.draftStatusReverse) {
            targetValue = !draft;
          }
          if (targetValue === true) {
            if (!startsWithUnderscore) {
              const newName = `_${fileName}${file.extension ? `.${file.extension}` : ""}`;
              pathParts[pathParts.length - 1] = newName;
              const newPath = pathParts.join("/");
              await this.app.fileManager.renameFile(file, newPath);
            }
          } else {
            if (startsWithUnderscore) {
              const newName = fileName.substring(1) + (file.extension ? `.${file.extension}` : "");
              pathParts[pathParts.length - 1] = newName;
              const newPath = pathParts.join("/");
              await this.app.fileManager.renameFile(file, newPath);
            }
          }
        } else {
          const cleanConfigProperty = settings.draftStatusProperty && settings.draftStatusProperty.trim() ? settings.draftStatusProperty.startsWith("note.") ? settings.draftStatusProperty.substring(5) : settings.draftStatusProperty : "draft";
          let targetValue = draft;
          if (settings.draftStatusReverse) {
            targetValue = !draft;
          }
          await processFileFrontMatter(this.app, file, (frontmatter) => {
            frontmatter[cleanConfigProperty] = targetValue;
          });
        }
      } else {
        await processFileFrontMatter(this.app, file, (frontmatter) => {
          frontmatter.draft = draft;
        });
      }
    });
    new import_obsidian13.Notice(`Set ${files.length} file${files.length !== 1 ? "s" : ""} to ${draft ? "draft" : "published"}`);
  }
  /**
   * Add tags to multiple files
   */
  async addTags(files, tags) {
    const props = /* @__PURE__ */ new Map();
    props.set("tags", {
      type: "tags",
      data: tags,
      overwrite: false,
      delimiter: ","
    });
    await this.batchProcessFiles(files, async (file) => {
      await addProperties(this.app, file, props, false);
    });
    new import_obsidian13.Notice(`Added tags to ${files.length} file${files.length !== 1 ? "s" : ""}`);
  }
  /**
   * Remove tags from multiple files
   */
  async removeTags(files, tagsToRemove) {
    await this.batchProcessFiles(files, async (file) => {
      const frontmatter = await getFileFrontmatter(this.app, file);
      if (frontmatter == null ? void 0 : frontmatter.tags) {
        const fmTags = frontmatter.tags;
        const currentTags = Array.isArray(fmTags) ? fmTags : [fmTags];
        const updatedTags = currentTags.filter(
          (tag) => !tagsToRemove.includes(tag)
        );
        await processFileFrontMatter(this.app, file, (fm) => {
          if (updatedTags.length > 0) {
            fm.tags = updatedTags;
          } else {
            fm.tags = void 0;
          }
        });
      }
    });
    new import_obsidian13.Notice(`Removed tags from ${files.length} file${files.length !== 1 ? "s" : ""}`);
  }
  /**
   * Set a property value for multiple files
   */
  async setProperty(files, property, value, propertyType = "text") {
    const cleanProperty = property.startsWith("note.") ? property.substring(5) : property;
    const props = /* @__PURE__ */ new Map();
    props.set(cleanProperty, {
      type: propertyType,
      data: value,
      overwrite: true,
      delimiter: ","
    });
    await this.batchProcessFiles(files, async (file) => {
      await addProperties(this.app, file, props, true);
    });
    new import_obsidian13.Notice(`Set ${cleanProperty} on ${files.length} file${files.length !== 1 ? "s" : ""}`);
  }
  /**
   * Remove a property from multiple files
   */
  async removeProperty(files, property) {
    const cleanProperty = property.startsWith("note.") ? property.substring(5) : property;
    await this.batchProcessFiles(files, async (file) => {
      await removeProperties(this.app, file, [cleanProperty]);
    });
    new import_obsidian13.Notice(`Removed ${cleanProperty} from ${files.length} file${files.length !== 1 ? "s" : ""}`);
  }
  /**
   * Batch process files with progress indication
   */
  async batchProcessFiles(files, processor) {
    let processed = 0;
    const total = files.length;
    for (const filePath of files) {
      const file = this.app.vault.getAbstractFileByPath(filePath);
      if (file instanceof import_obsidian13.TFile) {
        try {
          await processor(file);
          processed++;
        } catch (error) {
          console.error(`Error processing ${filePath}:`, error);
        }
      }
    }
    if (processed < total) {
      new import_obsidian13.Notice(`Processed ${processed} of ${total} files`);
    }
  }
};

// src/components/manage-tags-modal.ts
var import_obsidian14 = require("obsidian");
init_frontmatter_helper();
var ManageTagsModal = class extends import_obsidian14.Modal {
  constructor(app, files) {
    super(app);
    this.tagsToAdd = "";
    this.tagsToRemove = /* @__PURE__ */ new Set();
    this.files = files;
    this.bulkOps = new BulkOperations(app);
  }
  onOpen() {
    const { contentEl } = this;
    contentEl.empty();
    new import_obsidian14.Setting(contentEl).setName("Manage tags").setHeading();
    contentEl.createEl("p", { text: `Managing tags for ${this.files.length} file${this.files.length !== 1 ? "s" : ""}` });
    new import_obsidian14.Setting(contentEl).setName("Add tags").setDesc("Enter tags to add (comma-separated).").addText((text) => {
      text.setPlaceholder("tag1, tag2, tag3").onChange((value) => {
        this.tagsToAdd = value;
      });
    });
    contentEl.createEl("h3", { text: "Remove tags" });
    const removeContainer = contentEl.createDiv();
    const allTags = /* @__PURE__ */ new Set();
    for (const filePath of this.files) {
      const file = this.app.vault.getAbstractFileByPath(filePath);
      if (file instanceof import_obsidian14.TFile) {
        if (file.extension === "mdx") {
          void (async () => {
            const frontmatter = await getFileFrontmatter(this.app, file);
            if (frontmatter == null ? void 0 : frontmatter.tags) {
              const tags = Array.isArray(frontmatter.tags) ? frontmatter.tags : [frontmatter.tags];
              tags.forEach((tag) => {
                if (!allTags.has(tag)) {
                  allTags.add(tag);
                  if (this.contentEl && this.contentEl.isConnected && removeContainer.isConnected) {
                    this.addTagCheckbox(removeContainer, tag);
                  }
                }
              });
            }
          })();
        } else {
          const metadata = this.app.metadataCache.getFileCache(file);
          const frontmatter = metadata == null ? void 0 : metadata.frontmatter;
          if (frontmatter == null ? void 0 : frontmatter.tags) {
            const tags = Array.isArray(frontmatter.tags) ? frontmatter.tags : [frontmatter.tags];
            tags.forEach((tag) => allTags.add(tag));
          }
        }
      }
    }
    for (const tag of Array.from(allTags).sort()) {
      new import_obsidian14.Setting(removeContainer).setName(tag).addToggle((toggle) => {
        toggle.setValue(this.tagsToRemove.has(tag)).onChange((value) => {
          if (value) {
            this.tagsToRemove.add(tag);
          } else {
            this.tagsToRemove.delete(tag);
          }
        });
      });
    }
    const buttonContainer = contentEl.createDiv();
    buttonContainer.addClass("bases-cms-modal-button-container");
    const cancelBtn = buttonContainer.createEl("button");
    cancelBtn.setText("Cancel");
    cancelBtn.addEventListener("click", () => this.close());
    const applyBtn = buttonContainer.createEl("button");
    applyBtn.setText("Apply");
    applyBtn.addClass("mod-cta");
    applyBtn.addEventListener("click", () => {
      void (async () => {
        await this.applyChanges();
        this.close();
      })();
    });
  }
  addTagCheckbox(container, tag) {
    new import_obsidian14.Setting(container).setName(tag).addToggle((toggle) => {
      toggle.setValue(this.tagsToRemove.has(tag)).onChange((value) => {
        if (value) {
          this.tagsToRemove.add(tag);
        } else {
          this.tagsToRemove.delete(tag);
        }
      });
    });
  }
  async applyChanges() {
    if (this.tagsToAdd.trim()) {
      const tagsToAdd = this.tagsToAdd.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
      if (tagsToAdd.length > 0) {
        await this.bulkOps.addTags(this.files, tagsToAdd);
      }
    }
    if (this.tagsToRemove.size > 0) {
      await this.bulkOps.removeTags(this.files, Array.from(this.tagsToRemove));
    }
  }
  onClose() {
    const { contentEl } = this;
    contentEl.empty();
  }
};

// src/components/set-property-modal.ts
var import_obsidian15 = require("obsidian");
var SetPropertyModal = class extends import_obsidian15.Modal {
  constructor(app, files) {
    super(app);
    this.propertyName = "";
    this.propertyValue = "";
    this.propertyType = "text";
    this.files = files;
    this.bulkOps = new BulkOperations(app);
  }
  onOpen() {
    const { contentEl } = this;
    contentEl.empty();
    new import_obsidian15.Setting(contentEl).setName("Set property").setHeading();
    contentEl.createEl("p", { text: `Setting property on ${this.files.length} file${this.files.length !== 1 ? "s" : ""}` });
    new import_obsidian15.Setting(contentEl).setName("Property name").setDesc("Enter the property name to set.").addText((text) => {
      text.setPlaceholder("Enter name").onChange((value) => {
        this.propertyName = value;
      });
    });
    new import_obsidian15.Setting(contentEl).setName("Property type").setDesc("Select the property type.").addDropdown((dropdown) => {
      dropdown.addOption("text", "Text").addOption("number", "Number").addOption("checkbox", "Checkbox").addOption("date", "Date").setValue(this.propertyType).onChange((value) => {
        this.propertyType = value;
      });
    });
    new import_obsidian15.Setting(contentEl).setName("Property value").setDesc("Enter the property value.").addText((text) => {
      text.setPlaceholder("Enter value").onChange((value) => {
        this.propertyValue = value;
      });
    });
    const buttonContainer = contentEl.createDiv();
    buttonContainer.addClass("bases-cms-modal-button-container");
    const cancelBtn = buttonContainer.createEl("button");
    cancelBtn.setText("Cancel");
    cancelBtn.addEventListener("click", () => this.close());
    const applyBtn = buttonContainer.createEl("button");
    applyBtn.setText("Apply");
    applyBtn.addClass("mod-cta");
    applyBtn.addEventListener("click", () => {
      void (async () => {
        if (this.propertyName && this.propertyValue) {
          await this.applyChanges();
          this.close();
        }
      })();
    });
  }
  async applyChanges() {
    let value = this.propertyValue;
    if (this.propertyType === "number") {
      value = Number(this.propertyValue);
    } else if (this.propertyType === "checkbox") {
      value = this.propertyValue.toLowerCase() === "true" || this.propertyValue === "1";
    } else if (this.propertyType === "date") {
      value = this.propertyValue;
    }
    await this.bulkOps.setProperty(this.files, this.propertyName, value, this.propertyType);
  }
  onClose() {
    const { contentEl } = this;
    contentEl.empty();
  }
};

// src/components/remove-property-modal.ts
var import_obsidian16 = require("obsidian");
init_frontmatter_helper();
var RemovePropertyModal = class extends import_obsidian16.Modal {
  constructor(app, files) {
    super(app);
    this.propertiesToRemove = /* @__PURE__ */ new Set();
    this.files = files;
    this.bulkOps = new BulkOperations(app);
  }
  onOpen() {
    const { contentEl } = this;
    contentEl.empty();
    new import_obsidian16.Setting(contentEl).setName("Remove property").setHeading();
    contentEl.createEl("p", { text: `Removing properties from ${this.files.length} file${this.files.length !== 1 ? "s" : ""}` });
    const propertiesContainer = contentEl.createDiv();
    const allProperties = /* @__PURE__ */ new Set();
    for (const filePath of this.files) {
      const file = this.app.vault.getAbstractFileByPath(filePath);
      if (file instanceof import_obsidian16.TFile && file.extension !== "mdx") {
        const metadata = this.app.metadataCache.getFileCache(file);
        const frontmatter = metadata == null ? void 0 : metadata.frontmatter;
        if (frontmatter) {
          for (const key in frontmatter) {
            if (key !== "tags" && key !== "title") {
              allProperties.add(key);
            }
          }
        }
      }
    }
    for (const prop of Array.from(allProperties).sort()) {
      this.addPropertyCheckbox(propertiesContainer, prop);
    }
    void (async () => {
      for (const filePath of this.files) {
        const file = this.app.vault.getAbstractFileByPath(filePath);
        if (file instanceof import_obsidian16.TFile && file.extension === "mdx") {
          const frontmatter = await getFileFrontmatter(this.app, file);
          if (frontmatter) {
            for (const key in frontmatter) {
              if (key !== "tags" && key !== "title") {
                if (!allProperties.has(key)) {
                  allProperties.add(key);
                  if (this.contentEl && this.contentEl.isConnected && propertiesContainer.isConnected) {
                    this.addPropertyCheckbox(propertiesContainer, key);
                  }
                }
              }
            }
          }
        }
      }
    })();
    if (allProperties.size === 0) {
      contentEl.createEl("p", { text: "No properties found in selected files." });
    }
    const buttonContainer = contentEl.createDiv();
    buttonContainer.addClass("bases-cms-modal-button-container");
    const cancelBtn = buttonContainer.createEl("button");
    cancelBtn.setText("Cancel");
    cancelBtn.addEventListener("click", () => this.close());
    const applyBtn = buttonContainer.createEl("button");
    applyBtn.setText("Apply");
    applyBtn.addClass("mod-cta");
    applyBtn.addEventListener("click", () => {
      void (async () => {
        if (this.propertiesToRemove.size > 0) {
          await this.applyChanges();
          this.close();
        }
      })();
    });
  }
  addPropertyCheckbox(container, prop) {
    new import_obsidian16.Setting(container).setName(prop).addToggle((toggle) => {
      toggle.setValue(this.propertiesToRemove.has(prop)).onChange((value) => {
        if (value) {
          this.propertiesToRemove.add(prop);
        } else {
          this.propertiesToRemove.delete(prop);
        }
      });
    });
  }
  async applyChanges() {
    for (const prop of this.propertiesToRemove) {
      await this.bulkOps.removeProperty(this.files, prop);
    }
  }
  onClose() {
    const { contentEl } = this;
    contentEl.empty();
  }
};

// src/utils/toolbar-actions.ts
init_deletion_preview();

// src/components/bulk-operation-confirm.ts
var import_obsidian20 = require("obsidian");
var BulkOperationConfirmModal = class extends import_obsidian20.Modal {
  constructor(app, files, operation, onConfirm) {
    super(app);
    this.files = files;
    this.operation = operation;
    this.onConfirm = onConfirm;
  }
  onOpen() {
    const { contentEl } = this;
    contentEl.empty();
    const operationName = this.operation === "draft" ? "mark as draft" : "mark as published";
    const headingText = operationName.charAt(0).toUpperCase() + operationName.slice(1);
    new import_obsidian20.Setting(contentEl).setName(`Confirm ${headingText}`).setHeading();
    contentEl.createEl("p", {
      text: `Are you sure you want to ${operationName} ${this.files.length} file${this.files.length !== 1 ? "s" : ""}?`
    });
    if (this.files.length > 0) {
      const filesList = contentEl.createEl("ul", { cls: "bases-cms-deletion-list" });
      for (const filePath of this.files.slice(0, 20)) {
        const li = filesList.createEl("li");
        li.setText(filePath);
      }
      if (this.files.length > 20) {
        filesList.createEl("li", {
          text: `... and ${this.files.length - 20} more file${this.files.length - 20 !== 1 ? "s" : ""}`
        });
      }
    }
    const buttonContainer = contentEl.createDiv();
    buttonContainer.addClass("bases-cms-modal-button-container");
    const cancelBtn = buttonContainer.createEl("button");
    cancelBtn.setText("Cancel");
    cancelBtn.addEventListener("click", () => this.close());
    const confirmBtn = buttonContainer.createEl("button");
    confirmBtn.setText("Confirm");
    confirmBtn.addClass("mod-cta");
    confirmBtn.addEventListener("click", () => {
      this.onConfirm();
      this.close();
    });
  }
  onClose() {
    const { contentEl } = this;
    contentEl.empty();
  }
};

// src/utils/toolbar-actions.ts
init_smart_deletion();
var ToolbarActions = class {
  constructor(app, plugin, getSelectedFiles, clearSelection, refreshView, showToolbar) {
    this.app = app;
    this.plugin = plugin;
    this.getSelectedFiles = getSelectedFiles;
    this.clearSelection = clearSelection;
    this.refreshView = refreshView;
    this.showToolbar = showToolbar;
    this.bulkOps = new BulkOperations(app);
  }
  async handleSetDraft(settings) {
    const files = this.getSelectedFiles();
    if (files.length === 0) return;
    if (this.plugin.settings.confirmBulkOperations) {
      const modal = new BulkOperationConfirmModal(
        this.app,
        files,
        "draft",
        () => {
          void (async () => {
            await this.bulkOps.setDraft(files, true, settings);
            this.refreshView();
          })();
        }
      );
      modal.open();
    } else {
      await this.bulkOps.setDraft(files, true, settings);
      this.refreshView();
    }
  }
  async handlePublish(settings) {
    const files = this.getSelectedFiles();
    if (files.length === 0) return;
    if (this.plugin.settings.confirmBulkOperations) {
      const modal = new BulkOperationConfirmModal(
        this.app,
        files,
        "publish",
        () => {
          void (async () => {
            await this.bulkOps.setDraft(files, false, settings);
            this.refreshView();
          })();
        }
      );
      modal.open();
    } else {
      await this.bulkOps.setDraft(files, false, settings);
      this.refreshView();
    }
  }
  handleManageTags() {
    const files = this.getSelectedFiles();
    if (files.length === 0) return;
    const modal = new ManageTagsModal(this.app, files);
    modal.onClose = () => {
      this.showToolbar();
      this.refreshView();
    };
    modal.open();
  }
  handleSetProperty() {
    const files = this.getSelectedFiles();
    if (files.length === 0) return;
    const modal = new SetPropertyModal(this.app, files);
    modal.onClose = () => {
      this.showToolbar();
      this.refreshView();
    };
    modal.open();
  }
  handleRemoveProperty() {
    const files = this.getSelectedFiles();
    if (files.length === 0) return;
    const modal = new RemovePropertyModal(this.app, files);
    modal.onClose = () => {
      this.showToolbar();
      this.refreshView();
    };
    modal.open();
  }
  async handleDelete() {
    const files = this.getSelectedFiles();
    if (files.length === 0) return;
    if (this.plugin.settings.confirmDeletions) {
      const preview = await prepareDeletionPreview(
        this.app,
        files,
        this.plugin.settings
      );
      const modal = new DeletionPreviewModal(
        this.app,
        preview,
        () => {
          this.clearSelection();
          this.refreshView();
        }
      );
      modal.open();
    } else {
      const preview = await prepareDeletionPreview(
        this.app,
        files,
        this.plugin.settings
      );
      await executeSmartDeletion(this.app, preview);
      this.clearSelection();
      this.refreshView();
    }
  }
};

// src/components/bulk-toolbar.ts
var BulkToolbar = class {
  constructor(app, plugin, container, getSelectedFiles, clearSelection, refreshView, selectAllCallback, settings) {
    this.app = app;
    this.plugin = plugin;
    this.container = container;
    this.getSelectedFiles = getSelectedFiles;
    this.clearSelection = clearSelection;
    this.refreshView = refreshView;
    this.toolbarEl = null;
    this.countEl = null;
    this.resizeObserver = null;
    this.timeoutIds = [];
    this.selectAllCallback = selectAllCallback;
    this.settings = settings;
    this.actions = new ToolbarActions(
      this.app,
      this.plugin,
      this.getSelectedFiles,
      this.clearSelection,
      this.refreshView,
      () => this.show()
    );
    this.createToolbar();
  }
  /**
   * Update settings (called when view settings change)
   */
  updateSettings(settings) {
    this.settings = settings;
  }
  /**
   * Get toolbar actions (for use in context menus)
   */
  getActions() {
    return this.actions;
  }
  createToolbar() {
    this.toolbarEl = document.createElement("div");
    this.toolbarEl.className = "bases-toolbar bases-cms-bulk-toolbar bases-cms-bulk-toolbar-hidden";
    this.toolbarEl.__bulkToolbarInstance = this;
    this.createToolbarContent();
    this.positionToolbar();
    const timeoutId = window.setTimeout(() => this.positionToolbar(), 100);
    this.timeoutIds.push(timeoutId);
  }
  positionToolbar() {
    var _a, _b;
    if (!this.toolbarEl) return;
    const safeInsertBefore = (parent2, newNode, refNode) => {
      if (!parent2 || !newNode) return false;
      if (newNode.parentElement === parent2 && (refNode === null ? !newNode.nextSibling : newNode.nextSibling === refNode)) {
        return true;
      }
      try {
        if (refNode && !parent2.contains(refNode)) {
          parent2.appendChild(newNode);
        } else {
          parent2.insertBefore(newNode, refNode);
        }
        return true;
      } catch (e) {
        console.warn("[Bases CMS] Failed to insert toolbar:", e);
        return false;
      }
    };
    const basesHeader = ((_a = this.container.closest(".view-content")) == null ? void 0 : _a.querySelector(".bases-header")) || ((_b = this.container.parentElement) == null ? void 0 : _b.querySelector(".bases-header"));
    if (basesHeader instanceof HTMLElement && basesHeader.parentElement) {
      if (safeInsertBefore(basesHeader.parentElement, this.toolbarEl, basesHeader.nextSibling)) return;
    }
    const parent = this.container.parentElement;
    if (parent) {
      safeInsertBefore(parent, this.toolbarEl, this.container);
    }
  }
  createToolbarContent() {
    if (!this.toolbarEl) return;
    const leftContainer = this.toolbarEl.createDiv("bases-cms-bulk-toolbar-left");
    const createBasesButton = (iconName, text, onClick, container, isDestructive = false) => {
      const toolbarItem = container.createDiv("bases-toolbar-item");
      const button = toolbarItem.createDiv("text-icon-button");
      if (isDestructive) {
        button.addClass("destructive");
      }
      button.setAttribute("tabindex", "0");
      const iconEl = button.createSpan("text-button-icon");
      (0, import_obsidian21.setIcon)(iconEl, iconName);
      const textEl = button.createSpan("text-button-label");
      textEl.setText(text);
      button.addEventListener("click", onClick);
      return button;
    };
    if (this.plugin.settings.showToolbarSelectAll) {
      createBasesButton("copy-check", "Select all", () => this.handleSelectAll(), leftContainer);
    }
    if (this.plugin.settings.showToolbarClear) {
      createBasesButton("square-x", "Clear", () => this.clearSelection(), leftContainer);
    }
    const countItem = leftContainer.createDiv("bases-toolbar-item bases-cms-selected-count");
    this.countEl = countItem.createSpan("text-button-label");
    this.countEl.setText("0 selected");
    const rightContainer = this.toolbarEl.createDiv("bases-cms-bulk-toolbar-right");
    if (this.plugin.settings.showToolbarPublish) {
      createBasesButton("book-check", "Publish", () => {
        void this.actions.handlePublish(this.settings);
      }, rightContainer);
    }
    if (this.plugin.settings.showToolbarDraft) {
      createBasesButton("book-dashed", "Draft", () => {
        void this.actions.handleSetDraft(this.settings);
      }, rightContainer);
    }
    if (this.plugin.settings.showToolbarTags) {
      createBasesButton("tags", "Tags", () => this.actions.handleManageTags(), rightContainer);
    }
    if (this.plugin.settings.showToolbarSet) {
      createBasesButton("list-check", "Set", () => this.actions.handleSetProperty(), rightContainer);
    }
    if (this.plugin.settings.showToolbarRemove) {
      createBasesButton("list-x", "Remove", () => this.actions.handleRemoveProperty(), rightContainer);
    }
    if (this.plugin.settings.showToolbarDelete) {
      createBasesButton("trash-2", "Delete", () => {
        void this.actions.handleDelete();
      }, rightContainer, true);
    }
    this.setupResponsiveBehavior();
  }
  setupResponsiveBehavior() {
    if (!this.toolbarEl) return;
    const timeoutId1 = window.setTimeout(() => {
      this.updateCollapsedState();
    }, 100);
    this.timeoutIds.push(timeoutId1);
    if (this.toolbarEl) {
      this.resizeObserver = new ResizeObserver(() => {
        this.updateCollapsedState();
      });
      this.resizeObserver.observe(this.toolbarEl);
    }
    const container = this.container;
    if (container) {
      const containerObserver = new ResizeObserver(() => {
        const timeoutId = window.setTimeout(() => {
          this.updateCollapsedState();
        }, 10);
        this.timeoutIds.push(timeoutId);
      });
      containerObserver.observe(container);
      this.containerObserver = containerObserver;
    }
  }
  updateCollapsedState() {
    if (!this.toolbarEl) return;
    const visibleButtons = this.toolbarEl.querySelectorAll(".text-icon-button");
    const buttonCount = visibleButtons.length;
    const baseWidth = 140;
    const perButtonWidth = 75;
    const dynamicThreshold = baseWidth + buttonCount * perButtonWidth;
    const toolbarWidth = this.toolbarEl.offsetWidth;
    if (toolbarWidth === 0) {
      const containerWidth = this.container.offsetWidth;
      if (containerWidth > 0 && containerWidth < dynamicThreshold) {
        this.toolbarEl.addClass("collapsed");
      }
      return;
    }
    const isCollapsed = toolbarWidth < dynamicThreshold;
    if (isCollapsed) {
      this.toolbarEl.addClass("collapsed");
    } else {
      this.toolbarEl.removeClass("collapsed");
    }
  }
  updateCount(count) {
    if (this.countEl) {
      this.countEl.setText(`${count} selected`);
    }
    this.updateCollapsedState();
  }
  handleSelectAll() {
    if (this.selectAllCallback) {
      this.selectAllCallback();
    }
  }
  show() {
    if (!this.toolbarEl) {
      console.warn("[Bases CMS] Toolbar element not found, recreating...");
      this.createToolbar();
    }
    if (this.toolbarEl) {
      this.positionToolbar();
      if (!this.toolbarEl.parentElement) {
        console.warn("[Bases CMS] Toolbar not in DOM, repositioning...");
        this.positionToolbar();
      }
      this.toolbarEl.removeClass("bases-cms-bulk-toolbar-hidden");
      this.toolbarEl.addClass("bases-cms-bulk-toolbar-visible");
      void this.toolbarEl.offsetHeight;
      const timeoutId = window.setTimeout(() => {
        if (this.toolbarEl) {
          this.toolbarEl.removeClass("bases-cms-bulk-toolbar-animating-out");
          this.toolbarEl.addClass("bases-cms-bulk-toolbar-animating-in");
        }
      }, 10);
      this.timeoutIds.push(timeoutId);
    } else {
      console.error("[Bases CMS] Failed to show toolbar - element is null");
    }
  }
  hide() {
    if (this.toolbarEl) {
      this.toolbarEl.removeClass("bases-cms-bulk-toolbar-animating-in");
      this.toolbarEl.addClass("bases-cms-bulk-toolbar-animating-out");
      const timeoutId = window.setTimeout(() => {
        if (this.toolbarEl) {
          this.toolbarEl.removeClass("bases-cms-bulk-toolbar-visible");
          this.toolbarEl.addClass("bases-cms-bulk-toolbar-hidden");
        }
      }, 200);
      this.timeoutIds.push(timeoutId);
    }
  }
  /**
   * Recreate the toolbar with updated settings
   * Preserves visibility state and count
   */
  recreate() {
    const wasVisible = this.toolbarEl && !this.toolbarEl.hasClass("bases-cms-bulk-toolbar-hidden");
    let currentCount = 0;
    if (this.countEl && this.countEl.textContent) {
      const match = this.countEl.textContent.match(/\d+/);
      if (match) {
        currentCount = parseInt(match[0], 10);
      }
    }
    this.destroy();
    this.createToolbar();
    if (wasVisible && this.toolbarEl && currentCount > 0) {
      this.updateCount(currentCount);
      this.show();
    }
  }
  destroy() {
    this.timeoutIds.forEach((id) => window.clearTimeout(id));
    this.timeoutIds = [];
    if (this.resizeObserver) {
      this.resizeObserver.disconnect();
      this.resizeObserver = null;
    }
    const containerObserver = this.containerObserver;
    if (containerObserver) {
      containerObserver.disconnect();
      this.containerObserver = void 0;
    }
    if (this.toolbarEl) {
      this.toolbarEl.remove();
      this.toolbarEl = null;
    }
  }
};

// src/utils/new-note-interceptor.ts
init_settings_schema();
function setupNewNoteInterceptor(app, containerEl, config, pluginSettings, registerCleanup) {
  const interceptNewButton = (e) => {
    const target = e.target;
    const buttonEl = target.closest('.bases-toolbar-new-item-menu, .bases-toolbar-new-item-menu .text-icon-button, [data-action="new-item"], button[aria-label*="new"], button[aria-label*="New"], .bases-toolbar button');
    if (!buttonEl) {
      return;
    }
    if (target.closest(".bases-cms-bulk-toolbar, .bases-cms-container .card")) {
      return;
    }
    const activeLeaf = app.workspace.activeLeaf;
    const activeView = activeLeaf == null ? void 0 : activeLeaf.view;
    const activeViewContainer = activeView == null ? void 0 : activeView.containerEl;
    const isCMSView = (activeView == null ? void 0 : activeView.type) === "bases-cms" || (activeViewContainer == null ? void 0 : activeViewContainer.querySelector(".bases-cms-container")) !== null;
    if (!isCMSView) {
      return;
    }
    const isOurView = activeViewContainer && (activeViewContainer === containerEl || activeViewContainer.contains(containerEl) || containerEl.contains(activeViewContainer));
    if (!isOurView) {
      return;
    }
    const containerWithView = containerEl;
    const viewInstance = containerWithView.__cmsView;
    const viewConfig = (viewInstance == null ? void 0 : viewInstance.config) || containerWithView.__cmsConfig || config;
    const settings = readCMSSettings(viewConfig, pluginSettings);
    const hasCustomLocation = settings.newNoteLocation && settings.newNoteLocation.trim() !== "";
    if (settings.customizeNewButton || hasCustomLocation) {
      e.preventDefault();
      e.stopPropagation();
      e.stopImmediatePropagation();
      void (async () => {
        var _a;
        const locationInput = ((_a = settings.newNoteLocation) == null ? void 0 : _a.trim()) || "";
        if (locationInput === "" && !settings.customizeNewButton) {
          const vaultConfig = app.vault.config;
          const newFileLocation = (vaultConfig == null ? void 0 : vaultConfig.newFileLocation) || "folder";
          const newFileFolderPath = (vaultConfig == null ? void 0 : vaultConfig.newFileFolderPath) || "";
          let filePath = "Untitled.md";
          if (newFileLocation === "folder" && newFileFolderPath) {
            filePath = `${newFileFolderPath}/Untitled.md`;
          } else if (newFileLocation === "current") {
            const activeFile = app.workspace.getActiveFile();
            if (activeFile && activeFile.parent) {
              filePath = `${activeFile.parent.path}/Untitled.md`;
            }
          } else if (newFileLocation === "root") {
            filePath = "Untitled.md";
          }
          const file = await app.vault.create(filePath, "");
          if (settings.customizeNewButton) {
            await app.workspace.openLinkText(file.path, "", false);
          }
          return;
        }
        if (locationInput === "/" || locationInput.replace(/\//g, "") === "") {
          const newFile = await app.vault.create("Untitled.md", "");
          if (settings.customizeNewButton) {
            await app.workspace.openLinkText(newFile.path, "", false);
          }
          return;
        }
        const folderPath = locationInput.replace(/^\/+|\/+$/g, "");
        let folder = app.vault.getAbstractFileByPath(folderPath);
        if (!folder || !("children" in folder)) {
          await app.vault.createFolder(folderPath);
          folder = app.vault.getAbstractFileByPath(folderPath);
        }
        if (folder && "children" in folder) {
          const newFile = await app.vault.create(`${folderPath}/Untitled.md`, "");
          if (settings.customizeNewButton) {
            await app.workspace.openLinkText(newFile.path, "", false);
          }
        }
      })().catch((error) => {
        console.error("[CMS] Error creating new note:", error);
      });
    }
  };
  document.addEventListener("click", interceptNewButton, true);
  const observer = new MutationObserver(() => {
    const buttons2 = document.querySelectorAll('.bases-toolbar-new-item-menu, .bases-toolbar-new-item-menu .text-icon-button, [data-action="new-item"]');
    buttons2.forEach((buttonEl) => {
      const buttonWithFlag = buttonEl;
      if (!buttonWithFlag.__cmsIntercepted) {
        buttonWithFlag.__cmsIntercepted = true;
        buttonEl.addEventListener("click", interceptNewButton, true);
      }
    });
  });
  observer.observe(document.body, { childList: true, subtree: true });
  const buttons = document.querySelectorAll('.bases-toolbar-new-item-menu, .bases-toolbar-new-item-menu .text-icon-button, [data-action="new-item"]');
  buttons.forEach((buttonEl) => {
    const buttonWithFlag = buttonEl;
    if (!buttonWithFlag.__cmsIntercepted) {
      buttonWithFlag.__cmsIntercepted = true;
      buttonEl.addEventListener("click", interceptNewButton, true);
    }
  });
  registerCleanup(() => {
    document.removeEventListener("click", interceptNewButton, true);
    observer.disconnect();
  });
}

// src/utils/property-toggle-handler.ts
var import_obsidian22 = require("obsidian");
init_settings_schema();
init_frontmatter_helper();
var PropertyToggleHandler = class {
  constructor(app, config, pluginSettings, onRefresh) {
    this.app = app;
    this.config = config;
    this.pluginSettings = pluginSettings;
    this.onRefresh = onRefresh;
  }
  async handlePropertyToggle(path, property, value) {
    try {
      const file = this.app.vault.getAbstractFileByPath(path);
      if (!(file instanceof import_obsidian22.TFile)) return;
      const cleanProperty = property.startsWith("note.") ? property.substring(5) : property;
      const settings = readCMSSettings(
        this.config,
        this.pluginSettings
      );
      const isDraftProperty = settings.showDraftStatus && cleanProperty === "draft";
      let shouldRefresh = false;
      if (isDraftProperty) {
        if (settings.draftStatusUseFilenamePrefix) {
          const fileName = file.basename;
          const startsWithUnderscore = fileName.startsWith("_");
          const currentPath = file.path;
          const pathParts = currentPath.split("/");
          if (value === true) {
            if (!startsWithUnderscore) {
              const newName = `_${fileName}${file.extension ? `.${file.extension}` : ""}`;
              pathParts[pathParts.length - 1] = newName;
              const newPath = pathParts.join("/");
              await this.app.fileManager.renameFile(file, newPath);
              shouldRefresh = true;
            }
          } else {
            if (startsWithUnderscore) {
              const newName = fileName.substring(1) + (file.extension ? `.${file.extension}` : "");
              pathParts[pathParts.length - 1] = newName;
              const newPath = pathParts.join("/");
              await this.app.fileManager.renameFile(file, newPath);
              shouldRefresh = true;
            }
          }
        } else {
          const cleanConfigProperty = settings.draftStatusProperty && settings.draftStatusProperty.trim() ? settings.draftStatusProperty.startsWith("note.") ? settings.draftStatusProperty.substring(5) : settings.draftStatusProperty : "draft";
          await processFileFrontMatter(this.app, file, (frontmatter) => {
            frontmatter[cleanConfigProperty] = value;
          });
          shouldRefresh = true;
        }
      } else {
        await processFileFrontMatter(this.app, file, (frontmatter) => {
          frontmatter[cleanProperty] = value;
        });
        shouldRefresh = true;
      }
      if (shouldRefresh) {
        requestAnimationFrame(() => {
          window.setTimeout(() => {
            try {
              this.onRefresh();
            } catch (error) {
              console.error("Error refreshing view after property toggle:", error);
            }
          }, 100);
        });
      }
    } catch (error) {
      console.error("Error toggling property:", error);
    }
  }
};

// src/utils/scroll-layout-manager.ts
init_settings_schema();
var ScrollLayoutManager = class {
  constructor(containerEl, app, config, pluginSettings, onLoadMore, registerCleanup) {
    this.containerEl = containerEl;
    this.app = app;
    this.pluginSettings = pluginSettings;
    this.onLoadMore = onLoadMore;
    this.registerCleanup = registerCleanup;
    this.scrollListener = null;
    this.scrollThrottleTimeout = null;
    this.resizeObserver = null;
    this.windowResizeHandler = null;
    this.isLoading = false;
    this.displayedCount = 50;
    this.totalEntries = 0;
    this.configPollInterval = null;
    this.lastCardSize = null;
    this.lastImageAspectRatio = null;
    // Virtual scrolling state
    this.virtualScrollEnabled = false;
    this.estimatedCardHeight = 300;
    // Default estimate, updated on render
    this.cardsPerRow = 3;
    // Default, updated based on container width
    this.lastScrollTop = 0;
    this.virtualScrollCallback = null;
    var _a;
    this.config = config;
    const isMobile = (_a = this.app.isMobile) != null ? _a : false;
    this.displayedCount = isMobile ? 25 : 50;
  }
  /**
   * Update the config reference (useful when config becomes available after construction)
   */
  updateConfig(config) {
    this.config = config;
  }
  setDisplayedCount(count) {
    this.displayedCount = count;
  }
  /**
   * Reset displayed count and scroll position
   */
  resetScroll() {
    var _a;
    const isMobile = (_a = this.app.isMobile) != null ? _a : false;
    this.displayedCount = isMobile ? 25 : 50;
    this.containerEl.scrollTop = 0;
  }
  getDisplayedCount() {
    return this.displayedCount;
  }
  setIsLoading(loading) {
    this.isLoading = loading;
  }
  setupInfiniteScroll(totalEntries) {
    this.totalEntries = totalEntries;
    if (this.scrollListener) {
      this.containerEl.removeEventListener("scroll", this.scrollListener);
      this.scrollListener = null;
    }
    if (this.displayedCount >= totalEntries) {
      return;
    }
    this.scrollListener = () => {
      var _a;
      if (this.scrollThrottleTimeout !== null) {
        return;
      }
      if (this.isLoading) {
        return;
      }
      const scrollTop = this.containerEl.scrollTop;
      const scrollHeight = this.containerEl.scrollHeight;
      const clientHeight = this.containerEl.clientHeight;
      const distanceFromBottom = scrollHeight - (scrollTop + clientHeight);
      const isMobile = (_a = this.app.isMobile) != null ? _a : false;
      const viewportMultiplier = isMobile ? 1 : 2;
      const threshold = clientHeight * viewportMultiplier;
      if (distanceFromBottom < threshold && this.displayedCount < totalEntries) {
        this.isLoading = true;
        const batchSize = 50;
        this.displayedCount = Math.min(this.displayedCount + batchSize, totalEntries);
        this.onLoadMore();
      }
      this.scrollThrottleTimeout = window.setTimeout(() => {
        this.scrollThrottleTimeout = null;
      }, 100);
    };
    this.containerEl.addEventListener("scroll", this.scrollListener);
    this.registerCleanup(() => {
      if (this.scrollListener) {
        this.containerEl.removeEventListener("scroll", this.scrollListener);
      }
      if (this.scrollThrottleTimeout !== null) {
        window.clearTimeout(this.scrollThrottleTimeout);
      }
    });
  }
  setupResizeObserver() {
    if (this.resizeObserver) {
      return;
    }
    const updateGrid = () => {
      if (!this.config || typeof this.config.get !== "function") {
        return;
      }
      const currentSettings = readCMSSettings(
        this.config,
        this.pluginSettings
      );
      const cardMinWidth = currentSettings.cardSize;
      const imageAspectRatio = currentSettings.imageAspectRatio;
      this.containerEl.style.setProperty("--card-min-width", `${cardMinWidth}px`);
      this.containerEl.style.setProperty("--bases-cms-image-aspect-ratio", String(imageAspectRatio));
      this.lastCardSize = cardMinWidth;
      this.lastImageAspectRatio = imageAspectRatio;
    };
    this.resizeObserver = new ResizeObserver(updateGrid);
    this.resizeObserver.observe(this.containerEl);
    updateGrid();
    this.configPollInterval = window.setInterval(() => {
      if (!this.config || typeof this.config.get !== "function") {
        return;
      }
      const currentSettings = readCMSSettings(
        this.config,
        this.pluginSettings
      );
      const currentCardSize = currentSettings.cardSize;
      const currentImageAspectRatio = currentSettings.imageAspectRatio;
      if (this.lastCardSize !== currentCardSize || this.lastImageAspectRatio !== currentImageAspectRatio) {
        this.containerEl.style.setProperty("--card-min-width", `${currentCardSize}px`);
        this.containerEl.style.setProperty("--bases-cms-image-aspect-ratio", String(currentImageAspectRatio));
        this.lastCardSize = currentCardSize;
        this.lastImageAspectRatio = currentImageAspectRatio;
      }
    }, 100);
    this.registerCleanup(() => {
      if (this.configPollInterval !== null) {
        window.clearInterval(this.configPollInterval);
        this.configPollInterval = null;
      }
    });
  }
  updateGridLayout(settings) {
    this.containerEl.style.setProperty("--card-min-width", `${settings.cardSize}px`);
    this.containerEl.style.setProperty("--bases-cms-image-aspect-ratio", String(settings.imageAspectRatio));
    this.lastCardSize = settings.cardSize;
    this.lastImageAspectRatio = settings.imageAspectRatio;
  }
  cleanup() {
    if (this.resizeObserver) {
      this.resizeObserver.disconnect();
      this.resizeObserver = null;
    }
    if (this.windowResizeHandler) {
      window.removeEventListener("resize", this.windowResizeHandler);
      this.windowResizeHandler = null;
    }
    if (this.scrollListener) {
      this.containerEl.removeEventListener("scroll", this.scrollListener);
      this.scrollListener = null;
    }
    if (this.scrollThrottleTimeout !== null) {
      window.clearTimeout(this.scrollThrottleTimeout);
      this.scrollThrottleTimeout = null;
    }
    if (this.configPollInterval !== null) {
      window.clearInterval(this.configPollInterval);
      this.configPollInterval = null;
    }
    this.virtualScrollCallback = null;
  }
  /**
   * Check if virtual scrolling should be enabled based on total entries and settings
   */
  shouldEnableVirtualScroll(totalEntries) {
    const threshold = this.pluginSettings.virtualScrollThreshold;
    return totalEntries > threshold;
  }
  /**
   * Get whether virtual scrolling is currently enabled
   */
  isVirtualScrollEnabled() {
    return this.virtualScrollEnabled;
  }
  /**
   * Update estimated card height based on actual rendered cards
   */
  updateCardMetrics(cardHeight, cardsPerRow) {
    if (cardHeight > 0) {
      this.estimatedCardHeight = cardHeight;
    }
    if (cardsPerRow > 0) {
      this.cardsPerRow = cardsPerRow;
    }
  }
  /**
   * Calculate cards per row based on container width and card min width
   */
  calculateCardsPerRow() {
    const containerWidth = this.containerEl.clientWidth;
    const cardMinWidth = this.lastCardSize || 280;
    const gap = 16;
    return Math.max(1, Math.floor((containerWidth + gap) / (cardMinWidth + gap)));
  }
  /**
   * Calculate which cards should be visible in the viewport
   */
  calculateVisibleRange(totalEntries) {
    const scrollTop = this.containerEl.scrollTop;
    const viewportHeight = this.containerEl.clientHeight;
    const buffer = this.pluginSettings.virtualScrollBuffer;
    this.cardsPerRow = this.calculateCardsPerRow();
    const rowHeight = this.estimatedCardHeight + 16;
    const totalRows = Math.ceil(totalEntries / this.cardsPerRow);
    const firstVisibleRow = Math.max(0, Math.floor(scrollTop / rowHeight) - buffer);
    const lastVisibleRow = Math.min(
      totalRows - 1,
      Math.ceil((scrollTop + viewportHeight) / rowHeight) + buffer
    );
    const startIndex = firstVisibleRow * this.cardsPerRow;
    const endIndex = Math.min(totalEntries - 1, (lastVisibleRow + 1) * this.cardsPerRow - 1);
    const topPadding = firstVisibleRow * rowHeight;
    const bottomPadding = Math.max(0, (totalRows - lastVisibleRow - 1) * rowHeight);
    return {
      startIndex,
      endIndex,
      topPadding,
      bottomPadding
    };
  }
  /**
   * Setup virtual scrolling for large card sets
   */
  setupVirtualScroll(totalEntries, onRangeChange) {
    this.totalEntries = totalEntries;
    this.virtualScrollCallback = onRangeChange;
    if (!this.shouldEnableVirtualScroll(totalEntries)) {
      this.virtualScrollEnabled = false;
      return null;
    }
    this.virtualScrollEnabled = true;
    if (this.scrollListener) {
      this.containerEl.removeEventListener("scroll", this.scrollListener);
      this.scrollListener = null;
    }
    this.scrollListener = () => {
      if (this.scrollThrottleTimeout !== null) {
        return;
      }
      const currentScrollTop = this.containerEl.scrollTop;
      if (Math.abs(currentScrollTop - this.lastScrollTop) < 50) {
        return;
      }
      this.lastScrollTop = currentScrollTop;
      const range = this.calculateVisibleRange(this.totalEntries);
      if (this.virtualScrollCallback) {
        this.virtualScrollCallback(range);
      }
      this.scrollThrottleTimeout = window.setTimeout(() => {
        this.scrollThrottleTimeout = null;
      }, 16);
    };
    this.containerEl.addEventListener("scroll", this.scrollListener, { passive: true });
    this.registerCleanup(() => {
      if (this.scrollListener) {
        this.containerEl.removeEventListener("scroll", this.scrollListener);
        this.scrollListener = null;
      }
    });
    return this.calculateVisibleRange(totalEntries);
  }
  /**
   * Get total scroll height for virtual scrolling
   */
  getVirtualScrollHeight(totalEntries) {
    const totalRows = Math.ceil(totalEntries / this.cardsPerRow);
    const rowHeight = this.estimatedCardHeight + 16;
    return totalRows * rowHeight;
  }
};

// src/utils/view-switch-listener.ts
var ViewSwitchListener = class {
  constructor(containerEl, plugin, config, controller, data, selectedFiles, onSelectionCleared, registerCleanup) {
    this.containerEl = containerEl;
    this.plugin = plugin;
    this.config = config;
    this.controller = controller;
    this.data = data;
    this.selectedFiles = selectedFiles;
    this.onSelectionCleared = onSelectionCleared;
    this.registerCleanup = registerCleanup;
    this.mutationObserver = null;
    this.backupInterval = null;
    this.currentBaseIdentifier = null;
  }
  setup(handleSelectionChange) {
    const startObserving = () => {
    };
    const stopObserving = () => {
      if (this.mutationObserver) {
        this.mutationObserver.disconnect();
        this.mutationObserver = null;
      }
    };
    const getBaseIdentifier = () => {
      var _a, _b, _c, _d;
      try {
        if ((_a = this.config) == null ? void 0 : _a.getName) {
          return this.config.getName();
        }
        if ((_b = this.config) == null ? void 0 : _b.name) {
          return String(this.config.name);
        }
        if (this.controller) {
          if ((_c = this.controller) == null ? void 0 : _c.getBaseName) {
            return this.controller.getBaseName();
          }
          if ((_d = this.controller) == null ? void 0 : _d.baseName) {
            return String(this.controller.baseName);
          }
        }
        if (this.data) {
          if (this.data.baseName) {
            return String(this.data.baseName);
          }
        }
      } catch (e) {
      }
      return null;
    };
    const backupCheck = () => {
      if (this.selectedFiles.size === 0) {
        if (this.backupInterval !== null) {
          window.clearInterval(this.backupInterval);
          this.backupInterval = null;
        }
        return;
      }
      const currentBaseId = getBaseIdentifier();
      if (this.currentBaseIdentifier !== null && currentBaseId !== null && this.currentBaseIdentifier !== currentBaseId) {
        this.selectedFiles.clear();
        this.onSelectionCleared();
        stopObserving();
        if (this.backupInterval !== null) {
          window.clearInterval(this.backupInterval);
          this.backupInterval = null;
        }
        return;
      }
      const allCards = this.containerEl.querySelectorAll(".card[data-path]");
      if (allCards.length === 0) {
        this.selectedFiles.clear();
        this.onSelectionCleared();
      }
    };
    const originalHandleSelectionChange = handleSelectionChange.bind(this);
    const wrappedHandleSelectionChange = (path, selected) => {
      originalHandleSelectionChange(path, selected);
      if (this.selectedFiles.size > 0) {
        if (this.currentBaseIdentifier === null) {
          this.currentBaseIdentifier = getBaseIdentifier();
        }
        startObserving();
        if (this.backupInterval === null) {
          this.backupInterval = this.plugin.registerInterval(window.setInterval(backupCheck, 500));
        }
      } else {
        this.currentBaseIdentifier = null;
        stopObserving();
        if (this.backupInterval !== null) {
          window.clearInterval(this.backupInterval);
          this.backupInterval = null;
        }
      }
    };
    this.registerCleanup(() => {
      stopObserving();
      if (this.backupInterval !== null) {
        window.clearInterval(this.backupInterval);
        this.backupInterval = null;
      }
    });
    return wrappedHandleSelectionChange;
  }
  cleanup() {
    if (this.mutationObserver) {
      this.mutationObserver.disconnect();
      this.mutationObserver = null;
    }
    if (this.backupInterval !== null) {
      window.clearInterval(this.backupInterval);
      this.backupInterval = null;
    }
  }
};

// src/views/cms-view.ts
init_frontmatter_helper();

// src/utils/embedded-view-detector.ts
function isEmbeddedView(containerEl) {
  if (!containerEl) {
    return false;
  }
  const embedParent = containerEl.closest(".markdown-embed, .internal-embed, .markdown-embed-content, .markdown-source-view, .markdown-reading-view");
  return embedParent !== null;
}

// src/views/cms-view.ts
var CMS_VIEW_TYPE = "cms";
var BasesCMSView = class extends import_obsidian23.BasesView {
  constructor(controller, parentContainerEl, plugin) {
    super(controller);
    this.type = CMS_VIEW_TYPE;
    this.selectedFiles = /* @__PURE__ */ new Set();
    this.snippets = {};
    this.images = {};
    this.hasImageAvailable = {};
    this.mdxFrontmatterCache = {};
    this.updateLayoutRef = { current: null };
    this.propertyObservers = [];
    this.bulkToolbar = null;
    this.isRefreshingWithSelection = false;
    this.propertyToggleHandler = null;
    this.viewSwitchListener = null;
    this.settingsPollInterval = null;
    this.lastSettings = null;
    this.lastUpdateId = 0;
    this.lastBaseId = null;
    this.hasAutoSwitched = false;
    this.lastClickedPath = null;
    this.lastVisiblePaths = [];
    this.basesController = controller;
    this.containerEl = parentContainerEl.createDiv("bases-cms-wrapper");
    this.containerEl.style.height = "100%";
    this.containerEl.style.width = "100%";
    this.plugin = plugin;
    const baseId = this.getBaseIdentifier();
    if (baseId) {
      const savedSelection = this.plugin.selections.get(baseId);
      if (savedSelection && savedSelection !== this.selectedFiles) {
        savedSelection.forEach((item) => this.selectedFiles.add(item));
        this.plugin.selections.set(baseId, this.selectedFiles);
      } else if (!savedSelection) {
        this.plugin.selections.set(baseId, this.selectedFiles);
      }
    }
    this.isEmbedded = isEmbeddedView(parentContainerEl);
    this.cardRenderer = new SharedCardRenderer(
      this.app,
      this.plugin,
      this.propertyObservers,
      this.updateLayoutRef,
      void 0,
      // Config not available in constructor
      controller
    );
    this.containerEl.addClass("bases-cms");
    this.containerEl.addClass("bases-cms-container");
    try {
      this.propertyToggleHandler = new PropertyToggleHandler(
        this.app,
        this.config,
        this.plugin.settings,
        () => this.onDataUpdated()
      );
    } catch (e) {
      this.propertyToggleHandler = null;
    }
    try {
      const configToUse = this.config && typeof this.config.get === "function" ? this.config : { get: () => void 0 };
      this.scrollLayoutManager = new ScrollLayoutManager(
        this.containerEl,
        this.app,
        configToUse,
        this.plugin.settings,
        () => this.onDataUpdated(),
        (cleanup) => this.register(cleanup)
      );
    } catch (e) {
      const dummyConfig = { get: () => void 0 };
      this.scrollLayoutManager = new ScrollLayoutManager(
        this.containerEl,
        this.app,
        dummyConfig,
        this.plugin.settings,
        () => this.onDataUpdated(),
        (cleanup) => this.register(cleanup)
      );
    }
    try {
      this.viewSwitchListener = new ViewSwitchListener(
        this.containerEl,
        this.plugin,
        this.config,
        this.controller,
        this.data,
        this.selectedFiles,
        () => this.updateSelectionUI(),
        (cleanup) => this.register(cleanup)
      );
    } catch (e) {
      this.viewSwitchListener = null;
    }
    if (this.viewSwitchListener) {
      const originalHandleSelectionChange = this.handleSelectionChange.bind(this);
      this.handleSelectionChange = this.viewSwitchListener.setup(originalHandleSelectionChange);
    }
  }
  /**
   * Sort entries by property using consistent logic for both MD and MDX files
   */
  async sortEntriesByProperty(entries, propertyName, direction) {
    if (!propertyName || propertyName === "") {
      return entries;
    }
    if (propertyName === "file.ctime" || propertyName === "file.mtime") {
      const isCtime = propertyName === "file.ctime";
      return [...entries].sort((a, b) => {
        const aTime = isCtime ? a.file.stat.ctime : a.file.stat.mtime;
        const bTime = isCtime ? b.file.stat.ctime : b.file.stat.mtime;
        const comparison = aTime - bTime;
        return direction === "desc" ? -comparison : comparison;
      });
    }
    const entriesWithValues = await Promise.all(
      entries.map(async (entry) => {
        const value = await getFirstBasesPropertyValue(entry, propertyName, this.app);
        return { entry, value };
      })
    );
    return entriesWithValues.sort((a, b) => {
      const aVal = a.value;
      const bVal = b.value;
      if (aVal == null && bVal == null) return 0;
      if (aVal == null) return 1;
      if (bVal == null) return -1;
      const aDate = this.parseDateValue(aVal);
      const bDate = this.parseDateValue(bVal);
      if (aDate && bDate) {
        const comparison2 = aDate.getTime() - bDate.getTime();
        return direction === "desc" ? -comparison2 : comparison2;
      }
      if (aDate && !bDate) {
        return direction === "desc" ? -1 : 1;
      }
      if (!aDate && bDate) {
        return direction === "desc" ? 1 : -1;
      }
      const aStr = this.valueToString(aVal);
      const bStr = this.valueToString(bVal);
      const comparison = aStr.localeCompare(bStr);
      return direction === "desc" ? -comparison : comparison;
    }).map((item) => item.entry);
  }
  /**
   * Parse a date value using the same logic as the shared renderer
   */
  parseDateValue(value) {
    if (!value) return null;
    if (typeof value === "object" && "date" in value && value.date instanceof Date) {
      return value.date;
    }
    let data = value;
    if (typeof value === "object" && "data" in value) {
      data = value.data;
    }
    if (!data) return null;
    if (data instanceof Date) {
      return data;
    }
    if (data && typeof data === "object" && "getTime" in data) {
      const dateLike = data;
      try {
        const timestamp = dateLike.getTime();
        if (typeof timestamp === "number" && !isNaN(timestamp)) {
          return new Date(timestamp);
        }
      } catch (e) {
      }
    }
    if (typeof data === "string") {
      const dateStr = data.trim();
      const isoDateStr = dateStr.includes("T") ? dateStr : `${dateStr}T00:00:00`;
      const parsedDate = new Date(isoDateStr);
      if (!isNaN(parsedDate.getTime())) {
        return parsedDate;
      } else {
        const fallbackDate = new Date(dateStr);
        if (!isNaN(fallbackDate.getTime())) {
          return fallbackDate;
        }
      }
    }
    if (typeof data === "number") {
      const parsedDate = new Date(data);
      if (!isNaN(parsedDate.getTime())) {
        return parsedDate;
      }
    }
    return null;
  }
  /**
   * Convert a value to string for comparison
   */
  valueToString(value) {
    if (!value) return "";
    let data = value;
    if (typeof value === "object" && "data" in value) {
      data = value.data;
    }
    if (typeof data === "string") {
      return data;
    } else if (typeof data === "number" || typeof data === "boolean") {
      return String(data);
    } else {
      return "";
    }
  }
  /**
   * Continue processing data after sorting is complete
   */
  async continueDataProcessing(processedGroups, settings, totalEntriesCount, savedScrollTop, updateId) {
    var _a;
    const isStillValid = () => updateId === this.lastUpdateId;
    const allFlatEntries = [];
    for (const processedGroup of processedGroups) {
      allFlatEntries.push(...processedGroup.entries);
    }
    const useVirtualScroll = this.scrollLayoutManager.shouldEnableVirtualScroll(totalEntriesCount);
    let visibleEntries;
    let startIndex = 0;
    let virtualRange = null;
    if (useVirtualScroll) {
      virtualRange = this.scrollLayoutManager.calculateVisibleRange(totalEntriesCount);
      startIndex = virtualRange.startIndex;
      visibleEntries = allFlatEntries.slice(virtualRange.startIndex, virtualRange.endIndex + 1);
    } else {
      const remainingCount = this.scrollLayoutManager.getDisplayedCount();
      visibleEntries = allFlatEntries.slice(0, remainingCount);
    }
    await this.loadContentForEntries(visibleEntries, settings);
    if (!isStillValid()) return;
    if (this.config && !this.containerEl.__cmsInterceptorSetup) {
      try {
        this.containerEl.__cmsInterceptorSetup = true;
        const containerWithConfig = this.containerEl;
        containerWithConfig.__cmsConfig = this.config;
        containerWithConfig.__cmsView = this;
        setupNewNoteInterceptor(
          this.app,
          this.containerEl,
          this.config,
          this.plugin.settings,
          (cleanup) => this.register(cleanup)
        );
      } catch (e) {
        this.containerEl.__cmsInterceptorSetup = true;
      }
    }
    if (!isStillValid()) return;
    this.cardRenderer.basesConfig = this.config;
    if (this.cardRenderer && typeof this.cardRenderer.setMdxFrontmatterCache === "function") {
      this.cardRenderer.setMdxFrontmatterCache(this.mdxFrontmatterCache);
    }
    this.containerEl.empty();
    this.mdxFrontmatterCache = {};
    this.propertyObservers.forEach((obs) => obs.disconnect());
    this.propertyObservers = [];
    const feedEl = this.containerEl.createDiv("bases-cms-grid");
    if (useVirtualScroll && virtualRange && virtualRange.topPadding > 0) {
      const topSpacer = feedEl.createDiv("bases-cms-virtual-spacer");
      topSpacer.style.height = `${virtualRange.topPadding}px`;
      setCssProps(topSpacer, { gridColumn: "1 / -1" });
    }
    let totalCardsRendered = 0;
    const cards = await transformBasesEntries(
      visibleEntries,
      settings,
      "",
      // sortMethod not used in transformBasesEntries
      false,
      this.snippets,
      this.images,
      this.hasImageAvailable,
      this.app,
      this.mdxFrontmatterCache
    );
    if (!isStillValid()) return;
    if (!useVirtualScroll && processedGroups.some((g) => g.group.hasKey())) {
      let displayedSoFar = 0;
      let cardIndex = 0;
      for (const processedGroup of processedGroups) {
        if (displayedSoFar >= this.scrollLayoutManager.getDisplayedCount()) break;
        const entriesToDisplay = Math.min(processedGroup.entries.length, this.scrollLayoutManager.getDisplayedCount() - displayedSoFar);
        if (entriesToDisplay === 0) continue;
        const groupEl = feedEl.createDiv("bases-cms-group");
        if (processedGroup.group.hasKey()) {
          const headerEl = groupEl.createDiv("bases-cms-group-heading");
          const valueEl = headerEl.createDiv("bases-cms-group-value");
          const keyValue = ((_a = processedGroup.group.key) == null ? void 0 : _a.toString()) || "";
          valueEl.setText(keyValue);
        }
        for (let i = 0; i < entriesToDisplay && cardIndex < cards.length; i++) {
          const card = cards[cardIndex];
          const entry = visibleEntries[cardIndex];
          try {
            this.renderCard(groupEl, card, entry, displayedSoFar + i, settings);
            totalCardsRendered++;
          } catch (e) {
          }
          cardIndex++;
        }
        displayedSoFar += entriesToDisplay;
      }
    } else {
      for (let i = 0; i < cards.length; i++) {
        const card = cards[i];
        const entry = visibleEntries[i];
        try {
          this.renderCard(feedEl, card, entry, startIndex + i, settings);
          totalCardsRendered++;
        } catch (e) {
        }
      }
    }
    if (useVirtualScroll && virtualRange && virtualRange.bottomPadding > 0) {
      const bottomSpacer = feedEl.createDiv("bases-cms-virtual-spacer");
      bottomSpacer.style.height = `${virtualRange.bottomPadding}px`;
      setCssProps(bottomSpacer, { gridColumn: "1 / -1" });
    }
    if (!isStillValid()) return;
    if (totalCardsRendered === 0 && totalEntriesCount > 0) {
      throw new Error("No cards were rendered despite having entries. Check card rendering logic.");
    }
    if (totalCardsRendered > 0) {
      const firstCard = feedEl.querySelector(".bases-cms-card");
      if (firstCard) {
        requestAnimationFrame(() => {
          const cardHeight = firstCard.offsetHeight;
          const containerWidth = this.containerEl.clientWidth;
          const cardMinWidth = settings.cardSize || 280;
          const gap = 16;
          const cardsPerRow = Math.max(1, Math.floor((containerWidth + gap) / (cardMinWidth + gap)));
          this.scrollLayoutManager.updateCardMetrics(cardHeight, cardsPerRow);
        });
      }
    }
    if (savedScrollTop > 0) {
      this.containerEl.scrollTop = savedScrollTop;
    }
    if (useVirtualScroll) {
      const cachedAllEntries = allFlatEntries;
      const cachedSettings = settings;
      const cachedUpdateId = updateId;
      this.scrollLayoutManager.setupVirtualScroll(totalEntriesCount, (range) => {
        if (cachedUpdateId === this.lastUpdateId) {
          void this.renderVirtualRange(cachedAllEntries, cachedSettings, range, feedEl);
        }
      });
    } else {
      this.scrollLayoutManager.setupInfiniteScroll(totalEntriesCount);
    }
    this.scrollLayoutManager.setupResizeObserver();
    this.setupSettingsPolling(settings);
    this.updateSelectionUI();
    this.scrollLayoutManager.setIsLoading(false);
  }
  /**
   * Render cards for a specific virtual scroll range
   */
  async renderVirtualRange(allEntries, settings, range, feedEl) {
    const visibleEntries = allEntries.slice(range.startIndex, range.endIndex + 1);
    await this.loadContentForEntries(visibleEntries, settings);
    feedEl.empty();
    if (range.topPadding > 0) {
      const topSpacer = feedEl.createDiv("bases-cms-virtual-spacer");
      topSpacer.style.height = `${range.topPadding}px`;
      setCssProps(topSpacer, { gridColumn: "1 / -1" });
    }
    const cards = await transformBasesEntries(
      visibleEntries,
      settings,
      "",
      false,
      this.snippets,
      this.images,
      this.hasImageAvailable,
      this.app,
      this.mdxFrontmatterCache
    );
    for (let i = 0; i < cards.length; i++) {
      const card = cards[i];
      const entry = visibleEntries[i];
      try {
        this.renderCard(feedEl, card, entry, range.startIndex + i, settings);
      } catch (e) {
      }
    }
    if (range.bottomPadding > 0) {
      const bottomSpacer = feedEl.createDiv("bases-cms-virtual-spacer");
      bottomSpacer.style.height = `${range.bottomPadding}px`;
      setCssProps(bottomSpacer, { gridColumn: "1 / -1" });
    }
    this.updateSelectionUI();
  }
  onDataUpdated() {
    const updateId = ++this.lastUpdateId;
    void (async () => {
      try {
        const isStillValid = () => updateId === this.lastUpdateId;
        if (!this.data) {
          let loadingEl = this.containerEl.querySelector(".bases-cms-loading");
          if (!loadingEl && this.containerEl.children.length === 0) {
            loadingEl = this.containerEl.createDiv("bases-cms-loading");
            loadingEl.setText("Loading...");
            setCssProps(loadingEl, {
              padding: "20px",
              textAlign: "center"
            });
          }
          setTimeout(() => {
            if (isStillValid() && this.data) {
              this.onDataUpdated();
            }
          }, 100);
          return;
        }
        if (!isStillValid()) return;
        const data = this.data;
        const topLevelDefaultView = data == null ? void 0 : data.defaultView;
        const config = this.config;
        const currentViewName = typeof config.getName === "function" ? config.getName() : config.name;
        if (topLevelDefaultView && currentViewName !== topLevelDefaultView) {
          if (!this.hasAutoSwitched) {
            this.hasAutoSwitched = true;
            const controller = this.basesController;
            console.debug("Bases CMS: Default view sync triggered", {
              target: topLevelDefaultView,
              current: currentViewName
            });
            if (typeof controller.selectView === "function") {
              controller.selectView(topLevelDefaultView);
              return;
            } else if (typeof controller.setView === "function") {
              controller.setView(topLevelDefaultView);
              return;
            } else if (typeof controller.switchView === "function") {
              controller.switchView(topLevelDefaultView);
              return;
            }
          }
        }
        const currentBaseId = this.getBaseIdentifier();
        if (this.lastBaseId !== currentBaseId) {
          this.lastBaseId = currentBaseId;
          if (currentBaseId) {
            const savedSelection = this.plugin.selections.get(currentBaseId);
            if (savedSelection && savedSelection !== this.selectedFiles) {
              this.selectedFiles.clear();
              savedSelection.forEach((item) => this.selectedFiles.add(item));
              this.plugin.selections.set(currentBaseId, this.selectedFiles);
            } else if (!savedSelection) {
              this.plugin.selections.set(currentBaseId, this.selectedFiles);
            }
          }
          this.scrollLayoutManager.resetScroll();
          this.snippets = {};
          this.images = {};
          this.hasImageAvailable = {};
          this.mdxFrontmatterCache = {};
        }
        if (!this.data.groupedData || !this.data.data) {
          setTimeout(() => {
            if (isStillValid() && this.data && this.data.groupedData && this.data.data) {
              this.onDataUpdated();
            }
          }, 100);
          return;
        }
        if (!isStillValid()) return;
        const groupedData = this.data.groupedData;
        const allEntries = this.data.data;
        const settings = readCMSSettings(
          this.config,
          this.plugin.settings
        );
        if (!isStillValid()) return;
        const allFlatEntries = Array.isArray(this.data.data) ? this.data.data : [];
        this.lastVisiblePaths = allFlatEntries.map((e) => {
          var _a;
          return (_a = e.file) == null ? void 0 : _a.path;
        }).filter(Boolean);
        if (this.config && typeof this.config.get === "function") {
          try {
            this.scrollLayoutManager.updateConfig(this.config);
          } catch (e) {
          }
        }
        this.scrollLayoutManager.updateGridLayout(settings);
        const savedScrollTop = this.containerEl.scrollTop;
        const sortConfigs = this.config.getSort();
        let processedGroups = groupedData.map((group) => ({
          group,
          entries: [...group.entries]
        }));
        if (sortConfigs && sortConfigs.length > 0) {
          const firstSort = sortConfigs[0];
          const property = firstSort.property;
          const direction = firstSort.direction.toLowerCase();
          if (property && !property.includes("ctime") && !property.includes("mtime")) {
            void (async () => {
              try {
                const allEntries2 = [];
                for (const processedGroup of processedGroups) {
                  allEntries2.push(...processedGroup.entries);
                }
                const sortedEntries = await this.sortEntriesByProperty(allEntries2, property, direction);
                const sortedProcessedGroups = [{
                  group: {
                    hasKey: () => false,
                    key: null,
                    entries: sortedEntries
                  },
                  entries: sortedEntries
                }];
                await this.continueDataProcessing(sortedProcessedGroups, settings, allEntries2.length, savedScrollTop, updateId);
              } catch (error) {
                console.error("Bases CMS: Error during custom sorting:", error);
                await this.continueDataProcessing(processedGroups, settings, allEntries.length, savedScrollTop, updateId);
              }
            })();
            return;
          }
        }
        await this.continueDataProcessing(processedGroups, settings, allEntries.length, savedScrollTop, updateId);
      } catch (error) {
        try {
          this.scrollLayoutManager.setIsLoading(false);
        } catch (e) {
        }
        if (this.containerEl && this.containerEl.isConnected) {
          this.containerEl.empty();
          const errorEl = this.containerEl.createDiv("bases-cms-error");
          errorEl.setText("Error loading view. Check console for details.");
          setCssProps(errorEl, {
            padding: "20px",
            textAlign: "center",
            color: "var(--text-error)",
            margin: "20px"
          });
        }
        console.error("Bases CMS: Error in onDataUpdated:", error);
      }
    })();
  }
  /**
   * Get a unique identifier for the current base configuration
   */
  getBaseIdentifier() {
    try {
      const controller = this.basesController;
      if (controller) {
        if (typeof controller.getBaseName === "function") return controller.getBaseName();
        if (controller.baseName) return controller.baseName;
      }
      if (this.config && typeof this.config.getName === "function") {
        return this.config.getName();
      }
      if (this.config && this.config.name) {
        return String(this.config.name);
      }
      if (this.data && this.data.baseName) {
        return String(this.data.baseName);
      }
    } catch (e) {
    }
    return null;
  }
  /**
   * Setup polling to detect settings changes and refresh view
   */
  setupSettingsPolling(initialSettings) {
    if (this.settingsPollInterval !== null) {
      return;
    }
    this.lastSettings = {
      descriptionProperty: initialSettings.descriptionProperty,
      showTextPreview: initialSettings.showTextPreview,
      fallbackToContent: initialSettings.fallbackToContent,
      truncatePreviewProperty: initialSettings.truncatePreviewProperty,
      imageProperty: initialSettings.imageProperty,
      imageFormat: initialSettings.imageFormat,
      fallbackToEmbeds: initialSettings.fallbackToEmbeds,
      propertyDisplay1: initialSettings.propertyDisplay1,
      propertyDisplay2: initialSettings.propertyDisplay2,
      propertyDisplay3: initialSettings.propertyDisplay3,
      propertyDisplay4: initialSettings.propertyDisplay4,
      propertyDisplay5: initialSettings.propertyDisplay5,
      propertyDisplay6: initialSettings.propertyDisplay6,
      propertyDisplay7: initialSettings.propertyDisplay7,
      propertyDisplay8: initialSettings.propertyDisplay8,
      propertyDisplay9: initialSettings.propertyDisplay9,
      propertyDisplay10: initialSettings.propertyDisplay10,
      propertyDisplay11: initialSettings.propertyDisplay11,
      propertyDisplay12: initialSettings.propertyDisplay12,
      propertyDisplay13: initialSettings.propertyDisplay13,
      propertyDisplay14: initialSettings.propertyDisplay14
    };
    this.settingsPollInterval = window.setInterval(() => {
      if (!this.config || typeof this.config.get !== "function") {
        return;
      }
      const currentSettings = readCMSSettings(
        this.config,
        this.plugin.settings
      );
      if (!this.lastSettings) {
        return;
      }
      const settingsChanged = this.lastSettings.descriptionProperty !== currentSettings.descriptionProperty || this.lastSettings.showTextPreview !== currentSettings.showTextPreview || this.lastSettings.fallbackToContent !== currentSettings.fallbackToContent || this.lastSettings.truncatePreviewProperty !== currentSettings.truncatePreviewProperty || this.lastSettings.imageProperty !== currentSettings.imageProperty || this.lastSettings.imageFormat !== currentSettings.imageFormat || this.lastSettings.fallbackToEmbeds !== currentSettings.fallbackToEmbeds || this.lastSettings.propertyDisplay1 !== currentSettings.propertyDisplay1 || this.lastSettings.propertyDisplay2 !== currentSettings.propertyDisplay2 || this.lastSettings.propertyDisplay3 !== currentSettings.propertyDisplay3 || this.lastSettings.propertyDisplay4 !== currentSettings.propertyDisplay4 || this.lastSettings.propertyDisplay5 !== currentSettings.propertyDisplay5 || this.lastSettings.propertyDisplay6 !== currentSettings.propertyDisplay6 || this.lastSettings.propertyDisplay7 !== currentSettings.propertyDisplay7 || this.lastSettings.propertyDisplay8 !== currentSettings.propertyDisplay8 || this.lastSettings.propertyDisplay9 !== currentSettings.propertyDisplay9 || this.lastSettings.propertyDisplay10 !== currentSettings.propertyDisplay10 || this.lastSettings.propertyDisplay11 !== currentSettings.propertyDisplay11 || this.lastSettings.propertyDisplay12 !== currentSettings.propertyDisplay12 || this.lastSettings.propertyDisplay13 !== currentSettings.propertyDisplay13 || this.lastSettings.propertyDisplay14 !== currentSettings.propertyDisplay14;
      if (settingsChanged) {
        if (this.lastSettings.descriptionProperty !== currentSettings.descriptionProperty || this.lastSettings.showTextPreview !== currentSettings.showTextPreview || this.lastSettings.fallbackToContent !== currentSettings.fallbackToContent || this.lastSettings.truncatePreviewProperty !== currentSettings.truncatePreviewProperty) {
          this.snippets = {};
        }
        if (this.lastSettings.imageProperty !== currentSettings.imageProperty || this.lastSettings.imageFormat !== currentSettings.imageFormat || this.lastSettings.fallbackToEmbeds !== currentSettings.fallbackToEmbeds) {
          this.images = {};
          this.hasImageAvailable = {};
        }
        this.lastSettings = {
          descriptionProperty: currentSettings.descriptionProperty,
          showTextPreview: currentSettings.showTextPreview,
          fallbackToContent: currentSettings.fallbackToContent,
          truncatePreviewProperty: currentSettings.truncatePreviewProperty,
          imageProperty: currentSettings.imageProperty,
          imageFormat: currentSettings.imageFormat,
          fallbackToEmbeds: currentSettings.fallbackToEmbeds,
          propertyDisplay1: currentSettings.propertyDisplay1,
          propertyDisplay2: currentSettings.propertyDisplay2,
          propertyDisplay3: currentSettings.propertyDisplay3,
          propertyDisplay4: currentSettings.propertyDisplay4,
          propertyDisplay5: currentSettings.propertyDisplay5,
          propertyDisplay6: currentSettings.propertyDisplay6,
          propertyDisplay7: currentSettings.propertyDisplay7,
          propertyDisplay8: currentSettings.propertyDisplay8,
          propertyDisplay9: currentSettings.propertyDisplay9,
          propertyDisplay10: currentSettings.propertyDisplay10,
          propertyDisplay11: currentSettings.propertyDisplay11,
          propertyDisplay12: currentSettings.propertyDisplay12,
          propertyDisplay13: currentSettings.propertyDisplay13,
          propertyDisplay14: currentSettings.propertyDisplay14
        };
        this.onDataUpdated();
      }
    }, 100);
    this.register(() => {
      if (this.settingsPollInterval !== null) {
        window.clearInterval(this.settingsPollInterval);
        this.settingsPollInterval = null;
      }
    });
  }
  /**
   * Preload MDX frontmatter for all visible entries to prevent flashing
   * This ensures all MDX data is available synchronously during card transformation
   */
  async preloadMdxFrontmatter(entries) {
    const mdxEntries = entries.filter((entry) => {
      const file = this.app.vault.getAbstractFileByPath(entry.file.path);
      return file instanceof import_obsidian23.TFile && file.extension === "mdx" && !(entry.file.path in this.mdxFrontmatterCache);
    });
    if (mdxEntries.length === 0) {
      return;
    }
    await Promise.all(
      mdxEntries.map(async (entry) => {
        const file = this.app.vault.getAbstractFileByPath(entry.file.path);
        if (file instanceof import_obsidian23.TFile) {
          try {
            const frontmatter = await getFileFrontmatter(this.app, file);
            this.mdxFrontmatterCache[entry.file.path] = frontmatter;
          } catch (error) {
            console.error(`Bases CMS: Error preloading properties for ${entry.file.path}:`, error);
            this.mdxFrontmatterCache[entry.file.path] = null;
          }
        }
      })
    );
  }
  async loadContentForEntries(entries, settings) {
    if (settings.showTextPreview) {
      const snippetEntriesPromises = entries.filter((entry) => !(entry.file.path in this.snippets)).map(async (entry) => {
        const file = this.app.vault.getAbstractFileByPath(entry.file.path);
        if (!(file instanceof import_obsidian23.TFile)) return null;
        const descValue = await getFirstBasesPropertyValue(entry, settings.descriptionProperty, this.app);
        return {
          path: entry.file.path,
          file,
          descriptionData: descValue == null ? void 0 : descValue.data
        };
      });
      const snippetEntries = (await Promise.all(snippetEntriesPromises)).filter((e) => e !== null);
      if (snippetEntries.length > 0) {
        await loadSnippetsForEntries(
          snippetEntries,
          settings.fallbackToContent,
          false,
          this.app,
          this.snippets,
          settings.truncatePreviewProperty
        );
      }
    }
    if (settings.imageFormat !== "none") {
      const imageEntriesPromises = entries.filter((entry) => !(entry.file.path in this.images)).map(async (entry) => {
        const file = this.app.vault.getAbstractFileByPath(entry.file.path);
        if (!(file instanceof import_obsidian23.TFile)) return null;
        const imagePropertyValues = await getAllBasesImagePropertyValues(entry, settings.imageProperty, this.app);
        return {
          path: entry.file.path,
          file,
          imagePropertyValues
        };
      });
      const imageEntries = (await Promise.all(imageEntriesPromises)).filter((e) => e !== null);
      if (imageEntries.length > 0) {
        await loadImagesForEntries(
          imageEntries,
          settings.fallbackToEmbeds,
          this.app,
          this.images,
          this.hasImageAvailable
        );
      }
    }
  }
  /**
   * Direct delete handler for context menu - deletes a single file without selection
   */
  getDirectDeleteHandler(filePath) {
    return async () => {
      const { prepareDeletionPreview: prepareDeletionPreview2, executeSmartDeletion: executeSmartDeletion2 } = await Promise.resolve().then(() => (init_smart_deletion(), smart_deletion_exports));
      const { DeletionPreviewModal: DeletionPreviewModal2 } = await Promise.resolve().then(() => (init_deletion_preview(), deletion_preview_exports));
      if (this.plugin.settings.confirmDeletions) {
        const preview = await prepareDeletionPreview2(
          this.app,
          [filePath],
          this.plugin.settings
        );
        const modal = new DeletionPreviewModal2(
          this.app,
          preview,
          () => {
            this.onDataUpdated();
          }
        );
        modal.open();
      } else {
        const preview = await prepareDeletionPreview2(
          this.app,
          [filePath],
          this.plugin.settings
        );
        await executeSmartDeletion2(this.app, preview);
        this.onDataUpdated();
      }
    };
  }
  renderCard(container, card, entry, index, settings) {
    const isSelected = this.selectedFiles.has(card.path);
    return this.cardRenderer.renderCard(
      container,
      card,
      entry,
      settings,
      this,
      isSelected,
      (path, selected, shiftKey) => {
        this.handleSelectionChange(path, selected, shiftKey);
      },
      (path, property, value) => {
        void this.handlePropertyToggle(path, property, value);
      },
      { handleDelete: this.getDirectDeleteHandler(card.path) }
    );
  }
  /**
   * Update card image when it becomes available
   * Called asynchronously after images load
   */
  updateCardImage(path, imageUrl) {
    var _a;
    const cardEl = this.containerEl.querySelector(`.card[data-path="${path}"]`);
    if (!cardEl) return;
    const url = Array.isArray(imageUrl) ? imageUrl[0] : imageUrl;
    if (!url) return;
    let imageEmbedContainer = cardEl.querySelector(".image-embed");
    if (!imageEmbedContainer) {
      const placeholder = cardEl.querySelector(".card-cover-placeholder, .card-thumbnail-placeholder");
      const isThumbnail = cardEl.classList.contains("image-format-thumbnail");
      const isCover = cardEl.classList.contains("image-format-cover");
      if (placeholder) {
        const existingBadge = placeholder.querySelector(".card-status-badge");
        const imageClassName = placeholder.classList.contains("card-cover-placeholder") ? "card-cover" : "card-thumbnail";
        const imageEl = (_a = placeholder.parentElement) == null ? void 0 : _a.createDiv(imageClassName);
        if (imageEl) {
          imageEmbedContainer = imageEl.createDiv("image-embed");
          if (existingBadge) {
            imageEl.appendChild(existingBadge);
          }
          placeholder.remove();
        }
      } else if (isThumbnail) {
        const contentContainer = cardEl.querySelector(".card-content");
        if (contentContainer) {
          const textWrapper = contentContainer.querySelector(".card-text-wrapper");
          const imageEl = textWrapper ? contentContainer.insertBefore(contentContainer.createDiv("card-thumbnail"), textWrapper) : contentContainer.createDiv("card-thumbnail");
          imageEmbedContainer = imageEl.createDiv("image-embed");
        }
      } else if (isCover) {
        const contentContainer = cardEl.querySelector(".card-content");
        if (contentContainer) {
          const imageEl = contentContainer.createDiv("card-cover");
          imageEmbedContainer = imageEl.createDiv("image-embed");
        }
      }
    }
    if (imageEmbedContainer) {
      void (async () => {
        const finalUrl = await convertGifToStatic(url, this.plugin.settings.forceStaticGifImages);
        imageEmbedContainer.style.backgroundImage = `url("${finalUrl}")`;
      })();
      imageEmbedContainer.style.backgroundImage = `url("${url}")`;
      setCssProps(imageEmbedContainer, {
        backgroundSize: "cover",
        backgroundPosition: "center center",
        backgroundRepeat: "no-repeat"
      });
    }
  }
  getSortMethod() {
    const sortConfigs = this.config.getSort();
    if (sortConfigs && sortConfigs.length > 0) {
      const firstSort = sortConfigs[0];
      const property = firstSort.property;
      const direction = firstSort.direction.toLowerCase();
      if (property.includes("ctime")) {
        return `ctime-${direction}`;
      }
      if (property.includes("mtime")) {
        return `mtime-${direction}`;
      }
    }
    return "mtime-desc";
  }
  handleSelectionChange(path, selected, shiftKey) {
    if (shiftKey && this.lastClickedPath && this.lastClickedPath !== path) {
      const start = this.lastVisiblePaths.indexOf(this.lastClickedPath);
      const end = this.lastVisiblePaths.indexOf(path);
      if (start !== -1 && end !== -1) {
        const min = Math.min(start, end);
        const max = Math.max(start, end);
        const pathsToToggle = this.lastVisiblePaths.slice(min, max + 1);
        pathsToToggle.forEach((p) => {
          if (selected) {
            this.selectedFiles.add(p);
          } else {
            this.selectedFiles.delete(p);
          }
        });
      }
    } else {
      if (selected) {
        this.selectedFiles.add(path);
      } else {
        this.selectedFiles.delete(path);
      }
    }
    this.lastClickedPath = path;
    this.updateSelectionUI();
    if (this.selectedFiles.size === 0) {
      if (this.bulkToolbar) {
        this.bulkToolbar.hide();
        const toolbarEl = this.containerEl.querySelector(".bases-cms-bulk-toolbar");
        if (toolbarEl instanceof HTMLElement) {
          toolbarEl.removeClass("bases-cms-bulk-toolbar-visible");
          toolbarEl.addClass("bases-cms-bulk-toolbar-hidden");
        }
      }
    }
  }
  async handlePropertyToggle(path, property, value) {
    if (this.propertyToggleHandler) {
      await this.propertyToggleHandler.handlePropertyToggle(path, property, value);
    }
  }
  selectAll() {
    this.lastVisiblePaths.forEach((path) => {
      this.selectedFiles.add(path);
    });
    this.updateSelectionUI();
  }
  deselectAll() {
    const cards = this.containerEl.querySelectorAll(".bases-cms-card.selected");
    cards.forEach((cardEl) => {
      cardEl.removeClass("selected");
      const checkbox = cardEl.querySelector('input[type="checkbox"].selection-checkbox');
      if (checkbox) {
        checkbox.checked = false;
      }
    });
    this.selectedFiles.clear();
    this.lastClickedPath = null;
    this.updateSelectionUI();
  }
  /**
   * Update checkbox and class for a specific card in the DOM
   */
  updateCardCheckboxState(path, selected) {
    const cardEl = this.containerEl.querySelector(`.bases-cms-card[data-path="${path}"]`);
    if (cardEl instanceof HTMLElement) {
      if (selected) {
        cardEl.addClass("selected");
      } else {
        cardEl.removeClass("selected");
      }
      const checkbox = cardEl.querySelector('input[type="checkbox"].selection-checkbox');
      if (checkbox) {
        checkbox.checked = selected;
      }
    }
  }
  /**
   * Refresh the toolbar when settings change
   * Called from settings tab when toolbar button visibility settings are updated
   */
  refreshToolbar() {
    if (this.bulkToolbar) {
      const currentCount = this.selectedFiles.size;
      this.bulkToolbar.recreate();
      if (currentCount > 0) {
        this.bulkToolbar.updateCount(currentCount);
      }
    }
  }
  updateSelectionUI() {
    const cards = this.containerEl.querySelectorAll(".card");
    cards.forEach((cardEl) => {
      const path = cardEl.getAttribute("data-path");
      const checkbox = cardEl.querySelector('input[type="checkbox"].selection-checkbox');
      if (path) {
        const isSelected = this.selectedFiles.has(path);
        if (isSelected) {
          cardEl.addClass("selected");
        } else {
          cardEl.removeClass("selected");
        }
        if (checkbox) {
          checkbox.checked = isSelected;
        }
      }
    });
    if (this.selectedFiles.size > 0) {
      const orphanedToolbars = document.querySelectorAll(".bases-cms-bulk-toolbar");
      orphanedToolbars.forEach((toolbar) => {
        const toolbarInstance = toolbar.__bulkToolbarInstance;
        if (!toolbarInstance || toolbarInstance !== this.bulkToolbar) {
          toolbar.remove();
        }
      });
      if (!this.bulkToolbar) {
        const settings = readCMSSettings(
          this.config,
          this.plugin.settings
        );
        this.bulkToolbar = new BulkToolbar(
          this.app,
          this.plugin,
          this.containerEl,
          () => Array.from(this.selectedFiles),
          () => {
            this.selectedFiles.clear();
            this.updateSelectionUI();
          },
          () => {
            const selectedPaths = Array.from(this.selectedFiles);
            this.isRefreshingWithSelection = true;
            if (this.bulkToolbar && selectedPaths.length > 0) {
              this.bulkToolbar.show();
            }
            this.onDataUpdated();
            window.setTimeout(() => {
              selectedPaths.forEach((path) => {
                if (this.app.vault.getAbstractFileByPath(path)) {
                  this.selectedFiles.add(path);
                }
              });
              this.isRefreshingWithSelection = false;
              this.updateSelectionUI();
              if (this.selectedFiles.size > 0 && this.bulkToolbar) {
                this.bulkToolbar.show();
                this.bulkToolbar.updateCount(this.selectedFiles.size);
              }
              window.setTimeout(() => {
                if (this.selectedFiles.size > 0 && this.bulkToolbar) {
                  this.bulkToolbar.show();
                  this.bulkToolbar.updateCount(this.selectedFiles.size);
                }
              }, 100);
            }, 250);
          },
          () => {
            this.selectAll();
          },
          settings
        );
      } else {
        const settings = readCMSSettings(
          this.config,
          this.plugin.settings
        );
        this.bulkToolbar.updateSettings(settings);
      }
      this.bulkToolbar.updateCount(this.selectedFiles.size);
      this.bulkToolbar.show();
    } else {
      if (this.bulkToolbar && !this.isRefreshingWithSelection) {
        this.bulkToolbar.hide();
        const toolbarEl = this.containerEl.querySelector(".bases-cms-bulk-toolbar");
        if (toolbarEl instanceof HTMLElement) {
          toolbarEl.removeClass("bases-cms-bulk-toolbar-visible");
          toolbarEl.addClass("bases-cms-bulk-toolbar-hidden");
        }
      }
    }
  }
  async onClose() {
    this.scrollLayoutManager.cleanup();
    if (this.viewSwitchListener) {
      this.viewSwitchListener.cleanup();
    }
    if (this.settingsPollInterval !== null) {
      window.clearInterval(this.settingsPollInterval);
      this.settingsPollInterval = null;
    }
    this.propertyObservers.forEach((obs) => obs.disconnect());
    this.propertyObservers = [];
    if (this.bulkToolbar) {
      this.bulkToolbar.destroy();
    }
    const orphanedToolbars = document.querySelectorAll(".bases-cms-bulk-toolbar");
    orphanedToolbars.forEach((toolbar) => toolbar.remove());
    const pluginWithMethod = this.plugin;
    if (pluginWithMethod && typeof pluginWithMethod.removeView === "function") {
      pluginWithMethod.removeView(this);
    }
  }
  /**
   * Override new note creation to use custom location if configured
   */
  async onNew() {
    var _a;
    const settings = readCMSSettings(
      this.config,
      this.plugin.settings
    );
    if (settings.customizeNewButton) {
      try {
        const locationInput = ((_a = settings.newNoteLocation) == null ? void 0 : _a.trim()) || "";
        if (locationInput === "") {
          const vaultConfig = this.app.vault.config;
          const newFileLocation = (vaultConfig == null ? void 0 : vaultConfig.newFileLocation) || "folder";
          const newFileFolderPath = (vaultConfig == null ? void 0 : vaultConfig.newFileFolderPath) || "";
          let filePath = "Untitled.md";
          if (newFileLocation === "folder" && newFileFolderPath) {
            filePath = `${newFileFolderPath}/Untitled.md`;
          } else if (newFileLocation === "current") {
            const activeFile = this.app.workspace.getActiveFile();
            if (activeFile && activeFile.parent) {
              filePath = `${activeFile.parent.path}/Untitled.md`;
            }
          } else if (newFileLocation === "root") {
            filePath = "Untitled.md";
          }
          const file = await this.app.vault.create(filePath, "");
          await this.app.workspace.openLinkText(file.path, "", false);
          return true;
        }
        if (locationInput === "/" || locationInput.replace(/\//g, "") === "") {
          const newFile = await this.app.vault.create("Untitled.md", "");
          await this.app.workspace.openLinkText(newFile.path, "", false);
          return true;
        }
        const folderPath = locationInput.replace(/^\/+|\/+$/g, "");
        let folder = this.app.vault.getAbstractFileByPath(folderPath);
        if (!folder || !("children" in folder)) {
          await this.app.vault.createFolder(folderPath);
          folder = this.app.vault.getAbstractFileByPath(folderPath);
        }
        if (folder && "children" in folder) {
          const newFile = await this.app.vault.create(`${folderPath}/Untitled.md`, "");
          await this.app.workspace.openLinkText(newFile.path, "", false);
          return true;
        }
      } catch (e) {
      }
    }
    return false;
  }
};

// src/types.ts
var DEFAULT_SETTINGS = {
  confirmBulkOperations: true,
  deleteParentFolder: false,
  deleteParentFolderFilename: "index",
  deleteUniqueAttachments: false,
  confirmDeletions: true,
  useHomeIcon: false,
  enableQuickEdit: false,
  quickEditCommand: "",
  quickEditCommandName: "",
  quickEditIcon: "pencil-line",
  quickEditOpenFile: false,
  showToolbarSelectAll: true,
  showToolbarClear: true,
  showToolbarDraft: true,
  showToolbarPublish: true,
  showToolbarTags: true,
  showToolbarSet: true,
  showToolbarRemove: true,
  showToolbarDelete: true,
  forceStaticGifImages: false,
  embeddedViewRefreshDebounceMs: 250,
  virtualScrollThreshold: 100,
  // Enable virtual scrolling for >100 cards
  virtualScrollBuffer: 20,
  // Render 20 cards above/below viewport
  migrationBasesCmsToCmsDone: false
};

// src/utils/view-registration.ts
function registerBasesCMSView(plugin, retries = 5) {
  try {
    const basesPlugin = plugin;
    if (typeof basesPlugin.registerBasesView === "function") {
      const viewOptionsFn = getCMSViewOptions2();
      const viewConfig = {
        name: "CMS",
        icon: plugin.settings.useHomeIcon ? "lucide-home" : "lucide-blocks",
        factory: (controller, containerEl) => {
          const view = new BasesCMSView(controller, containerEl, plugin);
          const pluginWithViews = plugin;
          if (pluginWithViews.activeViews) {
            pluginWithViews.activeViews.add(view);
          }
          if (view.isEmbedded) {
            let retryCount = 0;
            const maxRetries = 8;
            const baseDelay = 250;
            const tryRefresh = () => {
              try {
                const containerEl2 = view.containerEl;
                if (!containerEl2 || !containerEl2.isConnected) {
                  return;
                }
                const viewData = view.data;
                const hasData = viewData && Array.isArray(viewData.data) && viewData.data.length > 0 && viewData.groupedData;
                if (typeof view.onDataUpdated === "function") {
                  view.onDataUpdated();
                }
                if (!hasData && retryCount < maxRetries) {
                  retryCount++;
                  const delay = baseDelay + retryCount * 100;
                  window.setTimeout(tryRefresh, delay);
                }
              } catch (error) {
                console.warn("Bases CMS: Error refreshing newly created embedded view:", error);
              }
            };
            window.setTimeout(tryRefresh, baseDelay);
          }
          return view;
        },
        options: () => viewOptionsFn(CMS_VIEW_TYPE)
      };
      basesPlugin.registerBasesView(CMS_VIEW_TYPE, viewConfig);
    } else if (retries > 0) {
      const pluginWithTimeout = plugin;
      const registrationTimeout = pluginWithTimeout.registrationTimeout;
      if (registrationTimeout !== null && registrationTimeout !== void 0) {
        window.clearTimeout(registrationTimeout);
      }
      pluginWithTimeout.registrationTimeout = window.setTimeout(() => {
        pluginWithTimeout.registrationTimeout = null;
        registerBasesCMSView(plugin, retries - 1);
      }, 200);
    } else {
      console.warn("Bases CMS: registerBasesView not available. Is Bases plugin installed?");
    }
  } catch (error) {
    console.error("Bases CMS: Error registering view:", error);
  }
}
function getCMSViewOptions2() {
  const { getCMSViewOptions: getCMSViewOptions3 } = (init_settings_schema(), __toCommonJS(settings_schema_exports));
  return getCMSViewOptions3;
}

// src/utils/migration.ts
async function migrateBasesCmsToCms(app) {
  const files = app.vault.getFiles();
  let migratedCount = 0;
  console.log(`Bases CMS: Starting safe vault scan for 'bases-cms' types...`);
  for (const file of files) {
    const ext = file.extension.toLowerCase();
    if (ext === "md" || ext === "base" || ext === "mdx") {
      try {
        const content = await app.vault.read(file);
        if (content.toLowerCase().includes("bases-cms")) {
          const newContent = content.replace(/(type[ \t]*:[ \t]*["']?)bases-cms\b/gi, "$1cms");
          if (newContent !== content) {
            await app.vault.modify(file, newContent);
            migratedCount++;
            console.log(`Bases CMS: Migrated ${file.path}`);
          }
        }
      } catch (error) {
        console.error(`Bases CMS: Error reading ${file.path}:`, error);
      }
    }
  }
  console.log(`Bases CMS Migration: Updated ${migratedCount} files.`);
  return migratedCount;
}

// src/main.ts
var import_obsidian25 = require("obsidian");
var BasesCMSPlugin = class extends import_obsidian24.Plugin {
  constructor() {
    super(...arguments);
    this.activeViews = /* @__PURE__ */ new Set();
    this.registrationTimeout = null;
    this.refreshEmbeddedViewsTimeout = null;
    this.selections = /* @__PURE__ */ new Map();
  }
  async onload() {
    await this.loadSettings();
    this.app.workspace.onLayoutReady(async () => {
      if (!this.settings.migrationBasesCmsToCmsDone) {
        const migratedCount = await migrateBasesCmsToCms(this.app);
        this.settings.migrationBasesCmsToCmsDone = true;
        await this.saveSettings();
        if (migratedCount > 0) {
          new import_obsidian25.Notice(`Bases CMS: Successfully migrated ${migratedCount} files to new 'cms' view type.`);
        }
      }
    });
    this.addCommand({
      id: "run-bases-cms-migration",
      name: "Run Vault Migration (Convert bases-cms to cms)",
      callback: async () => {
        const migratedCount = await migrateBasesCmsToCms(this.app);
        new import_obsidian25.Notice(`Bases CMS: Migration complete. ${migratedCount} files updated.`);
      }
    });
    this.addSettingTab(new BasesCMSSettingTab(this.app, this));
    registerBasesCMSView(this);
    this.addCommand({
      id: "select-all",
      name: "Select all visible cards",
      checkCallback: (checking) => {
        const activeView = this.getActiveCMSView();
        if (activeView) {
          if (!checking) {
            activeView.selectAll();
          }
          return true;
        }
        return false;
      }
    });
    this.addCommand({
      id: "deselect-all",
      name: "Deselect all cards",
      checkCallback: (checking) => {
        const activeView = this.getActiveCMSView();
        if (activeView) {
          if (!checking) {
            activeView.deselectAll();
          }
          return true;
        }
        return false;
      }
    });
    this.registerEvent(
      this.app.workspace.on("active-leaf-change", () => {
        this.refreshEmbeddedViews();
      })
    );
    this.registerEvent(
      this.app.workspace.on("file-open", () => {
        this.refreshEmbeddedViews();
      })
    );
  }
  onunload() {
    if (this.registrationTimeout !== null) {
      window.clearTimeout(this.registrationTimeout);
      this.registrationTimeout = null;
    }
    if (this.refreshEmbeddedViewsTimeout !== null) {
      window.clearTimeout(this.refreshEmbeddedViewsTimeout);
      this.refreshEmbeddedViewsTimeout = null;
    }
    this.activeViews.clear();
  }
  async loadSettings() {
    const data = await this.loadData();
    this.settings = Object.assign({}, DEFAULT_SETTINGS, data);
  }
  /**
   * Robustly find the active CMS view
   */
  getActiveCMSView() {
    try {
      const obsidianActiveView = this.app.workspace.getActiveViewOfType(BasesCMSView);
      if (obsidianActiveView && obsidianActiveView instanceof BasesCMSView) {
        return obsidianActiveView;
      }
    } catch (e) {
    }
    const activeLeaf = this.app.workspace.activeLeaf;
    if (!activeLeaf) return null;
    for (const view of this.activeViews) {
      try {
        if (view.type !== CMS_VIEW_TYPE) continue;
        const containerEl = view.containerEl;
        if (containerEl && containerEl.isConnected) {
          if (activeLeaf.view.containerEl.contains(containerEl)) {
            return view;
          }
        }
      } catch (e) {
      }
    }
    return null;
  }
  async saveSettings() {
    await this.saveData(this.settings);
  }
  /**
   * Clean up stale view references that are no longer in the DOM
   * Returns the number of views removed
   */
  cleanupStaleViews() {
    const viewsToRemove = [];
    this.activeViews.forEach((view) => {
      const containerEl = view.containerEl;
      if (!containerEl || !containerEl.parentElement) {
        viewsToRemove.push(view);
      }
    });
    viewsToRemove.forEach((view) => this.activeViews.delete(view));
    return viewsToRemove.length;
  }
  /**
   * Refresh toolbars in all active CMS views
   */
  refreshAllToolbars() {
    this.cleanupStaleViews();
    this.activeViews.forEach((view) => {
      if (view && typeof view.refreshToolbar === "function") {
        view.refreshToolbar();
      }
    });
  }
  /**
   * Remove a view from tracking when it's closed
   */
  removeView(view) {
    this.activeViews.delete(view);
  }
  /**
   * Refresh all embedded CMS views when the active file changes
   * This ensures embedded views update their filters when using this.file properties
   * Debounced to avoid excessive refreshes when switching files quickly
   */
  refreshEmbeddedViews() {
    if (this.refreshEmbeddedViewsTimeout !== null) {
      window.clearTimeout(this.refreshEmbeddedViewsTimeout);
    }
    this.refreshEmbeddedViewsTimeout = window.setTimeout(() => {
      this.refreshEmbeddedViewsTimeout = null;
      this.cleanupStaleViews();
      let refreshedCount = 0;
      this.activeViews.forEach((view) => {
        if (view.isEmbedded) {
          try {
            const containerEl = view.containerEl;
            if (containerEl && containerEl.isConnected) {
              if (typeof view.onDataUpdated === "function") {
                view.onDataUpdated();
                refreshedCount++;
              }
            }
          } catch (error) {
            console.warn("Bases CMS: Error refreshing embedded view:", error);
          }
        }
      });
      if (refreshedCount > 0) {
        console.debug(`Bases CMS: Refreshed ${refreshedCount} embedded view(s) after active file change`);
      }
    }, this.settings.embeddedViewRefreshDebounceMs);
  }
};
//# sourceMappingURL=data:application/json;base64,[encoded data, 685956 characters]
