.. _upgrade-v2: ####################### Upgrading from v2 to v3 ####################### MathJax v3 is a complete rewrite of MathJax from the ground up (see :ref:`whats-new-3.0`), and so its internal structure is quite different from that of version 2. That means MathJax v3 is **not** a drop-in replacement for MathJax v2, and upgrading to version 3 takes some adjustment to your web pages. The sections below describe the changes you will need to make, and the most important differences between v2 and v3. .. warning:: If you are using the ``latest.js`` feature of MathJax v2 on a CDN, note that this will **not** update to version 3 automatically, since there are significant and potentially breaking changes in version 3. There is, however, a bug in ``latest.js`` in versions 2.7.5 and below; when the current version is 3.0 or higher, ``latest.js`` will not use the highest version of 2.x, but instead will use the version from which ``latest.js`` has been taken. For example, if you load ``latest.js`` from version 2.7.3, it currently is giving you version 2.7.5 as the latest version, when version 3 is released to the CDN, your pages will revert to using version 2.7.3 again. This behavior has been corrected in version 2.7.6, so if you change to loading ``latest.js`` from version 2.7.6, you should get the latest 2.x version regardless of the presence of version 3 on the CDN. MathJax v3 is still a work in progress; not all features of version 2 have been converted to version 3 yet, and some may not be. MathJax v2 will continue to be maintained as we work to move more features into version 3, but MathJax v2 likely will not see much further development, just maintenance, once MathJax v3 is fully converted. * :ref:`v2-configuration-changes` * :ref:`v2-loading-changes` * :ref:`v2-api-changes` * :ref:`v2-jax-changes` * :ref:`v2-not-available` * :ref:`v2-not-ported` * :ref:`v2-contextual-menu-changes` * :ref:`v2-mathjax-node` * :ref:`v2-compatibility-example` ----- .. _v2-configuration-changes: Configuration Changes ===================== There are a number of changes in version 3 that affect how MathJax is configured. In version 2, there were several ways to provide configuration for MathJax; in MathJax 3, when you are using :ref:`MathJax components `, there is now only one, which is to set the :data:`MathJax` global to contain the configuration information prior to loading MathJax. In particular, you no longer call :meth:`MathJax.Hub.Config()`, and this function does not exist in MathJax v3. See the section :ref:`configuration` for more details on how to configure MathJax. In addition to requiring the use of the :data:`MathJax` global variable for setting the configuration, the organization of the configuration options have been changed to accommodate the new internal structure of MathJax, and some of their names have changed as well. To help you convert your existing version 2 configurations to version 3, we provide a `conversion tool `_ that you can use to obtain a version 3 configuration that is as close as possible to your current one. Not all configuration parameters can be converted directly, however. For some of these, it is because the version 2 features have not yet been ported to version 3, but for others, the version 2 feature may simply not exist in the new architecture of version 3. For example, MathJax v2 updates the page in phases, first removing the math source expressions (e.g., the TeX code), then inserts a preview expression (fast to create, but not as accurately laid out), and then goes back and produces high-quality typeset versions, which it inserts in chunks between page updates. MathJax version 3 does not work that way (it does not change the page until the math is entirely typeset), and so the options that control the math preview and the chunking of the equations for display simply have no counterparts in version 3. Finally, configurations that change the MathJax code via augmenting the existing MathJax objects, or that hook into MathJax's processing pipeline via :meth:`MathJax.Hub.Register.StartupHook()` or one of the other hook mechanisms will not carry over to version 3. MathJax v3 does not use the queues, signals, and callbacks that are central to version 2, so code that relies on them will have to be updated. See the :ref:`web-configuration` section for some approaches to these issues. ----- .. _v2-loading-changes: Changes in Loading MathJax ========================== Just as there are changes in how MathJax is configured, there are also changes in how MathJax is loaded. With version 2, you load ``MathJax.js`` and indicate a combined configuration file using ``?config=`` followed by the name of the configuration file. This always required at least two files to be loaded (and often more than that), and the second file was always loaded asynchronously, meaning MathJax always operated asynchronously. In version 3, there is no longer a ``MathJax.js`` file, and you load a combined component file directly. E.g., you load ``tex-chtml.js`` to get TeX with CommonHTML output. This reduces the number of files that need to be requested, and improves performance. See :ref:`loading-mathjax` for more details. Just as there is no need to use ``?config=`` in version 3, the other parameters that could be set in this way also are absent from version 3. So, for example, you can't set ``delayStartupUntil`` in the script that loads MathJax. The startup sequence operates fundamentally differently in version 3 from how it did in version 2. In version 2, MathJax would begin its startup process immediately upon MathJax being loaded, queuing action to perform configuration blocks, load extensions and jax, do the initial typesetting, and so on. It was difficult to insert your own actions into this sequence, and timing issues could occur if you didn't put your configuration in the right place. In version 3, synchronization with MathJax is done through ES6 promises, rather than MathJax's queues and signals, and MathJax's startup process is more straight-forward. You can insert your own code into the startup process more easily, and can replace the default startup actions entirely, if you wish. The actions MathJax takes during startup are better separated so that you can pick and choose the ones you want to perform. See the :ref:`startup-actions` section for more details on how to accomplish this. ----- .. _v2-api-changes: Changes in the MathJax API ========================== Because the internals have been completely redesigned, its :ref:`API ` has changed, and so if you have been calling MathJax functions, or have modified MathJax internals by augmenting the existing MathJax objects, that code will no longer work with version 3, and will have to be modified. Some of the more important changes are discussed below. * The :meth:`MathJax.Hub.Typeset()` function has been replaced by the :meth:`MathJax.typesetPromise()` and :meth:`MathJax.typeset()` functions. In fact, the :attr:`MathJax.Hub` has been removed entirely. .. * The queues, signals, and callbacks that are central to version 2 have been replaced by ES6 promises in version 3. In particular, you can use :attr:`MathJax.startup.promise` as a replacement for :meth:`MathJax.Hub.Queue()`. See the :ref:`typeset-async` section for how this is done. See the :ref:`v2-compatibility-example` below for code that may make it possible for you to use your version 2 code in version 3. .. * The :meth:`MathJax.Hub.Register.StartupHook()` and other related hooks have been replaced by ``ready()`` functions in the :ref:`loader-component` component. So code that relies on these hooks to alter MathJax need to be reworked. The :ref:`startup-actions` section shows some mechanisms that can be used for this. .. * Version 2 configurations could include an :meth:`Augment` block that could be used to add (or override) methods and data in the main MathJax objects. In version 3, this should be handled through subclassing the MathJax object classes, and passing the new classes to the objects that use them. This can be done during the `startup` component's ``ready()`` function, when the MathJax classes are available, but before any of their instances have been created. See the :ref:`startup-actions` section for some ideas on how this can be done. .. * The ``Augment`` configuration blocks and :meth:`StartupHooks()` function described above could be used in version 2 to extend MathJax's capabilities, and in particular, to extend the TeX input jax by adding new javascript-based macros. These version-2 mechanisms are not available in version 3; instead, TeX extensions are more formalized in version 3. See the :ref:`custom-component` section for an example of how this can be done. .. .. _math-script-example: * In version 2, the mathematics that is located by MathJax is removed from the page and stored in special `` This uses the ``tex-chtml.js`` combined component, so change this to whichever one you want. If your website uses the MathJax API to queue typeset calls via .. code-block:: javascript MathJax.Hub.Queue(['Typeset', MathJax.Hub]); for example, these calls will need to be converted to use the :ref:`MathJax 3 API `. You may be able to use the following code to patch into MathJax version 3, which provides implementations for :meth:`MathJax.Hub.Typeset()`, and :meth:`MathJax.Hub.Queue()`. It also flags usages of :meth:`MathJax.Hub.Register.StartupHook()` and the other hook-registering commands, and that you have converted your :meth:`MathJax.Hub.Config()` and ``x-mathjax-config`` scripts to their version 3 counterparts (use the `conversion tool `__). Add the following lines right after the ``new CommandMap()`` call in the code above: .. code-block:: javascript // // Add a replacement for MathJax.Callback command // MathJax.Callback = function (args) { if (Array.isArray(args)) { if (args.length === 1 && typeof(args[0]) === 'function') { return args[0]; } else if (typeof(args[0]) === 'string' && args[1] instanceof Object && typeof(args[1][args[0]]) === 'function') { return Function.bind.apply(args[1][args[0]], args.slice(1)); } else if (typeof(args[0]) === 'function') { return Function.bind.apply(args[0], [window].concat(args.slice(1))); } else if (typeof(args[1]) === 'function') { return Function.bind.apply(args[1], [args[0]].concat(args.slice(2))); } } else if (typeof(args) === 'function') { return args; } throw Error("Can't make callback from given data"); }; // // Add a replacement for MathJax.Hub commands // MathJax.Hub = { Queue: function () { for (var i = 0, m = arguments.length; i < m; i++) { var fn = MathJax.Callback(arguments[i]); MathJax.startup.promise = MathJax.startup.promise.then(fn); } return MathJax.startup.promise; }, Typeset: function (elements, callback) { var promise = MathJax.typesetPromise(elements); if (callback) { promise = promise.then(callback); } return promise; }, Register: { MessageHook: function () {console.log('MessageHooks are not supported in version 3')}, StartupHook: function () {console.log('StartupHooks are not supported in version 3')}, LoadHook: function () {console.log('LoadHooks are not supported in version 3')} }, Config: function () {console.log('MathJax configurations should be converted for version 3')} }; // // Warn about x-mathjax-config scripts // if (document.querySelector('script[type="text/x-mathjax-config"]')) { throw Error('x-mathjax-config scripts should be converted to MathJax global variable'); } With this you may be able to get away with using your existing version 2 code to interact with version 3. But if not, either a more sophisticated compatibility module will be needed, or better yet, convert to the new version 3 API. |-----|