diff --git a/djblets/emojis/__init__.py b/djblets/emojis/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..5a549988963cba68996fe0b94088a13a28db33e8
--- /dev/null
+++ b/djblets/emojis/__init__.py
@@ -0,0 +1,3 @@
+"""Emoji support for Djblets."""
+
+from __future__ import unicode_literals
diff --git a/djblets/emojis/registry.py b/djblets/emojis/registry.py
new file mode 100644
index 0000000000000000000000000000000000000000..80380762b11bee3fb2de4c7f465ba6c3a8abab79
--- /dev/null
+++ b/djblets/emojis/registry.py
@@ -0,0 +1,310 @@
+from __future__ import unicode_literals
+
+import datetime
+import json
+from collections import OrderedDict
+
+import pytz
+
+from djblets.emojis.unicode_sort_order import get_unicode_sort_order
+from djblets.siteconfig.models import SiteConfiguration
+
+
+class EmojiRegistry():
+    """
+    Class that holds the emoji registry.
+    """
+
+    EMOJI_INDEX_KEY = "emoji_index"
+    ADDED_EMOJIS_KEY = "added_emojis"
+    REMOVED_EMOJIS_KEY = "removed_emojis"
+
+    GITHUB_UNICODE_CDN = \
+        'https://github.githubassets.com/images/icons/emoji/unicode/'
+
+    GITHUB_CDN = 'https://github.githubassets.com/images/icons/emoji/'
+
+    def store_emoji_indices(self, default_emoji_index, custom_emoji_index):
+        """Store given emoji indices in the registry.
+
+        If either indice was already stored, it won't be overwritten unless
+        a new custom index with a new name is passed
+
+        To force overwrite, use overwrite_custom_emoji_index
+
+        Args:
+            default_emoji_index (dict):
+                The default (base) emoji index.
+
+            custom_emoji_index (dict) - optional:
+                The custom emoji index.
+        """
+
+        siteconfig = SiteConfiguration.objects.get_current()
+        index = siteconfig.get(self.EMOJI_INDEX_KEY)
+
+        if custom_emoji_index is None:
+            if index is None:
+                # Add src attributes to default index
+                self._add_src_attributes(default_emoji_index)
+                index = default_emoji_index
+                index['last_updated'] = datetime.datetime.now(pytz.utc)
+                self._save_index_and_restore_emojis(index)
+        else:
+            has_new_custom_index = index is not None and \
+                index['custom_index_name'] != custom_emoji_index['name']
+
+            if index is None or has_new_custom_index:
+                self._add_src_attributes(default_emoji_index)
+                index = self._combine_indices(
+                    default_emoji_index,
+                    custom_emoji_index
+                )
+                index['custom_index_name'] = custom_emoji_index['name']
+                index['last_updated'] = datetime.datetime.now(pytz.utc)
+                self._save_index_and_restore_emojis(index)
+
+    def overwrite_custom_emoji_index(self, default_emoji_index, custom_emoji_index):
+        """Overwrite the custom emoji index.
+
+        This will overwrite the emoji index with the provided ones.
+
+        Args:
+            default_emoji_index (dict):
+                The default (base) emoji index.
+
+            custom_emoji_index (dict):
+                The custom emoji index to overwrite.
+        """
+        if custom_emoji_index is None:
+            return
+
+        siteconfig = SiteConfiguration.objects.get_current()
+        index = siteconfig.get(self.EMOJI_INDEX_KEY)
+
+        index['custom_index_name'] = custom_emoji_index['name']
+        index['last_updated'] = datetime.datetime.now(pytz.utc)
+
+        index['emoji'] = self._combine_indices(
+            default_emoji_index,
+            custom_emoji_index
+        )
+
+        self._add_src_attributes(index['emoji'])
+
+        self._save_index_and_restore_emojis(index)
+
+    def get_emoji_index(self, for_extension=False):
+        """Get the emoji index.
+
+        This will return the emoji index for the given index.
+
+        If it is not for the extension, the emoji list will be sorted
+
+        Args:
+            index (str):
+                The index to get.
+
+        Returns:
+            str: The sorted stringified emoji index
+        """
+        siteconfig = SiteConfiguration.objects.get_current()
+        index = siteconfig.get(self.EMOJI_INDEX_KEY)
+
+        if (for_extension):
+            return index
+
+        index['emoji'] = self._sort_emoji_index_by_unicode(index['emoji'])
+
+        return json.dumps(index)
+
+    def get_emoji(self, shortcode):
+        """Get the emoji for the given shortcode.
+
+        Args:
+            shortcode (str):
+                The shortcode to get the emoji for.
+
+        Returns:
+            dict:
+            The emoji for the given shortcode.
+        """
+        siteconfig = SiteConfiguration.objects.get_current()
+        index = siteconfig.get(self.EMOJI_INDEX_KEY)
+
+        return index['emoji'].get(shortcode)
+
+    def add_emoji(self, emoji):
+        """Add the given emoji to the registry.
+
+        Args:
+            emoji (dict):
+                The emoji to add.
+        """
+        siteconfig = SiteConfiguration.objects.get_current()
+        index = siteconfig.get(self.EMOJI_INDEX_KEY)
+
+        shortcode = list(emoji.keys())[0]
+        index['emoji'][shortcode] = emoji
+
+        added_emojis = index.get(self.ADDED_EMOJIS_KEY)
+        if added_emojis is None:
+            added_emojis = [emoji]
+        else:
+            added_emojis.append(emoji)
+
+        siteconfig.set(self.EMOJI_INDEX_KEY, index)
+        siteconfig.set(self.ADDED_EMOJIS_KEY, added_emojis)
+        siteconfig.save()
+
+    def remove_emoji(self, shortcode):
+        """Remove the given emoji from the registry.
+
+        Args:
+            shortcode (str):
+        """
+        siteconfig = SiteConfiguration.objects.get_current()
+        index = siteconfig.get(self.EMOJI_INDEX_KEY)
+
+        removed_emojis = index.get(self.REMOVED_EMOJIS_KEY)
+        if removed_emojis is None:
+            removed_emojis = [shortcode]
+        else:
+            removed_emojis.append(shortcode)
+
+        del index['emoji'][shortcode]
+
+        siteconfig.set(self.EMOJI_INDEX_KEY, index)
+        siteconfig.set(self.ADDED_EMOJIS_KEY, removed_emojis)
+        siteconfig.save()
+
+    def add_alias(self, shortcode, alias):
+        """Add the given alias to the registry.
+
+        Args:
+            shortcode (str):
+                The shortcode to add the alias to.
+
+            alias (str):
+                The alias to add.
+        """
+        siteconfig = SiteConfiguration.objects.get_current()
+        index = siteconfig.get(self.EMOJI_INDEX_KEY)
+
+        index['aliases'][alias] = shortcode
+
+        siteconfig.set(self.EMOJI_INDEX_KEY, index)
+        siteconfig.save()
+
+    def remove_alias(self, alias):
+        """Remove the given alias from the registry.
+
+        Args:
+            alias (str):
+                The alias to remove.
+        """
+        siteconfig = SiteConfiguration.objects.get_current()
+        index = siteconfig.get(self.EMOJI_INDEX_KEY)
+
+        del index['aliases'][alias]
+
+        siteconfig.set(self.EMOJI_INDEX_KEY, index)
+        siteconfig.save()
+
+    def _add_src_attributes(self, emoji_index):
+        """Add the src attributes to the given index.
+
+        Args:
+            index (dict):
+                The index to add the attributes to.
+        """
+        for key in emoji_index['emoji']:
+            unicode = emoji_index['emoji'][key].get('unicode')
+            if (unicode is not None):
+                link = self.GITHUB_UNICODE_CDN + unicode + '.png'
+            else:
+                name = emoji_index['emoji'][key].get('name')
+                link = self.GITHUB_CDN + name + '.png'
+
+            emoji_index['emoji'][key]['src'] = link
+
+    def _sort_emoji_index_by_unicode(self, index):
+        """Sort the emoji index by unicode.
+
+        Custom emojis will be placed at end.
+
+        Args:
+            index (dict):
+                The index to sort.
+
+        Returns:
+            dict:
+            The sorted index.
+        """
+        sort_order = get_unicode_sort_order()
+
+        def get_sort_index(x, index):
+            try:
+                sort_index = sort_order.get((index[x]['unicode']).upper())
+                if sort_index is not None:
+                    return sort_index
+                else:
+                    raise ValueError
+
+            except (ValueError, KeyError):
+                return 1000000
+
+        sorted_index = OrderedDict()
+        sorted_keys = sorted(index, key=lambda x: get_sort_index(x, index))
+
+        for key in sorted_keys:
+            sorted_index[key] = index[key]
+
+        return sorted_index
+
+    def _combine_indices(self, i1, i2):
+        """Combine two indexes.
+
+        This will combine the two indexes and return the result.
+
+        Args:
+            i1 (dict):
+                The first index.
+
+            i2 (dict):
+                The second index.
+
+        Returns:
+            dict:
+            The combined index.
+        """
+
+        name = "combined_emoji_index"
+        combined_indices = {**i1['emoji'], **i2['emoji']}
+        combined_aliases = {**i1['aliases'], **i2['aliases']}
+        combined_index = {
+            "name": name,
+            "emoji": combined_indices,
+            "aliases": combined_aliases
+        }
+
+        return combined_index
+
+    def _save_index_and_restore_emojis(self, index):
+        siteconfig = SiteConfiguration.objects.get_current()
+
+        # Re-add added emojis
+        added_emojis = siteconfig.get(self.ADDED_EMOJIS_KEY)
+        if added_emojis is not None:
+            for emoji in added_emojis:
+                index['emoji'][emoji['shortcode']] = emoji
+
+        # Re-remove removed emojis
+        removed_emojis = siteconfig.get(self.REMOVED_EMOJIS_KEY)
+        if removed_emojis is not None:
+            for emoji in removed_emojis:
+                if emoji in index['emoji']:
+                    del index['emoji'][emoji['shortcode']]
+
+        siteconfig.set(self.EMOJI_INDEX_KEY, index)
+        siteconfig.save()
diff --git a/djblets/emojis/sort_order.txt b/djblets/emojis/sort_order.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6ca6c9430bf149ab8b361d19bc48231f0c644f60
--- /dev/null
+++ b/djblets/emojis/sort_order.txt
@@ -0,0 +1,3633 @@
+1F600
+1F603
+1F604
+1F601
+1F606
+1F605
+1F923
+1F602
+1F642
+1F643
+1FAE0
+1F609
+1F60A
+1F607
+1F970
+1F60D
+1F929
+1F618
+1F617
+263A
+1F61A
+1F619
+1F972
+1F60B
+1F61B
+1F61C
+1F92A
+1F61D
+1F911
+1F917
+1F92D
+1FAE2
+1FAE3
+1F92B
+1F914
+1FAE1
+1F910
+1F928
+1F610
+1F611
+1F636
+1FAE5
+1F636
+1F60F
+1F612
+1F644
+1F62C
+1F62E
+1F925
+1F60C
+1F614
+1F62A
+1F924
+1F634
+1F637
+1F912
+1F915
+1F922
+1F92E
+1F927
+1F975
+1F976
+1F974
+1F635
+1F635
+1F92F
+1F920
+1F973
+1F978
+1F60E
+1F913
+1F9D0
+1F615
+1FAE4
+1F61F
+1F641
+2639
+1F62E
+1F62F
+1F632
+1F633
+1F97A
+1F979
+1F626
+1F627
+1F628
+1F630
+1F625
+1F622
+1F62D
+1F631
+1F616
+1F623
+1F61E
+1F613
+1F629
+1F62B
+1F971
+1F624
+1F621
+1F620
+1F92C
+1F608
+1F47F
+1F480
+2620
+1F4A9
+1F921
+1F479
+1F47A
+1F47B
+1F47D
+1F47E
+1F916
+1F63A
+1F638
+1F639
+1F63B
+1F63C
+1F63D
+1F640
+1F63F
+1F63E
+1F648
+1F649
+1F64A
+1F48B
+1F48C
+1F498
+1F49D
+1F496
+1F497
+1F493
+1F49E
+1F495
+1F49F
+2763
+1F494
+2764
+2764
+2764
+1F9E1
+1F49B
+1F49A
+1F499
+1F49C
+1F90E
+1F5A4
+1F90D
+1F4AF
+1F4A2
+1F4A5
+1F4AB
+1F4A6
+1F4A8
+1F573
+1F4A3
+1F4AC
+1F441
+1F5E8
+1F5EF
+1F4AD
+1F4A4
+1F44B
+1F44B
+1F44B
+1F44B
+1F44B
+1F44B
+1F91A
+1F91A
+1F91A
+1F91A
+1F91A
+1F91A
+1F590
+1F590
+1F590
+1F590
+1F590
+1F590
+270B
+270B
+270B
+270B
+270B
+270B
+1F596
+1F596
+1F596
+1F596
+1F596
+1F596
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF2
+1FAF2
+1FAF2
+1FAF2
+1FAF2
+1FAF2
+1FAF3
+1FAF3
+1FAF3
+1FAF3
+1FAF3
+1FAF3
+1FAF4
+1FAF4
+1FAF4
+1FAF4
+1FAF4
+1FAF4
+1F44C
+1F44C
+1F44C
+1F44C
+1F44C
+1F44C
+1F90C
+1F90C
+1F90C
+1F90C
+1F90C
+1F90C
+1F90F
+1F90F
+1F90F
+1F90F
+1F90F
+1F90F
+270C
+270C
+270C
+270C
+270C
+270C
+1F91E
+1F91E
+1F91E
+1F91E
+1F91E
+1F91E
+1FAF0
+1FAF0
+1FAF0
+1FAF0
+1FAF0
+1FAF0
+1F91F
+1F91F
+1F91F
+1F91F
+1F91F
+1F91F
+1F918
+1F918
+1F918
+1F918
+1F918
+1F918
+1F919
+1F919
+1F919
+1F919
+1F919
+1F919
+1F448
+1F448
+1F448
+1F448
+1F448
+1F448
+1F449
+1F449
+1F449
+1F449
+1F449
+1F449
+1F446
+1F446
+1F446
+1F446
+1F446
+1F446
+1F595
+1F595
+1F595
+1F595
+1F595
+1F595
+1F447
+1F447
+1F447
+1F447
+1F447
+1F447
+261D
+261D
+261D
+261D
+261D
+261D
+1FAF5
+1FAF5
+1FAF5
+1FAF5
+1FAF5
+1FAF5
+1F44D
+1F44D
+1F44D
+1F44D
+1F44D
+1F44D
+1F44E
+1F44E
+1F44E
+1F44E
+1F44E
+1F44E
+270A
+270A
+270A
+270A
+270A
+270A
+1F44A
+1F44A
+1F44A
+1F44A
+1F44A
+1F44A
+1F91B
+1F91B
+1F91B
+1F91B
+1F91B
+1F91B
+1F91C
+1F91C
+1F91C
+1F91C
+1F91C
+1F91C
+1F44F
+1F44F
+1F44F
+1F44F
+1F44F
+1F44F
+1F64C
+1F64C
+1F64C
+1F64C
+1F64C
+1F64C
+1FAF6
+1FAF6
+1FAF6
+1FAF6
+1FAF6
+1FAF6
+1F450
+1F450
+1F450
+1F450
+1F450
+1F450
+1F932
+1F932
+1F932
+1F932
+1F932
+1F932
+1F91D
+1F91D
+1F91D
+1F91D
+1F91D
+1F91D
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1FAF1
+1F64F
+1F64F
+1F64F
+1F64F
+1F64F
+1F64F
+270D
+270D
+270D
+270D
+270D
+270D
+1F485
+1F485
+1F485
+1F485
+1F485
+1F485
+1F933
+1F933
+1F933
+1F933
+1F933
+1F933
+1F4AA
+1F4AA
+1F4AA
+1F4AA
+1F4AA
+1F4AA
+1F9BE
+1F9BF
+1F9B5
+1F9B5
+1F9B5
+1F9B5
+1F9B5
+1F9B5
+1F9B6
+1F9B6
+1F9B6
+1F9B6
+1F9B6
+1F9B6
+1F442
+1F442
+1F442
+1F442
+1F442
+1F442
+1F9BB
+1F9BB
+1F9BB
+1F9BB
+1F9BB
+1F9BB
+1F443
+1F443
+1F443
+1F443
+1F443
+1F443
+1F9E0
+1FAC0
+1FAC1
+1F9B7
+1F9B4
+1F440
+1F441
+1F445
+1F444
+1FAE6
+1F476
+1F476
+1F476
+1F476
+1F476
+1F476
+1F9D2
+1F9D2
+1F9D2
+1F9D2
+1F9D2
+1F9D2
+1F466
+1F466
+1F466
+1F466
+1F466
+1F466
+1F467
+1F467
+1F467
+1F467
+1F467
+1F467
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F471
+1F471
+1F471
+1F471
+1F471
+1F471
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F9D4
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F471
+1F471
+1F471
+1F471
+1F471
+1F471
+1F471
+1F471
+1F471
+1F471
+1F471
+1F471
+1F9D3
+1F9D3
+1F9D3
+1F9D3
+1F9D3
+1F9D3
+1F474
+1F474
+1F474
+1F474
+1F474
+1F474
+1F475
+1F475
+1F475
+1F475
+1F475
+1F475
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64D
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F64E
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F645
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F646
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F481
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F64B
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F9CF
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F647
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F926
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F937
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F46E
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F575
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F482
+1F977
+1F977
+1F977
+1F977
+1F977
+1F977
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1F477
+1FAC5
+1FAC5
+1FAC5
+1FAC5
+1FAC5
+1FAC5
+1F934
+1F934
+1F934
+1F934
+1F934
+1F934
+1F478
+1F478
+1F478
+1F478
+1F478
+1F478
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F473
+1F472
+1F472
+1F472
+1F472
+1F472
+1F472
+1F9D5
+1F9D5
+1F9D5
+1F9D5
+1F9D5
+1F9D5
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F935
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F470
+1F930
+1F930
+1F930
+1F930
+1F930
+1F930
+1FAC3
+1FAC3
+1FAC3
+1FAC3
+1FAC3
+1FAC3
+1FAC4
+1FAC4
+1FAC4
+1FAC4
+1FAC4
+1FAC4
+1F931
+1F931
+1F931
+1F931
+1F931
+1F931
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F47C
+1F47C
+1F47C
+1F47C
+1F47C
+1F47C
+1F385
+1F385
+1F385
+1F385
+1F385
+1F385
+1F936
+1F936
+1F936
+1F936
+1F936
+1F936
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B8
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9B9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9D9
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DA
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DB
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DC
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DD
+1F9DE
+1F9DE
+1F9DE
+1F9DF
+1F9DF
+1F9DF
+1F9CC
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F486
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F487
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F6B6
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CD
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9CE
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F3C3
+1F483
+1F483
+1F483
+1F483
+1F483
+1F483
+1F57A
+1F57A
+1F57A
+1F57A
+1F57A
+1F57A
+1F574
+1F574
+1F574
+1F574
+1F574
+1F574
+1F46F
+1F46F
+1F46F
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D6
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F9D7
+1F93A
+1F3C7
+1F3C7
+1F3C7
+1F3C7
+1F3C7
+1F3C7
+26F7
+1F3C2
+1F3C2
+1F3C2
+1F3C2
+1F3C2
+1F3C2
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3CC
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F3C4
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F6A3
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+1F3CA
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+26F9
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F3CB
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B4
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F6B5
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F938
+1F93C
+1F93C
+1F93C
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93D
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F93E
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F939
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F9D8
+1F6C0
+1F6C0
+1F6C0
+1F6C0
+1F6C0
+1F6C0
+1F6CC
+1F6CC
+1F6CC
+1F6CC
+1F6CC
+1F6CC
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F46D
+1F46D
+1F469
+1F469
+1F469
+1F469
+1F469
+1F46D
+1F469
+1F469
+1F469
+1F469
+1F469
+1F46D
+1F469
+1F469
+1F469
+1F469
+1F469
+1F46D
+1F469
+1F469
+1F469
+1F469
+1F469
+1F46D
+1F46B
+1F46B
+1F469
+1F469
+1F469
+1F469
+1F469
+1F46B
+1F469
+1F469
+1F469
+1F469
+1F469
+1F46B
+1F469
+1F469
+1F469
+1F469
+1F469
+1F46B
+1F469
+1F469
+1F469
+1F469
+1F469
+1F46B
+1F46C
+1F46C
+1F468
+1F468
+1F468
+1F468
+1F468
+1F46C
+1F468
+1F468
+1F468
+1F468
+1F468
+1F46C
+1F468
+1F468
+1F468
+1F468
+1F468
+1F46C
+1F468
+1F468
+1F468
+1F468
+1F468
+1F46C
+1F48F
+1F48F
+1F48F
+1F48F
+1F48F
+1F48F
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F491
+1F491
+1F491
+1F491
+1F491
+1F491
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F9D1
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F469
+1F46A
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F468
+1F468
+1F468
+1F468
+1F468
+1F469
+1F469
+1F469
+1F469
+1F469
+1F5E3
+1F464
+1F465
+1FAC2
+1F463
+1F3FB
+1F3FC
+1F3FD
+1F3FE
+1F3FF
+1F9B0
+1F9B1
+1F9B3
+1F9B2
+1F435
+1F412
+1F98D
+1F9A7
+1F436
+1F415
+1F9AE
+1F415
+1F429
+1F43A
+1F98A
+1F99D
+1F431
+1F408
+1F408
+1F981
+1F42F
+1F405
+1F406
+1F434
+1F40E
+1F984
+1F993
+1F98C
+1F9AC
+1F42E
+1F402
+1F403
+1F404
+1F437
+1F416
+1F417
+1F43D
+1F40F
+1F411
+1F410
+1F42A
+1F42B
+1F999
+1F992
+1F418
+1F9A3
+1F98F
+1F99B
+1F42D
+1F401
+1F400
+1F439
+1F430
+1F407
+1F43F
+1F9AB
+1F994
+1F987
+1F43B
+1F43B
+1F428
+1F43C
+1F9A5
+1F9A6
+1F9A8
+1F998
+1F9A1
+1F43E
+1F983
+1F414
+1F413
+1F423
+1F424
+1F425
+1F426
+1F427
+1F54A
+1F985
+1F986
+1F9A2
+1F989
+1F9A4
+1FAB6
+1F9A9
+1F99A
+1F99C
+1F438
+1F40A
+1F422
+1F98E
+1F40D
+1F432
+1F409
+1F995
+1F996
+1F433
+1F40B
+1F42C
+1F9AD
+1F41F
+1F420
+1F421
+1F988
+1F419
+1F41A
+1FAB8
+1F40C
+1F98B
+1F41B
+1F41C
+1F41D
+1FAB2
+1F41E
+1F997
+1FAB3
+1F577
+1F578
+1F982
+1F99F
+1FAB0
+1FAB1
+1F9A0
+1F490
+1F338
+1F4AE
+1FAB7
+1F3F5
+1F339
+1F940
+1F33A
+1F33B
+1F33C
+1F337
+1F331
+1FAB4
+1F332
+1F333
+1F334
+1F335
+1F33E
+1F33F
+2618
+1F340
+1F341
+1F342
+1F343
+1FAB9
+1FABA
+1F347
+1F348
+1F349
+1F34A
+1F34B
+1F34C
+1F34D
+1F96D
+1F34E
+1F34F
+1F350
+1F351
+1F352
+1F353
+1FAD0
+1F95D
+1F345
+1FAD2
+1F965
+1F951
+1F346
+1F954
+1F955
+1F33D
+1F336
+1FAD1
+1F952
+1F96C
+1F966
+1F9C4
+1F9C5
+1F344
+1F95C
+1FAD8
+1F330
+1F35E
+1F950
+1F956
+1FAD3
+1F968
+1F96F
+1F95E
+1F9C7
+1F9C0
+1F356
+1F357
+1F969
+1F953
+1F354
+1F35F
+1F355
+1F32D
+1F96A
+1F32E
+1F32F
+1FAD4
+1F959
+1F9C6
+1F95A
+1F373
+1F958
+1F372
+1FAD5
+1F963
+1F957
+1F37F
+1F9C8
+1F9C2
+1F96B
+1F371
+1F358
+1F359
+1F35A
+1F35B
+1F35C
+1F35D
+1F360
+1F362
+1F363
+1F364
+1F365
+1F96E
+1F361
+1F95F
+1F960
+1F961
+1F980
+1F99E
+1F990
+1F991
+1F9AA
+1F366
+1F367
+1F368
+1F369
+1F36A
+1F382
+1F370
+1F9C1
+1F967
+1F36B
+1F36C
+1F36D
+1F36E
+1F36F
+1F37C
+1F95B
+2615
+1FAD6
+1F375
+1F376
+1F37E
+1F377
+1F378
+1F379
+1F37A
+1F37B
+1F942
+1F943
+1FAD7
+1F964
+1F9CB
+1F9C3
+1F9C9
+1F9CA
+1F962
+1F37D
+1F374
+1F944
+1F52A
+1FAD9
+1F3FA
+1F30D
+1F30E
+1F30F
+1F310
+1F5FA
+1F5FE
+1F9ED
+1F3D4
+26F0
+1F30B
+1F5FB
+1F3D5
+1F3D6
+1F3DC
+1F3DD
+1F3DE
+1F3DF
+1F3DB
+1F3D7
+1F9F1
+1FAA8
+1FAB5
+1F6D6
+1F3D8
+1F3DA
+1F3E0
+1F3E1
+1F3E2
+1F3E3
+1F3E4
+1F3E5
+1F3E6
+1F3E8
+1F3E9
+1F3EA
+1F3EB
+1F3EC
+1F3ED
+1F3EF
+1F3F0
+1F492
+1F5FC
+1F5FD
+26EA
+1F54C
+1F6D5
+1F54D
+26E9
+1F54B
+26F2
+26FA
+1F301
+1F303
+1F3D9
+1F304
+1F305
+1F306
+1F307
+1F309
+2668
+1F3A0
+1F6DD
+1F3A1
+1F3A2
+1F488
+1F3AA
+1F682
+1F683
+1F684
+1F685
+1F686
+1F687
+1F688
+1F689
+1F68A
+1F69D
+1F69E
+1F68B
+1F68C
+1F68D
+1F68E
+1F690
+1F691
+1F692
+1F693
+1F694
+1F695
+1F696
+1F697
+1F698
+1F699
+1F6FB
+1F69A
+1F69B
+1F69C
+1F3CE
+1F3CD
+1F6F5
+1F9BD
+1F9BC
+1F6FA
+1F6B2
+1F6F4
+1F6F9
+1F6FC
+1F68F
+1F6E3
+1F6E4
+1F6E2
+26FD
+1F6DE
+1F6A8
+1F6A5
+1F6A6
+1F6D1
+1F6A7
+2693
+1F6DF
+26F5
+1F6F6
+1F6A4
+1F6F3
+26F4
+1F6E5
+1F6A2
+2708
+1F6E9
+1F6EB
+1F6EC
+1FA82
+1F4BA
+1F681
+1F69F
+1F6A0
+1F6A1
+1F6F0
+1F680
+1F6F8
+1F6CE
+1F9F3
+231B
+23F3
+231A
+23F0
+23F1
+23F2
+1F570
+1F55B
+1F567
+1F550
+1F55C
+1F551
+1F55D
+1F552
+1F55E
+1F553
+1F55F
+1F554
+1F560
+1F555
+1F561
+1F556
+1F562
+1F557
+1F563
+1F558
+1F564
+1F559
+1F565
+1F55A
+1F566
+1F311
+1F312
+1F313
+1F314
+1F315
+1F316
+1F317
+1F318
+1F319
+1F31A
+1F31B
+1F31C
+1F321
+2600
+1F31D
+1F31E
+1FA90
+2B50
+1F31F
+1F320
+1F30C
+2601
+26C5
+26C8
+1F324
+1F325
+1F326
+1F327
+1F328
+1F329
+1F32A
+1F32B
+1F32C
+1F300
+1F308
+1F302
+2602
+2614
+26F1
+26A1
+2744
+2603
+26C4
+2604
+1F525
+1F4A7
+1F30A
+1F383
+1F384
+1F386
+1F387
+1F9E8
+2728
+1F388
+1F389
+1F38A
+1F38B
+1F38D
+1F38E
+1F38F
+1F390
+1F391
+1F9E7
+1F380
+1F381
+1F397
+1F39F
+1F3AB
+1F396
+1F3C6
+1F3C5
+1F947
+1F948
+1F949
+26BD
+26BE
+1F94E
+1F3C0
+1F3D0
+1F3C8
+1F3C9
+1F3BE
+1F94F
+1F3B3
+1F3CF
+1F3D1
+1F3D2
+1F94D
+1F3D3
+1F3F8
+1F94A
+1F94B
+1F945
+26F3
+26F8
+1F3A3
+1F93F
+1F3BD
+1F3BF
+1F6F7
+1F94C
+1F3AF
+1FA80
+1FA81
+1F3B1
+1F52E
+1FA84
+1F9FF
+1FAAC
+1F3AE
+1F579
+1F3B0
+1F3B2
+1F9E9
+1F9F8
+1FA85
+1FAA9
+1FA86
+2660
+2665
+2666
+2663
+265F
+1F0CF
+1F004
+1F3B4
+1F3AD
+1F5BC
+1F3A8
+1F9F5
+1FAA1
+1F9F6
+1FAA2
+1F453
+1F576
+1F97D
+1F97C
+1F9BA
+1F454
+1F455
+1F456
+1F9E3
+1F9E4
+1F9E5
+1F9E6
+1F457
+1F458
+1F97B
+1FA71
+1FA72
+1FA73
+1F459
+1F45A
+1F45B
+1F45C
+1F45D
+1F6CD
+1F392
+1FA74
+1F45E
+1F45F
+1F97E
+1F97F
+1F460
+1F461
+1FA70
+1F462
+1F451
+1F452
+1F3A9
+1F393
+1F9E2
+1FA96
+26D1
+1F4FF
+1F484
+1F48D
+1F48E
+1F507
+1F508
+1F509
+1F50A
+1F4E2
+1F4E3
+1F4EF
+1F514
+1F515
+1F3BC
+1F3B5
+1F3B6
+1F399
+1F39A
+1F39B
+1F3A4
+1F3A7
+1F4FB
+1F3B7
+1FA97
+1F3B8
+1F3B9
+1F3BA
+1F3BB
+1FA95
+1F941
+1FA98
+1F4F1
+1F4F2
+260E
+1F4DE
+1F4DF
+1F4E0
+1F50B
+1FAAB
+1F50C
+1F4BB
+1F5A5
+1F5A8
+2328
+1F5B1
+1F5B2
+1F4BD
+1F4BE
+1F4BF
+1F4C0
+1F9EE
+1F3A5
+1F39E
+1F4FD
+1F3AC
+1F4FA
+1F4F7
+1F4F8
+1F4F9
+1F4FC
+1F50D
+1F50E
+1F56F
+1F4A1
+1F526
+1F3EE
+1FA94
+1F4D4
+1F4D5
+1F4D6
+1F4D7
+1F4D8
+1F4D9
+1F4DA
+1F4D3
+1F4D2
+1F4C3
+1F4DC
+1F4C4
+1F4F0
+1F5DE
+1F4D1
+1F516
+1F3F7
+1F4B0
+1FA99
+1F4B4
+1F4B5
+1F4B6
+1F4B7
+1F4B8
+1F4B3
+1F9FE
+1F4B9
+2709
+1F4E7
+1F4E8
+1F4E9
+1F4E4
+1F4E5
+1F4E6
+1F4EB
+1F4EA
+1F4EC
+1F4ED
+1F4EE
+1F5F3
+270F
+2712
+1F58B
+1F58A
+1F58C
+1F58D
+1F4DD
+1F4BC
+1F4C1
+1F4C2
+1F5C2
+1F4C5
+1F4C6
+1F5D2
+1F5D3
+1F4C7
+1F4C8
+1F4C9
+1F4CA
+1F4CB
+1F4CC
+1F4CD
+1F4CE
+1F587
+1F4CF
+1F4D0
+2702
+1F5C3
+1F5C4
+1F5D1
+1F512
+1F513
+1F50F
+1F510
+1F511
+1F5DD
+1F528
+1FA93
+26CF
+2692
+1F6E0
+1F5E1
+2694
+1F52B
+1FA83
+1F3F9
+1F6E1
+1FA9A
+1F527
+1FA9B
+1F529
+2699
+1F5DC
+2696
+1F9AF
+1F517
+26D3
+1FA9D
+1F9F0
+1F9F2
+1FA9C
+2697
+1F9EA
+1F9EB
+1F9EC
+1F52C
+1F52D
+1F4E1
+1F489
+1FA78
+1F48A
+1FA79
+1FA7C
+1FA7A
+1FA7B
+1F6AA
+1F6D7
+1FA9E
+1FA9F
+1F6CF
+1F6CB
+1FA91
+1F6BD
+1FAA0
+1F6BF
+1F6C1
+1FAA4
+1FA92
+1F9F4
+1F9F7
+1F9F9
+1F9FA
+1F9FB
+1FAA3
+1F9FC
+1FAE7
+1FAA5
+1F9FD
+1F9EF
+1F6D2
+1F6AC
+26B0
+1FAA6
+26B1
+1F5FF
+1FAA7
+1FAAA
+1F3E7
+1F6AE
+1F6B0
+267F
+1F6B9
+1F6BA
+1F6BB
+1F6BC
+1F6BE
+1F6C2
+1F6C3
+1F6C4
+1F6C5
+26A0
+1F6B8
+26D4
+1F6AB
+1F6B3
+1F6AD
+1F6AF
+1F6B1
+1F6B7
+1F4F5
+1F51E
+2622
+2623
+2B06
+2197
+27A1
+2198
+2B07
+2199
+2B05
+2196
+2195
+2194
+21A9
+21AA
+2934
+2935
+1F503
+1F504
+1F519
+1F51A
+1F51B
+1F51C
+1F51D
+1F6D0
+269B
+1F549
+2721
+2638
+262F
+271D
+2626
+262A
+262E
+1F54E
+1F52F
+2648
+2649
+264A
+264B
+264C
+264D
+264E
+264F
+2650
+2651
+2652
+2653
+26CE
+1F500
+1F501
+1F502
+25B6
+23E9
+23ED
+23EF
+25C0
+23EA
+23EE
+1F53C
+23EB
+1F53D
+23EC
+23F8
+23F9
+23FA
+23CF
+1F3A6
+1F505
+1F506
+1F4F6
+1F4F3
+1F4F4
+2640
+2642
+26A7
+2716
+2795
+2796
+2797
+1F7F0
+267E
+203C
+2049
+2753
+2754
+2755
+2757
+3030
+1F4B1
+1F4B2
+2695
+267B
+269C
+1F531
+1F4DB
+1F530
+2B55
+2705
+2611
+2714
+274C
+274E
+27B0
+27BF
+303D
+2733
+2734
+2747
+00A9
+00AE
+2122
+0023
+002A
+0030
+0031
+0032
+0033
+0034
+0035
+0036
+0037
+0038
+0039
+1F51F
+1F520
+1F521
+1F522
+1F523
+1F524
+1F170
+1F18E
+1F171
+1F191
+1F192
+1F193
+2139
+1F194
+24C2
+1F195
+1F196
+1F17E
+1F197
+1F17F
+1F198
+1F199
+1F19A
+1F201
+1F202
+1F237
+1F236
+1F22F
+1F250
+1F239
+1F21A
+1F232
+1F251
+1F238
+1F234
+1F233
+3297
+3299
+1F23A
+1F235
+1F534
+1F7E0
+1F7E1
+1F7E2
+1F535
+1F7E3
+1F7E4
+26AB
+26AA
+1F7E5
+1F7E7
+1F7E8
+1F7E9
+1F7E6
+1F7EA
+1F7EB
+2B1B
+2B1C
+25FC
+25FB
+25FE
+25FD
+25AA
+25AB
+1F536
+1F537
+1F538
+1F539
+1F53A
+1F53B
+1F4A0
+1F518
+1F533
+1F532
+1F3C1
+1F6A9
+1F38C
+1F3F4
+1F3F3
+1F3F3
+1F3F3
+1F3F4
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E6
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E7
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E8
+1F1E9
+1F1E9
+1F1E9
+1F1E9
+1F1E9
+1F1E9
+1F1E9
+1F1EA
+1F1EA
+1F1EA
+1F1EA
+1F1EA
+1F1EA
+1F1EA
+1F1EA
+1F1EA
+1F1EB
+1F1EB
+1F1EB
+1F1EB
+1F1EB
+1F1EB
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1EC
+1F1ED
+1F1ED
+1F1ED
+1F1ED
+1F1ED
+1F1ED
+1F1EE
+1F1EE
+1F1EE
+1F1EE
+1F1EE
+1F1EE
+1F1EE
+1F1EE
+1F1EE
+1F1EE
+1F1EE
+1F1EF
+1F1EF
+1F1EF
+1F1EF
+1F1F0
+1F1F0
+1F1F0
+1F1F0
+1F1F0
+1F1F0
+1F1F0
+1F1F0
+1F1F0
+1F1F0
+1F1F0
+1F1F1
+1F1F1
+1F1F1
+1F1F1
+1F1F1
+1F1F1
+1F1F1
+1F1F1
+1F1F1
+1F1F1
+1F1F1
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F2
+1F1F3
+1F1F3
+1F1F3
+1F1F3
+1F1F3
+1F1F3
+1F1F3
+1F1F3
+1F1F3
+1F1F3
+1F1F3
+1F1F3
+1F1F4
+1F1F5
+1F1F5
+1F1F5
+1F1F5
+1F1F5
+1F1F5
+1F1F5
+1F1F5
+1F1F5
+1F1F5
+1F1F5
+1F1F5
+1F1F5
+1F1F5
+1F1F6
+1F1F7
+1F1F7
+1F1F7
+1F1F7
+1F1F7
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F8
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1F9
+1F1FA
+1F1FA
+1F1FA
+1F1FA
+1F1FA
+1F1FA
+1F1FA
+1F1FB
+1F1FB
+1F1FB
+1F1FB
+1F1FB
+1F1FB
+1F1FB
+1F1FC
+1F1FC
+1F1FD
+1F1FE
+1F1FE
+1F1FF
+1F1FF
+1F1FF
+1F3F4
+1F3F4
+1F3F4
\ No newline at end of file
diff --git a/djblets/emojis/tests.py b/djblets/emojis/tests.py
new file mode 100644
index 0000000000000000000000000000000000000000..6c072af55ea86e5ef240f11a9557db57aec67af4
--- /dev/null
+++ b/djblets/emojis/tests.py
@@ -0,0 +1,253 @@
+"""Tests for djblets.emojis."""
+
+from __future__ import unicode_literals
+
+import datetime
+
+from django.contrib.sites.models import Site
+from django.core.cache import cache
+from kgb import SpyAgency
+
+from djblets.emojis.registry import EmojiRegistry
+from djblets.siteconfig.models import SiteConfiguration
+from djblets.testing.testcases import TestCase
+import pymdownx.emoji
+
+
+class EmojiRegistryTests(SpyAgency, TestCase):
+    """Tests for djblets.emojis.registry."""
+
+    custom_index = {
+        "name": "mycustomindex",
+        "emoji": {
+            ":montreal-canadiens-logo:": {
+                "category": "Custom",
+                "name": "montreal-canadiens-logo",
+                "src": "random_src"
+            },
+        },
+        "aliases": {
+            ":habs:": ":montreal-canadiens-logo:"
+        }
+    }
+
+    def custom_emoji_index(self):
+        """The custom index."""
+        return {
+            "name": self.custom_index['name'],
+            "emoji": self.custom_index['emoji'],
+            "aliases": self.custom_index['aliases']
+        }
+
+    def setUp(self):
+        super(EmojiRegistryTests, self).setUp()
+        self.registry = EmojiRegistry()
+
+        self.siteconfig = SiteConfiguration.objects.create(
+            site=Site.objects.get_current())
+        cache.clear()
+
+    def tearDown(self):
+        super(EmojiRegistryTests, self).tearDown()
+        cache.clear()
+
+    def test_store_emoji_indices_base(self):
+        """Testing EmojiRegistry.store_emoji_indices"""
+
+        with self.siteconfig_settings({self.registry.EMOJI_INDEX_KEY: None}):
+            siteconfig = SiteConfiguration.objects.get_current()
+
+            index = siteconfig.get(self.registry.EMOJI_INDEX_KEY)
+            self.assertIsNone(index)
+
+            self.registry.store_emoji_indices(pymdownx.emoji.gemoji(), None)
+
+            index = siteconfig.get(self.registry.EMOJI_INDEX_KEY)
+            self.assertIsNotNone(index)
+
+            self.assertIsNotNone(index.get('emoji'))
+            self.assertIn(':heart:', index.get('emoji'))
+            self.assertNotIn(':montreal-canadiens-logo:', index.get('emoji'))
+
+            self.assertIsNotNone(index.get('aliases'))
+            self.assertIn(':+1:', index.get('emoji'))
+            self.assertNotIn(':habs:', index.get('emoji'))
+
+            self.assertEqual(index.get('name'), 'gemoji')
+
+            self.assertIsNotNone(index.get('last_updated').tzinfo)
+
+    def test_store_emoji_indices_custom(self):
+        """Testing EmojiRegistry.store_emoji_indices with custom index"""
+
+        with self.siteconfig_settings({self.registry.EMOJI_INDEX_KEY: None}):
+            siteconfig = SiteConfiguration.objects.get_current()
+
+            index = siteconfig.get(self.registry.EMOJI_INDEX_KEY)
+            self.assertIsNone(index)
+
+            self.registry.store_emoji_indices(
+                pymdownx.emoji.gemoji(),
+                self.custom_emoji_index())
+
+            index = siteconfig.get(self.registry.EMOJI_INDEX_KEY)
+            self.assertIsNotNone(index)
+
+            self.assertIsNotNone(index.get('emoji'))
+            self.assertIn(':heart:', index.get('emoji'))
+            self.assertIn(':montreal-canadiens-logo:', index.get('emoji'))
+
+            self.assertIsNotNone(index.get('aliases'))
+            self.assertIn(':+1:', index.get('emoji'))
+            self.assertIn(':habs:', index.get('aliases'))
+
+            self.assertEqual(index.get('name'), 'combined_emoji_index')
+
+            self.assertIsNotNone(index.get('last_updated').tzinfo)
+
+    def test_get_emoji_index(self):
+        """Testing EmojiRegistry.get_emoji_index"""
+
+        with self.siteconfig_settings({self.registry.EMOJI_INDEX_KEY: None}):
+            siteconfig = SiteConfiguration.objects.get_current()
+
+            self.registry.store_emoji_indices(
+                pymdownx.emoji.gemoji(), None)
+
+            i1 = self.registry.get_emoji_index(for_extension=True)
+            i2 = siteconfig.get(self.registry.EMOJI_INDEX_KEY)
+
+            self.assertEqual(len(i1.get('emoji')), len(i2.get('emoji')))
+            self.assertEqual(len(i1.get('aliases')), len(i2.get('aliases')))
+            self.assertEqual(i1.get('name'), i2.get('name'))
+
+            i1_date = i1.get('last_updated')
+            i1_date = datetime.datetime.strptime(
+                i1_date, '%Y-%m-%dT%H:%M:%S.%fZ'
+            )
+            i2_date = i2.get('last_updated')
+
+            self.assertEqual(i1_date.year, i2_date.year)
+            self.assertEqual(i1_date.month, i2_date.month)
+            self.assertEqual(i1_date.day, i2_date.day)
+            self.assertEqual(i1_date.hour, i2_date.hour)
+            self.assertEqual(i1_date.minute, i2_date.minute)
+            self.assertEqual(i1_date.second, i2_date.second)
+
+    def test_add_emoji(self):
+        """Testing EmojiRegistry.add_emoji"""
+
+        with self.siteconfig_settings(
+            {
+                self.registry.EMOJI_INDEX_KEY: None,
+                self.registry.ADDED_EMOJIS_KEY: []
+            }):
+            siteconfig = SiteConfiguration.objects.get_current()
+
+            self.registry.store_emoji_indices(
+                pymdownx.emoji.gemoji(),
+                self.custom_emoji_index())
+
+            emoji = {
+                ":new-random-logo:": {
+                    "category": "Custom",
+                    "name": "new-random-logo",
+                    "src": "random_src"
+                }
+            }
+
+            self.registry.add_emoji(emoji)
+
+            siteconfig = SiteConfiguration.objects.get_current()
+            index = siteconfig.get(self.registry.EMOJI_INDEX_KEY)
+            added_emojis = siteconfig.get(self.registry.ADDED_EMOJIS_KEY)
+
+            self.assertIn(':new-random-logo:', index.get('emoji'))
+            self.assertIn(emoji, added_emojis)
+
+    def test_remove_emoji(self):
+        """Testing EmojiRegistry.remove_emoji"""
+
+        with self.siteconfig_settings(
+            {
+                self.registry.EMOJI_INDEX_KEY: None,
+                self.registry.ADDED_EMOJIS_KEY: []
+            }):
+            siteconfig = SiteConfiguration.objects.get_current()
+
+            self.registry.store_emoji_indices(
+                pymdownx.emoji.gemoji(),
+                self.custom_emoji_index())
+
+            emoji = {
+                ":new-random-logo:": {
+                    "category": "Custom",
+                    "name": "new-random-logo",
+                    "src": "random_src"
+                }
+            }
+
+            self.registry.add_emoji(emoji)
+
+            siteconfig = SiteConfiguration.objects.get_current()
+            index = siteconfig.get(self.registry.EMOJI_INDEX_KEY)
+            added_emojis = siteconfig.get(self.registry.ADDED_EMOJIS_KEY)
+
+            self.assertIn(':new-random-logo:', index.get('emoji'))
+            self.assertIn(emoji, added_emojis)
+
+            self.registry.remove_emoji(':new-random-logo:')
+
+            siteconfig = SiteConfiguration.objects.get_current()
+            index = siteconfig.get(self.registry.EMOJI_INDEX_KEY)
+            added_emojis = siteconfig.get(self.registry.ADDED_EMOJIS_KEY)
+
+            self.assertNotIn(':new-random-logo:', index.get('emoji'))
+            self.assertNotIn(emoji, added_emojis)
+
+    def test_add_alias(self):
+        """Testing EmojiRegistry.add_alias"""
+
+        with self.siteconfig_settings(
+            {
+                self.registry.EMOJI_INDEX_KEY: None,
+                self.registry.ADDED_EMOJIS_KEY: []
+            }):
+
+            self.registry.store_emoji_indices(
+                pymdownx.emoji.gemoji(),
+                self.custom_emoji_index())
+
+            self.registry.add_alias(':new-random-logo:', ':random-alias:')
+
+            siteconfig = SiteConfiguration.objects.get_current()
+            index = siteconfig.get(self.registry.EMOJI_INDEX_KEY)
+
+            self.assertIn(':random-alias:', index.get('aliases'))
+
+    def test_remove_alias(self):
+        """Testing EmojiRegistry.remove_alias"""
+
+        with self.siteconfig_settings(
+            {
+                self.registry.EMOJI_INDEX_KEY: None,
+                self.registry.ADDED_EMOJIS_KEY: []
+            }):
+
+            self.registry.store_emoji_indices(
+                pymdownx.emoji.gemoji(),
+                self.custom_emoji_index())
+
+            self.registry.add_alias(':new-random-logo:', ':random-alias:')
+
+            siteconfig = SiteConfiguration.objects.get_current()
+            index = siteconfig.get(self.registry.EMOJI_INDEX_KEY)
+
+            self.assertIn(':random-alias:', index.get('aliases'))
+
+            self.registry.remove_alias(':random-alias:')
+
+            siteconfig = SiteConfiguration.objects.get_current()
+            index = siteconfig.get(self.registry.EMOJI_INDEX_KEY)
+
+            self.assertNotIn(':random-alias:', index.get('aliases'))
diff --git a/djblets/emojis/unicode_sort_order.py b/djblets/emojis/unicode_sort_order.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c778e2dd2f4dcecd6f9a95561b9de83b61d9e0b
--- /dev/null
+++ b/djblets/emojis/unicode_sort_order.py
@@ -0,0 +1,22 @@
+import os.path
+
+current_dir = os.path.dirname(os.path.abspath(__file__))
+
+
+def get_unicode_sort_order():
+    """
+    Returns the default sort order for the emojis as per unicode
+    category standards. https://unicode.org/emoji/charts/emoji-ordering.txt
+
+    Sort order defined in sort_order.txt
+    """
+
+    path = os.path.join(current_dir, 'sort_order.txt')
+    with open(path, 'r') as f:
+        sort_order = {}
+        current_index = 0
+        for line in f:
+            sort_order[line.strip()] = current_index
+            current_index += 1
+
+    return sort_order
diff --git a/djblets/markdown/extensions/emoji_extension_wrapper.py b/djblets/markdown/extensions/emoji_extension_wrapper.py
new file mode 100644
index 0000000000000000000000000000000000000000..446d44a7cc9f99079e811982830bba3bd63a99f6
--- /dev/null
+++ b/djblets/markdown/extensions/emoji_extension_wrapper.py
@@ -0,0 +1,165 @@
+"""
+Markdown extension to allow extra functionality for emojis on top of the
+standard emoji markdown extension.
+"""
+
+from __future__ import unicode_literals
+
+from djblets.emojis.registry import EmojiRegistry
+from markdown.extensions import Extension
+from markdown import util as md_util
+import pymdownx.emoji
+
+
+DEFAULT_BASE_EMOJI_INDEX = pymdownx.emoji.gemoji
+
+
+def add_attributes(options, attributes):
+    """Add additional attributes from options."""
+
+    attr = options.get('attributes', {})
+    if attr:
+        for k, v in attr.items():
+            attributes[k] = v
+
+
+def custom_emoji_to_png_generator(index, shortname, alias, uc, alt, title, category, options, md):
+    """Return PNG element."""
+    emoji_registry = EmojiRegistry()
+
+    if category == "Custom":
+        emoji = emoji_registry.get_emoji(shortname)
+        src = emoji.get('src')
+
+    else:
+        image_path = emoji_registry.GITHUB_UNICODE_CDN
+        non_std_image_path = emoji_registry.GITHUB_CDN
+
+        is_unicode = uc is not None
+
+        """
+        In general we can use the alias, but github specific images
+        don't have one for each alias.
+
+        We can tell we have a github specific if there is no Unicode value.
+        """
+        if is_unicode:
+            img_path = options.get('image_path', image_path)
+        else:
+            img_path = options.get('non_standard_image_path', non_std_image_path)
+
+        src = "%s%s.png" % (
+            img_path,
+            uc if is_unicode else shortname[1:-1]
+        )
+
+    classes = options.get('classes', index)
+
+    attributes = {
+        "class": classes,
+        "alt": alt,
+        "src": src
+    }
+
+    if title:
+        attributes['title'] = title
+
+    add_attributes(options, attributes)
+
+    return md_util.etree.Element("img", attributes)
+
+
+class EmojiExtensionWrapper(Extension):
+    """
+    Extension to add a custom Emoji registry.
+    """
+
+    def __init__(self, *args, **kwargs):
+        """Initialize."""
+
+        self.config = {
+            'emoji_index': [
+                DEFAULT_BASE_EMOJI_INDEX,
+                'Function that returns the desired base emoji index'
+            ],
+            'custom_emoji_index': [
+                None,
+                'Function that returns the custom emoji index.'
+                "Default: 'None'"
+            ],
+            'emoji_generator': [
+                custom_emoji_to_png_generator,
+                'Emoji generator method.'
+                "Default: 'custom_emoji_to_png_generator'"
+            ],
+            'title': [
+                'short',
+                "Options: 'short', 'long', or 'none'"
+                "Default: 'short'"
+            ],
+            'alt': [
+                'unicode',
+                "Options: 'short', 'unicode', or 'html_entity'"
+                "Default: 'unicode'"
+            ],
+            'remove_variation_selector': [
+                False,
+                'Remove variation selector 16 from unicode. - Default: False'
+            ],
+            'options': [
+                {'classes': 'emoji'},
+                'Emoji options'
+                'See documentation for options for github and emojione.'
+            ]
+        }
+
+        new_kwargs = kwargs.copy()
+
+        # Store inputed emoji indices to the registry
+        emoji_registry = EmojiRegistry()
+
+        if 'emoji_index' in new_kwargs:
+            default_index = kwargs.get('emoji_index')
+        else:
+            default_index = DEFAULT_BASE_EMOJI_INDEX
+
+        emoji_registry.store_emoji_indices(default_index(), kwargs.get('custom_emoji_index')())
+
+        if kwargs.get('custom_emoji_index') is not None:
+            new_kwargs['emoji_index'] = lambda: emoji_registry.get_emoji_index(for_extension=True)
+            new_kwargs.pop('custom_emoji_index', None)
+
+        self.emojiExtension = pymdownx.emoji.EmojiExtension(*args, **new_kwargs)
+        self.emojiExtension.config = self.config
+        super(EmojiExtensionWrapper, self).__init__(*args, **new_kwargs)
+
+    def extendMarkdown(self, md, md_globals):
+        """Extend the list of Markdown processors.
+
+        Args:
+            md (markdown.Markdown):
+                The Markdown renderer.
+
+            md_globals (dict):
+                Global variables from the :py:mod:`markdown` module.
+
+        Returns:
+            The emoji markdown's extension extendMarkdown method.
+        """
+        return self.emojiExtension.extendMarkdown(md)
+
+
+def makeExtension(*args, **kwargs):
+    """Create and return an instance of this extension.
+
+    Args:
+        *args (tuple):
+            Positional arguments for the extension.
+
+        **kwargs (dict):
+            Keyword arguments for the extension.
+
+    Returns:
+        The emoji markdown's extension makeExtension method.
+    """
+    return EmojiExtensionWrapper(*args, **kwargs)
