Using Emojis with Pelican and Python Markdown

I didn't have much time this weekend, but I wanted to write a little code for keeping my brain active. So I looked at my website and noticed: I can't use emojis! 😮

Supporting emojis sounds like a nice little task, so let's take a look at how to do it.

You can find the final extensions on the GitHub repository at:

Pelican

This website is generated by Pelican, which is a static site generator written in Python:

I am using Markdown for writing the posts, so the plan is: Write a custom Python Markdown extension to replace Emoji Names with their Unicode representation.

Writing Python Markdown Extensions is quite simple and there is a good tutorial here:

Emojis

Then I got a list of Emojis from the EmojiCodeSheet project:

There are several JSON files, with the emojis as Unicode characters:

[
  "peoples": {
    "people": [
      {
        "key": "grinning_face",
        "value": "😀"
      },
      {
        "key": "grimacing_face",
        "value": "😬"
      },

      ...
]

I turned it into a list of Key / Value Pairs, so it looks like this:

[
  {
    "key": "grinning_face",
    "value": "😀"
  },
  {
    "key": "grimacing_face",
    "value": "😬"
  },

  ...
]

Implementing the Markdown Extension

import io
import json
from markdown.extensions import Extension
from markdown.inlinepatterns import Pattern

EMOJI_RE = r'(::)(.*?)::'

class EmojiExtension(Extension):

    def __init__(self, **kwargs):
        self.config = {
            'emojis': [[], 'List of Emojis.']
        }
        super(EmojiExtension, self).__init__(**kwargs)

    def extendMarkdown(self, md, md_globals):
        emojis = self._as_dictionary(self.getConfig('emojis'))
        pattern = EmojiInlinePattern(EMOJI_RE, emojis)
        md.inlinePatterns.add('emoji', pattern,'<not_strong')

    def _as_dictionary(self, emojis):
        return dict((emoji['key'], emoji['value']) for emoji in emojis)

    @staticmethod
    def create_from_json(filename):
        with io.open(filename, encoding='utf-8') as filehandle:
            data = json.load(filehandle)
            return EmojiExtension(emojis=data)

class EmojiInlinePattern(Pattern):

    def __init__(self, pattern, emojis):
        super(EmojiInlinePattern, self).__init__(pattern)
        self.emojis = emojis

    def handleMatch(self, m):
        emoji_key = m.group(3)

        return self.emojis.get(emoji_key, '')

Finally I wrote a setup.py file to install the Extension:

from setuptools import setup

setup(
    name='emojiextension',
    description='Extension for displaying Emojis',
    version='1.1',
    py_modules=['emojiextension'],
    install_requires = ['markdown>=2.5']
)

The extension can now be installed by running:

python setup.py install

Integrating it into Pelican

What's left is to integrate the Markdown extension into Pelican. So in the Pelican Settings file I am first importing the EmojiExtension:

from emojiextension import EmojiExtension

And then register it in the MARKDOWN variable:

# Markdown Configuration:
MARKDOWN = {
    'extensions' : [EmojiExtension.create_from_json('./resources/emojis.json')],
    'extension_configs': {
        'markdown.extensions.codehilite': {'css_class': 'highlight'},
        'markdown.extensions.toc' : {},
        'markdown.extensions.extra': {},
        'markdown.extensions.meta': {},
    },
    'output_format': 'html5',
}

And that's it!

Does it work?

I think so! 👍

How to contribute

One of the easiest ways to contribute is to participate in discussions. You can also contribute by submitting pull requests.

General feedback and discussions?

Do you have questions or feedback on this article? Please create an issue on the GitHub issue tracker.

Something is wrong or missing?

There may be something wrong or missing in this article. If you want to help fixing it, then please make a Pull Request to this file on GitHub.