Hey Ihor,

On 2025-08-10 04:06, Ihor Radchenko wrote:
> I was mostly talking about internals. If you mean something like "Use
> `LaTeX' as an intermediary" in your first message, then it is _not_ what
> I had in mind. What I had in mind is some kind of internal backend that
> will be used by html/odt/etc. The advantage of using a backend is that
> we can plug export customization system - filters, custom templates,
> in-buffer options, etc.

I misunderstood then, thanks for the explanation. I’ll study
'org-export-toc-entry-backend' to better understand how internal
backends are used.

> So, ox-odt now does support it.
> https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=8b900ae37

Thank you! I’ve attached a patch series that:

1. Fixes the description of 'org-odt-with-latex' to match the export
   behaviour.

2. Allows any symbol from 'org-preview-latex-process-alist', just like
   'org-html-with-latex'. This way, 'xelatex' and any future additions
   are allowed, including user-defined symbols.

3. Replaces the hard-coded 'ltxmathml' directory with a variable.

Best,

-- 
Jacob S. Gordon
jacob.as.gor...@gmail.com
Please avoid sending me HTML emails and MS Office documents.
https://useplaintext.email/#etiquette
From 140afc20276690c059646e08814f84ae24589c29 Mon Sep 17 00:00:00 2001
From: "Jacob S. Gordon" <jacob.as.gor...@gmail.com>
Date: Sun, 10 Aug 2025 18:08:02 -0400
Subject: [PATCH v1 1/3] ox-odt: Align 'org-odt-with-latex' with export
 behavior

* lisp/ox-odt.el (org-odt-with-latex): Remove 'mathjax', add missing
'mathml' and 'dvisvgm' options, and clarify when 'verbatim' is used as
a fallback.
(org-odt--translate-latex-fragments): Update comment.
---
 lisp/ox-odt.el | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el
index 8fb026247..0c59d516f 100644
--- a/lisp/ox-odt.el
+++ b/lisp/ox-odt.el
@@ -722,26 +722,30 @@ When set, the exporter will process LaTeX environments and
 fragments.
 
 This option can also be set with the +OPTIONS line,
-e.g. \"tex:mathjax\".  Allowed values are:
+e.g. \"tex:dvipng\".  Allowed values are:
 
 nil            Ignore math snippets.
-`verbatim'     Keep everything in verbatim
-`dvipng'       Process the LaTeX fragments to images.  This will also
-               include processing of non-math environments.
+t, `mathml'    Convert the LaTeX fragments to MathML if the
+               `org-latex-to-mathml-convert-command' is usable.
+`dvipng'       Process the LaTeX fragments to PNG images.  This will
+               also include processing of non-math environments.
 `imagemagick'  Convert the LaTeX fragments to pdf files and use
                imagemagick to convert pdf files to png files.
-`mathjax'      Do MathJax preprocessing and arrange for MathJax.js to
-               be loaded.
+`dvisvgm'      Process the LaTeX fragments to SVG images.  This will
+               also include processing of non-math environments.
+`verbatim'     Keep everything in verbatim.
 
-Any other symbol is a synonym for `mathjax'."
+If the desired converter is not available or any other symbol is
+provided, process as `verbatim'."
   :version "24.4"
   :package-version '(Org . "8.0")
   :type '(choice
 	  (const :tag "Do not process math in any way" nil)
-	  (const :tag "Leave math verbatim" verbatim)
+	  (const :tag "Convert fragments to MathML" mathml)
 	  (const :tag "Use dvipng to make images" dvipng)
 	  (const :tag "Use imagemagick to make images" imagemagick)
-	  (other :tag "Use MathJax to display math" mathjax)))
+	  (const :tag "Use dvisvgm to make images" dvisvgm)
+	  (const :tag "Leave math verbatim" verbatim)))
 
 
 ;;;; Links
