Skip to content

Publish QTI editor formulas as MathML - #6349

Open
rtibblesbot wants to merge 7 commits into
learningequality:unstablefrom
rtibblesbot:issue-6327-cced4e
Open

rtibblesbot wants to merge 7 commits into
learningequality:unstablefrom
rtibblesbot:issue-6327-cced4e

Conversation

@rtibblesbot

@rtibblesbot rtibblesbot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • QTI editor formulas published as empty spans; now MathML with TeX annotation (Perseus: $$latex$$).
  • Restore turns that MathML back into editor formulas.
  • Legacy $$…$$ formulas open as editor formulas.
  • Unconvertible LaTeX publishes as $$latex$$ instead of aborting.

References

Fixes #6327. Related: #6347.

Reviewer guidance

Suggested review: Full code review, then manual QA once the reviewer sets Needs QA.

  • User-visible files changed: contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/extensions/Math.js, contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/utils/comparisonKey.js.
  • The shared TipTap Math node now loads any <math> carrying an application/x-tex annotation as an editable formula, so saving a converted legacy, restored or ricecooker item rewrites its MathML as data-latex spans that publish inline, block formulas included.
  • Legacy markdown conversion changed beyond the MathML namespace: a line starting with $$…$$ followed by text now converts inline and keeps that text, and \text{} holding < or & now converts instead of failing.
  • QA: publish a QTI-editor exercise with formulas in a prompt, a choice and a hint, check they render in Kolibri develop (QTI) and an older Kolibri (Perseus), then restore the channel and reopen the question in the editor.

Open questions:

  • Restore converts any latex2mathml-shaped <math> with a TeX annotation, so republish regenerates ricecooker MathML — acceptable?
  • Unconvertible legacy LaTeX ($$x_$$) becomes editable QTI text instead of staying legacy — acceptable?

QA (riskiest: reopen, publish). Requires: a new Studio channel and a Kolibri develop build.

  1. Formulas from the math tool
    • Make an exercise with "Single Choice", "Multiple Choice" and "Numeric" questions.
    • Click "Math formula"; add a formula to the question, two choices and a hint.
    • Type text directly after each formula. Include a<b&c once.
    • Click "CLOSE", reload, reopen each question.
    • Each formula shows as maths; text after it stays.
  2. Publish and view in Kolibri
    • Publish and import into Kolibri.
    • Open the exercise as a learner. Each formula shows as maths.
  3. Old questions with formulas
    • Requires: an exercise from the old question editor with $$…$$ formulas in the question, answers and hints.
    • Open it in the side panel and in "Edit details" > "QUESTIONS" > "Edit". Each formula shows as maths.
    • Change other text, click "CLOSE", reload. Formulas stay.
    • Publish. The publish completes.
  4. Restore
    • Restore the channel from step 2; open the question in the QTI editor. Formulas reopen as formulas.

Look out for:

  • Missing words directly after a formula in old questions, e.g. "$$5$$ exactly".

Evidence

Legacy $$…$$ formulas in preview and editor

Step Screenshot
Before: MathML and LaTeX run together ("x2+1x^2 + 1") Before: MathML and LaTeX run together

After: not captured (stale QA bundle).

Unconvertible legacy LaTeX

Step Screenshot
Preview: formulas as $$…$$ source Preview: formulas as $$…$$ source
s2-unconvertible-latex-edit-save.webm

Math tool formulas survive save and reload

Step Screenshot
Reloaded hints: x/y, 1+1 and following text intact Reloaded hints: x/y, 1+1 and following text intact
s3-reopen-formulas-after-reload.webm

<, &, \frac and malformed formulas

Step Screenshot
After reload: a<b&c, ½, both x_ and following text intact After reload: a<b&c, ½, both x_ and following text intact

Mixed legacy + QTI channel publish

Step Screenshot
Reopened after publish: formulas intact Reopened after publish: formulas intact
s5-publish-mixed-channel.webm
More captures (16)
Step Screenshot
Before: legacy question flattened in editor Before: legacy question flattened in editor
Unconvertible question opened for editing Unconvertible question opened for editing
Aligned block opened as editable $$…$$ text Aligned block opened as editable $$…$$ text
Unconvertible questions after edit and reload Unconvertible questions after edit and reload
Math formula dialog with x^2+1 Math formula dialog with x^2+1
Single Choice formulas authored Single Choice formulas authored
Multiple Choice formulas authored Multiple Choice formulas authored
Numeric formula authored Numeric formula authored
Hint formulas authored Hint formulas authored
Hint formulas after reload Hint formulas after reload
Malformed x_ in the math dialog Malformed x_ in the math dialog
Prompt formulas authored Prompt formulas authored
Mixed channel before publish Mixed channel before publish
Publish panel Publish panel
Mixed channel published Mixed channel published
QTI-editor exercise question list after publish QTI-editor exercise question list after publish

AI usage

Claude Code wrote the implementation and tests. Verified with the assessment utils and restore suites and pre-commit; no Kolibri import run.


Written by rtibblesbot, an LLM-based coding agent.

@rtibblesbot

🟡 Waiting for feedback

Last updated: 2026-10-28 01:55 UTC

rtibblesbot and others added 7 commits October 27, 2026 18:51
Rendered <math> now declares the MathML namespace, so converted items
with formulas pass the item XSD. Renames _convert to latex_to_mathml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
latex2mathml raises on malformed input such as `x_` or `{`, which
aborted the whole channel publish. The formula now renders as escaped
`$$latex$$` text and a warning is logged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The native QTI publish replaces each `span[data-latex]` the editor wrote
with latex_to_mathml output, in prompts, choices and hints. Stored
raw_data is left as the editor wrote it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A `span[data-latex]` used to unwrap to its empty content, so the
formula vanished. It now derives as `$$latex$$`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restore keeps the packaged MathML, which the editor loads as formulas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A line opening with $$…$$ was parsed as block math, dropping the rest
of the line (`$$5$$ exactly` lost "exactly"). Block math now needs the
formula to end its line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Converted legacy items carry formulas as MathML, which TipTap flattened
to text, MathML and LaTeX run together, so saving an edit destroyed
them. The Math node now parses MathML with a TeX annotation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rtibblesbot
rtibblesbot marked this pull request as ready for review October 28, 2026 01:55
@rtibblesbot
rtibblesbot requested review from a team and leq-bot October 28, 2026 01:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[QTI] - The formulas are not shown in Kolibri

1 participant