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: Fri, 11 Nov 2022 13:50:06 +0100	[thread overview]
Message-ID: <m27d018xkx.fsf@me.com> (raw)
In-Reply-To: <87pmdvk054.fsf@localhost>

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

Ihor Radchenko <yantar92@posteo.net> writes:

> Then, please mention this in the NEWS. Something like "we drop
> extension support as it never worked anyway".

Fixed.  I also reworded the surrounding text to match.

> You may even drop append and use ,@options inside `(...). Not a big
> deal though.

Fixed.

> If value is invalid string (not an actual number), `string-to-number'
> will return 0. This may cause very strange export output I think.

Fixed and added two new tests:

- ox-html/mathjax-legacy-scale-invalid
- ox-html/mathjax-legacy-scale-invalid-message

Below, I attach the 7th revision of the patch.

Rudy


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

From 49f1dc5e58720c68546a2aedfeb8f87df60ac6cb 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                 |  38 ++
 lisp/ox-html.el              | 257 ++++++++---
 testing/lisp/test-ox-html.el | 818 +++++++++++++++++++++++++++++++++++
 testing/org-test.el          |  11 +
 5 files changed, 1063 insertions(+), 81 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..d9a80a2e5 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -139,6 +139,44 @@ 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.
+
+MathJax 3, a ground-up rewrite of MathJax 2 came out 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
+
+MathJax 3 comes with useful extensions.  For instance, you can typeset
+calculus with the ~physics~ extension or chemistry with the ~mhchem~
+extension, like in LaTeX.
+
+Note that the Org manual does not discuss loading of MathJax
+extensions via ~+HTML_MATHJAX~ anymore.  It has never worked anyway.
+To actually load extensions, consult the official documentation:
+
+https://docs.mathjax.org/en/latest/input/tex/extensions.html
+
+Lastly, 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..443ae4ebe 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)
@@ -1945,21 +2000,85 @@ INFO is a plist used as a communication channel."
   "Insert the user setup into the mathjax template.
 INFO is a plist used as a communication channel."
   (when (and (memq (plist-get info :with-latex) '(mathjax t))
-	     (org-element-map (plist-get info :parse-tree)
-		 '(latex-fragment latex-environment) #'identity info t nil t))
+             (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))
-	  (in-buffer (or (plist-get info :html-mathjax) "")))
+          (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.
+                     `((,(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
+                   ((value-new
+                     (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 value-new)))
+              (`linebreaks
+               (org-display-warning
+                "Converting legacy MathJax option: linebreaks")
+               (setq symbol 'overflow
+                     value (if (string= value "true")
+                               "linebreak"
+                             "overflow")))
+              (`scale
+               (when (stringp value)
+                 (let ((value-maybe (string-to-number value)))
+                   (setq value
+                         (if (= value-maybe 0)
+                             (progn
+                               (org-display-warning
+                                (format "Non-numerical MathJax scale: %s"
+                                        value))
+                               1.0)
+                           value-maybe))))
+               (when (>= value 10)
+                 (setq value
+                       (let ((value-new (/ (float value) 100)))
+                         (org-display-warning
+                          (format "Converting legacy MathJax scale: %s to %s"
+                                  value
+                                  value-new))
+                         value-new))))
+              (`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..e1b492733
--- /dev/null
+++ b/testing/lisp/test-ox-html.el
@@ -0,0 +1,818 @@
+;;; 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"))))))))))
+
+(ert-deftest ox-html/mathjax-legacy-scale-invalid ()
+  "Test the legacy scale conversion with an invalid 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 "xxx") 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-invalid-message ()
+  "Test the invalid legacy scale conversion message."
+  (should
+   (= 1
+      (seq-count
+       (lambda (message)
+         (string= "Non-numerical MathJax scale: xxx"
+                  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 "xxx") org-html-mathjax-options)))
+             (org-export-to-buffer 'html export-buffer
+               nil nil nil nil nil
+               #'html-mode))))))))
+
+\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: 246 bytes --]

-- 
"One can begin to reason only when a clear picture has been formed in
the imagination."
-- Walter Warwick Sawyer, Mathematician's Delight, 1943

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

  reply	other threads:[~2022-11-11 12:51 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č
2022-11-10  2:34                               ` Ihor Radchenko
2022-11-11 12:50                                 ` Rudolf Adamkovič [this message]
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=m27d018xkx.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).