import Slugger from "github-slugger";
import { visit } from "unist-util-visit";
import { InvalidAstroDataError, safelyGetAstroData } from "./frontmatter-injection.js";
const rawNodeTypes = /* @__PURE__ */ new Set(["text", "raw", "mdxTextExpression"]);
const codeTagNames = /* @__PURE__ */ new Set(["code", "pre"]);
function rehypeHeadingIds() {
  return function(tree, file) {
    const headings = [];
    const slugger = new Slugger();
    const isMDX = isMDXFile(file);
    const astroData = safelyGetAstroData(file.data);
    visit(tree, (node) => {
      if (node.type !== "element") return;
      const { tagName } = node;
      if (tagName[0] !== "h") return;
      const [, level] = /h([0-6])/.exec(tagName) ?? [];
      if (!level) return;
      const depth = Number.parseInt(level);
      let text = "";
      visit(node, (child, __, parent) => {
        if (child.type === "element" || parent == null) {
          return;
        }
        if (child.type === "raw") {
          if (/^\n?<.*>\n?$/.test(child.value)) {
            return;
          }
        }
        if (rawNodeTypes.has(child.type)) {
          if (isMDX || codeTagNames.has(parent.tagName)) {
            let value = child.value;
            if (isMdxTextExpression(child) && !(astroData instanceof InvalidAstroDataError)) {
              const frontmatterPath = getMdxFrontmatterVariablePath(child);
              if (Array.isArray(frontmatterPath) && frontmatterPath.length > 0) {
                const frontmatterValue = getMdxFrontmatterVariableValue(astroData, frontmatterPath);
                if (typeof frontmatterValue === "string") {
                  value = frontmatterValue;
                }
              }
            }
            text += value;
          } else {
            text += child.value.replace(/\{/g, "${");
          }
        }
      });
      node.properties = node.properties || {};
      if (typeof node.properties.id !== "string") {
        let slug = slugger.slug(text);
        if (slug.endsWith("-")) slug = slug.slice(0, -1);
        node.properties.id = slug;
      }
      headings.push({ depth, slug: node.properties.id, text });
    });
    file.data.__astroHeadings = headings;
  };
}
function isMDXFile(file) {
  return Boolean(file.history[0]?.endsWith(".mdx"));
}
function getMdxFrontmatterVariablePath(node) {
  if (!node.data?.estree || node.data.estree.body.length !== 1) return new Error();
  const statement = node.data.estree.body[0];
  if (statement?.type !== "ExpressionStatement" || statement.expression.type !== "MemberExpression")
    return new Error();
  let expression = statement.expression;
  const expressionPath = [];
  while (expression.type === "MemberExpression" && expression.property.type === (expression.computed ? "Literal" : "Identifier")) {
    expressionPath.push(
      expression.property.type === "Literal" ? String(expression.property.value) : expression.property.name
    );
    expression = expression.object;
  }
  if (expression.type !== "Identifier" || expression.name !== "frontmatter") return new Error();
  return expressionPath.reverse();
}
function getMdxFrontmatterVariableValue(astroData, path) {
  let value = astroData.frontmatter;
  for (const key of path) {
    if (!value[key]) return void 0;
    value = value[key];
  }
  return value;
}
function isMdxTextExpression(node) {
  return node.type === "mdxTextExpression";
}
export {
  rehypeHeadingIds
};
