// src/plugin/transform.ts
import MarkdownIt from "markdown-it";
import katex from "katex";

// src/plugin/utils.ts
function hidden(box, field, value) {
  if (!(field in box)) {
    Object.defineProperty(box, field, {
      enumerable: false,
      value
    });
  }
  return box;
}

// src/plugin/transform.ts
function isValidDelim(state, pos) {
  const result = {
    canOpen: true,
    canClose: true
  };
  const max = state.posMax;
  const prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
  const nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;
  if (prevChar === 32 || prevChar === 9 || nextChar >= 48 && nextChar <= 57) {
    result.canClose = false;
  }
  if (nextChar === 32 || nextChar === 9) {
    result.canOpen = false;
  }
  return result;
}
var mathInline = (state, silent) => {
  if (state.src[state.pos] !== "$") {
    return false;
  }
  let res = isValidDelim(state, state.pos);
  if (!res.canOpen) {
    if (!silent) {
      state.pending += "$";
    }
    state.pos += 1;
    return true;
  }
  const start = state.pos + 1;
  let match = start;
  while ((match = state.src.indexOf("$", match)) !== -1) {
    let pos = match - 1;
    while (state.src[pos] === "\\") {
      pos -= 1;
    }
    if ((match - pos) % 2 === 1) {
      break;
    }
    match += 1;
  }
  if (match === -1) {
    if (!silent) {
      state.pending += "$";
    }
    state.pos = start;
    return true;
  }
  if (match - start === 0) {
    if (!silent) {
      state.pending += "$$";
    }
    state.pos = start + 1;
    return true;
  }
  res = isValidDelim(state, match);
  if (!res.canClose) {
    if (!silent) {
      state.pending += "$";
    }
    state.pos = start;
    return true;
  }
  if (!silent) {
    const token = state.push("math_inline", "math", 0);
    token.markup = "$";
    token.content = state.src.slice(start, match);
  }
  state.pos = match + 1;
  return true;
};
var mathBlock = (state, start, end, silent) => {
  let found = false;
  let pos = state.bMarks[start] + state.tShift[start];
  let max = state.eMarks[start];
  if (pos + 2 > max) {
    return false;
  }
  if (state.src.slice(pos, pos + 2) !== "$$") {
    return false;
  }
  pos += 2;
  let firstLine = state.src.slice(pos, max);
  if (silent) {
    return true;
  }
  if (firstLine.trim().slice(-2) === "$$") {
    firstLine = firstLine.trim().slice(0, -2);
    found = true;
  }
  let lastLine = "", lastPos = -1;
  let next = start;
  while (!found) {
    next++;
    if (next >= end) {
      break;
    }
    pos = state.bMarks[next] + state.tShift[next];
    max = state.eMarks[next];
    if (pos < max && state.tShift[next] < state.blkIndent) {
      break;
    }
    if (state.src.slice(pos, max).trim().slice(-2) === "$$") {
      lastPos = state.src.slice(0, max).lastIndexOf("$$");
      lastLine = state.src.slice(pos, lastPos);
      found = true;
    }
  }
  state.line = next + 1;
  const token = state.push("math_block", "math", 0);
  token.block = true;
  token.content = (firstLine && firstLine.trim() ? firstLine + "\n" : "") + state.getLines(start + 1, next, state.tShift[start], true) + (lastLine && lastLine.trim() ? lastLine : "");
  token.map = [start, state.line];
  token.markup = "$$";
  return true;
};
var registerTransforms = (md, {
  runtime,
  bundle,
  onBundle,
  output
}) => {
  function applyTransforms(match) {
    return (state, ...args) => {
      const { env } = state;
      hidden(env, "bundled", /* @__PURE__ */ new Set());
      const matched = match(state, ...args);
      if (matched) {
        env.meta = env.meta || {};
        env.meta.script = env.meta.script || [];
        env.meta.script.push(runtime.script);
        env.meta.style = env.meta.style || [];
        env.meta.style.push(runtime.style);
        if (bundle && !env.bundled.has("@diplodoc/latex-extension") && onBundle) {
          onBundle(env, output, runtime);
        }
      }
      return matched;
    };
  }
  md.inline.ruler.after("escape", "math_inline", applyTransforms(mathInline));
  md.block.ruler.after("blockquote", "math_block", applyTransforms(mathBlock), {
    alt: ["paragraph", "reference", "blockquote", "list"]
  });
};
function transform(options = {}) {
  const {
    classes = "yfm-latex",
    bundle = true,
    validate = true,
    katexOptions = {},
    onBundle
  } = options;
  if (bundle && typeof options.runtime === "string") {
    throw new TypeError("Option `runtime` should be record when `bundle` is enabled.");
  }
  const runtime = typeof options.runtime === "string" ? { script: options.runtime, style: options.runtime } : options.runtime || {
    script: "_assets/latex-extension.js",
    style: "_assets/latex-extension.css"
  };
  const render = (tag, displayMode) => (tokens, idx) => {
    const content = tokens[idx].content;
    const options2 = {
      ...katexOptions,
      displayMode
    };
    if (validate) {
      katex.renderToString(content, {
        ...options2,
        throwOnError: false
      });
    }
    const econtent = encodeURIComponent(content);
    const eoptions = encodeURIComponent(JSON.stringify(options2));
    return `<${tag} class="${classes}" data-content="${econtent}" data-options="${eoptions}"></${tag}>`;
  };
  const plugin = function(md, { output = "." }) {
    registerTransforms(md, {
      runtime,
      bundle,
      output,
      onBundle
    });
    md.renderer.rules.math_inline = render("span", false);
    md.renderer.rules.math_block = render("p", true);
  };
  Object.assign(plugin, {
    collect(input, { destRoot = "." }) {
      const md = new MarkdownIt().use((md2) => {
        registerTransforms(md2, {
          runtime,
          bundle,
          output: destRoot,
          onBundle
        });
      });
      md.parse(input, {});
    }
  });
  return plugin;
}
export {
  transform
};
//# sourceMappingURL=index.js.map
