Live-reloading Pandoc + Reveal.js
I’ve been using markdown + pandoc + reveal.js to create presentations at work.
Pandoc doesn’t have a live-reload feature so I wrote a small script that watches for changes in the markdown file and recompiles the presentation.
fswatch
I decided to use fswatch to listen for changes in the markdown file.
fswatch -0 presentation.md | xargs -0 -I {} sh -c "pandoc --to revealjs -s --output presentation.html {}"
fswatch -0
watches for changes in the markdown file and outputs the name of the file that changed followed by the null character.xargs -0
reads null-terminated lines from stdin.xargs -I {}
replaces{}
in the following command with the input.pandoc --to revealjs -s --output presentation.html {}
compiles the markdown file to reveal.js.
This gets us compile-on-save, but we still need to refresh the browser to see the changes.
Websockets
We can extend the script to start a websocket server that sends a message to the browser when the markdown file changes.
I used websocat to start the websocket server from the command line.
fswatch -0 presentation.md | xargs -0 -I {} sh -c "pandoc --to revealjs -s --output presentation.html {} && echo reload" | websocat -s 56789
echo reload
is sent to stdout after the markdown file is compiled.websocat -s 56789
starts a websocket server on port 56789.
The echo message is piped to websocat.
Browser
Pandoc supports YAML frontmatter in markdown files. The header-includes
field
can be used to include arbitrary HTML in the <head>
tag of the generated HTML.
---
title: My presentation
header-includes: |
<script>
function connect() {
const ws = new WebSocket("ws://localhost:56789");
ws.onopen = () => setTimeout(() => ws.send("keepalive"), 30000);
ws.onclose = () => setTimeout(connect, 1000);
ws.onmessage = () => location.reload();
}
connect();
</script>---
This script connects to the websocket server and reloads the page when it receives any message. A keepalive message is sent every 30 seconds to keep the connection alive. When the connection is closed, the script tries to reconnect every second.
This is a really cursed hack but it got me up and running with the tools I already had.
Last modified 2023-08-19