Temml Administration

Browser Support

Temml works in browsers that support MathML. This includes Chrome, Edge, Firefox, and Safari. Temml will never work in Internet Explorer.

Installation

For use in the browser, you can download a zip file of Temml from the releases page of the Temml repository. For server-side use, you can obtain Temml via CLI commands npm install temml or yarn add temml.

The minimum browser installation needs the following files. The css file and font file must be in the same folder.

A server-side installation should use temml.cjs or temml.mjs instead of temml.min.js.

Starter template

<!DOCTYPE html>
<!-- Temml requires the use of the HTML5 doctype. -->
<html>
    <head>
        ...
        <link rel="stylesheet" href="./Temml-Local.css">
        <script src="./temml.min.js"></script>
    </head>
    ...
</html>

API

Overview

Say that you have an HTMLCollection of elements whose contents should be converted from TeX strings to math. The code for such a conversion might look like this:

Option 1: Macros do not persist between calls to Temml:

// Render all the math.
for (let aSpan of [...mathSpans]) {
    const tex = aSpan.textContent;
    const displayMode = aSpan.classList.contains("display");
    temml.render(tex, aSpan, { displayMode });
}
// Optional postProcess to render \ref{}
temml.postProcess(document.body);
Option 2: Macros defined with \gdef do persist:
// Optional macros object to hold macros that persist between calls to Temml.
const macros = {}
// Render all the math.
for (let aSpan of [...mathSpans]) {
    const tex = aSpan.textContent;
    const displayMode = aSpan.classList.contains("display");
    // Notice the macros argument below.
    // It carries macros that were defined with \gdef or \global\let
    temml.render(tex, aSpan, { macros, displayMode });
}
// Optional postProcess to render \ref{}
temml.postProcess(document.body);

Notice that you can choose when to stop macro persistence by redefining macros.


Option 3: Macros persist and there are some predefined macros:

Now say that you wish to pre-define two macros and a color with document-wide scope.

// Optional preamble to pre-define macros.
const macros = temml.definePreamble(
    `\\newcommand\\d[0]{\\operatorname{d}\\!}
    \\def\\foo{x^2}
    \\definecolor{sortaGreen}{RGB}{128,128,0}`
);
// Render all the math.
for (let aSpan of [...mathSpans]) {
    const tex = aSpan.textContent;
    const displayMode = aSpan.classList.contains("display");
    temml.render(tex, aSpan, { macros, displayMode });
}
// Optional postProcess to render \ref{}
temml.postProcess(document.body);

Below, we examine the parts of that code.

In-Browser

To render math in one DOM element, call temml.render with a TeX expression and a DOM element to render into:

temml.render("c = \\pm\\sqrt{a^2 + b^2}", element);

If the element you provide is a <math> element, Temml will populate it. Otherwise, it will create a new <math> element and make it a child of the element you provide.

Server-Side

To generate MathML on the server or to generate an MathML string of the rendered math, you can use temml.renderToString:

const temml = require('./temml.cjs');  // if in Node.js
const mathML = temml.renderToString("c = \\pm\\sqrt{a^2 + b^2}");

Preamble

To give document-wide scope to a set of macros or colors, define them in a preamble.

const macros = temml.definePreamble(
    `\\newcommand\\d[0]{\\operatorname{d}\\!}
    \\def\\foo{x^2}
    \\definecolor{sortaGreen}{RGB}{128,128,0}`
);

Any valid Temml macro or \definecolor may be written into a preamble. Then include the resulting macros in the Temml options.

Options

You can provide an object of options as the last argument to temml.render and temml.renderToString. For example:

temml.render(
  "c = \\pm\\sqrt{a^2 + b^2}",
  element, 
  { displayMode: true,  macros }
);

Available options are:

Post Process

The postProcess function implements the AMS functions \ref and \label. It should be called outside of any loop.

The main Temml functions, temml.render and temml.renderToString, each operate on only one element at a time. In contrast, the postProcess function makes two passes through the entire document. If you choose not to support \ref, postProcess can be omitted.

If Temml is used server-side, \ref and \label are still implemented at runtime with client-side JavaScript. A small file, temmlPostProcess.js, is provided to be installed in place of temml.min.js. It exposes one function:

temml.postProcess(document.body)

If you do not provide a runtime postProcess, everything in Temml will work except \ref.

If you use the auto-render extension, it includes the post-processor nuances.

Fonts

Temml has several different pre-written CSS files. You should use only one and by that choice, you also choose a math font. There are several math fonts available and each has different advantages.

Latin Modern will provide the best quality rendering. It is a clone of Computer Modern and so is very home-like for readers accustomed to LaTeX documents. For best results, you must also serve a small (10kb) Temml.woff2 file. Then you’ll get support for \mathscr{…} and you’ll get primes at the correct vertical alignment in Chrome and Edge.