@@ -3779,9 +3783,9 @@ contextual information."
   (let ((processing-type (plist-get info :with-latex))
 	(count 0)
         (warning nil))
-    ;; Normalize processing-type to one of dvipng, mathml or verbatim.
-    ;; If the desired converter is not available, force verbatim
-    ;; processing.
+    ;; Normalize processing-type to one of mathml, dvipng,
+    ;; imagemagick, dvisvgm, or verbatim.  If the desired converter is
+    ;; not available, force verbatim processing.
     (cl-case processing-type
       ((t mathml)
        (if (and (fboundp 'org-format-latex-mathml-available-p)

base-commit: f90f6912afd17001006e9b1b30ad5af86342ebe8
-- 
Jacob S. Gordon
jacob.as.gor...@gmail.com
Please avoid sending me HTML emails and MS Office documents.
https://useplaintext.email/#etiquette

From f0130f09cb638a8e716caa1ae43b82cf04ab0c20 Mon Sep 17 00:00:00 2001
From: "Jacob S. Gordon" <jacob.as.gor...@gmail.com>
Date: Sun, 10 Aug 2025 21:23:56 -0400
Subject: [PATCH v1 2/3] ox-odt: Allow LaTeX fragment conversion from any
 preview method

Previously, only 'dvipng', 'imagemagick' and 'dvisvgm' could be used
to convert LaTeX fragments to images.  This missed 'xelatex' and any
user-defined symbols.  Any symbol in 'org-preview-latex-process-alist'
can now be used.

* lisp/ox-odt.el (org-odt-with-latex): Replace specific conversion
methods with a generic symbol, mirroring 'org-html-with-latex'.
(org-odt--translate-latex-fragments): Replace hard-coded symbols with
those from 'org-preview-latex-process-alist', and check all external
commands from the same.  Generalize comments.
---
 lisp/ox-odt.el | 77 +++++++++++++++++++++++++-------------------------
 1 file changed, 38 insertions(+), 39 deletions(-)

diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el
index 0c59d516f..d0feb05c3 100644
--- a/lisp/ox-odt.el
+++ b/lisp/ox-odt.el
@@ -727,12 +727,9 @@ e.g. \"tex:dvipng\".  Allowed values are:
 nil            Ignore math snippets.
 t, `mathml'    Convert the LaTeX fragments to MathML if the
                `org-latex-to-mathml-convert-command' is usable.
-`dvipng'       Process the LaTeX fragments to PNG images.  This will
-               also include processing of non-math environments.
-`imagemagick'  Convert the LaTeX fragments to pdf files and use
-               imagemagick to convert pdf files to png files.
-`dvisvgm'      Process the LaTeX fragments to SVG images.  This will
-               also include processing of non-math environments.
+SYMBOL         Convert the LaTeX fragments to images using any symbol
+               defined in `org-preview-latex-process-alist', e.g.,
+               `dvipng'.
 `verbatim'     Keep everything in verbatim.
 
 If the desired converter is not available or any other symbol is
@@ -742,9 +739,7 @@ provided, process as `verbatim'."
   :type '(choice
 	  (const :tag "Do not process math in any way" nil)
 	  (const :tag "Convert fragments to MathML" mathml)
-	  (const :tag "Use dvipng to make images" dvipng)
-	  (const :tag "Use imagemagick to make images" imagemagick)
-	  (const :tag "Use dvisvgm to make images" dvisvgm)
+	  (symbol :tag "Convert fragments to images" :value dvipng)
 	  (const :tag "Leave math verbatim" verbatim)))
 
 
@@ -3781,30 +3776,36 @@ contextual information."
 
 (defun org-odt--translate-latex-fragments (tree _backend info)
   (let ((processing-type (plist-get info :with-latex))
+	(preview-symbols (mapcar #'car org-preview-latex-process-alist))
 	(count 0)
         (warning nil))
-    ;; Normalize processing-type to one of mathml, dvipng,
-    ;; imagemagick, dvisvgm, or verbatim.  If the desired converter is
-    ;; not available, force verbatim processing.
-    (cl-case processing-type
-      ((t mathml)
+    ;; Normalize processing-type to one of mathml, verbatim, or a
+    ;; symbol in org-preview-latex-process-alist.  If the desired
+    ;; converter is not available, force verbatim processing.
+    (pcase processing-type
+      ((or 't 'mathml)
        (if (and (fboundp 'org-format-latex-mathml-available-p)
 		(org-format-latex-mathml-available-p))
 	   (setq processing-type 'mathml)
          (setq warning "`org-odt-with-latex': LaTeX to MathML converter not available.  Falling back to verbatim.")
 	 (setq processing-type 'verbatim)))
-      ((dvipng imagemagick dvisvgm)
-       (unless (and (org-check-external-command "latex" "" t)
-		    (org-check-external-command
-                     (cl-case processing-type
-                       (dvipng "dvipng")
-                       (dvisvgm "dvisvgm")
-                       (imagemagick "convert"))
-		     "" t))
-	 (setq warning "`org-odt-with-latex': LaTeX to PNG converter not available.  Falling back to verbatim.")
+      ((and s
+	    (guard (memq s preview-symbols))
+	    (let ext-commands
+	      (plist-get
+	       (cdr (assq s org-preview-latex-process-alist))
+	       :programs))
+	    (let ext-commands-check
+	      (seq-reduce (lambda (result cmd)
+			    (and result
+				 (not (null
+				       (org-check-external-command cmd "" t)))))
+			  ext-commands t)))
+       (unless ext-commands-check
+	 (setq warning "`org-odt-with-latex': LaTeX to image converter not available.  Falling back to verbatim.")
 	 (setq processing-type 'verbatim)))
-      (verbatim) ;; nothing to do
-      (otherwise
+      ('verbatim) ;; nothing to do
+      (_
        (setq warning "`org-odt-with-latex': Unknown LaTeX option.  Forcing verbatim.")
        (setq processing-type 'verbatim)))
 
@@ -3821,34 +3822,32 @@ contextual information."
     (message "Formatting LaTeX using %s" processing-type)
 
     ;; Convert `latex-fragment's and `latex-environment's.
-    (when (memq processing-type '(mathml dvipng dvisvgm imagemagick))
+    (when (memq processing-type (append '(mathml) preview-symbols))
       (org-element-map tree '(latex-fragment latex-environment)
 	(lambda (latex-*)
 	  (cl-incf count)
 	  (let* ((latex-frag (org-element-property :value latex-*))
 		 (input-file (plist-get info :input-file))
+                 (is-image (memq processing-type preview-symbols))
 		 (cache-dir (file-name-directory input-file))
 		 (cache-subdir (concat
-				(cl-case processing-type
-				  ((dvipng dvisvgm imagemagick)
-				   org-preview-latex-image-directory)
-				  (mathml "ltxmathml/"))
+				(if is-image
+				    org-preview-latex-image-directory
+				  "ltxmathml/")
 				(file-name-sans-extension
 				 (file-name-nondirectory input-file))))
 		 (display-msg
-		  (cl-case processing-type
-		    ((dvipng dvisvgm imagemagick)
-		     (format "Creating LaTeX Image %d..." count))
-		    (mathml (format "Creating MathML snippet %d..." count))))
-		 ;; Get an Org-style link to PNG image or the MathML
-		 ;; file.
+		  (if is-image
+		      (format "Creating LaTeX image %d..." count)
+		    (format "Creating MathML snippet %d..." count)))
+		 ;; Get an Org-style link to image or the MathML file.
 		 (link
 		  (with-temp-buffer
 		    (insert latex-frag)
                     (delay-mode-hooks (let ((org-inhibit-startup t)) (org-mode)))
-		    ;; When converting to a PNG image, make sure to
-		    ;; copy all LaTeX header specifications from the
-		    ;; Org source.
+		    ;; When converting to an image, make sure to copy
+		    ;; all LaTeX header specifications from the Org
+		    ;; source.
 		    (unless (eq processing-type 'mathml)
 		      (let ((h (plist-get info :latex-header)))
 			(when h
-- 
Jacob S. Gordon
jacob.as.gor...@gmail.com
Please avoid sending me HTML emails and MS Office documents.
https://useplaintext.email/#etiquette

From 1709da8c3f8cb63bbb1976cf1daf1b3d5783d927 Mon Sep 17 00:00:00 2001
From: "Jacob S. Gordon" <jacob.as.gor...@gmail.com>
Date: Sun, 10 Aug 2025 21:41:24 -0400
Subject: [PATCH v1 3/3] ox-odt: Add variable to specify path of generated
 MathML files

* lisp/org.el (org-latex-mathml-directory): Add custom variable.
* lisp/ox-odt.el (org-odt--translate-latex-fragments): Replace
hard-coded MathML directory with the new variable.
---
 lisp/org.el    | 9 +++++++++
 lisp/ox-odt.el | 2 +-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/lisp/org.el b/lisp/org.el
index 65abfbe1a..29143cafb 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -3513,6 +3513,15 @@ images at the same place."
   :package-version '(Org . "9.0")
   :type 'string)
 
+(defcustom org-latex-mathml-directory "ltxmathml/"
+  "Path to store MathML files converted from LaTeX fragments.
+A relative path here creates many directories relative to the
+processed Org files paths.  An absolute path puts all files
+in the same place."
+  :group 'org-latex
+  :version "31.1"
+  :type 'string)
+
 (defun org-format-latex-mathml-available-p ()
   "Return t if `org-latex-to-mathml-convert-command' is usable."
   (save-match-data
diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el
index d0feb05c3..8f3bb175a 100644
--- a/lisp/ox-odt.el
+++ b/lisp/ox-odt.el
@@ -3833,7 +3833,7 @@ contextual information."
 		 (cache-subdir (concat
 				(if is-image
 				    org-preview-latex-image-directory
-				  "ltxmathml/")
+				  org-latex-mathml-directory)
 				(file-name-sans-extension
 				 (file-name-nondirectory input-file))))
 		 (display-msg
-- 
Jacob S. Gordon
jacob.as.gor...@gmail.com
Please avoid sending me HTML emails and MS Office documents.
https://useplaintext.email/#etiquette

Reply via email to