emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: "Rudolf Adamkovič" <salutis@me.com>
To: Ihor Radchenko <yantar92@posteo.net>
Cc: Ihor Radchenko <yantar92@gmail.com>, emacs-orgmode@gnu.org
Subject: Re: [PATCH] Re: Update Org to MathJax 3
Date: Thu, 10 Nov 2022 00:01:51 +0100	[thread overview]
Message-ID: <m2pmdvlokg.fsf@me.com> (raw)
In-Reply-To: <87zgd0adod.fsf@localhost>

[-- Attachment #1: Type: text/plain, Size: 2711 bytes --]

Ihor Radchenko <yantar92@posteo.net> writes:

> Is it really recommended by mathjax?

Yes.

> I cannot find any mention of jsdelivr.com.

1. Open MathJax docs (https://docs.mathjax.org/en/latest/).
2. Type "jsDelivr" into the search box.
3. Check the search results.

> You may update the URL to something more precise.

Fixed.

> Are these extensions no longer supported?

MathJax 3+ supports extensions, and one can load them in multiple ways.
See [1].  It deserves some thinking, for the extensions mirror LaTeX
extensions.  So, to make both HTML and PDF work, one has:

  Use the Physics package in both LaTeX and MathJax.

  #+latex_header: \usepackage{physics}
  
  #+html_head_extra: <div style="display: none">
  #+html_head_extra:   \(
  #+html_head_extra:     \require{physics}
  #+html_head_extra:   \)
  #+html_head_extra: </div>

(The example taken from my Org notebook.)

[1]: https://docs.mathjax.org/en/latest/input/tex/extensions.html

That said, I do not currently have bandwidth to extend the scope of the
patch to include MathJax extensions.  (Note that they have never worked
anyway, so the user loses nothing, and we correct documentation.)

A slight digression, just FYI:

I realized that I should have improved LaTeX to SVG exports instead of
focusing on MathJax.  Org supports LaTeX environments, but outside of
PDFs, it does so poorly.  Packages such as TikZ, for example, do not
work out of the box, so people use Babel to hack around it.  Worse
still, Org does not even properly adjust baselines for inline math, so
HTML exports remain barely usable for any mathematical work.

If we fix LaTeX, Org could have fast and good mathematics, with no
JavaScript, like Wikipedia has.  Then, we could use it by default,
instead of MathJax.

Having good support for LaTeX would position Org as the king of markup
editors, because LaTeX can do everything under the sun.  For instance,
one can typeset a chess game in a couple of lines.  Or sheet music.  Or
molecules in three dimensions.  No mainstream Markdown editor or web
authoring tool can do that.  Yet, Org can *almost* do it.

> It would be more compact to use `(...) notation.

Fixed.

> nreverse will be more memory-efficient.

Fixed and TIL.

> Mostly because supporting MathJax 2 is an extra maintenance burden.  I
> do not see much point catering bugs of MathJax2 -> MathJax3
> conversion. If users want to use MathJax2 specifically, they should be
> able to customize Org to use MathJax2. If they want MathJax3, they
> need to fix the options. Relying on auto-conversion is calling for
> trouble.

Fixed.

Please see the 6th version of the patch, attached below.

P.S. I also replaced two subsequent `setq' calls with one.

Rudy

[-- Attachment #2: 0001-ox-html-Update-from-MathJax-2-to-MathJax-3.patch --]
[-- Type: text/x-patch, Size: 50720 bytes --]

From 5009350869879cce6f083a9b38961b95f1c51f58 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rudolf=20Adamkovi=C4=8D?= <salutis@me.com>
Date: Fri, 7 Oct 2022 15:03:48 +0200
Subject: [PATCH] ox-html: Update from MathJax 2 to MathJax 3+

* lisp/ox-html.el (
org-html-mathjax-options,
org-html-mathjax-template,
org-html--build-mathjax-config
): Update from MathJax 2 to 3 while maintaining compatibility.  All
legacy options should continue to work, except for the 'path' option
which must now point to MathJax 3 or later.
* testing/lisp/test-ox-html.el (
ox-html/mathjax-path-none,
ox-html/mathjax-path-default,
ox-html/mathjax-path-custom,
ox-html/mathjax-path-in-buffer,
ox-html/mathjax-options-default,
ox-html/mathjax-options-custom,
ox-html/mathjax-options-in-buffer,
ox-html/mathjax-legacy-scale-default,
ox-html/mathjax-legacy-scale-custom,
ox-html/mathjax-legacy-scale-in-buffer,
ox-html/mathjax-legacy-scale-message,
ox-html/mathjax-legacy-scale-message-in-buffer,
ox-html/mathjax-legacy-scale-ignore,
ox-html/mathjax-legacy-autonumber-ams,
ox-html/mathjax-legacy-autonumber-ams-in-buffer,
ox-html/mathjax-legacy-autonumber-none,
ox-html/mathjax-legacy-autonumber-none-in-buffer,
ox-html/mathjax-legacy-autonumber-all,
ox-html/mathjax-legacy-autonumber-all-in-buffer,
ox-html/mathjax-legacy-autonumber-message,
ox-html/mathjax-legacy-autonumber-message-in-buffer,
ox-html/mathjax-legacy-font-tex,
ox-html/mathjax-legacy-font-tex-in-buffer,
ox-html/mathjax-legacy-font-stix-web,
ox-html/mathjax-legacy-font-stix-web-in-buffer,
ox-html/mathjax-legacy-font-asana-math,
ox-html/mathjax-legacy-font-asana-math-in-buffer,
ox-html/mathjax-legacy-font-neo-euler,
ox-html/mathjax-legacy-font-neo-euler-in-buffer,
ox-html/mathjax-legacy-font-gyre-pagella,
ox-html/mathjax-legacy-font-gyre-pagella-in-buffer,
ox-html/mathjax-legacy-font-gyre-termes,
ox-html/mathjax-legacy-font-gyre-termes-in-buffer,
ox-html/mathjax-legacy-font-latin-modern,
ox-html/mathjax-legacy-font-latin-modern-in-buffer,
ox-html/mathjax-legacy-line-breaks-true,
ox-html/mathjax-legacy-line-breaks-true-in-buffer,
ox-html/mathjax-legacy-line-breaks-false,
ox-html/mathjax-legacy-line-breaks-false-in-buffer,
ox-html/mathjax-legacy-line-breaks-message,
ox-html/mathjax-legacy-line-breaks-message-in-buffer): Test MathJax in
general and also the conversion of legacy options from MathJax 2 to 3.
* testing/org-test.el (org-test-capture-messages): Add a new macro
useful for testing the messages put in the echo area.
* etc/ORG-NEWS: Document MathJax 2 to 3 upgrade, highlighting the
benefits of the new version but also mentioning the fact that the user
may need to update the `path' option in `org-html-mathjax-options'.
* doc/org-manual.org (Math formatting in HTML export): Update the link
to the MathJax CDN and the example of how to use `+HTML_MATHJAX' with
MathJax 3.  Also, remove the note on MathJax extensions, as they did
not work (and do not work) as documented.

Link: https://list.orgmode.org/orgmode/m2a667n4ax.fsf@me.com/
---
 doc/org-manual.org           |  20 +-
 etc/ORG-NEWS                 |  32 ++
 lisp/ox-html.el              | 242 ++++++++---
 testing/lisp/test-ox-html.el | 785 +++++++++++++++++++++++++++++++++++
 testing/org-test.el          |  11 +
 5 files changed, 1012 insertions(+), 78 deletions(-)
 create mode 100644 testing/lisp/test-ox-html.el

diff --git a/doc/org-manual.org b/doc/org-manual.org
index dc2fc57cd..3514f84e4 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -13228,24 +13228,20 @@ as-is.
 LaTeX math snippets (see [[*LaTeX fragments]]) can be displayed in two
 different ways on HTML pages.  The default is to use the
 [[https://www.mathjax.org][MathJax]], which should work out of the box
-with Org[fn:: By default Org loads MathJax from
-[[https://cdnjs.com][cdnjs.com]] as recommended by
-[[https://www.mathjax.org][MathJax]].][fn:46].  Some MathJax display
-options can be configured via ~org-html-mathjax-options~, or in the
-buffer.  For example, with the following settings,
+with Org[fn:: By default, Org loads MathJax from
+[[https://www.jsdelivr.com/][jsDelivr]], as recommended in
+[[https://docs.mathjax.org/en/latest/web/start.html][Getting Started
+with MathJax Components]].][fn:46].  Some MathJax display options can
+be configured via ~org-html-mathjax-options~, or in the buffer.  For
+example, with the following settings,
 
 #+begin_example
-,#+HTML_MATHJAX: align: left indent: 5em tagside: left font: Neo-Euler
-,#+HTML_MATHJAX: cancel.js noErrors.js
+,#+HTML_MATHJAX: align: left indent: 5em tagside: left
 #+end_example
 
 #+texinfo: @noindent
 equation labels are displayed on the left margin and equations are
-five em from the left margin.  In addition, it loads the two MathJax
-extensions =cancel.js= and =noErrors.js=[fn:: See
-[[https://docs.mathjax.org/en/latest/input/tex/extensions.html#tex-and-latex-extensions][TeX
-and LaTeX extensions]] in the [[https://docs.mathjax.org][MathJax
-manual]] to learn about extensions.].
+five em from the left margin.
 
 #+vindex: org-html-mathjax-template
 See the docstring of ~org-html-mathjax-options~ for all supported
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index b542da34b..f063c80d2 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -139,6 +139,38 @@ rely on the details of visibility state implementation in
 backend.  From now on, using =outline-*= functions is strongly
 discouraged when working with Org files.
 
+*** HTML export uses MathJax 3+ instead of MathJax 2
+
+Org now uses MathJax 3 by default instead of MathJax 2.  During HTML
+exports, Org automatically converts all legacy MathJax 2 options to
+the corresponding MathJax 3+ options, except for the ~path~ in
+~org-html-mathjax-options~ which must now point to a file containing
+MathJax version 3 or later.
+
+Further, if you need to use a non-default ~font~ or ~linebreaks~ (now
+~overflow~), then the ~path~ must point to MathJax 4 or later.
+
+See the updated ~org-html-mathjax-options~ for more details.
+
+Org 9.6 uses MathJax 3, a ground-up rewrite of MathJax 2 released
+in 2019.  The new version brings modularity, better and faster
+rendering, improved LaTeX support, and more.
+
+For more information about new features, see:
+
+https://docs.mathjax.org/en/latest/upgrading/whats-new-3.0.html
+https://docs.mathjax.org/en/latest/upgrading/whats-new-3.1.html
+https://docs.mathjax.org/en/latest/upgrading/whats-new-3.2.html
+
+For instance, one can typeset calculus with the built-in ~physics~
+package or chemistry with the built-in ~mhchem~ package, like in
+LaTeX.
+
+Please note that MathJax 3 changed the default JavaScript content
+delivery network (CDN) provider from CloudFlare to jsDelivr.  You can
+find the new terms of service, including the privacy policy, at
+https://www.jsdelivr.com/terms.
+
 ** New features
 *** Clock table can now produce quarterly reports
 
diff --git a/lisp/ox-html.el b/lisp/ox-html.el
index cad06aebf..09a57bf11 100644
--- a/lisp/ox-html.el
+++ b/lisp/ox-html.el
@@ -1166,72 +1166,116 @@ See `format-time-string' for more information on its components."
 ;;;; Template :: Mathjax
 
 (defcustom org-html-mathjax-options
-  '((path "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_HTML" )
-    (scale "100")
+  '((path "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js")
+    (scale 1.0)
     (align "center")
-    (font "TeX")
-    (linebreaks "false")
-    (autonumber "AMS")
+    (font "mathjax-modern")
+    (overflow "overflow")
+    (tags "ams")
     (indent "0em")
     (multlinewidth "85%")
     (tagindent ".8em")
     (tagside "right"))
   "Options for MathJax setup.
 
-Alist of the following elements.  All values are strings.
+Alist of the following elements.
 
-path          The path to MathJax.
+path          The path to MathJax version 3 or later.
 scale         Scaling with HTML-CSS, MathML and SVG output engines.
 align         How to align display math: left, center, or right.
-font          The font to use with HTML-CSS and SVG output.  As of MathJax 2.5
-              the following values are understood: \"TeX\", \"STIX-Web\",
-              \"Asana-Math\", \"Neo-Euler\", \"Gyre-Pagella\",
-              \"Gyre-Termes\", and \"Latin-Modern\".
+font          The font to use with HTML-CSS and SVG output.  Needs
+              MathJax version 4+.  MathJax 4 provides 11 fonts:
+              \"mathjax-modern\"   Latin-Modern font, default in MathJax 4+
+              \"mathjax-asana\"    Asana-Math font
+              \"mathjax-bonum\"    Gyre Bonum font
+              \"mathjax-dejavu\"   Gyre DejaVu font
+              \"mathjax-pagella\"  Gyre Pagella font
+              \"mathjax-schola\"   Gyre Schola font
+              \"mathjax-termes\"   Gyre Termes font
+              \"mathjax-stix2\"    STIX2 font
+              \"mathjax-fira\"     Fira and Fira-Math fonts
+              \"mathjax-euler\"    Neo Euler font that extends Latin-Modern
+              \"mathjax-tex\"      The original MathJax TeX font
+overflow      How to break displayed equations when too large. Needs
+              MathJax 4 or newer.  Supported options include
+              \"overflow\", \"scale\", \"scroll\", \"truncate\",
+              \"linebreak\", and \"elide\".
 linebreaks    Let MathJax perform automatic linebreaks.  Valid values
               are \"true\" and \"false\".
 indent        If align is not center, how far from the left/right side?  For
               example, \"1em\".
 multlinewidth The width of the multline environment.
-autonumber    How to number equations.  Valid values are \"none\",
-              \"all\" and \"AMS\".
+tags          How to number equations.  Valid values are \"none\",
+              \"all\" and \"ams\".
 tagindent     The amount tags are indented.
 tagside       Which side to show tags/labels on.  Valid values are
               \"left\" and \"right\"
 
-You can also customize this for each buffer, using something like
+You can also customize this for some buffer, using something like
 
-#+HTML_MATHJAX: align: left indent: 5em tagside: left font: Neo-Euler
+#+HTML_MATHJAX: align: left indent: 5em tagside: left
 
 For further information about MathJax options, see the MathJax documentation:
 
-  https://docs.mathjax.org/"
+  https://docs.mathjax.org/
+
+To maintain compatibility with pre-9.6 Org that used MathJax 2,
+the following conversions take place.
+
+The legacy \"autonumber\" option, with the value \"AMS\",
+\"None\", or \"All\", becomes the \"tags\" option set to the
+value \"ams\", \"none\", or \"all\", respectively.
+
+Any legacy values of the \"scale\" option, specified as
+percentage strings, become converted to unit-interval numbers.
+For example, a legacy scale of \"150\" becomes a scale of 1.5.
+
+The legacy \"linebreaks\" option, with the value \"true\" or
+\"false\", becomes the \"overflow\" option set to the value
+\"linebreak\" or \"overflow\", respectively.
+
+The legacy values of the \"font\" option, namely \"TeX\",
+\"STIX-Web\", \"Asana-Math\", \"Neo-Euler\", \"Gyre-Pagella\",
+\"Gyre-Termes\", \"Latin-Modern\", become converted to the
+corresponding MathJax 4+ font names.
+
+Legacy options and values always take precedence.
+"
   :group 'org-export-html
-  :package-version '(Org . "8.3")
+  :package-version '(Org . "9.6")
   :type '(list :greedy t
 	       (list :tag "path   (the path from where to load MathJax.js)"
 		     (const :format "       " path) (string))
 	       (list :tag "scale  (scaling for the displayed math)"
-		     (const :format "       " scale) (string))
+		     (const :format "   " scale) (float))
 	       (list :tag "align  (alignment of displayed equations)"
 		     (const :format "       " align) (string))
-	       (list :tag "font (used to display math)"
-		     (const :format "            " font)
-		     (choice (const "TeX")
-			     (const "STIX-Web")
-			     (const "Asana-Math")
-			     (const "Neo-Euler")
-			     (const "Gyre-Pagella")
-			     (const "Gyre-Termes")
-			     (const "Latin-Modern")))
-	       (list :tag "linebreaks (automatic line-breaking)"
-		     (const :format "      " linebreaks)
-		     (choice (const "true")
-			     (const "false")))
-	       (list :tag "autonumber (when should equations be numbered)"
-		     (const :format "      " autonumber)
-		     (choice (const "AMS")
-			     (const "None")
-			     (const "All")))
+               (list :tag "font (used to typeset math)"
+		     (const :format "               " font)
+                     (choice (const "mathjax-modern")
+                             (const "mathjax-asana")
+                             (const "mathjax-bonum")
+                             (const "mathjax-dejavu")
+                             (const "mathjax-pagella")
+                             (const "mathjax-schola")
+                             (const "mathjax-termes")
+                             (const "mathjax-stix2")
+                             (const "mathjax-fira")
+                             (const "mathjax-euler")
+                             (const "mathjax-tex")))
+               (list :tag "overflow (how to break displayed math)"
+		     (const :format "         " overflow)
+                     (choice (const "overflow")
+                             (const "scale")
+                             (const "scroll")
+                             (const "truncate")
+                             (const "linebreak")
+                             (const "elide")))
+	       (list :tag "tags (whether equations are numbered and how)"
+		     (const :format "    " tags)
+		     (choice (const "ams")
+			     (const "none")
+			     (const "all")))
 	       (list :tag "indent (indentation with left or right alignment)"
 		     (const :format "       " indent) (string))
 	       (list :tag "multlinewidth (width to use for the multline environment)"
@@ -1244,27 +1288,38 @@ For further information about MathJax options, see the MathJax documentation:
 			     (const "right")))))
 
 (defcustom org-html-mathjax-template
-  "<script type=\"text/x-mathjax-config\">
-    MathJax.Hub.Config({
-        displayAlign: \"%ALIGN\",
-        displayIndent: \"%INDENT\",
-
-        \"HTML-CSS\": { scale: %SCALE,
-                        linebreaks: { automatic: \"%LINEBREAKS\" },
-                        webFont: \"%FONT\"
-                       },
-        SVG: {scale: %SCALE,
-              linebreaks: { automatic: \"%LINEBREAKS\" },
-              font: \"%FONT\"},
-        NativeMML: {scale: %SCALE},
-        TeX: { equationNumbers: {autoNumber: \"%AUTONUMBER\"},
-               MultLineWidth: \"%MULTLINEWIDTH\",
-               TagSide: \"%TAGSIDE\",
-               TagIndent: \"%TAGINDENT\"
-             }
-});
+  "<script>
+  window.MathJax = {
+    tex: {
+      ams: {
+        multlineWidth: '%MULTLINEWIDTH'
+      },
+      tags: '%TAGS',
+      tagSide: '%TAGSIDE',
+      tagIndent: '%TAGINDENT'
+    },
+    chtml: {
+      scale: %SCALE,
+      displayAlign: '%ALIGN',
+      displayIndent: '%INDENT'
+    },
+    svg: {
+      scale: %SCALE,
+      displayAlign: '%ALIGN',
+      displayIndent: '%INDENT'
+    },
+    output: {
+      font: '%FONT',
+      displayOverflow: '%OVERFLOW'
+    }
+  };
 </script>
-<script src=\"%PATH\"></script>"
+
+<script
+  id=\"MathJax-script\"
+  async
+  src=\"%PATH\">
+</script>"
   "The MathJax template.  See also `org-html-mathjax-options'."
   :group 'org-export-html
   :type 'string)
@@ -1948,18 +2003,73 @@ INFO is a plist used as a communication channel."
 	     (org-element-map (plist-get info :parse-tree)
 		 '(latex-fragment latex-environment) #'identity info t nil t))
     (let ((template (plist-get info :html-mathjax-template))
-	  (options (plist-get info :html-mathjax-options))
+	  (options (let ((options (plist-get info :html-mathjax-options)))
+                     ;; If the user customized some legacy option, set
+                     ;; the corresponding new option to nil, so that
+                     ;; the legacy user choice overrides the default.
+                     ;; Otherwise, the user did not set the legacy
+                     ;; option, in which case still set the legacy
+                     ;; option but to no value, so that the code can
+                     ;; find its in-buffer value, if set.
+                     (append `((,(if (plist-member options 'autonumber)
+                                     'tags 'autonumber)
+                                nil)
+                               (,(if (plist-member options 'linebreaks)
+                                     'overflow 'linebreaks)
+                                nil))
+                             options)))
 	  (in-buffer (or (plist-get info :html-mathjax) "")))
       (dolist (e options (org-element-normalize-string template))
-	(let ((name (car e))
-	      (val (nth 1 e)))
-	  (when (string-match (concat "\\<" (symbol-name name) ":") in-buffer)
-	    (setq val
-		  (car (read-from-string (substring in-buffer (match-end 0))))))
-	  (unless (stringp val) (setq val (format "%s" val)))
-	  (while (string-match (concat "%" (upcase (symbol-name name)))
-			       template)
-	    (setq template (replace-match val t t template))))))))
+	(let ((symbol (car e))
+	      (value (nth 1 e)))
+          (when (string-match (concat "\\<" (symbol-name symbol) ":")
+                              in-buffer)
+            (setq value
+                  (car (split-string (substring in-buffer
+                                                (match-end 0))))))
+          (when value
+            (pcase symbol
+              (`font
+               (when-let
+                   ((new-value
+                     (pcase value
+                       ("TeX" "mathjax-tex")
+                       ("STIX-Web" "mathjax-stix2")
+                       ("Asana-Math" "mathjax-asana")
+                       ("Neo-Euler" "mathjax-euler")
+                       ("Gyre-Pagella" "mathjax-pagella")
+                       ("Gyre-Termes" "mathjax-termes")
+                       ("Latin-Modern" "mathjax-modern"))))
+                 (setq value new-value)))
+              (`linebreaks
+               (org-display-warning
+                "Converting legacy MathJax option: linebreaks")
+               (setq symbol 'overflow
+                     value (if (string= value "true")
+                               "linebreak"
+                             "overflow")))
+              (`scale
+               (when (stringp value)
+                 (setq value (string-to-number value)))
+               (when (>= value 10)
+                 (let ((new-value (/ (float value) 100)))
+                   (org-display-warning
+                    (format "Converting legacy MathJax scale: %s to %s"
+                            value
+                            new-value))
+                   (setq value new-value))))
+              (`autonumber
+               (org-display-warning
+                "Converting legacy MathJax option: autonumber")
+               (setq symbol 'tags
+                     value (downcase value))))
+            (while (string-match (format "\\(%%%s\\)[^A-Z]"
+                                         (upcase (symbol-name symbol)))
+                                 template)
+              (setq template
+                    (replace-match (format "%s" value)
+                                   t
+                                   t template 1)))))))))
 
 (defun org-html-format-spec (info)
   "Return format specification for preamble and postamble.
diff --git a/testing/lisp/test-ox-html.el b/testing/lisp/test-ox-html.el
new file mode 100644
index 000000000..7cf8b3afb
--- /dev/null
+++ b/testing/lisp/test-ox-html.el
@@ -0,0 +1,785 @@
+;;; test-ox-html.el --- Tests for ox-html.el
+
+;; Copyright (C) 2022  Rudolf Adamkovič
+
+;; Author: Rudolf Adamkovič <salutis@me.com>
+
+;; This file is part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ox-html)
+
+\f
+;;; Loading MathJax
+
+(ert-deftest ox-html/mathjax-path-none ()
+  "Test that MathJax does not load when not needed."
+  (should-not
+   (org-test-with-temp-text "No LaTeX here."
+     (let ((export-buffer "*Test HTML Export*")
+           (org-export-show-temporary-export-buffer nil))
+       (org-export-to-buffer 'html export-buffer
+         nil nil nil nil nil
+         #'html-mode)
+       (with-current-buffer export-buffer
+         (let ((case-fold-search t))
+           (search-forward "MathJax" nil t)))))))
+
+(ert-deftest ox-html/mathjax-path-default ()
+  "Test the default path from which MathJax loads."
+  (should
+   (= 1 (org-test-with-temp-text "$x$"
+          (let ((export-buffer "*Test HTML Export*")
+                (org-export-show-temporary-export-buffer nil))
+            (org-export-to-buffer 'html export-buffer
+              nil nil nil nil nil
+              #'html-mode)
+            (with-current-buffer export-buffer
+              (how-many (rx "<script
+  id=\"MathJax-script\"
+  async
+  src=\"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js\">
+</script>"))))))))
+
+(ert-deftest ox-html/mathjax-path-custom ()
+  "Test a customized path from which MathJax loads."
+  (should
+   (= 1 (org-test-with-temp-text "$x$"
+          (let ((export-buffer "*Test HTML Export*")
+                (org-export-show-temporary-export-buffer nil)
+                (org-html-mathjax-options
+                 '((path "./mathjax/es5/tex-mml-chtml.js"))))
+            (org-export-to-buffer 'html export-buffer
+              nil nil nil nil nil
+              #'html-mode)
+            (with-current-buffer export-buffer
+              (how-many (rx "<script
+  id=\"MathJax-script\"
+  async
+  src=\"./mathjax/es5/tex-mml-chtml.js\">
+</script>"))))))))
+
+(ert-deftest ox-html/mathjax-path-in-buffer ()
+  "Test a in-buffer customized path from which MathJax loads."
+  (should
+   (= 1 (org-test-with-temp-text "
+#+HTML_MATHJAX: path: ./mathjax/es5/tex-mml-chtml.js
+$x$"
+          (let ((export-buffer "*Test HTML Export*")
+                (org-export-show-temporary-export-buffer nil))
+            (org-export-to-buffer 'html export-buffer
+              nil nil nil nil nil
+              #'html-mode)
+            (with-current-buffer export-buffer
+              (how-many (rx "<script
+  id=\"MathJax-script\"
+  async
+  src=\"./mathjax/es5/tex-mml-chtml.js\">
+</script>"))))))))
+
+\f
+;;; Configuring MathJax with options
+
+(ert-deftest ox-html/mathjax-options-default ()
+  "Test the default MathJax options."
+  (should
+   (= 1 (org-test-with-temp-text "$x$"
+          (let ((export-buffer "*Test HTML Export*")
+                (org-export-show-temporary-export-buffer nil))
+            (org-export-to-buffer 'html export-buffer
+              nil nil nil nil nil
+              #'html-mode)
+            (with-current-buffer export-buffer
+              (how-many (rx "<script>
+  window.MathJax = {
+    tex: {
+      ams: {
+        multlineWidth: '85%'
+      },
+      tags: 'ams',
+      tagSide: 'right',
+      tagIndent: '.8em'
+    },
+    chtml: {
+      scale: 1.0,
+      displayAlign: 'center',
+      displayIndent: '0em'
+    },
+    svg: {
+      scale: 1.0,
+      displayAlign: 'center',
+      displayIndent: '0em'
+    },
+    output: {
+      font: 'mathjax-modern',
+      displayOverflow: 'overflow'
+    }
+  };
+</script>"))))))))
+
+(ert-deftest ox-html/mathjax-options-custom ()
+  "Test customized MathJax options."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               '((path "<unused>")      ; tested elsewhere
+                 (scale 0.5)
+                 (align "right")
+                 (font "mathjax-euler")
+                 (overflow "scale")
+                 (tags "all")
+                 (indent "1em")
+                 (multlinewidth "100%")
+                 (tagindent "2em")
+                 (tagside "left"))))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx "<script>
+  window.MathJax = {
+    tex: {
+      ams: {
+        multlineWidth: '100%'
+      },
+      tags: 'all',
+      tagSide: 'left',
+      tagIndent: '2em'
+    },
+    chtml: {
+      scale: 0.5,
+      displayAlign: 'right',
+      displayIndent: '1em'
+    },
+    svg: {
+      scale: 0.5,
+      displayAlign: 'right',
+      displayIndent: '1em'
+    },
+    output: {
+      font: 'mathjax-euler',
+      displayOverflow: 'scale'
+    }
+  };
+</script>"))))))))
+
+(ert-deftest ox-html/mathjax-options-in-buffer ()
+  "Test in-buffer customized MathJax options."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: scale: 0.5
+#+HTML_MATHJAX: align: right
+#+HTML_MATHJAX: font: mathjax-euler
+#+HTML_MATHJAX: overflow: scale
+#+HTML_MATHJAX: tags: all
+#+HTML_MATHJAX: indent: 1em
+#+HTML_MATHJAX: multlinewidth: 100%
+#+HTML_MATHJAX: tagindent: 2em
+#+HTML_MATHJAX: tagside: left"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx "<script>
+  window.MathJax = {
+    tex: {
+      ams: {
+        multlineWidth: '100%'
+      },
+      tags: 'all',
+      tagSide: 'left',
+      tagIndent: '2em'
+    },
+    chtml: {
+      scale: 0.5,
+      displayAlign: 'right',
+      displayIndent: '1em'
+    },
+    svg: {
+      scale: 0.5,
+      displayAlign: 'right',
+      displayIndent: '1em'
+    },
+    output: {
+      font: 'mathjax-euler',
+      displayOverflow: 'scale'
+    }
+  };
+</script>"))))))))
+
+\f
+;;; Converting legacy MathJax scales
+
+;; Define a legacy scale as any scale given as a percentage string,
+;; such as "150", instead of a unit-interval float, such as 1.5.
+
+(ert-deftest ox-html/mathjax-legacy-scale-default ()
+  "Test the legacy scale conversion with the old default value."
+  (should
+   (= 2
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(scale "100") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "scale: 1.0" (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-scale-custom ()
+  "Test the legacy scale conversion with a non-default value."
+  (should
+   (= 2
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(scale "10") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "scale: 0.1" (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-scale-in-buffer ()
+  "Test the legacy scale conversion with an in-buffer value."
+  (should
+   (= 2
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: scale: 10"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "scale: 0.1" (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-scale-message ()
+  "Test the legacy scale conversion message."
+  (should
+   (= 1
+      (seq-count
+       (lambda (message)
+         (string= "Converting legacy MathJax scale: 20 to 0.2"
+                  message))
+       (org-test-capture-warnings
+         (org-test-with-temp-text "$x$"
+           (let ((export-buffer "*Test HTML Export*")
+                 (org-export-show-temporary-export-buffer nil)
+                 (org-html-mathjax-options
+                  (cons '(scale "20") org-html-mathjax-options)))
+             (org-export-to-buffer 'html export-buffer
+               nil nil nil nil nil
+               #'html-mode))))))))
+
+(ert-deftest ox-html/mathjax-legacy-scale-message-in-buffer ()
+  "Test the legacy scale conversion message for an in-buffer value."
+  (should
+   (seq-count
+    (lambda (message)
+      (string= "Converting legacy MathJax scale: 20 to 0.2"
+               message))
+    (org-test-capture-warnings
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: scale: 20"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)))))))
+
+(ert-deftest ox-html/mathjax-legacy-scale-ignore ()
+  "Test the legacy scale conversion ignores small values."
+  (should
+   (= 2
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options '((scale "9"))))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "scale: 9" (or "," "\n"))))))))))
+
+\f
+;;; Converting legacy MathJax auto-numbering
+
+;; NOTE: AMS stands for American Mathematical Society.
+
+(ert-deftest ox-html/mathjax-legacy-autonumber-ams ()
+  "Test legacy auto-numbering, when AMS."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(autonumber "AMS") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "tags: 'ams'" (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-autonumber-ams-in-buffer ()
+  "Test legacy auto-numbering, when AMS in-buffer."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: autonumber: AMS"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "tags: 'ams'" (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-autonumber-none ()
+  "Test legacy auto-numbering, when disabled."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(autonumber "None") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "tags: 'none'" (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-autonumber-none-in-buffer ()
+  "Test legacy auto-numbering, when disabled in-buffer."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: autonumber: None"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "tags: 'none'" (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-autonumber-all ()
+  "Test legacy auto-numbering, when enabled."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(autonumber "All") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "tags: 'all'" (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-autonumber-all-in-buffer ()
+  "Test legacy auto-numbering, when enabled in-buffer."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: autonumber: All"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "tags: 'all'" (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-autonumber-message ()
+  "Test legacy auto-numbering conversion message."
+  (should
+   (= 1
+      (seq-count
+       (lambda (message)
+         (string= "Converting legacy MathJax option: autonumber"
+                  message))
+       (org-test-capture-warnings
+         (org-test-with-temp-text "$x$"
+           (let ((export-buffer "*Test HTML Export*")
+                 (org-export-show-temporary-export-buffer nil)
+                 (org-html-mathjax-options
+                  (cons '(autonumber "AMS") org-html-mathjax-options)))
+             (org-export-to-buffer 'html export-buffer
+               nil nil nil nil nil
+               #'html-mode))))))))
+
+(ert-deftest ox-html/mathjax-legacy-autonumber-message-in-buffer ()
+  "Test legacy auto-numbering conversion message."
+  (should
+   (= 1
+      (seq-count
+       (lambda (message)
+         (string= "Converting legacy MathJax option: autonumber"
+                  message))
+       (org-test-capture-warnings
+         (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: autonumber: AMS"
+           (let ((export-buffer "*Test HTML Export*")
+                 (org-export-show-temporary-export-buffer nil))
+             (org-export-to-buffer 'html export-buffer
+               nil nil nil nil nil
+               #'html-mode))))))))
+
+\f
+;;; Converting legacy MathJax fonts
+
+(ert-deftest ox-html/mathjax-legacy-font-tex ()
+  "Test legacy font, when TeX."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(font "TeX") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-tex'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-tex-in-buffer ()
+  "Test legacy font, when TeX in-buffer."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: font: TeX"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-tex'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-stix-web ()
+  "Test legacy font, when STIX-Web."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(font "STIX-Web") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-stix2'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-stix-web-in-buffer ()
+  "Test legacy font, when STIX-Web in-buffer."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: font: STIX-Web"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-stix2'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-asana-math ()
+  "Test legacy font, when Asana-Math."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(font "Asana-Math") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-asana'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-asana-math-in-buffer ()
+  "Test legacy font, when Asana-Math in-buffer."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: font: Asana-Math"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-asana'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-neo-euler ()
+  "Test legacy font, when Neo-Euler."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(font "Neo-Euler") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-euler'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-neo-euler-in-buffer ()
+  "Test legacy font, when Neo-Euler in-buffer."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: font: Neo-Euler"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-euler'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-gyre-pagella ()
+  "Test legacy font, when Gyre-Pagella."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(font "Gyre-Pagella") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-pagella'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-gyre-pagella-in-buffer ()
+  "Test legacy font, when Gyre-Pagella in-buffer."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: font: Gyre-Pagella"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-pagella'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-gyre-termes ()
+  "Test legacy font, when Gyre-Termes."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(font "Gyre-Termes") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-termes'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-gyre-termes-in-buffer ()
+  "Test legacy font, when Gyre-Termes in-buffer."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: font: Gyre-Termes"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-termes'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-latin-modern ()
+  "Test legacy font, when Latin-Modern."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(font "Latin-Modern") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-modern'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-font-latin-modern-in-buffer ()
+  "Test legacy font, when Latin-Modern in-buffer."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: font: Latin-Modern"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "font: 'mathjax-modern'"
+                               (or "," "\n"))))))))))
+
+\f
+;;; Converting legacy MathJax line breaks
+
+(ert-deftest ox-html/mathjax-legacy-line-breaks-true ()
+  "Test legacy line breaks, when true."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (append '((linebreaks "true")
+                         (overflow "overflow"))
+                       org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "displayOverflow: 'linebreak'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-line-breaks-true-in-buffer ()
+  "Test legacy line breaks, when true in-buffer."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: linebreaks: true"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(overflow "overflow") org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "displayOverflow: 'linebreak'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-line-breaks-false ()
+  "Test legacy line breaks, when false."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (append '((linebreaks "false")
+                         (overflow "linebreak"))
+                       org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "displayOverflow: 'overflow'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-line-breaks-false-in-buffer ()
+  "Test legacy line breaks, when true in-buffer."
+  (should
+   (= 1
+      (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: linebreaks: false"
+        (let ((export-buffer "*Test HTML Export*")
+              (org-export-show-temporary-export-buffer nil)
+              (org-html-mathjax-options
+               (cons '(overflow "linebreak")
+                     org-html-mathjax-options)))
+          (org-export-to-buffer 'html export-buffer
+            nil nil nil nil nil
+            #'html-mode)
+          (with-current-buffer export-buffer
+            (how-many (rx (seq "displayOverflow: 'overflow'"
+                               (or "," "\n"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-line-breaks-message ()
+  "Test the legacy line breaks conversion message."
+  (should
+   (= 1
+      (seq-count
+       (lambda (message)
+         (string= "Converting legacy MathJax option: linebreaks"
+                  message))
+       (org-test-capture-warnings
+         (org-test-with-temp-text "$x$"
+           (let ((export-buffer "*Test HTML Export*")
+                 (org-export-show-temporary-export-buffer nil)
+                 (org-html-mathjax-options (cons '(linebreaks "true")
+                                                 org-html-mathjax-options)))
+             (org-export-to-buffer 'html export-buffer
+               nil nil nil nil nil
+               #'html-mode))))))))
+
+(ert-deftest ox-html/mathjax-legacy-line-breaks-message-in-buffer ()
+  "Test the legacy scale conversion message for an in-buffer value."
+  (should
+   (= 1
+      (seq-count
+       (lambda (message)
+         (string= "Converting legacy MathJax option: linebreaks"
+                  message))
+       (org-test-capture-warnings
+         (org-test-with-temp-text "$x$
+#+HTML_MATHJAX: linebreaks: true"
+           (let ((export-buffer "*Test HTML Export*")
+                 (org-export-show-temporary-export-buffer nil))
+             (org-export-to-buffer 'html export-buffer
+               nil nil nil nil nil
+               #'html-mode))))))))
+
+(provide 'test-ox-html)
+;;; test-ox-html.el ends here
diff --git a/testing/org-test.el b/testing/org-test.el
index 9f7bab9ea..880d9e845 100644
--- a/testing/org-test.el
+++ b/testing/org-test.el
@@ -33,6 +33,7 @@
 
 (require 'org)
 (require 'org-id)
+(require 'org-macs)
 
 ;;; Ob constants
 
@@ -531,6 +532,16 @@ TIME can be a non-nil Lisp time value, or a string specifying a date and time."
 				    (or a ,at) (or b ,at)))))
 	 ,@body))))
 
+(defmacro org-test-capture-warnings (&rest body)
+  "Capture all warnings passed to `org-display-warning' within BODY."
+  (declare (indent 0) (debug t))
+  `(let ((messages (list)))
+     (cl-letf (((symbol-function 'org-display-warning)
+                (lambda (message)
+                  (setq messages (cons message messages)))))
+       ,@body)
+     (nreverse messages)))
+
 (provide 'org-test)
 
 ;;; org-test.el ends here
-- 
2.38.1


[-- Attachment #3: Type: text/plain, Size: 257 bytes --]

-- 
"Logic is a science of the necessary laws of thought, without which no
employment of the understanding and the reason takes place."
-- Immanuel Kant, 1785

Rudolf Adamkovič <salutis@me.com> [he/him]
Studenohorská 25
84103 Bratislava
Slovakia

  reply	other threads:[~2022-11-09 23:03 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-07 13:36 Update Org to MathJax 3 Rudolf Adamkovič
2022-10-08  7:20 ` Ihor Radchenko
2022-10-08 21:32   ` Rudolf Adamkovič
2022-11-05  0:20     ` [PATCH] " Rudolf Adamkovič
2022-11-05 12:01       ` Ihor Radchenko
2022-11-05 16:56         ` Rudolf Adamkovič
2022-11-05 22:44           ` Rudolf Adamkovič
2022-11-06  3:52             ` Ihor Radchenko
2022-11-06 23:49               ` Rudolf Adamkovič
2022-11-07  3:02                 ` Ihor Radchenko
2022-11-07 20:56                   ` Rudolf Adamkovič
2022-11-08  5:20                     ` Ihor Radchenko
2022-11-08 23:37                       ` Rudolf Adamkovič
2022-11-09  0:05                         ` Rudolf Adamkovič
2022-11-09  5:40                           ` Ihor Radchenko
2022-11-09 23:01                             ` Rudolf Adamkovič [this message]
2022-11-10  2:34                               ` Ihor Radchenko
2022-11-11 12:50                                 ` Rudolf Adamkovič
2022-11-13  4:24                                   ` Ihor Radchenko
2022-11-13 20:52                                     ` Rudolf Adamkovič
2022-11-14  4:33                                       ` Ihor Radchenko
2022-11-19 13:10                                         ` Bastien Guerry
2022-11-21  2:51                                           ` Ihor Radchenko
2022-11-22 20:56                                             ` Rudolf Adamkovič
2022-11-23 11:11                                               ` Ihor Radchenko
2022-11-23 23:08                                                 ` Rudolf Adamkovič
2022-11-09  2:49                         ` Ihor Radchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m2pmdvlokg.fsf@me.com \
    --to=salutis@me.com \
    --cc=emacs-orgmode@gnu.org \
    --cc=yantar92@gmail.com \
    --cc=yantar92@posteo.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).