emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: svg file from tikz picture


From: Akira Kyle
Subject: Re: svg file from tikz picture
Date: Thu, 22 Sep 2022 20:28:57 -0600

I've been using the attached patch for the last few years and I've meaning to 
send it here/start a discussion about ob-latex.el since I used it pretty much 
daily to write tikz figures in org mode. So I'm glad to see this discussion has 
been started!

I've found it to be incredibly productive to use babel to develop tikz diagrams 
as I can make come changes and quickly `org-ctrl-c-ctrl-c` to render them in 
the same buffer.

I think when I made this patch I had been caught by some of the quirks of the 
svg export. For example, sometimes I would have some latex equation which I use 
~org-latex-preview~ on as I was writing it, but then it would fail to render as 
mathjax upon html export since I would use some latex package that isn't 
available under mathjax. So by using ob-latex I could easily fix this by using 
the ~:file .svg~ header and get a nice html export. However due to the 
different way of assembling the ~.tex~ file sometimes ~org-latex-preview~ would 
work but ob-latex wouldn't. I think my use case may be fairly common and so I 
think ob-latex really should be updated so svg uses the ~org-latex-preview~ 
code. o

Also I think the ~.tikz~ extension doesn't really make any sense since one 
really can but arbitrary tex code in such a block, and I think that's why I 
renamed it in my patch. However I'm now realizing that this evaluation method 
probably doesn't make much since `:tangle` will already do this, with the added 
benefit of handling noweb references correctly. So perhaps this should be 
removed and document using tangling in lieu of ~:file *.tikz~?

PS: I'm not currently subbed to this mailing list, so please try to cc me

>From 5d94745dfbe0858d4fd7d6530b821445b06d5013 Mon Sep 17 00:00:00 2001
From: Akira Kyle <akira@akirakyle.com>
Date: Tue, 4 Jan 2022 14:33:05 -0700
Subject: [PATCH] ob-latex: Create svg images the same way as png images

Also some cleanup of generation .html and .pdf files
---
 lisp/ob-latex.el | 161 +++++++++++++++--------------------------------
 1 file changed, 50 insertions(+), 111 deletions(-)

diff --git a/lisp/ob-latex.el b/lisp/ob-latex.el
index a86699e22..71b01058c 100644
--- a/lisp/ob-latex.el
+++ b/lisp/ob-latex.el
@@ -39,7 +39,7 @@
 
 (declare-function org-create-formula-image "org" (string tofile options buffer 
&optional type))
 (declare-function org-latex-compile "ox-latex" (texfile &optional snippet))
-(declare-function org-latex-guess-inputenc "ox-latex" (header))
+(declare-function org-latex-make-preamble "ox-latex" (info &optional template 
snippet?))
 (declare-function org-splice-latex-header "org" (tpl def-pkg pkg snippets-p 
&optional extra))
 (declare-function org-at-heading-p "org" (&optional _))
 (declare-function org-back-to-heading "org" (&optional invisible-ok))
@@ -115,12 +115,6 @@ exporting the literal LaTeX source."
   :group 'org-babel
   :type 'string)
 
