Repository: pie-framework/pie-lib (and coordinated changes in pie-framework/pie-elements, pie-framework/mathquill).
Last reviewed: 2026-04-07 (branch snapshot).
- Long term: Replace MathQuill with MathLive for math editing and in-editor display, aligning with a modern stack (no jQuery).
- Short term (done): The
@pie-framework/mathquillfork ships a small jQuery shim so apps do not depend on jQuery directly. - Display pipeline: Keep MathJax (via
@pie-lib/math-rendering) for authored/read-only math in the player and similar surfaces unless product later decides to consolidate rendering.
| Decision | Choice |
|---|---|
| Package strategy | Copy @pie-lib/math-input → @pie-lib/math-input-mathlive, preserve the public API. Consumers switch import + dependency when ready; legacy math-input stays publishable during transition. |
| Virtual keyboard | Keep HorizontalKeypad initially. Move to MathLive’s built-in keyboard only after accessibility / product decisions are finalized. |
| Rich text | TipTap (editable-html-tip-tap) is the primary integration target. Slate (editable-html) remains in the monorepo; treat MathLive migration for Slate as out of scope unless product requires it. |
| MathML → LaTeX | Continue using @pie-framework/mathml-to-latex where needed; MathLive does not replace that path. |
- MathQuill: Interactive editing (
MQ.MathField), static/in-editor math (MQ.StaticMath), custom embeds (MQ.registerEmbed), keypad labels (viamq.Static). - MathJax (
math-rendering): Typeset LaTeX in DOM; normalizes\embed{newLine}[]→\newlinefor compatibility with non–MathQuill output.
| Location | Role |
|---|---|
packages/math-input/src/mq/input.jsx |
MathQuill.getInterface(3), MQ.MathField, registers line-break embed (via custom-elements) |
packages/math-input/src/mq/static.jsx |
MQ.StaticMath, \MathQuillMathField[rN]{...} handling |
packages/math-input/src/mq/custom-elements.js |
MQ.registerEmbed('newLine', ...) |
packages/math-input/package.json |
Declares @pie-framework/mathquill |
Dev-only mathquill (tests / tooling): packages/editable-html, packages/editable-html-tip-tap, packages/demo (versions aligned with math-input, currently 1.2.1-beta.1).
| Package | Depends on |
|---|---|
math-toolbar |
@pie-lib/math-input (mq.Input, mq.Static), heavy .mq-* styling, this.input.mathField / __controller usage in editor-and-pad.jsx |
editable-html-tip-tap |
math-input, math-toolbar |
editable-html |
Same (Slate path) |
demo |
Dynamic require of math-input to avoid SSR loading mathquill |
__mocks__/@pie-framework/mathquill.js— Jest mock.pslb/pslb.config.js— bundles@pie-framework/mathquillin the math-edit module.packages/demo/next.config.js— transpiles@pie-framework/mathquill.
math-inline and math-templated historically import @pie-framework/mathquill for registerEmbed('answerBlock') and MQ.StaticMath. Phase 0 removes that direct dependency in favor of @pie-lib/math-input APIs.
- Phase 0a (pie-lib):
registerEmbedandapplyStaticMathare implemented inpackages/math-input/src/mq/mathquill-instance.jsand exported frompackages/math-input/src/index.jsx. MathQuill is initialized once there;mq/input.jsxandmq/static.jsximport sharedMQ. - Phase 0b (pie-elements): still to do — switch
math-inline/math-templated/ configure UI to these APIs and drop direct@pie-framework/mathquillimports.
Objective: @pie-framework/mathquill is imported only inside @pie-lib/math-input (plus mocks/tooling). pie-elements stops importing the fork directly.
- Add
registerEmbed(name, factory)— delegate toMQ.registerEmbedwhenMQis available (sametypeof window !== 'undefined'pattern as today). - Add
applyStaticMath(element, latex)— set text/content as required, then callMQ.StaticMath(element)(match current pie-elements usage; adjust if they pass latex separately today). - Export both from
packages/math-input/src/index.jsx. - Unit tests for the new exports (mock
@pie-framework/mathquillat module boundary).
Publish: release a new math-input version so pie-elements can bump.
math-inline:main.jsxandconfigure/src/general-config-block.jsx— import{ registerEmbed, applyStaticMath }from@pie-lib/math-input; remove@pie-framework/mathquillfrom package deps.math-templated: same pattern inmain.jsx.- Update tests/mocks.
Verification:
# In pie-elements (after changes)
rg '@pie-framework/mathquill' packages/*/src/
# Expect: no matches in source (only lockfiles if any)- Copy
packages/math-input→packages/math-input-mathlive(new package name inpackage.json). - Replace dependency:
mathliveinstead of@pie-framework/mathquill. - Reimplement internals:
mq/input.jsx—<math-field>/MathfieldElement, maplatex(),cmd/write/keystroke, focus/blur.mq/static.jsx— read-only math-field orconvertLatexToMarkupwhere sub-fields are not needed; plan\MathQuillMathField[rN]{...}→ MathLive placeholders for templated flows.custom-elements.js/ newline — macro or normalize\embed{newLine}[]→\newline(consistent withmath-rendering).registerEmbed/applyStaticMath— MathLive implementations (\placeholder{}, markup injection, or surrounding React chrome for answer blocks).- Keypad labels — prefer
convertLatexToMarkupover per-button MathQuill instances. updateSpans.js— re-evaluate against MathLive DOM; may become no-op or new selectors.common-mq-styles.js— replace.mq-*with MathLive.ML__*(or equivalent) as needed.
- Keep
HorizontalKeypadandkeys/; only the rendering path for LaTeX on keys changes. - Export surface matches
math-input(includingregisterEmbed,applyStaticMath).
- Point dependency from
@pie-lib/math-input→@pie-lib/math-input-mathlive. - Replace all
.mq-*styles andutils.jsDOM assumptions with MathLive structure. - Remove deep MathQuill access in
editor-and-pad.jsx(mathField.__controller.cursor, synthetickeydown) — reimplement mixed-number / fraction behavior using supported MathLive APIs.
editable-html-tip-tap— switch tomath-input-mathlive; adjust any MathQuill-specific CSS.demo— imports +next.config.jstranspile list (mathliveinstead of@pie-framework/mathquillwhere applicable).pslb/pslb.config.js— math-edit module includesmathliveinstead of (or alongside) mathquill during transition.editable-html(Slate) — only if still required by product; otherwise leave on legacymath-inputuntil Slate is removed or deprecated.
pie-elements: bump to math-input-mathlive after pie-lib packages are stable.
- Stored LaTeX: Items may contain
\embed{answerBlock},\embed{newLine}[],\MathQuillMathField[...]. Ensure authoring + player either normalize at load time or support both during a transition window. - MathJax: Keep
math-renderingbehavior for player-facing HTML; editing stack changes do not require replacing MathJax immediately.
- Remove
@pie-framework/mathquillfrom allpackage.jsonfiles that still list it. - Remove or replace
__mocks__/@pie-framework/mathquill.js. - Archive or retire the mathquill fork when nothing depends on it.
- Optional: rename
math-input-mathlive→math-inputwith a major version when consumers are gone.
| Area | Risk |
|---|---|
| Answer block embeds | MathQuill registerEmbed has no 1:1 MathLive equivalent; may need placeholders + React UI around the field. |
\MathQuillMathField |
Stored content; needs explicit conversion or MathLive feature parity. |
updateSpans |
Tied to mathquill-command-id; must be revalidated for MathLive output. |
| math-toolbar | Tight coupling to .mq-* and internal __controller APIs. |
| Bundle size | MathLive is larger than MathQuill; mitigate with lazy-loading (existing math-edit split helps). |
| Visual regression | Plan manual QA + optional screenshot tests around math editor and keypad. |
| # | Scope | Points | Notes |
|---|---|---|---|
| 1 | math-input: registerEmbed, applyStaticMath, exports, tests |
2 | No consumer changes yet. |
| 2 | math-inline + configure: use new API, drop fork dep, tests |
3 | Two files + mocks. |
| 3 | math-templated: same as ticket 2 |
2 | Single main file pattern. |
| 4 | Spike: MathLive POC (field, static, placeholder, keypad label, newline) | 3 | Can run parallel to 1–3 after ticket 1 is merged (or in parallel if no API conflict). |
Order: 1 → 2 → 3; then 4 and Phase 1.
| Phase | Effort |
|---|---|
| 0 | ~1–3 days engineering + review + publish |
| 1 | ~2–3 weeks |
| 2 | ~1 week |
| 3 | ~1 week (TipTap + demo + pie-elements bumps) |
| 4–5 | As needed for compat and cleanup |
- Fork:
@pie-framework/mathquill(jQuery shim, Interface v3). - Internal audit and Q&A that shaped this document: Cursor chat / team notes (search for “Migration Plan: MathQuill → MathLive”, Phase 0 centralization).