Skip to content
Permalink
Browse files

Initial

  • Loading branch information...
kernc committed Dec 31, 2014
0 parents commit 5225b1d31485fe58a7156578736b747d9fa278d2
Showing with 264 additions and 0 deletions.
  1. +61 −0 README.md
  2. +167 −0 mdx_unimoji.py
  3. +36 −0 setup.py
@@ -0,0 +1,61 @@
Unicode Emojis for Python-Markdown
==================================

Converts defined emoticon symbols to Unicode emojis, supported on a
variety of devices [1].

[1]: http://apps.timwhitlock.info/emoji/tables/unicode#block-1-emoticons

Usage:

>>> from __future__ import print_function
>>> from markdown import markdown
>>> text = 'I <3 you! Just kidding. :P'
>>> print(markdown(text, ['unimoji'])) # doctest: +NORMALIZE_WHITESPACE
<p>I <span class="emoji" style="color:red">❤</span> you! \
Just kidding. <span class="emoji">😛</span></p>
**NOTE**: The emojis are only replaced when whitespace-delimited on both sides!

The following options are accepted:

- `emoji`, the emoticon-to-list-of-aliases mapping,
- `span_class`, the class name of the encompassing `<span>` element
(default: 'emoji'). No element is created if `None`.

An example with these custom settings:

>>> from mdx_unimoji import UnimojiExtension
>>> img_heart = '<img alt="love" src="heart.png"/>'
>>> img_tongue = '<img alt=":P" src="tongue.png"/>'
>>> overrides = UnimojiExtension.EMOJI
>>> overrides.update({img_heart: ['<3'],
... img_tongue: ':p :P :-p :-P'.split()})
>>> print(markdown(text,
... extensions=[UnimojiExtension(span_class='other',
... emoji=overrides)]))
... # doctest: +NORMALIZE_WHITESPACE
<p>I <img alt="love" class="other" src="heart.png" /> you! \
Just kidding. <img alt=":P" class="other" src="tongue.png" /></p>
You can use the `span_class` value in your CSS, e.g.:

.emoji {
font-family: "Apple Color Emoji", "Segoe UI Emoji",
"Noto Color Emoji", EmojiSymbols, "DejaVu Sans", Symbola;
}

Install
-------

To install and make available to Markdown, you can issue:

pip install mdx_unimoji

or

pip install --upgrade git+git://github.com/kernc/mdx_unimoji.git

Then use the above provided examples to figure your way around.

HF!
@@ -0,0 +1,167 @@
# coding: utf-8
"""
Unicode Emojis for Python-Markdown
==================================
Converts defined emoticon symbols to Unicode emojis, supported on a
variety of devices [1].
[1]: http://apps.timwhitlock.info/emoji/tables/unicode#block-1-emoticons
Usage:
>>> from __future__ import print_function
>>> from markdown import markdown
>>> text = 'I <3 you! Just kidding. :P'
>>> print(markdown(text, ['unimoji'])) # doctest: +NORMALIZE_WHITESPACE
<p>I <span class="emoji" style="color:red">❤</span> you! \
Just kidding. <span class="emoji">😛</span></p>
**NOTE**: The emojis are only replaced when whitespace-delimited on both sides!
The following options are accepted:
- `emoji`, the emoticon-to-list-of-aliases mapping,
- `span_class`, the class name of the encompassing `<span>` element
(default: 'emoji'). No element is created if `None`.
An example with these custom settings:
>>> from mdx_unimoji import UnimojiExtension
>>> img_heart = '<img alt="love" src="heart.png"/>'
>>> img_tongue = '<img alt=":P" src="tongue.png"/>'
>>> overrides = UnimojiExtension.EMOJI
>>> overrides.update({img_heart: ['<3'],
... img_tongue: ':p :P :-p :-P'.split()})
>>> print(markdown(text,
... extensions=[UnimojiExtension(span_class='other',
... emoji=overrides)]))
... # doctest: +NORMALIZE_WHITESPACE
<p>I <img alt="love" class="other" src="heart.png" /> you! \
Just kidding. <img alt=":P" class="other" src="tongue.png" /></p>
You can use the `span_class` value in your CSS, e.g.:
.emoji {
font-family: "Apple Color Emoji", "Segoe UI Emoji",
"Noto Color Emoji", EmojiSymbols, "DejaVu Sans", Symbola;
}
HF!
"""
from __future__ import unicode_literals
from markdown import Extension
from markdown.util import etree
from markdown.inlinepatterns import Pattern

