GitHub-like Markdown preview with Emacs

This post describes how to set up Markdown live previews with Emacs.

What I want to accomplish

  • Live preview in the web browser
  • Update preview as you type
  • GitHub look

How to (using use-package)

Editing

I use markdown-mode for editing Markdown files in Emacs.

(use-package markdown-mode
  :ensure t
  :mode ("\\.md\\'" . gfm-mode)
  :commands (markdown-mode gfm-mode)
  :config
  (setq markdown-command "pandoc -t html5"))

Pandoc is used for HTML rendering. So make sure you have it installed or change the markdown-command.

Preview

impatient-mode takes the content of your buffer, passes it through a filter an serves the result via simple-httpd HTTP server.

First install both packages.

(use-package simple-httpd
  :ensure t
  :config
  (setq httpd-port 7070)
  (setq httpd-host (system-name)))

(use-package impatient-mode
  :ensure t
  :commands impatient-mode)

Now create a filter function to process the Markdown buffer.

(defun my-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 = \"https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.min.css\"/>
<body><article class=\"markdown-body\" style=\"box-sizing: border-box;min-width: 200px;max-width: 980px;margin: 0 auto;padding: 45px;\">%s</article></body></html>" (buffer-string))))
   (current-buffer)))

The function uses the markdown command from markdown-mode to generate HTML content. To mimic the look of GitHub, it uses the CSS from github-markdown-css.

Last but not least create a function to show preview.

(defun my-markdown-preview ()
  "Preview markdown."
  (interactive)
  (unless (process-status "httpd")
    (httpd-start))
  (impatient-mode)
  (imp-set-user-filter 'my-markdown-filter)
  (imp-visit-buffer))

Run my-markdown-preview in any Markdown buffer, it will open a new window in your browser and update it as you type.

Alternatives

There are some other packages that also provide live previews, but didn’t work out for me.