-(defcustom org-babel-latex-htlatex-packages
-  '("[usenames]{color}" "{tikz}" "{color}" "{listings}" "{amsmath}")
-  "Packages to use for htlatex export."
-  :group 'org-babel
-  :type '(repeat (string)))
-
 (defun org-babel-expand-body:latex (body params)
   "Expand BODY according to PARAMS, return the expanded body."
   (mapc (lambda (pair) ;; replace variables
@@ -142,132 +136,82 @@ This function is called by 
`org-babel-execute-src-block'."
             (extension (file-name-extension out-file))
             (tex-file (org-babel-temp-file "latex-" ".tex"))
             (border (cdr (assq :border params)))
-            (imagemagick (cdr (assq :imagemagick params)))
-            (im-in-options (cdr (assq :iminoptions params)))
-            (im-out-options (cdr (assq :imoutoptions params)))
             (fit (or (cdr (assq :fit params)) border))
             (height (and fit (cdr (assq :pdfheight params))))
             (width (and fit (cdr (assq :pdfwidth params))))
             (headers (cdr (assq :headers params)))
             (in-buffer (not (string= "no" (cdr (assq :buffer params)))))
+            (imagemagick (cdr (assq :imagemagick params)))
+            (im-in-options (cdr (assq :iminoptions params)))
+            (im-out-options (cdr (assq :imoutoptions params)))
             (org-latex-packages-alist
-             (append (cdr (assq :packages params)) org-latex-packages-alist)))
+             (append (cdr (assq :packages params)) org-latex-packages-alist))
+            (org-format-latex-header
+             (concat org-format-latex-header
+                     (mapconcat #'identity (cdr (assq :headers params)) "\n")
+                     (if fit "\n\\usepackage[active, tightpage]{preview}\n" "")
+                     (if border
+                         (format "\\setlength{\\PreviewBorder}{%s}" border) "")
+                     (if height
+                         (concat "\n" (format "\\pdfpageheight %s" height)) "")
+                     (if width
+                         (concat "\n" (format "\\pdfpagewidth %s" width)) "")))
+            (body (if fit 
+                      (concat "\n\\begin{preview}\n" body "\n\\end{preview}\n")
+                    body)))
         (cond
          ((and (string-suffix-p ".png" out-file) (not imagemagick))
           (let ((org-format-latex-header
                 (concat org-format-latex-header "\n"
                         (mapconcat #'identity headers "\n"))))
-           (org-create-formula-image
-             body out-file org-format-latex-options in-buffer)))
-        ((string= "svg" extension)
-         (with-temp-file tex-file
-           (insert (concat (funcall org-babel-latex-preamble params)
-                           (mapconcat #'identity headers "\n")
-                           (funcall org-babel-latex-begin-env params)
-                           body
-                           (funcall org-babel-latex-end-env params))))
-         (let ((tmp-pdf (org-babel-latex-tex-to-pdf tex-file)))
-            (let* ((log-buf (get-buffer-create "*Org Babel LaTeX Output*"))
-                   (err-msg "org babel latex failed")
-                   (img-out (org-compile-file
-                            tmp-pdf
-                             (list org-babel-latex-pdf-svg-process)
-                             extension err-msg log-buf)))
-              (shell-command (format "mv %s %s" img-out out-file)))))
-         ((string-suffix-p ".tikz" out-file)
+          (org-create-formula-image
+            body out-file org-format-latex-options in-buffer 'dvipng)))
+         ((and (string= "svg" extension) (not imagemagick))
+          (org-create-formula-image
+           body out-file org-format-latex-options in-buffer 'dvisvgm))
+         ((string-suffix-p ".tex" out-file)
          (when (file-exists-p out-file) (delete-file out-file))
          (with-temp-file out-file
            (insert body)))
-        ((and (string= "html" extension)
+        ((and (string= "html" extension) (not imagemagick)
               (executable-find org-babel-latex-htlatex))
-         ;; TODO: this is a very different way of generating the
-         ;; frame latex document than in the pdf case.  Ideally, both
-         ;; would be unified.  This would prevent bugs creeping in
-         ;; such as the one fixed on Aug 16 2014 whereby :headers was
-         ;; not included in the SVG/HTML case.
-         (with-temp-file tex-file
-           (insert (concat
-                    "\\documentclass[preview]{standalone}
-\\def\\pgfsysdriver{pgfsys-tex4ht.def}
-"
-                    (mapconcat (lambda (pkg)
-                                 (concat "\\usepackage" pkg))
-                               org-babel-latex-htlatex-packages
-                               "\n")
-                    (if headers
-                        (concat "\n"
-                                (if (listp headers)
-                                    (mapconcat #'identity headers "\n")
-                                  headers) "\n")
-                      "")
-                    "\\begin{document}"
-                    body
-                    "\\end{document}")))
+         (let ((org-format-latex-header
+                (concat org-format-latex-header
+                        "\\def\\pgfsysdriver{pgfsys-tex4ht.def}")))
+           (org-babel-latex-format-tex tex-file body))
          (when (file-exists-p out-file) (delete-file out-file))
          (let ((default-directory (file-name-directory tex-file)))
            (shell-command (format "%s %s" org-babel-latex-htlatex tex-file)))
-         (cond
-          ((file-exists-p (concat (file-name-sans-extension tex-file) 
"-1.svg"))
-           (if (string-suffix-p ".svg" out-file)
-               (progn
-                 (shell-command "pwd")
-                 (shell-command (format "mv %s %s"
-                                        (concat (file-name-sans-extension 
tex-file) "-1.svg")
-                                        out-file)))
-             (error "SVG file produced but HTML file requested")))
-          ((file-exists-p (concat (file-name-sans-extension tex-file) ".html"))
-           (if (string-suffix-p ".html" out-file)
-               (shell-command "mv %s %s"
-                              (concat (file-name-sans-extension tex-file)
-                                      ".html")
-                              out-file)
-             (error "HTML file produced but SVG file requested")))))
+         (rename-file (concat (file-name-sans-extension tex-file) ".html")
+                        out-file))
         ((or (string= "pdf" extension) imagemagick)
-         (with-temp-file tex-file
-           (require 'ox-latex)
-           (insert
-            (org-latex-guess-inputenc
-             (org-splice-latex-header
-              org-format-latex-header
-              (delq
-               nil
-               (mapcar
-                (lambda (el)
-                  (unless (and (listp el) (string= "hyperref" (cadr el)))
-                    el))
-                org-latex-default-packages-alist))
-              org-latex-packages-alist
-              nil))
-            (if fit "\n\\usepackage[active, tightpage]{preview}\n" "")
-            (if border (format "\\setlength{\\PreviewBorder}{%s}" border) "")
-            (if height (concat "\n" (format "\\pdfpageheight %s" height)) "")
-            (if width  (concat "\n" (format "\\pdfpagewidth %s" width))   "")
-            (if headers
-                (concat "\n"
-                        (if (listp headers)
-                            (mapconcat #'identity headers "\n")
-                          headers) "\n")
-              "")
-            (if fit
-                (concat "\n\\begin{document}\n\\begin{preview}\n" body
-                        "\n\\end{preview}\n\\end{document}\n")
-              (concat "\n\\begin{document}\n" body "\n\\end{document}\n"))))
-          (when (file-exists-p out-file) (delete-file out-file))
-         (let ((transient-pdf-file (org-babel-latex-tex-to-pdf tex-file)))
+         (org-babel-latex-format-tex tex-file body)
+         (let ((default-directory (file-name-directory tex-file)))
+           (org-latex-compile tex-file))
+         (let ((transient-pdf-file
+                (concat (file-name-sans-extension tex-file) ".pdf")))
+           (when (file-exists-p out-file) (delete-file out-file))
            (cond
             ((string= "pdf" extension)
              (rename-file transient-pdf-file out-file))
             (imagemagick
              (org-babel-latex-convert-pdf
-              transient-pdf-file out-file im-in-options im-out-options)
-             (when (file-exists-p transient-pdf-file)
-               (delete-file transient-pdf-file)))
-            (t
-             (error "Can not create %s files, please specify a .png or .pdf 
file or try the :imagemagick header argument"
-                    extension))))))
+              transient-pdf-file out-file im-in-options im-out-options)))))
+        (t
+         (error "Can't create %s files, please specify a .tex, .pdf, .png, or 
.svg file, or try the :imagemagick header argument"
+                extension)))
         nil) ;; signal that output has already been written to file
     body))
 
+(defun org-babel-latex-format-tex (tex-file body)
+  "Generate a temporary tex file from execute params."
+  (with-temp-file tex-file
+    (insert
+     (org-latex-make-preamble
+      (org-export-get-environment (org-export-get-backend 'latex))
+      org-format-latex-header)
+     (concat "\n\\begin{document}\n" body "\n\\end{document}\n"))))
+
 (defun org-babel-latex-convert-pdf (pdffile out-file im-in-options 
im-out-options)
   "Generate a file from a pdf file using imagemagick."
   (let ((cmd (concat "convert " im-in-options " " pdffile " "
@@ -275,11 +219,6 @@ This function is called by `org-babel-execute-src-block'."
     (message "Converting pdffile file %s..." cmd)
     (shell-command cmd)))
 
-(defun org-babel-latex-tex-to-pdf (file)
-  "Generate a pdf file according to the contents FILE."
-  (require 'ox-latex)
-  (org-latex-compile file))
-
 (defun org-babel-prep-session:latex (_session _params)
   "Return an error because LaTeX doesn't support sessions."
   (error "LaTeX does not support sessions"))
-- 
2.36.1


reply via email to

[Prev in Thread] Current Thread [Next in Thread]