"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/index.ts
var index_exports = {};
__export(index_exports, {
  DEFAULT_BUTTON_NAME: () => DEFAULT_BUTTON_NAME,
  DEFAULT_FORMULA_ATTRIBUTE: () => import_renderer3.DEFAULT_FORMULA_ATTRIBUTE,
  DEFAULT_FORMULA_CLASS: () => import_renderer3.DEFAULT_FORMULA_CLASS,
  DEFAULT_MODEL_NAME: () => DEFAULT_MODEL_NAME,
  FORMULA_FLAG_ATTRIBUTE: () => import_renderer3.FORMULA_FLAG_ATTRIBUTE,
  FormulaX: () => FormulaX,
  FormulaXCommand: () => FormulaXCommand,
  default: () => FormulaX,
  openFormulaXModal: () => openFormulaXModal,
  resolveOptions: () => resolveOptions
});
module.exports = __toCommonJS(index_exports);
var import_renderer3 = require("@formulaxjs/renderer");

// src/plugin.ts
var import_ckeditor5 = require("ckeditor5");
var import_renderer2 = require("@formulaxjs/renderer");
var import_renderer_kity = require("@formulaxjs/renderer-kity");
var import_editor2 = require("@formulaxjs/editor");

// src/modal.ts
var import_editor = require("@formulaxjs/editor");
var import_renderer = require("@formulaxjs/renderer");
function openFormulaXModal(input) {
  (0, import_editor.recordFormulaXPerfPoint)("fx:modal:open:start");
  const modalOpenStart = (0, import_editor.markFormulaXPerf)("fx:modal:open:start:scope");
  (0, import_editor.ensureFormulaXModalStyles)(document);
  const root = document.createElement("div");
  root.className = "fx-formula-modal-root";
  root.setAttribute("data-formulax-modal", "true");
  const submitText = input.isUpdate ? input.options.modal.updateText : input.options.modal.insertText;
  root.innerHTML = `
    <div class="fx-formula-modal-backdrop" data-action="backdrop"></div>
    <div class="fx-formula-modal" role="dialog" aria-modal="true" aria-label="${(0, import_renderer.escapeAttribute)(input.options.modal.title)}">
      <header class="fx-formula-modal__header">
        <h2 class="fx-formula-modal__title">${(0, import_renderer.escapeHtml)(input.options.modal.title)}</h2>
        <button class="fx-formula-modal__close" type="button" data-action="close" aria-label="Close">\xD7</button>
      </header>
      <section class="fx-formula-modal__body">
        <div class="fx-formula-editor-host"></div>
      </section>
      <footer class="fx-formula-modal__footer">
        <button class="fx-formula-modal__button" type="button" data-action="cancel">${(0, import_renderer.escapeHtml)(input.options.modal.cancelText)}</button>
        <button class="fx-formula-modal__button fx-formula-modal__button--primary" type="button" data-action="submit">${(0, import_renderer.escapeHtml)(submitText)}</button>
      </footer>
    </div>
  `;
  document.body.appendChild(root);
  document.body.classList.add("fx-formula-modal-open");
  const modalDomReadyMark = (0, import_editor.markFormulaXPerf)("fx:modal:dom-ready");
  (0, import_editor.measureFormulaXPerf)("fx:modal:dom-ready", modalOpenStart, modalDomReadyMark);
  (0, import_editor.clearFormulaXPerfMarks)(modalDomReadyMark);
  const host = root.querySelector(".fx-formula-editor-host");
  if (!host) {
    root.remove();
    (0, import_editor.clearFormulaXPerfMarks)(modalOpenStart);
    return Promise.reject(new Error("[FormulaX] CKEditor 5 modal host not found."));
  }
  (0, import_editor.renderFormulaXEditorLoadingState)(host);
  let closed = false;
  let mounted = null;
  const mountedPromise = (0, import_editor.waitForFormulaXAnimationFrame)().then(() => {
    if (closed) {
      (0, import_editor.clearFormulaXPerfMarks)(modalOpenStart);
      return null;
    }
    const mountStartMark = (0, import_editor.markFormulaXPerf)("fx:modal:editor-mount-start");
    (0, import_editor.measureFormulaXPerf)("fx:modal:editor-mount-start", modalOpenStart, mountStartMark);
    (0, import_editor.clearFormulaXPerfMarks)(mountStartMark);
    const nextMounted = (0, import_editor.mountFormulaXEditor)(host, {
      initialLatex: input.initialLatex,
      height: input.options.editor.height,
      autofocus: input.options.editor.autofocus,
      assets: input.options.editor.assets,
      render: {
        fontsize: input.options.editor.render.fontsize
      }
    });
    mounted = nextMounted;
    const mountedMark = (0, import_editor.markFormulaXPerf)("fx:modal:editor-mounted");
    (0, import_editor.measureFormulaXPerf)("fx:modal:editor-mounted", modalOpenStart, mountedMark);
    (0, import_editor.clearFormulaXPerfMarks)(mountedMark, modalOpenStart);
    queueMicrotask(() => {
      if (!closed) {
        nextMounted.root.focus();
      }
    });
    return nextMounted;
  }).catch((error) => {
    (0, import_editor.clearFormulaXPerfMarks)(modalOpenStart);
    throw error;
  });
  return new Promise((resolve) => {
    const close = (payload) => {
      if (closed) return;
      closed = true;
      mounted?.destroy();
      root.removeEventListener("click", onClick);
      document.removeEventListener("keydown", onKeydown, true);
      root.remove();
      document.body.classList.remove("fx-formula-modal-open");
      resolve(payload);
    };
    const submit = async () => {
      try {
        const activeMounted = mounted ?? await mountedPromise;
        if (!activeMounted) {
          return;
        }
        const latex = await activeMounted.getLatex();
        close({ latex });
      } catch (error) {
        host.innerHTML = `
          <div class="fx-formula-editor-error">
            Failed to read FormulaX editor content.
            <pre>${(0, import_renderer.escapeHtml)(error instanceof Error ? error.message : String(error))}</pre>
          </div>
        `;
      }
    };
    function onClick(event) {
      const action = event.target.closest("[data-action]")?.dataset.action;
      if (!action) return;
      if (action === "submit") {
        void submit();
        return;
      }
      if (action === "cancel" || action === "close") {
        close(null);
        return;
      }
      if (action === "backdrop" && input.options.modal.closeOnBackdrop) {
        close(null);
      }
    }
    function onKeydown(event) {
      if (event.key === "Escape") {
        event.preventDefault();
        close(null);
      }
    }
    root.addEventListener("click", onClick);
    document.addEventListener("keydown", onKeydown, true);
  });
}

