Markdown in Emacs: Live Preview, Math and Images
Ping Zhou, 2020-11-11
Introduction
Emacs has a Markdown mode, but I need a more comprehensive setup with features like:
- Live preview window
- Rendering of math equations
- Rendering of local and remote images
Basically I need a setup that provides similar functionality as VS Code + Markdown extensions.
Install dependencies
Emacs packages needed:
- markdown-mode
- markdown-mode
- simple-httpd
- impatient-mode
Install pandoc:
brew install pandoc
Get MathJax:
git clone https://github.com/mathjax/MathJax.git mathjax
Configure Emacs
Markdown settings
Add these customization to Emacs config:
markdown-command: "/usr/local/bin/pandoc --mathjax"
(assuming pandoc is installed at /usr/local/bin)markdown-display-remote-images: t
markdown-enable-math: t
This can be done with Emacs Customization UI (M-x customize), or by manually editing custom-set-variables:
(custom-set-variables ;; ;; Other custom values... ;; '(markdown-command "/usr/local/bin/pandoc --mathjax") '(markdown-display-remote-images t) '(markdown-enable-math t) ;; ;; ... )
Simple HTTPD
Add this to Emacs config file to enable simple-httpd (a simple Web server inside Emacs):
(require 'simple-httpd) (use-package simple-httpd :ensure t :config (setq httpd-port 7070))
This will configure the simple-httpd to run on localhost:7070.
Default root folder of simple-httpd is ~/public_html
. This can also be customized by changing the httpd-root
variable. For example, I set it to ~/www:
;; Add this to custom-set-variables: ;; '(httpd-root "~/www")
Impatient Mode
Add these to Emacs config file to configure markdown filter for impatient-mode:
(defun markdown-filter (buffer) (princ (with-temp-buffer (let ((tmp (buffer-name))) (set-buffer buffer) (set-buffer (markdown tmp)) (format "<!DOCTYPE html><html><title>Markdown preview</title> <body><article class=\"markdown-body\" style=\"box-sizing: border-box;min-width: 200px;max-width: 800px;margin: 0 auto;padding: 45px;\">%s</article></body><script src=\"/mathjax/es5/tex-chtml-full.js\"></script></html>" (buffer-string)))) (current-buffer))) (defun markdown-live-preview () "Preview markdown." (interactive) (unless (process-status "httpd") (httpd-start)) (impatient-mode) (imp-set-user-filter 'my-markdown-filter) (imp-visit-buffer))
The filter will insert MathJax script in the generated HTML so that math symbols/equations will be properly rendered.
You can point it to any URL that hosts MathJax (if you trust the source), but I decide to host MathJax locally in simple-httpd:
<script src=\"/mathjax/es5/tex-chtml-full.js\"></script>
So I need to copy MathJax repo over to the root folder of simple-httpd:
cp -rf ~/mathjax ~/www
Now MathJax script should be available to impatient-mode.
(Optional) Add GitHub Style
The rendered HTML seems to be plain. So I added a GitHub-style CSS to the impatient-mode filter:
git clone https://github.com/sindresorhus/github-markdown-css.git cp github-markdown-css/github-markdown.css ~/www
The CSS file is also hosted locally in simple-httpd.
Add this line to my filter:
<link rel=\"stylesheet\" href = \"/github-markdown.css\"/>
Now the filter is like this:
(defun markdown-filter (buffer) (princ (with-temp-buffer (let ((tmp (buffer-name))) (set-buffer buffer) (set-buffer (markdown tmp)) (format "<!DOCTYPE html><html><title>Markdown preview</title><link rel=\"stylesheet\" href = \"/github-markdown.css\"/> <body><article class=\"markdown-body\" style=\"box-sizing: border-box;min-width: 200px;max-width: 800px;margin: 0 auto;padding: 45px;\">%s</article></body><script src=\"/mathjax/es5/tex-chtml-full.js\"></script></html>" (buffer-string)))) (current-buffer)))
Test Run
Live Preview
Open a Markdown file, and then start live preview:
M-x markdown-live-preview
A new page will be opened in browser, showing the live preview.
As you type in the Markdown file, live preview also changes accordingly.
Images
To add images, just insert the <img> tag in Markdown:
<img src="./test.png" width="600" />
This relative path works for impatient-mode too (i.e. it will look for test.png in the same folder as current Markdown file).
Math Equations
Try math equations in Markdown:
$$ \begin{pmatrix} aa & bb \\ cc & dd \\ \end{pmatrix} \otimes \begin{pmatrix} ee & ff \\ gg & hh \\ \end{pmatrix} $$
Rendered like this in live preview:
\begin{matrix} \begin{pmatrix} aa & bb \\ cc & dd \\ \end{pmatrix} \otimes \begin{pmatrix} ee & ff \\ gg & hh \\ \end{pmatrix} \end{matrix}Looking good!