Issues observed while migrating from MathJax 3.1.2 to 4.1.1

92 views
Skip to first unread message

akhil joshi

unread,
Mar 12, 2026, 7:28:31 AMMar 12
to mathja...@googlegroups.com
Hi MathJax Team,
We encountered the following issue while migrating from MathJax 3.1.2 to version 4.1.1.
Issue 1 — <mi>cos</mi> treated as a multi-character identifier
In MathJax 4, multi-letter sequences inside <mi> are treated as identifiers. The TeX input jax places multi-letter sequences into a single <mi> element within macros such as \mathrm\mathbf, and related commands. This behavior is configurable, but by default it applies to letter sequences.
Because of this change, using <mi>cos</mi> renders the text in italics as a variable name rather than as a function operator.
Workaround implemented
To correct the rendering, we replaced <mi>cos</mi> with <mo>cos</mo> throughout the XML.
Summary of observations
  1. In the older version (3.1.2), the structure was as follows, and the rendering in proof was correct.

image.png

image.png


  2) When the same structure is used in version 4.1.1, it does not render correctly and produces the issue described above.


image.png



3) After updating the code to replace <mi>cos</mi> with <mo>cos</mo>, the rendering in version 4.1.1 appears correct 


image.png


image.png

Issue 2 —  Missing <mo> function-apply separator (invisible character)

In the existing code, <mo>cos</mo> is immediately followed by <mrow> without the invisible function-application operator &#x2061;. MathJax 4 appears to be stricter regarding this spacing.

 

To address this, we added <mo>&#x2061;</mo> (invisible function apply) after each cos.

image011.png


Issue 3 — Underscore symbol alignment
In MathJax 3.1.2, the underscore/underline renders correctly and is properly aligned under the character.
image.png

image.png

However, in MathJax 4.1.1, the underscore appears slightly left-aligned compared to the base character.
Observation
  • The same MathML structure that rendered correctly in version 3 now appears misaligned in version 4.1.1.
  • The underline glyph appears slightly shifted to the left in the rendered output.

    image.png

Could you please confirm:
  • Whether these changes are expected behavior in MathJax 4.1.1.
  • If there is a recommended configuration or styling approach to maintain the rendering behavior from MathJax 3.x.
Could you please confirm whether this is the recommended approach when migrating MathML content to MathJax 4, or if there is a preferred configuration change that would preserve the previous behavior?
Thank you for your guidance.

Thanks & Regards,
Akhil Joshi 

Davide Cervone

unread,
Mar 12, 2026, 11:32:18 AMMar 12
to mathja...@googlegroups.com
Issue 1 — <mi>cos</mi> treated as a multi-character identifier
In MathJax 4, multi-letter sequences inside <mi> are treated as identifiers. The TeX input jax places multi-letter sequences into a single <mi> element within macros such as \mathrm\mathbf, and related commands. This behavior is configurable, but by default it applies to letter sequences.
Because of this change, using <mi>cos</mi> renders the text in italics as a variable name rather than as a function operator.
Your observation is incorrect.  In MathML, multi-letter identifiers are rendered in the upright font, not italics.  E.g.

  <mi>cos</mi>
  <mi>x</mi>
</math>

renders as

PastedGraphic-1.png

in v4.1.1.  This has not changed in v4.  Even your 4.1.1 rendering shows the cosine in an upright font:

PastedGraphic-2.png
I'm wondering if the CSS on your page may be interfering with MathJax's output.  You don't give the MathJax configuration you are using or the MathJax component you are loading (e.g., mml-chtml.js), so it is hard to test without making assumptions.

The issue you don't discuss is the red "mfrac", which indicates a problem with that fraction's MathML structure.  Often that means the number of children is incorrect.  Using the MathJax contextual menu to Show Math As  the MathML Code should an attribute on on <merror> element for the mfrac that shows the actual error message.  It would help to see what that is.

The equation you provided in the first image in your summary section renders properly for me in v4.1.1:

mjx-4.1.1.png

so I'm wondering if the MathML is actually the same as the MathML in your v4.1.1 test.  (Perhaps it was actually the result of your trying to replace the cosines with <mo> elements, but something has gone wrong?)  Can you provide a link to a page that actually exhibits the problem?

To correct the rendering, we replaced <mi>cos</mi> with <mo>cos</mo> throughout the XML.

That should not be necessary, as shown in my image above.  If this is making a difference for you, then again I wonder about CSS that might be affecting the result.

