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

var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/utils/VaultPathHelper.ts
var VaultPathHelper_exports = {};
__export(VaultPathHelper_exports, {
  getVaultPath: () => getVaultPath,
  resolveProjectRoot: () => resolveProjectRoot,
  toVaultRelative: () => toVaultRelative
});
function getVaultPath(app) {
  var _a;
  const adapter = app.vault.adapter;
  if (typeof adapter.getBasePath === "function") {
    try {
      const p2 = adapter.getBasePath();
      return p2 ? path.normalize(p2) : null;
    } catch (e) {
    }
  }
  const p = (_a = adapter.basePath) != null ? _a : adapter.path;
  return p ? path.normalize(p) : null;
}
function toVaultRelative(app, absolutePath) {
  const vaultPath = getVaultPath(app);
  if (!vaultPath) return absolutePath;
  try {
    const rel = path.relative(vaultPath, path.normalize(absolutePath));
    return rel.split(path.sep).join("/") || ".";
  } catch (e) {
    return absolutePath;
  }
}
function resolveProjectRoot(app, projectRoot) {
  const vaultPath = getVaultPath(app);
  if (!vaultPath || !(projectRoot == null ? void 0 : projectRoot.trim())) return null;
  const trimmed = projectRoot.trim();
  if (path.isAbsolute(trimmed)) return path.normalize(trimmed);
  return path.resolve(vaultPath, trimmed);
}
var path;
var init_VaultPathHelper = __esm({
  "src/utils/VaultPathHelper.ts"() {
    path = __toESM(require("path"), 1);
  }
});

// src/utils/ProjectRootResolver.ts
var ProjectRootResolver_exports = {};
__export(ProjectRootResolver_exports, {
  resolveProjectRoot: () => resolveProjectRoot2,
  resolveProjectRootFromVaultPath: () => resolveProjectRootFromVaultPath
});
function resolveProjectRoot2(app, projectRoot) {
  const vaultPath = getVaultPath(app);
  if (!vaultPath || !(projectRoot == null ? void 0 : projectRoot.trim())) return null;
  const trimmed = projectRoot.trim();
  if (path7.isAbsolute(trimmed)) return path7.normalize(trimmed);
  return path7.resolve(vaultPath, trimmed);
}
function resolveProjectRootFromVaultPath(vaultPath, projectRoot) {
  if (!projectRoot || !vaultPath) return null;
  const trimmed = projectRoot.trim();
  if (!trimmed) return null;
  return path7.isAbsolute(trimmed) ? path7.normalize(trimmed) : path7.resolve(vaultPath, trimmed);
}
var path7;
var init_ProjectRootResolver = __esm({
  "src/utils/ProjectRootResolver.ts"() {
    path7 = __toESM(require("path"), 1);
    init_VaultPathHelper();
  }
});

// src/utils/GitManager.ts
var GitManager_exports = {};
__export(GitManager_exports, {
  GitManager: () => GitManager
});
var import_obsidian15, import_child_process, import_util, path9, fs6, execAsync, GitManager;
var init_GitManager = __esm({
  "src/utils/GitManager.ts"() {
    import_obsidian15 = require("obsidian");
    import_child_process = require("child_process");
    import_util = require("util");
    path9 = __toESM(require("path"), 1);
    fs6 = __toESM(require("fs"), 1);
    execAsync = (0, import_util.promisify)(import_child_process.exec);
    GitManager = class {
      /**
       * Checks if a directory is a Git repository.
       */
      static async isRepo(projectRoot) {
        if (!projectRoot) return false;
        try {
          const absolutePath = path9.resolve(projectRoot);
          const dotGitPath = path9.join(absolutePath, ".git");
          const exists = fs6.existsSync(dotGitPath);
          console.debug("GitManager.isRepo check:", {
            projectRoot,
            absolutePath,
            dotGitPath,
            exists
          });
          if (!fs6.existsSync(absolutePath)) return false;
          return exists;
        } catch (error) {
          console.error("GitManager.isRepo error:", error);
          return false;
        }
      }
      /**
       * Initializes a new Git repository at the given path.
       */
      static async initRepo(projectRoot) {
        await execAsync("git init", { cwd: projectRoot });
      }
      /**
       * Sets the remote URL for the repository.
       */
      static async setRemote(projectRoot, url, remoteName = "origin") {
        try {
          await execAsync(`git remote add ${remoteName} ${url}`, { cwd: projectRoot });
        } catch (error) {
          if (error instanceof Error && error.message.includes("already exists")) {
            await execAsync(`git remote set-url ${remoteName} ${url}`, { cwd: projectRoot });
          } else {
            throw error;
          }
        }
      }
      /**
       * Gets the remote URL for the repository, scrubbing any tokens for security.
       */
      static async getRemoteUrl(projectRoot, remoteName = "origin") {
        try {
          const { stdout } = await execAsync(`git remote get-url ${remoteName}`, { cwd: projectRoot });
          let url = stdout.trim() || null;
          if (url && url.includes("@github.com")) {
            url = url.replace(/https:\/\/.*@github\.com/, "https://github.com");
          }
          return url;
        } catch (e) {
          return null;
        }
      }
      /**
       * Gets the current local branch name.
       */
      static async getCurrentBranch(projectRoot) {
        try {
          const { stdout } = await execAsync("git branch --show-current", { cwd: projectRoot });
          return stdout.trim() || "main";
        } catch (e) {
          return "main";
        }
      }
      /**
       * Creates an initial commit and pushes to the remote, setting the upstream.
       */
      static async initialCommitAndPush(projectRoot, branch, remoteName = "origin", token) {
        try {
          console.debug("GitManager.initialCommitAndPush: starting", { projectRoot, branch, remoteName, hasToken: !!token });
          try {
            await execAsync("git config user.name", { cwd: projectRoot });
          } catch (e) {
            console.debug("GitManager: Setting local git user.name");
            await execAsync('git config user.name "Vault CMS User"', { cwd: projectRoot });
            await execAsync('git config user.email "vault-cms@example.com"', { cwd: projectRoot });
          }
          await execAsync("git add .", { cwd: projectRoot });
          try {
            await execAsync('git commit -m "Initial commit from Vault CMS"', { cwd: projectRoot });
          } catch (commitError) {
            const errorMessage = commitError instanceof Error ? commitError.message : String(commitError);
            if (errorMessage.includes("nothing to commit") || errorMessage.includes("working tree clean")) {
              console.debug("GitManager: Nothing to commit");
            } else {
              throw commitError;
            }
          }
          await execAsync(`git branch -M ${branch}`, { cwd: projectRoot });
          console.debug("GitManager: Pushing to remote...");
          if (token) {
            const remoteUrl = await this.getRemoteUrl(projectRoot, remoteName);
            if (remoteUrl && remoteUrl.startsWith("https://")) {
              const authenticatedUrl = remoteUrl.replace("https://", `https://${token}@`);
              const escaped = authenticatedUrl.replace(/"/g, '\\"');
              const original = remoteUrl.replace(/"/g, '\\"');
              await execAsync(
                `git -c "url.${escaped}.insteadOf=${original}" push -u ${remoteName} ${branch}`,
                { cwd: projectRoot, maxBuffer: 10 * 1024 * 1024 }
              );
            } else {
              await execAsync(`git push -u ${remoteName} ${branch}`, { cwd: projectRoot, maxBuffer: 10 * 1024 * 1024 });
            }
          } else {
            await execAsync(`git push -u ${remoteName} ${branch}`, { cwd: projectRoot, maxBuffer: 10 * 1024 * 1024 });
          }
          try {
            const { stdout: trackingInfo } = await execAsync(`git rev-parse --abbrev-ref ${branch}@{upstream}`, { cwd: projectRoot });
            console.debug("GitManager: Push verified. Upstream:", trackingInfo.trim());
          } catch (e) {
            throw new Error(`Push failed. The repository was created but files could not be uploaded. Try pushing manually with: git push -u origin ${branch}`);
          }
        } catch (error) {
          console.error("GitManager.initialCommitAndPush failed:", error);
          throw error;
        }
      }
      /**
       * Creates a new repository on GitHub.
       */
      static async createGitHubRepo(token, name, description, isPrivate) {
        var _a, _b;
        const params = {
          url: "https://api.github.com/user/repos",
          method: "POST",
          headers: {
            "Authorization": `token ${token}`,
            "Accept": "application/vnd.github.v3+json",
            "Content-Type": "application/json"
          },
          body: JSON.stringify({
            name,
            description,
            private: isPrivate
          })
        };
        try {
          const response = await (0, import_obsidian15.requestUrl)(params);
          if (response.status === 422) {
            throw new Error("Repository name already exists on your GitHub account.");
          }
          if (response.status !== 201) {
            let errorMessage = `GitHub API Error: ${response.status}`;
            try {
              const errorData = typeof response.json === "string" ? JSON.parse(response.json) : response.json;
              if (errorData == null ? void 0 : errorData.message) {
                errorMessage = `GitHub API Error: ${errorData.message}`;
                if ((_b = (_a = errorData.errors) == null ? void 0 : _a[0]) == null ? void 0 : _b.message) {
                  errorMessage += ` (${errorData.errors[0].message})`;
                }
              }
            } catch (e) {
            }
            throw new Error(errorMessage);
          }
          return response.json;
        } catch (error) {
          if (error instanceof Error && (error.message.includes("already exists") || error.message.includes("GitHub API Error"))) {
            throw error;
          }
          const message = error instanceof Error ? error.message : String(error);
          if (message.includes("422") || message.includes("already exists")) {
            throw new Error("Repository name already exists on your GitHub account.");
          }
          throw error;
        }
      }
      /**
       * Verifies if the GitHub PAT is valid and returns the username.
       */
      static async verifyToken(token) {
        var _a;
        try {
          const params = {
            url: "https://api.github.com/user",
            method: "GET",
            headers: {
              "Authorization": `token ${token}`,
              "Accept": "application/vnd.github.v3+json"
            }
          };
          const response = await (0, import_obsidian15.requestUrl)(params);
          if (response.status === 200) {
            return ((_a = response.json) == null ? void 0 : _a.login) || null;
          }
          return null;
        } catch (e) {
          return null;
        }
      }
    };
  }
});

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

// src/settings.ts
var DEFAULT_SETTINGS = {
  projectRoot: "",
  configFilePath: "",
  contentTypes: [],
  frontmatterProperties: {},
  attachmentHandlingMode: "subfolder",
  attachmentFolderName: void 0,
  preset: "vanilla",
  presetName: "",
  presetsRepo: "davidvkimball/vaultcms-presets",
  enableEditingToolbar: false,
  enableExtendedFileTypes: false,
  enabledPlugins: [],
  disabledPlugins: [],
  theme: "",
  basesCMSConfig: {
    views: []
  },
  astroComposerConfig: {
    customContentTypes: [],
    defaultTemplate: "",
    configFilePath: "",
    terminalProjectRootPath: ""
  },
  seoConfig: {
    titleProperty: "title",
    descriptionProperty: void 0,
    scanDirectories: "",
    useFilenameAsTitle: false,
    useFilenameAsSlug: true,
    enableMDXSupport: false
  },
  propertyOverFileName: {
    propertyKey: "title"
  },
  imageManager: {},
  homeBase: {},
  explorerFocus: {},
  ignoreConfig: {
    gitIgnoreConfigured: false,
    viteIgnoreConfigured: false
  },
  gitConfig: {
    enabled: false,
    isPrivate: true,
    branchName: "main",
    autoConfigureObsidianGit: true
  },
  deploymentPlatform: "",
  resolvePublicImages: false,
  runWizardOnStartup: true,
  wizardCompleted: false
};

// src/ui/SettingsTab.ts
var import_obsidian27 = require("obsidian");

// src/ui/SetupWizardModal.ts
var import_obsidian23 = require("obsidian");

// src/utils/ImageManagerConfig.ts
var import_obsidian = require("obsidian");
var ImageManagerConfigurator = class {
  constructor(app) {
    this.app = app;
  }
  async loadConfig() {
    var _a;
    const pluginId = "image-manager";
    try {
      const plugins = this.app.plugins;
      const imageManagerPlugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a[pluginId];
      if (imageManagerPlugin && imageManagerPlugin.settings) {
        return imageManagerPlugin.settings;
      }
    } catch (error) {
      console.warn("Failed to load Image Manager config from plugin API:", error);
    }
    return await this.loadConfigFallback();
  }
  async loadConfigFallback() {
    const pluginId = "image-manager";
    const configDir = this.app.vault.configDir;
    const pluginDataPath = `${configDir}/plugins/${pluginId}/data.json`;
    const dataFile = this.app.vault.getAbstractFileByPath(pluginDataPath);
    if (dataFile && dataFile instanceof import_obsidian.TFile) {
      try {
        const existingData = JSON.parse(await this.app.vault.read(dataFile));
        return existingData;
      } catch (error) {
        console.warn("Failed to parse existing Image Manager data.json:", error);
        return {};
      }
    }
    return {};
  }
  async saveConfig(config) {
    var _a;
    const pluginId = "image-manager";
    try {
      const plugins = this.app.plugins;
      const imageManagerPlugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a[pluginId];
      if (imageManagerPlugin && imageManagerPlugin.settings) {
        const pluginSettings = imageManagerPlugin.settings;
        Object.assign(pluginSettings, config);
        if (typeof imageManagerPlugin.saveSettings === "function") {
          await imageManagerPlugin.saveSettings();
          console.debug("ImageManagerConfig: Successfully saved via plugin.saveSettings()");
          return;
        }
      }
      await this.saveConfigFallback(config);
    } catch (error) {
      console.error("Failed to save Image Manager config:", error);
      try {
        await this.saveConfigFallback(config);
      } catch (fallbackError) {
        console.error("Failed to save Image Manager config via fallback:", fallbackError);
      }
    }
  }
  async saveConfigFallback(config) {
    const pluginId = "image-manager";
    const configDir = this.app.vault.configDir;
    const pluginDataPath = `${configDir}/plugins/${pluginId}/data.json`;
    let existingData = {};
    const dataFile = this.app.vault.getAbstractFileByPath(pluginDataPath);
    if (dataFile && dataFile instanceof import_obsidian.TFile) {
      try {
        existingData = JSON.parse(await this.app.vault.read(dataFile));
      } catch (error) {
        console.warn("Failed to parse existing Image Manager data.json, starting fresh:", error);
        existingData = {};
      }
    }
    const mergedData = {
      ...existingData,
      ...config
    };
    if (dataFile && dataFile instanceof import_obsidian.TFile) {
      await this.app.vault.modify(dataFile, JSON.stringify(mergedData, null, 2));
    } else {
      const pluginDir = `${configDir}/plugins/${pluginId}`;
      const pluginDirFile = this.app.vault.getAbstractFileByPath(pluginDir);
      if (!pluginDirFile) {
        try {
          await this.app.vault.createFolder(pluginDir);
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : String(error);
          if (errorMessage && !errorMessage.includes("already exists") && !errorMessage.includes("File already exists")) {
            throw error;
          }
        }
      }
      try {
        await this.app.vault.create(pluginDataPath, JSON.stringify(mergedData, null, 2));
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        if (errorMessage && (errorMessage.includes("already exists") || errorMessage.includes("File already exists"))) {
          const retryFile = this.app.vault.getAbstractFileByPath(pluginDataPath);
          if (retryFile instanceof import_obsidian.TFile) {
            await this.app.vault.modify(retryFile, JSON.stringify(mergedData, null, 2));
          } else {
            throw error;
          }
        } else {
          throw error;
        }
      }
    }
  }
  /**
   * Resolves the image property from the wizard state and syncs it to Image Manager settings
   */
  async resolveAndSyncImageProperty(state) {
    var _a, _b;
    const contentTypes = state.contentTypes || [];
    const frontmatterProperties = state.frontmatterProperties || {};
    const defaultTypeId = state.defaultContentTypeId;
    let resolvedImageProperty;
    if (defaultTypeId && ((_a = frontmatterProperties[defaultTypeId]) == null ? void 0 : _a.imageProperty)) {
      resolvedImageProperty = frontmatterProperties[defaultTypeId].imageProperty;
    }
    if (!resolvedImageProperty) {
      for (const type of contentTypes) {
        if ((_b = frontmatterProperties[type.id]) == null ? void 0 : _b.imageProperty) {
          resolvedImageProperty = frontmatterProperties[type.id].imageProperty;
          break;
        }
      }
    }
    if (resolvedImageProperty) {
      const config = await this.loadConfig();
      config.defaultPropertyName = resolvedImageProperty;
      if (config.banner) {
        if (typeof config.banner === "object") {
          if (!config.banner.properties) {
            config.banner.properties = {};
          }
          config.banner.properties.imageProperty = resolvedImageProperty;
        }
      } else {
        config.banner = {
          properties: {
            imageProperty: resolvedImageProperty
          }
        };
      }
      await this.saveConfig(config);
      if (state.imageManager) {
        state.imageManager.defaultPropertyName = resolvedImageProperty;
        if (state.imageManager.banner) {
          if (typeof state.imageManager.banner === "object") {
            if (!state.imageManager.banner.properties) {
              state.imageManager.banner.properties = {};
            }
            state.imageManager.banner.properties.imageProperty = resolvedImageProperty;
          }
        } else {
          state.imageManager.banner = {
            properties: {
              imageProperty: resolvedImageProperty
            }
          };
        }
      }
      console.debug(`ImageManagerConfigurator: Synced image property "${resolvedImageProperty}" to Image Manager and state`);
    }
  }
};

// src/utils/HomeBaseConfig.ts
var import_obsidian2 = require("obsidian");
var HomeBaseConfigurator = class {
  constructor(app) {
    this.app = app;
  }
  async loadConfig() {
    var _a;
    const pluginId = "home-base";
    try {
      const plugins = this.app.plugins;
      const homeBasePlugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a[pluginId];
      if (homeBasePlugin && homeBasePlugin.settings) {
        return homeBasePlugin.settings;
      }
    } catch (error) {
      console.warn("Failed to load Home Base config from plugin API:", error);
    }
    return await this.loadConfigFallback();
  }
  async loadConfigFallback() {
    const pluginId = "home-base";
    const configDir = this.app.vault.configDir;
    const pluginDataPath = `${configDir}/plugins/${pluginId}/data.json`;
    const dataFile = this.app.vault.getAbstractFileByPath(pluginDataPath);
    if (dataFile && dataFile instanceof import_obsidian2.TFile) {
      try {
        const existingData = JSON.parse(await this.app.vault.read(dataFile));
        return existingData;
      } catch (error) {
        console.warn("Failed to parse existing Home Base data.json:", error);
        return {};
      }
    }
    return {};
  }
  async saveConfig(config) {
    var _a;
    const pluginId = "home-base";
    try {
      const plugins = this.app.plugins;
      const homeBasePlugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a[pluginId];
      if (homeBasePlugin && homeBasePlugin.settings) {
        const pluginSettings = homeBasePlugin.settings;
        Object.assign(pluginSettings, config);
        if (typeof homeBasePlugin.saveSettings === "function") {
          await homeBasePlugin.saveSettings();
          console.debug("HomeBaseConfig: Successfully saved via plugin.saveSettings()");
          return;
        }
      }
      await this.saveConfigFallback(config);
    } catch (error) {
      console.error("Failed to save Home Base config:", error);
      try {
        await this.saveConfigFallback(config);
      } catch (fallbackError) {
        console.error("Failed to save Home Base config via fallback:", fallbackError);
      }
    }
  }
  async saveConfigFallback(config) {
    const pluginId = "home-base";
    const configDir = this.app.vault.configDir;
    const pluginDataPath = `${configDir}/plugins/${pluginId}/data.json`;
    let existingData = {};
    const dataFile = this.app.vault.getAbstractFileByPath(pluginDataPath);
    if (dataFile && dataFile instanceof import_obsidian2.TFile) {
      try {
        existingData = JSON.parse(await this.app.vault.read(dataFile));
      } catch (error) {
        console.warn("Failed to parse existing Home Base data.json, starting fresh:", error);
        existingData = {};
      }
    }
    const mergedData = {
      ...existingData,
      ...config
    };
    if (dataFile && dataFile instanceof import_obsidian2.TFile) {
      await this.app.vault.modify(dataFile, JSON.stringify(mergedData, null, 2));
    } else {
      const pluginDir = `${configDir}/plugins/${pluginId}`;
      const pluginDirFile = this.app.vault.getAbstractFileByPath(pluginDir);
      if (!pluginDirFile) {
        try {
          await this.app.vault.createFolder(pluginDir);
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : String(error);
          if (errorMessage && !errorMessage.includes("already exists") && !errorMessage.includes("File already exists")) {
            throw error;
          }
        }
      }
      try {
        await this.app.vault.create(pluginDataPath, JSON.stringify(mergedData, null, 2));
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        if (errorMessage && (errorMessage.includes("already exists") || errorMessage.includes("File already exists"))) {
          const retryFile = this.app.vault.getAbstractFileByPath(pluginDataPath);
          if (retryFile instanceof import_obsidian2.TFile) {
            await this.app.vault.modify(retryFile, JSON.stringify(mergedData, null, 2));
          } else {
            throw error;
          }
        } else {
          throw error;
        }
      }
    }
  }
};

// src/utils/ExplorerFocusConfig.ts
var import_obsidian3 = require("obsidian");
var ExplorerFocusConfigurator = class {
  constructor(app) {
    this.app = app;
  }
  async saveConfig(config) {
    var _a;
    const pluginId = "explorer-focus";
    try {
      const plugins = this.app.plugins;
      const explorerFocusPlugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a[pluginId];
      if (explorerFocusPlugin && explorerFocusPlugin.settings) {
        console.debug("ExplorerFocusConfig: Using plugin.settings API");
        const settings = explorerFocusPlugin.settings;
        for (const [key, value] of Object.entries(config)) {
          settings[key] = value;
        }
        if (typeof explorerFocusPlugin.saveSettings === "function") {
          await explorerFocusPlugin.saveSettings();
          console.debug("ExplorerFocusConfig: Successfully saved via plugin.saveSettings()");
          return;
        }
      }
      console.debug("ExplorerFocusConfig: Plugin API not available, using fallback file method");
      await this.saveConfigFallback(config);
    } catch (error) {
      console.error("Failed to save Explorer Focus config:", error);
      await this.saveConfigFallback(config);
    }
  }
  async loadConfig() {
    const pluginId = "explorer-focus";
    const configDir = this.app.vault.configDir;
    const pluginDataPath = `${configDir}/plugins/${pluginId}/data.json`;
    try {
      const dataFile = this.app.vault.getAbstractFileByPath(pluginDataPath);
      if (dataFile instanceof import_obsidian3.TFile) {
        const content = await this.app.vault.read(dataFile);
        return JSON.parse(content);
      }
    } catch (error) {
      console.warn("Failed to load Explorer Focus config:", error);
    }
    return null;
  }
  async saveConfigFallback(config) {
    const pluginId = "explorer-focus";
    const configDir = this.app.vault.configDir;
    const pluginDataPath = `${configDir}/plugins/${pluginId}/data.json`;
    let existingData = {};
    const dataFile = this.app.vault.getAbstractFileByPath(pluginDataPath);
    if (dataFile instanceof import_obsidian3.TFile) {
      try {
        existingData = JSON.parse(await this.app.vault.read(dataFile));
      } catch (error) {
        console.warn("Failed to parse existing explorer-focus data.json:", error);
      }
    }
    const mergedData = {
      ...existingData,
      ...config
    };
    const pluginDir = `${configDir}/plugins/${pluginId}`;
    const pluginDirFile = this.app.vault.getAbstractFileByPath(pluginDir);
    if (!pluginDirFile) {
      try {
        await this.app.vault.createFolder(pluginDir);
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        if (errorMessage && !errorMessage.includes("already exists") && !errorMessage.includes("File already exists") && !errorMessage.includes("Folder already exists")) {
          throw error;
        }
      }
    }
    const content = JSON.stringify(mergedData, null, 2);
    if (dataFile instanceof import_obsidian3.TFile) {
      await this.app.vault.modify(dataFile, content);
    } else {
      await this.app.vault.create(pluginDataPath, content);
    }
    console.debug("ExplorerFocusConfig: Successfully saved explorer-focus config via fallback");
  }
};

// src/utils/EditingToolbarConfig.ts
var import_obsidian4 = require("obsidian");
var EditingToolbarConfigurator = class {
  constructor(app) {
    this.app = app;
  }
  /**
   * Enable/disable the editing toolbar visibility
   */
  async toggleVisibility(app, enable) {
    var _a;
    console.debug(`EditingToolbarConfig: toggleVisibility called with enable=${enable}`);
    try {
      const plugins = app.plugins;
      if (!plugins) {
        console.warn("EditingToolbarConfig: Plugins API not available");
        return;
      }
      const editingToolbarPlugin = (_a = plugins.plugins) == null ? void 0 : _a["editing-toolbar"];
      if (!editingToolbarPlugin) {
        console.warn("EditingToolbarConfig: Editing Toolbar plugin not found");
        return;
      }
      console.debug(`EditingToolbarConfig: Editing Toolbar plugin found, enabled=${editingToolbarPlugin.enabled}`);
      console.debug(`EditingToolbarConfig: Plugin settings available:`, !!editingToolbarPlugin.settings);
      if (editingToolbarPlugin.settings) {
        console.debug(`EditingToolbarConfig: Current cMenuVisibility:`, editingToolbarPlugin.settings.cMenuVisibility);
      }
      if (editingToolbarPlugin.settings && typeof editingToolbarPlugin.saveSettings === "function") {
        console.debug("EditingToolbarConfig: Using plugin.saveSettings() method");
        const oldValue = editingToolbarPlugin.settings.cMenuVisibility;
        editingToolbarPlugin.settings.cMenuVisibility = enable;
        console.debug(`EditingToolbarConfig: Set cMenuVisibility from ${oldValue} to ${enable}`);
        await editingToolbarPlugin.saveSettings();
        console.debug("EditingToolbarConfig: Successfully saved editing-toolbar via plugin.saveSettings()");
        console.debug("EditingToolbarConfig: Dispatching editingToolbar-NewCommand event");
        window.dispatchEvent(new Event("editingToolbar-NewCommand"));
        if (enable) {
          console.debug("EditingToolbarConfig: Waiting for settings to persist...");
          await new Promise((resolve11) => setTimeout(resolve11, 500));
          if (typeof editingToolbarPlugin.loadSettings === "function") {
            console.debug("EditingToolbarConfig: Reloading editing toolbar plugin settings");
            await editingToolbarPlugin.loadSettings();
          }
          if (typeof editingToolbarPlugin.refresh === "function") {
            console.debug("EditingToolbarConfig: Refreshing editing toolbar plugin");
            editingToolbarPlugin.refresh();
          }
        }
        return;
      } else {
        console.debug("EditingToolbarConfig: Plugin saveSettings not available, using fallback");
      }
      await this.toggleVisibilityFallback(app, enable);
    } catch (error) {
      console.error("EditingToolbarConfig: Failed to toggle editing toolbar plugin:", error);
      try {
        await this.toggleVisibilityFallback(app, enable);
      } catch (fallbackError) {
        console.error("EditingToolbarConfig: Failed to toggle editing toolbar via fallback:", fallbackError);
      }
    }
  }
  async toggleVisibilityFallback(app, enable) {
    const pluginId = "editing-toolbar";
    const configDir = app.vault.configDir;
    const pluginDataPath = `${configDir}/plugins/${pluginId}/data.json`;
    let existingData = {};
    const dataFile = app.vault.getAbstractFileByPath(pluginDataPath);
    if (dataFile instanceof import_obsidian4.TFile) {
      try {
        existingData = JSON.parse(await app.vault.read(dataFile));
      } catch (error) {
        console.warn("Failed to parse existing editing-toolbar data.json, starting fresh:", error);
        existingData = {};
      }
    }
    existingData.cMenuVisibility = enable;
    if (dataFile instanceof import_obsidian4.TFile) {
      await app.vault.modify(dataFile, JSON.stringify(existingData, null, 2));
      console.debug("EditingToolbarConfig: Successfully saved editing-toolbar via file modify");
    } else {
      const pluginDir = `${configDir}/plugins/${pluginId}`;
      const pluginDirFile = app.vault.getAbstractFileByPath(pluginDir);
      if (!pluginDirFile) {
        try {
          await app.vault.createFolder(pluginDir);
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : String(error);
          if (errorMessage && !errorMessage.includes("already exists") && !errorMessage.includes("File already exists") && !errorMessage.includes("Folder already exists")) {
            throw error;
          }
        }
      }
      try {
        await app.vault.create(pluginDataPath, JSON.stringify(existingData, null, 2));
        console.debug("EditingToolbarConfig: Successfully created editing-toolbar data.json");
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        if (errorMessage && (errorMessage.includes("already exists") || errorMessage.includes("File already exists"))) {
          const retryFile = app.vault.getAbstractFileByPath(pluginDataPath);
          if (retryFile instanceof import_obsidian4.TFile) {
            await app.vault.modify(retryFile, JSON.stringify(existingData, null, 2));
            console.debug("EditingToolbarConfig: Successfully saved editing-toolbar via retry modify");
          } else {
            await new Promise((resolve11) => setTimeout(resolve11, 200));
            const retryFile2 = app.vault.getAbstractFileByPath(pluginDataPath);
            if (retryFile2 instanceof import_obsidian4.TFile) {
              await app.vault.modify(retryFile2, JSON.stringify(existingData, null, 2));
              console.debug("EditingToolbarConfig: Successfully saved editing-toolbar via delayed retry modify");
            } else {
              throw error;
            }
          }
        } else {
          throw error;
        }
      }
    }
  }
  /**
   * Get the current visibility of the editing toolbar
   */
  async getVisibility(app) {
    var _a;
    try {
      const plugins = app.plugins;
      const editingToolbarPlugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a["editing-toolbar"];
      if (editingToolbarPlugin == null ? void 0 : editingToolbarPlugin.settings) {
        return editingToolbarPlugin.settings.cMenuVisibility;
      }
      const configDir = app.vault.configDir;
      const pluginDataPath = `${configDir}/plugins/editing-toolbar/data.json`;
      const dataFile = app.vault.getAbstractFileByPath(pluginDataPath);
      if (dataFile instanceof import_obsidian4.TFile) {
        const existingData = JSON.parse(await app.vault.read(dataFile));
        return existingData.cMenuVisibility;
      }
    } catch (error) {
      console.warn("EditingToolbarConfig: Failed to get editing toolbar visibility:", error);
    }
    return void 0;
  }
};

// src/ui/wizard/WizardStateManager.ts
var WizardStateManager = class {
  constructor(plugin) {
    this.plugin = plugin;
    this.editingToolbarConfigurator = new EditingToolbarConfigurator(plugin.app);
    const settings = plugin.settings;
    this.state = this.initializeState(settings);
  }
  initializeState(settings) {
    var _a, _b, _c, _d;
    const savedProjectDetection = settings.projectRoot && settings.configFilePath ? {
      projectRoot: settings.projectRoot,
      configFilePath: settings.configFilePath,
      vaultLocation: "content"
    } : void 0;
    let attachmentHandlingMode = settings.attachmentHandlingMode;
    let attachmentFolderName = settings.attachmentFolderName;
    if (!attachmentHandlingMode) {
      const vault = this.plugin.app.vault;
      const obsidianConfig = vault.config;
      const folderPath = obsidianConfig == null ? void 0 : obsidianConfig.attachmentFolderPath;
      if (folderPath !== void 0) {
        if (folderPath === "" || folderPath === "./" || folderPath === ".") {
          attachmentHandlingMode = "same-folder";
          attachmentFolderName = void 0;
        } else if (folderPath.startsWith("./")) {
          attachmentHandlingMode = "subfolder";
          attachmentFolderName = folderPath.substring(2);
        } else {
          attachmentHandlingMode = "specified-folder";
          attachmentFolderName = folderPath;
        }
      }
    }
    return {
      currentStep: 0,
      projectDetection: savedProjectDetection,
      contentTypes: settings.contentTypes || [],
      frontmatterProperties: settings.frontmatterProperties || {},
      defaultContentTypeId: settings.defaultContentTypeId,
      attachmentHandlingMode: attachmentHandlingMode || "subfolder",
      attachmentFolderName,
      resolvePublicImages: (_a = settings.resolvePublicImages) != null ? _a : false,
      preset: settings.preset || "vanilla",
      presetName: settings.presetName || "",
      presetsRepo: settings.presetsRepo || "davidvkimball/vaultcms-presets",
      enableEditingToolbar: (_c = (_b = settings.enableEditingToolbar) != null ? _b : settings.enableWYSIWYG) != null ? _c : false,
      enableMdxSupport: settings.enableMdxSupport,
      enableExtendedFileTypes: settings.enableExtendedFileTypes,
      enabledPlugins: settings.enabledPlugins || [],
      disabledPlugins: settings.disabledPlugins || [],
      theme: settings.theme || "",
      basesCMSConfig: settings.basesCMSConfig || { views: [] },
      astroComposerConfig: settings.astroComposerConfig || {
        customContentTypes: [],
        defaultTemplate: "",
        configFilePath: "",
        terminalProjectRootPath: ""
      },
      seoConfig: settings.seoConfig || {
        titleProperty: "title",
        scanDirectories: "",
        useFilenameAsTitle: false,
        useFilenameAsSlug: true,
        enableMDXSupport: (_d = settings.enableMdxSupport) != null ? _d : false
      },
      propertyOverFileName: settings.propertyOverFileName || { propertyKey: "title" },
      imageManager: settings.imageManager || {},
      homeBase: settings.homeBase || {},
      explorerFocus: settings.explorerFocus || {},
      ignoreConfig: settings.ignoreConfig || { gitIgnoreConfigured: false, viteIgnoreConfigured: false },
      gitConfig: settings.gitConfig || { enabled: false, autoConfigureObsidianGit: true }
    };
  }
  getState() {
    return this.state;
  }
  updateState(updates) {
    this.state = { ...this.state, ...updates };
  }
  setState(updates) {
    this.state = { ...this.state, ...updates };
  }
  nextStep(totalSteps) {
    if (this.state.currentStep < totalSteps - 1) {
      this.state.currentStep++;
    }
  }
  previousStep() {
    if (this.state.currentStep > 0) {
      this.state.currentStep--;
    }
  }
  canGoNext(totalSteps) {
    return this.state.currentStep < totalSteps - 1;
  }
  canGoPrevious() {
    return this.state.currentStep > 0;
  }
  getProgress(totalSteps) {
    if (totalSteps === 0) return 0;
    return (this.state.currentStep + 1) / totalSteps * 100;
  }
  async refreshState() {
    var _a, _b, _c;
    const settings = this.plugin.settings;
    if (settings.projectRoot && settings.configFilePath) {
      this.state.projectDetection = {
        projectRoot: settings.projectRoot,
        configFilePath: settings.configFilePath,
        vaultLocation: "content"
      };
    } else {
      this.state.projectDetection = void 0;
    }
    this.state.contentTypes = settings.contentTypes || [];
    this.state.frontmatterProperties = settings.frontmatterProperties || {};
    this.state.defaultContentTypeId = settings.defaultContentTypeId;
    this.state.resolvePublicImages = (_a = settings.resolvePublicImages) != null ? _a : false;
    if (settings.attachmentHandlingMode) {
      this.state.attachmentHandlingMode = settings.attachmentHandlingMode;
      this.state.attachmentFolderName = settings.attachmentFolderName;
    } else {
      const vault = this.plugin.app.vault;
      const obsidianConfig = vault.config;
      const folderPath = obsidianConfig == null ? void 0 : obsidianConfig.attachmentFolderPath;
      if (folderPath !== void 0) {
        if (folderPath === "" || folderPath === "./" || folderPath === ".") {
          this.state.attachmentHandlingMode = "same-folder";
          this.state.attachmentFolderName = void 0;
        } else if (folderPath.startsWith("./")) {
          this.state.attachmentHandlingMode = "subfolder";
          this.state.attachmentFolderName = folderPath.substring(2);
        } else {
          this.state.attachmentHandlingMode = "specified-folder";
          this.state.attachmentFolderName = folderPath;
        }
      } else {
        this.state.attachmentHandlingMode = "subfolder";
        this.state.attachmentFolderName = void 0;
      }
    }
    this.state.preset = settings.preset || "vanilla";
    this.state.presetName = settings.presetName || "";
    this.state.presetsRepo = settings.presetsRepo || "davidvkimball/vaultcms-presets";
    const actualVisibility = await this.editingToolbarConfigurator.getVisibility(this.plugin.app);
    if (actualVisibility !== void 0) {
      this.state.enableEditingToolbar = actualVisibility;
    } else {
      this.state.enableEditingToolbar = (_c = (_b = settings.enableEditingToolbar) != null ? _b : settings.enableWYSIWYG) != null ? _c : false;
    }
    this.state.enableMdxSupport = settings.enableMdxSupport;
    this.state.enableExtendedFileTypes = settings.enableExtendedFileTypes;
    this.state.enabledPlugins = settings.enabledPlugins || [];
    this.state.disabledPlugins = settings.disabledPlugins || [];
    this.state.theme = settings.theme || "";
    this.state.basesCMSConfig = settings.basesCMSConfig || { views: [] };
    this.state.astroComposerConfig = settings.astroComposerConfig || {
      customContentTypes: [],
      defaultTemplate: "",
      configFilePath: "",
      terminalProjectRootPath: ""
    };
    this.state.seoConfig = settings.seoConfig || {
      titleProperty: "title",
      scanDirectories: "",
      useFilenameAsTitle: false,
      useFilenameAsSlug: true
    };
    this.state.propertyOverFileName = settings.propertyOverFileName || { propertyKey: "title" };
    this.state.explorerFocus = settings.explorerFocus || {};
    if (!this.state.imageManager || Object.keys(this.state.imageManager).length === 0) {
      try {
        const imageManagerConfigurator = new ImageManagerConfigurator(this.plugin.app);
        const loadedConfig = await imageManagerConfigurator.loadConfig();
        if (loadedConfig && Object.keys(loadedConfig).length > 0) {
          this.state.imageManager = loadedConfig;
        } else {
          this.state.imageManager = settings.imageManager || {};
        }
      } catch (error) {
        console.warn("Failed to load Image Manager config during refresh:", error);
        this.state.imageManager = settings.imageManager || {};
      }
    } else {
      this.state.imageManager = settings.imageManager || {};
    }
    if (!this.state.homeBase || Object.keys(this.state.homeBase).length === 0) {
      try {
        const homeBaseConfigurator = new HomeBaseConfigurator(this.plugin.app);
        const loadedConfig = await homeBaseConfigurator.loadConfig();
        if (loadedConfig && Object.keys(loadedConfig).length > 0) {
          this.state.homeBase = loadedConfig;
        } else {
          this.state.homeBase = settings.homeBase || {};
        }
      } catch (error) {
        console.warn("Failed to load Home Base config during refresh:", error);
        this.state.homeBase = settings.homeBase || {};
      }
    } else {
      this.state.homeBase = settings.homeBase || {};
    }
    if (!this.state.explorerFocus || Object.keys(this.state.explorerFocus).length === 0) {
      try {
        const explorerFocusConfigurator = new ExplorerFocusConfigurator(this.plugin.app);
        const loadedConfig = await explorerFocusConfigurator.loadConfig();
        if (loadedConfig && Object.keys(loadedConfig).length > 0) {
          this.state.explorerFocus = loadedConfig;
        } else {
          this.state.explorerFocus = settings.explorerFocus || {};
        }
      } catch (error) {
        console.warn("Failed to load Explorer Focus config during refresh:", error);
        this.state.explorerFocus = settings.explorerFocus || {};
      }
    } else {
      this.state.explorerFocus = settings.explorerFocus || {};
    }
    this.state.gitConfig = settings.gitConfig || { enabled: false, autoConfigureObsidianGit: true };
    this.state.ignoreConfig = settings.ignoreConfig || { gitIgnoreConfigured: false, viteIgnoreConfigured: false };
  }
  async buildFinalSettings() {
    var _a, _b, _c, _d, _e;
    const settings = this.plugin.settings;
    settings.projectRoot = ((_a = this.state.projectDetection) == null ? void 0 : _a.projectRoot) || "";
    settings.configFilePath = ((_b = this.state.projectDetection) == null ? void 0 : _b.configFilePath) || "";
    settings.contentTypes = this.state.contentTypes;
    settings.frontmatterProperties = this.state.frontmatterProperties;
    settings.defaultContentTypeId = this.state.defaultContentTypeId;
    settings.attachmentHandlingMode = this.state.attachmentHandlingMode;
    settings.attachmentFolderName = this.state.attachmentFolderName;
    settings.resolvePublicImages = (_c = this.state.resolvePublicImages) != null ? _c : false;
    settings.preset = this.state.preset;
    settings.presetName = this.state.presetName || "";
    settings.presetsRepo = this.state.presetsRepo || "davidvkimball/vaultcms-presets";
    settings.enableEditingToolbar = this.state.enableEditingToolbar;
    if (settings.enableWYSIWYG !== void 0) {
      delete settings.enableWYSIWYG;
    }
    settings.enableMdxSupport = (_d = this.state.enableMdxSupport) != null ? _d : false;
    settings.enableExtendedFileTypes = (_e = this.state.enableExtendedFileTypes) != null ? _e : false;
    settings.enabledPlugins = this.state.enabledPlugins;
    settings.disabledPlugins = this.state.disabledPlugins;
    settings.theme = this.state.theme;
    settings.basesCMSConfig = this.state.basesCMSConfig;
    settings.astroComposerConfig = this.state.astroComposerConfig;
    settings.seoConfig = this.state.seoConfig;
    settings.propertyOverFileName = this.state.propertyOverFileName;
    const settingsRecord = settings;
    if (settingsRecord.uiTweaker) {
      delete settingsRecord.uiTweaker;
    }
    if (settingsRecord.tabBarCommands) {
      delete settingsRecord.tabBarCommands;
    }
    if (settingsRecord.commanderConfig) {
      delete settingsRecord.commanderConfig;
    }
    if (settingsRecord.imageInserter) {
      delete settingsRecord.imageInserter;
    }
    settings.imageManager = this.state.imageManager;
    settings.homeBase = this.state.homeBase;
    settings.explorerFocus = this.state.explorerFocus;
    settings.ignoreConfig = this.state.ignoreConfig;
    settings.gitConfig = { ...this.state.gitConfig };
    try {
      const imageManagerConfigurator = new ImageManagerConfigurator(this.plugin.app);
      await imageManagerConfigurator.resolveAndSyncImageProperty(this.state);
    } catch (error) {
      console.warn("WizardStateManager: Failed to sync image property with Image Manager:", error);
    }
  }
};

// src/ui/wizard/BaseWizardStep.ts
var BaseWizardStep = class {
  constructor(app, containerEl, state, onNext, onBack, onCancel) {
    this.showNextButton = true;
    this.app = app;
    this.containerEl = containerEl;
    this.state = state;
    this.onNext = onNext;
    this.onBack = onBack;
    this.onCancel = onCancel;
  }
  /**
   * Check if this step should be automatically skipped
   */
  async shouldSkip() {
    return false;
  }
  /**
   * Convert absolute path to relative path from vault root
   */
  toRelativePath(absolutePath) {
    const adapter = this.app.vault.adapter;
    const vaultPath = adapter.basePath || adapter.path;
    if (!vaultPath) {
      return absolutePath;
    }
    const vaultNormalized = vaultPath.replace(/\\/g, "/").replace(/\/$/, "");
    const absoluteNormalized = absolutePath.replace(/\\/g, "/").replace(/\/$/, "");
    if (absoluteNormalized.startsWith(vaultNormalized)) {
      const relative7 = absoluteNormalized.slice(vaultNormalized.length);
      const trimmedRelative = relative7.startsWith("/") ? relative7.slice(1) : relative7;
      return trimmedRelative || ".";
    }
    try {
      const vaultParts = vaultNormalized.split("/").filter((p) => p);
      const absoluteParts = absoluteNormalized.split("/").filter((p) => p);
      let commonLength = 0;
      while (commonLength < vaultParts.length && commonLength < absoluteParts.length && vaultParts[commonLength] === absoluteParts[commonLength]) {
        commonLength++;
      }
      const upLevels = vaultParts.length - commonLength;
      const relativeParts = absoluteParts.slice(commonLength);
      const relative7 = (upLevels > 0 ? "../".repeat(upLevels) : "") + relativeParts.join("/");
      return relative7 || absolutePath;
    } catch (e) {
      return absolutePath;
    }
  }
};

// src/ui/wizard/WelcomeStep.ts
function setCssProps(element, props) {
  for (const [key, value] of Object.entries(props)) {
    element.style.setProperty(key.replace(/([A-Z])/g, "-$1").toLowerCase(), value);
  }
}
var WelcomeStep = class extends BaseWizardStep {
  display() {
    const { containerEl } = this;
    containerEl.empty();
    containerEl.createEl("h2", { text: "Welcome to Vault CMS" });
    containerEl.createEl("p", {
      text: "This wizard will help you configure Vault CMS for your project. We'll guide you through:"
    });
    const list = containerEl.createEl("ul");
    list.createEl("li", { text: "Detecting your Astro project structure" });
    list.createEl("li", { text: "Identifying your content types" });
    list.createEl("li", { text: "Mapping properties" });
    list.createEl("li", { text: "Configuring plugins and themes" });
    list.createEl("li", { text: "Setting up Home Base content views" });
    list.createEl("li", { text: "Configuring Astro Composer and SEO plugins" });
    containerEl.createEl("p", {
      text: "Choose an option to continue:"
    });
    const buttonContainer = containerEl.createDiv("wizard-welcome-buttons");
    setCssProps(buttonContainer, {
      display: "flex",
      gap: "10px",
      marginTop: "20px"
    });
    const getStartedBtn = buttonContainer.createEl("button", {
      text: "Get started",
      cls: "mod-button mod-cta"
    });
    getStartedBtn.addEventListener("click", () => {
      this.onNext();
    });
    const selectPresetBtn = buttonContainer.createEl("button", {
      text: "Select preset",
      cls: "mod-button"
    });
    selectPresetBtn.addEventListener("click", () => {
      this.onCancel();
      const appWithSetting = this.app;
      if (appWithSetting.setting && typeof appWithSetting.setting.open === "function") {
        appWithSetting.setting.open();
        if (typeof appWithSetting.setting.openTabById === "function") {
          appWithSetting.setting.openTabById("vault-cms");
        }
      }
    });
  }
  validate() {
    return true;
  }
  getTitle() {
    return "Welcome";
  }
  getDescription() {
    return "Introduction to Vault CMS setup";
  }
};

// src/ui/wizard/ProjectDetectionStep.ts
var import_obsidian6 = require("obsidian");
var path5 = __toESM(require("path"), 1);
var fs4 = __toESM(require("fs"), 1);

// src/utils/ProjectDetector.ts
var path2 = __toESM(require("path"), 1);
var fs = __toESM(require("fs"), 1);
init_VaultPathHelper();
var ProjectDetector = class {
  constructor(app) {
    this.app = app;
  }
  detectProject() {
    const vaultPath = getVaultPath(this.app);
    if (!vaultPath) {
      return null;
    }
    const configResult = this.searchUpwardForConfig(vaultPath);
    if (!configResult) {
      return null;
    }
    const vaultLocation = this.detectVaultLocation(vaultPath, configResult.projectRoot);
    const relativeProjectRoot = this.toVaultRelative(configResult.projectRoot, vaultPath);
    const relativeConfigFilePath = this.toVaultRelative(configResult.configFilePath, vaultPath);
    return {
      projectRoot: relativeProjectRoot,
      configFilePath: relativeConfigFilePath,
      vaultLocation
    };
  }
  /**
   * Convert an absolute path to a vault-relative path.
   * If the path is at or above the vault, uses relative notation (e.g. ".." or ".").
   */
  toVaultRelative(absolutePath, vaultPath) {
    const relative7 = path2.relative(vaultPath, absolutePath);
    return relative7.split(path2.sep).join("/") || ".";
  }
  /**
   * Search upward from the vault path to find an Astro config file.
   * This allows the vault to be anywhere within the Astro project structure.
   * Bias towards src/config.ts if it exists alongside a root config file.
   */
  searchUpwardForConfig(startPath) {
    const rootConfigFileNames = [
      "astro.config.mjs",
      "astro.config.ts",
      "astro.config.js",
      "astro.config.mts",
      "astro.config.cjs",
      "astro.config.yml",
      "astro.config.yaml"
    ];
    const srcConfigFileName = "src/config.ts";
    let currentDir = path2.resolve(startPath);
    const root = path2.parse(currentDir).root;
    while (currentDir !== root) {
      const srcConfigPath = path2.join(currentDir, srcConfigFileName);
      try {
        if (fs.existsSync(srcConfigPath) && fs.statSync(srcConfigPath).isFile()) {
          return {
            projectRoot: currentDir,
            configFilePath: srcConfigPath
          };
        }
      } catch (e) {
      }
      for (const fileName of rootConfigFileNames) {
        const configPath = path2.join(currentDir, fileName);
        try {
          if (fs.existsSync(configPath) && fs.statSync(configPath).isFile()) {
            return {
              projectRoot: currentDir,
              configFilePath: configPath
            };
          }
        } catch (e) {
        }
      }
      const parentDir = path2.dirname(currentDir);
      if (parentDir === currentDir) {
        break;
      }
      currentDir = parentDir;
    }
    return null;
  }
  /**
   * Determine vault location relative to the detected project root.
   */
  detectVaultLocation(vaultPath, projectRoot) {
    const normalizedVaultPath = path2.normalize(vaultPath);
    const normalizedProjectRoot = path2.normalize(projectRoot);
    if (!normalizedVaultPath.startsWith(normalizedProjectRoot)) {
      return "root";
    }
    const relativePath = path2.relative(normalizedProjectRoot, normalizedVaultPath);
    const pathParts = relativePath.split(path2.sep).filter((part) => part.length > 0);
    const contentIndex = pathParts.findIndex((part) => part.toLowerCase() === "content");
    if (contentIndex > 0) {
      const parentIndex = contentIndex - 1;
      if (parentIndex >= 0 && pathParts[parentIndex].toLowerCase() === "src") {
        return "content";
      }
    }
    const srcIndex = pathParts.findIndex((part) => part.toLowerCase() === "src");
    if (srcIndex >= 0 && srcIndex < pathParts.length - 1) {
      const nextPart = pathParts[srcIndex + 1];
      if (nextPart.toLowerCase() === "content") {
        return "nested-content";
      }
    }
    return "root";
  }
};

// src/utils/MdxDetector.ts
var path3 = __toESM(require("path"), 1);
var fs2 = __toESM(require("fs"), 1);
init_VaultPathHelper();
var MdxDetector = class {
  constructor(app) {
    this.app = app;
  }
  /**
   * Detect if MDX files are present in the content folders
   * Scans all content type folders (posts, pages, etc.) for .mdx files
   */
  detectMdxUsage(projectDetection, contentTypes) {
    console.debug("MdxDetector.detectMdxUsage: called with", {
      projectRoot: projectDetection == null ? void 0 : projectDetection.projectRoot,
      vaultLocation: projectDetection == null ? void 0 : projectDetection.vaultLocation,
      contentTypesCount: contentTypes == null ? void 0 : contentTypes.length
    });
    if (!projectDetection) {
      console.debug("MdxDetector: No projectDetection, returning false");
      return false;
    }
    const vaultPath = getVaultPath(this.app);
    console.debug("MdxDetector: vaultPath =", vaultPath);
    if (!vaultPath) {
      console.debug("MdxDetector: No vaultPath, returning false");
      return false;
    }
    const projectRoot = projectDetection.projectRoot;
    let projectRootPath;
    if (path3.isAbsolute(projectRoot)) {
      projectRootPath = projectRoot;
    } else {
      projectRootPath = path3.resolve(vaultPath, projectRoot);
    }
    console.debug("MdxDetector: projectRootPath =", projectRootPath);
    let contentBasePath;
    if (projectDetection.vaultLocation === "content") {
      contentBasePath = vaultPath;
    } else if (projectDetection.vaultLocation === "nested-content") {
      contentBasePath = path3.resolve(vaultPath, "..");
    } else {
      contentBasePath = path3.join(projectRootPath, "src", "content");
    }
    console.debug("MdxDetector: contentBasePath =", contentBasePath);
    console.debug("MdxDetector: vaultLocation =", projectDetection.vaultLocation);
    console.debug("MdxDetector: contentTypes to scan =", contentTypes.map((ct) => `${ct.name} (${ct.folder})`));
    for (const contentType of contentTypes) {
      let contentTypePath;
      if (contentType.folder.startsWith("src/content/")) {
        contentTypePath = path3.join(projectRootPath, contentType.folder);
      } else {
        contentTypePath = path3.join(contentBasePath, contentType.folder);
      }
      console.debug("MdxDetector: scanning", contentTypePath, "(enabled:", contentType.enabled, ")");
      try {
        if (fs2.existsSync(contentTypePath) && fs2.statSync(contentTypePath).isDirectory()) {
          const foundMdx = this.scanDirectoryForMdx(contentTypePath);
          console.debug("MdxDetector: found MDX in", contentTypePath, "=", foundMdx);
          if (foundMdx) {
            return true;
          }
        } else {
          console.debug("MdxDetector: path does not exist or is not a directory:", contentTypePath, "exists:", fs2.existsSync(contentTypePath));
        }
      } catch (error) {
        console.debug("MdxDetector: error scanning", contentTypePath, error);
        continue;
      }
    }
    console.debug("MdxDetector: no MDX files found");
    return false;
  }
  /**
   * Recursively scan a directory for .mdx files
   */
  scanDirectoryForMdx(dirPath) {
    try {
      const entries = fs2.readdirSync(dirPath, { withFileTypes: true });
      for (const entry of entries) {
        const fullPath = path3.join(dirPath, entry.name);
        if (entry.isFile() && entry.name.endsWith(".mdx")) {
          return true;
        }
        if (entry.isDirectory()) {
          if (this.scanDirectoryForMdx(fullPath)) {
            return true;
          }
        }
      }
    } catch (e) {
      return false;
    }
    return false;
  }
};

// src/utils/ContentTypeDetector.ts
var import_obsidian5 = require("obsidian");
init_VaultPathHelper();
var path4 = __toESM(require("path"), 1);
var fs3 = __toESM(require("fs"), 1);
var ContentTypeDetector = class {
  constructor(app) {
    this.app = app;
  }
  detectContentTypes(projectDetection) {
    const contentFolder = this.findContentDirectory(projectDetection);
    if (!contentFolder) {
      return this.detectContentTypesFromFolder(this.app.vault.getRoot());
    }
    return this.detectContentTypesFromFolder(contentFolder);
  }
  /**
   * Detect content types based on immediate subfolders of the given root.
   */
  detectContentTypesFromFolder(rootFolder) {
    const contentTypes = [];
    const subfolders = this.getTopLevelFolders(rootFolder);
    if (subfolders.length > 0) {
      for (const folder of subfolders) {
        const contentType = this.detectContentType(folder);
        if (contentType) {
          contentTypes.push(contentType);
        }
      }
    } else {
      if (rootFolder.name === "/" && rootFolder.children.length === 0) {
        return [];
      }
      const contentType = this.detectContentType(rootFolder);
      if (contentType) {
        contentTypes.push(contentType);
      }
    }
    return contentTypes;
  }
  /**
   * Find the src/content directory regardless of where the vault is located.
   * Handles cases where vault is at:
   * - src level (need to go into src/content)
   * - src/content level (already there)
   * - src/content/post level (vault is inside a content type, can't access parent, return null to use fallback)
   */
  findContentDirectory(projectDetection) {
    if (!projectDetection || !projectDetection.projectRoot) {
      return null;
    }
    const vaultPath = getVaultPath(this.app);
    if (!vaultPath) {
      return null;
    }
    let projectRoot;
    if (path4.isAbsolute(projectDetection.projectRoot)) {
      projectRoot = projectDetection.projectRoot;
    } else {
      projectRoot = path4.resolve(vaultPath, projectDetection.projectRoot);
    }
    const expectedContentPath = path4.join(projectRoot, "src", "content");
    if (!fs3.existsSync(expectedContentPath) || !fs3.statSync(expectedContentPath).isDirectory()) {
      return null;
    }
    const vaultRoot = this.app.vault.getRoot();
    if (!(vaultRoot instanceof import_obsidian5.TFolder)) {
      return null;
    }
    const vaultNormalized = path4.resolve(vaultPath).toLowerCase();
    const contentNormalized = path4.resolve(expectedContentPath).toLowerCase();
    if (contentNormalized.startsWith(vaultNormalized)) {
      const relativePath = path4.relative(path4.resolve(vaultPath), path4.resolve(expectedContentPath));
      const normalizedRelativePath = relativePath.split(path4.sep).join("/");
      const pathParts = normalizedRelativePath.split("/").filter((part) => part.length > 0);
      if (pathParts.length === 0) {
        return vaultRoot;
      }
      let currentFolder = vaultRoot;
      for (const part of pathParts) {
        if (!currentFolder.children) {
          return null;
        }
        const child = currentFolder.children.find((c) => c instanceof import_obsidian5.TFolder && c.name === part);
        if (!(child instanceof import_obsidian5.TFolder)) {
          return null;
        }
        currentFolder = child;
      }
      return currentFolder;
    }
    return null;
  }
  getTopLevelFolders(folder) {
    const folders = [];
    if (!folder.children) {
      return folders;
    }
    for (const child of folder.children) {
      if (child instanceof import_obsidian5.TFolder) {
        const configDir = this.app.vault.configDir;
        if (!child.name.startsWith(".") && child.name !== "bases" && child.name !== "_bases" && child.name !== "home" && child.name !== "_home" && child.name !== "base" && child.name !== "_base" && child.name !== "node_modules" && child.name !== configDir) {
          folders.push(child);
        }
      }
    }
    return folders;
  }
  detectContentType(folder) {
    const name = this.capitalizeFirst(folder.name);
    return {
      id: `content-type-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
      name,
      folder: folder.path,
      // Use vault-relative path instead of just the folder name
      fileOrganization: "file",
      enabled: true,
      // Enable all discovered content types by default
      indexFileName: "index"
    };
  }
  capitalizeFirst(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }
};

// src/ui/wizard/ProjectDetectionStep.ts
init_VaultPathHelper();
function setCssProps2(element, props) {
  for (const [key, value] of Object.entries(props)) {
    element.style.setProperty(key.replace(/([A-Z])/g, "-$1").toLowerCase(), value);
  }
}
var ProjectDetectionStep = class extends BaseWizardStep {
  constructor(app, containerEl, state, onNext, onBack, onCancel) {
    super(app, containerEl, state, onNext, onBack, onCancel);
    this.detected = false;
    this.projectRootDisplay = null;
    this.configFileDisplay = null;
    this.projectDetector = new ProjectDetector(app);
    this.mdxDetector = new MdxDetector(app);
    this.contentTypeDetector = new ContentTypeDetector(app);
  }
  async display() {
    var _a, _b, _c, _d, _e, _f;
    console.debug("ProjectDetectionStep.display: called");
    const { containerEl } = this;
    containerEl.empty();
    const hasSavedValues = ((_a = this.state.projectDetection) == null ? void 0 : _a.projectRoot) && ((_b = this.state.projectDetection) == null ? void 0 : _b.configFilePath);
    console.debug("ProjectDetectionStep.display: hasSavedValues =", hasSavedValues);
    console.debug("ProjectDetectionStep.display: current enableMdxSupport =", this.state.enableMdxSupport);
    if (!hasSavedValues) {
      containerEl.createEl("h2", { text: "Project detection" });
      containerEl.createEl("p", {
        text: "Detecting your Astro project structure..."
      });
      const result = this.projectDetector.detectProject();
      console.debug("ProjectDetectionStep.display: detection result =", result);
      if (result) {
        this.state.projectDetection = {
          projectRoot: result.projectRoot,
          configFilePath: result.configFilePath,
          vaultLocation: result.vaultLocation
        };
        console.debug("ProjectDetectionStep.display: set projectDetection =", this.state.projectDetection);
        this.detected = true;
      } else {
        this.detected = false;
      }
    } else {
      console.debug("ProjectDetectionStep.display: using saved projectDetection =", this.state.projectDetection);
      this.detected = true;
    }
    if (this.state.projectDetection && (this.detected || hasSavedValues)) {
      await new Promise((resolve11) => setTimeout(resolve11, 500));
      containerEl.empty();
      containerEl.createEl("h2", { text: "Project detected" });
      containerEl.createEl("p", {
        text: 'Project structure detected successfully. You can modify the paths below if needed, then click "Next" to continue.'
      });
      const projectRootSetting = new import_obsidian6.Setting(containerEl).setName("Project root").setDesc("Select the folder containing your Astro project root");
      this.projectRootDisplay = projectRootSetting.descEl.createDiv({
        text: (_c = this.state.projectDetection.projectRoot) != null ? _c : "No folder selected",
        cls: "vault-cms-path-display"
      });
      setCssProps2(this.projectRootDisplay, { color: "var(--text-normal)" });
      projectRootSetting.addButton((button) => button.setButtonText("Browse...").setCta().onClick(() => {
        (() => {
          const selectedPath = this.selectFolder();
          if (selectedPath) {
            this.state.projectDetection.projectRoot = toVaultRelative(this.app, selectedPath);
            if (this.projectRootDisplay) {
              this.projectRootDisplay.textContent = this.state.projectDetection.projectRoot;
              setCssProps2(this.projectRootDisplay, { color: "var(--text-normal)" });
            }
            this.detected = false;
          }
        })();
      }));
      const configFileSetting = new import_obsidian6.Setting(containerEl).setName("Config file").setDesc("Select your Astro config file (astro.config.mjs, astro.config.js, src/config.ts, etc.)");
      this.configFileDisplay = configFileSetting.descEl.createDiv({
        text: (_d = this.state.projectDetection.configFilePath) != null ? _d : "No file selected",
        cls: "vault-cms-path-display"
      });
      setCssProps2(this.configFileDisplay, { color: "var(--text-normal)" });
      configFileSetting.addButton((button) => button.setButtonText("Browse...").setCta().onClick(() => {
        (() => {
          var _a2;
          const vaultPath = getVaultPath(this.app);
          const defaultPath = ((_a2 = this.state.projectDetection) == null ? void 0 : _a2.projectRoot) ? vaultPath ? path5.resolve(vaultPath, this.state.projectDetection.projectRoot) : void 0 : vaultPath != null ? vaultPath : void 0;
          const selectedPath = this.selectConfigFile(defaultPath);
          if (selectedPath) {
            this.state.projectDetection.configFilePath = toVaultRelative(this.app, selectedPath);
            if (this.configFileDisplay) {
              this.configFileDisplay.textContent = this.state.projectDetection.configFilePath;
              setCssProps2(this.configFileDisplay, { color: "var(--text-normal)" });
            }
            this.detected = false;
          }
        })();
      }));
      let autoDetectedMdx = false;
      if (this.state.projectDetection) {
        try {
          console.debug("ProjectDetectionStep: Starting MDX detection");
          console.debug("ProjectDetectionStep: projectDetection =", this.state.projectDetection);
          console.debug("ProjectDetectionStep: existing contentTypes =", this.state.contentTypes.length);
          let contentTypesToUse = this.state.contentTypes;
          if (contentTypesToUse.length === 0) {
            console.debug("ProjectDetectionStep: No content types in state, detecting now...");
            contentTypesToUse = this.contentTypeDetector.detectContentTypes(this.state.projectDetection);
            console.debug("ProjectDetectionStep: Detected content types =", contentTypesToUse.length, contentTypesToUse.map((ct) => `${ct.name} (${ct.folder}, enabled: ${ct.enabled})`));
          } else {
            console.debug("ProjectDetectionStep: Using existing content types =", contentTypesToUse.map((ct) => `${ct.name} (${ct.folder}, enabled: ${ct.enabled})`));
          }
          if (contentTypesToUse.length > 0) {
            console.debug("ProjectDetectionStep: Calling mdxDetector.detectMdxUsage...");
            autoDetectedMdx = this.mdxDetector.detectMdxUsage(
              this.state.projectDetection,
              contentTypesToUse
            );
            console.debug("ProjectDetectionStep: MDX detection result =", autoDetectedMdx);
          } else {
            console.debug("ProjectDetectionStep: No content types to scan");
          }
        } catch (error) {
          console.error("ProjectDetectionStep: MDX detection failed:", error);
          autoDetectedMdx = false;
        }
      } else {
        console.debug("ProjectDetectionStep: No projectDetection, skipping MDX detection");
      }
      if (this.state.enableMdxSupport === void 0) {
        this.state.enableMdxSupport = autoDetectedMdx;
        console.debug("ProjectDetectionStep: Set enableMdxSupport to", autoDetectedMdx, "based on auto-detection");
      } else {
        console.debug("ProjectDetectionStep: enableMdxSupport already set to", this.state.enableMdxSupport, ", skipping auto-detection overwrite");
      }
      const mdxSetting = new import_obsidian6.Setting(containerEl).setName("MDX file support").setDesc("Enable MDX file support for Astro Composer, Property Over File Name, SEO, and UI Tweaker plugins.");
      mdxSetting.addToggle((toggle) => {
        var _a2;
        toggle.setValue((_a2 = this.state.enableMdxSupport) != null ? _a2 : false).onChange((value) => {
          this.state.enableMdxSupport = value;
        });
        if (autoDetectedMdx && this.state.enableMdxSupport) {
          const autoDetectMsg = mdxSetting.descEl.createDiv({
            text: "MDX files detected in content folders",
            cls: "vault-cms-auto-detect-msg"
          });
          setCssProps2(autoDetectMsg, {
            color: "var(--text-muted)",
            fontSize: "0.9em",
            marginTop: "4px"
          });
        }
      });
      const extendedFileTypesSetting = new import_obsidian6.Setting(containerEl).setName("Extended file types").setDesc("Enable support to view, edit, and create .json and .astro files via the Data Files Editor plugin.");
      extendedFileTypesSetting.addToggle((toggle) => {
        var _a2;
        toggle.setValue((_a2 = this.state.enableExtendedFileTypes) != null ? _a2 : false).onChange((value) => {
          this.state.enableExtendedFileTypes = value;
        });
      });
    } else {
      containerEl.empty();
      containerEl.createEl("h2", { text: "Project detection failed" });
      containerEl.createEl("p", {
        text: "Could not detect Astro project structure. Please select your Astro project root and config file manually."
      });
      if (!this.state.projectDetection) {
        this.state.projectDetection = {
          projectRoot: "",
          configFilePath: "",
          vaultLocation: "root"
        };
      }
      const projectRootSetting = new import_obsidian6.Setting(containerEl).setName("Project root").setDesc("Select the folder containing your Astro project root");
      this.projectRootDisplay = projectRootSetting.descEl.createDiv({
        text: (_e = this.state.projectDetection.projectRoot) != null ? _e : "No folder selected",
        cls: "vault-cms-path-display"
      });
      if (this.state.projectDetection.projectRoot) {
        setCssProps2(this.projectRootDisplay, { color: "var(--text-normal)" });
      } else {
        setCssProps2(this.projectRootDisplay, { color: "var(--text-muted)" });
      }
      projectRootSetting.addButton((button) => button.setButtonText("Browse...").setCta().onClick(() => {
        (() => {
          const selectedPath = this.selectFolder();
          if (selectedPath) {
            this.state.projectDetection.projectRoot = toVaultRelative(this.app, selectedPath);
            if (this.projectRootDisplay) {
              this.projectRootDisplay.textContent = this.state.projectDetection.projectRoot;
              setCssProps2(this.projectRootDisplay, { color: "var(--text-normal)" });
            }
          }
        })();
      }));
      const configFileSetting = new import_obsidian6.Setting(containerEl).setName("Config file").setDesc("Select your Astro config file (astro.config.mjs, astro.config.js, src/config.ts, etc.)");
      this.configFileDisplay = configFileSetting.descEl.createDiv({
        text: (_f = this.state.projectDetection.configFilePath) != null ? _f : "No file selected",
        cls: "vault-cms-path-display"
      });
      if (this.state.projectDetection.configFilePath) {
        setCssProps2(this.configFileDisplay, { color: "var(--text-normal)" });
      } else {
        setCssProps2(this.configFileDisplay, { color: "var(--text-muted)" });
      }
      configFileSetting.addButton((button) => button.setButtonText("Browse...").setCta().onClick(() => {
        (() => {
          var _a2;
          const vaultPath = getVaultPath(this.app);
          const defaultPath = ((_a2 = this.state.projectDetection) == null ? void 0 : _a2.projectRoot) ? vaultPath ? path5.resolve(vaultPath, this.state.projectDetection.projectRoot) : void 0 : vaultPath != null ? vaultPath : void 0;
          const selectedPath = this.selectConfigFile(defaultPath);
          if (selectedPath) {
            this.state.projectDetection.configFilePath = toVaultRelative(this.app, selectedPath);
            if (this.configFileDisplay) {
              this.configFileDisplay.textContent = this.state.projectDetection.configFilePath;
              setCssProps2(this.configFileDisplay, { color: "var(--text-normal)" });
            }
          }
        })();
      }));
      let autoDetectedMdx = false;
      if (this.state.projectDetection && this.state.projectDetection.projectRoot && this.state.projectDetection.configFilePath) {
        try {
          const detectedContentTypes = this.contentTypeDetector.detectContentTypes(this.state.projectDetection);
          if (detectedContentTypes.length > 0) {
            autoDetectedMdx = this.mdxDetector.detectMdxUsage(
              this.state.projectDetection,
              detectedContentTypes
            );
          }
        } catch (e) {
          autoDetectedMdx = false;
        }
      }
      if (this.state.enableMdxSupport === void 0) {
        this.state.enableMdxSupport = autoDetectedMdx;
        console.debug("ProjectDetectionStep (manual): Set enableMdxSupport to", autoDetectedMdx, "based on auto-detection");
      } else {
        console.debug("ProjectDetectionStep (manual): enableMdxSupport already set to", this.state.enableMdxSupport, ", skipping auto-detection overwrite");
      }
      const mdxSetting = new import_obsidian6.Setting(containerEl).setName("MDX file support").setDesc("Enable MDX file support for Astro Composer, Property Over File Name, SEO, and UI Tweaker plugins.");
      mdxSetting.addToggle((toggle) => {
        var _a2;
        toggle.setValue((_a2 = this.state.enableMdxSupport) != null ? _a2 : false).onChange((value) => {
          this.state.enableMdxSupport = value;
        });
        if (autoDetectedMdx && this.state.enableMdxSupport) {
          const autoDetectMsg = mdxSetting.descEl.createDiv({
            text: "MDX files detected in content folders",
            cls: "vault-cms-auto-detect-msg"
          });
          setCssProps2(autoDetectMsg, {
            color: "var(--text-muted)",
            fontSize: "0.9em",
            marginTop: "4px"
          });
        }
      });
      const extendedFileTypesSetting = new import_obsidian6.Setting(containerEl).setName("Extended file types").setDesc("Enable support to view, edit, and create .json and .astro files via the Data Files Editor plugin.");
      extendedFileTypesSetting.addToggle((toggle) => {
        var _a2;
        toggle.setValue((_a2 = this.state.enableExtendedFileTypes) != null ? _a2 : false).onChange((value) => {
          this.state.enableExtendedFileTypes = value;
        });
      });
    }
  }
  /**
   * Open native folder picker dialog
   */
  selectFolder() {
    var _a, _b, _c, _d;
    try {
      let dialog = null;
      try {
        const electronRemote = require("@electron/remote");
        dialog = (electronRemote == null ? void 0 : electronRemote.dialog) || null;
      } catch (e) {
      }
      if (!dialog) {
        try {
          const electron = ((_a = window.require) == null ? void 0 : _a.call(window, "electron")) || require("electron");
          dialog = ((_b = electron == null ? void 0 : electron.remote) == null ? void 0 : _b.dialog) || null;
        } catch (e) {
        }
      }
      if (!dialog) {
        try {
          const electron = require("electron");
          dialog = (electron == null ? void 0 : electron.dialog) || null;
        } catch (e) {
        }
      }
      if (!dialog || typeof dialog.showOpenDialogSync !== "function") {
        throw new Error("Electron dialog API not available");
      }
      const vaultPath = (_c = getVaultPath(this.app)) != null ? _c : "";
      let defaultPath = ((_d = this.state.projectDetection) == null ? void 0 : _d.projectRoot) ? vaultPath ? path5.resolve(vaultPath, this.state.projectDetection.projectRoot) : this.state.projectDetection.projectRoot : vaultPath;
      if (defaultPath && !path5.isAbsolute(defaultPath)) {
        defaultPath = path5.resolve(vaultPath, defaultPath);
      }
      const result = dialog.showOpenDialogSync({
        title: "Select Astro Project Root Folder",
        defaultPath,
        properties: ["openDirectory"]
      });
      if (result && result.length > 0) {
        return path5.normalize(result[0]);
      }
    } catch (error) {
      console.error("Error opening folder picker:", error);
      new import_obsidian6.Notice("Unable to open folder picker. Please ensure you are using Obsidian on desktop.");
    }
    return null;
  }
  /**
   * Open native file picker dialog for config file
   */
  selectConfigFile(defaultPath) {
    var _a, _b, _c, _d;
    try {
      let dialog = null;
      try {
        const electronRemote = require("@electron/remote");
        dialog = (electronRemote == null ? void 0 : electronRemote.dialog) || null;
      } catch (e) {
      }
      if (!dialog) {
        try {
          const electron = ((_a = window.require) == null ? void 0 : _a.call(window, "electron")) || require("electron");
          dialog = ((_b = electron == null ? void 0 : electron.remote) == null ? void 0 : _b.dialog) || null;
        } catch (e) {
        }
      }
      if (!dialog) {
        try {
          const electron = require("electron");
          dialog = (electron == null ? void 0 : electron.dialog) || null;
        } catch (e) {
        }
      }
      if (!dialog || typeof dialog.showOpenDialogSync !== "function") {
        throw new Error("Electron dialog API not available");
      }
      const vaultPath = (_c = getVaultPath(this.app)) != null ? _c : "/";
      let startPath = defaultPath || vaultPath;
      if (!defaultPath && ((_d = this.state.projectDetection) == null ? void 0 : _d.configFilePath)) {
        const configPath = this.state.projectDetection.configFilePath;
        if (path5.isAbsolute(configPath)) {
          startPath = path5.dirname(configPath);
        } else {
          startPath = path5.dirname(path5.resolve(vaultPath, configPath));
        }
      } else if (defaultPath && !path5.isAbsolute(defaultPath)) {
        startPath = path5.resolve(vaultPath, defaultPath);
        if (path5.extname(startPath)) {
          startPath = path5.dirname(startPath);
        }
      } else if (defaultPath && path5.isAbsolute(defaultPath)) {
        if (path5.extname(defaultPath)) {
          startPath = path5.dirname(defaultPath);
        } else {
          startPath = defaultPath;
        }
      }
      const result = dialog.showOpenDialogSync({
        title: "Select Astro Config File",
        defaultPath: startPath,
        filters: [
          { name: "Astro Config Files", extensions: ["ts", "mjs", "js", "mts", "cjs", "yml", "yaml"] },
          { name: "All Files", extensions: ["*"] }
        ],
        properties: ["openFile"]
      });
      if (result && result.length > 0) {
        return path5.normalize(result[0]);
      }
    } catch (error) {
      console.error("Error opening file picker:", error);
      new import_obsidian6.Notice("Unable to open file picker. Please ensure you are using Obsidian on desktop.");
    }
    return null;
  }
  validate() {
    var _a, _b;
    if (this.detected) {
      return true;
    }
    const projectRoot = (_a = this.state.projectDetection) == null ? void 0 : _a.projectRoot;
    const configFilePath = (_b = this.state.projectDetection) == null ? void 0 : _b.configFilePath;
    if (!projectRoot || !configFilePath) {
      return false;
    }
    try {
      const vaultPath = getVaultPath(this.app);
      if (!vaultPath) return false;
      const resolvedProjectRoot = path5.isAbsolute(projectRoot) ? projectRoot : path5.resolve(vaultPath, projectRoot);
      const resolvedConfigFilePath = path5.isAbsolute(configFilePath) ? configFilePath : path5.join(vaultPath, configFilePath);
      if (!fs4.existsSync(resolvedProjectRoot) || !fs4.statSync(resolvedProjectRoot).isDirectory()) {
        return false;
      }
      if (!fs4.existsSync(resolvedConfigFilePath) || !fs4.statSync(resolvedConfigFilePath).isFile()) {
        return false;
      }
      return true;
    } catch (e) {
      return false;
    }
  }
  getTitle() {
    return "Project detection";
  }
  getDescription() {
    return "Detect Astro project structure";
  }
};

// src/ui/wizard/ContentTypeStep.ts
var import_obsidian8 = require("obsidian");

// src/utils/PathResolver.ts
var path6 = __toESM(require("path"), 1);
init_VaultPathHelper();
var PathResolver = class {
  constructor(app) {
    this.app = app;
  }
  /**
   * Get the folder path from vault root to the content type folder.
   * This is used by Bases CMS filters and Astro Composer folder settings.
   * 
   * Examples:
   * - Vault at src level, content type "docs": returns "content/docs"
   * - Vault at src/content level, content type "docs": returns "docs"
   * - Vault at src/content/post level, content type "docs": returns "../docs" (if accessible) or "docs" (if vault is the content type folder)
   * 
   * @param folderName The content type folder name (e.g., "docs", "posts")
   * @param projectDetection Project detection result with project root and vault location
   * @returns Path from vault root to content type folder, or null if cannot be determined
   */
  getFolderPathFromVaultRoot(folderName, projectDetection) {
    const vaultPath = getVaultPath(this.app);
    const file = this.app.vault.getAbstractFileByPath(folderName);
    if (file) {
      return folderName;
    }
    if (projectDetection && projectDetection.projectRoot && vaultPath) {
      const projectRoot = path6.isAbsolute(projectDetection.projectRoot) ? projectDetection.projectRoot : path6.resolve(vaultPath, projectDetection.projectRoot);
      let contentTypeAbsolutePath;
      if (folderName.startsWith("src/content/") || folderName.includes("/src/content/")) {
        contentTypeAbsolutePath = path6.resolve(projectRoot, folderName);
      } else {
        contentTypeAbsolutePath = path6.resolve(projectRoot, "src", "content", folderName);
      }
      const vaultAbsolutePath = path6.resolve(vaultPath);
      const relativePath = path6.relative(vaultAbsolutePath, contentTypeAbsolutePath);
      if (!relativePath.startsWith("..") && !path6.isAbsolute(relativePath)) {
        return relativePath.split(path6.sep).join("/") || ".";
      }
    }
    return folderName;
  }
  /**
   * Get the folder path from project root to the content type folder.
   * This is always "src/content/{folderName}" relative to project root.
   * 
   * @param folderName The content type folder name (e.g., "docs", "posts")
   * @returns Path from project root (e.g., "src/content/docs")
   */
  getFolderPathFromProjectRoot(folderName) {
    return `src/content/${folderName}`;
  }
  /**
   * Get the folder path for Astro Composer, which needs the path relative to vault root
   * but should work correctly regardless of vault location.
   * 
   * @param folderName The content type folder name
   * @param projectDetection Project detection result
   * @returns Path from vault root to content type folder
   */
  getAstroComposerFolderPath(folderName, projectDetection) {
    return this.getFolderPathFromVaultRoot(folderName, projectDetection);
  }
  /**
   * Get the folder path for Bases CMS filter, which needs to match files
   * in the content type folder regardless of vault location.
   * 
   * @param folderName The content type folder name
   * @param projectDetection Project detection result
   * @returns Path from vault root to content type folder (for use in file.folder.startsWith filter)
   */
  getBasesCMSFolderPath(folderName, projectDetection) {
    return this.getFolderPathFromVaultRoot(folderName, projectDetection);
  }
};

// src/utils/SafeConfigWriter.ts
var import_obsidian7 = require("obsidian");
var SafeConfigWriter = class {
  constructor(app) {
    this.app = app;
  }
  /**
   * Validates that a value is a valid JSON object
   */
  validateJSON(data) {
    if (!data || typeof data !== "object" || Array.isArray(data)) {
      return false;
    }
    try {
      JSON.parse(JSON.stringify(data));
      return true;
    } catch (e) {
      return false;
    }
  }
  /**
   * Creates a backup of a plugin's data.json file
   */
  async createBackup(pluginId, originalFile) {
    try {
      const content = await this.app.vault.read(originalFile);
      const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
      const backupPath = `${this.app.vault.configDir}/plugins/${pluginId}/data.json.backup-${timestamp2}`;
      await this.app.vault.create(backupPath, content);
      console.debug(`SafeConfigWriter: Created backup at ${backupPath}`);
    } catch (error) {
      console.warn(`SafeConfigWriter: Failed to create backup for ${pluginId}:`, error);
    }
  }
  /**
   * Safely reads a plugin's data.json file
   */
  async readConfig(pluginId) {
    const configPath = `${this.app.vault.configDir}/plugins/${pluginId}/data.json`;
    const dataFile = this.app.vault.getAbstractFileByPath(configPath);
    if (!dataFile || !(dataFile instanceof import_obsidian7.TFile)) {
      console.debug(`SafeConfigWriter: Config file not found for ${pluginId}`);
      return null;
    }
    try {
      const content = await this.app.vault.read(dataFile);
      const parsed = JSON.parse(content);
      if (!this.validateJSON(parsed)) {
        console.error(`SafeConfigWriter: Invalid JSON structure in ${pluginId} config`);
        return null;
      }
      return parsed;
    } catch (error) {
      console.error(`SafeConfigWriter: Failed to read/parse config for ${pluginId}:`, error);
      return null;
    }
  }
  /**
   * Safely writes to a plugin's data.json file with backup and validation
   */
  async writeConfig(pluginId, data, options = {}) {
    const { showNotice = true, createBackup = true } = options;
    if (!this.validateJSON(data)) {
      const message = `Invalid configuration data for ${pluginId}`;
      console.error(`SafeConfigWriter: ${message}`);
      if (showNotice) {
        new import_obsidian7.Notice(`Failed to save ${pluginId} settings: Invalid data`);
      }
      return false;
    }
    const configPath = `${this.app.vault.configDir}/plugins/${pluginId}/data.json`;
    try {
      const dataFile = this.app.vault.getAbstractFileByPath(configPath);
      if (dataFile && dataFile instanceof import_obsidian7.TFile) {
        if (createBackup) {
          await this.createBackup(pluginId, dataFile);
        }
        const content = JSON.stringify(data, null, 2);
        await this.app.vault.modify(dataFile, content);
        console.debug(`SafeConfigWriter: Successfully updated ${pluginId} config`);
      } else {
        const pluginDir = `${this.app.vault.configDir}/plugins/${pluginId}`;
        const pluginDirFile = this.app.vault.getAbstractFileByPath(pluginDir);
        if (!pluginDirFile) {
          await this.app.vault.createFolder(pluginDir);
        }
        const content = JSON.stringify(data, null, 2);
        await this.app.vault.create(configPath, content);
        console.debug(`SafeConfigWriter: Successfully created ${pluginId} config`);
      }
      return true;
    } catch (error) {
      const message = error instanceof Error ? error.message : String(error);
      console.error(`SafeConfigWriter: Failed to write config for ${pluginId}:`, error);
      if (showNotice) {
        new import_obsidian7.Notice(`Failed to save ${pluginId} settings: ${message}`);
      }
      return false;
    }
  }
  /**
   * Safely merges new settings into existing plugin config
   */
  async mergeConfig(pluginId, updates, options = {}) {
    const existingConfig = await this.readConfig(pluginId) || {};
    const mergedConfig = { ...existingConfig, ...updates };
    return this.writeConfig(pluginId, mergedConfig, options);
  }
};

// src/utils/AstroComposerConfig.ts
init_VaultPathHelper();
var AstroComposerConfigurator = class {
  constructor(app) {
    this.app = app;
    this.pathResolver = new PathResolver(app);
    this.safeWriter = new SafeConfigWriter(app);
  }
  configureAstroComposer(contentTypes, frontmatterProperties, projectRoot, configFilePath, defaultContentTypeId, projectDetection, enableMdxSupport) {
    this.frontmatterProperties = frontmatterProperties;
    this.contentTypes = contentTypes;
    const config = {
      customContentTypes: [],
      defaultTemplate: "",
      configFilePath: this.relativePath(configFilePath),
      terminalProjectRootPath: this.relativePath(projectRoot),
      showMdxFilesInExplorer: enableMdxSupport != null ? enableMdxSupport : false
    };
    const defaultContentType = defaultContentTypeId ? contentTypes.find((ct) => ct.id === defaultContentTypeId && ct.enabled) : null;
    const otherContentTypes = contentTypes.filter((ct) => ct.enabled && (!defaultContentTypeId || ct.id !== defaultContentTypeId));
    if (defaultContentType) {
      const props = frontmatterProperties[defaultContentType.id];
      let linkBasePath = defaultContentType.linkBasePath;
      if (linkBasePath === void 0 || linkBasePath === "") {
        const pathParts = defaultContentType.folder.split("/").filter((p) => p.length > 0);
        const folderName = pathParts[pathParts.length - 1] || defaultContentType.folder;
        linkBasePath = `/${folderName}/`;
      }
      const folderPath = this.pathResolver.getAstroComposerFolderPath(defaultContentType.folder, projectDetection);
      config.customContentTypes.push({
        id: defaultContentType.id,
        name: defaultContentType.name,
        folder: folderPath,
        template: (props == null ? void 0 : props.template) || this.generateTemplate(props),
        enabled: true,
        linkBasePath,
        creationMode: defaultContentType.fileOrganization,
        indexFileName: defaultContentType.indexFileName || "index"
      });
      config.postsFolder = folderPath;
      config.postsCreationMode = defaultContentType.fileOrganization;
      config.postsIndexFileName = defaultContentType.indexFileName || "index";
      config.defaultTemplate = (props == null ? void 0 : props.template) || this.generateTemplate(props);
    }
    const defaultProps = defaultContentType ? frontmatterProperties[defaultContentType.id] : void 0;
    if (defaultProps) {
      if (defaultProps.hasDraftStatus) {
        config.syncDraftDate = true;
        if (defaultProps.draftProperty) {
          config.draftDetectionMode = "property";
          config.draftProperty = defaultProps.draftProperty;
          config.draftLogic = defaultProps.draftLogic === "false-draft" ? "false-is-draft" : "true-is-draft";
        } else {
          config.draftDetectionMode = "underscore-prefix";
        }
      }
      if (defaultProps.dateProperty) {
        config.publishDateField = defaultProps.dateProperty;
      }
    }
    for (const contentType of otherContentTypes) {
      const props = frontmatterProperties[contentType.id];
      let linkBasePath = contentType.linkBasePath;
      if (linkBasePath === void 0 || linkBasePath === "") {
        const pathParts = contentType.folder.split("/").filter((p) => p.length > 0);
        const folderName = pathParts[pathParts.length - 1] || contentType.folder;
        linkBasePath = `/${folderName}/`;
      }
      const folderPath = this.pathResolver.getAstroComposerFolderPath(contentType.folder, projectDetection);
      config.customContentTypes.push({
        id: contentType.id,
        name: contentType.name,
        folder: folderPath,
        // Use template from props if available, otherwise generate
        template: (props == null ? void 0 : props.template) || this.generateTemplate(props),
        enabled: true,
        linkBasePath,
        creationMode: contentType.fileOrganization,
        indexFileName: contentType.indexFileName || "index"
      });
    }
    return Promise.resolve(config);
  }
  generateTemplate(props) {
    if (props == null ? void 0 : props.template) {
      return props.template;
    }
    if (!props) {
      return '---\ntitle: "{{title}}"\n---\n';
    }
    let template = "---\n";
    template += `${props.titleProperty || "title"}: "{{title}}"
`;
    if (props.dateProperty) {
      template += `${props.dateProperty}: {{date}}
`;
    }
    if (props.descriptionProperty) {
      template += `${props.descriptionProperty}: ""
`;
    }
    if (props.tagsProperty) {
      template += `${props.tagsProperty}: []
`;
    }
    if (props.draftProperty) {
      const draftValue = props.draftLogic === "false-draft" ? "false" : "true";
      template += `${props.draftProperty}: ${draftValue}
`;
    }
    template += "---\n";
    return template;
  }
  getCreationModeFromAttachmentHandling(mode) {
    return mode === "same-folder" ? "folder" : "file";
  }
  relativePath(inputPath) {
    if (!inputPath.startsWith("/") && !/^[A-Z]:/.test(inputPath)) {
      return inputPath;
    }
    const vaultPath = getVaultPath(this.app);
    if (!vaultPath) return inputPath;
    const vaultNormalized = vaultPath.replace(/\\/g, "/").replace(/\/$/, "");
    const absoluteNormalized = inputPath.replace(/\\/g, "/").replace(/\/$/, "");
    if (absoluteNormalized.startsWith(vaultNormalized)) {
      const relative7 = absoluteNormalized.slice(vaultNormalized.length);
      return relative7.startsWith("/") ? relative7.slice(1) : relative7;
    }
    return inputPath;
  }
  async saveConfig(config) {
    var _a, _b;
    try {
      const plugins = this.app.plugins;
      const astroComposerPlugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a["astro-composer"];
      if (!astroComposerPlugin) {
        console.warn("AstroComposerConfig: Astro Composer plugin not found, using fallback file method");
        await this.saveConfigFallback(config);
        return;
      }
      if (!astroComposerPlugin.settings) {
        console.warn("AstroComposerConfig: Astro Composer plugin settings not available, using fallback file method");
        await this.saveConfigFallback(config);
        return;
      }
      const pluginSettings = astroComposerPlugin.settings;
      if (config.defaultTemplate) {
        pluginSettings.defaultTemplate = config.defaultTemplate;
      }
      if (config.pageTemplate) {
        pluginSettings.pageTemplate = config.pageTemplate;
      }
      if (config.postsFolder) {
        pluginSettings.postsFolder = config.postsFolder;
      }
      if (config.postsCreationMode) {
        pluginSettings.creationMode = config.postsCreationMode;
      }
      if (config.postsIndexFileName) {
        pluginSettings.indexFileName = config.postsIndexFileName;
      }
      if (config.enablePages !== void 0) {
        pluginSettings.enablePages = config.enablePages;
      }
      if (config.pagesFolder) {
        pluginSettings.pagesFolder = config.pagesFolder;
      }
      if (config.pagesCreationMode) {
        pluginSettings.pagesCreationMode = config.pagesCreationMode;
      }
      if (config.pagesIndexFileName) {
        pluginSettings.pagesIndexFileName = config.pagesIndexFileName;
      }
      if (config.configFilePath) {
        pluginSettings.configFilePath = config.configFilePath;
      }
      if (config.terminalProjectRootPath) {
        pluginSettings.terminalProjectRootPath = config.terminalProjectRootPath;
      }
      if (config.configFilePath && config.terminalProjectRootPath) {
        pluginSettings.enableOpenTerminalCommand = true;
        pluginSettings.enableOpenConfigFileCommand = true;
        pluginSettings.enableTerminalRibbonIcon = true;
        pluginSettings.enableConfigRibbonIcon = true;
      }
      if (config.syncDraftDate !== void 0) {
        pluginSettings.syncDraftDate = config.syncDraftDate;
      }
      if (config.draftDetectionMode) {
        pluginSettings.draftDetectionMode = config.draftDetectionMode;
      }
      if (config.draftProperty !== void 0) {
        pluginSettings.draftProperty = config.draftProperty;
      }
      if (config.draftLogic) {
        pluginSettings.draftLogic = config.draftLogic;
      }
      if (config.publishDateField) {
        pluginSettings.publishDateField = config.publishDateField;
      }
      if (config.showMdxFilesInExplorer !== void 0) {
        pluginSettings.showMdxFilesInExplorer = config.showMdxFilesInExplorer;
        console.debug("AstroComposerConfig: Set showMdxFilesInExplorer to", config.showMdxFilesInExplorer);
      } else {
        console.debug("AstroComposerConfig: showMdxFilesInExplorer is undefined, not updating");
      }
      if (!Array.isArray(pluginSettings.contentTypes)) {
        pluginSettings.contentTypes = [];
      }
      for (const newType of config.customContentTypes) {
        const contentType = (_b = this.contentTypes) == null ? void 0 : _b.find((ct) => ct.id === newType.id);
        const props = contentType && this.frontmatterProperties ? this.frontmatterProperties[contentType.id] : void 0;
        const shouldEnableUnderscorePrefix = (props == null ? void 0 : props.hasDraftStatus) === true && !(props == null ? void 0 : props.draftProperty);
        const contentTypes = pluginSettings.contentTypes || [];
        let existingIndex = -1;
        let matchedById = false;
        if (newType.id) {
          existingIndex = contentTypes.findIndex((ct) => ct.id === newType.id);
          if (existingIndex >= 0) {
            matchedById = true;
          }
        }
        if (existingIndex < 0) {
          existingIndex = contentTypes.findIndex(
            (ct) => ct.name === newType.name && ct.folder === newType.folder
          );
        }
        if (existingIndex >= 0) {
          const existingEntry = contentTypes[existingIndex];
          contentTypes[existingIndex] = {
            ...existingEntry,
            // Only update ID if we matched by ID, otherwise keep existing ID for consistency
            id: matchedById ? newType.id : existingEntry.id || newType.id,
            name: newType.name,
            folder: newType.folder,
            linkBasePath: newType.linkBasePath,
            template: newType.template,
            enabled: newType.enabled,
            creationMode: newType.creationMode,
            indexFileName: newType.indexFileName,
            enableUnderscorePrefix: shouldEnableUnderscorePrefix
          };
        } else {
          contentTypes.push({
            id: newType.id,
            name: newType.name,
            folder: newType.folder,
            linkBasePath: newType.linkBasePath,
            template: newType.template,
            enabled: newType.enabled,
            creationMode: newType.creationMode,
            indexFileName: newType.indexFileName,
            ignoreSubfolders: false,
            enableUnderscorePrefix: shouldEnableUnderscorePrefix
          });
        }
      }
      pluginSettings.customContentTypes = this.mergeCustomContentTypes(
        pluginSettings.customContentTypes || [],
        config.customContentTypes || []
      );
      if (typeof astroComposerPlugin.saveSettings === "function") {
        await astroComposerPlugin.saveSettings();
        console.debug("AstroComposerConfig: Successfully saved via plugin.saveSettings()");
      } else {
        console.warn("AstroComposerConfig: Plugin saveSettings not available, using fallback");
        await this.saveConfigFallback(config);
      }
    } catch (error) {
      console.error("Failed to save Astro Composer config via plugin method:", error);
      await this.saveConfigFallback(config);
    }
  }
  async saveConfigFallback(config) {
    var _a;
    const pluginId = "astro-composer";
    let existingData = await this.safeWriter.readConfig(pluginId);
    if (!existingData) {
      existingData = {};
    }
    if (config.defaultTemplate) existingData.defaultTemplate = config.defaultTemplate;
    if (config.pageTemplate) existingData.pageTemplate = config.pageTemplate;
    if (config.postsFolder) existingData.postsFolder = config.postsFolder;
    if (config.postsCreationMode) existingData.creationMode = config.postsCreationMode;
    if (config.postsIndexFileName) existingData.indexFileName = config.postsIndexFileName;
    if (config.enablePages !== void 0) existingData.enablePages = config.enablePages;
    if (config.pagesFolder) existingData.pagesFolder = config.pagesFolder;
    if (config.pagesCreationMode) existingData.pagesCreationMode = config.pagesCreationMode;
    if (config.pagesIndexFileName) existingData.pagesIndexFileName = config.pagesIndexFileName;
    if (config.configFilePath) existingData.configFilePath = config.configFilePath;
    if (config.terminalProjectRootPath) existingData.terminalProjectRootPath = config.terminalProjectRootPath;
    if (config.showMdxFilesInExplorer !== void 0) existingData.showMdxFilesInExplorer = config.showMdxFilesInExplorer;
    if (config.syncDraftDate !== void 0) existingData.syncDraftDate = config.syncDraftDate;
    if (config.draftDetectionMode) existingData.draftDetectionMode = config.draftDetectionMode;
    if (config.draftProperty !== void 0) existingData.draftProperty = config.draftProperty;
    if (config.draftLogic) existingData.draftLogic = config.draftLogic;
    if (config.publishDateField) existingData.publishDateField = config.publishDateField;
    if (config.configFilePath && config.terminalProjectRootPath) {
      existingData.enableOpenTerminalCommand = true;
      existingData.enableOpenConfigFileCommand = true;
      existingData.enableTerminalRibbonIcon = true;
      existingData.enableConfigRibbonIcon = true;
    }
    if (!Array.isArray(existingData.contentTypes)) {
      existingData.contentTypes = [];
    }
    for (const newType of config.customContentTypes) {
      const contentType = (_a = this.contentTypes) == null ? void 0 : _a.find((ct) => ct.id === newType.id);
      const props = contentType && this.frontmatterProperties ? this.frontmatterProperties[contentType.id] : void 0;
      const shouldEnableUnderscorePrefix = (props == null ? void 0 : props.hasDraftStatus) === true && !(props == null ? void 0 : props.draftProperty);
      const contentTypes = existingData.contentTypes || [];
      let existingIndex = -1;
      let matchedById = false;
      if (newType.id) {
        existingIndex = contentTypes.findIndex((ct) => ct.id === newType.id);
        if (existingIndex >= 0) {
          matchedById = true;
        }
      }
      if (existingIndex < 0) {
        existingIndex = contentTypes.findIndex(
          (ct) => ct.name === newType.name && ct.folder === newType.folder
        );
      }
      if (existingIndex >= 0) {
        const existingEntry = contentTypes[existingIndex];
        contentTypes[existingIndex] = {
          ...existingEntry,
          // Only update ID if we matched by ID, otherwise keep existing ID for consistency
          id: matchedById ? newType.id : existingEntry.id || newType.id,
          name: newType.name,
          folder: newType.folder,
          linkBasePath: newType.linkBasePath,
          template: newType.template,
          enabled: newType.enabled,
          creationMode: newType.creationMode,
          indexFileName: newType.indexFileName,
          enableUnderscorePrefix: shouldEnableUnderscorePrefix
        };
      } else {
        contentTypes.push({
          id: newType.id,
          name: newType.name,
          folder: newType.folder,
          linkBasePath: newType.linkBasePath,
          template: newType.template,
          enabled: newType.enabled,
          creationMode: newType.creationMode,
          indexFileName: newType.indexFileName,
          ignoreSubfolders: false,
          enableUnderscorePrefix: shouldEnableUnderscorePrefix
        });
      }
    }
    existingData.customContentTypes = this.mergeCustomContentTypes(
      existingData.customContentTypes || [],
      config.customContentTypes || []
    );
    const success = await this.safeWriter.writeConfig(pluginId, existingData, {
      showNotice: true,
      createBackup: true
    });
    if (!success) {
      throw new Error("Failed to save Astro Composer configuration");
    }
  }
  mergeCustomContentTypes(existing, newTypes) {
    const merged = [...existing];
    for (const newType of newTypes) {
      const existingIndex = merged.findIndex((ct) => ct.id === newType.id);
      if (existingIndex >= 0) {
        merged[existingIndex] = { ...merged[existingIndex], ...newType };
      } else {
        merged.push(newType);
      }
    }
    return merged;
  }
};

// src/ui/wizard/ContentTypeStep.ts
function setCssProps3(element, props) {
  for (const [key, value] of Object.entries(props)) {
    element.style.setProperty(key.replace(/([A-Z])/g, "-$1").toLowerCase(), value);
  }
}
var FolderNameSuggest = class extends import_obsidian8.AbstractInputSuggest {
  constructor(app, inputEl, mode) {
    super(app, inputEl);
    this.inputEl = inputEl;
    this.mode = mode;
  }
  getSuggestions(inputStr) {
    const suggestions = [];
    const lowerInput = inputStr.toLowerCase();
    if (this.mode === "subfolder") {
      if ("attachments".toLowerCase().includes(lowerInput)) {
        suggestions.push("attachments");
      }
      const allFiles = this.app.vault.getAllLoadedFiles();
      const folderNames = /* @__PURE__ */ new Set();
      for (const file of allFiles) {
        if (file instanceof import_obsidian8.TFolder) {
          const folderName = file.name;
          if (folderName.toLowerCase().includes(lowerInput) && folderName !== "attachments") {
            folderNames.add(folderName);
          }
        }
      }
      suggestions.push(...Array.from(folderNames).slice(0, 10));
    } else {
      const allFiles = this.app.vault.getAllLoadedFiles();
      const paths = /* @__PURE__ */ new Set();
      for (const file of allFiles) {
        if (file instanceof import_obsidian8.TFolder) {
          const path13 = file.path;
          if (path13.toLowerCase().includes(lowerInput)) {
            paths.add(path13);
          }
        }
      }
      suggestions.push(...Array.from(paths).slice(0, 10));
    }
    return suggestions;
  }
  renderSuggestion(suggestion, el) {
    el.setText(suggestion);
  }
  selectSuggestion(suggestion) {
    this.inputEl.value = suggestion;
    this.inputEl.trigger("input");
    this.close();
  }
};
var ContentTypeStep = class extends BaseWizardStep {
  constructor(app, containerEl, state, onNext, onBack, onCancel) {
    super(app, containerEl, state, onNext, onBack, onCancel);
    this.detected = false;
    this.contentTypeDetector = new ContentTypeDetector(app);
    this.astroComposerConfigurator = new AstroComposerConfigurator(app);
  }
  /**
   * Import content types from Astro Composer data.json if it exists
   * First tries plugin API, then falls back to file reading
   */
  async importFromAstroComposer() {
    var _a;
    try {
      const plugins = this.app.plugins;
      console.debug("ContentTypeStep: Checking plugins API:", !!plugins);
      if (plugins) {
        const astroComposerPlugin = (_a = plugins.plugins) == null ? void 0 : _a["astro-composer"];
        console.debug("ContentTypeStep: Astro Composer plugin found:", !!astroComposerPlugin);
        if (astroComposerPlugin) {
          console.debug("ContentTypeStep: Plugin settings available:", !!astroComposerPlugin.settings);
          console.debug("ContentTypeStep: Plugin settings keys:", astroComposerPlugin.settings ? Object.keys(astroComposerPlugin.settings) : "none");
          if (astroComposerPlugin.settings) {
            const contentTypes = astroComposerPlugin.settings.contentTypes;
            console.debug("ContentTypeStep: contentTypes from plugin:", contentTypes ? `Array with ${contentTypes.length} items` : "not found");
            if (Array.isArray(contentTypes) && contentTypes.length > 0) {
              console.debug("ContentTypeStep: Importing", contentTypes.length, "content types from Astro Composer (via plugin API)");
              const importedTypes2 = contentTypes.map((ct) => ({
                id: ct.id || `content-type-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
                name: ct.name || this.capitalizeFirst(ct.folder),
                folder: ct.folder,
                fileOrganization: ct.creationMode === "folder" ? "folder" : "file",
                indexFileName: ct.indexFileName || "index",
                linkBasePath: ct.linkBasePath,
                enabled: ct.enabled !== false
                // Default to enabled if not specified
              }));
              return importedTypes2;
            }
          }
        }
      }
      const configDir = this.app.vault.configDir;
      const pluginDataPath = `${configDir}/plugins/astro-composer/data.json`;
      console.debug("ContentTypeStep: Trying to read file:", pluginDataPath);
      const dataFile = this.app.vault.getAbstractFileByPath(pluginDataPath);
      console.debug("ContentTypeStep: File found:", !!dataFile, dataFile ? `Type: ${dataFile.constructor.name}` : "not found");
      if (!dataFile || !(dataFile instanceof import_obsidian8.TFile)) {
        const altPaths = [
          `${configDir}/plugins/astro-composer/data.json`,
          `obsidian/plugins/astro-composer/data.json`
        ];
        for (const altPath of altPaths) {
          const altFile = this.app.vault.getAbstractFileByPath(altPath);
          if (altFile && altFile instanceof import_obsidian8.TFile) {
            console.debug("ContentTypeStep: Found file at alternative path:", altPath);
            const content2 = await this.app.vault.read(altFile);
            const data2 = JSON.parse(content2);
            if (data2.contentTypes && Array.isArray(data2.contentTypes)) {
              console.debug("ContentTypeStep: Importing", data2.contentTypes.length, "content types from Astro Composer (via file at", altPath, ")");
              const importedTypes2 = data2.contentTypes.map((ct) => ({
                id: ct.id || `content-type-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
                name: ct.name || this.capitalizeFirst(ct.folder),
                folder: ct.folder,
                fileOrganization: ct.creationMode === "folder" ? "folder" : "file",
                indexFileName: ct.indexFileName || "index",
                linkBasePath: ct.linkBasePath,
                enabled: ct.enabled !== false
              }));
              return importedTypes2;
            }
          }
        }
        console.debug("ContentTypeStep: No Astro Composer data.json found, will scan folders");
        return [];
      }
      const content = await this.app.vault.read(dataFile);
      const data = JSON.parse(content);
      if (!data.contentTypes || !Array.isArray(data.contentTypes)) {
        console.debug("ContentTypeStep: Astro Composer data.json has no contentTypes array. Data keys:", Object.keys(data));
        return [];
      }
      console.debug("ContentTypeStep: Importing", data.contentTypes.length, "content types from Astro Composer (via file)");
      const importedTypes = data.contentTypes.map((ct) => ({
        id: ct.id || `content-type-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
        name: ct.name || this.capitalizeFirst(ct.folder),
        folder: ct.folder,
        fileOrganization: ct.creationMode === "folder" ? "folder" : "file",
        indexFileName: ct.indexFileName || "index",
        linkBasePath: ct.linkBasePath,
        enabled: ct.enabled !== false
        // Default to enabled if not specified
      }));
      return importedTypes;
    } catch (error) {
      console.error("ContentTypeStep: Failed to import from Astro Composer:", error);
      return [];
    }
  }
  /**
   * Walk up from the step container to find the element that actually scrolls (modal body).
   */
  findWizardScrollParent() {
    let el = this.containerEl;
    while (el && el !== document.body) {
      const style = window.getComputedStyle(el);
      const oy = style.overflowY;
      if (el.scrollHeight > el.clientHeight && (oy === "auto" || oy === "scroll" || style.overflow === "auto" || style.overflow === "scroll")) {
        return el;
      }
      el = el.parentElement;
    }
    return this.containerEl.closest(".modal-content") || this.containerEl.parentElement;
  }
  /**
   * Show or hide the optional "Attachment folder" row without re-rendering the whole step.
   */
  renderAttachmentExtraSlot(slot) {
    slot.empty();
    const mode = this.state.attachmentHandlingMode;
    if (mode !== "specified-folder" && mode !== "subfolder") {
      return;
    }
    const descText = mode === "specified-folder" ? 'Enter the exact path to the folder for attachments (e.g., "attachments" or "images/attachments"). Leave blank to use "attachments" as default.' : 'Enter the name of the subfolder for attachments (e.g., "attachments"). Leave blank to use "attachments" as default.';
    const folderNameSetting = new import_obsidian8.Setting(slot).setName("Attachment folder").setDesc(descText);
    folderNameSetting.addText((text) => {
      text.setPlaceholder("attachments").setValue(this.state.attachmentFolderName || "").onChange((value) => {
        this.state.attachmentFolderName = value || void 0;
      });
      new FolderNameSuggest(this.app, text.inputEl, mode);
    });
  }
  /**
   * Show or hide the index file name row for one content type without re-rendering the whole step.
   */
  renderIndexFileSlot(contentType, slot) {
    slot.empty();
    if (contentType.fileOrganization !== "folder") {
      return;
    }
    new import_obsidian8.Setting(slot).setName(`${contentType.name} - Index file name`).setDesc("Name of the index file in folder-based organization").addText(
      (text) => text.setValue(contentType.indexFileName || "index").onChange((value) => {
        contentType.indexFileName = value || "index";
      })
    );
  }
  async display() {
    var _a;
    const { containerEl } = this;
    const scrollParent = this.findWizardScrollParent();
    const savedScrollTop = (_a = scrollParent == null ? void 0 : scrollParent.scrollTop) != null ? _a : 0;
    const activeEl = document.activeElement;
    if (activeEl instanceof HTMLElement && containerEl.contains(activeEl)) {
      activeEl.blur();
    }
    let stepContentWrapper = containerEl.querySelector(".content-type-step-content");
    if (!stepContentWrapper) {
      containerEl.empty();
      stepContentWrapper = containerEl.createDiv({ cls: "content-type-step-content" });
    } else {
      stepContentWrapper.empty();
    }
    const restoreScroll = () => {
      if (!scrollParent) {
        return;
      }
      const top = savedScrollTop;
      const apply = () => {
        scrollParent.scrollTop = top;
      };
      requestAnimationFrame(() => {
        requestAnimationFrame(() => {
          apply();
          setTimeout(apply, 0);
        });
      });
    };
    stepContentWrapper.createEl("h2", { text: "Content types" });
    stepContentWrapper.createEl("p", {
      text: "Detecting content types in your vault..."
    });
    if (!this.detected) {
      const savedContentTypes = this.state.contentTypes || [];
      const savedContentTypesMap = new Map(savedContentTypes.map((ct) => [ct.folder, ct]));
      const importedTypes = await this.importFromAstroComposer();
      const scannedTypes = this.contentTypeDetector.detectContentTypes(this.state.projectDetection);
      const allDetectedTypes = [];
      const imported = [...importedTypes];
      for (const scanned of scannedTypes) {
        const matchingImportedIndex = imported.findIndex(
          (it) => scanned.folder === it.folder || scanned.folder.endsWith(`/${it.folder}`) || it.folder.endsWith(`/${scanned.folder}`)
        );
        if (matchingImportedIndex >= 0) {
          const importedType = imported[matchingImportedIndex];
          if (scanned.folder.length > importedType.folder.length) {
            console.debug(`ContentTypeStep: Updating imported type "${importedType.name}" folder from "${importedType.folder}" to "${scanned.folder}"`);
            imported[matchingImportedIndex] = {
              ...importedType,
              folder: scanned.folder
            };
          }
        } else {
          allDetectedTypes.push(scanned);
        }
      }
      allDetectedTypes.push(...imported);
      const detectedTypesMap = new Map(allDetectedTypes.map((ct) => [ct.folder, ct]));
      const mergedTypes = [];
      const processedFolders = /* @__PURE__ */ new Set();
      const allFolders = /* @__PURE__ */ new Set([
        ...savedContentTypes.map((ct) => ct.folder),
        ...allDetectedTypes.map((ct) => ct.folder)
      ]);
      for (const folder of allFolders) {
        if (processedFolders.has(folder)) continue;
        let savedType = savedContentTypesMap.get(folder);
        const detectedType = detectedTypesMap.get(folder);
        if (savedType && !detectedType) {
          const matchingDetected = allDetectedTypes.find(
            (dt) => dt.folder.endsWith(`/${folder}`) || dt.folder === folder
          );
          if (matchingDetected && !processedFolders.has(matchingDetected.folder)) {
            console.debug(`ContentTypeStep: Reconciling saved folder "${folder}" with detected folder "${matchingDetected.folder}"`);
            mergedTypes.push({
              ...savedType,
              folder: matchingDetected.folder
            });
            processedFolders.add(folder);
            processedFolders.add(matchingDetected.folder);
            continue;
          }
        }
        if (savedType) {
          if (detectedType) {
            mergedTypes.push({
              ...savedType,
              // Preserve all saved settings (enabled, custom name, linkBasePath, etc.)
              // Always preserve saved folder and name (user may have customized the name)
              folder: savedType.folder,
              name: savedType.name
              // Always use saved name (may be customized)
            });
          } else {
            mergedTypes.push(savedType);
          }
        } else if (detectedType) {
          mergedTypes.push(detectedType);
        }
        processedFolders.add(folder);
      }
      mergedTypes.sort((a, b) => a.name.localeCompare(b.name));
      this.state.contentTypes = mergedTypes;
      this.detected = true;
    }
    stepContentWrapper.empty();
    stepContentWrapper.createEl("h2", { text: "Content types" });
    stepContentWrapper.createEl("p", {
      text: "Select and configure your content types:"
    });
    stepContentWrapper.createEl("h3", { text: "Attachment handling", cls: "vault-cms-section-header" });
    stepContentWrapper.createEl("p", {
      text: "How should attachments be stored globally?",
      cls: "vault-cms-section-desc"
    });
    let attachmentExtraSlot;
    new import_obsidian8.Setting(stepContentWrapper).setName("How are attachments handled?").setDesc("Choose how attachments are stored for all content types").addDropdown((dropdown) => dropdown.addOption("same-folder", "Same folder as current file").addOption("specified-folder", "In the specified folder").addOption("subfolder", "In subfolder under current folder").setValue(this.state.attachmentHandlingMode || "subfolder").onChange((value) => {
      this.state.attachmentHandlingMode = value;
      if (value === "same-folder") {
        this.state.attachmentFolderName = void 0;
      }
      this.renderAttachmentExtraSlot(attachmentExtraSlot);
    }));
    attachmentExtraSlot = stepContentWrapper.createDiv({ cls: "vault-cms-attachment-extra-slot" });
    this.renderAttachmentExtraSlot(attachmentExtraSlot);
    new import_obsidian8.Setting(stepContentWrapper).setName("Resolve cover images from public folder").setDesc("Enable this if your theme uses absolute image paths (like /images/photo.jpg) that reference the Astro project's public/ folder. This lets banners and card thumbnails display correctly in Obsidian.").addToggle((toggle) => {
      var _a2;
      return toggle.setValue((_a2 = this.state.resolvePublicImages) != null ? _a2 : false).onChange((value) => {
        this.state.resolvePublicImages = value;
      });
    });
    stepContentWrapper.createEl("hr", { cls: "vault-cms-divider" });
    stepContentWrapper.createEl("h3", { text: "Content types", cls: "vault-cms-section-header" });
    for (const contentType of this.state.contentTypes) {
      const block = stepContentWrapper.createDiv({ cls: "vault-cms-ct-block" });
      const setting = new import_obsidian8.Setting(block);
      const nameContainer = setting.nameEl.createDiv({ cls: "vault-cms-editable-name" });
      setCssProps3(nameContainer, { display: "flex", alignItems: "center", gap: "0.5rem" });
      const createNameDisplay = (name) => {
        nameContainer.empty();
        const display = nameContainer.createSpan({
          text: name,
          cls: "vault-cms-name-display"
        });
        const iconContainer = nameContainer.createDiv({ cls: "vault-cms-edit-icon" });
        setCssProps3(iconContainer, { opacity: "0.6" });
        (0, import_obsidian8.setIcon)(iconContainer, "lucide-pencil-line");
        const startEdit = () => {
          const currentName = contentType.name;
          nameContainer.empty();
          const nameInput = nameContainer.createEl("input", {
            type: "text",
            value: currentName
          });
          nameInput.addClass("mod-text-input");
          nameInput.focus();
          nameInput.select();
          const saveName = () => {
            nameInput.removeEventListener("blur", saveName);
            let newName = nameInput.value.trim();
            if (!newName) {
              newName = currentName;
            }
            newName = newName.replace(/[<>:"/\\|?*\x00-\x1F]/g, "");
            if (!newName.trim()) {
              newName = currentName;
            } else {
              newName = newName.trim();
            }
            contentType.name = newName;
            void this.display();
          };
          nameInput.addEventListener("keydown", (e) => {
            if (e.key === "Enter") {
              e.preventDefault();
              saveName();
            } else if (e.key === "Escape") {
              e.preventDefault();
              createNameDisplay(currentName);
            }
          });
          nameInput.addEventListener("blur", saveName);
        };
        display.addEventListener("click", startEdit);
        iconContainer.addEventListener("click", startEdit);
        iconContainer.addEventListener("mouseenter", () => {
          setCssProps3(iconContainer, { opacity: "1" });
        });
        iconContainer.addEventListener("mouseleave", () => {
          setCssProps3(iconContainer, { opacity: "0.6" });
        });
        return display;
      };
      createNameDisplay(contentType.name);
      setting.setDesc(`Folder: ${contentType.folder}`).addToggle((toggle) => toggle.setValue(contentType.enabled).onChange((value) => {
        contentType.enabled = value;
      }));
      let indexFileSlot;
      new import_obsidian8.Setting(block).setName(`${contentType.name} - File organization`).setDesc("Choose how content is organized for this content type").addDropdown((dropdown) => dropdown.addOption("file", "File-based").addOption("folder", "Folder-based").setValue(contentType.fileOrganization || "file").onChange((value) => {
        contentType.fileOrganization = value;
        this.renderIndexFileSlot(contentType, indexFileSlot);
      }));
      indexFileSlot = block.createDiv({ cls: "vault-cms-index-file-slot" });
      this.renderIndexFileSlot(contentType, indexFileSlot);
      const pathParts = contentType.folder.split("/").filter((p) => p.length > 0);
      const folderName = pathParts[pathParts.length - 1] || contentType.folder;
      const defaultLinkBasePath = `/${folderName}/`;
      new import_obsidian8.Setting(block).setName(`${contentType.name} - Link base path`).setDesc(`URL path for this content type ("/posts/" or "/" for root). Leave blank to use default: ${defaultLinkBasePath}`).addText((text) => text.setPlaceholder(defaultLinkBasePath).setValue(contentType.linkBasePath || "").onChange((value) => {
        contentType.linkBasePath = value || void 0;
      }));
    }
    const addButton = stepContentWrapper.createEl("button", {
      text: "Add additional content type",
      cls: "mod-cta"
    });
    setCssProps3(addButton, { marginTop: "20px", marginBottom: "30px" });
    addButton.addEventListener("click", () => {
      void (async () => {
        const selectedFolder = this.selectContentTypeFolder();
        if (selectedFolder) {
          const vaultPath = this.getVaultPath();
          let folderPath = selectedFolder;
          if (selectedFolder.startsWith(vaultPath)) {
            folderPath = selectedFolder.substring(vaultPath.length).replace(/^[/\\]+/, "");
          }
          const pathParts = folderPath.split(/[/\\]/).filter((p) => p.length > 0);
          const leafFolderName = pathParts[pathParts.length - 1] || folderPath;
          const newType = {
            id: `content-type-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
            name: this.capitalizeFirst(leafFolderName),
            folder: folderPath,
            fileOrganization: "file",
            enabled: true,
            // Enable by default so it shows up in Step 5
            indexFileName: "index"
          };
          this.state.contentTypes.push(newType);
          await this.display();
        }
      })();
    });
    restoreScroll();
  }
  /**
   * Select folder for additional content type
   */
  selectContentTypeFolder() {
    var _a, _b;
    try {
      let dialog = null;
      try {
        const electronRemote = require("@electron/remote");
        dialog = (electronRemote == null ? void 0 : electronRemote.dialog) || null;
      } catch (e) {
      }
      if (!dialog) {
        try {
          const electron = ((_a = window.require) == null ? void 0 : _a.call(window, "electron")) || require("electron");
          dialog = ((_b = electron == null ? void 0 : electron.remote) == null ? void 0 : _b.dialog) || null;
        } catch (e) {
        }
      }
      if (!dialog) {
        try {
          const electron = require("electron");
          dialog = (electron == null ? void 0 : electron.dialog) || null;
        } catch (e) {
        }
      }
      if (!dialog || typeof dialog.showOpenDialogSync !== "function") {
        throw new Error("Electron dialog API not available");
      }
      const vaultPath = this.getVaultPath();
      const result = dialog.showOpenDialogSync({
        title: "Select Content Type Folder",
        defaultPath: vaultPath,
        properties: ["openDirectory"]
      });
      if (result && result.length > 0) {
        return result[0].replace(/\\/g, "/").replace(/\/$/, "");
      }
    } catch (error) {
      console.error("Error opening folder picker:", error);
      new import_obsidian8.Notice("Unable to open folder picker. Please ensure you are using Obsidian on desktop.");
    }
    return null;
  }
  /**
   * Get the vault path
   */
  getVaultPath() {
    const adapter = this.app.vault.adapter;
    const vaultPath = adapter.basePath || adapter.path;
    if (vaultPath) {
      if (vaultPath.startsWith("/") || /^[A-Z]:/.test(vaultPath)) {
        return vaultPath.replace(/\\/g, "/");
      }
      return vaultPath.replace(/\\/g, "/");
    }
    return "/";
  }
  /**
   * Capitalize first letter
   */
  capitalizeFirst(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }
  validate() {
    return this.state.contentTypes.some((ct) => ct.enabled);
  }
  getTitle() {
    return "Content types";
  }
  getDescription() {
    return "Configure content types";
  }
};

// src/ui/wizard/FrontmatterPropertiesStep.ts
var import_obsidian10 = require("obsidian");

// src/utils/FrontmatterAnalyzer.ts
var import_obsidian9 = require("obsidian");

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/nodes/identity.js
var ALIAS = Symbol.for("yaml.alias");
var DOC = Symbol.for("yaml.document");
var MAP = Symbol.for("yaml.map");
var PAIR = Symbol.for("yaml.pair");
var SCALAR = Symbol.for("yaml.scalar");
var SEQ = Symbol.for("yaml.seq");
var NODE_TYPE = Symbol.for("yaml.node.type");
var isAlias = (node) => !!node && typeof node === "object" && node[NODE_TYPE] === ALIAS;
var isDocument = (node) => !!node && typeof node === "object" && node[NODE_TYPE] === DOC;
var isMap = (node) => !!node && typeof node === "object" && node[NODE_TYPE] === MAP;
var isPair = (node) => !!node && typeof node === "object" && node[NODE_TYPE] === PAIR;
var isScalar = (node) => !!node && typeof node === "object" && node[NODE_TYPE] === SCALAR;
var isSeq = (node) => !!node && typeof node === "object" && node[NODE_TYPE] === SEQ;
function isCollection(node) {
  if (node && typeof node === "object")
    switch (node[NODE_TYPE]) {
      case MAP:
      case SEQ:
        return true;
    }
  return false;
}
function isNode(node) {
  if (node && typeof node === "object")
    switch (node[NODE_TYPE]) {
      case ALIAS:
      case MAP:
      case SCALAR:
      case SEQ:
        return true;
    }
  return false;
}
var hasAnchor = (node) => (isScalar(node) || isCollection(node)) && !!node.anchor;

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/visit.js
var BREAK = Symbol("break visit");
var SKIP = Symbol("skip children");
var REMOVE = Symbol("remove node");
function visit(node, visitor) {
  const visitor_ = initVisitor(visitor);
  if (isDocument(node)) {
    const cd = visit_(null, node.contents, visitor_, Object.freeze([node]));
    if (cd === REMOVE)
      node.contents = null;
  } else
    visit_(null, node, visitor_, Object.freeze([]));
}
visit.BREAK = BREAK;
visit.SKIP = SKIP;
visit.REMOVE = REMOVE;
function visit_(key, node, visitor, path13) {
  const ctrl = callVisitor(key, node, visitor, path13);
  if (isNode(ctrl) || isPair(ctrl)) {
    replaceNode(key, path13, ctrl);
    return visit_(key, ctrl, visitor, path13);
  }
  if (typeof ctrl !== "symbol") {
    if (isCollection(node)) {
      path13 = Object.freeze(path13.concat(node));
      for (let i = 0; i < node.items.length; ++i) {
        const ci = visit_(i, node.items[i], visitor, path13);
        if (typeof ci === "number")
          i = ci - 1;
        else if (ci === BREAK)
          return BREAK;
        else if (ci === REMOVE) {
          node.items.splice(i, 1);
          i -= 1;
        }
      }
    } else if (isPair(node)) {
      path13 = Object.freeze(path13.concat(node));
      const ck = visit_("key", node.key, visitor, path13);
      if (ck === BREAK)
        return BREAK;
      else if (ck === REMOVE)
        node.key = null;
      const cv = visit_("value", node.value, visitor, path13);
      if (cv === BREAK)
        return BREAK;
      else if (cv === REMOVE)
        node.value = null;
    }
  }
  return ctrl;
}
async function visitAsync(node, visitor) {
  const visitor_ = initVisitor(visitor);
  if (isDocument(node)) {
    const cd = await visitAsync_(null, node.contents, visitor_, Object.freeze([node]));
    if (cd === REMOVE)
      node.contents = null;
  } else
    await visitAsync_(null, node, visitor_, Object.freeze([]));
}
visitAsync.BREAK = BREAK;
visitAsync.SKIP = SKIP;
visitAsync.REMOVE = REMOVE;
async function visitAsync_(key, node, visitor, path13) {
  const ctrl = await callVisitor(key, node, visitor, path13);
  if (isNode(ctrl) || isPair(ctrl)) {
    replaceNode(key, path13, ctrl);
    return visitAsync_(key, ctrl, visitor, path13);
  }
  if (typeof ctrl !== "symbol") {
    if (isCollection(node)) {
      path13 = Object.freeze(path13.concat(node));
      for (let i = 0; i < node.items.length; ++i) {
        const ci = await visitAsync_(i, node.items[i], visitor, path13);
        if (typeof ci === "number")
          i = ci - 1;
        else if (ci === BREAK)
          return BREAK;
        else if (ci === REMOVE) {
          node.items.splice(i, 1);
          i -= 1;
        }
      }
    } else if (isPair(node)) {
      path13 = Object.freeze(path13.concat(node));
      const ck = await visitAsync_("key", node.key, visitor, path13);
      if (ck === BREAK)
        return BREAK;
      else if (ck === REMOVE)
        node.key = null;
      const cv = await visitAsync_("value", node.value, visitor, path13);
      if (cv === BREAK)
        return BREAK;
      else if (cv === REMOVE)
        node.value = null;
    }
  }
  return ctrl;
}
function initVisitor(visitor) {
  if (typeof visitor === "object" && (visitor.Collection || visitor.Node || visitor.Value)) {
    return Object.assign({
      Alias: visitor.Node,
      Map: visitor.Node,
      Scalar: visitor.Node,
      Seq: visitor.Node
    }, visitor.Value && {
      Map: visitor.Value,
      Scalar: visitor.Value,
      Seq: visitor.Value
    }, visitor.Collection && {
      Map: visitor.Collection,
      Seq: visitor.Collection
    }, visitor);
  }
  return visitor;
}
function callVisitor(key, node, visitor, path13) {
  var _a, _b, _c, _d, _e;
  if (typeof visitor === "function")
    return visitor(key, node, path13);
  if (isMap(node))
    return (_a = visitor.Map) == null ? void 0 : _a.call(visitor, key, node, path13);
  if (isSeq(node))
    return (_b = visitor.Seq) == null ? void 0 : _b.call(visitor, key, node, path13);
  if (isPair(node))
    return (_c = visitor.Pair) == null ? void 0 : _c.call(visitor, key, node, path13);
  if (isScalar(node))
    return (_d = visitor.Scalar) == null ? void 0 : _d.call(visitor, key, node, path13);
  if (isAlias(node))
    return (_e = visitor.Alias) == null ? void 0 : _e.call(visitor, key, node, path13);
  return void 0;
}
function replaceNode(key, path13, node) {
  const parent = path13[path13.length - 1];
  if (isCollection(parent)) {
    parent.items[key] = node;
  } else if (isPair(parent)) {
    if (key === "key")
      parent.key = node;
    else
      parent.value = node;
  } else if (isDocument(parent)) {
    parent.contents = node;
  } else {
    const pt = isAlias(parent) ? "alias" : "scalar";
    throw new Error(`Cannot replace node with ${pt} parent`);
  }
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/doc/directives.js
var escapeChars = {
  "!": "%21",
  ",": "%2C",
  "[": "%5B",
  "]": "%5D",
  "{": "%7B",
  "}": "%7D"
};
var escapeTagName = (tn) => tn.replace(/[!,[\]{}]/g, (ch) => escapeChars[ch]);
var Directives = class _Directives {
  constructor(yaml, tags) {
    this.docStart = null;
    this.docEnd = false;
    this.yaml = Object.assign({}, _Directives.defaultYaml, yaml);
    this.tags = Object.assign({}, _Directives.defaultTags, tags);
  }
  clone() {
    const copy = new _Directives(this.yaml, this.tags);
    copy.docStart = this.docStart;
    return copy;
  }
  /**
   * During parsing, get a Directives instance for the current document and
   * update the stream state according to the current version's spec.
   */
  atDocument() {
    const res = new _Directives(this.yaml, this.tags);
    switch (this.yaml.version) {
      case "1.1":
        this.atNextDocument = true;
        break;
      case "1.2":
        this.atNextDocument = false;
        this.yaml = {
          explicit: _Directives.defaultYaml.explicit,
          version: "1.2"
        };
        this.tags = Object.assign({}, _Directives.defaultTags);
        break;
    }
    return res;
  }
  /**
   * @param onError - May be called even if the action was successful
   * @returns `true` on success
   */
  add(line, onError) {
    if (this.atNextDocument) {
      this.yaml = { explicit: _Directives.defaultYaml.explicit, version: "1.1" };
      this.tags = Object.assign({}, _Directives.defaultTags);
      this.atNextDocument = false;
    }
    const parts = line.trim().split(/[ \t]+/);
    const name = parts.shift();
    switch (name) {
      case "%TAG": {
        if (parts.length !== 2) {
          onError(0, "%TAG directive should contain exactly two parts");
          if (parts.length < 2)
            return false;
        }
        const [handle, prefix] = parts;
        this.tags[handle] = prefix;
        return true;
      }
      case "%YAML": {
        this.yaml.explicit = true;
        if (parts.length !== 1) {
          onError(0, "%YAML directive should contain exactly one part");
          return false;
        }
        const [version] = parts;
        if (version === "1.1" || version === "1.2") {
          this.yaml.version = version;
          return true;
        } else {
          const isValid = /^\d+\.\d+$/.test(version);
          onError(6, `Unsupported YAML version ${version}`, isValid);
          return false;
        }
      }
      default:
        onError(0, `Unknown directive ${name}`, true);
        return false;
    }
  }
  /**
   * Resolves a tag, matching handles to those defined in %TAG directives.
   *
   * @returns Resolved tag, which may also be the non-specific tag `'!'` or a
   *   `'!local'` tag, or `null` if unresolvable.
   */
  tagName(source, onError) {
    if (source === "!")
      return "!";
    if (source[0] !== "!") {
      onError(`Not a valid tag: ${source}`);
      return null;
    }
    if (source[1] === "<") {
      const verbatim = source.slice(2, -1);
      if (verbatim === "!" || verbatim === "!!") {
        onError(`Verbatim tags aren't resolved, so ${source} is invalid.`);
        return null;
      }
      if (source[source.length - 1] !== ">")
        onError("Verbatim tags must end with a >");
      return verbatim;
    }
    const [, handle, suffix] = source.match(/^(.*!)([^!]*)$/s);
    if (!suffix)
      onError(`The ${source} tag has no suffix`);
    const prefix = this.tags[handle];
    if (prefix) {
      try {
        return prefix + decodeURIComponent(suffix);
      } catch (error) {
        onError(String(error));
        return null;
      }
    }
    if (handle === "!")
      return source;
    onError(`Could not resolve tag: ${source}`);
    return null;
  }
  /**
   * Given a fully resolved tag, returns its printable string form,
   * taking into account current tag prefixes and defaults.
   */
  tagString(tag) {
    for (const [handle, prefix] of Object.entries(this.tags)) {
      if (tag.startsWith(prefix))
        return handle + escapeTagName(tag.substring(prefix.length));
    }
    return tag[0] === "!" ? tag : `!<${tag}>`;
  }
  toString(doc) {
    const lines = this.yaml.explicit ? [`%YAML ${this.yaml.version || "1.2"}`] : [];
    const tagEntries = Object.entries(this.tags);
    let tagNames;
    if (doc && tagEntries.length > 0 && isNode(doc.contents)) {
      const tags = {};
      visit(doc.contents, (_key, node) => {
        if (isNode(node) && node.tag)
          tags[node.tag] = true;
      });
      tagNames = Object.keys(tags);
    } else
      tagNames = [];
    for (const [handle, prefix] of tagEntries) {
      if (handle === "!!" && prefix === "tag:yaml.org,2002:")
        continue;
      if (!doc || tagNames.some((tn) => tn.startsWith(prefix)))
        lines.push(`%TAG ${handle} ${prefix}`);
    }
    return lines.join("\n");
  }
};
Directives.defaultYaml = { explicit: false, version: "1.2" };
Directives.defaultTags = { "!!": "tag:yaml.org,2002:" };

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/doc/anchors.js
function anchorIsValid(anchor) {
  if (/[\x00-\x19\s,[\]{}]/.test(anchor)) {
    const sa = JSON.stringify(anchor);
    const msg = `Anchor must not contain whitespace or control characters: ${sa}`;
    throw new Error(msg);
  }
  return true;
}
function anchorNames(root) {
  const anchors = /* @__PURE__ */ new Set();
  visit(root, {
    Value(_key, node) {
      if (node.anchor)
        anchors.add(node.anchor);
    }
  });
  return anchors;
}
function findNewAnchor(prefix, exclude) {
  for (let i = 1; true; ++i) {
    const name = `${prefix}${i}`;
    if (!exclude.has(name))
      return name;
  }
}
function createNodeAnchors(doc, prefix) {
  const aliasObjects = [];
  const sourceObjects = /* @__PURE__ */ new Map();
  let prevAnchors = null;
  return {
    onAnchor: (source) => {
      aliasObjects.push(source);
      prevAnchors != null ? prevAnchors : prevAnchors = anchorNames(doc);
      const anchor = findNewAnchor(prefix, prevAnchors);
      prevAnchors.add(anchor);
      return anchor;
    },
    /**
     * With circular references, the source node is only resolved after all
     * of its child nodes are. This is why anchors are set only after all of
     * the nodes have been created.
     */
    setAnchors: () => {
      for (const source of aliasObjects) {
        const ref = sourceObjects.get(source);
        if (typeof ref === "object" && ref.anchor && (isScalar(ref.node) || isCollection(ref.node))) {
          ref.node.anchor = ref.anchor;
        } else {
          const error = new Error("Failed to resolve repeated object (this should not happen)");
          error.source = source;
          throw error;
        }
      }
    },
    sourceObjects
  };
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/doc/applyReviver.js
function applyReviver(reviver, obj, key, val) {
  if (val && typeof val === "object") {
    if (Array.isArray(val)) {
      for (let i = 0, len = val.length; i < len; ++i) {
        const v0 = val[i];
        const v1 = applyReviver(reviver, val, String(i), v0);
        if (v1 === void 0)
          delete val[i];
        else if (v1 !== v0)
          val[i] = v1;
      }
    } else if (val instanceof Map) {
      for (const k of Array.from(val.keys())) {
        const v0 = val.get(k);
        const v1 = applyReviver(reviver, val, k, v0);
        if (v1 === void 0)
          val.delete(k);
        else if (v1 !== v0)
          val.set(k, v1);
      }
    } else if (val instanceof Set) {
      for (const v0 of Array.from(val)) {
        const v1 = applyReviver(reviver, val, v0, v0);
        if (v1 === void 0)
          val.delete(v0);
        else if (v1 !== v0) {
          val.delete(v0);
          val.add(v1);
        }
      }
    } else {
      for (const [k, v0] of Object.entries(val)) {
        const v1 = applyReviver(reviver, val, k, v0);
        if (v1 === void 0)
          delete val[k];
        else if (v1 !== v0)
          val[k] = v1;
      }
    }
  }
  return reviver.call(obj, key, val);
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/nodes/toJS.js
function toJS(value, arg, ctx) {
  if (Array.isArray(value))
    return value.map((v, i) => toJS(v, String(i), ctx));
  if (value && typeof value.toJSON === "function") {
    if (!ctx || !hasAnchor(value))
      return value.toJSON(arg, ctx);
    const data = { aliasCount: 0, count: 1, res: void 0 };
    ctx.anchors.set(value, data);
    ctx.onCreate = (res2) => {
      data.res = res2;
      delete ctx.onCreate;
    };
    const res = value.toJSON(arg, ctx);
    if (ctx.onCreate)
      ctx.onCreate(res);
    return res;
  }
  if (typeof value === "bigint" && !(ctx == null ? void 0 : ctx.keep))
    return Number(value);
  return value;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/nodes/Node.js
var NodeBase = class {
  constructor(type) {
    Object.defineProperty(this, NODE_TYPE, { value: type });
  }
  /** Create a copy of this node.  */
  clone() {
    const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
    if (this.range)
      copy.range = this.range.slice();
    return copy;
  }
  /** A plain JavaScript representation of this node. */
  toJS(doc, { mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
    if (!isDocument(doc))
      throw new TypeError("A document argument is required");
    const ctx = {
      anchors: /* @__PURE__ */ new Map(),
      doc,
      keep: true,
      mapAsMap: mapAsMap === true,
      mapKeyWarned: false,
      maxAliasCount: typeof maxAliasCount === "number" ? maxAliasCount : 100
    };
    const res = toJS(this, "", ctx);
    if (typeof onAnchor === "function")
      for (const { count, res: res2 } of ctx.anchors.values())
        onAnchor(res2, count);
    return typeof reviver === "function" ? applyReviver(reviver, { "": res }, "", res) : res;
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/nodes/Alias.js
var Alias = class extends NodeBase {
  constructor(source) {
    super(ALIAS);
    this.source = source;
    Object.defineProperty(this, "tag", {
      set() {
        throw new Error("Alias nodes cannot have tags");
      }
    });
  }
  /**
   * Resolve the value of this alias within `doc`, finding the last
   * instance of the `source` anchor before this node.
   */
  resolve(doc, ctx) {
    let nodes;
    if (ctx == null ? void 0 : ctx.aliasResolveCache) {
      nodes = ctx.aliasResolveCache;
    } else {
      nodes = [];
      visit(doc, {
        Node: (_key, node) => {
          if (isAlias(node) || hasAnchor(node))
            nodes.push(node);
        }
      });
      if (ctx)
        ctx.aliasResolveCache = nodes;
    }
    let found = void 0;
    for (const node of nodes) {
      if (node === this)
        break;
      if (node.anchor === this.source)
        found = node;
    }
    return found;
  }
  toJSON(_arg, ctx) {
    if (!ctx)
      return { source: this.source };
    const { anchors, doc, maxAliasCount } = ctx;
    const source = this.resolve(doc, ctx);
    if (!source) {
      const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
      throw new ReferenceError(msg);
    }
    let data = anchors.get(source);
    if (!data) {
      toJS(source, null, ctx);
      data = anchors.get(source);
    }
    if ((data == null ? void 0 : data.res) === void 0) {
      const msg = "This should not happen: Alias anchor was not resolved?";
      throw new ReferenceError(msg);
    }
    if (maxAliasCount >= 0) {
      data.count += 1;
      if (data.aliasCount === 0)
        data.aliasCount = getAliasCount(doc, source, anchors);
      if (data.count * data.aliasCount > maxAliasCount) {
        const msg = "Excessive alias count indicates a resource exhaustion attack";
        throw new ReferenceError(msg);
      }
    }
    return data.res;
  }
  toString(ctx, _onComment, _onChompKeep) {
    const src = `*${this.source}`;
    if (ctx) {
      anchorIsValid(this.source);
      if (ctx.options.verifyAliasOrder && !ctx.anchors.has(this.source)) {
        const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
        throw new Error(msg);
      }
      if (ctx.implicitKey)
        return `${src} `;
    }
    return src;
  }
};
function getAliasCount(doc, node, anchors) {
  if (isAlias(node)) {
    const source = node.resolve(doc);
    const anchor = anchors && source && anchors.get(source);
    return anchor ? anchor.count * anchor.aliasCount : 0;
  } else if (isCollection(node)) {
    let count = 0;
    for (const item of node.items) {
      const c = getAliasCount(doc, item, anchors);
      if (c > count)
        count = c;
    }
    return count;
  } else if (isPair(node)) {
    const kc = getAliasCount(doc, node.key, anchors);
    const vc = getAliasCount(doc, node.value, anchors);
    return Math.max(kc, vc);
  }
  return 1;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/nodes/Scalar.js
var isScalarValue = (value) => !value || typeof value !== "function" && typeof value !== "object";
var Scalar = class extends NodeBase {
  constructor(value) {
    super(SCALAR);
    this.value = value;
  }
  toJSON(arg, ctx) {
    return (ctx == null ? void 0 : ctx.keep) ? this.value : toJS(this.value, arg, ctx);
  }
  toString() {
    return String(this.value);
  }
};
Scalar.BLOCK_FOLDED = "BLOCK_FOLDED";
Scalar.BLOCK_LITERAL = "BLOCK_LITERAL";
Scalar.PLAIN = "PLAIN";
Scalar.QUOTE_DOUBLE = "QUOTE_DOUBLE";
Scalar.QUOTE_SINGLE = "QUOTE_SINGLE";

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/doc/createNode.js
var defaultTagPrefix = "tag:yaml.org,2002:";
function findTagObject(value, tagName, tags) {
  var _a;
  if (tagName) {
    const match = tags.filter((t) => t.tag === tagName);
    const tagObj = (_a = match.find((t) => !t.format)) != null ? _a : match[0];
    if (!tagObj)
      throw new Error(`Tag ${tagName} not found`);
    return tagObj;
  }
  return tags.find((t) => {
    var _a2;
    return ((_a2 = t.identify) == null ? void 0 : _a2.call(t, value)) && !t.format;
  });
}
function createNode(value, tagName, ctx) {
  var _a, _b, _c, _d;
  if (isDocument(value))
    value = value.contents;
  if (isNode(value))
    return value;
  if (isPair(value)) {
    const map2 = (_b = (_a = ctx.schema[MAP]).createNode) == null ? void 0 : _b.call(_a, ctx.schema, null, ctx);
    map2.items.push(value);
    return map2;
  }
  if (value instanceof String || value instanceof Number || value instanceof Boolean || typeof BigInt !== "undefined" && value instanceof BigInt) {
    value = value.valueOf();
  }
  const { aliasDuplicateObjects, onAnchor, onTagObj, schema: schema4, sourceObjects } = ctx;
  let ref = void 0;
  if (aliasDuplicateObjects && value && typeof value === "object") {
    ref = sourceObjects.get(value);
    if (ref) {
      (_c = ref.anchor) != null ? _c : ref.anchor = onAnchor(value);
      return new Alias(ref.anchor);
    } else {
      ref = { anchor: null, node: null };
      sourceObjects.set(value, ref);
    }
  }
  if (tagName == null ? void 0 : tagName.startsWith("!!"))
    tagName = defaultTagPrefix + tagName.slice(2);
  let tagObj = findTagObject(value, tagName, schema4.tags);
  if (!tagObj) {
    if (value && typeof value.toJSON === "function") {
      value = value.toJSON();
    }
    if (!value || typeof value !== "object") {
      const node2 = new Scalar(value);
      if (ref)
        ref.node = node2;
      return node2;
    }
    tagObj = value instanceof Map ? schema4[MAP] : Symbol.iterator in Object(value) ? schema4[SEQ] : schema4[MAP];
  }
  if (onTagObj) {
    onTagObj(tagObj);
    delete ctx.onTagObj;
  }
  const node = (tagObj == null ? void 0 : tagObj.createNode) ? tagObj.createNode(ctx.schema, value, ctx) : typeof ((_d = tagObj == null ? void 0 : tagObj.nodeClass) == null ? void 0 : _d.from) === "function" ? tagObj.nodeClass.from(ctx.schema, value, ctx) : new Scalar(value);
  if (tagName)
    node.tag = tagName;
  else if (!tagObj.default)
    node.tag = tagObj.tag;
  if (ref)
    ref.node = node;
  return node;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/nodes/Collection.js
function collectionFromPath(schema4, path13, value) {
  let v = value;
  for (let i = path13.length - 1; i >= 0; --i) {
    const k = path13[i];
    if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
      const a = [];
      a[k] = v;
      v = a;
    } else {
      v = /* @__PURE__ */ new Map([[k, v]]);
    }
  }
  return createNode(v, void 0, {
    aliasDuplicateObjects: false,
    keepUndefined: false,
    onAnchor: () => {
      throw new Error("This should not happen, please report a bug.");
    },
    schema: schema4,
    sourceObjects: /* @__PURE__ */ new Map()
  });
}
var isEmptyPath = (path13) => path13 == null || typeof path13 === "object" && !!path13[Symbol.iterator]().next().done;
var Collection = class extends NodeBase {
  constructor(type, schema4) {
    super(type);
    Object.defineProperty(this, "schema", {
      value: schema4,
      configurable: true,
      enumerable: false,
      writable: true
    });
  }
  /**
   * Create a copy of this collection.
   *
   * @param schema - If defined, overwrites the original's schema
   */
  clone(schema4) {
    const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
    if (schema4)
      copy.schema = schema4;
    copy.items = copy.items.map((it) => isNode(it) || isPair(it) ? it.clone(schema4) : it);
    if (this.range)
      copy.range = this.range.slice();
    return copy;
  }
  /**
   * Adds a value to the collection. For `!!map` and `!!omap` the value must
   * be a Pair instance or a `{ key, value }` object, which may not have a key
   * that already exists in the map.
   */
  addIn(path13, value) {
    if (isEmptyPath(path13))
      this.add(value);
    else {
      const [key, ...rest] = path13;
      const node = this.get(key, true);
      if (isCollection(node))
        node.addIn(rest, value);
      else if (node === void 0 && this.schema)
        this.set(key, collectionFromPath(this.schema, rest, value));
      else
        throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
    }
  }
  /**
   * Removes a value from the collection.
   * @returns `true` if the item was found and removed.
   */
  deleteIn(path13) {
    const [key, ...rest] = path13;
    if (rest.length === 0)
      return this.delete(key);
    const node = this.get(key, true);
    if (isCollection(node))
      return node.deleteIn(rest);
    else
      throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
  }
  /**
   * Returns item at `key`, or `undefined` if not found. By default unwraps
   * scalar values from their surrounding node; to disable set `keepScalar` to
   * `true` (collections are always returned intact).
   */
  getIn(path13, keepScalar) {
    const [key, ...rest] = path13;
    const node = this.get(key, true);
    if (rest.length === 0)
      return !keepScalar && isScalar(node) ? node.value : node;
    else
      return isCollection(node) ? node.getIn(rest, keepScalar) : void 0;
  }
  hasAllNullValues(allowScalar) {
    return this.items.every((node) => {
      if (!isPair(node))
        return false;
      const n = node.value;
      return n == null || allowScalar && isScalar(n) && n.value == null && !n.commentBefore && !n.comment && !n.tag;
    });
  }
  /**
   * Checks if the collection includes a value with the key `key`.
   */
  hasIn(path13) {
    const [key, ...rest] = path13;
    if (rest.length === 0)
      return this.has(key);
    const node = this.get(key, true);
    return isCollection(node) ? node.hasIn(rest) : false;
  }
  /**
   * Sets a value in this collection. For `!!set`, `value` needs to be a
   * boolean to add/remove the item from the set.
   */
  setIn(path13, value) {
    const [key, ...rest] = path13;
    if (rest.length === 0) {
      this.set(key, value);
    } else {
      const node = this.get(key, true);
      if (isCollection(node))
        node.setIn(rest, value);
      else if (node === void 0 && this.schema)
        this.set(key, collectionFromPath(this.schema, rest, value));
      else
        throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
    }
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/stringify/stringifyComment.js
var stringifyComment = (str) => str.replace(/^(?!$)(?: $)?/gm, "#");
function indentComment(comment, indent) {
  if (/^\n+$/.test(comment))
    return comment.substring(1);
  return indent ? comment.replace(/^(?! *$)/gm, indent) : comment;
}
var lineComment = (str, indent, comment) => str.endsWith("\n") ? indentComment(comment, indent) : comment.includes("\n") ? "\n" + indentComment(comment, indent) : (str.endsWith(" ") ? "" : " ") + comment;

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/stringify/foldFlowLines.js
var FOLD_FLOW = "flow";
var FOLD_BLOCK = "block";
var FOLD_QUOTED = "quoted";
function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
  if (!lineWidth || lineWidth < 0)
    return text;
  if (lineWidth < minContentWidth)
    minContentWidth = 0;
  const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length);
  if (text.length <= endStep)
    return text;
  const folds = [];
  const escapedFolds = {};
  let end = lineWidth - indent.length;
  if (typeof indentAtStart === "number") {
    if (indentAtStart > lineWidth - Math.max(2, minContentWidth))
      folds.push(0);
    else
      end = lineWidth - indentAtStart;
  }
  let split = void 0;
  let prev = void 0;
  let overflow = false;
  let i = -1;
  let escStart = -1;
  let escEnd = -1;
  if (mode === FOLD_BLOCK) {
    i = consumeMoreIndentedLines(text, i, indent.length);
    if (i !== -1)
      end = i + endStep;
  }
  for (let ch; ch = text[i += 1]; ) {
    if (mode === FOLD_QUOTED && ch === "\\") {
      escStart = i;
      switch (text[i + 1]) {
        case "x":
          i += 3;
          break;
        case "u":
          i += 5;
          break;
        case "U":
          i += 9;
          break;
        default:
          i += 1;
      }
      escEnd = i;
    }
    if (ch === "\n") {
      if (mode === FOLD_BLOCK)
        i = consumeMoreIndentedLines(text, i, indent.length);
      end = i + indent.length + endStep;
      split = void 0;
    } else {
      if (ch === " " && prev && prev !== " " && prev !== "\n" && prev !== "	") {
        const next = text[i + 1];
        if (next && next !== " " && next !== "\n" && next !== "	")
          split = i;
      }
      if (i >= end) {
        if (split) {
          folds.push(split);
          end = split + endStep;
          split = void 0;
        } else if (mode === FOLD_QUOTED) {
          while (prev === " " || prev === "	") {
            prev = ch;
            ch = text[i += 1];
            overflow = true;
          }
          const j = i > escEnd + 1 ? i - 2 : escStart - 1;
          if (escapedFolds[j])
            return text;
          folds.push(j);
          escapedFolds[j] = true;
          end = j + endStep;
          split = void 0;
        } else {
          overflow = true;
        }
      }
    }
    prev = ch;
  }
  if (overflow && onOverflow)
    onOverflow();
  if (folds.length === 0)
    return text;
  if (onFold)
    onFold();
  let res = text.slice(0, folds[0]);
  for (let i2 = 0; i2 < folds.length; ++i2) {
    const fold = folds[i2];
    const end2 = folds[i2 + 1] || text.length;
    if (fold === 0)
      res = `
${indent}${text.slice(0, end2)}`;
    else {
      if (mode === FOLD_QUOTED && escapedFolds[fold])
        res += `${text[fold]}\\`;
      res += `
${indent}${text.slice(fold + 1, end2)}`;
    }
  }
  return res;
}
function consumeMoreIndentedLines(text, i, indent) {
  let end = i;
  let start = i + 1;
  let ch = text[start];
  while (ch === " " || ch === "	") {
    if (i < start + indent) {
      ch = text[++i];
    } else {
      do {
        ch = text[++i];
      } while (ch && ch !== "\n");
      end = i;
      start = i + 1;
      ch = text[start];
    }
  }
  return end;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/stringify/stringifyString.js
var getFoldOptions = (ctx, isBlock2) => ({
  indentAtStart: isBlock2 ? ctx.indent.length : ctx.indentAtStart,
  lineWidth: ctx.options.lineWidth,
  minContentWidth: ctx.options.minContentWidth
});
var containsDocumentMarker = (str) => /^(%|---|\.\.\.)/m.test(str);
function lineLengthOverLimit(str, lineWidth, indentLength) {
  if (!lineWidth || lineWidth < 0)
    return false;
  const limit = lineWidth - indentLength;
  const strLen = str.length;
  if (strLen <= limit)
    return false;
  for (let i = 0, start = 0; i < strLen; ++i) {
    if (str[i] === "\n") {
      if (i - start > limit)
        return true;
      start = i + 1;
      if (strLen - start <= limit)
        return false;
    }
  }
  return true;
}
function doubleQuotedString(value, ctx) {
  const json = JSON.stringify(value);
  if (ctx.options.doubleQuotedAsJSON)
    return json;
  const { implicitKey } = ctx;
  const minMultiLineLength = ctx.options.doubleQuotedMinMultiLineLength;
  const indent = ctx.indent || (containsDocumentMarker(value) ? "  " : "");
  let str = "";
  let start = 0;
  for (let i = 0, ch = json[i]; ch; ch = json[++i]) {
    if (ch === " " && json[i + 1] === "\\" && json[i + 2] === "n") {
      str += json.slice(start, i) + "\\ ";
      i += 1;
      start = i;
      ch = "\\";
    }
    if (ch === "\\")
      switch (json[i + 1]) {
        case "u":
          {
            str += json.slice(start, i);
            const code = json.substr(i + 2, 4);
            switch (code) {
              case "0000":
                str += "\\0";
                break;
              case "0007":
                str += "\\a";
                break;
              case "000b":
                str += "\\v";
                break;
              case "001b":
                str += "\\e";
                break;
              case "0085":
                str += "\\N";
                break;
              case "00a0":
                str += "\\_";
                break;
              case "2028":
                str += "\\L";
                break;
              case "2029":
                str += "\\P";
                break;
              default:
                if (code.substr(0, 2) === "00")
                  str += "\\x" + code.substr(2);
                else
                  str += json.substr(i, 6);
            }
            i += 5;
            start = i + 1;
          }
          break;
        case "n":
          if (implicitKey || json[i + 2] === '"' || json.length < minMultiLineLength) {
            i += 1;
          } else {
            str += json.slice(start, i) + "\n\n";
            while (json[i + 2] === "\\" && json[i + 3] === "n" && json[i + 4] !== '"') {
              str += "\n";
              i += 2;
            }
            str += indent;
            if (json[i + 2] === " ")
              str += "\\";
            i += 1;
            start = i + 1;
          }
          break;
        default:
          i += 1;
      }
  }
  str = start ? str + json.slice(start) : json;
  return implicitKey ? str : foldFlowLines(str, indent, FOLD_QUOTED, getFoldOptions(ctx, false));
}
function singleQuotedString(value, ctx) {
  if (ctx.options.singleQuote === false || ctx.implicitKey && value.includes("\n") || /[ \t]\n|\n[ \t]/.test(value))
    return doubleQuotedString(value, ctx);
  const indent = ctx.indent || (containsDocumentMarker(value) ? "  " : "");
  const res = "'" + value.replace(/'/g, "''").replace(/\n+/g, `$&
${indent}`) + "'";
  return ctx.implicitKey ? res : foldFlowLines(res, indent, FOLD_FLOW, getFoldOptions(ctx, false));
}
function quotedString(value, ctx) {
  const { singleQuote } = ctx.options;
  let qs;
  if (singleQuote === false)
    qs = doubleQuotedString;
  else {
    const hasDouble = value.includes('"');
    const hasSingle = value.includes("'");
    if (hasDouble && !hasSingle)
      qs = singleQuotedString;
    else if (hasSingle && !hasDouble)
      qs = doubleQuotedString;
    else
      qs = singleQuote ? singleQuotedString : doubleQuotedString;
  }
  return qs(value, ctx);
}
var blockEndNewlines;
try {
  blockEndNewlines = new RegExp("(^|(?<!\n))\n+(?!\n|$)", "g");
} catch (e) {
  blockEndNewlines = /\n+(?!\n|$)/g;
}
function blockString({ comment, type, value }, ctx, onComment, onChompKeep) {
  const { blockQuote, commentString, lineWidth } = ctx.options;
  if (!blockQuote || /\n[\t ]+$/.test(value)) {
    return quotedString(value, ctx);
  }
  const indent = ctx.indent || (ctx.forceBlockIndent || containsDocumentMarker(value) ? "  " : "");
  const literal = blockQuote === "literal" ? true : blockQuote === "folded" || type === Scalar.BLOCK_FOLDED ? false : type === Scalar.BLOCK_LITERAL ? true : !lineLengthOverLimit(value, lineWidth, indent.length);
  if (!value)
    return literal ? "|\n" : ">\n";
  let chomp;
  let endStart;
  for (endStart = value.length; endStart > 0; --endStart) {
    const ch = value[endStart - 1];
    if (ch !== "\n" && ch !== "	" && ch !== " ")
      break;
  }
  let end = value.substring(endStart);
  const endNlPos = end.indexOf("\n");
  if (endNlPos === -1) {
    chomp = "-";
  } else if (value === end || endNlPos !== end.length - 1) {
    chomp = "+";
    if (onChompKeep)
      onChompKeep();
  } else {
    chomp = "";
  }
  if (end) {
    value = value.slice(0, -end.length);
    if (end[end.length - 1] === "\n")
      end = end.slice(0, -1);
    end = end.replace(blockEndNewlines, `$&${indent}`);
  }
  let startWithSpace = false;
  let startEnd;
  let startNlPos = -1;
  for (startEnd = 0; startEnd < value.length; ++startEnd) {
    const ch = value[startEnd];
    if (ch === " ")
      startWithSpace = true;
    else if (ch === "\n")
      startNlPos = startEnd;
    else
      break;
  }
  let start = value.substring(0, startNlPos < startEnd ? startNlPos + 1 : startEnd);
  if (start) {
    value = value.substring(start.length);
    start = start.replace(/\n+/g, `$&${indent}`);
  }
  const indentSize = indent ? "2" : "1";
  let header = (startWithSpace ? indentSize : "") + chomp;
  if (comment) {
    header += " " + commentString(comment.replace(/ ?[\r\n]+/g, " "));
    if (onComment)
      onComment();
  }
  if (!literal) {
    const foldedValue = value.replace(/\n+/g, "\n$&").replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g, "$1$2").replace(/\n+/g, `$&${indent}`);
    let literalFallback = false;
    const foldOptions = getFoldOptions(ctx, true);
    if (blockQuote !== "folded" && type !== Scalar.BLOCK_FOLDED) {
      foldOptions.onOverflow = () => {
        literalFallback = true;
      };
    }
    const body = foldFlowLines(`${start}${foldedValue}${end}`, indent, FOLD_BLOCK, foldOptions);
    if (!literalFallback)
      return `>${header}
${indent}${body}`;
  }
  value = value.replace(/\n+/g, `$&${indent}`);
  return `|${header}
${indent}${start}${value}${end}`;
}
function plainString(item, ctx, onComment, onChompKeep) {
  const { type, value } = item;
  const { actualString, implicitKey, indent, indentStep, inFlow } = ctx;
  if (implicitKey && value.includes("\n") || inFlow && /[[\]{},]/.test(value)) {
    return quotedString(value, ctx);
  }
  if (/^[\n\t ,[\]{}#&*!|>'"%@`]|^[?-]$|^[?-][ \t]|[\n:][ \t]|[ \t]\n|[\n\t ]#|[\n\t :]$/.test(value)) {
    return implicitKey || inFlow || !value.includes("\n") ? quotedString(value, ctx) : blockString(item, ctx, onComment, onChompKeep);
  }
  if (!implicitKey && !inFlow && type !== Scalar.PLAIN && value.includes("\n")) {
    return blockString(item, ctx, onComment, onChompKeep);
  }
  if (containsDocumentMarker(value)) {
    if (indent === "") {
      ctx.forceBlockIndent = true;
      return blockString(item, ctx, onComment, onChompKeep);
    } else if (implicitKey && indent === indentStep) {
      return quotedString(value, ctx);
    }
  }
  const str = value.replace(/\n+/g, `$&
${indent}`);
  if (actualString) {
    const test = (tag) => {
      var _a;
      return tag.default && tag.tag !== "tag:yaml.org,2002:str" && ((_a = tag.test) == null ? void 0 : _a.test(str));
    };
    const { compat, tags } = ctx.doc.schema;
    if (tags.some(test) || (compat == null ? void 0 : compat.some(test)))
      return quotedString(value, ctx);
  }
  return implicitKey ? str : foldFlowLines(str, indent, FOLD_FLOW, getFoldOptions(ctx, false));
}
function stringifyString(item, ctx, onComment, onChompKeep) {
  const { implicitKey, inFlow } = ctx;
  const ss = typeof item.value === "string" ? item : Object.assign({}, item, { value: String(item.value) });
  let { type } = item;
  if (type !== Scalar.QUOTE_DOUBLE) {
    if (/[\x00-\x08\x0b-\x1f\x7f-\x9f\u{D800}-\u{DFFF}]/u.test(ss.value))
      type = Scalar.QUOTE_DOUBLE;
  }
  const _stringify = (_type) => {
    switch (_type) {
      case Scalar.BLOCK_FOLDED:
      case Scalar.BLOCK_LITERAL:
        return implicitKey || inFlow ? quotedString(ss.value, ctx) : blockString(ss, ctx, onComment, onChompKeep);
      case Scalar.QUOTE_DOUBLE:
        return doubleQuotedString(ss.value, ctx);
      case Scalar.QUOTE_SINGLE:
        return singleQuotedString(ss.value, ctx);
      case Scalar.PLAIN:
        return plainString(ss, ctx, onComment, onChompKeep);
      default:
        return null;
    }
  };
  let res = _stringify(type);
  if (res === null) {
    const { defaultKeyType, defaultStringType } = ctx.options;
    const t = implicitKey && defaultKeyType || defaultStringType;
    res = _stringify(t);
    if (res === null)
      throw new Error(`Unsupported default string type ${t}`);
  }
  return res;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/stringify/stringify.js
function createStringifyContext(doc, options) {
  const opt = Object.assign({
    blockQuote: true,
    commentString: stringifyComment,
    defaultKeyType: null,
    defaultStringType: "PLAIN",
    directives: null,
    doubleQuotedAsJSON: false,
    doubleQuotedMinMultiLineLength: 40,
    falseStr: "false",
    flowCollectionPadding: true,
    indentSeq: true,
    lineWidth: 80,
    minContentWidth: 20,
    nullStr: "null",
    simpleKeys: false,
    singleQuote: null,
    trueStr: "true",
    verifyAliasOrder: true
  }, doc.schema.toStringOptions, options);
  let inFlow;
  switch (opt.collectionStyle) {
    case "block":
      inFlow = false;
      break;
    case "flow":
      inFlow = true;
      break;
    default:
      inFlow = null;
  }
  return {
    anchors: /* @__PURE__ */ new Set(),
    doc,
    flowCollectionPadding: opt.flowCollectionPadding ? " " : "",
    indent: "",
    indentStep: typeof opt.indent === "number" ? " ".repeat(opt.indent) : "  ",
    inFlow,
    options: opt
  };
}
function getTagObject(tags, item) {
  var _a, _b, _c, _d;
  if (item.tag) {
    const match = tags.filter((t) => t.tag === item.tag);
    if (match.length > 0)
      return (_a = match.find((t) => t.format === item.format)) != null ? _a : match[0];
  }
  let tagObj = void 0;
  let obj;
  if (isScalar(item)) {
    obj = item.value;
    let match = tags.filter((t) => {
      var _a2;
      return (_a2 = t.identify) == null ? void 0 : _a2.call(t, obj);
    });
    if (match.length > 1) {
      const testMatch = match.filter((t) => t.test);
      if (testMatch.length > 0)
        match = testMatch;
    }
    tagObj = (_b = match.find((t) => t.format === item.format)) != null ? _b : match.find((t) => !t.format);
  } else {
    obj = item;
    tagObj = tags.find((t) => t.nodeClass && obj instanceof t.nodeClass);
  }
  if (!tagObj) {
    const name = (_d = (_c = obj == null ? void 0 : obj.constructor) == null ? void 0 : _c.name) != null ? _d : obj === null ? "null" : typeof obj;
    throw new Error(`Tag not resolved for ${name} value`);
  }
  return tagObj;
}
function stringifyProps(node, tagObj, { anchors, doc }) {
  var _a;
  if (!doc.directives)
    return "";
  const props = [];
  const anchor = (isScalar(node) || isCollection(node)) && node.anchor;
  if (anchor && anchorIsValid(anchor)) {
    anchors.add(anchor);
    props.push(`&${anchor}`);
  }
  const tag = (_a = node.tag) != null ? _a : tagObj.default ? null : tagObj.tag;
  if (tag)
    props.push(doc.directives.tagString(tag));
  return props.join(" ");
}
function stringify(item, ctx, onComment, onChompKeep) {
  var _a, _b;
  if (isPair(item))
    return item.toString(ctx, onComment, onChompKeep);
  if (isAlias(item)) {
    if (ctx.doc.directives)
      return item.toString(ctx);
    if ((_a = ctx.resolvedAliases) == null ? void 0 : _a.has(item)) {
      throw new TypeError(`Cannot stringify circular structure without alias nodes`);
    } else {
      if (ctx.resolvedAliases)
        ctx.resolvedAliases.add(item);
      else
        ctx.resolvedAliases = /* @__PURE__ */ new Set([item]);
      item = item.resolve(ctx.doc);
    }
  }
  let tagObj = void 0;
  const node = isNode(item) ? item : ctx.doc.createNode(item, { onTagObj: (o) => tagObj = o });
  tagObj != null ? tagObj : tagObj = getTagObject(ctx.doc.schema.tags, node);
  const props = stringifyProps(node, tagObj, ctx);
  if (props.length > 0)
    ctx.indentAtStart = ((_b = ctx.indentAtStart) != null ? _b : 0) + props.length + 1;
  const str = typeof tagObj.stringify === "function" ? tagObj.stringify(node, ctx, onComment, onChompKeep) : isScalar(node) ? stringifyString(node, ctx, onComment, onChompKeep) : node.toString(ctx, onComment, onChompKeep);
  if (!props)
    return str;
  return isScalar(node) || str[0] === "{" || str[0] === "[" ? `${props} ${str}` : `${props}
${ctx.indent}${str}`;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/stringify/stringifyPair.js
function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
  var _a, _b;
  const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
  let keyComment = isNode(key) && key.comment || null;
  if (simpleKeys) {
    if (keyComment) {
      throw new Error("With simple keys, key nodes cannot have comments");
    }
    if (isCollection(key) || !isNode(key) && typeof key === "object") {
      const msg = "With simple keys, collection cannot be used as a key value";
      throw new Error(msg);
    }
  }
  let explicitKey = !simpleKeys && (!key || keyComment && value == null && !ctx.inFlow || isCollection(key) || (isScalar(key) ? key.type === Scalar.BLOCK_FOLDED || key.type === Scalar.BLOCK_LITERAL : typeof key === "object"));
  ctx = Object.assign({}, ctx, {
    allNullValues: false,
    implicitKey: !explicitKey && (simpleKeys || !allNullValues),
    indent: indent + indentStep
  });
  let keyCommentDone = false;
  let chompKeep = false;
  let str = stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
  if (!explicitKey && !ctx.inFlow && str.length > 1024) {
    if (simpleKeys)
      throw new Error("With simple keys, single line scalar must not span more than 1024 characters");
    explicitKey = true;
  }
  if (ctx.inFlow) {
    if (allNullValues || value == null) {
      if (keyCommentDone && onComment)
        onComment();
      return str === "" ? "?" : explicitKey ? `? ${str}` : str;
    }
  } else if (allNullValues && !simpleKeys || value == null && explicitKey) {
    str = `? ${str}`;
    if (keyComment && !keyCommentDone) {
      str += lineComment(str, ctx.indent, commentString(keyComment));
    } else if (chompKeep && onChompKeep)
      onChompKeep();
    return str;
  }
  if (keyCommentDone)
    keyComment = null;
  if (explicitKey) {
    if (keyComment)
      str += lineComment(str, ctx.indent, commentString(keyComment));
    str = `? ${str}
${indent}:`;
  } else {
    str = `${str}:`;
    if (keyComment)
      str += lineComment(str, ctx.indent, commentString(keyComment));
  }
  let vsb, vcb, valueComment;
  if (isNode(value)) {
    vsb = !!value.spaceBefore;
    vcb = value.commentBefore;
    valueComment = value.comment;
  } else {
    vsb = false;
    vcb = null;
    valueComment = null;
    if (value && typeof value === "object")
      value = doc.createNode(value);
  }
  ctx.implicitKey = false;
  if (!explicitKey && !keyComment && isScalar(value))
    ctx.indentAtStart = str.length + 1;
  chompKeep = false;
  if (!indentSeq && indentStep.length >= 2 && !ctx.inFlow && !explicitKey && isSeq(value) && !value.flow && !value.tag && !value.anchor) {
    ctx.indent = ctx.indent.substring(2);
  }
  let valueCommentDone = false;
  const valueStr = stringify(value, ctx, () => valueCommentDone = true, () => chompKeep = true);
  let ws = " ";
  if (keyComment || vsb || vcb) {
    ws = vsb ? "\n" : "";
    if (vcb) {
      const cs = commentString(vcb);
      ws += `
${indentComment(cs, ctx.indent)}`;
    }
    if (valueStr === "" && !ctx.inFlow) {
      if (ws === "\n" && valueComment)
        ws = "\n\n";
    } else {
      ws += `
${ctx.indent}`;
    }
  } else if (!explicitKey && isCollection(value)) {
    const vs0 = valueStr[0];
    const nl0 = valueStr.indexOf("\n");
    const hasNewline = nl0 !== -1;
    const flow = (_b = (_a = ctx.inFlow) != null ? _a : value.flow) != null ? _b : value.items.length === 0;
    if (hasNewline || !flow) {
      let hasPropsLine = false;
      if (hasNewline && (vs0 === "&" || vs0 === "!")) {
        let sp0 = valueStr.indexOf(" ");
        if (vs0 === "&" && sp0 !== -1 && sp0 < nl0 && valueStr[sp0 + 1] === "!") {
          sp0 = valueStr.indexOf(" ", sp0 + 1);
        }
        if (sp0 === -1 || nl0 < sp0)
          hasPropsLine = true;
      }
      if (!hasPropsLine)
        ws = `
${ctx.indent}`;
    }
  } else if (valueStr === "" || valueStr[0] === "\n") {
    ws = "";
  }
  str += ws + valueStr;
  if (ctx.inFlow) {
    if (valueCommentDone && onComment)
      onComment();
  } else if (valueComment && !valueCommentDone) {
    str += lineComment(str, ctx.indent, commentString(valueComment));
  } else if (chompKeep && onChompKeep) {
    onChompKeep();
  }
  return str;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/log.js
function warn(logLevel, warning) {
  if (logLevel === "debug" || logLevel === "warn") {
    console.warn(warning);
  }
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js
var MERGE_KEY = "<<";
var merge = {
  identify: (value) => value === MERGE_KEY || typeof value === "symbol" && value.description === MERGE_KEY,
  default: "key",
  tag: "tag:yaml.org,2002:merge",
  test: /^<<$/,
  resolve: () => Object.assign(new Scalar(Symbol(MERGE_KEY)), {
    addToJSMap: addMergeToJSMap
  }),
  stringify: () => MERGE_KEY
};
var isMergeKey = (ctx, key) => (merge.identify(key) || isScalar(key) && (!key.type || key.type === Scalar.PLAIN) && merge.identify(key.value)) && (ctx == null ? void 0 : ctx.doc.schema.tags.some((tag) => tag.tag === merge.tag && tag.default));
function addMergeToJSMap(ctx, map2, value) {
  value = ctx && isAlias(value) ? value.resolve(ctx.doc) : value;
  if (isSeq(value))
    for (const it of value.items)
      mergeValue(ctx, map2, it);
  else if (Array.isArray(value))
    for (const it of value)
      mergeValue(ctx, map2, it);
  else
    mergeValue(ctx, map2, value);
}
function mergeValue(ctx, map2, value) {
  const source = ctx && isAlias(value) ? value.resolve(ctx.doc) : value;
  if (!isMap(source))
    throw new Error("Merge sources must be maps or map aliases");
  const srcMap = source.toJSON(null, ctx, Map);
  for (const [key, value2] of srcMap) {
    if (map2 instanceof Map) {
      if (!map2.has(key))
        map2.set(key, value2);
    } else if (map2 instanceof Set) {
      map2.add(key);
    } else if (!Object.prototype.hasOwnProperty.call(map2, key)) {
      Object.defineProperty(map2, key, {
        value: value2,
        writable: true,
        enumerable: true,
        configurable: true
      });
    }
  }
  return map2;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js
function addPairToJSMap(ctx, map2, { key, value }) {
  if (isNode(key) && key.addToJSMap)
    key.addToJSMap(ctx, map2, value);
  else if (isMergeKey(ctx, key))
    addMergeToJSMap(ctx, map2, value);
  else {
    const jsKey = toJS(key, "", ctx);
    if (map2 instanceof Map) {
      map2.set(jsKey, toJS(value, jsKey, ctx));
    } else if (map2 instanceof Set) {
      map2.add(jsKey);
    } else {
      const stringKey = stringifyKey(key, jsKey, ctx);
      const jsValue = toJS(value, stringKey, ctx);
      if (stringKey in map2)
        Object.defineProperty(map2, stringKey, {
          value: jsValue,
          writable: true,
          enumerable: true,
          configurable: true
        });
      else
        map2[stringKey] = jsValue;
    }
  }
  return map2;
}
function stringifyKey(key, jsKey, ctx) {
  if (jsKey === null)
    return "";
  if (typeof jsKey !== "object")
    return String(jsKey);
  if (isNode(key) && (ctx == null ? void 0 : ctx.doc)) {
    const strCtx = createStringifyContext(ctx.doc, {});
    strCtx.anchors = /* @__PURE__ */ new Set();
    for (const node of ctx.anchors.keys())
      strCtx.anchors.add(node.anchor);
    strCtx.inFlow = true;
    strCtx.inStringifyKey = true;
    const strKey = key.toString(strCtx);
    if (!ctx.mapKeyWarned) {
      let jsonStr = JSON.stringify(strKey);
      if (jsonStr.length > 40)
        jsonStr = jsonStr.substring(0, 36) + '..."';
      warn(ctx.doc.options.logLevel, `Keys with collection values will be stringified due to JS Object restrictions: ${jsonStr}. Set mapAsMap: true to use object keys.`);
      ctx.mapKeyWarned = true;
    }
    return strKey;
  }
  return JSON.stringify(jsKey);
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/nodes/Pair.js
function createPair(key, value, ctx) {
  const k = createNode(key, void 0, ctx);
  const v = createNode(value, void 0, ctx);
  return new Pair(k, v);
}
var Pair = class _Pair {
  constructor(key, value = null) {
    Object.defineProperty(this, NODE_TYPE, { value: PAIR });
    this.key = key;
    this.value = value;
  }
  clone(schema4) {
    let { key, value } = this;
    if (isNode(key))
      key = key.clone(schema4);
    if (isNode(value))
      value = value.clone(schema4);
    return new _Pair(key, value);
  }
  toJSON(_, ctx) {
    const pair = (ctx == null ? void 0 : ctx.mapAsMap) ? /* @__PURE__ */ new Map() : {};
    return addPairToJSMap(ctx, pair, this);
  }
  toString(ctx, onComment, onChompKeep) {
    return (ctx == null ? void 0 : ctx.doc) ? stringifyPair(this, ctx, onComment, onChompKeep) : JSON.stringify(this);
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/stringify/stringifyCollection.js
function stringifyCollection(collection, ctx, options) {
  var _a;
  const flow = (_a = ctx.inFlow) != null ? _a : collection.flow;
  const stringify4 = flow ? stringifyFlowCollection : stringifyBlockCollection;
  return stringify4(collection, ctx, options);
}
function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
  const { indent, options: { commentString } } = ctx;
  const itemCtx = Object.assign({}, ctx, { indent: itemIndent, type: null });
  let chompKeep = false;
  const lines = [];
  for (let i = 0; i < items.length; ++i) {
    const item = items[i];
    let comment2 = null;
    if (isNode(item)) {
      if (!chompKeep && item.spaceBefore)
        lines.push("");
      addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
      if (item.comment)
        comment2 = item.comment;
    } else if (isPair(item)) {
      const ik = isNode(item.key) ? item.key : null;
      if (ik) {
        if (!chompKeep && ik.spaceBefore)
          lines.push("");
        addCommentBefore(ctx, lines, ik.commentBefore, chompKeep);
      }
    }
    chompKeep = false;
    let str2 = stringify(item, itemCtx, () => comment2 = null, () => chompKeep = true);
    if (comment2)
      str2 += lineComment(str2, itemIndent, commentString(comment2));
    if (chompKeep && comment2)
      chompKeep = false;
    lines.push(blockItemPrefix + str2);
  }
  let str;
  if (lines.length === 0) {
    str = flowChars.start + flowChars.end;
  } else {
    str = lines[0];
    for (let i = 1; i < lines.length; ++i) {
      const line = lines[i];
      str += line ? `
${indent}${line}` : "\n";
    }
  }
  if (comment) {
    str += "\n" + indentComment(commentString(comment), indent);
    if (onComment)
      onComment();
  } else if (chompKeep && onChompKeep)
    onChompKeep();
  return str;
}
function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
  const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
  itemIndent += indentStep;
  const itemCtx = Object.assign({}, ctx, {
    indent: itemIndent,
    inFlow: true,
    type: null
  });
  let reqNewline = false;
  let linesAtValue = 0;
  const lines = [];
  for (let i = 0; i < items.length; ++i) {
    const item = items[i];
    let comment = null;
    if (isNode(item)) {
      if (item.spaceBefore)
        lines.push("");
      addCommentBefore(ctx, lines, item.commentBefore, false);
      if (item.comment)
        comment = item.comment;
    } else if (isPair(item)) {
      const ik = isNode(item.key) ? item.key : null;
      if (ik) {
        if (ik.spaceBefore)
          lines.push("");
        addCommentBefore(ctx, lines, ik.commentBefore, false);
        if (ik.comment)
          reqNewline = true;
      }
      const iv = isNode(item.value) ? item.value : null;
      if (iv) {
        if (iv.comment)
          comment = iv.comment;
        if (iv.commentBefore)
          reqNewline = true;
      } else if (item.value == null && (ik == null ? void 0 : ik.comment)) {
        comment = ik.comment;
      }
    }
    if (comment)
      reqNewline = true;
    let str = stringify(item, itemCtx, () => comment = null);
    if (i < items.length - 1)
      str += ",";
    if (comment)
      str += lineComment(str, itemIndent, commentString(comment));
    if (!reqNewline && (lines.length > linesAtValue || str.includes("\n")))
      reqNewline = true;
    lines.push(str);
    linesAtValue = lines.length;
  }
  const { start, end } = flowChars;
  if (lines.length === 0) {
    return start + end;
  } else {
    if (!reqNewline) {
      const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
      reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
    }
    if (reqNewline) {
      let str = start;
      for (const line of lines)
        str += line ? `
${indentStep}${indent}${line}` : "\n";
      return `${str}
${indent}${end}`;
    } else {
      return `${start}${fcPadding}${lines.join(" ")}${fcPadding}${end}`;
    }
  }
}
function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
  if (comment && chompKeep)
    comment = comment.replace(/^\n+/, "");
  if (comment) {
    const ic = indentComment(commentString(comment), indent);
    lines.push(ic.trimStart());
  }
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/nodes/YAMLMap.js
function findPair(items, key) {
  const k = isScalar(key) ? key.value : key;
  for (const it of items) {
    if (isPair(it)) {
      if (it.key === key || it.key === k)
        return it;
      if (isScalar(it.key) && it.key.value === k)
        return it;
    }
  }
  return void 0;
}
var YAMLMap = class extends Collection {
  static get tagName() {
    return "tag:yaml.org,2002:map";
  }
  constructor(schema4) {
    super(MAP, schema4);
    this.items = [];
  }
  /**
   * A generic collection parsing method that can be extended
   * to other node classes that inherit from YAMLMap
   */
  static from(schema4, obj, ctx) {
    const { keepUndefined, replacer } = ctx;
    const map2 = new this(schema4);
    const add = (key, value) => {
      if (typeof replacer === "function")
        value = replacer.call(obj, key, value);
      else if (Array.isArray(replacer) && !replacer.includes(key))
        return;
      if (value !== void 0 || keepUndefined)
        map2.items.push(createPair(key, value, ctx));
    };
    if (obj instanceof Map) {
      for (const [key, value] of obj)
        add(key, value);
    } else if (obj && typeof obj === "object") {
      for (const key of Object.keys(obj))
        add(key, obj[key]);
    }
    if (typeof schema4.sortMapEntries === "function") {
      map2.items.sort(schema4.sortMapEntries);
    }
    return map2;
  }
  /**
   * Adds a value to the collection.
   *
   * @param overwrite - If not set `true`, using a key that is already in the
   *   collection will throw. Otherwise, overwrites the previous value.
   */
  add(pair, overwrite) {
    var _a;
    let _pair;
    if (isPair(pair))
      _pair = pair;
    else if (!pair || typeof pair !== "object" || !("key" in pair)) {
      _pair = new Pair(pair, pair == null ? void 0 : pair.value);
    } else
      _pair = new Pair(pair.key, pair.value);
    const prev = findPair(this.items, _pair.key);
    const sortEntries = (_a = this.schema) == null ? void 0 : _a.sortMapEntries;
    if (prev) {
      if (!overwrite)
        throw new Error(`Key ${_pair.key} already set`);
      if (isScalar(prev.value) && isScalarValue(_pair.value))
        prev.value.value = _pair.value;
      else
        prev.value = _pair.value;
    } else if (sortEntries) {
      const i = this.items.findIndex((item) => sortEntries(_pair, item) < 0);
      if (i === -1)
        this.items.push(_pair);
      else
        this.items.splice(i, 0, _pair);
    } else {
      this.items.push(_pair);
    }
  }
  delete(key) {
    const it = findPair(this.items, key);
    if (!it)
      return false;
    const del = this.items.splice(this.items.indexOf(it), 1);
    return del.length > 0;
  }
  get(key, keepScalar) {
    var _a;
    const it = findPair(this.items, key);
    const node = it == null ? void 0 : it.value;
    return (_a = !keepScalar && isScalar(node) ? node.value : node) != null ? _a : void 0;
  }
  has(key) {
    return !!findPair(this.items, key);
  }
  set(key, value) {
    this.add(new Pair(key, value), true);
  }
  /**
   * @param ctx - Conversion context, originally set in Document#toJS()
   * @param {Class} Type - If set, forces the returned collection type
   * @returns Instance of Type, Map, or Object
   */
  toJSON(_, ctx, Type) {
    const map2 = Type ? new Type() : (ctx == null ? void 0 : ctx.mapAsMap) ? /* @__PURE__ */ new Map() : {};
    if (ctx == null ? void 0 : ctx.onCreate)
      ctx.onCreate(map2);
    for (const item of this.items)
      addPairToJSMap(ctx, map2, item);
    return map2;
  }
  toString(ctx, onComment, onChompKeep) {
    if (!ctx)
      return JSON.stringify(this);
    for (const item of this.items) {
      if (!isPair(item))
        throw new Error(`Map items must all be pairs; found ${JSON.stringify(item)} instead`);
    }
    if (!ctx.allNullValues && this.hasAllNullValues(false))
      ctx = Object.assign({}, ctx, { allNullValues: true });
    return stringifyCollection(this, ctx, {
      blockItemPrefix: "",
      flowChars: { start: "{", end: "}" },
      itemIndent: ctx.indent || "",
      onChompKeep,
      onComment
    });
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/common/map.js
var map = {
  collection: "map",
  default: true,
  nodeClass: YAMLMap,
  tag: "tag:yaml.org,2002:map",
  resolve(map2, onError) {
    if (!isMap(map2))
      onError("Expected a mapping for this tag");
    return map2;
  },
  createNode: (schema4, obj, ctx) => YAMLMap.from(schema4, obj, ctx)
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/nodes/YAMLSeq.js
var YAMLSeq = class extends Collection {
  static get tagName() {
    return "tag:yaml.org,2002:seq";
  }
  constructor(schema4) {
    super(SEQ, schema4);
    this.items = [];
  }
  add(value) {
    this.items.push(value);
  }
  /**
   * Removes a value from the collection.
   *
   * `key` must contain a representation of an integer for this to succeed.
   * It may be wrapped in a `Scalar`.
   *
   * @returns `true` if the item was found and removed.
   */
  delete(key) {
    const idx = asItemIndex(key);
    if (typeof idx !== "number")
      return false;
    const del = this.items.splice(idx, 1);
    return del.length > 0;
  }
  get(key, keepScalar) {
    const idx = asItemIndex(key);
    if (typeof idx !== "number")
      return void 0;
    const it = this.items[idx];
    return !keepScalar && isScalar(it) ? it.value : it;
  }
  /**
   * Checks if the collection includes a value with the key `key`.
   *
   * `key` must contain a representation of an integer for this to succeed.
   * It may be wrapped in a `Scalar`.
   */
  has(key) {
    const idx = asItemIndex(key);
    return typeof idx === "number" && idx < this.items.length;
  }
  /**
   * Sets a value in this collection. For `!!set`, `value` needs to be a
   * boolean to add/remove the item from the set.
   *
   * If `key` does not contain a representation of an integer, this will throw.
   * It may be wrapped in a `Scalar`.
   */
  set(key, value) {
    const idx = asItemIndex(key);
    if (typeof idx !== "number")
      throw new Error(`Expected a valid index, not ${key}.`);
    const prev = this.items[idx];
    if (isScalar(prev) && isScalarValue(value))
      prev.value = value;
    else
      this.items[idx] = value;
  }
  toJSON(_, ctx) {
    const seq2 = [];
    if (ctx == null ? void 0 : ctx.onCreate)
      ctx.onCreate(seq2);
    let i = 0;
    for (const item of this.items)
      seq2.push(toJS(item, String(i++), ctx));
    return seq2;
  }
  toString(ctx, onComment, onChompKeep) {
    if (!ctx)
      return JSON.stringify(this);
    return stringifyCollection(this, ctx, {
      blockItemPrefix: "- ",
      flowChars: { start: "[", end: "]" },
      itemIndent: (ctx.indent || "") + "  ",
      onChompKeep,
      onComment
    });
  }
  static from(schema4, obj, ctx) {
    const { replacer } = ctx;
    const seq2 = new this(schema4);
    if (obj && Symbol.iterator in Object(obj)) {
      let i = 0;
      for (let it of obj) {
        if (typeof replacer === "function") {
          const key = obj instanceof Set ? it : String(i++);
          it = replacer.call(obj, key, it);
        }
        seq2.items.push(createNode(it, void 0, ctx));
      }
    }
    return seq2;
  }
};
function asItemIndex(key) {
  let idx = isScalar(key) ? key.value : key;
  if (idx && typeof idx === "string")
    idx = Number(idx);
  return typeof idx === "number" && Number.isInteger(idx) && idx >= 0 ? idx : null;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/common/seq.js
var seq = {
  collection: "seq",
  default: true,
  nodeClass: YAMLSeq,
  tag: "tag:yaml.org,2002:seq",
  resolve(seq2, onError) {
    if (!isSeq(seq2))
      onError("Expected a sequence for this tag");
    return seq2;
  },
  createNode: (schema4, obj, ctx) => YAMLSeq.from(schema4, obj, ctx)
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/common/string.js
var string = {
  identify: (value) => typeof value === "string",
  default: true,
  tag: "tag:yaml.org,2002:str",
  resolve: (str) => str,
  stringify(item, ctx, onComment, onChompKeep) {
    ctx = Object.assign({ actualString: true }, ctx);
    return stringifyString(item, ctx, onComment, onChompKeep);
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/common/null.js
var nullTag = {
  identify: (value) => value == null,
  createNode: () => new Scalar(null),
  default: true,
  tag: "tag:yaml.org,2002:null",
  test: /^(?:~|[Nn]ull|NULL)?$/,
  resolve: () => new Scalar(null),
  stringify: ({ source }, ctx) => typeof source === "string" && nullTag.test.test(source) ? source : ctx.options.nullStr
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/core/bool.js
var boolTag = {
  identify: (value) => typeof value === "boolean",
  default: true,
  tag: "tag:yaml.org,2002:bool",
  test: /^(?:[Tt]rue|TRUE|[Ff]alse|FALSE)$/,
  resolve: (str) => new Scalar(str[0] === "t" || str[0] === "T"),
  stringify({ source, value }, ctx) {
    if (source && boolTag.test.test(source)) {
      const sv = source[0] === "t" || source[0] === "T";
      if (value === sv)
        return source;
    }
    return value ? ctx.options.trueStr : ctx.options.falseStr;
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/stringify/stringifyNumber.js
function stringifyNumber({ format, minFractionDigits, tag, value }) {
  if (typeof value === "bigint")
    return String(value);
  const num = typeof value === "number" ? value : Number(value);
  if (!isFinite(num))
    return isNaN(num) ? ".nan" : num < 0 ? "-.inf" : ".inf";
  let n = Object.is(value, -0) ? "-0" : JSON.stringify(value);
  if (!format && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^\d/.test(n)) {
    let i = n.indexOf(".");
    if (i < 0) {
      i = n.length;
      n += ".";
    }
    let d = minFractionDigits - (n.length - i - 1);
    while (d-- > 0)
      n += "0";
  }
  return n;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/core/float.js
var floatNaN = {
  identify: (value) => typeof value === "number",
  default: true,
  tag: "tag:yaml.org,2002:float",
  test: /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,
  resolve: (str) => str.slice(-3).toLowerCase() === "nan" ? NaN : str[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
  stringify: stringifyNumber
};
var floatExp = {
  identify: (value) => typeof value === "number",
  default: true,
  tag: "tag:yaml.org,2002:float",
  format: "EXP",
  test: /^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/,
  resolve: (str) => parseFloat(str),
  stringify(node) {
    const num = Number(node.value);
    return isFinite(num) ? num.toExponential() : stringifyNumber(node);
  }
};
var float = {
  identify: (value) => typeof value === "number",
  default: true,
  tag: "tag:yaml.org,2002:float",
  test: /^[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*)$/,
  resolve(str) {
    const node = new Scalar(parseFloat(str));
    const dot = str.indexOf(".");
    if (dot !== -1 && str[str.length - 1] === "0")
      node.minFractionDigits = str.length - dot - 1;
    return node;
  },
  stringify: stringifyNumber
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/core/int.js
var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
var intResolve = (str, offset, radix, { intAsBigInt }) => intAsBigInt ? BigInt(str) : parseInt(str.substring(offset), radix);
function intStringify(node, radix, prefix) {
  const { value } = node;
  if (intIdentify(value) && value >= 0)
    return prefix + value.toString(radix);
  return stringifyNumber(node);
}
var intOct = {
  identify: (value) => intIdentify(value) && value >= 0,
  default: true,
  tag: "tag:yaml.org,2002:int",
  format: "OCT",
  test: /^0o[0-7]+$/,
  resolve: (str, _onError, opt) => intResolve(str, 2, 8, opt),
  stringify: (node) => intStringify(node, 8, "0o")
};
var int = {
  identify: intIdentify,
  default: true,
  tag: "tag:yaml.org,2002:int",
  test: /^[-+]?[0-9]+$/,
  resolve: (str, _onError, opt) => intResolve(str, 0, 10, opt),
  stringify: stringifyNumber
};
var intHex = {
  identify: (value) => intIdentify(value) && value >= 0,
  default: true,
  tag: "tag:yaml.org,2002:int",
  format: "HEX",
  test: /^0x[0-9a-fA-F]+$/,
  resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt),
  stringify: (node) => intStringify(node, 16, "0x")
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/core/schema.js
var schema = [
  map,
  seq,
  string,
  nullTag,
  boolTag,
  intOct,
  int,
  intHex,
  floatNaN,
  floatExp,
  float
];

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/json/schema.js
function intIdentify2(value) {
  return typeof value === "bigint" || Number.isInteger(value);
}
var stringifyJSON = ({ value }) => JSON.stringify(value);
var jsonScalars = [
  {
    identify: (value) => typeof value === "string",
    default: true,
    tag: "tag:yaml.org,2002:str",
    resolve: (str) => str,
    stringify: stringifyJSON
  },
  {
    identify: (value) => value == null,
    createNode: () => new Scalar(null),
    default: true,
    tag: "tag:yaml.org,2002:null",
    test: /^null$/,
    resolve: () => null,
    stringify: stringifyJSON
  },
  {
    identify: (value) => typeof value === "boolean",
    default: true,
    tag: "tag:yaml.org,2002:bool",
    test: /^true$|^false$/,
    resolve: (str) => str === "true",
    stringify: stringifyJSON
  },
  {
    identify: intIdentify2,
    default: true,
    tag: "tag:yaml.org,2002:int",
    test: /^-?(?:0|[1-9][0-9]*)$/,
    resolve: (str, _onError, { intAsBigInt }) => intAsBigInt ? BigInt(str) : parseInt(str, 10),
    stringify: ({ value }) => intIdentify2(value) ? value.toString() : JSON.stringify(value)
  },
  {
    identify: (value) => typeof value === "number",
    default: true,
    tag: "tag:yaml.org,2002:float",
    test: /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$/,
    resolve: (str) => parseFloat(str),
    stringify: stringifyJSON
  }
];
var jsonError = {
  default: true,
  tag: "",
  test: /^/,
  resolve(str, onError) {
    onError(`Unresolved plain scalar ${JSON.stringify(str)}`);
    return str;
  }
};
var schema2 = [map, seq].concat(jsonScalars, jsonError);

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js
var binary = {
  identify: (value) => value instanceof Uint8Array,
  // Buffer inherits from Uint8Array
  default: false,
  tag: "tag:yaml.org,2002:binary",
  /**
   * Returns a Buffer in node and an Uint8Array in browsers
   *
   * To use the resulting buffer as an image, you'll want to do something like:
   *
   *   const blob = new Blob([buffer], { type: 'image/jpeg' })
   *   document.querySelector('#photo').src = URL.createObjectURL(blob)
   */
  resolve(src, onError) {
    if (typeof atob === "function") {
      const str = atob(src.replace(/[\n\r]/g, ""));
      const buffer = new Uint8Array(str.length);
      for (let i = 0; i < str.length; ++i)
        buffer[i] = str.charCodeAt(i);
      return buffer;
    } else {
      onError("This environment does not support reading binary tags; either Buffer or atob is required");
      return src;
    }
  },
  stringify({ comment, type, value }, ctx, onComment, onChompKeep) {
    if (!value)
      return "";
    const buf = value;
    let str;
    if (typeof btoa === "function") {
      let s = "";
      for (let i = 0; i < buf.length; ++i)
        s += String.fromCharCode(buf[i]);
      str = btoa(s);
    } else {
      throw new Error("This environment does not support writing binary tags; either Buffer or btoa is required");
    }
    type != null ? type : type = Scalar.BLOCK_LITERAL;
    if (type !== Scalar.QUOTE_DOUBLE) {
      const lineWidth = Math.max(ctx.options.lineWidth - ctx.indent.length, ctx.options.minContentWidth);
      const n = Math.ceil(str.length / lineWidth);
      const lines = new Array(n);
      for (let i = 0, o = 0; i < n; ++i, o += lineWidth) {
        lines[i] = str.substr(o, lineWidth);
      }
      str = lines.join(type === Scalar.BLOCK_LITERAL ? "\n" : " ");
    }
    return stringifyString({ comment, type, value: str }, ctx, onComment, onChompKeep);
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js
function resolvePairs(seq2, onError) {
  var _a;
  if (isSeq(seq2)) {
    for (let i = 0; i < seq2.items.length; ++i) {
      let item = seq2.items[i];
      if (isPair(item))
        continue;
      else if (isMap(item)) {
        if (item.items.length > 1)
          onError("Each pair must have its own sequence indicator");
        const pair = item.items[0] || new Pair(new Scalar(null));
        if (item.commentBefore)
          pair.key.commentBefore = pair.key.commentBefore ? `${item.commentBefore}
${pair.key.commentBefore}` : item.commentBefore;
        if (item.comment) {
          const cn = (_a = pair.value) != null ? _a : pair.key;
          cn.comment = cn.comment ? `${item.comment}
${cn.comment}` : item.comment;
        }
        item = pair;
      }
      seq2.items[i] = isPair(item) ? item : new Pair(item);
    }
  } else
    onError("Expected a sequence for this tag");
  return seq2;
}
function createPairs(schema4, iterable, ctx) {
  const { replacer } = ctx;
  const pairs2 = new YAMLSeq(schema4);
  pairs2.tag = "tag:yaml.org,2002:pairs";
  let i = 0;
  if (iterable && Symbol.iterator in Object(iterable))
    for (let it of iterable) {
      if (typeof replacer === "function")
        it = replacer.call(iterable, String(i++), it);
      let key, value;
      if (Array.isArray(it)) {
        if (it.length === 2) {
          key = it[0];
          value = it[1];
        } else
          throw new TypeError(`Expected [key, value] tuple: ${it}`);
      } else if (it && it instanceof Object) {
        const keys = Object.keys(it);
        if (keys.length === 1) {
          key = keys[0];
          value = it[key];
        } else {
          throw new TypeError(`Expected tuple with one key, not ${keys.length} keys`);
        }
      } else {
        key = it;
      }
      pairs2.items.push(createPair(key, value, ctx));
    }
  return pairs2;
}
var pairs = {
  collection: "seq",
  default: false,
  tag: "tag:yaml.org,2002:pairs",
  resolve: resolvePairs,
  createNode: createPairs
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js
var YAMLOMap = class _YAMLOMap extends YAMLSeq {
  constructor() {
    super();
    this.add = YAMLMap.prototype.add.bind(this);
    this.delete = YAMLMap.prototype.delete.bind(this);
    this.get = YAMLMap.prototype.get.bind(this);
    this.has = YAMLMap.prototype.has.bind(this);
    this.set = YAMLMap.prototype.set.bind(this);
    this.tag = _YAMLOMap.tag;
  }
  /**
   * If `ctx` is given, the return type is actually `Map<unknown, unknown>`,
   * but TypeScript won't allow widening the signature of a child method.
   */
  toJSON(_, ctx) {
    if (!ctx)
      return super.toJSON(_);
    const map2 = /* @__PURE__ */ new Map();
    if (ctx == null ? void 0 : ctx.onCreate)
      ctx.onCreate(map2);
    for (const pair of this.items) {
      let key, value;
      if (isPair(pair)) {
        key = toJS(pair.key, "", ctx);
        value = toJS(pair.value, key, ctx);
      } else {
        key = toJS(pair, "", ctx);
      }
      if (map2.has(key))
        throw new Error("Ordered maps must not include duplicate keys");
      map2.set(key, value);
    }
    return map2;
  }
  static from(schema4, iterable, ctx) {
    const pairs2 = createPairs(schema4, iterable, ctx);
    const omap2 = new this();
    omap2.items = pairs2.items;
    return omap2;
  }
};
YAMLOMap.tag = "tag:yaml.org,2002:omap";
var omap = {
  collection: "seq",
  identify: (value) => value instanceof Map,
  nodeClass: YAMLOMap,
  default: false,
  tag: "tag:yaml.org,2002:omap",
  resolve(seq2, onError) {
    const pairs2 = resolvePairs(seq2, onError);
    const seenKeys = [];
    for (const { key } of pairs2.items) {
      if (isScalar(key)) {
        if (seenKeys.includes(key.value)) {
          onError(`Ordered maps must not include duplicate keys: ${key.value}`);
        } else {
          seenKeys.push(key.value);
        }
      }
    }
    return Object.assign(new YAMLOMap(), pairs2);
  },
  createNode: (schema4, iterable, ctx) => YAMLOMap.from(schema4, iterable, ctx)
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js
function boolStringify({ value, source }, ctx) {
  const boolObj = value ? trueTag : falseTag;
  if (source && boolObj.test.test(source))
    return source;
  return value ? ctx.options.trueStr : ctx.options.falseStr;
}
var trueTag = {
  identify: (value) => value === true,
  default: true,
  tag: "tag:yaml.org,2002:bool",
  test: /^(?:Y|y|[Yy]es|YES|[Tt]rue|TRUE|[Oo]n|ON)$/,
  resolve: () => new Scalar(true),
  stringify: boolStringify
};
var falseTag = {
  identify: (value) => value === false,
  default: true,
  tag: "tag:yaml.org,2002:bool",
  test: /^(?:N|n|[Nn]o|NO|[Ff]alse|FALSE|[Oo]ff|OFF)$/,
  resolve: () => new Scalar(false),
  stringify: boolStringify
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js
var floatNaN2 = {
  identify: (value) => typeof value === "number",
  default: true,
  tag: "tag:yaml.org,2002:float",
  test: /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,
  resolve: (str) => str.slice(-3).toLowerCase() === "nan" ? NaN : str[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
  stringify: stringifyNumber
};
var floatExp2 = {
  identify: (value) => typeof value === "number",
  default: true,
  tag: "tag:yaml.org,2002:float",
  format: "EXP",
  test: /^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,
  resolve: (str) => parseFloat(str.replace(/_/g, "")),
  stringify(node) {
    const num = Number(node.value);
    return isFinite(num) ? num.toExponential() : stringifyNumber(node);
  }
};
var float2 = {
  identify: (value) => typeof value === "number",
  default: true,
  tag: "tag:yaml.org,2002:float",
  test: /^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/,
  resolve(str) {
    const node = new Scalar(parseFloat(str.replace(/_/g, "")));
    const dot = str.indexOf(".");
    if (dot !== -1) {
      const f = str.substring(dot + 1).replace(/_/g, "");
      if (f[f.length - 1] === "0")
        node.minFractionDigits = f.length;
    }
    return node;
  },
  stringify: stringifyNumber
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js
var intIdentify3 = (value) => typeof value === "bigint" || Number.isInteger(value);
function intResolve2(str, offset, radix, { intAsBigInt }) {
  const sign = str[0];
  if (sign === "-" || sign === "+")
    offset += 1;
  str = str.substring(offset).replace(/_/g, "");
  if (intAsBigInt) {
    switch (radix) {
      case 2:
        str = `0b${str}`;
        break;
      case 8:
        str = `0o${str}`;
        break;
      case 16:
        str = `0x${str}`;
        break;
    }
    const n2 = BigInt(str);
    return sign === "-" ? BigInt(-1) * n2 : n2;
  }
  const n = parseInt(str, radix);
  return sign === "-" ? -1 * n : n;
}
function intStringify2(node, radix, prefix) {
  const { value } = node;
  if (intIdentify3(value)) {
    const str = value.toString(radix);
    return value < 0 ? "-" + prefix + str.substr(1) : prefix + str;
  }
  return stringifyNumber(node);
}
var intBin = {
  identify: intIdentify3,
  default: true,
  tag: "tag:yaml.org,2002:int",
  format: "BIN",
  test: /^[-+]?0b[0-1_]+$/,
  resolve: (str, _onError, opt) => intResolve2(str, 2, 2, opt),
  stringify: (node) => intStringify2(node, 2, "0b")
};
var intOct2 = {
  identify: intIdentify3,
  default: true,
  tag: "tag:yaml.org,2002:int",
  format: "OCT",
  test: /^[-+]?0[0-7_]+$/,
  resolve: (str, _onError, opt) => intResolve2(str, 1, 8, opt),
  stringify: (node) => intStringify2(node, 8, "0")
};
var int2 = {
  identify: intIdentify3,
  default: true,
  tag: "tag:yaml.org,2002:int",
  test: /^[-+]?[0-9][0-9_]*$/,
  resolve: (str, _onError, opt) => intResolve2(str, 0, 10, opt),
  stringify: stringifyNumber
};
var intHex2 = {
  identify: intIdentify3,
  default: true,
  tag: "tag:yaml.org,2002:int",
  format: "HEX",
  test: /^[-+]?0x[0-9a-fA-F_]+$/,
  resolve: (str, _onError, opt) => intResolve2(str, 2, 16, opt),
  stringify: (node) => intStringify2(node, 16, "0x")
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js
var YAMLSet = class _YAMLSet extends YAMLMap {
  constructor(schema4) {
    super(schema4);
    this.tag = _YAMLSet.tag;
  }
  add(key) {
    let pair;
    if (isPair(key))
      pair = key;
    else if (key && typeof key === "object" && "key" in key && "value" in key && key.value === null)
      pair = new Pair(key.key, null);
    else
      pair = new Pair(key, null);
    const prev = findPair(this.items, pair.key);
    if (!prev)
      this.items.push(pair);
  }
  /**
   * If `keepPair` is `true`, returns the Pair matching `key`.
   * Otherwise, returns the value of that Pair's key.
   */
  get(key, keepPair) {
    const pair = findPair(this.items, key);
    return !keepPair && isPair(pair) ? isScalar(pair.key) ? pair.key.value : pair.key : pair;
  }
  set(key, value) {
    if (typeof value !== "boolean")
      throw new Error(`Expected boolean value for set(key, value) in a YAML set, not ${typeof value}`);
    const prev = findPair(this.items, key);
    if (prev && !value) {
      this.items.splice(this.items.indexOf(prev), 1);
    } else if (!prev && value) {
      this.items.push(new Pair(key));
    }
  }
  toJSON(_, ctx) {
    return super.toJSON(_, ctx, Set);
  }
  toString(ctx, onComment, onChompKeep) {
    if (!ctx)
      return JSON.stringify(this);
    if (this.hasAllNullValues(true))
      return super.toString(Object.assign({}, ctx, { allNullValues: true }), onComment, onChompKeep);
    else
      throw new Error("Set items must all have null values");
  }
  static from(schema4, iterable, ctx) {
    const { replacer } = ctx;
    const set2 = new this(schema4);
    if (iterable && Symbol.iterator in Object(iterable))
      for (let value of iterable) {
        if (typeof replacer === "function")
          value = replacer.call(iterable, value, value);
        set2.items.push(createPair(value, null, ctx));
      }
    return set2;
  }
};
YAMLSet.tag = "tag:yaml.org,2002:set";
var set = {
  collection: "map",
  identify: (value) => value instanceof Set,
  nodeClass: YAMLSet,
  default: false,
  tag: "tag:yaml.org,2002:set",
  createNode: (schema4, iterable, ctx) => YAMLSet.from(schema4, iterable, ctx),
  resolve(map2, onError) {
    if (isMap(map2)) {
      if (map2.hasAllNullValues(true))
        return Object.assign(new YAMLSet(), map2);
      else
        onError("Set items must all have null values");
    } else
      onError("Expected a mapping for this tag");
    return map2;
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js
function parseSexagesimal(str, asBigInt) {
  const sign = str[0];
  const parts = sign === "-" || sign === "+" ? str.substring(1) : str;
  const num = (n) => asBigInt ? BigInt(n) : Number(n);
  const res = parts.replace(/_/g, "").split(":").reduce((res2, p) => res2 * num(60) + num(p), num(0));
  return sign === "-" ? num(-1) * res : res;
}
function stringifySexagesimal(node) {
  let { value } = node;
  let num = (n) => n;
  if (typeof value === "bigint")
    num = (n) => BigInt(n);
  else if (isNaN(value) || !isFinite(value))
    return stringifyNumber(node);
  let sign = "";
  if (value < 0) {
    sign = "-";
    value *= num(-1);
  }
  const _60 = num(60);
  const parts = [value % _60];
  if (value < 60) {
    parts.unshift(0);
  } else {
    value = (value - parts[0]) / _60;
    parts.unshift(value % _60);
    if (value >= 60) {
      value = (value - parts[0]) / _60;
      parts.unshift(value);
    }
  }
  return sign + parts.map((n) => String(n).padStart(2, "0")).join(":").replace(/000000\d*$/, "");
}
var intTime = {
  identify: (value) => typeof value === "bigint" || Number.isInteger(value),
  default: true,
  tag: "tag:yaml.org,2002:int",
  format: "TIME",
  test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+$/,
  resolve: (str, _onError, { intAsBigInt }) => parseSexagesimal(str, intAsBigInt),
  stringify: stringifySexagesimal
};
var floatTime = {
  identify: (value) => typeof value === "number",
  default: true,
  tag: "tag:yaml.org,2002:float",
  format: "TIME",
  test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*$/,
  resolve: (str) => parseSexagesimal(str, false),
  stringify: stringifySexagesimal
};
var timestamp = {
  identify: (value) => value instanceof Date,
  default: true,
  tag: "tag:yaml.org,2002:timestamp",
  // If the time zone is omitted, the timestamp is assumed to be specified in UTC. The time part
  // may be omitted altogether, resulting in a date format. In such a case, the time part is
  // assumed to be 00:00:00Z (start of day, UTC).
  test: RegExp("^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})(?:(?:t|T|[ \\t]+)([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?)?$"),
  resolve(str) {
    const match = str.match(timestamp.test);
    if (!match)
      throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");
    const [, year, month, day, hour, minute, second] = match.map(Number);
    const millisec = match[7] ? Number((match[7] + "00").substr(1, 3)) : 0;
    let date = Date.UTC(year, month - 1, day, hour || 0, minute || 0, second || 0, millisec);
    const tz = match[8];
    if (tz && tz !== "Z") {
      let d = parseSexagesimal(tz, false);
      if (Math.abs(d) < 30)
        d *= 60;
      date -= 6e4 * d;
    }
    return new Date(date);
  },
  stringify: ({ value }) => {
    var _a;
    return (_a = value == null ? void 0 : value.toISOString().replace(/(T00:00:00)?\.000Z$/, "")) != null ? _a : "";
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js
var schema3 = [
  map,
  seq,
  string,
  nullTag,
  trueTag,
  falseTag,
  intBin,
  intOct2,
  int2,
  intHex2,
  floatNaN2,
  floatExp2,
  float2,
  binary,
  merge,
  omap,
  pairs,
  set,
  intTime,
  floatTime,
  timestamp
];

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/tags.js
var schemas = /* @__PURE__ */ new Map([
  ["core", schema],
  ["failsafe", [map, seq, string]],
  ["json", schema2],
  ["yaml11", schema3],
  ["yaml-1.1", schema3]
]);
var tagsByName = {
  binary,
  bool: boolTag,
  float,
  floatExp,
  floatNaN,
  floatTime,
  int,
  intHex,
  intOct,
  intTime,
  map,
  merge,
  null: nullTag,
  omap,
  pairs,
  seq,
  set,
  timestamp
};
var coreKnownTags = {
  "tag:yaml.org,2002:binary": binary,
  "tag:yaml.org,2002:merge": merge,
  "tag:yaml.org,2002:omap": omap,
  "tag:yaml.org,2002:pairs": pairs,
  "tag:yaml.org,2002:set": set,
  "tag:yaml.org,2002:timestamp": timestamp
};
function getTags(customTags, schemaName, addMergeTag) {
  const schemaTags = schemas.get(schemaName);
  if (schemaTags && !customTags) {
    return addMergeTag && !schemaTags.includes(merge) ? schemaTags.concat(merge) : schemaTags.slice();
  }
  let tags = schemaTags;
  if (!tags) {
    if (Array.isArray(customTags))
      tags = [];
    else {
      const keys = Array.from(schemas.keys()).filter((key) => key !== "yaml11").map((key) => JSON.stringify(key)).join(", ");
      throw new Error(`Unknown schema "${schemaName}"; use one of ${keys} or define customTags array`);
    }
  }
  if (Array.isArray(customTags)) {
    for (const tag of customTags)
      tags = tags.concat(tag);
  } else if (typeof customTags === "function") {
    tags = customTags(tags.slice());
  }
  if (addMergeTag)
    tags = tags.concat(merge);
  return tags.reduce((tags2, tag) => {
    const tagObj = typeof tag === "string" ? tagsByName[tag] : tag;
    if (!tagObj) {
      const tagName = JSON.stringify(tag);
      const keys = Object.keys(tagsByName).map((key) => JSON.stringify(key)).join(", ");
      throw new Error(`Unknown custom tag ${tagName}; use one of ${keys}`);
    }
    if (!tags2.includes(tagObj))
      tags2.push(tagObj);
    return tags2;
  }, []);
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/schema/Schema.js
var sortMapEntriesByKey = (a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
var Schema = class _Schema {
  constructor({ compat, customTags, merge: merge2, resolveKnownTags, schema: schema4, sortMapEntries, toStringDefaults }) {
    this.compat = Array.isArray(compat) ? getTags(compat, "compat") : compat ? getTags(null, compat) : null;
    this.name = typeof schema4 === "string" && schema4 || "core";
    this.knownTags = resolveKnownTags ? coreKnownTags : {};
    this.tags = getTags(customTags, this.name, merge2);
    this.toStringOptions = toStringDefaults != null ? toStringDefaults : null;
    Object.defineProperty(this, MAP, { value: map });
    Object.defineProperty(this, SCALAR, { value: string });
    Object.defineProperty(this, SEQ, { value: seq });
    this.sortMapEntries = typeof sortMapEntries === "function" ? sortMapEntries : sortMapEntries === true ? sortMapEntriesByKey : null;
  }
  clone() {
    const copy = Object.create(_Schema.prototype, Object.getOwnPropertyDescriptors(this));
    copy.tags = this.tags.slice();
    return copy;
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/stringify/stringifyDocument.js
function stringifyDocument(doc, options) {
  var _a;
  const lines = [];
  let hasDirectives = options.directives === true;
  if (options.directives !== false && doc.directives) {
    const dir = doc.directives.toString(doc);
    if (dir) {
      lines.push(dir);
      hasDirectives = true;
    } else if (doc.directives.docStart)
      hasDirectives = true;
  }
  if (hasDirectives)
    lines.push("---");
  const ctx = createStringifyContext(doc, options);
  const { commentString } = ctx.options;
  if (doc.commentBefore) {
    if (lines.length !== 1)
      lines.unshift("");
    const cs = commentString(doc.commentBefore);
    lines.unshift(indentComment(cs, ""));
  }
  let chompKeep = false;
  let contentComment = null;
  if (doc.contents) {
    if (isNode(doc.contents)) {
      if (doc.contents.spaceBefore && hasDirectives)
        lines.push("");
      if (doc.contents.commentBefore) {
        const cs = commentString(doc.contents.commentBefore);
        lines.push(indentComment(cs, ""));
      }
      ctx.forceBlockIndent = !!doc.comment;
      contentComment = doc.contents.comment;
    }
    const onChompKeep = contentComment ? void 0 : () => chompKeep = true;
    let body = stringify(doc.contents, ctx, () => contentComment = null, onChompKeep);
    if (contentComment)
      body += lineComment(body, "", commentString(contentComment));
    if ((body[0] === "|" || body[0] === ">") && lines[lines.length - 1] === "---") {
      lines[lines.length - 1] = `--- ${body}`;
    } else
      lines.push(body);
  } else {
    lines.push(stringify(doc.contents, ctx));
  }
  if ((_a = doc.directives) == null ? void 0 : _a.docEnd) {
    if (doc.comment) {
      const cs = commentString(doc.comment);
      if (cs.includes("\n")) {
        lines.push("...");
        lines.push(indentComment(cs, ""));
      } else {
        lines.push(`... ${cs}`);
      }
    } else {
      lines.push("...");
    }
  } else {
    let dc = doc.comment;
    if (dc && chompKeep)
      dc = dc.replace(/^\n+/, "");
    if (dc) {
      if ((!chompKeep || contentComment) && lines[lines.length - 1] !== "")
        lines.push("");
      lines.push(indentComment(commentString(dc), ""));
    }
  }
  return lines.join("\n") + "\n";
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/doc/Document.js
var Document = class _Document {
  constructor(value, replacer, options) {
    this.commentBefore = null;
    this.comment = null;
    this.errors = [];
    this.warnings = [];
    Object.defineProperty(this, NODE_TYPE, { value: DOC });
    let _replacer = null;
    if (typeof replacer === "function" || Array.isArray(replacer)) {
      _replacer = replacer;
    } else if (options === void 0 && replacer) {
      options = replacer;
      replacer = void 0;
    }
    const opt = Object.assign({
      intAsBigInt: false,
      keepSourceTokens: false,
      logLevel: "warn",
      prettyErrors: true,
      strict: true,
      stringKeys: false,
      uniqueKeys: true,
      version: "1.2"
    }, options);
    this.options = opt;
    let { version } = opt;
    if (options == null ? void 0 : options._directives) {
      this.directives = options._directives.atDocument();
      if (this.directives.yaml.explicit)
        version = this.directives.yaml.version;
    } else
      this.directives = new Directives({ version });
    this.setSchema(version, options);
    this.contents = value === void 0 ? null : this.createNode(value, _replacer, options);
  }
  /**
   * Create a deep copy of this Document and its contents.
   *
   * Custom Node values that inherit from `Object` still refer to their original instances.
   */
  clone() {
    const copy = Object.create(_Document.prototype, {
      [NODE_TYPE]: { value: DOC }
    });
    copy.commentBefore = this.commentBefore;
    copy.comment = this.comment;
    copy.errors = this.errors.slice();
    copy.warnings = this.warnings.slice();
    copy.options = Object.assign({}, this.options);
    if (this.directives)
      copy.directives = this.directives.clone();
    copy.schema = this.schema.clone();
    copy.contents = isNode(this.contents) ? this.contents.clone(copy.schema) : this.contents;
    if (this.range)
      copy.range = this.range.slice();
    return copy;
  }
  /** Adds a value to the document. */
  add(value) {
    if (assertCollection(this.contents))
      this.contents.add(value);
  }
  /** Adds a value to the document. */
  addIn(path13, value) {
    if (assertCollection(this.contents))
      this.contents.addIn(path13, value);
  }
  /**
   * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
   *
   * If `node` already has an anchor, `name` is ignored.
   * Otherwise, the `node.anchor` value will be set to `name`,
   * or if an anchor with that name is already present in the document,
   * `name` will be used as a prefix for a new unique anchor.
   * If `name` is undefined, the generated anchor will use 'a' as a prefix.
   */
  createAlias(node, name) {
    if (!node.anchor) {
      const prev = anchorNames(this);
      node.anchor = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
      !name || prev.has(name) ? findNewAnchor(name || "a", prev) : name;
    }
    return new Alias(node.anchor);
  }
  createNode(value, replacer, options) {
    let _replacer = void 0;
    if (typeof replacer === "function") {
      value = replacer.call({ "": value }, "", value);
      _replacer = replacer;
    } else if (Array.isArray(replacer)) {
      const keyToStr = (v) => typeof v === "number" || v instanceof String || v instanceof Number;
      const asStr = replacer.filter(keyToStr).map(String);
      if (asStr.length > 0)
        replacer = replacer.concat(asStr);
      _replacer = replacer;
    } else if (options === void 0 && replacer) {
      options = replacer;
      replacer = void 0;
    }
    const { aliasDuplicateObjects, anchorPrefix, flow, keepUndefined, onTagObj, tag } = options != null ? options : {};
    const { onAnchor, setAnchors, sourceObjects } = createNodeAnchors(
      this,
      // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
      anchorPrefix || "a"
    );
    const ctx = {
      aliasDuplicateObjects: aliasDuplicateObjects != null ? aliasDuplicateObjects : true,
      keepUndefined: keepUndefined != null ? keepUndefined : false,
      onAnchor,
      onTagObj,
      replacer: _replacer,
      schema: this.schema,
      sourceObjects
    };
    const node = createNode(value, tag, ctx);
    if (flow && isCollection(node))
      node.flow = true;
    setAnchors();
    return node;
  }
  /**
   * Convert a key and a value into a `Pair` using the current schema,
   * recursively wrapping all values as `Scalar` or `Collection` nodes.
   */
  createPair(key, value, options = {}) {
    const k = this.createNode(key, null, options);
    const v = this.createNode(value, null, options);
    return new Pair(k, v);
  }
  /**
   * Removes a value from the document.
   * @returns `true` if the item was found and removed.
   */
  delete(key) {
    return assertCollection(this.contents) ? this.contents.delete(key) : false;
  }
  /**
   * Removes a value from the document.
   * @returns `true` if the item was found and removed.
   */
  deleteIn(path13) {
    if (isEmptyPath(path13)) {
      if (this.contents == null)
        return false;
      this.contents = null;
      return true;
    }
    return assertCollection(this.contents) ? this.contents.deleteIn(path13) : false;
  }
  /**
   * Returns item at `key`, or `undefined` if not found. By default unwraps
   * scalar values from their surrounding node; to disable set `keepScalar` to
   * `true` (collections are always returned intact).
   */
  get(key, keepScalar) {
    return isCollection(this.contents) ? this.contents.get(key, keepScalar) : void 0;
  }
  /**
   * Returns item at `path`, or `undefined` if not found. By default unwraps
   * scalar values from their surrounding node; to disable set `keepScalar` to
   * `true` (collections are always returned intact).
   */
  getIn(path13, keepScalar) {
    if (isEmptyPath(path13))
      return !keepScalar && isScalar(this.contents) ? this.contents.value : this.contents;
    return isCollection(this.contents) ? this.contents.getIn(path13, keepScalar) : void 0;
  }
  /**
   * Checks if the document includes a value with the key `key`.
   */
  has(key) {
    return isCollection(this.contents) ? this.contents.has(key) : false;
  }
  /**
   * Checks if the document includes a value at `path`.
   */
  hasIn(path13) {
    if (isEmptyPath(path13))
      return this.contents !== void 0;
    return isCollection(this.contents) ? this.contents.hasIn(path13) : false;
  }
  /**
   * Sets a value in this document. For `!!set`, `value` needs to be a
   * boolean to add/remove the item from the set.
   */
  set(key, value) {
    if (this.contents == null) {
      this.contents = collectionFromPath(this.schema, [key], value);
    } else if (assertCollection(this.contents)) {
      this.contents.set(key, value);
    }
  }
  /**
   * Sets a value in this document. For `!!set`, `value` needs to be a
   * boolean to add/remove the item from the set.
   */
  setIn(path13, value) {
    if (isEmptyPath(path13)) {
      this.contents = value;
    } else if (this.contents == null) {
      this.contents = collectionFromPath(this.schema, Array.from(path13), value);
    } else if (assertCollection(this.contents)) {
      this.contents.setIn(path13, value);
    }
  }
  /**
   * Change the YAML version and schema used by the document.
   * A `null` version disables support for directives, explicit tags, anchors, and aliases.
   * It also requires the `schema` option to be given as a `Schema` instance value.
   *
   * Overrides all previously set schema options.
   */
  setSchema(version, options = {}) {
    if (typeof version === "number")
      version = String(version);
    let opt;
    switch (version) {
      case "1.1":
        if (this.directives)
          this.directives.yaml.version = "1.1";
        else
          this.directives = new Directives({ version: "1.1" });
        opt = { resolveKnownTags: false, schema: "yaml-1.1" };
        break;
      case "1.2":
      case "next":
        if (this.directives)
          this.directives.yaml.version = version;
        else
          this.directives = new Directives({ version });
        opt = { resolveKnownTags: true, schema: "core" };
        break;
      case null:
        if (this.directives)
          delete this.directives;
        opt = null;
        break;
      default: {
        const sv = JSON.stringify(version);
        throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${sv}`);
      }
    }
    if (options.schema instanceof Object)
      this.schema = options.schema;
    else if (opt)
      this.schema = new Schema(Object.assign(opt, options));
    else
      throw new Error(`With a null YAML version, the { schema: Schema } option is required`);
  }
  // json & jsonArg are only used from toJSON()
  toJS({ json, jsonArg, mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
    const ctx = {
      anchors: /* @__PURE__ */ new Map(),
      doc: this,
      keep: !json,
      mapAsMap: mapAsMap === true,
      mapKeyWarned: false,
      maxAliasCount: typeof maxAliasCount === "number" ? maxAliasCount : 100
    };
    const res = toJS(this.contents, jsonArg != null ? jsonArg : "", ctx);
    if (typeof onAnchor === "function")
      for (const { count, res: res2 } of ctx.anchors.values())
        onAnchor(res2, count);
    return typeof reviver === "function" ? applyReviver(reviver, { "": res }, "", res) : res;
  }
  /**
   * A JSON representation of the document `contents`.
   *
   * @param jsonArg Used by `JSON.stringify` to indicate the array index or
   *   property name.
   */
  toJSON(jsonArg, onAnchor) {
    return this.toJS({ json: true, jsonArg, mapAsMap: false, onAnchor });
  }
  /** A YAML representation of the document. */
  toString(options = {}) {
    if (this.errors.length > 0)
      throw new Error("Document with errors cannot be stringified");
    if ("indent" in options && (!Number.isInteger(options.indent) || Number(options.indent) <= 0)) {
      const s = JSON.stringify(options.indent);
      throw new Error(`"indent" option must be a positive integer, not ${s}`);
    }
    return stringifyDocument(this, options);
  }
};
function assertCollection(contents) {
  if (isCollection(contents))
    return true;
  throw new Error("Expected a YAML collection as document contents");
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/errors.js
var YAMLError = class extends Error {
  constructor(name, pos, code, message) {
    super();
    this.name = name;
    this.code = code;
    this.message = message;
    this.pos = pos;
  }
};
var YAMLParseError = class extends YAMLError {
  constructor(pos, code, message) {
    super("YAMLParseError", pos, code, message);
  }
};
var YAMLWarning = class extends YAMLError {
  constructor(pos, code, message) {
    super("YAMLWarning", pos, code, message);
  }
};
var prettifyError = (src, lc) => (error) => {
  if (error.pos[0] === -1)
    return;
  error.linePos = error.pos.map((pos) => lc.linePos(pos));
  const { line, col } = error.linePos[0];
  error.message += ` at line ${line}, column ${col}`;
  let ci = col - 1;
  let lineStr = src.substring(lc.lineStarts[line - 1], lc.lineStarts[line]).replace(/[\n\r]+$/, "");
  if (ci >= 60 && lineStr.length > 80) {
    const trimStart = Math.min(ci - 39, lineStr.length - 79);
    lineStr = "\u2026" + lineStr.substring(trimStart);
    ci -= trimStart - 1;
  }
  if (lineStr.length > 80)
    lineStr = lineStr.substring(0, 79) + "\u2026";
  if (line > 1 && /^ *$/.test(lineStr.substring(0, ci))) {
    let prev = src.substring(lc.lineStarts[line - 2], lc.lineStarts[line - 1]);
    if (prev.length > 80)
      prev = prev.substring(0, 79) + "\u2026\n";
    lineStr = prev + lineStr;
  }
  if (/[^ ]/.test(lineStr)) {
    let count = 1;
    const end = error.linePos[1];
    if ((end == null ? void 0 : end.line) === line && end.col > col) {
      count = Math.max(1, Math.min(end.col - col, 80 - ci));
    }
    const pointer = " ".repeat(ci) + "^".repeat(count);
    error.message += `:

${lineStr}
${pointer}
`;
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/resolve-props.js
function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIndent, startOnNewline }) {
  let spaceBefore = false;
  let atNewline = startOnNewline;
  let hasSpace = startOnNewline;
  let comment = "";
  let commentSep = "";
  let hasNewline = false;
  let reqSpace = false;
  let tab = null;
  let anchor = null;
  let tag = null;
  let newlineAfterProp = null;
  let comma = null;
  let found = null;
  let start = null;
  for (const token of tokens) {
    if (reqSpace) {
      if (token.type !== "space" && token.type !== "newline" && token.type !== "comma")
        onError(token.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space");
      reqSpace = false;
    }
    if (tab) {
      if (atNewline && token.type !== "comment" && token.type !== "newline") {
        onError(tab, "TAB_AS_INDENT", "Tabs are not allowed as indentation");
      }
      tab = null;
    }
    switch (token.type) {
      case "space":
        if (!flow && (indicator !== "doc-start" || (next == null ? void 0 : next.type) !== "flow-collection") && token.source.includes("	")) {
          tab = token;
        }
        hasSpace = true;
        break;
      case "comment": {
        if (!hasSpace)
          onError(token, "MISSING_CHAR", "Comments must be separated from other tokens by white space characters");
        const cb = token.source.substring(1) || " ";
        if (!comment)
          comment = cb;
        else
          comment += commentSep + cb;
        commentSep = "";
        atNewline = false;
        break;
      }
      case "newline":
        if (atNewline) {
          if (comment)
            comment += token.source;
          else if (!found || indicator !== "seq-item-ind")
            spaceBefore = true;
        } else
          commentSep += token.source;
        atNewline = true;
        hasNewline = true;
        if (anchor || tag)
          newlineAfterProp = token;
        hasSpace = true;
        break;
      case "anchor":
        if (anchor)
          onError(token, "MULTIPLE_ANCHORS", "A node can have at most one anchor");
        if (token.source.endsWith(":"))
          onError(token.offset + token.source.length - 1, "BAD_ALIAS", "Anchor ending in : is ambiguous", true);
        anchor = token;
        start != null ? start : start = token.offset;
        atNewline = false;
        hasSpace = false;
        reqSpace = true;
        break;
      case "tag": {
        if (tag)
          onError(token, "MULTIPLE_TAGS", "A node can have at most one tag");
        tag = token;
        start != null ? start : start = token.offset;
        atNewline = false;
        hasSpace = false;
        reqSpace = true;
        break;
      }
      case indicator:
        if (anchor || tag)
          onError(token, "BAD_PROP_ORDER", `Anchors and tags must be after the ${token.source} indicator`);
        if (found)
          onError(token, "UNEXPECTED_TOKEN", `Unexpected ${token.source} in ${flow != null ? flow : "collection"}`);
        found = token;
        atNewline = indicator === "seq-item-ind" || indicator === "explicit-key-ind";
        hasSpace = false;
        break;
      case "comma":
        if (flow) {
          if (comma)
            onError(token, "UNEXPECTED_TOKEN", `Unexpected , in ${flow}`);
          comma = token;
          atNewline = false;
          hasSpace = false;
          break;
        }
      // else fallthrough
      default:
        onError(token, "UNEXPECTED_TOKEN", `Unexpected ${token.type} token`);
        atNewline = false;
        hasSpace = false;
    }
  }
  const last = tokens[tokens.length - 1];
  const end = last ? last.offset + last.source.length : offset;
  if (reqSpace && next && next.type !== "space" && next.type !== "newline" && next.type !== "comma" && (next.type !== "scalar" || next.source !== "")) {
    onError(next.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space");
  }
  if (tab && (atNewline && tab.indent <= parentIndent || (next == null ? void 0 : next.type) === "block-map" || (next == null ? void 0 : next.type) === "block-seq"))
    onError(tab, "TAB_AS_INDENT", "Tabs are not allowed as indentation");
  return {
    comma,
    found,
    spaceBefore,
    comment,
    hasNewline,
    anchor,
    tag,
    newlineAfterProp,
    end,
    start: start != null ? start : end
  };
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/util-contains-newline.js
function containsNewline(key) {
  if (!key)
    return null;
  switch (key.type) {
    case "alias":
    case "scalar":
    case "double-quoted-scalar":
    case "single-quoted-scalar":
      if (key.source.includes("\n"))
        return true;
      if (key.end) {
        for (const st of key.end)
          if (st.type === "newline")
            return true;
      }
      return false;
    case "flow-collection":
      for (const it of key.items) {
        for (const st of it.start)
          if (st.type === "newline")
            return true;
        if (it.sep) {
          for (const st of it.sep)
            if (st.type === "newline")
              return true;
        }
        if (containsNewline(it.key) || containsNewline(it.value))
          return true;
      }
      return false;
    default:
      return true;
  }
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js
function flowIndentCheck(indent, fc, onError) {
  if ((fc == null ? void 0 : fc.type) === "flow-collection") {
    const end = fc.end[0];
    if (end.indent === indent && (end.source === "]" || end.source === "}") && containsNewline(fc)) {
      const msg = "Flow end indicator should be more indented than parent";
      onError(end, "BAD_INDENT", msg, true);
    }
  }
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/util-map-includes.js
function mapIncludes(ctx, items, search) {
  const { uniqueKeys } = ctx.options;
  if (uniqueKeys === false)
    return false;
  const isEqual = typeof uniqueKeys === "function" ? uniqueKeys : (a, b) => a === b || isScalar(a) && isScalar(b) && a.value === b.value;
  return items.some((pair) => isEqual(pair.key, search));
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/resolve-block-map.js
var startColMsg = "All mapping items must start at the same column";
function resolveBlockMap({ composeNode: composeNode2, composeEmptyNode: composeEmptyNode2 }, ctx, bm, onError, tag) {
  var _a, _b;
  const NodeClass = (_a = tag == null ? void 0 : tag.nodeClass) != null ? _a : YAMLMap;
  const map2 = new NodeClass(ctx.schema);
  if (ctx.atRoot)
    ctx.atRoot = false;
  let offset = bm.offset;
  let commentEnd = null;
  for (const collItem of bm.items) {
    const { start, key, sep: sep6, value } = collItem;
    const keyProps = resolveProps(start, {
      indicator: "explicit-key-ind",
      next: key != null ? key : sep6 == null ? void 0 : sep6[0],
      offset,
      onError,
      parentIndent: bm.indent,
      startOnNewline: true
    });
    const implicitKey = !keyProps.found;
    if (implicitKey) {
      if (key) {
        if (key.type === "block-seq")
          onError(offset, "BLOCK_AS_IMPLICIT_KEY", "A block sequence may not be used as an implicit map key");
        else if ("indent" in key && key.indent !== bm.indent)
          onError(offset, "BAD_INDENT", startColMsg);
      }
      if (!keyProps.anchor && !keyProps.tag && !sep6) {
        commentEnd = keyProps.end;
        if (keyProps.comment) {
          if (map2.comment)
            map2.comment += "\n" + keyProps.comment;
          else
            map2.comment = keyProps.comment;
        }
        continue;
      }
      if (keyProps.newlineAfterProp || containsNewline(key)) {
        onError(key != null ? key : start[start.length - 1], "MULTILINE_IMPLICIT_KEY", "Implicit keys need to be on a single line");
      }
    } else if (((_b = keyProps.found) == null ? void 0 : _b.indent) !== bm.indent) {
      onError(offset, "BAD_INDENT", startColMsg);
    }
    ctx.atKey = true;
    const keyStart = keyProps.end;
    const keyNode = key ? composeNode2(ctx, key, keyProps, onError) : composeEmptyNode2(ctx, keyStart, start, null, keyProps, onError);
    if (ctx.schema.compat)
      flowIndentCheck(bm.indent, key, onError);
    ctx.atKey = false;
    if (mapIncludes(ctx, map2.items, keyNode))
      onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
    const valueProps = resolveProps(sep6 != null ? sep6 : [], {
      indicator: "map-value-ind",
      next: value,
      offset: keyNode.range[2],
      onError,
      parentIndent: bm.indent,
      startOnNewline: !key || key.type === "block-scalar"
    });
    offset = valueProps.end;
    if (valueProps.found) {
      if (implicitKey) {
        if ((value == null ? void 0 : value.type) === "block-map" && !valueProps.hasNewline)
          onError(offset, "BLOCK_AS_IMPLICIT_KEY", "Nested mappings are not allowed in compact mappings");
        if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
          onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
      }
      const valueNode = value ? composeNode2(ctx, value, valueProps, onError) : composeEmptyNode2(ctx, offset, sep6, null, valueProps, onError);
      if (ctx.schema.compat)
        flowIndentCheck(bm.indent, value, onError);
      offset = valueNode.range[2];
      const pair = new Pair(keyNode, valueNode);
      if (ctx.options.keepSourceTokens)
        pair.srcToken = collItem;
      map2.items.push(pair);
    } else {
      if (implicitKey)
        onError(keyNode.range, "MISSING_CHAR", "Implicit map keys need to be followed by map values");
      if (valueProps.comment) {
        if (keyNode.comment)
          keyNode.comment += "\n" + valueProps.comment;
        else
          keyNode.comment = valueProps.comment;
      }
      const pair = new Pair(keyNode);
      if (ctx.options.keepSourceTokens)
        pair.srcToken = collItem;
      map2.items.push(pair);
    }
  }
  if (commentEnd && commentEnd < offset)
    onError(commentEnd, "IMPOSSIBLE", "Map comment with trailing content");
  map2.range = [bm.offset, offset, commentEnd != null ? commentEnd : offset];
  return map2;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/resolve-block-seq.js
function resolveBlockSeq({ composeNode: composeNode2, composeEmptyNode: composeEmptyNode2 }, ctx, bs, onError, tag) {
  var _a;
  const NodeClass = (_a = tag == null ? void 0 : tag.nodeClass) != null ? _a : YAMLSeq;
  const seq2 = new NodeClass(ctx.schema);
  if (ctx.atRoot)
    ctx.atRoot = false;
  if (ctx.atKey)
    ctx.atKey = false;
  let offset = bs.offset;
  let commentEnd = null;
  for (const { start, value } of bs.items) {
    const props = resolveProps(start, {
      indicator: "seq-item-ind",
      next: value,
      offset,
      onError,
      parentIndent: bs.indent,
      startOnNewline: true
    });
    if (!props.found) {
      if (props.anchor || props.tag || value) {
        if ((value == null ? void 0 : value.type) === "block-seq")
          onError(props.end, "BAD_INDENT", "All sequence items must start at the same column");
        else
          onError(offset, "MISSING_CHAR", "Sequence item without - indicator");
      } else {
        commentEnd = props.end;
        if (props.comment)
          seq2.comment = props.comment;
        continue;
      }
    }
    const node = value ? composeNode2(ctx, value, props, onError) : composeEmptyNode2(ctx, props.end, start, null, props, onError);
    if (ctx.schema.compat)
      flowIndentCheck(bs.indent, value, onError);
    offset = node.range[2];
    seq2.items.push(node);
  }
  seq2.range = [bs.offset, offset, commentEnd != null ? commentEnd : offset];
  return seq2;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/resolve-end.js
function resolveEnd(end, offset, reqSpace, onError) {
  let comment = "";
  if (end) {
    let hasSpace = false;
    let sep6 = "";
    for (const token of end) {
      const { source, type } = token;
      switch (type) {
        case "space":
          hasSpace = true;
          break;
        case "comment": {
          if (reqSpace && !hasSpace)
            onError(token, "MISSING_CHAR", "Comments must be separated from other tokens by white space characters");
          const cb = source.substring(1) || " ";
          if (!comment)
            comment = cb;
          else
            comment += sep6 + cb;
          sep6 = "";
          break;
        }
        case "newline":
          if (comment)
            sep6 += source;
          hasSpace = true;
          break;
        default:
          onError(token, "UNEXPECTED_TOKEN", `Unexpected ${type} at node end`);
      }
      offset += source.length;
    }
  }
  return { comment, offset };
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js
var blockMsg = "Block collections are not allowed within flow collections";
var isBlock = (token) => token && (token.type === "block-map" || token.type === "block-seq");
function resolveFlowCollection({ composeNode: composeNode2, composeEmptyNode: composeEmptyNode2 }, ctx, fc, onError, tag) {
  var _a, _b, _c;
  const isMap2 = fc.start.source === "{";
  const fcName = isMap2 ? "flow map" : "flow sequence";
  const NodeClass = (_a = tag == null ? void 0 : tag.nodeClass) != null ? _a : isMap2 ? YAMLMap : YAMLSeq;
  const coll = new NodeClass(ctx.schema);
  coll.flow = true;
  const atRoot = ctx.atRoot;
  if (atRoot)
    ctx.atRoot = false;
  if (ctx.atKey)
    ctx.atKey = false;
  let offset = fc.offset + fc.start.source.length;
  for (let i = 0; i < fc.items.length; ++i) {
    const collItem = fc.items[i];
    const { start, key, sep: sep6, value } = collItem;
    const props = resolveProps(start, {
      flow: fcName,
      indicator: "explicit-key-ind",
      next: key != null ? key : sep6 == null ? void 0 : sep6[0],
      offset,
      onError,
      parentIndent: fc.indent,
      startOnNewline: false
    });
    if (!props.found) {
      if (!props.anchor && !props.tag && !sep6 && !value) {
        if (i === 0 && props.comma)
          onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
        else if (i < fc.items.length - 1)
          onError(props.start, "UNEXPECTED_TOKEN", `Unexpected empty item in ${fcName}`);
        if (props.comment) {
          if (coll.comment)
            coll.comment += "\n" + props.comment;
          else
            coll.comment = props.comment;
        }
        offset = props.end;
        continue;
      }
      if (!isMap2 && ctx.options.strict && containsNewline(key))
        onError(
          key,
          // checked by containsNewline()
          "MULTILINE_IMPLICIT_KEY",
          "Implicit keys of flow sequence pairs need to be on a single line"
        );
    }
    if (i === 0) {
      if (props.comma)
        onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
    } else {
      if (!props.comma)
        onError(props.start, "MISSING_CHAR", `Missing , between ${fcName} items`);
      if (props.comment) {
        let prevItemComment = "";
        loop: for (const st of start) {
          switch (st.type) {
            case "comma":
            case "space":
              break;
            case "comment":
              prevItemComment = st.source.substring(1);
              break loop;
            default:
              break loop;
          }
        }
        if (prevItemComment) {
          let prev = coll.items[coll.items.length - 1];
          if (isPair(prev))
            prev = (_b = prev.value) != null ? _b : prev.key;
          if (prev.comment)
            prev.comment += "\n" + prevItemComment;
          else
            prev.comment = prevItemComment;
          props.comment = props.comment.substring(prevItemComment.length + 1);
        }
      }
    }
    if (!isMap2 && !sep6 && !props.found) {
      const valueNode = value ? composeNode2(ctx, value, props, onError) : composeEmptyNode2(ctx, props.end, sep6, null, props, onError);
      coll.items.push(valueNode);
      offset = valueNode.range[2];
      if (isBlock(value))
        onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
    } else {
      ctx.atKey = true;
      const keyStart = props.end;
      const keyNode = key ? composeNode2(ctx, key, props, onError) : composeEmptyNode2(ctx, keyStart, start, null, props, onError);
      if (isBlock(key))
        onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
      ctx.atKey = false;
      const valueProps = resolveProps(sep6 != null ? sep6 : [], {
        flow: fcName,
        indicator: "map-value-ind",
        next: value,
        offset: keyNode.range[2],
        onError,
        parentIndent: fc.indent,
        startOnNewline: false
      });
      if (valueProps.found) {
        if (!isMap2 && !props.found && ctx.options.strict) {
          if (sep6)
            for (const st of sep6) {
              if (st === valueProps.found)
                break;
              if (st.type === "newline") {
                onError(st, "MULTILINE_IMPLICIT_KEY", "Implicit keys of flow sequence pairs need to be on a single line");
                break;
              }
            }
          if (props.start < valueProps.found.offset - 1024)
            onError(valueProps.found, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit flow sequence key");
        }
      } else if (value) {
        if ("source" in value && ((_c = value.source) == null ? void 0 : _c[0]) === ":")
          onError(value, "MISSING_CHAR", `Missing space after : in ${fcName}`);
        else
          onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
      }
      const valueNode = value ? composeNode2(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode2(ctx, valueProps.end, sep6, null, valueProps, onError) : null;
      if (valueNode) {
        if (isBlock(value))
          onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
      } else if (valueProps.comment) {
        if (keyNode.comment)
          keyNode.comment += "\n" + valueProps.comment;
        else
          keyNode.comment = valueProps.comment;
      }
      const pair = new Pair(keyNode, valueNode);
      if (ctx.options.keepSourceTokens)
        pair.srcToken = collItem;
      if (isMap2) {
        const map2 = coll;
        if (mapIncludes(ctx, map2.items, keyNode))
          onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
        map2.items.push(pair);
      } else {
        const map2 = new YAMLMap(ctx.schema);
        map2.flow = true;
        map2.items.push(pair);
        const endRange = (valueNode != null ? valueNode : keyNode).range;
        map2.range = [keyNode.range[0], endRange[1], endRange[2]];
        coll.items.push(map2);
      }
      offset = valueNode ? valueNode.range[2] : valueProps.end;
    }
  }
  const expectedEnd = isMap2 ? "}" : "]";
  const [ce, ...ee] = fc.end;
  let cePos = offset;
  if ((ce == null ? void 0 : ce.source) === expectedEnd)
    cePos = ce.offset + ce.source.length;
  else {
    const name = fcName[0].toUpperCase() + fcName.substring(1);
    const msg = atRoot ? `${name} must end with a ${expectedEnd}` : `${name} in block collection must be sufficiently indented and end with a ${expectedEnd}`;
    onError(offset, atRoot ? "MISSING_CHAR" : "BAD_INDENT", msg);
    if (ce && ce.source.length !== 1)
      ee.unshift(ce);
  }
  if (ee.length > 0) {
    const end = resolveEnd(ee, cePos, ctx.options.strict, onError);
    if (end.comment) {
      if (coll.comment)
        coll.comment += "\n" + end.comment;
      else
        coll.comment = end.comment;
    }
    coll.range = [fc.offset, cePos, end.offset];
  } else {
    coll.range = [fc.offset, cePos, cePos];
  }
  return coll;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/compose-collection.js
function resolveCollection(CN2, ctx, token, onError, tagName, tag) {
  const coll = token.type === "block-map" ? resolveBlockMap(CN2, ctx, token, onError, tag) : token.type === "block-seq" ? resolveBlockSeq(CN2, ctx, token, onError, tag) : resolveFlowCollection(CN2, ctx, token, onError, tag);
  const Coll = coll.constructor;
  if (tagName === "!" || tagName === Coll.tagName) {
    coll.tag = Coll.tagName;
    return coll;
  }
  if (tagName)
    coll.tag = tagName;
  return coll;
}
function composeCollection(CN2, ctx, token, props, onError) {
  var _a, _b, _c;
  const tagToken = props.tag;
  const tagName = !tagToken ? null : ctx.directives.tagName(tagToken.source, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg));
  if (token.type === "block-seq") {
    const { anchor, newlineAfterProp: nl } = props;
    const lastProp = anchor && tagToken ? anchor.offset > tagToken.offset ? anchor : tagToken : anchor != null ? anchor : tagToken;
    if (lastProp && (!nl || nl.offset < lastProp.offset)) {
      const message = "Missing newline after block sequence props";
      onError(lastProp, "MISSING_CHAR", message);
    }
  }
  const expType = token.type === "block-map" ? "map" : token.type === "block-seq" ? "seq" : token.start.source === "{" ? "map" : "seq";
  if (!tagToken || !tagName || tagName === "!" || tagName === YAMLMap.tagName && expType === "map" || tagName === YAMLSeq.tagName && expType === "seq") {
    return resolveCollection(CN2, ctx, token, onError, tagName);
  }
  let tag = ctx.schema.tags.find((t) => t.tag === tagName && t.collection === expType);
  if (!tag) {
    const kt = ctx.schema.knownTags[tagName];
    if ((kt == null ? void 0 : kt.collection) === expType) {
      ctx.schema.tags.push(Object.assign({}, kt, { default: false }));
      tag = kt;
    } else {
      if (kt) {
        onError(tagToken, "BAD_COLLECTION_TYPE", `${kt.tag} used for ${expType} collection, but expects ${(_a = kt.collection) != null ? _a : "scalar"}`, true);
      } else {
        onError(tagToken, "TAG_RESOLVE_FAILED", `Unresolved tag: ${tagName}`, true);
      }
      return resolveCollection(CN2, ctx, token, onError, tagName);
    }
  }
  const coll = resolveCollection(CN2, ctx, token, onError, tagName, tag);
  const res = (_c = (_b = tag.resolve) == null ? void 0 : _b.call(tag, coll, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg), ctx.options)) != null ? _c : coll;
  const node = isNode(res) ? res : new Scalar(res);
  node.range = coll.range;
  node.tag = tagName;
  if (tag == null ? void 0 : tag.format)
    node.format = tag.format;
  return node;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js
function resolveBlockScalar(ctx, scalar, onError) {
  const start = scalar.offset;
  const header = parseBlockScalarHeader(scalar, ctx.options.strict, onError);
  if (!header)
    return { value: "", type: null, comment: "", range: [start, start, start] };
  const type = header.mode === ">" ? Scalar.BLOCK_FOLDED : Scalar.BLOCK_LITERAL;
  const lines = scalar.source ? splitLines(scalar.source) : [];
  let chompStart = lines.length;
  for (let i = lines.length - 1; i >= 0; --i) {
    const content = lines[i][1];
    if (content === "" || content === "\r")
      chompStart = i;
    else
      break;
  }
  if (chompStart === 0) {
    const value2 = header.chomp === "+" && lines.length > 0 ? "\n".repeat(Math.max(1, lines.length - 1)) : "";
    let end2 = start + header.length;
    if (scalar.source)
      end2 += scalar.source.length;
    return { value: value2, type, comment: header.comment, range: [start, end2, end2] };
  }
  let trimIndent = scalar.indent + header.indent;
  let offset = scalar.offset + header.length;
  let contentStart = 0;
  for (let i = 0; i < chompStart; ++i) {
    const [indent, content] = lines[i];
    if (content === "" || content === "\r") {
      if (header.indent === 0 && indent.length > trimIndent)
        trimIndent = indent.length;
    } else {
      if (indent.length < trimIndent) {
        const message = "Block scalars with more-indented leading empty lines must use an explicit indentation indicator";
        onError(offset + indent.length, "MISSING_CHAR", message);
      }
      if (header.indent === 0)
        trimIndent = indent.length;
      contentStart = i;
      if (trimIndent === 0 && !ctx.atRoot) {
        const message = "Block scalar values in collections must be indented";
        onError(offset, "BAD_INDENT", message);
      }
      break;
    }
    offset += indent.length + content.length + 1;
  }
  for (let i = lines.length - 1; i >= chompStart; --i) {
    if (lines[i][0].length > trimIndent)
      chompStart = i + 1;
  }
  let value = "";
  let sep6 = "";
  let prevMoreIndented = false;
  for (let i = 0; i < contentStart; ++i)
    value += lines[i][0].slice(trimIndent) + "\n";
  for (let i = contentStart; i < chompStart; ++i) {
    let [indent, content] = lines[i];
    offset += indent.length + content.length + 1;
    const crlf = content[content.length - 1] === "\r";
    if (crlf)
      content = content.slice(0, -1);
    if (content && indent.length < trimIndent) {
      const src = header.indent ? "explicit indentation indicator" : "first line";
      const message = `Block scalar lines must not be less indented than their ${src}`;
      onError(offset - content.length - (crlf ? 2 : 1), "BAD_INDENT", message);
      indent = "";
    }
    if (type === Scalar.BLOCK_LITERAL) {
      value += sep6 + indent.slice(trimIndent) + content;
      sep6 = "\n";
    } else if (indent.length > trimIndent || content[0] === "	") {
      if (sep6 === " ")
        sep6 = "\n";
      else if (!prevMoreIndented && sep6 === "\n")
        sep6 = "\n\n";
      value += sep6 + indent.slice(trimIndent) + content;
      sep6 = "\n";
      prevMoreIndented = true;
    } else if (content === "") {
      if (sep6 === "\n")
        value += "\n";
      else
        sep6 = "\n";
    } else {
      value += sep6 + content;
      sep6 = " ";
      prevMoreIndented = false;
    }
  }
  switch (header.chomp) {
    case "-":
      break;
    case "+":
      for (let i = chompStart; i < lines.length; ++i)
        value += "\n" + lines[i][0].slice(trimIndent);
      if (value[value.length - 1] !== "\n")
        value += "\n";
      break;
    default:
      value += "\n";
  }
  const end = start + header.length + scalar.source.length;
  return { value, type, comment: header.comment, range: [start, end, end] };
}
function parseBlockScalarHeader({ offset, props }, strict, onError) {
  if (props[0].type !== "block-scalar-header") {
    onError(props[0], "IMPOSSIBLE", "Block scalar header not found");
    return null;
  }
  const { source } = props[0];
  const mode = source[0];
  let indent = 0;
  let chomp = "";
  let error = -1;
  for (let i = 1; i < source.length; ++i) {
    const ch = source[i];
    if (!chomp && (ch === "-" || ch === "+"))
      chomp = ch;
    else {
      const n = Number(ch);
      if (!indent && n)
        indent = n;
      else if (error === -1)
        error = offset + i;
    }
  }
  if (error !== -1)
    onError(error, "UNEXPECTED_TOKEN", `Block scalar header includes extra characters: ${source}`);
  let hasSpace = false;
  let comment = "";
  let length = source.length;
  for (let i = 1; i < props.length; ++i) {
    const token = props[i];
    switch (token.type) {
      case "space":
        hasSpace = true;
      // fallthrough
      case "newline":
        length += token.source.length;
        break;
      case "comment":
        if (strict && !hasSpace) {
          const message = "Comments must be separated from other tokens by white space characters";
          onError(token, "MISSING_CHAR", message);
        }
        length += token.source.length;
        comment = token.source.substring(1);
        break;
      case "error":
        onError(token, "UNEXPECTED_TOKEN", token.message);
        length += token.source.length;
        break;
      /* istanbul ignore next should not happen */
      default: {
        const message = `Unexpected token in block scalar header: ${token.type}`;
        onError(token, "UNEXPECTED_TOKEN", message);
        const ts = token.source;
        if (ts && typeof ts === "string")
          length += ts.length;
      }
    }
  }
  return { mode, indent, chomp, comment, length };
}
function splitLines(source) {
  const split = source.split(/\n( *)/);
  const first = split[0];
  const m = first.match(/^( *)/);
  const line0 = (m == null ? void 0 : m[1]) ? [m[1], first.slice(m[1].length)] : ["", first];
  const lines = [line0];
  for (let i = 1; i < split.length; i += 2)
    lines.push([split[i], split[i + 1]]);
  return lines;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js
function resolveFlowScalar(scalar, strict, onError) {
  const { offset, type, source, end } = scalar;
  let _type;
  let value;
  const _onError = (rel, code, msg) => onError(offset + rel, code, msg);
  switch (type) {
    case "scalar":
      _type = Scalar.PLAIN;
      value = plainValue(source, _onError);
      break;
    case "single-quoted-scalar":
      _type = Scalar.QUOTE_SINGLE;
      value = singleQuotedValue(source, _onError);
      break;
    case "double-quoted-scalar":
      _type = Scalar.QUOTE_DOUBLE;
      value = doubleQuotedValue(source, _onError);
      break;
    /* istanbul ignore next should not happen */
    default:
      onError(scalar, "UNEXPECTED_TOKEN", `Expected a flow scalar value, but found: ${type}`);
      return {
        value: "",
        type: null,
        comment: "",
        range: [offset, offset + source.length, offset + source.length]
      };
  }
  const valueEnd = offset + source.length;
  const re = resolveEnd(end, valueEnd, strict, onError);
  return {
    value,
    type: _type,
    comment: re.comment,
    range: [offset, valueEnd, re.offset]
  };
}
function plainValue(source, onError) {
  let badChar = "";
  switch (source[0]) {
    /* istanbul ignore next should not happen */
    case "	":
      badChar = "a tab character";
      break;
    case ",":
      badChar = "flow indicator character ,";
      break;
    case "%":
      badChar = "directive indicator character %";
      break;
    case "|":
    case ">": {
      badChar = `block scalar indicator ${source[0]}`;
      break;
    }
    case "@":
    case "`": {
      badChar = `reserved character ${source[0]}`;
      break;
    }
  }
  if (badChar)
    onError(0, "BAD_SCALAR_START", `Plain value cannot start with ${badChar}`);
  return foldLines(source);
}
function singleQuotedValue(source, onError) {
  if (source[source.length - 1] !== "'" || source.length === 1)
    onError(source.length, "MISSING_CHAR", "Missing closing 'quote");
  return foldLines(source.slice(1, -1)).replace(/''/g, "'");
}
function foldLines(source) {
  var _a;
  let first, line;
  try {
    first = new RegExp("(.*?)(?<![ 	])[ 	]*\r?\n", "sy");
    line = new RegExp("[ 	]*(.*?)(?:(?<![ 	])[ 	]*)?\r?\n", "sy");
  } catch (e) {
    first = /(.*?)[ \t]*\r?\n/sy;
    line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
  }
  let match = first.exec(source);
  if (!match)
    return source;
  let res = match[1];
  let sep6 = " ";
  let pos = first.lastIndex;
  line.lastIndex = pos;
  while (match = line.exec(source)) {
    if (match[1] === "") {
      if (sep6 === "\n")
        res += sep6;
      else
        sep6 = "\n";
    } else {
      res += sep6 + match[1];
      sep6 = " ";
    }
    pos = line.lastIndex;
  }
  const last = /[ \t]*(.*)/sy;
  last.lastIndex = pos;
  match = last.exec(source);
  return res + sep6 + ((_a = match == null ? void 0 : match[1]) != null ? _a : "");
}
function doubleQuotedValue(source, onError) {
  let res = "";
  for (let i = 1; i < source.length - 1; ++i) {
    const ch = source[i];
    if (ch === "\r" && source[i + 1] === "\n")
      continue;
    if (ch === "\n") {
      const { fold, offset } = foldNewline(source, i);
      res += fold;
      i = offset;
    } else if (ch === "\\") {
      let next = source[++i];
      const cc = escapeCodes[next];
      if (cc)
        res += cc;
      else if (next === "\n") {
        next = source[i + 1];
        while (next === " " || next === "	")
          next = source[++i + 1];
      } else if (next === "\r" && source[i + 1] === "\n") {
        next = source[++i + 1];
        while (next === " " || next === "	")
          next = source[++i + 1];
      } else if (next === "x" || next === "u" || next === "U") {
        const length = { x: 2, u: 4, U: 8 }[next];
        res += parseCharCode(source, i + 1, length, onError);
        i += length;
      } else {
        const raw = source.substr(i - 1, 2);
        onError(i - 1, "BAD_DQ_ESCAPE", `Invalid escape sequence ${raw}`);
        res += raw;
      }
    } else if (ch === " " || ch === "	") {
      const wsStart = i;
      let next = source[i + 1];
      while (next === " " || next === "	")
        next = source[++i + 1];
      if (next !== "\n" && !(next === "\r" && source[i + 2] === "\n"))
        res += i > wsStart ? source.slice(wsStart, i + 1) : ch;
    } else {
      res += ch;
    }
  }
  if (source[source.length - 1] !== '"' || source.length === 1)
    onError(source.length, "MISSING_CHAR", 'Missing closing "quote');
  return res;
}
function foldNewline(source, offset) {
  let fold = "";
  let ch = source[offset + 1];
  while (ch === " " || ch === "	" || ch === "\n" || ch === "\r") {
    if (ch === "\r" && source[offset + 2] !== "\n")
      break;
    if (ch === "\n")
      fold += "\n";
    offset += 1;
    ch = source[offset + 1];
  }
  if (!fold)
    fold = " ";
  return { fold, offset };
}
var escapeCodes = {
  "0": "\0",
  // null character
  a: "\x07",
  // bell character
  b: "\b",
  // backspace
  e: "\x1B",
  // escape character
  f: "\f",
  // form feed
  n: "\n",
  // line feed
  r: "\r",
  // carriage return
  t: "	",
  // horizontal tab
  v: "\v",
  // vertical tab
  N: "\x85",
  // Unicode next line
  _: "\xA0",
  // Unicode non-breaking space
  L: "\u2028",
  // Unicode line separator
  P: "\u2029",
  // Unicode paragraph separator
  " ": " ",
  '"': '"',
  "/": "/",
  "\\": "\\",
  "	": "	"
};
function parseCharCode(source, offset, length, onError) {
  const cc = source.substr(offset, length);
  const ok = cc.length === length && /^[0-9a-fA-F]+$/.test(cc);
  const code = ok ? parseInt(cc, 16) : NaN;
  if (isNaN(code)) {
    const raw = source.substr(offset - 2, length + 2);
    onError(offset - 2, "BAD_DQ_ESCAPE", `Invalid escape sequence ${raw}`);
    return raw;
  }
  return String.fromCodePoint(code);
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/compose-scalar.js
function composeScalar(ctx, token, tagToken, onError) {
  const { value, type, comment, range } = token.type === "block-scalar" ? resolveBlockScalar(ctx, token, onError) : resolveFlowScalar(token, ctx.options.strict, onError);
  const tagName = tagToken ? ctx.directives.tagName(tagToken.source, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg)) : null;
  let tag;
  if (ctx.options.stringKeys && ctx.atKey) {
    tag = ctx.schema[SCALAR];
  } else if (tagName)
    tag = findScalarTagByName(ctx.schema, value, tagName, tagToken, onError);
  else if (token.type === "scalar")
    tag = findScalarTagByTest(ctx, value, token, onError);
  else
    tag = ctx.schema[SCALAR];
  let scalar;
  try {
    const res = tag.resolve(value, (msg) => onError(tagToken != null ? tagToken : token, "TAG_RESOLVE_FAILED", msg), ctx.options);
    scalar = isScalar(res) ? res : new Scalar(res);
  } catch (error) {
    const msg = error instanceof Error ? error.message : String(error);
    onError(tagToken != null ? tagToken : token, "TAG_RESOLVE_FAILED", msg);
    scalar = new Scalar(value);
  }
  scalar.range = range;
  scalar.source = value;
  if (type)
    scalar.type = type;
  if (tagName)
    scalar.tag = tagName;
  if (tag.format)
    scalar.format = tag.format;
  if (comment)
    scalar.comment = comment;
  return scalar;
}
function findScalarTagByName(schema4, value, tagName, tagToken, onError) {
  var _a;
  if (tagName === "!")
    return schema4[SCALAR];
  const matchWithTest = [];
  for (const tag of schema4.tags) {
    if (!tag.collection && tag.tag === tagName) {
      if (tag.default && tag.test)
        matchWithTest.push(tag);
      else
        return tag;
    }
  }
  for (const tag of matchWithTest)
    if ((_a = tag.test) == null ? void 0 : _a.test(value))
      return tag;
  const kt = schema4.knownTags[tagName];
  if (kt && !kt.collection) {
    schema4.tags.push(Object.assign({}, kt, { default: false, test: void 0 }));
    return kt;
  }
  onError(tagToken, "TAG_RESOLVE_FAILED", `Unresolved tag: ${tagName}`, tagName !== "tag:yaml.org,2002:str");
  return schema4[SCALAR];
}
function findScalarTagByTest({ atKey, directives, schema: schema4 }, value, token, onError) {
  var _a;
  const tag = schema4.tags.find((tag2) => {
    var _a2;
    return (tag2.default === true || atKey && tag2.default === "key") && ((_a2 = tag2.test) == null ? void 0 : _a2.test(value));
  }) || schema4[SCALAR];
  if (schema4.compat) {
    const compat = (_a = schema4.compat.find((tag2) => {
      var _a2;
      return tag2.default && ((_a2 = tag2.test) == null ? void 0 : _a2.test(value));
    })) != null ? _a : schema4[SCALAR];
    if (tag.tag !== compat.tag) {
      const ts = directives.tagString(tag.tag);
      const cs = directives.tagString(compat.tag);
      const msg = `Value may be parsed as either ${ts} or ${cs}`;
      onError(token, "TAG_RESOLVE_FAILED", msg, true);
    }
  }
  return tag;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js
function emptyScalarPosition(offset, before, pos) {
  if (before) {
    pos != null ? pos : pos = before.length;
    for (let i = pos - 1; i >= 0; --i) {
      let st = before[i];
      switch (st.type) {
        case "space":
        case "comment":
        case "newline":
          offset -= st.source.length;
          continue;
      }
      st = before[++i];
      while ((st == null ? void 0 : st.type) === "space") {
        offset += st.source.length;
        st = before[++i];
      }
      break;
    }
  }
  return offset;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/compose-node.js
var CN = { composeNode, composeEmptyNode };
function composeNode(ctx, token, props, onError) {
  const atKey = ctx.atKey;
  const { spaceBefore, comment, anchor, tag } = props;
  let node;
  let isSrcToken = true;
  switch (token.type) {
    case "alias":
      node = composeAlias(ctx, token, onError);
      if (anchor || tag)
        onError(token, "ALIAS_PROPS", "An alias node must not specify any properties");
      break;
    case "scalar":
    case "single-quoted-scalar":
    case "double-quoted-scalar":
    case "block-scalar":
      node = composeScalar(ctx, token, tag, onError);
      if (anchor)
        node.anchor = anchor.source.substring(1);
      break;
    case "block-map":
    case "block-seq":
    case "flow-collection":
      node = composeCollection(CN, ctx, token, props, onError);
      if (anchor)
        node.anchor = anchor.source.substring(1);
      break;
    default: {
      const message = token.type === "error" ? token.message : `Unsupported token (type: ${token.type})`;
      onError(token, "UNEXPECTED_TOKEN", message);
      node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError);
      isSrcToken = false;
    }
  }
  if (anchor && node.anchor === "")
    onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string");
  if (atKey && ctx.options.stringKeys && (!isScalar(node) || typeof node.value !== "string" || node.tag && node.tag !== "tag:yaml.org,2002:str")) {
    const msg = "With stringKeys, all keys must be strings";
    onError(tag != null ? tag : token, "NON_STRING_KEY", msg);
  }
  if (spaceBefore)
    node.spaceBefore = true;
  if (comment) {
    if (token.type === "scalar" && token.source === "")
      node.comment = comment;
    else
      node.commentBefore = comment;
  }
  if (ctx.options.keepSourceTokens && isSrcToken)
    node.srcToken = token;
  return node;
}
function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anchor, tag, end }, onError) {
  const token = {
    type: "scalar",
    offset: emptyScalarPosition(offset, before, pos),
    indent: -1,
    source: ""
  };
  const node = composeScalar(ctx, token, tag, onError);
  if (anchor) {
    node.anchor = anchor.source.substring(1);
    if (node.anchor === "")
      onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string");
  }
  if (spaceBefore)
    node.spaceBefore = true;
  if (comment) {
    node.comment = comment;
    node.range[2] = end;
  }
  return node;
}
function composeAlias({ options }, { offset, source, end }, onError) {
  const alias = new Alias(source.substring(1));
  if (alias.source === "")
    onError(offset, "BAD_ALIAS", "Alias cannot be an empty string");
  if (alias.source.endsWith(":"))
    onError(offset + source.length - 1, "BAD_ALIAS", "Alias ending in : is ambiguous", true);
  const valueEnd = offset + source.length;
  const re = resolveEnd(end, valueEnd, options.strict, onError);
  alias.range = [offset, valueEnd, re.offset];
  if (re.comment)
    alias.comment = re.comment;
  return alias;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/compose-doc.js
function composeDoc(options, directives, { offset, start, value, end }, onError) {
  const opts = Object.assign({ _directives: directives }, options);
  const doc = new Document(void 0, opts);
  const ctx = {
    atKey: false,
    atRoot: true,
    directives: doc.directives,
    options: doc.options,
    schema: doc.schema
  };
  const props = resolveProps(start, {
    indicator: "doc-start",
    next: value != null ? value : end == null ? void 0 : end[0],
    offset,
    onError,
    parentIndent: 0,
    startOnNewline: true
  });
  if (props.found) {
    doc.directives.docStart = true;
    if (value && (value.type === "block-map" || value.type === "block-seq") && !props.hasNewline)
      onError(props.end, "MISSING_CHAR", "Block collection cannot start on same line with directives-end marker");
  }
  doc.contents = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, start, null, props, onError);
  const contentEnd = doc.contents.range[2];
  const re = resolveEnd(end, contentEnd, false, onError);
  if (re.comment)
    doc.comment = re.comment;
  doc.range = [offset, contentEnd, re.offset];
  return doc;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/compose/composer.js
function getErrorPos(src) {
  if (typeof src === "number")
    return [src, src + 1];
  if (Array.isArray(src))
    return src.length === 2 ? src : [src[0], src[1]];
  const { offset, source } = src;
  return [offset, offset + (typeof source === "string" ? source.length : 1)];
}
function parsePrelude(prelude) {
  var _a;
  let comment = "";
  let atComment = false;
  let afterEmptyLine = false;
  for (let i = 0; i < prelude.length; ++i) {
    const source = prelude[i];
    switch (source[0]) {
      case "#":
        comment += (comment === "" ? "" : afterEmptyLine ? "\n\n" : "\n") + (source.substring(1) || " ");
        atComment = true;
        afterEmptyLine = false;
        break;
      case "%":
        if (((_a = prelude[i + 1]) == null ? void 0 : _a[0]) !== "#")
          i += 1;
        atComment = false;
        break;
      default:
        if (!atComment)
          afterEmptyLine = true;
        atComment = false;
    }
  }
  return { comment, afterEmptyLine };
}
var Composer = class {
  constructor(options = {}) {
    this.doc = null;
    this.atDirectives = false;
    this.prelude = [];
    this.errors = [];
    this.warnings = [];
    this.onError = (source, code, message, warning) => {
      const pos = getErrorPos(source);
      if (warning)
        this.warnings.push(new YAMLWarning(pos, code, message));
      else
        this.errors.push(new YAMLParseError(pos, code, message));
    };
    this.directives = new Directives({ version: options.version || "1.2" });
    this.options = options;
  }
  decorate(doc, afterDoc) {
    const { comment, afterEmptyLine } = parsePrelude(this.prelude);
    if (comment) {
      const dc = doc.contents;
      if (afterDoc) {
        doc.comment = doc.comment ? `${doc.comment}
${comment}` : comment;
      } else if (afterEmptyLine || doc.directives.docStart || !dc) {
        doc.commentBefore = comment;
      } else if (isCollection(dc) && !dc.flow && dc.items.length > 0) {
        let it = dc.items[0];
        if (isPair(it))
          it = it.key;
        const cb = it.commentBefore;
        it.commentBefore = cb ? `${comment}
${cb}` : comment;
      } else {
        const cb = dc.commentBefore;
        dc.commentBefore = cb ? `${comment}
${cb}` : comment;
      }
    }
    if (afterDoc) {
      Array.prototype.push.apply(doc.errors, this.errors);
      Array.prototype.push.apply(doc.warnings, this.warnings);
    } else {
      doc.errors = this.errors;
      doc.warnings = this.warnings;
    }
    this.prelude = [];
    this.errors = [];
    this.warnings = [];
  }
  /**
   * Current stream status information.
   *
   * Mostly useful at the end of input for an empty stream.
   */
  streamInfo() {
    return {
      comment: parsePrelude(this.prelude).comment,
      directives: this.directives,
      errors: this.errors,
      warnings: this.warnings
    };
  }
  /**
   * Compose tokens into documents.
   *
   * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
   * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
   */
  *compose(tokens, forceDoc = false, endOffset = -1) {
    for (const token of tokens)
      yield* this.next(token);
    yield* this.end(forceDoc, endOffset);
  }
  /** Advance the composer by one CST token. */
  *next(token) {
    switch (token.type) {
      case "directive":
        this.directives.add(token.source, (offset, message, warning) => {
          const pos = getErrorPos(token);
          pos[0] += offset;
          this.onError(pos, "BAD_DIRECTIVE", message, warning);
        });
        this.prelude.push(token.source);
        this.atDirectives = true;
        break;
      case "document": {
        const doc = composeDoc(this.options, this.directives, token, this.onError);
        if (this.atDirectives && !doc.directives.docStart)
          this.onError(token, "MISSING_CHAR", "Missing directives-end/doc-start indicator line");
        this.decorate(doc, false);
        if (this.doc)
          yield this.doc;
        this.doc = doc;
        this.atDirectives = false;
        break;
      }
      case "byte-order-mark":
      case "space":
        break;
      case "comment":
      case "newline":
        this.prelude.push(token.source);
        break;
      case "error": {
        const msg = token.source ? `${token.message}: ${JSON.stringify(token.source)}` : token.message;
        const error = new YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg);
        if (this.atDirectives || !this.doc)
          this.errors.push(error);
        else
          this.doc.errors.push(error);
        break;
      }
      case "doc-end": {
        if (!this.doc) {
          const msg = "Unexpected doc-end without preceding document";
          this.errors.push(new YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg));
          break;
        }
        this.doc.directives.docEnd = true;
        const end = resolveEnd(token.end, token.offset + token.source.length, this.doc.options.strict, this.onError);
        this.decorate(this.doc, true);
        if (end.comment) {
          const dc = this.doc.comment;
          this.doc.comment = dc ? `${dc}
${end.comment}` : end.comment;
        }
        this.doc.range[2] = end.offset;
        break;
      }
      default:
        this.errors.push(new YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", `Unsupported token ${token.type}`));
    }
  }
  /**
   * Call at end of input to yield any remaining document.
   *
   * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
   * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
   */
  *end(forceDoc = false, endOffset = -1) {
    if (this.doc) {
      this.decorate(this.doc, true);
      yield this.doc;
      this.doc = null;
    } else if (forceDoc) {
      const opts = Object.assign({ _directives: this.directives }, this.options);
      const doc = new Document(void 0, opts);
      if (this.atDirectives)
        this.onError(endOffset, "MISSING_CHAR", "Missing directives-end indicator line");
      doc.range = [0, endOffset, endOffset];
      this.decorate(doc, false);
      yield doc;
    }
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/parse/cst-visit.js
var BREAK2 = Symbol("break visit");
var SKIP2 = Symbol("skip children");
var REMOVE2 = Symbol("remove item");
function visit2(cst, visitor) {
  if ("type" in cst && cst.type === "document")
    cst = { start: cst.start, value: cst.value };
  _visit(Object.freeze([]), cst, visitor);
}
visit2.BREAK = BREAK2;
visit2.SKIP = SKIP2;
visit2.REMOVE = REMOVE2;
visit2.itemAtPath = (cst, path13) => {
  let item = cst;
  for (const [field, index] of path13) {
    const tok = item == null ? void 0 : item[field];
    if (tok && "items" in tok) {
      item = tok.items[index];
    } else
      return void 0;
  }
  return item;
};
visit2.parentCollection = (cst, path13) => {
  const parent = visit2.itemAtPath(cst, path13.slice(0, -1));
  const field = path13[path13.length - 1][0];
  const coll = parent == null ? void 0 : parent[field];
  if (coll && "items" in coll)
    return coll;
  throw new Error("Parent collection not found");
};
function _visit(path13, item, visitor) {
  let ctrl = visitor(item, path13);
  if (typeof ctrl === "symbol")
    return ctrl;
  for (const field of ["key", "value"]) {
    const token = item[field];
    if (token && "items" in token) {
      for (let i = 0; i < token.items.length; ++i) {
        const ci = _visit(Object.freeze(path13.concat([[field, i]])), token.items[i], visitor);
        if (typeof ci === "number")
          i = ci - 1;
        else if (ci === BREAK2)
          return BREAK2;
        else if (ci === REMOVE2) {
          token.items.splice(i, 1);
          i -= 1;
        }
      }
      if (typeof ctrl === "function" && field === "key")
        ctrl = ctrl(item, path13);
    }
  }
  return typeof ctrl === "function" ? ctrl(item, path13) : ctrl;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/parse/cst.js
var BOM = "\uFEFF";
var DOCUMENT = "";
var FLOW_END = "";
var SCALAR2 = "";
function tokenType(source) {
  switch (source) {
    case BOM:
      return "byte-order-mark";
    case DOCUMENT:
      return "doc-mode";
    case FLOW_END:
      return "flow-error-end";
    case SCALAR2:
      return "scalar";
    case "---":
      return "doc-start";
    case "...":
      return "doc-end";
    case "":
    case "\n":
    case "\r\n":
      return "newline";
    case "-":
      return "seq-item-ind";
    case "?":
      return "explicit-key-ind";
    case ":":
      return "map-value-ind";
    case "{":
      return "flow-map-start";
    case "}":
      return "flow-map-end";
    case "[":
      return "flow-seq-start";
    case "]":
      return "flow-seq-end";
    case ",":
      return "comma";
  }
  switch (source[0]) {
    case " ":
    case "	":
      return "space";
    case "#":
      return "comment";
    case "%":
      return "directive-line";
    case "*":
      return "alias";
    case "&":
      return "anchor";
    case "!":
      return "tag";
    case "'":
      return "single-quoted-scalar";
    case '"':
      return "double-quoted-scalar";
    case "|":
    case ">":
      return "block-scalar-header";
  }
  return null;
}

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/parse/lexer.js
function isEmpty(ch) {
  switch (ch) {
    case void 0:
    case " ":
    case "\n":
    case "\r":
    case "	":
      return true;
    default:
      return false;
  }
}
var hexDigits = new Set("0123456789ABCDEFabcdef");
var tagChars = new Set("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-#;/?:@&=+$_.!~*'()");
var flowIndicatorChars = new Set(",[]{}");
var invalidAnchorChars = new Set(" ,[]{}\n\r	");
var isNotAnchorChar = (ch) => !ch || invalidAnchorChars.has(ch);
var Lexer = class {
  constructor() {
    this.atEnd = false;
    this.blockScalarIndent = -1;
    this.blockScalarKeep = false;
    this.buffer = "";
    this.flowKey = false;
    this.flowLevel = 0;
    this.indentNext = 0;
    this.indentValue = 0;
    this.lineEndPos = null;
    this.next = null;
    this.pos = 0;
  }
  /**
   * Generate YAML tokens from the `source` string. If `incomplete`,
   * a part of the last line may be left as a buffer for the next call.
   *
   * @returns A generator of lexical tokens
   */
  *lex(source, incomplete = false) {
    var _a;
    if (source) {
      if (typeof source !== "string")
        throw TypeError("source is not a string");
      this.buffer = this.buffer ? this.buffer + source : source;
      this.lineEndPos = null;
    }
    this.atEnd = !incomplete;
    let next = (_a = this.next) != null ? _a : "stream";
    while (next && (incomplete || this.hasChars(1)))
      next = yield* this.parseNext(next);
  }
  atLineEnd() {
    let i = this.pos;
    let ch = this.buffer[i];
    while (ch === " " || ch === "	")
      ch = this.buffer[++i];
    if (!ch || ch === "#" || ch === "\n")
      return true;
    if (ch === "\r")
      return this.buffer[i + 1] === "\n";
    return false;
  }
  charAt(n) {
    return this.buffer[this.pos + n];
  }
  continueScalar(offset) {
    let ch = this.buffer[offset];
    if (this.indentNext > 0) {
      let indent = 0;
      while (ch === " ")
        ch = this.buffer[++indent + offset];
      if (ch === "\r") {
        const next = this.buffer[indent + offset + 1];
        if (next === "\n" || !next && !this.atEnd)
          return offset + indent + 1;
      }
      return ch === "\n" || indent >= this.indentNext || !ch && !this.atEnd ? offset + indent : -1;
    }
    if (ch === "-" || ch === ".") {
      const dt = this.buffer.substr(offset, 3);
      if ((dt === "---" || dt === "...") && isEmpty(this.buffer[offset + 3]))
        return -1;
    }
    return offset;
  }
  getLine() {
    let end = this.lineEndPos;
    if (typeof end !== "number" || end !== -1 && end < this.pos) {
      end = this.buffer.indexOf("\n", this.pos);
      this.lineEndPos = end;
    }
    if (end === -1)
      return this.atEnd ? this.buffer.substring(this.pos) : null;
    if (this.buffer[end - 1] === "\r")
      end -= 1;
    return this.buffer.substring(this.pos, end);
  }
  hasChars(n) {
    return this.pos + n <= this.buffer.length;
  }
  setNext(state) {
    this.buffer = this.buffer.substring(this.pos);
    this.pos = 0;
    this.lineEndPos = null;
    this.next = state;
    return null;
  }
  peek(n) {
    return this.buffer.substr(this.pos, n);
  }
  *parseNext(next) {
    switch (next) {
      case "stream":
        return yield* this.parseStream();
      case "line-start":
        return yield* this.parseLineStart();
      case "block-start":
        return yield* this.parseBlockStart();
      case "doc":
        return yield* this.parseDocument();
      case "flow":
        return yield* this.parseFlowCollection();
      case "quoted-scalar":
        return yield* this.parseQuotedScalar();
      case "block-scalar":
        return yield* this.parseBlockScalar();
      case "plain-scalar":
        return yield* this.parsePlainScalar();
    }
  }
  *parseStream() {
    let line = this.getLine();
    if (line === null)
      return this.setNext("stream");
    if (line[0] === BOM) {
      yield* this.pushCount(1);
      line = line.substring(1);
    }
    if (line[0] === "%") {
      let dirEnd = line.length;
      let cs = line.indexOf("#");
      while (cs !== -1) {
        const ch = line[cs - 1];
        if (ch === " " || ch === "	") {
          dirEnd = cs - 1;
          break;
        } else {
          cs = line.indexOf("#", cs + 1);
        }
      }
      while (true) {
        const ch = line[dirEnd - 1];
        if (ch === " " || ch === "	")
          dirEnd -= 1;
        else
          break;
      }
      const n = (yield* this.pushCount(dirEnd)) + (yield* this.pushSpaces(true));
      yield* this.pushCount(line.length - n);
      this.pushNewline();
      return "stream";
    }
    if (this.atLineEnd()) {
      const sp = yield* this.pushSpaces(true);
      yield* this.pushCount(line.length - sp);
      yield* this.pushNewline();
      return "stream";
    }
    yield DOCUMENT;
    return yield* this.parseLineStart();
  }
  *parseLineStart() {
    const ch = this.charAt(0);
    if (!ch && !this.atEnd)
      return this.setNext("line-start");
    if (ch === "-" || ch === ".") {
      if (!this.atEnd && !this.hasChars(4))
        return this.setNext("line-start");
      const s = this.peek(3);
      if ((s === "---" || s === "...") && isEmpty(this.charAt(3))) {
        yield* this.pushCount(3);
        this.indentValue = 0;
        this.indentNext = 0;
        return s === "---" ? "doc" : "stream";
      }
    }
    this.indentValue = yield* this.pushSpaces(false);
    if (this.indentNext > this.indentValue && !isEmpty(this.charAt(1)))
      this.indentNext = this.indentValue;
    return yield* this.parseBlockStart();
  }
  *parseBlockStart() {
    const [ch0, ch1] = this.peek(2);
    if (!ch1 && !this.atEnd)
      return this.setNext("block-start");
    if ((ch0 === "-" || ch0 === "?" || ch0 === ":") && isEmpty(ch1)) {
      const n = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
      this.indentNext = this.indentValue + 1;
      this.indentValue += n;
      return yield* this.parseBlockStart();
    }
    return "doc";
  }
  *parseDocument() {
    yield* this.pushSpaces(true);
    const line = this.getLine();
    if (line === null)
      return this.setNext("doc");
    let n = yield* this.pushIndicators();
    switch (line[n]) {
      case "#":
        yield* this.pushCount(line.length - n);
      // fallthrough
      case void 0:
        yield* this.pushNewline();
        return yield* this.parseLineStart();
      case "{":
      case "[":
        yield* this.pushCount(1);
        this.flowKey = false;
        this.flowLevel = 1;
        return "flow";
      case "}":
      case "]":
        yield* this.pushCount(1);
        return "doc";
      case "*":
        yield* this.pushUntil(isNotAnchorChar);
        return "doc";
      case '"':
      case "'":
        return yield* this.parseQuotedScalar();
      case "|":
      case ">":
        n += yield* this.parseBlockScalarHeader();
        n += yield* this.pushSpaces(true);
        yield* this.pushCount(line.length - n);
        yield* this.pushNewline();
        return yield* this.parseBlockScalar();
      default:
        return yield* this.parsePlainScalar();
    }
  }
  *parseFlowCollection() {
    let nl, sp;
    let indent = -1;
    do {
      nl = yield* this.pushNewline();
      if (nl > 0) {
        sp = yield* this.pushSpaces(false);
        this.indentValue = indent = sp;
      } else {
        sp = 0;
      }
      sp += yield* this.pushSpaces(true);
    } while (nl + sp > 0);
    const line = this.getLine();
    if (line === null)
      return this.setNext("flow");
    if (indent !== -1 && indent < this.indentNext && line[0] !== "#" || indent === 0 && (line.startsWith("---") || line.startsWith("...")) && isEmpty(line[3])) {
      const atFlowEndMarker = indent === this.indentNext - 1 && this.flowLevel === 1 && (line[0] === "]" || line[0] === "}");
      if (!atFlowEndMarker) {
        this.flowLevel = 0;
        yield FLOW_END;
        return yield* this.parseLineStart();
      }
    }
    let n = 0;
    while (line[n] === ",") {
      n += yield* this.pushCount(1);
      n += yield* this.pushSpaces(true);
      this.flowKey = false;
    }
    n += yield* this.pushIndicators();
    switch (line[n]) {
      case void 0:
        return "flow";
      case "#":
        yield* this.pushCount(line.length - n);
        return "flow";
      case "{":
      case "[":
        yield* this.pushCount(1);
        this.flowKey = false;
        this.flowLevel += 1;
        return "flow";
      case "}":
      case "]":
        yield* this.pushCount(1);
        this.flowKey = true;
        this.flowLevel -= 1;
        return this.flowLevel ? "flow" : "doc";
      case "*":
        yield* this.pushUntil(isNotAnchorChar);
        return "flow";
      case '"':
      case "'":
        this.flowKey = true;
        return yield* this.parseQuotedScalar();
      case ":": {
        const next = this.charAt(1);
        if (this.flowKey || isEmpty(next) || next === ",") {
          this.flowKey = false;
          yield* this.pushCount(1);
          yield* this.pushSpaces(true);
          return "flow";
        }
      }
      // fallthrough
      default:
        this.flowKey = false;
        return yield* this.parsePlainScalar();
    }
  }
  *parseQuotedScalar() {
    const quote = this.charAt(0);
    let end = this.buffer.indexOf(quote, this.pos + 1);
    if (quote === "'") {
      while (end !== -1 && this.buffer[end + 1] === "'")
        end = this.buffer.indexOf("'", end + 2);
    } else {
      while (end !== -1) {
        let n = 0;
        while (this.buffer[end - 1 - n] === "\\")
          n += 1;
        if (n % 2 === 0)
          break;
        end = this.buffer.indexOf('"', end + 1);
      }
    }
    const qb = this.buffer.substring(0, end);
    let nl = qb.indexOf("\n", this.pos);
    if (nl !== -1) {
      while (nl !== -1) {
        const cs = this.continueScalar(nl + 1);
        if (cs === -1)
          break;
        nl = qb.indexOf("\n", cs);
      }
      if (nl !== -1) {
        end = nl - (qb[nl - 1] === "\r" ? 2 : 1);
      }
    }
    if (end === -1) {
      if (!this.atEnd)
        return this.setNext("quoted-scalar");
      end = this.buffer.length;
    }
    yield* this.pushToIndex(end + 1, false);
    return this.flowLevel ? "flow" : "doc";
  }
  *parseBlockScalarHeader() {
    this.blockScalarIndent = -1;
    this.blockScalarKeep = false;
    let i = this.pos;
    while (true) {
      const ch = this.buffer[++i];
      if (ch === "+")
        this.blockScalarKeep = true;
      else if (ch > "0" && ch <= "9")
        this.blockScalarIndent = Number(ch) - 1;
      else if (ch !== "-")
        break;
    }
    return yield* this.pushUntil((ch) => isEmpty(ch) || ch === "#");
  }
  *parseBlockScalar() {
    let nl = this.pos - 1;
    let indent = 0;
    let ch;
    loop: for (let i2 = this.pos; ch = this.buffer[i2]; ++i2) {
      switch (ch) {
        case " ":
          indent += 1;
          break;
        case "\n":
          nl = i2;
          indent = 0;
          break;
        case "\r": {
          const next = this.buffer[i2 + 1];
          if (!next && !this.atEnd)
            return this.setNext("block-scalar");
          if (next === "\n")
            break;
        }
        // fallthrough
        default:
          break loop;
      }
    }
    if (!ch && !this.atEnd)
      return this.setNext("block-scalar");
    if (indent >= this.indentNext) {
      if (this.blockScalarIndent === -1)
        this.indentNext = indent;
      else {
        this.indentNext = this.blockScalarIndent + (this.indentNext === 0 ? 1 : this.indentNext);
      }
      do {
        const cs = this.continueScalar(nl + 1);
        if (cs === -1)
          break;
        nl = this.buffer.indexOf("\n", cs);
      } while (nl !== -1);
      if (nl === -1) {
        if (!this.atEnd)
          return this.setNext("block-scalar");
        nl = this.buffer.length;
      }
    }
    let i = nl + 1;
    ch = this.buffer[i];
    while (ch === " ")
      ch = this.buffer[++i];
    if (ch === "	") {
      while (ch === "	" || ch === " " || ch === "\r" || ch === "\n")
        ch = this.buffer[++i];
      nl = i - 1;
    } else if (!this.blockScalarKeep) {
      do {
        let i2 = nl - 1;
        let ch2 = this.buffer[i2];
        if (ch2 === "\r")
          ch2 = this.buffer[--i2];
        const lastChar = i2;
        while (ch2 === " ")
          ch2 = this.buffer[--i2];
        if (ch2 === "\n" && i2 >= this.pos && i2 + 1 + indent > lastChar)
          nl = i2;
        else
          break;
      } while (true);
    }
    yield SCALAR2;
    yield* this.pushToIndex(nl + 1, true);
    return yield* this.parseLineStart();
  }
  *parsePlainScalar() {
    const inFlow = this.flowLevel > 0;
    let end = this.pos - 1;
    let i = this.pos - 1;
    let ch;
    while (ch = this.buffer[++i]) {
      if (ch === ":") {
        const next = this.buffer[i + 1];
        if (isEmpty(next) || inFlow && flowIndicatorChars.has(next))
          break;
        end = i;
      } else if (isEmpty(ch)) {
        let next = this.buffer[i + 1];
        if (ch === "\r") {
          if (next === "\n") {
            i += 1;
            ch = "\n";
            next = this.buffer[i + 1];
          } else
            end = i;
        }
        if (next === "#" || inFlow && flowIndicatorChars.has(next))
          break;
        if (ch === "\n") {
          const cs = this.continueScalar(i + 1);
          if (cs === -1)
            break;
          i = Math.max(i, cs - 2);
        }
      } else {
        if (inFlow && flowIndicatorChars.has(ch))
          break;
        end = i;
      }
    }
    if (!ch && !this.atEnd)
      return this.setNext("plain-scalar");
    yield SCALAR2;
    yield* this.pushToIndex(end + 1, true);
    return inFlow ? "flow" : "doc";
  }
  *pushCount(n) {
    if (n > 0) {
      yield this.buffer.substr(this.pos, n);
      this.pos += n;
      return n;
    }
    return 0;
  }
  *pushToIndex(i, allowEmpty) {
    const s = this.buffer.slice(this.pos, i);
    if (s) {
      yield s;
      this.pos += s.length;
      return s.length;
    } else if (allowEmpty)
      yield "";
    return 0;
  }
  *pushIndicators() {
    switch (this.charAt(0)) {
      case "!":
        return (yield* this.pushTag()) + (yield* this.pushSpaces(true)) + (yield* this.pushIndicators());
      case "&":
        return (yield* this.pushUntil(isNotAnchorChar)) + (yield* this.pushSpaces(true)) + (yield* this.pushIndicators());
      case "-":
      // this is an error
      case "?":
      // this is an error outside flow collections
      case ":": {
        const inFlow = this.flowLevel > 0;
        const ch1 = this.charAt(1);
        if (isEmpty(ch1) || inFlow && flowIndicatorChars.has(ch1)) {
          if (!inFlow)
            this.indentNext = this.indentValue + 1;
          else if (this.flowKey)
            this.flowKey = false;
          return (yield* this.pushCount(1)) + (yield* this.pushSpaces(true)) + (yield* this.pushIndicators());
        }
      }
    }
    return 0;
  }
  *pushTag() {
    if (this.charAt(1) === "<") {
      let i = this.pos + 2;
      let ch = this.buffer[i];
      while (!isEmpty(ch) && ch !== ">")
        ch = this.buffer[++i];
      return yield* this.pushToIndex(ch === ">" ? i + 1 : i, false);
    } else {
      let i = this.pos + 1;
      let ch = this.buffer[i];
      while (ch) {
        if (tagChars.has(ch))
          ch = this.buffer[++i];
        else if (ch === "%" && hexDigits.has(this.buffer[i + 1]) && hexDigits.has(this.buffer[i + 2])) {
          ch = this.buffer[i += 3];
        } else
          break;
      }
      return yield* this.pushToIndex(i, false);
    }
  }
  *pushNewline() {
    const ch = this.buffer[this.pos];
    if (ch === "\n")
      return yield* this.pushCount(1);
    else if (ch === "\r" && this.charAt(1) === "\n")
      return yield* this.pushCount(2);
    else
      return 0;
  }
  *pushSpaces(allowTabs) {
    let i = this.pos - 1;
    let ch;
    do {
      ch = this.buffer[++i];
    } while (ch === " " || allowTabs && ch === "	");
    const n = i - this.pos;
    if (n > 0) {
      yield this.buffer.substr(this.pos, n);
      this.pos = i;
    }
    return n;
  }
  *pushUntil(test) {
    let i = this.pos;
    let ch = this.buffer[i];
    while (!test(ch))
      ch = this.buffer[++i];
    return yield* this.pushToIndex(i, false);
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/parse/line-counter.js
var LineCounter = class {
  constructor() {
    this.lineStarts = [];
    this.addNewLine = (offset) => this.lineStarts.push(offset);
    this.linePos = (offset) => {
      let low = 0;
      let high = this.lineStarts.length;
      while (low < high) {
        const mid = low + high >> 1;
        if (this.lineStarts[mid] < offset)
          low = mid + 1;
        else
          high = mid;
      }
      if (this.lineStarts[low] === offset)
        return { line: low + 1, col: 1 };
      if (low === 0)
        return { line: 0, col: offset };
      const start = this.lineStarts[low - 1];
      return { line: low, col: offset - start + 1 };
    };
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/parse/parser.js
function includesToken(list, type) {
  for (let i = 0; i < list.length; ++i)
    if (list[i].type === type)
      return true;
  return false;
}
function findNonEmptyIndex(list) {
  for (let i = 0; i < list.length; ++i) {
    switch (list[i].type) {
      case "space":
      case "comment":
      case "newline":
        break;
      default:
        return i;
    }
  }
  return -1;
}
function isFlowToken(token) {
  switch (token == null ? void 0 : token.type) {
    case "alias":
    case "scalar":
    case "single-quoted-scalar":
    case "double-quoted-scalar":
    case "flow-collection":
      return true;
    default:
      return false;
  }
}
function getPrevProps(parent) {
  var _a;
  switch (parent.type) {
    case "document":
      return parent.start;
    case "block-map": {
      const it = parent.items[parent.items.length - 1];
      return (_a = it.sep) != null ? _a : it.start;
    }
    case "block-seq":
      return parent.items[parent.items.length - 1].start;
    /* istanbul ignore next should not happen */
    default:
      return [];
  }
}
function getFirstKeyStartProps(prev) {
  var _a;
  if (prev.length === 0)
    return [];
  let i = prev.length;
  loop: while (--i >= 0) {
    switch (prev[i].type) {
      case "doc-start":
      case "explicit-key-ind":
      case "map-value-ind":
      case "seq-item-ind":
      case "newline":
        break loop;
    }
  }
  while (((_a = prev[++i]) == null ? void 0 : _a.type) === "space") {
  }
  return prev.splice(i, prev.length);
}
function fixFlowSeqItems(fc) {
  if (fc.start.type === "flow-seq-start") {
    for (const it of fc.items) {
      if (it.sep && !it.value && !includesToken(it.start, "explicit-key-ind") && !includesToken(it.sep, "map-value-ind")) {
        if (it.key)
          it.value = it.key;
        delete it.key;
        if (isFlowToken(it.value)) {
          if (it.value.end)
            Array.prototype.push.apply(it.value.end, it.sep);
          else
            it.value.end = it.sep;
        } else
          Array.prototype.push.apply(it.start, it.sep);
        delete it.sep;
      }
    }
  }
}
var Parser = class {
  /**
   * @param onNewLine - If defined, called separately with the start position of
   *   each new line (in `parse()`, including the start of input).
   */
  constructor(onNewLine) {
    this.atNewLine = true;
    this.atScalar = false;
    this.indent = 0;
    this.offset = 0;
    this.onKeyLine = false;
    this.stack = [];
    this.source = "";
    this.type = "";
    this.lexer = new Lexer();
    this.onNewLine = onNewLine;
  }
  /**
   * Parse `source` as a YAML stream.
   * If `incomplete`, a part of the last line may be left as a buffer for the next call.
   *
   * Errors are not thrown, but yielded as `{ type: 'error', message }` tokens.
   *
   * @returns A generator of tokens representing each directive, document, and other structure.
   */
  *parse(source, incomplete = false) {
    if (this.onNewLine && this.offset === 0)
      this.onNewLine(0);
    for (const lexeme of this.lexer.lex(source, incomplete))
      yield* this.next(lexeme);
    if (!incomplete)
      yield* this.end();
  }
  /**
   * Advance the parser by the `source` of one lexical token.
   */
  *next(source) {
    this.source = source;
    if (this.atScalar) {
      this.atScalar = false;
      yield* this.step();
      this.offset += source.length;
      return;
    }
    const type = tokenType(source);
    if (!type) {
      const message = `Not a YAML token: ${source}`;
      yield* this.pop({ type: "error", offset: this.offset, message, source });
      this.offset += source.length;
    } else if (type === "scalar") {
      this.atNewLine = false;
      this.atScalar = true;
      this.type = "scalar";
    } else {
      this.type = type;
      yield* this.step();
      switch (type) {
        case "newline":
          this.atNewLine = true;
          this.indent = 0;
          if (this.onNewLine)
            this.onNewLine(this.offset + source.length);
          break;
        case "space":
          if (this.atNewLine && source[0] === " ")
            this.indent += source.length;
          break;
        case "explicit-key-ind":
        case "map-value-ind":
        case "seq-item-ind":
          if (this.atNewLine)
            this.indent += source.length;
          break;
        case "doc-mode":
        case "flow-error-end":
          return;
        default:
          this.atNewLine = false;
      }
      this.offset += source.length;
    }
  }
  /** Call at end of input to push out any remaining constructions */
  *end() {
    while (this.stack.length > 0)
      yield* this.pop();
  }
  get sourceToken() {
    const st = {
      type: this.type,
      offset: this.offset,
      indent: this.indent,
      source: this.source
    };
    return st;
  }
  *step() {
    const top = this.peek(1);
    if (this.type === "doc-end" && (top == null ? void 0 : top.type) !== "doc-end") {
      while (this.stack.length > 0)
        yield* this.pop();
      this.stack.push({
        type: "doc-end",
        offset: this.offset,
        source: this.source
      });
      return;
    }
    if (!top)
      return yield* this.stream();
    switch (top.type) {
      case "document":
        return yield* this.document(top);
      case "alias":
      case "scalar":
      case "single-quoted-scalar":
      case "double-quoted-scalar":
        return yield* this.scalar(top);
      case "block-scalar":
        return yield* this.blockScalar(top);
      case "block-map":
        return yield* this.blockMap(top);
      case "block-seq":
        return yield* this.blockSequence(top);
      case "flow-collection":
        return yield* this.flowCollection(top);
      case "doc-end":
        return yield* this.documentEnd(top);
    }
    yield* this.pop();
  }
  peek(n) {
    return this.stack[this.stack.length - n];
  }
  *pop(error) {
    const token = error != null ? error : this.stack.pop();
    if (!token) {
      const message = "Tried to pop an empty stack";
      yield { type: "error", offset: this.offset, source: "", message };
    } else if (this.stack.length === 0) {
      yield token;
    } else {
      const top = this.peek(1);
      if (token.type === "block-scalar") {
        token.indent = "indent" in top ? top.indent : 0;
      } else if (token.type === "flow-collection" && top.type === "document") {
        token.indent = 0;
      }
      if (token.type === "flow-collection")
        fixFlowSeqItems(token);
      switch (top.type) {
        case "document":
          top.value = token;
          break;
        case "block-scalar":
          top.props.push(token);
          break;
        case "block-map": {
          const it = top.items[top.items.length - 1];
          if (it.value) {
            top.items.push({ start: [], key: token, sep: [] });
            this.onKeyLine = true;
            return;
          } else if (it.sep) {
            it.value = token;
          } else {
            Object.assign(it, { key: token, sep: [] });
            this.onKeyLine = !it.explicitKey;
            return;
          }
          break;
        }
        case "block-seq": {
          const it = top.items[top.items.length - 1];
          if (it.value)
            top.items.push({ start: [], value: token });
          else
            it.value = token;
          break;
        }
        case "flow-collection": {
          const it = top.items[top.items.length - 1];
          if (!it || it.value)
            top.items.push({ start: [], key: token, sep: [] });
          else if (it.sep)
            it.value = token;
          else
            Object.assign(it, { key: token, sep: [] });
          return;
        }
        /* istanbul ignore next should not happen */
        default:
          yield* this.pop();
          yield* this.pop(token);
      }
      if ((top.type === "document" || top.type === "block-map" || top.type === "block-seq") && (token.type === "block-map" || token.type === "block-seq")) {
        const last = token.items[token.items.length - 1];
        if (last && !last.sep && !last.value && last.start.length > 0 && findNonEmptyIndex(last.start) === -1 && (token.indent === 0 || last.start.every((st) => st.type !== "comment" || st.indent < token.indent))) {
          if (top.type === "document")
            top.end = last.start;
          else
            top.items.push({ start: last.start });
          token.items.splice(-1, 1);
        }
      }
    }
  }
  *stream() {
    switch (this.type) {
      case "directive-line":
        yield { type: "directive", offset: this.offset, source: this.source };
        return;
      case "byte-order-mark":
      case "space":
      case "comment":
      case "newline":
        yield this.sourceToken;
        return;
      case "doc-mode":
      case "doc-start": {
        const doc = {
          type: "document",
          offset: this.offset,
          start: []
        };
        if (this.type === "doc-start")
          doc.start.push(this.sourceToken);
        this.stack.push(doc);
        return;
      }
    }
    yield {
      type: "error",
      offset: this.offset,
      message: `Unexpected ${this.type} token in YAML stream`,
      source: this.source
    };
  }
  *document(doc) {
    if (doc.value)
      return yield* this.lineEnd(doc);
    switch (this.type) {
      case "doc-start": {
        if (findNonEmptyIndex(doc.start) !== -1) {
          yield* this.pop();
          yield* this.step();
        } else
          doc.start.push(this.sourceToken);
        return;
      }
      case "anchor":
      case "tag":
      case "space":
      case "comment":
      case "newline":
        doc.start.push(this.sourceToken);
        return;
    }
    const bv = this.startBlockValue(doc);
    if (bv)
      this.stack.push(bv);
    else {
      yield {
        type: "error",
        offset: this.offset,
        message: `Unexpected ${this.type} token in YAML document`,
        source: this.source
      };
    }
  }
  *scalar(scalar) {
    if (this.type === "map-value-ind") {
      const prev = getPrevProps(this.peek(2));
      const start = getFirstKeyStartProps(prev);
      let sep6;
      if (scalar.end) {
        sep6 = scalar.end;
        sep6.push(this.sourceToken);
        delete scalar.end;
      } else
        sep6 = [this.sourceToken];
      const map2 = {
        type: "block-map",
        offset: scalar.offset,
        indent: scalar.indent,
        items: [{ start, key: scalar, sep: sep6 }]
      };
      this.onKeyLine = true;
      this.stack[this.stack.length - 1] = map2;
    } else
      yield* this.lineEnd(scalar);
  }
  *blockScalar(scalar) {
    switch (this.type) {
      case "space":
      case "comment":
      case "newline":
        scalar.props.push(this.sourceToken);
        return;
      case "scalar":
        scalar.source = this.source;
        this.atNewLine = true;
        this.indent = 0;
        if (this.onNewLine) {
          let nl = this.source.indexOf("\n") + 1;
          while (nl !== 0) {
            this.onNewLine(this.offset + nl);
            nl = this.source.indexOf("\n", nl) + 1;
          }
        }
        yield* this.pop();
        break;
      /* istanbul ignore next should not happen */
      default:
        yield* this.pop();
        yield* this.step();
    }
  }
  *blockMap(map2) {
    var _a;
    const it = map2.items[map2.items.length - 1];
    switch (this.type) {
      case "newline":
        this.onKeyLine = false;
        if (it.value) {
          const end = "end" in it.value ? it.value.end : void 0;
          const last = Array.isArray(end) ? end[end.length - 1] : void 0;
          if ((last == null ? void 0 : last.type) === "comment")
            end == null ? void 0 : end.push(this.sourceToken);
          else
            map2.items.push({ start: [this.sourceToken] });
        } else if (it.sep) {
          it.sep.push(this.sourceToken);
        } else {
          it.start.push(this.sourceToken);
        }
        return;
      case "space":
      case "comment":
        if (it.value) {
          map2.items.push({ start: [this.sourceToken] });
        } else if (it.sep) {
          it.sep.push(this.sourceToken);
        } else {
          if (this.atIndentedComment(it.start, map2.indent)) {
            const prev = map2.items[map2.items.length - 2];
            const end = (_a = prev == null ? void 0 : prev.value) == null ? void 0 : _a.end;
            if (Array.isArray(end)) {
              Array.prototype.push.apply(end, it.start);
              end.push(this.sourceToken);
              map2.items.pop();
              return;
            }
          }
          it.start.push(this.sourceToken);
        }
        return;
    }
    if (this.indent >= map2.indent) {
      const atMapIndent = !this.onKeyLine && this.indent === map2.indent;
      const atNextItem = atMapIndent && (it.sep || it.explicitKey) && this.type !== "seq-item-ind";
      let start = [];
      if (atNextItem && it.sep && !it.value) {
        const nl = [];
        for (let i = 0; i < it.sep.length; ++i) {
          const st = it.sep[i];
          switch (st.type) {
            case "newline":
              nl.push(i);
              break;
            case "space":
              break;
            case "comment":
              if (st.indent > map2.indent)
                nl.length = 0;
              break;
            default:
              nl.length = 0;
          }
        }
        if (nl.length >= 2)
          start = it.sep.splice(nl[1]);
      }
      switch (this.type) {
        case "anchor":
        case "tag":
          if (atNextItem || it.value) {
            start.push(this.sourceToken);
            map2.items.push({ start });
            this.onKeyLine = true;
          } else if (it.sep) {
            it.sep.push(this.sourceToken);
          } else {
            it.start.push(this.sourceToken);
          }
          return;
        case "explicit-key-ind":
          if (!it.sep && !it.explicitKey) {
            it.start.push(this.sourceToken);
            it.explicitKey = true;
          } else if (atNextItem || it.value) {
            start.push(this.sourceToken);
            map2.items.push({ start, explicitKey: true });
          } else {
            this.stack.push({
              type: "block-map",
              offset: this.offset,
              indent: this.indent,
              items: [{ start: [this.sourceToken], explicitKey: true }]
            });
          }
          this.onKeyLine = true;
          return;
        case "map-value-ind":
          if (it.explicitKey) {
            if (!it.sep) {
              if (includesToken(it.start, "newline")) {
                Object.assign(it, { key: null, sep: [this.sourceToken] });
              } else {
                const start2 = getFirstKeyStartProps(it.start);
                this.stack.push({
                  type: "block-map",
                  offset: this.offset,
                  indent: this.indent,
                  items: [{ start: start2, key: null, sep: [this.sourceToken] }]
                });
              }
            } else if (it.value) {
              map2.items.push({ start: [], key: null, sep: [this.sourceToken] });
            } else if (includesToken(it.sep, "map-value-ind")) {
              this.stack.push({
                type: "block-map",
                offset: this.offset,
                indent: this.indent,
                items: [{ start, key: null, sep: [this.sourceToken] }]
              });
            } else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
              const start2 = getFirstKeyStartProps(it.start);
              const key = it.key;
              const sep6 = it.sep;
              sep6.push(this.sourceToken);
              delete it.key;
              delete it.sep;
              this.stack.push({
                type: "block-map",
                offset: this.offset,
                indent: this.indent,
                items: [{ start: start2, key, sep: sep6 }]
              });
            } else if (start.length > 0) {
              it.sep = it.sep.concat(start, this.sourceToken);
            } else {
              it.sep.push(this.sourceToken);
            }
          } else {
            if (!it.sep) {
              Object.assign(it, { key: null, sep: [this.sourceToken] });
            } else if (it.value || atNextItem) {
              map2.items.push({ start, key: null, sep: [this.sourceToken] });
            } else if (includesToken(it.sep, "map-value-ind")) {
              this.stack.push({
                type: "block-map",
                offset: this.offset,
                indent: this.indent,
                items: [{ start: [], key: null, sep: [this.sourceToken] }]
              });
            } else {
              it.sep.push(this.sourceToken);
            }
          }
          this.onKeyLine = true;
          return;
        case "alias":
        case "scalar":
        case "single-quoted-scalar":
        case "double-quoted-scalar": {
          const fs7 = this.flowScalar(this.type);
          if (atNextItem || it.value) {
            map2.items.push({ start, key: fs7, sep: [] });
            this.onKeyLine = true;
          } else if (it.sep) {
            this.stack.push(fs7);
          } else {
            Object.assign(it, { key: fs7, sep: [] });
            this.onKeyLine = true;
          }
          return;
        }
        default: {
          const bv = this.startBlockValue(map2);
          if (bv) {
            if (bv.type === "block-seq") {
              if (!it.explicitKey && it.sep && !includesToken(it.sep, "newline")) {
                yield* this.pop({
                  type: "error",
                  offset: this.offset,
                  message: "Unexpected block-seq-ind on same line with key",
                  source: this.source
                });
                return;
              }
            } else if (atMapIndent) {
              map2.items.push({ start });
            }
            this.stack.push(bv);
            return;
          }
        }
      }
    }
    yield* this.pop();
    yield* this.step();
  }
  *blockSequence(seq2) {
    var _a;
    const it = seq2.items[seq2.items.length - 1];
    switch (this.type) {
      case "newline":
        if (it.value) {
          const end = "end" in it.value ? it.value.end : void 0;
          const last = Array.isArray(end) ? end[end.length - 1] : void 0;
          if ((last == null ? void 0 : last.type) === "comment")
            end == null ? void 0 : end.push(this.sourceToken);
          else
            seq2.items.push({ start: [this.sourceToken] });
        } else
          it.start.push(this.sourceToken);
        return;
      case "space":
      case "comment":
        if (it.value)
          seq2.items.push({ start: [this.sourceToken] });
        else {
          if (this.atIndentedComment(it.start, seq2.indent)) {
            const prev = seq2.items[seq2.items.length - 2];
            const end = (_a = prev == null ? void 0 : prev.value) == null ? void 0 : _a.end;
            if (Array.isArray(end)) {
              Array.prototype.push.apply(end, it.start);
              end.push(this.sourceToken);
              seq2.items.pop();
              return;
            }
          }
          it.start.push(this.sourceToken);
        }
        return;
      case "anchor":
      case "tag":
        if (it.value || this.indent <= seq2.indent)
          break;
        it.start.push(this.sourceToken);
        return;
      case "seq-item-ind":
        if (this.indent !== seq2.indent)
          break;
        if (it.value || includesToken(it.start, "seq-item-ind"))
          seq2.items.push({ start: [this.sourceToken] });
        else
          it.start.push(this.sourceToken);
        return;
    }
    if (this.indent > seq2.indent) {
      const bv = this.startBlockValue(seq2);
      if (bv) {
        this.stack.push(bv);
        return;
      }
    }
    yield* this.pop();
    yield* this.step();
  }
  *flowCollection(fc) {
    const it = fc.items[fc.items.length - 1];
    if (this.type === "flow-error-end") {
      let top;
      do {
        yield* this.pop();
        top = this.peek(1);
      } while ((top == null ? void 0 : top.type) === "flow-collection");
    } else if (fc.end.length === 0) {
      switch (this.type) {
        case "comma":
        case "explicit-key-ind":
          if (!it || it.sep)
            fc.items.push({ start: [this.sourceToken] });
          else
            it.start.push(this.sourceToken);
          return;
        case "map-value-ind":
          if (!it || it.value)
            fc.items.push({ start: [], key: null, sep: [this.sourceToken] });
          else if (it.sep)
            it.sep.push(this.sourceToken);
          else
            Object.assign(it, { key: null, sep: [this.sourceToken] });
          return;
        case "space":
        case "comment":
        case "newline":
        case "anchor":
        case "tag":
          if (!it || it.value)
            fc.items.push({ start: [this.sourceToken] });
          else if (it.sep)
            it.sep.push(this.sourceToken);
          else
            it.start.push(this.sourceToken);
          return;
        case "alias":
        case "scalar":
        case "single-quoted-scalar":
        case "double-quoted-scalar": {
          const fs7 = this.flowScalar(this.type);
          if (!it || it.value)
            fc.items.push({ start: [], key: fs7, sep: [] });
          else if (it.sep)
            this.stack.push(fs7);
          else
            Object.assign(it, { key: fs7, sep: [] });
          return;
        }
        case "flow-map-end":
        case "flow-seq-end":
          fc.end.push(this.sourceToken);
          return;
      }
      const bv = this.startBlockValue(fc);
      if (bv)
        this.stack.push(bv);
      else {
        yield* this.pop();
        yield* this.step();
      }
    } else {
      const parent = this.peek(2);
      if (parent.type === "block-map" && (this.type === "map-value-ind" && parent.indent === fc.indent || this.type === "newline" && !parent.items[parent.items.length - 1].sep)) {
        yield* this.pop();
        yield* this.step();
      } else if (this.type === "map-value-ind" && parent.type !== "flow-collection") {
        const prev = getPrevProps(parent);
        const start = getFirstKeyStartProps(prev);
        fixFlowSeqItems(fc);
        const sep6 = fc.end.splice(1, fc.end.length);
        sep6.push(this.sourceToken);
        const map2 = {
          type: "block-map",
          offset: fc.offset,
          indent: fc.indent,
          items: [{ start, key: fc, sep: sep6 }]
        };
        this.onKeyLine = true;
        this.stack[this.stack.length - 1] = map2;
      } else {
        yield* this.lineEnd(fc);
      }
    }
  }
  flowScalar(type) {
    if (this.onNewLine) {
      let nl = this.source.indexOf("\n") + 1;
      while (nl !== 0) {
        this.onNewLine(this.offset + nl);
        nl = this.source.indexOf("\n", nl) + 1;
      }
    }
    return {
      type,
      offset: this.offset,
      indent: this.indent,
      source: this.source
    };
  }
  startBlockValue(parent) {
    switch (this.type) {
      case "alias":
      case "scalar":
      case "single-quoted-scalar":
      case "double-quoted-scalar":
        return this.flowScalar(this.type);
      case "block-scalar-header":
        return {
          type: "block-scalar",
          offset: this.offset,
          indent: this.indent,
          props: [this.sourceToken],
          source: ""
        };
      case "flow-map-start":
      case "flow-seq-start":
        return {
          type: "flow-collection",
          offset: this.offset,
          indent: this.indent,
          start: this.sourceToken,
          items: [],
          end: []
        };
      case "seq-item-ind":
        return {
          type: "block-seq",
          offset: this.offset,
          indent: this.indent,
          items: [{ start: [this.sourceToken] }]
        };
      case "explicit-key-ind": {
        this.onKeyLine = true;
        const prev = getPrevProps(parent);
        const start = getFirstKeyStartProps(prev);
        start.push(this.sourceToken);
        return {
          type: "block-map",
          offset: this.offset,
          indent: this.indent,
          items: [{ start, explicitKey: true }]
        };
      }
      case "map-value-ind": {
        this.onKeyLine = true;
        const prev = getPrevProps(parent);
        const start = getFirstKeyStartProps(prev);
        return {
          type: "block-map",
          offset: this.offset,
          indent: this.indent,
          items: [{ start, key: null, sep: [this.sourceToken] }]
        };
      }
    }
    return null;
  }
  atIndentedComment(start, indent) {
    if (this.type !== "comment")
      return false;
    if (this.indent <= indent)
      return false;
    return start.every((st) => st.type === "newline" || st.type === "space");
  }
  *documentEnd(docEnd) {
    if (this.type !== "doc-mode") {
      if (docEnd.end)
        docEnd.end.push(this.sourceToken);
      else
        docEnd.end = [this.sourceToken];
      if (this.type === "newline")
        yield* this.pop();
    }
  }
  *lineEnd(token) {
    switch (this.type) {
      case "comma":
      case "doc-start":
      case "doc-end":
      case "flow-seq-end":
      case "flow-map-end":
      case "map-value-ind":
        yield* this.pop();
        yield* this.step();
        break;
      case "newline":
        this.onKeyLine = false;
      // fallthrough
      case "space":
      case "comment":
      default:
        if (token.end)
          token.end.push(this.sourceToken);
        else
          token.end = [this.sourceToken];
        if (this.type === "newline")
          yield* this.pop();
    }
  }
};

// node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/browser/dist/public-api.js
function parseOptions(options) {
  const prettyErrors = options.prettyErrors !== false;
  const lineCounter = options.lineCounter || prettyErrors && new LineCounter() || null;
  return { lineCounter, prettyErrors };
}
function parseDocument(source, options = {}) {
  const { lineCounter, prettyErrors } = parseOptions(options);
  const parser = new Parser(lineCounter == null ? void 0 : lineCounter.addNewLine);
  const composer = new Composer(options);
  let doc = null;
  for (const _doc of composer.compose(parser.parse(source), true, source.length)) {
    if (!doc)
      doc = _doc;
    else if (doc.options.logLevel !== "silent") {
      doc.errors.push(new YAMLParseError(_doc.range.slice(0, 2), "MULTIPLE_DOCS", "Source contains multiple documents; please use YAML.parseAllDocuments()"));
      break;
    }
  }
  if (prettyErrors && lineCounter) {
    doc.errors.forEach(prettifyError(source, lineCounter));
    doc.warnings.forEach(prettifyError(source, lineCounter));
  }
  return doc;
}
function parse2(src, reviver, options) {
  let _reviver = void 0;
  if (typeof reviver === "function") {
    _reviver = reviver;
  } else if (options === void 0 && reviver && typeof reviver === "object") {
    options = reviver;
  }
  const doc = parseDocument(src, options);
  if (!doc)
    return null;
  doc.warnings.forEach((warning) => warn(doc.options.logLevel, warning));
  if (doc.errors.length > 0) {
    if (doc.options.logLevel !== "silent")
      throw doc.errors[0];
    else
      doc.errors = [];
  }
  return doc.toJS(Object.assign({ reviver: _reviver }, options));
}

// src/utils/FrontmatterAnalyzer.ts
var FrontmatterAnalyzer = class {
  constructor(app) {
    this.app = app;
  }
  async findExampleFile(folderPath, includeMdx = false) {
    const folder = this.app.vault.getAbstractFileByPath(folderPath);
    if (!folder) {
      return null;
    }
    if (folder instanceof import_obsidian9.TFile) {
      const ext = folder.extension;
      if (ext === "md" || includeMdx && ext === "mdx") {
        return await this.parseFrontmatter(folder);
      }
      return null;
    }
    if (!(folder instanceof import_obsidian9.TFolder)) {
      return null;
    }
    let files = this.getMarkdownFiles(folder, false, void 0, 0, includeMdx);
    if (files.length === 0) {
      files = this.getMarkdownFiles(folder, true, 1, 0, includeMdx);
      if (files.length === 0) {
        files = this.getMarkdownFiles(folder, true, 2, 0, includeMdx);
      }
      if (files.length === 0) {
        files = this.getMarkdownFiles(folder, true, void 0, 0, includeMdx);
      }
    }
    const isLikelySectionConfig = (f) => {
      if (!f.parent) return false;
      const mdSiblings = f.parent.children.filter(
        (c) => c instanceof import_obsidian9.TFile && c.path !== f.path && (c.extension === "md" || c.extension === "mdx")
      );
      if (mdSiblings.length === 0) return false;
      const name = f.basename.toLowerCase();
      if (name === "index" || name === "-index" || name === "_index") return true;
      return false;
    };
    if (files.length > 1) {
      const candidates = [];
      for (const file of files) {
        const example = await this.parseFrontmatter(file);
        if (!example) continue;
        let score = 0;
        if (!isLikelySectionConfig(file)) score += 100;
        if (example.frontmatter) score += Object.keys(example.frontmatter).length;
        candidates.push({ file, example, score });
      }
      candidates.sort((a, b) => b.score - a.score);
      if (candidates.length > 0) return candidates[0].example;
    } else {
      for (const file of files) {
        const example = await this.parseFrontmatter(file);
        if (example) return example;
      }
    }
    return null;
  }
  /**
   * Scans multiple files in a folder to aggregate all unique frontmatter properties.
   * This ensures properties aren't missed just because they're not in the single "latest" file.
   */
  async getPropertiesInFolder(folderPath, includeMdx = false, limit = 50) {
    const folder = this.app.vault.getAbstractFileByPath(folderPath);
    if (!(folder instanceof import_obsidian9.TFolder)) {
      return /* @__PURE__ */ new Set();
    }
    const files = this.getMarkdownFiles(folder, true, void 0, 0, includeMdx);
    const filesToScan = files.slice(0, limit);
    const fileKeys = /* @__PURE__ */ new Map();
    for (const file of filesToScan) {
      let keys = [];
      if (file.extension === "md") {
        const cache = this.app.metadataCache.getFileCache(file);
        if (cache == null ? void 0 : cache.frontmatter) keys = Object.keys(cache.frontmatter);
      } else if (includeMdx && file.extension === "mdx") {
        const parsed = await this.parseFrontmatter(file);
        if (parsed == null ? void 0 : parsed.frontmatter) keys = Object.keys(parsed.frontmatter);
      }
      if (keys.length > 0) fileKeys.set(file.path, new Set(keys));
    }
    const keyFrequency = /* @__PURE__ */ new Map();
    for (const keys of fileKeys.values()) {
      for (const k of keys) keyFrequency.set(k, (keyFrequency.get(k) || 0) + 1);
    }
    const threshold = Math.max(1, Math.floor(fileKeys.size / 2));
    const consensusKeys = /* @__PURE__ */ new Set();
    for (const [k, count] of keyFrequency) {
      if (count >= threshold) consensusKeys.add(k);
    }
    const isSectionConfig = (f) => {
      if (!f.parent) return false;
      const mdSiblings = f.parent.children.filter(
        (c) => c instanceof import_obsidian9.TFile && c.path !== f.path && (c.extension === "md" || c.extension === "mdx")
      );
      if (mdSiblings.length === 0) return false;
      const keys = fileKeys.get(f.path);
      if (keys && consensusKeys.size > 0) {
        let overlap = 0;
        for (const k of keys) {
          if (consensusKeys.has(k)) overlap++;
        }
        const similarity = overlap / Math.max(keys.size, 1);
        if (similarity < 0.3 && keys.size > 2) return true;
      }
      const name = f.basename.toLowerCase();
      return name === "index" || name === "-index" || name === "_index";
    };
    const propCount = /* @__PURE__ */ new Map();
    let nonIndexFileCount = 0;
    for (const file of filesToScan) {
      const isConfig = isSectionConfig(file);
      if (!isConfig) nonIndexFileCount++;
      const keys = fileKeys.get(file.path);
      if (!keys) continue;
      for (const key of keys) {
        if (isConfig) {
          if (!propCount.has(key)) propCount.set(key, 0);
        } else {
          propCount.set(key, (propCount.get(key) || 0) + 1);
        }
      }
    }
    const aggregateProps = /* @__PURE__ */ new Set();
    for (const [key, count] of propCount.entries()) {
      if (nonIndexFileCount === 0 || count > 0) {
        aggregateProps.add(key);
      }
    }
    return aggregateProps;
  }
  hasUnderscoreFiles(folderPath) {
    const folder = this.app.vault.getAbstractFileByPath(folderPath);
    if (!(folder instanceof import_obsidian9.TFolder)) {
      return Promise.resolve(false);
    }
    const files = this.getMarkdownFiles(folder, true);
    return Promise.resolve(files.some((file) => file.name.startsWith("_")));
  }
  getMarkdownFiles(folder, recursive = true, maxDepth, currentDepth = 0, includeMdx = false) {
    const files = [];
    if (!folder.children) {
      return files;
    }
    if (maxDepth !== void 0 && currentDepth >= maxDepth) {
      return files;
    }
    for (const child of folder.children) {
      if (child instanceof import_obsidian9.TFile) {
        if (child.extension === "md" || includeMdx && child.extension === "mdx") {
          files.push(child);
        }
      } else if (recursive && child instanceof import_obsidian9.TFolder && child.children) {
        files.push(...this.getMarkdownFiles(child, recursive, maxDepth, currentDepth + 1, includeMdx));
      }
    }
    return files;
  }
  async parseFrontmatter(file) {
    try {
      const content = await this.app.vault.read(file);
      const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n/;
      const match = content.match(frontmatterRegex);
      if (!match) {
        return null;
      }
      const yamlContent = match[1];
      const frontmatter = parse2(yamlContent);
      if (!frontmatter || typeof frontmatter !== "object") {
        return null;
      }
      return {
        file: file.path,
        frontmatter,
        rawYaml: yamlContent
      };
    } catch (e) {
      return null;
    }
  }
  autoDetectTitleProperty(frontmatter) {
    const titleProperties = ["title", "name", "headline", "heading", "subject"];
    for (const prop of titleProperties) {
      if (frontmatter.hasOwnProperty(prop)) {
        return prop;
      }
    }
    return null;
  }
  autoDetectDateProperty(frontmatter) {
    const dateProperties = ["date", "pubDate", "publishedDate", "publishDate", "created", "modified", "updated"];
    for (const prop of dateProperties) {
      if (frontmatter.hasOwnProperty(prop)) {
        return prop;
      }
    }
    for (const prop in frontmatter) {
      if (prop.toLowerCase().includes("date") && this.looksLikeDate(frontmatter[prop])) {
        return prop;
      }
    }
    return null;
  }
  looksLikeDate(value) {
    if (value instanceof Date) return true;
    if (typeof value === "string") {
      return /^\d{4}-\d{2}-\d{2}/.test(value);
    }
    if (typeof value === "number") {
      return value > 1e9;
    }
    return false;
  }
  autoDetectDescriptionProperty(frontmatter, exampleFrontmatter) {
    const descKeywords = ["description", "summary", "excerpt", "intro", "snippet", "blurb"];
    const findMatch = (keys) => {
      for (const kw of descKeywords) {
        if (keys.includes(kw)) return kw;
      }
      for (const key of keys) {
        const lower = key.toLowerCase();
        if (descKeywords.some((kw) => lower.includes(kw))) return key;
      }
      return null;
    };
    if (exampleFrontmatter) {
      const match = findMatch(Object.keys(exampleFrontmatter));
      if (match) return match;
    }
    return findMatch(Object.keys(frontmatter));
  }
  autoDetectTagsProperty(frontmatter) {
    if (frontmatter.hasOwnProperty("tags")) {
      return "tags";
    }
    return null;
  }
  autoDetectDraftProperty(frontmatter) {
    if (frontmatter.hasOwnProperty("draft")) {
      const val = frontmatter["draft"];
      if (typeof val === "boolean" || val === null) {
        return { property: "draft", logic: "true-draft" };
      }
    }
    if (frontmatter.hasOwnProperty("published")) {
      const val = frontmatter["published"];
      if (typeof val === "boolean" || val === null) {
        if (val === null) return null;
        return { property: "published", logic: "false-draft" };
      }
    }
    if (frontmatter.hasOwnProperty("visible")) {
      const val = frontmatter["visible"];
      if (typeof val === "boolean" || val === null) {
        return { property: "visible", logic: "false-draft" };
      }
    }
    return null;
  }
  autoDetectImageProperty(frontmatter) {
    const imageProperties = ["image", "cover", "coverImage", "thumbnail", "featuredImage", "heroImage"];
    for (const prop of imageProperties) {
      if (frontmatter.hasOwnProperty(prop)) {
        return prop;
      }
    }
    return null;
  }
};

// src/ui/wizard/FrontmatterPropertiesStep.ts
function setCssProps4(element, props) {
  for (const [key, value] of Object.entries(props)) {
    element.style.setProperty(key.replace(/([A-Z])/g, "-$1").toLowerCase(), value);
  }
}
var FrontmatterPropertiesStep = class extends BaseWizardStep {
  constructor(app, containerEl, state, onNext, onBack, onCancel) {
    super(app, containerEl, state, onNext, onBack, onCancel);
    this.examples = {};
    this.frontmatterAnalyzer = new FrontmatterAnalyzer(app);
  }
  async display() {
    const { containerEl } = this;
    const existingWrapper = containerEl.querySelector(".frontmatter-step-content");
    if (existingWrapper) {
      existingWrapper.remove();
    }
    const stepContentWrapper = containerEl.createDiv({ cls: "frontmatter-step-content" });
    stepContentWrapper.createEl("h2", { text: "Frontmatter properties" });
    stepContentWrapper.createEl("p", {
      text: "Map properties for each content type. We'll find example files to help you."
    });
    for (const contentType of this.state.contentTypes) {
      if (!contentType.enabled) {
        continue;
      }
      const contentTypeWrapper = stepContentWrapper.createDiv({ cls: "content-type-settings" });
      const pathResolver = new PathResolver(this.app);
      const folderPath = pathResolver.getFolderPathFromVaultRoot(contentType.folder, this.state.projectDetection);
      if (!this.examples[contentType.id]) {
        const example2 = await this.frontmatterAnalyzer.findExampleFile(folderPath, this.state.enableMdxSupport);
        if (example2) {
          this.examples[contentType.id] = example2;
        }
      }
      const example = this.examples[contentType.id];
      const aggregateProps = await this.frontmatterAnalyzer.getPropertiesInFolder(folderPath, this.state.enableMdxSupport);
      const dummyFrontmatter = {};
      aggregateProps.forEach((key) => dummyFrontmatter[key] = null);
      contentTypeWrapper.createEl("h3", { text: contentType.name });
      if (example) {
        contentTypeWrapper.createEl("p", { text: `Example file: ${example.file}` });
        const preEl = contentTypeWrapper.createEl("pre", {
          text: example.rawYaml,
          cls: "frontmatter-example"
        });
        setCssProps4(preEl, {
          fontFamily: "var(--font-monospace)",
          fontSize: "0.85em",
          whiteSpace: "pre-wrap",
          overflowWrap: "break-word",
          maxWidth: "100%",
          padding: "10px",
          backgroundColor: "var(--background-secondary)",
          borderRadius: "4px",
          border: "1px solid var(--background-modifier-border)"
        });
      }
      const hasUnderscoreFiles = await this.frontmatterAnalyzer.hasUnderscoreFiles(folderPath);
      if (!this.state.frontmatterProperties[contentType.id]) {
        const detectedDraft = this.frontmatterAnalyzer.autoDetectDraftProperty(dummyFrontmatter);
        const detectedTags = this.frontmatterAnalyzer.autoDetectTagsProperty(dummyFrontmatter);
        const detectedImage = this.frontmatterAnalyzer.autoDetectImageProperty(dummyFrontmatter);
        const detectedDesc = this.frontmatterAnalyzer.autoDetectDescriptionProperty(dummyFrontmatter, example == null ? void 0 : example.frontmatter);
        const detectedTitle = this.frontmatterAnalyzer.autoDetectTitleProperty(dummyFrontmatter);
        const detectedDate = this.frontmatterAnalyzer.autoDetectDateProperty(dummyFrontmatter);
        const useDraftProperty = hasUnderscoreFiles ? void 0 : detectedDraft == null ? void 0 : detectedDraft.property;
        this.state.frontmatterProperties[contentType.id] = {
          titleProperty: detectedTitle || void 0,
          dateProperty: detectedDate || void 0,
          descriptionProperty: detectedDesc || void 0,
          tagsProperty: detectedTags || void 0,
          draftProperty: useDraftProperty,
          draftLogic: useDraftProperty === "published" ? "false-draft" : useDraftProperty ? "true-draft" : void 0,
          hasDraftStatus: !!useDraftProperty || hasUnderscoreFiles,
          imageProperty: detectedImage || void 0
        };
      }
      const props = this.state.frontmatterProperties[contentType.id];
      new import_obsidian10.Setting(contentTypeWrapper).setName("Title property").setDesc("The property that contains the title (like title, name, heading). Leave blank to use full file name instead.").addText((text) => {
        const detected = "title";
        text.setPlaceholder(detected).setValue(props.titleProperty || "").onChange((value) => {
          props.titleProperty = value.trim() || void 0;
        });
      });
      new import_obsidian10.Setting(contentTypeWrapper).setName("Date property").setDesc("The property that contains the date (like date, pubDate, publishedDate, publishDate). Leave blank to use file created date instead.").addText((text) => {
        const detected = example ? this.frontmatterAnalyzer.autoDetectDateProperty(example.frontmatter) : null;
        text.setPlaceholder(detected || "date").setValue(props.dateProperty || "").onChange((value) => {
          props.dateProperty = value.trim() || void 0;
        });
      });
      const descSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Has description/summary?").setDesc("Does this content type have a description or summary field?");
      let descTextSetting = null;
      descSetting.addToggle((toggle) => toggle.setValue(!!props.descriptionProperty).onChange((value) => {
        if (value && !props.descriptionProperty) {
          props.descriptionProperty = example ? this.frontmatterAnalyzer.autoDetectDescriptionProperty(example.frontmatter) || "description" : "description";
          if (!descTextSetting) {
            descTextSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Description property").setDesc("The property that contains the description (like description, summary, excerpt, intro, snippet, blurb)").addText((text) => text.setValue(props.descriptionProperty || "").onChange((value2) => {
              props.descriptionProperty = value2.trim() || void 0;
            }));
            descTextSetting.settingEl.remove();
            descSetting.settingEl.insertAdjacentElement("afterend", descTextSetting.settingEl);
          }
        } else if (!value) {
          props.descriptionProperty = void 0;
          if (descTextSetting) {
            descTextSetting.settingEl.remove();
            descTextSetting = null;
          }
        }
      }));
      if (props.descriptionProperty) {
        descTextSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Description property").setDesc("The property that contains the description (like description, summary, excerpt, intro, snippet, blurb)").addText((text) => text.setValue(props.descriptionProperty || "").onChange((value) => {
          props.descriptionProperty = value.trim() || void 0;
        }));
        descTextSetting.settingEl.remove();
        descSetting.settingEl.insertAdjacentElement("afterend", descTextSetting.settingEl);
      }
      const tagsSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Has tags?").setDesc("Does this content type have tags?");
      let tagsTextSetting = null;
      tagsSetting.addToggle((toggle) => toggle.setValue(!!props.tagsProperty).onChange((value) => {
        if (value && !props.tagsProperty) {
          const detected = example ? this.frontmatterAnalyzer.autoDetectTagsProperty(example.frontmatter) : null;
          props.tagsProperty = detected || "tags";
          if (!tagsTextSetting) {
            tagsTextSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Tags property").setDesc("The property that contains tags (like tags, tag, categories, category). Leave blank if not applicable.").addText((text) => {
              const detected2 = example ? this.frontmatterAnalyzer.autoDetectTagsProperty(example.frontmatter) : null;
              text.setPlaceholder(detected2 || "tags").setValue(props.tagsProperty || "").onChange((value2) => {
                props.tagsProperty = value2.trim() || void 0;
              });
            });
            tagsTextSetting.settingEl.remove();
            tagsSetting.settingEl.insertAdjacentElement("afterend", tagsTextSetting.settingEl);
          }
        } else if (!value) {
          props.tagsProperty = void 0;
          if (tagsTextSetting) {
            tagsTextSetting.settingEl.remove();
            tagsTextSetting = null;
          }
        }
      }));
      if (props.tagsProperty) {
        tagsTextSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Tags property").setDesc("The property that contains tags (like tags, tag, categories, category). Leave blank if not applicable.").addText((text) => {
          const detected = example ? this.frontmatterAnalyzer.autoDetectTagsProperty(example.frontmatter) : null;
          text.setPlaceholder(detected || "tags").setValue(props.tagsProperty || "").onChange((value) => {
            props.tagsProperty = value.trim() || void 0;
          });
        });
        tagsTextSetting.settingEl.remove();
        tagsSetting.settingEl.insertAdjacentElement("afterend", tagsTextSetting.settingEl);
      }
      const draftSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Enable draft status").setDesc("Property-based drafts use a property key (like draft). Underscore-only drafts use file prefix (_post.md) with no property.");
      let draftPropertySetting = null;
      let draftLogicSetting = null;
      if (props.hasDraftStatus === void 0) {
        props.hasDraftStatus = !!props.draftProperty;
      }
      draftSetting.addToggle((toggle) => {
        var _a;
        return toggle.setValue((_a = props.hasDraftStatus) != null ? _a : !!props.draftProperty).onChange((value) => {
          props.hasDraftStatus = value;
          if (value && !props.draftProperty) {
            const detectedDraft = !hasUnderscoreFiles && example ? this.frontmatterAnalyzer.autoDetectDraftProperty(example.frontmatter) : null;
            props.draftProperty = detectedDraft == null ? void 0 : detectedDraft.property;
            if (props.draftProperty) {
              if (props.draftProperty === "published") {
                props.draftLogic = "false-draft";
              } else {
                props.draftLogic = "true-draft";
              }
            }
            if (!draftPropertySetting) {
              draftPropertySetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Draft property").setDesc("The frontmatter property that contains draft status. Leave blank to use an underscore prefix instead.").addText((text) => {
                const detected = example ? this.frontmatterAnalyzer.autoDetectDraftProperty(example.frontmatter) : null;
                text.setPlaceholder((detected == null ? void 0 : detected.property) || "draft").setValue(props.draftProperty || "").onChange((value2) => {
                  props.draftProperty = value2.trim() || void 0;
                  if (value2 === "published") {
                    props.draftLogic = "false-draft";
                  } else if (value2) {
                    props.draftLogic = "true-draft";
                  }
                  if (value2 && !draftLogicSetting) {
                    draftLogicSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Draft logic").setDesc("How draft status is represented").addDropdown((dropdown) => dropdown.addOption("true-draft", "true = draft").addOption("false-draft", "false = draft").setValue(props.draftLogic || "true-draft").onChange((dropdownValue) => {
                      props.draftLogic = dropdownValue;
                    }));
                    draftLogicSetting.settingEl.remove();
                    if (draftPropertySetting) {
                      draftPropertySetting.settingEl.insertAdjacentElement("afterend", draftLogicSetting.settingEl);
                    }
                  } else if (!value2 && draftLogicSetting) {
                    draftLogicSetting.settingEl.remove();
                    draftLogicSetting = null;
                  }
                });
              });
              draftPropertySetting.settingEl.remove();
              draftSetting.settingEl.insertAdjacentElement("afterend", draftPropertySetting.settingEl);
            }
            if (props.draftProperty && !draftLogicSetting) {
              draftLogicSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Draft logic").setDesc("How draft status is represented").addDropdown((dropdown) => dropdown.addOption("true-draft", "true = draft").addOption("false-draft", "false = draft").setValue(props.draftLogic || "true-draft").onChange((value2) => {
                props.draftLogic = value2;
              }));
              draftLogicSetting.settingEl.remove();
              if (draftPropertySetting !== null) {
                draftPropertySetting.settingEl.insertAdjacentElement("afterend", draftLogicSetting.settingEl);
              }
            }
          } else if (!value) {
            props.draftProperty = void 0;
            props.draftLogic = void 0;
            props.hasDraftStatus = false;
            if (draftPropertySetting) {
              draftPropertySetting.settingEl.remove();
              draftPropertySetting = null;
            }
            if (draftLogicSetting) {
              draftLogicSetting.settingEl.remove();
              draftLogicSetting = null;
            }
          }
        });
      });
      if (props.hasDraftStatus) {
        draftPropertySetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Draft property").setDesc("The frontmatter property that contains draft status. Leave blank to use an underscore prefix instead.").addText((text) => {
          const detected = example ? this.frontmatterAnalyzer.autoDetectDraftProperty(example.frontmatter) : null;
          text.setPlaceholder((detected == null ? void 0 : detected.property) || "draft").setValue(props.draftProperty || "").onChange((value) => {
            props.draftProperty = value.trim() || void 0;
            if (value === "published") {
              props.draftLogic = "false-draft";
            } else if (value) {
              props.draftLogic = "true-draft";
            }
            if (value && !draftLogicSetting) {
              draftLogicSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Draft logic").setDesc("How draft status is represented").addDropdown((dropdown) => dropdown.addOption("true-draft", "true = draft").addOption("false-draft", "false = draft").setValue(props.draftLogic || "true-draft").onChange((dropdownValue) => {
                props.draftLogic = dropdownValue;
              }));
              draftLogicSetting.settingEl.remove();
              if (draftPropertySetting) {
                draftPropertySetting.settingEl.insertAdjacentElement("afterend", draftLogicSetting.settingEl);
              }
            } else if (!value && draftLogicSetting) {
              draftLogicSetting.settingEl.remove();
              draftLogicSetting = null;
            }
          });
        });
        draftPropertySetting.settingEl.remove();
        draftSetting.settingEl.insertAdjacentElement("afterend", draftPropertySetting.settingEl);
        if (props.draftProperty) {
          draftLogicSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Draft logic").setDesc("How draft status is represented").addDropdown((dropdown) => dropdown.addOption("true-draft", "true = draft").addOption("false-draft", "false = draft").setValue(props.draftLogic || "true-draft").onChange((value) => {
            props.draftLogic = value;
          }));
          draftLogicSetting.settingEl.remove();
          if (draftPropertySetting !== null) {
            draftPropertySetting.settingEl.insertAdjacentElement("afterend", draftLogicSetting.settingEl);
          }
        }
      }
      const imageSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Has image/cover property?").setDesc("Does this content type have an image or cover property? Used for Bases CMS cover images and Image Manager.");
      let imageTextSetting = null;
      imageSetting.addToggle((toggle) => toggle.setValue(!!props.imageProperty).onChange((value) => {
        if (value && !props.imageProperty) {
          const detected = example ? this.frontmatterAnalyzer.autoDetectImageProperty(example.frontmatter) : null;
          props.imageProperty = detected || "image";
          if (!imageTextSetting) {
            imageTextSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Image property").setDesc("The property that contains the image/cover (like image, cover, coverImage, thumbnail, featuredImage). Leave blank if not applicable.").addText((text) => {
              const detected2 = example ? this.frontmatterAnalyzer.autoDetectImageProperty(example.frontmatter) : null;
              text.setPlaceholder(detected2 || "image").setValue(props.imageProperty || "").onChange((value2) => {
                props.imageProperty = value2.trim() || void 0;
              });
            });
            imageTextSetting.settingEl.remove();
            imageSetting.settingEl.insertAdjacentElement("afterend", imageTextSetting.settingEl);
          }
        } else if (!value) {
          props.imageProperty = void 0;
          if (imageTextSetting) {
            imageTextSetting.settingEl.remove();
            imageTextSetting = null;
          }
        }
      }));
      if (props.imageProperty) {
        imageTextSetting = new import_obsidian10.Setting(contentTypeWrapper).setName("Image property").setDesc("The property that contains the image/cover (like image, cover, coverImage, thumbnail, featuredImage). Leave blank if not applicable.").addText((text) => {
          const detected = example ? this.frontmatterAnalyzer.autoDetectImageProperty(example.frontmatter) : null;
          text.setPlaceholder(detected || "image").setValue(props.imageProperty || "").onChange((value) => {
            props.imageProperty = value.trim() || void 0;
          });
        });
        imageTextSetting.settingEl.remove();
        imageSetting.settingEl.insertAdjacentElement("afterend", imageTextSetting.settingEl);
      }
      contentTypeWrapper.createEl("h4", { text: "Template" });
      contentTypeWrapper.createEl("p", {
        text: 'Edit the template that will be used when creating new files of this content type. Use {{title}} and {{date}} as variables. Note: {{title}} should be in quotes (like title: "{{title}}"), while {{date}} should not be in quotes (like date: {{date}}).'
      });
      {
        const pathResolver2 = new PathResolver(this.app);
        const folderPath2 = pathResolver2.getFolderPathFromVaultRoot(contentType.folder, this.state.projectDetection);
        const aggregateProps2 = await this.frontmatterAnalyzer.getPropertiesInFolder(folderPath2, this.state.enableMdxSupport);
        props.template = this.generateDefaultTemplate(props, example, aggregateProps2);
      }
      const templateTextArea = contentTypeWrapper.createEl("textarea", {
        cls: "template-editor",
        attr: {
          rows: "10",
          style: "width: 100%; font-family: monospace;",
          spellcheck: "false"
        }
      });
      templateTextArea.value = props.template || "";
      templateTextArea.addEventListener("input", (e) => {
        const target = e.target;
        props.template = target.value;
      });
    }
  }
  generateDefaultTemplate(props, example, aggregateProps) {
    let template = "---\n";
    if (example && example.rawYaml) {
      const lines = example.rawYaml.split("\n");
      const topLevelLines = lines.filter((line) => line.length > 0 && !line.startsWith(" ") && !line.startsWith("	") && !line.startsWith("#"));
      const processedProps = /* @__PURE__ */ new Set();
      let titleAdded = false;
      if (props.titleProperty) {
        for (const line of topLevelLines) {
          const trimmed = line.trim();
          if (!trimmed) continue;
          const colonIndex = trimmed.indexOf(":");
          if (colonIndex > 0) {
            const prop = trimmed.substring(0, colonIndex).trim();
            if (prop === props.titleProperty) {
              template += `${props.titleProperty}: "{{title}}"
`;
              titleAdded = true;
              processedProps.add(prop);
              continue;
            }
          }
        }
        if (!titleAdded) {
          template += `${props.titleProperty}: "{{title}}"
`;
        }
      }
      let dateAdded = false;
      if (props.dateProperty) {
        for (const line of topLevelLines) {
          const trimmed = line.trim();
          if (!trimmed) continue;
          const colonIndex = trimmed.indexOf(":");
          if (colonIndex > 0) {
            const prop = trimmed.substring(0, colonIndex).trim();
            if (prop === props.dateProperty && !processedProps.has(prop)) {
              template += `${props.dateProperty}: {{date}}
`;
              dateAdded = true;
              processedProps.add(prop);
              continue;
            }
          }
        }
        if (!dateAdded && !processedProps.has(props.dateProperty)) {
          template += `${props.dateProperty}: {{date}}
`;
          processedProps.add(props.dateProperty);
        }
      }
      for (const line of topLevelLines) {
        const trimmed = line.trim();
        if (!trimmed) continue;
        const colonIndex = trimmed.indexOf(":");
        if (colonIndex > 0) {
          const prop = trimmed.substring(0, colonIndex).trim();
          if (processedProps.has(prop)) {
            continue;
          }
          if (prop === props.descriptionProperty) {
            template += `${prop}: ""
`;
            processedProps.add(prop);
            continue;
          }
          if (prop === props.draftProperty && props.draftProperty) {
            const draftValue = props.draftLogic === "false-draft" ? "false" : "true";
            template += `${prop}: ${draftValue}
`;
            processedProps.add(prop);
            continue;
          }
          if ((prop === "draft" || prop === "published" || prop === "visible") && !props.draftProperty) {
            processedProps.add(prop);
            continue;
          }
          const value = example.frontmatter[prop];
          if (value === null || value === void 0) {
            template += `${prop}:
`;
          } else if (Array.isArray(value)) {
            template += `${prop}: []
`;
          } else if (typeof value === "boolean") {
            template += `${prop}: ${value}
`;
          } else if (typeof value === "number") {
            template += `${prop}: ${value}
`;
          } else if (typeof value === "string") {
            template += `${prop}: ""
`;
          } else {
            template += `${prop}: ""
`;
          }
          processedProps.add(prop);
        }
      }
      const descVariants = /* @__PURE__ */ new Set(["description", "summary", "excerpt", "intro", "snippet", "blurb", "metaDescription", "meta_description"]);
      for (const prop of aggregateProps) {
        if (processedProps.has(prop)) continue;
        if (props.descriptionProperty && prop !== props.descriptionProperty && descVariants.has(prop)) {
          continue;
        }
        if (prop === props.titleProperty) {
          template += `${prop}: "{{title}}"
`;
        } else if (prop === props.dateProperty) {
          template += `${prop}: {{date}}
`;
        } else if (prop === props.descriptionProperty) {
          template += `${prop}: ""
`;
        } else if (prop === props.tagsProperty) {
          template += `${prop}: []
`;
        } else if (prop === props.imageProperty) {
          template += `${prop}: ""
`;
        } else if (prop === props.draftProperty) {
          const draftValue = props.draftLogic === "false-draft" ? "false" : "true";
          template += `${prop}: ${draftValue}
`;
        } else if ((prop === "draft" || prop === "published" || prop === "visible") && !props.draftProperty) {
        } else {
          template += `${prop}: ""
`;
        }
        processedProps.add(prop);
      }
    } else {
      if (props.titleProperty) {
        template += `${props.titleProperty}: "{{title}}"
`;
      }
      if (props.dateProperty) {
        template += `${props.dateProperty}: {{date}}
`;
      }
      if (props.descriptionProperty) {
        template += `${props.descriptionProperty}: ""
`;
      }
      if (props.tagsProperty) {
        template += `${props.tagsProperty}: []
`;
      }
      if (props.draftProperty) {
        const draftValue = props.draftLogic === "false-draft" ? "false" : "true";
        template += `${props.draftProperty}: ${draftValue}
`;
      }
    }
    template += "---\n";
    return template;
  }
  validate() {
    return true;
  }
  getTitle() {
    return "Frontmatter properties";
  }
  getDescription() {
    return "Map frontmatter properties";
  }
};

// src/ui/wizard/PluginConfigurationStep.ts
var import_obsidian11 = require("obsidian");
function setCssProps5(element, props) {
  for (const [key, value] of Object.entries(props)) {
    element.style.setProperty(key.replace(/([A-Z])/g, "-$1").toLowerCase(), value);
  }
}
var PluginConfigurationStep = class extends BaseWizardStep {
  display() {
    var _a;
    const { containerEl } = this;
    containerEl.empty();
    containerEl.createEl("h2", { text: "Plugin Configuration" });
    containerEl.createEl("p", {
      text: "Your plugins will be automatically configured using your mapped properties. Review the settings below."
    });
    const enabledTypes = this.state.contentTypes.filter((ct) => ct.enabled);
    if (enabledTypes.length === 0) {
      containerEl.createEl("p", {
        text: "No content types enabled. Please go back and enable at least one content type."
      });
      return;
    }
    const basesCMSDiv = containerEl.createDiv({ cls: "plugin-config-section", attr: { style: "margin-bottom: 2rem;" } });
    basesCMSDiv.createEl("b", { text: "Base views to be created:", attr: { style: "display: block; margin-bottom: 0.5rem;" } });
    const basesList = basesCMSDiv.createEl("ul", { attr: { style: "margin-top: 0;" } });
    for (const contentType of enabledTypes) {
      const props = this.state.frontmatterProperties[contentType.id];
      if (props) {
        const properties = [];
        if (props.titleProperty) properties.push(props.titleProperty);
        if (props.dateProperty) properties.push(props.dateProperty);
        if (props.descriptionProperty) properties.push(props.descriptionProperty);
        if (props.tagsProperty) properties.push(props.tagsProperty);
        if (props.imageProperty) properties.push(props.imageProperty);
        if (props.draftProperty) properties.push(props.draftProperty);
        const propertiesText = properties.length > 0 ? properties.join(", ") : "default properties";
        basesList.createEl("li", {
          text: `${contentType.name}: ${propertiesText}`
        });
      }
    }
    const astroComposerDiv = containerEl.createDiv({ cls: "plugin-config-section", attr: { style: "margin-bottom: 2rem;" } });
    astroComposerDiv.createEl("b", { text: "Creation logic:", attr: { style: "display: block; margin-bottom: 0.5rem;" } });
    const astroList = astroComposerDiv.createEl("ul", { attr: { style: "margin-top: 0;" } });
    for (const contentType of enabledTypes) {
      const modeLabel = contentType.fileOrganization === "folder" ? "folder-based" : "file-based";
      astroList.createEl("li", {
        text: `${contentType.name} (${contentType.folder}): ${modeLabel}`
      });
    }
    const configDiv = containerEl.createDiv({ cls: "plugin-config-section", attr: { style: "border-top: 1px solid var(--background-modifier-border); padding-top: 1rem;" } });
    const titleProperties = /* @__PURE__ */ new Set();
    const descriptionProperties = /* @__PURE__ */ new Set();
    for (const contentType of enabledTypes) {
      const props = this.state.frontmatterProperties[contentType.id];
      if (props) {
        if (props.titleProperty) titleProperties.add(props.titleProperty);
        if (props.descriptionProperty) descriptionProperties.add(props.descriptionProperty);
      }
    }
    if (titleProperties.size > 1 || descriptionProperties.size > 1) {
      const warningDiv = configDiv.createDiv({ cls: "vault-cms-warning" });
      setCssProps5(warningDiv, {
        padding: "10px",
        backgroundColor: "var(--background-modifier-border)",
        borderLeft: "3px solid var(--text-warning)",
        marginBottom: "15px"
      });
      warningDiv.createEl("p", {
        text: "\u26A0\uFE0F Warning: Different content types use different properties for title or description. SEO will use the default content type's properties.",
        attr: { style: "margin: 0; font-size: 0.9em;" }
      });
    }
    new import_obsidian11.Setting(configDiv).setName("Default content type").setDesc("Choose the default content type for new notes and Home base").addDropdown((dropdown) => {
      var _a2;
      enabledTypes.forEach((ct) => {
        dropdown.addOption(ct.id, ct.name);
      });
      dropdown.setValue(this.state.defaultContentTypeId || (((_a2 = enabledTypes[0]) == null ? void 0 : _a2.id) || ""));
      dropdown.onChange((value) => {
        this.state.defaultContentTypeId = value;
      });
    });
    const pathResolver = new PathResolver(this.app);
    const defaultScanDirs = this.state.contentTypes.filter((ct) => ct.enabled).map((ct) => pathResolver.getFolderPathFromVaultRoot(ct.folder, this.state.projectDetection)).join(",");
    const savedScanDirs = (_a = this.state.seoConfig) == null ? void 0 : _a.scanDirectories;
    const initialScanDirs = savedScanDirs && savedScanDirs.trim() ? savedScanDirs : defaultScanDirs;
    if (!this.state.seoConfig.scanDirectories || !this.state.seoConfig.scanDirectories.trim()) {
      this.state.seoConfig.scanDirectories = initialScanDirs;
    }
    new import_obsidian11.Setting(configDiv).setName("SEO Scan directories").setDesc("Comma-separated list of directories to scan").addText((text) => text.setValue(this.state.seoConfig.scanDirectories).onChange((value) => {
      if (this.state.seoConfig) {
        this.state.seoConfig.scanDirectories = value;
      }
    }));
  }
  validate() {
    return this.state.contentTypes.some((ct) => ct.enabled);
  }
  getTitle() {
    return "Plugin configuration";
  }
  getDescription() {
    return "Configure Bases, Astro Composer, SEO, and Default Type";
  }
};

// src/ui/wizard/OptionalPluginsStep.ts
var import_obsidian12 = require("obsidian");

// src/utils/PluginManager.ts
var PluginManager = class {
  constructor(app) {
    this.app = app;
  }
  async enablePlugin(pluginId) {
    var _a, _b;
    const plugins = this.app.plugins;
    if (!plugins) {
      return;
    }
    const plugin = (_a = plugins.plugins) == null ? void 0 : _a[pluginId];
    if (plugin && !plugin.enabled) {
      await ((_b = plugins.enablePlugin) == null ? void 0 : _b.call(plugins, pluginId));
    }
  }
  async disablePlugin(pluginId) {
    var _a, _b;
    const plugins = this.app.plugins;
    if (!plugins) {
      return;
    }
    const plugin = (_a = plugins.plugins) == null ? void 0 : _a[pluginId];
    if (plugin && plugin.enabled) {
      await ((_b = plugins.disablePlugin) == null ? void 0 : _b.call(plugins, pluginId));
    }
  }
  async setPluginStates(enabled, disabled) {
    const corePlugins = ["bases-cms", "astro-composer", "vault-cms"];
    const safeDisabled = disabled.filter((p) => !corePlugins.includes(p));
    for (const pluginId of safeDisabled) {
      await this.disablePlugin(pluginId);
    }
    for (const pluginId of enabled) {
      await this.enablePlugin(pluginId);
    }
  }
  getPresetPlugins(preset) {
    const corePlugins = [
      "astro-composer",
      "bases-cms",
      "homepage",
      "new-tab-default-page",
      "property-over-file-name",
      "settings-search",
      "statusbar-organizer",
      "seo",
      "ui-tweaker",
      "zenmode",
      "cmdr",
      "simple-focus",
      "tag-wrangler"
    ];
    const optionalPlugins = [
      "editing-toolbar",
      "insert-unsplash-image",
      "custom-save",
      "title-only-tab",
      "obsidian-paste-image-rename",
      "obsidian42-brat",
      "obsidian-hider",
      "disable-tabs",
      "obsidian-style-settings",
      "mdx-as-md-obsidian",
      "explorer-focus"
    ];
    const opinionatedPlugins = [
      "obsidian-oxygen",
      "obsidian-style-settings"
    ];
    if (preset === "vanilla") {
      return {
        enabled: [...corePlugins, ...optionalPlugins.filter((p) => !opinionatedPlugins.includes(p))],
        disabled: opinionatedPlugins
      };
    } else if (preset === "opinionated") {
      return {
        enabled: [...corePlugins, ...optionalPlugins],
        disabled: []
      };
    } else {
      return {
        enabled: [],
        disabled: []
      };
    }
  }
};

// src/ui/wizard/OptionalPluginsStep.ts
function setCssProps6(element, props) {
  for (const [key, value] of Object.entries(props)) {
    element.style.setProperty(key.replace(/([A-Z])/g, "-$1").toLowerCase(), value);
  }
}
var OptionalPluginsStep = class extends BaseWizardStep {
  constructor(app, containerEl, state, onNext, onBack, onCancel) {
    super(app, containerEl, state, onNext, onBack, onCancel);
    this.pluginManager = new PluginManager(app);
  }
  display() {
    const { containerEl } = this;
    containerEl.empty();
    containerEl.createEl("h2", { text: "Plugin detection" });
    containerEl.createEl("p", {
      text: "Review and configure your installed plugins. Essential plugins are recommended for the core Vault CMS experience."
    });
    const allPlugins = [
      { id: "astro-composer", name: "Astro Composer", category: "essential", source: "brat", repo: "davidvkimball/obsidian-astro-composer" },
      { id: "bases-cms", name: "Bases CMS", category: "essential", source: "brat", repo: "davidvkimball/obsidian-bases-cms" },
      { id: "new-tab-default-page", name: "Default New Tab Page", category: "essential", source: "community" },
      { id: "editing-toolbar", name: "Editing Toolbar", category: "essential", source: "community" },
      { id: "home-base", name: "Home Base", category: "essential", source: "brat", repo: "davidvkimball/obsidian-home-base" },
      { id: "homepage", name: "Homepage", category: "essential", source: "community" },
      { id: "image-manager", name: "Image Manager", category: "essential", source: "brat", repo: "davidvkimball/obsidian-image-manager" },
      { id: "obsidian-paste-image-rename", name: "Paste Image Rename", category: "essential", source: "community" },
      { id: "property-over-file-name", name: "Property Over File Name", category: "essential", source: "brat", repo: "davidvkimball/obsidian-property-over-file-name" },
      { id: "seo", name: "SEO", category: "essential", source: "brat", repo: "davidvkimball/obsidian-seo" },
      { id: "ui-tweaker", name: "UI Tweaker", category: "essential", source: "brat", repo: "davidvkimball/obsidian-ui-tweaker" },
      { id: "simple-focus", name: "Simple Focus", category: "essential", source: "community" },
      { id: "statusbar-organizer", name: "Status Bar Organizer", category: "essential", source: "community" },
      { id: "omnisearch", name: "Omnisearch", category: "nice-to-have", source: "community" },
      { id: "file-name-history", name: "File Name History", category: "nice-to-have", source: "brat", repo: "davidvkimball/obsidian-file-name-history" },
      { id: "data-files-editor", name: "Data Files Editor", category: "nice-to-have", source: "brat", repo: "davidvkimball/obsidian-data-files-editor" },
      { id: "iconic", name: "Iconic", category: "nice-to-have", source: "community" },
      { id: "paste-image-into-property", name: "Paste Image Into Property", category: "nice-to-have", source: "community" },
      { id: "settings-search", name: "Settings Search", category: "nice-to-have", source: "community" },
      { id: "tag-wrangler", name: "Tag Wrangler", category: "nice-to-have", source: "community" },
      { id: "zenmode", name: "Zen Mode", category: "nice-to-have", source: "brat", repo: "davidvkimball/obsidian-zenmode" },
      { id: "explorer-focus", name: "Explorer Focus", category: "nice-to-have", source: "brat", repo: "davidvkimball/obsidian-explorer-focus" }
    ];
    const plugins = this.app.plugins;
    const installedPluginIds = (plugins == null ? void 0 : plugins.plugins) ? Object.keys(plugins.plugins) : [];
    const ignoredPlugins = ["obsidian42-brat", "astro-modular-settings", "folder-notes", "disable-tabs", "vault-cms"];
    const essentialPlugins = allPlugins.filter(
      (p) => p.category === "essential" && installedPluginIds.includes(p.id) && !ignoredPlugins.includes(p.id)
    );
    const niceToHavePlugins = allPlugins.filter(
      (p) => p.category === "nice-to-have" && installedPluginIds.includes(p.id) && !ignoredPlugins.includes(p.id)
    ).sort((a, b) => a.name.localeCompare(b.name));
    if (essentialPlugins.length > 0) {
      const details = containerEl.createEl("details", { attr: { style: "margin-bottom: 1rem;" } });
      details.createEl("summary", {
        text: `Essential plugins (${essentialPlugins.length} found)`,
        attr: { style: "font-weight: bold; cursor: pointer; padding: 0.5rem 0;" }
      });
      const content = details.createDiv({ attr: { style: "padding: 0.5rem 0.5rem 0.5rem 1.5rem; border-left: 2px solid var(--background-modifier-border);" } });
      for (const plugin of essentialPlugins) {
        this.renderPluginStatus(content, plugin, plugins);
      }
    }
    if (niceToHavePlugins.length > 0) {
      const details = containerEl.createEl("details", { attr: { style: "margin-bottom: 2rem;" } });
      details.createEl("summary", {
        text: `Nice to have plugins (${niceToHavePlugins.length} found)`,
        attr: { style: "font-weight: bold; cursor: pointer; padding: 0.5rem 0;" }
      });
      const content = details.createDiv({ attr: { style: "padding: 0.5rem 0.5rem 0.5rem 1.5rem; border-left: 2px solid var(--background-modifier-border);" } });
      for (const plugin of niceToHavePlugins) {
        this.renderPluginStatus(content, plugin, plugins);
      }
    }
    if (essentialPlugins.length === 0 && niceToHavePlugins.length === 0) {
      containerEl.createEl("p", { text: "No Vault CMS plugins detected." });
    }
    const missingPlugins = allPlugins.filter(
      (p) => !installedPluginIds.includes(p.id) && !ignoredPlugins.includes(p.id)
    );
    if (missingPlugins.length > 0) {
      const missingEssential = missingPlugins.filter((p) => p.category === "essential");
      const missingNiceToHave = missingPlugins.filter((p) => p.category === "nice-to-have");
      if (missingEssential.length > 0 || missingNiceToHave.length > 0) {
        const details = containerEl.createEl("details", { attr: { style: "margin-bottom: 1rem;" } });
        details.createEl("summary", {
          text: `Not installed (${missingPlugins.length})`,
          attr: { style: "font-weight: bold; cursor: pointer; padding: 0.5rem 0; color: var(--text-muted);" }
        });
        const content = details.createDiv({ attr: { style: "padding: 0.5rem 0.5rem 0.5rem 1.5rem; border-left: 2px solid var(--background-modifier-border);" } });
        for (const plugin of [...missingEssential, ...missingNiceToHave]) {
          const setting = new import_obsidian12.Setting(content).setName(plugin.name).setDesc(plugin.category === "essential" ? "Recommended" : "Optional");
          setting.nameEl.style.fontSize = "0.9em";
          setting.descEl.style.fontSize = "0.8em";
          if (plugin.source === "community") {
            setting.addButton((btn) => btn.setButtonText("Install").setCta().onClick(() => {
              window.open(`obsidian://show-plugin?id=${plugin.id}`);
            }));
          } else if (plugin.source === "brat" && plugin.repo) {
            setting.addButton((btn) => btn.setButtonText("GitHub").onClick(() => {
              window.open(`https://github.com/${plugin.repo}`);
            }));
          }
        }
      }
    }
    const toolbarDiv = containerEl.createDiv({
      attr: { style: "margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--background-modifier-border);" }
    });
    new import_obsidian12.Setting(toolbarDiv).setName("Enable Editing Toolbar").setDesc("Show the visual editing toolbar for formatting text").addToggle((toggle) => toggle.setValue(this.state.enableEditingToolbar).onChange((value) => {
      this.state.enableEditingToolbar = value;
    }));
  }
  renderPluginStatus(container, plugin, plugins) {
    var _a, _b, _c, _d, _e;
    const pluginInstance = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a[plugin.id];
    const isInstalled = !!pluginInstance;
    const pluginInstanceTyped = pluginInstance;
    const isCurrentlyEnabled = (_e = (_d = (_c = (_b = plugins == null ? void 0 : plugins.enabledPlugins) == null ? void 0 : _b.has) == null ? void 0 : _c.call(_b, plugin.id)) != null ? _d : pluginInstanceTyped == null ? void 0 : pluginInstanceTyped.enabled) != null ? _e : false;
    if (isInstalled && isCurrentlyEnabled) {
      if (!this.state.enabledPlugins.includes(plugin.id)) {
        this.state.enabledPlugins.push(plugin.id);
      }
      this.state.disabledPlugins = this.state.disabledPlugins.filter((p) => p !== plugin.id);
    } else if (isInstalled && !isCurrentlyEnabled) {
      this.state.enabledPlugins = this.state.enabledPlugins.filter((p) => p !== plugin.id);
      if (!this.state.disabledPlugins.includes(plugin.id)) {
        this.state.disabledPlugins.push(plugin.id);
      }
    }
    const setting = new import_obsidian12.Setting(container).setName(plugin.name).setDesc(isCurrentlyEnabled ? "Installed and enabled" : "Installed but disabled");
    setting.nameEl.style.fontSize = "0.9em";
    setting.descEl.style.fontSize = "0.8em";
    const iconContainer = setting.controlEl.createDiv({ cls: "vault-cms-plugin-status" });
    if (isCurrentlyEnabled) {
      (0, import_obsidian12.setIcon)(iconContainer, "lucide-check-circle-2");
      setCssProps6(iconContainer, { color: "var(--text-success)" });
    } else {
      (0, import_obsidian12.setIcon)(iconContainer, "lucide-x-circle");
      setCssProps6(iconContainer, { color: "var(--text-error)" });
    }
  }
  validate() {
    return true;
  }
  getTitle() {
    return "Optional Plugins";
  }
  getDescription() {
    return "Configure optional plugins and detection";
  }
};

// src/ui/wizard/IgnoreStep.ts
var import_obsidian14 = require("obsidian");

// src/utils/ProjectOptimizer.ts
var import_obsidian13 = require("obsidian");
var path8 = __toESM(require("path"), 1);
var fs5 = __toESM(require("fs"), 1);
init_VaultPathHelper();
init_ProjectRootResolver();
function setCssProps7(element, props) {
  for (const [key, value] of Object.entries(props)) {
    element.style.setProperty(key.replace(/([A-Z])/g, "-$1").toLowerCase(), value);
  }
}
var ProjectOptimizer = class {
  constructor(app, state) {
    this.app = app;
    this.state = state;
  }
  resolveProjectRoot() {
    var _a;
    const vaultPath = getVaultPath(this.app);
    return resolveProjectRootFromVaultPath(vaultPath != null ? vaultPath : "", (_a = this.state.projectDetection) == null ? void 0 : _a.projectRoot);
  }
  async getStatus() {
    var _a;
    const status = {
      gitIgnoreStatus: "not-configured",
      viteIgnoreStatus: "not-configured",
      gitHooksStatus: "none"
    };
    const projectRoot = this.resolveProjectRoot();
    if (!projectRoot) {
      console.debug("[Vault CMS] ProjectOptimizer: No projectRoot in state");
      return status;
    }
    const configDir = this.app.vault.configDir;
    console.debug("[Vault CMS] ProjectOptimizer: Checking status for root:", projectRoot, "configDir:", configDir);
    const gitIgnorePath = path8.join(projectRoot, ".gitignore");
    if (fs5.existsSync(gitIgnorePath)) {
      const content = fs5.readFileSync(gitIgnorePath, "utf8");
      const isConfigured = content.includes(`${configDir}/workspace.json`) || content.includes(`**/${configDir}/workspace.json`);
      console.debug("[Vault CMS] ProjectOptimizer: .gitignore exists, configured:", isConfigured);
      if (isConfigured) {
        status.gitIgnoreStatus = "configured";
      }
    } else {
      console.debug("[Vault CMS] ProjectOptimizer: .gitignore NOT found at:", gitIgnorePath);
    }
    const astroConfigNames = ["astro.config.ts", "astro.config.mjs", "astro.config.js", "astro.config.mts", "astro.config.cjs"];
    let resolvedViteConfigPath = "";
    for (const name of astroConfigNames) {
      const p = path8.join(projectRoot, name);
      if (fs5.existsSync(p)) {
        resolvedViteConfigPath = p;
        break;
      }
    }
    if (!resolvedViteConfigPath && ((_a = this.state.projectDetection) == null ? void 0 : _a.configFilePath)) {
      const adapter = this.app.vault.adapter;
      const vaultPath = adapter.basePath || adapter.path || "";
      resolvedViteConfigPath = path8.resolve(vaultPath, this.state.projectDetection.configFilePath);
    }
    if (resolvedViteConfigPath && fs5.existsSync(resolvedViteConfigPath)) {
      console.debug("[Vault CMS] ProjectOptimizer: Checking Vite config at:", resolvedViteConfigPath);
      const content = fs5.readFileSync(resolvedViteConfigPath, "utf8");
      const hasWatchIgnored = content.includes("server.watch.ignored") || content.includes("ignored:");
      const hasAssetsInclude = content.includes("assetsInclude:");
      const hasConfigDir = content.includes(configDir);
      const hasBasesPattern = content.includes("bases") || content.includes("home") || content.includes("base");
      console.debug("[Vault CMS] ProjectOptimizer: Vite config has patterns:", { hasWatchIgnored, hasAssetsInclude, hasConfigDir, hasBasesPattern });
      if (hasWatchIgnored && hasAssetsInclude && (hasConfigDir || hasBasesPattern)) {
        status.viteIgnoreStatus = "configured";
      }
    } else {
      console.debug("[Vault CMS] ProjectOptimizer: No valid Astro config found to check");
    }
    status.gitHooksStatus = this.detectGitHooks(projectRoot);
    return status;
  }
  /**
   * Detects developer git hooks that would interfere with Obsidian-based publishing.
   * Checks for: husky, simple-git-hooks, lefthook, lint-staged, commitlint.
   */
  detectGitHooks(projectRoot) {
    const huskyPreCommit = path8.join(projectRoot, ".husky", "pre-commit");
    const huskyCommitMsg = path8.join(projectRoot, ".husky", "commit-msg");
    const lefthookYml = path8.join(projectRoot, "lefthook.yml");
    const simpleGitHooksInPkg = this.packageJsonHasHookTools(projectRoot);
    const hasHooks = fs5.existsSync(huskyPreCommit) || fs5.existsSync(huskyCommitMsg) || fs5.existsSync(lefthookYml) || simpleGitHooksInPkg;
    if (!hasHooks) return "none";
    const isNeutralized = this.isHookNeutralized(huskyPreCommit) && this.isHookNeutralized(huskyCommitMsg);
    if (isNeutralized && !fs5.existsSync(lefthookYml) && !simpleGitHooksInPkg) return "neutralized";
    return "detected";
  }
  isHookNeutralized(hookPath) {
    if (!fs5.existsSync(hookPath)) return true;
    const content = fs5.readFileSync(hookPath, "utf8").trim();
    return content === "exit 0" || content === "" || content === "#!/bin/sh\nexit 0";
  }
  packageJsonHasHookTools(projectRoot) {
    const pkgPath = path8.join(projectRoot, "package.json");
    if (!fs5.existsSync(pkgPath)) return false;
    try {
      const pkg = JSON.parse(fs5.readFileSync(pkgPath, "utf8"));
      const scripts = pkg.scripts || {};
      const prepare = scripts.prepare || "";
      return /husky|simple-git-hooks|lefthook/.test(prepare);
    } catch (e) {
      return false;
    }
  }
  /**
   * Neutralizes git hooks so they don't block Obsidian-based publishing.
   * - Replaces husky hook scripts with "exit 0"
   * - Removes the "prepare" script from package.json if it references hook tools
   */
  neutralizeGitHooks() {
    var _a;
    const projectRoot = this.resolveProjectRoot();
    if (!projectRoot) return false;
    let changed = false;
    const huskyDir = path8.join(projectRoot, ".husky");
    if (fs5.existsSync(huskyDir)) {
      for (const hookName of ["pre-commit", "commit-msg", "pre-push"]) {
        const hookPath = path8.join(huskyDir, hookName);
        if (fs5.existsSync(hookPath) && !this.isHookNeutralized(hookPath)) {
          fs5.writeFileSync(hookPath, "exit 0", "utf8");
          changed = true;
        }
      }
    }
    const pkgPath = path8.join(projectRoot, "package.json");
    if (fs5.existsSync(pkgPath)) {
      try {
        const pkgContent = fs5.readFileSync(pkgPath, "utf8");
        const pkg = JSON.parse(pkgContent);
        if (((_a = pkg.scripts) == null ? void 0 : _a.prepare) && /husky|simple-git-hooks|lefthook/.test(pkg.scripts.prepare)) {
          delete pkg.scripts.prepare;
          fs5.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
          changed = true;
        }
      } catch (e) {
        console.error("[Vault CMS] Failed to patch package.json:", e);
      }
    }
    const lefthookPath = path8.join(projectRoot, "lefthook.yml");
    if (fs5.existsSync(lefthookPath)) {
      try {
        fs5.unlinkSync(lefthookPath);
        changed = true;
      } catch (e) {
        console.error("[Vault CMS] Failed to remove lefthook.yml:", e);
      }
    }
    return changed;
  }
  async configureGitIgnore() {
    const projectRoot = this.resolveProjectRoot();
    if (!projectRoot) {
      console.error("[Vault CMS] ProjectOptimizer: No projectRoot for Git configuration");
      return false;
    }
    const configDir = this.app.vault.configDir;
    const gitIgnorePath = path8.join(projectRoot, ".gitignore");
    const rules = `
# Obsidian workspace files
**/${configDir}/workspace.json
**/${configDir}/workspace-mobile.json
`;
    console.debug("[Vault CMS] ProjectOptimizer: Configuring Git ignore at:", gitIgnorePath);
    try {
      if (fs5.existsSync(gitIgnorePath)) {
        let content = fs5.readFileSync(gitIgnorePath, "utf8");
        const hasNewPattern = content.includes(`**/${configDir}/workspace.json`);
        const hasOldPattern = content.includes(`*/${configDir}/workspace.json`) || content.includes(`${configDir}/workspace.json`);
        if (hasOldPattern && !hasNewPattern) {
          console.debug("[Vault CMS] ProjectOptimizer: Updating old Git patterns");
          content = content.replace(new RegExp(`\\*?/?${configDir}/workspace\\.json`, "g"), `**/${configDir}/workspace.json`);
          content = content.replace(new RegExp(`\\*?/?${configDir}/workspace-mobile\\.json`, "g"), `**/${configDir}/workspace-mobile.json`);
          fs5.writeFileSync(gitIgnorePath, content, "utf8");
        } else if (!hasNewPattern) {
          console.debug("[Vault CMS] ProjectOptimizer: Adding new Git patterns");
          content += rules;
          fs5.writeFileSync(gitIgnorePath, content, "utf8");
        } else {
          console.debug("[Vault CMS] ProjectOptimizer: Git patterns already present");
        }
      } else {
        console.debug("[Vault CMS] ProjectOptimizer: Creating new .gitignore");
        fs5.writeFileSync(gitIgnorePath, rules, "utf8");
      }
      return true;
    } catch (error) {
      console.error("[Vault CMS] Failed to update .gitignore:", error);
      throw error;
    }
  }
  async configureViteIgnore() {
    var _a;
    const projectRoot = this.resolveProjectRoot();
    if (!projectRoot) return false;
    const configDir = this.app.vault.configDir;
    const astroConfigNames = ["astro.config.ts", "astro.config.mjs", "astro.config.js", "astro.config.mts", "astro.config.cjs"];
    let resolvedConfigPath = "";
    let configFileName = "";
    for (const name of astroConfigNames) {
      const p = path8.join(projectRoot, name);
      if (fs5.existsSync(p)) {
        resolvedConfigPath = p;
        configFileName = name;
        break;
      }
    }
    if (!resolvedConfigPath && ((_a = this.state.projectDetection) == null ? void 0 : _a.configFilePath)) {
      const adapter = this.app.vault.adapter;
      const vaultPath = adapter.basePath || adapter.path || "";
      resolvedConfigPath = path8.resolve(vaultPath, this.state.projectDetection.configFilePath);
      configFileName = path8.basename(resolvedConfigPath);
    }
    if (!resolvedConfigPath || !fs5.existsSync(resolvedConfigPath)) {
      console.error("[Vault CMS] ProjectOptimizer: Vite config NOT found in:", projectRoot);
      throw new Error(`Astro config file not found in: ${projectRoot}`);
    }
    console.debug("[Vault CMS] ProjectOptimizer: Configuring Vite ignore at:", resolvedConfigPath);
    try {
      const content = fs5.readFileSync(resolvedConfigPath, "utf8");
      if (content.includes("server.watch.ignored") && content.includes(configDir)) {
        return true;
      }
      const exportIdx = content.lastIndexOf("export default");
      let startIndex = -1;
      let endIndex = -1;
      let configBody = "";
      let isWholeFile = false;
      if (exportIdx !== -1) {
        startIndex = content.indexOf("{", exportIdx);
        if (startIndex !== -1) {
          let braceCount = 0;
          for (let i = startIndex; i < content.length; i++) {
            if (content[i] === "{") braceCount++;
            else if (content[i] === "}") braceCount--;
            if (braceCount === 0) {
              endIndex = i;
              break;
            }
          }
          if (endIndex !== -1) {
            configBody = content.substring(startIndex + 1, endIndex);
          }
        }
      }
      if (!configBody && (content.includes("vite:") || content.includes("server:"))) {
        configBody = content;
        isWholeFile = true;
      }
      if (configBody) {
        if (configBody.includes("vite:")) {
          if (!configBody.includes("assetsInclude:")) {
            configBody = configBody.replace(/vite:\s*\{/, `vite: {
    assetsInclude: ['**/*.base', '**/.obsidian/**', '**/_bases/**'],`);
          }
          if (configBody.includes("server:")) {
            if (configBody.includes("watch:")) {
              if (configBody.includes("ignored:")) {
                if (!configBody.includes(configDir)) {
                  const ignorePatterns = `'**/${configDir}/**', '**/_bases/**', '**/bases/**', '**/_home/**', '**/home/**', '**/_base/**', '**/base/**'`;
                  configBody = configBody.replace(/ignored:\s*\[([^\]]*)\]/, (_m, p1) => {
                    const existing = p1.trim();
                    const separator = existing ? ", " : "";
                    return `ignored: [${existing}${separator}${ignorePatterns}]`;
                  });
                }
              } else {
                configBody = configBody.replace(/watch:\s*\{/, `watch: {
      ignored: ['**/${configDir}/**', '**/_bases/**', '**/bases/**', '**/_home/**', '**/home/**', '**/_base/**', '**/base/**'],`);
              }
            } else {
              configBody = configBody.replace(/server:\s*\{/, `server: {
    watch: {
      ignored: ['**/${configDir}/**', '**/_bases/**', '**/bases/**', '**/_home/**', '**/home/**', '**/_base/**', '**/base/**']
    },`);
            }
          } else {
            configBody = configBody.replace(/vite:\s*\{/, `vite: {
    server: {
      watch: {
        ignored: ['**/${configDir}/**', '**/_bases/**', '**/bases/**', '**/_home/**', '**/home/**', '**/_base/**', '**/base/**']
      }
    },`);
          }
        } else {
          if (isWholeFile) {
            if (content.includes("defineConfig")) {
              configBody = configBody.replace(/defineConfig\s*\(\s*\{/, `defineConfig({
  vite: {
    assetsInclude: ['**/*.base', '**/.obsidian/**', '**/_bases/**'],
    server: {
      watch: {
        ignored: ['**/${configDir}/**', '**/_bases/**', '**/bases/**', '**/_home/**', '**/home/**', '**/_base/**', '**/base/**']
      }
    }
  },`);
            } else {
              throw new Error(`Could not find a clear place to insert Vite config in ${configFileName}.`);
            }
          } else {
            configBody = `
  vite: {
    assetsInclude: ['**/*.base', '**/.obsidian/**', '**/_bases/**'],
    server: {
      watch: {
        ignored: ['**/${configDir}/**', '**/_bases/**', '**/bases/**', '**/_home/**', '**/home/**', '**/_base/**', '**/base/**']
      }
    }
  },` + configBody;
          }
        }
        const updatedContent = isWholeFile ? configBody : content.substring(0, startIndex + 1) + configBody + content.substring(endIndex);
        fs5.writeFileSync(resolvedConfigPath, updatedContent, "utf8");
        return true;
      } else {
        throw new Error(`Could not parse configuration in ${configFileName}.`);
      }
    } catch (error) {
      console.error(`ProjectOptimizer: Error updating ${configFileName}:`, error);
      throw error;
    }
  }
  renderStatus(container, status) {
    const statusEl = container.createDiv({ cls: "vault-cms-plugin-status" });
    if (status === "configured") {
      (0, import_obsidian13.setIcon)(statusEl, "lucide-check-circle-2");
      setCssProps7(statusEl, { color: "var(--text-success)" });
    } else {
      (0, import_obsidian13.setIcon)(statusEl, "lucide-alert-circle");
      setCssProps7(statusEl, { color: "var(--text-warning)" });
    }
  }
};

// src/ui/wizard/IgnoreStep.ts
var IgnoreStep = class extends BaseWizardStep {
  constructor(app, containerEl, state, onNext, onBack, onCancel) {
    super(app, containerEl, state, onNext, onBack, onCancel);
    this.optimizer = new ProjectOptimizer(app, state);
  }
  async display() {
    const { containerEl } = this;
    containerEl.empty();
    const status = await this.optimizer.getStatus();
    this.state.ignoreConfig.gitIgnoreConfigured = status.gitIgnoreStatus === "configured";
    this.state.ignoreConfig.viteIgnoreConfigured = status.viteIgnoreStatus === "configured";
    containerEl.createEl("h2", { text: "Project optimization (optional)" });
    containerEl.createEl("p", {
      text: "Optimize your project by ignoring Obsidian-specific files in Git and Vite."
    });
    this.gitSetting = new import_obsidian14.Setting(containerEl);
    this.updateGitSetting(status.gitIgnoreStatus);
    this.viteSetting = new import_obsidian14.Setting(containerEl);
    this.updateViteSetting(status.viteIgnoreStatus);
    if (status.gitHooksStatus !== "none") {
      this.hooksSetting = new import_obsidian14.Setting(containerEl);
      this.updateHooksSetting(status.gitHooksStatus);
    }
    return Promise.resolve();
  }
  updateGitSetting(status) {
    this.gitSetting.setName("Ignore workspace files in Git").setDesc("Add Obsidian workspace files to .gitignore to prevent them from being tracked.").clear();
    this.gitSetting.addButton((button) => {
      button.setButtonText(status === "configured" ? "Re-configure" : "Configure").onClick(async () => {
        try {
          await this.optimizer.configureGitIgnore();
          this.state.ignoreConfig.gitIgnoreConfigured = true;
          new import_obsidian14.Notice(".gitignore updated");
          const newStatus = await this.optimizer.getStatus();
          this.updateGitSetting(newStatus.gitIgnoreStatus);
        } catch (error) {
          new import_obsidian14.Notice(`Failed to update .gitignore: ${error instanceof Error ? error.message : String(error)}`);
        }
      });
    });
    this.optimizer.renderStatus(this.gitSetting.controlEl, status);
  }
  updateViteSetting(status) {
    this.viteSetting.setName("Ignore workspace and Home Base folders in Vite").setDesc("Configure Vite to ignore Obsidian and Home Base folders.").clear();
    this.viteSetting.addButton((button) => {
      button.setButtonText(status === "configured" ? "Re-configure" : "Configure").onClick(async () => {
        try {
          await this.optimizer.configureViteIgnore();
          this.state.ignoreConfig.viteIgnoreConfigured = true;
          new import_obsidian14.Notice("Vite optimization applied");
          const newStatus = await this.optimizer.getStatus();
          this.updateViteSetting(newStatus.viteIgnoreStatus);
        } catch (error) {
          new import_obsidian14.Notice(`Failed to update Vite config: ${error instanceof Error ? error.message : String(error)}`);
        }
      });
    });
    this.optimizer.renderStatus(this.viteSetting.controlEl, status);
  }
  updateHooksSetting(status) {
    this.hooksSetting.setName("Neutralize developer git hooks").setDesc("This project has git hooks (like husky or commitlint) that can block publishing from Obsidian. Disable so commits can happen easily from Obsidian.").clear();
    if (status === "detected") {
      this.hooksSetting.addButton((button) => {
        button.setButtonText("Neutralize").setCta().onClick(async () => {
          try {
            this.optimizer.neutralizeGitHooks();
            new import_obsidian14.Notice("Git hooks neutralized");
            const newStatus = await this.optimizer.getStatus();
            this.updateHooksSetting(newStatus.gitHooksStatus);
          } catch (error) {
            new import_obsidian14.Notice(`Failed to neutralize git hooks: ${error instanceof Error ? error.message : String(error)}`);
          }
        });
      });
    }
    this.optimizer.renderStatus(this.hooksSetting.controlEl, status === "neutralized" ? "configured" : "not-configured");
  }
  validate() {
    return true;
  }
  getTitle() {
    return "Project optimization (optional)";
  }
  getDescription() {
    return "Configure project-level ignores";
  }
};

// src/ui/wizard/GitSetupStep.ts
var import_obsidian21 = require("obsidian");
init_GitManager();

// src/utils/BasesCMSConfig.ts
var import_obsidian16 = require("obsidian");
var BasesCMSConfigurator = class {
  constructor(app) {
    this.app = app;
    this.pathResolver = new PathResolver(app);
  }
  async resolveBaseFilePath() {
    const candidateFolders = ["_bases", "bases", "_home", "home", "_base", "base"];
    const candidateFiles = ["Home.base", "home.base", "index.base"];
    for (const folder of candidateFolders) {
      for (const file of candidateFiles) {
        const fullPath = `${folder}/${file}`;
        if (await this.app.vault.adapter.exists(fullPath)) {
          return fullPath;
        }
      }
    }
    for (const folder of candidateFolders) {
      if (await this.app.vault.adapter.exists(folder)) {
        return `${folder}/Home.base`;
      }
    }
    return "_bases/Home.base";
  }
  async createOrUpdateBaseFile(contentTypes, frontmatterProperties, defaultContentTypeId, projectDetection, enableMdxSupport) {
    const baseFilePath = await this.resolveBaseFilePath();
    const folderPath = baseFilePath.split("/")[0];
    const basesFolder = this.app.vault.getAbstractFileByPath(folderPath);
    if (!basesFolder) {
      try {
        await this.app.vault.createFolder(folderPath);
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        if (!errorMessage || !errorMessage.includes("already exists")) {
          console.warn(`BasesCMSConfig: Could not create ${folderPath} folder:`, error);
        }
      }
    }
    const baseFileAbstract = this.app.vault.getAbstractFileByPath(baseFilePath);
    let baseFile = baseFileAbstract instanceof import_obsidian16.TFile ? baseFileAbstract : null;
    let existingBase = null;
    if (baseFile) {
      try {
        const content = await this.app.vault.read(baseFile);
        existingBase = parse2(content);
      } catch (error) {
        console.error("BasesCMSConfig: Failed to parse existing base file:", error);
      }
    }
    const enabledTypes = contentTypes.filter((ct) => ct.enabled);
    console.debug("BasesCMSConfig: Generating base content for", contentTypes.length, "content types");
    console.debug("BasesCMSConfig: Enabled content types:", enabledTypes.map((ct) => ct.name));
    const baseContent = this.generateBaseContent(contentTypes, frontmatterProperties, defaultContentTypeId, existingBase, projectDetection, enableMdxSupport);
    const viewMatches = baseContent.match(/^\s*-\s+type:\s+(?:cms|bases-cms)/gm);
    const viewCount = viewMatches ? viewMatches.length : 0;
    console.debug("BasesCMSConfig: Generated", viewCount, "views in base content");
    const baseFileAbstract2 = this.app.vault.getAbstractFileByPath(baseFilePath);
    baseFile = baseFileAbstract2 instanceof import_obsidian16.TFile ? baseFileAbstract2 : null;
    if (baseFile) {
      console.debug(`BasesCMSConfig: Modifying existing ${baseFilePath} file`);
      try {
        await this.app.vault.modify(baseFile, baseContent);
        console.debug(`BasesCMSConfig: Successfully modified ${baseFilePath} file`);
        return;
      } catch (error) {
        console.error("BasesCMSConfig: Failed to modify file:", error);
        throw error;
      }
    }
    console.debug(`BasesCMSConfig: Creating new ${baseFilePath} file`);
    try {
      await this.app.vault.create(baseFilePath, baseContent);
      console.debug(`BasesCMSConfig: Successfully created ${baseFilePath} file`);
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      if (errorMessage && (errorMessage.includes("already exists") || errorMessage.includes("File already exists"))) {
        console.debug("BasesCMSConfig: File existed, attempting direct modify via path");
        try {
          const adapter = this.app.vault.adapter;
          if (adapter && typeof adapter.write === "function") {
            await adapter.write(baseFilePath, baseContent);
            console.debug("BasesCMSConfig: Successfully wrote Home.base file via adapter");
          } else {
            console.debug("BasesCMSConfig: Adapter write not available, retrying getAbstractFileByPath");
            for (let i = 0; i < 10; i++) {
              await new Promise((resolve11) => setTimeout(resolve11, 200));
              const retryFileAbstract = this.app.vault.getAbstractFileByPath(baseFilePath);
              const retryFile = retryFileAbstract instanceof import_obsidian16.TFile ? retryFileAbstract : null;
              if (retryFile) {
                await this.app.vault.modify(retryFile, baseContent);
                console.debug(`BasesCMSConfig: Successfully modified Home.base file on retry ${i + 1}`);
                return;
              }
            }
            console.error("BasesCMSConfig: File exists but cannot be found after all retries");
            throw new Error(`File exists but cannot be accessed. Please try again or manually edit ${baseFilePath}`);
          }
        } catch (writeError) {
          console.error("BasesCMSConfig: Failed to write file via adapter:", writeError);
          throw writeError;
        }
      } else {
        console.error("BasesCMSConfig: Failed to create base file:", error);
        throw error;
      }
    }
  }
  generateBaseContent(contentTypes, frontmatterProperties, defaultContentTypeId, existingBase, projectDetection, enableMdxSupport) {
    const lines = [];
    const defaultContentType = defaultContentTypeId ? contentTypes.find((ct) => ct.id === defaultContentTypeId && ct.enabled) : null;
    if (defaultContentType) {
      lines.push(`defaultView: "${defaultContentType.name}"`);
    }
    if (existingBase == null ? void 0 : existingBase.formulas) {
      lines.push("formulas:");
      for (const [key, value] of Object.entries(existingBase.formulas)) {
        if (typeof value === "string") {
          lines.push(`  ${key}: |-`);
          const formulaLines = value.split("\n");
          for (const formulaLine of formulaLines) {
            lines.push(`    ${formulaLine}`);
          }
        }
      }
      lines.push("");
    }
    lines.push("filters:");
    if (enableMdxSupport) {
      lines.push("  or:");
      lines.push('    - file.ext == "md"');
      lines.push('    - file.ext == "mdx"');
    } else {
      lines.push("  and:");
      lines.push('    - file.ext == "md"');
    }
    lines.push("");
    const allProperties = /* @__PURE__ */ new Set();
    for (const contentType of contentTypes) {
      const props = frontmatterProperties[contentType.id];
      if (props) {
        if (props.titleProperty) allProperties.add(`note.${props.titleProperty}`);
        if (props.dateProperty) allProperties.add(`note.${props.dateProperty}`);
        if (props.descriptionProperty) allProperties.add(`note.${props.descriptionProperty}`);
        if (props.tagsProperty) allProperties.add(`note.${props.tagsProperty}`);
        if (props.draftProperty) allProperties.add(`note.${props.draftProperty}`);
        if (props.imageProperty) allProperties.add(`note.${props.imageProperty}`);
      }
    }
    allProperties.add("note.title");
    allProperties.add("note.date");
    allProperties.add("note.pubDate");
    allProperties.add("note.draft");
    allProperties.add("file.fullname");
    allProperties.add("file.name");
    if (existingBase == null ? void 0 : existingBase.properties) {
      for (const prop of Object.keys(existingBase.properties)) {
        if (prop.startsWith("formula.")) {
          allProperties.add(prop);
        }
      }
    }
    if (allProperties.size > 0) {
      lines.push("properties:");
      const existingProps = (existingBase == null ? void 0 : existingBase.properties) || {};
      for (const prop of Array.from(allProperties).sort()) {
        lines.push(`  ${prop}:`);
        const existingProp = existingProps[prop];
        if (existingProp == null ? void 0 : existingProp.displayName) {
          lines.push(`    displayName: ${existingProp.displayName}`);
        } else if (prop === "file.fullname") {
          lines.push(`    displayName: Full File Name`);
        } else {
          const propName = prop.replace("note.", "").replace("file.", "");
          lines.push(`    displayName: ${this.capitalizeFirst(propName)}`);
        }
      }
      lines.push("");
    }
    lines.push("views:");
    const existingViews = (existingBase == null ? void 0 : existingBase.views) || [];
    const viewsByName = /* @__PURE__ */ new Map();
    for (const view of existingViews) {
      if (view.name) viewsByName.set(view.name, view);
    }
    const finalViews = [];
    const processedViewNames = /* @__PURE__ */ new Set();
    const enabledTypes = contentTypes.filter((ct) => ct.enabled);
    const defaultType = defaultContentTypeId ? enabledTypes.find((ct) => ct.id === defaultContentTypeId) : null;
    const otherTypes = enabledTypes.filter((ct) => ct !== defaultType);
    const processType = (ct) => {
      const props = frontmatterProperties[ct.id];
      if (!props) return;
      const existingView = viewsByName.get(ct.name);
      if (existingView) {
        finalViews.push(existingView);
        processedViewNames.add(ct.name);
      } else {
        const generatedView = this.generateViewForContentType(ct, props, projectDetection);
        finalViews.push(generatedView);
        processedViewNames.add(ct.name);
      }
    };
    if (defaultType) processType(defaultType);
    for (const ct of otherTypes) processType(ct);
    for (const view of existingViews) {
      if (view.name === "Vault CMS Guide" || view.name === "Guide" || processedViewNames.has(view.name)) continue;
      finalViews.push(view);
    }
    let guideView = viewsByName.get("Vault CMS Guide") || viewsByName.get("Guide");
    if (guideView) {
      guideView = { ...guideView, name: "Vault CMS Guide" };
      finalViews.push(guideView);
    }
    for (const view of finalViews) {
      lines.push(...this.serializeView(view));
    }
    return lines.join("\n");
  }
  generateViewForContentType(contentType, props, projectDetection) {
    const folderPath = this.pathResolver.getBasesCMSFolderPath(contentType.folder, projectDetection);
    const view = {
      type: "cms",
      name: contentType.name,
      filters: {
        and: [
          folderPath === "" || folderPath === "." ? 'file.folder == "/"' : `file.folder.startsWith("${folderPath}")`
        ]
      },
      imageFormat: "cover",
      showDate: true,
      customizeNewButton: true,
      newNoteLocation: folderPath,
      fallbackToEmbeds: "if-empty",
      propertyDisplay1: "file.fullname",
      showTextPreview: true,
      propertyLabels: "above",
      sort: [
        {
          property: props.dateProperty ? `note.${props.dateProperty}` : "file.ctime",
          direction: "DESC"
        }
      ]
    };
    if (props.titleProperty) {
      view.titleProperty = `note.${props.titleProperty}`;
    } else {
      view.titleProperty = `file.fullname`;
    }
    if (props.dateProperty) {
      view.dateProperty = `note.${props.dateProperty}`;
    } else {
      view.dateProperty = `file.ctime`;
    }
    if (props.descriptionProperty) {
      view.descriptionProperty = `note.${props.descriptionProperty}`;
    }
    if (props.imageProperty) {
      view.imageProperty = `note.${props.imageProperty}`;
    }
    view.showTags = !!props.tagsProperty;
    if (props.tagsProperty) {
      view.tagsProperty = `note.${props.tagsProperty}`;
    }
    view.showDraftStatus = !!props.hasDraftStatus;
    if (props.hasDraftStatus) {
      if (props.draftProperty) {
        view.draftStatusProperty = `note.${props.draftProperty}`;
        view.draftStatusReverse = props.draftLogic === "false-draft";
      } else {
        view.draftStatusUseFilenamePrefix = true;
      }
    }
    return view;
  }
  capitalizeFirst(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }
  /**
   * Serialize a view object to YAML lines (with proper indentation)
   */
  serializeView(view) {
    const viewLines = [];
    viewLines.push("  - type: cms");
    viewLines.push(`    name: "${view.name}"`);
    if (view.filters) {
      viewLines.push("    filters:");
      if (view.filters.and) {
        if (view.filters.and.length === 0) {
          viewLines.push("      and: []");
        } else {
          viewLines.push("      and:");
          for (const filter of view.filters.and) {
            if (typeof filter === "string") {
              viewLines.push(`        - ${filter}`);
            } else if (typeof filter === "object") {
              for (const [key, value] of Object.entries(filter)) {
                const valueStr = typeof value === "string" ? `"${value}"` : String(value);
                viewLines.push(`        - ${key}: ${valueStr}`);
              }
            }
          }
        }
      }
    }
    if (view.groupBy) {
      viewLines.push("    groupBy:");
      if (typeof view.groupBy === "object") {
        if (view.groupBy.property) viewLines.push(`      property: ${view.groupBy.property}`);
        if (view.groupBy.direction) viewLines.push(`      direction: ${view.groupBy.direction}`);
      } else if (typeof view.groupBy === "string") {
        viewLines.push(`      ${view.groupBy}`);
      }
    }
    if (view.order) {
      if (view.order.length === 0) {
        viewLines.push("    order: []");
      } else {
        viewLines.push("    order:");
        for (const orderItem of view.order) {
          viewLines.push(`      - ${orderItem}`);
        }
      }
    }
    if (view.sort) {
      if (view.sort.length === 0) {
        viewLines.push("    sort: []");
      } else {
        viewLines.push("    sort:");
        for (const sortItem of view.sort) {
          if (typeof sortItem === "object" && sortItem.property) {
            viewLines.push(`      - property: ${sortItem.property}`);
            viewLines.push(`        direction: ${sortItem.direction || "ASC"}`);
          }
        }
      }
    }
    const skipProps = ["type", "name", "filters", "groupBy", "order", "sort"];
    for (const prop of Object.keys(view)) {
      if (skipProps.includes(prop) || view[prop] === void 0) {
        continue;
      }
      const value = view[prop];
      if (value === null) {
        viewLines.push(`    ${prop}: null`);
      } else if (typeof value === "boolean") {
        viewLines.push(`    ${prop}: ${value}`);
      } else if (typeof value === "number") {
        viewLines.push(`    ${prop}: ${value}`);
      } else if (typeof value === "string") {
        if (value === "") {
          viewLines.push(`    ${prop}: ""`);
          continue;
        }
        const isPropertyRef = (prop.includes("Property") || prop.startsWith("propertyDisplay")) && (value.startsWith("note.") || value.startsWith("file."));
        if (isPropertyRef) {
          viewLines.push(`    ${prop}: ${value}`);
        } else if (prop === "newNoteLocation") {
          viewLines.push(`    ${prop}: "${value}"`);
        } else {
          viewLines.push(`    ${prop}: "${value}"`);
        }
      }
    }
    return viewLines;
  }
};

// src/utils/SEOConfig.ts
var SEOConfigurator = class {
  constructor(app) {
    this.app = app;
    this.pathResolver = new PathResolver(app);
    this.safeWriter = new SafeConfigWriter(app);
  }
  generateSEOConfig(contentTypes, frontmatterProperties, projectDetection, enableMdxSupport, defaultContentTypeId) {
    const defaultType = defaultContentTypeId ? contentTypes.find((ct) => ct.id === defaultContentTypeId && ct.enabled) : void 0;
    const firstType = defaultType || contentTypes.find((ct) => ct.enabled);
    const firstProps = firstType ? frontmatterProperties[firstType.id] : void 0;
    const scanDirectories = contentTypes.filter((ct) => ct.enabled).map((ct) => this.pathResolver.getFolderPathFromVaultRoot(ct.folder, projectDetection)).join(",");
    const config = {
      // Only set titleProperty if it exists (not blank) - this comes from the wizard
      titleProperty: (firstProps == null ? void 0 : firstProps.titleProperty) && firstProps.titleProperty.trim() !== "" ? firstProps.titleProperty : "title",
      // Default fallback
      // Only set descriptionProperty if it exists (not blank) - this comes from the wizard
      descriptionProperty: (firstProps == null ? void 0 : firstProps.descriptionProperty) && firstProps.descriptionProperty.trim() !== "" ? firstProps.descriptionProperty : void 0,
      scanDirectories,
      // Don't set these - we don't collect them in the wizard
      keywordProperty: void 0,
      useFilenameAsTitle: false,
      useFilenameAsSlug: true,
      enableMDXSupport: enableMdxSupport != null ? enableMdxSupport : false
    };
    return config;
  }
  async saveConfig(config) {
    var _a;
    try {
      const plugins = this.app.plugins;
      const seoPlugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a["seo"];
      if (seoPlugin && seoPlugin.settings) {
        const pluginSettings = seoPlugin.settings;
        if (config.scanDirectories) {
          pluginSettings.scanDirectories = config.scanDirectories;
        }
        if (config.titleProperty !== void 0) {
          pluginSettings.titleProperty = config.titleProperty;
        }
        if (config.descriptionProperty !== void 0) {
          pluginSettings.descriptionProperty = config.descriptionProperty;
        }
        if (config.enableMDXSupport !== void 0) {
          pluginSettings.enableMDXSupport = config.enableMDXSupport;
        }
        if (typeof seoPlugin.saveSettings === "function") {
          await seoPlugin.saveSettings();
          console.debug("SEOConfig: Successfully saved via plugin.saveSettings()");
          return;
        }
      }
      await this.saveConfigFallback(config);
    } catch (error) {
      console.error("Failed to save SEO config via plugin method:", error);
      await this.saveConfigFallback(config);
    }
  }
  async saveConfigFallback(config) {
    const pluginId = "seo";
    try {
      let existingData = await this.safeWriter.readConfig(pluginId);
      if (!existingData) {
        existingData = {};
      }
      const mergedData = {
        ...existingData,
        // Always update scanDirectories
        scanDirectories: config.scanDirectories,
        // Update titleProperty if provided (from wizard)
        ...config.titleProperty !== void 0 && { titleProperty: config.titleProperty },
        // Update descriptionProperty if provided (from wizard)
        ...config.descriptionProperty !== void 0 && { descriptionProperty: config.descriptionProperty },
        // Update enableMDXSupport if provided (from wizard)
        ...config.enableMDXSupport !== void 0 && { enableMDXSupport: config.enableMDXSupport }
        // All other properties (keywordProperty, useFilenameAsTitle, useFilenameAsSlug, etc.)
        // are preserved from existingData - we don't collect them in the wizard
      };
      const success = await this.safeWriter.writeConfig(pluginId, mergedData, {
        showNotice: true,
        createBackup: true
      });
      if (!success) {
        throw new Error("Failed to save SEO configuration");
      }
      console.debug("SEOConfig: Successfully saved SEO plugin configuration");
    } catch (error) {
      console.error("Failed to save SEO config (fallback):", error);
      throw error;
    }
  }
};

// src/utils/PropertyOverFileNameConfig.ts
var import_obsidian17 = require("obsidian");
var PropertyOverFileNameConfigurator = class {
  constructor(app) {
    this.app = app;
  }
  async saveConfig(config) {
    var _a;
    try {
      const plugins = this.app.plugins;
      const propertyOverFileNamePlugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a["property-over-file-name"];
      if (propertyOverFileNamePlugin && propertyOverFileNamePlugin.settings) {
        const pluginSettings = propertyOverFileNamePlugin.settings;
        console.debug("PropertyOverFileNameConfig: Using plugin.saveSettings() method");
        console.debug("PropertyOverFileNameConfig: Input config.enableMdxSupport =", config.enableMdxSupport);
        if (config.propertyKey) {
          pluginSettings.propertyKey = config.propertyKey;
        }
        if (config.enableMdxSupport !== void 0) {
          pluginSettings.enableMdxSupport = config.enableMdxSupport;
          console.debug("PropertyOverFileNameConfig: Set pluginSettings.enableMdxSupport to", config.enableMdxSupport);
        } else {
          console.warn("PropertyOverFileNameConfig: config.enableMdxSupport is undefined!");
        }
        if (typeof propertyOverFileNamePlugin.saveSettings === "function") {
          await propertyOverFileNamePlugin.saveSettings();
          console.debug("PropertyOverFileNameConfig: Successfully saved via plugin.saveSettings()");
          return;
        } else {
          console.warn("PropertyOverFileNameConfig: Plugin saveSettings not available, using fallback");
        }
      } else {
        console.warn("PropertyOverFileNameConfig: Plugin not found or settings not available, using fallback");
      }
      await this.saveConfigFallback(config);
    } catch (error) {
      console.error("Failed to save Property Over File Name config via plugin method:", error);
      await this.saveConfigFallback(config);
    }
  }
  async saveConfigFallback(config) {
    const pluginId = "property-over-file-name";
    const configDir = this.app.vault.configDir;
    const pluginDataPath = `${configDir}/plugins/${pluginId}/data.json`;
    try {
      let existingData = {};
      const dataFile = this.app.vault.getAbstractFileByPath(pluginDataPath);
      if (dataFile instanceof import_obsidian17.TFile) {
        existingData = JSON.parse(await this.app.vault.read(dataFile));
      }
      console.debug("PropertyOverFileNameConfig: Using fallback file method");
      console.debug("PropertyOverFileNameConfig: Input config =", JSON.stringify(config));
      console.debug("PropertyOverFileNameConfig: Input config.enableMdxSupport =", config.enableMdxSupport);
      console.debug("PropertyOverFileNameConfig: Existing data =", JSON.stringify(existingData));
      const mergedData = {
        ...existingData,
        ...config
      };
      if (config.enableMdxSupport !== void 0) {
        mergedData.enableMdxSupport = config.enableMdxSupport;
        console.debug("PropertyOverFileNameConfig: Explicitly set enableMdxSupport to", config.enableMdxSupport);
      } else {
        console.warn("PropertyOverFileNameConfig: config.enableMdxSupport is undefined!");
      }
      console.debug("PropertyOverFileNameConfig: Final mergedData.enableMdxSupport =", mergedData.enableMdxSupport);
      console.debug("PropertyOverFileNameConfig: Final mergedData =", JSON.stringify(mergedData));
      if (dataFile instanceof import_obsidian17.TFile) {
        await this.app.vault.modify(dataFile, JSON.stringify(mergedData, null, 2));
      } else {
        const pluginDir = `${configDir}/plugins/${pluginId}`;
        const pluginDirFile = this.app.vault.getAbstractFileByPath(pluginDir);
        if (!pluginDirFile) {
          try {
            await this.app.vault.createFolder(pluginDir);
          } catch (error) {
            if (error instanceof Error && !error.message.includes("already exists")) {
              throw error;
            }
          }
        }
        await this.app.vault.create(pluginDataPath, JSON.stringify(mergedData, null, 2));
      }
    } catch (error) {
      console.error("Failed to save Property Over File Name config (fallback):", error);
      throw error;
    }
  }
};

// src/utils/UITweakerConfig.ts
var import_obsidian18 = require("obsidian");
var UITweakerConfigurator = class {
  constructor(app) {
    this.app = app;
  }
  async saveConfig(enableMdxSupport) {
    var _a;
    const pluginId = "ui-tweaker";
    try {
      const plugins = this.app.plugins;
      const uiTweakerPlugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a[pluginId];
      if (uiTweakerPlugin && uiTweakerPlugin.settings) {
        console.debug("UITweakerConfig: Using plugin.settings API");
        const settings = uiTweakerPlugin.settings;
        this.forceMdxUpdate(settings, enableMdxSupport);
        if (typeof uiTweakerPlugin.saveSettings === "function") {
          await uiTweakerPlugin.saveSettings();
          console.debug("UITweakerConfig: Successfully saved via plugin.saveSettings()");
          return;
        }
      }
      console.debug("UITweakerConfig: Plugin API not available, using fallback file method");
      await this.saveConfigFallback(enableMdxSupport);
    } catch (error) {
      console.error("Failed to save UI Tweaker config:", error);
      await this.saveConfigFallback(enableMdxSupport);
    }
  }
  forceMdxUpdate(settings, enableMdxSupport) {
    const mdxFileTypes = enableMdxSupport ? "md,mdx" : "md";
    if (!settings.tabBarCommands || !Array.isArray(settings.tabBarCommands)) {
      settings.tabBarCommands = [];
    }
    const tabBarCommands = settings.tabBarCommands;
    const toolbarCommandIndex = tabBarCommands.findIndex((cmd) => cmd.id === "editing-toolbar:hide-show-menu");
    if (toolbarCommandIndex !== -1) {
      tabBarCommands[toolbarCommandIndex] = {
        ...tabBarCommands[toolbarCommandIndex],
        "showOnFileTypes": mdxFileTypes
      };
      console.debug(`UITweakerConfig: Updated existing toolbar command showOnFileTypes to ${mdxFileTypes}`);
    } else {
      tabBarCommands.push({
        "id": "editing-toolbar:hide-show-menu",
        "icon": "lucide-panel-top-open",
        "name": "Toggle editing toolbar",
        "displayName": "Editing Toolbar: Hide/Show ",
        "mode": "desktop",
        "toggleIcon": "lucide-panel-top-close",
        "showOnFileTypes": mdxFileTypes
      });
      console.debug(`UITweakerConfig: Added missing toolbar command with showOnFileTypes=${mdxFileTypes}`);
    }
  }
  async saveConfigFallback(enableMdxSupport) {
    const pluginId = "ui-tweaker";
    const configDir = this.app.vault.configDir;
    const pluginDataPath = `${configDir}/plugins/${pluginId}/data.json`;
    let existingData = {};
    const dataFile = this.app.vault.getAbstractFileByPath(pluginDataPath);
    if (dataFile instanceof import_obsidian18.TFile) {
      try {
        existingData = JSON.parse(await this.app.vault.read(dataFile));
      } catch (error) {
        console.warn("Failed to parse existing ui-tweaker data.json:", error);
      }
    }
    this.forceMdxUpdate(existingData, enableMdxSupport);
    const pluginDir = `${configDir}/plugins/${pluginId}`;
    const pluginDirFile = this.app.vault.getAbstractFileByPath(pluginDir);
    if (!pluginDirFile) {
      try {
        await this.app.vault.createFolder(pluginDir);
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        if (errorMessage && !errorMessage.includes("already exists") && !errorMessage.includes("File already exists") && !errorMessage.includes("Folder already exists")) {
          throw error;
        }
      }
    }
    const content = JSON.stringify(existingData, null, 2);
    if (dataFile instanceof import_obsidian18.TFile) {
      await this.app.vault.modify(dataFile, content);
    } else {
      await this.app.vault.create(pluginDataPath, content);
    }
    console.debug("UITweakerConfig: Successfully saved ui-tweaker config via fallback");
  }
};

// src/utils/DataFilesEditorConfig.ts
var import_obsidian19 = require("obsidian");
var DataFilesEditorConfigurator = class {
  constructor(app) {
    this.app = app;
  }
  async saveConfig(enabled) {
    var _a;
    const pluginId = "data-files-editor";
    try {
      const plugins = this.app.plugins;
      const plugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a[pluginId];
      if (plugin && plugin.settings) {
        console.debug("DataFilesEditorConfig: Using plugin.settings API");
        const settings = plugin.settings;
        this.applySettings(settings, enabled);
        if (typeof plugin.saveSettings === "function") {
          await plugin.saveSettings();
          console.debug("DataFilesEditorConfig: Successfully saved via plugin.saveSettings()");
          return;
        }
      }
      console.debug("DataFilesEditorConfig: Plugin API not available or settings not loaded, using fallback file method");
      await this.saveConfigFallback(enabled);
    } catch (error) {
      console.error("Failed to save Data Files Editor config:", error);
      await this.saveConfigFallback(enabled);
    }
  }
  applySettings(settings, enabled) {
    settings.doLoadJson = enabled;
    settings.doCreateJson = enabled;
    settings.doLoadAstro = enabled;
    settings.doCreateAstro = enabled;
    settings.doLoadTxt = false;
    settings.doCreateTxt = false;
    settings.doLoadXml = false;
    settings.doCreateXml = false;
    settings.doLoadYaml = false;
    settings.doCreateYaml = false;
    settings.doLoadTs = false;
    settings.doCreateTs = false;
    settings.doLoadCss = false;
    settings.doCreateCss = false;
    settings.doLoadHtml = false;
    settings.doCreateHtml = false;
    settings.doLoadJs = false;
    settings.doCreateJs = false;
    settings.doLoadMjs = false;
    settings.doCreateMjs = false;
    settings.doAutosaveFiles = true;
    settings.lineWrapping = true;
  }
  async saveConfigFallback(enabled) {
    const pluginId = "data-files-editor";
    const configDir = this.app.vault.configDir;
    const pluginDataPath = `${configDir}/plugins/${pluginId}/data.json`;
    let existingData = {};
    const dataFile = this.app.vault.getAbstractFileByPath(pluginDataPath);
    if (dataFile instanceof import_obsidian19.TFile) {
      try {
        existingData = JSON.parse(await this.app.vault.read(dataFile));
      } catch (error) {
        console.warn("Failed to parse existing data-files-editor data.json:", error);
      }
    }
    this.applySettings(existingData, enabled);
    const pluginDir = `${configDir}/plugins/${pluginId}`;
    const pluginDirFile = this.app.vault.getAbstractFileByPath(pluginDir);
    if (!pluginDirFile) {
      try {
        await this.app.vault.createFolder(pluginDir);
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        if (errorMessage && !errorMessage.includes("already exists") && !errorMessage.includes("File already exists") && !errorMessage.includes("Folder already exists")) {
          throw error;
        }
      }
    }
    const content = JSON.stringify(existingData, null, 2);
    if (dataFile instanceof import_obsidian19.TFile) {
      await this.app.vault.modify(dataFile, content);
    } else {
      await this.app.vault.create(pluginDataPath, content);
    }
    console.debug("DataFilesEditorConfig: Successfully saved data-files-editor config via fallback");
  }
};

// src/utils/FileNameHistoryConfig.ts
var PLUGIN_ID = "file-name-history";
var FileNameHistoryConfigurator = class {
  constructor(app) {
    this.app = app;
  }
  async saveConfig(enableMdxSupport) {
    var _a;
    const configPath = `${this.app.vault.configDir}/plugins/${PLUGIN_ID}/data.json`;
    try {
      const plugins = this.app.plugins;
      const plugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a[PLUGIN_ID];
      if (plugin == null ? void 0 : plugin.settings) {
        plugin.settings.fileExtensions = enableMdxSupport ? ["md", "mdx"] : ["md"];
        if (typeof plugin.saveSettings === "function") {
          await plugin.saveSettings();
        }
        return;
      }
      const data = await this.app.vault.adapter.read(configPath).catch(() => "{}");
      const parsed = JSON.parse(data || "{}");
      parsed.fileExtensions = enableMdxSupport ? ["md", "mdx"] : ["md"];
      await this.app.vault.adapter.write(configPath, JSON.stringify(parsed, null, 2) + "\n");
    } catch (error) {
      console.warn("[Vault CMS] Could not configure File Name History:", error);
    }
  }
};

// src/utils/ConfigFlushService.ts
var ConfigFlushService = class {
  constructor(app) {
    this.app = app;
    this.basesCMSConfigurator = new BasesCMSConfigurator(app);
    this.astroComposerConfigurator = new AstroComposerConfigurator(app);
    this.seoConfigurator = new SEOConfigurator(app);
    this.propertyOverFileNameConfigurator = new PropertyOverFileNameConfigurator(app);
    this.uiTweakerConfigurator = new UITweakerConfigurator(app);
    this.imageManagerConfigurator = new ImageManagerConfigurator(app);
    this.homeBaseConfigurator = new HomeBaseConfigurator(app);
    this.explorerFocusConfigurator = new ExplorerFocusConfigurator(app);
    this.dataFilesEditorConfigurator = new DataFilesEditorConfigurator(app);
    this.editingToolbarConfigurator = new EditingToolbarConfigurator(app);
    this.fileNameHistoryConfigurator = new FileNameHistoryConfigurator(app);
  }
  /**
   * Flushes current wizard state to various plugin configuration files.
   * This ensures the disk reflects the current wizard configuration without
   * needing to reach the finalization step.
   */
  async flush(state) {
    var _a, _b;
    console.debug("ConfigFlushService: Starting configuration flush");
    await this.basesCMSConfigurator.createOrUpdateBaseFile(
      state.contentTypes,
      state.frontmatterProperties,
      state.defaultContentTypeId,
      state.projectDetection,
      state.enableMdxSupport === true
    );
    const baseFilePath = await this.basesCMSConfigurator.resolveBaseFilePath();
    state.homeBase = { ...state.homeBase, homeBaseType: "File", homeBaseValue: baseFilePath };
    if (state.projectDetection) {
      const astroConfig = await this.astroComposerConfigurator.configureAstroComposer(
        state.contentTypes,
        state.frontmatterProperties,
        state.projectDetection.projectRoot,
        state.projectDetection.configFilePath,
        state.defaultContentTypeId,
        state.projectDetection,
        state.enableMdxSupport
      );
      state.astroComposerConfig = astroConfig;
      await this.astroComposerConfigurator.saveConfig(astroConfig);
    }
    const generatedSeo = this.seoConfigurator.generateSEOConfig(
      state.contentTypes,
      state.frontmatterProperties,
      state.projectDetection,
      state.enableMdxSupport,
      state.defaultContentTypeId
    );
    const userScanDirs = (_b = (_a = state.seoConfig) == null ? void 0 : _a.scanDirectories) == null ? void 0 : _b.trim();
    state.seoConfig = {
      ...generatedSeo,
      scanDirectories: userScanDirs || generatedSeo.scanDirectories
    };
    await this.seoConfigurator.saveConfig(state.seoConfig);
    const firstType = state.contentTypes.find((ct) => ct.enabled);
    const firstProps = firstType ? state.frontmatterProperties[firstType.id] : void 0;
    if (firstProps && firstProps.titleProperty) {
      state.propertyOverFileName.propertyKey = firstProps.titleProperty;
    }
    state.propertyOverFileName.enableMdxSupport = state.enableMdxSupport === true;
    await this.propertyOverFileNameConfigurator.saveConfig(state.propertyOverFileName);
    await this.uiTweakerConfigurator.saveConfig(state.enableMdxSupport === true);
    if (state.enabledPlugins.includes("file-name-history")) {
      await this.fileNameHistoryConfigurator.saveConfig(state.enableMdxSupport === true);
    }
    if (state.enabledPlugins.includes("image-manager") || Object.keys(state.imageManager).length > 0) {
      await this.imageManagerConfigurator.resolveAndSyncImageProperty(state);
      await this.imageManagerConfigurator.saveConfig(state.imageManager);
    }
    if (state.enabledPlugins.includes("home-base") || Object.keys(state.homeBase).length > 0) {
      await this.homeBaseConfigurator.saveConfig(state.homeBase);
    }
    if (state.projectDetection && (!state.explorerFocus || Object.keys(state.explorerFocus).length === 0)) {
      const vaultLocation = state.projectDetection.vaultLocation;
      if (vaultLocation === "root") {
        state.explorerFocus = {
          showRightClickMenu: true,
          showFileExplorerIcon: true,
          focusLevel: "custom",
          customFolderPath: "src/content",
          hideAncestorFolders: false
        };
        console.debug("ConfigFlushService: Auto-configured Explorer Focus for root install (custom: src/content)");
      } else {
        state.explorerFocus = {
          showRightClickMenu: true,
          showFileExplorerIcon: true,
          focusLevel: "parent",
          hideAncestorFolders: false
        };
        console.debug("ConfigFlushService: Auto-configured Explorer Focus for content install (parent)");
      }
    }
    if (state.enabledPlugins.includes("explorer-focus") || Object.keys(state.explorerFocus).length > 0) {
      await this.explorerFocusConfigurator.saveConfig(state.explorerFocus);
    }
    await this.editingToolbarConfigurator.toggleVisibility(this.app, state.enableEditingToolbar);
    await this.dataFilesEditorConfigurator.saveConfig(state.enableExtendedFileTypes === true);
    console.debug("ConfigFlushService: Configuration flush complete");
  }
};

// src/ui/wizard/GitSetupStep.ts
init_ProjectRootResolver();

// src/ui/wizard/DeploymentStep.ts
var import_obsidian20 = require("obsidian");
init_ProjectRootResolver();
var path10 = __toESM(require("path"), 1);
var DeploymentStep = class extends BaseWizardStep {
  constructor(app, containerEl, state, onNext, onBack, onCancel) {
    super(app, containerEl, state, onNext, onBack, onCancel);
    this.selectedPlatform = "";
  }
  async shouldSkip() {
    return false;
  }
  getAbsoluteProjectRoot() {
    var _a;
    return resolveProjectRoot2(this.app, (_a = this.state.projectDetection) == null ? void 0 : _a.projectRoot);
  }
  getProjectName() {
    const projectRoot = this.getAbsoluteProjectRoot();
    if (projectRoot) {
      return projectRoot.split(/[\\/]/).pop() || "my-site";
    }
    return "my-site";
  }
  getPlatforms() {
    return [
      {
        id: "netlify",
        name: "Netlify",
        description: "Fast and reliable hosting with a great developer experience.",
        url: "https://app.netlify.com/start",
        configFile: "netlify.toml",
        configContent: () => [
          "[build]",
          '  command = "pnpm run build"',
          '  publish = "dist"',
          ""
        ].join("\n")
      },
      {
        id: "vercel",
        name: "Vercel",
        description: "Optimized for frontend frameworks with zero-config deployment.",
        url: "https://vercel.com/new/import",
        configFile: "vercel.json",
        configContent: () => JSON.stringify({ framework: "astro" }, null, 2) + "\n"
      },
      {
        id: "cloudflare",
        name: "Cloudflare",
        description: "Global edge network with generous free tier.",
        url: "https://dash.cloudflare.com/",
        configFile: "wrangler.toml",
        configContent: () => {
          const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
          const projectName = this.getProjectName();
          return [
            `name = "${projectName}"`,
            `compatibility_date = "${today}"`,
            "",
            "[assets]",
            '  directory = "./dist"',
            '  not_found_handling = "404-page"',
            ""
          ].join("\n");
        }
      },
      {
        id: "github-pages",
        name: "GitHub Pages",
        description: "Host directly from your GitHub repository. Requires a public repo for free accounts.",
        url: "https://github.com/features/pages"
      }
    ];
  }
  async display() {
    const { containerEl } = this;
    containerEl.empty();
    containerEl.createEl("h2", { text: "Deployment" });
    containerEl.createEl("p", {
      text: "Choose where you want to host your site. A config file will be created for your chosen platform."
    });
    this.selectedPlatform = this.state.deploymentPlatform || "";
    const platforms = this.getPlatforms();
    for (const platform of platforms) {
      const setting = new import_obsidian20.Setting(containerEl);
      setting.setName(platform.name);
      setting.setDesc(platform.description);
      setting.addButton((btn) => {
        const isSelected = this.selectedPlatform === platform.id;
        btn.setButtonText(isSelected ? "Selected" : "Select");
        if (isSelected) btn.setCta();
        if (isSelected) btn.setDisabled(true);
        btn.onClick(async () => {
          this.selectedPlatform = platform.id;
          this.state.deploymentPlatform = platform.id;
          if (platform.configFile && platform.configContent) {
            await this.generateConfigFile(platform.configFile, platform.configContent());
          }
          await this.display();
        });
      });
    }
  }
  async generateConfigFile(filename, content) {
    const projectRoot = this.getAbsoluteProjectRoot();
    if (!projectRoot) return;
    const filePath = path10.join(projectRoot, filename);
    try {
      const fs7 = require("fs");
      if (fs7.existsSync(filePath)) {
        return;
      }
      fs7.writeFileSync(filePath, content, "utf-8");
      new import_obsidian20.Notice(`Created ${filename}`);
    } catch (e) {
    }
  }
  /**
   * Returns the deploy URL for the selected platform.
   * Called by GitSetupStep after a successful push.
   */
  static getDeployUrl(platform) {
    switch (platform) {
      case "netlify":
        return "https://app.netlify.com/start";
      case "vercel":
        return "https://vercel.com/new/import";
      case "cloudflare":
        return "https://dash.cloudflare.com/";
      case "github-pages":
        return "https://github.com/features/pages";
      default:
        return "";
    }
  }
  static getPlatformName(platform) {
    switch (platform) {
      case "netlify":
        return "Netlify";
      case "vercel":
        return "Vercel";
      case "cloudflare":
        return "Cloudflare";
      case "github-pages":
        return "GitHub Pages";
      default:
        return "";
    }
  }
  validate() {
    return true;
  }
  getTitle() {
    return "Deployment";
  }
  getDescription() {
    return "Choose your hosting platform";
  }
};

// src/ui/wizard/GitSetupStep.ts
var path11 = __toESM(require("path"), 1);
var GitSetupStep = class extends BaseWizardStep {
  // In-memory only, never persisted
  constructor(app, containerEl, state, onNext, onBack, onCancel) {
    super(app, containerEl, state, onNext, onBack, onCancel);
    this.pendingPat = "";
    this.hasAdvanced = false;
    this.gitManager = GitManager;
    this.configFlushService = new ConfigFlushService(app);
    this.safeConfigWriter = new SafeConfigWriter(app);
  }
  getAbsoluteProjectRoot() {
    var _a, _b;
    return (_b = resolveProjectRoot2(this.app, ((_a = this.state.projectDetection) == null ? void 0 : _a.projectRoot) || ".")) != null ? _b : null;
  }
  async display() {
    var _a, _b;
    const { containerEl } = this;
    containerEl.empty();
    containerEl.createEl("h2", { text: "Git Integration" });
    containerEl.createEl("p", {
      text: 'Connect your project to GitHub to enable sync and deployment. Click "Skip" to set this up later.',
      attr: { style: "font-style: italic; opacity: 0.8; margin-bottom: 2rem;" }
    });
    const projectRoot = (_a = this.getAbsoluteProjectRoot()) != null ? _a : "";
    const rootInfo = containerEl.createDiv({ cls: "git-root-info", attr: { style: "margin-bottom: 1rem;" } });
    rootInfo.createEl("b", { text: "Project Root: " });
    rootInfo.createSpan({ text: projectRoot || "(not set)" });
    const statusEl = containerEl.createDiv({
      cls: "git-status-message",
      attr: { style: "margin-bottom: 2rem; padding: 1rem; border: 1px solid var(--background-modifier-border); border-radius: 4px; min-height: 50px;" }
    });
    statusEl.createEl("i", { text: "Checking Git status...", attr: { style: "opacity: 0.5;" } });
    let isRepo = false;
    let remoteUrl = null;
    if (projectRoot) {
      isRepo = await this.gitManager.isRepo(projectRoot);
      if (isRepo) {
        remoteUrl = await this.gitManager.getRemoteUrl(projectRoot);
      }
    }
    statusEl.empty();
    if (isRepo) {
      statusEl.createEl("b", { text: "Status: " });
      statusEl.createSpan({
        text: "Git is already initialized.",
        attr: { style: "color: var(--text-success); font-weight: bold;" }
      });
      if (remoteUrl) {
        const remoteEl = statusEl.createDiv({ attr: { style: "margin-top: 0.5rem;" } });
        remoteEl.createEl("b", { text: "Remote: " });
        remoteEl.createSpan({ text: remoteUrl });
      }
    } else {
      statusEl.createEl("b", { text: "Status: " });
      statusEl.createSpan({ text: "Not a Git repository." });
    }
    const configContainer = containerEl.createDiv({ cls: "git-config-container" });
    let setupContent = configContainer;
    if (isRepo) {
      const details = configContainer.createEl("details", { attr: { style: "margin-bottom: 2rem;" } });
      details.createEl("summary", {
        text: "Update Settings",
        attr: { style: "font-weight: bold; cursor: pointer; padding: 0.5rem 0; opacity: 0.8;" }
      });
      setupContent = details.createDiv({ attr: { style: "padding: 1rem; border-left: 2px solid var(--background-modifier-border);" } });
    }
    const instructions = setupContent.createDiv({ cls: "git-instructions" });
    instructions.createEl("p", {
      text: 'Connect your project to GitHub to publish your site. Click "Skip" to skip Git setup now and set it up later.'
    });
    const gitDownload = instructions.createEl("p");
    gitDownload.createSpan({ text: "1. " });
    gitDownload.createEl("a", {
      text: "Download and install Git",
      href: "https://git-scm.com/"
    });
    const tokenLink = instructions.createEl("p");
    tokenLink.createSpan({ text: "2. " });
    tokenLink.createEl("a", {
      text: "Generate a new GitHub Personal access token",
      href: `https://github.com/settings/tokens/new?scopes=repo&description=${encodeURIComponent((this.state.gitConfig.repoName || "Project") + " (Vault CMS)")}`
    });
    const tokenHelp = instructions.createEl("ul");
    tokenHelp.createEl("li", { text: `Set a Note (like "${this.state.gitConfig.repoName || "Project"} (Vault CMS)")` });
    tokenHelp.createEl("li", { text: 'Set Expiration to "No expiration"' });
    tokenHelp.createEl("li", { text: 'Check the "repo" box (so all top options are selected)' });
    tokenHelp.createEl("li", { text: 'Click "Generate token" at the bottom, copy it, and paste it below.' });
    if (!remoteUrl) {
      setupContent.createEl("h3", { text: isRepo ? "Connect to GitHub" : "Create New Repository" });
    } else {
      setupContent.createEl("h3", { text: "Update GitHub Connection" });
    }
    const patSetting = new import_obsidian21.Setting(setupContent).setName("GitHub Personal Access Token").setDesc("Stored securely in Obsidian Secrets.").addExtraButton((btn) => {
      btn.setIcon("link").setTooltip("Generate a new Personal access token on GitHub").onClick(() => {
        const description = encodeURIComponent((this.state.gitConfig.repoName || "Project") + " (Vault CMS)");
        window.open(`https://github.com/settings/tokens/new?scopes=repo&description=${description}`);
      });
    });
    const secretId = "vault-cms-github-pat";
    let secretValue = (_b = this.app.secretStorage) == null ? void 0 : _b.getSecret(secretId);
    if (secretValue && !this.pendingPat) {
    }
    patSetting.addText((text) => {
      text.setPlaceholder("ghp_xxxxxxxxxxxx").setValue(secretValue ? "********" : "").onChange((value) => {
        this.pendingPat = value.trim();
      });
      text.inputEl.type = "password";
    });
    const patStatus = setupContent.createDiv({ cls: "pat-status-info", attr: { style: "margin-bottom: 1rem; font-size: 0.9em; color: var(--text-muted);" } });
    if (secretValue) {
      patStatus.createSpan({ text: "\u2713 Linked to Obsidian Secret: ", attr: { style: "color: var(--text-success); font-weight: bold;" } });
      patStatus.createSpan({ text: secretId });
    }
    patSetting.addButton((button) => {
      button.setButtonText("Verify Token").onClick(async () => {
        var _a2;
        let token = this.pendingPat;
        if (!token || token === "********" || token === "vault-cms-github-pat") {
          token = (_a2 = this.app.secretStorage) == null ? void 0 : _a2.getSecret("vault-cms-github-pat");
        }
        if (!token) {
          new import_obsidian21.Notice("Please enter or paste your GitHub Personal Access Token.");
          return;
        }
        button.setDisabled(true);
        button.setButtonText("Verifying...");
        patStatus.empty();
        try {
          const username = await this.gitManager.verifyToken(token);
          if (username) {
            new import_obsidian21.Notice(`Token verified successfully as ${username}!`);
            patStatus.createSpan({ text: `\u2713 Verified as `, attr: { style: "color: var(--text-success);" } });
            patStatus.createEl("b", { text: username });
            if (this.app.secretStorage) {
              await this.app.secretStorage.setSecret("vault-cms-github-pat", token);
            }
            try {
              this.app.saveLocalStorage("obsidian-git:username", username);
            } catch (e) {
              localStorage.setItem("obsidian-git:username", username);
            }
            this.state.gitConfig.enabled = true;
            button.setButtonText("Verified");
            button.buttonEl.style.backgroundColor = "var(--interactive-accent)";
            button.buttonEl.style.color = "var(--text-on-accent)";
          } else {
            new import_obsidian21.Notice("Invalid token or GitHub API error.");
            patStatus.createSpan({ text: "\u2717 Invalid token or GitHub API error.", attr: { style: "color: var(--text-error);" } });
            button.setButtonText("Verify Token");
            button.setDisabled(false);
          }
        } catch (e) {
          new import_obsidian21.Notice("Verification failed. Check your connection.");
          patStatus.createSpan({ text: "\u2717 Verification failed. Check your connection.", attr: { style: "color: var(--text-error);" } });
          button.setButtonText("Verify Token");
          button.setDisabled(false);
        }
      });
    });
    new import_obsidian21.Setting(setupContent).setName(remoteUrl ? "New Repository Name" : "Repository Name").setDesc("The name of your GitHub repository.").addText((text) => {
      const defaultName = projectRoot ? projectRoot.split(/[\\/]/).pop() : "";
      const initialValue = this.state.gitConfig.repoName || defaultName || "";
      if (!this.state.gitConfig.repoName) {
        this.state.gitConfig.repoName = initialValue;
      }
      text.setPlaceholder("my-blog").setValue(initialValue).onChange((value) => {
        this.state.gitConfig.repoName = value.trim();
      });
    });
    new import_obsidian21.Setting(setupContent).setName("Description").setDesc("A short description for your repository.").addText((text) => {
      text.setPlaceholder("My personal blog").setValue(this.state.gitConfig.repoDescription || "").onChange((value) => {
        this.state.gitConfig.repoDescription = value.trim();
      });
    });
    new import_obsidian21.Setting(setupContent).setName("Private Repository").setDesc("Keep this repository private and hidden from the public.").addToggle((toggle) => {
      toggle.setValue(this.state.gitConfig.isPrivate).onChange((value) => {
        this.state.gitConfig.isPrivate = value;
      });
    });
    new import_obsidian21.Setting(setupContent).setName("Default Branch").setDesc('The name of the initial branch ("main" or "master").').addText((text) => {
      const initialBranch = this.state.gitConfig.branchName || "main";
      if (!this.state.gitConfig.branchName) {
        this.state.gitConfig.branchName = initialBranch;
      }
      text.setPlaceholder("main").setValue(initialBranch).onChange((value) => {
        this.state.gitConfig.branchName = value.trim() || "main";
      });
    });
    new import_obsidian21.Setting(setupContent).setName("Auto-configure Git plugin").setDesc('Automatically set up the "Git" plugin to work with this project.').addToggle((toggle) => {
      toggle.setValue(this.state.gitConfig.autoConfigureObsidianGit).onChange((value) => {
        this.state.gitConfig.autoConfigureObsidianGit = value;
      });
    });
    const actionContainer = setupContent.createDiv({ cls: "git-action-container", attr: { style: "margin-top: 2rem;" } });
    let buttonText = isRepo ? remoteUrl ? "Update Remote & Push" : "Connect to GitHub" : "Initialize & Push to GitHub";
    const createBtn = new import_obsidian21.ButtonComponent(actionContainer).setButtonText(buttonText).setCta().onClick(async () => {
      await this.handleGitSetup(createBtn, isRepo, !!remoteUrl);
    });
    configContainer.createEl("p", {
      cls: "git-skip-info",
      attr: { style: "font-size: 0.8em; color: var(--text-muted); margin-top: 1rem; border-top: 1px solid var(--background-modifier-border); padding-top: 1rem;" },
      text: 'Click "Skip" to skip Git setup.'
    });
  }
  async handleGitSetup(button, alreadyRepo, alreadyHasRemote) {
    var _a;
    if (this.hasAdvanced) return;
    let pat = this.pendingPat;
    const { repoName, repoDescription, isPrivate, branchName } = this.state.gitConfig;
    const projectRoot = this.getAbsoluteProjectRoot();
    const branch = branchName || "main";
    if (!pat || pat === "********" || pat === "vault-cms-github-pat") {
      pat = ((_a = this.app.secretStorage) == null ? void 0 : _a.getSecret("vault-cms-github-pat")) || pat;
    }
    const token = pat;
    if (!token || token === "********" || token === "vault-cms-github-pat" || !projectRoot) {
      new import_obsidian21.Notice("Please provide a valid Token and ensure project root is detected.");
      button.setDisabled(false);
      return;
    }
    if (!alreadyHasRemote && !repoName) {
      new import_obsidian21.Notice("Please provide a Repository Name.");
      button.setDisabled(false);
      return;
    }
    button.setDisabled(true);
    button.setButtonText(alreadyHasRemote ? "Updating..." : "Initializing...");
    try {
      if (!alreadyRepo) {
        await this.gitManager.initRepo(projectRoot);
        new import_obsidian21.Notice("Local Git repository initialized.");
      }
      new import_obsidian21.Notice(alreadyHasRemote ? "Creating new GitHub repository..." : "Creating GitHub repository...");
      const repoInfo = await this.gitManager.createGitHubRepo(token, repoName, repoDescription || "", isPrivate);
      await this.gitManager.setRemote(projectRoot, repoInfo.clone_url);
      new import_obsidian21.Notice(`Successfully ${alreadyHasRemote ? "updated" : "connected"} to ${repoInfo.html_url}`);
      try {
        await this.configFlushService.flush(this.state);
        console.debug("GitSetupStep: Early configuration flush successful");
      } catch (flushError) {
        console.warn("GitSetupStep: Early configuration flush failed, but continuing with sync:", flushError);
      }
      try {
        await this.gitManager.initialCommitAndPush(projectRoot, branch, "origin", token);
        new import_obsidian21.Notice("Successfully synced with GitHub!");
      } catch (pushError) {
        console.error("Sync failed:", pushError);
        new import_obsidian21.Notice("Initial sync failed. Please ensure you have Git configured locally and your credentials are set up (like Git Credential Manager).");
      }
      if (this.state.gitConfig.autoConfigureObsidianGit) {
        await this.configureObsidianGit(token, projectRoot, branch);
      }
      if (pat && this.app.secretStorage) {
        await this.app.secretStorage.setSecret("vault-cms-github-pat", pat);
      }
      this.pendingPat = "";
      this.state.gitConfig.enabled = true;
      button.setButtonText("Success!");
      new import_obsidian21.Notice("Git setup complete!");
      const selectedPlatform = this.state.deploymentPlatform || "";
      if (selectedPlatform) {
        const platformName = DeploymentStep.getPlatformName(selectedPlatform);
        const deployUrl = DeploymentStep.getDeployUrl(selectedPlatform);
        if (platformName && deployUrl) {
          const deployContainer = this.containerEl.createDiv({ attr: { style: "margin-top: 1.5rem; padding: 1rem; border: 1px solid var(--interactive-accent); border-radius: 8px; text-align: center;" } });
          deployContainer.createEl("p", { text: `Your code has been pushed. Connect your repo to ${platformName} to go live.` });
          new import_obsidian21.Setting(deployContainer).addButton((btn) => btn.setButtonText(`Deploy on ${platformName}`).setCta().onClick(() => {
            window.open(deployUrl);
          }));
        }
      }
      if (!this.hasAdvanced) {
        this.hasAdvanced = true;
        if (!selectedPlatform) {
          setTimeout(() => this.onNext(), 1500);
        }
      }
    } catch (error) {
      console.error("Git integration failed:", error);
      const errorMessage = error instanceof Error ? error.message : String(error);
      new import_obsidian21.Notice(`Setup failed: ${errorMessage}`);
      button.setDisabled(false);
      button.setButtonText(alreadyHasRemote ? "Update Settings & Sync" : "Initialize & Push to GitHub");
    }
  }
  async configureObsidianGit(pat, projectRoot, branch) {
    var _a;
    console.debug("GitSetupStep: Configuring Obsidian Git plugin...");
    try {
      this.app.saveLocalStorage("obsidian-git:password", pat);
    } catch (e) {
      localStorage.setItem("obsidian-git:password", pat);
    }
    const adapter = this.app.vault.adapter;
    const vaultRoot = adapter.getBasePath ? adapter.getBasePath() : "";
    if (vaultRoot && projectRoot) {
      const absoluteProjectRoot = path11.isAbsolute(projectRoot) ? projectRoot : path11.resolve(vaultRoot, projectRoot);
      const relativePath = path11.relative(vaultRoot, absoluteProjectRoot).replace(/\\/g, "/");
      const configUpdates = {
        basePath: relativePath || "",
        gitRemote: "origin",
        remoteName: "origin",
        // Some versions use this
        mainBranch: branch,
        branch,
        // Some versions use this
        currentRemote: "origin"
      };
      const gitPlugin = (_a = this.app.plugins) == null ? void 0 : _a.getPlugin("obsidian-git");
      if (gitPlugin) {
        console.debug("GitSetupStep: Found running Obsidian Git plugin, updating in-memory settings");
        gitPlugin.settings = {
          ...gitPlugin.settings,
          ...configUpdates
        };
        if (typeof gitPlugin.saveSettings === "function") {
          await gitPlugin.saveSettings();
        }
      }
      await this.safeConfigWriter.mergeConfig("obsidian-git", configUpdates);
    }
    new import_obsidian21.Notice("Obsidian Git plugin configured.");
  }
  validate() {
    return true;
  }
  getTitle() {
    return "Git Integration";
  }
  getDescription() {
    return "Connect to GitHub";
  }
};

// src/ui/wizard/FinalizeStep.ts
var import_obsidian22 = require("obsidian");
var FinalizeStep = class extends BaseWizardStep {
  constructor(app, containerEl, state, onNext, onBack, onCancel) {
    super(app, containerEl, state, onNext, onBack, onCancel);
    this.applied = false;
    this.pluginManager = new PluginManager(app);
    this.basesCMSConfigurator = new BasesCMSConfigurator(app);
    this.configFlushService = new ConfigFlushService(app);
  }
  isApplied() {
    return this.applied;
  }
  display() {
    const { containerEl } = this;
    containerEl.empty();
    containerEl.createEl("h2", { text: "Finalize configuration" });
    containerEl.createEl("p", {
      text: 'Review your configuration and click "Apply and restart" below to save and apply all settings.'
    });
    const summary = containerEl.createEl("div", { cls: "finalize-summary" });
    summary.createEl("h3", { text: "Summary" });
    const enabledContentTypes = this.state.contentTypes.filter((ct) => ct.enabled);
    summary.createEl("p", { text: `Content Types: ${enabledContentTypes.length}` });
    summary.createEl("p", { text: `Editing Toolbar: ${this.state.enableEditingToolbar ? "Enabled" : "Disabled"}` });
    const basesViewsCount = enabledContentTypes.length;
    summary.createEl("p", { text: `Bases CMS Views: ${basesViewsCount} new view${basesViewsCount !== 1 ? "s" : ""} to be created` });
    const seoDirectories = enabledContentTypes.map((ct) => ct.folder);
    const seoDirectoriesCount = seoDirectories.length;
    summary.createEl("p", { text: `SEO Scan Directories: ${seoDirectoriesCount} director${seoDirectoriesCount !== 1 ? "ies" : "y"} (${seoDirectories.join(", ")})` });
  }
  async applyConfiguration(shouldRestart = false) {
    return this.applyConfigurationInternal(shouldRestart);
  }
  async applyConfigurationInternal(shouldRestart = false) {
    var _a;
    if (this.applied) {
      return;
    }
    try {
      console.debug("FinalizeStep: Starting configuration application");
      console.debug("FinalizeStep: Enabled content types:", this.state.contentTypes.filter((ct) => ct.enabled).map((ct) => ct.name));
      console.debug("FinalizeStep: Configuring plugin states");
      if (this.state.enableExtendedFileTypes) {
        const pluginId = "data-files-editor";
        if (!this.state.enabledPlugins.includes(pluginId)) {
          console.debug(`FinalizeStep: Enabling ${pluginId} because Extended File Types is toggle on`);
          this.state.enabledPlugins.push(pluginId);
        }
        this.state.disabledPlugins = this.state.disabledPlugins.filter((p) => p !== pluginId);
      }
      await this.pluginManager.setPluginStates(this.state.enabledPlugins, this.state.disabledPlugins);
      await this.configFlushService.flush(this.state);
      const defaultTypeId = this.state.defaultContentTypeId || ((_a = this.state.contentTypes.find((ct) => ct.enabled)) == null ? void 0 : _a.id);
      if (defaultTypeId && !this.state.defaultContentTypeId) {
        this.state.defaultContentTypeId = defaultTypeId;
      }
      if (defaultTypeId) {
        const defaultType = this.state.contentTypes.find((ct) => ct.id === defaultTypeId);
        if (defaultType) {
          console.debug("FinalizeStep: Configuring Obsidian settings for default content type:", defaultType.name);
          const app = this.app;
          let targetPath = "./";
          if (this.state.attachmentHandlingMode === "same-folder") {
            targetPath = "./";
          } else if (this.state.attachmentHandlingMode === "subfolder") {
            const folderName = this.state.attachmentFolderName || "attachments";
            targetPath = `./${folderName}`;
          } else if (this.state.attachmentHandlingMode === "specified-folder") {
            const folderName = this.state.attachmentFolderName || "attachments";
            targetPath = folderName;
          }
          if (app.setting && typeof app.setting.set === "function") {
            console.debug("FinalizeStep: Using app.setting API");
            await app.setting.set("newFileLocation", "folder");
            await app.setting.set("newFileFolderPath", defaultType.folder);
            await app.setting.set("attachmentFolderPath", targetPath);
            await app.setting.set("newLinkFormat", "relative");
            if (typeof app.setting.save === "function") {
              await app.setting.save();
              console.debug("FinalizeStep: Obsidian settings saved via app.setting.save()");
            }
          } else {
            console.debug("FinalizeStep: Using vault.config API");
            const vault = this.app.vault;
            const obsidianSettings = vault.config;
            if (!obsidianSettings) {
              console.error("FinalizeStep: vault.config is not available");
            } else {
              obsidianSettings.newFileLocation = "folder";
              obsidianSettings.newFileFolderPath = defaultType.folder;
              obsidianSettings.attachmentFolderPath = targetPath;
              obsidianSettings.newLinkFormat = "relative";
              if (typeof vault.saveConfig === "function") {
                await vault.saveConfig();
                console.debug("FinalizeStep: Obsidian settings saved via vault.saveConfig()");
              } else {
                console.error("FinalizeStep: vault.saveConfig() is not available");
              }
            }
          }
        }
      }
      this.applied = true;
      if (shouldRestart) {
        new import_obsidian22.Notice("Configuration applied. Obsidian will now restart...", 3e3);
      } else {
        new import_obsidian22.Notice("Configuration applied successfully! You may need to restart Obsidian to see all changes.", 8e3);
      }
    } catch (error) {
      console.error("Failed to apply configuration:", error);
      new import_obsidian22.Notice("Failed to apply configuration. Please check the console for details.", 6e3);
    }
  }
  /**
   * Find any active Bases views and switch them to the new default view.
   * Closes old tabs and reopens them to force a clean reload if not restarting.
   */
  async updateActiveBasesViews(defaultViewName, shouldRestart) {
    const baseFilePath = await this.basesCMSConfigurator.resolveBaseFilePath();
    let updated = false;
    const leavesToUpdate = [];
    this.app.workspace.iterateAllLeaves((leaf) => {
      var _a;
      const viewType = leaf.view.getViewType();
      if (viewType === "bases" || viewType === "bases-cms" || viewType === "cms") {
        const state = leaf.getViewState();
        if (((_a = state.state) == null ? void 0 : _a.file) === baseFilePath) {
          console.debug(`FinalizeStep: Found Bases leaf to update (type: ${viewType})`);
          leavesToUpdate.push({ leaf, state });
        }
      }
    });
    for (const { leaf, state } of leavesToUpdate) {
      console.debug("FinalizeStep: Updating existing Bases leaf state");
      await leaf.setViewState({
        ...state,
        state: {
          ...state.state,
          view: defaultViewName,
          viewName: defaultViewName
        }
      });
      updated = true;
    }
    if (!updated) {
      console.debug("FinalizeStep: Opening new Bases leaf with fresh state");
      const leaf = this.app.workspace.getLeaf("tab");
      await leaf.setViewState({
        type: "cms",
        active: true,
        state: {
          file: baseFilePath,
          view: defaultViewName,
          viewName: defaultViewName
        }
      });
      this.app.workspace.setActiveLeaf(leaf, { focus: true });
      updated = true;
    }
    if (shouldRestart) {
      try {
        const adapter = this.app.vault.adapter;
        const configDir = this.app.vault.configDir;
        const workspacePath = `${configDir}/workspace.json`;
        if (await adapter.exists(workspacePath)) {
          console.debug("FinalizeStep: Attempting direct workspace.json modification");
          const content = await adapter.read(workspacePath);
          const workspace = JSON.parse(content);
          let modified = false;
          const updateNode = (node) => {
            var _a;
            if (!node) return;
            if (node.type === "leaf" && node.state) {
              if ((node.state.type === "bases" || node.state.type === "bases-cms" || node.state.type === "cms") && ((_a = node.state.state) == null ? void 0 : _a.file) === baseFilePath) {
                console.debug(`FinalizeStep: Found Bases leaf in workspace.json, updating to ${defaultViewName}`);
                if (node.state.state) {
                  node.state.state.view = defaultViewName;
                  node.state.state.viewName = defaultViewName;
                  modified = true;
                }
              }
            }
            if (node.children) {
              if (Array.isArray(node.children)) {
                node.children.forEach((child) => updateNode(child));
              } else {
                updateNode(node.children);
              }
            }
          };
          updateNode(workspace.main);
          updateNode(workspace.left);
          updateNode(workspace.right);
          if (modified) {
            await adapter.write(workspacePath, JSON.stringify(workspace, null, 2));
            console.debug("FinalizeStep: Successfully modified workspace.json");
          }
        }
      } catch (error) {
        console.warn("FinalizeStep: Failed to modify workspace.json directly:", error);
      }
    }
  }
  validate() {
    return true;
  }
  getTitle() {
    return "Finalize";
  }
  getDescription() {
    return "Review and apply configuration";
  }
};

// src/ui/wizard/WizardStateMachine.ts
var WizardStateMachine = class {
  constructor(steps) {
    // State to step index mapping
    this.stateStepMap = /* @__PURE__ */ new Map([
      ["welcome", 0],
      ["detect", 1],
      ["content-types", 2],
      ["frontmatter", 3],
      ["plugins", 4],
      ["complete", 9]
    ]);
    // Reverse mapping: step index to state
    this.stepStateMap = /* @__PURE__ */ new Map([
      [0, "welcome"],
      [1, "detect"],
      [2, "content-types"],
      [3, "frontmatter"],
      [4, "plugins"],
      // PluginConfigurationStep
      [5, "plugins"],
      // OptionalPluginsStep
      [6, "plugins"],
      // IgnoreStep
      [7, "plugins"],
      // GitSetupStep
      [8, "plugins"],
      // DeploymentStep
      [9, "complete"]
      // FinalizeStep
    ]);
    // State transition rules
    this.transitions = /* @__PURE__ */ new Map([
      ["welcome", ["detect"]],
      ["detect", ["content-types"]],
      ["content-types", ["frontmatter"]],
      ["frontmatter", ["plugins"]],
      ["plugins", ["complete"]],
      ["complete", []]
      // Terminal state
    ]);
    this.currentState = "welcome";
    this.stepIndex = 0;
    this.steps = steps || [
      WelcomeStep,
      ProjectDetectionStep,
      ContentTypeStep,
      FrontmatterPropertiesStep,
      PluginConfigurationStep,
      OptionalPluginsStep,
      IgnoreStep,
      GitSetupStep,
      DeploymentStep,
      FinalizeStep
    ];
  }
  /**
   * Get the current state
   */
  getState() {
    return this.currentState;
  }
  /**
   * Get the current step index
   */
  getStepIndex() {
    return this.stepIndex;
  }
  /**
   * Get the total number of steps
   */
  getTotalSteps() {
    return this.steps.length;
  }
  /**
   * Get the step constructor for a given index
   */
  getStepConstructor(index) {
    return this.steps[index];
  }
  /**
   * Check if we can transition to the next step/state
   */
  canGoNext() {
    return this.stepIndex < this.steps.length - 1;
  }
  /**
   * Check if we can go back to the previous step/state
   */
  canGoBack() {
    return this.stepIndex > 0;
  }
  /**
   * Move to the next step
   * Updates both step index and state
   */
  next() {
    if (!this.canGoNext()) {
      console.warn("WizardStateMachine: Cannot go to next step - already at final step");
      return;
    }
    const nextStepIndex = this.stepIndex + 1;
    const nextState = this.stepStateMap.get(nextStepIndex);
    if (!nextState) {
      console.error(`WizardStateMachine: No state mapping for step index ${nextStepIndex}`);
      return;
    }
    const allowedTransitions = this.transitions.get(this.currentState) || [];
    if (!allowedTransitions.includes(nextState) && nextState !== this.currentState) {
      console.warn(
        `WizardStateMachine: Invalid transition from ${this.currentState} to ${nextState}`
      );
    }
    this.stepIndex = nextStepIndex;
    this.currentState = nextState;
    console.debug(
      `WizardStateMachine: Transitioned to step ${this.stepIndex} (state: ${this.currentState})`
    );
  }
  /**
   * Move to the previous step
   * Updates both step index and state
   */
  previous() {
    if (!this.canGoBack()) {
      console.warn("WizardStateMachine: Cannot go to previous step - already at first step");
      return;
    }
    const prevStepIndex = this.stepIndex - 1;
    const prevState = this.stepStateMap.get(prevStepIndex);
    if (!prevState) {
      console.error(`WizardStateMachine: No state mapping for step index ${prevStepIndex}`);
      return;
    }
    this.stepIndex = prevStepIndex;
    this.currentState = prevState;
    console.debug(
      `WizardStateMachine: Went back to step ${this.stepIndex} (state: ${this.currentState})`
    );
  }
  /**
   * Jump to a specific step index
   * Updates both step index and state
   */
  jumpToStep(index) {
    const clampedIndex = Math.max(0, Math.min(index, this.steps.length - 1));
    const state = this.stepStateMap.get(clampedIndex);
    if (!state) {
      console.error(`WizardStateMachine: No state mapping for step index ${clampedIndex}`);
      return;
    }
    this.stepIndex = clampedIndex;
    this.currentState = state;
    console.debug(
      `WizardStateMachine: Jumped to step ${this.stepIndex} (state: ${this.currentState})`
    );
  }
  /**
   * Jump to a specific state
   * This will move to the first step of that state
   */
  jumpToState(state) {
    const stepIndex = this.stateStepMap.get(state);
    if (stepIndex === void 0) {
      console.error(`WizardStateMachine: No step mapping for state ${state}`);
      return;
    }
    this.jumpToStep(stepIndex);
  }
  /**
   * Get progress as a percentage
   */
  getProgress() {
    if (this.steps.length === 0) return 0;
    return (this.stepIndex + 1) / this.steps.length * 100;
  }
  /**
   * Get a human-readable description of the current state
   */
  getStateDescription() {
    switch (this.currentState) {
      case "welcome":
        return "Welcome";
      case "detect":
        return "Project Detection";
      case "content-types":
        return "Content Type Setup";
      case "frontmatter":
        return "Frontmatter Configuration";
      case "plugins":
        return "Plugin Configuration";
      case "complete":
        return "Finalization";
      default:
        return "Unknown State";
    }
  }
  /**
   * Debug: Get a summary of the current state machine status
   */
  getDebugInfo() {
    return `State: ${this.currentState} (${this.getStateDescription()}) | Step: ${this.stepIndex + 1}/${this.steps.length} | Progress: ${this.getProgress().toFixed(1)}%`;
  }
};

// src/ui/SetupWizardModal.ts
function setCssProps8(element, props) {
  for (const [key, value] of Object.entries(props)) {
    const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
    element.style.setProperty(cssKey, value);
  }
}
var SetupWizardModal = class extends import_obsidian23.Modal {
  // Track navigation direction for skip logic
  constructor(app, initialState, pluginInstance) {
    var _a, _b, _c, _d, _e;
    super(app);
    this.currentStepInstance = null;
    this.isCompleting = false;
    this.initialSettingsSnapshot = null;
    this.lastSavedStepIndex = -1;
    // Track the last step where "Next" was clicked
    this.navigatingBack = false;
    this.plugin = pluginInstance || ((_b = (_a = app.plugins) == null ? void 0 : _a.plugins) == null ? void 0 : _b["vault-cms"]);
    if (!this.plugin) {
      throw new Error("VaultCMSPlugin instance is required");
    }
    this.stateManager = new WizardStateManager(this.plugin);
    if (initialState) {
      this.stateManager.updateState(initialState);
      if (initialState.currentStep && initialState.currentStep > 1) {
        const currentState = this.stateManager.getState();
        if (!((_c = currentState.projectDetection) == null ? void 0 : _c.projectRoot) && this.plugin.settings.projectRoot) {
          this.stateManager.updateState({
            projectDetection: {
              projectRoot: this.plugin.settings.projectRoot,
              configFilePath: ((_d = currentState.projectDetection) == null ? void 0 : _d.configFilePath) || "",
              vaultLocation: ((_e = currentState.projectDetection) == null ? void 0 : _e.vaultLocation) || "root"
            }
          });
        }
      }
    }
    this.steps = [
      WelcomeStep,
      ProjectDetectionStep,
      ContentTypeStep,
      FrontmatterPropertiesStep,
      PluginConfigurationStep,
      OptionalPluginsStep,
      IgnoreStep,
      DeploymentStep,
      GitSetupStep,
      FinalizeStep
    ];
    this.stateMachine = new WizardStateMachine(this.steps);
    console.debug("SetupWizardModal: State machine initialized -", this.stateMachine.getDebugInfo());
  }
  async onOpen() {
    const { contentEl } = this;
    contentEl.empty();
    contentEl.addClass("vault-cms-wizard");
    await this.stateManager.refreshState();
    this.initialSettingsSnapshot = this.createSettingsSnapshot();
    void this.renderCurrentStep();
  }
  onClose() {
    const { contentEl } = this;
    contentEl.empty();
    this.isCompleting = false;
  }
  scrollToTop() {
    const { contentEl } = this;
    let scrollableParent = contentEl;
    while (scrollableParent && scrollableParent !== document.body) {
      const style = window.getComputedStyle(scrollableParent);
      if (scrollableParent.scrollHeight > scrollableParent.clientHeight && (style.overflowY === "auto" || style.overflowY === "scroll" || style.overflow === "auto" || style.overflow === "scroll")) {
        scrollableParent.scrollTop = 0;
        break;
      }
      scrollableParent = scrollableParent.parentElement;
    }
    const modalContent = contentEl.closest(".modal-content");
    if (modalContent) {
      modalContent.scrollTop = 0;
    }
    const modalContainer = contentEl.closest(".modal-container");
    if (modalContainer) {
      modalContainer.scrollTop = 0;
    }
    contentEl.scrollTop = 0;
  }
  async renderCurrentStep() {
    const { contentEl } = this;
    const state = this.stateManager.getState();
    const stepIndex = state.currentStep;
    if (stepIndex >= 0 && stepIndex < this.steps.length) {
      const StepClass = this.steps[stepIndex];
      const tempDiv = document.createElement("div");
      const stepInstance = new StepClass(
        this.app,
        tempDiv,
        state,
        () => {
        },
        // Temporary handlers
        () => {
        },
        () => {
        }
      );
      if (await stepInstance.shouldSkip()) {
        if (this.navigatingBack) {
          console.debug(`SetupWizardModal: Step ${StepClass.name} requested skip (going back)...`);
          if (this.stateManager.canGoPrevious()) {
            this.stateManager.previousStep();
          } else {
            this.navigatingBack = false;
          }
        } else {
          console.debug(`SetupWizardModal: Step ${StepClass.name} requested skip. Advancing...`);
          this.stateManager.nextStep(this.steps.length);
          this.stateMachine.next();
        }
        return this.renderCurrentStep();
      }
    }
    this.navigatingBack = false;
    this.scrollToTop();
    contentEl.empty();
    contentEl.addClass("vault-cms-wizard");
    this.scrollToTop();
    this.renderProgress(contentEl);
    const stepContent = contentEl.createDiv("wizard-content");
    setCssProps8(stepContent, { minHeight: "400px" });
    await this.renderStepContent(stepContent);
    this.renderFooter(contentEl);
    requestAnimationFrame(() => {
      this.scrollToTop();
    });
  }
  renderProgress(container) {
    try {
      const state = this.stateManager.getState();
      const totalSteps = this.steps.length;
      if (!state || !this.stateMachine) {
        console.error("SetupWizardModal: state or stateMachine is missing in renderProgress");
        return;
      }
      const progress = container.createDiv("wizard-progress");
      this.stateMachine.jumpToStep(state.currentStep);
      const progressBar = progress.createDiv("progress-bar");
      const progressFill = progressBar.createDiv("progress-fill");
      const progressPercent = (state.currentStep + 1) / totalSteps * 100;
      progressFill.style.width = `${progressPercent}%`;
      const progressText = progress.createDiv("progress-text");
      progressText.textContent = `Step ${state.currentStep + 1} of ${totalSteps} - ${this.stateMachine.getStateDescription()}`;
    } catch (error) {
      console.error("SetupWizardModal: Error rendering progress bar:", error);
    }
  }
  async renderStepContent(container) {
    const state = this.stateManager.getState();
    const stepIndex = state.currentStep;
    if (stepIndex >= 0 && stepIndex < this.steps.length) {
      const StepClass = this.steps[stepIndex];
      const stepName = StepClass.name || "Unknown";
      console.debug(
        `SetupWizardModal: Displaying step ${stepIndex + 1}/${this.steps.length}: ${stepName}`,
        `[${this.stateMachine.getDebugInfo()}]`
      );
      this.currentStepInstance = new StepClass(
        this.app,
        container,
        state,
        () => {
          void (async () => {
            if (this.currentStepInstance && this.currentStepInstance.validate()) {
              await this.saveCurrentStepToWizardState();
              this.stateManager.nextStep(this.steps.length);
              this.stateMachine.next();
              console.debug("SetupWizardModal: Advanced to next step -", this.stateMachine.getDebugInfo());
              await this.renderCurrentStep();
            }
          })();
        },
        () => {
          this.discardCurrentStepChanges();
          this.stateManager.previousStep();
          this.stateMachine.previous();
          console.debug("SetupWizardModal: Went back to previous step -", this.stateMachine.getDebugInfo());
          void this.renderCurrentStep();
        },
        () => this.close()
      );
      await this.currentStepInstance.display();
    }
  }
  renderFooter(container) {
    var _a;
    const footer = container.createDiv("wizard-footer");
    setCssProps8(footer, { display: "flex", justifyContent: "space-between", alignItems: "center" });
    if (this.stateManager.getState().currentStep === 0) {
      const startupSetting = footer.createDiv("wizard-startup-setting-footer");
      const label = startupSetting.createEl("label", { cls: "wizard-checkbox-label" });
      setCssProps8(label, { cursor: "default" });
      const checkbox = label.createEl("input", { type: "checkbox" });
      setCssProps8(checkbox, { cursor: "default" });
      checkbox.checked = !this.plugin.settings.runWizardOnStartup;
      label.createSpan({ text: " I've already set up my vault, don't show on startup" });
      checkbox.addEventListener("change", () => {
        this.plugin.settings.runWizardOnStartup = !checkbox.checked;
        void this.plugin.saveSettings();
      });
    } else {
      footer.createDiv();
    }
    const buttons = footer.createDiv("wizard-buttons");
    setCssProps8(buttons, { display: "flex", gap: "10px" });
    if (this.stateManager.canGoPrevious()) {
      const prevBtn = buttons.createEl("button", {
        text: "Previous",
        cls: "mod-button"
      });
      prevBtn.addEventListener("click", () => {
        this.discardCurrentStepChanges();
        this.navigatingBack = true;
        this.stateManager.previousStep();
        void this.renderCurrentStep();
      });
    }
    if (this.stateManager.canGoNext(this.steps.length)) {
      if (this.stateManager.getState().currentStep !== 0 && ((_a = this.currentStepInstance) == null ? void 0 : _a.showNextButton) !== false) {
        const nextBtn = buttons.createEl("button", {
          text: "Next",
          cls: "mod-button mod-cta"
        });
        nextBtn.addEventListener("click", () => {
          void (async () => {
            if (this.currentStepInstance && this.currentStepInstance.validate()) {
              await this.saveCurrentStepToWizardState();
              this.lastSavedStepIndex = this.stateManager.getState().currentStep;
              this.stateManager.nextStep(this.steps.length);
              await this.renderCurrentStep();
            }
          })();
        });
      }
    } else {
      if (this.currentStepInstance instanceof FinalizeStep) {
        const applyBtn = buttons.createEl("button", {
          text: "Apply",
          cls: "mod-button"
        });
        applyBtn.addEventListener("click", () => {
          void this.handleComplete(false);
        });
        const applyRestartBtn = buttons.createEl("button", {
          text: "Apply and restart",
          cls: "mod-button mod-cta"
        });
        applyRestartBtn.addEventListener("click", () => {
          void this.handleComplete(true);
        });
      } else {
        const completeBtn = buttons.createEl("button", {
          text: "Complete setup",
          cls: "mod-button mod-cta"
        });
        completeBtn.addEventListener("click", () => {
          void this.handleComplete(false);
        });
      }
    }
    if (this.stateManager.canGoNext(this.steps.length)) {
      if (this.stateManager.getState().currentStep !== 0) {
        const skipBtn = buttons.createEl("button", {
          text: "Skip",
          cls: "mod-button"
        });
        skipBtn.addClass("wizard-skip-button");
        setCssProps8(skipBtn, { opacity: "0.6" });
        skipBtn.addEventListener("click", () => {
          this.stateManager.nextStep(this.steps.length);
          void this.renderCurrentStep();
        });
      }
    }
  }
  async handleComplete(shouldRestart) {
    if (this.isCompleting) return;
    this.isCompleting = true;
    try {
      if (this.currentStepInstance && this.currentStepInstance.validate()) {
        if (this.currentStepInstance instanceof FinalizeStep) {
          await this.currentStepInstance.applyConfiguration(shouldRestart);
          await this.stateManager.buildFinalSettings();
        } else {
          await this.saveCurrentStepToWizardState();
        }
        this.plugin.settings.wizardCompleted = true;
        this.plugin.settings.runWizardOnStartup = false;
        await this.plugin.saveSettings();
        await this.plugin.loadSettings();
        this.close();
        if (shouldRestart) {
          setTimeout(() => {
            this.app.commands.executeCommandById("app:reload");
          }, 1e3);
        }
      }
    } catch (error) {
      console.error("Error completing wizard:", error);
      new import_obsidian23.Notice("Failed to complete setup. Please check the console for details.");
    } finally {
      this.isCompleting = false;
    }
  }
  async saveCurrentStepToWizardState() {
    try {
      await this.stateManager.buildFinalSettings();
      await this.plugin.saveSettings();
      await this.plugin.loadSettings();
    } catch (error) {
      console.error("Error saving current step to data.json:", error);
    }
  }
  discardCurrentStepChanges() {
    void this.stateManager.refreshState();
  }
  async saveWizardStateToDataJson(showNotification = true) {
    try {
      await this.stateManager.buildFinalSettings();
      const hasChanges = this.hasSettingsChanged();
      if (!hasChanges) {
        return;
      }
      await this.plugin.saveSettings();
      await this.plugin.loadSettings();
      if (showNotification) {
        new import_obsidian23.Notice("Configuration saved");
      }
    } catch (error) {
      console.error("Error saving wizard state to data.json:", error);
      if (showNotification) {
        new import_obsidian23.Notice(`Failed to save configuration: ${error instanceof Error ? error.message : String(error)}`);
      }
    }
  }
  createSettingsSnapshot() {
    const state = this.stateManager.getState();
    return JSON.parse(JSON.stringify({
      projectDetection: state.projectDetection,
      contentTypes: state.contentTypes,
      frontmatterProperties: state.frontmatterProperties,
      defaultContentTypeId: state.defaultContentTypeId,
      preset: state.preset,
      enableEditingToolbar: state.enableEditingToolbar,
      enabledPlugins: state.enabledPlugins,
      disabledPlugins: state.disabledPlugins,
      theme: state.theme,
      basesCMSConfig: state.basesCMSConfig,
      astroComposerConfig: state.astroComposerConfig,
      seoConfig: state.seoConfig,
      propertyOverFileName: state.propertyOverFileName,
      imageManager: state.imageManager,
      homeBase: state.homeBase
    }));
  }
  hasSettingsChanged() {
    if (!this.initialSettingsSnapshot) {
      return false;
    }
    const currentSnapshot = this.createSettingsSnapshot();
    return JSON.stringify(currentSnapshot.projectDetection) !== JSON.stringify(this.initialSettingsSnapshot.projectDetection) || JSON.stringify(currentSnapshot.contentTypes) !== JSON.stringify(this.initialSettingsSnapshot.contentTypes) || JSON.stringify(currentSnapshot.frontmatterProperties) !== JSON.stringify(this.initialSettingsSnapshot.frontmatterProperties) || currentSnapshot.defaultContentTypeId !== this.initialSettingsSnapshot.defaultContentTypeId || currentSnapshot.preset !== this.initialSettingsSnapshot.preset || currentSnapshot.enableEditingToolbar !== this.initialSettingsSnapshot.enableEditingToolbar || JSON.stringify(currentSnapshot.enabledPlugins) !== JSON.stringify(this.initialSettingsSnapshot.enabledPlugins) || JSON.stringify(currentSnapshot.disabledPlugins) !== JSON.stringify(this.initialSettingsSnapshot.disabledPlugins) || currentSnapshot.theme !== this.initialSettingsSnapshot.theme || JSON.stringify(currentSnapshot.basesCMSConfig) !== JSON.stringify(this.initialSettingsSnapshot.basesCMSConfig) || JSON.stringify(currentSnapshot.astroComposerConfig) !== JSON.stringify(this.initialSettingsSnapshot.astroComposerConfig) || JSON.stringify(currentSnapshot.seoConfig) !== JSON.stringify(this.initialSettingsSnapshot.seoConfig) || JSON.stringify(currentSnapshot.propertyOverFileName) !== JSON.stringify(this.initialSettingsSnapshot.propertyOverFileName) || JSON.stringify(currentSnapshot.imageManager) !== JSON.stringify(this.initialSettingsSnapshot.imageManager) || JSON.stringify(currentSnapshot.homeBase) !== JSON.stringify(this.initialSettingsSnapshot.homeBase);
  }
  getState() {
    return this.stateManager.getState();
  }
  // Callback to save state to plugin settings (kept for backward compatibility)
  setSaveCallback(callback) {
    console.warn("setSaveCallback is deprecated - state is now managed automatically");
  }
};

// src/ui/HealthCheckModal.ts
var import_obsidian24 = require("obsidian");
init_ProjectRootResolver();
var HealthCheckModal = class extends import_obsidian24.Modal {
  constructor(app, plugin) {
    super(app);
    this.results = [];
    this.plugin = plugin;
  }
  async onOpen() {
    const { contentEl } = this;
    contentEl.empty();
    contentEl.addClass("vault-cms-health-check");
    contentEl.createEl("h2", { text: "Vault CMS Health Check" });
    await this.runHealthChecks();
    this.displayResults(contentEl);
    const footer = contentEl.createDiv({ cls: "health-check-footer" });
    const closeBtn = footer.createEl("button", {
      text: "Close",
      cls: "mod-cta"
    });
    closeBtn.addEventListener("click", () => this.close());
  }
  async runHealthChecks() {
    this.results = [];
    await this.checkCompanionPluginsInstalled();
    await this.checkCompanionPluginsEnabled();
    await this.checkAstroProjectDetection();
    await this.checkPluginConfiguration();
    await this.checkGitIntegration();
  }
  async checkCompanionPluginsInstalled() {
    var _a;
    const requiredPlugins = [
      { id: "astro-composer", name: "Astro Composer" },
      { id: "bases-cms", name: "Bases CMS" },
      { id: "home-base", name: "Home Base" },
      { id: "seo", name: "SEO" }
    ];
    const optionalPlugins = [
      { id: "property-over-file-name", name: "Property Over File Name" },
      { id: "image-manager", name: "Image Manager" }
    ];
    const checks = [];
    const plugins = ((_a = this.app.plugins) == null ? void 0 : _a.plugins) || {};
    for (const plugin of requiredPlugins) {
      const isInstalled = !!plugins[plugin.id];
      checks.push({
        name: `${plugin.name} installed`,
        status: isInstalled ? "pass" : "fail",
        message: isInstalled ? void 0 : "Plugin not installed"
      });
    }
    for (const plugin of optionalPlugins) {
      const isInstalled = !!plugins[plugin.id];
      checks.push({
        name: `${plugin.name} installed`,
        status: isInstalled ? "pass" : "warning",
        message: isInstalled ? void 0 : "Optional plugin not installed"
      });
    }
    this.results.push({
      category: "Plugin Installation",
      checks
    });
  }
  async checkCompanionPluginsEnabled() {
    const requiredPlugins = [
      { id: "astro-composer", name: "Astro Composer" },
      { id: "bases-cms", name: "Bases CMS" },
      { id: "home-base", name: "Home Base" },
      { id: "seo", name: "SEO" }
    ];
    const checks = [];
    const pluginsAPI = this.app.plugins;
    const enabledPlugins = (pluginsAPI == null ? void 0 : pluginsAPI.enabledPlugins) || /* @__PURE__ */ new Set();
    for (const plugin of requiredPlugins) {
      const isEnabled = enabledPlugins.has(plugin.id);
      checks.push({
        name: `${plugin.name} enabled`,
        status: isEnabled ? "pass" : "fail",
        message: isEnabled ? void 0 : "Plugin is installed but not enabled"
      });
    }
    this.results.push({
      category: "Plugin Status",
      checks
    });
  }
  async checkAstroProjectDetection() {
    const checks = [];
    const hasProjectRoot = !!this.plugin.settings.projectRoot;
    const hasConfigFile = !!this.plugin.settings.configFilePath;
    checks.push({
      name: "Project root configured",
      status: hasProjectRoot ? "pass" : "fail",
      message: hasProjectRoot ? this.plugin.settings.projectRoot : "Project root not set"
    });
    checks.push({
      name: "Config file detected",
      status: hasConfigFile ? "pass" : "fail",
      message: hasConfigFile ? this.plugin.settings.configFilePath : "Config file not found"
    });
    if (hasProjectRoot && hasConfigFile) {
      const detector = new ProjectDetector(this.app);
      try {
        const detection = await detector.detectProject();
        checks.push({
          name: "Project structure valid",
          status: detection ? "pass" : "warning",
          message: detection ? `Found ${detection.configFilePath}` : "Could not validate project structure"
        });
      } catch (error) {
        checks.push({
          name: "Project structure valid",
          status: "warning",
          message: `Error: ${error instanceof Error ? error.message : String(error)}`
        });
      }
    }
    const hasContentTypes = this.plugin.settings.contentTypes && this.plugin.settings.contentTypes.length > 0;
    checks.push({
      name: "Content types configured",
      status: hasContentTypes ? "pass" : "warning",
      message: hasContentTypes ? `${this.plugin.settings.contentTypes.length} content type(s) configured` : "No content types configured"
    });
    this.results.push({
      category: "Astro Project",
      checks
    });
  }
  async checkPluginConfiguration() {
    var _a, _b, _c, _d, _e, _f, _g;
    const checks = [];
    const configDir = this.app.vault.configDir;
    let astroComposerContentTypes = 0;
    try {
      const plugins = this.app.plugins;
      const astroComposerPlugin = (_a = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _a["astro-composer"];
      if ((_b = astroComposerPlugin == null ? void 0 : astroComposerPlugin.settings) == null ? void 0 : _b.contentTypes) {
        astroComposerContentTypes = astroComposerPlugin.settings.contentTypes.length;
      } else {
        const astroComposerPath = `${configDir}/plugins/astro-composer/data.json`;
        const astroFile = this.app.vault.getAbstractFileByPath(astroComposerPath);
        if (astroFile instanceof import_obsidian24.TFile) {
          const content = await this.app.vault.read(astroFile);
          const data = JSON.parse(content);
          astroComposerContentTypes = ((_c = data.contentTypes) == null ? void 0 : _c.length) || 0;
        }
      }
    } catch (e) {
    }
    checks.push({
      name: "Astro Composer configured",
      status: astroComposerContentTypes > 0 ? "pass" : "warning",
      message: astroComposerContentTypes > 0 ? `${astroComposerContentTypes} content type(s)` : "No content types configured"
    });
    let basesConfigured = false;
    let basesMessage = "No base file found";
    try {
      const configurator = new BasesCMSConfigurator(this.app);
      const baseFilePath = await configurator.resolveBaseFilePath();
      if (await this.app.vault.adapter.exists(baseFilePath)) {
        basesConfigured = true;
        basesMessage = `${baseFilePath} found`;
      }
    } catch (e) {
    }
    checks.push({
      name: "Bases CMS configured",
      status: basesConfigured ? "pass" : "warning",
      message: basesMessage
    });
    let seoScanDirs = "";
    try {
      const plugins = this.app.plugins;
      const seoPlugin = (_d = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _d["seo"];
      if ((_e = seoPlugin == null ? void 0 : seoPlugin.settings) == null ? void 0 : _e.scanDirectories) {
        seoScanDirs = seoPlugin.settings.scanDirectories;
      } else {
        const seoPath = `${configDir}/plugins/seo/data.json`;
        const seoFile = this.app.vault.getAbstractFileByPath(seoPath);
        if (seoFile instanceof import_obsidian24.TFile) {
          const content = await this.app.vault.read(seoFile);
          const data = JSON.parse(content);
          seoScanDirs = data.scanDirectories || "";
        }
      }
    } catch (e) {
    }
    checks.push({
      name: "SEO plugin configured",
      status: seoScanDirs.length > 0 ? "pass" : "warning",
      message: seoScanDirs.length > 0 ? `Scanning: ${seoScanDirs}` : "No scan directories configured"
    });
    const hasDefaultContentType = !!this.plugin.settings.defaultContentTypeId;
    let defaultContentTypeName = this.plugin.settings.defaultContentTypeId || "";
    if (hasDefaultContentType) {
      try {
        const plugins = this.app.plugins;
        const astroComposerPlugin = (_f = plugins == null ? void 0 : plugins.plugins) == null ? void 0 : _f["astro-composer"];
        const contentTypes = (_g = astroComposerPlugin == null ? void 0 : astroComposerPlugin.settings) == null ? void 0 : _g.contentTypes;
        if (contentTypes) {
          const matchingType = contentTypes.find((ct) => ct.id === this.plugin.settings.defaultContentTypeId);
          if (matchingType == null ? void 0 : matchingType.name) {
            defaultContentTypeName = matchingType.name;
          }
        }
      } catch (e) {
      }
    }
    checks.push({
      name: "Default content type set",
      status: hasDefaultContentType ? "pass" : "warning",
      message: hasDefaultContentType ? defaultContentTypeName : "No default content type"
    });
    this.results.push({
      category: "Plugin Configuration",
      checks
    });
  }
  async checkGitIntegration() {
    var _a;
    const checks = [];
    const { gitConfig, projectRoot: relativeRoot } = this.plugin.settings;
    const projectRoot = resolveProjectRoot2(this.app, relativeRoot);
    if (projectRoot) {
      const { GitManager: GitManager2 } = await Promise.resolve().then(() => (init_GitManager(), GitManager_exports));
      const isRepo = await GitManager2.isRepo(projectRoot);
      const remoteUrl = isRepo ? await GitManager2.getRemoteUrl(projectRoot) : null;
      checks.push({
        name: "Git repository initialized",
        status: isRepo ? "pass" : "fail",
        message: isRepo ? "Repository detected at project root" : "No repository found at project root"
      });
      if (isRepo) {
        const isConfigured = gitConfig.enabled || !!remoteUrl;
        checks.push({
          name: "Git integration status",
          status: isConfigured ? "pass" : "warning",
          message: remoteUrl ? `Connected to ${remoteUrl}` : gitConfig.enabled ? "Integration active" : "Not configured (Optional)"
        });
        const savedSecret = (_a = this.app.secretStorage) == null ? void 0 : _a.getSecret("vault-cms-github-pat");
        const hasPat = !!savedSecret;
        if (gitConfig.enabled) {
          checks.push({
            name: "GitHub PAT configured",
            status: hasPat ? "pass" : "warning",
            message: hasPat ? "Token present" : "No token found in settings"
          });
        }
      }
    } else {
      checks.push({
        name: "Git repository check",
        status: "fail",
        message: relativeRoot ? "Project root path could not be resolved" : "Project root not configured"
      });
    }
    this.results.push({
      category: "Git Integration",
      checks
    });
  }
  displayResults(container) {
    const resultsContainer = container.createDiv({ cls: "health-check-results" });
    for (const result of this.results) {
      const categorySection = resultsContainer.createDiv({ cls: "health-check-category" });
      categorySection.createEl("h3", { text: result.category });
      const checksList = categorySection.createDiv({ cls: "health-check-list" });
      for (const check of result.checks) {
        const checkItem = checksList.createDiv({ cls: "health-check-item" });
        const statusIcon = checkItem.createSpan({ cls: "health-check-icon" });
        if (check.status === "pass") {
          (0, import_obsidian24.setIcon)(statusIcon, "lucide-check-circle-2");
          statusIcon.addClass("health-check-pass");
        } else if (check.status === "fail") {
          (0, import_obsidian24.setIcon)(statusIcon, "lucide-alert-circle");
          statusIcon.addClass("health-check-fail");
        } else {
          (0, import_obsidian24.setIcon)(statusIcon, "lucide-help-circle");
          statusIcon.addClass("health-check-warning");
        }
        const checkName = checkItem.createSpan({
          text: check.name,
          cls: "health-check-name"
        });
        if (check.message) {
          const checkMessage = checkItem.createDiv({
            text: check.message,
            cls: "health-check-message"
          });
        }
      }
    }
    this.addStyles(container);
  }
  addStyles(container) {
    const style = container.createEl("style");
    style.textContent = `
			.vault-cms-health-check {
				padding: 20px;
			}

			.health-check-results {
				margin: 20px 0;
			}

			.health-check-category {
				margin-bottom: 30px;
			}

			.health-check-category h3 {
				margin-bottom: 10px;
				border-bottom: 1px solid var(--background-modifier-border);
				padding-bottom: 5px;
			}

			.health-check-list {
				display: flex;
				flex-direction: column;
				gap: 10px;
			}

			.health-check-item {
				display: flex;
				align-items: flex-start;
				gap: 10px;
				padding: 8px;
				background: var(--background-secondary);
				border-radius: 4px;
			}

			.health-check-icon {
				font-size: 18px;
				font-weight: bold;
				min-width: 24px;
				text-align: center;
			}

			.health-check-pass {
				color: var(--text-success);
			}

			.health-check-fail {
				color: var(--text-error);
			}

			.health-check-warning {
				color: var(--text-warning);
			}

			.health-check-icon svg {
				width: 18px;
				height: 18px;
				display: block;
			}

			.health-check-icon {
				display: flex;
				align-items: center;
				justify-content: center;
				min-width: 24px;
				height: 24px;
			}

			.health-check-name {
				flex: 1;
				font-weight: 500;
			}

			.health-check-message {
				font-size: 0.9em;
				color: var(--text-muted);
				margin-left: 34px;
				margin-top: 4px;
			}

			.health-check-footer {
				display: flex;
				justify-content: flex-end;
				margin-top: 20px;
				padding-top: 15px;
				border-top: 1px solid var(--background-modifier-border);
			}
		`;
  }
  onClose() {
    const { contentEl } = this;
    contentEl.empty();
  }
};

// src/utils/PresetManager.ts
var import_obsidian26 = require("obsidian");

// src/ui/ApplyPresetModal.ts
var import_obsidian25 = require("obsidian");
var ApplyPresetModal = class extends import_obsidian25.Modal {
  constructor(app, backupPath, onConfirm) {
    super(app);
    this.backupPath = backupPath;
    this.onConfirm = onConfirm;
  }
  onOpen() {
    const { contentEl } = this;
    contentEl.empty();
    contentEl.createEl("h2", { text: "Preset applied successfully" });
    contentEl.createEl("p", { text: "The preset has been applied successfully. You need to reload Obsidian for all changes to take effect." });
    contentEl.createEl("p", { text: `A backup of your original configuration folder was created at: ${this.backupPath}` });
    new import_obsidian25.Setting(contentEl).setName("Delete backup and reload").setDesc('Remove the backup folder and reload Obsidian. This is the recommended "clean" option.').addButton((button) => button.setButtonText("Delete and reload").setCta().onClick(() => {
      this.close();
      this.onConfirm(true);
    }));
    new import_obsidian25.Setting(contentEl).setName("Keep backup and reload").setDesc("Keep the backup folder for safety and reload Obsidian.").addButton((button) => button.setButtonText("Keep and reload").onClick(() => {
      this.close();
      this.onConfirm(false);
    }));
  }
  onClose() {
    const { contentEl } = this;
    contentEl.empty();
  }
};

// src/utils/PresetManager.ts
var PresetManager = class {
  constructor(app) {
    this.app = app;
  }
  async applyPreset(repo, presetName) {
    if (!repo || !presetName) {
      new import_obsidian26.Notice("Please configure both repository and preset name in settings.");
      return;
    }
    try {
      new import_obsidian26.Notice(`Fetching preset "${presetName}" from ${repo}...`);
      const files = await this.fetchPresetFilesRecursive(repo, presetName);
      if (files.length === 0) {
        new import_obsidian26.Notice(`No files found for preset "${presetName}" in repo ${repo}.`);
        return;
      }
      new import_obsidian26.Notice("Backing up configuration folder...");
      const backupPath = await this.backupObsidianFolder();
      new import_obsidian26.Notice(`Downloading and applying ${files.length} files...`);
      let successCount = 0;
      for (const file of files) {
        if (file.download_url) {
          const relativePath = file.path.substring(presetName.length + 1);
          try {
            await this.downloadAndWriteFile(file.download_url, relativePath);
            successCount++;
          } catch (e) {
            console.error(`Failed to download ${relativePath}:`, e);
          }
        }
      }
      new import_obsidian26.Notice(`Applied ${successCount} files.`);
      new ApplyPresetModal(this.app, backupPath, (deleteBackup) => {
        void (async () => {
          if (deleteBackup) {
            try {
              await this.app.vault.adapter.rmdir(backupPath, true);
              new import_obsidian26.Notice("Backup deleted.");
            } catch (e) {
              console.error("Failed to delete backup:", e);
              new import_obsidian26.Notice("Failed to delete backup folder. You may need to remove it manually.");
            }
          }
          const appWithCommands = this.app;
          if (appWithCommands.commands && typeof appWithCommands.commands.executeCommandById === "function") {
            appWithCommands.commands.executeCommandById("app:reload");
          }
        })();
      }).open();
    } catch (error) {
      console.error("Failed to apply preset:", error);
      const message = error instanceof Error ? error.message : String(error);
      new import_obsidian26.Notice(`Failed to apply preset: ${message}`);
    }
  }
  async fetchPresetFilesRecursive(repo, path13) {
    const url = `https://api.github.com/repos/${repo}/contents/${path13}`;
    try {
      const response = await (0, import_obsidian26.requestUrl)({ url });
      if (response.status !== 200) {
        throw new Error(`GitHub API returned status ${response.status}`);
      }
      const items = response.json;
      let allFiles = [];
      for (const item of items) {
        if (item.type === "dir") {
          const subFiles = await this.fetchPresetFilesRecursive(repo, item.path);
          allFiles = allFiles.concat(subFiles);
        } else if (item.type === "file") {
          allFiles.push(item);
        }
      }
      return allFiles;
    } catch (e) {
      if (e && typeof e === "object" && "status" in e && e.status === 404) {
        throw new Error(`Preset folder "${path13}" not found in repository "${repo}".`);
      }
      throw e;
    }
  }
  async backupObsidianFolder() {
    const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").split("T")[0] + "-" + Math.floor(Date.now() / 1e3);
    const configDir = this.app.vault.configDir;
    const backupPath = `${configDir}_backup_${timestamp2}`;
    const adapter = this.app.vault.adapter;
    await adapter.mkdir(backupPath);
    await this.copyRecursive(configDir, `${backupPath}/${configDir}`);
    return backupPath;
  }
  async copyRecursive(source, destination) {
    const adapter = this.app.vault.adapter;
    if (!await adapter.exists(source)) {
      return;
    }
    const stats = await adapter.list(source);
    if (!await adapter.exists(destination)) {
      await adapter.mkdir(destination);
    }
    for (const file of stats.files) {
      const fileName = file.split("/").pop();
      if (fileName) {
        const destFile = destination + "/" + fileName;
        try {
          await adapter.copy(file, destFile);
        } catch (e) {
          console.error(`Failed to copy file ${file} to ${destFile}:`, e);
        }
      }
    }
    for (const folder of stats.folders) {
      const folderName = folder.split("/").pop();
      if (folderName) {
        const destFolder = destination + "/" + folderName;
        await this.copyRecursive(folder, destFolder);
      }
    }
  }
  async downloadAndWriteFile(url, path13) {
    const adapter = this.app.vault.adapter;
    const response = await (0, import_obsidian26.requestUrl)({ url });
    if (response.status !== 200) {
      throw new Error(`Failed to download ${path13} from ${url}`);
    }
    const parts = path13.split("/");
    if (parts.length > 1) {
      for (let i = 1; i < parts.length; i++) {
        const dir = parts.slice(0, i).join("/");
        if (!await adapter.exists(dir)) {
          await adapter.mkdir(dir);
        }
      }
    }
    await adapter.writeBinary(path13, response.arrayBuffer);
  }
};

// src/ui/SettingsTab.ts
var SettingsTab = class extends import_obsidian27.PluginSettingTab {
  constructor(app, plugin) {
    super(app, plugin);
    this.icon = "lucide-vault";
    this.plugin = plugin;
  }
  display() {
    const { containerEl } = this;
    containerEl.empty();
    this.contentEl = containerEl.createDiv("vault-cms-settings-container");
    void this.render();
  }
  async render() {
    if (!this.contentEl) return;
    this.contentEl.empty();
    const generalGroup = new import_obsidian27.SettingGroup(this.contentEl);
    generalGroup.addSetting((setting) => {
      setting.setName("Open setup wizard").setDesc("Launch the setup wizard").addButton((button) => {
        button.setButtonText("Open wizard").setCta().onClick(() => {
          new SetupWizardModal(this.app, this.plugin.settings, this.plugin).open();
        });
      });
    });
    generalGroup.addSetting((setting) => {
      setting.setName("Run wizard on startup").setDesc("Automatically open the wizard when the plugin loads").addToggle((toggle) => {
        toggle.setValue(this.plugin.settings.runWizardOnStartup).onChange(async (value) => {
          this.plugin.settings.runWizardOnStartup = value;
          await this.plugin.saveSettings();
        });
      });
    });
    generalGroup.addSetting((setting) => {
      setting.setName("Health check").setDesc("Check plugin installation and configuration status").addButton((button) => {
        button.setButtonText("Run health check").onClick(() => {
          new HealthCheckModal(this.app, this.plugin).open();
        });
      });
    });
    const presetGroup = new import_obsidian27.SettingGroup(this.contentEl).setHeading("Preset configuration");
    presetGroup.addSetting((setting) => {
      setting.setName("Preset folder name").setDesc("Folder name in the repository").addText((text) => {
        text.setPlaceholder("Example: starlight").setValue(this.plugin.settings.presetName).onChange(async (value) => {
          this.plugin.settings.presetName = value;
          await this.plugin.saveSettings();
        });
      });
    });
    presetGroup.addSetting((setting) => {
      setting.setName("Presets repository").setDesc("GitHub repository containing the presets").addText((text) => {
        text.setPlaceholder("Example: owner/repo").setValue(this.plugin.settings.presetsRepo).onChange(async (value) => {
          this.plugin.settings.presetsRepo = value;
          await this.plugin.saveSettings();
        });
      });
    });
    presetGroup.addSetting((setting) => {
      setting.setName("Download and apply preset").setDesc("Download the specified preset and apply it to your vault").addButton((button) => {
        button.setButtonText("Apply preset").onClick(async () => {
          const manager = new PresetManager(this.app);
          await manager.applyPreset(this.plugin.settings.presetsRepo, this.plugin.settings.presetName);
        });
      });
    });
    const gitGroup = new import_obsidian27.SettingGroup(this.contentEl).setHeading("Git configuration");
    let isFullyConfigured = false;
    if (this.plugin.settings.projectRoot && this.plugin.settings.projectRoot.trim() !== "") {
      try {
        const { GitManager: GitManager2 } = await Promise.resolve().then(() => (init_GitManager(), GitManager_exports));
        const { resolveProjectRoot: resolveProjectRoot3 } = await Promise.resolve().then(() => (init_ProjectRootResolver(), ProjectRootResolver_exports));
        const projectRoot = resolveProjectRoot3(this.app, this.plugin.settings.projectRoot);
        if (!projectRoot) throw new Error("Could not resolve project root");
        const isRepo = await GitManager2.isRepo(projectRoot);
        const remoteUrl = isRepo ? await GitManager2.getRemoteUrl(projectRoot) : null;
        isFullyConfigured = isRepo && !!remoteUrl;
        gitGroup.addSetting((setting) => {
          setting.setName("Local repository status").setDesc(isRepo ? "Git is initialized at project root." : "Git is NOT initialized at project root.");
          const statusIcon = setting.controlEl.createSpan({
            cls: isRepo ? "git-status-icon-ok" : "git-status-icon-warn",
            attr: { style: `margin-left: 10px; color: ${isRepo ? "var(--text-success)" : "var(--text-warning)"};` }
          });
          statusIcon.setText(isRepo ? "\u2713 Detected" : "\u26A0 Missing");
        });
        gitGroup.addSetting((setting) => {
          setting.setName("Project root path").setDesc("Direct path being checked for Git").addText((text) => {
            text.setValue(projectRoot).setDisabled(true);
          });
        });
        if (remoteUrl) {
          gitGroup.addSetting((setting) => {
            setting.setName("Remote URL").setDesc("Connected GitHub repository").addText((text) => {
              text.setValue(remoteUrl).setDisabled(true);
            });
          });
        }
      } catch (error) {
        console.warn("SettingsTab: Failed to check Git status:", error);
      }
    }
    if (!isFullyConfigured) {
      gitGroup.addSetting((setting) => {
        setting.setName("Deployment and Git setup").setDesc("Choose a deployment platform and connect to GitHub.").addButton((button) => {
          button.setButtonText("Setup...").onClick(() => {
            const modal = new SetupWizardModal(this.app, { currentStep: 7 }, this.plugin);
            modal.open();
          });
        });
      });
    }
    const optimizationGroup = new import_obsidian27.SettingGroup(this.contentEl).setHeading("Project optimization (optional)");
    if (!this.plugin.settings.projectRoot) {
      optimizationGroup.addSetting((setting) => {
        setting.setName("Project not detected").setDesc("Complete the setup wizard first to detect your Astro project before configuring optimizations.");
      });
      return;
    }
    const wizardState = {
      ...this.plugin.settings,
      currentStep: 0,
      projectDetection: {
        projectRoot: this.plugin.settings.projectRoot,
        configFilePath: this.plugin.settings.configFilePath,
        vaultLocation: "content"
      }
    };
    this.optimizer = new ProjectOptimizer(this.app, wizardState);
    const status = await this.optimizer.getStatus();
    optimizationGroup.addSetting((setting) => {
      this.gitSetting = setting;
      this.updateGitSetting(status.gitIgnoreStatus);
    });
    optimizationGroup.addSetting((setting) => {
      this.viteSetting = setting;
      this.updateViteSetting(status.viteIgnoreStatus);
    });
    if (status.gitHooksStatus !== "none") {
      optimizationGroup.addSetting((setting) => {
        this.hooksSetting = setting;
        this.updateHooksSetting(status.gitHooksStatus);
      });
    }
  }
  updateGitSetting(status) {
    this.gitSetting.setName("Ignore in Git").setDesc("Add workspace files to Git ignore").clear();
    this.gitSetting.addButton((button) => {
      button.setButtonText(status === "configured" ? "Re-configure" : "Configure").onClick(async () => {
        try {
          const success = await this.optimizer.configureGitIgnore();
          if (success) {
            this.plugin.settings.ignoreConfig.gitIgnoreConfigured = true;
            await this.plugin.saveSettings();
            new import_obsidian27.Notice("Git ignore updated");
          } else {
            new import_obsidian27.Notice("Could not configure Git ignore: project root not detected");
          }
          const newStatus = await this.optimizer.getStatus();
          this.updateGitSetting(newStatus.gitIgnoreStatus);
        } catch (error) {
          new import_obsidian27.Notice(`Failed to update Git ignore: ${error instanceof Error ? error.message : String(error)}`);
        }
      });
    });
    this.optimizer.renderStatus(this.gitSetting.controlEl, status);
  }
  updateViteSetting(status) {
    this.viteSetting.setName("Ignore workspace and Home Base folders in Vite").setDesc("Configure Vite to ignore Obsidian and Home Base folders.").clear();
    this.viteSetting.addButton((button) => {
      button.setButtonText(status === "configured" ? "Re-configure" : "Configure").onClick(async () => {
        try {
          const success = await this.optimizer.configureViteIgnore();
          if (success) {
            this.plugin.settings.ignoreConfig.viteIgnoreConfigured = true;
            await this.plugin.saveSettings();
            new import_obsidian27.Notice("Vite optimization applied");
          } else {
            new import_obsidian27.Notice("Could not configure Vite: project root not detected");
          }
          const newStatus = await this.optimizer.getStatus();
          this.updateViteSetting(newStatus.viteIgnoreStatus);
        } catch (error) {
          new import_obsidian27.Notice(`Failed to update Vite config: ${error instanceof Error ? error.message : String(error)}`);
        }
      });
    });
    this.optimizer.renderStatus(this.viteSetting.controlEl, status);
  }
  updateHooksSetting(status) {
    this.hooksSetting.setName("Neutralize developer git hooks").setDesc("This project has git hooks (like husky or commitlint) that can block publishing from Obsidian. Disable so commits can happen easily from Obsidian.").clear();
    if (status === "detected") {
      this.hooksSetting.addButton((button) => {
        button.setButtonText("Neutralize").setCta().onClick(async () => {
          try {
            this.optimizer.neutralizeGitHooks();
            new import_obsidian27.Notice("Git hooks neutralized");
            const newStatus = await this.optimizer.getStatus();
            this.updateHooksSetting(newStatus.gitHooksStatus);
          } catch (error) {
            new import_obsidian27.Notice(`Failed to neutralize git hooks: ${error instanceof Error ? error.message : String(error)}`);
          }
        });
      });
    }
    this.optimizer.renderStatus(this.hooksSetting.controlEl, status === "neutralized" ? "configured" : "not-configured");
  }
};

// src/commands/index.ts
function registerCommands(plugin) {
  plugin.addCommand({
    id: "open-wizard",
    name: "Open setup wizard",
    callback: () => {
      const wizard = new SetupWizardModal(plugin.app, plugin.settings, plugin);
      wizard.open();
    }
  });
  plugin.addCommand({
    id: "health-check",
    name: "Check Vault CMS setup",
    callback: () => {
      const healthCheck = new HealthCheckModal(plugin.app, plugin);
      healthCheck.open();
    }
  });
  plugin.addCommand({
    id: "download-apply-preset",
    name: "Download and apply preset",
    callback: async () => {
      const manager = new PresetManager(plugin.app);
      await manager.applyPreset(plugin.settings.presetsRepo, plugin.settings.presetName);
    }
  });
}

// src/main.ts
var path12 = __toESM(require("path"), 1);
var VaultCMSPlugin = class extends import_obsidian28.Plugin {
  async onload() {
    await this.loadSettings();
    if (this.settings.projectRoot && path12.isAbsolute(this.settings.projectRoot)) {
      const { getVaultPath: getVaultPath2 } = await Promise.resolve().then(() => (init_VaultPathHelper(), VaultPathHelper_exports));
      const vaultPath = getVaultPath2(this.app);
      if (vaultPath) {
        const relativePath = path12.relative(vaultPath, this.settings.projectRoot).split(path12.sep).join("/") || ".";
        console.debug(`[Vault CMS] Migrating absolute projectRoot to relative: ${this.settings.projectRoot} -> ${relativePath}`);
        this.settings.projectRoot = relativePath;
        if (this.settings.configFilePath && path12.isAbsolute(this.settings.configFilePath)) {
          const relativeConfig = path12.relative(vaultPath, this.settings.configFilePath).split(path12.sep).join("/");
          console.debug(`[Vault CMS] Migrating absolute configFilePath to relative: ${this.settings.configFilePath} -> ${relativeConfig}`);
          this.settings.configFilePath = relativeConfig;
        }
        await this.saveSettings();
      }
    }
    registerCommands(this);
    this.addSettingTab(new SettingsTab(this.app, this));
    if (this.settings.runWizardOnStartup) {
      this.app.workspace.onLayoutReady(() => {
        this.startupTimeoutId = window.setTimeout(() => {
          void (async () => {
            await this.loadSettings();
            if (this.settings.runWizardOnStartup) {
              const wizard = new SetupWizardModal(this.app, void 0, this);
              wizard.open();
            }
          })();
        }, 2e3);
      });
    }
  }
  onunload() {
    if (this.startupTimeoutId) {
      window.clearTimeout(this.startupTimeoutId);
    }
  }
  async loadSettings() {
    this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
  }
  async saveSettings() {
    await this.saveData(this.settings);
  }
  /**
   * Public API: Resolve an absolute image path (e.g. /images/blog/1.jpg)
   * against the Astro project's public/ folder.
   * Returns a file:// resource URL if the file exists, null otherwise.
   * Other plugins (Image Manager, Bases CMS) can call this via:
   *   app.plugins.plugins['vault-cms']?.resolvePublicPath('/images/blog/1.jpg')
   */
  resolvePublicPath(absolutePath) {
    if (!this.settings.resolvePublicImages || !this.settings.projectRoot) return null;
    if (!absolutePath.startsWith("/")) return null;
    try {
      const fs7 = require("fs");
      const pathModule = require("path");
      const { Platform } = require("obsidian");
      const adapter = this.app.vault.adapter;
      const vaultPath = String(adapter.basePath || adapter.path || "");
      if (!vaultPath) return null;
      const projectRoot = pathModule.resolve(vaultPath, this.settings.projectRoot);
      const relativePath = absolutePath.slice(1);
      const candidates = [
        pathModule.join(projectRoot, "public", relativePath),
        pathModule.join(projectRoot, "src", "assets", relativePath),
        pathModule.join(projectRoot, "static", relativePath),
        pathModule.join(projectRoot, "assets", relativePath)
      ];
      for (const candidate of candidates) {
        if (fs7.existsSync(candidate)) {
          return Platform.resourcePathPrefix + candidate.replace(/\\/g, "/");
        }
      }
      return null;
    } catch (e) {
      return null;
    }
  }
};
//# sourceMappingURL=data:application/json;base64,[encoded data, 1381508 characters]
