Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MathML operators get no spacing if they are not in the operator dictionary #3288

Open
xworld21 opened this issue Sep 20, 2024 · 2 comments
Open
Labels
Accepted Issue has been reproduced by MathJax team Code Example Contains an illustrative code example, solution, or work-around v3 v4
Milestone

Comments

@xworld21
Copy link

Issue Summary

Try the following with MathJax 3:

<math>
  <mrow>
    <mi>a</mi>
    <mo>&#x1D438;</mo>
    <mi>b</mi>
  </mrow>
</math>

$a \mathrel{E} b$

The first a E b is rendered with no spacing, unlike the second one.

I'd expect them to be rendered identically, because the default MathML operator spacing prescribes 0.27777em spacing on both sides. (Note: this is assuming I am reading the operator dictionary correctly! However, the native Chrome MathML renderer seems to agree with me.)

Technical details:

  • MathJax Version: 3.2.2
  • Client OS: Windows 11
  • Browser: Chrome 129.0.6668.59

I am replicating this on https://www.mathjax.org/#demo

Supporting information:

Screenshot
image

@dpvc
Copy link
Member

dpvc commented Sep 21, 2024

There are a couple of things going on, here. First, MathJax doesn't use MathML spacing rules by default. Rather, it tries to use TeX spacing rules unless you tell it not to. So to get the spacing you want, you would need to set the mathmlSpacing option to true in the chtml and svg blocks of your MathJax configuration.

But it turns out that that doesn't fix the problem entirely, as MathJax does some extra work to try to decide the spacing for values that aren't in the operator dictionary (in order to get the TeX spacing right). Unfortunately, this doesn't work well when mathmlSpacing is in effect. I will make a PR to fix the problem in v4, but for now, you can use the following configuration to work around the issue:

MathJax = {
  chtml: {
    mathmlSpacing: true
  },
  svg: {
    mathmlSpacing: true
  },
  startup: {
    ready: function() {
      const SMALLSIZE = 2/18;
      const MOSPACE = 5/18;
      function MathMLSpace(script, nodict, size) {
        return (nodict ? MOSPACE : script ? size < SMALLSIZE ? 0 : SMALLSIZE : size);
      }
      const {CommonWrapper} = MathJax._.output.common.Wrapper;
      const {OPTABLE} = MathJax._.core.MmlTree.OperatorDictionary;
      CommonWrapper.prototype.getMathMLSpacing = function () {
        const node = this.node.coreMO();
        const child = node.coreParent();
        const parent = child.parent;
        if (!parent || !parent.isKind('mrow') || parent.childNodes.length === 1) return;

        const mo = node.getText();
        const noDictDef = OPTABLE.infix[mo] || OPTABLE.prefix[mo] || OPTABLE.postfix[mo];
        const attributes = node.attributes;
        const isScript = (attributes.get('scriptlevel') > 0);
        this.bbox.L = (attributes.isSet('lspace') ?
                       Math.max(0, this.length2em(attributes.get('lspace'))) :
                       MathMLSpace(isScript, noDictDef, node.lspace));
        this.bbox.R = (attributes.isSet('rspace') ?
                       Math.max(0, this.length2em(attributes.get('rspace'))) :
                       MathMLSpace(isScript, noDictDef, node.rspace));

        const n = parent.childIndex(child);
        if (n === 0) return;
        const prev = parent.childNodes[n - 1];
        if (!prev.isEmbellished) return;
        const bbox = this.jax.nodeMap.get(prev).getBBox();
        if (bbox.R) {
          this.bbox.L = Math.max(0, this.bbox.L - bbox.R);
        }
      }
      MathJax.startup.defaultReady();
    }
  }
};

I know it is a bit long, but there was not a good way to make the needed changes without override the complete getMathMLSpacing() function.

See if that works for you for now.

@dpvc dpvc added Accepted Issue has been reproduced by MathJax team v3 Code Example Contains an illustrative code example, solution, or work-around v4 labels Sep 21, 2024
@dpvc dpvc added this to the v4.0 milestone Sep 21, 2024
@xworld21
Copy link
Author

Awesome, thanks! Yes, that should solve the problem. I'll double check that it matches the MathML Core spacing rules for all cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Accepted Issue has been reproduced by MathJax team Code Example Contains an illustrative code example, solution, or work-around v3 v4
Projects
None yet
Development

No branches or pull requests

2 participants