.. _v4-breaking-changes:
======================
Breaking Changes in V4
======================
A number of breaking changes have already been mentioned elsewhere:
* :ref:`v4-scoped-packages` discusses the change to scoped npm
packages, and in particular, moving from ``mathjax-full`` to
``@mathjax/src``.
* :ref:`v4-promises` discusses the greater need to use promises in v4.
* :ref:`v4-es6-modules` discusses the changes to the directory
structure and the removal of the ``/es5`` from the URLs used to
obtain MathJax from a CDN.
* :ref:`v4-tex-improvements` discusses some potentially breaking
changes for some pages, including the fact that the the
:ref:`tex-textmacros` extension is now included in all combined
components, the update to the :ref:`tex-mathtools` extension to
include the changes in the corresponding LaTeX package from 2022 and
2024, and the change from :data:`digits` to :data:`numberPattern`
for configuring the pattern used to identify a number in TeX input.
In addition to those, there are a number of other potentially breaking
changes, as described below.
.. _v4-all-packages:
Removal of AllPackages
======================
The ``AllPackages.ts`` file and the ``all-packages`` extension were
intended as a means of loading most of the TeX extensions up front so
that you did not need to worry about asynchronous loading of
extensions via the ``autoload`` package. But now that MathJax's
output is also asynchronous, using ``AllPackages`` is no longer
sufficient to allow for synchronous processing. As more extensions
have been created, they have not all been added to ``AllPackages.ts``,
and as the library of extensions, both core and third-party, grows, it
is impractical to keep all of them in one package. So in this
release, these files have been removed. For those employing MathJax
in node applications, you can use
.. code-block:: js
import {source} from '@mathjax/src/components/js/source.js';
const AllPackages = Object.keys(source).filter((name) => name.substring(0,6) === '[tex]/').sort();
to get a list of the main TeX packages. For use on the web, you could use
.. code-block:: html
to load all the extensions. Add any other configuration options that
you need to the :data:`window.MathJax` variable.
.. _v4-breaking-speech:
Changes for Speech Generation
=============================
The :ref:`v4-api-changes` section describes the separation of the
semantic enrichment from the speech generation and the introduction of
a new `speech` component. Because the speech is now generated within
a web worker or node worker thread, the speech-generation code is no
longer in the main MathJax components, but is in a separate file that
is run in the worker. That means there is no more access to speech
generation directly within MathJax (it is only available in the
worker). In particular, the ``ts/a11y/sre.ts`` file now only includes
the semantic-enrichment methods of the speech-rule engine, and
:js:meth:`Sre.toSpeech()` is no longer available. In a node
application, you can load this function directly from the
speech-rule-engine's API, however. Here is an example command-line
script that takes a TeX expression and returns its speech string using
this approach:
.. code-block:: js
//
// Load the modules needed for MathJax
//
import {mathjax} from '@mathjax/src/js/mathjax.js';
import {TeX} from '@mathjax/src/js/input/tex.js';
import {liteAdaptor} from '@mathjax/src/js/adaptors/liteAdaptor.js';
import {RegisterHTMLHandler} from '@mathjax/src/js/handlers/html.js';
import {SerializedMmlVisitor} from '@mathjax/src/js/core/MmlTree/SerializedMmlVisitor.js';
import {STATE} from '@mathjax/src/js/core/MathItem.js';
//
// Import the speech-rule-engine
//
import '@mathjax/src/components/require.mjs';
import {setupEngine, engineReady, toSpeech} from 'speech-rule-engine/js/common/system.js';
//
// Import the needed TeX packages
//
import '@mathjax/src/js/input/tex/base/BaseConfiguration.js';
import '@mathjax/src/js/input/tex/ams/AmsConfiguration.js';
import '@mathjax/src/js/input/tex/newcommand/NewcommandConfiguration.js';
import '@mathjax/src/js/input/tex/noundefined/NoUndefinedConfiguration.js';
//
// The em and ex sizes and container width to use during the conversion
//
const EM = 16; // size of an em in pixels
const EX = 8; // size of an ex in pixels
const WIDTH = 80 * EM; // width of container for linebreaking
//
// Create DOM adaptor and register it for HTML documents
//
const adaptor = liteAdaptor({fontSize: EM});
RegisterHTMLHandler(adaptor);
//
// Create input jax and a (blank) document using it
//
const tex = new TeX({
packages: ['base', 'ams', 'newcommand', 'noundefined'],
formatError(jax, err) {console.error(err.message); process.exit(1)},
//
// Other TeX configuration goes here
//
});
const html = mathjax.document('', {
InputJax: tex,
//
// Other document options go here
//
});
//
// Create a MathML serializer
//
const visitor = new SerializedMmlVisitor();
const toMathML = (node => visitor.visitTree(node, html));
//
// Convert the math from the command line
//
const mml = html.convert(process.argv[2] || '', {
display: true,
em: EM,
ex: EX,
containerWidth: WIDTH,
end: STATE.CONVERT // stop after conversion to MathML
});
//
// Set up the speech engine to use English
//
const locale = process.argv[3] || 'en';
const modality = locale === 'nemeth' || locale === 'euro' ? 'braille' : 'speech';
await setupEngine({locale, modality}).then(() => engineReady());
//
// Produce the speech for the converted MathML
//
console.log(toSpeech(toMathML(mml)));
With the speech generation being performed in a worker, the process is
now inherently asynchronous, as the communication between the main
thread and the worker thread is mediated by promises. That means that
speech generation can't be done synchronously, and you must use the
promise-based functions for handling typeset and conversion operations
that involve speech, unless you use a technique like the one above.
The speech-generation process now applies the speech attributes to the
DOM nodes themselves, rather than to the internal MathML structure (as
was done in v3), so serialized versions of the internal MathML will
not include the speech as they did in the past.
.. _v4-breaking-names:
Object and Type Name Changes
============================
Some name changes have occurred within the code to help clarify the
purpose of some objects or methods. In particular, the
:js:meth:`Loader.preLoad()` method has been renamed
:js:meth:`Loader.preLoaded()` in order to make it clear that this does
not itself load the given components, but that your code has done that
and you are telling MathJax that they have already been loaded.
Another change involves the objects used to handle CSS styles.
MathJax has two object classes that deal with CSS definitions, one
that specifies CSS styles via object literals (essentially JSON
structures), and one that parses a CSS string into an object structure
that acts like a DOM element's :attr:`style` attribute. Moreover both
modules declared a :data:`StyleList` type, and these were not
compatible. That both caused confusion and complicated their use
together in the same module, so the names for these types and objects
have been changed in this release in order to make it clearer which is
which.
To accomplish this, the ``ts/util/CssStyles.js`` file was renamed to
``ts/util/StyleJson.js``, and with that, :data:`StyleList` is changed
to :data:`StyleJson`, :data:`StyleData` to :data:`StyleJsonData`, and
:data:`CssStyles` to :data:`StyleJsonSheet`. This more accurately
describes what this object does (it is the one that takes JSON data),
and what the objects represent, while the ``ts/util/Style.ts`` file
implements (a subset of) the DOM object :attr:`style` attribute.
The move to ESM modules and compiling to ES6 rather than ES5 lead to
an issue with the webpacked versions of some component files that
would cause errors when they are loaded. The source of the problem
was due to the use of a custom :data:`Symbol` class in MathJax's TeX
input jax that conflicts with the native javascript :data:`Symbol`
object. This was not an issue in previous versions of MathJax, but
due to differences between how webpack handles CommonJS and ESM
modules, it caused problems with some TeX extension packages that use
the :data:`Symbol` class. This has lead us to rename the custom
:data:`Symbol` class to :data:`Token`, and rename the ``Symbol.ts``
and ``SymbolMap.ts`` files to ``Token.ts`` and ``TokenMap.ts``. This
is a potential breaking change to those who have created their own TeX
extension packages that load one of these files.
The names of a number of internal objects have been normalized to be
Pascal case (like camel case, but with an initial upper-case letter).
For example, the internal MathML items like ``CHTMLmath`` have been
renamed as ``ChtmlMath``. Such changes would only affect those
writing their own extensions, but for those who do, you may need to
adjust the names of classes like this.
Finally, the ``latest.js`` file has been removed, as ``jsdelivr.net``
and other CDNs handle providing the latest version automatically, and
with more granularity than this file did.
|-----|