Skip to content

v4-beta.3 linebreak not respected with \text (and other issues) #3098

Open
@TrebledJ

Description

@TrebledJ

Issue Summary

Linebreak issue with text elements.

Steps to Reproduce:

  1. Open web page.
  2. See math sticking out of container and not breaking.
  3. Cry.

Linebreak not working with text. Math is a bit better, but also sticks out a bit.

For example:

$\texttt{The quick brown } \text{fox jumps } \textsf{over the lazy dog}\dots\ \texttt{And } \texttt{over } \texttt{the } \texttt{rainbow } \texttt{dost } \texttt{thy } \texttt{chicken } \texttt{poop } \texttt{fly}\dots$

There are also instances when output errors occur for regular LaTeX and for \breaks.

$$
e^{i\pi} + 1 = 0
\qquad
\begin{align}
x + y + z &= 1 \\\\
2x - y + 3z &= 2 \\\\
4x - 5y + 10z &= 3 \\\\
\end{align}
$$

$\texttt{Maybe (Either (a, a) (Bool, a))} \break \equiv \texttt{(Maybe a, Maybe a)}$
$\texttt{Maybe (Either (a, a) (Bool, a))} \break = \texttt{(Maybe a, Maybe a)}$

All of these are shown in the supporting demo.

Technical details:

  • MathJax Version: 4.0.0-beta.3
  • Client OS: MacOS 12.6.8
  • Browser: Chrome Version 116.0.5845.179 (Official Build) (x86_64)

I am using the following MathJax configuration:

MathJax = {
    tex: {
        inlineMath: [
            [
                '$', '$'
            ],
            [
                '\\(', '\\)'
            ]
        ],
    },
    svg: {
        fontCache: 'global',
        displayOverflow: 'linebreak',
    },
};

and loading MathJax via

<script defer id="MathJax-script" src="https://cdn.jsdelivr.net/npm/mathjax@4.0.0-beta.3/tex-mml-svg.js" type="text/javascript"></script>

Supporting information:

Activity

changed the title [-]v4-beta.3 linebreak not respected (and other issues)[/-] [+]v4-beta.3 linebreak not respected with `\text` (and other issues)[/+] on Sep 12, 2023
pkra

pkra commented on Sep 14, 2023

@pkra
Contributor

I believe you need to load the textmacros extension to get \\ to work inside \text.

dpvc

dpvc commented on Sep 14, 2023

@dpvc
Member

I believe you need to load the textmacros extension to get \\ to work inside \text.

While true, none of the example use \\ inside \text.

dpvc

dpvc commented on Sep 14, 2023

@dpvc
Member

MathJax's rules for breaking in-line math are based on the TeX rules for in-line breaks, which are basically that breaks can occur at characters that have class BIN or REL (binary operators and relations) at the top level of the expression. Your first example has no binary or relational operator (the \dots produce characters with class INNER), so there is no valid breakpoint in that expression. In particular, the spaces inside the \text elements are not valid breakpoints in TeX; if you put this expression into actual TeX, it also will not break. So MathJax is doing what it was intended to do in this case.

Your second example, with the align environment, is not valid LaTeX markup; the error message is correct and similar to the one you get if you put this expression into actual LaTeX. The align environment is a top-level environment, and can't be placed inside other expressions. For that, you need to use the aligned environment. If you switch to that, the expression should work for you.

Your third and fourth examples that use \break are more subtle. MathJax translates your expressions into MathML internally, and there are some side-effects of the MathML that are occurring here. MathML has a concept called an embellished operator, which is intended to allow things like an equal sign with a question mark over top to be treated (for spacing and line-breaking purposes) as the operator at their core, so that the embellishments don't interfere with the spacing. An operator is embellished if it is in a container whose only other elements are "spacelike" elements (there are also some other ways to be embellished). A spacelike element is either an mspace or an mtext element (or some other more complicated things), and a container can be the expression itself. It is natural to consider mspace to be spacelike, but I've never fully understood why the specification makes mtext be spacelike. Apparently, it is because some people use mtext with space characters to perform spacing, but that seems a poor reason to make all mtext elements be spacelike.

In your expression \texttt{Maybe (Either (a, a) (Bool, a))} \break \equiv \texttt{(Maybe a, Maybe a)}, the underlying MathML is

<math xmlns="http://www.w3.org/1998/Math/MathML">
  <mtext mathvariant="monospace">Maybe (Either (a, a) (Bool, a))</mtext>
  <mspace linebreak="newline"></mspace>
  <mo>&#x2261;</mo>
  <mtext mathvariant="monospace">(Maybe a, Maybe a)</mtext>
