@pie-lib/editable-html-tip-tap 3.1.2-next.20261020155912 → 3.1.2-next.20261021000713

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.
@@ -228,7 +228,8 @@ var S = {
228
228
  te.configure(K),
229
229
  re.configure({
230
230
  toolbarOpts: P,
231
- math: y.pluginProps?.math || {}
231
+ math: y.pluginProps?.math || {},
232
+ mathMlOptions: y.mathMlOptions || {}
232
233
  }),
233
234
  ve,
234
235
  _e,
@@ -279,7 +280,11 @@ var S = {
279
280
  onBlur: ({ editor: e }) => {
280
281
  !k(e) && e.schema && (U.current?.cancel(), R(e));
281
282
  }
282
- }, [y.charactersLimit]);
283
+ }, [
284
+ y.charactersLimit,
285
+ y.mathMlOptions?.mmlEditing,
286
+ y.mathMlOptions?.mmlOutput
287
+ ]);
283
288
  m(() => {
284
289
  y.editorRef && y.editorRef(Q);
285
290
  }, [y.editorRef, Q]), m(() => {
@@ -1,6 +1,18 @@
1
1
  import React from 'react';
2
2
  import { Node } from '@tiptap/core';
3
3
  import { Plugin } from 'prosemirror-state';
4
+ /**
5
+ * LaTeX for a MathML string, or null when there is none to give. `mmlToLatex` answers an empty
6
+ * string for MathML it cannot read, and the input back when its converter throws; neither is LaTeX,
7
+ * and neither may become a math node.
8
+ */
9
+ export declare const convertMathMlToLatex: (mathMl: any) => string | null;
10
+ /**
11
+ * MathML for LaTeX, or null when there is none to give: MathJax has not started, or cannot read the
12
+ * LaTeX. A caller keeps the LaTeX then. The MathML carries the LaTeX it was made from, so that
13
+ * editing it again reads that back exactly, where converting the MathML would lose some.
14
+ */
15
+ export declare const convertLatexToMathMl: (latex: any, wrapper: any) => string | null;
4
16
  export declare const EnsureTextAfterMathPlugin: (mathNodeName: any) => Plugin<any>;
5
17
  export declare const ZeroWidthSpaceHandlingPlugin: Plugin<any>;
6
18
  export declare const MathNode: Node<any, any>;
@@ -6,16 +6,42 @@ import { Node as s } from "@tiptap/core";
6
6
  import { NodeSelection as c, Plugin as l, PluginKey as u, TextSelection as d } from "prosemirror-state";
7
7
  import f from "react-dom";
8
8
  import { jsx as p, jsxs as m } from "react/jsx-runtime";
9
- import { unWrapMath as h, wrapMath as g } from "@pie-element/shared-math-rendering-mathjax";
10
- import { MathPreview as _, MathToolbar as v } from "@pie-lib/math-toolbar";
9
+ import { latexToMml as h, mmlToLatex as g, unWrapMath as _, wrapMath as v } from "@pie-element/shared-math-rendering-mathjax";
10
+ import { MathPreview as y, MathToolbar as b } from "@pie-lib/math-toolbar";
11
11
  //#region src/extensions/math.tsx
12
- var y = new u("ensureTextAfterMath"), b = (e = []) => e.map((e) => ({
12
+ var x = /\\left\.\s*|\\right\.\s*/g, S = /<mo(?: [^>]*)?>&#x2061;<\/mo>/g, C = {
13
+ open: "\\[",
14
+ close: "\\]"
15
+ }, w = "data-pie-latex", T = (e) => e.replaceAll("&", "&amp;").replaceAll("\"", "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"), E = (e) => typeof e == "string" ? e === "double_dollar" : ["$$", "\\["].includes(e?.open), D = (e) => {
16
+ let t = e.replaceAll("&nbsp;", " "), n = g(t);
17
+ return !n || n === t ? null : n.replace(x, "") || null;
18
+ }, O = (e, t) => {
19
+ let n = h(e, { display: E(t) });
20
+ return !n || !n.startsWith("<math") ? null : n.replace(S, "").replace("<math", () => `<math ${w}="${T(e)}"`);
21
+ }, k = (e, t, n) => {
22
+ if (!t?.mathMlOptions?.mmlEditing) return !1;
23
+ let r = n?.getAttribute("display") === "block" ? C : null, i = (n?.getAttribute(w) ?? n?.getAttribute("data-latex"))?.trim();
24
+ if (i) return {
25
+ latex: i,
26
+ wrapper: r
27
+ };
28
+ let a = D(e);
29
+ if (a === null) return !1;
30
+ let { unwrapped: o, wrapper: s } = _(a);
31
+ return {
32
+ latex: o,
33
+ wrapper: s || r
34
+ };
35
+ }, A = (e) => {
36
+ let t = document.implementation.createHTMLDocument("").createElement("span");
37
+ return t.setAttribute("data-type", "mathml"), t.innerHTML = e, t;
38
+ }, j = new u("ensureTextAfterMath"), M = (e = []) => e.map((e) => ({
13
39
  name: e,
14
40
  latex: e,
15
41
  write: e,
16
42
  label: e
17
- })), x = (e) => new l({
18
- key: y,
43
+ })), N = (e) => new l({
44
+ key: j,
19
45
  appendTransaction: (t, n, r) => {
20
46
  if (!t.some((e) => e.docChanged)) return null;
21
47
  let i = r.tr, a = !1;
@@ -26,7 +52,7 @@ var y = new u("ensureTextAfterMath"), b = (e = []) => e.map((e) => ({
26
52
  }
27
53
  }), a ? i : null;
28
54
  }
29
- }), S = (e, t) => {
55
+ }), P = (e, t) => {
30
56
  let n;
31
57
  for (n = t; n > 0; n--) {
32
58
  let t = e.nodeAt(n);
@@ -34,16 +60,16 @@ var y = new u("ensureTextAfterMath"), b = (e = []) => e.map((e) => ({
34
60
  if (t && t?.type?.name !== "text") break;
35
61
  }
36
62
  return n;
37
- }, C = new l({
63
+ }, F = new l({
38
64
  key: new u("zeroWidthSpaceHandling"),
39
65
  props: { handleKeyDown(e, t) {
40
66
  let { state: n, dispatch: r } = e, { selection: i, doc: a } = n, { from: o, empty: s } = i;
41
67
  if (s && t.key === "Backspace" && o > 0) {
42
- let e = S(a, o);
68
+ let e = P(a, o);
43
69
  return e !== -1 && (r(n.tr.delete(e, o)), !0);
44
70
  }
45
71
  if (s && t.key === "ArrowLeft" && o > 0) {
46
- let e = S(a, o);
72
+ let e = P(a, o);
47
73
  if (e === -1) return !1;
48
74
  let t = n.doc.resolve(e);
49
75
  if (t.nodeAfter || t.nodeBefore) {
@@ -54,7 +80,7 @@ var y = new u("ensureTextAfterMath"), b = (e = []) => e.map((e) => ({
54
80
  }
55
81
  return !1;
56
82
  } }
57
- }), w = s.create({
83
+ }), I = s.create({
58
84
  name: "math",
59
85
  group: "inline",
60
86
  inline: !0,
@@ -67,16 +93,35 @@ var y = new u("ensureTextAfterMath"), b = (e = []) => e.map((e) => ({
67
93
  };
68
94
  },
69
95
  addProseMirrorPlugins() {
70
- return [x(this.name), C];
96
+ return [N(this.name), F];
71
97
  },
72
98
  parseHTML() {
73
- return [{
74
- tag: "span[data-latex]",
75
- getAttrs: (e) => ({ latex: h(e.getAttribute("data-raw") || e.textContent).unwrapped })
76
- }, {
77
- tag: "span[data-type=\"mathml\"]",
78
- getAttrs: (e) => ({ html: e.innerHTML })
79
- }];
99
+ return [
100
+ {
101
+ tag: "span[data-latex]",
102
+ getAttrs: (e) => ({ latex: _(e.getAttribute("data-raw") || e.textContent).unwrapped })
103
+ },
104
+ {
105
+ tag: "span[data-type=\"mathml\"]",
106
+ priority: 60,
107
+ getAttrs: (e) => {
108
+ let t = e.querySelector("math");
109
+ return k(t?.outerHTML || e.innerHTML, this.options, t);
110
+ }
111
+ },
112
+ {
113
+ tag: "math",
114
+ getAttrs: (e) => k(e.outerHTML, this.options, e)
115
+ },
116
+ {
117
+ tag: "span[data-type=\"mathml\"]",
118
+ getAttrs: (e) => ({ html: e.innerHTML })
119
+ },
120
+ {
121
+ tag: "math",
122
+ getAttrs: (e) => ({ html: e.outerHTML })
123
+ }
124
+ ];
80
125
  },
81
126
  addCommands() {
82
127
  return { insertMath: (e = "") => ({ tr: n, editor: r, dispatch: i }) => {
@@ -89,32 +134,34 @@ var y = new u("ensureTextAfterMath"), b = (e = []) => e.map((e) => ({
89
134
  } };
90
135
  },
91
136
  renderHTML({ HTMLAttributes: e }) {
92
- return e.html ? ["span", {
93
- "data-type": "mathml",
94
- dangerouslySetInnerHTML: { __html: e.html }
95
- }] : [
137
+ if (e.html) return A(e.html);
138
+ if (this.options.mathMlOptions?.mmlOutput) {
139
+ let t = O(e.latex, e.wrapper);
140
+ if (t) return A(t);
141
+ }
142
+ return [
96
143
  "span",
97
144
  {
98
145
  "data-latex": "",
99
146
  "data-raw": e.latex
100
147
  },
101
- g(e.latex, e.wrapper)
148
+ v(e.latex, e.wrapper)
102
149
  ];
103
150
  },
104
151
  addNodeView() {
105
- return o((e) => /* @__PURE__ */ p(T, {
152
+ return o((e) => /* @__PURE__ */ p(L, {
106
153
  ...e,
107
154
  options: this.options
108
155
  }));
109
156
  }
110
- }), T = (o) => {
111
- let { node: s, updateAttributes: c, editor: l, selected: u, options: h, getPos: g } = o, [y, x] = i(u), S = r(null), C = r(null), w = r(Date.now()), [T, E] = i({
157
+ }), L = (o) => {
158
+ let { node: s, updateAttributes: c, editor: l, selected: u, options: h, getPos: g } = o, [_, v] = i(u), x = r(null), S = r(null), C = r(Date.now()), [w, T] = i({
112
159
  top: 0,
113
160
  left: 0
114
- }), { math: D = {} } = h || {}, { keypadMode: O, controlledKeypadMode: k = !0, customKeys: A = [], keyPadCharacterRef: j, setKeypadInteraction: M } = D, N = s.attrs.latex || "", P = (e) => {
161
+ }), { math: E = {} } = h || {}, { keypadMode: D, controlledKeypadMode: O = !0, customKeys: k = [], keyPadCharacterRef: A, setKeypadInteraction: j } = E, N = s.attrs.latex || "", P = (e) => {
115
162
  c({ latex: e });
116
163
  }, F = (e, { moveCursorAfterNode: t = !0 } = {}) => {
117
- if (c({ latex: e }), x(!1), t && typeof g == "function") {
164
+ if (c({ latex: e }), v(!1), t && typeof g == "function") {
118
165
  let e = g(), { doc: t } = l.state, n = d.create(t, e + s.nodeSize), r = l.state.tr.setSelection(n);
119
166
  l.view.dispatch(r);
120
167
  }
@@ -123,27 +170,27 @@ var y = new u("ensureTextAfterMath"), b = (e = []) => e.map((e) => ({
123
170
  return n(() => {
124
171
  if (!u) return;
125
172
  let { selection: e } = l.state;
126
- e.node?.type?.name === "math" && x(!0);
173
+ e.node?.type?.name === "math" && v(!0);
127
174
  }, [u, l]), n(() => {
128
- t(l, u || y);
175
+ t(l, u || _);
129
176
  }, [
130
177
  l,
131
- y,
178
+ _,
132
179
  u
133
180
  ]), n(() => {
134
- if (!l || !y) {
135
- E({
181
+ if (!l || !_) {
182
+ T({
136
183
  top: 0,
137
184
  left: 0
138
185
  });
139
186
  return;
140
187
  }
141
188
  let e = () => {
142
- if (!S.current) return;
143
- let { from: e } = l.state.selection, t = l.view.coordsAtPos(e), n = C.current?.getBoundingClientRect?.(), r = n?.height ? n.top : t.top, i = n?.width ? n.left : t.left, a = n?.height ? n.bottom : t.bottom ?? t.top, o = S.current.offsetHeight, s = S.current.offsetWidth, c = window.innerHeight - (a + 0) >= o ? a + 0 : r - o - 0, u = i;
189
+ if (!x.current) return;
190
+ let { from: e } = l.state.selection, t = l.view.coordsAtPos(e), n = S.current?.getBoundingClientRect?.(), r = n?.height ? n.top : t.top, i = n?.width ? n.left : t.left, a = n?.height ? n.bottom : t.bottom ?? t.top, o = x.current.offsetHeight, s = x.current.offsetWidth, c = window.innerHeight - (a + 0) >= o ? a + 0 : r - o - 0, u = i;
144
191
  c = Math.max(8, Math.min(c, window.innerHeight - o - 8)), u = Math.max(8, Math.min(u, window.innerWidth - s - 8));
145
192
  let d = (l._tiptapContainerEl || document.body).getBoundingClientRect();
146
- E({
193
+ T({
147
194
  top: c - d.top,
148
195
  left: u - d.left
149
196
  });
@@ -159,23 +206,32 @@ var y = new u("ensureTextAfterMath"), b = (e = []) => e.map((e) => ({
159
206
  }), window.addEventListener("scroll", n, !0), window.addEventListener("resize", n), () => {
160
207
  t !== null && cancelAnimationFrame(t), window.removeEventListener("scroll", n, !0), window.removeEventListener("resize", n);
161
208
  };
162
- }, [l, y]), n(() => {
209
+ }, [l, _]), n(() => {
163
210
  let e = performance.now(), t = (t) => {
164
211
  if (t?.timeStamp < e) return;
165
- let n = t?.target, r = (document.querySelectorAll?.("[id^=\"equation-editor-select\"][id*=\"listbox\"], [aria-labelledby=\"equation-editor-label\"][role=\"listbox\"]") || []).length > 0, i = !!(n?.id && n.id.includes("equation-editor-select")) || !!n?.closest?.("[id*=\"equation-editor-select\"]"), a = !!n?.closest?.(`.math-node-${w.current}`);
166
- if (S.current && !S.current.contains(n) && !n?.closest?.("[data-inline-node]") && !r && !i && !a) {
167
- x(!1);
212
+ let n = t?.target, r = (document.querySelectorAll?.("[id^=\"equation-editor-select\"][id*=\"listbox\"], [aria-labelledby=\"equation-editor-label\"][role=\"listbox\"]") || []).length > 0, i = !!(n?.id && n.id.includes("equation-editor-select")) || !!n?.closest?.("[id*=\"equation-editor-select\"]"), a = !!n?.closest?.(`.math-node-${C.current}`);
213
+ if (x.current && !x.current.contains(n) && !n?.closest?.("[data-inline-node]") && !r && !i && !a) {
214
+ v(!1);
168
215
  let e = !!l?.view?.dom?.contains(n);
169
216
  F(s.attrs.latex, { moveCursorAfterNode: !e });
170
217
  }
171
218
  };
172
- return y ? document.addEventListener("click", t) : document.removeEventListener("click", t), () => document.removeEventListener("click", t);
219
+ return _ ? document.addEventListener("click", t) : document.removeEventListener("click", t), () => document.removeEventListener("click", t);
173
220
  }, [
174
221
  l,
175
- y,
222
+ _,
176
223
  s
177
- ]), /* @__PURE__ */ m(a, {
178
- className: `math-node-${w.current}`,
224
+ ]), s.attrs.html && !N ? /* @__PURE__ */ p(a, {
225
+ as: "span",
226
+ "data-type": "mathml",
227
+ style: {
228
+ display: "inline-block",
229
+ margin: "0 4px"
230
+ },
231
+ contentEditable: !1,
232
+ dangerouslySetInnerHTML: { __html: s.attrs.html }
233
+ }) : /* @__PURE__ */ m(a, {
234
+ className: `math-node-${C.current}`,
179
235
  style: {
180
236
  display: "inline-flex",
181
237
  cursor: "pointer",
@@ -183,34 +239,34 @@ var y = new u("ensureTextAfterMath"), b = (e = []) => e.map((e) => ({
183
239
  },
184
240
  "data-selected": u,
185
241
  children: [/* @__PURE__ */ p("div", {
186
- ref: C,
187
- onClick: () => x(!0),
188
- contentEditable: !1,
189
- children: /* @__PURE__ */ p(_, { latex: N })
190
- }), y && f.createPortal(/* @__PURE__ */ p("div", {
191
242
  ref: S,
243
+ onClick: () => v(!0),
244
+ contentEditable: !1,
245
+ children: /* @__PURE__ */ p(y, { latex: N })
246
+ }), _ && f.createPortal(/* @__PURE__ */ p("div", {
247
+ ref: x,
192
248
  "data-toolbar-for": l.instanceId,
193
249
  style: {
194
250
  position: "absolute",
195
- top: `${T.top}px`,
196
- left: `${T.left}px`,
251
+ top: `${w.top}px`,
252
+ left: `${w.left}px`,
197
253
  zIndex: 1e3,
198
254
  background: e,
199
255
  boxShadow: "0px 1px 5px 0px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 3px 1px -2px rgba(0, 0, 0, 0.12)"
200
256
  },
201
- children: /* @__PURE__ */ p(v, {
257
+ children: /* @__PURE__ */ p(b, {
202
258
  latex: N,
203
259
  autoFocus: !0,
204
260
  onChange: P,
205
261
  onDone: F,
206
- keypadMode: O,
207
- controlledKeypadMode: k,
208
- additionalKeys: b(A),
209
- keyPadCharacterRef: j,
210
- setKeypadInteraction: M
262
+ keypadMode: D,
263
+ controlledKeypadMode: O,
264
+ additionalKeys: M(k),
265
+ keyPadCharacterRef: A,
266
+ setKeypadInteraction: j
211
267
  })
212
268
  }), l?._tiptapContainerEl || document.body)]
213
269
  });
214
270
  };
215
271
  //#endregion
216
- export { x as EnsureTextAfterMathPlugin, w as MathNode, T as MathNodeView, C as ZeroWidthSpaceHandlingPlugin };
272
+ export { N as EnsureTextAfterMathPlugin, I as MathNode, L as MathNodeView, F as ZeroWidthSpaceHandlingPlugin, O as convertLatexToMathMl, D as convertMathMlToLatex };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pie-lib/editable-html-tip-tap",
3
- "version": "3.1.2-next.20261020155912",
3
+ "version": "3.1.2-next.20261021000713",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,10 +13,10 @@
13
13
  "@dnd-kit/utilities": "3.2.2",
14
14
  "@mui/icons-material": "^7.3.4",
15
15
  "@mui/material": "^7.3.4",
16
- "@pie-lib/drag": "5.0.7-next.20261020155912",
17
- "@pie-lib/math-input": "9.0.7-next.20261020155912",
18
- "@pie-lib/math-toolbar": "4.0.7-next.20261020155912",
19
- "@pie-lib/render-ui": "8.0.7-next.20261020155912",
16
+ "@pie-lib/drag": "5.0.7-next.20261021000713",
17
+ "@pie-lib/math-input": "9.0.7-next.20261021000713",
18
+ "@pie-lib/math-toolbar": "4.0.7-next.20261021000713",
19
+ "@pie-lib/render-ui": "8.0.7-next.20261021000713",
20
20
  "@pie-lib/translator": "5.0.2-next.20261019155156",
21
21
  "@tiptap/core": "3.32.0",
22
22
  "@tiptap/extension-character-count": "3.32.0",
@@ -46,7 +46,7 @@
46
46
  "@pie-element/shared-lodash": "0.1.3-next.20261020155912",
47
47
  "clsx": "^2.1.1",
48
48
  "prosemirror-state": "^1.4.4",
49
- "@pie-element/shared-math-rendering-mathjax": "0.1.8-next.20261019155156",
49
+ "@pie-element/shared-math-rendering-mathjax": "0.1.8-next.20261021000713",
50
50
  "@tiptap/extensions": "3.32.0",
51
51
  "@tiptap/extension-list": "3.32.0",
52
52
  "@tiptap/extension-bubble-menu": "3.32.0",