@formulaxjs/tiptap 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -31,11 +31,16 @@ __export(index_exports, {
31
31
  module.exports = __toCommonJS(index_exports);
32
32
  var import_core = require("@tiptap/core");
33
33
  var import_core2 = require("@formulaxjs/core");
34
+ var import_renderer2 = require("@formulaxjs/renderer");
35
+ var import_renderer_kity = require("@formulaxjs/renderer-kity");
34
36
  var import_editor2 = require("@formulaxjs/editor");
35
37
 
36
38
  // src/modal.ts
37
39
  var import_editor = require("@formulaxjs/editor");
40
+ var import_renderer = require("@formulaxjs/renderer");
38
41
  function openFormulaXTiptapModal(input) {
42
+ (0, import_editor.recordFormulaXPerfPoint)("fx:modal:open:start");
43
+ const modalOpenStart = (0, import_editor.markFormulaXPerf)("fx:modal:open:start:scope");
39
44
  (0, import_editor.ensureFormulaXModalStyles)(document);
40
45
  const root = document.createElement("div");
41
46
  root.className = "fx-formula-modal-root";
@@ -43,44 +48,72 @@ function openFormulaXTiptapModal(input) {
43
48
  const submitText = input.isUpdate ? input.options.modal.updateText : input.options.modal.insertText;
44
49
  root.innerHTML = `
45
50
  <div class="fx-formula-modal-backdrop" data-action="backdrop"></div>
46
- <div class="fx-formula-modal" role="dialog" aria-modal="true" aria-label="${(0, import_editor.escapeAttribute)(input.options.modal.title)}">
51
+ <div class="fx-formula-modal" role="dialog" aria-modal="true" aria-label="${(0, import_renderer.escapeAttribute)(input.options.modal.title)}">
47
52
  <header class="fx-formula-modal__header">
48
- <h2 class="fx-formula-modal__title">${(0, import_editor.escapeHtml)(input.options.modal.title)}</h2>
53
+ <h2 class="fx-formula-modal__title">${(0, import_renderer.escapeHtml)(input.options.modal.title)}</h2>
49
54
  <button class="fx-formula-modal__close" type="button" data-action="close" aria-label="Close">\xD7</button>
50
55
  </header>
51
56
  <section class="fx-formula-modal__body">
52
57
  <div class="fx-formula-editor-host"></div>
53
58
  </section>
54
59
  <footer class="fx-formula-modal__footer">
55
- <button class="fx-formula-modal__button" type="button" data-action="cancel">${(0, import_editor.escapeHtml)(input.options.modal.cancelText)}</button>
56
- <button class="fx-formula-modal__button fx-formula-modal__button--primary" type="button" data-action="submit">${(0, import_editor.escapeHtml)(submitText)}</button>
60
+ <button class="fx-formula-modal__button" type="button" data-action="cancel">${(0, import_renderer.escapeHtml)(input.options.modal.cancelText)}</button>
61
+ <button class="fx-formula-modal__button fx-formula-modal__button--primary" type="button" data-action="submit">${(0, import_renderer.escapeHtml)(submitText)}</button>
57
62
  </footer>
58
63
  </div>
59
64
  `;
60
65
  document.body.appendChild(root);
61
66
  document.body.classList.add("fx-formula-modal-open");
67
+ const modalDomReadyMark = (0, import_editor.markFormulaXPerf)("fx:modal:dom-ready");
68
+ (0, import_editor.measureFormulaXPerf)("fx:modal:dom-ready", modalOpenStart, modalDomReadyMark);
69
+ (0, import_editor.clearFormulaXPerfMarks)(modalDomReadyMark);
62
70
  const host = root.querySelector(".fx-formula-editor-host");
63
71
  if (!host) {
64
72
  root.remove();
73
+ (0, import_editor.clearFormulaXPerfMarks)(modalOpenStart);
65
74
  return Promise.reject(new Error("[FormulaX] Tiptap modal host not found."));
66
75
  }
67
- const mounted = (0, import_editor.mountFormulaXEditor)(host, {
68
- initialLatex: input.initialLatex,
69
- height: input.options.editor.height,
70
- autofocus: input.options.editor.autofocus,
71
- assets: input.options.editor.assets,
72
- render: {
73
- fontsize: input.options.editor.render.fontsize
76
+ (0, import_editor.renderFormulaXEditorLoadingState)(host);
77
+ let closed = false;
78
+ let mounted = null;
79
+ const mountedPromise = (0, import_editor.waitForFormulaXAnimationFrame)().then(() => {
80
+ if (closed) {
81
+ (0, import_editor.clearFormulaXPerfMarks)(modalOpenStart);
82
+ return null;
74
83
  }
84
+ const mountStartMark = (0, import_editor.markFormulaXPerf)("fx:modal:editor-mount-start");
85
+ (0, import_editor.measureFormulaXPerf)("fx:modal:editor-mount-start", modalOpenStart, mountStartMark);
86
+ (0, import_editor.clearFormulaXPerfMarks)(mountStartMark);
87
+ const nextMounted = (0, import_editor.mountFormulaXEditor)(host, {
88
+ initialLatex: input.initialLatex,
89
+ height: input.options.editor.height,
90
+ autofocus: input.options.editor.autofocus,
91
+ assets: input.options.editor.assets,
92
+ render: {
93
+ fontsize: input.options.editor.render.fontsize
94
+ }
95
+ });
96
+ mounted = nextMounted;
97
+ const mountedMark = (0, import_editor.markFormulaXPerf)("fx:modal:editor-mounted");
98
+ (0, import_editor.measureFormulaXPerf)("fx:modal:editor-mounted", modalOpenStart, mountedMark);
99
+ (0, import_editor.clearFormulaXPerfMarks)(mountedMark, modalOpenStart);
100
+ queueMicrotask(() => {
101
+ if (!closed) {
102
+ nextMounted.root.focus();
103
+ }
104
+ });
105
+ return nextMounted;
106
+ }).catch((error) => {
107
+ (0, import_editor.clearFormulaXPerfMarks)(modalOpenStart);
108
+ throw error;
75
109
  });
76
- let closed = false;
77
110
  return new Promise((resolve) => {
78
111
  const close = (payload) => {
79
112
  if (closed) {
80
113
  return;
81
114
  }
82
115
  closed = true;
83
- mounted.destroy();
116
+ mounted?.destroy();
84
117
  root.removeEventListener("click", onClick);
85
118
  document.removeEventListener("keydown", onKeydown, true);
86
119
  root.remove();
@@ -89,13 +122,17 @@ function openFormulaXTiptapModal(input) {
89
122
  };
90
123
  const submit = async () => {
91
124
  try {
92
- const latex = await mounted.getLatex();
125
+ const activeMounted = mounted ?? await mountedPromise;
126
+ if (!activeMounted) {
127
+ return;
128
+ }
129
+ const latex = await activeMounted.getLatex();
93
130
  close({ latex });
94
131
  } catch (error) {
95
132
  host.innerHTML = `
96
133
  <div class="fx-formula-editor-error">
97
134
  Failed to read FormulaX editor content.
98
- <pre>${(0, import_editor.escapeHtml)(error instanceof Error ? error.message : String(error))}</pre>
135
+ <pre>${(0, import_renderer.escapeHtml)(error instanceof Error ? error.message : String(error))}</pre>
99
136
  </div>
100
137
  `;
101
138
  }
@@ -125,9 +162,6 @@ function openFormulaXTiptapModal(input) {
125
162
  }
126
163
  root.addEventListener("click", onClick);
127
164
  document.addEventListener("keydown", onKeydown, true);
128
- queueMicrotask(() => {
129
- mounted.root.focus();
130
- });
131
165
  });
132
166
  }
133
167
 
@@ -136,10 +170,16 @@ var FORMULAX_NODE_NAME = "formulaX";
136
170
  function resolveOptions(options = {}) {
137
171
  return {
138
172
  name: options.name ?? FORMULAX_NODE_NAME,
139
- formulaClassName: options.formulaClassName ?? import_editor2.DEFAULT_FORMULA_CLASS,
140
- formulaAttributeName: options.formulaAttributeName ?? import_editor2.DEFAULT_FORMULA_ATTRIBUTE,
173
+ formulaClassName: options.formulaClassName ?? import_renderer2.DEFAULT_FORMULA_CLASS,
174
+ formulaAttributeName: options.formulaAttributeName ?? import_renderer2.DEFAULT_FORMULA_ATTRIBUTE,
141
175
  cursorStyle: options.cursorStyle ?? "pointer",
142
176
  initialLatex: options.initialLatex ?? "",
177
+ renderer: options.renderer ?? (0, import_renderer_kity.createKityFormulaRenderer)({
178
+ fontSize: options.editor?.render?.fontsize ?? 40,
179
+ height: options.editor?.height ?? "100%",
180
+ assets: options.editor?.assets ?? {}
181
+ }),
182
+ preload: options.preload ?? "idle",
143
183
  modal: {
144
184
  title: options.modal?.title ?? "FormulaX Editor",
145
185
  insertText: options.modal?.insertText ?? "Insert",
@@ -176,11 +216,30 @@ function createFormulaXNodeConfig(options) {
176
216
  addOptions() {
177
217
  return options;
178
218
  },
219
+ addStorage() {
220
+ return {
221
+ preloadCleanup: null
222
+ };
223
+ },
179
224
  onCreate() {
180
225
  warnDuplicateNodeName(this);
181
226
  if (typeof document !== "undefined") {
227
+ (0, import_renderer2.ensureFormulaXBaseStyles)(document);
182
228
  (0, import_editor2.ensureFormulaXModalStyles)(document);
183
229
  }
230
+ const preloadCleanup = (0, import_editor2.scheduleFormulaXEditorPreload)(
231
+ options.preload,
232
+ this.editor?.view?.dom ?? null
233
+ );
234
+ if (this.storage) {
235
+ this.storage.preloadCleanup = preloadCleanup;
236
+ }
237
+ },
238
+ onDestroy() {
239
+ this.storage?.preloadCleanup?.();
240
+ if (this.storage) {
241
+ this.storage.preloadCleanup = null;
242
+ }
184
243
  },
185
244
  addAttributes() {
186
245
  return {
@@ -197,7 +256,7 @@ function createFormulaXNodeConfig(options) {
197
256
  return false;
198
257
  }
199
258
  return {
200
- latex: (0, import_editor2.getFormulaLatexFromElement)(element, this.options.formulaAttributeName)
259
+ latex: (0, import_renderer2.getFormulaLatexFromElement)(element, this.options.formulaAttributeName)
201
260
  };
202
261
  }
203
262
  }];
@@ -348,7 +407,7 @@ function createFormulaNodeContent(payload, nodeName = FORMULAX_NODE_NAME) {
348
407
  };
349
408
  }
350
409
  function createFormulaDomElement(ownerDocument, attrs, options) {
351
- return (0, import_editor2.createFormulaElement)(ownerDocument, attrs.latex, {
410
+ return (0, import_renderer2.createFormulaElement)(ownerDocument, attrs.latex, {
352
411
  attributeName: options.formulaAttributeName,
353
412
  className: options.formulaClassName,
354
413
  cursorStyle: options.cursorStyle
@@ -370,7 +429,6 @@ function syncFormulaDomElement(dom, attrs, options) {
370
429
  dom.setAttribute(attribute.name, attribute.value);
371
430
  });
372
431
  }
373
- var formulaRenderCache = /* @__PURE__ */ new Map();
374
432
  async function renderFormulaIntoElement(dom, attrs, options) {
375
433
  const latex = attrs.latex.trim();
376
434
  const renderToken = `${latex}::${Date.now()}::${Math.random().toString(36).slice(2, 8)}`;
@@ -383,11 +441,14 @@ async function renderFormulaIntoElement(dom, attrs, options) {
383
441
  return;
384
442
  }
385
443
  try {
386
- const markup = await renderFormulaSvgMarkup(latex, options);
444
+ const result = await options.renderer.renderLatex(latex, {
445
+ fontSize: options.editor.render.fontsize,
446
+ className: options.formulaClassName
447
+ });
387
448
  if (dom.dataset.renderToken !== renderToken) {
388
449
  return;
389
450
  }
390
- dom.innerHTML = markup;
451
+ dom.innerHTML = result.html;
391
452
  } catch (error) {
392
453
  if (dom.dataset.renderToken !== renderToken) {
393
454
  return;
@@ -399,46 +460,6 @@ async function renderFormulaIntoElement(dom, attrs, options) {
399
460
  }
400
461
  }
401
462
  }
402
- function renderFormulaSvgMarkup(latex, options) {
403
- const cached = formulaRenderCache.get(latex);
404
- if (cached) {
405
- return cached;
406
- }
407
- const pending = (async () => {
408
- const host = document.createElement("div");
409
- host.style.position = "fixed";
410
- host.style.left = "-100000px";
411
- host.style.top = "0";
412
- host.style.width = "1px";
413
- host.style.height = "1px";
414
- host.style.opacity = "0";
415
- host.style.pointerEvents = "none";
416
- host.setAttribute("aria-hidden", "true");
417
- document.body.appendChild(host);
418
- const mounted = (0, import_editor2.mountFormulaXEditor)(host, {
419
- initialLatex: latex,
420
- height: options.editor.height,
421
- autofocus: false,
422
- assets: options.editor.assets,
423
- render: {
424
- fontsize: options.editor.render.fontsize
425
- }
426
- });
427
- try {
428
- return await mounted.getRenderHtml();
429
- } finally {
430
- mounted.destroy();
431
- host.remove();
432
- }
433
- })();
434
- formulaRenderCache.set(latex, pending);
435
- pending.catch(() => {
436
- if (formulaRenderCache.get(latex) === pending) {
437
- formulaRenderCache.delete(latex);
438
- }
439
- });
440
- return pending;
441
- }
442
463
  // Annotate the CommonJS export names for ESM import in node:
443
464
  0 && (module.exports = {
444
465
  FORMULAX_NODE_NAME,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/modal.ts"],"sourcesContent":["import { Node } from '@tiptap/core';\nimport { parseLatex, serializeLatex, type FormulaDoc } from '@formulaxjs/core';\nimport {\n createFormulaElement,\n DEFAULT_FORMULA_ATTRIBUTE,\n DEFAULT_FORMULA_CLASS,\n ensureFormulaXModalStyles,\n getFormulaLatexFromElement,\n mountFormulaXEditor,\n} from '@formulaxjs/editor';\nimport { openFormulaXTiptapModal } from './modal';\nimport type { FormulaXPayload, FormulaXTiptapOptions, RequiredFormulaXTiptapOptions } from './types';\n\nexport interface FormulaXNodeAttributes {\n latex: string;\n}\n\nexport const FORMULAX_NODE_NAME = 'formulaX';\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n formulaX: {\n openFormulaX: () => ReturnType;\n };\n }\n}\n\nexport function resolveOptions(options: FormulaXTiptapOptions = {}): RequiredFormulaXTiptapOptions {\n return {\n name: options.name ?? FORMULAX_NODE_NAME,\n formulaClassName: options.formulaClassName ?? DEFAULT_FORMULA_CLASS,\n formulaAttributeName: options.formulaAttributeName ?? DEFAULT_FORMULA_ATTRIBUTE,\n cursorStyle: options.cursorStyle ?? 'pointer',\n initialLatex: options.initialLatex ?? '',\n modal: {\n title: options.modal?.title ?? 'FormulaX Editor',\n insertText: options.modal?.insertText ?? 'Insert',\n updateText: options.modal?.updateText ?? 'Update',\n cancelText: options.modal?.cancelText ?? 'Cancel',\n closeOnBackdrop: options.modal?.closeOnBackdrop ?? true,\n },\n editor: {\n height: options.editor?.height ?? '100%',\n autofocus: options.editor?.autofocus ?? true,\n assets: options.editor?.assets ?? {},\n render: {\n fontsize: options.editor?.render?.fontsize ?? 40,\n },\n },\n };\n}\n\nfunction warnDuplicateNodeName(extension: {\n name: string;\n editor?: { extensionManager?: { extensions?: Array<{ name?: string }> } };\n}) {\n const extensions = extension.editor?.extensionManager?.extensions ?? [];\n const duplicates = extensions.filter((item) => item?.name === extension.name);\n\n if (duplicates.length > 1) {\n console.warn(\n `[FormulaX] TipTap node name \"${extension.name}\" is already registered. ` +\n 'Pass a unique \"name\" option to avoid schema collisions.',\n );\n }\n}\n\nfunction createFormulaXNodeConfig(options: RequiredFormulaXTiptapOptions): any {\n return {\n name: options.name,\n group: 'inline',\n inline: true,\n atom: true,\n selectable: true,\n addOptions() {\n return options;\n },\n onCreate() {\n warnDuplicateNodeName(this);\n\n if (typeof document !== 'undefined') {\n ensureFormulaXModalStyles(document);\n }\n },\n addAttributes() {\n return {\n latex: {\n default: '',\n },\n };\n },\n parseHTML() {\n return [{\n tag: 'span[data-formulax]',\n getAttrs: (element: Node | string) => {\n if (!(element instanceof HTMLElement)) {\n return false;\n }\n\n return {\n latex: getFormulaLatexFromElement(element, this.options.formulaAttributeName),\n };\n },\n }];\n },\n renderHTML({ node }: { node: { attrs: FormulaXNodeAttributes } }) {\n if (typeof document === 'undefined') {\n return [\n 'span',\n {\n 'data-formulax': 'true',\n [this.options.formulaAttributeName]: node.attrs.latex,\n 'data-latex': node.attrs.latex,\n },\n node.attrs.latex || '\\\\square',\n ] as const;\n }\n\n return createFormulaDomElement(document, node.attrs, this.options);\n },\n addCommands() {\n return {\n openFormulaX: () => () => {\n const selectedFormula = getSelectedFormula(this.editor, this.name);\n const initialLatex = selectedFormula?.attrs.latex ?? this.options.initialLatex;\n\n void openFormulaXTiptapModal({\n initialLatex,\n isUpdate: Boolean(selectedFormula),\n options: this.options,\n }).then((payload) => {\n if (!payload) {\n return;\n }\n\n applyFormulaPayload(this.editor, payload, selectedFormula, this.name);\n this.editor.commands.focus();\n });\n\n return true;\n },\n };\n },\n addKeyboardShortcuts() {\n return {\n Enter: () => {\n if (!getSelectedFormula(this.editor, this.name)) {\n return false;\n }\n\n return this.editor.commands.openFormulaX();\n },\n Space: () => {\n if (!getSelectedFormula(this.editor, this.name)) {\n return false;\n }\n\n return this.editor.commands.openFormulaX();\n },\n };\n },\n addNodeView() {\n return ({ editor, getPos, node }: {\n editor: { commands: { openFormulaX: () => boolean; setNodeSelection?: (position: number) => boolean } };\n getPos: () => number;\n node: { attrs: FormulaXNodeAttributes };\n }) => {\n const dom = createFormulaDomElement(document, node.attrs, this.options) ?? document.createElement('span');\n dom.classList.add('formulax-math--interactive');\n void renderFormulaIntoElement(dom, node.attrs, this.options);\n\n const selectNode = (): void => {\n const position = getPos();\n if (typeof position !== 'number') {\n return;\n }\n\n editor.commands.setNodeSelection?.(position);\n };\n\n dom.addEventListener('click', (event) => {\n event.preventDefault();\n selectNode();\n });\n\n dom.addEventListener('dblclick', (event) => {\n event.preventDefault();\n event.stopPropagation();\n selectNode();\n editor.commands.openFormulaX();\n });\n\n return {\n dom,\n update: (updatedNode: { attrs: FormulaXNodeAttributes; type: { name: string } }) => {\n if (updatedNode.type.name !== this.name) {\n return false;\n }\n\n syncFormulaDomElement(dom, updatedNode.attrs, this.options);\n void renderFormulaIntoElement(dom, updatedNode.attrs, this.options);\n return true;\n },\n selectNode: () => {\n dom.classList.add('ProseMirror-selectednode');\n },\n deselectNode: () => {\n dom.classList.remove('ProseMirror-selectednode');\n },\n };\n };\n },\n };\n}\n\nexport interface TiptapNodeFactory {\n create: typeof Node.create;\n}\n\nexport function createFormulaXNode(\n nodeFactory: TiptapNodeFactory = Node,\n options?: FormulaXTiptapOptions,\n) {\n return nodeFactory.create(createFormulaXNodeConfig(resolveOptions(options))) as any;\n}\n\nexport const FormulaXNode = createFormulaXNode();\n\nexport const createFormulaXPayload = (latex: string): FormulaDoc => parseLatex(latex);\n\nexport const serializeFormulaXPayload = (doc: FormulaDoc): string => serializeLatex(doc);\n\nfunction applyFormulaPayload(\n editor: {\n chain: () => {\n focus: () => {\n deleteRange: (range: { from: number; to: number }) => { run: () => boolean };\n insertContent: (content: unknown) => { run: () => boolean };\n insertContentAt: (range: { from: number; to: number }, content: unknown) => { run: () => boolean };\n };\n };\n },\n payload: FormulaXPayload,\n selectedFormula: SelectedFormula | null,\n nodeName: string,\n): void {\n const latex = payload.latex.trim();\n\n if (selectedFormula) {\n if (!latex) {\n editor.chain().focus().deleteRange({\n from: selectedFormula.from,\n to: selectedFormula.to,\n }).run();\n return;\n }\n\n editor.chain().focus().insertContentAt(\n {\n from: selectedFormula.from,\n to: selectedFormula.to,\n },\n createFormulaNodeContent(payload, nodeName),\n ).run();\n return;\n }\n\n if (!latex) {\n return;\n }\n\n editor.chain().focus().insertContent(createFormulaNodeContent(payload, nodeName)).run();\n}\n\ninterface SelectedFormula {\n from: number;\n to: number;\n attrs: FormulaXNodeAttributes;\n}\n\nfunction getSelectedFormula(editor: {\n state: {\n selection: {\n from: number;\n to: number;\n node?: { type?: { name?: string }; attrs?: FormulaXNodeAttributes };\n };\n };\n}, nodeName: string): SelectedFormula | null {\n const { selection } = editor.state;\n const node = selection.node;\n\n if (node?.type?.name !== nodeName) {\n return null;\n }\n\n return {\n from: selection.from,\n to: selection.to,\n attrs: {\n latex: node.attrs?.latex ?? '',\n },\n };\n}\n\nfunction createFormulaNodeContent(\n payload: FormulaXPayload,\n nodeName = FORMULAX_NODE_NAME,\n): {\n type: string;\n attrs: FormulaXNodeAttributes;\n} {\n return {\n type: nodeName,\n attrs: {\n latex: payload.latex,\n },\n };\n}\n\nfunction createFormulaDomElement(\n ownerDocument: Document,\n attrs: FormulaXNodeAttributes,\n options: RequiredFormulaXTiptapOptions,\n): HTMLElement | null {\n return createFormulaElement(ownerDocument, attrs.latex, {\n attributeName: options.formulaAttributeName,\n className: options.formulaClassName,\n cursorStyle: options.cursorStyle,\n });\n}\n\nfunction syncFormulaDomElement(\n dom: HTMLElement,\n attrs: FormulaXNodeAttributes,\n options: RequiredFormulaXTiptapOptions,\n): void {\n const next = createFormulaDomElement(dom.ownerDocument ?? document, attrs, options);\n if (!next) {\n return;\n }\n\n dom.replaceChildren(...Array.from(next.childNodes));\n Array.from(dom.attributes).forEach((attribute) => {\n if (attribute.name === 'class') {\n return;\n }\n\n dom.removeAttribute(attribute.name);\n });\n\n Array.from(next.attributes).forEach((attribute) => {\n dom.setAttribute(attribute.name, attribute.value);\n });\n}\n\nconst formulaRenderCache = new Map<string, Promise<string>>();\n\nasync function renderFormulaIntoElement(\n dom: HTMLElement,\n attrs: FormulaXNodeAttributes,\n options: RequiredFormulaXTiptapOptions,\n): Promise<void> {\n const latex = attrs.latex.trim();\n const renderToken = `${latex}::${Date.now()}::${Math.random().toString(36).slice(2, 8)}`;\n dom.dataset.renderToken = renderToken;\n\n if (!latex) {\n const placeholder = dom.querySelector<HTMLElement>(`.${options.formulaClassName}__render`);\n if (placeholder) {\n placeholder.textContent = '\\\\square';\n }\n return;\n }\n\n try {\n const markup = await renderFormulaSvgMarkup(latex, options);\n if (dom.dataset.renderToken !== renderToken) {\n return;\n }\n\n dom.innerHTML = markup;\n } catch (error) {\n if (dom.dataset.renderToken !== renderToken) {\n return;\n }\n\n console.error('[FormulaX] Failed to render Tiptap formula node:', error);\n const placeholder = dom.querySelector<HTMLElement>(`.${options.formulaClassName}__render`);\n if (placeholder) {\n placeholder.textContent = latex;\n }\n }\n}\n\nfunction renderFormulaSvgMarkup(\n latex: string,\n options: RequiredFormulaXTiptapOptions,\n): Promise<string> {\n const cached = formulaRenderCache.get(latex);\n if (cached) {\n return cached;\n }\n\n const pending = (async () => {\n const host = document.createElement('div');\n host.style.position = 'fixed';\n host.style.left = '-100000px';\n host.style.top = '0';\n host.style.width = '1px';\n host.style.height = '1px';\n host.style.opacity = '0';\n host.style.pointerEvents = 'none';\n host.setAttribute('aria-hidden', 'true');\n document.body.appendChild(host);\n\n const mounted = mountFormulaXEditor(host, {\n initialLatex: latex,\n height: options.editor.height,\n autofocus: false,\n assets: options.editor.assets,\n render: {\n fontsize: options.editor.render.fontsize,\n },\n });\n\n try {\n return await mounted.getRenderHtml();\n } finally {\n mounted.destroy();\n host.remove();\n }\n })();\n\n formulaRenderCache.set(latex, pending);\n pending.catch(() => {\n if (formulaRenderCache.get(latex) === pending) {\n formulaRenderCache.delete(latex);\n }\n });\n return pending;\n}\n\nexport type { FormulaXPayload, FormulaXTiptapOptions, RequiredFormulaXTiptapOptions } from './types';\nexport { openFormulaXTiptapModal } from './modal';\n","import {\n ensureFormulaXModalStyles,\n escapeAttribute,\n escapeHtml,\n mountFormulaXEditor,\n} from '@formulaxjs/editor';\nimport type { FormulaXPayload, RequiredFormulaXTiptapOptions } from './types';\n\nexport interface OpenFormulaXTiptapModalInput {\n initialLatex: string;\n isUpdate: boolean;\n options: RequiredFormulaXTiptapOptions;\n}\n\nexport function openFormulaXTiptapModal(\n input: OpenFormulaXTiptapModalInput,\n): Promise<FormulaXPayload | null> {\n ensureFormulaXModalStyles(document);\n\n const root = document.createElement('div');\n root.className = 'fx-formula-modal-root';\n root.setAttribute('data-formulax-modal', 'true');\n\n const submitText = input.isUpdate ? input.options.modal.updateText : input.options.modal.insertText;\n\n root.innerHTML = `\n <div class=\"fx-formula-modal-backdrop\" data-action=\"backdrop\"></div>\n <div class=\"fx-formula-modal\" role=\"dialog\" aria-modal=\"true\" aria-label=\"${escapeAttribute(input.options.modal.title)}\">\n <header class=\"fx-formula-modal__header\">\n <h2 class=\"fx-formula-modal__title\">${escapeHtml(input.options.modal.title)}</h2>\n <button class=\"fx-formula-modal__close\" type=\"button\" data-action=\"close\" aria-label=\"Close\">×</button>\n </header>\n <section class=\"fx-formula-modal__body\">\n <div class=\"fx-formula-editor-host\"></div>\n </section>\n <footer class=\"fx-formula-modal__footer\">\n <button class=\"fx-formula-modal__button\" type=\"button\" data-action=\"cancel\">${escapeHtml(input.options.modal.cancelText)}</button>\n <button class=\"fx-formula-modal__button fx-formula-modal__button--primary\" type=\"button\" data-action=\"submit\">${escapeHtml(submitText)}</button>\n </footer>\n </div>\n `;\n\n document.body.appendChild(root);\n document.body.classList.add('fx-formula-modal-open');\n\n const host = root.querySelector<HTMLElement>('.fx-formula-editor-host');\n if (!host) {\n root.remove();\n return Promise.reject(new Error('[FormulaX] Tiptap modal host not found.'));\n }\n\n const mounted = mountFormulaXEditor(host, {\n initialLatex: input.initialLatex,\n height: input.options.editor.height,\n autofocus: input.options.editor.autofocus,\n assets: input.options.editor.assets,\n render: {\n fontsize: input.options.editor.render.fontsize,\n },\n });\n let closed = false;\n\n return new Promise((resolve) => {\n const close = (payload: FormulaXPayload | null): void => {\n if (closed) {\n return;\n }\n\n closed = true;\n mounted.destroy();\n root.removeEventListener('click', onClick);\n document.removeEventListener('keydown', onKeydown, true);\n root.remove();\n document.body.classList.remove('fx-formula-modal-open');\n resolve(payload);\n };\n\n const submit = async (): Promise<void> => {\n try {\n const latex = await mounted.getLatex();\n close({ latex });\n } catch (error) {\n host.innerHTML = `\n <div class=\"fx-formula-editor-error\">\n Failed to read FormulaX editor content.\n <pre>${escapeHtml(error instanceof Error ? error.message : String(error))}</pre>\n </div>\n `;\n }\n };\n\n function onClick(event: MouseEvent): void {\n const action = (event.target as HTMLElement).closest<HTMLElement>('[data-action]')?.dataset.action;\n if (!action) {\n return;\n }\n\n if (action === 'submit') {\n void submit();\n return;\n }\n\n if (action === 'cancel' || action === 'close') {\n close(null);\n return;\n }\n\n if (action === 'backdrop' && input.options.modal.closeOnBackdrop) {\n close(null);\n }\n }\n\n function onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape') {\n event.preventDefault();\n close(null);\n }\n }\n\n root.addEventListener('click', onClick);\n document.addEventListener('keydown', onKeydown, true);\n\n queueMicrotask(() => {\n mounted.root.focus();\n });\n });\n}\n"],"mappings":"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","names":["import_core","import_editor"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/modal.ts"],"sourcesContent":["import { Node } from '@tiptap/core';\nimport { parseLatex, serializeLatex, type FormulaDoc } from '@formulaxjs/core';\nimport {\n createFormulaElement,\n DEFAULT_FORMULA_ATTRIBUTE,\n DEFAULT_FORMULA_CLASS,\n ensureFormulaXBaseStyles,\n getFormulaLatexFromElement,\n} from '@formulaxjs/renderer';\nimport { createKityFormulaRenderer } from '@formulaxjs/renderer-kity';\nimport { ensureFormulaXModalStyles, scheduleFormulaXEditorPreload } from '@formulaxjs/editor';\nimport { openFormulaXTiptapModal } from './modal';\nimport type { FormulaXPayload, FormulaXTiptapOptions, RequiredFormulaXTiptapOptions } from './types';\n\nexport interface FormulaXNodeAttributes {\n latex: string;\n}\n\nexport const FORMULAX_NODE_NAME = 'formulaX';\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n formulaX: {\n openFormulaX: () => ReturnType;\n };\n }\n}\n\nexport function resolveOptions(options: FormulaXTiptapOptions = {}): RequiredFormulaXTiptapOptions {\n return {\n name: options.name ?? FORMULAX_NODE_NAME,\n formulaClassName: options.formulaClassName ?? DEFAULT_FORMULA_CLASS,\n formulaAttributeName: options.formulaAttributeName ?? DEFAULT_FORMULA_ATTRIBUTE,\n cursorStyle: options.cursorStyle ?? 'pointer',\n initialLatex: options.initialLatex ?? '',\n renderer: options.renderer ?? createKityFormulaRenderer({\n fontSize: options.editor?.render?.fontsize ?? 40,\n height: options.editor?.height ?? '100%',\n assets: options.editor?.assets ?? {},\n }),\n preload: options.preload ?? 'idle',\n modal: {\n title: options.modal?.title ?? 'FormulaX Editor',\n insertText: options.modal?.insertText ?? 'Insert',\n updateText: options.modal?.updateText ?? 'Update',\n cancelText: options.modal?.cancelText ?? 'Cancel',\n closeOnBackdrop: options.modal?.closeOnBackdrop ?? true,\n },\n editor: {\n height: options.editor?.height ?? '100%',\n autofocus: options.editor?.autofocus ?? true,\n assets: options.editor?.assets ?? {},\n render: {\n fontsize: options.editor?.render?.fontsize ?? 40,\n },\n },\n };\n}\n\nfunction warnDuplicateNodeName(extension: {\n name: string;\n editor?: { extensionManager?: { extensions?: Array<{ name?: string }> } };\n}) {\n const extensions = extension.editor?.extensionManager?.extensions ?? [];\n const duplicates = extensions.filter((item) => item?.name === extension.name);\n\n if (duplicates.length > 1) {\n console.warn(\n `[FormulaX] TipTap node name \"${extension.name}\" is already registered. ` +\n 'Pass a unique \"name\" option to avoid schema collisions.',\n );\n }\n}\n\nfunction createFormulaXNodeConfig(options: RequiredFormulaXTiptapOptions): any {\n return {\n name: options.name,\n group: 'inline',\n inline: true,\n atom: true,\n selectable: true,\n addOptions() {\n return options;\n },\n addStorage() {\n return {\n preloadCleanup: null as null | (() => void),\n };\n },\n onCreate() {\n warnDuplicateNodeName(this);\n\n if (typeof document !== 'undefined') {\n ensureFormulaXBaseStyles(document);\n ensureFormulaXModalStyles(document);\n }\n\n const preloadCleanup = scheduleFormulaXEditorPreload(\n options.preload,\n this.editor?.view?.dom ?? null,\n );\n\n if (this.storage) {\n this.storage.preloadCleanup = preloadCleanup;\n }\n },\n onDestroy() {\n this.storage?.preloadCleanup?.();\n\n if (this.storage) {\n this.storage.preloadCleanup = null;\n }\n },\n addAttributes() {\n return {\n latex: {\n default: '',\n },\n };\n },\n parseHTML() {\n return [{\n tag: 'span[data-formulax]',\n getAttrs: (element: Node | string) => {\n if (!(element instanceof HTMLElement)) {\n return false;\n }\n\n return {\n latex: getFormulaLatexFromElement(element, this.options.formulaAttributeName),\n };\n },\n }];\n },\n renderHTML({ node }: { node: { attrs: FormulaXNodeAttributes } }) {\n if (typeof document === 'undefined') {\n return [\n 'span',\n {\n 'data-formulax': 'true',\n [this.options.formulaAttributeName]: node.attrs.latex,\n 'data-latex': node.attrs.latex,\n },\n node.attrs.latex || '\\\\square',\n ] as const;\n }\n\n return createFormulaDomElement(document, node.attrs, this.options);\n },\n addCommands() {\n return {\n openFormulaX: () => () => {\n const selectedFormula = getSelectedFormula(this.editor, this.name);\n const initialLatex = selectedFormula?.attrs.latex ?? this.options.initialLatex;\n\n void openFormulaXTiptapModal({\n initialLatex,\n isUpdate: Boolean(selectedFormula),\n options: this.options,\n }).then((payload) => {\n if (!payload) {\n return;\n }\n\n applyFormulaPayload(this.editor, payload, selectedFormula, this.name);\n this.editor.commands.focus();\n });\n\n return true;\n },\n };\n },\n addKeyboardShortcuts() {\n return {\n Enter: () => {\n if (!getSelectedFormula(this.editor, this.name)) {\n return false;\n }\n\n return this.editor.commands.openFormulaX();\n },\n Space: () => {\n if (!getSelectedFormula(this.editor, this.name)) {\n return false;\n }\n\n return this.editor.commands.openFormulaX();\n },\n };\n },\n addNodeView() {\n return ({ editor, getPos, node }: {\n editor: { commands: { openFormulaX: () => boolean; setNodeSelection?: (position: number) => boolean } };\n getPos: () => number;\n node: { attrs: FormulaXNodeAttributes };\n }) => {\n const dom = createFormulaDomElement(document, node.attrs, this.options) ?? document.createElement('span');\n dom.classList.add('formulax-math--interactive');\n void renderFormulaIntoElement(dom, node.attrs, this.options);\n\n const selectNode = (): void => {\n const position = getPos();\n if (typeof position !== 'number') {\n return;\n }\n\n editor.commands.setNodeSelection?.(position);\n };\n\n dom.addEventListener('click', (event) => {\n event.preventDefault();\n selectNode();\n });\n\n dom.addEventListener('dblclick', (event) => {\n event.preventDefault();\n event.stopPropagation();\n selectNode();\n editor.commands.openFormulaX();\n });\n\n return {\n dom,\n update: (updatedNode: { attrs: FormulaXNodeAttributes; type: { name: string } }) => {\n if (updatedNode.type.name !== this.name) {\n return false;\n }\n\n syncFormulaDomElement(dom, updatedNode.attrs, this.options);\n void renderFormulaIntoElement(dom, updatedNode.attrs, this.options);\n return true;\n },\n selectNode: () => {\n dom.classList.add('ProseMirror-selectednode');\n },\n deselectNode: () => {\n dom.classList.remove('ProseMirror-selectednode');\n },\n };\n };\n },\n };\n}\n\nexport interface TiptapNodeFactory {\n create: typeof Node.create;\n}\n\nexport function createFormulaXNode(\n nodeFactory: TiptapNodeFactory = Node,\n options?: FormulaXTiptapOptions,\n) {\n return nodeFactory.create(createFormulaXNodeConfig(resolveOptions(options))) as any;\n}\n\nexport const FormulaXNode = createFormulaXNode();\n\nexport const createFormulaXPayload = (latex: string): FormulaDoc => parseLatex(latex);\n\nexport const serializeFormulaXPayload = (doc: FormulaDoc): string => serializeLatex(doc);\n\nfunction applyFormulaPayload(\n editor: {\n chain: () => {\n focus: () => {\n deleteRange: (range: { from: number; to: number }) => { run: () => boolean };\n insertContent: (content: unknown) => { run: () => boolean };\n insertContentAt: (range: { from: number; to: number }, content: unknown) => { run: () => boolean };\n };\n };\n },\n payload: FormulaXPayload,\n selectedFormula: SelectedFormula | null,\n nodeName: string,\n): void {\n const latex = payload.latex.trim();\n\n if (selectedFormula) {\n if (!latex) {\n editor.chain().focus().deleteRange({\n from: selectedFormula.from,\n to: selectedFormula.to,\n }).run();\n return;\n }\n\n editor.chain().focus().insertContentAt(\n {\n from: selectedFormula.from,\n to: selectedFormula.to,\n },\n createFormulaNodeContent(payload, nodeName),\n ).run();\n return;\n }\n\n if (!latex) {\n return;\n }\n\n editor.chain().focus().insertContent(createFormulaNodeContent(payload, nodeName)).run();\n}\n\ninterface SelectedFormula {\n from: number;\n to: number;\n attrs: FormulaXNodeAttributes;\n}\n\nfunction getSelectedFormula(editor: {\n state: {\n selection: {\n from: number;\n to: number;\n node?: { type?: { name?: string }; attrs?: FormulaXNodeAttributes };\n };\n };\n}, nodeName: string): SelectedFormula | null {\n const { selection } = editor.state;\n const node = selection.node;\n\n if (node?.type?.name !== nodeName) {\n return null;\n }\n\n return {\n from: selection.from,\n to: selection.to,\n attrs: {\n latex: node.attrs?.latex ?? '',\n },\n };\n}\n\nfunction createFormulaNodeContent(\n payload: FormulaXPayload,\n nodeName = FORMULAX_NODE_NAME,\n): {\n type: string;\n attrs: FormulaXNodeAttributes;\n} {\n return {\n type: nodeName,\n attrs: {\n latex: payload.latex,\n },\n };\n}\n\nfunction createFormulaDomElement(\n ownerDocument: Document,\n attrs: FormulaXNodeAttributes,\n options: RequiredFormulaXTiptapOptions,\n): HTMLElement | null {\n return createFormulaElement(ownerDocument, attrs.latex, {\n attributeName: options.formulaAttributeName,\n className: options.formulaClassName,\n cursorStyle: options.cursorStyle,\n });\n}\n\nfunction syncFormulaDomElement(\n dom: HTMLElement,\n attrs: FormulaXNodeAttributes,\n options: RequiredFormulaXTiptapOptions,\n): void {\n const next = createFormulaDomElement(dom.ownerDocument ?? document, attrs, options);\n if (!next) {\n return;\n }\n\n dom.replaceChildren(...Array.from(next.childNodes));\n Array.from(dom.attributes).forEach((attribute) => {\n if (attribute.name === 'class') {\n return;\n }\n\n dom.removeAttribute(attribute.name);\n });\n\n Array.from(next.attributes).forEach((attribute) => {\n dom.setAttribute(attribute.name, attribute.value);\n });\n}\n\nasync function renderFormulaIntoElement(\n dom: HTMLElement,\n attrs: FormulaXNodeAttributes,\n options: RequiredFormulaXTiptapOptions,\n): Promise<void> {\n const latex = attrs.latex.trim();\n const renderToken = `${latex}::${Date.now()}::${Math.random().toString(36).slice(2, 8)}`;\n dom.dataset.renderToken = renderToken;\n\n if (!latex) {\n const placeholder = dom.querySelector<HTMLElement>(`.${options.formulaClassName}__render`);\n if (placeholder) {\n placeholder.textContent = '\\\\square';\n }\n return;\n }\n\n try {\n const result = await options.renderer.renderLatex(latex, {\n fontSize: options.editor.render.fontsize,\n className: options.formulaClassName,\n });\n if (dom.dataset.renderToken !== renderToken) {\n return;\n }\n\n dom.innerHTML = result.html;\n } catch (error) {\n if (dom.dataset.renderToken !== renderToken) {\n return;\n }\n\n console.error('[FormulaX] Failed to render Tiptap formula node:', error);\n const placeholder = dom.querySelector<HTMLElement>(`.${options.formulaClassName}__render`);\n if (placeholder) {\n placeholder.textContent = latex;\n }\n }\n}\n\nexport type { FormulaXPayload, FormulaXTiptapOptions, RequiredFormulaXTiptapOptions } from './types';\nexport { openFormulaXTiptapModal } from './modal';\n","import {\n clearFormulaXPerfMarks,\n ensureFormulaXModalStyles,\n markFormulaXPerf,\n measureFormulaXPerf,\n mountFormulaXEditor,\n recordFormulaXPerfPoint,\n renderFormulaXEditorLoadingState,\n waitForFormulaXAnimationFrame,\n} from '@formulaxjs/editor';\nimport {\n escapeAttribute,\n escapeHtml,\n} from '@formulaxjs/renderer';\nimport type { FormulaXPayload, RequiredFormulaXTiptapOptions } from './types';\n\nexport interface OpenFormulaXTiptapModalInput {\n initialLatex: string;\n isUpdate: boolean;\n options: RequiredFormulaXTiptapOptions;\n}\n\nexport function openFormulaXTiptapModal(\n input: OpenFormulaXTiptapModalInput,\n): Promise<FormulaXPayload | null> {\n recordFormulaXPerfPoint('fx:modal:open:start');\n const modalOpenStart = markFormulaXPerf('fx:modal:open:start:scope');\n ensureFormulaXModalStyles(document);\n\n const root = document.createElement('div');\n root.className = 'fx-formula-modal-root';\n root.setAttribute('data-formulax-modal', 'true');\n\n const submitText = input.isUpdate ? input.options.modal.updateText : input.options.modal.insertText;\n\n root.innerHTML = `\n <div class=\"fx-formula-modal-backdrop\" data-action=\"backdrop\"></div>\n <div class=\"fx-formula-modal\" role=\"dialog\" aria-modal=\"true\" aria-label=\"${escapeAttribute(input.options.modal.title)}\">\n <header class=\"fx-formula-modal__header\">\n <h2 class=\"fx-formula-modal__title\">${escapeHtml(input.options.modal.title)}</h2>\n <button class=\"fx-formula-modal__close\" type=\"button\" data-action=\"close\" aria-label=\"Close\">×</button>\n </header>\n <section class=\"fx-formula-modal__body\">\n <div class=\"fx-formula-editor-host\"></div>\n </section>\n <footer class=\"fx-formula-modal__footer\">\n <button class=\"fx-formula-modal__button\" type=\"button\" data-action=\"cancel\">${escapeHtml(input.options.modal.cancelText)}</button>\n <button class=\"fx-formula-modal__button fx-formula-modal__button--primary\" type=\"button\" data-action=\"submit\">${escapeHtml(submitText)}</button>\n </footer>\n </div>\n `;\n\n document.body.appendChild(root);\n document.body.classList.add('fx-formula-modal-open');\n const modalDomReadyMark = markFormulaXPerf('fx:modal:dom-ready');\n measureFormulaXPerf('fx:modal:dom-ready', modalOpenStart, modalDomReadyMark);\n clearFormulaXPerfMarks(modalDomReadyMark);\n\n const host = root.querySelector<HTMLElement>('.fx-formula-editor-host');\n if (!host) {\n root.remove();\n clearFormulaXPerfMarks(modalOpenStart);\n return Promise.reject(new Error('[FormulaX] Tiptap modal host not found.'));\n }\n\n renderFormulaXEditorLoadingState(host);\n let closed = false;\n let mounted: ReturnType<typeof mountFormulaXEditor> | null = null;\n\n const mountedPromise = waitForFormulaXAnimationFrame()\n .then(() => {\n if (closed) {\n clearFormulaXPerfMarks(modalOpenStart);\n return null;\n }\n\n const mountStartMark = markFormulaXPerf('fx:modal:editor-mount-start');\n measureFormulaXPerf('fx:modal:editor-mount-start', modalOpenStart, mountStartMark);\n clearFormulaXPerfMarks(mountStartMark);\n\n const nextMounted = mountFormulaXEditor(host, {\n initialLatex: input.initialLatex,\n height: input.options.editor.height,\n autofocus: input.options.editor.autofocus,\n assets: input.options.editor.assets,\n render: {\n fontsize: input.options.editor.render.fontsize,\n },\n });\n\n mounted = nextMounted;\n\n const mountedMark = markFormulaXPerf('fx:modal:editor-mounted');\n measureFormulaXPerf('fx:modal:editor-mounted', modalOpenStart, mountedMark);\n clearFormulaXPerfMarks(mountedMark, modalOpenStart);\n\n queueMicrotask(() => {\n if (!closed) {\n nextMounted.root.focus();\n }\n });\n\n return nextMounted;\n })\n .catch((error) => {\n clearFormulaXPerfMarks(modalOpenStart);\n throw error;\n });\n\n return new Promise((resolve) => {\n const close = (payload: FormulaXPayload | null): void => {\n if (closed) {\n return;\n }\n\n closed = true;\n mounted?.destroy();\n root.removeEventListener('click', onClick);\n document.removeEventListener('keydown', onKeydown, true);\n root.remove();\n document.body.classList.remove('fx-formula-modal-open');\n resolve(payload);\n };\n\n const submit = async (): Promise<void> => {\n try {\n const activeMounted = mounted ?? await mountedPromise;\n if (!activeMounted) {\n return;\n }\n\n const latex = await activeMounted.getLatex();\n close({ latex });\n } catch (error) {\n host.innerHTML = `\n <div class=\"fx-formula-editor-error\">\n Failed to read FormulaX editor content.\n <pre>${escapeHtml(error instanceof Error ? error.message : String(error))}</pre>\n </div>\n `;\n }\n };\n\n function onClick(event: MouseEvent): void {\n const action = (event.target as HTMLElement).closest<HTMLElement>('[data-action]')?.dataset.action;\n if (!action) {\n return;\n }\n\n if (action === 'submit') {\n void submit();\n return;\n }\n\n if (action === 'cancel' || action === 'close') {\n close(null);\n return;\n }\n\n if (action === 'backdrop' && input.options.modal.closeOnBackdrop) {\n close(null);\n }\n }\n\n function onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape') {\n event.preventDefault();\n close(null);\n }\n }\n\n root.addEventListener('click', onClick);\n document.addEventListener('keydown', onKeydown, true);\n });\n}\n"],"mappings":"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","names":["import_core","import_renderer","import_editor"]}