Ihor Radchenko <yanta...@posteo.net> writes:

I think that rather than inventing something new, we can reuse the existing semantics of `org-latex-pdf-process' and `org-compile-file'.

I redid the code (see attached patch) to you use =defcustom= to define only a single variable and have that variable use the =%o= and =%f= syntax similar to =`org-latex-pdf-process=. I also allow the user to set that variable to indicate not to do conversion if desired and issue a warning only if the variable is unset and neither inkscape nor rsvg-convert are found.

I tested various cases (with rsvg-convert, with inkscape, and with neither).

I am sorry for not being able to get org-persist working. I tried your suggestions but could not figure out how to do it. I grepped the lisp directory of org-mode from the git repo but could not find any examples that fit my use case. I also asked Claude and Gemini and they could not produce a working example. I recognize your time is valuable and I tried figuring it out but at some point I have to give up.

I think the attached patch is still a step forward since it makes latex export work with SVGs which is not the case on my system without this patch. Also, I prefer having the PDFs from the converted SVGs available in the same directory as the SVG. If there is a desire to hide the converted PDFs, perhaps that can be a project or patch for future work.

Thanks,
-Emin


>From fa72485de964b64934859f6580adf5ce8957506b Mon Sep 17 00:00:00 2001
From: Emin Martinian <emin.martin...@gmail.com>
Date: Tue, 20 May 2025 11:24:27 -0400
Subject: [PATCH] Convert SVG to PDF on latex export

* ox-latex.el (org-export-latex-link-svg, org-latex--inline-image): Convert SVG to PDF on latex export.
(org-latex--inline-image): Call new org-export-latex-link-svg to
convert SVG to PDF as controlled by new org-latex-svg-to-pdf-cmd variable.

The current SVG handling uses `\includesvg` which seems brittle, does
not work for me, and seems to require inkscape. If we are going to
require inkscape, it seems cleaner to convert SVG to PDF and just
`\includegraphics` instead of `\includesvg`.
---
 lisp/ox-latex.el | 59 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 51 insertions(+), 8 deletions(-)

diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 2867cc695..e6af41d2f 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -2842,6 +2842,45 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
 (defun org-latex-image-link-filter (data _backend info)
   (org-export-insert-image-links data info org-latex-inline-image-rules))
 
+(defcustom org-latex-svg-to-pdf-cmd
+  (if (executable-find "inkscape")
+      "inkscape %f --export-filename=%o"
+    (if (executable-find "rsvg-convert")
+        "rsvg-convert -f pdf -o %o %f"))
+  "Command to run to convert SVG file to PDF.
+Use %f as the file to convert and %o as the output file.
+For example, \"inkscape %f --export-filename=%o\" would use inkscape.
+If you do not want SVG to PDF conversion, set this to \"no\"
+or \"includesvg\" otherwise a warning will be generated on export."
+  :group 'org-export-latex :type 'string
+  )
+
+(defun org-export-latex-link-svg (svg-file)
+  "Export SVG links by converting them to PDF.
+SVG-FILE is the path to the SVG file to convert.  You can customize
+the org-latex-svg-to-pdf-cmd to control the conversion program used."
+  (if (member org-latex-svg-to-pdf-cmd '(nil "no" "includesvg"))
+      (if (not org-latex-svg-to-pdf-cmd) ;; not explicitly set
+          (display-warning "Variable %s not set so using falling back to %s"
+                           "org-latex-svg-to-pdf-cmd" "\\includesvg"))
+    (let* ((pdf-file (concat (file-name-sans-extension svg-file) ".pdf"))
+           (replaced-cmd
+            (replace-regexp-in-string
+             "%o" pdf-file (replace-regexp-in-string
+                            "%f" svg-file org-latex-svg-to-pdf-cmd)))
+           (cmd-split (split-string-shell-command replaced-cmd))
+           (cmd (car cmd-split))
+           (arg-list (cdr cmd-split)))
+      ;; Convert SVG to PDF if needed
+      (when (and (file-exists-p svg-file)
+                 (or (not (file-exists-p pdf-file))
+		     (file-newer-than-file-p svg-file pdf-file)))
+        (message "Converting %s to %s for LaTeX export via: %s %s"
+                 svg-file pdf-file cmd arg-list)
+        (apply 'call-process cmd nil nil nil arg-list)
+        ))))
+
+
 (defun org-latex--inline-image (link info)
   "Return LaTeX code for an inline image.
 LINK is the link pointing to the inline image.  INFO is a plist
@@ -2966,14 +3005,18 @@ used as a communication channel."
                         (concat "\\detokenize{" path "}")
                       path)))
       (when (equal filetype "svg")
-	(setq image-code (replace-regexp-in-string "^\\\\includegraphics"
-						   "\\includesvg"
-						   image-code
-						   nil t))
-	(setq image-code (replace-regexp-in-string "\\.svg}"
-						   "}"
-						   image-code
-						   nil t))))
+	(org-export-latex-link-svg path)
+        (if (file-exists-p  ;; check if we converted the svg to pdf
+             (concat (file-name-sans-extension path) ".pdf"))
+	    (setq image-code (replace-regexp-in-string "\\.svg}"
+						       "}"
+						       image-code
+						       nil t))
+          ;; if we did not create a PDF of the SVG, then try to includesvg
+          (setq image-code (replace-regexp-in-string "^\\\\includegraphics"
+                                                     "\\includesvg"
+						     image-code
+						     nil t)))))
     ;; Return proper string, depending on FLOAT.
     (pcase float
       ((and (pred stringp) env-string)
-- 
2.34.1

Reply via email to