class UnimojiExtension(Extension):
EMOJI = {
'😊': ':) :-) :] :-] =) =] ^^ ^_^ ☺'.split(),
'😉': ';) ;-) ;] ;-]'.split(),
'😄': ':D :-D =D'.split(),
'😂': ":,D :'D =,D ='D".split(),
'😆': 'xD XD'.split(),
'😛': ':p :-p :P :-P =p =P'.split(),
'😜': ';p ;-p ;P ;-P'.split(),
'😏': ':> :->'.split(),
'😞': ':( :-( ;( ;-( =( =[ ☹'.split(),
'😣': 'x( X('.split(),
'😢': ":,( :'( =,( ='(".split(),
'😠': '>:( >=('.split(),
'😲': ':O :-O 8-O =O'.split(),
'😵': 'x-O X-O'.split(),
'😳': ':$ :-$ :">'.split(),
'😴': ':zzz:'.split(),
'😓': ':-X :X :-# :# :-& :&'.split(),
'😇': 'O:) O:-)'.split(),
'😈': '3:) 3:-) >:) >:-) >;) >;-)'.split(),
'😎': '8)'.split(),
'😖': ':s :-s :S :-S'.split(),
'😒': ':/ :-/ :\\ :-\\ =/ =\\ :L'.split(),
'😚': ':* :-*'.split(),
'😘': ';* ;-*'.split(),
'': '<3'.split(),
'💔': '</3'.split(),
'👍': ':y: :Y: :+1:'.split(),
'👎': ':n: :N: :-1:'.split(),
'🙌': '\\o/'.split(),
'🍰': ':cake:'.split(),
'😸': ':^) :} :-} :3 :-3'.split(),
'😺': ':^D =^D'.split(),
'😿': ':^( :{'.split(),
}
STYLES = {
'': 'color:red',
'💔': 'color:red',
'🍰': 'color:maroon',
}
config = {
'emoji': [
EMOJI,
'A mapping from emoticon symbols to a list of aliases.'
],
'styles': [
STYLES,
'A mapping from emoticon symbol to a CSS style string. '
'Only works if span_class is enabled.'
],
'span_class': [
'emoji',
'A CSS class (default: "emoji") for the emoticons-encompassing'
'<span>. Disabled if None.'
],
}

def __init__ (self, *args, **kwargs):
super(UnimojiExtension, self).__init__(*args, **kwargs)
# Set keys as aliases so they get processed the same
for k, v in self.getConfig('emoji').items(): v.append(k)
# Inverse the emoji mapping
aliases = {}
for emoticon, alias in self.getConfig('emoji').items():
for a in alias:
aliases[a] = emoticon
self.config['aliases'] = [aliases, '']

def extendMarkdown(self, md, md_globals):
import re
RE = r'((?<=\s)|(?<=^))(?P<emoticon>%s)(?=\s|$)' % '|'.join(map(re.escape, self.getConfig('aliases')))
md.inlinePatterns['emoji'] = UnimojiPattern(RE, md, self)


class UnimojiPattern(Pattern):
def __init__ (self, pattern, md, extension):
super(UnimojiPattern, self).__init__(pattern, md)
self.ext = extension

def handleMatch(self, m):
# Get the preferred Unicode emoticon, or override
emoticon = self.ext.getConfig('aliases')[m.group('emoticon')]
# Try to parse it as HTML in case it's overriden
try: element = etree.fromstring(emoticon.encode('utf-8'))
except etree.ParseError:
pass
# Apply class name if needed
span_class = self.ext.getConfig('span_class')
if span_class:
try: element
except NameError:
element = etree.Element('span')
element.text = emoticon
element.set('class', span_class)
# Apply style formatting
style = self.ext.getConfig('styles').get(emoticon)
if style: element.set('style', style)
try:
return element
except NameError:
return emoticon


def makeExtension(*args, **kwargs):
return UnimojiExtension(*args, **kwargs)


if __name__ == '__main__':
import doctest; doctest.testmod()
@@ -0,0 +1,36 @@
#!/usr/bin/env python

from setuptools import setup
import doctest

MODULE = 'mdx_unimoji'

tests = lambda: doctest.DocTestSuite(MODULE)

setup(
name=MODULE,
version='1.0',
author='Jack Nicholson',
author_email='kern.ce.ce++@gmail.com',
description='Python-Markdown extension that replaces common smileys with their Unicode emoji emoticons. ;)',
long_description_markdown_filename='README.md',
url='https://github.com/kernc/' + MODULE,
py_modules=[MODULE],
test_suite='setup.tests',
install_requires=['Markdown'],
setup_requires=['setuptools-markdown'],
license='GPLv3+',
keywords='markdown unicode emoji emoticon',
classifiers=[
'Development Status :: 5 - Production/Stable',
'Operating System :: OS Independent',
'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
'Environment :: Web Environment',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content :: Message Boards',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content :: News/Diary',
'Topic :: Text Processing :: Filters',
'Topic :: Text Processing :: Markup :: HTML'
]
)

0 comments on commit 5225b1d

Please sign in to comment.
You can’t perform that action at this time.