web/convert.rst
.. _convert-math:
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:
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:
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:
display, a boolean specifying whether the math is in
display-mode or not (for TeX input). Default is true.em, a number giving the number of pixels in an em for
the surrounding font. Default is 16.ex, a number giving the number of pixels in an ex for
the surrounding font. Default is 8.containerWidth, a number giving the width of the container,
in pixels. Default is 80 times the :attr:ex value.scale, a number giving a scaling factor to apply to the
resulting conversion. Default is 1.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:
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:
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:
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.
|-----|