David's Blog

Using reveal-md with emojis everywhere!

March 14, 2019

7 min read

Last time I presented you the awesome reveal-md tool that I use to create impressive technical slideshows.

One of the things I use too much is emojis. I tend to put them everywhere possible, for me they are like a form of modern ideograms that future generations will find etched on glass pyramids…


However, for the time being, I still have an issue with how emojis are supported.

Going back to reveal-md, when I exported to PDF, the emojis were broken, and the same thing happened for my Windows 7 co-workers when they were looking at the exported website or when I was presenting from that kind of OS.

Thus, I was in need of a way to transform emojis to images inside my presentations.

Time to present item number 9 on my “I ❤️ reveal” list of reveal’s preferred feature!


Preprocessor to the rescue

reveal-md has a preprocessor option that allow us to pass it a JavaScript file that will apply some code to change the markdown before presenting it. And, this my dear reader, is exactly what I needed to solve my emojis issue!

Combined with Twemoji, I could parse all my presentation’s markdown and convert emoji Unicode strings to image tags with SVG.



What is it?

It is an open source library made by Twitter. It contains their whole collection of emojis! There is also a JavaScript API that can parse text or DOM nodes to replace emoji Unicode characters with tags.

Here is the attribution:

Copyright 2018 Twitter, Inc and other contributors Code licensed under the MIT License: http://opensource.org/licenses/MIT Graphics licensed under CC-BY 4.0: https://creativecommons.org/licenses/by/4.0/

Thank you Twitter 😘


So, I installed it in my repo using:

npm install --save twemoji

Free the emojis!

Now we can look at how we will combine Twemoji with a reveal-md preprocessor to make the emojis free from the OS and browsers!

reveal-md Preprocessor using twemoji

The preprocessor is really simple:

// emoji2svgimg.js
const twemoji = require('twemoji');

module.exports = (markdown, options) => {
  return new Promise((resolve, reject) => {
    return resolve(
      twemoji.parse(markdown, {
        folder: 'svg',
        ext: '.svg'

As you see it returns the Promise that it will have transformed the markdown using twemoji.parse.

Wait a minute.


If you don’t know Promises, I urge you to go watch this YouTube video — MPJ is just 🤩

I also recommend to subscribe to his channel, all the content is stellar 💫.


For better antialiasing (because you can zoom with ALT+click using Reveal-md presentation mode) I used SVG with these special parser options:

twemoji.parse(markdown, {
        folder: 'svg',
        ext: '.svg'

using the preprocessor

To use this, append the --preprocessor command line option for reveal-md:

reveal-md presentation.md --preprocessor emoji2svgimg.js

Looking at my presentation, I saw a few regressions happening to the emojis: the CSS seemed wrong, and the animated fragments inside a slide was broken.

Fixing CSS

I had to tweak the CSS for the twemojis to have a size related to the font size. I already had a local.css file to tweak CSS for my slides, so I added the recommended CSS:

img.emoji {
   height: 1em;
   width: 1em;
   margin: 0 .05em 0 .1em;
   vertical-align: -0.1em;

It did not play well as I had some rules forcing the height of all images… so I had to rewrite this. I learned a new CSS selector on the way, sweet 😎!

img:not(.emoji) {
    height: 200pt !important;

Sorry, I promise I won’t use !important in production ever again

Broken fragments

Using fragments in a slide was broken as the <!-- fragment --> became applied to the img tag instead of the image.

To solve this issue, I had to change the fragment comment by using more HTML to delineate the fragment that would contain emoji image.

It went from a clean Markdown to an embedded HTML markup with the reveal-md magic fragment comments:

1. 🔍 what is WASM?
<!-- .element: class="fragment" -->
2. 🎩 History: when did it came to be?
<!-- .element: class="fragment" -->
3. 👀 what does it look like?
<!-- .element: class="fragment" -->
4. 🤹‍♀️ what could it be used for?
<!-- .element: class="fragment" -->


  <li class="fragment"> 🔍 what is WASM?</li>
  <li class="fragment"> 🎩 History: when did it came to be?</li>
  <li class="fragment"> 👀 what does it look like?</li>
  <li class="fragment"> 🤹‍♀️ what could it be used for?</li>


<!-- .element class="fragment" -->

became infected with a mild case of divitis:

<div class="fragment">🤢</div>

Dare I say that I reduced the character count and readability? 🤐

exporting to PDF

Exporting the presentation to a PDF works and even, adding the preprocessor solves an old issue on emoji rendering. Before the preprocessor, emojis were rendered by capturing snapshots of the presentation via a headless chromium browser. So.. one less issue: Win!

Here is what was added in the NPM scripts to use the preprocessor:

  "scripts": {
    "preexport:pdf": "cp presentation.md 2print.md && replace-in-file '/class=\"fragment\"/g' ' ' 2print.md --isRegex",
    "export:pdf": "reveal-md 2print.md -w --css local.css --theme white --print presentation.pdf --preprocessor emoji2svgimg.js",
    "postexport:pdf": "rm 2print.md"

(see my previous post if you want to know more about the other reveal export options and npm scripts)

exporting to an HTML static website

Exporting the presentation to a static website still works. The links to Twemoji images are external to the site. For example, the SVG for the 💩 is an URL pointing to a CDN URL:



What a really nice pile of poo! Such smooth anti-aliasing! Thank you so much Scalable Vector Graphics! 👍

I also changed the NPM scripts to use the preprocessor:

  "scripts": {
    "export:site": "reveal-md presentation.md --css local.css --theme white --static _site --preprocessor emoji2svgimg.js",
    "postexport:site": "cp *.svg _site/ && cp *.png _site/ && cp *.jpg _site/ && cp *.mp4 _site/ && cp robots.txt _site/ && cp *.svg _site/_assets/ && cp *.png _site/_assets/ && cp *.jpg _site/_assets/",

🎁 Sample repository

Well, here is a gift for you!

To illustrate this post and the previous one, I made a sample repository. It shows all my adaptations. I use nearly the same at work, branded with my company’s logo and colors.

Feel free to use it. It is open source, so you can also contribute by opening issues, asking questions, pushing code via Pull Requests, etc.

You can even see a sample exported PDF with Twemojis and without.

Try opening both PDFs on a non-emoji friendly OS for comparison 😉


Regarding emojis in reveal-md presentations, PDFs or static website exports, now anyone will be able to enjoy them without depending on their OS/browser!

Particularly those unlucky people stuck on old windows OSes… 😇

I hope you enjoyed this post! If you have any feedback about how it makes you almost laugh, was useful in any way, want to fix my lame jokes, content, or my English, send me a message on Twitter.


David Lacourt

Written by David Lacourt who lives in Senlis 🦌, and works in Paris 🇫🇷, and 🧡 building things with code.