MathJax v4.0.0-beta.2
Pre-releaseThis is the second preliminary release of version 4, which we hope to be the last beta release before the official version becomes available. We include fixes for a number of issues reported with the alpha release, and add several new features and improvements as well. A significant one is that we now provide the MathJax JavaScript files as both ES modules as well as the older CommonJS format that we have been using in the past, and these newer ES modules are compiled into ES6 rather than the older ES5 used in earlier versions. This is discussed more fully below. There is a lot of information here, but you can use the links below to jump to the points that interest you.
New Features
This beta version of MathJax introduces the following significant new features in addition to those from the v4 alpha release.
ES6 Modules
When MathJax was first released, the current version of JavaScript was ES5, so when the code base was moved to Typescript for v3, it was down-compiled to produce ES5 code. Modern browsers support ES6, which include many new features, such as true object class
creation and inheritance, proper import
and export
commands, Set
and Map
objects, promises, iterators, and many other features that make JavaScript programs faster and more reliable.
Along with new language features, ES6 introduced a new module structure that affects how individual javascript files obtain values from other files, and how they make their own definitions available to others. ES6 modules (which we will refer to as "MJS") use the new import
and export
commands to do this, while the older CommonJS module format (which we will call "CJS") used require()
and the module.exports
object to perform those functions.
MathJax v3 uses CommonJS modules with ES5 code (though this was not quite pure ES5, since one of its dependencies was actually ES6), but modern JavaScript applications are moving more and more to MJS format. Beginning with this beta version of v4, MathJax offers both MJS and CJS versions, with the MJS version being ES6, but the CJS version remaining ES5, as in past versions. The webpacked components for use in web pages are now based on the MJS versions.
Implications for MathJax in Web Pages
The webpacked MJS files are smaller than the earlier webpacked CJS files, so that should mean faster download and compile times, and the ES6 code is more efficient, so should run faster. But since this version is no longer ES5, the es5
directory that was part of the URLs for accessing MathJax from a CDN is no longer correct. The details of how the directories have been adjusted are given in the next section, but for use on the web, the only important difference introduced by the change to ES6 is that you simply remove the /es5
from the url. For example, you would use
https://cdn.jsdelivr.net/npm/[email protected]/tex-mml-chtml.js
to load the tex-mml-chtml.js
combined component.
Support for IE11 has been dropped with this version, as it does not support enough of the ES6 standards. (It is possible to webpack the CJS versions, so you can build your own ES5 version if that is necessary for you. This is described at the end of this section below.) In version 3, we recommended a link to polyfill.io
in order to support IE11. This can now be removed since this version will not work with IE11 even with the polyfill.
If your only usage is in a web browser, you can skip to the section on line breaking.
New Directory Structure
MathJax's new dual distribution of both MJS and CJS modules requires a new directory structure in the mathjax/MathJax-src
repository and its associated mathjax-full
npm package in order to accommodate both versions. In the past, the compiled JavaScript code was found in the js
directory, and the webpacked components were in the es5
directory. Now that there are both CommonJS and ES-module versions of the compiled code, these are stored in the cjs
and mjs
directories, respectively.
The webpacked components are now based on the new mjs
files, hence they are ES6 files, and so the es5
directory has been removed, with the components now being placed in the new generically named bundle
directory. That way, if there is a move to ES7 or higher, the directory name doesn't need to change again. The mathjax/MathJax
repository and associated mathjax
package have also eliminated the es5
directory, and the combined components and component directories are now at the top level of the repository. That means you can access them without the need for /es5
in the URL that was needed in v3. (See the Availability section below for more information on how to access v4.0.0-beta.2 in a browser.)
Existing node applications that use MathJax may have code that refers to mathjax-full/js
(e.g., the examples in the MathJax-demos-node repository), and mathjax-full/es5
or mathjax/es5
directories, which no longer exist. To accommodate these, this beta release includes an exports
section in its package.json
file that maps these references to the proper new locations. In particular, references to mathjax-full/es5
are routed to mathjax-full/bundle
automatically, and similarly, mathjax/es5
is routed to mathjax
. For the mathjax-full/js
directory, references will be routed to mathjax-full/mjs
or mathjax-full/cjs
depending on whether the reference is from an import
statement or a require()
call. That means that ES modules (using import
) will get the mjs
versions, while CommonJS modules (using require()
) will get the cjs
ones, and so you can continue to use mathjax-full/js
, mathjax-full/es5
and mathjax/es5
as you have in the past.
The main package.json
file now includes a "type": "module"
line so that the .js
files are considered to be MJS files automatically. The cjs
directory (and other directories that need to be marked as CJS files), contain separate package.json
files that set the type to commonjs
so that the .js
files they contain will be treated as CJS files.
Similar changes have been made to the font directories in the font packages. In particular, there are mjs
and cjs
directories, and the es5
directory has been removed. The bundled files for the fonts are now in the top-level directory, as they are in the mathjax
npm package.
Changes to components/src
The files that are used to create the webpacked component files are ES6 modules, since they use import
and export
, and in previous versions of MathJax, you needed to use node -r esm
to be able to require()
these in your own programs (you can't use require()
to load ES modules directly). Although you could load the webpacked versions of the component files in either MJS or CJS applications, the fact that the source component files are MJS modules made it difficult to use the source versions of the components in CJS applications.
Now that MathJax provides both MJS and CJS versions, we wanted to allow the source component files to be available in both forms as well. Originally, the component files were found in components/src
; with this beta version, those are now in components/mjs
, since they are ES modules.
Prior to this version, MathJax used Babel to convert these to ES5 during the webpack process, but since the webpacked versions are now ES6, that is no longer necessary, and Babel is no longer needed as a dependency for MathJax. Instead, for those who wish to use the components from source in a CommonJS node application, we use Typescript to down-compile the components/mjs
files into the components/cjs
directory as CJS modules of ES5 code.
In previous versions, require('mathjax-full')
would load components/src/node-main/node-main.js
, which would load the components from source rather than the webpacked versions. With the mathjax
package, which only includes the webpacked versions, require('mathjax')
would get es5/node-main.js
, the webpacked version. In this beta version, the two have been standardized so that they both load the webpacked version. When used with require()
, you will get bundle/node-main.cjs
, while import
will load bundle/node-main.mjs
. This is accomplished via the exports
section of the package.json
file.
In order to get the source versions in mathjax-full
, use require('mathjax-full/source').init(...)
or import {init} from 'mathjax-full/source'
and then call init(...)
. These load components/mjs/node-main/node-main.mjs
or components/cjs/node-main/node-main.cjs
, respectively.
For those who have been using components/src
to load individual components from source, we map components/src
to components/mjs
when included via an import
command, and to components/cjs
when included via require()
.
The end result is that you should always get an appropriate version for your situation, whether you are importing MathJax into an MJS application or requiring it into a CJS one.
More MJS/CJS Issues
Since MathJax now needs to produce javascript files in two different formats, we use different typescript configuration files for the different setups. These are stored in the tsconfig
directory. The MJS files are produced using tsconfig/mjs.json
and the CJS one use tsconfig/cjs.json
. Both of these call in tsconfig/common.json
to set the parameters that are common to both, and then specify the target
and module
values to be correct for the desired JavaScript version and module format. The main tsconfig.json
file simply calls in tsconfig/mjs.def
and is there as a convenience for tools that expect a tsconfig.json
file in the main directory.
In order to support both MJS and CJS versions, MathJax's dependencies also must provide both versions. The speech-rule-engine, mj-context-menu, and mhchemparser packages all now include both module formats using dual directories similar to MathJax itself. This means that the imports used by MathJax for these packages need to change depending on which module version is being created. In order to accomplish this, the references to those packages are handled using pseudo-package references that are remapped to the correct locations via the tsconfig.json
and package.json
files.
To this end, MathJax now uses the #sre
, #menu
, and #mhchem
pseudo-package names to refer to these packages. The main package.json
file uses the imports
section to map these to the actual package directories that contain their MJS JavaScript files. E.g., #mhchem/*
is mapped to mhchemparser/esm/*
, to obtain the ES module versions of the parser. Conversely, the package.json
file that is placed in the cjs
directory maps #mhchem/*
to mhchemparser/js/*
to obtain the CommonJS versions. Similar mappings are done for the other two packages.
In addition to the mappings in the package.json
file to let node (and webpack) know which directory to use, Typescript must also be told where to look for the .d.ts
files for these packages. This is accomplished through the tsconfig
json files via the paths
array.
MathJax takes its default font from one of the MathJax font packages, and that also has separate MJS and CJS directories, so the MathJax code uses a pseudo-package, #default-font
, to link to the proper mjs
or cjs
directory in the font package. This also provides a means of specifying what the default font is (mathjax-modern
by default), as changing the mappings in the package.json
files and the tsconfig
files would change the default font.
For the most part, MathJax's typescript source code can be used to produce either ES modules or CommonJS modules without alteration. But there are a few differences between MJS and CJS code that do need to be taken into account. For example, CommonJS code provides __dirname
for the location of the file being compiled, but this is not available in MJS modules; meanwhile, MJS files must use new URL(import.meta.url).pathname
to get that data, and import
is not available in CJS modules. That means there is no common method that can be used for this in both cases, and so MathJax has some module-specific files to handle the few instances where module-specific code is needed.
To accommodate this, we introduce additional pseudo-package names that can be used to select between MJS and CJS files that export the needed data using the module-specific mechanisms. The #root
and #mml3
pseudo-package names are used for these two situations in the Typescript code, and #js
and #source
are used in the components/mjs
definitions to link to the mjs
or cjs
JavaScript code and to module-specific code for obtaining the directory name. These are mapped to the proper locations in the package.json
files and the tsconfig
files. The module-specific code that these link to are stored in mjs
and cjs
directories where they are needed, so that #root/root.js
gets mapped to ts/components/mjs/root.js
when MJS files are being produced, but to ts/components/cjs/root.js
for CJS files. The tsconfig
files exclude the directories for the other format so that they are not compiled when not needed.
Finally, since modern browsers can import MJS files, it is possible to load the MathJax files into a browser directly via a <script type="module">
tag. To do so, however, you need to include a <script type="importmap">
tag that tells the browser how to find the pseudo-packages described above. Something like
<script type="importmap">
{
"imports": {
"#js/": "./node_modules/mathjax-full/mjs/",
"#source/source.cjs": "./node_modules/mathjax-full/components/mjs/source-lab.js",
"#root/": "./node_modules/mathjax-full/mjs/components/mjs/",
"#mml3/": "./node_modules/mathjax-full/mjs/input/mathml/mml3/mjs/",
"#default-font/": "./node_modules/mathjax-modern-font/mjs/",
"#sre/": "./node_modules/speech-rule-engine/js/",
"#menu/": "./node_modules/mj-context-menu/js/",
"#mhchem/": "./node_modules/mhchemparser/esm/",
"mathjax-full/components/src/a11y/util.js": "./node_modules/mathjax-full/components/src/a11y/util-lab.js",
"mathjax-full/components/src/": "./node_modules/mathjax-full/components/mjs/",
"mathjax-full/js/": "./node_modules/mathjax-full/mjs/",
"mathjax-full/": "./node_modules/mathjax-full/"
}
}
</script>
should do the trick. Then you can set up your MathJax configuration in a file mathjax-config.js
as in
import {source} from 'mathjax-full/components/src/source.js';
window.MathJax = {
loader: {
load: ['input/tex', 'output/chtml'],
source: source
}
};
and then use
<script type="module">
import './mathjax-config.js';
import 'mathjax-full/components/src/startup/startup.js';
</script>
to load MathJax components via their source code rather than webpacked files.
This is useful for testing changes to MathJax, but should not be used in production, as the number of files that will be loaded can be quite large, and each file will need to be retrieved separately, making for unneeded network overhead.
Component JSON files
In past versions of MathJax, the components/src
directory contained files that control the production of the webpacked component files in the es5
directory. Each component had a subdirectory that contained files that told the MathJax build tools how to construct the component. These included at least one .js
file that imported the needed MathJax modules and did any setup needed for the component, along with one or more of build.json
, copy.json
, and webpack.config.js
that contain the data needed for the build tools to process the component.
In this version, these three .json
files have been combined into a single config.json
file that contains sections for each of the three original ones. The build
property of config.json
contains the data that used to be in build.json
, the copy
property holds what was in copy.json
, and the webpack
property holds the data needed to pack the component.
The webpack
data primarily consists of the data that used to be passed to the PACKAGE()
function in webpack.config.js
, but as named properties, and only those that differ from the defaults need to be included (unlike the calls to PACKAGE()
where all arguments were needed). The defaults are set up so that most properties don't need to be specified, just the name of the component and the libs
array, in most cases. There are some additional properties that control whether the default font should be included in the packed file, or whether a function from an external file should be called to modify the default webpack configuration after it has been constructed. See the config.json
files in the various components/mjs
subdirectories for examples.
Building MJS and CJS versions
There are a large number of new package scripts used for building the files used by MathJax. The main changes are that there are separate commands for building the MJS and CJS files, along with new commands to make everything all in one step, and for making single components individually.
The npm run -s compile
and npm run -s make-components
scripts perform these steps for the MJS versions, and there is a new
npm run -s build
command that does both of these at once. The command
npm run -s build-all
not only compiles and packs the MJS versions, but also compiles the CJS versions.
Additional commands and details are given in the section on Changes to the Build Tools section below.
Reproducing the Old ES5 Webpack Files
The new webpacked components in the bundle
directory are based on the MJS files, which are ES6 JavaScript files. In contrast, the earlier versions of MathJax had CJS versions of ES5 code. If you need to support an ES5 environment (like IE11), it is possible to build that using
npm run -s compile-cjs
npm run -s make-cjs-components
which will create a bundle-cjs
directory that contains ES5 versions of the webpacked components, comparable to the old es5
directory.
The tsconfig.json
file has the settings for the MJS versions of the JavaScript files, and if you use an editor like emacs, the typescript editing mode automatically compiles the .ts
files based on tsconfig.json
into the mjs
directory. If you need to make modifications to the typescript files and your application links to the CJS versions of the compiled files, it may be convenient to switch the tsconfig.json
file to produce the CJS versions instead. To do that, use
npm run -s use-cjs
which will point the tsconfig.json
file to the parameters for compiling into the cjs
directory instead. When you are done,
npm run -s use-mjs
will set things back to the original arrangement.
Improvements to Line Breaking
The v4 alpha release was the first to include MathJax's new line-breaking algorithm, and while it has been received well by those who have used it, some issues did arise.
First, there were situations in which the line-breaking could lead to an internal error; these have been resolved in this beta release.
Second, the spacing at potential breakpoints for in-line math was not always correct. This turned out to be due to some browsers' minimum font size limitations, and so this beta version uses a different approach to providing that space to avoid that problem.
Third, there was an issue when using the contextual menu to switch from SVG to CHTML output that would cause unwanted breaks for in-line expressions; that has been resolved here.
Finally, the TeX \allowbreak
and related macros originally used mo
elements for inserting the potential breakpoints; but this could lead to the mo
being treated as an embellished operator, making the breakpoint appear in the wrong location. So this beta version now uses mspace
elements instead, as they can't form embellished operators.
A subtler problem occurs within tables when breaks are needed in multiple columns. By default, the baseline of a cell that contains breakpoints is the baseline of the top line of the cell, and since the default row alignment is on the cell's baseline, this means that the rows align on the top lines' baselines. In the situation where the table is from an alignment environment, such as \begin{align}...\end{align}
, if the first column requires breaks and the second has an equal sign at the beginning of it, then the equal sign appears to be after the top line of the first column, as shown below:
![bad-align](https://private-user-images.githubusercontent.com/432782/249884144-7dec68a1-6994-40b1-977a-e2be49cd9755.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkzNjcxMDksIm5iZiI6MTczOTM2NjgwOSwicGF0aCI6Ii80MzI3ODIvMjQ5ODg0MTQ0LTdkZWM2OGExLTY5OTQtNDBiMS05NzdhLWUyYmU0OWNkOTc1NS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjEyJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxMlQxMzI2NDlaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mMjE2ZWI5ZGU3MjNmZjEyZDFhNzRkOTM2YWRkNzY0YmM2ODMxYTFhZmU0YjQ5MGJmNzhhYzNmNmIzZWMxZjQwJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.R_ocAyD1im9zGBhzUgU3mewkWnVqemarHPRPWF_kWJM)
which can cause confusing results. This beta version introduces additional controls for how cells containing line breaks should be aligned, and sets the defaults for environments like align
so that the first column aligns on its bottom line while the second is on the top line, producing more effective results:
![good-align](https://private-user-images.githubusercontent.com/432782/249884193-4a6686aa-f60e-46bf-a396-acdb5966f685.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkzNjcxMDksIm5iZiI6MTczOTM2NjgwOSwicGF0aCI6Ii80MzI3ODIvMjQ5ODg0MTkzLTRhNjY4NmFhLWY2MGUtNDZiZi1hMzk2LWFjZGI1OTY2ZjY4NS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjEyJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxMlQxMzI2NDlaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1kMGU4ZmYzNTNiZDM0M2NmODI1NzEwNGE2MWRlZjMyYjRjNDU0YTU0NjljOTZhZTMyYTdmMDNiNjk0MTU0ZGNiJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.xeSGWuVcXtAOoWo3F7lQbJwJss6QcTW0P2LtI9deK0I)
In addition, it introduces a new non-standard \breakAlign
macro that can be used to set the vertical alignment for the various cells, rows, or columns in the alignment. The format is \breakAlign{type}{align}
, where type
is one of c
, r
, or t
, indicating whether the alignment is for the single cell in which it occurs, the row in which it occurs, or for the entire table, and align
is one of t
, c
, m
, b
, for top, center, middle, or bottom. The difference between c
and m
is that c
always centers the cell regardless of line breaks, while m
only centers if there are line breaks, and otherwise aligns on the cell baseline. When type
is r
or t
, then align
can be a sequence of these letters giving the alignments to use in each entry in the row, with the last one being repeated if there are more columns than letters. When type
is t
the alignments are applied as row alignments to each row in the table.
For example, \breakAlign{t}{bt}
could be used at the beginning of an alignment to make the baseline of the bottom row of the first column align with that of the top row of the second column, as in the diagram above.
The same can be accomplished in MathML input using the new data-break-align
attribute on the mtable
, mtr
, or mlabeledtr
elements, or the data-vertial-align
attribute for mtd
elements. These can have values of top
, center
, middle
, or bottom
(repeated and space-separated for tables and rows).
The data-vertical-align
attribute can be used on msqrt
, mroot
, and mrow
elements as well to adjust how they are aligned when they contain line breaks. The default for roots is bottom
, so that if line-breaks occur within a root, the root will align on its bottom line:
![root-break](https://private-user-images.githubusercontent.com/432782/249884218-de195c7d-dee9-4496-a595-6a6126f915a9.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkzNjcxMDksIm5iZiI6MTczOTM2NjgwOSwicGF0aCI6Ii80MzI3ODIvMjQ5ODg0MjE4LWRlMTk1YzdkLWRlZTktNDQ5Ni1hNTk1LTZhNjEyNmY5MTVhOS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjEyJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxMlQxMzI2NDlaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mZTJkZTUxOTdlYTZiZGZiYTBhN2RmMmNmZDg5YmNhZGFhODQ0YWFlNDI1MTYxNWY3YmIxZjkzYWI5ZTZkYjk1JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.y6NDrTPaNRHJWtNuYuTbsDvYScYTrNlfYuznEdmdwkk)
In TeX there is no direct control over this attribute within roots.
Improvements to Assistive Support
The following are the major improvements of a11y support in MathJax:
- New Korean locale for speech output.
- Explorer adaptation to support the exploration of line-broken elements.
- New text heuristics that distinguishes genuine text elements from expressions that only use text to enforce font changes to
roman
ormathvariant=normal
. - Improved speech output for tensor expressions.
- Better support of self-voicing and synchronised highlighting via automatic marking of elements in SRE's SSML renderer. This also removes the old step renderer as it is no longer necessary.
Some changes that are available in this beta release, but that are still in an
experimental stage:
- Option
aria
allows the generation of enriched expression that provide compatibility support for the ARIA tree role. - Generation of LaTeX snippets for subexpression, which are included in the MathJax data structure. This supports SRE's Euro Braille output also for sub-expressions. Note, that the Euro Braille option still needs to be set manually.
- Improvements in alphabet generation and symbol translations reduces the size of the locale files in the distribution.
Changes To SRE's Code Structure
- Updated build process to use ES modules instead of CommonJS modules. For compatibility reasons, CommonJS versions are still created, and both ES module and CommonJS sources are distributed.
- New package structure:
js
contains JavaScript files in ES module format,cjs
contains JavaScript files in CommonJS format.
- New package structure:
- XML handling in node now based on the latest
@xmldom/xmldom
library, makingxmldom-sre
obsolete. - Computation of Clearspeak moved to the MathJax code base.
Fixes
- Correctly marks all newly created elements during the enrichment process by adding an
added
attribute. - Initialization bug in tree colorer.
- Solves Firefox-related Xpath issue in tree colorer.
- Correct treatment of all
maction
elements withtoggle
attribute.
The following are fixes related to libraries used in node
:
- Security fix due to
xmldom
vulnerability. - Fixes for Xpath problems due to incomplete implementation in
xmldom-sre
.
New TeX Features
This update includes several new features for the TeX input jax, including updated Unicode positions for some macros, new macros for characters that are now available in the fonts, updates to some TeX extensions packages, new configuration parameters, and a new macro for controlling vertical alignment of blocks with line breaks. More details are given below.
The Unicode characters produced by \vdash
, \models
, and \backslash
have been adjusted to produce better results. The \iddots
, \dddot
, \ddddot
, \oiint
, \oiiint
, \ointop
, and \AA
macros have been added, as have the displaymath
, math
, and darray
environments.
The non-standard \bbFont
and \scr
macros have been removed, and the \frak
macro has been made compatible with its usual LaTeX version.
The \underline
, \llap
, \rlap
, \phantom
, \vphantom
, \hphantom
, \smash
, \mmlToken
macros have been added to the textmacros
package for use in text mode.
The \char
macro is now available for inserting characters by their Unicode character positions. It produces an internal mn
, mi
, mo
, or mtext
element depending on the character specified. E.g., \char"61
produces <mi>a</mi>
internally.
A new non-standard macro \U
is now available for inserting a Unicode character into the TeX input string to be processed as though it had been in the input stream originally. It takes on argument, which is the Unicode code point in hexadeciaml notation. For example, \U{229E}
would produce the character U+229E, a plus sign in a square. Note in particular that these macros can be used in the second argument to \mmlToken
, as in \mmlToken{mi}{\U{213C}}
.
A new non-standard macro \breakAlign
has been added to control the vertical alignment of blocks that contain line breaks. This is discussed in the previous section on line breaks.
The units
package has been added, which makes the \units
, \unitfrac
, and \nicefrac
macros available. There are new tex.units.loose
and tex.units.ugly
configuration options. Both are boolean values, and the first controls how large the space is before units (true is a large space, false a smaller one), while the second determines whether \nicefrac
produces bevelled fractions (false) or stacked fractions (true).
The configmacros
package now allows you to create active characters that are bound to macros, so that
MathJax = {
tex: {
active: {
'x': '\\mmlToken{mi}[mathvariant="bold"]{x}'
}
}
}
defined x
to always produce a boldface x.
Note that you need to take care not to cause a loop by using the character you are making active in its own definition. In the example above, since the argument to \mmlToken
is not further processed as TeX commands (except for instances of \U
), that is not the case here.
A new formatRef
configuration option has been added to the tagformat
package that allows you to specify how \eqref
is formatted. It should be a function that takes one argument, the tag associated with the specified label, and returns the string that should be used in place of the \eqref
. The default is to use the result of formatTag
, which is the string that will be used for the equation number on the equation itself. The returned string will be used as the link text for the link that targets the specified expression.
A new tex.tagAlign
configuration option is now available that specifies how tags should be vertically aligned compared to their equations. The default is to align on the baseline, but you can specify top
, center
, bottom
, baseline
, or axis
. One use case for this is when the equation is likely to have automatic line breaks inserted, in which case the baseline will be the baseline of the top line of the equation (in most cases), but you may want to have the alignment be the center of the broken equation rather than the baseline of the top line. Setting tagAlign
to center
would make sense in this case, without harming the usual placement for most equations.
A new tex.mathStyle
configuration parameter has been added to control the italicization of variables in TeX expressions, as can be done in LaTeX via the math-style document setting. This can be set to one of TeX
, ISO
, French
, or upright
. The setting affects how upper- and lower-case Latin and Greek letters are italicized. TeX
uses italics for all but upper-case Greek, whereas ISO
makes everything italic, upright
makes them all upright, and French
makes everything upright except lower-case Latin letters.
When converting TeX to MathJax's internal MathML format, the TeX input jax will put multi-letter sequences into a single mi
element when they appear inside \mathrm
, \mathbf
, and related macros. What constitutes a "letter" in this setting is now configurable via the tex.identifierPattern
configuration option, which is a regular expression that indicates what characters should be combined into one identifier. The default value is /^[a-zA-Z]+/
, but it can be extended to include other characters (e.g., numbers or accented characters) via this configuration option. Note that the pattern must begin with ^
to tie it to the beginning of the string.
Similarly, there is now a configuration option tex.ams.operatornamePattern
to specify what should be put into a single mi
within the argument to \operatorname
. Because LaTeX treats -
and *
as text characters (rather than mathematical operators) within \operatorname
, the default for this pattern is /^[-*a-zA-Z]+/
. Again, the pattern should always begin with ^
.
In the past, if an array environment had lines around the outside of the array, and there were mixed solid and dotted lines used, then MathJax might change some of them so that they are all the same style. This has been fixed in this version, so the boundary lines should now have the correct style in all cases.
Finally, the checking for proper nesting of AMS environments has been improved. This may affect existing expressions that are improperly nested but were not flagged by MathJax in the past. Previously, there was no check that these environments appeared at the top level of the expression, so an align
environment could be used inside an array
, for example; this now generates an error. On the other hand, gather
should be allowed within align
(but not another gather
), but was being flagged as erroneous nesting; this is now allowed.
See the TeX Updates section for additional bugs that have been fixed.
New Output Features
The SVG output jax has two new configuration options. The first is svg.blacker
, which is a number that indicates the stroke width (in thousandths of an em) to use for the character paths. Because some parts of some characters are very thin, the default is 3 in an attempt to help prevent those sections from disappearing at small sizes. Some page authors may wish to increase or decrease this in order to help the weight of the MathJax fonts better match the surrounding text font.
The second is svg.useXlink
, which is either true or false, and specifies whether the SVG elements should use xlink
namespaces for their href
attributes. In HTML5, the xlink
namespace is no longer necessary, but older systems may still require it, so the option is available.
In addition, the SVG output jax now groups characters that are not in the MathJax fonts into a single <text>
element. That allows combining characters to combine, so that languages and emojis that use multiple characters to form a single glyph will be handled properly. So use \text{}
around such characters to allow them to combine properly.
An improvement has been made in a long-standing issue with WebKit-based browsers, like Safari, where characters (particularly in runs of text) would not line up on the baseline properly. This is a bug in WebKit, but this version of MathJax includes a work-around that should help with the alignment in \text{}
, \mathrm{}
and similar macros, and other situations where the character are grouped into a single MathML element.
In the past, the hidden MathML that is produced by the assistive-mml
extension could be rendered by the browser larger than the math typeset by MathJax, which could interfere with the size of the container for the expression. This version includes additional CSS to resolve this problem.
There are a number of improvements to the handling of accents and stretchy characters. In particular, there was an issue with some accents in some of the fonts where they could be offset too far to the left in some browsers (due to differences in how browsers treat combining characters whose width is not set to zero); this version includes a work-around for those differences. There are also improvements to the placement of accents, as well as for the handling of italic correction for super- and subscripts when the base is in \it
or \mathit
. In the alpha version, the skew data needed for proper accent placement was missing from the mathjax-tex font; that data is now included in this version.
Finally, data for additional stretchy characters was added to all the fonts for consistency so that they all now can stretch at least the ones that were stretchable in the original MathJax TeX font. The font npm packages have been updated to new versions that contain this data.
User-Interface Updates
Several new items have been added to the Show Math As
and Copy to Clipboard
submenus of the MathJax contextual menu. These include:
SpeechText
, which is the generated speech string for the mathematical expression.SVG Image
, which is a serialized SVG object representing the expression, which can be pasted into a stand-alone image file for use elsewhere.Error Message
, which is the full error message when there is a TeX or MathML input error, or an internal MathJax error. In particular, when the TeXnoerrors
extension is used (so that error messages are not displayed within the page), this can give you the actual error message for an expression that doesn't typeset.
Note that SpeechText
is only available when the assistive tools are available (as is the case for the default combined components). Similarly, SVG Image
is only available when the SVG output jax is available (either in a configuration that loads it, or if the user changes to SVG output in the contextual menu).
There is also a new Filter semantic annotations
entry in the Math Settings
submenu that controls whether the MathML versions produced by the Show Math As
and Copy to Clipboard
menus will include the attributes that have been added by the semantic enhancement. There are a lot of these, and they can make the MathML hard to read, and generally are not necessary for use outside of MathJax, so the default is to filter these attributes, but you can uncheck that item if you want to include them in the MathML output.
API Changes
There are several API changes in this release, though most should not be breaking changes, as described below.
In the past, promise-based functions, like MathJax.typesetPromise()
, MathJax.tex2chtmlPromise()
, etc., could not be called while another one was currently in effect. That is, you needed to use the promise from one such call to tell when you could do the next call, and the documentation encouraged you to use MathJax.startup.promise
to help chain these calls together. In this release, these functions now use MathJax.startup.promise
internally to prevent more than one from running concurrently. In particular, you should no longer use MathJax.startup.promise
yourself to serialize your calls to these functions.
In earlier versions, the MathDocument's inputJax
array included any input jax that you have loaded. E.g., in the tex-mml-svg.js
combined component, it would contain entries for both the TeX and MathML input jax. Because this is an array, it was not obvious which of the two entries was which (you would need to check each entry's name
property to see if it is the one you want). In this release, the inputJax
array also includes properties that point to the input jax by name. That is, inputJax.tex
will point to the TeX input jax, if any, and similarly for inputJax.mathml
.
As mentioned above, the fact that the webpacked components are now ES6 files means that MathJax will no longer run in IE11, so there is no need to include the polyfill.io
script that was recommended in the documentation for IE11 support.
Also as mentioned earlier, the es5
directory has been removed from the MathJax distribution, so the /es5
should be removed from the URL used to access MathJax's components. Similarly, the font packages no longer need es5
in their URLs, so if you have set the output.fontPath
or chtml.fontURL
configuration options, you may need to remove the /es5
from them.
The tex.skipHtmlTags
configuration property now includes select
and option
tags, since pop-up menu items can only contain textual content, not other HTML tags.
In addition to the new configuration options discussed the other sections above, there are two additional options available in this release:
-
options.menuOptions.settings.filterSRE
, which controls whether to remove the data attributes generated by the speech-rule-engine from MathML output in the "Show Math As" and "Copy to Clipboard" menus. -
mathml.verify.checkMathvariants
, which controls whether the MathML input jax will check thatmathvariant
attribute values are valid math variants and report an error if not. Invalidmathvariant
values can cause MathJax to crash under some circumstances, so the default value of this option is true, but this may cause current expressions with invalid math variant values that used to render to now show those nodes as having errors.
The lineWidth
property of the Metrics
object, used to store information about the font metrics of the container surrounding an expression, has been removed, as the line-breaking algorithm ended up using the containerWidth
property directly. That affects functions that accept metric data as their inputs (such as MathDocument.convert()
and MathJax.tex2chtml()
), as these will no longer accept lineWidth
in the options passed to them.
Some backward-compatibility code in v3 has been removed; e.g., when the tex.multlineWidth
configuration option was moved to tex.ams.multlineWidth
in an earlier version, there was code to move the old value to the new location, but that code has been removed in v4.
Changes to the Build Tools
The tools used for creating the webpacked component files have been significantly updated for this beta release. Partly this is to accommodate the changes needed for the production of the dual MJS/CJS files, and partly in order to make it easier to do individual steps of the build process in isolation. There are now package scripts for performing most of the development tasks that you might need to do if you are modifying MathJax or building your own components.
In the past, to compile the typescript files into javascript, you would use npm run -s compile
, and to build the webpacked component files, you did npm run -s make-components
. These commands are still available, but there is a new
npm run -s build
command that does both at once.
Because we now make both MJS and CJS versions of the MathJax files, there are commands to make each type. The commands above make the MJS versions, but there are also module-specific commands that make the MJS and CJS versions separately.
npm run -s compile-cjs
npm run -s compile-mjs
npm run -s make-cjs-components
npm run -s make-mjs-components
npm run -s build-cjs
npm run -s build-mjs
The generic versions are just aliases for the MJS-specific ones. Note that because the webpacked versions use the MJS JavaScript files, the make-cjs-components
script is never run, but if you want to make ES5-based versions of the webpacked files,
npm run -s compile-cjs
npm run -s make-cjs-components
will create a bundle-cjs
directory containing the ES5 webpacked files comparable to the ones that used to be in the es5
directory.
There is also
npm run -s build-all
that does both the build-mjs
and build-cjs
actions, creating all the files in the mjs
, cjs
, bundle
and components/cjs
directories.
Because the make-components
action webpacks all the components, a time consuming process, there is a make-one
script that webpacks only one component. The format for this is
npm run -s make-one <component> <module-type>
where <component>
is the name of the directory in components/mjs
that defines the component, and <module-type>
is either mjs
or cjs
. For example
npm run -s make-one input/tex mjs
would pack only the TeX input component.
These commands all rely on the components/bin/makeAll
script, which has been enhanced for this version. It now has a number of command-line options to control its functions, including:
--no-subdirs
to prevent it from processing all the subdirectories of the given directory--cjs
to process using CJS rules--mjs
to process using MJS rules (the default)--terse
to only print the main headings rather than the file details like the files included in a webpacked version--build
to only perform the build steps (i.e., creating thelib
directories used for shared imports)--copy
to only perform the copy steps (e.g., copying the CHTML woff files into place)--pack
to only do the webpack steps--bundle-cjs
to webpack into thebundle-cjs
directory rather than thebundle
directory
These can also be passed to npm run -s -- make-one
if you want to restrict the steps performed (it already uses --no-subdirs
and one of --cjs
or --mjs
).
These changes mean you only need to use makeAll
, since it handles calling components/bin/build
, components/bin/copy
and components/bin/pack
itself. The arguments for these sub-programs have changed in this version, particularly for components/bin/pack
, so you should not call these by hand yourself unless you have looked at the internals of them carefully.
If you use a checked-out copy of this repository for your development, then there needs to be a symbolic link from node_modules/mathjax-full
to this repository directory. That should be created automatically when you do npm install
, but if you need to install other npm packages, that link will be removed by npm
, so you will need to recreate the link. To do so, you can use
npm run -s link:full
which should produce the proper link for you.
Updates and Issues Resolved
This section lists the issues that are fixed and pull requests that are included in this release. Many of these include more details about the changes in the pull request associated with the issue, so be sure to look at both.
TeX Updates
-
Properly handle italic correction for
\mathit
, and for subscripts with multi-character bases. (#961) -
Properly place super- and subscripts for stretched operators. (mathjax/MathJax#3049) (#962)
-
Make vertical spacing for horizontal stretchy characters more like TeX. (#960)
-
Handle dash during font-change in
\operatorname
. (mathjax/MathJax#3038) (#958) -
Handle multiple spaces in
\text{}
as in LaTeX. (#937) -
Properly handle arrays with dashed frame borders. (mathjax/MathJax#2972) (#932)
-
Add
nulldelimiterspace
for null delimiters. (mathjax/MathJax#985) (#391) -
Don't treat
\overrightarrow
as a mathaccent. (mathjax/MathJax#3010) (#929) -
Add a number of requested macros and environments now that we can support them:
\AA
,\iddots
,\oiint
and\oiiint
,\dddot
and\ddddot
,\ointop
, and thedarray
,math
, anddisplaymath
environments. (#923) -
Make un-delimited in-line environments possible. (#923)
-
The Unicode value for
\backslash
has been changed to U+005C. (#923) -
Implement
\char
and add\U
for raw unicode characters. (#921) -
Better checking of improperly nested AMS environments. (mathjax/MathJax#1892) (#915)
-
Add the latex
units
package. (#881) -
Make
\frak
consistent with LaTeX, and remove non-standard\scr
and\bbFont
. (mathjax/MathJax#1780) (#917) -
Add ability to define active characters as macros. (math/MathJax#2967) (#914)
-
Allow separate formatting for
\eqref{}
. (mathjax/MathJax#2736) -
Make vertical bar have the correct TeX class. (mathjax/MathJax#2938) (#907)
-
Provide an option for placement of equation numbers in TeX input. (mathjax/MathJax#2977) (#904)
-
Allow
\columncolor
in the array preamble. (mathjax/MathJax#2955) (#902) -
Allow (embellished) operators in
\underset
,\overset
, and\underoverset
to specifyaccent="true"
. (#894) -
Handle newlines as spaces in text mode. (mathjax/MathJax#2993) (#898)
-
Add
\underline
and several other macros totextmacros
package. (mathjax/MathJax#2969) (#897) -
Map
\models
to correct Unicode point, and don't use variant form for\vDash
(mathjax/MathJax#2543) (#895) -
Better handling of multiple children from
\operatorname{}
(mathjax/MathJax#2991) (#888) -
Fix parsing of vertical bar delimiters in physics package (mathjax/MathJax#2973) (#876)
-
Properly handle
\over
withinbraket
andphysics
packages. (mathjax/MathJax#3000) (#906) -
Fix infinite loop when
<tex-html>
is used more than once (mathjax/MathJax#2948) (#875) -
Fix memory leak in
textmacros
package. (mathjax/MathJax#3061) (#968) -
Handle \operatorname{} like named functions. (mathjax/MathJax#2899) (#860)
MathML Updates
-
Fix problem with MML3 extension when MathML includes
. (mathjax/MathJax#3030) (#949) -
Add checks for valid
mathvariant
attributes. (#940) -
Add a tooltip for MathML verification short errors that shows the full error. (#939)
-
Verify that
<math>
elements are not nested. (#938) -
Add
<html>
,<head>
, and<body>
tags to MathML when parsing a MathML expression as HTML. (#880)
Output Updates
-
Allow inline-breaking within top-level nodes added by SRE (#971)
-
Honor the
rule_thickness
andsurd_height
font parameters. (#948) -
Work around WebKit bug that causes baseline alignment problems. (mathjax/MathJax#2866) (#957)
-
Remove forced breaks that SVG inserted when switching to CHTML. (#956)
-
More reliable handling of stretchy assemblies. (#952)
-
Use
<mspace>
for\allowbreak
, etc., and fix issues with<mspace>
breaking. (#935) -
Move handling of overflow scrolling to CSS and allow tagged expressions to scroll. (#945)
-
Remove Safari hack that is not needed with v4. (mathjax/MathJax#3023) (#933)
-
Better control over breaking in tables, and over vertical alignment of nodes containing breaks. (#927)
-
Handle
<mrow>
with classINNER
as a unit to get spacing after it correct. (mathjax/MathJax#3018) (#930) -
Fix issue with size of spaces for potential in-line break points, and improve line spacing when a breakpoint occurs. (mathjax/MathJax#3005) (#919)
-
Combine unknown characters into a common
<text>
element in SVG output. (mathjax/MathJax#2672) (#903) -
Allow space for labels when deciding on a table's width for line breaking its columns. (#926)
-
Fix potential crash with line breaks. (mathjax/MathJax#3015) (#925)
-
Use left alignment and no indent for forced inline breaks when inline breaking is off. (mathjax/MathJax#3005) (#919)
-
Provide option to control how
<mi>
is italicized. (mathjax/MathJax#2570) (#900) -
Add option to not use
xlink
namespace in serialized SVG output. (mathjax/MathJax#2929) (#910) -
Allow SVG character
stroke-width
to be specified. (mathjax/MathJax#2859) (#909) -
Better handling of
scriptminsize
. (mathjax/MathJax#2975) (#901) -
Allow borders to inherit surrounding color in SVG. (mathjax/MathJax#2939) (#896)
-
Fix problems with size of horizontal stretchy characters in some cases. (mathjax/MathJax#2981)
-
Fix CHTML so that depth is correct for empty
<mpadded>
elements that have depth specified. (#891) -
Improve vertical separation for x-arrows (#mathjax/MathJax#2981) (#887)
-
Work around combining characters being handled as 0-width automatically by some browsers. (#885)
-
Use proper scaling factors for placement of top and bottom of
<munderover>
when the construct is scaled (mathjax/MathJax#2983) (#898) -
Update use of skew values from accents to allow better placement. (mathjax/MathJax#3051) (#966)
-
Don't remap U+0060 to U+2035 so
\grave
works properly. (#967)
User Interface Updates
-
Add
SVG Image
andSpeech Text
toShow As
andCopy As
menu items. (#942) -
Better handling of dynamic submenus in the MathJax contextual menu. (#872)
-
Fix longstanding issues with the assistive explorer, and add autovoicing. (#857)
-
Update CSS used by
assistive-mml
so its size matches that of the typeset math. (mathjax/MathJax#2936) (#920) -
Fix scaling of tooltips when text font is inherited. (mathjax/MathJax#2957) (#908)
API Updates
-
Make it easier to find a specific input jax by name. (#959)
-
Use promises when changing the renderer so that dynamic files can be loaded properly. (#950)
-
Make promise-based calls use
MathJax.startup.promise
to avoid concurrency. (#941) -
Remove
lineWidth
from the Metrics object, since it is never used. (#936) -
Remove backward-compatibility code from previous version. (#934)
-
Make sure math in multiple container elements are typeset in order. (mathjax/MathJax#2999) (#912)
-
Don't typeset within
<select>
or<option>
nodes by default. (mathjax/MathJax#3006) (#911) -
Allow
semantic-enrich
to enrich HTML-in-MML. (#890) -
Only activate explorer if in a browser. (#878)
Availability of v4.0.0-beta
The MathJax 4.0.0-beta.2 version can be accessed via CDN as
https://cdn.jsdelivr.net/npm/[email protected]/tex-mml-chtml.js
or using one of the other combined configuration files:
tex-html.js
tex-svg.js
tex-mml-chtml.js
tex-mml-svg.js
mml-html.js
mml-svg.js
Each of these includes the mathjax-modern font, but also comes in a version ending in -nofont.js
(e.g., tex-mml-chtml-nofont.js
) that does not include it, where you are expected to specify the font using the output.font
configuration option. This saves your readers from having to download the data for the mathjax-modern font that is not going to be used.
Note that the es5
directory is no longer needed in the URL when you are using [email protected]
, as all the combined configuration files are now at the top level of the mathjax
npm package that is used by CDNs to deliver MathJax.
The source code for MathJax v4 is available in the [email protected]
npm package, or in the v4.0.0-beta
branch of the MathJax-src repository on GitHub.
The fonts are each in their own npm package, e.g., mathjax-modern-font
, mathjax-stix2-font
, etc., which you can install in your own node applications as needed. In a browser, MathJax should access the fonts from cdn.jsdelivr.com
automatically. These font packages also include combined configuration files that are like tex-mml-chtml.js
and tex-mml-svg.js
, but that include that package's font rather than mathjax-modern. For example, the mathjax-stix2-font
package include tex-mml-chtml-mathjax-stix2.js
and tex-mml-svg-mathjax-stix2.js
, so you can use
https://cdn.jsdelivr.net/npm/mathjax-stix2-font/tex-mml-chtml-mathjax-stix2.js
in order to get a single-file MathJax component that includes the mathjax-stix2 font rather than mathjax-modern. In particular, you can get the equivalent of the tex-mml-html.js
file with the original MathJax TeX font all-in-one file using
https://cdn.jsdelivr.net/npm/mathjax-tex-font/tex-mml-chtml-mathjax-tex.js
This font does not have dynamic ranges (all the font data is in one file), so it should operate much the same as MathJax v3 in that respect, but it does have a more limited character coverage than the other fonts.