@formulaxjs/tiptap 0.2.1 → 0.2.2

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
@@ -64,7 +64,7 @@ function openFormulaXTiptapModal(input) {
64
64
  root.remove();
65
65
  return Promise.reject(new Error("[FormulaX] Tiptap modal host not found."));
66
66
  }
67
- const mounted = (0, import_editor.mountFormulaXKityEditor)(host, {
67
+ const mounted = (0, import_editor.mountFormulaXEditor)(host, {
68
68
  initialLatex: input.initialLatex,
69
69
  height: input.options.editor.height,
70
70
  autofocus: input.options.editor.autofocus,
@@ -415,7 +415,7 @@ function renderFormulaSvgMarkup(latex, options) {
415
415
  host.style.pointerEvents = "none";
416
416
  host.setAttribute("aria-hidden", "true");
417
417
  document.body.appendChild(host);
418
- const mounted = (0, import_editor2.mountFormulaXKityEditor)(host, {
418
+ const mounted = (0, import_editor2.mountFormulaXEditor)(host, {
419
419
  initialLatex: latex,
420
420
  height: options.editor.height,
421
421
  autofocus: false,
@@ -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 mountFormulaXKityEditor,\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 = mountFormulaXKityEditor(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 mountFormulaXKityEditor,\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 = mountFormulaXKityEditor(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 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"]}
@@ -4012,7 +4012,7 @@ var FormulaX = (() => {
4012
4012
  }
4013
4013
  });
4014
4014
 
4015
- // ../kity-runtime/dist/chunk-EKIJQ64F.js
4015
+ // ../kity-runtime/dist/chunk-53JBJHMR.js
4016
4016
  function getLegacyEventId(target) {
4017
4017
  return target.__kfeEventId ?? target.__kfe_eid;
4018
4018
  }
@@ -4157,23 +4157,7 @@ var FormulaX = (() => {
4157
4157
  return node.classList;
4158
4158
  }
4159
4159
  function createLegacyUiUtils() {
4160
- return {
4161
- ele: createElement,
4162
- getRectBox,
4163
- on(target, type, fn) {
4164
- addEvent(target, type, fn);
4165
- return this;
4166
- },
4167
- delegate(target, selector, type, fn) {
4168
- delegateEvent(target, selector, type, fn);
4169
- return this;
4170
- },
4171
- publish(topic, ...args) {
4172
- publish(topic, ...args);
4173
- },
4174
- subscribe,
4175
- getClassList
4176
- };
4160
+ return legacyUiUtils;
4177
4161
  }
4178
4162
  function setToolbarAssetUrls(assets) {
4179
4163
  toolbarAssetFileMap = {
@@ -4189,9 +4173,9 @@ var FormulaX = (() => {
4189
4173
  }
4190
4174
  throw new Error(`Missing Kity toolbar asset URL for "${normalizedFileName}".`);
4191
4175
  }
4192
- var legacyBoxType, legacyKfEvent, eventListenerStore, eventId, beforeResult, eventHandler, legacyEventListener, utils, utils_default, legacyBaseUtils, legacyEleType, legacyGroupType, replacementMap, legacyInputFilter, legacyItemType, legacyKfExtDef, legacySysconf, legacyUiDef, topicPool, legacyOtherPosition, toolbarAssetFileMap;
4193
- var init_chunk_EKIJQ64F = __esm({
4194
- "../kity-runtime/dist/chunk-EKIJQ64F.js"() {
4176
+ var legacyBoxType, legacyKfEvent, eventListenerStore, eventId, beforeResult, eventHandler, legacyEventListener, utils, utils_default, legacyBaseUtils, legacyEleType, legacyGroupType, replacementMap, legacyInputFilter, legacyItemType, legacyKfExtDef, legacySysconf, legacyUiDef, topicPool, legacyUiUtils, legacyOtherPosition, toolbarAssetFileMap;
4177
+ var init_chunk_53JBJHMR = __esm({
4178
+ "../kity-runtime/dist/chunk-53JBJHMR.js"() {
4195
4179
  "use strict";
4196
4180
  init_lodash();
4197
4181
  init_lodash();
@@ -4391,6 +4375,23 @@ var FormulaX = (() => {
4391
4375
  }
4392
4376
  };
4393
4377
  topicPool = /* @__PURE__ */ new Map();
4378
+ legacyUiUtils = {
4379
+ ele: createElement,
4380
+ getRectBox,
4381
+ on(target, type, fn) {
4382
+ addEvent(target, type, fn);
4383
+ return this;
4384
+ },
4385
+ delegate(target, selector, type, fn) {
4386
+ delegateEvent(target, selector, type, fn);
4387
+ return this;
4388
+ },
4389
+ publish(topic, ...args) {
4390
+ publish(topic, ...args);
4391
+ },
4392
+ subscribe,
4393
+ getClassList
4394
+ };
4394
4395
  legacyOtherPosition = {
4395
4396
  "x=\\frac {-b\\pm\\sqrt {b^2-4ac}}{2a}": {
4396
4397
  "pos": {
@@ -14245,9 +14246,9 @@ var FormulaX = (() => {
14245
14246
  }
14246
14247
  });
14247
14248
 
14248
- // ../kity-runtime/dist/start-GQH6XUBI.js
14249
- var start_GQH6XUBI_exports = {};
14250
- __export(start_GQH6XUBI_exports, {
14249
+ // ../kity-runtime/dist/start-2M6472FZ.js
14250
+ var start_2M6472FZ_exports = {};
14251
+ __export(start_2M6472FZ_exports, {
14251
14252
  Factory: () => factory_default,
14252
14253
  KFEditor: () => editor_default,
14253
14254
  default: () => start_default,
@@ -14977,10 +14978,10 @@ var FormulaX = (() => {
14977
14978
  };
14978
14979
  }
14979
14980
  var defaultOptions, components, kity, kf, KFEditor, editor_default, EditorWrapper, factory, factory_default, PREFIX, LIST_OFFSET, DEFAULT_OPTIONS2, $$, kity2, Button, button_default, PREFIX2, $$2, kity3, List, list_default, kity4, $$3, PREFIX3, BOX_TYPE, ITEM_TYPE, SCROLL_STEP, BoxItem, Box, box_default, PREFIX4, PANEL_HEIGHT, $$4, kity5, Area, area_default, PREFIX5, $$5, kity6, Delimiter, delimiter_default, $$6, kity7, DrapdownBox, dropdown_box_default, UiImpl, ui_impl_default, $$7, kity8, Toolbar, toolbar_default, SCROLLBAR_DEF, SCROLLBAR_CONF, CLASS_PREFIX, kity9, Scrollbar, scrollbar_default, UNICODE_SYMBOLS, STYLE_FONT_MAP, UI_ELE_TYPE, BOX_TYPE2, OTHER_POSITION, config, toolbar_config_default, $$8, VIEW_STATE, DEFAULT_EDIT_AREA_HEIGHT, kity10, UIComponent, ui_default, kity11, kf2, PlaceholderOperator, kf_ext_placeholder_operator_default, kity12, kf3, BaseCompoundExpression, PlaceholderExpression, kf_ext_placeholder_expression_default, kf4, kf_ext_extension_default, legacyVirtualGroupMap, vgroup_def_default, CURSOR_CHAR, ROOT_P_TEXT, COMBINATION_NAME, PID_PREFIX, pidSeed, kity13, kf5, BaseComponent, Parser, parser_default, DEFAULT_OPTIONS22, kity14, kf6, BaseComponent2, RenderComponent, render_default, kity15, PositionComponent, position_default, kity16, DeleteComponent, syntax_delete_default, kity17, MoveComponent, syntax_move_default, CURSOR_CHAR2, kity18, SyntaxComponent, syntax_default, KEY_CODE, kity19, InputComponent, input_default, kity20, LocationComponent, location_default, MAX_DISTANCE, kity21, SelectionComponent, selection_default, kity22, ListenerComponent, listener_default, kity23, ControllerComponent, controller_default, kity24, Printer, printer_default, installed3, start_default;
14980
- var init_start_GQH6XUBI = __esm({
14981
- "../kity-runtime/dist/start-GQH6XUBI.js"() {
14981
+ var init_start_2M6472FZ = __esm({
14982
+ "../kity-runtime/dist/start-2M6472FZ.js"() {
14982
14983
  "use strict";
14983
- init_chunk_EKIJQ64F();
14984
+ init_chunk_53JBJHMR();
14984
14985
  defaultOptions = {
14985
14986
  formula: {
14986
14987
  fontsize: 50,
@@ -26798,7 +26799,7 @@ var FormulaX = (() => {
26798
26799
  var serializeLatex = (document2) => serializeNode(document2);
26799
26800
 
26800
26801
  // ../kity-runtime/dist/index.js
26801
- init_chunk_EKIJQ64F();
26802
+ init_chunk_53JBJHMR();
26802
26803
  var btn_default = "./btn-5DANP6JY.png";
26803
26804
  var other_default = "./other-OMWJFGL5.png";
26804
26805
  var editor_default2 = "./editor-JT5KLVXX.css?url";
@@ -30283,7 +30284,7 @@ var FormulaX = (() => {
30283
30284
  kity: runtimeWindow.kity,
30284
30285
  otherPosition: legacyOtherPosition,
30285
30286
  uiDef: legacyUiDef,
30286
- uiUtils: createLegacyUiUtils()
30287
+ uiUtils: legacyUiUtils
30287
30288
  };
30288
30289
  }
30289
30290
  async function ensureKityRuntime() {
@@ -30300,7 +30301,7 @@ var FormulaX = (() => {
30300
30301
  const { installLegacyParserRuntime: installLegacyParserRuntime2 } = await Promise.resolve().then(() => (init_install_HKCG5NWK(), install_HKCG5NWK_exports));
30301
30302
  installLegacyParserRuntime2(runtimeWindow);
30302
30303
  installLegacyRuntime(runtimeWindow);
30303
- const { installKityEditorStart: installKityEditorStart2 } = await Promise.resolve().then(() => (init_start_GQH6XUBI(), start_GQH6XUBI_exports));
30304
+ const { installKityEditorStart: installKityEditorStart2 } = await Promise.resolve().then(() => (init_start_2M6472FZ(), start_2M6472FZ_exports));
30304
30305
  installKityEditorStart2(runtimeWindow);
30305
30306
  })();
30306
30307
  return runtimePromise;
@@ -30707,7 +30708,7 @@ var FormulaX = (() => {
30707
30708
  style.textContent = formulaXModalStyles;
30708
30709
  doc2.head.appendChild(style);
30709
30710
  }
30710
- function mountFormulaXKityEditor(root2, options = {}) {
30711
+ function mountFormulaXEditor(root2, options = {}) {
30711
30712
  let destroyed = false;
30712
30713
  let latestLatex = options.initialLatex ?? "";
30713
30714
  let handle = null;
@@ -31147,7 +31148,7 @@ var FormulaX = (() => {
31147
31148
  root2.remove();
31148
31149
  return Promise.reject(new Error("[FormulaX] Tiptap modal host not found."));
31149
31150
  }
31150
- const mounted = mountFormulaXKityEditor(host, {
31151
+ const mounted = mountFormulaXEditor(host, {
31151
31152
  initialLatex: input.initialLatex,
31152
31153
  height: input.options.editor.height,
31153
31154
  autofocus: input.options.editor.autofocus,
@@ -31498,7 +31499,7 @@ var FormulaX = (() => {
31498
31499
  host.style.pointerEvents = "none";
31499
31500
  host.setAttribute("aria-hidden", "true");
31500
31501
  document.body.appendChild(host);
31501
- const mounted = mountFormulaXKityEditor(host, {
31502
+ const mounted = mountFormulaXEditor(host, {
31502
31503
  initialLatex: latex,
31503
31504
  height: options.editor.height,
31504
31505
  autofocus: false,