Skip to content

Commit

Permalink
Merge pull request #1 from freakboy3742/master
Browse files Browse the repository at this point in the history
Added Django template tag and filter for emojificate
  • Loading branch information
glasnt authored Aug 7, 2016
2 parents c270478 + 01f6984 commit d161d96
Show file tree
Hide file tree
Showing 12 changed files with 205 additions and 73 deletions.
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
*.pyc
__pycache__
*~
.*.sw[op]
*.egg-info
*.egg
.eggs
.tox
local
dist
build
_build
distribute-*
7 changes: 7 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
include *.rst
include LICENSE
recursive-include tests *.py
recursive-include docs Makefile
recursive-include docs *.py
recursive-include docs *.bat
recursive-include docs *.rst
36 changes: 0 additions & 36 deletions README.md

This file was deleted.

48 changes: 48 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
emojificate
===========

Emojificate is a Python implementation of a concept of using fallback images, alt text, title text and aria labels to represent emoji in HTML code in a more accessible method.

Usage
-----

To convert a string from the command line::

$ python3 -m emojificate "I 💜 emoji 😊"
I <img src="https://twemoji.maxcdn.com/36x36/1f49c.png" alt="💜" title="Purple Heart" height="16px" aria-label="Emoji: Purple Heart"> emoji <img src="https://twemoji.maxcdn.com/36x36/1f60a.png" alt="😊" title="Smiling Face With Smiling Eyes" height="16px" aria-label="Emoji: Smiling Face With Smiling Eyes">

Or, if you've got a Django project, put ``emojificate`` into your ``INSTALLED_APPS``, and then use the following in a template::

{% load emojificate %}
This is some {{ user_content|emojificate }} that has emoji in it.

{% emojified %}
This is some template content that 💜 emoji as well.
{% endemojified %}

Implementation
--------------

TL;DR: Take a string, split it into token, and if a token is emoji, process it into a nice format.

Splitting the string is a problem, because at the moment it **does not handle Zero Width Joining sequences**. However, native Python string tokenization does work for the most part.

Given a list of tokens, we can leverage the native `unicodedata <https://docs.python.org/3/library/unicodedata.html>`__ to:

* see if a token is a unicode Symbol (an emoji)
* get the codepoint for the emoji, and
* get the name of the emoji

From there, we construct an ``<img>`` replacement for the emoji:

* Use images from `twemoji <https://github.com/twitter/twemoji>`__, Twitter's emoji set
* Have an ``alt`` parameter containing the original emoji. This allows for copying-pasting.
* Use the name of the emoji in the ``title`` parameter. This allows for hover-tooltips.
* Add an ``aria-label`` for screen-reader accessibility.

For more information, see `Solve For Emoji <http://glasnt.com/blog/2016/08/06/solve-for-emoji.html>`__.

Limitations
-----------

* Does not handle Zero Width Join Sequences; for example: 🖐🏽, 👩‍👩‍👧
37 changes: 0 additions & 37 deletions emojificate.py

This file was deleted.

9 changes: 9 additions & 0 deletions emojificate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Examples of valid version strings
# __version__ = '1.2.3.dev1' # Development release 1
# __version__ = '1.2.3a1' # Alpha Release 1
# __version__ = '1.2.3b1' # Beta Release 1
# __version__ = '1.2.3rc1' # RC Release 1
# __version__ = '1.2.3' # Final Release
# __version__ = '1.2.3.post1' # Post Release 1

__version__ = "0.1.0"
16 changes: 16 additions & 0 deletions emojificate/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import sys

from .filter import emojificate


def display_help():
print("emojificate.py -- turns text with emoji into text with accessible emoji")


if __name__ == "__main__":
line = " ".join(sys.argv[1:])
if line:
print(emojificate(line))
else:
display_help()
sys.exit(1)
32 changes: 32 additions & 0 deletions emojificate/filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import unicodedata


__all__ = ['emojificate']


cdn = "https://twemoji.maxcdn.com/36x36/"
cdn_ft = ".png"


def tag(a, b):
return "%s=\"%s\"" % (a, b)


def convert(char):
if unicodedata.category(char) == "So":
name = unicodedata.name(char).title()
code = char.encode("unicode_escape").decode("utf-8")[2:].strip("0")
return "".join([
"<img",
tag(" src", cdn + code + cdn_ft),
tag(" alt", char),
tag(" title", name),
tag(" aria-label", "Emoji: %s" % name),
">"
])
else:
return char


def emojificate(line):
return ''.join(convert(ch) for ch in line)
Empty file.
35 changes: 35 additions & 0 deletions emojificate/templatetags/emojificate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from django.template import Library, Node
from django.utils.safestring import mark_safe
from django.utils.html import conditional_escape

from ..filter import emojificate


register = Library()


@register.filter('emojificate', needs_autoescape=True)
def emojificate_filter(content, autoescape=True):
"Convert any emoji in a string into accessible content."
# return mark_safe(emojificate(content))
if autoescape:
esc = conditional_escape
else:
esc = lambda x: x
return mark_safe(emojificate(esc(content)))


@register.tag('emojified')
def do_emojified(parser, token):
nodelist = parser.parse(('endemojified',))
parser.delete_first_token()
return EmojifiedNode(nodelist)


class EmojifiedNode(Node):
def __init__(self, nodelist):
self.nodelist = nodelist

def render(self, context):
output = self.nodelist.render(context)
return emojificate(output)
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[bdist_wheel]
universal=1
43 changes: 43 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import re
from setuptools import setup, find_packages
from codecs import open
from os import path

here = path.abspath(path.dirname(__file__))

# Get the long description from the relevant file
with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
long_description = f.read()

with open(path.join(here, 'emojificate', '__init__.py'), encoding='utf8') as version_file:
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file.read(), re.M)
if version_match:
version = version_match.group(1)
else:
raise RuntimeError("Unable to find version string.")

setup(
name='emojificate',
version=version,
description='A Python implementation of a concept of using fallback images, alt text, title text and aria labels to represent emoji in HTML code in a more accessible method.',
long_description=long_description,
url='https://github.com/glasnt/emojificate',
author='Katie McLaughlin',
author_email='[email protected]',
license='New BSD',
classifiers=[
'Development Status :: 3 - Alpha',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Topic :: Text Processing :: Filters',
'Topic :: Utilities',
],
keywords='emoji accessibility a11y',
packages=find_packages(exclude=['docs', 'test']),
)

0 comments on commit d161d96

Please sign in to comment.