Include inline SVGs in Org Mode HTML and Markdown exports
Posted: - Modified: | emacs, org, images- : Fixed descriptions.
- : Fixed path when inlining file URLs.
- : Now I can specify
#+ATTR_HTML :data-link tto make it link instead of include. - : Whoops, forgot to make sure ox-11ty is also covered.
In my Org Mode HTML and Markdown exports, I
usually want to include SVGs inline so that I can
use links. Sometimes I also want to use Javascript
and CSS to modify elements within the images. I
used to use a my-include: link to do this, but I
realized that I can also modify this behaviour by
making my own functions that call org-html-link
or org-md-link and then put those functions in
org-export-backend-transcoders.
Here is an example of an SVG:
digraph g {
rankdir=LR;
node [fontcolor="#000000",fontname="Roboto,Arial,sans-serif"];
edge [fontcolor="#000000",fontname="Roboto,Arial,sans-serif"];
Graphviz -> "Org Mode" [label="SVG"];
"Org Mode" -> {HTML Markdown};
Graphviz[URL="https://graphviz.org",fontcolor="blue"];
}
The following code overrides HTML and Markdown exports to include SVGs.
;;;###autoload
(defun my-ox-link-path (link _ info)
(let* ((raw-path (org-element-property :path link)))
(setq raw-path
(org-export-file-uri
(org-publish-file-relative-name raw-path info)))
;; Possibly append `:html-link-home' to relative file
;; name.
(let ((home (and (plist-get info :html-link-home)
(org-trim (plist-get info :html-link-home)))))
(when (and home
(plist-get info :html-link-use-abs-url)
(not (file-name-absolute-p raw-path)))
(setq raw-path (concat (file-name-as-directory home) raw-path))))
raw-path))
;;;###autoload
(defun my-org-html-link (link desc info)
(if (and
(string= (org-element-property :type link) "file")
(not (plist-get (org-export-read-attribute :attr_html (org-element-parent-element link))
:data-link))
(org-export-inline-image-p link (plist-get info :html-inline-image-rules)))
(let ((path (org-element-property :path link))
(attr (org-export-read-attribute :attr_html (org-element-parent-element link))))
(if (string= (file-name-extension path) "svg")
(with-temp-buffer
(set-buffer-multibyte t)
(insert-file-contents path)
(if attr
(replace-regexp-in-string
"<svg "
(concat
"<svg "
(org-html--make-attribute-string attr)
" ")
(buffer-string))
(buffer-string)))
(org-html-link link desc info)))
(org-html-link link desc info)))
;;;###autoload
(defun my-org-md-link (link desc info)
(if (and (string= (org-element-property :type link) "file")
(not (plist-get (org-export-read-attribute :attr_html (org-element-parent-element link))
:data-link)))
(let ((path (org-element-property :path link)))
(if (string= (file-name-extension path) "svg")
(with-temp-buffer
(insert-file-contents-literally path)
(buffer-string))
(org-md-link link desc info)))
(org-md-link link desc info)))
;;;###autoload
(defun my-org-11ty-link (link desc info)
(if (and (string= (org-element-property :type link) "file")
(not (plist-get (org-export-read-attribute :attr_html (org-element-parent-element link))
:data-link))
(not desc))
(let ((path (org-element-property :path link))
(attr (org-export-read-attribute :attr_html (org-element-parent-element link))))
(if (string= (file-name-extension path) "svg")
(with-temp-buffer
(set-buffer-multibyte t)
(insert-file-contents path)
(if attr
(replace-regexp-in-string
"<svg "
(concat
"<svg "
(org-html--make-attribute-string attr)
" ")
(buffer-string))
(buffer-string)))
(org-11ty-link link desc info)))
(org-11ty-link link desc info)))
(with-eval-after-load 'ox-html
(setf
(alist-get 'link (org-export-backend-transcoders (org-export-get-backend 'html)))
'my-org-html-link))
(with-eval-after-load 'ox-md
(setf
(alist-get 'link (org-export-backend-transcoders (org-export-get-backend 'md)))
'my-org-md-link))
(with-eval-after-load 'ox-11ty
(setf
(alist-get 'link (org-export-backend-transcoders (org-export-get-backend '11ty)))
'my-org-11ty-link))
This is part of my Emacs configuration.
You can e-mail me at sacha@sachachua.com.