Issue 2 —  Missing <mo> function-apply separator (invisible character)
In the existing code, <mo>cos</mo> is immediately followed by <mrow> without the invisible function-application operator &#x2061;. MathJax 4 appears to be stricter regarding this spacing.

This is not true.  For example,

  <mo>cos</mo>
  <mrow>
    <mi>&#x3C9;</mi>
    <mi>t</mi>
  </mrow>
</math>

produces

PastedGraphic-3.png

which has the proper spacing after the "cos".  Here is your equation with the <mo>cos</mi> replaced by <mo>cos</mo> without additional invisible function-apply:

PastedGraphic-4.png

The spacing of the cosines is correct without the U+2061 characters.

Issue 3 — Underscore symbol alignment
In MathJax 3.1.2, the underscore/underline renders correctly and is properly aligned under the character. ...  However, in MathJax 4.1.1, the underscore appears slightly left-aligned compared to the base character.

I am not able to reproduce the issue you are seeing.  Here is the expression rendered in v4.1.1 for me:

PastedGraphic-5.png

Again, without more information about your setup,. it is hard to diagnose the problem.  What OS and browser (and versions) are you using?  If you remove (or disable) the CSS from your page, does that make a difference?

Could you please confirm:
  • Whether these changes are expected behavior in MathJax 4.1.1.

No they are not, and I am not able to produce any of the issues you are seeing.

If you can provide a test page that illustrates the problems, I can investigate further.

Davide

akhil joshi

unread,
Mar 13, 2026, 3:23:38 AMMar 13
to MathJax Users

Hi Davide,

Thanks for your feedback.

Please check the attached implementation screenshot for MathJax 4.x.
Also, we are not injecting any CSS from MathJax in our implementation.
We are comparing the results using the https://www.mathjax.org/#demo link. We copied the original MathML code from the equation rendered in OnProof and pasted the same code into the MathJax demo site.The same issue/error appears there as well.

Test link: Please check below. (Only the equations for which issues were reported via email are included in the link below.)
https://qaops2editor.pubmate.co.in/#/?templateID=5fd5e790c0274a93b6b9cd413887e64e071609633

Environment details:

  • OS: Windows 11

  • Browser used for rendering: Google Chrome Version 145.0.7632.160 (Official Build) (64-bit)

Please let us know if you need any additional information.

Best regards,
Akhil Joshi 

sc2.png
sc3.png
sc4.png
sc1.png

Davide Cervone

unread,
Mar 14, 2026, 8:01:57 AMMar 14
to mathja...@googlegroups.com
Thanks for the additional information.  That was helpful.

The issue with the mfrac turns out to be due to the semantic enrichment that is part of the speech generation process.  It is adding an extra node to the mfrac that is causing it to have the wrong number of children, and that is producing the red error node.  The extra node is an invisible multiplication that should added before the mfrac, but is being added inside it instead.  One solution would be to add <mo>&#x2062;</mo> before the mfrac yourself, as that would prevent the semantic-enrichment from needing to add one.  Alternatively, since you are already turning of speech and Braille generation, you could disable the semantic enrichment entirely (though a use could still turn it on, which will cause the error again).

The issue with the underlines turns out to be an interaction between the CSS for the two different sizes of the underline character being used.  Combining characters like U+0332 are always hard for mathJax to work with, because they operate differently in different browser, and ins some fonts they are implemented by zero-width characters that overlap to the left.  MathJax uses extra CSS to manage the zero-width characters so that all browsers will handle them the same.  In the mathjax-newcm font, one size is zero-width and the other is not, but the CSS for the zero-width version was being inherited by the larger size, causing the improper placement.  This was sensitive to the order in which things occurred, which is why I didn't see it in my output initially.

A work-around would be to include

mjx-c.mjx-c332.NCM-SO {
  margin-left: 0;
}

in your page's CSS.

I'm not sure what issue the third equation in your test page is intended to show.  It seems to work as expected for me.

we are not injecting any CSS from MathJax in our implementation.

When I mentioned CSS, it was not about the MathJax CSS, but about the other CSS in the page.  (MathJax inserts its own, so you would not be doing that yourself.)  It turns out that was not the issue after all, so I was wrong in my suspicions there.

We copied the original MathML code from the equation rendered in OnProof and pasted the same code into the MathJax demo site