// src/plugin.ts
var DEFAULT_BUTTON_NAME = "formulaX";
var DEFAULT_MODEL_NAME = "formulaX";
function resolveOptions(options = {}) {
  return {
    name: options.name ?? DEFAULT_MODEL_NAME,
    buttonName: options.buttonName ?? DEFAULT_BUTTON_NAME,
    toolbarText: options.toolbarText ?? "FormulaX",
    tooltip: options.tooltip ?? "Insert or edit formula",
    cursorStyle: options.cursorStyle ?? "pointer",
    formulaClassName: options.formulaClassName ?? import_renderer2.DEFAULT_FORMULA_CLASS,
    formulaAttributeName: options.formulaAttributeName ?? import_renderer2.DEFAULT_FORMULA_ATTRIBUTE,
    renderer: options.renderer ?? (0, import_renderer_kity.createKityFormulaRenderer)({
      fontSize: options.editor?.render?.fontsize ?? 40,
      height: options.editor?.height ?? "100%",
      assets: options.editor?.assets ?? {}
    }),
    preload: options.preload ?? "idle",
    modal: {
      title: options.modal?.title ?? "FormulaX Editor",
      insertText: options.modal?.insertText ?? "Insert",
      updateText: options.modal?.updateText ?? "Update",
      cancelText: options.modal?.cancelText ?? "Cancel",
      closeOnBackdrop: options.modal?.closeOnBackdrop ?? true
    },
    editor: {
      height: options.editor?.height ?? "100%",
      autofocus: options.editor?.autofocus ?? true,
      assets: options.editor?.assets ?? {},
      render: {
        fontsize: options.editor?.render?.fontsize ?? 40
      }
    }
  };
}
var FormulaXCommand = class extends import_ckeditor5.Command {
  options;
  constructor(editor, options) {
    super(editor);
    this.options = options;
  }
  refresh() {
    this.isEnabled = true;
  }
  execute() {
    const editor = this.editor;
    const selectedFormula = getSelectedFormulaModelElement(editor, this.options.name);
    const initialLatex = String(selectedFormula?.getAttribute("latex") ?? "");
    void openFormulaXModal({
      initialLatex,
      isUpdate: Boolean(selectedFormula),
      options: this.options
    }).then((payload) => {
      if (!payload) return;
      applyFormulaPayload(editor, selectedFormula, payload, this.options.name);
      editor.editing.view.focus();
    });
  }
};
var FormulaX = class extends import_ckeditor5.Plugin {
  preloadCleanup = null;
  static get pluginName() {
    return "FormulaX";
  }
  static get requires() {
    return [import_ckeditor5.Widget];
  }
  init() {
    const editor = this.editor;
    const options = resolveOptions(editor.config.get("formulaX"));
    if (hasRegisteredFormulaModelName(editor, options.name)) {
      console.error(
        `[FormulaX] CKEditor5 model name "${options.name}" is already registered. Pass a unique "name" option to avoid schema collisions.`
      );
      return;
    }
    (0, import_renderer2.ensureFormulaXBaseStyles)(document);
    (0, import_editor2.ensureFormulaXModalStyles)(document);
    this.preloadCleanup = (0, import_editor2.scheduleFormulaXEditorPreload)(
      options.preload,
      getEditorPreloadTarget(editor)
    );
    defineFormulaSchema(editor, options.name);
    defineFormulaConverters(editor, options);
    editor.editing.mapper.on(
      "viewToModelPosition",
      (0, import_ckeditor5.viewToModelPositionOutsideModelElement)(editor.model, isFormulaWidgetView)
    );
    const command = new FormulaXCommand(editor, options);
    editor.commands.add(options.buttonName, command);
    editor.ui.componentFactory.add(options.buttonName, (locale) => {
      const button = new import_ckeditor5.ButtonView(locale);
      button.set({
        label: options.toolbarText,
        tooltip: options.tooltip,
        withText: true
      });
      button.bind("isEnabled").to(command, "isEnabled");
      this.listenTo(button, "execute", () => editor.execute(options.buttonName));
      return button;
    });
  }
  destroy() {
    this.preloadCleanup?.();
    this.preloadCleanup = null;
    super.destroy();
  }
};
function applyFormulaPayload(editor, selectedFormula, payload, modelName) {
  editor.model.change((writer) => {
    if (selectedFormula) {
      if (!payload.latex.trim()) {
        writer.remove(selectedFormula);
        return;
      }
      writer.setAttribute("latex", payload.latex, selectedFormula);
      return;
    }
    if (!payload.latex.trim()) return;
    const formula = writer.createElement(modelName, {
      latex: payload.latex
    });
    editor.model.insertObject(formula, null, null, { setSelection: "after" });
  });
}
function hasRegisteredFormulaModelName(editor, modelName) {
  const schema = editor?.model?.schema;
  if (!schema) {
    return false;
  }
  if (typeof schema.isRegistered === "function") {
    return Boolean(schema.isRegistered(modelName));
  }
  if (typeof schema.getDefinition === "function") {
    return Boolean(schema.getDefinition(modelName));
  }
  if (schema._sourceDefinitions?.has) {
    return Boolean(schema._sourceDefinitions.has(modelName));
  }
  return Boolean(schema._definitions?.[modelName]);
}
function defineFormulaSchema(editor, modelName) {
  editor.model.schema.register(modelName, {
    allowWhere: "$text",
    isInline: true,
    isObject: true,
    allowAttributes: ["latex"]
  });
}
function defineFormulaConverters(editor, options) {
  editor.conversion.for("upcast").elementToElement({
    view: {
      name: "span",
      attributes: {
        [import_renderer2.FORMULA_FLAG_ATTRIBUTE]: true
      }
    },
    model: (viewElement, { writer }) => writer.createElement(options.name, {
      latex: readFormulaLatexFromView(viewElement, options)
    })
  });
  editor.conversion.for("dataDowncast").elementToElement({
    model: createFormulaConverterModelDefinition(options.name),
    view: (modelElement, { writer }) => createFormulaRawElement(writer, modelElement, options)
  });
  editor.conversion.for("editingDowncast").elementToElement({
    model: createFormulaConverterModelDefinition(options.name),
    view: (modelElement, { writer }) => {
      const widgetElement = createFormulaWidgetElement(writer, modelElement, options, editor);
      return (0, import_ckeditor5.toWidget)(widgetElement, writer, { label: "FormulaX formula" });
    }
  });
}
function createFormulaConverterModelDefinition(modelName) {
  return {
    name: modelName,
    attributes: ["latex"]
  };
}
function createFormulaRawElement(writer, modelElement, options) {
  const latex = String(modelElement.getAttribute("latex") ?? "");
  const element = writer.createContainerElement(
    "span",
    createFormulaViewAttributes(latex, options)
  );
  writer.insert(
    writer.createPositionAt(element, 0),
    writer.createText(latex || "\\square")
  );
  return element;
}
function createFormulaWidgetElement(writer, modelElement, options, editor) {
  const latex = String(modelElement.getAttribute("latex") ?? "");
  const widgetElement = writer.createContainerElement(
    "span",
    createFormulaViewAttributes(latex, options)
  );
  const contentElement = writer.createRawElement(
    "span",
    {
      class: `${options.formulaClassName}__content`,
      "aria-hidden": "true"
    },
    (domElement) => {
      domElement.innerHTML = createFormulaFallbackMarkup(latex, options);
      void renderFormulaIntoElement(domElement, latex, options);
      bindFormulaWidgetDomEvents(domElement, editor, modelElement, options.buttonName);
    }
  );
  writer.insert(writer.createPositionAt(widgetElement, 0), contentElement);
  return widgetElement;
}
function createFormulaViewAttributes(latex, options) {
  return {
    class: options.formulaClassName,
    [import_renderer2.FORMULA_FLAG_ATTRIBUTE]: "true",
    [options.formulaAttributeName]: latex,
    "data-latex": latex,
    contenteditable: "false",
    role: "button",
    style: `cursor: ${options.cursorStyle}`,
    tabindex: "0"
  };
}
function bindFormulaWidgetDomEvents(domElement, editor, modelElement, commandName) {
  domElement.onclick = (event) => {
    event.preventDefault();
    selectFormulaModelElement(editor, modelElement);
  };
  domElement.ondblclick = (event) => {
    event.preventDefault();
    event.stopPropagation();
    selectFormulaModelElement(editor, modelElement);
    editor.execute(commandName);
  };
}
function selectFormulaModelElement(editor, modelElement) {
  if (!modelElement?.is?.("element", "formulaX")) {
    return;
  }
  editor.editing.view.focus();
  editor.model.change((writer) => {
    writer.setSelection(modelElement, "on");
  });
}
function createFormulaFallbackMarkup(latex, options) {
  const markup = (0, import_renderer2.createFormulaMarkup)(latex, {
    attributeName: options.formulaAttributeName,
    className: options.formulaClassName
  });
  return extractInnerHtml(markup);
}
function extractInnerHtml(markup) {
  const wrapper = document.createElement("span");
  wrapper.innerHTML = markup;
  return wrapper.firstElementChild?.innerHTML ?? "";
}
function getEditorPreloadTarget(editor) {
  return editor?.ui?.getEditableElement?.() ?? editor?.ui?.view?.editable?.element ?? null;
}
function getSelectedFormulaModelElement(editor, modelName) {
  const selectedElement = editor.model.document.selection.getSelectedElement();
  return selectedElement?.is?.("element", modelName) ? selectedElement : null;
}
function isFormulaWidgetView(node) {
  return Boolean(node?.is?.("element") && node.hasAttribute?.(import_renderer2.FORMULA_FLAG_ATTRIBUTE));
}
function readFormulaLatexFromView(viewElement, options) {
  return String(
    viewElement.getAttribute(options.formulaAttributeName) ?? viewElement.getAttribute("data-latex") ?? ""
  );
}
async function renderFormulaIntoElement(domElement, latex, options) {
  const trimmedLatex = latex.trim();
  const renderToken = `${trimmedLatex}::${Date.now()}::${Math.random().toString(36).slice(2, 8)}`;
  domElement.dataset.renderToken = renderToken;
  if (!trimmedLatex) {
    return;
  }
  try {
    const result = await options.renderer.renderLatex(trimmedLatex, {
      fontSize: options.editor.render.fontsize,
      className: options.formulaClassName
    });
    if (domElement.dataset.renderToken !== renderToken) {
      return;
    }
    domElement.innerHTML = result.html;
  } catch (error) {
    if (domElement.dataset.renderToken !== renderToken) {
      return;
    }
    console.error("[FormulaX] Failed to render CKEditor5 formula widget:", error);
  }
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  DEFAULT_BUTTON_NAME,
  DEFAULT_FORMULA_ATTRIBUTE,
  DEFAULT_FORMULA_CLASS,
  DEFAULT_MODEL_NAME,
  FORMULA_FLAG_ATTRIBUTE,
  FormulaX,
  FormulaXCommand,
  openFormulaXModal,
  resolveOptions
});
//# sourceMappingURL=index.cjs.map