5

How do I specify different actions for different export backends in org-mode?

To be more specific, I would like to export an pdf figure in latex export, while using a png in html export (in fact, a png thumbnail linking to the pdf, if that is of relevance):

#+CAPTION: cation of figure
#+NAME:    myfig
# case export to latex: [[file:./figure.pdf]]
# case export to html:  [[file:./figure.pdf][file:./figure.png]]

I tried macros and this answer, which did not work. There are also answers on similar cases for tikz pdf/svg/png export like this thread, which do not seem to be transferable to my case.

Note: I initially posted this question on stackoverflow. It occured to me later that emacs stackexchange is a more appropriate site for this question. So I deleted it on stackoverflow (there were no answers) to repost it here.

2
  • In some cases you can use things like #+begin_html or by-backend macro (I think I picked it from Org wiki somewhere), example here: raw.githubusercontent.com/wvxvw/introduction-to-data-structures/… . But I'm unaware of general purpose mechanism for this.
    – wvxvw
    Dec 12 '16 at 16:32
  • @wvxvw: The #+begin_html/#+begin_latex blocks would be fine for a single figure or so, but I have plenty in my document. However, searching for by-backend macros on google lead me to the solution, thank you!
    – lccopper
    Dec 13 '16 at 12:29
4

I finally found a way to do this, using a macro provided by fniessen:

#+MACRO: if-latex-else (eval (if (org-export-derived-backend-p org-export-current-backend 'latex) "$1" "$2"))

If more/other export-backends than LaTeX and HTML are used, a condition statement can be used instead:

#+MACRO: if-latex-html-else (eval (cond ((org-export-derived-backend-p org-export-current-backend 'latex) "$1") ((org-export-derived-backend-p org-export-current-backend 'html) "$2") (t "$3") ))

Usage would be something like

{{{if-latex-html-else([[file:./figure.pdf]], [[file:./figure.pdf][file:./figure.png]], /Figure *figure.pdf* is supposed to be here/)}}}

Not as short as a simple switch, but substantially better than providing native LaTeX/HTML/whatever code for every figure that is to be included.

1
  • 1
    Unfortunately this does not work anymore since org-mode 9.2. The code should now be written as #+MACRO: if-latex-else (eval (if (org-export-derived-backend-p org-export-current-backend 'latex) $1 $2)). This means that you have to rewrite your org-mode files for them to be exportable. Nov 20 '20 at 22:25
1

Using macros as the accepted answer is a great option, which I also used following this question. But there is one alternative that I started using and that some may prefer: define a src block with emacs-lisp and a call it with #+CALL for each figure we want to include.

It works like this, add the block below to your org-mode document (it can be inside a heading with the :noexport: tag) and change it according with your preferences.

#+NAME: get-filename-by-backend
#+begin_src emacs-lisp :var filename="default" :exports none :results raw
  (concat "[[file:"
          (case org-export-current-backend
            (html (concat filename ".svg"))
            (twbs (concat filename ".svg"))
            (latex (concat filename ".pdf"))
            (t (concat filename ".png")))
          "]]")
#+end_src

Now, whenever you want to include a figure just add something like

#+NAME: a_name_for_this_figure_call
#+CALL: get-filename-by-backend(filename="figs/my_nice_figure")

and execute the block with C-c C-c. This will add the result as

#+RESULTS: a_name_for_this_figure_call
[[file:figs/my_nice_figure.png]]

Now you can add #+NAME: figure_label, #+CAPTION: The figure caption., #+ATTR_LATEX: ..., etc above the #+RESULTS: line.

The trick here is that we get a png image when we are not exporting, which can be nicely displayed with org-toggle-inline-images. However, during the export the #+CALL: line is re-evaluated and we get a pdf image for latex export and an svg image for HTML export.

The advantage of this solution, compared with a macro solution, goes beyond just displaying the image inline. Since you can pass a variable to a src block that receives the result of another src block it means that you can have a src block using your preferred language that generates "backend dependent" export code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.