changeset 211:3a626c48e9ae

Fix #81: could not get paragraphs in Markdown due to the interaction between smiley and Markdown. Refactored the smilify code to use a series of regular expressions over the text when working with markdown.
author Brian Neal <bgneal@gmail.com>
date Sat, 08 May 2010 23:44:59 +0000
parents 77b606e0ad5f
children fad7548b7f6e
files gpp/core/markup.py gpp/smiley/__init__.py gpp/smiley/models.py gpp/smiley/templatetags/smiley_tags.py
diffstat 4 files changed, 51 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/gpp/core/markup.py	Fri May 07 02:56:49 2010 +0000
+++ b/gpp/core/markup.py	Sat May 08 23:44:59 2010 +0000
@@ -4,7 +4,7 @@
 import markdown as _markdown
 from django.utils.encoding import force_unicode
 
-from smiley import Smilify
+from smiley import SmilifyMarkdown
 
 class Markdown(object):
     """
@@ -42,10 +42,10 @@
     """
     def __init__(self):
         self.md = Markdown()
-        self.smiley = Smilify()
+        self.smiley = SmilifyMarkdown()
 
     def convert(self, s):
-        return self.md.convert(self.smiley.markdown(s))
+        return self.md.convert(self.smiley.convert(s))
 
 
 def site_markup(s):
--- a/gpp/smiley/__init__.py	Fri May 07 02:56:49 2010 +0000
+++ b/gpp/smiley/__init__.py	Sat May 08 23:44:59 2010 +0000
@@ -1,5 +1,5 @@
 """
-Smiley class and function.
+Smiley classes and functions.
 """
 import re
 
@@ -9,22 +9,18 @@
 from smiley.models import Smiley
 
 
-class Smilify(object):
+class SmilifyHtml(object):
     """
-    A class to "smilify" text by replacing text with either HTML img tags 
-    or markdown syntax for smiley images.
+    A class to "smilify" text by replacing text with HTML img tags for smiley
+    images.
     """
-    HTML = 0
-    MARKDOWN = 1
-
     def __init__(self):
         self.map = Smiley.objects.get_smiley_map()
 
-    def _convert(self, value, rep_index, autoescape=False):
+    def convert(self, value, autoescape=False):
         """
-        Converts and returns the supplied text with either the
-        HTML or markdown version of the smileys according to the
-        output parameter.
+        Converts and returns the supplied text with the HTML version of the
+        smileys.
         """
         if not autoescape or isinstance(value, SafeData):
             esc = lambda x: x
@@ -34,39 +30,35 @@
         words = value.split()
         for i, word in enumerate(words):
             if word in self.map:
-                words[i] = self.map[word][rep_index]
+                words[i] = self.map[word]
             else:
                 words[i] = esc(words[i])
         return u' '.join(words)
 
-    def html(self, value, autoescape=False):
+
+class SmilifyMarkdown(object):
+    """
+    A class to "smilify" text by replacing text with Markdown image syntax for
+    smiley images.
+    """
+    def __init__(self):
+        self.regexes = Smiley.objects.get_smiley_regexes()
+
+    def convert(self, s):
         """
-        Converts the supplied text by replacing the smiley codes with
-        HTML img tags.
+        Returns a string copy of the input s that has the smiley codes replaced
+        with Markdown for smiley images.
         """
-        return self._convert(value, self.HTML, autoescape=autoescape)
+        for regex, repl in self.regexes:
+            s = regex.sub(repl, s)
+        return s
 
-    def markdown(self, value, autoescape=False):
-        """
-        Converts the supplied text by replacing the smiley codes with
-        markdown image syntax.
-        """
-        return self._convert(value, self.MARKDOWN, autoescape=autoescape)
-        
 
 def smilify_html(value, autoescape=False):
     """
     A convenience function to "smilify" text by replacing text with HTML
     img tags of smilies.
     """
-    s = Smilify()
-    return s.html(value, autoescape=autoescape)
+    s = SmilifyHtml()
+    return s.convert(value, autoescape=autoescape)
 
-
-def smilify_markdown(value, autoescape=False):
-    """
-    A convenience function to "smilify" text by replacing text with 
-    markdown syntax for the images of smilies.
-    """
-    s = Smilify()
-    return s.markdown(value, autoescape=autoescape)
--- a/gpp/smiley/models.py	Fri May 07 02:56:49 2010 +0000
+++ b/gpp/smiley/models.py	Sat May 08 23:44:59 2010 +0000
@@ -1,6 +1,8 @@
 """
 Models for the smiley application.
 """
+import re
+
 from django.db import models
 from django.core.cache import cache
 
@@ -11,20 +13,22 @@
 
     def get_smiley_map(self):
         """
-        Returns a dictionary of 2-tuples, indexed by smiley codes.
-        Element 0 of the tuple is the HTML representation of the smiley,
-        and element 1 is the markdown version.
+        Returns a dictionary, the keys are smiley codes.
+        The values are the HTML representations of the keys.
         The dictionary is cached.
         """
         map = cache.get('smiley_map')
         if map:
             return map
 
-        map = dict((s.code, (s.html(), s.markdown())) for s in self.all())
+        map = dict((s.code, s.html()) for s in self.all())
         cache.set('smiley_map', map, CACHE_TIMEOUT)
         return map
 
     def get_smilies(self, extra=False):
+        """
+        Returns smiley model instances filtered by the extra flag.
+        """
         key = 'smileys' if not extra else 'smileys_extra'
         smilies = cache.get(key)
         if smilies:
@@ -34,6 +38,21 @@
         cache.set(key, smilies, CACHE_TIMEOUT)
         return smilies
 
+    def get_smiley_regexes(self):
+        """
+        Returns a list of 2-tuples of the form: (regex, repl)
+        where regex is a regular expression for a smiley and
+        repl is the replacement image in Markdown format.
+        """
+        regexes = cache.get('smiley_regexes')
+        if regexes:
+            return regexes
+
+        regexes = [(re.compile(r"(^|\s|(?<=\s))%s(\s|$)" % re.escape(s.code)),
+            r"\1%s\2" % s.markdown()) for s in self.all()]
+        cache.set('smiley_regexes', regexes, CACHE_TIMEOUT)
+        return regexes
+
 
 class Smiley(models.Model):
     image = models.ImageField(upload_to='smiley/images/')
--- a/gpp/smiley/templatetags/smiley_tags.py	Fri May 07 02:56:49 2010 +0000
+++ b/gpp/smiley/templatetags/smiley_tags.py	Sat May 08 23:44:59 2010 +0000
@@ -19,18 +19,6 @@
 smiley_html.needs_autoescape = True
 
 
-@register.filter
-@stringfilter
-def smiley_markdown(value, autoescape=False):
-    """
-    A filter to "smilify" text by replacing text with Markdown image notation 
-    for smilies.
-    """
-    from smiley import smilify_markdown
-    return mark_safe(smilify_markdown(value, autoescape=autoescape))
-smiley_markdown.needs_autoescape = True
-
-
 @register.inclusion_tag('smiley/smiley_farm.html')
 def smiley_farm():
     """An inclusion tag that displays all of the smilies in clickable form."""