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

Fix rendering of embedded HTML to work with scaling and mathsize changes. (mathjax/MathJax#3116) #1012

Merged
merged 5 commits into from
Dec 20, 2023

Conversation

dpvc
Copy link
Member

@dpvc dpvc commented Nov 5, 2023

This PR consolidates the handling of HTML nodes in MathML with the handling of XML nodes in generate (that are used in annotation-xml nodes). This makes the output for HTML embedded in token nodes and the legacy handling of an initial annotation-xml node in a semantics node both work the same, and allows them to share common code. The main reason to revisit this code was to make it work better when the output is scaled, either by a scaling factor in the configuration, or by a mathsize attribute. Also, when the math is being processed outside of the DOM (as in MathJax.tex2svg() or MathJax.mml2chtml() and other similar calls, and the result is inserted into a container with a different font size.

This PR should make nested HTML work in all combinations of container font-size, mathsize attributes on the MathML (including those set by \large, \small, etc.), MathJax output scaling (as set by the Scale all math contextual menu item), font-size attributes within the embedded HTML, and output renderer. It should also work in combination with the data-mjx-hdw attribute on the top-level HTML element that specifies the size of the HTML (in the em units of the HTML node itself, not the em units of the math font) in all the above combinations. That is a lot of potential interactions!

These can be tested using

\def\TEST{\begin{array}{|c|c|}\hline
<tex-html>
    <div style="background-color: red; width: 10em;">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eu erat vel est convallis feugiat eu quis massa.</div>
</tex-html>&
<tex-html><img src="https://www.mathjax.org/badge/badge-square-2.png" style="width:4em; height:8em"></tex-html>&
<tex-html> <div style="width: 50px; height: 75px; background-color:red"></div></tex-html>&
<tex-html><img src="https://www.mathjax.org/badge/badge-square-2.png" width="50" height="75"></tex-html>\\
\Rule{10em}{1em}{0em} & \Rule{4em}{1em}{0em} & \Rule{50px}{1em}{0em} & \Rule{50px}{1em}{0em}\\\hline
\end{array}}

\begin{array}{l}
\tiny\TEST\\
\TEST\\
\Large\TEST
\end{array}

This makes several tables containing examples of HTML that have em-unit dimensions (first two columns) and px-unit dimensions (last two columns). The first table uses \tiny size, the middle is normal size, and the last is \Large size. The em-dimensions should change with the size, while the px-dimensions should stay the same through all three. The tables also include black bars below that are em- and px-sized as comparisons within TeX for the HTML content. Note that the px-size stays the same in TeX as well as HTML. The em within TeX is based on the em-size of the TeX fonts (which are scaled to match the ex-height of the surrounding font), so doesn't match the em-size in the HTML exactly, but should give you a sense of expected size.

You can use the contextual menu to set the math scaling factor to larger or smaller percentages, and should see the entire table scale including the px sized content.

In order to allow the HTML content to be processed, you need to add the allowTexHTML flag to the tex block of the configuration. If you are using the v4 lab, you can enter

MathJax.config.tex.allowTexHTML = true

in the command console and then clock one of the TeX package checkboxes to get that to be processed. Otherwise, you can use a stand-alone document with that value set.


The code changes are summarized below.

The changes in semantic-enrich.ts are to allow the HTML content to be serialized as XML (in order to get end tags to be included), so that SRE can parse the result as XML without producing error messages.

In the past, there were basically two separate implementations of embedded HTML, on in the HtmlNode.ts files, and one for annotation-xml nodes when they are used as the first child of a semantics node (the legacy way of getting HTML into MathML that is not actually valid MathML, but worked in Firefox, so we retained it). In this PR, we refactor the code to use a common XmlNode as the basis for both (the HtmlNode is is a subclass of that). The output jax have a CommonXmlNode wrapper for XmlNodes and create jax-specific ChtmlXmlNode and SvgXmlNode classes that do the needed work for each output format, and ChtmlHtmlNode and SvgHtmlNode classes that are basically shells around the XmlNode implementations. This makes the HTML embedded in token nodes work the same as the HTML in annotation-xml nodes, as the same code is used for both.

So the core HtmlNode object is based off the core XmlNode object, so the changes here reflect that.

The getInitialScale() in chtml.ts is removed, since that is the default in common.ts.

The CHTML and SVG HtmlNode wrappers are now based on the XmlNode wrapper, so they now basically just inherit everything. The ChtmlXmlNode and SvgXmlNode classes are defined in the semantics.ts files, and since they now share a common XmlNode wrapper as the base, they now call the CommonXmlNodeMixin to create these jax-specific classes. That requires adding the interfaces for the instance and class objects. Most of the code is now in the common mixin, with just the toCHTML() or toSVG() and addHDW() functions handling the specifics that differ for CHTML and SVG output.

The measureXMLnode() function has been moved from common.ts to the common XmlNode wrapper mixin.

The common Wrapper object now has a new getRScale() function that gets the scale of the node relative to the top of the math tree (as opposed to the rscale property of the BBox object, which is the scale relative just to its parent node). This is needed in order to properly measure the size of the HTML content as it will be scaled in the end.

The code that used to be in the common HtmlNode wrapper has been moved to the new common XmlNode wrapper (the file was actually renamed and then edited). The measureXmlNode() code has been moved here, and modified to handle all the scaling issues, and the addHDW() function is meant to be implemented in the output jax themselves.

Finally, the SVG output jax sets the matchFontHeight value, since it is being done automatically in the width and height of the final SVG element, as they are in units of ex, so match the surrounding text automatically.

Resolves issue mathjax/MathJax#3116

@dpvc dpvc requested a review from zorkow November 5, 2023 16:23
@dpvc dpvc added this to the v4.0 milestone Nov 5, 2023
Copy link
Member

@zorkow zorkow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wondering if the XmlNode and CommonXmlNode classes should not be abstract classes with some of their methods abstract (e.g., addHDW) as they should not have any instances of their own anyway.

ts/output/common/Wrappers/XmlNode.ts Show resolved Hide resolved
@dpvc dpvc merged commit df55d8b into develop Dec 20, 2023
@dpvc dpvc deleted the issue3116 branch December 20, 2023 22:03
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.

2 participants