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/
This commit is contained in:
Rudolf Adamkovič 2022-10-07 15:03:48 +02:00 committed by Ihor Radchenko
parent 46c4335e44
commit 62e1513b5a
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
5 changed files with 1063 additions and 81 deletions

View File

@ -13231,24 +13231,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

View File

@ -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~ option in
which now /must/ point to a file containing MathJax version 3 or
later. The new Org does /not/ work with the legacy MathJax 2.
Further, if you need to use a non-default ~font~ or ~linebreaks~ (now
~overflow~), then the ~path~ must point to MathJax 3 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

View File

@ -1167,72 +1167,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 3+. MathJax 3 provides 11 fonts:
\"mathjax-modern\" Latin-Modern font, default in MathJax 3+
\"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 3 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 3+ 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)"
@ -1245,27 +1289,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,21 +2003,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.

View File

@ -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)
;;; 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
(= 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))))))))
;;; 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))))))))
;;; 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
(= 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

View File

@ -33,6 +33,7 @@
(require 'org)
(require 'org-id)
(require 'org-macs)
;;; Ob constants
@ -536,6 +537,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