diff --git a/CHANGES.rst b/CHANGES.rst index 35b73a2b0c..43b06613f8 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -86,6 +86,13 @@ Features added Patch by Philipp A. * #13468: Add config options to :mod:`sphinx.ext.duration`. Patch by Erik Bedard and Adam Turner. +* #14022: Use MathJax v4 by default in the :mod:`sphinx.ext.mathjax` extension, + from v3 previously. + To keep using an older version, set the :confval:`mathjax_path` option. + Also add the new :confval:`mathjax4_config` option to configure MathJax v4. + Note that MathJax v3 is mostly compatible with MathJax v4, so existing + :confval:`mathjax3_config` settings should not need to change. + Patch by Matthias Geier. Bugs fixed ---------- diff --git a/doc/usage/extensions/math.rst b/doc/usage/extensions/math.rst index 79ec7bbe32..f79ce23a5b 100644 --- a/doc/usage/extensions/math.rst +++ b/doc/usage/extensions/math.rst @@ -196,12 +196,15 @@ are built: .. module:: sphinx.ext.mathjax :synopsis: Render math using JavaScript via MathJax. -.. warning:: - Sphinx 4.0 changes the version of MathJax used to version 3. - You may need to override :confval:`mathjax_path` to - ``https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_HTMLorMML`` - or update your configuration options for version 3 - (see :confval:`mathjax3_config`). +.. attention:: + + The default version of MathJax changed + from version 2 to version 3 in Sphinx 4.0, and + from version 3 to version 4 in Sphinx 9.0. + + You may need to override :confval:`mathjax_path` to load an older version, + or update your :confval:`configuration options `. + In general, MathJax v3 and v4 options are compatible. .. versionadded:: 1.1 @@ -227,7 +230,7 @@ Sphinx but is set to automatically include it from a third-party site. .. confval:: mathjax_path :type: :code-py:`str` - :default: :code-py:`'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'` + :default: :code-py:`'https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-chtml.js'` The path to the JavaScript file to include in the HTML files in order to load MathJax. @@ -252,6 +255,24 @@ Sphinx but is set to automatically include it from a third-party site. You can also give a full ``https://`` URL different from the CDN URL. + .. versionchanged:: 4.0 + The default version of MathJax is now version 3. + To keep using MathJax v2, you must explicitly load it via this option. + For example: + + .. code-block:: python + + mathjax_path = 'https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_HTMLorMML' + + .. versionchanged:: 9.0 + The default version of MathJax is now version 4. + To keep using MathJax v3, you must explicitly load it via this option. + For example: + + .. code-block:: python + + mathjax_path = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js' + .. confval:: mathjax_options :type: :code-py:`dict[str, Any]` :default: :code-py:`{}` @@ -270,17 +291,38 @@ Sphinx but is set to automatically include it from a third-party site. Allow to change the loading method (async or defer) of MathJax if "async" or "defer" key is set. +.. confval:: mathjax4_config + :type: :code-py:`dict[str, Any] | None` + :default: :code-py:`None` + + The configuration options for MathJax v4 (which is used by default). + The given dictionary is assigned to the JavaScript variable + ``window.MathJax``. + For more information, please read `Configuring MathJax`__. + + __ https://docs.mathjax.org/en/stable/web/configuration.html#configuration + + + For help converting your old MathJax configuration to to the new + :confval:`mathjax4_config`, see `Converting your old Configuration to v4`__. + + __ https://docs.mathjax.org/en/stable/web/ + configuration.html#converting-your-old-configuration-to-v4 + + .. versionadded:: 9.0 + .. confval:: mathjax3_config :type: :code-py:`dict[str, Any] | None` :default: :code-py:`None` - The configuration options for MathJax v3 (which is used by default). + The configuration options for MathJax v3 (which can be loaded via + :confval:`mathjax_path`). If given, the dictionary is converted to a JSON object and assigned to the JavaScript variable ``window.MathJax``. For more information, please read `Configuring MathJax`__. - __ https://docs.mathjax.org/en/latest/web/configuration.html#configuration + __ https://docs.mathjax.org/en/v3.2/web/configuration.html#configuration .. versionadded:: 4.0 @@ -293,7 +335,7 @@ Sphinx but is set to automatically include it from a third-party site. The value is used as a parameter of ``MathJax.Hub.Config()``. For more information, please read `Using in-line configuration options`__. - __ https://docs.mathjax.org/en/v2.7-latest/ + __ https://docs.mathjax.org/en/v2.7/ configuration.html#using-in-line-configuration-options For example:: @@ -303,6 +345,12 @@ Sphinx but is set to automatically include it from a third-party site. 'jax': ['input/TeX', 'output/HTML-CSS'], } + For help converting your old MathJax configuration to to the new + :confval:`mathjax3_config`, see `Converting Your v2 Configuration to v3`__. + + __ https://docs.mathjax.org/en/v3.2/web/ + configuration.html#converting-your-v2-configuration-to-v3 + .. versionadded:: 4.0 :confval:`mathjax_config` has been renamed to :confval:`mathjax2_config`. @@ -313,12 +361,6 @@ Sphinx but is set to automatically include it from a third-party site. Former name of :confval:`mathjax2_config`. - For help converting your old MathJax configuration to to the new - :confval:`mathjax3_config`, see `Converting Your v2 Configuration to v3`__. - - __ https://docs.mathjax.org/en/latest/web/ - configuration.html#converting-your-v2-configuration-to-v3 - .. versionadded:: 1.8 .. versionchanged:: 4.0 diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py index d8d083725c..35766ddcac 100644 --- a/sphinx/ext/mathjax.py +++ b/sphinx/ext/mathjax.py @@ -28,7 +28,7 @@ if TYPE_CHECKING: # more information for mathjax secure url is here: # https://docs.mathjax.org/en/latest/web/start.html#using-mathjax-from-a-content-delivery-network-cdn -MATHJAX_URL = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js' +MATHJAX_URL = 'https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-chtml.js' logger = sphinx.util.logging.getLogger(__name__) @@ -102,7 +102,7 @@ def install_mathjax( if app.config.mathjax_path == MATHJAX_URL: logger.warning( 'mathjax_config/mathjax2_config does not work ' - 'for the current MathJax version, use mathjax3_config instead' + 'for the current MathJax version, use mathjax4_config instead' ) body = f'MathJax.Hub.Config({json.dumps(app.config.mathjax2_config)})' builder.add_js_file('', type='text/x-mathjax-config', body=body) @@ -111,6 +111,10 @@ def install_mathjax( body = f'window.MathJax = {json.dumps(app.config.mathjax3_config)}' builder.add_js_file('', body=body) + if app.config.mathjax4_config: + body = f'window.MathJax = {json.dumps(app.config.mathjax4_config)}' + builder.add_js_file('', body=body) + if app.config.mathjax_config_path: config_path = app.confdir / app.config.mathjax_config_path if not config_path.exists(): @@ -162,6 +166,9 @@ def setup(app: Sphinx) -> ExtensionMetadata: app.add_config_value( 'mathjax3_config', None, 'html', types=frozenset({dict, NoneType}) ) + app.add_config_value( + 'mathjax4_config', None, 'html', types=frozenset({dict, NoneType}) + ) app.add_config_value('mathjax_config_path', '', 'html', types=frozenset({str})) app.connect('html-page-context', install_mathjax) diff --git a/tests/test_extensions/test_ext_math.py b/tests/test_extensions/test_ext_math.py index fed7b1242b..a79f7708b9 100644 --- a/tests/test_extensions/test_ext_math.py +++ b/tests/test_extensions/test_ext_math.py @@ -17,6 +17,8 @@ from sphinx.testing.util import assert_node if TYPE_CHECKING: from sphinx.testing.util import SphinxTestApp +FAKE_MATHJAX_URL = 'https://example.org/fake-mathjax.js' + def has_binary(binary: str) -> bool: try: @@ -125,7 +127,7 @@ def test_mathjax_options(app: SphinxTestApp) -> None: shutil.rmtree(app.outdir) assert ( '' ) in content @@ -363,20 +365,38 @@ def test_math_compat(app: SphinxTestApp) -> None: ) +@pytest.mark.sphinx( + 'html', + testroot='ext-math', + confoverrides={ + 'extensions': ['sphinx.ext.mathjax'], + 'mathjax4_config': {'extensions': ['tex2jax.js']}, + }, +) +def test_mathjax4_config(app: SphinxTestApp) -> None: + app.build(force_all=True) + + content = (app.outdir / 'index.html').read_text(encoding='utf8') + assert MATHJAX_URL in content + assert '' in content + + @pytest.mark.sphinx( 'html', testroot='ext-math', confoverrides={ 'extensions': ['sphinx.ext.mathjax'], 'mathjax3_config': {'extensions': ['tex2jax.js']}, + 'mathjax_path': FAKE_MATHJAX_URL, }, ) def test_mathjax3_config(app: SphinxTestApp) -> None: app.build(force_all=True) content = (app.outdir / 'index.html').read_text(encoding='utf8') - assert MATHJAX_URL in content - assert '' in content @@ -405,13 +425,14 @@ def test_mathjax_config_path_config(app: SphinxTestApp) -> None: confoverrides={ 'extensions': ['sphinx.ext.mathjax'], 'mathjax2_config': {'extensions': ['tex2jax.js']}, + 'mathjax_path': FAKE_MATHJAX_URL, }, ) def test_mathjax2_config(app: SphinxTestApp) -> None: app.build(force_all=True) content = (app.outdir / 'index.html').read_text(encoding='utf8') - assert '