From the screen shot, it appears that you pasted in the enriched MathML (it includes the data-semenatic attributes), not the original MathML.  The former will have been modified to remove the invalid mfrac elements and insert the merror elements in its place, so pasting that into the MathJa demo would certainly have produce the output with the red mfrac nodes in it.  But you are right that had you put in the original, it would still have done the same, since the semantic-enrichment is being done on the MathJax site as well.  I'm only mentioning this because pasting in the final MathML would not be a valid test, as it already contains the red mfrac nodes.

Davide

On Mar 13, 2026, at 3:23 AM, akhil joshi <akkijo...@gmail.com> wrote:

Hi Davide,

Thanks for your feedback.

Please check the attached implementation screenshot for MathJax 4.x.
Also, we are not injecting any CSS from MathJax in our implementation.
We are comparing the results using the https://www.mathjax.org/#demo link. We copied the original MathML code from the equation rendered in OnProof and pasted the same code into the MathJax demo site.The same issue/error appears there as well.

Test link: Please check below. (Only the equations for which issues were reported via email are included in the link below.)
https://qaops2editor.pubmate.co.in/#/?templateID=5fd5e790c0274a93b6b9cd413887e64e071609633

Environment details:

  • OS: Windows 11

  • Browser used for rendering: Google Chrome Version 145.0.7632.160 (Official Build) (64-bit)

Please let us know if you need any additional information.

Best regards,
Akhil Joshi 



On Thursday, March 12, 2026 at 9:02:18 PM UTC+5:30 Davide Cervone wrote:
Issue 1 — <mi>cos</mi> treated as a multi-character identifier
In MathJax 4, multi-letter sequences inside <mi> are treated as identifiers. The TeX input jax places multi-letter sequences into a single <mi> element within macros such as \mathrm\mathbf, and related commands. This behavior is configurable, but by default it applies to letter sequences.
Because of this change, using <mi>cos</mi> renders the text in italics as a variable name rather than as a function operator.
Your observation is incorrect.  In MathML, multi-letter identifiers are rendered in the upright font, not italics.  E.g.

  <mi>cos</mi>
  <mi>x</mi>
</math>

renders as

<PastedGraphic-1.png>

in v4.1.1.  This has not changed in v4.  Even your 4.1.1 rendering shows the cosine in an upright font:

<PastedGraphic-2.png>
I'm wondering if the CSS on your page may be interfering with MathJax's output.  You don't give the MathJax configuration you are using or the MathJax component you are loading (e.g., mml-chtml.js), so it is hard to test without making assumptions.

The issue you don't discuss is the red "mfrac", which indicates a problem with that fraction's MathML structure.  Often that means the number of children is incorrect.  Using the MathJax contextual menu to Show Math As  the MathML Code should an attribute on on <merror> element for the mfrac that shows the actual error message.  It would help to see what that is.

The equation you provided in the first image in your summary section renders properly for me in v4.1.1:

<mjx-4.1.1.png>

so I'm wondering if the MathML is actually the same as the MathML in your v4.1.1 test.  (Perhaps it was actually the result of your trying to replace the cosines with <mo> elements, but something has gone wrong?)  Can you provide a link to a page that actually exhibits the problem?

To correct the rendering, we replaced <mi>cos</mi> with <mo>cos</mo> throughout the XML.

That should not be necessary, as shown in my image above.  If this is making a difference for you, then again I wonder about CSS that might be affecting the result.

Issue 2 —  Missing <mo> function-apply separator (invisible character)
In the existing code, <mo>cos</mo> is immediately followed by <mrow> without the invisible function-application operator &#x2061;. MathJax 4 appears to be stricter regarding this spacing.

This is not true.  For example,

  <mo>cos</mo>
  <mrow>
    <mi>&#x3C9;</mi>
    <mi>t</mi>
  </mrow>
</math>

produces

<PastedGraphic-3.png>

which has the proper spacing after the "cos".  Here is your equation with the <mo>cos</mi> replaced by <mo>cos</mo> without additional invisible function-apply:

<PastedGraphic-4.png>

The spacing of the cosines is correct without the U+2061 characters.

Issue 3 — Underscore symbol alignment
In MathJax 3.1.2, the underscore/underline renders correctly and is properly aligned under the character. ...  However, in MathJax 4.1.1, the underscore appears slightly left-aligned compared to the base character.

I am not able to reproduce the issue you are seeing.  Here is the expression rendered in v4.1.1 for me:

