Seamless Writing and Rendering with Emacs Org
One nice feature of .org
files is their easy export to HTML for
viewing on any browser. Recently, I realized that it is even possible
to seamlessly integrate writing and exporting processes by telling
Emacs to export the .org
file every time I save it. Then by launching
a local server with autoreload, I can immediately preview the HTML
version of the .org
file. This is particular useful in writing LaTeX
equations, where it is very hard to imagine what you are writign
without renderin.
The basic idea is creating a customized minor mode in which the
exporting function is added to the after-save-hook
. Combining with the
prettify-symbols-mode
(discussed in the previous post), writing
formulae in Emacs turns out to be enjoyable for me.
Above is the final effect (the vedio was recorded and inserted via Loom). It involves several simple components:
- A minor mode called
dms/blog-mode
in which the file gets exported to HTML after saving; - A local server which can reload the html page when it changes;
- (Optional) The KaTeX framework for math rendering to replace MathJax.
A new minor mode
Create such a new minor mode is very simple.
(define-minor-mode dms/blog-mode "Automatically export Org files to HTML after saving. This mode also enables the prettify-symbols-mode." :lighter " dms/blog" (if dms/blog-mode (add-hook 'after-save-hook 'org-html-export-to-html 0 'make-it-local) (remove-hook 'after-save-hook 'org-html-export-to-html 'make-it-local)) (prettify-symbols-mode 1) )
As any function in after-save-hook
will be executed after saving, I
add org-html-export-to-html
to it when enering this new minor mode and
remove it when exiting. In either case, the prettify-symbols-mode
is
enabled.
A simple local server with autoreload
As the exported file is only a static HTML page, it will not be updated when its content changes. So it is necessary to find a way to refresh the page after updates. Fortunately, there is a nice python project python-livereload which can start a simple local http server, watch a file/directory and reload pages on changes.
After installation, I can use a simple command to launch a server and
host a static HTML page, e.g., /tmp/temporary-drafts.html
on the URL
http://localhost:35729//tmp/temporary-drafts.html
(35729 is the
default port used by livereload
; see its doc for more details).
livereload -t /tmp/temporary-drafts.html
Replace MathJax with KaTeX
By default, Emacs uses MathJax in the exported HTML file to rende math equations. But personally I feel KaTeX is smoother and faster. So I use the following snippet to disable MathJax and insert KaTeX scripts in the head; see also the doc for how to included it in HTML.
(use-package org ;; replace MathJax with KaTeX :config (setq org-html-mathjax-template "") (setq org-html-head (concat org-html-head "<!-- Math Support by KaTeX --> <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css\" integrity=\"sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV\" crossorigin=\"anonymous\"> <!-- The loading of KaTeX is deferred to speed up page rendering --> <script defer src=\"https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js\" integrity=\"sha384-XjKyOOlGwcjNTAIQHIpgOno0Hl1YQqzUOEleOLALmuqehneUG+vnGctmUb0ZY0l8\" crossorigin=\"anonymous\"></script> <!-- To automatically render math in text elements, include the auto-render extension: --> <script defer src=\"https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js\" integrity=\"sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05\" crossorigin=\"anonymous\" onload=\"renderMathInElement(document.body);\"></script>")) )
If you prefer MathJax, I recommend modifying the default value of
org-html-mathjax-template
to enable the lazy typesetting feature; see the MathJax doc.