In org mode, is there a way to define how #+CAPTION: ... would work for custom link types? i.e, make org refer to them as images.

I created a custom link type called tex-fig (using org-link-set-parameters, as described here) that has custom behaviors when exporting to LaTeX and HTML, and I'd like to have figure captions for these tex-fig links. Currently, just doing

#+CAPTION: caption caption

doesn't work when exporting to either backend. How can I define caption/float behavior for custom link types?

I've searched for hours, and it seems that the caption is handled through element properties, which are inaccessible through the :export callback when defining links by org-link-set-parameters (as the callback is given only literal strings, not elements or positions in the document). What are the alternative ways?

2 Answers 2


You posted already the solution for the HTML backend. So I will address only the LaTeX backend here.

Pittingly, you did not describe how you want to export tex-fig links to LaTeX. I assume here you want to use \import{...} for such figures as the org LaTeX export does for pgf figures.

For that case we can just re-use the .pgf branch of org-latex--inline-image for our purpose. We just have to take care that we

  1. provide the right arguments
  2. fake a .pgf file name which we correct in the resulting exported string

At first glance the code seems a bit bulky. But, the bits of the code are quite general. So, the gv setter for org-element-property can be used in general and I am surprised that the Org API didn't provide it already. Furthermore, my-org-let-info can be useful for other exporters as well.

(require 'org-element)

(defun my-org-export-tex-fig (path description backend)
  "Call the BACKEND specific tex-fig exporter.
The name of the exporter is `my-org-export-tex-fig:BACKEND'.
It is called with PATH and DESCRIPTION as arguments."
  (let ((sym (intern-soft (format "my-org-export-tex-fig:%s" backend))))
    (if sym
        (funcall sym path description)
      (user-error "Backend %s not implemented" backend))))

(defvar my-org-let-info nil
  "Save `info' arg of `org-latex-link'.")

(defun my-org-let-info (fun link desc info)
  "Save INFO locally in `my-org-latex-info'.
Just pass all args LINK, DESC, and INFO to FUN."
  (let ((my-org-let-info (list link info)))
    (funcall fun link desc info)))

(advice-add 'org-latex-link :around #'my-org-let-info)

 (lambda (property element value)
   (org-element-put-property element property value))

(defun my-org-export-tex-fig:latex (path description)
  "LaTeX specific tex-fig exporter.
Export org links of form [[tex-fig:PATH][DESCRIPTION]] to LaTeX."
  (cl-letf* ((link (nth 0 my-org-let-info))
             ((org-element-property :path link)
              (concat path ".pgf"))
             (info (nth 1 my-org-let-info))
             (ret (org-latex--inline-image link info)))
    (replace-regexp-in-string "\\\\input{.*?\\(\\.pgf\\)}" "" ret t t 1)))

 "tex-fig" :export #'my-org-export-tex-fig)

The code is tested with Emacs 26.3 called as emacs -Q.


Well, I've succeeded in HTML exporting by simply telling it that tex-fig should be treated as an image:

(add-to-list 'org-html-inline-image-rules
             (cons "tex-fig" "\\.tex"))

But there seem to be no way to do it in LaTeX. I've read the source code, and while exporting a link through LaTeX it first checks if the link can be exported through a custom protocol, and only if not it tries as an image - so there is no way to export a custom link AS an image. This might not be the intended behavior...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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