Using Emacs Lisp to export TXT/EPUB/PDF from Org Mode to the Supernote via Browse and Access

| supernote, org, emacs

I've been experimenting with the Supernote's Browse and Access feature because I want to be able to upload files quickly instead of waiting for Dropbox to synchronize. First, I want to store the IP address in a variable:

my-supernote-ip-address
(defvar my-supernote-ip-address "192.168.1.221")

Here's how to upload:

(defun my-supernote-upload (filename &optional supernote-path)
  (interactive "FFile: ")
  (setq supernote-path (or supernote-path "/INBOX"))
  (let* ((boundary (mml-compute-boundary '()))
         (url-request-method "POST")
         (url-request-extra-headers
          `(("Content-Type" . ,(format "multipart/form-data; boundary=%s" boundary))))
         (url-request-data
          (mm-url-encode-multipart-form-data
           `(("file" . (("name" . "file")
                        ("filename" . ,(file-name-nondirectory filename))
                        ("content-type" . "application/octet-stream")
                        ("filedata" . ,(with-temp-buffer
                                         (insert-file-contents-literally filename)
                                         (buffer-substring-no-properties (point-min) (point-max)))))))
           boundary)))
    (with-current-buffer
        (url-retrieve-synchronously
         (format "http://%s:8089%s" my-supernote-ip-address supernote-path))
      (re-search-backward "^$")
      (prog1 (json-read)
        (kill-buffer)))))

HTML isn't supported. Text works, but it doesn't support annotation. PDF or EPUB could work. It would make sense to register this as an export backend so that I can call it as part of the usual export process.

(defun my-supernote-org-upload-as-text (&optional async subtree visible-only body-only ext-plist)
  "Export Org format, but save it with a .txt extension."
  (interactive (list nil current-prefix-arg))
  (let ((filename (org-export-output-file-name ".txt" subtree))
        (text (org-export-as 'org subtree visible-only body-only ext-plist)))
    ;; consider copying instead of exporting so that #+begin_export html etc. is preserved
    (with-temp-file filename
      (insert text))
    (my-supernote-upload filename)))

(defun my-supernote-org-upload-as-pdf (&optional async subtree visible-only body-only ext-plist)
  (interactive (list nil current-prefix-arg))
  (my-supernote-upload (org-latex-export-to-pdf async subtree visible-only body-only ext-plist)))

(defun my-supernote-org-upload-as-epub (&optional async subtree visible-only body-only ext-plist)
  (interactive (list nil current-prefix-arg))
  (my-supernote-upload (org-epub-export-to-epub async subtree visible-only ext-plist)))

(org-export-define-backend
    'supernote nil
    :menu-entry '(?s "Supernote"
                     ((?s "as PDF" my-supernote-org-upload-as-pdf)
                      (?e "as EPUB" my-supernote-org-upload-as-epub)
                      (?o "as Org" my-supernote-org-upload-as-text))))

Adding this line to my Org file allows me to use \spacing{1.5} for 1.5 line spacing, so I can write in more annotations..

#+LATEX_HEADER+: \usepackage{setspace}

Sometimes I use custom blocks for HTML classes. When LaTeX complains about undefined environments, I can define them like this:

#+LATEX_HEADER+: \newenvironment{whatever_my_custom_environment_is_called}

Now I can export a subtree or file to my Supernote for easy review.

I wonder if multimodal AI models can handle annotated images with editing marks…

This is part of my Emacs configuration.
View org source for this post
You can comment with Disqus or you can e-mail me at sacha@sachachua.com.