Temml-Local.css is the light-weight option. It calls two fonts: Cambria Math, which comes pre-installed in Windows, or STIX TWO, which comes pre-installed in iOS and MacOS (as of Safari 16). It also needs to be augmented with Temml.woff2.

Sadly, this option has rendering issues. Chrome botches extensible arrows and it will fail to stretch the symbol on Windows. Android does not currently provide a font with a MATH table, so it has many problems.

Asana and Libertinus have some of the same rendering problems as Cambria Math, although Asana does contain its own roundhand glyphs.

Fira Math is a sans-serif math font.

Several other math fonts exist and you can try them out at Frédéric Wang’s Mathematical OpenType Fonts.

Where to find font files:

If you want a different math font size, you can add a rule to your own page's CSS, like this example:

math { font-size: 125%; }

Equation numbering

In order to place automatic equation numbering in certain AMS environments, Temml contains these CSS rules:

.tml-eqn::before {
  counter-increment: tmlEqnNo;
  content: "(" counter(tmlEqnNo) ")";
}
body { counter-reset: tmlEqnNo; }

You can overwrite the content rule to produce customized equation numbers. For instance, if chapter three of your book is in its own html file, that file’s <head> could contain:

<style>
   .tml-eqn::before { content: "(3." counter(tmlEqnNo) ")"; }
</style>

Then the automatic equation numbering in that chapter would look like: (3.1)

If your site does not render automatic numbering properly, check if your other CSS has overwritten the Temml counter-reset.

Extensions

More Temml functionality can be added via the following extensions:

To install extensions for browser use, include the appropriate file from the contrib folder of the Temml repository. Then reference the file in the <head> of the HTML page. As in this mhchem example:

  <head>
    ...
    <link rel="stylesheet" href="./Temml-Local.css">
    <script src="./temml.min.js"></script>
    <script src="./mhchem.min.js"></script>
  </head>

The extension reference must come after the reference to temml.min.js.

For server-side use, just use temml.cjs or temml.mjs instead of temml.min.js. temml.cjs and temml.mjs both include mhchem, physics, and texvc.

Security

Any HTML generated by Temml should be safe from <script> or other code injection attacks.

A variety of options give finer control over the security of Temml with untrusted inputs; refer to Options for more details.

Browser Issues

If you are deciding whether to render math in MathML, know that all the major browser engines now support MathML. If you want to revel in the sight of over a thousand LaTeX functions rendered well in MathML, head on over to the Temml function support page.

The rest of you, stay here. This section identifies functions that browsers render poorly.

Item Chromium Gecko
(Firefox)
WebKit
(Safari)
Examples
Renders well on first paintbad¹E^ABCD
Accentsbad²𝖺^
Integral, ∫, in display modemeh³ab
\left( x \right)meh⁴(x)
\cancel, \bcancel, \xcancelmeh⁵meh⁵meh⁵5
Tag placementpoor⁶

x(tag)

Extensible arrowspoor⁷bad7, 8AnoteB
Radical heightmeh⁹meh⁹fc
Size 4 radicalsmeh¹⁰
Line-breakingbad¹¹
\smashbad¹²xyz

Notes:

  1. There are several items that WebKit places correctly only after a page refresh, or sometimes only after a back-button navigation.

    • accent height

    • accent italic correction

    • extensible accents

    • extensible arrows

    • height of ‖ in {Vmatrix} environment

  2. WebKit renders some accents too high even after a page refresh. Temml does some work to mitigate this. It’s not enough.

  3. Chromium does not stretch a Cambria Math ∫ in display mode. Latin Modern is okay.

  4. WebKit mis-aligns short parentheses, given a \left and \right.

  5. Because Chromium does not support <enclose>, Temml uses background images for \cancel. It may not print properly.

  6. WebKit mis-locates tags and AMS automatic equation numbers because it ignores width: 100% on an <mtable>.

  7. Chromium and WebKit system font extensible arrows have notes placed too high. Some do not stretch in Cambria Math. Again, Latin Modern is okay.

  8. WebKit fails to stretch most extensible arrows.

  9. Firefox and WebKit sometimes select radicals that are too tall. (Root cause: They don’t cramp subscripts and superscripts.)

  10. In very tall radicals, Chromium does not accurately match the vinculum to the surd.

  11. Automatic linebreaking (non-display mode) works in Chromium and Firefox. Not in WebKit.

  12. WebKit hides anything inside \smash{…}. Root cause: WebKit does not implement <mpadded> correctly.

Another issue if you are targeting mobile: Android has not provided a math system font. They are planning to add a MATH table to the Noto Sans font. I don’t think it has shipped.

You can suggest revisions to this page at the Temml issues page.


Copyright © 2021-2024 Ron Kok. Released under the MIT License