<PastedGraphic-5.png>

Again, without more information about your setup,. it is hard to diagnose the problem.  What OS and browser (and versions) are you using?  If you remove (or disable) the CSS from your page, does that make a difference?

Could you please confirm:
  • Whether these changes are expected behavior in MathJax 4.1.1.

No they are not, and I am not able to produce any of the issues you are seeing.

If you can provide a test page that illustrates the problems, I can investigate further.

Davide

--
You received this message because you are subscribed to the Google Groups "MathJax Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mathjax-user...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/mathjax-users/f8d306ad-26fa-4a26-baff-95ff86c0ecc2n%40googlegroups.com.
<sc2.png><sc3.png><sc4.png><sc1.png><PastedGraphic-1.png><PastedGraphic-2.png><mjx-4.1.1.png><PastedGraphic-3.png><PastedGraphic-4.png><PastedGraphic-5.png>

akhil joshi

unread,
Mar 18, 2026, 6:10:59 AMMar 18
to MathJax Users
Hi MathJax Team,

  1. Issue 1: Multi-character identifiers (e.g., <mi>cos</mi>)
We are currently integrating MathML with MathJax 4 and have encountered a couple of related issues that require manual intervention. While the suggested workarounds resolve the problems, they are not scalable for our use case, so we would like clarification on the recommended long-term approach.

Issue 1: Multi-character identifiers (e.g., <mi>cos</mi>) and Issue 2: Semantic enrichment breaking <mfrac>
In MathJax 4, expressions like <mi>cos</mi> are treated as multi-character identifiers and rendered in italics (as variables), rather than as function operators.
Current workaround:
We have manually replaced:
<mi>cos</mi>
with:
<mo>cos</mo>
This fixes the rendering, but requires preprocessing across our content.
We also encountered an issue where semantic enrichment inserts an invisible multiplication operator (<mo>&#x2062;</mo>) inside an <mfrac>, resulting in an invalid structure and a rendering error.
Suggested workaround (from your guidance):
  • Manually insert <mo>&#x2062;</mo> before <mfrac>, or
  • Disable semantic enrichment
We implemented the workaround, and it resolves the issue.

Main concern
Both fixes require manual intervention or preprocessing, which is not ideal because:
  • Our content is generated dynamically and at scale
  • Manual transformations are error-prone and hard to maintain
  • Even if we disable enrichment, users may re-enable accessibility features, reintroducing the issue

Questions
  1. Is it expected that developers should preprocess MathML (e.g., converting <mi>cos</mi> to <mo>cos</mo>) when using MathJax 4?
  2. Is there a recommended configuration to automatically treat common function names (sin, cos, log, etc.) as operators instead of identifiers?
  3. Regarding the <mfrac> issue:
    • Is this a known limitation/bug in semantic enrichment?
    • Are there plans for MathJax to handle correct placement of invisible operators automatically?
  4. Is there a way to safely enable accessibility features without risking structural issues in MathML?
  5. Overall, what is the recommended approach to avoid manual intervention for these cases?

Expectation
We would prefer a solution where:
  • MathJax handles these cases internally, or
  • A configuration-based approach eliminates the need for manual preprocessing


2)  undersscore aligmnet issue  :
Additionally, regarding the underline alignment issue (U+0332), we are currently using the suggested CSS workaround:
mjx-c.mjx-c332.NCM-SO {
margin-left: 0;
}
We would like to confirm:
  1. Is this considered a safe and recommended workaround for production use?
  2. Are the class names (e.g., .mjx-c332, .NCM-SO) stable across versions?
  3. Is there a plan to address this issue within MathJax itself to avoid the need for custom CSS?

3)  Extra invisible operator nodes affecting equation editing in MathJax v4  
for e.g.  <mjx-mo data-semantic-type="operator" data-semantic-role="multiplication" data-semantic-annotation="depth:9" data-semantic-id="77" data-semantic-parent="78" data-semantic-added="true" data-semantic-operator="infixop,⁢" data-semantic-level-number="8" data-speech-node="true"><mjx-c class="mjx-c2062">⁢</mjx-c></mjx-mo>

(resonse from your side for third issue) I'm not sure what issue the third equation in your test page is intended to show.  It seems to work as expected for me.

Check the attached images for the 3.1.2 which no boxes while editing and second one is for boxes showing inside equations 
when user makes any changes the extra entity is added in out xml which not present in first time i have attached those screenshot also.

