@pie-lib/math-input-mathlive 1.0.6 → 1.0.8

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.
Files changed (40) hide show
  1. package/lib/__tests__/composites.test.js +255 -0
  2. package/lib/__tests__/composites.test.js.map +1 -0
  3. package/lib/__tests__/keypad-label.test.js +6 -7
  4. package/lib/__tests__/keypad-label.test.js.map +1 -1
  5. package/lib/__tests__/keypad-render.test.js +206 -0
  6. package/lib/__tests__/keypad-render.test.js.map +1 -0
  7. package/lib/__tests__/latex-bridge.test.js +65 -0
  8. package/lib/__tests__/latex-bridge.test.js.map +1 -1
  9. package/lib/__tests__/mathlive-instance.test.js +18 -0
  10. package/lib/__tests__/mathlive-instance.test.js.map +1 -1
  11. package/lib/__tests__/mount-race.test.js +194 -0
  12. package/lib/__tests__/mount-race.test.js.map +1 -0
  13. package/lib/__tests__/static-prompts.test.js +282 -0
  14. package/lib/__tests__/static-prompts.test.js.map +1 -0
  15. package/lib/keypad/index.js +4 -28
  16. package/lib/keypad/index.js.map +1 -1
  17. package/lib/latex-bridge.js +124 -4
  18. package/lib/latex-bridge.js.map +1 -1
  19. package/lib/mathlive-instance.js +28 -4
  20. package/lib/mathlive-instance.js.map +1 -1
  21. package/lib/mf/common-styles.js +13 -0
  22. package/lib/mf/common-styles.js.map +1 -1
  23. package/lib/mf/input.js +18 -5
  24. package/lib/mf/input.js.map +1 -1
  25. package/lib/mf/static.js +24 -7
  26. package/lib/mf/static.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/__tests__/composites.test.jsx +220 -0
  29. package/src/__tests__/keypad-label.test.jsx +1 -1
  30. package/src/__tests__/keypad-render.test.jsx +123 -0
  31. package/src/__tests__/latex-bridge.test.js +87 -1
  32. package/src/__tests__/mathlive-instance.test.js +20 -0
  33. package/src/__tests__/mount-race.test.jsx +129 -0
  34. package/src/__tests__/static-prompts.test.jsx +251 -0
  35. package/src/keypad/index.jsx +3 -25
  36. package/src/latex-bridge.js +128 -3
  37. package/src/mathlive-instance.js +29 -5
  38. package/src/mf/common-styles.js +13 -0
  39. package/src/mf/input.jsx +19 -5
  40. package/src/mf/static.jsx +23 -4
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.toMathLive = exports.keyToAction = exports.fromMathLive = exports.fieldIds = exports.NEWLINE_EMBED = exports.KEYSTROKES = exports.DEFAULT_FIELD_ID = exports.COMMANDS_WITH_ARGS = void 0;
6
+ exports.withVisibleEmptySlots = exports.toNativeCommands = exports.toMathLive = exports.keyToAction = exports.fromMathLive = exports.fieldIds = exports.NEWLINE_EMBED = exports.KEYSTROKES = exports.DEFAULT_FIELD_ID = exports.COMMANDS_WITH_ARGS = void 0;
7
7
  /**
8
8
  * LaTeX translation layer between the MathQuill-era content model and MathLive.
9
9
  *
@@ -35,9 +35,114 @@ var DISPLAYLINES_REGEX = /^\\displaylines\{([\s\S]*)\}$/;
35
35
  var MQ_FIELD_REGEX = /\\MathQuillMathField\[([^\]]*)\]\{([^{}]*)\}/g;
36
36
  var PLACEHOLDER_REGEX = /\\placeholder\[([^\]]*)\]\{([^{}]*)\}/g;
37
37
 
38
+ /**
39
+ * Unnamed placeholders, which MathLive inserts on its own.
40
+ *
41
+ * Typing a command with empty arguments (`\longdiv{}`, `\frac{}{}`) makes
42
+ * MathLive serialise the empty slots as `\placeholder{}`. That token is
43
+ * MathLive-specific: MathJax - which @pie-lib/math-rendering uses to render
44
+ * prompts and previews - has no such command and renders it as red error text.
45
+ * Stored latex must therefore keep plain empty groups.
46
+ */
47
+ var BARE_PLACEHOLDER_REGEX = /\\placeholder\{([^{}]*)\}/g;
48
+ var BARE_PLACEHOLDER_NO_ARG_REGEX = /\\placeholder(?![[{a-zA-Z])/g;
49
+
38
50
  /** Default id used when stored latex has an unnamed field. */
39
51
  var DEFAULT_FIELD_ID = exports.DEFAULT_FIELD_ID = 'r1';
40
52
 
53
+ /**
54
+ * A visible stand-in for an empty argument slot, used for STATIC rendering only.
55
+ *
56
+ * Stored latex legitimately contains empty groups - `\longdiv{}`, `\frac{}{}`,
57
+ * `x^{}` - to express a command's shape. MathQuill drew those as a shaded box
58
+ * (`.mq-empty`); MathLive renders `{}` as nothing, so `convertLatexToMarkup`
59
+ * output comes out completely blank (not even the surrounding bracket, in the
60
+ * case of `\enclose{longdiv}{}`).
61
+ *
62
+ * `\placeholder{}` is not usable here: in static markup it renders as a
63
+ * non-breaking space, because its editable box only exists inside a live
64
+ * mathfield. So an actual glyph is required.
65
+ *
66
+ * Live mathfields need none of this - MathLive manages empty slots itself.
67
+ */
68
+ var EMPTY_SLOT = "\\htmlData{pie-empty=1}{\\unicode{\"25AB}}";
69
+ var EMPTY_GROUP_REGEX = /\{\s*\}/g;
70
+
71
+ /**
72
+ * Make empty argument slots visible, for static rendering.
73
+ *
74
+ * Display-only: never feed the result to a mathfield or to storage - the
75
+ * original latex is what gets typed and saved.
76
+ *
77
+ * @param {string} latex
78
+ * @returns {string}
79
+ */
80
+ var withVisibleEmptySlots = exports.withVisibleEmptySlots = function withVisibleEmptySlots(latex) {
81
+ return (latex || '').replace(EMPTY_GROUP_REGEX, "{".concat(EMPTY_SLOT, "}"));
82
+ };
83
+
84
+ /**
85
+ * Pie commands that take an argument, and their native MathLive equivalents.
86
+ *
87
+ * These MUST NOT be handled as MathLive macros. A macro is serialised from the
88
+ * arguments it was created with, so text typed inside its expansion never makes
89
+ * it back out: `getValue('latex')` keeps returning `\longdiv{\placeholder{}}`
90
+ * while `getValue('ascii-math')` shows the typed content. Setting
91
+ * `captureSelection: false` lets the cursor in but does not change
92
+ * serialisation.
93
+ *
94
+ * Expanding to native constructs instead gives real, editable atoms that
95
+ * round-trip. All three targets are understood by MathJax too, so stored latex
96
+ * still renders in @pie-lib/math-rendering without a reverse mapping.
97
+ */
98
+ /**
99
+ * Rewrite argument-taking pie commands into native MathLive latex.
100
+ * Applied on the way *into* a mathfield.
101
+ *
102
+ * @param {string} latex
103
+ * @returns {string}
104
+ */
105
+ var toNativeCommands = exports.toNativeCommands = function toNativeCommands(latex) {
106
+ if (typeof latex !== 'string' || !latex) {
107
+ return latex || '';
108
+ }
109
+ var out = latex;
110
+
111
+ // \abs{x} -> \left|x\right| needs brace-aware handling, the rest are prefix
112
+ // swaps.
113
+ out = replaceAbs(out);
114
+ out = out.replace(/\\longdiv\{/g, '\\enclose{longdiv}{');
115
+ out = out.replace(/\\overarc\{/g, '\\overparen{');
116
+ return out;
117
+ };
118
+
119
+ /** `\abs{x}` -> `\left|x\right|`, matching balanced braces. */
120
+ var replaceAbs = function replaceAbs(latex) {
121
+ var out = latex;
122
+ var idx = out.indexOf('\\abs{');
123
+ while (idx !== -1) {
124
+ var open = idx + '\\abs{'.length - 1;
125
+ var depth = 0;
126
+ var close = -1;
127
+ for (var i = open; i < out.length; i++) {
128
+ if (out[i] === '{') depth++;else if (out[i] === '}') {
129
+ depth--;
130
+ if (depth === 0) {
131
+ close = i;
132
+ break;
133
+ }
134
+ }
135
+ }
136
+ if (close === -1) {
137
+ break;
138
+ }
139
+ var inner = out.slice(open + 1, close);
140
+ out = "".concat(out.slice(0, idx), "\\left|").concat(inner, "\\right|").concat(out.slice(close + 1));
141
+ idx = out.indexOf('\\abs{');
142
+ }
143
+ return out;
144
+ };
145
+
41
146
  /**
42
147
  * Ids of the answer blocks in a piece of stored latex, in document order.
43
148
  *
@@ -69,8 +174,12 @@ var toMathLive = exports.toMathLive = function toMathLive(latex) {
69
174
  return latex || '';
70
175
  }
71
176
 
177
+ // Argument-taking pie commands -> native constructs, so their content stays
178
+ // editable and serialises back correctly (see toNativeCommands).
179
+ var out = toNativeCommands(latex);
180
+
72
181
  // Answer blocks: \MathQuillMathField[id]{x} -> \placeholder[id]{x}
73
- var out = latex.replace(MQ_FIELD_REGEX, function (_m, id, content) {
182
+ out = out.replace(MQ_FIELD_REGEX, function (_m, id, content) {
74
183
  return "\\placeholder[".concat(id || DEFAULT_FIELD_ID, "]{").concat(content, "}");
75
184
  });
76
185
 
@@ -107,6 +216,15 @@ var fromMathLive = exports.fromMathLive = function fromMathLive(latex) {
107
216
  out = out.replace(PLACEHOLDER_REGEX, function (_m, id, content) {
108
217
  return "\\MathQuillMathField[".concat(id || DEFAULT_FIELD_ID, "]{").concat(content, "}");
109
218
  });
219
+
220
+ // Unnamed placeholders are MathLive's own representation of an empty slot and
221
+ // must not reach storage or MathJax. Unwrap them: keep any content, drop the
222
+ // command itself (the surrounding braces are already part of the host latex,
223
+ // so re-adding them here would produce `\longdiv{{}}`).
224
+ out = out.replace(BARE_PLACEHOLDER_REGEX, function (_m, content) {
225
+ return content;
226
+ });
227
+ out = out.replace(BARE_PLACEHOLDER_NO_ARG_REGEX, '');
110
228
  return out;
111
229
  };
112
230
 
@@ -123,8 +241,10 @@ var COMMANDS_WITH_ARGS = exports.COMMANDS_WITH_ARGS = {
123
241
  '\\overline': '\\overline{#?}',
124
242
  '\\overrightarrow': '\\overrightarrow{#?}',
125
243
  '\\overleftrightarrow': '\\overleftrightarrow{#?}',
126
- '\\overarc': '\\overarc{#?}',
127
- '\\longdiv': '\\longdiv{#?}',
244
+ // Native forms, not the pie macros: a macro would not serialise the user's
245
+ // typed content back out (see toNativeCommands).
246
+ '\\overarc': '\\overparen{#?}',
247
+ '\\longdiv': '\\enclose{longdiv}{#?}',
128
248
  '^': '^{#?}',
129
249
  _: '_{#?}',
130
250
  '(': '\\left(#?\\right)',
@@ -1 +1 @@
1
- {"version":3,"file":"latex-bridge.js","names":["NEWLINE_EMBED","exports","NEWLINE_EMBED_REGEX","DISPLAYLINES_REGEX","MQ_FIELD_REGEX","PLACEHOLDER_REGEX","DEFAULT_FIELD_ID","fieldIds","latex","out","match","lastIndex","exec","push","toMathLive","replace","_m","id","content","concat","indexOf","split","join","fromMathLive","trim","map","s","COMMANDS_WITH_ARGS","_","KEYSTROKES","Left","Right","Backspace","Delete","Up","Down","keyToAction","key","undefined","command","type","value","write","parts","Array","isArray","c","keystroke","selector"],"sources":["../src/latex-bridge.js"],"sourcesContent":["/**\n * LaTeX translation layer between the MathQuill-era content model and MathLive.\n *\n * Two independent concerns live here:\n *\n * 1. Newlines. MathQuill had no line break, so pie-lib registered a custom\n * `newLine` embed that serialises to `\\embed{newLine}[]`. MathLive has no\n * embed system but supports real multiline environments, so we translate\n * `\\embed{newLine}[]` <-> `\\\\` inside `\\displaylines{}`.\n *\n * Authored content keeps its `\\embed{newLine}[]` on-disk form (that is what\n * @pie-lib/math-rendering already normalises for MathJax), so each renderer\n * normalises at its own boundary and stored items stay compatible.\n *\n * 2. Keypad key -> MathLive action. MathQuill keys carry `write`/`command`/\n * `keystroke` built for `mf.write()` / `mf.cmd()` / `mf.keystroke()`.\n * MathLive has `insert()` and `executeCommand()` instead.\n */\n\nexport const NEWLINE_EMBED = '\\\\embed{newLine}[]';\nconst NEWLINE_EMBED_REGEX = /\\\\embed\\{newLine\\}\\[\\]/g;\nconst DISPLAYLINES_REGEX = /^\\\\displaylines\\{([\\s\\S]*)\\}$/;\n\n/**\n * MathQuill's editable sub-field syntax, e.g. `\\MathQuillMathField[r1]{}`.\n * These are the answer blocks in templated math items; MathLive expresses the\n * same idea as `\\placeholder[id]{}` and reads them back via the prompts API.\n */\nconst MQ_FIELD_REGEX = /\\\\MathQuillMathField\\[([^\\]]*)\\]\\{([^{}]*)\\}/g;\nconst PLACEHOLDER_REGEX = /\\\\placeholder\\[([^\\]]*)\\]\\{([^{}]*)\\}/g;\n\n/** Default id used when stored latex has an unnamed field. */\nexport const DEFAULT_FIELD_ID = 'r1';\n\n/**\n * Ids of the answer blocks in a piece of stored latex, in document order.\n *\n * @param {string} latex\n * @returns {string[]}\n */\nexport const fieldIds = (latex) => {\n if (typeof latex !== 'string') {\n return [];\n }\n\n const out = [];\n let match;\n\n MQ_FIELD_REGEX.lastIndex = 0;\n\n while ((match = MQ_FIELD_REGEX.exec(latex)) !== null) {\n out.push(match[1] || DEFAULT_FIELD_ID);\n }\n\n return out;\n};\n\n/**\n * Convert stored latex (which may contain `\\embed{newLine}[]`) into latex that\n * MathLive can parse and render as multiple lines.\n *\n * @param {string} latex\n * @returns {string}\n */\nexport const toMathLive = (latex) => {\n if (typeof latex !== 'string' || !latex) {\n return latex || '';\n }\n\n // Answer blocks: \\MathQuillMathField[id]{x} -> \\placeholder[id]{x}\n let out = latex.replace(MQ_FIELD_REGEX, (_m, id, content) => `\\\\placeholder[${id || DEFAULT_FIELD_ID}]{${content}}`);\n\n // Newlines: \\embed{newLine}[] -> a multiline environment\n if (out.indexOf(NEWLINE_EMBED) !== -1) {\n out = `\\\\displaylines{${out.split(NEWLINE_EMBED_REGEX).join(' \\\\\\\\ ')}}`;\n }\n\n return out;\n};\n\n/**\n * Convert latex out of MathLive back into the stored form, so items authored\n * with the MathLive editor remain readable by @pie-lib/math-rendering and by\n * the existing MathQuill implementation.\n *\n * @param {string} latex\n * @returns {string}\n */\nexport const fromMathLive = (latex) => {\n if (typeof latex !== 'string' || !latex) {\n return latex || '';\n }\n\n const match = latex.trim().match(DISPLAYLINES_REGEX);\n let out = match ? match[1] : latex;\n\n // `\\\\` is the line separator inside a multiline environment.\n if (out.indexOf('\\\\\\\\') !== -1) {\n out = out\n .split(/\\s*\\\\\\\\\\s*/)\n .map((s) => s.trim())\n .join(NEWLINE_EMBED);\n }\n\n // Answer blocks: \\placeholder[id]{x} -> \\MathQuillMathField[id]{x}\n out = out.replace(\n PLACEHOLDER_REGEX,\n (_m, id, content) => `\\\\MathQuillMathField[${id || DEFAULT_FIELD_ID}]{${content}}`,\n );\n\n return out;\n};\n\n/**\n * MathQuill `cmd()` semantics: commands that take arguments should land the\n * cursor inside the first argument. MathLive expresses that with `#?`\n * placeholders in the inserted latex.\n */\nconst COMMANDS_WITH_ARGS = {\n '\\\\frac': '\\\\frac{#?}{#?}',\n '/': '\\\\frac{#?}{#?}',\n '\\\\sqrt': '\\\\sqrt{#?}',\n '\\\\nthroot': '\\\\sqrt[#?]{#?}',\n '\\\\overline': '\\\\overline{#?}',\n '\\\\overrightarrow': '\\\\overrightarrow{#?}',\n '\\\\overleftrightarrow': '\\\\overleftrightarrow{#?}',\n '\\\\overarc': '\\\\overarc{#?}',\n '\\\\longdiv': '\\\\longdiv{#?}',\n '^': '^{#?}',\n _: '_{#?}',\n '(': '\\\\left(#?\\\\right)',\n '[': '\\\\left[#?\\\\right]',\n '|': '\\\\left|#?\\\\right|',\n};\n\n/**\n * MathQuill keystroke names -> MathLive command selectors.\n */\nconst KEYSTROKES = {\n Left: 'moveToPreviousChar',\n Right: 'moveToNextChar',\n Backspace: 'deleteBackward',\n Delete: 'deleteForward',\n Up: 'moveUp',\n Down: 'moveDown',\n};\n\n/**\n * Translate a keypad key definition into a MathLive action.\n *\n * Mirrors the precedence in @pie-lib/math-input's MathInput.keypadPress:\n * latex (unless a command is present) -> write -> command -> keystroke.\n *\n * @param {object} key\n * @returns {{type: 'insert'|'command', value: string}|undefined}\n */\nexport const keyToAction = (key) => {\n if (!key) {\n return undefined;\n }\n\n if (key.latex && !key.command) {\n return { type: 'insert', value: key.latex };\n }\n\n if (key.write) {\n return { type: 'insert', value: key.write };\n }\n\n if (key.command) {\n // Some keys carry an array of commands (e.g. Measured Angle is\n // ['m', '\\\\angle'], log-base-n is ['\\\\log', '_']). MathQuill's `cmd()`\n // applied them in sequence; MathLive inserts one latex string, so expand\n // each part and concatenate.\n const parts = Array.isArray(key.command) ? key.command : [key.command];\n const value = parts.map((c) => COMMANDS_WITH_ARGS[c] || c).join('');\n\n return { type: 'insert', value };\n }\n\n if (key.keystroke) {\n const selector = KEYSTROKES[key.keystroke];\n\n return selector ? { type: 'command', value: selector } : undefined;\n }\n\n return undefined;\n};\n\nexport { COMMANDS_WITH_ARGS, KEYSTROKES };\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"latex-bridge.js","names":["NEWLINE_EMBED","exports","NEWLINE_EMBED_REGEX","DISPLAYLINES_REGEX","MQ_FIELD_REGEX","PLACEHOLDER_REGEX","BARE_PLACEHOLDER_REGEX","BARE_PLACEHOLDER_NO_ARG_REGEX","DEFAULT_FIELD_ID","EMPTY_SLOT","EMPTY_GROUP_REGEX","withVisibleEmptySlots","latex","replace","concat","toNativeCommands","out","replaceAbs","idx","indexOf","open","length","depth","close","i","inner","slice","fieldIds","match","lastIndex","exec","push","toMathLive","_m","id","content","split","join","fromMathLive","trim","map","s","COMMANDS_WITH_ARGS","_","KEYSTROKES","Left","Right","Backspace","Delete","Up","Down","keyToAction","key","undefined","command","type","value","write","parts","Array","isArray","c","keystroke","selector"],"sources":["../src/latex-bridge.js"],"sourcesContent":["/**\n * LaTeX translation layer between the MathQuill-era content model and MathLive.\n *\n * Two independent concerns live here:\n *\n * 1. Newlines. MathQuill had no line break, so pie-lib registered a custom\n * `newLine` embed that serialises to `\\embed{newLine}[]`. MathLive has no\n * embed system but supports real multiline environments, so we translate\n * `\\embed{newLine}[]` <-> `\\\\` inside `\\displaylines{}`.\n *\n * Authored content keeps its `\\embed{newLine}[]` on-disk form (that is what\n * @pie-lib/math-rendering already normalises for MathJax), so each renderer\n * normalises at its own boundary and stored items stay compatible.\n *\n * 2. Keypad key -> MathLive action. MathQuill keys carry `write`/`command`/\n * `keystroke` built for `mf.write()` / `mf.cmd()` / `mf.keystroke()`.\n * MathLive has `insert()` and `executeCommand()` instead.\n */\n\nexport const NEWLINE_EMBED = '\\\\embed{newLine}[]';\nconst NEWLINE_EMBED_REGEX = /\\\\embed\\{newLine\\}\\[\\]/g;\nconst DISPLAYLINES_REGEX = /^\\\\displaylines\\{([\\s\\S]*)\\}$/;\n\n/**\n * MathQuill's editable sub-field syntax, e.g. `\\MathQuillMathField[r1]{}`.\n * These are the answer blocks in templated math items; MathLive expresses the\n * same idea as `\\placeholder[id]{}` and reads them back via the prompts API.\n */\nconst MQ_FIELD_REGEX = /\\\\MathQuillMathField\\[([^\\]]*)\\]\\{([^{}]*)\\}/g;\nconst PLACEHOLDER_REGEX = /\\\\placeholder\\[([^\\]]*)\\]\\{([^{}]*)\\}/g;\n\n/**\n * Unnamed placeholders, which MathLive inserts on its own.\n *\n * Typing a command with empty arguments (`\\longdiv{}`, `\\frac{}{}`) makes\n * MathLive serialise the empty slots as `\\placeholder{}`. That token is\n * MathLive-specific: MathJax - which @pie-lib/math-rendering uses to render\n * prompts and previews - has no such command and renders it as red error text.\n * Stored latex must therefore keep plain empty groups.\n */\nconst BARE_PLACEHOLDER_REGEX = /\\\\placeholder\\{([^{}]*)\\}/g;\nconst BARE_PLACEHOLDER_NO_ARG_REGEX = /\\\\placeholder(?![[{a-zA-Z])/g;\n\n/** Default id used when stored latex has an unnamed field. */\nexport const DEFAULT_FIELD_ID = 'r1';\n\n/**\n * A visible stand-in for an empty argument slot, used for STATIC rendering only.\n *\n * Stored latex legitimately contains empty groups - `\\longdiv{}`, `\\frac{}{}`,\n * `x^{}` - to express a command's shape. MathQuill drew those as a shaded box\n * (`.mq-empty`); MathLive renders `{}` as nothing, so `convertLatexToMarkup`\n * output comes out completely blank (not even the surrounding bracket, in the\n * case of `\\enclose{longdiv}{}`).\n *\n * `\\placeholder{}` is not usable here: in static markup it renders as a\n * non-breaking space, because its editable box only exists inside a live\n * mathfield. So an actual glyph is required.\n *\n * Live mathfields need none of this - MathLive manages empty slots itself.\n */\nconst EMPTY_SLOT = '\\\\htmlData{pie-empty=1}{\\\\unicode{\"25AB}}';\nconst EMPTY_GROUP_REGEX = /\\{\\s*\\}/g;\n\n/**\n * Make empty argument slots visible, for static rendering.\n *\n * Display-only: never feed the result to a mathfield or to storage - the\n * original latex is what gets typed and saved.\n *\n * @param {string} latex\n * @returns {string}\n */\nexport const withVisibleEmptySlots = (latex) => (latex || '').replace(EMPTY_GROUP_REGEX, `{${EMPTY_SLOT}}`);\n\n/**\n * Pie commands that take an argument, and their native MathLive equivalents.\n *\n * These MUST NOT be handled as MathLive macros. A macro is serialised from the\n * arguments it was created with, so text typed inside its expansion never makes\n * it back out: `getValue('latex')` keeps returning `\\longdiv{\\placeholder{}}`\n * while `getValue('ascii-math')` shows the typed content. Setting\n * `captureSelection: false` lets the cursor in but does not change\n * serialisation.\n *\n * Expanding to native constructs instead gives real, editable atoms that\n * round-trip. All three targets are understood by MathJax too, so stored latex\n * still renders in @pie-lib/math-rendering without a reverse mapping.\n */\n/**\n * Rewrite argument-taking pie commands into native MathLive latex.\n * Applied on the way *into* a mathfield.\n *\n * @param {string} latex\n * @returns {string}\n */\nexport const toNativeCommands = (latex) => {\n if (typeof latex !== 'string' || !latex) {\n return latex || '';\n }\n\n let out = latex;\n\n // \\abs{x} -> \\left|x\\right| needs brace-aware handling, the rest are prefix\n // swaps.\n out = replaceAbs(out);\n out = out.replace(/\\\\longdiv\\{/g, '\\\\enclose{longdiv}{');\n out = out.replace(/\\\\overarc\\{/g, '\\\\overparen{');\n\n return out;\n};\n\n/** `\\abs{x}` -> `\\left|x\\right|`, matching balanced braces. */\nconst replaceAbs = (latex) => {\n let out = latex;\n let idx = out.indexOf('\\\\abs{');\n\n while (idx !== -1) {\n const open = idx + '\\\\abs{'.length - 1;\n let depth = 0;\n let close = -1;\n\n for (let i = open; i < out.length; i++) {\n if (out[i] === '{') depth++;\n else if (out[i] === '}') {\n depth--;\n if (depth === 0) {\n close = i;\n break;\n }\n }\n }\n\n if (close === -1) {\n break;\n }\n\n const inner = out.slice(open + 1, close);\n\n out = `${out.slice(0, idx)}\\\\left|${inner}\\\\right|${out.slice(close + 1)}`;\n idx = out.indexOf('\\\\abs{');\n }\n\n return out;\n};\n\n/**\n * Ids of the answer blocks in a piece of stored latex, in document order.\n *\n * @param {string} latex\n * @returns {string[]}\n */\nexport const fieldIds = (latex) => {\n if (typeof latex !== 'string') {\n return [];\n }\n\n const out = [];\n let match;\n\n MQ_FIELD_REGEX.lastIndex = 0;\n\n while ((match = MQ_FIELD_REGEX.exec(latex)) !== null) {\n out.push(match[1] || DEFAULT_FIELD_ID);\n }\n\n return out;\n};\n\n/**\n * Convert stored latex (which may contain `\\embed{newLine}[]`) into latex that\n * MathLive can parse and render as multiple lines.\n *\n * @param {string} latex\n * @returns {string}\n */\nexport const toMathLive = (latex) => {\n if (typeof latex !== 'string' || !latex) {\n return latex || '';\n }\n\n // Argument-taking pie commands -> native constructs, so their content stays\n // editable and serialises back correctly (see toNativeCommands).\n let out = toNativeCommands(latex);\n\n // Answer blocks: \\MathQuillMathField[id]{x} -> \\placeholder[id]{x}\n out = out.replace(MQ_FIELD_REGEX, (_m, id, content) => `\\\\placeholder[${id || DEFAULT_FIELD_ID}]{${content}}`);\n\n // Newlines: \\embed{newLine}[] -> a multiline environment\n if (out.indexOf(NEWLINE_EMBED) !== -1) {\n out = `\\\\displaylines{${out.split(NEWLINE_EMBED_REGEX).join(' \\\\\\\\ ')}}`;\n }\n\n return out;\n};\n\n/**\n * Convert latex out of MathLive back into the stored form, so items authored\n * with the MathLive editor remain readable by @pie-lib/math-rendering and by\n * the existing MathQuill implementation.\n *\n * @param {string} latex\n * @returns {string}\n */\nexport const fromMathLive = (latex) => {\n if (typeof latex !== 'string' || !latex) {\n return latex || '';\n }\n\n const match = latex.trim().match(DISPLAYLINES_REGEX);\n let out = match ? match[1] : latex;\n\n // `\\\\` is the line separator inside a multiline environment.\n if (out.indexOf('\\\\\\\\') !== -1) {\n out = out\n .split(/\\s*\\\\\\\\\\s*/)\n .map((s) => s.trim())\n .join(NEWLINE_EMBED);\n }\n\n // Answer blocks: \\placeholder[id]{x} -> \\MathQuillMathField[id]{x}\n out = out.replace(\n PLACEHOLDER_REGEX,\n (_m, id, content) => `\\\\MathQuillMathField[${id || DEFAULT_FIELD_ID}]{${content}}`,\n );\n\n // Unnamed placeholders are MathLive's own representation of an empty slot and\n // must not reach storage or MathJax. Unwrap them: keep any content, drop the\n // command itself (the surrounding braces are already part of the host latex,\n // so re-adding them here would produce `\\longdiv{{}}`).\n out = out.replace(BARE_PLACEHOLDER_REGEX, (_m, content) => content);\n out = out.replace(BARE_PLACEHOLDER_NO_ARG_REGEX, '');\n\n return out;\n};\n\n/**\n * MathQuill `cmd()` semantics: commands that take arguments should land the\n * cursor inside the first argument. MathLive expresses that with `#?`\n * placeholders in the inserted latex.\n */\nconst COMMANDS_WITH_ARGS = {\n '\\\\frac': '\\\\frac{#?}{#?}',\n '/': '\\\\frac{#?}{#?}',\n '\\\\sqrt': '\\\\sqrt{#?}',\n '\\\\nthroot': '\\\\sqrt[#?]{#?}',\n '\\\\overline': '\\\\overline{#?}',\n '\\\\overrightarrow': '\\\\overrightarrow{#?}',\n '\\\\overleftrightarrow': '\\\\overleftrightarrow{#?}',\n // Native forms, not the pie macros: a macro would not serialise the user's\n // typed content back out (see toNativeCommands).\n '\\\\overarc': '\\\\overparen{#?}',\n '\\\\longdiv': '\\\\enclose{longdiv}{#?}',\n '^': '^{#?}',\n _: '_{#?}',\n '(': '\\\\left(#?\\\\right)',\n '[': '\\\\left[#?\\\\right]',\n '|': '\\\\left|#?\\\\right|',\n};\n\n/**\n * MathQuill keystroke names -> MathLive command selectors.\n */\nconst KEYSTROKES = {\n Left: 'moveToPreviousChar',\n Right: 'moveToNextChar',\n Backspace: 'deleteBackward',\n Delete: 'deleteForward',\n Up: 'moveUp',\n Down: 'moveDown',\n};\n\n/**\n * Translate a keypad key definition into a MathLive action.\n *\n * Mirrors the precedence in @pie-lib/math-input's MathInput.keypadPress:\n * latex (unless a command is present) -> write -> command -> keystroke.\n *\n * @param {object} key\n * @returns {{type: 'insert'|'command', value: string}|undefined}\n */\nexport const keyToAction = (key) => {\n if (!key) {\n return undefined;\n }\n\n if (key.latex && !key.command) {\n return { type: 'insert', value: key.latex };\n }\n\n if (key.write) {\n return { type: 'insert', value: key.write };\n }\n\n if (key.command) {\n // Some keys carry an array of commands (e.g. Measured Angle is\n // ['m', '\\\\angle'], log-base-n is ['\\\\log', '_']). MathQuill's `cmd()`\n // applied them in sequence; MathLive inserts one latex string, so expand\n // each part and concatenate.\n const parts = Array.isArray(key.command) ? key.command : [key.command];\n const value = parts.map((c) => COMMANDS_WITH_ARGS[c] || c).join('');\n\n return { type: 'insert', value };\n }\n\n if (key.keystroke) {\n const selector = KEYSTROKES[key.keystroke];\n\n return selector ? { type: 'command', value: selector } : undefined;\n }\n\n return undefined;\n};\n\nexport { COMMANDS_WITH_ARGS, KEYSTROKES };\n"],"mappings":"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","ignoreList":[]}
@@ -5,6 +5,7 @@ var _typeof = require("@babel/runtime/helpers/typeof");
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
+ exports.MATH_MODE_SPACE = void 0;
8
9
  Object.defineProperty(exports, "NEWLINE_EMBED", {
9
10
  enumerable: true,
10
11
  get: function get() {
@@ -89,6 +90,18 @@ var configureFonts = exports.configureFonts = function configureFonts(dir) {
89
90
  }
90
91
  };
91
92
 
93
+ /**
94
+ * What the spacebar inserts in math mode.
95
+ *
96
+ * MathLive's `mathModeSpace` defaults to an empty string, which makes the
97
+ * spacebar a no-op - users cannot type a space at all. `\\ ` (a LaTeX control
98
+ * space) is what MathQuill serialised spaces as, so existing content and the
99
+ * MathJax renderer in @pie-lib/math-rendering both already understand it.
100
+ *
101
+ * A literal " " is not usable: LaTeX skips raw whitespace.
102
+ */
103
+ var MATH_MODE_SPACE = exports.MATH_MODE_SPACE = '\\ ';
104
+
92
105
  /**
93
106
  * Custom macros for the pie-specific commands that the MathQuill fork
94
107
  * understood but stock LaTeX does not.
@@ -98,8 +111,9 @@ var configureFonts = exports.configureFonts = function configureFonts(dir) {
98
111
  * way in the editor and in the static renderer.
99
112
  */
100
113
  var PIE_MACROS = exports.PIE_MACROS = {
114
+ // Argument-less symbols. Atomic is correct here: backspace should remove the
115
+ // whole glyph, and there is nothing to type into.
101
116
  parallelogram: "\\htmlData{pie-macro=parallelogram}{\\unicode{\"25B1}}",
102
- overarc: '\\overparen{#1}',
103
117
  napprox: '\\not\\approx',
104
118
  nsim: '\\not\\sim',
105
119
  ncong: '\\not\\cong',
@@ -108,7 +122,14 @@ var PIE_MACROS = exports.PIE_MACROS = {
108
122
  divide: '\\div',
109
123
  degree: '^{\\circ}',
110
124
  square: "\\unicode{\"25A1}",
111
- longdiv: '\\htmlData{pie-macro=longdiv}{#1}',
125
+ // Argument-taking commands, kept ONLY so previously authored latex still
126
+ // parses and renders. They are never used for editing: MathLive serialises a
127
+ // macro from the arguments it was created with, so text typed inside the
128
+ // expansion never comes back out of `getValue('latex')`. Anything entering a
129
+ // mathfield is rewritten to the native equivalent first - see
130
+ // `toNativeCommands` in latex-bridge.
131
+ longdiv: '\\enclose{longdiv}{#1}',
132
+ overarc: '\\overparen{#1}',
112
133
  abs: '\\left|#1\\right|'
113
134
  };
114
135
 
@@ -376,7 +397,7 @@ function applyStaticMath(element, latex) {
376
397
  });
377
398
  return undefined;
378
399
  }
379
- element.innerHTML = ml.convertLatexToMarkup((0, _latexBridge.toMathLive)(source), {
400
+ element.innerHTML = ml.convertLatexToMarkup((0, _latexBridge.withVisibleEmptySlots)((0, _latexBridge.toMathLive)(source)), {
380
401
  macros: _objectSpread(_objectSpread({}, getMacros()), options.macros || {})
381
402
  });
382
403
  return element;
@@ -399,7 +420,10 @@ function latexToMarkup(latex) {
399
420
  return '';
400
421
  }
401
422
  try {
402
- return ml.convertLatexToMarkup((0, _latexBridge.toMathLive)(latex), _objectSpread({
423
+ // Empty groups render as nothing in static markup, so give them a visible
424
+ // box. This covers every static path: keypad labels, mf.Static in display
425
+ // mode, and applyStaticMath.
426
+ return ml.convertLatexToMarkup((0, _latexBridge.withVisibleEmptySlots)((0, _latexBridge.toMathLive)(latex)), _objectSpread({
403
427
  macros: _objectSpread(_objectSpread({}, getMacros()), options.macros || {})
404
428
  }, options));
405
429
  } catch (e) {
@@ -1 +1 @@
1
- {"version":3,"file":"mathlive-instance.js","names":["_debug","_interopRequireDefault","require","_latexBridge","ownKeys","e","r","t","Object","keys","getOwnPropertySymbols","o","filter","getOwnPropertyDescriptor","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty2","getOwnPropertyDescriptors","defineProperties","defineProperty","_interopRequireWildcard","WeakMap","n","__esModule","i","f","__proto__","_typeof","has","get","set","_t2","hasOwnProperty","call","log","debug","mathlive","fontsDirectory","absoluteFontsDirectory","dir","test","URL","document","baseURI","href","message","configureFonts","exports","MathfieldElement","PIE_MACROS","parallelogram","overarc","napprox","nsim","ncong","nparallel","perpendicular","divide","degree","square","longdiv","abs","embeds","Map","KNOWN_EMBED_LATEX","newLine","answerBlock","loadWarned","configureLoaded","undefined","injectCoreStylesheet","renderMathInElement","createElement","loadMathLiveSync","window","loadMathLive","_ref","_asyncToGenerator2","_regenerator","mark","_callee","_t","wrap","_context","prev","next","abrupt","Promise","resolve","then","sent","process","env","NODE_ENV","console","warn","stop","getMathLive","getMacros","out","_ref2","name","latex","concat","registerEmbed","factory","definition","prototype","mathliveLatex","registeredEmbeds","Array","from","__resetEmbeds","clear","__setMathLiveForTest","stub","applyStaticMath","element","options","source","textContent","ml","loaded","isConnected","innerHTML","convertLatexToMarkup","toMathLive","macros","latexToMarkup"],"sources":["../src/mathlive-instance.js"],"sourcesContent":["import debug from 'debug';\nimport { NEWLINE_EMBED, toMathLive } from './latex-bridge';\n\nconst log = debug('pie-lib:math-input-mathlive:instance');\n\n/**\n * MathLive bootstrap + compatibility shims for @pie-lib/math-input's public API.\n *\n * MathLive is loaded lazily and only in the browser: the editor bundle is\n * ~227KB gzip and registers custom elements, so it must never run during SSR.\n */\n\nlet mathlive;\n\n/**\n * Where the KaTeX woff2 fonts are served from, as configured by the host app.\n * `undefined` means \"not configured\"; `null` means \"explicitly disabled\".\n */\nlet fontsDirectory;\n\n/**\n * Turn a fonts path into a fully-qualified URL.\n *\n * MathLive's default `fontsDirectory` is the relative `'./fonts/'`, which it\n * resolves against its own script URL. Under a bundler (webpack/Next) that\n * script URL is empty, so `new URL('./fonts/', '')` throws\n * \"Failed to construct 'URL': Invalid base URL\" from `loadFonts`.\n * Resolving against `document.baseURI` avoids that entirely and honours any\n * <base href> / asset prefix the host app uses.\n */\nconst absoluteFontsDirectory = (dir) => {\n if (!dir) {\n return dir;\n }\n\n // Already absolute (http://, https://, //cdn...) - MathLive handles these.\n if (/^(?:[a-z+]+:)?\\/\\//i.test(dir)) {\n return dir;\n }\n\n try {\n return new URL(dir, document.baseURI).href;\n } catch (e) {\n log('could not resolve fontsDirectory \"%s\": %s', dir, e && e.message);\n return null;\n }\n};\n\n/**\n * Tell the package where the MathLive fonts are served from.\n *\n * Call before `loadMathLive()`. Accepts an absolute URL, a root-relative path\n * (`/mathlive-fonts`) or a relative one; pass `null` to skip font loading and\n * fall back to system fonts.\n *\n * The fonts ship inside the `mathlive` package (`node_modules/mathlive/fonts`)\n * and must be copied into whatever the host app serves statically.\n *\n * @param {string|null} dir\n */\nexport const configureFonts = (dir) => {\n fontsDirectory = dir;\n\n if (mathlive) {\n mathlive.MathfieldElement.fontsDirectory = absoluteFontsDirectory(dir);\n }\n};\n\n/**\n * Custom macros for the pie-specific commands that the MathQuill fork\n * understood but stock LaTeX does not.\n *\n * Kept deliberately in sync with the MathJax macros in\n * @pie-lib/math-rendering (`render-math.js`) so the same latex renders the same\n * way in the editor and in the static renderer.\n */\nexport const PIE_MACROS = {\n parallelogram: '\\\\htmlData{pie-macro=parallelogram}{\\\\unicode{\"25B1}}',\n overarc: '\\\\overparen{#1}',\n napprox: '\\\\not\\\\approx',\n nsim: '\\\\not\\\\sim',\n ncong: '\\\\not\\\\cong',\n nparallel: '\\\\not\\\\parallel',\n perpendicular: '\\\\perp',\n divide: '\\\\div',\n degree: '^{\\\\circ}',\n square: '\\\\unicode{\"25A1}',\n longdiv: '\\\\htmlData{pie-macro=longdiv}{#1}',\n abs: '\\\\left|#1\\\\right|',\n};\n\n/**\n * Registry for `registerEmbed`.\n *\n * MathLive has no embed plugin system, so an embed is expressed as a macro that\n * expands to real LaTeX. `\\htmlData{embed=<name>}` tags the rendered output so\n * consumers can target it with CSS exactly as they targeted the old\n * `htmlString` markup.\n *\n * Known embeds map to native constructs:\n * - `newLine` -> structural, handled by latex-bridge (`\\displaylines` + `\\\\`)\n * - `answerBlock`-> `\\placeholder{}` (interactive, read via the prompts API)\n *\n * @type {Map<string, {factory: Function, latex: string}>}\n */\nconst embeds = new Map();\n\nconst KNOWN_EMBED_LATEX = {\n // newLine is structural: it is translated by latex-bridge before it ever\n // reaches MathLive, so the macro only needs to be harmless.\n newLine: '',\n answerBlock: '\\\\placeholder{}',\n};\n\nlet loadWarned = false;\n\n/** Apply post-load configuration exactly once. */\nconst configureLoaded = () => {\n // Always replace MathLive's relative `'./fonts/'` default: it throws\n // \"Invalid base URL\" when bundled. Either point at the host app's copy or\n // disable font loading, both of which are safe.\n if (fontsDirectory === undefined) {\n log(\n 'no fontsDirectory configured - MathLive will use fallback fonts. ' +\n 'Call configureFonts(\"/path/to/fonts\") with a copy of node_modules/mathlive/fonts to enable them.',\n );\n }\n\n mathlive.MathfieldElement.fontsDirectory =\n fontsDirectory === undefined ? null : absoluteFontsDirectory(fontsDirectory);\n\n injectCoreStylesheet();\n};\n\n/**\n * Ensure MathLive's \"core\" stylesheet is in the document.\n *\n * `convertLatexToMarkup` - which renders keypad labels and static math - does\n * NOT inject it, while `renderMathInElement` and live mathfields do. Without it\n * the generated markup is unstyled: glyphs misalign and the <svg> used by\n * stretchy accents lays out statically at an unbounded width.\n *\n * Hosts that can import CSS should `import 'mathlive/static.css'`. For bundles\n * that cannot handle CSS imports (pie-elements ships JS-only web components),\n * this triggers MathLive's own injection against a detached element, so the\n * styles come from MathLive itself rather than being duplicated here.\n */\nconst injectCoreStylesheet = () => {\n if (typeof document === 'undefined' || !mathlive || !mathlive.renderMathInElement) {\n return;\n }\n\n try {\n mathlive.renderMathInElement(document.createElement('span'));\n } catch (e) {\n log('could not trigger MathLive core stylesheet injection: %s', e && e.message);\n }\n};\n\n/**\n * Load MathLive synchronously when the bundler allows it.\n *\n * `require` keeps MathLive inside the host's bundle. An `import()` would make\n * webpack emit a separate chunk, and a deployment that does not serve that\n * chunk fails with a 404 at runtime - leaving every mathfield and keypad label\n * blank with no obvious cause. Being in the main bundle also makes the engine\n * available on first render, so callers that run synchronously (applyStaticMath,\n * keypad labels) work without a second pass.\n *\n * Returns undefined during SSR or if the module is genuinely unavailable.\n *\n * @returns {object|undefined}\n */\nexport const loadMathLiveSync = () => {\n if (typeof window === 'undefined') {\n return undefined;\n }\n\n if (!mathlive) {\n try {\n // eslint-disable-next-line global-require\n mathlive = require('mathlive');\n configureLoaded();\n } catch (e) {\n log('synchronous MathLive load unavailable: %s', e && e.message);\n return undefined;\n }\n }\n\n return mathlive;\n};\n\n/**\n * Load MathLive. Prefers the synchronous path; falls back to a dynamic import.\n * Resolves to undefined during SSR.\n *\n * @returns {Promise<object|undefined>}\n */\nexport const loadMathLive = async () => {\n if (typeof window === 'undefined') {\n return undefined;\n }\n\n if (mathlive) {\n return mathlive;\n }\n\n if (loadMathLiveSync()) {\n return mathlive;\n }\n\n try {\n mathlive = await import('mathlive');\n configureLoaded();\n } catch (e) {\n // Surface this once: a silent failure here renders every field and keypad\n // label blank, which is very hard to trace back to a module load.\n // Skipped under test, where jsdom cannot load the browser build.\n if (!loadWarned && process.env.NODE_ENV !== 'test') {\n loadWarned = true;\n // eslint-disable-next-line no-console\n console.warn(\n '[@pie-lib/math-input-mathlive] MathLive could not be loaded; math input will not render. ' +\n 'If this is a bundling issue, ensure \"mathlive\" is resolvable from the host bundle. Cause: ' +\n (e && e.message),\n );\n }\n\n return undefined;\n }\n\n return mathlive;\n};\n\n/**\n * Synchronous accessor for an already-loaded MathLive.\n * @returns {object|undefined}\n */\nexport const getMathLive = () => mathlive;\n\n/**\n * The macro dictionary to hand to a mathfield: pie macros plus anything\n * registered through `registerEmbed`.\n *\n * @returns {object}\n */\nexport const getMacros = () => {\n const out = { ...PIE_MACROS };\n\n embeds.forEach(({ latex }, name) => {\n out[name] = `\\\\htmlData{embed=${name}}{${latex}}`;\n });\n\n return out;\n};\n\n/**\n * Register an embed. API-compatible with @pie-lib/math-input's `registerEmbed`\n * so existing callers do not change.\n *\n * MathQuill's factory returns `{ htmlString, text, latex }`. Only the\n * declarative parts survive: `latex` round-trips through a macro and the\n * styling hook becomes a `data-embed` attribute. Arbitrary DOM injection via\n * `htmlString` has no MathLive equivalent and is ignored.\n *\n * @param {string} name\n * @param {Function} factory\n */\nexport function registerEmbed(name, factory) {\n if (!name || typeof factory !== 'function') {\n return;\n }\n\n let definition = {};\n\n try {\n definition = factory() || {};\n } catch (e) {\n log('embed factory threw for \"%s\": %s', name, e.message);\n }\n\n const latex = Object.prototype.hasOwnProperty.call(KNOWN_EMBED_LATEX, name)\n ? KNOWN_EMBED_LATEX[name]\n : definition.mathliveLatex || '\\\\placeholder{}';\n\n if (!Object.prototype.hasOwnProperty.call(KNOWN_EMBED_LATEX, name) && !definition.mathliveLatex) {\n // Unknown third-party embed: degrade instead of throwing. `htmlString`\n // cannot be reproduced, so it renders as an editable slot.\n log(\n 'embed \"%s\" is not natively supported by MathLive; rendering as a placeholder. ' +\n 'Provide `mathliveLatex` in the factory result to control this.',\n name,\n );\n }\n\n embeds.set(name, { factory, latex });\n}\n\n/**\n * Embeds registered so far. Exposed for tests/diagnostics.\n * @returns {string[]}\n */\nexport const registeredEmbeds = () => Array.from(embeds.keys());\n\n/** Reset the embed registry. Test helper. */\nexport const __resetEmbeds = () => embeds.clear();\n\n/** Inject a stub MathLive instance. Test helper. */\nexport const __setMathLiveForTest = (stub) => {\n mathlive = stub;\n};\n\n/**\n * Render static math into an element. API-compatible with\n * @pie-lib/math-input's `applyStaticMath`.\n *\n * Callers written against MathQuill invoke this synchronously from lifecycle\n * methods, where MathLive (a dynamic import) may not have loaded yet. Rather\n * than silently rendering nothing, this kicks off the load and re-applies once\n * the engine is ready, so the element fills in on the next tick.\n *\n * @param {HTMLElement} element\n * @param {string} [latex] assigned to the element before rendering\n * @param {object} [options] `{ macros }` overrides\n * @returns {HTMLElement|undefined} the element, or undefined if deferred\n */\nexport function applyStaticMath(element, latex, options = {}) {\n if (!element || typeof window === 'undefined') {\n return undefined;\n }\n\n // Capture the source now: if we defer, the element's textContent may have\n // been overwritten by the time MathLive is ready.\n const source = latex === undefined || latex === null ? element.textContent : latex;\n const ml = getMathLive() || loadMathLiveSync();\n\n if (!ml) {\n log('applyStaticMath called before MathLive loaded - deferring until it is ready');\n\n loadMathLive().then((loaded) => {\n // The element may have been unmounted while loading.\n if (loaded && element.isConnected !== false) {\n applyStaticMath(element, source, options);\n }\n });\n\n return undefined;\n }\n\n element.innerHTML = ml.convertLatexToMarkup(toMathLive(source), {\n macros: { ...getMacros(), ...(options.macros || {}) },\n });\n\n return element;\n}\n\n/**\n * Convert latex to markup using the pie macro set. Used for keypad labels and\n * any read-only rendering that does not need a live mathfield.\n *\n * @param {string} latex\n * @param {object} [options]\n * @returns {string} HTML markup, or '' if MathLive is not loaded\n */\nexport function latexToMarkup(latex, options = {}) {\n // Try the synchronous load so the very first render can produce markup\n // instead of falling back to raw latex.\n const ml = getMathLive() || loadMathLiveSync();\n\n if (!ml || !latex) {\n return '';\n }\n\n try {\n return ml.convertLatexToMarkup(toMathLive(latex), {\n macros: { ...getMacros(), ...(options.macros || {}) },\n ...options,\n });\n } catch (e) {\n log('convertLatexToMarkup failed for \"%s\": %s', latex, e.message);\n return '';\n }\n}\n\nexport { NEWLINE_EMBED };\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"mathlive-instance.js","names":["_debug","_interopRequireDefault","require","_latexBridge","ownKeys","e","r","t","Object","keys","getOwnPropertySymbols","o","filter","getOwnPropertyDescriptor","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty2","getOwnPropertyDescriptors","defineProperties","defineProperty","_interopRequireWildcard","WeakMap","n","__esModule","i","f","__proto__","_typeof","has","get","set","_t2","hasOwnProperty","call","log","debug","mathlive","fontsDirectory","absoluteFontsDirectory","dir","test","URL","document","baseURI","href","message","configureFonts","exports","MathfieldElement","MATH_MODE_SPACE","PIE_MACROS","parallelogram","napprox","nsim","ncong","nparallel","perpendicular","divide","degree","square","longdiv","overarc","abs","embeds","Map","KNOWN_EMBED_LATEX","newLine","answerBlock","loadWarned","configureLoaded","undefined","injectCoreStylesheet","renderMathInElement","createElement","loadMathLiveSync","window","loadMathLive","_ref","_asyncToGenerator2","_regenerator","mark","_callee","_t","wrap","_context","prev","next","abrupt","Promise","resolve","then","sent","process","env","NODE_ENV","console","warn","stop","getMathLive","getMacros","out","_ref2","name","latex","concat","registerEmbed","factory","definition","prototype","mathliveLatex","registeredEmbeds","Array","from","__resetEmbeds","clear","__setMathLiveForTest","stub","applyStaticMath","element","options","source","textContent","ml","loaded","isConnected","innerHTML","convertLatexToMarkup","withVisibleEmptySlots","toMathLive","macros","latexToMarkup"],"sources":["../src/mathlive-instance.js"],"sourcesContent":["import debug from 'debug';\nimport { NEWLINE_EMBED, toMathLive, withVisibleEmptySlots } from './latex-bridge';\n\nconst log = debug('pie-lib:math-input-mathlive:instance');\n\n/**\n * MathLive bootstrap + compatibility shims for @pie-lib/math-input's public API.\n *\n * MathLive is loaded lazily and only in the browser: the editor bundle is\n * ~227KB gzip and registers custom elements, so it must never run during SSR.\n */\n\nlet mathlive;\n\n/**\n * Where the KaTeX woff2 fonts are served from, as configured by the host app.\n * `undefined` means \"not configured\"; `null` means \"explicitly disabled\".\n */\nlet fontsDirectory;\n\n/**\n * Turn a fonts path into a fully-qualified URL.\n *\n * MathLive's default `fontsDirectory` is the relative `'./fonts/'`, which it\n * resolves against its own script URL. Under a bundler (webpack/Next) that\n * script URL is empty, so `new URL('./fonts/', '')` throws\n * \"Failed to construct 'URL': Invalid base URL\" from `loadFonts`.\n * Resolving against `document.baseURI` avoids that entirely and honours any\n * <base href> / asset prefix the host app uses.\n */\nconst absoluteFontsDirectory = (dir) => {\n if (!dir) {\n return dir;\n }\n\n // Already absolute (http://, https://, //cdn...) - MathLive handles these.\n if (/^(?:[a-z+]+:)?\\/\\//i.test(dir)) {\n return dir;\n }\n\n try {\n return new URL(dir, document.baseURI).href;\n } catch (e) {\n log('could not resolve fontsDirectory \"%s\": %s', dir, e && e.message);\n return null;\n }\n};\n\n/**\n * Tell the package where the MathLive fonts are served from.\n *\n * Call before `loadMathLive()`. Accepts an absolute URL, a root-relative path\n * (`/mathlive-fonts`) or a relative one; pass `null` to skip font loading and\n * fall back to system fonts.\n *\n * The fonts ship inside the `mathlive` package (`node_modules/mathlive/fonts`)\n * and must be copied into whatever the host app serves statically.\n *\n * @param {string|null} dir\n */\nexport const configureFonts = (dir) => {\n fontsDirectory = dir;\n\n if (mathlive) {\n mathlive.MathfieldElement.fontsDirectory = absoluteFontsDirectory(dir);\n }\n};\n\n/**\n * What the spacebar inserts in math mode.\n *\n * MathLive's `mathModeSpace` defaults to an empty string, which makes the\n * spacebar a no-op - users cannot type a space at all. `\\\\ ` (a LaTeX control\n * space) is what MathQuill serialised spaces as, so existing content and the\n * MathJax renderer in @pie-lib/math-rendering both already understand it.\n *\n * A literal \" \" is not usable: LaTeX skips raw whitespace.\n */\nexport const MATH_MODE_SPACE = '\\\\ ';\n\n/**\n * Custom macros for the pie-specific commands that the MathQuill fork\n * understood but stock LaTeX does not.\n *\n * Kept deliberately in sync with the MathJax macros in\n * @pie-lib/math-rendering (`render-math.js`) so the same latex renders the same\n * way in the editor and in the static renderer.\n */\nexport const PIE_MACROS = {\n // Argument-less symbols. Atomic is correct here: backspace should remove the\n // whole glyph, and there is nothing to type into.\n parallelogram: '\\\\htmlData{pie-macro=parallelogram}{\\\\unicode{\"25B1}}',\n napprox: '\\\\not\\\\approx',\n nsim: '\\\\not\\\\sim',\n ncong: '\\\\not\\\\cong',\n nparallel: '\\\\not\\\\parallel',\n perpendicular: '\\\\perp',\n divide: '\\\\div',\n degree: '^{\\\\circ}',\n square: '\\\\unicode{\"25A1}',\n\n // Argument-taking commands, kept ONLY so previously authored latex still\n // parses and renders. They are never used for editing: MathLive serialises a\n // macro from the arguments it was created with, so text typed inside the\n // expansion never comes back out of `getValue('latex')`. Anything entering a\n // mathfield is rewritten to the native equivalent first - see\n // `toNativeCommands` in latex-bridge.\n longdiv: '\\\\enclose{longdiv}{#1}',\n overarc: '\\\\overparen{#1}',\n abs: '\\\\left|#1\\\\right|',\n};\n\n/**\n * Registry for `registerEmbed`.\n *\n * MathLive has no embed plugin system, so an embed is expressed as a macro that\n * expands to real LaTeX. `\\htmlData{embed=<name>}` tags the rendered output so\n * consumers can target it with CSS exactly as they targeted the old\n * `htmlString` markup.\n *\n * Known embeds map to native constructs:\n * - `newLine` -> structural, handled by latex-bridge (`\\displaylines` + `\\\\`)\n * - `answerBlock`-> `\\placeholder{}` (interactive, read via the prompts API)\n *\n * @type {Map<string, {factory: Function, latex: string}>}\n */\nconst embeds = new Map();\n\nconst KNOWN_EMBED_LATEX = {\n // newLine is structural: it is translated by latex-bridge before it ever\n // reaches MathLive, so the macro only needs to be harmless.\n newLine: '',\n answerBlock: '\\\\placeholder{}',\n};\n\nlet loadWarned = false;\n\n/** Apply post-load configuration exactly once. */\nconst configureLoaded = () => {\n // Always replace MathLive's relative `'./fonts/'` default: it throws\n // \"Invalid base URL\" when bundled. Either point at the host app's copy or\n // disable font loading, both of which are safe.\n if (fontsDirectory === undefined) {\n log(\n 'no fontsDirectory configured - MathLive will use fallback fonts. ' +\n 'Call configureFonts(\"/path/to/fonts\") with a copy of node_modules/mathlive/fonts to enable them.',\n );\n }\n\n mathlive.MathfieldElement.fontsDirectory =\n fontsDirectory === undefined ? null : absoluteFontsDirectory(fontsDirectory);\n\n injectCoreStylesheet();\n};\n\n/**\n * Ensure MathLive's \"core\" stylesheet is in the document.\n *\n * `convertLatexToMarkup` - which renders keypad labels and static math - does\n * NOT inject it, while `renderMathInElement` and live mathfields do. Without it\n * the generated markup is unstyled: glyphs misalign and the <svg> used by\n * stretchy accents lays out statically at an unbounded width.\n *\n * Hosts that can import CSS should `import 'mathlive/static.css'`. For bundles\n * that cannot handle CSS imports (pie-elements ships JS-only web components),\n * this triggers MathLive's own injection against a detached element, so the\n * styles come from MathLive itself rather than being duplicated here.\n */\nconst injectCoreStylesheet = () => {\n if (typeof document === 'undefined' || !mathlive || !mathlive.renderMathInElement) {\n return;\n }\n\n try {\n mathlive.renderMathInElement(document.createElement('span'));\n } catch (e) {\n log('could not trigger MathLive core stylesheet injection: %s', e && e.message);\n }\n};\n\n/**\n * Load MathLive synchronously when the bundler allows it.\n *\n * `require` keeps MathLive inside the host's bundle. An `import()` would make\n * webpack emit a separate chunk, and a deployment that does not serve that\n * chunk fails with a 404 at runtime - leaving every mathfield and keypad label\n * blank with no obvious cause. Being in the main bundle also makes the engine\n * available on first render, so callers that run synchronously (applyStaticMath,\n * keypad labels) work without a second pass.\n *\n * Returns undefined during SSR or if the module is genuinely unavailable.\n *\n * @returns {object|undefined}\n */\nexport const loadMathLiveSync = () => {\n if (typeof window === 'undefined') {\n return undefined;\n }\n\n if (!mathlive) {\n try {\n // eslint-disable-next-line global-require\n mathlive = require('mathlive');\n configureLoaded();\n } catch (e) {\n log('synchronous MathLive load unavailable: %s', e && e.message);\n return undefined;\n }\n }\n\n return mathlive;\n};\n\n/**\n * Load MathLive. Prefers the synchronous path; falls back to a dynamic import.\n * Resolves to undefined during SSR.\n *\n * @returns {Promise<object|undefined>}\n */\nexport const loadMathLive = async () => {\n if (typeof window === 'undefined') {\n return undefined;\n }\n\n if (mathlive) {\n return mathlive;\n }\n\n if (loadMathLiveSync()) {\n return mathlive;\n }\n\n try {\n mathlive = await import('mathlive');\n configureLoaded();\n } catch (e) {\n // Surface this once: a silent failure here renders every field and keypad\n // label blank, which is very hard to trace back to a module load.\n // Skipped under test, where jsdom cannot load the browser build.\n if (!loadWarned && process.env.NODE_ENV !== 'test') {\n loadWarned = true;\n // eslint-disable-next-line no-console\n console.warn(\n '[@pie-lib/math-input-mathlive] MathLive could not be loaded; math input will not render. ' +\n 'If this is a bundling issue, ensure \"mathlive\" is resolvable from the host bundle. Cause: ' +\n (e && e.message),\n );\n }\n\n return undefined;\n }\n\n return mathlive;\n};\n\n/**\n * Synchronous accessor for an already-loaded MathLive.\n * @returns {object|undefined}\n */\nexport const getMathLive = () => mathlive;\n\n/**\n * The macro dictionary to hand to a mathfield: pie macros plus anything\n * registered through `registerEmbed`.\n *\n * @returns {object}\n */\nexport const getMacros = () => {\n const out = { ...PIE_MACROS };\n\n embeds.forEach(({ latex }, name) => {\n out[name] = `\\\\htmlData{embed=${name}}{${latex}}`;\n });\n\n return out;\n};\n\n/**\n * Register an embed. API-compatible with @pie-lib/math-input's `registerEmbed`\n * so existing callers do not change.\n *\n * MathQuill's factory returns `{ htmlString, text, latex }`. Only the\n * declarative parts survive: `latex` round-trips through a macro and the\n * styling hook becomes a `data-embed` attribute. Arbitrary DOM injection via\n * `htmlString` has no MathLive equivalent and is ignored.\n *\n * @param {string} name\n * @param {Function} factory\n */\nexport function registerEmbed(name, factory) {\n if (!name || typeof factory !== 'function') {\n return;\n }\n\n let definition = {};\n\n try {\n definition = factory() || {};\n } catch (e) {\n log('embed factory threw for \"%s\": %s', name, e.message);\n }\n\n const latex = Object.prototype.hasOwnProperty.call(KNOWN_EMBED_LATEX, name)\n ? KNOWN_EMBED_LATEX[name]\n : definition.mathliveLatex || '\\\\placeholder{}';\n\n if (!Object.prototype.hasOwnProperty.call(KNOWN_EMBED_LATEX, name) && !definition.mathliveLatex) {\n // Unknown third-party embed: degrade instead of throwing. `htmlString`\n // cannot be reproduced, so it renders as an editable slot.\n log(\n 'embed \"%s\" is not natively supported by MathLive; rendering as a placeholder. ' +\n 'Provide `mathliveLatex` in the factory result to control this.',\n name,\n );\n }\n\n embeds.set(name, { factory, latex });\n}\n\n/**\n * Embeds registered so far. Exposed for tests/diagnostics.\n * @returns {string[]}\n */\nexport const registeredEmbeds = () => Array.from(embeds.keys());\n\n/** Reset the embed registry. Test helper. */\nexport const __resetEmbeds = () => embeds.clear();\n\n/** Inject a stub MathLive instance. Test helper. */\nexport const __setMathLiveForTest = (stub) => {\n mathlive = stub;\n};\n\n/**\n * Render static math into an element. API-compatible with\n * @pie-lib/math-input's `applyStaticMath`.\n *\n * Callers written against MathQuill invoke this synchronously from lifecycle\n * methods, where MathLive (a dynamic import) may not have loaded yet. Rather\n * than silently rendering nothing, this kicks off the load and re-applies once\n * the engine is ready, so the element fills in on the next tick.\n *\n * @param {HTMLElement} element\n * @param {string} [latex] assigned to the element before rendering\n * @param {object} [options] `{ macros }` overrides\n * @returns {HTMLElement|undefined} the element, or undefined if deferred\n */\nexport function applyStaticMath(element, latex, options = {}) {\n if (!element || typeof window === 'undefined') {\n return undefined;\n }\n\n // Capture the source now: if we defer, the element's textContent may have\n // been overwritten by the time MathLive is ready.\n const source = latex === undefined || latex === null ? element.textContent : latex;\n const ml = getMathLive() || loadMathLiveSync();\n\n if (!ml) {\n log('applyStaticMath called before MathLive loaded - deferring until it is ready');\n\n loadMathLive().then((loaded) => {\n // The element may have been unmounted while loading.\n if (loaded && element.isConnected !== false) {\n applyStaticMath(element, source, options);\n }\n });\n\n return undefined;\n }\n\n element.innerHTML = ml.convertLatexToMarkup(withVisibleEmptySlots(toMathLive(source)), {\n macros: { ...getMacros(), ...(options.macros || {}) },\n });\n\n return element;\n}\n\n/**\n * Convert latex to markup using the pie macro set. Used for keypad labels and\n * any read-only rendering that does not need a live mathfield.\n *\n * @param {string} latex\n * @param {object} [options]\n * @returns {string} HTML markup, or '' if MathLive is not loaded\n */\nexport function latexToMarkup(latex, options = {}) {\n // Try the synchronous load so the very first render can produce markup\n // instead of falling back to raw latex.\n const ml = getMathLive() || loadMathLiveSync();\n\n if (!ml || !latex) {\n return '';\n }\n\n try {\n // Empty groups render as nothing in static markup, so give them a visible\n // box. This covers every static path: keypad labels, mf.Static in display\n // mode, and applyStaticMath.\n return ml.convertLatexToMarkup(withVisibleEmptySlots(toMathLive(latex)), {\n macros: { ...getMacros(), ...(options.macros || {}) },\n ...options,\n });\n } catch (e) {\n log('convertLatexToMarkup failed for \"%s\": %s', latex, e.message);\n return '';\n }\n}\n\nexport { NEWLINE_EMBED };\n"],"mappings":"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","ignoreList":[]}
@@ -60,6 +60,19 @@ var placeholderStyles = exports.placeholderStyles = {
60
60
  '& .ML__placeholder': {
61
61
  borderBottom: '1px solid currentColor',
62
62
  minWidth: '1em'
63
+ },
64
+ // Stand-in glyph for an empty argument slot in STATIC math (see
65
+ // `withVisibleEmptySlots`). Muted so it reads as "a slot goes here" rather
66
+ // than as part of the symbol, matching how MathQuill shaded `.mq-empty`.
67
+ '& [data-pie-empty]': {
68
+ opacity: 0.5
69
+ },
70
+ // Stretchy accents render an <svg>; mathlive-static.css positions it
71
+ // absolutely at width:100%. Repeated here so static math cannot blow out its
72
+ // container if that stylesheet is missing.
73
+ '& svg': {
74
+ position: 'absolute',
75
+ width: '100%'
63
76
  }
64
77
  };
65
78
 
@@ -1 +1 @@
1
- {"version":3,"file":"common-styles.js","names":["commonMqFontStyles","exports","fontFamily","longdivStyles","display","supsubStyles","placeholderStyles","borderBottom","minWidth","commonMqKeyboardStyles","_objectSpread","touchAction","fontSize","outline","commonMathLiveStyles","commonKeyboardStyles","_default"],"sources":["../../src/mf/common-styles.js"],"sourcesContent":["/**\n * Shared MathLive styling.\n *\n * Replaces @pie-lib/math-input's `common-mq-styles.js`. That file was built\n * around MathQuill's `.mq-*` class names, none of which exist in MathLive\n * output, so the selectors here target MathLive's own structure instead.\n *\n * The four named groups are kept because consumers destructure them:\n *\n * const { commonMqFontStyles, commonMqKeyboardStyles, longdivStyles, supsubStyles }\n * = mq.CommonMqStyles; // math-toolbar/src/editor-and-pad.jsx, math-preview.jsx\n *\n * Most are intentionally near-empty: MathLive sizes scripts, radicals and\n * fences correctly on its own, so the MathQuill-era corrections are not needed.\n * They stay as documented extension points rather than being deleted, so the\n * destructuring above keeps working.\n */\n\n/**\n * Font styling. MathQuill needed explicit MathJax font families to match the\n * static renderer; MathLive ships the KaTeX fonts it renders with, so this only\n * smooths rendering and lets the host override the family.\n */\nexport const commonMqFontStyles = {\n '-webkit-font-smoothing': 'antialiased',\n '& math-field': {\n fontFamily: 'inherit',\n },\n};\n\n/**\n * Long division. The MathQuill fork drew this with nested `.mq-longdiv-*`\n * elements that needed manual offsets; here it comes from the `\\longdiv` macro\n * (see `PIE_MACROS`), tagged with `data-pie-macro=\"longdiv\"`.\n */\nexport const longdivStyles = {\n '& [data-pie-macro=\"longdiv\"]': {\n display: 'inline-flex',\n },\n};\n\n/**\n * Superscript/subscript sizing. MathLive follows TeX metrics, so no overrides\n * are required.\n */\nexport const supsubStyles = {};\n\n/** Empty placeholder boxes (answer blocks / open slots). */\nexport const placeholderStyles = {\n '& .ML__placeholder': {\n borderBottom: '1px solid currentColor',\n minWidth: '1em',\n },\n};\n\n/**\n * Styling for the on-screen keyboard and any container rendering math labels.\n * Also hides MathLive's own affordances, since pie supplies its own keypad.\n */\nexport const commonMqKeyboardStyles = {\n ...commonMqFontStyles,\n ...longdivStyles,\n ...placeholderStyles,\n touchAction: 'manipulation',\n '& math-field': {\n fontSize: 'inherit',\n outline: 'none',\n },\n '& math-field::part(virtual-keyboard-toggle)': {\n display: 'none',\n },\n '& math-field::part(menu-toggle)': {\n display: 'none',\n },\n};\n\n/** Everything combined - the common case for a container of math. */\nexport const commonMathLiveStyles = {\n ...commonMqFontStyles,\n ...longdivStyles,\n ...supsubStyles,\n ...placeholderStyles,\n '& math-field': {\n fontSize: 'inherit',\n outline: 'none',\n },\n '& math-field::part(virtual-keyboard-toggle)': {\n display: 'none',\n },\n '& math-field::part(menu-toggle)': {\n display: 'none',\n },\n};\n\nexport const commonKeyboardStyles = commonMqKeyboardStyles;\n\n/**\n * Default export mirrors @pie-lib/math-input's `CommonMqStyles` object so\n * existing destructuring keeps working.\n */\nexport default {\n commonMqFontStyles,\n longdivStyles,\n supsubStyles,\n commonMqKeyboardStyles,\n placeholderStyles,\n commonMathLiveStyles,\n};\n"],"mappings":";;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACO,IAAMA,kBAAkB,GAAAC,OAAA,CAAAD,kBAAA,GAAG;EAChC,wBAAwB,EAAE,aAAa;EACvC,cAAc,EAAE;IACdE,UAAU,EAAE;EACd;AACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACO,IAAMC,aAAa,GAAAF,OAAA,CAAAE,aAAA,GAAG;EAC3B,8BAA8B,EAAE;IAC9BC,OAAO,EAAE;EACX;AACF,CAAC;;AAED;AACA;AACA;AACA;AACO,IAAMC,YAAY,GAAAJ,OAAA,CAAAI,YAAA,GAAG,CAAC,CAAC;;AAE9B;AACO,IAAMC,iBAAiB,GAAAL,OAAA,CAAAK,iBAAA,GAAG;EAC/B,oBAAoB,EAAE;IACpBC,YAAY,EAAE,wBAAwB;IACtCC,QAAQ,EAAE;EACZ;AACF,CAAC;;AAED;AACA;AACA;AACA;AACO,IAAMC,sBAAsB,GAAAR,OAAA,CAAAQ,sBAAA,GAAAC,aAAA,CAAAA,aAAA,CAAAA,aAAA,CAAAA,aAAA,KAC9BV,kBAAkB,GAClBG,aAAa,GACbG,iBAAiB;EACpBK,WAAW,EAAE,cAAc;EAC3B,cAAc,EAAE;IACdC,QAAQ,EAAE,SAAS;IACnBC,OAAO,EAAE;EACX,CAAC;EACD,6CAA6C,EAAE;IAC7CT,OAAO,EAAE;EACX,CAAC;EACD,iCAAiC,EAAE;IACjCA,OAAO,EAAE;EACX;AAAC,EACF;;AAED;AACO,IAAMU,oBAAoB,GAAAb,OAAA,CAAAa,oBAAA,GAAAJ,aAAA,CAAAA,aAAA,CAAAA,aAAA,CAAAA,aAAA,CAAAA,aAAA,KAC5BV,kBAAkB,GAClBG,aAAa,GACbE,YAAY,GACZC,iBAAiB;EACpB,cAAc,EAAE;IACdM,QAAQ,EAAE,SAAS;IACnBC,OAAO,EAAE;EACX,CAAC;EACD,6CAA6C,EAAE;IAC7CT,OAAO,EAAE;EACX,CAAC;EACD,iCAAiC,EAAE;IACjCA,OAAO,EAAE;EACX;AAAC,EACF;AAEM,IAAMW,oBAAoB,GAAAd,OAAA,CAAAc,oBAAA,GAAGN,sBAAsB;;AAE1D;AACA;AACA;AACA;AAHA,IAAAO,QAAA,GAAAf,OAAA,cAIe;EACbD,kBAAkB,EAAlBA,kBAAkB;EAClBG,aAAa,EAAbA,aAAa;EACbE,YAAY,EAAZA,YAAY;EACZI,sBAAsB,EAAtBA,sBAAsB;EACtBH,iBAAiB,EAAjBA,iBAAiB;EACjBQ,oBAAoB,EAApBA;AACF,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"common-styles.js","names":["commonMqFontStyles","exports","fontFamily","longdivStyles","display","supsubStyles","placeholderStyles","borderBottom","minWidth","opacity","position","width","commonMqKeyboardStyles","_objectSpread","touchAction","fontSize","outline","commonMathLiveStyles","commonKeyboardStyles","_default"],"sources":["../../src/mf/common-styles.js"],"sourcesContent":["/**\n * Shared MathLive styling.\n *\n * Replaces @pie-lib/math-input's `common-mq-styles.js`. That file was built\n * around MathQuill's `.mq-*` class names, none of which exist in MathLive\n * output, so the selectors here target MathLive's own structure instead.\n *\n * The four named groups are kept because consumers destructure them:\n *\n * const { commonMqFontStyles, commonMqKeyboardStyles, longdivStyles, supsubStyles }\n * = mq.CommonMqStyles; // math-toolbar/src/editor-and-pad.jsx, math-preview.jsx\n *\n * Most are intentionally near-empty: MathLive sizes scripts, radicals and\n * fences correctly on its own, so the MathQuill-era corrections are not needed.\n * They stay as documented extension points rather than being deleted, so the\n * destructuring above keeps working.\n */\n\n/**\n * Font styling. MathQuill needed explicit MathJax font families to match the\n * static renderer; MathLive ships the KaTeX fonts it renders with, so this only\n * smooths rendering and lets the host override the family.\n */\nexport const commonMqFontStyles = {\n '-webkit-font-smoothing': 'antialiased',\n '& math-field': {\n fontFamily: 'inherit',\n },\n};\n\n/**\n * Long division. The MathQuill fork drew this with nested `.mq-longdiv-*`\n * elements that needed manual offsets; here it comes from the `\\longdiv` macro\n * (see `PIE_MACROS`), tagged with `data-pie-macro=\"longdiv\"`.\n */\nexport const longdivStyles = {\n '& [data-pie-macro=\"longdiv\"]': {\n display: 'inline-flex',\n },\n};\n\n/**\n * Superscript/subscript sizing. MathLive follows TeX metrics, so no overrides\n * are required.\n */\nexport const supsubStyles = {};\n\n/** Empty placeholder boxes (answer blocks / open slots). */\nexport const placeholderStyles = {\n '& .ML__placeholder': {\n borderBottom: '1px solid currentColor',\n minWidth: '1em',\n },\n // Stand-in glyph for an empty argument slot in STATIC math (see\n // `withVisibleEmptySlots`). Muted so it reads as \"a slot goes here\" rather\n // than as part of the symbol, matching how MathQuill shaded `.mq-empty`.\n '& [data-pie-empty]': {\n opacity: 0.5,\n },\n // Stretchy accents render an <svg>; mathlive-static.css positions it\n // absolutely at width:100%. Repeated here so static math cannot blow out its\n // container if that stylesheet is missing.\n '& svg': {\n position: 'absolute',\n width: '100%',\n },\n};\n\n/**\n * Styling for the on-screen keyboard and any container rendering math labels.\n * Also hides MathLive's own affordances, since pie supplies its own keypad.\n */\nexport const commonMqKeyboardStyles = {\n ...commonMqFontStyles,\n ...longdivStyles,\n ...placeholderStyles,\n touchAction: 'manipulation',\n '& math-field': {\n fontSize: 'inherit',\n outline: 'none',\n },\n '& math-field::part(virtual-keyboard-toggle)': {\n display: 'none',\n },\n '& math-field::part(menu-toggle)': {\n display: 'none',\n },\n};\n\n/** Everything combined - the common case for a container of math. */\nexport const commonMathLiveStyles = {\n ...commonMqFontStyles,\n ...longdivStyles,\n ...supsubStyles,\n ...placeholderStyles,\n '& math-field': {\n fontSize: 'inherit',\n outline: 'none',\n },\n '& math-field::part(virtual-keyboard-toggle)': {\n display: 'none',\n },\n '& math-field::part(menu-toggle)': {\n display: 'none',\n },\n};\n\nexport const commonKeyboardStyles = commonMqKeyboardStyles;\n\n/**\n * Default export mirrors @pie-lib/math-input's `CommonMqStyles` object so\n * existing destructuring keeps working.\n */\nexport default {\n commonMqFontStyles,\n longdivStyles,\n supsubStyles,\n commonMqKeyboardStyles,\n placeholderStyles,\n commonMathLiveStyles,\n};\n"],"mappings":";;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACO,IAAMA,kBAAkB,GAAAC,OAAA,CAAAD,kBAAA,GAAG;EAChC,wBAAwB,EAAE,aAAa;EACvC,cAAc,EAAE;IACdE,UAAU,EAAE;EACd;AACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACO,IAAMC,aAAa,GAAAF,OAAA,CAAAE,aAAA,GAAG;EAC3B,8BAA8B,EAAE;IAC9BC,OAAO,EAAE;EACX;AACF,CAAC;;AAED;AACA;AACA;AACA;AACO,IAAMC,YAAY,GAAAJ,OAAA,CAAAI,YAAA,GAAG,CAAC,CAAC;;AAE9B;AACO,IAAMC,iBAAiB,GAAAL,OAAA,CAAAK,iBAAA,GAAG;EAC/B,oBAAoB,EAAE;IACpBC,YAAY,EAAE,wBAAwB;IACtCC,QAAQ,EAAE;EACZ,CAAC;EACD;EACA;EACA;EACA,oBAAoB,EAAE;IACpBC,OAAO,EAAE;EACX,CAAC;EACD;EACA;EACA;EACA,OAAO,EAAE;IACPC,QAAQ,EAAE,UAAU;IACpBC,KAAK,EAAE;EACT;AACF,CAAC;;AAED;AACA;AACA;AACA;AACO,IAAMC,sBAAsB,GAAAX,OAAA,CAAAW,sBAAA,GAAAC,aAAA,CAAAA,aAAA,CAAAA,aAAA,CAAAA,aAAA,KAC9Bb,kBAAkB,GAClBG,aAAa,GACbG,iBAAiB;EACpBQ,WAAW,EAAE,cAAc;EAC3B,cAAc,EAAE;IACdC,QAAQ,EAAE,SAAS;IACnBC,OAAO,EAAE;EACX,CAAC;EACD,6CAA6C,EAAE;IAC7CZ,OAAO,EAAE;EACX,CAAC;EACD,iCAAiC,EAAE;IACjCA,OAAO,EAAE;EACX;AAAC,EACF;;AAED;AACO,IAAMa,oBAAoB,GAAAhB,OAAA,CAAAgB,oBAAA,GAAAJ,aAAA,CAAAA,aAAA,CAAAA,aAAA,CAAAA,aAAA,CAAAA,aAAA,KAC5Bb,kBAAkB,GAClBG,aAAa,GACbE,YAAY,GACZC,iBAAiB;EACpB,cAAc,EAAE;IACdS,QAAQ,EAAE,SAAS;IACnBC,OAAO,EAAE;EACX,CAAC;EACD,6CAA6C,EAAE;IAC7CZ,OAAO,EAAE;EACX,CAAC;EACD,iCAAiC,EAAE;IACjCA,OAAO,EAAE;EACX;AAAC,EACF;AAEM,IAAMc,oBAAoB,GAAAjB,OAAA,CAAAiB,oBAAA,GAAGN,sBAAsB;;AAE1D;AACA;AACA;AACA;AAHA,IAAAO,QAAA,GAAAlB,OAAA,cAIe;EACbD,kBAAkB,EAAlBA,kBAAkB;EAClBG,aAAa,EAAbA,aAAa;EACbE,YAAY,EAAZA,YAAY;EACZO,sBAAsB,EAAtBA,sBAAsB;EACtBN,iBAAiB,EAAjBA,iBAAiB;EACjBW,oBAAoB,EAApBA;AACF,CAAC","ignoreList":[]}
package/lib/mf/input.js CHANGED
@@ -80,16 +80,22 @@ var Input = exports.Input = /*#__PURE__*/function (_React$Component) {
80
80
  key: "componentDidMount",
81
81
  value: function () {
82
82
  var _componentDidMount = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee() {
83
- var _this$setState;
84
- var ml;
83
+ var generation, ml;
85
84
  return _regenerator["default"].wrap(function (_context) {
86
85
  while (1) switch (_context.prev = _context.next) {
87
86
  case 0:
87
+ // MathLive loads asynchronously, so this method resumes after an await and
88
+ // has to know whether it is still the current mount. React StrictMode calls
89
+ // mount -> unmount -> mount on the SAME instance in dev, so a boolean
90
+ // "unmounted" flag would latch and block the remount from ever creating a
91
+ // field. A generation counter identifies the live mount instead: only the
92
+ // newest one proceeds, and a real unmount invalidates all pending ones.
93
+ generation = this.mountGeneration = (this.mountGeneration || 0) + 1;
88
94
  _context.next = 1;
89
95
  return (0, _mathliveInstance.loadMathLive)();
90
96
  case 1:
91
97
  ml = _context.sent;
92
- if (!(!ml || !this.holderRef.current)) {
98
+ if (!(generation !== this.mountGeneration || !ml || !this.holderRef.current || this.mathField)) {
93
99
  _context.next = 2;
94
100
  break;
95
101
  }
@@ -105,12 +111,16 @@ var Input = exports.Input = /*#__PURE__*/function (_React$Component) {
105
111
 
106
112
  // pie drives input through its own keypad, so suppress MathLive's.
107
113
  this.mathField.mathVirtualKeyboardPolicy = 'manual';
114
+ // Without this the spacebar does nothing: MathLive's mathModeSpace
115
+ // defaults to an empty string.
116
+ this.mathField.mathModeSpace = _mathliveInstance.MATH_MODE_SPACE;
108
117
  this.mathField.addEventListener('input', this.onInputEdit);
109
- this.holderRef.current.appendChild(this.mathField);
118
+
119
+ // Belt and braces: drop anything a previous mount may have left behind.
120
+ this.holderRef.current.replaceChildren(this.mathField);
110
121
  if (this.props.innerRef) {
111
122
  this.props.innerRef(this);
112
123
  }
113
- (_this$setState = this.setState) === null || _this$setState === void 0 || _this$setState.call(this, {});
114
124
  case 3:
115
125
  case "end":
116
126
  return _context.stop();
@@ -148,6 +158,9 @@ var Input = exports.Input = /*#__PURE__*/function (_React$Component) {
148
158
  }, {
149
159
  key: "componentWillUnmount",
150
160
  value: function componentWillUnmount() {
161
+ // Invalidate any mount still awaiting the MathLive load, so it does not
162
+ // append a field into a holder that is going away.
163
+ this.mountGeneration = (this.mountGeneration || 0) + 1;
151
164
  if (this.mathField) {
152
165
  this.mathField.removeEventListener('input', this.onInputEdit);
153
166
  this.mathField.remove();