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 ...

skizo
  • 265
  • 2
  • 8
  • Can you show the output that you get when a link is processed? – NickD Oct 12 '17 at 02: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 02:35

1 Answers1

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)
skizo
  • 265
  • 2
  • 8
  • 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](https://www.gnu.org/software/emacs/manual/html_node/elisp/Local-Variables.html#Local-Variables) in the Emacs Lisp manual. – NickD Oct 12 '17 at 12:24