Impact on our workflow

  • When a user clicks on an equation, it opens in our editor (iMathEQ).

  • The editor expects a clean structure and displays editable placeholders (blank boxes).

  • Due to the additional invisible operator nodes, extra placeholders/boxes are appearing inside the equation.

  • This behavior was not present in MathJax 3.1.2.


Clarification needed

We would like your guidance on the following:

  1. Is the insertion of the invisible multiplication operator (&#x2062;) part of semantic enrichment?

  2. Is there a way to prevent these additional nodes from being inserted during rendering?

  3. Would disabling semantic enrichment fully prevent such modifications to the DOM structure?

  4. Is there a recommended approach for integrating MathJax-rendered output with equation editors, without introducing extra structural elements?


Our concern is avoiding fragile fixes that may break with future updates.
Any guidance on best practices for handling these scenarios in a scalable way would be greatly appreciated.
Thank you for your support.
4.1.1.png
3.1.2.png
inputxml.png
outxml.png

Davide Cervone

unread,
Mar 18, 2026, 8:42:23 PMMar 18
to mathja...@googlegroups.com
Issue 1: Multi-character identifiers (e.g., <mi>cos</mi>) and Issue 2: Semantic enrichment breaking <mfrac>
In MathJax 4, expressions like <mi>cos</mi> are treated as multi-character identifiers and rendered in italics (as variables), rather than as function operators.

This is incorrect, as I mentioned previously.  MathML specifies that multi-character <mi> elements have mathvariant="normal" by default (only single-letter <mi> have mathvariant="italic" by default).  MathJax properly renders multi-character <mi> in an upright font, as the images I included in my previous message illustrated.  If you are not seeing that result, then you will need to provide an example showing that.  (Note, however, that the sample page you linked to in a previous message were to a Wiley site that prevents one from opening the browser's developer console to inspect the DOM or enter commands, so it is not particularly useful for investigating your problems).

We also encountered an issue where semantic enrichment inserts an invisible multiplication operator (<mo>&#x2062;</mo>) inside an <mfrac>, resulting in an invalid structure and a rendering error.
  1. Is it expected that developers should preprocess MathML (e.g., converting <mi>cos</mi> to <mo>cos</mo>) when using MathJax 4?

No, there should not be an issue with <mi>cos</mi>.  I am not able to reproduce the problem, and you haven't given an example where it occurs for you.

  1. Is there a recommended configuration to automatically treat common function names (sin, cos, log, etc.) as operators instead of identifiers?

No.  They should work properly as is.

  1. Regarding the <mfrac> issue:
    • Is this a known limitation/bug in semantic enrichment?

Yes, I diagnosed it while investigating your earlier report, though I haven't yet made a bug report in the speech-rule-engine repository's issue tracker..

    • Are there plans for MathJax to handle correct placement of invisible operators automatically?

I'm sure it will be fixed in a future release.

  1. Is there a way to safely enable accessibility features without risking structural issues in MathML?

The semantic enrichment is a complicated process, and it may still have issues like this.  There is no guarantee that it will not have bugs.  We appreciate your reporting the issues that you find with it, and we will fix them as soon as we can.  But there is always going to be the risk that there are more issues to be found.

  1. Overall, what is the recommended approach to avoid manual intervention for these cases?

I have given you mmlfilters in some cases to fix the issues that you are having automatically, which I don't consider to be "manual intervention" (in that the fixes are applied automatically once the filter is written).  It would be possible to look for the incorrect <mfrac> elements and move the errant nodes using such a filter.  It would be possible even to convert <mi> to <mo> for multi-letter identifiers, though there should be no reason to do that, as I have said.

Here is a configuration that will move the extra nodes out of the mfrac nodes to being before the mfrac:

MathJax = {
  loader: {
    'a11y/semantic-enrich': {
      ready() {
        for (const item of MathJax.startup.extensions.items) {
          if (item.item.toString().match(/allowHtmlInTokenNodes/)) {
            const {MathML} = MathJax._.input.mathml_ts;
            const {EnrichHandler} = MathJax._.a11y['semantic-enrich'];
            const Mml = new MathML({allowHtmlInTokenNodes: true});
            item.item = (handler) => EnrichHandler(handler, Mml);
            Mml.mmlFilters.add(({data}) => {
              const nodes = data.querySelectorAll('mfrac > mo[data-semantic-added]');
              for (const node of nodes) {
                const mfrac = node.parentNode;
                mfrac.parentNode.insertBefore(node, mfrac);
              }
            });
            break;
          }
        }
      }
    }
  }
};

It takes a little work to get access to the MathML input jax that is used to read the semantically-enriched MathML.  We need to access it in order to add an mmlFilter that fixes the broken MathML.

2)  undersscore aligmnet issue  :
Additionally, regarding the underline alignment issue (U+0332), we are currently using the suggested CSS workaround:
mjx-c.mjx-c332.NCM-SO {
margin-left: 0;
}
We would like to confirm:
  1. Is this considered a safe and recommended workaround for production use?

Yes, this is safe, and can be used in production.  The next version of MathJax will include a fix for the issue, but you can use this CSS for now, and it won't hurt the future fix.

  1. Are the class names (e.g., .mjx-c332, .NCM-SO) stable across versions?

There is no guarantee of this, but I don't foresee them changing.

  1. Is there a plan to address this issue within MathJax itself to avoid the need for custom CSS?

Yes, I have a fix but have not yet made a PR for it.

3)  Extra invisible operator nodes affecting equation editing in MathJax v4  
for e.g.  <mjx-mo data-semantic-type="operator" data-semantic-role="multiplication" data-semantic-annotation="depth:9" data-semantic-id="77" data-semantic-parent="78" data-semantic-added="true" data-semantic-operator="infixop,⁢" data-semantic-level-number="8" data-speech-node="true"><mjx-c class="mjx-c2062">⁢</mjx-c></mjx-mo>

(resonse from your side for third issue) I'm not sure what issue the third equation in your test page is intended to show.  It seems to work as expected for me.

Check the attached images for the 3.1.2 which no boxes while editing and second one is for boxes showing inside equations 
when user makes any changes the extra entity is added in out xml which not present in first time i have attached those screenshot also.

OK, I don't recall your having mentioned this as an editor problem before, which is why I didn't understand why it was included in your list of equations.

Impact on our workflow

  • When a user clicks on an equation, it opens in our editor (iMathEQ).

  • The editor expects a clean structure and displays editable placeholders (blank boxes).

  • Due to the additional invisible operator nodes, extra placeholders/boxes are appearing inside the equation.

  • This behavior was not present in MathJax 3.1.2.


Again, these nodes are being added by the semantic enrichment.  That would have happened in v3 if you (or one of your users) turned on the accessibility tools.  (Try it and see.)

Is the editor actually editing the MathJax output?  (That would be a bad idea.)  What are you actually sending to the editor?  I'm not clear on how this pipeline works and what part of MathJax's output you are accessing for this.


Clarification needed

We would like your guidance on the following:

  1. Is the insertion of the invisible multiplication operator (&#x2062;) part of semantic enrichment?


Yes.

  1. Is there a way to prevent these additional nodes from being inserted during rendering?


Only to disable semantic enrichment.

  1. Would disabling semantic enrichment fully prevent such modifications to the DOM structure?


It's not the DOM that is being modified, it is the MathML prior to converting it to HTML that is modified.  Disabling semantic enrichment would prevent the original MathML from being modified, so the corresponding HTML nodes would reflect the original MathML structure rather than the enriched one.

  1. Is there a recommended approach for integrating MathJax-rendered output with equation editors, without introducing extra structural elements?


If you are sending the editor MathML nodes or serialized MathML, you should probably be giving it the original (non-enriched) MathML, not the enriched version, and when you get it back from the editor and render it in MathJax, it will be enriched again from the editor MathML.  That would be the safest way to handle it.  Depending on how you are getting the data that you re sending to the editor, there are several different possible ways to obtain the original MathML.  But without knowing more about how your site interacts with the editor, I'm not really able to give you much detail about that.

If the editor is actually reading the HTML produced by MathJax and inferring the original expression from that, then that is an approach that I would expect to be pretty fragile.  If the editor is reading from the DOM, you would be better off including the original MathML in the MathJax output (there are several ways that could be done) and have the editor pick it up from there rather than trying to interpret the MathJax HTML output.

Our concern is avoiding fragile fixes that may break with future updates.

The HTML (and SVG) output structure is not guaranteed to be the same from version to version.  For example, in a future release when we implement the rowspan and columnspan attributes for tables, the table structure is going to have to be completely reworked.  We do include the MathML node names in the output when possible, but that is not always exactly the structure of the original MathML.  For example, an <msqrt> node will include an <mjx-mo> node for the surd that is part of the square root symbol, even though there is no <mo> for it in the original MathML itself.  Another example occurs with <mlabeledtr> nodes, where the first <mtd> is the equation label for that row; in the HTML DOM tree, the label's <mjx-mtd>` will not be inside the `<mjx-mlabeledr>`, element, as the labels are all placed outside the main table layout so that they float with window size changes.  Using the HTML DOM for editing purposes is not going to work well in these types of situations.

Furthermore, as you have discovered, the output is based on the semantically enriched MathML tree, not the original one, and the semantic enrichment can reorganize the tree, and add nodes like the ones you are seeing for the invisible times and invisible function apply characters.  The resulting structure may change from version to version as improvements in the enrichment (or bug fixes) are made.  So relying on that for your editing is also bad idea.

The only save approach is to edit the original MathML, not the enriched MathML or the final HTML DOM nodes.

Turning off semantic enrichment would prevent the changes to the original MathML, but it would also disable the speech generation, the expression explorer, and the improved line breaking that the enrichment provides (if you are doing automatic displayed-equation line breaks).  And as you point out, users could turn it on again using the MathJax menu (though you could disable the semantic enrichment option in the menu to prevent that).  Relying on the older assistive-mathml extension instead of the speech-rule engine (which does the semantic enrichment as well as the speech generation) would mean that it would not work well on some systems (like Mac OS), so your users who need assistive support would have to work in Windows.

Any guidance on best practices for handling these scenarios in a scalable way would be greatly appreciated.

I hope this gives you the advice you need.  I have spent time in the past providing you with mmlFilters to work around some of the issues you have faced.  If you would like more of these, or help with interfacing with your editor, you could contract with me to perform additional coding of this type.  If you want to pursue that, we can communicate off-list to work out the details.

Davide




akhil joshi

unread,
Mar 23, 2026, 8:58:54 AM (13 days ago) Mar 23
to MathJax Users

Hi Davide,

Thanks for the suggestion — using an mmlFilter to move the extra nodes works well.

Initially, the provided configuration didn’t work in my setup, but after making a few adjustments on my side, I was able to get it working.

I’m sharing the updated code along with links where the earlier <mfrac> issue was occurring. With the current implementation, the issue no longer appears.

Could you please take a look and confirm whether this approach is safe for production use?

Updated Code :

  private setMathJaxConfig() {
  if ((window as any).MathJax) return;
  (window as any).MathJax = {
    tex: {
      inlineMath: [['$', '$'], ['\\(', '\\)']],
      displayMath: [['$$', '$$'], ['\\[', '\\]']]
    },
    options: {
      enableMenu: true,
      menuOptions: {
       settings: {
          speech: false,
          braille: false,
          assistiveMml: true,
        }
      }
    },
    startup: {
      typeset: true,
        polyfillHasOwn: false,
    },
   loader: {
  'a11y/semantic-enrich': {
    ready() {
      let MJ = (window as any).MathJax;

      for (let item of MJ.startup.extensions.items) {
        if (item.item.toString().match(/allowHtmlInTokenNodes/)) {

          let { MathML } = MJ._.input.mathml_ts;
          let { EnrichHandler } = MJ._.a11y['semantic-enrich'];

          let Mml = new MathML({ allowHtmlInTokenNodes: true });

          item.item = (handler) => EnrichHandler(handler, Mml);

          Mml.mmlFilters.add(({ data }) => {
            let nodes = data.querySelectorAll('mfrac > mo[data-semantic-added]');
            for (let node of nodes) {
              let mfrac = node.parentNode;
              mfrac.parentNode.insertBefore(node, mfrac);
            }
          });

          break;
        }
      }
    }
  }
}
  };
}

Test Link : https://qaops2editor.pubmate.co.in/#/?templateID=0abf977f959d4a49a63bf97a29c8f8fe124051050  

Thanks again for your help!

Davide Cervone

unread,
Mar 25, 2026, 4:14:00 PM (11 days ago) Mar 25
to mathja...@googlegroups.com
Akhil:

Could you please take a look and confirm whether this approach is safe for production use?


Yes, I think that should work for you.  I'm not sure whey you needed to change the "const" to "let", but either should work (though "const" is preferred for these, since their values aren't changing).

Davide
Reply all
Reply to author
Forward
0 new messages