Rudolf Adamkovič <salu...@me.com> writes:

> I will resurrect the thread when I have something to show.

All right, I have finished the second version of the patch.

What do you think?

Rudy

>From aee823f34498cccd6c08bcedb177c82d5de40269 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rudolf=20Adamkovi=C4=8D?= <salu...@me.com>
Date: Fri, 7 Oct 2022 15:03:48 +0200
Subject: [PATCH] ox-html: Update from MathJax 2 to MathJax 3+
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* lisp/ox-html.el (
org-html-mathjax-options,
org-html-mathjax-template,
org-html--build-mathjax-config
): Update to MathJax 3 while maintaining compatibility with MathJax 2.
All legacy options get converted automatically, except for the 'path'
option which must now point to MathJax 3 or later and not MathJax 2.
* 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.

Reported-by: Rudolf Adamkovič <salu...@me.com>
Link: https://list.orgmode.org/orgmode/m2a667n4ax....@me.com/
---
 etc/ORG-NEWS                 |  25 ++
 lisp/ox-html.el              | 247 +++++++++---
 testing/lisp/test-ox-html.el | 762 +++++++++++++++++++++++++++++++++++
 3 files changed, 968 insertions(+), 66 deletions(-)
 create mode 100644 testing/lisp/test-ox-html.el

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index b542da34b..7ad17bd70 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -139,6 +139,31 @@ 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 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.
+
+During the export, Org automatically converts all legacy MathJax 2
+options to the corresponding MathJax 3+ options, except for the =path=
+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.
+
 ** New features
 *** Clock table can now produce quarterly reports
 
diff --git a/lisp/ox-html.el b/lisp/ox-html.el
index cad06aebf..9436623e0 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,78 @@ 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
+                      (list (list (if (plist-member options 'autonumber)
+                                      'tags 'autonumber)
+                                  nil)
+                            (list (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 (cond
+                                ((string= value "TeX")
+                                 "mathjax-tex")
+                                ((string= value "STIX-Web")
+                                 "mathjax-stix2")
+                                ((string= value "Asana-Math")
+                                 "mathjax-asana")
+                                ((string= value "Neo-Euler")
+                                 "mathjax-euler")
+                                ((string= value "Gyre-Pagella")
+                                 "mathjax-pagella")
+                                ((string= value "Gyre-Termes")
+                                 "mathjax-termes")
+                                ((string= value "Latin-Modern")
+                                 "mathjax-modern")
+                                nil)))
+                 (setq value new-value)))
+              ('linebreaks
+               (message "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)))
+                   (message "Converting legacy MathJax scale: %s to %s"
+                            value
+                            new-value)
+                   (setq value new-value))))
+              ('autonumber
+               (message "Converting legacy MathJax option: autonumber")
+               (setq symbol 'tags)
+               (setq 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..65d987dd7
--- /dev/null
+++ b/testing/lisp/test-ox-html.el
@@ -0,0 +1,762 @@
+;;; test-ox-html.el --- Tests for ox-html.el
+
+;; Copyright (C) 2022  Rudolf Adamkovič
+
+;; Author: Rudolf Adamkovič <salu...@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)
+
+
+;;; 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>"))))))))
+
+
+;;; 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>"))))))))
+
+
+;;; 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
+   (string= "Converting legacy MathJax scale: 20 to 0.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 "20") org-html-mathjax-options)))
+                (org-export-to-buffer 'html export-buffer
+                  nil nil nil nil nil
+                  #'html-mode)
+                (current-message))))))
+
+(ert-deftest ox-html/mathjax-legacy-scale-message-in-buffer ()
+  "Test the legacy scale conversion message for an in-buffer value."
+  (should
+   (string= "Converting legacy MathJax scale: 20 to 0.2"
+            (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)
+                (current-message))))))
+
+(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"))))))))))
+
+
+;;; 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
+   (string= "Converting legacy MathJax option: autonumber"
+            (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)
+                (current-message))))))
+
+(ert-deftest ox-html/mathjax-legacy-autonumber-message-in-buffer ()
+  "Test legacy auto-numbering conversion message."
+  (should
+   (string= "Converting legacy MathJax option: autonumber"
+            (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)
+                (current-message))))))
+
+
+;;; 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"))))))))))
+
+
+;;; 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
+   (string= "Converting legacy MathJax option: linebreaks"
+            (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)
+                (current-message))))))
+
+(ert-deftest ox-html/mathjax-legacy-line-breaks-message-in-buffer ()
+  "Test the legacy scale conversion message for an in-buffer value."
+  (should
+   (string= "Converting legacy MathJax option: linebreaks"
+            (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)
+                (current-message))))))
+
+(provide 'test-ox-html)
+;;; test-ox-html.el ends here
-- 
2.38.1

-- 
"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č <salu...@me.com> [he/him]
Studenohorská 25
84103 Bratislava
Slovakia

Reply via email to