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