Back to Mathjax

Converting a Math String to Other Formats

web/convert.rst

latest14.3 KB
Original Source

.. _convert-math:

========================================= Converting a Math String to Other Formats

An important use case for MathJax is to convert a string containing mathematics (in one of the three forms that MathJax understands) and convert it into another form (either MathML, or one of the output formats that MathJax supports). This was difficult to do in MathJax version 2, but easy to do in current versions of MathJax.

(add something about inserting the math into the document's math list)


.. _conversion-methods:

Conversion Methods

When MathJax starts up, it creates methods for converting from the input format(s) to the output format(s) that you have loaded, and to MathML format. Based on those input and output formats, you will get the corresponding functions from the list below:

.. js:function:: MathJax.tex2chtml(math[,options]) MathJax.tex2chtmlPromise(math[,options]) MathJax.tex2svg(math[,options]) MathJax.tex2svgPromise(math[,options]) MathJax.tex2mml(math[,options]) MathJax.tex2mmlPromise(math[,options])

.. js:function:: MathJax.mathml2chtml(math[,options]) MathJax.mathml2chtmlPromise(math[,options]) MathJax.mathml2svg(math[,options]) MathJax.mathml2svgPromise(math[,options]) MathJax.mathml2mml(math[,options]) MathJax.mathml2mmlPromise(math[,options])

.. js:function:: MathJax.asciimath2chtml(math[,options]) MathJax.asciimath2chtmlPromise(math[,options]) MathJax.asciimath2svg(math[,options]) MathJax.asciimath2svgPromise(math[,options]) MathJax.asciimath2mml(math[,options]) MathJax.asciimath2mmlPromise(math[,options])

:param string math: The TeX, serialized MathML, or AsciiMath string to be converted. :param OptionList options: Described in the section below. :return: The DOM tree (for CHTML or SVG output), a serialized MathML string, or a promise that returns one of these and that is resolved when the result is ready.

For example, if you have loaded the MathML input jax and the SVG output jax (say by using the mml-svg component), then MathJax will create the methods above that involve both mathml and svg.

The functions with names containing chtml or svg produce DOM elements as the results of the conversion, with the promise version passing that to its :meth:then() function as an argument, and the non-promise versions returning them immediately. You can insert these DOM elements into the document directly, or you can use their :attr:outerHTML property to obtain their serialized string form. Note that you may need to run

.. code-block:: javascript

MathJax.startup.document.reset(); MathJax.startup.document.updateDocument();

in order to update the CSS needed for the output, especially for CHTML output.

.. warning::

If you do insert the result of a conversion function into the page, note that it will not have the MathJax contextual menu attached, and it will not become part of the list of math expressions that MathJax knows about in the page. That means that it will not be updated if a user changes menu settings that would require the math to be rerendered (e.g., if the renderer is changed, or if assistive settings like whether to use Braille output are changed). For these reasons, it is better to insert the original math string into the page and use :js:meth:MathJax.typeset() or :js:meth:MathJax.typesetPromise() to typeset the contents of the DOM element containing the math rather than convert it by hand and then inserting the result into the page.

The functions that convert to MathML produce serialized MathML strings automatically, rather than DOM elements. You can use the browser's :attr:DOMParser object to convert the string into a MathML DOM tree if you need that instead. Alternatively, you can use :js:meth:MathJax.startup.adaptor.parse() to convert the string to an HTMLdocument or XMLDocument object. For example,

.. code-block:: javascript

const mml = MathJax.tex2mml('\sqrt{x^2+1}'); const math = MathJax.startup.adaptor.parse(mml).body.firstChild;

will set math to be the <math> node containing the MathML DOM tree from the TeX expression \sqrt{x^2+1}.

The functions ending in Promise perform the conversion asynchronously, and return promises, while the others operate synchronously and return the converted form immediately.

.. warning::

In version 4, the promise-based conversion functions wait for any previously pending typeset or conversion operations to complete before performing their own conversion. The version 3 documentation recommended using and setting :js:data:MathJax.startup.promise to make sure typeset calls were serialized; if you included that code pattern in your v3 work-flow, you should remove it, as that is now being handled by the conversion functions internally.

Note that the synchronous functions only work if the math you typeset doesn't require MathJax to load any extensions or data files (e.g., TeX input that uses \require or macros that are autoloaded from an extension, or output that requires additional font data to be obtained). If a file needs to be loaded, MathJax with throw a MathJax retry error, which will prevent the conversion from completing. In that case, you should either switch to the promise-based versions of the conversion function you are using, or preload the needed component or data files. See the :ref:retry-error section for more details.

.. warning::

In MathJax v4, with the introduction of new fonts that include many more characters than the original MathJax TeX fonts did, the fonts have been broken into smaller pieces so that your readers don't have to download the entire font and its data for characters that may never be used. That means that typesetting mathematics may need to operate asynchronously even if the TeX doesn't include \require or any auto-loaded extensions, as the output itself could need extra font data files to be loaded. Thus in version 4, it is always best to use the promise-based commands.


.. _conversion-options:

Conversion Options

All of the functions listed above require an argument that is the math string to be converted (e.g., the serialized MathML string, the TeX or LaTeX string, or the AsciiMath string). Note that this is not a serialized HTML string with embedded math, but only a single math expression in one of the formats that MathJax understands. Note also that you should not include math delimiters like $$...$$ or \(...\) as part of the string; it is just the mathematics itself.

You may also pass a second argument that is an object containing options that control the conversion process. The options that can be included are:

  • :attr:display, a boolean specifying whether the math is in display-mode or not (for TeX input). Default is true.
  • :attr:em, a number giving the number of pixels in an em for the surrounding font. Default is 16.
  • :attr:ex, a number giving the number of pixels in an ex for the surrounding font. Default is 8.
  • :attr:containerWidth, a number giving the width of the container, in pixels. Default is 80 times the :attr:ex value.
  • :attr:scale, a number giving a scaling factor to apply to the resulting conversion. Default is 1.
  • :attr:family, a font family name to be used for mtext and merror elements when their fonts are set to be inherited (via the :attr:mtextInheritFont or :attr:merrorInheritFont configuration options).

For example,

.. code-block:: javascript

const html = MathJax.tex2chtml('\sqrt{x^2+1}', {em: 12, ex: 6, display: false});

would convert the TeX expression \sqrt{x^2+1} to HTML as an in-line expression, with em size being 12 pixels and ex size being 6 pixels. The result will be a DOM element containing the HTML for the expression. Similarly,

.. code-block:: javascript

const html = MathJax.tex2chtml('\sqrt{x^2+1}', {em: 12, ex: 6, display: false}); const text = html.outerHTML;

sets :data:text to be the serialized HTML string for the expression.


.. _get-metrics:

Obtaining the Output Metrics

Since the :attr:em, :attr:ex, :attr:containerWidth, and :attr:family properties all depend on the location where the math will be placed in the document (they are values based on the surrounding text font and the container element's width), MathJax provides a method for obtaining these values from a given DOM element.

.. js:function:: MathJax.getMetricsFor(node, display)

:param HTMLElement node: The DOM node that is the container for the mathematics. :param boolean display: True if the math is in display mode, false if not. :return: An object containing em, ex, containerWidth, scale, and family values for the container, together with the display value.

This takes a DOM element (node) and a boolean (display), indicating if the math is in display mode or not, and returns an object containing the options listed above. You can pass this object directly to the conversion methods discussed above. So you can do something like

.. code-block:: javascript

let node = document.querySelector('#math'); let options = MathJax.getMetricsFor(node, true); let html = MathJax.tex2svg('\sqrt{x^2+1}', options); node.appendChild(html); MathJax.startup.document.reset(); MathJax.startup.document.updateDocument();

in order to get the correct metrics for the (eventual) location of the math that is being converted. Of course, it would be easier to simply insert the TeX code into the page and use :js:meth:MathJax.typesetPromise() to typeset it, but this is just an example to show you how to obtain the metrics from a particular location in the page.

Note that obtaining the metrics causes a page refresh, so it is expensive to do this. If you need to get the metrics from many different locations, there are more efficient ways, but these are advanced topics to be dealt with elsewhere.


.. _conversion-stylesheet:

Obtaining the Output Styles

The output from the SVG and CommonHTML output jax both depend on CSS stylesheets in order to properly format their results. You can obtain the SVG stylesheet element by calling

.. js:function:: MathJax.svgStylesheet()

and the CommonHTML stylesheet from

.. js:function:: MathJax.chtmlStylesheet()

The CommonHTML output jax CSS can be quite large, so the output jax tries to minimize the stylesheet by including only the styles that are actually needed for the mathematics that has been processed by the output jax. That means you should request the stylesheet only after you have typeset the mathematics itself.

MathJax adds rules to these stylesheets dynamically, and one side-effect of this is that those styles are not part of the stylesheet element's text content, so won't be included if you call textContent or any of the other methods of obtaining the text of the stylesheet. For this reason, MathJax provides the command

.. js:function:: MathJax.startup.adaptor.cssText(stylesheet)

that will give the complete text content of a stylesheet, including the dynamically added rules.

Note that, if you typeset several expressions, the stylesheet will include everything needed for all the expressions you have typeset. If you want to reset the stylesheet, then use

.. js:function:: MathJax.startup.output.clearCache()

if the output jax is the CommonHTML output jax. So if you want to produce the style sheet for a single expression, issue the :js:meth:Mathjax.startup.output.clearCache() command just before the :js:meth:MathJax.tex2chtml() call.


.. _stand-alone-svg:

Creating Stand-Alone SVG Images

If you are using the SVG output jax to produce stand-alone SVG files, then you should set the fontCache value in the svg section of your MathJax configuration to be local or none. If set to global, then there will be a common global cache created for all the character paths used in the expressions you typeset. To clear that cache, use

.. js:function:: MathJax.startup.output.clearFontCache()

With a local font cache, the paths are stored within the SVG element itself. There will still be some dependencies on CSS, however. You can use the following to insert the needed style definitions directly into the SVG image.

.. code-block:: javascript

const svgCss = [ 'svg a{fill:blue;stroke:blue}', '[data-mml-node="merror"]>g{fill:red;stroke:red}', '[data-mml-node="merror"]>rect[data-background]{fill:yellow;stroke:none}', '[data-frame],[data-line]{stroke-width:70px;fill:none}', '.mjx-dashed{stroke-dasharray:140}', '.mjx-dotted{stroke-linecap:round;stroke-dasharray:0,140}', 'use[data-c]{stroke-width:3px}' ].join(''); const xmlDeclaration = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'; const SVGXMLNS = 'http://www.w3.org/2000/svg';

async function getSvgImage(math, options = {}) { const adaptor = MathJax.startup.adaptor; const result = await MathJax.tex2svgPromise(math, options); const svg = adaptor.tags(result, 'svg')[0]; const defs = adaptor.tags(svg, 'defs')[0] || adaptor.append(svg, adaptor.create('defs')); adaptor.append(defs, adaptor.node('style', {}, [adaptor.text(svgCss)], SVGXMLNS)); adaptor.removeAttribute(svg, 'role'); adaptor.removeAttribute(svg, 'focusable'); adaptor.removeAttribute(svg, 'aria-hidden'); const g = adaptor.tags(svg, 'g')[0]; adaptor.setAttribute(g, 'stroke', 'black'); adaptor.setAttribute(g, 'fill', 'black'); return xmlDeclaration + '\n' + adaptor.serializeXML(svg); }

This defines a function :meth:getSvgImage() that takes a math string and returns a self-contained serialized SVG image of the math.

Note that in version 4, the MathJax contextual menu also includes a SVG Image option in the Show Math As and Copy Math As submenus that you can use to obtain the SVG image directly.

|-----|