1

This question https://emacs.stackexchange.com/a/27065/13217 explains perfectly how to embed base64 image inside of an HTML exported document, and it works great.

I wonder now how could I automate this process for each image file referenced in my document ?

Adding a pre-export task replacing all file references with the base64 encoded image seems the way to go, but I don't have any practice with elisp. Can anyone help me out ?

I found out some ideas in this documentation : http://orgmode.org/manual/Advanced-configuration.html which seems a good starting point. But I fail to manipulate correctly the input text.

This is what I came out with :

(defun html-base64-images (text backend info)
  (when (org-export-derived-backend-p backend 'html)
    (message "The text is: %S" text)
    (setq filename (replace-regexp-in-string "\\\"\(.*\)+\\\"" "\1" text))
    (message "The filename is: %S" filename)
    (setq output-text (replace-regexp-in-string "img src=\".*\"" "img src=\"data:image/png;base64," text))
    (concat output-text tob64(filename))
    (message "The new text is %S" output-text)
    output-text
    )
  )

(add-to-list 'org-export-filter-link-functions
             'html-base64-images)

So in the Messages buffer I can see my messages, but I have problems to manipulate the TEXT string correctly. The output looks like :

The text is: "<img src=\"./GN_moissonnage2.png\" alt=\"GN_moissonnage2.png\" />"
The filename is: "<img src=\"./GN_moissonnage2.png\" alt=\"GN_moissonnage2.png\" />"
The new text is "<img src=\"data:image/png;base64, />"

I need to :

  1. get the filename
  2. replace it with my base64 URI

I'm not used to elisp at all ... maybe I'm doing it the wrong way ...

  • Can you show the output that you get when a link is processed? – NickD Oct 12 '17 at 2:23
  • You probably don't want to use replace-regexp-in-string at all: you want to extract the filename somehow (that's why I wanted to see the output: that'll depend on what the text looks like) and you want to construct the output string from scratch, not replace anything in text: the (format ...) in the linked answer is probably close to what you need (with the extracted filename replacing the hardwired name that's used in that answer). – NickD Oct 12 '17 at 2:35
2

Thanks to @Nick's usefull comments, I managed to get what I wanted.

This function will insert base64 images in my HTML exported org document, making it completely standalone (and quite bigger of course).

(defun tob64 (filename)
  "Transforms a file FILENAME in base64."
  (base64-encode-string
   (with-temp-buffer
     (insert-file-contents filename)
     (buffer-string))))

(defun html-base64-images (text backend info)
  "Replaces files links in TEXT with appropriate html string when BACKEND is html. INFO is ignored."
  (when (org-export-derived-backend-p backend 'html)
    (when (string-match "^<img" text)
      (let ((filename (replace-regexp-in-string ".*=\"" "" (replace-regexp-in-string "\\\" .*" "" text))))
      (format  "<img src=\"data:image/png;base64,%s\">" (tob64 filename)))
      )
    )
  )

(add-to-list 'org-export-filter-link-functions 'html-base64-images)
  • NIce! I still think that the extraction of the filename should be simpler but I can't argue too much with "it works" :-) – NickD Oct 12 '17 at 12:15
  • 1
    One more thing: you should use a (let ((filename ...)) (format ...)) form so that filename is locally bound in the function. See Local Variables in the Emacs Lisp manual. – NickD Oct 12 '17 at 12:24

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.