</math>

Note that this consists of an operator (the equivalent sign) together with mtext and mspace elements, all contained in the math element container, so the mo is considered an embellished operator. That means that it, together with its embellishments (the mspace and mtext elements) are all treated as a unit. That is why the break indicated by the mspace is not being shown.

This is the same issue for your case that involves the equal sign as well. Ironically, it is also the case for the long text example at the bottom of your supporting demo page. There is one operator in that expression (the period), and the rest are text elements, so the entire sentence is an embellished operator, and treated as a single (unbreakable) unit, so no line-breaking occurs. This illustrates why I find the idea that mtext elements are to be "spacelike" to be so inappropriate.

One way around the problem is to add any non-text, non-space element into the expression. For example, adding {} to the beginning of the expression, as in

{}\texttt{Maybe (Either (a, a) (Bool, a))} \break \equiv \texttt{(Maybe a, Maybe a)}

would make the operator no longer be an embellished one, and so line breaking would occur as expected. The same goes for the long expression in your demo (or you could put the period inside one of the preceding \text{} macro, so there would be no operator at all).

Alternatively, you could adjust how MathJax interprets "spacelike" to make mtext elements spacelike only if they consist only of actual space characters, and not make mspace spacelike if it is specifying a line break. To do that, you can incorporate

MathJax = {
  startup: {
    ready() {
      const {MML} = MathJax._.core.MmlTree.MML;
      MML.mspace = class myMmlMspace extends MML.mspace {
        get isSpacelike() {
          return this.attributes.getExplicit('linebreak') === undefined && this.canBreak;
        }
      }
      MML.mtext = class myMmlMtext extends MML.mtext {
        get isSpacelike() {
          const attributes = this.attributes;
          const spaces = !!this.getText().match(/^\s*$/);
          return spaces && (attributes.getExplicit('mathbackground') === undefined &&
                            attributes.getExplicit('background') === undefined &&
                            attributes.getExplicit('style') === undefined);
        }
      }
      MathJax.startup.defaultReady();
    }
  }
};

into your MathJax configuration. Then the expression you have used should break as you would expect.

added
AcceptedIssue has been reproduced by MathJax team
on Sep 14, 2023
dpvc

dpvc commented on Sep 14, 2023

@dpvc
Member

I forgot to mention the error messages you received. That is due to having switched to CHTML output using the contextual menu. It turns out that the way exports are handled in ESM modules is causing a problem loading the output/chtml and output/svg extensions used to switch renderers. I will have a fix for that in the next beta release, but for now, you can use the contextual menu to switch back to SVG and the message should go away.

dpvc

dpvc commented on Sep 14, 2023

@dpvc
Member

Finally, it would help us if you only include one type of problem in one issue post. Your line-break issues could all be in one, but the problem with the expression involving the align environment, and the issue with the error messages in the console would be better in separate issues, as they are unrelated to the line breaking. Having a separate issue tracker for each makes it easier for us to track and resolve them independently. Thanks!

added
Code ExampleContains an illustrative code example, solution, or work-around
on Sep 14, 2023
TrebledJ

TrebledJ commented on Sep 15, 2023

@TrebledJ
Author

Thanks for the comprehensive explanation!

After some testing, placing {} at the start didn't seem to work for me, but placing it somewhere in the middle works. E.g.

\texttt{Maybe (Either (a, a) (Bool, a))} {} \break \equiv \texttt{(Maybe a, Maybe a)}

Another thing I forgot to mention was automatic linebreaking (i.e. without \break). I've put that in a different issue: #3099.

P.S. Apologies for not testing my align tex beforehand and conflating this issue. I had assumed the example would work. 🥲

dpvc

dpvc commented on Sep 15, 2023

@dpvc
Member

It shouldn't matter where the {} is, but wherever it works for you is fine.

Note that it should only matter when there is only one operator in the expression. If you have \text{...} \equiv \text{...} \equiv \text{...} it should not be needed.

added this to the v4.0 milestone on Sep 15, 2023
added 2 commits that reference this issue on Sep 15, 2023

Merge pull request #1001 from mathjax/issue3098a

b9d7b93

Merge pull request #1002 from mathjax/issue3098b

ca731d6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    AcceptedIssue has been reproduced by MathJax teamCode ExampleContains an illustrative code example, solution, or work-aroundExpected BehaviorThis is how MathJax worksv4

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @pkra@dpvc@TrebledJ

        Issue actions

          v4-beta.3 linebreak not respected with `\text` (and other issues) · Issue #3098 · mathjax/MathJax